@almadar/ui 5.58.0 → 5.60.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.
@@ -37970,6 +37970,12 @@ function getGroupColor(group, groups) {
37970
37970
  const idx = groups.indexOf(group);
37971
37971
  return GROUP_COLORS2[idx % GROUP_COLORS2.length];
37972
37972
  }
37973
+ function resolveColor2(color, el) {
37974
+ const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
37975
+ if (!m) return color;
37976
+ const resolved = getComputedStyle(el).getPropertyValue(m[1]).trim();
37977
+ return resolved || (m[2]?.trim() ?? "#888888");
37978
+ }
37973
37979
  var GROUP_COLORS2, GraphCanvas;
37974
37980
  var init_GraphCanvas = __esm({
37975
37981
  "components/core/molecules/GraphCanvas.tsx"() {
@@ -38000,6 +38006,9 @@ var init_GraphCanvas = __esm({
38000
38006
  actions,
38001
38007
  onNodeClick,
38002
38008
  nodeClickEvent,
38009
+ selectedNodeId,
38010
+ repulsion = 800,
38011
+ linkDistance = 100,
38003
38012
  layout = "force",
38004
38013
  entity,
38005
38014
  isLoading = false,
@@ -38015,6 +38024,37 @@ var init_GraphCanvas = __esm({
38015
38024
  const [hoveredNode, setHoveredNode] = React82.useState(null);
38016
38025
  const nodesRef = React82.useRef([]);
38017
38026
  const [, forceUpdate] = React82.useState(0);
38027
+ const interactionRef = React82.useRef({
38028
+ mode: "none",
38029
+ dragNodeId: null,
38030
+ startMouse: { x: 0, y: 0 },
38031
+ startOffset: { x: 0, y: 0 },
38032
+ downPos: { x: 0, y: 0 }
38033
+ });
38034
+ const toCoords = React82.useCallback(
38035
+ (e) => {
38036
+ const canvas = canvasRef.current;
38037
+ if (!canvas) return null;
38038
+ const rect = canvas.getBoundingClientRect();
38039
+ const scaleX = rect.width > 0 ? canvas.width / rect.width : 1;
38040
+ const scaleY = rect.height > 0 ? canvas.height / rect.height : 1;
38041
+ const screenX = (e.clientX - rect.left) * scaleX;
38042
+ const screenY = (e.clientY - rect.top) * scaleY;
38043
+ return {
38044
+ screenX,
38045
+ screenY,
38046
+ graphX: (screenX - offset.x) / zoom,
38047
+ graphY: (screenY - offset.y) / zoom
38048
+ };
38049
+ },
38050
+ [offset, zoom]
38051
+ );
38052
+ const nodeAt = React82.useCallback((graphX, graphY) => {
38053
+ return nodesRef.current.find((n) => {
38054
+ const dist = Math.sqrt((n.x - graphX) ** 2 + (n.y - graphY) ** 2);
38055
+ return dist < (n.size || 8) + 4;
38056
+ });
38057
+ }, []);
38018
38058
  const handleAction = React82.useCallback(
38019
38059
  (action) => {
38020
38060
  if (action.event) {
@@ -38080,7 +38120,7 @@ var init_GraphCanvas = __esm({
38080
38120
  const dx = nodes[j].x - nodes[i].x;
38081
38121
  const dy = nodes[j].y - nodes[i].y;
38082
38122
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
38083
- const force = 800 / (dist * dist);
38123
+ const force = repulsion / (dist * dist);
38084
38124
  const fx = dx / dist * force;
38085
38125
  const fy = dy / dist * force;
38086
38126
  nodes[i].fx -= fx;
@@ -38096,7 +38136,7 @@ var init_GraphCanvas = __esm({
38096
38136
  const dx = target.x - source.x;
38097
38137
  const dy = target.y - source.y;
38098
38138
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
38099
- const force = (dist - 100) * 0.05;
38139
+ const force = (dist - linkDistance) * 0.05;
38100
38140
  const fx = dx / dist * force;
38101
38141
  const fy = dy / dist * force;
38102
38142
  source.fx += fx;
@@ -38130,7 +38170,7 @@ var init_GraphCanvas = __esm({
38130
38170
  return () => {
38131
38171
  cancelAnimationFrame(animRef.current);
38132
38172
  };
38133
- }, [propNodes, propEdges, layout]);
38173
+ }, [propNodes, propEdges, layout, repulsion, linkDistance]);
38134
38174
  React82.useEffect(() => {
38135
38175
  const canvas = canvasRef.current;
38136
38176
  if (!canvas) return;
@@ -38139,6 +38179,7 @@ var init_GraphCanvas = __esm({
38139
38179
  const w = canvas.width;
38140
38180
  const h = canvas.height;
38141
38181
  const nodes = nodesRef.current;
38182
+ const accentColor = resolveColor2("var(--color-accent)", canvas);
38142
38183
  ctx.clearRect(0, 0, w, h);
38143
38184
  ctx.save();
38144
38185
  ctx.translate(offset.x, offset.y);
@@ -38164,20 +38205,27 @@ var init_GraphCanvas = __esm({
38164
38205
  }
38165
38206
  for (const node of nodes) {
38166
38207
  const size = node.size || 8;
38167
- const color = node.color || getGroupColor(node.group, groups);
38208
+ const color = resolveColor2(node.color || getGroupColor(node.group, groups), canvas);
38168
38209
  const isHovered = hoveredNode === node.id;
38210
+ const isSelected = selectedNodeId !== void 0 && node.id === selectedNodeId;
38211
+ const radius = isSelected ? size + 4 : isHovered ? size + 2 : size;
38169
38212
  ctx.beginPath();
38170
- ctx.arc(node.x, node.y, isHovered ? size + 2 : size, 0, Math.PI * 2);
38213
+ ctx.arc(node.x, node.y, radius, 0, Math.PI * 2);
38171
38214
  ctx.fillStyle = color;
38172
38215
  ctx.fill();
38173
- ctx.strokeStyle = isHovered ? "#ffffff" : "#00000020";
38174
- ctx.lineWidth = isHovered ? 2 : 1;
38216
+ if (isSelected) {
38217
+ ctx.strokeStyle = accentColor;
38218
+ ctx.lineWidth = 3;
38219
+ } else {
38220
+ ctx.strokeStyle = isHovered ? "#ffffff" : "#00000020";
38221
+ ctx.lineWidth = isHovered ? 2 : 1;
38222
+ }
38175
38223
  ctx.stroke();
38176
38224
  if (showLabels && node.label) {
38177
38225
  ctx.fillStyle = "#666666";
38178
- ctx.font = `${isHovered ? "bold " : ""}10px system-ui`;
38226
+ ctx.font = `${isSelected || isHovered ? "bold " : ""}10px system-ui`;
38179
38227
  ctx.textAlign = "center";
38180
- ctx.fillText(node.label, node.x, node.y + size + 12);
38228
+ ctx.fillText(node.label, node.x, node.y + radius + 12);
38181
38229
  }
38182
38230
  }
38183
38231
  ctx.restore();
@@ -38188,6 +38236,97 @@ var init_GraphCanvas = __esm({
38188
38236
  setZoom(1);
38189
38237
  setOffset({ x: 0, y: 0 });
38190
38238
  }, []);
38239
+ const handleWheel = React82.useCallback(
38240
+ (e) => {
38241
+ if (!interactive) return;
38242
+ e.preventDefault();
38243
+ const coords = toCoords(e);
38244
+ if (!coords) return;
38245
+ const oldZoom = zoom;
38246
+ const factor = e.deltaY < 0 ? 1.1 : 1 / 1.1;
38247
+ const newZoom = Math.max(0.3, Math.min(3, oldZoom * factor));
38248
+ if (newZoom === oldZoom) return;
38249
+ setOffset((o) => ({
38250
+ x: coords.screenX - (coords.screenX - o.x) * (newZoom / oldZoom),
38251
+ y: coords.screenY - (coords.screenY - o.y) * (newZoom / oldZoom)
38252
+ }));
38253
+ setZoom(newZoom);
38254
+ },
38255
+ [interactive, toCoords, zoom]
38256
+ );
38257
+ const handleMouseDown = React82.useCallback(
38258
+ (e) => {
38259
+ const coords = toCoords(e);
38260
+ if (!coords) return;
38261
+ const node = nodeAt(coords.graphX, coords.graphY);
38262
+ const state = interactionRef.current;
38263
+ state.downPos = { x: e.clientX, y: e.clientY };
38264
+ state.startMouse = { x: e.clientX, y: e.clientY };
38265
+ state.startOffset = { ...offset };
38266
+ if (draggable && node) {
38267
+ state.mode = "dragging";
38268
+ state.dragNodeId = node.id;
38269
+ } else if (interactive) {
38270
+ state.mode = "panning";
38271
+ state.dragNodeId = null;
38272
+ } else {
38273
+ state.mode = "none";
38274
+ state.dragNodeId = null;
38275
+ }
38276
+ },
38277
+ [toCoords, nodeAt, draggable, interactive, offset]
38278
+ );
38279
+ const handleMouseMove = React82.useCallback(
38280
+ (e) => {
38281
+ const state = interactionRef.current;
38282
+ if (state.mode === "panning") {
38283
+ const dx = e.clientX - state.startMouse.x;
38284
+ const dy = e.clientY - state.startMouse.y;
38285
+ setOffset({ x: state.startOffset.x + dx, y: state.startOffset.y + dy });
38286
+ return;
38287
+ }
38288
+ if (state.mode === "dragging" && state.dragNodeId) {
38289
+ const coords2 = toCoords(e);
38290
+ if (!coords2) return;
38291
+ const node2 = nodesRef.current.find((n) => n.id === state.dragNodeId);
38292
+ if (node2) {
38293
+ node2.x = coords2.graphX;
38294
+ node2.y = coords2.graphY;
38295
+ node2.vx = 0;
38296
+ node2.vy = 0;
38297
+ forceUpdate((n) => n + 1);
38298
+ }
38299
+ return;
38300
+ }
38301
+ const coords = toCoords(e);
38302
+ if (!coords) return;
38303
+ const node = nodeAt(coords.graphX, coords.graphY);
38304
+ setHoveredNode(node?.id ?? null);
38305
+ },
38306
+ [toCoords, nodeAt]
38307
+ );
38308
+ const handleMouseUp = React82.useCallback(
38309
+ (e) => {
38310
+ const state = interactionRef.current;
38311
+ const moved = Math.abs(e.clientX - state.downPos.x) + Math.abs(e.clientY - state.downPos.y);
38312
+ state.mode = "none";
38313
+ state.dragNodeId = null;
38314
+ if (moved < 4) {
38315
+ const coords = toCoords(e);
38316
+ if (!coords) return;
38317
+ const node = nodeAt(coords.graphX, coords.graphY);
38318
+ if (node) {
38319
+ handleNodeClick(node);
38320
+ }
38321
+ }
38322
+ },
38323
+ [toCoords, nodeAt, handleNodeClick]
38324
+ );
38325
+ const handleMouseLeave = React82.useCallback(() => {
38326
+ interactionRef.current.mode = "none";
38327
+ interactionRef.current.dragNodeId = null;
38328
+ setHoveredNode(null);
38329
+ }, []);
38191
38330
  if (isLoading) {
38192
38331
  return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: t("common.loading"), className });
38193
38332
  }
@@ -38249,20 +38388,11 @@ var init_GraphCanvas = __esm({
38249
38388
  height,
38250
38389
  className: "w-full cursor-grab active:cursor-grabbing",
38251
38390
  style: { height },
38252
- onClick: (e) => {
38253
- const canvas = canvasRef.current;
38254
- if (!canvas) return;
38255
- const rect = canvas.getBoundingClientRect();
38256
- const x = (e.clientX - rect.left - offset.x) / zoom;
38257
- const y = (e.clientY - rect.top - offset.y) / zoom;
38258
- const clickedNode = nodesRef.current.find((n) => {
38259
- const dist = Math.sqrt((n.x - x) ** 2 + (n.y - y) ** 2);
38260
- return dist < (n.size || 8) + 4;
38261
- });
38262
- if (clickedNode) {
38263
- handleNodeClick(clickedNode);
38264
- }
38265
- }
38391
+ onWheel: handleWheel,
38392
+ onMouseDown: handleMouseDown,
38393
+ onMouseMove: handleMouseMove,
38394
+ onMouseUp: handleMouseUp,
38395
+ onMouseLeave: handleMouseLeave
38266
38396
  }
38267
38397
  ) }),
38268
38398
  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: [
@@ -37923,6 +37923,12 @@ function getGroupColor(group, groups) {
37923
37923
  const idx = groups.indexOf(group);
37924
37924
  return GROUP_COLORS2[idx % GROUP_COLORS2.length];
37925
37925
  }
37926
+ function resolveColor2(color, el) {
37927
+ const m = /^var\((--[^,)]+)(?:,\s*([^)]+))?\)$/.exec(color.trim());
37928
+ if (!m) return color;
37929
+ const resolved = getComputedStyle(el).getPropertyValue(m[1]).trim();
37930
+ return resolved || (m[2]?.trim() ?? "#888888");
37931
+ }
37926
37932
  var GROUP_COLORS2, GraphCanvas;
37927
37933
  var init_GraphCanvas = __esm({
37928
37934
  "components/core/molecules/GraphCanvas.tsx"() {
@@ -37953,6 +37959,9 @@ var init_GraphCanvas = __esm({
37953
37959
  actions,
37954
37960
  onNodeClick,
37955
37961
  nodeClickEvent,
37962
+ selectedNodeId,
37963
+ repulsion = 800,
37964
+ linkDistance = 100,
37956
37965
  layout = "force",
37957
37966
  entity,
37958
37967
  isLoading = false,
@@ -37968,6 +37977,37 @@ var init_GraphCanvas = __esm({
37968
37977
  const [hoveredNode, setHoveredNode] = useState(null);
37969
37978
  const nodesRef = useRef([]);
37970
37979
  const [, forceUpdate] = useState(0);
37980
+ const interactionRef = useRef({
37981
+ mode: "none",
37982
+ dragNodeId: null,
37983
+ startMouse: { x: 0, y: 0 },
37984
+ startOffset: { x: 0, y: 0 },
37985
+ downPos: { x: 0, y: 0 }
37986
+ });
37987
+ const toCoords = useCallback(
37988
+ (e) => {
37989
+ const canvas = canvasRef.current;
37990
+ if (!canvas) return null;
37991
+ const rect = canvas.getBoundingClientRect();
37992
+ const scaleX = rect.width > 0 ? canvas.width / rect.width : 1;
37993
+ const scaleY = rect.height > 0 ? canvas.height / rect.height : 1;
37994
+ const screenX = (e.clientX - rect.left) * scaleX;
37995
+ const screenY = (e.clientY - rect.top) * scaleY;
37996
+ return {
37997
+ screenX,
37998
+ screenY,
37999
+ graphX: (screenX - offset.x) / zoom,
38000
+ graphY: (screenY - offset.y) / zoom
38001
+ };
38002
+ },
38003
+ [offset, zoom]
38004
+ );
38005
+ const nodeAt = useCallback((graphX, graphY) => {
38006
+ return nodesRef.current.find((n) => {
38007
+ const dist = Math.sqrt((n.x - graphX) ** 2 + (n.y - graphY) ** 2);
38008
+ return dist < (n.size || 8) + 4;
38009
+ });
38010
+ }, []);
37971
38011
  const handleAction = useCallback(
37972
38012
  (action) => {
37973
38013
  if (action.event) {
@@ -38033,7 +38073,7 @@ var init_GraphCanvas = __esm({
38033
38073
  const dx = nodes[j].x - nodes[i].x;
38034
38074
  const dy = nodes[j].y - nodes[i].y;
38035
38075
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
38036
- const force = 800 / (dist * dist);
38076
+ const force = repulsion / (dist * dist);
38037
38077
  const fx = dx / dist * force;
38038
38078
  const fy = dy / dist * force;
38039
38079
  nodes[i].fx -= fx;
@@ -38049,7 +38089,7 @@ var init_GraphCanvas = __esm({
38049
38089
  const dx = target.x - source.x;
38050
38090
  const dy = target.y - source.y;
38051
38091
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
38052
- const force = (dist - 100) * 0.05;
38092
+ const force = (dist - linkDistance) * 0.05;
38053
38093
  const fx = dx / dist * force;
38054
38094
  const fy = dy / dist * force;
38055
38095
  source.fx += fx;
@@ -38083,7 +38123,7 @@ var init_GraphCanvas = __esm({
38083
38123
  return () => {
38084
38124
  cancelAnimationFrame(animRef.current);
38085
38125
  };
38086
- }, [propNodes, propEdges, layout]);
38126
+ }, [propNodes, propEdges, layout, repulsion, linkDistance]);
38087
38127
  useEffect(() => {
38088
38128
  const canvas = canvasRef.current;
38089
38129
  if (!canvas) return;
@@ -38092,6 +38132,7 @@ var init_GraphCanvas = __esm({
38092
38132
  const w = canvas.width;
38093
38133
  const h = canvas.height;
38094
38134
  const nodes = nodesRef.current;
38135
+ const accentColor = resolveColor2("var(--color-accent)", canvas);
38095
38136
  ctx.clearRect(0, 0, w, h);
38096
38137
  ctx.save();
38097
38138
  ctx.translate(offset.x, offset.y);
@@ -38117,20 +38158,27 @@ var init_GraphCanvas = __esm({
38117
38158
  }
38118
38159
  for (const node of nodes) {
38119
38160
  const size = node.size || 8;
38120
- const color = node.color || getGroupColor(node.group, groups);
38161
+ const color = resolveColor2(node.color || getGroupColor(node.group, groups), canvas);
38121
38162
  const isHovered = hoveredNode === node.id;
38163
+ const isSelected = selectedNodeId !== void 0 && node.id === selectedNodeId;
38164
+ const radius = isSelected ? size + 4 : isHovered ? size + 2 : size;
38122
38165
  ctx.beginPath();
38123
- ctx.arc(node.x, node.y, isHovered ? size + 2 : size, 0, Math.PI * 2);
38166
+ ctx.arc(node.x, node.y, radius, 0, Math.PI * 2);
38124
38167
  ctx.fillStyle = color;
38125
38168
  ctx.fill();
38126
- ctx.strokeStyle = isHovered ? "#ffffff" : "#00000020";
38127
- ctx.lineWidth = isHovered ? 2 : 1;
38169
+ if (isSelected) {
38170
+ ctx.strokeStyle = accentColor;
38171
+ ctx.lineWidth = 3;
38172
+ } else {
38173
+ ctx.strokeStyle = isHovered ? "#ffffff" : "#00000020";
38174
+ ctx.lineWidth = isHovered ? 2 : 1;
38175
+ }
38128
38176
  ctx.stroke();
38129
38177
  if (showLabels && node.label) {
38130
38178
  ctx.fillStyle = "#666666";
38131
- ctx.font = `${isHovered ? "bold " : ""}10px system-ui`;
38179
+ ctx.font = `${isSelected || isHovered ? "bold " : ""}10px system-ui`;
38132
38180
  ctx.textAlign = "center";
38133
- ctx.fillText(node.label, node.x, node.y + size + 12);
38181
+ ctx.fillText(node.label, node.x, node.y + radius + 12);
38134
38182
  }
38135
38183
  }
38136
38184
  ctx.restore();
@@ -38141,6 +38189,97 @@ var init_GraphCanvas = __esm({
38141
38189
  setZoom(1);
38142
38190
  setOffset({ x: 0, y: 0 });
38143
38191
  }, []);
38192
+ const handleWheel = useCallback(
38193
+ (e) => {
38194
+ if (!interactive) return;
38195
+ e.preventDefault();
38196
+ const coords = toCoords(e);
38197
+ if (!coords) return;
38198
+ const oldZoom = zoom;
38199
+ const factor = e.deltaY < 0 ? 1.1 : 1 / 1.1;
38200
+ const newZoom = Math.max(0.3, Math.min(3, oldZoom * factor));
38201
+ if (newZoom === oldZoom) return;
38202
+ setOffset((o) => ({
38203
+ x: coords.screenX - (coords.screenX - o.x) * (newZoom / oldZoom),
38204
+ y: coords.screenY - (coords.screenY - o.y) * (newZoom / oldZoom)
38205
+ }));
38206
+ setZoom(newZoom);
38207
+ },
38208
+ [interactive, toCoords, zoom]
38209
+ );
38210
+ const handleMouseDown = useCallback(
38211
+ (e) => {
38212
+ const coords = toCoords(e);
38213
+ if (!coords) return;
38214
+ const node = nodeAt(coords.graphX, coords.graphY);
38215
+ const state = interactionRef.current;
38216
+ state.downPos = { x: e.clientX, y: e.clientY };
38217
+ state.startMouse = { x: e.clientX, y: e.clientY };
38218
+ state.startOffset = { ...offset };
38219
+ if (draggable && node) {
38220
+ state.mode = "dragging";
38221
+ state.dragNodeId = node.id;
38222
+ } else if (interactive) {
38223
+ state.mode = "panning";
38224
+ state.dragNodeId = null;
38225
+ } else {
38226
+ state.mode = "none";
38227
+ state.dragNodeId = null;
38228
+ }
38229
+ },
38230
+ [toCoords, nodeAt, draggable, interactive, offset]
38231
+ );
38232
+ const handleMouseMove = useCallback(
38233
+ (e) => {
38234
+ const state = interactionRef.current;
38235
+ if (state.mode === "panning") {
38236
+ const dx = e.clientX - state.startMouse.x;
38237
+ const dy = e.clientY - state.startMouse.y;
38238
+ setOffset({ x: state.startOffset.x + dx, y: state.startOffset.y + dy });
38239
+ return;
38240
+ }
38241
+ if (state.mode === "dragging" && state.dragNodeId) {
38242
+ const coords2 = toCoords(e);
38243
+ if (!coords2) return;
38244
+ const node2 = nodesRef.current.find((n) => n.id === state.dragNodeId);
38245
+ if (node2) {
38246
+ node2.x = coords2.graphX;
38247
+ node2.y = coords2.graphY;
38248
+ node2.vx = 0;
38249
+ node2.vy = 0;
38250
+ forceUpdate((n) => n + 1);
38251
+ }
38252
+ return;
38253
+ }
38254
+ const coords = toCoords(e);
38255
+ if (!coords) return;
38256
+ const node = nodeAt(coords.graphX, coords.graphY);
38257
+ setHoveredNode(node?.id ?? null);
38258
+ },
38259
+ [toCoords, nodeAt]
38260
+ );
38261
+ const handleMouseUp = useCallback(
38262
+ (e) => {
38263
+ const state = interactionRef.current;
38264
+ const moved = Math.abs(e.clientX - state.downPos.x) + Math.abs(e.clientY - state.downPos.y);
38265
+ state.mode = "none";
38266
+ state.dragNodeId = null;
38267
+ if (moved < 4) {
38268
+ const coords = toCoords(e);
38269
+ if (!coords) return;
38270
+ const node = nodeAt(coords.graphX, coords.graphY);
38271
+ if (node) {
38272
+ handleNodeClick(node);
38273
+ }
38274
+ }
38275
+ },
38276
+ [toCoords, nodeAt, handleNodeClick]
38277
+ );
38278
+ const handleMouseLeave = useCallback(() => {
38279
+ interactionRef.current.mode = "none";
38280
+ interactionRef.current.dragNodeId = null;
38281
+ setHoveredNode(null);
38282
+ }, []);
38144
38283
  if (isLoading) {
38145
38284
  return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
38146
38285
  }
@@ -38202,20 +38341,11 @@ var init_GraphCanvas = __esm({
38202
38341
  height,
38203
38342
  className: "w-full cursor-grab active:cursor-grabbing",
38204
38343
  style: { height },
38205
- onClick: (e) => {
38206
- const canvas = canvasRef.current;
38207
- if (!canvas) return;
38208
- const rect = canvas.getBoundingClientRect();
38209
- const x = (e.clientX - rect.left - offset.x) / zoom;
38210
- const y = (e.clientY - rect.top - offset.y) / zoom;
38211
- const clickedNode = nodesRef.current.find((n) => {
38212
- const dist = Math.sqrt((n.x - x) ** 2 + (n.y - y) ** 2);
38213
- return dist < (n.size || 8) + 4;
38214
- });
38215
- if (clickedNode) {
38216
- handleNodeClick(clickedNode);
38217
- }
38218
- }
38344
+ onWheel: handleWheel,
38345
+ onMouseDown: handleMouseDown,
38346
+ onMouseMove: handleMouseMove,
38347
+ onMouseUp: handleMouseUp,
38348
+ onMouseLeave: handleMouseLeave
38219
38349
  }
38220
38350
  ) }),
38221
38351
  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: [