stickyflow 0.2.0 → 0.4.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-KFJIFHXG.js → chunk-65IVT4GK.js} +475 -199
  4. package/dist/chunk-65IVT4GK.js.map +1 -0
  5. package/dist/{chunk-6JKNT2YC.js → chunk-BYMIYXP5.js} +17 -7
  6. package/dist/chunk-BYMIYXP5.js.map +1 -0
  7. package/dist/{chunk-N6WVHOUQ.js → chunk-CSXQD3ON.js} +28 -15
  8. package/dist/chunk-CSXQD3ON.js.map +1 -0
  9. package/dist/{chunk-YM3XFBI4.cjs → chunk-CXL254BT.cjs} +17 -6
  10. package/dist/chunk-CXL254BT.cjs.map +1 -0
  11. package/dist/{chunk-S5BVAAEF.cjs → chunk-DDCTNLLD.cjs} +989 -713
  12. package/dist/chunk-DDCTNLLD.cjs.map +1 -0
  13. package/dist/{chunk-34PK7HEU.cjs → chunk-HFOGKSNU.cjs} +18 -18
  14. package/dist/{chunk-34PK7HEU.cjs.map → chunk-HFOGKSNU.cjs.map} +1 -1
  15. package/dist/{chunk-IIOJFR73.cjs → chunk-UXDWH2JC.cjs} +56 -43
  16. package/dist/chunk-UXDWH2JC.cjs.map +1 -0
  17. package/dist/{chunk-6LQJUAD4.js → chunk-XEN5QIIJ.js} +6 -6
  18. package/dist/{chunk-6LQJUAD4.js.map → chunk-XEN5QIIJ.js.map} +1 -1
  19. package/dist/index.cjs +24 -24
  20. package/dist/index.d.cts +4 -4
  21. package/dist/index.d.ts +4 -4
  22. package/dist/index.js +4 -4
  23. package/dist/interaction/index.cjs +780 -382
  24. package/dist/interaction/index.cjs.map +1 -1
  25. package/dist/interaction/index.d.cts +12 -3
  26. package/dist/interaction/index.d.ts +12 -3
  27. package/dist/interaction/index.js +562 -165
  28. package/dist/interaction/index.js.map +1 -1
  29. package/dist/{render-r1GYvjNm.d.cts → render-C5X74hds.d.cts} +75 -4
  30. package/dist/{render-r1GYvjNm.d.ts → render-C5X74hds.d.ts} +75 -4
  31. package/dist/{runtimeTypes-ByiafBwg.d.ts → runtimeTypes-D8hPZ62T.d.ts} +1 -1
  32. package/dist/{runtimeTypes-DwLeD-em.d.cts → runtimeTypes-yTSAvtCn.d.cts} +1 -1
  33. package/dist/stickyflow-diagram.global.js +37 -35
  34. package/dist/stickyflow-diagram.global.js.map +1 -1
  35. package/dist/{types-T7W2yTQF.d.cts → types-BDKDf4zr.d.cts} +1 -1
  36. package/dist/{types-ndGA1kbl.d.ts → types-CdgGdtoD.d.ts} +1 -1
  37. package/dist/viewer/index.cjs +9 -9
  38. package/dist/viewer/index.d.cts +4 -4
  39. package/dist/viewer/index.d.ts +4 -4
  40. package/dist/viewer/index.js +4 -4
  41. package/dist/web-component/index.cjs +6 -6
  42. package/dist/web-component/index.d.cts +2 -2
  43. package/dist/web-component/index.d.ts +2 -2
  44. package/dist/web-component/index.js +4 -4
  45. package/package.json +1 -1
  46. package/dist/chunk-6JKNT2YC.js.map +0 -1
  47. package/dist/chunk-IIOJFR73.cjs.map +0 -1
  48. package/dist/chunk-KFJIFHXG.js.map +0 -1
  49. package/dist/chunk-N6WVHOUQ.js.map +0 -1
  50. package/dist/chunk-S5BVAAEF.cjs.map +0 -1
  51. package/dist/chunk-YM3XFBI4.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk34PK7HEU_cjs = require('../chunk-34PK7HEU.cjs');
4
- var chunkYM3XFBI4_cjs = require('../chunk-YM3XFBI4.cjs');
3
+ var chunkHFOGKSNU_cjs = require('../chunk-HFOGKSNU.cjs');
4
+ var chunkCXL254BT_cjs = require('../chunk-CXL254BT.cjs');
5
5
 
6
6
  // src/runtime/interaction/chartValue/coordinates.ts
7
7
  function pointerUserY(svg, event) {
@@ -70,13 +70,13 @@ function updateConnectedLine(svg, drag) {
70
70
  }));
71
71
  const line = findConnectedLine(svg, drag.owner.id, drag.series);
72
72
  if (line) {
73
- line.setAttribute("d", chunkYM3XFBI4_cjs.linePathData(points, drag.lineTension));
73
+ line.setAttribute("d", chunkCXL254BT_cjs.linePathData(points, drag.lineTension));
74
74
  }
75
75
  const area = findConnectedLineArea(svg, drag.owner.id, drag.series);
76
76
  if (area && points.length > 1) {
77
77
  const first = points[0];
78
78
  const last = points[points.length - 1];
79
- const d = `${chunkYM3XFBI4_cjs.linePathData(points, drag.lineTension)} L ${last.x} ${drag.baseY} L ${first.x} ${drag.baseY} Z`;
79
+ const d = `${chunkCXL254BT_cjs.linePathData(points, drag.lineTension)} L ${last.x} ${drag.baseY} L ${first.x} ${drag.baseY} Z`;
80
80
  area.setAttribute("d", d);
81
81
  }
82
82
  }
@@ -90,14 +90,14 @@ function setBarPath(svg, drag, d) {
90
90
  function updateChartValuePreview(svg, drag, value) {
91
91
  if (drag.isBar && drag.scale.horizontal) {
92
92
  const width = Math.max(0, pixelForValue(value, drag.scale) - drag.barX);
93
- setBarPath(svg, drag, chunkYM3XFBI4_cjs.roundedBarPath(drag.barX, drag.barTop, width, drag.barHeight, drag.barRadius));
93
+ setBarPath(svg, drag, chunkCXL254BT_cjs.roundedBarPath(drag.barX, drag.barTop, width, drag.barHeight, drag.barRadius));
94
94
  return;
95
95
  }
96
96
  const y = pixelForValue(value, drag.scale);
97
97
  if (drag.isBar) {
98
98
  const top = Math.min(y, drag.baseY);
99
99
  const height = Math.max(0, Math.abs(drag.baseY - y));
100
- setBarPath(svg, drag, chunkYM3XFBI4_cjs.barShapePath(drag.barX, top, drag.barWidth, height, drag.barRadius));
100
+ setBarPath(svg, drag, chunkCXL254BT_cjs.barShapePath(drag.barX, top, drag.barWidth, height, drag.barRadius));
101
101
  return;
102
102
  }
103
103
  drag.element.setAttribute("cy", String(y));
@@ -120,24 +120,24 @@ function labelShift(placement, origin, top, height) {
120
120
  }
121
121
  function resizePill(pill, text, label, dy) {
122
122
  const fontSize = parseFloat(text.getAttribute("font-size") ?? "12");
123
- const size = chunkYM3XFBI4_cjs.barLabelSize(label, fontSize, true);
123
+ const size = chunkCXL254BT_cjs.barLabelSize(label, fontSize, true);
124
124
  const stored = pill.dataset.sfPillY ?? (pill.getAttribute("d") ?? "").split(/\s+/)[2];
125
125
  pill.dataset.sfPillY = stored;
126
126
  const centerX = Number(text.getAttribute("x"));
127
- pill.setAttribute("d", chunkYM3XFBI4_cjs.pillPath(centerX - size.width / 2, Number(stored), size.width, size.height));
127
+ pill.setAttribute("d", chunkCXL254BT_cjs.pillPath(centerX - size.width / 2, Number(stored), size.width, size.height));
128
128
  pill.setAttribute("transform", `translate(0 ${dy})`);
129
129
  }
130
130
  function updateHorizontalBarLabel(label, drag, origin, value) {
131
- const content = chunkYM3XFBI4_cjs.formatBarLabel(value, label.template);
131
+ const content = chunkCXL254BT_cjs.formatBarLabel(value, label.template);
132
132
  (label.text.querySelector("tspan") ?? label.text).textContent = content;
133
133
  if (label.placement === "axis") {
134
134
  return true;
135
135
  }
136
136
  const fontSize = parseFloat(label.text.getAttribute("font-size") ?? "12");
137
- const size = chunkYM3XFBI4_cjs.barLabelSize(content, fontSize, label.pill !== null);
137
+ const size = chunkCXL254BT_cjs.barLabelSize(content, fontSize, label.pill !== null);
138
138
  const width = Math.max(0, pixelForValue(value, drag.scale) - origin.left);
139
139
  const end = origin.left + width;
140
- const center = label.placement === "outside" ? end + chunkYM3XFBI4_cjs.BAR_LABEL.gap + size.width / 2 : label.placement === "inside" ? end - chunkYM3XFBI4_cjs.BAR_LABEL.gap - size.width / 2 : origin.left + width / 2;
140
+ const center = label.placement === "outside" ? end + chunkCXL254BT_cjs.BAR_LABEL.gap + size.width / 2 : label.placement === "inside" ? end - chunkCXL254BT_cjs.BAR_LABEL.gap - size.width / 2 : origin.left + width / 2;
141
141
  const stored = label.text.dataset.sfLabelX ?? label.text.getAttribute("x") ?? "0";
142
142
  label.text.dataset.sfLabelX = stored;
143
143
  label.text.setAttribute("transform", `translate(${center - Number(stored)} 0)`);
@@ -145,7 +145,7 @@ function updateHorizontalBarLabel(label, drag, origin, value) {
145
145
  const pillY = label.pill.dataset.sfPillY ?? (label.pill.getAttribute("d") ?? "").split(/\s+/)[2];
146
146
  label.pill.dataset.sfPillY = pillY;
147
147
  label.pill.removeAttribute("transform");
148
- label.pill.setAttribute("d", chunkYM3XFBI4_cjs.pillPath(center - size.width / 2, Number(pillY), size.width, size.height));
148
+ label.pill.setAttribute("d", chunkCXL254BT_cjs.pillPath(center - size.width / 2, Number(pillY), size.width, size.height));
149
149
  }
150
150
  return true;
151
151
  }
@@ -161,7 +161,7 @@ function updateBarLabel(svg, drag, origin, value) {
161
161
  const top = Math.min(y, drag.baseY);
162
162
  const height = Math.abs(drag.baseY - y);
163
163
  const dy = labelShift(label.placement, origin, top, height);
164
- const content = chunkYM3XFBI4_cjs.formatBarLabel(value, label.template);
164
+ const content = chunkCXL254BT_cjs.formatBarLabel(value, label.template);
165
165
  (label.text.querySelector("tspan") ?? label.text).textContent = content;
166
166
  label.text.setAttribute("transform", `translate(0 ${dy})`);
167
167
  if (label.pill) {
@@ -177,7 +177,7 @@ var HEIGHT = 18;
177
177
  var GAP = 8;
178
178
  var BACKGROUND = "rgba(15, 23, 42, 0.9)";
179
179
  function element(svg, tag) {
180
- return svg.ownerDocument.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, tag);
180
+ return svg.ownerDocument.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, tag);
181
181
  }
182
182
  function createValueReadout(svg) {
183
183
  const group = element(svg, "g");
@@ -273,7 +273,7 @@ function resolveChartValueDrag(svg, event) {
273
273
  if (!target) {
274
274
  return null;
275
275
  }
276
- const scale = parseValueScale(chunk34PK7HEU_cjs.findOwnerNode(svg, target.owner.id, chunk34PK7HEU_cjs.isPrimary));
276
+ const scale = parseValueScale(chunkHFOGKSNU_cjs.findOwnerNode(svg, target.owner.id, chunkHFOGKSNU_cjs.isPrimary));
277
277
  const geometry = scale ? resolveChartValueGeometry(svg, target, scale) : null;
278
278
  if (!scale || !geometry) {
279
279
  return null;
@@ -293,13 +293,13 @@ function createChartValueDragState(target, scale, geometry, pointerId) {
293
293
  };
294
294
  }
295
295
  function isChartValuePointer(event) {
296
- return event.button === 0 && !chunk34PK7HEU_cjs.isCameraGesture(event);
296
+ return event.button === 0 && !chunkHFOGKSNU_cjs.isCameraGesture(event);
297
297
  }
298
298
  function findChartValueMark(event) {
299
299
  return event.target?.closest?.("[data-sf-value-index]");
300
300
  }
301
301
  function readChartValueTarget(mark) {
302
- const owner = chunk34PK7HEU_cjs.resolveOwner(mark);
302
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(mark);
303
303
  if (owner?.role !== "chart") {
304
304
  return null;
305
305
  }
@@ -468,6 +468,39 @@ function normalizeHex(value) {
468
468
  const full = body.length === 3 ? body.split("").map((char) => char + char).join("") : body;
469
469
  return `#${full.toLowerCase()}`;
470
470
  }
471
+ var COLOR_FUNCTION = /^rgba?\(\s*(\d{1,3})\s*[, ]\s*(\d{1,3})\s*[, ]\s*(\d{1,3})\s*(?:[,/]\s*(\d*\.?\d+)(%?)\s*)?\)$/i;
472
+ var HEX_WITH_ALPHA = /^#([0-9a-f]{6})([0-9a-f]{2})$/i;
473
+ function parseColorAlpha(value) {
474
+ const raw = value.trim();
475
+ const fn = COLOR_FUNCTION.exec(raw);
476
+ if (fn) {
477
+ const alpha = fn[4] === void 0 ? 1 : Number(fn[4]) / (fn[5] ? 100 : 1);
478
+ return {
479
+ hex: rgbToHex({ r: Number(fn[1]), g: Number(fn[2]), b: Number(fn[3]) }),
480
+ alpha: Math.max(0, Math.min(1, alpha))
481
+ };
482
+ }
483
+ const eight = HEX_WITH_ALPHA.exec(raw);
484
+ if (eight) {
485
+ return { hex: `#${eight[1].toLowerCase()}`, alpha: Number.parseInt(eight[2], 16) / 255 };
486
+ }
487
+ const hex = normalizeHex(raw);
488
+ return hex ? { hex, alpha: 1 } : null;
489
+ }
490
+ function formatColorAlpha(hex, alpha) {
491
+ const clamped = Math.max(0, Math.min(1, alpha));
492
+ if (clamped >= 1) {
493
+ return hex;
494
+ }
495
+ const { r, g, b } = hexToRgb(hex);
496
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(clamped * 100) / 100})`;
497
+ }
498
+ function hexOf(value) {
499
+ return parseColorAlpha(value)?.hex ?? "#000000";
500
+ }
501
+ function alphaOf(value) {
502
+ return parseColorAlpha(value)?.alpha ?? 1;
503
+ }
471
504
  function clampChannel(value) {
472
505
  return Math.max(0, Math.min(255, Math.round(value)));
473
506
  }
@@ -534,7 +567,7 @@ function hsvToHex(hsv) {
534
567
  // src/runtime/interaction/colorEdit/gradientValue.ts
535
568
  var DEFAULT_GRADIENT_ANGLE = 90;
536
569
  var GRADIENT = /^gradient\(\s*(-?[\d.]+)\s*,\s*(.+)\)\s*$/i;
537
- var STOP = /(#[0-9a-f]{3}(?:[0-9a-f]{3})?)\s+(-?[\d.]+)%/gi;
570
+ var STOP = /(rgba?\([^)]*\)|#[0-9a-f]{3}(?:[0-9a-f]{3})?)\s+(-?[\d.]+)%/gi;
538
571
  function trim(value) {
539
572
  return Number(value.toFixed(1));
540
573
  }
@@ -555,10 +588,10 @@ function parseGradient(source) {
555
588
  }
556
589
  const stops = [];
557
590
  for (const stop of match[2].matchAll(STOP)) {
558
- const color = normalizeHex(stop[1]);
591
+ const parsed = parseColorAlpha(stop[1]);
559
592
  const position = Number(stop[2]);
560
- if (color && Number.isFinite(position)) {
561
- stops.push({ color, position: clampPosition(position) });
593
+ if (parsed && Number.isFinite(position)) {
594
+ stops.push({ color: formatColorAlpha(parsed.hex, parsed.alpha), position: clampPosition(position) });
562
595
  }
563
596
  }
564
597
  return stops.length >= 2 ? { angle, stops } : null;
@@ -593,10 +626,10 @@ function readGradientValue(svg, fill) {
593
626
  }
594
627
  const stops = [];
595
628
  for (const stop of def.querySelectorAll("stop")) {
596
- const color = normalizeHex(stop.getAttribute("stop-color") ?? "");
629
+ const parsed = parseColorAlpha(stop.getAttribute("stop-color") ?? "");
597
630
  const offset = Number.parseFloat(stop.getAttribute("offset") ?? "");
598
- if (color && Number.isFinite(offset)) {
599
- stops.push({ color, position: clampPosition(offset) });
631
+ if (parsed && Number.isFinite(offset)) {
632
+ stops.push({ color: formatColorAlpha(parsed.hex, parsed.alpha), position: clampPosition(offset) });
600
633
  }
601
634
  }
602
635
  if (stops.length < 2) {
@@ -615,17 +648,21 @@ function seedFrom(fill, gradient) {
615
648
  if (parsed) {
616
649
  return { mode: "gradient", angle: parsed.angle, stops: sortStops(parsed.stops) };
617
650
  }
618
- return { mode: "solid", color: fill && normalizeHex(fill) || FALLBACK_COLOR };
651
+ const solid = fill ? parseColorAlpha(fill) : null;
652
+ return { mode: "solid", color: solid?.hex ?? FALLBACK_COLOR, alpha: solid?.alpha ?? 1 };
619
653
  }
620
654
  function formatPickerValue(value) {
621
- return value.mode === "solid" ? value.color : formatGradient({ angle: value.angle, stops: value.stops });
655
+ return value.mode === "solid" ? formatColorAlpha(value.color, value.alpha ?? 1) : formatGradient({ angle: value.angle, stops: value.stops });
622
656
  }
623
657
  function cssBackground(color) {
624
658
  const gradient = parseGradient(color);
625
659
  return gradient ? gradientCss(gradient) : color;
626
660
  }
661
+ function toAlpha(value) {
662
+ return value.mode === "solid" ? value.alpha ?? 1 : alphaOf(sortStops(value.stops)[0]?.color ?? FALLBACK_COLOR);
663
+ }
627
664
  function toSolid(value) {
628
- return value.mode === "solid" ? value.color : sortStops(value.stops)[0]?.color ?? FALLBACK_COLOR;
665
+ return value.mode === "solid" ? value.color : hexOf(sortStops(value.stops)[0]?.color ?? FALLBACK_COLOR);
629
666
  }
630
667
  function darken(hex) {
631
668
  const hsv = hexToHsv(hex);
@@ -638,8 +675,8 @@ function toGradient(value) {
638
675
  return {
639
676
  angle: DEFAULT_GRADIENT_ANGLE,
640
677
  stops: [
641
- { color: value.color, position: 0 },
642
- { color: darken(value.color), position: 100 }
678
+ { color: formatColorAlpha(value.color, value.alpha ?? 1), position: 0 },
679
+ { color: formatColorAlpha(darken(value.color), value.alpha ?? 1), position: 100 }
643
680
  ]
644
681
  };
645
682
  }
@@ -651,17 +688,30 @@ function activeColor(picker) {
651
688
  const { state } = picker;
652
689
  return state.mode === "solid" ? state.solid : state.gradient.stops[state.selected]?.color ?? state.solid;
653
690
  }
654
- function setActiveColor(picker, hex) {
691
+ function activeHex(picker) {
692
+ return hexOf(activeColor(picker));
693
+ }
694
+ function activeAlpha(picker) {
695
+ return picker.state.mode === "solid" ? picker.state.alpha : alphaOf(activeColor(picker));
696
+ }
697
+ function setActiveColorAlpha(picker, hex, alpha) {
655
698
  const { state } = picker;
656
699
  if (state.mode === "solid") {
657
700
  state.solid = hex;
701
+ state.alpha = alpha;
658
702
  } else if (state.gradient.stops[state.selected]) {
659
- state.gradient.stops[state.selected] = { ...state.gradient.stops[state.selected], color: hex };
703
+ state.gradient.stops[state.selected] = {
704
+ ...state.gradient.stops[state.selected],
705
+ color: formatColorAlpha(hex, alpha)
706
+ };
660
707
  }
661
708
  }
709
+ function setActiveColor(picker, hex) {
710
+ setActiveColorAlpha(picker, hex, activeAlpha(picker));
711
+ }
662
712
  function currentValue(picker) {
663
713
  const { state } = picker;
664
- return state.mode === "solid" ? { mode: "solid", color: state.solid } : { mode: "gradient", ...state.gradient };
714
+ return state.mode === "solid" ? { mode: "solid", color: state.solid, alpha: state.alpha } : { mode: "gradient", ...state.gradient };
665
715
  }
666
716
  function commit(picker) {
667
717
  picker.onCommit(formatPickerValue(currentValue(picker)));
@@ -676,6 +726,14 @@ function applyHex(picker, hex) {
676
726
  setActiveColor(picker, hex);
677
727
  picker.render();
678
728
  }
729
+ function applyAlpha(picker, raw) {
730
+ const value = Number(raw);
731
+ if (!Number.isFinite(value)) {
732
+ return;
733
+ }
734
+ setActiveColorAlpha(picker, activeHex(picker), Math.max(0, Math.min(100, value)) / 100);
735
+ picker.render();
736
+ }
679
737
  function applyAngle(picker, raw) {
680
738
  const value = Number(raw);
681
739
  if (!Number.isFinite(value)) {
@@ -690,7 +748,7 @@ function selectStop(picker, index) {
690
748
  return;
691
749
  }
692
750
  state.selected = index;
693
- state.hsv = hexToHsv(state.gradient.stops[index].color);
751
+ state.hsv = hexToHsv(hexOf(state.gradient.stops[index].color));
694
752
  picker.render();
695
753
  }
696
754
  function removeStop(picker, index) {
@@ -700,7 +758,7 @@ function removeStop(picker, index) {
700
758
  }
701
759
  state.gradient = { ...state.gradient, stops: state.gradient.stops.filter((_stop, at) => at !== index) };
702
760
  state.selected = Math.min(state.selected, state.gradient.stops.length - 1);
703
- state.hsv = hexToHsv(activeColor(picker));
761
+ state.hsv = hexToHsv(activeHex(picker));
704
762
  picker.render();
705
763
  commit(picker);
706
764
  }
@@ -713,12 +771,12 @@ function appendStop(picker) {
713
771
  const last = sorted[sorted.length - 1];
714
772
  const previous = sorted[sorted.length - 2];
715
773
  const inserted = {
716
- color: darken(last.color),
774
+ color: formatColorAlpha(darken(hexOf(last.color)), alphaOf(last.color)),
717
775
  position: clampPosition((last.position + (previous?.position ?? 0)) / 2)
718
776
  };
719
777
  state.gradient = { ...state.gradient, stops: sortStops([...state.gradient.stops, inserted]) };
720
778
  state.selected = state.gradient.stops.indexOf(inserted);
721
- state.hsv = hexToHsv(activeColor(picker));
779
+ state.hsv = hexToHsv(activeHex(picker));
722
780
  picker.render();
723
781
  commit(picker);
724
782
  }
@@ -734,8 +792,9 @@ function setMode(picker, next) {
734
792
  state.selected = 0;
735
793
  } else {
736
794
  state.solid = toSolid(value);
795
+ state.alpha = toAlpha(value);
737
796
  }
738
- state.hsv = hexToHsv(activeColor(picker));
797
+ state.hsv = hexToHsv(activeHex(picker));
739
798
  picker.render();
740
799
  commit(picker);
741
800
  }
@@ -768,12 +827,23 @@ function numberField(parent, min, max) {
768
827
  input.max = String(max);
769
828
  return input;
770
829
  }
771
- function rangeField(parent, min, max) {
772
- const input = el("input", "sf-cp-range", parent);
773
- input.type = "range";
774
- input.min = String(min);
775
- input.max = String(max);
776
- return input;
830
+ function fluidField(parent, text, min, max) {
831
+ const row = el("div", "sf-cp-fluid", parent);
832
+ el("span", "sf-cp-fluid-fill", row);
833
+ el("span", "sf-cp-fluid-thumb", row);
834
+ el("span", "sf-cp-fluid-label", row).textContent = text;
835
+ const range = el("input", "sf-cp-fluid-range", row);
836
+ range.type = "range";
837
+ range.min = String(min);
838
+ range.max = String(max);
839
+ const number = numberField(row, min, max);
840
+ number.classList.add("sf-cp-fluid-number");
841
+ return { row, range, number };
842
+ }
843
+ function showRatio(range) {
844
+ const span = Number(range.max) - Number(range.min);
845
+ const ratio2 = span > 0 ? (Number(range.value) - Number(range.min)) / span : 0;
846
+ range.parentElement?.style.setProperty("--sf-ratio", String(Math.max(0, Math.min(1, ratio2))));
777
847
  }
778
848
  function labelledRow(parent, text) {
779
849
  const row = el("div", "sf-cp-row", parent);
@@ -820,23 +890,36 @@ function buildSolidControls(root) {
820
890
  const channelRanges = {};
821
891
  const channelNumbers = {};
822
892
  for (const channel of CHANNELS) {
823
- const row = labelledRow(rows, channel.toUpperCase());
824
- channelRanges[channel] = rangeField(row, 0, 255);
825
- channelNumbers[channel] = numberField(row, 0, 255);
893
+ const field = fluidField(rows, channel.toUpperCase(), 0, 255);
894
+ channelRanges[channel] = field.range;
895
+ channelNumbers[channel] = field.number;
826
896
  }
897
+ const alpha = fluidField(rows, "A", 0, 100);
898
+ alpha.row.classList.add("sf-cp-fluid--alpha");
899
+ const { row: alphaRow, range: alphaRange, number: alphaNumber } = alpha;
827
900
  const hexRow = labelledRow(rows, "Hex");
828
901
  const hexInput = el("input", "sf-cp-text", hexRow);
829
902
  hexInput.type = "text";
830
903
  hexInput.spellcheck = false;
831
- return { matrix, matrixCursor, hue, hueThumb, channelRanges, channelNumbers, hexInput };
904
+ return {
905
+ matrix,
906
+ matrixCursor,
907
+ hue,
908
+ hueThumb,
909
+ channelRanges,
910
+ channelNumbers,
911
+ alphaRow,
912
+ alphaRange,
913
+ alphaNumber,
914
+ hexInput
915
+ };
832
916
  }
833
917
  function buildGradientControls(root, lockStops) {
834
918
  const section = el("div", "sf-cp-section", root);
835
919
  const preview = el("div", "sf-cp-preview", section);
836
- const angleRow = labelledRow(section, "Angle");
837
- angleRow.hidden = lockStops;
838
- const angleRange = rangeField(angleRow, 0, 360);
839
- const angleNumber = numberField(angleRow, 0, 360);
920
+ const angle = fluidField(section, "Angle", 0, 360);
921
+ angle.row.hidden = lockStops;
922
+ const { range: angleRange, number: angleNumber } = angle;
840
923
  const head = el("div", "sf-cp-section-head", section);
841
924
  el("span", "sf-cp-heading", head).textContent = "Stops";
842
925
  const addStop = el("button", "sf-cp-icon-btn", head);
@@ -918,7 +1001,7 @@ function bindChannel(picker, channel) {
918
1001
  if (!Number.isFinite(value)) {
919
1002
  return;
920
1003
  }
921
- const next = { ...hexToRgb(activeColor(picker)), [channel]: value };
1004
+ const next = { ...hexToRgb(activeHex(picker)), [channel]: value };
922
1005
  const nextHsv = rgbToHsv(next);
923
1006
  picker.state.hsv = nextHsv.s === 0 ? { ...nextHsv, h: picker.state.hsv.h } : nextHsv;
924
1007
  setActiveColor(picker, rgbToHex(next));
@@ -930,6 +1013,14 @@ function bindChannel(picker, channel) {
930
1013
  channelNumbers[channel].addEventListener("input", (event) => fromChannel(read(event)));
931
1014
  channelNumbers[channel].addEventListener("change", () => commit(picker));
932
1015
  }
1016
+ function bindAlpha(picker) {
1017
+ const { alphaRange, alphaNumber } = picker.view;
1018
+ const read = (event) => event.target.value;
1019
+ alphaRange.addEventListener("input", (event) => applyAlpha(picker, read(event)));
1020
+ alphaRange.addEventListener("change", () => commit(picker));
1021
+ alphaNumber.addEventListener("input", (event) => applyAlpha(picker, read(event)));
1022
+ alphaNumber.addEventListener("change", () => commit(picker));
1023
+ }
933
1024
  function bindHex(picker) {
934
1025
  const { hexInput } = picker.view;
935
1026
  hexInput.addEventListener("input", () => {
@@ -966,6 +1057,7 @@ function bindPickerEvents(picker) {
966
1057
  for (const channel of CHANNELS) {
967
1058
  bindChannel(picker, channel);
968
1059
  }
1060
+ bindAlpha(picker);
969
1061
  bindHex(picker);
970
1062
  bindAngle(picker);
971
1063
  return disposers;
@@ -1016,7 +1108,8 @@ function renderStops(picker) {
1016
1108
  const row = rows[index];
1017
1109
  row.root.setAttribute("aria-selected", String(index === state.selected));
1018
1110
  row.swatch.style.background = stop.color;
1019
- row.hex.textContent = stop.color;
1111
+ const alpha = alphaOf(stop.color);
1112
+ row.hex.textContent = alpha < 1 ? `${hexOf(stop.color)} ${Math.round(alpha * 100)}%` : hexOf(stop.color);
1020
1113
  if (document.activeElement !== row.position) {
1021
1114
  row.position.value = String(Math.round(stop.position));
1022
1115
  }
@@ -1031,7 +1124,7 @@ function renderPicker(picker) {
1031
1124
  view.solidTab.setAttribute("aria-selected", String(state.mode === "solid"));
1032
1125
  view.gradientTab.setAttribute("aria-selected", String(state.mode === "gradient"));
1033
1126
  view.section.hidden = state.mode !== "gradient";
1034
- const hex = activeColor(picker);
1127
+ const hex = activeHex(picker);
1035
1128
  const rgb = hexToRgb(hex);
1036
1129
  view.matrix.style.background = `hsl(${state.hsv.h}, 100%, 50%)`;
1037
1130
  view.matrixCursor.style.left = `${state.hsv.s * 100}%`;
@@ -1039,15 +1132,25 @@ function renderPicker(picker) {
1039
1132
  view.hueThumb.style.top = `${state.hsv.h / 360 * 100}%`;
1040
1133
  for (const channel of CHANNELS) {
1041
1134
  view.channelRanges[channel].value = String(rgb[channel]);
1135
+ showRatio(view.channelRanges[channel]);
1042
1136
  if (document.activeElement !== view.channelNumbers[channel]) {
1043
1137
  view.channelNumbers[channel].value = String(rgb[channel]);
1044
1138
  }
1045
1139
  }
1140
+ const percent = Math.round(activeAlpha(picker) * 100);
1141
+ view.alphaRange.value = String(percent);
1142
+ showRatio(view.alphaRange);
1143
+ if (document.activeElement !== view.alphaNumber) {
1144
+ view.alphaNumber.value = String(percent);
1145
+ }
1146
+ const opaque = `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
1147
+ view.alphaRow.style.background = `linear-gradient(to right, rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0), ${opaque}), conic-gradient(var(--sf-cp-check-a) 25%, var(--sf-cp-check-b) 0 50%, var(--sf-cp-check-a) 0 75%, var(--sf-cp-check-b) 0) 0 0 / 8px 8px`;
1046
1148
  if (document.activeElement !== view.hexInput) {
1047
1149
  view.hexInput.value = hex;
1048
1150
  }
1049
1151
  if (state.mode === "gradient") {
1050
1152
  view.angleRange.value = String(Math.round(state.gradient.angle));
1153
+ showRatio(view.angleRange);
1051
1154
  if (document.activeElement !== view.angleNumber) {
1052
1155
  view.angleNumber.value = String(Math.round(state.gradient.angle));
1053
1156
  }
@@ -1063,8 +1166,8 @@ var DARK_TOKENS = `
1063
1166
  --sf-cp-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
1064
1167
  --sf-cp-fg: rgba(255, 255, 255, 0.92);
1065
1168
  --sf-cp-muted: rgba(255, 255, 255, 0.6);
1066
- --sf-cp-tabs-bg: rgba(255, 255, 255, 0.04);
1067
- --sf-cp-tab-active-bg: rgba(255, 255, 255, 0.12);
1169
+ --sf-cp-tabs-bg: rgba(255, 255, 255, 0.05);
1170
+ --sf-cp-tab-active-bg: rgba(255, 255, 255, 0.1);
1068
1171
  --sf-cp-field-bg: rgba(255, 255, 255, 0.04);
1069
1172
  --sf-cp-field-border: rgba(255, 255, 255, 0.08);
1070
1173
  --sf-cp-row-bg: rgba(255, 255, 255, 0.04);
@@ -1073,6 +1176,9 @@ var DARK_TOKENS = `
1073
1176
  --sf-cp-thumb-bg: #e8e8e8;
1074
1177
  --sf-cp-thumb-border: #555;
1075
1178
  --sf-cp-danger: #ff7a77;
1179
+ --sf-cp-accent: rgba(255, 255, 255, 0.85);
1180
+ --sf-cp-check-a: #3b3b3f;
1181
+ --sf-cp-check-b: #2a2a2d;
1076
1182
  `;
1077
1183
  var BASE_CSS = `
1078
1184
  .sf-cp {
@@ -1081,7 +1187,7 @@ var BASE_CSS = `
1081
1187
  --sf-cp-shadow: 0 8px 24px rgba(15, 23, 42, 0.16);
1082
1188
  --sf-cp-fg: #333333;
1083
1189
  --sf-cp-muted: #666666;
1084
- --sf-cp-tabs-bg: #f5f5f5;
1190
+ --sf-cp-tabs-bg: #f1f5f9;
1085
1191
  --sf-cp-tab-active-bg: #ffffff;
1086
1192
  --sf-cp-field-bg: #f8f8f8;
1087
1193
  --sf-cp-field-border: #e0e0e0;
@@ -1091,16 +1197,18 @@ var BASE_CSS = `
1091
1197
  --sf-cp-thumb-bg: #ffffff;
1092
1198
  --sf-cp-thumb-border: #666666;
1093
1199
  --sf-cp-danger: #e53935;
1094
- --sf-cp-accent: #9b42df;
1200
+ --sf-cp-accent: #0f172a;
1201
+ --sf-cp-check-a: #c8c8c8;
1202
+ --sf-cp-check-b: #ffffff;
1095
1203
 
1096
1204
  position: fixed;
1097
1205
  z-index: 10000;
1098
1206
  box-sizing: border-box;
1099
1207
  width: 268px;
1100
- padding: 12px;
1208
+ padding: 10px;
1101
1209
  display: flex;
1102
1210
  flex-direction: column;
1103
- gap: 14px;
1211
+ gap: 10px;
1104
1212
  border: 1px solid var(--sf-cp-border);
1105
1213
  border-radius: 12px;
1106
1214
  background: var(--sf-cp-bg);
@@ -1128,7 +1236,7 @@ var FIELDS_CSS = `
1128
1236
  .sf-cp-rows {
1129
1237
  display: flex;
1130
1238
  flex-direction: column;
1131
- gap: 8px;
1239
+ gap: 5px;
1132
1240
  }
1133
1241
 
1134
1242
  .sf-cp-row {
@@ -1144,44 +1252,114 @@ var FIELDS_CSS = `
1144
1252
  font-weight: 600;
1145
1253
  }
1146
1254
 
1147
- .sf-cp-range {
1148
- flex: 1;
1149
- min-width: 0;
1150
- height: 6px;
1151
- border-radius: 3px;
1152
- outline: none;
1153
- background: var(--sf-cp-track);
1154
- -webkit-appearance: none;
1155
- appearance: none;
1255
+ .sf-cp-fluid {
1256
+ --sf-ratio: 0;
1257
+ position: relative;
1258
+ display: flex;
1259
+ align-items: center;
1260
+ justify-content: space-between;
1261
+ gap: 10px;
1262
+ height: 26px;
1263
+ padding: 0 8px;
1264
+ border-radius: 8px;
1265
+ background: var(--sf-cp-row-bg);
1266
+ overflow: hidden;
1267
+ user-select: none;
1268
+ }
1269
+
1270
+ .sf-cp-fluid[hidden] {
1271
+ display: none;
1272
+ }
1273
+
1274
+ .sf-cp-fluid-fill {
1275
+ position: absolute;
1276
+ inset: 0 auto 0 0;
1277
+ width: calc(var(--sf-ratio) * 100%);
1278
+ border-radius: 8px;
1279
+ background: linear-gradient(90deg, color-mix(in srgb, currentColor 5%, transparent), color-mix(in srgb, currentColor 18%, transparent));
1280
+ pointer-events: none;
1281
+ }
1282
+
1283
+ .sf-cp-fluid--alpha .sf-cp-fluid-fill {
1284
+ display: none;
1285
+ }
1286
+
1287
+ .sf-cp-fluid-thumb {
1288
+ position: absolute;
1289
+ top: 50%;
1290
+ left: calc(var(--sf-ratio) * 100% - var(--sf-ratio) * 5px);
1291
+ width: 5px;
1292
+ height: 14px;
1293
+ border-radius: 999px;
1294
+ background: var(--sf-cp-fg);
1295
+ box-shadow: 0 0 0 1px var(--sf-cp-bg);
1296
+ transform: translateY(-50%);
1297
+ pointer-events: none;
1298
+ transition: height 180ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 220ms ease;
1299
+ }
1300
+
1301
+ .sf-cp-fluid:hover .sf-cp-fluid-thumb,
1302
+ .sf-cp-fluid:focus-within .sf-cp-fluid-thumb {
1303
+ height: 20px;
1304
+ }
1305
+
1306
+ .sf-cp-fluid:has(.sf-cp-fluid-range:active) .sf-cp-fluid-thumb {
1307
+ height: 26px;
1308
+ box-shadow: 0 0 0 1px var(--sf-cp-bg), 0 0 0 5px color-mix(in srgb, var(--sf-cp-fg) 15%, transparent);
1309
+ }
1310
+
1311
+ .sf-cp-fluid-label {
1312
+ position: relative;
1313
+ color: var(--sf-cp-muted);
1314
+ font-size: 11px;
1315
+ font-weight: 600;
1316
+ pointer-events: none;
1317
+ }
1318
+
1319
+ .sf-cp-fluid-range {
1320
+ position: absolute;
1321
+ inset: 0;
1322
+ width: 100%;
1323
+ height: 100%;
1324
+ margin: 0;
1325
+ opacity: 0;
1326
+ cursor: ew-resize;
1156
1327
  }
1157
1328
 
1158
- .sf-cp-range::-webkit-slider-thumb {
1329
+ .sf-cp-number.sf-cp-fluid-number {
1330
+ position: relative;
1331
+ z-index: 2;
1332
+ width: 44px;
1333
+ padding: 1px 6px;
1334
+ border: none;
1335
+ background: transparent;
1336
+ text-align: right;
1337
+ font-weight: 600;
1338
+ font-variant-numeric: tabular-nums;
1339
+ -moz-appearance: textfield;
1340
+ appearance: textfield;
1341
+ }
1342
+
1343
+ .sf-cp-fluid-number::-webkit-inner-spin-button,
1344
+ .sf-cp-fluid-number::-webkit-outer-spin-button {
1159
1345
  -webkit-appearance: none;
1160
- appearance: none;
1161
- width: 15px;
1162
- height: 15px;
1163
- border: 2px solid var(--sf-cp-thumb-border);
1164
- border-radius: 50%;
1165
- background: var(--sf-cp-thumb-bg);
1166
- cursor: pointer;
1167
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
1346
+ margin: 0;
1168
1347
  }
1169
1348
 
1170
- .sf-cp-range::-moz-range-thumb {
1171
- width: 15px;
1172
- height: 15px;
1173
- border: 2px solid var(--sf-cp-thumb-border);
1174
- border-radius: 50%;
1175
- background: var(--sf-cp-thumb-bg);
1176
- cursor: pointer;
1177
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
1349
+ .sf-cp-fluid-number:hover {
1350
+ background: var(--sf-cp-hover);
1351
+ }
1352
+
1353
+ .sf-cp-number.sf-cp-fluid-number:focus {
1354
+ background: var(--sf-cp-field-bg);
1355
+ box-shadow: 0 0 0 1px var(--sf-cp-accent);
1178
1356
  }
1179
1357
 
1180
1358
  .sf-cp-number,
1181
1359
  .sf-cp-text {
1182
1360
  flex: none;
1183
1361
  width: 52px;
1184
- padding: 4px 8px;
1362
+ padding: 3px 8px;
1185
1363
  border: 1px solid var(--sf-cp-field-border);
1186
1364
  border-radius: 6px;
1187
1365
  background: var(--sf-cp-field-bg);
@@ -1371,8 +1549,9 @@ var GRADIENT_CSS = `
1371
1549
  var TABS_AND_AREA_CSS = `
1372
1550
  .sf-cp-tabs {
1373
1551
  display: flex;
1374
- gap: 4px;
1375
- padding: 4px;
1552
+ gap: 2px;
1553
+ height: 28px;
1554
+ padding: 2px;
1376
1555
  border-radius: 8px;
1377
1556
  background: var(--sf-cp-tabs-bg);
1378
1557
  }
@@ -1383,12 +1562,13 @@ var TABS_AND_AREA_CSS = `
1383
1562
 
1384
1563
  .sf-cp-tab {
1385
1564
  flex: 1;
1386
- padding: 5px 12px;
1565
+ padding: 0 12px;
1387
1566
  border: none;
1388
1567
  border-radius: 6px;
1389
1568
  background: transparent;
1390
1569
  color: var(--sf-cp-muted);
1391
1570
  font: inherit;
1571
+ font-size: 11px;
1392
1572
  font-weight: 500;
1393
1573
  cursor: pointer;
1394
1574
  transition: background 0.15s ease, color 0.15s ease;
@@ -1401,8 +1581,8 @@ var TABS_AND_AREA_CSS = `
1401
1581
 
1402
1582
  .sf-cp-tab[aria-selected="true"] {
1403
1583
  background: var(--sf-cp-tab-active-bg);
1404
- color: var(--sf-cp-accent);
1405
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
1584
+ color: var(--sf-cp-fg);
1585
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
1406
1586
  }
1407
1587
 
1408
1588
  .sf-cp-area {
@@ -1503,6 +1683,7 @@ function openColorPopover(options) {
1503
1683
  state: {
1504
1684
  mode: allowGradient ? seed.mode : "solid",
1505
1685
  solid,
1686
+ alpha: toAlpha(seed),
1506
1687
  gradient: toGradient(seed),
1507
1688
  selected: 0,
1508
1689
  hsv: hexToHsv(solid)
@@ -1570,7 +1751,7 @@ var ColorEditSession = class {
1570
1751
  const hasOverride = target.node.getAttribute("data-sf-color-override") === "true";
1571
1752
  this.#open = openColorPopover({
1572
1753
  seed: seedFrom(fill, readGradientValue(this.#svg, fill)),
1573
- anchor: chunk34PK7HEU_cjs.screenRectOf(target.node),
1754
+ anchor: chunkHFOGKSNU_cjs.screenRectOf(target.node),
1574
1755
  theme: resolveTheme(this.#theme),
1575
1756
  allowGradient: !target.solidOnly,
1576
1757
  onCommit: (color) => {
@@ -1652,7 +1833,7 @@ function resolveTarget(event, selector, pathOf, rules) {
1652
1833
  return null;
1653
1834
  }
1654
1835
  const path = pathOf(node);
1655
- const owner = chunk34PK7HEU_cjs.resolveOwner(node);
1836
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(node);
1656
1837
  if (!path || !owner || !isEditablePath(path, rules) || requiresPriorSelection(node, owner)) {
1657
1838
  return null;
1658
1839
  }
@@ -1674,7 +1855,7 @@ function resolveZoneGradientTarget(event) {
1674
1855
  if (!node) {
1675
1856
  return null;
1676
1857
  }
1677
- const owner = chunk34PK7HEU_cjs.resolveOwner(node);
1858
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(node);
1678
1859
  if (!owner) {
1679
1860
  return null;
1680
1861
  }
@@ -1710,7 +1891,7 @@ var ZoneGradientSession = class {
1710
1891
  const beforeStops = sortStops(gradient.stops);
1711
1892
  this.#open = openColorPopover({
1712
1893
  seed: seedFrom(fill, gradient),
1713
- anchor: chunk34PK7HEU_cjs.screenRectOf(target.node),
1894
+ anchor: chunkHFOGKSNU_cjs.screenRectOf(target.node),
1714
1895
  theme: resolveTheme(this.#theme),
1715
1896
  allowGradient: true,
1716
1897
  lockStops: true,
@@ -1783,15 +1964,15 @@ function bindDeleteSelection(viewer, emitter) {
1783
1964
  }
1784
1965
 
1785
1966
  // src/runtime/interaction/events.ts
1786
- var Emitter2 = class extends chunk34PK7HEU_cjs.Emitter {
1967
+ var Emitter2 = class extends chunkHFOGKSNU_cjs.Emitter {
1787
1968
  };
1788
1969
 
1789
1970
  // src/runtime/interaction/linkPreview/geometry.ts
1790
1971
  function anchorPoint(bounds, side, other) {
1791
1972
  if (side) {
1792
- return chunkYM3XFBI4_cjs.pointAtPort(bounds, { side, offset: 0.5 });
1973
+ return chunkCXL254BT_cjs.pointAtPort(bounds, { side, offset: 0.5 });
1793
1974
  }
1794
- return chunkYM3XFBI4_cjs.edgePointToward(bounds, other);
1975
+ return chunkCXL254BT_cjs.edgePointToward(bounds, other);
1795
1976
  }
1796
1977
  function polylinePathData(points) {
1797
1978
  if (points.length < 4) {
@@ -1808,7 +1989,7 @@ function previewPathData(points, segments, pathType, strokeWidth) {
1808
1989
  return `M ${points[0]} ${points[1]} C ${points[2]} ${points[3]} ${points[4]} ${points[5]} ${points[6]} ${points[7]}`;
1809
1990
  }
1810
1991
  if (pathType === "orthogonal" && segments.length > 0) {
1811
- return chunkYM3XFBI4_cjs.roundedOrthogonalPathData(segments, Math.max(16, strokeWidth * 4));
1992
+ return chunkCXL254BT_cjs.roundedOrthogonalPathData(segments, Math.max(16, strokeWidth * 4));
1812
1993
  }
1813
1994
  return polylinePathData(points);
1814
1995
  }
@@ -1828,8 +2009,8 @@ function previewLink(fromSide, toSide) {
1828
2009
  function routePreviewLink(fromBounds, toBounds, fromSide, toSide, pathType) {
1829
2010
  const from = anchorPoint(fromBounds, fromSide, toBounds);
1830
2011
  const to = anchorPoint(toBounds, toSide, fromBounds);
1831
- const { points, segments } = chunkYM3XFBI4_cjs.calculateLinkRoute(previewLink(fromSide, toSide), from, to, pathType);
1832
- return { points, segments, midpoint: chunkYM3XFBI4_cjs.getLineMidpoint(points, pathType, from, to) };
2012
+ const { points, segments } = chunkCXL254BT_cjs.calculateLinkRoute(previewLink(fromSide, toSide), from, to, pathType);
2013
+ return { points, segments, midpoint: chunkCXL254BT_cjs.getLineMidpoint(points, pathType, from, to) };
1833
2014
  }
1834
2015
 
1835
2016
  // src/runtime/interaction/linkPreview/discovery.ts
@@ -1861,7 +2042,7 @@ function resolveOppositeEndpoint(svg, path, canvasObjectId) {
1861
2042
  if (!otherId) {
1862
2043
  return null;
1863
2044
  }
1864
- const otherPrimary = chunk34PK7HEU_cjs.findOwnerNode(svg, otherId, chunk34PK7HEU_cjs.isPrimary);
2045
+ const otherPrimary = chunkHFOGKSNU_cjs.findOwnerNode(svg, otherId, chunkHFOGKSNU_cjs.isPrimary);
1865
2046
  return otherPrimary ? { draggedIsFrom, bounds: otherPrimary.getBBox() } : null;
1866
2047
  }
1867
2048
  function captureLiveLinkLabel(svg, draft, draggedBounds) {
@@ -1908,8 +2089,8 @@ function resolveOtherFacePoint(svg, path, canvasObjectId) {
1908
2089
  if (!otherId || !face || !otherFace) {
1909
2090
  return null;
1910
2091
  }
1911
- const otherPrimary = chunk34PK7HEU_cjs.findOwnerNode(svg, otherId, chunk34PK7HEU_cjs.isPrimary);
1912
- const otherGeometry = otherPrimary && chunk34PK7HEU_cjs.isometricGeometryOf(otherPrimary);
2092
+ const otherPrimary = chunkHFOGKSNU_cjs.findOwnerNode(svg, otherId, chunkHFOGKSNU_cjs.isPrimary);
2093
+ const otherGeometry = otherPrimary && chunkHFOGKSNU_cjs.isometricGeometryOf(otherPrimary);
1913
2094
  if (!otherGeometry?.bounds) {
1914
2095
  return null;
1915
2096
  }
@@ -1920,7 +2101,7 @@ function resolveOtherFacePoint(svg, path, canvasObjectId) {
1920
2101
  height: otherGeometry.height,
1921
2102
  depth: otherGeometry.depth
1922
2103
  };
1923
- return { otherPoint: chunkYM3XFBI4_cjs.isometricFaceCenter(otherObject, otherFace), draggedIsFrom, face };
2104
+ return { otherPoint: chunkCXL254BT_cjs.isometricFaceCenter(otherObject, otherFace), draggedIsFrom, face };
1924
2105
  }
1925
2106
  function findLiveFaceLinks(svg, canvasObjectId) {
1926
2107
  const escapedId = CSS.escape(canvasObjectId);
@@ -1939,7 +2120,7 @@ function findLiveFaceLinks(svg, canvasObjectId) {
1939
2120
 
1940
2121
  // src/runtime/interaction/linkPreview/faceUpdate.ts
1941
2122
  function updateLiveFaceLink(link, liveObject) {
1942
- const draggedPoint = chunkYM3XFBI4_cjs.isometricFaceCenter(liveObject, link.face);
2123
+ const draggedPoint = chunkCXL254BT_cjs.isometricFaceCenter(liveObject, link.face);
1943
2124
  const from = link.draggedIsFrom ? draggedPoint : link.otherPoint;
1944
2125
  const to = link.draggedIsFrom ? link.otherPoint : draggedPoint;
1945
2126
  link.path.setAttribute("d", `M ${from.x} ${from.y} L ${to.x} ${to.y}`);
@@ -1963,7 +2144,7 @@ function updateLabelGap(link, points) {
1963
2144
  if (!link.labelGapSize) {
1964
2145
  return;
1965
2146
  }
1966
- const gap = chunkYM3XFBI4_cjs.labelGapDash(points, link.pathType, link.labelGapSize.width, link.labelGapSize.height);
2147
+ const gap = chunkCXL254BT_cjs.labelGapDash(points, link.pathType, link.labelGapSize.width, link.labelGapSize.height);
1967
2148
  if (gap) {
1968
2149
  link.path.setAttribute("stroke-dasharray", `${gap.dashBefore} ${gap.gapLength} 1000000`);
1969
2150
  } else {
@@ -2003,11 +2184,11 @@ function readIsometricSnapStep(svg) {
2003
2184
  return step > 0 ? step : null;
2004
2185
  }
2005
2186
  function nearestIsometricLatticePoint(point, step) {
2006
- const u = point.x / (chunkYM3XFBI4_cjs.AXIS_COS * step);
2007
- const v = point.y / (chunkYM3XFBI4_cjs.AXIS_SIN * step);
2187
+ const u = point.x / (chunkCXL254BT_cjs.AXIS_COS * step);
2188
+ const v = point.y / (chunkCXL254BT_cjs.AXIS_SIN * step);
2008
2189
  const i = Math.round((u + v) / 2);
2009
2190
  const j = Math.round((u - v) / 2);
2010
- return { x: (i + j) * chunkYM3XFBI4_cjs.AXIS_COS * step, y: (i - j) * chunkYM3XFBI4_cjs.AXIS_SIN * step };
2191
+ return { x: (i + j) * chunkCXL254BT_cjs.AXIS_COS * step, y: (i - j) * chunkCXL254BT_cjs.AXIS_SIN * step };
2011
2192
  }
2012
2193
  function snapToStep(value, step, min) {
2013
2194
  return Math.max(min, Math.round(value / step) * step);
@@ -2020,21 +2201,21 @@ var LABEL_FONT_SIZE = 12;
2020
2201
  var LABEL_LINE_HEIGHT = 1.2;
2021
2202
  var LABEL_BASELINE_OFFSET = -LABEL_GAP - LABEL_HEIGHT + (LABEL_HEIGHT - LABEL_FONT_SIZE * LABEL_LINE_HEIGHT) / 2 + LABEL_FONT_SIZE;
2022
2203
  function applyIsometricAxisPreview(nodes, object, cornerRadius, overlay, svg) {
2023
- const faces = chunkYM3XFBI4_cjs.isometricFaces(object);
2024
- nodes.top?.setAttribute("d", chunkYM3XFBI4_cjs.roundedPolygonPath(faces.top, 0));
2025
- nodes.front?.setAttribute("d", chunkYM3XFBI4_cjs.roundedPolygonPath(faces.front, 0));
2026
- nodes.side?.setAttribute("d", chunkYM3XFBI4_cjs.roundedPolygonPath(faces.right, 0));
2204
+ const faces = chunkCXL254BT_cjs.isometricFaces(object);
2205
+ nodes.top?.setAttribute("d", chunkCXL254BT_cjs.roundedPolygonPath(faces.top, 0));
2206
+ nodes.front?.setAttribute("d", chunkCXL254BT_cjs.roundedPolygonPath(faces.front, 0));
2207
+ nodes.side?.setAttribute("d", chunkCXL254BT_cjs.roundedPolygonPath(faces.right, 0));
2027
2208
  const silhouette = [faces.top[0], faces.top[1], faces.right[2], faces.front[2], faces.front[3], faces.top[3]];
2028
- const hullPath = chunkYM3XFBI4_cjs.roundedPolygonPath(silhouette, cornerRadius);
2209
+ const hullPath = chunkCXL254BT_cjs.roundedPolygonPath(silhouette, cornerRadius);
2029
2210
  nodes.hull?.setAttribute("d", hullPath);
2030
2211
  if (overlay.halo) {
2031
- chunk34PK7HEU_cjs.updateHalo(overlay.halo, hullPath);
2212
+ chunkHFOGKSNU_cjs.updateHalo(overlay.halo, hullPath);
2032
2213
  }
2033
- const placements = chunk34PK7HEU_cjs.axisArrowPlacements(object);
2214
+ const placements = chunkHFOGKSNU_cjs.axisArrowPlacements(object);
2034
2215
  Object.keys(placements).forEach((axis) => {
2035
2216
  const group = overlay.arrows[axis];
2036
2217
  if (group) {
2037
- chunk34PK7HEU_cjs.updateAxisArrowGroup(group, placements[axis].origin, placements[axis].direction, svg);
2218
+ chunkHFOGKSNU_cjs.updateAxisArrowGroup(group, placements[axis].origin, placements[axis].direction, svg);
2038
2219
  }
2039
2220
  });
2040
2221
  nodes.seams?.setAttribute(
@@ -2052,9 +2233,9 @@ function applyIsometricAxisPreview(nodes, object, cornerRadius, overlay, svg) {
2052
2233
  x: footprintCenter.x + (point.x - footprintCenter.x) * shadowSpread,
2053
2234
  y: footprintCenter.y + (point.y - footprintCenter.y) * shadowSpread
2054
2235
  }));
2055
- nodes.groundShadow.setAttribute("d", chunkYM3XFBI4_cjs.roundedPolygonPath(footprint, 0));
2236
+ nodes.groundShadow.setAttribute("d", chunkCXL254BT_cjs.roundedPolygonPath(footprint, 0));
2056
2237
  }
2057
- const anchor = chunkYM3XFBI4_cjs.isometricTopFaceCenter(object);
2238
+ const anchor = chunkCXL254BT_cjs.isometricTopFaceCenter(object);
2058
2239
  if (nodes.labelGuide) {
2059
2240
  nodes.labelGuide.setAttribute("d", `M ${anchor.x} ${anchor.y - LABEL_GAP} L ${anchor.x} ${anchor.y}`);
2060
2241
  }
@@ -2070,7 +2251,7 @@ function applyIsometricAxisPreview(nodes, object, cornerRadius, overlay, svg) {
2070
2251
  // src/runtime/interaction/isometricAxisResize/state.ts
2071
2252
  var AXES = ["width", "height", "depth"];
2072
2253
  function collectNodes(svg, ownerId) {
2073
- const all = chunk34PK7HEU_cjs.findAllOwnerNodes(svg, ownerId);
2254
+ const all = chunkHFOGKSNU_cjs.findAllOwnerNodes(svg, ownerId);
2074
2255
  const bySuffix = (suffix) => all.find((el2) => el2.id.endsWith(suffix)) ?? null;
2075
2256
  return {
2076
2257
  top: bySuffix("-top"),
@@ -2096,30 +2277,30 @@ function createIsometricAxisDragState(svg, event) {
2096
2277
  if (!ownerId) {
2097
2278
  return null;
2098
2279
  }
2099
- const primary = chunk34PK7HEU_cjs.findOwnerNode(svg, ownerId, chunk34PK7HEU_cjs.isPrimary);
2100
- const owner = primary && chunk34PK7HEU_cjs.resolveOwner(primary);
2280
+ const primary = chunkHFOGKSNU_cjs.findOwnerNode(svg, ownerId, chunkHFOGKSNU_cjs.isPrimary);
2281
+ const owner = primary && chunkHFOGKSNU_cjs.resolveOwner(primary);
2101
2282
  if (!primary || owner?.role !== "isometric") {
2102
2283
  return null;
2103
2284
  }
2104
- const startUser = chunk34PK7HEU_cjs.pointerUserPoint(svg, event);
2285
+ const startUser = chunkHFOGKSNU_cjs.pointerUserPoint(svg, event);
2105
2286
  if (!startUser) {
2106
2287
  return null;
2107
2288
  }
2108
- const geometry = chunk34PK7HEU_cjs.isometricGeometryOf(primary);
2289
+ const geometry = chunkHFOGKSNU_cjs.isometricGeometryOf(primary);
2109
2290
  const bounds = geometry?.bounds ?? primary.getBBox();
2110
2291
  const nodes = collectNodes(svg, ownerId);
2111
2292
  [nodes.top, nodes.front, nodes.side].forEach((node) => {
2112
2293
  node?.removeAttribute("clip-path");
2113
2294
  });
2114
2295
  captureTarget.setPointerCapture?.(event.pointerId);
2115
- const overlayHalo = overlay?.querySelector(`[${chunk34PK7HEU_cjs.ISO_HALO_ATTR}]`) ?? null;
2296
+ const overlayHalo = overlay?.querySelector(`[${chunkHFOGKSNU_cjs.ISO_HALO_ATTR}]`) ?? null;
2116
2297
  const overlayArrows = Object.fromEntries(
2117
2298
  AXES.map((axis2) => [
2118
2299
  axis2,
2119
2300
  overlay?.querySelector(`[data-sf-resize-handle="iso-${axis2}"]`) ?? null
2120
2301
  ])
2121
2302
  );
2122
- const overlayDuplicateBubbles = overlay?.querySelector(`[${chunk34PK7HEU_cjs.ISO_DUPLICATE_BUBBLES_ATTR}]`) ?? null;
2303
+ const overlayDuplicateBubbles = overlay?.querySelector(`[${chunkHFOGKSNU_cjs.ISO_DUPLICATE_BUBBLES_ATTR}]`) ?? null;
2123
2304
  if (overlayDuplicateBubbles) {
2124
2305
  overlayDuplicateBubbles.style.display = "none";
2125
2306
  }
@@ -2136,7 +2317,7 @@ function createIsometricAxisDragState(svg, event) {
2136
2317
  pointerId: event.pointerId,
2137
2318
  startUser,
2138
2319
  start,
2139
- cornerRadius: geometry?.cornerRadius ?? Number(primary.getAttribute(chunkYM3XFBI4_cjs.CORNER_RADIUS_ATTR)) ?? 0,
2320
+ cornerRadius: geometry?.cornerRadius ?? Number(primary.getAttribute(chunkCXL254BT_cjs.CORNER_RADIUS_ATTR)) ?? 0,
2140
2321
  nodes,
2141
2322
  overlayHalo,
2142
2323
  overlayArrows,
@@ -2155,15 +2336,15 @@ function nextGeometry(drag, point, step) {
2155
2336
  const dx = point.x - drag.startUser.x;
2156
2337
  const dy = point.y - drag.startUser.y;
2157
2338
  if (axis === "width") {
2158
- const delta2 = dx * chunkYM3XFBI4_cjs.AXIS_COS + dy * chunkYM3XFBI4_cjs.AXIS_SIN;
2339
+ const delta2 = dx * chunkCXL254BT_cjs.AXIS_COS + dy * chunkCXL254BT_cjs.AXIS_SIN;
2159
2340
  return { ...start, width: length(start.width + delta2, MIN_SIZE) };
2160
2341
  }
2161
2342
  if (axis === "height") {
2162
2343
  return { ...start, height: length(start.height + dy, MIN_SIZE) };
2163
2344
  }
2164
- const delta = -dx * chunkYM3XFBI4_cjs.AXIS_COS + dy * chunkYM3XFBI4_cjs.AXIS_SIN;
2345
+ const delta = -dx * chunkCXL254BT_cjs.AXIS_COS + dy * chunkCXL254BT_cjs.AXIS_SIN;
2165
2346
  const depth = length(start.depth + delta, 0);
2166
- const x = start.x + (start.depth - depth) * chunkYM3XFBI4_cjs.AXIS_COS;
2347
+ const x = start.x + (start.depth - depth) * chunkCXL254BT_cjs.AXIS_COS;
2167
2348
  return { ...start, x, depth };
2168
2349
  }
2169
2350
  var IsometricAxisResizeSession = class {
@@ -2175,7 +2356,7 @@ var IsometricAxisResizeSession = class {
2175
2356
  this.#emitter = emitter;
2176
2357
  }
2177
2358
  pointerDown = (event) => {
2178
- if (event.button !== 0 || this.#drag || chunk34PK7HEU_cjs.isCameraGesture(event)) {
2359
+ if (event.button !== 0 || this.#drag || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
2179
2360
  return;
2180
2361
  }
2181
2362
  this.#drag = createIsometricAxisDragState(this.#svg, event);
@@ -2185,7 +2366,7 @@ var IsometricAxisResizeSession = class {
2185
2366
  if (!drag || event.pointerId !== drag.pointerId) {
2186
2367
  return;
2187
2368
  }
2188
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
2369
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
2189
2370
  if (!point) {
2190
2371
  return;
2191
2372
  }
@@ -2283,7 +2464,7 @@ function findLabelMark(event) {
2283
2464
  );
2284
2465
  }
2285
2466
  function isLabelPointer(event) {
2286
- return event.button === 0 && !chunk34PK7HEU_cjs.isCameraGesture(event);
2467
+ return event.button === 0 && !chunkHFOGKSNU_cjs.isCameraGesture(event);
2287
2468
  }
2288
2469
  function findHull(svg, ownerId) {
2289
2470
  return svg.querySelector(`[data-sf-id="${CSS.escape(ownerId)}"][data-sf-primary="true"]`);
@@ -2299,21 +2480,21 @@ function resolveIsometricLabelDrag(svg, event) {
2299
2480
  if (!clicked) {
2300
2481
  return null;
2301
2482
  }
2302
- const owner = chunk34PK7HEU_cjs.resolveOwner(clicked);
2483
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(clicked);
2303
2484
  if (owner?.role !== "isometric") {
2304
2485
  return null;
2305
2486
  }
2306
2487
  const hull = findHull(svg, owner.id);
2307
- const geometry = hull ? chunk34PK7HEU_cjs.isometricGeometryOf(hull) : null;
2488
+ const geometry = hull ? chunkHFOGKSNU_cjs.isometricGeometryOf(hull) : null;
2308
2489
  if (!geometry?.bounds) {
2309
2490
  return null;
2310
2491
  }
2311
- const start = chunk34PK7HEU_cjs.pointerUserPoint(svg, event);
2492
+ const start = chunkHFOGKSNU_cjs.pointerUserPoint(svg, event);
2312
2493
  if (!start) {
2313
2494
  return null;
2314
2495
  }
2315
2496
  const anchorX = geometry.bounds.x + geometry.bounds.width / 2;
2316
- const anchorY = geometry.bounds.y + geometry.bounds.width * (chunkYM3XFBI4_cjs.AXIS_SIN / chunkYM3XFBI4_cjs.AXIS_COS) / 2;
2497
+ const anchorY = geometry.bounds.y + geometry.bounds.width * (chunkCXL254BT_cjs.AXIS_SIN / chunkCXL254BT_cjs.AXIS_COS) / 2;
2317
2498
  const text = findBySuffix(svg, `-${owner.id}-label`);
2318
2499
  if (!text) {
2319
2500
  return null;
@@ -2365,7 +2546,7 @@ var IsometricLabelDragSession = class {
2365
2546
  if (!this.#drag || event.pointerId !== this.#drag.pointerId) {
2366
2547
  return;
2367
2548
  }
2368
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
2549
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
2369
2550
  if (!point) {
2370
2551
  return;
2371
2552
  }
@@ -2440,7 +2621,7 @@ function isIsometricDirection(value) {
2440
2621
  function bindIsometricQuickDuplicate(viewer, emitter) {
2441
2622
  const svg = viewer.svg;
2442
2623
  const onPointerDown = (event) => {
2443
- if (event.button !== 0 || chunk34PK7HEU_cjs.isCameraGesture(event)) {
2624
+ if (event.button !== 0 || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
2444
2625
  return;
2445
2626
  }
2446
2627
  const bubble = event.target?.closest("[data-sf-quick-duplicate]");
@@ -2451,7 +2632,7 @@ function bindIsometricQuickDuplicate(viewer, emitter) {
2451
2632
  const overlay = bubble.closest("[data-sf-selection-overlay]");
2452
2633
  const sourceId = overlay?.getAttribute("data-sf-selection-overlay");
2453
2634
  const primary = sourceId ? svg.querySelector(`[data-sf-id="${CSS.escape(sourceId)}"][data-sf-primary="true"]`) : null;
2454
- const owner = primary && chunk34PK7HEU_cjs.resolveOwner(primary);
2635
+ const owner = primary && chunkHFOGKSNU_cjs.resolveOwner(primary);
2455
2636
  if (!owner) {
2456
2637
  return;
2457
2638
  }
@@ -2519,7 +2700,7 @@ function updateEndpointPreview(drag, draggedPoint, draggedSide) {
2519
2700
  const toPoint = drag.end === "to" ? draggedPoint : drag.fixedPoint;
2520
2701
  const fromSide = drag.end === "from" ? draggedSide : drag.fixedSide;
2521
2702
  const toSide = drag.end === "to" ? draggedSide : drag.fixedSide;
2522
- const { points, segments } = chunkYM3XFBI4_cjs.calculateLinkRoute(previewLink2(fromSide, toSide), fromPoint, toPoint, drag.pathType);
2703
+ const { points, segments } = chunkCXL254BT_cjs.calculateLinkRoute(previewLink2(fromSide, toSide), fromPoint, toPoint, drag.pathType);
2523
2704
  drag.path.setAttribute("d", previewPathData(points, segments, drag.pathType, drag.strokeWidth));
2524
2705
  }
2525
2706
 
@@ -2541,7 +2722,7 @@ var LinkGhost = class {
2541
2722
  constructor(svg, path) {
2542
2723
  this.#svg = svg;
2543
2724
  this.#path = path;
2544
- this.#anchors = svg.ownerDocument.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, "g");
2725
+ this.#anchors = svg.ownerDocument.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, "g");
2545
2726
  this.#anchors.setAttribute("data-sf-link-target", "");
2546
2727
  this.#anchors.setAttribute("pointer-events", "none");
2547
2728
  }
@@ -2551,7 +2732,7 @@ var LinkGhost = class {
2551
2732
  for (const name of RESTORED_ATTRIBUTES) {
2552
2733
  this.#saved.set(name, this.#path.getAttribute(name));
2553
2734
  }
2554
- const dash = GHOST_DASH_PX / chunk34PK7HEU_cjs.pxPerUnit(this.#svg);
2735
+ const dash = GHOST_DASH_PX / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg);
2555
2736
  this.#path.setAttribute("stroke-dasharray", `${dash} ${dash}`);
2556
2737
  this.#path.setAttribute("stroke-linecap", "round");
2557
2738
  this.#path.setAttribute("opacity", GHOST_OPACITY);
@@ -2580,7 +2761,7 @@ var LinkGhost = class {
2580
2761
  if (!bounds) {
2581
2762
  return;
2582
2763
  }
2583
- const unit = 1 / chunk34PK7HEU_cjs.pxPerUnit(this.#svg);
2764
+ const unit = 1 / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg);
2584
2765
  const centers = [
2585
2766
  [bounds.x + bounds.width / 2, bounds.y],
2586
2767
  [bounds.x + bounds.width, bounds.y + bounds.height / 2],
@@ -2588,7 +2769,7 @@ var LinkGhost = class {
2588
2769
  [bounds.x, bounds.y + bounds.height / 2]
2589
2770
  ];
2590
2771
  for (const [cx, cy] of centers) {
2591
- const dot = this.#svg.ownerDocument.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, "circle");
2772
+ const dot = this.#svg.ownerDocument.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, "circle");
2592
2773
  dot.setAttribute("cx", String(cx));
2593
2774
  dot.setAttribute("cy", String(cy));
2594
2775
  dot.setAttribute("r", String(ANCHOR_RADIUS_PX * unit));
@@ -2608,7 +2789,7 @@ function collectEndpointCandidates(svg) {
2608
2789
  if (element2.getAttribute("data-sf-role") === "link") {
2609
2790
  continue;
2610
2791
  }
2611
- const owner = chunk34PK7HEU_cjs.resolveOwner(element2);
2792
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(element2);
2612
2793
  if (owner) {
2613
2794
  candidates.push({ owner, bounds: element2.getBBox() });
2614
2795
  }
@@ -2685,7 +2866,7 @@ function inferFixedSide(svg, reference, fixedPrimary) {
2685
2866
  if (reference.declaredSide) {
2686
2867
  return reference.declaredSide;
2687
2868
  }
2688
- const draggedPrimary = reference.draggedId ? chunk34PK7HEU_cjs.findOwnerNode(svg, reference.draggedId, chunk34PK7HEU_cjs.isPrimary) : null;
2869
+ const draggedPrimary = reference.draggedId ? chunkHFOGKSNU_cjs.findOwnerNode(svg, reference.draggedId, chunkHFOGKSNU_cjs.isPrimary) : null;
2689
2870
  if (!draggedPrimary) {
2690
2871
  return "right";
2691
2872
  }
@@ -2693,7 +2874,7 @@ function inferFixedSide(svg, reference, fixedPrimary) {
2693
2874
  }
2694
2875
  function resolveFixedEndpoint(svg, path, draggedEnd) {
2695
2876
  const reference = fixedEndpointReference(path, draggedEnd);
2696
- const fixedPrimary = reference.fixedId ? chunk34PK7HEU_cjs.findOwnerNode(svg, reference.fixedId, chunk34PK7HEU_cjs.isPrimary) : null;
2877
+ const fixedPrimary = reference.fixedId ? chunkHFOGKSNU_cjs.findOwnerNode(svg, reference.fixedId, chunkHFOGKSNU_cjs.isPrimary) : null;
2697
2878
  if (!fixedPrimary) {
2698
2879
  return null;
2699
2880
  }
@@ -2712,8 +2893,8 @@ function selectLinkEndpoint(svg, event) {
2712
2893
  if (!target || !end || !linkId) {
2713
2894
  return null;
2714
2895
  }
2715
- const path = chunk34PK7HEU_cjs.findOwnerNode(svg, linkId, chunk34PK7HEU_cjs.isPrimary);
2716
- const linkOwner = path && chunk34PK7HEU_cjs.resolveOwner(path);
2896
+ const path = chunkHFOGKSNU_cjs.findOwnerNode(svg, linkId, chunkHFOGKSNU_cjs.isPrimary);
2897
+ const linkOwner = path && chunkHFOGKSNU_cjs.resolveOwner(path);
2717
2898
  if (!path || !linkOwner) {
2718
2899
  return null;
2719
2900
  }
@@ -2755,8 +2936,8 @@ function nearestPort(bounds, point) {
2755
2936
  let nearest = { side: "right", offset: 0.5 };
2756
2937
  let nearestDistance = Infinity;
2757
2938
  for (const side of SIDES2) {
2758
- const offset = Math.max(0, Math.min(1, chunkYM3XFBI4_cjs.relativeOffsetOnRectangleSide(bounds, side, point)));
2759
- const candidate = chunkYM3XFBI4_cjs.pointAtPort(bounds, { side, offset });
2939
+ const offset = Math.max(0, Math.min(1, chunkCXL254BT_cjs.relativeOffsetOnRectangleSide(bounds, side, point)));
2940
+ const candidate = chunkCXL254BT_cjs.pointAtPort(bounds, { side, offset });
2760
2941
  const distance = Math.hypot(candidate.x - point.x, candidate.y - point.y);
2761
2942
  if (distance < nearestDistance) {
2762
2943
  nearestDistance = distance;
@@ -2815,7 +2996,7 @@ function resolveLinkTarget(candidates, fixedPoint, point, unitsPerPx) {
2815
2996
  }
2816
2997
  const port = snapPort(candidate.bounds, point, unitsPerPx);
2817
2998
  return {
2818
- point: chunkYM3XFBI4_cjs.pointAtPort(candidate.bounds, port),
2999
+ point: chunkCXL254BT_cjs.pointAtPort(candidate.bounds, port),
2819
3000
  side: port.side,
2820
3001
  hit: { owner: candidate.owner, side: port.side, offset: port.offset },
2821
3002
  bounds: candidate.bounds
@@ -2839,7 +3020,7 @@ var LinkEndpointSession = class {
2839
3020
  this.#emitter = emitter;
2840
3021
  }
2841
3022
  pointerDown = (event) => {
2842
- if (event.button !== 0 || this.#drag || chunk34PK7HEU_cjs.isCameraGesture(event)) {
3023
+ if (event.button !== 0 || this.#drag || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
2843
3024
  return;
2844
3025
  }
2845
3026
  this.#drag = createLinkEndpointDragState(this.#svg, event);
@@ -2853,7 +3034,7 @@ var LinkEndpointSession = class {
2853
3034
  return;
2854
3035
  }
2855
3036
  drag.moved = true;
2856
- const target = resolveEndpointTarget(drag, endpointPointerPosition(this.#svg, event), 1 / chunk34PK7HEU_cjs.pxPerUnit(this.#svg));
3037
+ const target = resolveEndpointTarget(drag, endpointPointerPosition(this.#svg, event), 1 / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg));
2857
3038
  updateEndpointPreview(drag, target.point, target.side);
2858
3039
  drag.ghost.show(target.hit !== null, target.bounds);
2859
3040
  };
@@ -2967,7 +3148,7 @@ var LinkSegmentSession = class {
2967
3148
  this.#emitter = emitter;
2968
3149
  }
2969
3150
  pointerDown = (event) => {
2970
- if (event.button !== 0 || this.#drag || chunk34PK7HEU_cjs.isCameraGesture(event)) {
3151
+ if (event.button !== 0 || this.#drag || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
2971
3152
  return;
2972
3153
  }
2973
3154
  const target = event.target;
@@ -2977,12 +3158,12 @@ var LinkSegmentSession = class {
2977
3158
  if (!handle || !overlay || !linkId) {
2978
3159
  return;
2979
3160
  }
2980
- const path = chunk34PK7HEU_cjs.findOwnerNode(this.#svg, linkId, chunk34PK7HEU_cjs.isPrimary);
2981
- const owner = path && chunk34PK7HEU_cjs.resolveOwner(path);
3161
+ const path = chunkHFOGKSNU_cjs.findOwnerNode(this.#svg, linkId, chunkHFOGKSNU_cjs.isPrimary);
3162
+ const owner = path && chunkHFOGKSNU_cjs.resolveOwner(path);
2982
3163
  const index = Number(handle.getAttribute("data-sf-link-segment"));
2983
3164
  const segments = path ? parseSegments(path) : [];
2984
3165
  const segment = segments[index];
2985
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
3166
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
2986
3167
  if (!path || !owner || !segment || !point) {
2987
3168
  return;
2988
3169
  }
@@ -2990,7 +3171,7 @@ var LinkSegmentSession = class {
2990
3171
  const guide = document.createElementNS(SVG_NAMESPACE2, "line");
2991
3172
  guide.setAttribute("stroke", GUIDE_COLOR);
2992
3173
  guide.setAttribute("stroke-dasharray", "4 4");
2993
- guide.setAttribute("stroke-width", String(1 / chunk34PK7HEU_cjs.pxPerUnit(this.#svg)));
3174
+ guide.setAttribute("stroke-width", String(1 / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg)));
2994
3175
  guide.setAttribute("visibility", "hidden");
2995
3176
  overlay.appendChild(guide);
2996
3177
  handle.setPointerCapture?.(event.pointerId);
@@ -3025,7 +3206,7 @@ var LinkSegmentSession = class {
3025
3206
  return;
3026
3207
  }
3027
3208
  drag.moved = true;
3028
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
3209
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
3029
3210
  if (!point) {
3030
3211
  return;
3031
3212
  }
@@ -3051,8 +3232,8 @@ var LinkSegmentSession = class {
3051
3232
  doubleClick = (event) => {
3052
3233
  const handle = event.target?.closest("[data-sf-link-segment]");
3053
3234
  const linkId = handle?.closest("[data-sf-selection-overlay]")?.getAttribute("data-sf-selection-overlay");
3054
- const path = linkId ? chunk34PK7HEU_cjs.findOwnerNode(this.#svg, linkId, chunk34PK7HEU_cjs.isPrimary) : null;
3055
- const owner = path && chunk34PK7HEU_cjs.resolveOwner(path);
3235
+ const path = linkId ? chunkHFOGKSNU_cjs.findOwnerNode(this.#svg, linkId, chunkHFOGKSNU_cjs.isPrimary) : null;
3236
+ const owner = path && chunkHFOGKSNU_cjs.resolveOwner(path);
3056
3237
  if (!handle || !owner) {
3057
3238
  return;
3058
3239
  }
@@ -3075,7 +3256,7 @@ var LinkSegmentSession = class {
3075
3256
  if (isSnapDisabled(this.#svg)) {
3076
3257
  return { value: raw, snapped: null };
3077
3258
  }
3078
- const threshold = SNAP_PX / chunk34PK7HEU_cjs.pxPerUnit(this.#svg);
3259
+ const threshold = SNAP_PX / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg);
3079
3260
  let best = null;
3080
3261
  for (const candidate of [drag.base, ...drag.candidates]) {
3081
3262
  const closer = best === null || Math.abs(candidate - raw) < Math.abs(best - raw);
@@ -3088,7 +3269,7 @@ var LinkSegmentSession = class {
3088
3269
  #preview(drag, snapped) {
3089
3270
  const next = movedSegments(drag, drag.value);
3090
3271
  const strokeWidth = Number(drag.path.getAttribute("stroke-width")) || 2;
3091
- const data = chunkYM3XFBI4_cjs.roundedOrthogonalPathData(pathSegments(next), Math.max(16, strokeWidth * 4));
3272
+ const data = chunkCXL254BT_cjs.roundedOrthogonalPathData(pathSegments(next), Math.max(16, strokeWidth * 4));
3092
3273
  drag.path.setAttribute("d", data);
3093
3274
  drag.overlay.querySelector("path")?.setAttribute("d", data);
3094
3275
  const segment = next[drag.index];
@@ -3262,8 +3443,8 @@ function nearestCandidates(bounds, candidates, limit = 50) {
3262
3443
 
3263
3444
  // src/runtime/interaction/snapping/isometricDiagonal.ts
3264
3445
  var AXES2 = [
3265
- { x: chunkYM3XFBI4_cjs.AXIS_COS, y: chunkYM3XFBI4_cjs.AXIS_SIN },
3266
- { x: -chunkYM3XFBI4_cjs.AXIS_COS, y: chunkYM3XFBI4_cjs.AXIS_SIN }
3446
+ { x: chunkCXL254BT_cjs.AXIS_COS, y: chunkCXL254BT_cjs.AXIS_SIN },
3447
+ { x: -chunkCXL254BT_cjs.AXIS_COS, y: chunkCXL254BT_cjs.AXIS_SIN }
3267
3448
  ];
3268
3449
  var GUIDE_OVERHANG = 40;
3269
3450
  function snapIsometricDiagonal(apex, rawDx, rawDy, candidates, threshold) {
@@ -3332,13 +3513,13 @@ function isometricApexOf(svg, drag, declared = false) {
3332
3513
  if (lead.owner.role !== "isometric") {
3333
3514
  return null;
3334
3515
  }
3335
- const primary = chunk34PK7HEU_cjs.findOwnerNode(svg, lead.owner.id, chunk34PK7HEU_cjs.isPrimary);
3336
- const geometry = primary && chunk34PK7HEU_cjs.isometricGeometryOf(primary);
3516
+ const primary = chunkHFOGKSNU_cjs.findOwnerNode(svg, lead.owner.id, chunkHFOGKSNU_cjs.isPrimary);
3517
+ const geometry = primary && chunkHFOGKSNU_cjs.isometricGeometryOf(primary);
3337
3518
  if (!geometry) {
3338
3519
  return null;
3339
3520
  }
3340
3521
  const frame = declared && geometry.bounds ? geometry.bounds : lead.draggedBounds;
3341
- return { x: frame.x + geometry.depth * chunkYM3XFBI4_cjs.AXIS_COS, y: frame.y };
3522
+ return { x: frame.x + geometry.depth * chunkCXL254BT_cjs.AXIS_COS, y: frame.y };
3342
3523
  }
3343
3524
  function snapIsometricGrid(svg, drag, rawDx, rawDy) {
3344
3525
  const step = readIsometricSnapStep(svg);
@@ -3355,8 +3536,8 @@ function snapIsometricMove(svg, drag, rawDx, rawDy) {
3355
3536
  return null;
3356
3537
  }
3357
3538
  const excludedIds = new Set(drag.canvasObjects.map((canvasObject) => canvasObject.owner.id));
3358
- const candidates = chunk34PK7HEU_cjs.findIsometricApexCandidates(svg, excludedIds);
3359
- const snap = snapIsometricDiagonal(apex, rawDx, rawDy, candidates, SNAP_THRESHOLD_PX / chunk34PK7HEU_cjs.pxPerUnit(svg));
3539
+ const candidates = chunkHFOGKSNU_cjs.findIsometricApexCandidates(svg, excludedIds);
3540
+ const snap = snapIsometricDiagonal(apex, rawDx, rawDy, candidates, SNAP_THRESHOLD_PX / chunkHFOGKSNU_cjs.pxPerUnit(svg));
3360
3541
  return snap ? { dx: snap.dx, dy: snap.dy, guides: [snap.guide] } : null;
3361
3542
  }
3362
3543
  function snapMove(svg, drag, rawDx, rawDy) {
@@ -3373,9 +3554,9 @@ function snapMove(svg, drag, rawDx, rawDy) {
3373
3554
  }
3374
3555
  const leadBounds = offsetBounds(drag.canvasObjects[0].draggedBounds, rawDx, rawDy);
3375
3556
  const excludedIds = new Set(drag.canvasObjects.map((canvasObject) => canvasObject.owner.id));
3376
- const candidates = nearestCandidates(leadBounds, chunk34PK7HEU_cjs.findSnapCandidateBounds(svg, excludedIds));
3557
+ const candidates = nearestCandidates(leadBounds, chunkHFOGKSNU_cjs.findSnapCandidateBounds(svg, excludedIds));
3377
3558
  const snap = computeSnap(leadBounds, candidates, {
3378
- threshold: SNAP_THRESHOLD_PX / chunk34PK7HEU_cjs.pxPerUnit(svg),
3559
+ threshold: SNAP_THRESHOLD_PX / chunkHFOGKSNU_cjs.pxPerUnit(svg),
3379
3560
  activeX: MOVE_ACTIVE_POINTS,
3380
3561
  activeY: MOVE_ACTIVE_POINTS,
3381
3562
  guideOverhang: GUIDE_OVERHANG2
@@ -3436,7 +3617,7 @@ function isCompositeOwner(owner) {
3436
3617
  return owner !== null && owner !== void 0 && COMPOSITE_ROLES.has(owner.role);
3437
3618
  }
3438
3619
  function hasDerivedHeight(owner) {
3439
- return owner !== null && owner !== void 0 && chunk34PK7HEU_cjs.DERIVED_HEIGHT_ROLES.has(owner.role);
3620
+ return owner !== null && owner !== void 0 && chunkHFOGKSNU_cjs.DERIVED_HEIGHT_ROLES.has(owner.role);
3440
3621
  }
3441
3622
 
3442
3623
  // src/runtime/interaction/move/canvasObjectCapture.ts
@@ -3457,7 +3638,7 @@ function parentContainerBounds(svg, primary, groupIds) {
3457
3638
  if (!parentId || groupIds.has(parentId)) {
3458
3639
  return void 0;
3459
3640
  }
3460
- const container = chunk34PK7HEU_cjs.findOwnerNode(svg, parentId, chunk34PK7HEU_cjs.isPrimary);
3641
+ const container = chunkHFOGKSNU_cjs.findOwnerNode(svg, parentId, chunkHFOGKSNU_cjs.isPrimary);
3461
3642
  if (!container) {
3462
3643
  return void 0;
3463
3644
  }
@@ -3465,14 +3646,14 @@ function parentContainerBounds(svg, primary, groupIds) {
3465
3646
  return { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height };
3466
3647
  }
3467
3648
  function captureCanvasObject(svg, owner, groupIds) {
3468
- const nodes = chunk34PK7HEU_cjs.findAllOwnerNodes(svg, owner.id);
3469
- const primary = chunk34PK7HEU_cjs.findOwnerNode(svg, owner.id, chunk34PK7HEU_cjs.isPrimary);
3649
+ const nodes = chunkHFOGKSNU_cjs.findAllOwnerNodes(svg, owner.id);
3650
+ const primary = chunkHFOGKSNU_cjs.findOwnerNode(svg, owner.id, chunkHFOGKSNU_cjs.isPrimary);
3470
3651
  if (!nodes.length || !primary) {
3471
3652
  return null;
3472
3653
  }
3473
3654
  const overlays = [...svg.querySelectorAll(`[data-sf-selection-overlay="${CSS.escape(owner.id)}"]`)];
3474
3655
  const draggedBounds = primary.getBBox();
3475
- const isometricGeometry = owner.role === "isometric" ? chunk34PK7HEU_cjs.isometricGeometryOf(primary) : null;
3656
+ const isometricGeometry = owner.role === "isometric" ? chunkHFOGKSNU_cjs.isometricGeometryOf(primary) : null;
3476
3657
  const isometricSize = isometricGeometry ? { width: isometricGeometry.width, height: isometricGeometry.height, depth: isometricGeometry.depth } : void 0;
3477
3658
  return {
3478
3659
  owner,
@@ -3514,7 +3695,7 @@ function captureInternalLinks(svg, groupIds) {
3514
3695
  if (!linkId || !belongsToMoveGroup(path, groupIds)) {
3515
3696
  continue;
3516
3697
  }
3517
- const nodes = chunk34PK7HEU_cjs.findAllOwnerNodes(svg, linkId);
3698
+ const nodes = chunkHFOGKSNU_cjs.findAllOwnerNodes(svg, linkId);
3518
3699
  if (nodes.length) {
3519
3700
  links.push({ nodes, baseTransforms: nodes.map((node) => node.getAttribute("transform")) });
3520
3701
  }
@@ -3548,7 +3729,7 @@ function containedChildren(viewer, owner) {
3548
3729
  return [];
3549
3730
  }
3550
3731
  const nodes = viewer.svg.querySelectorAll(`[data-sf-parent-frame="${CSS.escape(owner.id)}"]`);
3551
- return [...nodes].map((node) => chunk34PK7HEU_cjs.resolveOwner(node)).filter((ref) => ref !== null);
3732
+ return [...nodes].map((node) => chunkHFOGKSNU_cjs.resolveOwner(node)).filter((ref) => ref !== null);
3552
3733
  }
3553
3734
  function selectedMoveGroup(viewer, owner) {
3554
3735
  const selection = viewer.getSelection();
@@ -3565,7 +3746,7 @@ function isChartInteractiveMark(target) {
3565
3746
  }
3566
3747
  function createMoveDragState(viewer, event, startUser) {
3567
3748
  const target = event.target;
3568
- const owner = chunk34PK7HEU_cjs.resolveOwner(target);
3749
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(target);
3569
3750
  if (!hasMovableGeometry(owner) || isChartInteractiveMark(target)) {
3570
3751
  return null;
3571
3752
  }
@@ -3599,7 +3780,7 @@ var MoveSession = class {
3599
3780
  this.#emitter = emitter;
3600
3781
  }
3601
3782
  pointerDown = (event) => {
3602
- if (event.button !== 0 || this.#drag || chunk34PK7HEU_cjs.isCameraGesture(event)) {
3783
+ if (event.button !== 0 || this.#drag || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
3603
3784
  return;
3604
3785
  }
3605
3786
  this.#drag = createMoveDragState(this.#viewer, event, movePointerPosition(this.#svg, event));
@@ -3617,7 +3798,7 @@ var MoveSession = class {
3617
3798
  const delta = snapMove(this.#svg, drag, rawDelta.dx, rawDelta.dy);
3618
3799
  const clamped = clampMoveDelta(drag.canvasObjects, delta.dx, delta.dy);
3619
3800
  applyMovePreview(drag, clamped.dx, clamped.dy);
3620
- chunk34PK7HEU_cjs.updateAlignmentGuides(this.#svg, delta.guides, MOVE_GUIDE_COLOR);
3801
+ chunkHFOGKSNU_cjs.updateAlignmentGuides(this.#svg, delta.guides, MOVE_GUIDE_COLOR);
3621
3802
  };
3622
3803
  pointerUp = (event) => {
3623
3804
  const drag = this.#drag;
@@ -3626,7 +3807,7 @@ var MoveSession = class {
3626
3807
  }
3627
3808
  this.#drag = null;
3628
3809
  event.target.releasePointerCapture?.(drag.pointerId);
3629
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
3810
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
3630
3811
  emitMoveCompletion(this.#svg, this.#emitter, drag, event);
3631
3812
  };
3632
3813
  cancel() {
@@ -3651,6 +3832,43 @@ function bindShapeMovement(viewer, emitter) {
3651
3832
  };
3652
3833
  }
3653
3834
 
3835
+ // src/runtime/interaction/nudgeSelection.ts
3836
+ var STEP = 1;
3837
+ var SHIFT_STEP = 10;
3838
+ var DIRECTIONS = {
3839
+ ArrowLeft: { x: -1, y: 0 },
3840
+ ArrowRight: { x: 1, y: 0 },
3841
+ ArrowUp: { x: 0, y: -1 },
3842
+ ArrowDown: { x: 0, y: 1 }
3843
+ };
3844
+ function typingInField(event) {
3845
+ return event.target instanceof Element && event.target.closest('input, textarea, [contenteditable="true"]') !== null;
3846
+ }
3847
+ function bindNudgeSelection(viewer, emitter) {
3848
+ const svg = viewer.svg;
3849
+ const onKeyDown = (e) => {
3850
+ const direction = DIRECTIONS[e.key];
3851
+ if (!direction || e.altKey || e.ctrlKey || e.metaKey || typingInField(e)) {
3852
+ return;
3853
+ }
3854
+ const owners = viewer.getSelection().filter(hasMovableGeometry);
3855
+ if (!owners.length) {
3856
+ return;
3857
+ }
3858
+ e.preventDefault();
3859
+ const step = e.shiftKey ? SHIFT_STEP : STEP;
3860
+ for (const owner of owners) {
3861
+ emitter.emit("moveChange", { owner, dx: direction.x * step, dy: direction.y * step });
3862
+ }
3863
+ };
3864
+ svg.addEventListener("keydown", onKeyDown);
3865
+ return {
3866
+ destroy() {
3867
+ svg.removeEventListener("keydown", onKeyDown);
3868
+ }
3869
+ };
3870
+ }
3871
+
3654
3872
  // src/runtime/interaction/pathDraw/geometry.ts
3655
3873
  var MIN_POINTS_TO_CLOSE = 3;
3656
3874
  var MIN_POINTS_OPEN = 2;
@@ -3735,9 +3953,9 @@ var START_POINT_RADIUS_PX = 6;
3735
3953
  var POINT_STROKE_WIDTH_PX = 1.5;
3736
3954
  function createPathDrawPreview(svg) {
3737
3955
  const document2 = svg.ownerDocument;
3738
- const group = document2.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, "g");
3956
+ const group = document2.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, "g");
3739
3957
  group.setAttribute("pointer-events", "none");
3740
- const line = document2.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, "path");
3958
+ const line = document2.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, "path");
3741
3959
  line.setAttribute("fill", "none");
3742
3960
  line.setAttribute("stroke", PREVIEW_COLOR);
3743
3961
  line.setAttribute("stroke-linecap", "round");
@@ -3747,8 +3965,8 @@ function createPathDrawPreview(svg) {
3747
3965
  }
3748
3966
  function pointMarker(svg, point, highlighted) {
3749
3967
  const document2 = svg.ownerDocument;
3750
- const unit = 1 / chunk34PK7HEU_cjs.pxPerUnit(svg);
3751
- const circle = document2.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, "circle");
3968
+ const unit = 1 / chunkHFOGKSNU_cjs.pxPerUnit(svg);
3969
+ const circle = document2.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, "circle");
3752
3970
  circle.setAttribute("cx", String(point.x));
3753
3971
  circle.setAttribute("cy", String(point.y));
3754
3972
  circle.setAttribute("r", String((highlighted ? START_POINT_RADIUS_PX : POINT_RADIUS_PX) * unit));
@@ -3762,11 +3980,11 @@ function updatePathDrawPreview(svg, state) {
3762
3980
  if (!previewLine || !previewGroup) {
3763
3981
  return;
3764
3982
  }
3765
- const unit = 1 / chunk34PK7HEU_cjs.pxPerUnit(svg);
3983
+ const unit = 1 / chunkHFOGKSNU_cjs.pxPerUnit(svg);
3766
3984
  previewLine.setAttribute("stroke-width", String(LINE_WIDTH_PX * unit));
3767
3985
  previewLine.setAttribute("stroke-dasharray", `${DASH_PX * unit} ${GAP_PX * unit}`);
3768
3986
  const live = state.cursor ? [...state.points, state.cursor] : state.points;
3769
- previewLine.setAttribute("d", chunkYM3XFBI4_cjs.freeformPathData({ points: live, tension: state.tension, closed: false }));
3987
+ previewLine.setAttribute("d", chunkCXL254BT_cjs.freeformPathData({ points: live, tension: state.tension, closed: false }));
3770
3988
  while (previewGroup.childNodes.length > 1) {
3771
3989
  previewGroup.lastChild?.remove();
3772
3990
  }
@@ -3826,12 +4044,12 @@ var PathDrawSession = class {
3826
4044
  }
3827
4045
  }
3828
4046
  pointerDown = (event) => {
3829
- if (!this.#state.active || event.button !== 0 || chunk34PK7HEU_cjs.isCameraGesture(event)) {
4047
+ if (!this.#state.active || event.button !== 0 || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
3830
4048
  return;
3831
4049
  }
3832
4050
  event.stopPropagation();
3833
4051
  event.preventDefault();
3834
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
4052
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
3835
4053
  if (!point) {
3836
4054
  return;
3837
4055
  }
@@ -3850,14 +4068,14 @@ var PathDrawSession = class {
3850
4068
  this.#state.cursor = resolved.point;
3851
4069
  this.#state.willClose = false;
3852
4070
  updatePathDrawPreview(this.#svg, this.#state);
3853
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
4071
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
3854
4072
  };
3855
4073
  pointerMove = (event) => {
3856
4074
  if (!this.#state.active) {
3857
4075
  return;
3858
4076
  }
3859
4077
  event.stopPropagation();
3860
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
4078
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
3861
4079
  if (!point) {
3862
4080
  return;
3863
4081
  }
@@ -3866,9 +4084,9 @@ var PathDrawSession = class {
3866
4084
  this.#state.willClose = resolved.willClose;
3867
4085
  updatePathDrawPreview(this.#svg, this.#state);
3868
4086
  if (resolved.guide) {
3869
- chunk34PK7HEU_cjs.updateAlignmentGuides(this.#svg, [resolved.guide], GUIDE_COLOR2);
4087
+ chunkHFOGKSNU_cjs.updateAlignmentGuides(this.#svg, [resolved.guide], GUIDE_COLOR2);
3870
4088
  } else {
3871
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
4089
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
3872
4090
  }
3873
4091
  };
3874
4092
  pointerUp = (event) => {
@@ -3903,10 +4121,10 @@ var PathDrawSession = class {
3903
4121
  } else if (event.key === "Backspace" && this.#state.points.length > 0) {
3904
4122
  event.preventDefault();
3905
4123
  this.#state.points = this.#state.points.slice(0, -1);
3906
- const closeSnapUnits = CLOSE_SNAP_PX / chunk34PK7HEU_cjs.pxPerUnit(this.#svg);
4124
+ const closeSnapUnits = CLOSE_SNAP_PX / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg);
3907
4125
  this.#state.willClose = this.#state.cursor ? isCloseToStart(this.#state.points, this.#state.cursor, closeSnapUnits) : false;
3908
4126
  updatePathDrawPreview(this.#svg, this.#state);
3909
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
4127
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
3910
4128
  }
3911
4129
  };
3912
4130
  keyUp = (event) => {
@@ -3915,7 +4133,7 @@ var PathDrawSession = class {
3915
4133
  }
3916
4134
  };
3917
4135
  #resolvePoint(raw) {
3918
- const closeSnapUnits = CLOSE_SNAP_PX / chunk34PK7HEU_cjs.pxPerUnit(this.#svg);
4136
+ const closeSnapUnits = CLOSE_SNAP_PX / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg);
3919
4137
  if (isCloseToStart(this.#state.points, raw, closeSnapUnits)) {
3920
4138
  return { point: this.#state.points[0], willClose: true, guide: null };
3921
4139
  }
@@ -3925,7 +4143,7 @@ var PathDrawSession = class {
3925
4143
  return { point: raw, willClose: false, guide: null };
3926
4144
  }
3927
4145
  const angleSnapped = snapTo45Degrees(last, raw);
3928
- const guideSnapUnits = GUIDE_SNAP_PX / chunk34PK7HEU_cjs.pxPerUnit(this.#svg);
4146
+ const guideSnapUnits = GUIDE_SNAP_PX / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg);
3929
4147
  const { point, guide } = snapToSessionGuides(last, angleSnapped, points.slice(0, -1), raw, guideSnapUnits);
3930
4148
  return { point, willClose: false, guide };
3931
4149
  }
@@ -3939,7 +4157,7 @@ var PathDrawSession = class {
3939
4157
  }
3940
4158
  #reset(callExit) {
3941
4159
  this.#state.previewGroup?.remove();
3942
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
4160
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
3943
4161
  const exit = this.#state.onExit;
3944
4162
  this.#state = createIdlePathDrawState();
3945
4163
  this.#shiftHeld = false;
@@ -3982,7 +4200,7 @@ function applyPathReshapePreview(drag, point) {
3982
4200
  const points = drag.points.map(
3983
4201
  (existing, index) => index === drag.pointIndex ? [point.x, point.y] : existing
3984
4202
  );
3985
- const d = chunkYM3XFBI4_cjs.freeformPathData({
4203
+ const d = chunkCXL254BT_cjs.freeformPathData({
3986
4204
  points: points.map(([x, y]) => ({ x, y })),
3987
4205
  tension: drag.tension,
3988
4206
  closed: drag.closed
@@ -3990,22 +4208,22 @@ function applyPathReshapePreview(drag, point) {
3990
4208
  drag.pathNode.setAttribute("d", d);
3991
4209
  drag.handle.setAttribute("cx", String(point.x));
3992
4210
  drag.handle.setAttribute("cy", String(point.y));
3993
- drag.overlay?.querySelector(`[${chunk34PK7HEU_cjs.PATH_HALO_ATTR}]`)?.setAttribute("d", d);
4211
+ drag.overlay?.querySelector(`[${chunkHFOGKSNU_cjs.PATH_HALO_ATTR}]`)?.setAttribute("d", d);
3994
4212
  return points;
3995
4213
  }
3996
4214
 
3997
4215
  // src/runtime/interaction/pathReshape/target.ts
3998
4216
  function resolvePathReshapeTarget(svg, event) {
3999
- const handle = event.target?.closest?.(`[${chunkYM3XFBI4_cjs.PATH_POINT_INDEX_ATTR}]`) ?? null;
4000
- const indexAttr = handle?.getAttribute(chunkYM3XFBI4_cjs.PATH_POINT_INDEX_ATTR) ?? null;
4217
+ const handle = event.target?.closest?.(`[${chunkCXL254BT_cjs.PATH_POINT_INDEX_ATTR}]`) ?? null;
4218
+ const indexAttr = handle?.getAttribute(chunkCXL254BT_cjs.PATH_POINT_INDEX_ATTR) ?? null;
4001
4219
  const pointIndex = indexAttr !== null ? Number(indexAttr) : Number.NaN;
4002
4220
  const ownerId = handle?.closest("[data-sf-selection-overlay]")?.getAttribute("data-sf-selection-overlay");
4003
4221
  if (!handle || !Number.isInteger(pointIndex) || !ownerId) {
4004
4222
  return null;
4005
4223
  }
4006
- const pathNode = chunk34PK7HEU_cjs.findOwnerNode(svg, ownerId, chunk34PK7HEU_cjs.isPrimary);
4007
- const owner = pathNode && chunk34PK7HEU_cjs.resolveOwner(pathNode);
4008
- const geometry = pathNode && chunk34PK7HEU_cjs.pathGeometryOf(pathNode);
4224
+ const pathNode = chunkHFOGKSNU_cjs.findOwnerNode(svg, ownerId, chunkHFOGKSNU_cjs.isPrimary);
4225
+ const owner = pathNode && chunkHFOGKSNU_cjs.resolveOwner(pathNode);
4226
+ const geometry = pathNode && chunkHFOGKSNU_cjs.pathGeometryOf(pathNode);
4009
4227
  if (!pathNode || !owner || !geometry || pointIndex < 0 || pointIndex >= geometry.points.length) {
4010
4228
  return null;
4011
4229
  }
@@ -4048,7 +4266,7 @@ var PathReshapeSession = class {
4048
4266
  this.#emitter = emitter;
4049
4267
  }
4050
4268
  pointerDown = (event) => {
4051
- if (event.button !== 0 || this.#drag || chunk34PK7HEU_cjs.isCameraGesture(event)) {
4269
+ if (event.button !== 0 || this.#drag || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
4052
4270
  return;
4053
4271
  }
4054
4272
  this.#drag = createPathReshapeDragState(this.#svg, event);
@@ -4059,7 +4277,7 @@ var PathReshapeSession = class {
4059
4277
  return;
4060
4278
  }
4061
4279
  drag.moved = true;
4062
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
4280
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
4063
4281
  if (point) {
4064
4282
  applyPathReshapePreview(drag, point);
4065
4283
  }
@@ -4074,7 +4292,7 @@ var PathReshapeSession = class {
4074
4292
  if (!drag.moved) {
4075
4293
  return;
4076
4294
  }
4077
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event) ?? {
4295
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event) ?? {
4078
4296
  x: drag.points[drag.pointIndex][0],
4079
4297
  y: drag.points[drag.pointIndex][1]
4080
4298
  };
@@ -4115,7 +4333,7 @@ function updatePieLabelDragPreview(drag, dx, dy) {
4115
4333
  }
4116
4334
  const from = { x: drag.tickStartX, y: drag.tickStartY };
4117
4335
  const to = { x: drag.restX + dx, y: drag.restY + dy };
4118
- const clipped = chunkYM3XFBI4_cjs.clipSegmentToRect(from, to, drag.halfWidth, drag.halfHeight);
4336
+ const clipped = chunkCXL254BT_cjs.clipSegmentToRect(from, to, drag.halfWidth, drag.halfHeight);
4119
4337
  drag.tickElement.setAttribute("d", `M ${from.x} ${from.y} L ${clipped.x} ${clipped.y}`);
4120
4338
  drag.tickElement.setAttribute("stroke", PREVIEW_TICK_COLOR);
4121
4339
  drag.tickElement.setAttribute("stroke-width", PREVIEW_TICK_STROKE_WIDTH);
@@ -4141,7 +4359,7 @@ function restoreAttribute(element2, name, value) {
4141
4359
 
4142
4360
  // src/runtime/interaction/pieGeometry.ts
4143
4361
  function readPieGeometry(svg, ownerId) {
4144
- const raw = chunk34PK7HEU_cjs.findOwnerNode(svg, ownerId, chunk34PK7HEU_cjs.isPrimary)?.getAttribute("data-sf-pie-geometry");
4362
+ const raw = chunkHFOGKSNU_cjs.findOwnerNode(svg, ownerId, chunkHFOGKSNU_cjs.isPrimary)?.getAttribute("data-sf-pie-geometry");
4145
4363
  if (!raw) {
4146
4364
  return null;
4147
4365
  }
@@ -4160,7 +4378,7 @@ function findLabelMark2(event) {
4160
4378
  return event.target?.closest?.(selector);
4161
4379
  }
4162
4380
  function isLabelPointer2(event) {
4163
- return event.button === 0 && !chunk34PK7HEU_cjs.isCameraGesture(event);
4381
+ return event.button === 0 && !chunkHFOGKSNU_cjs.isCameraGesture(event);
4164
4382
  }
4165
4383
  function findLabelSiblings(svg, ownerId, seriesId, mark) {
4166
4384
  const selector = `[data-sf-id="${CSS.escape(ownerId)}"][data-sf-series="${CSS.escape(seriesId)}"][data-sf-mark="${mark}"]`;
@@ -4192,7 +4410,7 @@ function resolvePieLabelDrag(svg, event) {
4192
4410
  if (!clicked) {
4193
4411
  return null;
4194
4412
  }
4195
- const owner = chunk34PK7HEU_cjs.resolveOwner(clicked);
4413
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(clicked);
4196
4414
  if (owner?.role !== "chart") {
4197
4415
  return null;
4198
4416
  }
@@ -4211,7 +4429,7 @@ function resolvePieLabelDrag(svg, event) {
4211
4429
  const wedgeRadius = clicked.getAttribute("data-sf-pie-wedge-radius");
4212
4430
  const explicitRadius = wedgeRadius === null ? Number.NaN : Number(wedgeRadius);
4213
4431
  const outerRadius = Number.isFinite(explicitRadius) ? explicitRadius : geometry.outerRadius;
4214
- const start = chunk34PK7HEU_cjs.pointerUserPoint(svg, event);
4432
+ const start = chunkHFOGKSNU_cjs.pointerUserPoint(svg, event);
4215
4433
  if (!start) {
4216
4434
  return null;
4217
4435
  }
@@ -4233,13 +4451,13 @@ function resolvePieLabelDrag(svg, event) {
4233
4451
  outerRadius,
4234
4452
  anchorX: geometry.centerX + outerRadius * Math.cos(midAngle),
4235
4453
  anchorY: geometry.centerY + outerRadius * Math.sin(midAngle),
4236
- tickStartX: geometry.centerX + (outerRadius + chunkYM3XFBI4_cjs.LEADER_INSET) * Math.cos(midAngle),
4237
- tickStartY: geometry.centerY + (outerRadius + chunkYM3XFBI4_cjs.LEADER_INSET) * Math.sin(midAngle),
4454
+ tickStartX: geometry.centerX + (outerRadius + chunkCXL254BT_cjs.LEADER_INSET) * Math.cos(midAngle),
4455
+ tickStartY: geometry.centerY + (outerRadius + chunkCXL254BT_cjs.LEADER_INSET) * Math.sin(midAngle),
4238
4456
  restX,
4239
4457
  restY,
4240
4458
  startX: start.x,
4241
4459
  startY: start.y,
4242
- halfWidth: chunkYM3XFBI4_cjs.LABEL_WIDTH / 2,
4460
+ halfWidth: chunkCXL254BT_cjs.LABEL_WIDTH / 2,
4243
4461
  halfHeight: fontSize * 1.2,
4244
4462
  moved: false,
4245
4463
  lastDx: 0,
@@ -4275,7 +4493,7 @@ var PieLabelDragSession = class {
4275
4493
  if (!this.#drag || event.pointerId !== this.#drag.pointerId) {
4276
4494
  return;
4277
4495
  }
4278
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
4496
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
4279
4497
  if (!point) {
4280
4498
  return;
4281
4499
  }
@@ -4307,8 +4525,8 @@ var PieLabelDragSession = class {
4307
4525
  if (!drag.moved) {
4308
4526
  return;
4309
4527
  }
4310
- const pathX = chunkYM3XFBI4_cjs.seriesLabelOffsetXProp(drag.seriesId);
4311
- const pathY = chunkYM3XFBI4_cjs.seriesLabelOffsetYProp(drag.seriesId);
4528
+ const pathX = chunkCXL254BT_cjs.seriesLabelOffsetXProp(drag.seriesId);
4529
+ const pathY = chunkCXL254BT_cjs.seriesLabelOffsetYProp(drag.seriesId);
4312
4530
  if (!pathX || !pathY) {
4313
4531
  return;
4314
4532
  }
@@ -4370,7 +4588,7 @@ function siblingNodes(svg, owner, path) {
4370
4588
  });
4371
4589
  }
4372
4590
  function resolvePropertyDrag(svg, event, rules) {
4373
- if (event.button !== 0 || chunk34PK7HEU_cjs.isCameraGesture(event)) {
4591
+ if (event.button !== 0 || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
4374
4592
  return null;
4375
4593
  }
4376
4594
  const node = event.target?.closest?.('[data-sf-prop-kind="value"]');
@@ -4378,11 +4596,11 @@ function resolvePropertyDrag(svg, event, rules) {
4378
4596
  return null;
4379
4597
  }
4380
4598
  const path = node.getAttribute("data-sf-prop");
4381
- const owner = chunk34PK7HEU_cjs.resolveOwner(node);
4599
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(node);
4382
4600
  if (!path || owner?.role !== "chart" || !isEditablePath(path, rules)) {
4383
4601
  return null;
4384
4602
  }
4385
- const scale = parseValueScale(chunk34PK7HEU_cjs.findOwnerNode(svg, owner.id, chunk34PK7HEU_cjs.isPrimary));
4603
+ const scale = parseValueScale(chunkHFOGKSNU_cjs.findOwnerNode(svg, owner.id, chunkHFOGKSNU_cjs.isPrimary));
4386
4604
  if (!scale) {
4387
4605
  return null;
4388
4606
  }
@@ -4651,7 +4869,7 @@ function resolvePropertyTarget(event, rules) {
4651
4869
  return null;
4652
4870
  }
4653
4871
  const path = hit.getAttribute("data-sf-prop");
4654
- const owner = chunk34PK7HEU_cjs.resolveOwner(hit);
4872
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(hit);
4655
4873
  if (!path || !owner || !isEditablePath(path, rules)) {
4656
4874
  return null;
4657
4875
  }
@@ -4690,7 +4908,7 @@ var PropertyEditingSession = class {
4690
4908
  begin(target) {
4691
4909
  this.cancel();
4692
4910
  const { node } = target;
4693
- const rect = chunk34PK7HEU_cjs.screenRectOf(node);
4911
+ const rect = chunkHFOGKSNU_cjs.screenRectOf(node);
4694
4912
  const fontSize = Number.parseFloat(node.getAttribute("font-size") || "12");
4695
4913
  const originalText = node.textContent ?? "";
4696
4914
  const anchor = node.getAttribute("text-anchor");
@@ -4780,9 +4998,9 @@ function crossedDuplicateDragThreshold(drag, event) {
4780
4998
  var PREVIEW_STROKE_PX = 2;
4781
4999
  var NEW_LINK_PATH_TYPE = "orthogonal";
4782
5000
  function createDuplicatePreviewPath(svg) {
4783
- const path = svg.ownerDocument.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, "path");
5001
+ const path = svg.ownerDocument.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, "path");
4784
5002
  path.setAttribute("fill", "none");
4785
- path.setAttribute("stroke-width", String(PREVIEW_STROKE_PX / chunk34PK7HEU_cjs.pxPerUnit(svg)));
5003
+ path.setAttribute("stroke-width", String(PREVIEW_STROKE_PX / chunkHFOGKSNU_cjs.pxPerUnit(svg)));
4786
5004
  path.style.pointerEvents = "none";
4787
5005
  return path;
4788
5006
  }
@@ -4801,7 +5019,7 @@ function previewLink3(fromSide, toSide) {
4801
5019
  }
4802
5020
  function updateDuplicatePreview(drag, toPoint, toSide) {
4803
5021
  const link = previewLink3(drag.direction, toSide);
4804
- const { points, segments } = chunkYM3XFBI4_cjs.calculateLinkRoute(link, drag.fixedPoint, toPoint, NEW_LINK_PATH_TYPE);
5022
+ const { points, segments } = chunkCXL254BT_cjs.calculateLinkRoute(link, drag.fixedPoint, toPoint, NEW_LINK_PATH_TYPE);
4805
5023
  drag.previewPath.setAttribute("d", previewPathData(points, segments, NEW_LINK_PATH_TYPE, 2));
4806
5024
  }
4807
5025
 
@@ -4812,7 +5030,7 @@ function duplicateCandidates(svg, sourceId) {
4812
5030
  if (element2.getAttribute("data-sf-role") === "link") {
4813
5031
  continue;
4814
5032
  }
4815
- const owner = chunk34PK7HEU_cjs.resolveOwner(element2);
5033
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(element2);
4816
5034
  if (owner && owner.id !== sourceId) {
4817
5035
  candidates.push({ owner, bounds: element2.getBBox() });
4818
5036
  }
@@ -4826,8 +5044,8 @@ function createQuickDuplicateDragState(svg, event, previewPath) {
4826
5044
  if (!bubble || !direction || direction.startsWith("iso-") || !sourceId) {
4827
5045
  return null;
4828
5046
  }
4829
- const primary = chunk34PK7HEU_cjs.findOwnerNode(svg, sourceId, chunk34PK7HEU_cjs.isPrimary);
4830
- const sourceOwner = primary && chunk34PK7HEU_cjs.resolveOwner(primary);
5047
+ const primary = chunkHFOGKSNU_cjs.findOwnerNode(svg, sourceId, chunkHFOGKSNU_cjs.isPrimary);
5048
+ const sourceOwner = primary && chunkHFOGKSNU_cjs.resolveOwner(primary);
4831
5049
  if (!primary || !sourceOwner) {
4832
5050
  return null;
4833
5051
  }
@@ -4835,7 +5053,7 @@ function createQuickDuplicateDragState(svg, event, previewPath) {
4835
5053
  return {
4836
5054
  sourceOwner,
4837
5055
  direction,
4838
- fixedPoint: chunkYM3XFBI4_cjs.pointAtPort(primary.getBBox(), { side: direction, offset: 0.5 }),
5056
+ fixedPoint: chunkCXL254BT_cjs.pointAtPort(primary.getBBox(), { side: direction, offset: 0.5 }),
4839
5057
  previewPath,
4840
5058
  ghost: new LinkGhost(svg, previewPath),
4841
5059
  candidates: duplicateCandidates(svg, sourceId),
@@ -4863,7 +5081,7 @@ var QuickDuplicateSession = class {
4863
5081
  this.#emitter = emitter;
4864
5082
  }
4865
5083
  pointerDown = (event) => {
4866
- if (event.button !== 0 || this.#drag || chunk34PK7HEU_cjs.isCameraGesture(event)) {
5084
+ if (event.button !== 0 || this.#drag || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
4867
5085
  return;
4868
5086
  }
4869
5087
  this.#drag = createQuickDuplicateDragState(this.#svg, event, createDuplicatePreviewPath(this.#svg));
@@ -4877,7 +5095,7 @@ var QuickDuplicateSession = class {
4877
5095
  return;
4878
5096
  }
4879
5097
  this.beginPreview(drag);
4880
- const target = resolveDuplicateTarget(drag, duplicatePointerPosition(this.#svg, event), 1 / chunk34PK7HEU_cjs.pxPerUnit(this.#svg));
5098
+ const target = resolveDuplicateTarget(drag, duplicatePointerPosition(this.#svg, event), 1 / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg));
4881
5099
  updateDuplicatePreview(drag, target.point, target.side);
4882
5100
  drag.ghost.show(target.hit !== null, target.bounds);
4883
5101
  };
@@ -4935,14 +5153,14 @@ function seriesShapes(svg, ownerId, series) {
4935
5153
  return [...svg.querySelectorAll(selector)];
4936
5154
  }
4937
5155
  function updateRadarVertexDragPreview(svg, drag, value) {
4938
- const point = chunkYM3XFBI4_cjs.radarVertexPoint(drag.frame, drag.index, value);
5156
+ const point = chunkCXL254BT_cjs.radarVertexPoint(drag.frame, drag.index, value);
4939
5157
  drag.element.setAttribute("cx", String(point.x));
4940
5158
  drag.element.setAttribute("cy", String(point.y));
4941
5159
  const points = seriesVertices(svg, drag.owner.id, drag.series).map((vertex) => ({
4942
5160
  x: Number(vertex.getAttribute("cx")),
4943
5161
  y: Number(vertex.getAttribute("cy"))
4944
5162
  }));
4945
- const path = chunkYM3XFBI4_cjs.radarSeriesPath(points, drag.frame.curved);
5163
+ const path = chunkCXL254BT_cjs.radarSeriesPath(points, drag.frame.curved, drag.frame.tension);
4946
5164
  for (const shape of seriesShapes(svg, drag.owner.id, drag.series)) {
4947
5165
  shape.setAttribute("d", path);
4948
5166
  }
@@ -4978,17 +5196,26 @@ function parseRadarFrame(node) {
4978
5196
  if (!raw) {
4979
5197
  return null;
4980
5198
  }
4981
- const [centerX, centerY, radius, min, max, count, curved] = raw.split(",").map(Number);
5199
+ const [centerX, centerY, radius, min, max, count, curved, tension] = raw.split(",").map(Number);
4982
5200
  if (![centerX, centerY, radius, min, max, count].every(Number.isFinite) || count < 3 || max === min) {
4983
5201
  return null;
4984
5202
  }
4985
- return { centerX, centerY, radius, min, max, count, curved: curved === 1 };
5203
+ return {
5204
+ centerX,
5205
+ centerY,
5206
+ radius,
5207
+ min,
5208
+ max,
5209
+ count,
5210
+ curved: curved === 1,
5211
+ tension: Number.isFinite(tension) ? tension : void 0
5212
+ };
4986
5213
  }
4987
5214
  function findVertex(event) {
4988
5215
  return event.target?.closest?.('[data-sf-mark="radar-vertex"]');
4989
5216
  }
4990
5217
  function isVertexPointer(event) {
4991
- return event.button === 0 && !chunk34PK7HEU_cjs.isCameraGesture(event);
5218
+ return event.button === 0 && !chunkHFOGKSNU_cjs.isCameraGesture(event);
4992
5219
  }
4993
5220
  function resolveRadarVertexDrag(svg, event) {
4994
5221
  if (!isVertexPointer(event)) {
@@ -4998,7 +5225,7 @@ function resolveRadarVertexDrag(svg, event) {
4998
5225
  if (!element2) {
4999
5226
  return null;
5000
5227
  }
5001
- const owner = chunk34PK7HEU_cjs.resolveOwner(element2);
5228
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(element2);
5002
5229
  if (owner?.role !== "chart") {
5003
5230
  return null;
5004
5231
  }
@@ -5007,7 +5234,7 @@ function resolveRadarVertexDrag(svg, event) {
5007
5234
  if (!series || !Number.isInteger(index) || index < 0) {
5008
5235
  return null;
5009
5236
  }
5010
- const frame = parseRadarFrame(chunk34PK7HEU_cjs.findOwnerNode(svg, owner.id, chunk34PK7HEU_cjs.isPrimary));
5237
+ const frame = parseRadarFrame(chunkHFOGKSNU_cjs.findOwnerNode(svg, owner.id, chunkHFOGKSNU_cjs.isPrimary));
5011
5238
  if (!frame || index >= frame.count) {
5012
5239
  return null;
5013
5240
  }
@@ -5017,11 +5244,11 @@ function resolveRadarVertexDrag(svg, event) {
5017
5244
 
5018
5245
  // src/runtime/interaction/radarVertexDrag/session.ts
5019
5246
  function valueFrom(svg, event, drag) {
5020
- const point = chunk34PK7HEU_cjs.pointerUserPoint(svg, event);
5247
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(svg, event);
5021
5248
  if (!point) {
5022
5249
  return null;
5023
5250
  }
5024
- return chunkYM3XFBI4_cjs.radarValueAtPoint(drag.frame, drag.index, point.x, point.y);
5251
+ return chunkCXL254BT_cjs.radarValueAtPoint(drag.frame, drag.index, point.x, point.y);
5025
5252
  }
5026
5253
  var RadarVertexDragSession = class {
5027
5254
  #svg;
@@ -5053,7 +5280,7 @@ var RadarVertexDragSession = class {
5053
5280
  if (!this.#readout) {
5054
5281
  this.#readout = createValueReadout(this.#svg);
5055
5282
  }
5056
- const vertex = chunkYM3XFBI4_cjs.radarVertexPoint(this.#drag.frame, this.#drag.index, value);
5283
+ const vertex = chunkCXL254BT_cjs.radarVertexPoint(this.#drag.frame, this.#drag.index, value);
5057
5284
  positionRadarReadout(this.#readout, vertex, this.#drag.frame.centerY, value);
5058
5285
  }
5059
5286
  cancel() {
@@ -5144,7 +5371,7 @@ function captureTextFit(text) {
5144
5371
  fontSize,
5145
5372
  lineHeight,
5146
5373
  padding: Math.max(8, text.strokeWidth * 2),
5147
- longestWord: Math.max(0, ...words.map((word) => chunkYM3XFBI4_cjs.estimateTextWidth(word, fontSize, bold)))
5374
+ longestWord: Math.max(0, ...words.map((word) => chunkCXL254BT_cjs.estimateTextWidth(word, fontSize, bold)))
5148
5375
  };
5149
5376
  }
5150
5377
  var COMMIT_PRECISION = 10;
@@ -5155,7 +5382,7 @@ function minWidthForText(fit) {
5155
5382
  return roundUpForCommit(fit.longestWord + fit.padding * 2);
5156
5383
  }
5157
5384
  function minHeightForText(fit, width) {
5158
- const lines = chunkYM3XFBI4_cjs.wrapText(fit.rawText, Math.max(0, width - fit.padding * 2), fit.fontSize);
5385
+ const lines = chunkCXL254BT_cjs.wrapText(fit.rawText, Math.max(0, width - fit.padding * 2), fit.fontSize);
5159
5386
  return roundUpForCommit(lines.length * fit.fontSize * fit.lineHeight + fit.padding * 2);
5160
5387
  }
5161
5388
 
@@ -5265,7 +5492,7 @@ function applyRectBounds(rect, kind, bounds) {
5265
5492
  rect.setAttribute("width", String(bounds.width));
5266
5493
  rect.setAttribute("height", String(bounds.height));
5267
5494
  if (kind === "pill") {
5268
- rect.setAttribute("rx", String(chunkYM3XFBI4_cjs.pillCornerRadius(bounds.width, bounds.height)));
5495
+ rect.setAttribute("rx", String(chunkCXL254BT_cjs.pillCornerRadius(bounds.width, bounds.height)));
5269
5496
  }
5270
5497
  }
5271
5498
  function applyEllipseBounds(ellipse, bounds) {
@@ -5275,7 +5502,7 @@ function applyEllipseBounds(ellipse, bounds) {
5275
5502
  ellipse.setAttribute("ry", String(bounds.height / 2));
5276
5503
  }
5277
5504
  function applySymbolBounds(path, bounds) {
5278
- const raw = path.getAttribute(chunkYM3XFBI4_cjs.SYMBOL_POINTS_ATTR);
5505
+ const raw = path.getAttribute(chunkCXL254BT_cjs.SYMBOL_POINTS_ATTR);
5279
5506
  if (!raw) {
5280
5507
  return false;
5281
5508
  }
@@ -5283,22 +5510,22 @@ function applySymbolBounds(path, bounds) {
5283
5510
  x: bounds.x + x * bounds.width,
5284
5511
  y: bounds.y + y * bounds.height
5285
5512
  }));
5286
- const tension = Number(path.getAttribute(chunkYM3XFBI4_cjs.SYMBOL_TENSION_ATTR)) || 0;
5287
- path.setAttribute("d", chunkYM3XFBI4_cjs.freeformPathData({ points, tension, closed: true }));
5513
+ const tension = Number(path.getAttribute(chunkCXL254BT_cjs.SYMBOL_TENSION_ATTR)) || 0;
5514
+ path.setAttribute("d", chunkCXL254BT_cjs.freeformPathData({ points, tension, closed: true }));
5288
5515
  return true;
5289
5516
  }
5290
5517
  function applyPathBounds(path, kind, bounds) {
5291
5518
  if (kind === "symbol" && applySymbolBounds(path, bounds)) {
5292
5519
  return;
5293
5520
  }
5294
- const pathData = chunkYM3XFBI4_cjs.localShapePath(kind, bounds.x, bounds.y, bounds.width, bounds.height);
5521
+ const pathData = chunkCXL254BT_cjs.localShapePath(kind, bounds.x, bounds.y, bounds.width, bounds.height);
5295
5522
  if (pathData) {
5296
5523
  path.setAttribute("d", pathData);
5297
5524
  }
5298
5525
  }
5299
5526
  function applyFrameBoundaryBounds(path, bounds) {
5300
- const cornerRadius = Number(path.getAttribute(chunkYM3XFBI4_cjs.CORNER_RADIUS_ATTR) ?? 0);
5301
- const squareCorner = path.getAttribute(chunkYM3XFBI4_cjs.SQUARE_CORNER_ATTR);
5527
+ const cornerRadius = Number(path.getAttribute(chunkCXL254BT_cjs.CORNER_RADIUS_ATTR) ?? 0);
5528
+ const squareCorner = path.getAttribute(chunkCXL254BT_cjs.SQUARE_CORNER_ATTR);
5302
5529
  const radii = {
5303
5530
  topLeft: cornerRadius,
5304
5531
  topRight: cornerRadius,
@@ -5308,7 +5535,7 @@ function applyFrameBoundaryBounds(path, bounds) {
5308
5535
  if (squareCorner) {
5309
5536
  radii[squareCorner] = 0;
5310
5537
  }
5311
- path.setAttribute("d", chunkYM3XFBI4_cjs.cornersRoundedRectPath(bounds.x, bounds.y, bounds.width, bounds.height, radii));
5538
+ path.setAttribute("d", chunkCXL254BT_cjs.cornersRoundedRectPath(bounds.x, bounds.y, bounds.width, bounds.height, radii));
5312
5539
  }
5313
5540
  function applySingleNodeBounds(primary, kind, bounds) {
5314
5541
  const tag = primary.tagName.toLowerCase();
@@ -5318,7 +5545,7 @@ function applySingleNodeBounds(primary, kind, bounds) {
5318
5545
  applyEllipseBounds(primary, bounds);
5319
5546
  } else if (tag === "foreignobject") {
5320
5547
  applyRectBounds(primary, null, bounds);
5321
- } else if (tag === "path" && primary.hasAttribute(chunkYM3XFBI4_cjs.CORNER_RADIUS_ATTR)) {
5548
+ } else if (tag === "path" && primary.hasAttribute(chunkCXL254BT_cjs.CORNER_RADIUS_ATTR)) {
5322
5549
  applyFrameBoundaryBounds(primary, bounds);
5323
5550
  } else if (tag === "path" && kind) {
5324
5551
  applyPathBounds(primary, kind, bounds);
@@ -5357,7 +5584,7 @@ function updateSelectionRing(overlay, bounds) {
5357
5584
  }
5358
5585
  function updateSelectionOverlay(overlay, bounds) {
5359
5586
  updateSelectionRing(overlay, bounds);
5360
- for (const [centerX, centerY, name] of chunk34PK7HEU_cjs.resizeHandlePositions(bounds)) {
5587
+ for (const [centerX, centerY, name] of chunkHFOGKSNU_cjs.resizeHandlePositions(bounds)) {
5361
5588
  const handle = overlay.querySelector(`[data-sf-resize-handle="${name}"]`);
5362
5589
  if (!handle) {
5363
5590
  continue;
@@ -5374,7 +5601,7 @@ function replaceTextLines(textElement, lines, x, lineHeight) {
5374
5601
  textElement.removeChild(textElement.firstChild);
5375
5602
  }
5376
5603
  lines.forEach((line, index) => {
5377
- const tspan = document.createElementNS(chunk34PK7HEU_cjs.SVG_NAMESPACE, "tspan");
5604
+ const tspan = document.createElementNS(chunkHFOGKSNU_cjs.SVG_NAMESPACE, "tspan");
5378
5605
  tspan.setAttribute("x", String(x));
5379
5606
  if (index > 0) {
5380
5607
  tspan.setAttribute("dy", `${lineHeight}px`);
@@ -5394,7 +5621,7 @@ function applyLiveText(textElement, rawText, bounds, strokeWidth) {
5394
5621
  const height = Math.max(0, bounds.height - padding * 2);
5395
5622
  const boxX = bounds.x + padding;
5396
5623
  const boxY = bounds.y + padding;
5397
- const lines = chunkYM3XFBI4_cjs.wrapText(rawText, width, fontSize);
5624
+ const lines = chunkCXL254BT_cjs.wrapText(rawText, width, fontSize);
5398
5625
  const linePixels = fontSize * lineHeight;
5399
5626
  const contentHeight = lines.length * linePixels;
5400
5627
  const firstY = verticalAlign === "top" ? boxY + fontSize : verticalAlign === "bottom" ? boxY + height - contentHeight + fontSize : boxY + (height - contentHeight) / 2 + fontSize;
@@ -5407,7 +5634,7 @@ function applyLiveText(textElement, rawText, bounds, strokeWidth) {
5407
5634
 
5408
5635
  // src/runtime/interaction/resize/preview.ts
5409
5636
  function textBoundsFor(kind, bounds) {
5410
- return kind === "person" ? chunkYM3XFBI4_cjs.personLabelArea(bounds.x, bounds.y, bounds.width, bounds.height) : bounds;
5637
+ return kind === "person" ? chunkCXL254BT_cjs.personLabelArea(bounds.x, bounds.y, bounds.width, bounds.height) : bounds;
5411
5638
  }
5412
5639
  function applyGeometryPreview(drag, bounds) {
5413
5640
  if (drag.isComposite) {
@@ -5427,7 +5654,7 @@ function applyResizePreview(drag, bounds) {
5427
5654
  applyLiveText(drag.text.el, drag.text.rawText, textBoundsFor(drag.kind, bounds), drag.text.strokeWidth);
5428
5655
  }
5429
5656
  if (drag.bubbles) {
5430
- chunk34PK7HEU_cjs.updateQuickDuplicateBubbles(drag.bubbles, bounds);
5657
+ chunkHFOGKSNU_cjs.updateQuickDuplicateBubbles(drag.bubbles, bounds);
5431
5658
  }
5432
5659
  updateLiveLinks(drag.liveLinks, bounds);
5433
5660
  }
@@ -5449,9 +5676,9 @@ function snapResize(svg, drag, pointer) {
5449
5676
  };
5450
5677
  }
5451
5678
  const axes = HANDLE_AXES[drag.handle];
5452
- const candidates = nearestCandidates(proposed, chunk34PK7HEU_cjs.findSnapCandidateBounds(svg, /* @__PURE__ */ new Set([drag.owner.id])));
5679
+ const candidates = nearestCandidates(proposed, chunkHFOGKSNU_cjs.findSnapCandidateBounds(svg, /* @__PURE__ */ new Set([drag.owner.id])));
5453
5680
  const snap = computeSnap(proposed, candidates, {
5454
- threshold: SNAP_THRESHOLD_PX2 / chunk34PK7HEU_cjs.pxPerUnit(svg),
5681
+ threshold: SNAP_THRESHOLD_PX2 / chunkHFOGKSNU_cjs.pxPerUnit(svg),
5455
5682
  activeX: resizeActivePoints(axes.x),
5456
5683
  activeY: resizeActivePoints(axes.y),
5457
5684
  guideOverhang: GUIDE_OVERHANG3
@@ -5492,13 +5719,13 @@ function selectResizeTarget(svg, event) {
5492
5719
  if (!ownerId) {
5493
5720
  return null;
5494
5721
  }
5495
- const primary = chunk34PK7HEU_cjs.findOwnerNode(svg, ownerId, chunk34PK7HEU_cjs.isPrimary);
5496
- const owner = primary && chunk34PK7HEU_cjs.resolveOwner(primary);
5722
+ const primary = chunkHFOGKSNU_cjs.findOwnerNode(svg, ownerId, chunkHFOGKSNU_cjs.isPrimary);
5723
+ const owner = primary && chunkHFOGKSNU_cjs.resolveOwner(primary);
5497
5724
  if (!primary || !hasEditableGeometry(owner)) {
5498
5725
  return null;
5499
5726
  }
5500
- const nodes = chunk34PK7HEU_cjs.findAllOwnerNodes(svg, ownerId);
5501
- const geometryNodes = isCompositeOwner(owner) ? nodes : nodes.filter((node) => !chunk34PK7HEU_cjs.isTextLabel(node));
5727
+ const nodes = chunkHFOGKSNU_cjs.findAllOwnerNodes(svg, ownerId);
5728
+ const geometryNodes = isCompositeOwner(owner) ? nodes : nodes.filter((node) => !chunkHFOGKSNU_cjs.isTextLabel(node));
5502
5729
  if (!geometryNodes.length) {
5503
5730
  return null;
5504
5731
  }
@@ -5516,7 +5743,7 @@ function selectResizeTarget(svg, event) {
5516
5743
 
5517
5744
  // src/runtime/interaction/resize/textCapture.ts
5518
5745
  function captureResizeText(nodes, primary) {
5519
- const textElement = nodes.find(chunk34PK7HEU_cjs.isTextLabel);
5746
+ const textElement = nodes.find(chunkHFOGKSNU_cjs.isTextLabel);
5520
5747
  const rawText = primary.getAttribute("aria-label");
5521
5748
  if (!textElement || !rawText) {
5522
5749
  return null;
@@ -5534,7 +5761,7 @@ function createResizeDragState(svg, event) {
5534
5761
  if (!selection) {
5535
5762
  return null;
5536
5763
  }
5537
- const startBounds = chunk34PK7HEU_cjs.symbolDeclaredBounds(selection.primary) ?? selection.primary.getBBox();
5764
+ const startBounds = chunkHFOGKSNU_cjs.symbolDeclaredBounds(selection.primary) ?? selection.primary.getBBox();
5538
5765
  const composite = isCompositeOwner(selection.owner);
5539
5766
  const isContainer = CONTAINER_ROLES.has(selection.owner.role);
5540
5767
  selection.captureTarget.setPointerCapture?.(event.pointerId);
@@ -5547,7 +5774,7 @@ function createResizeDragState(svg, event) {
5547
5774
  isComposite: composite,
5548
5775
  geometryNodes: selection.geometryNodes,
5549
5776
  insets: selection.geometryNodes.map(
5550
- (node) => node === selection.primary ? NO_INSET : insetWithin(startBounds, chunk34PK7HEU_cjs.symbolDeclaredBounds(node) ?? node.getBBox())
5777
+ (node) => node === selection.primary ? NO_INSET : insetWithin(startBounds, chunkHFOGKSNU_cjs.symbolDeclaredBounds(node) ?? node.getBBox())
5551
5778
  ),
5552
5779
  baseTransforms: selection.geometryNodes.map((node) => node.getAttribute("transform")),
5553
5780
  overlay: selection.overlay,
@@ -5573,7 +5800,7 @@ var ResizeSession = class {
5573
5800
  this.#emitter = emitter;
5574
5801
  }
5575
5802
  pointerDown = (event) => {
5576
- if (event.button !== 0 || this.#drag || chunk34PK7HEU_cjs.isCameraGesture(event)) {
5803
+ if (event.button !== 0 || this.#drag || chunkHFOGKSNU_cjs.isCameraGesture(event)) {
5577
5804
  return;
5578
5805
  }
5579
5806
  this.#drag = createResizeDragState(this.#svg, event);
@@ -5586,7 +5813,7 @@ var ResizeSession = class {
5586
5813
  drag.moved = true;
5587
5814
  const { bounds, guides } = snapResize(this.#svg, drag, resizePointerPosition(this.#svg, event));
5588
5815
  applyResizePreview(drag, clampResizeToChildren(bounds, drag.childrenBounds));
5589
- chunk34PK7HEU_cjs.updateAlignmentGuides(this.#svg, guides, RESIZE_GUIDE_COLOR);
5816
+ chunkHFOGKSNU_cjs.updateAlignmentGuides(this.#svg, guides, RESIZE_GUIDE_COLOR);
5590
5817
  };
5591
5818
  pointerUp = (event) => {
5592
5819
  const drag = this.#drag;
@@ -5595,7 +5822,7 @@ var ResizeSession = class {
5595
5822
  }
5596
5823
  this.#drag = null;
5597
5824
  event.target?.releasePointerCapture?.(drag.pointerId);
5598
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
5825
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
5599
5826
  if (!drag.moved) {
5600
5827
  return;
5601
5828
  }
@@ -5633,7 +5860,7 @@ function resolveSankeyNodeLabelTarget(event) {
5633
5860
  if (!labelElement) {
5634
5861
  return null;
5635
5862
  }
5636
- const owner = chunk34PK7HEU_cjs.resolveOwner(labelElement);
5863
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(labelElement);
5637
5864
  if (owner?.role !== "chart") {
5638
5865
  return null;
5639
5866
  }
@@ -5644,7 +5871,7 @@ function resolveSankeyNodeLabelTarget(event) {
5644
5871
  return { owner, nodeId, labelElement };
5645
5872
  }
5646
5873
  function createSankeyNodeLabelEditor(target, emitter, onClose) {
5647
- const rect = chunk34PK7HEU_cjs.screenRectOf(target.labelElement);
5874
+ const rect = chunkHFOGKSNU_cjs.screenRectOf(target.labelElement);
5648
5875
  if (rect.width <= 0 && rect.height <= 0) {
5649
5876
  return null;
5650
5877
  }
@@ -5701,7 +5928,7 @@ function clearSankeyNodeDragPreview(drag) {
5701
5928
  // src/runtime/interaction/sankeyNode/target.ts
5702
5929
  var RIBBON_PATH = /^M\s+(-?[\d.]+)\s+(-?[\d.]+)\s+C\s+-?[\d.]+\s+-?[\d.]+\s+-?[\d.]+\s+(-?[\d.]+)\s+(-?[\d.]+)\s+-?[\d.]+\s+L\s+-?[\d.]+\s+(-?[\d.]+)\s+C\s+-?[\d.]+\s+-?[\d.]+\s+-?[\d.]+\s+(-?[\d.]+)\s+-?[\d.]+\s+-?[\d.]+\s+Z$/;
5703
5930
  function isNodePointer(event) {
5704
- return event.button === 0 && !chunk34PK7HEU_cjs.isCameraGesture(event);
5931
+ return event.button === 0 && !chunkHFOGKSNU_cjs.isCameraGesture(event);
5705
5932
  }
5706
5933
  function findNodeRect(event) {
5707
5934
  return event.target?.closest?.('[data-sf-mark="sankey-node"]');
@@ -5759,7 +5986,7 @@ function resolveSankeyNodeDrag(svg, event) {
5759
5986
  if (!rect) {
5760
5987
  return null;
5761
5988
  }
5762
- const owner = chunk34PK7HEU_cjs.resolveOwner(rect);
5989
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(rect);
5763
5990
  if (owner?.role !== "chart") {
5764
5991
  return null;
5765
5992
  }
@@ -5767,7 +5994,7 @@ function resolveSankeyNodeDrag(svg, event) {
5767
5994
  if (!nodeId) {
5768
5995
  return null;
5769
5996
  }
5770
- const start = chunk34PK7HEU_cjs.pointerUserPoint(svg, event);
5997
+ const start = chunkHFOGKSNU_cjs.pointerUserPoint(svg, event);
5771
5998
  if (!start) {
5772
5999
  return null;
5773
6000
  }
@@ -5813,7 +6040,7 @@ var SankeyNodeDragSession = class {
5813
6040
  if (!this.#drag || event.pointerId !== this.#drag.pointerId) {
5814
6041
  return;
5815
6042
  }
5816
- const point = chunk34PK7HEU_cjs.pointerUserPoint(this.#svg, event);
6043
+ const point = chunkHFOGKSNU_cjs.pointerUserPoint(this.#svg, event);
5817
6044
  if (!point) {
5818
6045
  return;
5819
6046
  }
@@ -5827,7 +6054,7 @@ var SankeyNodeDragSession = class {
5827
6054
  const leadBounds = offsetBounds(drag.originalBounds, rawDx, rawDy);
5828
6055
  const candidates = nearestCandidates(leadBounds, drag.siblingBounds);
5829
6056
  const snap = computeSnap(leadBounds, candidates, {
5830
- threshold: SNAP_THRESHOLD_PX3 / chunk34PK7HEU_cjs.pxPerUnit(this.#svg),
6057
+ threshold: SNAP_THRESHOLD_PX3 / chunkHFOGKSNU_cjs.pxPerUnit(this.#svg),
5831
6058
  activeX: MOVE_ACTIVE_POINTS,
5832
6059
  activeY: MOVE_ACTIVE_POINTS,
5833
6060
  guideOverhang: GUIDE_OVERHANG4
@@ -5837,7 +6064,7 @@ var SankeyNodeDragSession = class {
5837
6064
  drag.lastDx = dx;
5838
6065
  drag.lastDy = dy;
5839
6066
  updateSankeyNodeDragPreview(drag, dx, dy);
5840
- chunk34PK7HEU_cjs.updateAlignmentGuides(
6067
+ chunkHFOGKSNU_cjs.updateAlignmentGuides(
5841
6068
  this.#svg,
5842
6069
  [snap.x.guide, snap.y.guide].filter((guide) => guide !== null),
5843
6070
  GUIDE_COLOR3
@@ -5848,7 +6075,7 @@ var SankeyNodeDragSession = class {
5848
6075
  clearSankeyNodeDragPreview(this.#drag);
5849
6076
  }
5850
6077
  this.#drag = null;
5851
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
6078
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
5852
6079
  }
5853
6080
  finish(event) {
5854
6081
  if (!this.#drag || event.pointerId !== this.#drag.pointerId) {
@@ -5858,7 +6085,7 @@ var SankeyNodeDragSession = class {
5858
6085
  this.#drag = null;
5859
6086
  event.target?.releasePointerCapture?.(drag.pointerId);
5860
6087
  clearSankeyNodeDragPreview(drag);
5861
- chunk34PK7HEU_cjs.clearAlignmentGuides(this.#svg);
6088
+ chunkHFOGKSNU_cjs.clearAlignmentGuides(this.#svg);
5862
6089
  if (!drag.moved) {
5863
6090
  return;
5864
6091
  }
@@ -5914,7 +6141,7 @@ function bindSankeyNode(viewer, emitter) {
5914
6141
  var FALLBACK_WIDTH = 120;
5915
6142
  var FALLBACK_HEIGHT = 28;
5916
6143
  function centeredLabelRect(primaryNode) {
5917
- const primaryRect = chunk34PK7HEU_cjs.screenRectOf(primaryNode);
6144
+ const primaryRect = chunkHFOGKSNU_cjs.screenRectOf(primaryNode);
5918
6145
  return {
5919
6146
  left: primaryRect.left + (primaryRect.width - FALLBACK_WIDTH) / 2,
5920
6147
  top: primaryRect.top + (primaryRect.height - FALLBACK_HEIGHT) / 2,
@@ -5924,10 +6151,10 @@ function centeredLabelRect(primaryNode) {
5924
6151
  }
5925
6152
  function resolveTextEditRect(owner, textNode, primaryNode) {
5926
6153
  if (owner.role === "shape") {
5927
- return primaryNode ? chunk34PK7HEU_cjs.screenRectOf(primaryNode) : null;
6154
+ return primaryNode ? chunkHFOGKSNU_cjs.screenRectOf(primaryNode) : null;
5928
6155
  }
5929
6156
  if (textNode) {
5930
- return chunk34PK7HEU_cjs.screenRectOf(textNode);
6157
+ return chunkHFOGKSNU_cjs.screenRectOf(textNode);
5931
6158
  }
5932
6159
  return primaryNode ? centeredLabelRect(primaryNode) : null;
5933
6160
  }
@@ -5947,8 +6174,8 @@ function textAlign(owner, textNode) {
5947
6174
  return anchor === "end" ? "right" : "left";
5948
6175
  }
5949
6176
  function createActiveTextEditor(svg, owner, emitter, onClose) {
5950
- const textNode = chunk34PK7HEU_cjs.findOwnerNode(svg, owner.id, chunk34PK7HEU_cjs.isTextLabel);
5951
- const primaryNode = chunk34PK7HEU_cjs.findOwnerNode(svg, owner.id, chunk34PK7HEU_cjs.isPrimary);
6177
+ const textNode = chunkHFOGKSNU_cjs.findOwnerNode(svg, owner.id, chunkHFOGKSNU_cjs.isTextLabel);
6178
+ const primaryNode = chunkHFOGKSNU_cjs.findOwnerNode(svg, owner.id, chunkHFOGKSNU_cjs.isPrimary);
5952
6179
  const rect = resolveTextEditRect(owner, textNode, primaryNode);
5953
6180
  if (!rect) {
5954
6181
  return null;
@@ -5994,7 +6221,7 @@ function isFrameTitle(target) {
5994
6221
  }
5995
6222
  function resolveEditableTextOwner(event) {
5996
6223
  const target = event.target;
5997
- const owner = chunk34PK7HEU_cjs.resolveOwner(target);
6224
+ const owner = chunkHFOGKSNU_cjs.resolveOwner(target);
5998
6225
  if (!owner) {
5999
6226
  return null;
6000
6227
  }
@@ -6135,7 +6362,7 @@ function applyToken(target, lines, token) {
6135
6362
  function maskSource(lines) {
6136
6363
  let tokens;
6137
6364
  try {
6138
- tokens = chunkYM3XFBI4_cjs.tokenizeSource(lines.join("\n"));
6365
+ tokens = chunkCXL254BT_cjs.tokenizeSource(lines.join("\n"));
6139
6366
  } catch {
6140
6367
  return null;
6141
6368
  }
@@ -6468,7 +6695,7 @@ function resolveCanvasObjectInsertionTarget(sfl, lines, parentId) {
6468
6695
  const modelRange = findFirstBlockOfKind(lines, "Model");
6469
6696
  return modelRange ? { range: modelRange, origin: { x: 0, y: 0 } } : null;
6470
6697
  }
6471
- const parent = chunkYM3XFBI4_cjs.sflToCanvasState(sfl).canvasObjects.find((canvasObject) => canvasObject.id === parentId);
6698
+ const parent = chunkCXL254BT_cjs.sflToCanvasState(sfl).canvasObjects.find((canvasObject) => canvasObject.id === parentId);
6472
6699
  if (!parent) {
6473
6700
  return null;
6474
6701
  }
@@ -6910,7 +7137,7 @@ function movePathPoints(lines, range, dx, dy) {
6910
7137
  replacePropertyValue(lines, span, shifted);
6911
7138
  }
6912
7139
  function applyMoveChange(sfl, event) {
6913
- const state = chunkYM3XFBI4_cjs.sflToCanvasState(sfl);
7140
+ const state = chunkCXL254BT_cjs.sflToCanvasState(sfl);
6914
7141
  const canvasObject = state.canvasObjects.find((candidate) => candidate.id === event.owner.id);
6915
7142
  if (!canvasObject) {
6916
7143
  return sfl;
@@ -6935,7 +7162,7 @@ function applyMoveChange(sfl, event) {
6935
7162
 
6936
7163
  // src/runtime/interaction/sflPatch/changes/pathPointChange.ts
6937
7164
  function applyPathPointChange(sfl, event) {
6938
- const canvasObjects = chunkYM3XFBI4_cjs.sflToCanvasState(sfl).canvasObjects;
7165
+ const canvasObjects = chunkCXL254BT_cjs.sflToCanvasState(sfl).canvasObjects;
6939
7166
  const canvasObject = canvasObjects.find((candidate) => candidate.id === event.owner.id);
6940
7167
  if (!canvasObject) {
6941
7168
  return sfl;
@@ -7061,9 +7288,260 @@ function shouldQuote(current, quote, indexed) {
7061
7288
  return indexed && trimmed === "none";
7062
7289
  }
7063
7290
 
7291
+ // src/runtime/interaction/sflPatch/connectionPatch/blockText.ts
7292
+ function buildConnectionBlock(options, baseIndent) {
7293
+ const bodyIndent = `${baseIndent} `;
7294
+ const block = [
7295
+ `${baseIndent}Connection ${options.id} {`,
7296
+ `${bodyIndent}from: ${options.fromId}`,
7297
+ `${bodyIndent}to: ${options.toId}`,
7298
+ `${bodyIndent}fromFace: "${options.fromFace}"`,
7299
+ `${bodyIndent}toFace: "${options.toFace}"`
7300
+ ];
7301
+ if (options.body) {
7302
+ block.push(...indentBlock(options.body, bodyIndent));
7303
+ }
7304
+ block.push(`${baseIndent}}`);
7305
+ return block;
7306
+ }
7307
+
7308
+ // src/runtime/interaction/sflPatch/connectionPatch/insertionTarget.ts
7309
+ function resolveConnectionInsertionTarget(sfl, lines, options) {
7310
+ if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7311
+ return null;
7312
+ }
7313
+ const canvasObjects = chunkCXL254BT_cjs.sflToCanvasState(sfl).canvasObjects;
7314
+ const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7315
+ const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7316
+ if (!hasSource || !hasTarget) {
7317
+ return null;
7318
+ }
7319
+ return findFirstBlockOfKind(lines, "Model");
7320
+ }
7321
+
7322
+ // src/runtime/interaction/sflPatch/connectionPatch/insert.ts
7323
+ function insertConnection(sfl, options) {
7324
+ const lines = sfl.split("\n");
7325
+ const modelRange = resolveConnectionInsertionTarget(sfl, lines, options);
7326
+ if (!modelRange) {
7327
+ return sfl;
7328
+ }
7329
+ insertBlockLines(lines, modelRange, (baseIndent) => buildConnectionBlock(options, baseIndent));
7330
+ return lines.join("\n");
7331
+ }
7332
+
7333
+ // src/runtime/interaction/sflPatch/changes/quickDuplicate/styleBlock.ts
7334
+ var QUOTED_KEYS = /* @__PURE__ */ new Set(["fill", "stroke", "textColor", "fontFamily", "shadow", "labelBackground"]);
7335
+ function styleLine(key, value) {
7336
+ return QUOTED_KEYS.has(key) ? ` ${key}: "${value.replace(/"/g, '\\"')}"` : ` ${key}: ${value}`;
7337
+ }
7338
+ function styleBlock(props, keys, leading = []) {
7339
+ const copied = keys.flatMap((key) => {
7340
+ const value = props?.[key];
7341
+ return value === void 0 ? [] : [styleLine(key, value)];
7342
+ });
7343
+ const lines = [...leading, ...copied];
7344
+ return lines.length > 0 ? `style {
7345
+ ${lines.join("\n")}
7346
+ }` : void 0;
7347
+ }
7348
+
7349
+ // src/runtime/interaction/sflPatch/changes/quickDuplicate/isometricDuplicate.ts
7350
+ var ISOMETRIC_GAP = 40;
7351
+ var ISOMETRIC_STYLE_KEYS = [
7352
+ "fill",
7353
+ "stroke",
7354
+ "strokeWidth",
7355
+ "cornerRadius",
7356
+ "shadow",
7357
+ "labelOffsetX",
7358
+ "labelOffsetY",
7359
+ "labelBackground"
7360
+ ];
7361
+ var TOUCHING_FACES = {
7362
+ "iso-width-pos": { fromFace: "right", toFace: "left" },
7363
+ "iso-width-neg": { fromFace: "left", toFace: "right" },
7364
+ "iso-depth-pos": { fromFace: "front", toFace: "back" },
7365
+ "iso-depth-neg": { fromFace: "back", toFace: "front" },
7366
+ "iso-height-pos": { fromFace: "bottom", toFace: "top" },
7367
+ "iso-height-neg": { fromFace: "top", toFace: "bottom" }
7368
+ };
7369
+ function isIsometricDirection2(direction) {
7370
+ return direction.startsWith("iso-");
7371
+ }
7372
+ function isometricOffset(direction, object, gap) {
7373
+ const { width, height } = object;
7374
+ const { depth } = object.isometric;
7375
+ switch (direction) {
7376
+ case "iso-width-pos":
7377
+ return { dx: (width + gap) * chunkCXL254BT_cjs.AXIS_COS, dy: (width + gap) * chunkCXL254BT_cjs.AXIS_SIN };
7378
+ case "iso-width-neg":
7379
+ return { dx: -(width + gap) * chunkCXL254BT_cjs.AXIS_COS, dy: -(width + gap) * chunkCXL254BT_cjs.AXIS_SIN };
7380
+ case "iso-depth-pos":
7381
+ return { dx: -(depth + gap) * chunkCXL254BT_cjs.AXIS_COS, dy: (depth + gap) * chunkCXL254BT_cjs.AXIS_SIN };
7382
+ case "iso-depth-neg":
7383
+ return { dx: (depth + gap) * chunkCXL254BT_cjs.AXIS_COS, dy: -(depth + gap) * chunkCXL254BT_cjs.AXIS_SIN };
7384
+ case "iso-height-pos":
7385
+ return { dx: 0, dy: height + gap };
7386
+ case "iso-height-neg":
7387
+ return { dx: 0, dy: -(height + gap) };
7388
+ }
7389
+ }
7390
+ function copyStyle(object, direction) {
7391
+ if (!direction.startsWith("iso-height-")) {
7392
+ return styleBlock(object.props, ISOMETRIC_STYLE_KEYS);
7393
+ }
7394
+ return styleBlock(
7395
+ object.props,
7396
+ ISOMETRIC_STYLE_KEYS.filter((key) => key !== "shadow"),
7397
+ [' shadow: "off"']
7398
+ );
7399
+ }
7400
+ function copyOf(object, direction, options) {
7401
+ const { dx, dy } = isometricOffset(direction, object, options.gap ?? ISOMETRIC_GAP);
7402
+ return {
7403
+ id: options.shapeId,
7404
+ kind: "isometric",
7405
+ text: object.text ?? "",
7406
+ x: object.x + dx,
7407
+ y: object.y + dy,
7408
+ width: object.width,
7409
+ height: object.height,
7410
+ depth: object.isometric.depth,
7411
+ parentId: object.parentFrameId,
7412
+ body: copyStyle(object, direction)
7413
+ };
7414
+ }
7415
+ function duplicateIsometricObject(sfl, object, direction, options) {
7416
+ const withCopy = insertCanvasObject(sfl, copyOf(object, direction, options));
7417
+ return insertConnection(withCopy, {
7418
+ id: options.linkId,
7419
+ fromId: object.id,
7420
+ toId: options.shapeId,
7421
+ ...TOUCHING_FACES[direction]
7422
+ });
7423
+ }
7424
+
7425
+ // src/runtime/interaction/sflPatch/linkPatch/blockText.ts
7426
+ function buildLinkBlock(options, baseIndent) {
7427
+ const bodyIndent = `${baseIndent} `;
7428
+ const from = formatLinkEndpoint({ id: options.fromId, side: options.fromSide, fraction: options.fromFraction });
7429
+ const to = formatLinkEndpoint({ id: options.toId, side: options.toSide, fraction: options.toFraction });
7430
+ const block = [`${baseIndent}Link ${options.id} {`, `${bodyIndent}from: ${from}`, `${bodyIndent}to: ${to}`];
7431
+ if (options.text !== void 0) {
7432
+ block.push(`${bodyIndent}text: "${escapeSflString(options.text)}"`);
7433
+ }
7434
+ if (options.body) {
7435
+ block.push(...indentBlock(options.body, bodyIndent));
7436
+ }
7437
+ block.push(`${baseIndent}}`);
7438
+ return block;
7439
+ }
7440
+
7441
+ // src/runtime/interaction/sflPatch/linkPatch/insertionTarget.ts
7442
+ function resolveLinkInsertionTarget(sfl, lines, options) {
7443
+ if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7444
+ return null;
7445
+ }
7446
+ const canvasObjects = chunkCXL254BT_cjs.sflToCanvasState(sfl).canvasObjects;
7447
+ const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7448
+ const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7449
+ if (!hasSource || !hasTarget) {
7450
+ return null;
7451
+ }
7452
+ return findFirstBlockOfKind(lines, "Model");
7453
+ }
7454
+
7455
+ // src/runtime/interaction/sflPatch/linkPatch/insert.ts
7456
+ function insertLink(sfl, options) {
7457
+ const lines = sfl.split("\n");
7458
+ const modelRange = resolveLinkInsertionTarget(sfl, lines, options);
7459
+ if (!modelRange) {
7460
+ return sfl;
7461
+ }
7462
+ insertBlockLines(lines, modelRange, (baseIndent) => buildLinkBlock(options, baseIndent));
7463
+ return lines.join("\n");
7464
+ }
7465
+
7466
+ // src/runtime/interaction/sflPatch/changes/quickDuplicate/shapeDuplicate.ts
7467
+ var SHAPE_GAP = 200;
7468
+ var OPPOSITE_SIDE = { top: "bottom", right: "left", bottom: "top", left: "right" };
7469
+ var SHAPE_STYLE_KEYS = [
7470
+ "fill",
7471
+ "stroke",
7472
+ "strokeWidth",
7473
+ "strokeStyle",
7474
+ "textColor",
7475
+ "fontSize",
7476
+ "fontFamily",
7477
+ "cornerRadius",
7478
+ "opacity",
7479
+ "shadow"
7480
+ ];
7481
+ var LINK_STYLE_KEYS = ["stroke", "strokeWidth", "strokeStyle", "markerStart", "markerEnd", "route"];
7482
+ function shapeOffset(side, object, gap) {
7483
+ switch (side) {
7484
+ case "top":
7485
+ return { dx: 0, dy: -(object.height + gap) };
7486
+ case "bottom":
7487
+ return { dx: 0, dy: object.height + gap };
7488
+ case "left":
7489
+ return { dx: -(object.width + gap), dy: 0 };
7490
+ case "right":
7491
+ return { dx: object.width + gap, dy: 0 };
7492
+ }
7493
+ }
7494
+ function copyOf2(object, side, options) {
7495
+ const { dx, dy } = shapeOffset(side, object, options.gap ?? SHAPE_GAP);
7496
+ const shape = object.shapeType ? [` shape: ${object.shapeType}`] : [];
7497
+ return {
7498
+ id: options.shapeId,
7499
+ kind: "shape",
7500
+ text: object.text ?? "",
7501
+ x: object.x + dx,
7502
+ y: object.y + dy,
7503
+ width: object.width,
7504
+ height: object.height,
7505
+ parentId: object.parentFrameId,
7506
+ body: styleBlock(object.props, SHAPE_STYLE_KEYS, shape)
7507
+ };
7508
+ }
7509
+ function linkStyleReference(links, objectId) {
7510
+ return links.find((link) => link.fromId === objectId) ?? links[0];
7511
+ }
7512
+ function linkToCopy(object, links, side, options) {
7513
+ return {
7514
+ id: options.linkId,
7515
+ fromId: object.id,
7516
+ toId: options.shapeId,
7517
+ fromSide: side,
7518
+ toSide: OPPOSITE_SIDE[side],
7519
+ body: styleBlock(linkStyleReference(links, object.id)?.props, LINK_STYLE_KEYS)
7520
+ };
7521
+ }
7522
+ function duplicateShape(sfl, input) {
7523
+ const { object, links, side, options } = input;
7524
+ const withCopy = insertCanvasObject(sfl, copyOf2(object, side, options));
7525
+ return insertLink(withCopy, linkToCopy(object, links, side, options));
7526
+ }
7527
+
7528
+ // src/runtime/interaction/sflPatch/changes/quickDuplicateChange.ts
7529
+ function applyQuickDuplicateChange(sfl, event, options) {
7530
+ const state = chunkCXL254BT_cjs.sflToCanvasState(sfl);
7531
+ const object = state.canvasObjects.find((candidate) => candidate.id === event.owner.id);
7532
+ if (!object) {
7533
+ return sfl;
7534
+ }
7535
+ const { direction } = event;
7536
+ if (isIsometricDirection2(direction)) {
7537
+ return chunkCXL254BT_cjs.isIsometricObject(object) ? duplicateIsometricObject(sfl, object, direction, options) : sfl;
7538
+ }
7539
+ return chunkCXL254BT_cjs.isIsometricObject(object) ? sfl : duplicateShape(sfl, { object, links: state.links, side: direction, options });
7540
+ }
7541
+
7064
7542
  // src/runtime/interaction/sflPatch/changes/resizeChange.ts
7065
7543
  function applyResizeChange(sfl, event) {
7066
- const state = chunkYM3XFBI4_cjs.sflToCanvasState(sfl);
7544
+ const state = chunkCXL254BT_cjs.sflToCanvasState(sfl);
7067
7545
  const canvasObject = state.canvasObjects.find((candidate) => candidate.id === event.owner.id);
7068
7546
  const parent = canvasObject?.parentFrameId ? state.canvasObjects.find((candidate) => candidate.id === canvasObject.parentFrameId) : void 0;
7069
7547
  const originX = parent?.x ?? 0;
@@ -7185,89 +7663,6 @@ function applyTextChange(sfl, event) {
7185
7663
  return lines.join("\n");
7186
7664
  }
7187
7665
 
7188
- // src/runtime/interaction/sflPatch/connectionPatch/blockText.ts
7189
- function buildConnectionBlock(options, baseIndent) {
7190
- const bodyIndent = `${baseIndent} `;
7191
- const block = [
7192
- `${baseIndent}Connection ${options.id} {`,
7193
- `${bodyIndent}from: ${options.fromId}`,
7194
- `${bodyIndent}to: ${options.toId}`,
7195
- `${bodyIndent}fromFace: "${options.fromFace}"`,
7196
- `${bodyIndent}toFace: "${options.toFace}"`
7197
- ];
7198
- if (options.body) {
7199
- block.push(...indentBlock(options.body, bodyIndent));
7200
- }
7201
- block.push(`${baseIndent}}`);
7202
- return block;
7203
- }
7204
-
7205
- // src/runtime/interaction/sflPatch/connectionPatch/insertionTarget.ts
7206
- function resolveConnectionInsertionTarget(sfl, lines, options) {
7207
- if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7208
- return null;
7209
- }
7210
- const canvasObjects = chunkYM3XFBI4_cjs.sflToCanvasState(sfl).canvasObjects;
7211
- const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7212
- const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7213
- if (!hasSource || !hasTarget) {
7214
- return null;
7215
- }
7216
- return findFirstBlockOfKind(lines, "Model");
7217
- }
7218
-
7219
- // src/runtime/interaction/sflPatch/connectionPatch/insert.ts
7220
- function insertConnection(sfl, options) {
7221
- const lines = sfl.split("\n");
7222
- const modelRange = resolveConnectionInsertionTarget(sfl, lines, options);
7223
- if (!modelRange) {
7224
- return sfl;
7225
- }
7226
- insertBlockLines(lines, modelRange, (baseIndent) => buildConnectionBlock(options, baseIndent));
7227
- return lines.join("\n");
7228
- }
7229
-
7230
- // src/runtime/interaction/sflPatch/linkPatch/blockText.ts
7231
- function buildLinkBlock(options, baseIndent) {
7232
- const bodyIndent = `${baseIndent} `;
7233
- const from = formatLinkEndpoint({ id: options.fromId, side: options.fromSide, fraction: options.fromFraction });
7234
- const to = formatLinkEndpoint({ id: options.toId, side: options.toSide, fraction: options.toFraction });
7235
- const block = [`${baseIndent}Link ${options.id} {`, `${bodyIndent}from: ${from}`, `${bodyIndent}to: ${to}`];
7236
- if (options.text !== void 0) {
7237
- block.push(`${bodyIndent}text: "${escapeSflString(options.text)}"`);
7238
- }
7239
- if (options.body) {
7240
- block.push(...indentBlock(options.body, bodyIndent));
7241
- }
7242
- block.push(`${baseIndent}}`);
7243
- return block;
7244
- }
7245
-
7246
- // src/runtime/interaction/sflPatch/linkPatch/insertionTarget.ts
7247
- function resolveLinkInsertionTarget(sfl, lines, options) {
7248
- if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7249
- return null;
7250
- }
7251
- const canvasObjects = chunkYM3XFBI4_cjs.sflToCanvasState(sfl).canvasObjects;
7252
- const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7253
- const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7254
- if (!hasSource || !hasTarget) {
7255
- return null;
7256
- }
7257
- return findFirstBlockOfKind(lines, "Model");
7258
- }
7259
-
7260
- // src/runtime/interaction/sflPatch/linkPatch/insert.ts
7261
- function insertLink(sfl, options) {
7262
- const lines = sfl.split("\n");
7263
- const modelRange = resolveLinkInsertionTarget(sfl, lines, options);
7264
- if (!modelRange) {
7265
- return sfl;
7266
- }
7267
- insertBlockLines(lines, modelRange, (baseIndent) => buildLinkBlock(options, baseIndent));
7268
- return lines.join("\n");
7269
- }
7270
-
7271
7666
  // src/runtime/interaction/sflPatch/linkPatch/remove.ts
7272
7667
  function removeLink(sfl, id) {
7273
7668
  const lines = sfl.split("\n");
@@ -7293,6 +7688,7 @@ function bindEditing(viewer, options = {}) {
7293
7688
  const quickDuplicate = bindQuickDuplicate(viewer, emitter);
7294
7689
  const isometricQuickDuplicate = bindIsometricQuickDuplicate(viewer, emitter);
7295
7690
  const deleteSelection = bindDeleteSelection(viewer, emitter);
7691
+ const nudgeSelection = bindNudgeSelection(viewer, emitter);
7296
7692
  const chartValues = bindChartValueDrag(viewer, emitter);
7297
7693
  const pieLabels = bindPieLabelDrag(viewer, emitter);
7298
7694
  const isometricLabels = bindIsometricLabelDrag(viewer, emitter);
@@ -7317,6 +7713,7 @@ function bindEditing(viewer, options = {}) {
7317
7713
  quickDuplicate.destroy();
7318
7714
  isometricQuickDuplicate.destroy();
7319
7715
  deleteSelection.destroy();
7716
+ nudgeSelection.destroy();
7320
7717
  chartValues.destroy();
7321
7718
  pieLabels.destroy();
7322
7719
  isometricLabels.destroy();
@@ -7336,6 +7733,7 @@ exports.applyLinkSegmentChange = applyLinkSegmentChange;
7336
7733
  exports.applyMoveChange = applyMoveChange;
7337
7734
  exports.applyPathPointChange = applyPathPointChange;
7338
7735
  exports.applyPropertyChange = applyPropertyChange;
7736
+ exports.applyQuickDuplicateChange = applyQuickDuplicateChange;
7339
7737
  exports.applyResizeChange = applyResizeChange;
7340
7738
  exports.applySankeyNodeMoveChange = applySankeyNodeMoveChange;
7341
7739
  exports.applySankeyNodeRenameChange = applySankeyNodeRenameChange;