ooxml-core 1.18.0 → 1.19.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-X6AO6LKJ.mjs → PptxHandler-5GBBVJCR.mjs} +2 -2
- package/dist/{PptxHandler-5X4VOWAO.mjs → PptxHandler-H43MAMTO.mjs} +1 -1
- package/dist/{PptxHandler-4AHDZDA5.cjs → PptxHandler-ZHPGBSAF.cjs} +2 -2
- package/dist/{PresentationBuilder-UY3S4YE2.mjs → PresentationBuilder-7ZSUKCX5.mjs} +1 -1
- package/dist/{PresentationBuilder-LRX55PXA.mjs → PresentationBuilder-IJW42L3R.mjs} +2 -2
- package/dist/{PresentationBuilder-MJB4LIFS.cjs → PresentationBuilder-O4H4MMWB.cjs} +4 -4
- package/dist/automation/index.cjs +535 -266
- package/dist/automation/index.mjs +535 -266
- package/dist/chart/axis-range-auto.d.ts +10 -0
- package/dist/chart/axis-range-auto.d.ts.map +1 -0
- package/dist/chart/axis-range-types.d.ts +27 -0
- package/dist/chart/axis-range-types.d.ts.map +1 -0
- package/dist/chart/axis-range.d.ts +37 -0
- package/dist/chart/axis-range.d.ts.map +1 -0
- package/dist/chart/axis-ticks.d.ts +8 -0
- package/dist/chart/axis-ticks.d.ts.map +1 -0
- package/dist/chart/index.cjs +815 -165
- package/dist/chart/index.d.ts +6 -0
- package/dist/chart/index.d.ts.map +1 -1
- package/dist/chart/index.mjs +795 -166
- package/dist/chart/line-dash.d.ts +2 -0
- package/dist/chart/line-dash.d.ts.map +1 -0
- package/dist/chart/marker-shape.d.ts +70 -0
- package/dist/chart/marker-shape.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-axes.d.ts +9 -0
- package/dist/chart/render/chart-svg-axes.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-cartesian.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-markers.d.ts +6 -0
- package/dist/chart/render/chart-svg-markers.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-axes.d.ts +30 -0
- package/dist/chart/render/chart-view-axes.d.ts.map +1 -0
- package/dist/chart/render/chart-view-markers.d.ts +27 -0
- package/dist/chart/render/chart-view-markers.d.ts.map +1 -0
- package/dist/chart/render/chart-view-series.d.ts.map +1 -1
- package/dist/chart/render/chart-view.d.ts +4 -1
- package/dist/chart/render/chart-view.d.ts.map +1 -1
- package/dist/chart/render/index.d.ts +2 -0
- package/dist/chart/render/index.d.ts.map +1 -1
- package/dist/chart/render/summary-from-space.d.ts.map +1 -1
- package/dist/chart/render/summary.d.ts +6 -1
- package/dist/chart/render/summary.d.ts.map +1 -1
- package/dist/{chunk-7NWQUCGX.mjs → chunk-3XFPCZKB.mjs} +1 -1
- package/dist/{chunk-Z5Y53IZD.mjs → chunk-75GLSRZE.mjs} +4 -4
- package/dist/{chunk-LT7RCEHY.mjs → chunk-BIVNVDAH.mjs} +1 -1
- package/dist/{chunk-I5ZE3VLI.mjs → chunk-QBJRB6WW.mjs} +1 -1
- package/dist/{chunk-U7IDT6VT.mjs → chunk-RUZEMWDI.mjs} +1 -1
- package/dist/docx/index.cjs +695 -168
- package/dist/docx/index.mjs +695 -168
- package/dist/docx/layout/index.cjs +697 -170
- package/dist/docx/layout/index.mjs +697 -170
- package/dist/docx/ui/index.cjs +704 -177
- package/dist/docx/ui/index.mjs +704 -177
- package/dist/index.cjs +912 -262
- package/dist/index.mjs +912 -262
- package/dist/pptx/automation/index.cjs +54 -0
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/cli/index.cjs +54 -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 +54 -0
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +71 -5
- package/dist/teams/index.mjs +71 -5
- package/dist/visio/index.cjs +483 -214
- package/dist/visio/index.mjs +483 -214
- package/dist/visio/ui/index.cjs +504 -235
- package/dist/visio/ui/index.mjs +504 -235
- package/dist/xlsx/edit/chart-colors.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +818 -281
- package/dist/xlsx/index.mjs +818 -281
- package/dist/xlsx/load/index.cjs +58 -5
- package/dist/xlsx/load/index.mjs +58 -5
- package/dist/xlsx/read/chart.d.ts.map +1 -1
- package/dist/xlsx/ui/index.cjs +835 -298
- package/dist/xlsx/ui/index.mjs +835 -298
- package/package.json +1 -1
- /package/dist/{chunk-C363NN2C.mjs → chunk-H6TNNXJK.mjs} +0 -0
- /package/dist/{chunk-R4BCOQHB.cjs → chunk-MHMVD23Y.cjs} +0 -0
package/dist/chart/index.cjs
CHANGED
|
@@ -610,12 +610,12 @@ function formatCompactAxisValue(value, formatCode) {
|
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
// chart/bubble-radius.ts
|
|
613
|
-
function computeBubbleRadius(sizeVal, maxBubble, medianRadius,
|
|
614
|
-
const scale = (
|
|
613
|
+
function computeBubbleRadius(sizeVal, maxBubble, medianRadius, options2) {
|
|
614
|
+
const scale = (options2?.bubbleScale ?? 100) / 100;
|
|
615
615
|
if (sizeVal === void 0) return medianRadius * scale;
|
|
616
616
|
const denom = maxBubble > 0 ? maxBubble : 1;
|
|
617
617
|
const magnitude = Math.abs(sizeVal);
|
|
618
|
-
const ratio = (
|
|
618
|
+
const ratio = (options2?.sizeRepresents ?? "w") === "area" ? Math.sqrt(magnitude) / Math.sqrt(denom) : magnitude / denom;
|
|
619
619
|
return medianRadius * scale * 0.5 + ratio * medianRadius * scale * 1.5;
|
|
620
620
|
}
|
|
621
621
|
function maxBubbleSize(sizes) {
|
|
@@ -1016,14 +1016,14 @@ function scottBinCount(values, min, max) {
|
|
|
1016
1016
|
const width = 3.49 * sd * values.length ** (-1 / 3);
|
|
1017
1017
|
return Math.max(1, Math.ceil((max - min) / width));
|
|
1018
1018
|
}
|
|
1019
|
-
function computeHistogramBins(values,
|
|
1020
|
-
const closed =
|
|
1019
|
+
function computeHistogramBins(values, options2, format = String) {
|
|
1020
|
+
const closed = options2.intervalClosed ?? "l";
|
|
1021
1021
|
const finite = values.map((value, sourceIndex) => ({ value, sourceIndex })).filter((item) => Number.isFinite(item.value));
|
|
1022
1022
|
if (finite.length === 0) {
|
|
1023
1023
|
return [];
|
|
1024
1024
|
}
|
|
1025
|
-
const underflow = typeof
|
|
1026
|
-
const overflow = typeof
|
|
1025
|
+
const underflow = typeof options2.underflow === "number" ? options2.underflow : void 0;
|
|
1026
|
+
const overflow = typeof options2.overflow === "number" ? options2.overflow : void 0;
|
|
1027
1027
|
const under = underflow === void 0 ? [] : finite.filter(
|
|
1028
1028
|
(item) => closed === "r" ? item.value <= underflow : item.value < underflow
|
|
1029
1029
|
);
|
|
@@ -1040,8 +1040,8 @@ function computeHistogramBins(values, options, format = String) {
|
|
|
1040
1040
|
if (regular.length > 0) {
|
|
1041
1041
|
const min = Math.min(...regular.map((item) => item.value));
|
|
1042
1042
|
const max = Math.max(...regular.map((item) => item.value));
|
|
1043
|
-
const requestedSize =
|
|
1044
|
-
const requestedCount =
|
|
1043
|
+
const requestedSize = options2.binSize && options2.binSize > 0 ? options2.binSize : void 0;
|
|
1044
|
+
const requestedCount = options2.binCount && options2.binCount > 0 ? options2.binCount : void 0;
|
|
1045
1045
|
const start = requestedSize ? Math.floor(min / requestedSize) * requestedSize : min;
|
|
1046
1046
|
const count = requestedSize ? Math.max(
|
|
1047
1047
|
closed === "l" ? Math.floor((max - start) / requestedSize) + 1 : Math.ceil((max - start) / requestedSize),
|
|
@@ -1092,9 +1092,9 @@ function aggregateByCategory(values, rawCategories) {
|
|
|
1092
1092
|
}
|
|
1093
1093
|
|
|
1094
1094
|
// chart/waterfall.ts
|
|
1095
|
-
function buildWaterfallSteps(values,
|
|
1095
|
+
function buildWaterfallSteps(values, options2) {
|
|
1096
1096
|
const subtotalIndices = new Set(
|
|
1097
|
-
|
|
1097
|
+
options2?.subtotalIndices ?? (values.length > 0 ? [values.length - 1] : [])
|
|
1098
1098
|
);
|
|
1099
1099
|
const steps = [];
|
|
1100
1100
|
let runningTotal = 0;
|
|
@@ -1170,13 +1170,13 @@ var noFit = () => ({
|
|
|
1170
1170
|
rSquared: 0,
|
|
1171
1171
|
coefficients: []
|
|
1172
1172
|
});
|
|
1173
|
-
function fitModel(
|
|
1173
|
+
function fitModel(options2, xVals, yVals) {
|
|
1174
1174
|
const xs = [...xVals];
|
|
1175
1175
|
const ys = [...yVals];
|
|
1176
|
-
switch (
|
|
1176
|
+
switch (options2.kind) {
|
|
1177
1177
|
case "linear": {
|
|
1178
1178
|
const reg = computeLinearRegression(xs, ys);
|
|
1179
|
-
const fixed =
|
|
1179
|
+
const fixed = options2.intercept;
|
|
1180
1180
|
const slope = fixed !== void 0 ? ys.reduce((s, y, i) => s + (y - fixed) * xs[i], 0) / xs.reduce((s, x) => s + x * x, 0) : reg.slope;
|
|
1181
1181
|
const b = fixed ?? reg.intercept;
|
|
1182
1182
|
return {
|
|
@@ -1226,7 +1226,7 @@ function fitModel(options, xVals, yVals) {
|
|
|
1226
1226
|
};
|
|
1227
1227
|
}
|
|
1228
1228
|
case "polynomial": {
|
|
1229
|
-
const order = Math.min(
|
|
1229
|
+
const order = Math.min(options2.order ?? 2, 6);
|
|
1230
1230
|
const coeffs = fitPolynomial(xs, ys, order);
|
|
1231
1231
|
const evaluate = (x) => coeffs.reduce((s, c2, i) => s + c2 * x ** i, 0);
|
|
1232
1232
|
return {
|
|
@@ -1240,11 +1240,11 @@ function fitModel(options, xVals, yVals) {
|
|
|
1240
1240
|
return void 0;
|
|
1241
1241
|
}
|
|
1242
1242
|
}
|
|
1243
|
-
function fitChartTrendline(
|
|
1243
|
+
function fitChartTrendline(options2, xVals, yVals) {
|
|
1244
1244
|
const count = yVals.length;
|
|
1245
1245
|
if (count < 2) return noFit();
|
|
1246
|
-
if (
|
|
1247
|
-
const period =
|
|
1246
|
+
if (options2.kind === "movingAvg") {
|
|
1247
|
+
const period = options2.period ?? 2;
|
|
1248
1248
|
const points2 = [];
|
|
1249
1249
|
for (let i = period - 1; i < count; i++) {
|
|
1250
1250
|
let sum = 0;
|
|
@@ -1253,10 +1253,10 @@ function fitChartTrendline(options, xVals, yVals) {
|
|
|
1253
1253
|
}
|
|
1254
1254
|
return { points: points2, equation: `${period}-period moving average`, rSquared: 0, coefficients: [] };
|
|
1255
1255
|
}
|
|
1256
|
-
const model = fitModel(
|
|
1256
|
+
const model = fitModel(options2, xVals, yVals);
|
|
1257
1257
|
if (!model) return noFit();
|
|
1258
|
-
const startX = Math.min(...xVals) - (
|
|
1259
|
-
const endX = Math.max(...xVals) + (
|
|
1258
|
+
const startX = Math.min(...xVals) - (options2.backward ?? 0);
|
|
1259
|
+
const endX = Math.max(...xVals) + (options2.forward ?? 0);
|
|
1260
1260
|
const steps = Math.max(Math.ceil((endX - startX) * 4), 20);
|
|
1261
1261
|
const points = [];
|
|
1262
1262
|
for (let step = 0; step <= steps; step++) {
|
|
@@ -1279,18 +1279,18 @@ function chartSampleVariance(values) {
|
|
|
1279
1279
|
const mean = values.reduce((sum, value) => sum + value, 0) / count;
|
|
1280
1280
|
return values.reduce((sum, value) => sum + (value - mean) ** 2, 0) / Math.max(count - 1, 1);
|
|
1281
1281
|
}
|
|
1282
|
-
function chartErrorBarAmount(
|
|
1283
|
-
switch (
|
|
1282
|
+
function chartErrorBarAmount(options2, values, displayIndex, sourceIndex, side) {
|
|
1283
|
+
switch (options2.valueType) {
|
|
1284
1284
|
case "fixedVal":
|
|
1285
|
-
return
|
|
1285
|
+
return options2.value ?? 0;
|
|
1286
1286
|
case "percentage":
|
|
1287
|
-
return Math.abs(values[displayIndex] ?? 0) * ((
|
|
1287
|
+
return Math.abs(values[displayIndex] ?? 0) * ((options2.value ?? 0) / 100);
|
|
1288
1288
|
case "stdDev":
|
|
1289
|
-
return Math.sqrt(chartSampleVariance(values)) * (
|
|
1289
|
+
return Math.sqrt(chartSampleVariance(values)) * (options2.value ?? 1);
|
|
1290
1290
|
case "stdErr":
|
|
1291
1291
|
return Math.sqrt(chartSampleVariance(values) / Math.max(values.length, 1));
|
|
1292
1292
|
case "cust":
|
|
1293
|
-
return side === "plus" ?
|
|
1293
|
+
return side === "plus" ? options2.customPlus?.[sourceIndex] ?? 0 : options2.customMinus?.[sourceIndex] ?? 0;
|
|
1294
1294
|
}
|
|
1295
1295
|
}
|
|
1296
1296
|
|
|
@@ -1495,8 +1495,8 @@ function rgbToHsl(r, g, b) {
|
|
|
1495
1495
|
}
|
|
1496
1496
|
return { h, s: clampUnitInterval(s), l: clampUnitInterval(l) };
|
|
1497
1497
|
}
|
|
1498
|
-
function hslToRgb(h, s, l, roundChannel = Math.round,
|
|
1499
|
-
const sC =
|
|
1498
|
+
function hslToRgb(h, s, l, roundChannel = Math.round, options2) {
|
|
1499
|
+
const sC = options2?.clampSaturation === false ? s : clampUnitInterval(s);
|
|
1500
1500
|
const lC = clampUnitInterval(l);
|
|
1501
1501
|
const hN = (h % 360 + 360) % 360;
|
|
1502
1502
|
const c2 = (1 - Math.abs(2 * lC - 1)) * sC;
|
|
@@ -1901,11 +1901,11 @@ function checkXmlLimits(xml, label, limits = {}) {
|
|
|
1901
1901
|
throw new Error(`${label} XML exceeds the nesting depth limit of ${maxDepth}`);
|
|
1902
1902
|
}
|
|
1903
1903
|
}
|
|
1904
|
-
function parseXml(xml,
|
|
1905
|
-
const label =
|
|
1904
|
+
function parseXml(xml, options2 = {}) {
|
|
1905
|
+
const label = options2.label ?? "OOXML";
|
|
1906
1906
|
if (/<!DOCTYPE|<!ENTITY/i.test(xml))
|
|
1907
1907
|
throw new Error(`${label} XML with DTD or entity declarations is not supported`);
|
|
1908
|
-
checkXmlLimits(xml, label,
|
|
1908
|
+
checkXmlLimits(xml, label, options2.limits);
|
|
1909
1909
|
let parseError = "";
|
|
1910
1910
|
let parsed;
|
|
1911
1911
|
try {
|
|
@@ -2101,13 +2101,13 @@ var APPLIED = /* @__PURE__ */ new Set([
|
|
|
2101
2101
|
"lumMod",
|
|
2102
2102
|
"lumOff"
|
|
2103
2103
|
]);
|
|
2104
|
-
function resolveDrawingColor(color, theme,
|
|
2104
|
+
function resolveDrawingColor(color, theme, options2) {
|
|
2105
2105
|
const base = baseHex(color, theme);
|
|
2106
2106
|
const rgb = base ? hexToRgbChannels(base) : null;
|
|
2107
2107
|
if (!rgb) return void 0;
|
|
2108
|
-
if (
|
|
2108
|
+
if (options2?.transformOrder === "document") {
|
|
2109
2109
|
const value = orderedColorTransforms(rgb, color.transforms);
|
|
2110
|
-
const round =
|
|
2110
|
+
const round = options2.hslRounding === "halfDown" ? (channel) => Math.ceil(channel - 0.5) : Math.round;
|
|
2111
2111
|
return {
|
|
2112
2112
|
hex: `#${toHex(round(value.r))}${toHex(round(value.g))}${toHex(round(value.b))}`,
|
|
2113
2113
|
alpha: value.alpha,
|
|
@@ -2158,7 +2158,7 @@ function resolveDrawingColor(color, theme, options) {
|
|
|
2158
2158
|
if (lumMod !== void 0) hsl.l = clampUnitInterval(hsl.l * lumMod);
|
|
2159
2159
|
const lumOff = parseDrawingFraction(find("lumOff"));
|
|
2160
2160
|
if (lumOff !== void 0) hsl.l = clampUnitInterval(hsl.l + lumOff);
|
|
2161
|
-
const round =
|
|
2161
|
+
const round = options2?.hslRounding === "halfDown" ? (value) => Math.ceil(value - 0.5) : Math.round;
|
|
2162
2162
|
({ r, g, b } = hslToRgb(hsl.h, hsl.s, hsl.l, round));
|
|
2163
2163
|
}
|
|
2164
2164
|
let alpha = parseDrawingPercent(find("alpha")) ?? 1;
|
|
@@ -3104,7 +3104,7 @@ function resolveInnerRect(fillToRect, focalPoint) {
|
|
|
3104
3104
|
function lerpEdge(inner, outer, t) {
|
|
3105
3105
|
return inner + (outer - inner) * t;
|
|
3106
3106
|
}
|
|
3107
|
-
function buildRectPathGradientSvg(stops, focalPoint, fillToRect,
|
|
3107
|
+
function buildRectPathGradientSvg(stops, focalPoint, fillToRect, options2) {
|
|
3108
3108
|
if (stops.length === 0) {
|
|
3109
3109
|
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"/>';
|
|
3110
3110
|
}
|
|
@@ -3113,7 +3113,7 @@ function buildRectPathGradientSvg(stops, focalPoint, fillToRect, options) {
|
|
|
3113
3113
|
const rects = [];
|
|
3114
3114
|
const alphaRects = [];
|
|
3115
3115
|
const masked = sorted.some((stop) => (stop.opacity ?? 1) < 1);
|
|
3116
|
-
const bands =
|
|
3116
|
+
const bands = options2?.bands;
|
|
3117
3117
|
if (!Number.isInteger(bands) || bands < 1) throw new RangeError("Invalid gradient band count");
|
|
3118
3118
|
for (let i = bands; i >= 0; i -= 1) {
|
|
3119
3119
|
const t = i / bands;
|
|
@@ -3236,12 +3236,12 @@ function chartGradientMarkup(def) {
|
|
|
3236
3236
|
|
|
3237
3237
|
// chart/bar-cluster-geometry.ts
|
|
3238
3238
|
var DEFAULT_BAR_GAP_WIDTH = 150;
|
|
3239
|
-
function assertBarClusterOptions(
|
|
3239
|
+
function assertBarClusterOptions(options2) {
|
|
3240
3240
|
for (const [field, min, max] of [
|
|
3241
3241
|
["barGapWidth", 0, 500],
|
|
3242
3242
|
["barOverlap", -100, 100]
|
|
3243
3243
|
]) {
|
|
3244
|
-
const value =
|
|
3244
|
+
const value = options2[field];
|
|
3245
3245
|
if (value !== void 0 && (!Number.isInteger(value) || value < min || value > max))
|
|
3246
3246
|
throw new RangeError(`${field} must be an integer from ${min} to ${max}`);
|
|
3247
3247
|
}
|
|
@@ -4527,8 +4527,8 @@ function titleXml(context, title) {
|
|
|
4527
4527
|
chartTextXml(context, tx, false) + layoutXml(context, title.layout) + valXml("overlay", title.overlay) + shapePropertiesXml(context, title.spPr) + textBodyXml(context, title.txPr) + raw(context, title.extLst)
|
|
4528
4528
|
);
|
|
4529
4529
|
}
|
|
4530
|
-
function labelOptionsXml(context,
|
|
4531
|
-
return numberFormatXml(
|
|
4530
|
+
function labelOptionsXml(context, options2) {
|
|
4531
|
+
return numberFormatXml(options2.numberFormat) + shapePropertiesXml(context, options2.spPr) + textBodyXml(context, options2.txPr) + valXml("dLblPos", options2.position) + valXml("showLegendKey", options2.showLegendKey) + valXml("showVal", options2.showValue) + valXml("showCatName", options2.showCategoryName) + valXml("showSerName", options2.showSeriesName) + valXml("showPercent", options2.showPercent) + valXml("showBubbleSize", options2.showBubbleSize) + (options2.separator === void 0 ? "" : textElement("separator", options2.separator));
|
|
4532
4532
|
}
|
|
4533
4533
|
function labelXml(context, label) {
|
|
4534
4534
|
return elementXml(
|
|
@@ -4698,7 +4698,7 @@ function styleXml(context, space) {
|
|
|
4698
4698
|
);
|
|
4699
4699
|
}
|
|
4700
4700
|
var relationship = (local, id, content = "") => id === void 0 ? "" : elementXml(local, content, ` r:id="${escapeAttribute(id)}"`);
|
|
4701
|
-
function writeChartSpace(space,
|
|
4701
|
+
function writeChartSpace(space, options2 = {}) {
|
|
4702
4702
|
const bindings = new Map(CHART_ROOT_BINDINGS);
|
|
4703
4703
|
for (const { prefix, uri } of space.namespaceDeclarations ?? [])
|
|
4704
4704
|
if (!bindings.has(prefix) && /^[A-Za-z_][\w.-]*$/.test(prefix)) bindings.set(prefix, uri);
|
|
@@ -4713,10 +4713,204 @@ function writeChartSpace(space, options = {}) {
|
|
|
4713
4713
|
space.externalDataRelId,
|
|
4714
4714
|
valXml("autoUpdate", space.externalDataAutoUpdate)
|
|
4715
4715
|
) + raw(context, space.printSettings) + relationship("userShapes", space.userShapesRelId) + raw(context, space.extLst);
|
|
4716
|
-
const breakAfter =
|
|
4716
|
+
const breakAfter = options2.declarationBreak ?? "\r\n";
|
|
4717
4717
|
return `${DECLARATION2}${breakAfter}<c:chartSpace${declarations}>${body}</c:chartSpace>`;
|
|
4718
4718
|
}
|
|
4719
4719
|
|
|
4720
|
+
// chart/marker-shape.ts
|
|
4721
|
+
var CHART_PX_PER_PT = 4 / 3;
|
|
4722
|
+
var DEFAULT_MARKER_OUTLINE_PT = 0.75;
|
|
4723
|
+
function markerOutline(marker) {
|
|
4724
|
+
if (!marker.stroke) {
|
|
4725
|
+
return {};
|
|
4726
|
+
}
|
|
4727
|
+
return {
|
|
4728
|
+
stroke: marker.stroke,
|
|
4729
|
+
strokeWidth: (marker.strokeWidth ?? DEFAULT_MARKER_OUTLINE_PT) * CHART_PX_PER_PT
|
|
4730
|
+
};
|
|
4731
|
+
}
|
|
4732
|
+
var AUTOMATIC_MARKER_CYCLE = [
|
|
4733
|
+
"diamond",
|
|
4734
|
+
"square",
|
|
4735
|
+
"triangle",
|
|
4736
|
+
"x",
|
|
4737
|
+
"star",
|
|
4738
|
+
"circle",
|
|
4739
|
+
"plus",
|
|
4740
|
+
"dot",
|
|
4741
|
+
"dash"
|
|
4742
|
+
];
|
|
4743
|
+
function automaticMarkerSymbol(seriesIdx) {
|
|
4744
|
+
const length = AUTOMATIC_MARKER_CYCLE.length;
|
|
4745
|
+
const normalized = (Math.trunc(seriesIdx) % length + length) % length;
|
|
4746
|
+
return AUTOMATIC_MARKER_CYCLE[Number.isFinite(normalized) ? normalized : 0];
|
|
4747
|
+
}
|
|
4748
|
+
function markerRadius(size, defaultRadius) {
|
|
4749
|
+
if (size === void 0 || !Number.isFinite(size) || size <= 0) {
|
|
4750
|
+
return defaultRadius;
|
|
4751
|
+
}
|
|
4752
|
+
return size / 2;
|
|
4753
|
+
}
|
|
4754
|
+
function polygonPoints(vertices) {
|
|
4755
|
+
return vertices.map(([x, y]) => `${x.toFixed(2)},${y.toFixed(2)}`).join(" ");
|
|
4756
|
+
}
|
|
4757
|
+
function starVertices(cx2, cy, r) {
|
|
4758
|
+
const inner = r * 0.5;
|
|
4759
|
+
const out = [];
|
|
4760
|
+
for (let i = 0; i < 10; i++) {
|
|
4761
|
+
const radius = i % 2 === 0 ? r : inner;
|
|
4762
|
+
const angle = -Math.PI / 2 + Math.PI * i / 5;
|
|
4763
|
+
out.push([cx2 + radius * Math.cos(angle), cy + radius * Math.sin(angle)]);
|
|
4764
|
+
}
|
|
4765
|
+
return out;
|
|
4766
|
+
}
|
|
4767
|
+
function rectPolygon(x, y, w, h) {
|
|
4768
|
+
return polygonPoints([
|
|
4769
|
+
[x, y],
|
|
4770
|
+
[x + w, y],
|
|
4771
|
+
[x + w, y + h],
|
|
4772
|
+
[x, y + h]
|
|
4773
|
+
]);
|
|
4774
|
+
}
|
|
4775
|
+
function buildMarkerPrimitive(input) {
|
|
4776
|
+
const { symbol, cx: cx2, cy, fill } = input;
|
|
4777
|
+
const part = input.part === void 0 ? {} : { part: input.part };
|
|
4778
|
+
if (symbol === "none") {
|
|
4779
|
+
return null;
|
|
4780
|
+
}
|
|
4781
|
+
const r = markerRadius(input.size, input.defaultRadius);
|
|
4782
|
+
const outline = input.stroke ? {
|
|
4783
|
+
stroke: input.stroke,
|
|
4784
|
+
strokeWidth: input.strokeWidth ?? DEFAULT_MARKER_OUTLINE_PT * CHART_PX_PER_PT
|
|
4785
|
+
} : void 0;
|
|
4786
|
+
const polygonStroke = outline ?? { stroke: fill, strokeWidth: 0 };
|
|
4787
|
+
const lineStroke = input.stroke ?? fill;
|
|
4788
|
+
switch (symbol) {
|
|
4789
|
+
case "square":
|
|
4790
|
+
case "dash": {
|
|
4791
|
+
const h = symbol === "dash" ? r * 0.64 : r * 2;
|
|
4792
|
+
const y = cy - h / 2;
|
|
4793
|
+
if (outline) {
|
|
4794
|
+
return {
|
|
4795
|
+
kind: "polygon",
|
|
4796
|
+
points: rectPolygon(cx2 - r, y, r * 2, h),
|
|
4797
|
+
fill,
|
|
4798
|
+
...outline,
|
|
4799
|
+
...part
|
|
4800
|
+
};
|
|
4801
|
+
}
|
|
4802
|
+
return { kind: "rect", x: cx2 - r, y, w: r * 2, h, fill, ...part };
|
|
4803
|
+
}
|
|
4804
|
+
case "diamond":
|
|
4805
|
+
return {
|
|
4806
|
+
kind: "polygon",
|
|
4807
|
+
points: polygonPoints([
|
|
4808
|
+
[cx2, cy - r],
|
|
4809
|
+
[cx2 + r, cy],
|
|
4810
|
+
[cx2, cy + r],
|
|
4811
|
+
[cx2 - r, cy]
|
|
4812
|
+
]),
|
|
4813
|
+
fill,
|
|
4814
|
+
...polygonStroke,
|
|
4815
|
+
...part
|
|
4816
|
+
};
|
|
4817
|
+
case "triangle":
|
|
4818
|
+
return {
|
|
4819
|
+
kind: "polygon",
|
|
4820
|
+
points: polygonPoints([
|
|
4821
|
+
[cx2, cy - r],
|
|
4822
|
+
[cx2 + r * 0.9, cy + r * 0.75],
|
|
4823
|
+
[cx2 - r * 0.9, cy + r * 0.75]
|
|
4824
|
+
]),
|
|
4825
|
+
fill,
|
|
4826
|
+
...polygonStroke,
|
|
4827
|
+
...part
|
|
4828
|
+
};
|
|
4829
|
+
case "star":
|
|
4830
|
+
return {
|
|
4831
|
+
kind: "polygon",
|
|
4832
|
+
points: polygonPoints(starVertices(cx2, cy, r)),
|
|
4833
|
+
fill,
|
|
4834
|
+
...polygonStroke,
|
|
4835
|
+
...part
|
|
4836
|
+
};
|
|
4837
|
+
case "plus":
|
|
4838
|
+
return {
|
|
4839
|
+
kind: "path",
|
|
4840
|
+
d: `M${(cx2 - r).toFixed(2)},${cy.toFixed(2)} L${(cx2 + r).toFixed(2)},${cy.toFixed(2)} M${cx2.toFixed(2)},${(cy - r).toFixed(2)} L${cx2.toFixed(2)},${(cy + r).toFixed(2)}`,
|
|
4841
|
+
fill: "none",
|
|
4842
|
+
stroke: lineStroke,
|
|
4843
|
+
strokeWidth: Math.max(1, r * 0.4),
|
|
4844
|
+
...part
|
|
4845
|
+
};
|
|
4846
|
+
case "x":
|
|
4847
|
+
return {
|
|
4848
|
+
kind: "path",
|
|
4849
|
+
d: `M${(cx2 - r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx2 + r).toFixed(2)},${(cy + r).toFixed(2)} M${(cx2 + r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx2 - r).toFixed(2)},${(cy + r).toFixed(2)}`,
|
|
4850
|
+
fill: "none",
|
|
4851
|
+
stroke: lineStroke,
|
|
4852
|
+
strokeWidth: Math.max(1, r * 0.4),
|
|
4853
|
+
...part
|
|
4854
|
+
};
|
|
4855
|
+
case "dot":
|
|
4856
|
+
return { kind: "circle", cx: cx2, cy, r: Math.max(r * 0.6, 1), fill, ...part, ...outline };
|
|
4857
|
+
default:
|
|
4858
|
+
return { kind: "circle", cx: cx2, cy, r, fill, ...part, ...outline };
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
|
|
4862
|
+
// chart/render/chart-view-markers.ts
|
|
4863
|
+
function summaryMarkers(source, group2, seriesPosition) {
|
|
4864
|
+
if (!["line", "scatter", "radar"].includes(group2.kind)) return {};
|
|
4865
|
+
const enabled = group2.kind === "line" ? group2.marker === true : group2.kind === "radar" ? group2.radarStyle === "marker" : !["line", "smooth", "none"].includes(group2.scatterStyle ?? "marker");
|
|
4866
|
+
const symbol = source.marker?.symbol;
|
|
4867
|
+
const marker = {
|
|
4868
|
+
...source.marker,
|
|
4869
|
+
symbol: symbol && symbol !== "auto" ? symbol : source.marker || enabled ? automaticMarkerSymbol(source.index ?? seriesPosition) : "none"
|
|
4870
|
+
};
|
|
4871
|
+
const pointMarkers = {};
|
|
4872
|
+
for (const point of source.dataPoints) {
|
|
4873
|
+
if (point.index === void 0 || !point.marker) continue;
|
|
4874
|
+
const override = point.marker;
|
|
4875
|
+
pointMarkers[point.index] = {
|
|
4876
|
+
...marker,
|
|
4877
|
+
...override,
|
|
4878
|
+
...override.symbol === "auto" || !source.marker && override.symbol === void 0 ? { symbol: automaticMarkerSymbol(source.index ?? seriesPosition) } : {},
|
|
4879
|
+
...marker.spPr || override.spPr ? {
|
|
4880
|
+
spPr: {
|
|
4881
|
+
...marker.spPr,
|
|
4882
|
+
...override.spPr,
|
|
4883
|
+
...marker.spPr?.line || override.spPr?.line ? { line: { ...marker.spPr?.line, ...override.spPr?.line } } : {}
|
|
4884
|
+
}
|
|
4885
|
+
} : {}
|
|
4886
|
+
};
|
|
4887
|
+
}
|
|
4888
|
+
return { marker, ...Object.keys(pointMarkers).length ? { pointMarkers } : {} };
|
|
4889
|
+
}
|
|
4890
|
+
function seriesMarkerViews(source, drawingColor) {
|
|
4891
|
+
const fillColor = (fill) => fill?.kind === "none" ? "none" : fill?.kind === "solid" ? drawingColor(fill.color) : void 0;
|
|
4892
|
+
const resolve = (marker) => {
|
|
4893
|
+
const fill = fillColor(marker.spPr?.fill);
|
|
4894
|
+
const stroke = fillColor(marker.spPr?.line?.fill);
|
|
4895
|
+
const width = marker.spPr?.line?.widthEmu;
|
|
4896
|
+
return {
|
|
4897
|
+
...marker.symbol !== void 0 ? { symbol: marker.symbol } : {},
|
|
4898
|
+
...marker.size !== void 0 ? { size: marker.size } : {},
|
|
4899
|
+
...fill !== void 0 ? { fill } : {},
|
|
4900
|
+
...stroke !== void 0 ? { stroke } : {},
|
|
4901
|
+
...width !== void 0 ? { strokeWidth: width / 9525 } : {}
|
|
4902
|
+
};
|
|
4903
|
+
};
|
|
4904
|
+
return {
|
|
4905
|
+
...source.marker ? { marker: resolve(source.marker) } : {},
|
|
4906
|
+
...source.pointMarkers ? {
|
|
4907
|
+
pointMarkers: Object.fromEntries(
|
|
4908
|
+
Object.entries(source.pointMarkers).map(([i, marker]) => [i, resolve(marker)])
|
|
4909
|
+
)
|
|
4910
|
+
} : {}
|
|
4911
|
+
};
|
|
4912
|
+
}
|
|
4913
|
+
|
|
4720
4914
|
// chart/render/summary-analysis.ts
|
|
4721
4915
|
function summaryTrendline(source) {
|
|
4722
4916
|
const kind = chartTrendlineKind(source.trendlineType);
|
|
@@ -4758,17 +4952,17 @@ function summaryAnalysis(series) {
|
|
|
4758
4952
|
}
|
|
4759
4953
|
|
|
4760
4954
|
// chart/render/summary-labels.ts
|
|
4761
|
-
function level(
|
|
4955
|
+
function level(options2, custom) {
|
|
4762
4956
|
const out = {};
|
|
4763
|
-
if (
|
|
4764
|
-
if (
|
|
4765
|
-
if (
|
|
4766
|
-
if (
|
|
4767
|
-
if (
|
|
4768
|
-
if (
|
|
4769
|
-
if (
|
|
4770
|
-
if (
|
|
4771
|
-
if (
|
|
4957
|
+
if (options2.deleted !== void 0) out.deleted = options2.deleted;
|
|
4958
|
+
if (options2.showValue !== void 0) out.showValue = options2.showValue;
|
|
4959
|
+
if (options2.showCategoryName !== void 0) out.showCategory = options2.showCategoryName;
|
|
4960
|
+
if (options2.showSeriesName !== void 0) out.showSeriesName = options2.showSeriesName;
|
|
4961
|
+
if (options2.showPercent !== void 0) out.showPercent = options2.showPercent;
|
|
4962
|
+
if (options2.showBubbleSize !== void 0) out.showBubbleSize = options2.showBubbleSize;
|
|
4963
|
+
if (options2.separator !== void 0) out.separator = options2.separator;
|
|
4964
|
+
if (options2.position) out.position = options2.position;
|
|
4965
|
+
if (options2.numberFormat?.formatCode) out.numberFormat = options2.numberFormat.formatCode;
|
|
4772
4966
|
if (custom?.text !== void 0) out.text = custom.text;
|
|
4773
4967
|
return out;
|
|
4774
4968
|
}
|
|
@@ -4875,7 +5069,10 @@ function extraGroups(chartSpace, firstType) {
|
|
|
4875
5069
|
const type = group2.kind === "bar" ? "column" : group2.kind;
|
|
4876
5070
|
const entry3 = {
|
|
4877
5071
|
chartType: type,
|
|
4878
|
-
series: group2.series.map((source) =>
|
|
5072
|
+
series: group2.series.map((source, index) => ({
|
|
5073
|
+
...chartSummarySeries(source, type, group2.dataLabels),
|
|
5074
|
+
...summaryMarkers(source, group2, index)
|
|
5075
|
+
})),
|
|
4879
5076
|
secondary: valueAxisId(chartSpace, group2.axisIds) !== primary
|
|
4880
5077
|
};
|
|
4881
5078
|
if (group2.grouping && GROUPINGS.has(group2.grouping))
|
|
@@ -4893,13 +5090,16 @@ function chartSummaryFromSpace(chartSpace, extras = {}) {
|
|
|
4893
5090
|
const group2 = chartSpace.plotArea.groups[0];
|
|
4894
5091
|
let chartType = group2 ? GROUP_TYPES[group2.kind] : "column";
|
|
4895
5092
|
if (chartType === "bar" && group2?.barDirection !== "bar") chartType = "column";
|
|
4896
|
-
const series = (group2?.series ?? []).map(
|
|
4897
|
-
|
|
4898
|
-
|
|
5093
|
+
const series = (group2?.series ?? []).map((source, index) => ({
|
|
5094
|
+
...chartSummarySeries(source, chartType, group2?.dataLabels),
|
|
5095
|
+
...group2 ? summaryMarkers(source, group2, index) : {}
|
|
5096
|
+
}));
|
|
4899
5097
|
const summary = {
|
|
4900
5098
|
chartType,
|
|
4901
5099
|
series,
|
|
4902
|
-
showLegend: chartSpace.legend !== void 0
|
|
5100
|
+
showLegend: chartSpace.legend !== void 0,
|
|
5101
|
+
axes: chartSpace.plotArea.axes,
|
|
5102
|
+
axisIds: group2?.axisIds ?? []
|
|
4903
5103
|
};
|
|
4904
5104
|
const combined = extraGroups(chartSpace, chartType);
|
|
4905
5105
|
if (combined.length) summary.extraGroups = combined;
|
|
@@ -5419,7 +5619,7 @@ function chartTextAttributes(model, part, fallbackSize = FONT_SIZE) {
|
|
|
5419
5619
|
function chartStroke(model, part) {
|
|
5420
5620
|
const entry3 = model.appearance?.[part];
|
|
5421
5621
|
return {
|
|
5422
|
-
color: entry3?.axisVisible === false ? "none" : entry3?.lineColor ?? (part
|
|
5622
|
+
color: entry3?.axisVisible === false ? "none" : entry3?.lineColor ?? (part.startsWith("gridline") ? GRID_COLOR : AXIS_COLOR),
|
|
5423
5623
|
width: entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth)
|
|
5424
5624
|
};
|
|
5425
5625
|
}
|
|
@@ -5710,6 +5910,60 @@ function scatterAnalysis(model, px, py, out) {
|
|
|
5710
5910
|
});
|
|
5711
5911
|
}
|
|
5712
5912
|
|
|
5913
|
+
// chart/render/chart-svg-markers.ts
|
|
5914
|
+
function chartMarkerRadius(series, index, defaultRadius = 3) {
|
|
5915
|
+
const marker = { ...series.marker, ...series.pointMarkers?.[index] };
|
|
5916
|
+
if (marker.symbol === "none") return 0;
|
|
5917
|
+
const radius = markerRadius(marker.size, defaultRadius);
|
|
5918
|
+
return marker.symbol === "dot" ? Math.max(radius * 0.6, 1) : radius;
|
|
5919
|
+
}
|
|
5920
|
+
function chartSeriesMarkerSvg(series, index, cx2, cy, defaultRadius = 3) {
|
|
5921
|
+
const marker = { ...series.marker, ...series.pointMarkers?.[index] };
|
|
5922
|
+
const primitive = buildMarkerPrimitive({
|
|
5923
|
+
...marker,
|
|
5924
|
+
symbol: marker.symbol,
|
|
5925
|
+
size: marker.size,
|
|
5926
|
+
cx: cx2,
|
|
5927
|
+
cy,
|
|
5928
|
+
fill: marker.fill ?? series.pointColors?.[index] ?? series.color,
|
|
5929
|
+
defaultRadius
|
|
5930
|
+
});
|
|
5931
|
+
if (!primitive) return "";
|
|
5932
|
+
let geometry;
|
|
5933
|
+
switch (primitive.kind) {
|
|
5934
|
+
case "circle":
|
|
5935
|
+
geometry = `cx="${n(primitive.cx)}" cy="${n(primitive.cy)}" r="${n(primitive.r)}"`;
|
|
5936
|
+
break;
|
|
5937
|
+
case "rect":
|
|
5938
|
+
geometry = `x="${n(primitive.x)}" y="${n(primitive.y)}" width="${n(primitive.w)}" height="${n(primitive.h)}"`;
|
|
5939
|
+
break;
|
|
5940
|
+
case "path":
|
|
5941
|
+
geometry = `d="${esc(primitive.d)}"`;
|
|
5942
|
+
break;
|
|
5943
|
+
case "polygon":
|
|
5944
|
+
geometry = `points="${esc(primitive.points)}"`;
|
|
5945
|
+
break;
|
|
5946
|
+
}
|
|
5947
|
+
const outline = primitive.stroke ? ` stroke="${esc(primitive.stroke)}" stroke-width="${n(primitive.strokeWidth ?? 1)}"` : "";
|
|
5948
|
+
const filter = series.shadowFilter ? ` filter="${esc(series.shadowFilter)}"` : "";
|
|
5949
|
+
return `<${primitive.kind} ${geometry} fill="${esc(primitive.fill)}"${outline}${filter}/>`;
|
|
5950
|
+
}
|
|
5951
|
+
|
|
5952
|
+
// chart/line-dash.ts
|
|
5953
|
+
function chartLineDashArray(style, width) {
|
|
5954
|
+
if (!style || style === "solid") {
|
|
5955
|
+
return void 0;
|
|
5956
|
+
}
|
|
5957
|
+
const unit = Math.max(width, 1);
|
|
5958
|
+
if (style === "dot" || style === "sysDot") {
|
|
5959
|
+
return `${unit} ${unit * 2}`;
|
|
5960
|
+
}
|
|
5961
|
+
if (style === "lgDash") {
|
|
5962
|
+
return `${unit * 6} ${unit * 3}`;
|
|
5963
|
+
}
|
|
5964
|
+
return `${unit * 3} ${unit * 2}`;
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5713
5967
|
// chart/render/chart-scale.ts
|
|
5714
5968
|
var clean = (n2) => Number(n2.toPrecision(12));
|
|
5715
5969
|
function* units(raw2) {
|
|
@@ -5720,14 +5974,14 @@ function* units(raw2) {
|
|
|
5720
5974
|
exp++;
|
|
5721
5975
|
}
|
|
5722
5976
|
}
|
|
5723
|
-
function niceScale(dataMin, dataMax,
|
|
5724
|
-
const maxIntervals = Math.max(1,
|
|
5977
|
+
function niceScale(dataMin, dataMax, options2 = {}) {
|
|
5978
|
+
const maxIntervals = Math.max(1, options2.maxIntervals ?? 10);
|
|
5725
5979
|
let lo = Number.isFinite(dataMin) ? dataMin : 0;
|
|
5726
5980
|
let hi = Number.isFinite(dataMax) ? dataMax : 0;
|
|
5727
5981
|
if (lo > hi) [lo, hi] = [hi, lo];
|
|
5728
5982
|
if (lo === hi) {
|
|
5729
5983
|
if (lo === 0) hi = 1;
|
|
5730
|
-
else if (
|
|
5984
|
+
else if (options2.noZero) {
|
|
5731
5985
|
const pad = Math.abs(lo) * 0.1 || 1;
|
|
5732
5986
|
lo -= pad;
|
|
5733
5987
|
hi += pad;
|
|
@@ -5736,7 +5990,7 @@ function niceScale(dataMin, dataMax, options = {}) {
|
|
|
5736
5990
|
}
|
|
5737
5991
|
let fixedLo = false;
|
|
5738
5992
|
let fixedHi = false;
|
|
5739
|
-
if (!
|
|
5993
|
+
if (!options2.noZero) {
|
|
5740
5994
|
if (lo >= 0 && hi - lo >= hi / 6) {
|
|
5741
5995
|
lo = 0;
|
|
5742
5996
|
fixedLo = true;
|
|
@@ -5776,6 +6030,329 @@ function formatAxisValue(value, percent = false) {
|
|
|
5776
6030
|
return `${v < 0 ? "-" : ""}${grouped}${frac ? `.${frac}` : ""}`;
|
|
5777
6031
|
}
|
|
5778
6032
|
|
|
6033
|
+
// chart/render/chart-svg-axes.ts
|
|
6034
|
+
function axisTickText(value, axis, percent = false) {
|
|
6035
|
+
return formatChartNumber(value, axis?.source.numberFormat?.formatCode) ?? formatAxisValue(value, percent);
|
|
6036
|
+
}
|
|
6037
|
+
function axisLine(model, axis, part, x1, y1, x2, y2) {
|
|
6038
|
+
if (axis?.source.deleted) return "";
|
|
6039
|
+
return styledAxisLine(x1, y1, x2, y2, axis?.line, chartStroke(model, part));
|
|
6040
|
+
}
|
|
6041
|
+
function styledAxisLine(x1, y1, x2, y2, paint2, fallback) {
|
|
6042
|
+
const color = paint2?.color ?? fallback.color;
|
|
6043
|
+
const width = paint2?.width ?? fallback.width;
|
|
6044
|
+
if (color === "none" || width === 0) return "";
|
|
6045
|
+
const dash = chartLineDashArray(paint2?.dash, width);
|
|
6046
|
+
return line(x1, y1, x2, y2, esc(color), width).replace(
|
|
6047
|
+
"/>",
|
|
6048
|
+
dash ? ` stroke-dasharray="${dash}"/>` : "/>"
|
|
6049
|
+
);
|
|
6050
|
+
}
|
|
6051
|
+
function axisGridlines(model, axis, ticks, position, plot, vertical) {
|
|
6052
|
+
const draw2 = (values, paint2, minor2) => {
|
|
6053
|
+
const fallback = chartStroke(model, minor2 ? "gridlineMinor" : "gridlineMajor");
|
|
6054
|
+
return values.map((value) => {
|
|
6055
|
+
const p = position(value);
|
|
6056
|
+
return vertical ? styledAxisLine(p, plot.y, p, plot.y + plot.h, paint2, fallback) : styledAxisLine(plot.x, p, plot.x + plot.w, p, paint2, fallback);
|
|
6057
|
+
}).join("");
|
|
6058
|
+
};
|
|
6059
|
+
const major = !axis || axis.source.majorGridlines ? draw2(ticks, axis?.majorGrid, false) : "";
|
|
6060
|
+
const minor = axis?.source.minorGridlines ? draw2(axis.minorTicks, axis.minorGrid, true) : "";
|
|
6061
|
+
return major + minor;
|
|
6062
|
+
}
|
|
6063
|
+
|
|
6064
|
+
// chart/axis-range-auto.ts
|
|
6065
|
+
function computeAxisValueRange(series, plotHeightPx) {
|
|
6066
|
+
let dataMin = Number.POSITIVE_INFINITY, dataMax = Number.NEGATIVE_INFINITY;
|
|
6067
|
+
for (const item of series) {
|
|
6068
|
+
for (const value of item.values) {
|
|
6069
|
+
if (value !== null && Number.isFinite(value) && value < dataMin) {
|
|
6070
|
+
dataMin = value;
|
|
6071
|
+
}
|
|
6072
|
+
if (value !== null && Number.isFinite(value) && value > dataMax) {
|
|
6073
|
+
dataMax = value;
|
|
6074
|
+
}
|
|
6075
|
+
}
|
|
6076
|
+
}
|
|
6077
|
+
if (dataMin === Number.POSITIVE_INFINITY) {
|
|
6078
|
+
return { min: 0, max: 1, span: 1 };
|
|
6079
|
+
}
|
|
6080
|
+
const { min, max, majorUnit } = niceValueAxisBounds(
|
|
6081
|
+
dataMin,
|
|
6082
|
+
dataMax,
|
|
6083
|
+
plotHeightPx !== void 0 ? axisTargetIntervals(plotHeightPx) : void 0
|
|
6084
|
+
);
|
|
6085
|
+
return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
|
|
6086
|
+
}
|
|
6087
|
+
function computeAxisStackedValueRange(series, catCount, plotHeightPx) {
|
|
6088
|
+
let maxSum = 0, minSum = 0;
|
|
6089
|
+
for (let ci = 0; ci < catCount; ci++) {
|
|
6090
|
+
let pos = 0, neg = 0;
|
|
6091
|
+
for (const s of series) {
|
|
6092
|
+
const v = s.values[ci] ?? 0;
|
|
6093
|
+
if (v >= 0) {
|
|
6094
|
+
pos += v;
|
|
6095
|
+
} else {
|
|
6096
|
+
neg += v;
|
|
6097
|
+
}
|
|
6098
|
+
}
|
|
6099
|
+
maxSum = Math.max(maxSum, pos);
|
|
6100
|
+
minSum = Math.min(minSum, neg);
|
|
6101
|
+
}
|
|
6102
|
+
const { min, max, majorUnit } = niceValueAxisBounds(
|
|
6103
|
+
Math.min(minSum, 0),
|
|
6104
|
+
Math.max(maxSum, 0),
|
|
6105
|
+
plotHeightPx !== void 0 ? axisTargetIntervals(plotHeightPx) : void 0
|
|
6106
|
+
);
|
|
6107
|
+
return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
|
|
6108
|
+
}
|
|
6109
|
+
|
|
6110
|
+
// chart/axis-range.ts
|
|
6111
|
+
function computeLogValueRange(series, logBase) {
|
|
6112
|
+
const allValues = series.flatMap((item) => item.values).filter((value) => value !== null && Number.isFinite(value) && value > 0);
|
|
6113
|
+
if (allValues.length === 0) {
|
|
6114
|
+
return { min: 1, max: logBase, span: 1, logScale: true, logBase };
|
|
6115
|
+
}
|
|
6116
|
+
const dataMin = Math.min(...allValues);
|
|
6117
|
+
const dataMax = Math.max(...allValues);
|
|
6118
|
+
const logMin = Math.floor(Math.log(dataMin) / Math.log(logBase));
|
|
6119
|
+
const logMax = Math.ceil(Math.log(dataMax) / Math.log(logBase));
|
|
6120
|
+
const min = logBase ** logMin;
|
|
6121
|
+
const max = logBase ** Math.max(logMax, logMin + 1);
|
|
6122
|
+
return {
|
|
6123
|
+
min,
|
|
6124
|
+
max,
|
|
6125
|
+
span: Math.max(Math.log(max) / Math.log(logBase) - Math.log(min) / Math.log(logBase), 1),
|
|
6126
|
+
logScale: true,
|
|
6127
|
+
logBase
|
|
6128
|
+
};
|
|
6129
|
+
}
|
|
6130
|
+
function computeValueRangeForAxis(series, axis, plotHeightPx) {
|
|
6131
|
+
const requestedLogBase = axis?.logBase ?? 10;
|
|
6132
|
+
const logBase = axis?.logScale && Number.isFinite(requestedLogBase) && requestedLogBase > 1 ? requestedLogBase : axis?.logScale ? 10 : void 0;
|
|
6133
|
+
const automatic = logBase ? computeLogValueRange(series, logBase) : computeAxisValueRange(series, plotHeightPx);
|
|
6134
|
+
return withAxisBounds(automatic, axis, logBase);
|
|
6135
|
+
}
|
|
6136
|
+
function computeStackedValueRangeForAxis(series, catCount, axis, isPercent, plotSizePx) {
|
|
6137
|
+
if (isPercent) {
|
|
6138
|
+
return {
|
|
6139
|
+
...percentStackedRange(series, catCount, plotSizePx),
|
|
6140
|
+
...axis?.orientation === "maxMin" ? { reverseOrder: true } : {}
|
|
6141
|
+
};
|
|
6142
|
+
}
|
|
6143
|
+
return withAxisBounds(computeAxisStackedValueRange(series, catCount, plotSizePx), axis);
|
|
6144
|
+
}
|
|
6145
|
+
function percentStackedRange(series, catCount, plotSizePx) {
|
|
6146
|
+
const shares = series.map((entry3) => ({
|
|
6147
|
+
...entry3,
|
|
6148
|
+
values: Array.from({ length: catCount }, (_, ci) => {
|
|
6149
|
+
const total = series.reduce((sum, s) => sum + Math.abs(s.values[ci] ?? 0), 0);
|
|
6150
|
+
return total > 0 ? (entry3.values[ci] ?? 0) / total * 100 : 0;
|
|
6151
|
+
})
|
|
6152
|
+
}));
|
|
6153
|
+
const automatic = computeAxisStackedValueRange(shares, catCount, plotSizePx);
|
|
6154
|
+
if (automatic.min >= 0) {
|
|
6155
|
+
return { min: 0, max: 100, span: 100 };
|
|
6156
|
+
}
|
|
6157
|
+
const min = Math.max(automatic.min, -100);
|
|
6158
|
+
const unit = automatic.majorUnit;
|
|
6159
|
+
return {
|
|
6160
|
+
min,
|
|
6161
|
+
max: 100,
|
|
6162
|
+
span: 100 - min,
|
|
6163
|
+
...unit !== void 0 && 100 % unit === 0 && min % unit === 0 ? { majorUnit: unit } : {}
|
|
6164
|
+
};
|
|
6165
|
+
}
|
|
6166
|
+
function withAxisBounds(automatic, axis, logBase) {
|
|
6167
|
+
const validMin = typeof axis?.min === "number" && Number.isFinite(axis.min) && (!logBase || axis.min > 0) ? axis.min : void 0;
|
|
6168
|
+
const validMax = typeof axis?.max === "number" && Number.isFinite(axis.max) && (!logBase || axis.max > 0) ? axis.max : void 0;
|
|
6169
|
+
const min = validMin ?? automatic.min;
|
|
6170
|
+
let max = validMax ?? automatic.max;
|
|
6171
|
+
const majorUnit = validMin === void 0 && validMax === void 0 ? automatic.majorUnit : void 0;
|
|
6172
|
+
if (max <= min) {
|
|
6173
|
+
max = logBase ? min * logBase : min + 1;
|
|
6174
|
+
}
|
|
6175
|
+
const span = logBase ? Math.log(max) / Math.log(logBase) - Math.log(min) / Math.log(logBase) : max - min;
|
|
6176
|
+
return {
|
|
6177
|
+
min,
|
|
6178
|
+
max,
|
|
6179
|
+
span: Math.max(span, Number.EPSILON),
|
|
6180
|
+
...majorUnit !== void 0 ? { majorUnit } : {},
|
|
6181
|
+
...logBase ? { logScale: true, logBase } : {},
|
|
6182
|
+
...axis?.orientation === "maxMin" ? { reverseOrder: true } : {}
|
|
6183
|
+
};
|
|
6184
|
+
}
|
|
6185
|
+
function valueToYLog(val, range, topY, bottomY) {
|
|
6186
|
+
const base = range.logBase ?? 10;
|
|
6187
|
+
const logValue = Math.log(Math.max(val, range.min)) / Math.log(base);
|
|
6188
|
+
const logMin = Math.log(range.min) / Math.log(base);
|
|
6189
|
+
const ratio = (logValue - logMin) / range.span;
|
|
6190
|
+
return range.reverseOrder ? topY + ratio * (bottomY - topY) : bottomY - ratio * (bottomY - topY);
|
|
6191
|
+
}
|
|
6192
|
+
function findLogAxis(axes) {
|
|
6193
|
+
return axes?.find((axis) => axis.axisType === "valAx" && axis.logScale);
|
|
6194
|
+
}
|
|
6195
|
+
function computeValueRangeForChart(series, axes, plotHeightPx) {
|
|
6196
|
+
const primaryAxis = axes?.find((axis) => axis.axisType === "valAx" && axis.axPos === "l") ?? axes?.find((axis) => axis.axisType === "valAx" && axis.axPos !== "r");
|
|
6197
|
+
return computeValueRangeForAxis(series, primaryAxis, plotHeightPx);
|
|
6198
|
+
}
|
|
6199
|
+
|
|
6200
|
+
// chart/axis-ticks.ts
|
|
6201
|
+
var LOG_EXPONENT_TOLERANCE = 1e-12;
|
|
6202
|
+
function generateLogTicks(range) {
|
|
6203
|
+
if (!range.logScale || !range.logBase) {
|
|
6204
|
+
return [];
|
|
6205
|
+
}
|
|
6206
|
+
const base = range.logBase;
|
|
6207
|
+
const logMin = Math.log(range.min) / Math.log(base);
|
|
6208
|
+
const logMax = Math.log(range.max) / Math.log(base);
|
|
6209
|
+
const firstExponent = Math.ceil(logMin - LOG_EXPONENT_TOLERANCE);
|
|
6210
|
+
const lastExponent = Math.floor(logMax + LOG_EXPONENT_TOLERANCE);
|
|
6211
|
+
if (lastExponent < firstExponent) {
|
|
6212
|
+
return range.min === range.max ? [range.min] : [range.min, range.max];
|
|
6213
|
+
}
|
|
6214
|
+
return Array.from(
|
|
6215
|
+
{ length: lastExponent - firstExponent + 1 },
|
|
6216
|
+
(_unused, index) => base ** (firstExponent + index)
|
|
6217
|
+
);
|
|
6218
|
+
}
|
|
6219
|
+
function generateIntervalTicks(range, unit) {
|
|
6220
|
+
if (!Number.isFinite(unit) || unit <= 0 || range.logScale) {
|
|
6221
|
+
return [];
|
|
6222
|
+
}
|
|
6223
|
+
const tolerance = Math.max(1, Math.abs(range.min), Math.abs(range.max)) * 1e-12;
|
|
6224
|
+
const first2 = Math.ceil((range.min - tolerance) / unit);
|
|
6225
|
+
const last = Math.floor((range.max + tolerance) / unit);
|
|
6226
|
+
const count = Math.min(Math.max(last - first2 + 1, 0), 2e3);
|
|
6227
|
+
return Array.from({ length: count }, (_, index) => (first2 + index) * unit);
|
|
6228
|
+
}
|
|
6229
|
+
function generateAxisTicks(range, axis, defaultIntervals) {
|
|
6230
|
+
if (range.logScale && range.logBase) {
|
|
6231
|
+
return generateLogTicks(range);
|
|
6232
|
+
}
|
|
6233
|
+
const explicit = generateIntervalTicks(range, axis?.majorUnit ?? 0);
|
|
6234
|
+
if (explicit.length > 0) {
|
|
6235
|
+
return explicit;
|
|
6236
|
+
}
|
|
6237
|
+
const automatic = generateIntervalTicks(range, range.majorUnit ?? 0);
|
|
6238
|
+
if (automatic.length > 0) {
|
|
6239
|
+
return automatic;
|
|
6240
|
+
}
|
|
6241
|
+
return Array.from(
|
|
6242
|
+
{ length: defaultIntervals + 1 },
|
|
6243
|
+
(_, index) => range.min + range.span / defaultIntervals * index
|
|
6244
|
+
);
|
|
6245
|
+
}
|
|
6246
|
+
function generateMinorAxisTicks(range, axis) {
|
|
6247
|
+
const minor = generateIntervalTicks(range, axis?.minorUnit ?? 0);
|
|
6248
|
+
if (minor.length === 0) {
|
|
6249
|
+
return [];
|
|
6250
|
+
}
|
|
6251
|
+
const majorUnit = axis?.majorUnit;
|
|
6252
|
+
if (!majorUnit || !Number.isFinite(majorUnit) || majorUnit <= 0) {
|
|
6253
|
+
return minor;
|
|
6254
|
+
}
|
|
6255
|
+
const tolerance = Math.max(1, Math.abs(range.min), Math.abs(range.max)) * 1e-10;
|
|
6256
|
+
return minor.filter(
|
|
6257
|
+
(value) => Math.abs(value / majorUnit - Math.round(value / majorUnit)) > tolerance
|
|
6258
|
+
);
|
|
6259
|
+
}
|
|
6260
|
+
|
|
6261
|
+
// chart/render/chart-view-axes.ts
|
|
6262
|
+
function chartAxisRatio(value, scale, axis) {
|
|
6263
|
+
const range = axis?.range;
|
|
6264
|
+
const ratio = range?.logScale ? Math.log(Math.max(value, range.min) / range.min) / Math.log(range.max / range.min) : (value - scale.min) / (scale.max - scale.min || 1);
|
|
6265
|
+
return range?.reverseOrder ? 1 - ratio : ratio;
|
|
6266
|
+
}
|
|
6267
|
+
function chartAxisLabels(axis) {
|
|
6268
|
+
return axis?.source.deleted !== true && axis?.source.tickLabelPosition !== "none";
|
|
6269
|
+
}
|
|
6270
|
+
function options(axis) {
|
|
6271
|
+
return {
|
|
6272
|
+
...axis.scaling,
|
|
6273
|
+
...axis.scaling.logBase === void 0 ? {} : { logScale: true },
|
|
6274
|
+
...axis.majorUnit === void 0 ? {} : { majorUnit: axis.majorUnit },
|
|
6275
|
+
...axis.minorUnit === void 0 ? {} : { minorUnit: axis.minorUnit }
|
|
6276
|
+
};
|
|
6277
|
+
}
|
|
6278
|
+
function applyChartAxes(model, chart, color) {
|
|
6279
|
+
if (!chart.axes?.length) return;
|
|
6280
|
+
const axes = chart.axes;
|
|
6281
|
+
const linked = axes.filter((axis) => axis.id !== void 0 && chart.axisIds?.includes(axis.id));
|
|
6282
|
+
const candidates = linked.length ? linked : axes;
|
|
6283
|
+
const xy = model.type === "scatter" || model.type === "bubble";
|
|
6284
|
+
const value = candidates.find((axis) => axis.kind === "val" && !["b", "t"].includes(axis.position ?? "")) ?? candidates.find((axis) => axis.kind === "val");
|
|
6285
|
+
const category = candidates.find(
|
|
6286
|
+
(axis) => xy ? axis.kind === "val" && axis !== value : axis.kind === "cat" || axis.kind === "date"
|
|
6287
|
+
);
|
|
6288
|
+
const secondary = axes.find((axis) => axis.kind === "val" && axis !== value && axis !== category);
|
|
6289
|
+
const paint2 = (shape) => {
|
|
6290
|
+
const ln = shape?.line;
|
|
6291
|
+
const fill = ln?.fill;
|
|
6292
|
+
const resolved = fill?.kind === "none" ? "none" : color(fill?.kind === "solid" ? fill.color : void 0);
|
|
6293
|
+
return {
|
|
6294
|
+
...resolved === void 0 ? {} : { color: resolved },
|
|
6295
|
+
...ln?.widthEmu === void 0 ? {} : { width: ln.widthEmu / EMU_PER_PIXEL },
|
|
6296
|
+
...ln?.dash === void 0 ? {} : { dash: ln.dash }
|
|
6297
|
+
};
|
|
6298
|
+
};
|
|
6299
|
+
const bind = (axis, scale, values) => {
|
|
6300
|
+
const opts = options(axis);
|
|
6301
|
+
const automatic = opts.logScale ? computeLogValueRange(
|
|
6302
|
+
[{ values: values ?? [] }],
|
|
6303
|
+
opts.logBase && Number.isFinite(opts.logBase) && opts.logBase > 1 ? opts.logBase : 10
|
|
6304
|
+
) : {
|
|
6305
|
+
min: scale?.min ?? 0,
|
|
6306
|
+
max: scale?.max ?? 1,
|
|
6307
|
+
span: (scale?.max ?? 1) - (scale?.min ?? 0),
|
|
6308
|
+
...scale ? { majorUnit: scale.majorUnit } : {}
|
|
6309
|
+
};
|
|
6310
|
+
const logBase = automatic.logBase;
|
|
6311
|
+
const range = withAxisBounds(automatic, opts, logBase);
|
|
6312
|
+
if (scale) {
|
|
6313
|
+
scale.min = range.min;
|
|
6314
|
+
scale.max = range.max;
|
|
6315
|
+
scale.ticks = generateAxisTicks(range, opts, 5);
|
|
6316
|
+
}
|
|
6317
|
+
return {
|
|
6318
|
+
source: axis,
|
|
6319
|
+
range,
|
|
6320
|
+
minorTicks: generateMinorAxisTicks(range, opts),
|
|
6321
|
+
line: paint2(axis.spPr),
|
|
6322
|
+
majorGrid: paint2(axis.majorGridlinesSpPr),
|
|
6323
|
+
minorGrid: paint2(axis.minorGridlinesSpPr)
|
|
6324
|
+
};
|
|
6325
|
+
};
|
|
6326
|
+
const out = {};
|
|
6327
|
+
if (value)
|
|
6328
|
+
out.value = bind(
|
|
6329
|
+
value,
|
|
6330
|
+
model.valueAxis,
|
|
6331
|
+
[
|
|
6332
|
+
...model.series,
|
|
6333
|
+
...model.extraGroups?.filter((g) => !g.secondary).flatMap((g) => g.series) ?? []
|
|
6334
|
+
].flatMap((s) => s.values)
|
|
6335
|
+
);
|
|
6336
|
+
if (category)
|
|
6337
|
+
out.category = bind(
|
|
6338
|
+
category,
|
|
6339
|
+
model.xAxis ?? {
|
|
6340
|
+
min: 0,
|
|
6341
|
+
max: Math.max(1, model.categories.length - 1),
|
|
6342
|
+
majorUnit: 1,
|
|
6343
|
+
ticks: []
|
|
6344
|
+
},
|
|
6345
|
+
model.series.flatMap((s) => s.xValues ?? [])
|
|
6346
|
+
);
|
|
6347
|
+
if (secondary)
|
|
6348
|
+
out.secondary = bind(
|
|
6349
|
+
secondary,
|
|
6350
|
+
model.secondaryAxis,
|
|
6351
|
+
model.extraGroups?.filter((g) => g.secondary).flatMap((g) => g.series.flatMap((s) => s.values))
|
|
6352
|
+
);
|
|
6353
|
+
model.axes = out;
|
|
6354
|
+
}
|
|
6355
|
+
|
|
5779
6356
|
// chart/render/chart-view-analysis.ts
|
|
5780
6357
|
function strokeOf(line2, fallback, resolve) {
|
|
5781
6358
|
if (line2?.fill?.kind === "none") return void 0;
|
|
@@ -5825,15 +6402,15 @@ function seriesName(series, index, evaluateRef) {
|
|
|
5825
6402
|
const fromRef = resolveRef(series.nameRef, evaluateRef)?.map(toText).filter((t) => t !== "").join(" ");
|
|
5826
6403
|
return fromRef || series.name || `Series${index + 1}`;
|
|
5827
6404
|
}
|
|
5828
|
-
function seriesContext(chart, theme,
|
|
6405
|
+
function seriesContext(chart, theme, options2) {
|
|
5829
6406
|
const scheme = chartColorScheme(theme);
|
|
5830
6407
|
const resolver = { scheme: (name) => scheme[name] };
|
|
5831
6408
|
return {
|
|
5832
6409
|
theme,
|
|
5833
6410
|
scheme,
|
|
5834
6411
|
palette: chart.colorPalette === void 0 ? void 0 : findChartColorPalette(chart.colorPalette),
|
|
5835
|
-
evaluateRef:
|
|
5836
|
-
seriesColor:
|
|
6412
|
+
evaluateRef: options2.evaluateRef ?? (() => []),
|
|
6413
|
+
seriesColor: options2.seriesColor,
|
|
5837
6414
|
drawingColor: (color) => color && drawingColorCss(resolveDrawingColor(color, resolver, { transformOrder: "document" })),
|
|
5838
6415
|
gradient: (fill) => fill?.kind === "gradient" ? resolveChartGradient(
|
|
5839
6416
|
fill,
|
|
@@ -5859,7 +6436,11 @@ function seriesView(ctx, s, index, total, categoriesOf) {
|
|
|
5859
6436
|
})
|
|
5860
6437
|
);
|
|
5861
6438
|
if (Object.keys(points).length) view.pointGradients = points;
|
|
5862
|
-
Object.assign(
|
|
6439
|
+
Object.assign(
|
|
6440
|
+
view,
|
|
6441
|
+
analysisView(s, color, ctx.drawingColor),
|
|
6442
|
+
seriesMarkerViews(s, ctx.drawingColor)
|
|
6443
|
+
);
|
|
5863
6444
|
return view;
|
|
5864
6445
|
}
|
|
5865
6446
|
|
|
@@ -6159,11 +6740,11 @@ function histogramView(chart, model) {
|
|
|
6159
6740
|
const first2 = model.series[0];
|
|
6160
6741
|
if (!first2) return;
|
|
6161
6742
|
const raw2 = first2.values.map((v) => v ?? Number.NaN);
|
|
6162
|
-
const
|
|
6163
|
-
const bins =
|
|
6743
|
+
const options2 = chart.histogram ?? {};
|
|
6744
|
+
const bins = options2.aggregateByCategory ? aggregateByCategory(
|
|
6164
6745
|
first2.values.map((v) => v ?? 0),
|
|
6165
6746
|
model.categories
|
|
6166
|
-
) : computeHistogramBins(raw2,
|
|
6747
|
+
) : computeHistogramBins(raw2, options2, formatAxisValue);
|
|
6167
6748
|
model.categories = bins.map((bin) => bin.label);
|
|
6168
6749
|
first2.values = bins.map((bin) => bin.value);
|
|
6169
6750
|
model.barGapWidth = 0;
|
|
@@ -6187,11 +6768,11 @@ var SUPPORTED = /* @__PURE__ */ new Set([
|
|
|
6187
6768
|
"treemap",
|
|
6188
6769
|
"sunburst"
|
|
6189
6770
|
]);
|
|
6190
|
-
function chartSummaryView(chart, theme,
|
|
6771
|
+
function chartSummaryView(chart, theme, options2 = {}) {
|
|
6191
6772
|
const type = chart.chartType;
|
|
6192
6773
|
const radial = type === "pie" || type === "doughnut";
|
|
6193
6774
|
const byPoint = radial || type === "treemap" || type === "sunburst";
|
|
6194
|
-
const ctx = seriesContext(chart, theme,
|
|
6775
|
+
const ctx = seriesContext(chart, theme, options2);
|
|
6195
6776
|
const { palette, scheme, drawingColor } = ctx;
|
|
6196
6777
|
const grouping = chart.grouping ?? (type === "bar" || type === "column" ? "clustered" : "standard");
|
|
6197
6778
|
const rawCategories = [];
|
|
@@ -6277,6 +6858,7 @@ function chartSummaryView(chart, theme, options = {}) {
|
|
|
6277
6858
|
else if (!byPoint) model.valueAxis = valueAxis(model);
|
|
6278
6859
|
applyDataLabels(model, chart.series, extra);
|
|
6279
6860
|
chartExtraAxes(model);
|
|
6861
|
+
applyChartAxes(model, chart, ctx.drawingColor);
|
|
6280
6862
|
return model;
|
|
6281
6863
|
}
|
|
6282
6864
|
|
|
@@ -6284,15 +6866,13 @@ function chartSummaryView(chart, theme, options = {}) {
|
|
|
6284
6866
|
function cartesianAxes(model, area, out) {
|
|
6285
6867
|
const scale = model.valueAxis;
|
|
6286
6868
|
if (!scale) return void 0;
|
|
6287
|
-
const labels = scale.ticks.map((t) =>
|
|
6869
|
+
const labels = scale.ticks.map((t) => axisTickText(t, model.axes?.value, scale.percent));
|
|
6288
6870
|
const valueAttrs = chartTextAttributes(model, "valueAxis");
|
|
6289
6871
|
const categoryAttrs = chartTextAttributes(model, "categoryAxis");
|
|
6290
6872
|
const valueSize = valueAttrs.size ?? 10;
|
|
6291
6873
|
const categorySize = categoryAttrs.size ?? 10;
|
|
6292
|
-
const
|
|
6293
|
-
const
|
|
6294
|
-
const valueLabels = model.appearance?.valueAxis?.labelsVisible !== false;
|
|
6295
|
-
const categoryLabels = model.appearance?.categoryAxis?.labelsVisible !== false;
|
|
6874
|
+
const valueLabels = chartAxisLabels(model.axes?.value) && model.appearance?.valueAxis?.labelsVisible !== false;
|
|
6875
|
+
const categoryLabels = chartAxisLabels(model.axes?.category) && model.appearance?.categoryAxis?.labelsVisible !== false;
|
|
6296
6876
|
const labelW = valueLabels ? Math.max(...labels.map((l) => textWidth(l, valueSize)), 8) + 6 : 4;
|
|
6297
6877
|
const horizontal = model.horizontal;
|
|
6298
6878
|
const cats = Math.max(1, model.categories.length);
|
|
@@ -6301,7 +6881,7 @@ function cartesianAxes(model, area, out) {
|
|
|
6301
6881
|
Math.max(...model.categories.map((c2) => textWidth(c2, categorySize)), 8) + 6
|
|
6302
6882
|
);
|
|
6303
6883
|
const second = horizontal ? void 0 : model.secondaryAxis;
|
|
6304
|
-
const secondLabels = second?.ticks.map((t) =>
|
|
6884
|
+
const secondLabels = second?.ticks.map((t) => axisTickText(t, model.axes?.secondary, second.percent)) ?? [];
|
|
6305
6885
|
const secondW = second ? valueLabels ? Math.max(...secondLabels.map((l) => textWidth(l, valueSize)), 8) + 8 : 4 : 0;
|
|
6306
6886
|
const plot = horizontal ? {
|
|
6307
6887
|
x: area.x + catW,
|
|
@@ -6314,29 +6894,47 @@ function cartesianAxes(model, area, out) {
|
|
|
6314
6894
|
w: Math.max(1, area.w - labelW - 4 - secondW),
|
|
6315
6895
|
h: Math.max(1, area.h - Math.max(20, categorySize * 1.5))
|
|
6316
6896
|
};
|
|
6317
|
-
const
|
|
6318
|
-
const value = horizontal ? (v) => plot.x + (v - scale.min) / span * plot.w : (v) => plot.y + plot.h - (v - scale.min) / span * plot.h;
|
|
6897
|
+
const value = horizontal ? (v) => plot.x + chartAxisRatio(v, scale, model.axes?.value) * plot.w : (v) => plot.y + plot.h - chartAxisRatio(v, scale, model.axes?.value) * plot.h;
|
|
6319
6898
|
const bandSize = (horizontal ? plot.h : plot.w) / cats;
|
|
6320
|
-
const
|
|
6899
|
+
const index = (i) => model.axes?.category?.range.reverseOrder ? cats - 1 - i : i;
|
|
6900
|
+
const band = horizontal ? (i) => plot.y + plot.h - bandSize * (index(i) + 0.5) : (i) => plot.x + bandSize * (index(i) + 0.5);
|
|
6321
6901
|
out.push(chartAreaRect(model, "plotArea", plot));
|
|
6902
|
+
out.push(axisGridlines(model, model.axes?.value, scale.ticks, value, plot, horizontal));
|
|
6903
|
+
if (model.axes?.category?.source.majorGridlines || model.axes?.category?.source.minorGridlines)
|
|
6904
|
+
out.push(
|
|
6905
|
+
axisGridlines(
|
|
6906
|
+
model,
|
|
6907
|
+
model.axes.category,
|
|
6908
|
+
model.categories.map((_, i) => i),
|
|
6909
|
+
band,
|
|
6910
|
+
plot,
|
|
6911
|
+
!horizontal
|
|
6912
|
+
)
|
|
6913
|
+
);
|
|
6322
6914
|
scale.ticks.forEach((t, i) => {
|
|
6323
6915
|
const p = value(t);
|
|
6324
6916
|
const label = labels[i] ?? "";
|
|
6325
6917
|
if (horizontal) {
|
|
6326
|
-
out.push(line(p, plot.y, p, plot.y + plot.h, grid.color, grid.width));
|
|
6327
6918
|
if (valueLabels)
|
|
6328
6919
|
out.push(
|
|
6329
6920
|
text2(p, plot.y + plot.h + valueSize + 2, label, { anchor: "middle", ...valueAttrs })
|
|
6330
6921
|
);
|
|
6331
6922
|
} else {
|
|
6332
|
-
out.push(line(plot.x, p, plot.x + plot.w, p, grid.color, grid.width));
|
|
6333
6923
|
if (valueLabels)
|
|
6334
6924
|
out.push(text2(plot.x - 4, p + valueSize * 0.3, label, { anchor: "end", ...valueAttrs }));
|
|
6335
6925
|
}
|
|
6336
6926
|
});
|
|
6337
|
-
const
|
|
6338
|
-
|
|
6339
|
-
|
|
6927
|
+
const source = model.axes?.value?.source;
|
|
6928
|
+
const crossing = source?.crosses === "max" ? scale.max : source?.crosses === "min" ? scale.min : source?.crossesAt ?? 0;
|
|
6929
|
+
const zero = value(Math.min(Math.max(crossing, scale.min), scale.max));
|
|
6930
|
+
if (horizontal)
|
|
6931
|
+
out.push(
|
|
6932
|
+
axisLine(model, model.axes?.category, "categoryAxis", zero, plot.y, zero, plot.y + plot.h)
|
|
6933
|
+
);
|
|
6934
|
+
else
|
|
6935
|
+
out.push(
|
|
6936
|
+
axisLine(model, model.axes?.category, "categoryAxis", plot.x, zero, plot.x + plot.w, zero)
|
|
6937
|
+
);
|
|
6340
6938
|
const step = Math.max(
|
|
6341
6939
|
1,
|
|
6342
6940
|
Math.ceil(cats / Math.max(1, Math.floor((horizontal ? plot.h : plot.w) / 14)))
|
|
@@ -6361,20 +6959,23 @@ function cartesianAxes(model, area, out) {
|
|
|
6361
6959
|
});
|
|
6362
6960
|
const frame = { plot, value, band, bandSize };
|
|
6363
6961
|
if (second) {
|
|
6364
|
-
|
|
6365
|
-
frame.secondary = (v) => plot.y + plot.h - (v - second.min) / secondSpan * plot.h;
|
|
6366
|
-
const secondAxis = chartStroke(model, "valueAxis");
|
|
6962
|
+
frame.secondary = (v) => plot.y + plot.h - chartAxisRatio(v, second, model.axes?.secondary) * plot.h;
|
|
6367
6963
|
out.push(
|
|
6368
|
-
|
|
6964
|
+
axisLine(
|
|
6965
|
+
model,
|
|
6966
|
+
model.axes?.secondary,
|
|
6967
|
+
"valueAxis",
|
|
6369
6968
|
plot.x + plot.w,
|
|
6370
6969
|
plot.y,
|
|
6371
6970
|
plot.x + plot.w,
|
|
6372
|
-
plot.y + plot.h
|
|
6373
|
-
secondAxis.color,
|
|
6374
|
-
secondAxis.width
|
|
6971
|
+
plot.y + plot.h
|
|
6375
6972
|
)
|
|
6376
6973
|
);
|
|
6377
|
-
if (
|
|
6974
|
+
if (model.axes?.secondary?.source.majorGridlines || model.axes?.secondary?.source.minorGridlines)
|
|
6975
|
+
out.push(
|
|
6976
|
+
axisGridlines(model, model.axes.secondary, second.ticks, frame.secondary, plot, false)
|
|
6977
|
+
);
|
|
6978
|
+
if (chartAxisLabels(model.axes?.secondary))
|
|
6378
6979
|
second.ticks.forEach(
|
|
6379
6980
|
(t, i) => out.push(
|
|
6380
6981
|
text2(plot.x + plot.w + 4, frame.secondary(t) + valueSize * 0.3, secondLabels[i] ?? "", {
|
|
@@ -6418,18 +7019,19 @@ function linesAndAreas(model, frame, out) {
|
|
|
6418
7019
|
index: i,
|
|
6419
7020
|
x: frame.band(i),
|
|
6420
7021
|
y: frame.value(top),
|
|
6421
|
-
radius: area ? 0 :
|
|
7022
|
+
radius: area ? 0 : chartMarkerRadius(s, i, 2.5)
|
|
6422
7023
|
});
|
|
6423
7024
|
lower.push([frame.band(i), frame.value(below)]);
|
|
6424
7025
|
});
|
|
6425
7026
|
layers.push({
|
|
7027
|
+
series: s,
|
|
6426
7028
|
points,
|
|
6427
7029
|
lower,
|
|
6428
7030
|
color: s.color,
|
|
6429
7031
|
filter: s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""
|
|
6430
7032
|
});
|
|
6431
7033
|
});
|
|
6432
|
-
for (const { points, lower, color, filter } of area ? [...layers].reverse() : layers) {
|
|
7034
|
+
for (const { points, lower, color, filter, series } of area ? [...layers].reverse() : layers) {
|
|
6433
7035
|
if (area) {
|
|
6434
7036
|
const poly = [...points, ...[...lower].reverse()].map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
|
|
6435
7037
|
out.push(`<polygon points="${poly}" fill="${color}" fill-opacity="0.85"${filter}/>`);
|
|
@@ -6448,9 +7050,9 @@ function linesAndAreas(model, frame, out) {
|
|
|
6448
7050
|
else segment2.push(`${n(x)},${n(y)}`);
|
|
6449
7051
|
}
|
|
6450
7052
|
flush();
|
|
6451
|
-
|
|
6452
|
-
if (!Number.isNaN(x))
|
|
6453
|
-
|
|
7053
|
+
points.forEach(([x, y], index) => {
|
|
7054
|
+
if (!Number.isNaN(x)) out.push(chartSeriesMarkerSvg(series, index, x, y, 2.5));
|
|
7055
|
+
});
|
|
6454
7056
|
}
|
|
6455
7057
|
pointLabels(model, marks, out);
|
|
6456
7058
|
}
|
|
@@ -6460,16 +7062,14 @@ function scatter(model, area, out) {
|
|
|
6460
7062
|
const ys = model.valueAxis;
|
|
6461
7063
|
const xs = model.xAxis;
|
|
6462
7064
|
if (!ys || !xs) return;
|
|
6463
|
-
const yLabels = ys.ticks.map((t) =>
|
|
7065
|
+
const yLabels = ys.ticks.map((t) => axisTickText(t, model.axes?.value));
|
|
6464
7066
|
const valueAttrs = chartTextAttributes(model, "valueAxis");
|
|
6465
7067
|
const categoryAttrs = chartTextAttributes(model, "categoryAxis");
|
|
6466
7068
|
const valueSize = valueAttrs.size ?? 10;
|
|
6467
7069
|
const categorySize = categoryAttrs.size ?? 10;
|
|
6468
|
-
const grid = chartStroke(model, "gridlineMajor");
|
|
6469
7070
|
const xAxis = chartStroke(model, "categoryAxis");
|
|
6470
|
-
const
|
|
6471
|
-
const
|
|
6472
|
-
const categoryLabels = model.appearance?.categoryAxis?.labelsVisible !== false;
|
|
7071
|
+
const valueLabels = chartAxisLabels(model.axes?.value) && model.appearance?.valueAxis?.labelsVisible !== false;
|
|
7072
|
+
const categoryLabels = chartAxisLabels(model.axes?.category) && model.appearance?.categoryAxis?.labelsVisible !== false;
|
|
6473
7073
|
const labelW = valueLabels ? Math.max(...yLabels.map((l) => textWidth(l, valueSize)), 8) + 6 : 4;
|
|
6474
7074
|
const plot = {
|
|
6475
7075
|
x: area.x + labelW,
|
|
@@ -6489,17 +7089,24 @@ function scatter(model, area, out) {
|
|
|
6489
7089
|
s.values.forEach((_, i) => {
|
|
6490
7090
|
reach = Math.max(reach, radiusOf(s.sizes?.[i] ?? void 0) ?? 0);
|
|
6491
7091
|
});
|
|
6492
|
-
const widen = (s, length) => {
|
|
7092
|
+
const widen = (s, length, axis) => {
|
|
7093
|
+
if (axis?.range.logScale) return s;
|
|
6493
7094
|
const pad = reach * (s.max - s.min || 1) / Math.max(1, length - 2 * reach);
|
|
6494
|
-
return {
|
|
7095
|
+
return {
|
|
7096
|
+
...s,
|
|
7097
|
+
min: axis?.source.scaling.min === void 0 ? s.min - pad : s.min,
|
|
7098
|
+
max: axis?.source.scaling.max === void 0 ? s.max + pad : s.max
|
|
7099
|
+
};
|
|
6495
7100
|
};
|
|
6496
|
-
const xView = widen(xs, plot.w);
|
|
6497
|
-
const yView = widen(ys, plot.h);
|
|
6498
|
-
const px = (v) => plot.x + (v
|
|
6499
|
-
const py = (v) => plot.y + plot.h - (v
|
|
7101
|
+
const xView = widen(xs, plot.w, model.axes?.category);
|
|
7102
|
+
const yView = widen(ys, plot.h, model.axes?.value);
|
|
7103
|
+
const px = (v) => plot.x + chartAxisRatio(v, xView, model.axes?.category) * plot.w;
|
|
7104
|
+
const py = (v) => plot.y + plot.h - chartAxisRatio(v, yView, model.axes?.value) * plot.h;
|
|
6500
7105
|
out.push(chartAreaRect(model, "plotArea", plot));
|
|
7106
|
+
out.push(axisGridlines(model, model.axes?.value, ys.ticks, py, plot, false));
|
|
7107
|
+
if (model.axes?.category)
|
|
7108
|
+
out.push(axisGridlines(model, model.axes.category, xs.ticks, px, plot, true));
|
|
6501
7109
|
ys.ticks.forEach((t, i) => {
|
|
6502
|
-
out.push(line(plot.x, py(t), plot.x + plot.w, py(t), grid.color, grid.width));
|
|
6503
7110
|
if (valueLabels)
|
|
6504
7111
|
out.push(
|
|
6505
7112
|
text2(plot.x - 4, py(t) + valueSize * 0.3, yLabels[i] ?? "", {
|
|
@@ -6509,19 +7116,30 @@ function scatter(model, area, out) {
|
|
|
6509
7116
|
);
|
|
6510
7117
|
});
|
|
6511
7118
|
for (const t of xs.ticks) {
|
|
6512
|
-
|
|
7119
|
+
if (!model.axes?.category?.source.deleted)
|
|
7120
|
+
out.push(line(px(t), plot.y + plot.h, px(t), plot.y + plot.h + 3, xAxis.color, xAxis.width));
|
|
6513
7121
|
if (categoryLabels)
|
|
6514
7122
|
out.push(
|
|
6515
|
-
text2(px(t), plot.y + plot.h + categorySize + 3,
|
|
7123
|
+
text2(px(t), plot.y + plot.h + categorySize + 3, axisTickText(t, model.axes?.category), {
|
|
6516
7124
|
anchor: "middle",
|
|
6517
7125
|
...categoryAttrs
|
|
6518
7126
|
})
|
|
6519
7127
|
);
|
|
6520
7128
|
}
|
|
6521
7129
|
out.push(
|
|
6522
|
-
|
|
7130
|
+
axisLine(
|
|
7131
|
+
model,
|
|
7132
|
+
model.axes?.category,
|
|
7133
|
+
"categoryAxis",
|
|
7134
|
+
plot.x,
|
|
7135
|
+
plot.y + plot.h,
|
|
7136
|
+
plot.x + plot.w,
|
|
7137
|
+
plot.y + plot.h
|
|
7138
|
+
)
|
|
7139
|
+
);
|
|
7140
|
+
out.push(
|
|
7141
|
+
axisLine(model, model.axes?.value, "valueAxis", plot.x, plot.y, plot.x, plot.y + plot.h)
|
|
6523
7142
|
);
|
|
6524
|
-
out.push(line(plot.x, plot.y, plot.x, plot.y + plot.h, yAxis.color, yAxis.width));
|
|
6525
7143
|
const marks = [];
|
|
6526
7144
|
for (const [si, s] of model.series.entries())
|
|
6527
7145
|
s.values.forEach((v, i) => {
|
|
@@ -6530,8 +7148,8 @@ function scatter(model, area, out) {
|
|
|
6530
7148
|
const filter = s.shadowFilter ? ` filter="${s.shadowFilter}"` : "";
|
|
6531
7149
|
const fill = s.pointColors?.[i] ?? s.color;
|
|
6532
7150
|
if (!bubble) {
|
|
6533
|
-
out.push(
|
|
6534
|
-
marks.push({ series: s, index: i, x: px(x), y: py(v), radius:
|
|
7151
|
+
out.push(chartSeriesMarkerSvg(s, i, px(x), py(v)));
|
|
7152
|
+
marks.push({ series: s, index: i, x: px(x), y: py(v), radius: chartMarkerRadius(s, i) });
|
|
6535
7153
|
return;
|
|
6536
7154
|
}
|
|
6537
7155
|
const r = radiusOf(s.sizes?.[i] ?? void 0);
|
|
@@ -6751,32 +7369,37 @@ function radarSvg(model, area) {
|
|
|
6751
7369
|
const valueSize = valueAttrs.size ?? 9;
|
|
6752
7370
|
const categorySize = categoryAttrs.size ?? 10;
|
|
6753
7371
|
const grid = chartStroke(model, "gridlineMajor");
|
|
6754
|
-
const axis = chartStroke(model, "categoryAxis");
|
|
6755
7372
|
const cx2 = area.x + area.w / 2;
|
|
6756
7373
|
const cy = area.y + area.h / 2 + 4;
|
|
6757
7374
|
const radius = Math.max(1, Math.min(area.w, area.h) / 2 - Math.max(18, categorySize * 1.8));
|
|
6758
7375
|
const angle = (i) => i / count * Math.PI * 2;
|
|
6759
|
-
const r = (v) => (v
|
|
7376
|
+
const r = (v) => chartAxisRatio(v, scale, model.axes?.value) * radius;
|
|
6760
7377
|
const labelEvery = Math.max(
|
|
6761
7378
|
1,
|
|
6762
7379
|
Math.ceil(12 / Math.max(1, radius / Math.max(1, scale.ticks.length - 1)))
|
|
6763
7380
|
);
|
|
6764
7381
|
for (const [k, t] of scale.ticks.entries()) {
|
|
6765
7382
|
const ring = Array.from({ length: count }, (_, i) => polar(cx2, cy, r(t), angle(i))).map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
|
|
6766
|
-
|
|
6767
|
-
`<polygon points="${ring}" fill="none" stroke="${grid.color}" stroke-width="${n(grid.width)}"/>`
|
|
6768
|
-
);
|
|
6769
|
-
if (model.appearance?.valueAxis?.labelsVisible !== false && k % labelEvery === 0)
|
|
7383
|
+
if (!model.axes?.value || model.axes.value.source.majorGridlines)
|
|
6770
7384
|
out.push(
|
|
6771
|
-
|
|
7385
|
+
`<polygon points="${ring}" fill="none" stroke="${grid.color}" stroke-width="${n(grid.width)}"/>`
|
|
7386
|
+
);
|
|
7387
|
+
if (chartAxisLabels(model.axes?.value) && model.appearance?.valueAxis?.labelsVisible !== false && k % labelEvery === 0)
|
|
7388
|
+
out.push(
|
|
7389
|
+
text2(
|
|
7390
|
+
cx2 + 3,
|
|
7391
|
+
cy - r(t) + valueSize * 0.3,
|
|
7392
|
+
axisTickText(t, model.axes?.value, scale.percent),
|
|
7393
|
+
valueAttrs
|
|
7394
|
+
)
|
|
6772
7395
|
);
|
|
6773
7396
|
}
|
|
6774
7397
|
model.categories.forEach((c2, i) => {
|
|
6775
7398
|
const [x, y] = polar(cx2, cy, radius, angle(i));
|
|
6776
|
-
out.push(
|
|
7399
|
+
out.push(axisLine(model, model.axes?.category, "categoryAxis", cx2, cy, x, y));
|
|
6777
7400
|
const [lx, ly] = polar(cx2, cy, radius + 10, angle(i));
|
|
6778
7401
|
const anchor = Math.abs(lx - cx2) < 2 ? "middle" : lx > cx2 ? "start" : "end";
|
|
6779
|
-
if (model.appearance?.categoryAxis?.labelsVisible !== false)
|
|
7402
|
+
if (chartAxisLabels(model.axes?.category) && model.appearance?.categoryAxis?.labelsVisible !== false)
|
|
6780
7403
|
out.push(
|
|
6781
7404
|
text2(lx, ly + categorySize * 0.3, fit(c2, area.w / 4, categorySize), {
|
|
6782
7405
|
anchor,
|
|
@@ -6787,7 +7410,13 @@ function radarSvg(model, area) {
|
|
|
6787
7410
|
const marks = [];
|
|
6788
7411
|
for (const s of model.series) {
|
|
6789
7412
|
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) =>
|
|
7413
|
+
vertices.forEach(([x, y], i) => {
|
|
7414
|
+
if (s.values[i] === null) return;
|
|
7415
|
+
const markerSeries = s;
|
|
7416
|
+
if (markerSeries.marker || markerSeries.pointMarkers)
|
|
7417
|
+
out.push(chartSeriesMarkerSvg(s, i, x, y));
|
|
7418
|
+
marks.push({ series: s, index: i, x, y, radius: chartMarkerRadius(s, i) });
|
|
7419
|
+
});
|
|
6791
7420
|
const points = vertices.map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
|
|
6792
7421
|
out.push(
|
|
6793
7422
|
`<polygon points="${points}" fill="none" stroke="${s.color}" stroke-width="2"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
|
|
@@ -6884,33 +7513,33 @@ var CHART_FONT_FAMILY = "Calibri, Carlito, Arial, sans-serif";
|
|
|
6884
7513
|
function cssFont(attrs) {
|
|
6885
7514
|
return `${attrs.italic ? "italic" : "normal"} ${attrs.weight ?? "normal"} ${attrs.size ?? 10}px ${attrs.family ?? CHART_FONT_FAMILY}`;
|
|
6886
7515
|
}
|
|
6887
|
-
function chartFontMetrics(attrs,
|
|
6888
|
-
const metrics =
|
|
7516
|
+
function chartFontMetrics(attrs, options2) {
|
|
7517
|
+
const metrics = options2.measureFont?.(cssFont(attrs));
|
|
6889
7518
|
return metrics && Number.isFinite(metrics.ascent) && Number.isFinite(metrics.descent) && metrics.ascent >= 0 && metrics.descent >= 0 && metrics.ascent + metrics.descent > 0 ? metrics : void 0;
|
|
6890
7519
|
}
|
|
6891
|
-
function chartTextWidth(content, attrs,
|
|
6892
|
-
const width =
|
|
7520
|
+
function chartTextWidth(content, attrs, options2) {
|
|
7521
|
+
const width = options2.measureText?.(content, cssFont(attrs));
|
|
6893
7522
|
return width !== void 0 && Number.isFinite(width) && width >= 0 ? width : textWidth(content, attrs.size);
|
|
6894
7523
|
}
|
|
6895
|
-
function fitChartText(content, maxWidth, attrs,
|
|
6896
|
-
if (!
|
|
6897
|
-
if (chartTextWidth(content, attrs,
|
|
7524
|
+
function fitChartText(content, maxWidth, attrs, options2) {
|
|
7525
|
+
if (!options2.measureText) return fit(content, maxWidth, attrs.size);
|
|
7526
|
+
if (chartTextWidth(content, attrs, options2) <= maxWidth) return content;
|
|
6898
7527
|
const points = [...content];
|
|
6899
7528
|
let low = 0;
|
|
6900
7529
|
let high = points.length;
|
|
6901
7530
|
while (low < high) {
|
|
6902
7531
|
const mid = Math.ceil((low + high) / 2);
|
|
6903
|
-
if (chartTextWidth(`${points.slice(0, mid).join("")}\u2026`, attrs,
|
|
7532
|
+
if (chartTextWidth(`${points.slice(0, mid).join("")}\u2026`, attrs, options2) <= maxWidth) low = mid;
|
|
6904
7533
|
else high = mid - 1;
|
|
6905
7534
|
}
|
|
6906
7535
|
return `${points.slice(0, low).join("")}\u2026`;
|
|
6907
7536
|
}
|
|
6908
7537
|
|
|
6909
7538
|
// chart/render/chart-svg-legend.ts
|
|
6910
|
-
function chartLegendSvg(model, area, frame,
|
|
7539
|
+
function chartLegendSvg(model, area, frame, options2) {
|
|
6911
7540
|
const automatic = [];
|
|
6912
7541
|
const bounds = {};
|
|
6913
|
-
const reserved = automaticLegend(model, area, automatic,
|
|
7542
|
+
const reserved = automaticLegend(model, area, automatic, options2, bounds);
|
|
6914
7543
|
const plot = model.legendOverlay ? area : reserved;
|
|
6915
7544
|
const box = bounds.box;
|
|
6916
7545
|
if (!box) return { plot, markup: "", foreground: false };
|
|
@@ -6924,11 +7553,11 @@ function chartLegendSvg(model, area, frame, options) {
|
|
|
6924
7553
|
const entries = legendEntries(model);
|
|
6925
7554
|
const attrs = chartTextAttributes(model, "legend");
|
|
6926
7555
|
const size = attrs.size ?? 10;
|
|
6927
|
-
const font = chartFontMetrics(attrs,
|
|
7556
|
+
const font = chartFontMetrics(attrs, options2);
|
|
6928
7557
|
const keySize = size / 2;
|
|
6929
7558
|
const keyGap = size / 4;
|
|
6930
7559
|
const widths = entries.map(
|
|
6931
|
-
(entry3) => chartTextWidth(entry3.label, attrs,
|
|
7560
|
+
(entry3) => chartTextWidth(entry3.label, attrs, options2) + keySize + keyGap
|
|
6932
7561
|
);
|
|
6933
7562
|
const horizontal = manual.width > manual.height && widths.reduce((sum, width) => sum + width, 0) + size <= manual.width;
|
|
6934
7563
|
const rowWidth = horizontal ? manual.width / entries.length : manual.width;
|
|
@@ -6943,8 +7572,8 @@ function chartLegendSvg(model, area, frame, options) {
|
|
|
6943
7572
|
];
|
|
6944
7573
|
const baselineOffset = font ? (font.ascent - font.descent) / 2 : size * 0.35;
|
|
6945
7574
|
entries.forEach((entry3, i) => {
|
|
6946
|
-
const available = horizontal ? chartTextWidth(entry3.label, attrs,
|
|
6947
|
-
const label = fitChartText(entry3.label, available, attrs,
|
|
7575
|
+
const available = horizontal ? chartTextWidth(entry3.label, attrs, options2) : Math.max(0, rowWidth - size / 2 - keySize - keyGap);
|
|
7576
|
+
const label = fitChartText(entry3.label, available, attrs, options2);
|
|
6948
7577
|
const contentWidth = Math.min(
|
|
6949
7578
|
horizontal ? widths[i] ?? 0 : Math.max(...widths),
|
|
6950
7579
|
rowWidth - size / 2
|
|
@@ -6987,7 +7616,7 @@ function legendEntries(model) {
|
|
|
6987
7616
|
color: s.color
|
|
6988
7617
|
}));
|
|
6989
7618
|
}
|
|
6990
|
-
function automaticLegend(model, area, out,
|
|
7619
|
+
function automaticLegend(model, area, out, options2, bounds) {
|
|
6991
7620
|
const entries = legendEntries(model);
|
|
6992
7621
|
if (!model.showLegend || entries.length === 0) return area;
|
|
6993
7622
|
const pos = model.legendPosition;
|
|
@@ -6996,7 +7625,7 @@ function automaticLegend(model, area, out, options, bounds) {
|
|
|
6996
7625
|
const rowH = Math.max(16, size * 1.4);
|
|
6997
7626
|
if (pos === "t" || pos === "b") {
|
|
6998
7627
|
const widths = entries.map(
|
|
6999
|
-
(e) => Math.min(chartTextWidth(e.label, attrs,
|
|
7628
|
+
(e) => Math.min(chartTextWidth(e.label, attrs, options2) + 20, area.w / 2)
|
|
7000
7629
|
);
|
|
7001
7630
|
const total = widths.reduce((a2, b) => a2 + b, 0);
|
|
7002
7631
|
let x2 = area.x + Math.max(0, (area.w - total) / 2);
|
|
@@ -7013,14 +7642,14 @@ function automaticLegend(model, area, out, options, bounds) {
|
|
|
7013
7642
|
entries.forEach((e, i) => {
|
|
7014
7643
|
const w = widths[i] ?? 0;
|
|
7015
7644
|
out.push(rect(x2, y, 8, 8, e.color));
|
|
7016
|
-
out.push(text2(x2 + 12, y + 8, fitChartText(e.label, w - 16, attrs,
|
|
7645
|
+
out.push(text2(x2 + 12, y + 8, fitChartText(e.label, w - 16, attrs, options2), attrs));
|
|
7017
7646
|
x2 += w;
|
|
7018
7647
|
});
|
|
7019
7648
|
return pos === "t" ? { x: area.x, y: area.y + rowH + 4, w: area.w, h: area.h - rowH - 4 } : { x: area.x, y: area.y, w: area.w, h: area.h - rowH - 4 };
|
|
7020
7649
|
}
|
|
7021
7650
|
const width = Math.min(
|
|
7022
7651
|
area.w * 0.35,
|
|
7023
|
-
Math.max(...entries.map((e) => chartTextWidth(e.label, attrs,
|
|
7652
|
+
Math.max(...entries.map((e) => chartTextWidth(e.label, attrs, options2))) + 22
|
|
7024
7653
|
);
|
|
7025
7654
|
const height = entries.length * rowH;
|
|
7026
7655
|
const x = pos === "l" ? area.x + 4 : area.x + area.w - width;
|
|
@@ -7038,14 +7667,14 @@ function automaticLegend(model, area, out, options, bounds) {
|
|
|
7038
7667
|
const y = y0 + i * rowH;
|
|
7039
7668
|
if (y + rowH > area.y + area.h + 2) return;
|
|
7040
7669
|
out.push(rect(x, y + 3, 8, 8, e.color));
|
|
7041
|
-
out.push(text2(x + 12, y + 11, fitChartText(e.label, width - 16, attrs,
|
|
7670
|
+
out.push(text2(x + 12, y + 11, fitChartText(e.label, width - 16, attrs, options2), attrs));
|
|
7042
7671
|
});
|
|
7043
7672
|
return pos === "l" ? { x: area.x + width + 8, y: area.y, w: area.w - width - 8, h: area.h } : { x: area.x, y: area.y, w: area.w - width - 8, h: area.h };
|
|
7044
7673
|
}
|
|
7045
7674
|
|
|
7046
7675
|
// text/wrap-styled-runs.ts
|
|
7047
7676
|
var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
7048
|
-
function wrapStyledRuns(runs, maxWidth, measure2,
|
|
7677
|
+
function wrapStyledRuns(runs, maxWidth, measure2, options2 = {}) {
|
|
7049
7678
|
const groups = [];
|
|
7050
7679
|
for (const [source, run2] of runs.entries()) {
|
|
7051
7680
|
for (const token of run2.text.split(/(\r\n|[\r\n]|[ \t]+)/u).filter(Boolean)) {
|
|
@@ -7093,7 +7722,7 @@ function wrapStyledRuns(runs, maxWidth, measure2, options = {}) {
|
|
|
7093
7722
|
if (line2.length && width(merged(line2, [...separator, ...group2.pieces])) > maxWidth) flush();
|
|
7094
7723
|
else line2 = merged(line2, separator);
|
|
7095
7724
|
spaces = [];
|
|
7096
|
-
if (
|
|
7725
|
+
if (options2.breakWords && wordWidth > maxWidth) {
|
|
7097
7726
|
for (const piece of group2.pieces) {
|
|
7098
7727
|
for (const { segment: segment2 } of graphemes.segment(piece.text)) {
|
|
7099
7728
|
const next = { ...piece, text: segment2 };
|
|
@@ -7111,11 +7740,11 @@ function wrapStyledRuns(runs, maxWidth, measure2, options = {}) {
|
|
|
7111
7740
|
function spacing2(value, naturalHeight, fallback) {
|
|
7112
7741
|
return value ? value.unit === "points" ? chartPointsToPixels(value.value) : naturalHeight * value.value : fallback;
|
|
7113
7742
|
}
|
|
7114
|
-
function chartRichTitleSvg(model, width,
|
|
7743
|
+
function chartRichTitleSvg(model, width, options2 = {}, frameHeight = 400) {
|
|
7115
7744
|
if (!model.title) return void 0;
|
|
7116
7745
|
const base = chartTextAttributes(model, "title", 14);
|
|
7117
7746
|
const capacity = Math.max(1, width * 0.8 - 8);
|
|
7118
|
-
if (!model.titleText && !hasManualLayoutFields(model.titleLayout) && !model.titleOverlay && !model.title.includes("\n") && chartTextWidth(model.title, base,
|
|
7747
|
+
if (!model.titleText && !hasManualLayoutFields(model.titleLayout) && !model.titleOverlay && !model.title.includes("\n") && chartTextWidth(model.title, base, options2) <= capacity)
|
|
7119
7748
|
return void 0;
|
|
7120
7749
|
const paragraphs = model.titleText?.paragraphs ?? [
|
|
7121
7750
|
{
|
|
@@ -7151,7 +7780,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
|
|
|
7151
7780
|
"title",
|
|
7152
7781
|
base.size
|
|
7153
7782
|
),
|
|
7154
|
-
|
|
7783
|
+
options2
|
|
7155
7784
|
),
|
|
7156
7785
|
{ breakWords: true }
|
|
7157
7786
|
);
|
|
@@ -7175,10 +7804,10 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
|
|
|
7175
7804
|
return {
|
|
7176
7805
|
...line2,
|
|
7177
7806
|
runs,
|
|
7178
|
-
width: runs.reduce((sum, run2) => sum + chartTextWidth(run2.text, run2.attrs,
|
|
7807
|
+
width: runs.reduce((sum, run2) => sum + chartTextWidth(run2.text, run2.attrs, options2), 0),
|
|
7179
7808
|
size: runs.length ? Math.max(...runs.map((run2) => run2.attrs.size ?? 14)) : base.size ?? 14,
|
|
7180
7809
|
fontMetrics: (runs.length ? runs.map((run2) => run2.attrs) : [base]).map(
|
|
7181
|
-
(attrs) => chartFontMetrics(attrs,
|
|
7810
|
+
(attrs) => chartFontMetrics(attrs, options2)
|
|
7182
7811
|
)
|
|
7183
7812
|
};
|
|
7184
7813
|
});
|
|
@@ -7216,7 +7845,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
|
|
|
7216
7845
|
anchor: "start"
|
|
7217
7846
|
}).replace("<text ", '<tspan data-chart-title-run="true" ').replace("</text>", "</tspan>")
|
|
7218
7847
|
);
|
|
7219
|
-
x += chartTextWidth(run2.text, run2.attrs,
|
|
7848
|
+
x += chartTextWidth(run2.text, run2.attrs, options2);
|
|
7220
7849
|
}
|
|
7221
7850
|
}
|
|
7222
7851
|
const parent = text2(0, 0, "", { ...base, underline: false }).replace(
|
|
@@ -7242,7 +7871,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
|
|
|
7242
7871
|
}
|
|
7243
7872
|
|
|
7244
7873
|
// chart/render/chart-svg.ts
|
|
7245
|
-
function renderChartSvg(model, width, height,
|
|
7874
|
+
function renderChartSvg(model, width, height, options2 = {}) {
|
|
7246
7875
|
const paint2 = chartGradientPaint(model, Math.max(1, width), Math.max(1, height));
|
|
7247
7876
|
model = paint2.model;
|
|
7248
7877
|
const w = Math.max(1, width);
|
|
@@ -7256,7 +7885,7 @@ function renderChartSvg(model, width, height, options = {}) {
|
|
|
7256
7885
|
if (paint2.defs) out.push(paint2.defs);
|
|
7257
7886
|
out.push(chartAreaRect(model, "chartArea", { x: 0, y: 0, w, h }));
|
|
7258
7887
|
let area = { x: 8, y: 8, w: w - 16, h: h - 16 };
|
|
7259
|
-
const richTitle = chartRichTitleSvg(model, w,
|
|
7888
|
+
const richTitle = chartRichTitleSvg(model, w, options2, h);
|
|
7260
7889
|
if (richTitle) {
|
|
7261
7890
|
if (model.titleLayout || model.titleOverlay) foregroundTitle = richTitle.markup;
|
|
7262
7891
|
else out.push(richTitle.markup);
|
|
@@ -7265,9 +7894,9 @@ function renderChartSvg(model, width, height, options = {}) {
|
|
|
7265
7894
|
} else if (model.title) {
|
|
7266
7895
|
const attrs = chartTextAttributes(model, "title", 14);
|
|
7267
7896
|
const size = attrs.size ?? 14;
|
|
7268
|
-
const label = fitChartText(model.title, w - 16, attrs,
|
|
7269
|
-
const titleWidth = Math.min(w - 16, chartTextWidth(label, attrs,
|
|
7270
|
-
const font = chartFontMetrics(attrs,
|
|
7897
|
+
const label = fitChartText(model.title, w - 16, attrs, options2);
|
|
7898
|
+
const titleWidth = Math.min(w - 16, chartTextWidth(label, attrs, options2) + 8);
|
|
7899
|
+
const font = chartFontMetrics(attrs, options2);
|
|
7271
7900
|
const titleHeight = Math.max(24, font ? font.ascent + font.descent + 4 : size * 1.4 + 4);
|
|
7272
7901
|
out.push(
|
|
7273
7902
|
chartAreaRect(model, "title", {
|
|
@@ -7295,7 +7924,7 @@ function renderChartSvg(model, width, height, options = {}) {
|
|
|
7295
7924
|
out.push("</svg>");
|
|
7296
7925
|
return out.join("");
|
|
7297
7926
|
}
|
|
7298
|
-
const legend = chartLegendSvg(model, area, { width: w, height: h },
|
|
7927
|
+
const legend = chartLegendSvg(model, area, { width: w, height: h }, options2);
|
|
7299
7928
|
area = legend.plot;
|
|
7300
7929
|
if (!legend.foreground) out.push(legend.markup);
|
|
7301
7930
|
if (area.w > 4 && area.h > 4) {
|
|
@@ -7342,8 +7971,8 @@ function chartSpaceKind(space) {
|
|
|
7342
7971
|
const type = chartSummaryFromSpace(space).chartType;
|
|
7343
7972
|
return { type, drawn: DRAWN_CHART_TYPES.has(type) };
|
|
7344
7973
|
}
|
|
7345
|
-
function renderChartSpaceSvg(space,
|
|
7346
|
-
const { width, height, theme, fonts, formatting, colorPalette, styleDefinition, ...svg } =
|
|
7974
|
+
function renderChartSpaceSvg(space, options2) {
|
|
7975
|
+
const { width, height, theme, fonts, formatting, colorPalette, styleDefinition, ...svg } = options2;
|
|
7347
7976
|
const summary = chartSummaryFromSpace(space, {
|
|
7348
7977
|
...formatting ? { formatting } : {},
|
|
7349
7978
|
...colorPalette !== void 0 ? { colorPalette } : {},
|
|
@@ -7352,8 +7981,8 @@ function renderChartSpaceSvg(space, options) {
|
|
|
7352
7981
|
const view = chartSummaryView(summary, chartThemePalette(theme, fonts));
|
|
7353
7982
|
return renderChartSvg(view, width, height, svg);
|
|
7354
7983
|
}
|
|
7355
|
-
function renderChartSummarySvg(summary,
|
|
7356
|
-
const { width, height, theme, fonts, ...svg } =
|
|
7984
|
+
function renderChartSummarySvg(summary, options2) {
|
|
7985
|
+
const { width, height, theme, fonts, ...svg } = options2;
|
|
7357
7986
|
const view = chartSummaryView(summary, chartThemePalette(theme, fonts));
|
|
7358
7987
|
return renderChartSvg(view, width, height, svg);
|
|
7359
7988
|
}
|
|
@@ -7387,9 +8016,11 @@ exports.aggregate = aggregate;
|
|
|
7387
8016
|
exports.aggregateByCategory = aggregateByCategory;
|
|
7388
8017
|
exports.assertBarClusterOptions = assertBarClusterOptions;
|
|
7389
8018
|
exports.autoSeriesColor = autoSeriesColor;
|
|
8019
|
+
exports.automaticMarkerSymbol = automaticMarkerSymbol;
|
|
7390
8020
|
exports.axisTargetIntervals = axisTargetIntervals;
|
|
7391
8021
|
exports.buildChartGradientDef = buildChartGradientDef;
|
|
7392
8022
|
exports.buildHierarchyRoots = buildHierarchyRoots;
|
|
8023
|
+
exports.buildMarkerPrimitive = buildMarkerPrimitive;
|
|
7393
8024
|
exports.buildWaterfallSteps = buildWaterfallSteps;
|
|
7394
8025
|
exports.builtInChartStyleXml = builtInChartStyleXml;
|
|
7395
8026
|
exports.builtInChartTextStyle = builtInChartTextStyle;
|
|
@@ -7401,10 +8032,13 @@ exports.chartColorStyleXml = chartColorStyleXml;
|
|
|
7401
8032
|
exports.chartErrorBarAmount = chartErrorBarAmount;
|
|
7402
8033
|
exports.chartExSummary = chartExSummary;
|
|
7403
8034
|
exports.chartGradientMarkup = chartGradientMarkup;
|
|
8035
|
+
exports.chartLineDashArray = chartLineDashArray;
|
|
8036
|
+
exports.chartMarkerRadius = chartMarkerRadius;
|
|
7404
8037
|
exports.chartPaletteColors = chartPaletteColors;
|
|
7405
8038
|
exports.chartPaletteSeriesColor = chartPaletteSeriesColor;
|
|
7406
8039
|
exports.chartPaletteSeriesColorChoice = chartPaletteSeriesColorChoice;
|
|
7407
8040
|
exports.chartSampleVariance = chartSampleVariance;
|
|
8041
|
+
exports.chartSeriesMarkerSvg = chartSeriesMarkerSvg;
|
|
7408
8042
|
exports.chartSourceValues = chartSourceValues;
|
|
7409
8043
|
exports.chartSpaceKind = chartSpaceKind;
|
|
7410
8044
|
exports.chartSummaryFromSpace = chartSummaryFromSpace;
|
|
@@ -7415,18 +8049,25 @@ exports.chartTrendlineKind = chartTrendlineKind;
|
|
|
7415
8049
|
exports.chartTrendlineType = chartTrendlineType;
|
|
7416
8050
|
exports.clusteredBarGeometry = clusteredBarGeometry;
|
|
7417
8051
|
exports.composeDataLabelText = composeDataLabelText;
|
|
8052
|
+
exports.computeAxisStackedValueRange = computeAxisStackedValueRange;
|
|
8053
|
+
exports.computeAxisValueRange = computeAxisValueRange;
|
|
7418
8054
|
exports.computeBoxStats = computeBoxStats;
|
|
7419
8055
|
exports.computeBubbleRadius = computeBubbleRadius;
|
|
7420
8056
|
exports.computeHierarchicalSunburstArcs = computeHierarchicalSunburstArcs;
|
|
7421
8057
|
exports.computeHistogramBins = computeHistogramBins;
|
|
7422
8058
|
exports.computeLinearRegression = computeLinearRegression;
|
|
8059
|
+
exports.computeLogValueRange = computeLogValueRange;
|
|
7423
8060
|
exports.computeRSquared = computeRSquared;
|
|
7424
8061
|
exports.computeRadarPoints = computeRadarPoints;
|
|
7425
8062
|
exports.computeStackedSeriesPlots = computeStackedSeriesPlots;
|
|
8063
|
+
exports.computeStackedValueRangeForAxis = computeStackedValueRangeForAxis;
|
|
7426
8064
|
exports.computeSunburstArcs = computeSunburstArcs;
|
|
8065
|
+
exports.computeValueRangeForAxis = computeValueRangeForAxis;
|
|
8066
|
+
exports.computeValueRangeForChart = computeValueRangeForChart;
|
|
7427
8067
|
exports.computeWaterfallRange = computeWaterfallRange;
|
|
7428
8068
|
exports.effectiveBuiltInChartStyle = effectiveBuiltInChartStyle;
|
|
7429
8069
|
exports.findChartColorPalette = findChartColorPalette;
|
|
8070
|
+
exports.findLogAxis = findLogAxis;
|
|
7430
8071
|
exports.fitChartTrendline = fitChartTrendline;
|
|
7431
8072
|
exports.fitPolynomial = fitPolynomial;
|
|
7432
8073
|
exports.formatChartNumber = formatChartNumber;
|
|
@@ -7438,6 +8079,9 @@ exports.formatLogarithmicEquation = formatLogarithmicEquation;
|
|
|
7438
8079
|
exports.formatPolynomialEquation = formatPolynomialEquation;
|
|
7439
8080
|
exports.formatPowerEquation = formatPowerEquation;
|
|
7440
8081
|
exports.formatTrendlineCoefficient = formatTrendlineCoefficient;
|
|
8082
|
+
exports.generateAxisTicks = generateAxisTicks;
|
|
8083
|
+
exports.generateLogTicks = generateLogTicks;
|
|
8084
|
+
exports.generateMinorAxisTicks = generateMinorAxisTicks;
|
|
7441
8085
|
exports.getChartStylePalette = getChartStylePalette;
|
|
7442
8086
|
exports.groupRowsByCategory = groupRowsByCategory;
|
|
7443
8087
|
exports.hasManualLayoutFields = hasManualLayoutFields;
|
|
@@ -7445,6 +8089,8 @@ exports.hierarchyBranchLabels = hierarchyBranchLabels;
|
|
|
7445
8089
|
exports.impliesAutoTitle = impliesAutoTitle;
|
|
7446
8090
|
exports.isChartexOnlyType = isChartexOnlyType;
|
|
7447
8091
|
exports.layoutTreemap = layoutTreemap;
|
|
8092
|
+
exports.markerOutline = markerOutline;
|
|
8093
|
+
exports.markerRadius = markerRadius;
|
|
7448
8094
|
exports.maxBubbleSize = maxBubbleSize;
|
|
7449
8095
|
exports.medianBubbleRadius = medianBubbleRadius;
|
|
7450
8096
|
exports.modulateLuminance = modulateLuminance;
|
|
@@ -7472,16 +8118,20 @@ exports.resolveChartStyleDefinition = resolveChartStyleDefinition;
|
|
|
7472
8118
|
exports.resolveDataLabelFlags = resolveDataLabelFlags;
|
|
7473
8119
|
exports.resolveManualLayoutRect = resolveManualLayoutRect;
|
|
7474
8120
|
exports.scottBinCount = scottBinCount;
|
|
8121
|
+
exports.seriesMarkerViews = seriesMarkerViews;
|
|
7475
8122
|
exports.shade = shade;
|
|
7476
8123
|
exports.sortGradientStops = sortGradientStops;
|
|
7477
8124
|
exports.squarify = squarify;
|
|
7478
8125
|
exports.stockCandle = stockCandle;
|
|
7479
8126
|
exports.stockSlots = stockSlots;
|
|
8127
|
+
exports.summaryMarkers = summaryMarkers;
|
|
7480
8128
|
exports.sunburstArcPath = sunburstArcPath;
|
|
7481
8129
|
exports.themeColor = themeColor;
|
|
7482
8130
|
exports.tint = tint;
|
|
7483
8131
|
exports.updateGradientStop = updateGradientStop;
|
|
8132
|
+
exports.valueToYLog = valueToYLog;
|
|
7484
8133
|
exports.visibleRuns = visibleRuns;
|
|
8134
|
+
exports.withAxisBounds = withAxisBounds;
|
|
7485
8135
|
exports.withChartGradientDirection = withChartGradientDirection;
|
|
7486
8136
|
exports.withinLinearTransform = withinLinearTransform;
|
|
7487
8137
|
exports.writeChartAxisFormatting = writeChartAxisFormatting;
|