@perses-dev/pie-chart-plugin 0.10.0 → 0.12.1

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 (123) hide show
  1. package/__mf/css/async/442.d3010b86.css +1 -0
  2. package/__mf/css/async/61.d3010b86.css +1 -0
  3. package/__mf/css/async/823.d3010b86.css +1 -0
  4. package/__mf/js/PieChart.b1153c53.js +6 -0
  5. package/__mf/js/async/{964.7fdfdfd5.js → 121.281eb287.js} +2 -2
  6. package/__mf/js/async/{488.a0bde6cf.js → 177.c83badab.js} +1 -1
  7. package/__mf/js/async/192.b0eb01c2.js +1 -0
  8. package/__mf/js/async/2.ba8aa6eb.js +1 -0
  9. package/__mf/js/async/217.01ced8ce.js +110 -0
  10. package/__mf/js/async/235.88141957.js +1 -0
  11. package/__mf/js/async/250.baaa2e6d.js +7 -0
  12. package/__mf/js/async/252.f2f74aad.js +22 -0
  13. package/__mf/js/async/274.78035147.js +2 -0
  14. package/__mf/js/async/322.e2f8adf7.js +2 -0
  15. package/__mf/js/async/337.13482c5c.js +1 -0
  16. package/__mf/js/async/350.7f227cc5.js +1 -0
  17. package/__mf/js/async/356.75a8af4c.js +1 -0
  18. package/__mf/js/async/392.4e64389c.js +2 -0
  19. package/__mf/js/async/469.e52e96c4.js +1 -0
  20. package/__mf/js/async/470.844ea64f.js +2 -0
  21. package/__mf/js/async/554.2692322c.js +2 -0
  22. package/__mf/js/async/{214.a7648318.js → 587.6f746ff5.js} +1 -1
  23. package/__mf/js/async/616.b6650249.js +1 -0
  24. package/__mf/js/async/663.c0629798.js +1 -0
  25. package/__mf/js/async/721.8dc45583.js +1 -0
  26. package/__mf/js/async/873.8b5831f0.js +1 -0
  27. package/__mf/js/async/941.ca6b716b.js +38 -0
  28. package/__mf/js/async/{738.5a36e399.js → 968.a62ee0f7.js} +1 -1
  29. package/__mf/js/async/__federation_expose_PieChart.af9fd247.js +1 -0
  30. package/__mf/js/async/lib-router.34969c19.js +2 -0
  31. package/__mf/js/main.75a48646.js +6 -0
  32. package/lib/PieChartBase.d.ts +1 -2
  33. package/lib/PieChartBase.d.ts.map +1 -1
  34. package/lib/PieChartBase.js +27 -26
  35. package/lib/PieChartBase.js.map +1 -1
  36. package/lib/PieChartOptionsEditorSettings.d.ts.map +1 -1
  37. package/lib/PieChartOptionsEditorSettings.js +145 -18
  38. package/lib/PieChartOptionsEditorSettings.js.map +1 -1
  39. package/lib/PieChartPanel.d.ts.map +1 -1
  40. package/lib/PieChartPanel.js +37 -28
  41. package/lib/PieChartPanel.js.map +1 -1
  42. package/lib/bootstrap.js +1 -1
  43. package/lib/bootstrap.js.map +1 -1
  44. package/lib/cjs/PieChartBase.js +24 -23
  45. package/lib/cjs/PieChartOptionsEditorSettings.js +142 -15
  46. package/lib/cjs/PieChartPanel.js +35 -26
  47. package/lib/cjs/colors.js +207 -0
  48. package/lib/cjs/index-federation.js +12 -12
  49. package/lib/cjs/index.js +2 -4
  50. package/lib/cjs/pie-chart-model.js +8 -7
  51. package/lib/cjs/utils.js +13 -33
  52. package/lib/colors.d.ts +38 -0
  53. package/lib/colors.d.ts.map +1 -0
  54. package/lib/colors.js +192 -0
  55. package/lib/colors.js.map +1 -0
  56. package/lib/index.d.ts +2 -4
  57. package/lib/index.d.ts.map +1 -1
  58. package/lib/index.js +2 -4
  59. package/lib/index.js.map +1 -1
  60. package/lib/pie-chart-model.d.ts +5 -3
  61. package/lib/pie-chart-model.d.ts.map +1 -1
  62. package/lib/pie-chart-model.js +3 -2
  63. package/lib/pie-chart-model.js.map +1 -1
  64. package/lib/utils.d.ts.map +1 -1
  65. package/lib/utils.js +10 -30
  66. package/lib/utils.js.map +1 -1
  67. package/mf-manifest.json +35 -55
  68. package/mf-stats.json +35 -58
  69. package/package.json +4 -4
  70. package/__mf/css/async/263.80005a4a.css +0 -1
  71. package/__mf/css/async/341.80005a4a.css +0 -1
  72. package/__mf/css/async/759.80005a4a.css +0 -1
  73. package/__mf/js/PieChart.df86cbf0.js +0 -5
  74. package/__mf/js/async/109.77dcc7d9.js +0 -73
  75. package/__mf/js/async/173.c694e6f7.js +0 -2
  76. package/__mf/js/async/224.43460380.js +0 -1
  77. package/__mf/js/async/238.3e689a99.js +0 -1
  78. package/__mf/js/async/288.4cad0403.js +0 -7
  79. package/__mf/js/async/289.c295f73f.js +0 -38
  80. package/__mf/js/async/292.67519c5b.js +0 -1
  81. package/__mf/js/async/298.707087d2.js +0 -1
  82. package/__mf/js/async/409.9c48d616.js +0 -1
  83. package/__mf/js/async/470.1e913aa7.js +0 -2
  84. package/__mf/js/async/651.9c74cbf3.js +0 -1
  85. package/__mf/js/async/656.13055e59.js +0 -1
  86. package/__mf/js/async/680.f1da299d.js +0 -110
  87. package/__mf/js/async/694.011b21e8.js +0 -1
  88. package/__mf/js/async/707.c77cb775.js +0 -1
  89. package/__mf/js/async/708.77a1c1f6.js +0 -1
  90. package/__mf/js/async/740.254a5697.js +0 -1
  91. package/__mf/js/async/75.a825d10b.js +0 -1
  92. package/__mf/js/async/770.73dda090.js +0 -1
  93. package/__mf/js/async/863.2d634113.js +0 -2
  94. package/__mf/js/async/960.021d7634.js +0 -2
  95. package/__mf/js/async/981.e6f0d188.js +0 -2
  96. package/__mf/js/async/__federation_expose_PieChart.3d887a98.js +0 -1
  97. package/__mf/js/async/lib-router.5205dc27.js +0 -2
  98. package/__mf/js/main.47849ff0.js +0 -5
  99. package/lib/cjs/model.js +0 -16
  100. package/lib/cjs/palette-gen.js +0 -63
  101. package/lib/cjs/palette.js +0 -83
  102. package/lib/model.d.ts +0 -20
  103. package/lib/model.d.ts.map +0 -1
  104. package/lib/model.js +0 -15
  105. package/lib/model.js.map +0 -1
  106. package/lib/palette-gen.d.ts +0 -20
  107. package/lib/palette-gen.d.ts.map +0 -1
  108. package/lib/palette-gen.js +0 -50
  109. package/lib/palette-gen.js.map +0 -1
  110. package/lib/palette.d.ts +0 -6
  111. package/lib/palette.d.ts.map +0 -1
  112. package/lib/palette.js +0 -64
  113. package/lib/palette.js.map +0 -1
  114. /package/__mf/js/async/{964.7fdfdfd5.js.LICENSE.txt → 121.281eb287.js.LICENSE.txt} +0 -0
  115. /package/__mf/js/async/{680.f1da299d.js.LICENSE.txt → 217.01ced8ce.js.LICENSE.txt} +0 -0
  116. /package/__mf/js/async/{288.4cad0403.js.LICENSE.txt → 250.baaa2e6d.js.LICENSE.txt} +0 -0
  117. /package/__mf/js/async/{109.77dcc7d9.js.LICENSE.txt → 252.f2f74aad.js.LICENSE.txt} +0 -0
  118. /package/__mf/js/async/{960.021d7634.js.LICENSE.txt → 274.78035147.js.LICENSE.txt} +0 -0
  119. /package/__mf/js/async/{863.2d634113.js.LICENSE.txt → 322.e2f8adf7.js.LICENSE.txt} +0 -0
  120. /package/__mf/js/async/{981.e6f0d188.js.LICENSE.txt → 392.4e64389c.js.LICENSE.txt} +0 -0
  121. /package/__mf/js/async/{173.c694e6f7.js.LICENSE.txt → 470.844ea64f.js.LICENSE.txt} +0 -0
  122. /package/__mf/js/async/{470.1e913aa7.js.LICENSE.txt → 554.2692322c.js.LICENSE.txt} +0 -0
  123. /package/__mf/js/async/{lib-router.5205dc27.js.LICENSE.txt → lib-router.34969c19.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: Object.getOwnPropertyDescriptor(all, name).get
21
+ });
22
+ }
23
+ _export(exports, {
24
+ get generateGradientColor () {
25
+ return generateGradientColor;
26
+ },
27
+ get getAutoPaletteColor () {
28
+ return getAutoPaletteColor;
29
+ },
30
+ get getColor () {
31
+ return getColor;
32
+ },
33
+ get getConsistentColor () {
34
+ return getConsistentColor;
35
+ },
36
+ get getConsistentSeriesNameColor () {
37
+ return getConsistentSeriesNameColor;
38
+ },
39
+ get getDefaultSeriesColor () {
40
+ return getDefaultSeriesColor;
41
+ },
42
+ get getSeriesColor () {
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
+ }
@@ -1,15 +1,3 @@
1
- // Copyright 2024 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
1
  "use strict";
14
2
  function _getRequireWildcardCache(nodeInterop) {
15
3
  if (typeof WeakMap !== "function") return null;
@@ -52,4 +40,16 @@ function _interop_require_wildcard(obj, nodeInterop) {
52
40
  }
53
41
  return newObj;
54
42
  }
43
+ // Copyright 2024 The Perses Authors
44
+ // Licensed under the Apache License, Version 2.0 (the "License");
45
+ // you may not use this file except in compliance with the License.
46
+ // You may obtain a copy of the License at
47
+ //
48
+ // http://www.apache.org/licenses/LICENSE-2.0
49
+ //
50
+ // Unless required by applicable law or agreed to in writing, software
51
+ // distributed under the License is distributed on an "AS IS" BASIS,
52
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
53
+ // See the License for the specific language governing permissions and
54
+ // limitations under the License.
55
55
  Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./bootstrap")));
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);
@@ -17,20 +17,20 @@ Object.defineProperty(exports, "__esModule", {
17
17
  function _export(target, all) {
18
18
  for(var name in all)Object.defineProperty(target, name, {
19
19
  enumerable: true,
20
- get: all[name]
20
+ get: Object.getOwnPropertyDescriptor(all, name).get
21
21
  });
22
22
  }
23
23
  _export(exports, {
24
- DEFAULT_FORMAT: function() {
24
+ get DEFAULT_FORMAT () {
25
25
  return DEFAULT_FORMAT;
26
26
  },
27
- DEFAULT_MODE: function() {
27
+ get DEFAULT_MODE () {
28
28
  return DEFAULT_MODE;
29
29
  },
30
- DEFAULT_SORT: function() {
30
+ get DEFAULT_SORT () {
31
31
  return DEFAULT_SORT;
32
32
  },
33
- createInitialPieChartOptions: function() {
33
+ get createInitialPieChartOptions () {
34
34
  return createInitialPieChartOptions;
35
35
  }
36
36
  });
@@ -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
@@ -17,14 +17,14 @@ Object.defineProperty(exports, "__esModule", {
17
17
  function _export(target, all) {
18
18
  for(var name in all)Object.defineProperty(target, name, {
19
19
  enumerable: true,
20
- get: all[name]
20
+ get: Object.getOwnPropertyDescriptor(all, name).get
21
21
  });
22
22
  }
23
23
  _export(exports, {
24
- calculatePercentages: function() {
24
+ get calculatePercentages () {
25
25
  return calculatePercentages;
26
26
  },
27
- sortSeriesData: function() {
27
+ get sortSeriesData () {
28
28
  return sortSeriesData;
29
29
  }
30
30
  });
@@ -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
  }