@opendata-ai/openchart-engine 6.22.0 → 6.23.1

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
@@ -35,9 +35,9 @@ function computeTextBounds(labelX, labelY, text, fontSize, fontWeight) {
35
35
  const isMultiLine = lines.length > 1;
36
36
  const maxWidth = Math.max(...lines.map((line) => estimateTextWidth(line, fontSize, fontWeight)));
37
37
  const totalHeight = lines.length * fontSize * DEFAULT_LINE_HEIGHT;
38
- const x = isMultiLine ? labelX - maxWidth / 2 : labelX;
38
+ const x2 = isMultiLine ? labelX - maxWidth / 2 : labelX;
39
39
  return {
40
- x,
40
+ x: x2,
41
41
  y: labelY - fontSize,
42
42
  width: maxWidth,
43
43
  height: totalHeight
@@ -395,25 +395,25 @@ function resolveTextAnnotation(annotation, scales, chartArea, isDark) {
395
395
 
396
396
  // src/annotations/resolve-range.ts
397
397
  function resolveRangeAnnotation(annotation, scales, chartArea, isDark) {
398
- let x = chartArea.x;
399
- let y = chartArea.y;
398
+ let x2 = chartArea.x;
399
+ let y2 = chartArea.y;
400
400
  let width = chartArea.width;
401
401
  let height = chartArea.height;
402
402
  if (annotation.x1 !== void 0 && annotation.x2 !== void 0) {
403
403
  const x1px = resolvePosition(annotation.x1, scales.x);
404
404
  const x2px = resolvePosition(annotation.x2, scales.x);
405
405
  if (x1px === null || x2px === null) return null;
406
- x = Math.min(x1px, x2px);
406
+ x2 = Math.min(x1px, x2px);
407
407
  width = Math.abs(x2px - x1px);
408
408
  }
409
409
  if (annotation.y1 !== void 0 && annotation.y2 !== void 0) {
410
410
  const y1px = resolvePosition(annotation.y1, scales.y);
411
411
  const y2px = resolvePosition(annotation.y2, scales.y);
412
412
  if (y1px === null || y2px === null) return null;
413
- y = Math.min(y1px, y2px);
413
+ y2 = Math.min(y1px, y2px);
414
414
  height = Math.abs(y2px - y1px);
415
415
  }
416
- const rect = { x, y, width, height };
416
+ const rect = { x: x2, y: y2, width, height };
417
417
  let label;
418
418
  if (annotation.label) {
419
419
  const anchor = annotation.labelAnchor ?? "top";
@@ -427,11 +427,11 @@ function resolveRangeAnnotation(annotation, scales, chartArea, isDark) {
427
427
  } else if (anchor === "right") {
428
428
  style.textAnchor = "end";
429
429
  }
430
- const baseX = centered ? x + width / 2 : anchor === "right" ? x + width : x;
430
+ const baseX = centered ? x2 + width / 2 : anchor === "right" ? x2 + width : x2;
431
431
  label = {
432
432
  text: annotation.label,
433
433
  x: baseX + labelDelta.dx,
434
- y: y + labelDelta.dy,
434
+ y: y2 + labelDelta.dy,
435
435
  style,
436
436
  visible: true
437
437
  };
@@ -581,74 +581,2684 @@ function computeAnnotations(spec, scales, chartArea, strategy, isDark = false, o
581
581
  return annotations;
582
582
  }
583
583
 
584
+ // src/charts/bar/compute.ts
585
+ import { isGradientDef } from "@opendata-ai/openchart-core";
586
+
584
587
  // src/transforms/predicates.ts
585
588
  function isFieldPredicate(pred) {
586
589
  return "field" in pred;
587
590
  }
588
- function evaluateFieldPredicate(datum, pred) {
589
- const value2 = datum[pred.field];
590
- if (pred.valid !== void 0) {
591
- const isValid = value2 !== null && value2 !== void 0 && !Number.isNaN(value2);
592
- return pred.valid ? isValid : !isValid;
591
+ function evaluateFieldPredicate(datum, pred) {
592
+ const value2 = datum[pred.field];
593
+ if (pred.valid !== void 0) {
594
+ const isValid = value2 !== null && value2 !== void 0 && !Number.isNaN(value2);
595
+ return pred.valid ? isValid : !isValid;
596
+ }
597
+ if (pred.equal !== void 0) {
598
+ return value2 == pred.equal;
599
+ }
600
+ const numValue = Number(value2);
601
+ if (pred.lt !== void 0) {
602
+ return numValue < pred.lt;
603
+ }
604
+ if (pred.lte !== void 0) {
605
+ return numValue <= pred.lte;
606
+ }
607
+ if (pred.gt !== void 0) {
608
+ return numValue > pred.gt;
609
+ }
610
+ if (pred.gte !== void 0) {
611
+ return numValue >= pred.gte;
612
+ }
613
+ if (pred.range !== void 0) {
614
+ const [min4, max4] = pred.range;
615
+ return numValue >= min4 && numValue <= max4;
616
+ }
617
+ if (pred.oneOf !== void 0) {
618
+ return pred.oneOf.some((v) => v == value2);
619
+ }
620
+ return true;
621
+ }
622
+ function evaluatePredicate(datum, predicate) {
623
+ if (isFieldPredicate(predicate)) {
624
+ return evaluateFieldPredicate(datum, predicate);
625
+ }
626
+ if ("and" in predicate) {
627
+ return predicate.and.every((p) => evaluatePredicate(datum, p));
628
+ }
629
+ if ("or" in predicate) {
630
+ return predicate.or.some((p) => evaluatePredicate(datum, p));
631
+ }
632
+ if ("not" in predicate) {
633
+ return !evaluatePredicate(datum, predicate.not);
634
+ }
635
+ return true;
636
+ }
637
+
638
+ // src/transforms/conditional.ts
639
+ function resolveConditionalValue(datum, channelDef) {
640
+ const conditions = Array.isArray(channelDef.condition) ? channelDef.condition : [channelDef.condition];
641
+ for (const cond of conditions) {
642
+ if (evaluatePredicate(datum, cond.test)) {
643
+ if (cond.field !== void 0) {
644
+ return datum[cond.field];
645
+ }
646
+ return cond.value;
647
+ }
648
+ }
649
+ return channelDef.value;
650
+ }
651
+ function isConditionalValueDef(def) {
652
+ return def !== null && typeof def === "object" && "condition" in def;
653
+ }
654
+
655
+ // src/charts/_shared/format-label-value.ts
656
+ import { abbreviateNumber, formatNumber } from "@opendata-ai/openchart-core";
657
+ function formatLabelValue(value2) {
658
+ if (Math.abs(value2) >= 1e3) return abbreviateNumber(value2);
659
+ return formatNumber(value2);
660
+ }
661
+
662
+ // src/charts/utils.ts
663
+ var DEFAULT_COLOR = "#1b7fa3";
664
+ function scaleValue(scale, scaleType, value2) {
665
+ if (value2 == null) return null;
666
+ if (scaleType === "time" || scaleType === "utc") {
667
+ const date2 = value2 instanceof Date ? value2 : new Date(String(value2));
668
+ if (Number.isNaN(date2.getTime())) return null;
669
+ return scale(date2);
670
+ }
671
+ if (scaleType === "point" || scaleType === "band" || scaleType === "ordinal") {
672
+ const result = scale(String(value2));
673
+ return result ?? null;
674
+ }
675
+ const num = typeof value2 === "number" ? value2 : Number(value2);
676
+ if (!Number.isFinite(num)) return null;
677
+ return scale(num);
678
+ }
679
+ function groupByField(data, field) {
680
+ const groups = /* @__PURE__ */ new Map();
681
+ if (!field) {
682
+ groups.set("__default__", data);
683
+ return groups;
684
+ }
685
+ for (const row of data) {
686
+ const key = String(row[field] ?? "__default__");
687
+ const existing = groups.get(key);
688
+ if (existing) {
689
+ existing.push(row);
690
+ } else {
691
+ groups.set(key, [row]);
692
+ }
693
+ }
694
+ return groups;
695
+ }
696
+ function sortByField(data, field) {
697
+ if (data.length <= 1) return [...data];
698
+ return [...data].sort((a, b) => {
699
+ const aVal = a[field];
700
+ const bVal = b[field];
701
+ if (aVal == null && bVal == null) return 0;
702
+ if (aVal == null) return 1;
703
+ if (bVal == null) return -1;
704
+ if (typeof aVal === "number" && typeof bVal === "number") {
705
+ return aVal - bVal;
706
+ }
707
+ if (aVal instanceof Date && bVal instanceof Date) {
708
+ return aVal.getTime() - bVal.getTime();
709
+ }
710
+ const aStr = String(aVal);
711
+ const bStr = String(bVal);
712
+ const aNum = Number(aStr);
713
+ const bNum = Number(bStr);
714
+ if (Number.isFinite(aNum) && Number.isFinite(bNum)) {
715
+ return aNum - bNum;
716
+ }
717
+ return aStr.localeCompare(bStr);
718
+ });
719
+ }
720
+ function getColor(scales, key, _index, fallback = DEFAULT_COLOR) {
721
+ if (scales.color && key !== "__default__") {
722
+ const colorScale = scales.color.scale;
723
+ return colorScale(key);
724
+ }
725
+ return scales.defaultColor ?? fallback;
726
+ }
727
+ function getSequentialColor(scales, value2, fallback = DEFAULT_COLOR) {
728
+ if (scales.color?.type === "sequential") {
729
+ const colorScale = scales.color.scale;
730
+ return colorScale(value2);
731
+ }
732
+ return scales.defaultColor ?? fallback;
733
+ }
734
+
735
+ // src/charts/bar/compute.ts
736
+ function orientGradientForHorizontalBar(grad) {
737
+ if (grad.gradient !== "linear") return grad;
738
+ const lg = grad;
739
+ const isDefaultVertical = (lg.x1 === void 0 || lg.x1 === 0) && (lg.y1 === void 0 || lg.y1 === 0) && (lg.x2 === void 0 || lg.x2 === 0) && (lg.y2 === void 0 || lg.y2 === 1);
740
+ if (!isDefaultVertical) return grad;
741
+ return { ...lg, x1: 0, y1: 0, x2: 1, y2: 0 };
742
+ }
743
+ var MIN_BAR_WIDTH = 1;
744
+ function computeBarMarks(spec, scales, _chartArea, _strategy) {
745
+ const encoding = spec.encoding;
746
+ const xChannel = encoding.x;
747
+ const yChannel = encoding.y;
748
+ if (!xChannel || !yChannel || !scales.x || !scales.y) {
749
+ return [];
750
+ }
751
+ const yScale = scales.y.scale;
752
+ const xScale = scales.x.scale;
753
+ if (typeof yScale.bandwidth !== "function") {
754
+ return [];
755
+ }
756
+ const bandwidth = yScale.bandwidth();
757
+ const baseline = xScale(0);
758
+ const colorEnc = encoding.color && "field" in encoding.color ? encoding.color : void 0;
759
+ const conditionalColor = encoding.color && isConditionalValueDef(encoding.color) ? encoding.color : void 0;
760
+ const colorField = colorEnc?.field;
761
+ const isSequentialColor = colorEnc?.type === "quantitative";
762
+ if (!colorField || isSequentialColor) {
763
+ return computeSimpleBars(
764
+ spec.data,
765
+ xChannel.field,
766
+ yChannel.field,
767
+ xScale,
768
+ yScale,
769
+ bandwidth,
770
+ baseline,
771
+ scales,
772
+ isSequentialColor,
773
+ conditionalColor
774
+ );
775
+ }
776
+ const categoryGroups = groupByField(spec.data, yChannel.field);
777
+ const needsStacking = Array.from(categoryGroups.values()).some((rows) => rows.length > 1);
778
+ if (needsStacking) {
779
+ const stackDisabled = xChannel.stack === null || xChannel.stack === false;
780
+ if (stackDisabled) {
781
+ return computeGroupedBars(
782
+ spec.data,
783
+ xChannel.field,
784
+ yChannel.field,
785
+ colorField,
786
+ xScale,
787
+ yScale,
788
+ bandwidth,
789
+ baseline,
790
+ scales
791
+ );
792
+ }
793
+ const stackMode = xChannel.stack === "normalize" ? "normalize" : xChannel.stack === "center" ? "center" : "zero";
794
+ return computeStackedBars(
795
+ spec.data,
796
+ xChannel.field,
797
+ yChannel.field,
798
+ colorField,
799
+ xScale,
800
+ yScale,
801
+ bandwidth,
802
+ baseline,
803
+ scales,
804
+ stackMode
805
+ );
806
+ }
807
+ return computeColoredBars(
808
+ spec.data,
809
+ xChannel.field,
810
+ yChannel.field,
811
+ colorField,
812
+ xScale,
813
+ yScale,
814
+ bandwidth,
815
+ baseline,
816
+ scales
817
+ );
818
+ }
819
+ function computeStackedBars(data, valueField, categoryField, colorField, xScale, yScale, bandwidth, _baseline, scales, stackMode = "zero") {
820
+ const marks = [];
821
+ const categoryGroups = groupByField(data, categoryField);
822
+ for (const [category, rows] of categoryGroups) {
823
+ const bandY = yScale(category);
824
+ if (bandY === void 0) continue;
825
+ let categoryTotal = 0;
826
+ for (const row of rows) {
827
+ const v = Number(row[valueField] ?? 0);
828
+ if (Number.isFinite(v) && v > 0) categoryTotal += v;
829
+ }
830
+ let cumulativeValue = stackMode === "center" ? -categoryTotal / 2 : 0;
831
+ for (const row of rows) {
832
+ const groupKey2 = String(row[colorField] ?? "");
833
+ const rawValue = Number(row[valueField] ?? 0);
834
+ if (!Number.isFinite(rawValue) || rawValue <= 0) continue;
835
+ const value2 = stackMode === "normalize" && categoryTotal > 0 ? rawValue / categoryTotal : rawValue;
836
+ const color2 = getColor(scales, groupKey2);
837
+ const xLeft = xScale(cumulativeValue);
838
+ const xRight = xScale(cumulativeValue + value2);
839
+ const barWidth = Math.max(Math.abs(xRight - xLeft), MIN_BAR_WIDTH);
840
+ const aria = {
841
+ label: `${category}, ${groupKey2}: ${formatLabelValue(rawValue)}`
842
+ };
843
+ marks.push({
844
+ type: "rect",
845
+ x: Math.min(xLeft, xRight),
846
+ y: bandY,
847
+ width: barWidth,
848
+ height: bandwidth,
849
+ fill: isGradientDef(color2) ? orientGradientForHorizontalBar(color2) : color2,
850
+ cornerRadius: 0,
851
+ data: row,
852
+ aria,
853
+ orient: "horizontal",
854
+ stackGroup: category
855
+ });
856
+ cumulativeValue += value2;
857
+ }
858
+ }
859
+ return marks;
860
+ }
861
+ function computeGroupedBars(data, valueField, categoryField, colorField, xScale, yScale, bandwidth, baseline, scales) {
862
+ const marks = [];
863
+ const categoryGroups = groupByField(data, categoryField);
864
+ const groupIndexMap = /* @__PURE__ */ new Map();
865
+ for (const row of data) {
866
+ const key = String(row[colorField] ?? "");
867
+ if (!groupIndexMap.has(key)) {
868
+ groupIndexMap.set(key, groupIndexMap.size);
869
+ }
870
+ }
871
+ const groupCount = groupIndexMap.size;
872
+ if (groupCount === 0) return marks;
873
+ const gap = Math.min(1, bandwidth * 0.05);
874
+ const subBandHeight = Math.max((bandwidth - gap * (groupCount - 1)) / groupCount, MIN_BAR_WIDTH);
875
+ for (const [category, rows] of categoryGroups) {
876
+ const bandY = yScale(category);
877
+ if (bandY === void 0) continue;
878
+ for (const row of rows) {
879
+ const groupKey2 = String(row[colorField] ?? "");
880
+ const value2 = Number(row[valueField] ?? 0);
881
+ if (!Number.isFinite(value2)) continue;
882
+ const groupIndex = groupIndexMap.get(groupKey2) ?? 0;
883
+ const color2 = getColor(scales, groupKey2);
884
+ const xPos = value2 >= 0 ? baseline : xScale(value2);
885
+ const barWidth = Math.max(Math.abs(xScale(value2) - baseline), MIN_BAR_WIDTH);
886
+ const subY = bandY + groupIndex * (subBandHeight + gap);
887
+ const aria = {
888
+ label: `${category}, ${groupKey2}: ${formatLabelValue(value2)}`
889
+ };
890
+ marks.push({
891
+ type: "rect",
892
+ x: xPos,
893
+ y: subY,
894
+ width: barWidth,
895
+ height: subBandHeight,
896
+ fill: isGradientDef(color2) ? orientGradientForHorizontalBar(color2) : color2,
897
+ cornerRadius: 2,
898
+ data: row,
899
+ aria,
900
+ orient: "horizontal"
901
+ });
902
+ }
903
+ }
904
+ return marks;
905
+ }
906
+ function computeColoredBars(data, valueField, categoryField, colorField, xScale, yScale, bandwidth, baseline, scales) {
907
+ const marks = [];
908
+ for (const row of data) {
909
+ const category = String(row[categoryField] ?? "");
910
+ const value2 = Number(row[valueField] ?? 0);
911
+ if (!Number.isFinite(value2)) continue;
912
+ const bandY = yScale(category);
913
+ if (bandY === void 0) continue;
914
+ const groupKey2 = String(row[colorField] ?? "");
915
+ const color2 = getColor(scales, groupKey2);
916
+ const xPos = value2 >= 0 ? baseline : xScale(value2);
917
+ const barWidth = Math.max(Math.abs(xScale(value2) - baseline), MIN_BAR_WIDTH);
918
+ const aria = {
919
+ label: `${category}, ${groupKey2}: ${formatLabelValue(value2)}`
920
+ };
921
+ marks.push({
922
+ type: "rect",
923
+ x: xPos,
924
+ y: bandY,
925
+ width: barWidth,
926
+ height: bandwidth,
927
+ fill: isGradientDef(color2) ? orientGradientForHorizontalBar(color2) : color2,
928
+ cornerRadius: 2,
929
+ data: row,
930
+ aria,
931
+ orient: "horizontal"
932
+ });
933
+ }
934
+ return marks;
935
+ }
936
+ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, bandwidth, baseline, scales, sequentialColor = false, conditionalColor) {
937
+ const marks = [];
938
+ for (const row of data) {
939
+ const category = String(row[categoryField] ?? "");
940
+ const value2 = Number(row[valueField] ?? 0);
941
+ if (!Number.isFinite(value2)) continue;
942
+ const bandY = yScale(category);
943
+ if (bandY === void 0) continue;
944
+ let color2;
945
+ if (conditionalColor) {
946
+ const resolved = resolveConditionalValue(row, conditionalColor);
947
+ if (resolved != null) {
948
+ color2 = isGradientDef(resolved) ? resolved : String(resolved);
949
+ } else {
950
+ color2 = getColor(scales, "__default__");
951
+ }
952
+ } else if (sequentialColor) {
953
+ color2 = getSequentialColor(scales, value2);
954
+ } else {
955
+ color2 = getColor(scales, "__default__");
956
+ }
957
+ const xPos = value2 >= 0 ? baseline : xScale(value2);
958
+ const barWidth = Math.max(Math.abs(xScale(value2) - baseline), MIN_BAR_WIDTH);
959
+ const aria = {
960
+ label: `${category}: ${formatLabelValue(value2)}`
961
+ };
962
+ marks.push({
963
+ type: "rect",
964
+ x: xPos,
965
+ y: bandY,
966
+ width: barWidth,
967
+ height: bandwidth,
968
+ fill: isGradientDef(color2) ? orientGradientForHorizontalBar(color2) : color2,
969
+ cornerRadius: 2,
970
+ data: row,
971
+ aria,
972
+ orient: "horizontal"
973
+ });
974
+ }
975
+ return marks;
976
+ }
977
+
978
+ // src/charts/bar/labels.ts
979
+ import {
980
+ buildD3Formatter,
981
+ estimateTextWidth as estimateTextWidth2,
982
+ getRepresentativeColor,
983
+ resolveCollisions
984
+ } from "@opendata-ai/openchart-core";
985
+
986
+ // src/charts/_shared/density-filter.ts
987
+ function filterByDensity(marks, density) {
988
+ if (density === "none") return [];
989
+ if (density === "endpoints" && marks.length > 1) {
990
+ return [marks[0], marks[marks.length - 1]];
991
+ }
992
+ return marks;
993
+ }
994
+
995
+ // src/charts/bar/labels.ts
996
+ var SUFFIX_MULTIPLIERS = {
997
+ K: 1e3,
998
+ M: 1e6,
999
+ B: 1e9,
1000
+ T: 1e12
1001
+ };
1002
+ function parseDisplayNumber(raw) {
1003
+ const trimmed = raw.trim().replace(/\u2212/g, "-");
1004
+ if (!trimmed) return NaN;
1005
+ const last = trimmed[trimmed.length - 1].toUpperCase();
1006
+ const multiplier = SUFFIX_MULTIPLIERS[last];
1007
+ if (multiplier) {
1008
+ const numPart = trimmed.slice(0, -1).replace(/,/g, "");
1009
+ const n = Number(numPart);
1010
+ return Number.isNaN(n) ? NaN : n * multiplier;
1011
+ }
1012
+ if (last === "%") {
1013
+ return Number(trimmed.slice(0, -1).replace(/,/g, ""));
1014
+ }
1015
+ return Number(trimmed.replace(/,/g, ""));
1016
+ }
1017
+ var LABEL_FONT_SIZE = 11;
1018
+ var LABEL_FONT_WEIGHT = 600;
1019
+ var LABEL_PADDING = 6;
1020
+ var MIN_WIDTH_FOR_INSIDE_LABEL = 40;
1021
+ function computeBarLabels(marks, _chartArea, density = "auto", labelFormat, labelPrefix, valueField) {
1022
+ const targetMarks = filterByDensity(marks, density);
1023
+ const candidates = [];
1024
+ const fitsInSegment = [];
1025
+ const formatter = buildD3Formatter(labelFormat);
1026
+ for (const mark of targetMarks) {
1027
+ let valuePart;
1028
+ const rawNum = valueField != null ? Number(mark.data[valueField]) : NaN;
1029
+ if (formatter && Number.isFinite(rawNum)) {
1030
+ valuePart = formatter(rawNum);
1031
+ } else if (Number.isFinite(rawNum)) {
1032
+ valuePart = formatLabelValue(rawNum);
1033
+ } else {
1034
+ const ariaLabel = mark.aria.label;
1035
+ const lastColon = ariaLabel.lastIndexOf(":");
1036
+ const rawValue = lastColon >= 0 ? ariaLabel.slice(lastColon + 1).trim() : "";
1037
+ if (!rawValue) continue;
1038
+ if (formatter) {
1039
+ const num = parseDisplayNumber(rawValue);
1040
+ valuePart = !Number.isNaN(num) ? formatter(num) : rawValue;
1041
+ } else {
1042
+ valuePart = rawValue;
1043
+ }
1044
+ }
1045
+ if (labelPrefix) valuePart = labelPrefix + valuePart;
1046
+ const textWidth = estimateTextWidth2(valuePart, LABEL_FONT_SIZE, LABEL_FONT_WEIGHT);
1047
+ const textHeight = LABEL_FONT_SIZE * 1.2;
1048
+ const isStacked = mark.cornerRadius === 0;
1049
+ const isInside = mark.width >= MIN_WIDTH_FOR_INSIDE_LABEL;
1050
+ let anchorX;
1051
+ let fill;
1052
+ let textAnchor;
1053
+ if (isStacked && isInside) {
1054
+ anchorX = mark.x + mark.width / 2;
1055
+ fill = "#ffffff";
1056
+ textAnchor = "middle";
1057
+ } else if (isInside) {
1058
+ anchorX = mark.x + mark.width - LABEL_PADDING;
1059
+ fill = "#ffffff";
1060
+ textAnchor = "end";
1061
+ } else {
1062
+ anchorX = mark.x + mark.width + LABEL_PADDING;
1063
+ fill = getRepresentativeColor(mark.fill);
1064
+ textAnchor = "start";
1065
+ }
1066
+ const anchorY = mark.y + mark.height / 2;
1067
+ const fits = !(isStacked && textWidth > mark.width - 2 * LABEL_PADDING);
1068
+ fitsInSegment.push(fits);
1069
+ candidates.push({
1070
+ text: valuePart,
1071
+ anchorX,
1072
+ anchorY,
1073
+ width: textWidth,
1074
+ height: textHeight,
1075
+ priority: "data",
1076
+ style: {
1077
+ fontFamily: "system-ui, -apple-system, sans-serif",
1078
+ fontSize: LABEL_FONT_SIZE,
1079
+ fontWeight: LABEL_FONT_WEIGHT,
1080
+ fill,
1081
+ lineHeight: 1.2,
1082
+ textAnchor,
1083
+ dominantBaseline: "central"
1084
+ }
1085
+ });
1086
+ }
1087
+ if (candidates.length === 0) return [];
1088
+ if (density === "all") {
1089
+ return candidates.map((c, i) => ({
1090
+ text: c.text,
1091
+ x: c.anchorX,
1092
+ y: c.anchorY,
1093
+ style: c.style,
1094
+ visible: fitsInSegment[i] !== false
1095
+ }));
1096
+ }
1097
+ const fittingCandidates = [];
1098
+ const unfittingIndices = /* @__PURE__ */ new Set();
1099
+ for (let i = 0; i < candidates.length; i++) {
1100
+ if (fitsInSegment[i] === false) {
1101
+ unfittingIndices.add(i);
1102
+ } else {
1103
+ fittingCandidates.push(candidates[i]);
1104
+ }
1105
+ }
1106
+ const resolved = resolveCollisions(fittingCandidates);
1107
+ const results = [];
1108
+ let resolvedIdx = 0;
1109
+ for (let i = 0; i < candidates.length; i++) {
1110
+ if (unfittingIndices.has(i)) {
1111
+ results.push({
1112
+ text: candidates[i].text,
1113
+ x: candidates[i].anchorX,
1114
+ y: candidates[i].anchorY,
1115
+ style: candidates[i].style,
1116
+ visible: false
1117
+ });
1118
+ } else {
1119
+ results.push(resolved[resolvedIdx++]);
1120
+ }
1121
+ }
1122
+ return results;
1123
+ }
1124
+
1125
+ // src/charts/bar/index.ts
1126
+ var barRenderer = (spec, scales, chartArea, strategy, _theme) => {
1127
+ const marks = computeBarMarks(spec, scales, chartArea, strategy);
1128
+ const valueField = spec.encoding?.x && "field" in spec.encoding.x ? spec.encoding.x.field : void 0;
1129
+ const labels = computeBarLabels(
1130
+ marks,
1131
+ chartArea,
1132
+ spec.labels.density,
1133
+ spec.labels.format,
1134
+ spec.labels.prefix,
1135
+ valueField
1136
+ );
1137
+ for (let i = 0; i < marks.length && i < labels.length; i++) {
1138
+ marks[i].label = labels[i];
1139
+ }
1140
+ return marks;
1141
+ };
1142
+
1143
+ // src/charts/column/compute.ts
1144
+ import { isGradientDef as isGradientDef2 } from "@opendata-ai/openchart-core";
1145
+ var MIN_COLUMN_HEIGHT = 1;
1146
+ function computeColumnMarks(spec, scales, _chartArea, _strategy) {
1147
+ const encoding = spec.encoding;
1148
+ const xChannel = encoding.x;
1149
+ const yChannel = encoding.y;
1150
+ if (!xChannel || !yChannel || !scales.x || !scales.y) {
1151
+ return [];
1152
+ }
1153
+ const xScale = scales.x.scale;
1154
+ const yScale = scales.y.scale;
1155
+ if (typeof xScale.bandwidth !== "function") {
1156
+ return [];
1157
+ }
1158
+ const bandwidth = xScale.bandwidth();
1159
+ const baseline = yScale(0);
1160
+ const colorEnc = encoding.color && "field" in encoding.color ? encoding.color : void 0;
1161
+ const conditionalColor = encoding.color && isConditionalValueDef(encoding.color) ? encoding.color : void 0;
1162
+ const colorField = colorEnc?.field;
1163
+ const isSequentialColor = colorEnc?.type === "quantitative";
1164
+ if (colorField && !isSequentialColor) {
1165
+ const categoryGroups = groupByField(spec.data, xChannel.field);
1166
+ const needsStacking = Array.from(categoryGroups.values()).some((rows) => rows.length > 1);
1167
+ if (needsStacking) {
1168
+ const stackDisabled = yChannel.stack === null || yChannel.stack === false;
1169
+ if (stackDisabled) {
1170
+ return computeGroupedColumns(
1171
+ spec.data,
1172
+ xChannel.field,
1173
+ yChannel.field,
1174
+ colorField,
1175
+ xScale,
1176
+ yScale,
1177
+ bandwidth,
1178
+ baseline,
1179
+ scales
1180
+ );
1181
+ }
1182
+ const stackMode = yChannel.stack === "normalize" ? "normalize" : yChannel.stack === "center" ? "center" : "zero";
1183
+ return computeStackedColumns(
1184
+ spec.data,
1185
+ xChannel.field,
1186
+ yChannel.field,
1187
+ colorField,
1188
+ xScale,
1189
+ yScale,
1190
+ bandwidth,
1191
+ baseline,
1192
+ scales,
1193
+ stackMode
1194
+ );
1195
+ }
1196
+ return computeColoredColumns(
1197
+ spec.data,
1198
+ xChannel.field,
1199
+ yChannel.field,
1200
+ colorField,
1201
+ xScale,
1202
+ yScale,
1203
+ bandwidth,
1204
+ baseline,
1205
+ scales
1206
+ );
1207
+ }
1208
+ return computeSimpleColumns(
1209
+ spec.data,
1210
+ xChannel.field,
1211
+ yChannel.field,
1212
+ xScale,
1213
+ yScale,
1214
+ bandwidth,
1215
+ baseline,
1216
+ scales,
1217
+ isSequentialColor,
1218
+ conditionalColor
1219
+ );
1220
+ }
1221
+ function computeSimpleColumns(data, categoryField, valueField, xScale, yScale, bandwidth, baseline, scales, sequentialColor = false, conditionalColor) {
1222
+ const marks = [];
1223
+ for (const row of data) {
1224
+ const category = String(row[categoryField] ?? "");
1225
+ const value2 = Number(row[valueField] ?? 0);
1226
+ if (!Number.isFinite(value2)) continue;
1227
+ const bandX = xScale(category);
1228
+ if (bandX === void 0) continue;
1229
+ let color2;
1230
+ if (conditionalColor) {
1231
+ const resolved = resolveConditionalValue(row, conditionalColor);
1232
+ if (resolved != null) {
1233
+ color2 = isGradientDef2(resolved) ? resolved : String(resolved);
1234
+ } else {
1235
+ color2 = getColor(scales, "__default__");
1236
+ }
1237
+ } else if (sequentialColor) {
1238
+ color2 = getSequentialColor(scales, value2);
1239
+ } else {
1240
+ color2 = getColor(scales, "__default__");
1241
+ }
1242
+ const yPos = yScale(value2);
1243
+ const columnHeight = Math.max(Math.abs(baseline - yPos), MIN_COLUMN_HEIGHT);
1244
+ const y2 = value2 >= 0 ? yPos : baseline;
1245
+ const aria = {
1246
+ label: `${category}: ${formatLabelValue(value2)}`
1247
+ };
1248
+ marks.push({
1249
+ type: "rect",
1250
+ x: bandX,
1251
+ y: y2,
1252
+ width: bandwidth,
1253
+ height: columnHeight,
1254
+ fill: color2,
1255
+ cornerRadius: 2,
1256
+ data: row,
1257
+ aria,
1258
+ orient: "vertical"
1259
+ });
1260
+ }
1261
+ return marks;
1262
+ }
1263
+ function computeColoredColumns(data, categoryField, valueField, colorField, xScale, yScale, bandwidth, baseline, scales) {
1264
+ const marks = [];
1265
+ for (const row of data) {
1266
+ const category = String(row[categoryField] ?? "");
1267
+ const value2 = Number(row[valueField] ?? 0);
1268
+ if (!Number.isFinite(value2)) continue;
1269
+ const bandX = xScale(category);
1270
+ if (bandX === void 0) continue;
1271
+ const groupKey2 = String(row[colorField] ?? "");
1272
+ const color2 = getColor(scales, groupKey2);
1273
+ const yPos = yScale(value2);
1274
+ const columnHeight = Math.max(Math.abs(baseline - yPos), MIN_COLUMN_HEIGHT);
1275
+ const y2 = value2 >= 0 ? yPos : baseline;
1276
+ const aria = {
1277
+ label: `${category}, ${groupKey2}: ${formatLabelValue(value2)}`
1278
+ };
1279
+ marks.push({
1280
+ type: "rect",
1281
+ x: bandX,
1282
+ y: y2,
1283
+ width: bandwidth,
1284
+ height: columnHeight,
1285
+ fill: color2,
1286
+ cornerRadius: 2,
1287
+ data: row,
1288
+ aria,
1289
+ orient: "vertical"
1290
+ });
1291
+ }
1292
+ return marks;
1293
+ }
1294
+ function computeGroupedColumns(data, categoryField, valueField, colorField, xScale, yScale, bandwidth, baseline, scales) {
1295
+ const marks = [];
1296
+ const categoryGroups = groupByField(data, categoryField);
1297
+ const groupIndexMap = /* @__PURE__ */ new Map();
1298
+ for (const row of data) {
1299
+ const key = String(row[colorField] ?? "");
1300
+ if (!groupIndexMap.has(key)) {
1301
+ groupIndexMap.set(key, groupIndexMap.size);
1302
+ }
1303
+ }
1304
+ const groupCount = groupIndexMap.size;
1305
+ if (groupCount === 0) return marks;
1306
+ const gap = Math.min(1, bandwidth * 0.05);
1307
+ const subBandWidth = Math.max(
1308
+ (bandwidth - gap * (groupCount - 1)) / groupCount,
1309
+ MIN_COLUMN_HEIGHT
1310
+ );
1311
+ for (const [category, rows] of categoryGroups) {
1312
+ const bandX = xScale(category);
1313
+ if (bandX === void 0) continue;
1314
+ for (const row of rows) {
1315
+ const groupKey2 = String(row[colorField] ?? "");
1316
+ const value2 = Number(row[valueField] ?? 0);
1317
+ if (!Number.isFinite(value2)) continue;
1318
+ const groupIndex = groupIndexMap.get(groupKey2) ?? 0;
1319
+ const color2 = getColor(scales, groupKey2);
1320
+ const yPos = yScale(value2);
1321
+ const columnHeight = Math.max(Math.abs(baseline - yPos), MIN_COLUMN_HEIGHT);
1322
+ const y2 = value2 >= 0 ? yPos : baseline;
1323
+ const subX = bandX + groupIndex * (subBandWidth + gap);
1324
+ const aria = {
1325
+ label: `${category}, ${groupKey2}: ${formatLabelValue(value2)}`
1326
+ };
1327
+ marks.push({
1328
+ type: "rect",
1329
+ x: subX,
1330
+ y: y2,
1331
+ width: subBandWidth,
1332
+ height: columnHeight,
1333
+ fill: color2,
1334
+ cornerRadius: 2,
1335
+ data: row,
1336
+ aria,
1337
+ orient: "vertical"
1338
+ });
1339
+ }
1340
+ }
1341
+ return marks;
1342
+ }
1343
+ function computeStackedColumns(data, categoryField, valueField, colorField, xScale, yScale, bandwidth, _baseline, scales, stackMode = "zero") {
1344
+ const marks = [];
1345
+ const categoryGroups = groupByField(data, categoryField);
1346
+ for (const [category, rows] of categoryGroups) {
1347
+ const bandX = xScale(category);
1348
+ if (bandX === void 0) continue;
1349
+ let categoryTotal = 0;
1350
+ for (const row of rows) {
1351
+ const v = Number(row[valueField] ?? 0);
1352
+ if (Number.isFinite(v) && v > 0) categoryTotal += v;
1353
+ }
1354
+ let cumulativeValue = stackMode === "center" ? -categoryTotal / 2 : 0;
1355
+ for (const row of rows) {
1356
+ const groupKey2 = String(row[colorField] ?? "");
1357
+ const rawValue = Number(row[valueField] ?? 0);
1358
+ if (!Number.isFinite(rawValue) || rawValue <= 0) continue;
1359
+ const value2 = stackMode === "normalize" && categoryTotal > 0 ? rawValue / categoryTotal : rawValue;
1360
+ const color2 = getColor(scales, groupKey2);
1361
+ const yTop = yScale(cumulativeValue + value2);
1362
+ const yBottom = yScale(cumulativeValue);
1363
+ const columnHeight = Math.max(Math.abs(yBottom - yTop), MIN_COLUMN_HEIGHT);
1364
+ const aria = {
1365
+ label: `${category}, ${groupKey2}: ${formatLabelValue(rawValue)}`
1366
+ };
1367
+ marks.push({
1368
+ type: "rect",
1369
+ x: bandX,
1370
+ y: Math.min(yTop, yBottom),
1371
+ width: bandwidth,
1372
+ height: columnHeight,
1373
+ fill: color2,
1374
+ cornerRadius: 0,
1375
+ data: row,
1376
+ aria,
1377
+ orient: "vertical",
1378
+ stackGroup: category
1379
+ });
1380
+ cumulativeValue += value2;
1381
+ }
1382
+ }
1383
+ return marks;
1384
+ }
1385
+
1386
+ // src/charts/column/labels.ts
1387
+ import {
1388
+ buildD3Formatter as buildD3Formatter2,
1389
+ estimateTextWidth as estimateTextWidth3,
1390
+ getRepresentativeColor as getRepresentativeColor2,
1391
+ resolveCollisions as resolveCollisions2
1392
+ } from "@opendata-ai/openchart-core";
1393
+ var LABEL_FONT_SIZE2 = 10;
1394
+ var LABEL_FONT_WEIGHT2 = 600;
1395
+ var LABEL_OFFSET_Y = 6;
1396
+ function computeColumnLabels(marks, _chartArea, density = "auto", labelFormat, labelPrefix, valueField) {
1397
+ const targetMarks = filterByDensity(marks, density);
1398
+ const formatter = buildD3Formatter2(labelFormat);
1399
+ const candidates = [];
1400
+ for (const mark of targetMarks) {
1401
+ let valuePart;
1402
+ const rawNum = valueField != null ? Number(mark.data[valueField]) : NaN;
1403
+ if (formatter && Number.isFinite(rawNum)) {
1404
+ valuePart = formatter(rawNum);
1405
+ } else if (Number.isFinite(rawNum)) {
1406
+ valuePart = formatLabelValue(rawNum);
1407
+ } else {
1408
+ const ariaLabel = mark.aria.label;
1409
+ const lastColon = ariaLabel.lastIndexOf(":");
1410
+ const rawValue = lastColon >= 0 ? ariaLabel.slice(lastColon + 1).trim() : "";
1411
+ if (!rawValue) continue;
1412
+ if (formatter) {
1413
+ const num = Number(rawValue.replace(/[^0-9.-]/g, ""));
1414
+ valuePart = !Number.isNaN(num) ? formatter(num) : rawValue;
1415
+ } else {
1416
+ valuePart = rawValue;
1417
+ }
1418
+ }
1419
+ if (labelPrefix) valuePart = labelPrefix + valuePart;
1420
+ const numericValue = parseFloat(valuePart);
1421
+ const isNegative = Number.isFinite(numericValue) && numericValue < 0;
1422
+ const textWidth = estimateTextWidth3(valuePart, LABEL_FONT_SIZE2, LABEL_FONT_WEIGHT2);
1423
+ const textHeight = LABEL_FONT_SIZE2 * 1.2;
1424
+ const anchorX = mark.x + mark.width / 2;
1425
+ const anchorY = isNegative ? mark.y + mark.height + LABEL_OFFSET_Y : mark.y - LABEL_OFFSET_Y - textHeight;
1426
+ candidates.push({
1427
+ text: valuePart,
1428
+ anchorX,
1429
+ anchorY,
1430
+ width: textWidth,
1431
+ height: textHeight,
1432
+ priority: "data",
1433
+ style: {
1434
+ fontFamily: "system-ui, -apple-system, sans-serif",
1435
+ fontSize: LABEL_FONT_SIZE2,
1436
+ fontWeight: LABEL_FONT_WEIGHT2,
1437
+ fill: getRepresentativeColor2(mark.fill),
1438
+ lineHeight: 1.2,
1439
+ textAnchor: "middle",
1440
+ dominantBaseline: isNegative ? "hanging" : "auto"
1441
+ }
1442
+ });
1443
+ }
1444
+ if (candidates.length === 0) return [];
1445
+ if (density === "all") {
1446
+ return candidates.map((c) => ({
1447
+ text: c.text,
1448
+ x: c.anchorX,
1449
+ y: c.anchorY,
1450
+ style: c.style,
1451
+ visible: true
1452
+ }));
1453
+ }
1454
+ return resolveCollisions2(candidates);
1455
+ }
1456
+
1457
+ // src/charts/column/index.ts
1458
+ var columnRenderer = (spec, scales, chartArea, strategy, _theme) => {
1459
+ const marks = computeColumnMarks(spec, scales, chartArea, strategy);
1460
+ const valueField = spec.encoding?.y && "field" in spec.encoding.y ? spec.encoding.y.field : void 0;
1461
+ const labels = computeColumnLabels(
1462
+ marks,
1463
+ chartArea,
1464
+ spec.labels.density,
1465
+ spec.labels.format,
1466
+ spec.labels.prefix,
1467
+ valueField
1468
+ );
1469
+ for (let i = 0; i < marks.length && i < labels.length; i++) {
1470
+ marks[i].label = labels[i];
1471
+ }
1472
+ return marks;
1473
+ };
1474
+
1475
+ // src/charts/dot/compute.ts
1476
+ var DOT_RADIUS = 6;
1477
+ var STEM_WIDTH = 2;
1478
+ var STEM_COLOR = "#cccccc";
1479
+ function computeDotMarks(spec, scales, _chartArea, _strategy) {
1480
+ const encoding = spec.encoding;
1481
+ const xChannel = encoding.x;
1482
+ const yChannel = encoding.y;
1483
+ if (!xChannel || !yChannel || !scales.x || !scales.y) {
1484
+ return [];
1485
+ }
1486
+ const xScale = scales.x.scale;
1487
+ const yScale = scales.y.scale;
1488
+ if (typeof yScale.bandwidth !== "function") {
1489
+ return [];
1490
+ }
1491
+ const bandwidth = yScale.bandwidth();
1492
+ const baseline = xScale(0);
1493
+ const colorEnc = encoding.color && "field" in encoding.color ? encoding.color : void 0;
1494
+ const isSequentialColor = colorEnc?.type === "quantitative";
1495
+ const colorField = isSequentialColor ? void 0 : colorEnc?.field;
1496
+ if (colorField) {
1497
+ return computeDumbbellMarks(
1498
+ spec.data,
1499
+ xChannel.field,
1500
+ yChannel.field,
1501
+ colorField,
1502
+ xScale,
1503
+ yScale,
1504
+ bandwidth,
1505
+ scales
1506
+ );
1507
+ }
1508
+ return computeLollipopMarks(
1509
+ spec.data,
1510
+ xChannel.field,
1511
+ yChannel.field,
1512
+ xScale,
1513
+ yScale,
1514
+ bandwidth,
1515
+ baseline,
1516
+ scales,
1517
+ isSequentialColor
1518
+ );
1519
+ }
1520
+ function computeDumbbellMarks(data, valueField, categoryField, colorField, xScale, yScale, bandwidth, scales) {
1521
+ const marks = [];
1522
+ const categoryGroups = groupByField([...data], categoryField);
1523
+ for (const [category, rows] of categoryGroups) {
1524
+ const bandY = yScale(category);
1525
+ if (bandY === void 0) continue;
1526
+ const cy = bandY + bandwidth / 2;
1527
+ const xValues = [];
1528
+ for (const row of rows) {
1529
+ const value2 = Number(row[valueField] ?? 0);
1530
+ if (Number.isFinite(value2)) xValues.push(value2);
1531
+ }
1532
+ if (xValues.length === 0) continue;
1533
+ const minVal = Math.min(...xValues);
1534
+ const maxVal = Math.max(...xValues);
1535
+ const xLeft = xScale(minVal);
1536
+ const xRight = xScale(maxVal);
1537
+ const barWidth = Math.abs(xRight - xLeft);
1538
+ if (barWidth > 0) {
1539
+ const stemAria = {
1540
+ label: `Range for ${category}: ${minVal} to ${maxVal}`
1541
+ };
1542
+ marks.push({
1543
+ type: "rect",
1544
+ x: Math.min(xLeft, xRight),
1545
+ y: cy - STEM_WIDTH / 2,
1546
+ width: barWidth,
1547
+ height: STEM_WIDTH,
1548
+ fill: STEM_COLOR,
1549
+ data: rows[0],
1550
+ aria: stemAria
1551
+ });
1552
+ }
1553
+ for (const row of rows) {
1554
+ const value2 = Number(row[valueField] ?? 0);
1555
+ if (!Number.isFinite(value2)) continue;
1556
+ const cx = xScale(value2);
1557
+ const colorCategory = String(row[colorField] ?? "");
1558
+ const color2 = getColor(scales, colorCategory);
1559
+ const dotAria = {
1560
+ label: `${category}, ${colorCategory}: ${value2}`
1561
+ };
1562
+ marks.push({
1563
+ type: "point",
1564
+ cx,
1565
+ cy,
1566
+ r: DOT_RADIUS,
1567
+ fill: color2,
1568
+ stroke: "#ffffff",
1569
+ strokeWidth: 2,
1570
+ data: row,
1571
+ aria: dotAria
1572
+ });
1573
+ }
1574
+ }
1575
+ return marks;
1576
+ }
1577
+ function computeLollipopMarks(data, valueField, categoryField, xScale, yScale, bandwidth, baseline, scales, isSequentialColor = false) {
1578
+ const marks = [];
1579
+ for (const row of data) {
1580
+ const category = String(row[categoryField] ?? "");
1581
+ const value2 = Number(row[valueField] ?? 0);
1582
+ if (!Number.isFinite(value2)) continue;
1583
+ const bandY = yScale(category);
1584
+ if (bandY === void 0) continue;
1585
+ const cx = xScale(value2);
1586
+ const cy = bandY + bandwidth / 2;
1587
+ const color2 = isSequentialColor ? getSequentialColor(scales, value2) : getColor(scales, "__default__");
1588
+ const stemX = Math.min(baseline, cx);
1589
+ const stemWidth = Math.abs(cx - baseline);
1590
+ if (stemWidth > 0) {
1591
+ const stemAria = {
1592
+ label: `Stem for ${category}`
1593
+ };
1594
+ marks.push({
1595
+ type: "rect",
1596
+ x: stemX,
1597
+ y: cy - STEM_WIDTH / 2,
1598
+ width: stemWidth,
1599
+ height: STEM_WIDTH,
1600
+ fill: STEM_COLOR,
1601
+ data: row,
1602
+ aria: stemAria
1603
+ });
1604
+ }
1605
+ const dotAria = {
1606
+ label: `${category}: ${value2}`
1607
+ };
1608
+ marks.push({
1609
+ type: "point",
1610
+ cx,
1611
+ cy,
1612
+ r: DOT_RADIUS,
1613
+ fill: color2,
1614
+ stroke: "#ffffff",
1615
+ strokeWidth: 2,
1616
+ data: row,
1617
+ aria: dotAria
1618
+ });
1619
+ }
1620
+ return marks;
1621
+ }
1622
+
1623
+ // src/charts/dot/labels.ts
1624
+ import {
1625
+ buildD3Formatter as buildD3Formatter3,
1626
+ estimateTextWidth as estimateTextWidth4,
1627
+ getRepresentativeColor as getRepresentativeColor3,
1628
+ resolveCollisions as resolveCollisions3
1629
+ } from "@opendata-ai/openchart-core";
1630
+ var LABEL_FONT_SIZE3 = 11;
1631
+ var LABEL_FONT_WEIGHT3 = 600;
1632
+ var LABEL_OFFSET_X = 10;
1633
+ function computeDotLabels(marks, _chartArea, density = "auto", labelPrefix, labelFormat, valueField) {
1634
+ const targetMarks = filterByDensity(marks, density);
1635
+ const formatter = buildD3Formatter3(labelFormat);
1636
+ const candidates = [];
1637
+ for (const mark of targetMarks) {
1638
+ let valuePart;
1639
+ const rawNum = valueField != null ? Number(mark.data[valueField]) : NaN;
1640
+ if (formatter && Number.isFinite(rawNum)) {
1641
+ valuePart = formatter(rawNum);
1642
+ } else if (Number.isFinite(rawNum)) {
1643
+ valuePart = formatLabelValue(rawNum);
1644
+ } else {
1645
+ const ariaLabel = mark.aria.label;
1646
+ const lastColon = ariaLabel.lastIndexOf(":");
1647
+ valuePart = lastColon >= 0 ? ariaLabel.slice(lastColon + 1).trim() : "";
1648
+ if (!valuePart) continue;
1649
+ if (formatter) {
1650
+ const num = Number(valuePart.replace(/[^0-9.-]/g, ""));
1651
+ if (!Number.isNaN(num)) valuePart = formatter(num);
1652
+ }
1653
+ }
1654
+ if (labelPrefix) valuePart = labelPrefix + valuePart;
1655
+ const textWidth = estimateTextWidth4(valuePart, LABEL_FONT_SIZE3, LABEL_FONT_WEIGHT3);
1656
+ const textHeight = LABEL_FONT_SIZE3 * 1.2;
1657
+ candidates.push({
1658
+ text: valuePart,
1659
+ anchorX: mark.cx + mark.r + LABEL_OFFSET_X,
1660
+ anchorY: mark.cy - textHeight / 2,
1661
+ width: textWidth,
1662
+ height: textHeight,
1663
+ priority: "data",
1664
+ style: {
1665
+ fontFamily: "system-ui, -apple-system, sans-serif",
1666
+ fontSize: LABEL_FONT_SIZE3,
1667
+ fontWeight: LABEL_FONT_WEIGHT3,
1668
+ fill: getRepresentativeColor3(mark.fill),
1669
+ lineHeight: 1.2,
1670
+ textAnchor: "start",
1671
+ dominantBaseline: "central"
1672
+ }
1673
+ });
1674
+ }
1675
+ if (candidates.length === 0) return [];
1676
+ if (density === "all") {
1677
+ return candidates.map((c) => ({
1678
+ text: c.text,
1679
+ x: c.anchorX,
1680
+ y: c.anchorY,
1681
+ style: c.style,
1682
+ visible: true
1683
+ }));
1684
+ }
1685
+ return resolveCollisions3(candidates);
1686
+ }
1687
+
1688
+ // src/charts/dot/index.ts
1689
+ var dotRenderer = (spec, scales, chartArea, strategy, _theme) => {
1690
+ const marks = computeDotMarks(spec, scales, chartArea, strategy);
1691
+ const pointMarks = marks.filter((m) => m.type === "point");
1692
+ const valueField = spec.encoding?.x && "field" in spec.encoding.x ? spec.encoding.x.field : void 0;
1693
+ const labels = computeDotLabels(
1694
+ pointMarks,
1695
+ chartArea,
1696
+ spec.labels.density,
1697
+ spec.labels.prefix,
1698
+ spec.labels.format,
1699
+ valueField
1700
+ );
1701
+ let labelIdx = 0;
1702
+ for (const mark of marks) {
1703
+ if (mark.type === "point" && labelIdx < labels.length) {
1704
+ mark.label = labels[labelIdx];
1705
+ labelIdx++;
1706
+ }
1707
+ }
1708
+ return marks;
1709
+ };
1710
+
1711
+ // src/charts/line/index.ts
1712
+ import { getRepresentativeColor as getRepresentativeColor6 } from "@opendata-ai/openchart-core";
1713
+
1714
+ // src/charts/line/area.ts
1715
+ import { getRepresentativeColor as getRepresentativeColor4 } from "@opendata-ai/openchart-core";
1716
+
1717
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/constant.js
1718
+ function constant_default(x2) {
1719
+ return function constant2() {
1720
+ return x2;
1721
+ };
1722
+ }
1723
+
1724
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/math.js
1725
+ var abs = Math.abs;
1726
+ var atan2 = Math.atan2;
1727
+ var cos = Math.cos;
1728
+ var max = Math.max;
1729
+ var min = Math.min;
1730
+ var sin = Math.sin;
1731
+ var sqrt = Math.sqrt;
1732
+ var epsilon = 1e-12;
1733
+ var pi = Math.PI;
1734
+ var halfPi = pi / 2;
1735
+ var tau = 2 * pi;
1736
+ function acos(x2) {
1737
+ return x2 > 1 ? 0 : x2 < -1 ? pi : Math.acos(x2);
1738
+ }
1739
+ function asin(x2) {
1740
+ return x2 >= 1 ? halfPi : x2 <= -1 ? -halfPi : Math.asin(x2);
1741
+ }
1742
+
1743
+ // ../../node_modules/.bun/d3-path@3.1.0/node_modules/d3-path/src/path.js
1744
+ var pi2 = Math.PI;
1745
+ var tau2 = 2 * pi2;
1746
+ var epsilon2 = 1e-6;
1747
+ var tauEpsilon = tau2 - epsilon2;
1748
+ function append(strings) {
1749
+ this._ += strings[0];
1750
+ for (let i = 1, n = strings.length; i < n; ++i) {
1751
+ this._ += arguments[i] + strings[i];
1752
+ }
1753
+ }
1754
+ function appendRound(digits) {
1755
+ let d = Math.floor(digits);
1756
+ if (!(d >= 0)) throw new Error(`invalid digits: ${digits}`);
1757
+ if (d > 15) return append;
1758
+ const k = 10 ** d;
1759
+ return function(strings) {
1760
+ this._ += strings[0];
1761
+ for (let i = 1, n = strings.length; i < n; ++i) {
1762
+ this._ += Math.round(arguments[i] * k) / k + strings[i];
1763
+ }
1764
+ };
1765
+ }
1766
+ var Path = class {
1767
+ constructor(digits) {
1768
+ this._x0 = this._y0 = // start of current subpath
1769
+ this._x1 = this._y1 = null;
1770
+ this._ = "";
1771
+ this._append = digits == null ? append : appendRound(digits);
1772
+ }
1773
+ moveTo(x2, y2) {
1774
+ this._append`M${this._x0 = this._x1 = +x2},${this._y0 = this._y1 = +y2}`;
1775
+ }
1776
+ closePath() {
1777
+ if (this._x1 !== null) {
1778
+ this._x1 = this._x0, this._y1 = this._y0;
1779
+ this._append`Z`;
1780
+ }
1781
+ }
1782
+ lineTo(x2, y2) {
1783
+ this._append`L${this._x1 = +x2},${this._y1 = +y2}`;
1784
+ }
1785
+ quadraticCurveTo(x1, y1, x2, y2) {
1786
+ this._append`Q${+x1},${+y1},${this._x1 = +x2},${this._y1 = +y2}`;
1787
+ }
1788
+ bezierCurveTo(x1, y1, x2, y2, x3, y3) {
1789
+ this._append`C${+x1},${+y1},${+x2},${+y2},${this._x1 = +x3},${this._y1 = +y3}`;
1790
+ }
1791
+ arcTo(x1, y1, x2, y2, r) {
1792
+ x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
1793
+ if (r < 0) throw new Error(`negative radius: ${r}`);
1794
+ let x0 = this._x1, y0 = this._y1, x21 = x2 - x1, y21 = y2 - y1, x01 = x0 - x1, y01 = y0 - y1, l01_2 = x01 * x01 + y01 * y01;
1795
+ if (this._x1 === null) {
1796
+ this._append`M${this._x1 = x1},${this._y1 = y1}`;
1797
+ } else if (!(l01_2 > epsilon2)) ;
1798
+ else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon2) || !r) {
1799
+ this._append`L${this._x1 = x1},${this._y1 = y1}`;
1800
+ } else {
1801
+ let x20 = x2 - x0, y20 = y2 - y0, l21_2 = x21 * x21 + y21 * y21, l20_2 = x20 * x20 + y20 * y20, l21 = Math.sqrt(l21_2), l01 = Math.sqrt(l01_2), l = r * Math.tan((pi2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), t01 = l / l01, t21 = l / l21;
1802
+ if (Math.abs(t01 - 1) > epsilon2) {
1803
+ this._append`L${x1 + t01 * x01},${y1 + t01 * y01}`;
1804
+ }
1805
+ this._append`A${r},${r},0,0,${+(y01 * x20 > x01 * y20)},${this._x1 = x1 + t21 * x21},${this._y1 = y1 + t21 * y21}`;
1806
+ }
1807
+ }
1808
+ arc(x2, y2, r, a0, a1, ccw) {
1809
+ x2 = +x2, y2 = +y2, r = +r, ccw = !!ccw;
1810
+ if (r < 0) throw new Error(`negative radius: ${r}`);
1811
+ let dx = r * Math.cos(a0), dy = r * Math.sin(a0), x0 = x2 + dx, y0 = y2 + dy, cw = 1 ^ ccw, da = ccw ? a0 - a1 : a1 - a0;
1812
+ if (this._x1 === null) {
1813
+ this._append`M${x0},${y0}`;
1814
+ } else if (Math.abs(this._x1 - x0) > epsilon2 || Math.abs(this._y1 - y0) > epsilon2) {
1815
+ this._append`L${x0},${y0}`;
1816
+ }
1817
+ if (!r) return;
1818
+ if (da < 0) da = da % tau2 + tau2;
1819
+ if (da > tauEpsilon) {
1820
+ this._append`A${r},${r},0,1,${cw},${x2 - dx},${y2 - dy}A${r},${r},0,1,${cw},${this._x1 = x0},${this._y1 = y0}`;
1821
+ } else if (da > epsilon2) {
1822
+ this._append`A${r},${r},0,${+(da >= pi2)},${cw},${this._x1 = x2 + r * Math.cos(a1)},${this._y1 = y2 + r * Math.sin(a1)}`;
1823
+ }
1824
+ }
1825
+ rect(x2, y2, w, h) {
1826
+ this._append`M${this._x0 = this._x1 = +x2},${this._y0 = this._y1 = +y2}h${w = +w}v${+h}h${-w}Z`;
1827
+ }
1828
+ toString() {
1829
+ return this._;
1830
+ }
1831
+ };
1832
+ function path() {
1833
+ return new Path();
1834
+ }
1835
+ path.prototype = Path.prototype;
1836
+
1837
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/path.js
1838
+ function withPath(shape) {
1839
+ let digits = 3;
1840
+ shape.digits = function(_) {
1841
+ if (!arguments.length) return digits;
1842
+ if (_ == null) {
1843
+ digits = null;
1844
+ } else {
1845
+ const d = Math.floor(_);
1846
+ if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);
1847
+ digits = d;
1848
+ }
1849
+ return shape;
1850
+ };
1851
+ return () => new Path(digits);
1852
+ }
1853
+
1854
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/arc.js
1855
+ function arcInnerRadius(d) {
1856
+ return d.innerRadius;
1857
+ }
1858
+ function arcOuterRadius(d) {
1859
+ return d.outerRadius;
1860
+ }
1861
+ function arcStartAngle(d) {
1862
+ return d.startAngle;
1863
+ }
1864
+ function arcEndAngle(d) {
1865
+ return d.endAngle;
1866
+ }
1867
+ function arcPadAngle(d) {
1868
+ return d && d.padAngle;
1869
+ }
1870
+ function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
1871
+ var x10 = x1 - x0, y10 = y1 - y0, x32 = x3 - x2, y32 = y3 - y2, t = y32 * x10 - x32 * y10;
1872
+ if (t * t < epsilon) return;
1873
+ t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t;
1874
+ return [x0 + t * x10, y0 + t * y10];
1875
+ }
1876
+ function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
1877
+ var x01 = x0 - x1, y01 = y0 - y1, lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x11 = x0 + ox, y11 = y0 + oy, x10 = x1 + ox, y10 = y1 + oy, x00 = (x11 + x10) / 2, y00 = (y11 + y10) / 2, dx = x10 - x11, dy = y10 - y11, d2 = dx * dx + dy * dy, r = r1 - rc, D = x11 * y10 - x10 * y11, d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x00, dy0 = cy0 - y00, dx1 = cx1 - x00, dy1 = cy1 - y00;
1878
+ if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
1879
+ return {
1880
+ cx: cx0,
1881
+ cy: cy0,
1882
+ x01: -ox,
1883
+ y01: -oy,
1884
+ x11: cx0 * (r1 / r - 1),
1885
+ y11: cy0 * (r1 / r - 1)
1886
+ };
1887
+ }
1888
+ function arc_default() {
1889
+ var innerRadius = arcInnerRadius, outerRadius = arcOuterRadius, cornerRadius = constant_default(0), padRadius = null, startAngle = arcStartAngle, endAngle = arcEndAngle, padAngle = arcPadAngle, context = null, path2 = withPath(arc);
1890
+ function arc() {
1891
+ var buffer, r, r0 = +innerRadius.apply(this, arguments), r1 = +outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) - halfPi, a1 = endAngle.apply(this, arguments) - halfPi, da = abs(a1 - a0), cw = a1 > a0;
1892
+ if (!context) context = buffer = path2();
1893
+ if (r1 < r0) r = r1, r1 = r0, r0 = r;
1894
+ if (!(r1 > epsilon)) context.moveTo(0, 0);
1895
+ else if (da > tau - epsilon) {
1896
+ context.moveTo(r1 * cos(a0), r1 * sin(a0));
1897
+ context.arc(0, 0, r1, a0, a1, !cw);
1898
+ if (r0 > epsilon) {
1899
+ context.moveTo(r0 * cos(a1), r0 * sin(a1));
1900
+ context.arc(0, 0, r0, a1, a0, cw);
1901
+ }
1902
+ } else {
1903
+ var a01 = a0, a11 = a1, a00 = a0, a10 = a1, da0 = da, da1 = da, ap = padAngle.apply(this, arguments) / 2, rp = ap > epsilon && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)), rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), rc0 = rc, rc1 = rc, t02, t12;
1904
+ if (rp > epsilon) {
1905
+ var p0 = asin(rp / r0 * sin(ap)), p1 = asin(rp / r1 * sin(ap));
1906
+ if ((da0 -= p0 * 2) > epsilon) p0 *= cw ? 1 : -1, a00 += p0, a10 -= p0;
1907
+ else da0 = 0, a00 = a10 = (a0 + a1) / 2;
1908
+ if ((da1 -= p1 * 2) > epsilon) p1 *= cw ? 1 : -1, a01 += p1, a11 -= p1;
1909
+ else da1 = 0, a01 = a11 = (a0 + a1) / 2;
1910
+ }
1911
+ var x01 = r1 * cos(a01), y01 = r1 * sin(a01), x10 = r0 * cos(a10), y10 = r0 * sin(a10);
1912
+ if (rc > epsilon) {
1913
+ var x11 = r1 * cos(a11), y11 = r1 * sin(a11), x00 = r0 * cos(a00), y00 = r0 * sin(a00), oc;
1914
+ if (da < pi) {
1915
+ if (oc = intersect(x01, y01, x00, y00, x11, y11, x10, y10)) {
1916
+ var ax = x01 - oc[0], ay = y01 - oc[1], bx = x11 - oc[0], by = y11 - oc[1], kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2), lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
1917
+ rc0 = min(rc, (r0 - lc) / (kc - 1));
1918
+ rc1 = min(rc, (r1 - lc) / (kc + 1));
1919
+ } else {
1920
+ rc0 = rc1 = 0;
1921
+ }
1922
+ }
1923
+ }
1924
+ if (!(da1 > epsilon)) context.moveTo(x01, y01);
1925
+ else if (rc1 > epsilon) {
1926
+ t02 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
1927
+ t12 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
1928
+ context.moveTo(t02.cx + t02.x01, t02.cy + t02.y01);
1929
+ if (rc1 < rc) context.arc(t02.cx, t02.cy, rc1, atan2(t02.y01, t02.x01), atan2(t12.y01, t12.x01), !cw);
1930
+ else {
1931
+ context.arc(t02.cx, t02.cy, rc1, atan2(t02.y01, t02.x01), atan2(t02.y11, t02.x11), !cw);
1932
+ context.arc(0, 0, r1, atan2(t02.cy + t02.y11, t02.cx + t02.x11), atan2(t12.cy + t12.y11, t12.cx + t12.x11), !cw);
1933
+ context.arc(t12.cx, t12.cy, rc1, atan2(t12.y11, t12.x11), atan2(t12.y01, t12.x01), !cw);
1934
+ }
1935
+ } else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
1936
+ if (!(r0 > epsilon) || !(da0 > epsilon)) context.lineTo(x10, y10);
1937
+ else if (rc0 > epsilon) {
1938
+ t02 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
1939
+ t12 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
1940
+ context.lineTo(t02.cx + t02.x01, t02.cy + t02.y01);
1941
+ if (rc0 < rc) context.arc(t02.cx, t02.cy, rc0, atan2(t02.y01, t02.x01), atan2(t12.y01, t12.x01), !cw);
1942
+ else {
1943
+ context.arc(t02.cx, t02.cy, rc0, atan2(t02.y01, t02.x01), atan2(t02.y11, t02.x11), !cw);
1944
+ context.arc(0, 0, r0, atan2(t02.cy + t02.y11, t02.cx + t02.x11), atan2(t12.cy + t12.y11, t12.cx + t12.x11), cw);
1945
+ context.arc(t12.cx, t12.cy, rc0, atan2(t12.y11, t12.x11), atan2(t12.y01, t12.x01), !cw);
1946
+ }
1947
+ } else context.arc(0, 0, r0, a10, a00, cw);
1948
+ }
1949
+ context.closePath();
1950
+ if (buffer) return context = null, buffer + "" || null;
1951
+ }
1952
+ arc.centroid = function() {
1953
+ var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2;
1954
+ return [cos(a) * r, sin(a) * r];
1955
+ };
1956
+ arc.innerRadius = function(_) {
1957
+ return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant_default(+_), arc) : innerRadius;
1958
+ };
1959
+ arc.outerRadius = function(_) {
1960
+ return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant_default(+_), arc) : outerRadius;
1961
+ };
1962
+ arc.cornerRadius = function(_) {
1963
+ return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant_default(+_), arc) : cornerRadius;
1964
+ };
1965
+ arc.padRadius = function(_) {
1966
+ return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant_default(+_), arc) : padRadius;
1967
+ };
1968
+ arc.startAngle = function(_) {
1969
+ return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant_default(+_), arc) : startAngle;
1970
+ };
1971
+ arc.endAngle = function(_) {
1972
+ return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant_default(+_), arc) : endAngle;
1973
+ };
1974
+ arc.padAngle = function(_) {
1975
+ return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant_default(+_), arc) : padAngle;
1976
+ };
1977
+ arc.context = function(_) {
1978
+ return arguments.length ? (context = _ == null ? null : _, arc) : context;
1979
+ };
1980
+ return arc;
1981
+ }
1982
+
1983
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/array.js
1984
+ var slice = Array.prototype.slice;
1985
+ function array_default(x2) {
1986
+ return typeof x2 === "object" && "length" in x2 ? x2 : Array.from(x2);
1987
+ }
1988
+
1989
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/curve/linear.js
1990
+ function Linear(context) {
1991
+ this._context = context;
1992
+ }
1993
+ Linear.prototype = {
1994
+ areaStart: function() {
1995
+ this._line = 0;
1996
+ },
1997
+ areaEnd: function() {
1998
+ this._line = NaN;
1999
+ },
2000
+ lineStart: function() {
2001
+ this._point = 0;
2002
+ },
2003
+ lineEnd: function() {
2004
+ if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
2005
+ this._line = 1 - this._line;
2006
+ },
2007
+ point: function(x2, y2) {
2008
+ x2 = +x2, y2 = +y2;
2009
+ switch (this._point) {
2010
+ case 0:
2011
+ this._point = 1;
2012
+ this._line ? this._context.lineTo(x2, y2) : this._context.moveTo(x2, y2);
2013
+ break;
2014
+ case 1:
2015
+ this._point = 2;
2016
+ // falls through
2017
+ default:
2018
+ this._context.lineTo(x2, y2);
2019
+ break;
2020
+ }
2021
+ }
2022
+ };
2023
+ function linear_default(context) {
2024
+ return new Linear(context);
2025
+ }
2026
+
2027
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/point.js
2028
+ function x(p) {
2029
+ return p[0];
2030
+ }
2031
+ function y(p) {
2032
+ return p[1];
2033
+ }
2034
+
2035
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/line.js
2036
+ function line_default(x2, y2) {
2037
+ var defined = constant_default(true), context = null, curve = linear_default, output = null, path2 = withPath(line);
2038
+ x2 = typeof x2 === "function" ? x2 : x2 === void 0 ? x : constant_default(x2);
2039
+ y2 = typeof y2 === "function" ? y2 : y2 === void 0 ? y : constant_default(y2);
2040
+ function line(data) {
2041
+ var i, n = (data = array_default(data)).length, d, defined0 = false, buffer;
2042
+ if (context == null) output = curve(buffer = path2());
2043
+ for (i = 0; i <= n; ++i) {
2044
+ if (!(i < n && defined(d = data[i], i, data)) === defined0) {
2045
+ if (defined0 = !defined0) output.lineStart();
2046
+ else output.lineEnd();
2047
+ }
2048
+ if (defined0) output.point(+x2(d, i, data), +y2(d, i, data));
2049
+ }
2050
+ if (buffer) return output = null, buffer + "" || null;
2051
+ }
2052
+ line.x = function(_) {
2053
+ return arguments.length ? (x2 = typeof _ === "function" ? _ : constant_default(+_), line) : x2;
2054
+ };
2055
+ line.y = function(_) {
2056
+ return arguments.length ? (y2 = typeof _ === "function" ? _ : constant_default(+_), line) : y2;
2057
+ };
2058
+ line.defined = function(_) {
2059
+ return arguments.length ? (defined = typeof _ === "function" ? _ : constant_default(!!_), line) : defined;
2060
+ };
2061
+ line.curve = function(_) {
2062
+ return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
2063
+ };
2064
+ line.context = function(_) {
2065
+ return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
2066
+ };
2067
+ return line;
2068
+ }
2069
+
2070
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/area.js
2071
+ function area_default(x0, y0, y1) {
2072
+ var x1 = null, defined = constant_default(true), context = null, curve = linear_default, output = null, path2 = withPath(area);
2073
+ x0 = typeof x0 === "function" ? x0 : x0 === void 0 ? x : constant_default(+x0);
2074
+ y0 = typeof y0 === "function" ? y0 : y0 === void 0 ? constant_default(0) : constant_default(+y0);
2075
+ y1 = typeof y1 === "function" ? y1 : y1 === void 0 ? y : constant_default(+y1);
2076
+ function area(data) {
2077
+ var i, j, k, n = (data = array_default(data)).length, d, defined0 = false, buffer, x0z = new Array(n), y0z = new Array(n);
2078
+ if (context == null) output = curve(buffer = path2());
2079
+ for (i = 0; i <= n; ++i) {
2080
+ if (!(i < n && defined(d = data[i], i, data)) === defined0) {
2081
+ if (defined0 = !defined0) {
2082
+ j = i;
2083
+ output.areaStart();
2084
+ output.lineStart();
2085
+ } else {
2086
+ output.lineEnd();
2087
+ output.lineStart();
2088
+ for (k = i - 1; k >= j; --k) {
2089
+ output.point(x0z[k], y0z[k]);
2090
+ }
2091
+ output.lineEnd();
2092
+ output.areaEnd();
2093
+ }
2094
+ }
2095
+ if (defined0) {
2096
+ x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
2097
+ output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
2098
+ }
2099
+ }
2100
+ if (buffer) return output = null, buffer + "" || null;
2101
+ }
2102
+ function arealine() {
2103
+ return line_default().defined(defined).curve(curve).context(context);
2104
+ }
2105
+ area.x = function(_) {
2106
+ return arguments.length ? (x0 = typeof _ === "function" ? _ : constant_default(+_), x1 = null, area) : x0;
2107
+ };
2108
+ area.x0 = function(_) {
2109
+ return arguments.length ? (x0 = typeof _ === "function" ? _ : constant_default(+_), area) : x0;
2110
+ };
2111
+ area.x1 = function(_) {
2112
+ return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant_default(+_), area) : x1;
2113
+ };
2114
+ area.y = function(_) {
2115
+ return arguments.length ? (y0 = typeof _ === "function" ? _ : constant_default(+_), y1 = null, area) : y0;
2116
+ };
2117
+ area.y0 = function(_) {
2118
+ return arguments.length ? (y0 = typeof _ === "function" ? _ : constant_default(+_), area) : y0;
2119
+ };
2120
+ area.y1 = function(_) {
2121
+ return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant_default(+_), area) : y1;
2122
+ };
2123
+ area.lineX0 = area.lineY0 = function() {
2124
+ return arealine().x(x0).y(y0);
2125
+ };
2126
+ area.lineY1 = function() {
2127
+ return arealine().x(x0).y(y1);
2128
+ };
2129
+ area.lineX1 = function() {
2130
+ return arealine().x(x1).y(y0);
2131
+ };
2132
+ area.defined = function(_) {
2133
+ return arguments.length ? (defined = typeof _ === "function" ? _ : constant_default(!!_), area) : defined;
2134
+ };
2135
+ area.curve = function(_) {
2136
+ return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
2137
+ };
2138
+ area.context = function(_) {
2139
+ return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
2140
+ };
2141
+ return area;
2142
+ }
2143
+
2144
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/descending.js
2145
+ function descending_default(a, b) {
2146
+ return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
2147
+ }
2148
+
2149
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/identity.js
2150
+ function identity_default(d) {
2151
+ return d;
2152
+ }
2153
+
2154
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/pie.js
2155
+ function pie_default() {
2156
+ var value2 = identity_default, sortValues = descending_default, sort = null, startAngle = constant_default(0), endAngle = constant_default(tau), padAngle = constant_default(0);
2157
+ function pie(data) {
2158
+ 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;
2159
+ for (i = 0; i < n; ++i) {
2160
+ if ((v = arcs[index[i] = i] = +value2(data[i], i, data)) > 0) {
2161
+ sum2 += v;
2162
+ }
2163
+ }
2164
+ if (sortValues != null) index.sort(function(i2, j2) {
2165
+ return sortValues(arcs[i2], arcs[j2]);
2166
+ });
2167
+ else if (sort != null) index.sort(function(i2, j2) {
2168
+ return sort(data[i2], data[j2]);
2169
+ });
2170
+ for (i = 0, k = sum2 ? (da - n * pa) / sum2 : 0; i < n; ++i, a0 = a1) {
2171
+ j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
2172
+ data: data[j],
2173
+ index: i,
2174
+ value: v,
2175
+ startAngle: a0,
2176
+ endAngle: a1,
2177
+ padAngle: p
2178
+ };
2179
+ }
2180
+ return arcs;
2181
+ }
2182
+ pie.value = function(_) {
2183
+ return arguments.length ? (value2 = typeof _ === "function" ? _ : constant_default(+_), pie) : value2;
2184
+ };
2185
+ pie.sortValues = function(_) {
2186
+ return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
2187
+ };
2188
+ pie.sort = function(_) {
2189
+ return arguments.length ? (sort = _, sortValues = null, pie) : sort;
2190
+ };
2191
+ pie.startAngle = function(_) {
2192
+ return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant_default(+_), pie) : startAngle;
2193
+ };
2194
+ pie.endAngle = function(_) {
2195
+ return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant_default(+_), pie) : endAngle;
2196
+ };
2197
+ pie.padAngle = function(_) {
2198
+ return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant_default(+_), pie) : padAngle;
2199
+ };
2200
+ return pie;
2201
+ }
2202
+
2203
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/curve/basis.js
2204
+ function point(that, x2, y2) {
2205
+ that._context.bezierCurveTo(
2206
+ (2 * that._x0 + that._x1) / 3,
2207
+ (2 * that._y0 + that._y1) / 3,
2208
+ (that._x0 + 2 * that._x1) / 3,
2209
+ (that._y0 + 2 * that._y1) / 3,
2210
+ (that._x0 + 4 * that._x1 + x2) / 6,
2211
+ (that._y0 + 4 * that._y1 + y2) / 6
2212
+ );
2213
+ }
2214
+ function Basis(context) {
2215
+ this._context = context;
2216
+ }
2217
+ Basis.prototype = {
2218
+ areaStart: function() {
2219
+ this._line = 0;
2220
+ },
2221
+ areaEnd: function() {
2222
+ this._line = NaN;
2223
+ },
2224
+ lineStart: function() {
2225
+ this._x0 = this._x1 = this._y0 = this._y1 = NaN;
2226
+ this._point = 0;
2227
+ },
2228
+ lineEnd: function() {
2229
+ switch (this._point) {
2230
+ case 3:
2231
+ point(this, this._x1, this._y1);
2232
+ // falls through
2233
+ case 2:
2234
+ this._context.lineTo(this._x1, this._y1);
2235
+ break;
2236
+ }
2237
+ if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
2238
+ this._line = 1 - this._line;
2239
+ },
2240
+ point: function(x2, y2) {
2241
+ x2 = +x2, y2 = +y2;
2242
+ switch (this._point) {
2243
+ case 0:
2244
+ this._point = 1;
2245
+ this._line ? this._context.lineTo(x2, y2) : this._context.moveTo(x2, y2);
2246
+ break;
2247
+ case 1:
2248
+ this._point = 2;
2249
+ break;
2250
+ case 2:
2251
+ this._point = 3;
2252
+ this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6);
2253
+ // falls through
2254
+ default:
2255
+ point(this, x2, y2);
2256
+ break;
2257
+ }
2258
+ this._x0 = this._x1, this._x1 = x2;
2259
+ this._y0 = this._y1, this._y1 = y2;
2260
+ }
2261
+ };
2262
+ function basis_default(context) {
2263
+ return new Basis(context);
2264
+ }
2265
+
2266
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/curve/cardinal.js
2267
+ function point2(that, x2, y2) {
2268
+ that._context.bezierCurveTo(
2269
+ that._x1 + that._k * (that._x2 - that._x0),
2270
+ that._y1 + that._k * (that._y2 - that._y0),
2271
+ that._x2 + that._k * (that._x1 - x2),
2272
+ that._y2 + that._k * (that._y1 - y2),
2273
+ that._x2,
2274
+ that._y2
2275
+ );
2276
+ }
2277
+ function Cardinal(context, tension) {
2278
+ this._context = context;
2279
+ this._k = (1 - tension) / 6;
2280
+ }
2281
+ Cardinal.prototype = {
2282
+ areaStart: function() {
2283
+ this._line = 0;
2284
+ },
2285
+ areaEnd: function() {
2286
+ this._line = NaN;
2287
+ },
2288
+ lineStart: function() {
2289
+ this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;
2290
+ this._point = 0;
2291
+ },
2292
+ lineEnd: function() {
2293
+ switch (this._point) {
2294
+ case 2:
2295
+ this._context.lineTo(this._x2, this._y2);
2296
+ break;
2297
+ case 3:
2298
+ point2(this, this._x1, this._y1);
2299
+ break;
2300
+ }
2301
+ if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
2302
+ this._line = 1 - this._line;
2303
+ },
2304
+ point: function(x2, y2) {
2305
+ x2 = +x2, y2 = +y2;
2306
+ switch (this._point) {
2307
+ case 0:
2308
+ this._point = 1;
2309
+ this._line ? this._context.lineTo(x2, y2) : this._context.moveTo(x2, y2);
2310
+ break;
2311
+ case 1:
2312
+ this._point = 2;
2313
+ this._x1 = x2, this._y1 = y2;
2314
+ break;
2315
+ case 2:
2316
+ this._point = 3;
2317
+ // falls through
2318
+ default:
2319
+ point2(this, x2, y2);
2320
+ break;
2321
+ }
2322
+ this._x0 = this._x1, this._x1 = this._x2, this._x2 = x2;
2323
+ this._y0 = this._y1, this._y1 = this._y2, this._y2 = y2;
2324
+ }
2325
+ };
2326
+ var cardinal_default = (function custom(tension) {
2327
+ function cardinal(context) {
2328
+ return new Cardinal(context, tension);
2329
+ }
2330
+ cardinal.tension = function(tension2) {
2331
+ return custom(+tension2);
2332
+ };
2333
+ return cardinal;
2334
+ })(0);
2335
+
2336
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/curve/monotone.js
2337
+ function sign(x2) {
2338
+ return x2 < 0 ? -1 : 1;
2339
+ }
2340
+ function slope3(that, x2, y2) {
2341
+ var h0 = that._x1 - that._x0, h1 = x2 - that._x1, s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), p = (s0 * h1 + s1 * h0) / (h0 + h1);
2342
+ return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
2343
+ }
2344
+ function slope2(that, t) {
2345
+ var h = that._x1 - that._x0;
2346
+ return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
2347
+ }
2348
+ function point3(that, t02, t12) {
2349
+ var x0 = that._x0, y0 = that._y0, x1 = that._x1, y1 = that._y1, dx = (x1 - x0) / 3;
2350
+ that._context.bezierCurveTo(x0 + dx, y0 + dx * t02, x1 - dx, y1 - dx * t12, x1, y1);
2351
+ }
2352
+ function MonotoneX(context) {
2353
+ this._context = context;
2354
+ }
2355
+ MonotoneX.prototype = {
2356
+ areaStart: function() {
2357
+ this._line = 0;
2358
+ },
2359
+ areaEnd: function() {
2360
+ this._line = NaN;
2361
+ },
2362
+ lineStart: function() {
2363
+ this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN;
2364
+ this._point = 0;
2365
+ },
2366
+ lineEnd: function() {
2367
+ switch (this._point) {
2368
+ case 2:
2369
+ this._context.lineTo(this._x1, this._y1);
2370
+ break;
2371
+ case 3:
2372
+ point3(this, this._t0, slope2(this, this._t0));
2373
+ break;
2374
+ }
2375
+ if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
2376
+ this._line = 1 - this._line;
2377
+ },
2378
+ point: function(x2, y2) {
2379
+ var t12 = NaN;
2380
+ x2 = +x2, y2 = +y2;
2381
+ if (x2 === this._x1 && y2 === this._y1) return;
2382
+ switch (this._point) {
2383
+ case 0:
2384
+ this._point = 1;
2385
+ this._line ? this._context.lineTo(x2, y2) : this._context.moveTo(x2, y2);
2386
+ break;
2387
+ case 1:
2388
+ this._point = 2;
2389
+ break;
2390
+ case 2:
2391
+ this._point = 3;
2392
+ point3(this, slope2(this, t12 = slope3(this, x2, y2)), t12);
2393
+ break;
2394
+ default:
2395
+ point3(this, this._t0, t12 = slope3(this, x2, y2));
2396
+ break;
2397
+ }
2398
+ this._x0 = this._x1, this._x1 = x2;
2399
+ this._y0 = this._y1, this._y1 = y2;
2400
+ this._t0 = t12;
2401
+ }
2402
+ };
2403
+ function MonotoneY(context) {
2404
+ this._context = new ReflectContext(context);
2405
+ }
2406
+ (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x2, y2) {
2407
+ MonotoneX.prototype.point.call(this, y2, x2);
2408
+ };
2409
+ function ReflectContext(context) {
2410
+ this._context = context;
2411
+ }
2412
+ ReflectContext.prototype = {
2413
+ moveTo: function(x2, y2) {
2414
+ this._context.moveTo(y2, x2);
2415
+ },
2416
+ closePath: function() {
2417
+ this._context.closePath();
2418
+ },
2419
+ lineTo: function(x2, y2) {
2420
+ this._context.lineTo(y2, x2);
2421
+ },
2422
+ bezierCurveTo: function(x1, y1, x2, y2, x3, y3) {
2423
+ this._context.bezierCurveTo(y1, x1, y2, x2, y3, x3);
2424
+ }
2425
+ };
2426
+ function monotoneX(context) {
2427
+ return new MonotoneX(context);
2428
+ }
2429
+
2430
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/curve/natural.js
2431
+ function Natural(context) {
2432
+ this._context = context;
2433
+ }
2434
+ Natural.prototype = {
2435
+ areaStart: function() {
2436
+ this._line = 0;
2437
+ },
2438
+ areaEnd: function() {
2439
+ this._line = NaN;
2440
+ },
2441
+ lineStart: function() {
2442
+ this._x = [];
2443
+ this._y = [];
2444
+ },
2445
+ lineEnd: function() {
2446
+ var x2 = this._x, y2 = this._y, n = x2.length;
2447
+ if (n) {
2448
+ this._line ? this._context.lineTo(x2[0], y2[0]) : this._context.moveTo(x2[0], y2[0]);
2449
+ if (n === 2) {
2450
+ this._context.lineTo(x2[1], y2[1]);
2451
+ } else {
2452
+ var px = controlPoints(x2), py = controlPoints(y2);
2453
+ for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
2454
+ this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x2[i1], y2[i1]);
2455
+ }
2456
+ }
2457
+ }
2458
+ if (this._line || this._line !== 0 && n === 1) this._context.closePath();
2459
+ this._line = 1 - this._line;
2460
+ this._x = this._y = null;
2461
+ },
2462
+ point: function(x2, y2) {
2463
+ this._x.push(+x2);
2464
+ this._y.push(+y2);
2465
+ }
2466
+ };
2467
+ function controlPoints(x2) {
2468
+ var i, n = x2.length - 1, m, a = new Array(n), b = new Array(n), r = new Array(n);
2469
+ a[0] = 0, b[0] = 2, r[0] = x2[0] + 2 * x2[1];
2470
+ for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x2[i] + 2 * x2[i + 1];
2471
+ a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x2[n - 1] + x2[n];
2472
+ for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
2473
+ a[n - 1] = r[n - 1] / b[n - 1];
2474
+ for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
2475
+ b[n - 1] = (x2[n] + a[n - 1]) / 2;
2476
+ for (i = 0; i < n - 1; ++i) b[i] = 2 * x2[i + 1] - a[i + 1];
2477
+ return [a, b];
2478
+ }
2479
+ function natural_default(context) {
2480
+ return new Natural(context);
2481
+ }
2482
+
2483
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/curve/step.js
2484
+ function Step(context, t) {
2485
+ this._context = context;
2486
+ this._t = t;
2487
+ }
2488
+ Step.prototype = {
2489
+ areaStart: function() {
2490
+ this._line = 0;
2491
+ },
2492
+ areaEnd: function() {
2493
+ this._line = NaN;
2494
+ },
2495
+ lineStart: function() {
2496
+ this._x = this._y = NaN;
2497
+ this._point = 0;
2498
+ },
2499
+ lineEnd: function() {
2500
+ if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
2501
+ if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
2502
+ if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
2503
+ },
2504
+ point: function(x2, y2) {
2505
+ x2 = +x2, y2 = +y2;
2506
+ switch (this._point) {
2507
+ case 0:
2508
+ this._point = 1;
2509
+ this._line ? this._context.lineTo(x2, y2) : this._context.moveTo(x2, y2);
2510
+ break;
2511
+ case 1:
2512
+ this._point = 2;
2513
+ // falls through
2514
+ default: {
2515
+ if (this._t <= 0) {
2516
+ this._context.lineTo(this._x, y2);
2517
+ this._context.lineTo(x2, y2);
2518
+ } else {
2519
+ var x1 = this._x * (1 - this._t) + x2 * this._t;
2520
+ this._context.lineTo(x1, this._y);
2521
+ this._context.lineTo(x1, y2);
2522
+ }
2523
+ break;
2524
+ }
2525
+ }
2526
+ this._x = x2, this._y = y2;
2527
+ }
2528
+ };
2529
+ function step_default(context) {
2530
+ return new Step(context, 0.5);
2531
+ }
2532
+ function stepBefore(context) {
2533
+ return new Step(context, 0);
2534
+ }
2535
+ function stepAfter(context) {
2536
+ return new Step(context, 1);
2537
+ }
2538
+
2539
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/offset/none.js
2540
+ function none_default(series, order) {
2541
+ if (!((n = series.length) > 1)) return;
2542
+ for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
2543
+ s0 = s1, s1 = series[order[i]];
2544
+ for (j = 0; j < m; ++j) {
2545
+ s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
2546
+ }
593
2547
  }
594
- if (pred.equal !== void 0) {
595
- return value2 == pred.equal;
2548
+ }
2549
+
2550
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/order/none.js
2551
+ function none_default2(series) {
2552
+ var n = series.length, o = new Array(n);
2553
+ while (--n >= 0) o[n] = n;
2554
+ return o;
2555
+ }
2556
+
2557
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/stack.js
2558
+ function stackValue(d, key) {
2559
+ return d[key];
2560
+ }
2561
+ function stackSeries(key) {
2562
+ const series = [];
2563
+ series.key = key;
2564
+ return series;
2565
+ }
2566
+ function stack_default() {
2567
+ var keys = constant_default([]), order = none_default2, offset = none_default, value2 = stackValue;
2568
+ function stack(data) {
2569
+ var sz = Array.from(keys.apply(this, arguments), stackSeries), i, n = sz.length, j = -1, oz;
2570
+ for (const d of data) {
2571
+ for (i = 0, ++j; i < n; ++i) {
2572
+ (sz[i][j] = [0, +value2(d, sz[i].key, j, data)]).data = d;
2573
+ }
2574
+ }
2575
+ for (i = 0, oz = array_default(order(sz)); i < n; ++i) {
2576
+ sz[oz[i]].index = i;
2577
+ }
2578
+ offset(sz, oz);
2579
+ return sz;
596
2580
  }
597
- const numValue = Number(value2);
598
- if (pred.lt !== void 0) {
599
- return numValue < pred.lt;
2581
+ stack.keys = function(_) {
2582
+ return arguments.length ? (keys = typeof _ === "function" ? _ : constant_default(Array.from(_)), stack) : keys;
2583
+ };
2584
+ stack.value = function(_) {
2585
+ return arguments.length ? (value2 = typeof _ === "function" ? _ : constant_default(+_), stack) : value2;
2586
+ };
2587
+ stack.order = function(_) {
2588
+ return arguments.length ? (order = _ == null ? none_default2 : typeof _ === "function" ? _ : constant_default(Array.from(_)), stack) : order;
2589
+ };
2590
+ stack.offset = function(_) {
2591
+ return arguments.length ? (offset = _ == null ? none_default : _, stack) : offset;
2592
+ };
2593
+ return stack;
2594
+ }
2595
+
2596
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/offset/expand.js
2597
+ function expand_default(series, order) {
2598
+ if (!((n = series.length) > 0)) return;
2599
+ for (var i, n, j = 0, m = series[0].length, y2; j < m; ++j) {
2600
+ for (y2 = i = 0; i < n; ++i) y2 += series[i][j][1] || 0;
2601
+ if (y2) for (i = 0; i < n; ++i) series[i][j][1] /= y2;
600
2602
  }
601
- if (pred.lte !== void 0) {
602
- return numValue <= pred.lte;
2603
+ none_default(series, order);
2604
+ }
2605
+
2606
+ // ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/offset/silhouette.js
2607
+ function silhouette_default(series, order) {
2608
+ if (!((n = series.length) > 0)) return;
2609
+ for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
2610
+ for (var i = 0, y2 = 0; i < n; ++i) y2 += series[i][j][1] || 0;
2611
+ s0[j][1] += s0[j][0] = -y2 / 2;
603
2612
  }
604
- if (pred.gt !== void 0) {
605
- return numValue > pred.gt;
2613
+ none_default(series, order);
2614
+ }
2615
+
2616
+ // src/charts/line/curves.ts
2617
+ var CURVE_MAP = {
2618
+ linear: linear_default,
2619
+ monotone: monotoneX,
2620
+ step: step_default,
2621
+ "step-before": stepBefore,
2622
+ "step-after": stepAfter,
2623
+ basis: basis_default,
2624
+ cardinal: cardinal_default,
2625
+ natural: natural_default
2626
+ };
2627
+ function resolveCurve(interpolate) {
2628
+ if (!interpolate) return monotoneX;
2629
+ return CURVE_MAP[interpolate] ?? monotoneX;
2630
+ }
2631
+
2632
+ // src/charts/line/area.ts
2633
+ var DEFAULT_FILL_OPACITY = 0.15;
2634
+ function computeSingleArea(spec, scales, _chartArea) {
2635
+ const encoding = spec.encoding;
2636
+ const xChannel = encoding.x;
2637
+ const yChannel = encoding.y;
2638
+ if (!xChannel || !yChannel || !scales.x || !scales.y) return [];
2639
+ const yScale = scales.y.scale;
2640
+ const domain = yScale.domain();
2641
+ const baselineY = yScale(Math.min(domain[0], domain[1]));
2642
+ const colorField = encoding.color && "field" in encoding.color ? encoding.color.field : void 0;
2643
+ const groups = /* @__PURE__ */ new Map();
2644
+ if (!colorField) {
2645
+ groups.set("__default__", spec.data);
2646
+ } else {
2647
+ for (const row of spec.data) {
2648
+ const key = String(row[colorField] ?? "__default__");
2649
+ const existing = groups.get(key);
2650
+ if (existing) {
2651
+ existing.push(row);
2652
+ } else {
2653
+ groups.set(key, [row]);
2654
+ }
2655
+ }
606
2656
  }
607
- if (pred.gte !== void 0) {
608
- return numValue >= pred.gte;
2657
+ const marks = [];
2658
+ for (const [seriesKey, rows] of groups) {
2659
+ const color2 = getColor(scales, seriesKey);
2660
+ const sortedRows = xChannel.type === "nominal" || xChannel.type === "ordinal" ? rows : sortByField(rows, xChannel.field);
2661
+ const validPoints = [];
2662
+ for (const row of sortedRows) {
2663
+ const xVal = scaleValue(scales.x.scale, scales.x.type, row[xChannel.field]);
2664
+ const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
2665
+ if (xVal === null || yVal === null) continue;
2666
+ validPoints.push({
2667
+ x: xVal,
2668
+ yTop: yVal,
2669
+ yBottom: baselineY,
2670
+ row
2671
+ });
2672
+ }
2673
+ if (validPoints.length === 0) continue;
2674
+ const curve = resolveCurve(spec.markDef.interpolate);
2675
+ const areaGenerator = area_default().x((d) => d.x).y0((d) => d.yBottom).y1((d) => d.yTop).curve(curve);
2676
+ const pathStr = areaGenerator(validPoints) ?? "";
2677
+ const topLineGenerator = line_default().x((d) => d.x).y((d) => d.yTop).curve(curve);
2678
+ const topPathStr = topLineGenerator(validPoints) ?? "";
2679
+ const topPoints = validPoints.map((p) => ({ x: p.x, y: p.yTop }));
2680
+ const bottomPoints = validPoints.map((p) => ({ x: p.x, y: p.yBottom }));
2681
+ const ariaLabel = seriesKey === "__default__" ? `Area with ${validPoints.length} data points` : `${seriesKey}: area with ${validPoints.length} data points`;
2682
+ const aria = { label: ariaLabel };
2683
+ marks.push({
2684
+ type: "area",
2685
+ topPoints,
2686
+ bottomPoints,
2687
+ path: pathStr,
2688
+ topPath: topPathStr,
2689
+ fill: color2,
2690
+ fillOpacity: DEFAULT_FILL_OPACITY,
2691
+ stroke: getRepresentativeColor4(color2),
2692
+ strokeWidth: 2,
2693
+ seriesKey: seriesKey === "__default__" ? void 0 : seriesKey,
2694
+ data: validPoints.map((p) => p.row),
2695
+ dataPoints: validPoints.map((p) => ({ x: p.x, y: p.yTop, datum: p.row })),
2696
+ aria
2697
+ });
609
2698
  }
610
- if (pred.range !== void 0) {
611
- const [min3, max3] = pred.range;
612
- return numValue >= min3 && numValue <= max3;
2699
+ return marks;
2700
+ }
2701
+ function computeStackedArea(spec, scales, chartArea) {
2702
+ const encoding = spec.encoding;
2703
+ const xChannel = encoding.x;
2704
+ const yChannel = encoding.y;
2705
+ const colorField = encoding.color && "field" in encoding.color ? encoding.color.field : void 0;
2706
+ if (!xChannel || !yChannel || !scales.x || !scales.y || !colorField) {
2707
+ return computeSingleArea(spec, scales, chartArea);
2708
+ }
2709
+ const sortedData = xChannel.type === "nominal" || xChannel.type === "ordinal" ? spec.data : sortByField(spec.data, xChannel.field);
2710
+ const seriesKeys = /* @__PURE__ */ new Set();
2711
+ const xValueSet = /* @__PURE__ */ new Set();
2712
+ const rowsByXSeries = /* @__PURE__ */ new Map();
2713
+ const rowsByX = /* @__PURE__ */ new Map();
2714
+ for (const row of sortedData) {
2715
+ const xStr = String(row[xChannel.field]);
2716
+ const series = String(row[colorField]);
2717
+ seriesKeys.add(series);
2718
+ xValueSet.add(xStr);
2719
+ rowsByXSeries.set(`${xStr}::${series}`, row);
2720
+ const existing = rowsByX.get(xStr);
2721
+ if (existing) {
2722
+ existing.push(row);
2723
+ } else {
2724
+ rowsByX.set(xStr, [row]);
2725
+ }
613
2726
  }
614
- if (pred.oneOf !== void 0) {
615
- return pred.oneOf.some((v) => v == value2);
2727
+ const keys = Array.from(seriesKeys);
2728
+ const xValues = Array.from(xValueSet);
2729
+ const pivotData = xValues.map((xVal) => {
2730
+ const pivot = { __x__: xVal };
2731
+ for (const key of keys) {
2732
+ pivot[key] = 0;
2733
+ }
2734
+ const xRows = rowsByX.get(xVal);
2735
+ if (xRows) {
2736
+ for (const row of xRows) {
2737
+ const series = String(row[colorField]);
2738
+ pivot[series] = row[yChannel.field] ?? 0;
2739
+ }
2740
+ }
2741
+ return pivot;
2742
+ });
2743
+ const stackProp = yChannel.stack;
2744
+ const offsetFn = stackProp === "normalize" ? expand_default : stackProp === "center" ? silhouette_default : none_default;
2745
+ const stackGenerator = stack_default().keys(keys).order(none_default2).offset(offsetFn);
2746
+ const stackedData = stackGenerator(pivotData);
2747
+ const yScale = scales.y.scale;
2748
+ const marks = [];
2749
+ for (const layer of stackedData) {
2750
+ const seriesKey = layer.key;
2751
+ const color2 = getColor(scales, seriesKey);
2752
+ const validPoints = [];
2753
+ for (const d of layer) {
2754
+ const xVal = scaleValue(scales.x.scale, scales.x.type, d.data.__x__);
2755
+ if (xVal === null) continue;
2756
+ const yTop = yScale(d[1]);
2757
+ const yBottom = yScale(d[0]);
2758
+ validPoints.push({ x: xVal, yTop, yBottom });
2759
+ }
2760
+ if (validPoints.length === 0) continue;
2761
+ const stackCurve = resolveCurve(spec.markDef.interpolate);
2762
+ const areaGenerator = area_default().x((p) => p.x).y0((p) => p.yBottom).y1((p) => p.yTop).curve(stackCurve);
2763
+ const pathStr = areaGenerator(validPoints) ?? "";
2764
+ const topLineGenerator = line_default().x((p) => p.x).y((p) => p.yTop).curve(stackCurve);
2765
+ const topPathStr = topLineGenerator(validPoints) ?? "";
2766
+ const topPoints = validPoints.map((p) => ({ x: p.x, y: p.yTop }));
2767
+ const bottomPoints = validPoints.map((p) => ({ x: p.x, y: p.yBottom }));
2768
+ const aria = {
2769
+ label: `${seriesKey}: stacked area with ${validPoints.length} data points`
2770
+ };
2771
+ marks.push({
2772
+ type: "area",
2773
+ topPoints,
2774
+ bottomPoints,
2775
+ path: pathStr,
2776
+ topPath: topPathStr,
2777
+ fill: color2,
2778
+ fillOpacity: 0.7,
2779
+ // Higher opacity for stacked so layers are visible
2780
+ stroke: getRepresentativeColor4(color2),
2781
+ strokeWidth: 1,
2782
+ seriesKey,
2783
+ data: layer.map((d) => {
2784
+ const xStr = String(d.data.__x__);
2785
+ return rowsByXSeries.get(`${xStr}::${seriesKey}`) ?? d.data;
2786
+ }),
2787
+ dataPoints: validPoints.map((p, idx) => {
2788
+ const xStr = String(layer[idx]?.data.__x__);
2789
+ const datum = rowsByXSeries.get(`${xStr}::${seriesKey}`) ?? layer[idx]?.data ?? {};
2790
+ return { x: p.x, y: p.yTop, datum };
2791
+ }),
2792
+ aria
2793
+ });
616
2794
  }
617
- return true;
2795
+ return marks;
618
2796
  }
619
- function evaluatePredicate(datum, predicate) {
620
- if (isFieldPredicate(predicate)) {
621
- return evaluateFieldPredicate(datum, predicate);
2797
+ function computeAreaMarks(spec, scales, chartArea) {
2798
+ const encoding = spec.encoding;
2799
+ const hasColor = !!encoding.color;
2800
+ if (hasColor) {
2801
+ return computeStackedArea(spec, scales, chartArea);
622
2802
  }
623
- if ("and" in predicate) {
624
- return predicate.and.every((p) => evaluatePredicate(datum, p));
2803
+ return computeSingleArea(spec, scales, chartArea);
2804
+ }
2805
+
2806
+ // src/charts/line/compute.ts
2807
+ import { getRepresentativeColor as getRepresentativeColor5 } from "@opendata-ai/openchart-core";
2808
+ var DEFAULT_STROKE_WIDTH = 2.5;
2809
+ var DEFAULT_POINT_RADIUS = 3;
2810
+ function computeLineMarks(spec, scales, _chartArea, _strategy) {
2811
+ const encoding = spec.encoding;
2812
+ const xChannel = encoding.x;
2813
+ const yChannel = encoding.y;
2814
+ if (!xChannel || !yChannel || !scales.x || !scales.y) {
2815
+ return [];
625
2816
  }
626
- if ("or" in predicate) {
627
- return predicate.or.some((p) => evaluatePredicate(datum, p));
2817
+ const colorEnc = encoding.color && "field" in encoding.color ? encoding.color : void 0;
2818
+ const isSequentialColor = colorEnc?.type === "quantitative";
2819
+ const colorField = isSequentialColor ? void 0 : colorEnc?.field;
2820
+ const sequentialColorField = isSequentialColor ? colorEnc.field : void 0;
2821
+ const groups = groupByField(spec.data, colorField);
2822
+ const marks = [];
2823
+ for (const [seriesKey, rows] of groups) {
2824
+ const color2 = isSequentialColor ? getSequentialColor(scales, _getMidValue(rows, sequentialColorField)) : getColor(scales, seriesKey);
2825
+ const strokeColor = getRepresentativeColor5(color2);
2826
+ const sortedRows = xChannel.type === "nominal" || xChannel.type === "ordinal" ? rows : sortByField(rows, xChannel.field);
2827
+ const pointsWithData = [];
2828
+ const segments = [];
2829
+ let currentSegment = [];
2830
+ for (const row of sortedRows) {
2831
+ const xVal = scaleValue(scales.x.scale, scales.x.type, row[xChannel.field]);
2832
+ const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
2833
+ if (xVal === null || yVal === null) {
2834
+ if (currentSegment.length > 0) {
2835
+ segments.push(currentSegment);
2836
+ currentSegment = [];
2837
+ }
2838
+ continue;
2839
+ }
2840
+ const point5 = { x: xVal, y: yVal };
2841
+ currentSegment.push(point5);
2842
+ pointsWithData.push({ ...point5, row });
2843
+ }
2844
+ if (currentSegment.length > 0) {
2845
+ segments.push(currentSegment);
2846
+ }
2847
+ const curve = resolveCurve(spec.markDef.interpolate);
2848
+ const lineGenerator = line_default().x((d) => d.x).y((d) => d.y).curve(curve);
2849
+ const allPoints = [];
2850
+ const pathParts = [];
2851
+ for (const segment of segments) {
2852
+ if (segment.length === 0) continue;
2853
+ const pathStr = lineGenerator(segment);
2854
+ if (pathStr) {
2855
+ pathParts.push(pathStr);
2856
+ }
2857
+ allPoints.push(...segment);
2858
+ }
2859
+ if (allPoints.length === 0) continue;
2860
+ const ariaLabel = seriesKey === "__default__" ? `Line with ${allPoints.length} data points` : `${seriesKey}: line with ${allPoints.length} data points`;
2861
+ const aria = {
2862
+ label: ariaLabel
2863
+ };
2864
+ const combinedPath = pathParts.join(" ");
2865
+ const seriesStyleKey = seriesKey === "__default__" ? void 0 : seriesKey;
2866
+ const styleOverride = seriesStyleKey ? spec.seriesStyles?.[seriesStyleKey] : void 0;
2867
+ let strokeDasharray;
2868
+ if (styleOverride?.lineStyle === "dashed") strokeDasharray = "6 4";
2869
+ else if (styleOverride?.lineStyle === "dotted") strokeDasharray = "2 3";
2870
+ const lineMark = {
2871
+ type: "line",
2872
+ points: allPoints,
2873
+ path: combinedPath,
2874
+ stroke: strokeColor,
2875
+ strokeWidth: styleOverride?.strokeWidth ?? DEFAULT_STROKE_WIDTH,
2876
+ strokeDasharray,
2877
+ opacity: styleOverride?.opacity,
2878
+ seriesKey: seriesStyleKey,
2879
+ data: pointsWithData.map((p) => p.row),
2880
+ dataPoints: pointsWithData.map((p) => ({ x: p.x, y: p.y, datum: p.row })),
2881
+ aria
2882
+ };
2883
+ marks.push(lineMark);
2884
+ const markPoint = spec.markDef.point;
2885
+ const showPoints = markPoint === true || markPoint === "transparent" || isSequentialColor;
2886
+ if (showPoints) {
2887
+ const isTransparent = markPoint === "transparent";
2888
+ const seriesShowPoints = styleOverride?.showPoints !== false;
2889
+ for (let i = 0; i < pointsWithData.length; i++) {
2890
+ const p = pointsWithData[i];
2891
+ const visible = seriesShowPoints && !isTransparent;
2892
+ let pointColor = color2;
2893
+ if (isSequentialColor) {
2894
+ const val = Number(p.row[sequentialColorField]);
2895
+ pointColor = Number.isFinite(val) ? getSequentialColor(scales, val) : color2;
2896
+ }
2897
+ const pointMark = {
2898
+ type: "point",
2899
+ cx: p.x,
2900
+ cy: p.y,
2901
+ r: visible ? DEFAULT_POINT_RADIUS : 0,
2902
+ fill: pointColor,
2903
+ stroke: visible ? "#ffffff" : "transparent",
2904
+ strokeWidth: visible ? 1.5 : 0,
2905
+ fillOpacity: isTransparent ? 0 : 1,
2906
+ data: p.row,
2907
+ aria: {
2908
+ label: `Data point: ${xChannel.field}=${String(p.row[xChannel.field])}, ${yChannel.field}=${String(p.row[yChannel.field])}`
2909
+ }
2910
+ };
2911
+ marks.push(pointMark);
2912
+ }
2913
+ }
628
2914
  }
629
- if ("not" in predicate) {
630
- return !evaluatePredicate(datum, predicate.not);
2915
+ return marks;
2916
+ }
2917
+ function _getMidValue(rows, field) {
2918
+ const values = rows.map((r) => Number(r[field])).filter(Number.isFinite);
2919
+ if (values.length === 0) return 0;
2920
+ const sorted = values.sort((a, b) => a - b);
2921
+ return sorted[Math.floor(sorted.length / 2)];
2922
+ }
2923
+
2924
+ // src/charts/line/labels.ts
2925
+ import {
2926
+ EXTENDED_OFFSET_STRATEGIES,
2927
+ estimateTextWidth as estimateTextWidth5,
2928
+ resolveCollisions as resolveCollisions4
2929
+ } from "@opendata-ai/openchart-core";
2930
+ var LABEL_FONT_SIZE4 = 11;
2931
+ var LABEL_FONT_WEIGHT4 = 600;
2932
+ var LABEL_OFFSET_X2 = 6;
2933
+ function computeLineLabels(marks, strategy, density = "auto", labelOffsets) {
2934
+ const result = /* @__PURE__ */ new Map();
2935
+ if (density === "none") return result;
2936
+ if (strategy.labelMode === "none") {
2937
+ return result;
631
2938
  }
632
- return true;
2939
+ const candidates = [];
2940
+ const seriesOrder = [];
2941
+ for (const mark of marks) {
2942
+ if (mark.points.length === 0) continue;
2943
+ const labelText = mark.seriesKey ?? "";
2944
+ if (!labelText) continue;
2945
+ const lastPoint = mark.points[mark.points.length - 1];
2946
+ const textWidth = estimateTextWidth5(labelText, LABEL_FONT_SIZE4, LABEL_FONT_WEIGHT4);
2947
+ const textHeight = LABEL_FONT_SIZE4 * 1.2;
2948
+ candidates.push({
2949
+ text: labelText,
2950
+ anchorX: lastPoint.x + LABEL_OFFSET_X2,
2951
+ anchorY: lastPoint.y - textHeight / 2,
2952
+ width: textWidth,
2953
+ height: textHeight,
2954
+ priority: "data",
2955
+ style: {
2956
+ fontFamily: "system-ui, -apple-system, sans-serif",
2957
+ fontSize: LABEL_FONT_SIZE4,
2958
+ fontWeight: LABEL_FONT_WEIGHT4,
2959
+ fill: mark.stroke,
2960
+ lineHeight: 1.2,
2961
+ textAnchor: "start",
2962
+ dominantBaseline: "central"
2963
+ }
2964
+ });
2965
+ seriesOrder.push(labelText);
2966
+ }
2967
+ if (candidates.length === 0) return result;
2968
+ if (density === "all") {
2969
+ for (let i = 0; i < candidates.length; i++) {
2970
+ const c = candidates[i];
2971
+ const seriesKey = seriesOrder[i];
2972
+ const userOffset = labelOffsets?.[seriesKey];
2973
+ result.set(seriesKey, {
2974
+ text: c.text,
2975
+ x: c.anchorX + (userOffset?.dx ?? 0),
2976
+ y: c.anchorY + (userOffset?.dy ?? 0),
2977
+ style: c.style,
2978
+ visible: true
2979
+ });
2980
+ }
2981
+ return result;
2982
+ }
2983
+ const resolved = resolveCollisions4(candidates, EXTENDED_OFFSET_STRATEGIES);
2984
+ for (let i = 0; i < resolved.length; i++) {
2985
+ const seriesKey = seriesOrder[i];
2986
+ const label = resolved[i];
2987
+ const userOffset = labelOffsets?.[seriesKey];
2988
+ if (userOffset) {
2989
+ label.x += userOffset.dx ?? 0;
2990
+ label.y += userOffset.dy ?? 0;
2991
+ }
2992
+ result.set(seriesKey, label);
2993
+ }
2994
+ return result;
633
2995
  }
634
2996
 
635
- // src/transforms/conditional.ts
636
- function resolveConditionalValue(datum, channelDef) {
637
- const conditions = Array.isArray(channelDef.condition) ? channelDef.condition : [channelDef.condition];
638
- for (const cond of conditions) {
639
- if (evaluatePredicate(datum, cond.test)) {
640
- if (cond.field !== void 0) {
641
- return datum[cond.field];
2997
+ // src/charts/line/index.ts
2998
+ var lineRenderer = (spec, scales, chartArea, strategy, _theme) => {
2999
+ const marks = computeLineMarks(spec, scales, chartArea, strategy);
3000
+ const lineMarks = marks.filter((m) => m.type === "line");
3001
+ const labelMap = computeLineLabels(lineMarks, strategy, spec.labels.density, spec.labels.offsets);
3002
+ for (const mark of marks) {
3003
+ if (mark.type === "line" && mark.seriesKey) {
3004
+ const label = labelMap.get(mark.seriesKey);
3005
+ if (label) {
3006
+ mark.label = label;
642
3007
  }
643
- return cond.value;
644
3008
  }
645
3009
  }
646
- return channelDef.value;
3010
+ return marks;
3011
+ };
3012
+ var areaRenderer = (spec, scales, chartArea, strategy, _theme) => {
3013
+ const areas = computeAreaMarks(spec, scales, chartArea);
3014
+ const encoding = spec.encoding;
3015
+ const hasColor = !!(encoding.color && "field" in encoding.color);
3016
+ const lines = hasColor ? linesFromAreas(areas) : computeLineMarks(spec, scales, chartArea, strategy);
3017
+ return [...areas, ...lines];
3018
+ };
3019
+ function linesFromAreas(areas) {
3020
+ return areas.map((a) => ({
3021
+ type: "line",
3022
+ points: a.topPoints,
3023
+ path: a.topPath,
3024
+ stroke: getRepresentativeColor6(a.fill),
3025
+ strokeWidth: a.strokeWidth ?? 1,
3026
+ seriesKey: a.seriesKey,
3027
+ data: a.data,
3028
+ dataPoints: a.dataPoints,
3029
+ aria: { label: `${a.seriesKey ?? "Series"}: line with ${a.topPoints.length} data points` }
3030
+ }));
647
3031
  }
648
- function isConditionalValueDef(def) {
649
- return def !== null && typeof def === "object" && "condition" in def;
3032
+
3033
+ // src/charts/pie/compute.ts
3034
+ import { isConditionalDef, isGradientDef as isGradientDef3 } from "@opendata-ai/openchart-core";
3035
+ var SMALL_SLICE_THRESHOLD = 0.03;
3036
+ var DEFAULT_PALETTE = [
3037
+ "#1b7fa3",
3038
+ "#c44e52",
3039
+ "#6a9f58",
3040
+ "#d47215",
3041
+ "#507e79",
3042
+ "#9a6a8d",
3043
+ "#c4636b",
3044
+ "#9c755f",
3045
+ "#a88f22",
3046
+ "#858078"
3047
+ ];
3048
+ function groupSmallSlices(slices, threshold2) {
3049
+ const total = slices.reduce((sum2, s) => sum2 + s.value, 0);
3050
+ if (total === 0) return slices;
3051
+ const big = [];
3052
+ let otherValue = 0;
3053
+ for (const slice2 of slices) {
3054
+ if (slice2.value / total < threshold2) {
3055
+ otherValue += slice2.value;
3056
+ } else {
3057
+ big.push(slice2);
3058
+ }
3059
+ }
3060
+ if (otherValue > 0) {
3061
+ big.push({
3062
+ label: "Other",
3063
+ value: otherValue,
3064
+ originalRow: { label: "Other", value: otherValue }
3065
+ });
3066
+ }
3067
+ return big;
3068
+ }
3069
+ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
3070
+ const encoding = spec.encoding;
3071
+ const valueChannel = encoding.y ?? encoding.x;
3072
+ const categoryField = encoding.color && "field" in encoding.color ? encoding.color.field : void 0;
3073
+ const conditionalColor = encoding.color && isConditionalDef(encoding.color) ? encoding.color : void 0;
3074
+ if (!valueChannel) return [];
3075
+ let slices = [];
3076
+ if (categoryField) {
3077
+ const categoryTotals = /* @__PURE__ */ new Map();
3078
+ const categoryRows = /* @__PURE__ */ new Map();
3079
+ for (const row of spec.data) {
3080
+ const cat = String(row[categoryField] ?? "");
3081
+ const val = Number(row[valueChannel.field] ?? 0);
3082
+ if (!Number.isFinite(val) || val < 0) continue;
3083
+ categoryTotals.set(cat, (categoryTotals.get(cat) ?? 0) + val);
3084
+ if (!categoryRows.has(cat)) {
3085
+ categoryRows.set(cat, row);
3086
+ }
3087
+ }
3088
+ for (const [label, value2] of categoryTotals) {
3089
+ slices.push({
3090
+ label,
3091
+ value: value2,
3092
+ originalRow: categoryRows.get(label) ?? {
3093
+ [categoryField]: label,
3094
+ [valueChannel.field]: value2
3095
+ }
3096
+ });
3097
+ }
3098
+ } else {
3099
+ for (let i = 0; i < spec.data.length; i++) {
3100
+ const row = spec.data[i];
3101
+ const val = Number(row[valueChannel.field] ?? 0);
3102
+ if (!Number.isFinite(val) || val < 0) continue;
3103
+ const label = String(row.label ?? row.name ?? row.category ?? `Slice ${i + 1}`);
3104
+ slices.push({ label, value: val, originalRow: row });
3105
+ }
3106
+ }
3107
+ if (slices.length === 0) return [];
3108
+ slices.sort((a, b) => b.value - a.value);
3109
+ slices = groupSmallSlices(slices, SMALL_SLICE_THRESHOLD);
3110
+ const pieGenerator = pie_default().value((d) => d.value).sort(null).padAngle(0.01);
3111
+ const arcs = pieGenerator(slices);
3112
+ const centerX = chartArea.x + chartArea.width / 2;
3113
+ const centerY = chartArea.y + chartArea.height / 2;
3114
+ const outerRadius = Math.min(chartArea.width, chartArea.height) / 2 * 0.85;
3115
+ const innerRadius = isDonut ? outerRadius * 0.6 : 0;
3116
+ const arcGenerator = arc_default().innerRadius(innerRadius).outerRadius(outerRadius);
3117
+ const marks = [];
3118
+ const center2 = { x: centerX, y: centerY };
3119
+ const total = slices.reduce((sum2, s) => sum2 + s.value, 0);
3120
+ for (let i = 0; i < arcs.length; i++) {
3121
+ const arcDatum = arcs[i];
3122
+ const slice2 = arcDatum.data;
3123
+ let color2;
3124
+ if (conditionalColor) {
3125
+ const resolved = resolveConditionalValue(
3126
+ slice2.originalRow,
3127
+ conditionalColor
3128
+ );
3129
+ if (resolved != null) {
3130
+ color2 = isGradientDef3(resolved) ? resolved : String(resolved);
3131
+ } else if (scales.color && categoryField) {
3132
+ const colorScale = scales.color.scale;
3133
+ color2 = colorScale(slice2.label);
3134
+ } else {
3135
+ color2 = DEFAULT_PALETTE[i % DEFAULT_PALETTE.length];
3136
+ }
3137
+ } else if (scales.color && categoryField) {
3138
+ const colorScale = scales.color.scale;
3139
+ color2 = colorScale(slice2.label);
3140
+ } else {
3141
+ color2 = DEFAULT_PALETTE[i % DEFAULT_PALETTE.length];
3142
+ }
3143
+ const path2 = arcGenerator(arcDatum) ?? "";
3144
+ const centroidResult = arcGenerator.centroid(arcDatum);
3145
+ const percentage = total > 0 ? (slice2.value / total * 100).toFixed(1) : "0";
3146
+ const aria = {
3147
+ label: `${slice2.label}: ${slice2.value} (${percentage}%)`
3148
+ };
3149
+ marks.push({
3150
+ type: "arc",
3151
+ path: path2,
3152
+ centroid: {
3153
+ x: centroidResult[0] + centerX,
3154
+ y: centroidResult[1] + centerY
3155
+ },
3156
+ center: center2,
3157
+ innerRadius,
3158
+ outerRadius,
3159
+ startAngle: arcDatum.startAngle,
3160
+ endAngle: arcDatum.endAngle,
3161
+ fill: color2,
3162
+ stroke: "#ffffff",
3163
+ strokeWidth: 2,
3164
+ data: slice2.originalRow,
3165
+ aria
3166
+ });
3167
+ }
3168
+ return marks;
650
3169
  }
651
3170
 
3171
+ // src/charts/pie/labels.ts
3172
+ import { estimateTextWidth as estimateTextWidth6, resolveCollisions as resolveCollisions5 } from "@opendata-ai/openchart-core";
3173
+ var LABEL_FONT_SIZE5 = 10;
3174
+ var LABEL_FONT_WEIGHT5 = 500;
3175
+ var LEADER_LINE_OFFSET = 12;
3176
+ function computePieLabels(marks, _chartArea, density = "auto", _textFill = "#333333") {
3177
+ if (marks.length === 0) return [];
3178
+ const centerX = marks[0].center.x;
3179
+ const centerY = marks[0].center.y;
3180
+ const targetMarks = filterByDensity(marks, density);
3181
+ if (targetMarks.length === 0) return [];
3182
+ const candidates = [];
3183
+ const targetMarkIndices = [];
3184
+ for (let mi = 0; mi < targetMarks.length; mi++) {
3185
+ const mark = targetMarks[mi];
3186
+ const ariaLabel = mark.aria.label;
3187
+ const firstColon = ariaLabel.indexOf(":");
3188
+ const labelText = firstColon >= 0 ? ariaLabel.slice(0, firstColon).trim() : "";
3189
+ if (!labelText) continue;
3190
+ const textWidth = estimateTextWidth6(labelText, LABEL_FONT_SIZE5, LABEL_FONT_WEIGHT5);
3191
+ const textHeight = LABEL_FONT_SIZE5 * 1.2;
3192
+ const midAngle = (mark.startAngle + mark.endAngle) / 2;
3193
+ const labelRadius = mark.outerRadius + LEADER_LINE_OFFSET;
3194
+ const labelX = centerX + Math.sin(midAngle) * labelRadius;
3195
+ const labelY = centerY - Math.cos(midAngle) * labelRadius;
3196
+ const isRight = Math.sin(midAngle) > 0;
3197
+ candidates.push({
3198
+ text: labelText,
3199
+ anchorX: isRight ? labelX : labelX - textWidth,
3200
+ anchorY: labelY - textHeight / 2,
3201
+ width: textWidth,
3202
+ height: textHeight,
3203
+ priority: "data",
3204
+ style: {
3205
+ fontFamily: "system-ui, -apple-system, sans-serif",
3206
+ fontSize: LABEL_FONT_SIZE5,
3207
+ fontWeight: LABEL_FONT_WEIGHT5,
3208
+ fill: _textFill,
3209
+ lineHeight: 1.2,
3210
+ textAnchor: isRight ? "start" : "end",
3211
+ dominantBaseline: "central"
3212
+ }
3213
+ });
3214
+ targetMarkIndices.push(mi);
3215
+ }
3216
+ if (candidates.length === 0) return [];
3217
+ let resolved;
3218
+ if (density === "all") {
3219
+ resolved = candidates.map((c) => ({
3220
+ text: c.text,
3221
+ x: c.anchorX,
3222
+ y: c.anchorY,
3223
+ style: c.style,
3224
+ visible: true
3225
+ }));
3226
+ } else {
3227
+ resolved = resolveCollisions5(candidates);
3228
+ }
3229
+ for (let i = 0; i < resolved.length && i < targetMarks.length; i++) {
3230
+ const label = resolved[i];
3231
+ const mark = targetMarks[i];
3232
+ if (label.visible) {
3233
+ label.connector = {
3234
+ from: { x: label.x, y: label.y },
3235
+ to: { x: mark.centroid.x, y: mark.centroid.y },
3236
+ stroke: _textFill,
3237
+ style: "straight"
3238
+ };
3239
+ }
3240
+ }
3241
+ return resolved;
3242
+ }
3243
+
3244
+ // src/charts/pie/index.ts
3245
+ var pieRenderer = (spec, scales, chartArea, strategy, theme) => {
3246
+ const marks = computePieMarks(spec, scales, chartArea, strategy, false);
3247
+ const labels = computePieLabels(marks, chartArea, spec.labels.density, theme.colors.text);
3248
+ for (let i = 0; i < marks.length && i < labels.length; i++) {
3249
+ marks[i].label = labels[i];
3250
+ }
3251
+ return marks;
3252
+ };
3253
+ var donutRenderer = (spec, scales, chartArea, strategy, theme) => {
3254
+ const marks = computePieMarks(spec, scales, chartArea, strategy, true);
3255
+ const labels = computePieLabels(marks, chartArea, spec.labels.density, theme.colors.text);
3256
+ for (let i = 0; i < marks.length && i < labels.length; i++) {
3257
+ marks[i].label = labels[i];
3258
+ }
3259
+ return marks;
3260
+ };
3261
+
652
3262
  // src/charts/registry.ts
653
3263
  var renderers = /* @__PURE__ */ new Map();
654
3264
  function registerChartRenderer(type, renderer) {
@@ -661,6 +3271,78 @@ function clearRenderers() {
661
3271
  renderers.clear();
662
3272
  }
663
3273
 
3274
+ // src/charts/rule/index.ts
3275
+ import { getRepresentativeColor as getRepresentativeColor7 } from "@opendata-ai/openchart-core";
3276
+ function computeRuleMarks(spec, scales, chartArea) {
3277
+ const encoding = spec.encoding;
3278
+ const xChannel = encoding.x;
3279
+ const yChannel = encoding.y;
3280
+ const x2Channel = encoding.x2;
3281
+ const y2Channel = encoding.y2;
3282
+ const colorEncoding = encoding.color && "field" in encoding.color ? encoding.color : void 0;
3283
+ const colorField = colorEncoding?.field;
3284
+ const marks = [];
3285
+ for (const row of spec.data) {
3286
+ let x1 = chartArea.x;
3287
+ let y1 = chartArea.y;
3288
+ let x2 = chartArea.x + chartArea.width;
3289
+ let y2 = chartArea.y + chartArea.height;
3290
+ if (xChannel && scales.x) {
3291
+ const xVal = scaleValue(scales.x.scale, scales.x.type, row[xChannel.field]);
3292
+ if (xVal == null) continue;
3293
+ x1 = xVal;
3294
+ x2 = xVal;
3295
+ }
3296
+ if (yChannel && scales.y) {
3297
+ const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
3298
+ if (yVal == null) continue;
3299
+ y1 = yVal;
3300
+ y2 = yVal;
3301
+ }
3302
+ if (xChannel && !yChannel) {
3303
+ y1 = chartArea.y;
3304
+ y2 = chartArea.y + chartArea.height;
3305
+ }
3306
+ if (yChannel && !xChannel) {
3307
+ x1 = chartArea.x;
3308
+ x2 = chartArea.x + chartArea.width;
3309
+ }
3310
+ if (x2Channel && scales.x) {
3311
+ const x2Val = scaleValue(scales.x.scale, scales.x.type, row[x2Channel.field]);
3312
+ if (x2Val != null) x2 = x2Val;
3313
+ }
3314
+ if (y2Channel && scales.y) {
3315
+ const y2Val = scaleValue(scales.y.scale, scales.y.type, row[y2Channel.field]);
3316
+ if (y2Val != null) y2 = y2Val;
3317
+ }
3318
+ const color2 = getRepresentativeColor7(
3319
+ colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
3320
+ );
3321
+ const strokeDashEncoding = encoding.strokeDash && "field" in encoding.strokeDash ? encoding.strokeDash : void 0;
3322
+ const strokeDasharray = strokeDashEncoding ? String(row[strokeDashEncoding.field] ?? "") : void 0;
3323
+ const aria = {
3324
+ label: `Rule from (${Math.round(x1)}, ${Math.round(y1)}) to (${Math.round(x2)}, ${Math.round(y2)})`
3325
+ };
3326
+ marks.push({
3327
+ type: "rule",
3328
+ x1,
3329
+ y1,
3330
+ x2,
3331
+ y2,
3332
+ stroke: color2,
3333
+ strokeWidth: 1,
3334
+ strokeDasharray: strokeDasharray || void 0,
3335
+ opacity: encoding.opacity && "field" in encoding.opacity ? Math.max(0, Math.min(1, Number(row[encoding.opacity.field]) || 1)) : void 0,
3336
+ data: row,
3337
+ aria
3338
+ });
3339
+ }
3340
+ return marks;
3341
+ }
3342
+ var ruleRenderer = (spec, scales, chartArea, _strategy, _theme) => {
3343
+ return computeRuleMarks(spec, scales, chartArea);
3344
+ };
3345
+
664
3346
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/ascending.js
665
3347
  function ascending(a, b) {
666
3348
  return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
@@ -676,38 +3358,38 @@ function bisector(f) {
676
3358
  let compare1, compare2, delta;
677
3359
  if (f.length !== 2) {
678
3360
  compare1 = ascending;
679
- compare2 = (d, x) => ascending(f(d), x);
680
- delta = (d, x) => f(d) - x;
3361
+ compare2 = (d, x2) => ascending(f(d), x2);
3362
+ delta = (d, x2) => f(d) - x2;
681
3363
  } else {
682
3364
  compare1 = f === ascending || f === descending ? f : zero;
683
3365
  compare2 = f;
684
3366
  delta = f;
685
3367
  }
686
- function left2(a, x, lo = 0, hi = a.length) {
3368
+ function left2(a, x2, lo = 0, hi = a.length) {
687
3369
  if (lo < hi) {
688
- if (compare1(x, x) !== 0) return hi;
3370
+ if (compare1(x2, x2) !== 0) return hi;
689
3371
  do {
690
3372
  const mid = lo + hi >>> 1;
691
- if (compare2(a[mid], x) < 0) lo = mid + 1;
3373
+ if (compare2(a[mid], x2) < 0) lo = mid + 1;
692
3374
  else hi = mid;
693
3375
  } while (lo < hi);
694
3376
  }
695
3377
  return lo;
696
3378
  }
697
- function right2(a, x, lo = 0, hi = a.length) {
3379
+ function right2(a, x2, lo = 0, hi = a.length) {
698
3380
  if (lo < hi) {
699
- if (compare1(x, x) !== 0) return hi;
3381
+ if (compare1(x2, x2) !== 0) return hi;
700
3382
  do {
701
3383
  const mid = lo + hi >>> 1;
702
- if (compare2(a[mid], x) <= 0) lo = mid + 1;
3384
+ if (compare2(a[mid], x2) <= 0) lo = mid + 1;
703
3385
  else hi = mid;
704
3386
  } while (lo < hi);
705
3387
  }
706
3388
  return lo;
707
3389
  }
708
- function center2(a, x, lo = 0, hi = a.length) {
709
- const i = left2(a, x, lo, hi - 1);
710
- return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i;
3390
+ function center2(a, x2, lo = 0, hi = a.length) {
3391
+ const i = left2(a, x2, lo, hi - 1);
3392
+ return i > lo && delta(a[i - 1], x2) > -delta(a[i], x2) ? i - 1 : i;
711
3393
  }
712
3394
  return { left: left2, center: center2, right: right2 };
713
3395
  }
@@ -716,8 +3398,8 @@ function zero() {
716
3398
  }
717
3399
 
718
3400
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/number.js
719
- function number(x) {
720
- return x === null ? NaN : +x;
3401
+ function number(x2) {
3402
+ return x2 === null ? NaN : +x2;
721
3403
  }
722
3404
 
723
3405
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/bisect.js
@@ -729,16 +3411,16 @@ var bisect_default = bisectRight;
729
3411
 
730
3412
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/extent.js
731
3413
  function extent(values, valueof) {
732
- let min3;
733
- let max3;
3414
+ let min4;
3415
+ let max4;
734
3416
  if (valueof === void 0) {
735
3417
  for (const value2 of values) {
736
3418
  if (value2 != null) {
737
- if (min3 === void 0) {
738
- if (value2 >= value2) min3 = max3 = value2;
3419
+ if (min4 === void 0) {
3420
+ if (value2 >= value2) min4 = max4 = value2;
739
3421
  } else {
740
- if (min3 > value2) min3 = value2;
741
- if (max3 < value2) max3 = value2;
3422
+ if (min4 > value2) min4 = value2;
3423
+ if (max4 < value2) max4 = value2;
742
3424
  }
743
3425
  }
744
3426
  }
@@ -746,16 +3428,16 @@ function extent(values, valueof) {
746
3428
  let index = -1;
747
3429
  for (let value2 of values) {
748
3430
  if ((value2 = valueof(value2, ++index, values)) != null) {
749
- if (min3 === void 0) {
750
- if (value2 >= value2) min3 = max3 = value2;
3431
+ if (min4 === void 0) {
3432
+ if (value2 >= value2) min4 = max4 = value2;
751
3433
  } else {
752
- if (min3 > value2) min3 = value2;
753
- if (max3 < value2) max3 = value2;
3434
+ if (min4 > value2) min4 = value2;
3435
+ if (max4 < value2) max4 = value2;
754
3436
  }
755
3437
  }
756
3438
  }
757
3439
  }
758
- return [min3, max3];
3440
+ return [min4, max4];
759
3441
  }
760
3442
 
761
3443
  // ../../node_modules/.bun/internmap@2.0.3/node_modules/internmap/src/index.js
@@ -851,43 +3533,43 @@ function tickStep(start, stop, count) {
851
3533
  }
852
3534
 
853
3535
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/max.js
854
- function max(values, valueof) {
855
- let max3;
3536
+ function max2(values, valueof) {
3537
+ let max4;
856
3538
  if (valueof === void 0) {
857
3539
  for (const value2 of values) {
858
- if (value2 != null && (max3 < value2 || max3 === void 0 && value2 >= value2)) {
859
- max3 = value2;
3540
+ if (value2 != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
3541
+ max4 = value2;
860
3542
  }
861
3543
  }
862
3544
  } else {
863
3545
  let index = -1;
864
3546
  for (let value2 of values) {
865
- if ((value2 = valueof(value2, ++index, values)) != null && (max3 < value2 || max3 === void 0 && value2 >= value2)) {
866
- max3 = value2;
3547
+ if ((value2 = valueof(value2, ++index, values)) != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
3548
+ max4 = value2;
867
3549
  }
868
3550
  }
869
3551
  }
870
- return max3;
3552
+ return max4;
871
3553
  }
872
3554
 
873
3555
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/min.js
874
- function min(values, valueof) {
875
- let min3;
3556
+ function min2(values, valueof) {
3557
+ let min4;
876
3558
  if (valueof === void 0) {
877
3559
  for (const value2 of values) {
878
- if (value2 != null && (min3 > value2 || min3 === void 0 && value2 >= value2)) {
879
- min3 = value2;
3560
+ if (value2 != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
3561
+ min4 = value2;
880
3562
  }
881
3563
  }
882
3564
  } else {
883
3565
  let index = -1;
884
3566
  for (let value2 of values) {
885
- if ((value2 = valueof(value2, ++index, values)) != null && (min3 > value2 || min3 === void 0 && value2 >= value2)) {
886
- min3 = value2;
3567
+ if ((value2 = valueof(value2, ++index, values)) != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
3568
+ min4 = value2;
887
3569
  }
888
3570
  }
889
3571
  }
890
- return min3;
3572
+ return min4;
891
3573
  }
892
3574
 
893
3575
  // ../../node_modules/.bun/d3-array@3.2.4/node_modules/d3-array/src/quantile.js
@@ -1037,7 +3719,7 @@ function pointish(scale) {
1037
3719
  };
1038
3720
  return scale;
1039
3721
  }
1040
- function point() {
3722
+ function point4() {
1041
3723
  return pointish(band.apply(null, arguments).paddingInner(1));
1042
3724
  }
1043
3725
 
@@ -1328,12 +4010,12 @@ function hslConvert(o) {
1328
4010
  if (!o) return new Hsl();
1329
4011
  if (o instanceof Hsl) return o;
1330
4012
  o = o.rgb();
1331
- 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;
4013
+ 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;
1332
4014
  if (s) {
1333
- if (r === max3) h = (g - b) / s + (g < b) * 6;
1334
- else if (g === max3) h = (b - r) / s + 2;
4015
+ if (r === max4) h = (g - b) / s + (g < b) * 6;
4016
+ else if (g === max4) h = (b - r) / s + 2;
1335
4017
  else h = (r - g) / s + 4;
1336
- s /= l < 0.5 ? max3 + min3 : 2 - max3 - min3;
4018
+ s /= l < 0.5 ? max4 + min4 : 2 - max4 - min4;
1337
4019
  h *= 60;
1338
4020
  } else {
1339
4021
  s = l > 0 && l < 1 ? 0 : h;
@@ -1394,7 +4076,7 @@ function basis(t12, v0, v1, v2, v3) {
1394
4076
  var t2 = t12 * t12, t3 = t2 * t12;
1395
4077
  return ((1 - 3 * t12 + 3 * t2 - t3) * v0 + (4 - 6 * t2 + 3 * t3) * v1 + (1 + 3 * t12 + 3 * t2 - 3 * t3) * v2 + t3 * v3) / 6;
1396
4078
  }
1397
- function basis_default(values) {
4079
+ function basis_default2(values) {
1398
4080
  var n = values.length - 1;
1399
4081
  return function(t) {
1400
4082
  var i = t <= 0 ? t = 0 : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), v1 = values[i], v2 = values[i + 1], v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
@@ -1412,7 +4094,7 @@ function basisClosed_default(values) {
1412
4094
  }
1413
4095
 
1414
4096
  // ../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/constant.js
1415
- var constant_default = (x) => () => x;
4097
+ var constant_default2 = (x2) => () => x2;
1416
4098
 
1417
4099
  // ../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/color.js
1418
4100
  function linear(a, d) {
@@ -1420,24 +4102,24 @@ function linear(a, d) {
1420
4102
  return a + t * d;
1421
4103
  };
1422
4104
  }
1423
- function exponential(a, b, y) {
1424
- return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
1425
- return Math.pow(a + t * b, y);
4105
+ function exponential(a, b, y2) {
4106
+ return a = Math.pow(a, y2), b = Math.pow(b, y2) - a, y2 = 1 / y2, function(t) {
4107
+ return Math.pow(a + t * b, y2);
1426
4108
  };
1427
4109
  }
1428
- function gamma(y) {
1429
- return (y = +y) === 1 ? nogamma : function(a, b) {
1430
- return b - a ? exponential(a, b, y) : constant_default(isNaN(a) ? b : a);
4110
+ function gamma(y2) {
4111
+ return (y2 = +y2) === 1 ? nogamma : function(a, b) {
4112
+ return b - a ? exponential(a, b, y2) : constant_default2(isNaN(a) ? b : a);
1431
4113
  };
1432
4114
  }
1433
4115
  function nogamma(a, b) {
1434
4116
  var d = b - a;
1435
- return d ? linear(a, d) : constant_default(isNaN(a) ? b : a);
4117
+ return d ? linear(a, d) : constant_default2(isNaN(a) ? b : a);
1436
4118
  }
1437
4119
 
1438
4120
  // ../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/rgb.js
1439
- var rgb_default = (function rgbGamma(y) {
1440
- var color2 = gamma(y);
4121
+ var rgb_default = (function rgbGamma(y2) {
4122
+ var color2 = gamma(y2);
1441
4123
  function rgb2(start, end) {
1442
4124
  var r = color2((start = rgb(start)).r, (end = rgb(end)).r), g = color2(start.g, end.g), b = color2(start.b, end.b), opacity = nogamma(start.opacity, end.opacity);
1443
4125
  return function(t) {
@@ -1472,7 +4154,7 @@ function rgbSpline(spline) {
1472
4154
  };
1473
4155
  };
1474
4156
  }
1475
- var rgbBasis = rgbSpline(basis_default);
4157
+ var rgbBasis = rgbSpline(basis_default2);
1476
4158
  var rgbBasisClosed = rgbSpline(basisClosed_default);
1477
4159
 
1478
4160
  // ../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/numberArray.js
@@ -1484,17 +4166,17 @@ function numberArray_default(a, b) {
1484
4166
  return c;
1485
4167
  };
1486
4168
  }
1487
- function isNumberArray(x) {
1488
- return ArrayBuffer.isView(x) && !(x instanceof DataView);
4169
+ function isNumberArray(x2) {
4170
+ return ArrayBuffer.isView(x2) && !(x2 instanceof DataView);
1489
4171
  }
1490
4172
 
1491
4173
  // ../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/array.js
1492
4174
  function genericArray(a, b) {
1493
- var nb = b ? b.length : 0, na = a ? Math.min(nb, a.length) : 0, x = new Array(na), c = new Array(nb), i;
1494
- for (i = 0; i < na; ++i) x[i] = value_default(a[i], b[i]);
4175
+ var nb = b ? b.length : 0, na = a ? Math.min(nb, a.length) : 0, x2 = new Array(na), c = new Array(nb), i;
4176
+ for (i = 0; i < na; ++i) x2[i] = value_default(a[i], b[i]);
1495
4177
  for (; i < nb; ++i) c[i] = b[i];
1496
4178
  return function(t) {
1497
- for (i = 0; i < na; ++i) c[i] = x[i](t);
4179
+ for (i = 0; i < na; ++i) c[i] = x2[i](t);
1498
4180
  return c;
1499
4181
  };
1500
4182
  }
@@ -1577,7 +4259,7 @@ function string_default(a, b) {
1577
4259
  // ../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/value.js
1578
4260
  function value_default(a, b) {
1579
4261
  var t = typeof b, c;
1580
- return b == null || t === "boolean" ? constant_default(b) : (t === "number" ? number_default : t === "string" ? (c = color(b)) ? (b = c, rgb_default) : string_default : b instanceof color ? rgb_default : b instanceof Date ? date_default : isNumberArray(b) ? numberArray_default : Array.isArray(b) ? genericArray : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object_default : number_default)(a, b);
4262
+ return b == null || t === "boolean" ? constant_default2(b) : (t === "number" ? number_default : t === "string" ? (c = color(b)) ? (b = c, rgb_default) : string_default : b instanceof color ? rgb_default : b instanceof Date ? date_default : isNumberArray(b) ? numberArray_default : Array.isArray(b) ? genericArray : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object_default : number_default)(a, b);
1581
4263
  }
1582
4264
 
1583
4265
  // ../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/round.js
@@ -1588,40 +4270,40 @@ function round_default(a, b) {
1588
4270
  }
1589
4271
 
1590
4272
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/constant.js
1591
- function constants(x) {
4273
+ function constants(x2) {
1592
4274
  return function() {
1593
- return x;
4275
+ return x2;
1594
4276
  };
1595
4277
  }
1596
4278
 
1597
4279
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/number.js
1598
- function number2(x) {
1599
- return +x;
4280
+ function number2(x2) {
4281
+ return +x2;
1600
4282
  }
1601
4283
 
1602
4284
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/continuous.js
1603
4285
  var unit = [0, 1];
1604
- function identity(x) {
1605
- return x;
4286
+ function identity(x2) {
4287
+ return x2;
1606
4288
  }
1607
4289
  function normalize(a, b) {
1608
- return (b -= a = +a) ? function(x) {
1609
- return (x - a) / b;
4290
+ return (b -= a = +a) ? function(x2) {
4291
+ return (x2 - a) / b;
1610
4292
  } : constants(isNaN(b) ? NaN : 0.5);
1611
4293
  }
1612
4294
  function clamper(a, b) {
1613
4295
  var t;
1614
4296
  if (a > b) t = a, a = b, b = t;
1615
- return function(x) {
1616
- return Math.max(a, Math.min(b, x));
4297
+ return function(x2) {
4298
+ return Math.max(a, Math.min(b, x2));
1617
4299
  };
1618
4300
  }
1619
4301
  function bimap(domain, range2, interpolate) {
1620
4302
  var d0 = domain[0], d1 = domain[1], r0 = range2[0], r1 = range2[1];
1621
4303
  if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0);
1622
4304
  else d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
1623
- return function(x) {
1624
- return r0(d0(x));
4305
+ return function(x2) {
4306
+ return r0(d0(x2));
1625
4307
  };
1626
4308
  }
1627
4309
  function polymap(domain, range2, interpolate) {
@@ -1634,9 +4316,9 @@ function polymap(domain, range2, interpolate) {
1634
4316
  d[i] = normalize(domain[i], domain[i + 1]);
1635
4317
  r[i] = interpolate(range2[i], range2[i + 1]);
1636
4318
  }
1637
- return function(x) {
1638
- var i2 = bisect_default(domain, x, 1, j) - 1;
1639
- return r[i2](d[i2](x));
4319
+ return function(x2) {
4320
+ var i2 = bisect_default(domain, x2, 1, j) - 1;
4321
+ return r[i2](d[i2](x2));
1640
4322
  };
1641
4323
  }
1642
4324
  function copy(source, target) {
@@ -1651,11 +4333,11 @@ function transformer() {
1651
4333
  output = input = null;
1652
4334
  return scale;
1653
4335
  }
1654
- function scale(x) {
1655
- return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range2, interpolate)))(transform(clamp(x)));
4336
+ function scale(x2) {
4337
+ return x2 == null || isNaN(x2 = +x2) ? unknown : (output || (output = piecewise(domain.map(transform), range2, interpolate)))(transform(clamp(x2)));
1656
4338
  }
1657
- scale.invert = function(y) {
1658
- return clamp(untransform((input || (input = piecewise(range2, domain.map(transform), number_default)))(y)));
4339
+ scale.invert = function(y2) {
4340
+ return clamp(untransform((input || (input = piecewise(range2, domain.map(transform), number_default)))(y2)));
1659
4341
  };
1660
4342
  scale.domain = function(_) {
1661
4343
  return arguments.length ? (domain = Array.from(_, number2), rescale()) : domain.slice();
@@ -1685,21 +4367,21 @@ function continuous() {
1685
4367
  }
1686
4368
 
1687
4369
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/formatDecimal.js
1688
- function formatDecimal_default(x) {
1689
- return Math.abs(x = Math.round(x)) >= 1e21 ? x.toLocaleString("en").replace(/,/g, "") : x.toString(10);
4370
+ function formatDecimal_default(x2) {
4371
+ return Math.abs(x2 = Math.round(x2)) >= 1e21 ? x2.toLocaleString("en").replace(/,/g, "") : x2.toString(10);
1690
4372
  }
1691
- function formatDecimalParts(x, p) {
1692
- if (!isFinite(x) || x === 0) return null;
1693
- var i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e"), coefficient = x.slice(0, i);
4373
+ function formatDecimalParts(x2, p) {
4374
+ if (!isFinite(x2) || x2 === 0) return null;
4375
+ var i = (x2 = p ? x2.toExponential(p - 1) : x2.toExponential()).indexOf("e"), coefficient = x2.slice(0, i);
1694
4376
  return [
1695
4377
  coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
1696
- +x.slice(i + 1)
4378
+ +x2.slice(i + 1)
1697
4379
  ];
1698
4380
  }
1699
4381
 
1700
4382
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/exponent.js
1701
- function exponent_default(x) {
1702
- return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
4383
+ function exponent_default(x2) {
4384
+ return x2 = formatDecimalParts(Math.abs(x2)), x2 ? x2[1] : NaN;
1703
4385
  }
1704
4386
 
1705
4387
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/formatGroup.js
@@ -1782,51 +4464,51 @@ function formatTrim_default(s) {
1782
4464
 
1783
4465
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/formatPrefixAuto.js
1784
4466
  var prefixExponent;
1785
- function formatPrefixAuto_default(x, p) {
1786
- var d = formatDecimalParts(x, p);
1787
- if (!d) return prefixExponent = void 0, x.toPrecision(p);
4467
+ function formatPrefixAuto_default(x2, p) {
4468
+ var d = formatDecimalParts(x2, p);
4469
+ if (!d) return prefixExponent = void 0, x2.toPrecision(p);
1788
4470
  var coefficient = d[0], exponent = d[1], i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, n = coefficient.length;
1789
- return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0];
4471
+ return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimalParts(x2, Math.max(0, p + i - 1))[0];
1790
4472
  }
1791
4473
 
1792
4474
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/formatRounded.js
1793
- function formatRounded_default(x, p) {
1794
- var d = formatDecimalParts(x, p);
1795
- if (!d) return x + "";
4475
+ function formatRounded_default(x2, p) {
4476
+ var d = formatDecimalParts(x2, p);
4477
+ if (!d) return x2 + "";
1796
4478
  var coefficient = d[0], exponent = d[1];
1797
4479
  return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0");
1798
4480
  }
1799
4481
 
1800
4482
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/formatTypes.js
1801
4483
  var formatTypes_default = {
1802
- "%": (x, p) => (x * 100).toFixed(p),
1803
- "b": (x) => Math.round(x).toString(2),
1804
- "c": (x) => x + "",
4484
+ "%": (x2, p) => (x2 * 100).toFixed(p),
4485
+ "b": (x2) => Math.round(x2).toString(2),
4486
+ "c": (x2) => x2 + "",
1805
4487
  "d": formatDecimal_default,
1806
- "e": (x, p) => x.toExponential(p),
1807
- "f": (x, p) => x.toFixed(p),
1808
- "g": (x, p) => x.toPrecision(p),
1809
- "o": (x) => Math.round(x).toString(8),
1810
- "p": (x, p) => formatRounded_default(x * 100, p),
4488
+ "e": (x2, p) => x2.toExponential(p),
4489
+ "f": (x2, p) => x2.toFixed(p),
4490
+ "g": (x2, p) => x2.toPrecision(p),
4491
+ "o": (x2) => Math.round(x2).toString(8),
4492
+ "p": (x2, p) => formatRounded_default(x2 * 100, p),
1811
4493
  "r": formatRounded_default,
1812
4494
  "s": formatPrefixAuto_default,
1813
- "X": (x) => Math.round(x).toString(16).toUpperCase(),
1814
- "x": (x) => Math.round(x).toString(16)
4495
+ "X": (x2) => Math.round(x2).toString(16).toUpperCase(),
4496
+ "x": (x2) => Math.round(x2).toString(16)
1815
4497
  };
1816
4498
 
1817
4499
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/identity.js
1818
- function identity_default(x) {
1819
- return x;
4500
+ function identity_default2(x2) {
4501
+ return x2;
1820
4502
  }
1821
4503
 
1822
4504
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/locale.js
1823
4505
  var map = Array.prototype.map;
1824
4506
  var prefixes = ["y", "z", "a", "f", "p", "n", "\xB5", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
1825
4507
  function locale_default(locale3) {
1826
- var group = locale3.grouping === void 0 || locale3.thousands === void 0 ? identity_default : formatGroup_default(map.call(locale3.grouping, Number), locale3.thousands + ""), currencyPrefix = locale3.currency === void 0 ? "" : locale3.currency[0] + "", currencySuffix = locale3.currency === void 0 ? "" : locale3.currency[1] + "", decimal = locale3.decimal === void 0 ? "." : locale3.decimal + "", numerals = locale3.numerals === void 0 ? identity_default : formatNumerals_default(map.call(locale3.numerals, String)), percent = locale3.percent === void 0 ? "%" : locale3.percent + "", minus = locale3.minus === void 0 ? "\u2212" : locale3.minus + "", nan = locale3.nan === void 0 ? "NaN" : locale3.nan + "";
4508
+ var group = locale3.grouping === void 0 || locale3.thousands === void 0 ? identity_default2 : formatGroup_default(map.call(locale3.grouping, Number), locale3.thousands + ""), currencyPrefix = locale3.currency === void 0 ? "" : locale3.currency[0] + "", currencySuffix = locale3.currency === void 0 ? "" : locale3.currency[1] + "", decimal = locale3.decimal === void 0 ? "." : locale3.decimal + "", numerals = locale3.numerals === void 0 ? identity_default2 : formatNumerals_default(map.call(locale3.numerals, String)), percent = locale3.percent === void 0 ? "%" : locale3.percent + "", minus = locale3.minus === void 0 ? "\u2212" : locale3.minus + "", nan = locale3.nan === void 0 ? "NaN" : locale3.nan + "";
1827
4509
  function newFormat(specifier, options) {
1828
4510
  specifier = formatSpecifier(specifier);
1829
- var fill = specifier.fill, align = specifier.align, sign = specifier.sign, symbol = specifier.symbol, zero3 = specifier.zero, width = specifier.width, comma = specifier.comma, precision = specifier.precision, trim = specifier.trim, type = specifier.type;
4511
+ var fill = specifier.fill, align = specifier.align, sign2 = specifier.sign, symbol = specifier.symbol, zero3 = specifier.zero, width = specifier.width, comma = specifier.comma, precision = specifier.precision, trim = specifier.trim, type = specifier.type;
1830
4512
  if (type === "n") comma = true, type = "g";
1831
4513
  else if (!formatTypes_default[type]) precision === void 0 && (precision = 12), trim = true, type = "g";
1832
4514
  if (zero3 || fill === "0" && align === "=") zero3 = true, fill = "0", align = "=";
@@ -1843,9 +4525,9 @@ function locale_default(locale3) {
1843
4525
  var valueNegative = value2 < 0 || 1 / value2 < 0;
1844
4526
  value2 = isNaN(value2) ? nan : formatType(Math.abs(value2), precision);
1845
4527
  if (trim) value2 = formatTrim_default(value2);
1846
- if (valueNegative && +value2 === 0 && sign !== "+") valueNegative = false;
1847
- valuePrefix = (valueNegative ? sign === "(" ? sign : minus : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
1848
- valueSuffix = (type === "s" && !isNaN(value2) && prefixExponent !== void 0 ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
4528
+ if (valueNegative && +value2 === 0 && sign2 !== "+") valueNegative = false;
4529
+ valuePrefix = (valueNegative ? sign2 === "(" ? sign2 : minus : sign2 === "-" || sign2 === "(" ? "" : sign2) + valuePrefix;
4530
+ valueSuffix = (type === "s" && !isNaN(value2) && prefixExponent !== void 0 ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign2 === "(" ? ")" : "");
1849
4531
  if (maybeSuffix) {
1850
4532
  i = -1, n = value2.length;
1851
4533
  while (++i < n) {
@@ -1920,9 +4602,9 @@ function precisionPrefix_default(step, value2) {
1920
4602
  }
1921
4603
 
1922
4604
  // ../../node_modules/.bun/d3-format@3.1.2/node_modules/d3-format/src/precisionRound.js
1923
- function precisionRound_default(step, max3) {
1924
- step = Math.abs(step), max3 = Math.abs(max3) - step;
1925
- return Math.max(0, exponent_default(max3) - exponent_default(step)) + 1;
4605
+ function precisionRound_default(step, max4) {
4606
+ step = Math.abs(step), max4 = Math.abs(max4) - step;
4607
+ return Math.max(0, exponent_default(max4) - exponent_default(step)) + 1;
1926
4608
  }
1927
4609
 
1928
4610
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/tickFormat.js
@@ -2021,29 +4703,29 @@ function nice(domain, interval) {
2021
4703
  }
2022
4704
 
2023
4705
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/log.js
2024
- function transformLog(x) {
2025
- return Math.log(x);
4706
+ function transformLog(x2) {
4707
+ return Math.log(x2);
2026
4708
  }
2027
- function transformExp(x) {
2028
- return Math.exp(x);
4709
+ function transformExp(x2) {
4710
+ return Math.exp(x2);
2029
4711
  }
2030
- function transformLogn(x) {
2031
- return -Math.log(-x);
4712
+ function transformLogn(x2) {
4713
+ return -Math.log(-x2);
2032
4714
  }
2033
- function transformExpn(x) {
2034
- return -Math.exp(-x);
4715
+ function transformExpn(x2) {
4716
+ return -Math.exp(-x2);
2035
4717
  }
2036
- function pow10(x) {
2037
- return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
4718
+ function pow10(x2) {
4719
+ return isFinite(x2) ? +("1e" + x2) : x2 < 0 ? 0 : x2;
2038
4720
  }
2039
4721
  function powp(base) {
2040
- return base === 10 ? pow10 : base === Math.E ? Math.exp : (x) => Math.pow(base, x);
4722
+ return base === 10 ? pow10 : base === Math.E ? Math.exp : (x2) => Math.pow(base, x2);
2041
4723
  }
2042
4724
  function logp(base) {
2043
- return base === Math.E ? Math.log : base === 10 && Math.log10 || base === 2 && Math.log2 || (base = Math.log(base), (x) => Math.log(x) / base);
4725
+ return base === Math.E ? Math.log : base === 10 && Math.log10 || base === 2 && Math.log2 || (base = Math.log(base), (x2) => Math.log(x2) / base);
2044
4726
  }
2045
4727
  function reflect(f) {
2046
- return (x, k) => -f(-x, k);
4728
+ return (x2, k) => -f(-x2, k);
2047
4729
  }
2048
4730
  function loggish(transform) {
2049
4731
  const scale = transform(transformLog, transformExp);
@@ -2120,8 +4802,8 @@ function loggish(transform) {
2120
4802
  };
2121
4803
  scale.nice = () => {
2122
4804
  return domain(nice(domain(), {
2123
- floor: (x) => pows(Math.floor(logs(x))),
2124
- ceil: (x) => pows(Math.ceil(logs(x)))
4805
+ floor: (x2) => pows(Math.floor(logs(x2))),
4806
+ ceil: (x2) => pows(Math.ceil(logs(x2)))
2125
4807
  }));
2126
4808
  };
2127
4809
  return scale;
@@ -2135,13 +4817,13 @@ function log() {
2135
4817
 
2136
4818
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/symlog.js
2137
4819
  function transformSymlog(c) {
2138
- return function(x) {
2139
- return Math.sign(x) * Math.log1p(Math.abs(x / c));
4820
+ return function(x2) {
4821
+ return Math.sign(x2) * Math.log1p(Math.abs(x2 / c));
2140
4822
  };
2141
4823
  }
2142
4824
  function transformSymexp(c) {
2143
- return function(x) {
2144
- return Math.sign(x) * Math.expm1(Math.abs(x)) * c;
4825
+ return function(x2) {
4826
+ return Math.sign(x2) * Math.expm1(Math.abs(x2)) * c;
2145
4827
  };
2146
4828
  }
2147
4829
  function symlogish(transform) {
@@ -2161,15 +4843,15 @@ function symlog() {
2161
4843
 
2162
4844
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/pow.js
2163
4845
  function transformPow(exponent) {
2164
- return function(x) {
2165
- return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
4846
+ return function(x2) {
4847
+ return x2 < 0 ? -Math.pow(-x2, exponent) : Math.pow(x2, exponent);
2166
4848
  };
2167
4849
  }
2168
- function transformSqrt(x) {
2169
- return x < 0 ? -Math.sqrt(-x) : Math.sqrt(x);
4850
+ function transformSqrt(x2) {
4851
+ return x2 < 0 ? -Math.sqrt(-x2) : Math.sqrt(x2);
2170
4852
  }
2171
- function transformSquare(x) {
2172
- return x < 0 ? -x * x : x * x;
4853
+ function transformSquare(x2) {
4854
+ return x2 < 0 ? -x2 * x2 : x2 * x2;
2173
4855
  }
2174
4856
  function powish(transform) {
2175
4857
  var scale = transform(identity, identity), exponent = 1;
@@ -2189,7 +4871,7 @@ function pow() {
2189
4871
  initRange.apply(scale, arguments);
2190
4872
  return scale;
2191
4873
  }
2192
- function sqrt() {
4874
+ function sqrt2() {
2193
4875
  return pow.apply(null, arguments).exponent(0.5);
2194
4876
  }
2195
4877
 
@@ -2202,11 +4884,11 @@ function quantile2() {
2202
4884
  while (++i < n) thresholds[i - 1] = quantileSorted(domain, i / n);
2203
4885
  return scale;
2204
4886
  }
2205
- function scale(x) {
2206
- return x == null || isNaN(x = +x) ? unknown : range2[bisect_default(thresholds, x)];
4887
+ function scale(x2) {
4888
+ return x2 == null || isNaN(x2 = +x2) ? unknown : range2[bisect_default(thresholds, x2)];
2207
4889
  }
2208
- scale.invertExtent = function(y) {
2209
- var i = range2.indexOf(y);
4890
+ scale.invertExtent = function(y2) {
4891
+ var i = range2.indexOf(y2);
2210
4892
  return i < 0 ? [NaN, NaN] : [
2211
4893
  i > 0 ? thresholds[i - 1] : domain[0],
2212
4894
  i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
@@ -2237,8 +4919,8 @@ function quantile2() {
2237
4919
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/quantize.js
2238
4920
  function quantize() {
2239
4921
  var x0 = 0, x1 = 1, n = 1, domain = [0.5], range2 = [0, 1], unknown;
2240
- function scale(x) {
2241
- return x != null && x <= x ? range2[bisect_default(domain, x, 0, n)] : unknown;
4922
+ function scale(x2) {
4923
+ return x2 != null && x2 <= x2 ? range2[bisect_default(domain, x2, 0, n)] : unknown;
2242
4924
  }
2243
4925
  function rescale() {
2244
4926
  var i = -1;
@@ -2252,8 +4934,8 @@ function quantize() {
2252
4934
  scale.range = function(_) {
2253
4935
  return arguments.length ? (n = (range2 = Array.from(_)).length - 1, rescale()) : range2.slice();
2254
4936
  };
2255
- scale.invertExtent = function(y) {
2256
- var i = range2.indexOf(y);
4937
+ scale.invertExtent = function(y2) {
4938
+ var i = range2.indexOf(y2);
2257
4939
  return i < 0 ? [NaN, NaN] : i < 1 ? [x0, domain[0]] : i >= n ? [domain[n - 1], x1] : [domain[i - 1], domain[i]];
2258
4940
  };
2259
4941
  scale.unknown = function(_) {
@@ -2271,8 +4953,8 @@ function quantize() {
2271
4953
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/threshold.js
2272
4954
  function threshold() {
2273
4955
  var domain = [0.5], range2 = [0, 1], unknown, n = 1;
2274
- function scale(x) {
2275
- return x != null && x <= x ? range2[bisect_default(domain, x, 0, n)] : unknown;
4956
+ function scale(x2) {
4957
+ return x2 != null && x2 <= x2 ? range2[bisect_default(domain, x2, 0, n)] : unknown;
2276
4958
  }
2277
4959
  scale.domain = function(_) {
2278
4960
  return arguments.length ? (domain = Array.from(_), n = Math.min(domain.length, range2.length - 1), scale) : domain.slice();
@@ -2280,8 +4962,8 @@ function threshold() {
2280
4962
  scale.range = function(_) {
2281
4963
  return arguments.length ? (range2 = Array.from(_), n = Math.min(domain.length, range2.length - 1), scale) : range2.slice();
2282
4964
  };
2283
- scale.invertExtent = function(y) {
2284
- var i = range2.indexOf(y);
4965
+ scale.invertExtent = function(y2) {
4966
+ var i = range2.indexOf(y2);
2285
4967
  return [domain[i - 1], domain[i]];
2286
4968
  };
2287
4969
  scale.unknown = function(_) {
@@ -2644,8 +5326,8 @@ function utcDate(d) {
2644
5326
  }
2645
5327
  return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
2646
5328
  }
2647
- function newDate(y, m, d) {
2648
- return { y, m, d, H: 0, M: 0, S: 0, L: 0 };
5329
+ function newDate(y2, m, d) {
5330
+ return { y: y2, m, d, H: 0, M: 0, S: 0, L: 0 };
2649
5331
  }
2650
5332
  function formatLocale(locale3) {
2651
5333
  var locale_dateTime = locale3.dateTime, locale_date = locale3.date, locale_time = locale3.time, locale_periods = locale3.periods, locale_weekdays = locale3.days, locale_shortWeekdays = locale3.shortDays, locale_months = locale3.months, locale_shortMonths = locale3.shortMonths;
@@ -2933,8 +5615,8 @@ var numberRe = /^\s*\d+/;
2933
5615
  var percentRe = /^%/;
2934
5616
  var requoteRe = /[\\^$*+?|[\]().{}]/g;
2935
5617
  function pad(value2, fill, width) {
2936
- var sign = value2 < 0 ? "-" : "", string = (sign ? -value2 : value2) + "", length = string.length;
2937
- return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
5618
+ var sign2 = value2 < 0 ? "-" : "", string = (sign2 ? -value2 : value2) + "", length = string.length;
5619
+ return sign2 + (length < width ? new Array(width - length + 1).join(fill) + string : string);
2938
5620
  }
2939
5621
  function requote(s) {
2940
5622
  return s.replace(requoteRe, "\\$&");
@@ -3206,8 +5888,8 @@ function calendar(ticks2, tickInterval, year, month, week, day, hour, minute, se
3206
5888
  function tickFormat2(date2) {
3207
5889
  return (second2(date2) < date2 ? formatMillisecond : minute(date2) < date2 ? formatSecond : hour(date2) < date2 ? formatMinute : day(date2) < date2 ? formatHour : month(date2) < date2 ? week(date2) < date2 ? formatDay : formatWeek : year(date2) < date2 ? formatMonth : formatYear2)(date2);
3208
5890
  }
3209
- scale.invert = function(y) {
3210
- return new Date(invert(y));
5891
+ scale.invert = function(y2) {
5892
+ return new Date(invert(y2));
3211
5893
  };
3212
5894
  scale.domain = function(_) {
3213
5895
  return arguments.length ? domain(Array.from(_, number3)) : domain().map(date);
@@ -3241,8 +5923,8 @@ function utcTime() {
3241
5923
  // ../../node_modules/.bun/d3-scale@4.0.2/node_modules/d3-scale/src/sequential.js
3242
5924
  function transformer2() {
3243
5925
  var x0 = 0, x1 = 1, t02, t12, k10, transform, interpolator = identity, clamp = false, unknown;
3244
- function scale(x) {
3245
- return x == null || isNaN(x = +x) ? unknown : interpolator(k10 === 0 ? 0.5 : (x = (transform(x) - t02) * k10, clamp ? Math.max(0, Math.min(1, x)) : x));
5926
+ function scale(x2) {
5927
+ return x2 == null || isNaN(x2 = +x2) ? unknown : interpolator(k10 === 0 ? 0.5 : (x2 = (transform(x2) - t02) * k10, clamp ? Math.max(0, Math.min(1, x2)) : x2));
3246
5928
  }
3247
5929
  scale.domain = function(_) {
3248
5930
  return arguments.length ? ([x0, x1] = _, t02 = transform(x0 = +x0), t12 = transform(x1 = +x1), k10 = t02 === t12 ? 0 : 1 / (t12 - t02), scale) : [x0, x1];
@@ -3280,6 +5962,293 @@ function sequential() {
3280
5962
  return initInterpolator.apply(scale, arguments);
3281
5963
  }
3282
5964
 
5965
+ // src/charts/scatter/compute.ts
5966
+ var DEFAULT_POINT_RADIUS2 = 5;
5967
+ var MIN_BUBBLE_RADIUS = 3;
5968
+ var MAX_BUBBLE_RADIUS = 30;
5969
+ function resolvePosition2(value2, channelType, scale) {
5970
+ switch (channelType) {
5971
+ case "nominal":
5972
+ case "ordinal": {
5973
+ const s = String(value2);
5974
+ if ("bandwidth" in scale && typeof scale.bandwidth === "function") {
5975
+ const bw = scale.bandwidth();
5976
+ const pos = scale(s);
5977
+ if (pos === void 0) return void 0;
5978
+ return bw > 0 ? pos + bw / 2 : pos;
5979
+ }
5980
+ return scale(s);
5981
+ }
5982
+ case "temporal": {
5983
+ const px = scale(new Date(value2));
5984
+ return Number.isNaN(px) ? void 0 : px;
5985
+ }
5986
+ default: {
5987
+ const num = Number(value2);
5988
+ if (!Number.isFinite(num)) return void 0;
5989
+ return scale(num);
5990
+ }
5991
+ }
5992
+ }
5993
+ function computeScatterMarks(spec, scales, _chartArea, _strategy) {
5994
+ const encoding = spec.encoding;
5995
+ const xChannel = encoding.x;
5996
+ const yChannel = encoding.y;
5997
+ if (!xChannel || !yChannel || !scales.x || !scales.y) {
5998
+ return [];
5999
+ }
6000
+ const xScale = scales.x.scale;
6001
+ const yScale = scales.y.scale;
6002
+ const xType = xChannel.type;
6003
+ const yType = yChannel.type;
6004
+ const colorEnc = encoding.color && "field" in encoding.color ? encoding.color : void 0;
6005
+ const isSequentialColor = colorEnc?.type === "quantitative";
6006
+ const colorField = colorEnc?.field;
6007
+ const sizeField = encoding.size && "field" in encoding.size ? encoding.size.field : void 0;
6008
+ let sizeScale;
6009
+ if (sizeField) {
6010
+ const sizeValues = spec.data.map((d) => Number(d[sizeField])).filter((v) => Number.isFinite(v));
6011
+ const sizeMin = min2(sizeValues) ?? 0;
6012
+ const sizeMax = max2(sizeValues) ?? 1;
6013
+ sizeScale = sqrt2().domain([sizeMin, sizeMax]).range([MIN_BUBBLE_RADIUS, MAX_BUBBLE_RADIUS]);
6014
+ }
6015
+ const marks = [];
6016
+ for (const row of spec.data) {
6017
+ const rawX = row[xChannel.field];
6018
+ const rawY = row[yChannel.field];
6019
+ const cx = resolvePosition2(rawX, xType, xScale);
6020
+ const cy = resolvePosition2(rawY, yType, yScale);
6021
+ if (cx === void 0 || cy === void 0) continue;
6022
+ const category = colorField && !isSequentialColor ? String(row[colorField] ?? "") : void 0;
6023
+ let color2;
6024
+ if (isSequentialColor && colorField) {
6025
+ const val = Number(row[colorField]);
6026
+ color2 = Number.isFinite(val) ? getSequentialColor(scales, val) : getColor(scales, "__default__");
6027
+ } else {
6028
+ color2 = getColor(scales, category ?? "__default__");
6029
+ }
6030
+ let radius = DEFAULT_POINT_RADIUS2;
6031
+ if (sizeScale && sizeField) {
6032
+ const sizeVal = Number(row[sizeField]);
6033
+ if (Number.isFinite(sizeVal)) {
6034
+ radius = sizeScale(sizeVal);
6035
+ }
6036
+ }
6037
+ const labelParts = [`${xChannel.field}=${rawX}`, `${yChannel.field}=${rawY}`];
6038
+ if (category) labelParts.push(`${colorField}=${category}`);
6039
+ if (sizeField && row[sizeField] != null) {
6040
+ labelParts.push(`${sizeField}=${row[sizeField]}`);
6041
+ }
6042
+ const aria = {
6043
+ label: `Data point: ${labelParts.join(", ")}`
6044
+ };
6045
+ marks.push({
6046
+ type: "point",
6047
+ cx,
6048
+ cy,
6049
+ r: radius,
6050
+ fill: color2,
6051
+ stroke: "#ffffff",
6052
+ strokeWidth: 1,
6053
+ fillOpacity: 0.7,
6054
+ data: row,
6055
+ aria
6056
+ });
6057
+ }
6058
+ return marks;
6059
+ }
6060
+
6061
+ // src/charts/scatter/trendline.ts
6062
+ var TRENDLINE_COLOR = "#666666";
6063
+ var TRENDLINE_STROKE_WIDTH = 1.5;
6064
+ var TRENDLINE_DASH = "6 4";
6065
+ function linearRegression(points) {
6066
+ const n = points.length;
6067
+ if (n < 2) return null;
6068
+ let sumX = 0;
6069
+ let sumY = 0;
6070
+ let sumXY = 0;
6071
+ let sumXX = 0;
6072
+ for (const p of points) {
6073
+ sumX += p.x;
6074
+ sumY += p.y;
6075
+ sumXY += p.x * p.y;
6076
+ sumXX += p.x * p.x;
6077
+ }
6078
+ const denominator = n * sumXX - sumX * sumX;
6079
+ if (denominator === 0) return null;
6080
+ const slope = (n * sumXY - sumX * sumY) / denominator;
6081
+ const intercept = (sumY - slope * sumX) / n;
6082
+ return { slope, intercept };
6083
+ }
6084
+ function computeTrendLine(marks) {
6085
+ if (marks.length < 2) return null;
6086
+ const points = marks.map((m) => ({ x: m.cx, y: m.cy }));
6087
+ const result = linearRegression(points);
6088
+ if (!result) return null;
6089
+ const { slope, intercept } = result;
6090
+ let minX = Infinity;
6091
+ let maxX = -Infinity;
6092
+ for (const m of marks) {
6093
+ if (m.cx < minX) minX = m.cx;
6094
+ if (m.cx > maxX) maxX = m.cx;
6095
+ }
6096
+ const y1 = slope * minX + intercept;
6097
+ const y2 = slope * maxX + intercept;
6098
+ const aria = {
6099
+ label: `Trend line: linear regression`
6100
+ };
6101
+ return {
6102
+ type: "line",
6103
+ points: [
6104
+ { x: minX, y: y1 },
6105
+ { x: maxX, y: y2 }
6106
+ ],
6107
+ stroke: TRENDLINE_COLOR,
6108
+ strokeWidth: TRENDLINE_STROKE_WIDTH,
6109
+ strokeDasharray: TRENDLINE_DASH,
6110
+ data: [],
6111
+ aria
6112
+ };
6113
+ }
6114
+
6115
+ // src/charts/scatter/index.ts
6116
+ var scatterRenderer = (spec, scales, chartArea, strategy, _theme) => {
6117
+ const pointMarks = computeScatterMarks(spec, scales, chartArea, strategy);
6118
+ const marks = [...pointMarks];
6119
+ const trendLine = computeTrendLine(pointMarks);
6120
+ if (trendLine) {
6121
+ marks.unshift(trendLine);
6122
+ }
6123
+ return marks;
6124
+ };
6125
+
6126
+ // src/charts/text/index.ts
6127
+ import { getRepresentativeColor as getRepresentativeColor8 } from "@opendata-ai/openchart-core";
6128
+ function computeTextMarks(spec, scales) {
6129
+ const encoding = spec.encoding;
6130
+ const xChannel = encoding.x;
6131
+ const yChannel = encoding.y;
6132
+ const textChannel = encoding.text;
6133
+ if (!textChannel || !("field" in textChannel)) return [];
6134
+ const marks = [];
6135
+ const colorEncoding = encoding.color && "field" in encoding.color ? encoding.color : void 0;
6136
+ const colorField = colorEncoding?.field;
6137
+ const sizeEncoding = encoding.size && "field" in encoding.size ? encoding.size : void 0;
6138
+ for (const row of spec.data) {
6139
+ let x2 = 0;
6140
+ if (xChannel && scales.x) {
6141
+ const xVal = scaleValue(scales.x.scale, scales.x.type, row[xChannel.field]);
6142
+ if (xVal == null) continue;
6143
+ x2 = xVal;
6144
+ }
6145
+ let y2 = 0;
6146
+ if (yChannel && scales.y) {
6147
+ const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
6148
+ if (yVal == null) continue;
6149
+ y2 = yVal;
6150
+ }
6151
+ const text = String(row[textChannel.field] ?? "");
6152
+ if (!text) continue;
6153
+ const color2 = getRepresentativeColor8(
6154
+ colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
6155
+ );
6156
+ const fontSize = sizeEncoding ? Math.max(8, Math.min(48, Number(row[sizeEncoding.field]) || 12)) : 12;
6157
+ const aria = {
6158
+ label: text
6159
+ };
6160
+ marks.push({
6161
+ type: "textMark",
6162
+ x: x2,
6163
+ y: y2,
6164
+ text,
6165
+ fill: color2,
6166
+ fontSize,
6167
+ textAnchor: "middle",
6168
+ angle: encoding.angle && "field" in encoding.angle ? Number(row[encoding.angle.field]) || 0 : void 0,
6169
+ data: row,
6170
+ aria
6171
+ });
6172
+ }
6173
+ return marks;
6174
+ }
6175
+ var textRenderer = (spec, scales, _chartArea, _strategy, _theme) => {
6176
+ return computeTextMarks(spec, scales);
6177
+ };
6178
+
6179
+ // src/charts/tick/index.ts
6180
+ import { getRepresentativeColor as getRepresentativeColor9 } from "@opendata-ai/openchart-core";
6181
+ var DEFAULT_TICK_LENGTH = 18;
6182
+ function computeTickMarks(spec, scales, _chartArea) {
6183
+ const encoding = spec.encoding;
6184
+ const xChannel = encoding.x;
6185
+ const yChannel = encoding.y;
6186
+ if (!xChannel || !yChannel || !scales.x || !scales.y) return [];
6187
+ const colorEncoding = encoding.color && "field" in encoding.color ? encoding.color : void 0;
6188
+ const colorField = colorEncoding?.field;
6189
+ const marks = [];
6190
+ const isHorizontal = xChannel.type === "quantitative" && yChannel.type !== "quantitative";
6191
+ const orient = isHorizontal ? "horizontal" : "vertical";
6192
+ for (const row of spec.data) {
6193
+ const xVal = scaleValue(scales.x.scale, scales.x.type, row[xChannel.field]);
6194
+ const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
6195
+ if (xVal == null || yVal == null) continue;
6196
+ const color2 = getRepresentativeColor9(
6197
+ colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
6198
+ );
6199
+ const aria = {
6200
+ label: `${row[xChannel.field]}, ${row[yChannel.field]}`
6201
+ };
6202
+ marks.push({
6203
+ type: "tick",
6204
+ x: xVal,
6205
+ y: yVal,
6206
+ length: DEFAULT_TICK_LENGTH,
6207
+ orient,
6208
+ stroke: color2,
6209
+ strokeWidth: 1,
6210
+ opacity: encoding.opacity && "field" in encoding.opacity ? Math.max(0, Math.min(1, Number(row[encoding.opacity.field]) || 1)) : void 0,
6211
+ data: row,
6212
+ aria
6213
+ });
6214
+ }
6215
+ return marks;
6216
+ }
6217
+ var tickRenderer = (spec, scales, chartArea, _strategy, _theme) => {
6218
+ return computeTickMarks(spec, scales, chartArea);
6219
+ };
6220
+
6221
+ // src/charts/builtin.ts
6222
+ var builtinRenderers = {
6223
+ line: lineRenderer,
6224
+ area: areaRenderer,
6225
+ bar: barRenderer,
6226
+ // horizontal bars
6227
+ "bar:vertical": columnRenderer,
6228
+ // vertical bars (old 'column')
6229
+ point: scatterRenderer,
6230
+ // old 'scatter'
6231
+ arc: pieRenderer,
6232
+ // old 'pie' (donut handled via innerRadius)
6233
+ "arc:donut": donutRenderer,
6234
+ // old 'donut'
6235
+ circle: dotRenderer,
6236
+ // old 'dot'
6237
+ lollipop: dotRenderer,
6238
+ // semantic alias for dot/circle
6239
+ text: textRenderer,
6240
+ rule: ruleRenderer,
6241
+ tick: tickRenderer,
6242
+ rect: columnRenderer
6243
+ // rect uses column renderer (RectMark output) as baseline for heatmaps
6244
+ };
6245
+ function registerBuiltinRenderers() {
6246
+ for (const [type, renderer] of Object.entries(builtinRenderers)) {
6247
+ registerChartRenderer(type, renderer);
6248
+ }
6249
+ }
6250
+ registerBuiltinRenderers();
6251
+
3283
6252
  // src/charts/post-process.ts
3284
6253
  function computeMarkObstacles(marks, scales) {
3285
6254
  if (scales.y?.type === "band") {
@@ -4484,7 +7453,7 @@ var MAX_NODE_RADIUS = 12;
4484
7453
  var DEFAULT_EDGE_WIDTH = 1;
4485
7454
  var MIN_EDGE_WIDTH = 0.5;
4486
7455
  var MAX_EDGE_WIDTH = 4;
4487
- var DEFAULT_STROKE_WIDTH = 1;
7456
+ var DEFAULT_STROKE_WIDTH2 = 1;
4488
7457
  function darkenColor(hex2, amount = 0.2) {
4489
7458
  const clean = hex2.replace(/^#/, "");
4490
7459
  if (clean.length !== 6 && clean.length !== 3) return hex2;
@@ -4523,9 +7492,9 @@ function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
4523
7492
  if (encoding.nodeSize?.field) {
4524
7493
  const field = encoding.nodeSize.field;
4525
7494
  const values = nodes.map((n) => Number(n[field])).filter((v) => Number.isFinite(v));
4526
- const sizeMin = min(values) ?? 0;
4527
- const sizeMax = max(values) ?? 1;
4528
- sizeScale = sqrt().domain([sizeMin, sizeMax]).range([MIN_NODE_RADIUS, MAX_NODE_RADIUS]);
7495
+ const sizeMin = min2(values) ?? 0;
7496
+ const sizeMax = max2(values) ?? 1;
7497
+ sizeScale = sqrt2().domain([sizeMin, sizeMax]).range([MIN_NODE_RADIUS, MAX_NODE_RADIUS]);
4529
7498
  }
4530
7499
  let colorFn;
4531
7500
  if (encoding.nodeColor?.field) {
@@ -4534,8 +7503,8 @@ function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
4534
7503
  const scaleConfig = encoding.nodeColor.scale;
4535
7504
  if (fieldType === "quantitative") {
4536
7505
  const values = nodes.map((n) => Number(n[field])).filter((v) => Number.isFinite(v));
4537
- const colorMin = min(values) ?? 0;
4538
- const colorMax = max(values) ?? 1;
7506
+ const colorMin = min2(values) ?? 0;
7507
+ const colorMax = max2(values) ?? 1;
4539
7508
  const seqPalettes = Object.values(theme.colors.sequential);
4540
7509
  const palette = seqPalettes.length > 0 ? seqPalettes[0] : ["#ccc", "#333"];
4541
7510
  const domain = scaleConfig?.domain && scaleConfig.domain.length === 2 ? scaleConfig.domain : [colorMin, colorMax];
@@ -4577,7 +7546,7 @@ function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
4577
7546
  const override = nodeOverrides?.[node.id];
4578
7547
  const finalFill = override?.fill ?? fill;
4579
7548
  const finalRadius = override?.radius ?? radius;
4580
- const finalStrokeWidth = override?.strokeWidth ?? DEFAULT_STROKE_WIDTH;
7549
+ const finalStrokeWidth = override?.strokeWidth ?? DEFAULT_STROKE_WIDTH2;
4581
7550
  const finalStroke = override?.stroke ?? stroke;
4582
7551
  const finalLabelPriority = override?.alwaysShowLabel ? Infinity : labelPriority;
4583
7552
  return {
@@ -4598,8 +7567,8 @@ function resolveEdgeVisuals(edges, encoding, theme) {
4598
7567
  if (encoding.edgeWidth?.field) {
4599
7568
  const field = encoding.edgeWidth.field;
4600
7569
  const values = edges.map((e) => Number(e[field])).filter((v) => Number.isFinite(v));
4601
- const widthMin = min(values) ?? 0;
4602
- const widthMax = max(values) ?? 1;
7570
+ const widthMin = min2(values) ?? 0;
7571
+ const widthMax = max2(values) ?? 1;
4603
7572
  widthScale = linear2().domain([widthMin, widthMax]).range([MIN_EDGE_WIDTH, MAX_EDGE_WIDTH]);
4604
7573
  }
4605
7574
  let edgeColorFn;
@@ -4609,8 +7578,8 @@ function resolveEdgeVisuals(edges, encoding, theme) {
4609
7578
  const scaleConfig = encoding.edgeColor.scale;
4610
7579
  if (fieldType === "quantitative") {
4611
7580
  const values = edges.map((e) => Number(e[field])).filter((v) => Number.isFinite(v));
4612
- const colorMin = min(values) ?? 0;
4613
- const colorMax = max(values) ?? 1;
7581
+ const colorMin = min2(values) ?? 0;
7582
+ const colorMax = max2(values) ?? 1;
4614
7583
  const seqPalettes = Object.values(theme.colors.sequential);
4615
7584
  const palette = seqPalettes.length > 0 ? seqPalettes[0] : ["#ccc", "#333"];
4616
7585
  const domain = scaleConfig?.domain && scaleConfig.domain.length === 2 ? scaleConfig.domain : [colorMin, colorMax];
@@ -4869,11 +7838,11 @@ function compileGraph(spec, options) {
4869
7838
  var DEFAULT_COLLISION_PADDING = 5;
4870
7839
 
4871
7840
  // src/layout/axes/thinning.ts
4872
- import { estimateTextWidth as estimateTextWidth2 } from "@opendata-ai/openchart-core";
7841
+ import { estimateTextWidth as estimateTextWidth7 } from "@opendata-ai/openchart-core";
4873
7842
  var MIN_TICK_GAP_FACTOR = 1;
4874
7843
  var MIN_TICK_COUNT = 2;
4875
7844
  function measureLabel(text, fontSize, fontWeight, measureText) {
4876
- return measureText ? measureText(text, fontSize, fontWeight).width : estimateTextWidth2(text, fontSize, fontWeight);
7845
+ return measureText ? measureText(text, fontSize, fontWeight).width : estimateTextWidth7(text, fontSize, fontWeight);
4877
7846
  }
4878
7847
  function ticksOverlap(ticks2, fontSize, fontWeight, measureText, orientation = "horizontal") {
4879
7848
  if (ticks2.length < 2) return false;
@@ -4914,11 +7883,11 @@ function thinTicksUntilFit(ticks2, fontSize, fontWeight, measureText, orientatio
4914
7883
 
4915
7884
  // src/layout/axes/ticks.ts
4916
7885
  import {
4917
- abbreviateNumber,
4918
- buildD3Formatter,
7886
+ abbreviateNumber as abbreviateNumber2,
7887
+ buildD3Formatter as buildD3Formatter4,
4919
7888
  buildTemporalFormatter,
4920
7889
  formatDate,
4921
- formatNumber
7890
+ formatNumber as formatNumber2
4922
7891
  } from "@opendata-ai/openchart-core";
4923
7892
  var Y_PX_PER_TICK = {
4924
7893
  full: 55,
@@ -4947,9 +7916,9 @@ var TICK_COUNTS = {
4947
7916
  };
4948
7917
  function targetTickCount(axisLength, density, orientation) {
4949
7918
  const pxPerTick = orientation === "y" ? Y_PX_PER_TICK[density] : X_PX_PER_TICK[density];
4950
- const [min3, max3] = orientation === "y" ? Y_TICK_COUNT_RANGE[density] : X_TICK_COUNT_RANGE[density];
7919
+ const [min4, max4] = orientation === "y" ? Y_TICK_COUNT_RANGE[density] : X_TICK_COUNT_RANGE[density];
4951
7920
  const raw = Math.round(axisLength / pxPerTick);
4952
- return Math.max(min3, Math.min(max3, raw));
7921
+ return Math.max(min4, Math.min(max4, raw));
4953
7922
  }
4954
7923
  var NUMERIC_SCALE_TYPES = /* @__PURE__ */ new Set([
4955
7924
  "linear",
@@ -4973,11 +7942,11 @@ function formatTickLabel(value2, resolvedScale) {
4973
7942
  if (NUMERIC_SCALE_TYPES.has(resolvedScale.type)) {
4974
7943
  const num = value2;
4975
7944
  if (formatStr) {
4976
- const fmt = buildD3Formatter(formatStr);
7945
+ const fmt = buildD3Formatter4(formatStr);
4977
7946
  if (fmt) return fmt(num);
4978
7947
  }
4979
- if (Math.abs(num) >= 1e3) return abbreviateNumber(num);
4980
- return formatNumber(num);
7948
+ if (Math.abs(num) >= 1e3) return abbreviateNumber2(num);
7949
+ return formatNumber2(num);
4981
7950
  }
4982
7951
  return String(value2);
4983
7952
  }
@@ -5258,7 +8227,7 @@ function computeAxes(scales, chartArea, strategy, theme, measureText) {
5258
8227
  }
5259
8228
 
5260
8229
  // src/layout/dimensions.ts
5261
- import { computeChrome as computeChrome2, estimateTextWidth as estimateTextWidth3 } from "@opendata-ai/openchart-core";
8230
+ import { computeChrome as computeChrome2, estimateTextWidth as estimateTextWidth8 } from "@opendata-ai/openchart-core";
5262
8231
  function chromeToInput(chrome) {
5263
8232
  return {
5264
8233
  title: chrome.title,
@@ -5307,7 +8276,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
5307
8276
  if (xField) {
5308
8277
  for (const row of spec.data) {
5309
8278
  const label = String(row[xField] ?? "");
5310
- const w = estimateTextWidth3(label, theme.fonts.sizes.axisTick, theme.fonts.weights.normal);
8279
+ const w = estimateTextWidth8(label, theme.fonts.sizes.axisTick, theme.fonts.weights.normal);
5311
8280
  if (w > maxLabelWidth) maxLabelWidth = w;
5312
8281
  }
5313
8282
  }
@@ -5335,7 +8304,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
5335
8304
  const label = String(row[colorField] ?? "");
5336
8305
  if (!seen.has(label)) {
5337
8306
  seen.add(label);
5338
- const w = estimateTextWidth3(label, 11, 600);
8307
+ const w = estimateTextWidth8(label, 11, 600);
5339
8308
  if (w > maxLabelWidth) maxLabelWidth = w;
5340
8309
  }
5341
8310
  }
@@ -5355,7 +8324,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
5355
8324
  const maxXStr = String(maxX);
5356
8325
  for (const ann of spec.annotations) {
5357
8326
  if (ann.type === "text" && String(ann.x) === maxXStr) {
5358
- const textWidth = estimateTextWidth3(ann.text, ann.fontSize ?? 11, ann.fontWeight ?? 600);
8327
+ const textWidth = estimateTextWidth8(ann.text, ann.fontSize ?? 11, ann.fontWeight ?? 600);
5359
8328
  const dx = ann.offset?.dx ?? 0;
5360
8329
  const anchor = ann.anchor ?? "auto";
5361
8330
  const baseRightExtent = anchor === "left" ? textWidth : (
@@ -5379,7 +8348,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
5379
8348
  let maxLabelWidth = 0;
5380
8349
  for (const row of spec.data) {
5381
8350
  const label = String(row[yField] ?? "");
5382
- const w = estimateTextWidth3(label, theme.fonts.sizes.axisTick, theme.fonts.weights.normal);
8351
+ const w = estimateTextWidth8(label, theme.fonts.sizes.axisTick, theme.fonts.weights.normal);
5383
8352
  if (w > maxLabelWidth) maxLabelWidth = w;
5384
8353
  }
5385
8354
  if (maxLabelWidth > 0) {
@@ -5411,7 +8380,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
5411
8380
  }
5412
8381
  const negPrefix = spec.data.some((r) => Number(r[yField]) < 0) ? "-" : "";
5413
8382
  const labelEst = negPrefix + sampleLabel;
5414
- const labelWidth = estimateTextWidth3(
8383
+ const labelWidth = estimateTextWidth8(
5415
8384
  labelEst,
5416
8385
  theme.fonts.sizes.axisTick,
5417
8386
  theme.fonts.weights.normal
@@ -5565,8 +8534,8 @@ function buildLinearScale(channel, data, rangeStart, rangeEnd) {
5565
8534
  domainMin = d0;
5566
8535
  domainMax = d1;
5567
8536
  } else {
5568
- domainMin = min(values) ?? 0;
5569
- domainMax = max(values) ?? 1;
8537
+ domainMin = min2(values) ?? 0;
8538
+ domainMax = max2(values) ?? 1;
5570
8539
  if (channel.scale?.zero !== false) {
5571
8540
  domainMin = Math.min(0, domainMin);
5572
8541
  domainMax = Math.max(0, domainMax);
@@ -5581,8 +8550,8 @@ function buildLinearScale(channel, data, rangeStart, rangeEnd) {
5581
8550
  }
5582
8551
  function buildLogScale(channel, data, rangeStart, rangeEnd) {
5583
8552
  const values = parseNumbers(fieldValues(data, channel.field)).filter((v) => v > 0);
5584
- const domainMin = channel.scale?.domain ? channel.scale.domain[0] : min(values) ?? 1;
5585
- const domainMax = channel.scale?.domain ? channel.scale.domain[1] : max(values) ?? 10;
8553
+ const domainMin = channel.scale?.domain ? channel.scale.domain[0] : min2(values) ?? 1;
8554
+ const domainMax = channel.scale?.domain ? channel.scale.domain[1] : max2(values) ?? 10;
5586
8555
  const scale = log().domain([domainMin, domainMax]).range([rangeStart, rangeEnd]);
5587
8556
  if (channel.scale?.base !== void 0) {
5588
8557
  scale.base(channel.scale.base);
@@ -5600,8 +8569,8 @@ function buildPowScale(channel, data, rangeStart, rangeEnd) {
5600
8569
  if (channel.scale?.domain) {
5601
8570
  [domainMin, domainMax] = channel.scale.domain;
5602
8571
  } else {
5603
- domainMin = min(values) ?? 0;
5604
- domainMax = max(values) ?? 1;
8572
+ domainMin = min2(values) ?? 0;
8573
+ domainMax = max2(values) ?? 1;
5605
8574
  if (channel.scale?.zero !== false) {
5606
8575
  domainMin = Math.min(0, domainMin);
5607
8576
  domainMax = Math.max(0, domainMax);
@@ -5624,14 +8593,14 @@ function buildSqrtScale(channel, data, rangeStart, rangeEnd) {
5624
8593
  if (channel.scale?.domain) {
5625
8594
  [domainMin, domainMax] = channel.scale.domain;
5626
8595
  } else {
5627
- domainMin = min(values) ?? 0;
5628
- domainMax = max(values) ?? 1;
8596
+ domainMin = min2(values) ?? 0;
8597
+ domainMax = max2(values) ?? 1;
5629
8598
  if (channel.scale?.zero !== false) {
5630
8599
  domainMin = Math.min(0, domainMin);
5631
8600
  domainMax = Math.max(0, domainMax);
5632
8601
  }
5633
8602
  }
5634
- const scale = sqrt().domain([domainMin, domainMax]).range([rangeStart, rangeEnd]);
8603
+ const scale = sqrt2().domain([domainMin, domainMax]).range([rangeStart, rangeEnd]);
5635
8604
  if (!channel.scale?.domain && channel.scale?.nice !== false) {
5636
8605
  scale.nice();
5637
8606
  }
@@ -5645,8 +8614,8 @@ function buildSymlogScale(channel, data, rangeStart, rangeEnd) {
5645
8614
  if (channel.scale?.domain) {
5646
8615
  [domainMin, domainMax] = channel.scale.domain;
5647
8616
  } else {
5648
- domainMin = min(values) ?? 0;
5649
- domainMax = max(values) ?? 1;
8617
+ domainMin = min2(values) ?? 0;
8618
+ domainMax = max2(values) ?? 1;
5650
8619
  if (channel.scale?.zero !== false) {
5651
8620
  domainMin = Math.min(0, domainMin);
5652
8621
  domainMax = Math.max(0, domainMax);
@@ -5670,8 +8639,8 @@ function buildQuantileScale(channel, data, rangeStart, rangeEnd) {
5670
8639
  }
5671
8640
  function buildQuantizeScale(channel, data, rangeStart, rangeEnd) {
5672
8641
  const values = parseNumbers(fieldValues(data, channel.field));
5673
- const domainMin = channel.scale?.domain ? channel.scale.domain[0] : min(values) ?? 0;
5674
- const domainMax = channel.scale?.domain ? channel.scale.domain[1] : max(values) ?? 1;
8642
+ const domainMin = channel.scale?.domain ? channel.scale.domain[0] : min2(values) ?? 0;
8643
+ const domainMax = channel.scale?.domain ? channel.scale.domain[1] : max2(values) ?? 1;
5675
8644
  const range2 = channel.scale?.range ? channel.scale.range : evenRange(rangeStart, rangeEnd, 4);
5676
8645
  const scale = quantize().domain([domainMin, domainMax]).range(range2);
5677
8646
  return { scale, type: "quantize", channel };
@@ -5706,7 +8675,7 @@ function buildBandScale(channel, data, rangeStart, rangeEnd) {
5706
8675
  function buildPointScale(channel, data, rangeStart, rangeEnd) {
5707
8676
  const values = channel.scale?.domain ? channel.scale.domain : applyCategoricalSort(uniqueStrings(fieldValues(data, channel.field)), channel.sort);
5708
8677
  const padding = channel.scale?.padding ?? 0.5;
5709
- const scale = point().domain(values).range([rangeStart, rangeEnd]).padding(padding);
8678
+ const scale = point4().domain(values).range([rangeStart, rangeEnd]).padding(padding);
5710
8679
  if (channel.scale?.reverse) {
5711
8680
  const [r0, r1] = scale.range();
5712
8681
  scale.range([r1, r0]);
@@ -5723,8 +8692,8 @@ function buildOrdinalColorScale(channel, data, palette) {
5723
8692
  }
5724
8693
  function buildSequentialColorScale(channel, data, palette) {
5725
8694
  const values = parseNumbers(fieldValues(data, channel.field));
5726
- const domainMin = min(values) ?? 0;
5727
- const domainMax = max(values) ?? 1;
8695
+ const domainMin = min2(values) ?? 0;
8696
+ const domainMax = max2(values) ?? 1;
5728
8697
  const explicitRange = channel.scale?.range;
5729
8698
  const colors = explicitRange ?? palette;
5730
8699
  const scale = linear2().domain([domainMin, domainMax]).range([colors[0], colors[colors.length - 1]]).clamp(true);
@@ -5925,10 +8894,10 @@ function computeScales(spec, chartArea, data) {
5925
8894
  }
5926
8895
 
5927
8896
  // src/legend/compute.ts
5928
- import { BRAND_RESERVE_WIDTH as BRAND_RESERVE_WIDTH2, estimateTextWidth as estimateTextWidth5 } from "@opendata-ai/openchart-core";
8897
+ import { BRAND_RESERVE_WIDTH as BRAND_RESERVE_WIDTH2, estimateTextWidth as estimateTextWidth10 } from "@opendata-ai/openchart-core";
5929
8898
 
5930
8899
  // src/legend/wrap.ts
5931
- import { estimateTextWidth as estimateTextWidth4 } from "@opendata-ai/openchart-core";
8900
+ import { estimateTextWidth as estimateTextWidth9 } from "@opendata-ai/openchart-core";
5932
8901
  var SWATCH_SIZE2 = 12;
5933
8902
  var SWATCH_GAP2 = 6;
5934
8903
  var ENTRY_GAP2 = 16;
@@ -5942,7 +8911,7 @@ function measureLegendWrap(entries, maxWidth, labelStyle, maxRows) {
5942
8911
  let fittingCount = entries.length;
5943
8912
  let fittingCountLocked = false;
5944
8913
  for (let i = 0; i < entries.length; i++) {
5945
- const labelWidth = estimateTextWidth4(
8914
+ const labelWidth = estimateTextWidth9(
5946
8915
  entries[i].label,
5947
8916
  labelStyle.fontSize,
5948
8917
  labelStyle.fontWeight
@@ -6045,8 +9014,8 @@ function computeLegend(spec, strategy, theme, chartArea, watermark = true) {
6045
9014
  if (isLineOrArea && hasLabels && labelsWillRender && hasColorEncoding && legendNotForced) {
6046
9015
  const isArea = spec.markType === "area";
6047
9016
  const quantChannel = spec.encoding.y?.type === "quantitative" ? spec.encoding.y : spec.encoding.x;
6048
- const stackValue = quantChannel?.stack;
6049
- const isStacked = stackValue !== null && stackValue !== false;
9017
+ const stackValue2 = quantChannel?.stack;
9018
+ const isStacked = stackValue2 !== null && stackValue2 !== false;
6050
9019
  if (!isArea || !isStacked) {
6051
9020
  entries = [];
6052
9021
  }
@@ -6072,7 +9041,7 @@ function computeLegend(spec, strategy, theme, chartArea, watermark = true) {
6072
9041
  }
6073
9042
  if (resolvedPosition === "right" || resolvedPosition === "bottom-right") {
6074
9043
  const maxLabelWidth = Math.max(
6075
- ...entries.map((e) => estimateTextWidth5(e.label, labelStyle.fontSize, labelStyle.fontWeight))
9044
+ ...entries.map((e) => estimateTextWidth10(e.label, labelStyle.fontSize, labelStyle.fontWeight))
6076
9045
  );
6077
9046
  const legendWidth = Math.min(
6078
9047
  LEGEND_RIGHT_WIDTH,
@@ -6123,7 +9092,7 @@ function computeLegend(spec, strategy, theme, chartArea, watermark = true) {
6123
9092
  entries = truncateEntries(entries, fittingCount);
6124
9093
  }
6125
9094
  const totalWidth = entries.reduce((sum2, entry) => {
6126
- const labelWidth = estimateTextWidth5(entry.label, labelStyle.fontSize, labelStyle.fontWeight);
9095
+ const labelWidth = estimateTextWidth10(entry.label, labelStyle.fontSize, labelStyle.fontWeight);
6127
9096
  return sum2 + SWATCH_SIZE2 + SWATCH_GAP2 + labelWidth + ENTRY_GAP2;
6128
9097
  }, 0);
6129
9098
  const { rowCount } = measureLegendWrap(entries, availableWidth, labelStyle);
@@ -6150,51 +9119,51 @@ function computeLegend(spec, strategy, theme, chartArea, watermark = true) {
6150
9119
  // src/sankey/compile-sankey.ts
6151
9120
  import {
6152
9121
  adaptTheme as adaptTheme2,
6153
- buildD3Formatter as buildD3Formatter2,
9122
+ buildD3Formatter as buildD3Formatter5,
6154
9123
  computeChrome as computeChrome3,
6155
- estimateTextWidth as estimateTextWidth6,
6156
- formatNumber as formatNumber2,
9124
+ estimateTextWidth as estimateTextWidth11,
9125
+ formatNumber as formatNumber3,
6157
9126
  resolveTheme as resolveTheme2
6158
9127
  } from "@opendata-ai/openchart-core";
6159
9128
 
6160
9129
  // ../../node_modules/.bun/d3-array@2.12.1/node_modules/d3-array/src/max.js
6161
- function max2(values, valueof) {
6162
- let max3;
9130
+ function max3(values, valueof) {
9131
+ let max4;
6163
9132
  if (valueof === void 0) {
6164
9133
  for (const value2 of values) {
6165
- if (value2 != null && (max3 < value2 || max3 === void 0 && value2 >= value2)) {
6166
- max3 = value2;
9134
+ if (value2 != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
9135
+ max4 = value2;
6167
9136
  }
6168
9137
  }
6169
9138
  } else {
6170
9139
  let index = -1;
6171
9140
  for (let value2 of values) {
6172
- if ((value2 = valueof(value2, ++index, values)) != null && (max3 < value2 || max3 === void 0 && value2 >= value2)) {
6173
- max3 = value2;
9141
+ if ((value2 = valueof(value2, ++index, values)) != null && (max4 < value2 || max4 === void 0 && value2 >= value2)) {
9142
+ max4 = value2;
6174
9143
  }
6175
9144
  }
6176
9145
  }
6177
- return max3;
9146
+ return max4;
6178
9147
  }
6179
9148
 
6180
9149
  // ../../node_modules/.bun/d3-array@2.12.1/node_modules/d3-array/src/min.js
6181
- function min2(values, valueof) {
6182
- let min3;
9150
+ function min3(values, valueof) {
9151
+ let min4;
6183
9152
  if (valueof === void 0) {
6184
9153
  for (const value2 of values) {
6185
- if (value2 != null && (min3 > value2 || min3 === void 0 && value2 >= value2)) {
6186
- min3 = value2;
9154
+ if (value2 != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
9155
+ min4 = value2;
6187
9156
  }
6188
9157
  }
6189
9158
  } else {
6190
9159
  let index = -1;
6191
9160
  for (let value2 of values) {
6192
- if ((value2 = valueof(value2, ++index, values)) != null && (min3 > value2 || min3 === void 0 && value2 >= value2)) {
6193
- min3 = value2;
9161
+ if ((value2 = valueof(value2, ++index, values)) != null && (min4 > value2 || min4 === void 0 && value2 >= value2)) {
9162
+ min4 = value2;
6194
9163
  }
6195
9164
  }
6196
9165
  }
6197
- return min3;
9166
+ return min4;
6198
9167
  }
6199
9168
 
6200
9169
  // ../../node_modules/.bun/d3-array@2.12.1/node_modules/d3-array/src/sum.js
@@ -6231,13 +9200,13 @@ function justify(node, n) {
6231
9200
  return node.sourceLinks.length ? node.depth : n - 1;
6232
9201
  }
6233
9202
  function center(node) {
6234
- return node.targetLinks.length ? node.depth : node.sourceLinks.length ? min2(node.sourceLinks, targetDepth) - 1 : 0;
9203
+ return node.targetLinks.length ? node.depth : node.sourceLinks.length ? min3(node.sourceLinks, targetDepth) - 1 : 0;
6235
9204
  }
6236
9205
 
6237
9206
  // ../../node_modules/.bun/d3-sankey@0.12.3/node_modules/d3-sankey/src/constant.js
6238
- function constant(x) {
9207
+ function constant(x2) {
6239
9208
  return function() {
6240
- return x;
9209
+ return x2;
6241
9210
  };
6242
9211
  }
6243
9212
 
@@ -6371,15 +9340,15 @@ function Sankey() {
6371
9340
  const n = nodes2.length;
6372
9341
  let current = new Set(nodes2);
6373
9342
  let next = /* @__PURE__ */ new Set();
6374
- let x = 0;
9343
+ let x2 = 0;
6375
9344
  while (current.size) {
6376
9345
  for (const node of current) {
6377
- node.depth = x;
9346
+ node.depth = x2;
6378
9347
  for (const { target } of node.sourceLinks) {
6379
9348
  next.add(target);
6380
9349
  }
6381
9350
  }
6382
- if (++x > n) throw new Error("circular link");
9351
+ if (++x2 > n) throw new Error("circular link");
6383
9352
  current = next;
6384
9353
  next = /* @__PURE__ */ new Set();
6385
9354
  }
@@ -6388,25 +9357,25 @@ function Sankey() {
6388
9357
  const n = nodes2.length;
6389
9358
  let current = new Set(nodes2);
6390
9359
  let next = /* @__PURE__ */ new Set();
6391
- let x = 0;
9360
+ let x2 = 0;
6392
9361
  while (current.size) {
6393
9362
  for (const node of current) {
6394
- node.height = x;
9363
+ node.height = x2;
6395
9364
  for (const { source } of node.targetLinks) {
6396
9365
  next.add(source);
6397
9366
  }
6398
9367
  }
6399
- if (++x > n) throw new Error("circular link");
9368
+ if (++x2 > n) throw new Error("circular link");
6400
9369
  current = next;
6401
9370
  next = /* @__PURE__ */ new Set();
6402
9371
  }
6403
9372
  }
6404
9373
  function computeNodeLayers({ nodes: nodes2 }) {
6405
- const x = max2(nodes2, (d) => d.depth) + 1;
6406
- const kx = (x1 - x0 - dx) / (x - 1);
6407
- const columns = new Array(x);
9374
+ const x2 = max3(nodes2, (d) => d.depth) + 1;
9375
+ const kx = (x1 - x0 - dx) / (x2 - 1);
9376
+ const columns = new Array(x2);
6408
9377
  for (const node of nodes2) {
6409
- const i = Math.max(0, Math.min(x - 1, Math.floor(align.call(null, node, x))));
9378
+ const i = Math.max(0, Math.min(x2 - 1, Math.floor(align.call(null, node, x2))));
6410
9379
  node.layer = i;
6411
9380
  node.x0 = x0 + i * kx;
6412
9381
  node.x1 = node.x0 + dx;
@@ -6419,29 +9388,29 @@ function Sankey() {
6419
9388
  return columns;
6420
9389
  }
6421
9390
  function initializeNodeBreadths(columns) {
6422
- const ky = min2(columns, (c) => (y1 - y0 - (c.length - 1) * py) / sum(c, value));
9391
+ const ky = min3(columns, (c) => (y1 - y0 - (c.length - 1) * py) / sum(c, value));
6423
9392
  for (const nodes2 of columns) {
6424
- let y = y0;
9393
+ let y2 = y0;
6425
9394
  for (const node of nodes2) {
6426
- node.y0 = y;
6427
- node.y1 = y + node.value * ky;
6428
- y = node.y1 + py;
9395
+ node.y0 = y2;
9396
+ node.y1 = y2 + node.value * ky;
9397
+ y2 = node.y1 + py;
6429
9398
  for (const link of node.sourceLinks) {
6430
9399
  link.width = link.value * ky;
6431
9400
  }
6432
9401
  }
6433
- y = (y1 - y + py) / (nodes2.length + 1);
9402
+ y2 = (y1 - y2 + py) / (nodes2.length + 1);
6434
9403
  for (let i = 0; i < nodes2.length; ++i) {
6435
9404
  const node = nodes2[i];
6436
- node.y0 += y * (i + 1);
6437
- node.y1 += y * (i + 1);
9405
+ node.y0 += y2 * (i + 1);
9406
+ node.y1 += y2 * (i + 1);
6438
9407
  }
6439
9408
  reorderLinks(nodes2);
6440
9409
  }
6441
9410
  }
6442
9411
  function computeNodeBreadths(graph) {
6443
9412
  const columns = computeNodeLayers(graph);
6444
- py = Math.min(dy, (y1 - y0) / (max2(columns, (c) => c.length) - 1));
9413
+ py = Math.min(dy, (y1 - y0) / (max3(columns, (c) => c.length) - 1));
6445
9414
  initializeNodeBreadths(columns);
6446
9415
  for (let i = 0; i < iterations; ++i) {
6447
9416
  const alpha = Math.pow(0.99, i);
@@ -6454,45 +9423,45 @@ function Sankey() {
6454
9423
  for (let i = 1, n = columns.length; i < n; ++i) {
6455
9424
  const column = columns[i];
6456
9425
  for (const target of column) {
6457
- let y = 0;
9426
+ let y2 = 0;
6458
9427
  let w = 0;
6459
9428
  for (const { source, value: value2 } of target.targetLinks) {
6460
9429
  let v = value2 * (target.layer - source.layer);
6461
- y += targetTop(source, target) * v;
9430
+ y2 += targetTop(source, target) * v;
6462
9431
  w += v;
6463
9432
  }
6464
9433
  if (!(w > 0)) continue;
6465
- let dy2 = (y / w - target.y0) * alpha;
9434
+ let dy2 = (y2 / w - target.y0) * alpha;
6466
9435
  target.y0 += dy2;
6467
9436
  target.y1 += dy2;
6468
9437
  reorderNodeLinks(target);
6469
9438
  }
6470
9439
  if (sort === void 0) column.sort(ascendingBreadth);
6471
- resolveCollisions(column, beta);
9440
+ resolveCollisions6(column, beta);
6472
9441
  }
6473
9442
  }
6474
9443
  function relaxRightToLeft(columns, alpha, beta) {
6475
9444
  for (let n = columns.length, i = n - 2; i >= 0; --i) {
6476
9445
  const column = columns[i];
6477
9446
  for (const source of column) {
6478
- let y = 0;
9447
+ let y2 = 0;
6479
9448
  let w = 0;
6480
9449
  for (const { target, value: value2 } of source.sourceLinks) {
6481
9450
  let v = value2 * (target.layer - source.layer);
6482
- y += sourceTop(source, target) * v;
9451
+ y2 += sourceTop(source, target) * v;
6483
9452
  w += v;
6484
9453
  }
6485
9454
  if (!(w > 0)) continue;
6486
- let dy2 = (y / w - source.y0) * alpha;
9455
+ let dy2 = (y2 / w - source.y0) * alpha;
6487
9456
  source.y0 += dy2;
6488
9457
  source.y1 += dy2;
6489
9458
  reorderNodeLinks(source);
6490
9459
  }
6491
9460
  if (sort === void 0) column.sort(ascendingBreadth);
6492
- resolveCollisions(column, beta);
9461
+ resolveCollisions6(column, beta);
6493
9462
  }
6494
9463
  }
6495
- function resolveCollisions(nodes2, alpha) {
9464
+ function resolveCollisions6(nodes2, alpha) {
6496
9465
  const i = nodes2.length >> 1;
6497
9466
  const subject = nodes2[i];
6498
9467
  resolveCollisionsBottomToTop(nodes2, subject.y0 - py, i - 1, alpha);
@@ -6500,20 +9469,20 @@ function Sankey() {
6500
9469
  resolveCollisionsBottomToTop(nodes2, y1, nodes2.length - 1, alpha);
6501
9470
  resolveCollisionsTopToBottom(nodes2, y0, 0, alpha);
6502
9471
  }
6503
- function resolveCollisionsTopToBottom(nodes2, y, i, alpha) {
9472
+ function resolveCollisionsTopToBottom(nodes2, y2, i, alpha) {
6504
9473
  for (; i < nodes2.length; ++i) {
6505
9474
  const node = nodes2[i];
6506
- const dy2 = (y - node.y0) * alpha;
9475
+ const dy2 = (y2 - node.y0) * alpha;
6507
9476
  if (dy2 > 1e-6) node.y0 += dy2, node.y1 += dy2;
6508
- y = node.y1 + py;
9477
+ y2 = node.y1 + py;
6509
9478
  }
6510
9479
  }
6511
- function resolveCollisionsBottomToTop(nodes2, y, i, alpha) {
9480
+ function resolveCollisionsBottomToTop(nodes2, y2, i, alpha) {
6512
9481
  for (; i >= 0; --i) {
6513
9482
  const node = nodes2[i];
6514
- const dy2 = (node.y1 - y) * alpha;
9483
+ const dy2 = (node.y1 - y2) * alpha;
6515
9484
  if (dy2 > 1e-6) node.y0 -= dy2, node.y1 -= dy2;
6516
- y = node.y0 - py;
9485
+ y2 = node.y0 - py;
6517
9486
  }
6518
9487
  }
6519
9488
  function reorderNodeLinks({ sourceLinks, targetLinks }) {
@@ -6535,28 +9504,28 @@ function Sankey() {
6535
9504
  }
6536
9505
  }
6537
9506
  function targetTop(source, target) {
6538
- let y = source.y0 - (source.sourceLinks.length - 1) * py / 2;
9507
+ let y2 = source.y0 - (source.sourceLinks.length - 1) * py / 2;
6539
9508
  for (const { target: node, width } of source.sourceLinks) {
6540
9509
  if (node === target) break;
6541
- y += width + py;
9510
+ y2 += width + py;
6542
9511
  }
6543
9512
  for (const { source: node, width } of target.targetLinks) {
6544
9513
  if (node === source) break;
6545
- y -= width;
9514
+ y2 -= width;
6546
9515
  }
6547
- return y;
9516
+ return y2;
6548
9517
  }
6549
9518
  function sourceTop(source, target) {
6550
- let y = target.y0 - (target.targetLinks.length - 1) * py / 2;
9519
+ let y2 = target.y0 - (target.targetLinks.length - 1) * py / 2;
6551
9520
  for (const { source: node, width } of target.targetLinks) {
6552
9521
  if (node === source) break;
6553
- y += width + py;
9522
+ y2 += width + py;
6554
9523
  }
6555
9524
  for (const { target: node, width } of source.sourceLinks) {
6556
9525
  if (node === target) break;
6557
- y -= width;
9526
+ y2 -= width;
6558
9527
  }
6559
- return y;
9528
+ return y2;
6560
9529
  }
6561
9530
  return sankey;
6562
9531
  }
@@ -6824,7 +9793,7 @@ function compileSankey(spec, options) {
6824
9793
  sankeySpec.nodeSort
6825
9794
  );
6826
9795
  const nodeLabelAlign = sankeySpec.nodeLabelAlign ?? "auto";
6827
- const maxDepthFirst = nodes.reduce((max3, n) => Math.max(max3, n.depth ?? 0), 0);
9796
+ const maxDepthFirst = nodes.reduce((max4, n) => Math.max(max4, n.depth ?? 0), 0);
6828
9797
  const rightEdge = area.x + area.width;
6829
9798
  let maxOverflow = 0;
6830
9799
  for (const node of nodes) {
@@ -6833,7 +9802,7 @@ function compileSankey(spec, options) {
6833
9802
  if (labelsLeft) continue;
6834
9803
  const labelX = (node.x1 ?? nodeWidth) + LABEL_GAP;
6835
9804
  const labelText = node.label ?? node.id;
6836
- const labelWidth = estimateTextWidth6(labelText, labelFontSize, labelFontWeight);
9805
+ const labelWidth = estimateTextWidth11(labelText, labelFontSize, labelFontWeight);
6837
9806
  const overflow = labelX + labelWidth - rightEdge;
6838
9807
  if (overflow > maxOverflow) maxOverflow = overflow;
6839
9808
  }
@@ -6866,7 +9835,7 @@ function compileSankey(spec, options) {
6866
9835
  sourceField,
6867
9836
  targetField
6868
9837
  );
6869
- const maxDepth = nodes.reduce((max3, n) => Math.max(max3, n.depth ?? 0), 0);
9838
+ const maxDepth = nodes.reduce((max4, n) => Math.max(max4, n.depth ?? 0), 0);
6870
9839
  const nodeMarks = nodes.map((node) => {
6871
9840
  const fill = nodeColorMap.get(node.id) ?? theme.colors.categorical[0];
6872
9841
  const depth = node.depth ?? 0;
@@ -7022,10 +9991,10 @@ function buildSankeyLegend(nodeColorMap, colorField, data, sourceField, targetFi
7022
9991
  }
7023
9992
  function formatFlowValue(value2, valueFormat) {
7024
9993
  if (valueFormat) {
7025
- const fmt = buildD3Formatter2(valueFormat);
9994
+ const fmt = buildD3Formatter5(valueFormat);
7026
9995
  if (fmt) return fmt(value2);
7027
9996
  }
7028
- return formatNumber2(value2);
9997
+ return formatNumber3(value2);
7029
9998
  }
7030
9999
  function buildTooltipDescriptors(nodes, links, valueFormat) {
7031
10000
  const descriptors = /* @__PURE__ */ new Map();
@@ -7094,7 +10063,7 @@ function emptyLayout(area, chrome, theme, options, watermark) {
7094
10063
  }
7095
10064
 
7096
10065
  // src/tables/compile-table.ts
7097
- import { computeChrome as computeChrome4, estimateTextWidth as estimateTextWidth7 } from "@opendata-ai/openchart-core";
10066
+ import { computeChrome as computeChrome4, estimateTextWidth as estimateTextWidth12 } from "@opendata-ai/openchart-core";
7098
10067
 
7099
10068
  // src/tables/bar-column.ts
7100
10069
  var NEGATIVE_BAR_COLOR = "#c44e52";
@@ -7132,24 +10101,24 @@ function computeBarCell(value2, config, columnMax, columnMin, theme, _darkMode)
7132
10101
  };
7133
10102
  }
7134
10103
  function computeColumnMax(data, key) {
7135
- let max3 = 0;
10104
+ let max4 = 0;
7136
10105
  for (const row of data) {
7137
10106
  const val = row[key];
7138
- if (typeof val === "number" && Number.isFinite(val) && val > max3) {
7139
- max3 = val;
10107
+ if (typeof val === "number" && Number.isFinite(val) && val > max4) {
10108
+ max4 = val;
7140
10109
  }
7141
10110
  }
7142
- return max3;
10111
+ return max4;
7143
10112
  }
7144
10113
  function computeColumnMin(data, key) {
7145
- let min3 = 0;
10114
+ let min4 = 0;
7146
10115
  for (const row of data) {
7147
10116
  const val = row[key];
7148
- if (typeof val === "number" && Number.isFinite(val) && val < min3) {
7149
- min3 = val;
10117
+ if (typeof val === "number" && Number.isFinite(val) && val < min4) {
10118
+ min4 = val;
7150
10119
  }
7151
10120
  }
7152
- return min3;
10121
+ return min4;
7153
10122
  }
7154
10123
 
7155
10124
  // src/tables/category-colors.ts
@@ -7211,7 +10180,7 @@ function computeCategoryColors(data, column, theme, darkMode) {
7211
10180
  }
7212
10181
 
7213
10182
  // src/tables/format-cells.ts
7214
- import { buildD3Formatter as buildD3Formatter3, formatDate as formatDate2, formatNumber as formatNumber3 } from "@opendata-ai/openchart-core";
10183
+ import { buildD3Formatter as buildD3Formatter6, formatDate as formatDate2, formatNumber as formatNumber4 } from "@opendata-ai/openchart-core";
7215
10184
  function isNumericValue(value2) {
7216
10185
  if (typeof value2 === "number") return Number.isFinite(value2);
7217
10186
  return false;
@@ -7230,7 +10199,7 @@ function formatCell(value2, column) {
7230
10199
  };
7231
10200
  }
7232
10201
  if (column.format && isNumericValue(value2)) {
7233
- const formatter = buildD3Formatter3(column.format);
10202
+ const formatter = buildD3Formatter6(column.format);
7234
10203
  if (formatter) {
7235
10204
  return {
7236
10205
  value: value2,
@@ -7242,7 +10211,7 @@ function formatCell(value2, column) {
7242
10211
  if (isNumericValue(value2)) {
7243
10212
  return {
7244
10213
  value: value2,
7245
- formattedValue: formatNumber3(value2),
10214
+ formattedValue: formatNumber4(value2),
7246
10215
  style
7247
10216
  };
7248
10217
  }
@@ -7262,13 +10231,13 @@ function formatCell(value2, column) {
7262
10231
  function formatValueForSearch(value2, column) {
7263
10232
  if (value2 == null) return "";
7264
10233
  if (column.format && isNumericValue(value2)) {
7265
- const formatter = buildD3Formatter3(column.format);
10234
+ const formatter = buildD3Formatter6(column.format);
7266
10235
  if (formatter) {
7267
10236
  return formatter(value2);
7268
10237
  }
7269
10238
  }
7270
10239
  if (isNumericValue(value2)) {
7271
- return formatNumber3(value2);
10240
+ return formatNumber4(value2);
7272
10241
  }
7273
10242
  return String(value2);
7274
10243
  }
@@ -7315,13 +10284,13 @@ function computeHeatmapColors(data, column, theme, darkMode) {
7315
10284
  if (config.domain) {
7316
10285
  domain = config.domain;
7317
10286
  } else {
7318
- let min3 = Infinity;
7319
- let max3 = -Infinity;
10287
+ let min4 = Infinity;
10288
+ let max4 = -Infinity;
7320
10289
  for (const { value: value2 } of numericValues) {
7321
- if (value2 < min3) min3 = value2;
7322
- if (value2 > max3) max3 = value2;
10290
+ if (value2 < min4) min4 = value2;
10291
+ if (value2 > max4) max4 = value2;
7323
10292
  }
7324
- domain = [min3, max3];
10293
+ domain = [min4, max4];
7325
10294
  }
7326
10295
  let stops = resolvePalette(config.palette, theme);
7327
10296
  if (darkMode) {
@@ -7437,14 +10406,14 @@ function computeSparkline(values, config, theme, _darkMode) {
7437
10406
  if (values.length === 0) return null;
7438
10407
  const type = config.type ?? "line";
7439
10408
  const color2 = config.color ?? theme.colors.categorical[0];
7440
- let min3 = Infinity;
7441
- let max3 = -Infinity;
10409
+ let min4 = Infinity;
10410
+ let max4 = -Infinity;
7442
10411
  for (const v of values) {
7443
- if (v < min3) min3 = v;
7444
- if (v > max3) max3 = v;
10412
+ if (v < min4) min4 = v;
10413
+ if (v > max4) max4 = v;
7445
10414
  }
7446
- const range2 = max3 - min3;
7447
- const normalize2 = (v) => range2 === 0 ? 0.5 : (v - min3) / range2;
10415
+ const range2 = max4 - min4;
10416
+ const normalize2 = (v) => range2 === 0 ? 0.5 : (v - min4) / range2;
7448
10417
  const startValue = values[0];
7449
10418
  const endValue = values[values.length - 1];
7450
10419
  if (type === "line") {
@@ -7509,13 +10478,13 @@ function estimateColumnWidth(col, data, fontSize) {
7509
10478
  if (col.image) return (col.image.width ?? 24) + PADDING;
7510
10479
  if (col.flag) return 60;
7511
10480
  const label = col.label ?? col.key;
7512
- const headerWidth = estimateTextWidth7(label, fontSize, 600) + PADDING;
10481
+ const headerWidth = estimateTextWidth12(label, fontSize, 600) + PADDING;
7513
10482
  const sampleSize = Math.min(100, data.length);
7514
10483
  let maxDataWidth = 0;
7515
10484
  for (let i = 0; i < sampleSize; i++) {
7516
10485
  const val = data[i][col.key];
7517
10486
  const text = val == null ? "" : String(val);
7518
- const width = estimateTextWidth7(text, fontSize, 400) + PADDING;
10487
+ const width = estimateTextWidth12(text, fontSize, 400) + PADDING;
7519
10488
  if (width > maxDataWidth) maxDataWidth = width;
7520
10489
  }
7521
10490
  return Math.max(MIN_WIDTH, headerWidth, maxDataWidth);
@@ -7743,8 +10712,8 @@ function compileTableLayout(spec, options, theme) {
7743
10712
  import {
7744
10713
  buildTemporalFormatter as buildTemporalFormatter2,
7745
10714
  formatDate as formatDate3,
7746
- formatNumber as formatNumber4,
7747
- getRepresentativeColor
10715
+ formatNumber as formatNumber5,
10716
+ getRepresentativeColor as getRepresentativeColor10
7748
10717
  } from "@opendata-ai/openchart-core";
7749
10718
  function formatValue(value2, fieldType, format2) {
7750
10719
  if (value2 == null) return "";
@@ -7758,10 +10727,10 @@ function formatValue(value2, fieldType, format2) {
7758
10727
  try {
7759
10728
  return format(format2)(value2);
7760
10729
  } catch {
7761
- return formatNumber4(value2);
10730
+ return formatNumber5(value2);
7762
10731
  }
7763
10732
  }
7764
- return formatNumber4(value2);
10733
+ return formatNumber5(value2);
7765
10734
  }
7766
10735
  return String(value2);
7767
10736
  }
@@ -7860,12 +10829,12 @@ function tooltipsForLine(mark, encoding, _markIndex) {
7860
10829
  }
7861
10830
  function tooltipsForPoint(mark, encoding, markIndex) {
7862
10831
  const title = getTooltipTitle(mark.data, encoding);
7863
- const fields = buildFields(mark.data, encoding, getRepresentativeColor(mark.fill));
10832
+ const fields = buildFields(mark.data, encoding, getRepresentativeColor10(mark.fill));
7864
10833
  return [[`point-${markIndex}`, { title, fields }]];
7865
10834
  }
7866
10835
  function tooltipsForRect(mark, encoding, markIndex) {
7867
10836
  const title = getTooltipTitle(mark.data, encoding);
7868
- const fields = buildFields(mark.data, encoding, getRepresentativeColor(mark.fill));
10837
+ const fields = buildFields(mark.data, encoding, getRepresentativeColor10(mark.fill));
7869
10838
  return [[`rect-${markIndex}`, { title, fields }]];
7870
10839
  }
7871
10840
  function tooltipsForArc(mark, encoding, markIndex) {
@@ -7878,14 +10847,14 @@ function tooltipsForArc(mark, encoding, markIndex) {
7878
10847
  fields.push({
7879
10848
  label: categoryName,
7880
10849
  value: formatValue(row[encoding.y.field], encoding.y.type, resolveFormat(encoding.y)),
7881
- color: getRepresentativeColor(mark.fill)
10850
+ color: getRepresentativeColor10(mark.fill)
7882
10851
  });
7883
10852
  }
7884
10853
  } else if (encoding.y) {
7885
10854
  fields.push({
7886
10855
  label: resolveLabel(encoding.y),
7887
10856
  value: formatValue(row[encoding.y.field], encoding.y.type, resolveFormat(encoding.y)),
7888
- color: getRepresentativeColor(mark.fill)
10857
+ color: getRepresentativeColor10(mark.fill)
7889
10858
  });
7890
10859
  }
7891
10860
  const title = colorEnc ? String(row[colorEnc.field] ?? "") : void 0;
@@ -7896,7 +10865,7 @@ function tooltipsForArea(mark, encoding, _markIndex) {
7896
10865
  for (const dp of mark.dataPoints) {
7897
10866
  dp.tooltip = {
7898
10867
  title: getTooltipTitle(dp.datum, encoding),
7899
- fields: buildFields(dp.datum, encoding, getRepresentativeColor(mark.fill))
10868
+ fields: buildFields(dp.datum, encoding, getRepresentativeColor10(mark.fill))
7900
10869
  };
7901
10870
  }
7902
10871
  }
@@ -8046,16 +11015,16 @@ function runBin(data, transform) {
8046
11015
  const field = transform.field;
8047
11016
  let extent2 = params.extent;
8048
11017
  if (!extent2) {
8049
- let min3 = Infinity;
8050
- let max3 = -Infinity;
11018
+ let min4 = Infinity;
11019
+ let max4 = -Infinity;
8051
11020
  for (const row of data) {
8052
11021
  const v = Number(row[field]);
8053
11022
  if (Number.isFinite(v)) {
8054
- if (v < min3) min3 = v;
8055
- if (v > max3) max3 = v;
11023
+ if (v < min4) min4 = v;
11024
+ if (v > max4) max4 = v;
8056
11025
  }
8057
11026
  }
8058
- extent2 = [min3 === Infinity ? 0 : min3, max3 === -Infinity ? 0 : max3];
11027
+ extent2 = [min4 === Infinity ? 0 : min4, max4 === -Infinity ? 0 : max4];
8059
11028
  }
8060
11029
  const step = params.step ?? computeStep(extent2, maxbins, nice2);
8061
11030
  const [startAs, endAs] = Array.isArray(transform.as) ? transform.as : [transform.as, void 0];