@aiready/components 0.13.6 → 0.13.8

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.
@@ -1,5 +1,5 @@
1
1
  import React, { forwardRef, useRef, useState, useEffect, useCallback, useImperativeHandle } from 'react';
2
- import * as d3 from 'd3';
2
+ import * as d32 from 'd3';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -137,6 +137,155 @@ var LinkItem = ({
137
137
  ] });
138
138
  };
139
139
  var LinkItem_default = LinkItem;
140
+
141
+ // src/charts/constants.ts
142
+ var DEFAULT_NODE_COLOR = "#64748b";
143
+ var DEFAULT_NODE_SIZE = 10;
144
+ var DEFAULT_LINK_COLOR = "#94a3b8";
145
+ var DEFAULT_LINK_WIDTH = 1;
146
+ var CIRCULAR_LAYOUT_RADIUS_RATIO = 0.35;
147
+ var FIT_VIEW_PADDING = 40;
148
+ var TRANSITION_DURATION_MS = 300;
149
+ var PACKAGE_BOUNDARY_FILL = "rgba(148,163,184,0.06)";
150
+ var PACKAGE_BOUNDARY_STROKE = "#475569";
151
+ var PACKAGE_BOUNDARY_STROKE_WIDTH = 2;
152
+ var PACKAGE_BOUNDARY_DASH = "6 6";
153
+ var PACKAGE_LABEL_FONT_SIZE = 11;
154
+ var PACKAGE_LABEL_COLOR = "#475569";
155
+ var PackageBoundaries = ({
156
+ packageBounds
157
+ }) => {
158
+ if (!packageBounds || Object.keys(packageBounds).length === 0) return null;
159
+ return /* @__PURE__ */ jsx("g", { className: "package-boundaries", pointerEvents: "none", children: Object.entries(packageBounds).map(([pid, b]) => /* @__PURE__ */ jsxs("g", { children: [
160
+ /* @__PURE__ */ jsx(
161
+ "circle",
162
+ {
163
+ cx: b.x,
164
+ cy: b.y,
165
+ r: b.r,
166
+ fill: PACKAGE_BOUNDARY_FILL,
167
+ stroke: PACKAGE_BOUNDARY_STROKE,
168
+ strokeWidth: PACKAGE_BOUNDARY_STROKE_WIDTH,
169
+ strokeDasharray: PACKAGE_BOUNDARY_DASH,
170
+ opacity: 0.9
171
+ }
172
+ ),
173
+ /* @__PURE__ */ jsx(
174
+ "text",
175
+ {
176
+ x: b.x,
177
+ y: Math.max(12, b.y - b.r + 14),
178
+ fill: PACKAGE_LABEL_COLOR,
179
+ fontSize: PACKAGE_LABEL_FONT_SIZE,
180
+ textAnchor: "middle",
181
+ pointerEvents: "none",
182
+ children: pid.replace(/^pkg:/, "")
183
+ }
184
+ )
185
+ ] }, pid)) });
186
+ };
187
+ PackageBoundaries.displayName = "PackageBoundaries";
188
+
189
+ // src/charts/layout-utils.ts
190
+ function applyCircularLayout(nodes, width, height) {
191
+ const centerX = width / 2;
192
+ const centerY = height / 2;
193
+ const radius = Math.min(width, height) * CIRCULAR_LAYOUT_RADIUS_RATIO;
194
+ nodes.forEach((node, i) => {
195
+ const angle = 2 * Math.PI * i / nodes.length;
196
+ node.fx = centerX + Math.cos(angle) * radius;
197
+ node.fy = centerY + Math.sin(angle) * radius;
198
+ node.x = node.fx;
199
+ node.y = node.fy;
200
+ });
201
+ }
202
+ function applyHierarchicalLayout(nodes, width, height) {
203
+ const groups = /* @__PURE__ */ new Map();
204
+ nodes.forEach((n) => {
205
+ const key = n.packageGroup || n.group || "root";
206
+ if (!groups.has(key)) groups.set(key, []);
207
+ groups.get(key).push(n);
208
+ });
209
+ const groupArray = Array.from(groups.entries());
210
+ const cols = Math.ceil(Math.sqrt(groupArray.length));
211
+ const groupSpacingX = width * 0.8 / cols;
212
+ const groupSpacingY = height * 0.8 / Math.ceil(groupArray.length / cols);
213
+ groupArray.forEach(([groupKey, groupNodes], gi) => {
214
+ const col = gi % cols;
215
+ const row = Math.floor(gi / cols);
216
+ const groupX = (col + 0.5) * groupSpacingX;
217
+ const groupY = (row + 0.5) * groupSpacingY;
218
+ if (groupKey.startsWith("pkg:") || groupKey === groupKey) {
219
+ groupNodes.forEach((n, ni) => {
220
+ const angle = 2 * Math.PI * ni / groupNodes.length;
221
+ const r = Math.min(80, 20 + groupNodes.length * 8);
222
+ n.fx = groupX + Math.cos(angle) * r;
223
+ n.fy = groupY + Math.sin(angle) * r;
224
+ n.x = n.fx;
225
+ n.y = n.fy;
226
+ });
227
+ }
228
+ });
229
+ }
230
+ function applyInitialForceLayout(nodes, width, height) {
231
+ nodes.forEach((node) => {
232
+ if (node.fx === void 0 || node.fx === null) {
233
+ node.x = Math.random() * width;
234
+ node.y = Math.random() * height;
235
+ }
236
+ });
237
+ }
238
+ function useGraphZoom(svgRef, gRef, enableZoom, setTransform, transformRef) {
239
+ useEffect(() => {
240
+ if (!enableZoom || !svgRef.current || !gRef.current) return;
241
+ const svg = d32.select(svgRef.current);
242
+ const g = d32.select(gRef.current);
243
+ const zoom3 = d32.zoom().scaleExtent([0.1, 10]).on("zoom", (event) => {
244
+ g.attr("transform", event.transform);
245
+ transformRef.current = event.transform;
246
+ setTransform(event.transform);
247
+ });
248
+ svg.call(zoom3);
249
+ return () => {
250
+ svg.on(".zoom", null);
251
+ };
252
+ }, [enableZoom, svgRef, gRef, setTransform, transformRef]);
253
+ }
254
+ function useWindowDrag(enableDrag, svgRef, transformRef, dragActiveRef, dragNodeRef, onDragEnd) {
255
+ useEffect(() => {
256
+ if (!enableDrag) return;
257
+ const handleWindowMove = (event) => {
258
+ if (!dragActiveRef.current || !dragNodeRef.current) return;
259
+ const svg = svgRef.current;
260
+ if (!svg) return;
261
+ const rect = svg.getBoundingClientRect();
262
+ const t = transformRef.current;
263
+ const x = (event.clientX - rect.left - t.x) / t.k;
264
+ const y = (event.clientY - rect.top - t.y) / t.k;
265
+ dragNodeRef.current.fx = x;
266
+ dragNodeRef.current.fy = y;
267
+ };
268
+ const handleWindowUp = () => {
269
+ if (!dragActiveRef.current) return;
270
+ onDragEnd();
271
+ dragNodeRef.current = null;
272
+ dragActiveRef.current = false;
273
+ };
274
+ const handleWindowLeave = (event) => {
275
+ if (event.relatedTarget === null) handleWindowUp();
276
+ };
277
+ window.addEventListener("mousemove", handleWindowMove);
278
+ window.addEventListener("mouseup", handleWindowUp);
279
+ window.addEventListener("mouseout", handleWindowLeave);
280
+ window.addEventListener("blur", handleWindowUp);
281
+ return () => {
282
+ window.removeEventListener("mousemove", handleWindowMove);
283
+ window.removeEventListener("mouseup", handleWindowUp);
284
+ window.removeEventListener("mouseout", handleWindowLeave);
285
+ window.removeEventListener("blur", handleWindowUp);
286
+ };
287
+ }, [enableDrag, svgRef, transformRef, dragActiveRef, dragNodeRef, onDragEnd]);
288
+ }
140
289
  var ForceDirectedGraph = forwardRef(
141
290
  ({
142
291
  nodes: initialNodes,
@@ -150,10 +299,10 @@ var ForceDirectedGraph = forwardRef(
150
299
  onLinkClick,
151
300
  selectedNodeId,
152
301
  hoveredNodeId,
153
- defaultNodeColor = "#69b3a2",
154
- defaultNodeSize = 10,
155
- defaultLinkColor = "#999",
156
- defaultLinkWidth = 1,
302
+ defaultNodeColor = DEFAULT_NODE_COLOR,
303
+ defaultNodeSize = DEFAULT_NODE_SIZE,
304
+ defaultLinkColor = DEFAULT_LINK_COLOR,
305
+ defaultLinkWidth = DEFAULT_LINK_WIDTH,
157
306
  showNodeLabels = true,
158
307
  showLinkLabels = false,
159
308
  className,
@@ -176,7 +325,7 @@ var ForceDirectedGraph = forwardRef(
176
325
  if (externalLayout && externalLayout !== layout) {
177
326
  setLayout(externalLayout);
178
327
  }
179
- }, [externalLayout]);
328
+ }, [externalLayout, layout]);
180
329
  const handleLayoutChange = useCallback(
181
330
  (newLayout) => {
182
331
  setLayout(newLayout);
@@ -189,36 +338,13 @@ var ForceDirectedGraph = forwardRef(
189
338
  }, [enableDrag]);
190
339
  const nodes = React.useMemo(() => {
191
340
  if (!initialNodes || !initialNodes.length) return initialNodes;
192
- const centerX = width / 2;
193
- const centerY = height / 2;
194
- if (layout === "force") {
195
- return initialNodes.map((n) => ({
196
- ...n,
197
- x: Math.random() * width,
198
- y: Math.random() * height
199
- }));
200
- }
201
- if (layout === "circular") {
202
- const radius = Math.min(width, height) * 0.35;
203
- return initialNodes.map((n, i) => ({
204
- ...n,
205
- x: centerX + Math.cos(2 * Math.PI * i / initialNodes.length) * radius,
206
- y: centerY + Math.sin(2 * Math.PI * i / initialNodes.length) * radius
207
- }));
208
- }
209
- if (layout === "hierarchical") {
210
- const cols = Math.ceil(Math.sqrt(initialNodes.length));
211
- const spacingX = width / (cols + 1);
212
- const spacingY = height / (Math.ceil(initialNodes.length / cols) + 1);
213
- return initialNodes.map((n, i) => ({
214
- ...n,
215
- x: spacingX * (i % cols + 1),
216
- y: spacingY * (Math.floor(i / cols) + 1)
217
- }));
218
- }
219
- return initialNodes;
341
+ const copy = initialNodes.map((n) => ({ ...n }));
342
+ if (layout === "circular") applyCircularLayout(copy, width, height);
343
+ else if (layout === "hierarchical")
344
+ applyHierarchicalLayout(copy, width, height);
345
+ else applyInitialForceLayout(copy, width, height);
346
+ return copy;
220
347
  }, [initialNodes, width, height, layout]);
221
- const links = initialLinks;
222
348
  const restart = React.useCallback(() => {
223
349
  }, []);
224
350
  const stop = React.useCallback(() => {
@@ -227,55 +353,14 @@ var ForceDirectedGraph = forwardRef(
227
353
  }, []);
228
354
  useEffect(() => {
229
355
  if (!nodes || nodes.length === 0) return;
230
- const applyLayout = () => {
231
- const centerX = width / 2;
232
- const centerY = height / 2;
233
- if (layout === "circular") {
234
- const radius = Math.min(width, height) * 0.35;
235
- nodes.forEach((node, i) => {
236
- const angle = 2 * Math.PI * i / nodes.length;
237
- node.fx = centerX + Math.cos(angle) * radius;
238
- node.fy = centerY + Math.sin(angle) * radius;
239
- });
240
- } else if (layout === "hierarchical") {
241
- const groups = /* @__PURE__ */ new Map();
242
- nodes.forEach((n) => {
243
- const key = n.packageGroup || n.group || "root";
244
- if (!groups.has(key)) groups.set(key, []);
245
- groups.get(key).push(n);
246
- });
247
- const groupArray = Array.from(groups.entries());
248
- const cols = Math.ceil(Math.sqrt(groupArray.length));
249
- const groupSpacingX = width * 0.8 / cols;
250
- const groupSpacingY = height * 0.8 / Math.ceil(groupArray.length / cols);
251
- groupArray.forEach(([groupKey, groupNodes], gi) => {
252
- const col = gi % cols;
253
- const row = Math.floor(gi / cols);
254
- const groupX = (col + 0.5) * groupSpacingX;
255
- const groupY = (row + 0.5) * groupSpacingY;
256
- if (groupKey.startsWith("pkg:") || groupKey === groupKey) {
257
- groupNodes.forEach((n, ni) => {
258
- const angle = 2 * Math.PI * ni / groupNodes.length;
259
- const r = Math.min(80, 20 + groupNodes.length * 8);
260
- n.fx = groupX + Math.cos(angle) * r;
261
- n.fy = groupY + Math.sin(angle) * r;
262
- });
263
- }
264
- });
265
- }
266
- try {
267
- restart();
268
- } catch (e) {
269
- }
270
- };
271
- applyLayout();
356
+ if (layout === "circular") applyCircularLayout(nodes, width, height);
357
+ else if (layout === "hierarchical")
358
+ applyHierarchicalLayout(nodes, width, height);
359
+ restart();
272
360
  }, [layout, nodes, width, height, restart]);
273
361
  useEffect(() => {
274
- try {
275
- if (manualLayout || pinnedNodes.size > 0) setForcesEnabled(false);
276
- else setForcesEnabled(true);
277
- } catch (e) {
278
- }
362
+ if (manualLayout || pinnedNodes.size > 0) setForcesEnabled(false);
363
+ else setForcesEnabled(true);
279
364
  }, [manualLayout, pinnedNodes, setForcesEnabled]);
280
365
  useImperativeHandle(
281
366
  ref,
@@ -311,7 +396,7 @@ var ForceDirectedGraph = forwardRef(
311
396
  let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
312
397
  nodes.forEach((node) => {
313
398
  if (node.x !== void 0 && node.y !== void 0) {
314
- const size = node.size || 10;
399
+ const size = node.size || DEFAULT_NODE_SIZE;
315
400
  minX = Math.min(minX, node.x - size);
316
401
  maxX = Math.max(maxX, node.x + size);
317
402
  minY = Math.min(minY, node.y - size);
@@ -319,22 +404,17 @@ var ForceDirectedGraph = forwardRef(
319
404
  }
320
405
  });
321
406
  if (!isFinite(minX)) return;
322
- const padding = 40;
323
- const nodeWidth = maxX - minX;
324
- const nodeHeight = maxY - minY;
325
407
  const scale = Math.min(
326
- (width - padding * 2) / nodeWidth,
327
- (height - padding * 2) / nodeHeight,
408
+ (width - FIT_VIEW_PADDING * 2) / (maxX - minX),
409
+ (height - FIT_VIEW_PADDING * 2) / (maxY - minY),
328
410
  10
329
411
  );
330
- const centerX = (minX + maxX) / 2;
331
- const centerY = (minY + maxY) / 2;
332
- const x = width / 2 - centerX * scale;
333
- const y = height / 2 - centerY * scale;
412
+ const x = width / 2 - (minX + maxX) / 2 * scale;
413
+ const y = height / 2 - (minY + maxY) / 2 * scale;
334
414
  if (gRef.current && svgRef.current) {
335
- const svg = d3.select(svgRef.current);
336
- const newTransform = d3.zoomIdentity.translate(x, y).scale(scale);
337
- svg.transition().duration(300).call(d3.zoom().transform, newTransform);
415
+ const svg = d32.select(svgRef.current);
416
+ const newTransform = d32.zoomIdentity.translate(x, y).scale(scale);
417
+ svg.transition().duration(TRANSITION_DURATION_MS).call(d32.zoom().transform, newTransform);
338
418
  setTransform(newTransform);
339
419
  }
340
420
  },
@@ -342,57 +422,56 @@ var ForceDirectedGraph = forwardRef(
342
422
  setDragMode: (enabled) => {
343
423
  internalDragEnabledRef.current = enabled;
344
424
  },
345
- setLayout: (newLayout) => {
346
- handleLayoutChange(newLayout);
347
- },
425
+ setLayout: (newLayout) => handleLayoutChange(newLayout),
348
426
  getLayout: () => layout
349
427
  }),
350
- [nodes, pinnedNodes, restart, width, height, layout, handleLayoutChange]
428
+ [
429
+ nodes,
430
+ pinnedNodes,
431
+ restart,
432
+ width,
433
+ height,
434
+ layout,
435
+ handleLayoutChange,
436
+ setForcesEnabled
437
+ ]
351
438
  );
352
439
  useEffect(() => {
353
- try {
354
- if (typeof onManualLayoutChange === "function")
355
- onManualLayoutChange(manualLayout);
356
- } catch (e) {
357
- }
440
+ if (typeof onManualLayoutChange === "function")
441
+ onManualLayoutChange(manualLayout);
358
442
  }, [manualLayout, onManualLayoutChange]);
359
- useEffect(() => {
360
- if (!enableZoom || !svgRef.current || !gRef.current) return;
361
- const svg = d3.select(svgRef.current);
362
- const g = d3.select(gRef.current);
363
- const zoom2 = d3.zoom().scaleExtent([0.1, 10]).on("zoom", (event) => {
364
- g.attr("transform", event.transform);
365
- transformRef.current = event.transform;
366
- setTransform(event.transform);
367
- });
368
- svg.call(zoom2);
369
- return () => {
370
- svg.on(".zoom", null);
371
- };
372
- }, [enableZoom]);
443
+ useGraphZoom(svgRef, gRef, enableZoom, setTransform, transformRef);
444
+ useWindowDrag(
445
+ enableDrag,
446
+ svgRef,
447
+ transformRef,
448
+ dragActiveRef,
449
+ dragNodeRef,
450
+ () => {
451
+ setForcesEnabled(true);
452
+ restart();
453
+ }
454
+ );
373
455
  useEffect(() => {
374
456
  if (!gRef.current) return;
375
- try {
376
- const g = d3.select(gRef.current);
377
- g.selectAll("g.node").each(function() {
378
- const datum = d3.select(this).datum();
379
- if (!datum) return;
380
- d3.select(this).attr(
381
- "transform",
382
- `translate(${datum.x || 0},${datum.y || 0})`
383
- );
384
- });
385
- g.selectAll("line").each(function() {
386
- const l = d3.select(this).datum();
387
- if (!l) return;
388
- const s = typeof l.source === "object" ? l.source : nodes.find((n) => n.id === l.source) || l.source;
389
- const t = typeof l.target === "object" ? l.target : nodes.find((n) => n.id === l.target) || l.target;
390
- if (!s || !t) return;
391
- d3.select(this).attr("x1", s.x).attr("y1", s.y).attr("x2", t.x).attr("y2", t.y);
392
- });
393
- } catch (e) {
394
- }
395
- }, [nodes, links]);
457
+ const g = d32.select(gRef.current);
458
+ g.selectAll("g.node").each(function() {
459
+ const datum = d32.select(this).datum();
460
+ if (!datum) return;
461
+ d32.select(this).attr(
462
+ "transform",
463
+ `translate(${datum.x || 0},${datum.y || 0})`
464
+ );
465
+ });
466
+ g.selectAll("line").each(function() {
467
+ const l = d32.select(this).datum();
468
+ if (!l) return;
469
+ const s = typeof l.source === "object" ? l.source : nodes.find((n) => n.id === l.source) || l.source;
470
+ const t = typeof l.target === "object" ? l.target : nodes.find((n) => n.id === l.target) || l.target;
471
+ if (!s || !t) return;
472
+ d32.select(this).attr("x1", s.x).attr("y1", s.y).attr("x2", t.x).attr("y2", t.y);
473
+ });
474
+ }, [nodes, initialLinks]);
396
475
  const handleDragStart = useCallback(
397
476
  (event, node) => {
398
477
  if (!enableDrag) return;
@@ -403,103 +482,50 @@ var ForceDirectedGraph = forwardRef(
403
482
  node.fx = node.x;
404
483
  node.fy = node.y;
405
484
  setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
406
- try {
407
- stop();
408
- } catch (e) {
409
- }
485
+ stop();
410
486
  },
411
- [enableDrag, restart]
487
+ [enableDrag, stop]
412
488
  );
413
- useEffect(() => {
414
- if (!enableDrag) return;
415
- const handleWindowMove = (event) => {
416
- if (!dragActiveRef.current || !dragNodeRef.current) return;
417
- const svg = svgRef.current;
418
- if (!svg) return;
419
- const rect = svg.getBoundingClientRect();
420
- const t = transformRef.current;
421
- const x = (event.clientX - rect.left - t.x) / t.k;
422
- const y = (event.clientY - rect.top - t.y) / t.k;
423
- dragNodeRef.current.fx = x;
424
- dragNodeRef.current.fy = y;
425
- };
426
- const handleWindowUp = () => {
427
- if (!dragActiveRef.current) return;
428
- try {
429
- setForcesEnabled(true);
430
- restart();
431
- } catch (e) {
432
- }
433
- dragNodeRef.current = null;
434
- dragActiveRef.current = false;
435
- };
436
- const handleWindowLeave = (event) => {
437
- if (event.relatedTarget === null) handleWindowUp();
438
- };
439
- window.addEventListener("mousemove", handleWindowMove);
440
- window.addEventListener("mouseup", handleWindowUp);
441
- window.addEventListener("mouseout", handleWindowLeave);
442
- window.addEventListener("blur", handleWindowUp);
443
- return () => {
444
- window.removeEventListener("mousemove", handleWindowMove);
445
- window.removeEventListener("mouseup", handleWindowUp);
446
- window.removeEventListener("mouseout", handleWindowLeave);
447
- window.removeEventListener("blur", handleWindowUp);
448
- };
449
- }, [enableDrag]);
450
489
  useEffect(() => {
451
490
  if (!gRef.current || !enableDrag) return;
452
- const g = d3.select(gRef.current);
453
- const dragBehavior = d3.drag().on("start", function(event) {
454
- try {
455
- const target = event.sourceEvent && event.sourceEvent.target || event.target;
456
- const grp = target.closest?.("g.node");
457
- const id = grp?.getAttribute("data-id");
458
- if (!id) return;
459
- const node = nodes.find((n) => n.id === id);
460
- if (!node) return;
461
- if (!internalDragEnabledRef.current) return;
462
- if (!event.active) restart();
463
- dragActiveRef.current = true;
464
- dragNodeRef.current = node;
465
- node.fx = node.x;
466
- node.fy = node.y;
467
- setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
468
- } catch (e) {
469
- }
470
- }).on("drag", function(event) {
491
+ const g = d32.select(gRef.current);
492
+ const dragBehavior = d32.drag().on("start", (event) => {
493
+ const target = event.sourceEvent && event.sourceEvent.target || event.target;
494
+ const grp = target.closest?.("g.node");
495
+ const id = grp?.getAttribute("data-id");
496
+ if (!id || !internalDragEnabledRef.current) return;
497
+ const node = nodes.find((n) => n.id === id);
498
+ if (!node) return;
499
+ if (!event.active) restart();
500
+ dragActiveRef.current = true;
501
+ dragNodeRef.current = node;
502
+ node.fx = node.x;
503
+ node.fy = node.y;
504
+ setPinnedNodes((prev) => /* @__PURE__ */ new Set([...prev, node.id]));
505
+ }).on("drag", (event) => {
471
506
  if (!dragActiveRef.current || !dragNodeRef.current) return;
472
507
  const svg = svgRef.current;
473
508
  if (!svg) return;
474
509
  const rect = svg.getBoundingClientRect();
475
- const x = (event.sourceEvent.clientX - rect.left - transform.x) / transform.k;
476
- const y = (event.sourceEvent.clientY - rect.top - transform.y) / transform.k;
477
- dragNodeRef.current.fx = x;
478
- dragNodeRef.current.fy = y;
479
- }).on("end", function() {
480
- try {
481
- setForcesEnabled(true);
482
- restart();
483
- } catch (e) {
484
- }
510
+ dragNodeRef.current.fx = (event.sourceEvent.clientX - rect.left - transform.x) / transform.k;
511
+ dragNodeRef.current.fy = (event.sourceEvent.clientY - rect.top - transform.y) / transform.k;
512
+ }).on("end", () => {
513
+ setForcesEnabled(true);
514
+ restart();
485
515
  });
486
- try {
487
- g.selectAll("g.node").call(dragBehavior);
488
- } catch (e) {
489
- }
516
+ g.selectAll("g.node").call(dragBehavior);
490
517
  return () => {
491
- try {
492
- g.selectAll("g.node").on(".drag", null);
493
- } catch (e) {
494
- }
518
+ g.selectAll("g.node").on(".drag", null);
495
519
  };
496
- }, [gRef, enableDrag, nodes, transform, restart]);
497
- const handleNodeClick = useCallback(
498
- (node) => {
499
- onNodeClick?.(node);
500
- },
501
- [onNodeClick]
502
- );
520
+ }, [
521
+ gRef,
522
+ enableDrag,
523
+ nodes,
524
+ transform,
525
+ restart,
526
+ setForcesEnabled,
527
+ internalDragEnabledRef
528
+ ]);
503
529
  const handleNodeDoubleClick = useCallback(
504
530
  (event, node) => {
505
531
  event.stopPropagation();
@@ -521,29 +547,6 @@ var ForceDirectedGraph = forwardRef(
521
547
  },
522
548
  [enableDrag, restart]
523
549
  );
524
- const handleCanvasDoubleClick = useCallback(() => {
525
- nodes.forEach((node) => {
526
- node.fx = null;
527
- node.fy = null;
528
- });
529
- setPinnedNodes(/* @__PURE__ */ new Set());
530
- restart();
531
- }, [nodes, restart]);
532
- const handleNodeMouseEnter = useCallback(
533
- (node) => {
534
- onNodeHover?.(node);
535
- },
536
- [onNodeHover]
537
- );
538
- const handleNodeMouseLeave = useCallback(() => {
539
- onNodeHover?.(null);
540
- }, [onNodeHover]);
541
- const handleLinkClick = useCallback(
542
- (link) => {
543
- onLinkClick?.(link);
544
- },
545
- [onLinkClick]
546
- );
547
550
  return /* @__PURE__ */ jsxs(
548
551
  "svg",
549
552
  {
@@ -551,7 +554,14 @@ var ForceDirectedGraph = forwardRef(
551
554
  width,
552
555
  height,
553
556
  className: cn("bg-white dark:bg-gray-900", className),
554
- onDoubleClick: handleCanvasDoubleClick,
557
+ onDoubleClick: () => {
558
+ nodes.forEach((n) => {
559
+ n.fx = null;
560
+ n.fy = null;
561
+ });
562
+ setPinnedNodes(/* @__PURE__ */ new Set());
563
+ restart();
564
+ },
555
565
  children: [
556
566
  /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
557
567
  "marker",
@@ -567,11 +577,11 @@ var ForceDirectedGraph = forwardRef(
567
577
  }
568
578
  ) }),
569
579
  /* @__PURE__ */ jsxs("g", { ref: gRef, children: [
570
- links.map((link, i) => /* @__PURE__ */ jsx(
580
+ initialLinks.map((link, i) => /* @__PURE__ */ jsx(
571
581
  LinkItem_default,
572
582
  {
573
583
  link,
574
- onClick: handleLinkClick,
584
+ onClick: onLinkClick,
575
585
  defaultWidth: defaultLinkWidth,
576
586
  showLabel: showLinkLabels,
577
587
  nodes
@@ -588,41 +598,15 @@ var ForceDirectedGraph = forwardRef(
588
598
  defaultNodeSize,
589
599
  defaultNodeColor,
590
600
  showLabel: showNodeLabels,
591
- onClick: handleNodeClick,
601
+ onClick: onNodeClick,
592
602
  onDoubleClick: handleNodeDoubleClick,
593
- onMouseEnter: handleNodeMouseEnter,
594
- onMouseLeave: handleNodeMouseLeave,
603
+ onMouseEnter: (n) => onNodeHover?.(n),
604
+ onMouseLeave: () => onNodeHover?.(null),
595
605
  onMouseDown: handleDragStart
596
606
  },
597
607
  node.id
598
608
  )),
599
- packageBounds && Object.keys(packageBounds).length > 0 && /* @__PURE__ */ jsx("g", { className: "package-boundaries", pointerEvents: "none", children: Object.entries(packageBounds).map(([pid, b]) => /* @__PURE__ */ jsxs("g", { children: [
600
- /* @__PURE__ */ jsx(
601
- "circle",
602
- {
603
- cx: b.x,
604
- cy: b.y,
605
- r: b.r,
606
- fill: "rgba(148,163,184,0.06)",
607
- stroke: "#475569",
608
- strokeWidth: 2,
609
- strokeDasharray: "6 6",
610
- opacity: 0.9
611
- }
612
- ),
613
- /* @__PURE__ */ jsx(
614
- "text",
615
- {
616
- x: b.x,
617
- y: Math.max(12, b.y - b.r + 14),
618
- fill: "#475569",
619
- fontSize: 11,
620
- textAnchor: "middle",
621
- pointerEvents: "none",
622
- children: pid.replace(/^pkg:/, "")
623
- }
624
- )
625
- ] }, pid)) })
609
+ /* @__PURE__ */ jsx(PackageBoundaries, { packageBounds: packageBounds || {} })
626
610
  ] })
627
611
  ]
628
612
  }