@particle-academy/fancy-flow 0.23.0 → 0.25.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/{chunk-AUL4LU63.js → chunk-ATQXZEVD.js} +122 -7
- package/dist/chunk-ATQXZEVD.js.map +1 -0
- package/dist/{chunk-OHVSEHDC.js → chunk-N5ICD2WZ.js} +3 -3
- package/dist/{chunk-OHVSEHDC.js.map → chunk-N5ICD2WZ.js.map} +1 -1
- package/dist/{chunk-O7F6SGV4.js → chunk-OFW7GN3Y.js} +18 -6
- package/dist/chunk-OFW7GN3Y.js.map +1 -0
- package/dist/{chunk-ZB4HHQMR.js → chunk-OWENS2H5.js} +11 -3
- package/dist/chunk-OWENS2H5.js.map +1 -0
- package/dist/{chunk-YXRLIV7A.js → chunk-Q6IPK64P.js} +4 -2
- package/dist/chunk-Q6IPK64P.js.map +1 -0
- package/dist/{chunk-KDHLKBL2.js → chunk-U2VJB7HR.js} +7 -5
- package/dist/chunk-U2VJB7HR.js.map +1 -0
- package/dist/engine.cjs +4 -2
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.js +3 -3
- package/dist/index.cjs +382 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -10
- package/dist/index.d.ts +7 -10
- package/dist/index.js +177 -64
- package/dist/index.js.map +1 -1
- package/dist/registry/index.d.cts +2 -2
- package/dist/registry/index.d.ts +2 -2
- package/dist/registry.cjs +114 -2
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +4 -4
- package/dist/runtime/index.d.cts +13 -1
- package/dist/runtime/index.d.ts +13 -1
- package/dist/runtime.cjs +17 -3
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +4 -4
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +2 -2
- package/dist/styles.css +80 -0
- package/dist/styles.css.map +1 -1
- package/dist/{types-CFEtuRWJ.d.ts → types-BGtR3k9J.d.ts} +8 -1
- package/dist/{types-DneUoivl.d.cts → types-B_pxRqfw.d.cts} +8 -1
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.d.cts +1 -1
- package/dist/ux.d.ts +1 -1
- package/dist/ux.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-AUL4LU63.js.map +0 -1
- package/dist/chunk-KDHLKBL2.js.map +0 -1
- package/dist/chunk-O7F6SGV4.js.map +0 -1
- package/dist/chunk-YXRLIV7A.js.map +0 -1
- package/dist/chunk-ZB4HHQMR.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -9,10 +9,10 @@ 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
10
|
import { AutoLayoutOptions } from './layout/index.cjs';
|
|
11
11
|
export { AutoLayoutDirection } from './layout/index.cjs';
|
|
12
|
-
import { N as NodeCategory, a as NodeKindDefinition, C as ConfigField } from './types-
|
|
13
|
-
export { D as DocumentConfigField, K as KeyValueConfigField, P as PortSpec, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField } from './types-
|
|
12
|
+
import { N as NodeCategory, a as NodeKindDefinition, C as ConfigField } from './types-B_pxRqfw.cjs';
|
|
13
|
+
export { D as DocumentConfigField, K as KeyValueConfigField, P as PortSpec, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField } from './types-B_pxRqfw.cjs';
|
|
14
14
|
import { FlowRunFeedEntry } from './runtime/index.cjs';
|
|
15
|
-
export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.cjs';
|
|
15
|
+
export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.cjs';
|
|
16
16
|
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-AXzOR-Wq.cjs';
|
|
17
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';
|
|
18
18
|
import './capabilities-exVeADXz.cjs';
|
|
@@ -36,6 +36,8 @@ type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" |
|
|
|
36
36
|
* disable. An `isValidConnection` you pass yourself always takes precedence.
|
|
37
37
|
*/
|
|
38
38
|
validateConnections?: boolean | ConnectionValidatorOptions;
|
|
39
|
+
/** Show alignment guide lines while dragging, and snap to them. Default off. */
|
|
40
|
+
showHelperLines?: boolean;
|
|
39
41
|
/** Optional toolbar / palette etc. rendered above the canvas. */
|
|
40
42
|
toolbar?: ReactNode;
|
|
41
43
|
className?: string;
|
|
@@ -50,7 +52,7 @@ type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" |
|
|
|
50
52
|
* (xyflow's standard pattern). The surrounding `useFlowState` hook in
|
|
51
53
|
* `runtime/use-flow-state.ts` is a convenience that wires those for you.
|
|
52
54
|
*/
|
|
53
|
-
declare function FlowCanvas({ nodes, edges, background, showControls, showMinimap, height, validateConnections, isValidConnection, toolbar, nodeTypes, edgeTypes, className, style, ...rest }: FlowCanvasProps): react.JSX.Element;
|
|
55
|
+
declare function FlowCanvas({ nodes, edges, background, showControls, showMinimap, height, validateConnections, isValidConnection, colorMode, showHelperLines, onNodesChange, toolbar, nodeTypes, edgeTypes, className, style, ...rest }: FlowCanvasProps): react.JSX.Element;
|
|
54
56
|
|
|
55
57
|
/**
|
|
56
58
|
* Clone a set of nodes AND the edges internal to that set, remapping every id.
|
|
@@ -421,12 +423,7 @@ declare const DecisionNode: react.MemoExoticComponent<typeof DecisionNodeInner>;
|
|
|
421
423
|
declare function OutputNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
422
424
|
declare const OutputNode: react.MemoExoticComponent<typeof OutputNodeInner>;
|
|
423
425
|
|
|
424
|
-
|
|
425
|
-
* NoteNode — annotation card with no ports. Useful for documenting graphs.
|
|
426
|
-
* Body is plain text; hosts can wire onChange via the editor's onNodesChange
|
|
427
|
-
* if they want it editable.
|
|
428
|
-
*/
|
|
429
|
-
declare function NoteNodeInner({ data, selected }: NodeProps<FlowNode>): react.JSX.Element;
|
|
426
|
+
declare function NoteNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
430
427
|
declare const NoteNode: react.MemoExoticComponent<typeof NoteNodeInner>;
|
|
431
428
|
|
|
432
429
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -9,10 +9,10 @@ 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
10
|
import { AutoLayoutOptions } from './layout/index.js';
|
|
11
11
|
export { AutoLayoutDirection } from './layout/index.js';
|
|
12
|
-
import { N as NodeCategory, a as NodeKindDefinition, C as ConfigField } from './types-
|
|
13
|
-
export { D as DocumentConfigField, K as KeyValueConfigField, P as PortSpec, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField } from './types-
|
|
12
|
+
import { N as NodeCategory, a as NodeKindDefinition, C as ConfigField } from './types-BGtR3k9J.js';
|
|
13
|
+
export { D as DocumentConfigField, K as KeyValueConfigField, P as PortSpec, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField } from './types-BGtR3k9J.js';
|
|
14
14
|
import { FlowRunFeedEntry } from './runtime/index.js';
|
|
15
|
-
export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.js';
|
|
15
|
+
export { HistoryController, UseFlowHistoryReturn, UseFlowRunOptions, UseFlowRunReturn, UseFlowStateReturn, applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './runtime/index.js';
|
|
16
16
|
export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-9U-gaYVF.js';
|
|
17
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';
|
|
18
18
|
import './capabilities-85Mjn4uW.js';
|
|
@@ -36,6 +36,8 @@ type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" |
|
|
|
36
36
|
* disable. An `isValidConnection` you pass yourself always takes precedence.
|
|
37
37
|
*/
|
|
38
38
|
validateConnections?: boolean | ConnectionValidatorOptions;
|
|
39
|
+
/** Show alignment guide lines while dragging, and snap to them. Default off. */
|
|
40
|
+
showHelperLines?: boolean;
|
|
39
41
|
/** Optional toolbar / palette etc. rendered above the canvas. */
|
|
40
42
|
toolbar?: ReactNode;
|
|
41
43
|
className?: string;
|
|
@@ -50,7 +52,7 @@ type FlowCanvasProps = Omit<ReactFlowProps<FlowNode, Edge>, "nodes" | "edges" |
|
|
|
50
52
|
* (xyflow's standard pattern). The surrounding `useFlowState` hook in
|
|
51
53
|
* `runtime/use-flow-state.ts` is a convenience that wires those for you.
|
|
52
54
|
*/
|
|
53
|
-
declare function FlowCanvas({ nodes, edges, background, showControls, showMinimap, height, validateConnections, isValidConnection, toolbar, nodeTypes, edgeTypes, className, style, ...rest }: FlowCanvasProps): react.JSX.Element;
|
|
55
|
+
declare function FlowCanvas({ nodes, edges, background, showControls, showMinimap, height, validateConnections, isValidConnection, colorMode, showHelperLines, onNodesChange, toolbar, nodeTypes, edgeTypes, className, style, ...rest }: FlowCanvasProps): react.JSX.Element;
|
|
54
56
|
|
|
55
57
|
/**
|
|
56
58
|
* Clone a set of nodes AND the edges internal to that set, remapping every id.
|
|
@@ -421,12 +423,7 @@ declare const DecisionNode: react.MemoExoticComponent<typeof DecisionNodeInner>;
|
|
|
421
423
|
declare function OutputNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
422
424
|
declare const OutputNode: react.MemoExoticComponent<typeof OutputNodeInner>;
|
|
423
425
|
|
|
424
|
-
|
|
425
|
-
* NoteNode — annotation card with no ports. Useful for documenting graphs.
|
|
426
|
-
* Body is plain text; hosts can wire onChange via the editor's onNodesChange
|
|
427
|
-
* if they want it editable.
|
|
428
|
-
*/
|
|
429
|
-
declare function NoteNodeInner({ data, selected }: NodeProps<FlowNode>): react.JSX.Element;
|
|
426
|
+
declare function NoteNodeInner(props: NodeProps<FlowNode>): react.JSX.Element;
|
|
430
427
|
declare const NoteNode: react.MemoExoticComponent<typeof NoteNodeInner>;
|
|
431
428
|
|
|
432
429
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
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, LaneNode, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds } from './chunk-
|
|
5
|
-
import { ReactFlowProvider, useReactFlow, addEdge, applyEdgeChanges, applyNodeChanges, Position, Handle, reconnectEdge, index, BackgroundVariant, Background, Controls, MiniMap } from './chunk-
|
|
1
|
+
import { useFlowState, useFlowRun, useFlowHistory, applyOutputsToNodes, applyStatusesToNodes } from './chunk-OFW7GN3Y.js';
|
|
2
|
+
export { applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './chunk-OFW7GN3Y.js';
|
|
3
|
+
import { buildNodeTypes, FlowEditorProvider, registerBuiltinKinds, NoteNode, createConnectionValidator } from './chunk-ATQXZEVD.js';
|
|
4
|
+
export { ANY_PORT_TYPE, BUILTIN_KINDS, LaneNode, NoteNode, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds, useFlowEditor, useFlowEditorOptional } from './chunk-ATQXZEVD.js';
|
|
5
|
+
import { ReactFlowProvider, useReactFlow, addEdge, applyEdgeChanges, applyNodeChanges, Position, Handle, reconnectEdge, index, BackgroundVariant, Background, Controls, MiniMap, ViewportPortal } from './chunk-OWENS2H5.js';
|
|
6
6
|
export { LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, decodePause, encodePause, isPause, pauseForHuman } from './chunk-UEOE6B52.js';
|
|
7
7
|
import './chunk-USL4FMFU.js';
|
|
8
|
-
export { runFlow } from './chunk-
|
|
9
|
-
import { workflowToBlob, importWorkflow, exportWorkflow } from './chunk-
|
|
10
|
-
export { WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './chunk-
|
|
8
|
+
export { runFlow } from './chunk-U2VJB7HR.js';
|
|
9
|
+
import { workflowToBlob, importWorkflow, exportWorkflow } from './chunk-N5ICD2WZ.js';
|
|
10
|
+
export { WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './chunk-N5ICD2WZ.js';
|
|
11
11
|
export { resolveNodePorts, resolvePortSpec } from './chunk-TITD5W4Y.js';
|
|
12
|
-
import { onNodeKindsChanged, listNodeKinds, getNodeKind, defaultConfigFor, validateConfig, categoryAccent } from './chunk-
|
|
13
|
-
export { categoryAccent, defaultConfigFor, getNodeKind, listNodeKinds, onNodeKindsChanged, registerNodeKind, validateConfig } from './chunk-
|
|
12
|
+
import { onNodeKindsChanged, listNodeKinds, getNodeKind, defaultConfigFor, validateConfig, categoryAccent } from './chunk-Q6IPK64P.js';
|
|
13
|
+
export { categoryAccent, defaultConfigFor, getNodeKind, listNodeKinds, onNodeKindsChanged, registerNodeKind, validateConfig } from './chunk-Q6IPK64P.js';
|
|
14
14
|
import { getRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
15
15
|
export { RichInputPreview, getRichInputAdapter, isRichInputEnabled, onRichInputAdapterChanged, registerRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
16
|
-
import { memo,
|
|
16
|
+
import { memo, forwardRef, useState, useEffect, useMemo, useCallback, useRef, useImperativeHandle } from 'react';
|
|
17
17
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
18
18
|
|
|
19
19
|
function NodeShellInner({
|
|
@@ -108,14 +108,6 @@ function OutputNodeInner(props) {
|
|
|
108
108
|
return /* @__PURE__ */ jsx(NodeShell, { node: props, accent: "#a855f7", tag: "OUTPUT", icon: "\u25CF", showOutputs: false });
|
|
109
109
|
}
|
|
110
110
|
var OutputNode = memo(OutputNodeInner);
|
|
111
|
-
function NoteNodeInner({ data, selected }) {
|
|
112
|
-
const noteData = data;
|
|
113
|
-
return /* @__PURE__ */ jsxs("div", { className: `ff-note ${selected ? "ff-note--selected" : ""}`, children: [
|
|
114
|
-
noteData.label && /* @__PURE__ */ jsx("div", { className: "ff-note__title", children: noteData.label }),
|
|
115
|
-
noteData.body && /* @__PURE__ */ jsx("p", { className: "ff-note__body", children: noteData.body })
|
|
116
|
-
] });
|
|
117
|
-
}
|
|
118
|
-
var NoteNode = memo(NoteNodeInner);
|
|
119
111
|
function SubgraphNodeInner(props) {
|
|
120
112
|
const data = props.data;
|
|
121
113
|
const childCount = data.childIds?.length ?? 0;
|
|
@@ -273,6 +265,97 @@ function distributeNodes(nodes, axis) {
|
|
|
273
265
|
return { ...n, position: axis === "h" ? { ...n.position, x: p } : { ...n.position, y: p } };
|
|
274
266
|
});
|
|
275
267
|
}
|
|
268
|
+
|
|
269
|
+
// src/components/canvas/helper-lines.ts
|
|
270
|
+
var w = (n) => n.width ?? n.measured?.width ?? 0;
|
|
271
|
+
var h = (n) => n.height ?? n.measured?.height ?? 0;
|
|
272
|
+
function getHelperLines(change, nodes, distance = 6) {
|
|
273
|
+
const result = { snapPosition: { x: void 0, y: void 0 } };
|
|
274
|
+
const a = nodes.find((n) => n.id === change.id);
|
|
275
|
+
if (!a || !change.position) return result;
|
|
276
|
+
const A = {
|
|
277
|
+
left: change.position.x,
|
|
278
|
+
right: change.position.x + w(a),
|
|
279
|
+
top: change.position.y,
|
|
280
|
+
bottom: change.position.y + h(a),
|
|
281
|
+
width: w(a),
|
|
282
|
+
height: h(a)
|
|
283
|
+
};
|
|
284
|
+
let vDist = distance;
|
|
285
|
+
let hDist = distance;
|
|
286
|
+
for (const b of nodes) {
|
|
287
|
+
if (b.id === a.id) continue;
|
|
288
|
+
const B = { left: b.position.x, right: b.position.x + w(b), top: b.position.y, bottom: b.position.y + h(b) };
|
|
289
|
+
const ll = Math.abs(A.left - B.left);
|
|
290
|
+
if (ll < vDist) {
|
|
291
|
+
result.snapPosition.x = B.left;
|
|
292
|
+
result.vertical = B.left;
|
|
293
|
+
vDist = ll;
|
|
294
|
+
}
|
|
295
|
+
const rr = Math.abs(A.right - B.right);
|
|
296
|
+
if (rr < vDist) {
|
|
297
|
+
result.snapPosition.x = B.right - A.width;
|
|
298
|
+
result.vertical = B.right;
|
|
299
|
+
vDist = rr;
|
|
300
|
+
}
|
|
301
|
+
const lr = Math.abs(A.left - B.right);
|
|
302
|
+
if (lr < vDist) {
|
|
303
|
+
result.snapPosition.x = B.right;
|
|
304
|
+
result.vertical = B.right;
|
|
305
|
+
vDist = lr;
|
|
306
|
+
}
|
|
307
|
+
const rl = Math.abs(A.right - B.left);
|
|
308
|
+
if (rl < vDist) {
|
|
309
|
+
result.snapPosition.x = B.left - A.width;
|
|
310
|
+
result.vertical = B.left;
|
|
311
|
+
vDist = rl;
|
|
312
|
+
}
|
|
313
|
+
const tt = Math.abs(A.top - B.top);
|
|
314
|
+
if (tt < hDist) {
|
|
315
|
+
result.snapPosition.y = B.top;
|
|
316
|
+
result.horizontal = B.top;
|
|
317
|
+
hDist = tt;
|
|
318
|
+
}
|
|
319
|
+
const bb = Math.abs(A.bottom - B.bottom);
|
|
320
|
+
if (bb < hDist) {
|
|
321
|
+
result.snapPosition.y = B.bottom - A.height;
|
|
322
|
+
result.horizontal = B.bottom;
|
|
323
|
+
hDist = bb;
|
|
324
|
+
}
|
|
325
|
+
const tb = Math.abs(A.top - B.bottom);
|
|
326
|
+
if (tb < hDist) {
|
|
327
|
+
result.snapPosition.y = B.bottom;
|
|
328
|
+
result.horizontal = B.bottom;
|
|
329
|
+
hDist = tb;
|
|
330
|
+
}
|
|
331
|
+
const bt = Math.abs(A.bottom - B.top);
|
|
332
|
+
if (bt < hDist) {
|
|
333
|
+
result.snapPosition.y = B.top - A.height;
|
|
334
|
+
result.horizontal = B.top;
|
|
335
|
+
hDist = bt;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
function HelperLines({ horizontal, vertical }) {
|
|
341
|
+
if (horizontal === void 0 && vertical === void 0) return null;
|
|
342
|
+
return /* @__PURE__ */ jsxs(ViewportPortal, { children: [
|
|
343
|
+
vertical !== void 0 && /* @__PURE__ */ jsx(
|
|
344
|
+
"div",
|
|
345
|
+
{
|
|
346
|
+
className: "ff-helper-line",
|
|
347
|
+
style: { position: "absolute", transform: `translateX(${vertical}px)`, top: -5e3, height: 1e4, width: 1, pointerEvents: "none" }
|
|
348
|
+
}
|
|
349
|
+
),
|
|
350
|
+
horizontal !== void 0 && /* @__PURE__ */ jsx(
|
|
351
|
+
"div",
|
|
352
|
+
{
|
|
353
|
+
className: "ff-helper-line",
|
|
354
|
+
style: { position: "absolute", transform: `translateY(${horizontal}px)`, left: -5e3, width: 1e4, height: 1, pointerEvents: "none" }
|
|
355
|
+
}
|
|
356
|
+
)
|
|
357
|
+
] });
|
|
358
|
+
}
|
|
276
359
|
var DEFAULT_FIT_VIEW = { padding: 0.2 };
|
|
277
360
|
var DEFAULT_EDGE_OPTIONS = {
|
|
278
361
|
type: "smoothstep",
|
|
@@ -287,6 +370,9 @@ function FlowCanvas({
|
|
|
287
370
|
height = 600,
|
|
288
371
|
validateConnections = true,
|
|
289
372
|
isValidConnection,
|
|
373
|
+
colorMode,
|
|
374
|
+
showHelperLines = false,
|
|
375
|
+
onNodesChange,
|
|
290
376
|
toolbar,
|
|
291
377
|
nodeTypes,
|
|
292
378
|
edgeTypes,
|
|
@@ -313,33 +399,68 @@ function FlowCanvas({
|
|
|
313
399
|
[edgeTypes]
|
|
314
400
|
);
|
|
315
401
|
const orderedNodes = useMemo(() => sortNodesParentFirst(nodes), [nodes]);
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
zoomActivationKeyCode: "Shift",
|
|
330
|
-
preventScrolling: false,
|
|
331
|
-
isValidConnection: resolvedIsValidConnection,
|
|
332
|
-
...rest,
|
|
333
|
-
children: [
|
|
334
|
-
background !== "none" && /* @__PURE__ */ jsx(Background, { variant: background, gap: 20, size: 1, color: "rgba(0,0,0,0.18)" }),
|
|
335
|
-
showControls && /* @__PURE__ */ jsx(Controls, { className: "ff-controls", position: "bottom-right" }),
|
|
336
|
-
showMinimap && /* @__PURE__ */ jsx(MiniMap, { className: "ff-minimap", pannable: true, zoomable: true })
|
|
337
|
-
]
|
|
402
|
+
const [helperLines, setHelperLines] = useState({});
|
|
403
|
+
const handleNodesChange = useCallback(
|
|
404
|
+
(changes) => {
|
|
405
|
+
if (showHelperLines) {
|
|
406
|
+
const pos = changes.filter((c) => c.type === "position" && c.position);
|
|
407
|
+
if (pos.length === 1 && pos[0].dragging) {
|
|
408
|
+
const lines = getHelperLines(pos[0], nodesRef.current);
|
|
409
|
+
if (lines.snapPosition.x !== void 0) pos[0].position.x = lines.snapPosition.x;
|
|
410
|
+
if (lines.snapPosition.y !== void 0) pos[0].position.y = lines.snapPosition.y;
|
|
411
|
+
setHelperLines({ horizontal: lines.horizontal, vertical: lines.vertical });
|
|
412
|
+
} else {
|
|
413
|
+
setHelperLines({});
|
|
414
|
+
}
|
|
338
415
|
}
|
|
339
|
-
|
|
340
|
-
|
|
416
|
+
onNodesChange?.(changes);
|
|
417
|
+
},
|
|
418
|
+
[showHelperLines, onNodesChange]
|
|
419
|
+
);
|
|
420
|
+
return /* @__PURE__ */ jsxs(
|
|
421
|
+
"div",
|
|
422
|
+
{
|
|
423
|
+
className: [
|
|
424
|
+
"ff-canvas",
|
|
425
|
+
// colorMode drives BOTH react-flow's chrome (below) and our `ff-` styles
|
|
426
|
+
// via the shared `.dark` class / light opt-out — one theme signal.
|
|
427
|
+
colorMode === "dark" ? "dark" : "",
|
|
428
|
+
colorMode === "light" ? "ff-canvas--light" : "",
|
|
429
|
+
className ?? ""
|
|
430
|
+
].filter(Boolean).join(" "),
|
|
431
|
+
style: { height, ...style },
|
|
432
|
+
children: [
|
|
433
|
+
toolbar && /* @__PURE__ */ jsx("div", { className: "ff-canvas__toolbar", children: toolbar }),
|
|
434
|
+
/* @__PURE__ */ jsx("div", { className: "ff-canvas__surface", children: /* @__PURE__ */ jsxs(
|
|
435
|
+
index,
|
|
436
|
+
{
|
|
437
|
+
nodes: orderedNodes,
|
|
438
|
+
edges,
|
|
439
|
+
onNodesChange: handleNodesChange,
|
|
440
|
+
colorMode,
|
|
441
|
+
nodeTypes: mergedNodeTypes,
|
|
442
|
+
edgeTypes: mergedEdgeTypes,
|
|
443
|
+
fitView: true,
|
|
444
|
+
fitViewOptions: DEFAULT_FIT_VIEW,
|
|
445
|
+
defaultEdgeOptions: DEFAULT_EDGE_OPTIONS,
|
|
446
|
+
proOptions: { hideAttribution: true },
|
|
447
|
+
zoomActivationKeyCode: "Shift",
|
|
448
|
+
preventScrolling: false,
|
|
449
|
+
isValidConnection: resolvedIsValidConnection,
|
|
450
|
+
...rest,
|
|
451
|
+
children: [
|
|
452
|
+
background !== "none" && /* @__PURE__ */ jsx(Background, { variant: background, gap: 20, size: 1, color: "rgba(0,0,0,0.18)" }),
|
|
453
|
+
showControls && /* @__PURE__ */ jsx(Controls, { className: "ff-controls", position: "bottom-right" }),
|
|
454
|
+
showMinimap && /* @__PURE__ */ jsx(MiniMap, { className: "ff-minimap", pannable: true, zoomable: true }),
|
|
455
|
+
showHelperLines && /* @__PURE__ */ jsx(HelperLines, { horizontal: helperLines.horizontal, vertical: helperLines.vertical })
|
|
456
|
+
]
|
|
457
|
+
}
|
|
458
|
+
) })
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
);
|
|
341
462
|
}
|
|
342
|
-
var CATEGORY_ORDER = ["trigger", "logic", "data", "ai", "io", "human", "output", "layout", "custom"];
|
|
463
|
+
var CATEGORY_ORDER = ["trigger", "logic", "data", "ai", "io", "human", "output", "layout", "annotation", "custom"];
|
|
343
464
|
var CATEGORY_LABELS = {
|
|
344
465
|
trigger: "Triggers",
|
|
345
466
|
logic: "Logic",
|
|
@@ -349,6 +470,7 @@ var CATEGORY_LABELS = {
|
|
|
349
470
|
human: "Human",
|
|
350
471
|
output: "Output",
|
|
351
472
|
layout: "Layout",
|
|
473
|
+
annotation: "Notes",
|
|
352
474
|
custom: "Custom"
|
|
353
475
|
};
|
|
354
476
|
function NodePalette({ categories, onPick, className, style }) {
|
|
@@ -940,18 +1062,6 @@ function formatTime(at) {
|
|
|
940
1062
|
const d = new Date(at);
|
|
941
1063
|
return `${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}.${Math.floor(d.getMilliseconds() / 100)}`;
|
|
942
1064
|
}
|
|
943
|
-
var FlowEditorContext = createContext(null);
|
|
944
|
-
var FlowEditorProvider = FlowEditorContext.Provider;
|
|
945
|
-
function useFlowEditor() {
|
|
946
|
-
const api = useContext(FlowEditorContext);
|
|
947
|
-
if (api === null) {
|
|
948
|
-
throw new Error("useFlowEditor() must be called inside <FlowEditor>.");
|
|
949
|
-
}
|
|
950
|
-
return api;
|
|
951
|
-
}
|
|
952
|
-
function useFlowEditorOptional() {
|
|
953
|
-
return useContext(FlowEditorContext);
|
|
954
|
-
}
|
|
955
1065
|
var FlowEditor = forwardRef(function FlowEditor2(props, ref) {
|
|
956
1066
|
return /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(
|
|
957
1067
|
"div",
|
|
@@ -993,8 +1103,11 @@ function FlowEditorInner({
|
|
|
993
1103
|
useEffect(() => onNodeKindsChanged(() => force((n) => n + 1)), []);
|
|
994
1104
|
const nodeTypes = useMemo(() => buildNodeTypes(), [listNodeKinds().length]);
|
|
995
1105
|
const renderedNodes = useMemo(
|
|
996
|
-
() =>
|
|
997
|
-
|
|
1106
|
+
() => applyOutputsToNodes(
|
|
1107
|
+
applyStatusesToNodes(flow.nodes, runner.statuses, runner.statusText),
|
|
1108
|
+
runner.outputs
|
|
1109
|
+
),
|
|
1110
|
+
[flow.nodes, runner.statuses, runner.statusText, runner.outputs]
|
|
998
1111
|
);
|
|
999
1112
|
const [selectedId, setSelectedId] = useState(null);
|
|
1000
1113
|
const selected = useMemo(() => flow.nodes.find((n) => n.id === selectedId) ?? null, [flow.nodes, selectedId]);
|
|
@@ -1178,10 +1291,10 @@ function FlowEditorInner({
|
|
|
1178
1291
|
(orientation = "horizontal", title) => {
|
|
1179
1292
|
const vertical = orientation === "vertical";
|
|
1180
1293
|
const lanes = flow.nodes.filter(isLaneNode);
|
|
1181
|
-
const
|
|
1182
|
-
const
|
|
1294
|
+
const w2 = vertical ? 280 : 680;
|
|
1295
|
+
const h2 = vertical ? 480 : 168;
|
|
1183
1296
|
const end = lanes.reduce(
|
|
1184
|
-
(m, l) => Math.max(m, vertical ? l.position.x + (l.width ??
|
|
1297
|
+
(m, l) => Math.max(m, vertical ? l.position.x + (l.width ?? w2) : l.position.y + (l.height ?? h2)),
|
|
1185
1298
|
0
|
|
1186
1299
|
);
|
|
1187
1300
|
const id = newNodeId();
|
|
@@ -1190,8 +1303,8 @@ function FlowEditorInner({
|
|
|
1190
1303
|
id,
|
|
1191
1304
|
type: "@particle-academy/lane",
|
|
1192
1305
|
position: vertical ? { x: lanes.length ? end + 12 : 0, y: 0 } : { x: 0, y: lanes.length ? end + 12 : 0 },
|
|
1193
|
-
width:
|
|
1194
|
-
height:
|
|
1306
|
+
width: w2,
|
|
1307
|
+
height: h2,
|
|
1195
1308
|
data: { kind: "@particle-academy/lane", label: name, config: { title: name, orientation } }
|
|
1196
1309
|
};
|
|
1197
1310
|
flow.setNodes((all) => [...all, node]);
|
|
@@ -1637,6 +1750,6 @@ function NodePort({ side, type, id, style, title, className }) {
|
|
|
1637
1750
|
// src/index.ts
|
|
1638
1751
|
registerBuiltinKinds();
|
|
1639
1752
|
|
|
1640
|
-
export { ActionNode, ConfigFieldRenderer, DecisionNode, FlowCanvas, FlowEditor, FlowRunControls, FlowRunFeed, NodeConfigPanel, NodePalette, NodePort, NodeShell,
|
|
1753
|
+
export { ActionNode, ConfigFieldRenderer, DecisionNode, FlowCanvas, FlowEditor, FlowRunControls, FlowRunFeed, NodeConfigPanel, NodePalette, NodePort, NodeShell, OutputNode, SubgraphNode, TriggerNode, alignNodes, cloneSubgraph, defaultNodeTypes, defineNode, distributeNodes, paletteDropHandlers, reconnectEdge2 as reconnectEdge };
|
|
1641
1754
|
//# sourceMappingURL=index.js.map
|
|
1642
1755
|
//# sourceMappingURL=index.js.map
|