@particle-academy/fancy-flow 0.19.0 → 0.21.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-PHX4SBOD.js → chunk-G3WHXMZ3.js} +3 -3
- package/dist/{chunk-PHX4SBOD.js.map → chunk-G3WHXMZ3.js.map} +1 -1
- package/dist/{chunk-D6W5FMCT.js → chunk-HMWYJIRP.js} +22 -4
- package/dist/chunk-HMWYJIRP.js.map +1 -0
- package/dist/{chunk-FSC64BPD.js → chunk-JE4ENQSE.js} +14 -4
- package/dist/chunk-JE4ENQSE.js.map +1 -0
- package/dist/{chunk-NF6NPY5N.js → chunk-ZB4HHQMR.js} +158 -32
- package/dist/chunk-ZB4HHQMR.js.map +1 -0
- package/dist/index.cjs +346 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -5
- package/dist/index.d.ts +51 -5
- package/dist/index.js +165 -10
- 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 +138 -30
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -2
- package/dist/runtime.js +2 -2
- package/dist/schema/index.d.cts +20 -1
- package/dist/schema/index.d.ts +20 -1
- package/dist/schema.cjs +20 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +1 -1
- package/dist/styles.css +20 -0
- package/dist/styles.css.map +1 -1
- package/dist/{types-D_jOR3Z2.d.cts → types-LG-YckGh.d.cts} +22 -0
- package/dist/{types-NerkPtHS.d.ts → types-VGkCXEO6.d.ts} +22 -0
- package/dist/ux.d.cts +1 -1
- package/dist/ux.d.ts +1 -1
- package/package.json +23 -3
- package/dist/chunk-D6W5FMCT.js.map +0 -1
- package/dist/chunk-FSC64BPD.js.map +0 -1
- package/dist/chunk-NF6NPY5N.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var ReactExports = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
-
require('react-dom');
|
|
5
|
+
var reactDom = require('react-dom');
|
|
6
6
|
|
|
7
7
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
8
|
|
|
@@ -1388,9 +1388,9 @@ function creator_default(name) {
|
|
|
1388
1388
|
// node_modules/d3-selection/src/selector.js
|
|
1389
1389
|
function none() {
|
|
1390
1390
|
}
|
|
1391
|
-
function selector_default(
|
|
1392
|
-
return
|
|
1393
|
-
return this.querySelector(
|
|
1391
|
+
function selector_default(selector2) {
|
|
1392
|
+
return selector2 == null ? none : function() {
|
|
1393
|
+
return this.querySelector(selector2);
|
|
1394
1394
|
};
|
|
1395
1395
|
}
|
|
1396
1396
|
|
|
@@ -1417,9 +1417,9 @@ function array(x) {
|
|
|
1417
1417
|
function empty() {
|
|
1418
1418
|
return [];
|
|
1419
1419
|
}
|
|
1420
|
-
function selectorAll_default(
|
|
1421
|
-
return
|
|
1422
|
-
return this.querySelectorAll(
|
|
1420
|
+
function selectorAll_default(selector2) {
|
|
1421
|
+
return selector2 == null ? empty : function() {
|
|
1422
|
+
return this.querySelectorAll(selector2);
|
|
1423
1423
|
};
|
|
1424
1424
|
}
|
|
1425
1425
|
|
|
@@ -1444,14 +1444,14 @@ function selectAll_default(select) {
|
|
|
1444
1444
|
}
|
|
1445
1445
|
|
|
1446
1446
|
// node_modules/d3-selection/src/matcher.js
|
|
1447
|
-
function matcher_default(
|
|
1447
|
+
function matcher_default(selector2) {
|
|
1448
1448
|
return function() {
|
|
1449
|
-
return this.matches(
|
|
1449
|
+
return this.matches(selector2);
|
|
1450
1450
|
};
|
|
1451
1451
|
}
|
|
1452
|
-
function childMatcher(
|
|
1452
|
+
function childMatcher(selector2) {
|
|
1453
1453
|
return function(node) {
|
|
1454
|
-
return node.matches(
|
|
1454
|
+
return node.matches(selector2);
|
|
1455
1455
|
};
|
|
1456
1456
|
}
|
|
1457
1457
|
|
|
@@ -1520,11 +1520,11 @@ EnterNode.prototype = {
|
|
|
1520
1520
|
insertBefore: function(child, next) {
|
|
1521
1521
|
return this._parent.insertBefore(child, next);
|
|
1522
1522
|
},
|
|
1523
|
-
querySelector: function(
|
|
1524
|
-
return this._parent.querySelector(
|
|
1523
|
+
querySelector: function(selector2) {
|
|
1524
|
+
return this._parent.querySelector(selector2);
|
|
1525
1525
|
},
|
|
1526
|
-
querySelectorAll: function(
|
|
1527
|
-
return this._parent.querySelectorAll(
|
|
1526
|
+
querySelectorAll: function(selector2) {
|
|
1527
|
+
return this._parent.querySelectorAll(selector2);
|
|
1528
1528
|
}
|
|
1529
1529
|
};
|
|
1530
1530
|
|
|
@@ -2135,8 +2135,8 @@ Selection.prototype = selection.prototype = {
|
|
|
2135
2135
|
var selection_default = selection;
|
|
2136
2136
|
|
|
2137
2137
|
// node_modules/d3-selection/src/select.js
|
|
2138
|
-
function select_default2(
|
|
2139
|
-
return typeof
|
|
2138
|
+
function select_default2(selector2) {
|
|
2139
|
+
return typeof selector2 === "string" ? new Selection([[document.querySelector(selector2)]], [document.documentElement]) : new Selection([[selector2]], root);
|
|
2140
2140
|
}
|
|
2141
2141
|
|
|
2142
2142
|
// node_modules/d3-selection/src/sourceEvent.js
|
|
@@ -4871,6 +4871,28 @@ var addEdge = (edgeParams, edges, options = {}) => {
|
|
|
4871
4871
|
}
|
|
4872
4872
|
return edges.concat(edge);
|
|
4873
4873
|
};
|
|
4874
|
+
var reconnectEdge = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
|
|
4875
|
+
const { id: oldEdgeId, ...rest } = oldEdge;
|
|
4876
|
+
if (!newConnection.source || !newConnection.target) {
|
|
4877
|
+
options.onError?.("006", errorMessages["error006"]());
|
|
4878
|
+
return edges;
|
|
4879
|
+
}
|
|
4880
|
+
const foundEdge = edges.find((e) => e.id === oldEdge.id);
|
|
4881
|
+
if (!foundEdge) {
|
|
4882
|
+
options.onError?.("007", errorMessages["error007"](oldEdgeId));
|
|
4883
|
+
return edges;
|
|
4884
|
+
}
|
|
4885
|
+
const edgeIdGenerator = options.getEdgeId || getEdgeId;
|
|
4886
|
+
const edge = {
|
|
4887
|
+
...rest,
|
|
4888
|
+
id: options.shouldReplaceId ? edgeIdGenerator(newConnection) : oldEdgeId,
|
|
4889
|
+
source: newConnection.source,
|
|
4890
|
+
target: newConnection.target,
|
|
4891
|
+
sourceHandle: newConnection.sourceHandle,
|
|
4892
|
+
targetHandle: newConnection.targetHandle
|
|
4893
|
+
};
|
|
4894
|
+
return edges.filter((e) => e.id !== oldEdgeId).concat(edge);
|
|
4895
|
+
};
|
|
4874
4896
|
function getStraightPath({ sourceX, sourceY, targetX, targetY }) {
|
|
4875
4897
|
const [labelX, labelY, offsetX, offsetY] = getEdgeCenter({
|
|
4876
4898
|
sourceX,
|
|
@@ -5128,6 +5150,40 @@ function createMarkerIds(edges, { id: id2, defaultColor, defaultMarkerStart, def
|
|
|
5128
5150
|
return markers;
|
|
5129
5151
|
}, []).sort((a, b) => a.id.localeCompare(b.id));
|
|
5130
5152
|
}
|
|
5153
|
+
function getNodeToolbarTransform(nodeRect, viewport, position, offset, align) {
|
|
5154
|
+
let alignmentOffset = 0.5;
|
|
5155
|
+
if (align === "start") {
|
|
5156
|
+
alignmentOffset = 0;
|
|
5157
|
+
} else if (align === "end") {
|
|
5158
|
+
alignmentOffset = 1;
|
|
5159
|
+
}
|
|
5160
|
+
let pos = [
|
|
5161
|
+
(nodeRect.x + nodeRect.width * alignmentOffset) * viewport.zoom + viewport.x,
|
|
5162
|
+
nodeRect.y * viewport.zoom + viewport.y - offset
|
|
5163
|
+
];
|
|
5164
|
+
let shift = [-100 * alignmentOffset, -100];
|
|
5165
|
+
switch (position) {
|
|
5166
|
+
case Position.Right:
|
|
5167
|
+
pos = [
|
|
5168
|
+
(nodeRect.x + nodeRect.width) * viewport.zoom + viewport.x + offset,
|
|
5169
|
+
(nodeRect.y + nodeRect.height * alignmentOffset) * viewport.zoom + viewport.y
|
|
5170
|
+
];
|
|
5171
|
+
shift = [0, -100 * alignmentOffset];
|
|
5172
|
+
break;
|
|
5173
|
+
case Position.Bottom:
|
|
5174
|
+
pos[1] = (nodeRect.y + nodeRect.height) * viewport.zoom + viewport.y + offset;
|
|
5175
|
+
shift[1] = 0;
|
|
5176
|
+
break;
|
|
5177
|
+
case Position.Left:
|
|
5178
|
+
pos = [
|
|
5179
|
+
nodeRect.x * viewport.zoom + viewport.x - offset,
|
|
5180
|
+
(nodeRect.y + nodeRect.height * alignmentOffset) * viewport.zoom + viewport.y
|
|
5181
|
+
];
|
|
5182
|
+
shift = [-100, -100 * alignmentOffset];
|
|
5183
|
+
break;
|
|
5184
|
+
}
|
|
5185
|
+
return `translate(${pos[0]}px, ${pos[1]}px) translate(${shift[0]}%, ${shift[1]}%)`;
|
|
5186
|
+
}
|
|
5131
5187
|
var SELECTED_NODE_Z = 1e3;
|
|
5132
5188
|
var ROOT_PARENT_Z_INCREMENT = 10;
|
|
5133
5189
|
var defaultOptions = {
|
|
@@ -5495,10 +5551,10 @@ function isParentSelected(node, nodeLookup) {
|
|
|
5495
5551
|
}
|
|
5496
5552
|
return isParentSelected(parentNode, nodeLookup);
|
|
5497
5553
|
}
|
|
5498
|
-
function hasSelector(target,
|
|
5554
|
+
function hasSelector(target, selector2, domNode) {
|
|
5499
5555
|
let current = target;
|
|
5500
5556
|
do {
|
|
5501
|
-
if (current?.matches?.(
|
|
5557
|
+
if (current?.matches?.(selector2))
|
|
5502
5558
|
return true;
|
|
5503
5559
|
if (current === domNode)
|
|
5504
5560
|
return false;
|
|
@@ -6456,6 +6512,8 @@ var ResizeControlVariant;
|
|
|
6456
6512
|
ResizeControlVariant2["Line"] = "line";
|
|
6457
6513
|
ResizeControlVariant2["Handle"] = "handle";
|
|
6458
6514
|
})(ResizeControlVariant || (ResizeControlVariant = {}));
|
|
6515
|
+
var XY_RESIZER_HANDLE_POSITIONS = ["top-left", "top-right", "bottom-left", "bottom-right"];
|
|
6516
|
+
var XY_RESIZER_LINE_POSITIONS = ["top", "right", "bottom", "left"];
|
|
6459
6517
|
function getResizeDirection({ width, prevWidth, height, prevHeight, affectsX, affectsY }) {
|
|
6460
6518
|
const deltaWidth = width - prevWidth;
|
|
6461
6519
|
const deltaHeight = height - prevHeight;
|
|
@@ -6812,7 +6870,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
|
|
|
6812
6870
|
destroy
|
|
6813
6871
|
};
|
|
6814
6872
|
}
|
|
6815
|
-
function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnapshot,
|
|
6873
|
+
function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnapshot, selector2, isEqual) {
|
|
6816
6874
|
const instRef = ReactExports.useRef(null);
|
|
6817
6875
|
let inst;
|
|
6818
6876
|
if (instRef.current === null) {
|
|
@@ -6829,7 +6887,7 @@ function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnaps
|
|
|
6829
6887
|
if (!hasMemo) {
|
|
6830
6888
|
hasMemo = true;
|
|
6831
6889
|
memoizedSnapshot = nextSnapshot;
|
|
6832
|
-
const nextSelection2 =
|
|
6890
|
+
const nextSelection2 = selector2(nextSnapshot);
|
|
6833
6891
|
if (isEqual !== void 0 && inst.hasValue) {
|
|
6834
6892
|
const currentSelection = inst.value;
|
|
6835
6893
|
if (isEqual(currentSelection, nextSelection2)) {
|
|
@@ -6845,7 +6903,7 @@ function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnaps
|
|
|
6845
6903
|
if (Object.is(prevSnapshot, nextSnapshot)) {
|
|
6846
6904
|
return prevSelection;
|
|
6847
6905
|
}
|
|
6848
|
-
const nextSelection =
|
|
6906
|
+
const nextSelection = selector2(nextSnapshot);
|
|
6849
6907
|
if (isEqual !== void 0 && isEqual(prevSelection, nextSelection)) {
|
|
6850
6908
|
memoizedSnapshot = nextSnapshot;
|
|
6851
6909
|
return prevSelection;
|
|
@@ -6858,7 +6916,7 @@ function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnaps
|
|
|
6858
6916
|
const getSnapshotWithSelector = () => memoizedSelector(getSnapshot());
|
|
6859
6917
|
const getServerSnapshotWithSelector = maybeGetServerSnapshot === null ? void 0 : () => memoizedSelector(maybeGetServerSnapshot());
|
|
6860
6918
|
return [getSnapshotWithSelector, getServerSnapshotWithSelector];
|
|
6861
|
-
}, [getSnapshot, getServerSnapshot,
|
|
6919
|
+
}, [getSnapshot, getServerSnapshot, selector2, isEqual]);
|
|
6862
6920
|
const value = ReactExports.useSyncExternalStore(subscribe, getSelection, getServerSelection);
|
|
6863
6921
|
ReactExports.useEffect(() => {
|
|
6864
6922
|
inst.hasValue = true;
|
|
@@ -6905,12 +6963,12 @@ var createStore = (createState) => createState ? createStoreImpl(createState) :
|
|
|
6905
6963
|
var { useDebugValue: useDebugValue2 } = ReactExports__default.default;
|
|
6906
6964
|
var { useSyncExternalStoreWithSelector: useSyncExternalStoreWithSelector2 } = use_sync_external_store_with_selector_default;
|
|
6907
6965
|
var identity3 = (arg) => arg;
|
|
6908
|
-
function useStoreWithEqualityFn(api,
|
|
6966
|
+
function useStoreWithEqualityFn(api, selector2 = identity3, equalityFn) {
|
|
6909
6967
|
const slice = useSyncExternalStoreWithSelector2(
|
|
6910
6968
|
api.subscribe,
|
|
6911
6969
|
api.getState,
|
|
6912
6970
|
api.getServerState || api.getInitialState,
|
|
6913
|
-
|
|
6971
|
+
selector2,
|
|
6914
6972
|
equalityFn
|
|
6915
6973
|
);
|
|
6916
6974
|
useDebugValue2(slice);
|
|
@@ -6918,7 +6976,7 @@ function useStoreWithEqualityFn(api, selector = identity3, equalityFn) {
|
|
|
6918
6976
|
}
|
|
6919
6977
|
var createWithEqualityFnImpl = (createState, defaultEqualityFn) => {
|
|
6920
6978
|
const api = createStore(createState);
|
|
6921
|
-
const useBoundStoreWithEqualityFn = (
|
|
6979
|
+
const useBoundStoreWithEqualityFn = (selector2, equalityFn = defaultEqualityFn) => useStoreWithEqualityFn(api, selector2, equalityFn);
|
|
6922
6980
|
Object.assign(useBoundStoreWithEqualityFn, api);
|
|
6923
6981
|
return useBoundStoreWithEqualityFn;
|
|
6924
6982
|
};
|
|
@@ -6964,12 +7022,12 @@ function shallow$1(objA, objB) {
|
|
|
6964
7022
|
var StoreContext = ReactExports.createContext(null);
|
|
6965
7023
|
var Provider$1 = StoreContext.Provider;
|
|
6966
7024
|
var zustandErrorMessage = errorMessages["error001"]("react");
|
|
6967
|
-
function useStore(
|
|
7025
|
+
function useStore(selector2, equalityFn) {
|
|
6968
7026
|
const store = ReactExports.useContext(StoreContext);
|
|
6969
7027
|
if (store === null) {
|
|
6970
7028
|
throw new Error(zustandErrorMessage);
|
|
6971
7029
|
}
|
|
6972
|
-
return useStoreWithEqualityFn(store,
|
|
7030
|
+
return useStoreWithEqualityFn(store, selector2, equalityFn);
|
|
6973
7031
|
}
|
|
6974
7032
|
function useStoreApi() {
|
|
6975
7033
|
const store = ReactExports.useContext(StoreContext);
|
|
@@ -7509,6 +7567,12 @@ function addEdge2(edgeParams, edges, options = {}) {
|
|
|
7509
7567
|
onError: options.onError ?? defaultOnError
|
|
7510
7568
|
});
|
|
7511
7569
|
}
|
|
7570
|
+
function reconnectEdge2(oldEdge, newConnection, edges, options = { shouldReplaceId: true }) {
|
|
7571
|
+
return reconnectEdge(oldEdge, newConnection, edges, {
|
|
7572
|
+
...options,
|
|
7573
|
+
onError: options.onError ?? defaultOnError
|
|
7574
|
+
});
|
|
7575
|
+
}
|
|
7512
7576
|
var isNode = (element) => isNodeBase(element);
|
|
7513
7577
|
var isEdge = (element) => isEdgeBase(element);
|
|
7514
7578
|
function fixedForwardRef(render) {
|
|
@@ -10161,7 +10225,69 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
|
|
|
10161
10225
|
...color2 && { [isHandleControl ? "backgroundColor" : "borderColor"]: color2 }
|
|
10162
10226
|
}, children: children2 });
|
|
10163
10227
|
}
|
|
10164
|
-
ReactExports.memo(ResizeControl);
|
|
10228
|
+
var NodeResizeControl = ReactExports.memo(ResizeControl);
|
|
10229
|
+
function NodeResizer({ nodeId, isVisible = true, handleClassName, handleStyle, lineClassName, lineStyle, color: color2, minWidth = 10, minHeight = 10, maxWidth = Number.MAX_VALUE, maxHeight = Number.MAX_VALUE, keepAspectRatio = false, autoScale = true, shouldResize, onResizeStart, onResize, onResizeEnd }) {
|
|
10230
|
+
if (!isVisible) {
|
|
10231
|
+
return null;
|
|
10232
|
+
}
|
|
10233
|
+
return jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [XY_RESIZER_LINE_POSITIONS.map((position) => jsxRuntime.jsx(NodeResizeControl, { className: lineClassName, style: lineStyle, nodeId, position, variant: ResizeControlVariant.Line, color: color2, minWidth, minHeight, maxWidth, maxHeight, onResizeStart, keepAspectRatio, autoScale, shouldResize, onResize, onResizeEnd }, position)), XY_RESIZER_HANDLE_POSITIONS.map((position) => jsxRuntime.jsx(NodeResizeControl, { className: handleClassName, style: handleStyle, nodeId, position, color: color2, minWidth, minHeight, maxWidth, maxHeight, onResizeStart, keepAspectRatio, autoScale, shouldResize, onResize, onResizeEnd }, position))] });
|
|
10234
|
+
}
|
|
10235
|
+
var selector = (state) => state.domNode?.querySelector(".react-flow__renderer");
|
|
10236
|
+
function NodeToolbarPortal({ children: children2 }) {
|
|
10237
|
+
const wrapperRef = useStore(selector);
|
|
10238
|
+
if (!wrapperRef) {
|
|
10239
|
+
return null;
|
|
10240
|
+
}
|
|
10241
|
+
return reactDom.createPortal(children2, wrapperRef);
|
|
10242
|
+
}
|
|
10243
|
+
var nodeEqualityFn = (a, b) => a?.internals.positionAbsolute.x !== b?.internals.positionAbsolute.x || a?.internals.positionAbsolute.y !== b?.internals.positionAbsolute.y || a?.measured.width !== b?.measured.width || a?.measured.height !== b?.measured.height || a?.selected !== b?.selected || a?.internals.z !== b?.internals.z;
|
|
10244
|
+
var nodesEqualityFn = (a, b) => {
|
|
10245
|
+
if (a.size !== b.size) {
|
|
10246
|
+
return false;
|
|
10247
|
+
}
|
|
10248
|
+
for (const [key, node] of a) {
|
|
10249
|
+
if (nodeEqualityFn(node, b.get(key))) {
|
|
10250
|
+
return false;
|
|
10251
|
+
}
|
|
10252
|
+
}
|
|
10253
|
+
return true;
|
|
10254
|
+
};
|
|
10255
|
+
var storeSelector = (state) => ({
|
|
10256
|
+
x: state.transform[0],
|
|
10257
|
+
y: state.transform[1],
|
|
10258
|
+
zoom: state.transform[2],
|
|
10259
|
+
selectedNodesCount: state.nodes.filter((node) => node.selected).length
|
|
10260
|
+
});
|
|
10261
|
+
function NodeToolbar({ nodeId, children: children2, className, style: style2, isVisible, position = Position.Top, offset = 10, align = "center", ...rest }) {
|
|
10262
|
+
const contextNodeId = useNodeId();
|
|
10263
|
+
const nodesSelector = ReactExports.useCallback((state) => {
|
|
10264
|
+
const nodeIds = Array.isArray(nodeId) ? nodeId : [nodeId || contextNodeId || ""];
|
|
10265
|
+
const internalNodes = nodeIds.reduce((res, id2) => {
|
|
10266
|
+
const node = state.nodeLookup.get(id2);
|
|
10267
|
+
if (node) {
|
|
10268
|
+
res.set(node.id, node);
|
|
10269
|
+
}
|
|
10270
|
+
return res;
|
|
10271
|
+
}, /* @__PURE__ */ new Map());
|
|
10272
|
+
return internalNodes;
|
|
10273
|
+
}, [nodeId, contextNodeId]);
|
|
10274
|
+
const nodes = useStore(nodesSelector, nodesEqualityFn);
|
|
10275
|
+
const { x, y, zoom, selectedNodesCount } = useStore(storeSelector, shallow$1);
|
|
10276
|
+
const isActive = typeof isVisible === "boolean" ? isVisible : nodes.size === 1 && nodes.values().next().value?.selected && selectedNodesCount === 1;
|
|
10277
|
+
if (!isActive || !nodes.size) {
|
|
10278
|
+
return null;
|
|
10279
|
+
}
|
|
10280
|
+
const nodeRect = getInternalNodesBounds(nodes);
|
|
10281
|
+
const nodesArray = Array.from(nodes.values());
|
|
10282
|
+
const zIndex = Math.max(...nodesArray.map((node) => node.internals.z + 1));
|
|
10283
|
+
const wrapperStyle2 = {
|
|
10284
|
+
position: "absolute",
|
|
10285
|
+
transform: getNodeToolbarTransform(nodeRect, { x, y, zoom }, position, offset, align),
|
|
10286
|
+
zIndex,
|
|
10287
|
+
...style2
|
|
10288
|
+
};
|
|
10289
|
+
return jsxRuntime.jsx(NodeToolbarPortal, { children: jsxRuntime.jsx("div", { style: wrapperStyle2, className: cc(["react-flow__node-toolbar", className]), ...rest, "data-id": nodesArray.reduce((acc, node) => `${acc}${node.id} `, "").trim(), children: children2 }) });
|
|
10290
|
+
}
|
|
10165
10291
|
function NodeShellInner({
|
|
10166
10292
|
node,
|
|
10167
10293
|
accent,
|
|
@@ -11219,6 +11345,7 @@ function toSchemaNode(n) {
|
|
|
11219
11345
|
const data = n.data ?? {};
|
|
11220
11346
|
const kindName = data.kind ?? n.type ?? "custom";
|
|
11221
11347
|
const ports = resolveNodePorts(n, getNodeKind(kindName) ?? void 0);
|
|
11348
|
+
const node = n;
|
|
11222
11349
|
return {
|
|
11223
11350
|
id: n.id,
|
|
11224
11351
|
kind: kindName,
|
|
@@ -11227,7 +11354,14 @@ function toSchemaNode(n) {
|
|
|
11227
11354
|
description: data.description,
|
|
11228
11355
|
config: data.config,
|
|
11229
11356
|
inputs: ports.inputs,
|
|
11230
|
-
outputs: ports.outputs
|
|
11357
|
+
outputs: ports.outputs,
|
|
11358
|
+
// Visual layout — only when explicitly set (never persist auto-`measured`
|
|
11359
|
+
// dimensions, which are derived, not authored).
|
|
11360
|
+
...node.parentId ? { parentId: node.parentId } : {},
|
|
11361
|
+
...node.extent ? { extent: node.extent } : {},
|
|
11362
|
+
...typeof node.width === "number" ? { width: node.width } : {},
|
|
11363
|
+
...typeof node.height === "number" ? { height: node.height } : {},
|
|
11364
|
+
...node.style ? { style: node.style } : {}
|
|
11231
11365
|
};
|
|
11232
11366
|
}
|
|
11233
11367
|
function toSchemaEdge(e) {
|
|
@@ -11240,9 +11374,13 @@ function toSchemaEdge(e) {
|
|
|
11240
11374
|
label: typeof e.label === "string" ? e.label : void 0
|
|
11241
11375
|
};
|
|
11242
11376
|
}
|
|
11377
|
+
function migrateSchema(schema) {
|
|
11378
|
+
return schema;
|
|
11379
|
+
}
|
|
11243
11380
|
function importWorkflow(schema, options = {}) {
|
|
11244
11381
|
const issues = [];
|
|
11245
11382
|
const lenient = options.lenient === true;
|
|
11383
|
+
schema = migrateSchema(schema);
|
|
11246
11384
|
if (!schema || typeof schema !== "object") {
|
|
11247
11385
|
return { ok: false, graph: { nodes: [], edges: [] }, issues: [{ level: "error", message: "Schema is not an object." }] };
|
|
11248
11386
|
}
|
|
@@ -11276,6 +11414,12 @@ function importWorkflow(schema, options = {}) {
|
|
|
11276
11414
|
id: n.id,
|
|
11277
11415
|
type: kindId,
|
|
11278
11416
|
position: { x: n.position?.x ?? 0, y: n.position?.y ?? 0 },
|
|
11417
|
+
// Rehydrate visual layout onto the node's top level (where xyflow reads it).
|
|
11418
|
+
...n.parentId ? { parentId: n.parentId } : {},
|
|
11419
|
+
...n.extent ? { extent: n.extent } : {},
|
|
11420
|
+
...typeof n.width === "number" ? { width: n.width } : {},
|
|
11421
|
+
...typeof n.height === "number" ? { height: n.height } : {},
|
|
11422
|
+
...n.style ? { style: n.style } : {},
|
|
11279
11423
|
data: {
|
|
11280
11424
|
kind: kindId,
|
|
11281
11425
|
label: n.label ?? kind?.label ?? n.kind,
|
|
@@ -11380,10 +11524,20 @@ function RegistryNodeInner(props) {
|
|
|
11380
11524
|
"ff-node",
|
|
11381
11525
|
`ff-node--status-${status}`,
|
|
11382
11526
|
`ff-node--cat-${kind.category}`,
|
|
11383
|
-
props.selected ? "ff-node--selected" : ""
|
|
11527
|
+
props.selected ? "ff-node--selected" : "",
|
|
11528
|
+
kind.resizable ? "ff-node--resizable" : ""
|
|
11384
11529
|
].filter(Boolean).join(" "),
|
|
11385
11530
|
style: { borderColor: props.selected ? accent : void 0 },
|
|
11386
11531
|
children: [
|
|
11532
|
+
kind.resizable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11533
|
+
NodeResizer,
|
|
11534
|
+
{
|
|
11535
|
+
isVisible: props.selected ?? false,
|
|
11536
|
+
color: accent,
|
|
11537
|
+
...typeof kind.resizable === "object" ? kind.resizable : {}
|
|
11538
|
+
}
|
|
11539
|
+
),
|
|
11540
|
+
kind.toolbar && /* @__PURE__ */ jsxRuntime.jsx(NodeToolbar, { isVisible: props.selected ?? false, children: kind.toolbar({ nodeId: props.id, config, selected: props.selected ?? false }) }),
|
|
11387
11541
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ff-node__header", style: { background: accent }, children: [
|
|
11388
11542
|
kind.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-node__icon", "aria-hidden": true, children: kind.icon }),
|
|
11389
11543
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-node__tag", children: kind.label.toUpperCase() }),
|
|
@@ -11523,6 +11677,65 @@ function duplicateNode(node, id2, offset = 40) {
|
|
|
11523
11677
|
data: JSON.parse(JSON.stringify(node.data ?? {}))
|
|
11524
11678
|
};
|
|
11525
11679
|
}
|
|
11680
|
+
function cloneSubgraph(nodes, edges, opts) {
|
|
11681
|
+
const offset = opts.offset ?? 40;
|
|
11682
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
11683
|
+
for (const n of nodes) idMap.set(n.id, opts.makeId());
|
|
11684
|
+
const clonedNodes = nodes.map((n) => {
|
|
11685
|
+
const cloned = duplicateNode(n, idMap.get(n.id), offset);
|
|
11686
|
+
const parentId = n.parentId;
|
|
11687
|
+
if (parentId && idMap.has(parentId)) cloned.parentId = idMap.get(parentId);
|
|
11688
|
+
else if (parentId) delete cloned.parentId;
|
|
11689
|
+
return cloned;
|
|
11690
|
+
});
|
|
11691
|
+
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) }));
|
|
11692
|
+
return { nodes: clonedNodes, edges: clonedEdges, idMap };
|
|
11693
|
+
}
|
|
11694
|
+
function reconnectEdge3(edges, oldEdge, newConnection) {
|
|
11695
|
+
return reconnectEdge2(oldEdge, newConnection, edges, { shouldReplaceId: false });
|
|
11696
|
+
}
|
|
11697
|
+
var nodeW = (n) => n.width ?? n.measured?.width ?? 0;
|
|
11698
|
+
var nodeH = (n) => n.height ?? n.measured?.height ?? 0;
|
|
11699
|
+
function alignNodes(nodes, edge) {
|
|
11700
|
+
if (nodes.length < 2) return nodes;
|
|
11701
|
+
const minL = Math.min(...nodes.map((n) => n.position.x));
|
|
11702
|
+
const maxR = Math.max(...nodes.map((n) => n.position.x + nodeW(n)));
|
|
11703
|
+
const minT = Math.min(...nodes.map((n) => n.position.y));
|
|
11704
|
+
const maxB = Math.max(...nodes.map((n) => n.position.y + nodeH(n)));
|
|
11705
|
+
const cx = (minL + maxR) / 2;
|
|
11706
|
+
const cy = (minT + maxB) / 2;
|
|
11707
|
+
return nodes.map((n) => {
|
|
11708
|
+
let { x, y } = n.position;
|
|
11709
|
+
if (edge === "left") x = minL;
|
|
11710
|
+
else if (edge === "right") x = maxR - nodeW(n);
|
|
11711
|
+
else if (edge === "hcenter") x = cx - nodeW(n) / 2;
|
|
11712
|
+
else if (edge === "top") y = minT;
|
|
11713
|
+
else if (edge === "bottom") y = maxB - nodeH(n);
|
|
11714
|
+
else if (edge === "vcenter") y = cy - nodeH(n) / 2;
|
|
11715
|
+
return { ...n, position: { x, y } };
|
|
11716
|
+
});
|
|
11717
|
+
}
|
|
11718
|
+
function distributeNodes(nodes, axis) {
|
|
11719
|
+
if (nodes.length < 3) return nodes;
|
|
11720
|
+
const size = (n) => axis === "h" ? nodeW(n) : nodeH(n);
|
|
11721
|
+
const coord = (n) => axis === "h" ? n.position.x : n.position.y;
|
|
11722
|
+
const sorted = [...nodes].sort((a, b) => coord(a) - coord(b));
|
|
11723
|
+
const start2 = coord(sorted[0]);
|
|
11724
|
+
const last = sorted[sorted.length - 1];
|
|
11725
|
+
const end = coord(last) + size(last);
|
|
11726
|
+
const totalSize = sorted.reduce((s, n) => s + size(n), 0);
|
|
11727
|
+
const gap = (end - start2 - totalSize) / (sorted.length - 1);
|
|
11728
|
+
const posById = /* @__PURE__ */ new Map();
|
|
11729
|
+
let cursor = start2;
|
|
11730
|
+
for (const n of sorted) {
|
|
11731
|
+
posById.set(n.id, cursor);
|
|
11732
|
+
cursor += size(n) + gap;
|
|
11733
|
+
}
|
|
11734
|
+
return nodes.map((n) => {
|
|
11735
|
+
const p = posById.get(n.id);
|
|
11736
|
+
return { ...n, position: axis === "h" ? { ...n.position, x: p } : { ...n.position, y: p } };
|
|
11737
|
+
});
|
|
11738
|
+
}
|
|
11526
11739
|
var FlowEditorContext = ReactExports.createContext(null);
|
|
11527
11740
|
var FlowEditorProvider = FlowEditorContext.Provider;
|
|
11528
11741
|
function useFlowEditor() {
|
|
@@ -11692,6 +11905,89 @@ function FlowEditorInner({
|
|
|
11692
11905
|
},
|
|
11693
11906
|
[flow, onEdgeDelete, confirmDelete]
|
|
11694
11907
|
);
|
|
11908
|
+
const selectedNodes = ReactExports.useMemo(() => flow.nodes.filter((n) => n.selected), [flow.nodes]);
|
|
11909
|
+
const selectedIds = ReactExports.useMemo(() => selectedNodes.map((n) => n.id), [selectedNodes]);
|
|
11910
|
+
const clipboard = ReactExports.useRef(null);
|
|
11911
|
+
const copySelection = ReactExports.useCallback(() => {
|
|
11912
|
+
const sel = flow.nodes.filter((n) => n.selected);
|
|
11913
|
+
if (sel.length === 0) return;
|
|
11914
|
+
const ids = new Set(sel.map((n) => n.id));
|
|
11915
|
+
const edges = flow.edges.filter((e) => ids.has(e.source) && ids.has(e.target));
|
|
11916
|
+
clipboard.current = { nodes: sel.map((n) => ({ ...n })), edges: edges.map((e) => ({ ...e })) };
|
|
11917
|
+
}, [flow]);
|
|
11918
|
+
const pasteClipboard = ReactExports.useCallback(
|
|
11919
|
+
(at) => {
|
|
11920
|
+
const clip = clipboard.current;
|
|
11921
|
+
if (!clip || clip.nodes.length === 0) return;
|
|
11922
|
+
const { nodes: clones, edges: cloneEdges } = cloneSubgraph(clip.nodes, clip.edges, { makeId: newNodeId, offset: 40 });
|
|
11923
|
+
let placed = clones;
|
|
11924
|
+
if (at) {
|
|
11925
|
+
const minX = Math.min(...clones.map((n) => n.position.x));
|
|
11926
|
+
const minY = Math.min(...clones.map((n) => n.position.y));
|
|
11927
|
+
placed = clones.map((n) => ({ ...n, position: { x: n.position.x - minX + at.x, y: n.position.y - minY + at.y } }));
|
|
11928
|
+
}
|
|
11929
|
+
flow.setGraph({
|
|
11930
|
+
nodes: [...flow.nodes.map((n) => ({ ...n, selected: false })), ...placed.map((n) => ({ ...n, selected: true }))],
|
|
11931
|
+
edges: [...flow.edges, ...cloneEdges]
|
|
11932
|
+
});
|
|
11933
|
+
},
|
|
11934
|
+
[flow]
|
|
11935
|
+
);
|
|
11936
|
+
const duplicateSelected = ReactExports.useCallback(() => {
|
|
11937
|
+
const sel = flow.nodes.filter((n) => n.selected);
|
|
11938
|
+
if (sel.length === 0) return;
|
|
11939
|
+
const ids = new Set(sel.map((n) => n.id));
|
|
11940
|
+
const internal2 = flow.edges.filter((e) => ids.has(e.source) && ids.has(e.target));
|
|
11941
|
+
const { nodes: clones, edges: cloneEdges } = cloneSubgraph(sel, internal2, { makeId: newNodeId, offset: 40 });
|
|
11942
|
+
flow.setGraph({
|
|
11943
|
+
nodes: [...flow.nodes.map((n) => ({ ...n, selected: false })), ...clones.map((n) => ({ ...n, selected: true }))],
|
|
11944
|
+
edges: [...flow.edges, ...cloneEdges]
|
|
11945
|
+
});
|
|
11946
|
+
}, [flow]);
|
|
11947
|
+
const alignSelected = ReactExports.useCallback(
|
|
11948
|
+
(edge) => {
|
|
11949
|
+
const sel = flow.nodes.filter((n) => n.selected);
|
|
11950
|
+
if (sel.length < 2) return;
|
|
11951
|
+
const byId = new Map(alignNodes(sel, edge).map((n) => [n.id, n]));
|
|
11952
|
+
flow.setNodes((all) => all.map((n) => byId.get(n.id) ?? n));
|
|
11953
|
+
},
|
|
11954
|
+
[flow]
|
|
11955
|
+
);
|
|
11956
|
+
const distributeSelected = ReactExports.useCallback(
|
|
11957
|
+
(axis) => {
|
|
11958
|
+
const sel = flow.nodes.filter((n) => n.selected);
|
|
11959
|
+
if (sel.length < 3) return;
|
|
11960
|
+
const byId = new Map(distributeNodes(sel, axis).map((n) => [n.id, n]));
|
|
11961
|
+
flow.setNodes((all) => all.map((n) => byId.get(n.id) ?? n));
|
|
11962
|
+
},
|
|
11963
|
+
[flow]
|
|
11964
|
+
);
|
|
11965
|
+
const onReconnect = ReactExports.useCallback(
|
|
11966
|
+
(oldEdge, conn) => flow.setEdges((eds) => reconnectEdge3(eds, oldEdge, conn)),
|
|
11967
|
+
[flow]
|
|
11968
|
+
);
|
|
11969
|
+
ReactExports.useEffect(() => {
|
|
11970
|
+
const onKey = (e) => {
|
|
11971
|
+
const t = e.target;
|
|
11972
|
+
if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
|
|
11973
|
+
if (!(e.ctrlKey || e.metaKey)) return;
|
|
11974
|
+
const key = e.key.toLowerCase();
|
|
11975
|
+
if (key === "c") copySelection();
|
|
11976
|
+
else if (key === "x") {
|
|
11977
|
+
e.preventDefault();
|
|
11978
|
+
copySelection();
|
|
11979
|
+
deleteNodes(selectedIds);
|
|
11980
|
+
} else if (key === "v") {
|
|
11981
|
+
e.preventDefault();
|
|
11982
|
+
pasteClipboard();
|
|
11983
|
+
} else if (key === "d") {
|
|
11984
|
+
e.preventDefault();
|
|
11985
|
+
duplicateSelected();
|
|
11986
|
+
}
|
|
11987
|
+
};
|
|
11988
|
+
window.addEventListener("keydown", onKey);
|
|
11989
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
11990
|
+
}, [copySelection, pasteClipboard, duplicateSelected, deleteNodes, selectedIds]);
|
|
11695
11991
|
const api = ReactExports.useMemo(() => {
|
|
11696
11992
|
const toWorkflow = () => exportWorkflow({ nodes: flow.nodes, edges: flow.edges }, metadata);
|
|
11697
11993
|
return {
|
|
@@ -11702,6 +11998,8 @@ function FlowEditorInner({
|
|
|
11702
11998
|
selected: selected2,
|
|
11703
11999
|
selectedEdgeId,
|
|
11704
12000
|
selectedEdge,
|
|
12001
|
+
selectedIds,
|
|
12002
|
+
selectedNodes,
|
|
11705
12003
|
running: runner.running,
|
|
11706
12004
|
statuses: runner.statuses,
|
|
11707
12005
|
select: setSelectedId,
|
|
@@ -11722,6 +12020,15 @@ function FlowEditorInner({
|
|
|
11722
12020
|
return copy.id;
|
|
11723
12021
|
},
|
|
11724
12022
|
setGraph: (graph) => flow.setGraph(graph),
|
|
12023
|
+
duplicateSelected,
|
|
12024
|
+
alignSelected,
|
|
12025
|
+
distributeSelected,
|
|
12026
|
+
copy: copySelection,
|
|
12027
|
+
cut: () => {
|
|
12028
|
+
copySelection();
|
|
12029
|
+
deleteNodes(selectedIds);
|
|
12030
|
+
},
|
|
12031
|
+
paste: pasteClipboard,
|
|
11725
12032
|
run: () => runner.run({ nodes: flow.nodes, edges: flow.edges }, executors),
|
|
11726
12033
|
cancel: runner.cancel,
|
|
11727
12034
|
reset: runner.reset,
|
|
@@ -11734,7 +12041,7 @@ function FlowEditorInner({
|
|
|
11734
12041
|
canUndo: hist.canUndo,
|
|
11735
12042
|
canRedo: hist.canRedo
|
|
11736
12043
|
};
|
|
11737
|
-
}, [flow, selectedId, selected2, selectedEdgeId, selectedEdge, runner, executors, metadata, addNode, deleteNodes, deleteEdges, hist, rf]);
|
|
12044
|
+
}, [flow, selectedId, selected2, selectedEdgeId, selectedEdge, selectedIds, selectedNodes, runner, executors, metadata, addNode, deleteNodes, deleteEdges, duplicateSelected, alignSelected, distributeSelected, copySelection, pasteClipboard, hist, rf]);
|
|
11738
12045
|
ReactExports.useImperativeHandle(apiRef, () => api, [api]);
|
|
11739
12046
|
const dropHandlers = paletteDropHandlers((kindName, evt) => {
|
|
11740
12047
|
const point = rf.screenToFlowPosition({ x: evt.clientX, y: evt.clientY });
|
|
@@ -11794,6 +12101,8 @@ function FlowEditorInner({
|
|
|
11794
12101
|
onNodesChange: flow.onNodesChange,
|
|
11795
12102
|
onEdgesChange: flow.onEdgesChange,
|
|
11796
12103
|
onConnect: flow.onConnect,
|
|
12104
|
+
onReconnect,
|
|
12105
|
+
edgesReconnectable: true,
|
|
11797
12106
|
onNodeDragStart: hist.onNodeDragStart,
|
|
11798
12107
|
onNodeClick: handleNodeClick2,
|
|
11799
12108
|
onNodeContextMenu: builtins.contextMenu === false ? void 0 : handleNodeContextMenu,
|
|
@@ -12083,9 +12392,11 @@ exports.SubgraphNode = SubgraphNode;
|
|
|
12083
12392
|
exports.TriggerNode = TriggerNode;
|
|
12084
12393
|
exports.WORKFLOW_SCHEMA_URL = WORKFLOW_SCHEMA_URL;
|
|
12085
12394
|
exports.WORKFLOW_SCHEMA_VERSION = WORKFLOW_SCHEMA_VERSION;
|
|
12395
|
+
exports.alignNodes = alignNodes;
|
|
12086
12396
|
exports.applyStatusesToNodes = applyStatusesToNodes;
|
|
12087
12397
|
exports.buildNodeTypes = buildNodeTypes;
|
|
12088
12398
|
exports.categoryAccent = categoryAccent;
|
|
12399
|
+
exports.cloneSubgraph = cloneSubgraph;
|
|
12089
12400
|
exports.createConnectionValidator = createConnectionValidator;
|
|
12090
12401
|
exports.createHistory = createHistory;
|
|
12091
12402
|
exports.decodePause = decodePause;
|
|
@@ -12093,6 +12404,7 @@ exports.defaultConfigFor = defaultConfigFor;
|
|
|
12093
12404
|
exports.defaultNodeTypes = defaultNodeTypes;
|
|
12094
12405
|
exports.defaultPortCompatibility = defaultPortCompatibility;
|
|
12095
12406
|
exports.defineNode = defineNode;
|
|
12407
|
+
exports.distributeNodes = distributeNodes;
|
|
12096
12408
|
exports.encodePause = encodePause;
|
|
12097
12409
|
exports.exportWorkflow = exportWorkflow;
|
|
12098
12410
|
exports.getNodeKind = getNodeKind;
|
|
@@ -12101,10 +12413,12 @@ exports.importWorkflow = importWorkflow;
|
|
|
12101
12413
|
exports.isPause = isPause;
|
|
12102
12414
|
exports.isRichInputEnabled = isRichInputEnabled;
|
|
12103
12415
|
exports.listNodeKinds = listNodeKinds;
|
|
12416
|
+
exports.migrateSchema = migrateSchema;
|
|
12104
12417
|
exports.onNodeKindsChanged = onNodeKindsChanged;
|
|
12105
12418
|
exports.onRichInputAdapterChanged = onRichInputAdapterChanged;
|
|
12106
12419
|
exports.paletteDropHandlers = paletteDropHandlers;
|
|
12107
12420
|
exports.pauseForHuman = pauseForHuman;
|
|
12421
|
+
exports.reconnectEdge = reconnectEdge3;
|
|
12108
12422
|
exports.registerBuiltinKinds = registerBuiltinKinds;
|
|
12109
12423
|
exports.registerNodeKind = registerNodeKind;
|
|
12110
12424
|
exports.registerRichInputAdapter = registerRichInputAdapter;
|