11import 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'
73import { createPortal } from 'react-dom'
84import type { JSX , ReactElement } from 'react'
95import type {
@@ -94,13 +90,19 @@ export interface TanStackDevtoolsReactInit {
9490
9591const convertRender = (
9692 Component : PluginRender ,
97- setComponent : React . Dispatch < React . SetStateAction < JSX . Element | null > > ,
93+ setComponents : React . Dispatch <
94+ React . SetStateAction < Record < string , JSX . Element > >
95+ > ,
9896 e : HTMLElement ,
9997 theme : 'dark' | 'light' ,
10098) => {
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+ } ) )
104106}
105107
106108export const TanStackDevtools = ( {
@@ -109,14 +111,21 @@ export const TanStackDevtools = ({
109111 eventBusConfig,
110112} : TanStackDevtoolsReactInit ) : ReactElement | null => {
111113 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+
120129 const [ devtools ] = useState (
121130 ( ) =>
122131 new TanStackDevtoolsCore ( {
@@ -128,30 +137,42 @@ export const TanStackDevtools = ({
128137 name :
129138 typeof plugin . name === 'string'
130139 ? 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+
138151 convertRender (
139152 plugin . name as PluginRender ,
140- setTitleComponent ,
153+ setTitleComponents ,
141154 e ,
142155 theme ,
143156 )
144157 } ,
145158 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 )
150170 } ,
151171 }
152172 } ) ,
153173 } ) ,
154174 )
175+
155176 useEffect ( ( ) => {
156177 if ( devToolRef . current ) {
157178 devtools . mount ( devToolRef . current )
@@ -160,14 +181,27 @@ export const TanStackDevtools = ({
160181 return ( ) => devtools . unmount ( )
161182 } , [ devtools ] )
162183
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+
163191 return (
164192 < >
165193 < 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+ )
168199 : null }
169- { titleContainer && TitleComponent
170- ? createPortal ( < > { TitleComponent } </ > , titleContainer )
200+
201+ { hasTitles
202+ ? Object . entries ( titleContainers ) . map ( ( [ key , titleContainer ] ) =>
203+ createPortal ( < > { TitleComponents [ key ] } </ > , titleContainer ) ,
204+ )
171205 : null }
172206 </ >
173207 )
0 commit comments