@dschz/solid-flow 0.3.0-next.0 → 0.3.0-next.1
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/index/index.d.ts +202 -246
- package/dist/index/index.js +1548 -1229
- package/dist/index/index.jsx +1278 -959
- package/dist/styles/index.css +747 -12
- package/package.json +1 -2
package/dist/index/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Dynamic, Portal, addEvent, claimElement, className, createComponent, delegateEvents, effect, insert, isServer, memo, mergeProps, ref, setAttribute, setStyleProperty, spread, style, template } from "@solidjs/web";
|
|
2
|
-
import { For, Show, createContext, createEffect, createMemo,
|
|
3
|
-
import { ReactiveMap } from "@solid-primitives/map";
|
|
2
|
+
import { For, Show, createContext, createEffect, createMemo, createProjection, createSignal, createStore, flush, mapArray, merge, omit, onCleanup, onSettled, snapshot, untrack, useContext } from "solid-js";
|
|
4
3
|
import { createMediaQuery } from "@solid-primitives/media";
|
|
5
|
-
import { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, Position as Position$1, ResizeControlVariant, SelectionMode, SelectionMode as SelectionMode$1, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, addEdge as addEdge$1, areConnectionMapsEqual, calcAutoPan, calculateNodePosition, clampPosition, clampPositionToParent, createDevWarn, createMarkerIds, elementSelectionKeys, evaluateAbsolutePosition, fitViewport, getBezierEdgeCenter, getBezierPath, getBezierPath as getBezierPath$1, getBoundsOfRects, getConnectedEdges, getConnectionStatus, getEdgeCenter, getEdgePosition, getEdgeToolbarTransform, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHostForElement, getIncomers, getInternalNodesBounds, getMarkerId, getNodeDimensions, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesBounds as getNodesBounds$1, getNodesInside, getOutgoers, getOverlappingArea, getSmoothStepPath, getSmoothStepPath as getSmoothStepPath$1, getStraightPath, getStraightPath as getStraightPath$1, getViewportForBounds, getViewportForBounds as getViewportForBounds$1, handleConnectionChange, infiniteExtent, initialConnection, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isNodeBase, isNumeric, isRectObject, mergeAriaLabelConfig, nodeHasDimensions, nodeToRect, panBy, pointToRendererPoint, rendererPointToPoint, shallowNodeData, snapPosition
|
|
4
|
+
import { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, Position as Position$1, ResizeControlVariant, SelectionMode, SelectionMode as SelectionMode$1, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, addEdge as addEdge$1, areConnectionMapsEqual, calcAutoPan, calculateNodePosition, clampPosition, clampPositionToParent, createDevWarn, createMarkerIds, elementSelectionKeys, evaluateAbsolutePosition, fitViewport, getBezierEdgeCenter, getBezierPath, getBezierPath as getBezierPath$1, getBoundsOfRects, getConnectedEdges, getConnectionStatus, getDimensions, getEdgeCenter, getEdgePosition, getEdgeToolbarTransform, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomers, getInternalNodesBounds, getMarkerId, getNodeDimensions, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesBounds as getNodesBounds$1, getNodesInside, getOutgoers, getOverlappingArea, getSmoothStepPath, getSmoothStepPath as getSmoothStepPath$1, getStraightPath, getStraightPath as getStraightPath$1, getViewportForBounds, getViewportForBounds as getViewportForBounds$1, handleConnectionChange, infiniteExtent, initialConnection, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isNodeBase, isNumeric, isRectObject, mergeAriaLabelConfig, nodeHasDimensions, nodeToRect, panBy, pointToRendererPoint, rendererPointToPoint, shallowNodeData, snapPosition } from "@xyflow/system";
|
|
6
5
|
import { createEventListener, createEventListenerMap } from "@solid-primitives/event-listener";
|
|
7
6
|
//#region src/components/contexts/edgeId.tsx
|
|
8
7
|
const EdgeIdContext = createContext(null);
|
|
@@ -280,7 +279,7 @@ const EdgeReconnectAnchor = (props) => {
|
|
|
280
279
|
style: {}
|
|
281
280
|
}), rest = omit(_props, "type", "class", "style", "position", "size", "reconnecting", "children"), { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow(), edgeId = useEdgeId(), [reconnecting, setReconnecting] = createSignal(!1);
|
|
282
281
|
if (!edgeId()) throw Error("[solid-flow]: EdgeReconnectAnchor must be used within an Edge component");
|
|
283
|
-
let edge = () => edgeLookup
|
|
282
|
+
let edge = () => edgeLookup[edgeId()], onPointerDown = (event) => {
|
|
284
283
|
if (event.button !== 0) return;
|
|
285
284
|
setReconnecting(!0), store.onReconnectStart?.(event, edge(), _props.type);
|
|
286
285
|
let opposite = _props.type === "target" ? {
|
|
@@ -825,689 +824,335 @@ const EdgeWrapper = (props) => {
|
|
|
825
824
|
return props.style;
|
|
826
825
|
}
|
|
827
826
|
});
|
|
828
|
-
},
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
827
|
+
}, getDefaultFlowStateProps = () => ({
|
|
828
|
+
id: "1",
|
|
829
|
+
nodes: [],
|
|
830
|
+
edges: [],
|
|
831
|
+
nodeOrigin: [0, 0],
|
|
832
|
+
nodeExtent: infiniteExtent,
|
|
833
|
+
defaultEdgeOptions: {},
|
|
834
|
+
colorMode: "system",
|
|
835
|
+
colorModeSSR: "light",
|
|
836
|
+
connectionMode: "strict",
|
|
837
|
+
connectionLineType: "default",
|
|
838
|
+
connectionRadius: 20,
|
|
839
|
+
nodeDragThreshold: 1,
|
|
840
|
+
minZoom: .5,
|
|
841
|
+
maxZoom: 2,
|
|
842
|
+
selectionMode: "partial",
|
|
843
|
+
fitView: !1,
|
|
844
|
+
noPanClass: "nopan",
|
|
845
|
+
noDragClass: "nodrag",
|
|
846
|
+
noWheelClass: "nowheel",
|
|
847
|
+
autoPanOnNodeDrag: !0,
|
|
848
|
+
autoPanOnConnect: !0,
|
|
849
|
+
autoPanOnNodeFocus: !0,
|
|
850
|
+
autoPanOnSelection: !0,
|
|
851
|
+
autoPanSpeed: 15,
|
|
852
|
+
elevateEdgesOnSelect: !0,
|
|
853
|
+
nodesDraggable: !0,
|
|
854
|
+
nodesConnectable: !0,
|
|
855
|
+
nodesFocusable: !0,
|
|
856
|
+
edgesFocusable: !0,
|
|
857
|
+
elementsSelectable: !0,
|
|
858
|
+
selectNodesOnDrag: !0,
|
|
859
|
+
elevateNodesOnSelect: !0,
|
|
860
|
+
zIndexMode: "basic",
|
|
861
|
+
onlyRenderVisibleElements: !1,
|
|
862
|
+
disableKeyboardA11y: !1,
|
|
863
|
+
defaultMarkerColor: "#b1b1b7",
|
|
864
|
+
ariaLiveMessage: "",
|
|
865
|
+
style: {},
|
|
866
|
+
isValidConnection: (() => !0),
|
|
867
|
+
onFlowError: createDevWarn("Solid Flow", "https://solidflow.dev/")
|
|
868
|
+
});
|
|
837
869
|
//#endregion
|
|
838
|
-
//#region src/
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
870
|
+
//#region src/core/facades.ts
|
|
871
|
+
/**
|
|
872
|
+
* A read-only `Map` view over an id-keyed record projection, for
|
|
873
|
+
* @xyflow/system interop: system helpers take `Map`s, our reactive lookups
|
|
874
|
+
* are records. Every read passes through to the record, so reads inside
|
|
875
|
+
* tracked scopes subscribe normally — `get`/`has` check with `in` first,
|
|
876
|
+
* which also subscribes while the key is still absent (the projection
|
|
877
|
+
* absent-key footgun), and `size`/iteration read the key set structurally.
|
|
878
|
+
*
|
|
879
|
+
* The mutating `Map` methods throw: writes belong to the roots the
|
|
880
|
+
* projection derives from.
|
|
881
|
+
*/
|
|
882
|
+
var RecordMapFacade = class {
|
|
883
|
+
#record;
|
|
884
|
+
constructor(record) {
|
|
885
|
+
this.#record = record;
|
|
886
|
+
}
|
|
887
|
+
get(key) {
|
|
888
|
+
return key in this.#record ? this.#record[key] : void 0;
|
|
889
|
+
}
|
|
890
|
+
has(key) {
|
|
891
|
+
return key in this.#record;
|
|
892
|
+
}
|
|
893
|
+
get size() {
|
|
894
|
+
return Object.keys(this.#record).length;
|
|
895
|
+
}
|
|
896
|
+
*keys() {
|
|
897
|
+
yield* Object.keys(this.#record);
|
|
898
|
+
}
|
|
899
|
+
*values() {
|
|
900
|
+
for (let key of Object.keys(this.#record)) yield this.#record[key];
|
|
901
|
+
}
|
|
902
|
+
*entries() {
|
|
903
|
+
for (let key of Object.keys(this.#record)) yield [key, this.#record[key]];
|
|
904
|
+
}
|
|
905
|
+
[Symbol.iterator]() {
|
|
906
|
+
return this.entries();
|
|
907
|
+
}
|
|
908
|
+
forEach(callback, thisArg) {
|
|
909
|
+
for (let [key, value] of this.entries()) callback.call(thisArg, value, key, this);
|
|
910
|
+
}
|
|
911
|
+
[Symbol.toStringTag] = "RecordMapFacade";
|
|
912
|
+
set() {
|
|
913
|
+
throw Error("RecordMapFacade is read-only; write to the projection's source roots");
|
|
914
|
+
}
|
|
915
|
+
getOrInsert() {
|
|
916
|
+
throw Error("RecordMapFacade is read-only; write to the projection's source roots");
|
|
917
|
+
}
|
|
918
|
+
getOrInsertComputed() {
|
|
919
|
+
throw Error("RecordMapFacade is read-only; write to the projection's source roots");
|
|
920
|
+
}
|
|
921
|
+
delete() {
|
|
922
|
+
throw Error("RecordMapFacade is read-only; write to the projection's source roots");
|
|
923
|
+
}
|
|
924
|
+
clear() {
|
|
925
|
+
throw Error("RecordMapFacade is read-only; write to the projection's source roots");
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
//#endregion
|
|
929
|
+
//#region src/core/projections/connections.ts
|
|
930
|
+
/**
|
|
931
|
+
* Lookup keys for the connection index. Each edge is registered under six
|
|
932
|
+
* keys — for both of its endpoints: the node, the node+handle-type, and (when
|
|
933
|
+
* a handle id is present) the node+type+handle:
|
|
934
|
+
* `${nodeId}` · `${nodeId}-${type}` · `${nodeId}-${type}-${handleId}`
|
|
935
|
+
*/
|
|
936
|
+
const connectionKey = (nodeId, type, handleId) => `${nodeId}${type ? handleId ? `-${type}-${handleId}` : `-${type}` : ""}`, pairKey = (aNode, aHandle, bNode, bHandle) => `${aNode}-${aHandle}--${bNode}-${bHandle}`, createConnections = (source) => createProjection(() => {
|
|
937
|
+
let out = {}, add = (key, entry, connection) => {
|
|
938
|
+
(out[key] ??= {})[entry] = connection;
|
|
939
|
+
};
|
|
940
|
+
for (let edge of source.edges) {
|
|
941
|
+
let sourceHandle = edge.sourceHandle ?? null, targetHandle = edge.targetHandle ?? null, connection = {
|
|
942
|
+
edgeId: edge.id,
|
|
943
|
+
source: edge.source,
|
|
944
|
+
target: edge.target,
|
|
945
|
+
sourceHandle,
|
|
946
|
+
targetHandle
|
|
947
|
+
}, sourceKey = pairKey(edge.source, sourceHandle, edge.target, targetHandle), targetKey = pairKey(edge.target, targetHandle, edge.source, sourceHandle);
|
|
948
|
+
add(edge.source, targetKey, connection), add(connectionKey(edge.source, "source"), targetKey, connection), sourceHandle && add(connectionKey(edge.source, "source", sourceHandle), targetKey, connection), add(edge.target, sourceKey, connection), add(connectionKey(edge.target, "target"), sourceKey, connection), targetHandle && add(connectionKey(edge.target, "target", targetHandle), sourceKey, connection);
|
|
949
|
+
}
|
|
950
|
+
return out;
|
|
951
|
+
}, {}, { key: "id" }), createEdgeLookup = (source) => createProjection(() => {
|
|
952
|
+
let out = {};
|
|
953
|
+
for (let edge of source.edges) out[edge.id] = edge;
|
|
954
|
+
return out;
|
|
955
|
+
}, {}, { key: "id" });
|
|
956
|
+
function isManualZIndexMode(zIndexMode) {
|
|
957
|
+
return zIndexMode === "manual";
|
|
958
|
+
}
|
|
959
|
+
function calculateZ(node, selectedNodeZ, zIndexMode) {
|
|
960
|
+
let zIndex = isNumeric(node.zIndex) ? node.zIndex : 0;
|
|
961
|
+
return isManualZIndexMode(zIndexMode) ? zIndex : zIndex + (node.selected ? selectedNodeZ : 0);
|
|
962
|
+
}
|
|
963
|
+
const EMPTY_AUTO_INDEX = /* @__PURE__ */ new Map(), createInternalNodes = (source) => {
|
|
964
|
+
let autoIndex = createMemo(() => {
|
|
965
|
+
if (source.zIndexMode !== "auto") return EMPTY_AUTO_INDEX;
|
|
966
|
+
let index = /* @__PURE__ */ new Map(), rootIds = /* @__PURE__ */ new Set();
|
|
967
|
+
for (let node of source.nodes) node.parentId ? rootIds.has(node.parentId) && !index.has(node.parentId) && index.set(node.parentId, index.size + 1) : rootIds.add(node.id);
|
|
968
|
+
return index;
|
|
969
|
+
}), entryById = /* @__PURE__ */ new Map(), rowStores = mapArray(() => source.nodes, (userNodeAccessor, index) => {
|
|
970
|
+
let id = userNodeAccessor().id, store = createProjection(() => {
|
|
971
|
+
let userNode = userNodeAccessor(), { nodeOrigin, nodeExtent, zIndexMode } = source, selectedNodeZ = source.elevateNodesOnSelect && !isManualZIndexMode(zIndexMode) ? 1e3 : 0, measurement = userNode.id in source.measurements ? source.measurements[userNode.id] : void 0, measured = {
|
|
972
|
+
width: userNode.measured?.width ?? measurement?.measured.width,
|
|
973
|
+
height: userNode.measured?.height ?? measurement?.measured.height
|
|
974
|
+
}, dimensions = getNodeDimensions({
|
|
975
|
+
measured,
|
|
976
|
+
width: userNode.width,
|
|
977
|
+
height: userNode.height,
|
|
978
|
+
initialWidth: userNode.initialWidth,
|
|
979
|
+
initialHeight: userNode.initialHeight
|
|
980
|
+
}), rootParentIndex = autoIndex().get(userNode.id), row = {
|
|
981
|
+
...userNode,
|
|
982
|
+
measured,
|
|
983
|
+
internals: {
|
|
984
|
+
positionAbsolute: clampPosition(getNodePositionWithOrigin(userNode, nodeOrigin), isCoordinateExtent(userNode.extent) ? userNode.extent : nodeExtent, dimensions),
|
|
985
|
+
handleBounds: measurement?.handleBounds,
|
|
986
|
+
z: calculateZ(userNode, selectedNodeZ, zIndexMode) + (rootParentIndex === void 0 ? 0 : rootParentIndex * 10),
|
|
987
|
+
...rootParentIndex === void 0 ? {} : { rootParentIndex },
|
|
988
|
+
userNode
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
if (userNode.parentId) {
|
|
992
|
+
let parentEntry = entryById.get(userNode.parentId);
|
|
993
|
+
if (parentEntry && parentEntry.index() < index()) {
|
|
994
|
+
let { x, y, z } = calculateChildXYZ(row, parentEntry.store.row, nodeOrigin, nodeExtent, selectedNodeZ, zIndexMode);
|
|
995
|
+
row.internals.positionAbsolute = {
|
|
996
|
+
x,
|
|
997
|
+
y
|
|
998
|
+
}, row.internals.z = z;
|
|
999
|
+
} else source.nodes.length;
|
|
1000
|
+
}
|
|
1001
|
+
if (userNode.parentId) {
|
|
1002
|
+
let parent = entryById.get(userNode.parentId);
|
|
1003
|
+
parent?.store.row.internals.positionAbsolute.x, parent?.store.row.internals.z;
|
|
1004
|
+
}
|
|
1005
|
+
return { row };
|
|
1006
|
+
}, {}, { key: "id" }), entry = {
|
|
1007
|
+
store,
|
|
1008
|
+
index
|
|
1009
|
+
};
|
|
1010
|
+
return entryById.set(id, entry), onCleanup(() => {
|
|
1011
|
+
entryById.get(id) === entry && entryById.delete(id);
|
|
1012
|
+
}), {
|
|
1013
|
+
id,
|
|
1014
|
+
store
|
|
1015
|
+
};
|
|
1016
|
+
}, { keyed: (userNode) => userNode.id }), assigned = /* @__PURE__ */ new Map();
|
|
1017
|
+
return createProjection((draft) => {
|
|
1018
|
+
let seen = /* @__PURE__ */ new Set();
|
|
1019
|
+
for (let { id, store } of rowStores()) {
|
|
1020
|
+
seen.add(id);
|
|
1021
|
+
let row = store.row;
|
|
1022
|
+
assigned.get(id) !== row && (assigned.set(id, row), draft[id] = row);
|
|
857
1023
|
}
|
|
858
|
-
|
|
1024
|
+
for (let id of assigned.keys()) seen.has(id) || (assigned.delete(id), delete draft[id]);
|
|
1025
|
+
}, {}, {
|
|
1026
|
+
key: null,
|
|
1027
|
+
shallow: !0
|
|
859
1028
|
});
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
return;
|
|
1029
|
+
};
|
|
1030
|
+
function calculateChildXYZ(childNode, parentNode, nodeOrigin, nodeExtent, selectedNodeZ, zIndexMode) {
|
|
1031
|
+
let { x: parentX, y: parentY } = parentNode.internals.positionAbsolute, childDimensions = getNodeDimensions(childNode), positionWithOrigin = getNodePositionWithOrigin(childNode, nodeOrigin), clampedPosition = isCoordinateExtent(childNode.extent) ? clampPosition(positionWithOrigin, childNode.extent, childDimensions) : positionWithOrigin, absolutePosition = clampPosition({
|
|
1032
|
+
x: parentX + clampedPosition.x,
|
|
1033
|
+
y: parentY + clampedPosition.y
|
|
1034
|
+
}, nodeExtent, childDimensions);
|
|
1035
|
+
childNode.extent === "parent" && (absolutePosition = clampPositionToParent(absolutePosition, childDimensions, parentNode));
|
|
1036
|
+
let childZ = calculateZ(childNode, selectedNodeZ, zIndexMode), parentZ = parentNode.internals.z ?? 0;
|
|
1037
|
+
return {
|
|
1038
|
+
x: absolutePosition.x,
|
|
1039
|
+
y: absolutePosition.y,
|
|
1040
|
+
z: parentZ >= childZ ? parentZ + 1 : childZ
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
//#endregion
|
|
1044
|
+
//#region src/core/projections/layoutedEdges.ts
|
|
1045
|
+
/**
|
|
1046
|
+
* Edge layout join: user edges × internal nodes → screen-space edge geometry,
|
|
1047
|
+
* decomposed into SUB-STORES (spike 13): each edge is its own keyed
|
|
1048
|
+
* projection holding `{ row }` — the layouted row, or null while the edge
|
|
1049
|
+
* produces none (missing/unready endpoints, culled) — and the public record
|
|
1050
|
+
* is a SHALLOW projection holding the PRESENT rows' proxies by reference.
|
|
1051
|
+
*
|
|
1052
|
+
* Reads chain: `record[id].sourceX` goes through the shallow slot into the
|
|
1053
|
+
* edge's own store, so every materialized leaf signal hangs off its EDGE's
|
|
1054
|
+
* computed (defeating rc.1's per-update companion walk — see
|
|
1055
|
+
* internalNodes.ts). The edge projection tracks exactly what the join reads —
|
|
1056
|
+
* the edge's props and its endpoints' geometry leaves through nodeLookup
|
|
1057
|
+
* (which chains into the node row stores) — so one node move re-runs only
|
|
1058
|
+
* the adjacent edges' projections; the record computed re-runs only when
|
|
1059
|
+
* membership or presence changes.
|
|
1060
|
+
*
|
|
1061
|
+
* The viewport participates only while onlyRenderVisibleElements is active —
|
|
1062
|
+
* panning must not touch edge rows otherwise.
|
|
1063
|
+
*
|
|
1064
|
+
* Rows whose endpoints are missing or unmeasured simply drop out of the
|
|
1065
|
+
* record — the same "no entry" contract the ReactiveMap pipeline had.
|
|
1066
|
+
*/
|
|
1067
|
+
const createLayoutedEdges = (source) => {
|
|
1068
|
+
let rowStores = mapArray(() => source.edges, (edgeAccessor) => ({
|
|
1069
|
+
id: edgeAccessor().id,
|
|
1070
|
+
store: createProjection(() => {
|
|
1071
|
+
let edge = edgeAccessor(), row = buildRow(source, edge);
|
|
1072
|
+
return source.nodeLookup.get(edge.source)?.internals.handleBounds, source.nodeLookup.get(edge.target)?.internals.handleBounds, { row };
|
|
1073
|
+
}, { row: null }, { key: "id" })
|
|
1074
|
+
}), { keyed: (edge) => edge.id }), assigned = /* @__PURE__ */ new Map();
|
|
1075
|
+
return createProjection((draft) => {
|
|
1076
|
+
let seen = /* @__PURE__ */ new Set();
|
|
1077
|
+
for (let { id, store } of rowStores()) {
|
|
1078
|
+
let row = store.row;
|
|
1079
|
+
row && (seen.add(id), assigned.get(id) !== row && (assigned.set(id, row), draft[id] = row));
|
|
912
1080
|
}
|
|
913
|
-
let
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1081
|
+
for (let id of assigned.keys()) seen.has(id) || (assigned.delete(id), delete draft[id]);
|
|
1082
|
+
}, {}, {
|
|
1083
|
+
key: null,
|
|
1084
|
+
shallow: !0
|
|
1085
|
+
});
|
|
1086
|
+
}, buildRow = (source, edge) => {
|
|
1087
|
+
let sourceNode = source.nodeLookup.get(edge.source), targetNode = source.nodeLookup.get(edge.target);
|
|
1088
|
+
if (!sourceNode || !targetNode) return source.nodeLookup.size, null;
|
|
1089
|
+
if (source.onlyRenderVisibleElements && !isEdgeVisible({
|
|
1090
|
+
sourceNode,
|
|
1091
|
+
targetNode,
|
|
1092
|
+
width: source.width ?? 0,
|
|
1093
|
+
height: source.height ?? 0,
|
|
1094
|
+
transform: source.transform
|
|
1095
|
+
})) return null;
|
|
1096
|
+
let edgePosition = getEdgePosition({
|
|
1097
|
+
id: edge.id,
|
|
1098
|
+
sourceNode,
|
|
1099
|
+
targetNode,
|
|
1100
|
+
sourceHandle: edge.sourceHandle || null,
|
|
1101
|
+
targetHandle: edge.targetHandle || null,
|
|
1102
|
+
connectionMode: source.connectionMode,
|
|
1103
|
+
onError: source.onError
|
|
1104
|
+
});
|
|
1105
|
+
return edgePosition ? {
|
|
1106
|
+
...source.defaultEdgeOptions,
|
|
1107
|
+
...edge,
|
|
1108
|
+
...edgePosition,
|
|
1109
|
+
zIndex: getElevatedEdgeZIndex({
|
|
1110
|
+
selected: edge.selected,
|
|
1111
|
+
zIndex: edge.zIndex ?? source.defaultEdgeOptions.zIndex,
|
|
1112
|
+
sourceNode,
|
|
1113
|
+
targetNode,
|
|
1114
|
+
elevateOnSelect: source.elevateEdgesOnSelect,
|
|
1115
|
+
zIndexMode: source.zIndexMode
|
|
1116
|
+
}),
|
|
1117
|
+
sourceNode,
|
|
1118
|
+
targetNode,
|
|
1119
|
+
edge
|
|
1120
|
+
} : null;
|
|
1121
|
+
}, createParentIds = (source) => createProjection(() => {
|
|
1122
|
+
let out = {};
|
|
1123
|
+
for (let node of source.nodes) node.parentId && (out[node.parentId] = !0);
|
|
1124
|
+
return out;
|
|
1125
|
+
}, {}, { key: "id" }), getInitialViewport = (fitView, initialViewport, width, height, nodeLookup) => {
|
|
1126
|
+
if (fitView && !initialViewport && width && height) {
|
|
1127
|
+
let bounds = getInternalNodesBounds(nodeLookup, { filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)) });
|
|
1128
|
+
return getViewportForBounds$1(bounds, width, height, .5, 2, .1);
|
|
1129
|
+
}
|
|
1130
|
+
return initialViewport ?? {
|
|
1131
|
+
x: 0,
|
|
1132
|
+
y: 0,
|
|
1133
|
+
zoom: 1
|
|
1134
|
+
};
|
|
1135
|
+
}, createFlowState = (props, injections = {}) => {
|
|
1136
|
+
let _props = merge(getDefaultFlowStateProps(), props), initialNodeTypes = injections.initialNodeTypes ?? {}, initialEdgeTypes = injections.initialEdgeTypes ?? {}, prefersDark = injections.prefersDark ?? (() => _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props), [ariaLabelConfig, setAriaLabelConfig] = createSignal(() => mergeAriaLabelConfig(config().ariaLabelConfig)), [ariaLiveMessage, setAriaLiveMessage] = createSignal(() => config().ariaLiveMessage), [clickConnectStartHandle, setClickConnectStartHandle] = createSignal(void 0), [connection, setConnection] = createSignal(initialConnection), [domNode, setDomNode] = createSignal(null), [dragging, setDragging] = createSignal(!1), [elementsSelectable, setElementsSelectable] = createSignal(() => config().elementsSelectable), [height, setHeight] = createSignal(() => config().height), [minZoom, _setMinZoom] = createSignal(() => config().minZoom), [maxZoom, _setMaxZoom] = createSignal(() => config().maxZoom), [nodesConnectable, setNodesConnectable] = createSignal(() => config().nodesDraggable), [nodesDraggable, setNodesDraggable] = createSignal(() => config().nodesDraggable), [panZoom, setPanZoom] = createSignal(null), [selectionRect, setSelectionRect] = createSignal(), [selectionRectMode, setSelectionRectMode] = createSignal(), [snapGrid, setSnapGrid] = createSignal(() => config().snapGrid), [translateExtent, _setTranslateExtent] = createSignal(() => config().translateExtent ?? infiniteExtent), [width, setWidth] = createSignal(() => config().width), [selectionKeyPressed, setSelectionKeyPressed] = createSignal(!1), [multiselectionKeyPressed, setMultiselectionKeyPressed] = createSignal(!1), [deleteKeyPressed, setDeleteKeyPressed] = createSignal(!1), [panActivationKeyPressed, setPanActivationKeyPressed] = createSignal(!1), [zoomActivationKeyPressed, setZoomActivationKeyPressed] = createSignal(!1), [nodesStore, setNodesStore] = createStore(_props.nodes), [edgesStore, setEdgesStore] = createStore(_props.edges), [measurementsStore, setMeasurementsStore] = createStore({}), internalNodes = createInternalNodes({
|
|
1137
|
+
get nodes() {
|
|
1138
|
+
return nodesStore;
|
|
945
1139
|
},
|
|
946
|
-
get
|
|
947
|
-
return
|
|
1140
|
+
get measurements() {
|
|
1141
|
+
return measurementsStore;
|
|
948
1142
|
},
|
|
949
|
-
get
|
|
950
|
-
return
|
|
1143
|
+
get nodeOrigin() {
|
|
1144
|
+
return config().nodeOrigin;
|
|
951
1145
|
},
|
|
952
|
-
get
|
|
953
|
-
return
|
|
1146
|
+
get nodeExtent() {
|
|
1147
|
+
return config().nodeExtent;
|
|
954
1148
|
},
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
return _props.style;
|
|
1149
|
+
get elevateNodesOnSelect() {
|
|
1150
|
+
return config().elevateNodesOnSelect;
|
|
958
1151
|
},
|
|
959
|
-
get
|
|
960
|
-
return
|
|
961
|
-
"solid-flow__handle",
|
|
962
|
-
`solid-flow__handle-${_props.position}`,
|
|
963
|
-
store.noDragClass,
|
|
964
|
-
store.noPanClass,
|
|
965
|
-
_props.class,
|
|
966
|
-
{
|
|
967
|
-
valid: valid(),
|
|
968
|
-
connectingto: !!connectingTo(),
|
|
969
|
-
connectingfrom: !!connectingFrom(),
|
|
970
|
-
source: !isTarget(),
|
|
971
|
-
target: isTarget(),
|
|
972
|
-
connectablestart: _props.isConnectableStart,
|
|
973
|
-
connectableend: _props.isConnectableEnd,
|
|
974
|
-
connectable: !!connectable(),
|
|
975
|
-
connectionindicator: connectionIndicator()
|
|
976
|
-
}
|
|
977
|
-
];
|
|
1152
|
+
get zIndexMode() {
|
|
1153
|
+
return config().zIndexMode;
|
|
978
1154
|
}
|
|
979
|
-
}),
|
|
980
|
-
}, DefaultNode = (props) => {
|
|
981
|
-
let _props = propDefaults(props, {
|
|
982
|
-
targetPosition: Position$1.Top,
|
|
983
|
-
sourcePosition: Position$1.Bottom
|
|
984
|
-
});
|
|
985
|
-
return [
|
|
986
|
-
createComponent(Handle, {
|
|
987
|
-
type: "target",
|
|
988
|
-
get position() {
|
|
989
|
-
return _props.targetPosition;
|
|
990
|
-
},
|
|
991
|
-
get isConnectable() {
|
|
992
|
-
return _props.isConnectable;
|
|
993
|
-
}
|
|
994
|
-
}),
|
|
995
|
-
memo(() => props.data.label),
|
|
996
|
-
createComponent(Handle, {
|
|
997
|
-
type: "source",
|
|
998
|
-
get position() {
|
|
999
|
-
return _props.sourcePosition;
|
|
1000
|
-
},
|
|
1001
|
-
get isConnectable() {
|
|
1002
|
-
return _props.isConnectable;
|
|
1003
|
-
}
|
|
1004
|
-
})
|
|
1005
|
-
];
|
|
1006
|
-
};
|
|
1007
|
-
//#endregion
|
|
1008
|
-
//#region src/components/graph/node/GroupNode.tsx
|
|
1009
|
-
var _tmpl$$28 = /* @__PURE__ */ template("<div style=position:absolute;left:0;top:0>");
|
|
1010
|
-
const GroupNode = (props) => (() => {
|
|
1011
|
-
var _el$ = _tmpl$$28();
|
|
1012
|
-
return effect(() => ({
|
|
1013
|
-
e: toPxString(props.width),
|
|
1014
|
-
t: toPxString(props.height)
|
|
1015
|
-
}), ({ e, t }, _p$) => {
|
|
1016
|
-
e !== _p$?.e && setStyleProperty(_el$, "width", e), t !== _p$?.t && setStyleProperty(_el$, "height", t);
|
|
1017
|
-
}), _el$;
|
|
1018
|
-
})(), InputNode = (props) => {
|
|
1019
|
-
let _props = propDefaults(props, { sourcePosition: Position$1.Bottom });
|
|
1020
|
-
return [memo(() => props.data?.label), createComponent(Handle, {
|
|
1021
|
-
type: "source",
|
|
1022
|
-
get position() {
|
|
1023
|
-
return _props.sourcePosition;
|
|
1024
|
-
},
|
|
1025
|
-
get isConnectable() {
|
|
1026
|
-
return _props.isConnectable;
|
|
1027
|
-
}
|
|
1028
|
-
})];
|
|
1029
|
-
}, createDraggable = (elem, params) => {
|
|
1030
|
-
let { store, nodeLookup, actions } = useInternalSolidFlow(), [dragging, setDragging] = createSignal(!1);
|
|
1031
|
-
return createEffect(() => ({
|
|
1032
|
-
el: elem(),
|
|
1033
|
-
current: params()
|
|
1034
|
-
}), ({ el, current }) => {
|
|
1035
|
-
if (!el || current.disabled) return;
|
|
1036
|
-
let { onDrag, onDragStart, onDragStop, onNodeMouseDown } = current, dragInstance = XYDrag({
|
|
1037
|
-
onDrag,
|
|
1038
|
-
onDragStart: (event, dragItems, node, nodes) => {
|
|
1039
|
-
setDragging(!0), onDragStart?.(event, dragItems, node, nodes);
|
|
1040
|
-
},
|
|
1041
|
-
onDragStop: (event, dragItems, node, nodes) => {
|
|
1042
|
-
setDragging(!1), onDragStop?.(event, dragItems, node, nodes);
|
|
1043
|
-
},
|
|
1044
|
-
onNodeMouseDown,
|
|
1045
|
-
getStoreItems: () => ({
|
|
1046
|
-
nodes: store.nodes,
|
|
1047
|
-
nodeLookup,
|
|
1048
|
-
edges: store.edges,
|
|
1049
|
-
nodeExtent: store.nodeExtent,
|
|
1050
|
-
snapGrid: store.snapGrid ?? [0, 0],
|
|
1051
|
-
snapToGrid: !!store.snapGrid,
|
|
1052
|
-
autoPanSpeed: store.autoPanSpeed,
|
|
1053
|
-
nodeOrigin: store.nodeOrigin,
|
|
1054
|
-
multiSelectionActive: store.multiselectionKeyPressed,
|
|
1055
|
-
domNode: store.domNode,
|
|
1056
|
-
transform: store.transform,
|
|
1057
|
-
autoPanOnNodeDrag: store.autoPanOnNodeDrag,
|
|
1058
|
-
nodesDraggable: store.nodesDraggable,
|
|
1059
|
-
selectNodesOnDrag: store.selectNodesOnDrag,
|
|
1060
|
-
nodeDragThreshold: store.nodeDragThreshold,
|
|
1061
|
-
unselectNodesAndEdges: actions.unselectNodesAndEdges,
|
|
1062
|
-
updateNodePositions: actions.updateNodePositions,
|
|
1063
|
-
panBy: actions.panBy
|
|
1064
|
-
})
|
|
1065
|
-
});
|
|
1066
|
-
return dragInstance.update({
|
|
1067
|
-
domNode: el,
|
|
1068
|
-
nodeId: current.nodeId,
|
|
1069
|
-
noDragClassName: current.noDragClass,
|
|
1070
|
-
handleSelector: current.handleSelector,
|
|
1071
|
-
isSelectable: current.isSelectable,
|
|
1072
|
-
nodeClickDistance: current.nodeClickDistance
|
|
1073
|
-
}), () => {
|
|
1074
|
-
dragInstance.destroy();
|
|
1075
|
-
};
|
|
1076
|
-
}), dragging;
|
|
1077
|
-
}, NodeIdContext = createContext(null);
|
|
1078
|
-
function useNodeId() {
|
|
1079
|
-
let ctx = useContext(NodeIdContext);
|
|
1080
|
-
if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeId");
|
|
1081
|
-
return ctx;
|
|
1082
|
-
}
|
|
1083
|
-
//#endregion
|
|
1084
|
-
//#region src/components/graph/node/NodeWrapper.tsx
|
|
1085
|
-
var _tmpl$$27 = /* @__PURE__ */ template("<div>");
|
|
1086
|
-
const NodeWrapper = (props) => {
|
|
1087
|
-
let { store, nodeLookup, parentLookup, actions } = useInternalSolidFlow(), [nodeRef, setNodeRef] = createSignal(), node = () => nodeLookup.get(props.nodeId), nodeId = () => node().id, nodeType = () => node().type ?? "default", deletable = () => node().deletable ?? !0, selectable = () => node().selectable ?? store.elementsSelectable, focusable = () => node().focusable ?? store.nodesFocusable, draggable = () => node().draggable ?? store.nodesDraggable, connectable = () => node().connectable ?? store.nodesConnectable, userNode = () => node().internals.userNode, nodeTypeValid = () => nodeType() in store.nodeTypes, nodeComponent = () => store.nodeTypes[nodeType()], isParentNode = () => parentLookup.has(node().id), transform = () => {
|
|
1088
|
-
let { x, y } = node().internals.positionAbsolute;
|
|
1089
|
-
return `translate(${x}px, ${y}px)`;
|
|
1090
|
-
}, sizeStyle = () => {
|
|
1091
|
-
let w = node().width ?? node().initialWidth, h = node().height ?? node().initialHeight;
|
|
1092
|
-
return {
|
|
1093
|
-
...node().style,
|
|
1094
|
-
...w ? { width: toPxString(w) } : {},
|
|
1095
|
-
...h ? { height: toPxString(h) } : {}
|
|
1096
|
-
};
|
|
1097
|
-
}, style = () => ({
|
|
1098
|
-
"z-index": node().internals.z,
|
|
1099
|
-
transform: transform(),
|
|
1100
|
-
visibility: nodeHasDimensions(node()) ? "visible" : "hidden",
|
|
1101
|
-
...sizeStyle(),
|
|
1102
|
-
...node().style ?? {}
|
|
1103
|
-
});
|
|
1104
|
-
createEffect(() => ({
|
|
1105
|
-
valid: nodeTypeValid(),
|
|
1106
|
-
nodeType: nodeType()
|
|
1107
|
-
}), ({ valid, nodeType }) => {}), createEffect(() => ({
|
|
1108
|
-
id: node().id,
|
|
1109
|
-
nodeElement: nodeRef(),
|
|
1110
|
-
nodeType: nodeType(),
|
|
1111
|
-
sourcePosition: node().sourcePosition,
|
|
1112
|
-
targetPosition: node().targetPosition
|
|
1113
|
-
}), (current, prev) => {
|
|
1114
|
-
current.nodeElement && (prev && prev.nodeElement === current.nodeElement && prev.sourcePosition === current.sourcePosition && prev.targetPosition === current.targetPosition && prev.nodeType === current.nodeType || actions.requestUpdateNodeInternals([[current.id, {
|
|
1115
|
-
id: current.id,
|
|
1116
|
-
nodeElement: current.nodeElement,
|
|
1117
|
-
force: !0
|
|
1118
|
-
}]]));
|
|
1119
|
-
}), createEffect(() => ({
|
|
1120
|
-
nodeElement: nodeRef(),
|
|
1121
|
-
hasDimensions: nodeHasDimensions(node()),
|
|
1122
|
-
resizeObserver: props.resizeObserver
|
|
1123
|
-
}), (current, prev) => {
|
|
1124
|
-
current.nodeElement === prev?.nodeElement && current.resizeObserver === prev?.resizeObserver && current.hasDimensions || (prev?.nodeElement && prev.resizeObserver?.unobserve(prev.nodeElement), current.nodeElement && current.resizeObserver?.observe(current.nodeElement));
|
|
1125
|
-
});
|
|
1126
|
-
let onSelectNodeHandler = (event) => {
|
|
1127
|
-
selectable() && (!store.selectNodesOnDrag || !draggable() || store.nodeDragThreshold > 0) && actions.handleNodeSelection(node().id), props.onNodeClick?.({
|
|
1128
|
-
node: userNode(),
|
|
1129
|
-
event
|
|
1130
|
-
});
|
|
1131
|
-
}, onKeyDown = (event) => {
|
|
1132
|
-
if (isInputDOMNode(event) || store.disableKeyboardA11y) return;
|
|
1133
|
-
if (elementSelectionKeys.includes(event.key) && selectable()) {
|
|
1134
|
-
actions.handleNodeSelection(node().id, event.key === "Escape", nodeRef());
|
|
1135
|
-
return;
|
|
1136
|
-
}
|
|
1137
|
-
let arrowKeyDiff = ARROW_KEY_DIFFS[event.key];
|
|
1138
|
-
draggable() && node().selected && arrowKeyDiff && (event.preventDefault(), actions.setAriaLiveMessage(store.ariaLabelConfig["node.a11yDescription.ariaLiveMessage"]({
|
|
1139
|
-
direction: event.key.replace("Arrow", "").toLowerCase(),
|
|
1140
|
-
x: ~~node().internals.positionAbsolute.x,
|
|
1141
|
-
y: ~~node().internals.positionAbsolute.y
|
|
1142
|
-
})), actions.moveSelectedNodes(arrowKeyDiff, event.shiftKey ? 4 : 1));
|
|
1143
|
-
}, onFocus = () => {
|
|
1144
|
-
if (store.disableKeyboardA11y || !store.autoPanOnNodeFocus || !nodeRef()?.matches(":focus-visible")) return;
|
|
1145
|
-
let { width, height, viewport } = store;
|
|
1146
|
-
getNodesInside(/* @__PURE__ */ new Map([[node().id, node()]]), {
|
|
1147
|
-
x: 0,
|
|
1148
|
-
y: 0,
|
|
1149
|
-
width,
|
|
1150
|
-
height
|
|
1151
|
-
}, [
|
|
1152
|
-
viewport.x,
|
|
1153
|
-
viewport.y,
|
|
1154
|
-
viewport.zoom
|
|
1155
|
-
], !0).length > 0 || actions.setCenter(node().position.x + (node().measured.width ?? 0) / 2, node().position.y + (node().measured.height ?? 0) / 2, { zoom: viewport.zoom });
|
|
1156
|
-
}, dragging = createDraggable(nodeRef, () => ({
|
|
1157
|
-
nodeId: node().id,
|
|
1158
|
-
isSelectable: selectable(),
|
|
1159
|
-
disabled: !draggable(),
|
|
1160
|
-
handleSelector: node().dragHandle,
|
|
1161
|
-
noDragClass: store.noDragClass,
|
|
1162
|
-
nodeClickDistance: props.nodeClickDistance,
|
|
1163
|
-
onNodeMouseDown: actions.handleNodeSelection,
|
|
1164
|
-
onDrag: (event, _, targetNode, nodes) => {
|
|
1165
|
-
props.onNodeDrag?.({
|
|
1166
|
-
event,
|
|
1167
|
-
targetNode,
|
|
1168
|
-
nodes
|
|
1169
|
-
});
|
|
1170
|
-
},
|
|
1171
|
-
onDragStart: (event, _, targetNode, nodes) => {
|
|
1172
|
-
props.onNodeDragStart?.({
|
|
1173
|
-
event,
|
|
1174
|
-
targetNode,
|
|
1175
|
-
nodes
|
|
1176
|
-
});
|
|
1177
|
-
},
|
|
1178
|
-
onDragStop: (event, _, targetNode, nodes) => {
|
|
1179
|
-
props.onNodeDragStop?.({
|
|
1180
|
-
event,
|
|
1181
|
-
targetNode,
|
|
1182
|
-
nodes
|
|
1183
|
-
});
|
|
1184
|
-
}
|
|
1185
|
-
}));
|
|
1186
|
-
return createComponent(Show, {
|
|
1187
|
-
get when() {
|
|
1188
|
-
return !node().hidden;
|
|
1189
|
-
},
|
|
1190
|
-
get children() {
|
|
1191
|
-
var _el$ = _tmpl$$27();
|
|
1192
|
-
return ref(() => setNodeRef, _el$), spread(_el$, mergeProps({
|
|
1193
|
-
get "data-id"() {
|
|
1194
|
-
return node().id;
|
|
1195
|
-
},
|
|
1196
|
-
get class() {
|
|
1197
|
-
return [
|
|
1198
|
-
"solid-flow__node",
|
|
1199
|
-
`solid-flow__node-${nodeType()}`,
|
|
1200
|
-
{
|
|
1201
|
-
connectable: !!connectable(),
|
|
1202
|
-
draggable: !!draggable(),
|
|
1203
|
-
dragging: dragging(),
|
|
1204
|
-
nopan: !!draggable(),
|
|
1205
|
-
parent: isParentNode(),
|
|
1206
|
-
selectable: !!selectable(),
|
|
1207
|
-
selected: !!node().selected
|
|
1208
|
-
},
|
|
1209
|
-
node().class
|
|
1210
|
-
];
|
|
1211
|
-
},
|
|
1212
|
-
get style() {
|
|
1213
|
-
return style();
|
|
1214
|
-
},
|
|
1215
|
-
onClick: onSelectNodeHandler,
|
|
1216
|
-
onPointerEnter: (event) => props.onNodePointerEnter?.({
|
|
1217
|
-
node: userNode(),
|
|
1218
|
-
event
|
|
1219
|
-
}),
|
|
1220
|
-
onPointerLeave: (event) => props.onNodePointerLeave?.({
|
|
1221
|
-
node: userNode(),
|
|
1222
|
-
event
|
|
1223
|
-
}),
|
|
1224
|
-
onPointerMove: (event) => props.onNodePointerMove?.({
|
|
1225
|
-
node: userNode(),
|
|
1226
|
-
event
|
|
1227
|
-
}),
|
|
1228
|
-
onContextMenu: (event) => props.onNodeContextMenu?.({
|
|
1229
|
-
node: userNode(),
|
|
1230
|
-
event
|
|
1231
|
-
}),
|
|
1232
|
-
onKeyDown: (e) => focusable() && onKeyDown(e),
|
|
1233
|
-
onFocus: () => focusable() && onFocus(),
|
|
1234
|
-
get tabindex() {
|
|
1235
|
-
return focusable() ? 0 : void 0;
|
|
1236
|
-
},
|
|
1237
|
-
get role() {
|
|
1238
|
-
return node().ariaRole ?? (focusable() ? "group" : void 0);
|
|
1239
|
-
},
|
|
1240
|
-
"aria-roledescription": "node",
|
|
1241
|
-
get "aria-describedby"() {
|
|
1242
|
-
return store.disableKeyboardA11y ? void 0 : `${ARIA_NODE_DESC_KEY}-${store.id}`;
|
|
1243
|
-
}
|
|
1244
|
-
}, () => node().domAttributes), !0), insert(_el$, createComponent(NodeIdContext, {
|
|
1245
|
-
value: nodeId,
|
|
1246
|
-
get children() {
|
|
1247
|
-
return createComponent(NodeConnectableContext, {
|
|
1248
|
-
value: connectable,
|
|
1249
|
-
get children() {
|
|
1250
|
-
return createComponent(Dynamic, {
|
|
1251
|
-
get component() {
|
|
1252
|
-
return nodeComponent();
|
|
1253
|
-
},
|
|
1254
|
-
get data() {
|
|
1255
|
-
return node().data;
|
|
1256
|
-
},
|
|
1257
|
-
get id() {
|
|
1258
|
-
return node().id;
|
|
1259
|
-
},
|
|
1260
|
-
get selected() {
|
|
1261
|
-
return !!node().selected;
|
|
1262
|
-
},
|
|
1263
|
-
get selectable() {
|
|
1264
|
-
return selectable();
|
|
1265
|
-
},
|
|
1266
|
-
get deletable() {
|
|
1267
|
-
return deletable();
|
|
1268
|
-
},
|
|
1269
|
-
get sourcePosition() {
|
|
1270
|
-
return node().sourcePosition;
|
|
1271
|
-
},
|
|
1272
|
-
get targetPosition() {
|
|
1273
|
-
return node().targetPosition;
|
|
1274
|
-
},
|
|
1275
|
-
get zIndex() {
|
|
1276
|
-
return node().internals.z;
|
|
1277
|
-
},
|
|
1278
|
-
get dragging() {
|
|
1279
|
-
return dragging();
|
|
1280
|
-
},
|
|
1281
|
-
get draggable() {
|
|
1282
|
-
return draggable();
|
|
1283
|
-
},
|
|
1284
|
-
get dragHandle() {
|
|
1285
|
-
return node().dragHandle;
|
|
1286
|
-
},
|
|
1287
|
-
get parentId() {
|
|
1288
|
-
return node().parentId;
|
|
1289
|
-
},
|
|
1290
|
-
get type() {
|
|
1291
|
-
return nodeType();
|
|
1292
|
-
},
|
|
1293
|
-
get isConnectable() {
|
|
1294
|
-
return connectable();
|
|
1295
|
-
},
|
|
1296
|
-
get positionAbsoluteX() {
|
|
1297
|
-
return node().internals.positionAbsolute.x;
|
|
1298
|
-
},
|
|
1299
|
-
get positionAbsoluteY() {
|
|
1300
|
-
return node().internals.positionAbsolute.y;
|
|
1301
|
-
},
|
|
1302
|
-
get width() {
|
|
1303
|
-
return node().width;
|
|
1304
|
-
},
|
|
1305
|
-
get height() {
|
|
1306
|
-
return node().height;
|
|
1307
|
-
}
|
|
1308
|
-
});
|
|
1309
|
-
}
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
1312
|
-
})), _el$;
|
|
1313
|
-
}
|
|
1314
|
-
});
|
|
1315
|
-
}, OutputNode = (props) => {
|
|
1316
|
-
let _props = propDefaults(props, { targetPosition: Position$1.Top });
|
|
1317
|
-
return [createComponent(Handle, {
|
|
1318
|
-
type: "target",
|
|
1319
|
-
get position() {
|
|
1320
|
-
return _props.targetPosition;
|
|
1321
|
-
},
|
|
1322
|
-
get isConnectable() {
|
|
1323
|
-
return _props.isConnectable;
|
|
1324
|
-
}
|
|
1325
|
-
}), memo(() => props.data?.label)];
|
|
1326
|
-
}, getDefaultFlowStateProps = () => ({
|
|
1327
|
-
id: "1",
|
|
1328
|
-
nodes: [],
|
|
1329
|
-
edges: [],
|
|
1330
|
-
nodeOrigin: [0, 0],
|
|
1331
|
-
nodeExtent: infiniteExtent,
|
|
1332
|
-
defaultEdgeOptions: {},
|
|
1333
|
-
colorMode: "system",
|
|
1334
|
-
colorModeSSR: "light",
|
|
1335
|
-
connectionMode: "strict",
|
|
1336
|
-
connectionLineType: "default",
|
|
1337
|
-
connectionRadius: 20,
|
|
1338
|
-
nodeDragThreshold: 1,
|
|
1339
|
-
minZoom: .5,
|
|
1340
|
-
maxZoom: 2,
|
|
1341
|
-
selectionMode: "partial",
|
|
1342
|
-
fitView: !1,
|
|
1343
|
-
noPanClass: "nopan",
|
|
1344
|
-
noDragClass: "nodrag",
|
|
1345
|
-
noWheelClass: "nowheel",
|
|
1346
|
-
autoPanOnNodeDrag: !0,
|
|
1347
|
-
autoPanOnConnect: !0,
|
|
1348
|
-
autoPanOnNodeFocus: !0,
|
|
1349
|
-
autoPanOnSelection: !0,
|
|
1350
|
-
autoPanSpeed: 15,
|
|
1351
|
-
elevateEdgesOnSelect: !0,
|
|
1352
|
-
nodesDraggable: !0,
|
|
1353
|
-
nodesConnectable: !0,
|
|
1354
|
-
nodesFocusable: !0,
|
|
1355
|
-
edgesFocusable: !0,
|
|
1356
|
-
elementsSelectable: !0,
|
|
1357
|
-
selectNodesOnDrag: !0,
|
|
1358
|
-
elevateNodesOnSelect: !0,
|
|
1359
|
-
zIndexMode: "basic",
|
|
1360
|
-
onlyRenderVisibleElements: !1,
|
|
1361
|
-
disableKeyboardA11y: !1,
|
|
1362
|
-
defaultMarkerColor: "#b1b1b7",
|
|
1363
|
-
ariaLiveMessage: "",
|
|
1364
|
-
style: {},
|
|
1365
|
-
isValidConnection: (() => !0),
|
|
1366
|
-
onFlowError: createDevWarn("Solid Flow", "https://solidflow.dev/")
|
|
1367
|
-
}), SELECTED_NODE_Z = 1e3, defaultOptions = {
|
|
1368
|
-
nodeOrigin: [0, 0],
|
|
1369
|
-
nodeExtent: infiniteExtent,
|
|
1370
|
-
elevateNodesOnSelect: !0,
|
|
1371
|
-
defaults: {},
|
|
1372
|
-
zIndexMode: "basic"
|
|
1373
|
-
};
|
|
1374
|
-
function isManualZIndexMode(zIndexMode) {
|
|
1375
|
-
return zIndexMode === "manual";
|
|
1376
|
-
}
|
|
1377
|
-
const adoptUserNodesDefaultOptions = {
|
|
1378
|
-
...defaultOptions,
|
|
1379
|
-
checkEquality: !0
|
|
1380
|
-
};
|
|
1381
|
-
function mergeObjects(base, incoming) {
|
|
1382
|
-
let result = { ...base };
|
|
1383
|
-
for (let key in incoming) incoming[key] !== void 0 && (result[key] = incoming[key]);
|
|
1384
|
-
return result;
|
|
1385
|
-
}
|
|
1386
|
-
function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
|
|
1387
|
-
let _options = mergeObjects(adoptUserNodesDefaultOptions, options), nodesInitialized = nodes.length > 0, rootParentIndex = { i: 0 }, tmpLookup = new Map(nodeLookup), selectedNodeZ = _options?.elevateNodesOnSelect && !isManualZIndexMode(_options.zIndexMode) ? SELECTED_NODE_Z : 0;
|
|
1388
|
-
nodeLookup.clear(), parentLookup.clear();
|
|
1389
|
-
for (let userNode of nodes) {
|
|
1390
|
-
let internalNode = tmpLookup.get(userNode.id);
|
|
1391
|
-
if (_options.checkEquality && userNode === internalNode?.internals.userNode) nodeLookup.set(userNode.id, internalNode);
|
|
1392
|
-
else {
|
|
1393
|
-
let positionWithOrigin = getNodePositionWithOrigin(userNode, _options.nodeOrigin), extent = isCoordinateExtent(userNode.extent) ? userNode.extent : _options.nodeExtent, clampedPosition = clampPosition(positionWithOrigin, extent, getNodeDimensions(userNode));
|
|
1394
|
-
internalNode = {
|
|
1395
|
-
..._options.defaults,
|
|
1396
|
-
...userNode,
|
|
1397
|
-
measured: {
|
|
1398
|
-
width: userNode.measured?.width,
|
|
1399
|
-
height: userNode.measured?.height
|
|
1400
|
-
},
|
|
1401
|
-
internals: {
|
|
1402
|
-
positionAbsolute: clampedPosition,
|
|
1403
|
-
handleBounds: userNode.measured ? internalNode?.internals.handleBounds : void 0,
|
|
1404
|
-
z: calculateZ(userNode, selectedNodeZ, _options.zIndexMode),
|
|
1405
|
-
userNode
|
|
1406
|
-
}
|
|
1407
|
-
}, nodeLookup.set(userNode.id, internalNode);
|
|
1408
|
-
}
|
|
1409
|
-
(internalNode.measured === void 0 || internalNode.measured.width === void 0 || internalNode.measured.height === void 0) && !internalNode.hidden && (nodesInitialized = !1), userNode.parentId && updateChildNode(internalNode, nodeLookup, parentLookup, options, rootParentIndex);
|
|
1410
|
-
}
|
|
1411
|
-
return nodesInitialized;
|
|
1412
|
-
}
|
|
1413
|
-
function updateParentLookup(node, parentLookup) {
|
|
1414
|
-
if (!node.parentId) return;
|
|
1415
|
-
let childNodes = parentLookup.get(node.parentId);
|
|
1416
|
-
childNodes ? childNodes.set(node.id, node) : parentLookup.set(node.parentId, /* @__PURE__ */ new Map([[node.id, node]]));
|
|
1417
|
-
}
|
|
1418
|
-
/**
|
|
1419
|
-
* Updates positionAbsolute and zIndex of a child node and the parentLookup.
|
|
1420
|
-
*/
|
|
1421
|
-
function updateChildNode(node, nodeLookup, parentLookup, options, rootParentIndex) {
|
|
1422
|
-
let { elevateNodesOnSelect, nodeOrigin, nodeExtent, zIndexMode } = mergeObjects(defaultOptions, options), parentId = node.parentId, parentNode = nodeLookup.get(parentId);
|
|
1423
|
-
if (!parentNode) return;
|
|
1424
|
-
updateParentLookup(node, parentLookup), rootParentIndex && !parentNode.parentId && parentNode.internals.rootParentIndex === void 0 && zIndexMode === "auto" && (parentNode.internals.rootParentIndex = ++rootParentIndex.i, parentNode.internals.z = parentNode.internals.z + rootParentIndex.i * 10), rootParentIndex && parentNode.internals.rootParentIndex !== void 0 && (rootParentIndex.i = parentNode.internals.rootParentIndex);
|
|
1425
|
-
let { x, y, z } = calculateChildXYZ(node, parentNode, nodeOrigin, nodeExtent, elevateNodesOnSelect && !isManualZIndexMode(zIndexMode) ? SELECTED_NODE_Z : 0, zIndexMode), { positionAbsolute } = node.internals, positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y;
|
|
1426
|
-
(positionChanged || z !== node.internals.z) && nodeLookup.set(node.id, {
|
|
1427
|
-
...node,
|
|
1428
|
-
internals: {
|
|
1429
|
-
...node.internals,
|
|
1430
|
-
positionAbsolute: positionChanged ? {
|
|
1431
|
-
x,
|
|
1432
|
-
y
|
|
1433
|
-
} : positionAbsolute,
|
|
1434
|
-
z
|
|
1435
|
-
}
|
|
1436
|
-
});
|
|
1437
|
-
}
|
|
1438
|
-
function calculateZ(node, selectedNodeZ, zIndexMode) {
|
|
1439
|
-
let zIndex = isNumeric(node.zIndex) ? node.zIndex : 0;
|
|
1440
|
-
return isManualZIndexMode(zIndexMode) ? zIndex : zIndex + (node.selected ? selectedNodeZ : 0);
|
|
1441
|
-
}
|
|
1442
|
-
function calculateChildXYZ(childNode, parentNode, nodeOrigin, nodeExtent, selectedNodeZ, zIndexMode) {
|
|
1443
|
-
let { x: parentX, y: parentY } = parentNode.internals.positionAbsolute, childDimensions = getNodeDimensions(childNode), positionWithOrigin = getNodePositionWithOrigin(childNode, nodeOrigin), clampedPosition = isCoordinateExtent(childNode.extent) ? clampPosition(positionWithOrigin, childNode.extent, childDimensions) : positionWithOrigin, absolutePosition = clampPosition({
|
|
1444
|
-
x: parentX + clampedPosition.x,
|
|
1445
|
-
y: parentY + clampedPosition.y
|
|
1446
|
-
}, nodeExtent, childDimensions);
|
|
1447
|
-
childNode.extent === "parent" && (absolutePosition = clampPositionToParent(absolutePosition, childDimensions, parentNode));
|
|
1448
|
-
let childZ = calculateZ(childNode, selectedNodeZ, zIndexMode), parentZ = parentNode.internals.z ?? 0;
|
|
1449
|
-
return {
|
|
1450
|
-
x: absolutePosition.x,
|
|
1451
|
-
y: absolutePosition.y,
|
|
1452
|
-
z: parentZ >= childZ ? parentZ + 1 : childZ
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
/**
|
|
1456
|
-
* this function adds the connection to the connectionLookup
|
|
1457
|
-
* at the following keys: nodeId-type-handleId, nodeId-type and nodeId
|
|
1458
|
-
* @param type type of the connection
|
|
1459
|
-
* @param connection connection that should be added to the lookup
|
|
1460
|
-
* @param connectionKey at which key the connection should be added
|
|
1461
|
-
* @param connectionLookup reference to the connection lookup
|
|
1462
|
-
* @param nodeId nodeId of the connection
|
|
1463
|
-
* @param handleId handleId of the conneciton
|
|
1464
|
-
*/
|
|
1465
|
-
function addConnectionToLookup(type, connection, connectionKey, connectionLookup, nodeId, handleId) {
|
|
1466
|
-
let add = (key) => {
|
|
1467
|
-
let next = new Map(untrack(() => connectionLookup.get(key)));
|
|
1468
|
-
next.set(connectionKey, connection), connectionLookup.set(key, next);
|
|
1469
|
-
};
|
|
1470
|
-
add(nodeId), add(`${nodeId}-${type}`), handleId && add(`${nodeId}-${type}-${handleId}`);
|
|
1471
|
-
}
|
|
1472
|
-
function removeConnectionFromLookup(type, connectionKey, connectionLookup, nodeId, handleId) {
|
|
1473
|
-
let remove = (key) => {
|
|
1474
|
-
let current = untrack(() => connectionLookup.get(key));
|
|
1475
|
-
if (!current) return;
|
|
1476
|
-
let next = new Map(current);
|
|
1477
|
-
next.delete(connectionKey), next.size === 0 ? connectionLookup.delete(key) : connectionLookup.set(key, next);
|
|
1478
|
-
};
|
|
1479
|
-
remove(nodeId), remove(`${nodeId}-${type}`), handleId && remove(`${nodeId}-${type}-${handleId}`);
|
|
1480
|
-
}
|
|
1481
|
-
//#endregion
|
|
1482
|
-
//#region src/data/createSolidFlow.tsx
|
|
1483
|
-
const InitialNodeTypesMap = {
|
|
1484
|
-
input: InputNode,
|
|
1485
|
-
output: OutputNode,
|
|
1486
|
-
default: DefaultNode,
|
|
1487
|
-
group: GroupNode
|
|
1488
|
-
}, InitialEdgeTypesMap = {
|
|
1489
|
-
straight: StraightEdgeInternal,
|
|
1490
|
-
smoothstep: SmoothStepEdgeInternal,
|
|
1491
|
-
default: BezierEdgeInternal,
|
|
1492
|
-
step: StepEdgeInternal
|
|
1493
|
-
}, getInitialViewport = (_nodesInitialized, fitView, initialViewport, width, height, nodeLookup) => {
|
|
1494
|
-
if (fitView && !initialViewport && width && height) {
|
|
1495
|
-
let bounds = getInternalNodesBounds(nodeLookup, { filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)) });
|
|
1496
|
-
return getViewportForBounds$1(bounds, width, height, .5, 2, .1);
|
|
1497
|
-
}
|
|
1498
|
-
return initialViewport ?? {
|
|
1499
|
-
x: 0,
|
|
1500
|
-
y: 0,
|
|
1501
|
-
zoom: 1
|
|
1502
|
-
};
|
|
1503
|
-
}, createSolidFlow = (props) => {
|
|
1504
|
-
let _props = merge(getDefaultFlowStateProps(), props), nodeLookup = new ReactiveMap(), parentLookup = new ReactiveMap(), edgeLookup = new ReactiveMap(), connectionLookup = new ReactiveMap(), layoutedEdgesMap = new ReactiveMap(), startNodesInitialized = untrack(() => adoptUserNodes(_props.nodes, nodeLookup, parentLookup, {
|
|
1505
|
-
nodeExtent: _props.nodeExtent,
|
|
1506
|
-
nodeOrigin: _props.nodeOrigin,
|
|
1507
|
-
elevateNodesOnSelect: _props.elevateNodesOnSelect,
|
|
1508
|
-
zIndexMode: _props.zIndexMode,
|
|
1509
|
-
checkEquality: !0
|
|
1510
|
-
})), initialViewport = getInitialViewport(startNodesInitialized, _props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), mediaPrefersDark = createMediaQuery("(prefers-color-scheme: dark)", _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props), [ariaLabelConfig, setAriaLabelConfig] = createSignal(() => mergeAriaLabelConfig(config().ariaLabelConfig)), [ariaLiveMessage, setAriaLiveMessage] = createSignal(() => config().ariaLiveMessage), [clickConnectStartHandle, setClickConnectStartHandle] = createSignal(void 0), [connection, setConnection] = createSignal(initialConnection), [domNode, setDomNode] = createSignal(null), [dragging, setDragging] = createSignal(!1), [elementsSelectable, setElementsSelectable] = createSignal(() => config().elementsSelectable), [height, setHeight] = createSignal(() => config().height), [minZoom, _setMinZoom] = createSignal(() => config().minZoom), [maxZoom, _setMaxZoom] = createSignal(() => config().maxZoom), [nodesConnectable, setNodesConnectable] = createSignal(() => config().nodesDraggable), [nodesDraggable, setNodesDraggable] = createSignal(() => config().nodesDraggable), [panZoom, setPanZoom] = createSignal(null), [selectionRect, setSelectionRect] = createSignal(), [selectionRectMode, setSelectionRectMode] = createSignal(), [snapGrid, setSnapGrid] = createSignal(() => config().snapGrid), [translateExtent, _setTranslateExtent] = createSignal(() => config().translateExtent ?? infiniteExtent), [width, setWidth] = createSignal(() => config().width), [selectionKeyPressed, setSelectionKeyPressed] = createSignal(!1), [multiselectionKeyPressed, setMultiselectionKeyPressed] = createSignal(!1), [deleteKeyPressed, setDeleteKeyPressed] = createSignal(!1), [panActivationKeyPressed, setPanActivationKeyPressed] = createSignal(!1), [zoomActivationKeyPressed, setZoomActivationKeyPressed] = createSignal(!1), [nodesStore, setNodesStore] = createStore(_props.nodes), [edgesStore, setEdgesStore] = createStore(_props.edges), [viewportStore, setViewportStore] = createStore(_props.viewport ?? initialViewport);
|
|
1155
|
+
}), nodeLookup = new RecordMapFacade(internalNodes), initialViewport = getInitialViewport(_props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), [viewportStore, setViewportStore] = createStore(_props.viewport ?? initialViewport);
|
|
1511
1156
|
createEffect(() => config().nodes, (next) => {
|
|
1512
1157
|
setNodesStore(() => next);
|
|
1513
1158
|
}, { defer: !0 }), createEffect(() => config().edges, (next) => {
|
|
@@ -1553,7 +1198,7 @@ const InitialNodeTypesMap = {
|
|
|
1553
1198
|
return clickConnectStartHandle();
|
|
1554
1199
|
},
|
|
1555
1200
|
get colorMode() {
|
|
1556
|
-
return this._colorMode === "system" ?
|
|
1201
|
+
return this._colorMode === "system" ? prefersDark() ? "dark" : "light" : this._colorMode;
|
|
1557
1202
|
},
|
|
1558
1203
|
get connection() {
|
|
1559
1204
|
let state = connection();
|
|
@@ -1570,7 +1215,7 @@ const InitialNodeTypesMap = {
|
|
|
1570
1215
|
},
|
|
1571
1216
|
get edgeTypes() {
|
|
1572
1217
|
return {
|
|
1573
|
-
...
|
|
1218
|
+
...initialEdgeTypes,
|
|
1574
1219
|
...this._edgeTypes
|
|
1575
1220
|
};
|
|
1576
1221
|
},
|
|
@@ -1595,382 +1240,1213 @@ const InitialNodeTypesMap = {
|
|
|
1595
1240
|
get edges() {
|
|
1596
1241
|
return edgesStore;
|
|
1597
1242
|
},
|
|
1598
|
-
get nodes() {
|
|
1599
|
-
return nodesStore;
|
|
1243
|
+
get nodes() {
|
|
1244
|
+
return nodesStore;
|
|
1245
|
+
},
|
|
1246
|
+
get nodesConnectable() {
|
|
1247
|
+
return nodesConnectable();
|
|
1248
|
+
},
|
|
1249
|
+
get nodesDraggable() {
|
|
1250
|
+
return nodesDraggable();
|
|
1251
|
+
},
|
|
1252
|
+
get nodeTypes() {
|
|
1253
|
+
return {
|
|
1254
|
+
...initialNodeTypes,
|
|
1255
|
+
...this._nodeTypes
|
|
1256
|
+
};
|
|
1257
|
+
},
|
|
1258
|
+
get panZoom() {
|
|
1259
|
+
return panZoom();
|
|
1260
|
+
},
|
|
1261
|
+
get selectedNodes() {
|
|
1262
|
+
return nodesStore.filter((node) => node.selected);
|
|
1263
|
+
},
|
|
1264
|
+
get selectedEdges() {
|
|
1265
|
+
return edgesStore.filter((edge) => edge.selected);
|
|
1266
|
+
},
|
|
1267
|
+
get selectionRect() {
|
|
1268
|
+
return selectionRect();
|
|
1269
|
+
},
|
|
1270
|
+
get selectionRectMode() {
|
|
1271
|
+
return selectionRectMode();
|
|
1272
|
+
},
|
|
1273
|
+
get snapGrid() {
|
|
1274
|
+
return snapGrid();
|
|
1275
|
+
},
|
|
1276
|
+
get viewport() {
|
|
1277
|
+
return viewportStore;
|
|
1278
|
+
},
|
|
1279
|
+
get viewportInitialized() {
|
|
1280
|
+
return panZoom() !== null;
|
|
1281
|
+
},
|
|
1282
|
+
get nodesInitialized() {
|
|
1283
|
+
return nodesInitialized();
|
|
1284
|
+
},
|
|
1285
|
+
get visibleEdgeIds() {
|
|
1286
|
+
return visibleEdgeIds();
|
|
1287
|
+
},
|
|
1288
|
+
get visibleNodeIds() {
|
|
1289
|
+
return visibleNodeIds();
|
|
1290
|
+
},
|
|
1291
|
+
get visibleNodesMap() {
|
|
1292
|
+
return visibleNodesMap();
|
|
1293
|
+
},
|
|
1294
|
+
get transform() {
|
|
1295
|
+
return transform();
|
|
1296
|
+
},
|
|
1297
|
+
get translateExtent() {
|
|
1298
|
+
return translateExtent();
|
|
1299
|
+
},
|
|
1300
|
+
get width() {
|
|
1301
|
+
return width();
|
|
1302
|
+
},
|
|
1303
|
+
get selectionKeyPressed() {
|
|
1304
|
+
return selectionKeyPressed();
|
|
1305
|
+
},
|
|
1306
|
+
get multiselectionKeyPressed() {
|
|
1307
|
+
return multiselectionKeyPressed();
|
|
1308
|
+
},
|
|
1309
|
+
get deleteKeyPressed() {
|
|
1310
|
+
return deleteKeyPressed();
|
|
1311
|
+
},
|
|
1312
|
+
get panActivationKeyPressed() {
|
|
1313
|
+
return panActivationKeyPressed();
|
|
1314
|
+
},
|
|
1315
|
+
get zoomActivationKeyPressed() {
|
|
1316
|
+
return zoomActivationKeyPressed();
|
|
1317
|
+
}
|
|
1318
|
+
}), visibleNodesMap = createMemo(() => nodeLookup), visibleNodeIds = createMemo(() => Object.keys(internalNodes)), parentIds = createParentIds({ get nodes() {
|
|
1319
|
+
return store.nodes;
|
|
1320
|
+
} }), edgeLookup = createEdgeLookup({ get edges() {
|
|
1321
|
+
return store.edges;
|
|
1322
|
+
} }), connections = createConnections({ get edges() {
|
|
1323
|
+
return store.edges;
|
|
1324
|
+
} }), layoutedEdges = createLayoutedEdges({
|
|
1325
|
+
get edges() {
|
|
1326
|
+
return store.edges;
|
|
1327
|
+
},
|
|
1328
|
+
get connectionMode() {
|
|
1329
|
+
return store.connectionMode;
|
|
1330
|
+
},
|
|
1331
|
+
get defaultEdgeOptions() {
|
|
1332
|
+
return store.defaultEdgeOptions;
|
|
1333
|
+
},
|
|
1334
|
+
get elevateEdgesOnSelect() {
|
|
1335
|
+
return store.elevateEdgesOnSelect;
|
|
1336
|
+
},
|
|
1337
|
+
get zIndexMode() {
|
|
1338
|
+
return store.zIndexMode;
|
|
1339
|
+
},
|
|
1340
|
+
get onlyRenderVisibleElements() {
|
|
1341
|
+
return store.onlyRenderVisibleElements;
|
|
1342
|
+
},
|
|
1343
|
+
get width() {
|
|
1344
|
+
return store.width;
|
|
1345
|
+
},
|
|
1346
|
+
get height() {
|
|
1347
|
+
return store.height;
|
|
1348
|
+
},
|
|
1349
|
+
get transform() {
|
|
1350
|
+
return store.transform;
|
|
1351
|
+
},
|
|
1352
|
+
get onError() {
|
|
1353
|
+
return store.onError;
|
|
1354
|
+
},
|
|
1355
|
+
nodeLookup
|
|
1356
|
+
}), visibleEdgeIds = createMemo(() => Object.keys(layoutedEdges)), getEdge = (id) => layoutedEdges[id], fitView = async (options) => store.panZoom ? await fitViewport({
|
|
1357
|
+
nodes: nodeLookup,
|
|
1358
|
+
width: store.width,
|
|
1359
|
+
height: store.height,
|
|
1360
|
+
panZoom: store.panZoom,
|
|
1361
|
+
minZoom: store.minZoom,
|
|
1362
|
+
maxZoom: store.maxZoom
|
|
1363
|
+
}, options ?? config().fitViewOptions) : !1, resetStoreValues = () => {
|
|
1364
|
+
setDragging(!1), setSelectionRect(void 0), setSelectionRectMode(void 0), setSelectionKeyPressed(!1), setMultiselectionKeyPressed(!1), setDeleteKeyPressed(!1), setPanActivationKeyPressed(!1), setZoomActivationKeyPressed(!1), setConnection({ ...initialConnection }), setClickConnectStartHandle(void 0), setViewportStore(() => config().initialViewport ?? {
|
|
1365
|
+
x: 0,
|
|
1366
|
+
y: 0,
|
|
1367
|
+
zoom: 1
|
|
1368
|
+
}), setAriaLiveMessage(""), setSnapGrid(void 0);
|
|
1369
|
+
}, addEdge = (edgeParams) => {
|
|
1370
|
+
setEdgesStore((edges) => {
|
|
1371
|
+
let next = addEdge$1(edgeParams, edges);
|
|
1372
|
+
next !== edges && edges.push(next[next.length - 1]);
|
|
1373
|
+
});
|
|
1374
|
+
}, initialFitViewApplied = !1, initialNodesMeasured = !1, applyInitialFitView = (initialFitView) => {
|
|
1375
|
+
initialFitViewApplied = !initialFitView;
|
|
1376
|
+
}, tryInitialFitView = () => {
|
|
1377
|
+
initialFitViewApplied || !initialNodesMeasured || untrack(() => store.panZoom && store.width && store.height) && (initialFitViewApplied = !0, untrack(() => fitView()));
|
|
1378
|
+
}, updateNodePositions = (nodeDragItems, dragging = !1) => {
|
|
1379
|
+
setNodesStore((nodes) => {
|
|
1380
|
+
for (let node of nodes) nodeDragItems.has(node.id) && (node.dragging = dragging, node.position = nodeDragItems.get(node.id).position);
|
|
1381
|
+
});
|
|
1382
|
+
}, applyMeasurementWrites = (writes) => {
|
|
1383
|
+
setMeasurementsStore((draft) => {
|
|
1384
|
+
for (let write of writes) if (write.hidden) {
|
|
1385
|
+
let entry = draft[write.id];
|
|
1386
|
+
entry && (entry.handleBounds = void 0);
|
|
1387
|
+
} else draft[write.id] = {
|
|
1388
|
+
measured: write.measured,
|
|
1389
|
+
handleBounds: write.handleBounds
|
|
1390
|
+
};
|
|
1391
|
+
});
|
|
1392
|
+
}, applyNodeChanges = (changes) => {
|
|
1393
|
+
changes.length !== 0 && setNodesStore((nodes) => {
|
|
1394
|
+
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
1395
|
+
for (let change of changes) {
|
|
1396
|
+
let node = nodeById.get(change.id);
|
|
1397
|
+
if (node) switch (change.type) {
|
|
1398
|
+
case "dimensions":
|
|
1399
|
+
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
1400
|
+
...node.measured,
|
|
1401
|
+
...change.dimensions
|
|
1402
|
+
};
|
|
1403
|
+
break;
|
|
1404
|
+
case "position": node.position = change.position ?? node.position;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
}, markInitialNodesMeasured = () => {
|
|
1409
|
+
initialNodesMeasured = !0, tryInitialFitView();
|
|
1410
|
+
}, requestMeasure = () => {}, setMeasureRequester = (fn) => {
|
|
1411
|
+
requestMeasure = fn;
|
|
1412
|
+
}, zoomBy = async (factor, options) => store.panZoom ? store.panZoom.scaleBy(factor, options) : !1, zoomIn = (options) => zoomBy(1.2, options), zoomOut = (options) => zoomBy(1 / 1.2, options), setCenter = async (x, y, options) => {
|
|
1413
|
+
let nextZoom = options?.zoom === void 0 ? store.maxZoom : options.zoom, currentPanZoom = store.panZoom;
|
|
1414
|
+
return currentPanZoom ? (await currentPanZoom.setViewport({
|
|
1415
|
+
x: store.width / 2 - x * nextZoom,
|
|
1416
|
+
y: store.height / 2 - y * nextZoom,
|
|
1417
|
+
zoom: nextZoom
|
|
1418
|
+
}, {
|
|
1419
|
+
duration: options?.duration,
|
|
1420
|
+
ease: options?.ease,
|
|
1421
|
+
interpolate: options?.interpolate
|
|
1422
|
+
}), Promise.resolve(!0)) : Promise.resolve(!1);
|
|
1423
|
+
}, setPaneClickDistance = (distance) => {
|
|
1424
|
+
store.panZoom?.setClickDistance(distance);
|
|
1425
|
+
}, unselectNodesAndEdges = ({ nodes: _nodes, edges } = {}) => {
|
|
1426
|
+
let nodesToUnselect = new Set((_nodes || store.nodes).map(({ id }) => id));
|
|
1427
|
+
nodesToUnselect.size && setNodesStore((nodes) => {
|
|
1428
|
+
for (let node of nodes) nodesToUnselect.has(node.id) && (node.selected = !1);
|
|
1429
|
+
});
|
|
1430
|
+
let edgesToUnselect = new Set((edges ?? store.edges).map(({ id }) => id));
|
|
1431
|
+
edgesToUnselect.size && setEdgesStore((edges) => {
|
|
1432
|
+
for (let edge of edges) edgesToUnselect.has(edge.id) && (edge.selected = !1);
|
|
1433
|
+
}), flush();
|
|
1434
|
+
}, addSelectedNodes = (ids) => {
|
|
1435
|
+
let isMultiSelection = store.multiselectionKeyPressed;
|
|
1436
|
+
setNodesStore((nodes) => {
|
|
1437
|
+
for (let node of nodes) {
|
|
1438
|
+
let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
1439
|
+
node.selected !== selected && (node.selected = selected);
|
|
1440
|
+
}
|
|
1441
|
+
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
1442
|
+
}, addSelectedEdges = (ids) => {
|
|
1443
|
+
let isMultiSelection = store.multiselectionKeyPressed;
|
|
1444
|
+
setEdgesStore((edges) => {
|
|
1445
|
+
for (let edge of edges) {
|
|
1446
|
+
let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
1447
|
+
edge.selected !== selected && (edge.selected = selected);
|
|
1448
|
+
}
|
|
1449
|
+
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
1450
|
+
}, handleNodeSelection = (id, unselect, nodeRef) => {
|
|
1451
|
+
let node = store.nodes.find((n) => n.id === id);
|
|
1452
|
+
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
1453
|
+
nodes: [node],
|
|
1454
|
+
edges: []
|
|
1455
|
+
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
1456
|
+
}, handleEdgeSelection = (id) => {
|
|
1457
|
+
let edge = edgeLookup[id];
|
|
1458
|
+
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
1459
|
+
nodes: [],
|
|
1460
|
+
edges: [edge]
|
|
1461
|
+
}) : addSelectedEdges([id]));
|
|
1462
|
+
}, moveSelectedNodes = (direction, factor) => {
|
|
1463
|
+
let nodeUpdates = /* @__PURE__ */ new Map(), xVelo = store.snapGrid?.[0] ?? 5, yVelo = store.snapGrid?.[1] ?? 5, xDiff = direction.x * xVelo * factor, yDiff = direction.y * yVelo * factor;
|
|
1464
|
+
for (let node of nodeLookup.values()) {
|
|
1465
|
+
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
1466
|
+
let nextPosition = {
|
|
1467
|
+
x: node.internals.positionAbsolute.x + xDiff,
|
|
1468
|
+
y: node.internals.positionAbsolute.y + yDiff
|
|
1469
|
+
};
|
|
1470
|
+
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
1471
|
+
let { position } = calculateNodePosition({
|
|
1472
|
+
nodeId: node.id,
|
|
1473
|
+
nextPosition,
|
|
1474
|
+
nodeLookup,
|
|
1475
|
+
nodeExtent: store.nodeExtent,
|
|
1476
|
+
nodeOrigin: store.nodeOrigin,
|
|
1477
|
+
onError: store.onError
|
|
1478
|
+
});
|
|
1479
|
+
nodeUpdates.set(node.id, { position });
|
|
1480
|
+
}
|
|
1481
|
+
updateNodePositions(nodeUpdates);
|
|
1482
|
+
}, panBy$1 = (delta) => panBy({
|
|
1483
|
+
delta,
|
|
1484
|
+
panZoom: store.panZoom,
|
|
1485
|
+
transform: store.transform,
|
|
1486
|
+
translateExtent: store.translateExtent,
|
|
1487
|
+
width: store.width,
|
|
1488
|
+
height: store.height
|
|
1489
|
+
}), cancelConnection = () => {
|
|
1490
|
+
setConnection({ ...initialConnection });
|
|
1491
|
+
}, reset = () => {
|
|
1492
|
+
resetStoreValues(), unselectNodesAndEdges();
|
|
1493
|
+
}, flow = {
|
|
1494
|
+
get nodes() {
|
|
1495
|
+
return store.nodes;
|
|
1496
|
+
},
|
|
1497
|
+
get edges() {
|
|
1498
|
+
return store.edges;
|
|
1499
|
+
},
|
|
1500
|
+
get internalNodes() {
|
|
1501
|
+
return internalNodes;
|
|
1502
|
+
},
|
|
1503
|
+
get layoutedEdges() {
|
|
1504
|
+
return layoutedEdges;
|
|
1505
|
+
},
|
|
1506
|
+
get connections() {
|
|
1507
|
+
return connections;
|
|
1508
|
+
},
|
|
1509
|
+
selection: {
|
|
1510
|
+
get nodes() {
|
|
1511
|
+
return store.selectedNodes;
|
|
1512
|
+
},
|
|
1513
|
+
get edges() {
|
|
1514
|
+
return store.selectedEdges;
|
|
1515
|
+
}
|
|
1516
|
+
},
|
|
1517
|
+
get nodesInitialized() {
|
|
1518
|
+
return store.nodesInitialized;
|
|
1519
|
+
},
|
|
1520
|
+
get viewportInitialized() {
|
|
1521
|
+
return store.viewportInitialized;
|
|
1522
|
+
},
|
|
1523
|
+
get viewport() {
|
|
1524
|
+
return store.viewport;
|
|
1525
|
+
},
|
|
1526
|
+
get width() {
|
|
1527
|
+
return store.width;
|
|
1528
|
+
},
|
|
1529
|
+
get height() {
|
|
1530
|
+
return store.height;
|
|
1531
|
+
},
|
|
1532
|
+
get colorMode() {
|
|
1533
|
+
return store.colorMode;
|
|
1534
|
+
},
|
|
1535
|
+
get connection() {
|
|
1536
|
+
return store.connection;
|
|
1537
|
+
},
|
|
1538
|
+
get dragging() {
|
|
1539
|
+
return store.dragging;
|
|
1540
|
+
},
|
|
1541
|
+
get minZoom() {
|
|
1542
|
+
return store.minZoom;
|
|
1543
|
+
},
|
|
1544
|
+
get maxZoom() {
|
|
1545
|
+
return store.maxZoom;
|
|
1546
|
+
},
|
|
1547
|
+
get nodesDraggable() {
|
|
1548
|
+
return store.nodesDraggable;
|
|
1549
|
+
},
|
|
1550
|
+
get nodesConnectable() {
|
|
1551
|
+
return store.nodesConnectable;
|
|
1552
|
+
},
|
|
1553
|
+
get elementsSelectable() {
|
|
1554
|
+
return store.elementsSelectable;
|
|
1555
|
+
},
|
|
1556
|
+
get snapGrid() {
|
|
1557
|
+
return store.snapGrid;
|
|
1558
|
+
}
|
|
1559
|
+
}, getNodeRect = (node) => {
|
|
1560
|
+
let nodeToUse = isNode(node) ? node : nodeLookup.get(node.id), position = nodeToUse.parentId ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, store.nodeOrigin) : nodeToUse.position, nodeWithPosition = {
|
|
1561
|
+
...nodeToUse,
|
|
1562
|
+
position,
|
|
1563
|
+
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
1564
|
+
height: nodeToUse.measured?.height ?? nodeToUse.height
|
|
1565
|
+
};
|
|
1566
|
+
return nodeToRect(nodeWithPosition);
|
|
1567
|
+
}, updateNode = (id, nodeUpdate, options = { replace: !1 }) => {
|
|
1568
|
+
setNodesStore((nodes) => {
|
|
1569
|
+
let index = nodes.findIndex((node) => node.id === id);
|
|
1570
|
+
if (index === -1) return;
|
|
1571
|
+
let node = nodes[index], nextNode = typeof nodeUpdate == "function" ? nodeUpdate(node) : nodeUpdate;
|
|
1572
|
+
nodes[index] = options?.replace && isNode(nextNode) ? nextNode : {
|
|
1573
|
+
...node,
|
|
1574
|
+
...nextNode
|
|
1575
|
+
};
|
|
1576
|
+
});
|
|
1577
|
+
}, commands = {
|
|
1578
|
+
fitView,
|
|
1579
|
+
fitBounds: async (bounds, options) => {
|
|
1580
|
+
if (!store.panZoom) return !1;
|
|
1581
|
+
let viewport = getViewportForBounds$1(bounds, store.width, store.height, store.minZoom, store.maxZoom, options?.padding ?? .1);
|
|
1582
|
+
return await store.panZoom.setViewport(viewport, {
|
|
1583
|
+
duration: options?.duration,
|
|
1584
|
+
ease: options?.ease,
|
|
1585
|
+
interpolate: options?.interpolate
|
|
1586
|
+
}), !0;
|
|
1587
|
+
},
|
|
1588
|
+
zoomIn,
|
|
1589
|
+
zoomOut,
|
|
1590
|
+
setZoom: (zoomLevel, options) => {
|
|
1591
|
+
let currentPanZoom = store.panZoom;
|
|
1592
|
+
return currentPanZoom ? currentPanZoom.scaleTo(zoomLevel, { duration: options?.duration }) : Promise.resolve(!1);
|
|
1600
1593
|
},
|
|
1601
|
-
|
|
1602
|
-
|
|
1594
|
+
setCenter,
|
|
1595
|
+
setViewport: async (nextViewport, options) => {
|
|
1596
|
+
let currentViewport = store.viewport;
|
|
1597
|
+
return store.panZoom ? (await store.panZoom.setViewport({
|
|
1598
|
+
x: nextViewport.x ?? currentViewport.x,
|
|
1599
|
+
y: nextViewport.y ?? currentViewport.y,
|
|
1600
|
+
zoom: nextViewport.zoom ?? currentViewport.zoom
|
|
1601
|
+
}, options), !0) : !1;
|
|
1603
1602
|
},
|
|
1604
|
-
|
|
1605
|
-
|
|
1603
|
+
panBy: panBy$1,
|
|
1604
|
+
screenToFlowPosition: (position, options = { snapToGrid: !0 }) => {
|
|
1605
|
+
if (!store.domNode) return position;
|
|
1606
|
+
let _snapGrid = options.snapToGrid ? store.snapGrid : !1, { x, y, zoom } = store.viewport, { x: domX, y: domY } = store.domNode.getBoundingClientRect(), correctedPosition = {
|
|
1607
|
+
x: position.x - domX,
|
|
1608
|
+
y: position.y - domY
|
|
1609
|
+
};
|
|
1610
|
+
return pointToRendererPoint(correctedPosition, [
|
|
1611
|
+
x,
|
|
1612
|
+
y,
|
|
1613
|
+
zoom
|
|
1614
|
+
], _snapGrid !== null, _snapGrid || [1, 1]);
|
|
1606
1615
|
},
|
|
1607
|
-
|
|
1616
|
+
flowToScreenPosition: (position) => {
|
|
1617
|
+
if (!store.domNode) return position;
|
|
1618
|
+
let { x, y, zoom } = store.viewport, { x: domX, y: domY } = store.domNode.getBoundingClientRect(), rendererPosition = rendererPointToPoint(position, [
|
|
1619
|
+
x,
|
|
1620
|
+
y,
|
|
1621
|
+
zoom
|
|
1622
|
+
]);
|
|
1608
1623
|
return {
|
|
1609
|
-
|
|
1610
|
-
|
|
1624
|
+
x: rendererPosition.x + domX,
|
|
1625
|
+
y: rendererPosition.y + domY
|
|
1611
1626
|
};
|
|
1612
1627
|
},
|
|
1613
|
-
|
|
1614
|
-
|
|
1628
|
+
addNodes: (payload) => {
|
|
1629
|
+
let newNodes = Array.isArray(payload) ? payload : [payload];
|
|
1630
|
+
setNodesStore((nodes) => [...nodes, ...newNodes]);
|
|
1615
1631
|
},
|
|
1616
|
-
|
|
1617
|
-
|
|
1632
|
+
addEdges: (payload) => {
|
|
1633
|
+
let newEdges = Array.isArray(payload) ? payload : [payload];
|
|
1634
|
+
setEdgesStore((edges) => [...edges, ...newEdges]);
|
|
1618
1635
|
},
|
|
1619
|
-
|
|
1620
|
-
|
|
1636
|
+
setNodes: setNodesStore,
|
|
1637
|
+
setEdges: setEdgesStore,
|
|
1638
|
+
updateNode,
|
|
1639
|
+
updateNodeData: (id, dataUpdate, options) => {
|
|
1640
|
+
let node = nodeLookup.get(id)?.internals.userNode;
|
|
1641
|
+
if (!node) return;
|
|
1642
|
+
let nextData = typeof dataUpdate == "function" ? dataUpdate(node) : dataUpdate;
|
|
1643
|
+
updateNode(id, (current) => ({
|
|
1644
|
+
...current,
|
|
1645
|
+
data: options?.replace ? nextData : {
|
|
1646
|
+
...current.data,
|
|
1647
|
+
...nextData
|
|
1648
|
+
}
|
|
1649
|
+
}));
|
|
1621
1650
|
},
|
|
1622
|
-
|
|
1623
|
-
|
|
1651
|
+
updateEdge: (id, edgeUpdate, options = { replace: !1 }) => {
|
|
1652
|
+
setEdgesStore((edges) => {
|
|
1653
|
+
let index = edges.findIndex((edge) => edge.id === id);
|
|
1654
|
+
if (index === -1) return;
|
|
1655
|
+
let edge = edges[index], nextEdge = typeof edgeUpdate == "function" ? edgeUpdate(edge) : edgeUpdate;
|
|
1656
|
+
edges[index] = options.replace && isEdge(nextEdge) ? nextEdge : {
|
|
1657
|
+
...edge,
|
|
1658
|
+
...nextEdge
|
|
1659
|
+
};
|
|
1660
|
+
});
|
|
1624
1661
|
},
|
|
1625
|
-
|
|
1626
|
-
|
|
1662
|
+
deleteElements: async ({ nodes: nodesToRemove = [], edges: edgesToRemove = [] }) => {
|
|
1663
|
+
let { nodes: matchingNodes, edges: matchingEdges } = await getElementsToRemove({
|
|
1664
|
+
nodesToRemove,
|
|
1665
|
+
edgesToRemove,
|
|
1666
|
+
nodes: store.nodes,
|
|
1667
|
+
edges: store.edges,
|
|
1668
|
+
onBeforeDelete: store.onBeforeDelete
|
|
1669
|
+
});
|
|
1670
|
+
if (matchingEdges) {
|
|
1671
|
+
let remainingEdges = store.edges.filter((edge) => !matchingEdges.some(({ id }) => id === edge.id));
|
|
1672
|
+
store.onEdgesDelete?.(matchingEdges), setEdgesStore(() => remainingEdges);
|
|
1673
|
+
}
|
|
1674
|
+
if (matchingNodes) {
|
|
1675
|
+
let remainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
|
|
1676
|
+
store.onNodesDelete?.(matchingNodes), setNodesStore(() => remainingNodes);
|
|
1677
|
+
}
|
|
1678
|
+
return {
|
|
1679
|
+
deletedNodes: matchingNodes,
|
|
1680
|
+
deletedEdges: matchingEdges
|
|
1681
|
+
};
|
|
1627
1682
|
},
|
|
1628
|
-
|
|
1629
|
-
|
|
1683
|
+
getIntersectingNodes: (nodeOrRect, partially = !0, nodesToIntersect) => {
|
|
1684
|
+
let isRect = isRectObject(nodeOrRect), nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
1685
|
+
return nodeRect ? (nodesToIntersect || store.nodes).filter((n) => {
|
|
1686
|
+
let internalNode = nodeLookup.get(n.id);
|
|
1687
|
+
if (!internalNode || !isRect && n.id === nodeOrRect.id) return !1;
|
|
1688
|
+
let currNodeRect = nodeToRect(internalNode), overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
1689
|
+
return partially && overlappingArea > 0 || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
1690
|
+
}) : [];
|
|
1630
1691
|
},
|
|
1631
|
-
|
|
1632
|
-
|
|
1692
|
+
isNodeIntersecting: (nodeOrRect, area, partially = !0) => {
|
|
1693
|
+
let nodeRect = isRectObject(nodeOrRect) ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
1694
|
+
if (!nodeRect) return !1;
|
|
1695
|
+
let overlappingArea = getOverlappingArea(nodeRect, area);
|
|
1696
|
+
return partially && overlappingArea > 0 || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
1633
1697
|
},
|
|
1634
|
-
|
|
1635
|
-
|
|
1698
|
+
getNodesBounds: (nodesToMeasure) => getNodesBounds$1(nodesToMeasure, {
|
|
1699
|
+
nodeLookup,
|
|
1700
|
+
nodeOrigin: store.nodeOrigin
|
|
1701
|
+
}),
|
|
1702
|
+
updateNodeInternals: (id) => {
|
|
1703
|
+
let updateIds = Array.isArray(id) ? id : [id], updates = [];
|
|
1704
|
+
for (let updateId of updateIds) {
|
|
1705
|
+
let nodeElement = store.domNode?.querySelector(`.solid-flow__node[data-id="${updateId}"]`);
|
|
1706
|
+
nodeElement && updates.push([updateId, {
|
|
1707
|
+
id: updateId,
|
|
1708
|
+
nodeElement,
|
|
1709
|
+
force: !0
|
|
1710
|
+
}]);
|
|
1711
|
+
}
|
|
1712
|
+
requestMeasure(updates);
|
|
1636
1713
|
},
|
|
1637
|
-
|
|
1638
|
-
|
|
1714
|
+
toObject: () => structuredClone({
|
|
1715
|
+
nodes: [...snapshot(store.nodes)],
|
|
1716
|
+
edges: [...snapshot(store.edges)],
|
|
1717
|
+
viewport: { ...snapshot(store.viewport) }
|
|
1718
|
+
})
|
|
1719
|
+
};
|
|
1720
|
+
return createEffect(() => !!(width() && height() && panZoom()), (ready) => {
|
|
1721
|
+
ready && tryInitialFitView();
|
|
1722
|
+
}), createEffect(() => ({
|
|
1723
|
+
panZoom: store.panZoom,
|
|
1724
|
+
viewport: {
|
|
1725
|
+
x: store.viewport.x,
|
|
1726
|
+
y: store.viewport.y,
|
|
1727
|
+
zoom: store.viewport.zoom
|
|
1728
|
+
}
|
|
1729
|
+
}), ({ panZoom, viewport }) => {
|
|
1730
|
+
panZoom?.syncViewport(viewport);
|
|
1731
|
+
}), createEffect(() => ({
|
|
1732
|
+
panZoom: panZoom(),
|
|
1733
|
+
extent: [store.minZoom, store.maxZoom]
|
|
1734
|
+
}), ({ panZoom, extent }) => {
|
|
1735
|
+
panZoom?.setScaleExtent(extent);
|
|
1736
|
+
}), createEffect(() => ({
|
|
1737
|
+
panZoom: panZoom(),
|
|
1738
|
+
extent: store.translateExtent
|
|
1739
|
+
}), ({ panZoom, extent }) => {
|
|
1740
|
+
panZoom?.setTranslateExtent(extent);
|
|
1741
|
+
}), createEffect(() => new Set(store.nodes.map((n) => n.id)), (currentIds) => {
|
|
1742
|
+
setMeasurementsStore((draft) => {
|
|
1743
|
+
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
1744
|
+
});
|
|
1745
|
+
}), {
|
|
1746
|
+
store,
|
|
1747
|
+
flow,
|
|
1748
|
+
commands,
|
|
1749
|
+
internalNodes,
|
|
1750
|
+
layoutedEdges,
|
|
1751
|
+
nodeLookup,
|
|
1752
|
+
edgeLookup,
|
|
1753
|
+
parentIds,
|
|
1754
|
+
connections,
|
|
1755
|
+
actions: {
|
|
1756
|
+
getEdge,
|
|
1757
|
+
applyInitialFitView,
|
|
1758
|
+
applyMeasurementWrites,
|
|
1759
|
+
applyNodeChanges,
|
|
1760
|
+
markInitialNodesMeasured,
|
|
1761
|
+
setMeasureRequester,
|
|
1762
|
+
resetStoreValues,
|
|
1763
|
+
setAriaLabelConfig,
|
|
1764
|
+
setAriaLiveMessage,
|
|
1765
|
+
setClickConnectStartHandle,
|
|
1766
|
+
setConfig,
|
|
1767
|
+
setConnection,
|
|
1768
|
+
setDeleteKeyPressed,
|
|
1769
|
+
setDomNode,
|
|
1770
|
+
setDragging,
|
|
1771
|
+
get setEdges() {
|
|
1772
|
+
return setEdgesStore;
|
|
1773
|
+
},
|
|
1774
|
+
setElementsSelectable,
|
|
1775
|
+
setHeight,
|
|
1776
|
+
setMultiselectionKeyPressed,
|
|
1777
|
+
get setNodes() {
|
|
1778
|
+
return setNodesStore;
|
|
1779
|
+
},
|
|
1780
|
+
setNodesConnectable,
|
|
1781
|
+
setNodesDraggable,
|
|
1782
|
+
setPanActivationKeyPressed,
|
|
1783
|
+
setPanZoom,
|
|
1784
|
+
setSelectionKeyPressed,
|
|
1785
|
+
setSelectionRect,
|
|
1786
|
+
setSelectionRectMode,
|
|
1787
|
+
get setViewport() {
|
|
1788
|
+
return (viewport) => setViewportStore(() => viewport);
|
|
1789
|
+
},
|
|
1790
|
+
setWidth,
|
|
1791
|
+
setZoomActivationKeyPressed,
|
|
1792
|
+
addEdge,
|
|
1793
|
+
updateNodePositions,
|
|
1794
|
+
zoomIn,
|
|
1795
|
+
zoomOut,
|
|
1796
|
+
fitView,
|
|
1797
|
+
setCenter,
|
|
1798
|
+
setPaneClickDistance,
|
|
1799
|
+
unselectNodesAndEdges,
|
|
1800
|
+
addSelectedNodes,
|
|
1801
|
+
addSelectedEdges,
|
|
1802
|
+
handleNodeSelection,
|
|
1803
|
+
handleEdgeSelection,
|
|
1804
|
+
moveSelectedNodes,
|
|
1805
|
+
panBy: panBy$1,
|
|
1806
|
+
cancelConnection,
|
|
1807
|
+
reset
|
|
1808
|
+
}
|
|
1809
|
+
};
|
|
1810
|
+
}, getEdgeId = (connection) => {
|
|
1811
|
+
let { source, sourceHandle, target, targetHandle } = connection;
|
|
1812
|
+
return `xy-edge__${source}${sourceHandle || ""}-${target}${targetHandle || ""}`;
|
|
1813
|
+
}, NodeConnectableContext = createContext(null);
|
|
1814
|
+
function useNodeConnectable() {
|
|
1815
|
+
let ctx = useContext(NodeConnectableContext);
|
|
1816
|
+
if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeConnectable");
|
|
1817
|
+
return ctx;
|
|
1818
|
+
}
|
|
1819
|
+
//#endregion
|
|
1820
|
+
//#region src/components/graph/handle/Handle.tsx
|
|
1821
|
+
var _tmpl$$29 = /* @__PURE__ */ template("<div>");
|
|
1822
|
+
const Handle = (props) => {
|
|
1823
|
+
let _props = propDefaults(props, {
|
|
1824
|
+
type: "source",
|
|
1825
|
+
position: "top",
|
|
1826
|
+
isConnectableStart: !0,
|
|
1827
|
+
isConnectableEnd: !0
|
|
1828
|
+
}), { store, nodeLookup, connections, actions } = useInternalSolidFlow(), rest = omit(_props, "id", "type", "position", "isConnectable", "isConnectableStart", "isConnectableEnd", "isValidConnection", "onConnect", "onDisconnect", "children", "class", "style"), nodeId = useNodeId(), nodeConnectable = useNodeConnectable(), connectable = () => _props.isConnectable ?? nodeConnectable(), isTarget = () => _props.type === "target", handleId = () => _props.id ?? null, connectionInProcess = () => !!store.connection.fromHandle, connectingFrom = () => store.connection.fromHandle && store.connection.fromHandle.nodeId === nodeId() && store.connection.fromHandle.type === _props.type && store.connection.fromHandle.id === handleId(), connectingTo = () => store.connection.toHandle && store.connection.toHandle.nodeId === nodeId() && store.connection.toHandle.type === _props.type && store.connection.toHandle.id === handleId(), isPossibleTargetHandle = () => store.connectionMode === "strict" ? store.connection.fromHandle?.type !== _props.type : nodeId() !== store.connection.fromHandle?.nodeId || handleId() !== store.connection.fromHandle?.id, valid = () => !!(connectingTo() && store.connection.isValid), prevConnections = null;
|
|
1829
|
+
createEffect(() => {
|
|
1830
|
+
if (!_props.onConnect && !_props.onDisconnect) return null;
|
|
1831
|
+
let rec = connections[connectionKey(nodeId(), _props.type, _props.id)], map = /* @__PURE__ */ new Map();
|
|
1832
|
+
for (let key of Object.keys(rec ?? {})) map.set(key, { ...rec[key] });
|
|
1833
|
+
return { connections: map };
|
|
1834
|
+
}, (current) => {
|
|
1835
|
+
if (!current) return;
|
|
1836
|
+
let { connections: next } = current;
|
|
1837
|
+
prevConnections && !areConnectionMapsEqual(next, prevConnections) && (handleConnectionChange(prevConnections, next, props.onDisconnect), handleConnectionChange(next, prevConnections, props.onConnect)), prevConnections = next;
|
|
1838
|
+
});
|
|
1839
|
+
let onConnectExtended = (connection) => {
|
|
1840
|
+
let handleConnection = {
|
|
1841
|
+
...connection,
|
|
1842
|
+
id: getEdgeId(connection)
|
|
1843
|
+
}, edge = store.onBeforeConnect?.(handleConnection) ?? handleConnection;
|
|
1844
|
+
actions.addEdge(edge), store.onConnect?.(handleConnection);
|
|
1845
|
+
}, onPointerDown = (event) => {
|
|
1846
|
+
XYHandle.onPointerDown(event, {
|
|
1847
|
+
handleId: handleId(),
|
|
1848
|
+
nodeId: nodeId(),
|
|
1849
|
+
isTarget: isTarget(),
|
|
1850
|
+
connectionRadius: store.connectionRadius,
|
|
1851
|
+
domNode: store.domNode,
|
|
1852
|
+
nodeLookup,
|
|
1853
|
+
connectionMode: store.connectionMode,
|
|
1854
|
+
lib: store.lib,
|
|
1855
|
+
autoPanOnConnect: store.autoPanOnConnect,
|
|
1856
|
+
flowId: store.id,
|
|
1857
|
+
isValidConnection: _props.isValidConnection ?? store.isValidConnection,
|
|
1858
|
+
updateConnection: ((connection) => {
|
|
1859
|
+
actions.setConnection(connection), flush();
|
|
1860
|
+
}),
|
|
1861
|
+
cancelConnection: actions.cancelConnection,
|
|
1862
|
+
panBy: actions.panBy,
|
|
1863
|
+
onConnect: onConnectExtended,
|
|
1864
|
+
onConnectStart: (event, startParams) => {
|
|
1865
|
+
store.onConnectStart?.(event, {
|
|
1866
|
+
nodeId: startParams.nodeId,
|
|
1867
|
+
handleId: startParams.handleId,
|
|
1868
|
+
handleType: startParams.handleType
|
|
1869
|
+
});
|
|
1870
|
+
},
|
|
1871
|
+
onConnectEnd: store.onConnectEnd,
|
|
1872
|
+
getTransform: () => store.transform,
|
|
1873
|
+
getFromHandle: () => store.connection.fromHandle,
|
|
1874
|
+
autoPanSpeed: store.autoPanSpeed,
|
|
1875
|
+
dragThreshold: store.connectionDragThreshold,
|
|
1876
|
+
handleDomNode: event.currentTarget
|
|
1877
|
+
});
|
|
1878
|
+
}, onClick = (event) => {
|
|
1879
|
+
if (!nodeId() || !store.clickConnectStartHandle && !_props.isConnectableStart) return;
|
|
1880
|
+
if (!store.clickConnectStartHandle) {
|
|
1881
|
+
store.onClickConnectStart?.(event, {
|
|
1882
|
+
nodeId: nodeId(),
|
|
1883
|
+
handleId: handleId(),
|
|
1884
|
+
handleType: _props.type
|
|
1885
|
+
}), actions.setClickConnectStartHandle({
|
|
1886
|
+
nodeId: nodeId(),
|
|
1887
|
+
type: _props.type,
|
|
1888
|
+
id: handleId()
|
|
1889
|
+
});
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
let doc = getHostForElement(event.target), isValidConnectionHandler = _props.isValidConnection ?? store.isValidConnection, { connection, isValid } = XYHandle.isValid(event, {
|
|
1893
|
+
handle: {
|
|
1894
|
+
nodeId: nodeId(),
|
|
1895
|
+
id: handleId(),
|
|
1896
|
+
type: _props.type
|
|
1897
|
+
},
|
|
1898
|
+
connectionMode: store.connectionMode,
|
|
1899
|
+
fromNodeId: store.clickConnectStartHandle.nodeId,
|
|
1900
|
+
fromHandleId: store.clickConnectStartHandle.id ?? null,
|
|
1901
|
+
fromType: store.clickConnectStartHandle.type,
|
|
1902
|
+
isValidConnection: isValidConnectionHandler,
|
|
1903
|
+
flowId: store.id,
|
|
1904
|
+
doc,
|
|
1905
|
+
lib: store.lib,
|
|
1906
|
+
nodeLookup
|
|
1907
|
+
});
|
|
1908
|
+
isValid && connection && onConnectExtended(connection);
|
|
1909
|
+
let connectionClone = structuredClone(snapshot(store.connection));
|
|
1910
|
+
delete connectionClone.inProgress, connectionClone.toPosition = connectionClone.toHandle ? connectionClone.toHandle.position : null, store.onClickConnectEnd?.(event, connectionClone), actions.setClickConnectStartHandle(void 0);
|
|
1911
|
+
}, connectionIndicator = () => connectable() && (!connectionInProcess() || isPossibleTargetHandle()) && (connectionInProcess() || store.clickConnectStartHandle ? _props.isConnectableEnd : _props.isConnectableStart);
|
|
1912
|
+
var _el$ = _tmpl$$29();
|
|
1913
|
+
return spread(_el$, mergeProps(rest, {
|
|
1914
|
+
role: "button",
|
|
1915
|
+
get "aria-label"() {
|
|
1916
|
+
return store.ariaLabelConfig["handle.ariaLabel"];
|
|
1639
1917
|
},
|
|
1640
|
-
|
|
1641
|
-
|
|
1918
|
+
tabindex: -1,
|
|
1919
|
+
get "data-handleid"() {
|
|
1920
|
+
return handleId();
|
|
1642
1921
|
},
|
|
1643
|
-
get
|
|
1644
|
-
return
|
|
1922
|
+
get "data-nodeid"() {
|
|
1923
|
+
return nodeId();
|
|
1645
1924
|
},
|
|
1646
|
-
get
|
|
1647
|
-
return
|
|
1925
|
+
get "data-handlepos"() {
|
|
1926
|
+
return _props.position;
|
|
1648
1927
|
},
|
|
1649
|
-
get
|
|
1650
|
-
return
|
|
1928
|
+
get "data-id"() {
|
|
1929
|
+
return `${store.id}-${nodeId()}-${_props.id || null}-${_props.type}`;
|
|
1651
1930
|
},
|
|
1652
|
-
get
|
|
1653
|
-
return
|
|
1931
|
+
get onClick() {
|
|
1932
|
+
return store.clickConnect ? onClick : void 0;
|
|
1654
1933
|
},
|
|
1655
|
-
|
|
1656
|
-
|
|
1934
|
+
onPointerDown,
|
|
1935
|
+
get style() {
|
|
1936
|
+
return _props.style;
|
|
1657
1937
|
},
|
|
1658
|
-
get
|
|
1659
|
-
return
|
|
1938
|
+
get class() {
|
|
1939
|
+
return [
|
|
1940
|
+
"solid-flow__handle",
|
|
1941
|
+
`solid-flow__handle-${_props.position}`,
|
|
1942
|
+
store.noDragClass,
|
|
1943
|
+
store.noPanClass,
|
|
1944
|
+
_props.class,
|
|
1945
|
+
{
|
|
1946
|
+
valid: valid(),
|
|
1947
|
+
connectingto: !!connectingTo(),
|
|
1948
|
+
connectingfrom: !!connectingFrom(),
|
|
1949
|
+
source: !isTarget(),
|
|
1950
|
+
target: isTarget(),
|
|
1951
|
+
connectablestart: _props.isConnectableStart,
|
|
1952
|
+
connectableend: _props.isConnectableEnd,
|
|
1953
|
+
connectable: !!connectable(),
|
|
1954
|
+
connectionindicator: connectionIndicator()
|
|
1955
|
+
}
|
|
1956
|
+
];
|
|
1957
|
+
}
|
|
1958
|
+
}), !0), insert(_el$, () => _props.children), _el$;
|
|
1959
|
+
}, DefaultNode = (props) => {
|
|
1960
|
+
let _props = propDefaults(props, {
|
|
1961
|
+
targetPosition: Position$1.Top,
|
|
1962
|
+
sourcePosition: Position$1.Bottom
|
|
1963
|
+
});
|
|
1964
|
+
return [
|
|
1965
|
+
createComponent(Handle, {
|
|
1966
|
+
type: "target",
|
|
1967
|
+
get position() {
|
|
1968
|
+
return _props.targetPosition;
|
|
1969
|
+
},
|
|
1970
|
+
get isConnectable() {
|
|
1971
|
+
return _props.isConnectable;
|
|
1972
|
+
}
|
|
1973
|
+
}),
|
|
1974
|
+
memo(() => props.data.label),
|
|
1975
|
+
createComponent(Handle, {
|
|
1976
|
+
type: "source",
|
|
1977
|
+
get position() {
|
|
1978
|
+
return _props.sourcePosition;
|
|
1979
|
+
},
|
|
1980
|
+
get isConnectable() {
|
|
1981
|
+
return _props.isConnectable;
|
|
1982
|
+
}
|
|
1983
|
+
})
|
|
1984
|
+
];
|
|
1985
|
+
};
|
|
1986
|
+
//#endregion
|
|
1987
|
+
//#region src/components/graph/node/GroupNode.tsx
|
|
1988
|
+
var _tmpl$$28 = /* @__PURE__ */ template("<div style=position:absolute;left:0;top:0>");
|
|
1989
|
+
const GroupNode = (props) => (() => {
|
|
1990
|
+
var _el$ = _tmpl$$28();
|
|
1991
|
+
return effect(() => ({
|
|
1992
|
+
e: toPxString(props.width),
|
|
1993
|
+
t: toPxString(props.height)
|
|
1994
|
+
}), ({ e, t }, _p$) => {
|
|
1995
|
+
e !== _p$?.e && setStyleProperty(_el$, "width", e), t !== _p$?.t && setStyleProperty(_el$, "height", t);
|
|
1996
|
+
}), _el$;
|
|
1997
|
+
})(), InputNode = (props) => {
|
|
1998
|
+
let _props = propDefaults(props, { sourcePosition: Position$1.Bottom });
|
|
1999
|
+
return [memo(() => props.data?.label), createComponent(Handle, {
|
|
2000
|
+
type: "source",
|
|
2001
|
+
get position() {
|
|
2002
|
+
return _props.sourcePosition;
|
|
1660
2003
|
},
|
|
1661
|
-
get
|
|
1662
|
-
return
|
|
2004
|
+
get isConnectable() {
|
|
2005
|
+
return _props.isConnectable;
|
|
2006
|
+
}
|
|
2007
|
+
})];
|
|
2008
|
+
}, createDraggable = (elem, params) => {
|
|
2009
|
+
let { store, nodeLookup, actions } = useInternalSolidFlow(), [dragging, setDragging] = createSignal(!1);
|
|
2010
|
+
return createEffect(() => ({
|
|
2011
|
+
el: elem(),
|
|
2012
|
+
current: params()
|
|
2013
|
+
}), ({ el, current }) => {
|
|
2014
|
+
if (!el || current.disabled) return;
|
|
2015
|
+
let { onDrag, onDragStart, onDragStop, onNodeMouseDown } = current, dragInstance = XYDrag({
|
|
2016
|
+
onDrag,
|
|
2017
|
+
onDragStart: (event, dragItems, node, nodes) => {
|
|
2018
|
+
setDragging(!0), onDragStart?.(event, dragItems, node, nodes);
|
|
2019
|
+
},
|
|
2020
|
+
onDragStop: (event, dragItems, node, nodes) => {
|
|
2021
|
+
setDragging(!1), onDragStop?.(event, dragItems, node, nodes);
|
|
2022
|
+
},
|
|
2023
|
+
onNodeMouseDown,
|
|
2024
|
+
getStoreItems: () => ({
|
|
2025
|
+
nodes: store.nodes,
|
|
2026
|
+
nodeLookup,
|
|
2027
|
+
edges: store.edges,
|
|
2028
|
+
nodeExtent: store.nodeExtent,
|
|
2029
|
+
snapGrid: store.snapGrid ?? [0, 0],
|
|
2030
|
+
snapToGrid: !!store.snapGrid,
|
|
2031
|
+
autoPanSpeed: store.autoPanSpeed,
|
|
2032
|
+
nodeOrigin: store.nodeOrigin,
|
|
2033
|
+
multiSelectionActive: store.multiselectionKeyPressed,
|
|
2034
|
+
domNode: store.domNode,
|
|
2035
|
+
transform: store.transform,
|
|
2036
|
+
autoPanOnNodeDrag: store.autoPanOnNodeDrag,
|
|
2037
|
+
nodesDraggable: store.nodesDraggable,
|
|
2038
|
+
selectNodesOnDrag: store.selectNodesOnDrag,
|
|
2039
|
+
nodeDragThreshold: store.nodeDragThreshold,
|
|
2040
|
+
unselectNodesAndEdges: actions.unselectNodesAndEdges,
|
|
2041
|
+
updateNodePositions: actions.updateNodePositions,
|
|
2042
|
+
panBy: actions.panBy
|
|
2043
|
+
})
|
|
2044
|
+
});
|
|
2045
|
+
return dragInstance.update({
|
|
2046
|
+
domNode: el,
|
|
2047
|
+
nodeId: current.nodeId,
|
|
2048
|
+
noDragClassName: current.noDragClass,
|
|
2049
|
+
handleSelector: current.handleSelector,
|
|
2050
|
+
isSelectable: current.isSelectable,
|
|
2051
|
+
nodeClickDistance: current.nodeClickDistance
|
|
2052
|
+
}), () => {
|
|
2053
|
+
dragInstance.destroy();
|
|
2054
|
+
};
|
|
2055
|
+
}), dragging;
|
|
2056
|
+
}, NodeIdContext = createContext(null);
|
|
2057
|
+
function useNodeId() {
|
|
2058
|
+
let ctx = useContext(NodeIdContext);
|
|
2059
|
+
if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeId");
|
|
2060
|
+
return ctx;
|
|
2061
|
+
}
|
|
2062
|
+
//#endregion
|
|
2063
|
+
//#region src/components/graph/node/NodeWrapper.tsx
|
|
2064
|
+
var _tmpl$$27 = /* @__PURE__ */ template("<div>");
|
|
2065
|
+
const NodeWrapper = (props) => {
|
|
2066
|
+
let { store, nodeLookup, parentIds, actions } = useInternalSolidFlow(), [nodeRef, setNodeRef] = createSignal(), node = () => nodeLookup.get(props.nodeId), nodeId = () => node().id, nodeType = () => node().type ?? "default", deletable = () => node().deletable ?? !0, selectable = () => node().selectable ?? store.elementsSelectable, focusable = () => node().focusable ?? store.nodesFocusable, draggable = () => node().draggable ?? store.nodesDraggable, connectable = () => node().connectable ?? store.nodesConnectable, userNode = () => node().internals.userNode, nodeTypeValid = () => nodeType() in store.nodeTypes, nodeComponent = () => store.nodeTypes[nodeType()], isParentNode = () => !!parentIds[node().id], transform = () => {
|
|
2067
|
+
let { x, y } = node().internals.positionAbsolute;
|
|
2068
|
+
return `translate(${x}px, ${y}px)`;
|
|
2069
|
+
}, sizeStyle = () => {
|
|
2070
|
+
let w = node().width ?? node().initialWidth, h = node().height ?? node().initialHeight;
|
|
2071
|
+
return {
|
|
2072
|
+
...node().style,
|
|
2073
|
+
...w ? { width: toPxString(w) } : {},
|
|
2074
|
+
...h ? { height: toPxString(h) } : {}
|
|
2075
|
+
};
|
|
2076
|
+
}, style = () => ({
|
|
2077
|
+
"z-index": node().internals.z,
|
|
2078
|
+
transform: transform(),
|
|
2079
|
+
visibility: nodeHasDimensions(node()) ? "visible" : "hidden",
|
|
2080
|
+
...sizeStyle(),
|
|
2081
|
+
...node().style ?? {}
|
|
2082
|
+
});
|
|
2083
|
+
createEffect(() => ({
|
|
2084
|
+
valid: nodeTypeValid(),
|
|
2085
|
+
nodeType: nodeType()
|
|
2086
|
+
}), ({ valid, nodeType }) => {}), createEffect(() => ({
|
|
2087
|
+
id: node().id,
|
|
2088
|
+
nodeElement: nodeRef(),
|
|
2089
|
+
nodeType: nodeType(),
|
|
2090
|
+
sourcePosition: node().sourcePosition,
|
|
2091
|
+
targetPosition: node().targetPosition
|
|
2092
|
+
}), (current, prev) => {
|
|
2093
|
+
current.nodeElement && (prev && prev.nodeElement === current.nodeElement && prev.sourcePosition === current.sourcePosition && prev.targetPosition === current.targetPosition && prev.nodeType === current.nodeType || actions.requestUpdateNodeInternals([[current.id, {
|
|
2094
|
+
id: current.id,
|
|
2095
|
+
nodeElement: current.nodeElement,
|
|
2096
|
+
force: !0
|
|
2097
|
+
}]]));
|
|
2098
|
+
}), createEffect(() => ({
|
|
2099
|
+
nodeElement: nodeRef(),
|
|
2100
|
+
hasDimensions: nodeHasDimensions(node()),
|
|
2101
|
+
resizeObserver: props.resizeObserver
|
|
2102
|
+
}), (current, prev) => {
|
|
2103
|
+
current.nodeElement === prev?.nodeElement && current.resizeObserver === prev?.resizeObserver && current.hasDimensions || (prev?.nodeElement && prev.resizeObserver?.unobserve(prev.nodeElement), current.nodeElement && current.resizeObserver?.observe(current.nodeElement));
|
|
2104
|
+
});
|
|
2105
|
+
let onSelectNodeHandler = (event) => {
|
|
2106
|
+
selectable() && (!store.selectNodesOnDrag || !draggable() || store.nodeDragThreshold > 0) && actions.handleNodeSelection(node().id), props.onNodeClick?.({
|
|
2107
|
+
node: userNode(),
|
|
2108
|
+
event
|
|
2109
|
+
});
|
|
2110
|
+
}, onKeyDown = (event) => {
|
|
2111
|
+
if (isInputDOMNode(event) || store.disableKeyboardA11y) return;
|
|
2112
|
+
if (elementSelectionKeys.includes(event.key) && selectable()) {
|
|
2113
|
+
actions.handleNodeSelection(node().id, event.key === "Escape", nodeRef());
|
|
2114
|
+
return;
|
|
2115
|
+
}
|
|
2116
|
+
let arrowKeyDiff = ARROW_KEY_DIFFS[event.key];
|
|
2117
|
+
draggable() && node().selected && arrowKeyDiff && (event.preventDefault(), actions.setAriaLiveMessage(store.ariaLabelConfig["node.a11yDescription.ariaLiveMessage"]({
|
|
2118
|
+
direction: event.key.replace("Arrow", "").toLowerCase(),
|
|
2119
|
+
x: ~~node().internals.positionAbsolute.x,
|
|
2120
|
+
y: ~~node().internals.positionAbsolute.y
|
|
2121
|
+
})), actions.moveSelectedNodes(arrowKeyDiff, event.shiftKey ? 4 : 1));
|
|
2122
|
+
}, onFocus = () => {
|
|
2123
|
+
if (store.disableKeyboardA11y || !store.autoPanOnNodeFocus || !nodeRef()?.matches(":focus-visible")) return;
|
|
2124
|
+
let { width, height, viewport } = store;
|
|
2125
|
+
getNodesInside(/* @__PURE__ */ new Map([[node().id, node()]]), {
|
|
2126
|
+
x: 0,
|
|
2127
|
+
y: 0,
|
|
2128
|
+
width,
|
|
2129
|
+
height
|
|
2130
|
+
}, [
|
|
2131
|
+
viewport.x,
|
|
2132
|
+
viewport.y,
|
|
2133
|
+
viewport.zoom
|
|
2134
|
+
], !0).length > 0 || actions.setCenter(node().position.x + (node().measured.width ?? 0) / 2, node().position.y + (node().measured.height ?? 0) / 2, { zoom: viewport.zoom });
|
|
2135
|
+
}, dragging = createDraggable(nodeRef, () => ({
|
|
2136
|
+
nodeId: node().id,
|
|
2137
|
+
isSelectable: selectable(),
|
|
2138
|
+
disabled: !draggable(),
|
|
2139
|
+
handleSelector: node().dragHandle,
|
|
2140
|
+
noDragClass: store.noDragClass,
|
|
2141
|
+
nodeClickDistance: props.nodeClickDistance,
|
|
2142
|
+
onNodeMouseDown: actions.handleNodeSelection,
|
|
2143
|
+
onDrag: (event, _, targetNode, nodes) => {
|
|
2144
|
+
props.onNodeDrag?.({
|
|
2145
|
+
event,
|
|
2146
|
+
targetNode,
|
|
2147
|
+
nodes
|
|
2148
|
+
});
|
|
1663
2149
|
},
|
|
1664
|
-
|
|
1665
|
-
|
|
2150
|
+
onDragStart: (event, _, targetNode, nodes) => {
|
|
2151
|
+
props.onNodeDragStart?.({
|
|
2152
|
+
event,
|
|
2153
|
+
targetNode,
|
|
2154
|
+
nodes
|
|
2155
|
+
});
|
|
1666
2156
|
},
|
|
1667
|
-
|
|
1668
|
-
|
|
2157
|
+
onDragStop: (event, _, targetNode, nodes) => {
|
|
2158
|
+
props.onNodeDragStop?.({
|
|
2159
|
+
event,
|
|
2160
|
+
targetNode,
|
|
2161
|
+
nodes
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
}));
|
|
2165
|
+
return createComponent(Show, {
|
|
2166
|
+
get when() {
|
|
2167
|
+
return !node().hidden;
|
|
1669
2168
|
},
|
|
1670
|
-
get
|
|
1671
|
-
|
|
2169
|
+
get children() {
|
|
2170
|
+
var _el$ = _tmpl$$27();
|
|
2171
|
+
return ref(() => setNodeRef, _el$), spread(_el$, mergeProps({
|
|
2172
|
+
get "data-id"() {
|
|
2173
|
+
return node().id;
|
|
2174
|
+
},
|
|
2175
|
+
get class() {
|
|
2176
|
+
return [
|
|
2177
|
+
"solid-flow__node",
|
|
2178
|
+
`solid-flow__node-${nodeType()}`,
|
|
2179
|
+
{
|
|
2180
|
+
connectable: !!connectable(),
|
|
2181
|
+
draggable: !!draggable(),
|
|
2182
|
+
dragging: dragging(),
|
|
2183
|
+
nopan: !!draggable(),
|
|
2184
|
+
parent: isParentNode(),
|
|
2185
|
+
selectable: !!selectable(),
|
|
2186
|
+
selected: !!node().selected
|
|
2187
|
+
},
|
|
2188
|
+
node().class
|
|
2189
|
+
];
|
|
2190
|
+
},
|
|
2191
|
+
get style() {
|
|
2192
|
+
return style();
|
|
2193
|
+
},
|
|
2194
|
+
onClick: onSelectNodeHandler,
|
|
2195
|
+
onPointerEnter: (event) => props.onNodePointerEnter?.({
|
|
2196
|
+
node: userNode(),
|
|
2197
|
+
event
|
|
2198
|
+
}),
|
|
2199
|
+
onPointerLeave: (event) => props.onNodePointerLeave?.({
|
|
2200
|
+
node: userNode(),
|
|
2201
|
+
event
|
|
2202
|
+
}),
|
|
2203
|
+
onPointerMove: (event) => props.onNodePointerMove?.({
|
|
2204
|
+
node: userNode(),
|
|
2205
|
+
event
|
|
2206
|
+
}),
|
|
2207
|
+
onContextMenu: (event) => props.onNodeContextMenu?.({
|
|
2208
|
+
node: userNode(),
|
|
2209
|
+
event
|
|
2210
|
+
}),
|
|
2211
|
+
onKeyDown: (e) => focusable() && onKeyDown(e),
|
|
2212
|
+
onFocus: () => focusable() && onFocus(),
|
|
2213
|
+
get tabindex() {
|
|
2214
|
+
return focusable() ? 0 : void 0;
|
|
2215
|
+
},
|
|
2216
|
+
get role() {
|
|
2217
|
+
return node().ariaRole ?? (focusable() ? "group" : void 0);
|
|
2218
|
+
},
|
|
2219
|
+
"aria-roledescription": "node",
|
|
2220
|
+
get "aria-describedby"() {
|
|
2221
|
+
return store.disableKeyboardA11y ? void 0 : `${ARIA_NODE_DESC_KEY}-${store.id}`;
|
|
2222
|
+
}
|
|
2223
|
+
}, () => node().domAttributes), !0), insert(_el$, createComponent(NodeIdContext, {
|
|
2224
|
+
value: nodeId,
|
|
2225
|
+
get children() {
|
|
2226
|
+
return createComponent(NodeConnectableContext, {
|
|
2227
|
+
value: connectable,
|
|
2228
|
+
get children() {
|
|
2229
|
+
return createComponent(Dynamic, {
|
|
2230
|
+
get component() {
|
|
2231
|
+
return nodeComponent();
|
|
2232
|
+
},
|
|
2233
|
+
get data() {
|
|
2234
|
+
return node().data;
|
|
2235
|
+
},
|
|
2236
|
+
get id() {
|
|
2237
|
+
return node().id;
|
|
2238
|
+
},
|
|
2239
|
+
get selected() {
|
|
2240
|
+
return !!node().selected;
|
|
2241
|
+
},
|
|
2242
|
+
get selectable() {
|
|
2243
|
+
return selectable();
|
|
2244
|
+
},
|
|
2245
|
+
get deletable() {
|
|
2246
|
+
return deletable();
|
|
2247
|
+
},
|
|
2248
|
+
get sourcePosition() {
|
|
2249
|
+
return node().sourcePosition;
|
|
2250
|
+
},
|
|
2251
|
+
get targetPosition() {
|
|
2252
|
+
return node().targetPosition;
|
|
2253
|
+
},
|
|
2254
|
+
get zIndex() {
|
|
2255
|
+
return node().internals.z;
|
|
2256
|
+
},
|
|
2257
|
+
get dragging() {
|
|
2258
|
+
return dragging();
|
|
2259
|
+
},
|
|
2260
|
+
get draggable() {
|
|
2261
|
+
return draggable();
|
|
2262
|
+
},
|
|
2263
|
+
get dragHandle() {
|
|
2264
|
+
return node().dragHandle;
|
|
2265
|
+
},
|
|
2266
|
+
get parentId() {
|
|
2267
|
+
return node().parentId;
|
|
2268
|
+
},
|
|
2269
|
+
get type() {
|
|
2270
|
+
return nodeType();
|
|
2271
|
+
},
|
|
2272
|
+
get isConnectable() {
|
|
2273
|
+
return connectable();
|
|
2274
|
+
},
|
|
2275
|
+
get positionAbsoluteX() {
|
|
2276
|
+
return node().internals.positionAbsolute.x;
|
|
2277
|
+
},
|
|
2278
|
+
get positionAbsoluteY() {
|
|
2279
|
+
return node().internals.positionAbsolute.y;
|
|
2280
|
+
},
|
|
2281
|
+
get width() {
|
|
2282
|
+
return node().width;
|
|
2283
|
+
},
|
|
2284
|
+
get height() {
|
|
2285
|
+
return node().height;
|
|
2286
|
+
}
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
});
|
|
2290
|
+
}
|
|
2291
|
+
})), _el$;
|
|
1672
2292
|
}
|
|
1673
|
-
})
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
y: 0,
|
|
1684
|
-
zoom: 1
|
|
1685
|
-
}), setAriaLiveMessage(""), setSnapGrid(void 0);
|
|
1686
|
-
}, addEdge = (edgeParams) => {
|
|
1687
|
-
setEdgesStore((edges) => {
|
|
1688
|
-
let next = addEdge$1(edgeParams, edges);
|
|
1689
|
-
next !== edges && edges.push(next[next.length - 1]);
|
|
1690
|
-
});
|
|
1691
|
-
}, initialFitViewApplied = !1, initialNodesMeasured = !1, applyInitialFitView = (initialFitView) => {
|
|
1692
|
-
initialFitViewApplied = !initialFitView;
|
|
1693
|
-
}, tryInitialFitView = () => {
|
|
1694
|
-
initialFitViewApplied || !initialNodesMeasured || untrack(() => store.panZoom && store.width && store.height) && (initialFitViewApplied = !0, untrack(() => fitView()));
|
|
1695
|
-
}, updateNodePositions = (nodeDragItems, dragging = !1) => {
|
|
1696
|
-
setNodesStore((nodes) => {
|
|
1697
|
-
for (let node of nodes) nodeDragItems.has(node.id) && (node.dragging = dragging, node.position = nodeDragItems.get(node.id).position);
|
|
1698
|
-
});
|
|
1699
|
-
}, pendingEntries, requestUpdateNodeInternals = (updateEntries) => {
|
|
1700
|
-
if (pendingEntries) {
|
|
1701
|
-
pendingEntries.push(...updateEntries);
|
|
1702
|
-
return;
|
|
2293
|
+
});
|
|
2294
|
+
}, OutputNode = (props) => {
|
|
2295
|
+
let _props = propDefaults(props, { targetPosition: Position$1.Top });
|
|
2296
|
+
return [createComponent(Handle, {
|
|
2297
|
+
type: "target",
|
|
2298
|
+
get position() {
|
|
2299
|
+
return _props.targetPosition;
|
|
2300
|
+
},
|
|
2301
|
+
get isConnectable() {
|
|
2302
|
+
return _props.isConnectable;
|
|
1703
2303
|
}
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
x: store.width / 2 - x * nextZoom,
|
|
1739
|
-
y: store.height / 2 - y * nextZoom,
|
|
1740
|
-
zoom: nextZoom
|
|
1741
|
-
}, {
|
|
1742
|
-
duration: options?.duration,
|
|
1743
|
-
ease: options?.ease,
|
|
1744
|
-
interpolate: options?.interpolate
|
|
1745
|
-
}), Promise.resolve(!0)) : Promise.resolve(!1);
|
|
1746
|
-
}, setPaneClickDistance = (distance) => {
|
|
1747
|
-
store.panZoom?.setClickDistance(distance);
|
|
1748
|
-
}, unselectNodesAndEdges = ({ nodes: _nodes, edges } = {}) => {
|
|
1749
|
-
let nodesToUnselect = new Set((_nodes || store.nodes).map(({ id }) => id));
|
|
1750
|
-
nodesToUnselect.size && setNodesStore((nodes) => {
|
|
1751
|
-
for (let node of nodes) nodesToUnselect.has(node.id) && (node.selected = !1);
|
|
1752
|
-
});
|
|
1753
|
-
let edgesToUnselect = new Set((edges ?? store.edges).map(({ id }) => id));
|
|
1754
|
-
edgesToUnselect.size && setEdgesStore((edges) => {
|
|
1755
|
-
for (let edge of edges) edgesToUnselect.has(edge.id) && (edge.selected = !1);
|
|
1756
|
-
});
|
|
1757
|
-
}, addSelectedNodes = (ids) => {
|
|
1758
|
-
let isMultiSelection = store.multiselectionKeyPressed, selectState = /* @__PURE__ */ new Map();
|
|
1759
|
-
setNodesStore((nodes) => {
|
|
1760
|
-
for (let node of nodes) {
|
|
1761
|
-
let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
1762
|
-
if (selectState.set(node.id, selected), node.selected === selected) continue;
|
|
1763
|
-
let internalNode = nodeLookup.get(node.id);
|
|
1764
|
-
internalNode && (internalNode.selected = selected), node.selected = selected;
|
|
1765
|
-
}
|
|
1766
|
-
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] });
|
|
1767
|
-
}, addSelectedEdges = (ids) => {
|
|
1768
|
-
let isMultiSelection = store.multiselectionKeyPressed, edgeSelectState = /* @__PURE__ */ new Map();
|
|
1769
|
-
setEdgesStore((edges) => {
|
|
1770
|
-
for (let edge of edges) {
|
|
1771
|
-
let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
1772
|
-
edgeSelectState.set(edge.id, selected), edge.selected !== selected && (edge.selected = selected);
|
|
1773
|
-
}
|
|
1774
|
-
}), isMultiSelection || unselectNodesAndEdges({ edges: [] });
|
|
1775
|
-
};
|
|
1776
|
-
return createEffect(() => !!(width() && height() && panZoom()), (ready) => {
|
|
1777
|
-
ready && tryInitialFitView();
|
|
1778
|
-
}), createEffect(() => ({
|
|
1779
|
-
panZoom: store.panZoom,
|
|
1780
|
-
viewport: {
|
|
1781
|
-
x: store.viewport.x,
|
|
1782
|
-
y: store.viewport.y,
|
|
1783
|
-
zoom: store.viewport.zoom
|
|
2304
|
+
}), memo(() => props.data?.label)];
|
|
2305
|
+
};
|
|
2306
|
+
//#endregion
|
|
2307
|
+
//#region src/data/xyflow.ts
|
|
2308
|
+
/**
|
|
2309
|
+
* The DOM side of the measurement pipeline (fork of @xyflow/system's
|
|
2310
|
+
* updateNodeInternals): reads each updated node element's dimensions and
|
|
2311
|
+
* handle bounds from the DOM and reports them as data — measurement writes
|
|
2312
|
+
* for the measurements root plus user-facing dimension/position changes —
|
|
2313
|
+
* instead of writing into a node lookup. The internalNodes projection turns
|
|
2314
|
+
* the measurement writes back into internal-node state.
|
|
2315
|
+
*
|
|
2316
|
+
* `parentExpandChildren` must be turned into changes via
|
|
2317
|
+
* {@link handleExpandParent} only AFTER the measurement writes have been
|
|
2318
|
+
* flushed, so parent geometry reflects this measuring pass.
|
|
2319
|
+
*/
|
|
2320
|
+
function measureNodeInternals(updates, nodeLookup, domNode, nodeExtent) {
|
|
2321
|
+
let measurementWrites = [], changes = [], parentExpandChildren = [], updatedInternals = !1, viewportNode = domNode?.querySelector(".xyflow__viewport");
|
|
2322
|
+
if (!viewportNode) return {
|
|
2323
|
+
updatedInternals,
|
|
2324
|
+
measurementWrites,
|
|
2325
|
+
changes,
|
|
2326
|
+
parentExpandChildren
|
|
2327
|
+
};
|
|
2328
|
+
let style = window.getComputedStyle(viewportNode), { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);
|
|
2329
|
+
for (let update of updates.values()) {
|
|
2330
|
+
let node = nodeLookup.get(update.id);
|
|
2331
|
+
if (!node) continue;
|
|
2332
|
+
if (node.hidden) {
|
|
2333
|
+
measurementWrites.push({
|
|
2334
|
+
id: node.id,
|
|
2335
|
+
hidden: !0
|
|
2336
|
+
}), updatedInternals = !0;
|
|
2337
|
+
continue;
|
|
1784
2338
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
2339
|
+
let dimensions = getDimensions(update.nodeElement), dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
|
|
2340
|
+
if (dimensions.width && dimensions.height && (dimensionChanged || !node.internals.handleBounds || update.force)) {
|
|
2341
|
+
let nodeBounds = update.nodeElement.getBoundingClientRect(), extent = isCoordinateExtent(node.extent) ? node.extent : nodeExtent, { positionAbsolute } = node.internals;
|
|
2342
|
+
node.parentId && node.extent === "parent" ? positionAbsolute = clampPositionToParent(positionAbsolute, dimensions, nodeLookup.get(node.parentId)) : extent && (positionAbsolute = clampPosition(positionAbsolute, extent, dimensions)), measurementWrites.push({
|
|
2343
|
+
id: node.id,
|
|
2344
|
+
measured: dimensions,
|
|
2345
|
+
handleBounds: {
|
|
2346
|
+
source: getHandleBounds("source", update.nodeElement, nodeBounds, zoom, node.id),
|
|
2347
|
+
target: getHandleBounds("target", update.nodeElement, nodeBounds, zoom, node.id)
|
|
2348
|
+
}
|
|
2349
|
+
}), updatedInternals = !0, dimensionChanged && (changes.push({
|
|
2350
|
+
id: node.id,
|
|
2351
|
+
type: "dimensions",
|
|
2352
|
+
dimensions
|
|
2353
|
+
}), node.expandParent && node.parentId && parentExpandChildren.push({
|
|
2354
|
+
id: node.id,
|
|
2355
|
+
parentId: node.parentId,
|
|
2356
|
+
rect: nodeToRect({
|
|
2357
|
+
...node,
|
|
2358
|
+
measured: dimensions,
|
|
2359
|
+
internals: {
|
|
2360
|
+
...node.internals,
|
|
2361
|
+
positionAbsolute
|
|
2362
|
+
}
|
|
2363
|
+
})
|
|
2364
|
+
}));
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
return {
|
|
2368
|
+
updatedInternals,
|
|
2369
|
+
measurementWrites,
|
|
2370
|
+
changes,
|
|
2371
|
+
parentExpandChildren
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
function handleExpandParent(children, nodeLookup, getChildNodes, nodeOrigin = [0, 0]) {
|
|
2375
|
+
let changes = [], parentExpansions = /* @__PURE__ */ new Map();
|
|
2376
|
+
for (let child of children) {
|
|
2377
|
+
let parent = nodeLookup.get(child.parentId);
|
|
2378
|
+
if (!parent) continue;
|
|
2379
|
+
let parentRect = parentExpansions.get(child.parentId)?.expandedRect ?? nodeToRect(parent), expandedRect = getBoundsOfRects(parentRect, child.rect);
|
|
2380
|
+
parentExpansions.set(child.parentId, {
|
|
2381
|
+
expandedRect,
|
|
2382
|
+
parent
|
|
2383
|
+
});
|
|
2384
|
+
}
|
|
2385
|
+
return parentExpansions.size > 0 && parentExpansions.forEach(({ expandedRect, parent }, parentId) => {
|
|
2386
|
+
let positionAbsolute = parent.internals.positionAbsolute, dimensions = getNodeDimensions(parent), origin = parent.origin ?? nodeOrigin, xChange = expandedRect.x < positionAbsolute.x ? Math.round(Math.abs(positionAbsolute.x - expandedRect.x)) : 0, yChange = expandedRect.y < positionAbsolute.y ? Math.round(Math.abs(positionAbsolute.y - expandedRect.y)) : 0, newWidth = Math.max(dimensions.width, Math.round(expandedRect.width)), newHeight = Math.max(dimensions.height, Math.round(expandedRect.height)), widthChange = (newWidth - dimensions.width) * origin[0], heightChange = (newHeight - dimensions.height) * origin[1];
|
|
2387
|
+
if (xChange > 0 || yChange > 0 || widthChange || heightChange) {
|
|
2388
|
+
changes.push({
|
|
2389
|
+
id: parentId,
|
|
2390
|
+
type: "position",
|
|
2391
|
+
position: {
|
|
2392
|
+
x: parent.position.x - xChange + widthChange,
|
|
2393
|
+
y: parent.position.y - yChange + heightChange
|
|
1810
2394
|
}
|
|
1811
|
-
};
|
|
1812
|
-
nodeLookup.set(userNode.id, updatedNodeInternals), userNode.parentId && updateChildNode(updatedNodeInternals, nodeLookup, parentLookup, {
|
|
1813
|
-
nodeOrigin: store.nodeOrigin,
|
|
1814
|
-
nodeExtent: store.nodeExtent,
|
|
1815
|
-
elevateNodesOnSelect: store.elevateNodesOnSelect,
|
|
1816
|
-
zIndexMode: store.zIndexMode,
|
|
1817
|
-
checkEquality: !0
|
|
1818
|
-
});
|
|
1819
|
-
}, () => {}), onCleanup(() => {});
|
|
1820
|
-
}), () => {}), createEffect(() => new Set(store.nodes.map((n) => n.id)), (currentIds) => {
|
|
1821
|
-
for (let id of untrack(() => Array.from(nodeLookup.keys()))) currentIds.has(id) || nodeLookup.delete(id);
|
|
1822
|
-
}), createRenderEffect(mapArray(() => store.edges, (edge) => {
|
|
1823
|
-
let { source: sourceNodeId, target: targetNodeId, sourceHandle = null, targetHandle = null } = edge, connection = {
|
|
1824
|
-
edgeId: edge.id,
|
|
1825
|
-
source: sourceNodeId,
|
|
1826
|
-
target: targetNodeId,
|
|
1827
|
-
sourceHandle,
|
|
1828
|
-
targetHandle
|
|
1829
|
-
}, sourceKey = `${sourceNodeId}-${sourceHandle}--${targetNodeId}-${targetHandle}`, targetKey = `${targetNodeId}-${targetHandle}--${sourceNodeId}-${sourceHandle}`;
|
|
1830
|
-
createRenderEffect(() => {
|
|
1831
|
-
addConnectionToLookup("source", connection, targetKey, connectionLookup, sourceNodeId, sourceHandle), addConnectionToLookup("target", connection, sourceKey, connectionLookup, targetNodeId, targetHandle), edgeLookup.set(edge.id, edge);
|
|
1832
|
-
}, () => {}), createRenderEffect(() => {
|
|
1833
|
-
let sourceNode = nodeLookup.get(edge.source), targetNode = nodeLookup.get(edge.target);
|
|
1834
|
-
if (!sourceNode || !targetNode) return;
|
|
1835
|
-
if (store.onlyRenderVisibleElements) {
|
|
1836
|
-
if (!isEdgeVisible({
|
|
1837
|
-
sourceNode,
|
|
1838
|
-
targetNode,
|
|
1839
|
-
width: store.width ?? 0,
|
|
1840
|
-
height: store.height ?? 0,
|
|
1841
|
-
transform: store.transform
|
|
1842
|
-
})) return;
|
|
1843
|
-
store.visibleNodesMap.set(sourceNode.id, sourceNode), store.visibleNodesMap.set(targetNode.id, targetNode);
|
|
1844
|
-
}
|
|
1845
|
-
let edgePosition = getEdgePosition({
|
|
1846
|
-
id: edge.id,
|
|
1847
|
-
sourceNode,
|
|
1848
|
-
targetNode,
|
|
1849
|
-
sourceHandle: edge.sourceHandle || null,
|
|
1850
|
-
targetHandle: edge.targetHandle || null,
|
|
1851
|
-
connectionMode: store.connectionMode,
|
|
1852
|
-
onError: store.onError
|
|
1853
2395
|
});
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
sourceNode,
|
|
1862
|
-
targetNode,
|
|
1863
|
-
elevateOnSelect: store.elevateEdgesOnSelect,
|
|
1864
|
-
zIndexMode: store.zIndexMode
|
|
1865
|
-
}),
|
|
1866
|
-
sourceNode,
|
|
1867
|
-
targetNode,
|
|
1868
|
-
edge
|
|
2396
|
+
for (let childNode of getChildNodes(parentId)) children.some((child) => child.id === childNode.id) || changes.push({
|
|
2397
|
+
id: childNode.id,
|
|
2398
|
+
type: "position",
|
|
2399
|
+
position: {
|
|
2400
|
+
x: childNode.position.x + xChange,
|
|
2401
|
+
y: childNode.position.y + yChange
|
|
2402
|
+
}
|
|
1869
2403
|
});
|
|
1870
|
-
}
|
|
1871
|
-
|
|
2404
|
+
}
|
|
2405
|
+
(dimensions.width < expandedRect.width || dimensions.height < expandedRect.height || xChange || yChange) && changes.push({
|
|
2406
|
+
id: parentId,
|
|
2407
|
+
type: "dimensions",
|
|
2408
|
+
setAttributes: !0,
|
|
2409
|
+
dimensions: {
|
|
2410
|
+
width: newWidth + (xChange ? origin[0] * xChange - widthChange : 0),
|
|
2411
|
+
height: newHeight + (yChange ? origin[1] * yChange - heightChange : 0)
|
|
2412
|
+
}
|
|
1872
2413
|
});
|
|
1873
|
-
}),
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
2414
|
+
}), changes;
|
|
2415
|
+
}
|
|
2416
|
+
//#endregion
|
|
2417
|
+
//#region src/data/createSolidFlow.tsx
|
|
2418
|
+
const InitialNodeTypesMap = {
|
|
2419
|
+
input: InputNode,
|
|
2420
|
+
output: OutputNode,
|
|
2421
|
+
default: DefaultNode,
|
|
2422
|
+
group: GroupNode
|
|
2423
|
+
}, InitialEdgeTypesMap = {
|
|
2424
|
+
straight: StraightEdgeInternal,
|
|
2425
|
+
smoothstep: SmoothStepEdgeInternal,
|
|
2426
|
+
default: BezierEdgeInternal,
|
|
2427
|
+
step: StepEdgeInternal
|
|
2428
|
+
}, createSolidFlow = (props) => {
|
|
2429
|
+
let state = createFlowState(props, {
|
|
2430
|
+
prefersDark: createMediaQuery("(prefers-color-scheme: dark)", props.colorModeSSR === "dark"),
|
|
2431
|
+
initialNodeTypes: InitialNodeTypesMap,
|
|
2432
|
+
initialEdgeTypes: InitialEdgeTypesMap
|
|
2433
|
+
}), { store, nodeLookup, actions } = state, pendingEntries, requestUpdateNodeInternals = (updateEntries) => {
|
|
2434
|
+
if (pendingEntries) {
|
|
2435
|
+
pendingEntries.push(...updateEntries);
|
|
2436
|
+
return;
|
|
2437
|
+
}
|
|
2438
|
+
pendingEntries = updateEntries, scheduleIdleCallback(() => {
|
|
2439
|
+
let updates = new Map(pendingEntries);
|
|
2440
|
+
pendingEntries = void 0;
|
|
2441
|
+
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode);
|
|
2442
|
+
updatedInternals && (actions.applyMeasurementWrites(measurementWrites), flush(), parentExpandChildren.length > 0 && changes.push(...handleExpandParent(parentExpandChildren, nodeLookup, (parentId) => store.nodes.filter((node) => node.parentId === parentId), store.nodeOrigin)), actions.applyNodeChanges(changes), flush(), actions.markInitialNodesMeasured());
|
|
2443
|
+
});
|
|
2444
|
+
};
|
|
2445
|
+
return actions.setMeasureRequester(requestUpdateNodeInternals), {
|
|
2446
|
+
...state,
|
|
1881
2447
|
actions: {
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
resetStoreValues,
|
|
1885
|
-
requestUpdateNodeInternals,
|
|
1886
|
-
setAriaLabelConfig,
|
|
1887
|
-
setAriaLiveMessage,
|
|
1888
|
-
setClickConnectStartHandle,
|
|
1889
|
-
setConfig,
|
|
1890
|
-
setConnection,
|
|
1891
|
-
setDeleteKeyPressed,
|
|
1892
|
-
setDomNode,
|
|
1893
|
-
setDragging,
|
|
1894
|
-
get setEdges() {
|
|
1895
|
-
return setEdgesStore;
|
|
1896
|
-
},
|
|
1897
|
-
setElementsSelectable,
|
|
1898
|
-
setHeight,
|
|
1899
|
-
setMultiselectionKeyPressed,
|
|
1900
|
-
get setNodes() {
|
|
1901
|
-
return setNodesStore;
|
|
1902
|
-
},
|
|
1903
|
-
setNodesConnectable,
|
|
1904
|
-
setNodesDraggable,
|
|
1905
|
-
setPanActivationKeyPressed,
|
|
1906
|
-
setPanZoom,
|
|
1907
|
-
setSelectionKeyPressed,
|
|
1908
|
-
setSelectionRect,
|
|
1909
|
-
setSelectionRectMode,
|
|
1910
|
-
get setViewport() {
|
|
1911
|
-
return (viewport) => setViewportStore(() => viewport);
|
|
1912
|
-
},
|
|
1913
|
-
setWidth,
|
|
1914
|
-
setZoomActivationKeyPressed,
|
|
1915
|
-
addEdge,
|
|
1916
|
-
updateNodePositions,
|
|
1917
|
-
zoomIn,
|
|
1918
|
-
zoomOut,
|
|
1919
|
-
fitView,
|
|
1920
|
-
setCenter,
|
|
1921
|
-
setPaneClickDistance,
|
|
1922
|
-
unselectNodesAndEdges,
|
|
1923
|
-
addSelectedNodes,
|
|
1924
|
-
addSelectedEdges,
|
|
1925
|
-
handleNodeSelection: (id, unselect, nodeRef) => {
|
|
1926
|
-
let node = store.nodes.find((n) => n.id === id);
|
|
1927
|
-
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
1928
|
-
nodes: [node],
|
|
1929
|
-
edges: []
|
|
1930
|
-
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
1931
|
-
},
|
|
1932
|
-
handleEdgeSelection: (id) => {
|
|
1933
|
-
let edge = edgeLookup.get(id);
|
|
1934
|
-
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
1935
|
-
nodes: [],
|
|
1936
|
-
edges: [edge]
|
|
1937
|
-
}) : addSelectedEdges([id]));
|
|
1938
|
-
},
|
|
1939
|
-
moveSelectedNodes: (direction, factor) => {
|
|
1940
|
-
let nodeUpdates = /* @__PURE__ */ new Map(), xVelo = store.snapGrid?.[0] ?? 5, yVelo = store.snapGrid?.[1] ?? 5, xDiff = direction.x * xVelo * factor, yDiff = direction.y * yVelo * factor;
|
|
1941
|
-
for (let node of nodeLookup.values()) {
|
|
1942
|
-
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
1943
|
-
let nextPosition = {
|
|
1944
|
-
x: node.internals.positionAbsolute.x + xDiff,
|
|
1945
|
-
y: node.internals.positionAbsolute.y + yDiff
|
|
1946
|
-
};
|
|
1947
|
-
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
1948
|
-
let { position, positionAbsolute } = calculateNodePosition({
|
|
1949
|
-
nodeId: node.id,
|
|
1950
|
-
nextPosition,
|
|
1951
|
-
nodeLookup,
|
|
1952
|
-
nodeExtent: store.nodeExtent,
|
|
1953
|
-
nodeOrigin: store.nodeOrigin,
|
|
1954
|
-
onError: store.onError
|
|
1955
|
-
});
|
|
1956
|
-
node.position = position, node.internals.positionAbsolute = positionAbsolute, nodeUpdates.set(node.id, node);
|
|
1957
|
-
}
|
|
1958
|
-
updateNodePositions(nodeUpdates);
|
|
1959
|
-
},
|
|
1960
|
-
panBy: (delta) => panBy({
|
|
1961
|
-
delta,
|
|
1962
|
-
panZoom: store.panZoom,
|
|
1963
|
-
transform: store.transform,
|
|
1964
|
-
translateExtent: store.translateExtent,
|
|
1965
|
-
width: store.width,
|
|
1966
|
-
height: store.height
|
|
1967
|
-
}),
|
|
1968
|
-
cancelConnection: () => {
|
|
1969
|
-
setConnection({ ...initialConnection });
|
|
1970
|
-
},
|
|
1971
|
-
reset: () => {
|
|
1972
|
-
resetStoreValues(), unselectNodesAndEdges();
|
|
1973
|
-
}
|
|
2448
|
+
...actions,
|
|
2449
|
+
requestUpdateNodeInternals
|
|
1974
2450
|
}
|
|
1975
2451
|
};
|
|
1976
2452
|
}, SolidFlowContext = createContext(null);
|
|
@@ -2139,7 +2615,7 @@ const isSetEqual = (a, b) => {
|
|
|
2139
2615
|
for (let item of a) if (!b.has(item)) return !1;
|
|
2140
2616
|
return !0;
|
|
2141
2617
|
}, Pane = (props) => {
|
|
2142
|
-
let { store, nodeLookup, edgeLookup,
|
|
2618
|
+
let { store, nodeLookup, edgeLookup, connections, actions } = useInternalSolidFlow(), [containerRef, setContainerRef] = createSignal(), container, containerBounds = null, connectionEndedOnPane = !1, selectionInProgress = !1, selectedNodeIds = /* @__PURE__ */ new Set(), selectedEdgeIds = /* @__PURE__ */ new Set(), autoPanId = 0, position = {
|
|
2143
2619
|
x: 0,
|
|
2144
2620
|
y: 0
|
|
2145
2621
|
}, autoPanStarted = !1, autoPanOnSelection = () => props.autoPanOnSelection ?? !0, paneClickDistance = () => props.paneClickDistance ?? 1, _panOnDrag = () => store.panActivationKeyPressed || props.panOnDrag, isSelecting = () => store.selectionKeyPressed || !!store.selectionRect || props.selectionOnDrag && _panOnDrag() !== !0, isSelectionEnabled = () => store.elementsSelectable && (isSelecting() || store.selectionRectMode === "user"), onClick = (event) => {
|
|
@@ -2185,9 +2661,9 @@ const isSetEqual = (a, b) => {
|
|
|
2185
2661
|
let edgesSelectable = store.defaultEdgeOptions.selectable ?? !0;
|
|
2186
2662
|
selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
2187
2663
|
for (let nodeId of selectedNodeIds) {
|
|
2188
|
-
let
|
|
2189
|
-
if (
|
|
2190
|
-
let edge = edgeLookup
|
|
2664
|
+
let nodeConnections = connections[nodeId];
|
|
2665
|
+
if (nodeConnections) for (let { edgeId } of Object.values(nodeConnections)) {
|
|
2666
|
+
let edge = edgeLookup[edgeId];
|
|
2191
2667
|
edge && (edge.selectable ?? edgesSelectable) && selectedEdgeIds.add(edgeId);
|
|
2192
2668
|
}
|
|
2193
2669
|
}
|
|
@@ -2793,7 +3269,7 @@ var _tmpl$$8 = /* @__PURE__ */ template("<div>");
|
|
|
2793
3269
|
* The toolbar does not scale with the viewport so that its content is always legible.
|
|
2794
3270
|
*/
|
|
2795
3271
|
const EdgeToolbar = (props) => {
|
|
2796
|
-
let rest = omit(props, "x", "y", "alignX", "alignY", "isVisible", "selectEdgeOnClick", "class", "children"), { store, edgeLookup } = useInternalSolidFlow(), edgeId = useEdgeId(), isActive = () => typeof props.isVisible == "boolean" ? props.isVisible : !!edgeLookup
|
|
3272
|
+
let rest = omit(props, "x", "y", "alignX", "alignY", "isVisible", "selectEdgeOnClick", "class", "children"), { store, edgeLookup } = useInternalSolidFlow(), edgeId = useEdgeId(), isActive = () => typeof props.isVisible == "boolean" ? props.isVisible : !!edgeLookup[edgeId()]?.selected, transform = () => getEdgeToolbarTransform(props.x, props.y, store.viewport.zoom, props.alignX ?? "center", props.alignY ?? "center");
|
|
2797
3273
|
return createComponent(Show, {
|
|
2798
3274
|
get when() {
|
|
2799
3275
|
return isActive();
|
|
@@ -3146,8 +3622,8 @@ const ResizeControl = (props) => {
|
|
|
3146
3622
|
* @returns an accessor for the current color mode class
|
|
3147
3623
|
*/
|
|
3148
3624
|
function useColorMode() {
|
|
3149
|
-
let {
|
|
3150
|
-
return () =>
|
|
3625
|
+
let { flow } = useInternalSolidFlow();
|
|
3626
|
+
return () => flow.colorMode;
|
|
3151
3627
|
}
|
|
3152
3628
|
//#endregion
|
|
3153
3629
|
//#region src/hooks/useConnection.tsx
|
|
@@ -3158,8 +3634,8 @@ function useColorMode() {
|
|
|
3158
3634
|
* @returns current connection as a readable store
|
|
3159
3635
|
*/
|
|
3160
3636
|
function useConnection() {
|
|
3161
|
-
let {
|
|
3162
|
-
return () =>
|
|
3637
|
+
let { flow } = useInternalSolidFlow();
|
|
3638
|
+
return () => flow.connection;
|
|
3163
3639
|
}
|
|
3164
3640
|
//#endregion
|
|
3165
3641
|
//#region src/hooks/useGraph.ts
|
|
@@ -3190,15 +3666,15 @@ function useEdges() {
|
|
|
3190
3666
|
* @returns store with the viewport object
|
|
3191
3667
|
*/
|
|
3192
3668
|
function useViewport() {
|
|
3193
|
-
let {
|
|
3194
|
-
return () =>
|
|
3669
|
+
let { flow } = useInternalSolidFlow();
|
|
3670
|
+
return () => flow.viewport;
|
|
3195
3671
|
}
|
|
3196
3672
|
//#endregion
|
|
3197
3673
|
//#region src/hooks/useHandleEdgeSelect.tsx
|
|
3198
3674
|
function useHandleEdgeSelect() {
|
|
3199
3675
|
let { store, edgeLookup, actions } = useInternalSolidFlow();
|
|
3200
3676
|
return (id) => {
|
|
3201
|
-
let edge = edgeLookup
|
|
3677
|
+
let edge = edgeLookup[id];
|
|
3202
3678
|
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (actions.setSelectionRect(void 0), actions.setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && actions.unselectNodesAndEdges({
|
|
3203
3679
|
nodes: [],
|
|
3204
3680
|
edges: [edge]
|
|
@@ -3217,8 +3693,8 @@ function useHandleEdgeSelect() {
|
|
|
3217
3693
|
* @returns an accessor that indicates whether the nodes are initialized
|
|
3218
3694
|
*/
|
|
3219
3695
|
function useNodesInitialized() {
|
|
3220
|
-
let {
|
|
3221
|
-
return () =>
|
|
3696
|
+
let { flow } = useInternalSolidFlow();
|
|
3697
|
+
return () => flow.nodesInitialized;
|
|
3222
3698
|
}
|
|
3223
3699
|
/**
|
|
3224
3700
|
* Hook for seeing if the viewport is initialized.
|
|
@@ -3229,8 +3705,8 @@ function useNodesInitialized() {
|
|
|
3229
3705
|
* @returns an accessor that indicates whether the viewport is initialized
|
|
3230
3706
|
*/
|
|
3231
3707
|
function useViewportInitialized() {
|
|
3232
|
-
let {
|
|
3233
|
-
return () =>
|
|
3708
|
+
let { flow } = useInternalSolidFlow();
|
|
3709
|
+
return () => flow.viewportInitialized;
|
|
3234
3710
|
}
|
|
3235
3711
|
//#endregion
|
|
3236
3712
|
//#region src/hooks/useInternalNode.tsx
|
|
@@ -3242,8 +3718,8 @@ function useViewportInitialized() {
|
|
|
3242
3718
|
* @returns an accessor with an internal node or undefined
|
|
3243
3719
|
*/
|
|
3244
3720
|
function useInternalNode(id) {
|
|
3245
|
-
let {
|
|
3246
|
-
return () =>
|
|
3721
|
+
let { flow } = useInternalSolidFlow();
|
|
3722
|
+
return () => flow.internalNodes[id()];
|
|
3247
3723
|
}
|
|
3248
3724
|
//#endregion
|
|
3249
3725
|
//#region src/hooks/useNodeConnections.ts
|
|
@@ -3259,24 +3735,28 @@ function useInternalNode(id) {
|
|
|
3259
3735
|
* @returns an array with connections
|
|
3260
3736
|
*/
|
|
3261
3737
|
const useNodeConnections = (params) => {
|
|
3262
|
-
let {
|
|
3738
|
+
let { flow } = useInternalSolidFlow(), ctxNodeId = () => {
|
|
3263
3739
|
let id = useContext(NodeIdContext);
|
|
3264
3740
|
return id ? id() : "";
|
|
3265
|
-
}, id = () => params().handleId, type = () => params().handleType, nodeId = () => params().id ?? ctxNodeId(), [connections, setConnections] = createSignal([]),
|
|
3266
|
-
return createEffect(() =>
|
|
3267
|
-
|
|
3741
|
+
}, id = () => params().handleId, type = () => params().handleType, nodeId = () => params().id ?? ctxNodeId(), [connections, setConnections] = createSignal([]), prevConnections;
|
|
3742
|
+
return createEffect(() => {
|
|
3743
|
+
let rec = flow.connections[connectionKey(nodeId(), type(), id())], map = /* @__PURE__ */ new Map();
|
|
3744
|
+
for (let key of Object.keys(rec ?? {})) map.set(key, { ...rec[key] });
|
|
3745
|
+
return { connections: map };
|
|
3746
|
+
}, ({ connections: nextConnections }) => {
|
|
3747
|
+
areConnectionMapsEqual(nextConnections, prevConnections) || (prevConnections = nextConnections, setConnections(Array.from(nextConnections.values())));
|
|
3268
3748
|
}), connections;
|
|
3269
3749
|
};
|
|
3270
3750
|
//#endregion
|
|
3271
3751
|
//#region src/hooks/useNodesData.ts
|
|
3272
3752
|
function useNodesData(nodeIds) {
|
|
3273
|
-
let {
|
|
3753
|
+
let { flow } = useInternalSolidFlow(), prevNodesData = [];
|
|
3274
3754
|
return createMemo(() => {
|
|
3275
3755
|
let nodesData = [], idValues = nodeIds();
|
|
3276
3756
|
if (!idValues) return;
|
|
3277
3757
|
let ids = Array.isArray(idValues) ? idValues : [idValues];
|
|
3278
3758
|
for (let nodeId of ids) {
|
|
3279
|
-
let node =
|
|
3759
|
+
let node = flow.internalNodes[nodeId]?.internals.userNode;
|
|
3280
3760
|
node && nodesData.push({
|
|
3281
3761
|
id: node.id,
|
|
3282
3762
|
type: node.type,
|
|
@@ -3289,206 +3769,45 @@ function useNodesData(nodeIds) {
|
|
|
3289
3769
|
//#endregion
|
|
3290
3770
|
//#region src/hooks/useSolidFlow.tsx
|
|
3291
3771
|
/**
|
|
3292
|
-
* Hook for accessing the
|
|
3772
|
+
* Hook for accessing the flow instance: `{ flow, commands }` plus the
|
|
3773
|
+
* commands spread at the top level for upstream familiarity.
|
|
3774
|
+
*
|
|
3775
|
+
* `flow` and `commands` are stable identities, so destructuring them is safe:
|
|
3776
|
+
* `const { flow, commands } = useSolidFlow()`.
|
|
3293
3777
|
*
|
|
3294
3778
|
* @public
|
|
3295
|
-
* @returns
|
|
3779
|
+
* @returns the flow's read struct, write surface, and deprecated aliases
|
|
3296
3780
|
*/
|
|
3297
3781
|
function useSolidFlow() {
|
|
3298
|
-
let {
|
|
3299
|
-
let nodeToUse = isNode(node) ? node : nodeLookup.get(node.id), position = nodeToUse.parentId ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, store.nodeOrigin) : nodeToUse.position, nodeWithPosition = {
|
|
3300
|
-
...nodeToUse,
|
|
3301
|
-
position,
|
|
3302
|
-
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
3303
|
-
height: nodeToUse.measured?.height ?? nodeToUse.height
|
|
3304
|
-
};
|
|
3305
|
-
return nodeToRect(nodeWithPosition);
|
|
3306
|
-
}, updateNode = (id, nodeUpdate, options = { replace: !1 }) => {
|
|
3307
|
-
actions.setNodes((nodes) => {
|
|
3308
|
-
let index = nodes.findIndex((node) => node.id === id);
|
|
3309
|
-
if (index === -1) return;
|
|
3310
|
-
let node = nodes[index], nextNode = typeof nodeUpdate == "function" ? nodeUpdate(node) : nodeUpdate;
|
|
3311
|
-
nodes[index] = options?.replace && isNode(nextNode) ? nextNode : {
|
|
3312
|
-
...node,
|
|
3313
|
-
...nextNode
|
|
3314
|
-
};
|
|
3315
|
-
});
|
|
3316
|
-
}, updateEdge = (id, edgeUpdate, options = { replace: !1 }) => {
|
|
3317
|
-
actions.setEdges((edges) => {
|
|
3318
|
-
let index = edges.findIndex((edge) => edge.id === id);
|
|
3319
|
-
if (index === -1) return;
|
|
3320
|
-
let edge = edges[index], nextEdge = typeof edgeUpdate == "function" ? edgeUpdate(edge) : edgeUpdate;
|
|
3321
|
-
edges[index] = options.replace && isEdge(nextEdge) ? nextEdge : {
|
|
3322
|
-
...edge,
|
|
3323
|
-
...nextEdge
|
|
3324
|
-
};
|
|
3325
|
-
});
|
|
3326
|
-
}, getInternalNode = (id) => nodeLookup.get(id);
|
|
3782
|
+
let { flow, commands, store, edgeLookup } = useInternalSolidFlow(), getInternalNode = (id) => flow.internalNodes[id];
|
|
3327
3783
|
return {
|
|
3328
|
-
|
|
3329
|
-
|
|
3784
|
+
...commands,
|
|
3785
|
+
flow,
|
|
3786
|
+
commands,
|
|
3330
3787
|
getInternalNode,
|
|
3331
|
-
setCenter: actions.setCenter,
|
|
3332
|
-
fitView: actions.fitView,
|
|
3333
3788
|
getNode: (id) => getInternalNode(id)?.internals.userNode,
|
|
3334
|
-
getNodes: (ids) => ids ?
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
},
|
|
3341
|
-
addEdges: (payload) => {
|
|
3342
|
-
let newEdges = Array.isArray(payload) ? payload : [payload];
|
|
3343
|
-
actions.setEdges((edges) => [...edges, ...newEdges]);
|
|
3344
|
-
},
|
|
3789
|
+
getNodes: (ids) => ids ? ids.flatMap((id) => {
|
|
3790
|
+
let userNode = flow.internalNodes[id]?.internals.userNode;
|
|
3791
|
+
return userNode ? [userNode] : [];
|
|
3792
|
+
}) : [...flow.nodes],
|
|
3793
|
+
getEdge: (id) => edgeLookup[id],
|
|
3794
|
+
getEdges: (ids) => ids ? ids.flatMap((id) => edgeLookup[id] ? [edgeLookup[id]] : []) : [...flow.edges],
|
|
3345
3795
|
getViewport: () => snapshot(store.viewport),
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
return store.panZoom ? (await store.panZoom.setViewport({
|
|
3349
|
-
x: nextViewport.x ?? currentViewport.x,
|
|
3350
|
-
y: nextViewport.y ?? currentViewport.y,
|
|
3351
|
-
zoom: nextViewport.zoom ?? currentViewport.zoom
|
|
3352
|
-
}, options), Promise.resolve(!0)) : Promise.resolve(!1);
|
|
3353
|
-
},
|
|
3354
|
-
getZoom: () => store.viewport.zoom,
|
|
3355
|
-
setZoom: (zoomLevel, options) => {
|
|
3356
|
-
let panZoom = store.panZoom;
|
|
3357
|
-
return panZoom ? panZoom.scaleTo(zoomLevel, { duration: options?.duration }) : Promise.resolve(!1);
|
|
3358
|
-
},
|
|
3359
|
-
fitBounds: async (bounds, options) => {
|
|
3360
|
-
if (!store.panZoom) return Promise.resolve(!1);
|
|
3361
|
-
let viewport = getViewportForBounds$1(bounds, store.width, store.height, store.minZoom, store.maxZoom, options?.padding ?? .1);
|
|
3362
|
-
return await store.panZoom.setViewport(viewport, {
|
|
3363
|
-
duration: options?.duration,
|
|
3364
|
-
ease: options?.ease,
|
|
3365
|
-
interpolate: options?.interpolate
|
|
3366
|
-
}), Promise.resolve(!0);
|
|
3367
|
-
},
|
|
3368
|
-
getIntersectingNodes: (nodeOrRect, partially = !0, nodesToIntersect) => {
|
|
3369
|
-
let isRect = isRectObject(nodeOrRect), nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
3370
|
-
return nodeRect ? (nodesToIntersect || store.nodes).filter((n) => {
|
|
3371
|
-
let internalNode = nodeLookup.get(n.id);
|
|
3372
|
-
if (!internalNode || !isRect && n.id === nodeOrRect.id) return !1;
|
|
3373
|
-
let currNodeRect = nodeToRect(internalNode), overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
3374
|
-
return partially && overlappingArea > 0 || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
3375
|
-
}) : [];
|
|
3376
|
-
},
|
|
3377
|
-
isNodeIntersecting: (nodeOrRect, area, partially = !0) => {
|
|
3378
|
-
let nodeRect = isRectObject(nodeOrRect) ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
3379
|
-
if (!nodeRect) return !1;
|
|
3380
|
-
let overlappingArea = getOverlappingArea(nodeRect, area);
|
|
3381
|
-
return partially && overlappingArea > 0 || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
3382
|
-
},
|
|
3383
|
-
deleteElements: async ({ nodes: nodesToRemove = [], edges: edgesToRemove = [] }) => {
|
|
3384
|
-
let { nodes: matchingNodes, edges: matchingEdges } = await getElementsToRemove({
|
|
3385
|
-
nodesToRemove,
|
|
3386
|
-
edgesToRemove,
|
|
3387
|
-
nodes: store.nodes,
|
|
3388
|
-
edges: store.edges,
|
|
3389
|
-
onBeforeDelete: store.onBeforeDelete
|
|
3390
|
-
});
|
|
3391
|
-
if (matchingEdges) {
|
|
3392
|
-
let remmainingEdges = store.edges.filter((edge) => !matchingEdges.some(({ id }) => id === edge.id));
|
|
3393
|
-
store.onEdgesDelete?.(matchingEdges), actions.setEdges(() => remmainingEdges);
|
|
3394
|
-
}
|
|
3395
|
-
if (matchingNodes) {
|
|
3396
|
-
let remmainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
|
|
3397
|
-
store.onNodesDelete?.(matchingNodes), actions.setNodes(() => remmainingNodes);
|
|
3398
|
-
}
|
|
3399
|
-
return {
|
|
3400
|
-
deletedNodes: matchingNodes,
|
|
3401
|
-
deletedEdges: matchingEdges
|
|
3402
|
-
};
|
|
3403
|
-
},
|
|
3404
|
-
screenToFlowPosition: (position, options = { snapToGrid: !0 }) => {
|
|
3405
|
-
if (!store.domNode) return position;
|
|
3406
|
-
let _snapGrid = options.snapToGrid ? store.snapGrid : !1, { x, y, zoom } = store.viewport, { x: domX, y: domY } = store.domNode.getBoundingClientRect(), correctedPosition = {
|
|
3407
|
-
x: position.x - domX,
|
|
3408
|
-
y: position.y - domY
|
|
3409
|
-
};
|
|
3410
|
-
return pointToRendererPoint(correctedPosition, [
|
|
3411
|
-
x,
|
|
3412
|
-
y,
|
|
3413
|
-
zoom
|
|
3414
|
-
], _snapGrid !== null, _snapGrid || [1, 1]);
|
|
3415
|
-
},
|
|
3416
|
-
/**
|
|
3417
|
-
*
|
|
3418
|
-
* @param position
|
|
3419
|
-
* @returns
|
|
3420
|
-
*/
|
|
3421
|
-
flowToScreenPosition: (position) => {
|
|
3422
|
-
if (!store.domNode) return position;
|
|
3423
|
-
let { x, y, zoom } = store.viewport, { x: domX, y: domY } = store.domNode.getBoundingClientRect(), rendererPosition = rendererPointToPoint(position, [
|
|
3424
|
-
x,
|
|
3425
|
-
y,
|
|
3426
|
-
zoom
|
|
3427
|
-
]);
|
|
3428
|
-
return {
|
|
3429
|
-
x: rendererPosition.x + domX,
|
|
3430
|
-
y: rendererPosition.y + domY
|
|
3431
|
-
};
|
|
3432
|
-
},
|
|
3433
|
-
toObject: () => structuredClone({
|
|
3434
|
-
nodes: [...snapshot(store.nodes)],
|
|
3435
|
-
edges: [...snapshot(store.edges)],
|
|
3436
|
-
viewport: { ...snapshot(store.viewport) }
|
|
3437
|
-
}),
|
|
3438
|
-
updateNode,
|
|
3439
|
-
updateNodeData: (id, dataUpdate, options) => {
|
|
3440
|
-
let node = nodeLookup.get(id)?.internals.userNode;
|
|
3441
|
-
if (!node) return;
|
|
3442
|
-
let nextData = typeof dataUpdate == "function" ? dataUpdate(node) : dataUpdate;
|
|
3443
|
-
updateNode(id, (node) => ({
|
|
3444
|
-
...node,
|
|
3445
|
-
data: options?.replace ? nextData : {
|
|
3446
|
-
...node.data,
|
|
3447
|
-
...nextData
|
|
3448
|
-
}
|
|
3449
|
-
}));
|
|
3450
|
-
},
|
|
3451
|
-
updateEdge,
|
|
3452
|
-
getNodesBounds: (nodes) => getNodesBounds$1(nodes, {
|
|
3453
|
-
nodeLookup,
|
|
3454
|
-
nodeOrigin: store.nodeOrigin
|
|
3455
|
-
}),
|
|
3456
|
-
getHandleConnections: ({ type, id, nodeId }) => Array.from(connectionLookup.get(`${nodeId}-${type}-${id ?? null}`)?.values() ?? [])
|
|
3796
|
+
getZoom: () => flow.viewport.zoom,
|
|
3797
|
+
getHandleConnections: ({ type, id, nodeId }) => Object.values(flow.connections[connectionKey(nodeId, type, id ?? null)] ?? {})
|
|
3457
3798
|
};
|
|
3458
3799
|
}
|
|
3459
|
-
function getElements(lookup, ids) {
|
|
3460
|
-
let result = [];
|
|
3461
|
-
for (let id of ids) {
|
|
3462
|
-
let item = lookup.get(id);
|
|
3463
|
-
if (item) {
|
|
3464
|
-
let element = "internals" in item ? item.internals?.userNode : item;
|
|
3465
|
-
result.push(element);
|
|
3466
|
-
}
|
|
3467
|
-
}
|
|
3468
|
-
return result;
|
|
3469
|
-
}
|
|
3470
3800
|
//#endregion
|
|
3471
3801
|
//#region src/hooks/useUpdateNodeInternals.ts
|
|
3472
3802
|
/**
|
|
3473
|
-
* Hook for updating node internals.
|
|
3803
|
+
* Hook for updating node internals. Sugar for `commands.updateNodeInternals`.
|
|
3474
3804
|
*
|
|
3475
3805
|
* @public
|
|
3476
3806
|
* @returns function for updating node internals
|
|
3477
3807
|
*/
|
|
3478
3808
|
function useUpdateNodeInternals() {
|
|
3479
|
-
let {
|
|
3480
|
-
return
|
|
3481
|
-
let updateIds = Array.isArray(id) ? id : [id], updates = [];
|
|
3482
|
-
for (let updateId of updateIds) {
|
|
3483
|
-
let nodeElement = store.domNode?.querySelector(`.solid-flow__node[data-id="${updateId}"]`);
|
|
3484
|
-
nodeElement && updates.push([updateId, {
|
|
3485
|
-
id: updateId,
|
|
3486
|
-
nodeElement,
|
|
3487
|
-
force: !0
|
|
3488
|
-
}]);
|
|
3489
|
-
}
|
|
3490
|
-
actions.requestUpdateNodeInternals(updates);
|
|
3491
|
-
};
|
|
3809
|
+
let { commands } = useInternalSolidFlow();
|
|
3810
|
+
return commands.updateNodeInternals;
|
|
3492
3811
|
}
|
|
3493
3812
|
//#endregion
|
|
3494
3813
|
//#region src/components/graph/plugins/NodeToolbar.tsx
|
|
@@ -4053,4 +4372,4 @@ const SolidFlow = (props) => {
|
|
|
4053
4372
|
return [store, setStore];
|
|
4054
4373
|
};
|
|
4055
4374
|
//#endregion
|
|
4056
|
-
export { Background, BaseEdge, BezierEdge, BezierEdgeInternal, ConnectionLine, ConnectionLineType, ConnectionMode, ControlButton, Controls, DefaultNode, EdgeLabel, EdgeLabelRenderer, EdgeReconnectAnchor, EdgeRenderer, EdgeToolbar, EdgeWrapper, GroupNode, Handle, InputNode, Marker, MarkerDefinition, MarkerType, MiniMap, NodeRenderer, NodeResizer, NodeSelection, NodeToolbar, NodeWrapper, OutputNode, PanOnScrollMode, Pane, Panel, Position, ResizeControl, ResizeControlVariant, Selection, SelectionMode, SmoothStepEdge, SmoothStepEdgeInternal, SolidFlow, SolidFlowProvider, StepEdge, StepEdgeInternal, StraightEdge, StraightEdgeInternal, Viewport, ViewportPortal, Zoom, addEdge, createEdgeStore, createNodeStore, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds, useColorMode, useConnection, useEdges, useHandleEdgeSelect, useInternalNode, useNodeConnections, useNodes, useNodesData, useNodesInitialized, useSolidFlow, useUpdateNodeInternals, useViewport, useViewportInitialized };
|
|
4375
|
+
export { Background, BaseEdge, BezierEdge, BezierEdgeInternal, ConnectionLine, ConnectionLineType, ConnectionMode, ControlButton, Controls, DefaultNode, EdgeLabel, EdgeLabelRenderer, EdgeReconnectAnchor, EdgeRenderer, EdgeToolbar, EdgeWrapper, GroupNode, Handle, InputNode, Marker, MarkerDefinition, MarkerType, MiniMap, NodeRenderer, NodeResizer, NodeSelection, NodeToolbar, NodeWrapper, OutputNode, PanOnScrollMode, Pane, Panel, Position, ResizeControl, ResizeControlVariant, Selection, SelectionMode, SmoothStepEdge, SmoothStepEdgeInternal, SolidFlow, SolidFlowProvider, StepEdge, StepEdgeInternal, StraightEdge, StraightEdgeInternal, Viewport, ViewportPortal, Zoom, addEdge, connectionKey, createEdgeStore, createNodeStore, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds, useColorMode, useConnection, useEdges, useHandleEdgeSelect, useInternalNode, useNodeConnections, useNodes, useNodesData, useNodesInitialized, useSolidFlow, useUpdateNodeInternals, useViewport, useViewportInitialized };
|