Skip to content

Commit 8ea8ef7

Browse files
fix: fix issue with solid start (#31)
Fixes #28 --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 0738b4a commit 8ea8ef7

7 files changed

Lines changed: 199 additions & 193 deletions

File tree

‎.changeset/hip-moons-enter.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/solid-devtools': patch
3+
---
4+
5+
Fixed issue where solid devtools didn't work with solid start

‎examples/solid/start/package.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
},
99
"dependencies": {
1010
"@solidjs/start": "^1.1.0",
11-
"@tanstack/solid-devtools": "^0.2.2",
12-
"solid-js": "^1.9.5",
11+
"@tanstack/solid-devtools": "^0.3.0",
12+
"solid-js": "^1.9.7",
1313
"vinxi": "^0.5.7"
1414
},
1515
"engines": {

‎knip.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"ignoreDependencies": ["@size-limit/preset-small-lib", "@faker-js/faker"],
44
"ignoreWorkspaces": ["examples/**"],
55
"workspaces": {
6-
"packages/react-devtools": {
7-
"ignore": []
6+
"packages/solid-devtools": {
7+
"ignore": ["**/core.tsx"]
88
}
99
}
1010
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import {
2+
createMemo,
3+
createSignal,
4+
onMount,
5+
sharedConfig,
6+
splitProps,
7+
untrack,
8+
} from 'solid-js'
9+
import { isServer } from 'solid-js/web'
10+
import type { Component, ComponentProps, JSX, Setter } from 'solid-js'
11+
12+
/**
13+
*
14+
* Read more: https://docs.solidjs.com/solid-start/reference/client/client-only
15+
*/
16+
// not using Suspense
17+
export default function clientOnly<T extends Component<any>>(
18+
fn: () => Promise<{
19+
default: T
20+
}>,
21+
options: { lazy?: boolean } = {},
22+
) {
23+
if (isServer)
24+
return (props: ComponentProps<T> & { fallback?: JSX.Element }) =>
25+
props.fallback
26+
27+
const [comp, setComp] = createSignal<T>()
28+
!options.lazy && load(fn, setComp)
29+
return (props: ComponentProps<T>) => {
30+
let Comp: T | undefined
31+
let m: boolean
32+
const [, rest] = splitProps(props, ['fallback'])
33+
options.lazy && load(fn, setComp)
34+
if ((Comp = comp()) && !sharedConfig.context) return Comp(rest)
35+
const [mounted, setMounted] = createSignal(!sharedConfig.context)
36+
onMount(() => setMounted(true))
37+
return createMemo(
38+
() => (
39+
(Comp = comp()),
40+
(m = mounted()),
41+
untrack(() => (Comp && m ? Comp(rest) : props.fallback))
42+
),
43+
)
44+
}
45+
}
46+
47+
function load<T>(
48+
fn: () => Promise<{
49+
default: T
50+
}>,
51+
setComp: Setter<T>,
52+
) {
53+
fn().then((m) => setComp(() => m.default))
54+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { TanStackDevtoolsCore } from '@tanstack/devtools'
2+
import { createEffect, createSignal, onCleanup, onMount } from 'solid-js'
3+
import { Portal } from 'solid-js/web'
4+
import type { JSX } from 'solid-js'
5+
import type {
6+
ClientEventBusConfig,
7+
TanStackDevtoolsConfig,
8+
TanStackDevtoolsPlugin,
9+
} from '@tanstack/devtools'
10+
11+
type SolidPluginRender = JSX.Element | (() => JSX.Element)
12+
const convertRender = (
13+
el: HTMLDivElement | HTMLHeadingElement,
14+
Component: SolidPluginRender,
15+
) => (
16+
<Portal mount={el}>
17+
{typeof Component === 'function' ? <Component /> : Component}
18+
</Portal>
19+
)
20+
21+
export type TanStackDevtoolsSolidPlugin = Omit<
22+
TanStackDevtoolsPlugin,
23+
'render' | 'name'
24+
> & {
25+
/**
26+
* The render function can be a SolidJS element or a function that returns a SolidJS element.
27+
* If it's a function, it will be called to render the plugin, otherwise it will be rendered directly.
28+
*
29+
* Example:
30+
* ```ts
31+
* {
32+
* render: () => <CustomPluginComponent />,
33+
* }
34+
* ```
35+
* or
36+
* ```ts
37+
* {
38+
* render: <CustomPluginComponent />,
39+
* }
40+
* ```
41+
*/
42+
render: SolidPluginRender
43+
/**
44+
* Name to be displayed in the devtools UI.
45+
* If a string, it will be used as the plugin name.
46+
* If a function, it will be called with the mount element.
47+
*
48+
* Example:
49+
* ```ts
50+
* {
51+
* name: "Your Plugin",
52+
* render: () => <CustomPluginComponent />,
53+
* }
54+
* ```
55+
* or
56+
* ```ts
57+
* {
58+
* name: <h1>Your Plugin title</h1>,
59+
* render: () => <CustomPluginComponent />,
60+
* }
61+
* ```
62+
*/
63+
name: string | SolidPluginRender
64+
}
65+
export interface TanstackDevtoolsInit {
66+
/**
67+
* Array of plugins to be used in the devtools.
68+
* Each plugin should have a `render` function that returns a React element or a function
69+
*
70+
* Example:
71+
* ```jsx
72+
* <TanstackDevtools
73+
* plugins={[
74+
* {
75+
* id: "your-plugin-id",
76+
* name: "Your Plugin",
77+
* render: <CustomPluginComponent />,
78+
* }
79+
* ]}
80+
* />
81+
* ```
82+
*/
83+
plugins?: Array<TanStackDevtoolsSolidPlugin>
84+
/**
85+
* Configuration for the devtools shell. These configuration options are used to set the
86+
* initial state of the devtools when it is started for the first time. Afterwards,
87+
* the settings are persisted in local storage and changed through the settings panel.
88+
*/
89+
config?: Partial<TanStackDevtoolsConfig>
90+
/**
91+
* Configuration for the TanStack Devtools client event bus.
92+
*/
93+
eventBusConfig?: ClientEventBusConfig
94+
}
95+
96+
export default function SolidDevtoolsCore({
97+
config,
98+
plugins,
99+
eventBusConfig,
100+
}: TanstackDevtoolsInit) {
101+
const [devtools] = createSignal(
102+
new TanStackDevtoolsCore({
103+
config,
104+
eventBusConfig,
105+
plugins: plugins?.map((plugin) => ({
106+
...plugin,
107+
name:
108+
typeof plugin.name === 'string'
109+
? plugin.name
110+
: // The check above confirms that `plugin.name` is of Render type
111+
(el) => convertRender(el, plugin.name as SolidPluginRender),
112+
render: (el: HTMLDivElement) => convertRender(el, plugin.render),
113+
})),
114+
}),
115+
)
116+
let devToolRef: HTMLDivElement | undefined
117+
createEffect(() => {
118+
devtools().setConfig({ config })
119+
})
120+
onMount(() => {
121+
if (devToolRef) {
122+
devtools().mount(devToolRef)
123+
124+
onCleanup(() => {
125+
devtools().unmount()
126+
})
127+
}
128+
})
129+
return <div style={{ height: '100%' }} ref={devToolRef} />
130+
}
Lines changed: 3 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,5 @@
1-
import { TanStackDevtoolsCore } from '@tanstack/devtools'
2-
import { createEffect, createSignal, onCleanup, onMount } from 'solid-js'
3-
import { Portal } from 'solid-js/web'
4-
import type { JSX } from 'solid-js'
5-
import type {
6-
ClientEventBusConfig,
7-
TanStackDevtoolsConfig,
8-
TanStackDevtoolsPlugin,
9-
} from '@tanstack/devtools'
1+
import clientOnly from './client-only'
102

11-
type SolidPluginRender = JSX.Element | (() => JSX.Element)
12-
const convertRender = (
13-
el: HTMLDivElement | HTMLHeadingElement,
14-
Component: SolidPluginRender,
15-
) => (
16-
<Portal mount={el}>
17-
{typeof Component === 'function' ? <Component /> : Component}
18-
</Portal>
3+
export const TanstackDevtools = clientOnly(() =>
4+
import('./core').then((m) => m),
195
)
20-
21-
export type TanStackDevtoolsSolidPlugin = Omit<
22-
TanStackDevtoolsPlugin,
23-
'render' | 'name'
24-
> & {
25-
/**
26-
* The render function can be a SolidJS element or a function that returns a SolidJS element.
27-
* If it's a function, it will be called to render the plugin, otherwise it will be rendered directly.
28-
*
29-
* Example:
30-
* ```ts
31-
* {
32-
* render: () => <CustomPluginComponent />,
33-
* }
34-
* ```
35-
* or
36-
* ```ts
37-
* {
38-
* render: <CustomPluginComponent />,
39-
* }
40-
* ```
41-
*/
42-
render: SolidPluginRender
43-
/**
44-
* Name to be displayed in the devtools UI.
45-
* If a string, it will be used as the plugin name.
46-
* If a function, it will be called with the mount element.
47-
*
48-
* Example:
49-
* ```ts
50-
* {
51-
* name: "Your Plugin",
52-
* render: () => <CustomPluginComponent />,
53-
* }
54-
* ```
55-
* or
56-
* ```ts
57-
* {
58-
* name: <h1>Your Plugin title</h1>,
59-
* render: () => <CustomPluginComponent />,
60-
* }
61-
* ```
62-
*/
63-
name: string | SolidPluginRender
64-
}
65-
interface TanstackDevtoolsInit {
66-
/**
67-
* Array of plugins to be used in the devtools.
68-
* Each plugin should have a `render` function that returns a React element or a function
69-
*
70-
* Example:
71-
* ```jsx
72-
* <TanstackDevtools
73-
* plugins={[
74-
* {
75-
* id: "your-plugin-id",
76-
* name: "Your Plugin",
77-
* render: <CustomPluginComponent />,
78-
* }
79-
* ]}
80-
* />
81-
* ```
82-
*/
83-
plugins?: Array<TanStackDevtoolsSolidPlugin>
84-
/**
85-
* Configuration for the devtools shell. These configuration options are used to set the
86-
* initial state of the devtools when it is started for the first time. Afterwards,
87-
* the settings are persisted in local storage and changed through the settings panel.
88-
*/
89-
config?: Partial<TanStackDevtoolsConfig>
90-
/**
91-
* Configuration for the TanStack Devtools client event bus.
92-
*/
93-
eventBusConfig?: ClientEventBusConfig
94-
}
95-
96-
export const TanstackDevtools = ({
97-
config,
98-
plugins,
99-
eventBusConfig,
100-
}: TanstackDevtoolsInit) => {
101-
const [devtools] = createSignal(
102-
new TanStackDevtoolsCore({
103-
config,
104-
eventBusConfig,
105-
plugins: plugins?.map((plugin) => ({
106-
...plugin,
107-
name:
108-
typeof plugin.name === 'string'
109-
? plugin.name
110-
: // The check above confirms that `plugin.name` is of Render type
111-
(el) => convertRender(el, plugin.name as SolidPluginRender),
112-
render: (el: HTMLDivElement) => convertRender(el, plugin.render),
113-
})),
114-
}),
115-
)
116-
let devToolRef: HTMLDivElement | undefined
117-
createEffect(() => {
118-
devtools().setConfig({ config })
119-
})
120-
onMount(() => {
121-
if (devToolRef) {
122-
devtools().mount(devToolRef)
123-
124-
onCleanup(() => {
125-
devtools().unmount()
126-
})
127-
}
128-
})
129-
return <div style={{ height: '100%' }} ref={devToolRef} />
130-
}

0 commit comments

Comments
 (0)