@signalsafe/tree-spec-editor-react
v0.3.3
Published
UI-kit agnostic React Flow canvas for the SignalSafe TreeSpec graph editor (no UI library).
Maintainers
Readme
@signalsafe/tree-spec-editor-react
Current source and planned customer-subdomain impact: current-state summary.
Headless React + React Flow layer for the SignalSafe TreeSpec graph editor: canvas component, orchestration hook, and wiring to @signalsafe/tree-spec-editor-core.
| | |
|---|---|
| npm | @signalsafe/tree-spec-editor-react |
| GitHub | SignalSafeSoftware/tree-spec-editor-react |
| Peer deps | react, react-dom, reactflow (^18 / ^11) — no UI library required |
UI-kit agnostic canvas
The React Flow canvas uses semantic HTML and graph-editor-* class hooks only. It does not require Bootstrap CSS, Bootstrap Icons, or any component library.
Host applications own styling. Map graph-editor-* in your theme, or pass className on TreeSpecGraphEditor for layout/sizing. See docs/UI_KIT_AGNOSTIC_CANVAS.md.
What this package does
- Renders
TreeSpecGraphEditor(React Flow canvas, custom nodes/edges, selection). - Exposes
useTreeSpecEditorfor load/validate/autosave/publish orchestration (host injects adapter callbacks). - Re-exports core editor types used by the hook.
What this package does not do
- Sidebar panels, modals, toolbars, or UI-kit chrome — use
@signalsafe/tree-spec-editoror your own UI shell. - Routing, HTTP, authentication, or persistence — host app provides adapter implementations.
- Wire compile/publish to a backend without your adapter code.
Install
npm install @signalsafe/tree-spec-editor-react @signalsafe/tree-spec-editor-core @signalsafe/tree-spec react react-dom reactflowReact Flow CSS (host-owned)
This package does not import reactflow/dist/style.css from built JavaScript. Native Node ESM imports of @signalsafe/tree-spec-editor-react therefore do not fail on .css file extensions.
Host applications that want React Flow default styling should import the stylesheet from their own app entrypoint:
import "reactflow/dist/style.css";If you use @signalsafe/tree-spec-editor as the authoring shell, map graph-editor-* canvas hooks in host CSS — Bootstrap is optional and host-owned.
Quick start
import { useState } from "react";
import TreeSpecGraphEditor from "@signalsafe/tree-spec-editor-react";
import {
END_NODE_ID,
type EditorTree,
} from "@signalsafe/tree-spec-editor-core";
const initialTree: EditorTree = {
start_node: "start",
nodes: {
start: {
id: "start",
type: "prompt",
prompt: "Example prompt",
choices: [{ id: "done", label: "Finish" }],
position: { x: 40, y: 120 },
},
},
transitions: [
{
id: "t1",
fromNodeId: "start",
fromChoiceId: "done",
toNodeId: END_NODE_ID,
outcome: "safe",
},
],
};
export function ExampleCanvas() {
const [tree, setTree] = useState(initialTree);
return (
<TreeSpecGraphEditor
tree={tree}
onChange={setTree}
className="graph-editor-canvas-root my-canvas-host"
/>
);
}For full authoring flows (load/save/validate), compose useTreeSpecEditor with your adapter — see tests and @signalsafe/tree-spec-editor for a reference shell.
Revision-aware saves
Adapters may implement optional saveVersion for optimistic-concurrency
handling. It receives the baseline and local compiled TreeSpec and returns
{ status: "saved" } or a typed { status: "conflict", remoteTreeSpec,
message? }. The hook exposes a conflict through saveConflict without
overwriting local edits. Hosts own revision tokens, three-way merging,
transport, persistence, and conflict UI; adapters that omit saveVersion
continue to use the compatible updateVersion callback.
Public exports
| Export | Purpose |
|---|---|
| default / TreeSpecGraphEditor | React Flow canvas |
| TreeSpecGraphEditorProps | Canvas props |
| useTreeSpecEditor | Stateful editor orchestration |
| TreeSpecEditorAdapter, UseTreeSpecEditorResult, … | Adapter and hook types |
| TreeSpecSaveResult, TreeSpecSaveConflict | Optional typed save/conflict result |
Import from @signalsafe/tree-spec-editor-react only (no subpath exports).
Documentation preview
The graph image below is generated from the live example data with the built
TreeSpecGraphEditor component. The browser-backed generator captures the
same React Flow canvas that this package exports, including the editor's
virtual END node.
Run yarn docs:images to regenerate the image locally. CI runs
yarn docs:check with Chromium to keep the committed asset in sync.
Package boundaries
| Layer | Package |
|---|---|
| Wire | @signalsafe/tree-spec |
| Editor model | @signalsafe/tree-spec-editor-core |
| React canvas (this package) | @signalsafe/tree-spec-editor-react |
| Authoring shell | @signalsafe/tree-spec-editor |
Canvas selection behavior
| Selection | Inspector context | Contextual zoom (default on) |
|---|---|---|
| Node | selected node | fits node in viewport |
| Edge | source node + focused choice | viewport unchanged |
| Choice | focusChoiceId set | fits parent node when selected |
Pass contextualZoom={false} to disable automatic viewport fitting.
Development
Requires Node.js >=22.12.0 (engines.node). CI runs checks, tests, and smoke on Node 22 and 24; publish uses Node 24. Node 20 is no longer supported (GitHub Actions Node 20 deprecation).
yarn build uses tsconfig.build.json and resolves @signalsafe/* from node_modules. Ecosystem sibling paths in tsconfig.json apply to local typecheck/tests only.
yarn install
yarn build
yarn test
yarn typecheckSecurity
See SECURITY.md. Host applications must authenticate users, authorize edits, and validate TreeSpec JSON server-side before publish.
Changelog and releases
Related packages
@signalsafe/tree-spec-editor-core— framework-agnostic editor helpers.@signalsafe/tree-spec-editor— UI-kit agnostic authoring shell (panels, modals, toolbar).
Explicit read-only and failed saves (local 0.3.3-r42.1 candidate)
useTreeSpecEditor accepts optional readOnly?: boolean and onSaveError?: (error: unknown) => void. Default editing behavior is unchanged. Pass explicit readOnly for retained definitions that cannot be edited even when is_published is false. Bind canvas/inspector editing controls to returned readOnly; display publication metadata from returned isPublished. Explicit readOnly blocks graph/history changes and save/publish/snapshot/restore/clone writes, including keyboard and autosave paths. Selection, preview, validation and read-only inspection remain available. Already dispatched network writes cannot be cancelled by changing this option.
Save failures retain the local graph and saved baseline, clear saving, set existing autosave status dirty, expose nullable saveError, and invoke the optional error observer with the original rejection. A null/undefined rejection becomes a generic Error in state. Save resolves after failure so void toolbar/keyboard callers do not produce an unhandled rejection; observer rejection is contained too. Retry explicitly with Save; success clears saveError and marks saved. The same failed payload is not silently autosaved again; a new edit may debounce normally. The host owns failure wording, command recovery and authorization.
Release and compatibility
Release 0.3.3 preserves the installed Step 5 editor capabilities and the verified audit fixes. The coordinated dependency floor is TreeSpec ^0.4.4, editor-core ^0.2.3, and editor-react ^0.3.3 where declared. React integrations retain React 18 / React Flow 11. See release preparation for verification and publication order. The coordinated release was approved on 2026-10-21; registry availability is recorded in release verification receipts.
See the current release documentation for release-specific compatibility and verification boundaries.
