Skip to content

Commit 758e3a8

Browse files
committed
Merge branch 'main' into feat/bus-connection
2 parents 77e2f6e + f61c97e commit 758e3a8

File tree

21 files changed

+731
-34
lines changed

21 files changed

+731
-34
lines changed

docs/configuration.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
title: Configuration
3+
id: configuration
4+
---
5+
6+
Both TanStack `DevTools` and `EventClient` can be configured.
7+
8+
> **important** all configuration is optional unless marked (required)
9+
10+
## Devtools Configuration
11+
12+
With the `Devtools` there are two configuration objects, regardless of Frameworks these are the same and are provided to the Devtools through props.
13+
14+
- `config` configuration for the devtool panel and interaction with it
15+
- `eventBusConfig` configuration for the event bus
16+
17+
The `config` object is mainly focused around user interaction with the devtools panel and accepts the following properties:
18+
19+
- `defaultOpen` - If the devtools are open by default
20+
21+
```ts
22+
{defaultOpen: boolean}
23+
```
24+
25+
- `hideUntilHover` - Hides the TanStack devtools trigger until hovered
26+
27+
```ts
28+
{hideUntilHover: boolean}
29+
```
30+
31+
- `position` - The position of the TanStack devtools trigger
32+
33+
```ts
34+
{position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'middle-left' | 'middle-right'}
35+
```
36+
37+
- `panelLocation` - The location of the devtools panel
38+
39+
```ts
40+
{panelLocation: 'top' | 'bottom'}
41+
42+
```
43+
44+
- `openHotkey` - The hotkey set to open the devtools
45+
46+
```ts
47+
type ModifierKey = 'Alt' | 'Control' | 'Meta' | 'Shift';
48+
type KeyboardKey = ModifierKey | (string & {});
49+
50+
{openHotkey: Array<KeyboardKey>}
51+
```
52+
53+
- `requireUrlFlag` - Requires a flag present in the url to enable devtools
54+
55+
```ts
56+
{requireUrlFlag: boolean}
57+
58+
```
59+
60+
- `urlFlag` - The required flag that must be present in the url to enable devtools.
61+
62+
```ts
63+
{urlFlag: string}
64+
```
65+
66+
The `eventBusConfig` is configuration for the back bone of the devtools, the ``, and accepts the following properties:
67+
68+
- `debug` - Enables debug mode for the EventBus
69+
70+
```ts
71+
{debug: boolean}
72+
```
73+
74+
- `connectToServerBus` - Optional flag to indicate if the devtools server event bus is available to connect to
75+
76+
```ts
77+
{connectToServerBus: boolean}
78+
```
79+
80+
- `port` - The port at which the client connects to the devtools server event bus
81+
82+
```ts
83+
{port: number}
84+
```
85+
86+
Put together here is an example in react:
87+
88+
```tsx
89+
import { StrictMode } from 'react'
90+
import { createRoot } from 'react-dom/client'
91+
import { FormDevtools } from '@tanstack/react-form'
92+
93+
import { TanstackDevtools } from '@tanstack/react-devtools'
94+
95+
import App from './App'
96+
97+
createRoot(document.getElementById('root')!).render(
98+
<StrictMode>
99+
<App />
100+
101+
<TanstackDevtools
102+
config={{ hideUntilHover: true, }}
103+
eventBusConfig={{ debug: true }}
104+
plugins={[
105+
{
106+
name: 'Tanstack Form',
107+
render: <FormDevtools />,
108+
},
109+
]}
110+
/>
111+
</StrictMode>,
112+
)
113+
114+
```
115+
116+
## EventClient Configuration
117+
118+
Configuration for the `EventClient` is as follows
119+
120+
- `pluginId` (required) - The plugin identifier used by the event bus to direct events to listeners
121+
122+
```ts
123+
{pluginId: string}
124+
```
125+
126+
- `debug` - Enables debug mode for the EventClient
127+
128+
```ts
129+
{debug: boolean}
130+
```
131+
132+
Put together the `EventClient` configuration looks like:
133+
134+
```tsx
135+
import { EventClient } from '@tanstack/devtools-event-client'
136+
137+
type EventMap = {
138+
'custom-devtools:custom-state': { state: string }
139+
}
140+
141+
class customEventClient extends EventClient<EventMap> {
142+
constructor() {
143+
super({
144+
debug: true,
145+
pluginId: 'custom-devtools',
146+
})
147+
}
148+
}
149+
```
150+
151+
More information about EventClient configuration can be found in our [custom-plugins example](https://tanstack.com/devtools/latest/docs/framework/react/examples/basic)
File renamed without changes.
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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/react/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+
history.push(count);
24+
count++;
25+
},
26+
decrement: () => {
27+
history.push(count);
28+
count--;
29+
},
30+
};
31+
}
32+
```
33+
34+
## Event Client Setup
35+
36+
Install the [TanStack Devtools Event Client](https://tanstack.com/devtools/) 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 FormEventClient()
66+
```
67+
68+
## Event Client Integration
69+
70+
Now we need to hook our `EventClient` into out 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+
history.push(count)
86+
87+
// The emit eventSuffix must match that of the EventMap defined in eventClient.ts
88+
DevtoolsEventClient.emit('counter-state', {
89+
count: count++,
90+
history: history,
91+
})
92+
},
93+
decrement: () => {
94+
history.push(count)
95+
96+
DevtoolsEventClient.emit('counter-state', {
97+
count: count--,
98+
history: history,
99+
})
100+
},
101+
}
102+
}
103+
```
104+
105+
> **Important** `EventClient` is framework agnostic so this process will be the same regardless of framework or even in vanilla JavaScript.
106+
107+
## Consuming The Event Client
108+
109+
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.
110+
111+
> 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).
112+
113+
DevtoolsPanel.ts
114+
```tsx
115+
import { DevtoolsEventClient } from './eventClient.ts'
116+
117+
export function DevtoolPanel() {
118+
const [state,setState] = useState();
119+
120+
useEffect(() => {
121+
// subscribe to the emitted event
122+
const cleanup = client.on("counter-state", e => setState(e.payload)
123+
return cleanup
124+
}, []);
125+
126+
return (
127+
<div>
128+
<div>{state.count}</div>
129+
<div>{JSON.stringify(state.history)}</div>
130+
<div/>
131+
)
132+
}
133+
```
134+
135+
## Application Integration
136+
137+
This step follows what's shown in [../basic-setup] for a more documented guide go check it out. As well as the complete [custom-plugin example](https://tanstack.com/devtools/latest/docs/framework/react/examples/custom-plugin) in our examples section.
138+
139+
Main.tsx
140+
```tsx
141+
import { DevtoolPanel } from './DevtoolPanel'
142+
143+
createRoot(document.getElementById('root')!).render(
144+
<StrictMode>
145+
<App />
146+
147+
<TanstackDevtools
148+
plugins={[
149+
{
150+
// Name it what you like, this is how it will appear in the Menu
151+
name: 'Custom devtools',
152+
render: <DevtoolPanel />,
153+
},
154+
]}
155+
/>
156+
</StrictMode>,
157+
)
158+
159+
```
160+
161+
## Debugging
162+
163+
Both the TansTack `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.
164+
165+
TanstackDevtool's debugging mode can be activated like so:
166+
```tsx
167+
<TanstackDevtools
168+
eventBusConfig={{ debug: true }}
169+
plugins={[
170+
{
171+
// call it what you like, this is how it will appear in the Menu
172+
name: 'Custom devtools',
173+
render: <DevtoolPanel />,
174+
},
175+
]}
176+
/>
177+
```
178+
179+
Where as the EventClient's debug mode can be activated by:
180+
```tsx
181+
class CustomEventClient extends EventClient<EventMap> {
182+
constructor() {
183+
super({
184+
pluginId: 'custom-devtools',
185+
debug: true,
186+
})
187+
}
188+
}
189+
```
190+
191+
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]`.
192+
193+
Heres an example of both:
194+
```
195+
🌴 [tanstack-devtools:client-bus] Initializing client event bus
196+
197+
🌴 [tanstack-devtools:custom-devtools-plugin] Registered event to bus custom-devtools:counter-state
198+
```
File renamed without changes.

examples/react/basic/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1" />
77
<meta name="theme-color" content="#000000" />
88
<script src="https://unpkg.com/react-scan/dist/auto.global.js"></script>
9-
<title>TanStack Devtools Example</title>
9+
<title>Basic Example - TanStack Devtools</title>
1010
</head>
1111
<body>
1212
<noscript>You need to enable JavaScript to run this app.</noscript>

examples/react/basic/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"devDependencies": {
2323
"@types/react": "^19.1.2",
2424
"@types/react-dom": "^19.1.2",
25-
"@vitejs/plugin-react": "^4.4.1",
25+
"@vitejs/plugin-react": "^4.5.2",
2626
"vite": "^7.0.6"
2727
},
2828
"browserslist": {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @ts-check
2+
3+
/** @type {import('eslint').Linter.Config} */
4+
const config = {
5+
extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'],
6+
rules: {
7+
'react/no-children-prop': 'off',
8+
},
9+
}
10+
11+
module.exports = config

0 commit comments

Comments
 (0)