@dschz/solid-flow 1.0.0-next.6 → 1.0.0-next.8
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 +27 -0
- package/dist/index/index.d.ts +157 -103
- package/dist/index/index.js +773 -460
- package/dist/index/index.jsx +716 -400
- package/dist/styles/index.css +16 -4
- package/package.json +6 -5
package/dist/index/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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 { 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
|
+
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, errorMessages, 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";
|
|
3
3
|
import { For, Show, createContext, createEffect, createMemo, createProjection, createSignal, createStore, flush, mapArray, merge, omit, onCleanup, onSettled, snapshot, untrack, useContext } from "solid-js";
|
|
4
4
|
import { createMediaQuery } from "@solid-primitives/media";
|
|
5
5
|
import { createEventListener, createEventListenerMap } from "@solid-primitives/event-listener";
|
|
@@ -65,6 +65,8 @@ function propDefaults(props, defaults) {
|
|
|
65
65
|
const getEdgeId = (connection) => {
|
|
66
66
|
let { source, sourceHandle, target, targetHandle } = connection;
|
|
67
67
|
return `xy-edge__${source}${sourceHandle || ""}-${target}${targetHandle || ""}`;
|
|
68
|
+
}, isEdgeSelectable = (edge, store) => edge.selectable ?? store.defaultEdgeOptions.selectable ?? store.elementsSelectable, emitFlowError = (onError, id, message) => {
|
|
69
|
+
onError && onError(id, message);
|
|
68
70
|
}, EdgeLabelRenderer = (props) => {
|
|
69
71
|
let { store } = useInternalSolidFlow(), labelNode = () => store.domNode?.querySelector(".solid-flow__edge-labels");
|
|
70
72
|
return createComponent(Show, {
|
|
@@ -92,7 +94,7 @@ const EdgeLabel = (props) => {
|
|
|
92
94
|
selectEdgeOnClick: !1,
|
|
93
95
|
transparent: !1,
|
|
94
96
|
style: {}
|
|
95
|
-
}), rest = omit(_props, "x", "y", "width", "height", "selectEdgeOnClick", "transparent", "children", "class", "style"), { actions } = useInternalSolidFlow(), id = useEdgeId(), zIndex = () => actions.
|
|
97
|
+
}), rest = omit(_props, "x", "y", "width", "height", "selectEdgeOnClick", "transparent", "children", "class", "style"), { actions } = useInternalSolidFlow(), id = useEdgeId(), zIndex = () => actions.getLayoutedEdge(id())?.zIndex;
|
|
96
98
|
return createComponent(EdgeLabelRenderer, { get children() {
|
|
97
99
|
var _el$ = _tmpl$$34();
|
|
98
100
|
return spread(_el$, mergeProps({
|
|
@@ -282,6 +284,205 @@ const BaseEdge = (props) => {
|
|
|
282
284
|
});
|
|
283
285
|
};
|
|
284
286
|
//#endregion
|
|
287
|
+
//#region src/core/spatial/grid.ts
|
|
288
|
+
/**
|
|
289
|
+
* A uniform spatial hash over axis-aligned rects — the plain, NON-reactive
|
|
290
|
+
* building block behind the flow's spatial queries (RFC-4239 dossier:
|
|
291
|
+
* gesture-scoped snapshots and epoch-rebuilt indexes; deliberately never a
|
|
292
|
+
* live-maintained reactive structure, which would re-create the round-6
|
|
293
|
+
* central-collection anti-pattern).
|
|
294
|
+
*
|
|
295
|
+
* Every operation is O(cells touched); with cellSize on the order of the
|
|
296
|
+
* query radius or median node size, inserts and queries touch O(1) cells.
|
|
297
|
+
* No balancing, no extent-known-up-front requirement, no dependency —
|
|
298
|
+
* upstream's own bake-off (quadtree vs BVH vs rbush) is why: fixed-radius
|
|
299
|
+
* neighborhood and rect-vs-box queries are the textbook grid case.
|
|
300
|
+
*/
|
|
301
|
+
var SpatialGrid = class {
|
|
302
|
+
cellSize;
|
|
303
|
+
cells = /* @__PURE__ */ new Map();
|
|
304
|
+
rects = /* @__PURE__ */ new Map();
|
|
305
|
+
constructor(cellSize) {
|
|
306
|
+
this.cellSize = cellSize;
|
|
307
|
+
}
|
|
308
|
+
cellRange(rect) {
|
|
309
|
+
let size = this.cellSize;
|
|
310
|
+
return {
|
|
311
|
+
minX: Math.floor(rect.x / size),
|
|
312
|
+
maxX: Math.floor((rect.x + rect.width) / size),
|
|
313
|
+
minY: Math.floor(rect.y / size),
|
|
314
|
+
maxY: Math.floor((rect.y + rect.height) / size)
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
insert(id, rect) {
|
|
318
|
+
this.rects.set(id, rect);
|
|
319
|
+
let { minX, maxX, minY, maxY } = this.cellRange(rect);
|
|
320
|
+
for (let cx = minX; cx <= maxX; cx++) for (let cy = minY; cy <= maxY; cy++) {
|
|
321
|
+
let key = `${cx}:${cy}`, bucket = this.cells.get(key);
|
|
322
|
+
bucket ? bucket.push(id) : this.cells.set(key, [id]);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/** Ids of entries whose rect overlaps the query rect (touching counts). */
|
|
326
|
+
queryRect(query) {
|
|
327
|
+
let { minX, maxX, minY, maxY } = this.cellRange(query), seen = /* @__PURE__ */ new Set(), result = [];
|
|
328
|
+
for (let cx = minX; cx <= maxX; cx++) for (let cy = minY; cy <= maxY; cy++) {
|
|
329
|
+
let bucket = this.cells.get(`${cx}:${cy}`);
|
|
330
|
+
if (bucket) for (let id of bucket) {
|
|
331
|
+
if (seen.has(id)) continue;
|
|
332
|
+
seen.add(id);
|
|
333
|
+
let rect = this.rects.get(id);
|
|
334
|
+
rect.x <= query.x + query.width && rect.x + rect.width >= query.x && rect.y <= query.y + query.height && rect.y + rect.height >= query.y && result.push(id);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return result;
|
|
338
|
+
}
|
|
339
|
+
get size() {
|
|
340
|
+
return this.rects.size;
|
|
341
|
+
}
|
|
342
|
+
}, GestureSpatialLookup = class {
|
|
343
|
+
#real;
|
|
344
|
+
#cellSize;
|
|
345
|
+
#grid = null;
|
|
346
|
+
#queryRect = null;
|
|
347
|
+
constructor(real, cellSize) {
|
|
348
|
+
this.#real = real, this.#cellSize = cellSize;
|
|
349
|
+
}
|
|
350
|
+
/** Snapshot the current geometry into the grid (gesture start). */
|
|
351
|
+
arm(rectOf) {
|
|
352
|
+
let grid = new SpatialGrid(this.#cellSize);
|
|
353
|
+
for (let [id, value] of this.#real.entries()) grid.insert(id, rectOf(value));
|
|
354
|
+
this.#grid = grid, this.#queryRect = null;
|
|
355
|
+
}
|
|
356
|
+
/** Focus iteration on the neighborhood of the pointer (per move). */
|
|
357
|
+
setQueryCenter(center, radius) {
|
|
358
|
+
this.#queryRect = {
|
|
359
|
+
x: center.x - radius,
|
|
360
|
+
y: center.y - radius,
|
|
361
|
+
width: radius * 2,
|
|
362
|
+
height: radius * 2
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/** Focus iteration on an explicit rect (box-selection gestures). */
|
|
366
|
+
setQueryRect(rect) {
|
|
367
|
+
this.#queryRect = rect;
|
|
368
|
+
}
|
|
369
|
+
/** Back to plain pass-through (gesture end). */
|
|
370
|
+
disarm() {
|
|
371
|
+
this.#grid = null, this.#queryRect = null;
|
|
372
|
+
}
|
|
373
|
+
#candidateIds() {
|
|
374
|
+
return !this.#grid || !this.#queryRect ? null : this.#grid.queryRect(this.#queryRect);
|
|
375
|
+
}
|
|
376
|
+
get(key) {
|
|
377
|
+
return this.#real.get(key);
|
|
378
|
+
}
|
|
379
|
+
has(key) {
|
|
380
|
+
return this.#real.has(key);
|
|
381
|
+
}
|
|
382
|
+
get size() {
|
|
383
|
+
return this.#real.size;
|
|
384
|
+
}
|
|
385
|
+
*keys() {
|
|
386
|
+
let candidates = this.#candidateIds();
|
|
387
|
+
if (!candidates) {
|
|
388
|
+
yield* this.#real.keys();
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
for (let id of candidates) this.#real.has(id) && (yield id);
|
|
392
|
+
}
|
|
393
|
+
*values() {
|
|
394
|
+
let candidates = this.#candidateIds();
|
|
395
|
+
if (!candidates) {
|
|
396
|
+
yield* this.#real.values();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
for (let id of candidates) {
|
|
400
|
+
let value = this.#real.get(id);
|
|
401
|
+
value !== void 0 && (yield value);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
*entries() {
|
|
405
|
+
let candidates = this.#candidateIds();
|
|
406
|
+
if (!candidates) {
|
|
407
|
+
yield* this.#real.entries();
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
for (let id of candidates) {
|
|
411
|
+
let value = this.#real.get(id);
|
|
412
|
+
value !== void 0 && (yield [id, value]);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
[Symbol.iterator]() {
|
|
416
|
+
return this.entries();
|
|
417
|
+
}
|
|
418
|
+
forEach(callback, thisArg) {
|
|
419
|
+
for (let [key, value] of this.entries()) callback.call(thisArg, value, key, this);
|
|
420
|
+
}
|
|
421
|
+
[Symbol.toStringTag] = "GestureSpatialLookup";
|
|
422
|
+
set() {
|
|
423
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
424
|
+
}
|
|
425
|
+
getOrInsert() {
|
|
426
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
427
|
+
}
|
|
428
|
+
getOrInsertComputed() {
|
|
429
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
430
|
+
}
|
|
431
|
+
delete() {
|
|
432
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
433
|
+
}
|
|
434
|
+
clear() {
|
|
435
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region src/components/handle/connectionGestureLookup.ts
|
|
440
|
+
/**
|
|
441
|
+
* Upstream `getClosestHandle` prefilters nodes within
|
|
442
|
+
* `connectionRadius + ADDITIONAL_DISTANCE` of the pointer; ADDITIONAL_DISTANCE
|
|
443
|
+
* is hardcoded to 250 in @xyflow/system (xyhandle/utils.ts). Tracked here with
|
|
444
|
+
* a safety pad: a superset of candidates is always correct (their exact
|
|
445
|
+
* distance filter runs after), so the pad only costs a few extra candidates.
|
|
446
|
+
*/
|
|
447
|
+
const armConnectionGestureLookup = (options) => {
|
|
448
|
+
let { event, real, domNode, getTransform, connectionRadius } = options, containerBounds = domNode?.getBoundingClientRect();
|
|
449
|
+
if (!containerBounds) return real;
|
|
450
|
+
let radius = connectionRadius + 250 + 50, lookup = new GestureSpatialLookup(real, radius);
|
|
451
|
+
lookup.arm((node) => nodeToRect(node));
|
|
452
|
+
let update = (moveEvent) => {
|
|
453
|
+
lookup.setQueryCenter(pointToRendererPoint(getEventPosition(moveEvent, containerBounds), getTransform(), !1, [1, 1]), radius);
|
|
454
|
+
};
|
|
455
|
+
update(event);
|
|
456
|
+
let doc = getHostForElement(event.target), dispose = () => {
|
|
457
|
+
doc.removeEventListener("mousemove", update, !0), doc.removeEventListener("touchmove", update, !0), doc.removeEventListener("mouseup", dispose, !0), doc.removeEventListener("touchend", dispose, !0), lookup.disarm();
|
|
458
|
+
};
|
|
459
|
+
return doc.addEventListener("mousemove", update, !0), doc.addEventListener("touchmove", update, !0), doc.addEventListener("mouseup", dispose, !0), doc.addEventListener("touchend", dispose, !0), lookup;
|
|
460
|
+
}, buildConnectionGestureParams = (options) => {
|
|
461
|
+
let { event, store, actions, gestureLookup } = options;
|
|
462
|
+
return {
|
|
463
|
+
lib: store.lib,
|
|
464
|
+
flowId: store.id,
|
|
465
|
+
domNode: store.domNode,
|
|
466
|
+
autoPanOnConnect: store.autoPanOnConnect,
|
|
467
|
+
autoPanSpeed: store.autoPanSpeed,
|
|
468
|
+
connectionMode: store.connectionMode,
|
|
469
|
+
connectionRadius: store.connectionRadius,
|
|
470
|
+
nodeLookup: gestureLookup,
|
|
471
|
+
cancelConnection: actions.cancelConnection,
|
|
472
|
+
panBy: actions.panBy,
|
|
473
|
+
updateConnection: ((connection) => {
|
|
474
|
+
actions.setConnection(connection), flush();
|
|
475
|
+
}),
|
|
476
|
+
isValidConnection: store.isValidConnection,
|
|
477
|
+
onConnectStart: store.onConnectStart,
|
|
478
|
+
onConnectEnd: store.onConnectEnd,
|
|
479
|
+
getTransform: () => store.transform,
|
|
480
|
+
getFromHandle: () => store.connection.fromHandle,
|
|
481
|
+
dragThreshold: store.connectionDragThreshold,
|
|
482
|
+
handleDomNode: event.currentTarget
|
|
483
|
+
};
|
|
484
|
+
};
|
|
485
|
+
//#endregion
|
|
285
486
|
//#region src/components/edge/EdgeReconnectAnchor.tsx
|
|
286
487
|
var _tmpl$$32 = /* @__PURE__ */ template("<div style=background:transparent;border:none;cursor:move>");
|
|
287
488
|
/** Grab area that lets an edge end be dragged off its handle and reconnected. */
|
|
@@ -305,27 +506,24 @@ const EdgeReconnectAnchor = (props) => {
|
|
|
305
506
|
nodeId: edge().target,
|
|
306
507
|
handleId: edge().targetHandle ?? null,
|
|
307
508
|
type: "target"
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
flowId: store.id,
|
|
509
|
+
}, gestureLookup = armConnectionGestureLookup({
|
|
510
|
+
event,
|
|
511
|
+
real: nodeLookup,
|
|
312
512
|
domNode: store.domNode,
|
|
513
|
+
getTransform: () => store.transform,
|
|
514
|
+
connectionRadius: store.connectionRadius
|
|
515
|
+
});
|
|
516
|
+
XYHandle.onPointerDown(event, {
|
|
517
|
+
...buildConnectionGestureParams({
|
|
518
|
+
event,
|
|
519
|
+
store,
|
|
520
|
+
actions,
|
|
521
|
+
gestureLookup
|
|
522
|
+
}),
|
|
313
523
|
nodeId: opposite.nodeId,
|
|
314
524
|
handleId: opposite.handleId,
|
|
315
|
-
autoPanOnConnect: store.autoPanOnConnect,
|
|
316
|
-
connectionMode: store.connectionMode,
|
|
317
|
-
connectionRadius: store.connectionRadius,
|
|
318
|
-
nodeLookup,
|
|
319
525
|
isTarget: opposite.type === "target",
|
|
320
526
|
edgeUpdaterType: opposite.type,
|
|
321
|
-
cancelConnection: actions.cancelConnection,
|
|
322
|
-
panBy: actions.panBy,
|
|
323
|
-
updateConnection: (connection) => {
|
|
324
|
-
actions.setConnection(connection), flush();
|
|
325
|
-
},
|
|
326
|
-
isValidConnection: store.isValidConnection,
|
|
327
|
-
onConnectStart: store.onConnectStart,
|
|
328
|
-
onConnectEnd: store.onConnectEnd,
|
|
329
527
|
onConnect: (connection) => {
|
|
330
528
|
let newEdge = {
|
|
331
529
|
...edge(),
|
|
@@ -335,12 +533,7 @@ const EdgeReconnectAnchor = (props) => {
|
|
|
335
533
|
},
|
|
336
534
|
onReconnectEnd: (event, connectionState) => {
|
|
337
535
|
setReconnectingState(!1), store.onReconnectEnd?.(event, edge(), opposite.type, connectionState);
|
|
338
|
-
}
|
|
339
|
-
getTransform: () => store.transform,
|
|
340
|
-
getFromHandle: () => store.connection.fromHandle,
|
|
341
|
-
autoPanSpeed: store.autoPanSpeed,
|
|
342
|
-
dragThreshold: store.connectionDragThreshold,
|
|
343
|
-
handleDomNode: event.currentTarget
|
|
536
|
+
}
|
|
344
537
|
});
|
|
345
538
|
};
|
|
346
539
|
return createComponent(EdgeLabel, mergeProps({
|
|
@@ -416,9 +609,81 @@ const A11yDescriptions = () => {
|
|
|
416
609
|
}
|
|
417
610
|
})
|
|
418
611
|
];
|
|
419
|
-
},
|
|
420
|
-
let
|
|
421
|
-
|
|
612
|
+
}, createSelectionCommands = ({ store, setNodesStore, setEdgesStore, setSelectionRect, setSelectionRectMode, nodeLookup, edgeLookup, updateNodePositions }) => {
|
|
613
|
+
let unselectNodesAndEdges = ({ nodes: _nodes, edges } = {}) => {
|
|
614
|
+
let nodesToUnselect = new Set((_nodes || store.nodes).map(({ id }) => id));
|
|
615
|
+
nodesToUnselect.size && setNodesStore((nodes) => {
|
|
616
|
+
for (let node of nodes) nodesToUnselect.has(node.id) && (node.selected = !1);
|
|
617
|
+
});
|
|
618
|
+
let edgesToUnselect = new Set((edges ?? store.edges).map(({ id }) => id));
|
|
619
|
+
edgesToUnselect.size && setEdgesStore((edges) => {
|
|
620
|
+
for (let edge of edges) edgesToUnselect.has(edge.id) && (edge.selected = !1);
|
|
621
|
+
}), flush();
|
|
622
|
+
}, addSelectedNodes = (ids) => {
|
|
623
|
+
let isMultiSelection = store.multiselectionKeyPressed, idSet = new Set(ids);
|
|
624
|
+
setNodesStore((nodes) => {
|
|
625
|
+
for (let node of nodes) {
|
|
626
|
+
let nodeWillBeSelected = idSet.has(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
627
|
+
node.selected !== selected && (node.selected = selected);
|
|
628
|
+
}
|
|
629
|
+
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
630
|
+
}, addSelectedEdges = (ids) => {
|
|
631
|
+
let isMultiSelection = store.multiselectionKeyPressed, idSet = new Set(ids);
|
|
632
|
+
setEdgesStore((edges) => {
|
|
633
|
+
for (let edge of edges) {
|
|
634
|
+
let edgeWillBeSelected = idSet.has(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
635
|
+
edge.selected !== selected && (edge.selected = selected);
|
|
636
|
+
}
|
|
637
|
+
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
638
|
+
};
|
|
639
|
+
return {
|
|
640
|
+
unselectNodesAndEdges,
|
|
641
|
+
addSelectedNodes,
|
|
642
|
+
addSelectedEdges,
|
|
643
|
+
handleNodeSelection: (id, unselect, nodeRef) => {
|
|
644
|
+
let node = store.nodes.find((n) => n.id === id);
|
|
645
|
+
if (!node) {
|
|
646
|
+
emitFlowError(store.onError, "012", errorMessages.error012(id));
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
650
|
+
nodes: [node],
|
|
651
|
+
edges: []
|
|
652
|
+
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]);
|
|
653
|
+
},
|
|
654
|
+
handleEdgeSelection: (id) => {
|
|
655
|
+
let edge = edgeLookup[id];
|
|
656
|
+
if (!edge) {
|
|
657
|
+
emitFlowError(store.onError, "012", errorMessages.error012(id));
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
isEdgeSelectable(edge, store) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
661
|
+
nodes: [],
|
|
662
|
+
edges: [edge]
|
|
663
|
+
}) : addSelectedEdges([id]));
|
|
664
|
+
},
|
|
665
|
+
moveSelectedNodes: (direction, factor) => {
|
|
666
|
+
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;
|
|
667
|
+
for (let node of nodeLookup.values()) {
|
|
668
|
+
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
669
|
+
let nextPosition = {
|
|
670
|
+
x: node.internals.positionAbsolute.x + xDiff,
|
|
671
|
+
y: node.internals.positionAbsolute.y + yDiff
|
|
672
|
+
};
|
|
673
|
+
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
674
|
+
let { position } = calculateNodePosition({
|
|
675
|
+
nodeId: node.id,
|
|
676
|
+
nextPosition,
|
|
677
|
+
nodeLookup,
|
|
678
|
+
nodeExtent: store.nodeExtent,
|
|
679
|
+
nodeOrigin: store.nodeOrigin,
|
|
680
|
+
onError: store.onError
|
|
681
|
+
});
|
|
682
|
+
nodeUpdates.set(node.id, { position });
|
|
683
|
+
}
|
|
684
|
+
updateNodePositions(nodeUpdates);
|
|
685
|
+
}
|
|
686
|
+
};
|
|
422
687
|
}, 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(() => {
|
|
423
688
|
let { width, height } = source;
|
|
424
689
|
if (!width || !height) return null;
|
|
@@ -549,14 +814,48 @@ var RecordMapFacade = class {
|
|
|
549
814
|
}
|
|
550
815
|
};
|
|
551
816
|
//#endregion
|
|
552
|
-
//#region src/core/
|
|
817
|
+
//#region src/core/measurementIngest.ts
|
|
553
818
|
/**
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
819
|
+
* The measurement ingest lifecycle (WP3): everything that flows FROM the DOM
|
|
820
|
+
* measuring pass INTO the data graph, plus the garbage collection that keeps
|
|
821
|
+
* the measurements root aligned with graph membership. The DOM side (resize
|
|
822
|
+
* observers, the idle-scheduled measuring pass) lives in createSolidFlow;
|
|
823
|
+
* headless usage never calls these.
|
|
558
824
|
*/
|
|
559
|
-
const
|
|
825
|
+
const createMeasurementIngest = ({ setMeasurementsStore, setNodesStore, nodes }) => (createEffect(() => new Set(nodes().map((n) => n.id)), (currentIds) => {
|
|
826
|
+
setMeasurementsStore((draft) => {
|
|
827
|
+
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
828
|
+
});
|
|
829
|
+
}), {
|
|
830
|
+
applyMeasurementWrites: (writes) => {
|
|
831
|
+
setMeasurementsStore((draft) => {
|
|
832
|
+
for (let write of writes) if (write.hidden) {
|
|
833
|
+
let entry = draft[write.id];
|
|
834
|
+
entry && (entry.handleBounds = void 0);
|
|
835
|
+
} else draft[write.id] = {
|
|
836
|
+
measured: write.measured,
|
|
837
|
+
handleBounds: write.handleBounds
|
|
838
|
+
};
|
|
839
|
+
});
|
|
840
|
+
},
|
|
841
|
+
applyNodeChanges: (changes) => {
|
|
842
|
+
changes.length !== 0 && setNodesStore((nodes) => {
|
|
843
|
+
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
844
|
+
for (let change of changes) {
|
|
845
|
+
let node = nodeById.get(change.id);
|
|
846
|
+
if (node) switch (change.type) {
|
|
847
|
+
case "dimensions":
|
|
848
|
+
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
849
|
+
...node.measured,
|
|
850
|
+
...change.dimensions
|
|
851
|
+
};
|
|
852
|
+
break;
|
|
853
|
+
case "position": node.position = change.position ?? node.position;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
}), connectionKey = (nodeId, type, handleId) => `${nodeId}${type ? handleId ? `-${type}-${handleId}` : `-${type}` : ""}`, pairKey = (aNode, aHandle, bNode, bHandle) => `${aNode}-${aHandle}--${bNode}-${bHandle}`, createConnections = (source) => createProjection(() => {
|
|
560
859
|
let out = {}, add = (key, entry, connection) => {
|
|
561
860
|
(out[key] ??= {})[entry] = connection;
|
|
562
861
|
};
|
|
@@ -575,7 +874,20 @@ const connectionKey = (nodeId, type, handleId) => `${nodeId}${type ? handleId ?
|
|
|
575
874
|
let out = {};
|
|
576
875
|
for (let edge of source.edges) out[edge.id] = edge;
|
|
577
876
|
return out;
|
|
578
|
-
}, {}, { key: "id" })
|
|
877
|
+
}, {}, { key: "id" }), createRowRecordProjection = (rowStores) => {
|
|
878
|
+
let assigned = /* @__PURE__ */ new Map();
|
|
879
|
+
return createProjection((draft) => {
|
|
880
|
+
let seen = /* @__PURE__ */ new Set();
|
|
881
|
+
for (let { id, store } of rowStores()) {
|
|
882
|
+
let row = store.row;
|
|
883
|
+
row && (seen.add(id), assigned.get(id) !== row && (assigned.set(id, row), draft[id] = row));
|
|
884
|
+
}
|
|
885
|
+
for (let id of assigned.keys()) seen.has(id) || (assigned.delete(id), delete draft[id]);
|
|
886
|
+
}, {}, {
|
|
887
|
+
key: null,
|
|
888
|
+
shallow: !0
|
|
889
|
+
});
|
|
890
|
+
};
|
|
579
891
|
function isManualZIndexMode(zIndexMode) {
|
|
580
892
|
return zIndexMode === "manual";
|
|
581
893
|
}
|
|
@@ -619,11 +931,7 @@ const EMPTY_AUTO_INDEX = /* @__PURE__ */ new Map(), createInternalNodes = (sourc
|
|
|
619
931
|
x,
|
|
620
932
|
y
|
|
621
933
|
}, row.internals.z = z;
|
|
622
|
-
} else source.nodes.length;
|
|
623
|
-
}
|
|
624
|
-
if (userNode.parentId) {
|
|
625
|
-
let parent = entryById.get(userNode.parentId);
|
|
626
|
-
parent?.store.row.internals.positionAbsolute.x, parent?.store.row.internals.z;
|
|
934
|
+
} else source.nodes.length, emitFlowError(source.onError, "parent-missing", `Parent node ${userNode.parentId} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);
|
|
627
935
|
}
|
|
628
936
|
return { row };
|
|
629
937
|
}, {}, { key: "id" }), entry = {
|
|
@@ -636,19 +944,8 @@ const EMPTY_AUTO_INDEX = /* @__PURE__ */ new Map(), createInternalNodes = (sourc
|
|
|
636
944
|
id,
|
|
637
945
|
store
|
|
638
946
|
};
|
|
639
|
-
}, { keyed: (userNode) => userNode.id })
|
|
640
|
-
return
|
|
641
|
-
let seen = /* @__PURE__ */ new Set();
|
|
642
|
-
for (let { id, store } of rowStores()) {
|
|
643
|
-
seen.add(id);
|
|
644
|
-
let row = store.row;
|
|
645
|
-
assigned.get(id) !== row && (assigned.set(id, row), draft[id] = row);
|
|
646
|
-
}
|
|
647
|
-
for (let id of assigned.keys()) seen.has(id) || (assigned.delete(id), delete draft[id]);
|
|
648
|
-
}, {}, {
|
|
649
|
-
key: null,
|
|
650
|
-
shallow: !0
|
|
651
|
-
});
|
|
947
|
+
}, { keyed: (userNode) => userNode.id });
|
|
948
|
+
return createRowRecordProjection(rowStores);
|
|
652
949
|
};
|
|
653
950
|
function calculateChildXYZ(childNode, parentNode, nodeOrigin, nodeExtent, selectedNodeZ, zIndexMode) {
|
|
654
951
|
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({
|
|
@@ -693,24 +990,14 @@ const createLayoutedEdges = (source) => {
|
|
|
693
990
|
let rowStores = mapArray(() => source.edges, (edgeAccessor) => ({
|
|
694
991
|
id: edgeAccessor().id,
|
|
695
992
|
store: createProjection(() => {
|
|
696
|
-
let edge = edgeAccessor()
|
|
697
|
-
return
|
|
993
|
+
let edge = edgeAccessor();
|
|
994
|
+
return { row: buildRow(source, edge) };
|
|
698
995
|
}, { row: null }, { key: "id" })
|
|
699
|
-
}), { keyed: (edge) => edge.id })
|
|
700
|
-
return
|
|
701
|
-
let seen = /* @__PURE__ */ new Set();
|
|
702
|
-
for (let { id, store } of rowStores()) {
|
|
703
|
-
let row = store.row;
|
|
704
|
-
row && (seen.add(id), assigned.get(id) !== row && (assigned.set(id, row), draft[id] = row));
|
|
705
|
-
}
|
|
706
|
-
for (let id of assigned.keys()) seen.has(id) || (assigned.delete(id), delete draft[id]);
|
|
707
|
-
}, {}, {
|
|
708
|
-
key: null,
|
|
709
|
-
shallow: !0
|
|
710
|
-
});
|
|
996
|
+
}), { keyed: (edge) => edge.id });
|
|
997
|
+
return createRowRecordProjection(rowStores);
|
|
711
998
|
}, buildRow = (source, edge) => {
|
|
712
999
|
let sourceNode = source.nodeLookup.get(edge.source), targetNode = source.nodeLookup.get(edge.target);
|
|
713
|
-
if (!sourceNode || !targetNode) return
|
|
1000
|
+
if (!sourceNode || !targetNode) return null;
|
|
714
1001
|
let edgePosition = getEdgePosition({
|
|
715
1002
|
id: edge.id,
|
|
716
1003
|
sourceNode,
|
|
@@ -740,7 +1027,33 @@ const createLayoutedEdges = (source) => {
|
|
|
740
1027
|
let out = {};
|
|
741
1028
|
for (let node of source.nodes) node.parentId && (out[node.parentId] = !0);
|
|
742
1029
|
return out;
|
|
743
|
-
}, {}, { key: "id" }),
|
|
1030
|
+
}, {}, { key: "id" }), createSeededGraphStores = (props, config) => {
|
|
1031
|
+
props.nodes !== void 0 && props.defaultNodes, props.edges !== void 0 && props.defaultEdges;
|
|
1032
|
+
let [nodesStore, setNodesStore] = createStore(props.nodes ?? [...props.defaultNodes ?? []]), [edgesStore, setEdgesStore] = createStore(props.edges ?? [...props.defaultEdges ?? []]), nodeSeedAdopted = props.nodes !== void 0 || props.defaultNodes !== void 0, edgeSeedAdopted = props.edges !== void 0 || props.defaultEdges !== void 0;
|
|
1033
|
+
return createEffect(() => {
|
|
1034
|
+
let next = config().nodes;
|
|
1035
|
+
if (next) for (let node of next);
|
|
1036
|
+
return { next };
|
|
1037
|
+
}, ({ next }) => {
|
|
1038
|
+
next && (nodeSeedAdopted = !0, setNodesStore(() => next));
|
|
1039
|
+
}, { defer: !0 }), createEffect(() => {
|
|
1040
|
+
let next = config().edges;
|
|
1041
|
+
if (next) for (let edge of next);
|
|
1042
|
+
return { next };
|
|
1043
|
+
}, ({ next }) => {
|
|
1044
|
+
next && (edgeSeedAdopted = !0, setEdgesStore(() => next));
|
|
1045
|
+
}, { defer: !0 }), createEffect(() => ({
|
|
1046
|
+
nodes: config().defaultNodes,
|
|
1047
|
+
edges: config().defaultEdges
|
|
1048
|
+
}), ({ nodes: defaultNodes, edges: defaultEdges }) => {
|
|
1049
|
+
defaultNodes && !nodeSeedAdopted && config().nodes === void 0 && (nodeSeedAdopted = !0, setNodesStore(() => [...defaultNodes])), defaultEdges && !edgeSeedAdopted && config().edges === void 0 && (edgeSeedAdopted = !0, setEdgesStore(() => [...defaultEdges]));
|
|
1050
|
+
}, { defer: !0 }), {
|
|
1051
|
+
nodesStore,
|
|
1052
|
+
setNodesStore,
|
|
1053
|
+
edgesStore,
|
|
1054
|
+
setEdgesStore
|
|
1055
|
+
};
|
|
1056
|
+
}, getInitialViewport = (fitView, initialViewport, width, height, nodeLookup) => {
|
|
744
1057
|
if (fitView && !initialViewport && width && height) {
|
|
745
1058
|
let bounds = getInternalNodesBounds(nodeLookup, { filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)) });
|
|
746
1059
|
return getViewportForBounds$1(bounds, width, height, .5, 2, .1);
|
|
@@ -751,9 +1064,7 @@ const createLayoutedEdges = (source) => {
|
|
|
751
1064
|
zoom: 1
|
|
752
1065
|
};
|
|
753
1066
|
}, createFlowState = (props, injections = {}) => {
|
|
754
|
-
let _props = merge(getDefaultFlowStateProps(), props), initialNodeTypes = injections.initialNodeTypes ?? {}, initialEdgeTypes = injections.initialEdgeTypes ?? {}, prefersDark = injections.prefersDark ?? (() => _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props),
|
|
755
|
-
props.nodes !== void 0 && props.defaultNodes, props.edges !== void 0 && props.defaultEdges;
|
|
756
|
-
let [nodesStore, setNodesStore] = createStore(props.nodes ?? [...props.defaultNodes ?? []]), [edgesStore, setEdgesStore] = createStore(props.edges ?? [...props.defaultEdges ?? []]), nodeSeedAdopted = props.nodes !== void 0 || props.defaultNodes !== void 0, edgeSeedAdopted = props.edges !== void 0 || props.defaultEdges !== void 0, [measurementsStore, setMeasurementsStore] = createStore({}), internalNodes = createInternalNodes({
|
|
1067
|
+
let _props = merge(getDefaultFlowStateProps(), props), initialNodeTypes = injections.initialNodeTypes ?? {}, initialEdgeTypes = injections.initialEdgeTypes ?? {}, prefersDark = injections.prefersDark ?? (() => _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props), ariaLabelConfig = createMemo(() => 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 = createMemo(() => config().minZoom), maxZoom = createMemo(() => config().maxZoom), [nodesConnectable, setNodesConnectable] = createSignal(() => config().nodesConnectable), [nodesDraggable, setNodesDraggable] = createSignal(() => config().nodesDraggable), [panZoom, setPanZoom] = createSignal(null), [selectionRect, setSelectionRect] = createSignal(), [selectionRectMode, setSelectionRectMode] = createSignal(), [snapGrid, setSnapGrid] = createSignal(() => config().snapGrid), translateExtent = createMemo(() => 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, edgesStore, setEdgesStore } = createSeededGraphStores(props, config), [measurementsStore, setMeasurementsStore] = createStore({}), internalNodes = createInternalNodes({
|
|
757
1068
|
get nodes() {
|
|
758
1069
|
return nodesStore;
|
|
759
1070
|
},
|
|
@@ -771,26 +1082,12 @@ const createLayoutedEdges = (source) => {
|
|
|
771
1082
|
},
|
|
772
1083
|
get zIndexMode() {
|
|
773
1084
|
return config().zIndexMode;
|
|
1085
|
+
},
|
|
1086
|
+
get onError() {
|
|
1087
|
+
return config().onFlowError;
|
|
774
1088
|
}
|
|
775
1089
|
}), nodeLookup = new RecordMapFacade(internalNodes), initialViewport = getInitialViewport(_props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), [viewportStore, setViewportStore] = createStore(_props.viewport ?? initialViewport);
|
|
776
|
-
createEffect(() => {
|
|
777
|
-
let next = config().nodes;
|
|
778
|
-
if (next) for (let node of next);
|
|
779
|
-
return { next };
|
|
780
|
-
}, ({ next }) => {
|
|
781
|
-
next && (nodeSeedAdopted = !0, setNodesStore(() => next));
|
|
782
|
-
}, { defer: !0 }), createEffect(() => {
|
|
783
|
-
let next = config().edges;
|
|
784
|
-
if (next) for (let edge of next);
|
|
785
|
-
return { next };
|
|
786
|
-
}, ({ next }) => {
|
|
787
|
-
next && (edgeSeedAdopted = !0, setEdgesStore(() => next));
|
|
788
|
-
}, { defer: !0 }), createEffect(() => ({
|
|
789
|
-
nodes: config().defaultNodes,
|
|
790
|
-
edges: config().defaultEdges
|
|
791
|
-
}), ({ nodes: defaultNodes, edges: defaultEdges }) => {
|
|
792
|
-
defaultNodes && !nodeSeedAdopted && config().nodes === void 0 && (nodeSeedAdopted = !0, setNodesStore(() => [...defaultNodes])), defaultEdges && !edgeSeedAdopted && config().edges === void 0 && (edgeSeedAdopted = !0, setEdgesStore(() => [...defaultEdges]));
|
|
793
|
-
}, { defer: !0 }), createEffect(() => config().viewport, (next) => {
|
|
1090
|
+
createEffect(() => config().viewport, (next) => {
|
|
794
1091
|
next && setViewportStore(() => next);
|
|
795
1092
|
}, { defer: !0 });
|
|
796
1093
|
let transform = createMemo(() => [
|
|
@@ -802,25 +1099,33 @@ const createLayoutedEdges = (source) => {
|
|
|
802
1099
|
if (nodes.length === 0) return !1;
|
|
803
1100
|
for (let node of nodes) if (!node.hidden && (node.measured?.width === void 0 || node.measured?.height === void 0)) return !1;
|
|
804
1101
|
return !0;
|
|
805
|
-
}),
|
|
1102
|
+
}), resolvedColorMode = createMemo(() => {
|
|
1103
|
+
let mode = config().colorMode;
|
|
1104
|
+
return mode === "system" ? prefersDark() ? "dark" : "light" : mode;
|
|
1105
|
+
}), projectedConnection = createMemo(() => {
|
|
1106
|
+
let state = connection();
|
|
1107
|
+
return state.inProgress ? {
|
|
1108
|
+
...state,
|
|
1109
|
+
to: pointToRendererPoint(state.to, transform())
|
|
1110
|
+
} : state;
|
|
1111
|
+
}), connectionFromHandle = createMemo(() => connection().fromHandle ?? null, { equals: (a, b) => a === b || !!a && !!b && a.nodeId === b.nodeId && a.type === b.type && a.id === b.id }), connectionTargetByHandle = createProjection((draft) => {
|
|
1112
|
+
let state = connection(), toHandle = state.inProgress ? state.toHandle : null, key = toHandle ? connectionKey(toHandle.nodeId, toHandle.type, toHandle.id ?? null) : null;
|
|
1113
|
+
for (let existing of Object.keys(draft)) existing !== key && delete draft[existing];
|
|
1114
|
+
key && (draft[key] = state.isValid ? "valid" : "invalid");
|
|
1115
|
+
}, {}, { key: null }), connectionOriginByHandle = createProjection((draft) => {
|
|
1116
|
+
let fromHandle = connection().fromHandle ?? clickConnectStartHandle(), fromKey = fromHandle ? connectionKey(fromHandle.nodeId, fromHandle.type, fromHandle.id ?? null) : null, siblingKey = fromHandle ? connectionKey(fromHandle.nodeId, fromHandle.type === "source" ? "target" : "source", fromHandle.id ?? null) : null;
|
|
1117
|
+
for (let existing of Object.keys(draft)) existing !== fromKey && existing !== siblingKey && delete draft[existing];
|
|
1118
|
+
fromKey && (draft[fromKey] = "from"), siblingKey && (draft[siblingKey] = "excluded");
|
|
1119
|
+
}, {}, { key: null }), mergedNodeTypes = createMemo(() => ({
|
|
1120
|
+
...initialNodeTypes,
|
|
1121
|
+
...config().nodeTypes
|
|
1122
|
+
})), mergedEdgeTypes = createMemo(() => ({
|
|
1123
|
+
...initialEdgeTypes,
|
|
1124
|
+
...config().edgeTypes
|
|
1125
|
+
})), selectedNodesView = createMemo(() => nodesStore.filter((node) => node.selected)), selectedEdgesView = createMemo(() => edgesStore.filter((edge) => edge.selected)), store = merge({
|
|
806
1126
|
width: 0,
|
|
807
1127
|
height: 0
|
|
808
1128
|
}, config, {
|
|
809
|
-
get _colorMode() {
|
|
810
|
-
return config().colorMode;
|
|
811
|
-
},
|
|
812
|
-
get _colorModeSSR() {
|
|
813
|
-
return config().colorModeSSR;
|
|
814
|
-
},
|
|
815
|
-
get _connection() {
|
|
816
|
-
return connection();
|
|
817
|
-
},
|
|
818
|
-
get _nodeTypes() {
|
|
819
|
-
return config().nodeTypes;
|
|
820
|
-
},
|
|
821
|
-
get _edgeTypes() {
|
|
822
|
-
return config().edgeTypes;
|
|
823
|
-
},
|
|
824
1129
|
get ariaLabelConfig() {
|
|
825
1130
|
return ariaLabelConfig();
|
|
826
1131
|
},
|
|
@@ -831,14 +1136,19 @@ const createLayoutedEdges = (source) => {
|
|
|
831
1136
|
return clickConnectStartHandle();
|
|
832
1137
|
},
|
|
833
1138
|
get colorMode() {
|
|
834
|
-
return
|
|
1139
|
+
return resolvedColorMode();
|
|
835
1140
|
},
|
|
836
1141
|
get connection() {
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1142
|
+
return projectedConnection();
|
|
1143
|
+
},
|
|
1144
|
+
get connectionFromHandle() {
|
|
1145
|
+
return connectionFromHandle();
|
|
1146
|
+
},
|
|
1147
|
+
get connectionTargetByHandle() {
|
|
1148
|
+
return connectionTargetByHandle;
|
|
1149
|
+
},
|
|
1150
|
+
get connectionOriginByHandle() {
|
|
1151
|
+
return connectionOriginByHandle;
|
|
842
1152
|
},
|
|
843
1153
|
get domNode() {
|
|
844
1154
|
return domNode();
|
|
@@ -847,10 +1157,7 @@ const createLayoutedEdges = (source) => {
|
|
|
847
1157
|
return dragging();
|
|
848
1158
|
},
|
|
849
1159
|
get edgeTypes() {
|
|
850
|
-
return
|
|
851
|
-
...initialEdgeTypes,
|
|
852
|
-
...this._edgeTypes
|
|
853
|
-
};
|
|
1160
|
+
return mergedEdgeTypes();
|
|
854
1161
|
},
|
|
855
1162
|
get elementsSelectable() {
|
|
856
1163
|
return elementsSelectable();
|
|
@@ -883,19 +1190,16 @@ const createLayoutedEdges = (source) => {
|
|
|
883
1190
|
return nodesDraggable();
|
|
884
1191
|
},
|
|
885
1192
|
get nodeTypes() {
|
|
886
|
-
return
|
|
887
|
-
...initialNodeTypes,
|
|
888
|
-
...this._nodeTypes
|
|
889
|
-
};
|
|
1193
|
+
return mergedNodeTypes();
|
|
890
1194
|
},
|
|
891
1195
|
get panZoom() {
|
|
892
1196
|
return panZoom();
|
|
893
1197
|
},
|
|
894
1198
|
get selectedNodes() {
|
|
895
|
-
return
|
|
1199
|
+
return selectedNodesView();
|
|
896
1200
|
},
|
|
897
1201
|
get selectedEdges() {
|
|
898
|
-
return
|
|
1202
|
+
return selectedEdgesView();
|
|
899
1203
|
},
|
|
900
1204
|
get selectionRect() {
|
|
901
1205
|
return selectionRect();
|
|
@@ -984,7 +1288,7 @@ const createLayoutedEdges = (source) => {
|
|
|
984
1288
|
return store.onError;
|
|
985
1289
|
},
|
|
986
1290
|
nodeLookup
|
|
987
|
-
}), visibleEdgeIds = createMemo(() => Object.keys(layoutedEdges)),
|
|
1291
|
+
}), visibleEdgeIds = createMemo(() => Object.keys(layoutedEdges)), getLayoutedEdge = (id) => layoutedEdges[id], fitView = async (options) => store.panZoom ? await fitViewport({
|
|
988
1292
|
nodes: nodeLookup,
|
|
989
1293
|
width: store.width,
|
|
990
1294
|
height: store.height,
|
|
@@ -1010,33 +1314,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1010
1314
|
setNodesStore((nodes) => {
|
|
1011
1315
|
for (let node of nodes) nodeDragItems.has(node.id) && (node.dragging = dragging, node.position = nodeDragItems.get(node.id).position);
|
|
1012
1316
|
});
|
|
1013
|
-
}, applyMeasurementWrites = (
|
|
1014
|
-
setMeasurementsStore
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
} else draft[write.id] = {
|
|
1019
|
-
measured: write.measured,
|
|
1020
|
-
handleBounds: write.handleBounds
|
|
1021
|
-
};
|
|
1022
|
-
});
|
|
1023
|
-
}, applyNodeChanges = (changes) => {
|
|
1024
|
-
changes.length !== 0 && setNodesStore((nodes) => {
|
|
1025
|
-
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
1026
|
-
for (let change of changes) {
|
|
1027
|
-
let node = nodeById.get(change.id);
|
|
1028
|
-
if (node) switch (change.type) {
|
|
1029
|
-
case "dimensions":
|
|
1030
|
-
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
1031
|
-
...node.measured,
|
|
1032
|
-
...change.dimensions
|
|
1033
|
-
};
|
|
1034
|
-
break;
|
|
1035
|
-
case "position": node.position = change.position ?? node.position;
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
});
|
|
1039
|
-
}, markInitialNodesMeasured = () => {
|
|
1317
|
+
}, { applyMeasurementWrites, applyNodeChanges } = createMeasurementIngest({
|
|
1318
|
+
setMeasurementsStore,
|
|
1319
|
+
setNodesStore,
|
|
1320
|
+
nodes: () => nodesStore
|
|
1321
|
+
}), markInitialNodesMeasured = () => {
|
|
1040
1322
|
initialNodesMeasured = !0, tryInitialFitView();
|
|
1041
1323
|
}, requestMeasure = () => {}, setMeasureRequester = (fn) => {
|
|
1042
1324
|
requestMeasure = fn;
|
|
@@ -1051,66 +1333,16 @@ const createLayoutedEdges = (source) => {
|
|
|
1051
1333
|
ease: options?.ease,
|
|
1052
1334
|
interpolate: options?.interpolate
|
|
1053
1335
|
}), Promise.resolve(!0)) : Promise.resolve(!1);
|
|
1054
|
-
},
|
|
1055
|
-
store
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
}), flush();
|
|
1065
|
-
}, addSelectedNodes = (ids) => {
|
|
1066
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
1067
|
-
setNodesStore((nodes) => {
|
|
1068
|
-
for (let node of nodes) {
|
|
1069
|
-
let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
1070
|
-
node.selected !== selected && (node.selected = selected);
|
|
1071
|
-
}
|
|
1072
|
-
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
1073
|
-
}, addSelectedEdges = (ids) => {
|
|
1074
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
1075
|
-
setEdgesStore((edges) => {
|
|
1076
|
-
for (let edge of edges) {
|
|
1077
|
-
let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
1078
|
-
edge.selected !== selected && (edge.selected = selected);
|
|
1079
|
-
}
|
|
1080
|
-
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
1081
|
-
}, handleNodeSelection = (id, unselect, nodeRef) => {
|
|
1082
|
-
let node = store.nodes.find((n) => n.id === id);
|
|
1083
|
-
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
1084
|
-
nodes: [node],
|
|
1085
|
-
edges: []
|
|
1086
|
-
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
1087
|
-
}, handleEdgeSelection = (id) => {
|
|
1088
|
-
let edge = edgeLookup[id];
|
|
1089
|
-
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
1090
|
-
nodes: [],
|
|
1091
|
-
edges: [edge]
|
|
1092
|
-
}) : addSelectedEdges([id]));
|
|
1093
|
-
}, moveSelectedNodes = (direction, factor) => {
|
|
1094
|
-
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;
|
|
1095
|
-
for (let node of nodeLookup.values()) {
|
|
1096
|
-
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
1097
|
-
let nextPosition = {
|
|
1098
|
-
x: node.internals.positionAbsolute.x + xDiff,
|
|
1099
|
-
y: node.internals.positionAbsolute.y + yDiff
|
|
1100
|
-
};
|
|
1101
|
-
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
1102
|
-
let { position } = calculateNodePosition({
|
|
1103
|
-
nodeId: node.id,
|
|
1104
|
-
nextPosition,
|
|
1105
|
-
nodeLookup,
|
|
1106
|
-
nodeExtent: store.nodeExtent,
|
|
1107
|
-
nodeOrigin: store.nodeOrigin,
|
|
1108
|
-
onError: store.onError
|
|
1109
|
-
});
|
|
1110
|
-
nodeUpdates.set(node.id, { position });
|
|
1111
|
-
}
|
|
1112
|
-
updateNodePositions(nodeUpdates);
|
|
1113
|
-
}, panBy$1 = (delta) => panBy({
|
|
1336
|
+
}, stableSetViewport = (viewport) => setViewportStore(() => viewport), { unselectNodesAndEdges, addSelectedNodes, addSelectedEdges, handleNodeSelection, handleEdgeSelection, moveSelectedNodes } = createSelectionCommands({
|
|
1337
|
+
store,
|
|
1338
|
+
setNodesStore,
|
|
1339
|
+
setEdgesStore,
|
|
1340
|
+
setSelectionRect,
|
|
1341
|
+
setSelectionRectMode,
|
|
1342
|
+
nodeLookup,
|
|
1343
|
+
edgeLookup,
|
|
1344
|
+
updateNodePositions
|
|
1345
|
+
}), panBy$1 = (delta) => panBy({
|
|
1114
1346
|
delta,
|
|
1115
1347
|
panZoom: store.panZoom,
|
|
1116
1348
|
transform: store.transform,
|
|
@@ -1187,8 +1419,27 @@ const createLayoutedEdges = (source) => {
|
|
|
1187
1419
|
get snapGrid() {
|
|
1188
1420
|
return store.snapGrid;
|
|
1189
1421
|
}
|
|
1190
|
-
},
|
|
1191
|
-
|
|
1422
|
+
}, intersectionGrid = null, intersectionRows = null, queryIntersectionCandidates = (rect) => untrack(() => {
|
|
1423
|
+
if (!intersectionGrid) {
|
|
1424
|
+
let grid = new SpatialGrid(300), rows = /* @__PURE__ */ new Map();
|
|
1425
|
+
for (let node of store.nodes) {
|
|
1426
|
+
let internalNode = nodeLookup.get(node.id);
|
|
1427
|
+
internalNode && (grid.insert(node.id, nodeToRect(internalNode)), rows.set(node.id, node));
|
|
1428
|
+
}
|
|
1429
|
+
intersectionGrid = grid, intersectionRows = rows, queueMicrotask(() => {
|
|
1430
|
+
intersectionGrid = null, intersectionRows = null;
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
let rows = intersectionRows, result = [];
|
|
1434
|
+
for (let id of intersectionGrid.queryRect(rect)) {
|
|
1435
|
+
let row = rows.get(id);
|
|
1436
|
+
row && result.push(row);
|
|
1437
|
+
}
|
|
1438
|
+
return result;
|
|
1439
|
+
}), getNodeRect = (node) => {
|
|
1440
|
+
let nodeToUse = isNode(node) ? node : nodeLookup.get(node.id);
|
|
1441
|
+
if (!nodeToUse) return null;
|
|
1442
|
+
let position = nodeToUse.parentId ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, store.nodeOrigin) : nodeToUse.position, nodeWithPosition = {
|
|
1192
1443
|
...nodeToUse,
|
|
1193
1444
|
position,
|
|
1194
1445
|
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
@@ -1242,7 +1493,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1242
1493
|
x,
|
|
1243
1494
|
y,
|
|
1244
1495
|
zoom
|
|
1245
|
-
], _snapGrid
|
|
1496
|
+
], !!_snapGrid, _snapGrid || [1, 1]);
|
|
1246
1497
|
},
|
|
1247
1498
|
flowToScreenPosition: (position) => {
|
|
1248
1499
|
if (!store.domNode) return position;
|
|
@@ -1306,14 +1557,18 @@ const createLayoutedEdges = (source) => {
|
|
|
1306
1557
|
let remainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
|
|
1307
1558
|
store.onNodesDelete?.(matchingNodes), setNodesStore(() => remainingNodes);
|
|
1308
1559
|
}
|
|
1309
|
-
|
|
1560
|
+
let deletedNodes = matchingNodes ?? [], deletedEdges = matchingEdges ?? [];
|
|
1561
|
+
return (deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
1562
|
+
nodes: deletedNodes,
|
|
1563
|
+
edges: deletedEdges
|
|
1564
|
+
}), {
|
|
1310
1565
|
deletedNodes: matchingNodes,
|
|
1311
1566
|
deletedEdges: matchingEdges
|
|
1312
1567
|
};
|
|
1313
1568
|
},
|
|
1314
1569
|
getIntersectingNodes: (nodeOrRect, partially = !0, nodesToIntersect) => {
|
|
1315
1570
|
let isRect = isRectObject(nodeOrRect), nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
1316
|
-
return nodeRect ? (nodesToIntersect
|
|
1571
|
+
return nodeRect ? (nodesToIntersect ?? queryIntersectionCandidates(nodeRect)).filter((n) => {
|
|
1317
1572
|
let internalNode = nodeLookup.get(n.id);
|
|
1318
1573
|
if (!internalNode || !isRect && n.id === nodeOrRect.id) return !1;
|
|
1319
1574
|
let currNodeRect = nodeToRect(internalNode), overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
@@ -1369,10 +1624,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1369
1624
|
extent: store.translateExtent
|
|
1370
1625
|
}), ({ panZoom, extent }) => {
|
|
1371
1626
|
panZoom?.setTranslateExtent(extent);
|
|
1372
|
-
}), createEffect(() => new Set(store.nodes.map((n) => n.id)), (currentIds) => {
|
|
1373
|
-
setMeasurementsStore((draft) => {
|
|
1374
|
-
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
1375
|
-
});
|
|
1376
1627
|
}), {
|
|
1377
1628
|
store,
|
|
1378
1629
|
flow,
|
|
@@ -1384,14 +1635,12 @@ const createLayoutedEdges = (source) => {
|
|
|
1384
1635
|
parentIds,
|
|
1385
1636
|
connections,
|
|
1386
1637
|
actions: {
|
|
1387
|
-
|
|
1638
|
+
getLayoutedEdge,
|
|
1388
1639
|
applyInitialFitView,
|
|
1389
1640
|
applyMeasurementWrites,
|
|
1390
1641
|
applyNodeChanges,
|
|
1391
1642
|
markInitialNodesMeasured,
|
|
1392
1643
|
setMeasureRequester,
|
|
1393
|
-
resetStoreValues,
|
|
1394
|
-
setAriaLabelConfig,
|
|
1395
1644
|
setAriaLiveMessage,
|
|
1396
1645
|
setClickConnectStartHandle,
|
|
1397
1646
|
setConfig,
|
|
@@ -1399,15 +1648,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1399
1648
|
setDeleteKeyPressed,
|
|
1400
1649
|
setDomNode,
|
|
1401
1650
|
setDragging,
|
|
1402
|
-
|
|
1403
|
-
return setEdgesStore;
|
|
1404
|
-
},
|
|
1651
|
+
setEdges: setEdgesStore,
|
|
1405
1652
|
setElementsSelectable,
|
|
1406
1653
|
setHeight,
|
|
1407
1654
|
setMultiselectionKeyPressed,
|
|
1408
|
-
|
|
1409
|
-
return setNodesStore;
|
|
1410
|
-
},
|
|
1655
|
+
setNodes: setNodesStore,
|
|
1411
1656
|
setNodesConnectable,
|
|
1412
1657
|
setNodesDraggable,
|
|
1413
1658
|
setPanActivationKeyPressed,
|
|
@@ -1415,9 +1660,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1415
1660
|
setSelectionKeyPressed,
|
|
1416
1661
|
setSelectionRect,
|
|
1417
1662
|
setSelectionRectMode,
|
|
1418
|
-
|
|
1419
|
-
return (viewport) => setViewportStore(() => viewport);
|
|
1420
|
-
},
|
|
1663
|
+
setViewport: stableSetViewport,
|
|
1421
1664
|
setWidth,
|
|
1422
1665
|
setZoomActivationKeyPressed,
|
|
1423
1666
|
addEdge,
|
|
@@ -1426,7 +1669,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1426
1669
|
zoomOut,
|
|
1427
1670
|
fitView,
|
|
1428
1671
|
setCenter,
|
|
1429
|
-
setPaneClickDistance,
|
|
1430
1672
|
unselectNodesAndEdges,
|
|
1431
1673
|
addSelectedNodes,
|
|
1432
1674
|
addSelectedEdges,
|
|
@@ -1438,8 +1680,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1438
1680
|
reset
|
|
1439
1681
|
}
|
|
1440
1682
|
};
|
|
1683
|
+
}, createEdgeStore = (edges) => {
|
|
1684
|
+
let [store, setStore] = typeof edges == "function" ? createStore(edges, []) : createStore(edges);
|
|
1685
|
+
return [store, setStore];
|
|
1441
1686
|
}, createNodeStore = (nodes) => {
|
|
1442
|
-
let [store, setStore] = createStore(nodes);
|
|
1687
|
+
let [store, setStore] = typeof nodes == "function" ? createStore(nodes, []) : createStore(nodes);
|
|
1443
1688
|
return [store, setStore];
|
|
1444
1689
|
};
|
|
1445
1690
|
//#endregion
|
|
@@ -1447,21 +1692,28 @@ const createLayoutedEdges = (source) => {
|
|
|
1447
1692
|
var _tmpl$$30 = /* @__PURE__ */ template("<svg class=solid-flow__edge-wrapper><g>");
|
|
1448
1693
|
/** Internal per-edge wrapper: interaction, a11y, viewport culling, and the dynamic edge component. */
|
|
1449
1694
|
const EdgeWrapper = (props) => {
|
|
1450
|
-
let edgeRef, { store, actions } = useInternalSolidFlow(), edgeId = () => props.edgeId, edge = () => actions.
|
|
1695
|
+
let edgeRef, { store, actions } = useInternalSolidFlow(), edgeId = () => props.edgeId, edge = () => actions.getLayoutedEdge(edgeId()), edgeType = () => edge().type ?? "default", selectable = () => isEdgeSelectable(edge(), store), focusable = () => edge().focusable ?? store.edgesFocusable, edgeTypeValid = () => edgeType() in store.edgeTypes, edgeComponent = () => store.edgeTypes[edgeTypeValid() ? edgeType() : "default"];
|
|
1696
|
+
createEffect(() => ({
|
|
1697
|
+
valid: edgeTypeValid(),
|
|
1698
|
+
edgeType: edgeType()
|
|
1699
|
+
}), ({ valid, edgeType }) => {
|
|
1700
|
+
valid || emitFlowError(store.onError, "011", errorMessages.error011(edgeType));
|
|
1701
|
+
});
|
|
1702
|
+
let markerStartUrl = () => edge().markerStart ? `url('#${getMarkerId(edge().markerStart, store.id)}')` : void 0, markerEndUrl = () => edge().markerEnd ? `url('#${getMarkerId(edge().markerEnd, store.id)}')` : void 0, onClick = (event) => {
|
|
1451
1703
|
selectable() && actions.handleEdgeSelection(edgeId()), props.onEdgeClick?.({
|
|
1452
1704
|
edge: edge(),
|
|
1453
1705
|
event
|
|
1454
1706
|
});
|
|
1455
|
-
},
|
|
1456
|
-
(
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
}, onKeyDown = (event) => {
|
|
1707
|
+
}, onContextMenu = (event) => props.onEdgeContextMenu?.({
|
|
1708
|
+
edge: edge(),
|
|
1709
|
+
event
|
|
1710
|
+
}), onPointerEnter = (event) => props.onEdgePointerEnter?.({
|
|
1711
|
+
edge: edge(),
|
|
1712
|
+
event
|
|
1713
|
+
}), onPointerLeave = (event) => props.onEdgePointerLeave?.({
|
|
1714
|
+
edge: edge(),
|
|
1715
|
+
event
|
|
1716
|
+
}), onKeyDown = (event) => {
|
|
1465
1717
|
store.disableKeyboardA11y || !elementSelectionKeys.includes(event.key) || !selectable() || (event.key === "Escape" ? (edgeRef?.blur(), actions.unselectNodesAndEdges({ edges: [edge()] })) : actions.addSelectedEdges([edge().id]));
|
|
1466
1718
|
}, ariaLabel = () => edge().ariaLabel ?? `Edge from ${edge().source} to ${edge().target}`, culled = createMemo(() => isEdgeCulled(edge(), store.cullingViewport));
|
|
1467
1719
|
return createComponent(EdgeIdContext, {
|
|
@@ -1504,9 +1756,9 @@ const EdgeWrapper = (props) => {
|
|
|
1504
1756
|
},
|
|
1505
1757
|
onClick,
|
|
1506
1758
|
onKeyDown: (e) => focusable() && onKeyDown(e),
|
|
1507
|
-
onContextMenu
|
|
1508
|
-
onPointerEnter
|
|
1509
|
-
onPointerLeave
|
|
1759
|
+
onContextMenu,
|
|
1760
|
+
onPointerEnter,
|
|
1761
|
+
onPointerLeave
|
|
1510
1762
|
}, () => edge().domAttributes), !0), insert(_el$2, createComponent(Dynamic, {
|
|
1511
1763
|
get component() {
|
|
1512
1764
|
return edgeComponent();
|
|
@@ -1887,7 +2139,7 @@ const Handle = (props) => {
|
|
|
1887
2139
|
position: "top",
|
|
1888
2140
|
isConnectableStart: !0,
|
|
1889
2141
|
isConnectableEnd: !0
|
|
1890
|
-
}), { 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,
|
|
2142
|
+
}), { 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, originState = () => store.connectionOriginByHandle[connectionKey(nodeId(), _props.type, handleId())], connectingFrom = () => originState() === "from", targetState = () => store.connectionTargetByHandle[connectionKey(nodeId(), _props.type, handleId())], connectingTo = () => targetState() !== void 0, valid = () => targetState() === "valid", prevConnections = null;
|
|
1891
2143
|
createEffect(() => {
|
|
1892
2144
|
if (!_props.onConnect && !_props.onDisconnect) return null;
|
|
1893
2145
|
let rec = connections[connectionKey(nodeId(), _props.type, _props.id)], map = /* @__PURE__ */ new Map();
|
|
@@ -1905,37 +2157,25 @@ const Handle = (props) => {
|
|
|
1905
2157
|
}, edge = store.onBeforeConnect?.(handleConnection) ?? handleConnection;
|
|
1906
2158
|
actions.addEdge(edge), store.onConnect?.(handleConnection);
|
|
1907
2159
|
}, onPointerDown = (event) => {
|
|
2160
|
+
let gestureLookup = armConnectionGestureLookup({
|
|
2161
|
+
event,
|
|
2162
|
+
real: nodeLookup,
|
|
2163
|
+
domNode: store.domNode,
|
|
2164
|
+
getTransform: () => store.transform,
|
|
2165
|
+
connectionRadius: store.connectionRadius
|
|
2166
|
+
});
|
|
1908
2167
|
XYHandle.onPointerDown(event, {
|
|
2168
|
+
...buildConnectionGestureParams({
|
|
2169
|
+
event,
|
|
2170
|
+
store,
|
|
2171
|
+
actions,
|
|
2172
|
+
gestureLookup
|
|
2173
|
+
}),
|
|
1909
2174
|
handleId: handleId(),
|
|
1910
2175
|
nodeId: nodeId(),
|
|
1911
2176
|
isTarget: isTarget(),
|
|
1912
|
-
connectionRadius: store.connectionRadius,
|
|
1913
|
-
domNode: store.domNode,
|
|
1914
|
-
nodeLookup,
|
|
1915
|
-
connectionMode: store.connectionMode,
|
|
1916
|
-
lib: store.lib,
|
|
1917
|
-
autoPanOnConnect: store.autoPanOnConnect,
|
|
1918
|
-
flowId: store.id,
|
|
1919
2177
|
isValidConnection: _props.isValidConnection ?? store.isValidConnection,
|
|
1920
|
-
|
|
1921
|
-
actions.setConnection(connection), flush();
|
|
1922
|
-
}),
|
|
1923
|
-
cancelConnection: actions.cancelConnection,
|
|
1924
|
-
panBy: actions.panBy,
|
|
1925
|
-
onConnect: onConnectExtended,
|
|
1926
|
-
onConnectStart: (event, startParams) => {
|
|
1927
|
-
store.onConnectStart?.(event, {
|
|
1928
|
-
nodeId: startParams.nodeId,
|
|
1929
|
-
handleId: startParams.handleId,
|
|
1930
|
-
handleType: startParams.handleType
|
|
1931
|
-
});
|
|
1932
|
-
},
|
|
1933
|
-
onConnectEnd: store.onConnectEnd,
|
|
1934
|
-
getTransform: () => store.transform,
|
|
1935
|
-
getFromHandle: () => store.connection.fromHandle,
|
|
1936
|
-
autoPanSpeed: store.autoPanSpeed,
|
|
1937
|
-
dragThreshold: store.connectionDragThreshold,
|
|
1938
|
-
handleDomNode: event.currentTarget
|
|
2178
|
+
onConnect: onConnectExtended
|
|
1939
2179
|
});
|
|
1940
2180
|
}, onClick = (event) => {
|
|
1941
2181
|
if (!nodeId() || !store.clickConnectStartHandle && !_props.isConnectableStart) return;
|
|
@@ -1970,7 +2210,7 @@ const Handle = (props) => {
|
|
|
1970
2210
|
isValid && connection && onConnectExtended(connection);
|
|
1971
2211
|
let connectionClone = structuredClone(snapshot(store.connection));
|
|
1972
2212
|
delete connectionClone.inProgress, connectionClone.toPosition = connectionClone.toHandle ? connectionClone.toHandle.position : null, store.onClickConnectEnd?.(event, connectionClone), actions.setClickConnectStartHandle(void 0);
|
|
1973
|
-
}
|
|
2213
|
+
};
|
|
1974
2214
|
var _el$ = _tmpl$$29();
|
|
1975
2215
|
return spread(_el$, mergeProps(rest, {
|
|
1976
2216
|
role: "button",
|
|
@@ -2013,7 +2253,7 @@ const Handle = (props) => {
|
|
|
2013
2253
|
connectablestart: _props.isConnectableStart,
|
|
2014
2254
|
connectableend: _props.isConnectableEnd,
|
|
2015
2255
|
connectable: !!connectable(),
|
|
2016
|
-
|
|
2256
|
+
excluded: !!originState()
|
|
2017
2257
|
}
|
|
2018
2258
|
];
|
|
2019
2259
|
}
|
|
@@ -2141,7 +2381,7 @@ const NodeWrapper = (props) => {
|
|
|
2141
2381
|
let el = nodeRef();
|
|
2142
2382
|
el && props.resizeObserver?.unobserve(el);
|
|
2143
2383
|
});
|
|
2144
|
-
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 = () => {
|
|
2384
|
+
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[nodeTypeValid() ? nodeType() : "default"], isParentNode = () => !!parentIds[node().id], transform = () => {
|
|
2145
2385
|
let { x, y } = node().internals.positionAbsolute;
|
|
2146
2386
|
return `translate(${x}px, ${y}px)`;
|
|
2147
2387
|
}, sizeStyle = () => {
|
|
@@ -2152,17 +2392,18 @@ const NodeWrapper = (props) => {
|
|
|
2152
2392
|
...h ? { height: toPxString(h) } : {}
|
|
2153
2393
|
};
|
|
2154
2394
|
}, culled = createMemo(() => isNodeCulled(node(), store.cullingViewport)), style = () => ({
|
|
2395
|
+
...sizeStyle(),
|
|
2155
2396
|
"z-index": node().internals.z,
|
|
2156
2397
|
transform: transform(),
|
|
2157
2398
|
visibility: culled() || !nodeHasDimensions(node()) ? "hidden" : "visible",
|
|
2158
|
-
"pointer-events": culled() ? "none" : void 0
|
|
2159
|
-
...sizeStyle(),
|
|
2160
|
-
...node().style ?? {}
|
|
2399
|
+
"pointer-events": culled() ? "none" : void 0
|
|
2161
2400
|
});
|
|
2162
2401
|
createEffect(() => ({
|
|
2163
2402
|
valid: nodeTypeValid(),
|
|
2164
2403
|
nodeType: nodeType()
|
|
2165
|
-
}), ({ valid, nodeType }) => {
|
|
2404
|
+
}), ({ valid, nodeType }) => {
|
|
2405
|
+
valid || emitFlowError(store.onError, "003", errorMessages.error003(nodeType));
|
|
2406
|
+
}), createEffect(() => ({
|
|
2166
2407
|
id: node().id,
|
|
2167
2408
|
nodeElement: nodeRef(),
|
|
2168
2409
|
nodeType: nodeType(),
|
|
@@ -2517,7 +2758,7 @@ const InitialNodeTypesMap = {
|
|
|
2517
2758
|
pendingEntries = updateEntries, scheduleIdleCallback(() => {
|
|
2518
2759
|
let updates = new Map(pendingEntries);
|
|
2519
2760
|
pendingEntries = void 0;
|
|
2520
|
-
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode);
|
|
2761
|
+
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode, store.nodeExtent);
|
|
2521
2762
|
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());
|
|
2522
2763
|
});
|
|
2523
2764
|
};
|
|
@@ -2539,21 +2780,29 @@ function useInternalSolidFlow() {
|
|
|
2539
2780
|
var _tmpl$$26 = /* @__PURE__ */ template("<svg class=\"solid-flow__container solid-flow__connectionline\"><g>"), _tmpl$2$2 = /* @__PURE__ */ template("<svg><path class=solid-flow__connection-path fill=none></svg>", 2);
|
|
2540
2781
|
/** Internal component rendering the in-progress connection line. */
|
|
2541
2782
|
const ConnectionLine = (props) => {
|
|
2542
|
-
let { store } = useInternalSolidFlow(), connectionStatus = () => getConnectionStatus(store.connection.isValid)
|
|
2783
|
+
let { store } = useInternalSolidFlow(), connectionStatus = () => getConnectionStatus(store.connection.isValid), inProgress = createMemo(() => {
|
|
2784
|
+
let state = store.connection;
|
|
2785
|
+
return state.inProgress ? state : null;
|
|
2786
|
+
});
|
|
2543
2787
|
return createComponent(Show, {
|
|
2544
2788
|
get when() {
|
|
2545
|
-
return
|
|
2789
|
+
return inProgress();
|
|
2546
2790
|
},
|
|
2547
|
-
|
|
2791
|
+
children: (connection) => (() => {
|
|
2548
2792
|
var _el$ = _tmpl$$26(), _el$2 = _el$.firstChild;
|
|
2549
2793
|
return insert(_el$2, createComponent(Show, {
|
|
2550
2794
|
get when() {
|
|
2551
2795
|
return props.component;
|
|
2552
2796
|
},
|
|
2553
2797
|
get fallback() {
|
|
2554
|
-
return createComponent(InternalConnectionLine, {
|
|
2555
|
-
|
|
2556
|
-
|
|
2798
|
+
return createComponent(InternalConnectionLine, {
|
|
2799
|
+
get style() {
|
|
2800
|
+
return props.style;
|
|
2801
|
+
},
|
|
2802
|
+
get connection() {
|
|
2803
|
+
return connection();
|
|
2804
|
+
}
|
|
2805
|
+
});
|
|
2557
2806
|
},
|
|
2558
2807
|
children: (CustomComponent) => {
|
|
2559
2808
|
let UserConnectionLine = CustomComponent();
|
|
@@ -2565,37 +2814,37 @@ const ConnectionLine = (props) => {
|
|
|
2565
2814
|
return props.style;
|
|
2566
2815
|
},
|
|
2567
2816
|
get fromNode() {
|
|
2568
|
-
return
|
|
2817
|
+
return connection().fromNode;
|
|
2569
2818
|
},
|
|
2570
2819
|
get fromHandle() {
|
|
2571
|
-
return
|
|
2820
|
+
return connection().fromHandle;
|
|
2572
2821
|
},
|
|
2573
2822
|
get fromX() {
|
|
2574
|
-
return
|
|
2823
|
+
return connection().from.x;
|
|
2575
2824
|
},
|
|
2576
2825
|
get fromY() {
|
|
2577
|
-
return
|
|
2826
|
+
return connection().from.y;
|
|
2578
2827
|
},
|
|
2579
2828
|
get toX() {
|
|
2580
|
-
return
|
|
2829
|
+
return connection().to.x;
|
|
2581
2830
|
},
|
|
2582
2831
|
get toY() {
|
|
2583
|
-
return
|
|
2832
|
+
return connection().to.y;
|
|
2584
2833
|
},
|
|
2585
2834
|
get fromPosition() {
|
|
2586
|
-
return
|
|
2835
|
+
return connection().fromPosition;
|
|
2587
2836
|
},
|
|
2588
2837
|
get toPosition() {
|
|
2589
|
-
return
|
|
2838
|
+
return connection().toPosition;
|
|
2590
2839
|
},
|
|
2591
2840
|
get connectionStatus() {
|
|
2592
2841
|
return connectionStatus();
|
|
2593
2842
|
},
|
|
2594
2843
|
get toNode() {
|
|
2595
|
-
return
|
|
2844
|
+
return connection().toNode;
|
|
2596
2845
|
},
|
|
2597
2846
|
get toHandle() {
|
|
2598
|
-
return
|
|
2847
|
+
return connection().toHandle;
|
|
2599
2848
|
}
|
|
2600
2849
|
});
|
|
2601
2850
|
}
|
|
@@ -2607,18 +2856,17 @@ const ConnectionLine = (props) => {
|
|
|
2607
2856
|
}), ({ e, t, a, o }, _p$) => {
|
|
2608
2857
|
e !== _p$?.e && setAttribute(_el$, "width", e), t !== _p$?.t && setAttribute(_el$, "height", t), style(_el$, a, _p$?.a), className(_el$2, o, _p$?.o);
|
|
2609
2858
|
}), _el$;
|
|
2610
|
-
}
|
|
2859
|
+
})()
|
|
2611
2860
|
});
|
|
2612
2861
|
}, InternalConnectionLine = (props) => {
|
|
2613
2862
|
let { store } = useInternalSolidFlow(), path = () => {
|
|
2614
|
-
if (!store.connection.inProgress) return;
|
|
2615
2863
|
let pathParams = {
|
|
2616
|
-
sourceX:
|
|
2617
|
-
sourceY:
|
|
2618
|
-
sourcePosition:
|
|
2619
|
-
targetX:
|
|
2620
|
-
targetY:
|
|
2621
|
-
targetPosition:
|
|
2864
|
+
sourceX: props.connection.from.x,
|
|
2865
|
+
sourceY: props.connection.from.y,
|
|
2866
|
+
sourcePosition: props.connection.fromPosition,
|
|
2867
|
+
targetX: props.connection.to.x,
|
|
2868
|
+
targetY: props.connection.to.y,
|
|
2869
|
+
targetPosition: props.connection.toPosition
|
|
2622
2870
|
};
|
|
2623
2871
|
switch (store.connectionLineType) {
|
|
2624
2872
|
case "default": {
|
|
@@ -2718,25 +2966,32 @@ const MarkerDefinition = () => {
|
|
|
2718
2966
|
})), _el$;
|
|
2719
2967
|
}
|
|
2720
2968
|
});
|
|
2969
|
+
}, createFocusedIdTracker = () => {
|
|
2970
|
+
let [focusedId, setFocusedId] = createSignal(null);
|
|
2971
|
+
return {
|
|
2972
|
+
focusedId,
|
|
2973
|
+
onFocusIn: (event) => {
|
|
2974
|
+
let element = event.target.closest("[data-id]");
|
|
2975
|
+
setFocusedId(element?.getAttribute("data-id") ?? null);
|
|
2976
|
+
},
|
|
2977
|
+
onFocusOut: () => setFocusedId(null)
|
|
2978
|
+
};
|
|
2721
2979
|
};
|
|
2722
2980
|
//#endregion
|
|
2723
2981
|
//#region src/components/container/EdgeRenderer.tsx
|
|
2724
2982
|
var _tmpl$$23 = /* @__PURE__ */ template("<div class=solid-flow__edges><!><!>");
|
|
2725
2983
|
/** Internal renderer iterating the edge id list into `EdgeWrapper`s. */
|
|
2726
2984
|
const EdgeRenderer = (props) => {
|
|
2727
|
-
let { store, actions } = useInternalSolidFlow(),
|
|
2728
|
-
let edgeElement = event.target.closest("[data-id]");
|
|
2729
|
-
setFocusedEdgeId(edgeElement?.getAttribute("data-id") ?? null);
|
|
2730
|
-
};
|
|
2985
|
+
let { store, actions } = useInternalSolidFlow(), { focusedId: focusedEdgeId, onFocusIn, onFocusOut } = createFocusedIdTracker();
|
|
2731
2986
|
var _el$ = _tmpl$$23(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
|
|
2732
|
-
return _el
|
|
2987
|
+
return addEvent(_el$, "focusout", onFocusOut, !0), addEvent(_el$, "focusin", onFocusIn, !0), insert(_el$, createComponent(MarkerDefinition, {}), _el$2), insert(_el$, createComponent(For, {
|
|
2733
2988
|
get each() {
|
|
2734
2989
|
return store.visibleEdgeIds;
|
|
2735
2990
|
},
|
|
2736
2991
|
children: (edgeId) => {
|
|
2737
2992
|
let unmounted = createMemo(() => {
|
|
2738
2993
|
if (!store.onlyRenderVisibleElements || focusedEdgeId() === edgeId) return !1;
|
|
2739
|
-
let edge = actions.
|
|
2994
|
+
let edge = actions.getLayoutedEdge(edgeId);
|
|
2740
2995
|
return !!edge && isEdgeCulled(edge, store.cullingViewport);
|
|
2741
2996
|
});
|
|
2742
2997
|
return createComponent(Show, {
|
|
@@ -2783,12 +3038,9 @@ const NodeRenderer = (props) => {
|
|
|
2783
3038
|
onCleanup(() => {
|
|
2784
3039
|
resizeObserver?.disconnect();
|
|
2785
3040
|
});
|
|
2786
|
-
let
|
|
2787
|
-
let nodeElement = event.target.closest("[data-id]");
|
|
2788
|
-
setFocusedNodeId(nodeElement?.getAttribute("data-id") ?? null);
|
|
2789
|
-
};
|
|
3041
|
+
let { focusedId: focusedNodeId, onFocusIn, onFocusOut } = createFocusedIdTracker();
|
|
2790
3042
|
var _el$ = _tmpl$$22();
|
|
2791
|
-
return _el
|
|
3043
|
+
return addEvent(_el$, "focusout", onFocusOut, !0), addEvent(_el$, "focusin", onFocusIn, !0), insert(_el$, createComponent(For, {
|
|
2792
3044
|
get each() {
|
|
2793
3045
|
return store.visibleNodeIds;
|
|
2794
3046
|
},
|
|
@@ -2848,10 +3100,10 @@ const isSetEqual = (a, b) => {
|
|
|
2848
3100
|
for (let item of a) if (!b.has(item)) return !1;
|
|
2849
3101
|
return !0;
|
|
2850
3102
|
}, Pane = (props) => {
|
|
2851
|
-
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 = {
|
|
3103
|
+
let { store, nodeLookup, edgeLookup, connections, actions } = useInternalSolidFlow(), [containerRef, setContainerRef] = createSignal(), container, containerBounds = null, connectionEndedOnPane = !1, selectionInProgress = !1, selectionSpatialLookup = new GestureSpatialLookup(nodeLookup, 400), selectedNodeIds = /* @__PURE__ */ new Set(), selectedEdgeIds = /* @__PURE__ */ new Set(), autoPanId = 0, position = {
|
|
2852
3104
|
x: 0,
|
|
2853
3105
|
y: 0
|
|
2854
|
-
}, autoPanStarted = !1, autoPanOnSelection = () => props.autoPanOnSelection ?? !0, paneClickDistance = () => props.paneClickDistance ??
|
|
3106
|
+
}, autoPanStarted = !1, autoPanOnSelection = () => props.autoPanOnSelection ?? !0, paneClickDistance = () => props.paneClickDistance ?? 0, _panOnDrag = () => store.panActivationKeyPressed || props.panOnDrag, isSelecting = () => store.selectionKeyPressed || !!store.selectionRect || props.selectionOnDrag && _panOnDrag() !== !0, isSelectionEnabled = () => store.elementsSelectable && (isSelecting() || store.selectionRectMode === "user"), onClick = (event) => {
|
|
2855
3107
|
if (event.target === container) {
|
|
2856
3108
|
if (selectionInProgress || store.connection.inProgress || connectionEndedOnPane) {
|
|
2857
3109
|
selectionInProgress = !1, connectionEndedOnPane = !1;
|
|
@@ -2863,7 +3115,7 @@ const isSetEqual = (a, b) => {
|
|
|
2863
3115
|
if (event.pointerType === "touch" && _panOnDrag() !== !1 && !store.selectionKeyPressed || (containerBounds = container?.getBoundingClientRect() ?? null, !containerBounds)) return;
|
|
2864
3116
|
let eventTargetIsContainer = event.target === container, isNoKeyEvent = !eventTargetIsContainer && !!event.target.closest(".nokey"), isSelectionActive = props.selectionOnDrag && eventTargetIsContainer || store.selectionKeyPressed;
|
|
2865
3117
|
if (isNoKeyEvent || !isSelecting() || !isSelectionActive || event.button !== 0 || !event.isPrimary) return;
|
|
2866
|
-
event.target?.setPointerCapture?.(event.pointerId), selectionInProgress = !1, autoPanStarted = !1;
|
|
3118
|
+
event.target?.setPointerCapture?.(event.pointerId), selectionSpatialLookup.arm((node) => nodeToRect(node)), selectionInProgress = !1, autoPanStarted = !1;
|
|
2867
3119
|
let { x, y } = getEventPosition(event, containerBounds), userSelectionFlowOrigin = pointToRendererPoint({
|
|
2868
3120
|
x,
|
|
2869
3121
|
y
|
|
@@ -2890,14 +3142,21 @@ const isSetEqual = (a, b) => {
|
|
|
2890
3142
|
width: Math.abs(mouseX - screenStart.x),
|
|
2891
3143
|
height: Math.abs(mouseY - screenStart.y)
|
|
2892
3144
|
}, prevSelectedNodeIds = selectedNodeIds, prevSelectedEdgeIds = selectedEdgeIds;
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
3145
|
+
{
|
|
3146
|
+
let [tx, ty, zoom] = store.transform;
|
|
3147
|
+
selectionSpatialLookup.setQueryRect({
|
|
3148
|
+
x: (nextUserSelectRect.x - tx) / zoom,
|
|
3149
|
+
y: (nextUserSelectRect.y - ty) / zoom,
|
|
3150
|
+
width: nextUserSelectRect.width / zoom,
|
|
3151
|
+
height: nextUserSelectRect.height / zoom
|
|
3152
|
+
});
|
|
3153
|
+
}
|
|
3154
|
+
selectedNodeIds = new Set(getNodesInside(selectionSpatialLookup, nextUserSelectRect, store.transform, store.selectionMode === SelectionMode$1.Partial, !0).map((n) => n.id)), selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
2896
3155
|
for (let nodeId of selectedNodeIds) {
|
|
2897
3156
|
let nodeConnections = connections[nodeId];
|
|
2898
3157
|
if (nodeConnections) for (let { edgeId } of Object.values(nodeConnections)) {
|
|
2899
3158
|
let edge = edgeLookup[edgeId];
|
|
2900
|
-
edge && (edge
|
|
3159
|
+
edge && isEdgeSelectable(edge, store) && selectedEdgeIds.add(edgeId);
|
|
2901
3160
|
}
|
|
2902
3161
|
}
|
|
2903
3162
|
isSetEqual(prevSelectedNodeIds, selectedNodeIds) || actions.setNodes((nodes) => {
|
|
@@ -3132,7 +3391,7 @@ const Selection = (props) => {
|
|
|
3132
3391
|
var _tmpl$$16 = /* @__PURE__ */ template("<div>");
|
|
3133
3392
|
/** Internal draggable bounding box rendered around multi-selected nodes. */
|
|
3134
3393
|
const NodeSelection = (props) => {
|
|
3135
|
-
let { store, nodeLookup, actions } = useInternalSolidFlow(), [ref$2, setRef] = createSignal(), bounds = () => store.selectionRectMode === "nodes" ? getInternalNodesBounds(nodeLookup, { filter: (node) => !!node.selected }) : null;
|
|
3394
|
+
let { store, nodeLookup, actions } = useInternalSolidFlow(), [ref$2, setRef] = createSignal(), bounds = createMemo(() => store.selectionRectMode === "nodes" ? getInternalNodesBounds(nodeLookup, { filter: (node) => !!node.selected }) : null);
|
|
3136
3395
|
createEffect(() => ({
|
|
3137
3396
|
el: ref$2(),
|
|
3138
3397
|
focusable: !store.disableKeyboardA11y
|
|
@@ -3140,13 +3399,13 @@ const NodeSelection = (props) => {
|
|
|
3140
3399
|
focusable && el?.focus({ preventScroll: !0 });
|
|
3141
3400
|
});
|
|
3142
3401
|
let onContextMenu = (event) => {
|
|
3143
|
-
let selectedNodes = store.
|
|
3402
|
+
let selectedNodes = store.selectedNodes;
|
|
3144
3403
|
props.onSelectionContextMenu?.({
|
|
3145
3404
|
nodes: selectedNodes,
|
|
3146
3405
|
event
|
|
3147
3406
|
});
|
|
3148
3407
|
}, onClick = (event) => {
|
|
3149
|
-
let selectedNodes = store.
|
|
3408
|
+
let selectedNodes = store.selectedNodes;
|
|
3150
3409
|
props.onSelectionClick?.({
|
|
3151
3410
|
nodes: selectedNodes,
|
|
3152
3411
|
event
|
|
@@ -3229,29 +3488,13 @@ const Attribution = (props) => createComponent(Show, {
|
|
|
3229
3488
|
}
|
|
3230
3489
|
});
|
|
3231
3490
|
}
|
|
3232
|
-
})
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
* `flow` and `commands` are stable identities, so destructuring them is safe:
|
|
3240
|
-
* `const { flow, commands } = useSolidFlow()`.
|
|
3241
|
-
*
|
|
3242
|
-
* @public
|
|
3243
|
-
* @returns the flow's read struct and write surface
|
|
3244
|
-
*/
|
|
3245
|
-
function useSolidFlow() {
|
|
3246
|
-
let { flow, commands } = useInternalSolidFlow();
|
|
3247
|
-
return {
|
|
3248
|
-
...commands,
|
|
3249
|
-
flow,
|
|
3250
|
-
commands
|
|
3251
|
-
};
|
|
3252
|
-
}
|
|
3253
|
-
//#endregion
|
|
3254
|
-
//#region src/components/utility/KeyHandler.ts
|
|
3491
|
+
}), MODIFIER_FLAG = {
|
|
3492
|
+
alt: "altKey",
|
|
3493
|
+
control: "ctrlKey",
|
|
3494
|
+
ctrl: "ctrlKey",
|
|
3495
|
+
meta: "metaKey",
|
|
3496
|
+
shift: "shiftKey"
|
|
3497
|
+
};
|
|
3255
3498
|
function isKeyObject(key) {
|
|
3256
3499
|
return typeof key == "object" && !!key;
|
|
3257
3500
|
}
|
|
@@ -3283,18 +3526,13 @@ function matchesKey(event, keyDef) {
|
|
|
3283
3526
|
function matchesKeyArray(event, keyDefs) {
|
|
3284
3527
|
return keyDefs ? (Array.isArray(keyDefs) ? keyDefs : [keyDefs]).some((keyDef) => matchesKey(event, keyDef)) : !1;
|
|
3285
3528
|
}
|
|
3286
|
-
const MODIFIER_FLAG = {
|
|
3287
|
-
alt: "altKey",
|
|
3288
|
-
control: "ctrlKey",
|
|
3289
|
-
ctrl: "ctrlKey",
|
|
3290
|
-
meta: "metaKey",
|
|
3291
|
-
shift: "shiftKey"
|
|
3292
|
-
};
|
|
3293
3529
|
/**
|
|
3294
3530
|
* Whether an event's modifier flags PROVE this key definition cannot be held
|
|
3295
3531
|
* right now: the key itself is a modifier whose flag is off, or one of its
|
|
3296
3532
|
* required modifiers is off. Definitions built on non-modifier keys are never
|
|
3297
|
-
* contradicted (their state isn't derivable from flags).
|
|
3533
|
+
* contradicted (their state isn't derivable from flags). This is the
|
|
3534
|
+
* self-heal for OS overlays that swallow keyups without blurring the window
|
|
3535
|
+
* (upstream xyflow#5679).
|
|
3298
3536
|
*/
|
|
3299
3537
|
function isContradicted(flags, keyDef) {
|
|
3300
3538
|
let keyFlag = MODIFIER_FLAG[getKeyString(keyDef).toLowerCase()];
|
|
@@ -3311,6 +3549,28 @@ function allContradicted(flags, keyDefs) {
|
|
|
3311
3549
|
let keys = Array.isArray(keyDefs) ? keyDefs : [keyDefs];
|
|
3312
3550
|
return keys.length > 0 && keys.every((keyDef) => isContradicted(flags, keyDef));
|
|
3313
3551
|
}
|
|
3552
|
+
//#endregion
|
|
3553
|
+
//#region src/hooks/useSolidFlow.ts
|
|
3554
|
+
/**
|
|
3555
|
+
* Hook for accessing the flow instance: `{ flow, commands }` plus the
|
|
3556
|
+
* commands spread at the top level for upstream familiarity.
|
|
3557
|
+
*
|
|
3558
|
+
* `flow` and `commands` are stable identities, so destructuring them is safe:
|
|
3559
|
+
* `const { flow, commands } = useSolidFlow()`.
|
|
3560
|
+
*
|
|
3561
|
+
* @public
|
|
3562
|
+
* @returns the flow's read struct and write surface
|
|
3563
|
+
*/
|
|
3564
|
+
function useSolidFlow() {
|
|
3565
|
+
let { flow, commands } = useInternalSolidFlow();
|
|
3566
|
+
return {
|
|
3567
|
+
...commands,
|
|
3568
|
+
flow,
|
|
3569
|
+
commands
|
|
3570
|
+
};
|
|
3571
|
+
}
|
|
3572
|
+
//#endregion
|
|
3573
|
+
//#region src/components/utility/KeyHandler.ts
|
|
3314
3574
|
const KeyHandler = (props) => {
|
|
3315
3575
|
let { store, actions } = useInternalSolidFlow(), { deleteElements } = useSolidFlow(), _props = {
|
|
3316
3576
|
get selectionKey() {
|
|
@@ -3345,14 +3605,11 @@ const KeyHandler = (props) => {
|
|
|
3345
3605
|
}, handleWindowBlur = () => {
|
|
3346
3606
|
resetKeysAndSelection(), cancelPointerGestures();
|
|
3347
3607
|
}, handleDelete = async () => {
|
|
3348
|
-
let selectedNodes = store.
|
|
3608
|
+
let selectedNodes = store.selectedNodes, selectedEdges = store.selectedEdges;
|
|
3609
|
+
await deleteElements({
|
|
3349
3610
|
nodes: selectedNodes,
|
|
3350
3611
|
edges: selectedEdges
|
|
3351
3612
|
});
|
|
3352
|
-
(deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
3353
|
-
nodes: deletedNodes,
|
|
3354
|
-
edges: deletedEdges
|
|
3355
|
-
});
|
|
3356
3613
|
};
|
|
3357
3614
|
return isServer || (createEventListenerMap(window, {
|
|
3358
3615
|
keydown: (event) => {
|
|
@@ -3370,7 +3627,7 @@ const KeyHandler = (props) => {
|
|
|
3370
3627
|
capture: !0,
|
|
3371
3628
|
passive: !0
|
|
3372
3629
|
})), null;
|
|
3373
|
-
};
|
|
3630
|
+
}, FLOW_PROP_KEYS = /* @__PURE__ */ "ariaLabelConfig.ariaLiveMessage.attributionPosition.autoPanOnConnect.autoPanOnNodeDrag.autoPanOnNodeFocus.autoPanOnSelection.autoPanSpeed.class.clickConnect.colorMode.colorModeSSR.connectionDragThreshold.connectionLineComponent.connectionLineContainerStyle.connectionLineStyle.connectionLineType.connectionMode.connectionRadius.defaultEdgeOptions.defaultEdges.defaultMarkerColor.defaultNodes.deleteKey.disableKeyboardA11y.edgeTypes.edges.edgesFocusable.elementsSelectable.elevateEdgesOnSelect.elevateNodesOnSelect.fitView.fitViewOptions.height.id.initialViewport.isValidConnection.maxZoom.minZoom.multiSelectionKey.noDragClass.noPanClass.noWheelClass.nodeClickDistance.nodeDragThreshold.nodeExtent.nodeOrigin.nodeTypes.nodes.nodesConnectable.nodesDraggable.nodesFocusable.onBeforeConnect.onBeforeDelete.onBeforeReconnect.onClickConnectEnd.onClickConnectStart.onConnect.onConnectEnd.onConnectStart.onDelete.onEdgeClick.onEdgeContextMenu.onEdgePointerEnter.onEdgePointerLeave.onEdgesDelete.onFlowError.onInit.onMove.onMoveEnd.onMoveStart.onNodeClick.onNodeContextMenu.onNodeDrag.onNodeDragStart.onNodeDragStop.onNodePointerEnter.onNodePointerLeave.onNodePointerMove.onNodesDelete.onPaneClick.onPaneContextMenu.onReconnect.onReconnectEnd.onReconnectStart.onSelectionChange.onSelectionClick.onSelectionContextMenu.onSelectionDrag.onSelectionDragStart.onSelectionDragStop.onSelectionEnd.onSelectionStart.onlyRenderVisibleElements.panActivationKey.panOnDrag.panOnScroll.panOnScrollMode.panOnScrollSpeed.paneClickDistance.preventScrolling.proOptions.selectNodesOnDrag.selectionKey.selectionMode.selectionOnDrag.snapGrid.style.translateExtent.viewport.width.zIndexMode.zoomActivationKey.zoomOnDoubleClick.zoomOnPinch.zoomOnScroll".split(".");
|
|
3374
3631
|
//#endregion
|
|
3375
3632
|
//#region src/components/SolidFlow.tsx
|
|
3376
3633
|
var _tmpl$$14 = /* @__PURE__ */ template("<div class=\"solid-flow__container solid-flow__viewport-back\">"), _tmpl$2 = /* @__PURE__ */ template("<div class=\"solid-flow__container solid-flow__edge-labels\">"), _tmpl$3 = /* @__PURE__ */ template("<div>");
|
|
@@ -3379,30 +3636,19 @@ const SolidFlow = (props) => {
|
|
|
3379
3636
|
let [domNodeRef, setDomNodeRef] = createSignal(), domNode, _props = merge({
|
|
3380
3637
|
...getDefaultFlowStateProps(),
|
|
3381
3638
|
colorMode: "light",
|
|
3382
|
-
deleteKeyCode: "Backspace",
|
|
3383
|
-
defaultViewport: {
|
|
3384
|
-
x: 0,
|
|
3385
|
-
y: 0,
|
|
3386
|
-
zoom: 1
|
|
3387
|
-
},
|
|
3388
|
-
multiSelectionKeyCode: isMacOs() ? "Meta" : "Control",
|
|
3389
3639
|
nodeClickDistance: 0,
|
|
3390
3640
|
panOnScroll: !1,
|
|
3391
|
-
panActivationKeyCode: "Space",
|
|
3392
3641
|
preventScrolling: !0,
|
|
3393
3642
|
panOnDrag: !0,
|
|
3394
3643
|
panOnScrollSpeed: .5,
|
|
3395
3644
|
panOnScrollMode: "free",
|
|
3396
3645
|
paneClickDistance: 0,
|
|
3397
|
-
reconnectRadius: 10,
|
|
3398
|
-
selectionKeyCode: "Shift",
|
|
3399
3646
|
selectionOnDrag: !1,
|
|
3400
3647
|
translateExtent: infiniteExtent,
|
|
3401
|
-
zoomActivationKeyCode: isMacOs() ? "Meta" : "Control",
|
|
3402
3648
|
zoomOnPinch: !0,
|
|
3403
3649
|
zoomOnDoubleClick: !0,
|
|
3404
3650
|
zoomOnScroll: !0
|
|
3405
|
-
}, props), htmlProps = omit(_props,
|
|
3651
|
+
}, props), htmlProps = omit(_props, ...FLOW_PROP_KEYS, "children"), TypedSolidFlowContext = SolidFlowContext, solidFlow = useContext(TypedSolidFlowContext) ?? createSolidFlow(_props), { store, actions } = solidFlow;
|
|
3406
3652
|
onSettled(() => (actions.applyInitialFitView(_props.fitView), actions.setConfig(_props), actions.setDomNode(domNode), () => {
|
|
3407
3653
|
actions.reset();
|
|
3408
3654
|
})), createEffect(() => domNodeRef(), (el) => {
|
|
@@ -3411,11 +3657,6 @@ const SolidFlow = (props) => {
|
|
|
3411
3657
|
actions.setWidth(el.clientWidth), actions.setHeight(el.clientHeight);
|
|
3412
3658
|
});
|
|
3413
3659
|
return observer.observe(el), () => observer.disconnect();
|
|
3414
|
-
}), createEffect(() => ({
|
|
3415
|
-
panZoom: store.panZoom,
|
|
3416
|
-
distance: _props.paneClickDistance
|
|
3417
|
-
}), ({ panZoom, distance }) => {
|
|
3418
|
-
panZoom?.setClickDistance(distance);
|
|
3419
3660
|
});
|
|
3420
3661
|
let selectedElements = createMemo(() => ({
|
|
3421
3662
|
nodes: store.selectedNodes,
|
|
@@ -3424,7 +3665,7 @@ const SolidFlow = (props) => {
|
|
|
3424
3665
|
createEffect(() => selectedElements(), (params) => {
|
|
3425
3666
|
untrack(() => _props.onSelectionChange)?.(params);
|
|
3426
3667
|
});
|
|
3427
|
-
let rootStyle = () => ({
|
|
3668
|
+
let asyncSeedGuard = () => (_props.nodes?.length, _props.edges?.length, null), rootStyle = () => ({
|
|
3428
3669
|
width: toPxString(_props.width),
|
|
3429
3670
|
height: toPxString(_props.height),
|
|
3430
3671
|
..._props.style
|
|
@@ -3440,7 +3681,13 @@ const SolidFlow = (props) => {
|
|
|
3440
3681
|
"solid-flow",
|
|
3441
3682
|
"solid-flow__container",
|
|
3442
3683
|
_props.class,
|
|
3443
|
-
store.colorMode
|
|
3684
|
+
store.colorMode,
|
|
3685
|
+
{
|
|
3686
|
+
connecting: !!store.connectionFromHandle || !!store.clickConnectStartHandle,
|
|
3687
|
+
"connecting-from-source": (store.connectionFromHandle ?? store.clickConnectStartHandle)?.type === "source",
|
|
3688
|
+
"connecting-from-target": (store.connectionFromHandle ?? store.clickConnectStartHandle)?.type === "target",
|
|
3689
|
+
"connection-strict": store.connectionMode === "strict"
|
|
3690
|
+
}
|
|
3444
3691
|
];
|
|
3445
3692
|
},
|
|
3446
3693
|
get style() {
|
|
@@ -3457,6 +3704,7 @@ const SolidFlow = (props) => {
|
|
|
3457
3704
|
value: solidFlow,
|
|
3458
3705
|
get children() {
|
|
3459
3706
|
return [
|
|
3707
|
+
memo(() => asyncSeedGuard()),
|
|
3460
3708
|
createComponent(KeyHandler, {
|
|
3461
3709
|
get selectionKey() {
|
|
3462
3710
|
return _props.selectionKey;
|
|
@@ -3551,9 +3799,6 @@ const SolidFlow = (props) => {
|
|
|
3551
3799
|
return [
|
|
3552
3800
|
_tmpl$$14(),
|
|
3553
3801
|
createComponent(EdgeRenderer, {
|
|
3554
|
-
get reconnectRadius() {
|
|
3555
|
-
return _props.reconnectRadius;
|
|
3556
|
-
},
|
|
3557
3802
|
get onEdgeClick() {
|
|
3558
3803
|
return _props.onEdgeClick;
|
|
3559
3804
|
},
|
|
@@ -3565,9 +3810,6 @@ const SolidFlow = (props) => {
|
|
|
3565
3810
|
},
|
|
3566
3811
|
get onEdgePointerLeave() {
|
|
3567
3812
|
return _props.onEdgePointerLeave;
|
|
3568
|
-
},
|
|
3569
|
-
get defaultEdgeOptions() {
|
|
3570
|
-
return _props.defaultEdgeOptions;
|
|
3571
3813
|
}
|
|
3572
3814
|
}),
|
|
3573
3815
|
_tmpl$2(),
|
|
@@ -3713,8 +3955,8 @@ function useConnection() {
|
|
|
3713
3955
|
* @returns store with an array of nodes
|
|
3714
3956
|
*/
|
|
3715
3957
|
function useNodes() {
|
|
3716
|
-
let {
|
|
3717
|
-
return () =>
|
|
3958
|
+
let { flow } = useInternalSolidFlow();
|
|
3959
|
+
return () => flow.nodes;
|
|
3718
3960
|
}
|
|
3719
3961
|
/**
|
|
3720
3962
|
* Hook for getting the current edges from the store.
|
|
@@ -3723,8 +3965,8 @@ function useNodes() {
|
|
|
3723
3965
|
* @returns store with an array of edges
|
|
3724
3966
|
*/
|
|
3725
3967
|
function useEdges() {
|
|
3726
|
-
let {
|
|
3727
|
-
return () =>
|
|
3968
|
+
let { flow } = useInternalSolidFlow();
|
|
3969
|
+
return () => flow.edges;
|
|
3728
3970
|
}
|
|
3729
3971
|
/**
|
|
3730
3972
|
* Hook for getting the current viewport from the store.
|
|
@@ -3782,6 +4024,52 @@ function useInternalNode(id) {
|
|
|
3782
4024
|
return () => flow.internalNodes[id()];
|
|
3783
4025
|
}
|
|
3784
4026
|
//#endregion
|
|
4027
|
+
//#region src/hooks/useKeyPress.ts
|
|
4028
|
+
/**
|
|
4029
|
+
* Reactive "is this key (combo) held right now?" — the Solid Flow
|
|
4030
|
+
* counterpart of React Flow's `useKeyPress`, usable anywhere (no flow
|
|
4031
|
+
* context required).
|
|
4032
|
+
*
|
|
4033
|
+
* The definition is an Accessor per house convention — `useKeyPress(() =>
|
|
4034
|
+
* "a")`, `useKeyPress(() => ["a", "d"])`, or `useKeyPress(() => ({ key:
|
|
4035
|
+
* "s", modifier: ["meta"] }))`; swapping the definition resets the state.
|
|
4036
|
+
*
|
|
4037
|
+
* Hardened beyond upstream:
|
|
4038
|
+
* - Combos re-activate when the base key is re-pressed while the modifier
|
|
4039
|
+
* stays held (upstream's oldest open key bug, xyflow#2248).
|
|
4040
|
+
* - Stuck modifiers self-heal from the flags later keyboard/pointer/wheel
|
|
4041
|
+
* events carry (OS overlays swallow keyups without blurring — the macOS
|
|
4042
|
+
* screenshot HUD; xyflow#5679), and window blur resets.
|
|
4043
|
+
*/
|
|
4044
|
+
function useKeyPress(keys) {
|
|
4045
|
+
let [pressed, setPressed] = createSignal(!1);
|
|
4046
|
+
if (createEffect(() => keys(), () => {
|
|
4047
|
+
setPressed(!1);
|
|
4048
|
+
}, { defer: !0 }), !isServer) {
|
|
4049
|
+
let reconcile = (event) => {
|
|
4050
|
+
pressed() && allContradicted(event, keys()) && (setPressed(!1), flush());
|
|
4051
|
+
};
|
|
4052
|
+
createEventListenerMap(window, {
|
|
4053
|
+
keydown: (event) => {
|
|
4054
|
+
reconcile(event), matchesKeyArray(event, keys()) && (setPressed(!0), flush());
|
|
4055
|
+
},
|
|
4056
|
+
keyup: (event) => {
|
|
4057
|
+
reconcile(event), matchesKeyArray(event, keys()) && (setPressed(!1), flush());
|
|
4058
|
+
},
|
|
4059
|
+
blur: () => {
|
|
4060
|
+
setPressed(!1), flush();
|
|
4061
|
+
}
|
|
4062
|
+
}), createEventListenerMap(window, {
|
|
4063
|
+
pointerdown: reconcile,
|
|
4064
|
+
wheel: reconcile
|
|
4065
|
+
}, {
|
|
4066
|
+
capture: !0,
|
|
4067
|
+
passive: !0
|
|
4068
|
+
});
|
|
4069
|
+
}
|
|
4070
|
+
return pressed;
|
|
4071
|
+
}
|
|
4072
|
+
//#endregion
|
|
3785
4073
|
//#region src/hooks/useNodeConnections.ts
|
|
3786
4074
|
/**
|
|
3787
4075
|
* Hook to retrieve all edges connected to a node. Can be filtered by handle type and id.
|
|
@@ -4151,7 +4439,7 @@ delegateEvents(["click"]);
|
|
|
4151
4439
|
//#endregion
|
|
4152
4440
|
//#region src/plugins/minimap/MiniMap.tsx
|
|
4153
4441
|
var _tmpl$$3 = /* @__PURE__ */ template("<svg class=solid-flow__minimap-svg role=img><title></title><path class=solid-flow__minimap-mask fill-rule=evenodd pointer-events=none>");
|
|
4154
|
-
const getAttrFunction = (
|
|
4442
|
+
const getAttrFunction = (value) => value instanceof Function ? value : () => value, MiniMap = (props) => {
|
|
4155
4443
|
let { store, nodeLookup } = useInternalSolidFlow(), _props = propDefaults(props, {
|
|
4156
4444
|
position: "bottom-right",
|
|
4157
4445
|
nodeClass: "",
|
|
@@ -4161,26 +4449,47 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4161
4449
|
width: 200,
|
|
4162
4450
|
height: 150,
|
|
4163
4451
|
nodeBorderRadius: 5,
|
|
4452
|
+
offsetScale: 5,
|
|
4164
4453
|
nodeStrokeWidth: 2,
|
|
4165
4454
|
style: {}
|
|
4166
|
-
}), 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 =
|
|
4455
|
+
}), paneProps = omit(_props, "class", "style", "position", "nodeClass", "nodeStrokeColor", "nodeColor", "pannable", "zoomable", "inversePan", "zoomStep", "offsetScale", "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}`), viewBB = createMemo(() => ({
|
|
4167
4456
|
x: -store.viewport.x / store.viewport.zoom,
|
|
4168
4457
|
y: -store.viewport.y / store.viewport.zoom,
|
|
4169
4458
|
width: store.width / store.viewport.zoom,
|
|
4170
4459
|
height: store.height / store.viewport.zoom
|
|
4171
|
-
}),
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4460
|
+
})), rectsEqual = (a, b) => a === b || !!a && !!b && a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height, sampleBounds = () => untrack(() => {
|
|
4461
|
+
if (nodeLookup.size === 0) return null;
|
|
4462
|
+
let bounds = getInternalNodesBounds(nodeLookup);
|
|
4463
|
+
return Number.isFinite(bounds.x) && Number.isFinite(bounds.width) ? bounds : null;
|
|
4464
|
+
}), [graphBounds, setGraphBounds] = createSignal(sampleBounds(), { equals: rectsEqual });
|
|
4465
|
+
createEffect(() => store.dragging, (dragging) => {
|
|
4466
|
+
if (!dragging) {
|
|
4467
|
+
setGraphBounds(sampleBounds());
|
|
4468
|
+
return;
|
|
4469
|
+
}
|
|
4470
|
+
let raf = requestAnimationFrame(function tick() {
|
|
4471
|
+
setGraphBounds(sampleBounds()), raf = requestAnimationFrame(tick);
|
|
4472
|
+
});
|
|
4473
|
+
return () => cancelAnimationFrame(raf);
|
|
4474
|
+
}), createEffect(() => ({
|
|
4475
|
+
count: store.nodes.length,
|
|
4476
|
+
initialized: store.nodesInitialized
|
|
4477
|
+
}), () => {
|
|
4478
|
+
setGraphBounds(sampleBounds());
|
|
4479
|
+
}), createEffect(() => null, () => {
|
|
4480
|
+
let interval = setInterval(() => setGraphBounds(sampleBounds()), 500);
|
|
4481
|
+
return () => clearInterval(interval);
|
|
4482
|
+
});
|
|
4483
|
+
let boundingRect = createMemo(() => {
|
|
4484
|
+
let view = viewBB(), bounds = graphBounds();
|
|
4485
|
+
return bounds ? getBoundsOfRects(bounds, view) : view;
|
|
4486
|
+
}), viewScale = createMemo(() => Math.max(boundingRect().width / _props.width, boundingRect().height / _props.height)), getViewWidth = () => viewScale() * _props.width, getViewHeight = () => viewScale() * _props.height, getOffset = () => _props.offsetScale * viewScale(), getX = () => {
|
|
4487
|
+
let rect = boundingRect();
|
|
4488
|
+
return rect.x - (getViewWidth() - rect.width) / 2 - getOffset();
|
|
4177
4489
|
}, getY = () => {
|
|
4178
|
-
let
|
|
4179
|
-
return
|
|
4180
|
-
}, getViewboxWidth = () => getViewWidth() + getOffset() * 2, getViewboxHeight = () => getViewHeight() + getOffset() * 2, strokeWidth = () => _props.maskStrokeWidth ? _props.maskStrokeWidth *
|
|
4181
|
-
let currentNodeIds = store.nodes.map((node) => node.id), currentSet = new Set(currentNodeIds);
|
|
4182
|
-
return (prevNodeIds.length !== currentNodeIds.length || !prevNodeIds.every((id) => currentSet.has(id))) && (prevNodeIds = currentNodeIds), prevNodeIds;
|
|
4183
|
-
};
|
|
4490
|
+
let rect = boundingRect();
|
|
4491
|
+
return rect.y - (getViewHeight() - rect.height) / 2 - getOffset();
|
|
4492
|
+
}, getViewboxWidth = () => getViewWidth() + getOffset() * 2, getViewboxHeight = () => getViewHeight() + getOffset() * 2, strokeWidth = () => _props.maskStrokeWidth ? _props.maskStrokeWidth * viewScale() : void 0, nodeIds = createMemo(() => store.nodes.map((node) => node.id), { equals: (a, b) => a.length === b.length && a.every((id, i) => id === b[i]) });
|
|
4184
4493
|
return createComponent(Panel, mergeProps({
|
|
4185
4494
|
get position() {
|
|
4186
4495
|
return _props.position;
|
|
@@ -4211,7 +4520,7 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4211
4520
|
domNode: el,
|
|
4212
4521
|
panZoom,
|
|
4213
4522
|
getTransform: () => store.transform,
|
|
4214
|
-
getViewScale
|
|
4523
|
+
getViewScale: viewScale
|
|
4215
4524
|
});
|
|
4216
4525
|
return setMinimap(instance), () => {
|
|
4217
4526
|
instance.destroy();
|
|
@@ -4248,58 +4557,62 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4248
4557
|
return nodeIds();
|
|
4249
4558
|
},
|
|
4250
4559
|
children: (nodeId) => {
|
|
4251
|
-
let
|
|
4560
|
+
let visibleNode = createMemo(() => {
|
|
4561
|
+
let row = nodeLookup.get(nodeId());
|
|
4562
|
+
return row && nodeHasDimensions(row) && !row.hidden ? row : null;
|
|
4563
|
+
});
|
|
4252
4564
|
return createComponent(Show, {
|
|
4253
4565
|
get when() {
|
|
4254
|
-
return
|
|
4566
|
+
return visibleNode();
|
|
4255
4567
|
},
|
|
4256
|
-
children: (
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4568
|
+
children: (node) => {
|
|
4569
|
+
let dimensions = () => getNodeDimensions(node()), userNode = () => node().internals.userNode;
|
|
4570
|
+
return createComponent(Dynamic, {
|
|
4571
|
+
get component() {
|
|
4572
|
+
return _props.nodeComponent ?? MiniMapNode;
|
|
4573
|
+
},
|
|
4574
|
+
get id() {
|
|
4575
|
+
return nodeId();
|
|
4576
|
+
},
|
|
4577
|
+
get x() {
|
|
4578
|
+
return node().internals.positionAbsolute.x;
|
|
4579
|
+
},
|
|
4580
|
+
get y() {
|
|
4581
|
+
return node().internals.positionAbsolute.y;
|
|
4582
|
+
},
|
|
4583
|
+
get borderRadius() {
|
|
4584
|
+
return _props.nodeBorderRadius;
|
|
4585
|
+
},
|
|
4586
|
+
get strokeWidth() {
|
|
4587
|
+
return _props.nodeStrokeWidth;
|
|
4588
|
+
},
|
|
4589
|
+
shapeRendering,
|
|
4590
|
+
get width() {
|
|
4591
|
+
return dimensions().width;
|
|
4592
|
+
},
|
|
4593
|
+
get height() {
|
|
4594
|
+
return dimensions().height;
|
|
4595
|
+
},
|
|
4596
|
+
get selected() {
|
|
4597
|
+
return node().selected;
|
|
4598
|
+
},
|
|
4599
|
+
get color() {
|
|
4600
|
+
return nodeColorFunc()?.call(null, userNode());
|
|
4601
|
+
},
|
|
4602
|
+
get strokeColor() {
|
|
4603
|
+
return nodeStrokeColorFunc().call(null, userNode());
|
|
4604
|
+
},
|
|
4605
|
+
get class() {
|
|
4606
|
+
return nodeClassFunc().call(null, userNode());
|
|
4607
|
+
},
|
|
4608
|
+
get style() {
|
|
4609
|
+
return node().style;
|
|
4610
|
+
},
|
|
4611
|
+
get onClick() {
|
|
4612
|
+
return _props.onNodeClick ? onSvgNodeClick : void 0;
|
|
4613
|
+
}
|
|
4614
|
+
});
|
|
4615
|
+
}
|
|
4303
4616
|
});
|
|
4304
4617
|
}
|
|
4305
4618
|
}), _el$2.nextSibling), effect(() => ({
|
|
@@ -4312,7 +4625,7 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4312
4625
|
s: strokeWidth(),
|
|
4313
4626
|
h: labelledBy(),
|
|
4314
4627
|
r: `M${getX() - getOffset()},${getY() - getOffset()}h${getViewboxWidth() + getOffset() * 2}v${getViewboxHeight() + getOffset() * 2}h${-getViewboxWidth() - getOffset() * 2}z
|
|
4315
|
-
M${
|
|
4628
|
+
M${viewBB().x},${viewBB().y}h${viewBB().width}v${viewBB().height}h${-viewBB().width}z`
|
|
4316
4629
|
}), ({ e, t, a, o, i, n, s, h, r }, _p$) => {
|
|
4317
4630
|
e !== _p$?.e && setAttribute(_el$, "width", e), t !== _p$?.t && setAttribute(_el$, "height", t), a !== _p$?.a && setAttribute(_el$, "viewBox", a), o !== _p$?.o && setAttribute(_el$, "aria-labelledby", o), i !== _p$?.i && setStyleProperty(_el$, "--xy-minimap-mask-background-color-props", i), n !== _p$?.n && setStyleProperty(_el$, "--xy-minimap-mask-stroke-color-props", n), s !== _p$?.s && setStyleProperty(_el$, "--xy-minimap-mask-stroke-width-props", s), h !== _p$?.h && setAttribute(_el$2, "id", h), r !== _p$?.r && setAttribute(_el$3, "d", r);
|
|
4318
4631
|
}), _el$;
|
|
@@ -4498,7 +4811,7 @@ const EdgeToolbar = (props) => {
|
|
|
4498
4811
|
var _tmpl$ = /* @__PURE__ */ template("<div>");
|
|
4499
4812
|
/** Toolbar attached to a node, rendered above the graph so it does not scale with zoom. */
|
|
4500
4813
|
const NodeToolbar = (props) => {
|
|
4501
|
-
let { store
|
|
4814
|
+
let { store, flow, commands } = useInternalSolidFlow(), _props = propDefaults(props, {
|
|
4502
4815
|
offset: 10,
|
|
4503
4816
|
position: "top",
|
|
4504
4817
|
align: "center",
|
|
@@ -4510,7 +4823,7 @@ const NodeToolbar = (props) => {
|
|
|
4510
4823
|
let node = flow.internalNodes[nodeId];
|
|
4511
4824
|
return node && res.push(node), res;
|
|
4512
4825
|
}, []), transform = () => {
|
|
4513
|
-
let nodeRect = getNodesBounds(toolbarNodes());
|
|
4826
|
+
let nodeRect = commands.getNodesBounds(toolbarNodes());
|
|
4514
4827
|
return nodeRect ? getNodeToolbarTransform(nodeRect, store.viewport, _props.position, _props.offset, _props.align) : "";
|
|
4515
4828
|
}, zIndex = () => {
|
|
4516
4829
|
let nodes = toolbarNodes();
|
|
@@ -4550,4 +4863,4 @@ const NodeToolbar = (props) => {
|
|
|
4550
4863
|
});
|
|
4551
4864
|
}, SelectionMode = SelectionMode$1, getEdgeCenter = getEdgeCenter$1, getBezierEdgeCenter = getBezierEdgeCenter$1;
|
|
4552
4865
|
//#endregion
|
|
4553
|
-
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 };
|
|
4866
|
+
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, useKeyPress, useNodeConnections, useNodeId, useNodes, useNodesData, useNodesInitialized, useSolidFlow, useUpdateNodeInternals, useViewport, useViewportInitialized };
|