@particle-academy/fancy-flow 0.21.0 → 0.23.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/dist/{capabilities-DUhAc-EJ.d.ts → capabilities-85Mjn4uW.d.ts} +1 -1
- package/dist/{capabilities-ChE3Xi8R.d.cts → capabilities-exVeADXz.d.cts} +1 -1
- package/dist/{chunk-JE4ENQSE.js → chunk-AUL4LU63.js} +55 -7
- package/dist/chunk-AUL4LU63.js.map +1 -0
- package/dist/{chunk-L4AX73Q6.js → chunk-KDHLKBL2.js} +11 -5
- package/dist/chunk-KDHLKBL2.js.map +1 -0
- package/dist/{chunk-G3WHXMZ3.js → chunk-O7F6SGV4.js} +3 -3
- package/dist/{chunk-G3WHXMZ3.js.map → chunk-O7F6SGV4.js.map} +1 -1
- package/dist/{chunk-HMWYJIRP.js → chunk-OHVSEHDC.js} +3 -3
- package/dist/{chunk-HMWYJIRP.js.map → chunk-OHVSEHDC.js.map} +1 -1
- package/dist/{chunk-U5F22BHV.js → chunk-YXRLIV7A.js} +4 -2
- package/dist/chunk-YXRLIV7A.js.map +1 -0
- package/dist/engine.cjs +8 -2
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +3 -3
- package/dist/engine.d.ts +3 -3
- package/dist/engine.js +4 -4
- package/dist/index.cjs +5271 -3395
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -7
- package/dist/index.d.ts +32 -7
- package/dist/index.js +213 -107
- package/dist/index.js.map +1 -1
- package/dist/layout/index.d.cts +30 -0
- package/dist/layout/index.d.ts +30 -0
- package/dist/layout.cjs +1693 -0
- package/dist/layout.cjs.map +1 -0
- package/dist/layout.js +1691 -0
- package/dist/layout.js.map +1 -0
- package/dist/llm/vercel-ai.d.cts +2 -2
- package/dist/llm/vercel-ai.d.ts +2 -2
- package/dist/registry/index.d.cts +5 -5
- package/dist/registry/index.d.ts +5 -5
- package/dist/registry.cjs +59 -3
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +4 -4
- package/dist/{run-flow-ChBi6q-W.d.ts → run-flow-9U-gaYVF.d.ts} +1 -1
- package/dist/{run-flow-VKm57Hcj.d.cts → run-flow-AXzOR-Wq.d.cts} +1 -1
- package/dist/runtime/index.d.cts +3 -3
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime.cjs +8 -2
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +3 -3
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +2 -2
- package/dist/styles.css +41 -0
- package/dist/styles.css.map +1 -1
- package/dist/{types-VGkCXEO6.d.ts → types-CFEtuRWJ.d.ts} +11 -3
- package/dist/{types-sOmpCitB.d.cts → types-CMSrWVYM.d.cts} +1 -1
- package/dist/{types-sOmpCitB.d.ts → types-CMSrWVYM.d.ts} +1 -1
- package/dist/{types-LG-YckGh.d.cts → types-DneUoivl.d.cts} +11 -3
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.d.cts +3 -3
- package/dist/ux.d.ts +3 -3
- package/dist/ux.js +1 -1
- package/package.json +12 -1
- package/dist/chunk-JE4ENQSE.js.map +0 -1
- package/dist/chunk-L4AX73Q6.js.map +0 -1
- package/dist/chunk-U5F22BHV.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -3,17 +3,19 @@ import { ReactNode, CSSProperties, ComponentType } from 'react';
|
|
|
3
3
|
import { ReactFlowProps, Edge, BackgroundVariant, Connection, NodeProps, NodeTypes } from '@xyflow/react';
|
|
4
4
|
import { ConnectionValidatorOptions } from './registry/index.cjs';
|
|
5
5
|
export { ANY_PORT_TYPE, BUILTIN_KINDS, PortCompatibility, RegistryNode, RichInputAdapter, RichInputPreview, buildNodeTypes, categoryAccent, createConnectionValidator, defaultConfigFor, defaultPortCompatibility, getNodeKind, getRichInputAdapter, isRichInputEnabled, listNodeKinds, onNodeKindsChanged, onRichInputAdapterChanged, registerBuiltinKinds, registerNodeKind, registerRichInputAdapter, resolveNodePorts, resolvePortSpec, validateConfig } from './registry/index.cjs';
|
|
6
|
-
import {
|
|
7
|
-
export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData,
|
|
6
|
+
import { a as FlowNode, F as FlowGraph, e as NodeRunStatus, E as ExecutorRegistry } from './types-CMSrWVYM.cjs';
|
|
7
|
+
export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, b as FlowEdge, c as FlowNodeData, d as FlowNodeKind, N as NodeExecutor, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, R as RunEvent, S as SubgraphNodeData, T as TriggerNodeData } from './types-CMSrWVYM.cjs';
|
|
8
8
|
import { WorkflowSchema, WorkflowMetadata } from './schema/index.cjs';
|
|
9
9
|
export { ImportIssue, ImportOptions, ImportResult, WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, WorkflowSchemaEdge, WorkflowSchemaNode, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './schema/index.cjs';
|
|
10
|
-
import {
|
|
11
|
-
export {
|
|
10
|
+
import { AutoLayoutOptions } from './layout/index.cjs';
|
|
11
|
+
export { AutoLayoutDirection } from './layout/index.cjs';
|
|
12
|
+
import { N as NodeCategory, a as NodeKindDefinition, C as ConfigField } from './types-DneUoivl.cjs';
|
|
13
|
+
export { D as DocumentConfigField, K as KeyValueConfigField, P as PortSpec, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField } from './types-DneUoivl.cjs';
|
|
12
14
|
import { FlowRunFeedEntry } from './runtime/index.cjs';
|
|
13
15
|
export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.cjs';
|
|
14
|
-
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-
|
|
16
|
+
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-AXzOR-Wq.cjs';
|
|
15
17
|
export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, P as PauseAwaiting, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.cjs';
|
|
16
|
-
import './capabilities-
|
|
18
|
+
import './capabilities-exVeADXz.cjs';
|
|
17
19
|
|
|
18
20
|
type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" | "height"> & {
|
|
19
21
|
nodes: FlowNode[];
|
|
@@ -136,6 +138,16 @@ type FlowEditorApi = {
|
|
|
136
138
|
alignSelected: (edge: AlignEdge) => void;
|
|
137
139
|
/** Evenly distribute the multi-selection's gaps along an axis (needs 3+). */
|
|
138
140
|
distributeSelected: (axis: "h" | "v") => void;
|
|
141
|
+
/** Add a swimlane, stacked with existing lanes. Returns the new lane id. */
|
|
142
|
+
addLane: (orientation?: "horizontal" | "vertical", title?: string) => string | null;
|
|
143
|
+
/** Put a node inside a lane (sets parentId + a lane-relative position). */
|
|
144
|
+
assignToLane: (nodeId: string, laneId: string) => void;
|
|
145
|
+
/** Remove a node from its lane (restores its absolute position). */
|
|
146
|
+
removeFromLane: (nodeId: string) => void;
|
|
147
|
+
/** Auto-arrange the graph (or a lane's children) into a tidy DAG layout. */
|
|
148
|
+
autoLayout: (options?: AutoLayoutOptions) => void;
|
|
149
|
+
/** Tidy just one lane's children. */
|
|
150
|
+
tidyLane: (laneId: string) => void;
|
|
139
151
|
/** Copy the current selection to the editor clipboard. */
|
|
140
152
|
copy: () => void;
|
|
141
153
|
/** Copy then delete the current selection. */
|
|
@@ -192,6 +204,10 @@ type FlowEditorBuiltins = {
|
|
|
192
204
|
delete?: boolean;
|
|
193
205
|
/** Undo/redo toolbar buttons. Default true. */
|
|
194
206
|
history?: boolean;
|
|
207
|
+
/** "Add lane" toolbar button. Default true. */
|
|
208
|
+
addLane?: boolean;
|
|
209
|
+
/** "Tidy" (auto-layout) toolbar button. Default true. */
|
|
210
|
+
autoLayout?: boolean;
|
|
195
211
|
/** Right-click a node for Delete / Duplicate. Default true. */
|
|
196
212
|
contextMenu?: boolean;
|
|
197
213
|
/** Right-click a connection for Label / Delete. Default true. */
|
|
@@ -426,6 +442,15 @@ declare const NoteNode: react.MemoExoticComponent<typeof NoteNodeInner>;
|
|
|
426
442
|
declare function SubgraphNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
427
443
|
declare const SubgraphNode: react.MemoExoticComponent<typeof SubgraphNodeInner>;
|
|
428
444
|
|
|
445
|
+
/**
|
|
446
|
+
* LaneNode — a resizable swimlane band. A portless container: child nodes are
|
|
447
|
+
* parented into it (`parentId` + `extent:'parent'`) and render on top, so this
|
|
448
|
+
* node is just the titled background. Wired as the `@particle-academy/lane`
|
|
449
|
+
* kind's `component`, so `buildNodeTypes` uses it instead of the default card.
|
|
450
|
+
*/
|
|
451
|
+
declare function LaneNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
452
|
+
declare const LaneNode: react.MemoExoticComponent<typeof LaneNodeInner>;
|
|
453
|
+
|
|
429
454
|
type NodeShellProps = {
|
|
430
455
|
/** Required: the xyflow node this is rendering. */
|
|
431
456
|
node: NodeProps<FlowNode>;
|
|
@@ -522,4 +547,4 @@ type FlowRunFeedProps = {
|
|
|
522
547
|
/** FlowRunFeed — scrolling log panel. Auto-scrolls to bottom on new entries. */
|
|
523
548
|
declare function FlowRunFeed({ entries, className, style }: FlowRunFeedProps): react.JSX.Element;
|
|
524
549
|
|
|
525
|
-
export { ActionNode, type AlignEdge, ConfigField, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
|
|
550
|
+
export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigField, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,17 +3,19 @@ import { ReactNode, CSSProperties, ComponentType } from 'react';
|
|
|
3
3
|
import { ReactFlowProps, Edge, BackgroundVariant, Connection, NodeProps, NodeTypes } from '@xyflow/react';
|
|
4
4
|
import { ConnectionValidatorOptions } from './registry/index.js';
|
|
5
5
|
export { ANY_PORT_TYPE, BUILTIN_KINDS, PortCompatibility, RegistryNode, RichInputAdapter, RichInputPreview, buildNodeTypes, categoryAccent, createConnectionValidator, defaultConfigFor, defaultPortCompatibility, getNodeKind, getRichInputAdapter, isRichInputEnabled, listNodeKinds, onNodeKindsChanged, onRichInputAdapterChanged, registerBuiltinKinds, registerNodeKind, registerRichInputAdapter, resolveNodePorts, resolvePortSpec, validateConfig } from './registry/index.js';
|
|
6
|
-
import {
|
|
7
|
-
export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData,
|
|
6
|
+
import { a as FlowNode, F as FlowGraph, e as NodeRunStatus, E as ExecutorRegistry } from './types-CMSrWVYM.js';
|
|
7
|
+
export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, b as FlowEdge, c as FlowNodeData, d as FlowNodeKind, N as NodeExecutor, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, R as RunEvent, S as SubgraphNodeData, T as TriggerNodeData } from './types-CMSrWVYM.js';
|
|
8
8
|
import { WorkflowSchema, WorkflowMetadata } from './schema/index.js';
|
|
9
9
|
export { ImportIssue, ImportOptions, ImportResult, WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, WorkflowSchemaEdge, WorkflowSchemaNode, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './schema/index.js';
|
|
10
|
-
import {
|
|
11
|
-
export {
|
|
10
|
+
import { AutoLayoutOptions } from './layout/index.js';
|
|
11
|
+
export { AutoLayoutDirection } from './layout/index.js';
|
|
12
|
+
import { N as NodeCategory, a as NodeKindDefinition, C as ConfigField } from './types-CFEtuRWJ.js';
|
|
13
|
+
export { D as DocumentConfigField, K as KeyValueConfigField, P as PortSpec, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField } from './types-CFEtuRWJ.js';
|
|
12
14
|
import { FlowRunFeedEntry } from './runtime/index.js';
|
|
13
15
|
export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.js';
|
|
14
|
-
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-
|
|
16
|
+
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-9U-gaYVF.js';
|
|
15
17
|
export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, P as PauseAwaiting, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.js';
|
|
16
|
-
import './capabilities-
|
|
18
|
+
import './capabilities-85Mjn4uW.js';
|
|
17
19
|
|
|
18
20
|
type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" | "height"> & {
|
|
19
21
|
nodes: FlowNode[];
|
|
@@ -136,6 +138,16 @@ type FlowEditorApi = {
|
|
|
136
138
|
alignSelected: (edge: AlignEdge) => void;
|
|
137
139
|
/** Evenly distribute the multi-selection's gaps along an axis (needs 3+). */
|
|
138
140
|
distributeSelected: (axis: "h" | "v") => void;
|
|
141
|
+
/** Add a swimlane, stacked with existing lanes. Returns the new lane id. */
|
|
142
|
+
addLane: (orientation?: "horizontal" | "vertical", title?: string) => string | null;
|
|
143
|
+
/** Put a node inside a lane (sets parentId + a lane-relative position). */
|
|
144
|
+
assignToLane: (nodeId: string, laneId: string) => void;
|
|
145
|
+
/** Remove a node from its lane (restores its absolute position). */
|
|
146
|
+
removeFromLane: (nodeId: string) => void;
|
|
147
|
+
/** Auto-arrange the graph (or a lane's children) into a tidy DAG layout. */
|
|
148
|
+
autoLayout: (options?: AutoLayoutOptions) => void;
|
|
149
|
+
/** Tidy just one lane's children. */
|
|
150
|
+
tidyLane: (laneId: string) => void;
|
|
139
151
|
/** Copy the current selection to the editor clipboard. */
|
|
140
152
|
copy: () => void;
|
|
141
153
|
/** Copy then delete the current selection. */
|
|
@@ -192,6 +204,10 @@ type FlowEditorBuiltins = {
|
|
|
192
204
|
delete?: boolean;
|
|
193
205
|
/** Undo/redo toolbar buttons. Default true. */
|
|
194
206
|
history?: boolean;
|
|
207
|
+
/** "Add lane" toolbar button. Default true. */
|
|
208
|
+
addLane?: boolean;
|
|
209
|
+
/** "Tidy" (auto-layout) toolbar button. Default true. */
|
|
210
|
+
autoLayout?: boolean;
|
|
195
211
|
/** Right-click a node for Delete / Duplicate. Default true. */
|
|
196
212
|
contextMenu?: boolean;
|
|
197
213
|
/** Right-click a connection for Label / Delete. Default true. */
|
|
@@ -426,6 +442,15 @@ declare const NoteNode: react.MemoExoticComponent<typeof NoteNodeInner>;
|
|
|
426
442
|
declare function SubgraphNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
427
443
|
declare const SubgraphNode: react.MemoExoticComponent<typeof SubgraphNodeInner>;
|
|
428
444
|
|
|
445
|
+
/**
|
|
446
|
+
* LaneNode — a resizable swimlane band. A portless container: child nodes are
|
|
447
|
+
* parented into it (`parentId` + `extent:'parent'`) and render on top, so this
|
|
448
|
+
* node is just the titled background. Wired as the `@particle-academy/lane`
|
|
449
|
+
* kind's `component`, so `buildNodeTypes` uses it instead of the default card.
|
|
450
|
+
*/
|
|
451
|
+
declare function LaneNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
452
|
+
declare const LaneNode: react.MemoExoticComponent<typeof LaneNodeInner>;
|
|
453
|
+
|
|
429
454
|
type NodeShellProps = {
|
|
430
455
|
/** Required: the xyflow node this is rendering. */
|
|
431
456
|
node: NodeProps<FlowNode>;
|
|
@@ -522,4 +547,4 @@ type FlowRunFeedProps = {
|
|
|
522
547
|
/** FlowRunFeed — scrolling log panel. Auto-scrolls to bottom on new entries. */
|
|
523
548
|
declare function FlowRunFeed({ entries, className, style }: FlowRunFeedProps): react.JSX.Element;
|
|
524
549
|
|
|
525
|
-
export { ActionNode, type AlignEdge, ConfigField, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
|
|
550
|
+
export { ActionNode, type AlignEdge, AutoLayoutOptions, ConfigField, ConfigFieldRenderer, type ConfigFieldRendererProps, ConnectionValidatorOptions, DecisionNode, ExecutorRegistry, FlowCanvas, type FlowCanvasProps, FlowEditor, type FlowEditorAction, type FlowEditorApi, type FlowEditorBuiltins, type FlowEditorProps, type FlowEditorSlots, FlowGraph, FlowNode, type FlowNodeRenderProps, FlowRunControls, type FlowRunControlsProps, FlowRunFeed, FlowRunFeedEntry, type FlowRunFeedProps, LaneNode, NodeCategory, NodeConfigPanel, type NodeConfigPanelProps, NodeKindDefinition, NodePalette, type NodePaletteProps, NodePort, type NodePortProps, type NodePortSide, type NodePortType, NodeRunStatus, NodeShell, type NodeShellProps, NoteNode, OutputNode, SubgraphNode, TriggerNode, WorkflowMetadata, WorkflowSchema, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, paletteDropHandlers, reconnectEdge, useFlowEditor, useFlowEditorOptional };
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { useFlowState, useFlowRun, useFlowHistory, applyStatusesToNodes } from './chunk-
|
|
2
|
-
export { applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './chunk-
|
|
3
|
-
import { buildNodeTypes, registerBuiltinKinds, createConnectionValidator } from './chunk-
|
|
4
|
-
export { ANY_PORT_TYPE, BUILTIN_KINDS, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds } from './chunk-
|
|
1
|
+
import { useFlowState, useFlowRun, useFlowHistory, applyStatusesToNodes } from './chunk-O7F6SGV4.js';
|
|
2
|
+
export { applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './chunk-O7F6SGV4.js';
|
|
3
|
+
import { buildNodeTypes, registerBuiltinKinds, createConnectionValidator } from './chunk-AUL4LU63.js';
|
|
4
|
+
export { ANY_PORT_TYPE, BUILTIN_KINDS, LaneNode, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds } from './chunk-AUL4LU63.js';
|
|
5
5
|
import { ReactFlowProvider, useReactFlow, addEdge, applyEdgeChanges, applyNodeChanges, Position, Handle, reconnectEdge, index, BackgroundVariant, Background, Controls, MiniMap } from './chunk-ZB4HHQMR.js';
|
|
6
6
|
export { LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, decodePause, encodePause, isPause, pauseForHuman } from './chunk-UEOE6B52.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import './chunk-USL4FMFU.js';
|
|
8
|
+
export { runFlow } from './chunk-KDHLKBL2.js';
|
|
9
|
+
import { workflowToBlob, importWorkflow, exportWorkflow } from './chunk-OHVSEHDC.js';
|
|
10
|
+
export { WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './chunk-OHVSEHDC.js';
|
|
10
11
|
export { resolveNodePorts, resolvePortSpec } from './chunk-TITD5W4Y.js';
|
|
11
|
-
import { onNodeKindsChanged, listNodeKinds, getNodeKind, defaultConfigFor, validateConfig, categoryAccent } from './chunk-
|
|
12
|
-
export { categoryAccent, defaultConfigFor, getNodeKind, listNodeKinds, onNodeKindsChanged, registerNodeKind, validateConfig } from './chunk-
|
|
12
|
+
import { onNodeKindsChanged, listNodeKinds, getNodeKind, defaultConfigFor, validateConfig, categoryAccent } from './chunk-YXRLIV7A.js';
|
|
13
|
+
export { categoryAccent, defaultConfigFor, getNodeKind, listNodeKinds, onNodeKindsChanged, registerNodeKind, validateConfig } from './chunk-YXRLIV7A.js';
|
|
13
14
|
import { getRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
14
15
|
export { RichInputPreview, getRichInputAdapter, isRichInputEnabled, onRichInputAdapterChanged, registerRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
15
|
-
import './chunk-USL4FMFU.js';
|
|
16
16
|
import { memo, createContext, forwardRef, useState, useEffect, useMemo, useCallback, useRef, useImperativeHandle, useContext } from 'react';
|
|
17
17
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
18
18
|
|
|
@@ -139,6 +139,140 @@ var defaultNodeTypes = {
|
|
|
139
139
|
note: NoteNode,
|
|
140
140
|
subgraph: SubgraphNode
|
|
141
141
|
};
|
|
142
|
+
|
|
143
|
+
// src/components/FlowEditor/graph-ops.ts
|
|
144
|
+
function removeNodes(graph, ids) {
|
|
145
|
+
if (ids.length === 0) return graph;
|
|
146
|
+
const doomed = new Set(ids);
|
|
147
|
+
return {
|
|
148
|
+
nodes: graph.nodes.filter((n) => !doomed.has(n.id)),
|
|
149
|
+
edges: graph.edges.filter((e) => !doomed.has(e.source) && !doomed.has(e.target))
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function removeEdges(edges, ids) {
|
|
153
|
+
if (ids.length === 0) return edges;
|
|
154
|
+
const doomed = new Set(ids);
|
|
155
|
+
return edges.filter((e) => !doomed.has(e.id));
|
|
156
|
+
}
|
|
157
|
+
function setEdgeLabel(edges, id, label) {
|
|
158
|
+
const next = label?.trim();
|
|
159
|
+
return edges.map((e) => {
|
|
160
|
+
if (e.id !== id) return e;
|
|
161
|
+
if (!next) {
|
|
162
|
+
const { label: _drop, ...rest } = e;
|
|
163
|
+
return rest;
|
|
164
|
+
}
|
|
165
|
+
return { ...e, label: next };
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function duplicateNode(node, id, offset = 40) {
|
|
169
|
+
return {
|
|
170
|
+
...node,
|
|
171
|
+
id,
|
|
172
|
+
position: { x: node.position.x + offset, y: node.position.y + offset },
|
|
173
|
+
// Deep copy so the clone's config edits don't mutate the original.
|
|
174
|
+
data: JSON.parse(JSON.stringify(node.data ?? {}))
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function cloneSubgraph(nodes, edges, opts) {
|
|
178
|
+
const offset = opts.offset ?? 40;
|
|
179
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
180
|
+
for (const n of nodes) idMap.set(n.id, opts.makeId());
|
|
181
|
+
const clonedNodes = nodes.map((n) => {
|
|
182
|
+
const cloned = duplicateNode(n, idMap.get(n.id), offset);
|
|
183
|
+
const parentId = n.parentId;
|
|
184
|
+
if (parentId && idMap.has(parentId)) cloned.parentId = idMap.get(parentId);
|
|
185
|
+
else if (parentId) delete cloned.parentId;
|
|
186
|
+
return cloned;
|
|
187
|
+
});
|
|
188
|
+
const clonedEdges = edges.filter((e) => idMap.has(e.source) && idMap.has(e.target)).map((e) => ({ ...e, id: opts.makeId(), source: idMap.get(e.source), target: idMap.get(e.target) }));
|
|
189
|
+
return { nodes: clonedNodes, edges: clonedEdges, idMap };
|
|
190
|
+
}
|
|
191
|
+
function reconnectEdge2(edges, oldEdge, newConnection) {
|
|
192
|
+
return reconnectEdge(oldEdge, newConnection, edges, { shouldReplaceId: false });
|
|
193
|
+
}
|
|
194
|
+
var nodeW = (n) => n.width ?? n.measured?.width ?? 0;
|
|
195
|
+
var nodeH = (n) => n.height ?? n.measured?.height ?? 0;
|
|
196
|
+
function alignNodes(nodes, edge) {
|
|
197
|
+
if (nodes.length < 2) return nodes;
|
|
198
|
+
const minL = Math.min(...nodes.map((n) => n.position.x));
|
|
199
|
+
const maxR = Math.max(...nodes.map((n) => n.position.x + nodeW(n)));
|
|
200
|
+
const minT = Math.min(...nodes.map((n) => n.position.y));
|
|
201
|
+
const maxB = Math.max(...nodes.map((n) => n.position.y + nodeH(n)));
|
|
202
|
+
const cx = (minL + maxR) / 2;
|
|
203
|
+
const cy = (minT + maxB) / 2;
|
|
204
|
+
return nodes.map((n) => {
|
|
205
|
+
let { x, y } = n.position;
|
|
206
|
+
if (edge === "left") x = minL;
|
|
207
|
+
else if (edge === "right") x = maxR - nodeW(n);
|
|
208
|
+
else if (edge === "hcenter") x = cx - nodeW(n) / 2;
|
|
209
|
+
else if (edge === "top") y = minT;
|
|
210
|
+
else if (edge === "bottom") y = maxB - nodeH(n);
|
|
211
|
+
else if (edge === "vcenter") y = cy - nodeH(n) / 2;
|
|
212
|
+
return { ...n, position: { x, y } };
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function sortNodesParentFirst(nodes) {
|
|
216
|
+
const byId = new Map(nodes.map((n) => [n.id, n]));
|
|
217
|
+
const seen = /* @__PURE__ */ new Set();
|
|
218
|
+
const out = [];
|
|
219
|
+
const visit = (n) => {
|
|
220
|
+
if (seen.has(n.id)) return;
|
|
221
|
+
const pid = n.parentId;
|
|
222
|
+
if (pid && byId.has(pid) && !seen.has(pid)) visit(byId.get(pid));
|
|
223
|
+
seen.add(n.id);
|
|
224
|
+
out.push(n);
|
|
225
|
+
};
|
|
226
|
+
for (const n of nodes) visit(n);
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
229
|
+
function absolutePosition(node, nodes) {
|
|
230
|
+
const pid = node.parentId;
|
|
231
|
+
if (!pid) return node.position;
|
|
232
|
+
const parent = nodes.find((n) => n.id === pid);
|
|
233
|
+
return parent ? { x: node.position.x + parent.position.x, y: node.position.y + parent.position.y } : node.position;
|
|
234
|
+
}
|
|
235
|
+
function assignToLane(nodes, nodeId, laneId) {
|
|
236
|
+
if (nodeId === laneId) return nodes;
|
|
237
|
+
const node = nodes.find((n) => n.id === nodeId);
|
|
238
|
+
const lane = nodes.find((n) => n.id === laneId);
|
|
239
|
+
if (!node || !lane) return nodes;
|
|
240
|
+
const abs = absolutePosition(node, nodes);
|
|
241
|
+
const laneAbs = absolutePosition(lane, nodes);
|
|
242
|
+
const rel = { x: abs.x - laneAbs.x, y: abs.y - laneAbs.y };
|
|
243
|
+
return nodes.map((n) => n.id === nodeId ? { ...n, parentId: laneId, extent: "parent", position: rel } : n);
|
|
244
|
+
}
|
|
245
|
+
function removeFromLane(nodes, nodeId) {
|
|
246
|
+
const node = nodes.find((n) => n.id === nodeId);
|
|
247
|
+
if (!node || !node.parentId) return nodes;
|
|
248
|
+
const abs = absolutePosition(node, nodes);
|
|
249
|
+
return nodes.map((n) => {
|
|
250
|
+
if (n.id !== nodeId) return n;
|
|
251
|
+
const { parentId: _p, extent: _e, ...rest } = n;
|
|
252
|
+
return { ...rest, position: abs };
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function distributeNodes(nodes, axis) {
|
|
256
|
+
if (nodes.length < 3) return nodes;
|
|
257
|
+
const size = (n) => axis === "h" ? nodeW(n) : nodeH(n);
|
|
258
|
+
const coord = (n) => axis === "h" ? n.position.x : n.position.y;
|
|
259
|
+
const sorted = [...nodes].sort((a, b) => coord(a) - coord(b));
|
|
260
|
+
const start = coord(sorted[0]);
|
|
261
|
+
const last = sorted[sorted.length - 1];
|
|
262
|
+
const end = coord(last) + size(last);
|
|
263
|
+
const totalSize = sorted.reduce((s, n) => s + size(n), 0);
|
|
264
|
+
const gap = (end - start - totalSize) / (sorted.length - 1);
|
|
265
|
+
const posById = /* @__PURE__ */ new Map();
|
|
266
|
+
let cursor = start;
|
|
267
|
+
for (const n of sorted) {
|
|
268
|
+
posById.set(n.id, cursor);
|
|
269
|
+
cursor += size(n) + gap;
|
|
270
|
+
}
|
|
271
|
+
return nodes.map((n) => {
|
|
272
|
+
const p = posById.get(n.id);
|
|
273
|
+
return { ...n, position: axis === "h" ? { ...n.position, x: p } : { ...n.position, y: p } };
|
|
274
|
+
});
|
|
275
|
+
}
|
|
142
276
|
var DEFAULT_FIT_VIEW = { padding: 0.2 };
|
|
143
277
|
var DEFAULT_EDGE_OPTIONS = {
|
|
144
278
|
type: "smoothstep",
|
|
@@ -178,12 +312,13 @@ function FlowCanvas({
|
|
|
178
312
|
() => edgeTypes ? { ...edgeTypes } : void 0,
|
|
179
313
|
[edgeTypes]
|
|
180
314
|
);
|
|
315
|
+
const orderedNodes = useMemo(() => sortNodesParentFirst(nodes), [nodes]);
|
|
181
316
|
return /* @__PURE__ */ jsxs("div", { className: ["ff-canvas", className ?? ""].filter(Boolean).join(" "), style: { height, ...style }, children: [
|
|
182
317
|
toolbar && /* @__PURE__ */ jsx("div", { className: "ff-canvas__toolbar", children: toolbar }),
|
|
183
318
|
/* @__PURE__ */ jsx("div", { className: "ff-canvas__surface", children: /* @__PURE__ */ jsxs(
|
|
184
319
|
index,
|
|
185
320
|
{
|
|
186
|
-
nodes,
|
|
321
|
+
nodes: orderedNodes,
|
|
187
322
|
edges,
|
|
188
323
|
nodeTypes: mergedNodeTypes,
|
|
189
324
|
edgeTypes: mergedEdgeTypes,
|
|
@@ -204,7 +339,7 @@ function FlowCanvas({
|
|
|
204
339
|
) })
|
|
205
340
|
] });
|
|
206
341
|
}
|
|
207
|
-
var CATEGORY_ORDER = ["trigger", "logic", "data", "ai", "io", "human", "output", "custom"];
|
|
342
|
+
var CATEGORY_ORDER = ["trigger", "logic", "data", "ai", "io", "human", "output", "layout", "custom"];
|
|
208
343
|
var CATEGORY_LABELS = {
|
|
209
344
|
trigger: "Triggers",
|
|
210
345
|
logic: "Logic",
|
|
@@ -213,6 +348,7 @@ var CATEGORY_LABELS = {
|
|
|
213
348
|
io: "Connectors",
|
|
214
349
|
human: "Human",
|
|
215
350
|
output: "Output",
|
|
351
|
+
layout: "Layout",
|
|
216
352
|
custom: "Custom"
|
|
217
353
|
};
|
|
218
354
|
function NodePalette({ categories, onPick, className, style }) {
|
|
@@ -804,100 +940,6 @@ function formatTime(at) {
|
|
|
804
940
|
const d = new Date(at);
|
|
805
941
|
return `${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}.${Math.floor(d.getMilliseconds() / 100)}`;
|
|
806
942
|
}
|
|
807
|
-
|
|
808
|
-
// src/components/FlowEditor/graph-ops.ts
|
|
809
|
-
function removeNodes(graph, ids) {
|
|
810
|
-
if (ids.length === 0) return graph;
|
|
811
|
-
const doomed = new Set(ids);
|
|
812
|
-
return {
|
|
813
|
-
nodes: graph.nodes.filter((n) => !doomed.has(n.id)),
|
|
814
|
-
edges: graph.edges.filter((e) => !doomed.has(e.source) && !doomed.has(e.target))
|
|
815
|
-
};
|
|
816
|
-
}
|
|
817
|
-
function removeEdges(edges, ids) {
|
|
818
|
-
if (ids.length === 0) return edges;
|
|
819
|
-
const doomed = new Set(ids);
|
|
820
|
-
return edges.filter((e) => !doomed.has(e.id));
|
|
821
|
-
}
|
|
822
|
-
function setEdgeLabel(edges, id, label) {
|
|
823
|
-
const next = label?.trim();
|
|
824
|
-
return edges.map((e) => {
|
|
825
|
-
if (e.id !== id) return e;
|
|
826
|
-
if (!next) {
|
|
827
|
-
const { label: _drop, ...rest } = e;
|
|
828
|
-
return rest;
|
|
829
|
-
}
|
|
830
|
-
return { ...e, label: next };
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
function duplicateNode(node, id, offset = 40) {
|
|
834
|
-
return {
|
|
835
|
-
...node,
|
|
836
|
-
id,
|
|
837
|
-
position: { x: node.position.x + offset, y: node.position.y + offset },
|
|
838
|
-
// Deep copy so the clone's config edits don't mutate the original.
|
|
839
|
-
data: JSON.parse(JSON.stringify(node.data ?? {}))
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
function cloneSubgraph(nodes, edges, opts) {
|
|
843
|
-
const offset = opts.offset ?? 40;
|
|
844
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
845
|
-
for (const n of nodes) idMap.set(n.id, opts.makeId());
|
|
846
|
-
const clonedNodes = nodes.map((n) => {
|
|
847
|
-
const cloned = duplicateNode(n, idMap.get(n.id), offset);
|
|
848
|
-
const parentId = n.parentId;
|
|
849
|
-
if (parentId && idMap.has(parentId)) cloned.parentId = idMap.get(parentId);
|
|
850
|
-
else if (parentId) delete cloned.parentId;
|
|
851
|
-
return cloned;
|
|
852
|
-
});
|
|
853
|
-
const clonedEdges = edges.filter((e) => idMap.has(e.source) && idMap.has(e.target)).map((e) => ({ ...e, id: opts.makeId(), source: idMap.get(e.source), target: idMap.get(e.target) }));
|
|
854
|
-
return { nodes: clonedNodes, edges: clonedEdges, idMap };
|
|
855
|
-
}
|
|
856
|
-
function reconnectEdge2(edges, oldEdge, newConnection) {
|
|
857
|
-
return reconnectEdge(oldEdge, newConnection, edges, { shouldReplaceId: false });
|
|
858
|
-
}
|
|
859
|
-
var nodeW = (n) => n.width ?? n.measured?.width ?? 0;
|
|
860
|
-
var nodeH = (n) => n.height ?? n.measured?.height ?? 0;
|
|
861
|
-
function alignNodes(nodes, edge) {
|
|
862
|
-
if (nodes.length < 2) return nodes;
|
|
863
|
-
const minL = Math.min(...nodes.map((n) => n.position.x));
|
|
864
|
-
const maxR = Math.max(...nodes.map((n) => n.position.x + nodeW(n)));
|
|
865
|
-
const minT = Math.min(...nodes.map((n) => n.position.y));
|
|
866
|
-
const maxB = Math.max(...nodes.map((n) => n.position.y + nodeH(n)));
|
|
867
|
-
const cx = (minL + maxR) / 2;
|
|
868
|
-
const cy = (minT + maxB) / 2;
|
|
869
|
-
return nodes.map((n) => {
|
|
870
|
-
let { x, y } = n.position;
|
|
871
|
-
if (edge === "left") x = minL;
|
|
872
|
-
else if (edge === "right") x = maxR - nodeW(n);
|
|
873
|
-
else if (edge === "hcenter") x = cx - nodeW(n) / 2;
|
|
874
|
-
else if (edge === "top") y = minT;
|
|
875
|
-
else if (edge === "bottom") y = maxB - nodeH(n);
|
|
876
|
-
else if (edge === "vcenter") y = cy - nodeH(n) / 2;
|
|
877
|
-
return { ...n, position: { x, y } };
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
function distributeNodes(nodes, axis) {
|
|
881
|
-
if (nodes.length < 3) return nodes;
|
|
882
|
-
const size = (n) => axis === "h" ? nodeW(n) : nodeH(n);
|
|
883
|
-
const coord = (n) => axis === "h" ? n.position.x : n.position.y;
|
|
884
|
-
const sorted = [...nodes].sort((a, b) => coord(a) - coord(b));
|
|
885
|
-
const start = coord(sorted[0]);
|
|
886
|
-
const last = sorted[sorted.length - 1];
|
|
887
|
-
const end = coord(last) + size(last);
|
|
888
|
-
const totalSize = sorted.reduce((s, n) => s + size(n), 0);
|
|
889
|
-
const gap = (end - start - totalSize) / (sorted.length - 1);
|
|
890
|
-
const posById = /* @__PURE__ */ new Map();
|
|
891
|
-
let cursor = start;
|
|
892
|
-
for (const n of sorted) {
|
|
893
|
-
posById.set(n.id, cursor);
|
|
894
|
-
cursor += size(n) + gap;
|
|
895
|
-
}
|
|
896
|
-
return nodes.map((n) => {
|
|
897
|
-
const p = posById.get(n.id);
|
|
898
|
-
return { ...n, position: axis === "h" ? { ...n.position, x: p } : { ...n.position, y: p } };
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
943
|
var FlowEditorContext = createContext(null);
|
|
902
944
|
var FlowEditorProvider = FlowEditorContext.Provider;
|
|
903
945
|
function useFlowEditor() {
|
|
@@ -1128,6 +1170,49 @@ function FlowEditorInner({
|
|
|
1128
1170
|
(oldEdge, conn) => flow.setEdges((eds) => reconnectEdge2(eds, oldEdge, conn)),
|
|
1129
1171
|
[flow]
|
|
1130
1172
|
);
|
|
1173
|
+
const isLaneNode = useCallback(
|
|
1174
|
+
(n) => getNodeKind(n.data?.kind ?? n.type)?.category === "layout",
|
|
1175
|
+
[]
|
|
1176
|
+
);
|
|
1177
|
+
const addLane = useCallback(
|
|
1178
|
+
(orientation = "horizontal", title) => {
|
|
1179
|
+
const vertical = orientation === "vertical";
|
|
1180
|
+
const lanes = flow.nodes.filter(isLaneNode);
|
|
1181
|
+
const w = vertical ? 280 : 680;
|
|
1182
|
+
const h = vertical ? 480 : 168;
|
|
1183
|
+
const end = lanes.reduce(
|
|
1184
|
+
(m, l) => Math.max(m, vertical ? l.position.x + (l.width ?? w) : l.position.y + (l.height ?? h)),
|
|
1185
|
+
0
|
|
1186
|
+
);
|
|
1187
|
+
const id = newNodeId();
|
|
1188
|
+
const name = title ?? `Lane ${lanes.length + 1}`;
|
|
1189
|
+
const node = {
|
|
1190
|
+
id,
|
|
1191
|
+
type: "@particle-academy/lane",
|
|
1192
|
+
position: vertical ? { x: lanes.length ? end + 12 : 0, y: 0 } : { x: 0, y: lanes.length ? end + 12 : 0 },
|
|
1193
|
+
width: w,
|
|
1194
|
+
height: h,
|
|
1195
|
+
data: { kind: "@particle-academy/lane", label: name, config: { title: name, orientation } }
|
|
1196
|
+
};
|
|
1197
|
+
flow.setNodes((all) => [...all, node]);
|
|
1198
|
+
setSelectedId(id);
|
|
1199
|
+
return id;
|
|
1200
|
+
},
|
|
1201
|
+
[flow, isLaneNode]
|
|
1202
|
+
);
|
|
1203
|
+
const handleNodeDragStop = useCallback(
|
|
1204
|
+
(_e, node) => {
|
|
1205
|
+
if (isLaneNode(node)) return;
|
|
1206
|
+
const overLane = rf.getIntersectingNodes(node).find((n) => isLaneNode(n));
|
|
1207
|
+
const currentParent = node.parentId;
|
|
1208
|
+
if (overLane && overLane.id !== currentParent) {
|
|
1209
|
+
flow.setNodes((all) => assignToLane(all, node.id, overLane.id));
|
|
1210
|
+
} else if (!overLane && currentParent) {
|
|
1211
|
+
flow.setNodes((all) => removeFromLane(all, node.id));
|
|
1212
|
+
}
|
|
1213
|
+
},
|
|
1214
|
+
[rf, flow, isLaneNode]
|
|
1215
|
+
);
|
|
1131
1216
|
useEffect(() => {
|
|
1132
1217
|
const onKey = (e) => {
|
|
1133
1218
|
const t = e.target;
|
|
@@ -1191,6 +1276,21 @@ function FlowEditorInner({
|
|
|
1191
1276
|
deleteNodes(selectedIds);
|
|
1192
1277
|
},
|
|
1193
1278
|
paste: pasteClipboard,
|
|
1279
|
+
addLane,
|
|
1280
|
+
assignToLane: (nodeId, laneId) => flow.setNodes((all) => assignToLane(all, nodeId, laneId)),
|
|
1281
|
+
removeFromLane: (nodeId) => flow.setNodes((all) => removeFromLane(all, nodeId)),
|
|
1282
|
+
// dagre is loaded lazily so it stays out of the eager bundle — consumers
|
|
1283
|
+
// who never tidy pay nothing for it.
|
|
1284
|
+
autoLayout: (opts) => {
|
|
1285
|
+
void import('./layout.js').then(
|
|
1286
|
+
({ autoLayout }) => flow.setGraph({ nodes: autoLayout({ nodes: flow.nodes, edges: flow.edges }, opts), edges: flow.edges })
|
|
1287
|
+
);
|
|
1288
|
+
},
|
|
1289
|
+
tidyLane: (laneId) => {
|
|
1290
|
+
void import('./layout.js').then(
|
|
1291
|
+
({ autoLayout }) => flow.setGraph({ nodes: autoLayout({ nodes: flow.nodes, edges: flow.edges }, { scope: laneId }), edges: flow.edges })
|
|
1292
|
+
);
|
|
1293
|
+
},
|
|
1194
1294
|
run: () => runner.run({ nodes: flow.nodes, edges: flow.edges }, executors),
|
|
1195
1295
|
cancel: runner.cancel,
|
|
1196
1296
|
reset: runner.reset,
|
|
@@ -1203,7 +1303,7 @@ function FlowEditorInner({
|
|
|
1203
1303
|
canUndo: hist.canUndo,
|
|
1204
1304
|
canRedo: hist.canRedo
|
|
1205
1305
|
};
|
|
1206
|
-
}, [flow, selectedId, selected, selectedEdgeId, selectedEdge, selectedIds, selectedNodes, runner, executors, metadata, addNode, deleteNodes, deleteEdges, duplicateSelected, alignSelected, distributeSelected, copySelection, pasteClipboard, hist, rf]);
|
|
1306
|
+
}, [flow, selectedId, selected, selectedEdgeId, selectedEdge, selectedIds, selectedNodes, runner, executors, metadata, addNode, deleteNodes, deleteEdges, duplicateSelected, alignSelected, distributeSelected, copySelection, pasteClipboard, addLane, hist, rf]);
|
|
1207
1307
|
useImperativeHandle(apiRef, () => api, [api]);
|
|
1208
1308
|
const dropHandlers = paletteDropHandlers((kindName, evt) => {
|
|
1209
1309
|
const point = rf.screenToFlowPosition({ x: evt.clientX, y: evt.clientY });
|
|
@@ -1239,6 +1339,11 @@ function FlowEditorInner({
|
|
|
1239
1339
|
}
|
|
1240
1340
|
)
|
|
1241
1341
|
] }),
|
|
1342
|
+
builtins.addLane !== false && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1343
|
+
/* @__PURE__ */ jsx("span", { className: "ff-editor__sep" }),
|
|
1344
|
+
/* @__PURE__ */ jsx("button", { className: "ff-editor__btn", "data-action": "add-lane", title: "Add a swimlane", onClick: () => api.addLane(), children: "\u25A4 Lane" })
|
|
1345
|
+
] }),
|
|
1346
|
+
builtins.autoLayout !== false && /* @__PURE__ */ jsx("button", { className: "ff-editor__btn", "data-action": "auto-layout", title: "Tidy \u2014 auto-arrange", onClick: () => api.autoLayout(), children: "\u2922 Tidy" }),
|
|
1242
1347
|
(builtins.export !== false || builtins.import !== false) && /* @__PURE__ */ jsx("span", { className: "ff-editor__sep" }),
|
|
1243
1348
|
builtins.export !== false && /* @__PURE__ */ jsx("button", { className: "ff-editor__btn", "data-action": "export", onClick: api.exportWorkflow, children: "\u2193 Export" }),
|
|
1244
1349
|
builtins.import !== false && /* @__PURE__ */ jsx("button", { className: "ff-editor__btn", "data-action": "import", onClick: api.importWorkflow, children: "\u2191 Import" }),
|
|
@@ -1266,6 +1371,7 @@ function FlowEditorInner({
|
|
|
1266
1371
|
onReconnect,
|
|
1267
1372
|
edgesReconnectable: true,
|
|
1268
1373
|
onNodeDragStart: hist.onNodeDragStart,
|
|
1374
|
+
onNodeDragStop: handleNodeDragStop,
|
|
1269
1375
|
onNodeClick: handleNodeClick,
|
|
1270
1376
|
onNodeContextMenu: builtins.contextMenu === false ? void 0 : handleNodeContextMenu,
|
|
1271
1377
|
onEdgeClick: handleEdgeClick,
|