@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 +3340 -371
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
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
|
|
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
|
|
399
|
-
let
|
|
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
|
-
|
|
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
|
-
|
|
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 ?
|
|
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:
|
|
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
|
-
|
|
595
|
-
|
|
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
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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
|
-
|
|
602
|
-
|
|
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
|
-
|
|
605
|
-
|
|
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
|
-
|
|
608
|
-
|
|
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
|
-
|
|
611
|
-
|
|
612
|
-
|
|
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
|
-
|
|
615
|
-
|
|
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
|
|
2795
|
+
return marks;
|
|
618
2796
|
}
|
|
619
|
-
function
|
|
620
|
-
|
|
621
|
-
|
|
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
|
-
|
|
624
|
-
|
|
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
|
-
|
|
627
|
-
|
|
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
|
-
|
|
630
|
-
|
|
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
|
-
|
|
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/
|
|
636
|
-
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
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
|
|
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
|
-
|
|
649
|
-
|
|
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,
|
|
680
|
-
delta = (d,
|
|
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,
|
|
3368
|
+
function left2(a, x2, lo = 0, hi = a.length) {
|
|
687
3369
|
if (lo < hi) {
|
|
688
|
-
if (compare1(
|
|
3370
|
+
if (compare1(x2, x2) !== 0) return hi;
|
|
689
3371
|
do {
|
|
690
3372
|
const mid = lo + hi >>> 1;
|
|
691
|
-
if (compare2(a[mid],
|
|
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,
|
|
3379
|
+
function right2(a, x2, lo = 0, hi = a.length) {
|
|
698
3380
|
if (lo < hi) {
|
|
699
|
-
if (compare1(
|
|
3381
|
+
if (compare1(x2, x2) !== 0) return hi;
|
|
700
3382
|
do {
|
|
701
3383
|
const mid = lo + hi >>> 1;
|
|
702
|
-
if (compare2(a[mid],
|
|
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,
|
|
709
|
-
const i = left2(a,
|
|
710
|
-
return i > lo && delta(a[i - 1],
|
|
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(
|
|
720
|
-
return
|
|
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
|
|
733
|
-
let
|
|
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 (
|
|
738
|
-
if (value2 >= value2)
|
|
3419
|
+
if (min4 === void 0) {
|
|
3420
|
+
if (value2 >= value2) min4 = max4 = value2;
|
|
739
3421
|
} else {
|
|
740
|
-
if (
|
|
741
|
-
if (
|
|
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 (
|
|
750
|
-
if (value2 >= value2)
|
|
3431
|
+
if (min4 === void 0) {
|
|
3432
|
+
if (value2 >= value2) min4 = max4 = value2;
|
|
751
3433
|
} else {
|
|
752
|
-
if (
|
|
753
|
-
if (
|
|
3434
|
+
if (min4 > value2) min4 = value2;
|
|
3435
|
+
if (max4 < value2) max4 = value2;
|
|
754
3436
|
}
|
|
755
3437
|
}
|
|
756
3438
|
}
|
|
757
3439
|
}
|
|
758
|
-
return [
|
|
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
|
|
855
|
-
let
|
|
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 && (
|
|
859
|
-
|
|
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 && (
|
|
866
|
-
|
|
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
|
|
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
|
|
875
|
-
let
|
|
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 && (
|
|
879
|
-
|
|
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 && (
|
|
886
|
-
|
|
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
|
|
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
|
|
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,
|
|
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 ===
|
|
1334
|
-
else if (g ===
|
|
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 ?
|
|
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
|
|
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
|
|
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,
|
|
1424
|
-
return a = Math.pow(a,
|
|
1425
|
-
return Math.pow(a + t * b,
|
|
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(
|
|
1429
|
-
return (
|
|
1430
|
-
return b - a ? exponential(a, b,
|
|
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) :
|
|
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(
|
|
1440
|
-
var color2 = gamma(
|
|
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(
|
|
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(
|
|
1488
|
-
return ArrayBuffer.isView(
|
|
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,
|
|
1494
|
-
for (i = 0; i < na; ++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] =
|
|
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" ?
|
|
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(
|
|
4273
|
+
function constants(x2) {
|
|
1592
4274
|
return function() {
|
|
1593
|
-
return
|
|
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(
|
|
1599
|
-
return +
|
|
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(
|
|
1605
|
-
return
|
|
4286
|
+
function identity(x2) {
|
|
4287
|
+
return x2;
|
|
1606
4288
|
}
|
|
1607
4289
|
function normalize(a, b) {
|
|
1608
|
-
return (b -= a = +a) ? function(
|
|
1609
|
-
return (
|
|
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(
|
|
1616
|
-
return Math.max(a, Math.min(b,
|
|
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(
|
|
1624
|
-
return r0(d0(
|
|
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(
|
|
1638
|
-
var i2 = bisect_default(domain,
|
|
1639
|
-
return r[i2](d[i2](
|
|
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(
|
|
1655
|
-
return
|
|
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(
|
|
1658
|
-
return clamp(untransform((input || (input = piecewise(range2, domain.map(transform), number_default)))(
|
|
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(
|
|
1689
|
-
return Math.abs(
|
|
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(
|
|
1692
|
-
if (!isFinite(
|
|
1693
|
-
var 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
|
-
+
|
|
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(
|
|
1702
|
-
return
|
|
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(
|
|
1786
|
-
var d = formatDecimalParts(
|
|
1787
|
-
if (!d) return prefixExponent = void 0,
|
|
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(
|
|
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(
|
|
1794
|
-
var d = formatDecimalParts(
|
|
1795
|
-
if (!d) return
|
|
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
|
-
"%": (
|
|
1803
|
-
"b": (
|
|
1804
|
-
"c": (
|
|
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": (
|
|
1807
|
-
"f": (
|
|
1808
|
-
"g": (
|
|
1809
|
-
"o": (
|
|
1810
|
-
"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": (
|
|
1814
|
-
"x": (
|
|
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
|
|
1819
|
-
return
|
|
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 ?
|
|
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,
|
|
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 &&
|
|
1847
|
-
valuePrefix = (valueNegative ?
|
|
1848
|
-
valueSuffix = (type === "s" && !isNaN(value2) && prefixExponent !== void 0 ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative &&
|
|
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,
|
|
1924
|
-
step = Math.abs(step),
|
|
1925
|
-
return Math.max(0, exponent_default(
|
|
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(
|
|
2025
|
-
return Math.log(
|
|
4706
|
+
function transformLog(x2) {
|
|
4707
|
+
return Math.log(x2);
|
|
2026
4708
|
}
|
|
2027
|
-
function transformExp(
|
|
2028
|
-
return Math.exp(
|
|
4709
|
+
function transformExp(x2) {
|
|
4710
|
+
return Math.exp(x2);
|
|
2029
4711
|
}
|
|
2030
|
-
function transformLogn(
|
|
2031
|
-
return -Math.log(-
|
|
4712
|
+
function transformLogn(x2) {
|
|
4713
|
+
return -Math.log(-x2);
|
|
2032
4714
|
}
|
|
2033
|
-
function transformExpn(
|
|
2034
|
-
return -Math.exp(-
|
|
4715
|
+
function transformExpn(x2) {
|
|
4716
|
+
return -Math.exp(-x2);
|
|
2035
4717
|
}
|
|
2036
|
-
function pow10(
|
|
2037
|
-
return isFinite(
|
|
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 : (
|
|
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), (
|
|
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 (
|
|
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: (
|
|
2124
|
-
ceil: (
|
|
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(
|
|
2139
|
-
return Math.sign(
|
|
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(
|
|
2144
|
-
return Math.sign(
|
|
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(
|
|
2165
|
-
return
|
|
4846
|
+
return function(x2) {
|
|
4847
|
+
return x2 < 0 ? -Math.pow(-x2, exponent) : Math.pow(x2, exponent);
|
|
2166
4848
|
};
|
|
2167
4849
|
}
|
|
2168
|
-
function transformSqrt(
|
|
2169
|
-
return
|
|
4850
|
+
function transformSqrt(x2) {
|
|
4851
|
+
return x2 < 0 ? -Math.sqrt(-x2) : Math.sqrt(x2);
|
|
2170
4852
|
}
|
|
2171
|
-
function transformSquare(
|
|
2172
|
-
return
|
|
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
|
|
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(
|
|
2206
|
-
return
|
|
4887
|
+
function scale(x2) {
|
|
4888
|
+
return x2 == null || isNaN(x2 = +x2) ? unknown : range2[bisect_default(thresholds, x2)];
|
|
2207
4889
|
}
|
|
2208
|
-
scale.invertExtent = function(
|
|
2209
|
-
var i = range2.indexOf(
|
|
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(
|
|
2241
|
-
return
|
|
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(
|
|
2256
|
-
var i = range2.indexOf(
|
|
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(
|
|
2275
|
-
return
|
|
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(
|
|
2284
|
-
var i = range2.indexOf(
|
|
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(
|
|
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
|
|
2937
|
-
return
|
|
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(
|
|
3210
|
-
return new Date(invert(
|
|
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(
|
|
3245
|
-
return
|
|
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
|
|
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 =
|
|
4527
|
-
const sizeMax =
|
|
4528
|
-
sizeScale =
|
|
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 =
|
|
4538
|
-
const colorMax =
|
|
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 ??
|
|
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 =
|
|
4602
|
-
const widthMax =
|
|
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 =
|
|
4613
|
-
const colorMax =
|
|
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
|
|
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 :
|
|
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 [
|
|
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(
|
|
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 =
|
|
7945
|
+
const fmt = buildD3Formatter4(formatStr);
|
|
4977
7946
|
if (fmt) return fmt(num);
|
|
4978
7947
|
}
|
|
4979
|
-
if (Math.abs(num) >= 1e3) return
|
|
4980
|
-
return
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
5569
|
-
domainMax =
|
|
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] :
|
|
5585
|
-
const domainMax = channel.scale?.domain ? channel.scale.domain[1] :
|
|
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 =
|
|
5604
|
-
domainMax =
|
|
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 =
|
|
5628
|
-
domainMax =
|
|
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 =
|
|
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 =
|
|
5649
|
-
domainMax =
|
|
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] :
|
|
5674
|
-
const domainMax = channel.scale?.domain ? channel.scale.domain[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 =
|
|
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 =
|
|
5727
|
-
const domainMax =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
6049
|
-
const isStacked =
|
|
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) =>
|
|
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 =
|
|
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
|
|
9122
|
+
buildD3Formatter as buildD3Formatter5,
|
|
6154
9123
|
computeChrome as computeChrome3,
|
|
6155
|
-
estimateTextWidth as
|
|
6156
|
-
formatNumber as
|
|
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
|
|
6162
|
-
let
|
|
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 && (
|
|
6166
|
-
|
|
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 && (
|
|
6173
|
-
|
|
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
|
|
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
|
|
6182
|
-
let
|
|
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 && (
|
|
6186
|
-
|
|
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 && (
|
|
6193
|
-
|
|
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
|
|
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 ?
|
|
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(
|
|
9207
|
+
function constant(x2) {
|
|
6239
9208
|
return function() {
|
|
6240
|
-
return
|
|
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
|
|
9343
|
+
let x2 = 0;
|
|
6375
9344
|
while (current.size) {
|
|
6376
9345
|
for (const node of current) {
|
|
6377
|
-
node.depth =
|
|
9346
|
+
node.depth = x2;
|
|
6378
9347
|
for (const { target } of node.sourceLinks) {
|
|
6379
9348
|
next.add(target);
|
|
6380
9349
|
}
|
|
6381
9350
|
}
|
|
6382
|
-
if (++
|
|
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
|
|
9360
|
+
let x2 = 0;
|
|
6392
9361
|
while (current.size) {
|
|
6393
9362
|
for (const node of current) {
|
|
6394
|
-
node.height =
|
|
9363
|
+
node.height = x2;
|
|
6395
9364
|
for (const { source } of node.targetLinks) {
|
|
6396
9365
|
next.add(source);
|
|
6397
9366
|
}
|
|
6398
9367
|
}
|
|
6399
|
-
if (++
|
|
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
|
|
6406
|
-
const kx = (x1 - x0 - dx) / (
|
|
6407
|
-
const columns = new Array(
|
|
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(
|
|
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 =
|
|
9391
|
+
const ky = min3(columns, (c) => (y1 - y0 - (c.length - 1) * py) / sum(c, value));
|
|
6423
9392
|
for (const nodes2 of columns) {
|
|
6424
|
-
let
|
|
9393
|
+
let y2 = y0;
|
|
6425
9394
|
for (const node of nodes2) {
|
|
6426
|
-
node.y0 =
|
|
6427
|
-
node.y1 =
|
|
6428
|
-
|
|
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
|
-
|
|
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 +=
|
|
6437
|
-
node.y1 +=
|
|
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) / (
|
|
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
|
|
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
|
-
|
|
9430
|
+
y2 += targetTop(source, target) * v;
|
|
6462
9431
|
w += v;
|
|
6463
9432
|
}
|
|
6464
9433
|
if (!(w > 0)) continue;
|
|
6465
|
-
let dy2 = (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
9451
|
+
y2 += sourceTop(source, target) * v;
|
|
6483
9452
|
w += v;
|
|
6484
9453
|
}
|
|
6485
9454
|
if (!(w > 0)) continue;
|
|
6486
|
-
let dy2 = (
|
|
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
|
-
|
|
9461
|
+
resolveCollisions6(column, beta);
|
|
6493
9462
|
}
|
|
6494
9463
|
}
|
|
6495
|
-
function
|
|
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,
|
|
9472
|
+
function resolveCollisionsTopToBottom(nodes2, y2, i, alpha) {
|
|
6504
9473
|
for (; i < nodes2.length; ++i) {
|
|
6505
9474
|
const node = nodes2[i];
|
|
6506
|
-
const dy2 = (
|
|
9475
|
+
const dy2 = (y2 - node.y0) * alpha;
|
|
6507
9476
|
if (dy2 > 1e-6) node.y0 += dy2, node.y1 += dy2;
|
|
6508
|
-
|
|
9477
|
+
y2 = node.y1 + py;
|
|
6509
9478
|
}
|
|
6510
9479
|
}
|
|
6511
|
-
function resolveCollisionsBottomToTop(nodes2,
|
|
9480
|
+
function resolveCollisionsBottomToTop(nodes2, y2, i, alpha) {
|
|
6512
9481
|
for (; i >= 0; --i) {
|
|
6513
9482
|
const node = nodes2[i];
|
|
6514
|
-
const dy2 = (node.y1 -
|
|
9483
|
+
const dy2 = (node.y1 - y2) * alpha;
|
|
6515
9484
|
if (dy2 > 1e-6) node.y0 -= dy2, node.y1 -= dy2;
|
|
6516
|
-
|
|
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
|
|
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
|
-
|
|
9510
|
+
y2 += width + py;
|
|
6542
9511
|
}
|
|
6543
9512
|
for (const { source: node, width } of target.targetLinks) {
|
|
6544
9513
|
if (node === source) break;
|
|
6545
|
-
|
|
9514
|
+
y2 -= width;
|
|
6546
9515
|
}
|
|
6547
|
-
return
|
|
9516
|
+
return y2;
|
|
6548
9517
|
}
|
|
6549
9518
|
function sourceTop(source, target) {
|
|
6550
|
-
let
|
|
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
|
-
|
|
9522
|
+
y2 += width + py;
|
|
6554
9523
|
}
|
|
6555
9524
|
for (const { target: node, width } of source.sourceLinks) {
|
|
6556
9525
|
if (node === target) break;
|
|
6557
|
-
|
|
9526
|
+
y2 -= width;
|
|
6558
9527
|
}
|
|
6559
|
-
return
|
|
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((
|
|
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 =
|
|
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((
|
|
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 =
|
|
9994
|
+
const fmt = buildD3Formatter5(valueFormat);
|
|
7026
9995
|
if (fmt) return fmt(value2);
|
|
7027
9996
|
}
|
|
7028
|
-
return
|
|
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
|
|
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
|
|
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 >
|
|
7139
|
-
|
|
10107
|
+
if (typeof val === "number" && Number.isFinite(val) && val > max4) {
|
|
10108
|
+
max4 = val;
|
|
7140
10109
|
}
|
|
7141
10110
|
}
|
|
7142
|
-
return
|
|
10111
|
+
return max4;
|
|
7143
10112
|
}
|
|
7144
10113
|
function computeColumnMin(data, key) {
|
|
7145
|
-
let
|
|
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 <
|
|
7149
|
-
|
|
10117
|
+
if (typeof val === "number" && Number.isFinite(val) && val < min4) {
|
|
10118
|
+
min4 = val;
|
|
7150
10119
|
}
|
|
7151
10120
|
}
|
|
7152
|
-
return
|
|
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
|
|
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 =
|
|
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:
|
|
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 =
|
|
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
|
|
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
|
|
7319
|
-
let
|
|
10287
|
+
let min4 = Infinity;
|
|
10288
|
+
let max4 = -Infinity;
|
|
7320
10289
|
for (const { value: value2 } of numericValues) {
|
|
7321
|
-
if (value2 <
|
|
7322
|
-
if (value2 >
|
|
10290
|
+
if (value2 < min4) min4 = value2;
|
|
10291
|
+
if (value2 > max4) max4 = value2;
|
|
7323
10292
|
}
|
|
7324
|
-
domain = [
|
|
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
|
|
7441
|
-
let
|
|
10409
|
+
let min4 = Infinity;
|
|
10410
|
+
let max4 = -Infinity;
|
|
7442
10411
|
for (const v of values) {
|
|
7443
|
-
if (v <
|
|
7444
|
-
if (v >
|
|
10412
|
+
if (v < min4) min4 = v;
|
|
10413
|
+
if (v > max4) max4 = v;
|
|
7445
10414
|
}
|
|
7446
|
-
const range2 =
|
|
7447
|
-
const normalize2 = (v) => range2 === 0 ? 0.5 : (v -
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
10730
|
+
return formatNumber5(value2);
|
|
7762
10731
|
}
|
|
7763
10732
|
}
|
|
7764
|
-
return
|
|
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,
|
|
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,
|
|
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:
|
|
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:
|
|
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,
|
|
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
|
|
8050
|
-
let
|
|
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 <
|
|
8055
|
-
if (v >
|
|
11023
|
+
if (v < min4) min4 = v;
|
|
11024
|
+
if (v > max4) max4 = v;
|
|
8056
11025
|
}
|
|
8057
11026
|
}
|
|
8058
|
-
extent2 = [
|
|
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];
|