@perses-dev/timeseries-chart-plugin 0.10.1 → 0.10.2

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 (62) hide show
  1. package/__mf/js/{TimeSeriesChart.2f8b193b.js → TimeSeriesChart.2e93229a.js} +5 -6
  2. package/__mf/js/async/109.f05e61af.js +73 -0
  3. package/__mf/js/async/{964.719c530c.js → 110.8b9c7f4b.js} +2 -2
  4. package/__mf/js/async/186.b17dcce5.js +1 -0
  5. package/__mf/js/async/{547.bb4f1e58.js → 547.a80ef962.js} +2 -2
  6. package/__mf/js/async/964.e89cbd3b.js +110 -0
  7. package/__mf/js/async/{580.5f4b0dbd.js → 971.6fcf317e.js} +3 -3
  8. package/__mf/js/async/__federation_expose_TimeSeriesChart.f017c9e5.js +3 -0
  9. package/__mf/js/{main.42f3cc3e.js → main.25080a30.js} +5 -6
  10. package/lib/GeneralSettingsEditor.d.ts +4 -0
  11. package/lib/GeneralSettingsEditor.d.ts.map +1 -0
  12. package/lib/{TimeSeriesChartOptionsEditorSettings.js → GeneralSettingsEditor.js} +3 -14
  13. package/lib/GeneralSettingsEditor.js.map +1 -0
  14. package/lib/QuerySettingsEditor.d.ts +3 -17
  15. package/lib/QuerySettingsEditor.d.ts.map +1 -1
  16. package/lib/QuerySettingsEditor.js +370 -88
  17. package/lib/QuerySettingsEditor.js.map +1 -1
  18. package/lib/TimeSeriesChart.d.ts.map +1 -1
  19. package/lib/TimeSeriesChart.js +8 -3
  20. package/lib/TimeSeriesChart.js.map +1 -1
  21. package/lib/TimeSeriesChartPanel.js +1 -1
  22. package/lib/TimeSeriesChartPanel.js.map +1 -1
  23. package/lib/VisualOptionsEditor.d.ts.map +1 -1
  24. package/lib/VisualOptionsEditor.js +84 -64
  25. package/lib/VisualOptionsEditor.js.map +1 -1
  26. package/lib/cjs/{TimeSeriesChartOptionsEditorSettings.js → GeneralSettingsEditor.js} +4 -15
  27. package/lib/cjs/QuerySettingsEditor.js +410 -95
  28. package/lib/cjs/TimeSeriesChart.js +8 -3
  29. package/lib/cjs/TimeSeriesChartPanel.js +1 -1
  30. package/lib/cjs/VisualOptionsEditor.js +82 -62
  31. package/lib/cjs/index.js +1 -1
  32. package/lib/cjs/time-series-chart-model.js +37 -0
  33. package/lib/cjs/utils/data-transform.js +7 -5
  34. package/lib/cjs/utils/palette-gen.js +2 -2
  35. package/lib/index.d.ts +1 -1
  36. package/lib/index.d.ts.map +1 -1
  37. package/lib/index.js +1 -1
  38. package/lib/index.js.map +1 -1
  39. package/lib/time-series-chart-model.d.ts +32 -2
  40. package/lib/time-series-chart-model.d.ts.map +1 -1
  41. package/lib/time-series-chart-model.js +25 -0
  42. package/lib/time-series-chart-model.js.map +1 -1
  43. package/lib/utils/data-transform.d.ts +5 -2
  44. package/lib/utils/data-transform.d.ts.map +1 -1
  45. package/lib/utils/data-transform.js +7 -5
  46. package/lib/utils/data-transform.js.map +1 -1
  47. package/lib/utils/palette-gen.js +2 -2
  48. package/lib/utils/palette-gen.js.map +1 -1
  49. package/mf-manifest.json +13 -13
  50. package/mf-stats.json +13 -13
  51. package/package.json +5 -5
  52. package/__mf/js/async/109.604f6c41.js +0 -73
  53. package/__mf/js/async/133.c48c8cc8.js +0 -110
  54. package/__mf/js/async/686.0cd9a75c.js +0 -1
  55. package/__mf/js/async/__federation_expose_TimeSeriesChart.f20a0aca.js +0 -3
  56. package/lib/TimeSeriesChartOptionsEditorSettings.d.ts +0 -4
  57. package/lib/TimeSeriesChartOptionsEditorSettings.d.ts.map +0 -1
  58. package/lib/TimeSeriesChartOptionsEditorSettings.js.map +0 -1
  59. /package/__mf/js/async/{109.604f6c41.js.LICENSE.txt → 109.f05e61af.js.LICENSE.txt} +0 -0
  60. /package/__mf/js/async/{964.719c530c.js.LICENSE.txt → 110.8b9c7f4b.js.LICENSE.txt} +0 -0
  61. /package/__mf/js/async/{547.bb4f1e58.js.LICENSE.txt → 547.a80ef962.js.LICENSE.txt} +0 -0
  62. /package/__mf/js/async/{133.c48c8cc8.js.LICENSE.txt → 964.e89cbd3b.js.LICENSE.txt} +0 -0
@@ -18,8 +18,7 @@ import { LegendOptionsEditor } from '@perses-dev/plugin-system';
18
18
  import { DEFAULT_VISUAL, DEFAULT_Y_AXIS } from './time-series-chart-model';
19
19
  import { VisualOptionsEditor } from './VisualOptionsEditor';
20
20
  import { YAxisOptionsEditor } from './YAxisOptionsEditor';
21
- import { QuerySettingsEditor } from './QuerySettingsEditor';
22
- export function TimeSeriesChartOptionsEditorSettings(props) {
21
+ export function TimeSeriesChartGeneralSettings(props) {
23
22
  const { onChange, value } = props;
24
23
  const handleLegendChange = (newLegend)=>{
25
24
  // TODO (sjcobb): fix type, add position, fix glitch
@@ -37,11 +36,6 @@ export function TimeSeriesChartOptionsEditorSettings(props) {
37
36
  draft.yAxis = newYAxis;
38
37
  }));
39
38
  };
40
- const handleQuerySettingsChange = (newQuerySettings)=>{
41
- onChange(produce(value, (draft)=>{
42
- draft.querySettings = newQuerySettings;
43
- }));
44
- };
45
39
  const handleThresholdsChange = (thresholds)=>{
46
40
  onChange(produce(value, (draft)=>{
47
41
  draft.thresholds = thresholds;
@@ -75,10 +69,6 @@ export function TimeSeriesChartOptionsEditorSettings(props) {
75
69
  thresholds: value.thresholds,
76
70
  onChange: handleThresholdsChange
77
71
  }),
78
- /*#__PURE__*/ _jsx(QuerySettingsEditor, {
79
- querySettingsList: value.querySettings,
80
- onChange: handleQuerySettingsChange
81
- }),
82
72
  /*#__PURE__*/ _jsx(OptionsEditorGroup, {
83
73
  title: "Reset Settings",
84
74
  children: /*#__PURE__*/ _jsx(Button, {
@@ -86,12 +76,11 @@ export function TimeSeriesChartOptionsEditorSettings(props) {
86
76
  color: "secondary",
87
77
  onClick: ()=>{
88
78
  onChange(produce(value, (draft)=>{
89
- // reset button removes all optional panel options
79
+ // reset button removes all general panel options
90
80
  draft.yAxis = undefined;
91
81
  draft.legend = undefined;
92
82
  draft.visual = undefined;
93
83
  draft.thresholds = undefined;
94
- draft.querySettings = undefined;
95
84
  }));
96
85
  },
97
86
  children: "Reset To Defaults"
@@ -103,4 +92,4 @@ export function TimeSeriesChartOptionsEditorSettings(props) {
103
92
  });
104
93
  }
105
94
 
106
- //# sourceMappingURL=TimeSeriesChartOptionsEditorSettings.js.map
95
+ //# sourceMappingURL=GeneralSettingsEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/GeneralSettingsEditor.tsx"],"sourcesContent":["// Copyright 2023 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 { Button } from '@mui/material';\nimport { produce } from 'immer';\nimport {\n OptionsEditorGroup,\n OptionsEditorGrid,\n OptionsEditorColumn,\n ThresholdsEditor,\n ThresholdsEditorProps,\n} from '@perses-dev/components';\nimport { LegendOptionsEditor, LegendOptionsEditorProps } from '@perses-dev/plugin-system';\nimport { ReactElement } from 'react';\nimport {\n TimeSeriesChartOptions,\n DEFAULT_VISUAL,\n DEFAULT_Y_AXIS,\n TimeSeriesChartOptionsEditorProps,\n} from './time-series-chart-model';\nimport { VisualOptionsEditor, VisualOptionsEditorProps } from './VisualOptionsEditor';\nimport { YAxisOptionsEditor, YAxisOptionsEditorProps } from './YAxisOptionsEditor';\n\nexport function TimeSeriesChartGeneralSettings(props: TimeSeriesChartOptionsEditorProps): ReactElement {\n const { onChange, value } = props;\n\n const handleLegendChange: LegendOptionsEditorProps['onChange'] = (newLegend) => {\n // TODO (sjcobb): fix type, add position, fix glitch\n onChange(\n produce(value, (draft: TimeSeriesChartOptions) => {\n draft.legend = newLegend;\n })\n );\n };\n\n const handleVisualChange: VisualOptionsEditorProps['onChange'] = (newVisual) => {\n onChange(\n produce(value, (draft: TimeSeriesChartOptions) => {\n draft.visual = newVisual;\n })\n );\n };\n\n const handleYAxisChange: YAxisOptionsEditorProps['onChange'] = (newYAxis) => {\n onChange(\n produce(value, (draft: TimeSeriesChartOptions) => {\n draft.yAxis = newYAxis;\n })\n );\n };\n\n const handleThresholdsChange: ThresholdsEditorProps['onChange'] = (thresholds) => {\n onChange(\n produce(value, (draft: TimeSeriesChartOptions) => {\n draft.thresholds = thresholds;\n })\n );\n };\n\n return (\n <OptionsEditorGrid>\n <OptionsEditorColumn>\n <LegendOptionsEditor calculation=\"aggregation\" value={value.legend} onChange={handleLegendChange} />\n <VisualOptionsEditor value={value.visual ?? DEFAULT_VISUAL} onChange={handleVisualChange} />\n </OptionsEditorColumn>\n <OptionsEditorColumn>\n <YAxisOptionsEditor value={value.yAxis ?? DEFAULT_Y_AXIS} onChange={handleYAxisChange} />\n </OptionsEditorColumn>\n <OptionsEditorColumn>\n <ThresholdsEditor hideDefault thresholds={value.thresholds} onChange={handleThresholdsChange} />\n <OptionsEditorGroup title=\"Reset Settings\">\n <Button\n variant=\"outlined\"\n color=\"secondary\"\n onClick={() => {\n onChange(\n produce(value, (draft: TimeSeriesChartOptions) => {\n // reset button removes all general panel options\n draft.yAxis = undefined;\n draft.legend = undefined;\n draft.visual = undefined;\n draft.thresholds = undefined;\n })\n );\n }}\n >\n Reset To Defaults\n </Button>\n </OptionsEditorGroup>\n </OptionsEditorColumn>\n </OptionsEditorGrid>\n );\n}\n"],"names":["Button","produce","OptionsEditorGroup","OptionsEditorGrid","OptionsEditorColumn","ThresholdsEditor","LegendOptionsEditor","DEFAULT_VISUAL","DEFAULT_Y_AXIS","VisualOptionsEditor","YAxisOptionsEditor","TimeSeriesChartGeneralSettings","props","onChange","value","handleLegendChange","newLegend","draft","legend","handleVisualChange","newVisual","visual","handleYAxisChange","newYAxis","yAxis","handleThresholdsChange","thresholds","calculation","hideDefault","title","variant","color","onClick","undefined"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,MAAM,QAAQ,gBAAgB;AACvC,SAASC,OAAO,QAAQ,QAAQ;AAChC,SACEC,kBAAkB,EAClBC,iBAAiB,EACjBC,mBAAmB,EACnBC,gBAAgB,QAEX,yBAAyB;AAChC,SAASC,mBAAmB,QAAkC,4BAA4B;AAE1F,SAEEC,cAAc,EACdC,cAAc,QAET,4BAA4B;AACnC,SAASC,mBAAmB,QAAkC,wBAAwB;AACtF,SAASC,kBAAkB,QAAiC,uBAAuB;AAEnF,OAAO,SAASC,+BAA+BC,KAAwC;IACrF,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAE,GAAGF;IAE5B,MAAMG,qBAA2D,CAACC;QAChE,oDAAoD;QACpDH,SACEZ,QAAQa,OAAO,CAACG;YACdA,MAAMC,MAAM,GAAGF;QACjB;IAEJ;IAEA,MAAMG,qBAA2D,CAACC;QAChEP,SACEZ,QAAQa,OAAO,CAACG;YACdA,MAAMI,MAAM,GAAGD;QACjB;IAEJ;IAEA,MAAME,oBAAyD,CAACC;QAC9DV,SACEZ,QAAQa,OAAO,CAACG;YACdA,MAAMO,KAAK,GAAGD;QAChB;IAEJ;IAEA,MAAME,yBAA4D,CAACC;QACjEb,SACEZ,QAAQa,OAAO,CAACG;YACdA,MAAMS,UAAU,GAAGA;QACrB;IAEJ;IAEA,qBACE,MAACvB;;0BACC,MAACC;;kCACC,KAACE;wBAAoBqB,aAAY;wBAAcb,OAAOA,MAAMI,MAAM;wBAAEL,UAAUE;;kCAC9E,KAACN;wBAAoBK,OAAOA,MAAMO,MAAM,IAAId;wBAAgBM,UAAUM;;;;0BAExE,KAACf;0BACC,cAAA,KAACM;oBAAmBI,OAAOA,MAAMU,KAAK,IAAIhB;oBAAgBK,UAAUS;;;0BAEtE,MAAClB;;kCACC,KAACC;wBAAiBuB,WAAW;wBAACF,YAAYZ,MAAMY,UAAU;wBAAEb,UAAUY;;kCACtE,KAACvB;wBAAmB2B,OAAM;kCACxB,cAAA,KAAC7B;4BACC8B,SAAQ;4BACRC,OAAM;4BACNC,SAAS;gCACPnB,SACEZ,QAAQa,OAAO,CAACG;oCACd,iDAAiD;oCACjDA,MAAMO,KAAK,GAAGS;oCACdhB,MAAMC,MAAM,GAAGe;oCACfhB,MAAMI,MAAM,GAAGY;oCACfhB,MAAMS,UAAU,GAAGO;gCACrB;4BAEJ;sCACD;;;;;;;AAOX"}
@@ -1,18 +1,4 @@
1
- import { ReactElement, RefObject } from 'react';
2
- import { QuerySettingsOptions } from './time-series-chart-model';
3
- export interface QuerySettingsEditorProps {
4
- querySettingsList?: QuerySettingsOptions[];
5
- onChange: (querySettingsList: QuerySettingsOptions[]) => void;
6
- }
7
- export declare function QuerySettingsEditor({ querySettingsList, onChange }: QuerySettingsEditorProps): ReactElement;
8
- export interface QuerySettingsInputProps {
9
- querySettings: QuerySettingsOptions;
10
- availableQueryIndexes: number[];
11
- onQueryIndexChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
12
- onColorModeChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
13
- onColorValueChange: (colorValue: string) => void;
14
- onDelete: () => void;
15
- inputRef?: RefObject<HTMLInputElement | null>;
16
- }
17
- export declare function QuerySettingsInput({ querySettings: { queryIndex, colorMode, colorValue }, availableQueryIndexes, onQueryIndexChange, onColorModeChange, onColorValueChange, onDelete, inputRef, }: QuerySettingsInputProps): ReactElement;
1
+ import { ReactElement } from 'react';
2
+ import { TimeSeriesChartOptionsEditorProps } from './time-series-chart-model';
3
+ export declare function QuerySettingsEditor(props: TimeSeriesChartOptionsEditorProps): ReactElement;
18
4
  //# sourceMappingURL=QuerySettingsEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"QuerySettingsEditor.d.ts","sourceRoot":"","sources":["../../src/QuerySettingsEditor.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAE,YAAY,EAAE,SAAS,EAA8B,MAAM,OAAO,CAAC;AAK5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAMjE,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAC3C,QAAQ,EAAE,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,KAAK,IAAI,CAAC;CAC/D;AAED,wBAAgB,mBAAmB,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,EAAE,wBAAwB,GAAG,YAAY,CAoI3G;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,oBAAoB,CAAC;IACpC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,kBAAkB,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACrE,iBAAiB,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACpE,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAC/C;AAED,wBAAgB,kBAAkB,CAAC,EACjC,aAAa,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,EACpD,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,QAAQ,GACT,EAAE,uBAAuB,GAAG,YAAY,CA8BxC"}
1
+ {"version":3,"file":"QuerySettingsEditor.d.ts","sourceRoot":"","sources":["../../src/QuerySettingsEditor.tsx"],"names":[],"mappings":"AA4BA,OAAc,EAAE,YAAY,EAAwC,MAAM,OAAO,CAAC;AAMlF,OAAO,EAEL,iCAAiC,EAKlC,MAAM,2BAA2B,CAAC;AAKnC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iCAAiC,GAAG,YAAY,CAwO1F"}
@@ -10,18 +10,26 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
- import { IconButton, MenuItem, Stack, TextField, Typography } from '@mui/material';
15
- import { InfoTooltip, OptionsEditorGroup, OptionsColorPicker } from '@perses-dev/components';
16
- import { useEffect, useMemo, useRef } from 'react';
13
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
+ import { Box, Button, IconButton, Menu, MenuItem, Slider, Stack, TextField, ToggleButton, ToggleButtonGroup, Typography, useTheme } from '@mui/material';
15
+ import { OptionsColorPicker } from '@perses-dev/components';
16
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
17
17
  import DeleteIcon from 'mdi-material-ui/DeleteOutline';
18
- import PlusIcon from 'mdi-material-ui/Plus';
18
+ import AddIcon from 'mdi-material-ui/Plus';
19
+ import CloseIcon from 'mdi-material-ui/Close';
19
20
  import { produce } from 'immer';
20
21
  import { useQueryCountContext } from '@perses-dev/plugin-system';
21
- const DEFAULT_COLOR_MODE = 'fixed';
22
+ import { DEFAULT_AREA_OPACITY, OPACITY_CONFIG, LINE_STYLE_CONFIG } from './time-series-chart-model';
22
23
  const DEFAULT_COLOR_VALUE = '#555';
23
24
  const NO_INDEX_AVAILABLE = -1; // invalid array index value used to represent the fact that no query index is available
24
- export function QuerySettingsEditor({ querySettingsList, onChange }) {
25
+ export function QuerySettingsEditor(props) {
26
+ const { onChange, value } = props;
27
+ const querySettingsList = value.querySettings;
28
+ const handleQuerySettingsChange = (newQuerySettings)=>{
29
+ onChange(produce(value, (draft)=>{
30
+ draft.querySettings = newQuerySettings;
31
+ }));
32
+ };
25
33
  // Every time a new query settings input is added, we want to focus the recently added input
26
34
  const recentlyAddedInputRef = useRef(null);
27
35
  const focusRef = useRef(false);
@@ -34,7 +42,7 @@ export function QuerySettingsEditor({ querySettingsList, onChange }) {
34
42
  ]);
35
43
  const handleQueryIndexChange = (e, i)=>{
36
44
  if (querySettingsList !== undefined) {
37
- onChange(produce(querySettingsList, (draft)=>{
45
+ handleQuerySettingsChange(produce(querySettingsList, (draft)=>{
38
46
  const querySettings = draft?.[i];
39
47
  if (querySettings) {
40
48
  querySettings.queryIndex = parseInt(e.target.value);
@@ -44,11 +52,17 @@ export function QuerySettingsEditor({ querySettingsList, onChange }) {
44
52
  };
45
53
  const handleColorModeChange = (e, i)=>{
46
54
  if (querySettingsList !== undefined) {
47
- onChange(produce(querySettingsList, (draft)=>{
55
+ handleQuerySettingsChange(produce(querySettingsList, (draft)=>{
48
56
  if (draft !== undefined) {
49
57
  const querySettings = draft[i];
50
58
  if (querySettings) {
51
- querySettings.colorMode = e.target.value;
59
+ const newColorMode = e.target.value;
60
+ if (!newColorMode) {
61
+ querySettings.colorMode = undefined;
62
+ querySettings.colorValue = undefined;
63
+ } else {
64
+ querySettings.colorMode = newColorMode;
65
+ }
52
66
  }
53
67
  }
54
68
  }));
@@ -56,7 +70,7 @@ export function QuerySettingsEditor({ querySettingsList, onChange }) {
56
70
  };
57
71
  const handleColorValueChange = (colorValue, i)=>{
58
72
  if (querySettingsList !== undefined) {
59
- onChange(produce(querySettingsList, (draft)=>{
73
+ handleQuerySettingsChange(produce(querySettingsList, (draft)=>{
60
74
  if (draft !== undefined) {
61
75
  const querySettings = draft[i];
62
76
  if (querySettings) {
@@ -66,14 +80,82 @@ export function QuerySettingsEditor({ querySettingsList, onChange }) {
66
80
  }));
67
81
  }
68
82
  };
83
+ const handleLineStyleChange = (lineStyle, i)=>{
84
+ if (querySettingsList !== undefined) {
85
+ handleQuerySettingsChange(produce(querySettingsList, (draft)=>{
86
+ if (draft !== undefined) {
87
+ const querySettings = draft[i];
88
+ if (querySettings) {
89
+ querySettings.lineStyle = lineStyle;
90
+ }
91
+ }
92
+ }));
93
+ }
94
+ };
95
+ const handleAreaOpacityChange = (_, sliderValue, i)=>{
96
+ const newValue = Array.isArray(sliderValue) ? sliderValue[0] : sliderValue;
97
+ if (querySettingsList !== undefined) {
98
+ handleQuerySettingsChange(produce(querySettingsList, (draft)=>{
99
+ if (draft !== undefined) {
100
+ const querySettings = draft[i];
101
+ if (querySettings) {
102
+ querySettings.areaOpacity = newValue;
103
+ }
104
+ }
105
+ }));
106
+ }
107
+ };
108
+ // Helper function to update query settings at a specific index
109
+ const updateQuerySettings = (i, updater)=>{
110
+ if (querySettingsList !== undefined) {
111
+ handleQuerySettingsChange(produce(querySettingsList, (draft)=>{
112
+ const qs = draft[i];
113
+ if (qs) {
114
+ updater(qs);
115
+ }
116
+ }));
117
+ }
118
+ };
69
119
  const deleteQuerySettingsInput = (i)=>{
70
120
  if (querySettingsList !== undefined) {
71
121
  const updatedQuerySettingsList = produce(querySettingsList, (draft)=>{
72
122
  draft.splice(i, 1);
73
123
  });
74
- onChange(updatedQuerySettingsList);
124
+ handleQuerySettingsChange(updatedQuerySettingsList);
75
125
  }
76
126
  };
127
+ const addColor = (i)=>{
128
+ updateQuerySettings(i, (qs)=>{
129
+ qs.colorMode = 'fixed-single';
130
+ qs.colorValue = DEFAULT_COLOR_VALUE;
131
+ });
132
+ };
133
+ const removeColor = (i)=>{
134
+ updateQuerySettings(i, (qs)=>{
135
+ qs.colorMode = undefined;
136
+ qs.colorValue = undefined;
137
+ });
138
+ };
139
+ const addLineStyle = (i)=>{
140
+ updateQuerySettings(i, (qs)=>{
141
+ qs.lineStyle = 'solid';
142
+ });
143
+ };
144
+ const removeLineStyle = (i)=>{
145
+ updateQuerySettings(i, (qs)=>{
146
+ qs.lineStyle = undefined;
147
+ });
148
+ };
149
+ const addAreaOpacity = (i)=>{
150
+ updateQuerySettings(i, (qs)=>{
151
+ qs.areaOpacity = DEFAULT_AREA_OPACITY;
152
+ });
153
+ };
154
+ const removeAreaOpacity = (i)=>{
155
+ updateQuerySettings(i, (qs)=>{
156
+ qs.areaOpacity = undefined;
157
+ });
158
+ };
77
159
  const queryCount = useQueryCountContext();
78
160
  // Compute the list of query indexes for which query settings are not already defined.
79
161
  // This is to avoid already-booked indexes to still be selectable in the dropdown(s)
@@ -93,106 +175,306 @@ export function QuerySettingsEditor({ querySettingsList, onChange }) {
93
175
  availableQueryIndexes
94
176
  ]);
95
177
  const defaultQuerySettings = {
96
- queryIndex: firstAvailableQueryIndex,
97
- colorMode: DEFAULT_COLOR_MODE,
98
- colorValue: DEFAULT_COLOR_VALUE
178
+ queryIndex: firstAvailableQueryIndex
99
179
  };
100
180
  const addQuerySettingsInput = ()=>{
101
181
  focusRef.current = true;
102
182
  if (querySettingsList === undefined) {
103
- onChange([
183
+ handleQuerySettingsChange([
104
184
  defaultQuerySettings
105
185
  ]);
106
186
  } else {
107
- onChange(produce(querySettingsList, (draft)=>{
187
+ handleQuerySettingsChange(produce(querySettingsList, (draft)=>{
108
188
  draft.push(defaultQuerySettings);
109
189
  }));
110
190
  }
111
191
  };
112
- return /*#__PURE__*/ _jsx(OptionsEditorGroup, {
113
- title: "Query settings",
114
- icon: firstAvailableQueryIndex !== NO_INDEX_AVAILABLE ? /*#__PURE__*/ _jsx(InfoTooltip, {
115
- description: "Add query settings",
116
- children: /*#__PURE__*/ _jsx(IconButton, {
117
- size: "small",
118
- "aria-label": "add query settings",
192
+ return /*#__PURE__*/ _jsxs(Stack, {
193
+ children: [
194
+ queryCount === 0 ? /*#__PURE__*/ _jsx(Typography, {
195
+ mb: 2,
196
+ fontStyle: "italic",
197
+ children: "No query defined"
198
+ }) : querySettingsList?.length && querySettingsList.map((querySettings, i)=>/*#__PURE__*/ _jsx(QuerySettingsInput, {
199
+ inputRef: i === querySettingsList.length - 1 ? recentlyAddedInputRef : undefined,
200
+ querySettings: querySettings,
201
+ availableQueryIndexes: availableQueryIndexes,
202
+ onQueryIndexChange: (e)=>{
203
+ handleQueryIndexChange(e, i);
204
+ },
205
+ onColorModeChange: (e)=>handleColorModeChange(e, i),
206
+ onColorValueChange: (color)=>handleColorValueChange(color, i),
207
+ onLineStyleChange: (lineStyle)=>handleLineStyleChange(lineStyle, i),
208
+ onAreaOpacityChange: (event, value)=>handleAreaOpacityChange(event, value, i),
209
+ onDelete: ()=>{
210
+ deleteQuerySettingsInput(i);
211
+ },
212
+ onAddColor: ()=>addColor(i),
213
+ onRemoveColor: ()=>removeColor(i),
214
+ onAddLineStyle: ()=>addLineStyle(i),
215
+ onRemoveLineStyle: ()=>removeLineStyle(i),
216
+ onAddAreaOpacity: ()=>addAreaOpacity(i),
217
+ onRemoveAreaOpacity: ()=>removeAreaOpacity(i)
218
+ }, i)),
219
+ queryCount > 0 && firstAvailableQueryIndex !== NO_INDEX_AVAILABLE && /*#__PURE__*/ _jsx(Button, {
220
+ variant: "contained",
221
+ startIcon: /*#__PURE__*/ _jsx(AddIcon, {}),
222
+ sx: {
223
+ marginTop: 1
224
+ },
119
225
  onClick: addQuerySettingsInput,
120
- children: /*#__PURE__*/ _jsx(PlusIcon, {})
226
+ children: "Add Query Settings"
121
227
  })
122
- }) : null,
123
- children: querySettingsList && querySettingsList.length > 0 ? querySettingsList.map((querySettings, i)=>/*#__PURE__*/ _jsx(QuerySettingsInput, {
124
- inputRef: i === querySettingsList.length - 1 ? recentlyAddedInputRef : undefined,
125
- querySettings: querySettings,
126
- availableQueryIndexes: availableQueryIndexes,
127
- onQueryIndexChange: (e)=>{
128
- handleQueryIndexChange(e, i);
129
- },
130
- onColorModeChange: (e)=>handleColorModeChange(e, i),
131
- onColorValueChange: (color)=>handleColorValueChange(color, i),
132
- onDelete: ()=>{
133
- deleteQuerySettingsInput(i);
134
- }
135
- }, i)) : /*#__PURE__*/ _jsx(Typography, {
136
- mb: 2,
137
- fontStyle: "italic",
138
- children: "No query settings defined"
139
- })
228
+ ]
140
229
  });
141
230
  }
142
- export function QuerySettingsInput({ querySettings: { queryIndex, colorMode, colorValue }, availableQueryIndexes, onQueryIndexChange, onColorModeChange, onColorValueChange, onDelete, inputRef }) {
231
+ function QuerySettingsInput({ querySettings: { queryIndex, colorMode, colorValue, lineStyle, areaOpacity }, availableQueryIndexes, onQueryIndexChange, onColorModeChange, onColorValueChange, onLineStyleChange, onAreaOpacityChange, onDelete, inputRef, onAddColor: onAddColor, onRemoveColor: onRemoveColor, onAddLineStyle, onRemoveLineStyle, onAddAreaOpacity, onRemoveAreaOpacity }) {
143
232
  // current query index should also be selectable
144
233
  const selectableQueryIndexes = availableQueryIndexes.concat(queryIndex).sort((a, b)=>a - b);
145
- return /*#__PURE__*/ _jsxs(Stack, {
146
- flex: 1,
147
- direction: "row",
148
- alignItems: "center",
149
- justifyContent: "space-between",
150
- spacing: 1,
234
+ // State for dropdown menu
235
+ const [anchorEl, setAnchorEl] = useState(null);
236
+ // Calculate available options
237
+ const availableOptions = useMemo(()=>{
238
+ const options = [];
239
+ if (!colorMode) options.push({
240
+ key: 'color',
241
+ label: 'Color',
242
+ action: onAddColor
243
+ });
244
+ if (!lineStyle) options.push({
245
+ key: 'lineStyle',
246
+ label: 'Line Style',
247
+ action: onAddLineStyle
248
+ });
249
+ if (areaOpacity === undefined) options.push({
250
+ key: 'opacity',
251
+ label: 'Opacity',
252
+ action: onAddAreaOpacity
253
+ });
254
+ return options;
255
+ }, [
256
+ colorMode,
257
+ lineStyle,
258
+ areaOpacity,
259
+ onAddColor,
260
+ onAddLineStyle,
261
+ onAddAreaOpacity
262
+ ]);
263
+ const handleAddMenuClick = (event)=>{
264
+ if (availableOptions.length === 1 && availableOptions[0]) {
265
+ // If only one option left, add it directly
266
+ availableOptions[0].action();
267
+ } else {
268
+ // Show dropdown
269
+ setAnchorEl(event.currentTarget);
270
+ }
271
+ };
272
+ const handleMenuClose = ()=>{
273
+ setAnchorEl(null);
274
+ };
275
+ const handleMenuItemClick = (action)=>{
276
+ action();
277
+ handleMenuClose();
278
+ };
279
+ return /*#__PURE__*/ _jsx(Stack, {
280
+ spacing: 2,
281
+ sx: {
282
+ borderBottom: '1px solid',
283
+ borderColor: 'divider',
284
+ borderRadius: 1,
285
+ p: 2
286
+ },
287
+ children: /*#__PURE__*/ _jsxs(Stack, {
288
+ direction: "row",
289
+ alignItems: "center",
290
+ spacing: 1,
291
+ sx: {
292
+ flexWrap: 'wrap',
293
+ gap: 1
294
+ },
295
+ children: [
296
+ /*#__PURE__*/ _jsx(TextField, {
297
+ select: true,
298
+ inputRef: inputRef,
299
+ value: queryIndex,
300
+ label: "Query",
301
+ onChange: onQueryIndexChange,
302
+ sx: {
303
+ minWidth: '75px'
304
+ },
305
+ children: selectableQueryIndexes.map((qi)=>/*#__PURE__*/ _jsxs(MenuItem, {
306
+ value: qi,
307
+ children: [
308
+ "#",
309
+ qi + 1
310
+ ]
311
+ }, `query-${qi}`))
312
+ }),
313
+ colorMode && /*#__PURE__*/ _jsxs(SettingsSection, {
314
+ label: "Color",
315
+ onRemove: onRemoveColor,
316
+ children: [
317
+ /*#__PURE__*/ _jsxs(TextField, {
318
+ select: true,
319
+ value: colorMode,
320
+ onChange: onColorModeChange,
321
+ size: "small",
322
+ sx: {
323
+ flexGrow: 1
324
+ },
325
+ children: [
326
+ /*#__PURE__*/ _jsx(MenuItem, {
327
+ value: "fixed-single",
328
+ children: "Fixed (single)"
329
+ }),
330
+ /*#__PURE__*/ _jsx(MenuItem, {
331
+ value: "fixed",
332
+ children: "Fixed"
333
+ })
334
+ ]
335
+ }),
336
+ /*#__PURE__*/ _jsx(OptionsColorPicker, {
337
+ label: `Query n°${queryIndex + 1}`,
338
+ color: colorValue || DEFAULT_COLOR_VALUE,
339
+ onColorChange: onColorValueChange
340
+ })
341
+ ]
342
+ }),
343
+ lineStyle && /*#__PURE__*/ _jsxs(SettingsSection, {
344
+ label: "Line Style",
345
+ onRemove: onRemoveLineStyle,
346
+ children: [
347
+ /*#__PURE__*/ _jsx(ToggleButtonGroup, {
348
+ color: "primary",
349
+ exclusive: true,
350
+ value: lineStyle,
351
+ onChange: (__, newValue)=>{
352
+ if (newValue !== null) {
353
+ onLineStyleChange(newValue);
354
+ }
355
+ },
356
+ size: "small",
357
+ children: Object.entries(LINE_STYLE_CONFIG).map(([styleValue, config])=>/*#__PURE__*/ _jsx(ToggleButton, {
358
+ value: styleValue,
359
+ "aria-label": `${styleValue} line style`,
360
+ children: config.label
361
+ }, styleValue))
362
+ }),
363
+ /*#__PURE__*/ _jsx(Box, {
364
+ sx: {
365
+ flexGrow: 1
366
+ }
367
+ })
368
+ ]
369
+ }),
370
+ areaOpacity !== undefined && /*#__PURE__*/ _jsxs(SettingsSection, {
371
+ label: "Opacity",
372
+ onRemove: onRemoveAreaOpacity,
373
+ children: [
374
+ /*#__PURE__*/ _jsx(Box, {}),
375
+ /*#__PURE__*/ _jsx(Slider, {
376
+ value: areaOpacity,
377
+ valueLabelDisplay: "auto",
378
+ step: OPACITY_CONFIG.step,
379
+ marks: true,
380
+ min: OPACITY_CONFIG.min,
381
+ max: OPACITY_CONFIG.max,
382
+ onChange: onAreaOpacityChange,
383
+ sx: {
384
+ flexGrow: 1
385
+ }
386
+ })
387
+ ]
388
+ }),
389
+ availableOptions.length > 0 && /*#__PURE__*/ _jsxs(_Fragment, {
390
+ children: [
391
+ /*#__PURE__*/ _jsx(IconButton, {
392
+ onClick: handleAddMenuClick,
393
+ "aria-label": "Add option",
394
+ children: /*#__PURE__*/ _jsx(AddIcon, {})
395
+ }),
396
+ /*#__PURE__*/ _jsx(Menu, {
397
+ anchorEl: anchorEl,
398
+ open: Boolean(anchorEl),
399
+ onClose: handleMenuClose,
400
+ anchorOrigin: {
401
+ vertical: 'bottom',
402
+ horizontal: 'left'
403
+ },
404
+ children: availableOptions.map((option)=>/*#__PURE__*/ _jsxs(MenuItem, {
405
+ onClick: ()=>handleMenuItemClick(option.action),
406
+ sx: {
407
+ minWidth: '120px'
408
+ },
409
+ children: [
410
+ /*#__PURE__*/ _jsx(AddIcon, {
411
+ sx: {
412
+ mr: 1,
413
+ fontSize: '1rem'
414
+ }
415
+ }),
416
+ option.label
417
+ ]
418
+ }, option.key))
419
+ })
420
+ ]
421
+ }),
422
+ /*#__PURE__*/ _jsx(Box, {
423
+ sx: {
424
+ flexGrow: 1
425
+ }
426
+ }),
427
+ /*#__PURE__*/ _jsx(IconButton, {
428
+ "aria-label": `delete settings for query n°${queryIndex + 1}`,
429
+ onClick: onDelete,
430
+ children: /*#__PURE__*/ _jsx(DeleteIcon, {})
431
+ })
432
+ ]
433
+ })
434
+ });
435
+ }
436
+ // Reusable section component
437
+ function SettingsSection(props) {
438
+ const { label, children, onRemove } = props;
439
+ const theme = useTheme();
440
+ return /*#__PURE__*/ _jsxs(Box, {
441
+ sx: {
442
+ position: 'relative',
443
+ minWidth: '250px'
444
+ },
151
445
  children: [
152
- /*#__PURE__*/ _jsx(TextField, {
153
- select: true,
154
- inputRef: inputRef,
155
- value: queryIndex,
156
- label: "Query",
157
- onChange: onQueryIndexChange,
446
+ /*#__PURE__*/ _jsx(Typography, {
447
+ variant: "caption",
158
448
  sx: {
159
- minWidth: '75px'
449
+ position: 'absolute',
450
+ top: -8,
451
+ left: 12,
452
+ backgroundColor: theme.palette.background.code,
453
+ px: 0.5,
454
+ color: 'text.secondary',
455
+ zIndex: 1
160
456
  },
161
- children: selectableQueryIndexes.map((queryIndex)=>/*#__PURE__*/ _jsxs(MenuItem, {
162
- value: queryIndex,
163
- children: [
164
- "#",
165
- queryIndex + 1
166
- ]
167
- }, `query-${queryIndex}`))
457
+ children: label
168
458
  }),
169
- /*#__PURE__*/ _jsxs(TextField, {
170
- select: true,
171
- value: colorMode,
172
- fullWidth: true,
173
- label: "Color mode",
174
- onChange: onColorModeChange,
459
+ /*#__PURE__*/ _jsxs(Stack, {
460
+ direction: "row",
461
+ alignItems: "center",
462
+ spacing: 1,
463
+ sx: {
464
+ border: '1px solid',
465
+ borderColor: 'divider',
466
+ borderRadius: 1,
467
+ p: 1
468
+ },
175
469
  children: [
176
- /*#__PURE__*/ _jsx(MenuItem, {
177
- value: "fixed-single",
178
- children: "Fixed (single)"
179
- }),
180
- /*#__PURE__*/ _jsx(MenuItem, {
181
- value: "fixed",
182
- children: "Fixed"
470
+ children,
471
+ /*#__PURE__*/ _jsx(IconButton, {
472
+ size: "small",
473
+ onClick: onRemove,
474
+ "aria-label": `Remove ${label}`,
475
+ children: /*#__PURE__*/ _jsx(CloseIcon, {})
183
476
  })
184
477
  ]
185
- }),
186
- /*#__PURE__*/ _jsx(OptionsColorPicker, {
187
- label: 'Query n°' + queryIndex,
188
- color: colorValue,
189
- onColorChange: onColorValueChange
190
- }),
191
- /*#__PURE__*/ _jsx(IconButton, {
192
- "aria-label": `delete settings for query n°${queryIndex + 1}`,
193
- size: "small",
194
- onClick: onDelete,
195
- children: /*#__PURE__*/ _jsx(DeleteIcon, {})
196
478
  })
197
479
  ]
198
480
  });