@perses-dev/plugin-system 0.55.0-beta.14 → 0.55.0-beta.15

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 (39) hide show
  1. package/dist/components/DatasourceSelect/DatasourceSelect.d.ts.map +1 -1
  2. package/dist/components/DatasourceSelect/DatasourceSelect.js +0 -1
  3. package/dist/components/DatasourceSelect/DatasourceSelect.js.map +1 -1
  4. package/dist/components/DatasourceTestConnectionButton/DatasourceTestConnectionButton.d.ts.map +1 -1
  5. package/dist/components/DatasourceTestConnectionButton/DatasourceTestConnectionButton.js +2 -7
  6. package/dist/components/DatasourceTestConnectionButton/DatasourceTestConnectionButton.js.map +1 -1
  7. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.d.ts +11 -0
  8. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.d.ts.map +1 -0
  9. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.js +62 -0
  10. package/dist/components/HTTPSettingsEditor/HTTPProxyOAuthPassthroughEditor.js.map +1 -0
  11. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.d.ts +1 -1
  12. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.d.ts.map +1 -1
  13. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.js +36 -13
  14. package/dist/components/HTTPSettingsEditor/HTTPSettingsEditor.js.map +1 -1
  15. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.d.ts.map +1 -1
  16. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.js +7 -1
  17. package/dist/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.js.map +1 -1
  18. package/dist/components/LinksEditor/LinksEditor.js +5 -0
  19. package/dist/components/LinksEditor/LinksEditor.js.map +1 -1
  20. package/dist/components/PluginEditor/plugin-editor-api.d.ts.map +1 -1
  21. package/dist/components/PluginEditor/plugin-editor-api.js +54 -46
  22. package/dist/components/PluginEditor/plugin-editor-api.js.map +1 -1
  23. package/dist/components/TimeRangeControls/TimeRangeControls.d.ts.map +1 -1
  24. package/dist/components/TimeRangeControls/TimeRangeControls.js +0 -2
  25. package/dist/components/TimeRangeControls/TimeRangeControls.js.map +1 -1
  26. package/dist/components/Variables/VariableEditorForm/VariablePreview.js +1 -1
  27. package/dist/components/Variables/VariableEditorForm/VariablePreview.js.map +1 -1
  28. package/dist/remote/PluginLoaderComponent.d.ts.map +1 -1
  29. package/dist/remote/PluginLoaderComponent.js +28 -15
  30. package/dist/remote/PluginLoaderComponent.js.map +1 -1
  31. package/dist/remote/PluginRuntime.d.ts.map +1 -1
  32. package/dist/remote/PluginRuntime.js +28 -21
  33. package/dist/remote/PluginRuntime.js.map +1 -1
  34. package/dist/runtime/TimeRangeProvider/query-params.js +7 -9
  35. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  36. package/dist/runtime/UsageMetricsProvider.d.ts.map +1 -1
  37. package/dist/runtime/UsageMetricsProvider.js +24 -20
  38. package/dist/runtime/UsageMetricsProvider.js.map +1 -1
  39. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { SwitchProps } from '@mui/material';\nimport {\n Box,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n FormControl,\n FormControlLabel,\n FormLabel,\n IconButton,\n InputLabel,\n MenuItem,\n Radio,\n RadioGroup,\n Select,\n Stack,\n Switch,\n TextField,\n Typography,\n} from '@mui/material';\nimport type { SelectChangeEvent } from '@mui/material/Select';\nimport {\n DragAndDropElement,\n DragButton,\n handleMoveDown,\n handleMoveUp,\n InfoTooltip,\n JSONEditor,\n OptionsEditorControl,\n OptionsEditorGroup,\n useDragAndDropMonitor,\n} from '@perses-dev/components';\nimport AlertIcon from 'mdi-material-ui/Alert';\nimport CheckIcon from 'mdi-material-ui/Check';\nimport ChevronDown from 'mdi-material-ui/ChevronDown';\nimport ChevronRight from 'mdi-material-ui/ChevronRight';\nimport CloseIcon from 'mdi-material-ui/Close';\nimport SettingsIcon from 'mdi-material-ui/Cog';\nimport DeleteIcon from 'mdi-material-ui/DeleteOutline';\nimport DownloadIcon from 'mdi-material-ui/Download';\nimport InfoIcon from 'mdi-material-ui/InformationOutline';\nimport LinkIcon from 'mdi-material-ui/Link';\nimport MagnifyScan from 'mdi-material-ui/MagnifyScan';\nimport PauseIcon from 'mdi-material-ui/Pause';\nimport PlayIcon from 'mdi-material-ui/Play';\nimport PlusIcon from 'mdi-material-ui/Plus';\nimport RefreshIcon from 'mdi-material-ui/Refresh';\nimport RobotOutline from 'mdi-material-ui/RobotOutline';\nimport SendIcon from 'mdi-material-ui/Send';\nimport StopIcon from 'mdi-material-ui/Stop';\nimport SyncIcon from 'mdi-material-ui/Sync';\nimport UploadIcon from 'mdi-material-ui/Upload';\nimport type { ReactElement } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\n\nexport type ActionIcon =\n | 'play'\n | 'pause'\n | 'stop'\n | 'delete'\n | 'refresh'\n | 'send'\n | 'download'\n | 'upload'\n | 'check'\n | 'close'\n | 'alert'\n | 'info'\n | 'settings'\n | 'link'\n | 'sync'\n | 'troubleshoot'\n | 'ask-ai';\n\nexport interface BaseAction {\n type: 'event' | 'webhook';\n name: string;\n confirmMessage?: string;\n icon?: ActionIcon;\n enabled?: boolean;\n batchMode: BatchMode;\n bodyTemplate?: string;\n}\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\nexport type BatchMode = 'batch' | 'individual';\n\nexport type ContentType = 'none' | 'json' | 'text';\n\nexport interface WebhookAction extends BaseAction {\n type: 'webhook';\n url: string;\n method: HttpMethod;\n contentType: ContentType;\n headers?: Record<string, string>;\n}\n\nexport interface EventAction extends BaseAction {\n type: 'event';\n eventName: string;\n}\n\nexport type ItemAction = EventAction | WebhookAction;\n\nexport interface ActionOptions {\n enabled?: boolean;\n actionsList?: ItemAction[];\n displayInHeader?: boolean;\n displayWithItem?: boolean;\n}\n\nexport interface SelectionOptions {\n enabled?: boolean;\n}\n\nexport interface ItemSelectionActionsEditorProps {\n actionOptions?: ActionOptions;\n selectionOptions?: SelectionOptions;\n onChangeActions: (actions?: ActionOptions) => void;\n onChangeSelection: (selection?: SelectionOptions) => void;\n}\n\nconst HTTP_METHODS: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\nconst BATCH_MODES: Array<{ value: BatchMode; label: string }> = [\n { value: 'individual', label: 'Individual (one request per selection)' },\n { value: 'batch', label: 'Batch (single request with all selections)' },\n];\nconst CONTENT_TYPES: Array<{ value: ContentType; label: string }> = [\n { value: 'none', label: 'None' },\n { value: 'json', label: 'JSON' },\n { value: 'text', label: 'Text' },\n];\nconst BODY_METHODS: Set<HttpMethod> = new Set(['POST', 'PUT', 'PATCH']);\nconst BODY_CLEAR_CONFIRM_MESSAGE = 'Changing this option will remove the current body template. Continue?';\n\n/** Available action icons with their display components */\nexport const ACTION_ICONS: Array<{ value: ActionIcon; label: string; icon: ReactElement }> = [\n { value: 'play', label: 'Play', icon: <PlayIcon fontSize=\"inherit\" /> },\n { value: 'pause', label: 'Pause', icon: <PauseIcon fontSize=\"inherit\" /> },\n { value: 'stop', label: 'Stop', icon: <StopIcon fontSize=\"inherit\" /> },\n { value: 'delete', label: 'Delete', icon: <DeleteIcon fontSize=\"inherit\" /> },\n { value: 'refresh', label: 'Refresh', icon: <RefreshIcon fontSize=\"inherit\" /> },\n { value: 'send', label: 'Send', icon: <SendIcon fontSize=\"inherit\" /> },\n { value: 'download', label: 'Download', icon: <DownloadIcon fontSize=\"inherit\" /> },\n { value: 'upload', label: 'Upload', icon: <UploadIcon fontSize=\"inherit\" /> },\n { value: 'check', label: 'Check', icon: <CheckIcon fontSize=\"inherit\" /> },\n { value: 'close', label: 'Close', icon: <CloseIcon fontSize=\"inherit\" /> },\n { value: 'alert', label: 'Alert', icon: <AlertIcon fontSize=\"inherit\" /> },\n { value: 'info', label: 'Info', icon: <InfoIcon fontSize=\"inherit\" /> },\n { value: 'settings', label: 'Settings', icon: <SettingsIcon fontSize=\"inherit\" /> },\n { value: 'link', label: 'Link', icon: <LinkIcon fontSize=\"inherit\" /> },\n { value: 'sync', label: 'Sync', icon: <SyncIcon fontSize=\"inherit\" /> },\n { value: 'troubleshoot', label: 'Troubleshoot', icon: <MagnifyScan fontSize=\"inherit\" /> },\n { value: 'ask-ai', label: 'Ask AI', icon: <RobotOutline fontSize=\"inherit\" /> },\n];\n\nconst URL_HELPER_TEXT = 'Supports interpolation: ${__data.fields[\"fieldName\"]}, ${__data.index}, ${__data.count}';\n\nfunction createDefaultEventAction(): EventAction {\n return {\n type: 'event',\n name: 'New Event Action',\n eventName: 'selection-action',\n batchMode: 'individual',\n enabled: true,\n };\n}\n\nfunction createDefaultWebhookAction(): WebhookAction {\n return {\n type: 'webhook',\n name: 'New Webhook Action',\n url: '',\n method: 'POST',\n contentType: 'none',\n batchMode: 'individual',\n enabled: true,\n };\n}\n\ninterface ItemActionEditorProps {\n action: ItemAction;\n index: number;\n onChange: (index: number, action: ItemAction) => void;\n onRemove: (index: number) => void;\n onMoveUp: () => void;\n onMoveDown: () => void;\n}\n\ninterface InterpolationHelperProps {\n batchMode: BatchMode;\n}\n\nfunction InterpolationHelper({ batchMode }: InterpolationHelperProps): ReactElement {\n let content: ReactElement = (\n <div>\n Individual mode patterns: <code>{'${__data.fields[\"field\"]}'}</code>, <code>{'${__data.index}'}</code>,{' '}\n <code>{'${__data.count}'}</code>\n </div>\n );\n\n if (batchMode === 'batch') {\n content = (\n <div>\n Batch mode patterns: <code>{'${__data}'}</code>, <code>{\"${__data[0].fields['field']}\"}</code>,{' '}\n <code>{\"${__data.fields['field']:csv}\"}</code>, <code>{'${__data.count}'}</code>\n </div>\n );\n }\n\n return (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ mb: 1, display: 'block' }}>\n {content}\n </Typography>\n );\n}\n\nfunction EventActionEditor({\n action,\n index,\n onChange,\n onRemove,\n onMoveDown,\n onMoveUp,\n}: ItemActionEditorProps): ReactElement {\n const eventAction = action as EventAction;\n\n const [isCollapsed, setIsCollapsed] = useState(true);\n const hasBodyTemplate = (eventAction.bodyTemplate ?? '').trim().length > 0;\n\n const handleIncludesTemplateChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const nextContentType = event.target.value as 'custom' | 'none';\n\n const bodyTemplate = nextContentType === 'custom' ? JSON.stringify({}) : undefined;\n\n onChange(index, { ...eventAction, bodyTemplate: bodyTemplate });\n },\n [index, onChange, eventAction],\n );\n\n const handleBodyTemplateChange = useCallback(\n (template: string) => {\n onChange(index, { ...eventAction, bodyTemplate: template || undefined });\n },\n [index, onChange, eventAction],\n );\n\n const jsonDataTemplate = useMemo(() => {\n if (eventAction.bodyTemplate) {\n try {\n return JSON.parse(eventAction.bodyTemplate);\n } catch {\n return {};\n }\n }\n }, [eventAction.bodyTemplate]);\n\n return (\n <DragAndDropElement data={eventAction as unknown as Record<string, unknown>}>\n <Stack direction=\"row\" alignItems=\"center\" justifyContent=\"space-between\" gap={4}>\n <Stack direction=\"row\" gap={1}>\n <IconButton\n data-testid={`event-action-toggle#${eventAction.name}`}\n size=\"small\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n >\n {isCollapsed ? <ChevronRight /> : <ChevronDown />}\n </IconButton>\n <Typography variant=\"overline\" component=\"h4\" sx={{ textTransform: 'none' }}>\n EVENT ACTION:{' '}\n {eventAction.name ? (\n <span>\n <strong>{eventAction.name}</strong>\n </span>\n ) : (\n <strong>{eventAction.name}</strong>\n )}\n </Typography>\n </Stack>\n\n <Stack direction=\"row\" gap={1}>\n <InfoTooltip description=\"Remove action settings\" placement=\"top\">\n <IconButton\n size=\"small\"\n sx={{ marginLeft: 'auto' }}\n onClick={() => onRemove(index)}\n key=\"delete-action-button\"\n >\n <DeleteIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description=\"Reorder action settings\" placement=\"top\">\n <DragButton\n onMoveUp={onMoveUp}\n onMoveDown={onMoveDown}\n menuSx={{\n '.MuiPaper-root': { backgroundColor: (theme) => theme.palette.background.lighter },\n }}\n key=\"reorder-action-button\"\n />\n </InfoTooltip>\n </Stack>\n </Stack>\n\n {!isCollapsed && (\n <Stack spacing={2}>\n <OptionsEditorControl\n label=\"Enabled\"\n control={\n <Switch\n checked={eventAction?.enabled ?? false}\n onChange={(e) => onChange(index, { ...eventAction, enabled: e.target.checked })}\n />\n }\n />\n\n <Stack direction=\"row\" spacing={2}>\n <TextField\n label=\"Action Name\"\n size=\"small\"\n value={eventAction.name}\n onChange={(e) => onChange(index, { ...eventAction, name: e.target.value })}\n sx={{ flexGrow: 1 }}\n />\n\n <FormControl size=\"small\" sx={{ minWidth: 120 }}>\n <InputLabel>Icon</InputLabel>\n <Select\n value={eventAction.icon || ''}\n label=\"Icon\"\n onChange={(e) => onChange(index, { ...eventAction, icon: (e.target.value as ActionIcon) || undefined })}\n >\n <MenuItem value=\"\">\n <em>None</em>\n </MenuItem>\n {ACTION_ICONS.map((iconOption) => (\n <MenuItem key={iconOption.value} value={iconOption.value}>\n <Stack direction=\"row\" alignItems=\"center\" spacing={1}>\n {iconOption.icon}\n <span>{iconOption.label}</span>\n </Stack>\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <Stack direction=\"row\" spacing={2}>\n <TextField\n label=\"Event Name\"\n size=\"small\"\n value={eventAction.eventName}\n onChange={(e) => onChange(index, { ...eventAction, eventName: e.target.value })}\n helperText=\"Name of the CustomEvent to dispatch (e.g., 'selection-action')\"\n fullWidth\n />\n\n <FormControl size=\"small\" sx={{ flexGrow: 1, minWidth: 280 }}>\n <InputLabel>Batch Mode</InputLabel>\n <Select\n value={eventAction.batchMode ?? 'individual'}\n label=\"Batch Mode\"\n onChange={(e) => onChange(index, { ...eventAction, batchMode: e.target.value as BatchMode })}\n >\n {BATCH_MODES.map((mode) => (\n <MenuItem key={mode.value} value={mode.value}>\n {mode.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <FormControl component=\"fieldset\" size=\"small\">\n <FormLabel component=\"legend\">Template</FormLabel>\n <RadioGroup row value={hasBodyTemplate ? 'custom' : 'none'} onChange={handleIncludesTemplateChange}>\n <FormControlLabel value=\"none\" control={<Radio size=\"small\" />} label=\"None\" />\n <FormControlLabel value=\"custom\" control={<Radio size=\"small\" />} label=\"JSON template\" />\n </RadioGroup>\n </FormControl>\n\n {hasBodyTemplate && (\n <>\n <InterpolationHelper batchMode={eventAction.batchMode} />\n <JSONEditor\n value={jsonDataTemplate || ''}\n onChange={handleBodyTemplateChange}\n minHeight=\"100px\"\n maxHeight=\"200px\"\n />\n </>\n )}\n\n <TextField\n label=\"Confirmation Message (optional)\"\n size=\"small\"\n value={eventAction.confirmMessage || ''}\n onChange={(e) => onChange(index, { ...eventAction, confirmMessage: e.target.value || undefined })}\n helperText=\"If set, shows a confirmation dialog before executing the action\"\n fullWidth\n multiline\n rows={2}\n />\n </Stack>\n )}\n </DragAndDropElement>\n );\n}\n\nfunction WebhookActionEditor({\n action,\n index,\n onChange,\n onRemove,\n onMoveUp,\n onMoveDown,\n}: ItemActionEditorProps): ReactElement {\n const webhookAction = action as WebhookAction;\n const [pendingChange, setPendingChange] = useState<\n { kind: 'contentType'; value: ContentType } | { kind: 'method'; value: HttpMethod } | null\n >(null);\n const contentTypeValue = webhookAction.contentType ?? 'none';\n const hasBodyTemplate = (webhookAction.bodyTemplate ?? '').trim().length > 0;\n const supportsBody = BODY_METHODS.has(webhookAction.method);\n\n const [isCollapsed, setIsCollapsed] = useState(true);\n\n const handleBodyTemplateChange = useCallback(\n (template: string) => {\n onChange(index, { ...webhookAction, bodyTemplate: template || undefined });\n },\n [index, onChange, webhookAction],\n );\n\n const handleTextTemplateChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n onChange(index, { ...webhookAction, bodyTemplate: event.target.value || undefined });\n },\n [index, onChange, webhookAction],\n );\n\n const handleContentTypeChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const nextContentType = event.target.value as ContentType;\n if (nextContentType === contentTypeValue) {\n return;\n }\n\n if (hasBodyTemplate) {\n setPendingChange({ kind: 'contentType', value: nextContentType });\n return;\n }\n\n onChange(index, { ...webhookAction, contentType: nextContentType });\n },\n [contentTypeValue, hasBodyTemplate, index, onChange, webhookAction],\n );\n\n const handleMethodChange = useCallback(\n (event: SelectChangeEvent<HttpMethod>) => {\n const nextMethod = event.target.value as HttpMethod;\n if (nextMethod === webhookAction.method) {\n return;\n }\n\n const nextSupportsBody = BODY_METHODS.has(nextMethod);\n if (!nextSupportsBody && hasBodyTemplate) {\n setPendingChange({ kind: 'method', value: nextMethod });\n return;\n }\n\n onChange(index, { ...webhookAction, method: nextMethod });\n },\n [hasBodyTemplate, index, onChange, webhookAction],\n );\n\n const handleConfirmClose = useCallback(() => {\n setPendingChange(null);\n }, []);\n\n const handleConfirmApply = useCallback(() => {\n if (!pendingChange) {\n return;\n }\n\n if (pendingChange.kind === 'contentType') {\n onChange(index, { ...webhookAction, contentType: pendingChange.value, bodyTemplate: undefined });\n } else {\n onChange(index, { ...webhookAction, method: pendingChange.value, bodyTemplate: undefined });\n }\n\n setPendingChange(null);\n }, [index, onChange, pendingChange, webhookAction]);\n\n const jsonBodyTemplate = useMemo(() => {\n if (webhookAction.contentType === 'json' && webhookAction.bodyTemplate) {\n try {\n return JSON.parse(webhookAction.bodyTemplate);\n } catch {\n return {};\n }\n }\n }, [webhookAction.bodyTemplate, webhookAction.contentType]);\n\n return (\n <DragAndDropElement data={webhookAction as unknown as Record<string, unknown>}>\n <Stack direction=\"row\" alignItems=\"center\" justifyContent=\"space-between\" gap={4}>\n <Stack direction=\"row\" gap={1}>\n <IconButton\n data-testid={`column-toggle#${webhookAction.name}`}\n size=\"small\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n >\n {isCollapsed ? <ChevronRight /> : <ChevronDown />}\n </IconButton>\n <Typography variant=\"overline\" component=\"h4\" sx={{ textTransform: 'none' }}>\n WEBHOOK ACTION: <strong>{webhookAction.name}</strong>\n </Typography>\n </Stack>\n\n <Stack direction=\"row\" gap={1}>\n <InfoTooltip description=\"Remove action settings\" placement=\"top\">\n <IconButton\n size=\"small\"\n sx={{ marginLeft: 'auto' }}\n onClick={() => onRemove(index)}\n key=\"delete-action-button\"\n >\n <DeleteIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description=\"Reorder action settings\" placement=\"top\">\n <DragButton\n onMoveUp={onMoveUp}\n onMoveDown={onMoveDown}\n menuSx={{\n '.MuiPaper-root': { backgroundColor: (theme) => theme.palette.background.lighter },\n }}\n key=\"reorder-action-button\"\n />\n </InfoTooltip>\n </Stack>\n </Stack>\n\n {!isCollapsed && (\n <Stack spacing={2}>\n <OptionsEditorControl\n label=\"Enabled\"\n control={\n <Switch\n checked={action?.enabled ?? false}\n onChange={(e) => onChange(index, { ...webhookAction, enabled: e.target.checked })}\n />\n }\n />\n\n <Stack direction=\"row\" spacing={2}>\n <TextField\n label=\"Action Name\"\n size=\"small\"\n value={webhookAction.name}\n onChange={(e) => onChange(index, { ...webhookAction, name: e.target.value })}\n sx={{ flexGrow: 1 }}\n />\n\n <FormControl size=\"small\" sx={{ minWidth: 120 }}>\n <InputLabel>Icon</InputLabel>\n <Select\n value={webhookAction.icon || ''}\n label=\"Icon\"\n onChange={(e) =>\n onChange(index, { ...webhookAction, icon: (e.target.value as ActionIcon) || undefined })\n }\n >\n <MenuItem value=\"\">\n <em>None</em>\n </MenuItem>\n {ACTION_ICONS.map((iconOption) => (\n <MenuItem key={iconOption.value} value={iconOption.value}>\n <Stack direction=\"row\" alignItems=\"center\" spacing={1}>\n {iconOption.icon}\n <span>{iconOption.label}</span>\n </Stack>\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <TextField\n label=\"URL\"\n size=\"small\"\n value={webhookAction.url}\n onChange={(e) => onChange(index, { ...webhookAction, url: e.target.value })}\n helperText={URL_HELPER_TEXT}\n fullWidth\n />\n\n <Stack direction=\"row\" spacing={2}>\n <FormControl size=\"small\" sx={{ minWidth: 120 }}>\n <InputLabel>Method</InputLabel>\n <Select value={webhookAction.method} label=\"Method\" onChange={handleMethodChange}>\n {HTTP_METHODS.map((method) => (\n <MenuItem key={method} value={method}>\n {method}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n\n <FormControl size=\"small\" sx={{ flexGrow: 1 }}>\n <InputLabel>Batch Mode</InputLabel>\n <Select\n value={webhookAction.batchMode}\n label=\"Batch Mode\"\n onChange={(e) => onChange(index, { ...webhookAction, batchMode: e.target.value as BatchMode })}\n >\n {BATCH_MODES.map((mode) => (\n <MenuItem key={mode.value} value={mode.value}>\n {mode.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <FormControl component=\"fieldset\" size=\"small\">\n <FormLabel component=\"legend\">Content Type</FormLabel>\n <RadioGroup row value={contentTypeValue} onChange={handleContentTypeChange}>\n {CONTENT_TYPES.map((option) => (\n <FormControlLabel\n key={option.value}\n value={option.value}\n control={<Radio size=\"small\" />}\n label={option.label}\n />\n ))}\n </RadioGroup>\n </FormControl>\n\n {supportsBody && contentTypeValue !== 'none' && (\n <Box>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mb: 1 }}>\n {contentTypeValue === 'json' ? 'Body Template (JSON)' : 'Body Template (Text)'}\n </Typography>\n <InterpolationHelper batchMode={webhookAction.batchMode} />\n {contentTypeValue === 'json' ? (\n <JSONEditor\n value={jsonBodyTemplate || ''}\n onChange={handleBodyTemplateChange}\n minHeight=\"100px\"\n maxHeight=\"200px\"\n />\n ) : (\n <TextField\n value={webhookAction.bodyTemplate || ''}\n onChange={handleTextTemplateChange}\n fullWidth\n multiline\n rows={5}\n />\n )}\n </Box>\n )}\n\n <TextField\n label=\"Confirmation Message (optional)\"\n size=\"small\"\n value={webhookAction.confirmMessage || ''}\n onChange={(e) => onChange(index, { ...webhookAction, confirmMessage: e.target.value || undefined })}\n helperText=\"If set, shows a confirmation dialog before executing the action\"\n fullWidth\n multiline\n rows={2}\n />\n </Stack>\n )}\n\n <Dialog open={Boolean(pendingChange)} onClose={handleConfirmClose} aria-labelledby=\"selection-body-clear-title\">\n <DialogTitle id=\"selection-body-clear-title\">Remove Body Template?</DialogTitle>\n <DialogContent>\n <DialogContentText>{BODY_CLEAR_CONFIRM_MESSAGE}</DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleConfirmClose}>Cancel</Button>\n <Button onClick={handleConfirmApply} variant=\"contained\" color=\"primary\">\n Continue\n </Button>\n </DialogActions>\n </Dialog>\n </DragAndDropElement>\n );\n}\n\nexport function ItemSelectionActionsEditor({\n actionOptions,\n selectionOptions,\n onChangeActions,\n onChangeSelection,\n}: ItemSelectionActionsEditorProps): ReactElement {\n const actions = useMemo(\n () => actionOptions || { enabled: true, displayInHeader: true, displayWithItem: false },\n [actionOptions],\n );\n\n const handleEnableActionsChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeActions({ ...actions, enabled: checked ? true : undefined });\n };\n\n const handleEnableSelectionChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeSelection({ ...selectionOptions, enabled: checked ? true : undefined });\n };\n\n const handleDisplayInHeaderChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeActions({ ...actions, displayInHeader: checked ? true : undefined });\n };\n\n const handleDisplayWithItemChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeActions({ ...actions, displayWithItem: checked ? true : undefined });\n };\n\n const handleAddEventAction = useCallback(() => {\n onChangeActions({ ...actions, actionsList: [...(actions.actionsList ?? []), createDefaultEventAction()] });\n }, [actions, onChangeActions]);\n\n const handleAddWebhookAction = useCallback(() => {\n onChangeActions({ ...actions, actionsList: [...(actions.actionsList ?? []), createDefaultWebhookAction()] });\n }, [actions, onChangeActions]);\n\n const handleActionChange = useCallback(\n (index: number, updatedAction: ItemAction) => {\n const newActions = actions.actionsList ? [...actions.actionsList] : [];\n newActions[index] = updatedAction;\n onChangeActions({ ...actions, actionsList: newActions });\n },\n [actions, onChangeActions],\n );\n\n const handleRemoveAction = useCallback(\n (index: number) => {\n const newActions = actions.actionsList ? actions.actionsList.filter((_, i) => i !== index) : [];\n onChangeActions(newActions.length > 0 ? { ...actions, actionsList: newActions } : undefined);\n },\n [actions, onChangeActions],\n );\n\n useDragAndDropMonitor({\n elements: actions.actionsList as unknown as Array<Record<string, unknown>>,\n accessKey: 'name',\n onChange: (newElements) => {\n onChangeActions({ ...actions, actionsList: newElements as unknown as ItemAction[] });\n },\n });\n\n return (\n <Stack spacing={1}>\n <OptionsEditorControl\n label=\"Enable Item Selection\"\n description=\"Allow selecting items\"\n control={<Switch checked={selectionOptions?.enabled ?? false} onChange={handleEnableSelectionChange} />}\n />\n <OptionsEditorControl\n label=\"Enable Item Actions\"\n description=\"Allow executing actions on selected items\"\n control={<Switch checked={actionOptions?.enabled ?? false} onChange={handleEnableActionsChange} />}\n />\n <OptionsEditorControl\n label=\"Display Actions in Panel Header\"\n description=\"Show action buttons in the panel header when items are selected\"\n control={<Switch checked={actionOptions?.displayInHeader ?? false} onChange={handleDisplayInHeaderChange} />}\n />\n <OptionsEditorControl\n label=\"Display Actions with Each Item\"\n description=\"Show action buttons alongside each item when selected\"\n control={<Switch checked={actionOptions?.displayWithItem ?? false} onChange={handleDisplayWithItemChange} />}\n />\n <OptionsEditorGroup title=\"Actions\">\n <Stack spacing={3}>\n {!actions.actionsList || actions.actionsList.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\" fontStyle=\"italic\">\n No actions defined. Add an action to enable triggering events or webhooks on selected data.\n </Typography>\n ) : (\n <Stack spacing={1} border=\"none\">\n {actions.actionsList &&\n actions.actionsList.map((action, index) => (\n <Box key={index} borderBottom={1} borderColor={(theme) => theme.palette.divider} pb={1}>\n {action.type === 'event' ? (\n <EventActionEditor\n action={action}\n index={index}\n onChange={handleActionChange}\n onRemove={handleRemoveAction}\n onMoveDown={() =>\n onChangeActions({ ...actions, actionsList: handleMoveDown(action, actions.actionsList!) })\n }\n onMoveUp={() =>\n onChangeActions({ ...actions, actionsList: handleMoveUp(action, actions.actionsList!) })\n }\n />\n ) : (\n <WebhookActionEditor\n action={action}\n index={index}\n onChange={handleActionChange}\n onRemove={handleRemoveAction}\n onMoveDown={() =>\n onChangeActions({ ...actions, actionsList: handleMoveDown(action, actions.actionsList!) })\n }\n onMoveUp={() =>\n onChangeActions({ ...actions, actionsList: handleMoveUp(action, actions.actionsList!) })\n }\n />\n )}\n </Box>\n ))}\n </Stack>\n )}\n\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"contained\" startIcon={<PlusIcon />} onClick={handleAddEventAction}>\n Add Event Action\n </Button>\n <Button variant=\"contained\" startIcon={<PlusIcon />} onClick={handleAddWebhookAction}>\n Add Webhook Action\n </Button>\n </Stack>\n </Stack>\n </OptionsEditorGroup>\n </Stack>\n );\n}\n"],"names":["Box","Button","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","FormControl","FormControlLabel","FormLabel","IconButton","InputLabel","MenuItem","Radio","RadioGroup","Select","Stack","Switch","TextField","Typography","DragAndDropElement","DragButton","handleMoveDown","handleMoveUp","InfoTooltip","JSONEditor","OptionsEditorControl","OptionsEditorGroup","useDragAndDropMonitor","AlertIcon","CheckIcon","ChevronDown","ChevronRight","CloseIcon","SettingsIcon","DeleteIcon","DownloadIcon","InfoIcon","LinkIcon","MagnifyScan","PauseIcon","PlayIcon","PlusIcon","RefreshIcon","RobotOutline","SendIcon","StopIcon","SyncIcon","UploadIcon","useCallback","useMemo","useState","HTTP_METHODS","BATCH_MODES","value","label","CONTENT_TYPES","BODY_METHODS","Set","BODY_CLEAR_CONFIRM_MESSAGE","ACTION_ICONS","icon","fontSize","URL_HELPER_TEXT","createDefaultEventAction","type","name","eventName","batchMode","enabled","createDefaultWebhookAction","url","method","contentType","InterpolationHelper","content","div","code","variant","color","sx","mb","display","EventActionEditor","action","index","onChange","onRemove","onMoveDown","onMoveUp","eventAction","isCollapsed","setIsCollapsed","hasBodyTemplate","bodyTemplate","trim","length","handleIncludesTemplateChange","event","nextContentType","target","JSON","stringify","undefined","handleBodyTemplateChange","template","jsonDataTemplate","parse","data","direction","alignItems","justifyContent","gap","data-testid","size","onClick","component","textTransform","span","strong","description","placement","marginLeft","menuSx","backgroundColor","theme","palette","background","lighter","spacing","control","checked","e","flexGrow","minWidth","em","map","iconOption","helperText","fullWidth","mode","row","minHeight","maxHeight","confirmMessage","multiline","rows","WebhookActionEditor","webhookAction","pendingChange","setPendingChange","contentTypeValue","supportsBody","has","handleTextTemplateChange","handleContentTypeChange","kind","handleMethodChange","nextMethod","nextSupportsBody","handleConfirmClose","handleConfirmApply","jsonBodyTemplate","option","open","Boolean","onClose","aria-labelledby","id","ItemSelectionActionsEditor","actionOptions","selectionOptions","onChangeActions","onChangeSelection","actions","displayInHeader","displayWithItem","handleEnableActionsChange","_","handleEnableSelectionChange","handleDisplayInHeaderChange","handleDisplayWithItemChange","handleAddEventAction","actionsList","handleAddWebhookAction","handleActionChange","updatedAction","newActions","handleRemoveAction","filter","i","elements","accessKey","newElements","title","fontStyle","border","borderBottom","borderColor","divider","pb","startIcon"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAGjC,SACEA,GAAG,EACHC,MAAM,EACNC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,iBAAiB,EACjBC,WAAW,EACXC,WAAW,EACXC,gBAAgB,EAChBC,SAAS,EACTC,UAAU,EACVC,UAAU,EACVC,QAAQ,EACRC,KAAK,EACLC,UAAU,EACVC,MAAM,EACNC,KAAK,EACLC,MAAM,EACNC,SAAS,EACTC,UAAU,QACL,gBAAgB;AAEvB,SACEC,kBAAkB,EAClBC,UAAU,EACVC,cAAc,EACdC,YAAY,EACZC,WAAW,EACXC,UAAU,EACVC,oBAAoB,EACpBC,kBAAkB,EAClBC,qBAAqB,QAChB,yBAAyB;AAChC,OAAOC,eAAe,wBAAwB;AAC9C,OAAOC,eAAe,wBAAwB;AAC9C,OAAOC,iBAAiB,8BAA8B;AACtD,OAAOC,kBAAkB,+BAA+B;AACxD,OAAOC,eAAe,wBAAwB;AAC9C,OAAOC,kBAAkB,sBAAsB;AAC/C,OAAOC,gBAAgB,gCAAgC;AACvD,OAAOC,kBAAkB,2BAA2B;AACpD,OAAOC,cAAc,qCAAqC;AAC1D,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,iBAAiB,8BAA8B;AACtD,OAAOC,eAAe,wBAAwB;AAC9C,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,iBAAiB,0BAA0B;AAClD,OAAOC,kBAAkB,+BAA+B;AACxD,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,gBAAgB,yBAAyB;AAEhD,SAASC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAQ;AAsEvD,MAAMC,eAA6B;IAAC;IAAO;IAAQ;IAAO;IAAS;CAAS;AAC5E,MAAMC,cAA0D;IAC9D;QAAEC,OAAO;QAAcC,OAAO;IAAyC;IACvE;QAAED,OAAO;QAASC,OAAO;IAA6C;CACvE;AACD,MAAMC,gBAA8D;IAClE;QAAEF,OAAO;QAAQC,OAAO;IAAO;IAC/B;QAAED,OAAO;QAAQC,OAAO;IAAO;IAC/B;QAAED,OAAO;QAAQC,OAAO;IAAO;CAChC;AACD,MAAME,eAAgC,IAAIC,IAAI;IAAC;IAAQ;IAAO;CAAQ;AACtE,MAAMC,6BAA6B;AAEnC,yDAAyD,GACzD,OAAO,MAAMC,eAAgF;IAC3F;QAAEN,OAAO;QAAQC,OAAO;QAAQM,oBAAM,KAACpB;YAASqB,UAAS;;IAAa;IACtE;QAAER,OAAO;QAASC,OAAO;QAASM,oBAAM,KAACrB;YAAUsB,UAAS;;IAAa;IACzE;QAAER,OAAO;QAAQC,OAAO;QAAQM,oBAAM,KAACf;YAASgB,UAAS;;IAAa;IACtE;QAAER,OAAO;QAAUC,OAAO;QAAUM,oBAAM,KAAC1B;YAAW2B,UAAS;;IAAa;IAC5E;QAAER,OAAO;QAAWC,OAAO;QAAWM,oBAAM,KAAClB;YAAYmB,UAAS;;IAAa;IAC/E;QAAER,OAAO;QAAQC,OAAO;QAAQM,oBAAM,KAAChB;YAASiB,UAAS;;IAAa;IACtE;QAAER,OAAO;QAAYC,OAAO;QAAYM,oBAAM,KAACzB;YAAa0B,UAAS;;IAAa;IAClF;QAAER,OAAO;QAAUC,OAAO;QAAUM,oBAAM,KAACb;YAAWc,UAAS;;IAAa;IAC5E;QAAER,OAAO;QAASC,OAAO;QAASM,oBAAM,KAAC/B;YAAUgC,UAAS;;IAAa;IACzE;QAAER,OAAO;QAASC,OAAO;QAASM,oBAAM,KAAC5B;YAAU6B,UAAS;;IAAa;IACzE;QAAER,OAAO;QAASC,OAAO;QAASM,oBAAM,KAAChC;YAAUiC,UAAS;;IAAa;IACzE;QAAER,OAAO;QAAQC,OAAO;QAAQM,oBAAM,KAACxB;YAASyB,UAAS;;IAAa;IACtE;QAAER,OAAO;QAAYC,OAAO;QAAYM,oBAAM,KAAC3B;YAAa4B,UAAS;;IAAa;IAClF;QAAER,OAAO;QAAQC,OAAO;QAAQM,oBAAM,KAACvB;YAASwB,UAAS;;IAAa;IACtE;QAAER,OAAO;QAAQC,OAAO;QAAQM,oBAAM,KAACd;YAASe,UAAS;;IAAa;IACtE;QAAER,OAAO;QAAgBC,OAAO;QAAgBM,oBAAM,KAACtB;YAAYuB,UAAS;;IAAa;IACzF;QAAER,OAAO;QAAUC,OAAO;QAAUM,oBAAM,KAACjB;YAAakB,UAAS;;IAAa;CAC/E,CAAC;AAEF,MAAMC,kBAAkB;AAExB,SAASC;IACP,OAAO;QACLC,MAAM;QACNC,MAAM;QACNC,WAAW;QACXC,WAAW;QACXC,SAAS;IACX;AACF;AAEA,SAASC;IACP,OAAO;QACLL,MAAM;QACNC,MAAM;QACNK,KAAK;QACLC,QAAQ;QACRC,aAAa;QACbL,WAAW;QACXC,SAAS;IACX;AACF;AAeA,SAASK,oBAAoB,EAAEN,SAAS,EAA4B;IAClE,IAAIO,wBACF,MAACC;;YAAI;0BACuB,KAACC;0BAAM;;YAAmC;0BAAE,KAACA;0BAAM;;YAAyB;YAAE;0BACxG,KAACA;0BAAM;;;;IAIX,IAAIT,cAAc,SAAS;QACzBO,wBACE,MAACC;;gBAAI;8BACkB,KAACC;8BAAM;;gBAAmB;8BAAE,KAACA;8BAAM;;gBAAsC;gBAAE;8BAChG,KAACA;8BAAM;;gBAAuC;8BAAE,KAACA;8BAAM;;;;IAG7D;IAEA,qBACE,KAAC1D;QAAW2D,SAAQ;QAAUC,OAAM;QAAiBC,IAAI;YAAEC,IAAI;YAAGC,SAAS;QAAQ;kBAChFP;;AAGP;AAEA,SAASQ,kBAAkB,EACzBC,MAAM,EACNC,KAAK,EACLC,QAAQ,EACRC,QAAQ,EACRC,UAAU,EACVC,QAAQ,EACc;IACtB,MAAMC,cAAcN;IAEpB,MAAM,CAACO,aAAaC,eAAe,GAAGzC,SAAS;IAC/C,MAAM0C,kBAAkB,AAACH,CAAAA,YAAYI,YAAY,IAAI,EAAC,EAAGC,IAAI,GAAGC,MAAM,GAAG;IAEzE,MAAMC,+BAA+BhD,YACnC,CAACiD;QACC,MAAMC,kBAAkBD,MAAME,MAAM,CAAC9C,KAAK;QAE1C,MAAMwC,eAAeK,oBAAoB,WAAWE,KAAKC,SAAS,CAAC,CAAC,KAAKC;QAEzEjB,SAASD,OAAO;YAAE,GAAGK,WAAW;YAAEI,cAAcA;QAAa;IAC/D,GACA;QAACT;QAAOC;QAAUI;KAAY;IAGhC,MAAMc,2BAA2BvD,YAC/B,CAACwD;QACCnB,SAASD,OAAO;YAAE,GAAGK,WAAW;YAAEI,cAAcW,YAAYF;QAAU;IACxE,GACA;QAAClB;QAAOC;QAAUI;KAAY;IAGhC,MAAMgB,mBAAmBxD,QAAQ;QAC/B,IAAIwC,YAAYI,YAAY,EAAE;YAC5B,IAAI;gBACF,OAAOO,KAAKM,KAAK,CAACjB,YAAYI,YAAY;YAC5C,EAAE,OAAM;gBACN,OAAO,CAAC;YACV;QACF;IACF,GAAG;QAACJ,YAAYI,YAAY;KAAC;IAE7B,qBACE,MAAC1E;QAAmBwF,MAAMlB;;0BACxB,MAAC1E;gBAAM6F,WAAU;gBAAMC,YAAW;gBAASC,gBAAe;gBAAgBC,KAAK;;kCAC7E,MAAChG;wBAAM6F,WAAU;wBAAMG,KAAK;;0CAC1B,KAACtG;gCACCuG,eAAa,CAAC,oBAAoB,EAAEvB,YAAYxB,IAAI,EAAE;gCACtDgD,MAAK;gCACLC,SAAS,IAAMvB,eAAe,CAACD;0CAE9BA,4BAAc,KAAC3D,kCAAkB,KAACD;;0CAErC,MAACZ;gCAAW2D,SAAQ;gCAAWsC,WAAU;gCAAKpC,IAAI;oCAAEqC,eAAe;gCAAO;;oCAAG;oCAC7D;oCACb3B,YAAYxB,IAAI,iBACf,KAACoD;kDACC,cAAA,KAACC;sDAAQ7B,YAAYxB,IAAI;;uDAG3B,KAACqD;kDAAQ7B,YAAYxB,IAAI;;;;;;kCAK/B,MAAClD;wBAAM6F,WAAU;wBAAMG,KAAK;;0CAC1B,KAACxF;gCAAYgG,aAAY;gCAAyBC,WAAU;0CAC1D,cAAA,KAAC/G;oCACCwG,MAAK;oCACLlC,IAAI;wCAAE0C,YAAY;oCAAO;oCACzBP,SAAS,IAAM5B,SAASF;8CAGxB,cAAA,KAAClD;mCAFG;;0CAKR,KAACX;gCAAYgG,aAAY;gCAA0BC,WAAU;0CAC3D,cAAA,KAACpG;oCACCoE,UAAUA;oCACVD,YAAYA;oCACZmC,QAAQ;wCACN,kBAAkB;4CAAEC,iBAAiB,CAACC,QAAUA,MAAMC,OAAO,CAACC,UAAU,CAACC,OAAO;wCAAC;oCACnF;mCACI;;;;;;YAMX,CAACrC,6BACA,MAAC3E;gBAAMiH,SAAS;;kCACd,KAACvG;wBACC6B,OAAM;wBACN2E,uBACE,KAACjH;4BACCkH,SAASzC,aAAarB,WAAW;4BACjCiB,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;oCAAE,GAAGK,WAAW;oCAAErB,SAAS+D,EAAEhC,MAAM,CAAC+B,OAAO;gCAAC;;;kCAKnF,MAACnH;wBAAM6F,WAAU;wBAAMoB,SAAS;;0CAC9B,KAAC/G;gCACCqC,OAAM;gCACN2D,MAAK;gCACL5D,OAAOoC,YAAYxB,IAAI;gCACvBoB,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;wCAAE,GAAGK,WAAW;wCAAExB,MAAMkE,EAAEhC,MAAM,CAAC9C,KAAK;oCAAC;gCACxE0B,IAAI;oCAAEqD,UAAU;gCAAE;;0CAGpB,MAAC9H;gCAAY2G,MAAK;gCAAQlC,IAAI;oCAAEsD,UAAU;gCAAI;;kDAC5C,KAAC3H;kDAAW;;kDACZ,MAACI;wCACCuC,OAAOoC,YAAY7B,IAAI,IAAI;wCAC3BN,OAAM;wCACN+B,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;gDAAE,GAAGK,WAAW;gDAAE7B,MAAM,AAACuE,EAAEhC,MAAM,CAAC9C,KAAK,IAAmBiD;4CAAU;;0DAErG,KAAC3F;gDAAS0C,OAAM;0DACd,cAAA,KAACiF;8DAAG;;;4CAEL3E,aAAa4E,GAAG,CAAC,CAACC,2BACjB,KAAC7H;oDAAgC0C,OAAOmF,WAAWnF,KAAK;8DACtD,cAAA,MAACtC;wDAAM6F,WAAU;wDAAMC,YAAW;wDAASmB,SAAS;;4DACjDQ,WAAW5E,IAAI;0EAChB,KAACyD;0EAAMmB,WAAWlF,KAAK;;;;mDAHZkF,WAAWnF,KAAK;;;;;;;kCAWvC,MAACtC;wBAAM6F,WAAU;wBAAMoB,SAAS;;0CAC9B,KAAC/G;gCACCqC,OAAM;gCACN2D,MAAK;gCACL5D,OAAOoC,YAAYvB,SAAS;gCAC5BmB,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;wCAAE,GAAGK,WAAW;wCAAEvB,WAAWiE,EAAEhC,MAAM,CAAC9C,KAAK;oCAAC;gCAC7EoF,YAAW;gCACXC,SAAS;;0CAGX,MAACpI;gCAAY2G,MAAK;gCAAQlC,IAAI;oCAAEqD,UAAU;oCAAGC,UAAU;gCAAI;;kDACzD,KAAC3H;kDAAW;;kDACZ,KAACI;wCACCuC,OAAOoC,YAAYtB,SAAS,IAAI;wCAChCb,OAAM;wCACN+B,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;gDAAE,GAAGK,WAAW;gDAAEtB,WAAWgE,EAAEhC,MAAM,CAAC9C,KAAK;4CAAc;kDAEzFD,YAAYmF,GAAG,CAAC,CAACI,qBAChB,KAAChI;gDAA0B0C,OAAOsF,KAAKtF,KAAK;0DACzCsF,KAAKrF,KAAK;+CADEqF,KAAKtF,KAAK;;;;;;kCAQjC,MAAC/C;wBAAY6G,WAAU;wBAAWF,MAAK;;0CACrC,KAACzG;gCAAU2G,WAAU;0CAAS;;0CAC9B,MAACtG;gCAAW+H,GAAG;gCAACvF,OAAOuC,kBAAkB,WAAW;gCAAQP,UAAUW;;kDACpE,KAACzF;wCAAiB8C,OAAM;wCAAO4E,uBAAS,KAACrH;4CAAMqG,MAAK;;wCAAY3D,OAAM;;kDACtE,KAAC/C;wCAAiB8C,OAAM;wCAAS4E,uBAAS,KAACrH;4CAAMqG,MAAK;;wCAAY3D,OAAM;;;;;;oBAI3EsC,iCACC;;0CACE,KAACnB;gCAAoBN,WAAWsB,YAAYtB,SAAS;;0CACrD,KAAC3C;gCACC6B,OAAOoD,oBAAoB;gCAC3BpB,UAAUkB;gCACVsC,WAAU;gCACVC,WAAU;;;;kCAKhB,KAAC7H;wBACCqC,OAAM;wBACN2D,MAAK;wBACL5D,OAAOoC,YAAYsD,cAAc,IAAI;wBACrC1D,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;gCAAE,GAAGK,WAAW;gCAAEsD,gBAAgBZ,EAAEhC,MAAM,CAAC9C,KAAK,IAAIiD;4BAAU;wBAC/FmC,YAAW;wBACXC,SAAS;wBACTM,SAAS;wBACTC,MAAM;;;;;;AAMlB;AAEA,SAASC,oBAAoB,EAC3B/D,MAAM,EACNC,KAAK,EACLC,QAAQ,EACRC,QAAQ,EACRE,QAAQ,EACRD,UAAU,EACY;IACtB,MAAM4D,gBAAgBhE;IACtB,MAAM,CAACiE,eAAeC,iBAAiB,GAAGnG,SAExC;IACF,MAAMoG,mBAAmBH,cAAc3E,WAAW,IAAI;IACtD,MAAMoB,kBAAkB,AAACuD,CAAAA,cAActD,YAAY,IAAI,EAAC,EAAGC,IAAI,GAAGC,MAAM,GAAG;IAC3E,MAAMwD,eAAe/F,aAAagG,GAAG,CAACL,cAAc5E,MAAM;IAE1D,MAAM,CAACmB,aAAaC,eAAe,GAAGzC,SAAS;IAE/C,MAAMqD,2BAA2BvD,YAC/B,CAACwD;QACCnB,SAASD,OAAO;YAAE,GAAG+D,aAAa;YAAEtD,cAAcW,YAAYF;QAAU;IAC1E,GACA;QAAClB;QAAOC;QAAU8D;KAAc;IAGlC,MAAMM,2BAA2BzG,YAC/B,CAACiD;QACCZ,SAASD,OAAO;YAAE,GAAG+D,aAAa;YAAEtD,cAAcI,MAAME,MAAM,CAAC9C,KAAK,IAAIiD;QAAU;IACpF,GACA;QAAClB;QAAOC;QAAU8D;KAAc;IAGlC,MAAMO,0BAA0B1G,YAC9B,CAACiD;QACC,MAAMC,kBAAkBD,MAAME,MAAM,CAAC9C,KAAK;QAC1C,IAAI6C,oBAAoBoD,kBAAkB;YACxC;QACF;QAEA,IAAI1D,iBAAiB;YACnByD,iBAAiB;gBAAEM,MAAM;gBAAetG,OAAO6C;YAAgB;YAC/D;QACF;QAEAb,SAASD,OAAO;YAAE,GAAG+D,aAAa;YAAE3E,aAAa0B;QAAgB;IACnE,GACA;QAACoD;QAAkB1D;QAAiBR;QAAOC;QAAU8D;KAAc;IAGrE,MAAMS,qBAAqB5G,YACzB,CAACiD;QACC,MAAM4D,aAAa5D,MAAME,MAAM,CAAC9C,KAAK;QACrC,IAAIwG,eAAeV,cAAc5E,MAAM,EAAE;YACvC;QACF;QAEA,MAAMuF,mBAAmBtG,aAAagG,GAAG,CAACK;QAC1C,IAAI,CAACC,oBAAoBlE,iBAAiB;YACxCyD,iBAAiB;gBAAEM,MAAM;gBAAUtG,OAAOwG;YAAW;YACrD;QACF;QAEAxE,SAASD,OAAO;YAAE,GAAG+D,aAAa;YAAE5E,QAAQsF;QAAW;IACzD,GACA;QAACjE;QAAiBR;QAAOC;QAAU8D;KAAc;IAGnD,MAAMY,qBAAqB/G,YAAY;QACrCqG,iBAAiB;IACnB,GAAG,EAAE;IAEL,MAAMW,qBAAqBhH,YAAY;QACrC,IAAI,CAACoG,eAAe;YAClB;QACF;QAEA,IAAIA,cAAcO,IAAI,KAAK,eAAe;YACxCtE,SAASD,OAAO;gBAAE,GAAG+D,aAAa;gBAAE3E,aAAa4E,cAAc/F,KAAK;gBAAEwC,cAAcS;YAAU;QAChG,OAAO;YACLjB,SAASD,OAAO;gBAAE,GAAG+D,aAAa;gBAAE5E,QAAQ6E,cAAc/F,KAAK;gBAAEwC,cAAcS;YAAU;QAC3F;QAEA+C,iBAAiB;IACnB,GAAG;QAACjE;QAAOC;QAAU+D;QAAeD;KAAc;IAElD,MAAMc,mBAAmBhH,QAAQ;QAC/B,IAAIkG,cAAc3E,WAAW,KAAK,UAAU2E,cAActD,YAAY,EAAE;YACtE,IAAI;gBACF,OAAOO,KAAKM,KAAK,CAACyC,cAActD,YAAY;YAC9C,EAAE,OAAM;gBACN,OAAO,CAAC;YACV;QACF;IACF,GAAG;QAACsD,cAActD,YAAY;QAAEsD,cAAc3E,WAAW;KAAC;IAE1D,qBACE,MAACrD;QAAmBwF,MAAMwC;;0BACxB,MAACpI;gBAAM6F,WAAU;gBAAMC,YAAW;gBAASC,gBAAe;gBAAgBC,KAAK;;kCAC7E,MAAChG;wBAAM6F,WAAU;wBAAMG,KAAK;;0CAC1B,KAACtG;gCACCuG,eAAa,CAAC,cAAc,EAAEmC,cAAclF,IAAI,EAAE;gCAClDgD,MAAK;gCACLC,SAAS,IAAMvB,eAAe,CAACD;0CAE9BA,4BAAc,KAAC3D,kCAAkB,KAACD;;0CAErC,MAACZ;gCAAW2D,SAAQ;gCAAWsC,WAAU;gCAAKpC,IAAI;oCAAEqC,eAAe;gCAAO;;oCAAG;kDAC3D,KAACE;kDAAQ6B,cAAclF,IAAI;;;;;;kCAI/C,MAAClD;wBAAM6F,WAAU;wBAAMG,KAAK;;0CAC1B,KAACxF;gCAAYgG,aAAY;gCAAyBC,WAAU;0CAC1D,cAAA,KAAC/G;oCACCwG,MAAK;oCACLlC,IAAI;wCAAE0C,YAAY;oCAAO;oCACzBP,SAAS,IAAM5B,SAASF;8CAGxB,cAAA,KAAClD;mCAFG;;0CAKR,KAACX;gCAAYgG,aAAY;gCAA0BC,WAAU;0CAC3D,cAAA,KAACpG;oCACCoE,UAAUA;oCACVD,YAAYA;oCACZmC,QAAQ;wCACN,kBAAkB;4CAAEC,iBAAiB,CAACC,QAAUA,MAAMC,OAAO,CAACC,UAAU,CAACC,OAAO;wCAAC;oCACnF;mCACI;;;;;;YAMX,CAACrC,6BACA,MAAC3E;gBAAMiH,SAAS;;kCACd,KAACvG;wBACC6B,OAAM;wBACN2E,uBACE,KAACjH;4BACCkH,SAAS/C,QAAQf,WAAW;4BAC5BiB,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;oCAAE,GAAG+D,aAAa;oCAAE/E,SAAS+D,EAAEhC,MAAM,CAAC+B,OAAO;gCAAC;;;kCAKrF,MAACnH;wBAAM6F,WAAU;wBAAMoB,SAAS;;0CAC9B,KAAC/G;gCACCqC,OAAM;gCACN2D,MAAK;gCACL5D,OAAO8F,cAAclF,IAAI;gCACzBoB,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;wCAAE,GAAG+D,aAAa;wCAAElF,MAAMkE,EAAEhC,MAAM,CAAC9C,KAAK;oCAAC;gCAC1E0B,IAAI;oCAAEqD,UAAU;gCAAE;;0CAGpB,MAAC9H;gCAAY2G,MAAK;gCAAQlC,IAAI;oCAAEsD,UAAU;gCAAI;;kDAC5C,KAAC3H;kDAAW;;kDACZ,MAACI;wCACCuC,OAAO8F,cAAcvF,IAAI,IAAI;wCAC7BN,OAAM;wCACN+B,UAAU,CAAC8C,IACT9C,SAASD,OAAO;gDAAE,GAAG+D,aAAa;gDAAEvF,MAAM,AAACuE,EAAEhC,MAAM,CAAC9C,KAAK,IAAmBiD;4CAAU;;0DAGxF,KAAC3F;gDAAS0C,OAAM;0DACd,cAAA,KAACiF;8DAAG;;;4CAEL3E,aAAa4E,GAAG,CAAC,CAACC,2BACjB,KAAC7H;oDAAgC0C,OAAOmF,WAAWnF,KAAK;8DACtD,cAAA,MAACtC;wDAAM6F,WAAU;wDAAMC,YAAW;wDAASmB,SAAS;;4DACjDQ,WAAW5E,IAAI;0EAChB,KAACyD;0EAAMmB,WAAWlF,KAAK;;;;mDAHZkF,WAAWnF,KAAK;;;;;;;kCAWvC,KAACpC;wBACCqC,OAAM;wBACN2D,MAAK;wBACL5D,OAAO8F,cAAc7E,GAAG;wBACxBe,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;gCAAE,GAAG+D,aAAa;gCAAE7E,KAAK6D,EAAEhC,MAAM,CAAC9C,KAAK;4BAAC;wBACzEoF,YAAY3E;wBACZ4E,SAAS;;kCAGX,MAAC3H;wBAAM6F,WAAU;wBAAMoB,SAAS;;0CAC9B,MAAC1H;gCAAY2G,MAAK;gCAAQlC,IAAI;oCAAEsD,UAAU;gCAAI;;kDAC5C,KAAC3H;kDAAW;;kDACZ,KAACI;wCAAOuC,OAAO8F,cAAc5E,MAAM;wCAAEjB,OAAM;wCAAS+B,UAAUuE;kDAC3DzG,aAAaoF,GAAG,CAAC,CAAChE,uBACjB,KAAC5D;gDAAsB0C,OAAOkB;0DAC3BA;+CADYA;;;;0CAOrB,MAACjE;gCAAY2G,MAAK;gCAAQlC,IAAI;oCAAEqD,UAAU;gCAAE;;kDAC1C,KAAC1H;kDAAW;;kDACZ,KAACI;wCACCuC,OAAO8F,cAAchF,SAAS;wCAC9Bb,OAAM;wCACN+B,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;gDAAE,GAAG+D,aAAa;gDAAEhF,WAAWgE,EAAEhC,MAAM,CAAC9C,KAAK;4CAAc;kDAE3FD,YAAYmF,GAAG,CAAC,CAACI,qBAChB,KAAChI;gDAA0B0C,OAAOsF,KAAKtF,KAAK;0DACzCsF,KAAKrF,KAAK;+CADEqF,KAAKtF,KAAK;;;;;;kCAQjC,MAAC/C;wBAAY6G,WAAU;wBAAWF,MAAK;;0CACrC,KAACzG;gCAAU2G,WAAU;0CAAS;;0CAC9B,KAACtG;gCAAW+H,GAAG;gCAACvF,OAAOiG;gCAAkBjE,UAAUqE;0CAChDnG,cAAcgF,GAAG,CAAC,CAAC2B,uBAClB,KAAC3J;wCAEC8C,OAAO6G,OAAO7G,KAAK;wCACnB4E,uBAAS,KAACrH;4CAAMqG,MAAK;;wCACrB3D,OAAO4G,OAAO5G,KAAK;uCAHd4G,OAAO7G,KAAK;;;;oBASxBkG,gBAAgBD,qBAAqB,wBACpC,MAACvJ;;0CACC,KAACmB;gCAAW2D,SAAQ;gCAAQC,OAAM;gCAAiBC,IAAI;oCAAEC,IAAI;gCAAE;0CAC5DsE,qBAAqB,SAAS,yBAAyB;;0CAE1D,KAAC7E;gCAAoBN,WAAWgF,cAAchF,SAAS;;4BACtDmF,qBAAqB,uBACpB,KAAC9H;gCACC6B,OAAO4G,oBAAoB;gCAC3B5E,UAAUkB;gCACVsC,WAAU;gCACVC,WAAU;+CAGZ,KAAC7H;gCACCoC,OAAO8F,cAActD,YAAY,IAAI;gCACrCR,UAAUoE;gCACVf,SAAS;gCACTM,SAAS;gCACTC,MAAM;;;;kCAMd,KAAChI;wBACCqC,OAAM;wBACN2D,MAAK;wBACL5D,OAAO8F,cAAcJ,cAAc,IAAI;wBACvC1D,UAAU,CAAC8C,IAAM9C,SAASD,OAAO;gCAAE,GAAG+D,aAAa;gCAAEJ,gBAAgBZ,EAAEhC,MAAM,CAAC9C,KAAK,IAAIiD;4BAAU;wBACjGmC,YAAW;wBACXC,SAAS;wBACTM,SAAS;wBACTC,MAAM;;;;0BAKZ,MAAChJ;gBAAOkK,MAAMC,QAAQhB;gBAAgBiB,SAASN;gBAAoBO,mBAAgB;;kCACjF,KAACjK;wBAAYkK,IAAG;kCAA6B;;kCAC7C,KAACpK;kCACC,cAAA,KAACC;sCAAmBsD;;;kCAEtB,MAACxD;;0CACC,KAACF;gCAAOkH,SAAS6C;0CAAoB;;0CACrC,KAAC/J;gCAAOkH,SAAS8C;gCAAoBnF,SAAQ;gCAAYC,OAAM;0CAAU;;;;;;;;AAOnF;AAEA,OAAO,SAAS0F,2BAA2B,EACzCC,aAAa,EACbC,gBAAgB,EAChBC,eAAe,EACfC,iBAAiB,EACe;IAChC,MAAMC,UAAU5H,QACd,IAAMwH,iBAAiB;YAAErG,SAAS;YAAM0G,iBAAiB;YAAMC,iBAAiB;QAAM,GACtF;QAACN;KAAc;IAGjB,MAAMO,4BAAqD,CAACC,GAAY/C;QACtEyC,gBAAgB;YAAE,GAAGE,OAAO;YAAEzG,SAAS8D,UAAU,OAAO5B;QAAU;IACpE;IAEA,MAAM4E,8BAAuD,CAACD,GAAY/C;QACxE0C,kBAAkB;YAAE,GAAGF,gBAAgB;YAAEtG,SAAS8D,UAAU,OAAO5B;QAAU;IAC/E;IAEA,MAAM6E,8BAAuD,CAACF,GAAY/C;QACxEyC,gBAAgB;YAAE,GAAGE,OAAO;YAAEC,iBAAiB5C,UAAU,OAAO5B;QAAU;IAC5E;IAEA,MAAM8E,8BAAuD,CAACH,GAAY/C;QACxEyC,gBAAgB;YAAE,GAAGE,OAAO;YAAEE,iBAAiB7C,UAAU,OAAO5B;QAAU;IAC5E;IAEA,MAAM+E,uBAAuBrI,YAAY;QACvC2H,gBAAgB;YAAE,GAAGE,OAAO;YAAES,aAAa;mBAAKT,QAAQS,WAAW,IAAI,EAAE;gBAAGvH;aAA2B;QAAC;IAC1G,GAAG;QAAC8G;QAASF;KAAgB;IAE7B,MAAMY,yBAAyBvI,YAAY;QACzC2H,gBAAgB;YAAE,GAAGE,OAAO;YAAES,aAAa;mBAAKT,QAAQS,WAAW,IAAI,EAAE;gBAAGjH;aAA6B;QAAC;IAC5G,GAAG;QAACwG;QAASF;KAAgB;IAE7B,MAAMa,qBAAqBxI,YACzB,CAACoC,OAAeqG;QACd,MAAMC,aAAab,QAAQS,WAAW,GAAG;eAAIT,QAAQS,WAAW;SAAC,GAAG,EAAE;QACtEI,UAAU,CAACtG,MAAM,GAAGqG;QACpBd,gBAAgB;YAAE,GAAGE,OAAO;YAAES,aAAaI;QAAW;IACxD,GACA;QAACb;QAASF;KAAgB;IAG5B,MAAMgB,qBAAqB3I,YACzB,CAACoC;QACC,MAAMsG,aAAab,QAAQS,WAAW,GAAGT,QAAQS,WAAW,CAACM,MAAM,CAAC,CAACX,GAAGY,IAAMA,MAAMzG,SAAS,EAAE;QAC/FuF,gBAAgBe,WAAW3F,MAAM,GAAG,IAAI;YAAE,GAAG8E,OAAO;YAAES,aAAaI;QAAW,IAAIpF;IACpF,GACA;QAACuE;QAASF;KAAgB;IAG5BhJ,sBAAsB;QACpBmK,UAAUjB,QAAQS,WAAW;QAC7BS,WAAW;QACX1G,UAAU,CAAC2G;YACTrB,gBAAgB;gBAAE,GAAGE,OAAO;gBAAES,aAAaU;YAAuC;QACpF;IACF;IAEA,qBACE,MAACjL;QAAMiH,SAAS;;0BACd,KAACvG;gBACC6B,OAAM;gBACNiE,aAAY;gBACZU,uBAAS,KAACjH;oBAAOkH,SAASwC,kBAAkBtG,WAAW;oBAAOiB,UAAU6F;;;0BAE1E,KAACzJ;gBACC6B,OAAM;gBACNiE,aAAY;gBACZU,uBAAS,KAACjH;oBAAOkH,SAASuC,eAAerG,WAAW;oBAAOiB,UAAU2F;;;0BAEvE,KAACvJ;gBACC6B,OAAM;gBACNiE,aAAY;gBACZU,uBAAS,KAACjH;oBAAOkH,SAASuC,eAAeK,mBAAmB;oBAAOzF,UAAU8F;;;0BAE/E,KAAC1J;gBACC6B,OAAM;gBACNiE,aAAY;gBACZU,uBAAS,KAACjH;oBAAOkH,SAASuC,eAAeM,mBAAmB;oBAAO1F,UAAU+F;;;0BAE/E,KAAC1J;gBAAmBuK,OAAM;0BACxB,cAAA,MAAClL;oBAAMiH,SAAS;;wBACb,CAAC6C,QAAQS,WAAW,IAAIT,QAAQS,WAAW,CAACvF,MAAM,KAAK,kBACtD,KAAC7E;4BAAW2D,SAAQ;4BAAQC,OAAM;4BAAiBoH,WAAU;sCAAS;2CAItE,KAACnL;4BAAMiH,SAAS;4BAAGmE,QAAO;sCACvBtB,QAAQS,WAAW,IAClBT,QAAQS,WAAW,CAAC/C,GAAG,CAAC,CAACpD,QAAQC,sBAC/B,KAACrF;oCAAgBqM,cAAc;oCAAGC,aAAa,CAACzE,QAAUA,MAAMC,OAAO,CAACyE,OAAO;oCAAEC,IAAI;8CAClFpH,OAAOnB,IAAI,KAAK,wBACf,KAACkB;wCACCC,QAAQA;wCACRC,OAAOA;wCACPC,UAAUmG;wCACVlG,UAAUqG;wCACVpG,YAAY,IACVoF,gBAAgB;gDAAE,GAAGE,OAAO;gDAAES,aAAajK,eAAe8D,QAAQ0F,QAAQS,WAAW;4CAAG;wCAE1F9F,UAAU,IACRmF,gBAAgB;gDAAE,GAAGE,OAAO;gDAAES,aAAahK,aAAa6D,QAAQ0F,QAAQS,WAAW;4CAAG;uDAI1F,KAACpC;wCACC/D,QAAQA;wCACRC,OAAOA;wCACPC,UAAUmG;wCACVlG,UAAUqG;wCACVpG,YAAY,IACVoF,gBAAgB;gDAAE,GAAGE,OAAO;gDAAES,aAAajK,eAAe8D,QAAQ0F,QAAQS,WAAW;4CAAG;wCAE1F9F,UAAU,IACRmF,gBAAgB;gDAAE,GAAGE,OAAO;gDAAES,aAAahK,aAAa6D,QAAQ0F,QAAQS,WAAW;4CAAG;;mCAxBpFlG;;sCAiClB,MAACrE;4BAAM6F,WAAU;4BAAMoB,SAAS;;8CAC9B,KAAChI;oCAAO6E,SAAQ;oCAAY2H,yBAAW,KAAC/J;oCAAayE,SAASmE;8CAAsB;;8CAGpF,KAACrL;oCAAO6E,SAAQ;oCAAY2H,yBAAW,KAAC/J;oCAAayE,SAASqE;8CAAwB;;;;;;;;;AAQlG"}
1
+ {"version":3,"sources":["../../../src/components/ItemSelectionActionsOptionsEditor/ItemSelectionActionsOptionsEditor.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { SwitchProps } from '@mui/material';\nimport {\n Box,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n FormControl,\n FormControlLabel,\n FormLabel,\n IconButton,\n InputLabel,\n MenuItem,\n Radio,\n RadioGroup,\n Select,\n Stack,\n Switch,\n TextField,\n Typography,\n} from '@mui/material';\nimport type { SelectChangeEvent } from '@mui/material/Select';\nimport {\n DragAndDropElement,\n DragButton,\n handleMoveDown,\n handleMoveUp,\n InfoTooltip,\n JSONEditor,\n OptionsEditorControl,\n OptionsEditorGroup,\n useDragAndDropMonitor,\n} from '@perses-dev/components';\nimport AlertIcon from 'mdi-material-ui/Alert';\nimport CheckIcon from 'mdi-material-ui/Check';\nimport ChevronDown from 'mdi-material-ui/ChevronDown';\nimport ChevronRight from 'mdi-material-ui/ChevronRight';\nimport CloseIcon from 'mdi-material-ui/Close';\nimport SettingsIcon from 'mdi-material-ui/Cog';\nimport DeleteIcon from 'mdi-material-ui/DeleteOutline';\nimport DownloadIcon from 'mdi-material-ui/Download';\nimport InfoIcon from 'mdi-material-ui/InformationOutline';\nimport LinkIcon from 'mdi-material-ui/Link';\nimport MagnifyScan from 'mdi-material-ui/MagnifyScan';\nimport PauseIcon from 'mdi-material-ui/Pause';\nimport PlayIcon from 'mdi-material-ui/Play';\nimport PlusIcon from 'mdi-material-ui/Plus';\nimport RefreshIcon from 'mdi-material-ui/Refresh';\nimport RobotOutline from 'mdi-material-ui/RobotOutline';\nimport SendIcon from 'mdi-material-ui/Send';\nimport StopIcon from 'mdi-material-ui/Stop';\nimport SyncIcon from 'mdi-material-ui/Sync';\nimport UploadIcon from 'mdi-material-ui/Upload';\nimport type { ReactElement } from 'react';\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nexport type ActionIcon =\n | 'play'\n | 'pause'\n | 'stop'\n | 'delete'\n | 'refresh'\n | 'send'\n | 'download'\n | 'upload'\n | 'check'\n | 'close'\n | 'alert'\n | 'info'\n | 'settings'\n | 'link'\n | 'sync'\n | 'troubleshoot'\n | 'ask-ai';\n\nexport interface BaseAction {\n type: 'event' | 'webhook';\n name: string;\n confirmMessage?: string;\n icon?: ActionIcon;\n enabled?: boolean;\n batchMode: BatchMode;\n bodyTemplate?: string;\n}\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\nexport type BatchMode = 'batch' | 'individual';\n\nexport type ContentType = 'none' | 'json' | 'text';\n\nexport interface WebhookAction extends BaseAction {\n type: 'webhook';\n url: string;\n method: HttpMethod;\n contentType: ContentType;\n headers?: Record<string, string>;\n}\n\nexport interface EventAction extends BaseAction {\n type: 'event';\n eventName: string;\n}\n\nexport type ItemAction = EventAction | WebhookAction;\n\nexport interface ActionOptions {\n enabled?: boolean;\n actionsList?: ItemAction[];\n displayInHeader?: boolean;\n displayWithItem?: boolean;\n}\n\nexport interface SelectionOptions {\n enabled?: boolean;\n}\n\nexport interface ItemSelectionActionsEditorProps {\n actionOptions?: ActionOptions;\n selectionOptions?: SelectionOptions;\n onChangeActions: (actions?: ActionOptions) => void;\n onChangeSelection: (selection?: SelectionOptions) => void;\n}\n\nconst HTTP_METHODS: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\nconst BATCH_MODES: Array<{ value: BatchMode; label: string }> = [\n { value: 'individual', label: 'Individual (one request per selection)' },\n { value: 'batch', label: 'Batch (single request with all selections)' },\n];\nconst CONTENT_TYPES: Array<{ value: ContentType; label: string }> = [\n { value: 'none', label: 'None' },\n { value: 'json', label: 'JSON' },\n { value: 'text', label: 'Text' },\n];\nconst BODY_METHODS: Set<HttpMethod> = new Set(['POST', 'PUT', 'PATCH']);\nconst BODY_CLEAR_CONFIRM_MESSAGE = 'Changing this option will remove the current body template. Continue?';\n\n/** Available action icons with their display components */\nexport const ACTION_ICONS: Array<{ value: ActionIcon; label: string; icon: ReactElement }> = [\n { value: 'play', label: 'Play', icon: <PlayIcon fontSize=\"inherit\" /> },\n { value: 'pause', label: 'Pause', icon: <PauseIcon fontSize=\"inherit\" /> },\n { value: 'stop', label: 'Stop', icon: <StopIcon fontSize=\"inherit\" /> },\n { value: 'delete', label: 'Delete', icon: <DeleteIcon fontSize=\"inherit\" /> },\n { value: 'refresh', label: 'Refresh', icon: <RefreshIcon fontSize=\"inherit\" /> },\n { value: 'send', label: 'Send', icon: <SendIcon fontSize=\"inherit\" /> },\n { value: 'download', label: 'Download', icon: <DownloadIcon fontSize=\"inherit\" /> },\n { value: 'upload', label: 'Upload', icon: <UploadIcon fontSize=\"inherit\" /> },\n { value: 'check', label: 'Check', icon: <CheckIcon fontSize=\"inherit\" /> },\n { value: 'close', label: 'Close', icon: <CloseIcon fontSize=\"inherit\" /> },\n { value: 'alert', label: 'Alert', icon: <AlertIcon fontSize=\"inherit\" /> },\n { value: 'info', label: 'Info', icon: <InfoIcon fontSize=\"inherit\" /> },\n { value: 'settings', label: 'Settings', icon: <SettingsIcon fontSize=\"inherit\" /> },\n { value: 'link', label: 'Link', icon: <LinkIcon fontSize=\"inherit\" /> },\n { value: 'sync', label: 'Sync', icon: <SyncIcon fontSize=\"inherit\" /> },\n { value: 'troubleshoot', label: 'Troubleshoot', icon: <MagnifyScan fontSize=\"inherit\" /> },\n { value: 'ask-ai', label: 'Ask AI', icon: <RobotOutline fontSize=\"inherit\" /> },\n];\n\nconst URL_HELPER_TEXT = 'Supports interpolation: ${__data.fields[\"fieldName\"]}, ${__data.index}, ${__data.count}';\n\nfunction createDefaultEventAction(): EventAction {\n return {\n type: 'event',\n name: 'New Event Action',\n eventName: 'selection-action',\n batchMode: 'individual',\n enabled: true,\n };\n}\n\nfunction createDefaultWebhookAction(): WebhookAction {\n return {\n type: 'webhook',\n name: 'New Webhook Action',\n url: '',\n method: 'POST',\n contentType: 'none',\n batchMode: 'individual',\n enabled: true,\n };\n}\n\ninterface ItemActionEditorProps {\n action: ItemAction;\n index: number;\n onChange: (index: number, action: ItemAction) => void;\n onRemove: (index: number) => void;\n onMoveUp: () => void;\n onMoveDown: () => void;\n}\n\ninterface InterpolationHelperProps {\n batchMode: BatchMode;\n}\n\nfunction InterpolationHelper({ batchMode }: InterpolationHelperProps): ReactElement {\n let content: ReactElement = (\n <div>\n Individual mode patterns: <code>{'${__data.fields[\"field\"]}'}</code>, <code>{'${__data.index}'}</code>,{' '}\n <code>{'${__data.count}'}</code>\n </div>\n );\n\n if (batchMode === 'batch') {\n content = (\n <div>\n Batch mode patterns: <code>{'${__data}'}</code>, <code>{\"${__data[0].fields['field']}\"}</code>,{' '}\n <code>{\"${__data.fields['field']:csv}\"}</code>, <code>{'${__data.count}'}</code>\n </div>\n );\n }\n\n return (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ mb: 1, display: 'block' }}>\n {content}\n </Typography>\n );\n}\n\nfunction EventActionEditor({\n action,\n index,\n onChange,\n onRemove,\n onMoveDown,\n onMoveUp,\n}: ItemActionEditorProps): ReactElement {\n const eventAction = action as EventAction;\n const dragHandleRef = useRef<HTMLButtonElement>(null);\n\n const [isCollapsed, setIsCollapsed] = useState(true);\n const hasBodyTemplate = (eventAction.bodyTemplate ?? '').trim().length > 0;\n\n const handleIncludesTemplateChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const nextContentType = event.target.value as 'custom' | 'none';\n\n const bodyTemplate = nextContentType === 'custom' ? JSON.stringify({}) : undefined;\n\n onChange(index, { ...eventAction, bodyTemplate: bodyTemplate });\n },\n [index, onChange, eventAction],\n );\n\n const handleBodyTemplateChange = useCallback(\n (template: string) => {\n onChange(index, { ...eventAction, bodyTemplate: template || undefined });\n },\n [index, onChange, eventAction],\n );\n\n const jsonDataTemplate = useMemo(() => {\n if (eventAction.bodyTemplate) {\n try {\n return JSON.parse(eventAction.bodyTemplate);\n } catch {\n return {};\n }\n }\n }, [eventAction.bodyTemplate]);\n\n return (\n <DragAndDropElement data={eventAction as unknown as Record<string, unknown>} dragHandleRef={dragHandleRef}>\n <Stack direction=\"row\" alignItems=\"center\" justifyContent=\"space-between\" gap={4}>\n <Stack direction=\"row\" gap={1}>\n <IconButton\n data-testid={`event-action-toggle#${eventAction.name}`}\n size=\"small\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n >\n {isCollapsed ? <ChevronRight /> : <ChevronDown />}\n </IconButton>\n <Typography variant=\"overline\" component=\"h4\" sx={{ textTransform: 'none' }}>\n EVENT ACTION:{' '}\n {eventAction.name ? (\n <span>\n <strong>{eventAction.name}</strong>\n </span>\n ) : (\n <strong>{eventAction.name}</strong>\n )}\n </Typography>\n </Stack>\n\n <Stack direction=\"row\" gap={1}>\n <InfoTooltip description=\"Remove action settings\" placement=\"top\">\n <IconButton\n size=\"small\"\n sx={{ marginLeft: 'auto' }}\n onClick={() => onRemove(index)}\n key=\"delete-action-button\"\n >\n <DeleteIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description=\"Reorder action settings\" placement=\"top\">\n <DragButton\n ref={dragHandleRef}\n onMoveUp={onMoveUp}\n onMoveDown={onMoveDown}\n menuSx={{\n '.MuiPaper-root': { backgroundColor: (theme) => theme.palette.background.lighter },\n }}\n key=\"reorder-action-button\"\n />\n </InfoTooltip>\n </Stack>\n </Stack>\n\n {!isCollapsed && (\n <Stack spacing={2}>\n <OptionsEditorControl\n label=\"Enabled\"\n control={\n <Switch\n checked={eventAction?.enabled ?? false}\n onChange={(e) => onChange(index, { ...eventAction, enabled: e.target.checked })}\n />\n }\n />\n\n <Stack direction=\"row\" spacing={2}>\n <TextField\n label=\"Action Name\"\n size=\"small\"\n value={eventAction.name}\n onChange={(e) => onChange(index, { ...eventAction, name: e.target.value })}\n sx={{ flexGrow: 1 }}\n />\n\n <FormControl size=\"small\" sx={{ minWidth: 120 }}>\n <InputLabel>Icon</InputLabel>\n <Select\n value={eventAction.icon || ''}\n label=\"Icon\"\n onChange={(e) => onChange(index, { ...eventAction, icon: (e.target.value as ActionIcon) || undefined })}\n >\n <MenuItem value=\"\">\n <em>None</em>\n </MenuItem>\n {ACTION_ICONS.map((iconOption) => (\n <MenuItem key={iconOption.value} value={iconOption.value}>\n <Stack direction=\"row\" alignItems=\"center\" spacing={1}>\n {iconOption.icon}\n <span>{iconOption.label}</span>\n </Stack>\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <Stack direction=\"row\" spacing={2}>\n <TextField\n label=\"Event Name\"\n size=\"small\"\n value={eventAction.eventName}\n onChange={(e) => onChange(index, { ...eventAction, eventName: e.target.value })}\n helperText=\"Name of the CustomEvent to dispatch (e.g., 'selection-action')\"\n fullWidth\n />\n\n <FormControl size=\"small\" sx={{ flexGrow: 1, minWidth: 280 }}>\n <InputLabel>Batch Mode</InputLabel>\n <Select\n value={eventAction.batchMode ?? 'individual'}\n label=\"Batch Mode\"\n onChange={(e) => onChange(index, { ...eventAction, batchMode: e.target.value as BatchMode })}\n >\n {BATCH_MODES.map((mode) => (\n <MenuItem key={mode.value} value={mode.value}>\n {mode.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <FormControl component=\"fieldset\" size=\"small\">\n <FormLabel component=\"legend\">Template</FormLabel>\n <RadioGroup row value={hasBodyTemplate ? 'custom' : 'none'} onChange={handleIncludesTemplateChange}>\n <FormControlLabel value=\"none\" control={<Radio size=\"small\" />} label=\"None\" />\n <FormControlLabel value=\"custom\" control={<Radio size=\"small\" />} label=\"JSON template\" />\n </RadioGroup>\n </FormControl>\n\n {hasBodyTemplate && (\n <>\n <InterpolationHelper batchMode={eventAction.batchMode} />\n <JSONEditor\n value={jsonDataTemplate || ''}\n onChange={handleBodyTemplateChange}\n minHeight=\"100px\"\n maxHeight=\"200px\"\n />\n </>\n )}\n\n <TextField\n label=\"Confirmation Message (optional)\"\n size=\"small\"\n value={eventAction.confirmMessage || ''}\n onChange={(e) => onChange(index, { ...eventAction, confirmMessage: e.target.value || undefined })}\n helperText=\"If set, shows a confirmation dialog before executing the action\"\n fullWidth\n multiline\n rows={2}\n />\n </Stack>\n )}\n </DragAndDropElement>\n );\n}\n\nfunction WebhookActionEditor({\n action,\n index,\n onChange,\n onRemove,\n onMoveUp,\n onMoveDown,\n}: ItemActionEditorProps): ReactElement {\n const webhookAction = action as WebhookAction;\n const dragHandleRef = useRef<HTMLButtonElement>(null);\n const [pendingChange, setPendingChange] = useState<\n { kind: 'contentType'; value: ContentType } | { kind: 'method'; value: HttpMethod } | null\n >(null);\n const contentTypeValue = webhookAction.contentType ?? 'none';\n const hasBodyTemplate = (webhookAction.bodyTemplate ?? '').trim().length > 0;\n const supportsBody = BODY_METHODS.has(webhookAction.method);\n\n const [isCollapsed, setIsCollapsed] = useState(true);\n\n const handleBodyTemplateChange = useCallback(\n (template: string) => {\n onChange(index, { ...webhookAction, bodyTemplate: template || undefined });\n },\n [index, onChange, webhookAction],\n );\n\n const handleTextTemplateChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n onChange(index, { ...webhookAction, bodyTemplate: event.target.value || undefined });\n },\n [index, onChange, webhookAction],\n );\n\n const handleContentTypeChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const nextContentType = event.target.value as ContentType;\n if (nextContentType === contentTypeValue) {\n return;\n }\n\n if (hasBodyTemplate) {\n setPendingChange({ kind: 'contentType', value: nextContentType });\n return;\n }\n\n onChange(index, { ...webhookAction, contentType: nextContentType });\n },\n [contentTypeValue, hasBodyTemplate, index, onChange, webhookAction],\n );\n\n const handleMethodChange = useCallback(\n (event: SelectChangeEvent<HttpMethod>) => {\n const nextMethod = event.target.value as HttpMethod;\n if (nextMethod === webhookAction.method) {\n return;\n }\n\n const nextSupportsBody = BODY_METHODS.has(nextMethod);\n if (!nextSupportsBody && hasBodyTemplate) {\n setPendingChange({ kind: 'method', value: nextMethod });\n return;\n }\n\n onChange(index, { ...webhookAction, method: nextMethod });\n },\n [hasBodyTemplate, index, onChange, webhookAction],\n );\n\n const handleConfirmClose = useCallback(() => {\n setPendingChange(null);\n }, []);\n\n const handleConfirmApply = useCallback(() => {\n if (!pendingChange) {\n return;\n }\n\n if (pendingChange.kind === 'contentType') {\n onChange(index, { ...webhookAction, contentType: pendingChange.value, bodyTemplate: undefined });\n } else {\n onChange(index, { ...webhookAction, method: pendingChange.value, bodyTemplate: undefined });\n }\n\n setPendingChange(null);\n }, [index, onChange, pendingChange, webhookAction]);\n\n const jsonBodyTemplate = useMemo(() => {\n if (webhookAction.contentType === 'json' && webhookAction.bodyTemplate) {\n try {\n return JSON.parse(webhookAction.bodyTemplate);\n } catch {\n return {};\n }\n }\n }, [webhookAction.bodyTemplate, webhookAction.contentType]);\n\n return (\n <DragAndDropElement data={webhookAction as unknown as Record<string, unknown>} dragHandleRef={dragHandleRef}>\n <Stack direction=\"row\" alignItems=\"center\" justifyContent=\"space-between\" gap={4}>\n <Stack direction=\"row\" gap={1}>\n <IconButton\n data-testid={`column-toggle#${webhookAction.name}`}\n size=\"small\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n >\n {isCollapsed ? <ChevronRight /> : <ChevronDown />}\n </IconButton>\n <Typography variant=\"overline\" component=\"h4\" sx={{ textTransform: 'none' }}>\n WEBHOOK ACTION: <strong>{webhookAction.name}</strong>\n </Typography>\n </Stack>\n\n <Stack direction=\"row\" gap={1}>\n <InfoTooltip description=\"Remove action settings\" placement=\"top\">\n <IconButton\n size=\"small\"\n sx={{ marginLeft: 'auto' }}\n onClick={() => onRemove(index)}\n key=\"delete-action-button\"\n >\n <DeleteIcon />\n </IconButton>\n </InfoTooltip>\n <InfoTooltip description=\"Reorder action settings\" placement=\"top\">\n <DragButton\n ref={dragHandleRef}\n onMoveUp={onMoveUp}\n onMoveDown={onMoveDown}\n menuSx={{\n '.MuiPaper-root': { backgroundColor: (theme) => theme.palette.background.lighter },\n }}\n key=\"reorder-action-button\"\n />\n </InfoTooltip>\n </Stack>\n </Stack>\n\n {!isCollapsed && (\n <Stack spacing={2}>\n <OptionsEditorControl\n label=\"Enabled\"\n control={\n <Switch\n checked={action?.enabled ?? false}\n onChange={(e) => onChange(index, { ...webhookAction, enabled: e.target.checked })}\n />\n }\n />\n\n <Stack direction=\"row\" spacing={2}>\n <TextField\n label=\"Action Name\"\n size=\"small\"\n value={webhookAction.name}\n onChange={(e) => onChange(index, { ...webhookAction, name: e.target.value })}\n sx={{ flexGrow: 1 }}\n />\n\n <FormControl size=\"small\" sx={{ minWidth: 120 }}>\n <InputLabel>Icon</InputLabel>\n <Select\n value={webhookAction.icon || ''}\n label=\"Icon\"\n onChange={(e) =>\n onChange(index, { ...webhookAction, icon: (e.target.value as ActionIcon) || undefined })\n }\n >\n <MenuItem value=\"\">\n <em>None</em>\n </MenuItem>\n {ACTION_ICONS.map((iconOption) => (\n <MenuItem key={iconOption.value} value={iconOption.value}>\n <Stack direction=\"row\" alignItems=\"center\" spacing={1}>\n {iconOption.icon}\n <span>{iconOption.label}</span>\n </Stack>\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <TextField\n label=\"URL\"\n size=\"small\"\n value={webhookAction.url}\n onChange={(e) => onChange(index, { ...webhookAction, url: e.target.value })}\n helperText={URL_HELPER_TEXT}\n fullWidth\n />\n\n <Stack direction=\"row\" spacing={2}>\n <FormControl size=\"small\" sx={{ minWidth: 120 }}>\n <InputLabel>Method</InputLabel>\n <Select value={webhookAction.method} label=\"Method\" onChange={handleMethodChange}>\n {HTTP_METHODS.map((method) => (\n <MenuItem key={method} value={method}>\n {method}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n\n <FormControl size=\"small\" sx={{ flexGrow: 1 }}>\n <InputLabel>Batch Mode</InputLabel>\n <Select\n value={webhookAction.batchMode}\n label=\"Batch Mode\"\n onChange={(e) => onChange(index, { ...webhookAction, batchMode: e.target.value as BatchMode })}\n >\n {BATCH_MODES.map((mode) => (\n <MenuItem key={mode.value} value={mode.value}>\n {mode.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <FormControl component=\"fieldset\" size=\"small\">\n <FormLabel component=\"legend\">Content Type</FormLabel>\n <RadioGroup row value={contentTypeValue} onChange={handleContentTypeChange}>\n {CONTENT_TYPES.map((option) => (\n <FormControlLabel\n key={option.value}\n value={option.value}\n control={<Radio size=\"small\" />}\n label={option.label}\n />\n ))}\n </RadioGroup>\n </FormControl>\n\n {supportsBody && contentTypeValue !== 'none' && (\n <Box>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mb: 1 }}>\n {contentTypeValue === 'json' ? 'Body Template (JSON)' : 'Body Template (Text)'}\n </Typography>\n <InterpolationHelper batchMode={webhookAction.batchMode} />\n {contentTypeValue === 'json' ? (\n <JSONEditor\n value={jsonBodyTemplate || ''}\n onChange={handleBodyTemplateChange}\n minHeight=\"100px\"\n maxHeight=\"200px\"\n />\n ) : (\n <TextField\n value={webhookAction.bodyTemplate || ''}\n onChange={handleTextTemplateChange}\n fullWidth\n multiline\n rows={5}\n />\n )}\n </Box>\n )}\n\n <TextField\n label=\"Confirmation Message (optional)\"\n size=\"small\"\n value={webhookAction.confirmMessage || ''}\n onChange={(e) => onChange(index, { ...webhookAction, confirmMessage: e.target.value || undefined })}\n helperText=\"If set, shows a confirmation dialog before executing the action\"\n fullWidth\n multiline\n rows={2}\n />\n </Stack>\n )}\n\n <Dialog open={Boolean(pendingChange)} onClose={handleConfirmClose} aria-labelledby=\"selection-body-clear-title\">\n <DialogTitle id=\"selection-body-clear-title\">Remove Body Template?</DialogTitle>\n <DialogContent>\n <DialogContentText>{BODY_CLEAR_CONFIRM_MESSAGE}</DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleConfirmClose}>Cancel</Button>\n <Button onClick={handleConfirmApply} variant=\"contained\" color=\"primary\">\n Continue\n </Button>\n </DialogActions>\n </Dialog>\n </DragAndDropElement>\n );\n}\n\nexport function ItemSelectionActionsEditor({\n actionOptions,\n selectionOptions,\n onChangeActions,\n onChangeSelection,\n}: ItemSelectionActionsEditorProps): ReactElement {\n const actions = useMemo(\n () => actionOptions || { enabled: true, displayInHeader: true, displayWithItem: false },\n [actionOptions],\n );\n\n const handleEnableActionsChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeActions({ ...actions, enabled: checked ? true : undefined });\n };\n\n const handleEnableSelectionChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeSelection({ ...selectionOptions, enabled: checked ? true : undefined });\n };\n\n const handleDisplayInHeaderChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeActions({ ...actions, displayInHeader: checked ? true : undefined });\n };\n\n const handleDisplayWithItemChange: SwitchProps['onChange'] = (_: unknown, checked: boolean) => {\n onChangeActions({ ...actions, displayWithItem: checked ? true : undefined });\n };\n\n const handleAddEventAction = useCallback(() => {\n onChangeActions({ ...actions, actionsList: [...(actions.actionsList ?? []), createDefaultEventAction()] });\n }, [actions, onChangeActions]);\n\n const handleAddWebhookAction = useCallback(() => {\n onChangeActions({ ...actions, actionsList: [...(actions.actionsList ?? []), createDefaultWebhookAction()] });\n }, [actions, onChangeActions]);\n\n const handleActionChange = useCallback(\n (index: number, updatedAction: ItemAction) => {\n const newActions = actions.actionsList ? [...actions.actionsList] : [];\n newActions[index] = updatedAction;\n onChangeActions({ ...actions, actionsList: newActions });\n },\n [actions, onChangeActions],\n );\n\n const handleRemoveAction = useCallback(\n (index: number) => {\n const newActions = actions.actionsList ? actions.actionsList.filter((_, i) => i !== index) : [];\n onChangeActions(newActions.length > 0 ? { ...actions, actionsList: newActions } : undefined);\n },\n [actions, onChangeActions],\n );\n\n useDragAndDropMonitor({\n elements: actions.actionsList as unknown as Array<Record<string, unknown>>,\n accessKey: 'name',\n onChange: (newElements) => {\n onChangeActions({ ...actions, actionsList: newElements as unknown as ItemAction[] });\n },\n });\n\n return (\n <Stack spacing={1}>\n <OptionsEditorControl\n label=\"Enable Item Selection\"\n description=\"Allow selecting items\"\n control={<Switch checked={selectionOptions?.enabled ?? false} onChange={handleEnableSelectionChange} />}\n />\n <OptionsEditorControl\n label=\"Enable Item Actions\"\n description=\"Allow executing actions on selected items\"\n control={<Switch checked={actionOptions?.enabled ?? false} onChange={handleEnableActionsChange} />}\n />\n <OptionsEditorControl\n label=\"Display Actions in Panel Header\"\n description=\"Show action buttons in the panel header when items are selected\"\n control={<Switch checked={actionOptions?.displayInHeader ?? false} onChange={handleDisplayInHeaderChange} />}\n />\n <OptionsEditorControl\n label=\"Display Actions with Each Item\"\n description=\"Show action buttons alongside each item when selected\"\n control={<Switch checked={actionOptions?.displayWithItem ?? false} onChange={handleDisplayWithItemChange} />}\n />\n <OptionsEditorGroup title=\"Actions\">\n <Stack spacing={3}>\n {!actions.actionsList || actions.actionsList.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\" fontStyle=\"italic\">\n No actions defined. Add an action to enable triggering events or webhooks on selected data.\n </Typography>\n ) : (\n <Stack spacing={1} border=\"none\">\n {actions.actionsList &&\n actions.actionsList.map((action, index) => (\n <Box key={index} borderBottom={1} borderColor={(theme) => theme.palette.divider} pb={1}>\n {action.type === 'event' ? (\n <EventActionEditor\n action={action}\n index={index}\n onChange={handleActionChange}\n onRemove={handleRemoveAction}\n onMoveDown={() =>\n onChangeActions({ ...actions, actionsList: handleMoveDown(action, actions.actionsList!) })\n }\n onMoveUp={() =>\n onChangeActions({ ...actions, actionsList: handleMoveUp(action, actions.actionsList!) })\n }\n />\n ) : (\n <WebhookActionEditor\n action={action}\n index={index}\n onChange={handleActionChange}\n onRemove={handleRemoveAction}\n onMoveDown={() =>\n onChangeActions({ ...actions, actionsList: handleMoveDown(action, actions.actionsList!) })\n }\n onMoveUp={() =>\n onChangeActions({ ...actions, actionsList: handleMoveUp(action, actions.actionsList!) })\n }\n />\n )}\n </Box>\n ))}\n </Stack>\n )}\n\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"contained\" startIcon={<PlusIcon />} onClick={handleAddEventAction}>\n Add Event Action\n </Button>\n <Button variant=\"contained\" startIcon={<PlusIcon />} onClick={handleAddWebhookAction}>\n Add Webhook Action\n </Button>\n </Stack>\n </Stack>\n </OptionsEditorGroup>\n </Stack>\n );\n}\n"],"names":["Box","Button","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","FormControl","FormControlLabel","FormLabel","IconButton","InputLabel","MenuItem","Radio","RadioGroup","Select","Stack","Switch","TextField","Typography","DragAndDropElement","DragButton","handleMoveDown","handleMoveUp","InfoTooltip","JSONEditor","OptionsEditorControl","OptionsEditorGroup","useDragAndDropMonitor","AlertIcon","CheckIcon","ChevronDown","ChevronRight","CloseIcon","SettingsIcon","DeleteIcon","DownloadIcon","InfoIcon","LinkIcon","MagnifyScan","PauseIcon","PlayIcon","PlusIcon","RefreshIcon","RobotOutline","SendIcon","StopIcon","SyncIcon","UploadIcon","useCallback","useMemo","useRef","useState","HTTP_METHODS","BATCH_MODES","value","label","CONTENT_TYPES","BODY_METHODS","Set","BODY_CLEAR_CONFIRM_MESSAGE","ACTION_ICONS","icon","fontSize","URL_HELPER_TEXT","createDefaultEventAction","type","name","eventName","batchMode","enabled","createDefaultWebhookAction","url","method","contentType","InterpolationHelper","content","div","code","variant","color","sx","mb","display","EventActionEditor","action","index","onChange","onRemove","onMoveDown","onMoveUp","eventAction","dragHandleRef","isCollapsed","setIsCollapsed","hasBodyTemplate","bodyTemplate","trim","length","handleIncludesTemplateChange","event","nextContentType","target","JSON","stringify","undefined","handleBodyTemplateChange","template","jsonDataTemplate","parse","data","direction","alignItems","justifyContent","gap","data-testid","size","onClick","component","textTransform","span","strong","description","placement","marginLeft","ref","menuSx","backgroundColor","theme","palette","background","lighter","spacing","control","checked","e","flexGrow","minWidth","em","map","iconOption","helperText","fullWidth","mode","row","minHeight","maxHeight","confirmMessage","multiline","rows","WebhookActionEditor","webhookAction","pendingChange","setPendingChange","contentTypeValue","supportsBody","has","handleTextTemplateChange","handleContentTypeChange","kind","handleMethodChange","nextMethod","nextSupportsBody","handleConfirmClose","handleConfirmApply","jsonBodyTemplate","option","open","Boolean","onClose","aria-labelledby","id","ItemSelectionActionsEditor","actionOptions","selectionOptions","onChangeActions","onChangeSelection","actions","displayInHeader","displayWithItem","handleEnableActionsChange","_","handleEnableSelectionChange","handleDisplayInHeaderChange","handleDisplayWithItemChange","handleAddEventAction","actionsList","handleAddWebhookAction","handleActionChange","updatedAction","newActions","handleRemoveAction","filter","i","elements","accessKey","newElements","title","fontStyle","border","borderBottom","borderColor","divider","pb","startIcon"],"mappings":"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"}
@@ -88,6 +88,7 @@ function LinkControl({ control, index }) {
88
88
  return /*#__PURE__*/ _jsx(LinkEditorForm, {
89
89
  mode: "inline",
90
90
  url: {
91
+ onBlur: field.onBlur,
91
92
  value: safeLink.url,
92
93
  label: 'URL',
93
94
  error: {
@@ -102,6 +103,7 @@ function LinkControl({ control, index }) {
102
103
  }
103
104
  },
104
105
  newTabOpen: {
106
+ onBlur: field.onBlur,
105
107
  value: !!safeLink.targetBlank,
106
108
  onChange: (targetBlank)=>{
107
109
  field.onChange({
@@ -112,6 +114,7 @@ function LinkControl({ control, index }) {
112
114
  label: 'Open in new tab'
113
115
  },
114
116
  name: {
117
+ onBlur: field.onBlur,
115
118
  value: safeLink.name ?? '',
116
119
  label: 'Name',
117
120
  onChange: (name)=>{
@@ -122,6 +125,7 @@ function LinkControl({ control, index }) {
122
125
  }
123
126
  },
124
127
  renderVariables: {
128
+ onBlur: field.onBlur,
125
129
  value: !!safeLink.renderVariables,
126
130
  label: 'Render variables',
127
131
  onChange: (renderVariables)=>{
@@ -132,6 +136,7 @@ function LinkControl({ control, index }) {
132
136
  }
133
137
  },
134
138
  tooltip: {
139
+ onBlur: field.onBlur,
135
140
  value: safeLink.tooltip ?? '',
136
141
  label: 'Tooltip',
137
142
  onChange: (tooltip)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/LinksEditor/LinksEditor.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Divider, IconButton, Stack, Typography } from '@mui/material';\nimport { LinkEditorForm } from '@perses-dev/components';\nimport MinusIcon from 'mdi-material-ui/Minus';\nimport PlusIcon from 'mdi-material-ui/Plus';\nimport type { HTMLAttributes, ReactElement } from 'react';\nimport { Fragment } from 'react';\nimport type { Control } from 'react-hook-form';\nimport { Controller, useFieldArray } from 'react-hook-form';\n\nimport type { PanelEditorValues } from '../../model';\n\nexport interface LinksEditorProps extends HTMLAttributes<HTMLDivElement> {\n control: Control<PanelEditorValues>;\n}\n\nexport function LinksEditor({ control, ...props }: LinksEditorProps): ReactElement {\n const { fields, append, remove } = useFieldArray({\n control: control,\n name: 'panelDefinition.spec.links',\n });\n\n return (\n <Stack {...props} gap={3}>\n {fields && fields.length > 0 ? (\n fields.map((field, index) => (\n <Fragment key={field.id}>\n <Stack direction=\"row\" gap={1} alignItems=\"center\">\n <LinkControl control={control} index={index} />\n <IconButton style={{ width: 'fit-content', height: 'fit-content' }} onClick={() => remove(index)}>\n <MinusIcon />\n </IconButton>\n </Stack>\n <Divider />\n </Fragment>\n ))\n ) : (\n <Typography variant=\"subtitle1\" mb={2} fontStyle=\"italic\">\n No links defined\n </Typography>\n )}\n <IconButton\n style={{ width: 'fit-content', height: 'fit-content' }}\n onClick={() => append({ url: '', name: '', tooltip: '', renderVariables: false, targetBlank: false })}\n >\n <PlusIcon />\n </IconButton>\n </Stack>\n );\n}\n\nfunction LinkControl({ control, index }: { control: Control<PanelEditorValues>; index: number }): ReactElement {\n const defaultLink = { url: '', name: '', tooltip: '', renderVariables: false, targetBlank: false };\n return (\n <Controller\n control={control}\n name={`panelDefinition.spec.links.${index}`}\n render={({ field, field: { value: link }, fieldState }) => {\n const safeLink = link ?? defaultLink;\n return (\n <LinkEditorForm\n mode=\"inline\"\n url={{\n value: safeLink.url,\n label: 'URL',\n error: { hasError: !!fieldState.error, helperText: fieldState.error?.message },\n onChange: (url) => {\n field.onChange({ ...link, url });\n },\n }}\n newTabOpen={{\n value: !!safeLink.targetBlank,\n onChange: (targetBlank) => {\n field.onChange({ ...link, targetBlank });\n },\n label: 'Open in new tab',\n }}\n name={{\n value: safeLink.name ?? '',\n label: 'Name',\n onChange: (name) => {\n field.onChange({ ...link, name });\n },\n }}\n renderVariables={{\n value: !!safeLink.renderVariables,\n label: 'Render variables',\n onChange: (renderVariables) => {\n field.onChange({ ...link, renderVariables });\n },\n }}\n tooltip={{\n value: safeLink.tooltip ?? '',\n label: 'Tooltip',\n onChange: (tooltip) => {\n field.onChange({ ...link, tooltip });\n },\n }}\n />\n );\n }}\n />\n );\n}\n"],"names":["Divider","IconButton","Stack","Typography","LinkEditorForm","MinusIcon","PlusIcon","Fragment","Controller","useFieldArray","LinksEditor","control","props","fields","append","remove","name","gap","length","map","field","index","direction","alignItems","LinkControl","style","width","height","onClick","id","variant","mb","fontStyle","url","tooltip","renderVariables","targetBlank","defaultLink","render","value","link","fieldState","safeLink","mode","label","error","hasError","helperText","message","onChange","newTabOpen"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/LinksEditor/LinksEditor.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Divider, IconButton, Stack, Typography } from '@mui/material';\nimport { LinkEditorForm } from '@perses-dev/components';\nimport MinusIcon from 'mdi-material-ui/Minus';\nimport PlusIcon from 'mdi-material-ui/Plus';\nimport type { HTMLAttributes, ReactElement } from 'react';\nimport { Fragment } from 'react';\nimport type { Control } from 'react-hook-form';\nimport { Controller, useFieldArray } from 'react-hook-form';\n\nimport type { PanelEditorValues } from '../../model';\n\nexport interface LinksEditorProps extends HTMLAttributes<HTMLDivElement> {\n control: Control<PanelEditorValues>;\n}\n\nexport function LinksEditor({ control, ...props }: LinksEditorProps): ReactElement {\n const { fields, append, remove } = useFieldArray({\n control: control,\n name: 'panelDefinition.spec.links',\n });\n\n return (\n <Stack {...props} gap={3}>\n {fields && fields.length > 0 ? (\n fields.map((field, index) => (\n <Fragment key={field.id}>\n <Stack direction=\"row\" gap={1} alignItems=\"center\">\n <LinkControl control={control} index={index} />\n <IconButton style={{ width: 'fit-content', height: 'fit-content' }} onClick={() => remove(index)}>\n <MinusIcon />\n </IconButton>\n </Stack>\n <Divider />\n </Fragment>\n ))\n ) : (\n <Typography variant=\"subtitle1\" mb={2} fontStyle=\"italic\">\n No links defined\n </Typography>\n )}\n <IconButton\n style={{ width: 'fit-content', height: 'fit-content' }}\n onClick={() => append({ url: '', name: '', tooltip: '', renderVariables: false, targetBlank: false })}\n >\n <PlusIcon />\n </IconButton>\n </Stack>\n );\n}\n\nfunction LinkControl({ control, index }: { control: Control<PanelEditorValues>; index: number }): ReactElement {\n const defaultLink = { url: '', name: '', tooltip: '', renderVariables: false, targetBlank: false };\n return (\n <Controller\n control={control}\n name={`panelDefinition.spec.links.${index}`}\n render={({ field, field: { value: link }, fieldState }) => {\n const safeLink = link ?? defaultLink;\n return (\n <LinkEditorForm\n mode=\"inline\"\n url={{\n onBlur: field.onBlur,\n value: safeLink.url,\n label: 'URL',\n error: { hasError: !!fieldState.error, helperText: fieldState.error?.message },\n onChange: (url) => {\n field.onChange({ ...link, url });\n },\n }}\n newTabOpen={{\n onBlur: field.onBlur,\n value: !!safeLink.targetBlank,\n onChange: (targetBlank) => {\n field.onChange({ ...link, targetBlank });\n },\n label: 'Open in new tab',\n }}\n name={{\n onBlur: field.onBlur,\n value: safeLink.name ?? '',\n label: 'Name',\n onChange: (name) => {\n field.onChange({ ...link, name });\n },\n }}\n renderVariables={{\n onBlur: field.onBlur,\n value: !!safeLink.renderVariables,\n label: 'Render variables',\n onChange: (renderVariables) => {\n field.onChange({ ...link, renderVariables });\n },\n }}\n tooltip={{\n onBlur: field.onBlur,\n value: safeLink.tooltip ?? '',\n label: 'Tooltip',\n onChange: (tooltip) => {\n field.onChange({ ...link, tooltip });\n },\n }}\n />\n );\n }}\n />\n );\n}\n"],"names":["Divider","IconButton","Stack","Typography","LinkEditorForm","MinusIcon","PlusIcon","Fragment","Controller","useFieldArray","LinksEditor","control","props","fields","append","remove","name","gap","length","map","field","index","direction","alignItems","LinkControl","style","width","height","onClick","id","variant","mb","fontStyle","url","tooltip","renderVariables","targetBlank","defaultLink","render","value","link","fieldState","safeLink","mode","onBlur","label","error","hasError","helperText","message","onChange","newTabOpen"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-editor-api.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAI9F,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,aAAa,CAAC;AAM3D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,qBAAqB,CAAC;IACjC,IAAI,EAAE,WAAW,CAAC;CACnB;AAID,KAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC;IACxE,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAKD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,OAAO,GAAG,UAAU,CAAC,GAAG;IACjG,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG;IAC5D,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,iBAAiB,EAAE,CAAC,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACtD,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC1C,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC,CA2IA"}
1
+ {"version":3,"file":"plugin-editor-api.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAK9F,OAAO,KAAK,EAAe,UAAU,EAAwB,MAAM,aAAa,CAAC;AAMjF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,qBAAqB,CAAC;IACjC,IAAI,EAAE,WAAW,CAAC;CACnB;AAID,KAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC;IACxE,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAKD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,OAAO,GAAG,UAAU,CAAC,GAAG;IACjG,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG;IAC5D,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,iBAAiB,EAAE,CAAC,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACtD,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC1C,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC,CAkIA"}
@@ -10,9 +10,10 @@
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 { useMutation, useQueryClient } from "@tanstack/react-query";
13
14
  import { produce } from "immer";
14
- import { useState, useRef, useEffect } from "react";
15
- import { usePlugin, usePluginRegistry } from "../../runtime/index.js";
15
+ import { useRef, useEffect } from "react";
16
+ import { usePluginRegistry } from "../../runtime/index.js";
16
17
  import { useEvent } from "../../utils/index.js";
17
18
  /**
18
19
  * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide
@@ -20,7 +21,6 @@ import { useEvent } from "../../utils/index.js";
20
21
  * remembers previous `spec` values that it's seen, allowing and restores those values if a user switches the plugin
21
22
  * kind back.
22
23
  */ export function usePluginEditor(props) {
23
- // eslint-disable-next-line @typescript-eslint/no-empty-function
24
24
  const { pluginTypes, value, onHideQueryEditorChange = ()=>{} } = props; // setting onHideQueryEditorChange to empty function here because useEvent requires a function
25
25
  // Keep a stable reference, so we don't run the effect below when we don't need to
26
26
  const onChange = useEvent(props.onChange);
@@ -43,61 +43,63 @@ import { useEvent } from "../../utils/index.js";
43
43
  const hideQueryState = useRef({
44
44
  [value.selection.kind]: false
45
45
  });
46
- const { defaultPluginKinds } = usePluginRegistry();
46
+ const { defaultPluginKinds, getPlugin } = usePluginRegistry();
47
+ const queryClient = useQueryClient();
48
+ const currentRequest = useRef(undefined);
49
+ const selectionLoad = useMutation({
50
+ mutationFn: (selection)=>queryClient.fetchQuery({
51
+ queryKey: [
52
+ 'getPlugin',
53
+ selection.type,
54
+ selection.kind,
55
+ selection.metadata?.version ?? '',
56
+ selection.metadata?.registry ?? ''
57
+ ],
58
+ queryFn: ()=>getPlugin({
59
+ kind: selection.type,
60
+ name: selection.kind,
61
+ version: selection.metadata?.version,
62
+ registry: selection.metadata?.registry
63
+ })
64
+ })
65
+ });
66
+ const pendingSelection = selectionLoad.isSuccess ? undefined : selectionLoad.variables;
47
67
  const defaultPluginType = pluginTypes[0];
48
68
  const defaultPluginKind = defaultPluginType ? defaultPluginKinds?.[defaultPluginType] : undefined;
49
- const defaultPluginSelection = defaultPluginType && defaultPluginKind ? {
50
- type: defaultPluginType,
51
- kind: defaultPluginKind
52
- } : undefined;
53
- const initPendingSelection = !value.selection && defaultPluginSelection ? defaultPluginSelection : undefined;
54
- // When kind changes and we haven't loaded that plugin before, we will need to enter a "pending" state so that we
55
- // can generate proper initial spec values that match the new plugin kind
56
- const [pendingSelection, setPendingSelection] = useState(initPendingSelection);
57
- // Take a default kind in case user write explicitly an empty kind in the initial value
69
+ // Notify the owner instead of mutating the selection passed by the caller.
58
70
  useEffect(()=>{
59
- if (value.selection.kind === '') {
60
- value.selection.kind = defaultPluginKind || '';
71
+ if (value.selection.kind === '' && defaultPluginKind) {
72
+ onChange({
73
+ ...value,
74
+ selection: {
75
+ ...value.selection,
76
+ kind: defaultPluginKind
77
+ }
78
+ });
61
79
  }
62
80
  }, [
63
- value.selection,
64
- defaultPluginKind
81
+ value,
82
+ defaultPluginKind,
83
+ onChange
65
84
  ]);
66
- // Load the pending plugin honoring the pinned version/registry, so the initial options come from the exact
67
- // implementation the definition will use rather than from the latest one.
68
- const { data: plugin, isFetching, error } = usePlugin(pendingSelection?.type, pendingSelection?.kind || '', {
69
- version: pendingSelection?.metadata?.version,
70
- registry: pendingSelection?.metadata?.registry
71
- });
72
- useEffect(()=>{
73
- // Nothing to do if no new plugin kind is pending
74
- if (!pendingSelection) return;
75
- // Can't get spec value until we have a plugin
76
- if (plugin === undefined || isFetching) return;
77
- // Fire an onChange to change to the pending kind with initial values from the plugin
85
+ // Apply each completed load once, independently of how the owner stores the selection metadata.
86
+ const applyLoadedSelection = useEvent((plugin, selection)=>{
87
+ // v4 `reset()` still observes the in-flight load, which then reports the current (empty or newer) result.
88
+ if (!plugin || selection !== currentRequest.current) return;
89
+ currentRequest.current = undefined;
78
90
  rememberCurrentSpecState();
79
91
  onChange({
80
- selection: pendingSelection,
92
+ selection,
81
93
  spec: plugin.createInitialOptions ? plugin.createInitialOptions() : {}
82
94
  });
83
- if (pendingSelection.type === 'Panel') {
95
+ if (selection.type === 'Panel') {
84
96
  const panelPlugin = plugin;
85
- hideQueryState.current[pendingSelection.kind] = !!panelPlugin.hideQueryEditor;
97
+ hideQueryState.current[selection.kind] = !!panelPlugin.hideQueryEditor;
86
98
  if (!!panelPlugin.hideQueryEditor !== hideQueryState.current[value.selection.kind]) {
87
99
  onHideQuery(!!panelPlugin.hideQueryEditor);
88
100
  }
89
101
  }
90
- setPendingSelection(undefined);
91
- }, [
92
- pendingSelection,
93
- plugin,
94
- isFetching,
95
- rememberCurrentSpecState,
96
- onChange,
97
- onHideQuery,
98
- hideQueryState,
99
- value.selection
100
- ]);
102
+ });
101
103
  /**
102
104
  * When the user tries to change the plugin kind, make sure we have the correct spec for that plugin kind before we
103
105
  * make the switch.
@@ -105,6 +107,8 @@ import { useEvent } from "../../utils/index.js";
105
107
  // If we already have state for this plugin type/kind from a previous selection, just use it
106
108
  const previousState = prevSpecState.current[nextSelection.type]?.[nextSelection.kind];
107
109
  if (previousState !== undefined) {
110
+ currentRequest.current = undefined;
111
+ selectionLoad.reset();
108
112
  rememberCurrentSpecState();
109
113
  onChange({
110
114
  selection: nextSelection,
@@ -112,7 +116,11 @@ import { useEvent } from "../../utils/index.js";
112
116
  });
113
117
  } else {
114
118
  // Otherwise, kick off the async loading process
115
- setPendingSelection(nextSelection);
119
+ // Per-call callbacks run only for the latest mutation while the editor is mounted.
120
+ currentRequest.current = nextSelection;
121
+ selectionLoad.mutate(nextSelection, {
122
+ onSuccess: applyLoadedSelection
123
+ });
116
124
  }
117
125
  if (nextSelection.type === 'Panel' && hideQueryState.current[nextSelection.kind] !== undefined && hideQueryState.current[value.selection.kind] !== hideQueryState.current[nextSelection.kind]) {
118
126
  onHideQuery(!!hideQueryState.current[nextSelection.kind]);
@@ -127,8 +135,8 @@ import { useEvent } from "../../utils/index.js";
127
135
  };
128
136
  return {
129
137
  pendingSelection,
130
- isLoading: isFetching,
131
- error,
138
+ isLoading: selectionLoad.isLoading,
139
+ error: selectionLoad.error,
132
140
  onSelectionChange,
133
141
  onSpecChange,
134
142
  rememberCurrentSpecState
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { BoxProps } from '@mui/material';\nimport type { DatasourceSpec, PluginDefinitionMetadata, UnknownSpec } from '@perses-dev/spec';\nimport { produce } from 'immer';\nimport { useState, useRef, useEffect } from 'react';\n\nimport type { PanelPlugin, PluginType } from '../../model';\nimport { usePlugin, usePluginRegistry } from '../../runtime';\nimport { useEvent } from '../../utils';\nimport type { PluginKindSelectProps } from '../PluginKindSelect';\nimport type { PluginSpecEditorProps } from '../PluginSpecEditor';\n\nexport interface PluginEditorSelection {\n type: PluginType;\n kind: string;\n /**\n * Optional plugin definition metadata (version and/or registry), matching the `metadata` field of a spec\n * `Definition`. Only set when the user explicitly picks a specific version/registry of a plugin that has several of\n * them available. When omitted, the latest available version is used.\n */\n metadata?: PluginDefinitionMetadata;\n}\n\nexport interface PluginEditorValue {\n selection: PluginEditorSelection;\n spec: UnknownSpec;\n}\n\n// Props on MUI Box that we don't want people to pass because we're either redefining them or providing them in\n// this component\ntype OmittedMuiProps = 'children' | 'value' | 'onChange';\n\nexport interface PluginEditorProps extends Omit<BoxProps, OmittedMuiProps> {\n pluginTypes: PluginType[];\n pluginKindLabel: string;\n value: PluginEditorValue;\n isReadonly?: boolean;\n withRunQueryButton?: boolean;\n filteredQueryPlugins?: string[];\n onChange: (next: PluginEditorValue) => void;\n onRunQuery?: () => void;\n testConnection?: (spec: DatasourceSpec, healthCheckPath: string) => Promise<void>;\n}\n\nexport interface PluginEditorRef {\n flushChanges?: () => void;\n}\n\ntype PreviousSpecState = Record<string, Record<string, UnknownSpec>>;\ntype HideQueryEditorState = Record<string, boolean>;\n\n/**\n * Props needed by the usePluginEditor hook.\n */\nexport type UsePluginEditorProps = Pick<PluginEditorProps, 'pluginTypes' | 'value' | 'onChange'> & {\n onHideQueryEditorChange?: (isHidden: boolean) => void;\n};\n\n/**\n * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide\n * a different UI, but want the same behavior of changing `kind` and `spec` together on plugin kind changes. Also\n * remembers previous `spec` values that it's seen, allowing and restores those values if a user switches the plugin\n * kind back.\n */\nexport function usePluginEditor(props: UsePluginEditorProps): {\n pendingSelection?: PluginEditorSelection;\n isLoading: boolean;\n error: Error | null;\n onSelectionChange: (s: PluginEditorSelection) => void;\n onSpecChange: (next: UnknownSpec) => void;\n rememberCurrentSpecState: () => void;\n} {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const { pluginTypes, value, onHideQueryEditorChange = (): void => {} } = props; // setting onHideQueryEditorChange to empty function here because useEvent requires a function\n\n // Keep a stable reference, so we don't run the effect below when we don't need to\n const onChange = useEvent(props.onChange);\n const onHideQuery = useEvent(onHideQueryEditorChange);\n\n // The previous spec state for PluginType and kind and a helper function for remembering current values\n const prevSpecState = useRef<PreviousSpecState>({\n [value.selection.type]: { [value.selection.kind]: value.spec },\n });\n const rememberCurrentSpecState = useEvent(() => {\n let byPluginType = prevSpecState.current[value.selection.type];\n if (byPluginType === undefined) {\n byPluginType = {};\n prevSpecState.current[value.selection.type] = byPluginType;\n }\n byPluginType[value.selection.kind] = value.spec;\n });\n\n // The previous hide query state for each panel kind\n const hideQueryState = useRef<HideQueryEditorState>({\n [value.selection.kind]: false,\n });\n\n const { defaultPluginKinds } = usePluginRegistry();\n const defaultPluginType = pluginTypes[0];\n const defaultPluginKind = defaultPluginType ? defaultPluginKinds?.[defaultPluginType] : undefined;\n const defaultPluginSelection =\n defaultPluginType && defaultPluginKind\n ? {\n type: defaultPluginType,\n kind: defaultPluginKind,\n }\n : undefined;\n const initPendingSelection = !value.selection && defaultPluginSelection ? defaultPluginSelection : undefined;\n\n // When kind changes and we haven't loaded that plugin before, we will need to enter a \"pending\" state so that we\n // can generate proper initial spec values that match the new plugin kind\n const [pendingSelection, setPendingSelection] = useState<PluginEditorSelection | undefined>(initPendingSelection);\n\n // Take a default kind in case user write explicitly an empty kind in the initial value\n useEffect(() => {\n if (value.selection.kind === '') {\n value.selection.kind = defaultPluginKind || '';\n }\n }, [value.selection, defaultPluginKind]);\n\n // Load the pending plugin honoring the pinned version/registry, so the initial options come from the exact\n // implementation the definition will use rather than from the latest one.\n const {\n data: plugin,\n isFetching,\n error,\n } = usePlugin(pendingSelection?.type, pendingSelection?.kind || '', {\n version: pendingSelection?.metadata?.version,\n registry: pendingSelection?.metadata?.registry,\n });\n\n useEffect(() => {\n // Nothing to do if no new plugin kind is pending\n if (!pendingSelection) return;\n\n // Can't get spec value until we have a plugin\n if (plugin === undefined || isFetching) return;\n\n // Fire an onChange to change to the pending kind with initial values from the plugin\n rememberCurrentSpecState();\n onChange({\n selection: pendingSelection,\n spec: plugin.createInitialOptions ? plugin.createInitialOptions() : {},\n });\n\n if (pendingSelection.type === 'Panel') {\n const panelPlugin = plugin as PanelPlugin;\n hideQueryState.current[pendingSelection.kind] = !!panelPlugin.hideQueryEditor;\n if (!!panelPlugin.hideQueryEditor !== hideQueryState.current[value.selection.kind]) {\n onHideQuery(!!panelPlugin.hideQueryEditor);\n }\n }\n setPendingSelection(undefined);\n }, [\n pendingSelection,\n plugin,\n isFetching,\n rememberCurrentSpecState,\n onChange,\n onHideQuery,\n hideQueryState,\n value.selection,\n ]);\n\n /**\n * When the user tries to change the plugin kind, make sure we have the correct spec for that plugin kind before we\n * make the switch.\n */\n const onSelectionChange: PluginKindSelectProps['onChange'] = (nextSelection) => {\n // If we already have state for this plugin type/kind from a previous selection, just use it\n const previousState = prevSpecState.current[nextSelection.type]?.[nextSelection.kind];\n if (previousState !== undefined) {\n rememberCurrentSpecState();\n onChange({\n selection: nextSelection,\n spec: previousState,\n });\n } else {\n // Otherwise, kick off the async loading process\n setPendingSelection(nextSelection);\n }\n\n if (\n nextSelection.type === 'Panel' &&\n hideQueryState.current[nextSelection.kind] !== undefined &&\n hideQueryState.current[value.selection.kind] !== hideQueryState.current[nextSelection.kind]\n ) {\n onHideQuery(!!hideQueryState.current[nextSelection.kind]);\n }\n };\n\n /**\n * Spec changes are independent and always just set the spec state.\n */\n const onSpecChange: PluginSpecEditorProps['onChange'] = (next) => {\n onChange(\n produce(value, (draft) => {\n draft.spec = next;\n }),\n );\n };\n\n return {\n pendingSelection,\n isLoading: isFetching,\n error,\n onSelectionChange,\n onSpecChange,\n rememberCurrentSpecState,\n };\n}\n"],"names":["produce","useState","useRef","useEffect","usePlugin","usePluginRegistry","useEvent","usePluginEditor","props","pluginTypes","value","onHideQueryEditorChange","onChange","onHideQuery","prevSpecState","selection","type","kind","spec","rememberCurrentSpecState","byPluginType","current","undefined","hideQueryState","defaultPluginKinds","defaultPluginType","defaultPluginKind","defaultPluginSelection","initPendingSelection","pendingSelection","setPendingSelection","data","plugin","isFetching","error","version","metadata","registry","createInitialOptions","panelPlugin","hideQueryEditor","onSelectionChange","nextSelection","previousState","onSpecChange","next","draft","isLoading"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { BoxProps } from '@mui/material';\nimport type { DatasourceSpec, PluginDefinitionMetadata, UnknownSpec } from '@perses-dev/spec';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { produce } from 'immer';\nimport { useRef, useEffect } from 'react';\n\nimport type { PanelPlugin, PluginType, PluginImplementation } from '../../model';\nimport { usePluginRegistry } from '../../runtime';\nimport { useEvent } from '../../utils';\nimport type { PluginKindSelectProps } from '../PluginKindSelect';\nimport type { PluginSpecEditorProps } from '../PluginSpecEditor';\n\nexport interface PluginEditorSelection {\n type: PluginType;\n kind: string;\n /**\n * Optional plugin definition metadata (version and/or registry), matching the `metadata` field of a spec\n * `Definition`. Only set when the user explicitly picks a specific version/registry of a plugin that has several of\n * them available. When omitted, the latest available version is used.\n */\n metadata?: PluginDefinitionMetadata;\n}\n\nexport interface PluginEditorValue {\n selection: PluginEditorSelection;\n spec: UnknownSpec;\n}\n\n// Props on MUI Box that we don't want people to pass because we're either redefining them or providing them in\n// this component\ntype OmittedMuiProps = 'children' | 'value' | 'onChange';\n\nexport interface PluginEditorProps extends Omit<BoxProps, OmittedMuiProps> {\n pluginTypes: PluginType[];\n pluginKindLabel: string;\n value: PluginEditorValue;\n isReadonly?: boolean;\n withRunQueryButton?: boolean;\n filteredQueryPlugins?: string[];\n onChange: (next: PluginEditorValue) => void;\n onRunQuery?: () => void;\n testConnection?: (spec: DatasourceSpec, healthCheckPath: string) => Promise<void>;\n}\n\nexport interface PluginEditorRef {\n flushChanges?: () => void;\n}\n\ntype PreviousSpecState = Record<string, Record<string, UnknownSpec>>;\ntype HideQueryEditorState = Record<string, boolean>;\n\n/**\n * Props needed by the usePluginEditor hook.\n */\nexport type UsePluginEditorProps = Pick<PluginEditorProps, 'pluginTypes' | 'value' | 'onChange'> & {\n onHideQueryEditorChange?: (isHidden: boolean) => void;\n};\n\n/**\n * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide\n * a different UI, but want the same behavior of changing `kind` and `spec` together on plugin kind changes. Also\n * remembers previous `spec` values that it's seen, allowing and restores those values if a user switches the plugin\n * kind back.\n */\nexport function usePluginEditor(props: UsePluginEditorProps): {\n pendingSelection?: PluginEditorSelection;\n isLoading: boolean;\n error: Error | null;\n onSelectionChange: (s: PluginEditorSelection) => void;\n onSpecChange: (next: UnknownSpec) => void;\n rememberCurrentSpecState: () => void;\n} {\n const { pluginTypes, value, onHideQueryEditorChange = (): void => {} } = props; // setting onHideQueryEditorChange to empty function here because useEvent requires a function\n\n // Keep a stable reference, so we don't run the effect below when we don't need to\n const onChange = useEvent(props.onChange);\n const onHideQuery = useEvent(onHideQueryEditorChange);\n\n // The previous spec state for PluginType and kind and a helper function for remembering current values\n const prevSpecState = useRef<PreviousSpecState>({\n [value.selection.type]: { [value.selection.kind]: value.spec },\n });\n const rememberCurrentSpecState = useEvent(() => {\n let byPluginType = prevSpecState.current[value.selection.type];\n if (byPluginType === undefined) {\n byPluginType = {};\n prevSpecState.current[value.selection.type] = byPluginType;\n }\n byPluginType[value.selection.kind] = value.spec;\n });\n\n // The previous hide query state for each panel kind\n const hideQueryState = useRef<HideQueryEditorState>({\n [value.selection.kind]: false,\n });\n\n const { defaultPluginKinds, getPlugin } = usePluginRegistry();\n const queryClient = useQueryClient();\n const currentRequest = useRef<PluginEditorSelection | undefined>(undefined);\n const selectionLoad = useMutation<PluginImplementation<PluginType>, Error, PluginEditorSelection>({\n mutationFn: (selection) =>\n queryClient.fetchQuery({\n queryKey: [\n 'getPlugin',\n selection.type,\n selection.kind,\n selection.metadata?.version ?? '',\n selection.metadata?.registry ?? '',\n ],\n queryFn: () =>\n getPlugin({\n kind: selection.type,\n name: selection.kind,\n version: selection.metadata?.version,\n registry: selection.metadata?.registry,\n }),\n }),\n });\n const pendingSelection = selectionLoad.isSuccess ? undefined : selectionLoad.variables;\n const defaultPluginType = pluginTypes[0];\n const defaultPluginKind = defaultPluginType ? defaultPluginKinds?.[defaultPluginType] : undefined;\n\n // Notify the owner instead of mutating the selection passed by the caller.\n useEffect(() => {\n if (value.selection.kind === '' && defaultPluginKind) {\n onChange({ ...value, selection: { ...value.selection, kind: defaultPluginKind } });\n }\n }, [value, defaultPluginKind, onChange]);\n\n // Apply each completed load once, independently of how the owner stores the selection metadata.\n const applyLoadedSelection = useEvent(\n (plugin: PluginImplementation<PluginType> | undefined, selection: PluginEditorSelection) => {\n // v4 `reset()` still observes the in-flight load, which then reports the current (empty or newer) result.\n if (!plugin || selection !== currentRequest.current) return;\n currentRequest.current = undefined;\n rememberCurrentSpecState();\n onChange({\n selection,\n spec: plugin.createInitialOptions ? plugin.createInitialOptions() : {},\n });\n\n if (selection.type === 'Panel') {\n const panelPlugin = plugin as PanelPlugin;\n hideQueryState.current[selection.kind] = !!panelPlugin.hideQueryEditor;\n if (!!panelPlugin.hideQueryEditor !== hideQueryState.current[value.selection.kind]) {\n onHideQuery(!!panelPlugin.hideQueryEditor);\n }\n }\n },\n );\n\n /**\n * When the user tries to change the plugin kind, make sure we have the correct spec for that plugin kind before we\n * make the switch.\n */\n const onSelectionChange: PluginKindSelectProps['onChange'] = (nextSelection) => {\n // If we already have state for this plugin type/kind from a previous selection, just use it\n const previousState = prevSpecState.current[nextSelection.type]?.[nextSelection.kind];\n if (previousState !== undefined) {\n currentRequest.current = undefined;\n selectionLoad.reset();\n rememberCurrentSpecState();\n onChange({\n selection: nextSelection,\n spec: previousState,\n });\n } else {\n // Otherwise, kick off the async loading process\n // Per-call callbacks run only for the latest mutation while the editor is mounted.\n currentRequest.current = nextSelection;\n selectionLoad.mutate(nextSelection, { onSuccess: applyLoadedSelection });\n }\n\n if (\n nextSelection.type === 'Panel' &&\n hideQueryState.current[nextSelection.kind] !== undefined &&\n hideQueryState.current[value.selection.kind] !== hideQueryState.current[nextSelection.kind]\n ) {\n onHideQuery(!!hideQueryState.current[nextSelection.kind]);\n }\n };\n\n /**\n * Spec changes are independent and always just set the spec state.\n */\n const onSpecChange: PluginSpecEditorProps['onChange'] = (next) => {\n onChange(\n produce(value, (draft) => {\n draft.spec = next;\n }),\n );\n };\n\n return {\n pendingSelection,\n isLoading: selectionLoad.isLoading,\n error: selectionLoad.error,\n onSelectionChange,\n onSpecChange,\n rememberCurrentSpecState,\n };\n}\n"],"names":["useMutation","useQueryClient","produce","useRef","useEffect","usePluginRegistry","useEvent","usePluginEditor","props","pluginTypes","value","onHideQueryEditorChange","onChange","onHideQuery","prevSpecState","selection","type","kind","spec","rememberCurrentSpecState","byPluginType","current","undefined","hideQueryState","defaultPluginKinds","getPlugin","queryClient","currentRequest","selectionLoad","mutationFn","fetchQuery","queryKey","metadata","version","registry","queryFn","name","pendingSelection","isSuccess","variables","defaultPluginType","defaultPluginKind","applyLoadedSelection","plugin","createInitialOptions","panelPlugin","hideQueryEditor","onSelectionChange","nextSelection","previousState","reset","mutate","onSuccess","onSpecChange","next","draft","isLoading","error"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TimeRangeControls.d.ts","sourceRoot":"","sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAiBzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAe1C,UAAU,sBAAsB;IAE9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,sBAAsB,CAAC,EAAE,UAAU,EAAE,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;CACtD;AAED,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,qBAA4B,EAC5B,iBAAwB,EACxB,mBAA0B,EAC1B,mBAAmB,EACnB,eAAsB,EACtB,WAAW,EACX,QAAQ,EACR,sBAAsB,EACtB,gBAAgB,GACjB,EAAE,sBAAsB,GAAG,YAAY,CAqKvC"}
1
+ {"version":3,"file":"TimeRangeControls.d.ts","sourceRoot":"","sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAezE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAe1C,UAAU,sBAAsB;IAE9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,sBAAsB,CAAC,EAAE,UAAU,EAAE,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;CACtD;AAED,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,qBAA4B,EAC5B,iBAAwB,EACxB,mBAA0B,EAC1B,mBAAmB,EACnB,eAAsB,EACtB,WAAW,EACX,QAAQ,EACR,sBAAsB,EACtB,gBAAgB,GACjB,EAAE,sBAAsB,GAAG,YAAY,CAqKvC"}
@@ -15,9 +15,7 @@ import { Stack } from "@mui/material";
15
15
  import { RefreshIntervalPicker, InfoTooltip, ToolbarIconButton, TimeRangeSelector, getTimeZoneOptions, buildRelativeTimeOption } from "@perses-dev/components";
16
16
  import { parseDurationString } from "@perses-dev/spec";
17
17
  import { milliseconds } from "date-fns";
18
- // eslint-disable-next-line import/no-duplicates
19
18
  import ZoomOut from "mdi-material-ui/MinusCircleOutline";
20
- // eslint-disable-next-line import/no-duplicates
21
19
  import ZoomIn from "mdi-material-ui/PlusCircleOutline";
22
20
  import RefreshIcon from "mdi-material-ui/Refresh";
23
21
  import { useCallback } from "react";