@rowsncolumns/charts 28.1.7 → 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.
@@ -9,6 +9,15 @@ export declare const applyLegendOverrides: (legend: LegendComponentOption, opts:
9
9
  */
10
10
  export declare const applyAxisOverrides: (axis: any, opts: any, numberFormatPattern?: string, locale?: string) => any;
11
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;
12
21
  export declare const buildSeriesLabelOption: (opts: any, seriesType?: string, locale?: string) => {
13
22
  readonly show: true;
14
23
  readonly position: any;
@@ -1 +1 @@
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,eAAO,MAAM,sBAAsB,GACjC,MAAM,GAAG,EACT,aAAa,MAAM,EACnB,SAAS,MAAM;;;iCApE0D,GAAG;aAiF7E,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"}
@@ -173,6 +173,13 @@ const ECHARTS_POINT_DLBL_POS = {
173
173
  right: "right",
174
174
  };
175
175
  const POINT_SERIES_TYPES = new Set(["line", "scatter", "effectScatter"]);
176
+ /**
177
+ * The data-label options one series renders with: its own
178
+ * `ChartData.dataLabels` when it has them (OOXML's `<c:ser><c:dLbls>`
179
+ * override — `{ show: false }` turns a labelled chart's labels off for
180
+ * that series alone), else the chart-level `ChartSpec.dataLabels`.
181
+ */
182
+ export const resolveSeriesDataLabels = (chartLevel, series) => series?.dataLabels ?? chartLevel;
176
183
  export const buildSeriesLabelOption = (opts, seriesType, locale) => {
177
184
  if (!opts?.show)
178
185
  return undefined;
@@ -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"}
@@ -13,25 +13,53 @@
13
13
  const isFiniteNum = (v) => typeof v === "number" && Number.isFinite(v);
14
14
  const toNumber = (v) => isFiniteNum(v) ? v : 0;
15
15
  /**
16
- * Build echarts radar indicators from category labels and series.
17
- * The `max` per indicator is the largest value seen across all series at
18
- * that category (rounded up a touch so the polygon doesn't touch the
19
- * rim). When every series is empty at an index, `max` defaults to 1.
16
+ * The next "nice" axis bound at or above `value` — the top tick a value
17
+ * axis would auto-scale to: the step is 1 / 2 / 5 × a power of ten sized
18
+ * for about five divisions, and the bound is the first multiple of that
19
+ * step at or above the value (9 → 10, 33 → 40, 0.7 → 0.8).
20
20
  */
21
- export const buildRadarIndicators = (categories, series) => {
22
- return categories.map((label, i) => {
23
- let max = 0;
24
- for (const s of series) {
25
- const v = s.values[i];
21
+ export const niceAxisCeiling = (value) => {
22
+ if (!isFiniteNum(value) || value <= 0)
23
+ return 1;
24
+ const rough = value / 5;
25
+ const magnitude = 10 ** Math.floor(Math.log10(rough));
26
+ const residual = rough / magnitude;
27
+ const step = (residual <= 1 ? 1 : residual <= 2 ? 2 : residual <= 5 ? 5 : 10) *
28
+ magnitude;
29
+ const ceiling = Math.ceil(value / step - 1e-9) * step;
30
+ // Avoid 0.30000000000000004-style bounds from the float arithmetic.
31
+ return Number(ceiling.toPrecision(12));
32
+ };
33
+ /**
34
+ * One value scale shared by every radar axis, as Excel draws it: `max` is
35
+ * the spec's `valueAxisOptions.max` when set, else the largest value across
36
+ * all series and categories rounded up to a nice bound (never below 1);
37
+ * `min` is `valueAxisOptions.min` when set (and below `max`), else 0.
38
+ */
39
+ export const radarValueScale = (series, axisOptions) => {
40
+ let largest = 0;
41
+ for (const s of series) {
42
+ for (const v of s.values) {
26
43
  if (isFiniteNum(v))
27
- max = Math.max(max, v);
44
+ largest = Math.max(largest, v);
28
45
  }
29
- return {
30
- name: String(label ?? ""),
31
- // Pad by 10% so the outermost ring has breathing room; never 0.
32
- max: max > 0 ? max * 1.1 : 1,
33
- };
34
- });
46
+ }
47
+ const max = isFiniteNum(axisOptions?.max)
48
+ ? axisOptions.max
49
+ : niceAxisCeiling(largest);
50
+ const min = isFiniteNum(axisOptions?.min) && axisOptions.min < max ? axisOptions.min : 0;
51
+ return { min, max };
52
+ };
53
+ /**
54
+ * Build echarts radar indicators from category labels and series. Every
55
+ * indicator carries the SAME `min` / `max` — the common scale of
56
+ * {@link radarValueScale} — so values on different axes compare, and a
57
+ * single series draws the shape of its data rather than a regular polygon
58
+ * (rowsncolumns/spreadsheet#1066).
59
+ */
60
+ export const buildRadarIndicators = (categories, series, axisOptions) => {
61
+ const { min, max } = radarValueScale(series, axisOptions);
62
+ return categories.map((label) => ({ name: String(label ?? ""), min, max }));
35
63
  };
36
64
  /**
37
65
  * Shape series into echarts radar data: one entry per series with its
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowsncolumns/charts",
3
- "version": "28.1.7",
3
+ "version": "28.1.8",
4
4
  "author": "Vinay M",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "main": "./dist/cjs/index.js",
@@ -70,9 +70,9 @@
70
70
  "@rowsncolumns/common-types": ">=5.3.2",
71
71
  "@rowsncolumns/grid": ">=13.2.35",
72
72
  "@rowsncolumns/icons": ">=7.2.33",
73
- "@rowsncolumns/spreadsheet": ">=10.4.6",
74
- "@rowsncolumns/spreadsheet-state": ">=29.1.7",
75
- "@rowsncolumns/toolkit": ">=24.5.8",
73
+ "@rowsncolumns/spreadsheet": ">=10.4.7",
74
+ "@rowsncolumns/spreadsheet-state": ">=29.1.8",
75
+ "@rowsncolumns/toolkit": ">=24.5.9",
76
76
  "@rowsncolumns/ui": ">=16.0.4",
77
77
  "@rowsncolumns/utils": ">=9.5.5",
78
78
  "@types/react-plotly.js": "^2.6.3",