@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.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;
|
|
@@ -271,8 +516,6 @@ const getEdgeId = (connection) => {
|
|
|
271
516
|
}, cullingViewport);
|
|
272
517
|
}, getDefaultFlowStateProps = () => ({
|
|
273
518
|
id: "1",
|
|
274
|
-
nodes: [],
|
|
275
|
-
edges: [],
|
|
276
519
|
nodeOrigin: [0, 0],
|
|
277
520
|
nodeExtent: infiniteExtent,
|
|
278
521
|
defaultEdgeOptions: {},
|
|
@@ -371,14 +614,48 @@ var RecordMapFacade = class {
|
|
|
371
614
|
}
|
|
372
615
|
};
|
|
373
616
|
//#endregion
|
|
374
|
-
//#region src/core/
|
|
617
|
+
//#region src/core/measurementIngest.ts
|
|
375
618
|
/**
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
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.
|
|
380
624
|
*/
|
|
381
|
-
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(() => {
|
|
382
659
|
let out = {}, add = (key, entry, connection) => {
|
|
383
660
|
(out[key] ??= {})[entry] = connection;
|
|
384
661
|
};
|
|
@@ -443,10 +720,6 @@ const EMPTY_AUTO_INDEX = /* @__PURE__ */ new Map(), createInternalNodes = (sourc
|
|
|
443
720
|
}, row.internals.z = z;
|
|
444
721
|
} else source.nodes.length;
|
|
445
722
|
}
|
|
446
|
-
if (userNode.parentId) {
|
|
447
|
-
let parent = entryById.get(userNode.parentId);
|
|
448
|
-
parent?.store.row.internals.positionAbsolute.x, parent?.store.row.internals.z;
|
|
449
|
-
}
|
|
450
723
|
return { row };
|
|
451
724
|
}, {}, { key: "id" }), entry = {
|
|
452
725
|
store,
|
|
@@ -515,8 +788,8 @@ const createLayoutedEdges = (source) => {
|
|
|
515
788
|
let rowStores = mapArray(() => source.edges, (edgeAccessor) => ({
|
|
516
789
|
id: edgeAccessor().id,
|
|
517
790
|
store: createProjection(() => {
|
|
518
|
-
let edge = edgeAccessor()
|
|
519
|
-
return
|
|
791
|
+
let edge = edgeAccessor();
|
|
792
|
+
return { row: buildRow(source, edge) };
|
|
520
793
|
}, { row: null }, { key: "id" })
|
|
521
794
|
}), { keyed: (edge) => edge.id }), assigned = /* @__PURE__ */ new Map();
|
|
522
795
|
return createProjection((draft) => {
|
|
@@ -532,7 +805,7 @@ const createLayoutedEdges = (source) => {
|
|
|
532
805
|
});
|
|
533
806
|
}, buildRow = (source, edge) => {
|
|
534
807
|
let sourceNode = source.nodeLookup.get(edge.source), targetNode = source.nodeLookup.get(edge.target);
|
|
535
|
-
if (!sourceNode || !targetNode) return
|
|
808
|
+
if (!sourceNode || !targetNode) return null;
|
|
536
809
|
let edgePosition = getEdgePosition({
|
|
537
810
|
id: edge.id,
|
|
538
811
|
sourceNode,
|
|
@@ -562,7 +835,33 @@ const createLayoutedEdges = (source) => {
|
|
|
562
835
|
let out = {};
|
|
563
836
|
for (let node of source.nodes) node.parentId && (out[node.parentId] = !0);
|
|
564
837
|
return out;
|
|
565
|
-
}, {}, { 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) => {
|
|
566
865
|
if (fitView && !initialViewport && width && height) {
|
|
567
866
|
let bounds = getInternalNodesBounds(nodeLookup, { filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)) });
|
|
568
867
|
return getViewportForBounds$1(bounds, width, height, .5, 2, .1);
|
|
@@ -573,7 +872,7 @@ const createLayoutedEdges = (source) => {
|
|
|
573
872
|
zoom: 1
|
|
574
873
|
};
|
|
575
874
|
}, createFlowState = (props, injections = {}) => {
|
|
576
|
-
let _props = merge(getDefaultFlowStateProps(), props), initialNodeTypes = injections.initialNodeTypes ?? {}, initialEdgeTypes = injections.initialEdgeTypes ?? {}, prefersDark = injections.prefersDark ?? (() => _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props),
|
|
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,19 +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
|
-
for (let node of next);
|
|
599
|
-
return { next };
|
|
600
|
-
}, ({ next }) => {
|
|
601
|
-
setNodesStore(() => next);
|
|
602
|
-
}, { defer: !0 }), createEffect(() => {
|
|
603
|
-
let next = config().edges;
|
|
604
|
-
for (let edge of next);
|
|
605
|
-
return { next };
|
|
606
|
-
}, ({ next }) => {
|
|
607
|
-
setEdgesStore(() => next);
|
|
608
|
-
}, { defer: !0 }), createEffect(() => config().viewport, (next) => {
|
|
895
|
+
createEffect(() => config().viewport, (next) => {
|
|
609
896
|
next && setViewportStore(() => next);
|
|
610
897
|
}, { defer: !0 });
|
|
611
898
|
let transform = createMemo(() => [
|
|
@@ -617,25 +904,29 @@ const createLayoutedEdges = (source) => {
|
|
|
617
904
|
if (nodes.length === 0) return !1;
|
|
618
905
|
for (let node of nodes) if (!node.hidden && (node.measured?.width === void 0 || node.measured?.height === void 0)) return !1;
|
|
619
906
|
return !0;
|
|
620
|
-
}),
|
|
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({
|
|
621
927
|
width: 0,
|
|
622
928
|
height: 0
|
|
623
929
|
}, config, {
|
|
624
|
-
get _colorMode() {
|
|
625
|
-
return config().colorMode;
|
|
626
|
-
},
|
|
627
|
-
get _colorModeSSR() {
|
|
628
|
-
return config().colorModeSSR;
|
|
629
|
-
},
|
|
630
|
-
get _connection() {
|
|
631
|
-
return connection();
|
|
632
|
-
},
|
|
633
|
-
get _nodeTypes() {
|
|
634
|
-
return config().nodeTypes;
|
|
635
|
-
},
|
|
636
|
-
get _edgeTypes() {
|
|
637
|
-
return config().edgeTypes;
|
|
638
|
-
},
|
|
639
930
|
get ariaLabelConfig() {
|
|
640
931
|
return ariaLabelConfig();
|
|
641
932
|
},
|
|
@@ -646,14 +937,16 @@ const createLayoutedEdges = (source) => {
|
|
|
646
937
|
return clickConnectStartHandle();
|
|
647
938
|
},
|
|
648
939
|
get colorMode() {
|
|
649
|
-
return
|
|
940
|
+
return resolvedColorMode();
|
|
650
941
|
},
|
|
651
942
|
get connection() {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
943
|
+
return projectedConnection();
|
|
944
|
+
},
|
|
945
|
+
get connectionFromHandle() {
|
|
946
|
+
return connectionFromHandle();
|
|
947
|
+
},
|
|
948
|
+
get connectionTargetByHandle() {
|
|
949
|
+
return connectionTargetByHandle;
|
|
657
950
|
},
|
|
658
951
|
get domNode() {
|
|
659
952
|
return domNode();
|
|
@@ -662,10 +955,7 @@ const createLayoutedEdges = (source) => {
|
|
|
662
955
|
return dragging();
|
|
663
956
|
},
|
|
664
957
|
get edgeTypes() {
|
|
665
|
-
return
|
|
666
|
-
...initialEdgeTypes,
|
|
667
|
-
...this._edgeTypes
|
|
668
|
-
};
|
|
958
|
+
return mergedEdgeTypes();
|
|
669
959
|
},
|
|
670
960
|
get elementsSelectable() {
|
|
671
961
|
return elementsSelectable();
|
|
@@ -698,19 +988,16 @@ const createLayoutedEdges = (source) => {
|
|
|
698
988
|
return nodesDraggable();
|
|
699
989
|
},
|
|
700
990
|
get nodeTypes() {
|
|
701
|
-
return
|
|
702
|
-
...initialNodeTypes,
|
|
703
|
-
...this._nodeTypes
|
|
704
|
-
};
|
|
991
|
+
return mergedNodeTypes();
|
|
705
992
|
},
|
|
706
993
|
get panZoom() {
|
|
707
994
|
return panZoom();
|
|
708
995
|
},
|
|
709
996
|
get selectedNodes() {
|
|
710
|
-
return
|
|
997
|
+
return selectedNodesView();
|
|
711
998
|
},
|
|
712
999
|
get selectedEdges() {
|
|
713
|
-
return
|
|
1000
|
+
return selectedEdgesView();
|
|
714
1001
|
},
|
|
715
1002
|
get selectionRect() {
|
|
716
1003
|
return selectionRect();
|
|
@@ -825,33 +1112,11 @@ const createLayoutedEdges = (source) => {
|
|
|
825
1112
|
setNodesStore((nodes) => {
|
|
826
1113
|
for (let node of nodes) nodeDragItems.has(node.id) && (node.dragging = dragging, node.position = nodeDragItems.get(node.id).position);
|
|
827
1114
|
});
|
|
828
|
-
}, applyMeasurementWrites = (
|
|
829
|
-
setMeasurementsStore
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
} else draft[write.id] = {
|
|
834
|
-
measured: write.measured,
|
|
835
|
-
handleBounds: write.handleBounds
|
|
836
|
-
};
|
|
837
|
-
});
|
|
838
|
-
}, applyNodeChanges = (changes) => {
|
|
839
|
-
changes.length !== 0 && setNodesStore((nodes) => {
|
|
840
|
-
let nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
841
|
-
for (let change of changes) {
|
|
842
|
-
let node = nodeById.get(change.id);
|
|
843
|
-
if (node) switch (change.type) {
|
|
844
|
-
case "dimensions":
|
|
845
|
-
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
846
|
-
...node.measured,
|
|
847
|
-
...change.dimensions
|
|
848
|
-
};
|
|
849
|
-
break;
|
|
850
|
-
case "position": node.position = change.position ?? node.position;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
});
|
|
854
|
-
}, markInitialNodesMeasured = () => {
|
|
1115
|
+
}, { applyMeasurementWrites, applyNodeChanges } = createMeasurementIngest({
|
|
1116
|
+
setMeasurementsStore,
|
|
1117
|
+
setNodesStore,
|
|
1118
|
+
nodes: () => nodesStore
|
|
1119
|
+
}), markInitialNodesMeasured = () => {
|
|
855
1120
|
initialNodesMeasured = !0, tryInitialFitView();
|
|
856
1121
|
}, requestMeasure = () => {}, setMeasureRequester = (fn) => {
|
|
857
1122
|
requestMeasure = fn;
|
|
@@ -866,66 +1131,16 @@ const createLayoutedEdges = (source) => {
|
|
|
866
1131
|
ease: options?.ease,
|
|
867
1132
|
interpolate: options?.interpolate
|
|
868
1133
|
}), Promise.resolve(!0)) : Promise.resolve(!1);
|
|
869
|
-
},
|
|
870
|
-
store
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
}), flush();
|
|
880
|
-
}, addSelectedNodes = (ids) => {
|
|
881
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
882
|
-
setNodesStore((nodes) => {
|
|
883
|
-
for (let node of nodes) {
|
|
884
|
-
let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
885
|
-
node.selected !== selected && (node.selected = selected);
|
|
886
|
-
}
|
|
887
|
-
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] }), flush();
|
|
888
|
-
}, addSelectedEdges = (ids) => {
|
|
889
|
-
let isMultiSelection = store.multiselectionKeyPressed;
|
|
890
|
-
setEdgesStore((edges) => {
|
|
891
|
-
for (let edge of edges) {
|
|
892
|
-
let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
893
|
-
edge.selected !== selected && (edge.selected = selected);
|
|
894
|
-
}
|
|
895
|
-
}), isMultiSelection || unselectNodesAndEdges({ edges: [] }), flush();
|
|
896
|
-
}, handleNodeSelection = (id, unselect, nodeRef) => {
|
|
897
|
-
let node = store.nodes.find((n) => n.id === id);
|
|
898
|
-
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
899
|
-
nodes: [node],
|
|
900
|
-
edges: []
|
|
901
|
-
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
902
|
-
}, handleEdgeSelection = (id) => {
|
|
903
|
-
let edge = edgeLookup[id];
|
|
904
|
-
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
905
|
-
nodes: [],
|
|
906
|
-
edges: [edge]
|
|
907
|
-
}) : addSelectedEdges([id]));
|
|
908
|
-
}, moveSelectedNodes = (direction, factor) => {
|
|
909
|
-
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;
|
|
910
|
-
for (let node of nodeLookup.values()) {
|
|
911
|
-
if (!(node.selected && (node.draggable || store.nodesDraggable && node.draggable === void 0))) continue;
|
|
912
|
-
let nextPosition = {
|
|
913
|
-
x: node.internals.positionAbsolute.x + xDiff,
|
|
914
|
-
y: node.internals.positionAbsolute.y + yDiff
|
|
915
|
-
};
|
|
916
|
-
store.snapGrid && (nextPosition = snapPosition(nextPosition, store.snapGrid));
|
|
917
|
-
let { position } = calculateNodePosition({
|
|
918
|
-
nodeId: node.id,
|
|
919
|
-
nextPosition,
|
|
920
|
-
nodeLookup,
|
|
921
|
-
nodeExtent: store.nodeExtent,
|
|
922
|
-
nodeOrigin: store.nodeOrigin,
|
|
923
|
-
onError: store.onError
|
|
924
|
-
});
|
|
925
|
-
nodeUpdates.set(node.id, { position });
|
|
926
|
-
}
|
|
927
|
-
updateNodePositions(nodeUpdates);
|
|
928
|
-
}, 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({
|
|
929
1144
|
delta,
|
|
930
1145
|
panZoom: store.panZoom,
|
|
931
1146
|
transform: store.transform,
|
|
@@ -1002,8 +1217,27 @@ const createLayoutedEdges = (source) => {
|
|
|
1002
1217
|
get snapGrid() {
|
|
1003
1218
|
return store.snapGrid;
|
|
1004
1219
|
}
|
|
1005
|
-
},
|
|
1006
|
-
|
|
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 = {
|
|
1007
1241
|
...nodeToUse,
|
|
1008
1242
|
position,
|
|
1009
1243
|
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
@@ -1057,7 +1291,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1057
1291
|
x,
|
|
1058
1292
|
y,
|
|
1059
1293
|
zoom
|
|
1060
|
-
], _snapGrid
|
|
1294
|
+
], !!_snapGrid, _snapGrid || [1, 1]);
|
|
1061
1295
|
},
|
|
1062
1296
|
flowToScreenPosition: (position) => {
|
|
1063
1297
|
if (!store.domNode) return position;
|
|
@@ -1121,14 +1355,18 @@ const createLayoutedEdges = (source) => {
|
|
|
1121
1355
|
let remainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
|
|
1122
1356
|
store.onNodesDelete?.(matchingNodes), setNodesStore(() => remainingNodes);
|
|
1123
1357
|
}
|
|
1124
|
-
|
|
1358
|
+
let deletedNodes = matchingNodes ?? [], deletedEdges = matchingEdges ?? [];
|
|
1359
|
+
return (deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
1360
|
+
nodes: deletedNodes,
|
|
1361
|
+
edges: deletedEdges
|
|
1362
|
+
}), {
|
|
1125
1363
|
deletedNodes: matchingNodes,
|
|
1126
1364
|
deletedEdges: matchingEdges
|
|
1127
1365
|
};
|
|
1128
1366
|
},
|
|
1129
1367
|
getIntersectingNodes: (nodeOrRect, partially = !0, nodesToIntersect) => {
|
|
1130
1368
|
let isRect = isRectObject(nodeOrRect), nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
1131
|
-
return nodeRect ? (nodesToIntersect
|
|
1369
|
+
return nodeRect ? (nodesToIntersect ?? queryIntersectionCandidates(nodeRect)).filter((n) => {
|
|
1132
1370
|
let internalNode = nodeLookup.get(n.id);
|
|
1133
1371
|
if (!internalNode || !isRect && n.id === nodeOrRect.id) return !1;
|
|
1134
1372
|
let currNodeRect = nodeToRect(internalNode), overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
@@ -1184,10 +1422,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1184
1422
|
extent: store.translateExtent
|
|
1185
1423
|
}), ({ panZoom, extent }) => {
|
|
1186
1424
|
panZoom?.setTranslateExtent(extent);
|
|
1187
|
-
}), createEffect(() => new Set(store.nodes.map((n) => n.id)), (currentIds) => {
|
|
1188
|
-
setMeasurementsStore((draft) => {
|
|
1189
|
-
for (let id of Object.keys(draft)) currentIds.has(id) || delete draft[id];
|
|
1190
|
-
});
|
|
1191
1425
|
}), {
|
|
1192
1426
|
store,
|
|
1193
1427
|
flow,
|
|
@@ -1205,8 +1439,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1205
1439
|
applyNodeChanges,
|
|
1206
1440
|
markInitialNodesMeasured,
|
|
1207
1441
|
setMeasureRequester,
|
|
1208
|
-
resetStoreValues,
|
|
1209
|
-
setAriaLabelConfig,
|
|
1210
1442
|
setAriaLiveMessage,
|
|
1211
1443
|
setClickConnectStartHandle,
|
|
1212
1444
|
setConfig,
|
|
@@ -1214,15 +1446,11 @@ const createLayoutedEdges = (source) => {
|
|
|
1214
1446
|
setDeleteKeyPressed,
|
|
1215
1447
|
setDomNode,
|
|
1216
1448
|
setDragging,
|
|
1217
|
-
|
|
1218
|
-
return setEdgesStore;
|
|
1219
|
-
},
|
|
1449
|
+
setEdges: setEdgesStore,
|
|
1220
1450
|
setElementsSelectable,
|
|
1221
1451
|
setHeight,
|
|
1222
1452
|
setMultiselectionKeyPressed,
|
|
1223
|
-
|
|
1224
|
-
return setNodesStore;
|
|
1225
|
-
},
|
|
1453
|
+
setNodes: setNodesStore,
|
|
1226
1454
|
setNodesConnectable,
|
|
1227
1455
|
setNodesDraggable,
|
|
1228
1456
|
setPanActivationKeyPressed,
|
|
@@ -1230,9 +1458,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1230
1458
|
setSelectionKeyPressed,
|
|
1231
1459
|
setSelectionRect,
|
|
1232
1460
|
setSelectionRectMode,
|
|
1233
|
-
|
|
1234
|
-
return (viewport) => setViewportStore(() => viewport);
|
|
1235
|
-
},
|
|
1461
|
+
setViewport: stableSetViewport,
|
|
1236
1462
|
setWidth,
|
|
1237
1463
|
setZoomActivationKeyPressed,
|
|
1238
1464
|
addEdge,
|
|
@@ -1241,7 +1467,6 @@ const createLayoutedEdges = (source) => {
|
|
|
1241
1467
|
zoomOut,
|
|
1242
1468
|
fitView,
|
|
1243
1469
|
setCenter,
|
|
1244
|
-
setPaneClickDistance,
|
|
1245
1470
|
unselectNodesAndEdges,
|
|
1246
1471
|
addSelectedNodes,
|
|
1247
1472
|
addSelectedEdges,
|
|
@@ -1253,25 +1478,28 @@ const createLayoutedEdges = (source) => {
|
|
|
1253
1478
|
reset
|
|
1254
1479
|
}
|
|
1255
1480
|
};
|
|
1481
|
+
}, createEdgeStore = (edges) => {
|
|
1482
|
+
let [store, setStore] = typeof edges == "function" ? createStore(edges, []) : createStore(edges);
|
|
1483
|
+
return [store, setStore];
|
|
1256
1484
|
}, createNodeStore = (nodes) => {
|
|
1257
|
-
let [store, setStore] = createStore(nodes);
|
|
1485
|
+
let [store, setStore] = typeof nodes == "function" ? createStore(nodes, []) : createStore(nodes);
|
|
1258
1486
|
return [store, setStore];
|
|
1259
1487
|
}, EdgeWrapper = (props) => {
|
|
1260
|
-
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) => {
|
|
1261
1489
|
selectable() && actions.handleEdgeSelection(edgeId()), props.onEdgeClick?.({
|
|
1262
1490
|
edge: edge(),
|
|
1263
1491
|
event
|
|
1264
1492
|
});
|
|
1265
|
-
},
|
|
1266
|
-
(
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
}, 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) => {
|
|
1275
1503
|
store.disableKeyboardA11y || !elementSelectionKeys.includes(event.key) || !selectable() || (event.key === "Escape" ? actions.unselectNodesAndEdges({ edges: [edge()] }) : actions.addSelectedEdges([edge().id]));
|
|
1276
1504
|
}, ariaLabel = () => edge().ariaLabel ?? `Edge from ${edge().source} to ${edge().target}`, culled = createMemo(() => isEdgeCulled(edge(), store.cullingViewport));
|
|
1277
1505
|
return <EdgeIdContext value={edgeId}>
|
|
@@ -1290,7 +1518,7 @@ const createLayoutedEdges = (source) => {
|
|
|
1290
1518
|
selectable: !!selectable()
|
|
1291
1519
|
},
|
|
1292
1520
|
edge().class
|
|
1293
|
-
]} onClick={onClick} onKeyDown={(e) => focusable() && onKeyDown(e)} onContextMenu={
|
|
1521
|
+
]} onClick={onClick} onKeyDown={(e) => focusable() && onKeyDown(e)} onContextMenu={onContextMenu} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave} {...edge().domAttributes}>
|
|
1294
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()} />
|
|
1295
1523
|
</g>
|
|
1296
1524
|
</svg>
|
|
@@ -1414,7 +1642,10 @@ const Handle = (props) => {
|
|
|
1414
1642
|
position: "top",
|
|
1415
1643
|
isConnectableStart: !0,
|
|
1416
1644
|
isConnectableEnd: !0
|
|
1417
|
-
}), { 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;
|
|
1418
1649
|
createEffect(() => {
|
|
1419
1650
|
if (!_props.onConnect && !_props.onDisconnect) return null;
|
|
1420
1651
|
let rec = connections[connectionKey(nodeId(), _props.type, _props.id)], map = /* @__PURE__ */ new Map();
|
|
@@ -1432,13 +1663,20 @@ const Handle = (props) => {
|
|
|
1432
1663
|
}, edge = store.onBeforeConnect?.(handleConnection) ?? handleConnection;
|
|
1433
1664
|
actions.addEdge(edge), store.onConnect?.(handleConnection);
|
|
1434
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
|
+
});
|
|
1435
1673
|
XYHandle.onPointerDown(event, {
|
|
1436
1674
|
handleId: handleId(),
|
|
1437
1675
|
nodeId: nodeId(),
|
|
1438
1676
|
isTarget: isTarget(),
|
|
1439
1677
|
connectionRadius: store.connectionRadius,
|
|
1440
1678
|
domNode: store.domNode,
|
|
1441
|
-
nodeLookup,
|
|
1679
|
+
nodeLookup: gestureLookup,
|
|
1442
1680
|
connectionMode: store.connectionMode,
|
|
1443
1681
|
lib: store.lib,
|
|
1444
1682
|
autoPanOnConnect: store.autoPanOnConnect,
|
|
@@ -1623,12 +1861,11 @@ const NodeWrapper = (props) => {
|
|
|
1623
1861
|
...h ? { height: toPxString(h) } : {}
|
|
1624
1862
|
};
|
|
1625
1863
|
}, culled = createMemo(() => isNodeCulled(node(), store.cullingViewport)), style = () => ({
|
|
1864
|
+
...sizeStyle(),
|
|
1626
1865
|
"z-index": node().internals.z,
|
|
1627
1866
|
transform: transform(),
|
|
1628
1867
|
visibility: culled() || !nodeHasDimensions(node()) ? "hidden" : "visible",
|
|
1629
|
-
"pointer-events": culled() ? "none" : void 0
|
|
1630
|
-
...sizeStyle(),
|
|
1631
|
-
...node().style ?? {}
|
|
1868
|
+
"pointer-events": culled() ? "none" : void 0
|
|
1632
1869
|
});
|
|
1633
1870
|
createEffect(() => ({
|
|
1634
1871
|
valid: nodeTypeValid(),
|
|
@@ -1888,7 +2125,7 @@ const InitialNodeTypesMap = {
|
|
|
1888
2125
|
pendingEntries = updateEntries, scheduleIdleCallback(() => {
|
|
1889
2126
|
let updates = new Map(pendingEntries);
|
|
1890
2127
|
pendingEntries = void 0;
|
|
1891
|
-
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode);
|
|
2128
|
+
let { updatedInternals, measurementWrites, changes, parentExpandChildren } = measureNodeInternals(updates, nodeLookup, store.domNode, store.nodeExtent);
|
|
1892
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());
|
|
1893
2130
|
});
|
|
1894
2131
|
};
|
|
@@ -2038,7 +2275,7 @@ const ConnectionLine = (props) => {
|
|
|
2038
2275
|
for (let item of a) if (!b.has(item)) return !1;
|
|
2039
2276
|
return !0;
|
|
2040
2277
|
}, Pane = (props) => {
|
|
2041
|
-
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 = {
|
|
2042
2279
|
x: 0,
|
|
2043
2280
|
y: 0
|
|
2044
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) => {
|
|
@@ -2053,7 +2290,7 @@ const ConnectionLine = (props) => {
|
|
|
2053
2290
|
if (event.pointerType === "touch" && _panOnDrag() !== !1 && !store.selectionKeyPressed || (containerBounds = container?.getBoundingClientRect() ?? null, !containerBounds)) return;
|
|
2054
2291
|
let eventTargetIsContainer = event.target === container, isNoKeyEvent = !eventTargetIsContainer && !!event.target.closest(".nokey"), isSelectionActive = props.selectionOnDrag && eventTargetIsContainer || store.selectionKeyPressed;
|
|
2055
2292
|
if (isNoKeyEvent || !isSelecting() || !isSelectionActive || event.button !== 0 || !event.isPrimary) return;
|
|
2056
|
-
event.target?.setPointerCapture?.(event.pointerId), selectionInProgress = !1, autoPanStarted = !1;
|
|
2293
|
+
event.target?.setPointerCapture?.(event.pointerId), selectionSpatialLookup.arm((node) => nodeToRect(node)), selectionInProgress = !1, autoPanStarted = !1;
|
|
2057
2294
|
let { x, y } = getEventPosition(event, containerBounds), userSelectionFlowOrigin = pointToRendererPoint({
|
|
2058
2295
|
x,
|
|
2059
2296
|
y
|
|
@@ -2080,14 +2317,21 @@ const ConnectionLine = (props) => {
|
|
|
2080
2317
|
width: Math.abs(mouseX - screenStart.x),
|
|
2081
2318
|
height: Math.abs(mouseY - screenStart.y)
|
|
2082
2319
|
}, prevSelectedNodeIds = selectedNodeIds, prevSelectedEdgeIds = selectedEdgeIds;
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
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();
|
|
2086
2330
|
for (let nodeId of selectedNodeIds) {
|
|
2087
2331
|
let nodeConnections = connections[nodeId];
|
|
2088
2332
|
if (nodeConnections) for (let { edgeId } of Object.values(nodeConnections)) {
|
|
2089
2333
|
let edge = edgeLookup[edgeId];
|
|
2090
|
-
edge && (edge
|
|
2334
|
+
edge && isEdgeSelectable(edge, store) && selectedEdgeIds.add(edgeId);
|
|
2091
2335
|
}
|
|
2092
2336
|
}
|
|
2093
2337
|
isSetEqual(prevSelectedNodeIds, selectedNodeIds) || actions.setNodes((nodes) => {
|
|
@@ -2268,7 +2512,7 @@ const ConnectionLine = (props) => {
|
|
|
2268
2512
|
<div class="solid-flow__selection" style={styles()} />
|
|
2269
2513
|
</Show>;
|
|
2270
2514
|
}, NodeSelection = (props) => {
|
|
2271
|
-
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);
|
|
2272
2516
|
createEffect(() => ({
|
|
2273
2517
|
el: ref(),
|
|
2274
2518
|
focusable: !store.disableKeyboardA11y
|
|
@@ -2276,13 +2520,13 @@ const ConnectionLine = (props) => {
|
|
|
2276
2520
|
focusable && el?.focus({ preventScroll: !0 });
|
|
2277
2521
|
});
|
|
2278
2522
|
let onContextMenu = (event) => {
|
|
2279
|
-
let selectedNodes = store.
|
|
2523
|
+
let selectedNodes = store.selectedNodes;
|
|
2280
2524
|
props.onSelectionContextMenu?.({
|
|
2281
2525
|
nodes: selectedNodes,
|
|
2282
2526
|
event
|
|
2283
2527
|
});
|
|
2284
2528
|
}, onClick = (event) => {
|
|
2285
|
-
let selectedNodes = store.
|
|
2529
|
+
let selectedNodes = store.selectedNodes;
|
|
2286
2530
|
props.onSelectionClick?.({
|
|
2287
2531
|
nodes: selectedNodes,
|
|
2288
2532
|
event
|
|
@@ -2447,14 +2691,11 @@ const KeyHandler = (props) => {
|
|
|
2447
2691
|
}, handleWindowBlur = () => {
|
|
2448
2692
|
resetKeysAndSelection(), cancelPointerGestures();
|
|
2449
2693
|
}, handleDelete = async () => {
|
|
2450
|
-
let selectedNodes = store.
|
|
2694
|
+
let selectedNodes = store.selectedNodes, selectedEdges = store.selectedEdges;
|
|
2695
|
+
await deleteElements({
|
|
2451
2696
|
nodes: selectedNodes,
|
|
2452
2697
|
edges: selectedEdges
|
|
2453
2698
|
});
|
|
2454
|
-
(deletedNodes.length > 0 || deletedEdges.length > 0) && store.onDelete?.({
|
|
2455
|
-
nodes: deletedNodes,
|
|
2456
|
-
edges: deletedEdges
|
|
2457
|
-
});
|
|
2458
2699
|
};
|
|
2459
2700
|
return isServer || (createEventListenerMap(window, {
|
|
2460
2701
|
keydown: (event) => {
|
|
@@ -2472,34 +2713,23 @@ const KeyHandler = (props) => {
|
|
|
2472
2713
|
capture: !0,
|
|
2473
2714
|
passive: !0
|
|
2474
2715
|
})), null;
|
|
2475
|
-
}, 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) => {
|
|
2476
2717
|
let [domNodeRef, setDomNodeRef] = createSignal(), domNode, _props = merge({
|
|
2477
2718
|
...getDefaultFlowStateProps(),
|
|
2478
2719
|
colorMode: "light",
|
|
2479
|
-
deleteKeyCode: "Backspace",
|
|
2480
|
-
defaultViewport: {
|
|
2481
|
-
x: 0,
|
|
2482
|
-
y: 0,
|
|
2483
|
-
zoom: 1
|
|
2484
|
-
},
|
|
2485
|
-
multiSelectionKeyCode: isMacOs() ? "Meta" : "Control",
|
|
2486
2720
|
nodeClickDistance: 0,
|
|
2487
2721
|
panOnScroll: !1,
|
|
2488
|
-
panActivationKeyCode: "Space",
|
|
2489
2722
|
preventScrolling: !0,
|
|
2490
2723
|
panOnDrag: !0,
|
|
2491
2724
|
panOnScrollSpeed: .5,
|
|
2492
2725
|
panOnScrollMode: "free",
|
|
2493
2726
|
paneClickDistance: 0,
|
|
2494
|
-
reconnectRadius: 10,
|
|
2495
|
-
selectionKeyCode: "Shift",
|
|
2496
2727
|
selectionOnDrag: !1,
|
|
2497
2728
|
translateExtent: infiniteExtent,
|
|
2498
|
-
zoomActivationKeyCode: isMacOs() ? "Meta" : "Control",
|
|
2499
2729
|
zoomOnPinch: !0,
|
|
2500
2730
|
zoomOnDoubleClick: !0,
|
|
2501
2731
|
zoomOnScroll: !0
|
|
2502
|
-
}, props), htmlProps = omit(_props,
|
|
2732
|
+
}, props), htmlProps = omit(_props, ...FLOW_PROP_KEYS, "children"), TypedSolidFlowContext = SolidFlowContext, solidFlow = useContext(TypedSolidFlowContext) ?? createSolidFlow(_props), { store, actions } = solidFlow;
|
|
2503
2733
|
onSettled(() => (actions.applyInitialFitView(_props.fitView), actions.setConfig(_props), actions.setDomNode(domNode), () => {
|
|
2504
2734
|
actions.reset();
|
|
2505
2735
|
})), createEffect(() => domNodeRef(), (el) => {
|
|
@@ -2508,11 +2738,6 @@ const KeyHandler = (props) => {
|
|
|
2508
2738
|
actions.setWidth(el.clientWidth), actions.setHeight(el.clientHeight);
|
|
2509
2739
|
});
|
|
2510
2740
|
return observer.observe(el), () => observer.disconnect();
|
|
2511
|
-
}), createEffect(() => ({
|
|
2512
|
-
panZoom: store.panZoom,
|
|
2513
|
-
distance: _props.paneClickDistance
|
|
2514
|
-
}), ({ panZoom, distance }) => {
|
|
2515
|
-
panZoom?.setClickDistance(distance);
|
|
2516
2741
|
});
|
|
2517
2742
|
let selectedElements = createMemo(() => ({
|
|
2518
2743
|
nodes: store.selectedNodes,
|
|
@@ -2521,7 +2746,7 @@ const KeyHandler = (props) => {
|
|
|
2521
2746
|
createEffect(() => selectedElements(), (params) => {
|
|
2522
2747
|
untrack(() => _props.onSelectionChange)?.(params);
|
|
2523
2748
|
});
|
|
2524
|
-
let rootStyle = () => ({
|
|
2749
|
+
let asyncSeedGuard = () => (_props.nodes?.length, _props.edges?.length, null), rootStyle = () => ({
|
|
2525
2750
|
width: toPxString(_props.width),
|
|
2526
2751
|
height: toPxString(_props.height),
|
|
2527
2752
|
..._props.style
|
|
@@ -2541,12 +2766,13 @@ const KeyHandler = (props) => {
|
|
|
2541
2766
|
});
|
|
2542
2767
|
}} {...htmlProps}>
|
|
2543
2768
|
<TypedSolidFlowContext value={solidFlow}>
|
|
2769
|
+
{asyncSeedGuard()}
|
|
2544
2770
|
<KeyHandler selectionKey={_props.selectionKey} deleteKey={_props.deleteKey} panActivationKey={_props.panActivationKey} multiSelectionKey={_props.multiSelectionKey} zoomActivationKey={_props.zoomActivationKey} />
|
|
2545
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}>
|
|
2546
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}>
|
|
2547
2773
|
<Viewport>
|
|
2548
2774
|
<div class="solid-flow__container solid-flow__viewport-back" />
|
|
2549
|
-
<EdgeRenderer
|
|
2775
|
+
<EdgeRenderer onEdgeClick={_props.onEdgeClick} onEdgeContextMenu={_props.onEdgeContextMenu} onEdgePointerEnter={_props.onEdgePointerEnter} onEdgePointerLeave={_props.onEdgePointerLeave} />
|
|
2550
2776
|
<div class="solid-flow__container solid-flow__edge-labels" />
|
|
2551
2777
|
<ConnectionLine type={_props.connectionLineType} component={_props.connectionLineComponent} containerStyle={_props.connectionLineContainerStyle} style={_props.connectionLineStyle} />
|
|
2552
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} />
|
|
@@ -2870,24 +3096,23 @@ const DotPattern = (props) => {
|
|
|
2870
3096
|
nodeBorderRadius: 5,
|
|
2871
3097
|
nodeStrokeWidth: 2,
|
|
2872
3098
|
style: {}
|
|
2873
|
-
}), 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(() => ({
|
|
2874
3100
|
x: -store.viewport.x / store.viewport.zoom,
|
|
2875
3101
|
y: -store.viewport.y / store.viewport.zoom,
|
|
2876
3102
|
width: store.width / store.viewport.zoom,
|
|
2877
3103
|
height: store.height / store.viewport.zoom
|
|
2878
|
-
}),
|
|
2879
|
-
let
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
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();
|
|
2884
3112
|
}, getY = () => {
|
|
2885
|
-
let
|
|
2886
|
-
return
|
|
2887
|
-
}, getViewboxWidth = () => getViewWidth() + getOffset() * 2, getViewboxHeight = () => getViewHeight() + getOffset() * 2, strokeWidth = () => _props.maskStrokeWidth ? _props.maskStrokeWidth *
|
|
2888
|
-
let currentNodeIds = store.nodes.map((node) => node.id), currentSet = new Set(currentNodeIds);
|
|
2889
|
-
return (prevNodeIds.length !== currentNodeIds.length || !prevNodeIds.every((id) => currentSet.has(id))) && (prevNodeIds = currentNodeIds), prevNodeIds;
|
|
2890
|
-
};
|
|
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]) });
|
|
2891
3116
|
return <Panel position={_props.position} data-testid="solid-flow__minimap" class={["solid-flow__minimap", _props.class]} style={{
|
|
2892
3117
|
"--xy-minimap-background-color-props": _props.bgColor,
|
|
2893
3118
|
..._props.style
|
|
@@ -2904,7 +3129,7 @@ const DotPattern = (props) => {
|
|
|
2904
3129
|
domNode: el,
|
|
2905
3130
|
panZoom,
|
|
2906
3131
|
getTransform: () => store.transform,
|
|
2907
|
-
getViewScale
|
|
3132
|
+
getViewScale: viewScale
|
|
2908
3133
|
});
|
|
2909
3134
|
return setMinimap(instance), () => {
|
|
2910
3135
|
instance.destroy();
|
|
@@ -2944,12 +3169,12 @@ const DotPattern = (props) => {
|
|
|
2944
3169
|
{(nodeId) => {
|
|
2945
3170
|
let node = createMemo(() => nodeLookup.get(nodeId())), nodeVisible = () => !!(node() && nodeHasDimensions(node()) && !node().hidden);
|
|
2946
3171
|
return <Show when={nodeVisible() && getNodeDimensions(node())}>
|
|
2947
|
-
{(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} />}
|
|
2948
3173
|
</Show>;
|
|
2949
3174
|
}}
|
|
2950
3175
|
</For>
|
|
2951
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
|
|
2952
|
-
M${
|
|
3177
|
+
M${viewBB().x},${viewBB().y}h${viewBB().width}v${viewBB().height}h${-viewBB().width}z`} fill-rule="evenodd" pointer-events="none" />
|
|
2953
3178
|
</svg>;
|
|
2954
3179
|
}}
|
|
2955
3180
|
</Show>
|