@rowsncolumns/charts 27.0.34 → 28.1.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/cjs/atoms/pivot-chart.atom.d.ts +14 -0
- package/dist/cjs/atoms/pivot-chart.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/pivot-chart.atom.js +9 -0
- package/dist/cjs/basic-chart/basic-chart.d.ts +1 -1
- package/dist/cjs/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/cjs/basic-chart/basic-chart.js +863 -371
- package/dist/cjs/components/dialogs/pivot-chart-dialog.d.ts +39 -0
- package/dist/cjs/components/dialogs/pivot-chart-dialog.d.ts.map +1 -0
- package/dist/cjs/components/dialogs/pivot-chart-dialog.js +100 -0
- package/dist/cjs/components/editors/chart-editor.d.ts +13 -1
- package/dist/cjs/components/editors/chart-editor.d.ts.map +1 -1
- package/dist/cjs/components/editors/chart-editor.js +225 -59
- package/dist/cjs/config.d.ts.map +1 -1
- package/dist/cjs/config.js +149 -12
- package/dist/cjs/hooks/use-charts.d.ts +21 -6
- package/dist/cjs/hooks/use-charts.d.ts.map +1 -1
- package/dist/cjs/hooks/use-charts.js +13 -1
- package/dist/cjs/hooks/use-on-create-chart.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-create-chart.js +7 -1
- package/dist/cjs/hooks/use-on-move-chart-to-sheet.d.ts +12 -0
- package/dist/cjs/hooks/use-on-move-chart-to-sheet.d.ts.map +1 -0
- package/dist/cjs/hooks/use-on-move-chart-to-sheet.js +26 -0
- package/dist/cjs/hooks/use-on-move-chart.d.ts +1 -1
- package/dist/cjs/hooks/use-on-move-chart.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-move-chart.js +2 -2
- package/dist/cjs/hooks/use-on-resize-chart.d.ts +1 -1
- package/dist/cjs/hooks/use-on-resize-chart.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-resize-chart.js +2 -2
- package/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +34 -1
- package/dist/cjs/interface/create-chart.d.ts.map +1 -1
- package/dist/cjs/interface/create-chart.js +33 -42
- package/dist/cjs/interface/delete-chart.d.ts.map +1 -1
- package/dist/cjs/interface/delete-chart.js +4 -0
- package/dist/cjs/interface/move-chart-to-sheet.d.ts +13 -0
- package/dist/cjs/interface/move-chart-to-sheet.d.ts.map +1 -0
- package/dist/cjs/interface/move-chart-to-sheet.js +136 -0
- package/dist/cjs/interface/move-chart.d.ts +2 -2
- package/dist/cjs/interface/move-chart.d.ts.map +1 -1
- package/dist/cjs/interface/move-chart.js +7 -1
- package/dist/cjs/interface/resize-chart.d.ts +2 -2
- package/dist/cjs/interface/resize-chart.d.ts.map +1 -1
- package/dist/cjs/interface/resize-chart.js +7 -1
- package/dist/cjs/interface/update-chart.d.ts.map +1 -1
- package/dist/cjs/interface/update-chart.js +4 -0
- package/dist/cjs/plotly/basic-chart/basic-chart.d.ts +1 -1
- package/dist/cjs/plotly/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/cjs/plotly/basic-chart/basic-chart.js +970 -585
- package/dist/cjs/plotly/basic-chart/helpers.d.ts.map +1 -1
- package/dist/cjs/plotly/basic-chart/helpers.js +3 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +7 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/utils/axis-number-format.d.ts +69 -0
- package/dist/cjs/utils/axis-number-format.d.ts.map +1 -0
- package/dist/cjs/utils/axis-number-format.js +217 -0
- package/dist/cjs/utils/category-levels.d.ts +27 -0
- package/dist/cjs/utils/category-levels.d.ts.map +1 -0
- package/dist/cjs/utils/category-levels.js +80 -0
- package/dist/cjs/utils/chart-image.d.ts +8 -0
- package/dist/cjs/utils/chart-image.d.ts.map +1 -0
- package/dist/cjs/utils/chart-image.js +28 -0
- package/dist/cjs/utils/chart-orientation.d.ts +67 -0
- package/dist/cjs/utils/chart-orientation.d.ts.map +1 -0
- package/dist/cjs/utils/chart-orientation.js +265 -0
- package/dist/cjs/utils/chart-spec-utils.d.ts +3 -0
- package/dist/cjs/utils/chart-spec-utils.d.ts.map +1 -1
- package/dist/cjs/utils/chart-spec-utils.js +12 -4
- package/dist/cjs/utils/chart-styles.d.ts +75 -0
- package/dist/cjs/utils/chart-styles.d.ts.map +1 -0
- package/dist/cjs/utils/chart-styles.js +283 -0
- package/dist/cjs/utils/empty-cells.d.ts +30 -0
- package/dist/cjs/utils/empty-cells.d.ts.map +1 -0
- package/dist/cjs/utils/empty-cells.js +91 -0
- package/dist/cjs/utils/overrides.d.ts +6 -1
- package/dist/cjs/utils/overrides.d.ts.map +1 -1
- package/dist/cjs/utils/overrides.js +19 -7
- package/dist/cjs/utils/pie-explosion.d.ts +30 -0
- package/dist/cjs/utils/pie-explosion.d.ts.map +1 -0
- package/dist/cjs/utils/pie-explosion.js +55 -0
- package/dist/cjs/utils/plotly-click.d.ts +34 -0
- package/dist/cjs/utils/plotly-click.d.ts.map +1 -0
- package/dist/cjs/utils/plotly-click.js +49 -0
- package/dist/cjs/utils/plotly-surface.d.ts +14 -0
- package/dist/cjs/utils/plotly-surface.d.ts.map +1 -0
- package/dist/cjs/utils/plotly-surface.js +64 -0
- package/dist/cjs/utils/plotly-title.d.ts +12 -0
- package/dist/cjs/utils/plotly-title.d.ts.map +1 -0
- package/dist/cjs/utils/plotly-title.js +24 -0
- package/dist/cjs/utils/series-click.d.ts +39 -0
- package/dist/cjs/utils/series-click.d.ts.map +1 -0
- package/dist/cjs/utils/series-click.js +75 -0
- package/dist/cjs/utils/three-d.d.ts +17 -1
- package/dist/cjs/utils/three-d.d.ts.map +1 -1
- package/dist/cjs/utils/three-d.js +32 -4
- package/dist/esm/atoms/pivot-chart.atom.d.ts +14 -0
- package/dist/esm/atoms/pivot-chart.atom.d.ts.map +1 -0
- package/dist/esm/atoms/pivot-chart.atom.js +4 -0
- package/dist/esm/basic-chart/basic-chart.d.ts +1 -1
- package/dist/esm/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/esm/basic-chart/basic-chart.js +680 -178
- package/dist/esm/components/dialogs/pivot-chart-dialog.d.ts +39 -0
- package/dist/esm/components/dialogs/pivot-chart-dialog.d.ts.map +1 -0
- package/dist/esm/components/dialogs/pivot-chart-dialog.js +89 -0
- package/dist/esm/components/editors/chart-editor.d.ts +13 -1
- package/dist/esm/components/editors/chart-editor.d.ts.map +1 -1
- package/dist/esm/components/editors/chart-editor.js +164 -20
- package/dist/esm/config.d.ts.map +1 -1
- package/dist/esm/config.js +149 -12
- package/dist/esm/hooks/use-charts.d.ts +21 -6
- package/dist/esm/hooks/use-charts.d.ts.map +1 -1
- package/dist/esm/hooks/use-charts.js +13 -1
- package/dist/esm/hooks/use-on-create-chart.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-create-chart.js +7 -1
- package/dist/esm/hooks/use-on-move-chart-to-sheet.d.ts +12 -0
- package/dist/esm/hooks/use-on-move-chart-to-sheet.d.ts.map +1 -0
- package/dist/esm/hooks/use-on-move-chart-to-sheet.js +19 -0
- package/dist/esm/hooks/use-on-move-chart.d.ts +1 -1
- package/dist/esm/hooks/use-on-move-chart.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-move-chart.js +2 -2
- package/dist/esm/hooks/use-on-resize-chart.d.ts +1 -1
- package/dist/esm/hooks/use-on-resize-chart.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-resize-chart.js +2 -2
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +14 -0
- package/dist/esm/interface/create-chart.d.ts.map +1 -1
- package/dist/esm/interface/create-chart.js +36 -58
- package/dist/esm/interface/delete-chart.d.ts.map +1 -1
- package/dist/esm/interface/delete-chart.js +4 -0
- package/dist/esm/interface/move-chart-to-sheet.d.ts +13 -0
- package/dist/esm/interface/move-chart-to-sheet.d.ts.map +1 -0
- package/dist/esm/interface/move-chart-to-sheet.js +126 -0
- package/dist/esm/interface/move-chart.d.ts +2 -2
- package/dist/esm/interface/move-chart.d.ts.map +1 -1
- package/dist/esm/interface/move-chart.js +7 -1
- package/dist/esm/interface/resize-chart.d.ts +2 -2
- package/dist/esm/interface/resize-chart.d.ts.map +1 -1
- package/dist/esm/interface/resize-chart.js +7 -1
- package/dist/esm/interface/update-chart.d.ts.map +1 -1
- package/dist/esm/interface/update-chart.js +4 -0
- package/dist/esm/plotly/basic-chart/basic-chart.d.ts +1 -1
- package/dist/esm/plotly/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/esm/plotly/basic-chart/basic-chart.js +858 -463
- package/dist/esm/plotly/basic-chart/helpers.d.ts.map +1 -1
- package/dist/esm/plotly/basic-chart/helpers.js +3 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +7 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils/axis-number-format.d.ts +69 -0
- package/dist/esm/utils/axis-number-format.d.ts.map +1 -0
- package/dist/esm/utils/axis-number-format.js +170 -0
- package/dist/esm/utils/category-levels.d.ts +27 -0
- package/dist/esm/utils/category-levels.d.ts.map +1 -0
- package/dist/esm/utils/category-levels.js +65 -0
- package/dist/esm/utils/chart-image.d.ts +8 -0
- package/dist/esm/utils/chart-image.d.ts.map +1 -0
- package/dist/esm/utils/chart-image.js +24 -0
- package/dist/esm/utils/chart-orientation.d.ts +67 -0
- package/dist/esm/utils/chart-orientation.d.ts.map +1 -0
- package/dist/esm/utils/chart-orientation.js +234 -0
- package/dist/esm/utils/chart-spec-utils.d.ts +3 -0
- package/dist/esm/utils/chart-spec-utils.d.ts.map +1 -1
- package/dist/esm/utils/chart-spec-utils.js +10 -2
- package/dist/esm/utils/chart-styles.d.ts +75 -0
- package/dist/esm/utils/chart-styles.d.ts.map +1 -0
- package/dist/esm/utils/chart-styles.js +357 -0
- package/dist/esm/utils/empty-cells.d.ts +30 -0
- package/dist/esm/utils/empty-cells.d.ts.map +1 -0
- package/dist/esm/utils/empty-cells.js +67 -0
- package/dist/esm/utils/overrides.d.ts +6 -1
- package/dist/esm/utils/overrides.d.ts.map +1 -1
- package/dist/esm/utils/overrides.js +14 -2
- package/dist/esm/utils/pie-explosion.d.ts +30 -0
- package/dist/esm/utils/pie-explosion.d.ts.map +1 -0
- package/dist/esm/utils/pie-explosion.js +43 -0
- package/dist/esm/utils/plotly-click.d.ts +34 -0
- package/dist/esm/utils/plotly-click.d.ts.map +1 -0
- package/dist/esm/utils/plotly-click.js +44 -0
- package/dist/esm/utils/plotly-surface.d.ts +14 -0
- package/dist/esm/utils/plotly-surface.d.ts.map +1 -0
- package/dist/esm/utils/plotly-surface.js +45 -0
- package/dist/esm/utils/plotly-title.d.ts +12 -0
- package/dist/esm/utils/plotly-title.d.ts.map +1 -0
- package/dist/esm/utils/plotly-title.js +20 -0
- package/dist/esm/utils/series-click.d.ts +39 -0
- package/dist/esm/utils/series-click.d.ts.map +1 -0
- package/dist/esm/utils/series-click.js +66 -0
- package/dist/esm/utils/three-d.d.ts +17 -1
- package/dist/esm/utils/three-d.d.ts.map +1 -1
- package/dist/esm/utils/three-d.js +29 -3
- package/package.json +16 -12
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Office's Change Colors gallery. Colorful 1 is the theme itself (no
|
|
3
|
+
* `colors` — the renderer keeps its accent fallback); the rest are the
|
|
4
|
+
* default Office theme's derived palettes.
|
|
5
|
+
*/
|
|
6
|
+
export const CHART_COLOR_PALETTES = [
|
|
7
|
+
{ id: "colorful1", label: "Colorful Palette 1", kind: "colorful" },
|
|
8
|
+
{
|
|
9
|
+
id: "colorful2",
|
|
10
|
+
label: "Colorful Palette 2",
|
|
11
|
+
kind: "colorful",
|
|
12
|
+
colors: ["#4472C4", "#A5A5A5", "#5B9BD5", "#264478", "#636363", "#255E91"],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: "colorful3",
|
|
16
|
+
label: "Colorful Palette 3",
|
|
17
|
+
kind: "colorful",
|
|
18
|
+
colors: ["#ED7D31", "#FFC000", "#70AD47", "#9E480E", "#997300", "#43682B"],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "colorful4",
|
|
22
|
+
label: "Colorful Palette 4",
|
|
23
|
+
kind: "colorful",
|
|
24
|
+
colors: ["#70AD47", "#4472C4", "#FFC000", "#43682B", "#264478", "#997300"],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "mono1",
|
|
28
|
+
label: "Monochromatic Palette 1",
|
|
29
|
+
kind: "monochromatic",
|
|
30
|
+
colors: ["#1F3864", "#2F5597", "#4472C4", "#8FAADC", "#B4C7E7", "#DAE3F3"],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "mono2",
|
|
34
|
+
label: "Monochromatic Palette 2",
|
|
35
|
+
kind: "monochromatic",
|
|
36
|
+
colors: ["#833C0B", "#C55A11", "#ED7D31", "#F4B183", "#F8CBAD", "#FBE5D6"],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "mono3",
|
|
40
|
+
label: "Monochromatic Palette 3",
|
|
41
|
+
kind: "monochromatic",
|
|
42
|
+
colors: ["#525252", "#7B7B7B", "#A5A5A5", "#C9C9C9", "#DBDBDB", "#EDEDED"],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "mono4",
|
|
46
|
+
label: "Monochromatic Palette 4",
|
|
47
|
+
kind: "monochromatic",
|
|
48
|
+
colors: ["#375623", "#548235", "#70AD47", "#A9D18E", "#C5E0B4", "#E2F0D9"],
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
const stripSeriesColor = (entry) => {
|
|
52
|
+
const { color: _color, gradient: _gradient, dataPointColors: _dataPointColors, negativeColor: _negativeColor, ...rest } = entry;
|
|
53
|
+
return rest;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Strip the per-series colour overrides so the chart-level palette shows
|
|
57
|
+
* through. Hierarchy specs (treemap / sunburst) carry no series.
|
|
58
|
+
*/
|
|
59
|
+
const withoutSeriesColors = (spec) => "series" in spec && Array.isArray(spec.series)
|
|
60
|
+
? { ...spec, series: spec.series.map(stripSeriesColor) }
|
|
61
|
+
: spec;
|
|
62
|
+
/**
|
|
63
|
+
* Change Colors: set the palette and clear every series' own colour so the
|
|
64
|
+
* palette applies (a series colour always wins over the palette).
|
|
65
|
+
*/
|
|
66
|
+
export const applyChartColorPalette = (spec, palette) => ({
|
|
67
|
+
...withoutSeriesColors(spec),
|
|
68
|
+
palette: palette.colors ? [...palette.colors] : undefined,
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* Reset to Match Style: drop the per-series formatting overrides so the
|
|
72
|
+
* series follow the chart style's palette again. Chart-level fields are
|
|
73
|
+
* untouched — they *are* the style.
|
|
74
|
+
*/
|
|
75
|
+
export const resetChartToMatchStyle = (spec) => withoutSeriesColors(spec);
|
|
76
|
+
/**
|
|
77
|
+
* The series colour cycle a renderer should use: the spec's palette when
|
|
78
|
+
* one is set, else the caller's theme accents.
|
|
79
|
+
*/
|
|
80
|
+
export const getChartPalette = (spec, fallback) => spec?.palette && spec.palette.length > 0
|
|
81
|
+
? [...spec.palette]
|
|
82
|
+
: [...fallback];
|
|
83
|
+
const GRAYSCALE_PALETTE = [
|
|
84
|
+
"#404040",
|
|
85
|
+
"#7F7F7F",
|
|
86
|
+
"#A5A5A5",
|
|
87
|
+
"#BFBFBF",
|
|
88
|
+
"#D9D9D9",
|
|
89
|
+
"#595959",
|
|
90
|
+
];
|
|
91
|
+
const MONOCHROME_PALETTE = CHART_COLOR_PALETTES.find((palette) => palette.id === "mono1").colors;
|
|
92
|
+
const COLORFUL_PREVIEW = ["#4472C4", "#ED7D31", "#A5A5A5", "#FFC000"];
|
|
93
|
+
const setTitleFormat = (spec, format) => ({
|
|
94
|
+
...(spec.titleTextFormat ?? {}),
|
|
95
|
+
...format,
|
|
96
|
+
});
|
|
97
|
+
const setAxisGridlines = (spec, show) => ({
|
|
98
|
+
valueAxisOptions: {
|
|
99
|
+
...(spec.valueAxisOptions ?? {}),
|
|
100
|
+
showMajorGridlines: show,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
/** Text colour for every chart text element (dark-frame styles). */
|
|
104
|
+
const setTextColor = (spec, color) => ({
|
|
105
|
+
titleTextFormat: setTitleFormat(spec, { color }),
|
|
106
|
+
legend: {
|
|
107
|
+
...(spec.legend ?? {}),
|
|
108
|
+
textFormat: { ...(spec.legend?.textFormat ?? {}), color },
|
|
109
|
+
},
|
|
110
|
+
valueAxisOptions: {
|
|
111
|
+
...(spec.valueAxisOptions ?? {}),
|
|
112
|
+
textFormat: { ...(spec.valueAxisOptions?.textFormat ?? {}), color },
|
|
113
|
+
},
|
|
114
|
+
categoryAxisOptions: {
|
|
115
|
+
...(spec.categoryAxisOptions ?? {}),
|
|
116
|
+
textFormat: { ...(spec.categoryAxisOptions?.textFormat ?? {}), color },
|
|
117
|
+
},
|
|
118
|
+
dataLabels: {
|
|
119
|
+
...(spec.dataLabels ?? {}),
|
|
120
|
+
textFormat: { ...(spec.dataLabels?.textFormat ?? {}), color },
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
/**
|
|
124
|
+
* The Chart Styles gallery. Each entry pins the look Excel's style of that
|
|
125
|
+
* id implies onto the spec fields both renderers read: chart-area fill,
|
|
126
|
+
* gridlines, data labels, legend placement, title font and — for the
|
|
127
|
+
* grayscale / monochromatic rows — the palette. Per-series colours are
|
|
128
|
+
* left alone (Reset to Match Style clears them).
|
|
129
|
+
*/
|
|
130
|
+
export const CHART_STYLES = [
|
|
131
|
+
{
|
|
132
|
+
id: 2,
|
|
133
|
+
label: "Style 1",
|
|
134
|
+
preview: { background: "#FFFFFF", bars: COLORFUL_PREVIEW },
|
|
135
|
+
apply: (spec) => ({
|
|
136
|
+
...spec,
|
|
137
|
+
chartStyle: 2,
|
|
138
|
+
backgroundColor: undefined,
|
|
139
|
+
...setAxisGridlines(spec, true),
|
|
140
|
+
dataLabels: { ...(spec.dataLabels ?? {}), show: false },
|
|
141
|
+
titleTextFormat: setTitleFormat(spec, {
|
|
142
|
+
fontSize: 14,
|
|
143
|
+
bold: false,
|
|
144
|
+
color: undefined,
|
|
145
|
+
}),
|
|
146
|
+
}),
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: 10,
|
|
150
|
+
label: "Style 2",
|
|
151
|
+
preview: { background: "#FFFFFF", bars: COLORFUL_PREVIEW },
|
|
152
|
+
apply: (spec) => ({
|
|
153
|
+
...spec,
|
|
154
|
+
chartStyle: 10,
|
|
155
|
+
backgroundColor: undefined,
|
|
156
|
+
...setAxisGridlines(spec, true),
|
|
157
|
+
dataLabels: {
|
|
158
|
+
...(spec.dataLabels ?? {}),
|
|
159
|
+
show: true,
|
|
160
|
+
position: "outsideEnd",
|
|
161
|
+
},
|
|
162
|
+
legend: { ...(spec.legend ?? {}), position: "top" },
|
|
163
|
+
titleTextFormat: setTitleFormat(spec, { fontSize: 16, bold: true }),
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: 18,
|
|
168
|
+
label: "Style 3",
|
|
169
|
+
preview: { background: "#FFFFFF", bars: COLORFUL_PREVIEW },
|
|
170
|
+
apply: (spec) => ({
|
|
171
|
+
...spec,
|
|
172
|
+
chartStyle: 18,
|
|
173
|
+
backgroundColor: undefined,
|
|
174
|
+
...setAxisGridlines(spec, false),
|
|
175
|
+
dataLabels: {
|
|
176
|
+
...(spec.dataLabels ?? {}),
|
|
177
|
+
show: true,
|
|
178
|
+
position: "insideEnd",
|
|
179
|
+
},
|
|
180
|
+
legend: { ...(spec.legend ?? {}), position: "bottom" },
|
|
181
|
+
titleTextFormat: setTitleFormat(spec, { fontSize: 14, bold: true }),
|
|
182
|
+
}),
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: 26,
|
|
186
|
+
label: "Style 4",
|
|
187
|
+
preview: { background: "#F2F2F2", bars: COLORFUL_PREVIEW },
|
|
188
|
+
apply: (spec) => ({
|
|
189
|
+
...spec,
|
|
190
|
+
chartStyle: 26,
|
|
191
|
+
backgroundColor: "#F2F2F2",
|
|
192
|
+
...setAxisGridlines(spec, true),
|
|
193
|
+
dataLabels: { ...(spec.dataLabels ?? {}), show: false },
|
|
194
|
+
legend: { ...(spec.legend ?? {}), position: "bottom" },
|
|
195
|
+
titleTextFormat: setTitleFormat(spec, { fontSize: 18, bold: true }),
|
|
196
|
+
}),
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: 1,
|
|
200
|
+
label: "Style 5",
|
|
201
|
+
preview: { background: "#FFFFFF", bars: GRAYSCALE_PALETTE.slice(0, 4) },
|
|
202
|
+
apply: (spec) => ({
|
|
203
|
+
...spec,
|
|
204
|
+
chartStyle: 1,
|
|
205
|
+
backgroundColor: undefined,
|
|
206
|
+
palette: [...GRAYSCALE_PALETTE],
|
|
207
|
+
...setAxisGridlines(spec, true),
|
|
208
|
+
titleTextFormat: setTitleFormat(spec, { fontSize: 14, bold: false }),
|
|
209
|
+
}),
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
id: 3,
|
|
213
|
+
label: "Style 6",
|
|
214
|
+
preview: { background: "#FFFFFF", bars: MONOCHROME_PALETTE.slice(0, 4) },
|
|
215
|
+
apply: (spec) => ({
|
|
216
|
+
...spec,
|
|
217
|
+
chartStyle: 3,
|
|
218
|
+
backgroundColor: undefined,
|
|
219
|
+
palette: [...MONOCHROME_PALETTE],
|
|
220
|
+
...setAxisGridlines(spec, true),
|
|
221
|
+
titleTextFormat: setTitleFormat(spec, { fontSize: 14, bold: false }),
|
|
222
|
+
}),
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
id: 34,
|
|
226
|
+
label: "Style 7",
|
|
227
|
+
preview: { background: "#404040", bars: COLORFUL_PREVIEW },
|
|
228
|
+
apply: (spec) => ({
|
|
229
|
+
...spec,
|
|
230
|
+
chartStyle: 34,
|
|
231
|
+
backgroundColor: "#404040",
|
|
232
|
+
...setTextColor(spec, "#F2F2F2"),
|
|
233
|
+
valueAxisOptions: {
|
|
234
|
+
...(spec.valueAxisOptions ?? {}),
|
|
235
|
+
textFormat: { ...(spec.valueAxisOptions?.textFormat ?? {}), color: "#F2F2F2" },
|
|
236
|
+
showMajorGridlines: true,
|
|
237
|
+
},
|
|
238
|
+
titleTextFormat: setTitleFormat(spec, {
|
|
239
|
+
fontSize: 16,
|
|
240
|
+
bold: true,
|
|
241
|
+
color: "#FFFFFF",
|
|
242
|
+
}),
|
|
243
|
+
}),
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
id: 42,
|
|
247
|
+
label: "Style 8",
|
|
248
|
+
preview: { background: "#000000", bars: COLORFUL_PREVIEW },
|
|
249
|
+
apply: (spec) => ({
|
|
250
|
+
...spec,
|
|
251
|
+
chartStyle: 42,
|
|
252
|
+
backgroundColor: "#000000",
|
|
253
|
+
...setTextColor(spec, "#FFFFFF"),
|
|
254
|
+
valueAxisOptions: {
|
|
255
|
+
...(spec.valueAxisOptions ?? {}),
|
|
256
|
+
textFormat: { ...(spec.valueAxisOptions?.textFormat ?? {}), color: "#FFFFFF" },
|
|
257
|
+
showMajorGridlines: false,
|
|
258
|
+
},
|
|
259
|
+
titleTextFormat: setTitleFormat(spec, {
|
|
260
|
+
fontSize: 16,
|
|
261
|
+
bold: true,
|
|
262
|
+
color: "#FFFFFF",
|
|
263
|
+
}),
|
|
264
|
+
}),
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
export const applyChartStyle = (spec, style) => style.apply(spec);
|
|
268
|
+
/** Excel inserts placeholder axis titles when a layout shows axis titles the chart lacks. */
|
|
269
|
+
const AXIS_TITLE_PLACEHOLDER = "Axis Title";
|
|
270
|
+
const withAxisTitles = (spec, show) => show
|
|
271
|
+
? {
|
|
272
|
+
verticalAxisTitle: spec.verticalAxisTitle || AXIS_TITLE_PLACEHOLDER,
|
|
273
|
+
horizontalAxisTitle: spec.horizontalAxisTitle || AXIS_TITLE_PLACEHOLDER,
|
|
274
|
+
}
|
|
275
|
+
: { verticalAxisTitle: undefined, horizontalAxisTitle: undefined };
|
|
276
|
+
const withDataLabels = (spec, show, position) => ({
|
|
277
|
+
dataLabels: {
|
|
278
|
+
...(spec.dataLabels ?? {}),
|
|
279
|
+
show,
|
|
280
|
+
...(show && position ? { position } : {}),
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
/**
|
|
284
|
+
* Excel's Quick Layout gallery (the first six of the column-chart set).
|
|
285
|
+
* Layouts arrange the existing elements; they never touch colours.
|
|
286
|
+
*/
|
|
287
|
+
export const CHART_QUICK_LAYOUTS = [
|
|
288
|
+
{
|
|
289
|
+
id: 1,
|
|
290
|
+
label: "Layout 1",
|
|
291
|
+
apply: (spec) => ({
|
|
292
|
+
...spec,
|
|
293
|
+
legend: { ...(spec.legend ?? {}), position: "right" },
|
|
294
|
+
...withDataLabels(spec, false),
|
|
295
|
+
...withAxisTitles(spec, false),
|
|
296
|
+
}),
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
id: 2,
|
|
300
|
+
label: "Layout 2",
|
|
301
|
+
apply: (spec) => ({
|
|
302
|
+
...spec,
|
|
303
|
+
legend: { ...(spec.legend ?? {}), position: "top" },
|
|
304
|
+
...withDataLabels(spec, true, "outsideEnd"),
|
|
305
|
+
...withAxisTitles(spec, false),
|
|
306
|
+
valueAxisOptions: {
|
|
307
|
+
...(spec.valueAxisOptions ?? {}),
|
|
308
|
+
showMajorGridlines: false,
|
|
309
|
+
},
|
|
310
|
+
}),
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
id: 3,
|
|
314
|
+
label: "Layout 3",
|
|
315
|
+
apply: (spec) => ({
|
|
316
|
+
...spec,
|
|
317
|
+
legend: { ...(spec.legend ?? {}), position: "bottom" },
|
|
318
|
+
...withDataLabels(spec, false),
|
|
319
|
+
...withAxisTitles(spec, false),
|
|
320
|
+
}),
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
id: 4,
|
|
324
|
+
label: "Layout 4",
|
|
325
|
+
apply: (spec) => ({
|
|
326
|
+
...spec,
|
|
327
|
+
legend: { ...(spec.legend ?? {}), position: "none" },
|
|
328
|
+
...withDataLabels(spec, true, "insideEnd"),
|
|
329
|
+
...withAxisTitles(spec, false),
|
|
330
|
+
valueAxisOptions: {
|
|
331
|
+
...(spec.valueAxisOptions ?? {}),
|
|
332
|
+
showMajorGridlines: false,
|
|
333
|
+
},
|
|
334
|
+
}),
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
id: 5,
|
|
338
|
+
label: "Layout 5",
|
|
339
|
+
apply: (spec) => ({
|
|
340
|
+
...spec,
|
|
341
|
+
legend: { ...(spec.legend ?? {}), position: "none" },
|
|
342
|
+
...withDataLabels(spec, false),
|
|
343
|
+
...withAxisTitles(spec, true),
|
|
344
|
+
}),
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
id: 6,
|
|
348
|
+
label: "Layout 6",
|
|
349
|
+
apply: (spec) => ({
|
|
350
|
+
...spec,
|
|
351
|
+
legend: { ...(spec.legend ?? {}), position: "right" },
|
|
352
|
+
...withDataLabels(spec, false),
|
|
353
|
+
...withAxisTitles(spec, true),
|
|
354
|
+
}),
|
|
355
|
+
},
|
|
356
|
+
];
|
|
357
|
+
export const applyChartQuickLayout = (spec, layout) => layout.apply(spec);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { EmbeddedChart } from "@rowsncolumns/spreadsheet";
|
|
2
|
+
type ChartSpec = EmbeddedChart["spec"];
|
|
3
|
+
export type EmptyCellsPolicy = NonNullable<ChartSpec["emptyCells"]>;
|
|
4
|
+
type EmptyCellsSpec = Pick<ChartSpec, "emptyCells" | "showNaAsEmpty">;
|
|
5
|
+
export declare const isChartErrorValue: (value: unknown) => boolean;
|
|
6
|
+
/** Excel's default is a gap. */
|
|
7
|
+
export declare const getEmptyCellsPolicy: (spec: EmptyCellsSpec) => EmptyCellsPolicy;
|
|
8
|
+
/** Only a line-like series has a line to carry across the hole. */
|
|
9
|
+
export declare const isLineLikeChartType: (chartType: ChartSpec["chartType"] | null | undefined) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* "Connect data points with line" — the renderer bridges the gap
|
|
12
|
+
* (echarts `connectNulls`, plotly `connectgaps`).
|
|
13
|
+
*/
|
|
14
|
+
export declare const connectsAcrossEmptyCells: (spec: EmptyCellsSpec, lineLike: boolean) => boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Plot-ready values for one series under the chart's "Hidden and Empty
|
|
17
|
+
* Cells" settings. `values` are the sanitized numbers (blanks and errors
|
|
18
|
+
* already `undefined`), `rawValues` the cells as read, index-aligned, so
|
|
19
|
+
* a blank can be told from an error:
|
|
20
|
+
*
|
|
21
|
+
* - a blank follows `emptyCells`: `"zero"` plots 0, `"gaps"` and
|
|
22
|
+
* `"connect"` leave `null` (the renderer's connect flag bridges it);
|
|
23
|
+
* - an error is a blank while `showNaAsEmpty` is on (Excel's default);
|
|
24
|
+
* with it off a line-like series is drawn straight through the point
|
|
25
|
+
* (linear interpolation between its numeric neighbours — Excel's
|
|
26
|
+
* pre-2016 #N/A behaviour), and any other series leaves a gap.
|
|
27
|
+
*/
|
|
28
|
+
export declare const applyEmptyCellsPolicy: (values: readonly (number | null | undefined)[], rawValues: readonly unknown[], spec: EmptyCellsSpec, lineLike: boolean) => (number | null)[];
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=empty-cells.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-cells.d.ts","sourceRoot":"","sources":["../../../utils/empty-cells.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,KAAK,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEvC,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;AAEpE,KAAK,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,GAAG,eAAe,CAAC,CAAC;AAetE,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,OACuB,CAAC;AAE3E,gCAAgC;AAChC,eAAO,MAAM,mBAAmB,GAAI,MAAM,cAAc,KAAG,gBAChC,CAAC;AAE5B,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,GAC9B,WAAW,SAAS,CAAC,WAAW,CAAC,GAAG,IAAI,GAAG,SAAS,KACnD,OAAuD,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,MAAM,cAAc,EACpB,UAAU,OAAO,KAChB,OAA8D,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EAC9C,WAAW,SAAS,OAAO,EAAE,EAC7B,MAAM,cAAc,EACpB,UAAU,OAAO,KAChB,CAAC,MAAM,GAAG,IAAI,CAAC,EA4BjB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const CHART_ERROR_VALUES = new Set([
|
|
2
|
+
"#N/A",
|
|
3
|
+
"#VALUE!",
|
|
4
|
+
"#REF!",
|
|
5
|
+
"#DIV/0!",
|
|
6
|
+
"#NUM!",
|
|
7
|
+
"#NAME?",
|
|
8
|
+
"#NULL!",
|
|
9
|
+
"#SPILL!",
|
|
10
|
+
"#CALC!",
|
|
11
|
+
"#GETTING_DATA",
|
|
12
|
+
]);
|
|
13
|
+
export const isChartErrorValue = (value) => typeof value === "string" && CHART_ERROR_VALUES.has(value.toUpperCase());
|
|
14
|
+
/** Excel's default is a gap. */
|
|
15
|
+
export const getEmptyCellsPolicy = (spec) => spec.emptyCells ?? "gaps";
|
|
16
|
+
/** Only a line-like series has a line to carry across the hole. */
|
|
17
|
+
export const isLineLikeChartType = (chartType) => chartType === "line" || chartType === "area";
|
|
18
|
+
/**
|
|
19
|
+
* "Connect data points with line" — the renderer bridges the gap
|
|
20
|
+
* (echarts `connectNulls`, plotly `connectgaps`).
|
|
21
|
+
*/
|
|
22
|
+
export const connectsAcrossEmptyCells = (spec, lineLike) => lineLike && getEmptyCellsPolicy(spec) === "connect";
|
|
23
|
+
/**
|
|
24
|
+
* Plot-ready values for one series under the chart's "Hidden and Empty
|
|
25
|
+
* Cells" settings. `values` are the sanitized numbers (blanks and errors
|
|
26
|
+
* already `undefined`), `rawValues` the cells as read, index-aligned, so
|
|
27
|
+
* a blank can be told from an error:
|
|
28
|
+
*
|
|
29
|
+
* - a blank follows `emptyCells`: `"zero"` plots 0, `"gaps"` and
|
|
30
|
+
* `"connect"` leave `null` (the renderer's connect flag bridges it);
|
|
31
|
+
* - an error is a blank while `showNaAsEmpty` is on (Excel's default);
|
|
32
|
+
* with it off a line-like series is drawn straight through the point
|
|
33
|
+
* (linear interpolation between its numeric neighbours — Excel's
|
|
34
|
+
* pre-2016 #N/A behaviour), and any other series leaves a gap.
|
|
35
|
+
*/
|
|
36
|
+
export const applyEmptyCellsPolicy = (values, rawValues, spec, lineLike) => {
|
|
37
|
+
const policy = getEmptyCellsPolicy(spec);
|
|
38
|
+
const naAsEmpty = spec.showNaAsEmpty !== false;
|
|
39
|
+
const plotted = values.map((value) => typeof value === "number" && Number.isFinite(value) ? value : null);
|
|
40
|
+
const legacyErrors = [];
|
|
41
|
+
for (let i = 0; i < plotted.length; i++) {
|
|
42
|
+
if (plotted[i] !== null)
|
|
43
|
+
continue;
|
|
44
|
+
if (!naAsEmpty && isChartErrorValue(rawValues[i])) {
|
|
45
|
+
legacyErrors.push(i);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (policy === "zero")
|
|
49
|
+
plotted[i] = 0;
|
|
50
|
+
}
|
|
51
|
+
if (lineLike) {
|
|
52
|
+
for (const i of legacyErrors) {
|
|
53
|
+
let prev = i - 1;
|
|
54
|
+
while (prev >= 0 && plotted[prev] === null)
|
|
55
|
+
prev--;
|
|
56
|
+
let next = i + 1;
|
|
57
|
+
while (next < plotted.length && plotted[next] === null)
|
|
58
|
+
next++;
|
|
59
|
+
if (prev < 0 || next >= plotted.length)
|
|
60
|
+
continue;
|
|
61
|
+
const a = plotted[prev];
|
|
62
|
+
const b = plotted[next];
|
|
63
|
+
plotted[i] = a + ((b - a) * (i - prev)) / (next - prev);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return plotted;
|
|
67
|
+
};
|
|
@@ -2,7 +2,12 @@ import type { LegendComponentOption } from "echarts";
|
|
|
2
2
|
/** Build an echarts `textStyle` from a parsed `ChartTextFormat`. */
|
|
3
3
|
export declare const textFormatToEchartsTextStyle: (fmt: any) => Record<string, any> | undefined;
|
|
4
4
|
export declare const applyLegendOverrides: (legend: LegendComponentOption, opts: any) => LegendComponentOption;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* `numberFormatPattern` is the axis' RESOLVED format (explicit pattern or
|
|
7
|
+
* the linked source-cell format — see `resolveValueAxisNumberFormat`); it
|
|
8
|
+
* becomes the tick-label formatter.
|
|
9
|
+
*/
|
|
10
|
+
export declare const applyAxisOverrides: (axis: any, opts: any, numberFormatPattern?: string) => any;
|
|
6
11
|
export declare const dataLabelFormatter: (opts: any) => (params: any) => string;
|
|
7
12
|
export declare const buildSeriesLabelOption: (opts: any) => {
|
|
8
13
|
readonly show: true;
|
|
@@ -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;
|
|
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,4 +1,5 @@
|
|
|
1
1
|
import { ssfFormat } from "@rowsncolumns/utils";
|
|
2
|
+
import { valueAxisLabelFormatter } from "./axis-number-format";
|
|
2
3
|
// Map ChartSpec.legend / dataLabels / axisOptions to ECharts option
|
|
3
4
|
// fragments. Each helper is a no-op when the spec field is missing, so
|
|
4
5
|
// callers can spread the result without checks. Shared by the main
|
|
@@ -69,10 +70,21 @@ export const applyLegendOverrides = (legend, opts) => {
|
|
|
69
70
|
}
|
|
70
71
|
return next;
|
|
71
72
|
};
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
/**
|
|
74
|
+
* `numberFormatPattern` is the axis' RESOLVED format (explicit pattern or
|
|
75
|
+
* the linked source-cell format — see `resolveValueAxisNumberFormat`); it
|
|
76
|
+
* becomes the tick-label formatter.
|
|
77
|
+
*/
|
|
78
|
+
export const applyAxisOverrides = (axis, opts, numberFormatPattern) => {
|
|
79
|
+
const formatter = valueAxisLabelFormatter(numberFormatPattern);
|
|
80
|
+
if (!opts && !formatter)
|
|
74
81
|
return axis;
|
|
75
82
|
const next = { ...axis };
|
|
83
|
+
if (formatter) {
|
|
84
|
+
next.axisLabel = { ...(next.axisLabel ?? {}), formatter };
|
|
85
|
+
}
|
|
86
|
+
if (!opts)
|
|
87
|
+
return next;
|
|
76
88
|
if (opts.logarithmic)
|
|
77
89
|
next.type = "log";
|
|
78
90
|
if (opts.reverse)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exploded pie / doughnut (rowsncolumns/spreadsheet#668 C-32). Excel stores
|
|
3
|
+
* the explosion as a percentage of the pie radius (`<c:explosion val="25"/>`,
|
|
4
|
+
* 25 being the gallery default); each slice moves outward along its own
|
|
5
|
+
* bisector by that much. Both renderers resolve the spec value here.
|
|
6
|
+
*/
|
|
7
|
+
/** Excel's gallery "Exploded Pie" / "Exploded Doughnut" explosion. */
|
|
8
|
+
export declare const DEFAULT_PIE_EXPLOSION = 25;
|
|
9
|
+
/**
|
|
10
|
+
* The explosion percentage a spec asks for, `0` when the slices touch
|
|
11
|
+
* (absent, non-numeric, negative or `0`).
|
|
12
|
+
*/
|
|
13
|
+
export declare const resolveExplosion: (spec: {
|
|
14
|
+
explosion?: number | null;
|
|
15
|
+
} | null | undefined) => number;
|
|
16
|
+
/**
|
|
17
|
+
* The outer radius of a pie in pixels for the container it renders in:
|
|
18
|
+
* echarts' `radius` is a percentage of half the shorter side (default
|
|
19
|
+
* `"75%"`) or an absolute pixel count.
|
|
20
|
+
*/
|
|
21
|
+
export declare const pieRadiusPx: (radius: (string | number)[] | null | undefined, width: number, height: number) => number;
|
|
22
|
+
/**
|
|
23
|
+
* echarts has no slice offset of its own; the exploded look is its
|
|
24
|
+
* `select` state (`selectedOffset`, in pixels) with every slice selected.
|
|
25
|
+
* The percentage is of the pie radius, so the offset scales with it.
|
|
26
|
+
*/
|
|
27
|
+
export declare const explosionOffsetPx: (explosion: number, radiusPx: number) => number;
|
|
28
|
+
/** plotly pie `pull` — a fraction of the radius. */
|
|
29
|
+
export declare const explosionToPlotlyPull: (explosion: number) => number | undefined;
|
|
30
|
+
//# sourceMappingURL=pie-explosion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-explosion.d.ts","sourceRoot":"","sources":["../../../utils/pie-explosion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAKxC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,KACrD,MAIF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACtB,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,EAC9C,OAAO,MAAM,EACb,QAAQ,MAAM,KACb,MAOF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,WAC3B,CAAC;AAE3C,oDAAoD;AACpD,eAAO,MAAM,qBAAqB,GAAI,WAAW,MAAM,uBACG,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exploded pie / doughnut (rowsncolumns/spreadsheet#668 C-32). Excel stores
|
|
3
|
+
* the explosion as a percentage of the pie radius (`<c:explosion val="25"/>`,
|
|
4
|
+
* 25 being the gallery default); each slice moves outward along its own
|
|
5
|
+
* bisector by that much. Both renderers resolve the spec value here.
|
|
6
|
+
*/
|
|
7
|
+
/** Excel's gallery "Exploded Pie" / "Exploded Doughnut" explosion. */
|
|
8
|
+
export const DEFAULT_PIE_EXPLOSION = 25;
|
|
9
|
+
/** OOXML `CT_UnsignedInt` explosion — Excel's dialog caps it at 400%. */
|
|
10
|
+
const MAX_PIE_EXPLOSION = 400;
|
|
11
|
+
/**
|
|
12
|
+
* The explosion percentage a spec asks for, `0` when the slices touch
|
|
13
|
+
* (absent, non-numeric, negative or `0`).
|
|
14
|
+
*/
|
|
15
|
+
export const resolveExplosion = (spec) => {
|
|
16
|
+
const explosion = spec?.explosion;
|
|
17
|
+
if (typeof explosion !== "number" || !Number.isFinite(explosion))
|
|
18
|
+
return 0;
|
|
19
|
+
return Math.min(MAX_PIE_EXPLOSION, Math.max(0, explosion));
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The outer radius of a pie in pixels for the container it renders in:
|
|
23
|
+
* echarts' `radius` is a percentage of half the shorter side (default
|
|
24
|
+
* `"75%"`) or an absolute pixel count.
|
|
25
|
+
*/
|
|
26
|
+
export const pieRadiusPx = (radius, width, height) => {
|
|
27
|
+
const half = Math.max(0, Math.min(width, height)) / 2;
|
|
28
|
+
const outer = radius?.[radius.length - 1] ?? "75%";
|
|
29
|
+
if (typeof outer === "number")
|
|
30
|
+
return Math.max(0, outer);
|
|
31
|
+
const parsed = Number.parseFloat(outer);
|
|
32
|
+
if (!Number.isFinite(parsed))
|
|
33
|
+
return half * 0.75;
|
|
34
|
+
return outer.trim().endsWith("%") ? (half * parsed) / 100 : parsed;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* echarts has no slice offset of its own; the exploded look is its
|
|
38
|
+
* `select` state (`selectedOffset`, in pixels) with every slice selected.
|
|
39
|
+
* The percentage is of the pie radius, so the offset scales with it.
|
|
40
|
+
*/
|
|
41
|
+
export const explosionOffsetPx = (explosion, radiusPx) => Math.round((radiusPx * explosion) / 100);
|
|
42
|
+
/** plotly pie `pull` — a fraction of the radius. */
|
|
43
|
+
export const explosionToPlotlyPull = (explosion) => explosion > 0 ? Math.min(1, explosion / 100) : undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plotly click → chart selection (rowsncolumns/spreadsheet#668 C-37 / C-38).
|
|
3
|
+
*
|
|
4
|
+
* The plotly renderer is interactive with `layout.dragmode: false`: plotly
|
|
5
|
+
* reports `plotly_click` but never starts a drag, so a body drag reaches
|
|
6
|
+
* the embed's move handler instead. plotly does not track that drag either
|
|
7
|
+
* and treats the mouseup as a click, so the caller compares the click's
|
|
8
|
+
* pointer position with where the pointer went down.
|
|
9
|
+
*/
|
|
10
|
+
/** Pointer travel (px) beyond which a mouseup is a drag, not a click. */
|
|
11
|
+
export declare const CLICK_DRAG_TOLERANCE_PX = 3;
|
|
12
|
+
export declare const wasDragged: (pointerDown: {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
} | undefined, clickEvent: {
|
|
16
|
+
clientX?: number;
|
|
17
|
+
clientY?: number;
|
|
18
|
+
} | undefined) => boolean;
|
|
19
|
+
export type PlotlyClickPoint = {
|
|
20
|
+
curveNumber: number;
|
|
21
|
+
/** Index of the clicked point within its trace (a category index). */
|
|
22
|
+
pointNumber?: number;
|
|
23
|
+
data?: unknown;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The `spec.series` entry (and data point) a plotly click lands on. Traces
|
|
27
|
+
* tagged with `meta.rncSeriesIndex` resolve through the tag; untagged ones
|
|
28
|
+
* map by curve position while it fits; anything else is not a series.
|
|
29
|
+
*/
|
|
30
|
+
export declare const resolvePlotlyClickSelection: (points: ReadonlyArray<PlotlyClickPoint> | undefined, seriesCount: number) => {
|
|
31
|
+
seriesIndex: number;
|
|
32
|
+
dataIndex?: number;
|
|
33
|
+
} | undefined;
|
|
34
|
+
//# sourceMappingURL=plotly-click.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plotly-click.d.ts","sourceRoot":"","sources":["../../../utils/plotly-click.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC,eAAO,MAAM,UAAU,GACrB,aAAa;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACjD,YAAY;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,KAC7D,OAQF,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,GACtC,QAAQ,aAAa,CAAC,gBAAgB,CAAC,GAAG,SAAS,EACnD,aAAa,MAAM,KAClB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAkBhD,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plotly click → chart selection (rowsncolumns/spreadsheet#668 C-37 / C-38).
|
|
3
|
+
*
|
|
4
|
+
* The plotly renderer is interactive with `layout.dragmode: false`: plotly
|
|
5
|
+
* reports `plotly_click` but never starts a drag, so a body drag reaches
|
|
6
|
+
* the embed's move handler instead. plotly does not track that drag either
|
|
7
|
+
* and treats the mouseup as a click, so the caller compares the click's
|
|
8
|
+
* pointer position with where the pointer went down.
|
|
9
|
+
*/
|
|
10
|
+
/** Pointer travel (px) beyond which a mouseup is a drag, not a click. */
|
|
11
|
+
export const CLICK_DRAG_TOLERANCE_PX = 3;
|
|
12
|
+
export const wasDragged = (pointerDown, clickEvent) => {
|
|
13
|
+
if (!pointerDown || !clickEvent)
|
|
14
|
+
return false;
|
|
15
|
+
const { clientX, clientY } = clickEvent;
|
|
16
|
+
if (typeof clientX !== "number" || typeof clientY !== "number")
|
|
17
|
+
return false;
|
|
18
|
+
return (Math.abs(clientX - pointerDown.x) > CLICK_DRAG_TOLERANCE_PX ||
|
|
19
|
+
Math.abs(clientY - pointerDown.y) > CLICK_DRAG_TOLERANCE_PX);
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The `spec.series` entry (and data point) a plotly click lands on. Traces
|
|
23
|
+
* tagged with `meta.rncSeriesIndex` resolve through the tag; untagged ones
|
|
24
|
+
* map by curve position while it fits; anything else is not a series.
|
|
25
|
+
*/
|
|
26
|
+
export const resolvePlotlyClickSelection = (points, seriesCount) => {
|
|
27
|
+
const point = points?.[0];
|
|
28
|
+
if (!point)
|
|
29
|
+
return undefined;
|
|
30
|
+
const meta = point.data
|
|
31
|
+
?.meta;
|
|
32
|
+
const seriesIndex = typeof meta?.rncSeriesIndex === "number"
|
|
33
|
+
? meta.rncSeriesIndex
|
|
34
|
+
: point.curveNumber < seriesCount
|
|
35
|
+
? point.curveNumber
|
|
36
|
+
: undefined;
|
|
37
|
+
if (seriesIndex === undefined || seriesIndex >= seriesCount) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const dataIndex = point.pointNumber;
|
|
41
|
+
return typeof dataIndex === "number" && dataIndex >= 0
|
|
42
|
+
? { seriesIndex, dataIndex }
|
|
43
|
+
: { seriesIndex };
|
|
44
|
+
};
|