@dschz/solid-flow 0.3.0-next.2 → 0.3.0-next.4
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/README.md +18 -0
- package/dist/index/index.d.ts +321 -65
- package/dist/index/index.js +204 -109
- package/dist/index/index.jsx +119 -66
- package/dist/styles/index.css +1 -1
- package/package.json +1 -1
package/dist/index/index.jsx
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, Position as Position$1, ResizeControlVariant, SelectionMode
|
|
1
|
+
import { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, Position as Position$1, ResizeControlVariant, 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 as getBezierEdgeCenter$1, getBezierPath, getBezierPath as getBezierPath$1, getBoundsOfRects, getConnectedEdges, getConnectionStatus, getDimensions, getEdgeCenter as getEdgeCenter$1, 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, isInputDOMNode, isMacOs, isNodeBase, isNumeric, isRectObject, mergeAriaLabelConfig, nodeHasDimensions, nodeToRect, panBy, pointToRendererPoint, rendererPointToPoint, shallowNodeData, snapPosition } from "@xyflow/system";
|
|
2
2
|
import { For, Show, createContext, createEffect, createMemo, createProjection, createSignal, createStore, flush, mapArray, merge, omit, onCleanup, onSettled, snapshot, untrack, useContext } from "solid-js";
|
|
3
3
|
import { createMediaQuery } from "@solid-primitives/media";
|
|
4
4
|
import { Dynamic, Portal, isServer } from "@solidjs/web";
|
|
5
5
|
import { createEventListener, createEventListenerMap } from "@solid-primitives/event-listener";
|
|
6
6
|
//#region src/contexts/edgeId.ts
|
|
7
7
|
const EdgeIdContext = createContext(null);
|
|
8
|
+
/**
|
|
9
|
+
* Returns the id of the edge this component is rendered inside. Available
|
|
10
|
+
* anywhere in a custom edge's subtree (provided by the edge wrapper), so
|
|
11
|
+
* nested components — like a custom edge label — can learn their host edge
|
|
12
|
+
* without prop drilling.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
* @returns a reactive accessor for the surrounding edge's id
|
|
16
|
+
*/
|
|
8
17
|
function useEdgeId() {
|
|
9
18
|
let ctx = useContext(EdgeIdContext);
|
|
10
|
-
if (!ctx) throw Error("solid-flow:
|
|
19
|
+
if (!ctx) throw Error("solid-flow: useEdgeId must be called inside an edge component (anywhere under a custom edge's subtree)");
|
|
11
20
|
return ctx;
|
|
12
21
|
}
|
|
13
22
|
//#endregion
|
|
@@ -141,11 +150,13 @@ const getEdgeId = (connection) => {
|
|
|
141
150
|
size: 25,
|
|
142
151
|
reconnecting: !1,
|
|
143
152
|
style: {}
|
|
144
|
-
}), rest = omit(_props, "type", "class", "style", "position", "size", "reconnecting", "children"), { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow(), edgeId = useEdgeId(), [reconnecting, setReconnecting] = createSignal(!1);
|
|
153
|
+
}), rest = omit(_props, "type", "class", "style", "position", "size", "reconnecting", "onReconnectingChange", "children"), { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow(), edgeId = useEdgeId(), [reconnecting, setReconnecting] = createSignal(!1);
|
|
145
154
|
if (!edgeId()) throw Error("[solid-flow]: EdgeReconnectAnchor must be used within an Edge component");
|
|
146
|
-
let edge = () => edgeLookup[edgeId()],
|
|
155
|
+
let edge = () => edgeLookup[edgeId()], isReconnecting = () => _props.reconnecting || reconnecting(), setReconnectingState = (next) => {
|
|
156
|
+
setReconnecting(next), _props.onReconnectingChange?.(next);
|
|
157
|
+
}, onPointerDown = (event) => {
|
|
147
158
|
if (event.button !== 0) return;
|
|
148
|
-
|
|
159
|
+
setReconnectingState(!0), store.onReconnectStart?.(event, edge(), _props.type);
|
|
149
160
|
let opposite = _props.type === "target" ? {
|
|
150
161
|
nodeId: edge().source,
|
|
151
162
|
handleId: edge().sourceHandle ?? null,
|
|
@@ -169,7 +180,9 @@ const getEdgeId = (connection) => {
|
|
|
169
180
|
edgeUpdaterType: opposite.type,
|
|
170
181
|
cancelConnection: actions.cancelConnection,
|
|
171
182
|
panBy: actions.panBy,
|
|
172
|
-
updateConnection:
|
|
183
|
+
updateConnection: (connection) => {
|
|
184
|
+
actions.setConnection(connection), flush();
|
|
185
|
+
},
|
|
173
186
|
isValidConnection: store.isValidConnection,
|
|
174
187
|
onConnectStart: store.onConnectStart,
|
|
175
188
|
onConnectEnd: store.onConnectEnd,
|
|
@@ -181,7 +194,7 @@ const getEdgeId = (connection) => {
|
|
|
181
194
|
newEdge = store.onBeforeReconnect?.(newEdge, edge()) ?? newEdge, newEdge && actions.setEdges((edges) => edges.map((e) => e.id === edge().id ? newEdge : e)), store.onReconnect?.(edge(), connection);
|
|
182
195
|
},
|
|
183
196
|
onReconnectEnd: (event, connectionState) => {
|
|
184
|
-
|
|
197
|
+
setReconnectingState(!1), store.onReconnectEnd?.(event, edge(), opposite.type, connectionState);
|
|
185
198
|
},
|
|
186
199
|
getTransform: () => store.transform,
|
|
187
200
|
getFromHandle: () => store.connection.fromHandle,
|
|
@@ -204,7 +217,7 @@ const getEdgeId = (connection) => {
|
|
|
204
217
|
cursor: "move",
|
|
205
218
|
..._props.style
|
|
206
219
|
}}>
|
|
207
|
-
<Show when={!
|
|
220
|
+
<Show when={!isReconnecting()}>{_props.children}</Show>
|
|
208
221
|
</div>
|
|
209
222
|
</EdgeLabel>;
|
|
210
223
|
}, ARIA_NODE_DESC_KEY = "solid-flow__node-desc", ARIA_EDGE_DESC_KEY = "solid-flow__edge-desc", A11yDescriptions = () => {
|
|
@@ -227,7 +240,6 @@ const getEdgeId = (connection) => {
|
|
|
227
240
|
let [store, setStore] = createStore(edges);
|
|
228
241
|
return [store, setStore];
|
|
229
242
|
}, STEP = .5 / 2, rectsEqual = (a, b) => a === b || !!a && !!b && a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height, rectsOverlap = (a, b) => a.x <= b.x + b.width && a.x + a.width >= b.x && a.y <= b.y + b.height && a.y + a.height >= b.y, createCullingViewport = (source) => createMemo(() => {
|
|
230
|
-
if (!source.onlyRenderVisibleElements) return null;
|
|
231
243
|
let { width, height } = source;
|
|
232
244
|
if (!width || !height) return null;
|
|
233
245
|
let [tx, ty, zoom] = source.transform, zoomBucket = 2 ** Math.floor(Math.log2(zoom)), bucketWidth = width / zoomBucket, bucketHeight = height / zoomBucket, stepX = bucketWidth * STEP, stepY = bucketHeight * STEP, centerX = (width / 2 - tx) / zoom, centerY = (height / 2 - ty) / zoom, quantizedX = Math.round(centerX / stepX) * stepX, quantizedY = Math.round(centerY / stepY) * stepY, halfWidth = bucketWidth * 1, halfHeight = bucketHeight * 1;
|
|
@@ -291,7 +303,7 @@ const getEdgeId = (connection) => {
|
|
|
291
303
|
selectNodesOnDrag: !0,
|
|
292
304
|
elevateNodesOnSelect: !0,
|
|
293
305
|
zIndexMode: "basic",
|
|
294
|
-
onlyRenderVisibleElements: !
|
|
306
|
+
onlyRenderVisibleElements: !1,
|
|
295
307
|
disableKeyboardA11y: !1,
|
|
296
308
|
defaultMarkerColor: "#b1b1b7",
|
|
297
309
|
ariaLiveMessage: "",
|
|
@@ -581,9 +593,17 @@ const createLayoutedEdges = (source) => {
|
|
|
581
593
|
return config().zIndexMode;
|
|
582
594
|
}
|
|
583
595
|
}), nodeLookup = new RecordMapFacade(internalNodes), initialViewport = getInitialViewport(_props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), [viewportStore, setViewportStore] = createStore(_props.viewport ?? initialViewport);
|
|
584
|
-
createEffect(() =>
|
|
596
|
+
createEffect(() => {
|
|
597
|
+
let next = config().nodes;
|
|
598
|
+
for (let node of next);
|
|
599
|
+
return { next };
|
|
600
|
+
}, ({ next }) => {
|
|
585
601
|
setNodesStore(() => next);
|
|
586
|
-
}, { defer: !0 }), createEffect(() =>
|
|
602
|
+
}, { defer: !0 }), createEffect(() => {
|
|
603
|
+
let next = config().edges;
|
|
604
|
+
for (let edge of next);
|
|
605
|
+
return { next };
|
|
606
|
+
}, ({ next }) => {
|
|
587
607
|
setEdgesStore(() => next);
|
|
588
608
|
}, { defer: !0 }), createEffect(() => config().viewport, (next) => {
|
|
589
609
|
next && setViewportStore(() => next);
|
|
@@ -744,9 +764,6 @@ const createLayoutedEdges = (source) => {
|
|
|
744
764
|
return zoomActivationKeyPressed();
|
|
745
765
|
}
|
|
746
766
|
}), cullingViewport = createCullingViewport({
|
|
747
|
-
get onlyRenderVisibleElements() {
|
|
748
|
-
return store.onlyRenderVisibleElements;
|
|
749
|
-
},
|
|
750
767
|
get width() {
|
|
751
768
|
return store.width;
|
|
752
769
|
},
|
|
@@ -1390,6 +1407,7 @@ function useNodeConnectable() {
|
|
|
1390
1407
|
}
|
|
1391
1408
|
//#endregion
|
|
1392
1409
|
//#region src/components/handle/Handle.tsx
|
|
1410
|
+
/** Connection point on a node; place inside custom nodes to make them connectable. */
|
|
1393
1411
|
const Handle = (props) => {
|
|
1394
1412
|
let _props = propDefaults(props, {
|
|
1395
1413
|
type: "source",
|
|
@@ -1571,15 +1589,30 @@ const Handle = (props) => {
|
|
|
1571
1589
|
};
|
|
1572
1590
|
}), dragging;
|
|
1573
1591
|
}, NodeIdContext = createContext(null);
|
|
1592
|
+
/**
|
|
1593
|
+
* Returns the id of the node this component is rendered inside. Available
|
|
1594
|
+
* anywhere in a custom node's subtree (provided by the node wrapper), so
|
|
1595
|
+
* nested components — like a custom `Handle` — can learn their host node
|
|
1596
|
+
* without prop drilling.
|
|
1597
|
+
*
|
|
1598
|
+
* @public
|
|
1599
|
+
* @returns a reactive accessor for the surrounding node's id
|
|
1600
|
+
*/
|
|
1574
1601
|
function useNodeId() {
|
|
1575
1602
|
let ctx = useContext(NodeIdContext);
|
|
1576
|
-
if (!ctx) throw Error("solid-flow:
|
|
1603
|
+
if (!ctx) throw Error("solid-flow: useNodeId must be called inside a node component (anywhere under a custom node's subtree)");
|
|
1577
1604
|
return ctx;
|
|
1578
1605
|
}
|
|
1579
1606
|
//#endregion
|
|
1580
1607
|
//#region src/components/node/NodeWrapper.tsx
|
|
1608
|
+
/** Internal per-node wrapper: dragging, selection, a11y, measurement, viewport culling, and the dynamic node component. */
|
|
1581
1609
|
const NodeWrapper = (props) => {
|
|
1582
|
-
let { store, nodeLookup, parentIds, actions } = useInternalSolidFlow(), [nodeRef, setNodeRef] = createSignal(), node = () => nodeLookup.get(props.nodeId)
|
|
1610
|
+
let { store, nodeLookup, parentIds, actions } = useInternalSolidFlow(), [nodeRef, setNodeRef] = createSignal(), node = () => nodeLookup.get(props.nodeId);
|
|
1611
|
+
onCleanup(() => {
|
|
1612
|
+
let el = nodeRef();
|
|
1613
|
+
el && props.resizeObserver?.unobserve(el);
|
|
1614
|
+
});
|
|
1615
|
+
let 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 = () => {
|
|
1583
1616
|
let { x, y } = node().internals.positionAbsolute;
|
|
1584
1617
|
return `translate(${x}px, ${y}px)`;
|
|
1585
1618
|
}, sizeStyle = () => {
|
|
@@ -1874,6 +1907,7 @@ function useInternalSolidFlow() {
|
|
|
1874
1907
|
}
|
|
1875
1908
|
//#endregion
|
|
1876
1909
|
//#region src/components/connection/ConnectionLine.tsx
|
|
1910
|
+
/** Internal component rendering the in-progress connection line. */
|
|
1877
1911
|
const ConnectionLine = (props) => {
|
|
1878
1912
|
let { store } = useInternalSolidFlow(), connectionStatus = () => getConnectionStatus(store.connection.isValid);
|
|
1879
1913
|
return <Show when={store.connection.inProgress}>
|
|
@@ -1947,16 +1981,28 @@ const ConnectionLine = (props) => {
|
|
|
1947
1981
|
</svg>
|
|
1948
1982
|
</Show>;
|
|
1949
1983
|
}, EdgeRenderer = (props) => {
|
|
1950
|
-
let { store } = useInternalSolidFlow()
|
|
1951
|
-
|
|
1984
|
+
let { store, actions } = useInternalSolidFlow(), [focusedEdgeId, setFocusedEdgeId] = createSignal(null), onFocusIn = (event) => {
|
|
1985
|
+
let edgeElement = event.target.closest("[data-id]");
|
|
1986
|
+
setFocusedEdgeId(edgeElement?.getAttribute("data-id") ?? null);
|
|
1987
|
+
};
|
|
1988
|
+
return <div class="solid-flow__edges" onFocusIn={onFocusIn} onFocusOut={() => setFocusedEdgeId(null)}>
|
|
1952
1989
|
<MarkerDefinition />
|
|
1953
1990
|
|
|
1954
1991
|
<For each={store.visibleEdgeIds}>
|
|
1955
|
-
{(edgeId) =>
|
|
1992
|
+
{(edgeId) => {
|
|
1993
|
+
let unmounted = createMemo(() => {
|
|
1994
|
+
if (!store.onlyRenderVisibleElements || focusedEdgeId() === edgeId) return !1;
|
|
1995
|
+
let edge = actions.getEdge(edgeId);
|
|
1996
|
+
return !!edge && isEdgeCulled(edge, store.cullingViewport);
|
|
1997
|
+
});
|
|
1998
|
+
return <Show when={!unmounted()}>
|
|
1999
|
+
<EdgeWrapper edgeId={edgeId} onEdgeClick={props.onEdgeClick} onEdgeContextMenu={props.onEdgeContextMenu} onEdgePointerEnter={props.onEdgePointerEnter} onEdgePointerLeave={props.onEdgePointerLeave} />
|
|
2000
|
+
</Show>;
|
|
2001
|
+
}}
|
|
1956
2002
|
</For>
|
|
1957
2003
|
</div>;
|
|
1958
2004
|
}, NodeRenderer = (props) => {
|
|
1959
|
-
let { actions, store } = useInternalSolidFlow(), resizeObserver = isServer ? void 0 : new ResizeObserver((entries) => {
|
|
2005
|
+
let { actions, store, nodeLookup } = useInternalSolidFlow(), resizeObserver = isServer ? void 0 : new ResizeObserver((entries) => {
|
|
1960
2006
|
actions.requestUpdateNodeInternals(entries.map((entry) => {
|
|
1961
2007
|
let id = entry.target.getAttribute("data-id");
|
|
1962
2008
|
return [id, {
|
|
@@ -1966,11 +2012,25 @@ const ConnectionLine = (props) => {
|
|
|
1966
2012
|
}];
|
|
1967
2013
|
}));
|
|
1968
2014
|
});
|
|
1969
|
-
|
|
2015
|
+
onCleanup(() => {
|
|
1970
2016
|
resizeObserver?.disconnect();
|
|
1971
|
-
})
|
|
2017
|
+
});
|
|
2018
|
+
let [focusedNodeId, setFocusedNodeId] = createSignal(null), onFocusIn = (event) => {
|
|
2019
|
+
let nodeElement = event.target.closest("[data-id]");
|
|
2020
|
+
setFocusedNodeId(nodeElement?.getAttribute("data-id") ?? null);
|
|
2021
|
+
};
|
|
2022
|
+
return <div class="solid-flow__container solid-flow__nodes" onFocusIn={onFocusIn} onFocusOut={() => setFocusedNodeId(null)}>
|
|
1972
2023
|
<For each={store.visibleNodeIds}>
|
|
1973
|
-
{(nodeId) =>
|
|
2024
|
+
{(nodeId) => {
|
|
2025
|
+
let unmounted = createMemo(() => {
|
|
2026
|
+
if (!store.onlyRenderVisibleElements || focusedNodeId() === nodeId) return !1;
|
|
2027
|
+
let node = nodeLookup.get(nodeId);
|
|
2028
|
+
return !!node && isNodeCulled(node, store.cullingViewport);
|
|
2029
|
+
});
|
|
2030
|
+
return <Show when={!unmounted()}>
|
|
2031
|
+
<NodeWrapper nodeId={nodeId} resizeObserver={resizeObserver} nodeClickDistance={props.nodeClickDistance} onNodeClick={props.onNodeClick} onNodePointerEnter={props.onNodePointerEnter} onNodePointerMove={props.onNodePointerMove} onNodePointerLeave={props.onNodePointerLeave} onNodeDrag={props.onNodeDrag} onNodeDragStart={props.onNodeDragStart} onNodeDragStop={props.onNodeDragStop} onNodeContextMenu={props.onNodeContextMenu} />
|
|
2032
|
+
</Show>;
|
|
2033
|
+
}}
|
|
1974
2034
|
</For>
|
|
1975
2035
|
</div>;
|
|
1976
2036
|
}, isSetEqual = (a, b) => {
|
|
@@ -2282,25 +2342,14 @@ const ConnectionLine = (props) => {
|
|
|
2282
2342
|
* `const { flow, commands } = useSolidFlow()`.
|
|
2283
2343
|
*
|
|
2284
2344
|
* @public
|
|
2285
|
-
* @returns the flow's read struct
|
|
2345
|
+
* @returns the flow's read struct and write surface
|
|
2286
2346
|
*/
|
|
2287
2347
|
function useSolidFlow() {
|
|
2288
|
-
let { flow, commands
|
|
2348
|
+
let { flow, commands } = useInternalSolidFlow();
|
|
2289
2349
|
return {
|
|
2290
2350
|
...commands,
|
|
2291
2351
|
flow,
|
|
2292
|
-
commands
|
|
2293
|
-
getInternalNode,
|
|
2294
|
-
getNode: (id) => getInternalNode(id)?.internals.userNode,
|
|
2295
|
-
getNodes: (ids) => ids ? ids.flatMap((id) => {
|
|
2296
|
-
let userNode = flow.internalNodes[id]?.internals.userNode;
|
|
2297
|
-
return userNode ? [userNode] : [];
|
|
2298
|
-
}) : [...flow.nodes],
|
|
2299
|
-
getEdge: (id) => edgeLookup[id],
|
|
2300
|
-
getEdges: (ids) => ids ? ids.flatMap((id) => edgeLookup[id] ? [edgeLookup[id]] : []) : [...flow.edges],
|
|
2301
|
-
getViewport: () => snapshot(store.viewport),
|
|
2302
|
-
getZoom: () => flow.viewport.zoom,
|
|
2303
|
-
getHandleConnections: ({ type, id, nodeId }) => Object.values(flow.connections[connectionKey(nodeId, type, id ?? null)] ?? {})
|
|
2352
|
+
commands
|
|
2304
2353
|
};
|
|
2305
2354
|
}
|
|
2306
2355
|
//#endregion
|
|
@@ -2531,18 +2580,6 @@ function useViewport() {
|
|
|
2531
2580
|
return () => flow.viewport;
|
|
2532
2581
|
}
|
|
2533
2582
|
//#endregion
|
|
2534
|
-
//#region src/hooks/useHandleEdgeSelect.ts
|
|
2535
|
-
function useHandleEdgeSelect() {
|
|
2536
|
-
let { store, edgeLookup, actions } = useInternalSolidFlow();
|
|
2537
|
-
return (id) => {
|
|
2538
|
-
let edge = edgeLookup[id];
|
|
2539
|
-
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({
|
|
2540
|
-
nodes: [],
|
|
2541
|
-
edges: [edge]
|
|
2542
|
-
}) : actions.addSelectedEdges([id]));
|
|
2543
|
-
};
|
|
2544
|
-
}
|
|
2545
|
-
//#endregion
|
|
2546
2583
|
//#region src/hooks/useInitialized.ts
|
|
2547
2584
|
/**
|
|
2548
2585
|
* Hook for seeing if all nodes have been measured.
|
|
@@ -2572,11 +2609,16 @@ function useViewportInitialized() {
|
|
|
2572
2609
|
//#endregion
|
|
2573
2610
|
//#region src/hooks/useInternalNode.ts
|
|
2574
2611
|
/**
|
|
2575
|
-
* Hook to get an internal node
|
|
2612
|
+
* Hook to get an internal node (the node enriched with measured dimensions,
|
|
2613
|
+
* absolute position, and z-order) by id.
|
|
2614
|
+
*
|
|
2615
|
+
* The id is an accessor (not a plain string) on purpose: passing a raw
|
|
2616
|
+
* reactive read like `props.nodeId` would capture the value once and silently
|
|
2617
|
+
* lose reactivity — `useInternalNode(() => props.nodeId)` keeps it live.
|
|
2576
2618
|
*
|
|
2577
2619
|
* @public
|
|
2578
|
-
* @param id - the node id
|
|
2579
|
-
* @returns an accessor with
|
|
2620
|
+
* @param id - a reactive accessor for the node id
|
|
2621
|
+
* @returns an accessor with the internal node, or undefined while absent
|
|
2580
2622
|
*/
|
|
2581
2623
|
function useInternalNode(id) {
|
|
2582
2624
|
let { flow } = useInternalSolidFlow();
|
|
@@ -2663,7 +2705,6 @@ const DotPattern = (props) => {
|
|
|
2663
2705
|
let _props = propDefaults(props, {
|
|
2664
2706
|
variant: "dots",
|
|
2665
2707
|
gap: 20,
|
|
2666
|
-
size: 1,
|
|
2667
2708
|
lineWidth: 1,
|
|
2668
2709
|
style: {}
|
|
2669
2710
|
}), { store } = useInternalSolidFlow(), isDots = () => _props.variant === "dots", isCross = () => _props.variant === "cross", patternId = () => `background-pattern-${store.id}-${_props.id ?? ""}`, scaledSize = () => (_props.size ?? DEFAULT_SIZE[_props.variant]) * store.viewport.zoom, gapXY = () => Array.isArray(_props.gap) ? _props.gap : [_props.gap, _props.gap], scaledGap = () => [gapXY()[0] * store.viewport.zoom || 1, gapXY()[1] * store.viewport.zoom || 1], patternDimensions = () => isCross() ? [scaledSize(), scaledSize()] : scaledGap(), patternOffset = () => isDots() ? [scaledSize() / 2, scaledSize() / 2] : [patternDimensions()[0] / 2, patternDimensions()[1] / 2];
|
|
@@ -2759,8 +2800,8 @@ const DotPattern = (props) => {
|
|
|
2759
2800
|
borderRadius: 5,
|
|
2760
2801
|
width: 0,
|
|
2761
2802
|
height: 0
|
|
2762
|
-
}), style = () => Object.entries({
|
|
2763
|
-
fill:
|
|
2803
|
+
}), fill = () => _props.color ?? _props.style?.background ?? _props.style?.["background-color"], style = () => Object.entries({
|
|
2804
|
+
fill: fill(),
|
|
2764
2805
|
stroke: _props.strokeColor,
|
|
2765
2806
|
"stroke-width": _props.strokeWidth
|
|
2766
2807
|
}).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => (acc[key] = value, acc), {});
|
|
@@ -2768,7 +2809,7 @@ const DotPattern = (props) => {
|
|
|
2768
2809
|
"solid-flow__minimap-node",
|
|
2769
2810
|
{ selected: !!_props.selected },
|
|
2770
2811
|
_props.class
|
|
2771
|
-
]} x={_props.x} y={_props.y} rx={_props.borderRadius} ry={_props.borderRadius} width={_props.width} height={_props.height} shape-rendering={_props.shapeRendering} style={style()} />;
|
|
2812
|
+
]} x={_props.x} y={_props.y} rx={_props.borderRadius} ry={_props.borderRadius} width={_props.width} height={_props.height} shape-rendering={_props.shapeRendering} style={style()} onClick={_props.onClick ? (event) => _props.onClick(event, _props.id) : void 0} />;
|
|
2772
2813
|
}, getAttrFunction = (func) => func instanceof Function ? func : () => func, MiniMap = (props) => {
|
|
2773
2814
|
let { store, nodeLookup } = useInternalSolidFlow(), _props = propDefaults(props, {
|
|
2774
2815
|
position: "bottom-right",
|
|
@@ -2781,7 +2822,7 @@ const DotPattern = (props) => {
|
|
|
2781
2822
|
nodeBorderRadius: 5,
|
|
2782
2823
|
nodeStrokeWidth: 2,
|
|
2783
2824
|
style: {}
|
|
2784
|
-
}), paneProps = omit(_props, "class", "style", "position", "nodeClass", "nodeStrokeColor", "nodeColor", "pannable", "zoomable", "inversePan", "zoomStep", "bgColor", "width", "height", "maskColor", "maskStrokeColor", "maskStrokeWidth", "nodeBorderRadius", "nodeStrokeWidth"), nodeColorFunc = () => _props.nodeColor === void 0 ? void 0 : getAttrFunction(_props.nodeColor), nodeStrokeColorFunc = () => getAttrFunction(_props.nodeStrokeColor), nodeClassFunc = () => getAttrFunction(_props.nodeClass), shapeRendering = () => typeof window > "u" || window.chrome ? "crispEdges" : "geometricPrecision", labelledBy = createMemo(() => `solid-flow__minimap-desc-${store.id}`), getViewBB = () => ({
|
|
2825
|
+
}), paneProps = omit(_props, "class", "style", "position", "nodeClass", "nodeStrokeColor", "nodeColor", "pannable", "zoomable", "inversePan", "zoomStep", "bgColor", "width", "height", "maskColor", "maskStrokeColor", "maskStrokeWidth", "nodeBorderRadius", "nodeStrokeWidth", "nodeComponent", "onClick", "onNodeClick"), nodeColorFunc = () => _props.nodeColor === void 0 ? void 0 : getAttrFunction(_props.nodeColor), nodeStrokeColorFunc = () => getAttrFunction(_props.nodeStrokeColor), nodeClassFunc = () => getAttrFunction(_props.nodeClass), shapeRendering = () => typeof window > "u" || window.chrome ? "crispEdges" : "geometricPrecision", labelledBy = createMemo(() => `solid-flow__minimap-desc-${store.id}`), getViewBB = () => ({
|
|
2785
2826
|
x: -store.viewport.x / store.viewport.zoom,
|
|
2786
2827
|
y: -store.viewport.y / store.viewport.zoom,
|
|
2787
2828
|
width: store.width / store.viewport.zoom,
|
|
@@ -2806,7 +2847,7 @@ const DotPattern = (props) => {
|
|
|
2806
2847
|
<Show when={store.panZoom}>
|
|
2807
2848
|
{(panZoom) => {
|
|
2808
2849
|
let [ref, setRef] = createSignal(), [minimap, setMinimap] = createSignal();
|
|
2809
|
-
|
|
2850
|
+
createEffect(() => ({
|
|
2810
2851
|
el: ref(),
|
|
2811
2852
|
panZoom: panZoom()
|
|
2812
2853
|
}), ({ el, panZoom }) => {
|
|
@@ -2833,7 +2874,19 @@ const DotPattern = (props) => {
|
|
|
2833
2874
|
}
|
|
2834
2875
|
}), ({ instance, options }) => {
|
|
2835
2876
|
instance?.update(options);
|
|
2836
|
-
})
|
|
2877
|
+
});
|
|
2878
|
+
let onSvgClick = (event) => {
|
|
2879
|
+
if (!_props.onClick) return;
|
|
2880
|
+
let [x, y] = minimap()?.pointer(event) ?? [0, 0];
|
|
2881
|
+
_props.onClick(event, {
|
|
2882
|
+
x,
|
|
2883
|
+
y
|
|
2884
|
+
});
|
|
2885
|
+
}, onSvgNodeClick = (event, nodeId) => {
|
|
2886
|
+
let node = nodeLookup.get(nodeId)?.internals.userNode;
|
|
2887
|
+
node && _props.onNodeClick?.(event, node);
|
|
2888
|
+
};
|
|
2889
|
+
return <svg ref={setRef} width={_props.width} height={_props.height} viewBox={`${getX()} ${getY()} ${getViewboxWidth()} ${getViewboxHeight()}`} class="solid-flow__minimap-svg" role="img" aria-labelledby={labelledBy()} onClick={_props.onClick ? onSvgClick : void 0} style={{
|
|
2837
2890
|
"--xy-minimap-mask-background-color-props": _props.maskColor,
|
|
2838
2891
|
"--xy-minimap-mask-stroke-color-props": _props.maskStrokeColor,
|
|
2839
2892
|
"--xy-minimap-mask-stroke-width-props": strokeWidth()
|
|
@@ -2843,7 +2896,7 @@ const DotPattern = (props) => {
|
|
|
2843
2896
|
{(nodeId) => {
|
|
2844
2897
|
let node = createMemo(() => nodeLookup.get(nodeId())), nodeVisible = () => !!(node() && nodeHasDimensions(node()) && !node().hidden);
|
|
2845
2898
|
return <Show when={nodeVisible() && getNodeDimensions(node())}>
|
|
2846
|
-
{(nodeDimensions) => <MiniMapNode x={node().internals.positionAbsolute.x} y={node().internals.positionAbsolute.y} borderRadius={_props.nodeBorderRadius} strokeWidth={_props.nodeStrokeWidth} shapeRendering={shapeRendering()} width={nodeDimensions().width} height={nodeDimensions().height} selected={node().selected} color={nodeColorFunc()?.call(null, node())} strokeColor={nodeStrokeColorFunc().call(null, node())} class={nodeClassFunc().call(null, node())} />}
|
|
2899
|
+
{(nodeDimensions) => <Dynamic component={_props.nodeComponent ?? MiniMapNode} id={nodeId()} x={node().internals.positionAbsolute.x} y={node().internals.positionAbsolute.y} borderRadius={_props.nodeBorderRadius} strokeWidth={_props.nodeStrokeWidth} shapeRendering={shapeRendering()} width={nodeDimensions().width} height={nodeDimensions().height} selected={node().selected} color={nodeColorFunc()?.call(null, node())} strokeColor={nodeStrokeColorFunc().call(null, node())} class={nodeClassFunc().call(null, node())} style={node().style} onClick={_props.onNodeClick ? onSvgNodeClick : void 0} />}
|
|
2847
2900
|
</Show>;
|
|
2848
2901
|
}}
|
|
2849
2902
|
</For>
|
|
@@ -2960,7 +3013,7 @@ const DotPattern = (props) => {
|
|
|
2960
3013
|
</EdgeLabel>
|
|
2961
3014
|
</Show>;
|
|
2962
3015
|
}, NodeToolbar = (props) => {
|
|
2963
|
-
let { store } = useInternalSolidFlow(), {
|
|
3016
|
+
let { store } = useInternalSolidFlow(), { flow, getNodesBounds } = useSolidFlow(), _props = propDefaults(props, {
|
|
2964
3017
|
offset: 10,
|
|
2965
3018
|
position: "top",
|
|
2966
3019
|
align: "center",
|
|
@@ -2969,7 +3022,7 @@ const DotPattern = (props) => {
|
|
|
2969
3022
|
let id = useContext(NodeIdContext);
|
|
2970
3023
|
return id ? id() : "";
|
|
2971
3024
|
}, toolbarNodes = () => (Array.isArray(_props.nodeId) ? _props.nodeId : [_props.nodeId ?? ctxNodeId()]).reduce((res, nodeId) => {
|
|
2972
|
-
let node =
|
|
3025
|
+
let node = flow.internalNodes[nodeId];
|
|
2973
3026
|
return node && res.push(node), res;
|
|
2974
3027
|
}, []), transform = () => {
|
|
2975
3028
|
let nodeRect = getNodesBounds(toolbarNodes());
|
|
@@ -2977,7 +3030,7 @@ const DotPattern = (props) => {
|
|
|
2977
3030
|
}, zIndex = () => {
|
|
2978
3031
|
let nodes = toolbarNodes();
|
|
2979
3032
|
return nodes.length === 0 ? 1 : Math.max(...nodes.map((node) => (node.internals.z || 5) + 1));
|
|
2980
|
-
}, selectedNodesCount = () =>
|
|
3033
|
+
}, selectedNodesCount = () => flow.selection.nodes.length, isActive = () => {
|
|
2981
3034
|
let nodes = toolbarNodes();
|
|
2982
3035
|
return typeof _props.isVisible == "boolean" ? _props.isVisible : nodes.length === 1 && !!nodes[0].selected && selectedNodesCount() === 1;
|
|
2983
3036
|
}, showPortal = () => !!(store.domNode && isActive() && toolbarNodes().length > 0);
|
|
@@ -2993,6 +3046,6 @@ const DotPattern = (props) => {
|
|
|
2993
3046
|
</div>
|
|
2994
3047
|
</Portal>
|
|
2995
3048
|
</Show>;
|
|
2996
|
-
};
|
|
3049
|
+
}, SelectionMode = SelectionMode$1, getEdgeCenter = getEdgeCenter$1, getBezierEdgeCenter = getBezierEdgeCenter$1;
|
|
2997
3050
|
//#endregion
|
|
2998
|
-
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,
|
|
3051
|
+
export { Background, BaseEdge, BezierEdge, BezierEdgeInternal, ConnectionLine, ConnectionLineType, ConnectionMode, ControlButton, Controls, DefaultNode, EdgeLabel, EdgeLabelRenderer, EdgeReconnectAnchor, EdgeRenderer, EdgeToolbar, EdgeWrapper, GroupNode, Handle, InputNode, Marker, MarkerDefinition, MarkerType, MiniMap, MiniMapNode, 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, useEdgeId, useEdges, useInternalNode, useNodeConnections, useNodeId, useNodes, useNodesData, useNodesInitialized, useSolidFlow, useUpdateNodeInternals, useViewport, useViewportInitialized };
|
package/dist/styles/index.css
CHANGED
package/package.json
CHANGED