@particle-academy/fancy-flow 0.18.0 → 0.19.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-MFMRTRPO.js → chunk-PHX4SBOD.js} +114 -5
- package/dist/chunk-PHX4SBOD.js.map +1 -0
- package/dist/index.cjs +193 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +83 -29
- package/dist/index.js.map +1 -1
- package/dist/runtime/index.d.cts +61 -1
- package/dist/runtime/index.d.ts +61 -1
- package/dist/runtime.cjs +112 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +1 -1
- package/package.json +6 -3
- package/dist/chunk-MFMRTRPO.js.map +0 -1
package/dist/runtime/index.d.cts
CHANGED
|
@@ -50,6 +50,13 @@ type UseFlowStateReturn = {
|
|
|
50
50
|
edges: FlowEdge[];
|
|
51
51
|
setNodes: React.Dispatch<React.SetStateAction<FlowNode[]>>;
|
|
52
52
|
setEdges: React.Dispatch<React.SetStateAction<FlowEdge[]>>;
|
|
53
|
+
/**
|
|
54
|
+
* Replace nodes AND edges atomically in a single commit. Use this for any op
|
|
55
|
+
* that touches both (delete-with-edge-prune, undo/redo restore, setGraph):
|
|
56
|
+
* calling `setNodes` then `setEdges` is NOT atomic in controlled mode (each
|
|
57
|
+
* closes over a stale `value`), so the second write clobbers the first.
|
|
58
|
+
*/
|
|
59
|
+
setGraph: (graph: FlowGraph) => void;
|
|
53
60
|
onNodesChange: (changes: NodeChange[]) => void;
|
|
54
61
|
onEdgesChange: (changes: EdgeChange[]) => void;
|
|
55
62
|
onConnect: (connection: Connection) => void;
|
|
@@ -62,4 +69,57 @@ type UseFlowStateReturn = {
|
|
|
62
69
|
*/
|
|
63
70
|
declare function useFlowState(initial: FlowGraph): UseFlowStateReturn;
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
type UseFlowHistoryReturn = {
|
|
73
|
+
/** The flow sink wrapped so committing mutations snapshot for undo first. */
|
|
74
|
+
flow: UseFlowStateReturn;
|
|
75
|
+
undo: () => void;
|
|
76
|
+
redo: () => void;
|
|
77
|
+
canUndo: boolean;
|
|
78
|
+
canRedo: boolean;
|
|
79
|
+
/** Snapshot the current graph as an undo point (before a programmatic edit). */
|
|
80
|
+
capture: () => void;
|
|
81
|
+
/** Wire to `<FlowCanvas onNodeDragStart>` — snapshots the pre-drag graph. */
|
|
82
|
+
onNodeDragStart: () => void;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* useFlowHistory — the commit/undo pipeline. Wraps a flow sink (the uncontrolled
|
|
86
|
+
* `useFlowState` hook OR the controlled adapter) so every *committing* mutation
|
|
87
|
+
* records a snapshot first, giving undo/redo without the editor threading
|
|
88
|
+
* history through each call site. This is the single interception point the
|
|
89
|
+
* two-sink architecture otherwise lacks.
|
|
90
|
+
*
|
|
91
|
+
* Granularity: a burst of setState calls from one logical op (e.g. a
|
|
92
|
+
* delete = setNodes+setEdges) is coalesced into ONE undo step; transient
|
|
93
|
+
* interactive changes (drag-move, dimension-measure, selection) are NOT captured
|
|
94
|
+
* — a drag is captured once at `onNodeDragStart` instead.
|
|
95
|
+
*/
|
|
96
|
+
declare function useFlowHistory(flow: UseFlowStateReturn): UseFlowHistoryReturn;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Undo/redo history — a pure, React-free snapshot controller. The editor pushes
|
|
100
|
+
* a graph snapshot BEFORE each committing mutation; `undo`/`redo` swap snapshots
|
|
101
|
+
* between the past/future stacks. Kept free of React so it can be unit-tested
|
|
102
|
+
* and reused by any host (or a headless driver).
|
|
103
|
+
*
|
|
104
|
+
* Coalescing (collapsing a burst of setState calls from one logical op into a
|
|
105
|
+
* single undo step) is the caller's job — see `useFlowHistory`.
|
|
106
|
+
*/
|
|
107
|
+
type HistoryController = {
|
|
108
|
+
/** Record `graph` as an undo point. Clears the redo stack (new branch). */
|
|
109
|
+
push: (graph: FlowGraph) => void;
|
|
110
|
+
/** Pop the last undo point; `current` is pushed onto the redo stack. */
|
|
111
|
+
undo: (current: FlowGraph) => FlowGraph | null;
|
|
112
|
+
/** Pop the last redo point; `current` is pushed back onto the undo stack. */
|
|
113
|
+
redo: (current: FlowGraph) => FlowGraph | null;
|
|
114
|
+
canUndo: () => boolean;
|
|
115
|
+
canRedo: () => boolean;
|
|
116
|
+
clear: () => void;
|
|
117
|
+
/** Test/inspection helper — sizes of the two stacks. */
|
|
118
|
+
size: () => {
|
|
119
|
+
past: number;
|
|
120
|
+
future: number;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
declare function createHistory(limit?: number): HistoryController;
|
|
124
|
+
|
|
125
|
+
export { type FlowRunFeedEntry, type HistoryController, RunOptions, RunResult, type UseFlowHistoryReturn, type UseFlowRunOptions, type UseFlowRunReturn, type UseFlowStateReturn, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState };
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -50,6 +50,13 @@ type UseFlowStateReturn = {
|
|
|
50
50
|
edges: FlowEdge[];
|
|
51
51
|
setNodes: React.Dispatch<React.SetStateAction<FlowNode[]>>;
|
|
52
52
|
setEdges: React.Dispatch<React.SetStateAction<FlowEdge[]>>;
|
|
53
|
+
/**
|
|
54
|
+
* Replace nodes AND edges atomically in a single commit. Use this for any op
|
|
55
|
+
* that touches both (delete-with-edge-prune, undo/redo restore, setGraph):
|
|
56
|
+
* calling `setNodes` then `setEdges` is NOT atomic in controlled mode (each
|
|
57
|
+
* closes over a stale `value`), so the second write clobbers the first.
|
|
58
|
+
*/
|
|
59
|
+
setGraph: (graph: FlowGraph) => void;
|
|
53
60
|
onNodesChange: (changes: NodeChange[]) => void;
|
|
54
61
|
onEdgesChange: (changes: EdgeChange[]) => void;
|
|
55
62
|
onConnect: (connection: Connection) => void;
|
|
@@ -62,4 +69,57 @@ type UseFlowStateReturn = {
|
|
|
62
69
|
*/
|
|
63
70
|
declare function useFlowState(initial: FlowGraph): UseFlowStateReturn;
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
type UseFlowHistoryReturn = {
|
|
73
|
+
/** The flow sink wrapped so committing mutations snapshot for undo first. */
|
|
74
|
+
flow: UseFlowStateReturn;
|
|
75
|
+
undo: () => void;
|
|
76
|
+
redo: () => void;
|
|
77
|
+
canUndo: boolean;
|
|
78
|
+
canRedo: boolean;
|
|
79
|
+
/** Snapshot the current graph as an undo point (before a programmatic edit). */
|
|
80
|
+
capture: () => void;
|
|
81
|
+
/** Wire to `<FlowCanvas onNodeDragStart>` — snapshots the pre-drag graph. */
|
|
82
|
+
onNodeDragStart: () => void;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* useFlowHistory — the commit/undo pipeline. Wraps a flow sink (the uncontrolled
|
|
86
|
+
* `useFlowState` hook OR the controlled adapter) so every *committing* mutation
|
|
87
|
+
* records a snapshot first, giving undo/redo without the editor threading
|
|
88
|
+
* history through each call site. This is the single interception point the
|
|
89
|
+
* two-sink architecture otherwise lacks.
|
|
90
|
+
*
|
|
91
|
+
* Granularity: a burst of setState calls from one logical op (e.g. a
|
|
92
|
+
* delete = setNodes+setEdges) is coalesced into ONE undo step; transient
|
|
93
|
+
* interactive changes (drag-move, dimension-measure, selection) are NOT captured
|
|
94
|
+
* — a drag is captured once at `onNodeDragStart` instead.
|
|
95
|
+
*/
|
|
96
|
+
declare function useFlowHistory(flow: UseFlowStateReturn): UseFlowHistoryReturn;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Undo/redo history — a pure, React-free snapshot controller. The editor pushes
|
|
100
|
+
* a graph snapshot BEFORE each committing mutation; `undo`/`redo` swap snapshots
|
|
101
|
+
* between the past/future stacks. Kept free of React so it can be unit-tested
|
|
102
|
+
* and reused by any host (or a headless driver).
|
|
103
|
+
*
|
|
104
|
+
* Coalescing (collapsing a burst of setState calls from one logical op into a
|
|
105
|
+
* single undo step) is the caller's job — see `useFlowHistory`.
|
|
106
|
+
*/
|
|
107
|
+
type HistoryController = {
|
|
108
|
+
/** Record `graph` as an undo point. Clears the redo stack (new branch). */
|
|
109
|
+
push: (graph: FlowGraph) => void;
|
|
110
|
+
/** Pop the last undo point; `current` is pushed onto the redo stack. */
|
|
111
|
+
undo: (current: FlowGraph) => FlowGraph | null;
|
|
112
|
+
/** Pop the last redo point; `current` is pushed back onto the undo stack. */
|
|
113
|
+
redo: (current: FlowGraph) => FlowGraph | null;
|
|
114
|
+
canUndo: () => boolean;
|
|
115
|
+
canRedo: () => boolean;
|
|
116
|
+
clear: () => void;
|
|
117
|
+
/** Test/inspection helper — sizes of the two stacks. */
|
|
118
|
+
size: () => {
|
|
119
|
+
past: number;
|
|
120
|
+
future: number;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
declare function createHistory(limit?: number): HistoryController;
|
|
124
|
+
|
|
125
|
+
export { type FlowRunFeedEntry, type HistoryController, RunOptions, RunResult, type UseFlowHistoryReturn, type UseFlowRunOptions, type UseFlowRunReturn, type UseFlowStateReturn, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState };
|
package/dist/runtime.cjs
CHANGED
|
@@ -9194,12 +9194,123 @@ function useFlowState(initial) {
|
|
|
9194
9194
|
const onConnect = ReactExports.useCallback((connection) => {
|
|
9195
9195
|
setEdges((es) => addEdge2(connection, es));
|
|
9196
9196
|
}, []);
|
|
9197
|
+
const setGraph = ReactExports.useCallback((graph) => {
|
|
9198
|
+
setNodes(graph.nodes);
|
|
9199
|
+
setEdges(graph.edges);
|
|
9200
|
+
}, []);
|
|
9197
9201
|
const toGraph = ReactExports.useCallback(() => ({ nodes, edges }), [nodes, edges]);
|
|
9198
|
-
return { nodes, edges, setNodes, setEdges, onNodesChange, onEdgesChange, onConnect, toGraph };
|
|
9202
|
+
return { nodes, edges, setNodes, setEdges, setGraph, onNodesChange, onEdgesChange, onConnect, toGraph };
|
|
9203
|
+
}
|
|
9204
|
+
|
|
9205
|
+
// src/runtime/history.ts
|
|
9206
|
+
function createHistory(limit = 100) {
|
|
9207
|
+
let past = [];
|
|
9208
|
+
let future = [];
|
|
9209
|
+
return {
|
|
9210
|
+
push(graph) {
|
|
9211
|
+
past.push(graph);
|
|
9212
|
+
if (past.length > limit) past.shift();
|
|
9213
|
+
future = [];
|
|
9214
|
+
},
|
|
9215
|
+
undo(current) {
|
|
9216
|
+
const prev = past.pop();
|
|
9217
|
+
if (prev === void 0) return null;
|
|
9218
|
+
future.push(current);
|
|
9219
|
+
return prev;
|
|
9220
|
+
},
|
|
9221
|
+
redo(current) {
|
|
9222
|
+
const next = future.pop();
|
|
9223
|
+
if (next === void 0) return null;
|
|
9224
|
+
past.push(current);
|
|
9225
|
+
return next;
|
|
9226
|
+
},
|
|
9227
|
+
canUndo: () => past.length > 0,
|
|
9228
|
+
canRedo: () => future.length > 0,
|
|
9229
|
+
clear() {
|
|
9230
|
+
past = [];
|
|
9231
|
+
future = [];
|
|
9232
|
+
},
|
|
9233
|
+
size: () => ({ past: past.length, future: future.length })
|
|
9234
|
+
};
|
|
9235
|
+
}
|
|
9236
|
+
|
|
9237
|
+
// src/runtime/use-flow-history.ts
|
|
9238
|
+
function useFlowHistory(flow) {
|
|
9239
|
+
const history = ReactExports.useRef(createHistory()).current;
|
|
9240
|
+
const restoring = ReactExports.useRef(false);
|
|
9241
|
+
const coalesced = ReactExports.useRef(false);
|
|
9242
|
+
const [, bump] = ReactExports.useState(0);
|
|
9243
|
+
const rerender = ReactExports.useCallback(() => bump((n) => n + 1), []);
|
|
9244
|
+
const graphRef = ReactExports.useRef({ nodes: flow.nodes, edges: flow.edges });
|
|
9245
|
+
graphRef.current = { nodes: flow.nodes, edges: flow.edges };
|
|
9246
|
+
const capture = ReactExports.useCallback(() => {
|
|
9247
|
+
if (restoring.current || coalesced.current) return;
|
|
9248
|
+
coalesced.current = true;
|
|
9249
|
+
queueMicrotask(() => {
|
|
9250
|
+
coalesced.current = false;
|
|
9251
|
+
});
|
|
9252
|
+
history.push(graphRef.current);
|
|
9253
|
+
rerender();
|
|
9254
|
+
}, [history, rerender]);
|
|
9255
|
+
const restore = ReactExports.useCallback(
|
|
9256
|
+
(g) => {
|
|
9257
|
+
if (!g) return;
|
|
9258
|
+
restoring.current = true;
|
|
9259
|
+
flow.setGraph(g);
|
|
9260
|
+
queueMicrotask(() => {
|
|
9261
|
+
restoring.current = false;
|
|
9262
|
+
});
|
|
9263
|
+
rerender();
|
|
9264
|
+
},
|
|
9265
|
+
[flow, rerender]
|
|
9266
|
+
);
|
|
9267
|
+
const undo = ReactExports.useCallback(() => restore(history.undo(graphRef.current)), [history, restore]);
|
|
9268
|
+
const redo = ReactExports.useCallback(() => restore(history.redo(graphRef.current)), [history, restore]);
|
|
9269
|
+
const wrapped = ReactExports.useMemo(
|
|
9270
|
+
() => ({
|
|
9271
|
+
...flow,
|
|
9272
|
+
setNodes: (next) => {
|
|
9273
|
+
capture();
|
|
9274
|
+
flow.setNodes(next);
|
|
9275
|
+
},
|
|
9276
|
+
setEdges: (next) => {
|
|
9277
|
+
capture();
|
|
9278
|
+
flow.setEdges(next);
|
|
9279
|
+
},
|
|
9280
|
+
setGraph: (g) => {
|
|
9281
|
+
capture();
|
|
9282
|
+
flow.setGraph(g);
|
|
9283
|
+
},
|
|
9284
|
+
onNodesChange: (changes) => {
|
|
9285
|
+
if (!restoring.current && changes.some((c) => c.type === "remove")) capture();
|
|
9286
|
+
flow.onNodesChange(changes);
|
|
9287
|
+
},
|
|
9288
|
+
onEdgesChange: (changes) => {
|
|
9289
|
+
if (!restoring.current && changes.some((c) => c.type === "remove")) capture();
|
|
9290
|
+
flow.onEdgesChange(changes);
|
|
9291
|
+
},
|
|
9292
|
+
onConnect: (conn) => {
|
|
9293
|
+
capture();
|
|
9294
|
+
flow.onConnect(conn);
|
|
9295
|
+
}
|
|
9296
|
+
}),
|
|
9297
|
+
[flow, capture]
|
|
9298
|
+
);
|
|
9299
|
+
return {
|
|
9300
|
+
flow: wrapped,
|
|
9301
|
+
undo,
|
|
9302
|
+
redo,
|
|
9303
|
+
canUndo: history.canUndo(),
|
|
9304
|
+
canRedo: history.canRedo(),
|
|
9305
|
+
capture,
|
|
9306
|
+
onNodeDragStart: capture
|
|
9307
|
+
};
|
|
9199
9308
|
}
|
|
9200
9309
|
|
|
9201
9310
|
exports.applyStatusesToNodes = applyStatusesToNodes;
|
|
9311
|
+
exports.createHistory = createHistory;
|
|
9202
9312
|
exports.runFlow = runFlow;
|
|
9313
|
+
exports.useFlowHistory = useFlowHistory;
|
|
9203
9314
|
exports.useFlowRun = useFlowRun;
|
|
9204
9315
|
exports.useFlowState = useFlowState;
|
|
9205
9316
|
//# sourceMappingURL=runtime.cjs.map
|