1
1
import React , { useEffect , useRef , useState } from 'react'
2
- import {
3
- PLUGIN_CONTAINER_ID ,
4
- PLUGIN_TITLE_CONTAINER_ID ,
5
- TanStackDevtoolsCore ,
6
- } from '@tanstack/devtools'
2
+ import { TanStackDevtoolsCore } from '@tanstack/devtools'
7
3
import { createPortal } from 'react-dom'
8
4
import type { JSX , ReactElement } from 'react'
9
5
import type {
@@ -94,13 +90,19 @@ export interface TanStackDevtoolsReactInit {
94
90
95
91
const convertRender = (
96
92
Component : PluginRender ,
97
- setComponent : React . Dispatch < React . SetStateAction < JSX . Element | null > > ,
93
+ setComponents : React . Dispatch <
94
+ React . SetStateAction < Record < string , JSX . Element > >
95
+ > ,
98
96
e : HTMLElement ,
99
97
theme : 'dark' | 'light' ,
100
98
) => {
101
- setComponent (
102
- typeof Component === 'function' ? Component ( e , theme ) : Component ,
103
- )
99
+ const element =
100
+ typeof Component === 'function' ? Component ( e , theme ) : Component
101
+
102
+ setComponents ( ( prev ) => ( {
103
+ ...prev ,
104
+ [ e . getAttribute ( 'id' ) as string ] : element ,
105
+ } ) )
104
106
}
105
107
106
108
export const TanStackDevtools = ( {
@@ -109,14 +111,21 @@ export const TanStackDevtools = ({
109
111
eventBusConfig,
110
112
} : TanStackDevtoolsReactInit ) : ReactElement | null => {
111
113
const devToolRef = useRef < HTMLDivElement > ( null )
112
- const [ pluginContainer , setPluginContainer ] = useState < HTMLElement | null > (
113
- null ,
114
- )
115
- const [ titleContainer , setTitleContainer ] = useState < HTMLElement | null > ( null )
116
- const [ PluginComponent , setPluginComponent ] = useState < JSX . Element | null > (
117
- null ,
118
- )
119
- const [ TitleComponent , setTitleComponent ] = useState < JSX . Element | null > ( null )
114
+
115
+ const [ pluginContainers , setPluginContainers ] = useState <
116
+ Record < string , HTMLElement >
117
+ > ( { } )
118
+ const [ titleContainers , setTitleContainers ] = useState <
119
+ Record < string , HTMLElement >
120
+ > ( { } )
121
+
122
+ const [ PluginComponents , setPluginComponents ] = useState <
123
+ Record < string , JSX . Element >
124
+ > ( { } )
125
+ const [ TitleComponents , setTitleComponents ] = useState <
126
+ Record < string , JSX . Element >
127
+ > ( { } )
128
+
120
129
const [ devtools ] = useState (
121
130
( ) =>
122
131
new TanStackDevtoolsCore ( {
@@ -128,30 +137,42 @@ export const TanStackDevtools = ({
128
137
name :
129
138
typeof plugin . name === 'string'
130
139
? plugin . name
131
- : // The check above confirms that `plugin.name` is of Render type
132
- ( e , theme ) => {
133
- setTitleContainer (
134
- e . ownerDocument . getElementById (
135
- PLUGIN_TITLE_CONTAINER_ID ,
136
- ) || null ,
137
- )
140
+ : ( e , theme ) => {
141
+ const id = e . getAttribute ( 'id' ) !
142
+ const target = e . ownerDocument . getElementById ( id )
143
+
144
+ if ( target ) {
145
+ setTitleContainers ( ( prev ) => ( {
146
+ ...prev ,
147
+ [ id ] : e ,
148
+ } ) )
149
+ }
150
+
138
151
convertRender (
139
152
plugin . name as PluginRender ,
140
- setTitleComponent ,
153
+ setTitleComponents ,
141
154
e ,
142
155
theme ,
143
156
)
144
157
} ,
145
158
render : ( e , theme ) => {
146
- setPluginContainer (
147
- e . ownerDocument . getElementById ( PLUGIN_CONTAINER_ID ) || null ,
148
- )
149
- convertRender ( plugin . render , setPluginComponent , e , theme )
159
+ const id = e . getAttribute ( 'id' ) !
160
+ const target = e . ownerDocument . getElementById ( id )
161
+
162
+ if ( target ) {
163
+ setPluginContainers ( ( prev ) => ( {
164
+ ...prev ,
165
+ [ id ] : e ,
166
+ } ) )
167
+ }
168
+
169
+ convertRender ( plugin . render , setPluginComponents , e , theme )
150
170
} ,
151
171
}
152
172
} ) ,
153
173
} ) ,
154
174
)
175
+
155
176
useEffect ( ( ) => {
156
177
if ( devToolRef . current ) {
157
178
devtools . mount ( devToolRef . current )
@@ -160,14 +181,27 @@ export const TanStackDevtools = ({
160
181
return ( ) => devtools . unmount ( )
161
182
} , [ devtools ] )
162
183
184
+ const hasPlugins =
185
+ Object . values ( pluginContainers ) . length > 0 &&
186
+ Object . values ( PluginComponents ) . length > 0
187
+ const hasTitles =
188
+ Object . values ( titleContainers ) . length > 0 &&
189
+ Object . values ( TitleComponents ) . length > 0
190
+
163
191
return (
164
192
< >
165
193
< div style = { { position : 'absolute' } } ref = { devToolRef } />
166
- { pluginContainer && PluginComponent
167
- ? createPortal ( < > { PluginComponent } </ > , pluginContainer )
194
+
195
+ { hasPlugins
196
+ ? Object . entries ( pluginContainers ) . map ( ( [ key , pluginContainer ] ) =>
197
+ createPortal ( < > { PluginComponents [ key ] } </ > , pluginContainer ) ,
198
+ )
168
199
: null }
169
- { titleContainer && TitleComponent
170
- ? createPortal ( < > { TitleComponent } </ > , titleContainer )
200
+
201
+ { hasTitles
202
+ ? Object . entries ( titleContainers ) . map ( ( [ key , titleContainer ] ) =>
203
+ createPortal ( < > { TitleComponents [ key ] } </ > , titleContainer ) ,
204
+ )
171
205
: null }
172
206
</ >
173
207
)
0 commit comments