@opendata-ai/openchart-engine 6.5.1 → 6.6.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.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/compile.ts
2
2
  import {
3
- adaptTheme as adaptTheme2,
3
+ adaptTheme as adaptTheme3,
4
4
  BRAND_RESERVE_WIDTH as BRAND_RESERVE_WIDTH2,
5
5
  computeLabelBounds,
6
6
  generateAltText,
@@ -8,7 +8,7 @@ import {
8
8
  getBreakpoint,
9
9
  getHeightClass,
10
10
  getLayoutStrategy,
11
- resolveTheme as resolveTheme2
11
+ resolveTheme as resolveTheme3
12
12
  } from "@opendata-ai/openchart-core";
13
13
 
14
14
  // src/annotations/compute.ts
@@ -44,23 +44,23 @@ function interpolateInDomain(numValue, domain, positionOf) {
44
44
  const t = (numValue - sorted[lower].n) / (sorted[upper].n - sorted[lower].n);
45
45
  return lowerPos + t * (upperPos - lowerPos);
46
46
  }
47
- function resolvePosition(value, scale) {
47
+ function resolvePosition(value2, scale) {
48
48
  if (!scale) return null;
49
49
  const s = scale.scale;
50
50
  const type = scale.type;
51
51
  if (type === "time") {
52
- const date2 = new Date(String(value));
52
+ const date2 = new Date(String(value2));
53
53
  if (Number.isNaN(date2.getTime())) return null;
54
54
  return s(date2);
55
55
  }
56
56
  if (type === "linear" || type === "log") {
57
- const num = typeof value === "number" ? value : Number(value);
57
+ const num = typeof value2 === "number" ? value2 : Number(value2);
58
58
  if (!Number.isFinite(num)) return null;
59
59
  return s(num);
60
60
  }
61
61
  if (type === "band") {
62
62
  const bandScale = s;
63
- const strValue2 = String(value);
63
+ const strValue2 = String(value2);
64
64
  const pos = bandScale(strValue2);
65
65
  if (pos !== void 0) return pos + (bandScale.bandwidth?.() ?? 0) / 2;
66
66
  const bw = bandScale.bandwidth?.() ?? 0;
@@ -70,7 +70,7 @@ function resolvePosition(value, scale) {
70
70
  (entry) => (bandScale(entry) ?? 0) + bw / 2
71
71
  );
72
72
  }
73
- const strValue = String(value);
73
+ const strValue = String(value2);
74
74
  const directResult = s(strValue);
75
75
  if (directResult !== void 0) return directResult;
76
76
  if (type === "point" || type === "ordinal") {
@@ -393,12 +393,6 @@ function nudgeAnnotationFromObstacles(annotation, originalAnnotation, scales, ch
393
393
  const labelCenterY = candidateBounds.y + candidateBounds.height / 2;
394
394
  const inBounds = labelCenterX >= chartArea.x && labelCenterX <= chartArea.x + chartArea.width + 10 && labelCenterY >= chartArea.y - fontSize && labelCenterY <= chartArea.y + chartArea.height + fontSize * 3;
395
395
  if (inBounds) {
396
- if (candidateLabel.connector && dx === 0 && dy !== 0) {
397
- candidateLabel.connector = {
398
- ...candidateLabel.connector,
399
- style: "caret"
400
- };
401
- }
402
396
  annotation.label = candidateLabel;
403
397
  return true;
404
398
  }
@@ -561,15 +555,15 @@ function isFieldPredicate(pred) {
561
555
  return "field" in pred;
562
556
  }
563
557
  function evaluateFieldPredicate(datum, pred) {
564
- const value = datum[pred.field];
558
+ const value2 = datum[pred.field];
565
559
  if (pred.valid !== void 0) {
566
- const isValid = value !== null && value !== void 0 && !Number.isNaN(value);
560
+ const isValid = value2 !== null && value2 !== void 0 && !Number.isNaN(value2);
567
561
  return pred.valid ? isValid : !isValid;
568
562
  }
569
563
  if (pred.equal !== void 0) {
570
- return value === pred.equal;
564
+ return value2 === pred.equal;
571
565
  }
572
- const numValue = Number(value);
566
+ const numValue = Number(value2);
573
567
  if (pred.lt !== void 0) {
574
568
  return numValue < pred.lt;
575
569
  }
@@ -583,11 +577,11 @@ function evaluateFieldPredicate(datum, pred) {
583
577
  return numValue >= pred.gte;
584
578
  }
585
579
  if (pred.range !== void 0) {
586
- const [min3, max3] = pred.range;
587
- return numValue >= min3 && numValue <= max3;
580
+ const [min4, max4] = pred.range;
581
+ return numValue >= min4 && numValue <= max4;
588
582
  }
589
583
  if (pred.oneOf !== void 0) {
590
- return pred.oneOf.includes(value);
584
+ return pred.oneOf.includes(value2);
591
585
  }
592
586
  return true;
593
587
  }
@@ -626,18 +620,18 @@ function isConditionalValueDef(def) {
626
620
 
627
621
  // src/charts/utils.ts
628
622
  var DEFAULT_COLOR = "#1b7fa3";
629
- function scaleValue(scale, scaleType, value) {
630
- if (value == null) return null;
623
+ function scaleValue(scale, scaleType, value2) {
624
+ if (value2 == null) return null;
631
625
  if (scaleType === "time" || scaleType === "utc") {
632
- const date2 = value instanceof Date ? value : new Date(String(value));
626
+ const date2 = value2 instanceof Date ? value2 : new Date(String(value2));
633
627
  if (Number.isNaN(date2.getTime())) return null;
634
628
  return scale(date2);
635
629
  }
636
630
  if (scaleType === "point" || scaleType === "band" || scaleType === "ordinal") {
637
- const result = scale(String(value));
631
+ const result = scale(String(value2));
638
632
  return result ?? null;
639
633
  }
640
- const num = typeof value === "number" ? value : Number(value);
634
+ const num = typeof value2 === "number" ? value2 : Number(value2);
641
635
  if (!Number.isFinite(num)) return null;
642
636
  return scale(num);
643
637
  }
@@ -689,19 +683,19 @@ function getColor(scales, key, _index, fallback = DEFAULT_COLOR) {
689
683
  }
690
684
  return scales.defaultColor ?? fallback;
691
685
  }
692
- function getSequentialColor(scales, value, fallback = DEFAULT_COLOR) {
686
+ function getSequentialColor(scales, value2, fallback = DEFAULT_COLOR) {
693
687
  if (scales.color?.type === "sequential") {
694
688
  const colorScale = scales.color.scale;
695
- return colorScale(value);
689
+ return colorScale(value2);
696
690
  }
697
691
  return scales.defaultColor ?? fallback;
698
692
  }
699
693
 
700
694
  // src/charts/bar/compute.ts
701
695
  var MIN_BAR_WIDTH = 1;
702
- function formatBarValue(value) {
703
- if (Math.abs(value) >= 1e3) return abbreviateNumber(value);
704
- return formatNumber(value);
696
+ function formatBarValue(value2) {
697
+ if (Math.abs(value2) >= 1e3) return abbreviateNumber(value2);
698
+ return formatNumber(value2);
705
699
  }
706
700
  function computeBarMarks(spec, scales, _chartArea, _strategy) {
707
701
  const encoding = spec.encoding;
@@ -756,14 +750,14 @@ function computeStackedBars(data, valueField, categoryField, colorField, xScale,
756
750
  let cumulativeValue = 0;
757
751
  for (const row of rows) {
758
752
  const groupKey = String(row[colorField] ?? "");
759
- const value = Number(row[valueField] ?? 0);
760
- if (!Number.isFinite(value) || value <= 0) continue;
753
+ const value2 = Number(row[valueField] ?? 0);
754
+ if (!Number.isFinite(value2) || value2 <= 0) continue;
761
755
  const color2 = getColor(scales, groupKey);
762
756
  const xLeft = xScale(cumulativeValue);
763
- const xRight = xScale(cumulativeValue + value);
757
+ const xRight = xScale(cumulativeValue + value2);
764
758
  const barWidth = Math.max(Math.abs(xRight - xLeft), MIN_BAR_WIDTH);
765
759
  const aria = {
766
- label: `${category}, ${groupKey}: ${formatBarValue(value)}`
760
+ label: `${category}, ${groupKey}: ${formatBarValue(value2)}`
767
761
  };
768
762
  marks.push({
769
763
  type: "rect",
@@ -778,7 +772,7 @@ function computeStackedBars(data, valueField, categoryField, colorField, xScale,
778
772
  orient: "horizontal",
779
773
  stackGroup: category
780
774
  });
781
- cumulativeValue += value;
775
+ cumulativeValue += value2;
782
776
  }
783
777
  }
784
778
  return marks;
@@ -787,8 +781,8 @@ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, band
787
781
  const marks = [];
788
782
  for (const row of data) {
789
783
  const category = String(row[categoryField] ?? "");
790
- const value = Number(row[valueField] ?? 0);
791
- if (!Number.isFinite(value)) continue;
784
+ const value2 = Number(row[valueField] ?? 0);
785
+ if (!Number.isFinite(value2)) continue;
792
786
  const bandY = yScale(category);
793
787
  if (bandY === void 0) continue;
794
788
  let color2;
@@ -797,14 +791,14 @@ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, band
797
791
  resolveConditionalValue(row, conditionalColor) ?? getColor(scales, "__default__")
798
792
  );
799
793
  } else if (sequentialColor) {
800
- color2 = getSequentialColor(scales, value);
794
+ color2 = getSequentialColor(scales, value2);
801
795
  } else {
802
796
  color2 = getColor(scales, "__default__");
803
797
  }
804
- const xPos = value >= 0 ? baseline : xScale(value);
805
- const barWidth = Math.max(Math.abs(xScale(value) - baseline), MIN_BAR_WIDTH);
798
+ const xPos = value2 >= 0 ? baseline : xScale(value2);
799
+ const barWidth = Math.max(Math.abs(xScale(value2) - baseline), MIN_BAR_WIDTH);
806
800
  const aria = {
807
- label: `${category}: ${formatBarValue(value)}`
801
+ label: `${category}: ${formatBarValue(value2)}`
808
802
  };
809
803
  marks.push({
810
804
  type: "rect",
@@ -958,9 +952,9 @@ var barRenderer = (spec, scales, chartArea, strategy, _theme) => {
958
952
  // src/charts/column/compute.ts
959
953
  import { abbreviateNumber as abbreviateNumber2, formatNumber as formatNumber2 } from "@opendata-ai/openchart-core";
960
954
  var MIN_COLUMN_HEIGHT = 1;
961
- function formatColumnValue(value) {
962
- if (Math.abs(value) >= 1e3) return abbreviateNumber2(value);
963
- return formatNumber2(value);
955
+ function formatColumnValue(value2) {
956
+ if (Math.abs(value2) >= 1e3) return abbreviateNumber2(value2);
957
+ return formatNumber2(value2);
964
958
  }
965
959
  function computeColumnMarks(spec, scales, _chartArea, _strategy) {
966
960
  const encoding = spec.encoding;
@@ -1025,8 +1019,8 @@ function computeSimpleColumns(data, categoryField, valueField, xScale, yScale, b
1025
1019
  const marks = [];
1026
1020
  for (const row of data) {
1027
1021
  const category = String(row[categoryField] ?? "");
1028
- const value = Number(row[valueField] ?? 0);
1029
- if (!Number.isFinite(value)) continue;
1022
+ const value2 = Number(row[valueField] ?? 0);
1023
+ if (!Number.isFinite(value2)) continue;
1030
1024
  const bandX = xScale(category);
1031
1025
  if (bandX === void 0) continue;
1032
1026
  let color2;
@@ -1035,15 +1029,15 @@ function computeSimpleColumns(data, categoryField, valueField, xScale, yScale, b
1035
1029
  resolveConditionalValue(row, conditionalColor) ?? getColor(scales, "__default__")
1036
1030
  );
1037
1031
  } else if (sequentialColor) {
1038
- color2 = getSequentialColor(scales, value);
1032
+ color2 = getSequentialColor(scales, value2);
1039
1033
  } else {
1040
1034
  color2 = getColor(scales, "__default__");
1041
1035
  }
1042
- const yPos = yScale(value);
1036
+ const yPos = yScale(value2);
1043
1037
  const columnHeight = Math.max(Math.abs(baseline - yPos), MIN_COLUMN_HEIGHT);
1044
- const y2 = value >= 0 ? yPos : baseline;
1038
+ const y2 = value2 >= 0 ? yPos : baseline;
1045
1039
  const aria = {
1046
- label: `${category}: ${formatColumnValue(value)}`
1040
+ label: `${category}: ${formatColumnValue(value2)}`
1047
1041
  };
1048
1042
  marks.push({
1049
1043
  type: "rect",
@@ -1064,17 +1058,17 @@ function computeColoredColumns(data, categoryField, valueField, colorField, xSca
1064
1058
  const marks = [];
1065
1059
  for (const row of data) {
1066
1060
  const category = String(row[categoryField] ?? "");
1067
- const value = Number(row[valueField] ?? 0);
1068
- if (!Number.isFinite(value)) continue;
1061
+ const value2 = Number(row[valueField] ?? 0);
1062
+ if (!Number.isFinite(value2)) continue;
1069
1063
  const bandX = xScale(category);
1070
1064
  if (bandX === void 0) continue;
1071
1065
  const groupKey = String(row[colorField] ?? "");
1072
1066
  const color2 = getColor(scales, groupKey);
1073
- const yPos = yScale(value);
1067
+ const yPos = yScale(value2);
1074
1068
  const columnHeight = Math.max(Math.abs(baseline - yPos), MIN_COLUMN_HEIGHT);
1075
- const y2 = value >= 0 ? yPos : baseline;
1069
+ const y2 = value2 >= 0 ? yPos : baseline;
1076
1070
  const aria = {
1077
- label: `${category}, ${groupKey}: ${formatColumnValue(value)}`
1071
+ label: `${category}, ${groupKey}: ${formatColumnValue(value2)}`
1078
1072
  };
1079
1073
  marks.push({
1080
1074
  type: "rect",
@@ -1100,14 +1094,14 @@ function computeStackedColumns(data, categoryField, valueField, colorField, xSca
1100
1094
  let cumulativeValue = 0;
1101
1095
  for (const row of rows) {
1102
1096
  const groupKey = String(row[colorField] ?? "");
1103
- const value = Number(row[valueField] ?? 0);
1104
- if (!Number.isFinite(value) || value <= 0) continue;
1097
+ const value2 = Number(row[valueField] ?? 0);
1098
+ if (!Number.isFinite(value2) || value2 <= 0) continue;
1105
1099
  const color2 = getColor(scales, groupKey);
1106
- const yTop = yScale(cumulativeValue + value);
1100
+ const yTop = yScale(cumulativeValue + value2);
1107
1101
  const yBottom = yScale(cumulativeValue);
1108
1102
  const columnHeight = Math.max(Math.abs(yBottom - yTop), MIN_COLUMN_HEIGHT);
1109
1103
  const aria = {
1110
- label: `${category}, ${groupKey}: ${formatColumnValue(value)}`
1104
+ label: `${category}, ${groupKey}: ${formatColumnValue(value2)}`
1111
1105
  };
1112
1106
  marks.push({
1113
1107
  type: "rect",
@@ -1122,7 +1116,7 @@ function computeStackedColumns(data, categoryField, valueField, colorField, xSca
1122
1116
  orient: "vertical",
1123
1117
  stackGroup: category
1124
1118
  });
1125
- cumulativeValue += value;
1119
+ cumulativeValue += value2;
1126
1120
  }
1127
1121
  }
1128
1122
  return marks;
@@ -1253,8 +1247,8 @@ function computeDumbbellMarks(data, valueField, categoryField, colorField, xScal
1253
1247
  const cy = bandY + bandwidth / 2;
1254
1248
  const xValues = [];
1255
1249
  for (const row of rows) {
1256
- const value = Number(row[valueField] ?? 0);
1257
- if (Number.isFinite(value)) xValues.push(value);
1250
+ const value2 = Number(row[valueField] ?? 0);
1251
+ if (Number.isFinite(value2)) xValues.push(value2);
1258
1252
  }
1259
1253
  if (xValues.length === 0) continue;
1260
1254
  const minVal = Math.min(...xValues);
@@ -1278,13 +1272,13 @@ function computeDumbbellMarks(data, valueField, categoryField, colorField, xScal
1278
1272
  });
1279
1273
  }
1280
1274
  for (const row of rows) {
1281
- const value = Number(row[valueField] ?? 0);
1282
- if (!Number.isFinite(value)) continue;
1283
- const cx = xScale(value);
1275
+ const value2 = Number(row[valueField] ?? 0);
1276
+ if (!Number.isFinite(value2)) continue;
1277
+ const cx = xScale(value2);
1284
1278
  const colorCategory = String(row[colorField] ?? "");
1285
1279
  const color2 = getColor(scales, colorCategory);
1286
1280
  const dotAria = {
1287
- label: `${category}, ${colorCategory}: ${value}`
1281
+ label: `${category}, ${colorCategory}: ${value2}`
1288
1282
  };
1289
1283
  marks.push({
1290
1284
  type: "point",
@@ -1305,13 +1299,13 @@ function computeLollipopMarks(data, valueField, categoryField, xScale, yScale, b
1305
1299
  const marks = [];
1306
1300
  for (const row of data) {
1307
1301
  const category = String(row[categoryField] ?? "");
1308
- const value = Number(row[valueField] ?? 0);
1309
- if (!Number.isFinite(value)) continue;
1302
+ const value2 = Number(row[valueField] ?? 0);
1303
+ if (!Number.isFinite(value2)) continue;
1310
1304
  const bandY = yScale(category);
1311
1305
  if (bandY === void 0) continue;
1312
- const cx = xScale(value);
1306
+ const cx = xScale(value2);
1313
1307
  const cy = bandY + bandwidth / 2;
1314
- const color2 = isSequentialColor ? getSequentialColor(scales, value) : getColor(scales, "__default__");
1308
+ const color2 = isSequentialColor ? getSequentialColor(scales, value2) : getColor(scales, "__default__");
1315
1309
  const stemX = Math.min(baseline, cx);
1316
1310
  const stemWidth = Math.abs(cx - baseline);
1317
1311
  if (stemWidth > 0) {
@@ -1330,7 +1324,7 @@ function computeLollipopMarks(data, valueField, categoryField, xScale, yScale, b
1330
1324
  });
1331
1325
  }
1332
1326
  const dotAria = {
1333
- label: `${category}: ${value}`
1327
+ label: `${category}: ${value2}`
1334
1328
  };
1335
1329
  marks.push({
1336
1330
  type: "point",
@@ -1411,7 +1405,7 @@ var dotRenderer = (spec, scales, chartArea, strategy, _theme) => {
1411
1405
 
1412
1406
  // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/constant.js
1413
1407
  function constant_default(x2) {
1414
- return function constant() {
1408
+ return function constant2() {
1415
1409
  return x2;
1416
1410
  };
1417
1411
  }
@@ -1848,12 +1842,12 @@ function identity_default(d) {
1848
1842
 
1849
1843
  // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/pie.js
1850
1844
  function pie_default() {
1851
- var value = identity_default, sortValues = descending_default, sort = null, startAngle = constant_default(0), endAngle = constant_default(tau), padAngle = constant_default(0);
1845
+ var value2 = identity_default, sortValues = descending_default, sort = null, startAngle = constant_default(0), endAngle = constant_default(tau), padAngle = constant_default(0);
1852
1846
  function pie(data) {
1853
- var i, n = (data = array_default(data)).length, j, k, sum = 0, index = new Array(n), arcs = new Array(n), a0 = +startAngle.apply(this, arguments), da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)), a1, p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), pa = p * (da < 0 ? -1 : 1), v;
1847
+ var i, n = (data = array_default(data)).length, j, k, sum2 = 0, index = new Array(n), arcs = new Array(n), a0 = +startAngle.apply(this, arguments), da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)), a1, p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), pa = p * (da < 0 ? -1 : 1), v;
1854
1848
  for (i = 0; i < n; ++i) {
1855
- if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
1856
- sum += v;
1849
+ if ((v = arcs[index[i] = i] = +value2(data[i], i, data)) > 0) {
1850
+ sum2 += v;
1857
1851
  }
1858
1852
  }
1859
1853
  if (sortValues != null) index.sort(function(i2, j2) {
@@ -1862,7 +1856,7 @@ function pie_default() {
1862
1856
  else if (sort != null) index.sort(function(i2, j2) {
1863
1857
  return sort(data[i2], data[j2]);
1864
1858
  });
1865
- for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
1859
+ for (i = 0, k = sum2 ? (da - n * pa) / sum2 : 0; i < n; ++i, a0 = a1) {
1866
1860
  j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
1867
1861
  data: data[j],
1868
1862
  index: i,
@@ -1875,7 +1869,7 @@ function pie_default() {
1875
1869
  return arcs;
1876
1870
  }
1877
1871
  pie.value = function(_) {
1878
- return arguments.length ? (value = typeof _ === "function" ? _ : constant_default(+_), pie) : value;
1872
+ return arguments.length ? (value2 = typeof _ === "function" ? _ : constant_default(+_), pie) : value2;
1879
1873
  };
1880
1874
  pie.sortValues = function(_) {
1881
1875
  return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
@@ -2259,12 +2253,12 @@ function stackSeries(key) {
2259
2253
  return series;
2260
2254
  }
2261
2255
  function stack_default() {
2262
- var keys = constant_default([]), order = none_default2, offset = none_default, value = stackValue;
2256
+ var keys = constant_default([]), order = none_default2, offset = none_default, value2 = stackValue;
2263
2257
  function stack(data) {
2264
2258
  var sz = Array.from(keys.apply(this, arguments), stackSeries), i, n = sz.length, j = -1, oz;
2265
2259
  for (const d of data) {
2266
2260
  for (i = 0, ++j; i < n; ++i) {
2267
- (sz[i][j] = [0, +value(d, sz[i].key, j, data)]).data = d;
2261
+ (sz[i][j] = [0, +value2(d, sz[i].key, j, data)]).data = d;
2268
2262
  }
2269
2263
  }
2270
2264
  for (i = 0, oz = array_default(order(sz)); i < n; ++i) {
@@ -2277,7 +2271,7 @@ function stack_default() {
2277
2271
  return arguments.length ? (keys = typeof _ === "function" ? _ : constant_default(Array.from(_)), stack) : keys;
2278
2272
  };
2279
2273
  stack.value = function(_) {
2280
- return arguments.length ? (value = typeof _ === "function" ? _ : constant_default(+_), stack) : value;
2274
+ return arguments.length ? (value2 = typeof _ === "function" ? _ : constant_default(+_), stack) : value2;
2281
2275
  };
2282
2276
  stack.order = function(_) {
2283
2277
  return arguments.length ? (order = _ == null ? none_default2 : typeof _ === "function" ? _ : constant_default(Array.from(_)), stack) : order;
@@ -2701,7 +2695,7 @@ var DEFAULT_PALETTE = [
2701
2695
  "#858078"
2702
2696
  ];
2703
2697
  function groupSmallSlices(slices, threshold2) {
2704
- const total = slices.reduce((sum, s) => sum + s.value, 0);
2698
+ const total = slices.reduce((sum2, s) => sum2 + s.value, 0);
2705
2699
  if (total === 0) return slices;
2706
2700
  const big = [];
2707
2701
  let otherValue = 0;
@@ -2739,13 +2733,13 @@ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
2739
2733
  categoryRows.set(cat, row);
2740
2734
  }
2741
2735
  }
2742
- for (const [label, value] of categoryTotals) {
2736
+ for (const [label, value2] of categoryTotals) {
2743
2737
  slices.push({
2744
2738
  label,
2745
- value,
2739
+ value: value2,
2746
2740
  originalRow: categoryRows.get(label) ?? {
2747
2741
  [categoryField]: label,
2748
- [valueChannel.field]: value
2742
+ [valueChannel.field]: value2
2749
2743
  }
2750
2744
  });
2751
2745
  }
@@ -2769,8 +2763,8 @@ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
2769
2763
  const innerRadius = isDonut ? outerRadius * 0.6 : 0;
2770
2764
  const arcGenerator = arc_default().innerRadius(innerRadius).outerRadius(outerRadius);
2771
2765
  const marks = [];
2772
- const center = { x: centerX, y: centerY };
2773
- const total = slices.reduce((sum, s) => sum + s.value, 0);
2766
+ const center2 = { x: centerX, y: centerY };
2767
+ const total = slices.reduce((sum2, s) => sum2 + s.value, 0);
2774
2768
  for (let i = 0; i < arcs.length; i++) {
2775
2769
  const arcDatum = arcs[i];
2776
2770
  const slice2 = arcDatum.data;
@@ -2794,7 +2788,7 @@ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
2794
2788
  x: centroidResult[0] + centerX,
2795
2789
  y: centroidResult[1] + centerY
2796
2790
  },
2797
- center,
2791
+ center: center2,
2798
2792
  innerRadius,
2799
2793
  outerRadius,
2800
2794
  startAngle: arcDatum.startAngle,
@@ -3003,7 +2997,7 @@ function bisector(f) {
3003
2997
  compare2 = f;
3004
2998
  delta = f;
3005
2999
  }
3006
- function left(a, x2, lo = 0, hi = a.length) {
3000
+ function left2(a, x2, lo = 0, hi = a.length) {
3007
3001
  if (lo < hi) {
3008
3002
  if (compare1(x2, x2) !== 0) return hi;
3009
3003
  do {
@@ -3014,7 +3008,7 @@ function bisector(f) {
3014
3008
  }
3015
3009
  return lo;
3016
3010
  }
3017
- function right(a, x2, lo = 0, hi = a.length) {
3011
+ function right2(a, x2, lo = 0, hi = a.length) {
3018
3012
  if (lo < hi) {
3019
3013
  if (compare1(x2, x2) !== 0) return hi;
3020
3014
  do {
@@ -3025,11 +3019,11 @@ function bisector(f) {
3025
3019
  }
3026
3020
  return lo;
3027
3021
  }
3028
- function center(a, x2, lo = 0, hi = a.length) {
3029
- const i = left(a, x2, lo, hi - 1);
3022
+ function center2(a, x2, lo = 0, hi = a.length) {
3023
+ const i = left2(a, x2, lo, hi - 1);
3030
3024
  return i > lo && delta(a[i - 1], x2) > -delta(a[i], x2) ? i - 1 : i;
3031
3025
  }
3032
- return { left, center, right };
3026
+ return { left: left2, center: center2, right: right2 };
3033
3027
  }
3034
3028
  function zero() {
3035
3029
  return 0;
@@ -3049,33 +3043,33 @@ var bisect_default = bisectRight;
3049
3043
 
3050
3044
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/extent.js
3051
3045
  function extent(values, valueof) {
3052
- let min3;
3053
- let max3;
3046
+ let min4;
3047
+ let max4;
3054
3048
  if (valueof === void 0) {
3055
- for (const value of values) {
3056
- if (value != null) {
3057
- if (min3 === void 0) {
3058
- if (value >= value) min3 = max3 = value;
3049
+ for (const value2 of values) {
3050
+ if (value2 != null) {
3051
+ if (min4 === void 0) {
3052
+ if (value2 >= value2) min4 = max4 = value2;
3059
3053
  } else {
3060
- if (min3 > value) min3 = value;
3061
- if (max3 < value) max3 = value;
3054
+ if (min4 > value2) min4 = value2;
3055
+ if (max4 < value2) max4 = value2;
3062
3056
  }
3063
3057
  }
3064
3058
  }
3065
3059
  } else {
3066
3060
  let index = -1;
3067
- for (let value of values) {
3068
- if ((value = valueof(value, ++index, values)) != null) {
3069
- if (min3 === void 0) {
3070
- if (value >= value) min3 = max3 = value;
3061
+ for (let value2 of values) {
3062
+ if ((value2 = valueof(value2, ++index, values)) != null) {
3063
+ if (min4 === void 0) {
3064
+ if (value2 >= value2) min4 = max4 = value2;
3071
3065
  } else {
3072
- if (min3 > value) min3 = value;
3073
- if (max3 < value) max3 = value;
3066
+ if (min4 > value2) min4 = value2;
3067
+ if (max4 < value2) max4 = value2;
3074
3068
  }
3075
3069
  }
3076
3070
  }
3077
3071
  }
3078
- return [min3, max3];
3072
+ return [min4, max4];
3079
3073
  }
3080
3074
 
3081
3075
  // ../../node_modules/.bun/internmap@2.0.3/node_modules/internmap/src/index.js
@@ -3083,7 +3077,7 @@ var InternMap = class extends Map {
3083
3077
  constructor(entries, key = keyof) {
3084
3078
  super();
3085
3079
  Object.defineProperties(this, { _intern: { value: /* @__PURE__ */ new Map() }, _key: { value: key } });
3086
- if (entries != null) for (const [key2, value] of entries) this.set(key2, value);
3080
+ if (entries != null) for (const [key2, value2] of entries) this.set(key2, value2);
3087
3081
  }
3088
3082
  get(key) {
3089
3083
  return super.get(intern_get(this, key));
@@ -3091,33 +3085,33 @@ var InternMap = class extends Map {
3091
3085
  has(key) {
3092
3086
  return super.has(intern_get(this, key));
3093
3087
  }
3094
- set(key, value) {
3095
- return super.set(intern_set(this, key), value);
3088
+ set(key, value2) {
3089
+ return super.set(intern_set(this, key), value2);
3096
3090
  }
3097
3091
  delete(key) {
3098
3092
  return super.delete(intern_delete(this, key));
3099
3093
  }
3100
3094
  };
3101
- function intern_get({ _intern, _key }, value) {
3102
- const key = _key(value);
3103
- return _intern.has(key) ? _intern.get(key) : value;
3095
+ function intern_get({ _intern, _key }, value2) {
3096
+ const key = _key(value2);
3097
+ return _intern.has(key) ? _intern.get(key) : value2;
3104
3098
  }
3105
- function intern_set({ _intern, _key }, value) {
3106
- const key = _key(value);
3099
+ function intern_set({ _intern, _key }, value2) {
3100
+ const key = _key(value2);
3107
3101
  if (_intern.has(key)) return _intern.get(key);
3108
- _intern.set(key, value);
3109
- return value;
3102
+ _intern.set(key, value2);
3103
+ return value2;
3110
3104
  }
3111
- function intern_delete({ _intern, _key }, value) {
3112
- const key = _key(value);
3105
+ function intern_delete({ _intern, _key }, value2) {
3106
+ const key = _key(value2);
3113
3107
  if (_intern.has(key)) {
3114
- value = _intern.get(key);
3108
+ value2 = _intern.get(key);
3115
3109
  _intern.delete(key);
3116
3110
  }
3117
- return value;
3111
+ return value2;
3118
3112
  }
3119
- function keyof(value) {
3120
- return value !== null && typeof value === "object" ? value.valueOf() : value;
3113
+ function keyof(value2) {
3114
+ return value2 !== null && typeof value2 === "object" ? value2.valueOf() : value2;
3121
3115
  }
3122
3116
 
3123
3117
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/ticks.js
@@ -3172,42 +3166,42 @@ function tickStep(start, stop, count) {
3172
3166
 
3173
3167
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/max.js
3174
3168
  function max2(values, valueof) {
3175
- let max3;
3169
+ let max4;
3176
3170
  if (valueof === void 0) {
3177
- for (const value of values) {
3178
- if (value != null && (max3 < value || max3 === void 0 && value >= value)) {
3179
- max3 = value;
3171
+ for (const value2 of values) {
3172
+ if (value2 != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
3173
+ max4 = value2;
3180
3174
  }
3181
3175
  }
3182
3176
  } else {
3183
3177
  let index = -1;
3184
- for (let value of values) {
3185
- if ((value = valueof(value, ++index, values)) != null && (max3 < value || max3 === void 0 && value >= value)) {
3186
- max3 = value;
3178
+ for (let value2 of values) {
3179
+ if ((value2 = valueof(value2, ++index, values)) != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
3180
+ max4 = value2;
3187
3181
  }
3188
3182
  }
3189
3183
  }
3190
- return max3;
3184
+ return max4;
3191
3185
  }
3192
3186
 
3193
3187
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/min.js
3194
3188
  function min2(values, valueof) {
3195
- let min3;
3189
+ let min4;
3196
3190
  if (valueof === void 0) {
3197
- for (const value of values) {
3198
- if (value != null && (min3 > value || min3 === void 0 && value >= value)) {
3199
- min3 = value;
3191
+ for (const value2 of values) {
3192
+ if (value2 != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
3193
+ min4 = value2;
3200
3194
  }
3201
3195
  }
3202
3196
  } else {
3203
3197
  let index = -1;
3204
- for (let value of values) {
3205
- if ((value = valueof(value, ++index, values)) != null && (min3 > value || min3 === void 0 && value >= value)) {
3206
- min3 = value;
3198
+ for (let value2 of values) {
3199
+ if ((value2 = valueof(value2, ++index, values)) != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
3200
+ min4 = value2;
3207
3201
  }
3208
3202
  }
3209
3203
  }
3210
- return min3;
3204
+ return min4;
3211
3205
  }
3212
3206
 
3213
3207
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/quantile.js
@@ -3277,9 +3271,9 @@ function ordinal() {
3277
3271
  scale.domain = function(_) {
3278
3272
  if (!arguments.length) return domain.slice();
3279
3273
  domain = [], index = new InternMap();
3280
- for (const value of _) {
3281
- if (index.has(value)) continue;
3282
- index.set(value, domain.push(value) - 1);
3274
+ for (const value2 of _) {
3275
+ if (index.has(value2)) continue;
3276
+ index.set(value2, domain.push(value2) - 1);
3283
3277
  }
3284
3278
  return scale;
3285
3279
  };
@@ -3629,12 +3623,12 @@ function rgb_formatRgb() {
3629
3623
  function clampa(opacity) {
3630
3624
  return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity));
3631
3625
  }
3632
- function clampi(value) {
3633
- return Math.max(0, Math.min(255, Math.round(value) || 0));
3626
+ function clampi(value2) {
3627
+ return Math.max(0, Math.min(255, Math.round(value2) || 0));
3634
3628
  }
3635
- function hex(value) {
3636
- value = clampi(value);
3637
- return (value < 16 ? "0" : "") + value.toString(16);
3629
+ function hex(value2) {
3630
+ value2 = clampi(value2);
3631
+ return (value2 < 16 ? "0" : "") + value2.toString(16);
3638
3632
  }
3639
3633
  function hsla(h, s, l, a) {
3640
3634
  if (a <= 0) h = s = l = NaN;
@@ -3648,12 +3642,12 @@ function hslConvert(o) {
3648
3642
  if (!o) return new Hsl();
3649
3643
  if (o instanceof Hsl) return o;
3650
3644
  o = o.rgb();
3651
- var r = o.r / 255, g = o.g / 255, b = o.b / 255, min3 = Math.min(r, g, b), max3 = Math.max(r, g, b), h = NaN, s = max3 - min3, l = (max3 + min3) / 2;
3645
+ var r = o.r / 255, g = o.g / 255, b = o.b / 255, min4 = Math.min(r, g, b), max4 = Math.max(r, g, b), h = NaN, s = max4 - min4, l = (max4 + min4) / 2;
3652
3646
  if (s) {
3653
- if (r === max3) h = (g - b) / s + (g < b) * 6;
3654
- else if (g === max3) h = (b - r) / s + 2;
3647
+ if (r === max4) h = (g - b) / s + (g < b) * 6;
3648
+ else if (g === max4) h = (b - r) / s + 2;
3655
3649
  else h = (r - g) / s + 4;
3656
- s /= l < 0.5 ? max3 + min3 : 2 - max3 - min3;
3650
+ s /= l < 0.5 ? max4 + min4 : 2 - max4 - min4;
3657
3651
  h *= 60;
3658
3652
  } else {
3659
3653
  s = l > 0 && l < 1 ? 0 : h;
@@ -3698,12 +3692,12 @@ define_default(Hsl, hsl, extend(Color, {
3698
3692
  return `${a === 1 ? "hsl(" : "hsla("}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? ")" : `, ${a})`}`;
3699
3693
  }
3700
3694
  }));
3701
- function clamph(value) {
3702
- value = (value || 0) % 360;
3703
- return value < 0 ? value + 360 : value;
3695
+ function clamph(value2) {
3696
+ value2 = (value2 || 0) % 360;
3697
+ return value2 < 0 ? value2 + 360 : value2;
3704
3698
  }
3705
- function clampt(value) {
3706
- return Math.max(0, Math.min(1, value || 0));
3699
+ function clampt(value2) {
3700
+ return Math.max(0, Math.min(1, value2 || 0));
3707
3701
  }
3708
3702
  function hsl2rgb(h, m1, m2) {
3709
3703
  return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
@@ -4024,11 +4018,11 @@ function exponent_default(x2) {
4024
4018
 
4025
4019
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/formatGroup.js
4026
4020
  function formatGroup_default(grouping, thousands) {
4027
- return function(value, width) {
4028
- var i = value.length, t = [], j = 0, g = grouping[0], length = 0;
4021
+ return function(value2, width) {
4022
+ var i = value2.length, t = [], j = 0, g = grouping[0], length = 0;
4029
4023
  while (i > 0 && g > 0) {
4030
4024
  if (length + g + 1 > width) g = Math.max(1, width - length);
4031
- t.push(value.substring(i -= g, i + g));
4025
+ t.push(value2.substring(i -= g, i + g));
4032
4026
  if ((length += g + 1) > width) break;
4033
4027
  g = grouping[j = (j + 1) % grouping.length];
4034
4028
  }
@@ -4038,8 +4032,8 @@ function formatGroup_default(grouping, thousands) {
4038
4032
 
4039
4033
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/formatNumerals.js
4040
4034
  function formatNumerals_default(numerals) {
4041
- return function(value) {
4042
- return value.replace(/[0-9]/g, function(i) {
4035
+ return function(value2) {
4036
+ return value2.replace(/[0-9]/g, function(i) {
4043
4037
  return numerals[+i];
4044
4038
  });
4045
4039
  };
@@ -4153,58 +4147,58 @@ function locale_default(locale3) {
4153
4147
  var prefix = (options && options.prefix !== void 0 ? options.prefix : "") + (symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : ""), suffix = (symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "") + (options && options.suffix !== void 0 ? options.suffix : "");
4154
4148
  var formatType = formatTypes_default[type], maybeSuffix = /[defgprs%]/.test(type);
4155
4149
  precision = precision === void 0 ? 6 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));
4156
- function format2(value) {
4150
+ function format2(value2) {
4157
4151
  var valuePrefix = prefix, valueSuffix = suffix, i, n, c;
4158
4152
  if (type === "c") {
4159
- valueSuffix = formatType(value) + valueSuffix;
4160
- value = "";
4153
+ valueSuffix = formatType(value2) + valueSuffix;
4154
+ value2 = "";
4161
4155
  } else {
4162
- value = +value;
4163
- var valueNegative = value < 0 || 1 / value < 0;
4164
- value = isNaN(value) ? nan : formatType(Math.abs(value), precision);
4165
- if (trim) value = formatTrim_default(value);
4166
- if (valueNegative && +value === 0 && sign2 !== "+") valueNegative = false;
4156
+ value2 = +value2;
4157
+ var valueNegative = value2 < 0 || 1 / value2 < 0;
4158
+ value2 = isNaN(value2) ? nan : formatType(Math.abs(value2), precision);
4159
+ if (trim) value2 = formatTrim_default(value2);
4160
+ if (valueNegative && +value2 === 0 && sign2 !== "+") valueNegative = false;
4167
4161
  valuePrefix = (valueNegative ? sign2 === "(" ? sign2 : minus : sign2 === "-" || sign2 === "(" ? "" : sign2) + valuePrefix;
4168
- valueSuffix = (type === "s" && !isNaN(value) && prefixExponent !== void 0 ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign2 === "(" ? ")" : "");
4162
+ valueSuffix = (type === "s" && !isNaN(value2) && prefixExponent !== void 0 ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign2 === "(" ? ")" : "");
4169
4163
  if (maybeSuffix) {
4170
- i = -1, n = value.length;
4164
+ i = -1, n = value2.length;
4171
4165
  while (++i < n) {
4172
- if (c = value.charCodeAt(i), 48 > c || c > 57) {
4173
- valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
4174
- value = value.slice(0, i);
4166
+ if (c = value2.charCodeAt(i), 48 > c || c > 57) {
4167
+ valueSuffix = (c === 46 ? decimal + value2.slice(i + 1) : value2.slice(i)) + valueSuffix;
4168
+ value2 = value2.slice(0, i);
4175
4169
  break;
4176
4170
  }
4177
4171
  }
4178
4172
  }
4179
4173
  }
4180
- if (comma && !zero3) value = group(value, Infinity);
4181
- var length = valuePrefix.length + value.length + valueSuffix.length, padding = length < width ? new Array(width - length + 1).join(fill) : "";
4182
- if (comma && zero3) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
4174
+ if (comma && !zero3) value2 = group(value2, Infinity);
4175
+ var length = valuePrefix.length + value2.length + valueSuffix.length, padding = length < width ? new Array(width - length + 1).join(fill) : "";
4176
+ if (comma && zero3) value2 = group(padding + value2, padding.length ? width - valueSuffix.length : Infinity), padding = "";
4183
4177
  switch (align) {
4184
4178
  case "<":
4185
- value = valuePrefix + value + valueSuffix + padding;
4179
+ value2 = valuePrefix + value2 + valueSuffix + padding;
4186
4180
  break;
4187
4181
  case "=":
4188
- value = valuePrefix + padding + value + valueSuffix;
4182
+ value2 = valuePrefix + padding + value2 + valueSuffix;
4189
4183
  break;
4190
4184
  case "^":
4191
- value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
4185
+ value2 = padding.slice(0, length = padding.length >> 1) + valuePrefix + value2 + valueSuffix + padding.slice(length);
4192
4186
  break;
4193
4187
  default:
4194
- value = padding + valuePrefix + value + valueSuffix;
4188
+ value2 = padding + valuePrefix + value2 + valueSuffix;
4195
4189
  break;
4196
4190
  }
4197
- return numerals(value);
4191
+ return numerals(value2);
4198
4192
  }
4199
4193
  format2.toString = function() {
4200
4194
  return specifier + "";
4201
4195
  };
4202
4196
  return format2;
4203
4197
  }
4204
- function formatPrefix2(specifier, value) {
4205
- var e = Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3, k = Math.pow(10, -e), f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier), { suffix: prefixes[8 + e / 3] });
4206
- return function(value2) {
4207
- return f(k * value2);
4198
+ function formatPrefix2(specifier, value2) {
4199
+ var e = Math.max(-8, Math.min(8, Math.floor(exponent_default(value2) / 3))) * 3, k = Math.pow(10, -e), f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier), { suffix: prefixes[8 + e / 3] });
4200
+ return function(value3) {
4201
+ return f(k * value3);
4208
4202
  };
4209
4203
  }
4210
4204
  return {
@@ -4235,14 +4229,14 @@ function precisionFixed_default(step) {
4235
4229
  }
4236
4230
 
4237
4231
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/precisionPrefix.js
4238
- function precisionPrefix_default(step, value) {
4239
- return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3 - exponent_default(Math.abs(step)));
4232
+ function precisionPrefix_default(step, value2) {
4233
+ return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent_default(value2) / 3))) * 3 - exponent_default(Math.abs(step)));
4240
4234
  }
4241
4235
 
4242
4236
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/precisionRound.js
4243
- function precisionRound_default(step, max3) {
4244
- step = Math.abs(step), max3 = Math.abs(max3) - step;
4245
- return Math.max(0, exponent_default(max3) - exponent_default(step)) + 1;
4237
+ function precisionRound_default(step, max4) {
4238
+ step = Math.abs(step), max4 = Math.abs(max4) - step;
4239
+ return Math.max(0, exponent_default(max4) - exponent_default(step)) + 1;
4246
4240
  }
4247
4241
 
4248
4242
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/tickFormat.js
@@ -4251,9 +4245,9 @@ function tickFormat(start, stop, count, specifier) {
4251
4245
  specifier = formatSpecifier(specifier == null ? ",f" : specifier);
4252
4246
  switch (specifier.type) {
4253
4247
  case "s": {
4254
- var value = Math.max(Math.abs(start), Math.abs(stop));
4255
- if (specifier.precision == null && !isNaN(precision = precisionPrefix_default(step, value))) specifier.precision = precision;
4256
- return formatPrefix(specifier, value);
4248
+ var value2 = Math.max(Math.abs(start), Math.abs(stop));
4249
+ if (specifier.precision == null && !isNaN(precision = precisionPrefix_default(step, value2))) specifier.precision = precision;
4250
+ return formatPrefix(specifier, value2);
4257
4251
  }
4258
4252
  case "":
4259
4253
  case "e":
@@ -5252,8 +5246,8 @@ var pads = { "-": "", "_": " ", "0": "0" };
5252
5246
  var numberRe = /^\s*\d+/;
5253
5247
  var percentRe = /^%/;
5254
5248
  var requoteRe = /[\\^$*+?|[\]().{}]/g;
5255
- function pad(value, fill, width) {
5256
- var sign2 = value < 0 ? "-" : "", string = (sign2 ? -value : value) + "", length = string.length;
5249
+ function pad(value2, fill, width) {
5250
+ var sign2 = value2 < 0 ? "-" : "", string = (sign2 ? -value2 : value2) + "", length = string.length;
5257
5251
  return sign2 + (length < width ? new Array(width - length + 1).join(fill) + string : string);
5258
5252
  }
5259
5253
  function requote(s) {
@@ -5604,11 +5598,11 @@ function sequential() {
5604
5598
  var DEFAULT_POINT_RADIUS2 = 5;
5605
5599
  var MIN_BUBBLE_RADIUS = 3;
5606
5600
  var MAX_BUBBLE_RADIUS = 30;
5607
- function resolvePosition2(value, channelType, scale) {
5601
+ function resolvePosition2(value2, channelType, scale) {
5608
5602
  switch (channelType) {
5609
5603
  case "nominal":
5610
5604
  case "ordinal": {
5611
- const s = String(value);
5605
+ const s = String(value2);
5612
5606
  if ("bandwidth" in scale && typeof scale.bandwidth === "function") {
5613
5607
  const bw = scale.bandwidth();
5614
5608
  const pos = scale(s);
@@ -5618,11 +5612,11 @@ function resolvePosition2(value, channelType, scale) {
5618
5612
  return scale(s);
5619
5613
  }
5620
5614
  case "temporal": {
5621
- const px = scale(new Date(value));
5615
+ const px = scale(new Date(value2));
5622
5616
  return Number.isNaN(px) ? void 0 : px;
5623
5617
  }
5624
5618
  default: {
5625
- const num = Number(value);
5619
+ const num = Number(value2);
5626
5620
  if (!Number.isFinite(num)) return void 0;
5627
5621
  return scale(num);
5628
5622
  }
@@ -5855,14 +5849,15 @@ import {
5855
5849
  isChartSpec,
5856
5850
  isGraphSpec,
5857
5851
  isLayerSpec,
5852
+ isSankeySpec,
5858
5853
  isTableSpec,
5859
5854
  resolveMarkDef,
5860
5855
  resolveMarkType
5861
5856
  } from "@opendata-ai/openchart-core";
5862
- function normalizeChromeField(value) {
5863
- if (value === void 0) return void 0;
5864
- if (typeof value === "string") return { text: value };
5865
- return value;
5857
+ function normalizeChromeField(value2) {
5858
+ if (value2 === void 0) return void 0;
5859
+ if (typeof value2 === "string") return { text: value2 };
5860
+ return value2;
5866
5861
  }
5867
5862
  function normalizeChrome(chrome) {
5868
5863
  if (!chrome) return {};
@@ -5880,26 +5875,26 @@ function inferFieldType(data, field) {
5880
5875
  let dateCount = 0;
5881
5876
  let totalNonNull = 0;
5882
5877
  for (let i = 0; i < sampleSize; i++) {
5883
- const value = data[i][field];
5884
- if (value == null) continue;
5878
+ const value2 = data[i][field];
5879
+ if (value2 == null) continue;
5885
5880
  totalNonNull++;
5886
- if (typeof value === "number" && Number.isFinite(value)) {
5881
+ if (typeof value2 === "number" && Number.isFinite(value2)) {
5887
5882
  numericCount++;
5888
5883
  continue;
5889
5884
  }
5890
- if (typeof value === "string") {
5891
- const num = Number(value);
5892
- if (!Number.isNaN(num) && Number.isFinite(num) && value.trim() !== "") {
5885
+ if (typeof value2 === "string") {
5886
+ const num = Number(value2);
5887
+ if (!Number.isNaN(num) && Number.isFinite(num) && value2.trim() !== "") {
5893
5888
  numericCount++;
5894
5889
  continue;
5895
5890
  }
5896
- const date2 = new Date(value);
5891
+ const date2 = new Date(value2);
5897
5892
  if (!Number.isNaN(date2.getTime())) {
5898
5893
  dateCount++;
5899
5894
  continue;
5900
5895
  }
5901
5896
  }
5902
- if (value instanceof Date && !Number.isNaN(value.getTime())) {
5897
+ if (value2 instanceof Date && !Number.isNaN(value2.getTime())) {
5903
5898
  dateCount++;
5904
5899
  }
5905
5900
  }
@@ -6003,6 +5998,23 @@ function normalizeTableSpec(spec, _warnings) {
6003
5998
  animation: spec.animation
6004
5999
  };
6005
6000
  }
6001
+ function normalizeSankeySpec(spec, _warnings) {
6002
+ return {
6003
+ type: "sankey",
6004
+ data: spec.data,
6005
+ encoding: spec.encoding,
6006
+ nodeWidth: spec.nodeWidth ?? 12,
6007
+ nodePadding: spec.nodePadding ?? 16,
6008
+ nodeAlign: spec.nodeAlign ?? "justify",
6009
+ iterations: spec.iterations ?? 6,
6010
+ linkStyle: spec.linkStyle ?? "gradient",
6011
+ chrome: normalizeChrome(spec.chrome),
6012
+ legend: spec.legend,
6013
+ theme: spec.theme ?? {},
6014
+ darkMode: spec.darkMode ?? "off",
6015
+ animation: spec.animation
6016
+ };
6017
+ }
6006
6018
  function normalizeGraphSpec(spec, _warnings) {
6007
6019
  const defaultLayout = {
6008
6020
  type: "force",
@@ -6043,8 +6055,11 @@ function normalizeSpec(spec, warnings = []) {
6043
6055
  if (isGraphSpec(spec)) {
6044
6056
  return normalizeGraphSpec(spec, warnings);
6045
6057
  }
6058
+ if (isSankeySpec(spec)) {
6059
+ return normalizeSankeySpec(spec, warnings);
6060
+ }
6046
6061
  throw new Error(
6047
- `Unknown spec shape. Expected mark (chart), layer, type: 'table', or type: 'graph'.`
6062
+ `Unknown spec shape. Expected mark (chart), layer, type: 'table', type: 'graph', or type: 'sankey'.`
6048
6063
  );
6049
6064
  }
6050
6065
  function flattenLayers(spec, parentData, parentEncoding, parentTransforms) {
@@ -6077,19 +6092,19 @@ import {
6077
6092
  } from "@opendata-ai/openchart-core";
6078
6093
  var VALID_FIELD_TYPES = /* @__PURE__ */ new Set(["quantitative", "temporal", "nominal", "ordinal"]);
6079
6094
  var VALID_DARK_MODES = /* @__PURE__ */ new Set(["auto", "force", "off"]);
6080
- function isParseableDate(value) {
6081
- if (value instanceof Date) return !Number.isNaN(value.getTime());
6082
- if (typeof value === "string") {
6083
- const d = new Date(value);
6095
+ function isParseableDate(value2) {
6096
+ if (value2 instanceof Date) return !Number.isNaN(value2.getTime());
6097
+ if (typeof value2 === "string") {
6098
+ const d = new Date(value2);
6084
6099
  return !Number.isNaN(d.getTime());
6085
6100
  }
6086
- if (typeof value === "number") return true;
6101
+ if (typeof value2 === "number") return true;
6087
6102
  return false;
6088
6103
  }
6089
- function isNumeric(value) {
6090
- if (typeof value === "number") return Number.isFinite(value);
6091
- if (typeof value === "string") {
6092
- const n = Number(value);
6104
+ function isNumeric(value2) {
6105
+ if (typeof value2 === "number") return Number.isFinite(value2);
6106
+ if (typeof value2 === "string") {
6107
+ const n = Number(value2);
6093
6108
  return !Number.isNaN(n) && Number.isFinite(n);
6094
6109
  }
6095
6110
  return false;
@@ -6504,6 +6519,85 @@ function validateGraphSpec(spec, errors) {
6504
6519
  }
6505
6520
  }
6506
6521
  }
6522
+ function validateSankeySpec(spec, errors) {
6523
+ if (!Array.isArray(spec.data)) {
6524
+ errors.push({
6525
+ message: 'Spec error: sankey spec requires a "data" array',
6526
+ path: "data",
6527
+ code: "INVALID_TYPE",
6528
+ suggestion: 'Provide data as an array of objects, e.g. data: [{ source: "A", target: "B", value: 10 }]'
6529
+ });
6530
+ return;
6531
+ }
6532
+ if (spec.data.length === 0) {
6533
+ errors.push({
6534
+ message: 'Spec error: "data" must be a non-empty array',
6535
+ path: "data",
6536
+ code: "EMPTY_DATA",
6537
+ suggestion: 'Add at least one data row, e.g. data: [{ source: "A", target: "B", value: 10 }]'
6538
+ });
6539
+ return;
6540
+ }
6541
+ const firstRow = spec.data[0];
6542
+ if (typeof firstRow !== "object" || firstRow === null || Array.isArray(firstRow)) {
6543
+ errors.push({
6544
+ message: 'Spec error: each item in "data" must be a plain object',
6545
+ path: "data[0]",
6546
+ code: "INVALID_TYPE",
6547
+ suggestion: 'Each data item should be an object, e.g. { source: "A", target: "B", value: 10 }'
6548
+ });
6549
+ return;
6550
+ }
6551
+ if (!spec.encoding || typeof spec.encoding !== "object") {
6552
+ errors.push({
6553
+ message: 'Spec error: sankey spec requires an "encoding" object with source, target, and value channels',
6554
+ path: "encoding",
6555
+ code: "MISSING_FIELD",
6556
+ suggestion: 'Add an encoding object, e.g. encoding: { source: { field: "source", type: "nominal" }, target: { field: "target", type: "nominal" }, value: { field: "value", type: "quantitative" } }'
6557
+ });
6558
+ return;
6559
+ }
6560
+ const encoding = spec.encoding;
6561
+ const dataColumns = new Set(Object.keys(firstRow));
6562
+ const availableColumns = [...dataColumns].join(", ");
6563
+ for (const channel of ["source", "target", "value"]) {
6564
+ const ch = encoding[channel];
6565
+ if (!ch || typeof ch !== "object") {
6566
+ errors.push({
6567
+ message: `Spec error: sankey encoding requires "${channel}" channel`,
6568
+ path: `encoding.${channel}`,
6569
+ code: "MISSING_FIELD",
6570
+ suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${[...dataColumns][0] ?? "myField"}", type: "${channel === "value" ? "quantitative" : "nominal"}" }`
6571
+ });
6572
+ continue;
6573
+ }
6574
+ if (!ch.field || typeof ch.field !== "string") {
6575
+ errors.push({
6576
+ message: `Spec error: encoding.${channel} must have a "field" string`,
6577
+ path: `encoding.${channel}.field`,
6578
+ code: "MISSING_FIELD",
6579
+ suggestion: `Add a field name from your data columns: ${availableColumns}`
6580
+ });
6581
+ continue;
6582
+ }
6583
+ if (!dataColumns.has(ch.field)) {
6584
+ errors.push({
6585
+ message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist in data. Available columns: ${availableColumns}`,
6586
+ path: `encoding.${channel}.field`,
6587
+ code: "DATA_FIELD_MISSING",
6588
+ suggestion: `Use one of the available data columns: ${availableColumns}`
6589
+ });
6590
+ }
6591
+ }
6592
+ if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
6593
+ errors.push({
6594
+ message: 'Spec error: darkMode must be "auto", "force", or "off"',
6595
+ path: "darkMode",
6596
+ code: "INVALID_VALUE",
6597
+ suggestion: 'Use one of: "auto" (system preference), "force" (always dark), or "off" (always light)'
6598
+ });
6599
+ }
6600
+ }
6507
6601
  function validateLayerSpec(spec, errors) {
6508
6602
  const layer = spec.layer;
6509
6603
  if (layer.length === 0) {
@@ -6597,17 +6691,18 @@ function validateSpec(spec) {
6597
6691
  const hasMark = "mark" in obj;
6598
6692
  const isTable = obj.type === "table";
6599
6693
  const isGraph = obj.type === "graph";
6600
- const isLayer = hasLayer && !isTable && !isGraph;
6601
- const isChart = hasMark && !hasLayer && !isTable && !isGraph;
6602
- if (!isChart && !isTable && !isGraph && !isLayer) {
6694
+ const isSankey = obj.type === "sankey";
6695
+ const isLayer = hasLayer && !isTable && !isGraph && !isSankey;
6696
+ const isChart = hasMark && !hasLayer && !isTable && !isGraph && !isSankey;
6697
+ if (!isChart && !isTable && !isGraph && !isSankey && !isLayer) {
6603
6698
  return {
6604
6699
  valid: false,
6605
6700
  errors: [
6606
6701
  {
6607
- message: 'Spec error: spec must have a "mark" field for charts, a "layer" array for layered charts, or a "type" field for tables/graphs',
6702
+ message: 'Spec error: spec must have a "mark" field for charts, a "layer" array for layered charts, or a "type" field for tables/graphs/sankey',
6608
6703
  path: "mark",
6609
6704
  code: "MISSING_FIELD",
6610
- suggestion: `Add a "mark" field for charts (e.g. mark: "bar"), a "layer" array for layered charts, or a "type" field for tables/graphs (type: "table" or type: "graph"). Valid mark types: ${[...MARK_TYPES].join(", ")}`
6705
+ suggestion: `Add a "mark" field for charts (e.g. mark: "bar"), a "layer" array for layered charts, or a "type" field for tables/graphs/sankey (type: "table", type: "graph", or type: "sankey"). Valid mark types: ${[...MARK_TYPES].join(", ")}`
6611
6706
  }
6612
6707
  ],
6613
6708
  normalized: null
@@ -6643,6 +6738,8 @@ function validateSpec(spec) {
6643
6738
  validateTableSpec(obj, errors);
6644
6739
  } else if (isGraph) {
6645
6740
  validateGraphSpec(obj, errors);
6741
+ } else if (isSankey) {
6742
+ validateSankeySpec(obj, errors);
6646
6743
  }
6647
6744
  if (errors.length > 0) {
6648
6745
  return { valid: false, errors, normalized: null };
@@ -6929,8 +7026,8 @@ function resolveEdgeVisuals(edges, encoding, theme) {
6929
7026
  function assignCommunities(nodes, clusteringField) {
6930
7027
  if (!clusteringField) return;
6931
7028
  for (const node of nodes) {
6932
- const value = node.data[clusteringField];
6933
- node.community = value != null ? String(value) : void 0;
7029
+ const value2 = node.data[clusteringField];
7030
+ node.community = value2 != null ? String(value2) : void 0;
6934
7031
  }
6935
7032
  }
6936
7033
  function buildCommunityColorMap(nodes, theme) {
@@ -7017,12 +7114,12 @@ function buildGraphTooltips(nodes) {
7017
7114
  color: node.fill
7018
7115
  });
7019
7116
  }
7020
- for (const [key, value] of Object.entries(node.data)) {
7117
+ for (const [key, value2] of Object.entries(node.data)) {
7021
7118
  if (key === "id") continue;
7022
- if (value == null) continue;
7119
+ if (value2 == null) continue;
7023
7120
  fields.push({
7024
7121
  label: key,
7025
- value: typeof value === "number" ? value.toLocaleString() : String(value)
7122
+ value: typeof value2 === "number" ? value2.toLocaleString() : String(value2)
7026
7123
  });
7027
7124
  }
7028
7125
  descriptors.set(node.id, {
@@ -7191,19 +7288,19 @@ function continuousTicks(resolvedScale, density) {
7191
7288
  const scale = resolvedScale.scale;
7192
7289
  if (!("ticks" in scale) || typeof scale.ticks !== "function") {
7193
7290
  const domain = scale.domain();
7194
- return domain.map((value) => ({
7195
- value,
7196
- position: scale(value),
7197
- label: formatTickLabel(value, resolvedScale)
7291
+ return domain.map((value2) => ({
7292
+ value: value2,
7293
+ position: scale(value2),
7294
+ label: formatTickLabel(value2, resolvedScale)
7198
7295
  }));
7199
7296
  }
7200
7297
  const explicitCount = resolvedScale.channel.axis?.tickCount;
7201
7298
  const count = explicitCount ?? TICK_COUNTS[density];
7202
7299
  const rawTicks = scale.ticks(count);
7203
- const ticks2 = rawTicks.map((value) => ({
7204
- value,
7205
- position: scale(value),
7206
- label: formatTickLabel(value, resolvedScale)
7300
+ const ticks2 = rawTicks.map((value2) => ({
7301
+ value: value2,
7302
+ position: scale(value2),
7303
+ label: formatTickLabel(value2, resolvedScale)
7207
7304
  }));
7208
7305
  return ticks2;
7209
7306
  }
@@ -7217,13 +7314,13 @@ function categoricalTicks(resolvedScale, density) {
7217
7314
  const step = Math.ceil(domain.length / maxTicks);
7218
7315
  selectedValues = domain.filter((_, i) => i % step === 0);
7219
7316
  }
7220
- const ticks2 = selectedValues.map((value) => {
7317
+ const ticks2 = selectedValues.map((value2) => {
7221
7318
  const bandScale = resolvedScale.type === "band" ? scale : null;
7222
- const pos = bandScale ? (bandScale(value) ?? 0) + bandScale.bandwidth() / 2 : scale(value) ?? 0;
7319
+ const pos = bandScale ? (bandScale(value2) ?? 0) + bandScale.bandwidth() / 2 : scale(value2) ?? 0;
7223
7320
  return {
7224
- value,
7321
+ value: value2,
7225
7322
  position: pos,
7226
- label: value
7323
+ label: value2
7227
7324
  };
7228
7325
  });
7229
7326
  return ticks2;
@@ -7239,16 +7336,16 @@ var NUMERIC_SCALE_TYPES = /* @__PURE__ */ new Set([
7239
7336
  "threshold"
7240
7337
  ]);
7241
7338
  var TEMPORAL_SCALE_TYPES = /* @__PURE__ */ new Set(["time", "utc"]);
7242
- function formatTickLabel(value, resolvedScale) {
7339
+ function formatTickLabel(value2, resolvedScale) {
7243
7340
  const formatStr = resolvedScale.channel.axis?.format;
7244
7341
  if (TEMPORAL_SCALE_TYPES.has(resolvedScale.type)) {
7245
7342
  const temporalFmt = buildTemporalFormatter(formatStr);
7246
- if (temporalFmt) return temporalFmt(value);
7343
+ if (temporalFmt) return temporalFmt(value2);
7247
7344
  const useUtc = resolvedScale.type === "utc";
7248
- return formatDate(value, void 0, void 0, useUtc);
7345
+ return formatDate(value2, void 0, void 0, useUtc);
7249
7346
  }
7250
7347
  if (NUMERIC_SCALE_TYPES.has(resolvedScale.type)) {
7251
- const num = value;
7348
+ const num = value2;
7252
7349
  if (formatStr) {
7253
7350
  const fmt = buildD3Formatter3(formatStr);
7254
7351
  if (fmt) return fmt(num);
@@ -7256,26 +7353,26 @@ function formatTickLabel(value, resolvedScale) {
7256
7353
  if (Math.abs(num) >= 1e3) return abbreviateNumber3(num);
7257
7354
  return formatNumber3(num);
7258
7355
  }
7259
- return String(value);
7356
+ return String(value2);
7260
7357
  }
7261
7358
  function resolveExplicitTicks(values, resolvedScale) {
7262
7359
  const scale = resolvedScale.scale;
7263
- return values.map((value) => {
7360
+ return values.map((value2) => {
7264
7361
  let position;
7265
7362
  if (TEMPORAL_SCALE_TYPES.has(resolvedScale.type)) {
7266
- const d = value instanceof Date ? value : new Date(String(value));
7363
+ const d = value2 instanceof Date ? value2 : new Date(String(value2));
7267
7364
  position = scale(d);
7268
7365
  } else if (resolvedScale.type === "band" || resolvedScale.type === "point" || resolvedScale.type === "ordinal") {
7269
- const s = String(value);
7366
+ const s = String(value2);
7270
7367
  const bandScale = resolvedScale.type === "band" ? scale : null;
7271
7368
  position = bandScale ? (bandScale(s) ?? 0) + bandScale.bandwidth() / 2 : scale(s) ?? 0;
7272
7369
  } else {
7273
- position = scale(value);
7370
+ position = scale(value2);
7274
7371
  }
7275
7372
  return {
7276
- value,
7373
+ value: value2,
7277
7374
  position,
7278
- label: formatTickLabel(value, resolvedScale)
7375
+ label: formatTickLabel(value2, resolvedScale)
7279
7376
  };
7280
7377
  });
7281
7378
  }
@@ -7486,7 +7583,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy) {
7486
7583
  }
7487
7584
  }
7488
7585
  }
7489
- if (spec.annotations.length > 0 && encoding.x) {
7586
+ if (strategy?.annotationPosition !== "tooltip-only" && spec.annotations.length > 0 && encoding.x) {
7490
7587
  const xField = encoding.x.field;
7491
7588
  let maxX;
7492
7589
  for (const row of spec.data) {
@@ -8033,8 +8130,8 @@ function extractColorEntries(spec, theme) {
8033
8130
  const uniqueValues = [...new Set(spec.data.map((d) => String(d[colorEnc.field])))];
8034
8131
  const palette = theme.colors.categorical;
8035
8132
  const shape = swatchShapeForType(spec.markType);
8036
- return uniqueValues.map((value, i) => ({
8037
- label: value,
8133
+ return uniqueValues.map((value2, i) => ({
8134
+ label: value2,
8038
8135
  color: palette[i % palette.length],
8039
8136
  shape,
8040
8137
  active: true
@@ -8162,9 +8259,9 @@ function computeLegend(spec, strategy, theme, chartArea) {
8162
8259
  if (maxFit < entries.length) {
8163
8260
  entries = truncateEntries(entries, maxFit);
8164
8261
  }
8165
- const totalWidth = entries.reduce((sum, entry) => {
8262
+ const totalWidth = entries.reduce((sum2, entry) => {
8166
8263
  const labelWidth = estimateTextWidth9(entry.label, labelStyle.fontSize, labelStyle.fontWeight);
8167
- return sum + SWATCH_SIZE2 + SWATCH_GAP2 + labelWidth + ENTRY_GAP2;
8264
+ return sum2 + SWATCH_SIZE2 + SWATCH_GAP2 + labelWidth + ENTRY_GAP2;
8168
8265
  }, 0);
8169
8266
  let rowCount = 1;
8170
8267
  let rowWidth = 0;
@@ -8198,15 +8295,879 @@ function computeLegend(spec, strategy, theme, chartArea) {
8198
8295
  };
8199
8296
  }
8200
8297
 
8298
+ // src/sankey/compile-sankey.ts
8299
+ import {
8300
+ adaptTheme as adaptTheme2,
8301
+ computeChrome as computeChrome3,
8302
+ estimateTextWidth as estimateTextWidth10,
8303
+ formatNumber as formatNumber4,
8304
+ resolveTheme as resolveTheme2
8305
+ } from "@opendata-ai/openchart-core";
8306
+
8307
+ // ../../node_modules/.bun/d3-array@2.12.1/node_modules/d3-array/src/max.js
8308
+ function max3(values, valueof) {
8309
+ let max4;
8310
+ if (valueof === void 0) {
8311
+ for (const value2 of values) {
8312
+ if (value2 != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
8313
+ max4 = value2;
8314
+ }
8315
+ }
8316
+ } else {
8317
+ let index = -1;
8318
+ for (let value2 of values) {
8319
+ if ((value2 = valueof(value2, ++index, values)) != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
8320
+ max4 = value2;
8321
+ }
8322
+ }
8323
+ }
8324
+ return max4;
8325
+ }
8326
+
8327
+ // ../../node_modules/.bun/d3-array@2.12.1/node_modules/d3-array/src/min.js
8328
+ function min3(values, valueof) {
8329
+ let min4;
8330
+ if (valueof === void 0) {
8331
+ for (const value2 of values) {
8332
+ if (value2 != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
8333
+ min4 = value2;
8334
+ }
8335
+ }
8336
+ } else {
8337
+ let index = -1;
8338
+ for (let value2 of values) {
8339
+ if ((value2 = valueof(value2, ++index, values)) != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
8340
+ min4 = value2;
8341
+ }
8342
+ }
8343
+ }
8344
+ return min4;
8345
+ }
8346
+
8347
+ // ../../node_modules/.bun/d3-array@2.12.1/node_modules/d3-array/src/sum.js
8348
+ function sum(values, valueof) {
8349
+ let sum2 = 0;
8350
+ if (valueof === void 0) {
8351
+ for (let value2 of values) {
8352
+ if (value2 = +value2) {
8353
+ sum2 += value2;
8354
+ }
8355
+ }
8356
+ } else {
8357
+ let index = -1;
8358
+ for (let value2 of values) {
8359
+ if (value2 = +valueof(value2, ++index, values)) {
8360
+ sum2 += value2;
8361
+ }
8362
+ }
8363
+ }
8364
+ return sum2;
8365
+ }
8366
+
8367
+ // ../../node_modules/.bun/d3-sankey@0.12.3/node_modules/d3-sankey/src/align.js
8368
+ function targetDepth(d) {
8369
+ return d.target.depth;
8370
+ }
8371
+ function left(node) {
8372
+ return node.depth;
8373
+ }
8374
+ function right(node, n) {
8375
+ return n - 1 - node.height;
8376
+ }
8377
+ function justify(node, n) {
8378
+ return node.sourceLinks.length ? node.depth : n - 1;
8379
+ }
8380
+ function center(node) {
8381
+ return node.targetLinks.length ? node.depth : node.sourceLinks.length ? min3(node.sourceLinks, targetDepth) - 1 : 0;
8382
+ }
8383
+
8384
+ // ../../node_modules/.bun/d3-sankey@0.12.3/node_modules/d3-sankey/src/constant.js
8385
+ function constant(x2) {
8386
+ return function() {
8387
+ return x2;
8388
+ };
8389
+ }
8390
+
8391
+ // ../../node_modules/.bun/d3-sankey@0.12.3/node_modules/d3-sankey/src/sankey.js
8392
+ function ascendingSourceBreadth(a, b) {
8393
+ return ascendingBreadth(a.source, b.source) || a.index - b.index;
8394
+ }
8395
+ function ascendingTargetBreadth(a, b) {
8396
+ return ascendingBreadth(a.target, b.target) || a.index - b.index;
8397
+ }
8398
+ function ascendingBreadth(a, b) {
8399
+ return a.y0 - b.y0;
8400
+ }
8401
+ function value(d) {
8402
+ return d.value;
8403
+ }
8404
+ function defaultId(d) {
8405
+ return d.index;
8406
+ }
8407
+ function defaultNodes(graph) {
8408
+ return graph.nodes;
8409
+ }
8410
+ function defaultLinks(graph) {
8411
+ return graph.links;
8412
+ }
8413
+ function find(nodeById, id) {
8414
+ const node = nodeById.get(id);
8415
+ if (!node) throw new Error("missing: " + id);
8416
+ return node;
8417
+ }
8418
+ function computeLinkBreadths({ nodes }) {
8419
+ for (const node of nodes) {
8420
+ let y0 = node.y0;
8421
+ let y1 = y0;
8422
+ for (const link of node.sourceLinks) {
8423
+ link.y0 = y0 + link.width / 2;
8424
+ y0 += link.width;
8425
+ }
8426
+ for (const link of node.targetLinks) {
8427
+ link.y1 = y1 + link.width / 2;
8428
+ y1 += link.width;
8429
+ }
8430
+ }
8431
+ }
8432
+ function Sankey() {
8433
+ let x0 = 0, y0 = 0, x1 = 1, y1 = 1;
8434
+ let dx = 24;
8435
+ let dy = 8, py;
8436
+ let id = defaultId;
8437
+ let align = justify;
8438
+ let sort;
8439
+ let linkSort;
8440
+ let nodes = defaultNodes;
8441
+ let links = defaultLinks;
8442
+ let iterations = 6;
8443
+ function sankey() {
8444
+ const graph = { nodes: nodes.apply(null, arguments), links: links.apply(null, arguments) };
8445
+ computeNodeLinks(graph);
8446
+ computeNodeValues(graph);
8447
+ computeNodeDepths(graph);
8448
+ computeNodeHeights(graph);
8449
+ computeNodeBreadths(graph);
8450
+ computeLinkBreadths(graph);
8451
+ return graph;
8452
+ }
8453
+ sankey.update = function(graph) {
8454
+ computeLinkBreadths(graph);
8455
+ return graph;
8456
+ };
8457
+ sankey.nodeId = function(_) {
8458
+ return arguments.length ? (id = typeof _ === "function" ? _ : constant(_), sankey) : id;
8459
+ };
8460
+ sankey.nodeAlign = function(_) {
8461
+ return arguments.length ? (align = typeof _ === "function" ? _ : constant(_), sankey) : align;
8462
+ };
8463
+ sankey.nodeSort = function(_) {
8464
+ return arguments.length ? (sort = _, sankey) : sort;
8465
+ };
8466
+ sankey.nodeWidth = function(_) {
8467
+ return arguments.length ? (dx = +_, sankey) : dx;
8468
+ };
8469
+ sankey.nodePadding = function(_) {
8470
+ return arguments.length ? (dy = py = +_, sankey) : dy;
8471
+ };
8472
+ sankey.nodes = function(_) {
8473
+ return arguments.length ? (nodes = typeof _ === "function" ? _ : constant(_), sankey) : nodes;
8474
+ };
8475
+ sankey.links = function(_) {
8476
+ return arguments.length ? (links = typeof _ === "function" ? _ : constant(_), sankey) : links;
8477
+ };
8478
+ sankey.linkSort = function(_) {
8479
+ return arguments.length ? (linkSort = _, sankey) : linkSort;
8480
+ };
8481
+ sankey.size = function(_) {
8482
+ return arguments.length ? (x0 = y0 = 0, x1 = +_[0], y1 = +_[1], sankey) : [x1 - x0, y1 - y0];
8483
+ };
8484
+ sankey.extent = function(_) {
8485
+ return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], sankey) : [[x0, y0], [x1, y1]];
8486
+ };
8487
+ sankey.iterations = function(_) {
8488
+ return arguments.length ? (iterations = +_, sankey) : iterations;
8489
+ };
8490
+ function computeNodeLinks({ nodes: nodes2, links: links2 }) {
8491
+ for (const [i, node] of nodes2.entries()) {
8492
+ node.index = i;
8493
+ node.sourceLinks = [];
8494
+ node.targetLinks = [];
8495
+ }
8496
+ const nodeById = new Map(nodes2.map((d, i) => [id(d, i, nodes2), d]));
8497
+ for (const [i, link] of links2.entries()) {
8498
+ link.index = i;
8499
+ let { source, target } = link;
8500
+ if (typeof source !== "object") source = link.source = find(nodeById, source);
8501
+ if (typeof target !== "object") target = link.target = find(nodeById, target);
8502
+ source.sourceLinks.push(link);
8503
+ target.targetLinks.push(link);
8504
+ }
8505
+ if (linkSort != null) {
8506
+ for (const { sourceLinks, targetLinks } of nodes2) {
8507
+ sourceLinks.sort(linkSort);
8508
+ targetLinks.sort(linkSort);
8509
+ }
8510
+ }
8511
+ }
8512
+ function computeNodeValues({ nodes: nodes2 }) {
8513
+ for (const node of nodes2) {
8514
+ node.value = node.fixedValue === void 0 ? Math.max(sum(node.sourceLinks, value), sum(node.targetLinks, value)) : node.fixedValue;
8515
+ }
8516
+ }
8517
+ function computeNodeDepths({ nodes: nodes2 }) {
8518
+ const n = nodes2.length;
8519
+ let current = new Set(nodes2);
8520
+ let next = /* @__PURE__ */ new Set();
8521
+ let x2 = 0;
8522
+ while (current.size) {
8523
+ for (const node of current) {
8524
+ node.depth = x2;
8525
+ for (const { target } of node.sourceLinks) {
8526
+ next.add(target);
8527
+ }
8528
+ }
8529
+ if (++x2 > n) throw new Error("circular link");
8530
+ current = next;
8531
+ next = /* @__PURE__ */ new Set();
8532
+ }
8533
+ }
8534
+ function computeNodeHeights({ nodes: nodes2 }) {
8535
+ const n = nodes2.length;
8536
+ let current = new Set(nodes2);
8537
+ let next = /* @__PURE__ */ new Set();
8538
+ let x2 = 0;
8539
+ while (current.size) {
8540
+ for (const node of current) {
8541
+ node.height = x2;
8542
+ for (const { source } of node.targetLinks) {
8543
+ next.add(source);
8544
+ }
8545
+ }
8546
+ if (++x2 > n) throw new Error("circular link");
8547
+ current = next;
8548
+ next = /* @__PURE__ */ new Set();
8549
+ }
8550
+ }
8551
+ function computeNodeLayers({ nodes: nodes2 }) {
8552
+ const x2 = max3(nodes2, (d) => d.depth) + 1;
8553
+ const kx = (x1 - x0 - dx) / (x2 - 1);
8554
+ const columns = new Array(x2);
8555
+ for (const node of nodes2) {
8556
+ const i = Math.max(0, Math.min(x2 - 1, Math.floor(align.call(null, node, x2))));
8557
+ node.layer = i;
8558
+ node.x0 = x0 + i * kx;
8559
+ node.x1 = node.x0 + dx;
8560
+ if (columns[i]) columns[i].push(node);
8561
+ else columns[i] = [node];
8562
+ }
8563
+ if (sort) for (const column of columns) {
8564
+ column.sort(sort);
8565
+ }
8566
+ return columns;
8567
+ }
8568
+ function initializeNodeBreadths(columns) {
8569
+ const ky = min3(columns, (c) => (y1 - y0 - (c.length - 1) * py) / sum(c, value));
8570
+ for (const nodes2 of columns) {
8571
+ let y2 = y0;
8572
+ for (const node of nodes2) {
8573
+ node.y0 = y2;
8574
+ node.y1 = y2 + node.value * ky;
8575
+ y2 = node.y1 + py;
8576
+ for (const link of node.sourceLinks) {
8577
+ link.width = link.value * ky;
8578
+ }
8579
+ }
8580
+ y2 = (y1 - y2 + py) / (nodes2.length + 1);
8581
+ for (let i = 0; i < nodes2.length; ++i) {
8582
+ const node = nodes2[i];
8583
+ node.y0 += y2 * (i + 1);
8584
+ node.y1 += y2 * (i + 1);
8585
+ }
8586
+ reorderLinks(nodes2);
8587
+ }
8588
+ }
8589
+ function computeNodeBreadths(graph) {
8590
+ const columns = computeNodeLayers(graph);
8591
+ py = Math.min(dy, (y1 - y0) / (max3(columns, (c) => c.length) - 1));
8592
+ initializeNodeBreadths(columns);
8593
+ for (let i = 0; i < iterations; ++i) {
8594
+ const alpha = Math.pow(0.99, i);
8595
+ const beta = Math.max(1 - alpha, (i + 1) / iterations);
8596
+ relaxRightToLeft(columns, alpha, beta);
8597
+ relaxLeftToRight(columns, alpha, beta);
8598
+ }
8599
+ }
8600
+ function relaxLeftToRight(columns, alpha, beta) {
8601
+ for (let i = 1, n = columns.length; i < n; ++i) {
8602
+ const column = columns[i];
8603
+ for (const target of column) {
8604
+ let y2 = 0;
8605
+ let w = 0;
8606
+ for (const { source, value: value2 } of target.targetLinks) {
8607
+ let v = value2 * (target.layer - source.layer);
8608
+ y2 += targetTop(source, target) * v;
8609
+ w += v;
8610
+ }
8611
+ if (!(w > 0)) continue;
8612
+ let dy2 = (y2 / w - target.y0) * alpha;
8613
+ target.y0 += dy2;
8614
+ target.y1 += dy2;
8615
+ reorderNodeLinks(target);
8616
+ }
8617
+ if (sort === void 0) column.sort(ascendingBreadth);
8618
+ resolveCollisions6(column, beta);
8619
+ }
8620
+ }
8621
+ function relaxRightToLeft(columns, alpha, beta) {
8622
+ for (let n = columns.length, i = n - 2; i >= 0; --i) {
8623
+ const column = columns[i];
8624
+ for (const source of column) {
8625
+ let y2 = 0;
8626
+ let w = 0;
8627
+ for (const { target, value: value2 } of source.sourceLinks) {
8628
+ let v = value2 * (target.layer - source.layer);
8629
+ y2 += sourceTop(source, target) * v;
8630
+ w += v;
8631
+ }
8632
+ if (!(w > 0)) continue;
8633
+ let dy2 = (y2 / w - source.y0) * alpha;
8634
+ source.y0 += dy2;
8635
+ source.y1 += dy2;
8636
+ reorderNodeLinks(source);
8637
+ }
8638
+ if (sort === void 0) column.sort(ascendingBreadth);
8639
+ resolveCollisions6(column, beta);
8640
+ }
8641
+ }
8642
+ function resolveCollisions6(nodes2, alpha) {
8643
+ const i = nodes2.length >> 1;
8644
+ const subject = nodes2[i];
8645
+ resolveCollisionsBottomToTop(nodes2, subject.y0 - py, i - 1, alpha);
8646
+ resolveCollisionsTopToBottom(nodes2, subject.y1 + py, i + 1, alpha);
8647
+ resolveCollisionsBottomToTop(nodes2, y1, nodes2.length - 1, alpha);
8648
+ resolveCollisionsTopToBottom(nodes2, y0, 0, alpha);
8649
+ }
8650
+ function resolveCollisionsTopToBottom(nodes2, y2, i, alpha) {
8651
+ for (; i < nodes2.length; ++i) {
8652
+ const node = nodes2[i];
8653
+ const dy2 = (y2 - node.y0) * alpha;
8654
+ if (dy2 > 1e-6) node.y0 += dy2, node.y1 += dy2;
8655
+ y2 = node.y1 + py;
8656
+ }
8657
+ }
8658
+ function resolveCollisionsBottomToTop(nodes2, y2, i, alpha) {
8659
+ for (; i >= 0; --i) {
8660
+ const node = nodes2[i];
8661
+ const dy2 = (node.y1 - y2) * alpha;
8662
+ if (dy2 > 1e-6) node.y0 -= dy2, node.y1 -= dy2;
8663
+ y2 = node.y0 - py;
8664
+ }
8665
+ }
8666
+ function reorderNodeLinks({ sourceLinks, targetLinks }) {
8667
+ if (linkSort === void 0) {
8668
+ for (const { source: { sourceLinks: sourceLinks2 } } of targetLinks) {
8669
+ sourceLinks2.sort(ascendingTargetBreadth);
8670
+ }
8671
+ for (const { target: { targetLinks: targetLinks2 } } of sourceLinks) {
8672
+ targetLinks2.sort(ascendingSourceBreadth);
8673
+ }
8674
+ }
8675
+ }
8676
+ function reorderLinks(nodes2) {
8677
+ if (linkSort === void 0) {
8678
+ for (const { sourceLinks, targetLinks } of nodes2) {
8679
+ sourceLinks.sort(ascendingTargetBreadth);
8680
+ targetLinks.sort(ascendingSourceBreadth);
8681
+ }
8682
+ }
8683
+ }
8684
+ function targetTop(source, target) {
8685
+ let y2 = source.y0 - (source.sourceLinks.length - 1) * py / 2;
8686
+ for (const { target: node, width } of source.sourceLinks) {
8687
+ if (node === target) break;
8688
+ y2 += width + py;
8689
+ }
8690
+ for (const { source: node, width } of target.targetLinks) {
8691
+ if (node === source) break;
8692
+ y2 -= width;
8693
+ }
8694
+ return y2;
8695
+ }
8696
+ function sourceTop(source, target) {
8697
+ let y2 = target.y0 - (target.targetLinks.length - 1) * py / 2;
8698
+ for (const { source: node, width } of target.targetLinks) {
8699
+ if (node === source) break;
8700
+ y2 += width + py;
8701
+ }
8702
+ for (const { target: node, width } of source.sourceLinks) {
8703
+ if (node === target) break;
8704
+ y2 -= width;
8705
+ }
8706
+ return y2;
8707
+ }
8708
+ return sankey;
8709
+ }
8710
+
8711
+ // src/sankey/layout.ts
8712
+ var ALIGN_MAP = {
8713
+ justify,
8714
+ left,
8715
+ right,
8716
+ center
8717
+ };
8718
+ function computeSankeyLayout(data, sourceField, targetField, valueField, area, nodeWidth, nodePadding, nodeAlign, iterations) {
8719
+ const nodeSet = /* @__PURE__ */ new Set();
8720
+ for (const row of data) {
8721
+ nodeSet.add(String(row[sourceField]));
8722
+ nodeSet.add(String(row[targetField]));
8723
+ }
8724
+ const nodes = [...nodeSet].map((id) => ({
8725
+ id,
8726
+ label: id
8727
+ }));
8728
+ const links = data.map((row) => ({
8729
+ source: String(row[sourceField]),
8730
+ target: String(row[targetField]),
8731
+ value: Number(row[valueField]) || 0,
8732
+ data: { ...row }
8733
+ }));
8734
+ const alignFn = ALIGN_MAP[nodeAlign] ?? justify;
8735
+ const generator = Sankey().nodeId((d) => d.id).nodeAlign(alignFn).nodeWidth(nodeWidth).nodePadding(nodePadding).extent([
8736
+ [area.x, area.y],
8737
+ [area.x + area.width, area.y + area.height]
8738
+ ]).iterations(iterations);
8739
+ const graph = generator({
8740
+ nodes,
8741
+ links
8742
+ });
8743
+ return {
8744
+ nodes: graph.nodes,
8745
+ links: graph.links
8746
+ };
8747
+ }
8748
+ function generateLinkPath(link) {
8749
+ const source = link.source;
8750
+ const target = link.target;
8751
+ const x0 = source.x1 ?? 0;
8752
+ const x1 = target.x0 ?? 0;
8753
+ const y0 = link.y0 ?? 0;
8754
+ const y1 = link.y1 ?? 0;
8755
+ const halfWidth0 = (link.width ?? 0) / 2;
8756
+ const halfWidth1 = halfWidth0;
8757
+ const mx = (x0 + x1) / 2;
8758
+ const topY0 = y0 - halfWidth0;
8759
+ const topY1 = y1 - halfWidth1;
8760
+ const botY0 = y0 + halfWidth0;
8761
+ const botY1 = y1 + halfWidth1;
8762
+ return [
8763
+ `M${x0},${topY0}`,
8764
+ `C${mx},${topY0} ${mx},${topY1} ${x1},${topY1}`,
8765
+ `L${x1},${botY1}`,
8766
+ `C${mx},${botY1} ${mx},${botY0} ${x0},${botY0}`,
8767
+ "Z"
8768
+ ].join(" ");
8769
+ }
8770
+
8771
+ // src/sankey/compile-sankey.ts
8772
+ var SWATCH_SIZE3 = 12;
8773
+ var SWATCH_GAP3 = 6;
8774
+ var ENTRY_GAP3 = 16;
8775
+ var LABEL_GAP = 6;
8776
+ var LINK_OPACITY = 0.35;
8777
+ var NODE_CORNER_RADIUS = 2;
8778
+ function pickColor(palette, index) {
8779
+ return palette[index % palette.length];
8780
+ }
8781
+ function buildNodeColorMap(nodes, palette, colorField, data, sourceField, targetField) {
8782
+ const colorMap = /* @__PURE__ */ new Map();
8783
+ if (colorField) {
8784
+ const nodeCategoryMap = /* @__PURE__ */ new Map();
8785
+ for (const row of data) {
8786
+ const src = String(row[sourceField]);
8787
+ const tgt = String(row[targetField]);
8788
+ const cat = String(row[colorField]);
8789
+ if (!nodeCategoryMap.has(src)) nodeCategoryMap.set(src, cat);
8790
+ if (!nodeCategoryMap.has(tgt)) nodeCategoryMap.set(tgt, cat);
8791
+ }
8792
+ const categoryIndex = /* @__PURE__ */ new Map();
8793
+ let nextIdx = 0;
8794
+ for (const node of nodes) {
8795
+ const category = nodeCategoryMap.get(node.id) ?? node.id;
8796
+ if (!categoryIndex.has(category)) {
8797
+ categoryIndex.set(category, nextIdx++);
8798
+ }
8799
+ colorMap.set(node.id, pickColor(palette, categoryIndex.get(category)));
8800
+ }
8801
+ } else {
8802
+ for (let i = 0; i < nodes.length; i++) {
8803
+ colorMap.set(nodes[i].id, pickColor(palette, i));
8804
+ }
8805
+ }
8806
+ return colorMap;
8807
+ }
8808
+ function getLinkColors(linkStyle, sourceColor, targetColor, neutralColor) {
8809
+ switch (linkStyle) {
8810
+ case "source":
8811
+ return { sourceColor, targetColor: sourceColor };
8812
+ case "target":
8813
+ return { sourceColor: targetColor, targetColor };
8814
+ case "neutral":
8815
+ return { sourceColor: neutralColor, targetColor: neutralColor };
8816
+ default:
8817
+ return { sourceColor, targetColor };
8818
+ }
8819
+ }
8820
+ function computeNodeLabel(node, maxDepth, theme, nodeWidth) {
8821
+ const depth = node.depth ?? 0;
8822
+ const isRightmost = depth === maxDepth;
8823
+ const style = {
8824
+ fontFamily: theme.fonts.family,
8825
+ fontSize: theme.fonts.sizes.small,
8826
+ fontWeight: theme.fonts.weights.normal,
8827
+ fill: theme.colors.text,
8828
+ lineHeight: 1.3
8829
+ };
8830
+ const x0 = node.x0 ?? 0;
8831
+ const x1 = node.x1 ?? nodeWidth;
8832
+ const y0 = node.y0 ?? 0;
8833
+ const y1 = node.y1 ?? 0;
8834
+ const midY = (y0 + y1) / 2;
8835
+ if (isRightmost) {
8836
+ return {
8837
+ text: node.label ?? node.id,
8838
+ x: x0 - LABEL_GAP,
8839
+ y: midY,
8840
+ style: { ...style, textAnchor: "end", dominantBaseline: "central" },
8841
+ visible: true
8842
+ };
8843
+ }
8844
+ return {
8845
+ text: node.label ?? node.id,
8846
+ x: x1 + LABEL_GAP,
8847
+ y: midY,
8848
+ style: { ...style, textAnchor: "start", dominantBaseline: "central" },
8849
+ visible: true
8850
+ };
8851
+ }
8852
+ function compileSankey(spec, options) {
8853
+ const { spec: normalized } = compile(spec);
8854
+ if (!("type" in normalized) || normalized.type !== "sankey") {
8855
+ throw new Error(
8856
+ "compileSankey received a non-sankey spec. Use compileChart, compileTable, or compileGraph instead."
8857
+ );
8858
+ }
8859
+ const sankeySpec = normalized;
8860
+ const mergedThemeConfig = options.theme ? { ...sankeySpec.theme, ...options.theme } : sankeySpec.theme;
8861
+ let theme = resolveTheme2(mergedThemeConfig);
8862
+ if (options.darkMode) {
8863
+ theme = adaptTheme2(theme);
8864
+ }
8865
+ const chrome = computeChrome3(
8866
+ {
8867
+ title: sankeySpec.chrome.title,
8868
+ subtitle: sankeySpec.chrome.subtitle,
8869
+ source: sankeySpec.chrome.source,
8870
+ byline: sankeySpec.chrome.byline,
8871
+ footer: sankeySpec.chrome.footer
8872
+ },
8873
+ theme,
8874
+ options.width,
8875
+ options.measureText
8876
+ );
8877
+ const padding = theme.spacing.padding;
8878
+ const fullArea = {
8879
+ x: padding,
8880
+ y: padding + chrome.topHeight,
8881
+ width: options.width - padding * 2,
8882
+ height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
8883
+ };
8884
+ if (fullArea.width <= 0 || fullArea.height <= 0) {
8885
+ return emptyLayout(fullArea, chrome, theme, options);
8886
+ }
8887
+ const sourceField = sankeySpec.encoding.source.field;
8888
+ const targetField = sankeySpec.encoding.target.field;
8889
+ const valueField = sankeySpec.encoding.value.field;
8890
+ const colorField = sankeySpec.encoding.color?.field;
8891
+ const tempNodeIds = /* @__PURE__ */ new Set();
8892
+ for (const row of sankeySpec.data) {
8893
+ tempNodeIds.add(String(row[sourceField]));
8894
+ tempNodeIds.add(String(row[targetField]));
8895
+ }
8896
+ const tempColorMap = buildNodeColorMap(
8897
+ [...tempNodeIds].map((id) => ({ id })),
8898
+ theme.colors.categorical,
8899
+ colorField,
8900
+ sankeySpec.data,
8901
+ sourceField,
8902
+ targetField
8903
+ );
8904
+ const legend = buildSankeyLegend(
8905
+ tempColorMap,
8906
+ colorField,
8907
+ sankeySpec.data,
8908
+ sourceField,
8909
+ targetField,
8910
+ theme,
8911
+ fullArea
8912
+ );
8913
+ const legendGap = legend.entries.length > 0 ? 4 : 0;
8914
+ const area = {
8915
+ x: fullArea.x,
8916
+ y: fullArea.y + legend.bounds.height + legendGap,
8917
+ width: fullArea.width,
8918
+ height: fullArea.height - legend.bounds.height - legendGap
8919
+ };
8920
+ if (area.height <= 0) {
8921
+ return emptyLayout(area, chrome, theme, options);
8922
+ }
8923
+ const { nodes, links } = computeSankeyLayout(
8924
+ sankeySpec.data,
8925
+ sourceField,
8926
+ targetField,
8927
+ valueField,
8928
+ area,
8929
+ sankeySpec.nodeWidth,
8930
+ sankeySpec.nodePadding,
8931
+ sankeySpec.nodeAlign,
8932
+ sankeySpec.iterations
8933
+ );
8934
+ const nodeColorMap = buildNodeColorMap(
8935
+ nodes,
8936
+ theme.colors.categorical,
8937
+ colorField,
8938
+ sankeySpec.data,
8939
+ sourceField,
8940
+ targetField
8941
+ );
8942
+ const maxDepth = nodes.reduce((max4, n) => Math.max(max4, n.depth ?? 0), 0);
8943
+ const nodeMarks = nodes.map((node) => {
8944
+ const fill = nodeColorMap.get(node.id) ?? theme.colors.categorical[0];
8945
+ const depth = node.depth ?? 0;
8946
+ return {
8947
+ type: "sankeyNode",
8948
+ x: node.x0 ?? 0,
8949
+ y: node.y0 ?? 0,
8950
+ width: (node.x1 ?? 0) - (node.x0 ?? 0),
8951
+ height: (node.y1 ?? 0) - (node.y0 ?? 0),
8952
+ fill,
8953
+ cornerRadius: NODE_CORNER_RADIUS,
8954
+ label: computeNodeLabel(node, maxDepth, theme, sankeySpec.nodeWidth),
8955
+ nodeId: node.id,
8956
+ value: node.value ?? 0,
8957
+ depth,
8958
+ data: { id: node.id, label: node.label },
8959
+ aria: {
8960
+ role: "img",
8961
+ label: `${node.label}: ${formatNumber4(node.value ?? 0)}`
8962
+ },
8963
+ animationIndex: 0
8964
+ // Reassigned below after sorting by depth
8965
+ };
8966
+ });
8967
+ nodeMarks.sort((a, b) => a.depth - b.depth || a.y - b.y);
8968
+ for (let i = 0; i < nodeMarks.length; i++) {
8969
+ nodeMarks[i].animationIndex = i;
8970
+ }
8971
+ const neutralColor = theme.colors.gridline;
8972
+ const linkMarks = links.map((link, i) => {
8973
+ const sourceNode = link.source;
8974
+ const targetNode = link.target;
8975
+ const srcColor = nodeColorMap.get(sourceNode.id) ?? theme.colors.categorical[0];
8976
+ const tgtColor = nodeColorMap.get(targetNode.id) ?? theme.colors.categorical[0];
8977
+ const colors = getLinkColors(sankeySpec.linkStyle, srcColor, tgtColor, neutralColor);
8978
+ return {
8979
+ type: "sankeyLink",
8980
+ path: generateLinkPath(link),
8981
+ sourceColor: colors.sourceColor,
8982
+ targetColor: colors.targetColor,
8983
+ fillOpacity: LINK_OPACITY,
8984
+ sourceId: sourceNode.id,
8985
+ targetId: targetNode.id,
8986
+ width: link.width ?? 0,
8987
+ value: link.value,
8988
+ data: link.data ?? {},
8989
+ aria: {
8990
+ role: "img",
8991
+ label: `${sourceNode.label} to ${targetNode.label}: ${formatNumber4(link.value)}`
8992
+ },
8993
+ // Links animate after nodes
8994
+ animationIndex: nodeMarks.length + i
8995
+ };
8996
+ });
8997
+ const finalLegend = buildSankeyLegend(
8998
+ nodeColorMap,
8999
+ colorField,
9000
+ sankeySpec.data,
9001
+ sourceField,
9002
+ targetField,
9003
+ theme,
9004
+ fullArea
9005
+ );
9006
+ const tooltipDescriptors = buildTooltipDescriptors(nodeMarks, linkMarks);
9007
+ const a11y = {
9008
+ altText: `Sankey diagram with ${nodeMarks.length} nodes and ${linkMarks.length} links`,
9009
+ dataTableFallback: linkMarks.map((l) => [l.sourceId, l.targetId, String(l.value)]),
9010
+ role: "img",
9011
+ keyboardNavigable: nodeMarks.length > 0
9012
+ };
9013
+ const resolvedAnimation = resolveAnimation(sankeySpec.animation);
9014
+ return {
9015
+ area,
9016
+ chrome,
9017
+ nodes: nodeMarks,
9018
+ links: linkMarks,
9019
+ legend: finalLegend,
9020
+ tooltipDescriptors,
9021
+ a11y,
9022
+ theme,
9023
+ dimensions: {
9024
+ width: options.width,
9025
+ height: options.height
9026
+ },
9027
+ animation: resolvedAnimation
9028
+ };
9029
+ }
9030
+ function buildSankeyLegend(nodeColorMap, colorField, data, sourceField, targetField, theme, area) {
9031
+ const labelStyle = {
9032
+ fontFamily: theme.fonts.family,
9033
+ fontSize: theme.fonts.sizes.small,
9034
+ fontWeight: theme.fonts.weights.normal,
9035
+ fill: theme.colors.text,
9036
+ lineHeight: 1.3
9037
+ };
9038
+ let entries;
9039
+ if (colorField) {
9040
+ const categoryColors = /* @__PURE__ */ new Map();
9041
+ const nodeCategoryMap = /* @__PURE__ */ new Map();
9042
+ for (const row of data) {
9043
+ const src = String(row[sourceField]);
9044
+ const tgt = String(row[targetField]);
9045
+ const cat = String(row[colorField]);
9046
+ if (!nodeCategoryMap.has(src)) nodeCategoryMap.set(src, cat);
9047
+ if (!nodeCategoryMap.has(tgt)) nodeCategoryMap.set(tgt, cat);
9048
+ }
9049
+ for (const [nodeId, category] of nodeCategoryMap) {
9050
+ if (!categoryColors.has(category)) {
9051
+ categoryColors.set(category, nodeColorMap.get(nodeId) ?? theme.colors.categorical[0]);
9052
+ }
9053
+ }
9054
+ entries = [...categoryColors.entries()].map(([label, color2]) => ({
9055
+ label,
9056
+ color: color2,
9057
+ shape: "square",
9058
+ active: true
9059
+ }));
9060
+ } else {
9061
+ entries = [];
9062
+ }
9063
+ let bounds = { x: 0, y: 0, width: 0, height: 0 };
9064
+ if (entries.length > 0) {
9065
+ const ROW_HEIGHT = SWATCH_SIZE3 + 4;
9066
+ const availableWidth = area.width;
9067
+ let rowCount = 1;
9068
+ let rowX = 0;
9069
+ for (const entry of entries) {
9070
+ const labelWidth = estimateTextWidth10(entry.label, labelStyle.fontSize, labelStyle.fontWeight);
9071
+ const entryWidth = SWATCH_SIZE3 + SWATCH_GAP3 + labelWidth + ENTRY_GAP3;
9072
+ if (rowX > 0 && rowX + entryWidth > availableWidth) {
9073
+ rowCount++;
9074
+ rowX = entryWidth;
9075
+ } else {
9076
+ rowX += entryWidth;
9077
+ }
9078
+ }
9079
+ rowCount = Math.min(rowCount, 2);
9080
+ const legendHeight = rowCount * ROW_HEIGHT;
9081
+ bounds = {
9082
+ x: area.x,
9083
+ y: area.y,
9084
+ width: availableWidth,
9085
+ height: legendHeight
9086
+ };
9087
+ }
9088
+ return {
9089
+ position: "top",
9090
+ entries,
9091
+ bounds,
9092
+ labelStyle,
9093
+ swatchSize: SWATCH_SIZE3,
9094
+ swatchGap: SWATCH_GAP3,
9095
+ entryGap: ENTRY_GAP3
9096
+ };
9097
+ }
9098
+ function buildTooltipDescriptors(nodes, links) {
9099
+ const descriptors = /* @__PURE__ */ new Map();
9100
+ for (const node of nodes) {
9101
+ const fields = [
9102
+ {
9103
+ label: "Total flow",
9104
+ value: formatNumber4(node.value)
9105
+ }
9106
+ ];
9107
+ descriptors.set(`node-${node.nodeId}`, {
9108
+ title: node.label.text,
9109
+ fields
9110
+ });
9111
+ }
9112
+ for (const link of links) {
9113
+ const fields = [
9114
+ {
9115
+ label: "Flow",
9116
+ value: formatNumber4(link.value)
9117
+ }
9118
+ ];
9119
+ descriptors.set(`link-${link.sourceId}-${link.targetId}`, {
9120
+ title: `${link.sourceId} \u2192 ${link.targetId}`,
9121
+ fields
9122
+ });
9123
+ }
9124
+ return descriptors;
9125
+ }
9126
+ function emptyLayout(area, chrome, theme, options) {
9127
+ return {
9128
+ area,
9129
+ chrome,
9130
+ nodes: [],
9131
+ links: [],
9132
+ legend: {
9133
+ position: "top",
9134
+ entries: [],
9135
+ bounds: { x: 0, y: 0, width: 0, height: 0 },
9136
+ labelStyle: {
9137
+ fontFamily: theme.fonts.family,
9138
+ fontSize: theme.fonts.sizes.small,
9139
+ fontWeight: theme.fonts.weights.normal,
9140
+ fill: theme.colors.text,
9141
+ lineHeight: 1.3
9142
+ },
9143
+ swatchSize: SWATCH_SIZE3,
9144
+ swatchGap: SWATCH_GAP3,
9145
+ entryGap: ENTRY_GAP3
9146
+ },
9147
+ tooltipDescriptors: /* @__PURE__ */ new Map(),
9148
+ a11y: {
9149
+ altText: "Empty sankey diagram",
9150
+ dataTableFallback: [],
9151
+ role: "img",
9152
+ keyboardNavigable: false
9153
+ },
9154
+ theme,
9155
+ dimensions: {
9156
+ width: options.width,
9157
+ height: options.height
9158
+ }
9159
+ };
9160
+ }
9161
+
8201
9162
  // src/tables/compile-table.ts
8202
- import { computeChrome as computeChrome3, estimateTextWidth as estimateTextWidth10 } from "@opendata-ai/openchart-core";
9163
+ import { computeChrome as computeChrome4, estimateTextWidth as estimateTextWidth11 } from "@opendata-ai/openchart-core";
8203
9164
 
8204
9165
  // src/tables/bar-column.ts
8205
9166
  var NEGATIVE_BAR_COLOR = "#c44e52";
8206
- function computeBarCell(value, config, columnMax, columnMin, theme, _darkMode) {
9167
+ function computeBarCell(value2, config, columnMax, columnMin, theme, _darkMode) {
8207
9168
  const barColor = config.color ?? theme.colors.categorical[0];
8208
9169
  const hasNegatives = columnMin < 0;
8209
- if (!Number.isFinite(value)) {
9170
+ if (!Number.isFinite(value2)) {
8210
9171
  return { barPercent: 0, barOffset: 0, barColor, isNegative: false };
8211
9172
  }
8212
9173
  if (!hasNegatives) {
@@ -8214,7 +9175,7 @@ function computeBarCell(value, config, columnMax, columnMin, theme, _darkMode) {
8214
9175
  if (maxValue <= 0) {
8215
9176
  return { barPercent: 0, barOffset: 0, barColor, isNegative: false };
8216
9177
  }
8217
- const barPercent2 = Math.max(0, Math.min(1, value / maxValue));
9178
+ const barPercent2 = Math.max(0, Math.min(1, value2 / maxValue));
8218
9179
  return { barPercent: barPercent2, barOffset: 0, barColor, isNegative: false };
8219
9180
  }
8220
9181
  const maxPos = config.maxValue ?? columnMax;
@@ -8224,11 +9185,11 @@ function computeBarCell(value, config, columnMax, columnMin, theme, _darkMode) {
8224
9185
  return { barPercent: 0, barOffset: 0, barColor, isNegative: false };
8225
9186
  }
8226
9187
  const zeroPos = absMin / totalRange;
8227
- if (value >= 0) {
8228
- const barPercent2 = value / totalRange;
9188
+ if (value2 >= 0) {
9189
+ const barPercent2 = value2 / totalRange;
8229
9190
  return { barPercent: barPercent2, barOffset: zeroPos, barColor, isNegative: false };
8230
9191
  }
8231
- const barPercent = Math.abs(value) / totalRange;
9192
+ const barPercent = Math.abs(value2) / totalRange;
8232
9193
  return {
8233
9194
  barPercent,
8234
9195
  barOffset: zeroPos - barPercent,
@@ -8237,24 +9198,24 @@ function computeBarCell(value, config, columnMax, columnMin, theme, _darkMode) {
8237
9198
  };
8238
9199
  }
8239
9200
  function computeColumnMax(data, key) {
8240
- let max3 = 0;
9201
+ let max4 = 0;
8241
9202
  for (const row of data) {
8242
9203
  const val = row[key];
8243
- if (typeof val === "number" && Number.isFinite(val) && val > max3) {
8244
- max3 = val;
9204
+ if (typeof val === "number" && Number.isFinite(val) && val > max4) {
9205
+ max4 = val;
8245
9206
  }
8246
9207
  }
8247
- return max3;
9208
+ return max4;
8248
9209
  }
8249
9210
  function computeColumnMin(data, key) {
8250
- let min3 = 0;
9211
+ let min4 = 0;
8251
9212
  for (const row of data) {
8252
9213
  const val = row[key];
8253
- if (typeof val === "number" && Number.isFinite(val) && val < min3) {
8254
- min3 = val;
9214
+ if (typeof val === "number" && Number.isFinite(val) && val < min4) {
9215
+ min4 = val;
8255
9216
  }
8256
9217
  }
8257
- return min3;
9218
+ return min4;
8258
9219
  }
8259
9220
 
8260
9221
  // src/tables/category-colors.ts
@@ -8307,67 +9268,67 @@ function computeCategoryColors(data, column, theme, darkMode) {
8307
9268
  }
8308
9269
 
8309
9270
  // src/tables/format-cells.ts
8310
- import { formatDate as formatDate2, formatNumber as formatNumber4 } from "@opendata-ai/openchart-core";
8311
- function isNumericValue(value) {
8312
- if (typeof value === "number") return Number.isFinite(value);
9271
+ import { formatDate as formatDate2, formatNumber as formatNumber5 } from "@opendata-ai/openchart-core";
9272
+ function isNumericValue(value2) {
9273
+ if (typeof value2 === "number") return Number.isFinite(value2);
8313
9274
  return false;
8314
9275
  }
8315
- function isDateValue(value) {
8316
- if (value instanceof Date) return !Number.isNaN(value.getTime());
9276
+ function isDateValue(value2) {
9277
+ if (value2 instanceof Date) return !Number.isNaN(value2.getTime());
8317
9278
  return false;
8318
9279
  }
8319
- function formatCell(value, column) {
9280
+ function formatCell(value2, column) {
8320
9281
  const style = {};
8321
- if (value == null) {
9282
+ if (value2 == null) {
8322
9283
  return {
8323
- value,
9284
+ value: value2,
8324
9285
  formattedValue: "",
8325
9286
  style
8326
9287
  };
8327
9288
  }
8328
- if (column.format && isNumericValue(value)) {
9289
+ if (column.format && isNumericValue(value2)) {
8329
9290
  try {
8330
9291
  const formatter = format(column.format);
8331
9292
  return {
8332
- value,
8333
- formattedValue: formatter(value),
9293
+ value: value2,
9294
+ formattedValue: formatter(value2),
8334
9295
  style
8335
9296
  };
8336
9297
  } catch {
8337
9298
  }
8338
9299
  }
8339
- if (isNumericValue(value)) {
9300
+ if (isNumericValue(value2)) {
8340
9301
  return {
8341
- value,
8342
- formattedValue: formatNumber4(value),
9302
+ value: value2,
9303
+ formattedValue: formatNumber5(value2),
8343
9304
  style
8344
9305
  };
8345
9306
  }
8346
- if (isDateValue(value)) {
9307
+ if (isDateValue(value2)) {
8347
9308
  return {
8348
- value,
8349
- formattedValue: formatDate2(value),
9309
+ value: value2,
9310
+ formattedValue: formatDate2(value2),
8350
9311
  style
8351
9312
  };
8352
9313
  }
8353
9314
  return {
8354
- value,
8355
- formattedValue: String(value),
9315
+ value: value2,
9316
+ formattedValue: String(value2),
8356
9317
  style
8357
9318
  };
8358
9319
  }
8359
- function formatValueForSearch(value, column) {
8360
- if (value == null) return "";
8361
- if (column.format && isNumericValue(value)) {
9320
+ function formatValueForSearch(value2, column) {
9321
+ if (value2 == null) return "";
9322
+ if (column.format && isNumericValue(value2)) {
8362
9323
  try {
8363
- return format(column.format)(value);
9324
+ return format(column.format)(value2);
8364
9325
  } catch {
8365
9326
  }
8366
9327
  }
8367
- if (isNumericValue(value)) {
8368
- return formatNumber4(value);
9328
+ if (isNumericValue(value2)) {
9329
+ return formatNumber5(value2);
8369
9330
  }
8370
- return String(value);
9331
+ return String(value2);
8371
9332
  }
8372
9333
 
8373
9334
  // src/tables/heatmap.ts
@@ -8412,13 +9373,13 @@ function computeHeatmapColors(data, column, theme, darkMode) {
8412
9373
  if (config.domain) {
8413
9374
  domain = config.domain;
8414
9375
  } else {
8415
- let min3 = Infinity;
8416
- let max3 = -Infinity;
8417
- for (const { value } of numericValues) {
8418
- if (value < min3) min3 = value;
8419
- if (value > max3) max3 = value;
9376
+ let min4 = Infinity;
9377
+ let max4 = -Infinity;
9378
+ for (const { value: value2 } of numericValues) {
9379
+ if (value2 < min4) min4 = value2;
9380
+ if (value2 > max4) max4 = value2;
8420
9381
  }
8421
- domain = [min3, max3];
9382
+ domain = [min4, max4];
8422
9383
  }
8423
9384
  let stops = resolvePalette(config.palette, theme);
8424
9385
  if (darkMode) {
@@ -8428,8 +9389,8 @@ function computeHeatmapColors(data, column, theme, darkMode) {
8428
9389
  }
8429
9390
  const interpolator = interpolatorFromStops(stops);
8430
9391
  const scale = sequential(interpolator).domain(domain).clamp(true);
8431
- for (const { index, value } of numericValues) {
8432
- const bg = scale(value);
9392
+ for (const { index, value: value2 } of numericValues) {
9393
+ const bg = scale(value2);
8433
9394
  const textColor = accessibleTextColor(bg);
8434
9395
  result.set(index, {
8435
9396
  backgroundColor: bg,
@@ -8534,14 +9495,14 @@ function computeSparkline(values, config, theme, _darkMode) {
8534
9495
  if (values.length === 0) return null;
8535
9496
  const type = config.type ?? "line";
8536
9497
  const color2 = config.color ?? theme.colors.categorical[0];
8537
- let min3 = Infinity;
8538
- let max3 = -Infinity;
9498
+ let min4 = Infinity;
9499
+ let max4 = -Infinity;
8539
9500
  for (const v of values) {
8540
- if (v < min3) min3 = v;
8541
- if (v > max3) max3 = v;
9501
+ if (v < min4) min4 = v;
9502
+ if (v > max4) max4 = v;
8542
9503
  }
8543
- const range2 = max3 - min3;
8544
- const normalize2 = (v) => range2 === 0 ? 0.5 : (v - min3) / range2;
9504
+ const range2 = max4 - min4;
9505
+ const normalize2 = (v) => range2 === 0 ? 0.5 : (v - min4) / range2;
8545
9506
  const startValue = values[0];
8546
9507
  const endValue = values[values.length - 1];
8547
9508
  if (type === "line") {
@@ -8606,13 +9567,13 @@ function estimateColumnWidth(col, data, fontSize) {
8606
9567
  if (col.image) return (col.image.width ?? 24) + PADDING;
8607
9568
  if (col.flag) return 60;
8608
9569
  const label = col.label ?? col.key;
8609
- const headerWidth = estimateTextWidth10(label, fontSize, 600) + PADDING;
9570
+ const headerWidth = estimateTextWidth11(label, fontSize, 600) + PADDING;
8610
9571
  const sampleSize = Math.min(100, data.length);
8611
9572
  let maxDataWidth = 0;
8612
9573
  for (let i = 0; i < sampleSize; i++) {
8613
9574
  const val = data[i][col.key];
8614
9575
  const text = val == null ? "" : String(val);
8615
- const width = estimateTextWidth10(text, fontSize, 400) + PADDING;
9576
+ const width = estimateTextWidth11(text, fontSize, 400) + PADDING;
8616
9577
  if (width > maxDataWidth) maxDataWidth = width;
8617
9578
  }
8618
9579
  return Math.max(MIN_WIDTH, headerWidth, maxDataWidth);
@@ -8632,8 +9593,8 @@ function resolveColumns(columns, data, totalWidth, theme) {
8632
9593
  }
8633
9594
  return estimateColumnWidth(col, data, fontSize);
8634
9595
  });
8635
- const fixedTotal = naturalWidths.reduce((sum, w, i) => sum + (isFixed[i] ? w : 0), 0);
8636
- const flexTotal = naturalWidths.reduce((sum, w, i) => sum + (isFixed[i] ? 0 : w), 0);
9596
+ const fixedTotal = naturalWidths.reduce((sum2, w, i) => sum2 + (isFixed[i] ? w : 0), 0);
9597
+ const flexTotal = naturalWidths.reduce((sum2, w, i) => sum2 + (isFixed[i] ? 0 : w), 0);
8637
9598
  const remainingWidth = totalWidth - fixedTotal;
8638
9599
  const flexScale = flexTotal > 0 && remainingWidth > 0 ? remainingWidth / flexTotal : 1;
8639
9600
  return columns.map((col, i) => ({
@@ -8645,9 +9606,9 @@ function resolveColumns(columns, data, totalWidth, theme) {
8645
9606
  cellType: determineCellType(col)
8646
9607
  }));
8647
9608
  }
8648
- function buildCell(value, column, resolvedColumn, heatmapStyle, categoryStyle, barData, sparklineData) {
8649
- const base = formatCell(value, column);
8650
- if (typeof value === "number") {
9609
+ function buildCell(value2, column, resolvedColumn, heatmapStyle, categoryStyle, barData, sparklineData) {
9610
+ const base = formatCell(value2, column);
9611
+ if (typeof value2 === "number") {
8651
9612
  base.style = { ...base.style, fontVariant: "tabular-nums" };
8652
9613
  }
8653
9614
  const cellType = resolvedColumn.cellType;
@@ -8686,7 +9647,7 @@ function buildCell(value, column, resolvedColumn, heatmapStyle, categoryStyle, b
8686
9647
  };
8687
9648
  }
8688
9649
  case "image": {
8689
- const src = typeof value === "string" ? value : "";
9650
+ const src = typeof value2 === "string" ? value2 : "";
8690
9651
  const imgConfig = column.image ?? {};
8691
9652
  return {
8692
9653
  ...base,
@@ -8698,7 +9659,7 @@ function buildCell(value, column, resolvedColumn, heatmapStyle, categoryStyle, b
8698
9659
  };
8699
9660
  }
8700
9661
  case "flag": {
8701
- const code = typeof value === "string" ? value : "";
9662
+ const code = typeof value2 === "string" ? value2 : "";
8702
9663
  return {
8703
9664
  ...base,
8704
9665
  cellType: "flag",
@@ -8773,13 +9734,13 @@ function compileTableLayout(spec, options, theme) {
8773
9734
  const rowId = spec.rowKey ? String(row[spec.rowKey] ?? origIdx) : String(origIdx);
8774
9735
  const cells = spec.columns.map((col, c) => {
8775
9736
  const resolved = resolvedColumns[c];
8776
- const value = row[col.key];
9737
+ const value2 = row[col.key];
8777
9738
  const heatmapStyle = heatmapMaps.get(col.key)?.get(origIdx);
8778
9739
  const categoryStyle = categoryMaps.get(col.key)?.get(origIdx);
8779
9740
  let barData;
8780
- if (resolved.cellType === "bar" && col.bar && typeof value === "number") {
9741
+ if (resolved.cellType === "bar" && col.bar && typeof value2 === "number") {
8781
9742
  barData = computeBarCell(
8782
- value,
9743
+ value2,
8783
9744
  col.bar,
8784
9745
  barMaxes.get(col.key) ?? 0,
8785
9746
  barMins.get(col.key) ?? 0,
@@ -8791,11 +9752,11 @@ function compileTableLayout(spec, options, theme) {
8791
9752
  if (resolved.cellType === "sparkline" && col.sparkline) {
8792
9753
  sparklineData = computeSparklineForRow(row, col.key, col.sparkline, theme, darkMode);
8793
9754
  }
8794
- return buildCell(value, col, resolved, heatmapStyle, categoryStyle, barData, sparklineData);
9755
+ return buildCell(value2, col, resolved, heatmapStyle, categoryStyle, barData, sparklineData);
8795
9756
  });
8796
9757
  return { id: rowId, cells, data: row };
8797
9758
  });
8798
- const chrome = computeChrome3(
9759
+ const chrome = computeChrome4(
8799
9760
  {
8800
9761
  title: spec.chrome.title,
8801
9762
  subtitle: spec.chrome.subtitle,
@@ -8832,25 +9793,25 @@ function compileTableLayout(spec, options, theme) {
8832
9793
  }
8833
9794
 
8834
9795
  // src/tooltips/compute.ts
8835
- import { buildTemporalFormatter as buildTemporalFormatter2, formatDate as formatDate3, formatNumber as formatNumber5 } from "@opendata-ai/openchart-core";
8836
- function formatValue(value, fieldType, format2) {
8837
- if (value == null) return "";
8838
- if (fieldType === "temporal" || value instanceof Date) {
9796
+ import { buildTemporalFormatter as buildTemporalFormatter2, formatDate as formatDate3, formatNumber as formatNumber6 } from "@opendata-ai/openchart-core";
9797
+ function formatValue(value2, fieldType, format2) {
9798
+ if (value2 == null) return "";
9799
+ if (fieldType === "temporal" || value2 instanceof Date) {
8839
9800
  const temporalFmt = buildTemporalFormatter2(format2);
8840
- if (temporalFmt) return temporalFmt(value);
8841
- return formatDate3(value);
9801
+ if (temporalFmt) return temporalFmt(value2);
9802
+ return formatDate3(value2);
8842
9803
  }
8843
- if (typeof value === "number") {
9804
+ if (typeof value2 === "number") {
8844
9805
  if (format2) {
8845
9806
  try {
8846
- return format(format2)(value);
9807
+ return format(format2)(value2);
8847
9808
  } catch {
8848
- return formatNumber5(value);
9809
+ return formatNumber6(value2);
8849
9810
  }
8850
9811
  }
8851
- return formatNumber5(value);
9812
+ return formatNumber6(value2);
8852
9813
  }
8853
- return String(value);
9814
+ return String(value2);
8854
9815
  }
8855
9816
  function buildExplicitTooltipFields(row, channels) {
8856
9817
  return channels.map((ch) => ({
@@ -9015,16 +9976,16 @@ function runBin(data, transform) {
9015
9976
  const field = transform.field;
9016
9977
  let extent2 = params.extent;
9017
9978
  if (!extent2) {
9018
- let min3 = Infinity;
9019
- let max3 = -Infinity;
9979
+ let min4 = Infinity;
9980
+ let max4 = -Infinity;
9020
9981
  for (const row of data) {
9021
9982
  const v = Number(row[field]);
9022
9983
  if (Number.isFinite(v)) {
9023
- if (v < min3) min3 = v;
9024
- if (v > max3) max3 = v;
9984
+ if (v < min4) min4 = v;
9985
+ if (v > max4) max4 = v;
9025
9986
  }
9026
9987
  }
9027
- extent2 = [min3 === Infinity ? 0 : min3, max3 === -Infinity ? 0 : max3];
9988
+ extent2 = [min4 === Infinity ? 0 : min4, max4 === -Infinity ? 0 : max4];
9028
9989
  }
9029
9990
  const step = params.step ?? computeStep(extent2, maxbins, nice2);
9030
9991
  const [startAs, endAs] = Array.isArray(transform.as) ? transform.as : [transform.as, void 0];
@@ -9131,10 +10092,10 @@ function extractTimeUnit(date2, unit2) {
9131
10092
  return `${String(date2.getHours()).padStart(2, "0")}:${String(date2.getMinutes()).padStart(2, "0")}`;
9132
10093
  }
9133
10094
  }
9134
- function toDate(value) {
9135
- if (value instanceof Date) return value;
9136
- if (typeof value === "string" || typeof value === "number") {
9137
- const d = new Date(value);
10095
+ function toDate(value2) {
10096
+ if (value2 instanceof Date) return value2;
10097
+ if (typeof value2 === "string" || typeof value2 === "number") {
10098
+ const d = new Date(value2);
9138
10099
  return Number.isNaN(d.getTime()) ? null : d;
9139
10100
  }
9140
10101
  return null;
@@ -9218,28 +10179,28 @@ function computeBandRowObstacles(marks, scales) {
9218
10179
  const rows = /* @__PURE__ */ new Map();
9219
10180
  for (const mark of marks) {
9220
10181
  let cy;
9221
- let left;
9222
- let right;
10182
+ let left2;
10183
+ let right2;
9223
10184
  if (mark.type === "point") {
9224
10185
  const pm = mark;
9225
10186
  cy = pm.cy;
9226
- left = pm.cx - pm.r;
9227
- right = pm.cx + pm.r;
10187
+ left2 = pm.cx - pm.r;
10188
+ right2 = pm.cx + pm.r;
9228
10189
  } else if (mark.type === "rect") {
9229
10190
  const rm = mark;
9230
10191
  cy = rm.y + rm.height / 2;
9231
- left = rm.x;
9232
- right = rm.x + rm.width;
10192
+ left2 = rm.x;
10193
+ right2 = rm.x + rm.width;
9233
10194
  } else {
9234
10195
  continue;
9235
10196
  }
9236
10197
  const key = Math.round(cy);
9237
10198
  const existing = rows.get(key);
9238
10199
  if (existing) {
9239
- existing.minX = Math.min(existing.minX, left);
9240
- existing.maxX = Math.max(existing.maxX, right);
10200
+ existing.minX = Math.min(existing.minX, left2);
10201
+ existing.maxX = Math.max(existing.maxX, right2);
9241
10202
  } else {
9242
- rows.set(key, { minX: left, maxX: right, bandY: cy });
10203
+ rows.set(key, { minX: left2, maxX: right2, bandY: cy });
9243
10204
  }
9244
10205
  }
9245
10206
  const bandScale = scales.y.scale;
@@ -9264,6 +10225,9 @@ function compileChart(spec, options) {
9264
10225
  if ("type" in normalized && normalized.type === "graph") {
9265
10226
  throw new Error("compileChart received a graph spec. Use compileGraph instead.");
9266
10227
  }
10228
+ if ("type" in normalized && normalized.type === "sankey") {
10229
+ throw new Error("compileChart received a sankey spec. Use compileSankey instead.");
10230
+ }
9267
10231
  let chartSpec = normalized;
9268
10232
  const rawTransforms = spec.transform;
9269
10233
  if (rawTransforms && rawTransforms.length > 0) {
@@ -9313,9 +10277,9 @@ function compileChart(spec, options) {
9313
10277
  const rawAnimationSpec = overrides?.[breakpoint]?.animation ?? rawSpec.animation;
9314
10278
  const resolvedAnimation = resolveAnimation(rawAnimationSpec);
9315
10279
  const mergedThemeConfig = options.theme ? { ...chartSpec.theme, ...options.theme } : chartSpec.theme;
9316
- let theme = resolveTheme2(mergedThemeConfig);
10280
+ let theme = resolveTheme3(mergedThemeConfig);
9317
10281
  if (options.darkMode) {
9318
- theme = adaptTheme2(theme);
10282
+ theme = adaptTheme3(theme);
9319
10283
  }
9320
10284
  const preliminaryArea = {
9321
10285
  x: 0,
@@ -9577,15 +10541,18 @@ function compileTable(spec, options) {
9577
10541
  }
9578
10542
  const tableSpec = normalized;
9579
10543
  const mergedThemeConfig = options.theme ? { ...tableSpec.theme, ...options.theme } : tableSpec.theme;
9580
- let theme = resolveTheme2(mergedThemeConfig);
10544
+ let theme = resolveTheme3(mergedThemeConfig);
9581
10545
  if (options.darkMode) {
9582
- theme = adaptTheme2(theme);
10546
+ theme = adaptTheme3(theme);
9583
10547
  }
9584
10548
  return compileTableLayout(tableSpec, options, theme);
9585
10549
  }
9586
10550
  function compileGraph2(spec, options) {
9587
10551
  return compileGraph(spec, options);
9588
10552
  }
10553
+ function compileSankey2(spec, options) {
10554
+ return compileSankey(spec, options);
10555
+ }
9589
10556
  export {
9590
10557
  clampStaggerDelay,
9591
10558
  clearRenderers,
@@ -9593,6 +10560,7 @@ export {
9593
10560
  compileChart,
9594
10561
  compileGraph2 as compileGraph,
9595
10562
  compileLayer,
10563
+ compileSankey2 as compileSankey,
9596
10564
  compileTable,
9597
10565
  evaluatePredicate,
9598
10566
  getChartRenderer,