@perses-dev/dashboards 0.52.0-rc.1 → 0.53.0-beta.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 (98) hide show
  1. package/dist/cjs/components/DashboardStickyToolbar/DashboardStickyToolbar.js +0 -2
  2. package/dist/cjs/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +5 -20
  3. package/dist/cjs/components/GridLayout/GridItemContent.js +6 -64
  4. package/dist/cjs/components/LeaveDialog/LeaveDialog.js +10 -1
  5. package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +186 -183
  6. package/dist/cjs/components/PanelDrawer/PanelPreview.js +3 -0
  7. package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.js +6 -21
  8. package/dist/cjs/components/QueryViewerDialog/QueryViewerDialog.js +121 -0
  9. package/dist/cjs/components/QueryViewerDialog/index.js +30 -0
  10. package/dist/cjs/components/Variables/ListVariableListBox.js +201 -0
  11. package/dist/cjs/components/Variables/Variable.js +130 -72
  12. package/dist/cjs/components/Variables/index.js +1 -0
  13. package/dist/cjs/components/index.js +2 -1
  14. package/dist/cjs/context/DashboardProvider/DashboardProviderWithQueryParams.js +5 -27
  15. package/dist/cjs/context/DashboardProvider/duplicate-panel-slice.js +1 -1
  16. package/dist/cjs/context/DashboardProvider/panel-editor-slice.js +1 -2
  17. package/dist/cjs/context/PanelEditorProvider/PanelEditorProvider.js +49 -0
  18. package/dist/cjs/context/PanelEditorProvider/index.js +23 -0
  19. package/dist/cjs/context/VariableProvider/query-params.js +14 -12
  20. package/dist/cjs/context/index.js +1 -0
  21. package/dist/cjs/test/render.js +8 -6
  22. package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.d.ts.map +1 -1
  23. package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.js +0 -2
  24. package/dist/components/DashboardStickyToolbar/DashboardStickyToolbar.js.map +1 -1
  25. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.d.ts.map +1 -1
  26. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +5 -15
  27. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js.map +1 -1
  28. package/dist/components/GridLayout/GridItemContent.d.ts.map +1 -1
  29. package/dist/components/GridLayout/GridItemContent.js +8 -66
  30. package/dist/components/GridLayout/GridItemContent.js.map +1 -1
  31. package/dist/components/LeaveDialog/LeaveDialog.d.ts +2 -1
  32. package/dist/components/LeaveDialog/LeaveDialog.d.ts.map +1 -1
  33. package/dist/components/LeaveDialog/LeaveDialog.js +10 -1
  34. package/dist/components/LeaveDialog/LeaveDialog.js.map +1 -1
  35. package/dist/components/PanelDrawer/PanelEditorForm.d.ts.map +1 -1
  36. package/dist/components/PanelDrawer/PanelEditorForm.js +186 -183
  37. package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
  38. package/dist/components/PanelDrawer/PanelPreview.d.ts.map +1 -1
  39. package/dist/components/PanelDrawer/PanelPreview.js +4 -1
  40. package/dist/components/PanelDrawer/PanelPreview.js.map +1 -1
  41. package/dist/components/PanelGroupDialog/PanelGroupDialog.d.ts.map +1 -1
  42. package/dist/components/PanelGroupDialog/PanelGroupDialog.js +5 -15
  43. package/dist/components/PanelGroupDialog/PanelGroupDialog.js.map +1 -1
  44. package/dist/components/QueryViewerDialog/QueryViewerDialog.d.ts +9 -0
  45. package/dist/components/QueryViewerDialog/QueryViewerDialog.d.ts.map +1 -0
  46. package/dist/components/QueryViewerDialog/QueryViewerDialog.js +72 -0
  47. package/dist/components/QueryViewerDialog/QueryViewerDialog.js.map +1 -0
  48. package/dist/components/QueryViewerDialog/index.d.ts +2 -0
  49. package/dist/components/QueryViewerDialog/index.d.ts.map +1 -0
  50. package/dist/components/QueryViewerDialog/index.js +15 -0
  51. package/dist/components/QueryViewerDialog/index.js.map +1 -0
  52. package/dist/components/Variables/ListVariableListBox.d.ts +16 -0
  53. package/dist/components/Variables/ListVariableListBox.d.ts.map +1 -0
  54. package/dist/components/Variables/ListVariableListBox.js +141 -0
  55. package/dist/components/Variables/ListVariableListBox.js.map +1 -0
  56. package/dist/components/Variables/Variable.d.ts.map +1 -1
  57. package/dist/components/Variables/Variable.js +134 -76
  58. package/dist/components/Variables/Variable.js.map +1 -1
  59. package/dist/components/Variables/index.d.ts +1 -0
  60. package/dist/components/Variables/index.d.ts.map +1 -1
  61. package/dist/components/Variables/index.js +1 -0
  62. package/dist/components/Variables/index.js.map +1 -1
  63. package/dist/components/index.d.ts +2 -1
  64. package/dist/components/index.d.ts.map +1 -1
  65. package/dist/components/index.js +2 -1
  66. package/dist/components/index.js.map +1 -1
  67. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.d.ts.map +1 -1
  68. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js +5 -27
  69. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js.map +1 -1
  70. package/dist/context/DashboardProvider/duplicate-panel-slice.js +2 -2
  71. package/dist/context/DashboardProvider/duplicate-panel-slice.js.map +1 -1
  72. package/dist/context/DashboardProvider/panel-editor-slice.d.ts.map +1 -1
  73. package/dist/context/DashboardProvider/panel-editor-slice.js +2 -3
  74. package/dist/context/DashboardProvider/panel-editor-slice.js.map +1 -1
  75. package/dist/context/PanelEditorProvider/PanelEditorProvider.d.ts +13 -0
  76. package/dist/context/PanelEditorProvider/PanelEditorProvider.d.ts.map +1 -0
  77. package/dist/context/PanelEditorProvider/PanelEditorProvider.js +33 -0
  78. package/dist/context/PanelEditorProvider/PanelEditorProvider.js.map +1 -0
  79. package/dist/context/PanelEditorProvider/index.d.ts +3 -0
  80. package/dist/context/PanelEditorProvider/index.d.ts.map +1 -0
  81. package/dist/context/PanelEditorProvider/index.js +16 -0
  82. package/dist/context/PanelEditorProvider/index.js.map +1 -0
  83. package/dist/context/VariableProvider/query-params.d.ts +3 -4
  84. package/dist/context/VariableProvider/query-params.d.ts.map +1 -1
  85. package/dist/context/VariableProvider/query-params.js +14 -9
  86. package/dist/context/VariableProvider/query-params.js.map +1 -1
  87. package/dist/context/index.d.ts +1 -0
  88. package/dist/context/index.d.ts.map +1 -1
  89. package/dist/context/index.js +1 -0
  90. package/dist/context/index.js.map +1 -1
  91. package/dist/test/render.d.ts.map +1 -1
  92. package/dist/test/render.js +8 -6
  93. package/dist/test/render.js.map +1 -1
  94. package/dist/utils/panelUtils.d.ts +3 -0
  95. package/dist/utils/panelUtils.d.ts.map +1 -1
  96. package/dist/utils/panelUtils.js +3 -0
  97. package/dist/utils/panelUtils.js.map +1 -1
  98. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/PanelGroupDialog/PanelGroupDialog.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 { IconButton, Dialog, DialogTitle, DialogContent, DialogActions, Button } from '@mui/material';\nimport CloseIcon from 'mdi-material-ui/Close';\nimport { ReactElement, useState } from 'react';\nimport { useVariableValues } from '@perses-dev/plugin-system';\nimport { usePanelGroupEditor } from '../../context';\nimport { PanelGroupEditorForm, panelGroupEditorFormId, PanelGroupEditorFormProps } from './PanelGroupEditorForm';\n\n/**\n * A dialog for adding or editing a Panel Group. Open and initial state is controlled by the DashboardStore.\n */\nexport function PanelGroupDialog(): ReactElement {\n const panelGroupEditor = usePanelGroupEditor();\n const variables = useVariableValues();\n\n // When the user clicks close, start closing but don't call the store yet to keep values stable during animtation\n const [isClosing, setIsClosing] = useState(false);\n const handleClose = (): void => setIsClosing(true);\n\n // Don't call close on the store until the Dialog has completely transitioned out\n const handleExited = (): void => {\n panelGroupEditor?.close();\n setIsClosing(false);\n };\n\n // Dialog is open if we have a model and we're not transitioning out\n const isOpen = panelGroupEditor !== undefined && isClosing === false;\n\n const handleSubmit: PanelGroupEditorFormProps['onSubmit'] = (values) => {\n // This shouldn't happen since we don't render the submit button until we have a model, but check to make TS happy\n if (panelGroupEditor === undefined) {\n throw new Error('Cannot apply changes');\n }\n panelGroupEditor.applyChanges(values);\n handleClose();\n };\n\n return (\n <Dialog open={isOpen} TransitionProps={{ onExited: handleExited }}>\n {panelGroupEditor !== undefined && (\n <>\n <DialogTitle>{panelGroupEditor.mode} Panel Group</DialogTitle>\n <IconButton\n aria-label=\"Close\"\n onClick={panelGroupEditor.close}\n sx={(theme) => ({\n position: 'absolute',\n top: theme.spacing(0.5),\n right: theme.spacing(0.5),\n })}\n >\n <CloseIcon />\n </IconButton>\n <DialogContent dividers sx={{ width: '500px' }}>\n <PanelGroupEditorForm\n initialValues={panelGroupEditor.initialValues}\n variables={Object.keys(variables)}\n onSubmit={handleSubmit}\n />\n </DialogContent>\n <DialogActions>\n <Button variant=\"contained\" type=\"submit\" form={panelGroupEditorFormId}>\n {panelGroupEditor.mode === 'Edit' ? 'Apply' : 'Add'}\n </Button>\n <Button variant=\"outlined\" color=\"secondary\" onClick={panelGroupEditor.close}>\n Cancel\n </Button>\n </DialogActions>\n </>\n )}\n </Dialog>\n );\n}\n"],"names":["IconButton","Dialog","DialogTitle","DialogContent","DialogActions","Button","CloseIcon","useState","useVariableValues","usePanelGroupEditor","PanelGroupEditorForm","panelGroupEditorFormId","PanelGroupDialog","panelGroupEditor","variables","isClosing","setIsClosing","handleClose","handleExited","close","isOpen","undefined","handleSubmit","values","Error","applyChanges","open","TransitionProps","onExited","mode","aria-label","onClick","sx","theme","position","top","spacing","right","dividers","width","initialValues","Object","keys","onSubmit","variant","type","form","color"],"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,UAAU,EAAEC,MAAM,EAAEC,WAAW,EAAEC,aAAa,EAAEC,aAAa,EAAEC,MAAM,QAAQ,gBAAgB;AACtG,OAAOC,eAAe,wBAAwB;AAC9C,SAAuBC,QAAQ,QAAQ,QAAQ;AAC/C,SAASC,iBAAiB,QAAQ,4BAA4B;AAC9D,SAASC,mBAAmB,QAAQ,gBAAgB;AACpD,SAASC,oBAAoB,EAAEC,sBAAsB,QAAmC,yBAAyB;AAEjH;;CAEC,GACD,OAAO,SAASC;IACd,MAAMC,mBAAmBJ;IACzB,MAAMK,YAAYN;IAElB,iHAAiH;IACjH,MAAM,CAACO,WAAWC,aAAa,GAAGT,SAAS;IAC3C,MAAMU,cAAc,IAAYD,aAAa;IAE7C,iFAAiF;IACjF,MAAME,eAAe;QACnBL,kBAAkBM;QAClBH,aAAa;IACf;IAEA,oEAAoE;IACpE,MAAMI,SAASP,qBAAqBQ,aAAaN,cAAc;IAE/D,MAAMO,eAAsD,CAACC;QAC3D,kHAAkH;QAClH,IAAIV,qBAAqBQ,WAAW;YAClC,MAAM,IAAIG,MAAM;QAClB;QACAX,iBAAiBY,YAAY,CAACF;QAC9BN;IACF;IAEA,qBACE,KAAChB;QAAOyB,MAAMN;QAAQO,iBAAiB;YAAEC,UAAUV;QAAa;kBAC7DL,qBAAqBQ,2BACpB;;8BACE,MAACnB;;wBAAaW,iBAAiBgB,IAAI;wBAAC;;;8BACpC,KAAC7B;oBACC8B,cAAW;oBACXC,SAASlB,iBAAiBM,KAAK;oBAC/Ba,IAAI,CAACC,QAAW,CAAA;4BACdC,UAAU;4BACVC,KAAKF,MAAMG,OAAO,CAAC;4BACnBC,OAAOJ,MAAMG,OAAO,CAAC;wBACvB,CAAA;8BAEA,cAAA,KAAC9B;;8BAEH,KAACH;oBAAcmC,QAAQ;oBAACN,IAAI;wBAAEO,OAAO;oBAAQ;8BAC3C,cAAA,KAAC7B;wBACC8B,eAAe3B,iBAAiB2B,aAAa;wBAC7C1B,WAAW2B,OAAOC,IAAI,CAAC5B;wBACvB6B,UAAUrB;;;8BAGd,MAAClB;;sCACC,KAACC;4BAAOuC,SAAQ;4BAAYC,MAAK;4BAASC,MAAMnC;sCAC7CE,iBAAiBgB,IAAI,KAAK,SAAS,UAAU;;sCAEhD,KAACxB;4BAAOuC,SAAQ;4BAAWG,OAAM;4BAAYhB,SAASlB,iBAAiBM,KAAK;sCAAE;;;;;;;AAQ1F"}
1
+ {"version":3,"sources":["../../../src/components/PanelGroupDialog/PanelGroupDialog.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 { ReactElement, useState } from 'react';\nimport { useVariableValues } from '@perses-dev/plugin-system';\nimport { Dialog } from '@perses-dev/components';\nimport { Button } from '@mui/material';\nimport { usePanelGroupEditor } from '../../context';\nimport { PanelGroupEditorForm, panelGroupEditorFormId, PanelGroupEditorFormProps } from './PanelGroupEditorForm';\n\n/**\n * A dialog for adding or editing a Panel Group. Open and initial state is controlled by the DashboardStore.\n */\nexport function PanelGroupDialog(): ReactElement {\n const panelGroupEditor = usePanelGroupEditor();\n const variables = useVariableValues();\n\n // When the user clicks close, start closing but don't call the store yet to keep values stable during animtation\n const [isClosing, setIsClosing] = useState(false);\n const handleClose = (): void => setIsClosing(true);\n\n // Don't call close on the store until the Dialog has completely transitioned out\n const handleExited = (): void => {\n panelGroupEditor?.close();\n setIsClosing(false);\n };\n\n // Dialog is open if we have a model and we're not transitioning out\n const isOpen = panelGroupEditor !== undefined && isClosing === false;\n\n const handleSubmit: PanelGroupEditorFormProps['onSubmit'] = (values) => {\n // This shouldn't happen since we don't render the submit button until we have a model, but check to make TS happy\n if (panelGroupEditor === undefined) {\n throw new Error('Cannot apply changes');\n }\n panelGroupEditor.applyChanges(values);\n handleClose();\n };\n\n return (\n <Dialog open={isOpen} TransitionProps={{ onExited: handleExited }}>\n {panelGroupEditor !== undefined && (\n <>\n <Dialog.Header>{panelGroupEditor.mode} Panel Group</Dialog.Header>\n <Dialog.Content dividers sx={{ width: '500px' }}>\n <PanelGroupEditorForm\n initialValues={panelGroupEditor.initialValues}\n variables={Object.keys(variables)}\n onSubmit={handleSubmit}\n />\n </Dialog.Content>\n <Dialog.Actions>\n <Button variant=\"contained\" type=\"submit\" form={panelGroupEditorFormId}>\n {panelGroupEditor.mode === 'Edit' ? 'Apply' : 'Add'}\n </Button>\n <Button variant=\"outlined\" color=\"secondary\" onClick={panelGroupEditor.close}>\n Cancel\n </Button>\n </Dialog.Actions>\n </>\n )}\n </Dialog>\n );\n}\n"],"names":["useState","useVariableValues","Dialog","Button","usePanelGroupEditor","PanelGroupEditorForm","panelGroupEditorFormId","PanelGroupDialog","panelGroupEditor","variables","isClosing","setIsClosing","handleClose","handleExited","close","isOpen","undefined","handleSubmit","values","Error","applyChanges","open","TransitionProps","onExited","Header","mode","Content","dividers","sx","width","initialValues","Object","keys","onSubmit","Actions","variant","type","form","color","onClick"],"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,SAAuBA,QAAQ,QAAQ,QAAQ;AAC/C,SAASC,iBAAiB,QAAQ,4BAA4B;AAC9D,SAASC,MAAM,QAAQ,yBAAyB;AAChD,SAASC,MAAM,QAAQ,gBAAgB;AACvC,SAASC,mBAAmB,QAAQ,gBAAgB;AACpD,SAASC,oBAAoB,EAAEC,sBAAsB,QAAmC,yBAAyB;AAEjH;;CAEC,GACD,OAAO,SAASC;IACd,MAAMC,mBAAmBJ;IACzB,MAAMK,YAAYR;IAElB,iHAAiH;IACjH,MAAM,CAACS,WAAWC,aAAa,GAAGX,SAAS;IAC3C,MAAMY,cAAc,IAAYD,aAAa;IAE7C,iFAAiF;IACjF,MAAME,eAAe;QACnBL,kBAAkBM;QAClBH,aAAa;IACf;IAEA,oEAAoE;IACpE,MAAMI,SAASP,qBAAqBQ,aAAaN,cAAc;IAE/D,MAAMO,eAAsD,CAACC;QAC3D,kHAAkH;QAClH,IAAIV,qBAAqBQ,WAAW;YAClC,MAAM,IAAIG,MAAM;QAClB;QACAX,iBAAiBY,YAAY,CAACF;QAC9BN;IACF;IAEA,qBACE,KAACV;QAAOmB,MAAMN;QAAQO,iBAAiB;YAAEC,UAAUV;QAAa;kBAC7DL,qBAAqBQ,2BACpB;;8BACE,MAACd,OAAOsB,MAAM;;wBAAEhB,iBAAiBiB,IAAI;wBAAC;;;8BACtC,KAACvB,OAAOwB,OAAO;oBAACC,QAAQ;oBAACC,IAAI;wBAAEC,OAAO;oBAAQ;8BAC5C,cAAA,KAACxB;wBACCyB,eAAetB,iBAAiBsB,aAAa;wBAC7CrB,WAAWsB,OAAOC,IAAI,CAACvB;wBACvBwB,UAAUhB;;;8BAGd,MAACf,OAAOgC,OAAO;;sCACb,KAAC/B;4BAAOgC,SAAQ;4BAAYC,MAAK;4BAASC,MAAM/B;sCAC7CE,iBAAiBiB,IAAI,KAAK,SAAS,UAAU;;sCAEhD,KAACtB;4BAAOgC,SAAQ;4BAAWG,OAAM;4BAAYC,SAAS/B,iBAAiBM,KAAK;sCAAE;;;;;;;AAQ1F"}
@@ -0,0 +1,9 @@
1
+ import { ReactElement } from 'react';
2
+ import { QueryDefinition } from '@perses-dev/core';
3
+ export interface QueryViewerDialogProps {
4
+ open: boolean;
5
+ queryDefinitions: QueryDefinition[];
6
+ onClose: () => void;
7
+ }
8
+ export declare function QueryViewerDialog({ open, queryDefinitions, onClose }: QueryViewerDialogProps): ReactElement;
9
+ //# sourceMappingURL=QueryViewerDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryViewerDialog.d.ts","sourceRoot":"","sources":["../../../src/components/QueryViewerDialog/QueryViewerDialog.tsx"],"names":[],"mappings":"AAaA,OAAc,EAAE,YAAY,EAAW,MAAM,OAAO,CAAC;AAIrD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,OAAO,CAAC;IACd,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,sBAAsB,GAAG,YAAY,CAmC3G"}
@@ -0,0 +1,72 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ import React, { useMemo } from 'react';
15
+ import { Dialog } from '@perses-dev/components';
16
+ import { Button, Divider } from '@mui/material';
17
+ import { PluginSpecEditor } from '@perses-dev/plugin-system';
18
+ export function QueryViewerDialog({ open, queryDefinitions, onClose }) {
19
+ const queryRows = useMemo(()=>{
20
+ if (!queryDefinitions?.length) return null;
21
+ const queryItems = [];
22
+ queryDefinitions.forEach((query, index)=>{
23
+ if (query?.spec?.plugin?.kind && query?.kind) {
24
+ queryItems.push(/*#__PURE__*/ _jsxs(React.Fragment, {
25
+ children: [
26
+ /*#__PURE__*/ _jsx(PluginSpecEditor, {
27
+ value: query.spec.plugin.spec,
28
+ pluginSelection: {
29
+ kind: query.spec.plugin.kind,
30
+ type: query.kind
31
+ },
32
+ onChange: ()=>{},
33
+ isReadonly: true
34
+ }),
35
+ index < queryDefinitions.length - 1 && /*#__PURE__*/ _jsx(Divider, {
36
+ sx: {
37
+ my: 2
38
+ }
39
+ })
40
+ ]
41
+ }, `query-${index}`));
42
+ }
43
+ });
44
+ return queryItems;
45
+ }, [
46
+ queryDefinitions
47
+ ]);
48
+ return /*#__PURE__*/ _jsxs(Dialog, {
49
+ open: open,
50
+ onClose: onClose,
51
+ maxWidth: "lg",
52
+ fullWidth: true,
53
+ children: [
54
+ /*#__PURE__*/ _jsx(Dialog.Header, {
55
+ children: "Query Viewer"
56
+ }),
57
+ /*#__PURE__*/ _jsx(Dialog.Content, {
58
+ children: queryRows
59
+ }),
60
+ /*#__PURE__*/ _jsx(Dialog.Actions, {
61
+ children: /*#__PURE__*/ _jsx(Button, {
62
+ variant: "outlined",
63
+ color: "secondary",
64
+ onClick: onClose,
65
+ children: "Close"
66
+ })
67
+ })
68
+ ]
69
+ });
70
+ }
71
+
72
+ //# sourceMappingURL=QueryViewerDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/QueryViewerDialog/QueryViewerDialog.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 React, { ReactElement, useMemo } from 'react';\nimport { Dialog } from '@perses-dev/components';\nimport { Button, Divider } from '@mui/material';\nimport { PluginSpecEditor } from '@perses-dev/plugin-system';\nimport { QueryDefinition } from '@perses-dev/core';\n\nexport interface QueryViewerDialogProps {\n open: boolean;\n queryDefinitions: QueryDefinition[];\n onClose: () => void;\n}\n\nexport function QueryViewerDialog({ open, queryDefinitions, onClose }: QueryViewerDialogProps): ReactElement {\n const queryRows = useMemo(() => {\n if (!queryDefinitions?.length) return null;\n\n const queryItems: ReactElement[] = [];\n queryDefinitions.forEach((query, index) => {\n if (query?.spec?.plugin?.kind && query?.kind) {\n queryItems.push(\n <React.Fragment key={`query-${index}`}>\n <PluginSpecEditor\n value={query.spec.plugin.spec}\n pluginSelection={{ kind: query.spec.plugin.kind, type: query.kind }}\n onChange={(): void => {}}\n isReadonly\n />\n {index < queryDefinitions.length - 1 && <Divider sx={{ my: 2 }} />}\n </React.Fragment>\n );\n }\n });\n\n return queryItems;\n }, [queryDefinitions]);\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"lg\" fullWidth={true}>\n <Dialog.Header>Query Viewer</Dialog.Header>\n <Dialog.Content>{queryRows}</Dialog.Content>\n <Dialog.Actions>\n <Button variant=\"outlined\" color=\"secondary\" onClick={onClose}>\n Close\n </Button>\n </Dialog.Actions>\n </Dialog>\n );\n}\n"],"names":["React","useMemo","Dialog","Button","Divider","PluginSpecEditor","QueryViewerDialog","open","queryDefinitions","onClose","queryRows","length","queryItems","forEach","query","index","spec","plugin","kind","push","Fragment","value","pluginSelection","type","onChange","isReadonly","sx","my","maxWidth","fullWidth","Header","Content","Actions","variant","color","onClick"],"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,OAAOA,SAAuBC,OAAO,QAAQ,QAAQ;AACrD,SAASC,MAAM,QAAQ,yBAAyB;AAChD,SAASC,MAAM,EAAEC,OAAO,QAAQ,gBAAgB;AAChD,SAASC,gBAAgB,QAAQ,4BAA4B;AAS7D,OAAO,SAASC,kBAAkB,EAAEC,IAAI,EAAEC,gBAAgB,EAAEC,OAAO,EAA0B;IAC3F,MAAMC,YAAYT,QAAQ;QACxB,IAAI,CAACO,kBAAkBG,QAAQ,OAAO;QAEtC,MAAMC,aAA6B,EAAE;QACrCJ,iBAAiBK,OAAO,CAAC,CAACC,OAAOC;YAC/B,IAAID,OAAOE,MAAMC,QAAQC,QAAQJ,OAAOI,MAAM;gBAC5CN,WAAWO,IAAI,eACb,MAACnB,MAAMoB,QAAQ;;sCACb,KAACf;4BACCgB,OAAOP,MAAME,IAAI,CAACC,MAAM,CAACD,IAAI;4BAC7BM,iBAAiB;gCAAEJ,MAAMJ,MAAME,IAAI,CAACC,MAAM,CAACC,IAAI;gCAAEK,MAAMT,MAAMI,IAAI;4BAAC;4BAClEM,UAAU,KAAa;4BACvBC,UAAU;;wBAEXV,QAAQP,iBAAiBG,MAAM,GAAG,mBAAK,KAACP;4BAAQsB,IAAI;gCAAEC,IAAI;4BAAE;;;mBAP1C,CAAC,MAAM,EAAEZ,OAAO;YAUzC;QACF;QAEA,OAAOH;IACT,GAAG;QAACJ;KAAiB;IAErB,qBACE,MAACN;QAAOK,MAAMA;QAAME,SAASA;QAASmB,UAAS;QAAKC,WAAW;;0BAC7D,KAAC3B,OAAO4B,MAAM;0BAAC;;0BACf,KAAC5B,OAAO6B,OAAO;0BAAErB;;0BACjB,KAACR,OAAO8B,OAAO;0BACb,cAAA,KAAC7B;oBAAO8B,SAAQ;oBAAWC,OAAM;oBAAYC,SAAS1B;8BAAS;;;;;AAMvE"}
@@ -0,0 +1,2 @@
1
+ export * from './QueryViewerDialog';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/QueryViewerDialog/index.ts"],"names":[],"mappings":"AAaA,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,15 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ export * from './QueryViewerDialog';
14
+
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/QueryViewerDialog/index.ts"],"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\nexport * from './QueryViewerDialog';\n"],"names":[],"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,cAAc,sBAAsB"}
@@ -0,0 +1,16 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { VariableOption } from '@perses-dev/plugin-system';
3
+ export interface ListVariableListBoxContextValue {
4
+ options: VariableOption[];
5
+ selectedOptions: VariableOption[];
6
+ filteredOptions: VariableOption[];
7
+ allowAllValue: boolean;
8
+ onChange: (selectedOptions: VariableOption[]) => void;
9
+ }
10
+ export declare function useListVariableListBoxContext(): ListVariableListBoxContextValue;
11
+ export declare function ListVariableListBoxProvider({ value, children, }: {
12
+ value: ListVariableListBoxContextValue;
13
+ children: ReactNode;
14
+ }): React.ReactElement;
15
+ export declare const ListVariableListBox: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLUListElement> & React.RefAttributes<HTMLUListElement>>;
16
+ //# sourceMappingURL=ListVariableListBox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListVariableListBox.d.ts","sourceRoot":"","sources":["../../../src/components/Variables/ListVariableListBox.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,EAAgC,SAAS,EAAmC,MAAM,OAAO,CAAC;AAExG,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;CACvD;AAID,wBAAgB,6BAA6B,IAAI,+BAA+B,CAI/E;AAmED,wBAAgB,2BAA2B,CAAC,EAC1C,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,+BAA+B,CAAC;IACvC,QAAQ,EAAE,SAAS,CAAC;CACrB,GAAG,KAAK,CAAC,YAAY,CAErB;AAED,eAAO,MAAM,mBAAmB,iHA0C9B,CAAC"}
@@ -0,0 +1,141 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ import React, { forwardRef, useContext, useMemo } from 'react';
15
+ import { Checkbox, Divider } from '@mui/material';
16
+ import { DEFAULT_ALL_VALUE } from '@perses-dev/core';
17
+ const ListVariableListBoxContext = /*#__PURE__*/ React.createContext(undefined);
18
+ export function useListVariableListBoxContext() {
19
+ const ctx = useContext(ListVariableListBoxContext);
20
+ if (!ctx) throw new Error('ListVariableListBoxContext not found');
21
+ return ctx;
22
+ }
23
+ /*
24
+ * Handles the logic for toggling the global select checkbox in the ListBox header.
25
+ *
26
+ * If all options are selected, it will deselect all options.
27
+ * Except if filteredOptions is a subset of options, then it will only deselect the filtered options.
28
+ *
29
+ * If some options are selected, it will select all filtered options.
30
+ *
31
+ * If no options are selected, it will select all filtered options.
32
+ * Should be not possible since a ListVariable has always at least one value.
33
+ *
34
+ * If allowAllValue is true, it will handle the special "All" option logic.
35
+ * Main difference is if some options are selected and there is no filter, it will select the "All" option
36
+ */ function handleGlobalSelectToggle(options, selectedOptions, filteredOptions, isIndeterminate, isAllSelected, allowAllValue, onChange) {
37
+ if (isAllSelected) {
38
+ if (filteredOptions.length !== options.length) {
39
+ onChange(selectedOptions.filter((o)=>!filteredOptions.includes(o)));
40
+ } else {
41
+ onChange([]);
42
+ }
43
+ return;
44
+ }
45
+ if (isIndeterminate) {
46
+ if (allowAllValue) {
47
+ if (filteredOptions.length === options.length) {
48
+ if (selectedOptions[0]?.value === DEFAULT_ALL_VALUE) {
49
+ onChange(options.filter((o)=>o.value !== DEFAULT_ALL_VALUE));
50
+ } else {
51
+ onChange([
52
+ {
53
+ label: DEFAULT_ALL_VALUE,
54
+ value: DEFAULT_ALL_VALUE
55
+ }
56
+ ]);
57
+ }
58
+ } else {
59
+ if (filteredOptions.every((o)=>selectedOptions.includes(o))) {
60
+ onChange(selectedOptions.filter((o)=>!filteredOptions.includes(o)));
61
+ } else {
62
+ onChange([
63
+ ...selectedOptions,
64
+ ...filteredOptions.filter((o)=>o.value !== DEFAULT_ALL_VALUE)
65
+ ]);
66
+ }
67
+ }
68
+ } else {
69
+ if (filteredOptions.length === options.length) {
70
+ onChange(options);
71
+ } else {
72
+ if (filteredOptions.every((o)=>selectedOptions.includes(o))) {
73
+ onChange(selectedOptions.filter((o)=>!filteredOptions.includes(o)));
74
+ } else {
75
+ onChange([
76
+ ...selectedOptions,
77
+ ...filteredOptions
78
+ ]);
79
+ }
80
+ }
81
+ }
82
+ return;
83
+ }
84
+ // Nothing selected, so select filtered options
85
+ onChange(filteredOptions);
86
+ }
87
+ export function ListVariableListBoxProvider({ value, children }) {
88
+ return /*#__PURE__*/ _jsx(ListVariableListBoxContext.Provider, {
89
+ value: value,
90
+ children: children
91
+ });
92
+ }
93
+ export const ListVariableListBox = /*#__PURE__*/ forwardRef(function ListVariableListBox(props, ref) {
94
+ const { children, ...rest } = props;
95
+ const { options, selectedOptions, filteredOptions, allowAllValue, onChange } = useListVariableListBoxContext();
96
+ // Derived selection metadata for context listbox header
97
+ const selectedCount = useMemo(()=>selectedOptions.length, [
98
+ selectedOptions
99
+ ]);
100
+ const isIndeterminate = useMemo(()=>options.length > 0 && selectedCount > 0 && selectedCount !== options.length, [
101
+ selectedCount,
102
+ options
103
+ ]);
104
+ const isAllSelected = useMemo(()=>options.length > 0 && selectedCount === options.length, [
105
+ selectedCount,
106
+ options
107
+ ]);
108
+ return /*#__PURE__*/ _jsxs("ul", {
109
+ ...rest,
110
+ ref: ref,
111
+ role: "listbox",
112
+ children: [
113
+ /*#__PURE__*/ _jsxs("li", {
114
+ style: {
115
+ display: 'flex',
116
+ alignItems: 'center'
117
+ },
118
+ children: [
119
+ /*#__PURE__*/ _jsx(Checkbox, {
120
+ indeterminate: isIndeterminate,
121
+ checked: isAllSelected,
122
+ // intentionally not passing event to underlying handler to mimic previous behavior
123
+ onChange: ()=>handleGlobalSelectToggle(options, selectedOptions, filteredOptions, isIndeterminate, isAllSelected, allowAllValue, onChange)
124
+ }),
125
+ /*#__PURE__*/ _jsxs("span", {
126
+ children: [
127
+ /*#__PURE__*/ _jsx("strong", {
128
+ children: selectedCount
129
+ }),
130
+ " Selected"
131
+ ]
132
+ })
133
+ ]
134
+ }),
135
+ /*#__PURE__*/ _jsx(Divider, {}),
136
+ children
137
+ ]
138
+ });
139
+ });
140
+
141
+ //# sourceMappingURL=ListVariableListBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/Variables/ListVariableListBox.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 React, { ForwardedRef, HTMLAttributes, ReactNode, forwardRef, useContext, useMemo } from 'react';\nimport { Checkbox, Divider } from '@mui/material';\nimport { VariableOption } from '@perses-dev/plugin-system';\nimport { DEFAULT_ALL_VALUE } from '@perses-dev/core';\n\nexport interface ListVariableListBoxContextValue {\n options: VariableOption[];\n selectedOptions: VariableOption[];\n filteredOptions: VariableOption[];\n allowAllValue: boolean;\n onChange: (selectedOptions: VariableOption[]) => void;\n}\n\nconst ListVariableListBoxContext = React.createContext<ListVariableListBoxContextValue | undefined>(undefined);\n\nexport function useListVariableListBoxContext(): ListVariableListBoxContextValue {\n const ctx = useContext(ListVariableListBoxContext);\n if (!ctx) throw new Error('ListVariableListBoxContext not found');\n return ctx;\n}\n\n/*\n * Handles the logic for toggling the global select checkbox in the ListBox header.\n *\n * If all options are selected, it will deselect all options.\n * Except if filteredOptions is a subset of options, then it will only deselect the filtered options.\n *\n * If some options are selected, it will select all filtered options.\n *\n * If no options are selected, it will select all filtered options.\n * Should be not possible since a ListVariable has always at least one value.\n *\n * If allowAllValue is true, it will handle the special \"All\" option logic.\n * Main difference is if some options are selected and there is no filter, it will select the \"All\" option\n */\nfunction handleGlobalSelectToggle(\n options: VariableOption[],\n selectedOptions: VariableOption[],\n filteredOptions: VariableOption[],\n isIndeterminate: boolean,\n isAllSelected: boolean,\n allowAllValue: boolean,\n onChange: (selectedOptions: VariableOption[]) => void\n): void {\n if (isAllSelected) {\n if (filteredOptions.length !== options.length) {\n onChange(selectedOptions.filter((o) => !filteredOptions.includes(o)));\n } else {\n onChange([]);\n }\n return;\n }\n\n if (isIndeterminate) {\n if (allowAllValue) {\n if (filteredOptions.length === options.length) {\n if (selectedOptions[0]?.value === DEFAULT_ALL_VALUE) {\n onChange(options.filter((o) => o.value !== DEFAULT_ALL_VALUE));\n } else {\n onChange([{ label: DEFAULT_ALL_VALUE, value: DEFAULT_ALL_VALUE }]);\n }\n } else {\n if (filteredOptions.every((o) => selectedOptions.includes(o))) {\n onChange(selectedOptions.filter((o) => !filteredOptions.includes(o)));\n } else {\n onChange([...selectedOptions, ...filteredOptions.filter((o) => o.value !== DEFAULT_ALL_VALUE)]);\n }\n }\n } else {\n if (filteredOptions.length === options.length) {\n onChange(options);\n } else {\n if (filteredOptions.every((o) => selectedOptions.includes(o))) {\n onChange(selectedOptions.filter((o) => !filteredOptions.includes(o)));\n } else {\n onChange([...selectedOptions, ...filteredOptions]);\n }\n }\n }\n return;\n }\n\n // Nothing selected, so select filtered options\n onChange(filteredOptions);\n}\n\nexport function ListVariableListBoxProvider({\n value,\n children,\n}: {\n value: ListVariableListBoxContextValue;\n children: ReactNode;\n}): React.ReactElement {\n return <ListVariableListBoxContext.Provider value={value}>{children}</ListVariableListBoxContext.Provider>;\n}\n\nexport const ListVariableListBox = forwardRef(function ListVariableListBox(\n props: HTMLAttributes<HTMLUListElement>,\n ref: ForwardedRef<HTMLUListElement>\n) {\n const { children, ...rest } = props;\n const { options, selectedOptions, filteredOptions, allowAllValue, onChange } = useListVariableListBoxContext();\n\n // Derived selection metadata for context listbox header\n const selectedCount = useMemo(() => selectedOptions.length, [selectedOptions]);\n const isIndeterminate = useMemo(\n () => options.length > 0 && selectedCount > 0 && selectedCount !== options.length,\n [selectedCount, options]\n );\n const isAllSelected = useMemo(() => options.length > 0 && selectedCount === options.length, [selectedCount, options]);\n\n return (\n <ul {...rest} ref={ref} role=\"listbox\">\n <li style={{ display: 'flex', alignItems: 'center' }}>\n <Checkbox\n indeterminate={isIndeterminate}\n checked={isAllSelected}\n // intentionally not passing event to underlying handler to mimic previous behavior\n onChange={() =>\n handleGlobalSelectToggle(\n options,\n selectedOptions,\n filteredOptions,\n isIndeterminate,\n isAllSelected,\n allowAllValue,\n onChange\n )\n }\n />\n <span>\n <strong>{selectedCount}</strong> Selected\n </span>\n </li>\n <Divider />\n {children}\n </ul>\n );\n});\n"],"names":["React","forwardRef","useContext","useMemo","Checkbox","Divider","DEFAULT_ALL_VALUE","ListVariableListBoxContext","createContext","undefined","useListVariableListBoxContext","ctx","Error","handleGlobalSelectToggle","options","selectedOptions","filteredOptions","isIndeterminate","isAllSelected","allowAllValue","onChange","length","filter","o","includes","value","label","every","ListVariableListBoxProvider","children","Provider","ListVariableListBox","props","ref","rest","selectedCount","ul","role","li","style","display","alignItems","indeterminate","checked","span","strong"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Variable.d.ts","sourceRoot":"","sources":["../../../src/components/Variables/Variable.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAgC,MAAM,OAAO,CAAC;AAEnE,OAAO,EAGL,gBAAgB,EAEhB,YAAY,EACZ,aAAa,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAA+B,cAAc,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACvG,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIvD,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,YAAY,CAWtE;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,GAAG,SAAS,EAClC,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,qBAAqB,EAAE,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,CAAC,GAC/D;IAED,KAAK,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,EAAE,GAAG,SAAS,CAAC;IAEtC,eAAe,EAAE,cAAc,GAAG,cAAc,EAAE,CAAC;IAEnD,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B,CA2FA"}
1
+ {"version":3,"file":"Variable.d.ts","sourceRoot":"","sources":["../../../src/components/Variables/Variable.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAA6C,MAAM,OAAO,CAAC;AAEhF,OAAO,EAGL,gBAAgB,EAEhB,YAAY,EACZ,aAAa,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAIL,cAAc,EACd,aAAa,EACd,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAKvD,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,YAAY,CAWtE;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,GAAG,SAAS,EAClC,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,qBAAqB,EAAE,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,CAAC,GAC/D;IAED,KAAK,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,EAAE,GAAG,SAAS,CAAC;IAEtC,eAAe,EAAE,cAAc,GAAG,cAAc,EAAE,CAAC;IAEnD,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B,CA4EA"}
@@ -10,13 +10,14 @@
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, Fragment as _Fragment } from "react/jsx-runtime";
14
- import { useEffect, useMemo, useState } from 'react';
15
- import { LinearProgress, TextField, Autocomplete, Popper } from '@mui/material';
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ import { useCallback, useEffect, useMemo, useState } from 'react';
15
+ import { TextField, Popper, Checkbox, Autocomplete, createFilterOptions } from '@mui/material';
16
16
  import { DEFAULT_ALL_VALUE } from '@perses-dev/core';
17
- import { useListVariablePluginValues } from '@perses-dev/plugin-system';
17
+ import { SORT_METHODS, useListVariablePluginValues } from '@perses-dev/plugin-system';
18
18
  import { useVariableDefinitionAndState, useVariableDefinitionActions } from '../../context';
19
19
  import { MAX_VARIABLE_WIDTH, MIN_VARIABLE_WIDTH } from '../../constants';
20
+ import { ListVariableListBoxProvider, ListVariableListBox } from './ListVariableListBox';
20
21
  function variableOptionToVariableValue(options) {
21
22
  if (options === null) {
22
23
  return null;
@@ -73,22 +74,8 @@ export function useListVariableState(spec, state, variablesOptionsQuery) {
73
74
  ...options
74
75
  ] : [];
75
76
  if (!sort || sort === 'none') return opts;
76
- switch(sort){
77
- case 'alphabetical-asc':
78
- return opts.sort((a, b)=>a.label > b.label ? 1 : -1);
79
- case 'alphabetical-desc':
80
- return opts.sort((a, b)=>a.label > b.label ? -1 : 1);
81
- case 'numerical-asc':
82
- return opts.sort((a, b)=>parseInt(a.label) > parseInt(b.label) ? 1 : -1);
83
- case 'numerical-desc':
84
- return opts.sort((a, b)=>parseInt(a.label) < parseInt(b.label) ? 1 : -1);
85
- case 'alphabetical-ci-asc':
86
- return opts.sort((a, b)=>a.label.toLowerCase() > b.label.toLowerCase() ? 1 : -1);
87
- case 'alphabetical-ci-desc':
88
- return opts.sort((a, b)=>a.label.toLowerCase() > b.label.toLowerCase() ? -1 : 1);
89
- default:
90
- return opts;
91
- }
77
+ const sortMethod = SORT_METHODS[sort];
78
+ return !sortMethod ? opts : sortMethod.sort(opts);
92
79
  }, [
93
80
  options,
94
81
  sort
@@ -196,6 +183,15 @@ function ListVariable({ name, source }) {
196
183
  const title = definition?.spec.display?.name ?? name;
197
184
  const allowMultiple = definition?.spec.allowMultiple === true;
198
185
  const allowAllValue = definition?.spec.allowAllValue === true;
186
+ const filterOptions = createFilterOptions({});
187
+ const filteredOptions = useMemo(()=>filterOptions(viewOptions, {
188
+ inputValue,
189
+ getOptionLabel: (o)=>o.label
190
+ }), [
191
+ inputValue,
192
+ viewOptions,
193
+ filterOptions
194
+ ]);
199
195
  // Update value when changed
200
196
  useEffect(()=>{
201
197
  if (value) {
@@ -227,64 +223,126 @@ function ListVariable({ name, source }) {
227
223
  options,
228
224
  source
229
225
  ]);
230
- return /*#__PURE__*/ _jsxs(_Fragment, {
231
- children: [
232
- /*#__PURE__*/ _jsx(Autocomplete, {
233
- disablePortal: true,
234
- disableCloseOnSelect: allowMultiple,
235
- multiple: allowMultiple,
236
- fullWidth: true,
237
- limitTags: 3,
238
- size: "small",
239
- disableClearable: true,
240
- slots: {
241
- popper: StyledPopper
242
- },
243
- renderInput: (params)=>{
244
- return allowMultiple ? /*#__PURE__*/ _jsx(TextField, {
245
- ...params,
246
- label: title,
247
- onChange: (e)=>setInputValue(e.target.value)
248
- }) : /*#__PURE__*/ _jsx(TextField, {
249
- ...params,
250
- label: title,
251
- style: {
252
- width: `${inputWidth}px`
253
- }
254
- });
255
- },
256
- sx: {
257
- '& .MuiInputBase-root': {
258
- minHeight: '38px'
259
- },
260
- '& .MuiAutocomplete-tag': {
261
- margin: '1px 2px'
262
- }
263
- },
264
- value: selectedOptions,
265
- onChange: (_, value)=>{
266
- if ((value === null || Array.isArray(value) && value.length === 0) && allowAllValue) {
267
- setVariableValue(name, DEFAULT_ALL_VALUE, source);
268
- } else {
269
- setVariableValue(name, variableOptionToVariableValue(value), source);
270
- }
271
- },
272
- inputValue: allowMultiple ? inputValue : undefined,
273
- onInputChange: (_, newInputValue)=>{
274
- if (!allowMultiple) {
275
- setInputWidth(getWidthPx(newInputValue, 'list'));
276
- }
226
+ const handleGlobalSelect = useCallback((options)=>{
227
+ setVariableValue(name, variableOptionToVariableValue(options), source);
228
+ }, [
229
+ name,
230
+ setVariableValue,
231
+ source
232
+ ]);
233
+ const listBoxProviderValue = useMemo(()=>({
234
+ options: viewOptions,
235
+ selectedOptions: selectedOptions,
236
+ filteredOptions: filteredOptions,
237
+ allowAllValue,
238
+ onChange: handleGlobalSelect
239
+ }), [
240
+ allowAllValue,
241
+ filteredOptions,
242
+ handleGlobalSelect,
243
+ selectedOptions,
244
+ viewOptions
245
+ ]);
246
+ const autocompleteComponent = useMemo(()=>{
247
+ return /*#__PURE__*/ _jsx(Autocomplete, {
248
+ disablePortal: true,
249
+ loading: loading,
250
+ disableCloseOnSelect: allowMultiple,
251
+ multiple: allowMultiple,
252
+ fullWidth: true,
253
+ limitTags: 3,
254
+ size: "small",
255
+ disableClearable: true,
256
+ slotProps: {
257
+ listbox: {
258
+ component: allowMultiple ? ListVariableListBox : undefined
259
+ }
260
+ },
261
+ slots: {
262
+ popper: StyledPopper
263
+ },
264
+ sx: {
265
+ '& .MuiInputBase-root': {
266
+ minHeight: '38px'
277
267
  },
278
- onBlur: ()=>{
279
- if (allowMultiple) {
280
- setInputValue('');
268
+ '& .MuiAutocomplete-tag': {
269
+ margin: '1px 2px'
270
+ }
271
+ },
272
+ filterOptions: filterOptions,
273
+ options: viewOptions,
274
+ value: selectedOptions,
275
+ onChange: (_, value)=>{
276
+ if ((value === null || Array.isArray(value) && value.length === 0) && allowAllValue) {
277
+ setVariableValue(name, DEFAULT_ALL_VALUE, source);
278
+ } else {
279
+ setVariableValue(name, variableOptionToVariableValue(value), source);
280
+ }
281
+ },
282
+ inputValue: allowMultiple ? inputValue : undefined,
283
+ onInputChange: (_, newInputValue)=>{
284
+ if (!allowMultiple) {
285
+ setInputWidth(getWidthPx(newInputValue, 'list'));
286
+ }
287
+ },
288
+ onBlur: ()=>{
289
+ if (allowMultiple) {
290
+ setInputValue('');
291
+ }
292
+ },
293
+ renderInput: (params)=>{
294
+ return allowMultiple ? /*#__PURE__*/ _jsx(TextField, {
295
+ ...params,
296
+ label: title,
297
+ onChange: (e)=>setInputValue(e.target.value)
298
+ }) : /*#__PURE__*/ _jsx(TextField, {
299
+ ...params,
300
+ label: title,
301
+ style: {
302
+ width: `${inputWidth}px`
281
303
  }
282
- },
283
- options: viewOptions
284
- }),
285
- loading && /*#__PURE__*/ _jsx(LinearProgress, {})
286
- ]
287
- });
304
+ });
305
+ },
306
+ renderOption: (props, option, { selected })=>{
307
+ const { key, ...optionProps } = props;
308
+ return /*#__PURE__*/ _jsxs("li", {
309
+ ...optionProps,
310
+ style: {
311
+ padding: 0
312
+ },
313
+ children: [
314
+ /*#__PURE__*/ _jsx(Checkbox, {
315
+ style: {
316
+ marginRight: 8
317
+ },
318
+ checked: selected
319
+ }),
320
+ option.label
321
+ ]
322
+ }, key);
323
+ }
324
+ });
325
+ }, [
326
+ allowAllValue,
327
+ allowMultiple,
328
+ filterOptions,
329
+ inputValue,
330
+ inputWidth,
331
+ loading,
332
+ name,
333
+ selectedOptions,
334
+ setVariableValue,
335
+ source,
336
+ title,
337
+ viewOptions
338
+ ]);
339
+ if (allowMultiple) {
340
+ return /*#__PURE__*/ _jsx(ListVariableListBoxProvider, {
341
+ value: listBoxProviderValue,
342
+ children: autocompleteComponent
343
+ });
344
+ }
345
+ return autocompleteComponent;
288
346
  }
289
347
  function TextVariable({ name, source }) {
290
348
  const ctx = useVariableDefinitionAndState(name, source);