@aiready/visualizer 0.6.18 → 0.6.19
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.
|
@@ -24895,7 +24895,7 @@ function superRefine(fn) {
|
|
|
24895
24895
|
return /* @__PURE__ */ _superRefine(fn);
|
|
24896
24896
|
}
|
|
24897
24897
|
//#endregion
|
|
24898
|
-
//#region ../../core/dist/chunk-
|
|
24898
|
+
//#region ../../core/dist/chunk-SQHS6PFL.mjs
|
|
24899
24899
|
var LeadSource = /* @__PURE__ */ ((LeadSource2) => {
|
|
24900
24900
|
LeadSource2["ClawMoreHero"] = "clawmore-hero";
|
|
24901
24901
|
LeadSource2["ClawMoreWaitlist"] = "clawmore-waitlist";
|
|
@@ -28335,6 +28335,374 @@ function ScoreCircle({ score, progress: customProgress, isInView = true, size =
|
|
|
28335
28335
|
});
|
|
28336
28336
|
}
|
|
28337
28337
|
(0, import_react.createContext)(void 0);
|
|
28338
|
+
function pinNode(node) {
|
|
28339
|
+
node.fx = node.x;
|
|
28340
|
+
node.fy = node.y;
|
|
28341
|
+
}
|
|
28342
|
+
function unpinNode(node) {
|
|
28343
|
+
node.fx = null;
|
|
28344
|
+
node.fy = null;
|
|
28345
|
+
}
|
|
28346
|
+
function unpinAllNodes(nodes) {
|
|
28347
|
+
nodes.forEach(unpinNode);
|
|
28348
|
+
}
|
|
28349
|
+
function useGraphZoom(svgRef, gRef, enableZoom, setTransform, transformRef) {
|
|
28350
|
+
(0, import_react.useEffect)(() => {
|
|
28351
|
+
if (!enableZoom || !svgRef.current || !gRef.current) return;
|
|
28352
|
+
const svg = select_default$1(svgRef.current);
|
|
28353
|
+
const g = select_default$1(gRef.current);
|
|
28354
|
+
const zoom3 = zoom_default().scaleExtent([.1, 10]).on("zoom", (event) => {
|
|
28355
|
+
g.attr("transform", event.transform);
|
|
28356
|
+
transformRef.current = event.transform;
|
|
28357
|
+
setTransform(event.transform);
|
|
28358
|
+
});
|
|
28359
|
+
svg.call(zoom3);
|
|
28360
|
+
return () => {
|
|
28361
|
+
svg.on(".zoom", null);
|
|
28362
|
+
};
|
|
28363
|
+
}, [
|
|
28364
|
+
enableZoom,
|
|
28365
|
+
svgRef,
|
|
28366
|
+
gRef,
|
|
28367
|
+
setTransform,
|
|
28368
|
+
transformRef
|
|
28369
|
+
]);
|
|
28370
|
+
}
|
|
28371
|
+
function useWindowDrag(enableDrag, svgRef, transformRef, dragActiveRef, dragNodeRef, onDragEnd) {
|
|
28372
|
+
(0, import_react.useEffect)(() => {
|
|
28373
|
+
if (!enableDrag) return;
|
|
28374
|
+
const handleWindowMove = (event) => {
|
|
28375
|
+
if (!dragActiveRef.current || !dragNodeRef.current) return;
|
|
28376
|
+
const svg = svgRef.current;
|
|
28377
|
+
if (!svg) return;
|
|
28378
|
+
const rect = svg.getBoundingClientRect();
|
|
28379
|
+
const t = transformRef.current;
|
|
28380
|
+
const x = (event.clientX - rect.left - t.x) / t.k;
|
|
28381
|
+
const y = (event.clientY - rect.top - t.y) / t.k;
|
|
28382
|
+
dragNodeRef.current.fx = x;
|
|
28383
|
+
dragNodeRef.current.fy = y;
|
|
28384
|
+
};
|
|
28385
|
+
const handleWindowUp = () => {
|
|
28386
|
+
if (!dragActiveRef.current) return;
|
|
28387
|
+
onDragEnd();
|
|
28388
|
+
dragNodeRef.current = null;
|
|
28389
|
+
dragActiveRef.current = false;
|
|
28390
|
+
};
|
|
28391
|
+
const handleWindowLeave = (event) => {
|
|
28392
|
+
if (event.relatedTarget === null) handleWindowUp();
|
|
28393
|
+
};
|
|
28394
|
+
window.addEventListener("mousemove", handleWindowMove);
|
|
28395
|
+
window.addEventListener("mouseup", handleWindowUp);
|
|
28396
|
+
window.addEventListener("mouseout", handleWindowLeave);
|
|
28397
|
+
window.addEventListener("blur", handleWindowUp);
|
|
28398
|
+
return () => {
|
|
28399
|
+
window.removeEventListener("mousemove", handleWindowMove);
|
|
28400
|
+
window.removeEventListener("mouseup", handleWindowUp);
|
|
28401
|
+
window.removeEventListener("mouseout", handleWindowLeave);
|
|
28402
|
+
window.removeEventListener("blur", handleWindowUp);
|
|
28403
|
+
};
|
|
28404
|
+
}, [
|
|
28405
|
+
enableDrag,
|
|
28406
|
+
svgRef,
|
|
28407
|
+
transformRef,
|
|
28408
|
+
dragActiveRef,
|
|
28409
|
+
dragNodeRef,
|
|
28410
|
+
onDragEnd
|
|
28411
|
+
]);
|
|
28412
|
+
}
|
|
28413
|
+
function useNodeInteractions(enableDrag, _nodes, _pinnedNodes, setPinnedNodes, restart, stop) {
|
|
28414
|
+
return {
|
|
28415
|
+
handleDragStart: (0, import_react.useCallback)((event, node) => {
|
|
28416
|
+
if (!enableDrag) return;
|
|
28417
|
+
event.preventDefault();
|
|
28418
|
+
event.stopPropagation();
|
|
28419
|
+
pinNode(node);
|
|
28420
|
+
setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
|
|
28421
|
+
stop();
|
|
28422
|
+
}, [
|
|
28423
|
+
enableDrag,
|
|
28424
|
+
stop,
|
|
28425
|
+
setPinnedNodes
|
|
28426
|
+
]),
|
|
28427
|
+
handleNodeDoubleClick: (0, import_react.useCallback)((event, node) => {
|
|
28428
|
+
event.stopPropagation();
|
|
28429
|
+
if (!enableDrag) return;
|
|
28430
|
+
if (node.fx === null || node.fx === void 0) {
|
|
28431
|
+
pinNode(node);
|
|
28432
|
+
setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
|
|
28433
|
+
} else {
|
|
28434
|
+
unpinNode(node);
|
|
28435
|
+
setPinnedNodes((prev) => {
|
|
28436
|
+
const next = new Set(prev);
|
|
28437
|
+
next.delete(node.id);
|
|
28438
|
+
return next;
|
|
28439
|
+
});
|
|
28440
|
+
}
|
|
28441
|
+
restart();
|
|
28442
|
+
}, [
|
|
28443
|
+
enableDrag,
|
|
28444
|
+
restart,
|
|
28445
|
+
setPinnedNodes
|
|
28446
|
+
])
|
|
28447
|
+
};
|
|
28448
|
+
}
|
|
28449
|
+
var DEFAULT_NODE_COLOR = "#64748b";
|
|
28450
|
+
var DEFAULT_NODE_SIZE = 10;
|
|
28451
|
+
var DEFAULT_LINK_COLOR = "#94a3b8";
|
|
28452
|
+
var DEFAULT_LINK_WIDTH = 1;
|
|
28453
|
+
var CIRCULAR_LAYOUT_RADIUS_RATIO = .35;
|
|
28454
|
+
var FIT_VIEW_PADDING = 40;
|
|
28455
|
+
var TRANSITION_DURATION_MS = 300;
|
|
28456
|
+
var PACKAGE_BOUNDARY_FILL = "rgba(148,163,184,0.06)";
|
|
28457
|
+
var PACKAGE_BOUNDARY_STROKE = "#475569";
|
|
28458
|
+
var PACKAGE_BOUNDARY_STROKE_WIDTH = 2;
|
|
28459
|
+
var PACKAGE_BOUNDARY_DASH = "6 6";
|
|
28460
|
+
var PACKAGE_LABEL_FONT_SIZE = 11;
|
|
28461
|
+
var PACKAGE_LABEL_COLOR = "#475569";
|
|
28462
|
+
function applyCircularLayout(nodes, width, height) {
|
|
28463
|
+
const centerX = width / 2;
|
|
28464
|
+
const centerY = height / 2;
|
|
28465
|
+
const radius = Math.min(width, height) * CIRCULAR_LAYOUT_RADIUS_RATIO;
|
|
28466
|
+
nodes.forEach((node, i) => {
|
|
28467
|
+
const angle = 2 * Math.PI * i / nodes.length;
|
|
28468
|
+
node.fx = centerX + Math.cos(angle) * radius;
|
|
28469
|
+
node.fy = centerY + Math.sin(angle) * radius;
|
|
28470
|
+
node.x = node.fx;
|
|
28471
|
+
node.y = node.fy;
|
|
28472
|
+
});
|
|
28473
|
+
}
|
|
28474
|
+
function applyHierarchicalLayout(nodes, width, height) {
|
|
28475
|
+
const groups = /* @__PURE__ */ new Map();
|
|
28476
|
+
nodes.forEach((n) => {
|
|
28477
|
+
const key = n.packageGroup || n.group || "root";
|
|
28478
|
+
if (!groups.has(key)) groups.set(key, []);
|
|
28479
|
+
groups.get(key).push(n);
|
|
28480
|
+
});
|
|
28481
|
+
const groupArray = Array.from(groups.entries());
|
|
28482
|
+
const cols = Math.ceil(Math.sqrt(groupArray.length));
|
|
28483
|
+
const groupSpacingX = width * .8 / cols;
|
|
28484
|
+
const groupSpacingY = height * .8 / Math.ceil(groupArray.length / cols);
|
|
28485
|
+
groupArray.forEach(([groupKey, groupNodes], gi) => {
|
|
28486
|
+
const col = gi % cols;
|
|
28487
|
+
const row = Math.floor(gi / cols);
|
|
28488
|
+
const groupX = (col + .5) * groupSpacingX;
|
|
28489
|
+
const groupY = (row + .5) * groupSpacingY;
|
|
28490
|
+
if (groupKey.startsWith("pkg:") || groupKey === groupKey) groupNodes.forEach((n, ni) => {
|
|
28491
|
+
const angle = 2 * Math.PI * ni / groupNodes.length;
|
|
28492
|
+
const r = Math.min(80, 20 + groupNodes.length * 8);
|
|
28493
|
+
n.fx = groupX + Math.cos(angle) * r;
|
|
28494
|
+
n.fy = groupY + Math.sin(angle) * r;
|
|
28495
|
+
n.x = n.fx;
|
|
28496
|
+
n.y = n.fy;
|
|
28497
|
+
});
|
|
28498
|
+
});
|
|
28499
|
+
}
|
|
28500
|
+
function applyInitialForceLayout(nodes, width, height) {
|
|
28501
|
+
nodes.forEach((node) => {
|
|
28502
|
+
if (node.fx === void 0 || node.fx === null) {
|
|
28503
|
+
node.x = Math.random() * width;
|
|
28504
|
+
node.y = Math.random() * height;
|
|
28505
|
+
}
|
|
28506
|
+
});
|
|
28507
|
+
}
|
|
28508
|
+
function useGraphLayout(initialNodes, width, height, layout, restart) {
|
|
28509
|
+
const nodes = (0, import_react.useMemo)(() => {
|
|
28510
|
+
if (!initialNodes || !initialNodes.length) return initialNodes;
|
|
28511
|
+
const copy = initialNodes.map((n) => ({ ...n }));
|
|
28512
|
+
if (layout === "circular") applyCircularLayout(copy, width, height);
|
|
28513
|
+
else if (layout === "hierarchical") applyHierarchicalLayout(copy, width, height);
|
|
28514
|
+
else applyInitialForceLayout(copy, width, height);
|
|
28515
|
+
return copy;
|
|
28516
|
+
}, [
|
|
28517
|
+
initialNodes,
|
|
28518
|
+
width,
|
|
28519
|
+
height,
|
|
28520
|
+
layout
|
|
28521
|
+
]);
|
|
28522
|
+
(0, import_react.useEffect)(() => {
|
|
28523
|
+
if (!nodes || nodes.length === 0) return;
|
|
28524
|
+
if (layout === "circular") applyCircularLayout(nodes, width, height);
|
|
28525
|
+
else if (layout === "hierarchical") applyHierarchicalLayout(nodes, width, height);
|
|
28526
|
+
restart();
|
|
28527
|
+
}, [
|
|
28528
|
+
layout,
|
|
28529
|
+
nodes,
|
|
28530
|
+
width,
|
|
28531
|
+
height,
|
|
28532
|
+
restart
|
|
28533
|
+
]);
|
|
28534
|
+
return { nodes };
|
|
28535
|
+
}
|
|
28536
|
+
function useSimulationControls() {
|
|
28537
|
+
return {
|
|
28538
|
+
restart: (0, import_react.useCallback)(() => {}, []),
|
|
28539
|
+
stop: (0, import_react.useCallback)(() => {}, []),
|
|
28540
|
+
setForcesEnabled: (0, import_react.useCallback)((enabled) => {}, [])
|
|
28541
|
+
};
|
|
28542
|
+
}
|
|
28543
|
+
function useImperativeHandleMethods({ nodes, pinnedNodes, setPinnedNodes, restart, width, height, layout, handleLayoutChange, svgRef, gRef, setTransform, internalDragEnabledRef }) {
|
|
28544
|
+
return {
|
|
28545
|
+
pinAll: (0, import_react.useCallback)(() => {
|
|
28546
|
+
const newPinned = /* @__PURE__ */ new Set();
|
|
28547
|
+
nodes.forEach((node) => {
|
|
28548
|
+
pinNode(node);
|
|
28549
|
+
newPinned.add(node.id);
|
|
28550
|
+
});
|
|
28551
|
+
setPinnedNodes(newPinned);
|
|
28552
|
+
restart();
|
|
28553
|
+
}, [
|
|
28554
|
+
nodes,
|
|
28555
|
+
setPinnedNodes,
|
|
28556
|
+
restart
|
|
28557
|
+
]),
|
|
28558
|
+
unpinAll: (0, import_react.useCallback)(() => {
|
|
28559
|
+
unpinAllNodes(nodes);
|
|
28560
|
+
setPinnedNodes(/* @__PURE__ */ new Set());
|
|
28561
|
+
restart();
|
|
28562
|
+
}, [
|
|
28563
|
+
nodes,
|
|
28564
|
+
setPinnedNodes,
|
|
28565
|
+
restart
|
|
28566
|
+
]),
|
|
28567
|
+
resetLayout: (0, import_react.useCallback)(() => {
|
|
28568
|
+
unpinAllNodes(nodes);
|
|
28569
|
+
setPinnedNodes(/* @__PURE__ */ new Set());
|
|
28570
|
+
restart();
|
|
28571
|
+
}, [
|
|
28572
|
+
nodes,
|
|
28573
|
+
setPinnedNodes,
|
|
28574
|
+
restart
|
|
28575
|
+
]),
|
|
28576
|
+
fitView: (0, import_react.useCallback)(() => {
|
|
28577
|
+
if (!svgRef.current || !nodes.length) return;
|
|
28578
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
28579
|
+
nodes.forEach((node) => {
|
|
28580
|
+
if (node.x !== void 0 && node.y !== void 0) {
|
|
28581
|
+
const size = node.size || DEFAULT_NODE_SIZE;
|
|
28582
|
+
minX = Math.min(minX, node.x - size);
|
|
28583
|
+
maxX = Math.max(maxX, node.x + size);
|
|
28584
|
+
minY = Math.min(minY, node.y - size);
|
|
28585
|
+
maxY = Math.max(maxY, node.y + size);
|
|
28586
|
+
}
|
|
28587
|
+
});
|
|
28588
|
+
if (!isFinite(minX)) return;
|
|
28589
|
+
const scale = Math.min((width - FIT_VIEW_PADDING * 2) / (maxX - minX), (height - FIT_VIEW_PADDING * 2) / (maxY - minY), 10);
|
|
28590
|
+
const x = width / 2 - (minX + maxX) / 2 * scale;
|
|
28591
|
+
const y = height / 2 - (minY + maxY) / 2 * scale;
|
|
28592
|
+
if (gRef.current && svgRef.current) {
|
|
28593
|
+
const svg = select_default$1(svgRef.current);
|
|
28594
|
+
const newTransform = identity.translate(x, y).scale(scale);
|
|
28595
|
+
svg.transition().duration(TRANSITION_DURATION_MS).call(zoom_default().transform, newTransform);
|
|
28596
|
+
setTransform(newTransform);
|
|
28597
|
+
}
|
|
28598
|
+
}, [
|
|
28599
|
+
nodes,
|
|
28600
|
+
width,
|
|
28601
|
+
height,
|
|
28602
|
+
svgRef,
|
|
28603
|
+
gRef,
|
|
28604
|
+
setTransform
|
|
28605
|
+
]),
|
|
28606
|
+
getPinnedNodes: (0, import_react.useCallback)(() => Array.from(pinnedNodes), [pinnedNodes]),
|
|
28607
|
+
setDragMode: (0, import_react.useCallback)((enabled) => {
|
|
28608
|
+
internalDragEnabledRef.current = enabled;
|
|
28609
|
+
}, [internalDragEnabledRef]),
|
|
28610
|
+
setLayout: (0, import_react.useCallback)((newLayout) => {
|
|
28611
|
+
handleLayoutChange(newLayout);
|
|
28612
|
+
}, [handleLayoutChange]),
|
|
28613
|
+
getLayout: (0, import_react.useCallback)(() => layout, [layout])
|
|
28614
|
+
};
|
|
28615
|
+
}
|
|
28616
|
+
var ControlButton = ({ onClick, active = false, icon, label, disabled = false }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28617
|
+
className: "relative group",
|
|
28618
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
28619
|
+
onClick,
|
|
28620
|
+
disabled,
|
|
28621
|
+
className: cn("p-2 rounded-lg transition-all duration-200", active ? "bg-blue-500 text-white shadow-md hover:bg-blue-600" : "bg-gray-100 text-gray-700 hover:bg-gray-200", disabled && "opacity-50 cursor-not-allowed hover:bg-gray-100", "dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600 dark:active:bg-blue-600"),
|
|
28622
|
+
title: label,
|
|
28623
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
28624
|
+
className: "text-lg",
|
|
28625
|
+
children: icon
|
|
28626
|
+
})
|
|
28627
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
28628
|
+
className: "absolute left-full ml-2 px-2 py-1 bg-gray-900 text-white text-xs rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-50",
|
|
28629
|
+
children: label
|
|
28630
|
+
})]
|
|
28631
|
+
});
|
|
28632
|
+
var GraphControls = ({ dragEnabled = true, onDragToggle, manualLayout = false, onManualLayoutToggle, onPinAll, onUnpinAll, onReset, onFitView, pinnedCount = 0, totalNodes = 0, visible = true, position = "top-left", className }) => {
|
|
28633
|
+
if (!visible) return null;
|
|
28634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28635
|
+
className: cn("fixed z-40 bg-white dark:bg-gray-800 rounded-lg shadow-lg p-2 border border-gray-200 dark:border-gray-700", {
|
|
28636
|
+
"top-left": "top-4 left-4",
|
|
28637
|
+
"top-right": "top-4 right-4",
|
|
28638
|
+
"bottom-left": "bottom-4 left-4",
|
|
28639
|
+
"bottom-right": "bottom-4 right-4"
|
|
28640
|
+
}[position], className),
|
|
28641
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28642
|
+
className: "flex flex-col gap-2",
|
|
28643
|
+
children: [
|
|
28644
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28645
|
+
onClick: () => onDragToggle?.(!dragEnabled),
|
|
28646
|
+
active: dragEnabled,
|
|
28647
|
+
icon: "✋",
|
|
28648
|
+
label: dragEnabled ? "Drag enabled" : "Drag disabled"
|
|
28649
|
+
}),
|
|
28650
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28651
|
+
onClick: () => onManualLayoutToggle?.(!manualLayout),
|
|
28652
|
+
active: manualLayout,
|
|
28653
|
+
icon: "🔧",
|
|
28654
|
+
label: manualLayout ? "Manual layout: ON" : "Manual layout: OFF"
|
|
28655
|
+
}),
|
|
28656
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-8 h-px bg-gray-300 dark:bg-gray-600 mx-auto my-1" }),
|
|
28657
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28658
|
+
className: "flex gap-1",
|
|
28659
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28660
|
+
onClick: () => onPinAll?.(),
|
|
28661
|
+
disabled: totalNodes === 0,
|
|
28662
|
+
icon: "📌",
|
|
28663
|
+
label: `Pin all nodes (${totalNodes})`
|
|
28664
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28665
|
+
onClick: () => onUnpinAll?.(),
|
|
28666
|
+
disabled: pinnedCount === 0,
|
|
28667
|
+
icon: "📍",
|
|
28668
|
+
label: `Unpin all (${pinnedCount} pinned)`
|
|
28669
|
+
})]
|
|
28670
|
+
}),
|
|
28671
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-8 h-px bg-gray-300 dark:bg-gray-600 mx-auto my-1" }),
|
|
28672
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28673
|
+
onClick: () => onFitView?.(),
|
|
28674
|
+
disabled: totalNodes === 0,
|
|
28675
|
+
icon: "🎯",
|
|
28676
|
+
label: "Fit all nodes in view"
|
|
28677
|
+
}),
|
|
28678
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28679
|
+
onClick: () => onReset?.(),
|
|
28680
|
+
disabled: totalNodes === 0,
|
|
28681
|
+
icon: "↺",
|
|
28682
|
+
label: "Reset to auto-layout"
|
|
28683
|
+
})
|
|
28684
|
+
]
|
|
28685
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28686
|
+
className: "mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 text-xs text-gray-600 dark:text-gray-400",
|
|
28687
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28688
|
+
className: "whitespace-nowrap",
|
|
28689
|
+
children: [
|
|
28690
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Nodes:" }),
|
|
28691
|
+
" ",
|
|
28692
|
+
totalNodes
|
|
28693
|
+
]
|
|
28694
|
+
}), pinnedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28695
|
+
className: "whitespace-nowrap",
|
|
28696
|
+
children: [
|
|
28697
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Pinned:" }),
|
|
28698
|
+
" ",
|
|
28699
|
+
pinnedCount
|
|
28700
|
+
]
|
|
28701
|
+
})]
|
|
28702
|
+
})]
|
|
28703
|
+
});
|
|
28704
|
+
};
|
|
28705
|
+
GraphControls.displayName = "GraphControls";
|
|
28338
28706
|
var NodeItem = ({ node, isSelected, isHovered, pinned, defaultNodeSize, defaultNodeColor, showLabel = true, onClick, onDoubleClick, onMouseEnter, onMouseLeave, onMouseDown }) => {
|
|
28339
28707
|
const nodeSize = node.size || defaultNodeSize;
|
|
28340
28708
|
const nodeColor = node.color || defaultNodeColor;
|
|
@@ -28427,19 +28795,6 @@ var LinkItem = ({ link, onClick, defaultWidth, showLabel = true, nodes = [] }) =
|
|
|
28427
28795
|
})] });
|
|
28428
28796
|
};
|
|
28429
28797
|
var LinkItem_default = LinkItem;
|
|
28430
|
-
var DEFAULT_NODE_COLOR = "#64748b";
|
|
28431
|
-
var DEFAULT_NODE_SIZE = 10;
|
|
28432
|
-
var DEFAULT_LINK_COLOR = "#94a3b8";
|
|
28433
|
-
var DEFAULT_LINK_WIDTH = 1;
|
|
28434
|
-
var CIRCULAR_LAYOUT_RADIUS_RATIO = .35;
|
|
28435
|
-
var FIT_VIEW_PADDING = 40;
|
|
28436
|
-
var TRANSITION_DURATION_MS = 300;
|
|
28437
|
-
var PACKAGE_BOUNDARY_FILL = "rgba(148,163,184,0.06)";
|
|
28438
|
-
var PACKAGE_BOUNDARY_STROKE = "#475569";
|
|
28439
|
-
var PACKAGE_BOUNDARY_STROKE_WIDTH = 2;
|
|
28440
|
-
var PACKAGE_BOUNDARY_DASH = "6 6";
|
|
28441
|
-
var PACKAGE_LABEL_FONT_SIZE = 11;
|
|
28442
|
-
var PACKAGE_LABEL_COLOR = "#475569";
|
|
28443
28798
|
var PackageBoundaries = ({ packageBounds }) => {
|
|
28444
28799
|
if (!packageBounds || Object.keys(packageBounds).length === 0) return null;
|
|
28445
28800
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("g", {
|
|
@@ -28466,128 +28821,59 @@ var PackageBoundaries = ({ packageBounds }) => {
|
|
|
28466
28821
|
});
|
|
28467
28822
|
};
|
|
28468
28823
|
PackageBoundaries.displayName = "PackageBoundaries";
|
|
28469
|
-
|
|
28470
|
-
|
|
28471
|
-
|
|
28472
|
-
|
|
28473
|
-
|
|
28474
|
-
|
|
28475
|
-
|
|
28476
|
-
|
|
28477
|
-
|
|
28478
|
-
|
|
28479
|
-
|
|
28480
|
-
|
|
28481
|
-
|
|
28482
|
-
|
|
28483
|
-
|
|
28484
|
-
|
|
28485
|
-
|
|
28486
|
-
|
|
28487
|
-
|
|
28488
|
-
|
|
28489
|
-
|
|
28490
|
-
|
|
28491
|
-
|
|
28492
|
-
|
|
28493
|
-
|
|
28494
|
-
|
|
28495
|
-
|
|
28496
|
-
|
|
28497
|
-
|
|
28498
|
-
|
|
28499
|
-
|
|
28500
|
-
|
|
28501
|
-
|
|
28502
|
-
|
|
28503
|
-
|
|
28504
|
-
|
|
28505
|
-
|
|
28506
|
-
|
|
28507
|
-
|
|
28508
|
-
|
|
28509
|
-
|
|
28510
|
-
|
|
28511
|
-
|
|
28512
|
-
|
|
28513
|
-
|
|
28514
|
-
|
|
28515
|
-
|
|
28516
|
-
|
|
28517
|
-
|
|
28518
|
-
|
|
28519
|
-
|
|
28520
|
-
|
|
28521
|
-
|
|
28522
|
-
transformRef.current = event.transform;
|
|
28523
|
-
setTransform(event.transform);
|
|
28524
|
-
});
|
|
28525
|
-
svg.call(zoom3);
|
|
28526
|
-
return () => {
|
|
28527
|
-
svg.on(".zoom", null);
|
|
28528
|
-
};
|
|
28529
|
-
}, [
|
|
28530
|
-
enableZoom,
|
|
28531
|
-
svgRef,
|
|
28532
|
-
gRef,
|
|
28533
|
-
setTransform,
|
|
28534
|
-
transformRef
|
|
28535
|
-
]);
|
|
28536
|
-
}
|
|
28537
|
-
function useWindowDrag(enableDrag, svgRef, transformRef, dragActiveRef, dragNodeRef, onDragEnd) {
|
|
28538
|
-
(0, import_react.useEffect)(() => {
|
|
28539
|
-
if (!enableDrag) return;
|
|
28540
|
-
const handleWindowMove = (event) => {
|
|
28541
|
-
if (!dragActiveRef.current || !dragNodeRef.current) return;
|
|
28542
|
-
const svg = svgRef.current;
|
|
28543
|
-
if (!svg) return;
|
|
28544
|
-
const rect = svg.getBoundingClientRect();
|
|
28545
|
-
const t = transformRef.current;
|
|
28546
|
-
const x = (event.clientX - rect.left - t.x) / t.k;
|
|
28547
|
-
const y = (event.clientY - rect.top - t.y) / t.k;
|
|
28548
|
-
dragNodeRef.current.fx = x;
|
|
28549
|
-
dragNodeRef.current.fy = y;
|
|
28550
|
-
};
|
|
28551
|
-
const handleWindowUp = () => {
|
|
28552
|
-
if (!dragActiveRef.current) return;
|
|
28553
|
-
onDragEnd();
|
|
28554
|
-
dragNodeRef.current = null;
|
|
28555
|
-
dragActiveRef.current = false;
|
|
28556
|
-
};
|
|
28557
|
-
const handleWindowLeave = (event) => {
|
|
28558
|
-
if (event.relatedTarget === null) handleWindowUp();
|
|
28559
|
-
};
|
|
28560
|
-
window.addEventListener("mousemove", handleWindowMove);
|
|
28561
|
-
window.addEventListener("mouseup", handleWindowUp);
|
|
28562
|
-
window.addEventListener("mouseout", handleWindowLeave);
|
|
28563
|
-
window.addEventListener("blur", handleWindowUp);
|
|
28564
|
-
return () => {
|
|
28565
|
-
window.removeEventListener("mousemove", handleWindowMove);
|
|
28566
|
-
window.removeEventListener("mouseup", handleWindowUp);
|
|
28567
|
-
window.removeEventListener("mouseout", handleWindowLeave);
|
|
28568
|
-
window.removeEventListener("blur", handleWindowUp);
|
|
28569
|
-
};
|
|
28570
|
-
}, [
|
|
28571
|
-
enableDrag,
|
|
28572
|
-
svgRef,
|
|
28573
|
-
transformRef,
|
|
28574
|
-
dragActiveRef,
|
|
28575
|
-
dragNodeRef,
|
|
28576
|
-
onDragEnd
|
|
28577
|
-
]);
|
|
28578
|
-
}
|
|
28579
|
-
function pinNode(node) {
|
|
28580
|
-
node.fx = node.x;
|
|
28581
|
-
node.fy = node.y;
|
|
28582
|
-
}
|
|
28583
|
-
function unpinNode(node) {
|
|
28584
|
-
node.fx = null;
|
|
28585
|
-
node.fy = null;
|
|
28586
|
-
}
|
|
28587
|
-
function unpinAllNodes(nodes) {
|
|
28588
|
-
nodes.forEach(unpinNode);
|
|
28589
|
-
}
|
|
28590
|
-
var ForceDirectedGraph = (0, import_react.forwardRef)(({ nodes: initialNodes, links: initialLinks, width, height, enableZoom = true, enableDrag = true, onNodeClick, onNodeHover, onLinkClick, selectedNodeId, hoveredNodeId, defaultNodeColor = DEFAULT_NODE_COLOR, defaultNodeSize = DEFAULT_NODE_SIZE, defaultLinkColor = DEFAULT_LINK_COLOR, defaultLinkWidth = DEFAULT_LINK_WIDTH, showNodeLabels = true, showLinkLabels = false, className, manualLayout = false, onManualLayoutChange, packageBounds, layout: externalLayout, onLayoutChange }, ref) => {
|
|
28824
|
+
var GraphCanvas = ({ svgRef, gRef, width, height, className, nodes, links, pinnedNodes, selectedNodeId, hoveredNodeId, defaultNodeColor = DEFAULT_NODE_COLOR, defaultNodeSize = DEFAULT_NODE_SIZE, defaultLinkColor = DEFAULT_LINK_COLOR, defaultLinkWidth = DEFAULT_LINK_WIDTH, showNodeLabels = true, showLinkLabels = false, onNodeClick, onNodeHover, onLinkClick, packageBounds, handleNodeDoubleClick, handleDragStart, restart, setPinnedNodes }) => {
|
|
28825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
|
|
28826
|
+
ref: svgRef,
|
|
28827
|
+
width,
|
|
28828
|
+
height,
|
|
28829
|
+
className: cn("bg-white dark:bg-gray-900", className),
|
|
28830
|
+
onDoubleClick: () => {
|
|
28831
|
+
unpinAllNodes(nodes);
|
|
28832
|
+
setPinnedNodes(/* @__PURE__ */ new Set());
|
|
28833
|
+
restart();
|
|
28834
|
+
},
|
|
28835
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("marker", {
|
|
28836
|
+
id: "arrow",
|
|
28837
|
+
viewBox: "0 0 10 10",
|
|
28838
|
+
refX: "20",
|
|
28839
|
+
refY: "5",
|
|
28840
|
+
markerWidth: "6",
|
|
28841
|
+
markerHeight: "6",
|
|
28842
|
+
orient: "auto",
|
|
28843
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
|
|
28844
|
+
d: "M 0 0 L 10 5 L 0 10 z",
|
|
28845
|
+
fill: defaultLinkColor
|
|
28846
|
+
})
|
|
28847
|
+
}) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", {
|
|
28848
|
+
ref: gRef,
|
|
28849
|
+
children: [
|
|
28850
|
+
links.map((link, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkItem_default, {
|
|
28851
|
+
link,
|
|
28852
|
+
onClick: onLinkClick,
|
|
28853
|
+
defaultWidth: defaultLinkWidth,
|
|
28854
|
+
showLabel: showLinkLabels,
|
|
28855
|
+
nodes
|
|
28856
|
+
}, `link-${i}`)),
|
|
28857
|
+
nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NodeItem_default, {
|
|
28858
|
+
node,
|
|
28859
|
+
isSelected: selectedNodeId === node.id,
|
|
28860
|
+
isHovered: hoveredNodeId === node.id,
|
|
28861
|
+
pinned: pinnedNodes.has(node.id),
|
|
28862
|
+
defaultNodeSize,
|
|
28863
|
+
defaultNodeColor,
|
|
28864
|
+
showLabel: showNodeLabels,
|
|
28865
|
+
onClick: onNodeClick,
|
|
28866
|
+
onDoubleClick: handleNodeDoubleClick,
|
|
28867
|
+
onMouseEnter: (n) => onNodeHover?.(n),
|
|
28868
|
+
onMouseLeave: () => onNodeHover?.(null),
|
|
28869
|
+
onMouseDown: handleDragStart
|
|
28870
|
+
}, node.id)),
|
|
28871
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PackageBoundaries, { packageBounds: packageBounds || {} })
|
|
28872
|
+
]
|
|
28873
|
+
})]
|
|
28874
|
+
});
|
|
28875
|
+
};
|
|
28876
|
+
var ForceDirectedGraph = (0, import_react.forwardRef)(({ nodes: initialNodes, links: initialLinks, width, height, enableZoom = true, enableDrag = true, onNodeClick, onNodeHover, onLinkClick, selectedNodeId, hoveredNodeId, defaultNodeColor, defaultNodeSize, defaultLinkColor, defaultLinkWidth, showNodeLabels, showLinkLabels, className, manualLayout = false, onManualLayoutChange, packageBounds, layout: externalLayout, onLayoutChange }, ref) => {
|
|
28591
28877
|
const svgRef = (0, import_react.useRef)(null);
|
|
28592
28878
|
const gRef = (0, import_react.useRef)(null);
|
|
28593
28879
|
const [transform, setTransform] = (0, import_react.useState)({
|
|
@@ -28611,91 +28897,28 @@ var ForceDirectedGraph = (0, import_react.forwardRef)(({ nodes: initialNodes, li
|
|
|
28611
28897
|
(0, import_react.useEffect)(() => {
|
|
28612
28898
|
internalDragEnabledRef.current = enableDrag;
|
|
28613
28899
|
}, [enableDrag]);
|
|
28614
|
-
const
|
|
28615
|
-
|
|
28616
|
-
const copy = initialNodes.map((n) => ({ ...n }));
|
|
28617
|
-
if (layout === "circular") applyCircularLayout(copy, width, height);
|
|
28618
|
-
else if (layout === "hierarchical") applyHierarchicalLayout(copy, width, height);
|
|
28619
|
-
else applyInitialForceLayout(copy, width, height);
|
|
28620
|
-
return copy;
|
|
28621
|
-
}, [
|
|
28622
|
-
initialNodes,
|
|
28623
|
-
width,
|
|
28624
|
-
height,
|
|
28625
|
-
layout
|
|
28626
|
-
]);
|
|
28627
|
-
const restart = import_react.useCallback(() => {}, []);
|
|
28628
|
-
const stop = import_react.useCallback(() => {}, []);
|
|
28629
|
-
const setForcesEnabled = import_react.useCallback((enabled) => {}, []);
|
|
28630
|
-
(0, import_react.useEffect)(() => {
|
|
28631
|
-
if (!nodes || nodes.length === 0) return;
|
|
28632
|
-
if (layout === "circular") applyCircularLayout(nodes, width, height);
|
|
28633
|
-
else if (layout === "hierarchical") applyHierarchicalLayout(nodes, width, height);
|
|
28634
|
-
restart();
|
|
28635
|
-
}, [
|
|
28636
|
-
layout,
|
|
28637
|
-
nodes,
|
|
28638
|
-
width,
|
|
28639
|
-
height,
|
|
28640
|
-
restart
|
|
28641
|
-
]);
|
|
28900
|
+
const { restart, stop, setForcesEnabled } = useSimulationControls();
|
|
28901
|
+
const { nodes } = useGraphLayout(initialNodes, width, height, layout, restart);
|
|
28642
28902
|
(0, import_react.useEffect)(() => {
|
|
28643
|
-
|
|
28644
|
-
else setForcesEnabled(true);
|
|
28903
|
+
setForcesEnabled(!(manualLayout || pinnedNodes.size > 0));
|
|
28645
28904
|
}, [
|
|
28646
28905
|
manualLayout,
|
|
28647
28906
|
pinnedNodes,
|
|
28648
28907
|
setForcesEnabled
|
|
28649
28908
|
]);
|
|
28650
|
-
(0, import_react.useImperativeHandle)(ref, () => ({
|
|
28651
|
-
|
|
28652
|
-
|
|
28653
|
-
|
|
28654
|
-
|
|
28655
|
-
|
|
28656
|
-
|
|
28657
|
-
|
|
28658
|
-
|
|
28659
|
-
|
|
28660
|
-
|
|
28661
|
-
|
|
28662
|
-
|
|
28663
|
-
restart();
|
|
28664
|
-
},
|
|
28665
|
-
resetLayout: () => {
|
|
28666
|
-
unpinAllNodes(nodes);
|
|
28667
|
-
setPinnedNodes(/* @__PURE__ */ new Set());
|
|
28668
|
-
restart();
|
|
28669
|
-
},
|
|
28670
|
-
fitView: () => {
|
|
28671
|
-
if (!svgRef.current || !nodes.length) return;
|
|
28672
|
-
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
28673
|
-
nodes.forEach((node) => {
|
|
28674
|
-
if (node.x !== void 0 && node.y !== void 0) {
|
|
28675
|
-
const size = node.size || DEFAULT_NODE_SIZE;
|
|
28676
|
-
minX = Math.min(minX, node.x - size);
|
|
28677
|
-
maxX = Math.max(maxX, node.x + size);
|
|
28678
|
-
minY = Math.min(minY, node.y - size);
|
|
28679
|
-
maxY = Math.max(maxY, node.y + size);
|
|
28680
|
-
}
|
|
28681
|
-
});
|
|
28682
|
-
if (!isFinite(minX)) return;
|
|
28683
|
-
const scale = Math.min((width - FIT_VIEW_PADDING * 2) / (maxX - minX), (height - FIT_VIEW_PADDING * 2) / (maxY - minY), 10);
|
|
28684
|
-
const x = width / 2 - (minX + maxX) / 2 * scale;
|
|
28685
|
-
const y = height / 2 - (minY + maxY) / 2 * scale;
|
|
28686
|
-
if (gRef.current && svgRef.current) {
|
|
28687
|
-
const svg = select_default$1(svgRef.current);
|
|
28688
|
-
const newTransform = identity.translate(x, y).scale(scale);
|
|
28689
|
-
svg.transition().duration(TRANSITION_DURATION_MS).call(zoom_default().transform, newTransform);
|
|
28690
|
-
setTransform(newTransform);
|
|
28691
|
-
}
|
|
28692
|
-
},
|
|
28693
|
-
getPinnedNodes: () => Array.from(pinnedNodes),
|
|
28694
|
-
setDragMode: (enabled) => {
|
|
28695
|
-
internalDragEnabledRef.current = enabled;
|
|
28696
|
-
},
|
|
28697
|
-
setLayout: (newLayout) => handleLayoutChange(newLayout),
|
|
28698
|
-
getLayout: () => layout
|
|
28909
|
+
(0, import_react.useImperativeHandle)(ref, () => useImperativeHandleMethods({
|
|
28910
|
+
nodes,
|
|
28911
|
+
pinnedNodes,
|
|
28912
|
+
setPinnedNodes,
|
|
28913
|
+
restart,
|
|
28914
|
+
width,
|
|
28915
|
+
height,
|
|
28916
|
+
layout,
|
|
28917
|
+
handleLayoutChange,
|
|
28918
|
+
svgRef,
|
|
28919
|
+
gRef,
|
|
28920
|
+
setTransform,
|
|
28921
|
+
internalDragEnabledRef
|
|
28699
28922
|
}), [
|
|
28700
28923
|
nodes,
|
|
28701
28924
|
pinnedNodes,
|
|
@@ -28707,7 +28930,7 @@ var ForceDirectedGraph = (0, import_react.forwardRef)(({ nodes: initialNodes, li
|
|
|
28707
28930
|
setForcesEnabled
|
|
28708
28931
|
]);
|
|
28709
28932
|
(0, import_react.useEffect)(() => {
|
|
28710
|
-
|
|
28933
|
+
onManualLayoutChange?.(manualLayout);
|
|
28711
28934
|
}, [manualLayout, onManualLayoutChange]);
|
|
28712
28935
|
useGraphZoom(svgRef, gRef, enableZoom, setTransform, transformRef);
|
|
28713
28936
|
useWindowDrag(enableDrag, svgRef, transformRef, dragActiveRef, dragNodeRef, () => {
|
|
@@ -28718,47 +28941,32 @@ var ForceDirectedGraph = (0, import_react.forwardRef)(({ nodes: initialNodes, li
|
|
|
28718
28941
|
if (!gRef.current) return;
|
|
28719
28942
|
const g = select_default$1(gRef.current);
|
|
28720
28943
|
g.selectAll("g.node").each(function() {
|
|
28721
|
-
const
|
|
28722
|
-
if (
|
|
28723
|
-
select_default$1(this).attr("transform", `translate(${datum.x || 0},${datum.y || 0})`);
|
|
28944
|
+
const d = select_default$1(this).datum();
|
|
28945
|
+
if (d) select_default$1(this).attr("transform", `translate(${d.x || 0},${d.y || 0})`);
|
|
28724
28946
|
});
|
|
28725
28947
|
g.selectAll("line").each(function() {
|
|
28726
28948
|
const l = select_default$1(this).datum();
|
|
28727
28949
|
if (!l) return;
|
|
28728
|
-
const s = typeof l.source === "object" ? l.source : nodes.find((n) => n.id === l.source)
|
|
28729
|
-
const t = typeof l.target === "object" ? l.target : nodes.find((n) => n.id === l.target)
|
|
28730
|
-
if (
|
|
28731
|
-
select_default$1(this).attr("x1", s.x).attr("y1", s.y).attr("x2", t.x).attr("y2", t.y);
|
|
28950
|
+
const s = typeof l.source === "object" ? l.source : nodes.find((n) => n.id === l.source);
|
|
28951
|
+
const t = typeof l.target === "object" ? l.target : nodes.find((n) => n.id === l.target);
|
|
28952
|
+
if (s && t) select_default$1(this).attr("x1", s.x).attr("y1", s.y).attr("x2", t.x).attr("y2", t.y);
|
|
28732
28953
|
});
|
|
28733
28954
|
}, [nodes, initialLinks]);
|
|
28734
|
-
const handleDragStart = (
|
|
28735
|
-
if (!enableDrag) return;
|
|
28736
|
-
event.preventDefault();
|
|
28737
|
-
event.stopPropagation();
|
|
28738
|
-
dragActiveRef.current = true;
|
|
28739
|
-
dragNodeRef.current = node;
|
|
28740
|
-
pinNode(node);
|
|
28741
|
-
setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
|
|
28742
|
-
stop();
|
|
28743
|
-
}, [enableDrag, stop]);
|
|
28955
|
+
const { handleDragStart, handleNodeDoubleClick } = useNodeInteractions(enableDrag, nodes, pinnedNodes, setPinnedNodes, restart, stop);
|
|
28744
28956
|
(0, import_react.useEffect)(() => {
|
|
28745
28957
|
if (!gRef.current || !enableDrag) return;
|
|
28746
28958
|
const g = select_default$1(gRef.current);
|
|
28747
28959
|
const dragBehavior = drag_default().on("start", (event) => {
|
|
28748
|
-
const id = (
|
|
28960
|
+
const id = (event.sourceEvent?.target || event.target).closest?.("g.node")?.getAttribute("data-id");
|
|
28749
28961
|
if (!id || !internalDragEnabledRef.current) return;
|
|
28750
28962
|
const node = nodes.find((n) => n.id === id);
|
|
28751
28963
|
if (!node) return;
|
|
28752
28964
|
if (!event.active) restart();
|
|
28753
28965
|
dragActiveRef.current = true;
|
|
28754
28966
|
dragNodeRef.current = node;
|
|
28755
|
-
pinNode(node);
|
|
28756
|
-
setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
|
|
28757
28967
|
}).on("drag", (event) => {
|
|
28758
|
-
if (!dragActiveRef.current || !dragNodeRef.current) return;
|
|
28759
|
-
const
|
|
28760
|
-
if (!svg) return;
|
|
28761
|
-
const rect = svg.getBoundingClientRect();
|
|
28968
|
+
if (!dragActiveRef.current || !dragNodeRef.current || !svgRef.current) return;
|
|
28969
|
+
const rect = svgRef.current.getBoundingClientRect();
|
|
28762
28970
|
dragNodeRef.current.fx = (event.sourceEvent.clientX - rect.left - transform.x) / transform.k;
|
|
28763
28971
|
dragNodeRef.current.fy = (event.sourceEvent.clientY - rect.top - transform.y) / transform.k;
|
|
28764
28972
|
}).on("end", () => {
|
|
@@ -28775,183 +28983,36 @@ var ForceDirectedGraph = (0, import_react.forwardRef)(({ nodes: initialNodes, li
|
|
|
28775
28983
|
nodes,
|
|
28776
28984
|
transform,
|
|
28777
28985
|
restart,
|
|
28778
|
-
setForcesEnabled
|
|
28779
|
-
internalDragEnabledRef
|
|
28986
|
+
setForcesEnabled
|
|
28780
28987
|
]);
|
|
28781
|
-
|
|
28782
|
-
|
|
28783
|
-
|
|
28784
|
-
if (node.fx === null || node.fx === void 0) {
|
|
28785
|
-
pinNode(node);
|
|
28786
|
-
setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
|
|
28787
|
-
} else {
|
|
28788
|
-
unpinNode(node);
|
|
28789
|
-
setPinnedNodes((prev) => {
|
|
28790
|
-
const next = new Set(prev);
|
|
28791
|
-
next.delete(node.id);
|
|
28792
|
-
return next;
|
|
28793
|
-
});
|
|
28794
|
-
}
|
|
28795
|
-
restart();
|
|
28796
|
-
}, [enableDrag, restart]);
|
|
28797
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
|
|
28798
|
-
ref: svgRef,
|
|
28988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GraphCanvas, {
|
|
28989
|
+
svgRef,
|
|
28990
|
+
gRef,
|
|
28799
28991
|
width,
|
|
28800
28992
|
height,
|
|
28801
|
-
className
|
|
28802
|
-
|
|
28803
|
-
|
|
28804
|
-
|
|
28805
|
-
|
|
28806
|
-
|
|
28807
|
-
|
|
28808
|
-
|
|
28809
|
-
|
|
28810
|
-
|
|
28811
|
-
|
|
28812
|
-
|
|
28813
|
-
|
|
28814
|
-
|
|
28815
|
-
|
|
28816
|
-
|
|
28817
|
-
|
|
28818
|
-
|
|
28819
|
-
|
|
28820
|
-
|
|
28821
|
-
children: [
|
|
28822
|
-
initialLinks.map((link, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkItem_default, {
|
|
28823
|
-
link,
|
|
28824
|
-
onClick: onLinkClick,
|
|
28825
|
-
defaultWidth: defaultLinkWidth,
|
|
28826
|
-
showLabel: showLinkLabels,
|
|
28827
|
-
nodes
|
|
28828
|
-
}, `link-${i}`)),
|
|
28829
|
-
nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NodeItem_default, {
|
|
28830
|
-
node,
|
|
28831
|
-
isSelected: selectedNodeId === node.id,
|
|
28832
|
-
isHovered: hoveredNodeId === node.id,
|
|
28833
|
-
pinned: pinnedNodes.has(node.id),
|
|
28834
|
-
defaultNodeSize,
|
|
28835
|
-
defaultNodeColor,
|
|
28836
|
-
showLabel: showNodeLabels,
|
|
28837
|
-
onClick: onNodeClick,
|
|
28838
|
-
onDoubleClick: handleNodeDoubleClick,
|
|
28839
|
-
onMouseEnter: (n) => onNodeHover?.(n),
|
|
28840
|
-
onMouseLeave: () => onNodeHover?.(null),
|
|
28841
|
-
onMouseDown: handleDragStart
|
|
28842
|
-
}, node.id)),
|
|
28843
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PackageBoundaries, { packageBounds: packageBounds || {} })
|
|
28844
|
-
]
|
|
28845
|
-
})]
|
|
28993
|
+
className,
|
|
28994
|
+
nodes,
|
|
28995
|
+
links: initialLinks,
|
|
28996
|
+
pinnedNodes,
|
|
28997
|
+
selectedNodeId,
|
|
28998
|
+
hoveredNodeId,
|
|
28999
|
+
defaultNodeColor,
|
|
29000
|
+
defaultNodeSize,
|
|
29001
|
+
defaultLinkColor,
|
|
29002
|
+
defaultLinkWidth,
|
|
29003
|
+
showNodeLabels,
|
|
29004
|
+
showLinkLabels,
|
|
29005
|
+
onNodeClick,
|
|
29006
|
+
onNodeHover,
|
|
29007
|
+
onLinkClick,
|
|
29008
|
+
packageBounds,
|
|
29009
|
+
handleNodeDoubleClick,
|
|
29010
|
+
handleDragStart,
|
|
29011
|
+
restart,
|
|
29012
|
+
setPinnedNodes
|
|
28846
29013
|
});
|
|
28847
29014
|
});
|
|
28848
29015
|
ForceDirectedGraph.displayName = "ForceDirectedGraph";
|
|
28849
|
-
var GraphControls = ({ dragEnabled = true, onDragToggle, manualLayout = false, onManualLayoutToggle, onPinAll, onUnpinAll, onReset, onFitView, pinnedCount = 0, totalNodes = 0, visible = true, position = "top-left", className }) => {
|
|
28850
|
-
if (!visible) return null;
|
|
28851
|
-
const positionClasses = {
|
|
28852
|
-
"top-left": "top-4 left-4",
|
|
28853
|
-
"top-right": "top-4 right-4",
|
|
28854
|
-
"bottom-left": "bottom-4 left-4",
|
|
28855
|
-
"bottom-right": "bottom-4 right-4"
|
|
28856
|
-
};
|
|
28857
|
-
const ControlButton = ({ onClick, active = false, icon, label, disabled = false }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28858
|
-
className: "relative group",
|
|
28859
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
28860
|
-
onClick,
|
|
28861
|
-
disabled,
|
|
28862
|
-
className: cn("p-2 rounded-lg transition-all duration-200", active ? "bg-blue-500 text-white shadow-md hover:bg-blue-600" : "bg-gray-100 text-gray-700 hover:bg-gray-200", disabled && "opacity-50 cursor-not-allowed hover:bg-gray-100", "dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600 dark:active:bg-blue-600"),
|
|
28863
|
-
title: label,
|
|
28864
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
28865
|
-
className: "text-lg",
|
|
28866
|
-
children: icon
|
|
28867
|
-
})
|
|
28868
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
28869
|
-
className: "absolute left-full ml-2 px-2 py-1 bg-gray-900 text-white text-xs rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-50",
|
|
28870
|
-
children: label
|
|
28871
|
-
})]
|
|
28872
|
-
});
|
|
28873
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28874
|
-
className: cn("fixed z-40 bg-white dark:bg-gray-800 rounded-lg shadow-lg p-2 border border-gray-200 dark:border-gray-700", positionClasses[position], className),
|
|
28875
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28876
|
-
className: "flex flex-col gap-2",
|
|
28877
|
-
children: [
|
|
28878
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28879
|
-
onClick: () => onDragToggle?.(!dragEnabled),
|
|
28880
|
-
active: dragEnabled,
|
|
28881
|
-
icon: "✋",
|
|
28882
|
-
label: dragEnabled ? "Drag enabled" : "Drag disabled"
|
|
28883
|
-
}),
|
|
28884
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28885
|
-
onClick: () => onManualLayoutToggle?.(!manualLayout),
|
|
28886
|
-
active: manualLayout,
|
|
28887
|
-
icon: "🔧",
|
|
28888
|
-
label: manualLayout ? "Manual layout: ON (drag freely)" : "Manual layout: OFF (forces active)"
|
|
28889
|
-
}),
|
|
28890
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-8 h-px bg-gray-300 dark:bg-gray-600 mx-auto my-1" }),
|
|
28891
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28892
|
-
className: "flex gap-1",
|
|
28893
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28894
|
-
onClick: () => onPinAll?.(),
|
|
28895
|
-
disabled: totalNodes === 0,
|
|
28896
|
-
icon: "📌",
|
|
28897
|
-
label: `Pin all nodes (${totalNodes})`
|
|
28898
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28899
|
-
onClick: () => onUnpinAll?.(),
|
|
28900
|
-
disabled: pinnedCount === 0,
|
|
28901
|
-
icon: "📍",
|
|
28902
|
-
label: `Unpin all (${pinnedCount} pinned)`
|
|
28903
|
-
})]
|
|
28904
|
-
}),
|
|
28905
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-8 h-px bg-gray-300 dark:bg-gray-600 mx-auto my-1" }),
|
|
28906
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28907
|
-
onClick: () => onFitView?.(),
|
|
28908
|
-
disabled: totalNodes === 0,
|
|
28909
|
-
icon: "🎯",
|
|
28910
|
-
label: "Fit all nodes in view"
|
|
28911
|
-
}),
|
|
28912
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, {
|
|
28913
|
-
onClick: () => onReset?.(),
|
|
28914
|
-
disabled: totalNodes === 0,
|
|
28915
|
-
icon: "↺",
|
|
28916
|
-
label: "Reset to auto-layout"
|
|
28917
|
-
})
|
|
28918
|
-
]
|
|
28919
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28920
|
-
className: "mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 text-xs text-gray-600 dark:text-gray-400",
|
|
28921
|
-
children: [
|
|
28922
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28923
|
-
className: "whitespace-nowrap",
|
|
28924
|
-
children: [
|
|
28925
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Nodes:" }),
|
|
28926
|
-
" ",
|
|
28927
|
-
totalNodes
|
|
28928
|
-
]
|
|
28929
|
-
}),
|
|
28930
|
-
pinnedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28931
|
-
className: "whitespace-nowrap",
|
|
28932
|
-
children: [
|
|
28933
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Pinned:" }),
|
|
28934
|
-
" ",
|
|
28935
|
-
pinnedCount
|
|
28936
|
-
]
|
|
28937
|
-
}),
|
|
28938
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
28939
|
-
className: "mt-2 text-gray-500 dark:text-gray-500 leading-snug",
|
|
28940
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Tips:" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", {
|
|
28941
|
-
className: "mt-1 ml-1 space-y-0.5",
|
|
28942
|
-
children: [
|
|
28943
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: "• Drag nodes to reposition" }),
|
|
28944
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: "• Double-click to pin/unpin" }),
|
|
28945
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: "• Double-click canvas to unpin all" }),
|
|
28946
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: "• Scroll to zoom" })
|
|
28947
|
-
]
|
|
28948
|
-
})]
|
|
28949
|
-
})
|
|
28950
|
-
]
|
|
28951
|
-
})]
|
|
28952
|
-
});
|
|
28953
|
-
};
|
|
28954
|
-
GraphControls.displayName = "GraphControls";
|
|
28955
29016
|
//#endregion
|
|
28956
29017
|
//#region src/components/LegendPanel.tsx
|
|
28957
29018
|
function LegendItemWithToggle({ color, label, isGlow = false, isLine = false, colors, isVisible, onToggle }) {
|
|
@@ -29286,4 +29347,4 @@ function App() {
|
|
|
29286
29347
|
(0, import_client.createRoot)(document.getElementById("root")).render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.StrictMode, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(App, {}) }));
|
|
29287
29348
|
//#endregion
|
|
29288
29349
|
|
|
29289
|
-
//# sourceMappingURL=index-
|
|
29350
|
+
//# sourceMappingURL=index-CkabxYJ5.js.map
|