@dschz/solid-flow 1.0.0-next.6 → 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 +27 -0
- package/dist/index/index.d.ts +131 -102
- package/dist/index/index.js +471 -259
- package/dist/index/index.jsx +470 -250
- package/package.json +6 -5
package/dist/index/index.jsx
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 <Show when={labelNode()}>{(root) => <Portal mount={root()}>{props.children}</Portal>}</Show>;
|
|
71
71
|
}, EdgeLabel = (props) => {
|
|
@@ -145,6 +145,181 @@ const getEdgeId = (connection) => {
|
|
|
145
145
|
};
|
|
146
146
|
};
|
|
147
147
|
return <BaseEdge path={pathData().path} labelX={pathData().labelX} labelY={pathData().labelY} label={props.label} labelStyle={props.labelStyle} markerStart={props.markerStart} markerEnd={props.markerEnd} interactionWidth={props.interactionWidth} style={props.style} />;
|
|
148
|
+
};
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/core/spatial/grid.ts
|
|
151
|
+
/**
|
|
152
|
+
* A uniform spatial hash over axis-aligned rects — the plain, NON-reactive
|
|
153
|
+
* building block behind the flow's spatial queries (RFC-4239 dossier:
|
|
154
|
+
* gesture-scoped snapshots and epoch-rebuilt indexes; deliberately never a
|
|
155
|
+
* live-maintained reactive structure, which would re-create the round-6
|
|
156
|
+
* central-collection anti-pattern).
|
|
157
|
+
*
|
|
158
|
+
* Every operation is O(cells touched); with cellSize on the order of the
|
|
159
|
+
* query radius or median node size, inserts and queries touch O(1) cells.
|
|
160
|
+
* No balancing, no extent-known-up-front requirement, no dependency —
|
|
161
|
+
* upstream's own bake-off (quadtree vs BVH vs rbush) is why: fixed-radius
|
|
162
|
+
* neighborhood and rect-vs-box queries are the textbook grid case.
|
|
163
|
+
*/
|
|
164
|
+
var SpatialGrid = class {
|
|
165
|
+
cellSize;
|
|
166
|
+
cells = /* @__PURE__ */ new Map();
|
|
167
|
+
rects = /* @__PURE__ */ new Map();
|
|
168
|
+
constructor(cellSize) {
|
|
169
|
+
this.cellSize = cellSize;
|
|
170
|
+
}
|
|
171
|
+
cellRange(rect) {
|
|
172
|
+
let size = this.cellSize;
|
|
173
|
+
return {
|
|
174
|
+
minX: Math.floor(rect.x / size),
|
|
175
|
+
maxX: Math.floor((rect.x + rect.width) / size),
|
|
176
|
+
minY: Math.floor(rect.y / size),
|
|
177
|
+
maxY: Math.floor((rect.y + rect.height) / size)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
insert(id, rect) {
|
|
181
|
+
this.rects.set(id, rect);
|
|
182
|
+
let { minX, maxX, minY, maxY } = this.cellRange(rect);
|
|
183
|
+
for (let cx = minX; cx <= maxX; cx++) for (let cy = minY; cy <= maxY; cy++) {
|
|
184
|
+
let key = `${cx}:${cy}`, bucket = this.cells.get(key);
|
|
185
|
+
bucket ? bucket.push(id) : this.cells.set(key, [id]);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** Ids of entries whose rect overlaps the query rect (touching counts). */
|
|
189
|
+
queryRect(query) {
|
|
190
|
+
let { minX, maxX, minY, maxY } = this.cellRange(query), seen = /* @__PURE__ */ new Set(), result = [];
|
|
191
|
+
for (let cx = minX; cx <= maxX; cx++) for (let cy = minY; cy <= maxY; cy++) {
|
|
192
|
+
let bucket = this.cells.get(`${cx}:${cy}`);
|
|
193
|
+
if (bucket) for (let id of bucket) {
|
|
194
|
+
if (seen.has(id)) continue;
|
|
195
|
+
seen.add(id);
|
|
196
|
+
let rect = this.rects.get(id);
|
|
197
|
+
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);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
get size() {
|
|
203
|
+
return this.rects.size;
|
|
204
|
+
}
|
|
205
|
+
}, GestureSpatialLookup = class {
|
|
206
|
+
#real;
|
|
207
|
+
#cellSize;
|
|
208
|
+
#grid = null;
|
|
209
|
+
#queryRect = null;
|
|
210
|
+
constructor(real, cellSize) {
|
|
211
|
+
this.#real = real, this.#cellSize = cellSize;
|
|
212
|
+
}
|
|
213
|
+
/** Snapshot the current geometry into the grid (gesture start). */
|
|
214
|
+
arm(rectOf) {
|
|
215
|
+
let grid = new SpatialGrid(this.#cellSize);
|
|
216
|
+
for (let [id, value] of this.#real.entries()) grid.insert(id, rectOf(value));
|
|
217
|
+
this.#grid = grid, this.#queryRect = null;
|
|
218
|
+
}
|
|
219
|
+
/** Focus iteration on the neighborhood of the pointer (per move). */
|
|
220
|
+
setQueryCenter(center, radius) {
|
|
221
|
+
this.#queryRect = {
|
|
222
|
+
x: center.x - radius,
|
|
223
|
+
y: center.y - radius,
|
|
224
|
+
width: radius * 2,
|
|
225
|
+
height: radius * 2
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/** Focus iteration on an explicit rect (box-selection gestures). */
|
|
229
|
+
setQueryRect(rect) {
|
|
230
|
+
this.#queryRect = rect;
|
|
231
|
+
}
|
|
232
|
+
/** Back to plain pass-through (gesture end). */
|
|
233
|
+
disarm() {
|
|
234
|
+
this.#grid = null, this.#queryRect = null;
|
|
235
|
+
}
|
|
236
|
+
#candidateIds() {
|
|
237
|
+
return !this.#grid || !this.#queryRect ? null : this.#grid.queryRect(this.#queryRect);
|
|
238
|
+
}
|
|
239
|
+
get(key) {
|
|
240
|
+
return this.#real.get(key);
|
|
241
|
+
}
|
|
242
|
+
has(key) {
|
|
243
|
+
return this.#real.has(key);
|
|
244
|
+
}
|
|
245
|
+
get size() {
|
|
246
|
+
return this.#real.size;
|
|
247
|
+
}
|
|
248
|
+
*keys() {
|
|
249
|
+
let candidates = this.#candidateIds();
|
|
250
|
+
if (!candidates) {
|
|
251
|
+
yield* this.#real.keys();
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
for (let id of candidates) this.#real.has(id) && (yield id);
|
|
255
|
+
}
|
|
256
|
+
*values() {
|
|
257
|
+
let candidates = this.#candidateIds();
|
|
258
|
+
if (!candidates) {
|
|
259
|
+
yield* this.#real.values();
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
for (let id of candidates) {
|
|
263
|
+
let value = this.#real.get(id);
|
|
264
|
+
value !== void 0 && (yield value);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
*entries() {
|
|
268
|
+
let candidates = this.#candidateIds();
|
|
269
|
+
if (!candidates) {
|
|
270
|
+
yield* this.#real.entries();
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
for (let id of candidates) {
|
|
274
|
+
let value = this.#real.get(id);
|
|
275
|
+
value !== void 0 && (yield [id, value]);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
[Symbol.iterator]() {
|
|
279
|
+
return this.entries();
|
|
280
|
+
}
|
|
281
|
+
forEach(callback, thisArg) {
|
|
282
|
+
for (let [key, value] of this.entries()) callback.call(thisArg, value, key, this);
|
|
283
|
+
}
|
|
284
|
+
[Symbol.toStringTag] = "GestureSpatialLookup";
|
|
285
|
+
set() {
|
|
286
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
287
|
+
}
|
|
288
|
+
getOrInsert() {
|
|
289
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
290
|
+
}
|
|
291
|
+
getOrInsertComputed() {
|
|
292
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
293
|
+
}
|
|
294
|
+
delete() {
|
|
295
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
296
|
+
}
|
|
297
|
+
clear() {
|
|
298
|
+
throw Error("GestureSpatialLookup is read-only");
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/components/handle/connectionGestureLookup.ts
|
|
303
|
+
/**
|
|
304
|
+
* Upstream `getClosestHandle` prefilters nodes within
|
|
305
|
+
* `connectionRadius + ADDITIONAL_DISTANCE` of the pointer; ADDITIONAL_DISTANCE
|
|
306
|
+
* is hardcoded to 250 in @xyflow/system (xyhandle/utils.ts). Tracked here with
|
|
307
|
+
* a safety pad: a superset of candidates is always correct (their exact
|
|
308
|
+
* distance filter runs after), so the pad only costs a few extra candidates.
|
|
309
|
+
*/
|
|
310
|
+
const armConnectionGestureLookup = (options) => {
|
|
311
|
+
let { event, real, domNode, getTransform, connectionRadius } = options, containerBounds = domNode?.getBoundingClientRect();
|
|
312
|
+
if (!containerBounds) return real;
|
|
313
|
+
let radius = connectionRadius + 250 + 50, lookup = new GestureSpatialLookup(real, radius);
|
|
314
|
+
lookup.arm((node) => nodeToRect(node));
|
|
315
|
+
let update = (moveEvent) => {
|
|
316
|
+
lookup.setQueryCenter(pointToRendererPoint(getEventPosition(moveEvent, containerBounds), getTransform(), !1, [1, 1]), radius);
|
|
317
|
+
};
|
|
318
|
+
update(event);
|
|
319
|
+
let doc = getHostForElement(event.target), dispose = () => {
|
|
320
|
+
doc.removeEventListener("mousemove", update, !0), doc.removeEventListener("touchmove", update, !0), doc.removeEventListener("mouseup", dispose, !0), doc.removeEventListener("touchend", dispose, !0), lookup.disarm();
|
|
321
|
+
};
|
|
322
|
+
return doc.addEventListener("mousemove", update, !0), doc.addEventListener("touchmove", update, !0), doc.addEventListener("mouseup", dispose, !0), doc.addEventListener("touchend", dispose, !0), lookup;
|
|
148
323
|
}, EdgeReconnectAnchor = (props) => {
|
|
149
324
|
let _props = propDefaults(props, {
|
|
150
325
|
size: 25,
|
|
@@ -165,7 +340,13 @@ const getEdgeId = (connection) => {
|
|
|
165
340
|
nodeId: edge().target,
|
|
166
341
|
handleId: edge().targetHandle ?? null,
|
|
167
342
|
type: "target"
|
|
168
|
-
}
|
|
343
|
+
}, gestureLookup = armConnectionGestureLookup({
|
|
344
|
+
event,
|
|
345
|
+
real: nodeLookup,
|
|
346
|
+
domNode: store.domNode,
|
|
347
|
+
getTransform: () => store.transform,
|
|
348
|
+
connectionRadius: store.connectionRadius
|
|
349
|
+
});
|
|
169
350
|
XYHandle.onPointerDown(event, {
|
|
170
351
|
lib: store.lib,
|
|
171
352
|
flowId: store.id,
|
|
@@ -175,7 +356,7 @@ const getEdgeId = (connection) => {
|
|
|
175
356
|
autoPanOnConnect: store.autoPanOnConnect,
|
|
176
357
|
connectionMode: store.connectionMode,
|
|
177
358
|
connectionRadius: store.connectionRadius,
|
|
178
|
-
nodeLookup,
|
|
359
|
+
nodeLookup: gestureLookup,
|
|
179
360
|
isTarget: opposite.type === "target",
|
|
180
361
|
edgeUpdaterType: opposite.type,
|
|
181
362
|
cancelConnection: actions.cancelConnection,
|
|
@@ -236,9 +417,73 @@ const getEdgeId = (connection) => {
|
|
|
236
417
|
</div>
|
|
237
418
|
</Show>
|
|
238
419
|
</>;
|
|
239
|
-
},
|
|
240
|
-
let
|
|
241
|
-
|
|
420
|
+
}, createSelectionCommands = ({ store, setNodesStore, setEdgesStore, setSelectionRect, setSelectionRectMode, nodeLookup, edgeLookup, updateNodePositions }) => {
|
|
421
|
+
let unselectNodesAndEdges = ({ nodes: _nodes, edges } = {}) => {
|
|
422
|
+
let nodesToUnselect = new Set((_nodes || store.nodes).map(({ id }) => id));
|
|
423
|
+
nodesToUnselect.size && setNodesStore((nodes) => {
|
|
424
|
+
for (let node of nodes) nodesToUnselect.has(node.id) && (node.selected = !1);
|
|
425
|
+
});
|
|
426
|
+
let edgesToUnselect = new Set((edges ?? store.edges).map(({ id }) => id));
|
|
427
|
+
edgesToUnselect.size && setEdgesStore((edges) => {
|
|
428
|
+
for (let edge of edges) edgesToUnselect.has(edge.id) && (edge.selected = !1);
|
|
429
|
+
}), flush();
|
|
430
|
+
}, addSelectedNodes = (ids) => {
|
|
431
|
+
let isMultiSelection = store.multiselectionKeyPressed, idSet = new Set(ids);
|
|
432
|
+
setNodesStore((nodes) => {
|
|
433
|
+
for (let node of nodes) {
|
|
434
|
+
let nodeWillBeSelected = idSet.has(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
435
|
+
node.selected !== selected && (node.selected = selected);
|
|
436
|
+
}
|
|
437
|
+
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
438
|
+
}, addSelectedEdges = (ids) => {
|
|
439
|
+
let isMultiSelection = store.multiselectionKeyPressed, idSet = new Set(ids);
|
|
440
|
+
setEdgesStore((edges) => {
|
|
441
|
+
for (let edge of edges) {
|
|
442
|
+
let edgeWillBeSelected = idSet.has(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
443
|
+
edge.selected !== selected && (edge.selected = selected);
|
|
444
|
+
}
|
|
445
|
+
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
446
|
+
};
|
|
447
|
+
return {
|
|
448
|
+
unselectNodesAndEdges,
|
|
449
|
+
addSelectedNodes,
|
|
450
|
+
addSelectedEdges,
|
|
451
|
+
handleNodeSelection: (id, unselect, nodeRef) => {
|
|
452
|
+
let node = store.nodes.find((n) => n.id === id);
|
|
453
|
+
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
454
|
+
nodes: [node],
|
|
455
|
+
edges: []
|
|
456
|
+
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
457
|
+
},
|
|
458
|
+
handleEdgeSelection: (id) => {
|
|
459
|
+
let edge = edgeLookup[id];
|
|
460
|
+
edge && isEdgeSelectable(edge, store) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
461
|
+
nodes: [],
|
|
462
|
+
edges: [edge]
|
|
463
|
+
}) : addSelectedEdges([id]));
|
|
464
|
+
},
|
|
465
|
+
moveSelectedNodes: (direction, factor) => {
|
|
466
|
+
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;
|
|
467
|
+
for (let node of nodeLookup.values()) {
|
|
468
|
+
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
469
|
+
let nextPosition = {
|
|
470
|
+
x: node.internals.positionAbsolute.x + xDiff,
|
|
471
|
+
y: node.internals.positionAbsolute.y + yDiff
|
|
472
|
+
};
|
|
473
|
+
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
474
|
+
let { position } = calculateNodePosition({
|
|
475
|
+
nodeId: node.id,
|
|
476
|
+
nextPosition,
|
|
477
|
+
nodeLookup,
|
|
478
|
+
nodeExtent: store.nodeExtent,
|
|
479
|
+
nodeOrigin: store.nodeOrigin,
|
|
480
|
+
onError: store.onError
|
|
481
|
+
});
|
|
482
|
+
nodeUpdates.set(node.id, { position });
|
|
483
|
+
}
|
|
484
|
+
updateNodePositions(nodeUpdates);
|
|
485
|
+
}
|
|
486
|
+
};
|
|
242
487
|
}, 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(() => {
|
|
243
488
|
let { width, height } = source;
|
|
244
489
|
if (!width || !height) return null;
|
|
@@ -369,14 +614,48 @@ var RecordMapFacade = class {
|
|
|
369
614
|
}
|
|
370
615
|
};
|
|
371
616
|
//#endregion
|
|
372
|
-
//#region src/core/
|
|
617
|
+
//#region src/core/measurementIngest.ts
|
|
373
618
|
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
619
|
+
* The measurement ingest lifecycle (WP3): everything that flows FROM the DOM
|
|
620
|
+
* measuring pass INTO the data graph, plus the garbage collection that keeps
|
|
621
|
+
* the measurements root aligned with graph membership. The DOM side (resize
|
|
622
|
+
* observers, the idle-scheduled measuring pass) lives in createSolidFlow;
|
|
623
|
+
* headless usage never calls these.
|
|
378
624
|
*/
|
|
379
|
-
const
|
|
625
|
+
const createMeasurementIngest = ({ setMeasurementsStore, setNodesStore, nodes }) => (createEffect(() => new Set(nodes().map((n) => n.id)), (currentIds) => {
|
|
626
|
+
setMeasurementsStore((draft) => {
|
|
627
|
+
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
628
|
+
});
|
|
629
|
+
}), {
|
|
630
|
+
applyMeasurementWrites: (writes) => {
|
|
631
|
+
setMeasurementsStore((draft) => {
|
|
632
|
+
for (let write of writes) if (write.hidden) {
|
|
633
|
+
let entry = draft[write.id];
|
|
634
|
+
entry && (entry.handleBounds = void 0);
|
|
635
|
+
} else draft[write.id] = {
|
|
636
|
+
measured: write.measured,
|
|
637
|
+
handleBounds: write.handleBounds
|
|
638
|
+
};
|
|
639
|
+
});
|
|
640
|
+
},
|
|
641
|
+
applyNodeChanges: (changes) => {
|
|
642
|
+
changes.length !== 0 && setNodesStore((nodes) => {
|
|
643
|
+
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
644
|
+
for (let change of changes) {
|
|
645
|
+
let node = nodeById.get(change.id);
|
|
646
|
+
if (node) switch (change.type) {
|
|
647
|
+
case "dimensions":
|
|
648
|
+
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
649
|
+
...node.measured,
|
|
650
|
+
...change.dimensions
|
|
651
|
+
};
|
|
652
|
+
break;
|
|
653
|
+
case "position": node.position = change.position ?? node.position;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}), connectionKey = (nodeId, type, handleId) => `${nodeId}${type ? handleId ? `-${type}-${handleId}` : `-${type}` : ""}`, pairKey = (aNode, aHandle, bNode, bHandle) => `${aNode}-${aHandle}--${bNode}-${bHandle}`, createConnections = (source) => createProjection(() => {
|
|
380
659
|
let out = {}, add = (key, entry, connection) => {
|
|
381
660
|
(out[key] ??= {})[entry] = connection;
|
|
382
661
|
};
|
|
@@ -441,10 +720,6 @@ const EMPTY_AUTO_INDEX = /* @__PURE__ */ new Map(), createInternalNodes = (sourc
|
|
|
441
720
|
}, row.internals.z = z;
|
|
442
721
|
} else source.nodes.length;
|
|
443
722
|
}
|
|
444
|
-
if (userNode.parentId) {
|
|
445
|
-
let parent = entryById.get(userNode.parentId);
|
|
446
|
-
parent?.store.row.internals.positionAbsolute.x, parent?.store.row.internals.z;
|
|
447
|
-
}
|
|
448
723
|
return { row };
|
|
449
724
|
}, {}, { key: "id" }), entry = {
|
|
450
725
|
store,
|
|
@@ -513,8 +788,8 @@ const createLayoutedEdges = (source) => {
|
|
|
513
788
|
let rowStores = mapArray(() => source.edges, (edgeAccessor) => ({
|
|
514
789
|
id: edgeAccessor().id,
|
|
515
790
|
store: createProjection(() => {
|
|
516
|
-
let edge = edgeAccessor()
|
|
517
|
-
return
|
|
791
|
+
let edge = edgeAccessor();
|
|
792
|
+
return { row: buildRow(source, edge) };
|
|
518
793
|
}, { row: null }, { key: "id" })
|
|
519
794
|
}), { keyed: (edge) => edge.id }), assigned = /* @__PURE__ */ new Map();
|
|
520
795
|
return createProjection((draft) => {
|
|
@@ -530,7 +805,7 @@ const createLayoutedEdges = (source) => {
|
|
|
530
805
|
});
|
|
531
806
|
}, buildRow = (source, edge) => {
|
|
532
807
|
let sourceNode = source.nodeLookup.get(edge.source), targetNode = source.nodeLookup.get(edge.target);
|
|
533
|
-
if (!sourceNode || !targetNode) return
|
|
808
|
+
if (!sourceNode || !targetNode) return null;
|
|
534
809
|
let edgePosition = getEdgePosition({
|
|
535
810
|
id: edge.id,
|
|
536
811
|
sourceNode,
|
|
@@ -560,7 +835,33 @@ const createLayoutedEdges = (source) => {
|
|
|
560
835
|
let out = {};
|
|
561
836
|
for (let node of source.nodes) node.parentId && (out[node.parentId] = !0);
|
|
562
837
|
return out;
|
|
563
|
-
}, {}, { key: "id" }),
|
|
838
|
+
}, {}, { key: "id" }), createSeededGraphStores = (props, config) => {
|
|
839
|
+
props.nodes !== void 0 && props.defaultNodes, props.edges !== void 0 && props.defaultEdges;
|
|
840
|
+
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;
|
|
841
|
+
return createEffect(() => {
|
|
842
|
+
let next = config().nodes;
|
|
843
|
+
if (next) for (let node of next);
|
|
844
|
+
return { next };
|
|
845
|
+
}, ({ next }) => {
|
|
846
|
+
next && (nodeSeedAdopted = !0, setNodesStore(() => next));
|
|
847
|
+
}, { defer: !0 }), createEffect(() => {
|
|
848
|
+
let next = config().edges;
|
|
849
|
+
if (next) for (let edge of next);
|
|
850
|
+
return { next };
|
|
851
|
+
}, ({ next }) => {
|
|
852
|
+
next && (edgeSeedAdopted = !0, setEdgesStore(() => next));
|
|
853
|
+
}, { defer: !0 }), createEffect(() => ({
|
|
854
|
+
nodes: config().defaultNodes,
|
|
855
|
+
edges: config().defaultEdges
|
|
856
|
+
}), ({ nodes: defaultNodes, edges: defaultEdges }) => {
|
|
857
|
+
defaultNodes && !nodeSeedAdopted && config().nodes === void 0 && (nodeSeedAdopted = !0, setNodesStore(() => [...defaultNodes])), defaultEdges && !edgeSeedAdopted && config().edges === void 0 && (edgeSeedAdopted = !0, setEdgesStore(() => [...defaultEdges]));
|
|
858
|
+
}, { defer: !0 }), {
|
|
859
|
+
nodesStore,
|
|
860
|
+
setNodesStore,
|
|
861
|
+
edgesStore,
|
|
862
|
+
setEdgesStore
|
|
863
|
+
};
|
|
864
|
+
}, getInitialViewport = (fitView, initialViewport, width, height, nodeLookup) => {
|
|
564
865
|
if (fitView && !initialViewport && width && height) {
|
|
565
866
|
let bounds = getInternalNodesBounds(nodeLookup, { filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)) });
|
|
566
867
|
return getViewportForBounds$1(bounds, width, height, .5, 2, .1);
|
|
@@ -571,9 +872,7 @@ const createLayoutedEdges = (source) => {
|
|
|
571
872
|
zoom: 1
|
|
572
873
|
};
|
|
573
874
|
}, createFlowState = (props, injections = {}) => {
|
|
574
|
-
let _props = merge(getDefaultFlowStateProps(), props), initialNodeTypes = injections.initialNodeTypes ?? {}, initialEdgeTypes = injections.initialEdgeTypes ?? {}, prefersDark = injections.prefersDark ?? (() => _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props),
|
|
575
|
-
props.nodes !== void 0 && props.defaultNodes, props.edges !== void 0 && props.defaultEdges;
|
|
576
|
-
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({
|
|
875
|
+
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({
|
|
577
876
|
get nodes() {
|
|
578
877
|
return nodesStore;
|
|
579
878
|
},
|
|
@@ -593,24 +892,7 @@ const createLayoutedEdges = (source) => {
|
|
|
593
892
|
return config().zIndexMode;
|
|
594
893
|
}
|
|
595
894
|
}), nodeLookup = new RecordMapFacade(internalNodes), initialViewport = getInitialViewport(_props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), [viewportStore, setViewportStore] = createStore(_props.viewport ?? initialViewport);
|
|
596
|
-
createEffect(() => {
|
|
597
|
-
let next = config().nodes;
|
|
598
|
-
if (next) for (let node of next);
|
|
599
|
-
return { next };
|
|
600
|
-
}, ({ next }) => {
|
|
601
|
-
next && (nodeSeedAdopted = !0, setNodesStore(() => next));
|
|
602
|
-
}, { defer: !0 }), createEffect(() => {
|
|
603
|
-
let next = config().edges;
|
|
604
|
-
if (next) for (let edge of next);
|
|
605
|
-
return { next };
|
|
606
|
-
}, ({ next }) => {
|
|
607
|
-
next && (edgeSeedAdopted = !0, setEdgesStore(() => next));
|
|
608
|
-
}, { defer: !0 }), createEffect(() => ({
|
|
609
|
-
nodes: config().defaultNodes,
|
|
610
|
-
edges: config().defaultEdges
|
|
611
|
-
}), ({ nodes: defaultNodes, edges: defaultEdges }) => {
|
|
612
|
-
defaultNodes && !nodeSeedAdopted && config().nodes === void 0 && (nodeSeedAdopted = !0, setNodesStore(() => [...defaultNodes])), defaultEdges && !edgeSeedAdopted && config().edges === void 0 && (edgeSeedAdopted = !0, setEdgesStore(() => [...defaultEdges]));
|
|
613
|
-
}, { defer: !0 }), createEffect(() => config().viewport, (next) => {
|
|
895
|
+
createEffect(() => config().viewport, (next) => {
|
|
614
896
|
next && setViewportStore(() => next);
|
|
615
897
|
}, { defer: !0 });
|
|
616
898
|
let transform = createMemo(() => [
|
|
@@ -622,25 +904,29 @@ const createLayoutedEdges = (source) => {
|
|
|
622
904
|
if (nodes.length === 0) return !1;
|
|
623
905
|
for (let node of nodes) if (!node.hidden && (node.measured?.width === void 0 || node.measured?.height === void 0)) return !1;
|
|
624
906
|
return !0;
|
|
625
|
-
}),
|
|
907
|
+
}), resolvedColorMode = createMemo(() => {
|
|
908
|
+
let mode = config().colorMode;
|
|
909
|
+
return mode === "system" ? prefersDark() ? "dark" : "light" : mode;
|
|
910
|
+
}), projectedConnection = createMemo(() => {
|
|
911
|
+
let state = connection();
|
|
912
|
+
return state.inProgress ? {
|
|
913
|
+
...state,
|
|
914
|
+
to: pointToRendererPoint(state.to, transform())
|
|
915
|
+
} : state;
|
|
916
|
+
}), 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) => {
|
|
917
|
+
let state = connection(), toHandle = state.inProgress ? state.toHandle : null, key = toHandle ? connectionKey(toHandle.nodeId, toHandle.type, toHandle.id ?? null) : null;
|
|
918
|
+
for (let existing of Object.keys(draft)) existing !== key && delete draft[existing];
|
|
919
|
+
key && (draft[key] = state.isValid ? "valid" : "invalid");
|
|
920
|
+
}, {}, { key: null }), mergedNodeTypes = createMemo(() => ({
|
|
921
|
+
...initialNodeTypes,
|
|
922
|
+
...config().nodeTypes
|
|
923
|
+
})), mergedEdgeTypes = createMemo(() => ({
|
|
924
|
+
...initialEdgeTypes,
|
|
925
|
+
...config().edgeTypes
|
|
926
|
+
})), selectedNodesView = createMemo(() => nodesStore.filter((node) => node.selected)), selectedEdgesView = createMemo(() => edgesStore.filter((edge) => edge.selected)), store = merge({
|
|
626
927
|
width: 0,
|
|
627
928
|
height: 0
|
|
628
929
|
}, config, {
|
|
629
|
-
get _colorMode() {
|
|
630
|
-
return config().colorMode;
|
|
631
|
-
},
|
|
632
|
-
get _colorModeSSR() {
|
|
633
|
-
return config().colorModeSSR;
|
|
634
|
-
},
|
|
635
|
-
get _connection() {
|
|
636
|
-
return connection();
|
|
637
|
-
},
|
|
638
|
-
get _nodeTypes() {
|
|
639
|
-
return config().nodeTypes;
|
|
640
|
-
},
|
|
641
|
-
get _edgeTypes() {
|
|
642
|
-
return config().edgeTypes;
|
|
643
|
-
},
|
|
644
930
|
get ariaLabelConfig() {
|
|
645
931
|
return ariaLabelConfig();
|
|
646
932
|
},
|
|
@@ -651,14 +937,16 @@ const createLayoutedEdges = (source) => {
|
|
|
651
937
|
return clickConnectStartHandle();
|
|
652
938
|
},
|
|
653
939
|
get colorMode() {
|
|
654
|
-
return
|
|
940
|
+
return resolvedColorMode();
|
|
655
941
|
},
|
|
656
942
|
get connection() {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
943
|
+
return projectedConnection();
|
|
944
|
+
},
|
|
945
|
+
get connectionFromHandle() {
|
|
946
|
+
return connectionFromHandle();
|
|
947
|
+
},
|
|
948
|
+
get connectionTargetByHandle() {
|
|
949
|
+
return connectionTargetByHandle;
|
|
662
950
|
},
|
|
663
951
|
get domNode() {
|
|
664
952
|
return domNode();
|
|
@@ -667,10 +955,7 @@ const createLayoutedEdges = (source) => {
|
|
|
667
955
|
return dragging();
|
|
668
956
|
},
|
|
669
957
|
get edgeTypes() {
|
|
670
|
-
return
|
|
671
|
-
...initialEdgeTypes,
|
|
672
|
-
...this._edgeTypes
|
|
673
|
-
};
|
|
958
|
+
return mergedEdgeTypes();
|
|
674
959
|
},
|
|
675
960
|
get elementsSelectable() {
|
|
676
961
|
return elementsSelectable();
|
|
@@ -703,19 +988,16 @@ const createLayoutedEdges = (source) => {
|
|
|
703
988
|
return nodesDraggable();
|
|
704
989
|
},
|
|
705
990
|
get nodeTypes() {
|
|
706
|
-
return
|
|
707
|
-
...initialNodeTypes,
|
|
708
|
-
...this._nodeTypes
|
|
709
|
-
};
|
|
991
|
+
return mergedNodeTypes();
|
|
710
992
|
},
|
|
711
993
|
get panZoom() {
|
|
712
994
|
return panZoom();
|
|
713
995
|
},
|
|
714
996
|
get selectedNodes() {
|
|
715
|
-
return
|
|
997
|
+
return selectedNodesView();
|
|
716
998
|
},
|
|
717
999
|
get selectedEdges() {
|
|
718
|
-
return
|
|
1000
|
+
return selectedEdgesView();
|
|
719
1001
|
},
|
|
720
1002
|
get selectionRect() {
|
|
721
1003
|
return selectionRect();
|
|
@@ -830,33 +1112,11 @@ const createLayoutedEdges = (source) => {
|
|
|
830
1112
|
setNodesStore((nodes) => {
|
|
831
1113
|
for (let node of nodes) nodeDragItems.has(node.id) && (node.dragging = dragging, node.position = nodeDragItems.get(node.id).position);
|
|
832
1114
|
});
|
|
833
|
-
}, applyMeasurementWrites = (
|
|
834
|
-
setMeasurementsStore
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
} else draft[write.id] = {
|
|
839
|
-
measured: write.measured,
|
|
840
|
-
handleBounds: write.handleBounds
|
|
841
|
-
};
|
|
842
|
-
});
|
|
843
|
-
}, applyNodeChanges = (changes) => {
|
|
844
|
-
changes.length !== 0 && setNodesStore((nodes) => {
|
|
845
|
-
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
846
|
-
for (let change of changes) {
|
|
847
|
-
let node = nodeById.get(change.id);
|
|
848
|
-
if (node) switch (change.type) {
|
|
849
|
-
case "dimensions":
|
|
850
|
-
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
851
|
-
...node.measured,
|
|
852
|
-
...change.dimensions
|
|
853
|
-
};
|
|
854
|
-
break;
|
|
855
|
-
case "position": node.position = change.position ?? node.position;
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
});
|
|
859
|
-
}, markInitialNodesMeasured = () => {
|
|
1115
|
+
}, { applyMeasurementWrites, applyNodeChanges } = createMeasurementIngest({
|
|
1116
|
+
setMeasurementsStore,
|
|
1117
|
+
setNodesStore,
|
|
1118
|
+
nodes: () => nodesStore
|
|
1119
|
+
}), markInitialNodesMeasured = () => {
|
|
860
1120
|
initialNodesMeasured = !0, tryInitialFitView();
|
|
861
1121
|
}, requestMeasure = () => {}, setMeasureRequester = (fn) => {
|
|
862
1122
|
requestMeasure = fn;
|
|
@@ -871,66 +1131,16 @@ const createLayoutedEdges = (source) => {
|
|
|
871
1131
|
ease: options?.ease,
|
|
872
1132
|
interpolate: options?.interpolate
|
|
873
1133
|
}), Promise.resolve(!0)) : Promise.resolve(!1);
|
|
874
|
-
},
|
|
875
|
-
store
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
}), flush();
|
|
885
|
-
}, addSelectedNodes = (ids) => {
|
|
886
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
887
|
-
setNodesStore((nodes) => {
|
|
888
|
-
for (let node of nodes) {
|
|
889
|
-
let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
890
|
-
node.selected !== selected && (node.selected = selected);
|
|
891
|
-
}
|
|
892
|
-
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
893
|
-
}, addSelectedEdges = (ids) => {
|
|
894
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
895
|
-
setEdgesStore((edges) => {
|
|
896
|
-
for (let edge of edges) {
|
|
897
|
-
let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
898
|
-
edge.selected !== selected && (edge.selected = selected);
|
|
899
|
-
}
|
|
900
|
-
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
901
|
-
}, handleNodeSelection = (id, unselect, nodeRef) => {
|
|
902
|
-
let node = store.nodes.find((n) => n.id === id);
|
|
903
|
-
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
904
|
-
nodes: [node],
|
|
905
|
-
edges: []
|
|
906
|
-
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
907
|
-
}, handleEdgeSelection = (id) => {
|
|
908
|
-
let edge = edgeLookup[id];
|
|
909
|
-
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
910
|
-
nodes: [],
|
|
911
|
-
edges: [edge]
|
|
912
|
-
}) : addSelectedEdges([id]));
|
|
913
|
-
}, moveSelectedNodes = (direction, factor) => {
|
|
914
|
-
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;
|
|
915
|
-
for (let node of nodeLookup.values()) {
|
|
916
|
-
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
917
|
-
let nextPosition = {
|
|
918
|
-
x: node.internals.positionAbsolute.x + xDiff,
|
|
919
|
-
y: node.internals.positionAbsolute.y + yDiff
|
|
920
|
-
};
|
|
921
|
-
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
922
|
-
let { position } = calculateNodePosition({
|
|
923
|
-
nodeId: node.id,
|
|
924
|
-
nextPosition,
|
|
925
|
-
nodeLookup,
|
|
926
|
-
nodeExtent: store.nodeExtent,
|
|
927
|
-
nodeOrigin: store.nodeOrigin,
|
|
928
|
-
onError: store.onError
|
|
929
|
-
});
|
|
930
|
-
nodeUpdates.set(node.id, { position });
|
|
931
|
-
}
|
|
932
|
-
updateNodePositions(nodeUpdates);
|
|
933
|
-
}, panBy$1 = (delta) => panBy({
|
|
1134
|
+
}, stableSetViewport = (viewport) => setViewportStore(() => viewport), { unselectNodesAndEdges, addSelectedNodes, addSelectedEdges, handleNodeSelection, handleEdgeSelection, moveSelectedNodes } = createSelectionCommands({
|
|
1135
|
+
store,
|
|
1136
|
+
setNodesStore,
|
|
1137
|
+
setEdgesStore,
|
|
1138
|
+
setSelectionRect,
|
|
1139
|
+
setSelectionRectMode,
|
|
1140
|
+
nodeLookup,
|
|
1141
|
+
edgeLookup,
|
|
1142
|
+
updateNodePositions
|
|
1143
|
+
}), panBy$1 = (delta) => panBy({
|
|
934
1144
|
delta,
|
|
935
1145
|
panZoom: store.panZoom,
|
|
936
1146
|
transform: store.transform,
|
|
@@ -1007,8 +1217,27 @@ const createLayoutedEdges = (source) => {
|
|
|
1007
1217
|
get snapGrid() {
|
|
1008
1218
|
return store.snapGrid;
|
|
1009
1219
|
}
|
|
1010
|
-
},
|
|
1011
|
-
|
|
1220
|
+
}, intersectionGrid = null, intersectionRows = null, queryIntersectionCandidates = (rect) => untrack(() => {
|
|
1221
|
+
if (!intersectionGrid) {
|
|
1222
|
+
let grid = new SpatialGrid(300), rows = /* @__PURE__ */ new Map();
|
|
1223
|
+
for (let node of store.nodes) {
|
|
1224
|
+
let internalNode = nodeLookup.get(node.id);
|
|
1225
|
+
internalNode && (grid.insert(node.id, nodeToRect(internalNode)), rows.set(node.id, node));
|
|
1226
|
+
}
|
|
1227
|
+
intersectionGrid = grid, intersectionRows = rows, queueMicrotask(() => {
|
|
1228
|
+
intersectionGrid = null, intersectionRows = null;
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
let rows = intersectionRows, result = [];
|
|
1232
|
+
for (let id of intersectionGrid.queryRect(rect)) {
|
|
1233
|
+
let row = rows.get(id);
|
|
1234
|
+
row && result.push(row);
|
|
1235
|
+
}
|
|
1236
|
+
return result;
|
|
1237
|
+
}), getNodeRect = (node) => {
|
|
1238
|
+
let nodeToUse = isNode(node) ? node : nodeLookup.get(node.id);
|
|
1239
|
+
if (!nodeToUse) return null;
|
|
1240
|
+
let position = nodeToUse.parentId ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, store.nodeOrigin) : nodeToUse.position, nodeWithPosition = {
|
|
1012
1241
|
...nodeToUse,
|
|
1013
1242
|
position,
|
|
1014
1243
|
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
@@ -1062,7 +1291,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1062
1291
|
x,
|
|
1063
1292
|
y,
|
|
1064
1293
|
zoom
|
|
1065
|
-
], _snapGrid
|
|
1294
|
+
], !!_snapGrid, _snapGrid || [1, 1]);
|
|
1066
1295
|
},
|
|
1067
1296
|
flowToScreenPosition: (position) => {
|
|
1068
1297
|
if (!store.domNode) return position;
|
|
@@ -1126,14 +1355,18 @@ const createLayoutedEdges = (source) => {
|
|
|
1126
1355
|
let remainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
|
|
1127
1356
|
store.onNodesDelete?.(matchingNodes), setNodesStore(() => remainingNodes);
|
|
1128
1357
|
}
|
|
1129
|
-
|
|
1358
|
+
let deletedNodes = matchingNodes ?? [], deletedEdges = matchingEdges ?? [];
|
|
1359
|
+
return (deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
1360
|
+
nodes: deletedNodes,
|
|
1361
|
+
edges: deletedEdges
|
|
1362
|
+
}), {
|
|
1130
1363
|
deletedNodes: matchingNodes,
|
|
1131
1364
|
deletedEdges: matchingEdges
|
|
1132
1365
|
};
|
|
1133
1366
|
},
|
|
1134
1367
|
getIntersectingNodes: (nodeOrRect, partially = !0, nodesToIntersect) => {
|
|
1135
1368
|
let isRect = isRectObject(nodeOrRect), nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
1136
|
-
return nodeRect ? (nodesToIntersect
|
|
1369
|
+
return nodeRect ? (nodesToIntersect ?? queryIntersectionCandidates(nodeRect)).filter((n) => {
|
|
1137
1370
|
let internalNode = nodeLookup.get(n.id);
|
|
1138
1371
|
if (!internalNode || !isRect && n.id === nodeOrRect.id) return !1;
|
|
1139
1372
|
let currNodeRect = nodeToRect(internalNode), overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
@@ -1189,10 +1422,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1189
1422
|
extent: store.translateExtent
|
|
1190
1423
|
}), ({ panZoom, extent }) => {
|
|
1191
1424
|
panZoom?.setTranslateExtent(extent);
|
|
1192
|
-
}), createEffect(() => new Set(store.nodes.map((n) => n.id)), (currentIds) => {
|
|
1193
|
-
setMeasurementsStore((draft) => {
|
|
1194
|
-
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
1195
|
-
});
|
|
1196
1425
|
}), {
|
|
1197
1426
|
store,
|
|
1198
1427
|
flow,
|
|
@@ -1210,8 +1439,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1210
1439
|
applyNodeChanges,
|
|
1211
1440
|
markInitialNodesMeasured,
|
|
1212
1441
|
setMeasureRequester,
|
|
1213
|
-
resetStoreValues,
|
|
1214
|
-
setAriaLabelConfig,
|
|
1215
1442
|
setAriaLiveMessage,
|
|
1216
1443
|
setClickConnectStartHandle,
|
|
1217
1444
|
setConfig,
|
|
@@ -1219,15 +1446,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1219
1446
|
setDeleteKeyPressed,
|
|
1220
1447
|
setDomNode,
|
|
1221
1448
|
setDragging,
|
|
1222
|
-
|
|
1223
|
-
return setEdgesStore;
|
|
1224
|
-
},
|
|
1449
|
+
setEdges: setEdgesStore,
|
|
1225
1450
|
setElementsSelectable,
|
|
1226
1451
|
setHeight,
|
|
1227
1452
|
setMultiselectionKeyPressed,
|
|
1228
|
-
|
|
1229
|
-
return setNodesStore;
|
|
1230
|
-
},
|
|
1453
|
+
setNodes: setNodesStore,
|
|
1231
1454
|
setNodesConnectable,
|
|
1232
1455
|
setNodesDraggable,
|
|
1233
1456
|
setPanActivationKeyPressed,
|
|
@@ -1235,9 +1458,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1235
1458
|
setSelectionKeyPressed,
|
|
1236
1459
|
setSelectionRect,
|
|
1237
1460
|
setSelectionRectMode,
|
|
1238
|
-
|
|
1239
|
-
return (viewport) => setViewportStore(() => viewport);
|
|
1240
|
-
},
|
|
1461
|
+
setViewport: stableSetViewport,
|
|
1241
1462
|
setWidth,
|
|
1242
1463
|
setZoomActivationKeyPressed,
|
|
1243
1464
|
addEdge,
|
|
@@ -1246,7 +1467,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1246
1467
|
zoomOut,
|
|
1247
1468
|
fitView,
|
|
1248
1469
|
setCenter,
|
|
1249
|
-
setPaneClickDistance,
|
|
1250
1470
|
unselectNodesAndEdges,
|
|
1251
1471
|
addSelectedNodes,
|
|
1252
1472
|
addSelectedEdges,
|
|
@@ -1258,25 +1478,28 @@ const createLayoutedEdges = (source) => {
|
|
|
1258
1478
|
reset
|
|
1259
1479
|
}
|
|
1260
1480
|
};
|
|
1481
|
+
}, createEdgeStore = (edges) => {
|
|
1482
|
+
let [store, setStore] = typeof edges == "function" ? createStore(edges, []) : createStore(edges);
|
|
1483
|
+
return [store, setStore];
|
|
1261
1484
|
}, createNodeStore = (nodes) => {
|
|
1262
|
-
let [store, setStore] = createStore(nodes);
|
|
1485
|
+
let [store, setStore] = typeof nodes == "function" ? createStore(nodes, []) : createStore(nodes);
|
|
1263
1486
|
return [store, setStore];
|
|
1264
1487
|
}, EdgeWrapper = (props) => {
|
|
1265
|
-
let edgeRef, { store, actions } = useInternalSolidFlow(), edgeId = () => props.edgeId, edge = () => actions.getEdge(edgeId()), edgeType = () => edge().type ?? "default", selectable = () => edge()
|
|
1488
|
+
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) => {
|
|
1266
1489
|
selectable() && actions.handleEdgeSelection(edgeId()), props.onEdgeClick?.({
|
|
1267
1490
|
edge: edge(),
|
|
1268
1491
|
event
|
|
1269
1492
|
});
|
|
1270
|
-
},
|
|
1271
|
-
(
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
}, onKeyDown = (event) => {
|
|
1493
|
+
}, onContextMenu = (event) => props.onEdgeContextMenu?.({
|
|
1494
|
+
edge: edge(),
|
|
1495
|
+
event
|
|
1496
|
+
}), onPointerEnter = (event) => props.onEdgePointerEnter?.({
|
|
1497
|
+
edge: edge(),
|
|
1498
|
+
event
|
|
1499
|
+
}), onPointerLeave = (event) => props.onEdgePointerLeave?.({
|
|
1500
|
+
edge: edge(),
|
|
1501
|
+
event
|
|
1502
|
+
}), onKeyDown = (event) => {
|
|
1280
1503
|
store.disableKeyboardA11y || !elementSelectionKeys.includes(event.key) || !selectable() || (event.key === "Escape" ? actions.unselectNodesAndEdges({ edges: [edge()] }) : actions.addSelectedEdges([edge().id]));
|
|
1281
1504
|
}, ariaLabel = () => edge().ariaLabel ?? `Edge from ${edge().source} to ${edge().target}`, culled = createMemo(() => isEdgeCulled(edge(), store.cullingViewport));
|
|
1282
1505
|
return <EdgeIdContext value={edgeId}>
|
|
@@ -1295,7 +1518,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1295
1518
|
selectable: !!selectable()
|
|
1296
1519
|
},
|
|
1297
1520
|
edge().class
|
|
1298
|
-
]} onClick={onClick} onKeyDown={(e) => focusable() && onKeyDown(e)} onContextMenu={
|
|
1521
|
+
]} onClick={onClick} onKeyDown={(e) => focusable() && onKeyDown(e)} onContextMenu={onContextMenu} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave} {...edge().domAttributes}>
|
|
1299
1522
|
<Dynamic component={edgeComponent()} id={edge().id} source={edge().source} target={edge().target} sourceX={edge().sourceX} sourceY={edge().sourceY} targetX={edge().targetX} targetY={edge().targetY} sourcePosition={edge().sourcePosition} targetPosition={edge().targetPosition} animated={edge().animated} selected={edge().selected} label={edge().label} labelStyle={edge().labelStyle} data={edge().data} style={edge().style} interactionWidth={edge().interactionWidth} selectable={selectable()} deletable={edge().deletable ?? !0} type={edgeType()} sourceHandleId={edge().sourceHandle} targetHandleId={edge().targetHandle} markerStart={markerStartUrl()} markerEnd={markerEndUrl()} />
|
|
1300
1523
|
</g>
|
|
1301
1524
|
</svg>
|
|
@@ -1419,7 +1642,10 @@ const Handle = (props) => {
|
|
|
1419
1642
|
position: "top",
|
|
1420
1643
|
isConnectableStart: !0,
|
|
1421
1644
|
isConnectableEnd: !0
|
|
1422
|
-
}), { 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.
|
|
1645
|
+
}), { 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 = () => {
|
|
1646
|
+
let fromHandle = store.connectionFromHandle;
|
|
1647
|
+
return fromHandle && fromHandle.nodeId === nodeId() && fromHandle.type === _props.type && fromHandle.id === handleId();
|
|
1648
|
+
}, 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;
|
|
1423
1649
|
createEffect(() => {
|
|
1424
1650
|
if (!_props.onConnect && !_props.onDisconnect) return null;
|
|
1425
1651
|
let rec = connections[connectionKey(nodeId(), _props.type, _props.id)], map = /* @__PURE__ */ new Map();
|
|
@@ -1437,13 +1663,20 @@ const Handle = (props) => {
|
|
|
1437
1663
|
}, edge = store.onBeforeConnect?.(handleConnection) ?? handleConnection;
|
|
1438
1664
|
actions.addEdge(edge), store.onConnect?.(handleConnection);
|
|
1439
1665
|
}, onPointerDown = (event) => {
|
|
1666
|
+
let gestureLookup = armConnectionGestureLookup({
|
|
1667
|
+
event,
|
|
1668
|
+
real: nodeLookup,
|
|
1669
|
+
domNode: store.domNode,
|
|
1670
|
+
getTransform: () => store.transform,
|
|
1671
|
+
connectionRadius: store.connectionRadius
|
|
1672
|
+
});
|
|
1440
1673
|
XYHandle.onPointerDown(event, {
|
|
1441
1674
|
handleId: handleId(),
|
|
1442
1675
|
nodeId: nodeId(),
|
|
1443
1676
|
isTarget: isTarget(),
|
|
1444
1677
|
connectionRadius: store.connectionRadius,
|
|
1445
1678
|
domNode: store.domNode,
|
|
1446
|
-
nodeLookup,
|
|
1679
|
+
nodeLookup: gestureLookup,
|
|
1447
1680
|
connectionMode: store.connectionMode,
|
|
1448
1681
|
lib: store.lib,
|
|
1449
1682
|
autoPanOnConnect: store.autoPanOnConnect,
|
|
@@ -1628,12 +1861,11 @@ const NodeWrapper = (props) => {
|
|
|
1628
1861
|
...h ? { height: toPxString(h) } : {}
|
|
1629
1862
|
};
|
|
1630
1863
|
}, culled = createMemo(() => isNodeCulled(node(), store.cullingViewport)), style = () => ({
|
|
1864
|
+
...sizeStyle(),
|
|
1631
1865
|
"z-index": node().internals.z,
|
|
1632
1866
|
transform: transform(),
|
|
1633
1867
|
visibility: culled() || !nodeHasDimensions(node()) ? "hidden" : "visible",
|
|
1634
|
-
"pointer-events": culled() ? "none" : void 0
|
|
1635
|
-
...sizeStyle(),
|
|
1636
|
-
...node().style ?? {}
|
|
1868
|
+
"pointer-events": culled() ? "none" : void 0
|
|
1637
1869
|
});
|
|
1638
1870
|
createEffect(() => ({
|
|
1639
1871
|
valid: nodeTypeValid(),
|
|
@@ -1893,7 +2125,7 @@ const InitialNodeTypesMap = {
|
|
|
1893
2125
|
pendingEntries = updateEntries, scheduleIdleCallback(() => {
|
|
1894
2126
|
let updates = new Map(pendingEntries);
|
|
1895
2127
|
pendingEntries = void 0;
|
|
1896
|
-
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode);
|
|
2128
|
+
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode, store.nodeExtent);
|
|
1897
2129
|
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());
|
|
1898
2130
|
});
|
|
1899
2131
|
};
|
|
@@ -2043,7 +2275,7 @@ const ConnectionLine = (props) => {
|
|
|
2043
2275
|
for (let item of a) if (!b.has(item)) return !1;
|
|
2044
2276
|
return !0;
|
|
2045
2277
|
}, Pane = (props) => {
|
|
2046
|
-
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 = {
|
|
2278
|
+
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 = {
|
|
2047
2279
|
x: 0,
|
|
2048
2280
|
y: 0
|
|
2049
2281
|
}, 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) => {
|
|
@@ -2058,7 +2290,7 @@ const ConnectionLine = (props) => {
|
|
|
2058
2290
|
if (event.pointerType === "touch" && _panOnDrag() !== !1 && !store.selectionKeyPressed || (containerBounds = container?.getBoundingClientRect() ?? null, !containerBounds)) return;
|
|
2059
2291
|
let eventTargetIsContainer = event.target === container, isNoKeyEvent = !eventTargetIsContainer && !!event.target.closest(".nokey"), isSelectionActive = props.selectionOnDrag && eventTargetIsContainer || store.selectionKeyPressed;
|
|
2060
2292
|
if (isNoKeyEvent || !isSelecting() || !isSelectionActive || event.button !== 0 || !event.isPrimary) return;
|
|
2061
|
-
event.target?.setPointerCapture?.(event.pointerId), selectionInProgress = !1, autoPanStarted = !1;
|
|
2293
|
+
event.target?.setPointerCapture?.(event.pointerId), selectionSpatialLookup.arm((node) => nodeToRect(node)), selectionInProgress = !1, autoPanStarted = !1;
|
|
2062
2294
|
let { x, y } = getEventPosition(event, containerBounds), userSelectionFlowOrigin = pointToRendererPoint({
|
|
2063
2295
|
x,
|
|
2064
2296
|
y
|
|
@@ -2085,14 +2317,21 @@ const ConnectionLine = (props) => {
|
|
|
2085
2317
|
width: Math.abs(mouseX - screenStart.x),
|
|
2086
2318
|
height: Math.abs(mouseY - screenStart.y)
|
|
2087
2319
|
}, prevSelectedNodeIds = selectedNodeIds, prevSelectedEdgeIds = selectedEdgeIds;
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2320
|
+
{
|
|
2321
|
+
let [tx, ty, zoom] = store.transform;
|
|
2322
|
+
selectionSpatialLookup.setQueryRect({
|
|
2323
|
+
x: (nextUserSelectRect.x - tx) / zoom,
|
|
2324
|
+
y: (nextUserSelectRect.y - ty) / zoom,
|
|
2325
|
+
width: nextUserSelectRect.width / zoom,
|
|
2326
|
+
height: nextUserSelectRect.height / zoom
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2329
|
+
selectedNodeIds = new Set(getNodesInside(selectionSpatialLookup, nextUserSelectRect, store.transform, store.selectionMode === SelectionMode$1.Partial, !0).map((n) => n.id)), selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
2091
2330
|
for (let nodeId of selectedNodeIds) {
|
|
2092
2331
|
let nodeConnections = connections[nodeId];
|
|
2093
2332
|
if (nodeConnections) for (let { edgeId } of Object.values(nodeConnections)) {
|
|
2094
2333
|
let edge = edgeLookup[edgeId];
|
|
2095
|
-
edge && (edge
|
|
2334
|
+
edge && isEdgeSelectable(edge, store) && selectedEdgeIds.add(edgeId);
|
|
2096
2335
|
}
|
|
2097
2336
|
}
|
|
2098
2337
|
isSetEqual(prevSelectedNodeIds, selectedNodeIds) || actions.setNodes((nodes) => {
|
|
@@ -2273,7 +2512,7 @@ const ConnectionLine = (props) => {
|
|
|
2273
2512
|
<div class="solid-flow__selection" style={styles()} />
|
|
2274
2513
|
</Show>;
|
|
2275
2514
|
}, NodeSelection = (props) => {
|
|
2276
|
-
let { store, nodeLookup, actions } = useInternalSolidFlow(), [ref, setRef] = createSignal(), bounds = () => store.selectionRectMode === "nodes" ? getInternalNodesBounds(nodeLookup, { filter: (node) => !!node.selected }) : null;
|
|
2515
|
+
let { store, nodeLookup, actions } = useInternalSolidFlow(), [ref, setRef] = createSignal(), bounds = createMemo(() => store.selectionRectMode === "nodes" ? getInternalNodesBounds(nodeLookup, { filter: (node) => !!node.selected }) : null);
|
|
2277
2516
|
createEffect(() => ({
|
|
2278
2517
|
el: ref(),
|
|
2279
2518
|
focusable: !store.disableKeyboardA11y
|
|
@@ -2281,13 +2520,13 @@ const ConnectionLine = (props) => {
|
|
|
2281
2520
|
focusable && el?.focus({ preventScroll: !0 });
|
|
2282
2521
|
});
|
|
2283
2522
|
let onContextMenu = (event) => {
|
|
2284
|
-
let selectedNodes = store.
|
|
2523
|
+
let selectedNodes = store.selectedNodes;
|
|
2285
2524
|
props.onSelectionContextMenu?.({
|
|
2286
2525
|
nodes: selectedNodes,
|
|
2287
2526
|
event
|
|
2288
2527
|
});
|
|
2289
2528
|
}, onClick = (event) => {
|
|
2290
|
-
let selectedNodes = store.
|
|
2529
|
+
let selectedNodes = store.selectedNodes;
|
|
2291
2530
|
props.onSelectionClick?.({
|
|
2292
2531
|
nodes: selectedNodes,
|
|
2293
2532
|
event
|
|
@@ -2452,14 +2691,11 @@ const KeyHandler = (props) => {
|
|
|
2452
2691
|
}, handleWindowBlur = () => {
|
|
2453
2692
|
resetKeysAndSelection(), cancelPointerGestures();
|
|
2454
2693
|
}, handleDelete = async () => {
|
|
2455
|
-
let selectedNodes = store.
|
|
2694
|
+
let selectedNodes = store.selectedNodes, selectedEdges = store.selectedEdges;
|
|
2695
|
+
await deleteElements({
|
|
2456
2696
|
nodes: selectedNodes,
|
|
2457
2697
|
edges: selectedEdges
|
|
2458
2698
|
});
|
|
2459
|
-
(deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
2460
|
-
nodes: deletedNodes,
|
|
2461
|
-
edges: deletedEdges
|
|
2462
|
-
});
|
|
2463
2699
|
};
|
|
2464
2700
|
return isServer || (createEventListenerMap(window, {
|
|
2465
2701
|
keydown: (event) => {
|
|
@@ -2477,34 +2713,23 @@ const KeyHandler = (props) => {
|
|
|
2477
2713
|
capture: !0,
|
|
2478
2714
|
passive: !0
|
|
2479
2715
|
})), null;
|
|
2480
|
-
}, SolidFlow = (props) => {
|
|
2716
|
+
}, 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("."), SolidFlow = (props) => {
|
|
2481
2717
|
let [domNodeRef, setDomNodeRef] = createSignal(), domNode, _props = merge({
|
|
2482
2718
|
...getDefaultFlowStateProps(),
|
|
2483
2719
|
colorMode: "light",
|
|
2484
|
-
deleteKeyCode: "Backspace",
|
|
2485
|
-
defaultViewport: {
|
|
2486
|
-
x: 0,
|
|
2487
|
-
y: 0,
|
|
2488
|
-
zoom: 1
|
|
2489
|
-
},
|
|
2490
|
-
multiSelectionKeyCode: isMacOs() ? "Meta" : "Control",
|
|
2491
2720
|
nodeClickDistance: 0,
|
|
2492
2721
|
panOnScroll: !1,
|
|
2493
|
-
panActivationKeyCode: "Space",
|
|
2494
2722
|
preventScrolling: !0,
|
|
2495
2723
|
panOnDrag: !0,
|
|
2496
2724
|
panOnScrollSpeed: .5,
|
|
2497
2725
|
panOnScrollMode: "free",
|
|
2498
2726
|
paneClickDistance: 0,
|
|
2499
|
-
reconnectRadius: 10,
|
|
2500
|
-
selectionKeyCode: "Shift",
|
|
2501
2727
|
selectionOnDrag: !1,
|
|
2502
2728
|
translateExtent: infiniteExtent,
|
|
2503
|
-
zoomActivationKeyCode: isMacOs() ? "Meta" : "Control",
|
|
2504
2729
|
zoomOnPinch: !0,
|
|
2505
2730
|
zoomOnDoubleClick: !0,
|
|
2506
2731
|
zoomOnScroll: !0
|
|
2507
|
-
}, props), htmlProps = omit(_props,
|
|
2732
|
+
}, props), htmlProps = omit(_props, ...FLOW_PROP_KEYS, "children"), TypedSolidFlowContext = SolidFlowContext, solidFlow = useContext(TypedSolidFlowContext) ?? createSolidFlow(_props), { store, actions } = solidFlow;
|
|
2508
2733
|
onSettled(() => (actions.applyInitialFitView(_props.fitView), actions.setConfig(_props), actions.setDomNode(domNode), () => {
|
|
2509
2734
|
actions.reset();
|
|
2510
2735
|
})), createEffect(() => domNodeRef(), (el) => {
|
|
@@ -2513,11 +2738,6 @@ const KeyHandler = (props) => {
|
|
|
2513
2738
|
actions.setWidth(el.clientWidth), actions.setHeight(el.clientHeight);
|
|
2514
2739
|
});
|
|
2515
2740
|
return observer.observe(el), () => observer.disconnect();
|
|
2516
|
-
}), createEffect(() => ({
|
|
2517
|
-
panZoom: store.panZoom,
|
|
2518
|
-
distance: _props.paneClickDistance
|
|
2519
|
-
}), ({ panZoom, distance }) => {
|
|
2520
|
-
panZoom?.setClickDistance(distance);
|
|
2521
2741
|
});
|
|
2522
2742
|
let selectedElements = createMemo(() => ({
|
|
2523
2743
|
nodes: store.selectedNodes,
|
|
@@ -2526,7 +2746,7 @@ const KeyHandler = (props) => {
|
|
|
2526
2746
|
createEffect(() => selectedElements(), (params) => {
|
|
2527
2747
|
untrack(() => _props.onSelectionChange)?.(params);
|
|
2528
2748
|
});
|
|
2529
|
-
let rootStyle = () => ({
|
|
2749
|
+
let asyncSeedGuard = () => (_props.nodes?.length, _props.edges?.length, null), rootStyle = () => ({
|
|
2530
2750
|
width: toPxString(_props.width),
|
|
2531
2751
|
height: toPxString(_props.height),
|
|
2532
2752
|
..._props.style
|
|
@@ -2546,12 +2766,13 @@ const KeyHandler = (props) => {
|
|
|
2546
2766
|
});
|
|
2547
2767
|
}} {...htmlProps}>
|
|
2548
2768
|
<TypedSolidFlowContext value={solidFlow}>
|
|
2769
|
+
{asyncSeedGuard()}
|
|
2549
2770
|
<KeyHandler selectionKey={_props.selectionKey} deleteKey={_props.deleteKey} panActivationKey={_props.panActivationKey} multiSelectionKey={_props.multiSelectionKey} zoomActivationKey={_props.zoomActivationKey} />
|
|
2550
2771
|
<Zoom panOnScrollMode={_props.panOnScrollMode} preventScrolling={_props.preventScrolling} zoomOnScroll={_props.zoomOnScroll} zoomOnDoubleClick={_props.zoomOnDoubleClick} zoomOnPinch={_props.zoomOnPinch} panOnScroll={_props.panOnScroll} panOnScrollSpeed={_props.panOnScrollSpeed} panOnDrag={_props.panOnDrag} paneClickDistance={_props.paneClickDistance} selectionOnDrag={_props.selectionOnDrag} onMoveStart={_props.onMoveStart} onMove={_props.onMove} onMoveEnd={_props.onMoveEnd} onViewportInitialized={_props.onInit} initialViewport={_props.viewport || _props.initialViewport}>
|
|
2551
2772
|
<Pane onPaneClick={_props.onPaneClick} onPaneContextMenu={_props.onPaneContextMenu} onSelectionStart={_props.onSelectionStart} onSelectionEnd={_props.onSelectionEnd} panOnDrag={_props.panOnDrag} selectionOnDrag={_props.selectionOnDrag} paneClickDistance={_props.paneClickDistance} autoPanOnSelection={_props.autoPanOnSelection}>
|
|
2552
2773
|
<Viewport>
|
|
2553
2774
|
<div class="solid-flow__container solid-flow__viewport-back" />
|
|
2554
|
-
<EdgeRenderer
|
|
2775
|
+
<EdgeRenderer onEdgeClick={_props.onEdgeClick} onEdgeContextMenu={_props.onEdgeContextMenu} onEdgePointerEnter={_props.onEdgePointerEnter} onEdgePointerLeave={_props.onEdgePointerLeave} />
|
|
2555
2776
|
<div class="solid-flow__container solid-flow__edge-labels" />
|
|
2556
2777
|
<ConnectionLine type={_props.connectionLineType} component={_props.connectionLineComponent} containerStyle={_props.connectionLineContainerStyle} style={_props.connectionLineStyle} />
|
|
2557
2778
|
<NodeRenderer nodeClickDistance={_props.nodeClickDistance} onNodeClick={_props.onNodeClick} onNodeContextMenu={_props.onNodeContextMenu} onNodePointerEnter={_props.onNodePointerEnter} onNodePointerMove={_props.onNodePointerMove} onNodePointerLeave={_props.onNodePointerLeave} onNodeDrag={_props.onNodeDrag} onNodeDragStart={_props.onNodeDragStart} onNodeDragStop={_props.onNodeDragStop} />
|
|
@@ -2875,24 +3096,23 @@ const DotPattern = (props) => {
|
|
|
2875
3096
|
nodeBorderRadius: 5,
|
|
2876
3097
|
nodeStrokeWidth: 2,
|
|
2877
3098
|
style: {}
|
|
2878
|
-
}), 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 =
|
|
3099
|
+
}), 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(() => ({
|
|
2879
3100
|
x: -store.viewport.x / store.viewport.zoom,
|
|
2880
3101
|
y: -store.viewport.y / store.viewport.zoom,
|
|
2881
3102
|
width: store.width / store.viewport.zoom,
|
|
2882
3103
|
height: store.height / store.viewport.zoom
|
|
2883
|
-
}),
|
|
2884
|
-
let
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
3104
|
+
})), boundingRect = createMemo(() => {
|
|
3105
|
+
let view = viewBB();
|
|
3106
|
+
if (nodeLookup.size === 0) return view;
|
|
3107
|
+
let bounds = getInternalNodesBounds(nodeLookup);
|
|
3108
|
+
return !Number.isFinite(bounds.x) || !Number.isFinite(bounds.width) ? view : getBoundsOfRects(bounds, view);
|
|
3109
|
+
}), viewScale = createMemo(() => Math.max(boundingRect().width / _props.width, boundingRect().height / _props.height)), getViewWidth = () => viewScale() * _props.width, getViewHeight = () => viewScale() * _props.height, getOffset = () => 5 * viewScale(), getX = () => {
|
|
3110
|
+
let rect = boundingRect();
|
|
3111
|
+
return rect.x - (getViewWidth() - rect.width) / 2 - getOffset();
|
|
2889
3112
|
}, getY = () => {
|
|
2890
|
-
let
|
|
2891
|
-
return
|
|
2892
|
-
}, getViewboxWidth = () => getViewWidth() + getOffset() * 2, getViewboxHeight = () => getViewHeight() + getOffset() * 2, strokeWidth = () => _props.maskStrokeWidth ? _props.maskStrokeWidth *
|
|
2893
|
-
let currentNodeIds = store.nodes.map((node) => node.id), currentSet = new Set(currentNodeIds);
|
|
2894
|
-
return (prevNodeIds.length !== currentNodeIds.length || !prevNodeIds.every((id) => currentSet.has(id))) && (prevNodeIds = currentNodeIds), prevNodeIds;
|
|
2895
|
-
};
|
|
3113
|
+
let rect = boundingRect();
|
|
3114
|
+
return rect.y - (getViewHeight() - rect.height) / 2 - getOffset();
|
|
3115
|
+
}, 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]) });
|
|
2896
3116
|
return <Panel position={_props.position} data-testid="solid-flow__minimap" class={["solid-flow__minimap", _props.class]} style={{
|
|
2897
3117
|
"--xy-minimap-background-color-props": _props.bgColor,
|
|
2898
3118
|
..._props.style
|
|
@@ -2909,7 +3129,7 @@ const DotPattern = (props) => {
|
|
|
2909
3129
|
domNode: el,
|
|
2910
3130
|
panZoom,
|
|
2911
3131
|
getTransform: () => store.transform,
|
|
2912
|
-
getViewScale
|
|
3132
|
+
getViewScale: viewScale
|
|
2913
3133
|
});
|
|
2914
3134
|
return setMinimap(instance), () => {
|
|
2915
3135
|
instance.destroy();
|
|
@@ -2949,12 +3169,12 @@ const DotPattern = (props) => {
|
|
|
2949
3169
|
{(nodeId) => {
|
|
2950
3170
|
let node = createMemo(() => nodeLookup.get(nodeId())), nodeVisible = () => !!(node() && nodeHasDimensions(node()) && !node().hidden);
|
|
2951
3171
|
return <Show when={nodeVisible() && getNodeDimensions(node())}>
|
|
2952
|
-
{(nodeDimensions) => <Dynamic component={_props.nodeComponent ?? MiniMapNode} id={nodeId()} x={node().internals.positionAbsolute.x} y={node().internals.positionAbsolute.y} borderRadius={_props.nodeBorderRadius} strokeWidth={_props.nodeStrokeWidth} shapeRendering={shapeRendering
|
|
3172
|
+
{(nodeDimensions) => <Dynamic component={_props.nodeComponent ?? MiniMapNode} id={nodeId()} x={node().internals.positionAbsolute.x} y={node().internals.positionAbsolute.y} borderRadius={_props.nodeBorderRadius} strokeWidth={_props.nodeStrokeWidth} shapeRendering={shapeRendering} width={nodeDimensions().width} height={nodeDimensions().height} selected={node().selected} color={nodeColorFunc()?.call(null, node())} strokeColor={nodeStrokeColorFunc().call(null, node())} class={nodeClassFunc().call(null, node())} style={node().style} onClick={_props.onNodeClick ? onSvgNodeClick : void 0} />}
|
|
2953
3173
|
</Show>;
|
|
2954
3174
|
}}
|
|
2955
3175
|
</For>
|
|
2956
3176
|
<path class="solid-flow__minimap-mask" d={`M${getX() - getOffset()},${getY() - getOffset()}h${getViewboxWidth() + getOffset() * 2}v${getViewboxHeight() + getOffset() * 2}h${-getViewboxWidth() - getOffset() * 2}z
|
|
2957
|
-
M${
|
|
3177
|
+
M${viewBB().x},${viewBB().y}h${viewBB().width}v${viewBB().height}h${-viewBB().width}z`} fill-rule="evenodd" pointer-events="none" />
|
|
2958
3178
|
</svg>;
|
|
2959
3179
|
}}
|
|
2960
3180
|
</Show>
|