@almadar/ui 5.146.3 → 5.148.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.
@@ -11940,7 +11940,10 @@ var init_LearningCanvas = __esm({
11940
11940
  ctx.fillRect(0, 0, width, height);
11941
11941
  }
11942
11942
  for (const shape of shapes) {
11943
- drawShape(ctx, shape, width, height);
11943
+ if (shape.type !== "text") drawShape(ctx, shape, width, height);
11944
+ }
11945
+ for (const shape of shapes) {
11946
+ if (shape.type === "text") drawShape(ctx, shape, width, height);
11944
11947
  }
11945
11948
  }, [width, height, backgroundColor, shapes]);
11946
11949
  React85.useEffect(() => {
@@ -13503,7 +13506,7 @@ var init_AlgorithmCanvas = __esm({
13503
13506
  DEFAULT_CELL_COLOR = "#e5e7eb";
13504
13507
  DEFAULT_POINTER_COLOR = "#dc2626";
13505
13508
  POINTER_BAND = 34;
13506
- TOP_PAD = 12;
13509
+ TOP_PAD = 26;
13507
13510
  AlgorithmCanvas = ({
13508
13511
  className,
13509
13512
  width = 600,
@@ -24914,6 +24917,7 @@ var init_FilterGroup = __esm({
24914
24917
  init_Badge();
24915
24918
  init_Stack();
24916
24919
  init_Icon();
24920
+ init_RangeSlider();
24917
24921
  init_useEventBus();
24918
24922
  init_useQuerySingleton();
24919
24923
  resolveFilterType = (filter) => filter.filterType ?? filter.type;
@@ -25108,6 +25112,35 @@ var init_FilterGroup = __esm({
25108
25112
  onClear: () => handleFilterSelect(`${filter.field}_to`, null)
25109
25113
  }
25110
25114
  )
25115
+ ] }) : resolveFilterType(filter) === "numberrange" || resolveFilterType(filter) === "number-range" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
25116
+ /* @__PURE__ */ jsxRuntime.jsx(
25117
+ RangeSlider,
25118
+ {
25119
+ min: filter.min ?? 0,
25120
+ max: filter.max ?? 100,
25121
+ step: filter.step ?? 1,
25122
+ value: Number(
25123
+ selectedValues[`${filter.field}_min`] ?? filter.min ?? 0
25124
+ ),
25125
+ onChange: (v) => handleFilterSelect(`${filter.field}_min`, String(v)),
25126
+ showTooltip: true,
25127
+ "aria-label": t("filterGroup.from")
25128
+ }
25129
+ ),
25130
+ /* @__PURE__ */ jsxRuntime.jsx(
25131
+ RangeSlider,
25132
+ {
25133
+ min: filter.min ?? 0,
25134
+ max: filter.max ?? 100,
25135
+ step: filter.step ?? 1,
25136
+ value: Number(
25137
+ selectedValues[`${filter.field}_max`] ?? filter.max ?? 100
25138
+ ),
25139
+ onChange: (v) => handleFilterSelect(`${filter.field}_max`, String(v)),
25140
+ showTooltip: true,
25141
+ "aria-label": t("filterGroup.to")
25142
+ }
25143
+ )
25111
25144
  ] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
25112
25145
  Input,
25113
25146
  {
@@ -25190,6 +25223,36 @@ var init_FilterGroup = __esm({
25190
25223
  className: "text-sm min-w-[100px]"
25191
25224
  }
25192
25225
  )
25226
+ ] }) : resolveFilterType(filter) === "numberrange" || resolveFilterType(filter) === "number-range" ? /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
25227
+ /* @__PURE__ */ jsxRuntime.jsx(
25228
+ RangeSlider,
25229
+ {
25230
+ min: filter.min ?? 0,
25231
+ max: filter.max ?? 100,
25232
+ step: filter.step ?? 1,
25233
+ value: Number(
25234
+ selectedValues[`${filter.field}_min`] ?? filter.min ?? 0
25235
+ ),
25236
+ onChange: (v) => handleFilterSelect(`${filter.field}_min`, String(v)),
25237
+ className: "min-w-[100px]",
25238
+ "aria-label": t("filterGroup.from")
25239
+ }
25240
+ ),
25241
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "-" }),
25242
+ /* @__PURE__ */ jsxRuntime.jsx(
25243
+ RangeSlider,
25244
+ {
25245
+ min: filter.min ?? 0,
25246
+ max: filter.max ?? 100,
25247
+ step: filter.step ?? 1,
25248
+ value: Number(
25249
+ selectedValues[`${filter.field}_max`] ?? filter.max ?? 100
25250
+ ),
25251
+ onChange: (v) => handleFilterSelect(`${filter.field}_max`, String(v)),
25252
+ className: "min-w-[100px]",
25253
+ "aria-label": t("filterGroup.to")
25254
+ }
25255
+ )
25193
25256
  ] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
25194
25257
  Input,
25195
25258
  {
@@ -25308,6 +25371,38 @@ var init_FilterGroup = __esm({
25308
25371
  className: "min-w-[130px]"
25309
25372
  }
25310
25373
  )
25374
+ ] }) : resolveFilterType(filter) === "numberrange" || resolveFilterType(filter) === "number-range" ? /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
25375
+ /* @__PURE__ */ jsxRuntime.jsx(
25376
+ RangeSlider,
25377
+ {
25378
+ min: filter.min ?? 0,
25379
+ max: filter.max ?? 100,
25380
+ step: filter.step ?? 1,
25381
+ value: Number(
25382
+ selectedValues[`${filter.field}_min`] ?? filter.min ?? 0
25383
+ ),
25384
+ onChange: (v) => handleFilterSelect(`${filter.field}_min`, String(v)),
25385
+ showTooltip: true,
25386
+ className: "min-w-[130px]",
25387
+ "aria-label": t("filterGroup.from")
25388
+ }
25389
+ ),
25390
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "-" }),
25391
+ /* @__PURE__ */ jsxRuntime.jsx(
25392
+ RangeSlider,
25393
+ {
25394
+ min: filter.min ?? 0,
25395
+ max: filter.max ?? 100,
25396
+ step: filter.step ?? 1,
25397
+ value: Number(
25398
+ selectedValues[`${filter.field}_max`] ?? filter.max ?? 100
25399
+ ),
25400
+ onChange: (v) => handleFilterSelect(`${filter.field}_max`, String(v)),
25401
+ showTooltip: true,
25402
+ className: "min-w-[130px]",
25403
+ "aria-label": t("filterGroup.to")
25404
+ }
25405
+ )
25311
25406
  ] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
25312
25407
  Input,
25313
25408
  {
@@ -27207,7 +27302,12 @@ function daysAgo(n) {
27207
27302
  d.setDate(d.getDate() - n);
27208
27303
  return d;
27209
27304
  }
27210
- var DEFAULT_PRESETS, DateRangePicker;
27305
+ function resolvePresetRange(preset) {
27306
+ if (typeof preset.range === "function") return preset.range();
27307
+ if (preset.range) return preset.range;
27308
+ return TOKEN_RANGES[preset.value]?.() ?? null;
27309
+ }
27310
+ var TOKEN_RANGES, DEFAULT_PRESETS, DateRangePicker;
27211
27311
  var init_DateRangePicker = __esm({
27212
27312
  "components/core/molecules/DateRangePicker.tsx"() {
27213
27313
  "use client";
@@ -27217,32 +27317,19 @@ var init_DateRangePicker = __esm({
27217
27317
  init_Stack();
27218
27318
  init_Typography();
27219
27319
  init_useEventBus();
27320
+ TOKEN_RANGES = {
27321
+ "7d": () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) }),
27322
+ "30d": () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) }),
27323
+ month: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) }),
27324
+ quarter: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) }),
27325
+ ytd: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27326
+ };
27220
27327
  DEFAULT_PRESETS = [
27221
- {
27222
- label: "Last 7 days",
27223
- value: "7d",
27224
- range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
27225
- },
27226
- {
27227
- label: "Last 30 days",
27228
- value: "30d",
27229
- range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
27230
- },
27231
- {
27232
- label: "This Month",
27233
- value: "month",
27234
- range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27235
- },
27236
- {
27237
- label: "This Quarter",
27238
- value: "quarter",
27239
- range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27240
- },
27241
- {
27242
- label: "YTD",
27243
- value: "ytd",
27244
- range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27245
- }
27328
+ { label: "Last 7 days", value: "7d" },
27329
+ { label: "Last 30 days", value: "30d" },
27330
+ { label: "This Month", value: "month" },
27331
+ { label: "This Quarter", value: "quarter" },
27332
+ { label: "YTD", value: "ytd" }
27246
27333
  ];
27247
27334
  DateRangePicker = ({
27248
27335
  from: fromProp,
@@ -27283,7 +27370,8 @@ var init_DateRangePicker = __esm({
27283
27370
  );
27284
27371
  const handlePreset = React85.useCallback(
27285
27372
  (preset) => {
27286
- const range = preset.range();
27373
+ const range = resolvePresetRange(preset);
27374
+ if (range === null) return;
27287
27375
  setFrom(range.from);
27288
27376
  setTo(range.to);
27289
27377
  setActivePreset(preset.value);
@@ -27291,8 +27379,12 @@ var init_DateRangePicker = __esm({
27291
27379
  },
27292
27380
  [emit]
27293
27381
  );
27382
+ const renderablePresets = React85.useMemo(
27383
+ () => presets.filter((p) => p.range !== void 0 || TOKEN_RANGES[p.value] !== void 0),
27384
+ [presets]
27385
+ );
27294
27386
  const presetButtons = React85.useMemo(
27295
- () => presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
27387
+ () => renderablePresets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
27296
27388
  Button,
27297
27389
  {
27298
27390
  variant: activePreset === preset.value ? "primary" : "ghost",
@@ -27302,7 +27394,7 @@ var init_DateRangePicker = __esm({
27302
27394
  },
27303
27395
  preset.value
27304
27396
  )),
27305
- [presets, activePreset, handlePreset]
27397
+ [renderablePresets, activePreset, handlePreset]
27306
27398
  );
27307
27399
  return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: cn(className), children: [
27308
27400
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", align: "end", children: [
@@ -27329,7 +27421,7 @@ var init_DateRangePicker = __esm({
27329
27421
  )
27330
27422
  ] })
27331
27423
  ] }),
27332
- presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
27424
+ renderablePresets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
27333
27425
  ] });
27334
27426
  };
27335
27427
  DateRangePicker.displayName = "DateRangePicker";
@@ -27771,6 +27863,208 @@ var init_PhysicsCanvas = __esm({
27771
27863
  };
27772
27864
  }
27773
27865
  });
27866
+
27867
+ // lib/graphViewLayouts.ts
27868
+ function buildAdjacency(nodeIds, edges) {
27869
+ const known = new Set(nodeIds);
27870
+ const out = /* @__PURE__ */ new Map();
27871
+ const inMap = /* @__PURE__ */ new Map();
27872
+ for (const id of nodeIds) {
27873
+ out.set(id, []);
27874
+ inMap.set(id, []);
27875
+ }
27876
+ for (const edge of edges) {
27877
+ if (!known.has(edge.source) || !known.has(edge.target)) continue;
27878
+ out.get(edge.source)?.push(edge.target);
27879
+ inMap.get(edge.target)?.push(edge.source);
27880
+ }
27881
+ return { out, in: inMap };
27882
+ }
27883
+ function findRoots(nodeIds, adjacency) {
27884
+ return nodeIds.filter((id) => (adjacency.in.get(id)?.length ?? 0) === 0);
27885
+ }
27886
+ function assignLayers(nodeIds, adjacency, roots) {
27887
+ const layer = new Map(nodeIds.map((id) => [id, 0]));
27888
+ const onStack = /* @__PURE__ */ new Set();
27889
+ const visit = (id) => {
27890
+ onStack.add(id);
27891
+ const currentLayer = layer.get(id) ?? 0;
27892
+ for (const next of adjacency.out.get(id) ?? []) {
27893
+ if (onStack.has(next)) continue;
27894
+ const candidate = currentLayer + 1;
27895
+ if (candidate > (layer.get(next) ?? 0)) {
27896
+ layer.set(next, candidate);
27897
+ }
27898
+ visit(next);
27899
+ }
27900
+ onStack.delete(id);
27901
+ };
27902
+ for (const root of roots) visit(root);
27903
+ return layer;
27904
+ }
27905
+ function computeVisitOrder(nodeIds, adjacency, roots) {
27906
+ const order = /* @__PURE__ */ new Map();
27907
+ const visited = /* @__PURE__ */ new Set();
27908
+ let counter = 0;
27909
+ const visit = (id) => {
27910
+ if (visited.has(id)) return;
27911
+ visited.add(id);
27912
+ order.set(id, counter++);
27913
+ for (const next of adjacency.out.get(id) ?? []) visit(next);
27914
+ };
27915
+ for (const root of roots) visit(root);
27916
+ for (const id of nodeIds) {
27917
+ if (!visited.has(id)) order.set(id, counter++);
27918
+ }
27919
+ return order;
27920
+ }
27921
+ function bfsDepthAndOrder(nodeIds, adjacency, roots) {
27922
+ const depth = new Map(nodeIds.map((id) => [id, 0]));
27923
+ const visitOrder = /* @__PURE__ */ new Map();
27924
+ const visited = /* @__PURE__ */ new Set();
27925
+ const queue = [];
27926
+ let counter = 0;
27927
+ for (const root of roots) {
27928
+ if (visited.has(root)) continue;
27929
+ visited.add(root);
27930
+ depth.set(root, 0);
27931
+ visitOrder.set(root, counter++);
27932
+ queue.push(root);
27933
+ }
27934
+ let head = 0;
27935
+ while (head < queue.length) {
27936
+ const id = queue[head++];
27937
+ const d = depth.get(id) ?? 0;
27938
+ for (const next of adjacency.out.get(id) ?? []) {
27939
+ if (visited.has(next)) continue;
27940
+ visited.add(next);
27941
+ depth.set(next, d + 1);
27942
+ visitOrder.set(next, counter++);
27943
+ queue.push(next);
27944
+ }
27945
+ }
27946
+ for (const id of nodeIds) {
27947
+ if (!visited.has(id)) visitOrder.set(id, counter++);
27948
+ }
27949
+ return { depth, visitOrder };
27950
+ }
27951
+ function edgeWalkOrder(nodeIds, adjacency) {
27952
+ const visited = /* @__PURE__ */ new Set();
27953
+ const result = [];
27954
+ for (const start of nodeIds) {
27955
+ if (visited.has(start)) continue;
27956
+ let current = start;
27957
+ while (current !== void 0 && !visited.has(current)) {
27958
+ visited.add(current);
27959
+ result.push(current);
27960
+ const outs = adjacency.out.get(current) ?? [];
27961
+ current = outs.find((next) => !visited.has(next));
27962
+ }
27963
+ }
27964
+ return result;
27965
+ }
27966
+ function groupByTier(nodeIds, tierOf, maxTier) {
27967
+ const groups = Array.from({ length: maxTier + 1 }, () => []);
27968
+ for (const id of nodeIds) {
27969
+ groups[tierOf.get(id) ?? 0].push(id);
27970
+ }
27971
+ return groups;
27972
+ }
27973
+ function distributeAxis(count, start, end) {
27974
+ if (count <= 0) return [];
27975
+ const slot = (end - start) / count;
27976
+ return Array.from({ length: count }, (_, i) => start + slot * (i + 0.5));
27977
+ }
27978
+ function orderByParentPositionThenInput(group, adjacency, positioned, inputIndex) {
27979
+ const withKey = group.map((id) => {
27980
+ const parentValues = (adjacency.in.get(id) ?? []).map((p) => positioned.get(p)).filter((v) => v !== void 0);
27981
+ const avg = parentValues.length > 0 ? parentValues.reduce((a, b) => a + b, 0) / parentValues.length : Number.POSITIVE_INFINITY;
27982
+ return { id, avg, idx: inputIndex.get(id) ?? 0 };
27983
+ });
27984
+ withKey.sort((a, b) => a.avg !== b.avg ? a.avg - b.avg : a.idx - b.idx);
27985
+ return withKey.map((k) => k.id);
27986
+ }
27987
+ function layoutFlow(nodeIds, adjacency, roots, width, height, margin) {
27988
+ const inputIndex = new Map(nodeIds.map((id, i) => [id, i]));
27989
+ const layers = assignLayers(nodeIds, adjacency, roots);
27990
+ const maxLayer = Math.max(...Array.from(layers.values()));
27991
+ const layerGroups = groupByTier(nodeIds, layers, maxLayer);
27992
+ const positions = /* @__PURE__ */ new Map();
27993
+ const yById = /* @__PURE__ */ new Map();
27994
+ for (let l = 0; l <= maxLayer; l++) {
27995
+ const x = margin + l * (width - 2 * margin) / Math.max(1, maxLayer);
27996
+ const ordered2 = orderByParentPositionThenInput(layerGroups[l], adjacency, yById, inputIndex);
27997
+ const ys = distributeAxis(ordered2.length, margin, height - margin);
27998
+ ordered2.forEach((id, i) => {
27999
+ positions.set(id, { id, x, y: ys[i] });
28000
+ yById.set(id, ys[i]);
28001
+ });
28002
+ }
28003
+ return nodeIds.map((id) => positions.get(id));
28004
+ }
28005
+ function layoutTree(nodeIds, adjacency, roots, width, height, margin) {
28006
+ const effectiveRoots = roots.length > 0 ? roots : [nodeIds[0]];
28007
+ const layers = assignLayers(nodeIds, adjacency, effectiveRoots);
28008
+ const maxLayer = Math.max(...Array.from(layers.values()));
28009
+ const visitOrder = computeVisitOrder(nodeIds, adjacency, effectiveRoots);
28010
+ const layerGroups = groupByTier(nodeIds, layers, maxLayer);
28011
+ const positions = /* @__PURE__ */ new Map();
28012
+ for (let l = 0; l <= maxLayer; l++) {
28013
+ const ordered2 = [...layerGroups[l]].sort(
28014
+ (a, b) => (visitOrder.get(a) ?? 0) - (visitOrder.get(b) ?? 0)
28015
+ );
28016
+ const y = margin + l * (height - 2 * margin) / Math.max(1, maxLayer);
28017
+ const xs = distributeAxis(ordered2.length, margin, width - margin);
28018
+ ordered2.forEach((id, i) => positions.set(id, { id, x: xs[i], y }));
28019
+ }
28020
+ return nodeIds.map((id) => positions.get(id));
28021
+ }
28022
+ function layoutRadial(nodeIds, adjacency, roots, width, height, margin) {
28023
+ const cx = width / 2;
28024
+ const cy = height / 2;
28025
+ const maxRadius = Math.min(width, height) / 2 - margin;
28026
+ if (roots.length === 0) {
28027
+ const order = edgeWalkOrder(nodeIds, adjacency);
28028
+ const k = order.length;
28029
+ const positions2 = /* @__PURE__ */ new Map();
28030
+ order.forEach((id, i) => {
28031
+ const angle = i / k * 2 * Math.PI;
28032
+ positions2.set(id, { id, x: cx + maxRadius * Math.cos(angle), y: cy + maxRadius * Math.sin(angle) });
28033
+ });
28034
+ return nodeIds.map((id) => positions2.get(id));
28035
+ }
28036
+ const { depth, visitOrder } = bfsDepthAndOrder(nodeIds, adjacency, roots);
28037
+ const maxDepth = Math.max(...Array.from(depth.values()));
28038
+ const ringGroups = groupByTier(nodeIds, depth, maxDepth);
28039
+ const positions = /* @__PURE__ */ new Map();
28040
+ for (let d = 0; d <= maxDepth; d++) {
28041
+ const ordered2 = [...ringGroups[d]].sort(
28042
+ (a, b) => (visitOrder.get(a) ?? 0) - (visitOrder.get(b) ?? 0)
28043
+ );
28044
+ const radius = d * maxRadius / Math.max(1, maxDepth);
28045
+ const k = ordered2.length;
28046
+ ordered2.forEach((id, i) => {
28047
+ const angle = i / k * 2 * Math.PI;
28048
+ positions.set(id, { id, x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) });
28049
+ });
28050
+ }
28051
+ return nodeIds.map((id) => positions.get(id));
28052
+ }
28053
+ function computeStaticLayout(mode, input) {
28054
+ const { nodeIds, edges, width, height } = input;
28055
+ const margin = input.margin ?? 40;
28056
+ if (nodeIds.length === 0) return [];
28057
+ if (nodeIds.length === 1) return [{ id: nodeIds[0], x: width / 2, y: height / 2 }];
28058
+ const adjacency = buildAdjacency(nodeIds, edges);
28059
+ const roots = findRoots(nodeIds, adjacency);
28060
+ if (mode === "flow") return layoutFlow(nodeIds, adjacency, roots, width, height, margin);
28061
+ if (mode === "tree") return layoutTree(nodeIds, adjacency, roots, width, height, margin);
28062
+ return layoutRadial(nodeIds, adjacency, roots, width, height, margin);
28063
+ }
28064
+ var init_graphViewLayouts = __esm({
28065
+ "lib/graphViewLayouts.ts"() {
28066
+ }
28067
+ });
27774
28068
  function resolveNodeColor(node, groups) {
27775
28069
  if (node.color) return node.color;
27776
28070
  if (node.group) {
@@ -27785,6 +28079,7 @@ var init_GraphView = __esm({
27785
28079
  "use client";
27786
28080
  init_cn();
27787
28081
  init_atoms();
28082
+ init_graphViewLayouts();
27788
28083
  GROUP_COLORS = [
27789
28084
  "#3b82f6",
27790
28085
  // blue-500
@@ -27815,11 +28110,13 @@ var init_GraphView = __esm({
27815
28110
  height: propHeight,
27816
28111
  className,
27817
28112
  showLabels = true,
27818
- zoomToFit = true
28113
+ zoomToFit = true,
28114
+ layout = "force"
27819
28115
  }) => {
27820
28116
  const { t } = hooks.useTranslate();
27821
28117
  const containerRef = React85.useRef(null);
27822
28118
  const animRef = React85.useRef(0);
28119
+ const arrowMarkerId = React85.useId();
27823
28120
  const [simNodes, setSimNodes] = React85.useState([]);
27824
28121
  const [settled, setSettled] = React85.useState(false);
27825
28122
  const [hoveredId, setHoveredId] = React85.useState(null);
@@ -27876,6 +28173,22 @@ var init_GraphView = __esm({
27876
28173
  fy: 0
27877
28174
  };
27878
28175
  });
28176
+ if (layout !== "force") {
28177
+ const points = computeStaticLayout(layout, {
28178
+ nodeIds: nodes.map((n) => n.id),
28179
+ edges,
28180
+ width: w,
28181
+ height: h
28182
+ });
28183
+ const pointById = new Map(points.map((p) => [p.id, p]));
28184
+ const laidOut = initialNodes.map((node) => {
28185
+ const point = pointById.get(node.id);
28186
+ return point ? { ...node, x: point.x, y: point.y } : node;
28187
+ });
28188
+ setSimNodes(laidOut);
28189
+ setSettled(true);
28190
+ return;
28191
+ }
27879
28192
  let iterations = 0;
27880
28193
  const maxIterations = 120;
27881
28194
  let currentNodes = initialNodes;
@@ -27944,7 +28257,7 @@ var init_GraphView = __esm({
27944
28257
  return () => {
27945
28258
  cancelAnimationFrame(animRef.current);
27946
28259
  };
27947
- }, [nodes, edges, w, h, groups]);
28260
+ }, [nodes, edges, w, h, groups, layout]);
27948
28261
  const viewBox = React85.useMemo(() => {
27949
28262
  if (!zoomToFit || !settled || simNodes.length === 0) {
27950
28263
  return `0 0 ${w} ${h}`;
@@ -28019,6 +28332,19 @@ var init_GraphView = __esm({
28019
28332
  viewBox,
28020
28333
  preserveAspectRatio: "xMidYMid meet",
28021
28334
  children: [
28335
+ layout !== "force" && /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
28336
+ "marker",
28337
+ {
28338
+ id: arrowMarkerId,
28339
+ viewBox: "0 0 10 10",
28340
+ refX: "9",
28341
+ refY: "5",
28342
+ markerWidth: "6",
28343
+ markerHeight: "6",
28344
+ orient: "auto-start-reverse",
28345
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M0,0 L10,5 L0,10 z", fill: "currentColor" })
28346
+ }
28347
+ ) }),
28022
28348
  edges.map((edge, idx) => {
28023
28349
  const source = nodeMap.get(edge.source);
28024
28350
  const target = nodeMap.get(edge.target);
@@ -28033,8 +28359,10 @@ var init_GraphView = __esm({
28033
28359
  x2: target.x,
28034
28360
  y2: target.y,
28035
28361
  stroke: edge.color ?? DEFAULT_EDGE_COLOR,
28362
+ color: edge.color ?? DEFAULT_EDGE_COLOR,
28036
28363
  strokeWidth: 1.5,
28037
- opacity: isHighlighted ? 0.8 : 0.15
28364
+ opacity: isHighlighted ? 0.8 : 0.15,
28365
+ markerEnd: layout !== "force" ? `url(#${arrowMarkerId})` : void 0
28038
28366
  }
28039
28367
  ),
28040
28368
  showLabels && edge.label && /* @__PURE__ */ jsxRuntime.jsx(