forked from TanStack/devtools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.tsx
More file actions
124 lines (115 loc) · 3.58 KB
/
core.tsx
File metadata and controls
124 lines (115 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { lazy } from 'solid-js'
import { Portal, render } from 'solid-js/web'
import { ClientEventBus } from '@tanstack/devtools-event-bus/client'
import { DevtoolsProvider } from './context/devtools-context'
import { initialState } from './context/devtools-store'
import { PiPProvider } from './context/pip-context'
import type { ClientEventBusConfig } from '@tanstack/devtools-event-bus/client'
import type {
TanStackDevtoolsConfig,
TanStackDevtoolsPlugin,
} from './context/devtools-context'
export interface TanStackDevtoolsInit {
/**
* Configuration for the devtools shell. These configuration options are used to set the
* initial state of the devtools when it is started for the first time. Afterwards,
* the settings are persisted in local storage and changed through the settings panel.
*/
config?: Partial<TanStackDevtoolsConfig>
/**
* Array of plugins to be used in the devtools.
* Each plugin has a `render` function that gives you the dom node to mount into
*
* Example:
* ```ts
* const devtools = new TanStackDevtoolsCore({
* plugins: [
* {
* id: "your-plugin-id",
* name: "Your Plugin",
* render: (el) => {
* // Your render logic here
* },
* },
* ],
* })
* ```
*/
plugins?: Array<TanStackDevtoolsPlugin>
eventBusConfig?: ClientEventBusConfig
}
export class TanStackDevtoolsCore {
#config: TanStackDevtoolsConfig = {
...initialState.settings,
}
#plugins: Array<TanStackDevtoolsPlugin> = []
#isMounted = false
#dispose?: () => void
#Component: any
#eventBus: ClientEventBus | undefined
#eventBusConfig: ClientEventBusConfig | undefined
#setPlugins?: (plugins: Array<TanStackDevtoolsPlugin>) => void
constructor(init: TanStackDevtoolsInit) {
this.#plugins = init.plugins || []
this.#eventBusConfig = init.eventBusConfig
this.#config = {
...this.#config,
...init.config,
}
}
mount<T extends HTMLElement>(el: T) {
// tsup-preset-solid statically replaces this variable during build, which eliminates this code from server bundle
// can be run outside of vite so we ignore the rule
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (import.meta.env?.SSR) return
if (this.#isMounted) {
throw new Error('Devtools is already mounted')
}
const mountTo = el
const dispose = render(() => {
this.#Component = lazy(() => import('./devtools'))
const Devtools = this.#Component
this.#eventBus = new ClientEventBus(this.#eventBusConfig)
this.#eventBus.start()
return (
<DevtoolsProvider
plugins={this.#plugins}
config={this.#config}
onSetPlugins={(setPlugins) => {
this.#setPlugins = setPlugins
}}
>
<PiPProvider>
<Portal mount={mountTo}>
<Devtools />
</Portal>
</PiPProvider>
</DevtoolsProvider>
)
}, mountTo)
this.#isMounted = true
this.#dispose = dispose
}
unmount() {
if (!this.#isMounted) {
throw new Error('Devtools is not mounted')
}
this.#eventBus?.stop()
this.#dispose?.()
this.#isMounted = false
}
setConfig(config: Partial<TanStackDevtoolsInit>) {
this.#config = {
...this.#config,
...config,
}
if (config.plugins) {
this.#plugins = config.plugins
// Update the reactive store if mounted
if (this.#isMounted && this.#setPlugins) {
this.#setPlugins(config.plugins)
}
}
}
}
export type { ClientEventBusConfig }