ooxml-core 1.17.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{PptxHandler-U6EFO73T.cjs → PptxHandler-4AHDZDA5.cjs} +2 -2
- package/dist/{PptxHandler-L3JPWOBN.mjs → PptxHandler-5X4VOWAO.mjs} +1 -1
- package/dist/{PptxHandler-K7GMS2ST.mjs → PptxHandler-X6AO6LKJ.mjs} +2 -2
- package/dist/{PresentationBuilder-OK526SZ4.mjs → PresentationBuilder-LRX55PXA.mjs} +2 -2
- package/dist/{PresentationBuilder-LUR6LGHU.cjs → PresentationBuilder-MJB4LIFS.cjs} +4 -4
- package/dist/{PresentationBuilder-XC3F3OPY.mjs → PresentationBuilder-UY3S4YE2.mjs} +1 -1
- package/dist/automation/index.cjs +4710 -3016
- package/dist/automation/index.mjs +4710 -3016
- package/dist/chart/data-label-text.d.ts +70 -0
- package/dist/chart/data-label-text.d.ts.map +1 -0
- package/dist/chart/formatting-nodes.d.ts +6 -0
- package/dist/chart/formatting-nodes.d.ts.map +1 -1
- package/dist/chart/index.cjs +690 -375
- package/dist/chart/index.d.ts +1 -0
- package/dist/chart/index.d.ts.map +1 -1
- package/dist/chart/index.mjs +687 -376
- package/dist/chart/read-formatting.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-bars.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-cartesian.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-labels.d.ts +42 -0
- package/dist/chart/render/chart-svg-labels.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-radial.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-xy.d.ts.map +1 -1
- package/dist/chart/render/chart-view-labels.d.ts +16 -0
- package/dist/chart/render/chart-view-labels.d.ts.map +1 -0
- package/dist/chart/render/chart-view.d.ts +3 -0
- package/dist/chart/render/chart-view.d.ts.map +1 -1
- package/dist/chart/render/summary-from-space.d.ts +2 -2
- package/dist/chart/render/summary-from-space.d.ts.map +1 -1
- package/dist/chart/render/summary-labels.d.ts +9 -0
- package/dist/chart/render/summary-labels.d.ts.map +1 -0
- package/dist/chart/render/summary.d.ts +23 -0
- package/dist/chart/render/summary.d.ts.map +1 -1
- package/dist/{chunk-IM5LFEA2.mjs → chunk-7NWQUCGX.mjs} +1 -1
- package/dist/{chunk-UFGJNXRG.mjs → chunk-I5ZE3VLI.mjs} +1 -1
- package/dist/{chunk-A7S2NYAU.mjs → chunk-LT7RCEHY.mjs} +1 -1
- package/dist/{chunk-HLZIALC5.mjs → chunk-U7IDT6VT.mjs} +1 -1
- package/dist/{chunk-YS43OMM3.mjs → chunk-Z5Y53IZD.mjs} +4 -4
- package/dist/docx/embedded.cjs +15 -0
- package/dist/docx/embedded.mjs +15 -0
- package/dist/docx/index.cjs +1261 -656
- package/dist/docx/index.mjs +1261 -656
- package/dist/docx/layout/index.cjs +1129 -539
- package/dist/docx/layout/index.mjs +1129 -539
- package/dist/docx/load/index.cjs +15 -0
- package/dist/docx/load/index.mjs +15 -0
- package/dist/docx/ui/index.cjs +1119 -529
- package/dist/docx/ui/index.mjs +1119 -529
- package/dist/index.cjs +757 -442
- package/dist/index.mjs +757 -442
- package/dist/pptx/automation/index.cjs +7 -0
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/cli/index.cjs +7 -0
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/editor/render/slide-operations.cjs +1 -1
- package/dist/pptx/editor/render/slide-operations.mjs +1 -1
- package/dist/pptx/index.cjs +7 -0
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +145 -49
- package/dist/teams/index.mjs +145 -49
- package/dist/visio/edit-chart-object-commands.d.ts +36 -0
- package/dist/visio/edit-chart-object-commands.d.ts.map +1 -0
- package/dist/visio/edit-chart-object.d.ts +7 -0
- package/dist/visio/edit-chart-object.d.ts.map +1 -0
- package/dist/visio/edit-commands.d.ts +2 -1
- package/dist/visio/edit-commands.d.ts.map +1 -1
- package/dist/visio/edit-foreign-frame.d.ts +8 -0
- package/dist/visio/edit-foreign-frame.d.ts.map +1 -0
- package/dist/visio/edit-metadata-commands.d.ts +7 -0
- package/dist/visio/edit-metadata-commands.d.ts.map +1 -1
- package/dist/visio/edit-picture.d.ts +8 -0
- package/dist/visio/edit-picture.d.ts.map +1 -1
- package/dist/visio/edit.d.ts.map +1 -1
- package/dist/visio/emf-bitmap.d.ts +8 -0
- package/dist/visio/emf-bitmap.d.ts.map +1 -0
- package/dist/visio/index.cjs +17093 -6136
- package/dist/visio/index.d.ts +2 -0
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +17091 -6137
- package/dist/visio/model.d.ts +18 -0
- package/dist/visio/model.d.ts.map +1 -1
- package/dist/visio/prepare-embedded.d.ts +10 -0
- package/dist/visio/prepare-embedded.d.ts.map +1 -0
- package/dist/visio/prepare-images.d.ts.map +1 -1
- package/dist/visio/shapes.d.ts.map +1 -1
- package/dist/visio/sheet.d.ts +2 -1
- package/dist/visio/sheet.d.ts.map +1 -1
- package/dist/visio/ui/edit-commands.d.ts.map +1 -1
- package/dist/visio/ui/index.cjs +33320 -22884
- package/dist/visio/ui/index.mjs +33318 -22884
- package/dist/visio/ui/insert.d.ts +11 -0
- package/dist/visio/ui/insert.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +1175 -564
- package/dist/xlsx/index.mjs +1175 -564
- package/dist/xlsx/load/index.cjs +136 -50
- package/dist/xlsx/load/index.mjs +136 -50
- package/dist/xlsx/model.d.ts +5 -0
- package/dist/xlsx/model.d.ts.map +1 -1
- package/dist/xlsx/read/load.d.ts.map +1 -1
- package/dist/xlsx/read/workbook-part.d.ts +2 -0
- package/dist/xlsx/read/workbook-part.d.ts.map +1 -1
- package/dist/xlsx/ui/dialogs/grid-chart.d.ts +22 -1
- package/dist/xlsx/ui/dialogs/grid-chart.d.ts.map +1 -1
- package/dist/xlsx/ui/index.cjs +16820 -4239
- package/dist/xlsx/ui/index.mjs +16810 -4237
- package/dist/xlsx/write/workbook-part.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/visio/edit-foreign-bitmap.d.ts +0 -7
- package/dist/visio/edit-foreign-bitmap.d.ts.map +0 -1
- /package/dist/{chunk-KU3SMBFU.mjs → chunk-C363NN2C.mjs} +0 -0
- /package/dist/{chunk-UWWS6VVJ.cjs → chunk-R4BCOQHB.cjs} +0 -0
package/dist/chart/index.mjs
CHANGED
|
@@ -526,6 +526,52 @@ function formatChartNumber(value, formatCode) {
|
|
|
526
526
|
return formatChartNumberWithColor(value, formatCode)?.text;
|
|
527
527
|
}
|
|
528
528
|
|
|
529
|
+
// chart/data-label-text.ts
|
|
530
|
+
var DATA_LABEL_SEPARATOR = ", ";
|
|
531
|
+
var DATA_LABEL_CATEGORY_PERCENT_SEPARATOR = "\n";
|
|
532
|
+
var FLAG_KEYS = [
|
|
533
|
+
"showValue",
|
|
534
|
+
"showCategory",
|
|
535
|
+
"showSeriesName",
|
|
536
|
+
"showPercent",
|
|
537
|
+
"showBubbleSize"
|
|
538
|
+
];
|
|
539
|
+
function resolveDataLabelFlags(levels) {
|
|
540
|
+
const { point, series, chart } = levels;
|
|
541
|
+
const picked = {};
|
|
542
|
+
for (const key of FLAG_KEYS) picked[key] = point?.[key] ?? series?.[key] ?? chart?.[key];
|
|
543
|
+
const anyDeclared = FLAG_KEYS.some((key) => picked[key] !== void 0);
|
|
544
|
+
return {
|
|
545
|
+
showValue: anyDeclared ? picked.showValue === true : levels.siblingOwnsLabels !== true,
|
|
546
|
+
showCategory: picked.showCategory === true,
|
|
547
|
+
showSeriesName: picked.showSeriesName === true,
|
|
548
|
+
showPercent: picked.showPercent === true,
|
|
549
|
+
showBubbleSize: picked.showBubbleSize === true,
|
|
550
|
+
separator: point?.separator ?? series?.separator ?? chart?.separator ?? (picked.showCategory === true && picked.showPercent === true ? DATA_LABEL_CATEGORY_PERCENT_SEPARATOR : DATA_LABEL_SEPARATOR)
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
function composeDataLabelText(input) {
|
|
554
|
+
const { flags, value, numberFormat: numberFormat2 } = input;
|
|
555
|
+
const parts = [];
|
|
556
|
+
let valueColor;
|
|
557
|
+
if (flags.showSeriesName && input.seriesName) parts.push(input.seriesName);
|
|
558
|
+
if (flags.showCategory && input.category) parts.push(input.category);
|
|
559
|
+
if (flags.showValue) {
|
|
560
|
+
const formatted = formatChartNumberWithColor(value, numberFormat2);
|
|
561
|
+
parts.push(formatted?.text ?? (input.formatValue ?? String)(value, numberFormat2));
|
|
562
|
+
valueColor = formatted?.color;
|
|
563
|
+
}
|
|
564
|
+
if (flags.showPercent) {
|
|
565
|
+
const base = input.percentBase;
|
|
566
|
+
parts.push(base > 0 ? `${Math.round(Math.abs(value) / base * 100)}%` : "0%");
|
|
567
|
+
}
|
|
568
|
+
if (flags.showBubbleSize && input.bubbleSize !== void 0)
|
|
569
|
+
parts.push((input.formatBubbleSize ?? String)(input.bubbleSize));
|
|
570
|
+
const text3 = parts.join(flags.separator);
|
|
571
|
+
if (text3.length === 0) return void 0;
|
|
572
|
+
return { text: text3, color: parts.length === 1 && flags.showValue ? valueColor : void 0 };
|
|
573
|
+
}
|
|
574
|
+
|
|
529
575
|
// chart/auto-title.ts
|
|
530
576
|
var CHART_AUTO_TITLE = "Chart Title";
|
|
531
577
|
var CHARTEX_ONLY_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -673,10 +719,10 @@ function squarify(nodes, box) {
|
|
|
673
719
|
|
|
674
720
|
// chart/hierarchy.ts
|
|
675
721
|
function normalizeLevels(levels, pointCount) {
|
|
676
|
-
return levels.map((
|
|
722
|
+
return levels.map((level2) => {
|
|
677
723
|
let previous = "";
|
|
678
724
|
return Array.from({ length: pointCount }, (_, index) => {
|
|
679
|
-
const label =
|
|
725
|
+
const label = level2[index]?.trim() ?? "";
|
|
680
726
|
if (label) previous = label;
|
|
681
727
|
return label || previous;
|
|
682
728
|
});
|
|
@@ -834,12 +880,12 @@ function computeSunburstArcs(series, cx2, cy, maxR) {
|
|
|
834
880
|
});
|
|
835
881
|
return out;
|
|
836
882
|
}
|
|
837
|
-
function hierarchyKey(levels,
|
|
838
|
-
return levels.slice(
|
|
883
|
+
function hierarchyKey(levels, level2, index) {
|
|
884
|
+
return levels.slice(level2).map((labels) => labels[index] ?? "").join("\0");
|
|
839
885
|
}
|
|
840
886
|
function computeHierarchicalSunburstArcs(categoryLevels2, values, cx2, cy, maxR) {
|
|
841
|
-
const levels = categoryLevels2.filter((
|
|
842
|
-
const leafCount = Math.max(values.length, ...levels.map((
|
|
887
|
+
const levels = categoryLevels2.filter((level2) => level2.length > 0);
|
|
888
|
+
const leafCount = Math.max(values.length, ...levels.map((level2) => level2.length), 0);
|
|
843
889
|
if (levels.length === 0 || leafCount === 0) return [];
|
|
844
890
|
const rawWeights = Array.from({ length: leafCount }, (_, index) => Math.abs(values[index] ?? 0));
|
|
845
891
|
const weights = rawWeights.some((value) => value !== 0) ? rawWeights : rawWeights.map(() => 1);
|
|
@@ -850,15 +896,15 @@ function computeHierarchicalSunburstArcs(categoryLevels2, values, cx2, cy, maxR)
|
|
|
850
896
|
const rootLabels = levels[levels.length - 1] ?? [];
|
|
851
897
|
const rootColors = /* @__PURE__ */ new Map();
|
|
852
898
|
const out = [];
|
|
853
|
-
for (let
|
|
854
|
-
const ringIndex = levels.length - 1 -
|
|
899
|
+
for (let level2 = levels.length - 1; level2 >= 0; level2--) {
|
|
900
|
+
const ringIndex = levels.length - 1 - level2;
|
|
855
901
|
const innerRadius = ringWidth * (ringIndex + 0.5);
|
|
856
902
|
const outerRadius = ringWidth * (ringIndex + 1.5);
|
|
857
903
|
let start = 0;
|
|
858
904
|
while (start < leafCount) {
|
|
859
|
-
const key = hierarchyKey(levels,
|
|
905
|
+
const key = hierarchyKey(levels, level2, start);
|
|
860
906
|
let end = start + 1;
|
|
861
|
-
while (end < leafCount && hierarchyKey(levels,
|
|
907
|
+
while (end < leafCount && hierarchyKey(levels, level2, end) === key) end++;
|
|
862
908
|
const startAngle = -Math.PI / 2 + (prefix[start] ?? 0) / total * Math.PI * 2;
|
|
863
909
|
const endAngle = -Math.PI / 2 + (prefix[end] ?? 0) / total * Math.PI * 2;
|
|
864
910
|
const rootLabel = rootLabels[start] ?? "";
|
|
@@ -868,8 +914,8 @@ function computeHierarchicalSunburstArcs(categoryLevels2, values, cx2, cy, maxR)
|
|
|
868
914
|
colorIndex: rootColors.get(rootLabel) ?? start,
|
|
869
915
|
opacity: Math.max(0.1, 0.9 - ringIndex * 0.1),
|
|
870
916
|
level: ringIndex,
|
|
871
|
-
label: levels[
|
|
872
|
-
...
|
|
917
|
+
label: levels[level2]?.[start] ?? "",
|
|
918
|
+
...level2 === 0 && end === start + 1 ? { pointIndex: start } : {},
|
|
873
919
|
...arcLabelPlacement(cx2, cy, (innerRadius + outerRadius) / 2, startAngle, endAngle)
|
|
874
920
|
});
|
|
875
921
|
start = end;
|
|
@@ -1862,8 +1908,8 @@ function parseXml(xml, options = {}) {
|
|
|
1862
1908
|
let parsed;
|
|
1863
1909
|
try {
|
|
1864
1910
|
parsed = new DOMParser({
|
|
1865
|
-
onError: (
|
|
1866
|
-
if (
|
|
1911
|
+
onError: (level2, message) => {
|
|
1912
|
+
if (level2 !== "warning") parseError = message;
|
|
1867
1913
|
}
|
|
1868
1914
|
}).parseFromString(xml, "application/xml");
|
|
1869
1915
|
} catch (error) {
|
|
@@ -2499,6 +2545,19 @@ function readChartStyle(xml) {
|
|
|
2499
2545
|
}
|
|
2500
2546
|
|
|
2501
2547
|
// chart/formatting-nodes.ts
|
|
2548
|
+
function chartDataLabelNode(root) {
|
|
2549
|
+
const plot = first(first(root, "chart", NS.c), "plotArea", NS.c);
|
|
2550
|
+
const groups = plot ? elements(plot).filter((node) => node.localName.endsWith("Chart")) : [];
|
|
2551
|
+
const candidates = groups.flatMap((group2) => [
|
|
2552
|
+
...children(group2, "ser", NS.c).map((ser) => first(ser, "dLbls", NS.c)),
|
|
2553
|
+
first(group2, "dLbls", NS.c)
|
|
2554
|
+
]);
|
|
2555
|
+
return candidates.find(
|
|
2556
|
+
(node) => node !== void 0 && (first(node, "txPr", NS.c) !== void 0 || elements(node).some(
|
|
2557
|
+
(child2) => child2.localName.startsWith("show") && child2.getAttribute("val") === "1"
|
|
2558
|
+
))
|
|
2559
|
+
);
|
|
2560
|
+
}
|
|
2502
2561
|
function chartFormattingNodes(root) {
|
|
2503
2562
|
const chart = first(root, "chart", NS.c);
|
|
2504
2563
|
const plot = first(chart, "plotArea", NS.c);
|
|
@@ -2673,6 +2732,8 @@ function readChartFormatting(root) {
|
|
|
2673
2732
|
const entries = Object.fromEntries(
|
|
2674
2733
|
Object.entries(nodes).flatMap(([name, node]) => node ? [[name, entry2(node)]] : [])
|
|
2675
2734
|
);
|
|
2735
|
+
const labels = chartDataLabelNode(root);
|
|
2736
|
+
if (labels) entries["dataLabel"] = entry2(labels);
|
|
2676
2737
|
const builtInStyle = readBuiltInChartStyle(root);
|
|
2677
2738
|
const textBody = c(root, "txPr");
|
|
2678
2739
|
const textDefaults = textBody ? {
|
|
@@ -4431,7 +4492,7 @@ function dataSourceInner(source) {
|
|
|
4431
4492
|
case "multiLvlStrRef": {
|
|
4432
4493
|
const levels = source.levels ? elementXml(
|
|
4433
4494
|
"multiLvlStrCache",
|
|
4434
|
-
valXml("ptCount", source.levelPointCount) + source.levels.map((
|
|
4495
|
+
valXml("ptCount", source.levelPointCount) + source.levels.map((level2) => elementXml("lvl", cachePoints(level2))).join("")
|
|
4435
4496
|
) : "";
|
|
4436
4497
|
return `<c:multiLvlStrRef>${formula}${levels}</c:multiLvlStrRef>`;
|
|
4437
4498
|
}
|
|
@@ -4694,6 +4755,41 @@ function summaryAnalysis(series) {
|
|
|
4694
4755
|
};
|
|
4695
4756
|
}
|
|
4696
4757
|
|
|
4758
|
+
// chart/render/summary-labels.ts
|
|
4759
|
+
function level(options, custom) {
|
|
4760
|
+
const out = {};
|
|
4761
|
+
if (options.deleted !== void 0) out.deleted = options.deleted;
|
|
4762
|
+
if (options.showValue !== void 0) out.showValue = options.showValue;
|
|
4763
|
+
if (options.showCategoryName !== void 0) out.showCategory = options.showCategoryName;
|
|
4764
|
+
if (options.showSeriesName !== void 0) out.showSeriesName = options.showSeriesName;
|
|
4765
|
+
if (options.showPercent !== void 0) out.showPercent = options.showPercent;
|
|
4766
|
+
if (options.showBubbleSize !== void 0) out.showBubbleSize = options.showBubbleSize;
|
|
4767
|
+
if (options.separator !== void 0) out.separator = options.separator;
|
|
4768
|
+
if (options.position) out.position = options.position;
|
|
4769
|
+
if (options.numberFormat?.formatCode) out.numberFormat = options.numberFormat.formatCode;
|
|
4770
|
+
if (custom?.text !== void 0) out.text = custom.text;
|
|
4771
|
+
return out;
|
|
4772
|
+
}
|
|
4773
|
+
function shows(levels, point) {
|
|
4774
|
+
const flags = resolveDataLabelFlags({ ...levels, ...point ? { point } : {} });
|
|
4775
|
+
return point?.text !== void 0 || Object.values(flags).some((value) => value === true);
|
|
4776
|
+
}
|
|
4777
|
+
function summaryDataLabels(series, group2) {
|
|
4778
|
+
const own = series.dataLabels;
|
|
4779
|
+
if (!own && !group2) return void 0;
|
|
4780
|
+
const out = {};
|
|
4781
|
+
if (group2) out.chart = level(group2);
|
|
4782
|
+
if (own) out.series = level(own);
|
|
4783
|
+
const points = {};
|
|
4784
|
+
for (const labels of [group2, own])
|
|
4785
|
+
for (const label of labels?.labels ?? [])
|
|
4786
|
+
if (label.index !== void 0)
|
|
4787
|
+
points[label.index] = { ...points[label.index], ...level(label, label.tx) };
|
|
4788
|
+
if (Object.keys(points).length) out.points = points;
|
|
4789
|
+
if (!shows(out) && !Object.values(points).some((point) => shows(out, point))) return void 0;
|
|
4790
|
+
return out;
|
|
4791
|
+
}
|
|
4792
|
+
|
|
4697
4793
|
// chart/render/summary-from-space.ts
|
|
4698
4794
|
var solidColor = (fill) => fill?.kind === "solid" ? fill.color : void 0;
|
|
4699
4795
|
var isSolidFill = (fill) => fill?.kind === "solid" || fill?.kind === "unsupported" && fill.element === "solidFill";
|
|
@@ -4711,7 +4807,7 @@ var GROUP_TYPES = {
|
|
|
4711
4807
|
surface: "surface"
|
|
4712
4808
|
};
|
|
4713
4809
|
var GROUPINGS = /* @__PURE__ */ new Set(["clustered", "stacked", "percentStacked", "standard"]);
|
|
4714
|
-
function chartSummarySeries(source, chartType) {
|
|
4810
|
+
function chartSummarySeries(source, chartType, groupLabels) {
|
|
4715
4811
|
const categories = source.categories ?? source.xValues;
|
|
4716
4812
|
const values = source.values ?? source.yValues;
|
|
4717
4813
|
const numeric = (v) => typeof v === "number" ? v : v === "" ? null : Number.isFinite(Number(v)) ? Number(v) : null;
|
|
@@ -4719,6 +4815,7 @@ function chartSummarySeries(source, chartType) {
|
|
|
4719
4815
|
categories: chartSourceValues(categories),
|
|
4720
4816
|
values: chartSourceValues(values).map(numeric)
|
|
4721
4817
|
};
|
|
4818
|
+
if (values?.cache?.formatCode !== void 0) out.numberFormat = values.cache.formatCode;
|
|
4722
4819
|
if (source.bubbleSizes) {
|
|
4723
4820
|
out.bubbleSizes = chartSourceValues(source.bubbleSizes).map(numeric);
|
|
4724
4821
|
if (source.bubbleSizes.formula) out.bubbleSizesRef = source.bubbleSizes.formula;
|
|
@@ -4747,6 +4844,8 @@ function chartSummarySeries(source, chartType) {
|
|
|
4747
4844
|
}
|
|
4748
4845
|
if (Object.keys(points).length) out.pointColors = points;
|
|
4749
4846
|
if (Object.keys(pointFills).length) out.pointFills = pointFills;
|
|
4847
|
+
const dataLabels = summaryDataLabels(source, groupLabels);
|
|
4848
|
+
if (dataLabels) out.dataLabels = dataLabels;
|
|
4750
4849
|
Object.assign(out, summaryAnalysis(source));
|
|
4751
4850
|
return out;
|
|
4752
4851
|
}
|
|
@@ -4774,7 +4873,7 @@ function extraGroups(chartSpace, firstType) {
|
|
|
4774
4873
|
const type = group2.kind === "bar" ? "column" : group2.kind;
|
|
4775
4874
|
const entry3 = {
|
|
4776
4875
|
chartType: type,
|
|
4777
|
-
series: group2.series.map((source) => chartSummarySeries(source, type)),
|
|
4876
|
+
series: group2.series.map((source) => chartSummarySeries(source, type, group2.dataLabels)),
|
|
4778
4877
|
secondary: valueAxisId(chartSpace, group2.axisIds) !== primary
|
|
4779
4878
|
};
|
|
4780
4879
|
if (group2.grouping && GROUPINGS.has(group2.grouping))
|
|
@@ -4792,7 +4891,9 @@ function chartSummaryFromSpace(chartSpace, extras = {}) {
|
|
|
4792
4891
|
const group2 = chartSpace.plotArea.groups[0];
|
|
4793
4892
|
let chartType = group2 ? GROUP_TYPES[group2.kind] : "column";
|
|
4794
4893
|
if (chartType === "bar" && group2?.barDirection !== "bar") chartType = "column";
|
|
4795
|
-
const series = (group2?.series ?? []).map(
|
|
4894
|
+
const series = (group2?.series ?? []).map(
|
|
4895
|
+
(source) => chartSummarySeries(source, chartType, group2?.dataLabels)
|
|
4896
|
+
);
|
|
4796
4897
|
const summary = {
|
|
4797
4898
|
chartType,
|
|
4798
4899
|
series,
|
|
@@ -4858,9 +4959,9 @@ function dimension(data, kind, type) {
|
|
|
4858
4959
|
const out = { points: [] };
|
|
4859
4960
|
const formula = text(cx(element, "f"));
|
|
4860
4961
|
if (formula) out.formula = formula;
|
|
4861
|
-
const
|
|
4862
|
-
const count = Number(
|
|
4863
|
-
for (const point of
|
|
4962
|
+
const level2 = cx(element, "lvl");
|
|
4963
|
+
const count = Number(level2?.getAttribute("ptCount") ?? 0);
|
|
4964
|
+
for (const point of level2 ? children(level2, "pt", NS.cx) : []) {
|
|
4864
4965
|
const index = Number(point.getAttribute("idx") ?? out.points.length);
|
|
4865
4966
|
if (Number.isInteger(index) && index >= 0) out.points[index] = text(point);
|
|
4866
4967
|
}
|
|
@@ -4869,10 +4970,10 @@ function dimension(data, kind, type) {
|
|
|
4869
4970
|
}
|
|
4870
4971
|
function categoryLevels(data) {
|
|
4871
4972
|
const element = data ? children(data, "strDim", NS.cx).find((d) => (d.getAttribute("type") ?? "") === "cat") : void 0;
|
|
4872
|
-
return (element ? children(element, "lvl", NS.cx) : []).map((
|
|
4973
|
+
return (element ? children(element, "lvl", NS.cx) : []).map((level2) => {
|
|
4873
4974
|
const points = [];
|
|
4874
|
-
const count = Number(
|
|
4875
|
-
for (const point of children(
|
|
4975
|
+
const count = Number(level2.getAttribute("ptCount") ?? 0);
|
|
4976
|
+
for (const point of children(level2, "pt", NS.cx)) {
|
|
4876
4977
|
const index = Number(point.getAttribute("idx") ?? points.length);
|
|
4877
4978
|
if (Number.isInteger(index) && index >= 0) points[index] = text(point);
|
|
4878
4979
|
}
|
|
@@ -5043,218 +5144,6 @@ function chartBarSpacing(chart) {
|
|
|
5043
5144
|
};
|
|
5044
5145
|
}
|
|
5045
5146
|
|
|
5046
|
-
// chart/render/chart-svg-bars.ts
|
|
5047
|
-
function barLayout(model, frame) {
|
|
5048
|
-
const count = Math.max(1, model.series.length);
|
|
5049
|
-
const geometry = clusteredBarGeometry(frame.bandSize, count, chartBarSpacing(model));
|
|
5050
|
-
const barSize = geometry.singleBarWidth;
|
|
5051
|
-
const offset = (si) => model.horizontal ? geometry.clusterWidth / 2 - barSize - si * geometry.step : -geometry.clusterWidth / 2 + si * geometry.step;
|
|
5052
|
-
return { barSize, offset };
|
|
5053
|
-
}
|
|
5054
|
-
function bars(model, frame, out, values) {
|
|
5055
|
-
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
5056
|
-
const { barSize, offset: barOffset } = barLayout(model, frame);
|
|
5057
|
-
const base = frame.value(0);
|
|
5058
|
-
const pos = new Array(model.categories.length).fill(0);
|
|
5059
|
-
const neg = new Array(model.categories.length).fill(0);
|
|
5060
|
-
model.series.forEach((s, si) => {
|
|
5061
|
-
values[si]?.forEach((v, i) => {
|
|
5062
|
-
if (v === null || i >= model.categories.length) return;
|
|
5063
|
-
let from = 0;
|
|
5064
|
-
let to = v;
|
|
5065
|
-
if (stacked) {
|
|
5066
|
-
const acc = v >= 0 ? pos : neg;
|
|
5067
|
-
from = acc[i] ?? 0;
|
|
5068
|
-
to = from + v;
|
|
5069
|
-
acc[i] = to;
|
|
5070
|
-
}
|
|
5071
|
-
const a2 = stacked ? frame.value(from) : base;
|
|
5072
|
-
const b = frame.value(to);
|
|
5073
|
-
const offset = barOffset(si);
|
|
5074
|
-
const center = frame.band(i);
|
|
5075
|
-
const width = model.horizontal ? Math.abs(b - a2) : barSize;
|
|
5076
|
-
const height = model.horizontal ? barSize : Math.abs(b - a2);
|
|
5077
|
-
let color = s.pointColors?.[i] ?? s.color;
|
|
5078
|
-
const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
|
|
5079
|
-
if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
|
|
5080
|
-
const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
|
|
5081
|
-
if (baseId) {
|
|
5082
|
-
const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
|
|
5083
|
-
const def = buildChartGradientDef(id, gradient, {
|
|
5084
|
-
width: Number(n(width)),
|
|
5085
|
-
height: Number(n(height)),
|
|
5086
|
-
shape: "rect"
|
|
5087
|
-
});
|
|
5088
|
-
out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
|
|
5089
|
-
color = `url(#${id})`;
|
|
5090
|
-
}
|
|
5091
|
-
}
|
|
5092
|
-
out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
|
|
5093
|
-
if (model.horizontal)
|
|
5094
|
-
out.push(
|
|
5095
|
-
rect(Math.min(a2, b), center + offset, Math.abs(b - a2), barSize, color, s.shadowFilter)
|
|
5096
|
-
);
|
|
5097
|
-
else
|
|
5098
|
-
out.push(
|
|
5099
|
-
rect(center + offset, Math.min(a2, b), barSize, Math.abs(b - a2), color, s.shadowFilter)
|
|
5100
|
-
);
|
|
5101
|
-
out.push("</g>");
|
|
5102
|
-
});
|
|
5103
|
-
});
|
|
5104
|
-
}
|
|
5105
|
-
|
|
5106
|
-
// chart/render/chart-svg-analysis.ts
|
|
5107
|
-
var DASHES = {
|
|
5108
|
-
dot: [1, 3],
|
|
5109
|
-
dash: [4, 3],
|
|
5110
|
-
lgDash: [8, 3],
|
|
5111
|
-
dashDot: [4, 3, 1, 3],
|
|
5112
|
-
lgDashDot: [8, 3, 1, 3],
|
|
5113
|
-
lgDashDotDot: [8, 3, 1, 3, 1, 3],
|
|
5114
|
-
sysDash: [3, 1],
|
|
5115
|
-
sysDot: [1, 1],
|
|
5116
|
-
sysDashDot: [3, 1, 1, 1],
|
|
5117
|
-
sysDashDotDot: [3, 1, 1, 1, 1, 1]
|
|
5118
|
-
};
|
|
5119
|
-
var CAP = 4;
|
|
5120
|
-
function strokeAttributes(stroke) {
|
|
5121
|
-
const pattern = stroke.dash ? DASHES[stroke.dash] : void 0;
|
|
5122
|
-
const dash = pattern ? ` stroke-dasharray="${pattern.map((step) => n(step * stroke.width)).join(" ")}"` : "";
|
|
5123
|
-
return `stroke="${esc(stroke.color)}" stroke-width="${n(stroke.width)}"${dash}`;
|
|
5124
|
-
}
|
|
5125
|
-
var segment = (x1, y1, x2, y2, stroke) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" ${stroke}/>`;
|
|
5126
|
-
function trendlines(series, si, xs, ys, plane, out) {
|
|
5127
|
-
for (const trendline of series.trendlines ?? []) {
|
|
5128
|
-
const fit2 = fitChartTrendline(trendline.fit, xs, ys);
|
|
5129
|
-
if (fit2.points.length < 2) continue;
|
|
5130
|
-
const points = fit2.points.map(({ x, y }) => plane(x, y).map(n).join(",")).join(" ");
|
|
5131
|
-
out.push(
|
|
5132
|
-
`<polyline points="${points}" fill="none" ${strokeAttributes(trendline.stroke)} data-chart-part="trendline" data-chart-series="${si}"/>`
|
|
5133
|
-
);
|
|
5134
|
-
}
|
|
5135
|
-
}
|
|
5136
|
-
function errorBar(bars2, at, values, plane, out) {
|
|
5137
|
-
const stroke = strokeAttributes(bars2.stroke);
|
|
5138
|
-
for (const side of ["plus", "minus"]) {
|
|
5139
|
-
if (bars2.barType !== side && bars2.barType !== "both") continue;
|
|
5140
|
-
const amount = chartErrorBarAmount(bars2.amount, values, at.displayIndex, at.sourceIndex, side);
|
|
5141
|
-
const sign = side === "plus" ? 1 : -1;
|
|
5142
|
-
const [x1, y1] = plane(at.x, at.y);
|
|
5143
|
-
const [x2, y2] = bars2.direction === "x" ? plane(at.x + sign * amount, at.y) : plane(at.x, at.y + sign * amount);
|
|
5144
|
-
out.push(segment(x1, y1, x2, y2, stroke));
|
|
5145
|
-
if (!bars2.endCap) continue;
|
|
5146
|
-
if (x1 === x2) out.push(segment(x2 - CAP, y2, x2 + CAP, y2, stroke));
|
|
5147
|
-
else out.push(segment(x2, y2 - CAP, x2, y2 + CAP, stroke));
|
|
5148
|
-
}
|
|
5149
|
-
}
|
|
5150
|
-
function plottedPoints(series, xOf) {
|
|
5151
|
-
return series.values.flatMap((y, index) => {
|
|
5152
|
-
const x = xOf(index);
|
|
5153
|
-
return y === null || x === null ? [] : [{ x, y, index }];
|
|
5154
|
-
});
|
|
5155
|
-
}
|
|
5156
|
-
function seriesAnalysis(series, si, xOf, plane, barPlane, categoryAxis, out) {
|
|
5157
|
-
const points = plottedPoints(series, xOf);
|
|
5158
|
-
const xs = points.map((p) => p.x);
|
|
5159
|
-
const ys = points.map((p) => p.y);
|
|
5160
|
-
trendlines(series, si, xs, ys, plane, out);
|
|
5161
|
-
for (const bars2 of series.errorBars ?? []) {
|
|
5162
|
-
if (categoryAxis && bars2.direction === "x") continue;
|
|
5163
|
-
const values = bars2.direction === "x" ? xs : ys;
|
|
5164
|
-
points.forEach(
|
|
5165
|
-
(p, displayIndex) => errorBar(bars2, { x: p.x, y: p.y, displayIndex, sourceIndex: p.index }, values, barPlane, out)
|
|
5166
|
-
);
|
|
5167
|
-
}
|
|
5168
|
-
}
|
|
5169
|
-
function categoryAnalysis(model, frame, out) {
|
|
5170
|
-
if (model.grouping === "stacked" || model.grouping === "percentStacked") return;
|
|
5171
|
-
const plane = (x, y) => model.horizontal ? [frame.value(y), frame.band(x - 1)] : [frame.band(x - 1), frame.value(y)];
|
|
5172
|
-
const barred = model.type === "bar" || model.type === "column";
|
|
5173
|
-
const layout = barred ? barLayout(model, frame) : void 0;
|
|
5174
|
-
model.series.forEach((series, si) => {
|
|
5175
|
-
if (!series.trendlines && !series.errorBars) return;
|
|
5176
|
-
const shift = layout ? layout.offset(si) + layout.barSize / 2 : 0;
|
|
5177
|
-
const barPlane = (x, y) => {
|
|
5178
|
-
const [px, py] = plane(x, y);
|
|
5179
|
-
return model.horizontal ? [px, py + shift] : [px + shift, py];
|
|
5180
|
-
};
|
|
5181
|
-
seriesAnalysis(series, si, (i) => i + 1, plane, barPlane, true, out);
|
|
5182
|
-
});
|
|
5183
|
-
}
|
|
5184
|
-
function scatterAnalysis(model, px, py, out) {
|
|
5185
|
-
const plane = (x, y) => [px(x), py(y)];
|
|
5186
|
-
model.series.forEach((series, si) => {
|
|
5187
|
-
if (!series.trendlines && !series.errorBars) return;
|
|
5188
|
-
seriesAnalysis(series, si, (i) => series.xValues?.[i] ?? null, plane, plane, false, out);
|
|
5189
|
-
});
|
|
5190
|
-
}
|
|
5191
|
-
|
|
5192
|
-
// chart/render/chart-scale.ts
|
|
5193
|
-
var clean = (n2) => Number(n2.toPrecision(12));
|
|
5194
|
-
function* units(raw2) {
|
|
5195
|
-
let exp = Math.floor(Math.log10(raw2)) - 1;
|
|
5196
|
-
for (; ; ) {
|
|
5197
|
-
const base = 10 ** exp;
|
|
5198
|
-
for (const m of [1, 2, 5]) yield clean(m * base);
|
|
5199
|
-
exp++;
|
|
5200
|
-
}
|
|
5201
|
-
}
|
|
5202
|
-
function niceScale(dataMin, dataMax, options = {}) {
|
|
5203
|
-
const maxIntervals = Math.max(1, options.maxIntervals ?? 10);
|
|
5204
|
-
let lo = Number.isFinite(dataMin) ? dataMin : 0;
|
|
5205
|
-
let hi = Number.isFinite(dataMax) ? dataMax : 0;
|
|
5206
|
-
if (lo > hi) [lo, hi] = [hi, lo];
|
|
5207
|
-
if (lo === hi) {
|
|
5208
|
-
if (lo === 0) hi = 1;
|
|
5209
|
-
else if (options.noZero) {
|
|
5210
|
-
const pad = Math.abs(lo) * 0.1 || 1;
|
|
5211
|
-
lo -= pad;
|
|
5212
|
-
hi += pad;
|
|
5213
|
-
} else if (lo > 0) lo = 0;
|
|
5214
|
-
else hi = 0;
|
|
5215
|
-
}
|
|
5216
|
-
let fixedLo = false;
|
|
5217
|
-
let fixedHi = false;
|
|
5218
|
-
if (!options.noZero) {
|
|
5219
|
-
if (lo >= 0 && hi - lo >= hi / 6) {
|
|
5220
|
-
lo = 0;
|
|
5221
|
-
fixedLo = true;
|
|
5222
|
-
} else if (hi <= 0 && hi - lo >= -lo / 6) {
|
|
5223
|
-
hi = 0;
|
|
5224
|
-
fixedHi = true;
|
|
5225
|
-
}
|
|
5226
|
-
}
|
|
5227
|
-
const range = hi - lo;
|
|
5228
|
-
const top = fixedHi ? hi : hi + range * 0.05;
|
|
5229
|
-
const bottom = fixedLo ? lo : lo - range * 0.05;
|
|
5230
|
-
for (const unit of units(range / maxIntervals)) {
|
|
5231
|
-
const min = fixedLo ? lo : Math.floor(clean(bottom / unit)) * unit;
|
|
5232
|
-
const max = fixedHi ? hi : Math.ceil(clean(top / unit)) * unit;
|
|
5233
|
-
const intervals = Math.round((max - min) / unit);
|
|
5234
|
-
if (intervals <= maxIntervals && intervals > 0) {
|
|
5235
|
-
const ticks = [];
|
|
5236
|
-
for (let i = 0; i <= intervals; i++) ticks.push(clean(min + i * unit));
|
|
5237
|
-
return { min: clean(min), max: clean(max), majorUnit: unit, ticks };
|
|
5238
|
-
}
|
|
5239
|
-
}
|
|
5240
|
-
return { min: lo, max: hi, majorUnit: range, ticks: [lo, hi] };
|
|
5241
|
-
}
|
|
5242
|
-
var PERCENT_SCALE = {
|
|
5243
|
-
min: 0,
|
|
5244
|
-
max: 1,
|
|
5245
|
-
majorUnit: 0.1,
|
|
5246
|
-
ticks: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
|
|
5247
|
-
};
|
|
5248
|
-
function formatAxisValue(value, percent = false) {
|
|
5249
|
-
if (percent) return `${clean(value * 100)}%`;
|
|
5250
|
-
const v = clean(value);
|
|
5251
|
-
if (Math.abs(v) >= 1e15 || v !== 0 && Math.abs(v) < 1e-6)
|
|
5252
|
-
return v.toExponential(2).replace("e+", "E+").replace("e-", "E-");
|
|
5253
|
-
const [int = "0", frac] = String(Math.abs(v)).split(".");
|
|
5254
|
-
const grouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
5255
|
-
return `${v < 0 ? "-" : ""}${grouped}${frac ? `.${frac}` : ""}`;
|
|
5256
|
-
}
|
|
5257
|
-
|
|
5258
5147
|
// drawingml/drawing-color-css.ts
|
|
5259
5148
|
function drawingColorCss(value) {
|
|
5260
5149
|
if (!value || value.alpha === 1) return value?.hex;
|
|
@@ -5268,36 +5157,6 @@ function drawingColorCss(value) {
|
|
|
5268
5157
|
var EMU_PER_PIXEL = 9525;
|
|
5269
5158
|
var EMU_PER_POINT = 12700;
|
|
5270
5159
|
|
|
5271
|
-
// drawingml/drawing-shadow.ts
|
|
5272
|
-
function resolveDrawingShadow(effects, theme) {
|
|
5273
|
-
const node = first(effects, "outerShdw", NS.a);
|
|
5274
|
-
if (!node) return void 0;
|
|
5275
|
-
const value = (key, fallback) => Number(node.getAttribute(key) ?? fallback);
|
|
5276
|
-
if (value("sx", 1e5) !== 1e5 || value("sy", 1e5) !== 1e5 || value("kx", 0) !== 0 || value("ky", 0) !== 0)
|
|
5277
|
-
return void 0;
|
|
5278
|
-
const color = parseDrawingColorIn(node);
|
|
5279
|
-
const resolved = color && resolveDrawingColor(color, theme, { transformOrder: "document" });
|
|
5280
|
-
const blur = value("blurRad", 0) / EMU_PER_PIXEL;
|
|
5281
|
-
const distance = value("dist", 0) / EMU_PER_PIXEL;
|
|
5282
|
-
const angle = value("dir", 0) / 6e4 * Math.PI / 180;
|
|
5283
|
-
if (!resolved || ![blur, distance, angle].every(Number.isFinite) || blur < 0 || distance < 0)
|
|
5284
|
-
return void 0;
|
|
5285
|
-
return {
|
|
5286
|
-
color: resolved.hex,
|
|
5287
|
-
opacity: resolved.alpha,
|
|
5288
|
-
blur,
|
|
5289
|
-
dx: Math.cos(angle) * distance,
|
|
5290
|
-
dy: Math.sin(angle) * distance
|
|
5291
|
-
};
|
|
5292
|
-
}
|
|
5293
|
-
function resolveDrawingShadowXml(xml, theme) {
|
|
5294
|
-
return xml ? resolveDrawingShadow(parseXml(xml).documentElement, theme) : void 0;
|
|
5295
|
-
}
|
|
5296
|
-
function svgDropShadowElement(s, format) {
|
|
5297
|
-
const num = format.number;
|
|
5298
|
-
return `<feDropShadow dx="${num(s.dx)}" dy="${num(s.dy)}" stdDeviation="${num(s.blur / 2)}" flood-color="${format.color(s.color, "#000000")}" flood-opacity="${num(s.opacity)}" result="shadow"/>`;
|
|
5299
|
-
}
|
|
5300
|
-
|
|
5301
5160
|
// chart/render/theme-palette.ts
|
|
5302
5161
|
var THEME_SLOTS = [
|
|
5303
5162
|
"lt1",
|
|
@@ -5359,6 +5218,36 @@ function autoSeriesColor(theme, index) {
|
|
|
5359
5218
|
return chartPaletteSeriesColor(findChartColorPalette(10), i, i + 1, chartColorScheme(theme));
|
|
5360
5219
|
}
|
|
5361
5220
|
|
|
5221
|
+
// drawingml/drawing-shadow.ts
|
|
5222
|
+
function resolveDrawingShadow(effects, theme) {
|
|
5223
|
+
const node = first(effects, "outerShdw", NS.a);
|
|
5224
|
+
if (!node) return void 0;
|
|
5225
|
+
const value = (key, fallback) => Number(node.getAttribute(key) ?? fallback);
|
|
5226
|
+
if (value("sx", 1e5) !== 1e5 || value("sy", 1e5) !== 1e5 || value("kx", 0) !== 0 || value("ky", 0) !== 0)
|
|
5227
|
+
return void 0;
|
|
5228
|
+
const color = parseDrawingColorIn(node);
|
|
5229
|
+
const resolved = color && resolveDrawingColor(color, theme, { transformOrder: "document" });
|
|
5230
|
+
const blur = value("blurRad", 0) / EMU_PER_PIXEL;
|
|
5231
|
+
const distance = value("dist", 0) / EMU_PER_PIXEL;
|
|
5232
|
+
const angle = value("dir", 0) / 6e4 * Math.PI / 180;
|
|
5233
|
+
if (!resolved || ![blur, distance, angle].every(Number.isFinite) || blur < 0 || distance < 0)
|
|
5234
|
+
return void 0;
|
|
5235
|
+
return {
|
|
5236
|
+
color: resolved.hex,
|
|
5237
|
+
opacity: resolved.alpha,
|
|
5238
|
+
blur,
|
|
5239
|
+
dx: Math.cos(angle) * distance,
|
|
5240
|
+
dy: Math.sin(angle) * distance
|
|
5241
|
+
};
|
|
5242
|
+
}
|
|
5243
|
+
function resolveDrawingShadowXml(xml, theme) {
|
|
5244
|
+
return xml ? resolveDrawingShadow(parseXml(xml).documentElement, theme) : void 0;
|
|
5245
|
+
}
|
|
5246
|
+
function svgDropShadowElement(s, format) {
|
|
5247
|
+
const num = format.number;
|
|
5248
|
+
return `<feDropShadow dx="${num(s.dx)}" dy="${num(s.dy)}" stdDeviation="${num(s.blur / 2)}" flood-color="${format.color(s.color, "#000000")}" flood-opacity="${num(s.opacity)}" result="shadow"/>`;
|
|
5249
|
+
}
|
|
5250
|
+
|
|
5362
5251
|
// chart/text-inheritance.ts
|
|
5363
5252
|
var TEXT_KEYS = [
|
|
5364
5253
|
"fontSize",
|
|
@@ -5447,6 +5336,444 @@ function chartAppearance(chart, theme) {
|
|
|
5447
5336
|
return out;
|
|
5448
5337
|
}
|
|
5449
5338
|
|
|
5339
|
+
// text/css-font-family.ts
|
|
5340
|
+
var FALLBACKS = {
|
|
5341
|
+
calibri: '"Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
5342
|
+
"calibri light": '"Calibri Light", "Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
5343
|
+
cambria: '"Cambria", "Caladea", Georgia, serif',
|
|
5344
|
+
arial: 'Arial, "Liberation Sans", Helvetica, sans-serif',
|
|
5345
|
+
"times new roman": '"Times New Roman", "Liberation Serif", Times, serif',
|
|
5346
|
+
"courier new": '"Courier New", "Liberation Mono", monospace',
|
|
5347
|
+
aptos: '"Aptos", "Calibri", "Carlito", "Segoe UI", sans-serif'
|
|
5348
|
+
};
|
|
5349
|
+
function cssFontFamily(name) {
|
|
5350
|
+
const known = FALLBACKS[name.toLowerCase()];
|
|
5351
|
+
if (known) return known;
|
|
5352
|
+
const quoted = `"${name.replace(/["\\]/g, "")}"`;
|
|
5353
|
+
return `${quoted}, "Calibri", "Carlito", "Segoe UI", sans-serif`;
|
|
5354
|
+
}
|
|
5355
|
+
|
|
5356
|
+
// chart/render/chart-svg-appearance.ts
|
|
5357
|
+
var nextPaintId = 0;
|
|
5358
|
+
function chartGradientPaint(model, width = 1024, height = 768) {
|
|
5359
|
+
const prefix = `xlsx-chart-${++nextPaintId}`;
|
|
5360
|
+
const appearance = { ...model.appearance };
|
|
5361
|
+
const defs = [];
|
|
5362
|
+
const shadowPaint = (shadow, suffix) => {
|
|
5363
|
+
const id = `${prefix}-${suffix}`;
|
|
5364
|
+
const pad = Math.max(4, shadow.blur * 3 + Math.abs(shadow.dx) + Math.abs(shadow.dy));
|
|
5365
|
+
defs.push(
|
|
5366
|
+
`<filter id="${id}" filterUnits="userSpaceOnUse" x="${n(-pad)}" y="${n(-pad)}" width="${n(width + pad * 2)}" height="${n(height + pad * 2)}" color-interpolation-filters="sRGB">${svgDropShadowElement(shadow, { number: n, color: (value) => esc(value) })}</filter>`
|
|
5367
|
+
);
|
|
5368
|
+
return `url(#${id})`;
|
|
5369
|
+
};
|
|
5370
|
+
for (const [part, entry3] of Object.entries(appearance)) {
|
|
5371
|
+
if (entry3?.textShadow)
|
|
5372
|
+
appearance[part] = {
|
|
5373
|
+
...entry3,
|
|
5374
|
+
textShadowFilter: shadowPaint(entry3.textShadow, `${part}-text-shadow`)
|
|
5375
|
+
};
|
|
5376
|
+
}
|
|
5377
|
+
const paint2 = (gradient, suffix, bounds) => {
|
|
5378
|
+
const def = buildChartGradientDef(`${prefix}-${suffix}`, gradient, bounds);
|
|
5379
|
+
defs.push(chartGradientMarkup(def));
|
|
5380
|
+
return `url(#${def.id})`;
|
|
5381
|
+
};
|
|
5382
|
+
for (const part of ["chartArea", "plotArea"]) {
|
|
5383
|
+
const entry3 = appearance[part];
|
|
5384
|
+
if (!entry3?.gradient) continue;
|
|
5385
|
+
if (part === "plotArea" && ["circle", "shape"].includes(entry3.gradient.path ?? "")) continue;
|
|
5386
|
+
appearance[part] = {
|
|
5387
|
+
...entry3,
|
|
5388
|
+
fillColor: paint2(entry3.gradient, part, { width, height, shape: "rect" })
|
|
5389
|
+
};
|
|
5390
|
+
}
|
|
5391
|
+
const series = model.series.map((source, index) => {
|
|
5392
|
+
const view = { ...source };
|
|
5393
|
+
if (source.shadow) view.shadowFilter = shadowPaint(source.shadow, `s${index}-shadow`);
|
|
5394
|
+
const bounds = model.type === "bar" || model.type === "column" ? { width: 1, height: 1, shape: "rect" } : void 0;
|
|
5395
|
+
if (source.gradient) view.color = paint2(source.gradient, `s${index}`, bounds);
|
|
5396
|
+
if (source.pointGradients) {
|
|
5397
|
+
view.pointColors = [...source.pointColors ?? []];
|
|
5398
|
+
for (const [key, gradient] of Object.entries(source.pointGradients))
|
|
5399
|
+
view.pointColors[Number(key)] = paint2(gradient, `s${index}-p${key}`, bounds);
|
|
5400
|
+
}
|
|
5401
|
+
return view;
|
|
5402
|
+
});
|
|
5403
|
+
return defs.length ? { model: { ...model, appearance, series }, defs: `<defs>${defs.join("")}</defs>` } : { model, defs: "" };
|
|
5404
|
+
}
|
|
5405
|
+
function chartTextAttributes(model, part, fallbackSize = FONT_SIZE) {
|
|
5406
|
+
const entry3 = model.appearance?.[part];
|
|
5407
|
+
return {
|
|
5408
|
+
size: entry3?.fontSize === void 0 ? fallbackSize : chartPointsToPixels(entry3.fontSize),
|
|
5409
|
+
...entry3?.color === void 0 ? {} : { fill: entry3.color },
|
|
5410
|
+
...entry3?.bold === void 0 ? {} : { weight: entry3.bold ? "bold" : "normal" },
|
|
5411
|
+
...entry3?.italic === void 0 ? {} : { italic: entry3.italic },
|
|
5412
|
+
...entry3?.underline === void 0 ? {} : { underline: entry3.underline },
|
|
5413
|
+
...entry3?.typeface === void 0 ? {} : { family: cssFontFamily(entry3.typeface) },
|
|
5414
|
+
...entry3?.textShadowFilter === void 0 ? {} : { filter: entry3.textShadowFilter }
|
|
5415
|
+
};
|
|
5416
|
+
}
|
|
5417
|
+
function chartStroke(model, part) {
|
|
5418
|
+
const entry3 = model.appearance?.[part];
|
|
5419
|
+
return {
|
|
5420
|
+
color: entry3?.axisVisible === false ? "none" : entry3?.lineColor ?? (part === "gridlineMajor" ? GRID_COLOR : AXIS_COLOR),
|
|
5421
|
+
width: entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth)
|
|
5422
|
+
};
|
|
5423
|
+
}
|
|
5424
|
+
function chartAreaRect(model, part, area) {
|
|
5425
|
+
if (area.w <= 0 || area.h <= 0) return "";
|
|
5426
|
+
const entry3 = model.appearance?.[part];
|
|
5427
|
+
let fill = entry3?.fillColor ?? (part === "chartArea" ? "#FFFFFF" : "none");
|
|
5428
|
+
let defs = "";
|
|
5429
|
+
if (part !== "chartArea" && entry3?.gradient && (part !== "plotArea" || ["circle", "shape"].includes(entry3.gradient.path ?? ""))) {
|
|
5430
|
+
const def = buildChartGradientDef(`xlsx-chart-${++nextPaintId}-${part}`, entry3.gradient, {
|
|
5431
|
+
width: area.w,
|
|
5432
|
+
height: area.h,
|
|
5433
|
+
shape: "rect"
|
|
5434
|
+
});
|
|
5435
|
+
defs = `<defs>${chartGradientMarkup(def)}</defs>`;
|
|
5436
|
+
fill = `url(#${def.id})`;
|
|
5437
|
+
}
|
|
5438
|
+
const stroke = entry3?.lineColor ?? "none";
|
|
5439
|
+
if (fill === "none" && stroke === "none") return "";
|
|
5440
|
+
const width = entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth);
|
|
5441
|
+
return `${defs}<rect x="${n(area.x)}" y="${n(area.y)}" width="${n(area.w)}" height="${n(area.h)}" fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${n(width)}" data-chart-part="${part}"/>`;
|
|
5442
|
+
}
|
|
5443
|
+
|
|
5444
|
+
// chart/render/chart-svg-labels.ts
|
|
5445
|
+
var GAP = 3;
|
|
5446
|
+
var LINE = 1.2;
|
|
5447
|
+
var NAMED_COLORS = /^(black|blue|cyan|green|magenta|red|white|yellow)$/iu;
|
|
5448
|
+
function measure(model, label) {
|
|
5449
|
+
const attrs = chartTextAttributes(model, "dataLabel", 10);
|
|
5450
|
+
const size = attrs.size ?? 10;
|
|
5451
|
+
const lines = label.text.split("\n");
|
|
5452
|
+
return {
|
|
5453
|
+
lines,
|
|
5454
|
+
size,
|
|
5455
|
+
w: Math.max(...lines.map((l) => textWidth(l, size))),
|
|
5456
|
+
h: lines.length * size * LINE,
|
|
5457
|
+
attrs
|
|
5458
|
+
};
|
|
5459
|
+
}
|
|
5460
|
+
function draw(m, label, x, y, anchor, out) {
|
|
5461
|
+
const fill = label.color && NAMED_COLORS.test(label.color) ? label.color.toLowerCase() : void 0;
|
|
5462
|
+
m.lines.forEach((line2, k) => {
|
|
5463
|
+
const lineY = y - m.h / 2 + (k + 0.5) * m.size * LINE + m.size * 0.35;
|
|
5464
|
+
out.push(text2(x, lineY, line2, { ...m.attrs, ...fill ? { fill } : {}, anchor }));
|
|
5465
|
+
});
|
|
5466
|
+
}
|
|
5467
|
+
function barLabels(model, marks, out) {
|
|
5468
|
+
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
5469
|
+
for (const mark of marks) {
|
|
5470
|
+
const label = mark.series.labels?.[mark.index];
|
|
5471
|
+
if (!label) continue;
|
|
5472
|
+
const m = measure(model, label);
|
|
5473
|
+
let position = label.position ?? (stacked ? "ctr" : "outEnd");
|
|
5474
|
+
if (stacked && position === "outEnd") position = "ctr";
|
|
5475
|
+
const cx2 = mark.x + mark.w / 2;
|
|
5476
|
+
const cy = mark.y + mark.h / 2;
|
|
5477
|
+
if (model.horizontal) {
|
|
5478
|
+
const end = mark.negative ? mark.x : mark.x + mark.w;
|
|
5479
|
+
const base = mark.negative ? mark.x + mark.w : mark.x;
|
|
5480
|
+
const dir2 = mark.negative ? -1 : 1;
|
|
5481
|
+
const side = (at, outward) => [
|
|
5482
|
+
at + (outward ? dir2 : -dir2) * GAP,
|
|
5483
|
+
(outward ? dir2 : -dir2) > 0 ? "start" : "end"
|
|
5484
|
+
];
|
|
5485
|
+
const [x, anchor] = position === "ctr" ? [cx2, "middle"] : position === "inEnd" ? side(end, false) : position === "inBase" ? side(base, true) : side(end, true);
|
|
5486
|
+
draw(m, label, x, cy, anchor, out);
|
|
5487
|
+
continue;
|
|
5488
|
+
}
|
|
5489
|
+
const top = mark.negative ? mark.y + mark.h : mark.y;
|
|
5490
|
+
const bottom = mark.negative ? mark.y : mark.y + mark.h;
|
|
5491
|
+
const dir = mark.negative ? 1 : -1;
|
|
5492
|
+
const y = position === "ctr" ? cy : position === "inEnd" ? top - dir * (GAP + m.h / 2) : position === "inBase" ? bottom + dir * (GAP + m.h / 2) : top + dir * (GAP + m.h / 2);
|
|
5493
|
+
draw(m, label, cx2, y, "middle", out);
|
|
5494
|
+
}
|
|
5495
|
+
}
|
|
5496
|
+
function pointLabels(model, marks, out) {
|
|
5497
|
+
for (const mark of marks) {
|
|
5498
|
+
const label = mark.series.labels?.[mark.index];
|
|
5499
|
+
if (!label) continue;
|
|
5500
|
+
const m = measure(model, label);
|
|
5501
|
+
const reach = mark.radius + GAP;
|
|
5502
|
+
switch (model.type === "area" ? "ctr" : label.position ?? "r") {
|
|
5503
|
+
case "ctr":
|
|
5504
|
+
draw(m, label, mark.x, mark.y, "middle", out);
|
|
5505
|
+
break;
|
|
5506
|
+
case "t":
|
|
5507
|
+
draw(m, label, mark.x, mark.y - reach - m.h / 2, "middle", out);
|
|
5508
|
+
break;
|
|
5509
|
+
case "b":
|
|
5510
|
+
draw(m, label, mark.x, mark.y + reach + m.h / 2, "middle", out);
|
|
5511
|
+
break;
|
|
5512
|
+
case "l":
|
|
5513
|
+
draw(m, label, mark.x - reach, mark.y, "end", out);
|
|
5514
|
+
break;
|
|
5515
|
+
default:
|
|
5516
|
+
draw(m, label, mark.x + reach, mark.y, "start", out);
|
|
5517
|
+
}
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
function sliceLabels(model, marks, out) {
|
|
5521
|
+
for (const mark of marks) {
|
|
5522
|
+
const label = mark.series.labels?.[mark.index];
|
|
5523
|
+
if (!label) continue;
|
|
5524
|
+
const m = measure(model, label);
|
|
5525
|
+
const mid = (mark.start + mark.end) / 2;
|
|
5526
|
+
const ux = Math.sin(mid);
|
|
5527
|
+
const uy = -Math.cos(mid);
|
|
5528
|
+
const place = (radius) => [
|
|
5529
|
+
mark.cx + radius * ux,
|
|
5530
|
+
mark.cy + radius * uy
|
|
5531
|
+
];
|
|
5532
|
+
const position = model.type === "doughnut" ? "ctr" : label.position ?? "bestFit";
|
|
5533
|
+
let x;
|
|
5534
|
+
let y;
|
|
5535
|
+
if (position === "ctr") [x, y] = place(mark.inner + (mark.outer - mark.inner) / 2);
|
|
5536
|
+
else if (position === "inEnd") {
|
|
5537
|
+
const extent = Math.abs(ux) * m.w / 2 + Math.abs(uy) * m.h / 2;
|
|
5538
|
+
[x, y] = place(Math.max(0, mark.outer - GAP - extent));
|
|
5539
|
+
} else if (position === "outEnd") {
|
|
5540
|
+
const extent = Math.abs(ux) * m.w / 2 + Math.abs(uy) * m.h / 2;
|
|
5541
|
+
[x, y] = place(mark.outer + GAP + extent);
|
|
5542
|
+
} else {
|
|
5543
|
+
const placed = placeBestFitLabel(
|
|
5544
|
+
{
|
|
5545
|
+
cx: mark.cx,
|
|
5546
|
+
cy: mark.cy,
|
|
5547
|
+
outerR: mark.outer,
|
|
5548
|
+
startAngle: mark.start - Math.PI / 2,
|
|
5549
|
+
endAngle: mark.end - Math.PI / 2
|
|
5550
|
+
},
|
|
5551
|
+
m.w,
|
|
5552
|
+
m.h
|
|
5553
|
+
);
|
|
5554
|
+
x = placed.x;
|
|
5555
|
+
y = placed.y;
|
|
5556
|
+
}
|
|
5557
|
+
draw(m, label, x, y, "middle", out);
|
|
5558
|
+
}
|
|
5559
|
+
}
|
|
5560
|
+
function hasOutsideLabels(model) {
|
|
5561
|
+
return model.series.some(
|
|
5562
|
+
(s) => s.labels?.some(
|
|
5563
|
+
(l) => l !== void 0 && ["bestFit", "outEnd"].includes(l.position ?? "bestFit")
|
|
5564
|
+
)
|
|
5565
|
+
);
|
|
5566
|
+
}
|
|
5567
|
+
|
|
5568
|
+
// chart/render/chart-svg-bars.ts
|
|
5569
|
+
function barLayout(model, frame) {
|
|
5570
|
+
const count = Math.max(1, model.series.length);
|
|
5571
|
+
const geometry = clusteredBarGeometry(frame.bandSize, count, chartBarSpacing(model));
|
|
5572
|
+
const barSize = geometry.singleBarWidth;
|
|
5573
|
+
const offset = (si) => model.horizontal ? geometry.clusterWidth / 2 - barSize - si * geometry.step : -geometry.clusterWidth / 2 + si * geometry.step;
|
|
5574
|
+
return { barSize, offset };
|
|
5575
|
+
}
|
|
5576
|
+
function bars(model, frame, out, values) {
|
|
5577
|
+
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
5578
|
+
const { barSize, offset: barOffset } = barLayout(model, frame);
|
|
5579
|
+
const base = frame.value(0);
|
|
5580
|
+
const pos = new Array(model.categories.length).fill(0);
|
|
5581
|
+
const neg = new Array(model.categories.length).fill(0);
|
|
5582
|
+
const marks = [];
|
|
5583
|
+
model.series.forEach((s, si) => {
|
|
5584
|
+
values[si]?.forEach((v, i) => {
|
|
5585
|
+
if (v === null || i >= model.categories.length) return;
|
|
5586
|
+
let from = 0;
|
|
5587
|
+
let to = v;
|
|
5588
|
+
if (stacked) {
|
|
5589
|
+
const acc = v >= 0 ? pos : neg;
|
|
5590
|
+
from = acc[i] ?? 0;
|
|
5591
|
+
to = from + v;
|
|
5592
|
+
acc[i] = to;
|
|
5593
|
+
}
|
|
5594
|
+
const a2 = stacked ? frame.value(from) : base;
|
|
5595
|
+
const b = frame.value(to);
|
|
5596
|
+
const offset = barOffset(si);
|
|
5597
|
+
const center = frame.band(i);
|
|
5598
|
+
const width = model.horizontal ? Math.abs(b - a2) : barSize;
|
|
5599
|
+
const height = model.horizontal ? barSize : Math.abs(b - a2);
|
|
5600
|
+
let color = s.pointColors?.[i] ?? s.color;
|
|
5601
|
+
const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
|
|
5602
|
+
if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
|
|
5603
|
+
const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
|
|
5604
|
+
if (baseId) {
|
|
5605
|
+
const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
|
|
5606
|
+
const def = buildChartGradientDef(id, gradient, {
|
|
5607
|
+
width: Number(n(width)),
|
|
5608
|
+
height: Number(n(height)),
|
|
5609
|
+
shape: "rect"
|
|
5610
|
+
});
|
|
5611
|
+
out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
|
|
5612
|
+
color = `url(#${id})`;
|
|
5613
|
+
}
|
|
5614
|
+
}
|
|
5615
|
+
out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
|
|
5616
|
+
const box = model.horizontal ? { x: Math.min(a2, b), y: center + offset, w: Math.abs(b - a2), h: barSize } : { x: center + offset, y: Math.min(a2, b), w: barSize, h: Math.abs(b - a2) };
|
|
5617
|
+
out.push(rect(box.x, box.y, box.w, box.h, color, s.shadowFilter));
|
|
5618
|
+
out.push("</g>");
|
|
5619
|
+
marks.push({ series: s, index: i, ...box, negative: v < 0 });
|
|
5620
|
+
});
|
|
5621
|
+
});
|
|
5622
|
+
barLabels(model, marks, out);
|
|
5623
|
+
}
|
|
5624
|
+
|
|
5625
|
+
// chart/render/chart-svg-analysis.ts
|
|
5626
|
+
var DASHES = {
|
|
5627
|
+
dot: [1, 3],
|
|
5628
|
+
dash: [4, 3],
|
|
5629
|
+
lgDash: [8, 3],
|
|
5630
|
+
dashDot: [4, 3, 1, 3],
|
|
5631
|
+
lgDashDot: [8, 3, 1, 3],
|
|
5632
|
+
lgDashDotDot: [8, 3, 1, 3, 1, 3],
|
|
5633
|
+
sysDash: [3, 1],
|
|
5634
|
+
sysDot: [1, 1],
|
|
5635
|
+
sysDashDot: [3, 1, 1, 1],
|
|
5636
|
+
sysDashDotDot: [3, 1, 1, 1, 1, 1]
|
|
5637
|
+
};
|
|
5638
|
+
var CAP = 4;
|
|
5639
|
+
function strokeAttributes(stroke) {
|
|
5640
|
+
const pattern = stroke.dash ? DASHES[stroke.dash] : void 0;
|
|
5641
|
+
const dash = pattern ? ` stroke-dasharray="${pattern.map((step) => n(step * stroke.width)).join(" ")}"` : "";
|
|
5642
|
+
return `stroke="${esc(stroke.color)}" stroke-width="${n(stroke.width)}"${dash}`;
|
|
5643
|
+
}
|
|
5644
|
+
var segment = (x1, y1, x2, y2, stroke) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" ${stroke}/>`;
|
|
5645
|
+
function trendlines(series, si, xs, ys, plane, out) {
|
|
5646
|
+
for (const trendline of series.trendlines ?? []) {
|
|
5647
|
+
const fit2 = fitChartTrendline(trendline.fit, xs, ys);
|
|
5648
|
+
if (fit2.points.length < 2) continue;
|
|
5649
|
+
const points = fit2.points.map(({ x, y }) => plane(x, y).map(n).join(",")).join(" ");
|
|
5650
|
+
out.push(
|
|
5651
|
+
`<polyline points="${points}" fill="none" ${strokeAttributes(trendline.stroke)} data-chart-part="trendline" data-chart-series="${si}"/>`
|
|
5652
|
+
);
|
|
5653
|
+
}
|
|
5654
|
+
}
|
|
5655
|
+
function errorBar(bars2, at, values, plane, out) {
|
|
5656
|
+
const stroke = strokeAttributes(bars2.stroke);
|
|
5657
|
+
for (const side of ["plus", "minus"]) {
|
|
5658
|
+
if (bars2.barType !== side && bars2.barType !== "both") continue;
|
|
5659
|
+
const amount = chartErrorBarAmount(bars2.amount, values, at.displayIndex, at.sourceIndex, side);
|
|
5660
|
+
const sign = side === "plus" ? 1 : -1;
|
|
5661
|
+
const [x1, y1] = plane(at.x, at.y);
|
|
5662
|
+
const [x2, y2] = bars2.direction === "x" ? plane(at.x + sign * amount, at.y) : plane(at.x, at.y + sign * amount);
|
|
5663
|
+
out.push(segment(x1, y1, x2, y2, stroke));
|
|
5664
|
+
if (!bars2.endCap) continue;
|
|
5665
|
+
if (x1 === x2) out.push(segment(x2 - CAP, y2, x2 + CAP, y2, stroke));
|
|
5666
|
+
else out.push(segment(x2, y2 - CAP, x2, y2 + CAP, stroke));
|
|
5667
|
+
}
|
|
5668
|
+
}
|
|
5669
|
+
function plottedPoints(series, xOf) {
|
|
5670
|
+
return series.values.flatMap((y, index) => {
|
|
5671
|
+
const x = xOf(index);
|
|
5672
|
+
return y === null || x === null ? [] : [{ x, y, index }];
|
|
5673
|
+
});
|
|
5674
|
+
}
|
|
5675
|
+
function seriesAnalysis(series, si, xOf, plane, barPlane, categoryAxis, out) {
|
|
5676
|
+
const points = plottedPoints(series, xOf);
|
|
5677
|
+
const xs = points.map((p) => p.x);
|
|
5678
|
+
const ys = points.map((p) => p.y);
|
|
5679
|
+
trendlines(series, si, xs, ys, plane, out);
|
|
5680
|
+
for (const bars2 of series.errorBars ?? []) {
|
|
5681
|
+
if (categoryAxis && bars2.direction === "x") continue;
|
|
5682
|
+
const values = bars2.direction === "x" ? xs : ys;
|
|
5683
|
+
points.forEach(
|
|
5684
|
+
(p, displayIndex) => errorBar(bars2, { x: p.x, y: p.y, displayIndex, sourceIndex: p.index }, values, barPlane, out)
|
|
5685
|
+
);
|
|
5686
|
+
}
|
|
5687
|
+
}
|
|
5688
|
+
function categoryAnalysis(model, frame, out) {
|
|
5689
|
+
if (model.grouping === "stacked" || model.grouping === "percentStacked") return;
|
|
5690
|
+
const plane = (x, y) => model.horizontal ? [frame.value(y), frame.band(x - 1)] : [frame.band(x - 1), frame.value(y)];
|
|
5691
|
+
const barred = model.type === "bar" || model.type === "column";
|
|
5692
|
+
const layout = barred ? barLayout(model, frame) : void 0;
|
|
5693
|
+
model.series.forEach((series, si) => {
|
|
5694
|
+
if (!series.trendlines && !series.errorBars) return;
|
|
5695
|
+
const shift = layout ? layout.offset(si) + layout.barSize / 2 : 0;
|
|
5696
|
+
const barPlane = (x, y) => {
|
|
5697
|
+
const [px, py] = plane(x, y);
|
|
5698
|
+
return model.horizontal ? [px, py + shift] : [px + shift, py];
|
|
5699
|
+
};
|
|
5700
|
+
seriesAnalysis(series, si, (i) => i + 1, plane, barPlane, true, out);
|
|
5701
|
+
});
|
|
5702
|
+
}
|
|
5703
|
+
function scatterAnalysis(model, px, py, out) {
|
|
5704
|
+
const plane = (x, y) => [px(x), py(y)];
|
|
5705
|
+
model.series.forEach((series, si) => {
|
|
5706
|
+
if (!series.trendlines && !series.errorBars) return;
|
|
5707
|
+
seriesAnalysis(series, si, (i) => series.xValues?.[i] ?? null, plane, plane, false, out);
|
|
5708
|
+
});
|
|
5709
|
+
}
|
|
5710
|
+
|
|
5711
|
+
// chart/render/chart-scale.ts
|
|
5712
|
+
var clean = (n2) => Number(n2.toPrecision(12));
|
|
5713
|
+
function* units(raw2) {
|
|
5714
|
+
let exp = Math.floor(Math.log10(raw2)) - 1;
|
|
5715
|
+
for (; ; ) {
|
|
5716
|
+
const base = 10 ** exp;
|
|
5717
|
+
for (const m of [1, 2, 5]) yield clean(m * base);
|
|
5718
|
+
exp++;
|
|
5719
|
+
}
|
|
5720
|
+
}
|
|
5721
|
+
function niceScale(dataMin, dataMax, options = {}) {
|
|
5722
|
+
const maxIntervals = Math.max(1, options.maxIntervals ?? 10);
|
|
5723
|
+
let lo = Number.isFinite(dataMin) ? dataMin : 0;
|
|
5724
|
+
let hi = Number.isFinite(dataMax) ? dataMax : 0;
|
|
5725
|
+
if (lo > hi) [lo, hi] = [hi, lo];
|
|
5726
|
+
if (lo === hi) {
|
|
5727
|
+
if (lo === 0) hi = 1;
|
|
5728
|
+
else if (options.noZero) {
|
|
5729
|
+
const pad = Math.abs(lo) * 0.1 || 1;
|
|
5730
|
+
lo -= pad;
|
|
5731
|
+
hi += pad;
|
|
5732
|
+
} else if (lo > 0) lo = 0;
|
|
5733
|
+
else hi = 0;
|
|
5734
|
+
}
|
|
5735
|
+
let fixedLo = false;
|
|
5736
|
+
let fixedHi = false;
|
|
5737
|
+
if (!options.noZero) {
|
|
5738
|
+
if (lo >= 0 && hi - lo >= hi / 6) {
|
|
5739
|
+
lo = 0;
|
|
5740
|
+
fixedLo = true;
|
|
5741
|
+
} else if (hi <= 0 && hi - lo >= -lo / 6) {
|
|
5742
|
+
hi = 0;
|
|
5743
|
+
fixedHi = true;
|
|
5744
|
+
}
|
|
5745
|
+
}
|
|
5746
|
+
const range = hi - lo;
|
|
5747
|
+
const top = fixedHi ? hi : hi + range * 0.05;
|
|
5748
|
+
const bottom = fixedLo ? lo : lo - range * 0.05;
|
|
5749
|
+
for (const unit of units(range / maxIntervals)) {
|
|
5750
|
+
const min = fixedLo ? lo : Math.floor(clean(bottom / unit)) * unit;
|
|
5751
|
+
const max = fixedHi ? hi : Math.ceil(clean(top / unit)) * unit;
|
|
5752
|
+
const intervals = Math.round((max - min) / unit);
|
|
5753
|
+
if (intervals <= maxIntervals && intervals > 0) {
|
|
5754
|
+
const ticks = [];
|
|
5755
|
+
for (let i = 0; i <= intervals; i++) ticks.push(clean(min + i * unit));
|
|
5756
|
+
return { min: clean(min), max: clean(max), majorUnit: unit, ticks };
|
|
5757
|
+
}
|
|
5758
|
+
}
|
|
5759
|
+
return { min: lo, max: hi, majorUnit: range, ticks: [lo, hi] };
|
|
5760
|
+
}
|
|
5761
|
+
var PERCENT_SCALE = {
|
|
5762
|
+
min: 0,
|
|
5763
|
+
max: 1,
|
|
5764
|
+
majorUnit: 0.1,
|
|
5765
|
+
ticks: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
|
|
5766
|
+
};
|
|
5767
|
+
function formatAxisValue(value, percent = false) {
|
|
5768
|
+
if (percent) return `${clean(value * 100)}%`;
|
|
5769
|
+
const v = clean(value);
|
|
5770
|
+
if (Math.abs(v) >= 1e15 || v !== 0 && Math.abs(v) < 1e-6)
|
|
5771
|
+
return v.toExponential(2).replace("e+", "E+").replace("e-", "E-");
|
|
5772
|
+
const [int = "0", frac] = String(Math.abs(v)).split(".");
|
|
5773
|
+
const grouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
5774
|
+
return `${v < 0 ? "-" : ""}${grouped}${frac ? `.${frac}` : ""}`;
|
|
5775
|
+
}
|
|
5776
|
+
|
|
5450
5777
|
// chart/render/chart-view-analysis.ts
|
|
5451
5778
|
function strokeOf(line2, fallback, resolve) {
|
|
5452
5779
|
if (line2?.fill?.kind === "none") return void 0;
|
|
@@ -5703,6 +6030,64 @@ function chartTitleText(chart, theme) {
|
|
|
5703
6030
|
};
|
|
5704
6031
|
}
|
|
5705
6032
|
|
|
6033
|
+
// chart/render/chart-view-labels.ts
|
|
6034
|
+
function labelsOf(source, view, categories, numberFormat2) {
|
|
6035
|
+
const { chart, series, points } = source;
|
|
6036
|
+
if ((series?.deleted ?? chart?.deleted) === true) return void 0;
|
|
6037
|
+
const percentBase = view.values.reduce(
|
|
6038
|
+
(sum, v) => sum + (v === null ? 0 : Math.abs(v)),
|
|
6039
|
+
0
|
|
6040
|
+
);
|
|
6041
|
+
const out = [];
|
|
6042
|
+
let any = false;
|
|
6043
|
+
view.values.forEach((value, i) => {
|
|
6044
|
+
const point = points?.[i];
|
|
6045
|
+
if (value === null || point?.deleted === true) return;
|
|
6046
|
+
const position = point?.position ?? series?.position ?? chart?.position;
|
|
6047
|
+
const x = view.xValues?.[i];
|
|
6048
|
+
const category = x === void 0 || x === null ? categories[i] : formatAxisValue(x);
|
|
6049
|
+
let built;
|
|
6050
|
+
if (point?.text !== void 0) built = { text: point.text };
|
|
6051
|
+
else {
|
|
6052
|
+
const flags = resolveDataLabelFlags({
|
|
6053
|
+
...point ? { point } : {},
|
|
6054
|
+
...series ? { series } : {},
|
|
6055
|
+
...chart ? { chart } : {}
|
|
6056
|
+
});
|
|
6057
|
+
built = composeDataLabelText({
|
|
6058
|
+
flags,
|
|
6059
|
+
seriesName: view.name,
|
|
6060
|
+
category,
|
|
6061
|
+
value,
|
|
6062
|
+
numberFormat: point?.numberFormat ?? series?.numberFormat ?? chart?.numberFormat ?? numberFormat2,
|
|
6063
|
+
percentBase,
|
|
6064
|
+
bubbleSize: view.sizes?.[i] ?? void 0,
|
|
6065
|
+
formatValue: (v) => formatAxisValue(v),
|
|
6066
|
+
formatBubbleSize: (size) => formatAxisValue(size)
|
|
6067
|
+
});
|
|
6068
|
+
}
|
|
6069
|
+
if (!built) return;
|
|
6070
|
+
any = true;
|
|
6071
|
+
out[i] = {
|
|
6072
|
+
text: built.text,
|
|
6073
|
+
...position ? { position } : {},
|
|
6074
|
+
...built.color ? { color: built.color } : {}
|
|
6075
|
+
};
|
|
6076
|
+
});
|
|
6077
|
+
return any ? out : void 0;
|
|
6078
|
+
}
|
|
6079
|
+
function applyDataLabels(model, sources, extra) {
|
|
6080
|
+
const apply = (source, view) => {
|
|
6081
|
+
if (!source?.dataLabels) return;
|
|
6082
|
+
const labels = labelsOf(source.dataLabels, view, model.categories, source.numberFormat);
|
|
6083
|
+
if (labels) view.labels = labels;
|
|
6084
|
+
};
|
|
6085
|
+
model.series.forEach((view, i) => apply(sources[i], view));
|
|
6086
|
+
model.extraGroups?.forEach(
|
|
6087
|
+
(group2, g) => group2.series.forEach((view, i) => apply(extra[g]?.series[i], view))
|
|
6088
|
+
);
|
|
6089
|
+
}
|
|
6090
|
+
|
|
5706
6091
|
// chart/render/chart-view-ex.ts
|
|
5707
6092
|
function groupsAxis(groups, categories) {
|
|
5708
6093
|
let min = Infinity;
|
|
@@ -5888,115 +6273,11 @@ function chartSummaryView(chart, theme, options = {}) {
|
|
|
5888
6273
|
chartExtraView(chart, model, ctx, total, collect);
|
|
5889
6274
|
if (type === "waterfall") waterfallView(chart, model, ctx);
|
|
5890
6275
|
else if (!byPoint) model.valueAxis = valueAxis(model);
|
|
6276
|
+
applyDataLabels(model, chart.series, extra);
|
|
5891
6277
|
chartExtraAxes(model);
|
|
5892
6278
|
return model;
|
|
5893
6279
|
}
|
|
5894
6280
|
|
|
5895
|
-
// text/css-font-family.ts
|
|
5896
|
-
var FALLBACKS = {
|
|
5897
|
-
calibri: '"Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
5898
|
-
"calibri light": '"Calibri Light", "Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
5899
|
-
cambria: '"Cambria", "Caladea", Georgia, serif',
|
|
5900
|
-
arial: 'Arial, "Liberation Sans", Helvetica, sans-serif',
|
|
5901
|
-
"times new roman": '"Times New Roman", "Liberation Serif", Times, serif',
|
|
5902
|
-
"courier new": '"Courier New", "Liberation Mono", monospace',
|
|
5903
|
-
aptos: '"Aptos", "Calibri", "Carlito", "Segoe UI", sans-serif'
|
|
5904
|
-
};
|
|
5905
|
-
function cssFontFamily(name) {
|
|
5906
|
-
const known = FALLBACKS[name.toLowerCase()];
|
|
5907
|
-
if (known) return known;
|
|
5908
|
-
const quoted = `"${name.replace(/["\\]/g, "")}"`;
|
|
5909
|
-
return `${quoted}, "Calibri", "Carlito", "Segoe UI", sans-serif`;
|
|
5910
|
-
}
|
|
5911
|
-
|
|
5912
|
-
// chart/render/chart-svg-appearance.ts
|
|
5913
|
-
var nextPaintId = 0;
|
|
5914
|
-
function chartGradientPaint(model, width = 1024, height = 768) {
|
|
5915
|
-
const prefix = `xlsx-chart-${++nextPaintId}`;
|
|
5916
|
-
const appearance = { ...model.appearance };
|
|
5917
|
-
const defs = [];
|
|
5918
|
-
const shadowPaint = (shadow, suffix) => {
|
|
5919
|
-
const id = `${prefix}-${suffix}`;
|
|
5920
|
-
const pad = Math.max(4, shadow.blur * 3 + Math.abs(shadow.dx) + Math.abs(shadow.dy));
|
|
5921
|
-
defs.push(
|
|
5922
|
-
`<filter id="${id}" filterUnits="userSpaceOnUse" x="${n(-pad)}" y="${n(-pad)}" width="${n(width + pad * 2)}" height="${n(height + pad * 2)}" color-interpolation-filters="sRGB">${svgDropShadowElement(shadow, { number: n, color: (value) => esc(value) })}</filter>`
|
|
5923
|
-
);
|
|
5924
|
-
return `url(#${id})`;
|
|
5925
|
-
};
|
|
5926
|
-
for (const [part, entry3] of Object.entries(appearance)) {
|
|
5927
|
-
if (entry3?.textShadow)
|
|
5928
|
-
appearance[part] = {
|
|
5929
|
-
...entry3,
|
|
5930
|
-
textShadowFilter: shadowPaint(entry3.textShadow, `${part}-text-shadow`)
|
|
5931
|
-
};
|
|
5932
|
-
}
|
|
5933
|
-
const paint2 = (gradient, suffix, bounds) => {
|
|
5934
|
-
const def = buildChartGradientDef(`${prefix}-${suffix}`, gradient, bounds);
|
|
5935
|
-
defs.push(chartGradientMarkup(def));
|
|
5936
|
-
return `url(#${def.id})`;
|
|
5937
|
-
};
|
|
5938
|
-
for (const part of ["chartArea", "plotArea"]) {
|
|
5939
|
-
const entry3 = appearance[part];
|
|
5940
|
-
if (!entry3?.gradient) continue;
|
|
5941
|
-
if (part === "plotArea" && ["circle", "shape"].includes(entry3.gradient.path ?? "")) continue;
|
|
5942
|
-
appearance[part] = {
|
|
5943
|
-
...entry3,
|
|
5944
|
-
fillColor: paint2(entry3.gradient, part, { width, height, shape: "rect" })
|
|
5945
|
-
};
|
|
5946
|
-
}
|
|
5947
|
-
const series = model.series.map((source, index) => {
|
|
5948
|
-
const view = { ...source };
|
|
5949
|
-
if (source.shadow) view.shadowFilter = shadowPaint(source.shadow, `s${index}-shadow`);
|
|
5950
|
-
const bounds = model.type === "bar" || model.type === "column" ? { width: 1, height: 1, shape: "rect" } : void 0;
|
|
5951
|
-
if (source.gradient) view.color = paint2(source.gradient, `s${index}`, bounds);
|
|
5952
|
-
if (source.pointGradients) {
|
|
5953
|
-
view.pointColors = [...source.pointColors ?? []];
|
|
5954
|
-
for (const [key, gradient] of Object.entries(source.pointGradients))
|
|
5955
|
-
view.pointColors[Number(key)] = paint2(gradient, `s${index}-p${key}`, bounds);
|
|
5956
|
-
}
|
|
5957
|
-
return view;
|
|
5958
|
-
});
|
|
5959
|
-
return defs.length ? { model: { ...model, appearance, series }, defs: `<defs>${defs.join("")}</defs>` } : { model, defs: "" };
|
|
5960
|
-
}
|
|
5961
|
-
function chartTextAttributes(model, part, fallbackSize = FONT_SIZE) {
|
|
5962
|
-
const entry3 = model.appearance?.[part];
|
|
5963
|
-
return {
|
|
5964
|
-
size: entry3?.fontSize === void 0 ? fallbackSize : chartPointsToPixels(entry3.fontSize),
|
|
5965
|
-
...entry3?.color === void 0 ? {} : { fill: entry3.color },
|
|
5966
|
-
...entry3?.bold === void 0 ? {} : { weight: entry3.bold ? "bold" : "normal" },
|
|
5967
|
-
...entry3?.italic === void 0 ? {} : { italic: entry3.italic },
|
|
5968
|
-
...entry3?.underline === void 0 ? {} : { underline: entry3.underline },
|
|
5969
|
-
...entry3?.typeface === void 0 ? {} : { family: cssFontFamily(entry3.typeface) },
|
|
5970
|
-
...entry3?.textShadowFilter === void 0 ? {} : { filter: entry3.textShadowFilter }
|
|
5971
|
-
};
|
|
5972
|
-
}
|
|
5973
|
-
function chartStroke(model, part) {
|
|
5974
|
-
const entry3 = model.appearance?.[part];
|
|
5975
|
-
return {
|
|
5976
|
-
color: entry3?.axisVisible === false ? "none" : entry3?.lineColor ?? (part === "gridlineMajor" ? GRID_COLOR : AXIS_COLOR),
|
|
5977
|
-
width: entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth)
|
|
5978
|
-
};
|
|
5979
|
-
}
|
|
5980
|
-
function chartAreaRect(model, part, area) {
|
|
5981
|
-
if (area.w <= 0 || area.h <= 0) return "";
|
|
5982
|
-
const entry3 = model.appearance?.[part];
|
|
5983
|
-
let fill = entry3?.fillColor ?? (part === "chartArea" ? "#FFFFFF" : "none");
|
|
5984
|
-
let defs = "";
|
|
5985
|
-
if (part !== "chartArea" && entry3?.gradient && (part !== "plotArea" || ["circle", "shape"].includes(entry3.gradient.path ?? ""))) {
|
|
5986
|
-
const def = buildChartGradientDef(`xlsx-chart-${++nextPaintId}-${part}`, entry3.gradient, {
|
|
5987
|
-
width: area.w,
|
|
5988
|
-
height: area.h,
|
|
5989
|
-
shape: "rect"
|
|
5990
|
-
});
|
|
5991
|
-
defs = `<defs>${chartGradientMarkup(def)}</defs>`;
|
|
5992
|
-
fill = `url(#${def.id})`;
|
|
5993
|
-
}
|
|
5994
|
-
const stroke = entry3?.lineColor ?? "none";
|
|
5995
|
-
if (fill === "none" && stroke === "none") return "";
|
|
5996
|
-
const width = entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth);
|
|
5997
|
-
return `${defs}<rect x="${n(area.x)}" y="${n(area.y)}" width="${n(area.w)}" height="${n(area.h)}" fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${n(width)}" data-chart-part="${part}"/>`;
|
|
5998
|
-
}
|
|
5999
|
-
|
|
6000
6281
|
// chart/render/chart-svg-cartesian.ts
|
|
6001
6282
|
function cartesianAxes(model, area, out) {
|
|
6002
6283
|
const scale = model.valueAxis;
|
|
@@ -6115,6 +6396,7 @@ function linesAndAreas(model, frame, out) {
|
|
|
6115
6396
|
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
6116
6397
|
const acc = new Array(model.categories.length).fill(0);
|
|
6117
6398
|
const area = model.type === "area";
|
|
6399
|
+
const marks = [];
|
|
6118
6400
|
const layers = [];
|
|
6119
6401
|
model.series.forEach((s, si) => {
|
|
6120
6402
|
const points = [];
|
|
@@ -6129,6 +6411,13 @@ function linesAndAreas(model, frame, out) {
|
|
|
6129
6411
|
const top = below + (v ?? 0);
|
|
6130
6412
|
if (stacked) acc[i] = top;
|
|
6131
6413
|
points.push([frame.band(i), frame.value(top)]);
|
|
6414
|
+
marks.push({
|
|
6415
|
+
series: s,
|
|
6416
|
+
index: i,
|
|
6417
|
+
x: frame.band(i),
|
|
6418
|
+
y: frame.value(top),
|
|
6419
|
+
radius: area ? 0 : 3
|
|
6420
|
+
});
|
|
6132
6421
|
lower.push([frame.band(i), frame.value(below)]);
|
|
6133
6422
|
});
|
|
6134
6423
|
layers.push({
|
|
@@ -6161,6 +6450,7 @@ function linesAndAreas(model, frame, out) {
|
|
|
6161
6450
|
if (!Number.isNaN(x))
|
|
6162
6451
|
out.push(`<circle cx="${n(x)}" cy="${n(y)}" r="2.5" fill="${color}"${filter}/>`);
|
|
6163
6452
|
}
|
|
6453
|
+
pointLabels(model, marks, out);
|
|
6164
6454
|
}
|
|
6165
6455
|
|
|
6166
6456
|
// chart/render/chart-svg-xy.ts
|
|
@@ -6230,6 +6520,7 @@ function scatter(model, area, out) {
|
|
|
6230
6520
|
line(plot.x, plot.y + plot.h, plot.x + plot.w, plot.y + plot.h, xAxis.color, xAxis.width)
|
|
6231
6521
|
);
|
|
6232
6522
|
out.push(line(plot.x, plot.y, plot.x, plot.y + plot.h, yAxis.color, yAxis.width));
|
|
6523
|
+
const marks = [];
|
|
6233
6524
|
for (const [si, s] of model.series.entries())
|
|
6234
6525
|
s.values.forEach((v, i) => {
|
|
6235
6526
|
const x = s.xValues?.[i] ?? null;
|
|
@@ -6238,14 +6529,17 @@ function scatter(model, area, out) {
|
|
|
6238
6529
|
const fill = s.pointColors?.[i] ?? s.color;
|
|
6239
6530
|
if (!bubble) {
|
|
6240
6531
|
out.push(`<circle cx="${n(px(x))}" cy="${n(py(v))}" r="3" fill="${fill}"${filter}/>`);
|
|
6532
|
+
marks.push({ series: s, index: i, x: px(x), y: py(v), radius: 3 });
|
|
6241
6533
|
return;
|
|
6242
6534
|
}
|
|
6243
6535
|
const r = radiusOf(s.sizes?.[i] ?? void 0);
|
|
6244
6536
|
if (r === void 0) return;
|
|
6537
|
+
marks.push({ series: s, index: i, x: px(x), y: py(v), radius: r });
|
|
6245
6538
|
out.push(
|
|
6246
6539
|
`<circle cx="${n(px(x))}" cy="${n(py(v))}" r="${n(r)}" fill="${fill}" fill-opacity="0.6" data-chart-series="${si}" data-chart-point="${i}"${filter}/>`
|
|
6247
6540
|
);
|
|
6248
6541
|
});
|
|
6542
|
+
pointLabels(model, marks, out);
|
|
6249
6543
|
scatterAnalysis(model, px, py, out);
|
|
6250
6544
|
}
|
|
6251
6545
|
|
|
@@ -6410,7 +6704,9 @@ function pieSvg(model, area) {
|
|
|
6410
6704
|
const out = [chartAreaRect(model, "plotArea", area)];
|
|
6411
6705
|
const cx2 = area.x + area.w / 2;
|
|
6412
6706
|
const cy = area.y + area.h / 2;
|
|
6413
|
-
const
|
|
6707
|
+
const margin = hasOutsideLabels(model) ? Math.min(area.w, area.h) * 0.12 : 0;
|
|
6708
|
+
const radius = Math.max(1, Math.min(area.w, area.h) / 2 - 4 - margin);
|
|
6709
|
+
const slices = [];
|
|
6414
6710
|
const rings = model.type === "doughnut" ? model.series : model.series.slice(0, 1);
|
|
6415
6711
|
const hole = model.type === "doughnut" ? radius * 0.5 : 0;
|
|
6416
6712
|
const ringSize = (radius - hole) / Math.max(1, rings.length);
|
|
@@ -6427,9 +6723,20 @@ function pieSvg(model, area) {
|
|
|
6427
6723
|
out.push(
|
|
6428
6724
|
`<path d="${slicePath(cx2, cy, outer, inner, angle, angle + sweep)}" fill="${color}" stroke="#FFFFFF" stroke-width="1"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
|
|
6429
6725
|
);
|
|
6726
|
+
slices.push({
|
|
6727
|
+
series: s,
|
|
6728
|
+
index: i,
|
|
6729
|
+
cx: cx2,
|
|
6730
|
+
cy,
|
|
6731
|
+
outer,
|
|
6732
|
+
inner,
|
|
6733
|
+
start: angle,
|
|
6734
|
+
end: angle + sweep
|
|
6735
|
+
});
|
|
6430
6736
|
angle += sweep;
|
|
6431
6737
|
});
|
|
6432
6738
|
});
|
|
6739
|
+
sliceLabels(model, slices, out);
|
|
6433
6740
|
return out.join("");
|
|
6434
6741
|
}
|
|
6435
6742
|
function radarSvg(model, area) {
|
|
@@ -6475,12 +6782,16 @@ function radarSvg(model, area) {
|
|
|
6475
6782
|
})
|
|
6476
6783
|
);
|
|
6477
6784
|
});
|
|
6785
|
+
const marks = [];
|
|
6478
6786
|
for (const s of model.series) {
|
|
6479
|
-
const
|
|
6787
|
+
const vertices = s.values.slice(0, count).map((v, i) => polar(cx2, cy, r(v ?? scale.min), angle(i)));
|
|
6788
|
+
vertices.forEach(([x, y], i) => marks.push({ series: s, index: i, x, y, radius: 3 }));
|
|
6789
|
+
const points = vertices.map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
|
|
6480
6790
|
out.push(
|
|
6481
6791
|
`<polygon points="${points}" fill="none" stroke="${s.color}" stroke-width="2"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
|
|
6482
6792
|
);
|
|
6483
6793
|
}
|
|
6794
|
+
pointLabels(model, marks, out);
|
|
6484
6795
|
return out.join("");
|
|
6485
6796
|
}
|
|
6486
6797
|
|
|
@@ -6732,7 +7043,7 @@ function automaticLegend(model, area, out, options, bounds) {
|
|
|
6732
7043
|
|
|
6733
7044
|
// text/wrap-styled-runs.ts
|
|
6734
7045
|
var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
6735
|
-
function wrapStyledRuns(runs, maxWidth,
|
|
7046
|
+
function wrapStyledRuns(runs, maxWidth, measure2, options = {}) {
|
|
6736
7047
|
const groups = [];
|
|
6737
7048
|
for (const [source, run2] of runs.entries()) {
|
|
6738
7049
|
for (const token of run2.text.split(/(\r\n|[\r\n]|[ \t]+)/u).filter(Boolean)) {
|
|
@@ -6755,7 +7066,7 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
|
|
|
6755
7066
|
return result2;
|
|
6756
7067
|
};
|
|
6757
7068
|
const width = (pieces) => pieces.reduce((sum, piece) => {
|
|
6758
|
-
const advance =
|
|
7069
|
+
const advance = measure2(piece.text, piece.run);
|
|
6759
7070
|
return sum + (Number.isFinite(advance) && advance >= 0 ? advance : 0);
|
|
6760
7071
|
}, 0);
|
|
6761
7072
|
const result = [];
|
|
@@ -7045,4 +7356,4 @@ function renderChartSummarySvg(summary, options) {
|
|
|
7045
7356
|
return renderChartSvg(view, width, height, svg);
|
|
7046
7357
|
}
|
|
7047
7358
|
|
|
7048
|
-
export { BEST_FIT_EDGE_TOLERANCE, BEST_FIT_OUTSIDE_GAP, BEST_FIT_RIM_INSET, CHART_AUTO_TITLE, CHART_COLOR_PALETTES, CHART_COLOR_STYLE_CONTENT_TYPE, CHART_COLOR_STYLE_NS, CHART_COLOR_STYLE_REL, CHART_ERROR_BAR_DIRECTIONS, CHART_ERROR_BAR_TYPES, CHART_ERROR_VALUE_TYPES, CHART_GROUP_ELEMENTS, CHART_STYLE_PARTS, DEFAULT_BAR_GAP_WIDTH, DEFAULT_CHART_PALETTE, DEFAULT_THEME_COLORS, DRAWN_CHART_TYPES, LABEL_COLLISION_GAP, STOCK_DEFAULT_DOWN_FILL, STOCK_DEFAULT_UP_FILL, STOCK_DEFAULT_WICK_COLOR, STOCK_TICK_WIDTH, THEME_SLOTS, aggregate, aggregateByCategory, assertBarClusterOptions, autoSeriesColor, axisTargetIntervals, buildChartGradientDef, buildHierarchyRoots, buildWaterfallSteps, builtInChartStyleXml, builtInChartTextStyle, categoryTotals, chartCacheValues, chartColorScheme, chartColorStyleId, chartColorStyleXml, chartErrorBarAmount, chartExSummary, chartGradientMarkup, chartPaletteColors, chartPaletteSeriesColor, chartPaletteSeriesColorChoice, chartSampleVariance, chartSourceValues, chartSpaceKind, chartSummaryFromSpace, chartSummarySeries, chartSummaryView, chartThemePalette, chartTrendlineKind, chartTrendlineType, clusteredBarGeometry, computeBoxStats, computeBubbleRadius, computeHierarchicalSunburstArcs, computeHistogramBins, computeLinearRegression, computeRSquared, computeRadarPoints, computeStackedSeriesPlots, computeSunburstArcs, computeWaterfallRange, effectiveBuiltInChartStyle, findChartColorPalette, fitChartTrendline, fitPolynomial, formatChartNumber, formatChartNumberWithColor, formatCompactAxisValue, formatExponentialEquation, formatLinearEquation, formatLogarithmicEquation, formatPolynomialEquation, formatPowerEquation, formatTrendlineCoefficient, getChartStylePalette, groupRowsByCategory, hasManualLayoutFields, hierarchyBranchLabels, impliesAutoTitle, isChartexOnlyType, layoutTreemap, maxBubbleSize, medianBubbleRadius, modulateLuminance, niceAxisStep, niceValueAxisBounds, normalizeLevels, nudgeOutsideLabels, parseChartSpace, placeBestFitLabel, radarAngle, radarRingPoints, readBuiltInChartStyle, readChartFormatting, readChartManualLayoutValues, readChartStyle, readDisplayNaAsBlank, removeGradientStop, renderChartSpaceSvg, renderChartSummarySvg, renderChartSvg, resolveAutoTitleText, resolveBlankDisplay, resolveChartGradient, resolveChartStyleDefinition, resolveManualLayoutRect, scottBinCount, shade, sortGradientStops, squarify, stockCandle, stockSlots, sunburstArcPath, themeColor, tint, updateGradientStop, visibleRuns, withChartGradientDirection, withinLinearTransform, writeChartAxisFormatting, writeChartFillFormatting, writeChartLayoutFormatting, writeChartSpace };
|
|
7359
|
+
export { BEST_FIT_EDGE_TOLERANCE, BEST_FIT_OUTSIDE_GAP, BEST_FIT_RIM_INSET, CHART_AUTO_TITLE, CHART_COLOR_PALETTES, CHART_COLOR_STYLE_CONTENT_TYPE, CHART_COLOR_STYLE_NS, CHART_COLOR_STYLE_REL, CHART_ERROR_BAR_DIRECTIONS, CHART_ERROR_BAR_TYPES, CHART_ERROR_VALUE_TYPES, CHART_GROUP_ELEMENTS, CHART_STYLE_PARTS, DATA_LABEL_CATEGORY_PERCENT_SEPARATOR, DATA_LABEL_SEPARATOR, DEFAULT_BAR_GAP_WIDTH, DEFAULT_CHART_PALETTE, DEFAULT_THEME_COLORS, DRAWN_CHART_TYPES, LABEL_COLLISION_GAP, STOCK_DEFAULT_DOWN_FILL, STOCK_DEFAULT_UP_FILL, STOCK_DEFAULT_WICK_COLOR, STOCK_TICK_WIDTH, THEME_SLOTS, aggregate, aggregateByCategory, assertBarClusterOptions, autoSeriesColor, axisTargetIntervals, buildChartGradientDef, buildHierarchyRoots, buildWaterfallSteps, builtInChartStyleXml, builtInChartTextStyle, categoryTotals, chartCacheValues, chartColorScheme, chartColorStyleId, chartColorStyleXml, chartErrorBarAmount, chartExSummary, chartGradientMarkup, chartPaletteColors, chartPaletteSeriesColor, chartPaletteSeriesColorChoice, chartSampleVariance, chartSourceValues, chartSpaceKind, chartSummaryFromSpace, chartSummarySeries, chartSummaryView, chartThemePalette, chartTrendlineKind, chartTrendlineType, clusteredBarGeometry, composeDataLabelText, computeBoxStats, computeBubbleRadius, computeHierarchicalSunburstArcs, computeHistogramBins, computeLinearRegression, computeRSquared, computeRadarPoints, computeStackedSeriesPlots, computeSunburstArcs, computeWaterfallRange, effectiveBuiltInChartStyle, findChartColorPalette, fitChartTrendline, fitPolynomial, formatChartNumber, formatChartNumberWithColor, formatCompactAxisValue, formatExponentialEquation, formatLinearEquation, formatLogarithmicEquation, formatPolynomialEquation, formatPowerEquation, formatTrendlineCoefficient, getChartStylePalette, groupRowsByCategory, hasManualLayoutFields, hierarchyBranchLabels, impliesAutoTitle, isChartexOnlyType, layoutTreemap, maxBubbleSize, medianBubbleRadius, modulateLuminance, niceAxisStep, niceValueAxisBounds, normalizeLevels, nudgeOutsideLabels, parseChartSpace, placeBestFitLabel, radarAngle, radarRingPoints, readBuiltInChartStyle, readChartFormatting, readChartManualLayoutValues, readChartStyle, readDisplayNaAsBlank, removeGradientStop, renderChartSpaceSvg, renderChartSummarySvg, renderChartSvg, resolveAutoTitleText, resolveBlankDisplay, resolveChartGradient, resolveChartStyleDefinition, resolveDataLabelFlags, resolveManualLayoutRect, scottBinCount, shade, sortGradientStops, squarify, stockCandle, stockSlots, sunburstArcPath, themeColor, tint, updateGradientStop, visibleRuns, withChartGradientDirection, withinLinearTransform, writeChartAxisFormatting, writeChartFillFormatting, writeChartLayoutFormatting, writeChartSpace };
|