bolt-flow-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bolt Flow contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # bolt-flow-react
2
+
3
+ Composable React 19 bindings for one React Flow canvas containing workflow nodes and optional native annotations. Alpha 0.1.0; unpublished, with validation ongoing. Use local npm workspaces and build package exports as described in the [root README](../../README.md).
4
+
5
+ ## Setup and CSS
6
+
7
+ Exports `BoltProvider`, `BoltCanvas`, `BoltTools`, `useBolt`, `useBoltSnapshot`, `CanvasToolProps`, `CanvasExtension`, `BoltCanvasProps`, and selected XYFlow primitives/types. Wrap the canvas in `BoltProvider` with a stable `BoltRuntime` and an explicitly sized parent. Dispose the runtime when its owning editor is permanently destroyed.
8
+
9
+ Import `bolt-flow-react/style.css` explicitly. It currently includes `@xyflow/react/dist/style.css` via CSS `@import`; if that import is not resolved by your CSS pipeline, import `@xyflow/react/dist/style.css` explicitly too. Consumers of the built optional drawing package must also import `bolt-flow-plugin-draw/style.css`. Source-aliased playground behavior is not a substitute for consumer CSS setup.
10
+
11
+ Drawing CSS imports `@fontsource/gochi-hand/latin-400.css` from the drawing plugin's direct dependency for self-hosted handwriting. If your pipeline does not resolve package CSS `@import`s, import that font CSS separately and make the dependency resolvable from the host app (declare it directly if necessary). Custom font faces are loaded by host CSS. The React adapter itself does not depend on Fontsource or drawing.
12
+
13
+ ## Tools and rendering slots
14
+
15
+ Share the same host-controlled `CanvasToolProps` between `BoltTools` and `BoltCanvas`'s `interaction` prop. Supply `tool`, JSON `options`, and callbacks `onToolChange`, `onOptionsChange`, `onCreated(id, kind)`, and `onMessage` as needed. The host owns tool/option state; default interaction is `select` with empty options.
16
+
17
+ - `BoltTools` renders `canvas.tools` contributions.
18
+ - `BoltCanvas` mounts `canvas.overlay` contributions inside React Flow and combines `canvas.nodeTypes` / `canvas.edgeTypes` with host renderers. Host renderers take precedence for matching types.
19
+ - Tool/overlay contributions use `CanvasExtension`: `{ id, component }`, where the component receives `CanvasToolProps`.
20
+ - Non-`select`/`pan` tools disable graph dragging, connecting, selection, and delete keys at canvas level. Explicit `pan` disables node dragging, connecting, and selection, and defaults `panOnDrag` to true; other tools default it to false. `select` defaults `selectionOnDrag` to true. Hosts can override pan behavior through React Flow props. `autoPanOnNodeDrag` and `autoPanOnSelection` default to false.
21
+ - Unrecognized node types show a missing-renderer placeholder without deleting saved data. Removing drawing unregisters rendering/tools; re-enabling restores its native renderers.
22
+
23
+ There is no separate drawing surface or embedded editor API. The optional drawing plugin supplies pen, shapes, smart arrows, text, and local comments without being imported into this adapter's defaults.
24
+
25
+ Drawing interaction IDs are prefixed (`draw.pen`, `draw.triangle`); plugin `tools` options and `draw.create.shape` use raw IDs (`pen`, `triangle`). The plugin supports `shapes`, `fonts`, `colors`, and drawing defaults; configure trusted shape functions/components in `drawPlugin`, not in JSON `interaction.options`. See the [drawing contracts and consumer example](../plugin-draw/README.md#options-and-exported-geometry). It contributes merged preset/custom font metadata through `draw.fonts` for host inspectors; this is not an adapter rendering slot. The playground inspector consumes it without importing drawing at runtime.
26
+
27
+ The playground starts Draw in **Select** and lazily loads its [custom shape/font configuration](../../apps/playground/src/drawing.tsx) with the drawing plugin. Successful pointer creation requests Select by default (`keepTool: false`); text, comments, and connected smart edges request Select even with `keepTool: true`. Hosts must update tool state through `onToolChange` and can select the created object in `onCreated`. Eraser remains active until another tool is chosen.
28
+
29
+ `BoltCanvas` defaults `fitView` to true for initial fitting. The playground does not automatically refit on inspector or Flow/Draw changes; explicit fit/focus, layout, import, and template actions still adjust the viewport. Keep UI layout changes separate from viewport commands.
30
+
31
+ ## Defaults, styles, and persistence
32
+
33
+ `nodeDefaults` accepts `style`, `className`, `draggable`, `selectable`, and `connectable`; these defaults do not apply to `role: 'annotation'` nodes. `edgeDefaults` accepts edge fields except `id`, `source`, and `target`, and is also applied to new handle connections. Per-object fields override defaults; `style` merges by property. Other fields, including label styles, are replaced rather than deeply merged.
34
+
35
+ Nodes and edges persist serializable `style` / `className`. Edges additionally support label styling, routing, animation, and markers. `markerStart: false` / `markerEnd: false` suppress inherited markers; undefined inherits them. Marker objects have `type: 'arrow' | 'arrowclosed'` and optional `color`, `width`, `height`. Defaults are React props, not automatically persisted: the playground saves its own settings in `extensions.appearance`.
36
+
37
+ Custom `nodeTypes`, `edgeTypes`, and unmanaged React Flow props are supported. The adapter owns node/edge arrays and change/connect handlers. Controlled `selectedNodeIds` / `selectedEdgeIds` updates change selection separately from document synchronization, preserving current live drag positions rather than remapping saved positions on selection changes. Drag positions commit at drag end, while attached annotations follow live owner dragging; independently moved annotations update their offsets. Owner deletion detaches annotations through core synchronization. Optional history restores document snapshots, not transient selection or viewport state.
38
+
39
+ Only the portable `BoltNode` / `BoltEdge` contract is supported, not every XYFlow field or full groups/subflows. Custom renderers/host CSS determine visual styling. Unknown extensions, including legacy Excalidraw scenes, remain opaque and are not rendered or migrated. Requires core and React/React DOM peers, with XYFlow as a dependency; no Excalidraw dependency or parity claim. Images, rotation, multiplayer, and full drawing-editor features are outside the current contract.
40
+
41
+ See the [root validation commands and dated snapshot](../../README.md#validate-and-build). Browser regressions cover viewport stability during Draw selection/dragging and inspector changes; the built-consumer check verifies public CSS without source aliases. Release qualification remains separate.
42
+
43
+ MIT © 2026 Bolt Flow contributors. XYFlow retains its own license and attribution requirements.
@@ -0,0 +1,42 @@
1
+ import * as bolt_flow_core from 'bolt-flow-core';
2
+ import { Json, BoltNode, BoltEdge, BoltRuntime } from 'bolt-flow-core';
3
+ import * as react from 'react';
4
+ import { ReactNode, ComponentType } from 'react';
5
+ import { ReactFlowProps } from '@xyflow/react';
6
+ export { BaseEdge, Edge, EdgeTypes, Handle, Node, NodeProps, NodeResizer, NodeTypes, Position, ReactFlowInstance, getBezierPath, useReactFlow, useViewport } from '@xyflow/react';
7
+
8
+ declare function BoltProvider({ runtime, children }: {
9
+ runtime: BoltRuntime;
10
+ children: ReactNode;
11
+ }): react.JSX.Element;
12
+ declare function useBolt(): BoltRuntime;
13
+ declare function useBoltSnapshot(): bolt_flow_core.RuntimeSnapshot;
14
+ /** A generic tool contract. The React adapter does not import drawing or other feature packages. */
15
+ interface CanvasToolProps {
16
+ tool: string;
17
+ options: Record<string, Json>;
18
+ onToolChange?: (tool: string) => void;
19
+ onOptionsChange?: (options: Record<string, Json>) => void;
20
+ onCreated?: (id: string, kind: 'node' | 'edge') => void;
21
+ onMessage?: (message: string) => void;
22
+ }
23
+ interface CanvasExtension {
24
+ id: string;
25
+ component: ComponentType<CanvasToolProps>;
26
+ }
27
+ declare function BoltTools(props: CanvasToolProps): react.JSX.Element;
28
+ interface BoltCanvasProps extends Omit<ReactFlowProps, 'nodes' | 'edges' | 'onNodesChange' | 'onEdgesChange' | 'onConnect'> {
29
+ theme?: 'light' | 'dark';
30
+ showGrid?: boolean;
31
+ showControls?: boolean;
32
+ showMinimap?: boolean;
33
+ interaction?: CanvasToolProps;
34
+ selectedNodeIds?: string[];
35
+ selectedEdgeIds?: string[];
36
+ nodeDefaults?: Partial<Pick<BoltNode, 'style' | 'className' | 'draggable' | 'connectable' | 'selectable'>>;
37
+ edgeDefaults?: Partial<Omit<BoltEdge, 'id' | 'source' | 'target'>>;
38
+ }
39
+ /** One graph viewport for flow nodes, drawing nodes, comments, and extension tools. */
40
+ declare function BoltCanvas({ theme, showGrid, showControls, showMinimap, interaction, selectedNodeIds, selectedEdgeIds, nodeDefaults, edgeDefaults, children, nodeTypes, edgeTypes, ...props }: BoltCanvasProps): react.JSX.Element;
41
+
42
+ export { BoltCanvas, type BoltCanvasProps, BoltProvider, BoltTools, type CanvasExtension, type CanvasToolProps, useBolt, useBoltSnapshot };
package/dist/index.js ADDED
@@ -0,0 +1,183 @@
1
+ // src/index.tsx
2
+ import { createContext, useContext, useSyncExternalStore, useState, useEffect, useMemo, useCallback } from "react";
3
+ import { ReactFlow, ReactFlowProvider, Background, BackgroundVariant, Controls, MiniMap, applyNodeChanges, applyEdgeChanges } from "@xyflow/react";
4
+ import { Handle, Position, useReactFlow, useViewport, NodeResizer, BaseEdge, getBezierPath } from "@xyflow/react";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ var RuntimeContext = createContext(null);
7
+ function BoltProvider({ runtime, children }) {
8
+ return /* @__PURE__ */ jsx(RuntimeContext.Provider, { value: runtime, children: /* @__PURE__ */ jsx(ReactFlowProvider, { children }) });
9
+ }
10
+ function useBolt() {
11
+ const runtime = useContext(RuntimeContext);
12
+ if (!runtime) throw new Error("Wrap your canvas in <BoltProvider runtime={runtime}>.");
13
+ return runtime;
14
+ }
15
+ function useBoltSnapshot() {
16
+ const runtime = useBolt();
17
+ return useSyncExternalStore(runtime.subscribe, runtime.getSnapshot, runtime.getSnapshot);
18
+ }
19
+ function BoltTools(props) {
20
+ const runtime = useBolt();
21
+ useBoltSnapshot();
22
+ return /* @__PURE__ */ jsx(Fragment, { children: runtime.getContributions("canvas.tools").map(({ id, component: Tools }) => /* @__PURE__ */ jsx(Tools, { ...props }, id)) });
23
+ }
24
+ function MissingNode({ data }) {
25
+ return /* @__PURE__ */ jsxs("div", { className: "bolt-missing-node", children: [
26
+ String(data.label ?? "Saved annotation"),
27
+ /* @__PURE__ */ jsx("small", { children: "Enable its rendering plugin to edit" })
28
+ ] });
29
+ }
30
+ var fallbackTypes = { "bolt:missing": MissingNode };
31
+ var idleInteraction = { tool: "select", options: {} };
32
+ function BoltCanvas({
33
+ theme = "light",
34
+ showGrid = true,
35
+ showControls = true,
36
+ showMinimap = false,
37
+ interaction = idleInteraction,
38
+ selectedNodeIds,
39
+ selectedEdgeIds,
40
+ nodeDefaults,
41
+ edgeDefaults,
42
+ children,
43
+ nodeTypes,
44
+ edgeTypes,
45
+ ...props
46
+ }) {
47
+ const runtime = useBolt();
48
+ const snapshot = useBoltSnapshot();
49
+ const { document } = snapshot;
50
+ const types = useMemo(() => ({ ...fallbackTypes, ...Object.assign({}, ...runtime.getContributions("canvas.nodeTypes")), ...nodeTypes }), [runtime, snapshot.plugins, nodeTypes]);
51
+ const connectionTypes = useMemo(() => ({ ...Object.assign({}, ...runtime.getContributions("canvas.edgeTypes")), ...edgeTypes }), [runtime, snapshot.plugins, edgeTypes]);
52
+ const mapNode = useCallback((node, current) => {
53
+ const requested = node.type ?? "default";
54
+ return {
55
+ ...node.role === "annotation" ? {} : nodeDefaults,
56
+ ...node,
57
+ style: { ...node.role === "annotation" ? {} : nodeDefaults?.style, ...node.style },
58
+ type: ["default", "input", "output", "group"].includes(requested) || types[requested] ? requested : "bolt:missing",
59
+ measured: current?.measured,
60
+ selected: current?.selected
61
+ };
62
+ }, [nodeDefaults, types]);
63
+ const mapEdge = useCallback((edge, current) => ({
64
+ ...edgeDefaults,
65
+ ...edge,
66
+ style: { ...edgeDefaults?.style, ...edge.style },
67
+ markerStart: (edge.markerStart ?? edgeDefaults?.markerStart) || void 0,
68
+ markerEnd: (edge.markerEnd ?? edgeDefaults?.markerEnd) || void 0,
69
+ selected: current?.selected
70
+ }), [edgeDefaults]);
71
+ const [nodes, setNodes] = useState(() => document.nodes.map((node) => ({ ...mapNode(node), selected: selectedNodeIds?.includes(node.id) })));
72
+ const [edges, setEdges] = useState(() => document.edges.map((edge) => ({ ...mapEdge(edge), selected: selectedEdgeIds?.includes(edge.id) })));
73
+ useEffect(() => {
74
+ setNodes((current) => document.nodes.map((node) => mapNode(node, current.find((item) => item.id === node.id))));
75
+ }, [document.nodes, mapNode]);
76
+ useEffect(() => {
77
+ setEdges((current) => document.edges.map((edge) => mapEdge(edge, current.find((item) => item.id === edge.id))));
78
+ }, [document.edges, mapEdge]);
79
+ useEffect(() => {
80
+ if (selectedNodeIds === void 0) return;
81
+ const selected = new Set(selectedNodeIds);
82
+ setNodes((current) => current.some((node) => !!node.selected !== selected.has(node.id)) ? current.map((node) => !!node.selected === selected.has(node.id) ? node : { ...node, selected: selected.has(node.id) }) : current);
83
+ }, [selectedNodeIds, document.nodes]);
84
+ useEffect(() => {
85
+ if (selectedEdgeIds === void 0) return;
86
+ const selected = new Set(selectedEdgeIds);
87
+ setEdges((current) => current.some((edge) => !!edge.selected !== selected.has(edge.id)) ? current.map((edge) => !!edge.selected === selected.has(edge.id) ? edge : { ...edge, selected: selected.has(edge.id) }) : current);
88
+ }, [selectedEdgeIds, document.edges]);
89
+ const onNodesChange = useCallback((changes) => {
90
+ setNodes((current) => {
91
+ const next = applyNodeChanges(changes, current);
92
+ const moving = new Set(changes.filter((change) => change.type === "position").map((change) => change.id));
93
+ return next.map((node) => {
94
+ const anchor = runtime.getDocument().nodes.find((item) => item.id === node.id)?.anchor;
95
+ if (!anchor || !moving.has(anchor.nodeId)) return node;
96
+ const owner = next.find((item) => item.id === anchor.nodeId);
97
+ return owner ? { ...node, position: { x: owner.position.x + anchor.offset.x, y: owner.position.y + anchor.offset.y } } : node;
98
+ });
99
+ });
100
+ const removed = new Set(changes.filter((change) => change.type === "remove").map((change) => change.id));
101
+ if (removed.size) runtime.updateDocument((draft) => {
102
+ draft.nodes = draft.nodes.filter((node) => !removed.has(node.id));
103
+ draft.edges = draft.edges.filter((edge) => !removed.has(edge.source) && !removed.has(edge.target));
104
+ }, { source: "graph.delete" });
105
+ }, [runtime]);
106
+ const onEdgesChange = useCallback((changes) => {
107
+ setEdges((current) => applyEdgeChanges(changes, current));
108
+ const removed = new Set(changes.filter((change) => change.type === "remove").map((change) => change.id));
109
+ if (removed.size) runtime.updateDocument((draft) => {
110
+ draft.edges = draft.edges.filter((edge) => !removed.has(edge.id));
111
+ }, { source: "graph.delete" });
112
+ }, [runtime]);
113
+ const onConnect = useCallback((connection) => {
114
+ runtime.updateDocument((draft) => {
115
+ if (draft.edges.some((edge) => edge.source === connection.source && edge.target === connection.target && (edge.sourceHandle ?? null) === connection.sourceHandle && (edge.targetHandle ?? null) === connection.targetHandle)) return;
116
+ draft.edges.push({ type: "smoothstep", ...edgeDefaults, ...connection, id: crypto.randomUUID() });
117
+ }, { source: "graph.connect" });
118
+ }, [runtime, edgeDefaults]);
119
+ const activeTool = interaction.tool !== "select" && interaction.tool !== "pan";
120
+ const panning = interaction.tool === "pan";
121
+ return /* @__PURE__ */ jsx("div", { className: "bolt-canvas", "data-theme": theme, "data-tool": interaction.tool, children: /* @__PURE__ */ jsxs(
122
+ ReactFlow,
123
+ {
124
+ ...props,
125
+ nodeTypes: types,
126
+ edgeTypes: connectionTypes,
127
+ nodes,
128
+ edges,
129
+ onNodesChange,
130
+ onEdgesChange,
131
+ onConnect,
132
+ nodesDraggable: !activeTool && !panning && (props.nodesDraggable ?? true),
133
+ nodesConnectable: !activeTool && !panning && (props.nodesConnectable ?? true),
134
+ elementsSelectable: !activeTool && !panning && (props.elementsSelectable ?? true),
135
+ panOnDrag: props.panOnDrag ?? panning,
136
+ selectionOnDrag: !activeTool && !panning && (props.selectionOnDrag ?? true),
137
+ autoPanOnNodeDrag: props.autoPanOnNodeDrag ?? false,
138
+ autoPanOnSelection: props.autoPanOnSelection ?? false,
139
+ colorMode: theme,
140
+ fitView: props.fitView ?? true,
141
+ minZoom: props.minZoom ?? 0.15,
142
+ maxZoom: props.maxZoom ?? 3,
143
+ deleteKeyCode: activeTool ? null : props.deleteKeyCode === void 0 ? ["Backspace", "Delete"] : props.deleteKeyCode,
144
+ onNodeDragStop: (event, node, draggedNodes) => {
145
+ const moved = new Map(draggedNodes.map((item) => [item.id, item.position]));
146
+ runtime.updateDocument((draft) => {
147
+ draft.nodes.forEach((item) => {
148
+ const position = moved.get(item.id);
149
+ if (!position) return;
150
+ item.position = position;
151
+ if (item.anchor && !moved.has(item.anchor.nodeId)) {
152
+ const owner = draft.nodes.find((candidate) => candidate.id === item.anchor.nodeId);
153
+ if (owner) item.anchor.offset = { x: position.x - owner.position.x, y: position.y - owner.position.y };
154
+ }
155
+ });
156
+ }, { source: "graph.move" });
157
+ props.onNodeDragStop?.(event, node, draggedNodes);
158
+ },
159
+ children: [
160
+ showGrid && /* @__PURE__ */ jsx(Background, { variant: BackgroundVariant.Dots, gap: 22, size: 1, color: theme === "dark" ? "#3a435a" : "#ccd1df" }),
161
+ showControls && /* @__PURE__ */ jsx(Controls, {}),
162
+ showMinimap && /* @__PURE__ */ jsx(MiniMap, { pannable: true, zoomable: true, nodeColor: "#a99af4" }),
163
+ runtime.getContributions("canvas.overlay").map(({ id, component: Overlay }) => /* @__PURE__ */ jsx(Overlay, { ...interaction }, id)),
164
+ children
165
+ ]
166
+ }
167
+ ) });
168
+ }
169
+ export {
170
+ BaseEdge,
171
+ BoltCanvas,
172
+ BoltProvider,
173
+ BoltTools,
174
+ Handle,
175
+ NodeResizer,
176
+ Position,
177
+ getBezierPath,
178
+ useBolt,
179
+ useBoltSnapshot,
180
+ useReactFlow,
181
+ useViewport
182
+ };
183
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import { createContext, useContext, useSyncExternalStore, useState, useEffect, useMemo, useCallback, type ComponentType, type ReactNode } from 'react';\nimport { ReactFlow, ReactFlowProvider, Background, BackgroundVariant, Controls, MiniMap, applyNodeChanges, applyEdgeChanges, type Node, type Edge, type ReactFlowProps, type NodeChange, type EdgeChange, type Connection, type NodeTypes, type EdgeTypes, type NodeProps } from '@xyflow/react';\nimport { BoltRuntime, type BoltNode, type Json, type BoltEdge } from 'bolt-flow-core';\n\nconst RuntimeContext = createContext<BoltRuntime | null>(null);\nexport function BoltProvider({ runtime, children }: { runtime: BoltRuntime; children: ReactNode }) {\n return <RuntimeContext.Provider value={runtime}><ReactFlowProvider>{children}</ReactFlowProvider></RuntimeContext.Provider>;\n}\nexport function useBolt() {\n const runtime = useContext(RuntimeContext);\n if (!runtime) throw new Error('Wrap your canvas in <BoltProvider runtime={runtime}>.');\n return runtime;\n}\nexport function useBoltSnapshot() {\n const runtime = useBolt();\n return useSyncExternalStore(runtime.subscribe, runtime.getSnapshot, runtime.getSnapshot);\n}\n/** A generic tool contract. The React adapter does not import drawing or other feature packages. */\nexport interface CanvasToolProps {\n tool: string;\n options: Record<string, Json>;\n onToolChange?: (tool: string) => void;\n onOptionsChange?: (options: Record<string, Json>) => void;\n onCreated?: (id: string, kind: 'node' | 'edge') => void;\n onMessage?: (message: string) => void;\n}\nexport interface CanvasExtension { id: string; component: ComponentType<CanvasToolProps> }\nexport function BoltTools(props: CanvasToolProps) {\n const runtime = useBolt();\n useBoltSnapshot();\n return <>{runtime.getContributions<CanvasExtension>('canvas.tools').map(({ id, component: Tools }) => <Tools key={id} {...props} />)}</>;\n}\nexport interface BoltCanvasProps extends Omit<ReactFlowProps, 'nodes' | 'edges' | 'onNodesChange' | 'onEdgesChange' | 'onConnect'> {\n theme?: 'light' | 'dark';\n showGrid?: boolean;\n showControls?: boolean;\n showMinimap?: boolean;\n interaction?: CanvasToolProps;\n selectedNodeIds?: string[];\n selectedEdgeIds?: string[];\n nodeDefaults?: Partial<Pick<BoltNode, 'style' | 'className' | 'draggable' | 'connectable' | 'selectable'>>;\n edgeDefaults?: Partial<Omit<BoltEdge, 'id' | 'source' | 'target'>>;\n}\nfunction MissingNode({ data }: NodeProps) {\n return <div className=\"bolt-missing-node\">{String(data.label ?? 'Saved annotation')}<small>Enable its rendering plugin to edit</small></div>;\n}\nconst fallbackTypes: NodeTypes = { 'bolt:missing': MissingNode };\nconst idleInteraction: CanvasToolProps = { tool: 'select', options: {} };\n\n/** One graph viewport for flow nodes, drawing nodes, comments, and extension tools. */\nexport function BoltCanvas({ theme = 'light', showGrid = true, showControls = true, showMinimap = false, interaction = idleInteraction,\n selectedNodeIds, selectedEdgeIds, nodeDefaults, edgeDefaults, children, nodeTypes, edgeTypes, ...props }: BoltCanvasProps) {\n const runtime = useBolt();\n const snapshot = useBoltSnapshot();\n const { document } = snapshot;\n const types = useMemo(() => ({ ...fallbackTypes, ...Object.assign({}, ...runtime.getContributions<NodeTypes>('canvas.nodeTypes')), ...nodeTypes }), [runtime, snapshot.plugins, nodeTypes]);\n const connectionTypes = useMemo(() => ({ ...Object.assign({}, ...runtime.getContributions<EdgeTypes>('canvas.edgeTypes')), ...edgeTypes }), [runtime, snapshot.plugins, edgeTypes]);\n const mapNode = useCallback((node: BoltNode, current?: Node): Node => {\n const requested = node.type ?? 'default';\n return {\n ...(node.role === 'annotation' ? {} : nodeDefaults), ...node,\n style: { ...(node.role === 'annotation' ? {} : nodeDefaults?.style), ...node.style },\n type: ['default', 'input', 'output', 'group'].includes(requested) || types[requested] ? requested : 'bolt:missing',\n measured: current?.measured,\n selected: current?.selected,\n };\n }, [nodeDefaults, types]);\n const mapEdge = useCallback((edge: BoltEdge, current?: Edge): Edge => ({\n ...edgeDefaults, ...edge, style: { ...edgeDefaults?.style, ...edge.style },\n markerStart: (edge.markerStart ?? edgeDefaults?.markerStart) || undefined,\n markerEnd: (edge.markerEnd ?? edgeDefaults?.markerEnd) || undefined,\n selected: current?.selected,\n }), [edgeDefaults]);\n const [nodes, setNodes] = useState<Node[]>(() => document.nodes.map((node) => ({ ...mapNode(node), selected: selectedNodeIds?.includes(node.id) })));\n const [edges, setEdges] = useState<Edge[]>(() => document.edges.map((edge) => ({ ...mapEdge(edge), selected: selectedEdgeIds?.includes(edge.id) })));\n useEffect(() => {\n setNodes((current) => document.nodes.map((node) => mapNode(node, current.find((item) => item.id === node.id))));\n }, [document.nodes, mapNode]);\n useEffect(() => {\n setEdges((current) => document.edges.map((edge) => mapEdge(edge, current.find((item) => item.id === edge.id))));\n }, [document.edges, mapEdge]);\n\n // Selection is UI state: never restore saved positions during a live drag.\n useEffect(() => {\n if (selectedNodeIds === undefined) return;\n const selected = new Set(selectedNodeIds);\n setNodes((current) => current.some((node) => !!node.selected !== selected.has(node.id))\n ? current.map((node) => !!node.selected === selected.has(node.id) ? node : { ...node, selected: selected.has(node.id) }) : current);\n }, [selectedNodeIds, document.nodes]);\n useEffect(() => {\n if (selectedEdgeIds === undefined) return;\n const selected = new Set(selectedEdgeIds);\n setEdges((current) => current.some((edge) => !!edge.selected !== selected.has(edge.id))\n ? current.map((edge) => !!edge.selected === selected.has(edge.id) ? edge : { ...edge, selected: selected.has(edge.id) }) : current);\n }, [selectedEdgeIds, document.edges]);\n\n const onNodesChange = useCallback((changes: NodeChange[]) => {\n setNodes((current) => {\n const next = applyNodeChanges(changes, current);\n const moving = new Set(changes.filter((change) => change.type === 'position').map((change) => change.id));\n // Attached ink follows the live React Flow drag, not just the committed document.\n return next.map((node) => {\n const anchor = runtime.getDocument().nodes.find((item) => item.id === node.id)?.anchor;\n if (!anchor || !moving.has(anchor.nodeId)) return node;\n const owner = next.find((item) => item.id === anchor.nodeId);\n return owner ? { ...node, position: { x: owner.position.x + anchor.offset.x, y: owner.position.y + anchor.offset.y } } : node;\n });\n });\n const removed = new Set(changes.filter((change) => change.type === 'remove').map((change) => change.id));\n if (removed.size) runtime.updateDocument((draft) => {\n draft.nodes = draft.nodes.filter((node) => !removed.has(node.id));\n draft.edges = draft.edges.filter((edge) => !removed.has(edge.source) && !removed.has(edge.target));\n }, { source: 'graph.delete' });\n }, [runtime]);\n const onEdgesChange = useCallback((changes: EdgeChange[]) => {\n setEdges((current) => applyEdgeChanges(changes, current));\n const removed = new Set(changes.filter((change) => change.type === 'remove').map((change) => change.id));\n if (removed.size) runtime.updateDocument((draft) => { draft.edges = draft.edges.filter((edge) => !removed.has(edge.id)); }, { source: 'graph.delete' });\n }, [runtime]);\n const onConnect = useCallback((connection: Connection) => {\n runtime.updateDocument((draft) => {\n if (draft.edges.some((edge) => edge.source === connection.source && edge.target === connection.target && (edge.sourceHandle ?? null) === connection.sourceHandle && (edge.targetHandle ?? null) === connection.targetHandle)) return;\n draft.edges.push({ type: 'smoothstep', ...edgeDefaults, ...connection, id: crypto.randomUUID() });\n }, { source: 'graph.connect' });\n }, [runtime, edgeDefaults]);\n const activeTool = interaction.tool !== 'select' && interaction.tool !== 'pan';\n const panning = interaction.tool === 'pan';\n return <div className=\"bolt-canvas\" data-theme={theme} data-tool={interaction.tool}>\n <ReactFlow {...props} nodeTypes={types} edgeTypes={connectionTypes} nodes={nodes} edges={edges}\n onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect}\n nodesDraggable={!activeTool && !panning && (props.nodesDraggable ?? true)} nodesConnectable={!activeTool && !panning && (props.nodesConnectable ?? true)}\n elementsSelectable={!activeTool && !panning && (props.elementsSelectable ?? true)}\n panOnDrag={props.panOnDrag ?? panning} selectionOnDrag={!activeTool && !panning && (props.selectionOnDrag ?? true)}\n autoPanOnNodeDrag={props.autoPanOnNodeDrag ?? false} autoPanOnSelection={props.autoPanOnSelection ?? false}\n colorMode={theme} fitView={props.fitView ?? true} minZoom={props.minZoom ?? 0.15} maxZoom={props.maxZoom ?? 3}\n deleteKeyCode={activeTool ? null : props.deleteKeyCode === undefined ? ['Backspace', 'Delete'] : props.deleteKeyCode}\n onNodeDragStop={(event, node, draggedNodes) => {\n const moved = new Map(draggedNodes.map((item) => [item.id, item.position]));\n runtime.updateDocument((draft) => {\n draft.nodes.forEach((item) => {\n const position = moved.get(item.id);\n if (!position) return;\n item.position = position;\n if (item.anchor && !moved.has(item.anchor.nodeId)) {\n const owner = draft.nodes.find((candidate) => candidate.id === item.anchor!.nodeId);\n if (owner) item.anchor.offset = { x: position.x - owner.position.x, y: position.y - owner.position.y };\n }\n });\n }, { source: 'graph.move' });\n props.onNodeDragStop?.(event, node, draggedNodes);\n }}>\n {showGrid && <Background variant={BackgroundVariant.Dots} gap={22} size={1} color={theme === 'dark' ? '#3a435a' : '#ccd1df'} />}\n {showControls && <Controls />}\n {showMinimap && <MiniMap pannable zoomable nodeColor=\"#a99af4\" />}\n {runtime.getContributions<CanvasExtension>('canvas.overlay').map(({ id, component: Overlay }) => <Overlay key={id} {...interaction} />)}\n {children}\n </ReactFlow>\n </div>;\n}\nexport { Handle, Position, useReactFlow, useViewport, NodeResizer, BaseEdge, getBezierPath } from '@xyflow/react';\nexport type { Node, Edge, NodeProps, NodeTypes, EdgeTypes, ReactFlowInstance } from '@xyflow/react';"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "bolt-flow-react",
3
+ "version": "0.1.0",
4
+ "description": "Composable React Flow canvas and React bindings for Bolt Flow",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "sideEffects": ["**/*.css"],
8
+ "files": ["dist", "src/style.css"],
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" }, "./style.css": "./src/style.css" },
12
+ "scripts": { "build": "tsup src/index.tsx --format esm --dts --sourcemap --clean --external bolt-flow-core --external @xyflow/react --external react --external react-dom" },
13
+ "dependencies": { "@xyflow/react": "^12.11.6" },
14
+ "peerDependencies": { "bolt-flow-core": "^0.1.0", "react": "^19.0.0", "react-dom": "^19.0.0" },
15
+ "publishConfig": { "access": "public" }
16
+ }
package/src/style.css ADDED
@@ -0,0 +1,14 @@
1
+ @import '@xyflow/react/dist/style.css';
2
+
3
+ .bolt-canvas { position: relative; width: 100%; height: 100%; min-height: 320px; --xy-background-color: #fafbfc; --xy-selection-background-color: #635bff0d; --xy-selection-border: 1px solid #7367db; }
4
+ .bolt-canvas[data-theme='dark'] { --xy-background-color: #1b1e26; --xy-selection-background-color: #b6a4ff18; --xy-selection-border: 1px solid #b6a4ff; }
5
+ .bolt-canvas[data-tool='select'] .react-flow__pane { cursor: default; }
6
+ .bolt-canvas[data-tool='pan'] .react-flow__pane, .bolt-canvas[data-tool='pan'] .react-flow__node { cursor: grab; }
7
+ .bolt-canvas[data-tool='pan'] .react-flow__pane.dragging, .bolt-canvas[data-tool='pan'] .react-flow__node:active { cursor: grabbing; }
8
+ .bolt-canvas .react-flow__edge-path { stroke: #b3b2c9; stroke-width: 1.6; }
9
+ .bolt-canvas .react-flow__edge.selected .react-flow__edge-path { filter: drop-shadow(0 0 3px #a886d299); }
10
+ .bolt-canvas .react-flow__controls { box-shadow: 0 2px 5px #18223806, 0 8px 24px #1822380d; border: 1px solid var(--line, #e4e7ec); border-radius: 10px; overflow: hidden; }
11
+ .bolt-canvas .react-flow__controls-button { background: var(--paper, #fff); color: var(--ink, #272b35); border-color: var(--line, #e4e7ec); }
12
+ .bolt-canvas .react-flow__controls-button:hover { background: var(--soft, #f5f6f8); }
13
+ .bolt-canvas .react-flow__controls-button:focus-visible { outline: 2px solid #7367db; outline-offset: -3px; }
14
+ .bolt-canvas .react-flow__minimap { border: 1px solid #e7e7f0; border-radius: 12px; overflow: hidden; box-shadow: 0 3px 16px #22224406; }