Skip to content

Commit 40db560

Browse files
feat: refactor props passing to plugins for improved flexibility (#319)
* feat: refactor props passing to plugins for improved flexibility * ci: apply automated fixes * fix tests * ci: apply automated fixes * fix * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent a120650 commit 40db560

File tree

23 files changed

+164
-98
lines changed

23 files changed

+164
-98
lines changed

.changeset/thirty-spies-fetch.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@tanstack/preact-devtools': minor
3+
'@tanstack/devtools-utils': minor
4+
'@tanstack/react-devtools': minor
5+
'@tanstack/solid-devtools': minor
6+
'@tanstack/devtools': minor
7+
---
8+
9+
Change the way props are passed to the plugins

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,5 @@ vite.config.ts.timestamp-*
5858
.angular
5959
.nitro
6060
.sonda
61-
*settings.local.json
61+
*settings.local.json
62+
.claude/worktrees

packages/devtools-utils/package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@
7575
"dependencies": {
7676
"@tanstack/devtools-ui": "workspace:^"
7777
},
78+
"devDependencies": {
79+
"@tanstack/devtools": "workspace:^",
80+
"tsup": "^8.5.0",
81+
"tsup-preset-solid": "^2.2.0",
82+
"vite-plugin-solid": "^2.11.8"
83+
},
7884
"peerDependencies": {
7985
"@types/react": ">=17.0.0",
8086
"preact": ">=10.0.0",
@@ -114,10 +120,5 @@
114120
"test:types": "tsc",
115121
"test:build": "publint --strict",
116122
"build": "vite build && vite build --config vite.config.preact.ts && vite build --config vite.config.vue.ts && vite build --config vite.config.solid-class.ts && tsup"
117-
},
118-
"devDependencies": {
119-
"tsup": "^8.5.0",
120-
"tsup-preset-solid": "^2.2.0",
121-
"vite-plugin-solid": "^2.11.8"
122123
}
123124
}

packages/devtools-utils/src/preact/panel.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/** @jsxImportSource preact */
22

33
import { useEffect, useRef } from 'preact/hooks'
4+
import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools'
45

5-
export interface DevtoolsPanelProps {
6-
theme?: 'light' | 'dark'
7-
}
6+
export interface DevtoolsPanelProps extends TanStackDevtoolsPluginProps {}
87

98
/**
109
* Creates a Preact component that dynamically imports and mounts a devtools panel. SSR friendly.
@@ -24,9 +23,9 @@ export interface DevtoolsPanelProps {
2423
* ```
2524
*/
2625
export function createPreactPanel<
27-
TComponentProps extends DevtoolsPanelProps | undefined,
26+
TComponentProps extends DevtoolsPanelProps,
2827
TCoreDevtoolsClass extends {
29-
mount: (el: HTMLElement, theme: 'light' | 'dark') => void
28+
mount: (el: HTMLElement, props: TanStackDevtoolsPluginProps) => void
3029
unmount: () => void
3130
},
3231
>(CoreClass: new () => TCoreDevtoolsClass) {
@@ -38,7 +37,7 @@ export function createPreactPanel<
3837
devtools.current = new CoreClass()
3938

4039
if (devToolRef.current) {
41-
devtools.current.mount(devToolRef.current, props?.theme ?? 'dark')
40+
devtools.current.mount(devToolRef.current, props)
4241
}
4342

4443
return () => {
@@ -47,7 +46,7 @@ export function createPreactPanel<
4746
devtools.current = null
4847
}
4948
}
50-
}, [props?.theme])
49+
}, [props])
5150

5251
return <div style={{ height: '100%' }} ref={devToolRef} />
5352
}

packages/devtools-utils/src/preact/plugin.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import type { JSX } from 'preact'
44
import type { DevtoolsPanelProps } from './panel'
5+
import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools'
56

67
export function createPreactPlugin({
78
Component,
@@ -15,15 +16,15 @@ export function createPreactPlugin({
1516
function Plugin() {
1617
return {
1718
...config,
18-
render: (_el: HTMLElement, theme: 'light' | 'dark') => (
19-
<Component theme={theme} />
19+
render: (_el: HTMLElement, props: TanStackDevtoolsPluginProps) => (
20+
<Component {...props} />
2021
),
2122
}
2223
}
2324
function NoOpPlugin() {
2425
return {
2526
...config,
26-
render: (_el: HTMLElement, _theme: 'light' | 'dark') => <></>,
27+
render: (_el: HTMLElement, _props: TanStackDevtoolsPluginProps) => <></>,
2728
}
2829
}
2930
return [Plugin, NoOpPlugin] as const

packages/devtools-utils/src/react/panel.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { useEffect, useRef } from 'react'
2+
import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools'
23

3-
export interface DevtoolsPanelProps {
4-
theme?: 'light' | 'dark'
5-
}
4+
export interface DevtoolsPanelProps extends TanStackDevtoolsPluginProps {}
65

76
/**
87
* Creates a React component that dynamically imports and mounts a devtools panel. SSR friendly.
@@ -22,9 +21,9 @@ export interface DevtoolsPanelProps {
2221
* ```
2322
*/
2423
export function createReactPanel<
25-
TComponentProps extends DevtoolsPanelProps | undefined,
24+
TComponentProps extends TanStackDevtoolsPluginProps,
2625
TCoreDevtoolsClass extends {
27-
mount: (el: HTMLElement, theme: 'light' | 'dark') => void
26+
mount: (el: HTMLElement, props: TanStackDevtoolsPluginProps) => void
2827
unmount: () => void
2928
},
3029
>(CoreClass: new () => TCoreDevtoolsClass) {
@@ -36,7 +35,7 @@ export function createReactPanel<
3635
devtools.current = new CoreClass()
3736

3837
if (devToolRef.current) {
39-
devtools.current.mount(devToolRef.current, props?.theme ?? 'dark')
38+
devtools.current.mount(devToolRef.current, props)
4039
}
4140

4241
return () => {
@@ -45,7 +44,7 @@ export function createReactPanel<
4544
devtools.current = null
4645
}
4746
}
48-
}, [props?.theme])
47+
}, [props])
4948

5049
return <div style={{ height: '100%' }} ref={devToolRef} />
5150
}

packages/devtools-utils/src/react/plugin.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { JSX } from 'react'
22
import type { DevtoolsPanelProps } from './panel'
3+
import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools'
34

45
export function createReactPlugin({
56
Component,
@@ -13,15 +14,15 @@ export function createReactPlugin({
1314
function Plugin() {
1415
return {
1516
...config,
16-
render: (_el: HTMLElement, theme: 'light' | 'dark') => (
17-
<Component theme={theme} />
17+
render: (_el: HTMLElement, props: TanStackDevtoolsPluginProps) => (
18+
<Component {...props} />
1819
),
1920
}
2021
}
2122
function NoOpPlugin() {
2223
return {
2324
...config,
24-
render: (_el: HTMLElement, _theme: 'light' | 'dark') => <></>,
25+
render: (_el: HTMLElement, _props: TanStackDevtoolsPluginProps) => <></>,
2526
}
2627
}
2728
return [Plugin, NoOpPlugin] as const

packages/devtools-utils/src/solid/class-mount-impl.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import { lazy } from 'solid-js'
44
import { Portal, render } from 'solid-js/web'
55
import type { JSX } from 'solid-js'
6+
import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools'
67

78
export function __mountComponent(
89
el: HTMLElement,
9-
theme: 'light' | 'dark',
10-
importFn: () => Promise<{ default: () => JSX.Element }>,
10+
props: TanStackDevtoolsPluginProps,
11+
importFn: () => Promise<{
12+
default: (props: TanStackDevtoolsPluginProps) => JSX.Element
13+
}>,
1114
): () => void {
1215
const Component = lazy(importFn)
1316
const ThemeProvider = lazy(() =>
@@ -20,8 +23,8 @@ export function __mountComponent(
2023
() => (
2124
<Portal mount={el}>
2225
<div style={{ height: '100%' }}>
23-
<ThemeProvider theme={theme}>
24-
<Component />
26+
<ThemeProvider theme={props.theme}>
27+
<Component {...props} />
2528
</ThemeProvider>
2629
</div>
2730
</Portal>

packages/devtools-utils/src/solid/class.test.tsx

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,23 @@ describe('constructCoreClass', () => {
2828
const [DevtoolsCore] = constructCoreClass(importFn)
2929
const instance = new DevtoolsCore()
3030
const el = document.createElement('div')
31-
await instance.mount(el, 'dark')
32-
expect(mountComponentMock).toHaveBeenCalledWith(el, 'dark', importFn)
31+
const props = { theme: 'dark' as const, devtoolsOpen: true }
32+
await instance.mount(el, props)
33+
expect(mountComponentMock).toHaveBeenCalledWith(el, props, importFn)
3334
})
3435

3536
it('DevtoolsCore should throw if mount is called twice without unmounting', async () => {
3637
const [DevtoolsCore] = constructCoreClass(importFn)
3738
const instance = new DevtoolsCore()
38-
await instance.mount(document.createElement('div'), 'dark')
39+
await instance.mount(document.createElement('div'), {
40+
theme: 'dark',
41+
devtoolsOpen: true,
42+
})
3943
await expect(
40-
instance.mount(document.createElement('div'), 'dark'),
44+
instance.mount(document.createElement('div'), {
45+
theme: 'dark',
46+
devtoolsOpen: true,
47+
}),
4148
).rejects.toThrow('Devtools is already mounted')
4249
})
4350

@@ -50,25 +57,37 @@ describe('constructCoreClass', () => {
5057
it('DevtoolsCore should allow mount after unmount', async () => {
5158
const [DevtoolsCore] = constructCoreClass(importFn)
5259
const instance = new DevtoolsCore()
53-
await instance.mount(document.createElement('div'), 'dark')
60+
await instance.mount(document.createElement('div'), {
61+
theme: 'dark',
62+
devtoolsOpen: true,
63+
})
5464
instance.unmount()
5565
await expect(
56-
instance.mount(document.createElement('div'), 'dark'),
66+
instance.mount(document.createElement('div'), {
67+
theme: 'dark',
68+
devtoolsOpen: true,
69+
}),
5770
).resolves.not.toThrow()
5871
})
5972

6073
it('DevtoolsCore should call dispose on unmount', async () => {
6174
const [DevtoolsCore] = constructCoreClass(importFn)
6275
const instance = new DevtoolsCore()
63-
await instance.mount(document.createElement('div'), 'dark')
76+
await instance.mount(document.createElement('div'), {
77+
theme: 'dark',
78+
devtoolsOpen: true,
79+
})
6480
instance.unmount()
6581
expect(disposeMock).toHaveBeenCalled()
6682
})
6783

6884
it('DevtoolsCore should abort mount if unmount is called during mounting', async () => {
6985
const [DevtoolsCore] = constructCoreClass(importFn)
7086
const instance = new DevtoolsCore()
71-
const mountPromise = instance.mount(document.createElement('div'), 'dark')
87+
const mountPromise = instance.mount(document.createElement('div'), {
88+
theme: 'dark',
89+
devtoolsOpen: true,
90+
})
7291
// Unmount while mount is in progress — triggers abort path
7392
// Note: since the mock resolves immediately, this tests the #abortMount flag
7493
await mountPromise
@@ -80,16 +99,25 @@ describe('constructCoreClass', () => {
8099
it('NoOpDevtoolsCore should not call __mountComponent when mount is called', async () => {
81100
const [, NoOpDevtoolsCore] = constructCoreClass(importFn)
82101
const noOpInstance = new NoOpDevtoolsCore()
83-
await noOpInstance.mount(document.createElement('div'), 'dark')
102+
await noOpInstance.mount(document.createElement('div'), {
103+
theme: 'dark',
104+
devtoolsOpen: true,
105+
})
84106
expect(mountComponentMock).not.toHaveBeenCalled()
85107
})
86108

87109
it('NoOpDevtoolsCore should not throw if mount is called multiple times', async () => {
88110
const [, NoOpDevtoolsCore] = constructCoreClass(importFn)
89111
const noOpInstance = new NoOpDevtoolsCore()
90-
await noOpInstance.mount(document.createElement('div'), 'dark')
112+
await noOpInstance.mount(document.createElement('div'), {
113+
theme: 'dark',
114+
devtoolsOpen: true,
115+
})
91116
await expect(
92-
noOpInstance.mount(document.createElement('div'), 'dark'),
117+
noOpInstance.mount(document.createElement('div'), {
118+
theme: 'dark',
119+
devtoolsOpen: true,
120+
}),
93121
).resolves.not.toThrow()
94122
})
95123

@@ -102,7 +130,10 @@ describe('constructCoreClass', () => {
102130
it('NoOpDevtoolsCore should not throw if unmount is called after mount', async () => {
103131
const [, NoOpDevtoolsCore] = constructCoreClass(importFn)
104132
const noOpInstance = new NoOpDevtoolsCore()
105-
await noOpInstance.mount(document.createElement('div'), 'dark')
133+
await noOpInstance.mount(document.createElement('div'), {
134+
theme: 'dark',
135+
devtoolsOpen: true,
136+
})
106137
expect(() => noOpInstance.unmount()).not.toThrow()
107138
})
108139
})

packages/devtools-utils/src/solid/class.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools'
12
import type { JSX } from 'solid-js'
23

34
/**
@@ -10,7 +11,9 @@ import type { JSX } from 'solid-js'
1011
* @returns Tuple containing the DevtoolsCore class and a NoOpDevtoolsCore class
1112
*/
1213
export function constructCoreClass(
13-
importFn: () => Promise<{ default: () => JSX.Element }>,
14+
importFn: () => Promise<{
15+
default: (props: TanStackDevtoolsPluginProps) => JSX.Element
16+
}>,
1417
) {
1518
class DevtoolsCore {
1619
#isMounted = false
@@ -20,7 +23,10 @@ export function constructCoreClass(
2023

2124
constructor() {}
2225

23-
async mount<T extends HTMLElement>(el: T, theme: 'light' | 'dark') {
26+
async mount<T extends HTMLElement>(
27+
el: T,
28+
props: TanStackDevtoolsPluginProps,
29+
) {
2430
if (this.#isMounted || this.#isMounting) {
2531
throw new Error('Devtools is already mounted')
2632
}
@@ -35,7 +41,7 @@ export function constructCoreClass(
3541
return
3642
}
3743

38-
this.#dispose = __mountComponent(el, theme, importFn)
44+
this.#dispose = __mountComponent(el, props, importFn)
3945
this.#isMounted = true
4046
this.#isMounting = false
4147
} catch (err) {
@@ -62,7 +68,10 @@ export function constructCoreClass(
6268
constructor() {
6369
super()
6470
}
65-
async mount<T extends HTMLElement>(_el: T, _theme: 'light' | 'dark') {}
71+
async mount<T extends HTMLElement>(
72+
_el: T,
73+
_props: TanStackDevtoolsPluginProps,
74+
) {}
6675
unmount() {}
6776
}
6877

0 commit comments

Comments
 (0)