@statelyai/flow-react 0.4.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/README.md +103 -0
- package/dist/esm/backgrounds.d.ts +20 -0
- package/dist/esm/backgrounds.js +53 -0
- package/dist/esm/hooks.js +255 -0
- package/dist/esm/index.d.ts +306 -0
- package/dist/esm/index.js +979 -0
- package/package.json +87 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import * as react10 from "react";
|
|
2
|
+
import { CSSProperties, HTMLAttributes, ReactNode, RefObject } from "react";
|
|
3
|
+
import { AnchorSpec, ConnectionEndedEvent, CreateFlowOptions, EdgePathData, FlowColorMode, FlowController, FlowEdge, FlowGraph, FlowInputMode, FlowNode, FlowProfile, FlowStoreContext, LayoutRequestedEvent, Point, Rect, Viewport, VisualPort } from "@statelyai/flow";
|
|
4
|
+
import { ResolvedFlowColorMode } from "@statelyai/flow-dom";
|
|
5
|
+
|
|
6
|
+
//#region src/createFlowInstance.d.ts
|
|
7
|
+
type FlowSelector<T> = (context: FlowStoreContext) => T;
|
|
8
|
+
type FlowSelectorEquality<T> = (current: T, next: T) => boolean;
|
|
9
|
+
type FlowStoreListener<T = unknown> = {
|
|
10
|
+
selector: FlowSelector<T>;
|
|
11
|
+
onChange: (value: T, previousValue: T, context: FlowStoreContext) => void;
|
|
12
|
+
isEqual?: FlowSelectorEquality<T>;
|
|
13
|
+
fireImmediately?: boolean;
|
|
14
|
+
};
|
|
15
|
+
type FlowEventListeners = {
|
|
16
|
+
connectionEnded?: (event: ConnectionEndedEvent) => void;
|
|
17
|
+
layoutRequested?: (event: LayoutRequestedEvent) => void;
|
|
18
|
+
};
|
|
19
|
+
type FlowInstanceSettings = Omit<CreateFlowOptions, "graph">;
|
|
20
|
+
type CreateFlowInstanceOptions = {
|
|
21
|
+
graph: FlowGraph;
|
|
22
|
+
settings?: FlowInstanceSettings;
|
|
23
|
+
listeners?: FlowStoreListener[];
|
|
24
|
+
events?: FlowEventListeners;
|
|
25
|
+
};
|
|
26
|
+
type FlowInstance = FlowController & {
|
|
27
|
+
getSnapshot(): FlowStoreContext;
|
|
28
|
+
/**
|
|
29
|
+
* Convert window client coordinates (e.g. `event.clientX/Y` from drops or
|
|
30
|
+
* window-level listeners) to canvas coordinates, accounting for the
|
|
31
|
+
* attached container's position. Unlike `screenToCanvas`, which expects
|
|
32
|
+
* container-relative pixels.
|
|
33
|
+
*/
|
|
34
|
+
clientToCanvas(point: Point): Point;
|
|
35
|
+
listen<T>(selector: FlowSelector<T>, listener: FlowStoreListener<T>["onChange"], options?: {
|
|
36
|
+
isEqual?: FlowSelectorEquality<T>;
|
|
37
|
+
fireImmediately?: boolean;
|
|
38
|
+
}): () => void;
|
|
39
|
+
};
|
|
40
|
+
declare function createFlowInstance(options: CreateFlowInstanceOptions): FlowInstance;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/FlowInstanceContext.d.ts
|
|
43
|
+
declare function FlowInstanceProvider(props: {
|
|
44
|
+
flow: FlowInstance;
|
|
45
|
+
children: ReactNode;
|
|
46
|
+
}): react10.JSX.Element;
|
|
47
|
+
declare function useFlowInstance(): FlowInstance;
|
|
48
|
+
declare function useOptionalFlowInstance(): FlowInstance | null;
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/hooks.d.ts
|
|
51
|
+
type UseCreateFlowInstanceOptions = CreateFlowInstanceOptions;
|
|
52
|
+
type UseFlowOptions = UseCreateFlowInstanceOptions;
|
|
53
|
+
declare function useFlow(options: UseFlowOptions): FlowInstance;
|
|
54
|
+
declare function useCreateFlowInstance(options: UseCreateFlowInstanceOptions): FlowInstance;
|
|
55
|
+
declare function useFlowSelector<T>(selector: FlowSelector<T>, options?: {
|
|
56
|
+
flow?: FlowInstance;
|
|
57
|
+
isEqual?: FlowSelectorEquality<T>;
|
|
58
|
+
}): T;
|
|
59
|
+
declare function useFlowContext(): FlowStoreContext;
|
|
60
|
+
/**
|
|
61
|
+
* Like `useFlowSelector`, but subscribed through the entity-change notifier:
|
|
62
|
+
* the selector re-runs only when the entity with `id` may have changed, not
|
|
63
|
+
* on every store transition. This is what makes thousands of mounted entity
|
|
64
|
+
* views affordable — see BENCHMARK.md.
|
|
65
|
+
*/
|
|
66
|
+
declare function useFlowEntity<T>(id: string, selector: FlowSelector<T>, options?: {
|
|
67
|
+
flow?: FlowInstance;
|
|
68
|
+
isEqual?: FlowSelectorEquality<T>;
|
|
69
|
+
}): T;
|
|
70
|
+
declare function useFlowValue<T>(selector: FlowSelector<T>, isEqual?: FlowSelectorEquality<T>): T;
|
|
71
|
+
type DerivedEntityFields = {
|
|
72
|
+
selected: boolean;
|
|
73
|
+
focused: boolean;
|
|
74
|
+
hovered: boolean;
|
|
75
|
+
props: HTMLAttributes<HTMLElement> & Record<`data-${string}`, string>;
|
|
76
|
+
};
|
|
77
|
+
type FlowNodeBinding<TData = any> = FlowNode<TData> & DerivedEntityFields;
|
|
78
|
+
type FlowEdgeBinding<TEdgeData = any, TLabelData = any> = FlowEdge<TEdgeData, TLabelData> & DerivedEntityFields & {
|
|
79
|
+
pathData: ReturnType<FlowInstance['getAllEdgePaths']> extends Map<string, infer TPath> ? TPath | null : never;
|
|
80
|
+
};
|
|
81
|
+
type FlowPortBinding = VisualPort & DerivedEntityFields & {
|
|
82
|
+
id: string;
|
|
83
|
+
nodeId: string;
|
|
84
|
+
portName: string;
|
|
85
|
+
};
|
|
86
|
+
type EntitySelector<TValue, TSelected> = (value: TValue, context: FlowStoreContext) => TSelected;
|
|
87
|
+
declare function useFlowNode<TData = any>(id: string): FlowNodeBinding<TData>;
|
|
88
|
+
declare function useFlowNode<TData = any, TSelected = unknown>(id: string, selector: EntitySelector<FlowNode<TData>, TSelected>, isEqual?: FlowSelectorEquality<TSelected>): TSelected;
|
|
89
|
+
declare function useFlowEdge<TEdgeData = any, TLabelData = any>(id: string): FlowEdgeBinding<TEdgeData, TLabelData>;
|
|
90
|
+
declare function useFlowEdge<TEdgeData = any, TLabelData = any, TSelected = unknown>(id: string, selector: EntitySelector<FlowEdge<TEdgeData, TLabelData>, TSelected>, isEqual?: FlowSelectorEquality<TSelected>): TSelected;
|
|
91
|
+
declare function useFlowPort(id: string): FlowPortBinding;
|
|
92
|
+
declare function useFlowPort<TSelected>(id: string, selector: EntitySelector<FlowPortBinding, TSelected>, isEqual?: FlowSelectorEquality<TSelected>): TSelected;
|
|
93
|
+
declare function useFlowViewport(): Viewport;
|
|
94
|
+
declare function useFlowMeasurement(id: string): Rect | null;
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/useFlowInput.d.ts
|
|
97
|
+
type UseFlowInputOptions = {
|
|
98
|
+
/**
|
|
99
|
+
* Input modes, or a resolver from store context. Defaults to the store
|
|
100
|
+
* profile's input modes (when a profile is given) and otherwise to the
|
|
101
|
+
* core default set, which follows the store's `context.mode`
|
|
102
|
+
* (interactive / readonly). Initial-only: changes after mount are ignored —
|
|
103
|
+
* swap behavior at runtime via `flow.trigger.setMode(...)` or a
|
|
104
|
+
* context-aware resolver.
|
|
105
|
+
*/
|
|
106
|
+
modes?: FlowInputMode[] | ((context: FlowStoreContext) => FlowInputMode[]);
|
|
107
|
+
/** Store profile whose per-mode `input.modes` drive the runtime. */
|
|
108
|
+
profile?: FlowProfile;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Bind a container element to the core input runtime: all pointer, wheel,
|
|
112
|
+
* and keyboard gestures inside the container are recognized by input modes
|
|
113
|
+
* and applied to the flow store. This replaces hand-written gesture handlers.
|
|
114
|
+
*/
|
|
115
|
+
declare function useFlowInput(flow: FlowInstance, containerRef: RefObject<HTMLElement | null>, options?: UseFlowInputOptions): void;
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/StatelyFlow.d.ts
|
|
118
|
+
type RenderNodeProps<TNodeData = unknown> = {
|
|
119
|
+
flow: FlowInstance;
|
|
120
|
+
node: FlowNode<TNodeData>;
|
|
121
|
+
bounds: Rect;
|
|
122
|
+
selected: boolean;
|
|
123
|
+
dragging: boolean;
|
|
124
|
+
hovered: boolean;
|
|
125
|
+
highlights: ReadonlyArray<{
|
|
126
|
+
kind: string;
|
|
127
|
+
meta: unknown;
|
|
128
|
+
}>;
|
|
129
|
+
};
|
|
130
|
+
type RenderEdgeProps<TEdgeData = unknown> = {
|
|
131
|
+
flow: FlowInstance;
|
|
132
|
+
edge: FlowEdge<TEdgeData>;
|
|
133
|
+
pathData: EdgePathData;
|
|
134
|
+
selected: boolean;
|
|
135
|
+
hovered: boolean;
|
|
136
|
+
highlights: ReadonlyArray<{
|
|
137
|
+
kind: string;
|
|
138
|
+
meta: unknown;
|
|
139
|
+
}>;
|
|
140
|
+
};
|
|
141
|
+
type StatelyFlowProps<TNodeData = unknown, TEdgeData = unknown> = {
|
|
142
|
+
flow?: FlowInstance;
|
|
143
|
+
graph: FlowGraph<TNodeData, TEdgeData>;
|
|
144
|
+
settings?: FlowInstanceSettings;
|
|
145
|
+
listeners?: FlowStoreListener[];
|
|
146
|
+
events?: FlowEventListeners;
|
|
147
|
+
renderNode?: (props: RenderNodeProps<TNodeData>) => ReactNode;
|
|
148
|
+
renderEdge?: (props: RenderEdgeProps<TEdgeData>) => ReactNode;
|
|
149
|
+
/**
|
|
150
|
+
* Only mount nodes/edges that intersect the viewport (plus an overscan
|
|
151
|
+
* margin). Recommended for large graphs.
|
|
152
|
+
*/
|
|
153
|
+
onlyRenderVisible?: boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Override the input modes driving gestures (initial-only). Defaults to
|
|
156
|
+
* the store profile's input modes when `settings.store.profile` is set,
|
|
157
|
+
* otherwise to the core defaults. Example — custom connection validity:
|
|
158
|
+
*
|
|
159
|
+
* ```tsx
|
|
160
|
+
* inputModes={[
|
|
161
|
+
* ...defaultInputModes.filter((mode) => mode.id !== "connect"),
|
|
162
|
+
* connectMode({ isValid: myValidity }),
|
|
163
|
+
* ]}
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
inputModes?: FlowInputMode[] | ((context: FlowStoreContext) => FlowInputMode[]);
|
|
167
|
+
className?: string;
|
|
168
|
+
style?: CSSProperties;
|
|
169
|
+
background?: ReactNode;
|
|
170
|
+
children?: ReactNode;
|
|
171
|
+
};
|
|
172
|
+
declare function StatelyFlow<TNodeData = unknown, TEdgeData = unknown>(props: StatelyFlowProps<TNodeData, TEdgeData>): react10.JSX.Element;
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/FlowToolbar.d.ts
|
|
175
|
+
/** Border-box size of an element, kept current via ResizeObserver. */
|
|
176
|
+
declare function useMeasuredSize<T extends HTMLElement>(deps?: ReadonlyArray<unknown>): readonly [(node: T | null) => void, {
|
|
177
|
+
width: number;
|
|
178
|
+
height: number;
|
|
179
|
+
}];
|
|
180
|
+
type UseFlowToolbarOptions = {
|
|
181
|
+
/**
|
|
182
|
+
* Which entities to anchor to. Defaults to the current selection — so one
|
|
183
|
+
* toolbar implementation covers nodes, edges, and multi-selections.
|
|
184
|
+
*/
|
|
185
|
+
ids?: string[];
|
|
186
|
+
/** Gap between the anchor and the toolbar (default 10). */
|
|
187
|
+
offset?: number;
|
|
188
|
+
/** Minimum gap from the container edges (default 8). */
|
|
189
|
+
padding?: number;
|
|
190
|
+
};
|
|
191
|
+
type FlowToolbarState = {
|
|
192
|
+
/** Attach to the toolbar element (measures it). */
|
|
193
|
+
setRef: (node: HTMLDivElement | null) => void;
|
|
194
|
+
/** Positioning style for the toolbar element. */
|
|
195
|
+
style: CSSProperties;
|
|
196
|
+
/** False when nothing is anchored (render nothing). */
|
|
197
|
+
visible: boolean;
|
|
198
|
+
/** The resolved screen-space anchor, when visible. */
|
|
199
|
+
anchor: Rect | null;
|
|
200
|
+
/** Which side of the anchor the toolbar sits on. */
|
|
201
|
+
side: "top" | "bottom";
|
|
202
|
+
};
|
|
203
|
+
declare function useFlowToolbar(options?: UseFlowToolbarOptions): FlowToolbarState;
|
|
204
|
+
type FlowToolbarProps = UseFlowToolbarOptions & {
|
|
205
|
+
children: ReactNode;
|
|
206
|
+
className?: string;
|
|
207
|
+
style?: CSSProperties;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Unstyled positioned toolbar anchored to the selection (or explicit `ids`).
|
|
211
|
+
* Marked `data-flow-interactive`, so its contents receive pointer events
|
|
212
|
+
* unopposed by canvas gestures.
|
|
213
|
+
*/
|
|
214
|
+
declare function FlowToolbar(props: FlowToolbarProps): react10.JSX.Element | null;
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/MiniMap.d.ts
|
|
217
|
+
type MiniMapProps = {
|
|
218
|
+
width?: number;
|
|
219
|
+
height?: number;
|
|
220
|
+
/** Padding around content as a fraction of its size (default 0.1). */
|
|
221
|
+
padding?: number;
|
|
222
|
+
className?: string;
|
|
223
|
+
style?: CSSProperties;
|
|
224
|
+
/** Render one node marker; defaults to a plain `<rect>`. */
|
|
225
|
+
renderNode?: (node: FlowNode, rect: Rect) => ReactNode;
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Overview map. Deliberately thin: all math lives in core
|
|
229
|
+
* (`getMinimapProjection`, `viewportCenteredOn`) and every interaction is a
|
|
230
|
+
* plain store trigger — this component is exactly what you would write in
|
|
231
|
+
* userland, kept here as a convenience.
|
|
232
|
+
*/
|
|
233
|
+
declare function MiniMap(props: MiniMapProps): react10.JSX.Element;
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/Controls.d.ts
|
|
236
|
+
type ControlsProps = {
|
|
237
|
+
className?: string;
|
|
238
|
+
style?: CSSProperties;
|
|
239
|
+
/** Extra buttons appended after the built-ins. */
|
|
240
|
+
children?: ReactNode;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Zoom/fit toolbar. Deliberately thin: every button is one store trigger
|
|
244
|
+
* (`zoomBy`, `fitView`) — replicate or extend it freely in userland.
|
|
245
|
+
*/
|
|
246
|
+
declare function Controls(props: ControlsProps): react10.JSX.Element;
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/EntityAnchor.d.ts
|
|
249
|
+
type EntityAnchorProps = {
|
|
250
|
+
bounds: Rect;
|
|
251
|
+
anchor: AnchorSpec;
|
|
252
|
+
inverseScale?: boolean;
|
|
253
|
+
className?: string;
|
|
254
|
+
style?: CSSProperties;
|
|
255
|
+
children: ReactNode;
|
|
256
|
+
};
|
|
257
|
+
declare function EntityAnchor(props: EntityAnchorProps): react10.JSX.Element;
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/Port.d.ts
|
|
260
|
+
type PortProps = {
|
|
261
|
+
name: string;
|
|
262
|
+
/**
|
|
263
|
+
* Whether the DOM element reports its bounds back to the graph (default
|
|
264
|
+
* true). Ports are unidirectional, one way or the other:
|
|
265
|
+
*
|
|
266
|
+
* - DOM-owned (default): position the element with your own CSS (offsets,
|
|
267
|
+
* percentages, flex…) — NEVER from `port.x`/`port.y` — and the graph's
|
|
268
|
+
* port geometry follows the DOM.
|
|
269
|
+
* - Graph-owned (`measured={false}`): position the element FROM
|
|
270
|
+
* `port.x`/`port.y` (layout results, "virtual" ports) and nothing is
|
|
271
|
+
* written back.
|
|
272
|
+
*
|
|
273
|
+
* Mixing the two (positioning from `port.x` while measuring) creates a
|
|
274
|
+
* feedback loop and runs away.
|
|
275
|
+
*/
|
|
276
|
+
measured?: boolean;
|
|
277
|
+
className?: string;
|
|
278
|
+
style?: CSSProperties;
|
|
279
|
+
children?: ReactNode;
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* A connection port. Purely declarative: it renders the
|
|
283
|
+
* `data-flow-port-name`/`data-flow-node-id` attributes that the input
|
|
284
|
+
* runtime's `connectMode` recognizes, and reports its measured bounds to the
|
|
285
|
+
* store. The connection gesture itself (start/move/validate/end) lives in
|
|
286
|
+
* core — customize it by swapping `connectMode({ isValid })` in the
|
|
287
|
+
* `inputModes` prop of `StatelyFlow` (or your own `useFlowInput` call), and
|
|
288
|
+
* observe results via `flow.on("connectionEnded", …)` or the store's
|
|
289
|
+
* `connection` state.
|
|
290
|
+
*/
|
|
291
|
+
declare function Port(props: PortProps): react10.JSX.Element;
|
|
292
|
+
//#endregion
|
|
293
|
+
//#region src/ColorMode.d.ts
|
|
294
|
+
type FlowColorModeScopeProps = {
|
|
295
|
+
children: ReactNode;
|
|
296
|
+
className?: string;
|
|
297
|
+
style?: CSSProperties;
|
|
298
|
+
};
|
|
299
|
+
declare function FlowColorModeScope(props: FlowColorModeScopeProps): react10.JSX.Element;
|
|
300
|
+
declare function useFlowColorMode(): {
|
|
301
|
+
colorMode: FlowColorMode;
|
|
302
|
+
resolvedColorMode: ResolvedFlowColorMode;
|
|
303
|
+
};
|
|
304
|
+
declare function useApplyFlowColorMode(element: HTMLElement | null): void;
|
|
305
|
+
//#endregion
|
|
306
|
+
export { Controls, type ControlsProps, type CreateFlowInstanceOptions, EntityAnchor, type EntityAnchorProps, FlowColorModeScope, type FlowColorModeScopeProps, type FlowEdgeBinding, type FlowEventListeners, type FlowInstance, FlowInstanceProvider, type FlowInstanceSettings, type FlowNodeBinding, type FlowPortBinding, type FlowSelector, type FlowSelectorEquality, type FlowStoreListener, FlowToolbar, type FlowToolbarProps, type FlowToolbarState, MiniMap, type MiniMapProps, Port, type PortProps, type RenderEdgeProps, type RenderNodeProps, StatelyFlow, type StatelyFlowProps, type UseCreateFlowInstanceOptions, type UseFlowInputOptions, type UseFlowOptions, type UseFlowToolbarOptions, createFlowInstance, useApplyFlowColorMode, useCreateFlowInstance, useFlow, useFlowColorMode, useFlowContext, useFlowEdge, useFlowEntity, useFlowInput, useFlowInstance, useFlowMeasurement, useFlowNode, useFlowPort, useFlowSelector, useFlowToolbar, useFlowValue, useFlowViewport, useMeasuredSize, useOptionalFlowInstance };
|