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