@homeostate/tool-devtools
v0.3.0
Published
Floating devtools to inspect and edit the state a homeostate sync engine keeps in sync, as a React component or mounted from any framework
Maintainers
Readme
@homeostate/tool-devtools
Devtools for @homeostate/core,
as a React component or mounted from any framework.
A floating button opens a panel where you can inspect and edit a store's state, compare it
with the synced backend document, follow a log of every change, and connect or disconnect
the engine.
Install
npm install -D @homeostate/tool-devtoolsThe React component needs react and react-dom 18 or 19, which are optional peer
dependencies: other apps use mountDevtools, which brings its own. Styles
are bundled and isolated in a shadow root, so no CSS setup is needed.
Usage
import * as Y from "yjs";
import { createSyncEngine } from "@homeostate/core";
import { createYjsBackend } from "@homeostate/crdt-yjs";
import { createZustandAdapter } from "@homeostate/store-zustand";
import { HomeostateDevtools } from "@homeostate/tool-devtools";
const adapter = createZustandAdapter(useTodoStore);
const backend = createYjsBackend(new Y.Doc(), "shared");
const engine = createSyncEngine(backend, adapter);
engine.connect();
export function App() {
return (
<>
<TodoList />
<HomeostateDevtools
sources={[{ name: "Todos", adapter, backend, engine }]}
/>
</>
);
}Pass several sources to inspect several stores. With the Zustand homeostate middleware, use
createZustandAdapter(store) as the adapter and store.homeostate as the engine. Pass what
createPersistence returned as persistence to see and compact the stored document on the
Storage tab. The engine tells the devtools which keys it keeps local and which changes are
remote. Pass a network link from createNetworkLink in @homeostate/tool-devtools/network
to slow down or cut the connection on the Network tab: see the documentation.
| Prop | Default | Description |
| ---------------- | ---------------- | --------------------------------------------------------------------- |
| sources | | One per store: { name, adapter } and the optional fields below |
| buttonPosition | "bottom-right" | Viewport corner of the button: bottom-left, top-right, top-left |
| panelPosition | "right" | Edge the panel docks to: left, bottom, top |
| initialIsOpen | false | Whether the panel starts open, until it is opened or closed once |
| open | | Controls whether the panel is open, to open it from your own UI |
| onOpenChange | | Called with the new state when the panel is opened or closed |
| theme | "system" | light, dark, or system to follow prefers-color-scheme |
| logLimit | 200 | Log entries kept per source |
buttonPosition, panelPosition and theme are where the devtools start: a corner, side or
theme picked in the panel's settings, behind the gear button, is remembered and applies instead.
Warning: edits go through the store like any local change, so every peer in the room receives them. Restoring a log entry replaces the shared state for everyone.
Without React
Apps on Angular, Vue, Svelte or no framework mount the same devtools with mountDevtools.
It takes the component's props as options and returns update and unmount. The panel
brings its own React and loads in the background, so the app needs no React and its initial
bundle grows by less than a kilobyte.
import { mountDevtools } from "@homeostate/tool-devtools/mount";
const devtools = mountDevtools({
sources: [{ name: "Todos", adapter, backend, engine }],
});
devtools.update({ open: true }); // change some options
devtools.unmount(); // when the store goes awayProduction builds
The component renders in every build. To leave it out of production bundles, load it only in
development and render it inside a Suspense boundary:
import { lazy } from "react";
const HomeostateDevtools = import.meta.env.DEV
? lazy(() =>
import("@homeostate/tool-devtools").then((module) => ({
default: module.HomeostateDevtools,
})),
)
: () => null;With mountDevtools, call it only in development, such as under import.meta.env.DEV.
See the documentation for the panel's tabs and editing behavior.
License
MIT — see LICENSE.
