Skip to content

Commit e0d58d5

Browse files
feat: add preact devtools (#283)
* feat: add preact devtools * changeset * ci: apply automated fixes * fix example jsx issue --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 66722f5 commit e0d58d5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2312
-131
lines changed

.changeset/every-crabs-rule.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@tanstack/preact-devtools': minor
3+
'@tanstack/devtools-utils': minor
4+
---
5+
6+
feat: add preact adapter for devtools. Add preact to devtool-utils

docs/config.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@
5656
}
5757
]
5858
},
59+
{
60+
"label": "preact",
61+
"children": [
62+
{
63+
"label": "Basic setup",
64+
"to": "framework/preact/basic-setup"
65+
},
66+
{
67+
"label": "Preact adapter",
68+
"to": "framework/preact/adapter"
69+
}
70+
]
71+
},
5972
{
6073
"label": "solid",
6174
"children": [
@@ -84,6 +97,15 @@
8497
}
8598
]
8699
},
100+
{
101+
"label": "preact",
102+
"children": [
103+
{
104+
"label": "Custom plugins",
105+
"to": "framework/preact/guides/custom-plugins"
106+
}
107+
]
108+
},
87109
{
88110
"label": "solid",
89111
"children": []
@@ -108,6 +130,15 @@
108130
}
109131
]
110132
},
133+
{
134+
"label": "preact",
135+
"children": [
136+
{
137+
"label": "Preact Hooks",
138+
"to": "framework/preact/reference/index"
139+
}
140+
]
141+
},
111142
{
112143
"label": "solid",
113144
"children": [
@@ -140,6 +171,19 @@
140171
}
141172
]
142173
},
174+
{
175+
"label": "preact",
176+
"children": [
177+
{
178+
"label": "Basic",
179+
"to": "framework/preact/examples/basic"
180+
},
181+
{
182+
"label": "Custom devtools",
183+
"to": "framework/preact/examples/custom-devtools"
184+
}
185+
]
186+
},
143187
{
144188
"label": "solid",
145189
"children": [

docs/framework/preact/adapter.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: TanStack Devtools Preact Adapter
3+
id: adapter
4+
---
5+
6+
If you are using TanStack Devtools in a Preact application, we recommend using the Preact Adapter. The Preact Adapter provides a set of easy-to-use hooks on top of the core Devtools utilities. If you find yourself wanting to use the core Devtools classes/functions directly, the Preact Adapter will also re-export everything from the core package.
7+
8+
## Installation
9+
10+
```sh
11+
npm install @tanstack/preact-devtools
12+
```
13+
14+
## Preact Hooks
15+
16+
TODO
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
title: Basic setup
3+
id: basic-setup
4+
---
5+
6+
TanStack devtools provides you with an easy to use and modular client that allows you to compose multiple devtools into one easy to use panel.
7+
8+
## Setup
9+
10+
Install the [TanStack Devtools](https://www.npmjs.com/package/@tanstack/preact-devtools) library, this will install the devtools core as well as provide you framework specific adapters.
11+
12+
```bash
13+
npm i @tanstack/preact-devtools
14+
```
15+
16+
Next in the root of your application import the `TanStackDevtools` from the required framework adapter (in this case @tanstack/preact-devtools).
17+
18+
```tsx
19+
import { TanStackDevtools } from '@tanstack/preact-devtools'
20+
import { render } from 'preact'
21+
22+
import App from './App'
23+
24+
render(
25+
<>
26+
<App />
27+
28+
<TanStackDevtools />
29+
</>,
30+
document.getElementById('root')!,
31+
)
32+
```
33+
34+
Import the desired devtools and provide it to the `TanStackDevtools` component along with a label for the menu.
35+
36+
Currently TanStack offers:
37+
38+
- `QueryDevtools`
39+
- `RouterDevtools`
40+
- `PacerDevtools`
41+
- `FormDevtools` [coming soon](https://github.com/TanStack/form/pull/1692)
42+
43+
```tsx
44+
import { render } from 'preact'
45+
46+
import { TanStackDevtools } from '@tanstack/preact-devtools'
47+
48+
import App from './App'
49+
50+
render(
51+
<>
52+
<App />
53+
54+
<TanStackDevtools
55+
plugins={[
56+
{
57+
name: 'Your Plugin',
58+
render: <YourPluginComponent />,
59+
},
60+
]}
61+
/>
62+
</>,
63+
document.getElementById('root')!,
64+
)
65+
```
66+
67+
Finally add any additional configuration you desire to the `TanStackDevtools` component, more information can be found under the [TanStack Devtools Configuration](../../configuration.md) section.
68+
69+
A complete working example can be found in our [basic example](https://tanstack.com/devtools/latest/docs/framework/preact/examples/basic).
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
---
2+
title: Custom plugins
3+
id: custom-plugins
4+
---
5+
6+
TanStack devtools allows you to create your own custom plugins by emitting and listening to our event bus.
7+
8+
## Prerequisite
9+
10+
This guide will walk you through a simple example where our library is a counter with a count history. A working example can be found in our [custom-plugin example](https://tanstack.com/devtools/latest/docs/framework/preact/examples/custom-plugin).
11+
12+
This is our library code:
13+
14+
counter.ts
15+
```tsx
16+
export function createCounter() {
17+
let count = 0
18+
const history = []
19+
20+
return {
21+
getCount: () => count,
22+
increment: () => {
23+
count++
24+
history.push(count)
25+
},
26+
decrement: () => {
27+
count--
28+
history.push(count)
29+
},
30+
};
31+
}
32+
```
33+
34+
## Event Client Setup
35+
36+
Install the [TanStack Devtools Event Client](https://www.npmjs.com/package/@tanstack/devtools-event-client) utils.
37+
38+
```bash
39+
npm i @tanstack/devtools-event-client
40+
```
41+
42+
First you will need to setup the `EventClient`.
43+
44+
eventClient.ts
45+
```tsx
46+
import { EventClient } from '@tanstack/devtools-event-client'
47+
48+
49+
type EventMap = {
50+
// The key of the event map is a combination of {pluginId}:{eventSuffix}
51+
// The value is the expected type of the event payload
52+
'custom-devtools:counter-state': { count: number, history: number[] }
53+
}
54+
55+
class CustomEventClient extends EventClient<EventMap> {
56+
constructor() {
57+
super({
58+
// The pluginId must match that of the event map key
59+
pluginId: 'custom-devtools',
60+
})
61+
}
62+
}
63+
64+
// This is where the magic happens, it'll be used throughout your application.
65+
export const DevtoolsEventClient = new CustomEventClient()
66+
```
67+
68+
## Event Client Integration
69+
70+
Now we need to hook our `EventClient` into the application code. This can be done in many way's, a useEffect that emits the current state, or a subscription to an observer, all that matters is that when you want to emit the current state you do the following.
71+
72+
Our new library code will looks as follows:
73+
74+
counter.ts
75+
```tsx
76+
import { DevtoolsEventClient } from './eventClient.ts'
77+
78+
export function createCounter() {
79+
let count = 0
80+
const history: Array<number> = []
81+
82+
return {
83+
getCount: () => count,
84+
increment: () => {
85+
count++
86+
history.push(count)
87+
88+
// The emit eventSuffix must match that of the EventMap defined in eventClient.ts
89+
DevtoolsEventClient.emit('counter-state', {
90+
count,
91+
history,
92+
})
93+
},
94+
decrement: () => {
95+
count--
96+
history.push(count)
97+
98+
DevtoolsEventClient.emit('counter-state', {
99+
count,
100+
history,
101+
})
102+
},
103+
}
104+
}
105+
```
106+
107+
> [!IMPORTANT]
108+
> `EventClient` is framework agnostic so this process will be the same regardless of framework or even in vanilla JavaScript.
109+
110+
## Consuming The Event Client
111+
112+
Now we need to create our devtools panel, for a simple approach write the devtools in the framework that the adapter is, be aware that this will make the plugin framework specific.
113+
114+
> Because TanStack is framework agnostic we have taken a more complicated approach that will be explained in coming docs (if framework agnosticism is not a concern to you, you can ignore this).
115+
116+
DevtoolsPanel.tsx
117+
```tsx
118+
import { useEffect, useState } from 'preact/hooks'
119+
import { DevtoolsEventClient } from './eventClient.ts'
120+
121+
export function DevtoolPanel() {
122+
const [state, setState] = useState<{ count: number; history: number[] } | undefined>()
123+
124+
useEffect(() => {
125+
// subscribe to the emitted event
126+
const cleanup = DevtoolsEventClient.on("counter-state", e => setState(e.payload))
127+
return cleanup
128+
}, [])
129+
130+
return (
131+
<div>
132+
<div>{state?.count}</div>
133+
<div>{JSON.stringify(state?.history)}</div>
134+
</div>
135+
)
136+
}
137+
```
138+
139+
## Application Integration
140+
141+
This step follows what's shown in [basic-setup](../basic-setup.md) for a more documented guide go check it out. As well as the complete [custom-devtools example](https://tanstack.com/devtools/latest/docs/framework/preact/examples/custom-devtools) in our examples section.
142+
143+
Main.tsx
144+
```tsx
145+
import { render } from 'preact'
146+
import { DevtoolPanel } from './DevtoolPanel'
147+
148+
render(
149+
<>
150+
<App />
151+
152+
<TanStackDevtools
153+
plugins={[
154+
{
155+
// Name it what you like, this is how it will appear in the Menu
156+
name: 'Custom devtools',
157+
render: <DevtoolPanel />,
158+
},
159+
]}
160+
/>
161+
</>,
162+
document.getElementById('root')!,
163+
)
164+
165+
```
166+
167+
## Debugging
168+
169+
Both the `TanStackDevtools` component and the TanStack `EventClient` come with built in debug mode which will log to the console the emitted event as well as the EventClient status.
170+
171+
TanStackDevtool's debugging mode can be activated like so:
172+
```tsx
173+
<TanStackDevtools
174+
eventBusConfig={{ debug: true }}
175+
plugins={[
176+
{
177+
// call it what you like, this is how it will appear in the Menu
178+
name: 'Custom devtools',
179+
render: <DevtoolPanel />,
180+
},
181+
]}
182+
/>
183+
```
184+
185+
Where as the EventClient's debug mode can be activated by:
186+
```tsx
187+
class CustomEventClient extends EventClient<EventMap> {
188+
constructor() {
189+
super({
190+
pluginId: 'custom-devtools',
191+
debug: true,
192+
})
193+
}
194+
}
195+
```
196+
197+
Activating the debug mode will log to the console the current events that emitter has emitted or listened to. The EventClient will have appended `[tanstack-devtools:${pluginId}]` and the client will have appended `[tanstack-devtools:client-bus]`.
198+
199+
Heres an example of both:
200+
```
201+
🌴 [tanstack-devtools:client-bus] Initializing client event bus
202+
203+
🌴 [tanstack-devtools:custom-devtools-plugin] Registered event to bus custom-devtools:counter-state
204+
```

docs/framework/solid/reference/functions/tanstackdevtools.md

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)