@dschz/solid-flow 0.3.0-next.5 → 1.0.0-next.7
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 +41 -12
- package/dist/index/index.d.ts +151 -106
- package/dist/index/index.js +471 -254
- package/dist/index/index.jsx +470 -245
- package/package.json +7 -6
package/dist/index/index.js
CHANGED
|
@@ -65,7 +65,7 @@ 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
|
-
}, EdgeLabelRenderer = (props) => {
|
|
68
|
+
}, isEdgeSelectable = (edge, store) => edge.selectable ?? store.defaultEdgeOptions.selectable ?? store.elementsSelectable, EdgeLabelRenderer = (props) => {
|
|
69
69
|
let { store } = useInternalSolidFlow(), labelNode = () => store.domNode?.querySelector(".solid-flow__edge-labels");
|
|
70
70
|
return createComponent(Show, {
|
|
71
71
|
get when() {
|
|
@@ -282,6 +282,181 @@ const BaseEdge = (props) => {
|
|
|
282
282
|
});
|
|
283
283
|
};
|
|
284
284
|
//#endregion
|
|
285
|
+
//#region src/core/spatial/grid.ts
|
|
286
|
+
/**
|
|
287
|
+
* A uniform spatial hash over axis-aligned rects — the plain, NON-reactive
|
|
288
|
+
* building block behind the flow's spatial queries (RFC-4239 dossier:
|
|
289
|
+
* gesture-scoped snapshots and epoch-rebuilt indexes; deliberately never a
|
|
290
|
+
* live-maintained reactive structure, which would re-create the round-6
|
|
291
|
+
* central-collection anti-pattern).
|
|
292
|
+
*
|
|
293
|
+
* Every operation is O(cells touched); with cellSize on the order of the
|
|
294
|
+
* query radius or median node size, inserts and queries touch O(1) cells.
|
|
295
|
+
* No balancing, no extent-known-up-front requirement, no dependency —
|
|
296
|
+
* upstream's own bake-off (quadtree vs BVH vs rbush) is why: fixed-radius
|
|
297
|
+
* neighborhood and rect-vs-box queries are the textbook grid case.
|
|
298
|
+
*/
|
|
299
|
+
var SpatialGrid = class {
|
|
300
|
+
cellSize;
|
|
301
|
+
cells = /* @__PURE__ */ new Map();
|
|
302
|
+
rects = /* @__PURE__ */ new Map();
|
|
303
|
+
constructor(cellSize) {
|
|
304
|
+
this.cellSize = cellSize;
|
|
305
|
+
}
|
|
306
|
+
cellRange(rect) {
|
|
307
|
+
let size = this.cellSize;
|
|
308
|
+
return {
|
|
309
|
+
minX: Math.floor(rect.x / size),
|
|
310
|
+
maxX: Math.floor((rect.x + rect.width) / size),
|
|
311
|
+
minY: Math.floor(rect.y / size),
|
|
312
|
+
maxY: Math.floor((rect.y + rect.height) / size)
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
insert(id, rect) {
|
|
316
|
+
this.rects.set(id, rect);
|
|
317
|
+
let { minX, maxX, minY, maxY } = this.cellRange(rect);
|
|
318
|
+
for (let cx = minX; cx <= maxX; cx++) for (let cy = minY; cy <= maxY; cy++) {
|
|
319
|
+
let key = `${cx}:${cy}`, bucket = this.cells.get(key);
|
|
320
|
+
bucket ? bucket.push(id) : this.cells.set(key, [id]);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/** Ids of entries whose rect overlaps the query rect (touching counts). */
|
|
324
|
+
queryRect(query) {
|
|
325
|
+
let { minX, maxX, minY, maxY } = this.cellRange(query), seen = /* @__PURE__ */ new Set(), result = [];
|
|
326
|
+
for (let cx = minX; cx <= maxX; cx++) for (let cy = minY; cy <= maxY; cy++) {
|
|
327
|
+
let bucket = this.cells.get(`${cx}:${cy}`);
|
|
328
|
+
if (bucket) for (let id of bucket) {
|
|
329
|
+
if (seen.has(id)) continue;
|
|
330
|
+
seen.add(id);
|
|
331
|
+
let rect = this.rects.get(id);
|
|
332
|
+
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);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
get size() {
|
|
338
|
+
return this.rects.size;
|
|
339
|
+
}
|
|
340
|
+
}, GestureSpatialLookup = class {
|
|
341
|
+
#real;
|
|
342
|
+
#cellSize;
|
|
343
|
+
#grid = null;
|
|
344
|
+
#queryRect = null;
|
|
345
|
+
constructor(real, cellSize) {
|
|
346
|
+
this.#real = real, this.#cellSize = cellSize;
|
|
347
|
+
}
|
|
348
|
+
/** Snapshot the current geometry into the grid (gesture start). */
|
|
349
|
+
arm(rectOf) {
|
|
350
|
+
let grid = new SpatialGrid(this.#cellSize);
|
|
351
|
+
for (let [id, value] of this.#real.entries()) grid.insert(id, rectOf(value));
|
|
352
|
+
this.#grid = grid, this.#queryRect = null;
|
|
353
|
+
}
|
|
354
|
+
/** Focus iteration on the neighborhood of the pointer (per move). */
|
|
355
|
+
setQueryCenter(center, radius) {
|
|
356
|
+
this.#queryRect = {
|
|
357
|
+
x: center.x - radius,
|
|
358
|
+
y: center.y - radius,
|
|
359
|
+
width: radius * 2,
|
|
360
|
+
height: radius * 2
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
/** Focus iteration on an explicit rect (box-selection gestures). */
|
|
364
|
+
setQueryRect(rect) {
|
|
365
|
+
this.#queryRect = rect;
|
|
366
|
+
}
|
|
367
|
+
/** Back to plain pass-through (gesture end). */
|
|
368
|
+
disarm() {
|
|
369
|
+
this.#grid = null, this.#queryRect = null;
|
|
370
|
+
}
|
|
371
|
+
#candidateIds() {
|
|
372
|
+
return !this.#grid || !this.#queryRect ? null : this.#grid.queryRect(this.#queryRect);
|
|
373
|
+
}
|
|
374
|
+
get(key) {
|
|
375
|
+
return this.#real.get(key);
|
|
376
|
+
}
|
|
377
|
+
has(key) {
|
|
378
|
+
return this.#real.has(key);
|
|
379
|
+
}
|
|
380
|
+
get size() {
|
|
381
|
+
return this.#real.size;
|
|
382
|
+
}
|
|
383
|
+
*keys() {
|
|
384
|
+
let candidates = this.#candidateIds();
|
|
385
|
+
if (!candidates) {
|
|
386
|
+
yield* this.#real.keys();
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
for (let id of candidates) this.#real.has(id) && (yield id);
|
|
390
|
+
}
|
|
391
|
+
*values() {
|
|
392
|
+
let candidates = this.#candidateIds();
|
|
393
|
+
if (!candidates) {
|
|
394
|
+
yield* this.#real.values();
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
for (let id of candidates) {
|
|
398
|
+
let value = this.#real.get(id);
|
|
399
|
+
value !== void 0 && (yield value);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
*entries() {
|
|
403
|
+
let candidates = this.#candidateIds();
|
|
404
|
+
if (!candidates) {
|
|
405
|
+
yield* this.#real.entries();
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
for (let id of candidates) {
|
|
409
|
+
let value = this.#real.get(id);
|
|
410
|
+
value !== void 0 && (yield [id, value]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
[Symbol.iterator]() {
|
|
414
|
+
return this.entries();
|
|
415
|
+
}
|
|
416
|
+
forEach(callback, thisArg) {
|
|
417
|
+
for (let [key, value] of this.entries()) callback.call(thisArg, value, key, this);
|
|
418
|
+
}
|
|
419
|
+
[Symbol.toStringTag] = "GestureSpatialLookup";
|
|
420
|
+
set() {
|
|
421
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
422
|
+
}
|
|
423
|
+
getOrInsert() {
|
|
424
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
425
|
+
}
|
|
426
|
+
getOrInsertComputed() {
|
|
427
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
428
|
+
}
|
|
429
|
+
delete() {
|
|
430
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
431
|
+
}
|
|
432
|
+
clear() {
|
|
433
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/components/handle/connectionGestureLookup.ts
|
|
438
|
+
/**
|
|
439
|
+
* Upstream `getClosestHandle` prefilters nodes within
|
|
440
|
+
* `connectionRadius + ADDITIONAL_DISTANCE` of the pointer; ADDITIONAL_DISTANCE
|
|
441
|
+
* is hardcoded to 250 in @xyflow/system (xyhandle/utils.ts). Tracked here with
|
|
442
|
+
* a safety pad: a superset of candidates is always correct (their exact
|
|
443
|
+
* distance filter runs after), so the pad only costs a few extra candidates.
|
|
444
|
+
*/
|
|
445
|
+
const armConnectionGestureLookup = (options) => {
|
|
446
|
+
let { event, real, domNode, getTransform, connectionRadius } = options, containerBounds = domNode?.getBoundingClientRect();
|
|
447
|
+
if (!containerBounds) return real;
|
|
448
|
+
let radius = connectionRadius + 250 + 50, lookup = new GestureSpatialLookup(real, radius);
|
|
449
|
+
lookup.arm((node) => nodeToRect(node));
|
|
450
|
+
let update = (moveEvent) => {
|
|
451
|
+
lookup.setQueryCenter(pointToRendererPoint(getEventPosition(moveEvent, containerBounds), getTransform(), !1, [1, 1]), radius);
|
|
452
|
+
};
|
|
453
|
+
update(event);
|
|
454
|
+
let doc = getHostForElement(event.target), dispose = () => {
|
|
455
|
+
doc.removeEventListener("mousemove", update, !0), doc.removeEventListener("touchmove", update, !0), doc.removeEventListener("mouseup", dispose, !0), doc.removeEventListener("touchend", dispose, !0), lookup.disarm();
|
|
456
|
+
};
|
|
457
|
+
return doc.addEventListener("mousemove", update, !0), doc.addEventListener("touchmove", update, !0), doc.addEventListener("mouseup", dispose, !0), doc.addEventListener("touchend", dispose, !0), lookup;
|
|
458
|
+
};
|
|
459
|
+
//#endregion
|
|
285
460
|
//#region src/components/edge/EdgeReconnectAnchor.tsx
|
|
286
461
|
var _tmpl$$32 = /* @__PURE__ */ template("<div style=background:transparent;border:none;cursor:move>");
|
|
287
462
|
/** Grab area that lets an edge end be dragged off its handle and reconnected. */
|
|
@@ -305,7 +480,13 @@ const EdgeReconnectAnchor = (props) => {
|
|
|
305
480
|
nodeId: edge().target,
|
|
306
481
|
handleId: edge().targetHandle ?? null,
|
|
307
482
|
type: "target"
|
|
308
|
-
}
|
|
483
|
+
}, gestureLookup = armConnectionGestureLookup({
|
|
484
|
+
event,
|
|
485
|
+
real: nodeLookup,
|
|
486
|
+
domNode: store.domNode,
|
|
487
|
+
getTransform: () => store.transform,
|
|
488
|
+
connectionRadius: store.connectionRadius
|
|
489
|
+
});
|
|
309
490
|
XYHandle.onPointerDown(event, {
|
|
310
491
|
lib: store.lib,
|
|
311
492
|
flowId: store.id,
|
|
@@ -315,7 +496,7 @@ const EdgeReconnectAnchor = (props) => {
|
|
|
315
496
|
autoPanOnConnect: store.autoPanOnConnect,
|
|
316
497
|
connectionMode: store.connectionMode,
|
|
317
498
|
connectionRadius: store.connectionRadius,
|
|
318
|
-
nodeLookup,
|
|
499
|
+
nodeLookup: gestureLookup,
|
|
319
500
|
isTarget: opposite.type === "target",
|
|
320
501
|
edgeUpdaterType: opposite.type,
|
|
321
502
|
cancelConnection: actions.cancelConnection,
|
|
@@ -416,9 +597,73 @@ const A11yDescriptions = () => {
|
|
|
416
597
|
}
|
|
417
598
|
})
|
|
418
599
|
];
|
|
419
|
-
},
|
|
420
|
-
let
|
|
421
|
-
|
|
600
|
+
}, createSelectionCommands = ({ store, setNodesStore, setEdgesStore, setSelectionRect, setSelectionRectMode, nodeLookup, edgeLookup, updateNodePositions }) => {
|
|
601
|
+
let unselectNodesAndEdges = ({ nodes: _nodes, edges } = {}) => {
|
|
602
|
+
let nodesToUnselect = new Set((_nodes || store.nodes).map(({ id }) => id));
|
|
603
|
+
nodesToUnselect.size && setNodesStore((nodes) => {
|
|
604
|
+
for (let node of nodes) nodesToUnselect.has(node.id) && (node.selected = !1);
|
|
605
|
+
});
|
|
606
|
+
let edgesToUnselect = new Set((edges ?? store.edges).map(({ id }) => id));
|
|
607
|
+
edgesToUnselect.size && setEdgesStore((edges) => {
|
|
608
|
+
for (let edge of edges) edgesToUnselect.has(edge.id) && (edge.selected = !1);
|
|
609
|
+
}), flush();
|
|
610
|
+
}, addSelectedNodes = (ids) => {
|
|
611
|
+
let isMultiSelection = store.multiselectionKeyPressed, idSet = new Set(ids);
|
|
612
|
+
setNodesStore((nodes) => {
|
|
613
|
+
for (let node of nodes) {
|
|
614
|
+
let nodeWillBeSelected = idSet.has(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
615
|
+
node.selected !== selected && (node.selected = selected);
|
|
616
|
+
}
|
|
617
|
+
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
618
|
+
}, addSelectedEdges = (ids) => {
|
|
619
|
+
let isMultiSelection = store.multiselectionKeyPressed, idSet = new Set(ids);
|
|
620
|
+
setEdgesStore((edges) => {
|
|
621
|
+
for (let edge of edges) {
|
|
622
|
+
let edgeWillBeSelected = idSet.has(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
623
|
+
edge.selected !== selected && (edge.selected = selected);
|
|
624
|
+
}
|
|
625
|
+
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
626
|
+
};
|
|
627
|
+
return {
|
|
628
|
+
unselectNodesAndEdges,
|
|
629
|
+
addSelectedNodes,
|
|
630
|
+
addSelectedEdges,
|
|
631
|
+
handleNodeSelection: (id, unselect, nodeRef) => {
|
|
632
|
+
let node = store.nodes.find((n) => n.id === id);
|
|
633
|
+
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
634
|
+
nodes: [node],
|
|
635
|
+
edges: []
|
|
636
|
+
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
637
|
+
},
|
|
638
|
+
handleEdgeSelection: (id) => {
|
|
639
|
+
let edge = edgeLookup[id];
|
|
640
|
+
edge && isEdgeSelectable(edge, store) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
641
|
+
nodes: [],
|
|
642
|
+
edges: [edge]
|
|
643
|
+
}) : addSelectedEdges([id]));
|
|
644
|
+
},
|
|
645
|
+
moveSelectedNodes: (direction, factor) => {
|
|
646
|
+
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;
|
|
647
|
+
for (let node of nodeLookup.values()) {
|
|
648
|
+
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
649
|
+
let nextPosition = {
|
|
650
|
+
x: node.internals.positionAbsolute.x + xDiff,
|
|
651
|
+
y: node.internals.positionAbsolute.y + yDiff
|
|
652
|
+
};
|
|
653
|
+
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
654
|
+
let { position } = calculateNodePosition({
|
|
655
|
+
nodeId: node.id,
|
|
656
|
+
nextPosition,
|
|
657
|
+
nodeLookup,
|
|
658
|
+
nodeExtent: store.nodeExtent,
|
|
659
|
+
nodeOrigin: store.nodeOrigin,
|
|
660
|
+
onError: store.onError
|
|
661
|
+
});
|
|
662
|
+
nodeUpdates.set(node.id, { position });
|
|
663
|
+
}
|
|
664
|
+
updateNodePositions(nodeUpdates);
|
|
665
|
+
}
|
|
666
|
+
};
|
|
422
667
|
}, 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
668
|
let { width, height } = source;
|
|
424
669
|
if (!width || !height) return null;
|
|
@@ -451,8 +696,6 @@ const A11yDescriptions = () => {
|
|
|
451
696
|
}, cullingViewport);
|
|
452
697
|
}, getDefaultFlowStateProps = () => ({
|
|
453
698
|
id: "1",
|
|
454
|
-
nodes: [],
|
|
455
|
-
edges: [],
|
|
456
699
|
nodeOrigin: [0, 0],
|
|
457
700
|
nodeExtent: infiniteExtent,
|
|
458
701
|
defaultEdgeOptions: {},
|
|
@@ -551,14 +794,48 @@ var RecordMapFacade = class {
|
|
|
551
794
|
}
|
|
552
795
|
};
|
|
553
796
|
//#endregion
|
|
554
|
-
//#region src/core/
|
|
797
|
+
//#region src/core/measurementIngest.ts
|
|
555
798
|
/**
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
799
|
+
* The measurement ingest lifecycle (WP3): everything that flows FROM the DOM
|
|
800
|
+
* measuring pass INTO the data graph, plus the garbage collection that keeps
|
|
801
|
+
* the measurements root aligned with graph membership. The DOM side (resize
|
|
802
|
+
* observers, the idle-scheduled measuring pass) lives in createSolidFlow;
|
|
803
|
+
* headless usage never calls these.
|
|
560
804
|
*/
|
|
561
|
-
const
|
|
805
|
+
const createMeasurementIngest = ({ setMeasurementsStore, setNodesStore, nodes }) => (createEffect(() => new Set(nodes().map((n) => n.id)), (currentIds) => {
|
|
806
|
+
setMeasurementsStore((draft) => {
|
|
807
|
+
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
808
|
+
});
|
|
809
|
+
}), {
|
|
810
|
+
applyMeasurementWrites: (writes) => {
|
|
811
|
+
setMeasurementsStore((draft) => {
|
|
812
|
+
for (let write of writes) if (write.hidden) {
|
|
813
|
+
let entry = draft[write.id];
|
|
814
|
+
entry && (entry.handleBounds = void 0);
|
|
815
|
+
} else draft[write.id] = {
|
|
816
|
+
measured: write.measured,
|
|
817
|
+
handleBounds: write.handleBounds
|
|
818
|
+
};
|
|
819
|
+
});
|
|
820
|
+
},
|
|
821
|
+
applyNodeChanges: (changes) => {
|
|
822
|
+
changes.length !== 0 && setNodesStore((nodes) => {
|
|
823
|
+
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
824
|
+
for (let change of changes) {
|
|
825
|
+
let node = nodeById.get(change.id);
|
|
826
|
+
if (node) switch (change.type) {
|
|
827
|
+
case "dimensions":
|
|
828
|
+
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
829
|
+
...node.measured,
|
|
830
|
+
...change.dimensions
|
|
831
|
+
};
|
|
832
|
+
break;
|
|
833
|
+
case "position": node.position = change.position ?? node.position;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}), connectionKey = (nodeId, type, handleId) => `${nodeId}${type ? handleId ? `-${type}-${handleId}` : `-${type}` : ""}`, pairKey = (aNode, aHandle, bNode, bHandle) => `${aNode}-${aHandle}--${bNode}-${bHandle}`, createConnections = (source) => createProjection(() => {
|
|
562
839
|
let out = {}, add = (key, entry, connection) => {
|
|
563
840
|
(out[key] ??= {})[entry] = connection;
|
|
564
841
|
};
|
|
@@ -623,10 +900,6 @@ const EMPTY_AUTO_INDEX = /* @__PURE__ */ new Map(), createInternalNodes = (sourc
|
|
|
623
900
|
}, row.internals.z = z;
|
|
624
901
|
} else source.nodes.length;
|
|
625
902
|
}
|
|
626
|
-
if (userNode.parentId) {
|
|
627
|
-
let parent = entryById.get(userNode.parentId);
|
|
628
|
-
parent?.store.row.internals.positionAbsolute.x, parent?.store.row.internals.z;
|
|
629
|
-
}
|
|
630
903
|
return { row };
|
|
631
904
|
}, {}, { key: "id" }), entry = {
|
|
632
905
|
store,
|
|
@@ -695,8 +968,8 @@ const createLayoutedEdges = (source) => {
|
|
|
695
968
|
let rowStores = mapArray(() => source.edges, (edgeAccessor) => ({
|
|
696
969
|
id: edgeAccessor().id,
|
|
697
970
|
store: createProjection(() => {
|
|
698
|
-
let edge = edgeAccessor()
|
|
699
|
-
return
|
|
971
|
+
let edge = edgeAccessor();
|
|
972
|
+
return { row: buildRow(source, edge) };
|
|
700
973
|
}, { row: null }, { key: "id" })
|
|
701
974
|
}), { keyed: (edge) => edge.id }), assigned = /* @__PURE__ */ new Map();
|
|
702
975
|
return createProjection((draft) => {
|
|
@@ -712,7 +985,7 @@ const createLayoutedEdges = (source) => {
|
|
|
712
985
|
});
|
|
713
986
|
}, buildRow = (source, edge) => {
|
|
714
987
|
let sourceNode = source.nodeLookup.get(edge.source), targetNode = source.nodeLookup.get(edge.target);
|
|
715
|
-
if (!sourceNode || !targetNode) return
|
|
988
|
+
if (!sourceNode || !targetNode) return null;
|
|
716
989
|
let edgePosition = getEdgePosition({
|
|
717
990
|
id: edge.id,
|
|
718
991
|
sourceNode,
|
|
@@ -742,7 +1015,33 @@ const createLayoutedEdges = (source) => {
|
|
|
742
1015
|
let out = {};
|
|
743
1016
|
for (let node of source.nodes) node.parentId && (out[node.parentId] = !0);
|
|
744
1017
|
return out;
|
|
745
|
-
}, {}, { key: "id" }),
|
|
1018
|
+
}, {}, { key: "id" }), createSeededGraphStores = (props, config) => {
|
|
1019
|
+
props.nodes !== void 0 && props.defaultNodes, props.edges !== void 0 && props.defaultEdges;
|
|
1020
|
+
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;
|
|
1021
|
+
return createEffect(() => {
|
|
1022
|
+
let next = config().nodes;
|
|
1023
|
+
if (next) for (let node of next);
|
|
1024
|
+
return { next };
|
|
1025
|
+
}, ({ next }) => {
|
|
1026
|
+
next && (nodeSeedAdopted = !0, setNodesStore(() => next));
|
|
1027
|
+
}, { defer: !0 }), createEffect(() => {
|
|
1028
|
+
let next = config().edges;
|
|
1029
|
+
if (next) for (let edge of next);
|
|
1030
|
+
return { next };
|
|
1031
|
+
}, ({ next }) => {
|
|
1032
|
+
next && (edgeSeedAdopted = !0, setEdgesStore(() => next));
|
|
1033
|
+
}, { defer: !0 }), createEffect(() => ({
|
|
1034
|
+
nodes: config().defaultNodes,
|
|
1035
|
+
edges: config().defaultEdges
|
|
1036
|
+
}), ({ nodes: defaultNodes, edges: defaultEdges }) => {
|
|
1037
|
+
defaultNodes && !nodeSeedAdopted && config().nodes === void 0 && (nodeSeedAdopted = !0, setNodesStore(() => [...defaultNodes])), defaultEdges && !edgeSeedAdopted && config().edges === void 0 && (edgeSeedAdopted = !0, setEdgesStore(() => [...defaultEdges]));
|
|
1038
|
+
}, { defer: !0 }), {
|
|
1039
|
+
nodesStore,
|
|
1040
|
+
setNodesStore,
|
|
1041
|
+
edgesStore,
|
|
1042
|
+
setEdgesStore
|
|
1043
|
+
};
|
|
1044
|
+
}, getInitialViewport = (fitView, initialViewport, width, height, nodeLookup) => {
|
|
746
1045
|
if (fitView && !initialViewport && width && height) {
|
|
747
1046
|
let bounds = getInternalNodesBounds(nodeLookup, { filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)) });
|
|
748
1047
|
return getViewportForBounds$1(bounds, width, height, .5, 2, .1);
|
|
@@ -753,7 +1052,7 @@ const createLayoutedEdges = (source) => {
|
|
|
753
1052
|
zoom: 1
|
|
754
1053
|
};
|
|
755
1054
|
}, createFlowState = (props, injections = {}) => {
|
|
756
|
-
let _props = merge(getDefaultFlowStateProps(), props), initialNodeTypes = injections.initialNodeTypes ?? {}, initialEdgeTypes = injections.initialEdgeTypes ?? {}, prefersDark = injections.prefersDark ?? (() => _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props),
|
|
1055
|
+
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
1056
|
get nodes() {
|
|
758
1057
|
return nodesStore;
|
|
759
1058
|
},
|
|
@@ -773,19 +1072,7 @@ const createLayoutedEdges = (source) => {
|
|
|
773
1072
|
return config().zIndexMode;
|
|
774
1073
|
}
|
|
775
1074
|
}), 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
|
-
for (let node of next);
|
|
779
|
-
return { next };
|
|
780
|
-
}, ({ next }) => {
|
|
781
|
-
setNodesStore(() => next);
|
|
782
|
-
}, { defer: !0 }), createEffect(() => {
|
|
783
|
-
let next = config().edges;
|
|
784
|
-
for (let edge of next);
|
|
785
|
-
return { next };
|
|
786
|
-
}, ({ next }) => {
|
|
787
|
-
setEdgesStore(() => next);
|
|
788
|
-
}, { defer: !0 }), createEffect(() => config().viewport, (next) => {
|
|
1075
|
+
createEffect(() => config().viewport, (next) => {
|
|
789
1076
|
next && setViewportStore(() => next);
|
|
790
1077
|
}, { defer: !0 });
|
|
791
1078
|
let transform = createMemo(() => [
|
|
@@ -797,25 +1084,29 @@ const createLayoutedEdges = (source) => {
|
|
|
797
1084
|
if (nodes.length === 0) return !1;
|
|
798
1085
|
for (let node of nodes) if (!node.hidden && (node.measured?.width === void 0 || node.measured?.height === void 0)) return !1;
|
|
799
1086
|
return !0;
|
|
800
|
-
}),
|
|
1087
|
+
}), resolvedColorMode = createMemo(() => {
|
|
1088
|
+
let mode = config().colorMode;
|
|
1089
|
+
return mode === "system" ? prefersDark() ? "dark" : "light" : mode;
|
|
1090
|
+
}), projectedConnection = createMemo(() => {
|
|
1091
|
+
let state = connection();
|
|
1092
|
+
return state.inProgress ? {
|
|
1093
|
+
...state,
|
|
1094
|
+
to: pointToRendererPoint(state.to, transform())
|
|
1095
|
+
} : state;
|
|
1096
|
+
}), 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) => {
|
|
1097
|
+
let state = connection(), toHandle = state.inProgress ? state.toHandle : null, key = toHandle ? connectionKey(toHandle.nodeId, toHandle.type, toHandle.id ?? null) : null;
|
|
1098
|
+
for (let existing of Object.keys(draft)) existing !== key && delete draft[existing];
|
|
1099
|
+
key && (draft[key] = state.isValid ? "valid" : "invalid");
|
|
1100
|
+
}, {}, { key: null }), mergedNodeTypes = createMemo(() => ({
|
|
1101
|
+
...initialNodeTypes,
|
|
1102
|
+
...config().nodeTypes
|
|
1103
|
+
})), mergedEdgeTypes = createMemo(() => ({
|
|
1104
|
+
...initialEdgeTypes,
|
|
1105
|
+
...config().edgeTypes
|
|
1106
|
+
})), selectedNodesView = createMemo(() => nodesStore.filter((node) => node.selected)), selectedEdgesView = createMemo(() => edgesStore.filter((edge) => edge.selected)), store = merge({
|
|
801
1107
|
width: 0,
|
|
802
1108
|
height: 0
|
|
803
1109
|
}, config, {
|
|
804
|
-
get _colorMode() {
|
|
805
|
-
return config().colorMode;
|
|
806
|
-
},
|
|
807
|
-
get _colorModeSSR() {
|
|
808
|
-
return config().colorModeSSR;
|
|
809
|
-
},
|
|
810
|
-
get _connection() {
|
|
811
|
-
return connection();
|
|
812
|
-
},
|
|
813
|
-
get _nodeTypes() {
|
|
814
|
-
return config().nodeTypes;
|
|
815
|
-
},
|
|
816
|
-
get _edgeTypes() {
|
|
817
|
-
return config().edgeTypes;
|
|
818
|
-
},
|
|
819
1110
|
get ariaLabelConfig() {
|
|
820
1111
|
return ariaLabelConfig();
|
|
821
1112
|
},
|
|
@@ -826,14 +1117,16 @@ const createLayoutedEdges = (source) => {
|
|
|
826
1117
|
return clickConnectStartHandle();
|
|
827
1118
|
},
|
|
828
1119
|
get colorMode() {
|
|
829
|
-
return
|
|
1120
|
+
return resolvedColorMode();
|
|
830
1121
|
},
|
|
831
1122
|
get connection() {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1123
|
+
return projectedConnection();
|
|
1124
|
+
},
|
|
1125
|
+
get connectionFromHandle() {
|
|
1126
|
+
return connectionFromHandle();
|
|
1127
|
+
},
|
|
1128
|
+
get connectionTargetByHandle() {
|
|
1129
|
+
return connectionTargetByHandle;
|
|
837
1130
|
},
|
|
838
1131
|
get domNode() {
|
|
839
1132
|
return domNode();
|
|
@@ -842,10 +1135,7 @@ const createLayoutedEdges = (source) => {
|
|
|
842
1135
|
return dragging();
|
|
843
1136
|
},
|
|
844
1137
|
get edgeTypes() {
|
|
845
|
-
return
|
|
846
|
-
...initialEdgeTypes,
|
|
847
|
-
...this._edgeTypes
|
|
848
|
-
};
|
|
1138
|
+
return mergedEdgeTypes();
|
|
849
1139
|
},
|
|
850
1140
|
get elementsSelectable() {
|
|
851
1141
|
return elementsSelectable();
|
|
@@ -878,19 +1168,16 @@ const createLayoutedEdges = (source) => {
|
|
|
878
1168
|
return nodesDraggable();
|
|
879
1169
|
},
|
|
880
1170
|
get nodeTypes() {
|
|
881
|
-
return
|
|
882
|
-
...initialNodeTypes,
|
|
883
|
-
...this._nodeTypes
|
|
884
|
-
};
|
|
1171
|
+
return mergedNodeTypes();
|
|
885
1172
|
},
|
|
886
1173
|
get panZoom() {
|
|
887
1174
|
return panZoom();
|
|
888
1175
|
},
|
|
889
1176
|
get selectedNodes() {
|
|
890
|
-
return
|
|
1177
|
+
return selectedNodesView();
|
|
891
1178
|
},
|
|
892
1179
|
get selectedEdges() {
|
|
893
|
-
return
|
|
1180
|
+
return selectedEdgesView();
|
|
894
1181
|
},
|
|
895
1182
|
get selectionRect() {
|
|
896
1183
|
return selectionRect();
|
|
@@ -1005,33 +1292,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1005
1292
|
setNodesStore((nodes) => {
|
|
1006
1293
|
for (let node of nodes) nodeDragItems.has(node.id) && (node.dragging = dragging, node.position = nodeDragItems.get(node.id).position);
|
|
1007
1294
|
});
|
|
1008
|
-
}, applyMeasurementWrites = (
|
|
1009
|
-
setMeasurementsStore
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
} else draft[write.id] = {
|
|
1014
|
-
measured: write.measured,
|
|
1015
|
-
handleBounds: write.handleBounds
|
|
1016
|
-
};
|
|
1017
|
-
});
|
|
1018
|
-
}, applyNodeChanges = (changes) => {
|
|
1019
|
-
changes.length !== 0 && setNodesStore((nodes) => {
|
|
1020
|
-
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
1021
|
-
for (let change of changes) {
|
|
1022
|
-
let node = nodeById.get(change.id);
|
|
1023
|
-
if (node) switch (change.type) {
|
|
1024
|
-
case "dimensions":
|
|
1025
|
-
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
1026
|
-
...node.measured,
|
|
1027
|
-
...change.dimensions
|
|
1028
|
-
};
|
|
1029
|
-
break;
|
|
1030
|
-
case "position": node.position = change.position ?? node.position;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
});
|
|
1034
|
-
}, markInitialNodesMeasured = () => {
|
|
1295
|
+
}, { applyMeasurementWrites, applyNodeChanges } = createMeasurementIngest({
|
|
1296
|
+
setMeasurementsStore,
|
|
1297
|
+
setNodesStore,
|
|
1298
|
+
nodes: () => nodesStore
|
|
1299
|
+
}), markInitialNodesMeasured = () => {
|
|
1035
1300
|
initialNodesMeasured = !0, tryInitialFitView();
|
|
1036
1301
|
}, requestMeasure = () => {}, setMeasureRequester = (fn) => {
|
|
1037
1302
|
requestMeasure = fn;
|
|
@@ -1046,66 +1311,16 @@ const createLayoutedEdges = (source) => {
|
|
|
1046
1311
|
ease: options?.ease,
|
|
1047
1312
|
interpolate: options?.interpolate
|
|
1048
1313
|
}), Promise.resolve(!0)) : Promise.resolve(!1);
|
|
1049
|
-
},
|
|
1050
|
-
store
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
}), flush();
|
|
1060
|
-
}, addSelectedNodes = (ids) => {
|
|
1061
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
1062
|
-
setNodesStore((nodes) => {
|
|
1063
|
-
for (let node of nodes) {
|
|
1064
|
-
let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
1065
|
-
node.selected !== selected && (node.selected = selected);
|
|
1066
|
-
}
|
|
1067
|
-
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
1068
|
-
}, addSelectedEdges = (ids) => {
|
|
1069
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
1070
|
-
setEdgesStore((edges) => {
|
|
1071
|
-
for (let edge of edges) {
|
|
1072
|
-
let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
1073
|
-
edge.selected !== selected && (edge.selected = selected);
|
|
1074
|
-
}
|
|
1075
|
-
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
1076
|
-
}, handleNodeSelection = (id, unselect, nodeRef) => {
|
|
1077
|
-
let node = store.nodes.find((n) => n.id === id);
|
|
1078
|
-
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
1079
|
-
nodes: [node],
|
|
1080
|
-
edges: []
|
|
1081
|
-
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
1082
|
-
}, handleEdgeSelection = (id) => {
|
|
1083
|
-
let edge = edgeLookup[id];
|
|
1084
|
-
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
1085
|
-
nodes: [],
|
|
1086
|
-
edges: [edge]
|
|
1087
|
-
}) : addSelectedEdges([id]));
|
|
1088
|
-
}, moveSelectedNodes = (direction, factor) => {
|
|
1089
|
-
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;
|
|
1090
|
-
for (let node of nodeLookup.values()) {
|
|
1091
|
-
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
1092
|
-
let nextPosition = {
|
|
1093
|
-
x: node.internals.positionAbsolute.x + xDiff,
|
|
1094
|
-
y: node.internals.positionAbsolute.y + yDiff
|
|
1095
|
-
};
|
|
1096
|
-
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
1097
|
-
let { position } = calculateNodePosition({
|
|
1098
|
-
nodeId: node.id,
|
|
1099
|
-
nextPosition,
|
|
1100
|
-
nodeLookup,
|
|
1101
|
-
nodeExtent: store.nodeExtent,
|
|
1102
|
-
nodeOrigin: store.nodeOrigin,
|
|
1103
|
-
onError: store.onError
|
|
1104
|
-
});
|
|
1105
|
-
nodeUpdates.set(node.id, { position });
|
|
1106
|
-
}
|
|
1107
|
-
updateNodePositions(nodeUpdates);
|
|
1108
|
-
}, panBy$1 = (delta) => panBy({
|
|
1314
|
+
}, stableSetViewport = (viewport) => setViewportStore(() => viewport), { unselectNodesAndEdges, addSelectedNodes, addSelectedEdges, handleNodeSelection, handleEdgeSelection, moveSelectedNodes } = createSelectionCommands({
|
|
1315
|
+
store,
|
|
1316
|
+
setNodesStore,
|
|
1317
|
+
setEdgesStore,
|
|
1318
|
+
setSelectionRect,
|
|
1319
|
+
setSelectionRectMode,
|
|
1320
|
+
nodeLookup,
|
|
1321
|
+
edgeLookup,
|
|
1322
|
+
updateNodePositions
|
|
1323
|
+
}), panBy$1 = (delta) => panBy({
|
|
1109
1324
|
delta,
|
|
1110
1325
|
panZoom: store.panZoom,
|
|
1111
1326
|
transform: store.transform,
|
|
@@ -1182,8 +1397,27 @@ const createLayoutedEdges = (source) => {
|
|
|
1182
1397
|
get snapGrid() {
|
|
1183
1398
|
return store.snapGrid;
|
|
1184
1399
|
}
|
|
1185
|
-
},
|
|
1186
|
-
|
|
1400
|
+
}, intersectionGrid = null, intersectionRows = null, queryIntersectionCandidates = (rect) => untrack(() => {
|
|
1401
|
+
if (!intersectionGrid) {
|
|
1402
|
+
let grid = new SpatialGrid(300), rows = /* @__PURE__ */ new Map();
|
|
1403
|
+
for (let node of store.nodes) {
|
|
1404
|
+
let internalNode = nodeLookup.get(node.id);
|
|
1405
|
+
internalNode && (grid.insert(node.id, nodeToRect(internalNode)), rows.set(node.id, node));
|
|
1406
|
+
}
|
|
1407
|
+
intersectionGrid = grid, intersectionRows = rows, queueMicrotask(() => {
|
|
1408
|
+
intersectionGrid = null, intersectionRows = null;
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
let rows = intersectionRows, result = [];
|
|
1412
|
+
for (let id of intersectionGrid.queryRect(rect)) {
|
|
1413
|
+
let row = rows.get(id);
|
|
1414
|
+
row && result.push(row);
|
|
1415
|
+
}
|
|
1416
|
+
return result;
|
|
1417
|
+
}), getNodeRect = (node) => {
|
|
1418
|
+
let nodeToUse = isNode(node) ? node : nodeLookup.get(node.id);
|
|
1419
|
+
if (!nodeToUse) return null;
|
|
1420
|
+
let position = nodeToUse.parentId ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, store.nodeOrigin) : nodeToUse.position, nodeWithPosition = {
|
|
1187
1421
|
...nodeToUse,
|
|
1188
1422
|
position,
|
|
1189
1423
|
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
@@ -1237,7 +1471,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1237
1471
|
x,
|
|
1238
1472
|
y,
|
|
1239
1473
|
zoom
|
|
1240
|
-
], _snapGrid
|
|
1474
|
+
], !!_snapGrid, _snapGrid || [1, 1]);
|
|
1241
1475
|
},
|
|
1242
1476
|
flowToScreenPosition: (position) => {
|
|
1243
1477
|
if (!store.domNode) return position;
|
|
@@ -1301,14 +1535,18 @@ const createLayoutedEdges = (source) => {
|
|
|
1301
1535
|
let remainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
|
|
1302
1536
|
store.onNodesDelete?.(matchingNodes), setNodesStore(() => remainingNodes);
|
|
1303
1537
|
}
|
|
1304
|
-
|
|
1538
|
+
let deletedNodes = matchingNodes ?? [], deletedEdges = matchingEdges ?? [];
|
|
1539
|
+
return (deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
1540
|
+
nodes: deletedNodes,
|
|
1541
|
+
edges: deletedEdges
|
|
1542
|
+
}), {
|
|
1305
1543
|
deletedNodes: matchingNodes,
|
|
1306
1544
|
deletedEdges: matchingEdges
|
|
1307
1545
|
};
|
|
1308
1546
|
},
|
|
1309
1547
|
getIntersectingNodes: (nodeOrRect, partially = !0, nodesToIntersect) => {
|
|
1310
1548
|
let isRect = isRectObject(nodeOrRect), nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
1311
|
-
return nodeRect ? (nodesToIntersect
|
|
1549
|
+
return nodeRect ? (nodesToIntersect ?? queryIntersectionCandidates(nodeRect)).filter((n) => {
|
|
1312
1550
|
let internalNode = nodeLookup.get(n.id);
|
|
1313
1551
|
if (!internalNode || !isRect && n.id === nodeOrRect.id) return !1;
|
|
1314
1552
|
let currNodeRect = nodeToRect(internalNode), overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
@@ -1364,10 +1602,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1364
1602
|
extent: store.translateExtent
|
|
1365
1603
|
}), ({ panZoom, extent }) => {
|
|
1366
1604
|
panZoom?.setTranslateExtent(extent);
|
|
1367
|
-
}), createEffect(() => new Set(store.nodes.map((n) => n.id)), (currentIds) => {
|
|
1368
|
-
setMeasurementsStore((draft) => {
|
|
1369
|
-
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
1370
|
-
});
|
|
1371
1605
|
}), {
|
|
1372
1606
|
store,
|
|
1373
1607
|
flow,
|
|
@@ -1385,8 +1619,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1385
1619
|
applyNodeChanges,
|
|
1386
1620
|
markInitialNodesMeasured,
|
|
1387
1621
|
setMeasureRequester,
|
|
1388
|
-
resetStoreValues,
|
|
1389
|
-
setAriaLabelConfig,
|
|
1390
1622
|
setAriaLiveMessage,
|
|
1391
1623
|
setClickConnectStartHandle,
|
|
1392
1624
|
setConfig,
|
|
@@ -1394,15 +1626,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1394
1626
|
setDeleteKeyPressed,
|
|
1395
1627
|
setDomNode,
|
|
1396
1628
|
setDragging,
|
|
1397
|
-
|
|
1398
|
-
return setEdgesStore;
|
|
1399
|
-
},
|
|
1629
|
+
setEdges: setEdgesStore,
|
|
1400
1630
|
setElementsSelectable,
|
|
1401
1631
|
setHeight,
|
|
1402
1632
|
setMultiselectionKeyPressed,
|
|
1403
|
-
|
|
1404
|
-
return setNodesStore;
|
|
1405
|
-
},
|
|
1633
|
+
setNodes: setNodesStore,
|
|
1406
1634
|
setNodesConnectable,
|
|
1407
1635
|
setNodesDraggable,
|
|
1408
1636
|
setPanActivationKeyPressed,
|
|
@@ -1410,9 +1638,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1410
1638
|
setSelectionKeyPressed,
|
|
1411
1639
|
setSelectionRect,
|
|
1412
1640
|
setSelectionRectMode,
|
|
1413
|
-
|
|
1414
|
-
return (viewport) => setViewportStore(() => viewport);
|
|
1415
|
-
},
|
|
1641
|
+
setViewport: stableSetViewport,
|
|
1416
1642
|
setWidth,
|
|
1417
1643
|
setZoomActivationKeyPressed,
|
|
1418
1644
|
addEdge,
|
|
@@ -1421,7 +1647,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1421
1647
|
zoomOut,
|
|
1422
1648
|
fitView,
|
|
1423
1649
|
setCenter,
|
|
1424
|
-
setPaneClickDistance,
|
|
1425
1650
|
unselectNodesAndEdges,
|
|
1426
1651
|
addSelectedNodes,
|
|
1427
1652
|
addSelectedEdges,
|
|
@@ -1433,8 +1658,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1433
1658
|
reset
|
|
1434
1659
|
}
|
|
1435
1660
|
};
|
|
1661
|
+
}, createEdgeStore = (edges) => {
|
|
1662
|
+
let [store, setStore] = typeof edges == "function" ? createStore(edges, []) : createStore(edges);
|
|
1663
|
+
return [store, setStore];
|
|
1436
1664
|
}, createNodeStore = (nodes) => {
|
|
1437
|
-
let [store, setStore] = createStore(nodes);
|
|
1665
|
+
let [store, setStore] = typeof nodes == "function" ? createStore(nodes, []) : createStore(nodes);
|
|
1438
1666
|
return [store, setStore];
|
|
1439
1667
|
};
|
|
1440
1668
|
//#endregion
|
|
@@ -1442,21 +1670,21 @@ const createLayoutedEdges = (source) => {
|
|
|
1442
1670
|
var _tmpl$$30 = /* @__PURE__ */ template("<svg class=solid-flow__edge-wrapper><g>");
|
|
1443
1671
|
/** Internal per-edge wrapper: interaction, a11y, viewport culling, and the dynamic edge component. */
|
|
1444
1672
|
const EdgeWrapper = (props) => {
|
|
1445
|
-
let edgeRef, { store, actions } = useInternalSolidFlow(), edgeId = () => props.edgeId, edge = () => actions.getEdge(edgeId()), edgeType = () => edge().type ?? "default", selectable = () => edge()
|
|
1673
|
+
let edgeRef, { store, actions } = useInternalSolidFlow(), edgeId = () => props.edgeId, edge = () => actions.getEdge(edgeId()), edgeType = () => edge().type ?? "default", selectable = () => isEdgeSelectable(edge(), store), focusable = () => edge().focusable ?? store.edgesFocusable, edgeComponent = () => store.edgeTypes[edgeType()], markerStartUrl = () => edge().markerStart ? `url('#${getMarkerId(edge().markerStart, store.id)}')` : void 0, markerEndUrl = () => edge().markerEnd ? `url('#${getMarkerId(edge().markerEnd, store.id)}')` : void 0, onClick = (event) => {
|
|
1446
1674
|
selectable() && actions.handleEdgeSelection(edgeId()), props.onEdgeClick?.({
|
|
1447
1675
|
edge: edge(),
|
|
1448
1676
|
event
|
|
1449
1677
|
});
|
|
1450
|
-
},
|
|
1451
|
-
(
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
}, onKeyDown = (event) => {
|
|
1678
|
+
}, onContextMenu = (event) => props.onEdgeContextMenu?.({
|
|
1679
|
+
edge: edge(),
|
|
1680
|
+
event
|
|
1681
|
+
}), onPointerEnter = (event) => props.onEdgePointerEnter?.({
|
|
1682
|
+
edge: edge(),
|
|
1683
|
+
event
|
|
1684
|
+
}), onPointerLeave = (event) => props.onEdgePointerLeave?.({
|
|
1685
|
+
edge: edge(),
|
|
1686
|
+
event
|
|
1687
|
+
}), onKeyDown = (event) => {
|
|
1460
1688
|
store.disableKeyboardA11y || !elementSelectionKeys.includes(event.key) || !selectable() || (event.key === "Escape" ? (edgeRef?.blur(), actions.unselectNodesAndEdges({ edges: [edge()] })) : actions.addSelectedEdges([edge().id]));
|
|
1461
1689
|
}, ariaLabel = () => edge().ariaLabel ?? `Edge from ${edge().source} to ${edge().target}`, culled = createMemo(() => isEdgeCulled(edge(), store.cullingViewport));
|
|
1462
1690
|
return createComponent(EdgeIdContext, {
|
|
@@ -1499,9 +1727,9 @@ const EdgeWrapper = (props) => {
|
|
|
1499
1727
|
},
|
|
1500
1728
|
onClick,
|
|
1501
1729
|
onKeyDown: (e) => focusable() && onKeyDown(e),
|
|
1502
|
-
onContextMenu
|
|
1503
|
-
onPointerEnter
|
|
1504
|
-
onPointerLeave
|
|
1730
|
+
onContextMenu,
|
|
1731
|
+
onPointerEnter,
|
|
1732
|
+
onPointerLeave
|
|
1505
1733
|
}, () => edge().domAttributes), !0), insert(_el$2, createComponent(Dynamic, {
|
|
1506
1734
|
get component() {
|
|
1507
1735
|
return edgeComponent();
|
|
@@ -1882,7 +2110,10 @@ const Handle = (props) => {
|
|
|
1882
2110
|
position: "top",
|
|
1883
2111
|
isConnectableStart: !0,
|
|
1884
2112
|
isConnectableEnd: !0
|
|
1885
|
-
}), { store, nodeLookup, connections, actions } = useInternalSolidFlow(), rest = omit(_props, "id", "type", "position", "isConnectable", "isConnectableStart", "isConnectableEnd", "isValidConnection", "onConnect", "onDisconnect", "children", "class", "style"), nodeId = useNodeId(), nodeConnectable = useNodeConnectable(), connectable = () => _props.isConnectable ?? nodeConnectable(), isTarget = () => _props.type === "target", handleId = () => _props.id ?? null, connectionInProcess = () => !!store.
|
|
2113
|
+
}), { store, nodeLookup, connections, actions } = useInternalSolidFlow(), rest = omit(_props, "id", "type", "position", "isConnectable", "isConnectableStart", "isConnectableEnd", "isValidConnection", "onConnect", "onDisconnect", "children", "class", "style"), nodeId = useNodeId(), nodeConnectable = useNodeConnectable(), connectable = () => _props.isConnectable ?? nodeConnectable(), isTarget = () => _props.type === "target", handleId = () => _props.id ?? null, connectionInProcess = () => !!store.connectionFromHandle, connectingFrom = () => {
|
|
2114
|
+
let fromHandle = store.connectionFromHandle;
|
|
2115
|
+
return fromHandle && fromHandle.nodeId === nodeId() && fromHandle.type === _props.type && fromHandle.id === handleId();
|
|
2116
|
+
}, targetState = () => store.connectionTargetByHandle[connectionKey(nodeId(), _props.type, handleId())], connectingTo = () => targetState() !== void 0, isPossibleTargetHandle = () => store.connectionMode === "strict" ? store.connectionFromHandle?.type !== _props.type : nodeId() !== store.connectionFromHandle?.nodeId || handleId() !== store.connectionFromHandle?.id, valid = () => targetState() === "valid", prevConnections = null;
|
|
1886
2117
|
createEffect(() => {
|
|
1887
2118
|
if (!_props.onConnect && !_props.onDisconnect) return null;
|
|
1888
2119
|
let rec = connections[connectionKey(nodeId(), _props.type, _props.id)], map = /* @__PURE__ */ new Map();
|
|
@@ -1900,13 +2131,20 @@ const Handle = (props) => {
|
|
|
1900
2131
|
}, edge = store.onBeforeConnect?.(handleConnection) ?? handleConnection;
|
|
1901
2132
|
actions.addEdge(edge), store.onConnect?.(handleConnection);
|
|
1902
2133
|
}, onPointerDown = (event) => {
|
|
2134
|
+
let gestureLookup = armConnectionGestureLookup({
|
|
2135
|
+
event,
|
|
2136
|
+
real: nodeLookup,
|
|
2137
|
+
domNode: store.domNode,
|
|
2138
|
+
getTransform: () => store.transform,
|
|
2139
|
+
connectionRadius: store.connectionRadius
|
|
2140
|
+
});
|
|
1903
2141
|
XYHandle.onPointerDown(event, {
|
|
1904
2142
|
handleId: handleId(),
|
|
1905
2143
|
nodeId: nodeId(),
|
|
1906
2144
|
isTarget: isTarget(),
|
|
1907
2145
|
connectionRadius: store.connectionRadius,
|
|
1908
2146
|
domNode: store.domNode,
|
|
1909
|
-
nodeLookup,
|
|
2147
|
+
nodeLookup: gestureLookup,
|
|
1910
2148
|
connectionMode: store.connectionMode,
|
|
1911
2149
|
lib: store.lib,
|
|
1912
2150
|
autoPanOnConnect: store.autoPanOnConnect,
|
|
@@ -2147,12 +2385,11 @@ const NodeWrapper = (props) => {
|
|
|
2147
2385
|
...h ? { height: toPxString(h) } : {}
|
|
2148
2386
|
};
|
|
2149
2387
|
}, culled = createMemo(() => isNodeCulled(node(), store.cullingViewport)), style = () => ({
|
|
2388
|
+
...sizeStyle(),
|
|
2150
2389
|
"z-index": node().internals.z,
|
|
2151
2390
|
transform: transform(),
|
|
2152
2391
|
visibility: culled() || !nodeHasDimensions(node()) ? "hidden" : "visible",
|
|
2153
|
-
"pointer-events": culled() ? "none" : void 0
|
|
2154
|
-
...sizeStyle(),
|
|
2155
|
-
...node().style ?? {}
|
|
2392
|
+
"pointer-events": culled() ? "none" : void 0
|
|
2156
2393
|
});
|
|
2157
2394
|
createEffect(() => ({
|
|
2158
2395
|
valid: nodeTypeValid(),
|
|
@@ -2512,7 +2749,7 @@ const InitialNodeTypesMap = {
|
|
|
2512
2749
|
pendingEntries = updateEntries, scheduleIdleCallback(() => {
|
|
2513
2750
|
let updates = new Map(pendingEntries);
|
|
2514
2751
|
pendingEntries = void 0;
|
|
2515
|
-
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode);
|
|
2752
|
+
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode, store.nodeExtent);
|
|
2516
2753
|
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());
|
|
2517
2754
|
});
|
|
2518
2755
|
};
|
|
@@ -2843,7 +3080,7 @@ const isSetEqual = (a, b) => {
|
|
|
2843
3080
|
for (let item of a) if (!b.has(item)) return !1;
|
|
2844
3081
|
return !0;
|
|
2845
3082
|
}, Pane = (props) => {
|
|
2846
|
-
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 = {
|
|
3083
|
+
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 = {
|
|
2847
3084
|
x: 0,
|
|
2848
3085
|
y: 0
|
|
2849
3086
|
}, autoPanStarted = !1, autoPanOnSelection = () => props.autoPanOnSelection ?? !0, paneClickDistance = () => props.paneClickDistance ?? 1, _panOnDrag = () => store.panActivationKeyPressed || props.panOnDrag, isSelecting = () => store.selectionKeyPressed || !!store.selectionRect || props.selectionOnDrag && _panOnDrag() !== !0, isSelectionEnabled = () => store.elementsSelectable && (isSelecting() || store.selectionRectMode === "user"), onClick = (event) => {
|
|
@@ -2858,7 +3095,7 @@ const isSetEqual = (a, b) => {
|
|
|
2858
3095
|
if (event.pointerType === "touch" && _panOnDrag() !== !1 && !store.selectionKeyPressed || (containerBounds = container?.getBoundingClientRect() ?? null, !containerBounds)) return;
|
|
2859
3096
|
let eventTargetIsContainer = event.target === container, isNoKeyEvent = !eventTargetIsContainer && !!event.target.closest(".nokey"), isSelectionActive = props.selectionOnDrag && eventTargetIsContainer || store.selectionKeyPressed;
|
|
2860
3097
|
if (isNoKeyEvent || !isSelecting() || !isSelectionActive || event.button !== 0 || !event.isPrimary) return;
|
|
2861
|
-
event.target?.setPointerCapture?.(event.pointerId), selectionInProgress = !1, autoPanStarted = !1;
|
|
3098
|
+
event.target?.setPointerCapture?.(event.pointerId), selectionSpatialLookup.arm((node) => nodeToRect(node)), selectionInProgress = !1, autoPanStarted = !1;
|
|
2862
3099
|
let { x, y } = getEventPosition(event, containerBounds), userSelectionFlowOrigin = pointToRendererPoint({
|
|
2863
3100
|
x,
|
|
2864
3101
|
y
|
|
@@ -2885,14 +3122,21 @@ const isSetEqual = (a, b) => {
|
|
|
2885
3122
|
width: Math.abs(mouseX - screenStart.x),
|
|
2886
3123
|
height: Math.abs(mouseY - screenStart.y)
|
|
2887
3124
|
}, prevSelectedNodeIds = selectedNodeIds, prevSelectedEdgeIds = selectedEdgeIds;
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
3125
|
+
{
|
|
3126
|
+
let [tx, ty, zoom] = store.transform;
|
|
3127
|
+
selectionSpatialLookup.setQueryRect({
|
|
3128
|
+
x: (nextUserSelectRect.x - tx) / zoom,
|
|
3129
|
+
y: (nextUserSelectRect.y - ty) / zoom,
|
|
3130
|
+
width: nextUserSelectRect.width / zoom,
|
|
3131
|
+
height: nextUserSelectRect.height / zoom
|
|
3132
|
+
});
|
|
3133
|
+
}
|
|
3134
|
+
selectedNodeIds = new Set(getNodesInside(selectionSpatialLookup, nextUserSelectRect, store.transform, store.selectionMode === SelectionMode$1.Partial, !0).map((n) => n.id)), selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
2891
3135
|
for (let nodeId of selectedNodeIds) {
|
|
2892
3136
|
let nodeConnections = connections[nodeId];
|
|
2893
3137
|
if (nodeConnections) for (let { edgeId } of Object.values(nodeConnections)) {
|
|
2894
3138
|
let edge = edgeLookup[edgeId];
|
|
2895
|
-
edge && (edge
|
|
3139
|
+
edge && isEdgeSelectable(edge, store) && selectedEdgeIds.add(edgeId);
|
|
2896
3140
|
}
|
|
2897
3141
|
}
|
|
2898
3142
|
isSetEqual(prevSelectedNodeIds, selectedNodeIds) || actions.setNodes((nodes) => {
|
|
@@ -3127,7 +3371,7 @@ const Selection = (props) => {
|
|
|
3127
3371
|
var _tmpl$$16 = /* @__PURE__ */ template("<div>");
|
|
3128
3372
|
/** Internal draggable bounding box rendered around multi-selected nodes. */
|
|
3129
3373
|
const NodeSelection = (props) => {
|
|
3130
|
-
let { store, nodeLookup, actions } = useInternalSolidFlow(), [ref$2, setRef] = createSignal(), bounds = () => store.selectionRectMode === "nodes" ? getInternalNodesBounds(nodeLookup, { filter: (node) => !!node.selected }) : null;
|
|
3374
|
+
let { store, nodeLookup, actions } = useInternalSolidFlow(), [ref$2, setRef] = createSignal(), bounds = createMemo(() => store.selectionRectMode === "nodes" ? getInternalNodesBounds(nodeLookup, { filter: (node) => !!node.selected }) : null);
|
|
3131
3375
|
createEffect(() => ({
|
|
3132
3376
|
el: ref$2(),
|
|
3133
3377
|
focusable: !store.disableKeyboardA11y
|
|
@@ -3135,13 +3379,13 @@ const NodeSelection = (props) => {
|
|
|
3135
3379
|
focusable && el?.focus({ preventScroll: !0 });
|
|
3136
3380
|
});
|
|
3137
3381
|
let onContextMenu = (event) => {
|
|
3138
|
-
let selectedNodes = store.
|
|
3382
|
+
let selectedNodes = store.selectedNodes;
|
|
3139
3383
|
props.onSelectionContextMenu?.({
|
|
3140
3384
|
nodes: selectedNodes,
|
|
3141
3385
|
event
|
|
3142
3386
|
});
|
|
3143
3387
|
}, onClick = (event) => {
|
|
3144
|
-
let selectedNodes = store.
|
|
3388
|
+
let selectedNodes = store.selectedNodes;
|
|
3145
3389
|
props.onSelectionClick?.({
|
|
3146
3390
|
nodes: selectedNodes,
|
|
3147
3391
|
event
|
|
@@ -3340,14 +3584,11 @@ const KeyHandler = (props) => {
|
|
|
3340
3584
|
}, handleWindowBlur = () => {
|
|
3341
3585
|
resetKeysAndSelection(), cancelPointerGestures();
|
|
3342
3586
|
}, handleDelete = async () => {
|
|
3343
|
-
let selectedNodes = store.
|
|
3587
|
+
let selectedNodes = store.selectedNodes, selectedEdges = store.selectedEdges;
|
|
3588
|
+
await deleteElements({
|
|
3344
3589
|
nodes: selectedNodes,
|
|
3345
3590
|
edges: selectedEdges
|
|
3346
3591
|
});
|
|
3347
|
-
(deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
3348
|
-
nodes: deletedNodes,
|
|
3349
|
-
edges: deletedEdges
|
|
3350
|
-
});
|
|
3351
3592
|
};
|
|
3352
3593
|
return isServer || (createEventListenerMap(window, {
|
|
3353
3594
|
keydown: (event) => {
|
|
@@ -3365,7 +3606,7 @@ const KeyHandler = (props) => {
|
|
|
3365
3606
|
capture: !0,
|
|
3366
3607
|
passive: !0
|
|
3367
3608
|
})), null;
|
|
3368
|
-
};
|
|
3609
|
+
}, 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(".");
|
|
3369
3610
|
//#endregion
|
|
3370
3611
|
//#region src/components/SolidFlow.tsx
|
|
3371
3612
|
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>");
|
|
@@ -3374,30 +3615,19 @@ const SolidFlow = (props) => {
|
|
|
3374
3615
|
let [domNodeRef, setDomNodeRef] = createSignal(), domNode, _props = merge({
|
|
3375
3616
|
...getDefaultFlowStateProps(),
|
|
3376
3617
|
colorMode: "light",
|
|
3377
|
-
deleteKeyCode: "Backspace",
|
|
3378
|
-
defaultViewport: {
|
|
3379
|
-
x: 0,
|
|
3380
|
-
y: 0,
|
|
3381
|
-
zoom: 1
|
|
3382
|
-
},
|
|
3383
|
-
multiSelectionKeyCode: isMacOs() ? "Meta" : "Control",
|
|
3384
3618
|
nodeClickDistance: 0,
|
|
3385
3619
|
panOnScroll: !1,
|
|
3386
|
-
panActivationKeyCode: "Space",
|
|
3387
3620
|
preventScrolling: !0,
|
|
3388
3621
|
panOnDrag: !0,
|
|
3389
3622
|
panOnScrollSpeed: .5,
|
|
3390
3623
|
panOnScrollMode: "free",
|
|
3391
3624
|
paneClickDistance: 0,
|
|
3392
|
-
reconnectRadius: 10,
|
|
3393
|
-
selectionKeyCode: "Shift",
|
|
3394
3625
|
selectionOnDrag: !1,
|
|
3395
3626
|
translateExtent: infiniteExtent,
|
|
3396
|
-
zoomActivationKeyCode: isMacOs() ? "Meta" : "Control",
|
|
3397
3627
|
zoomOnPinch: !0,
|
|
3398
3628
|
zoomOnDoubleClick: !0,
|
|
3399
3629
|
zoomOnScroll: !0
|
|
3400
|
-
}, props), htmlProps = omit(_props,
|
|
3630
|
+
}, props), htmlProps = omit(_props, ...FLOW_PROP_KEYS, "children"), TypedSolidFlowContext = SolidFlowContext, solidFlow = useContext(TypedSolidFlowContext) ?? createSolidFlow(_props), { store, actions } = solidFlow;
|
|
3401
3631
|
onSettled(() => (actions.applyInitialFitView(_props.fitView), actions.setConfig(_props), actions.setDomNode(domNode), () => {
|
|
3402
3632
|
actions.reset();
|
|
3403
3633
|
})), createEffect(() => domNodeRef(), (el) => {
|
|
@@ -3406,11 +3636,6 @@ const SolidFlow = (props) => {
|
|
|
3406
3636
|
actions.setWidth(el.clientWidth), actions.setHeight(el.clientHeight);
|
|
3407
3637
|
});
|
|
3408
3638
|
return observer.observe(el), () => observer.disconnect();
|
|
3409
|
-
}), createEffect(() => ({
|
|
3410
|
-
panZoom: store.panZoom,
|
|
3411
|
-
distance: _props.paneClickDistance
|
|
3412
|
-
}), ({ panZoom, distance }) => {
|
|
3413
|
-
panZoom?.setClickDistance(distance);
|
|
3414
3639
|
});
|
|
3415
3640
|
let selectedElements = createMemo(() => ({
|
|
3416
3641
|
nodes: store.selectedNodes,
|
|
@@ -3419,7 +3644,7 @@ const SolidFlow = (props) => {
|
|
|
3419
3644
|
createEffect(() => selectedElements(), (params) => {
|
|
3420
3645
|
untrack(() => _props.onSelectionChange)?.(params);
|
|
3421
3646
|
});
|
|
3422
|
-
let rootStyle = () => ({
|
|
3647
|
+
let asyncSeedGuard = () => (_props.nodes?.length, _props.edges?.length, null), rootStyle = () => ({
|
|
3423
3648
|
width: toPxString(_props.width),
|
|
3424
3649
|
height: toPxString(_props.height),
|
|
3425
3650
|
..._props.style
|
|
@@ -3452,6 +3677,7 @@ const SolidFlow = (props) => {
|
|
|
3452
3677
|
value: solidFlow,
|
|
3453
3678
|
get children() {
|
|
3454
3679
|
return [
|
|
3680
|
+
memo(() => asyncSeedGuard()),
|
|
3455
3681
|
createComponent(KeyHandler, {
|
|
3456
3682
|
get selectionKey() {
|
|
3457
3683
|
return _props.selectionKey;
|
|
@@ -3546,9 +3772,6 @@ const SolidFlow = (props) => {
|
|
|
3546
3772
|
return [
|
|
3547
3773
|
_tmpl$$14(),
|
|
3548
3774
|
createComponent(EdgeRenderer, {
|
|
3549
|
-
get reconnectRadius() {
|
|
3550
|
-
return _props.reconnectRadius;
|
|
3551
|
-
},
|
|
3552
3775
|
get onEdgeClick() {
|
|
3553
3776
|
return _props.onEdgeClick;
|
|
3554
3777
|
},
|
|
@@ -3560,9 +3783,6 @@ const SolidFlow = (props) => {
|
|
|
3560
3783
|
},
|
|
3561
3784
|
get onEdgePointerLeave() {
|
|
3562
3785
|
return _props.onEdgePointerLeave;
|
|
3563
|
-
},
|
|
3564
|
-
get defaultEdgeOptions() {
|
|
3565
|
-
return _props.defaultEdgeOptions;
|
|
3566
3786
|
}
|
|
3567
3787
|
}),
|
|
3568
3788
|
_tmpl$2(),
|
|
@@ -4158,24 +4378,23 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4158
4378
|
nodeBorderRadius: 5,
|
|
4159
4379
|
nodeStrokeWidth: 2,
|
|
4160
4380
|
style: {}
|
|
4161
|
-
}), 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 =
|
|
4381
|
+
}), paneProps = omit(_props, "class", "style", "position", "nodeClass", "nodeStrokeColor", "nodeColor", "pannable", "zoomable", "inversePan", "zoomStep", "bgColor", "width", "height", "maskColor", "maskStrokeColor", "maskStrokeWidth", "nodeBorderRadius", "nodeStrokeWidth", "nodeComponent", "onClick", "onNodeClick"), nodeColorFunc = () => _props.nodeColor === void 0 ? void 0 : getAttrFunction(_props.nodeColor), nodeStrokeColorFunc = () => getAttrFunction(_props.nodeStrokeColor), nodeClassFunc = () => getAttrFunction(_props.nodeClass), shapeRendering = typeof window > "u" || window.chrome ? "crispEdges" : "geometricPrecision", labelledBy = createMemo(() => `solid-flow__minimap-desc-${store.id}`), viewBB = createMemo(() => ({
|
|
4162
4382
|
x: -store.viewport.x / store.viewport.zoom,
|
|
4163
4383
|
y: -store.viewport.y / store.viewport.zoom,
|
|
4164
4384
|
width: store.width / store.viewport.zoom,
|
|
4165
4385
|
height: store.height / store.viewport.zoom
|
|
4166
|
-
}),
|
|
4167
|
-
let
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4386
|
+
})), boundingRect = createMemo(() => {
|
|
4387
|
+
let view = viewBB();
|
|
4388
|
+
if (nodeLookup.size === 0) return view;
|
|
4389
|
+
let bounds = getInternalNodesBounds(nodeLookup);
|
|
4390
|
+
return !Number.isFinite(bounds.x) || !Number.isFinite(bounds.width) ? view : getBoundsOfRects(bounds, view);
|
|
4391
|
+
}), viewScale = createMemo(() => Math.max(boundingRect().width / _props.width, boundingRect().height / _props.height)), getViewWidth = () => viewScale() * _props.width, getViewHeight = () => viewScale() * _props.height, getOffset = () => 5 * viewScale(), getX = () => {
|
|
4392
|
+
let rect = boundingRect();
|
|
4393
|
+
return rect.x - (getViewWidth() - rect.width) / 2 - getOffset();
|
|
4172
4394
|
}, getY = () => {
|
|
4173
|
-
let
|
|
4174
|
-
return
|
|
4175
|
-
}, getViewboxWidth = () => getViewWidth() + getOffset() * 2, getViewboxHeight = () => getViewHeight() + getOffset() * 2, strokeWidth = () => _props.maskStrokeWidth ? _props.maskStrokeWidth *
|
|
4176
|
-
let currentNodeIds = store.nodes.map((node) => node.id), currentSet = new Set(currentNodeIds);
|
|
4177
|
-
return (prevNodeIds.length !== currentNodeIds.length || !prevNodeIds.every((id) => currentSet.has(id))) && (prevNodeIds = currentNodeIds), prevNodeIds;
|
|
4178
|
-
};
|
|
4395
|
+
let rect = boundingRect();
|
|
4396
|
+
return rect.y - (getViewHeight() - rect.height) / 2 - getOffset();
|
|
4397
|
+
}, 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]) });
|
|
4179
4398
|
return createComponent(Panel, mergeProps({
|
|
4180
4399
|
get position() {
|
|
4181
4400
|
return _props.position;
|
|
@@ -4206,7 +4425,7 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4206
4425
|
domNode: el,
|
|
4207
4426
|
panZoom,
|
|
4208
4427
|
getTransform: () => store.transform,
|
|
4209
|
-
getViewScale
|
|
4428
|
+
getViewScale: viewScale
|
|
4210
4429
|
});
|
|
4211
4430
|
return setMinimap(instance), () => {
|
|
4212
4431
|
instance.destroy();
|
|
@@ -4267,9 +4486,7 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4267
4486
|
get strokeWidth() {
|
|
4268
4487
|
return _props.nodeStrokeWidth;
|
|
4269
4488
|
},
|
|
4270
|
-
|
|
4271
|
-
return shapeRendering();
|
|
4272
|
-
},
|
|
4489
|
+
shapeRendering,
|
|
4273
4490
|
get width() {
|
|
4274
4491
|
return nodeDimensions().width;
|
|
4275
4492
|
},
|
|
@@ -4307,7 +4524,7 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
|
|
|
4307
4524
|
s: strokeWidth(),
|
|
4308
4525
|
h: labelledBy(),
|
|
4309
4526
|
r: `M${getX() - getOffset()},${getY() - getOffset()}h${getViewboxWidth() + getOffset() * 2}v${getViewboxHeight() + getOffset() * 2}h${-getViewboxWidth() - getOffset() * 2}z
|
|
4310
|
-
M${
|
|
4527
|
+
M${viewBB().x},${viewBB().y}h${viewBB().width}v${viewBB().height}h${-viewBB().width}z`
|
|
4311
4528
|
}), ({ e, t, a, o, i, n, s, h, r }, _p$) => {
|
|
4312
4529
|
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);
|
|
4313
4530
|
}), _el$;
|