@rowsncolumns/charts 28.1.6 → 28.1.8

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.
Files changed (43) hide show
  1. package/dist/cjs/basic-chart/basic-chart.d.ts +1 -1
  2. package/dist/cjs/basic-chart/basic-chart.d.ts.map +1 -1
  3. package/dist/cjs/basic-chart/basic-chart.js +207 -152
  4. package/dist/cjs/components/editors/chart-editor.d.ts.map +1 -1
  5. package/dist/cjs/components/editors/chart-editor.js +5 -1
  6. package/dist/cjs/plotly/basic-chart/basic-chart.d.ts +1 -1
  7. package/dist/cjs/plotly/basic-chart/basic-chart.d.ts.map +1 -1
  8. package/dist/cjs/plotly/basic-chart/basic-chart.js +169 -96
  9. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  10. package/dist/cjs/utils/axis-number-format.d.ts +26 -7
  11. package/dist/cjs/utils/axis-number-format.d.ts.map +1 -1
  12. package/dist/cjs/utils/axis-number-format.js +94 -16
  13. package/dist/cjs/utils/doughnut.d.ts +19 -0
  14. package/dist/cjs/utils/doughnut.d.ts.map +1 -0
  15. package/dist/cjs/utils/doughnut.js +28 -0
  16. package/dist/cjs/utils/overrides.d.ts +12 -3
  17. package/dist/cjs/utils/overrides.d.ts.map +1 -1
  18. package/dist/cjs/utils/overrides.js +41 -16
  19. package/dist/cjs/utils/radar.d.ts +31 -5
  20. package/dist/cjs/utils/radar.d.ts.map +1 -1
  21. package/dist/cjs/utils/radar.js +67 -27
  22. package/dist/esm/basic-chart/basic-chart.d.ts +1 -1
  23. package/dist/esm/basic-chart/basic-chart.d.ts.map +1 -1
  24. package/dist/esm/basic-chart/basic-chart.js +129 -63
  25. package/dist/esm/components/editors/chart-editor.d.ts.map +1 -1
  26. package/dist/esm/components/editors/chart-editor.js +5 -1
  27. package/dist/esm/plotly/basic-chart/basic-chart.d.ts +1 -1
  28. package/dist/esm/plotly/basic-chart/basic-chart.d.ts.map +1 -1
  29. package/dist/esm/plotly/basic-chart/basic-chart.js +99 -23
  30. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  31. package/dist/esm/utils/axis-number-format.d.ts +26 -7
  32. package/dist/esm/utils/axis-number-format.d.ts.map +1 -1
  33. package/dist/esm/utils/axis-number-format.js +83 -13
  34. package/dist/esm/utils/doughnut.d.ts +19 -0
  35. package/dist/esm/utils/doughnut.d.ts.map +1 -0
  36. package/dist/esm/utils/doughnut.js +21 -0
  37. package/dist/esm/utils/overrides.d.ts +12 -3
  38. package/dist/esm/utils/overrides.d.ts.map +1 -1
  39. package/dist/esm/utils/overrides.js +40 -16
  40. package/dist/esm/utils/radar.d.ts +31 -5
  41. package/dist/esm/utils/radar.d.ts.map +1 -1
  42. package/dist/esm/utils/radar.js +44 -16
  43. package/package.json +4 -4
@@ -1 +1 @@
1
- {"root":["../../config.ts","../../echarts-gl.d.ts","../../geo-modules.d.ts","../../index.ts","../../plotly-dist.d.ts","../../types.ts","../../vitest.config.ts","../../atoms/editing-chart.atom.ts","../../atoms/pivot-chart.atom.ts","../../basic-chart/basic-chart.tsx","../../basic-chart/helpers.ts","../../basic-chart/index.tsx","../../components/dialogs/chart-editor-dialog.tsx","../../components/dialogs/pivot-chart-dialog.tsx","../../components/editors/chart-editor.tsx","../../components/editors/chart-range-input.tsx","../../hooks/use-chart-editor.ts","../../hooks/use-charts.ts","../../hooks/use-on-create-chart.ts","../../hooks/use-on-delete-chart.ts","../../hooks/use-on-move-chart-to-sheet.ts","../../hooks/use-on-move-chart.ts","../../hooks/use-on-resize-chart.ts","../../hooks/use-on-update-chart.ts","../../interface/create-chart.ts","../../interface/delete-chart.ts","../../interface/move-chart-to-sheet.ts","../../interface/move-chart.ts","../../interface/resize-chart.ts","../../interface/shift-chart-ranges.ts","../../interface/update-chart.ts","../../plotly/plot.ts","../../plotly/basic-chart/basic-chart.tsx","../../plotly/basic-chart/helpers.ts","../../plotly/basic-chart/index.tsx","../../utils/aggregation.ts","../../utils/axis-number-format.ts","../../utils/bar-layout.ts","../../utils/boxplot.ts","../../utils/bubble.ts","../../utils/category-levels.ts","../../utils/chart-image.ts","../../utils/chart-orientation.ts","../../utils/chart-spec-utils.ts","../../utils/chart-styles.ts","../../utils/echarts-gl-loader.ts","../../utils/empty-cells.ts","../../utils/error-bars.ts","../../utils/gradient.ts","../../utils/hierarchy.ts","../../utils/histogram.ts","../../utils/legend-layout.ts","../../utils/of-pie.ts","../../utils/overrides.ts","../../utils/pie-explosion.ts","../../utils/plotly-click.ts","../../utils/plotly-surface.ts","../../utils/plotly-title.ts","../../utils/radar.ts","../../utils/region-map-loader.ts","../../utils/region-map.ts","../../utils/series-click.ts","../../utils/stock.ts","../../utils/three-d.ts","../../utils/trendline.ts","../../utils/waterfall.ts","../../utils/webgl.ts"],"version":"5.8.3"}
1
+ {"root":["../../config.ts","../../echarts-gl.d.ts","../../geo-modules.d.ts","../../index.ts","../../plotly-dist.d.ts","../../types.ts","../../vitest.config.ts","../../atoms/editing-chart.atom.ts","../../atoms/pivot-chart.atom.ts","../../basic-chart/basic-chart.tsx","../../basic-chart/helpers.ts","../../basic-chart/index.tsx","../../components/dialogs/chart-editor-dialog.tsx","../../components/dialogs/pivot-chart-dialog.tsx","../../components/editors/chart-editor.tsx","../../components/editors/chart-range-input.tsx","../../hooks/use-chart-editor.ts","../../hooks/use-charts.ts","../../hooks/use-on-create-chart.ts","../../hooks/use-on-delete-chart.ts","../../hooks/use-on-move-chart-to-sheet.ts","../../hooks/use-on-move-chart.ts","../../hooks/use-on-resize-chart.ts","../../hooks/use-on-update-chart.ts","../../interface/create-chart.ts","../../interface/delete-chart.ts","../../interface/move-chart-to-sheet.ts","../../interface/move-chart.ts","../../interface/resize-chart.ts","../../interface/shift-chart-ranges.ts","../../interface/update-chart.ts","../../plotly/plot.ts","../../plotly/basic-chart/basic-chart.tsx","../../plotly/basic-chart/helpers.ts","../../plotly/basic-chart/index.tsx","../../utils/aggregation.ts","../../utils/axis-number-format.ts","../../utils/bar-layout.ts","../../utils/boxplot.ts","../../utils/bubble.ts","../../utils/category-levels.ts","../../utils/chart-image.ts","../../utils/chart-orientation.ts","../../utils/chart-spec-utils.ts","../../utils/chart-styles.ts","../../utils/doughnut.ts","../../utils/echarts-gl-loader.ts","../../utils/empty-cells.ts","../../utils/error-bars.ts","../../utils/gradient.ts","../../utils/hierarchy.ts","../../utils/histogram.ts","../../utils/legend-layout.ts","../../utils/of-pie.ts","../../utils/overrides.ts","../../utils/pie-explosion.ts","../../utils/plotly-click.ts","../../utils/plotly-surface.ts","../../utils/plotly-title.ts","../../utils/radar.ts","../../utils/region-map-loader.ts","../../utils/region-map.ts","../../utils/series-click.ts","../../utils/stock.ts","../../utils/three-d.ts","../../utils/trendline.ts","../../utils/waterfall.ts","../../utils/webgl.ts"],"version":"5.8.3"}
@@ -26,17 +26,28 @@ export declare const resolveValueAxisNumberFormat: ({ axisOptions, series, getFo
26
26
  getFormattingFromRange: RangeFormatReader | undefined;
27
27
  hiddenDimensionStrategy?: HIDDEN_DIMENSION_STRATEGY | null;
28
28
  }) => string | undefined;
29
- /** Format one numeric value through the resolved pattern; non-numbers pass through. */
30
- export declare const formatAxisValue: (pattern: string | undefined, value: unknown) => string;
31
- /** echarts `axisLabel.formatter` / `tooltip.valueFormatter` for a value axis. */
32
- export declare const valueAxisLabelFormatter: (pattern: string | undefined) => ((value: unknown) => string) | undefined;
29
+ export declare const formatPlainNumber: (value: number, locale: string | undefined, grouping?: boolean) => string;
30
+ /**
31
+ * Format one numeric value through the resolved pattern; non-numbers pass
32
+ * through. `locale` is the spreadsheet locale the cells format with: it
33
+ * picks the pattern's separators, and a number without a pattern reads
34
+ * like a `General` cell in that locale.
35
+ */
36
+ export declare const formatAxisValue: (pattern: string | undefined, value: unknown, locale?: string) => string;
37
+ /**
38
+ * echarts `axisLabel.formatter` / `tooltip.valueFormatter` for a value
39
+ * axis. Without a pattern the ticks keep echarts' own labels unless a
40
+ * locale is given, in which case they group thousands the way echarts
41
+ * does but with the locale's separators (#1050).
42
+ */
43
+ export declare const valueAxisLabelFormatter: (pattern: string | undefined, locale?: string) => ((value: unknown) => string) | undefined;
33
44
  /**
34
45
  * echarts `tooltip.valueFormatter` for a series whose data items are
35
46
  * tuples (candlestick, 3-D points): every number formats through the
36
47
  * pattern; `undefined` when there is no pattern so echarts keeps its
37
48
  * default.
38
49
  */
39
- export declare const tooltipValueFormatter: (pattern: string | undefined) => ((value: unknown) => string | string[]) | undefined;
50
+ export declare const tooltipValueFormatter: (pattern: string | undefined, locale?: string) => ((value: unknown) => string | string[]) | undefined;
40
51
  /**
41
52
  * Excel's data labels and tooltips are linked to *each series' own* source
42
53
  * cells, not to the axis: a revenue series formatted `$#,##0` next to a
@@ -45,11 +56,18 @@ export declare const tooltipValueFormatter: (pattern: string | undefined) => ((v
45
56
  */
46
57
  export declare const resolveSeriesNumberFormats: (series: Pick<ChartData, "sources">[] | undefined, getFormattingFromRange: RangeFormatReader | undefined, hiddenDimensionStrategy?: HIDDEN_DIMENSION_STRATEGY | null) => (string | undefined)[];
47
58
  /** echarts pie / doughnut tooltip: `name: value (percent%)` with the value formatted. */
48
- export declare const circularTooltipFormatter: (pattern: string | undefined) => (params: {
59
+ export declare const circularTooltipFormatter: (pattern: string | undefined, locale?: string) => (params: {
49
60
  name?: string;
50
61
  value?: unknown;
51
62
  percent?: number;
52
63
  }) => string;
64
+ /**
65
+ * plotly `layout.separators` for the spreadsheet locale: the decimal
66
+ * separator followed by the thousands separator, so ticks and hover
67
+ * values plotly formats itself read like the sheet's cells (#1050).
68
+ * `undefined` without a locale keeps plotly's default (`.,`).
69
+ */
70
+ export declare const plotlySeparators: (locale: string | undefined) => string | undefined;
53
71
  export type PlotlyTickFormat = {
54
72
  tickformat?: string;
55
73
  tickprefix?: string;
@@ -73,9 +91,10 @@ export declare const numberFormatToPlotlyTicks: (pattern: string | undefined) =>
73
91
  * measured; the fixed default of 50px only fits labels up to ~4 digits and
74
92
  * lets a currency axis title paint over its own tick labels.
75
93
  */
76
- export declare const valueAxisNameGap: ({ values, pattern, fontSize, minimum, }: {
94
+ export declare const valueAxisNameGap: ({ values, pattern, locale, fontSize, minimum, }: {
77
95
  values: readonly unknown[];
78
96
  pattern: string | undefined;
97
+ locale?: string;
79
98
  fontSize?: number;
80
99
  minimum?: number;
81
100
  }) => number;
@@ -1 +1 @@
1
- {"version":3,"file":"axis-number-format.d.ts","sourceRoot":"","sources":["../../../utils/axis-number-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,yBAAyB,EACzB,KAAK,EACL,UAAU,EACX,MAAM,2BAA2B,CAAC;AAWnC,KAAK,iBAAiB,GAAG,CACvB,UAAU,EAAE,UAAU,EACtB,uBAAuB,CAAC,EAAE,yBAAyB,KAChD,OAAO,EAAE,CAAC;AAMf;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS,KAAK,CAAC,MAAM,CAAC,GAAG,SAAS,YAGjC,CAAC;AAExC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GACpC,SAAS,UAAU,EAAE,GAAG,SAAS,EACjC,wBAAwB,iBAAiB,GAAG,SAAS,EACrD,0BAA0B,yBAAyB,GAAG,IAAI,KACzD,MAAM,GAAG,SAWX,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,GAAI,2EAK1C;IACD,WAAW,EAAE,KAAK,CAAC;QAAE,mBAAmB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC,GAAG,SAAS,CAAC;IACxE,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;IACrC,sBAAsB,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACtD,uBAAuB,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC5D,KAAG,MAAM,GAAG,SAQZ,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,GAAG,SAAS,EAC3B,OAAO,OAAO,KACb,MAIF,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,GAAI,SAAS,MAAM,GAAG,SAAS,cAC/C,OAAO,wBAAgD,CAAC;AAE5E;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,GAAG,SAAS,cAEnD,OAAO,mCAIN,CAAC;AAEhB;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GACrC,QAAQ,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,GAAG,SAAS,EAChD,wBAAwB,iBAAiB,GAAG,SAAS,EACrD,0BAA0B,yBAAyB,GAAG,IAAI,KACzD,CAAC,MAAM,GAAG,SAAS,CAAC,EAOpB,CAAC;AAEJ,yFAAyF;AACzF,eAAO,MAAM,wBAAwB,GAClC,SAAS,MAAM,GAAG,SAAS,MAC3B,QAAQ;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,WAGvD,CAAC;AAET,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GACpC,SAAS,MAAM,GAAG,SAAS,KAC1B,gBAAgB,GAAG,SA4DrB,CAAC;AA2BF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,yCAK9B;IACD,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,KAAG,MAgBH,CAAC"}
1
+ {"version":3,"file":"axis-number-format.d.ts","sourceRoot":"","sources":["../../../utils/axis-number-format.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.valueAxisNameGap = exports.numberFormatToPlotlyTicks = exports.circularTooltipFormatter = exports.resolveSeriesNumberFormats = exports.tooltipValueFormatter = exports.valueAxisLabelFormatter = exports.formatAxisValue = exports.resolveValueAxisNumberFormat = exports.resolveSourceNumberFormat = exports.isGeneralNumberFormat = void 0;
3
+ exports.valueAxisNameGap = exports.numberFormatToPlotlyTicks = exports.plotlySeparators = exports.circularTooltipFormatter = exports.resolveSeriesNumberFormats = exports.tooltipValueFormatter = exports.valueAxisLabelFormatter = exports.formatAxisValue = exports.formatPlainNumber = exports.resolveValueAxisNumberFormat = exports.resolveSourceNumberFormat = exports.isGeneralNumberFormat = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var utils_1 = require("@rowsncolumns/utils");
6
6
  var patternOf = function (format) {
@@ -62,18 +62,74 @@ var resolveValueAxisNumberFormat = function (_a) {
62
62
  return (0, exports.resolveSourceNumberFormat)((_b = series[0]) === null || _b === void 0 ? void 0 : _b.sources, getFormattingFromRange, hiddenDimensionStrategy);
63
63
  };
64
64
  exports.resolveValueAxisNumberFormat = resolveValueAxisNumberFormat;
65
- /** Format one numeric value through the resolved pattern; non-numbers pass through. */
66
- var formatAxisValue = function (pattern, value) {
65
+ // A number with no number format, in the spreadsheet locale (#1050). The
66
+ // grid's cells show such a value through `General` — the locale's decimal
67
+ // separator, no grouping — so a data label or tooltip reads the same;
68
+ // echarts' default tick label groups thousands, so ticks keep grouping.
69
+ // `toPrecision(15)` is Excel's significant-digit view of the double, which
70
+ // drops binary noise such as `0.30000000000000004`.
71
+ var plainNumberFormatters = new Map();
72
+ var plainNumberFormatter = function (locale, grouping) {
73
+ var key = "".concat(locale, "\0").concat(grouping ? 1 : 0);
74
+ var formatter = plainNumberFormatters.get(key);
75
+ if (!formatter) {
76
+ try {
77
+ formatter = new Intl.NumberFormat(locale, {
78
+ useGrouping: grouping,
79
+ maximumFractionDigits: 20,
80
+ });
81
+ }
82
+ catch (_a) {
83
+ formatter = new Intl.NumberFormat("en-US", {
84
+ useGrouping: grouping,
85
+ maximumFractionDigits: 20,
86
+ });
87
+ }
88
+ plainNumberFormatters.set(key, formatter);
89
+ }
90
+ return formatter;
91
+ };
92
+ var formatPlainNumber = function (value, locale, grouping) {
93
+ if (grouping === void 0) { grouping = false; }
94
+ return Number.isFinite(value)
95
+ ? plainNumberFormatter(locale !== null && locale !== void 0 ? locale : "en-US", grouping).format(Number(value.toPrecision(15)))
96
+ : String(value);
97
+ };
98
+ exports.formatPlainNumber = formatPlainNumber;
99
+ /**
100
+ * Format one numeric value through the resolved pattern; non-numbers pass
101
+ * through. `locale` is the spreadsheet locale the cells format with: it
102
+ * picks the pattern's separators, and a number without a pattern reads
103
+ * like a `General` cell in that locale.
104
+ */
105
+ var formatAxisValue = function (pattern, value, locale) {
67
106
  if (value === undefined || value === null)
68
107
  return "";
69
- if (pattern && typeof value === "number")
70
- return (0, utils_1.ssfFormat)(pattern, value);
108
+ if (typeof value === "number") {
109
+ if (pattern)
110
+ return (0, utils_1.ssfFormat)(pattern, value, locale);
111
+ if (locale)
112
+ return (0, exports.formatPlainNumber)(value, locale);
113
+ }
71
114
  return String(value);
72
115
  };
73
116
  exports.formatAxisValue = formatAxisValue;
74
- /** echarts `axisLabel.formatter` / `tooltip.valueFormatter` for a value axis. */
75
- var valueAxisLabelFormatter = function (pattern) {
76
- return pattern ? function (value) { return (0, exports.formatAxisValue)(pattern, value); } : undefined;
117
+ /**
118
+ * echarts `axisLabel.formatter` / `tooltip.valueFormatter` for a value
119
+ * axis. Without a pattern the ticks keep echarts' own labels unless a
120
+ * locale is given, in which case they group thousands the way echarts
121
+ * does but with the locale's separators (#1050).
122
+ */
123
+ var valueAxisLabelFormatter = function (pattern, locale) {
124
+ return pattern
125
+ ? function (value) { return (0, exports.formatAxisValue)(pattern, value, locale); }
126
+ : locale
127
+ ? function (value) {
128
+ return typeof value === "number"
129
+ ? (0, exports.formatPlainNumber)(value, locale, true)
130
+ : (0, exports.formatAxisValue)(undefined, value);
131
+ }
132
+ : undefined;
77
133
  };
78
134
  exports.valueAxisLabelFormatter = valueAxisLabelFormatter;
79
135
  /**
@@ -82,12 +138,12 @@ exports.valueAxisLabelFormatter = valueAxisLabelFormatter;
82
138
  * pattern; `undefined` when there is no pattern so echarts keeps its
83
139
  * default.
84
140
  */
85
- var tooltipValueFormatter = function (pattern) {
141
+ var tooltipValueFormatter = function (pattern, locale) {
86
142
  return pattern
87
143
  ? function (value) {
88
144
  return Array.isArray(value)
89
- ? value.map(function (entry) { return (0, exports.formatAxisValue)(pattern, entry); })
90
- : (0, exports.formatAxisValue)(pattern, value);
145
+ ? value.map(function (entry) { return (0, exports.formatAxisValue)(pattern, entry, locale); })
146
+ : (0, exports.formatAxisValue)(pattern, value, locale);
91
147
  }
92
148
  : undefined;
93
149
  };
@@ -105,13 +161,35 @@ var resolveSeriesNumberFormats = function (series, getFormattingFromRange, hidde
105
161
  };
106
162
  exports.resolveSeriesNumberFormats = resolveSeriesNumberFormats;
107
163
  /** echarts pie / doughnut tooltip: `name: value (percent%)` with the value formatted. */
108
- var circularTooltipFormatter = function (pattern) {
164
+ var circularTooltipFormatter = function (pattern, locale) {
109
165
  return function (params) {
110
166
  var _a, _b;
111
- return "".concat((_a = params.name) !== null && _a !== void 0 ? _a : "", ": ").concat((0, exports.formatAxisValue)(pattern, params.value), " (").concat((_b = params.percent) !== null && _b !== void 0 ? _b : "", "%)");
167
+ return "".concat((_a = params.name) !== null && _a !== void 0 ? _a : "", ": ").concat((0, exports.formatAxisValue)(pattern, params.value, locale), " (").concat((_b = params.percent) !== null && _b !== void 0 ? _b : "", "%)");
112
168
  };
113
169
  };
114
170
  exports.circularTooltipFormatter = circularTooltipFormatter;
171
+ /**
172
+ * plotly `layout.separators` for the spreadsheet locale: the decimal
173
+ * separator followed by the thousands separator, so ticks and hover
174
+ * values plotly formats itself read like the sheet's cells (#1050).
175
+ * `undefined` without a locale keeps plotly's default (`.,`).
176
+ */
177
+ var plotlySeparators = function (locale) {
178
+ var _a, _b, _c, _d;
179
+ if (!locale)
180
+ return undefined;
181
+ var parts;
182
+ try {
183
+ parts = new Intl.NumberFormat(locale).formatToParts(1234.5);
184
+ }
185
+ catch (_e) {
186
+ return undefined;
187
+ }
188
+ var decimal = (_b = (_a = parts.find(function (p) { return p.type === "decimal"; })) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ".";
189
+ var group = (_d = (_c = parts.find(function (p) { return p.type === "group"; })) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : ",";
190
+ return "".concat(decimal).concat(group);
191
+ };
192
+ exports.plotlySeparators = plotlySeparators;
115
193
  /**
116
194
  * Translate the numeric subset of a SpreadsheetML pattern into plotly's
117
195
  * d3-format axis settings (`tickformat` + literal prefix / suffix). Plotly
@@ -238,16 +316,16 @@ var measureLabelWidth = function (text, fontSize) {
238
316
  * lets a currency axis title paint over its own tick labels.
239
317
  */
240
318
  var valueAxisNameGap = function (_a) {
241
- var values = _a.values, pattern = _a.pattern, _b = _a.fontSize, fontSize = _b === void 0 ? 12 : _b, _c = _a.minimum, minimum = _c === void 0 ? 50 : _c;
319
+ var values = _a.values, pattern = _a.pattern, locale = _a.locale, _b = _a.fontSize, fontSize = _b === void 0 ? 12 : _b, _c = _a.minimum, minimum = _c === void 0 ? 50 : _c;
242
320
  var numbers = values.filter(function (v) { return typeof v === "number" && Number.isFinite(v); });
243
321
  if (!numbers.length)
244
322
  return minimum;
245
323
  var min = Math.min.apply(Math, tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(numbers), false), [0], false));
246
324
  var max = Math.max.apply(Math, tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(numbers), false), [0], false));
247
325
  // echarts' default axis label puts thousands separators on plain numbers.
248
- var defaultLabel = function (v) { return v.toLocaleString("en-US"); };
326
+ var defaultLabel = function (v) { return (0, exports.formatPlainNumber)(v, locale, true); };
249
327
  var labels = [min, max].map(function (v) {
250
- return pattern ? (0, exports.formatAxisValue)(pattern, v) : defaultLabel(v);
328
+ return pattern ? (0, exports.formatAxisValue)(pattern, v, locale) : defaultLabel(v);
251
329
  });
252
330
  var widest = Math.max.apply(Math, tslib_1.__spreadArray([], tslib_1.__read(labels.map(function (l) { return measureLabelWidth(l, fontSize); })), false));
253
331
  // 8px tick-label margin + the rotated title's own line box + breathing room.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Doughnut geometry shared by the renderers (rowsncolumns/spreadsheet#1064,
3
+ * #1065). Every fraction here is of the doughnut's OUTER radius — Excel's
4
+ * `<c:holeSize val="75"/>` is 0.75 of the outer edge, whatever the chart
5
+ * draws that edge at (echarts: 75% of the chart; plotly: the trace domain).
6
+ */
7
+ /** `doughnutHoleSize` clamped to Excel's 0-90% range; 0.5 when unset. */
8
+ export declare const clampDoughnutHole: (hole: unknown) => number;
9
+ export type DoughnutRing = {
10
+ inner: number;
11
+ outer: number;
12
+ };
13
+ /**
14
+ * Excel draws a doughnut's series as concentric rings, nested from the hole
15
+ * outwards — series 0 innermost — splitting the band between the hole and
16
+ * the outer edge evenly. One ring (the whole band) for a single series.
17
+ */
18
+ export declare const doughnutRings: (hole: number, count: number) => DoughnutRing[];
19
+ //# sourceMappingURL=doughnut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doughnut.d.ts","sourceRoot":"","sources":["../../../utils/doughnut.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,GAAI,MAAM,OAAO,KAAG,MACiB,CAAC;AAEpE,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,YAAY,EAOvE,CAAC"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * Doughnut geometry shared by the renderers (rowsncolumns/spreadsheet#1064,
4
+ * #1065). Every fraction here is of the doughnut's OUTER radius — Excel's
5
+ * `<c:holeSize val="75"/>` is 0.75 of the outer edge, whatever the chart
6
+ * draws that edge at (echarts: 75% of the chart; plotly: the trace domain).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.doughnutRings = exports.clampDoughnutHole = void 0;
10
+ /** `doughnutHoleSize` clamped to Excel's 0-90% range; 0.5 when unset. */
11
+ var clampDoughnutHole = function (hole) {
12
+ return typeof hole === "number" ? Math.max(0, Math.min(0.9, hole)) : 0.5;
13
+ };
14
+ exports.clampDoughnutHole = clampDoughnutHole;
15
+ /**
16
+ * Excel draws a doughnut's series as concentric rings, nested from the hole
17
+ * outwards — series 0 innermost — splitting the band between the hole and
18
+ * the outer edge evenly. One ring (the whole band) for a single series.
19
+ */
20
+ var doughnutRings = function (hole, count) {
21
+ var n = Math.max(1, Math.floor(count));
22
+ var band = 1 - hole;
23
+ return Array.from({ length: n }, function (_, k) { return ({
24
+ inner: hole + (band * k) / n,
25
+ outer: hole + (band * (k + 1)) / n,
26
+ }); });
27
+ };
28
+ exports.doughnutRings = doughnutRings;
@@ -7,9 +7,18 @@ export declare const applyLegendOverrides: (legend: LegendComponentOption, opts:
7
7
  * the linked source-cell format — see `resolveValueAxisNumberFormat`); it
8
8
  * becomes the tick-label formatter.
9
9
  */
10
- export declare const applyAxisOverrides: (axis: any, opts: any, numberFormatPattern?: string) => any;
11
- export declare const dataLabelFormatter: (opts: any) => (params: any) => string;
12
- export declare const buildSeriesLabelOption: (opts: any) => {
10
+ export declare const applyAxisOverrides: (axis: any, opts: any, numberFormatPattern?: string, locale?: string) => any;
11
+ export declare const dataLabelFormatter: (opts: any, locale?: string) => (params: any) => string;
12
+ /**
13
+ * The data-label options one series renders with: its own
14
+ * `ChartData.dataLabels` when it has them (OOXML's `<c:ser><c:dLbls>`
15
+ * override — `{ show: false }` turns a labelled chart's labels off for
16
+ * that series alone), else the chart-level `ChartSpec.dataLabels`.
17
+ */
18
+ export declare const resolveSeriesDataLabels: <T>(chartLevel: T | null | undefined, series: {
19
+ dataLabels?: T | null;
20
+ } | null | undefined) => T | null | undefined;
21
+ export declare const buildSeriesLabelOption: (opts: any, seriesType?: string, locale?: string) => {
13
22
  readonly show: true;
14
23
  readonly position: any;
15
24
  readonly formatter: (params: any) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"overrides.d.ts","sourceRoot":"","sources":["../../../utils/overrides.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAWrD,oEAAoE;AACpE,eAAO,MAAM,4BAA4B,GAAI,KAAK,GAAG,oCASpD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,qBAAqB,EAC7B,MAAM,GAAG,KACR,qBA6CF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,GAAG,EACT,MAAM,GAAG,EACT,sBAAsB,MAAM,QA4B7B,CAAC;AAqBF,eAAO,MAAM,kBAAkB,GAAI,MAAM,GAAG,MAAM,QAAQ,GAAG,WA4B5D,CAAC;AAWF,eAAO,MAAM,sBAAsB,GAAI,MAAM,GAAG;;;iCAvCU,GAAG;aA+C5D,CAAC"}
1
+ {"version":3,"file":"overrides.d.ts","sourceRoot":"","sources":["../../../utils/overrides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAWrD,oEAAoE;AACpE,eAAO,MAAM,4BAA4B,GAAI,KAAK,GAAG,oCASpD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,qBAAqB,EAC7B,MAAM,GAAG,KACR,qBA6CF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,GAAG,EACT,MAAM,GAAG,EACT,sBAAsB,MAAM,EAC5B,SAAS,MAAM,QA4BhB,CAAC;AAgBF,eAAO,MAAM,kBAAkB,GAAI,MAAM,GAAG,EAAE,SAAS,MAAM,MAAM,QAAQ,GAAG,WAiC7E,CAAC;AAgCF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,EACvC,YAAY,CAAC,GAAG,IAAI,GAAG,SAAS,EAChC,QAAQ;IAAE,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,KACnD,CAAC,GAAG,IAAI,GAAG,SAA6C,CAAC;AAE5D,eAAO,MAAM,sBAAsB,GACjC,MAAM,GAAG,EACT,aAAa,MAAM,EACnB,SAAS,MAAM;;;iCA/E0D,GAAG;aA4F7E,CAAC"}
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildSeriesLabelOption = exports.dataLabelFormatter = exports.applyAxisOverrides = exports.applyLegendOverrides = exports.textFormatToEchartsTextStyle = void 0;
3
+ exports.buildSeriesLabelOption = exports.resolveSeriesDataLabels = exports.dataLabelFormatter = exports.applyAxisOverrides = exports.applyLegendOverrides = exports.textFormatToEchartsTextStyle = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var utils_1 = require("@rowsncolumns/utils");
6
5
  var axis_number_format_1 = require("./axis-number-format");
7
6
  // Map ChartSpec.legend / dataLabels / axisOptions to ECharts option
8
7
  // fragments. Each helper is a no-op when the spec field is missing, so
@@ -82,9 +81,9 @@ exports.applyLegendOverrides = applyLegendOverrides;
82
81
  * the linked source-cell format — see `resolveValueAxisNumberFormat`); it
83
82
  * becomes the tick-label formatter.
84
83
  */
85
- var applyAxisOverrides = function (axis, opts, numberFormatPattern) {
84
+ var applyAxisOverrides = function (axis, opts, numberFormatPattern, locale) {
86
85
  var _a, _b, _c, _d, _e;
87
- var formatter = (0, axis_number_format_1.valueAxisLabelFormatter)(numberFormatPattern);
86
+ var formatter = (0, axis_number_format_1.valueAxisLabelFormatter)(numberFormatPattern, locale);
88
87
  if (!opts && !formatter)
89
88
  return axis;
90
89
  var next = tslib_1.__assign({}, axis);
@@ -126,14 +125,8 @@ exports.applyAxisOverrides = applyAxisOverrides;
126
125
  * over the normalized percentage so labels read "$1,831" not "84.6"
127
126
  * — Excel's behaviour.
128
127
  */
129
- var formatLabelValue = function (rawValue, originalValue, pattern) {
130
- var target = originalValue !== null && originalValue !== void 0 ? originalValue : rawValue;
131
- if (pattern) {
132
- return (0, utils_1.ssfFormat)(pattern, target);
133
- }
134
- return target === undefined || target === null ? "" : String(target);
135
- };
136
- var dataLabelFormatter = function (opts) { return function (params) {
128
+ var formatLabelValue = function (rawValue, originalValue, pattern, locale) { return (0, axis_number_format_1.formatAxisValue)(pattern, originalValue !== null && originalValue !== void 0 ? originalValue : rawValue, locale); };
129
+ var dataLabelFormatter = function (opts, locale) { return function (params) {
137
130
  var parts = [];
138
131
  if (opts.showSeriesName && params.seriesName)
139
132
  parts.push(params.seriesName);
@@ -156,7 +149,7 @@ var dataLabelFormatter = function (opts) { return function (params) {
156
149
  var originalValue = typeof params.data === "object" && params.data
157
150
  ? params.data.originalValue
158
151
  : undefined;
159
- parts.push(formatLabelValue(params.value, originalValue, opts.numberFormatPattern));
152
+ parts.push(formatLabelValue(params.value, originalValue, opts.numberFormatPattern, locale));
160
153
  }
161
154
  return parts.join(": ");
162
155
  }; };
@@ -168,16 +161,48 @@ var ECHARTS_DLBL_POS = {
168
161
  insideEnd: "insideTop",
169
162
  outsideEnd: "top",
170
163
  bestFit: "top",
164
+ above: "top",
165
+ below: "bottom",
166
+ left: "left",
167
+ right: "right",
171
168
  };
172
- var buildSeriesLabelOption = function (opts) {
169
+ // A line / scatter label sits on a point, not in a bar: echarts has no
170
+ // `outside` / `insideTop` for it (an unknown position is drawn at the
171
+ // default) and Excel offers centre / left / right / above / below. The
172
+ // bar-only placements land on Excel's default for a line, above the point.
173
+ var ECHARTS_POINT_DLBL_POS = {
174
+ center: "inside",
175
+ inside: "inside",
176
+ outside: "top",
177
+ insideEnd: "top",
178
+ outsideEnd: "top",
179
+ bestFit: "top",
180
+ above: "top",
181
+ below: "bottom",
182
+ left: "left",
183
+ right: "right",
184
+ };
185
+ var POINT_SERIES_TYPES = new Set(["line", "scatter", "effectScatter"]);
186
+ /**
187
+ * The data-label options one series renders with: its own
188
+ * `ChartData.dataLabels` when it has them (OOXML's `<c:ser><c:dLbls>`
189
+ * override — `{ show: false }` turns a labelled chart's labels off for
190
+ * that series alone), else the chart-level `ChartSpec.dataLabels`.
191
+ */
192
+ var resolveSeriesDataLabels = function (chartLevel, series) { var _a; return (_a = series === null || series === void 0 ? void 0 : series.dataLabels) !== null && _a !== void 0 ? _a : chartLevel; };
193
+ exports.resolveSeriesDataLabels = resolveSeriesDataLabels;
194
+ var buildSeriesLabelOption = function (opts, seriesType, locale) {
173
195
  var _a;
174
196
  if (!(opts === null || opts === void 0 ? void 0 : opts.show))
175
197
  return undefined;
176
- var position = (_a = (opts.position && ECHARTS_DLBL_POS[opts.position])) !== null && _a !== void 0 ? _a : "top";
198
+ var positions = seriesType && POINT_SERIES_TYPES.has(seriesType)
199
+ ? ECHARTS_POINT_DLBL_POS
200
+ : ECHARTS_DLBL_POS;
201
+ var position = (_a = (opts.position && positions[opts.position])) !== null && _a !== void 0 ? _a : "top";
177
202
  return {
178
203
  show: true,
179
204
  position: position,
180
- formatter: (0, exports.dataLabelFormatter)(opts),
205
+ formatter: (0, exports.dataLabelFormatter)(opts, locale),
181
206
  };
182
207
  };
183
208
  exports.buildSeriesLabelOption = buildSeriesLabelOption;
@@ -16,15 +16,41 @@ export type RadarSeriesInput = {
16
16
  };
17
17
  export type RadarIndicator = {
18
18
  name: string;
19
+ min: number;
19
20
  max: number;
20
21
  };
22
+ export type RadarAxisScale = {
23
+ min: number;
24
+ max: number;
25
+ };
26
+ /** The value-axis options a radar's common scale reads (`ChartAxisOptions`). */
27
+ export type RadarAxisOptions = {
28
+ min?: number | null;
29
+ max?: number | null;
30
+ visible?: boolean | null;
31
+ } | null | undefined;
32
+ /**
33
+ * The next "nice" axis bound at or above `value` — the top tick a value
34
+ * axis would auto-scale to: the step is 1 / 2 / 5 × a power of ten sized
35
+ * for about five divisions, and the bound is the first multiple of that
36
+ * step at or above the value (9 → 10, 33 → 40, 0.7 → 0.8).
37
+ */
38
+ export declare const niceAxisCeiling: (value: number) => number;
39
+ /**
40
+ * One value scale shared by every radar axis, as Excel draws it: `max` is
41
+ * the spec's `valueAxisOptions.max` when set, else the largest value across
42
+ * all series and categories rounded up to a nice bound (never below 1);
43
+ * `min` is `valueAxisOptions.min` when set (and below `max`), else 0.
44
+ */
45
+ export declare const radarValueScale: (series: RadarSeriesInput[], axisOptions?: RadarAxisOptions) => RadarAxisScale;
21
46
  /**
22
- * Build echarts radar indicators from category labels and series.
23
- * The `max` per indicator is the largest value seen across all series at
24
- * that category (rounded up a touch so the polygon doesn't touch the
25
- * rim). When every series is empty at an index, `max` defaults to 1.
47
+ * Build echarts radar indicators from category labels and series. Every
48
+ * indicator carries the SAME `min` / `max` — the common scale of
49
+ * {@link radarValueScale} — so values on different axes compare, and a
50
+ * single series draws the shape of its data rather than a regular polygon
51
+ * (rowsncolumns/spreadsheet#1066).
26
52
  */
27
- export declare const buildRadarIndicators: (categories: (string | number | boolean | null | undefined)[], series: RadarSeriesInput[]) => RadarIndicator[];
53
+ export declare const buildRadarIndicators: (categories: (string | number | boolean | null | undefined)[], series: RadarSeriesInput[], axisOptions?: RadarAxisOptions) => RadarIndicator[];
28
54
  /**
29
55
  * Shape series into echarts radar data: one entry per series with its
30
56
  * value vector aligned to the indicator order. Missing/non-numeric
@@ -1 +1 @@
1
- {"version":3,"file":"radar.d.ts","sourceRoot":"","sources":["../../../utils/radar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAQ3D;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EAC5D,QAAQ,gBAAgB,EAAE,KACzB,cAAc,EAahB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,gBAAgB,EAAE,EAC1B,gBAAgB,MAAM,KACrB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAQzC,CAAC"}
1
+ {"version":3,"file":"radar.d.ts","sourceRoot":"","sources":["../../../utils/radar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAQxE,MAAM,MAAM,cAAc,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,gFAAgF;AAChF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B,GAAG,IAAI,GAAG,SAAS,CAAC;AAErB;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,MAW/C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,QAAQ,gBAAgB,EAAE,EAC1B,cAAc,gBAAgB,KAC7B,cAaF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EAC5D,QAAQ,gBAAgB,EAAE,EAC1B,cAAc,gBAAgB,KAC7B,cAAc,EAGhB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,gBAAgB,EAAE,EAC1B,gBAAgB,MAAM,KACrB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAQzC,CAAC"}
@@ -12,7 +12,7 @@
12
12
  * labels and per-series numeric values.
13
13
  */
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.buildRadarSeriesData = exports.buildRadarIndicators = void 0;
15
+ exports.buildRadarSeriesData = exports.buildRadarIndicators = exports.radarValueScale = exports.niceAxisCeiling = void 0;
16
16
  var tslib_1 = require("tslib");
17
17
  var isFiniteNum = function (v) {
18
18
  return typeof v === "number" && Number.isFinite(v);
@@ -21,36 +21,76 @@ var toNumber = function (v) {
21
21
  return isFiniteNum(v) ? v : 0;
22
22
  };
23
23
  /**
24
- * Build echarts radar indicators from category labels and series.
25
- * The `max` per indicator is the largest value seen across all series at
26
- * that category (rounded up a touch so the polygon doesn't touch the
27
- * rim). When every series is empty at an index, `max` defaults to 1.
24
+ * The next "nice" axis bound at or above `value` — the top tick a value
25
+ * axis would auto-scale to: the step is 1 / 2 / 5 × a power of ten sized
26
+ * for about five divisions, and the bound is the first multiple of that
27
+ * step at or above the value (9 → 10, 33 → 40, 0.7 → 0.8).
28
28
  */
29
- var buildRadarIndicators = function (categories, series) {
30
- return categories.map(function (label, i) {
31
- var e_1, _a;
32
- var max = 0;
33
- try {
34
- for (var series_1 = tslib_1.__values(series), series_1_1 = series_1.next(); !series_1_1.done; series_1_1 = series_1.next()) {
35
- var s = series_1_1.value;
36
- var v = s.values[i];
37
- if (isFiniteNum(v))
38
- max = Math.max(max, v);
39
- }
40
- }
41
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
42
- finally {
29
+ var niceAxisCeiling = function (value) {
30
+ if (!isFiniteNum(value) || value <= 0)
31
+ return 1;
32
+ var rough = value / 5;
33
+ var magnitude = Math.pow(10, Math.floor(Math.log10(rough)));
34
+ var residual = rough / magnitude;
35
+ var step = (residual <= 1 ? 1 : residual <= 2 ? 2 : residual <= 5 ? 5 : 10) *
36
+ magnitude;
37
+ var ceiling = Math.ceil(value / step - 1e-9) * step;
38
+ // Avoid 0.30000000000000004-style bounds from the float arithmetic.
39
+ return Number(ceiling.toPrecision(12));
40
+ };
41
+ exports.niceAxisCeiling = niceAxisCeiling;
42
+ /**
43
+ * One value scale shared by every radar axis, as Excel draws it: `max` is
44
+ * the spec's `valueAxisOptions.max` when set, else the largest value across
45
+ * all series and categories rounded up to a nice bound (never below 1);
46
+ * `min` is `valueAxisOptions.min` when set (and below `max`), else 0.
47
+ */
48
+ var radarValueScale = function (series, axisOptions) {
49
+ var e_1, _a, e_2, _b;
50
+ var largest = 0;
51
+ try {
52
+ for (var series_1 = tslib_1.__values(series), series_1_1 = series_1.next(); !series_1_1.done; series_1_1 = series_1.next()) {
53
+ var s = series_1_1.value;
43
54
  try {
44
- if (series_1_1 && !series_1_1.done && (_a = series_1.return)) _a.call(series_1);
55
+ for (var _c = (e_2 = void 0, tslib_1.__values(s.values)), _d = _c.next(); !_d.done; _d = _c.next()) {
56
+ var v = _d.value;
57
+ if (isFiniteNum(v))
58
+ largest = Math.max(largest, v);
59
+ }
60
+ }
61
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
62
+ finally {
63
+ try {
64
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
65
+ }
66
+ finally { if (e_2) throw e_2.error; }
45
67
  }
46
- finally { if (e_1) throw e_1.error; }
47
68
  }
48
- return {
49
- name: String(label !== null && label !== void 0 ? label : ""),
50
- // Pad by 10% so the outermost ring has breathing room; never 0.
51
- max: max > 0 ? max * 1.1 : 1,
52
- };
53
- });
69
+ }
70
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
71
+ finally {
72
+ try {
73
+ if (series_1_1 && !series_1_1.done && (_a = series_1.return)) _a.call(series_1);
74
+ }
75
+ finally { if (e_1) throw e_1.error; }
76
+ }
77
+ var max = isFiniteNum(axisOptions === null || axisOptions === void 0 ? void 0 : axisOptions.max)
78
+ ? axisOptions.max
79
+ : (0, exports.niceAxisCeiling)(largest);
80
+ var min = isFiniteNum(axisOptions === null || axisOptions === void 0 ? void 0 : axisOptions.min) && axisOptions.min < max ? axisOptions.min : 0;
81
+ return { min: min, max: max };
82
+ };
83
+ exports.radarValueScale = radarValueScale;
84
+ /**
85
+ * Build echarts radar indicators from category labels and series. Every
86
+ * indicator carries the SAME `min` / `max` — the common scale of
87
+ * {@link radarValueScale} — so values on different axes compare, and a
88
+ * single series draws the shape of its data rather than a regular polygon
89
+ * (rowsncolumns/spreadsheet#1066).
90
+ */
91
+ var buildRadarIndicators = function (categories, series, axisOptions) {
92
+ var _a = (0, exports.radarValueScale)(series, axisOptions), min = _a.min, max = _a.max;
93
+ return categories.map(function (label) { return ({ name: String(label !== null && label !== void 0 ? label : ""), min: min, max: max }); });
54
94
  };
55
95
  exports.buildRadarIndicators = buildRadarIndicators;
56
96
  /**
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
2
  import type { EChartComponentProps } from "../types";
3
3
  export type BasicChartProps = EChartComponentProps;
4
- export declare const BasicChart: ({ width, height, chart, theme, isDarkMode, sheetId, readonly, getDomainValuesFromRange, getSeriesValuesFromRange, getFormattingFromRange, onDeleteChart, onUpdateChart, onRequestEdit, onRequestCalculate, isSelected, fieldButtons, }: BasicChartProps) => React.JSX.Element;
4
+ export declare const BasicChart: ({ width, height, chart, theme, isDarkMode, sheetId, readonly, getDomainValuesFromRange, getSeriesValuesFromRange, getFormattingFromRange, onDeleteChart, onUpdateChart, onRequestEdit, onRequestCalculate, isSelected, fieldButtons, locale, }: BasicChartProps) => React.JSX.Element;
5
5
  //# sourceMappingURL=basic-chart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"basic-chart.d.ts","sourceRoot":"","sources":["../../../basic-chart/basic-chart.tsx"],"names":[],"mappings":"AAkEA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAmQrD,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAqEnD,eAAO,MAAM,UAAU,GAAI,wOAiBxB,eAAe,sBAwzGjB,CAAC"}
1
+ {"version":3,"file":"basic-chart.d.ts","sourceRoot":"","sources":["../../../basic-chart/basic-chart.tsx"],"names":[],"mappings":"AAkEA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAqQrD,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAqEnD,eAAO,MAAM,UAAU,GAAI,gPAkBxB,eAAe,sBAq6GjB,CAAC"}