@perses-dev/components 0.31.0 → 0.33.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 (111) hide show
  1. package/dist/ContentWithLegend/ContentWithLegend.d.ts +11 -0
  2. package/dist/ContentWithLegend/ContentWithLegend.d.ts.map +1 -0
  3. package/dist/ContentWithLegend/ContentWithLegend.js +65 -0
  4. package/dist/ContentWithLegend/ContentWithLegend.js.map +1 -0
  5. package/dist/ContentWithLegend/index.d.ts +2 -0
  6. package/dist/ContentWithLegend/index.d.ts.map +1 -0
  7. package/dist/ContentWithLegend/index.js +15 -0
  8. package/dist/ContentWithLegend/index.js.map +1 -0
  9. package/dist/ContentWithLegend/model/content-with-legend-model.d.ts +68 -0
  10. package/dist/ContentWithLegend/model/content-with-legend-model.d.ts.map +1 -0
  11. package/dist/ContentWithLegend/model/content-with-legend-model.js +90 -0
  12. package/dist/ContentWithLegend/model/content-with-legend-model.js.map +1 -0
  13. package/dist/EChart/EChart.d.ts.map +1 -1
  14. package/dist/EChart/EChart.js +9 -1
  15. package/dist/EChart/EChart.js.map +1 -1
  16. package/dist/Legend/Legend.d.ts.map +1 -1
  17. package/dist/Legend/Legend.js +30 -15
  18. package/dist/Legend/Legend.js.map +1 -1
  19. package/dist/Legend/ListLegend.d.ts.map +1 -1
  20. package/dist/Legend/ListLegend.js +2 -23
  21. package/dist/Legend/ListLegend.js.map +1 -1
  22. package/dist/Legend/ListLegendItem.d.ts +1 -1
  23. package/dist/Legend/TableLegend.d.ts +12 -0
  24. package/dist/Legend/TableLegend.d.ts.map +1 -0
  25. package/dist/Legend/TableLegend.js +61 -0
  26. package/dist/Legend/TableLegend.js.map +1 -0
  27. package/dist/LegendOptionsEditor/LegendOptionsEditor.d.ts.map +1 -1
  28. package/dist/LegendOptionsEditor/LegendOptionsEditor.js +35 -3
  29. package/dist/LegendOptionsEditor/LegendOptionsEditor.js.map +1 -1
  30. package/dist/LineChart/LineChart.d.ts.map +1 -1
  31. package/dist/LineChart/LineChart.js +60 -22
  32. package/dist/LineChart/LineChart.js.map +1 -1
  33. package/dist/StatChart/StatChart.d.ts.map +1 -1
  34. package/dist/StatChart/StatChart.js +8 -1
  35. package/dist/StatChart/StatChart.js.map +1 -1
  36. package/dist/Table/InnerTable.js +1 -1
  37. package/dist/Table/InnerTable.js.map +1 -1
  38. package/dist/Table/TableCell.js +1 -1
  39. package/dist/Table/TableCell.js.map +1 -1
  40. package/dist/Table/TableRow.d.ts.map +1 -1
  41. package/dist/Table/TableRow.js +3 -3
  42. package/dist/Table/TableRow.js.map +1 -1
  43. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.d.ts +5 -5
  44. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.d.ts.map +1 -1
  45. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.js +36 -54
  46. package/dist/TimeSeriesTooltip/TimeSeriesTooltip.js.map +1 -1
  47. package/dist/TimeSeriesTooltip/TooltipContent.d.ts +0 -2
  48. package/dist/TimeSeriesTooltip/TooltipContent.d.ts.map +1 -1
  49. package/dist/TimeSeriesTooltip/TooltipContent.js +21 -97
  50. package/dist/TimeSeriesTooltip/TooltipContent.js.map +1 -1
  51. package/dist/TimeSeriesTooltip/TooltipHeader.d.ts +12 -0
  52. package/dist/TimeSeriesTooltip/TooltipHeader.d.ts.map +1 -0
  53. package/dist/TimeSeriesTooltip/TooltipHeader.js +163 -0
  54. package/dist/TimeSeriesTooltip/TooltipHeader.js.map +1 -0
  55. package/dist/TimeSeriesTooltip/index.d.ts +1 -0
  56. package/dist/TimeSeriesTooltip/index.d.ts.map +1 -1
  57. package/dist/TimeSeriesTooltip/index.js +1 -0
  58. package/dist/TimeSeriesTooltip/index.js.map +1 -1
  59. package/dist/TimeSeriesTooltip/nearby-series.d.ts +2 -2
  60. package/dist/TimeSeriesTooltip/nearby-series.d.ts.map +1 -1
  61. package/dist/TimeSeriesTooltip/nearby-series.js +2 -2
  62. package/dist/TimeSeriesTooltip/nearby-series.js.map +1 -1
  63. package/dist/TimeSeriesTooltip/tooltip-model.d.ts +10 -14
  64. package/dist/TimeSeriesTooltip/tooltip-model.d.ts.map +1 -1
  65. package/dist/TimeSeriesTooltip/tooltip-model.js +2 -1
  66. package/dist/TimeSeriesTooltip/tooltip-model.js.map +1 -1
  67. package/dist/TimeSeriesTooltip/utils.js +2 -2
  68. package/dist/TimeSeriesTooltip/utils.js.map +1 -1
  69. package/dist/cjs/ContentWithLegend/ContentWithLegend.js +70 -0
  70. package/dist/cjs/ContentWithLegend/index.js +28 -0
  71. package/dist/cjs/ContentWithLegend/model/content-with-legend-model.js +100 -0
  72. package/dist/cjs/EChart/EChart.js +9 -1
  73. package/dist/cjs/Legend/Legend.js +30 -15
  74. package/dist/cjs/Legend/ListLegend.js +2 -23
  75. package/dist/cjs/Legend/TableLegend.js +67 -0
  76. package/dist/cjs/LegendOptionsEditor/LegendOptionsEditor.js +34 -2
  77. package/dist/cjs/LineChart/LineChart.js +60 -22
  78. package/dist/cjs/StatChart/StatChart.js +8 -1
  79. package/dist/cjs/Table/InnerTable.js +1 -1
  80. package/dist/cjs/Table/TableCell.js +1 -1
  81. package/dist/cjs/Table/TableRow.js +2 -2
  82. package/dist/cjs/TimeSeriesTooltip/TimeSeriesTooltip.js +34 -91
  83. package/dist/cjs/TimeSeriesTooltip/TooltipContent.js +19 -100
  84. package/dist/cjs/TimeSeriesTooltip/TooltipHeader.js +174 -0
  85. package/dist/cjs/TimeSeriesTooltip/index.js +1 -0
  86. package/dist/cjs/TimeSeriesTooltip/nearby-series.js +2 -2
  87. package/dist/cjs/TimeSeriesTooltip/tooltip-model.js +3 -1
  88. package/dist/cjs/TimeSeriesTooltip/utils.js +2 -2
  89. package/dist/cjs/index.js +1 -0
  90. package/dist/cjs/model/legend.js +30 -1
  91. package/dist/cjs/theme/component-overrides/paper.js +27 -0
  92. package/dist/cjs/theme/palette/background.js +2 -2
  93. package/dist/cjs/theme/theme.js +2 -0
  94. package/dist/index.d.ts +1 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +1 -0
  97. package/dist/index.js.map +1 -1
  98. package/dist/model/legend.d.ts +9 -3
  99. package/dist/model/legend.d.ts.map +1 -1
  100. package/dist/model/legend.js +26 -1
  101. package/dist/model/legend.js.map +1 -1
  102. package/dist/theme/component-overrides/paper.d.ts +3 -0
  103. package/dist/theme/component-overrides/paper.d.ts.map +1 -0
  104. package/dist/theme/component-overrides/paper.js +21 -0
  105. package/dist/theme/component-overrides/paper.js.map +1 -0
  106. package/dist/theme/palette/background.js +2 -2
  107. package/dist/theme/palette/background.js.map +1 -1
  108. package/dist/theme/theme.d.ts.map +1 -1
  109. package/dist/theme/theme.js +2 -0
  110. package/dist/theme/theme.js.map +1 -1
  111. package/package.json +4 -7
@@ -0,0 +1,100 @@
1
+ // Copyright 2023 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
+ TABLE_LEGEND_SIZE: ()=>TABLE_LEGEND_SIZE,
25
+ getContentWithLegendLayout: ()=>getContentWithLegendLayout
26
+ });
27
+ const _table = require("../../Table");
28
+ const _legend = require("../../model/legend");
29
+ const TABLE_LEGEND_SIZE = {
30
+ // 5 rows plus header. Value to be multiplied by row height in pixels.
31
+ Bottom: 6,
32
+ // Pixel value
33
+ Right: 250
34
+ };
35
+ const PANEL_HEIGHT_LG_BREAKPOINT = 300;
36
+ const LEGEND_HEIGHT_SM = 40;
37
+ const LEGEND_HEIGHT_LG = 100;
38
+ function getContentWithLegendLayout({ width , height , legendOptions , minChildrenHeight , minChildrenWidth , spacing , theme }) {
39
+ const hasLegend = !!legendOptions;
40
+ const noLegendLayout = {
41
+ legend: {
42
+ show: false,
43
+ width: 0,
44
+ height: 0
45
+ },
46
+ content: {
47
+ width,
48
+ height
49
+ },
50
+ margin: {
51
+ right: 0,
52
+ bottom: 0
53
+ }
54
+ };
55
+ if (!hasLegend) {
56
+ return noLegendLayout;
57
+ }
58
+ const { position } = legendOptions;
59
+ const mode = (0, _legend.getLegendMode)(legendOptions.mode);
60
+ let legendWidth;
61
+ let legendHeight;
62
+ if (mode === 'List') {
63
+ // TODO: normalize list to share similar height options as the table
64
+ // when we add more size options.
65
+ legendWidth = position === 'Right' ? 200 : width;
66
+ // TODO: account for number of legend items returned when adjusting legend spacing
67
+ legendHeight = LEGEND_HEIGHT_SM;
68
+ if (position === 'Right') {
69
+ legendHeight = height;
70
+ } else if (height >= PANEL_HEIGHT_LG_BREAKPOINT) {
71
+ legendHeight = LEGEND_HEIGHT_LG;
72
+ }
73
+ } else {
74
+ // Table mode
75
+ const tableLayout = (0, _table.getTableCellLayout)(theme, 'compact');
76
+ legendWidth = position === 'Right' ? TABLE_LEGEND_SIZE['Right'] : width;
77
+ legendHeight = position === 'Bottom' ? TABLE_LEGEND_SIZE['Bottom'] * tableLayout.height : height;
78
+ }
79
+ const contentWidth = position === 'Right' ? width - legendWidth - spacing : width;
80
+ const contentHeight = position === 'Bottom' ? height - legendHeight - spacing : height;
81
+ if (position === 'Right' && contentWidth < minChildrenWidth || position === 'Bottom' && contentHeight < minChildrenHeight) {
82
+ // Legend does not fit. Just show the content.
83
+ return noLegendLayout;
84
+ }
85
+ return {
86
+ legend: {
87
+ width: legendWidth,
88
+ height: legendHeight,
89
+ show: true
90
+ },
91
+ content: {
92
+ width: contentWidth,
93
+ height: contentHeight
94
+ },
95
+ margin: {
96
+ right: position === 'Right' ? spacing : 0,
97
+ bottom: position === 'Bottom' ? spacing : 0
98
+ }
99
+ };
100
+ }
@@ -142,11 +142,19 @@ const EChart = /*#__PURE__*/ _react.default.memo(function EChart({ option , them
142
142
  }, [
143
143
  onEvents
144
144
  ]);
145
+ // TODO: re-evaluate how this is triggered. It's technically working right
146
+ // now because the sx prop is an object that gets re-created, but that also
147
+ // means it runs unnecessarily some of the time and theoretically might
148
+ // not run in some other cases. Maybe it should use a resize observer?
145
149
  (0, _react.useEffect)(()=>{
150
+ // TODO: fix this debouncing. This likely isn't working as intended because
151
+ // the debounced function is re-created every time this useEffect is called.
146
152
  const updateSize = (0, _lodashEs.debounce)(()=>{
147
153
  if (!chartElement.current) return;
148
154
  chartElement.current.resize();
149
- }, 200);
155
+ }, 200, {
156
+ leading: true
157
+ });
150
158
  updateSize();
151
159
  }, [
152
160
  sx
@@ -21,8 +21,10 @@ Object.defineProperty(exports, "Legend", {
21
21
  const _jsxRuntime = require("react/jsx-runtime");
22
22
  const _material = require("@mui/material");
23
23
  const _immer = require("immer");
24
+ const _model = require("../model");
24
25
  const _listLegend = require("./ListLegend");
25
26
  const _compactLegend = require("./CompactLegend");
27
+ const _tableLegend = require("./TableLegend");
26
28
  // When the number of items to display is above this number, it is likely to
27
29
  // cause performance issues in the browser. The legend will be displayed in a
28
30
  // format (list) that allows for virtualization to minimize the performance impact.
@@ -62,12 +64,37 @@ function Legend({ width , height , options , data , selectedItems , onSelectedIt
62
64
  });
63
65
  onSelectedItemsChange(newSelected);
64
66
  };
67
+ const mode = (0, _model.getLegendMode)(options.mode);
68
+ // The bottom legend is displayed as a list when the number of items is too
69
+ // large and requires virtualization. Otherwise, it is rendered more compactly.
70
+ // We do not need this check for the right-side legend because it is always
71
+ // a virtualized list.
72
+ const needsVirtualization = data.length >= NEED_VIRTUALIZATION_LIMIT;
65
73
  const commonLegendProps = {
66
74
  height,
67
75
  items: data,
68
76
  selectedItems,
69
77
  onLegendItemClick
70
78
  };
79
+ let legendContent;
80
+ if (mode === 'Table') {
81
+ legendContent = /*#__PURE__*/ (0, _jsxRuntime.jsx)(_tableLegend.TableLegend, {
82
+ ...commonLegendProps,
83
+ onSelectedItemsChange: onSelectedItemsChange,
84
+ width: width
85
+ });
86
+ } else if (options.position === 'Right' || needsVirtualization) {
87
+ legendContent = /*#__PURE__*/ (0, _jsxRuntime.jsx)(_listLegend.ListLegend, {
88
+ ...commonLegendProps,
89
+ width: width,
90
+ onLegendItemClick: onLegendItemClick
91
+ });
92
+ } else {
93
+ legendContent = /*#__PURE__*/ (0, _jsxRuntime.jsx)(_compactLegend.CompactLegend, {
94
+ ...commonLegendProps,
95
+ onLegendItemClick: onLegendItemClick
96
+ });
97
+ }
71
98
  if (options.position === 'Right') {
72
99
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Box, {
73
100
  sx: {
@@ -77,17 +104,10 @@ function Legend({ width , height , options , data , selectedItems , onSelectedIt
77
104
  top: 0,
78
105
  right: 0
79
106
  },
80
- children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_listLegend.ListLegend, {
81
- ...commonLegendProps,
82
- width: width
83
- })
107
+ children: legendContent
84
108
  });
85
109
  }
86
- // The bottom legend is displayed as a list when the number of items is too
87
- // large and requires virtualization. Otherwise, it is rendered more compactly.
88
- // We do not need this check for the right-side legend because it is always
89
- // a virtualized list.
90
- const needsVirtualization = data.length >= NEED_VIRTUALIZATION_LIMIT;
110
+ // Position bottom
91
111
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Box, {
92
112
  sx: {
93
113
  width: width,
@@ -95,11 +115,6 @@ function Legend({ width , height , options , data , selectedItems , onSelectedIt
95
115
  position: 'absolute',
96
116
  bottom: 0
97
117
  },
98
- children: needsVirtualization ? /*#__PURE__*/ (0, _jsxRuntime.jsx)(_listLegend.ListLegend, {
99
- ...commonLegendProps,
100
- width: width
101
- }) : /*#__PURE__*/ (0, _jsxRuntime.jsx)(_compactLegend.CompactLegend, {
102
- ...commonLegendProps
103
- })
118
+ children: legendContent
104
119
  });
105
120
  }
@@ -19,23 +19,10 @@ Object.defineProperty(exports, "ListLegend", {
19
19
  get: ()=>ListLegend
20
20
  });
21
21
  const _jsxRuntime = require("react/jsx-runtime");
22
- const _material = require("@mui/material");
23
22
  const _reactVirtuoso = require("react-virtuoso");
24
23
  const _model = require("../model");
25
24
  const _listLegendItem = require("./ListLegendItem");
26
25
  function ListLegend({ items , height , width , selectedItems , onLegendItemClick }) {
27
- const theme = (0, _material.useTheme)();
28
- // Padding value used in the react virtuoso header/footer components to
29
- // simulate top/bottom padding based on recommendation in this
30
- // issue.
31
- // https://github.com/petyosi/react-virtuoso/issues/238
32
- const LIST_PADDING = parseInt(theme.spacing(1), 10);
33
- const mockPadding = /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Box, {
34
- sx: {
35
- width: '100%',
36
- height: `${LIST_PADDING}px`
37
- }
38
- });
39
26
  // show full labels on hover when there are many total series
40
27
  const truncateLabels = items.length > 5;
41
28
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_reactVirtuoso.Virtuoso, {
@@ -53,20 +40,12 @@ function ListLegend({ items , height , width , selectedItems , onLegendItemClick
53
40
  sx: {
54
41
  // Having an explicit width is important for the ellipsizing to
55
42
  // work correctly. Subtract padding to simulate padding.
56
- width: width - LIST_PADDING,
43
+ width: width,
57
44
  wordBreak: 'break-word',
58
45
  overflow: 'hidden'
59
46
  }
60
47
  }, item.id);
61
48
  },
62
- role: "list",
63
- components: {
64
- Header: ()=>{
65
- return mockPadding;
66
- },
67
- Footer: ()=>{
68
- return mockPadding;
69
- }
70
- }
49
+ role: "list"
71
50
  });
72
51
  }
@@ -0,0 +1,67 @@
1
+ // Copyright 2023 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
+ Object.defineProperty(exports, "TableLegend", {
18
+ enumerable: true,
19
+ get: ()=>TableLegend
20
+ });
21
+ const _jsxRuntime = require("react/jsx-runtime");
22
+ const _react = require("react");
23
+ const _table = require("../Table");
24
+ const COLUMNS = [
25
+ {
26
+ accessorKey: 'label',
27
+ header: 'Name',
28
+ // Starting with `title` attr instead of a tooltip because it is easier to
29
+ // implement. We should try adding a tooltip in the future, but we'll need
30
+ // to be very careful about performance when doing so with large tables.
31
+ cell: ({ getValue })=>/*#__PURE__*/ (0, _jsxRuntime.jsx)("span", {
32
+ title: getValue(),
33
+ children: getValue()
34
+ })
35
+ }
36
+ ];
37
+ const getRowId = (data)=>{
38
+ return data.id;
39
+ };
40
+ const getCheckboxColor = (data)=>{
41
+ return data.color;
42
+ };
43
+ function TableLegend({ items , selectedItems: initRowSelection , onSelectedItemsChange , height , width }) {
44
+ const rowSelection = (0, _react.useMemo)(()=>{
45
+ return typeof initRowSelection !== 'string' ? initRowSelection : // items for checkboxes.
46
+ // TODO: clean this up if we switch to also using checkboxes in list legend.
47
+ items.reduce((allRowSelection, item, index)=>{
48
+ allRowSelection[getRowId(item, index)] = true;
49
+ return allRowSelection;
50
+ }, {});
51
+ }, [
52
+ initRowSelection,
53
+ items
54
+ ]);
55
+ return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_table.Table, {
56
+ height: height,
57
+ width: width,
58
+ rowSelection: rowSelection,
59
+ onRowSelectionChange: onSelectedItemsChange,
60
+ data: items,
61
+ columns: COLUMNS,
62
+ density: "compact",
63
+ getRowId: getRowId,
64
+ getCheckboxColor: getCheckboxColor,
65
+ checkboxSelection: true
66
+ });
67
+ }
@@ -29,6 +29,12 @@ const POSITION_OPTIONS = Object.entries(_model.LEGEND_POSITIONS_CONFIG).map(([id
29
29
  ...config
30
30
  };
31
31
  });
32
+ const MODE_OPTIONS = Object.entries(_model.LEGEND_MODE_CONFIG).map(([id, config])=>{
33
+ return {
34
+ id: id,
35
+ ...config
36
+ };
37
+ });
32
38
  function LegendOptionsEditor({ value , onChange }) {
33
39
  const handleLegendShowChange = (_, checked)=>{
34
40
  // legend is hidden when legend obj is undefined
@@ -43,9 +49,18 @@ function LegendOptionsEditor({ value , onChange }) {
43
49
  position: newValue.id
44
50
  });
45
51
  };
52
+ const handleLegendModeChange = (_, newValue)=>{
53
+ onChange({
54
+ ...value,
55
+ position: currentPosition,
56
+ mode: newValue.id
57
+ });
58
+ };
46
59
  const isValidLegend = (0, _model.validateLegendSpec)(value);
47
60
  const currentPosition = (0, _model.getLegendPosition)(value === null || value === void 0 ? void 0 : value.position);
48
- const legendConfig = _model.LEGEND_POSITIONS_CONFIG[currentPosition];
61
+ const legendPositionConfig = _model.LEGEND_POSITIONS_CONFIG[currentPosition];
62
+ const currentMode = (0, _model.getLegendMode)(value === null || value === void 0 ? void 0 : value.mode);
63
+ const legendModeConfig = _model.LEGEND_MODE_CONFIG[currentMode];
49
64
  return /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
50
65
  children: [
51
66
  !isValidLegend && /*#__PURE__*/ (0, _jsxRuntime.jsx)(_errorAlert.ErrorAlert, {
@@ -65,7 +80,7 @@ function LegendOptionsEditor({ value , onChange }) {
65
80
  label: "Position",
66
81
  control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Autocomplete, {
67
82
  value: {
68
- ...legendConfig,
83
+ ...legendPositionConfig,
69
84
  id: currentPosition
70
85
  },
71
86
  options: POSITION_OPTIONS,
@@ -77,6 +92,23 @@ function LegendOptionsEditor({ value , onChange }) {
77
92
  disabled: value === undefined,
78
93
  disableClearable: true
79
94
  })
95
+ }),
96
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_optionsEditorLayout.OptionsEditorControl, {
97
+ label: "Mode",
98
+ control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Autocomplete, {
99
+ value: {
100
+ ...legendModeConfig,
101
+ id: currentMode
102
+ },
103
+ options: MODE_OPTIONS,
104
+ isOptionEqualToValue: (option, value)=>option.id === value.id,
105
+ renderInput: (params)=>/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.TextField, {
106
+ ...params
107
+ }),
108
+ onChange: handleLegendModeChange,
109
+ disabled: value === undefined,
110
+ disableClearable: true
111
+ })
80
112
  })
81
113
  ]
82
114
  });
@@ -89,15 +89,17 @@ function LineChart({ height , data , yAxis , unit , grid , legend , tooltipConfi
89
89
  const chartsTheme = (0, _chartsThemeProvider.useChartsTheme)();
90
90
  const chartRef = (0, _react.useRef)();
91
91
  const [showTooltip, setShowTooltip] = (0, _react.useState)(true);
92
- const [isTooltipPinned, setIsTooltipPinned] = (0, _react.useState)(false);
92
+ const [tooltipPinnedCoords, setTooltipPinnedCoords] = (0, _react.useState)(null);
93
93
  const { timeZone } = (0, _timeZoneProvider.useTimeZone)();
94
+ const [isDragging, setIsDragging] = (0, _react.useState)(false);
95
+ const [startX, setStartX] = (0, _react.useState)(0);
94
96
  const handleEvents = (0, _react.useMemo)(()=>{
95
97
  return {
96
98
  datazoom: (params)=>{
97
99
  if (onDataZoom === undefined) {
98
100
  setTimeout(()=>{
99
101
  // workaround so unpin happens after click event
100
- setIsTooltipPinned(false);
102
+ setTooltipPinnedCoords(null);
101
103
  }, 10);
102
104
  }
103
105
  if (onDataZoom === undefined || params.batch[0] === undefined) return;
@@ -121,22 +123,11 @@ function LineChart({ height , data , yAxis , unit , grid , legend , tooltipConfi
121
123
  }, [
122
124
  data,
123
125
  onDataZoom,
124
- setIsTooltipPinned
126
+ setTooltipPinnedCoords
125
127
  ]);
126
128
  if (chartRef.current !== undefined) {
127
129
  (0, _utils.enableDataZoom)(chartRef.current);
128
130
  }
129
- const handleOnDoubleClick = (e)=>{
130
- setIsTooltipPinned(false);
131
- // either dispatch ECharts restore action to return to orig state or allow consumer to define behavior
132
- if (onDoubleClick === undefined) {
133
- if (chartRef.current !== undefined) {
134
- (0, _utils.restoreChart)(chartRef.current);
135
- }
136
- } else {
137
- onDoubleClick(e);
138
- }
139
- };
140
131
  const { noDataOption } = chartsTheme;
141
132
  const option = (0, _react.useMemo)(()=>{
142
133
  if (data.timeSeries === undefined) return {};
@@ -205,20 +196,57 @@ function LineChart({ height , data , yAxis , unit , grid , legend , tooltipConfi
205
196
  onClick: (e)=>{
206
197
  // Pin and unpin when clicking on chart canvas but not tooltip text.
207
198
  if (e.target instanceof HTMLCanvasElement) {
208
- setIsTooltipPinned((current)=>!current);
199
+ setTooltipPinnedCoords((current)=>{
200
+ if (current === null) {
201
+ return {
202
+ page: {
203
+ x: e.pageX,
204
+ y: e.pageY
205
+ },
206
+ client: {
207
+ x: e.clientX,
208
+ y: e.clientY
209
+ },
210
+ plotCanvas: {
211
+ x: e.nativeEvent.offsetX,
212
+ y: e.nativeEvent.offsetY
213
+ },
214
+ target: e.target
215
+ };
216
+ } else {
217
+ return null;
218
+ }
219
+ });
209
220
  }
210
221
  },
211
222
  onMouseDown: (e)=>{
212
- // Hide tooltip when user drags to zoom, but allow clicking inside tooltip to copy labels.
213
- if (e.target instanceof HTMLCanvasElement) {
214
- setShowTooltip(false);
223
+ const { clientX } = e;
224
+ setIsDragging(true);
225
+ setStartX(clientX);
226
+ },
227
+ onMouseMove: (e)=>{
228
+ // Allow clicking inside tooltip to copy labels.
229
+ if (!(e.target instanceof HTMLCanvasElement)) {
230
+ return;
231
+ }
232
+ const { clientX } = e;
233
+ if (isDragging) {
234
+ const deltaX = clientX - startX;
235
+ if (deltaX > 0) {
236
+ // Hide tooltip when user drags to zoom.
237
+ setShowTooltip(false);
238
+ }
215
239
  }
216
240
  },
217
241
  onMouseUp: ()=>{
242
+ setIsDragging(false);
243
+ setStartX(0);
218
244
  setShowTooltip(true);
219
245
  },
220
246
  onMouseLeave: ()=>{
221
- setShowTooltip(false);
247
+ if (tooltipPinnedCoords === null) {
248
+ setShowTooltip(false);
249
+ }
222
250
  },
223
251
  onMouseEnter: ()=>{
224
252
  setShowTooltip(true);
@@ -226,16 +254,26 @@ function LineChart({ height , data , yAxis , unit , grid , legend , tooltipConfi
226
254
  (0, _utils.enableDataZoom)(chartRef.current);
227
255
  }
228
256
  },
229
- onDoubleClick: handleOnDoubleClick,
257
+ onDoubleClick: (e)=>{
258
+ setTooltipPinnedCoords(null);
259
+ // either dispatch ECharts restore action to return to orig state or allow consumer to define behavior
260
+ if (onDoubleClick === undefined) {
261
+ if (chartRef.current !== undefined) {
262
+ (0, _utils.restoreChart)(chartRef.current);
263
+ }
264
+ } else {
265
+ onDoubleClick(e);
266
+ }
267
+ },
230
268
  children: [
231
269
  showTooltip === true && ((ref = option.tooltip) === null || ref === void 0 ? void 0 : ref.showContent) === false && tooltipConfig.hidden !== true && /*#__PURE__*/ (0, _jsxRuntime.jsx)(_timeSeriesTooltip.TimeSeriesTooltip, {
232
270
  chartRef: chartRef,
233
271
  chartData: data,
234
272
  wrapLabels: tooltipConfig.wrapLabels,
235
- isTooltipPinned: isTooltipPinned,
273
+ pinnedPos: tooltipPinnedCoords,
236
274
  unit: unit,
237
275
  onUnpinClick: ()=>{
238
- setIsTooltipPinned(false);
276
+ setTooltipPinnedCoords(null);
239
277
  }
240
278
  }),
241
279
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_echart.EChart, {
@@ -80,7 +80,14 @@ function StatChart(props) {
80
80
  },
81
81
  yAxis: {
82
82
  type: 'value',
83
- show: false
83
+ show: false,
84
+ min: (value)=>{
85
+ if (value.min >= 0 && value.min <= 1) {
86
+ // helps with PercentDecimal units, or datasets that return 0 or 1 booleans
87
+ return 0;
88
+ }
89
+ return value.min;
90
+ }
84
91
  },
85
92
  tooltip: {
86
93
  show: false
@@ -25,7 +25,7 @@ const StyledMuiTable = (0, _material.styled)(_material.Table)(({ theme })=>({
25
25
  // This value is needed to have a consistent table layout when scrolling.
26
26
  tableLayout: 'fixed',
27
27
  borderCollapse: 'separate',
28
- backgroundColor: theme.palette.background.paper
28
+ backgroundColor: theme.palette.background.default
29
29
  }));
30
30
  const TABLE_DENSITY_CONFIG = {
31
31
  compact: 'small',
@@ -27,7 +27,7 @@ const StyledMuiTableCell = (0, _material.styled)(_material.TableCell)(({ theme
27
27
  backgroundColor: 'inherit',
28
28
  '&.MuiTableCell-head': {
29
29
  // Important to avoid scrolling behind the header showing through.
30
- backgroundColor: theme.palette.background.paper
30
+ backgroundColor: theme.palette.background.default
31
31
  },
32
32
  '&:focus-visible': {
33
33
  outline: `solid 1px ${theme.palette.primary.main}`,
@@ -26,9 +26,9 @@ const TableRow = /*#__PURE__*/ (0, _react.forwardRef)(function TableRow(props, r
26
26
  ...props,
27
27
  ref: ref,
28
28
  sx: {
29
- backgroundColor: (theme)=>theme.palette.background.paper,
29
+ backgroundColor: (theme)=>theme.palette.background.default,
30
30
  '&:hover': {
31
- backgroundColor: (theme)=>theme.palette.primary.light
31
+ backgroundColor: (theme)=>(0, _material.alpha)(theme.palette.primary.main, theme.palette.action.hoverOpacity)
32
32
  }
33
33
  }
34
34
  });