@perses-dev/pie-chart-plugin 0.10.0 → 0.12.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.
Files changed (83) hide show
  1. package/__mf/css/async/263.d3010b86.css +1 -0
  2. package/__mf/css/async/341.d3010b86.css +1 -0
  3. package/__mf/css/async/759.d3010b86.css +1 -0
  4. package/__mf/js/{PieChart.df86cbf0.js → PieChart.1d58bffe.js} +3 -3
  5. package/__mf/js/async/156.1cf9ec35.js +1 -0
  6. package/__mf/js/async/264.6e9f3f27.js +110 -0
  7. package/__mf/js/async/298.e575048a.js +1 -0
  8. package/__mf/js/async/398.9b0b9c83.js +1 -0
  9. package/__mf/js/async/567.672f2dce.js +2 -0
  10. package/__mf/js/async/706.3e6ace36.js +38 -0
  11. package/__mf/js/async/711.2e914849.js +22 -0
  12. package/__mf/js/async/{75.a825d10b.js → 75.b6a33f75.js} +1 -1
  13. package/__mf/js/async/922.560b8115.js +7 -0
  14. package/__mf/js/async/__federation_expose_PieChart.6ae68990.js +1 -0
  15. package/__mf/js/{main.47849ff0.js → main.efe2355f.js} +3 -3
  16. package/lib/PieChartBase.d.ts +1 -2
  17. package/lib/PieChartBase.d.ts.map +1 -1
  18. package/lib/PieChartBase.js +26 -25
  19. package/lib/PieChartBase.js.map +1 -1
  20. package/lib/PieChartOptionsEditorSettings.d.ts.map +1 -1
  21. package/lib/PieChartOptionsEditorSettings.js +144 -17
  22. package/lib/PieChartOptionsEditorSettings.js.map +1 -1
  23. package/lib/PieChartPanel.d.ts.map +1 -1
  24. package/lib/PieChartPanel.js +36 -27
  25. package/lib/PieChartPanel.js.map +1 -1
  26. package/lib/cjs/PieChartBase.js +24 -23
  27. package/lib/cjs/PieChartOptionsEditorSettings.js +142 -15
  28. package/lib/cjs/PieChartPanel.js +35 -26
  29. package/lib/cjs/colors.js +207 -0
  30. package/lib/cjs/index.js +2 -4
  31. package/lib/cjs/pie-chart-model.js +3 -2
  32. package/lib/cjs/utils.js +10 -30
  33. package/lib/colors.d.ts +38 -0
  34. package/lib/colors.d.ts.map +1 -0
  35. package/lib/colors.js +192 -0
  36. package/lib/colors.js.map +1 -0
  37. package/lib/index.d.ts +2 -4
  38. package/lib/index.d.ts.map +1 -1
  39. package/lib/index.js +2 -4
  40. package/lib/index.js.map +1 -1
  41. package/lib/pie-chart-model.d.ts +5 -3
  42. package/lib/pie-chart-model.d.ts.map +1 -1
  43. package/lib/pie-chart-model.js +3 -2
  44. package/lib/pie-chart-model.js.map +1 -1
  45. package/lib/utils.d.ts.map +1 -1
  46. package/lib/utils.js +10 -30
  47. package/lib/utils.js.map +1 -1
  48. package/mf-manifest.json +21 -41
  49. package/mf-stats.json +21 -44
  50. package/package.json +4 -4
  51. package/__mf/css/async/263.80005a4a.css +0 -1
  52. package/__mf/css/async/341.80005a4a.css +0 -1
  53. package/__mf/css/async/759.80005a4a.css +0 -1
  54. package/__mf/js/async/109.77dcc7d9.js +0 -73
  55. package/__mf/js/async/224.43460380.js +0 -1
  56. package/__mf/js/async/238.3e689a99.js +0 -1
  57. package/__mf/js/async/288.4cad0403.js +0 -7
  58. package/__mf/js/async/289.c295f73f.js +0 -38
  59. package/__mf/js/async/298.707087d2.js +0 -1
  60. package/__mf/js/async/470.1e913aa7.js +0 -2
  61. package/__mf/js/async/680.f1da299d.js +0 -110
  62. package/__mf/js/async/708.77a1c1f6.js +0 -1
  63. package/__mf/js/async/740.254a5697.js +0 -1
  64. package/__mf/js/async/__federation_expose_PieChart.3d887a98.js +0 -1
  65. package/lib/cjs/model.js +0 -16
  66. package/lib/cjs/palette-gen.js +0 -63
  67. package/lib/cjs/palette.js +0 -83
  68. package/lib/model.d.ts +0 -20
  69. package/lib/model.d.ts.map +0 -1
  70. package/lib/model.js +0 -15
  71. package/lib/model.js.map +0 -1
  72. package/lib/palette-gen.d.ts +0 -20
  73. package/lib/palette-gen.d.ts.map +0 -1
  74. package/lib/palette-gen.js +0 -50
  75. package/lib/palette-gen.js.map +0 -1
  76. package/lib/palette.d.ts +0 -6
  77. package/lib/palette.d.ts.map +0 -1
  78. package/lib/palette.js +0 -64
  79. package/lib/palette.js.map +0 -1
  80. /package/__mf/js/async/{680.f1da299d.js.LICENSE.txt → 264.6e9f3f27.js.LICENSE.txt} +0 -0
  81. /package/__mf/js/async/{470.1e913aa7.js.LICENSE.txt → 567.672f2dce.js.LICENSE.txt} +0 -0
  82. /package/__mf/js/async/{109.77dcc7d9.js.LICENSE.txt → 711.2e914849.js.LICENSE.txt} +0 -0
  83. /package/__mf/js/async/{288.4cad0403.js.LICENSE.txt → 922.560b8115.js.LICENSE.txt} +0 -0
@@ -27,6 +27,7 @@ const _immer = require("immer");
27
27
  const _components = require("@perses-dev/components");
28
28
  const _core = require("@perses-dev/core");
29
29
  const _material = require("@mui/material");
30
+ const _react = require("react");
30
31
  const _piechartmodel = require("./pie-chart-model");
31
32
  function _interop_require_default(obj) {
32
33
  return obj && obj.__esModule ? obj : {
@@ -41,7 +42,6 @@ function PieChartOptionsEditorSettings(props) {
41
42
  }));
42
43
  };
43
44
  const handleLegendChange = (newLegend)=>{
44
- // TODO (sjcobb): fix type, add position, fix glitch
45
45
  onChange((0, _immer.produce)(value, (draft)=>{
46
46
  draft.legend = newLegend;
47
47
  }));
@@ -61,8 +61,68 @@ function PieChartOptionsEditorSettings(props) {
61
61
  draft.mode = newMode;
62
62
  }));
63
63
  };
64
+ const handleShowLabelsChange = (_, checked)=>{
65
+ onChange((0, _immer.produce)(value, (draft)=>{
66
+ draft.showLabels = checked;
67
+ }));
68
+ };
69
+ const chartsTheme = (0, _components.useChartsTheme)();
70
+ const themePalette = chartsTheme.echartsTheme.color;
71
+ const colorPalette = (0, _react.useMemo)(()=>{
72
+ return value.colorPalette || undefined;
73
+ }, [
74
+ value.colorPalette
75
+ ]);
76
+ const handleColorChange = (color)=>{
77
+ onChange((0, _immer.produce)(value, (draft)=>{
78
+ if (Array.isArray(color)) {
79
+ draft.colorPalette = color;
80
+ } else if (typeof color === 'string') {
81
+ draft.colorPalette = [
82
+ color
83
+ ];
84
+ } else {
85
+ draft.colorPalette = undefined;
86
+ }
87
+ }));
88
+ };
64
89
  // ensures decimalPlaces defaults to correct value
65
90
  const format = (0, _merge.default)({}, _piechartmodel.DEFAULT_FORMAT, value.format);
91
+ const colorScheme = (0, _react.useMemo)(()=>{
92
+ return Array.isArray(colorPalette) ? colorPalette.length === 1 ? 'gradient' : 'theme' : 'default';
93
+ }, [
94
+ colorPalette
95
+ ]);
96
+ const handleColorSchemeChange = (scheme)=>{
97
+ if (scheme === 'theme') {
98
+ handleColorChange(themePalette);
99
+ } else if (scheme === 'default') {
100
+ handleColorChange();
101
+ } else {
102
+ // gradient: keep existing single color if present (user-chosen via OptionsColorPicker)
103
+ if (Array.isArray(colorPalette) && colorPalette.length === 1) {
104
+ return;
105
+ }
106
+ // initialize with a sensible default so the color picker shows a color
107
+ handleColorChange([
108
+ '#ff0000'
109
+ ]);
110
+ }
111
+ };
112
+ const colorHelpText = (0, _react.useMemo)(()=>{
113
+ if (colorPalette === undefined) {
114
+ return 'Colors will be automatically assigned using metrics name hash.';
115
+ }
116
+ if (Array.isArray(colorPalette) && colorPalette.length > 1) {
117
+ return 'Colors will be automatically assigned using the current theme color palette.';
118
+ }
119
+ if (Array.isArray(colorPalette) && colorPalette.length === 1) {
120
+ return 'All series will use a gradient based on the selected color.';
121
+ }
122
+ return undefined;
123
+ }, [
124
+ colorPalette
125
+ ]);
66
126
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_components.OptionsEditorGrid, {
67
127
  children: [
68
128
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(_components.OptionsEditorColumn, {
@@ -75,6 +135,13 @@ function PieChartOptionsEditorSettings(props) {
75
135
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(_components.OptionsEditorGroup, {
76
136
  title: "Misc",
77
137
  children: [
138
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
139
+ label: "Show Labels",
140
+ control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Switch, {
141
+ checked: Boolean(value.showLabels),
142
+ onChange: handleShowLabelsChange
143
+ })
144
+ }),
78
145
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.FormatControls, {
79
146
  value: format,
80
147
  onChange: handleUnitChange,
@@ -97,21 +164,81 @@ function PieChartOptionsEditorSettings(props) {
97
164
  })
98
165
  ]
99
166
  }),
100
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorColumn, {
101
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorGroup, {
102
- title: "Reset Settings",
103
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
104
- variant: "outlined",
105
- color: "secondary",
106
- onClick: ()=>{
107
- onChange((0, _immer.produce)(value, (draft)=>{
108
- // reset button removes all optional panel options
109
- draft.legend = undefined;
110
- }));
111
- },
112
- children: "Reset To Defaults"
167
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_components.OptionsEditorColumn, {
168
+ children: [
169
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorGroup, {
170
+ title: "Colors",
171
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
172
+ spacing: 2,
173
+ children: [
174
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
175
+ direction: "row",
176
+ spacing: 2,
177
+ alignItems: "center",
178
+ children: [
179
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.FormControl, {
180
+ size: "small",
181
+ sx: {
182
+ minWidth: 150
183
+ },
184
+ children: [
185
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.InputLabel, {
186
+ children: "Color Scheme"
187
+ }),
188
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Select, {
189
+ value: colorScheme,
190
+ label: "Color Scheme",
191
+ onChange: (e)=>handleColorSchemeChange(e.target.value),
192
+ children: [
193
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
194
+ value: "default",
195
+ children: "Default"
196
+ }),
197
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
198
+ value: "theme",
199
+ children: "Theme"
200
+ }),
201
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
202
+ value: "gradient",
203
+ children: "Gradient"
204
+ })
205
+ ]
206
+ })
207
+ ]
208
+ }),
209
+ Array.isArray(colorPalette) && colorPalette.length === 1 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsColorPicker, {
210
+ label: "Color",
211
+ color: colorPalette?.[0] ?? themePalette[0] ?? '#ff0000',
212
+ onColorChange: (c)=>handleColorChange([
213
+ c
214
+ ])
215
+ })
216
+ ]
217
+ }),
218
+ colorHelpText && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
219
+ variant: "body2",
220
+ color: "text.secondary",
221
+ children: colorHelpText
222
+ })
223
+ ]
224
+ })
225
+ }),
226
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorGroup, {
227
+ title: "Reset Settings",
228
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Button, {
229
+ variant: "outlined",
230
+ color: "secondary",
231
+ onClick: ()=>{
232
+ onChange((0, _immer.produce)(value, (draft)=>{
233
+ // reset button removes all optional panel options
234
+ draft.legend = undefined;
235
+ draft.colorPalette = undefined;
236
+ }));
237
+ },
238
+ children: "Reset To Defaults"
239
+ })
113
240
  })
114
- })
241
+ ]
115
242
  })
116
243
  ]
117
244
  });
@@ -27,8 +27,8 @@ const _core = require("@perses-dev/core");
27
27
  const _pluginsystem = require("@perses-dev/plugin-system");
28
28
  const _merge = /*#__PURE__*/ _interop_require_default(require("lodash/merge"));
29
29
  const _react = require("react");
30
- const _palettegen = require("./palette-gen");
31
30
  const _utils = require("./utils");
31
+ const _colors = require("./colors");
32
32
  const _PieChartBase = require("./PieChartBase");
33
33
  function _interop_require_default(obj) {
34
34
  return obj && obj.__esModule ? obj : {
@@ -36,28 +36,28 @@ function _interop_require_default(obj) {
36
36
  };
37
37
  }
38
38
  function PieChartPanel(props) {
39
- const { spec: { calculation, sort, mode, legend: pieChartLegend }, contentDimensions, queryResults } = props;
39
+ const { spec: { calculation, sort, mode, legend: pieChartLegend, colorPalette: colorPalette }, contentDimensions, queryResults } = props;
40
40
  const chartsTheme = (0, _components.useChartsTheme)();
41
- const muiTheme = (0, _material.useTheme)();
42
- const PADDING = chartsTheme.container.padding.default;
43
41
  const chartId = (0, _components.useId)('time-series-panel');
44
- const categoricalPalette = chartsTheme.echartsTheme.color;
42
+ const seriesNames = queryResults.flatMap((result)=>result?.data.series?.map((series)=>series.name) || []);
43
+ // Memoize the color list so it only regenerates when color/palette/series count changes
44
+ const colorList = (0, _react.useMemo)(()=>{
45
+ return (0, _colors.getSeriesColor)(seriesNames, colorPalette);
46
+ }, [
47
+ colorPalette,
48
+ seriesNames
49
+ ]);
45
50
  const { pieChartData, legendItems, legendColumns } = (0, _react.useMemo)(()=>{
46
51
  const calculate = _core.CalculationsMap[calculation];
47
52
  const pieChartData = [];
48
53
  const legendItems = [];
49
54
  const legendColumns = [];
50
- for(let queryIndex = 0; queryIndex < queryResults.length; queryIndex++){
51
- const result = queryResults[queryIndex];
52
- let seriesIndex = 0;
53
- for (const seriesData of result?.data.series ?? []){
54
- const seriesColor = (0, _palettegen.getSeriesColor)({
55
- categoricalPalette: categoricalPalette,
56
- muiPrimaryColor: muiTheme.palette.primary.main,
57
- seriesName: seriesData.name
58
- });
59
- const seriesId = `${chartId}${seriesData.name}${seriesIndex}`;
60
- const series = {
55
+ queryResults.forEach((result, queryIndex)=>{
56
+ const series = result?.data.series ?? [];
57
+ series.forEach((seriesData, seriesIndex)=>{
58
+ const seriesId = `${chartId}${seriesData.name}${seriesIndex}${queryIndex}`;
59
+ const seriesColor = colorList[queryIndex * series.length + seriesIndex] ?? '#ff0000';
60
+ const seriesItem = {
61
61
  id: seriesId,
62
62
  value: calculate(seriesData.values) ?? null,
63
63
  name: seriesData.formattedName ?? '',
@@ -65,17 +65,26 @@ function PieChartPanel(props) {
65
65
  color: seriesColor
66
66
  }
67
67
  };
68
- pieChartData.push(series);
68
+ pieChartData.push(seriesItem);
69
69
  legendItems.push({
70
70
  id: seriesId,
71
- label: series.name,
71
+ label: seriesData.formattedName ?? '',
72
72
  color: seriesColor,
73
73
  data: {}
74
74
  });
75
- seriesIndex++;
76
- }
77
- }
75
+ });
76
+ });
78
77
  const sortedPieChartData = (0, _utils.sortSeriesData)(pieChartData, sort);
78
+ // Reorder legend items to reflect the current sorting order of series
79
+ const valueById = new Map(sortedPieChartData.map((pd)=>[
80
+ pd.id ?? pd.name,
81
+ pd.value ?? 0
82
+ ]));
83
+ legendItems.sort((a, b)=>{
84
+ const av = valueById.get(a.id) ?? 0;
85
+ const bv = valueById.get(b.id) ?? 0;
86
+ return sort === 'asc' ? av - bv : bv - av;
87
+ });
79
88
  if (pieChartLegend?.values?.length && pieChartLegend?.mode === 'table') {
80
89
  const { values } = pieChartLegend;
81
90
  [
@@ -122,8 +131,7 @@ function PieChartPanel(props) {
122
131
  sort,
123
132
  mode,
124
133
  queryResults,
125
- categoricalPalette,
126
- muiTheme.palette.primary.main,
134
+ colorList,
127
135
  chartId,
128
136
  pieChartLegend
129
137
  ]);
@@ -145,7 +153,7 @@ function PieChartPanel(props) {
145
153
  if (!contentDimensions) return null;
146
154
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
147
155
  sx: {
148
- padding: `${PADDING}px`
156
+ padding: `${contentPadding}px`
149
157
  },
150
158
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ContentWithLegend, {
151
159
  width: adjustedContentDimensions?.width ?? 400,
@@ -181,8 +189,9 @@ function PieChartPanel(props) {
181
189
  },
182
190
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_PieChartBase.PieChartBase, {
183
191
  data: pieChartData,
184
- width: contentDimensions.width - PADDING * 2,
185
- height: contentDimensions.height - PADDING * 2
192
+ width: width,
193
+ height: height,
194
+ showLabels: Boolean(props.spec.showLabels)
186
195
  })
187
196
  });
188
197
  }
@@ -0,0 +1,207 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ function _export(target, all) {
18
+ for(var name in all)Object.defineProperty(target, name, {
19
+ enumerable: true,
20
+ get: all[name]
21
+ });
22
+ }
23
+ _export(exports, {
24
+ generateGradientColor: function() {
25
+ return generateGradientColor;
26
+ },
27
+ getAutoPaletteColor: function() {
28
+ return getAutoPaletteColor;
29
+ },
30
+ getColor: function() {
31
+ return getColor;
32
+ },
33
+ getConsistentColor: function() {
34
+ return getConsistentColor;
35
+ },
36
+ getConsistentSeriesNameColor: function() {
37
+ return getConsistentSeriesNameColor;
38
+ },
39
+ getDefaultSeriesColor: function() {
40
+ return getDefaultSeriesColor;
41
+ },
42
+ getSeriesColor: function() {
43
+ return getSeriesColor;
44
+ }
45
+ });
46
+ const _colorhash = /*#__PURE__*/ _interop_require_default(require("color-hash"));
47
+ function _interop_require_default(obj) {
48
+ return obj && obj.__esModule ? obj : {
49
+ default: obj
50
+ };
51
+ }
52
+ // Valid hue values are 0 to 360 and can be adjusted to control the generated colors.
53
+ // More info: https://github.com/zenozeng/color-hash#custom-hue
54
+ // Picked min of 20 and max of 360 to exclude common threshold colors (red).
55
+ // Items with "error" in them will always be generated as red.
56
+ const ERROR_HUE_CUTOFF = 20;
57
+ const colorGenerator = new _colorhash.default({
58
+ hue: {
59
+ min: ERROR_HUE_CUTOFF,
60
+ max: 360
61
+ }
62
+ });
63
+ const redColorGenerator = new _colorhash.default({
64
+ hue: {
65
+ min: 0,
66
+ max: ERROR_HUE_CUTOFF
67
+ }
68
+ });
69
+ // Color utility functions
70
+ /**
71
+ * Converts a number to a 2-digit hex string
72
+ */ function toHex(n) {
73
+ const hex = n.toString(16);
74
+ return hex.length === 1 ? '0' + hex : hex;
75
+ }
76
+ /**
77
+ * Converts a hex color string to RGB values
78
+ */ function hexToRgb(hex) {
79
+ const cleanHex = hex.replace('#', '');
80
+ return {
81
+ r: parseInt(cleanHex.substring(0, 2), 16),
82
+ g: parseInt(cleanHex.substring(2, 4), 16),
83
+ b: parseInt(cleanHex.substring(4, 6), 16)
84
+ };
85
+ }
86
+ /**
87
+ * Returns a deterministic number between 0 and 1 for a given string
88
+ */ function stringToSeed(str) {
89
+ let hash = 0;
90
+ for(let i = 0; i < str.length; i++){
91
+ const char = str.charCodeAt(i);
92
+ hash = (hash << 5) - hash + char;
93
+ hash = hash & hash; // Convert to 32-bit integer
94
+ }
95
+ // Convert to positive number and normalize to 0-1 range
96
+ return Math.abs(hash) / 2147483647;
97
+ }
98
+ function generateGradientColor(baseColor, factor) {
99
+ // Convert hex color to RGB
100
+ const { r, g, b } = hexToRgb(baseColor);
101
+ const newR = Math.round(r * factor);
102
+ const newG = Math.round(g * factor);
103
+ const newB = Math.round(b * factor);
104
+ return `#${toHex(newR)}${toHex(newG)}${toHex(newB)}`;
105
+ }
106
+ function getSeriesColor(seriesNames, colorPalette) {
107
+ const totalSeries = seriesNames.length;
108
+ if (totalSeries <= 0) {
109
+ return [];
110
+ }
111
+ const colors = [];
112
+ // undefined palette - default
113
+ if (colorPalette === undefined) {
114
+ for(let nameIndex = 0; nameIndex < seriesNames.length; nameIndex++){
115
+ const seriesColor = getDefaultSeriesColor({
116
+ categoricalPalette: [
117
+ '#ff0000'
118
+ ],
119
+ muiPrimaryColor: '#ff0000',
120
+ seriesName: seriesNames[nameIndex] || ''
121
+ });
122
+ colors.push(seriesColor);
123
+ }
124
+ return colors;
125
+ }
126
+ // single color palette - generate gradients from that color
127
+ if (colorPalette.length === 1) {
128
+ const baseColor = colorPalette[0] ?? '#ff0000';
129
+ for(let i = 0; i < totalSeries; i++){
130
+ if (i === 0) {
131
+ colors.push(baseColor);
132
+ } else {
133
+ const gradientFactor = 1 * ((totalSeries - i) / totalSeries);
134
+ colors.push(generateGradientColor(baseColor, gradientFactor));
135
+ }
136
+ }
137
+ return colors.sort((a, b)=>{
138
+ const seedA = stringToSeed(seriesNames[colors.indexOf(a)] || 'fallback');
139
+ const seedB = stringToSeed(seriesNames[colors.indexOf(b)] || 'fallback');
140
+ return seedA - seedB;
141
+ });
142
+ }
143
+ // multi color palette - loops through colors and adds gradient when palette is exhausted
144
+ for(let i = 0; i < totalSeries; i++){
145
+ const color = getColor(colorPalette, i);
146
+ colors.push(color);
147
+ }
148
+ if (totalSeries > colorPalette.length) {
149
+ return colors.sort((a, b)=>{
150
+ const seedA = stringToSeed(seriesNames[colors.indexOf(a)] || 'fallback');
151
+ const seedB = stringToSeed(seriesNames[colors.indexOf(b)] || 'fallback');
152
+ return seedA - seedB;
153
+ });
154
+ }
155
+ return colors;
156
+ }
157
+ function getColor(palette, seriesIndex) {
158
+ // Handle undefined or empty palette
159
+ if (!palette || palette.length === 0) {
160
+ return '#ff0000';
161
+ }
162
+ const paletteTotalColors = palette.length;
163
+ const paletteIndex = seriesIndex % paletteTotalColors;
164
+ const baseColor = palette[paletteIndex] ?? '#ff0000';
165
+ // If we haven't exhausted the palette yet, use the original color
166
+ if (seriesIndex < paletteTotalColors) {
167
+ return baseColor;
168
+ }
169
+ // Calculate which "cycle" we're in (0 = first repeat, 1 = second repeat, etc.)
170
+ const cycleNumber = Math.floor(seriesIndex / paletteTotalColors);
171
+ // Apply gradient based on cycle number to create visual distinction
172
+ const gradientFactor = Math.min(1 - cycleNumber * 0.2, 1);
173
+ return generateGradientColor(baseColor, gradientFactor);
174
+ }
175
+ function computeConsistentColor(name, error) {
176
+ const [hue, saturation, lightness] = error ? redColorGenerator.hsl(name) : colorGenerator.hsl(name);
177
+ const saturationPercent = `${(saturation * 100).toFixed(0)}%`;
178
+ const lightnessPercent = `${(lightness * 100).toFixed(0)}%`;
179
+ return `hsla(${hue.toFixed(2)},${saturationPercent},${lightnessPercent},0.9)`;
180
+ }
181
+ // To check whether a color has already been generated for a given string.
182
+ // TODO: Predefined color aliases will be defined here
183
+ const colorLookup = {};
184
+ function getConsistentColor(name, error) {
185
+ const key = `${name}_____${error}`;
186
+ let value = colorLookup[key];
187
+ if (!value) {
188
+ value = computeConsistentColor(name, error);
189
+ colorLookup[key] = value;
190
+ }
191
+ return value;
192
+ }
193
+ function getConsistentSeriesNameColor(inputString) {
194
+ return getConsistentColor(inputString, inputString.toLowerCase().includes('error'));
195
+ }
196
+ function getDefaultSeriesColor(props) {
197
+ const { categoricalPalette, muiPrimaryColor, seriesName } = props;
198
+ // Fallback is unlikely to set unless echarts theme palette in charts theme provider is undefined.
199
+ const fallbackColor = Array.isArray(categoricalPalette) && categoricalPalette[0] ? categoricalPalette[0] // Needed since echarts color property isn't always an array.
200
+ : muiPrimaryColor;
201
+ return getAutoPaletteColor(seriesName, fallbackColor);
202
+ }
203
+ function getAutoPaletteColor(name, fallbackColor) {
204
+ // corresponds to 'Auto' in palette.kind for generative color palette
205
+ const generatedColor = getConsistentSeriesNameColor(name);
206
+ return generatedColor ?? fallbackColor;
207
+ }
package/lib/cjs/index.js CHANGED
@@ -8,11 +8,9 @@ Object.defineProperty(exports, "getPluginModule", {
8
8
  return _getPluginModule.getPluginModule;
9
9
  }
10
10
  });
11
- _export_star(require(".//PieChartPanel"), exports);
11
+ _export_star(require("./PieChartPanel"), exports);
12
12
  const _getPluginModule = require("./getPluginModule");
13
- _export_star(require("./model"), exports);
14
- _export_star(require("./palette"), exports);
15
- _export_star(require("./palette-gen"), exports);
13
+ _export_star(require("./colors"), exports);
16
14
  _export_star(require("./pie-chart-model"), exports);
17
15
  _export_star(require("./PieChart"), exports);
18
16
  _export_star(require("./PieChartOptionsEditorSettings"), exports);
@@ -45,8 +45,9 @@ function createInitialPieChartOptions() {
45
45
  return {
46
46
  calculation: _core.DEFAULT_CALCULATION,
47
47
  format: DEFAULT_FORMAT,
48
+ mode: DEFAULT_MODE,
48
49
  radius: 50,
49
- sort: DEFAULT_SORT,
50
- mode: DEFAULT_MODE
50
+ showLabels: false,
51
+ sort: DEFAULT_SORT
51
52
  };
52
53
  }
package/lib/cjs/utils.js CHANGED
@@ -35,38 +35,18 @@ function calculatePercentages(data) {
35
35
  const percentage = (seriesData.value ?? 0) / sum * 100;
36
36
  return {
37
37
  ...seriesData,
38
- value: percentage
38
+ value: Number(percentage.toFixed(2))
39
39
  };
40
40
  });
41
41
  }
42
42
  function sortSeriesData(data, sortOrder = _piechartmodel.DEFAULT_SORT) {
43
- if (sortOrder === 'asc') {
44
- // sort in ascending order by value
45
- return data.sort((a, b)=>{
46
- if (a.value === null) {
47
- return 1;
48
- }
49
- if (b.value === null) {
50
- return -1;
51
- }
52
- if (a.value === b.value) {
53
- return 0;
54
- }
55
- return a.value < b.value ? 1 : -1;
56
- });
57
- } else {
58
- // sort in descending order by value
59
- return data.sort((a, b)=>{
60
- if (a.value === null) {
61
- return -1;
62
- }
63
- if (b.value === null) {
64
- return 1;
65
- }
66
- if (a.value === b.value) {
67
- return 0;
68
- }
69
- return a.value < b.value ? -1 : 1;
70
- });
71
- }
43
+ return data.sort((a, b)=>{
44
+ // Handle null values - push them to the end regardless of sort order
45
+ if (a.value === null && b.value === null) return 0;
46
+ if (a.value === null) return 1;
47
+ if (b.value === null) return -1;
48
+ // Sort by value
49
+ const diff = (a.value ?? 0) - (b.value ?? 0);
50
+ return sortOrder === 'asc' ? diff : -diff;
51
+ });
72
52
  }
@@ -0,0 +1,38 @@
1
+ export interface SeriesColorProps {
2
+ categoricalPalette: string[];
3
+ muiPrimaryColor: string;
4
+ seriesName: string;
5
+ }
6
+ /**
7
+ * Helper function to generate gradient colors for series within a query
8
+ */
9
+ export declare function generateGradientColor(baseColor: string, factor: number): string;
10
+ /**
11
+ * Generates a list of color strings for a given number of series using a categorical palette.
12
+ * When the number of series exceeds the palette size, it cycles through the palette
13
+ * and applies gradients to create visual distinction.
14
+ * @param totalSeries - The total number of series that need colors
15
+ * @param colorPalette - Array of color strings to use as the base palette
16
+ * @returns Array of color strings, one for each series
17
+ */
18
+ export declare function getSeriesColor(seriesNames: string[], colorPalette?: string[]): string[];
19
+ /**
20
+ * Default classical qualitative palette that cycles through the colors array by index.
21
+ * When colors start repeating (after exhausting the palette), applies gradients for distinction.
22
+ */
23
+ export declare function getColor(palette: string[], seriesIndex: number): string;
24
+ /**
25
+ * Return a consistent color for (name, error) tuple
26
+ */
27
+ export declare function getConsistentColor(name: string, error: boolean): string;
28
+ export declare function getConsistentSeriesNameColor(inputString: string): string;
29
+ /**
30
+ * Get line color as well as color for tooltip and legend, account for whether palette is 'categorical' or 'auto' aka generative
31
+ */
32
+ export declare function getDefaultSeriesColor(props: SeriesColorProps): string;
33
+ /**
34
+ * Get color from generative color palette, this approaches uses series name as the seed and
35
+ * allows for consistent colors across panels (when all panels use this approach).
36
+ */
37
+ export declare function getAutoPaletteColor(name: string, fallbackColor: string): string;
38
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/colors.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAqCD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAS/E;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAsDvF;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAqBvE;AAaD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAQvE;AAKD,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAExE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAUrE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAI/E"}