@elabs-ai/components-flow 4.0.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 +21 -0
- package/README.md +79 -0
- package/dist/index.d.ts +634 -0
- package/dist/index.js +1577 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
- package/src/canvas-shell/canvas-shell.stories.tsx +77 -0
- package/src/canvas-shell/canvas-shell.test.tsx +106 -0
- package/src/canvas-shell/canvas-shell.tsx +128 -0
- package/src/canvas-shell/index.ts +1 -0
- package/src/flow-button-edge/flow-button-edge.stories.tsx +151 -0
- package/src/flow-button-edge/flow-button-edge.test.tsx +99 -0
- package/src/flow-button-edge/flow-button-edge.tsx +80 -0
- package/src/flow-button-edge/index.ts +5 -0
- package/src/flow-edge/flow-edge.stories.tsx +79 -0
- package/src/flow-edge/flow-edge.test.tsx +76 -0
- package/src/flow-edge/flow-edge.tsx +34 -0
- package/src/flow-edge/index.ts +1 -0
- package/src/flow-floating-edge/floating-edge-geometry.test.ts +100 -0
- package/src/flow-floating-edge/floating-edge-geometry.ts +128 -0
- package/src/flow-floating-edge/flow-floating-edge.stories.tsx +81 -0
- package/src/flow-floating-edge/flow-floating-edge.tsx +82 -0
- package/src/flow-floating-edge/index.ts +6 -0
- package/src/flow-group-node/flow-group-node.stories.tsx +283 -0
- package/src/flow-group-node/flow-group-node.test.tsx +100 -0
- package/src/flow-group-node/flow-group-node.tsx +134 -0
- package/src/flow-group-node/index.ts +6 -0
- package/src/flow-layout/flow-layout.stories.tsx +215 -0
- package/src/flow-layout/flow-layout.test.tsx +133 -0
- package/src/flow-layout/flow-layout.ts +104 -0
- package/src/flow-layout/index.ts +14 -0
- package/src/flow-layout/layout-graph.test.ts +257 -0
- package/src/flow-layout/layout-graph.ts +302 -0
- package/src/flow-layout/use-auto-layout.ts +26 -0
- package/src/flow-layout/use-flow-layout.ts +60 -0
- package/src/flow-mini-map/flow-mini-map.stories.tsx +74 -0
- package/src/flow-mini-map/flow-mini-map.test.tsx +56 -0
- package/src/flow-mini-map/flow-mini-map.tsx +29 -0
- package/src/flow-mini-map/index.ts +1 -0
- package/src/flow-node/flow-node.stories.tsx +143 -0
- package/src/flow-node/flow-node.test.tsx +156 -0
- package/src/flow-node/flow-node.tsx +190 -0
- package/src/flow-node/index.ts +8 -0
- package/src/flow-placeholder-node/flow-placeholder-node.stories.tsx +260 -0
- package/src/flow-placeholder-node/flow-placeholder-node.test.tsx +101 -0
- package/src/flow-placeholder-node/flow-placeholder-node.tsx +49 -0
- package/src/flow-placeholder-node/index.ts +5 -0
- package/src/flow-smart-edge/flow-smart-edge.stories.tsx +75 -0
- package/src/flow-smart-edge/flow-smart-edge.tsx +75 -0
- package/src/flow-smart-edge/index.ts +9 -0
- package/src/flow-smart-edge/smart-edge-geometry.test.ts +120 -0
- package/src/flow-smart-edge/smart-edge-geometry.ts +116 -0
- package/src/helper-lines/get-helper-lines.ts +98 -0
- package/src/helper-lines/helper-lines.stories.tsx +107 -0
- package/src/helper-lines/helper-lines.test.tsx +78 -0
- package/src/helper-lines/helper-lines.tsx +67 -0
- package/src/helper-lines/index.ts +7 -0
- package/src/helper-lines/use-helper-lines.ts +109 -0
- package/src/index.ts +37 -0
- package/src/inspector-panel/index.ts +1 -0
- package/src/inspector-panel/inspector-panel.stories.tsx +161 -0
- package/src/inspector-panel/inspector-panel.test.tsx +82 -0
- package/src/inspector-panel/inspector-panel.tsx +129 -0
- package/src/legend/index.ts +1 -0
- package/src/legend/legend.stories.tsx +56 -0
- package/src/legend/legend.test.tsx +46 -0
- package/src/legend/legend.tsx +39 -0
- package/src/templates-flow-workspace.stories.tsx +169 -0
- package/src/use-flow-groups/group-operations.test.ts +318 -0
- package/src/use-flow-groups/group-operations.ts +349 -0
- package/src/use-flow-groups/index.ts +13 -0
- package/src/use-flow-groups/use-flow-groups.ts +113 -0
- package/src/zoom-controls/index.ts +1 -0
- package/src/zoom-controls/zoom-controls.stories.tsx +68 -0
- package/src/zoom-controls/zoom-controls.test.tsx +80 -0
- package/src/zoom-controls/zoom-controls.tsx +78 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, SVGAttributes } from 'react';
|
|
3
|
+
import { Node, Edge, ReactFlowProps, NodeProps, EdgeProps, Position, NodeChange, MiniMapProps, PanelPosition } from '@xyflow/react';
|
|
4
|
+
export { Background, Connection, Controls, Edge, EdgeProps, MiniMap, Node, NodeProps, Panel, Position, ReactFlow, ReactFlowProvider, addEdge, useEdgesState, useNodesState, useReactFlow } from '@xyflow/react';
|
|
5
|
+
|
|
6
|
+
interface CanvasShellProps<NodeType extends Node = Node, EdgeType extends Edge = Edge> extends ReactFlowProps<NodeType, EdgeType> {
|
|
7
|
+
/** Render a branded dotted background grid. Defaults to true. */
|
|
8
|
+
background?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Enable alignment guides + snapping while a single node is dragged. Off by
|
|
11
|
+
* default; when false, CanvasShell behaves exactly as before. When true,
|
|
12
|
+
* CanvasShell wires `useHelperLines` around your `onNodesChange` and renders
|
|
13
|
+
* the `<HelperLines>` overlay internally — pass `nodes` + `onNodesChange`
|
|
14
|
+
* (the standard controlled setup, e.g. via `useNodesState`). For full control
|
|
15
|
+
* use the exported `useHelperLines` + `<HelperLines>` directly.
|
|
16
|
+
*/
|
|
17
|
+
helperLines?: boolean;
|
|
18
|
+
/** Overlays rendered inside the flow (ZoomControls, Legend, Panels). */
|
|
19
|
+
children?: ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Branded React Flow canvas. Sets a token-driven background + sensible
|
|
24
|
+
* defaults; pass nodes/edges/handlers through as normal React Flow props.
|
|
25
|
+
*
|
|
26
|
+
* Consumers MUST import the React Flow stylesheet once at the app root:
|
|
27
|
+
* import "@xyflow/react/dist/style.css";
|
|
28
|
+
*
|
|
29
|
+
* Children render inside the flow context, so <ZoomControls /> and React Flow
|
|
30
|
+
* <Panel>s work when placed here.
|
|
31
|
+
*/
|
|
32
|
+
declare function CanvasShell<NodeType extends Node = Node, EdgeType extends Edge = Edge>({ helperLines, ...props }: CanvasShellProps<NodeType, EdgeType>): react.JSX.Element;
|
|
33
|
+
|
|
34
|
+
/** A node side that can carry a handle. Doubles as the handle's stable id. */
|
|
35
|
+
type FlowHandleSide = "top" | "right" | "bottom" | "left";
|
|
36
|
+
/**
|
|
37
|
+
* Which sides of a node expose source and/or target handles. When omitted,
|
|
38
|
+
* `FlowNode` keeps its default single top **target** + bottom **source**. When
|
|
39
|
+
* set, a `<Handle>` is rendered on each listed side with a **stable id equal to
|
|
40
|
+
* the side name** (`"top" | "right" | "bottom" | "left"`), addressable per
|
|
41
|
+
* handle type — so edges (e.g. `FlowSmartEdge`) can pick a specific anchor.
|
|
42
|
+
*/
|
|
43
|
+
interface FlowNodeHandles {
|
|
44
|
+
/** Sides exposing a source handle (handle `id` === side). */
|
|
45
|
+
source?: FlowHandleSide[];
|
|
46
|
+
/** Sides exposing a target handle (handle `id` === side). */
|
|
47
|
+
target?: FlowHandleSide[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A `FlowNodeHandles` config exposing source **and** target anchors on all four
|
|
51
|
+
* sides. The recommended setup for `FlowSmartEdge` / `FlowFloatingEdge`: with
|
|
52
|
+
* anchors on every side, an edge connects on whichever side **faces** the other
|
|
53
|
+
* node (left/right when side-by-side, top/bottom when stacked) instead of always
|
|
54
|
+
* top/bottom. Spread onto a node's `data.handles`.
|
|
55
|
+
*/
|
|
56
|
+
declare const FLOW_ALL_SIDE_HANDLES: FlowNodeHandles;
|
|
57
|
+
interface FlowNodeData extends Record<string, unknown> {
|
|
58
|
+
title: string;
|
|
59
|
+
subtitle?: string;
|
|
60
|
+
/** Short type label shown as an eyebrow, e.g. "Source", "Transform". */
|
|
61
|
+
kind?: string;
|
|
62
|
+
icon?: ReactNode;
|
|
63
|
+
tone?: "default" | "accent" | "success" | "warning" | "destructive";
|
|
64
|
+
/**
|
|
65
|
+
* Optional multi-side handle configuration. Absent → default top-target /
|
|
66
|
+
* bottom-source (unchanged, backward-compatible).
|
|
67
|
+
*/
|
|
68
|
+
handles?: FlowNodeHandles;
|
|
69
|
+
}
|
|
70
|
+
type BrandFlowNode = Node<FlowNodeData, "brand">;
|
|
71
|
+
/**
|
|
72
|
+
* Branded custom node. Register it in `nodeTypes={{ brand: FlowNode }}` and
|
|
73
|
+
* create nodes with `type: "brand"` and `data: FlowNodeData`.
|
|
74
|
+
*/
|
|
75
|
+
declare function FlowNode({ data, selected, sourcePosition, targetPosition, }: NodeProps<BrandFlowNode>): react.JSX.Element;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Branded bezier edge using the `--flow-edge` token. Register it in
|
|
79
|
+
* `edgeTypes={{ brand: FlowEdge }}` and create edges with `type: "brand"`.
|
|
80
|
+
*/
|
|
81
|
+
declare function FlowEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, markerEnd, style, }: EdgeProps): react.JSX.Element;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Branded edge that picks the closest source/target handle pair (from a node's
|
|
85
|
+
* multi-side `FlowNodeHandles` config) and routes a bezier between them. Anchors
|
|
86
|
+
* are recomputed every render, so they flip as nodes are dragged. Register it in
|
|
87
|
+
* `edgeTypes={{ smart: FlowSmartEdge }}` and give the connected nodes a
|
|
88
|
+
* `data.handles` config. Uses the `--flow-edge` token, matching `FlowEdge`.
|
|
89
|
+
*/
|
|
90
|
+
declare function FlowSmartEdge({ id, source, target, markerEnd, style }: EdgeProps): react.JSX.Element | null;
|
|
91
|
+
|
|
92
|
+
/** Axis-aligned node rectangle in absolute flow coordinates. */
|
|
93
|
+
interface NodeRect {
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
width: number;
|
|
97
|
+
height: number;
|
|
98
|
+
}
|
|
99
|
+
/** All four candidate handle sides, in a stable order. */
|
|
100
|
+
declare const HANDLE_SIDES: FlowHandleSide[];
|
|
101
|
+
/** Maps a handle side to the React Flow `Position` used for bezier control. */
|
|
102
|
+
declare const sideToPosition: Record<FlowHandleSide, Position>;
|
|
103
|
+
/** Absolute coordinate of a handle on the given side (the side's midpoint). */
|
|
104
|
+
declare function handlePoint(rect: NodeRect, side: FlowHandleSide): {
|
|
105
|
+
x: number;
|
|
106
|
+
y: number;
|
|
107
|
+
};
|
|
108
|
+
/** The chosen source/target handle pair plus their absolute anchor points. */
|
|
109
|
+
interface ClosestHandles {
|
|
110
|
+
sourceSide: FlowHandleSide;
|
|
111
|
+
targetSide: FlowHandleSide;
|
|
112
|
+
sx: number;
|
|
113
|
+
sy: number;
|
|
114
|
+
tx: number;
|
|
115
|
+
ty: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Picks the source/target handle pair (one handle per node) with the shortest
|
|
119
|
+
* straight-line distance between their anchor points. Empty side lists fall
|
|
120
|
+
* back to all four sides so an edge always resolves to a pair.
|
|
121
|
+
*/
|
|
122
|
+
declare function pickClosestHandles(source: NodeRect, sourceSides: FlowHandleSide[], target: NodeRect, targetSides: FlowHandleSide[]): ClosestHandles;
|
|
123
|
+
|
|
124
|
+
/** Optional per-edge `data` for {@link FlowFloatingEdge}. */
|
|
125
|
+
interface FloatingEdgeData {
|
|
126
|
+
/**
|
|
127
|
+
* Show a small anchor dot at each border connection point. On by default so the
|
|
128
|
+
* edge visibly terminates on the node's closest side (rather than a bare line
|
|
129
|
+
* touching the border with no anchor). Set `false` to hide.
|
|
130
|
+
*/
|
|
131
|
+
anchors?: boolean;
|
|
132
|
+
[key: string]: unknown;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Branded floating edge: it attaches to the node **border** at the point facing
|
|
136
|
+
* the other node (no fixed handle), recomputed as nodes drag. Register it in
|
|
137
|
+
* `edgeTypes={{ floating: FlowFloatingEdge }}`; the connected nodes need no
|
|
138
|
+
* handle config. Uses the `--flow-edge` token, matching `FlowEdge`.
|
|
139
|
+
*
|
|
140
|
+
* A small **anchor dot** is drawn at each connection point (on by default) so the
|
|
141
|
+
* line clearly terminates on the node's closest border side — not at a bare,
|
|
142
|
+
* unanchored spot. Toggle per edge with `data.anchors: false`.
|
|
143
|
+
*/
|
|
144
|
+
declare function FlowFloatingEdge({ id, source, target, markerEnd, style, data }: EdgeProps): react.JSX.Element | null;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The minimal live node geometry `getEdgeParams` needs. A React Flow
|
|
148
|
+
* `InternalNode` satisfies this structurally (`internals.positionAbsolute` +
|
|
149
|
+
* `measured`), so you can pass one directly; tests can pass a plain fake.
|
|
150
|
+
*/
|
|
151
|
+
interface FloatingNodeGeometry {
|
|
152
|
+
internals: {
|
|
153
|
+
positionAbsolute: {
|
|
154
|
+
x: number;
|
|
155
|
+
y: number;
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
measured: {
|
|
159
|
+
width?: number;
|
|
160
|
+
height?: number;
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/** Border anchor points + `Position`s for a floating edge between two nodes. */
|
|
164
|
+
interface EdgeParams {
|
|
165
|
+
sx: number;
|
|
166
|
+
sy: number;
|
|
167
|
+
tx: number;
|
|
168
|
+
ty: number;
|
|
169
|
+
sourcePos: Position;
|
|
170
|
+
targetPos: Position;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Computes where a floating edge attaches to each node's border — the
|
|
174
|
+
* intersection of the center-to-center line with each rectangle — plus the
|
|
175
|
+
* border `Position`. Recompute per render so anchors track dragging nodes.
|
|
176
|
+
*/
|
|
177
|
+
declare function getEdgeParams(source: FloatingNodeGeometry, target: FloatingNodeGeometry): EdgeParams;
|
|
178
|
+
|
|
179
|
+
interface FlowPlaceholderNodeData extends Record<string, unknown> {
|
|
180
|
+
/** Label rendered inside the placeholder. @default "Add node" */
|
|
181
|
+
label?: string;
|
|
182
|
+
/** Called when the placeholder is activated (click, Enter, or Space). */
|
|
183
|
+
onActivate?: () => void;
|
|
184
|
+
}
|
|
185
|
+
type BrandFlowPlaceholderNode = Node<FlowPlaceholderNodeData, "placeholder">;
|
|
186
|
+
/**
|
|
187
|
+
* Dashed, muted "add here" node — a clickable affordance that grows the
|
|
188
|
+
* graph. Register it in `nodeTypes={{ placeholder: FlowPlaceholderNode }}`
|
|
189
|
+
* and create nodes with `type: "placeholder"` and `data: FlowPlaceholderNodeData`.
|
|
190
|
+
*
|
|
191
|
+
* Renders a real `<button>` (keyboard-activatable via native Enter/Space) with
|
|
192
|
+
* an `aria-label`, and a single **target** `<Handle>` (top) so an existing
|
|
193
|
+
* edge can point at it. Fires `data.onActivate?.()` on activation — the
|
|
194
|
+
* typical handler converts the placeholder into a real `FlowNode` and grows a
|
|
195
|
+
* fresh placeholder beneath it (see the "Placeholder tail" story).
|
|
196
|
+
*/
|
|
197
|
+
declare function FlowPlaceholderNode({ data }: NodeProps<BrandFlowPlaceholderNode>): react.JSX.Element;
|
|
198
|
+
|
|
199
|
+
interface FlowButtonEdgeData extends Record<string, unknown> {
|
|
200
|
+
/** aria-label for the insert button. @default "Insert node on edge" */
|
|
201
|
+
label?: string;
|
|
202
|
+
/** Called when the edge's "+" button is activated (click, Enter, or Space). */
|
|
203
|
+
onInsert?: () => void;
|
|
204
|
+
}
|
|
205
|
+
type BrandFlowButtonEdge = Edge<FlowButtonEdgeData, "button">;
|
|
206
|
+
/**
|
|
207
|
+
* Branded bezier edge (matching `FlowEdge`'s `--flow-edge` token) with a
|
|
208
|
+
* centered "+" button rendered via `EdgeLabelRenderer` at the edge midpoint.
|
|
209
|
+
* Register it in `edgeTypes={{ button: FlowButtonEdge }}` and create edges
|
|
210
|
+
* with `type: "button"` and `data: FlowButtonEdgeData`.
|
|
211
|
+
*
|
|
212
|
+
* The button is a real `<button>` with an `aria-label`, keyboard-activatable
|
|
213
|
+
* via native Enter/Space. Fires `data.onInsert?.()` on activation — the
|
|
214
|
+
* typical handler splits the edge: insert a new node between source and
|
|
215
|
+
* target and rewire the two edges (see the "Insert between" story).
|
|
216
|
+
*/
|
|
217
|
+
declare function FlowButtonEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, markerEnd, style, data, }: EdgeProps<BrandFlowButtonEdge>): react.JSX.Element;
|
|
218
|
+
|
|
219
|
+
/** Direction dagre lays the graph out in — top-to-bottom, left-to-right, etc. */
|
|
220
|
+
type FlowLayoutDirection = "TB" | "LR" | "BT" | "RL";
|
|
221
|
+
interface FlowLayoutOptions {
|
|
222
|
+
/** Layout direction. @default "TB" */
|
|
223
|
+
direction?: FlowLayoutDirection;
|
|
224
|
+
/** Gap between nodes in the same rank (dagre `nodesep`). @default 48 */
|
|
225
|
+
nodeSpacing?: number;
|
|
226
|
+
/** Gap between ranks (dagre `ranksep`). @default 72 */
|
|
227
|
+
rankSpacing?: number;
|
|
228
|
+
}
|
|
229
|
+
interface FlowLayoutResult<NodeType extends Node = Node, EdgeType extends Edge = Edge> {
|
|
230
|
+
nodes: NodeType[];
|
|
231
|
+
edges: EdgeType[];
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Pure dagre-powered auto layout. Computes new `position`s for `nodes` given
|
|
235
|
+
* `edges` — no React, no side effects, safe to call anywhere (including
|
|
236
|
+
* outside a component or in a test).
|
|
237
|
+
*
|
|
238
|
+
* Respects each node's **measured** size (`node.measured` — how React Flow
|
|
239
|
+
* v12 reports actual rendered dimensions), falling back to `node.width`/
|
|
240
|
+
* `node.height`, then a sensible default. Node identity and `data` are left
|
|
241
|
+
* untouched — only `position` changes.
|
|
242
|
+
*
|
|
243
|
+
* Pair with `useFlowLayout` to apply the result to a live canvas.
|
|
244
|
+
*/
|
|
245
|
+
declare function layoutFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], options?: FlowLayoutOptions): FlowLayoutResult<NodeType, EdgeType>;
|
|
246
|
+
|
|
247
|
+
interface UseFlowLayoutResult {
|
|
248
|
+
/**
|
|
249
|
+
* Auto-lay-out the current nodes/edges with dagre and fit the view. Safe to
|
|
250
|
+
* call repeatedly (e.g. from a toolbar button on every click). No-ops until
|
|
251
|
+
* React Flow has measured every node.
|
|
252
|
+
*/
|
|
253
|
+
layout: (direction?: FlowLayoutDirection, options?: Omit<FlowLayoutOptions, "direction">) => void;
|
|
254
|
+
/** Whether nodes are measured and ready to be laid out. */
|
|
255
|
+
ready: boolean;
|
|
256
|
+
/** Whether a layout pass is currently running (true only for the duration of `layout()`). */
|
|
257
|
+
layouting: boolean;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Hook form of `layoutFlow`. Reads the live nodes/edges from `useReactFlow()`,
|
|
261
|
+
* waits for `useNodesInitialized()` so real (measured) node sizes are used —
|
|
262
|
+
* never lays out against 0×0 unmeasured nodes — applies the computed
|
|
263
|
+
* positions via `setNodes`, then calls `fitView()`.
|
|
264
|
+
*
|
|
265
|
+
* Must be called from a component rendered inside a `<CanvasShell>` /
|
|
266
|
+
* `<ReactFlow>` (React Flow context).
|
|
267
|
+
*/
|
|
268
|
+
declare function useFlowLayout<NodeType extends Node = Node, EdgeType extends Edge = Edge>(): UseFlowLayoutResult;
|
|
269
|
+
|
|
270
|
+
/** Which generic graph-geometry algorithm `layoutGraph` should run. */
|
|
271
|
+
type LayoutAlgorithm = "concentric" | "force" | "layered-lr" | "grid";
|
|
272
|
+
/** Horizontal/vertical gap used by the `"grid"` and `"layered-lr"` algorithms. */
|
|
273
|
+
interface LayoutSpacing {
|
|
274
|
+
x: number;
|
|
275
|
+
y: number;
|
|
276
|
+
}
|
|
277
|
+
interface LayoutOptions {
|
|
278
|
+
/** Which layout algorithm to run. */
|
|
279
|
+
algorithm: LayoutAlgorithm;
|
|
280
|
+
/**
|
|
281
|
+
* `"concentric"` only — the focal node placed at the origin. Defaults to the
|
|
282
|
+
* highest-degree node when omitted (or when the id doesn't match a node).
|
|
283
|
+
*/
|
|
284
|
+
centerId?: string;
|
|
285
|
+
/** `"concentric"` only — radius of ring 1; ring N sits at `N × ringRadius`. @default 180 */
|
|
286
|
+
ringRadius?: number;
|
|
287
|
+
/** `"force"` only — number of synchronous simulation ticks to run. @default 300 */
|
|
288
|
+
iterations?: number;
|
|
289
|
+
/** `"grid"` / `"layered-lr"` — gap between nodes. @default {x:200,y:120} for grid. */
|
|
290
|
+
spacing?: LayoutSpacing;
|
|
291
|
+
/** Resolve a node's size by id. Falls back to `measured`/`width`/`height`/a sensible default. */
|
|
292
|
+
nodeSize?: (id: string) => {
|
|
293
|
+
width: number;
|
|
294
|
+
height: number;
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Pure graph-geometry auto layout. Computes new `position`s for `nodes` given
|
|
299
|
+
* `edges` and a `LayoutAlgorithm` — no React, no DOM, no side effects, safe to
|
|
300
|
+
* call anywhere (including outside a component or in a test). Deterministic:
|
|
301
|
+
* identical `nodes`/`edges`/`options` always produce identical positions.
|
|
302
|
+
*
|
|
303
|
+
* Node identity and `data` are left untouched — only `position` changes.
|
|
304
|
+
* Pair with `useAutoLayout` for a memoized hook form.
|
|
305
|
+
*
|
|
306
|
+
* - `"layered-lr"` delegates to the dagre-powered `layoutFlow` (direction `"LR"`).
|
|
307
|
+
* - `"concentric"` places `centerId` (or the highest-degree node) at the
|
|
308
|
+
* origin, with BFS shells at `ring × ringRadius`; disconnected nodes land in
|
|
309
|
+
* one extra outer ring so positions are never `NaN`.
|
|
310
|
+
* - `"force"` runs `d3-force` synchronously for a fixed number of `iterations`,
|
|
311
|
+
* seeded on a circle by index (no randomness) so runs are reproducible.
|
|
312
|
+
* - `"grid"` lays nodes out row-major using `spacing`.
|
|
313
|
+
*/
|
|
314
|
+
declare function layoutGraph<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], options: LayoutOptions): NodeType[];
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Memoized `layoutGraph` — pure graph-geometry layout (no live canvas access,
|
|
318
|
+
* no side effects). Recomputes only when `nodes`, `edges`, or `options`
|
|
319
|
+
* change; pass stable references (e.g. from `useNodesState`/`useEdgesState`
|
|
320
|
+
* and a memoized `options` object) to avoid recomputing every render.
|
|
321
|
+
*
|
|
322
|
+
* Use this when you want laid-out nodes to render with (e.g. feeding
|
|
323
|
+
* `useNodesState`'s initial value, or a derived/read-only view). To apply a
|
|
324
|
+
* layout to a *live* React Flow instance (read current nodes, set them back,
|
|
325
|
+
* fit the view), call `layoutGraph` directly from an event handler instead —
|
|
326
|
+
* see the `LayoutGraph` story.
|
|
327
|
+
*/
|
|
328
|
+
declare function useAutoLayout<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], options: LayoutOptions): NodeType[];
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Pure alignment-guide geometry for the helper-lines feature.
|
|
332
|
+
*
|
|
333
|
+
* Implemented fresh from the documented "helper lines" behaviour (the React Flow
|
|
334
|
+
* Pro example is paid — only the concept is reused): while a single node drags,
|
|
335
|
+
* compare its left / horizontal-center / right against every other node's
|
|
336
|
+
* left / center / right (and top / middle / bottom on the vertical axis). When a
|
|
337
|
+
* pair falls within `threshold` flow-coordinate pixels, record the guide's
|
|
338
|
+
* absolute coordinate and the snapped top-left position for the dragged node.
|
|
339
|
+
*
|
|
340
|
+
* Everything here is a pure function of plain rectangles so it is unit-testable
|
|
341
|
+
* without a live React Flow instance.
|
|
342
|
+
*/
|
|
343
|
+
/** A node's bounding box in absolute flow coordinates (top-left origin). */
|
|
344
|
+
interface HelperLineRect {
|
|
345
|
+
/** Left edge (top-left x) in flow coordinates. */
|
|
346
|
+
x: number;
|
|
347
|
+
/** Top edge (top-left y) in flow coordinates. */
|
|
348
|
+
y: number;
|
|
349
|
+
width: number;
|
|
350
|
+
height: number;
|
|
351
|
+
}
|
|
352
|
+
interface HelperLinesResult {
|
|
353
|
+
/** New top-left x for the dragged node once snapped to the vertical guide. */
|
|
354
|
+
snapX?: number;
|
|
355
|
+
/** New top-left y for the dragged node once snapped to the horizontal guide. */
|
|
356
|
+
snapY?: number;
|
|
357
|
+
/** Absolute flow-x of the active vertical guide line, if any. */
|
|
358
|
+
vertical?: number;
|
|
359
|
+
/** Absolute flow-y of the active horizontal guide line, if any. */
|
|
360
|
+
horizontal?: number;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Compute the closest vertical + horizontal alignment guides (and the snapped
|
|
364
|
+
* position) for a dragged rectangle against the other rectangles.
|
|
365
|
+
*
|
|
366
|
+
* @param dragged the dragged node's proposed bounding box (flow coordinates)
|
|
367
|
+
* @param others every other node's bounding box
|
|
368
|
+
* @param threshold max distance (flow px) at which alignment engages; a pair at
|
|
369
|
+
* exactly `threshold` does NOT match (strict boundary)
|
|
370
|
+
*/
|
|
371
|
+
declare function getHelperLines(dragged: HelperLineRect, others: Iterable<HelperLineRect>, threshold?: number): HelperLinesResult;
|
|
372
|
+
|
|
373
|
+
interface UseHelperLinesOptions {
|
|
374
|
+
/** Alignment threshold in flow coordinates. Defaults to 5. */
|
|
375
|
+
threshold?: number;
|
|
376
|
+
}
|
|
377
|
+
interface UseHelperLinesResult<NodeType extends Node = Node> {
|
|
378
|
+
/**
|
|
379
|
+
* Drop-in replacement for the consumer's `onNodesChange`: it snaps a dragged
|
|
380
|
+
* node onto any near-aligned edge/center, then forwards the (mutated) changes
|
|
381
|
+
* to the wrapped handler.
|
|
382
|
+
*/
|
|
383
|
+
onNodesChange: (changes: NodeChange<NodeType>[]) => void;
|
|
384
|
+
/** Absolute flow-y of the active horizontal guide, or `undefined`. */
|
|
385
|
+
helperLineHorizontal: number | undefined;
|
|
386
|
+
/** Absolute flow-x of the active vertical guide, or `undefined`. */
|
|
387
|
+
helperLineVertical: number | undefined;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Decorate a consumer's `onNodesChange` with alignment guides + snapping.
|
|
391
|
+
*
|
|
392
|
+
* While a **single** node is dragged, the returned handler compares its
|
|
393
|
+
* left/center/right and top/middle/bottom against every other node; when a pair
|
|
394
|
+
* is within `threshold` flow px it (a) snaps the dragged node's position change
|
|
395
|
+
* onto the guide and (b) exposes the guide coordinates so `<HelperLines>` can
|
|
396
|
+
* draw them. Guides clear when the drag ends or nothing aligns.
|
|
397
|
+
*
|
|
398
|
+
* Must be called inside a React Flow context (a `<ReactFlowProvider>` or a
|
|
399
|
+
* component rendered under `<ReactFlow>`), since it reads the live node store.
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
|
403
|
+
* const { onNodesChange: handle, helperLineHorizontal, helperLineVertical } =
|
|
404
|
+
* useHelperLines(onNodesChange);
|
|
405
|
+
* // <ReactFlow onNodesChange={handle}>
|
|
406
|
+
* // <HelperLines horizontal={helperLineHorizontal} vertical={helperLineVertical} />
|
|
407
|
+
*/
|
|
408
|
+
declare function useHelperLines<NodeType extends Node = Node>(onNodesChange?: (changes: NodeChange<NodeType>[]) => void, options?: UseHelperLinesOptions): UseHelperLinesResult<NodeType>;
|
|
409
|
+
|
|
410
|
+
interface HelperLinesProps extends SVGAttributes<SVGSVGElement> {
|
|
411
|
+
/** Absolute flow-y of the horizontal guide (from `useHelperLines`). */
|
|
412
|
+
horizontal?: number;
|
|
413
|
+
/** Absolute flow-x of the vertical guide (from `useHelperLines`). */
|
|
414
|
+
vertical?: number;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Decorative alignment-guide overlay. Draws a full-width horizontal line at
|
|
418
|
+
* `horizontal` and/or a full-height vertical line at `vertical`, coloured with
|
|
419
|
+
* the `--flow-helper-line` token. It reads the live viewport transform
|
|
420
|
+
* (zoom + pan) so the guides sit on the real alignment position when the canvas
|
|
421
|
+
* is zoomed or panned.
|
|
422
|
+
*
|
|
423
|
+
* Render as a child of `<CanvasShell>` / `<ReactFlow>` (it must be inside the
|
|
424
|
+
* flow context to read the viewport). Purely decorative — hidden from AT.
|
|
425
|
+
*/
|
|
426
|
+
declare const HelperLines: react.ForwardRefExoticComponent<HelperLinesProps & react.RefAttributes<SVGSVGElement>>;
|
|
427
|
+
|
|
428
|
+
type FlowMiniMapProps<NodeType extends Node = Node> = MiniMapProps<NodeType>;
|
|
429
|
+
/**
|
|
430
|
+
* Branded preset over React Flow's `<MiniMap>` — sources node/mask colors from
|
|
431
|
+
* the `--flow-minimap-*` tokens so the overview stays theme-aware (the raw
|
|
432
|
+
* `MiniMap` re-export defaults to library colors and renders theme-blind,
|
|
433
|
+
* especially under a low-chroma theme). Every prop can still be overridden; render
|
|
434
|
+
* inside a `<CanvasShell>` (it needs the React Flow context via `useStore`).
|
|
435
|
+
*/
|
|
436
|
+
declare function FlowMiniMap<NodeType extends Node = Node>({ className, nodeColor, nodeStrokeColor, maskColor, ...props }: FlowMiniMapProps<NodeType>): react.JSX.Element;
|
|
437
|
+
|
|
438
|
+
interface InspectorPanelProps {
|
|
439
|
+
title?: ReactNode;
|
|
440
|
+
children: ReactNode;
|
|
441
|
+
onClose?: () => void;
|
|
442
|
+
/** Empty-state shown when nothing is selected. */
|
|
443
|
+
emptyMessage?: ReactNode;
|
|
444
|
+
/** When false, render the empty state instead of children. */
|
|
445
|
+
hasSelection?: boolean;
|
|
446
|
+
/**
|
|
447
|
+
* Stable identity of the current selection (e.g. the selected node's id).
|
|
448
|
+
* When it changes, the body replays a quick fade so it reads as "details for
|
|
449
|
+
* THIS node". Pass the selected entity's id (or any stable key derived from
|
|
450
|
+
* the selected data).
|
|
451
|
+
*/
|
|
452
|
+
selectionKey?: string | number;
|
|
453
|
+
/**
|
|
454
|
+
* Collapse (research 09 step 3 — converged on the shared `@elabs-ai/components-ui`
|
|
455
|
+
* `useCollapsiblePanel` base; the panel stays single-view, drill-in is
|
|
456
|
+
* ContextPanel-only). Controlled `open` / uncontrolled `defaultOpen`.
|
|
457
|
+
*/
|
|
458
|
+
open?: boolean;
|
|
459
|
+
defaultOpen?: boolean;
|
|
460
|
+
onOpenChange?: (open: boolean) => void;
|
|
461
|
+
/** Which edge the panel sits on (collapse slide direction). Default `"right"`. */
|
|
462
|
+
side?: "left" | "right";
|
|
463
|
+
/** Expanded width (any CSS length). Default `"18rem"` (the original `w-72`). */
|
|
464
|
+
width?: string;
|
|
465
|
+
className?: string;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Properties panel for the selected node/edge. Reusable beside a canvas (e.g.
|
|
469
|
+
* inside a <SplitPanel>) or as a React Flow <Panel>. Always mounted; collapses
|
|
470
|
+
* via the canonical `useCollapsiblePanel` width tween (CSS-gated, reduced-
|
|
471
|
+
* motion safe) when `open`/`defaultOpen` drive it.
|
|
472
|
+
*/
|
|
473
|
+
declare function InspectorPanel({ title, children, onClose, emptyMessage, hasSelection, selectionKey, open, defaultOpen, onOpenChange, side, width, className, }: InspectorPanelProps): react.JSX.Element;
|
|
474
|
+
|
|
475
|
+
interface LegendItem {
|
|
476
|
+
label: string;
|
|
477
|
+
/** Any CSS color or token reference, e.g. "var(--chart-1)". */
|
|
478
|
+
color: string;
|
|
479
|
+
}
|
|
480
|
+
interface LegendProps {
|
|
481
|
+
items: LegendItem[];
|
|
482
|
+
title?: string;
|
|
483
|
+
className?: string;
|
|
484
|
+
}
|
|
485
|
+
/** Small legend mapping colors/types to labels for a canvas or chart. */
|
|
486
|
+
declare function Legend({ items, title, className }: LegendProps): react.JSX.Element;
|
|
487
|
+
|
|
488
|
+
interface ZoomControlsProps {
|
|
489
|
+
position?: PanelPosition;
|
|
490
|
+
className?: string;
|
|
491
|
+
}
|
|
492
|
+
/** Branded zoom in / out / fit controls. Render inside <CanvasShell>. */
|
|
493
|
+
declare function ZoomControls({ position, className }: ZoomControlsProps): react.JSX.Element;
|
|
494
|
+
|
|
495
|
+
/** Visual accent for a group container. */
|
|
496
|
+
type FlowGroupTone = "default" | "accent" | "success" | "warning" | "destructive";
|
|
497
|
+
interface FlowGroupNodeData extends Record<string, unknown> {
|
|
498
|
+
/** Header label for the group. */
|
|
499
|
+
title: string;
|
|
500
|
+
/** Optional leading glyph (a Lucide icon element, etc.). */
|
|
501
|
+
icon?: ReactNode;
|
|
502
|
+
/**
|
|
503
|
+
* Whether the group is collapsed to an overview chip. Managed by
|
|
504
|
+
* `useFlowGroups().collapseGroup` / `expandGroup`; the header toggle flips it.
|
|
505
|
+
*/
|
|
506
|
+
collapsed?: boolean;
|
|
507
|
+
/**
|
|
508
|
+
* Fallback count shown next to the title. When omitted, the node counts its
|
|
509
|
+
* live direct children from the store, so the badge stays accurate as nodes
|
|
510
|
+
* are added or removed.
|
|
511
|
+
*/
|
|
512
|
+
childCount?: number;
|
|
513
|
+
/** Accent tone for the header rule + count badge. */
|
|
514
|
+
tone?: FlowGroupTone;
|
|
515
|
+
}
|
|
516
|
+
type BrandFlowGroupNode = Node<FlowGroupNodeData, "group">;
|
|
517
|
+
/**
|
|
518
|
+
* Branded group container node. Register it as `nodeTypes={{ group: FlowGroupNode }}`
|
|
519
|
+
* and create nodes with `type: "group"` + typed `data: FlowGroupNodeData`. Children
|
|
520
|
+
* are re-parented onto it (`parentId`, `extent: "parent"`) — see `useFlowGroups`.
|
|
521
|
+
*
|
|
522
|
+
* The header carries the title, a live child-count badge and a collapse/expand
|
|
523
|
+
* toggle (a real `<button>` with `aria-expanded`) that drives
|
|
524
|
+
* `useFlowGroups().collapseGroup` / `expandGroup`. When selected (and expanded)
|
|
525
|
+
* a `<NodeResizer>` lets the group be resized.
|
|
526
|
+
*
|
|
527
|
+
* The surface uses the FL-01 tokens `--flow-group` (fill) + `--flow-group-border`
|
|
528
|
+
* (border). Under a theme whose `--flow-group` is near-transparent, the
|
|
529
|
+
* drawn border does the work.
|
|
530
|
+
*/
|
|
531
|
+
declare function FlowGroupNode({ id, data, selected }: NodeProps<BrandFlowGroupNode>): react.JSX.Element;
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Pure, framework-agnostic grouping operations over `nodes`/`edges` arrays.
|
|
535
|
+
*
|
|
536
|
+
* Every function is a **pure transform** — it never mutates its inputs and
|
|
537
|
+
* returns a fresh `{ nodes, edges }`. This is the testable core; `useFlowGroups`
|
|
538
|
+
* is a thin hook that wires these to a live canvas via `useReactFlow()`.
|
|
539
|
+
*/
|
|
540
|
+
/** Node type used for the group container (matches `nodeTypes={{ group: FlowGroupNode }}`). */
|
|
541
|
+
declare const FLOW_GROUP_NODE_TYPE = "group";
|
|
542
|
+
interface GroupNodesOptions {
|
|
543
|
+
/** Id for the new group node. Required so the operation stays deterministic/testable. */
|
|
544
|
+
groupId: string;
|
|
545
|
+
/** Header title for the group. @default "Group" */
|
|
546
|
+
title?: string;
|
|
547
|
+
/** Accent tone for the group header. */
|
|
548
|
+
tone?: FlowGroupTone;
|
|
549
|
+
/** Padding (px) around the child bounds. @default 28 */
|
|
550
|
+
padding?: number;
|
|
551
|
+
}
|
|
552
|
+
interface FlowGroupOperationResult<NodeType extends Node = Node, EdgeType extends Edge = Edge> {
|
|
553
|
+
nodes: NodeType[];
|
|
554
|
+
edges: EdgeType[];
|
|
555
|
+
}
|
|
556
|
+
/** Marker + metadata written onto a proxy edge's `data`. */
|
|
557
|
+
interface FlowGroupProxyEdgeData extends Record<string, unknown> {
|
|
558
|
+
__flowGroupProxy: true;
|
|
559
|
+
/** Id of the collapsed group this proxy edge stands in for. */
|
|
560
|
+
groupId: string;
|
|
561
|
+
}
|
|
562
|
+
/** True if `edge` is a proxy edge synthesized for a collapsed group. */
|
|
563
|
+
declare function isFlowGroupProxyEdge(edge: Edge): boolean;
|
|
564
|
+
/**
|
|
565
|
+
* Wrap `nodeIds` (assumed top-level) in a new `FlowGroupNode` parent.
|
|
566
|
+
*
|
|
567
|
+
* - Computes the child bounds with `getNodesBounds`.
|
|
568
|
+
* - Inserts the group node **before** its children in the array (React Flow
|
|
569
|
+
* requires a parent to precede its children).
|
|
570
|
+
* - Re-parents each child (`parentId`, `extent: "parent"`) and rewrites its
|
|
571
|
+
* position to be **relative to the group origin**.
|
|
572
|
+
*/
|
|
573
|
+
declare function groupNodes<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], nodeIds: string[], options: GroupNodesOptions): FlowGroupOperationResult<NodeType, EdgeType>;
|
|
574
|
+
/**
|
|
575
|
+
* Dissolve a group: remove the group node and restore its **direct** children to
|
|
576
|
+
* absolute positions (dropping `parentId`/`extent`). If the group is currently
|
|
577
|
+
* collapsed it is expanded first, so ungrouping a collapsed group is safe.
|
|
578
|
+
*/
|
|
579
|
+
declare function ungroup<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], groupId: string): FlowGroupOperationResult<NodeType, EdgeType>;
|
|
580
|
+
/**
|
|
581
|
+
* Collapse a group to an overview chip.
|
|
582
|
+
*
|
|
583
|
+
* - Hides every descendant (including nested groups and their subtrees).
|
|
584
|
+
* - Shrinks the group to a fixed overview size and marks `data.collapsed`.
|
|
585
|
+
* - Re-routes every edge that **crosses the collapse boundary** (exactly one
|
|
586
|
+
* endpoint inside the collapsed subtree) to a **proxy edge** targeting the
|
|
587
|
+
* group node; the original edge is hidden and stashed for restoration.
|
|
588
|
+
* - Edges fully inside or fully outside the subtree are left untouched.
|
|
589
|
+
*
|
|
590
|
+
* The full pre-collapse graph is stashed on the group's `data` so `expandGroup`
|
|
591
|
+
* is an exact inverse. Nested collapse is handled by snapshotting each
|
|
592
|
+
* descendant's exact prior state (a subgroup that was already collapsed stays
|
|
593
|
+
* collapsed on expand — no double-unhide).
|
|
594
|
+
*/
|
|
595
|
+
declare function collapseGroup<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], groupId: string): FlowGroupOperationResult<NodeType, EdgeType>;
|
|
596
|
+
/**
|
|
597
|
+
* Expand a collapsed group — the exact inverse of `collapseGroup`. Restores the
|
|
598
|
+
* group node, un-hides the descendant subtree (to each node's exact prior
|
|
599
|
+
* state), removes this group's proxy edges and restores the original edges.
|
|
600
|
+
* No-op if the group isn't collapsed.
|
|
601
|
+
*/
|
|
602
|
+
declare function expandGroup<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], groupId: string): FlowGroupOperationResult<NodeType, EdgeType>;
|
|
603
|
+
/** Collapse if expanded, expand if collapsed. */
|
|
604
|
+
declare function toggleGroupCollapsed<NodeType extends Node = Node, EdgeType extends Edge = Edge>(nodes: NodeType[], edges: EdgeType[], groupId: string): FlowGroupOperationResult<NodeType, EdgeType>;
|
|
605
|
+
|
|
606
|
+
/** Options for `groupNodes`/`groupSelection` with an optional generated id. */
|
|
607
|
+
type GroupOptions = Partial<Pick<GroupNodesOptions, "groupId">> & Omit<GroupNodesOptions, "groupId">;
|
|
608
|
+
interface UseFlowGroupsResult {
|
|
609
|
+
/**
|
|
610
|
+
* Wrap the given (top-level) node ids in a new `FlowGroupNode`. Returns the new
|
|
611
|
+
* group id, or `undefined` if nothing was grouped. Pass `options.groupId` for a
|
|
612
|
+
* deterministic id; otherwise one is generated.
|
|
613
|
+
*/
|
|
614
|
+
groupNodes: (nodeIds: string[], options?: GroupOptions) => string | undefined;
|
|
615
|
+
/** Group the currently-selected nodes. Returns the new group id (or `undefined`). */
|
|
616
|
+
groupSelection: (options?: GroupOptions) => string | undefined;
|
|
617
|
+
/** Dissolve a group, restoring its children to absolute positions. */
|
|
618
|
+
ungroup: (groupId: string) => void;
|
|
619
|
+
/** Collapse a group to an overview chip (hides subtree, reroutes boundary edges). */
|
|
620
|
+
collapseGroup: (groupId: string) => void;
|
|
621
|
+
/** Expand a collapsed group (exact inverse of collapse). */
|
|
622
|
+
expandGroup: (groupId: string) => void;
|
|
623
|
+
/** Collapse if expanded, expand if collapsed. */
|
|
624
|
+
toggleCollapse: (groupId: string) => void;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Thin hook over the pure grouping operations in `group-operations.ts`. Reads and
|
|
628
|
+
* writes the live graph via `useReactFlow()`; all the logic lives in the pure,
|
|
629
|
+
* unit-tested core. Must be called inside a React Flow context (e.g. from a
|
|
630
|
+
* `<Panel>` child of `<CanvasShell>` or from within a custom node).
|
|
631
|
+
*/
|
|
632
|
+
declare function useFlowGroups<NodeType extends Node = Node, EdgeType extends Edge = Edge>(): UseFlowGroupsResult;
|
|
633
|
+
|
|
634
|
+
export { type BrandFlowButtonEdge, type BrandFlowGroupNode, type BrandFlowNode, type BrandFlowPlaceholderNode, CanvasShell, type CanvasShellProps, type ClosestHandles, type EdgeParams, FLOW_ALL_SIDE_HANDLES, FLOW_GROUP_NODE_TYPE, type FloatingEdgeData, type FloatingNodeGeometry, FlowButtonEdge, type FlowButtonEdgeData, FlowEdge, FlowFloatingEdge, FlowGroupNode, type FlowGroupNodeData, type FlowGroupOperationResult, type FlowGroupProxyEdgeData, type FlowGroupTone, type FlowHandleSide, type FlowLayoutDirection, type FlowLayoutOptions, type FlowLayoutResult, FlowMiniMap, type FlowMiniMapProps, FlowNode, type FlowNodeData, type FlowNodeHandles, FlowPlaceholderNode, type FlowPlaceholderNodeData, FlowSmartEdge, type GroupNodesOptions, type GroupOptions, HANDLE_SIDES, type HelperLineRect, HelperLines, type HelperLinesProps, type HelperLinesResult, InspectorPanel, type InspectorPanelProps, type LayoutAlgorithm, type LayoutOptions, type LayoutSpacing, Legend, type LegendItem, type LegendProps, type NodeRect, type UseFlowGroupsResult, type UseFlowLayoutResult, type UseHelperLinesOptions, type UseHelperLinesResult, ZoomControls, type ZoomControlsProps, collapseGroup, expandGroup, getEdgeParams, getHelperLines, groupNodes, handlePoint, isFlowGroupProxyEdge, layoutFlow, layoutGraph, pickClosestHandles, sideToPosition, toggleGroupCollapsed, ungroup, useAutoLayout, useFlowGroups, useFlowLayout, useHelperLines };
|