@squeed/flow-sdk 0.1.16 → 2.0.1
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/README.md +241 -127
- package/THIRD_PARTY_NOTICES.txt +120 -0
- package/dist/index.cjs +2 -357
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +551 -0
- package/dist/index.d.ts +77 -10
- package/dist/index.js +8911 -31371
- package/dist/index.js.map +1 -1
- package/package.json +28 -16
package/README.md
CHANGED
|
@@ -1,151 +1,184 @@
|
|
|
1
1
|
# @squeed/flow-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Interactive React flow diagrams from JSON, using DOM nodes, SVG edges, and Dagre layout. Cytoscape is not included.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @squeed/flow-sdk
|
|
8
|
+
npm install @squeed/flow-sdk@^2 react@^18 react-dom@^18
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Peer dependencies: `react`, `react-dom`, `@chakra-ui/react`, `@
|
|
11
|
+
Requires React 18 and Chakra UI 3.36 or later. Peer dependencies: `react`, `react-dom`, `@chakra-ui/react`, `@emotion/react`, `@emotion/styled`, and `framer-motion` (11 or 12). npm installs the remaining peers automatically. React 19 is not currently supported.
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
import {
|
|
16
|
+
import { ChakraProvider, defaultSystem } from "@chakra-ui/react";
|
|
17
|
+
import { useState } from "react";
|
|
18
|
+
import {
|
|
19
|
+
FlowDiagram,
|
|
20
|
+
type FlowDirection,
|
|
21
|
+
type SqueedJson,
|
|
22
|
+
} from "@squeed/flow-sdk";
|
|
17
23
|
|
|
18
24
|
function App() {
|
|
25
|
+
const [doc, setDoc] = useState<SqueedJson>({
|
|
26
|
+
service: { $label: "Service", $collapsed: false, worker: {} },
|
|
27
|
+
database: { $label: "Database" },
|
|
28
|
+
});
|
|
29
|
+
const [direction, setDirection] = useState<FlowDirection>("LR");
|
|
30
|
+
|
|
19
31
|
return (
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
<ChakraProvider value={defaultSystem}>
|
|
33
|
+
<div style={{ height: 600 }}>
|
|
34
|
+
<FlowDiagram
|
|
35
|
+
json={doc}
|
|
36
|
+
title="My Diagram"
|
|
37
|
+
config={{ direction, editable: true, themeColor: "blue.500" }}
|
|
38
|
+
callbacks={{ onJsonChange: setDoc, onDirectionChange: setDirection }}
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
</ChakraProvider>
|
|
25
42
|
);
|
|
26
43
|
}
|
|
27
44
|
```
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
The container must have a height. Styles are injected automatically; no CSS import is required. Keep your existing Chakra provider if the application already has one.
|
|
30
47
|
|
|
31
|
-
|
|
48
|
+
`json` accepts a parsed object or array. Edits produce a new document via `onJsonChange(next, change)`; store `next` and pass it back. Granular callbacks still fire for notifications, but should not apply the same document edit again. With `nodes`/`edges` instead, the consumer owns graph updates and collapse filtering.
|
|
32
49
|
|
|
33
|
-
|
|
34
|
-
|------|------|-------------|
|
|
35
|
-
| `json` | `any` | JSON object or string to render as a flow diagram |
|
|
36
|
-
| `title` | `string` | Title shown on the root node (default: `"untitled"`) |
|
|
37
|
-
| `nodes` | `FlowDiagramNode[]` | Pre-computed nodes (alternative to `json`) |
|
|
38
|
-
| `edges` | `FlowDiagramEdge[]` | Pre-computed edges (alternative to `json`) |
|
|
39
|
-
| `config` | `FlowDiagramConfig` | Diagram configuration |
|
|
40
|
-
| `callbacks` | `FlowDiagramCallbacks` | Event callbacks |
|
|
41
|
-
| `showBottomBar` | `boolean` | Show the direction/mode bottom bar (default: `true`) |
|
|
42
|
-
| `className` | `string` | CSS class name |
|
|
43
|
-
| `style` | `CSSProperties` | Inline styles |
|
|
50
|
+
Editing a plain-string node label updates that string in place, preserving its JSON address and connections. Object-node labels continue to use `$label`.
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
## Migrating From v1
|
|
46
53
|
|
|
47
|
-
|
|
54
|
+
**v2 is a breaking release for consumers of the Cytoscape instance.** `onCyInit` has been removed. Use `onInit(engine)` to capture a `FlowEngine`; it is not a Cytoscape-compatible object.
|
|
48
55
|
|
|
49
|
-
|
|
56
|
+
| v1 | v2 |
|
|
57
|
+
| ------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
58
|
+
| `onCyInit(cy)` | `onInit(engine)` |
|
|
59
|
+
| `cy.zoom()` / `cy.zoom(level)` | `engine.zoom()` / `engine.zoom(level)` |
|
|
60
|
+
| `cy.pan()` / `cy.pan(position)` | `engine.pan()` / `engine.pan(position)` |
|
|
61
|
+
| `cy.zoom({ level, renderedPosition })` | `engine.zoomAt(level, renderedPosition)` |
|
|
62
|
+
| `cy.fit(undefined, 50)` / `cy.center()` | `engine.fit(50)` / `engine.center()` |
|
|
63
|
+
| `cy.on("pan zoom", ...)` | `callbacks.onViewportChange` or `engine.onViewportChange(listener)` |
|
|
64
|
+
| `cy.nodes()`, `cy.edges()`, `cy.style()`, plugins | Update the JSON, `nodes`/`edges`, or SDK config; no Cytoscape equivalent is exposed |
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|--------|------|---------|-------------|
|
|
53
|
-
| `direction` | `"LR" \| "RL" \| "TB" \| "BT"` | `"LR"` | Layout direction |
|
|
54
|
-
| `layout` | `"dagre" \| "elk" \| "tidytree" \| "concentric" \| "cose"` | `"dagre"` | Layout algorithm |
|
|
55
|
-
| `themeColor` | `string` | `"blue.500"` | Accent color (Chakra token) |
|
|
56
|
-
| `colorMode` | `"light" \| "dark"` | `"light"` | Color mode |
|
|
57
|
-
| `backgroundPattern` | `"dot" \| "grid" \| "steel" \| "none"` | `"dot"` | Background pattern |
|
|
58
|
-
| `backgroundColor` | `string` | — | Background color override |
|
|
59
|
-
| `edgeColor` | `string` | — | Edge/line color override |
|
|
60
|
-
| `minZoom` | `number` | `0.01` | Minimum zoom level |
|
|
61
|
-
| `maxZoom` | `number` | `1.5` | Maximum zoom level |
|
|
62
|
-
| `initialViewport` | `{ pan: { x, y }, zoom }` | — | Initial viewport |
|
|
63
|
-
| `edgeHandles` | `boolean` | `true` | Enable edge drawing handles |
|
|
64
|
-
| `readOnly` | `boolean` | `false` | Disable all interactions |
|
|
65
|
-
| `editable` | `boolean` | `false` | Enable inline node label editing |
|
|
66
|
-
| `autoCollapse` | `boolean \| AutoCollapseConfig` | — | Auto-collapse deep nodes for large data |
|
|
67
|
-
| `nodeOverlayActions` | `NodeOverlayAction[]` | — | Actions in node hover overlay |
|
|
68
|
-
| `renderNodeOverlay` | `(props: NodeOverlayProps) => ReactNode` | — | Custom node hover overlay |
|
|
69
|
-
| `renderSelectedNodeToolbar` | `(props: SelectedNodeToolbarProps) => ReactNode` | — | Custom multi-select toolbar |
|
|
70
|
-
|
|
71
|
-
## Auto-Collapse
|
|
72
|
-
|
|
73
|
-
For large JSON structures, enable auto-collapse to keep the diagram manageable. Nodes are collapsed at every Nth depth level when the data exceeds size thresholds.
|
|
66
|
+
`engine.getNodeBox(id)` returns `{ x, y, w, h }` in model units after layout, or `undefined` before placement. `clientToModel(clientX, clientY)` and `modelToClient({ x, y })` convert coordinates. `onViewportChange(listener)` returns an unsubscribe function.
|
|
74
67
|
|
|
75
|
-
|
|
76
|
-
// Use defaults (800+ lines AND 5+ depth triggers collapse every 3 levels)
|
|
77
|
-
<FlowDiagram json={largeJson} config={{ autoCollapse: true }} />
|
|
68
|
+
Direction, selection, drawing, editing, collapse, and custom render callbacks remain available. Internal Cytoscape DOM classes are gone. SVG routing and text metrics can differ from the old canvas renderer; exact pixel parity is not guaranteed. `initialViewport` is now respected instead of being overwritten by automatic fitting.
|
|
78
69
|
|
|
79
|
-
|
|
80
|
-
<FlowDiagram
|
|
81
|
-
json={largeJson}
|
|
82
|
-
config={{
|
|
83
|
-
autoCollapse: {
|
|
84
|
-
minLines: 200,
|
|
85
|
-
minDepth: 3,
|
|
86
|
-
collapseEveryNLevels: 2,
|
|
87
|
-
},
|
|
88
|
-
}}
|
|
89
|
-
/>
|
|
90
|
-
```
|
|
70
|
+
## Props
|
|
91
71
|
|
|
92
|
-
### `
|
|
72
|
+
### `FlowDiagramProps`
|
|
73
|
+
|
|
74
|
+
| Prop | Type | Description |
|
|
75
|
+
| --------------- | ---------------------- | ------------------------------------------------------------------ |
|
|
76
|
+
| `json` | `SqueedJson` | Parsed JSON object or array; takes precedence over `nodes`/`edges` |
|
|
77
|
+
| `title` | `string` | Title shown on the root node (default: `"untitled"`) |
|
|
78
|
+
| `nodes` | `FlowDiagramNode[]` | Pre-computed nodes (alternative to `json`) |
|
|
79
|
+
| `edges` | `FlowDiagramEdge[]` | Pre-computed edges (alternative to `json`) |
|
|
80
|
+
| `config` | `FlowDiagramConfig` | Diagram configuration |
|
|
81
|
+
| `callbacks` | `FlowDiagramCallbacks` | Event callbacks |
|
|
82
|
+
| `showBottomBar` | `boolean` | Show the direction/mode bottom bar (default: `true`) |
|
|
83
|
+
| `className` | `string` | CSS class name |
|
|
84
|
+
| `style` | `CSSProperties` | Inline styles |
|
|
85
|
+
|
|
86
|
+
You can provide either `json` (auto-generates nodes/edges) or `nodes` + `edges` (pre-computed).
|
|
87
|
+
|
|
88
|
+
## Config
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
|--------|------|---------|-------------|
|
|
96
|
-
| `minLines` | `number` | `800` | Min JSON lines to trigger |
|
|
97
|
-
| `minDepth` | `number` | `5` | Min depth to trigger |
|
|
98
|
-
| `collapseEveryNLevels` | `number` | `3` | Collapse every Nth depth level |
|
|
90
|
+
### `FlowDiagramConfig`
|
|
99
91
|
|
|
100
|
-
|
|
92
|
+
| Option | Type | Default | Description |
|
|
93
|
+
| ----------------------------------------------------------------------- | ------------------------------------------------ | ------------ | -------------------------------------------------------------------------------------- |
|
|
94
|
+
| `direction` | `"LR" \| "RL" \| "TB" \| "BT" \| "C"` | `"LR"` | Layout direction; `C` splits the JSON root's branches |
|
|
95
|
+
| `nodeAlignment` | `"leading" \| "center" \| "trailing"` | `"center"` | Align unequal node sizes within each layout rank |
|
|
96
|
+
| `edgeMode` | `"workflow" \| "properties"` | `"workflow"` | Attach edges to node boxes or named object-property rows; saved mappings are unchanged |
|
|
97
|
+
| `layout` | `LayoutAlgorithm` | `"dagre"` | Only Dagre is implemented; other legacy values do not select a different layout |
|
|
98
|
+
| `themeColor` | `string` | `"blue.500"` | Accent color (Chakra token) |
|
|
99
|
+
| `colorMode` | `"light" \| "dark"` | `"light"` | Color mode |
|
|
100
|
+
| `backgroundPattern` | `"dot" \| "grid" \| "steel" \| "none"` | `"dot"` | Background pattern |
|
|
101
|
+
| `backgroundColor` | `string` | — | Background color override |
|
|
102
|
+
| `edgeColor` | `string` | — | Edge/line color override |
|
|
103
|
+
| `minZoom` | `number` | `0.01` | Minimum zoom level |
|
|
104
|
+
| `maxZoom` | `number` | `1.5` | Maximum zoom level |
|
|
105
|
+
| `initialViewport` | `{ pan: { x, y }, zoom }` | — | Initial viewport; omitted means fit on first layout |
|
|
106
|
+
| `edgeHandles` | `boolean` | — | `false` disables edge drawing; `true` also starts in draw mode |
|
|
107
|
+
| `readOnly` | `boolean` | `false` | Disable graph gestures and edits; toolbar navigation remains available |
|
|
108
|
+
| `editable` | `boolean` | `false` | Enable inline node label editing |
|
|
109
|
+
| `parentNodeStyle` | `ParentNodeStyle` | — | Compound-node fill, border, padding, and label defaults |
|
|
110
|
+
| `selectionToolbar` | `SelectionToolbarConfig \| false` | — | Customize palette and hidden controls, or disable selection tools |
|
|
111
|
+
| `nodeOverlayActions` | `NodeOverlayAction[]` | — | Actions in node hover overlay |
|
|
112
|
+
| `renderNodeOverlay` | `(props: NodeOverlayProps) => ReactNode` | — | Custom node hover overlay |
|
|
113
|
+
| `renderSelectedNodeToolbar` | `(props: SelectedNodeToolbarProps) => ReactNode` | — | Custom multi-select toolbar |
|
|
114
|
+
| `renderSelectedEdgeToolbar` | `(props: SelectedEdgeToolbarProps) => ReactNode` | — | Custom edge selection toolbar |
|
|
115
|
+
| `renderBottomBar` | `(props: BottomBarRenderProps) => ReactNode` | — | Replace the bottom bar |
|
|
116
|
+
| `customViews` | `Record<string, ComponentType>` | — | Override node views |
|
|
117
|
+
| `disableKeyboardShortcuts` | `boolean` | `false` | Disable built-in keyboard shortcuts |
|
|
118
|
+
| `isZoomMode`, `isMultiSelectMode`, `isDragMode`, `isEdgeHandlesEnabled` | `boolean` | — | Externally controlled interaction modes |
|
|
119
|
+
|
|
120
|
+
Use `$collapsed: true` to collapse a JSON branch, and `false` to keep the expansion control. Automatic depth-based collapse is not part of the current API.
|
|
121
|
+
|
|
122
|
+
`nodeAlignment: "leading"` aligns left edges in `LR`/`C`, right edges in `RL`, top edges in `TB`, and bottom edges in `BT`. `"trailing"` aligns the opposite edge. Node dimensions and graph connections are unchanged; containers and edge paths follow the aligned positions.
|
|
101
123
|
|
|
102
124
|
## Callbacks
|
|
103
125
|
|
|
104
126
|
### Node Events
|
|
105
127
|
|
|
106
|
-
| Callback
|
|
107
|
-
|
|
108
|
-
| `onNodeSelect`
|
|
109
|
-
| `onNodeDeselect`
|
|
110
|
-
| `onNodeDoubleClick` | `(nodeId, nodeData) => void`
|
|
111
|
-
| `onNodeCreate`
|
|
112
|
-
| `onNodeDelete`
|
|
113
|
-
| `onNodeLabelChange` | `(nodeId, newLabel) => void`
|
|
114
|
-
| `onNodeCollapse`
|
|
115
|
-
| `onNodeColorChange` | `(nodeId, colorType, color) => void`
|
|
116
|
-
| `
|
|
128
|
+
| Callback | Signature | Description |
|
|
129
|
+
| ------------------- | -------------------------------------- | ---------------------------------------------- |
|
|
130
|
+
| `onNodeSelect` | `(nodeId, nodeData) => void` | Node clicked/selected |
|
|
131
|
+
| `onNodeDeselect` | `() => void` | Selection cleared |
|
|
132
|
+
| `onNodeDoubleClick` | `(nodeId, nodeData) => void` | Node double-clicked |
|
|
133
|
+
| `onNodeCreate` | `(params) => void` | Node created via edge drawing into empty space |
|
|
134
|
+
| `onNodeDelete` | `(nodeId, nodeData) => void` | Node deleted |
|
|
135
|
+
| `onNodeLabelChange` | `(nodeId, newLabel) => void` | Node label edited inline |
|
|
136
|
+
| `onNodeCollapse` | `(nodeId, collapsed) => void` | Collapse toggle clicked |
|
|
137
|
+
| `onNodeColorChange` | `(nodeId, colorType, color) => void` | Node color changed via toolbar |
|
|
138
|
+
| `onNodeIconChange` | `(nodeId, iconName) => void` | Node icon changed via toolbar |
|
|
139
|
+
| `onNodeHoverAction` | `(actionId, nodeId, nodeData) => void` | Hover overlay action clicked |
|
|
117
140
|
|
|
118
141
|
### Edge Events
|
|
119
142
|
|
|
120
|
-
| Callback
|
|
121
|
-
|
|
122
|
-
| `onEdgeCreate`
|
|
123
|
-
| `onEdgeSelect`
|
|
124
|
-
| `onEdgeDeselect`
|
|
125
|
-
| `onEdgeRemove`
|
|
126
|
-
| `
|
|
143
|
+
| Callback | Signature | Description |
|
|
144
|
+
| ------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
145
|
+
| `onEdgeCreate` | `(sourceId, targetId, properties?: FlowEdgeProperties) => void` | New edge drawn; optional `sourceProperty` / `targetProperty` identify rows |
|
|
146
|
+
| `onEdgeSelect` | `(edgeId, edgeData) => void` | Edge clicked/selected |
|
|
147
|
+
| `onEdgeDeselect` | `() => void` | Edge selection cleared |
|
|
148
|
+
| `onEdgeRemove` | `(edgeId, edgeData) => void` | Edge removed |
|
|
149
|
+
| `onEdgeDelete` | `(edgeId, edgeData) => void` | User requested deletion |
|
|
150
|
+
| `onEdgeColorChange` | `(edgeId, color) => void` | Edge color changed |
|
|
151
|
+
| `onEdgeLabelChange` | `(edgeId, label) => void` | Edge label changed |
|
|
152
|
+
| `onEdgeStyleChange` | `(edgeId, "solid" \| "dashed" \| "animated") => void` | Edge style changed |
|
|
127
153
|
|
|
128
154
|
### Diagram Events
|
|
129
155
|
|
|
130
|
-
| Callback
|
|
131
|
-
|
|
132
|
-
| `onViewportChange`
|
|
133
|
-
| `onDirectionChange` | `(direction) => void`
|
|
134
|
-
| `onArrayModeChange` | `(isArrayMode) => void`
|
|
135
|
-
| `
|
|
156
|
+
| Callback | Signature | Description |
|
|
157
|
+
| ------------------- | ------------------------------------------------------ | --------------------------------------------------------------------- |
|
|
158
|
+
| `onViewportChange` | `(viewport) => void` | Pan/zoom changed |
|
|
159
|
+
| `onDirectionChange` | `(direction) => void` | Direction changed via bottom bar |
|
|
160
|
+
| `onArrayModeChange` | `(isArrayMode) => void` | Array/set mode toggled |
|
|
161
|
+
| `onInit` | `(engine: FlowEngine) => void` | Renderer handle initialized; node boxes become available after layout |
|
|
162
|
+
| `onJsonChange` | `(next: SqueedJson, change: SqueedChangeInfo) => void` | Immutable document update |
|
|
136
163
|
|
|
137
164
|
## JSON Conventions
|
|
138
165
|
|
|
139
166
|
Special `$`-prefixed keys control node rendering:
|
|
140
167
|
|
|
141
|
-
| Key
|
|
142
|
-
|
|
143
|
-
| `$label`
|
|
144
|
-
| `$bgColor`
|
|
145
|
-
| `$textColor`
|
|
146
|
-
| `$
|
|
147
|
-
| `$
|
|
148
|
-
|
|
|
168
|
+
| Key | Description |
|
|
169
|
+
| ----------------------------------- | ------------------------------------------------------------------------------- |
|
|
170
|
+
| `$label` | Display label for the node |
|
|
171
|
+
| `$bgColor` | Background color (Chakra token, e.g. `"blue.500"`) |
|
|
172
|
+
| `$textColor` | Text color |
|
|
173
|
+
| `$icon` | React Icons name, e.g. `PiGear` |
|
|
174
|
+
| `$collapsed` | `true` to collapse children, `false` to force expanded |
|
|
175
|
+
| `$parent` | Parent node ID (creates compound/container nodes) |
|
|
176
|
+
| `$target` | Cross-link to a JSON address, e.g. `root.database`; one per source node |
|
|
177
|
+
| `$connections` | `SqueedConnection[]`; multiple node/property mappings, independent of `$target` |
|
|
178
|
+
| `$sourceLabel` / `$targetLabel` | Hierarchy-edge / cross-link label |
|
|
179
|
+
| `$edgeColor` | Edge color |
|
|
180
|
+
| `$isEdgeDashed` / `$isEdgeAnimated` | Dashed or animated edges |
|
|
181
|
+
| `$` | Array value (creates array child list, e.g. `{ $: ["a", "b"] }`) |
|
|
149
182
|
|
|
150
183
|
```json
|
|
151
184
|
{
|
|
@@ -163,76 +196,157 @@ Special `$`-prefixed keys control node rendering:
|
|
|
163
196
|
}
|
|
164
197
|
```
|
|
165
198
|
|
|
166
|
-
|
|
199
|
+
### Property Connections
|
|
200
|
+
|
|
201
|
+
Store mappings on the source node. Property references are exact row keys, while `target` is the destination node's JSON address:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"backend": {
|
|
206
|
+
"runtime": "Node",
|
|
207
|
+
"api": "REST",
|
|
208
|
+
"$connections": [
|
|
209
|
+
{
|
|
210
|
+
"sourceProperty": "api",
|
|
211
|
+
"target": "root.handlers",
|
|
212
|
+
"targetProperty": "http"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"sourceProperty": "runtime",
|
|
216
|
+
"target": "root.handlers",
|
|
217
|
+
"targetProperty": "ws"
|
|
218
|
+
}
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
"handlers": { "http": "express", "ws": "socket.io" }
|
|
222
|
+
}
|
|
223
|
+
```
|
|
167
224
|
|
|
168
225
|
```tsx
|
|
169
|
-
|
|
226
|
+
<FlowDiagram
|
|
227
|
+
json={doc}
|
|
228
|
+
config={{ edgeMode: "properties" }}
|
|
229
|
+
callbacks={{ onJsonChange: setDoc }}
|
|
230
|
+
/>
|
|
231
|
+
```
|
|
170
232
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
sprtObjctKy: false,
|
|
175
|
-
isCntr: false,
|
|
176
|
-
});
|
|
233
|
+
`"workflow"` attaches the same edges to node boxes; `"properties"` attaches to rows. Switching modes does not change the document or graph connections. Edges without property references keep their ordinary node attachment. Row ports stay left/right, reversed in `RL`, even for vertical layouts.
|
|
234
|
+
|
|
235
|
+
Drag an output port to an input port or destination row to append a mapping. Property drags into empty space cancel. Existing node-level drawing still writes `$target`. The edge toolbar edits/deletes only the selected mapping. In document mode, store the full `onJsonChange` document; in raw `nodes`/`edges` mode, store the optional third `onEdgeCreate` argument in the edge's `data`.
|
|
177
236
|
|
|
178
|
-
|
|
179
|
-
|
|
237
|
+
Each entry accepts `target`, optional `sourceProperty`/`targetProperty`, `id`, `label`, `color` (Chakra token or hex), and `style: "solid" | "dashed" | "animated"`. Drag-created mappings receive IDs and duplicate endpoint mappings are not appended. Supply explicit unique IDs when declaring otherwise identical mappings that need distinct identities.
|
|
238
|
+
|
|
239
|
+
Missing or unrendered rows fall back to the corresponding node endpoint. Missing/collapsed nodes hide their edges without deleting the saved mappings. Custom views can expose rows with `data-flow-property={key}`; their positions are measured automatically. `readOnly` and `edgeHandles: false` disable port dragging.
|
|
240
|
+
|
|
241
|
+
Mappings are metadata. The SDK does not execute workflows or transfer data.
|
|
242
|
+
|
|
243
|
+
## Exported Utilities
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
import { compileSqueed, setNodeProp, applyCollapsed } from "@squeed/flow-sdk";
|
|
180
247
|
|
|
181
|
-
|
|
182
|
-
const
|
|
248
|
+
const next = setNodeProp(json, "root.service", "$label", "API");
|
|
249
|
+
const { nodes, edges } = compileSqueed(next, {
|
|
250
|
+
title: "Services",
|
|
251
|
+
isCenter: false,
|
|
252
|
+
});
|
|
253
|
+
const visible = applyCollapsed(handBuiltNodes, handBuiltEdges);
|
|
183
254
|
```
|
|
184
255
|
|
|
256
|
+
`createFlowDiagram` remains exported as the lower-level compiler. Use `compileSqueed` for stable edge IDs, document styling, and `$connections`. `addConnection(json, sourceAddress, connection)` appends a mapping immutably. Hierarchy edges are removed by removing the child; `$target` links and individual `$connections` can be deleted independently.
|
|
257
|
+
|
|
185
258
|
## Custom Overlays
|
|
186
259
|
|
|
187
260
|
### Node Hover Overlay
|
|
188
261
|
|
|
189
262
|
```tsx
|
|
263
|
+
import { HStack, IconButton } from "@chakra-ui/react";
|
|
264
|
+
import { PiPencilSimple, PiTrash } from "react-icons/pi";
|
|
265
|
+
|
|
190
266
|
<FlowDiagram
|
|
191
267
|
json={data}
|
|
192
268
|
config={{
|
|
193
269
|
renderNodeOverlay: ({ nodeId, nodeData, isRoot }) => (
|
|
194
|
-
<HStack bg="gray.800" px={2} py={1} borderRadius={
|
|
195
|
-
<IconButton
|
|
196
|
-
|
|
270
|
+
<HStack bg="gray.800" px={2} py={1} borderRadius={8}>
|
|
271
|
+
<IconButton
|
|
272
|
+
aria-label="Edit node"
|
|
273
|
+
size="xs"
|
|
274
|
+
onClick={() => edit(nodeId)}
|
|
275
|
+
>
|
|
276
|
+
<PiPencilSimple />
|
|
277
|
+
</IconButton>
|
|
278
|
+
{!isRoot && (
|
|
279
|
+
<IconButton
|
|
280
|
+
aria-label="Delete node"
|
|
281
|
+
size="xs"
|
|
282
|
+
onClick={() => remove(nodeId)}
|
|
283
|
+
>
|
|
284
|
+
<PiTrash />
|
|
285
|
+
</IconButton>
|
|
286
|
+
)}
|
|
197
287
|
</HStack>
|
|
198
288
|
),
|
|
199
289
|
}}
|
|
200
|
-
|
|
290
|
+
/>;
|
|
201
291
|
```
|
|
202
292
|
|
|
203
293
|
### Selection Toolbar
|
|
204
294
|
|
|
205
295
|
```tsx
|
|
296
|
+
import { HStack, IconButton, Text } from "@chakra-ui/react";
|
|
297
|
+
import { PiX } from "react-icons/pi";
|
|
298
|
+
|
|
206
299
|
<FlowDiagram
|
|
207
300
|
json={data}
|
|
208
301
|
config={{
|
|
209
302
|
renderSelectedNodeToolbar: ({ selectedNodeIds, onDeselect }) => (
|
|
210
|
-
<HStack bg="gray.800" px={3} py={2} borderRadius={
|
|
303
|
+
<HStack bg="gray.800" px={3} py={2} borderRadius={8}>
|
|
211
304
|
<Text fontSize="xs">{selectedNodeIds.length} selected</Text>
|
|
212
|
-
<IconButton
|
|
305
|
+
<IconButton aria-label="Clear selection" size="xs" onClick={onDeselect}>
|
|
306
|
+
<PiX />
|
|
307
|
+
</IconButton>
|
|
213
308
|
</HStack>
|
|
214
309
|
),
|
|
215
310
|
}}
|
|
216
|
-
|
|
311
|
+
/>;
|
|
217
312
|
```
|
|
218
313
|
|
|
219
314
|
## Keyboard Shortcuts
|
|
220
315
|
|
|
221
|
-
| Key
|
|
222
|
-
|
|
223
|
-
| `Z`
|
|
224
|
-
| `M`
|
|
225
|
-
| `D`
|
|
316
|
+
| Key | Action |
|
|
317
|
+
| ---------------------- | --------------------------------- |
|
|
318
|
+
| `Z` | Toggle zoom mode (scroll to zoom) |
|
|
319
|
+
| `M` | Toggle multi-select mode |
|
|
320
|
+
| `D` | Toggle drag/pan mode |
|
|
321
|
+
| `Delete` / `Backspace` | Delete selected non-root nodes |
|
|
322
|
+
| `Escape` | Cancel drawing or a label edit |
|
|
323
|
+
|
|
324
|
+
The canvas supports pointer panning, wheel zoom, and two-finger pinch zoom. Interactive inputs inside nodes retain their own keyboard behavior.
|
|
226
325
|
|
|
227
326
|
## Theme Utilities
|
|
228
327
|
|
|
229
328
|
```tsx
|
|
230
|
-
import {
|
|
329
|
+
import {
|
|
330
|
+
useCustomColors,
|
|
331
|
+
getChakraColorHex,
|
|
332
|
+
getColorVariant,
|
|
333
|
+
} from "@squeed/flow-sdk";
|
|
231
334
|
|
|
232
335
|
const { background, colorText, border } = useCustomColors();
|
|
233
336
|
const hex = getChakraColorHex("blue.500"); // → "#3182ce"
|
|
234
337
|
```
|
|
235
338
|
|
|
339
|
+
## Development Checks
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
npm ci
|
|
343
|
+
npx playwright install chromium
|
|
344
|
+
npm run check:release
|
|
345
|
+
npm pack --dry-run
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
The release check runs unit tests, browser tests against the built ESM package, a clean tarball installation with ESM/CommonJS type and runtime checks, and the production dependency audit. Packing rebuilds the artifacts. React, Chakra, Emotion, Framer Motion, and React Icons are external to the SDK bundle; application download size includes whichever peers and icon libraries it uses.
|
|
349
|
+
|
|
236
350
|
---
|
|
237
351
|
|
|
238
352
|
Author: **seyi ogunbowale**
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Third-party software included in @squeed/flow-sdk
|
|
2
|
+
|
|
3
|
+
The SDK is licensed under the terms in LICENSE. The following notices apply
|
|
4
|
+
to bundled dependencies and adapted source code. React, Chakra UI, Emotion,
|
|
5
|
+
Framer Motion, and React Icons are external dependencies with their own licenses.
|
|
6
|
+
|
|
7
|
+
===========================================================================
|
|
8
|
+
Cytoscape.js - adapted edge geometry in src/engine/geometry.ts and EdgeView.tsx
|
|
9
|
+
https://github.com/cytoscape/cytoscape.js
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2016-2025, The Cytoscape Consortium.
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
14
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
15
|
+
the Software without restriction, including without limitation the rights to
|
|
16
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
17
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
18
|
+
so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
|
|
31
|
+
===========================================================================
|
|
32
|
+
Dagre and Graphlib
|
|
33
|
+
https://github.com/dagrejs/dagre
|
|
34
|
+
https://github.com/dagrejs/graphlib
|
|
35
|
+
|
|
36
|
+
Copyright (c) 2012-2014 Chris Pettitt
|
|
37
|
+
|
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
39
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
40
|
+
in the Software without restriction, including without limitation the rights
|
|
41
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
42
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
43
|
+
furnished to do so, subject to the following conditions:
|
|
44
|
+
|
|
45
|
+
The above copyright notice and this permission notice shall be included in
|
|
46
|
+
all copies or substantial portions of the Software.
|
|
47
|
+
|
|
48
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
49
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
50
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
51
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
52
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
53
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
54
|
+
THE SOFTWARE.
|
|
55
|
+
|
|
56
|
+
===========================================================================
|
|
57
|
+
Lodash and Lodash ES
|
|
58
|
+
https://github.com/lodash/lodash
|
|
59
|
+
|
|
60
|
+
Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
|
61
|
+
|
|
62
|
+
Based on Underscore.js, copyright Jeremy Ashkenas,
|
|
63
|
+
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
|
|
64
|
+
|
|
65
|
+
This software consists of voluntary contributions made by many
|
|
66
|
+
individuals. For exact contribution history, see the revision history
|
|
67
|
+
available at https://github.com/lodash/lodash
|
|
68
|
+
|
|
69
|
+
The following license applies to all parts of this software except as
|
|
70
|
+
documented below:
|
|
71
|
+
|
|
72
|
+
====
|
|
73
|
+
|
|
74
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
75
|
+
a copy of this software and associated documentation files (the
|
|
76
|
+
"Software"), to deal in the Software without restriction, including
|
|
77
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
78
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
79
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
80
|
+
the following conditions:
|
|
81
|
+
|
|
82
|
+
The above copyright notice and this permission notice shall be
|
|
83
|
+
included in all copies or substantial portions of the Software.
|
|
84
|
+
|
|
85
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
88
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
89
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
90
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
91
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
92
|
+
|
|
93
|
+
====
|
|
94
|
+
|
|
95
|
+
Copyright and related rights for sample code are waived via CC0. Sample
|
|
96
|
+
code is defined as all source code displayed within the prose of the
|
|
97
|
+
documentation.
|
|
98
|
+
|
|
99
|
+
CC0: http://creativecommons.org/publicdomain/zero/1.0/
|
|
100
|
+
|
|
101
|
+
====
|
|
102
|
+
|
|
103
|
+
Files located in the node_modules and vendor directories are externally
|
|
104
|
+
maintained libraries used by this software which have their own
|
|
105
|
+
licenses; we recommend you read them, as their terms may differ from the
|
|
106
|
+
terms above.
|
|
107
|
+
|
|
108
|
+
===========================================================================
|
|
109
|
+
UUID
|
|
110
|
+
https://github.com/uuidjs/uuid
|
|
111
|
+
|
|
112
|
+
The MIT License (MIT)
|
|
113
|
+
|
|
114
|
+
Copyright (c) 2010-2020 Robert Kieffer and other contributors
|
|
115
|
+
|
|
116
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
117
|
+
|
|
118
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
119
|
+
|
|
120
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|