-
-
Notifications
You must be signed in to change notification settings - Fork 69
Expand file tree
/
Copy pathclass.tsx
More file actions
94 lines (76 loc) · 2.5 KB
/
class.tsx
File metadata and controls
94 lines (76 loc) · 2.5 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
/** @jsxImportSource solid-js - we use Solid.js as JSX here */
import type { JSX } from 'solid-js'
/**
* Constructs the core class for the Devtools.
* This utility is used to construct a lazy loaded Solid component for the Devtools.
* It returns a tuple containing the main DevtoolsCore class and a NoOpDevtoolsCore class.
* The NoOpDevtoolsCore class is a no-op implementation that can be used for production if you want to explicitly exclude
* the Devtools from your application.
* @param importPath The path to the Solid component to be lazily imported
* @returns Tuple containing the DevtoolsCore class and a NoOpDevtoolsCore class
*/
export function constructCoreClass(Component: () => JSX.Element) {
class DevtoolsCore {
#isMounted = false
#isMounting = false
#mountCb: (() => void) | null = null
#dispose?: () => void
#Component: any
#ThemeProvider: any
constructor() {}
async mount<T extends HTMLElement>(el: T, theme: 'light' | 'dark') {
this.#isMounting = true
const { lazy } = await import('solid-js')
const { render } = await import('solid-js/web')
if (this.#isMounted) {
throw new Error('Devtools is already mounted')
}
const mountTo = el
const dispose = render(() => {
this.#Component = Component
this.#ThemeProvider = lazy(() =>
import('@tanstack/devtools-ui').then((mod) => ({
default: mod.ThemeContextProvider,
})),
)
const Devtools = this.#Component
const ThemeProvider = this.#ThemeProvider
return (
<ThemeProvider theme={theme}>
<Devtools />
</ThemeProvider>
)
}, mountTo)
this.#isMounted = true
this.#isMounting = false
this.#dispose = dispose
if (this.#mountCb) {
this.#mountCb()
this.#mountCb = null
}
}
unmount() {
if (!this.#isMounted && !this.#isMounting) {
throw new Error('Devtools is not mounted')
}
if (this.#isMounting) {
this.#mountCb = () => {
this.#dispose?.()
this.#isMounted = false
}
return
}
this.#dispose?.()
this.#isMounted = false
}
}
class NoOpDevtoolsCore extends DevtoolsCore {
constructor() {
super()
}
async mount<T extends HTMLElement>(_el: T, _theme: 'light' | 'dark') {}
unmount() {}
}
return [DevtoolsCore, NoOpDevtoolsCore] as const
}
export type ClassType = ReturnType<typeof constructCoreClass>[0]