@perses-dev/histogram-chart-plugin 0.11.0-beta.0 → 0.11.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 (66) hide show
  1. package/__mf/js/{HistogramChart.6093b28c.js → HistogramChart.f6bd8f08.js} +3 -3
  2. package/__mf/js/async/12.97ac25db.js +2 -0
  3. package/__mf/js/async/161.565de0af.js +144 -0
  4. package/__mf/js/async/392.712ee0cf.js +2 -0
  5. package/__mf/js/async/__federation_expose_HistogramChart.721e2e2a.js +1 -0
  6. package/__mf/js/{main.e8b69fff.js → main.26934b75.js} +3 -3
  7. package/lib/HistogramChart.js +1 -1
  8. package/lib/HistogramChart.js.map +1 -1
  9. package/lib/bootstrap.js +1 -1
  10. package/lib/bootstrap.js.map +1 -1
  11. package/lib/cjs/HistogramChart.js +1 -1
  12. package/lib/cjs/bootstrap.js +1 -1
  13. package/lib/cjs/components/HistogramChart.js +71 -20
  14. package/lib/cjs/components/HistogramChartOptionsEditorSettings.js +19 -1
  15. package/lib/cjs/components/HistogramChartPanel.js +3 -2
  16. package/lib/cjs/components/index.js +1 -1
  17. package/lib/cjs/env.d.js +1 -1
  18. package/lib/cjs/getPluginModule.js +12 -0
  19. package/lib/cjs/histogram-chart-model.js +25 -1
  20. package/lib/cjs/index-federation.js +1 -1
  21. package/lib/cjs/index.js +1 -1
  22. package/lib/cjs/setup-tests.js +1 -1
  23. package/lib/cjs/utils/index.js +1 -1
  24. package/lib/cjs/utils/thresholds.js +12 -0
  25. package/lib/components/HistogramChart.d.ts +3 -1
  26. package/lib/components/HistogramChart.d.ts.map +1 -1
  27. package/lib/components/HistogramChart.js +71 -20
  28. package/lib/components/HistogramChart.js.map +1 -1
  29. package/lib/components/HistogramChartOptionsEditorSettings.d.ts.map +1 -1
  30. package/lib/components/HistogramChartOptionsEditorSettings.js +21 -3
  31. package/lib/components/HistogramChartOptionsEditorSettings.js.map +1 -1
  32. package/lib/components/HistogramChartPanel.d.ts.map +1 -1
  33. package/lib/components/HistogramChartPanel.js +3 -2
  34. package/lib/components/HistogramChartPanel.js.map +1 -1
  35. package/lib/components/index.js +1 -1
  36. package/lib/components/index.js.map +1 -1
  37. package/lib/env.d.js +1 -1
  38. package/lib/env.d.js.map +1 -1
  39. package/lib/getPluginModule.d.ts.map +1 -1
  40. package/lib/getPluginModule.js +12 -0
  41. package/lib/getPluginModule.js.map +1 -1
  42. package/lib/histogram-chart-model.d.ts +11 -0
  43. package/lib/histogram-chart-model.d.ts.map +1 -1
  44. package/lib/histogram-chart-model.js +20 -1
  45. package/lib/histogram-chart-model.js.map +1 -1
  46. package/lib/index-federation.js +1 -1
  47. package/lib/index-federation.js.map +1 -1
  48. package/lib/index.js +1 -1
  49. package/lib/index.js.map +1 -1
  50. package/lib/setup-tests.js +1 -1
  51. package/lib/setup-tests.js.map +1 -1
  52. package/lib/utils/index.js +1 -1
  53. package/lib/utils/index.js.map +1 -1
  54. package/lib/utils/thresholds.d.ts.map +1 -1
  55. package/lib/utils/thresholds.js +12 -0
  56. package/lib/utils/thresholds.js.map +1 -1
  57. package/mf-manifest.json +12 -12
  58. package/mf-stats.json +12 -12
  59. package/package.json +4 -4
  60. package/__mf/js/async/12.41482399.js +0 -2
  61. package/__mf/js/async/392.3fc5b732.js +0 -2
  62. package/__mf/js/async/735.ab58bf74.js +0 -144
  63. package/__mf/js/async/__federation_expose_HistogramChart.da17bbfc.js +0 -1
  64. /package/__mf/js/async/{12.41482399.js.LICENSE.txt → 12.97ac25db.js.LICENSE.txt} +0 -0
  65. /package/__mf/js/async/{735.ab58bf74.js.LICENSE.txt → 161.565de0af.js.LICENSE.txt} +0 -0
  66. /package/__mf/js/async/{392.3fc5b732.js.LICENSE.txt → 392.712ee0cf.js.LICENSE.txt} +0 -0
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -29,28 +29,49 @@ const _utils = require("../utils");
29
29
  (0, _core.use)([
30
30
  _charts.CustomChart
31
31
  ]);
32
- function HistogramChart({ width, height, data, format, min, max, thresholds }) {
32
+ function HistogramChart({ width, height, data, format, min, max, thresholds, logBase }) {
33
33
  const chartsTheme = (0, _components.useChartsTheme)();
34
34
  const transformedData = (0, _react.useMemo)(()=>{
35
35
  return data.buckets.map(([bucket, lowerBound, upperBound, count])=>{
36
+ let lower = parseFloat(lowerBound);
37
+ const upper = parseFloat(upperBound);
38
+ const countValue = parseFloat(count);
39
+ // For logarithmic scales, we need to handle non-positive lower bounds
40
+ // since log(0) and log(negative) are undefined
41
+ if (logBase !== undefined && lower <= 0) {
42
+ // Skip buckets that would be entirely non-positive on a log scale
43
+ if (upper <= 0) {
44
+ return null;
45
+ }
46
+ // For buckets that span from 0 (or negative) to positive,
47
+ // use a small fraction of the upper bound as the lower bound
48
+ // This ensures the bucket is still visible on the log scale
49
+ lower = upper * 0.001; // Use 0.1% of upper bound as minimum
50
+ }
36
51
  return {
37
52
  value: [
38
- parseFloat(lowerBound),
39
- parseFloat(upperBound),
40
- parseFloat(count),
53
+ lower,
54
+ upper,
55
+ countValue,
41
56
  bucket
42
57
  ],
43
58
  itemStyle: {
44
59
  color: (0, _utils.getColorFromThresholds)(parseFloat(lowerBound), thresholds, chartsTheme, chartsTheme.echartsTheme[0])
45
60
  }
46
61
  };
47
- });
62
+ }).filter((item)=>item !== null);
48
63
  }, [
49
64
  chartsTheme,
50
65
  data.buckets,
66
+ logBase,
51
67
  thresholds
52
68
  ]);
53
69
  const minXAxis = (0, _react.useMemo)(()=>{
70
+ if (logBase !== undefined) {
71
+ // For logarithmic scales, let ECharts auto-calculate the range based on data
72
+ // to avoid issues with non-positive values
73
+ return undefined;
74
+ }
54
75
  if (min) {
55
76
  return min;
56
77
  }
@@ -59,6 +80,7 @@ function HistogramChart({ width, height, data, format, min, max, thresholds }) {
59
80
  }
60
81
  return undefined;
61
82
  }, [
83
+ logBase,
62
84
  min,
63
85
  transformedData
64
86
  ]);
@@ -76,38 +98,66 @@ function HistogramChart({ width, height, data, format, min, max, thresholds }) {
76
98
  ]);
77
99
  const option = (0, _react.useMemo)(()=>{
78
100
  if (!transformedData) return chartsTheme.noDataOption;
101
+ // Build xAxis configuration based on whether logarithmic scale is requested
102
+ const xAxisConfig = {
103
+ scale: false,
104
+ min: minXAxis,
105
+ max: maxXAxis
106
+ };
107
+ // Apply logarithmic scale settings if requested
108
+ if (logBase !== undefined) {
109
+ xAxisConfig.type = 'log';
110
+ xAxisConfig.logBase = logBase;
111
+ }
79
112
  return {
80
113
  title: {
81
114
  show: false
82
115
  },
83
116
  tooltip: {},
84
- xAxis: {
85
- scale: false,
86
- min: minXAxis,
87
- max: maxXAxis
88
- },
117
+ xAxis: xAxisConfig,
89
118
  yAxis: (0, _components.getFormattedAxis)({}, format),
90
119
  series: [
91
120
  {
92
121
  type: 'custom',
93
122
  renderItem: function(params, api) {
123
+ const lowerBound = api.value(0);
124
+ const upperBound = api.value(1);
94
125
  const yValue = api.value(2);
95
- const start = api.coord([
96
- api.value(0),
126
+ // Get the pixel coordinates for the start and end points of the bar
127
+ const startCoord = api.coord([
128
+ lowerBound,
97
129
  yValue
98
130
  ]);
99
- const size = api.size?.([
100
- api.value(1) - api.value(0),
101
- yValue
131
+ const endCoord = api.coord([
132
+ upperBound,
133
+ 0
102
134
  ]);
135
+ // Extract coordinates with safety checks
136
+ const startX = startCoord?.[0];
137
+ const startY = startCoord?.[1];
138
+ const endX = endCoord?.[0];
139
+ const endY = endCoord?.[1];
140
+ // Check if coordinates are valid before proceeding
141
+ if (startX === undefined || startY === undefined || endX === undefined || endY === undefined) {
142
+ return null;
143
+ }
144
+ // For logarithmic scales, api.size() doesn't work correctly because
145
+ // the visual width isn't linear. Instead, we calculate the width
146
+ // directly from the pixel coordinates.
147
+ const barWidth = endX - startX;
148
+ const barHeight = endY - startY;
103
149
  const style = api.style?.();
150
+ // Skip rendering if coordinates are invalid (can happen with log scale edge cases)
151
+ if (!Number.isFinite(startX) || !Number.isFinite(startY) || !Number.isFinite(barWidth) || !Number.isFinite(barHeight)) {
152
+ return null;
153
+ }
104
154
  return {
105
155
  type: 'rect',
106
156
  shape: {
107
- x: start[0],
108
- y: start[1],
109
- width: size[0],
110
- height: size[1]
157
+ x: startX,
158
+ y: startY,
159
+ width: barWidth,
160
+ height: barHeight
111
161
  },
112
162
  style: style
113
163
  };
@@ -138,6 +188,7 @@ function HistogramChart({ width, height, data, format, min, max, thresholds }) {
138
188
  }, [
139
189
  chartsTheme.noDataOption,
140
190
  format,
191
+ logBase,
141
192
  maxXAxis,
142
193
  minXAxis,
143
194
  transformedData
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -46,6 +46,8 @@ function HistogramChartOptionsEditorSettings(props) {
46
46
  // ensures decimalPlaces defaults to correct value
47
47
  const format = (0, _merge.default)({}, _histogramchartmodel.DEFAULT_FORMAT, value.format);
48
48
  const thresholds = (0, _merge.default)({}, _histogramchartmodel.DEFAULT_THRESHOLDS, value.thresholds);
49
+ // Get the current log base configuration
50
+ const logBase = value.logBase ? _histogramchartmodel.LOG_BASE_CONFIG[value.logBase] : _histogramchartmodel.LOG_BASE_CONFIG['none'];
49
51
  // max only needs to be set explicitly for units other than percent and percent-decimal
50
52
  let minPlaceholder = 'Enter value';
51
53
  if (format.unit === 'percent') {
@@ -105,6 +107,22 @@ function HistogramChartOptionsEditorSettings(props) {
105
107
  width: '100%'
106
108
  }
107
109
  })
110
+ }),
111
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.OptionsEditorControl, {
112
+ label: "Log Base",
113
+ control: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.SettingsAutocomplete, {
114
+ value: {
115
+ ...logBase,
116
+ id: logBase?.label ?? 'None'
117
+ },
118
+ options: _histogramchartmodel.LOG_BASE_OPTIONS,
119
+ onChange: (__, newValue)=>{
120
+ onChange((0, _immer.produce)(value, (draft)=>{
121
+ draft.logBase = newValue.log;
122
+ }));
123
+ },
124
+ disableClearable: true
125
+ })
108
126
  })
109
127
  ]
110
128
  })
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -95,7 +95,8 @@ function HistogramChartPanel(props) {
95
95
  format: format,
96
96
  min: min,
97
97
  max: max,
98
- thresholds: thresholds
98
+ thresholds: thresholds,
99
+ logBase: pluginSpec.logBase
99
100
  })
100
101
  }, `histogram-series-${seriesIndex}`);
101
102
  })
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
package/lib/cjs/env.d.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -1,3 +1,15 @@
1
+ // Copyright 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.
1
13
  "use strict";
2
14
  Object.defineProperty(exports, "__esModule", {
3
15
  value: true
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -39,6 +39,12 @@ _export(exports, {
39
39
  get DEFAULT_THRESHOLDS () {
40
40
  return DEFAULT_THRESHOLDS;
41
41
  },
42
+ get LOG_BASE_CONFIG () {
43
+ return LOG_BASE_CONFIG;
44
+ },
45
+ get LOG_BASE_OPTIONS () {
46
+ return LOG_BASE_OPTIONS;
47
+ },
42
48
  get createInitialHistogramChartOptions () {
43
49
  return createInitialHistogramChartOptions;
44
50
  }
@@ -53,6 +59,24 @@ const DEFAULT_MIN_PERCENT = 0;
53
59
  const DEFAULT_MAX_PERCENT = 100;
54
60
  const DEFAULT_MIN_PERCENT_DECIMAL = 0;
55
61
  const DEFAULT_MAX_PERCENT_DECIMAL = 1;
62
+ const LOG_BASE_CONFIG = {
63
+ none: {
64
+ label: 'None',
65
+ log: undefined
66
+ },
67
+ '2': {
68
+ label: '2',
69
+ log: 2
70
+ },
71
+ '10': {
72
+ label: '10',
73
+ log: 10
74
+ }
75
+ };
76
+ const LOG_BASE_OPTIONS = Object.entries(LOG_BASE_CONFIG).map(([id, config])=>({
77
+ id: id,
78
+ ...config
79
+ }));
56
80
  function createInitialHistogramChartOptions() {
57
81
  return {
58
82
  format: DEFAULT_FORMAT
@@ -40,7 +40,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
40
40
  }
41
41
  return newObj;
42
42
  }
43
- // Copyright 2025 The Perses Authors
43
+ // Copyright The Perses Authors
44
44
  // Licensed under the Apache License, Version 2.0 (the "License");
45
45
  // you may not use this file except in compliance with the License.
46
46
  // You may obtain a copy of the License at
package/lib/cjs/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -1,4 +1,4 @@
1
- // Copyright 2025 The Perses Authors
1
+ // Copyright The Perses Authors
2
2
  // Licensed under the Apache License, Version 2.0 (the "License");
3
3
  // you may not use this file except in compliance with the License.
4
4
  // You may obtain a copy of the License at
@@ -1,3 +1,15 @@
1
+ // Copyright 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.
1
13
  "use strict";
2
14
  Object.defineProperty(exports, "__esModule", {
3
15
  value: true
@@ -1,5 +1,6 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { FormatOptions, BucketTuple, ThresholdOptions } from '@perses-dev/core';
3
+ import { LOG_BASE } from '../histogram-chart-model';
3
4
  export interface HistogramChartData {
4
5
  buckets: BucketTuple[];
5
6
  }
@@ -11,6 +12,7 @@ export interface HistogramChartProps {
11
12
  min?: number;
12
13
  max?: number;
13
14
  thresholds?: ThresholdOptions;
15
+ logBase?: LOG_BASE;
14
16
  }
15
- export declare function HistogramChart({ width, height, data, format, min, max, thresholds, }: HistogramChartProps): ReactElement | null;
17
+ export declare function HistogramChart({ width, height, data, format, min, max, thresholds, logBase, }: HistogramChartProps): ReactElement | null;
16
18
  //# sourceMappingURL=HistogramChart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HistogramChart.d.ts","sourceRoot":"","sources":["../../../src/components/HistogramChart.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAW,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAShF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAE/B;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,IAAI,EACJ,MAAM,EACN,GAAG,EACH,GAAG,EACH,UAAU,GACX,EAAE,mBAAmB,GAAG,YAAY,GAAG,IAAI,CAuG3C"}
1
+ {"version":3,"file":"HistogramChart.d.ts","sourceRoot":"","sources":["../../../src/components/HistogramChart.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAW,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAMhF,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAIpD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,IAAI,EACJ,MAAM,EACN,GAAG,EACH,GAAG,EACH,UAAU,EACV,OAAO,GACR,EAAE,mBAAmB,GAAG,YAAY,GAAG,IAAI,CAyK3C"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- // Copyright 2025 The Perses Authors
2
+ // Copyright The Perses Authors
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
5
5
  // You may obtain a copy of the License at
@@ -19,28 +19,49 @@ import { getColorFromThresholds } from '../utils';
19
19
  use([
20
20
  CustomChart
21
21
  ]);
22
- export function HistogramChart({ width, height, data, format, min, max, thresholds }) {
22
+ export function HistogramChart({ width, height, data, format, min, max, thresholds, logBase }) {
23
23
  const chartsTheme = useChartsTheme();
24
24
  const transformedData = useMemo(()=>{
25
25
  return data.buckets.map(([bucket, lowerBound, upperBound, count])=>{
26
+ let lower = parseFloat(lowerBound);
27
+ const upper = parseFloat(upperBound);
28
+ const countValue = parseFloat(count);
29
+ // For logarithmic scales, we need to handle non-positive lower bounds
30
+ // since log(0) and log(negative) are undefined
31
+ if (logBase !== undefined && lower <= 0) {
32
+ // Skip buckets that would be entirely non-positive on a log scale
33
+ if (upper <= 0) {
34
+ return null;
35
+ }
36
+ // For buckets that span from 0 (or negative) to positive,
37
+ // use a small fraction of the upper bound as the lower bound
38
+ // This ensures the bucket is still visible on the log scale
39
+ lower = upper * 0.001; // Use 0.1% of upper bound as minimum
40
+ }
26
41
  return {
27
42
  value: [
28
- parseFloat(lowerBound),
29
- parseFloat(upperBound),
30
- parseFloat(count),
43
+ lower,
44
+ upper,
45
+ countValue,
31
46
  bucket
32
47
  ],
33
48
  itemStyle: {
34
49
  color: getColorFromThresholds(parseFloat(lowerBound), thresholds, chartsTheme, chartsTheme.echartsTheme[0])
35
50
  }
36
51
  };
37
- });
52
+ }).filter((item)=>item !== null);
38
53
  }, [
39
54
  chartsTheme,
40
55
  data.buckets,
56
+ logBase,
41
57
  thresholds
42
58
  ]);
43
59
  const minXAxis = useMemo(()=>{
60
+ if (logBase !== undefined) {
61
+ // For logarithmic scales, let ECharts auto-calculate the range based on data
62
+ // to avoid issues with non-positive values
63
+ return undefined;
64
+ }
44
65
  if (min) {
45
66
  return min;
46
67
  }
@@ -49,6 +70,7 @@ export function HistogramChart({ width, height, data, format, min, max, threshol
49
70
  }
50
71
  return undefined;
51
72
  }, [
73
+ logBase,
52
74
  min,
53
75
  transformedData
54
76
  ]);
@@ -66,38 +88,66 @@ export function HistogramChart({ width, height, data, format, min, max, threshol
66
88
  ]);
67
89
  const option = useMemo(()=>{
68
90
  if (!transformedData) return chartsTheme.noDataOption;
91
+ // Build xAxis configuration based on whether logarithmic scale is requested
92
+ const xAxisConfig = {
93
+ scale: false,
94
+ min: minXAxis,
95
+ max: maxXAxis
96
+ };
97
+ // Apply logarithmic scale settings if requested
98
+ if (logBase !== undefined) {
99
+ xAxisConfig.type = 'log';
100
+ xAxisConfig.logBase = logBase;
101
+ }
69
102
  return {
70
103
  title: {
71
104
  show: false
72
105
  },
73
106
  tooltip: {},
74
- xAxis: {
75
- scale: false,
76
- min: minXAxis,
77
- max: maxXAxis
78
- },
107
+ xAxis: xAxisConfig,
79
108
  yAxis: getFormattedAxis({}, format),
80
109
  series: [
81
110
  {
82
111
  type: 'custom',
83
112
  renderItem: function(params, api) {
113
+ const lowerBound = api.value(0);
114
+ const upperBound = api.value(1);
84
115
  const yValue = api.value(2);
85
- const start = api.coord([
86
- api.value(0),
116
+ // Get the pixel coordinates for the start and end points of the bar
117
+ const startCoord = api.coord([
118
+ lowerBound,
87
119
  yValue
88
120
  ]);
89
- const size = api.size?.([
90
- api.value(1) - api.value(0),
91
- yValue
121
+ const endCoord = api.coord([
122
+ upperBound,
123
+ 0
92
124
  ]);
125
+ // Extract coordinates with safety checks
126
+ const startX = startCoord?.[0];
127
+ const startY = startCoord?.[1];
128
+ const endX = endCoord?.[0];
129
+ const endY = endCoord?.[1];
130
+ // Check if coordinates are valid before proceeding
131
+ if (startX === undefined || startY === undefined || endX === undefined || endY === undefined) {
132
+ return null;
133
+ }
134
+ // For logarithmic scales, api.size() doesn't work correctly because
135
+ // the visual width isn't linear. Instead, we calculate the width
136
+ // directly from the pixel coordinates.
137
+ const barWidth = endX - startX;
138
+ const barHeight = endY - startY;
93
139
  const style = api.style?.();
140
+ // Skip rendering if coordinates are invalid (can happen with log scale edge cases)
141
+ if (!Number.isFinite(startX) || !Number.isFinite(startY) || !Number.isFinite(barWidth) || !Number.isFinite(barHeight)) {
142
+ return null;
143
+ }
94
144
  return {
95
145
  type: 'rect',
96
146
  shape: {
97
- x: start[0],
98
- y: start[1],
99
- width: size[0],
100
- height: size[1]
147
+ x: startX,
148
+ y: startY,
149
+ width: barWidth,
150
+ height: barHeight
101
151
  },
102
152
  style: style
103
153
  };
@@ -128,6 +178,7 @@ export function HistogramChart({ width, height, data, format, min, max, threshol
128
178
  }, [
129
179
  chartsTheme.noDataOption,
130
180
  format,
181
+ logBase,
131
182
  maxXAxis,
132
183
  minXAxis,
133
184
  transformedData
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/HistogramChart.tsx"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useMemo } from 'react';\nimport { FormatOptions, BucketTuple, ThresholdOptions } from '@perses-dev/core';\nimport { EChart, getFormattedAxis, useChartsTheme } from '@perses-dev/components';\nimport { use, EChartsCoreOption } from 'echarts/core';\nimport { CustomSeriesRenderItemAPI, CustomSeriesRenderItemParams } from 'echarts';\nimport { CustomChart } from 'echarts/charts';\nimport { getColorFromThresholds } from '../utils';\n\nuse([CustomChart]);\n\nexport interface HistogramChartData {\n buckets: BucketTuple[];\n}\n\nexport interface HistogramChartProps {\n width: number;\n height: number;\n data: HistogramChartData;\n format?: FormatOptions;\n min?: number;\n max?: number;\n thresholds?: ThresholdOptions;\n // TODO: exponential?: boolean;\n}\n\nexport function HistogramChart({\n width,\n height,\n data,\n format,\n min,\n max,\n thresholds,\n}: HistogramChartProps): ReactElement | null {\n const chartsTheme = useChartsTheme();\n\n const transformedData = useMemo(() => {\n return data.buckets.map(([bucket, lowerBound, upperBound, count]) => {\n return {\n value: [parseFloat(lowerBound), parseFloat(upperBound), parseFloat(count), bucket],\n itemStyle: {\n color: getColorFromThresholds(\n parseFloat(lowerBound),\n thresholds,\n chartsTheme,\n chartsTheme.echartsTheme[0] as string\n ),\n },\n };\n });\n }, [chartsTheme, data.buckets, thresholds]);\n\n const minXAxis: number | undefined = useMemo(() => {\n if (min) {\n return min;\n }\n\n if (transformedData && transformedData[0]) {\n return Math.min(0, Math.floor(transformedData[0]?.value[0] ?? 0));\n }\n return undefined;\n }, [min, transformedData]);\n\n const maxXAxis: number | undefined = useMemo(() => {\n if (max) {\n return max;\n }\n if (transformedData && transformedData[transformedData.length - 1]) {\n return Math.ceil(transformedData[transformedData.length - 1]?.value[1] ?? 1);\n }\n return undefined;\n }, [max, transformedData]);\n\n const option: EChartsCoreOption = useMemo(() => {\n if (!transformedData) return chartsTheme.noDataOption;\n\n return {\n title: {\n show: false,\n },\n tooltip: {},\n xAxis: {\n scale: false,\n min: minXAxis,\n max: maxXAxis,\n },\n yAxis: getFormattedAxis({}, format),\n series: [\n {\n type: 'custom',\n renderItem: function (params: CustomSeriesRenderItemParams, api: CustomSeriesRenderItemAPI) {\n const yValue = api.value(2);\n const start = api.coord([api.value(0), yValue]);\n const size = api.size?.([(api.value(1) as number) - (api.value(0) as number), yValue]) as number[];\n const style = api.style?.();\n\n return {\n type: 'rect',\n shape: {\n x: start[0],\n y: start[1],\n width: size[0],\n height: size[1],\n },\n style: style,\n };\n },\n label: {\n show: false,\n },\n dimensions: ['from', 'to'],\n encode: {\n x: [0, 1],\n y: 2,\n tooltip: [0, 1],\n itemName: 2,\n },\n data: transformedData,\n },\n ],\n };\n }, [chartsTheme.noDataOption, format, maxXAxis, minXAxis, transformedData]);\n\n return (\n <EChart\n style={{\n width: width,\n height: height,\n }}\n sx={{\n padding: `${chartsTheme.container.padding.default}px`,\n }}\n option={option}\n theme={chartsTheme.echartsTheme}\n />\n );\n}\n"],"names":["useMemo","EChart","getFormattedAxis","useChartsTheme","use","CustomChart","getColorFromThresholds","HistogramChart","width","height","data","format","min","max","thresholds","chartsTheme","transformedData","buckets","map","bucket","lowerBound","upperBound","count","value","parseFloat","itemStyle","color","echartsTheme","minXAxis","Math","floor","undefined","maxXAxis","length","ceil","option","noDataOption","title","show","tooltip","xAxis","scale","yAxis","series","type","renderItem","params","api","yValue","start","coord","size","style","shape","x","y","label","dimensions","encode","itemName","sx","padding","container","default","theme"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/HistogramChart.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useMemo } from 'react';\nimport { FormatOptions, BucketTuple, ThresholdOptions } from '@perses-dev/core';\nimport { EChart, getFormattedAxis, useChartsTheme } from '@perses-dev/components';\nimport { use, EChartsCoreOption } from 'echarts/core';\nimport { CustomSeriesRenderItemAPI, CustomSeriesRenderItemParams } from 'echarts';\nimport { CustomChart } from 'echarts/charts';\nimport { getColorFromThresholds } from '../utils';\nimport { LOG_BASE } from '../histogram-chart-model';\n\nuse([CustomChart]);\n\nexport interface HistogramChartData {\n buckets: BucketTuple[];\n}\n\nexport interface HistogramChartProps {\n width: number;\n height: number;\n data: HistogramChartData;\n format?: FormatOptions;\n min?: number;\n max?: number;\n thresholds?: ThresholdOptions;\n logBase?: LOG_BASE;\n}\n\nexport function HistogramChart({\n width,\n height,\n data,\n format,\n min,\n max,\n thresholds,\n logBase,\n}: HistogramChartProps): ReactElement | null {\n const chartsTheme = useChartsTheme();\n\n const transformedData = useMemo(() => {\n return data.buckets\n .map(([bucket, lowerBound, upperBound, count]) => {\n let lower = parseFloat(lowerBound);\n const upper = parseFloat(upperBound);\n const countValue = parseFloat(count);\n\n // For logarithmic scales, we need to handle non-positive lower bounds\n // since log(0) and log(negative) are undefined\n if (logBase !== undefined && lower <= 0) {\n // Skip buckets that would be entirely non-positive on a log scale\n if (upper <= 0) {\n return null;\n }\n // For buckets that span from 0 (or negative) to positive,\n // use a small fraction of the upper bound as the lower bound\n // This ensures the bucket is still visible on the log scale\n lower = upper * 0.001; // Use 0.1% of upper bound as minimum\n }\n\n return {\n value: [lower, upper, countValue, bucket],\n itemStyle: {\n color: getColorFromThresholds(\n parseFloat(lowerBound), // Use original lower bound for threshold coloring\n thresholds,\n chartsTheme,\n chartsTheme.echartsTheme[0] as string\n ),\n },\n };\n })\n .filter((item): item is NonNullable<typeof item> => item !== null);\n }, [chartsTheme, data.buckets, logBase, thresholds]);\n\n const minXAxis: number | undefined = useMemo(() => {\n if (logBase !== undefined) {\n // For logarithmic scales, let ECharts auto-calculate the range based on data\n // to avoid issues with non-positive values\n return undefined;\n }\n\n if (min) {\n return min;\n }\n\n if (transformedData && transformedData[0]) {\n return Math.min(0, Math.floor(transformedData[0]?.value[0] ?? 0));\n }\n return undefined;\n }, [logBase, min, transformedData]);\n\n const maxXAxis: number | undefined = useMemo(() => {\n if (max) {\n return max;\n }\n if (transformedData && transformedData[transformedData.length - 1]) {\n return Math.ceil(transformedData[transformedData.length - 1]?.value[1] ?? 1);\n }\n return undefined;\n }, [max, transformedData]);\n\n const option: EChartsCoreOption = useMemo(() => {\n if (!transformedData) return chartsTheme.noDataOption;\n\n // Build xAxis configuration based on whether logarithmic scale is requested\n const xAxisConfig: Record<string, unknown> = {\n scale: false,\n min: minXAxis,\n max: maxXAxis,\n };\n\n // Apply logarithmic scale settings if requested\n if (logBase !== undefined) {\n xAxisConfig.type = 'log';\n xAxisConfig.logBase = logBase;\n }\n\n return {\n title: {\n show: false,\n },\n tooltip: {},\n xAxis: xAxisConfig,\n yAxis: getFormattedAxis({}, format),\n series: [\n {\n type: 'custom',\n renderItem: function (params: CustomSeriesRenderItemParams, api: CustomSeriesRenderItemAPI) {\n const lowerBound = api.value(0) as number;\n const upperBound = api.value(1) as number;\n const yValue = api.value(2) as number;\n\n // Get the pixel coordinates for the start and end points of the bar\n const startCoord = api.coord([lowerBound, yValue]);\n const endCoord = api.coord([upperBound, 0]);\n\n // Extract coordinates with safety checks\n const startX = startCoord?.[0];\n const startY = startCoord?.[1];\n const endX = endCoord?.[0];\n const endY = endCoord?.[1];\n\n // Check if coordinates are valid before proceeding\n if (startX === undefined || startY === undefined || endX === undefined || endY === undefined) {\n return null;\n }\n\n // For logarithmic scales, api.size() doesn't work correctly because\n // the visual width isn't linear. Instead, we calculate the width\n // directly from the pixel coordinates.\n const barWidth = endX - startX;\n const barHeight = endY - startY;\n\n const style = api.style?.();\n\n // Skip rendering if coordinates are invalid (can happen with log scale edge cases)\n if (\n !Number.isFinite(startX) ||\n !Number.isFinite(startY) ||\n !Number.isFinite(barWidth) ||\n !Number.isFinite(barHeight)\n ) {\n return null;\n }\n\n return {\n type: 'rect',\n shape: {\n x: startX,\n y: startY,\n width: barWidth,\n height: barHeight,\n },\n style: style,\n };\n },\n label: {\n show: false,\n },\n dimensions: ['from', 'to'],\n encode: {\n x: [0, 1],\n y: 2,\n tooltip: [0, 1],\n itemName: 2,\n },\n data: transformedData,\n },\n ],\n };\n }, [chartsTheme.noDataOption, format, logBase, maxXAxis, minXAxis, transformedData]);\n\n return (\n <EChart\n style={{\n width: width,\n height: height,\n }}\n sx={{\n padding: `${chartsTheme.container.padding.default}px`,\n }}\n option={option}\n theme={chartsTheme.echartsTheme}\n />\n );\n}\n"],"names":["useMemo","EChart","getFormattedAxis","useChartsTheme","use","CustomChart","getColorFromThresholds","HistogramChart","width","height","data","format","min","max","thresholds","logBase","chartsTheme","transformedData","buckets","map","bucket","lowerBound","upperBound","count","lower","parseFloat","upper","countValue","undefined","value","itemStyle","color","echartsTheme","filter","item","minXAxis","Math","floor","maxXAxis","length","ceil","option","noDataOption","xAxisConfig","scale","type","title","show","tooltip","xAxis","yAxis","series","renderItem","params","api","yValue","startCoord","coord","endCoord","startX","startY","endX","endY","barWidth","barHeight","style","Number","isFinite","shape","x","y","label","dimensions","encode","itemName","sx","padding","container","default","theme"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"HistogramChartOptionsEditorSettings.d.ts","sourceRoot":"","sources":["../../../src/components/HistogramChartOptionsEditorSettings.tsx"],"names":[],"mappings":"AA0BA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACrC,OAAO,EAQL,gCAAgC,EACjC,MAAM,0BAA0B,CAAC;AAElC,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,gCAAgC,GAAG,YAAY,CA2FzG"}
1
+ {"version":3,"file":"HistogramChartOptionsEditorSettings.d.ts","sourceRoot":"","sources":["../../../src/components/HistogramChartOptionsEditorSettings.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACrC,OAAO,EAQL,gCAAgC,EAGjC,MAAM,0BAA0B,CAAC;AAElC,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,gCAAgC,GAAG,YAAY,CAkHzG"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // Copyright 2025 The Perses Authors
2
+ // Copyright The Perses Authors
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
5
5
  // You may obtain a copy of the License at
@@ -12,10 +12,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import { TextField } from '@mui/material';
15
- import { FormatControls, OptionsEditorColumn, OptionsEditorControl, OptionsEditorGrid, OptionsEditorGroup, ThresholdsEditor } from '@perses-dev/components';
15
+ import { FormatControls, OptionsEditorColumn, OptionsEditorControl, OptionsEditorGrid, OptionsEditorGroup, ThresholdsEditor, SettingsAutocomplete } from '@perses-dev/components';
16
16
  import { produce } from 'immer';
17
17
  import merge from 'lodash/merge';
18
- import { DEFAULT_FORMAT, DEFAULT_MAX_PERCENT, DEFAULT_MAX_PERCENT_DECIMAL, DEFAULT_MIN_PERCENT, DEFAULT_MIN_PERCENT_DECIMAL, DEFAULT_THRESHOLDS } from '../histogram-chart-model';
18
+ import { DEFAULT_FORMAT, DEFAULT_MAX_PERCENT, DEFAULT_MAX_PERCENT_DECIMAL, DEFAULT_MIN_PERCENT, DEFAULT_MIN_PERCENT_DECIMAL, DEFAULT_THRESHOLDS, LOG_BASE_CONFIG, LOG_BASE_OPTIONS } from '../histogram-chart-model';
19
19
  export function HistogramChartOptionsEditorSettings(props) {
20
20
  const { onChange, value } = props;
21
21
  const handleUnitChange = (newFormat)=>{
@@ -31,6 +31,8 @@ export function HistogramChartOptionsEditorSettings(props) {
31
31
  // ensures decimalPlaces defaults to correct value
32
32
  const format = merge({}, DEFAULT_FORMAT, value.format);
33
33
  const thresholds = merge({}, DEFAULT_THRESHOLDS, value.thresholds);
34
+ // Get the current log base configuration
35
+ const logBase = value.logBase ? LOG_BASE_CONFIG[value.logBase] : LOG_BASE_CONFIG['none'];
34
36
  // max only needs to be set explicitly for units other than percent and percent-decimal
35
37
  let minPlaceholder = 'Enter value';
36
38
  if (format.unit === 'percent') {
@@ -90,6 +92,22 @@ export function HistogramChartOptionsEditorSettings(props) {
90
92
  width: '100%'
91
93
  }
92
94
  })
95
+ }),
96
+ /*#__PURE__*/ _jsx(OptionsEditorControl, {
97
+ label: "Log Base",
98
+ control: /*#__PURE__*/ _jsx(SettingsAutocomplete, {
99
+ value: {
100
+ ...logBase,
101
+ id: logBase?.label ?? 'None'
102
+ },
103
+ options: LOG_BASE_OPTIONS,
104
+ onChange: (__, newValue)=>{
105
+ onChange(produce(value, (draft)=>{
106
+ draft.logBase = newValue.log;
107
+ }));
108
+ },
109
+ disableClearable: true
110
+ })
93
111
  })
94
112
  ]
95
113
  })