@perses-dev/plugin-system 0.22.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/cjs/components/OptionsEditorTabs/OptionsEditorTabs.js +4 -47
  2. package/dist/cjs/components/OptionsEditorTabs/OptionsEditorTabs.test.js +25 -85
  3. package/dist/cjs/components/PluginSpecEditor.js +38 -4
  4. package/dist/cjs/components/PluginSpecEditor.test.js +30 -8
  5. package/dist/cjs/model/panels.js +6 -0
  6. package/dist/cjs/test/test-plugins/bert/index.js +32 -19
  7. package/dist/components/OptionsEditorTabs/OptionsEditorTabs.d.ts +3 -24
  8. package/dist/components/OptionsEditorTabs/OptionsEditorTabs.d.ts.map +1 -1
  9. package/dist/components/OptionsEditorTabs/OptionsEditorTabs.js +4 -47
  10. package/dist/components/OptionsEditorTabs/OptionsEditorTabs.js.map +1 -1
  11. package/dist/components/OptionsEditorTabs/OptionsEditorTabs.test.js +25 -85
  12. package/dist/components/OptionsEditorTabs/OptionsEditorTabs.test.js.map +1 -1
  13. package/dist/components/PluginSpecEditor.d.ts.map +1 -1
  14. package/dist/components/PluginSpecEditor.js +39 -5
  15. package/dist/components/PluginSpecEditor.js.map +1 -1
  16. package/dist/components/PluginSpecEditor.test.js +30 -8
  17. package/dist/components/PluginSpecEditor.test.js.map +1 -1
  18. package/dist/model/panels.d.ts +14 -2
  19. package/dist/model/panels.d.ts.map +1 -1
  20. package/dist/model/panels.js +1 -1
  21. package/dist/model/panels.js.map +1 -1
  22. package/dist/model/plugin-base.d.ts +1 -1
  23. package/dist/model/plugin-base.d.ts.map +1 -1
  24. package/dist/model/plugin-base.js.map +1 -1
  25. package/dist/test/test-plugins/bert/index.d.ts.map +1 -1
  26. package/dist/test/test-plugins/bert/index.js +32 -19
  27. package/dist/test/test-plugins/bert/index.js.map +1 -1
  28. package/package.json +3 -3
@@ -22,54 +22,11 @@ const _jsxRuntime = require("react/jsx-runtime");
22
22
  const _material = require("@mui/material");
23
23
  const _react = require("react");
24
24
  const _tabPanel = require("./TabPanel");
25
- // Configuration of the order and labeling for tabs across plugins to enforce a
26
- // consistent UX.
27
- const TAB_CONFIG = [
28
- {
29
- id: 'query',
30
- label: 'Query'
31
- },
32
- {
33
- id: 'settings',
34
- label: 'Settings'
35
- },
36
- // Custom tabs go between the visual common tabs and the raw JSON editor.
37
- 'other',
38
- {
39
- id: 'json',
40
- label: 'JSON'
41
- }
42
- ];
43
25
  const OptionsEditorTabs = ({ tabs })=>{
44
26
  const [activeTab, setActiveTab] = (0, _react.useState)(0);
45
27
  const handleChange = (_, newValue)=>{
46
28
  setActiveTab(newValue);
47
29
  };
48
- // Normalize the common tabs that are managed via constants in this file
49
- // and custom tabs that bring their own config into a consistent shape for
50
- // rendering.
51
- const normalizedTabs = TAB_CONFIG.reduce((combinedTabs, tabConfig)=>{
52
- // Custom tabs
53
- if (tabConfig === 'other') {
54
- const otherTabs = (tabs === null || tabs === void 0 ? void 0 : tabs.other) || [];
55
- return [
56
- ...combinedTabs,
57
- ...otherTabs
58
- ];
59
- }
60
- // Common tabs
61
- const commonTab = tabs[tabConfig.id];
62
- if (commonTab) {
63
- return [
64
- ...combinedTabs,
65
- {
66
- ...tabConfig,
67
- ...commonTab
68
- }
69
- ];
70
- }
71
- return combinedTabs;
72
- }, []);
73
30
  return /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
74
31
  children: [
75
32
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Box, {
@@ -81,21 +38,21 @@ const OptionsEditorTabs = ({ tabs })=>{
81
38
  value: activeTab,
82
39
  onChange: handleChange,
83
40
  "aria-label": "Panel configuration tabs",
84
- children: normalizedTabs.map(({ id , label }, i)=>{
41
+ children: tabs.map(({ label }, i)=>{
85
42
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Tab, {
86
43
  label: label,
87
44
  id: `options-editor-tab-${i}`,
88
45
  "aria-controls": `options-editor-tabpanel-${i}`
89
- }, id);
46
+ }, label);
90
47
  })
91
48
  })
92
49
  }),
93
- normalizedTabs.map(({ id , content }, i)=>{
50
+ tabs.map(({ label , content }, i)=>{
94
51
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_tabPanel.TabPanel, {
95
52
  value: activeTab,
96
53
  index: i,
97
54
  children: content
98
- }, id);
55
+ }, label);
99
56
  })
100
57
  ]
101
58
  });
@@ -24,46 +24,32 @@ function _interopRequireDefault(obj) {
24
24
  };
25
25
  }
26
26
  describe('OptionsEditorTabs', ()=>{
27
+ const mockTabs = [
28
+ {
29
+ label: 'Query',
30
+ content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
31
+ children: "Edit query configuration"
32
+ })
33
+ },
34
+ {
35
+ label: 'Settings',
36
+ content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
37
+ children: "Edit settings configuration"
38
+ })
39
+ },
40
+ {
41
+ label: 'JSON',
42
+ content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
43
+ children: "JSON editor"
44
+ })
45
+ }
46
+ ];
27
47
  const renderTabs = (otherTabs)=>{
48
+ const tabs = otherTabs !== null && otherTabs !== void 0 ? otherTabs : mockTabs;
28
49
  (0, _react.render)(/*#__PURE__*/ (0, _jsxRuntime.jsx)(_optionsEditorTabs.OptionsEditorTabs, {
29
- tabs: {
30
- query: {
31
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
32
- children: "Edit query configuration"
33
- })
34
- },
35
- settings: {
36
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
37
- children: "Edit settings configuration"
38
- })
39
- },
40
- json: {
41
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
42
- children: "JSON editor"
43
- })
44
- },
45
- other: otherTabs
46
- }
50
+ tabs: tabs
47
51
  }));
48
52
  };
49
- const renderCustomTabs = ()=>{
50
- renderTabs([
51
- {
52
- id: 'tableCols',
53
- label: 'Table columns',
54
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
55
- children: "custom table column"
56
- })
57
- },
58
- {
59
- id: 'tableOpts',
60
- label: 'Table options',
61
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
62
- children: "custom table options"
63
- })
64
- }
65
- ]);
66
- };
67
53
  it('renders all specified tabs in a tab list', ()=>{
68
54
  renderTabs();
69
55
  const tabList = _react.screen.getByRole('tablist');
@@ -109,59 +95,13 @@ describe('OptionsEditorTabs', ()=>{
109
95
  const activeTabPanel = _react.screen.getByRole('tabpanel');
110
96
  expect(activeTabPanel).toHaveTextContent('settings configuration');
111
97
  });
112
- it('renders custom tabs between visual tabs and json editor', ()=>{
113
- renderCustomTabs();
98
+ it('renders tabs in correct order', ()=>{
99
+ renderTabs();
114
100
  const tabList = _react.screen.getByRole('tablist');
115
101
  const tabs = (0, _react.getAllByRole)(tabList, 'tab');
116
- expect(tabs).toHaveLength(5);
102
+ expect(tabs).toHaveLength(3);
117
103
  expect(tabs[0]).toHaveTextContent('Query');
118
104
  expect(tabs[1]).toHaveTextContent('Settings');
119
- expect(tabs[2]).toHaveTextContent('Table column');
120
- expect(tabs[3]).toHaveTextContent('Table options');
121
- expect(tabs[4]).toHaveTextContent('JSON');
122
- });
123
- it('shows the correct content when selecting a custom tab', ()=>{
124
- renderCustomTabs();
125
- const tableColTab = _react.screen.getByRole('tab', {
126
- name: 'Table columns'
127
- });
128
- _userEvent.default.click(tableColTab);
129
- const activeTab = _react.screen.getByRole('tab', {
130
- selected: true
131
- });
132
- expect(activeTab).toBe(tableColTab);
133
- const activeTabPanel = _react.screen.getByRole('tabpanel');
134
- expect(activeTabPanel).toHaveTextContent('custom table column');
135
- });
136
- it('only renders common tabs that are specified', ()=>{
137
- (0, _react.render)(/*#__PURE__*/ (0, _jsxRuntime.jsx)(_optionsEditorTabs.OptionsEditorTabs, {
138
- tabs: {
139
- settings: {
140
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
141
- children: "settings are alone"
142
- })
143
- },
144
- json: {
145
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
146
- children: "JSON is at the end"
147
- })
148
- },
149
- other: [
150
- {
151
- id: 'custom',
152
- label: 'Another tab',
153
- content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
154
- children: "another tab content"
155
- })
156
- }
157
- ]
158
- }
159
- }));
160
- const tabList = _react.screen.getByRole('tablist');
161
- const tabs = (0, _react.getAllByRole)(tabList, 'tab');
162
- expect(tabs).toHaveLength(3);
163
- expect(tabs[0]).toHaveTextContent('Settings');
164
- expect(tabs[1]).toHaveTextContent('Another tab');
165
105
  expect(tabs[2]).toHaveTextContent('JSON');
166
106
  });
167
107
  });
@@ -21,6 +21,7 @@ Object.defineProperty(exports, "PluginSpecEditor", {
21
21
  const _jsxRuntime = require("react/jsx-runtime");
22
22
  const _components = require("@perses-dev/components");
23
23
  const _runtime = require("../runtime");
24
+ const _optionsEditorTabs = require("./OptionsEditorTabs");
24
25
  function PluginSpecEditor(props) {
25
26
  const { pluginType , pluginKind , ...others } = props;
26
27
  const { data: plugin , isLoading , error } = (0, _runtime.usePlugin)(pluginType, pluginKind);
@@ -34,10 +35,43 @@ function PluginSpecEditor(props) {
34
35
  return null;
35
36
  }
36
37
  if (plugin === undefined) {
37
- throw new Error(`Missing OptionsEditorComponent for ${pluginType} plugin with kind '${pluginKind}'`);
38
+ throw new Error(`Missing implementation for ${pluginType} plugin with kind '${pluginKind}'`);
39
+ }
40
+ if (pluginType === 'Panel') {
41
+ const { PanelQueryEditorComponent , panelOptionsEditorComponents } = plugin;
42
+ let tabs = [];
43
+ if (PanelQueryEditorComponent !== undefined) {
44
+ tabs.push({
45
+ label: 'Query',
46
+ content: /*#__PURE__*/ (0, _jsxRuntime.jsx)(PanelQueryEditorComponent, {
47
+ ...others
48
+ })
49
+ });
50
+ }
51
+ if (panelOptionsEditorComponents !== undefined) {
52
+ tabs = tabs.concat(panelOptionsEditorComponents.map(({ label , content: OptionsEditorComponent })=>({
53
+ label,
54
+ content: /*#__PURE__*/ (0, _jsxRuntime.jsx)(OptionsEditorComponent, {
55
+ ...others
56
+ })
57
+ })));
58
+ }
59
+ // always show json editor by default
60
+ tabs.push({
61
+ label: 'JSON',
62
+ content: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.JSONEditor, {
63
+ ...others
64
+ })
65
+ });
66
+ return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_optionsEditorTabs.OptionsEditorTabs, {
67
+ tabs: tabs
68
+ });
38
69
  }
39
70
  const { OptionsEditorComponent } = plugin;
40
- return /*#__PURE__*/ (0, _jsxRuntime.jsx)(OptionsEditorComponent, {
41
- ...others
42
- });
71
+ if (OptionsEditorComponent !== undefined) {
72
+ return /*#__PURE__*/ (0, _jsxRuntime.jsx)(OptionsEditorComponent, {
73
+ ...others
74
+ });
75
+ }
76
+ return null;
43
77
  }
@@ -30,15 +30,37 @@ describe('PluginSpecEditor', ()=>{
30
30
  ...props
31
31
  }));
32
32
  };
33
- it('shows the options editor component for a plugin', async ()=>{
34
- renderComponent({
35
- pluginType: 'Panel',
36
- pluginKind: 'BertPanel1',
37
- value: {},
38
- onChange: jest.fn()
33
+ describe('Panel plugin', ()=>{
34
+ it('should show query and json editors', async ()=>{
35
+ renderComponent({
36
+ pluginType: 'Panel',
37
+ pluginKind: 'BertPanel1',
38
+ value: {},
39
+ onChange: jest.fn()
40
+ });
41
+ const queryTab = await _react.screen.findByLabelText('Query');
42
+ expect(queryTab).toBeInTheDocument();
43
+ const editor = await _react.screen.findByLabelText('BertPanel1 editor');
44
+ expect(editor).toBeInTheDocument();
45
+ const jsonEditor = await _react.screen.findByLabelText('JSON');
46
+ expect(jsonEditor).toBeInTheDocument();
47
+ });
48
+ it('should display other options editor components', async ()=>{
49
+ renderComponent({
50
+ pluginType: 'Panel',
51
+ pluginKind: 'BertPanel2',
52
+ value: {},
53
+ onChange: jest.fn()
54
+ });
55
+ const settingsTab = await _react.screen.findByLabelText('Settings');
56
+ expect(settingsTab).toBeInTheDocument();
57
+ const editor = await _react.screen.findByLabelText('BertPanel2 editor');
58
+ expect(editor).toBeInTheDocument();
59
+ const customTab = await _react.screen.findByLabelText('Custom Tab');
60
+ expect(customTab).toBeInTheDocument();
61
+ const jsonEditor = await _react.screen.findByLabelText('JSON');
62
+ expect(jsonEditor).toBeInTheDocument();
39
63
  });
40
- const editor = await _react.screen.findByLabelText('BertPanel1 editor');
41
- expect(editor).toBeInTheDocument();
42
64
  });
43
65
  it('propagates value changes', async ()=>{
44
66
  const onChange = jest.fn();
@@ -14,3 +14,9 @@
14
14
  Object.defineProperty(exports, "__esModule", {
15
15
  value: true
16
16
  });
17
+ const _react = /*#__PURE__*/ _interopRequireDefault(require("react"));
18
+ function _interopRequireDefault(obj) {
19
+ return obj && obj.__esModule ? obj : {
20
+ default: obj
21
+ };
22
+ }
@@ -27,7 +27,7 @@ _export(exports, {
27
27
  const _jsxRuntime = require("react/jsx-runtime");
28
28
  const BertPanel1 = {
29
29
  PanelComponent: ()=>null,
30
- OptionsEditorComponent: function BertPanel1Editor({ value , onChange }) {
30
+ PanelQueryEditorComponent: function BertPanel1Editor({ value , onChange }) {
31
31
  return /*#__PURE__*/ (0, _jsxRuntime.jsxs)("div", {
32
32
  children: [
33
33
  /*#__PURE__*/ (0, _jsxRuntime.jsx)("label", {
@@ -52,25 +52,38 @@ const BertPanel1 = {
52
52
  };
53
53
  const BertPanel2 = {
54
54
  PanelComponent: ()=>null,
55
- OptionsEditorComponent: function BertPanel2Editor({ value , onChange }) {
56
- return /*#__PURE__*/ (0, _jsxRuntime.jsxs)("div", {
57
- children: [
58
- /*#__PURE__*/ (0, _jsxRuntime.jsx)("label", {
59
- htmlFor: "editor-input",
60
- children: "BertPanel2 editor"
61
- }),
62
- /*#__PURE__*/ (0, _jsxRuntime.jsx)("input", {
63
- type: "text",
64
- id: "editor-input",
65
- value: value.option2,
66
- onChange: (e)=>onChange({
67
- ...value,
68
- option2: e.target.value
55
+ panelOptionsEditorComponents: [
56
+ {
57
+ label: 'Settings',
58
+ content: function BertPanel2Editor({ value , onChange }) {
59
+ return /*#__PURE__*/ (0, _jsxRuntime.jsxs)("div", {
60
+ children: [
61
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)("label", {
62
+ htmlFor: "editor-input",
63
+ children: "BertPanel2 editor"
64
+ }),
65
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)("input", {
66
+ type: "text",
67
+ id: "editor-input",
68
+ value: value.option2,
69
+ onChange: (e)=>onChange({
70
+ ...value,
71
+ option2: e.target.value
72
+ })
69
73
  })
70
- })
71
- ]
72
- });
73
- },
74
+ ]
75
+ });
76
+ }
77
+ },
78
+ {
79
+ label: 'Custom Tab',
80
+ content: function Editor() {
81
+ return /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
82
+ children: "custom content"
83
+ });
84
+ }
85
+ }
86
+ ],
74
87
  createInitialOptions: ()=>({
75
88
  option2: ''
76
89
  })
@@ -1,34 +1,13 @@
1
1
  /// <reference types="react" />
2
- import { TabProps } from '@mui/material';
3
- interface BaseTabConfig {
2
+ export declare type OptionsEditorTab = {
3
+ label: string;
4
4
  /**
5
5
  * Content rendered when the tab is active.
6
6
  */
7
7
  content: React.ReactNode;
8
- }
9
- interface OtherTabConfig extends BaseTabConfig {
10
- id: string;
11
- label: TabProps['label'];
12
- }
13
- declare type CommonTabId = 'query' | 'settings' | 'json';
14
- /**
15
- * Common tabs that are frequently used in the options editor across multiple
16
- * plugins. The label and display order of these tabs is not configurable to
17
- * avoid user experience inconsistencies across plugins.
18
- */
19
- declare type CommonTabs = {
20
- [property in CommonTabId]?: BaseTabConfig;
21
- };
22
- /**
23
- * Custom tabs specified for a given plugin. They are displayed after common
24
- * tabs.
25
- */
26
- declare type OtherTabs = {
27
- other?: OtherTabConfig[];
28
8
  };
29
9
  export declare type OptionsEditorTabsProps = {
30
- tabs: CommonTabs & OtherTabs;
10
+ tabs: OptionsEditorTab[];
31
11
  };
32
12
  export declare const OptionsEditorTabs: ({ tabs }: OptionsEditorTabsProps) => JSX.Element;
33
- export {};
34
13
  //# sourceMappingURL=OptionsEditorTabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OptionsEditorTabs.d.ts","sourceRoot":"","sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.tsx"],"names":[],"mappings":";AAaA,OAAO,EAAO,QAAQ,EAAwB,MAAM,eAAe,CAAC;AAIpE,UAAU,aAAa;IACrB;;OAEG;IACH,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B;AAED,UAAU,cAAe,SAAQ,aAAa;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED,aAAK,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAEjD;;;;GAIG;AACH,aAAK,UAAU,GAAG;KAAG,QAAQ,IAAI,WAAW,CAAC,CAAC,EAAE,aAAa;CAAE,CAAC;AAEhE;;;GAGG;AACH,aAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;CAC1B,CAAC;AAEF,oBAAY,sBAAsB,GAAG;IACnC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9B,CAAC;AAcF,eAAO,MAAM,iBAAiB,aAAc,sBAAsB,gBAyDjE,CAAC"}
1
+ {"version":3,"file":"OptionsEditorTabs.d.ts","sourceRoot":"","sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.tsx"],"names":[],"mappings":";AAiBA,oBAAY,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,CAAC;AAEF,oBAAY,sBAAsB,GAAG;IACnC,IAAI,EAAE,gBAAgB,EAAE,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,aAAc,sBAAsB,gBAgCjE,CAAC"}
@@ -14,54 +14,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
14
14
  import { Tab, Tabs, Box } from '@mui/material';
15
15
  import { useState } from 'react';
16
16
  import { TabPanel } from './TabPanel';
17
- // Configuration of the order and labeling for tabs across plugins to enforce a
18
- // consistent UX.
19
- const TAB_CONFIG = [
20
- {
21
- id: 'query',
22
- label: 'Query'
23
- },
24
- {
25
- id: 'settings',
26
- label: 'Settings'
27
- },
28
- // Custom tabs go between the visual common tabs and the raw JSON editor.
29
- 'other',
30
- {
31
- id: 'json',
32
- label: 'JSON'
33
- }
34
- ];
35
17
  export const OptionsEditorTabs = ({ tabs })=>{
36
18
  const [activeTab, setActiveTab] = useState(0);
37
19
  const handleChange = (_, newValue)=>{
38
20
  setActiveTab(newValue);
39
21
  };
40
- // Normalize the common tabs that are managed via constants in this file
41
- // and custom tabs that bring their own config into a consistent shape for
42
- // rendering.
43
- const normalizedTabs = TAB_CONFIG.reduce((combinedTabs, tabConfig)=>{
44
- // Custom tabs
45
- if (tabConfig === 'other') {
46
- const otherTabs = (tabs === null || tabs === void 0 ? void 0 : tabs.other) || [];
47
- return [
48
- ...combinedTabs,
49
- ...otherTabs
50
- ];
51
- }
52
- // Common tabs
53
- const commonTab = tabs[tabConfig.id];
54
- if (commonTab) {
55
- return [
56
- ...combinedTabs,
57
- {
58
- ...tabConfig,
59
- ...commonTab
60
- }
61
- ];
62
- }
63
- return combinedTabs;
64
- }, []);
65
22
  return /*#__PURE__*/ _jsxs(_Fragment, {
66
23
  children: [
67
24
  /*#__PURE__*/ _jsx(Box, {
@@ -73,21 +30,21 @@ export const OptionsEditorTabs = ({ tabs })=>{
73
30
  value: activeTab,
74
31
  onChange: handleChange,
75
32
  "aria-label": "Panel configuration tabs",
76
- children: normalizedTabs.map(({ id , label }, i)=>{
33
+ children: tabs.map(({ label }, i)=>{
77
34
  return /*#__PURE__*/ _jsx(Tab, {
78
35
  label: label,
79
36
  id: `options-editor-tab-${i}`,
80
37
  "aria-controls": `options-editor-tabpanel-${i}`
81
- }, id);
38
+ }, label);
82
39
  })
83
40
  })
84
41
  }),
85
- normalizedTabs.map(({ id , content }, i)=>{
42
+ tabs.map(({ label , content }, i)=>{
86
43
  return /*#__PURE__*/ _jsx(TabPanel, {
87
44
  value: activeTab,
88
45
  index: i,
89
46
  children: content
90
- }, id);
47
+ }, label);
91
48
  })
92
49
  ]
93
50
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.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 { Tab, TabProps, Tabs, TabsProps, Box } from '@mui/material';\nimport { useState } from 'react';\nimport { TabPanel } from './TabPanel';\n\ninterface BaseTabConfig {\n /**\n * Content rendered when the tab is active.\n */\n content: React.ReactNode;\n}\n\ninterface OtherTabConfig extends BaseTabConfig {\n id: string;\n label: TabProps['label'];\n}\n\ntype CommonTabId = 'query' | 'settings' | 'json';\n\n/**\n * Common tabs that are frequently used in the options editor across multiple\n * plugins. The label and display order of these tabs is not configurable to\n * avoid user experience inconsistencies across plugins.\n */\ntype CommonTabs = { [property in CommonTabId]?: BaseTabConfig };\n\n/**\n * Custom tabs specified for a given plugin. They are displayed after common\n * tabs.\n */\ntype OtherTabs = {\n other?: OtherTabConfig[];\n};\n\nexport type OptionsEditorTabsProps = {\n tabs: CommonTabs & OtherTabs;\n};\n\n// Configuration of the order and labeling for tabs across plugins to enforce a\n// consistent UX.\nconst TAB_CONFIG = [\n { id: 'query', label: 'Query' },\n { id: 'settings', label: 'Settings' },\n\n // Custom tabs go between the visual common tabs and the raw JSON editor.\n 'other',\n\n { id: 'json', label: 'JSON' },\n] as const;\n\nexport const OptionsEditorTabs = ({ tabs }: OptionsEditorTabsProps) => {\n const [activeTab, setActiveTab] = useState(0);\n\n const handleChange: TabsProps['onChange'] = (_, newValue) => {\n setActiveTab(newValue);\n };\n\n // Normalize the common tabs that are managed via constants in this file\n // and custom tabs that bring their own config into a consistent shape for\n // rendering.\n const normalizedTabs = TAB_CONFIG.reduce((combinedTabs, tabConfig) => {\n // Custom tabs\n if (tabConfig === 'other') {\n const otherTabs = tabs?.other || [];\n return [...combinedTabs, ...otherTabs];\n }\n\n // Common tabs\n const commonTab = tabs[tabConfig.id];\n if (commonTab) {\n return [\n ...combinedTabs,\n {\n ...tabConfig,\n ...commonTab,\n },\n ];\n }\n\n return combinedTabs;\n }, [] as OtherTabConfig[]);\n\n return (\n <>\n <Box sx={{ borderBottom: 1, borderColor: (theme) => theme.palette.divider }}>\n <Tabs value={activeTab} onChange={handleChange} aria-label=\"Panel configuration tabs\">\n {normalizedTabs.map(({ id, label }, i) => {\n return (\n <Tab\n key={id}\n label={label}\n id={`options-editor-tab-${i}`}\n aria-controls={`options-editor-tabpanel-${i}`}\n />\n );\n })}\n </Tabs>\n </Box>\n {normalizedTabs.map(({ id, content }, i) => {\n return (\n <TabPanel key={id} value={activeTab} index={i}>\n {content}\n </TabPanel>\n );\n })}\n </>\n );\n};\n"],"names":["Tab","Tabs","Box","useState","TabPanel","TAB_CONFIG","id","label","OptionsEditorTabs","tabs","activeTab","setActiveTab","handleChange","_","newValue","normalizedTabs","reduce","combinedTabs","tabConfig","otherTabs","other","commonTab","sx","borderBottom","borderColor","theme","palette","divider","value","onChange","aria-label","map","i","aria-controls","content","index"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.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 { Tab, Tabs, TabsProps, Box } from '@mui/material';\nimport { useState } from 'react';\nimport { TabPanel } from './TabPanel';\n\nexport type OptionsEditorTab = {\n label: string;\n /**\n * Content rendered when the tab is active.\n */\n content: React.ReactNode;\n};\n\nexport type OptionsEditorTabsProps = {\n tabs: OptionsEditorTab[];\n};\n\nexport const OptionsEditorTabs = ({ tabs }: OptionsEditorTabsProps) => {\n const [activeTab, setActiveTab] = useState(0);\n\n const handleChange: TabsProps['onChange'] = (_, newValue) => {\n setActiveTab(newValue);\n };\n\n return (\n <>\n <Box sx={{ borderBottom: 1, borderColor: (theme) => theme.palette.divider }}>\n <Tabs value={activeTab} onChange={handleChange} aria-label=\"Panel configuration tabs\">\n {tabs.map(({ label }, i) => {\n return (\n <Tab\n key={label}\n label={label}\n id={`options-editor-tab-${i}`}\n aria-controls={`options-editor-tabpanel-${i}`}\n />\n );\n })}\n </Tabs>\n </Box>\n {tabs.map(({ label, content }, i) => {\n return (\n <TabPanel key={label} value={activeTab} index={i}>\n {content}\n </TabPanel>\n );\n })}\n </>\n );\n};\n"],"names":["Tab","Tabs","Box","useState","TabPanel","OptionsEditorTabs","tabs","activeTab","setActiveTab","handleChange","_","newValue","sx","borderBottom","borderColor","theme","palette","divider","value","onChange","aria-label","map","label","i","id","aria-controls","content","index"],"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;AAAA,SAASA,GAAG,EAAEC,IAAI,EAAaC,GAAG,QAAQ,eAAe,CAAC;AAC1D,SAASC,QAAQ,QAAQ,OAAO,CAAC;AACjC,SAASC,QAAQ,QAAQ,YAAY,CAAC;AActC,OAAO,MAAMC,iBAAiB,GAAG,CAAC,EAAEC,IAAI,CAAA,EAA0B,GAAK;IACrE,MAAM,CAACC,SAAS,EAAEC,YAAY,CAAC,GAAGL,QAAQ,CAAC,CAAC,CAAC,AAAC;IAE9C,MAAMM,YAAY,GAA0B,CAACC,CAAC,EAAEC,QAAQ,GAAK;QAC3DH,YAAY,CAACG,QAAQ,CAAC,CAAC;IACzB,CAAC,AAAC;IAEF,qBACE;;0BACE,KAACT,GAAG;gBAACU,EAAE,EAAE;oBAAEC,YAAY,EAAE,CAAC;oBAAEC,WAAW,EAAE,CAACC,KAAK,GAAKA,KAAK,CAACC,OAAO,CAACC,OAAO;iBAAE;0BACzE,cAAA,KAAChB,IAAI;oBAACiB,KAAK,EAAEX,SAAS;oBAAEY,QAAQ,EAAEV,YAAY;oBAAEW,YAAU,EAAC,0BAA0B;8BAClFd,IAAI,CAACe,GAAG,CAAC,CAAC,EAAEC,KAAK,CAAA,EAAE,EAAEC,CAAC,GAAK;wBAC1B,qBACE,KAACvB,GAAG;4BAEFsB,KAAK,EAAEA,KAAK;4BACZE,EAAE,EAAE,CAAC,mBAAmB,EAAED,CAAC,CAAC,CAAC;4BAC7BE,eAAa,EAAE,CAAC,wBAAwB,EAAEF,CAAC,CAAC,CAAC;2BAHxCD,KAAK,CAIV,CACF;oBACJ,CAAC,CAAC;kBACG;cACH;YACLhB,IAAI,CAACe,GAAG,CAAC,CAAC,EAAEC,KAAK,CAAA,EAAEI,OAAO,CAAA,EAAE,EAAEH,CAAC,GAAK;gBACnC,qBACE,KAACnB,QAAQ;oBAAac,KAAK,EAAEX,SAAS;oBAAEoB,KAAK,EAAEJ,CAAC;8BAC7CG,OAAO;mBADKJ,KAAK,CAET,CACX;YACJ,CAAC,CAAC;;MACD,CACH;AACJ,CAAC,CAAC"}
@@ -15,46 +15,32 @@ import { screen, render, getAllByRole } from '@testing-library/react';
15
15
  import userEvent from '@testing-library/user-event';
16
16
  import { OptionsEditorTabs } from './OptionsEditorTabs';
17
17
  describe('OptionsEditorTabs', ()=>{
18
+ const mockTabs = [
19
+ {
20
+ label: 'Query',
21
+ content: /*#__PURE__*/ _jsx("div", {
22
+ children: "Edit query configuration"
23
+ })
24
+ },
25
+ {
26
+ label: 'Settings',
27
+ content: /*#__PURE__*/ _jsx("div", {
28
+ children: "Edit settings configuration"
29
+ })
30
+ },
31
+ {
32
+ label: 'JSON',
33
+ content: /*#__PURE__*/ _jsx("div", {
34
+ children: "JSON editor"
35
+ })
36
+ }
37
+ ];
18
38
  const renderTabs = (otherTabs)=>{
39
+ const tabs = otherTabs !== null && otherTabs !== void 0 ? otherTabs : mockTabs;
19
40
  render(/*#__PURE__*/ _jsx(OptionsEditorTabs, {
20
- tabs: {
21
- query: {
22
- content: /*#__PURE__*/ _jsx("div", {
23
- children: "Edit query configuration"
24
- })
25
- },
26
- settings: {
27
- content: /*#__PURE__*/ _jsx("div", {
28
- children: "Edit settings configuration"
29
- })
30
- },
31
- json: {
32
- content: /*#__PURE__*/ _jsx("div", {
33
- children: "JSON editor"
34
- })
35
- },
36
- other: otherTabs
37
- }
41
+ tabs: tabs
38
42
  }));
39
43
  };
40
- const renderCustomTabs = ()=>{
41
- renderTabs([
42
- {
43
- id: 'tableCols',
44
- label: 'Table columns',
45
- content: /*#__PURE__*/ _jsx("div", {
46
- children: "custom table column"
47
- })
48
- },
49
- {
50
- id: 'tableOpts',
51
- label: 'Table options',
52
- content: /*#__PURE__*/ _jsx("div", {
53
- children: "custom table options"
54
- })
55
- }
56
- ]);
57
- };
58
44
  it('renders all specified tabs in a tab list', ()=>{
59
45
  renderTabs();
60
46
  const tabList = screen.getByRole('tablist');
@@ -100,59 +86,13 @@ describe('OptionsEditorTabs', ()=>{
100
86
  const activeTabPanel = screen.getByRole('tabpanel');
101
87
  expect(activeTabPanel).toHaveTextContent('settings configuration');
102
88
  });
103
- it('renders custom tabs between visual tabs and json editor', ()=>{
104
- renderCustomTabs();
89
+ it('renders tabs in correct order', ()=>{
90
+ renderTabs();
105
91
  const tabList = screen.getByRole('tablist');
106
92
  const tabs = getAllByRole(tabList, 'tab');
107
- expect(tabs).toHaveLength(5);
93
+ expect(tabs).toHaveLength(3);
108
94
  expect(tabs[0]).toHaveTextContent('Query');
109
95
  expect(tabs[1]).toHaveTextContent('Settings');
110
- expect(tabs[2]).toHaveTextContent('Table column');
111
- expect(tabs[3]).toHaveTextContent('Table options');
112
- expect(tabs[4]).toHaveTextContent('JSON');
113
- });
114
- it('shows the correct content when selecting a custom tab', ()=>{
115
- renderCustomTabs();
116
- const tableColTab = screen.getByRole('tab', {
117
- name: 'Table columns'
118
- });
119
- userEvent.click(tableColTab);
120
- const activeTab = screen.getByRole('tab', {
121
- selected: true
122
- });
123
- expect(activeTab).toBe(tableColTab);
124
- const activeTabPanel = screen.getByRole('tabpanel');
125
- expect(activeTabPanel).toHaveTextContent('custom table column');
126
- });
127
- it('only renders common tabs that are specified', ()=>{
128
- render(/*#__PURE__*/ _jsx(OptionsEditorTabs, {
129
- tabs: {
130
- settings: {
131
- content: /*#__PURE__*/ _jsx("div", {
132
- children: "settings are alone"
133
- })
134
- },
135
- json: {
136
- content: /*#__PURE__*/ _jsx("div", {
137
- children: "JSON is at the end"
138
- })
139
- },
140
- other: [
141
- {
142
- id: 'custom',
143
- label: 'Another tab',
144
- content: /*#__PURE__*/ _jsx("div", {
145
- children: "another tab content"
146
- })
147
- }
148
- ]
149
- }
150
- }));
151
- const tabList = screen.getByRole('tablist');
152
- const tabs = getAllByRole(tabList, 'tab');
153
- expect(tabs).toHaveLength(3);
154
- expect(tabs[0]).toHaveTextContent('Settings');
155
- expect(tabs[1]).toHaveTextContent('Another tab');
156
96
  expect(tabs[2]).toHaveTextContent('JSON');
157
97
  });
158
98
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.test.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 { screen, render, getAllByRole } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\n\nimport { OptionsEditorTabs, OptionsEditorTabsProps } from './OptionsEditorTabs';\n\ndescribe('OptionsEditorTabs', () => {\n const renderTabs = (otherTabs?: OptionsEditorTabsProps['tabs']['other']) => {\n render(\n <OptionsEditorTabs\n tabs={{\n query: {\n content: <div>Edit query configuration</div>,\n },\n settings: {\n content: <div>Edit settings configuration</div>,\n },\n json: {\n content: <div>JSON editor</div>,\n },\n other: otherTabs,\n }}\n />\n );\n };\n\n const renderCustomTabs = () => {\n renderTabs([\n {\n id: 'tableCols',\n label: 'Table columns',\n content: <div>custom table column</div>,\n },\n {\n id: 'tableOpts',\n label: 'Table options',\n content: <div>custom table options</div>,\n },\n ]);\n };\n\n it('renders all specified tabs in a tab list', () => {\n renderTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n\n it('defaults to selecting the first tab', () => {\n renderTabs();\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toHaveTextContent('Query');\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('query configuration');\n });\n\n it('switches selected tab on click', () => {\n renderTabs();\n const jsonTab = screen.getByRole('tab', { name: 'JSON' });\n userEvent.click(jsonTab);\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(jsonTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('JSON editor');\n });\n\n it('switches selected tab on keyboard interactions', () => {\n renderTabs();\n const vizTab = screen.getByRole('tab', { name: 'Settings' });\n userEvent.tab();\n userEvent.keyboard('{arrowright}{space}');\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(vizTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('settings configuration');\n });\n\n it('renders custom tabs between visual tabs and json editor', () => {\n renderCustomTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(5);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('Table column');\n expect(tabs[3]).toHaveTextContent('Table options');\n expect(tabs[4]).toHaveTextContent('JSON');\n });\n\n it('shows the correct content when selecting a custom tab', () => {\n renderCustomTabs();\n\n const tableColTab = screen.getByRole('tab', { name: 'Table columns' });\n userEvent.click(tableColTab);\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(tableColTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('custom table column');\n });\n\n it('only renders common tabs that are specified', () => {\n render(\n <OptionsEditorTabs\n tabs={{\n settings: {\n content: <div>settings are alone</div>,\n },\n json: {\n content: <div>JSON is at the end</div>,\n },\n other: [\n {\n id: 'custom',\n label: 'Another tab',\n content: <div>another tab content</div>,\n },\n ],\n }}\n />\n );\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Settings');\n expect(tabs[1]).toHaveTextContent('Another tab');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n});\n"],"names":["screen","render","getAllByRole","userEvent","OptionsEditorTabs","describe","renderTabs","otherTabs","tabs","query","content","div","settings","json","other","renderCustomTabs","id","label","it","tabList","getByRole","expect","toHaveLength","toHaveTextContent","activeTab","selected","activeTabPanel","jsonTab","name","click","toBe","vizTab","tab","keyboard","tableColTab"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.test.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 { screen, render, getAllByRole } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\n\nimport { OptionsEditorTabs, OptionsEditorTabsProps } from './OptionsEditorTabs';\n\ndescribe('OptionsEditorTabs', () => {\n const mockTabs: OptionsEditorTabsProps['tabs'] = [\n {\n label: 'Query',\n content: <div>Edit query configuration</div>,\n },\n {\n label: 'Settings',\n content: <div>Edit settings configuration</div>,\n },\n {\n label: 'JSON',\n content: <div>JSON editor</div>,\n },\n ];\n const renderTabs = (otherTabs?: OptionsEditorTabsProps['tabs']) => {\n const tabs = otherTabs ?? mockTabs;\n render(<OptionsEditorTabs tabs={tabs} />);\n };\n\n it('renders all specified tabs in a tab list', () => {\n renderTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n\n it('defaults to selecting the first tab', () => {\n renderTabs();\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toHaveTextContent('Query');\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('query configuration');\n });\n\n it('switches selected tab on click', () => {\n renderTabs();\n const jsonTab = screen.getByRole('tab', { name: 'JSON' });\n userEvent.click(jsonTab);\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(jsonTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('JSON editor');\n });\n\n it('switches selected tab on keyboard interactions', () => {\n renderTabs();\n const vizTab = screen.getByRole('tab', { name: 'Settings' });\n userEvent.tab();\n userEvent.keyboard('{arrowright}{space}');\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(vizTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('settings configuration');\n });\n\n it('renders tabs in correct order', () => {\n renderTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n});\n"],"names":["screen","render","getAllByRole","userEvent","OptionsEditorTabs","describe","mockTabs","label","content","div","renderTabs","otherTabs","tabs","it","tabList","getByRole","expect","toHaveLength","toHaveTextContent","activeTab","selected","activeTabPanel","jsonTab","name","click","toBe","vizTab","tab","keyboard"],"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;AAAA,SAASA,MAAM,EAAEC,MAAM,EAAEC,YAAY,QAAQ,wBAAwB,CAAC;AACtE,OAAOC,SAAS,MAAM,6BAA6B,CAAC;AAEpD,SAASC,iBAAiB,QAAgC,qBAAqB,CAAC;AAEhFC,QAAQ,CAAC,mBAAmB,EAAE,IAAM;IAClC,MAAMC,QAAQ,GAAmC;QAC/C;YACEC,KAAK,EAAE,OAAO;YACdC,OAAO,gBAAE,KAACC,KAAG;0BAAC,0BAAwB;cAAM;SAC7C;QACD;YACEF,KAAK,EAAE,UAAU;YACjBC,OAAO,gBAAE,KAACC,KAAG;0BAAC,6BAA2B;cAAM;SAChD;QACD;YACEF,KAAK,EAAE,MAAM;YACbC,OAAO,gBAAE,KAACC,KAAG;0BAAC,aAAW;cAAM;SAChC;KACF,AAAC;IACF,MAAMC,UAAU,GAAG,CAACC,SAA0C,GAAK;QACjE,MAAMC,IAAI,GAAGD,SAAS,aAATA,SAAS,cAATA,SAAS,GAAIL,QAAQ,AAAC;QACnCL,MAAM,eAAC,KAACG,iBAAiB;YAACQ,IAAI,EAAEA,IAAI;UAAI,CAAC,CAAC;IAC5C,CAAC,AAAC;IAEFC,EAAE,CAAC,0CAA0C,EAAE,IAAM;QACnDH,UAAU,EAAE,CAAC;QAEb,MAAMI,OAAO,GAAGd,MAAM,CAACe,SAAS,CAAC,SAAS,CAAC,AAAC;QAC5C,MAAMH,IAAI,GAAGV,YAAY,CAACY,OAAO,EAAE,KAAK,CAAC,AAAC;QAC1CE,MAAM,CAACJ,IAAI,CAAC,CAACK,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7BD,MAAM,CAACJ,IAAI,CAAC,CAAC,CAAC,CAAC,CAACM,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC3CF,MAAM,CAACJ,IAAI,CAAC,CAAC,CAAC,CAAC,CAACM,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9CF,MAAM,CAACJ,IAAI,CAAC,CAAC,CAAC,CAAC,CAACM,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEHL,EAAE,CAAC,qCAAqC,EAAE,IAAM;QAC9CH,UAAU,EAAE,CAAC;QAEb,MAAMS,SAAS,GAAGnB,MAAM,CAACe,SAAS,CAAC,KAAK,EAAE;YACxCK,QAAQ,EAAE,IAAI;SACf,CAAC,AAAC;QACHJ,MAAM,CAACG,SAAS,CAAC,CAACD,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAE7C,MAAMG,cAAc,GAAGrB,MAAM,CAACe,SAAS,CAAC,UAAU,CAAC,AAAC;QACpDC,MAAM,CAACK,cAAc,CAAC,CAACH,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEHL,EAAE,CAAC,gCAAgC,EAAE,IAAM;QACzCH,UAAU,EAAE,CAAC;QACb,MAAMY,OAAO,GAAGtB,MAAM,CAACe,SAAS,CAAC,KAAK,EAAE;YAAEQ,IAAI,EAAE,MAAM;SAAE,CAAC,AAAC;QAC1DpB,SAAS,CAACqB,KAAK,CAACF,OAAO,CAAC,CAAC;QAEzB,MAAMH,SAAS,GAAGnB,MAAM,CAACe,SAAS,CAAC,KAAK,EAAE;YACxCK,QAAQ,EAAE,IAAI;SACf,CAAC,AAAC;QACHJ,MAAM,CAACG,SAAS,CAAC,CAACM,IAAI,CAACH,OAAO,CAAC,CAAC;QAEhC,MAAMD,cAAc,GAAGrB,MAAM,CAACe,SAAS,CAAC,UAAU,CAAC,AAAC;QACpDC,MAAM,CAACK,cAAc,CAAC,CAACH,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEHL,EAAE,CAAC,gDAAgD,EAAE,IAAM;QACzDH,UAAU,EAAE,CAAC;QACb,MAAMgB,MAAM,GAAG1B,MAAM,CAACe,SAAS,CAAC,KAAK,EAAE;YAAEQ,IAAI,EAAE,UAAU;SAAE,CAAC,AAAC;QAC7DpB,SAAS,CAACwB,GAAG,EAAE,CAAC;QAChBxB,SAAS,CAACyB,QAAQ,CAAC,qBAAqB,CAAC,CAAC;QAE1C,MAAMT,SAAS,GAAGnB,MAAM,CAACe,SAAS,CAAC,KAAK,EAAE;YACxCK,QAAQ,EAAE,IAAI;SACf,CAAC,AAAC;QACHJ,MAAM,CAACG,SAAS,CAAC,CAACM,IAAI,CAACC,MAAM,CAAC,CAAC;QAE/B,MAAML,cAAc,GAAGrB,MAAM,CAACe,SAAS,CAAC,UAAU,CAAC,AAAC;QACpDC,MAAM,CAACK,cAAc,CAAC,CAACH,iBAAiB,CAAC,wBAAwB,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEHL,EAAE,CAAC,+BAA+B,EAAE,IAAM;QACxCH,UAAU,EAAE,CAAC;QAEb,MAAMI,OAAO,GAAGd,MAAM,CAACe,SAAS,CAAC,SAAS,CAAC,AAAC;QAC5C,MAAMH,IAAI,GAAGV,YAAY,CAACY,OAAO,EAAE,KAAK,CAAC,AAAC;QAC1CE,MAAM,CAACJ,IAAI,CAAC,CAACK,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7BD,MAAM,CAACJ,IAAI,CAAC,CAAC,CAAC,CAAC,CAACM,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC3CF,MAAM,CAACJ,IAAI,CAAC,CAAC,CAAC,CAAC,CAACM,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9CF,MAAM,CAACJ,IAAI,CAAC,CAAC,CAAC,CAAC,CAACM,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PluginSpecEditor.d.ts","sourceRoot":"","sources":["../../src/components/PluginSpecEditor.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAG1D,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB,CAAC,WAAW,CAAC;IAC5E,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,sBAmB5D"}
1
+ {"version":3,"file":"PluginSpecEditor.d.ts","sourceRoot":"","sources":["../../src/components/PluginSpecEditor.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAe,UAAU,EAAE,MAAM,UAAU,CAAC;AAIvE,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB,CAAC,WAAW,CAAC;IAC5E,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,sBA8C5D"}
@@ -11,8 +11,9 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
- import { ErrorAlert } from '@perses-dev/components';
14
+ import { ErrorAlert, JSONEditor } from '@perses-dev/components';
15
15
  import { usePlugin } from '../runtime';
16
+ import { OptionsEditorTabs } from './OptionsEditorTabs';
16
17
  export function PluginSpecEditor(props) {
17
18
  const { pluginType , pluginKind , ...others } = props;
18
19
  const { data: plugin , isLoading , error } = usePlugin(pluginType, pluginKind);
@@ -26,12 +27,45 @@ export function PluginSpecEditor(props) {
26
27
  return null;
27
28
  }
28
29
  if (plugin === undefined) {
29
- throw new Error(`Missing OptionsEditorComponent for ${pluginType} plugin with kind '${pluginKind}'`);
30
+ throw new Error(`Missing implementation for ${pluginType} plugin with kind '${pluginKind}'`);
31
+ }
32
+ if (pluginType === 'Panel') {
33
+ const { PanelQueryEditorComponent , panelOptionsEditorComponents } = plugin;
34
+ let tabs = [];
35
+ if (PanelQueryEditorComponent !== undefined) {
36
+ tabs.push({
37
+ label: 'Query',
38
+ content: /*#__PURE__*/ _jsx(PanelQueryEditorComponent, {
39
+ ...others
40
+ })
41
+ });
42
+ }
43
+ if (panelOptionsEditorComponents !== undefined) {
44
+ tabs = tabs.concat(panelOptionsEditorComponents.map(({ label , content: OptionsEditorComponent })=>({
45
+ label,
46
+ content: /*#__PURE__*/ _jsx(OptionsEditorComponent, {
47
+ ...others
48
+ })
49
+ })));
50
+ }
51
+ // always show json editor by default
52
+ tabs.push({
53
+ label: 'JSON',
54
+ content: /*#__PURE__*/ _jsx(JSONEditor, {
55
+ ...others
56
+ })
57
+ });
58
+ return /*#__PURE__*/ _jsx(OptionsEditorTabs, {
59
+ tabs: tabs
60
+ });
30
61
  }
31
62
  const { OptionsEditorComponent } = plugin;
32
- return /*#__PURE__*/ _jsx(OptionsEditorComponent, {
33
- ...others
34
- });
63
+ if (OptionsEditorComponent !== undefined) {
64
+ return /*#__PURE__*/ _jsx(OptionsEditorComponent, {
65
+ ...others
66
+ });
67
+ }
68
+ return null;
35
69
  }
36
70
 
37
71
  //# sourceMappingURL=PluginSpecEditor.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/PluginSpecEditor.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 { ErrorAlert } from '@perses-dev/components';\nimport { UnknownSpec } from '@perses-dev/core';\nimport { OptionsEditorProps, PluginType } from '../model';\nimport { usePlugin } from '../runtime';\n\nexport interface PluginSpecEditorProps extends OptionsEditorProps<UnknownSpec> {\n pluginType: PluginType;\n pluginKind: string;\n}\n\nexport function PluginSpecEditor(props: PluginSpecEditorProps) {\n const { pluginType, pluginKind, ...others } = props;\n const { data: plugin, isLoading, error } = usePlugin(pluginType, pluginKind);\n\n if (error) {\n return <ErrorAlert error={error} />;\n }\n\n // TODO: Proper loading indicator\n if (isLoading) {\n return null;\n }\n\n if (plugin === undefined) {\n throw new Error(`Missing OptionsEditorComponent for ${pluginType} plugin with kind '${pluginKind}'`);\n }\n\n const { OptionsEditorComponent } = plugin;\n return <OptionsEditorComponent {...others} />;\n}\n"],"names":["ErrorAlert","usePlugin","PluginSpecEditor","props","pluginType","pluginKind","others","data","plugin","isLoading","error","undefined","Error","OptionsEditorComponent"],"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;AAAA,SAASA,UAAU,QAAQ,wBAAwB,CAAC;AAGpD,SAASC,SAAS,QAAQ,YAAY,CAAC;AAOvC,OAAO,SAASC,gBAAgB,CAACC,KAA4B,EAAE;IAC7D,MAAM,EAAEC,UAAU,CAAA,EAAEC,UAAU,CAAA,EAAE,GAAGC,MAAM,EAAE,GAAGH,KAAK,AAAC;IACpD,MAAM,EAAEI,IAAI,EAAEC,MAAM,CAAA,EAAEC,SAAS,CAAA,EAAEC,KAAK,CAAA,EAAE,GAAGT,SAAS,CAACG,UAAU,EAAEC,UAAU,CAAC,AAAC;IAE7E,IAAIK,KAAK,EAAE;QACT,qBAAO,KAACV,UAAU;YAACU,KAAK,EAAEA,KAAK;UAAI,CAAC;IACtC,CAAC;IAED,iCAAiC;IACjC,IAAID,SAAS,EAAE;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAID,MAAM,KAAKG,SAAS,EAAE;QACxB,MAAM,IAAIC,KAAK,CAAC,CAAC,mCAAmC,EAAER,UAAU,CAAC,mBAAmB,EAAEC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACvG,CAAC;IAED,MAAM,EAAEQ,sBAAsB,CAAA,EAAE,GAAGL,MAAM,AAAC;IAC1C,qBAAO,KAACK,sBAAsB;QAAE,GAAGP,MAAM;MAAI,CAAC;AAChD,CAAC"}
1
+ {"version":3,"sources":["../../src/components/PluginSpecEditor.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 { ErrorAlert, JSONEditor } from '@perses-dev/components';\nimport { UnknownSpec } from '@perses-dev/core';\nimport { OptionsEditorProps, PanelPlugin, PluginType } from '../model';\nimport { usePlugin } from '../runtime';\nimport { OptionsEditorTabsProps, OptionsEditorTabs } from './OptionsEditorTabs';\n\nexport interface PluginSpecEditorProps extends OptionsEditorProps<UnknownSpec> {\n pluginType: PluginType;\n pluginKind: string;\n}\n\nexport function PluginSpecEditor(props: PluginSpecEditorProps) {\n const { pluginType, pluginKind, ...others } = props;\n const { data: plugin, isLoading, error } = usePlugin(pluginType, pluginKind);\n\n if (error) {\n return <ErrorAlert error={error} />;\n }\n\n // TODO: Proper loading indicator\n if (isLoading) {\n return null;\n }\n\n if (plugin === undefined) {\n throw new Error(`Missing implementation for ${pluginType} plugin with kind '${pluginKind}'`);\n }\n\n if (pluginType === 'Panel') {\n const { PanelQueryEditorComponent, panelOptionsEditorComponents } = plugin as PanelPlugin;\n let tabs: OptionsEditorTabsProps['tabs'] = [];\n if (PanelQueryEditorComponent !== undefined) {\n tabs.push({ label: 'Query', content: <PanelQueryEditorComponent {...others} /> });\n }\n\n if (panelOptionsEditorComponents !== undefined) {\n tabs = tabs.concat(\n panelOptionsEditorComponents.map(({ label, content: OptionsEditorComponent }) => ({\n label,\n content: <OptionsEditorComponent {...others} />,\n }))\n );\n }\n\n // always show json editor by default\n tabs.push({ label: 'JSON', content: <JSONEditor {...others} /> });\n\n return <OptionsEditorTabs tabs={tabs} />;\n }\n\n const { OptionsEditorComponent } = plugin;\n\n if (OptionsEditorComponent !== undefined) {\n return <OptionsEditorComponent {...others} />;\n }\n\n return null;\n}\n"],"names":["ErrorAlert","JSONEditor","usePlugin","OptionsEditorTabs","PluginSpecEditor","props","pluginType","pluginKind","others","data","plugin","isLoading","error","undefined","Error","PanelQueryEditorComponent","panelOptionsEditorComponents","tabs","push","label","content","concat","map","OptionsEditorComponent"],"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;AAAA,SAASA,UAAU,EAAEC,UAAU,QAAQ,wBAAwB,CAAC;AAGhE,SAASC,SAAS,QAAQ,YAAY,CAAC;AACvC,SAAiCC,iBAAiB,QAAQ,qBAAqB,CAAC;AAOhF,OAAO,SAASC,gBAAgB,CAACC,KAA4B,EAAE;IAC7D,MAAM,EAAEC,UAAU,CAAA,EAAEC,UAAU,CAAA,EAAE,GAAGC,MAAM,EAAE,GAAGH,KAAK,AAAC;IACpD,MAAM,EAAEI,IAAI,EAAEC,MAAM,CAAA,EAAEC,SAAS,CAAA,EAAEC,KAAK,CAAA,EAAE,GAAGV,SAAS,CAACI,UAAU,EAAEC,UAAU,CAAC,AAAC;IAE7E,IAAIK,KAAK,EAAE;QACT,qBAAO,KAACZ,UAAU;YAACY,KAAK,EAAEA,KAAK;UAAI,CAAC;IACtC,CAAC;IAED,iCAAiC;IACjC,IAAID,SAAS,EAAE;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAID,MAAM,KAAKG,SAAS,EAAE;QACxB,MAAM,IAAIC,KAAK,CAAC,CAAC,2BAA2B,EAAER,UAAU,CAAC,mBAAmB,EAAEC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED,IAAID,UAAU,KAAK,OAAO,EAAE;QAC1B,MAAM,EAAES,yBAAyB,CAAA,EAAEC,4BAA4B,CAAA,EAAE,GAAGN,MAAM,AAAe,AAAC;QAC1F,IAAIO,IAAI,GAAmC,EAAE,AAAC;QAC9C,IAAIF,yBAAyB,KAAKF,SAAS,EAAE;YAC3CI,IAAI,CAACC,IAAI,CAAC;gBAAEC,KAAK,EAAE,OAAO;gBAAEC,OAAO,gBAAE,KAACL,yBAAyB;oBAAE,GAAGP,MAAM;kBAAI;aAAE,CAAC,CAAC;QACpF,CAAC;QAED,IAAIQ,4BAA4B,KAAKH,SAAS,EAAE;YAC9CI,IAAI,GAAGA,IAAI,CAACI,MAAM,CAChBL,4BAA4B,CAACM,GAAG,CAAC,CAAC,EAAEH,KAAK,CAAA,EAAEC,OAAO,EAAEG,sBAAsB,CAAA,EAAE,GAAM,CAAA;oBAChFJ,KAAK;oBACLC,OAAO,gBAAE,KAACG,sBAAsB;wBAAE,GAAGf,MAAM;sBAAI;iBAChD,CAAA,AAAC,CAAC,CACJ,CAAC;QACJ,CAAC;QAED,qCAAqC;QACrCS,IAAI,CAACC,IAAI,CAAC;YAAEC,KAAK,EAAE,MAAM;YAAEC,OAAO,gBAAE,KAACnB,UAAU;gBAAE,GAAGO,MAAM;cAAI;SAAE,CAAC,CAAC;QAElE,qBAAO,KAACL,iBAAiB;YAACc,IAAI,EAAEA,IAAI;UAAI,CAAC;IAC3C,CAAC;IAED,MAAM,EAAEM,sBAAsB,CAAA,EAAE,GAAGb,MAAM,AAAC;IAE1C,IAAIa,sBAAsB,KAAKV,SAAS,EAAE;QACxC,qBAAO,KAACU,sBAAsB;YAAE,GAAGf,MAAM;UAAI,CAAC;IAChD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -21,15 +21,37 @@ describe('PluginSpecEditor', ()=>{
21
21
  ...props
22
22
  }));
23
23
  };
24
- it('shows the options editor component for a plugin', async ()=>{
25
- renderComponent({
26
- pluginType: 'Panel',
27
- pluginKind: 'BertPanel1',
28
- value: {},
29
- onChange: jest.fn()
24
+ describe('Panel plugin', ()=>{
25
+ it('should show query and json editors', async ()=>{
26
+ renderComponent({
27
+ pluginType: 'Panel',
28
+ pluginKind: 'BertPanel1',
29
+ value: {},
30
+ onChange: jest.fn()
31
+ });
32
+ const queryTab = await screen.findByLabelText('Query');
33
+ expect(queryTab).toBeInTheDocument();
34
+ const editor = await screen.findByLabelText('BertPanel1 editor');
35
+ expect(editor).toBeInTheDocument();
36
+ const jsonEditor = await screen.findByLabelText('JSON');
37
+ expect(jsonEditor).toBeInTheDocument();
38
+ });
39
+ it('should display other options editor components', async ()=>{
40
+ renderComponent({
41
+ pluginType: 'Panel',
42
+ pluginKind: 'BertPanel2',
43
+ value: {},
44
+ onChange: jest.fn()
45
+ });
46
+ const settingsTab = await screen.findByLabelText('Settings');
47
+ expect(settingsTab).toBeInTheDocument();
48
+ const editor = await screen.findByLabelText('BertPanel2 editor');
49
+ expect(editor).toBeInTheDocument();
50
+ const customTab = await screen.findByLabelText('Custom Tab');
51
+ expect(customTab).toBeInTheDocument();
52
+ const jsonEditor = await screen.findByLabelText('JSON');
53
+ expect(jsonEditor).toBeInTheDocument();
30
54
  });
31
- const editor = await screen.findByLabelText('BertPanel1 editor');
32
- expect(editor).toBeInTheDocument();
33
55
  });
34
56
  it('propagates value changes', async ()=>{
35
57
  const onChange = jest.fn();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/PluginSpecEditor.test.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 userEvent from '@testing-library/user-event';\nimport { screen } from '@testing-library/react';\nimport { renderWithContext } from '../test';\nimport { PluginSpecEditor, PluginSpecEditorProps } from './PluginSpecEditor';\n\ndescribe('PluginSpecEditor', () => {\n const renderComponent = (props: PluginSpecEditorProps) => {\n renderWithContext(<PluginSpecEditor {...props} />);\n };\n\n it('shows the options editor component for a plugin', async () => {\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel1', value: {}, onChange: jest.fn() });\n const editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toBeInTheDocument();\n });\n\n it('propagates value changes', async () => {\n const onChange = jest.fn();\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel1', value: { option1: 'Option1Value' }, onChange });\n\n const editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toHaveValue('Option1Value');\n userEvent.clear(editor);\n expect(onChange).toHaveBeenCalledWith({ option1: '' });\n });\n\n it('shows an error if plugin fails to load', async () => {\n renderComponent({ pluginType: 'Variable', pluginKind: 'DoesNotExist', value: {}, onChange: jest.fn() });\n const errorAlert = await screen.findByRole('alert');\n expect(errorAlert).toHaveTextContent(/doesnotexist/i);\n });\n});\n"],"names":["userEvent","screen","renderWithContext","PluginSpecEditor","describe","renderComponent","props","it","pluginType","pluginKind","value","onChange","jest","fn","editor","findByLabelText","expect","toBeInTheDocument","option1","toHaveValue","clear","toHaveBeenCalledWith","errorAlert","findByRole","toHaveTextContent"],"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;AAAA,OAAOA,SAAS,MAAM,6BAA6B,CAAC;AACpD,SAASC,MAAM,QAAQ,wBAAwB,CAAC;AAChD,SAASC,iBAAiB,QAAQ,SAAS,CAAC;AAC5C,SAASC,gBAAgB,QAA+B,oBAAoB,CAAC;AAE7EC,QAAQ,CAAC,kBAAkB,EAAE,IAAM;IACjC,MAAMC,eAAe,GAAG,CAACC,KAA4B,GAAK;QACxDJ,iBAAiB,eAAC,KAACC,gBAAgB;YAAE,GAAGG,KAAK;UAAI,CAAC,CAAC;IACrD,CAAC,AAAC;IAEFC,EAAE,CAAC,iDAAiD,EAAE,UAAY;QAChEF,eAAe,CAAC;YAAEG,UAAU,EAAE,OAAO;YAAEC,UAAU,EAAE,YAAY;YAAEC,KAAK,EAAE,EAAE;YAAEC,QAAQ,EAAEC,IAAI,CAACC,EAAE,EAAE;SAAE,CAAC,CAAC;QACnG,MAAMC,MAAM,GAAG,MAAMb,MAAM,CAACc,eAAe,CAAC,mBAAmB,CAAC,AAAC;QACjEC,MAAM,CAACF,MAAM,CAAC,CAACG,iBAAiB,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEHV,EAAE,CAAC,0BAA0B,EAAE,UAAY;QACzC,MAAMI,QAAQ,GAAGC,IAAI,CAACC,EAAE,EAAE,AAAC;QAC3BR,eAAe,CAAC;YAAEG,UAAU,EAAE,OAAO;YAAEC,UAAU,EAAE,YAAY;YAAEC,KAAK,EAAE;gBAAEQ,OAAO,EAAE,cAAc;aAAE;YAAEP,QAAQ;SAAE,CAAC,CAAC;QAEjH,MAAMG,MAAM,GAAG,MAAMb,MAAM,CAACc,eAAe,CAAC,mBAAmB,CAAC,AAAC;QACjEC,MAAM,CAACF,MAAM,CAAC,CAACK,WAAW,CAAC,cAAc,CAAC,CAAC;QAC3CnB,SAAS,CAACoB,KAAK,CAACN,MAAM,CAAC,CAAC;QACxBE,MAAM,CAACL,QAAQ,CAAC,CAACU,oBAAoB,CAAC;YAAEH,OAAO,EAAE,EAAE;SAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEHX,EAAE,CAAC,wCAAwC,EAAE,UAAY;QACvDF,eAAe,CAAC;YAAEG,UAAU,EAAE,UAAU;YAAEC,UAAU,EAAE,cAAc;YAAEC,KAAK,EAAE,EAAE;YAAEC,QAAQ,EAAEC,IAAI,CAACC,EAAE,EAAE;SAAE,CAAC,CAAC;QACxG,MAAMS,UAAU,GAAG,MAAMrB,MAAM,CAACsB,UAAU,CAAC,OAAO,CAAC,AAAC;QACpDP,MAAM,CAACM,UAAU,CAAC,CAACE,iBAAiB,iBAAiB,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"sources":["../../src/components/PluginSpecEditor.test.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 userEvent from '@testing-library/user-event';\nimport { screen } from '@testing-library/react';\nimport { renderWithContext } from '../test';\nimport { PluginSpecEditor, PluginSpecEditorProps } from './PluginSpecEditor';\n\ndescribe('PluginSpecEditor', () => {\n const renderComponent = (props: PluginSpecEditorProps) => {\n renderWithContext(<PluginSpecEditor {...props} />);\n };\n\n describe('Panel plugin', () => {\n it('should show query and json editors', async () => {\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel1', value: {}, onChange: jest.fn() });\n const queryTab = await screen.findByLabelText('Query');\n expect(queryTab).toBeInTheDocument();\n const editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toBeInTheDocument();\n const jsonEditor = await screen.findByLabelText('JSON');\n expect(jsonEditor).toBeInTheDocument();\n });\n\n it('should display other options editor components', async () => {\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel2', value: {}, onChange: jest.fn() });\n const settingsTab = await screen.findByLabelText('Settings');\n expect(settingsTab).toBeInTheDocument();\n const editor = await screen.findByLabelText('BertPanel2 editor');\n expect(editor).toBeInTheDocument();\n const customTab = await screen.findByLabelText('Custom Tab');\n expect(customTab).toBeInTheDocument();\n const jsonEditor = await screen.findByLabelText('JSON');\n expect(jsonEditor).toBeInTheDocument();\n });\n });\n\n it('propagates value changes', async () => {\n const onChange = jest.fn();\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel1', value: { option1: 'Option1Value' }, onChange });\n\n const editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toHaveValue('Option1Value');\n userEvent.clear(editor);\n expect(onChange).toHaveBeenCalledWith({ option1: '' });\n });\n\n it('shows an error if plugin fails to load', async () => {\n renderComponent({ pluginType: 'Variable', pluginKind: 'DoesNotExist', value: {}, onChange: jest.fn() });\n const errorAlert = await screen.findByRole('alert');\n expect(errorAlert).toHaveTextContent(/doesnotexist/i);\n });\n});\n"],"names":["userEvent","screen","renderWithContext","PluginSpecEditor","describe","renderComponent","props","it","pluginType","pluginKind","value","onChange","jest","fn","queryTab","findByLabelText","expect","toBeInTheDocument","editor","jsonEditor","settingsTab","customTab","option1","toHaveValue","clear","toHaveBeenCalledWith","errorAlert","findByRole","toHaveTextContent"],"mappings":"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"}
@@ -1,11 +1,23 @@
1
- /// <reference types="react" />
2
1
  import { UnknownSpec } from '@perses-dev/core';
3
- import { Plugin } from './plugin-base';
2
+ import React from 'react';
3
+ import { OptionsEditorTab } from '../components';
4
+ import { OptionsEditorProps, Plugin } from './plugin-base';
5
+ export declare type PanelOptionsEditorComponent<T> = Pick<OptionsEditorTab, 'label'> & {
6
+ content: React.ComponentType<OptionsEditorProps<T>>;
7
+ };
4
8
  /**
5
9
  * Plugin the provides custom visualizations inside of a Panel.
6
10
  */
7
11
  export interface PanelPlugin<Spec = UnknownSpec> extends Plugin<Spec> {
8
12
  PanelComponent: React.ComponentType<PanelProps<Spec>>;
13
+ /**
14
+ * React component for the content of "Query" tab
15
+ */
16
+ PanelQueryEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;
17
+ /**
18
+ * React components for custom tabs
19
+ */
20
+ panelOptionsEditorComponents?: Array<PanelOptionsEditorComponent<Spec>>;
9
21
  }
10
22
  /**
11
23
  * The props provided by Perses to a panel plugin's PanelComponent.
@@ -1 +1 @@
1
- {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/model/panels.ts"],"names":[],"mappings":";AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,IAAI,GAAG,WAAW,CAAE,SAAQ,MAAM,CAAC,IAAI,CAAC;IACnE,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,IAAI;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,iBAAiB,CAAC,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH"}
1
+ {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/model/panels.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE3D,oBAAY,2BAA2B,CAAC,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG;IAC7E,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;CACrD,CAAC;AACF;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,IAAI,GAAG,WAAW,CAAE,SAAQ,MAAM,CAAC,IAAI,CAAC;IACnE,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACtD;;OAEG;IACH,yBAAyB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E;;OAEG;IACH,4BAA4B,CAAC,EAAE,KAAK,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;CACzE;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,IAAI;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,iBAAiB,CAAC,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH"}
@@ -10,6 +10,6 @@
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
- export { };
13
+ import React from 'react';
14
14
 
15
15
  //# sourceMappingURL=panels.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/model/panels.ts"],"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 { UnknownSpec } from '@perses-dev/core';\nimport { Plugin } from './plugin-base';\n\n/**\n * Plugin the provides custom visualizations inside of a Panel.\n */\nexport interface PanelPlugin<Spec = UnknownSpec> extends Plugin<Spec> {\n PanelComponent: React.ComponentType<PanelProps<Spec>>;\n}\n\n/**\n * The props provided by Perses to a panel plugin's PanelComponent.\n */\nexport interface PanelProps<Spec> {\n spec: Spec;\n contentDimensions?: {\n width: number;\n height: number;\n };\n}\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,WAmBC"}
1
+ {"version":3,"sources":["../../src/model/panels.ts"],"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 { UnknownSpec } from '@perses-dev/core';\nimport React from 'react';\nimport { OptionsEditorTab } from '../components';\nimport { OptionsEditorProps, Plugin } from './plugin-base';\n\nexport type PanelOptionsEditorComponent<T> = Pick<OptionsEditorTab, 'label'> & {\n content: React.ComponentType<OptionsEditorProps<T>>;\n};\n/**\n * Plugin the provides custom visualizations inside of a Panel.\n */\nexport interface PanelPlugin<Spec = UnknownSpec> extends Plugin<Spec> {\n PanelComponent: React.ComponentType<PanelProps<Spec>>;\n /**\n * React component for the content of \"Query\" tab\n */\n PanelQueryEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;\n /**\n * React components for custom tabs\n */\n panelOptionsEditorComponents?: Array<PanelOptionsEditorComponent<Spec>>;\n}\n\n/**\n * The props provided by Perses to a panel plugin's PanelComponent.\n */\nexport interface PanelProps<Spec> {\n spec: Spec;\n contentDimensions?: {\n width: number;\n height: number;\n };\n}\n"],"names":["React"],"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;AAGjC,OAAOA,KAAK,MAAM,OAAO,CAAC"}
@@ -6,7 +6,7 @@ export interface Plugin<Spec> {
6
6
  /**
7
7
  * React component for editing the plugin's options in the UI.
8
8
  */
9
- OptionsEditorComponent: React.ComponentType<OptionsEditorProps<Spec>>;
9
+ OptionsEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;
10
10
  /**
11
11
  * Callback for creating the initial options for the plugin.
12
12
  */
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-base.d.ts","sourceRoot":"","sources":["../../src/model/plugin-base.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,MAAM,CAAC,IAAI;IAC1B;;OAEG;IACH,sBAAsB,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtE;;OAEG;IACH,oBAAoB,EAAE,MAAM,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,IAAI;IAGtC,KAAK,EAAE,IAAI,CAAC;IACZ,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAChC"}
1
+ {"version":3,"file":"plugin-base.d.ts","sourceRoot":"","sources":["../../src/model/plugin-base.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,MAAM,CAAC,IAAI;IAC1B;;OAEG;IACH,sBAAsB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvE;;OAEG;IACH,oBAAoB,EAAE,MAAM,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,IAAI;IAGtC,KAAK,EAAE,IAAI,CAAC;IACZ,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAChC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/model/plugin-base.ts"],"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 React from 'react';\n\n/**\n * Base type of all plugin implementations.\n */\nexport interface Plugin<Spec> {\n /**\n * React component for editing the plugin's options in the UI.\n */\n OptionsEditorComponent: React.ComponentType<OptionsEditorProps<Spec>>;\n\n /**\n * Callback for creating the initial options for the plugin.\n */\n createInitialOptions: () => Spec;\n}\n\n/**\n * Common props passed to options editor components.\n */\nexport interface OptionsEditorProps<Spec> {\n // TODO: These are temporary and may not actually make sense, so replace\n // with whatever makes sense as visual editing evolves\n value: Spec;\n onChange: (next: Spec) => void;\n}\n"],"names":["React"],"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,KAAK,MAAM,OAAO,CAAC"}
1
+ {"version":3,"sources":["../../src/model/plugin-base.ts"],"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 React from 'react';\n\n/**\n * Base type of all plugin implementations.\n */\nexport interface Plugin<Spec> {\n /**\n * React component for editing the plugin's options in the UI.\n */\n OptionsEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;\n\n /**\n * Callback for creating the initial options for the plugin.\n */\n createInitialOptions: () => Spec;\n}\n\n/**\n * Common props passed to options editor components.\n */\nexport interface OptionsEditorProps<Spec> {\n // TODO: These are temporary and may not actually make sense, so replace\n // with whatever makes sense as visual editing evolves\n value: Spec;\n onChange: (next: Spec) => void;\n}\n"],"names":["React"],"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,KAAK,MAAM,OAAO,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/test/test-plugins/bert/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAgBvD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAgBvD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/test/test-plugins/bert/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAgBvD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CA2BvD,CAAC"}
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  // Dummy plugins to test loading
15
15
  export const BertPanel1 = {
16
16
  PanelComponent: ()=>null,
17
- OptionsEditorComponent: function BertPanel1Editor({ value , onChange }) {
17
+ PanelQueryEditorComponent: function BertPanel1Editor({ value , onChange }) {
18
18
  return /*#__PURE__*/ _jsxs("div", {
19
19
  children: [
20
20
  /*#__PURE__*/ _jsx("label", {
@@ -39,25 +39,38 @@ export const BertPanel1 = {
39
39
  };
40
40
  export const BertPanel2 = {
41
41
  PanelComponent: ()=>null,
42
- OptionsEditorComponent: function BertPanel2Editor({ value , onChange }) {
43
- return /*#__PURE__*/ _jsxs("div", {
44
- children: [
45
- /*#__PURE__*/ _jsx("label", {
46
- htmlFor: "editor-input",
47
- children: "BertPanel2 editor"
48
- }),
49
- /*#__PURE__*/ _jsx("input", {
50
- type: "text",
51
- id: "editor-input",
52
- value: value.option2,
53
- onChange: (e)=>onChange({
54
- ...value,
55
- option2: e.target.value
42
+ panelOptionsEditorComponents: [
43
+ {
44
+ label: 'Settings',
45
+ content: function BertPanel2Editor({ value , onChange }) {
46
+ return /*#__PURE__*/ _jsxs("div", {
47
+ children: [
48
+ /*#__PURE__*/ _jsx("label", {
49
+ htmlFor: "editor-input",
50
+ children: "BertPanel2 editor"
51
+ }),
52
+ /*#__PURE__*/ _jsx("input", {
53
+ type: "text",
54
+ id: "editor-input",
55
+ value: value.option2,
56
+ onChange: (e)=>onChange({
57
+ ...value,
58
+ option2: e.target.value
59
+ })
56
60
  })
57
- })
58
- ]
59
- });
60
- },
61
+ ]
62
+ });
63
+ }
64
+ },
65
+ {
66
+ label: 'Custom Tab',
67
+ content: function Editor() {
68
+ return /*#__PURE__*/ _jsx("div", {
69
+ children: "custom content"
70
+ });
71
+ }
72
+ }
73
+ ],
61
74
  createInitialOptions: ()=>({
62
75
  option2: ''
63
76
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/test/test-plugins/bert/index.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 { PanelPlugin } from '../../../model';\n\n// Dummy plugins to test loading\nexport const BertPanel1: PanelPlugin<{ option1: string }> = {\n PanelComponent: () => null,\n OptionsEditorComponent: function BertPanel1Editor({ value, onChange }) {\n return (\n <div>\n <label htmlFor=\"editor-input\">BertPanel1 editor</label>\n <input\n type=\"text\"\n id=\"editor-input\"\n value={value.option1}\n onChange={(e) => onChange({ ...value, option1: e.target.value })}\n />\n </div>\n );\n },\n createInitialOptions: () => ({ option1: '' }),\n};\n\nexport const BertPanel2: PanelPlugin<{ option2: string }> = {\n PanelComponent: () => null,\n OptionsEditorComponent: function BertPanel2Editor({ value, onChange }) {\n return (\n <div>\n <label htmlFor=\"editor-input\">BertPanel2 editor</label>\n <input\n type=\"text\"\n id=\"editor-input\"\n value={value.option2}\n onChange={(e) => onChange({ ...value, option2: e.target.value })}\n />\n </div>\n );\n },\n createInitialOptions: () => ({ option2: '' }),\n};\n"],"names":["BertPanel1","PanelComponent","OptionsEditorComponent","BertPanel1Editor","value","onChange","div","label","htmlFor","input","type","id","option1","e","target","createInitialOptions","BertPanel2","BertPanel2Editor","option2"],"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;AAEA,gCAAgC;AAChC,OAAO,MAAMA,UAAU,GAAqC;IAC1DC,cAAc,EAAE,IAAM,IAAI;IAC1BC,sBAAsB,EAAE,SAASC,gBAAgB,CAAC,EAAEC,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAAE,EAAE;QACrE,qBACE,MAACC,KAAG;;8BACF,KAACC,OAAK;oBAACC,OAAO,EAAC,cAAc;8BAAC,mBAAiB;kBAAQ;8BACvD,KAACC,OAAK;oBACJC,IAAI,EAAC,MAAM;oBACXC,EAAE,EAAC,cAAc;oBACjBP,KAAK,EAAEA,KAAK,CAACQ,OAAO;oBACpBP,QAAQ,EAAE,CAACQ,CAAC,GAAKR,QAAQ,CAAC;4BAAE,GAAGD,KAAK;4BAAEQ,OAAO,EAAEC,CAAC,CAACC,MAAM,CAACV,KAAK;yBAAE,CAAC;kBAChE;;UACE,CACN;IACJ,CAAC;IACDW,oBAAoB,EAAE,IAAO,CAAA;YAAEH,OAAO,EAAE,EAAE;SAAE,CAAA,AAAC;CAC9C,CAAC;AAEF,OAAO,MAAMI,UAAU,GAAqC;IAC1Df,cAAc,EAAE,IAAM,IAAI;IAC1BC,sBAAsB,EAAE,SAASe,gBAAgB,CAAC,EAAEb,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAAE,EAAE;QACrE,qBACE,MAACC,KAAG;;8BACF,KAACC,OAAK;oBAACC,OAAO,EAAC,cAAc;8BAAC,mBAAiB;kBAAQ;8BACvD,KAACC,OAAK;oBACJC,IAAI,EAAC,MAAM;oBACXC,EAAE,EAAC,cAAc;oBACjBP,KAAK,EAAEA,KAAK,CAACc,OAAO;oBACpBb,QAAQ,EAAE,CAACQ,CAAC,GAAKR,QAAQ,CAAC;4BAAE,GAAGD,KAAK;4BAAEc,OAAO,EAAEL,CAAC,CAACC,MAAM,CAACV,KAAK;yBAAE,CAAC;kBAChE;;UACE,CACN;IACJ,CAAC;IACDW,oBAAoB,EAAE,IAAO,CAAA;YAAEG,OAAO,EAAE,EAAE;SAAE,CAAA,AAAC;CAC9C,CAAC"}
1
+ {"version":3,"sources":["../../../../src/test/test-plugins/bert/index.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 { PanelPlugin } from '../../../model';\n\n// Dummy plugins to test loading\nexport const BertPanel1: PanelPlugin<{ option1: string }> = {\n PanelComponent: () => null,\n PanelQueryEditorComponent: function BertPanel1Editor({ value, onChange }) {\n return (\n <div>\n <label htmlFor=\"editor-input\">BertPanel1 editor</label>\n <input\n type=\"text\"\n id=\"editor-input\"\n value={value.option1}\n onChange={(e) => onChange({ ...value, option1: e.target.value })}\n />\n </div>\n );\n },\n createInitialOptions: () => ({ option1: '' }),\n};\n\nexport const BertPanel2: PanelPlugin<{ option2: string }> = {\n PanelComponent: () => null,\n panelOptionsEditorComponents: [\n {\n label: 'Settings',\n content: function BertPanel2Editor({ value, onChange }) {\n return (\n <div>\n <label htmlFor=\"editor-input\">BertPanel2 editor</label>\n <input\n type=\"text\"\n id=\"editor-input\"\n value={value.option2}\n onChange={(e) => onChange({ ...value, option2: e.target.value })}\n />\n </div>\n );\n },\n },\n {\n label: 'Custom Tab',\n content: function Editor() {\n return <div>custom content</div>;\n },\n },\n ],\n createInitialOptions: () => ({ option2: '' }),\n};\n"],"names":["BertPanel1","PanelComponent","PanelQueryEditorComponent","BertPanel1Editor","value","onChange","div","label","htmlFor","input","type","id","option1","e","target","createInitialOptions","BertPanel2","panelOptionsEditorComponents","content","BertPanel2Editor","option2","Editor"],"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;AAEA,gCAAgC;AAChC,OAAO,MAAMA,UAAU,GAAqC;IAC1DC,cAAc,EAAE,IAAM,IAAI;IAC1BC,yBAAyB,EAAE,SAASC,gBAAgB,CAAC,EAAEC,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAAE,EAAE;QACxE,qBACE,MAACC,KAAG;;8BACF,KAACC,OAAK;oBAACC,OAAO,EAAC,cAAc;8BAAC,mBAAiB;kBAAQ;8BACvD,KAACC,OAAK;oBACJC,IAAI,EAAC,MAAM;oBACXC,EAAE,EAAC,cAAc;oBACjBP,KAAK,EAAEA,KAAK,CAACQ,OAAO;oBACpBP,QAAQ,EAAE,CAACQ,CAAC,GAAKR,QAAQ,CAAC;4BAAE,GAAGD,KAAK;4BAAEQ,OAAO,EAAEC,CAAC,CAACC,MAAM,CAACV,KAAK;yBAAE,CAAC;kBAChE;;UACE,CACN;IACJ,CAAC;IACDW,oBAAoB,EAAE,IAAO,CAAA;YAAEH,OAAO,EAAE,EAAE;SAAE,CAAA,AAAC;CAC9C,CAAC;AAEF,OAAO,MAAMI,UAAU,GAAqC;IAC1Df,cAAc,EAAE,IAAM,IAAI;IAC1BgB,4BAA4B,EAAE;QAC5B;YACEV,KAAK,EAAE,UAAU;YACjBW,OAAO,EAAE,SAASC,gBAAgB,CAAC,EAAEf,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAAE,EAAE;gBACtD,qBACE,MAACC,KAAG;;sCACF,KAACC,OAAK;4BAACC,OAAO,EAAC,cAAc;sCAAC,mBAAiB;0BAAQ;sCACvD,KAACC,OAAK;4BACJC,IAAI,EAAC,MAAM;4BACXC,EAAE,EAAC,cAAc;4BACjBP,KAAK,EAAEA,KAAK,CAACgB,OAAO;4BACpBf,QAAQ,EAAE,CAACQ,CAAC,GAAKR,QAAQ,CAAC;oCAAE,GAAGD,KAAK;oCAAEgB,OAAO,EAAEP,CAAC,CAACC,MAAM,CAACV,KAAK;iCAAE,CAAC;0BAChE;;kBACE,CACN;YACJ,CAAC;SACF;QACD;YACEG,KAAK,EAAE,YAAY;YACnBW,OAAO,EAAE,SAASG,MAAM,GAAG;gBACzB,qBAAO,KAACf,KAAG;8BAAC,gBAAc;kBAAM,CAAC;YACnC,CAAC;SACF;KACF;IACDS,oBAAoB,EAAE,IAAO,CAAA;YAAEK,OAAO,EAAE,EAAE;SAAE,CAAA,AAAC;CAC9C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perses-dev/plugin-system",
3
- "version": "0.22.0",
3
+ "version": "0.23.1",
4
4
  "description": "The plugin feature in Pereses",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/perses/perses/blob/main/README.md",
@@ -27,8 +27,8 @@
27
27
  "lint:fix": "eslint --fix src --ext .ts,.tsx"
28
28
  },
29
29
  "dependencies": {
30
- "@perses-dev/components": "0.22.0",
31
- "@perses-dev/core": "0.22.0",
30
+ "@perses-dev/components": "0.23.1",
31
+ "@perses-dev/core": "0.23.1",
32
32
  "immer": "^9.0.15",
33
33
  "use-immer": "^0.7.0",
34
34
  "use-query-params": "^2.1.2"