@almadar/ui 5.58.0 → 5.59.0
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/dist/avl/index.cjs +143 -22
- package/dist/avl/index.js +143 -22
- package/dist/components/core/molecules/GraphCanvas.d.ts +6 -0
- package/dist/components/index.cjs +143 -22
- package/dist/components/index.js +143 -22
- package/dist/providers/index.cjs +143 -22
- package/dist/providers/index.js +143 -22
- package/dist/runtime/index.cjs +143 -22
- package/dist/runtime/index.js +143 -22
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -40199,6 +40199,9 @@ var init_GraphCanvas = __esm({
|
|
|
40199
40199
|
actions,
|
|
40200
40200
|
onNodeClick,
|
|
40201
40201
|
nodeClickEvent,
|
|
40202
|
+
selectedNodeId,
|
|
40203
|
+
repulsion = 800,
|
|
40204
|
+
linkDistance = 100,
|
|
40202
40205
|
layout = "force",
|
|
40203
40206
|
entity,
|
|
40204
40207
|
isLoading = false,
|
|
@@ -40214,6 +40217,35 @@ var init_GraphCanvas = __esm({
|
|
|
40214
40217
|
const [hoveredNode, setHoveredNode] = React90.useState(null);
|
|
40215
40218
|
const nodesRef = React90.useRef([]);
|
|
40216
40219
|
const [, forceUpdate] = React90.useState(0);
|
|
40220
|
+
const interactionRef = React90.useRef({
|
|
40221
|
+
mode: "none",
|
|
40222
|
+
dragNodeId: null,
|
|
40223
|
+
startMouse: { x: 0, y: 0 },
|
|
40224
|
+
startOffset: { x: 0, y: 0 },
|
|
40225
|
+
downPos: { x: 0, y: 0 }
|
|
40226
|
+
});
|
|
40227
|
+
const toCoords = React90.useCallback(
|
|
40228
|
+
(e) => {
|
|
40229
|
+
const canvas = canvasRef.current;
|
|
40230
|
+
if (!canvas) return null;
|
|
40231
|
+
const rect = canvas.getBoundingClientRect();
|
|
40232
|
+
const screenX = e.clientX - rect.left;
|
|
40233
|
+
const screenY = e.clientY - rect.top;
|
|
40234
|
+
return {
|
|
40235
|
+
screenX,
|
|
40236
|
+
screenY,
|
|
40237
|
+
graphX: (screenX - offset.x) / zoom,
|
|
40238
|
+
graphY: (screenY - offset.y) / zoom
|
|
40239
|
+
};
|
|
40240
|
+
},
|
|
40241
|
+
[offset, zoom]
|
|
40242
|
+
);
|
|
40243
|
+
const nodeAt = React90.useCallback((graphX, graphY) => {
|
|
40244
|
+
return nodesRef.current.find((n) => {
|
|
40245
|
+
const dist = Math.sqrt((n.x - graphX) ** 2 + (n.y - graphY) ** 2);
|
|
40246
|
+
return dist < (n.size || 8) + 4;
|
|
40247
|
+
});
|
|
40248
|
+
}, []);
|
|
40217
40249
|
const handleAction = React90.useCallback(
|
|
40218
40250
|
(action) => {
|
|
40219
40251
|
if (action.event) {
|
|
@@ -40279,7 +40311,7 @@ var init_GraphCanvas = __esm({
|
|
|
40279
40311
|
const dx = nodes[j].x - nodes[i].x;
|
|
40280
40312
|
const dy = nodes[j].y - nodes[i].y;
|
|
40281
40313
|
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
40282
|
-
const force =
|
|
40314
|
+
const force = repulsion / (dist * dist);
|
|
40283
40315
|
const fx = dx / dist * force;
|
|
40284
40316
|
const fy = dy / dist * force;
|
|
40285
40317
|
nodes[i].fx -= fx;
|
|
@@ -40295,7 +40327,7 @@ var init_GraphCanvas = __esm({
|
|
|
40295
40327
|
const dx = target.x - source.x;
|
|
40296
40328
|
const dy = target.y - source.y;
|
|
40297
40329
|
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
40298
|
-
const force = (dist -
|
|
40330
|
+
const force = (dist - linkDistance) * 0.05;
|
|
40299
40331
|
const fx = dx / dist * force;
|
|
40300
40332
|
const fy = dy / dist * force;
|
|
40301
40333
|
source.fx += fx;
|
|
@@ -40329,7 +40361,7 @@ var init_GraphCanvas = __esm({
|
|
|
40329
40361
|
return () => {
|
|
40330
40362
|
cancelAnimationFrame(animRef.current);
|
|
40331
40363
|
};
|
|
40332
|
-
}, [propNodes, propEdges, layout]);
|
|
40364
|
+
}, [propNodes, propEdges, layout, repulsion, linkDistance]);
|
|
40333
40365
|
React90.useEffect(() => {
|
|
40334
40366
|
const canvas = canvasRef.current;
|
|
40335
40367
|
if (!canvas) return;
|
|
@@ -40365,18 +40397,25 @@ var init_GraphCanvas = __esm({
|
|
|
40365
40397
|
const size = node.size || 8;
|
|
40366
40398
|
const color = node.color || getGroupColor(node.group, groups);
|
|
40367
40399
|
const isHovered = hoveredNode === node.id;
|
|
40400
|
+
const isSelected = selectedNodeId !== void 0 && node.id === selectedNodeId;
|
|
40401
|
+
const radius = isSelected ? size + 4 : isHovered ? size + 2 : size;
|
|
40368
40402
|
ctx.beginPath();
|
|
40369
|
-
ctx.arc(node.x, node.y,
|
|
40403
|
+
ctx.arc(node.x, node.y, radius, 0, Math.PI * 2);
|
|
40370
40404
|
ctx.fillStyle = color;
|
|
40371
40405
|
ctx.fill();
|
|
40372
|
-
|
|
40373
|
-
|
|
40406
|
+
if (isSelected) {
|
|
40407
|
+
ctx.strokeStyle = "var(--color-accent)";
|
|
40408
|
+
ctx.lineWidth = 3;
|
|
40409
|
+
} else {
|
|
40410
|
+
ctx.strokeStyle = isHovered ? "#ffffff" : "#00000020";
|
|
40411
|
+
ctx.lineWidth = isHovered ? 2 : 1;
|
|
40412
|
+
}
|
|
40374
40413
|
ctx.stroke();
|
|
40375
40414
|
if (showLabels && node.label) {
|
|
40376
40415
|
ctx.fillStyle = "#666666";
|
|
40377
|
-
ctx.font = `${isHovered ? "bold " : ""}10px system-ui`;
|
|
40416
|
+
ctx.font = `${isSelected || isHovered ? "bold " : ""}10px system-ui`;
|
|
40378
40417
|
ctx.textAlign = "center";
|
|
40379
|
-
ctx.fillText(node.label, node.x, node.y +
|
|
40418
|
+
ctx.fillText(node.label, node.x, node.y + radius + 12);
|
|
40380
40419
|
}
|
|
40381
40420
|
}
|
|
40382
40421
|
ctx.restore();
|
|
@@ -40387,6 +40426,97 @@ var init_GraphCanvas = __esm({
|
|
|
40387
40426
|
setZoom(1);
|
|
40388
40427
|
setOffset({ x: 0, y: 0 });
|
|
40389
40428
|
}, []);
|
|
40429
|
+
const handleWheel = React90.useCallback(
|
|
40430
|
+
(e) => {
|
|
40431
|
+
if (!interactive) return;
|
|
40432
|
+
e.preventDefault();
|
|
40433
|
+
const coords = toCoords(e);
|
|
40434
|
+
if (!coords) return;
|
|
40435
|
+
const oldZoom = zoom;
|
|
40436
|
+
const factor = e.deltaY < 0 ? 1.1 : 1 / 1.1;
|
|
40437
|
+
const newZoom = Math.max(0.3, Math.min(3, oldZoom * factor));
|
|
40438
|
+
if (newZoom === oldZoom) return;
|
|
40439
|
+
setOffset((o) => ({
|
|
40440
|
+
x: coords.screenX - (coords.screenX - o.x) * (newZoom / oldZoom),
|
|
40441
|
+
y: coords.screenY - (coords.screenY - o.y) * (newZoom / oldZoom)
|
|
40442
|
+
}));
|
|
40443
|
+
setZoom(newZoom);
|
|
40444
|
+
},
|
|
40445
|
+
[interactive, toCoords, zoom]
|
|
40446
|
+
);
|
|
40447
|
+
const handleMouseDown = React90.useCallback(
|
|
40448
|
+
(e) => {
|
|
40449
|
+
const coords = toCoords(e);
|
|
40450
|
+
if (!coords) return;
|
|
40451
|
+
const node = nodeAt(coords.graphX, coords.graphY);
|
|
40452
|
+
const state = interactionRef.current;
|
|
40453
|
+
state.downPos = { x: e.clientX, y: e.clientY };
|
|
40454
|
+
state.startMouse = { x: e.clientX, y: e.clientY };
|
|
40455
|
+
state.startOffset = { ...offset };
|
|
40456
|
+
if (draggable && node) {
|
|
40457
|
+
state.mode = "dragging";
|
|
40458
|
+
state.dragNodeId = node.id;
|
|
40459
|
+
} else if (interactive) {
|
|
40460
|
+
state.mode = "panning";
|
|
40461
|
+
state.dragNodeId = null;
|
|
40462
|
+
} else {
|
|
40463
|
+
state.mode = "none";
|
|
40464
|
+
state.dragNodeId = null;
|
|
40465
|
+
}
|
|
40466
|
+
},
|
|
40467
|
+
[toCoords, nodeAt, draggable, interactive, offset]
|
|
40468
|
+
);
|
|
40469
|
+
const handleMouseMove = React90.useCallback(
|
|
40470
|
+
(e) => {
|
|
40471
|
+
const state = interactionRef.current;
|
|
40472
|
+
if (state.mode === "panning") {
|
|
40473
|
+
const dx = e.clientX - state.startMouse.x;
|
|
40474
|
+
const dy = e.clientY - state.startMouse.y;
|
|
40475
|
+
setOffset({ x: state.startOffset.x + dx, y: state.startOffset.y + dy });
|
|
40476
|
+
return;
|
|
40477
|
+
}
|
|
40478
|
+
if (state.mode === "dragging" && state.dragNodeId) {
|
|
40479
|
+
const coords2 = toCoords(e);
|
|
40480
|
+
if (!coords2) return;
|
|
40481
|
+
const node2 = nodesRef.current.find((n) => n.id === state.dragNodeId);
|
|
40482
|
+
if (node2) {
|
|
40483
|
+
node2.x = coords2.graphX;
|
|
40484
|
+
node2.y = coords2.graphY;
|
|
40485
|
+
node2.vx = 0;
|
|
40486
|
+
node2.vy = 0;
|
|
40487
|
+
forceUpdate((n) => n + 1);
|
|
40488
|
+
}
|
|
40489
|
+
return;
|
|
40490
|
+
}
|
|
40491
|
+
const coords = toCoords(e);
|
|
40492
|
+
if (!coords) return;
|
|
40493
|
+
const node = nodeAt(coords.graphX, coords.graphY);
|
|
40494
|
+
setHoveredNode(node?.id ?? null);
|
|
40495
|
+
},
|
|
40496
|
+
[toCoords, nodeAt]
|
|
40497
|
+
);
|
|
40498
|
+
const handleMouseUp = React90.useCallback(
|
|
40499
|
+
(e) => {
|
|
40500
|
+
const state = interactionRef.current;
|
|
40501
|
+
const moved = Math.abs(e.clientX - state.downPos.x) + Math.abs(e.clientY - state.downPos.y);
|
|
40502
|
+
state.mode = "none";
|
|
40503
|
+
state.dragNodeId = null;
|
|
40504
|
+
if (moved < 4) {
|
|
40505
|
+
const coords = toCoords(e);
|
|
40506
|
+
if (!coords) return;
|
|
40507
|
+
const node = nodeAt(coords.graphX, coords.graphY);
|
|
40508
|
+
if (node) {
|
|
40509
|
+
handleNodeClick(node);
|
|
40510
|
+
}
|
|
40511
|
+
}
|
|
40512
|
+
},
|
|
40513
|
+
[toCoords, nodeAt, handleNodeClick]
|
|
40514
|
+
);
|
|
40515
|
+
const handleMouseLeave = React90.useCallback(() => {
|
|
40516
|
+
interactionRef.current.mode = "none";
|
|
40517
|
+
interactionRef.current.dragNodeId = null;
|
|
40518
|
+
setHoveredNode(null);
|
|
40519
|
+
}, []);
|
|
40390
40520
|
if (isLoading) {
|
|
40391
40521
|
return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: t("common.loading"), className });
|
|
40392
40522
|
}
|
|
@@ -40448,20 +40578,11 @@ var init_GraphCanvas = __esm({
|
|
|
40448
40578
|
height,
|
|
40449
40579
|
className: "w-full cursor-grab active:cursor-grabbing",
|
|
40450
40580
|
style: { height },
|
|
40451
|
-
|
|
40452
|
-
|
|
40453
|
-
|
|
40454
|
-
|
|
40455
|
-
|
|
40456
|
-
const y = (e.clientY - rect.top - offset.y) / zoom;
|
|
40457
|
-
const clickedNode = nodesRef.current.find((n) => {
|
|
40458
|
-
const dist = Math.sqrt((n.x - x) ** 2 + (n.y - y) ** 2);
|
|
40459
|
-
return dist < (n.size || 8) + 4;
|
|
40460
|
-
});
|
|
40461
|
-
if (clickedNode) {
|
|
40462
|
-
handleNodeClick(clickedNode);
|
|
40463
|
-
}
|
|
40464
|
-
}
|
|
40581
|
+
onWheel: handleWheel,
|
|
40582
|
+
onMouseDown: handleMouseDown,
|
|
40583
|
+
onMouseMove: handleMouseMove,
|
|
40584
|
+
onMouseUp: handleMouseUp,
|
|
40585
|
+
onMouseLeave: handleMouseLeave
|
|
40465
40586
|
}
|
|
40466
40587
|
) }),
|
|
40467
40588
|
groups.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "md", className: "px-4 py-2 border-t border-border", wrap: true, children: groups.map((group, idx) => /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
|
package/dist/avl/index.js
CHANGED
|
@@ -40152,6 +40152,9 @@ var init_GraphCanvas = __esm({
|
|
|
40152
40152
|
actions,
|
|
40153
40153
|
onNodeClick,
|
|
40154
40154
|
nodeClickEvent,
|
|
40155
|
+
selectedNodeId,
|
|
40156
|
+
repulsion = 800,
|
|
40157
|
+
linkDistance = 100,
|
|
40155
40158
|
layout = "force",
|
|
40156
40159
|
entity,
|
|
40157
40160
|
isLoading = false,
|
|
@@ -40167,6 +40170,35 @@ var init_GraphCanvas = __esm({
|
|
|
40167
40170
|
const [hoveredNode, setHoveredNode] = useState(null);
|
|
40168
40171
|
const nodesRef = useRef([]);
|
|
40169
40172
|
const [, forceUpdate] = useState(0);
|
|
40173
|
+
const interactionRef = useRef({
|
|
40174
|
+
mode: "none",
|
|
40175
|
+
dragNodeId: null,
|
|
40176
|
+
startMouse: { x: 0, y: 0 },
|
|
40177
|
+
startOffset: { x: 0, y: 0 },
|
|
40178
|
+
downPos: { x: 0, y: 0 }
|
|
40179
|
+
});
|
|
40180
|
+
const toCoords = useCallback(
|
|
40181
|
+
(e) => {
|
|
40182
|
+
const canvas = canvasRef.current;
|
|
40183
|
+
if (!canvas) return null;
|
|
40184
|
+
const rect = canvas.getBoundingClientRect();
|
|
40185
|
+
const screenX = e.clientX - rect.left;
|
|
40186
|
+
const screenY = e.clientY - rect.top;
|
|
40187
|
+
return {
|
|
40188
|
+
screenX,
|
|
40189
|
+
screenY,
|
|
40190
|
+
graphX: (screenX - offset.x) / zoom,
|
|
40191
|
+
graphY: (screenY - offset.y) / zoom
|
|
40192
|
+
};
|
|
40193
|
+
},
|
|
40194
|
+
[offset, zoom]
|
|
40195
|
+
);
|
|
40196
|
+
const nodeAt = useCallback((graphX, graphY) => {
|
|
40197
|
+
return nodesRef.current.find((n) => {
|
|
40198
|
+
const dist = Math.sqrt((n.x - graphX) ** 2 + (n.y - graphY) ** 2);
|
|
40199
|
+
return dist < (n.size || 8) + 4;
|
|
40200
|
+
});
|
|
40201
|
+
}, []);
|
|
40170
40202
|
const handleAction = useCallback(
|
|
40171
40203
|
(action) => {
|
|
40172
40204
|
if (action.event) {
|
|
@@ -40232,7 +40264,7 @@ var init_GraphCanvas = __esm({
|
|
|
40232
40264
|
const dx = nodes[j].x - nodes[i].x;
|
|
40233
40265
|
const dy = nodes[j].y - nodes[i].y;
|
|
40234
40266
|
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
40235
|
-
const force =
|
|
40267
|
+
const force = repulsion / (dist * dist);
|
|
40236
40268
|
const fx = dx / dist * force;
|
|
40237
40269
|
const fy = dy / dist * force;
|
|
40238
40270
|
nodes[i].fx -= fx;
|
|
@@ -40248,7 +40280,7 @@ var init_GraphCanvas = __esm({
|
|
|
40248
40280
|
const dx = target.x - source.x;
|
|
40249
40281
|
const dy = target.y - source.y;
|
|
40250
40282
|
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
40251
|
-
const force = (dist -
|
|
40283
|
+
const force = (dist - linkDistance) * 0.05;
|
|
40252
40284
|
const fx = dx / dist * force;
|
|
40253
40285
|
const fy = dy / dist * force;
|
|
40254
40286
|
source.fx += fx;
|
|
@@ -40282,7 +40314,7 @@ var init_GraphCanvas = __esm({
|
|
|
40282
40314
|
return () => {
|
|
40283
40315
|
cancelAnimationFrame(animRef.current);
|
|
40284
40316
|
};
|
|
40285
|
-
}, [propNodes, propEdges, layout]);
|
|
40317
|
+
}, [propNodes, propEdges, layout, repulsion, linkDistance]);
|
|
40286
40318
|
useEffect(() => {
|
|
40287
40319
|
const canvas = canvasRef.current;
|
|
40288
40320
|
if (!canvas) return;
|
|
@@ -40318,18 +40350,25 @@ var init_GraphCanvas = __esm({
|
|
|
40318
40350
|
const size = node.size || 8;
|
|
40319
40351
|
const color = node.color || getGroupColor(node.group, groups);
|
|
40320
40352
|
const isHovered = hoveredNode === node.id;
|
|
40353
|
+
const isSelected = selectedNodeId !== void 0 && node.id === selectedNodeId;
|
|
40354
|
+
const radius = isSelected ? size + 4 : isHovered ? size + 2 : size;
|
|
40321
40355
|
ctx.beginPath();
|
|
40322
|
-
ctx.arc(node.x, node.y,
|
|
40356
|
+
ctx.arc(node.x, node.y, radius, 0, Math.PI * 2);
|
|
40323
40357
|
ctx.fillStyle = color;
|
|
40324
40358
|
ctx.fill();
|
|
40325
|
-
|
|
40326
|
-
|
|
40359
|
+
if (isSelected) {
|
|
40360
|
+
ctx.strokeStyle = "var(--color-accent)";
|
|
40361
|
+
ctx.lineWidth = 3;
|
|
40362
|
+
} else {
|
|
40363
|
+
ctx.strokeStyle = isHovered ? "#ffffff" : "#00000020";
|
|
40364
|
+
ctx.lineWidth = isHovered ? 2 : 1;
|
|
40365
|
+
}
|
|
40327
40366
|
ctx.stroke();
|
|
40328
40367
|
if (showLabels && node.label) {
|
|
40329
40368
|
ctx.fillStyle = "#666666";
|
|
40330
|
-
ctx.font = `${isHovered ? "bold " : ""}10px system-ui`;
|
|
40369
|
+
ctx.font = `${isSelected || isHovered ? "bold " : ""}10px system-ui`;
|
|
40331
40370
|
ctx.textAlign = "center";
|
|
40332
|
-
ctx.fillText(node.label, node.x, node.y +
|
|
40371
|
+
ctx.fillText(node.label, node.x, node.y + radius + 12);
|
|
40333
40372
|
}
|
|
40334
40373
|
}
|
|
40335
40374
|
ctx.restore();
|
|
@@ -40340,6 +40379,97 @@ var init_GraphCanvas = __esm({
|
|
|
40340
40379
|
setZoom(1);
|
|
40341
40380
|
setOffset({ x: 0, y: 0 });
|
|
40342
40381
|
}, []);
|
|
40382
|
+
const handleWheel = useCallback(
|
|
40383
|
+
(e) => {
|
|
40384
|
+
if (!interactive) return;
|
|
40385
|
+
e.preventDefault();
|
|
40386
|
+
const coords = toCoords(e);
|
|
40387
|
+
if (!coords) return;
|
|
40388
|
+
const oldZoom = zoom;
|
|
40389
|
+
const factor = e.deltaY < 0 ? 1.1 : 1 / 1.1;
|
|
40390
|
+
const newZoom = Math.max(0.3, Math.min(3, oldZoom * factor));
|
|
40391
|
+
if (newZoom === oldZoom) return;
|
|
40392
|
+
setOffset((o) => ({
|
|
40393
|
+
x: coords.screenX - (coords.screenX - o.x) * (newZoom / oldZoom),
|
|
40394
|
+
y: coords.screenY - (coords.screenY - o.y) * (newZoom / oldZoom)
|
|
40395
|
+
}));
|
|
40396
|
+
setZoom(newZoom);
|
|
40397
|
+
},
|
|
40398
|
+
[interactive, toCoords, zoom]
|
|
40399
|
+
);
|
|
40400
|
+
const handleMouseDown = useCallback(
|
|
40401
|
+
(e) => {
|
|
40402
|
+
const coords = toCoords(e);
|
|
40403
|
+
if (!coords) return;
|
|
40404
|
+
const node = nodeAt(coords.graphX, coords.graphY);
|
|
40405
|
+
const state = interactionRef.current;
|
|
40406
|
+
state.downPos = { x: e.clientX, y: e.clientY };
|
|
40407
|
+
state.startMouse = { x: e.clientX, y: e.clientY };
|
|
40408
|
+
state.startOffset = { ...offset };
|
|
40409
|
+
if (draggable && node) {
|
|
40410
|
+
state.mode = "dragging";
|
|
40411
|
+
state.dragNodeId = node.id;
|
|
40412
|
+
} else if (interactive) {
|
|
40413
|
+
state.mode = "panning";
|
|
40414
|
+
state.dragNodeId = null;
|
|
40415
|
+
} else {
|
|
40416
|
+
state.mode = "none";
|
|
40417
|
+
state.dragNodeId = null;
|
|
40418
|
+
}
|
|
40419
|
+
},
|
|
40420
|
+
[toCoords, nodeAt, draggable, interactive, offset]
|
|
40421
|
+
);
|
|
40422
|
+
const handleMouseMove = useCallback(
|
|
40423
|
+
(e) => {
|
|
40424
|
+
const state = interactionRef.current;
|
|
40425
|
+
if (state.mode === "panning") {
|
|
40426
|
+
const dx = e.clientX - state.startMouse.x;
|
|
40427
|
+
const dy = e.clientY - state.startMouse.y;
|
|
40428
|
+
setOffset({ x: state.startOffset.x + dx, y: state.startOffset.y + dy });
|
|
40429
|
+
return;
|
|
40430
|
+
}
|
|
40431
|
+
if (state.mode === "dragging" && state.dragNodeId) {
|
|
40432
|
+
const coords2 = toCoords(e);
|
|
40433
|
+
if (!coords2) return;
|
|
40434
|
+
const node2 = nodesRef.current.find((n) => n.id === state.dragNodeId);
|
|
40435
|
+
if (node2) {
|
|
40436
|
+
node2.x = coords2.graphX;
|
|
40437
|
+
node2.y = coords2.graphY;
|
|
40438
|
+
node2.vx = 0;
|
|
40439
|
+
node2.vy = 0;
|
|
40440
|
+
forceUpdate((n) => n + 1);
|
|
40441
|
+
}
|
|
40442
|
+
return;
|
|
40443
|
+
}
|
|
40444
|
+
const coords = toCoords(e);
|
|
40445
|
+
if (!coords) return;
|
|
40446
|
+
const node = nodeAt(coords.graphX, coords.graphY);
|
|
40447
|
+
setHoveredNode(node?.id ?? null);
|
|
40448
|
+
},
|
|
40449
|
+
[toCoords, nodeAt]
|
|
40450
|
+
);
|
|
40451
|
+
const handleMouseUp = useCallback(
|
|
40452
|
+
(e) => {
|
|
40453
|
+
const state = interactionRef.current;
|
|
40454
|
+
const moved = Math.abs(e.clientX - state.downPos.x) + Math.abs(e.clientY - state.downPos.y);
|
|
40455
|
+
state.mode = "none";
|
|
40456
|
+
state.dragNodeId = null;
|
|
40457
|
+
if (moved < 4) {
|
|
40458
|
+
const coords = toCoords(e);
|
|
40459
|
+
if (!coords) return;
|
|
40460
|
+
const node = nodeAt(coords.graphX, coords.graphY);
|
|
40461
|
+
if (node) {
|
|
40462
|
+
handleNodeClick(node);
|
|
40463
|
+
}
|
|
40464
|
+
}
|
|
40465
|
+
},
|
|
40466
|
+
[toCoords, nodeAt, handleNodeClick]
|
|
40467
|
+
);
|
|
40468
|
+
const handleMouseLeave = useCallback(() => {
|
|
40469
|
+
interactionRef.current.mode = "none";
|
|
40470
|
+
interactionRef.current.dragNodeId = null;
|
|
40471
|
+
setHoveredNode(null);
|
|
40472
|
+
}, []);
|
|
40343
40473
|
if (isLoading) {
|
|
40344
40474
|
return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
|
|
40345
40475
|
}
|
|
@@ -40401,20 +40531,11 @@ var init_GraphCanvas = __esm({
|
|
|
40401
40531
|
height,
|
|
40402
40532
|
className: "w-full cursor-grab active:cursor-grabbing",
|
|
40403
40533
|
style: { height },
|
|
40404
|
-
|
|
40405
|
-
|
|
40406
|
-
|
|
40407
|
-
|
|
40408
|
-
|
|
40409
|
-
const y = (e.clientY - rect.top - offset.y) / zoom;
|
|
40410
|
-
const clickedNode = nodesRef.current.find((n) => {
|
|
40411
|
-
const dist = Math.sqrt((n.x - x) ** 2 + (n.y - y) ** 2);
|
|
40412
|
-
return dist < (n.size || 8) + 4;
|
|
40413
|
-
});
|
|
40414
|
-
if (clickedNode) {
|
|
40415
|
-
handleNodeClick(clickedNode);
|
|
40416
|
-
}
|
|
40417
|
-
}
|
|
40534
|
+
onWheel: handleWheel,
|
|
40535
|
+
onMouseDown: handleMouseDown,
|
|
40536
|
+
onMouseMove: handleMouseMove,
|
|
40537
|
+
onMouseUp: handleMouseUp,
|
|
40538
|
+
onMouseLeave: handleMouseLeave
|
|
40418
40539
|
}
|
|
40419
40540
|
) }),
|
|
40420
40541
|
groups.length > 1 && /* @__PURE__ */ jsx(HStack, { gap: "md", className: "px-4 py-2 border-t border-border", wrap: true, children: groups.map((group, idx) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
@@ -59,6 +59,12 @@ export interface GraphCanvasProps {
|
|
|
59
59
|
nodeClickEvent?: EventEmit<{
|
|
60
60
|
id: string;
|
|
61
61
|
}>;
|
|
62
|
+
/** Currently selected node id (rendered emphasized) */
|
|
63
|
+
selectedNodeId?: string;
|
|
64
|
+
/** Force-sim repulsion strength between nodes (larger ⇒ more spread out) */
|
|
65
|
+
repulsion?: number;
|
|
66
|
+
/** Force-sim target edge length (larger ⇒ more spread out) */
|
|
67
|
+
linkDistance?: number;
|
|
62
68
|
/** Layout algorithm */
|
|
63
69
|
layout?: "force" | "circular" | "grid";
|
|
64
70
|
/** Entity name for schema-driven auto-fetch */
|