@burdenoff/microfe-bigconsole 2026.729.2 → 2026.729.4
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.
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +412 -305
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +481 -420
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/hooks/useEventWebhooks.js +6 -2
- package/dist/bigconsole/hooks/useEventWebhooks.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionConfigDialog.js","names":[],"sources":["../../../../src/bigconsole/components/widgets/ActionConfigDialog.tsx"],"sourcesContent":["/**\n * ActionConfigDialog Component (v2.0)\n *\n * Modal dialog for creating/editing widget actions.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Textarea } from '@burdenoff/fe-libs/ui';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@burdenoff/fe-libs/ui';\nimport { Checkbox } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Zap, Plus, Pencil } from 'lucide-react';\nimport type {\n WidgetAction,\n ActionType,\n ActionStyle,\n ActionConfirmation,\n CreateWidgetActionInput,\n UpdateWidgetActionInput,\n} from '../../hooks/useWidgetActions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ActionConfigDialogProps {\n isOpen: boolean;\n action?: WidgetAction;\n isLoading?: boolean;\n onClose: () => void;\n onSave: (data: Omit<CreateWidgetActionInput, 'widgetId'> | UpdateWidgetActionInput) => void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst ACTION_TYPES: { value: ActionType; label: string }[] = [\n { value: 'BUTTON', label: 'Button' },\n { value: 'LINK', label: 'Link' },\n { value: 'EMIT_EVENT', label: 'Emit Event' },\n { value: 'CUSTOM', label: 'Custom' },\n];\n\nconst ACTION_STYLES: { value: ActionStyle; label: string; color: string }[] = [\n { value: 'PRIMARY', label: 'Primary', color: 'var(--color-action-primary-bg)' },\n { value: 'SECONDARY', label: 'Secondary', color: 'var(--color-action-secondary-bg)' },\n { value: 'SUCCESS', label: 'Success', color: 'var(--color-status-success-bg)' },\n { value: 'WARNING', label: 'Warning', color: 'var(--color-status-warning-bg)' },\n { value: 'DANGER', label: 'Danger', color: 'var(--color-action-danger-bg)' },\n];\n\nconst ICON_OPTIONS = [\n { value: '', label: 'No icon' },\n { value: 'refresh', label: 'Refresh' },\n { value: 'download', label: 'Download' },\n { value: 'upload', label: 'Upload' },\n { value: 'trash', label: 'Trash' },\n { value: 'edit', label: 'Edit' },\n { value: 'plus', label: 'Plus' },\n { value: 'check', label: 'Check' },\n { value: 'eye', label: 'View' },\n { value: 'copy', label: 'Copy' },\n { value: 'share', label: 'Share' },\n { value: 'settings', label: 'Settings' },\n { value: 'filter', label: 'Filter' },\n { value: 'search', label: 'Search' },\n];\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ActionConfigDialog: FC<ActionConfigDialogProps> = memo(function ActionConfigDialog({\n isOpen,\n action,\n isLoading = false,\n onClose,\n onSave,\n}) {\n const isEditMode = !!action;\n const nameInputRef = useRef<HTMLInputElement>(null);\n\n // Form state\n const [name, setName] = useState('');\n const [label, setLabel] = useState('');\n const [type, setType] = useState<ActionType>('BUTTON');\n const [style, setStyle] = useState<ActionStyle>('PRIMARY');\n const [icon, setIcon] = useState('');\n const [disabled, setDisabled] = useState(false);\n const [hidden, setHidden] = useState(false);\n const [hasConfirmation, setHasConfirmation] = useState(false);\n const [confirmTitle, setConfirmTitle] = useState('Confirm Action');\n const [confirmMessage, setConfirmMessage] = useState('Are you sure you want to proceed?');\n const [confirmLabel, setConfirmLabel] = useState('Confirm');\n const [cancelLabel, setCancelLabel] = useState('Cancel');\n const [error, setError] = useState<string | null>(null);\n\n // Reset form when dialog opens or action changes\n useEffect(() => {\n if (isOpen) {\n if (action) {\n setName(action.name);\n setLabel(action.label);\n setType(action.type);\n setStyle(action.style);\n setIcon(action.icon || '');\n setDisabled(action.disabled);\n setHidden(action.hidden);\n setHasConfirmation(!!action.confirmation);\n if (action.confirmation) {\n setConfirmTitle(action.confirmation.title);\n setConfirmMessage(action.confirmation.message);\n setConfirmLabel(action.confirmation.confirmLabel || 'Confirm');\n setCancelLabel(action.confirmation.cancelLabel || 'Cancel');\n }\n } else {\n setName('');\n setLabel('');\n setType('BUTTON');\n setStyle('PRIMARY');\n setIcon('');\n setDisabled(false);\n setHidden(false);\n setHasConfirmation(false);\n setConfirmTitle('Confirm Action');\n setConfirmMessage('Are you sure you want to proceed?');\n setConfirmLabel('Confirm');\n setCancelLabel('Cancel');\n }\n setError(null);\n setTimeout(() => nameInputRef.current?.focus(), 100);\n }\n }, [isOpen, action]);\n\n // Handle form submission\n const handleSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n const trimmedLabel = label.trim();\n\n if (!trimmedName) {\n setError('Action name is required');\n nameInputRef.current?.focus();\n return;\n }\n\n if (!trimmedLabel) {\n setError('Action label is required');\n return;\n }\n\n const confirmation: ActionConfirmation | undefined = hasConfirmation\n ? {\n title: confirmTitle.trim() || 'Confirm Action',\n message: confirmMessage.trim() || 'Are you sure?',\n confirmLabel: confirmLabel.trim() || 'Confirm',\n cancelLabel: cancelLabel.trim() || 'Cancel',\n }\n : undefined;\n\n if (isEditMode && action) {\n const updateData: UpdateWidgetActionInput = {\n id: action.id,\n name: trimmedName,\n label: trimmedLabel,\n type,\n style,\n icon: icon || undefined,\n confirmation: hasConfirmation ? confirmation : null,\n disabled,\n hidden,\n };\n onSave(updateData);\n } else {\n const createData: Omit<CreateWidgetActionInput, 'widgetId'> = {\n name: trimmedName,\n label: trimmedLabel,\n type,\n style,\n icon: icon || undefined,\n confirmation,\n disabled,\n hidden,\n };\n onSave(createData);\n }\n },\n [\n name,\n label,\n type,\n style,\n icon,\n disabled,\n hidden,\n hasConfirmation,\n confirmTitle,\n confirmMessage,\n confirmLabel,\n cancelLabel,\n isEditMode,\n action,\n onSave,\n ]\n );\n\n const getStyleColor = (s: ActionStyle) => {\n return ACTION_STYLES.find((as) => as.value === s)?.color || 'var(--color-action-primary-bg)';\n };\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && !isLoading && onClose()}>\n <DialogContent style={{ maxWidth: '500px', padding: 0 }}>\n {/* Header */}\n <DialogHeader style={{ padding: 'var(--space-pagePadding) var(--space-pagePadding) 0' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n boxShadow: 'var(--shadow-elevation-2)',\n }}\n >\n {isEditMode ? (\n <Pencil\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n ) : (\n <Zap\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n )}\n </div>\n <div>\n <DialogTitle\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n color: 'var(--color-text-primary)',\n margin: 0,\n }}\n >\n {isEditMode ? 'Edit Action' : 'Add Action'}\n </DialogTitle>\n <DialogDescription\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n margin: 'var(--space-controlGap) 0 0 0',\n }}\n >\n {isEditMode ? 'Update the action configuration' : 'Configure a new widget action'}\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <form onSubmit={handleSubmit}>\n {/* Form Content */}\n <div style={{ padding: 'var(--space-pagePadding)', maxHeight: '60vh', overflowY: 'auto' }}>\n {/* Error Display */}\n {error && (\n <div\n style={{\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n border: '1px solid var(--color-status-error-border)',\n borderRadius: 'var(--radius-button)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-status-error-text)', margin: 0 }}>\n {error}\n </p>\n </div>\n )}\n\n {/* Name Field */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Name <span style={{ color: 'var(--color-status-error-text)' }}>*</span>\n </label>\n <Input\n ref={nameInputRef}\n value={name}\n onChange={(e) => {\n setName(e.target.value);\n if (error) setError(null);\n }}\n placeholder=\"e.g., refresh, export, delete\"\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n Unique identifier for this action (used in events)\n </p>\n </div>\n\n {/* Label Field */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Label <span style={{ color: 'var(--color-status-error-text)' }}>*</span>\n </label>\n <Input\n value={label}\n onChange={(e) => setLabel(e.target.value)}\n placeholder=\"e.g., Refresh Data, Export CSV\"\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n Display text shown on the button\n </p>\n </div>\n\n {/* Type and Style Row */}\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n gap: 'var(--space-formGap)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n {/* Type */}\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Type\n </label>\n <Select value={type} onValueChange={(v) => setType(v as ActionType)} disabled={isLoading}>\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent\n style={{\n zIndex: 9999,\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface, #ffffff))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n {ACTION_TYPES.map((t) => (\n <SelectItem key={t.value} value={t.value}>\n {t.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Style */}\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Style\n </label>\n <Select value={style} onValueChange={(v) => setStyle(v as ActionStyle)} disabled={isLoading}>\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent\n style={{\n zIndex: 9999,\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface, #ffffff))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n {ACTION_STYLES.map((s) => (\n <SelectItem key={s.value} value={s.value}>\n {s.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {/* Style Preview */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n marginBottom: 'var(--space-formGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>Preview:</span>\n <button\n type=\"button\"\n style={{\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n borderRadius: 'var(--radius-button)',\n backgroundColor: getStyleColor(style),\n color: 'var(--color-action-primary-text)',\n border: 'none',\n cursor: 'default',\n }}\n >\n {label || 'Button'}\n </button>\n </div>\n\n {/* Icon */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Icon\n </label>\n <Select value={icon} onValueChange={setIcon} disabled={isLoading}>\n <SelectTrigger style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}>\n <SelectValue placeholder=\"No icon\" />\n </SelectTrigger>\n <SelectContent\n style={{\n zIndex: 9999,\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface, #ffffff))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n maxHeight: '200px',\n }}\n >\n {ICON_OPTIONS.map((i) => (\n <SelectItem key={i.value || 'none'} value={i.value || 'none'}>\n {i.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Visibility Options */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-sectionGap)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <label\n style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)', cursor: 'pointer' }}\n >\n <Checkbox checked={disabled} onCheckedChange={(c) => setDisabled(c === true)} disabled={isLoading} />\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-primary)' }}>\n Disabled\n </span>\n </label>\n <label\n style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)', cursor: 'pointer' }}\n >\n <Checkbox checked={hidden} onCheckedChange={(c) => setHidden(c === true)} disabled={isLoading} />\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-primary)' }}>Hidden</span>\n </label>\n </div>\n\n {/* Confirmation Section */}\n <div style={{ paddingTop: 'var(--space-formGap)', borderTop: '1px solid var(--color-border)' }}>\n <label\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n cursor: 'pointer',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <Checkbox\n checked={hasConfirmation}\n onCheckedChange={(c) => setHasConfirmation(c === true)}\n disabled={isLoading}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n Require confirmation\n </span>\n </label>\n\n {hasConfirmation && (\n <div\n style={{\n paddingLeft: 'var(--space-formGap)',\n borderLeft: '2px solid var(--color-border)',\n display: 'flex',\n flexDirection: 'column',\n gap: 'var(--space-controlGap)',\n }}\n >\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Dialog Title\n </label>\n <Input\n value={confirmTitle}\n onChange={(e) => setConfirmTitle(e.target.value)}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-sm)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Message\n </label>\n <Textarea\n value={confirmMessage}\n onChange={(e) => setConfirmMessage(e.target.value)}\n rows={2}\n disabled={isLoading}\n style={{ fontSize: 'var(--font-size-body-sm)', resize: 'none' }}\n />\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'var(--space-controlGap)' }}>\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Confirm Button\n </label>\n <Input\n value={confirmLabel}\n onChange={(e) => setConfirmLabel(e.target.value)}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-sm)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Cancel Button\n </label>\n <Input\n value={cancelLabel}\n onChange={(e) => setCancelLabel(e.target.value)}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-sm)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Footer */}\n <DialogFooter\n style={{\n padding: 'var(--space-formGap) var(--space-pagePadding)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 'var(--space-controlGap)',\n }}\n >\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-md)' }}\n >\n Cancel\n </Button>\n <Button\n type=\"submit\"\n disabled={isLoading || !name.trim() || !label.trim()}\n style={{ height: 'var(--size-controlHeight-md)', backgroundColor: 'var(--color-action-primary-bg)' }}\n >\n {isLoading ? (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Spinner style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n Saving...\n </span>\n ) : (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n {isEditMode ? (\n <Pencil style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n ) : (\n <Plus style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n )}\n {isEditMode ? 'Update Action' : 'Add Action'}\n </span>\n )}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ActionConfigDialog;\n"],"mappings":";;;;;AAgDA,IAAM,KAAuD;CAC3D;EAAE,OAAO;EAAU,OAAO;EAAU;CACpC;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAc,OAAO;EAAc;CAC5C;EAAE,OAAO;EAAU,OAAO;EAAU;CACrC,EAEK,IAAwE;CAC5E;EAAE,OAAO;EAAW,OAAO;EAAW,OAAO;EAAkC;CAC/E;EAAE,OAAO;EAAa,OAAO;EAAa,OAAO;EAAoC;CACrF;EAAE,OAAO;EAAW,OAAO;EAAW,OAAO;EAAkC;CAC/E;EAAE,OAAO;EAAW,OAAO;EAAW,OAAO;EAAkC;CAC/E;EAAE,OAAO;EAAU,OAAO;EAAU,OAAO;EAAiC;CAC7E,EAEK,IAAe;CACnB;EAAE,OAAO;EAAI,OAAO;EAAW;CAC/B;EAAE,OAAO;EAAW,OAAO;EAAW;CACtC;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAU,OAAO;EAAU;CACpC;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAO,OAAO;EAAQ;CAC/B;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAU,OAAO;EAAU;CACpC;EAAE,OAAO;EAAU,OAAO;EAAU;CACrC,EAMY,IAAkD,EAAK,SAA4B,EAC9F,WACA,WACA,eAAY,IACZ,YACA,aACC;CACD,IAAM,IAAa,CAAC,CAAC,GACf,IAAe,EAAyB,KAAK,EAG7C,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,CAAC,GAAM,KAAW,EAAqB,SAAS,EAChD,CAAC,GAAO,KAAY,EAAsB,UAAU,EACpD,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,CAAC,GAAiB,KAAsB,EAAS,GAAM,EACvD,CAAC,GAAc,KAAmB,EAAS,iBAAiB,EAC5D,CAAC,GAAgB,KAAqB,EAAS,oCAAoC,EACnF,CAAC,GAAc,KAAmB,EAAS,UAAU,EACrD,CAAC,GAAa,KAAkB,EAAS,SAAS,EAClD,CAAC,GAAO,KAAY,EAAwB,KAAK;AAGvD,SAAgB;AACd,EAAI,MACE,KACF,EAAQ,EAAO,KAAK,EACpB,EAAS,EAAO,MAAM,EACtB,EAAQ,EAAO,KAAK,EACpB,EAAS,EAAO,MAAM,EACtB,EAAQ,EAAO,QAAQ,GAAG,EAC1B,EAAY,EAAO,SAAS,EAC5B,EAAU,EAAO,OAAO,EACxB,EAAmB,CAAC,CAAC,EAAO,aAAa,EACrC,EAAO,iBACT,EAAgB,EAAO,aAAa,MAAM,EAC1C,EAAkB,EAAO,aAAa,QAAQ,EAC9C,EAAgB,EAAO,aAAa,gBAAgB,UAAU,EAC9D,EAAe,EAAO,aAAa,eAAe,SAAS,MAG7D,EAAQ,GAAG,EACX,EAAS,GAAG,EACZ,EAAQ,SAAS,EACjB,EAAS,UAAU,EACnB,EAAQ,GAAG,EACX,EAAY,GAAM,EAClB,EAAU,GAAM,EAChB,EAAmB,GAAM,EACzB,EAAgB,iBAAiB,EACjC,EAAkB,oCAAoC,EACtD,EAAgB,UAAU,EAC1B,EAAe,SAAS,GAE1B,EAAS,KAAK,EACd,iBAAiB,EAAa,SAAS,OAAO,EAAE,IAAI;IAErD,CAAC,GAAQ,EAAO,CAAC;CAGpB,IAAM,KAAe,GAClB,MAAuB;AACtB,IAAE,gBAAgB;EAElB,IAAM,IAAc,EAAK,MAAM,EACzB,IAAe,EAAM,MAAM;AAEjC,MAAI,CAAC,GAAa;AAEhB,GADA,EAAS,0BAA0B,EACnC,EAAa,SAAS,OAAO;AAC7B;;AAGF,MAAI,CAAC,GAAc;AACjB,KAAS,2BAA2B;AACpC;;EAGF,IAAM,IAA+C,IACjD;GACE,OAAO,EAAa,MAAM,IAAI;GAC9B,SAAS,EAAe,MAAM,IAAI;GAClC,cAAc,EAAa,MAAM,IAAI;GACrC,aAAa,EAAY,MAAM,IAAI;GACpC,GACD,KAAA;AAEJ,EAYE,EAZE,KAAc,IAC4B;GAC1C,IAAI,EAAO;GACX,MAAM;GACN,OAAO;GACP;GACA;GACA,MAAM,KAAQ,KAAA;GACd,cAAc,IAAkB,IAAe;GAC/C;GACA;GACD,GAG6D;GAC5D,MAAM;GACN,OAAO;GACP;GACA;GACA,MAAM,KAAQ,KAAA;GACd;GACA;GACA;GACD,CACiB;IAGtB;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAMD,QACE,kBAAC,IAAD;EAAQ,MAAM;EAAQ,eAAe,MAAS,CAAC,KAAQ,CAAC,KAAa,GAAS;YAC5E,kBAAC,IAAD;GAAe,OAAO;IAAE,UAAU;IAAS,SAAS;IAAG;aAAvD,CAEE,kBAAC,IAAD;IAAc,OAAO,EAAE,SAAS,uDAAuD;cACrF,kBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,YAAY;MAAU,KAAK;MAAwB;eAAlF,CACE,kBAAC,OAAD;MACE,OAAO;OACL,SAAS;OACT,QAAQ;OACR,OAAO;OACP,YAAY;OACZ,gBAAgB;OAChB,cAAc;OACd,iBAAiB;OACjB,WAAW;OACZ;gBAGC,EADD,IACE,IAQA,GARD,EACE,OAAO;OACL,QAAQ;OACR,OAAO;OACP,OAAO;OACR,EACD,CAQA;MAEA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,IAAD;MACE,OAAO;OACL,UAAU;OACV,YAAY;OACZ,OAAO;OACP,QAAQ;OACT;gBAEA,IAAa,gBAAgB;MAClB,CAAA,EACd,kBAAC,GAAD;MACE,OAAO;OACL,UAAU;OACV,OAAO;OACP,QAAQ;OACT;gBAEA,IAAa,oCAAoC;MAChC,CAAA,CAChB,EAAA,CAAA,CACF;;IACO,CAAA,EAEf,kBAAC,QAAD;IAAM,UAAU;cAAhB,CAEE,kBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAA4B,WAAW;MAAQ,WAAW;MAAQ;eAAzF;MAEG,KACC,kBAAC,OAAD;OACE,OAAO;QACL,SAAS;QACT,iBAAiB;QACjB,QAAQ;QACR,cAAc;QACd,cAAc;QACf;iBAED,kBAAC,KAAD;QAAG,OAAO;SAAE,UAAU;SAA4B,OAAO;SAAkC,QAAQ;SAAG;kBACnG;QACC,CAAA;OACA,CAAA;MAIR,kBAAC,OAAD;OAAK,OAAO,EAAE,cAAc,wBAAwB;iBAApD;QACE,kBAAC,SAAD;SACE,OAAO;UACL,SAAS;UACT,UAAU;UACV,YAAY;UACZ,OAAO;UACP,cAAc;UACf;mBAPH,CAQC,SACM,kBAAC,QAAD;UAAM,OAAO,EAAE,OAAO,kCAAkC;oBAAE;UAAQ,CAAA,CACjE;;QACR,kBAAC,GAAD;SACE,KAAK;SACL,OAAO;SACP,WAAW,MAAM;AAEf,UADA,EAAQ,EAAE,OAAO,MAAM,EACnB,KAAO,EAAS,KAAK;;SAE3B,aAAY;SACZ,UAAU;SACV,OAAO;UAAE,QAAQ;UAAgC,UAAU;UAA4B;SACvF,CAAA;QACF,kBAAC,KAAD;SACE,OAAO;UACL,UAAU;UACV,OAAO;UACP,WAAW;UACZ;mBACF;SAEG,CAAA;QACA;;MAGN,kBAAC,OAAD;OAAK,OAAO,EAAE,cAAc,wBAAwB;iBAApD;QACE,kBAAC,SAAD;SACE,OAAO;UACL,SAAS;UACT,UAAU;UACV,YAAY;UACZ,OAAO;UACP,cAAc;UACf;mBAPH,CAQC,UACO,kBAAC,QAAD;UAAM,OAAO,EAAE,OAAO,kCAAkC;oBAAE;UAAQ,CAAA,CAClE;;QACR,kBAAC,GAAD;SACE,OAAO;SACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;SACzC,aAAY;SACZ,UAAU;SACV,OAAO;UAAE,QAAQ;UAAgC,UAAU;UAA4B;SACvF,CAAA;QACF,kBAAC,KAAD;SACE,OAAO;UACL,UAAU;UACV,OAAO;UACP,WAAW;UACZ;mBACF;SAEG,CAAA;QACA;;MAGN,kBAAC,OAAD;OACE,OAAO;QACL,SAAS;QACT,qBAAqB;QACrB,KAAK;QACL,cAAc;QACf;iBANH,CASE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;QACE,OAAO;SACL,SAAS;SACT,UAAU;SACV,YAAY;SACZ,OAAO;SACP,cAAc;SACf;kBACF;QAEO,CAAA,EACR,kBAAC,GAAD;QAAQ,OAAO;QAAM,gBAAgB,MAAM,EAAQ,EAAgB;QAAE,UAAU;kBAA/E,CACE,kBAAC,GAAD;SACE,OAAO;UAAE,QAAQ;UAAgC,UAAU;UAA4B;mBAEvF,kBAAC,GAAD,EAAe,CAAA;SACD,CAAA,EAChB,kBAAC,GAAD;SACE,OAAO;UACL,QAAQ;UACR,iBAAiB;UACjB,QAAQ;UACR,WAAW;UACX,cAAc;UACf;mBAEA,GAAa,KAAK,MACjB,kBAAC,GAAD;UAA0B,OAAO,EAAE;oBAChC,EAAE;UACQ,EAFI,EAAE,MAEN,CACb;SACY,CAAA,CACT;UACL,EAAA,CAAA,EAGN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;QACE,OAAO;SACL,SAAS;SACT,UAAU;SACV,YAAY;SACZ,OAAO;SACP,cAAc;SACf;kBACF;QAEO,CAAA,EACR,kBAAC,GAAD;QAAQ,OAAO;QAAO,gBAAgB,MAAM,EAAS,EAAiB;QAAE,UAAU;kBAAlF,CACE,kBAAC,GAAD;SACE,OAAO;UAAE,QAAQ;UAAgC,UAAU;UAA4B;mBAEvF,kBAAC,GAAD,EAAe,CAAA;SACD,CAAA,EAChB,kBAAC,GAAD;SACE,OAAO;UACL,QAAQ;UACR,iBAAiB;UACjB,QAAQ;UACR,WAAW;UACX,cAAc;UACf;mBAEA,EAAc,KAAK,MAClB,kBAAC,GAAD;UAA0B,OAAO,EAAE;oBAChC,EAAE;UACQ,EAFI,EAAE,MAEN,CACb;SACY,CAAA,CACT;UACL,EAAA,CAAA,CACF;;MAGN,kBAAC,OAAD;OACE,OAAO;QACL,SAAS;QACT,YAAY;QACZ,KAAK;QACL,cAAc;QACd,SAAS;QACT,iBAAiB;QACjB,cAAc;QACf;iBATH,CAWE,kBAAC,QAAD;QAAM,OAAO;SAAE,UAAU;SAA4B,OAAO;SAA2B;kBAAE;QAAe,CAAA,EACxG,kBAAC,UAAD;QACE,MAAK;QACL,OAAO;SACL,SAAS;SACT,UAAU;SACV,YAAY;SACZ,cAAc;SACd,mBA9PO,MACd,EAAc,MAAM,MAAO,EAAG,UAAU,EAAE,EAAE,SAAS,kCA6Pf,EAAM;SACrC,OAAO;SACP,QAAQ;SACR,QAAQ;SACT;kBAEA,KAAS;QACH,CAAA,CACL;;MAGN,kBAAC,OAAD;OAAK,OAAO,EAAE,cAAc,wBAAwB;iBAApD,CACE,kBAAC,SAAD;QACE,OAAO;SACL,SAAS;SACT,UAAU;SACV,YAAY;SACZ,OAAO;SACP,cAAc;SACf;kBACF;QAEO,CAAA,EACR,kBAAC,GAAD;QAAQ,OAAO;QAAM,eAAe;QAAS,UAAU;kBAAvD,CACE,kBAAC,GAAD;SAAe,OAAO;UAAE,QAAQ;UAAgC,UAAU;UAA4B;mBACpG,kBAAC,GAAD,EAAa,aAAY,WAAY,CAAA;SACvB,CAAA,EAChB,kBAAC,GAAD;SACE,OAAO;UACL,QAAQ;UACR,iBAAiB;UACjB,QAAQ;UACR,WAAW;UACX,cAAc;UACd,WAAW;UACZ;mBAEA,EAAa,KAAK,MACjB,kBAAC,GAAD;UAAoC,OAAO,EAAE,SAAS;oBACnD,EAAE;UACQ,EAFI,EAAE,SAAS,OAEf,CACb;SACY,CAAA,CACT;UACL;;MAGN,kBAAC,OAAD;OACE,OAAO;QACL,SAAS;QACT,YAAY;QACZ,KAAK;QACL,cAAc;QACf;iBANH,CAQE,kBAAC,SAAD;QACE,OAAO;SAAE,SAAS;SAAQ,YAAY;SAAU,KAAK;SAA2B,QAAQ;SAAW;kBADrG,CAGE,kBAAC,GAAD;SAAU,SAAS;SAAU,kBAAkB,MAAM,EAAY,MAAM,GAAK;SAAE,UAAU;SAAa,CAAA,EACrG,kBAAC,QAAD;SAAM,OAAO;UAAE,UAAU;UAA4B,OAAO;UAA6B;mBAAE;SAEpF,CAAA,CACD;WACR,kBAAC,SAAD;QACE,OAAO;SAAE,SAAS;SAAQ,YAAY;SAAU,KAAK;SAA2B,QAAQ;SAAW;kBADrG,CAGE,kBAAC,GAAD;SAAU,SAAS;SAAQ,kBAAkB,MAAM,EAAU,MAAM,GAAK;SAAE,UAAU;SAAa,CAAA,EACjG,kBAAC,QAAD;SAAM,OAAO;UAAE,UAAU;UAA4B,OAAO;UAA6B;mBAAE;SAAa,CAAA,CAClG;UACJ;;MAGN,kBAAC,OAAD;OAAK,OAAO;QAAE,YAAY;QAAwB,WAAW;QAAiC;iBAA9F,CACE,kBAAC,SAAD;QACE,OAAO;SACL,SAAS;SACT,YAAY;SACZ,KAAK;SACL,QAAQ;SACR,cAAc;SACf;kBAPH,CASE,kBAAC,GAAD;SACE,SAAS;SACT,kBAAkB,MAAM,EAAmB,MAAM,GAAK;SACtD,UAAU;SACV,CAAA,EACF,kBAAC,QAAD;SACE,OAAO;UACL,UAAU;UACV,YAAY;UACZ,OAAO;UACR;mBACF;SAEM,CAAA,CACD;WAEP,KACC,kBAAC,OAAD;QACE,OAAO;SACL,aAAa;SACb,YAAY;SACZ,SAAS;SACT,eAAe;SACf,KAAK;SACN;kBAPH;SASE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;UACE,OAAO;WACL,SAAS;WACT,UAAU;WACV,YAAY;WACZ,OAAO;WACP,cAAc;WACf;oBACF;UAEO,CAAA,EACR,kBAAC,GAAD;UACE,OAAO;UACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAAM;UAChD,UAAU;UACV,OAAO;WAAE,QAAQ;WAAgC,UAAU;WAA4B;UACvF,CAAA,CACE,EAAA,CAAA;SACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;UACE,OAAO;WACL,SAAS;WACT,UAAU;WACV,YAAY;WACZ,OAAO;WACP,cAAc;WACf;oBACF;UAEO,CAAA,EACR,kBAAC,GAAD;UACE,OAAO;UACP,WAAW,MAAM,EAAkB,EAAE,OAAO,MAAM;UAClD,MAAM;UACN,UAAU;UACV,OAAO;WAAE,UAAU;WAA4B,QAAQ;WAAQ;UAC/D,CAAA,CACE,EAAA,CAAA;SACN,kBAAC,OAAD;UAAK,OAAO;WAAE,SAAS;WAAQ,qBAAqB;WAAW,KAAK;WAA2B;oBAA/F,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;WACE,OAAO;YACL,SAAS;YACT,UAAU;YACV,YAAY;YACZ,OAAO;YACP,cAAc;YACf;qBACF;WAEO,CAAA,EACR,kBAAC,GAAD;WACE,OAAO;WACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAAM;WAChD,UAAU;WACV,OAAO;YAAE,QAAQ;YAAgC,UAAU;YAA4B;WACvF,CAAA,CACE,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;WACE,OAAO;YACL,SAAS;YACT,UAAU;YACV,YAAY;YACZ,OAAO;YACP,cAAc;YACf;qBACF;WAEO,CAAA,EACR,kBAAC,GAAD;WACE,OAAO;WACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;WAC/C,UAAU;WACV,OAAO;YAAE,QAAQ;YAAgC,UAAU;YAA4B;WACvF,CAAA,CACE,EAAA,CAAA,CACF;;SACF;UAEJ;;MACF;QAGN,kBAAC,IAAD;KACE,OAAO;MACL,SAAS;MACT,WAAW;MACX,iBAAiB;MACjB,SAAS;MACT,gBAAgB;MAChB,KAAK;MACN;eARH,CAUE,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,SAAS;MACT,UAAU;MACV,OAAO,EAAE,QAAQ,gCAAgC;gBAClD;MAEQ,CAAA,EACT,kBAAC,GAAD;MACE,MAAK;MACL,UAAU,KAAa,CAAC,EAAK,MAAM,IAAI,CAAC,EAAM,MAAM;MACpD,OAAO;OAAE,QAAQ;OAAgC,iBAAiB;OAAkC;gBAEnG,IACC,kBAAC,QAAD;OAAM,OAAO;QAAE,SAAS;QAAQ,YAAY;QAAU,KAAK;QAAwB;iBAAnF,CACE,kBAAC,IAAD,EAAS,OAAO;QAAE,QAAQ;QAAuB,OAAO;QAAuB,EAAI,CAAA,EAAA,YAE9E;WAEP,kBAAC,QAAD;OAAM,OAAO;QAAE,SAAS;QAAQ,YAAY;QAAU,KAAK;QAAwB;iBAAnF,CAEI,EADD,IACE,IAEA,GAFD,EAAQ,OAAO;QAAE,QAAQ;QAAuB,OAAO;QAAuB,EAAI,CAEF,EAEjF,IAAa,kBAAkB,aAC3B;;MAEF,CAAA,CACI;OACV;MACO;;EACT,CAAA;EAEX"}
|
|
1
|
+
{"version":3,"file":"ActionConfigDialog.js","names":[],"sources":["../../../../src/bigconsole/components/widgets/ActionConfigDialog.tsx"],"sourcesContent":["/**\n * ActionConfigDialog Component (v2.1)\n *\n * Modal dialog for creating/editing widget actions.\n *\n * v2.1 (BOFF-5659): reframed around the *outcome* — \"When clicked, do this\" —\n * instead of the abstract action Type. A button always emits\n * `widget:<name>:clicked`; the dialog now lets the user attach the behaviour\n * inline. Today the two shippable outcomes are:\n * - \"Call a webhook / my API\" → captures a URL + method; the parent pairs the\n * action with an EventWebhookMapping bound to that event (no backend change).\n * - \"Just emit an event\" → the raw emit, for callers wiring their own\n * consumers.\n * The action `name` (the event id) is auto-derived from the label and tucked\n * under Advanced so there is a single required field.\n *\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Textarea } from '@burdenoff/fe-libs/ui';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@burdenoff/fe-libs/ui';\nimport { Checkbox } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Zap, Plus, Pencil, ChevronDown, ChevronRight } from 'lucide-react';\nimport type {\n WidgetAction,\n ActionStyle,\n ActionConfirmation,\n CreateWidgetActionInput,\n UpdateWidgetActionInput,\n} from '../../hooks/useWidgetActions';\nimport type { HttpMethod } from '../../hooks/useEventWebhooks';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** What should happen when the button is clicked. */\nexport type ActionOutcome = 'WEBHOOK' | 'EMIT';\n\n/** Webhook binding drafted in the dialog and reconciled by the parent. */\nexport interface ActionWebhookDraft {\n url: string;\n method: HttpMethod;\n}\n\n/**\n * The action fields passed to the create/update mutation. The webhook binding\n * is passed as a SEPARATE onSave argument (never embedded here) so it can never\n * leak into the GraphQL input.\n */\nexport type ActionSaveData = Omit<CreateWidgetActionInput, 'widgetId'> | UpdateWidgetActionInput;\n\nexport interface ActionConfigDialogProps {\n isOpen: boolean;\n action?: WidgetAction;\n /** Existing webhook binding for the edited action (prefills the URL field). */\n initialWebhook?: ActionWebhookDraft | null;\n isLoading?: boolean;\n /** A save failure from the parent (action or webhook mutation) to surface inline. */\n saveError?: string | null;\n onClose: () => void;\n /** `webhook` is the paired binding, or `null` to remove any existing one. */\n onSave: (data: ActionSaveData, webhook: ActionWebhookDraft | null) => void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst OUTCOMES: { value: ActionOutcome; label: string; hint: string }[] = [\n {\n value: 'WEBHOOK',\n label: 'Call a webhook / my API',\n hint: 'Sends an HTTP request to the URL below every time the button is clicked.',\n },\n {\n value: 'EMIT',\n label: 'Just emit an event (advanced)',\n hint: 'Emits widget:<name>:clicked. Wire it up yourself in the Webhooks/Events section.',\n },\n];\n\nconst HTTP_METHODS: HttpMethod[] = ['POST', 'GET', 'PUT', 'PATCH', 'DELETE'];\n\nconst ACTION_STYLES: { value: ActionStyle; label: string; color: string }[] = [\n { value: 'PRIMARY', label: 'Primary', color: 'var(--color-action-primary-bg)' },\n { value: 'SECONDARY', label: 'Secondary', color: 'var(--color-action-secondary-bg)' },\n { value: 'SUCCESS', label: 'Success', color: 'var(--color-status-success-bg)' },\n { value: 'WARNING', label: 'Warning', color: 'var(--color-status-warning-bg)' },\n { value: 'DANGER', label: 'Danger', color: 'var(--color-action-danger-bg)' },\n];\n\nconst ICON_OPTIONS = [\n { value: '', label: 'No icon' },\n { value: 'refresh', label: 'Refresh' },\n { value: 'download', label: 'Download' },\n { value: 'upload', label: 'Upload' },\n { value: 'trash', label: 'Trash' },\n { value: 'edit', label: 'Edit' },\n { value: 'plus', label: 'Plus' },\n { value: 'check', label: 'Check' },\n { value: 'eye', label: 'View' },\n { value: 'copy', label: 'Copy' },\n { value: 'share', label: 'Share' },\n { value: 'settings', label: 'Settings' },\n { value: 'filter', label: 'Filter' },\n { value: 'search', label: 'Search' },\n];\n\n// Derive the event-id (action name) from a human label: \"Refresh Data\" -> \"refresh_data\".\nfunction slugifyName(label: string): string {\n return label\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '');\n}\n\nconst labelStyle: React.CSSProperties = {\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n};\n\nconst hintStyle: React.CSSProperties = {\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n};\n\nconst selectContentStyle: React.CSSProperties = {\n zIndex: 9999,\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ActionConfigDialog: FC<ActionConfigDialogProps> = memo(function ActionConfigDialog({\n isOpen,\n action,\n initialWebhook,\n isLoading = false,\n saveError,\n onClose,\n onSave,\n}) {\n const isEditMode = !!action;\n const labelInputRef = useRef<HTMLInputElement>(null);\n // True once the user touches the webhook fields, so a late-arriving\n // `initialWebhook` fetch can seed the form without clobbering in-progress edits.\n const webhookTouchedRef = useRef(false);\n\n // Form state\n const [label, setLabel] = useState('');\n const [name, setName] = useState('');\n const [nameEdited, setNameEdited] = useState(false);\n const [style, setStyle] = useState<ActionStyle>('PRIMARY');\n const [icon, setIcon] = useState('');\n const [outcome, setOutcome] = useState<ActionOutcome>('WEBHOOK');\n const [webhookUrl, setWebhookUrl] = useState('');\n const [webhookMethod, setWebhookMethod] = useState<HttpMethod>('POST');\n const [disabled, setDisabled] = useState(false);\n const [hidden, setHidden] = useState(false);\n const [showAdvanced, setShowAdvanced] = useState(false);\n const [hasConfirmation, setHasConfirmation] = useState(false);\n const [confirmTitle, setConfirmTitle] = useState('Confirm Action');\n const [confirmMessage, setConfirmMessage] = useState('Are you sure you want to proceed?');\n const [confirmLabel, setConfirmLabel] = useState('Confirm');\n const [cancelLabel, setCancelLabel] = useState('Cancel');\n const [error, setError] = useState<string | null>(null);\n\n // Reset form when the dialog opens or the edited action changes. Deliberately\n // does NOT depend on `initialWebhook` — that fetch can settle after the dialog\n // is open, and re-running this would wipe the user's in-progress edits (#6).\n // The webhook fields are seeded by the separate effect below.\n useEffect(() => {\n if (!isOpen) return;\n\n webhookTouchedRef.current = false;\n setWebhookUrl('');\n setWebhookMethod('POST');\n\n if (action) {\n setLabel(action.label);\n setName(action.name);\n setNameEdited(false);\n setStyle(action.style);\n setIcon(action.icon || '');\n setDisabled(action.disabled);\n setHidden(action.hidden);\n // Default to \"emit\"; the seed effect flips to WEBHOOK if a mapping exists.\n setOutcome('EMIT');\n setHasConfirmation(!!action.confirmation);\n if (action.confirmation) {\n setConfirmTitle(action.confirmation.title);\n setConfirmMessage(action.confirmation.message);\n setConfirmLabel(action.confirmation.confirmLabel || 'Confirm');\n setCancelLabel(action.confirmation.cancelLabel || 'Cancel');\n } else {\n setConfirmTitle('Confirm Action');\n setConfirmMessage('Are you sure you want to proceed?');\n setConfirmLabel('Confirm');\n setCancelLabel('Cancel');\n }\n } else {\n setLabel('');\n setName('');\n setNameEdited(false);\n setStyle('PRIMARY');\n setIcon('');\n setOutcome('WEBHOOK');\n setDisabled(false);\n setHidden(false);\n setHasConfirmation(false);\n setConfirmTitle('Confirm Action');\n setConfirmMessage('Are you sure you want to proceed?');\n setConfirmLabel('Confirm');\n setCancelLabel('Cancel');\n }\n setShowAdvanced(false);\n setError(null);\n // Focus the label after the dialog paints — a double rAF is more reliable than\n // a magic setTimeout delay and doesn't race the open animation.\n const raf = requestAnimationFrame(() => requestAnimationFrame(() => labelInputRef.current?.focus()));\n return () => cancelAnimationFrame(raf);\n }, [isOpen, action]);\n\n // Seed the webhook fields from the (possibly late-arriving) mapping fetch,\n // unless the user has already started editing them.\n useEffect(() => {\n if (!isOpen || !initialWebhook || webhookTouchedRef.current) return;\n setOutcome('WEBHOOK');\n setWebhookUrl(initialWebhook.url);\n setWebhookMethod(initialWebhook.method);\n }, [isOpen, initialWebhook]);\n\n // Keep the auto-derived name in sync with the label until the user overrides it.\n const handleLabelChange = useCallback(\n (value: string) => {\n setLabel(value);\n if (!nameEdited) setName(slugifyName(value));\n if (error) setError(null);\n },\n [nameEdited, error]\n );\n\n const handleSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedLabel = label.trim();\n if (!trimmedLabel) {\n setError('Button label is required');\n labelInputRef.current?.focus();\n return;\n }\n\n // The action name is the event id (webhook contract). It is set once at\n // creation and never rewritten on edit — re-slugifying a stored name like\n // `refresh-v2` would silently change `widget:refresh-v2:clicked` and break\n // existing bindings/consumers (#1).\n const finalName =\n isEditMode && action ? action.name : slugifyName(nameEdited ? name : label) || slugifyName(label);\n if (!finalName) {\n setError('Enter a label using letters or numbers');\n return;\n }\n\n if (outcome === 'WEBHOOK') {\n const url = webhookUrl.trim();\n if (!url) {\n setError('Enter the URL to call when the button is clicked');\n return;\n }\n if (!/^https?:\\/\\//i.test(url)) {\n setError('Webhook URL must start with http:// or https://');\n return;\n }\n }\n\n const confirmation: ActionConfirmation | undefined = hasConfirmation\n ? {\n title: confirmTitle.trim() || 'Confirm Action',\n message: confirmMessage.trim() || 'Are you sure?',\n confirmLabel: confirmLabel.trim() || 'Confirm',\n cancelLabel: cancelLabel.trim() || 'Cancel',\n }\n : undefined;\n\n const webhook: ActionWebhookDraft | null =\n outcome === 'WEBHOOK' ? { url: webhookUrl.trim(), method: webhookMethod } : null;\n\n if (isEditMode && action) {\n const updateData: ActionSaveData = {\n id: action.id,\n name: finalName,\n label: trimmedLabel,\n // Webhook/emit outcomes must be a BUTTON so the click runs onAction and\n // emits the event. Saving a stale LINK type would render an <a> that\n // bypasses onAction, so the webhook would never fire (#3).\n type: 'BUTTON',\n style,\n icon: icon || undefined,\n confirmation: hasConfirmation ? confirmation : null,\n disabled,\n hidden,\n };\n onSave(updateData, webhook);\n } else {\n const createData: ActionSaveData = {\n name: finalName,\n label: trimmedLabel,\n // Webhook/emit outcomes must be a BUTTON so the click runs onAction and\n // emits the event. Saving a stale LINK type would render an <a> that\n // bypasses onAction, so the webhook would never fire (#3).\n type: 'BUTTON',\n style,\n icon: icon || undefined,\n confirmation,\n disabled,\n hidden,\n };\n onSave(createData, webhook);\n }\n },\n [\n label,\n name,\n nameEdited,\n outcome,\n webhookUrl,\n webhookMethod,\n style,\n icon,\n disabled,\n hidden,\n hasConfirmation,\n confirmTitle,\n confirmMessage,\n confirmLabel,\n cancelLabel,\n isEditMode,\n action,\n onSave,\n ]\n );\n\n const getStyleColor = (s: ActionStyle) =>\n ACTION_STYLES.find((as) => as.value === s)?.color || 'var(--color-action-primary-bg)';\n\n const activeOutcome = OUTCOMES.find((o) => o.value === outcome);\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && !isLoading && onClose()}>\n <DialogContent style={{ maxWidth: '500px', padding: 0 }}>\n {/* Header */}\n <DialogHeader style={{ padding: 'var(--space-pagePadding) var(--space-pagePadding) 0' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n boxShadow: 'var(--shadow-elevation-2)',\n }}\n >\n {isEditMode ? (\n <Pencil\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n ) : (\n <Zap\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n )}\n </div>\n <div>\n <DialogTitle\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n color: 'var(--color-text-primary)',\n margin: 0,\n }}\n >\n {isEditMode ? 'Edit Button' : 'Add Button'}\n </DialogTitle>\n <DialogDescription\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n margin: 'var(--space-controlGap) 0 0 0',\n }}\n >\n {isEditMode ? 'Update the button and what it does' : 'Add a button and choose what it does'}\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <form onSubmit={handleSubmit}>\n {/* Form Content */}\n <div style={{ padding: 'var(--space-pagePadding)', maxHeight: '60vh', overflowY: 'auto' }}>\n {/* Error Display — local validation error or a save failure from the parent. */}\n {(error || saveError) && (\n <div\n style={{\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n border: '1px solid var(--color-status-error-border)',\n borderRadius: 'var(--radius-button)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-status-error-text)', margin: 0 }}>\n {error || saveError}\n </p>\n </div>\n )}\n\n {/* Label Field */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label style={labelStyle}>\n Button label <span style={{ color: 'var(--color-status-error-text)' }}>*</span>\n </label>\n <Input\n ref={labelInputRef}\n value={label}\n onChange={(e) => handleLabelChange(e.target.value)}\n placeholder=\"e.g., Refresh Data, Export CSV\"\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n <p style={hintStyle}>Text shown on the button</p>\n </div>\n\n {/* Style + Icon Row */}\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n gap: 'var(--space-formGap)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <div>\n <label style={labelStyle}>Style</label>\n <Select value={style} onValueChange={(v) => setStyle(v as ActionStyle)} disabled={isLoading}>\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent style={selectContentStyle}>\n {ACTION_STYLES.map((s) => (\n <SelectItem key={s.value} value={s.value}>\n {s.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div>\n <label style={labelStyle}>Icon</label>\n <Select value={icon} onValueChange={setIcon} disabled={isLoading}>\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue placeholder=\"No icon\" />\n </SelectTrigger>\n <SelectContent style={{ ...selectContentStyle, maxHeight: '200px' }}>\n {ICON_OPTIONS.map((i) => (\n <SelectItem key={i.value || 'none'} value={i.value || 'none'}>\n {i.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {/* Style Preview */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n marginBottom: 'var(--space-formGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>Preview:</span>\n <button\n type=\"button\"\n style={{\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n borderRadius: 'var(--radius-button)',\n backgroundColor: getStyleColor(style),\n color: 'var(--color-action-primary-text)',\n border: 'none',\n cursor: 'default',\n }}\n >\n {label || 'Button'}\n </button>\n </div>\n\n {/* When clicked (outcome) */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label style={labelStyle}>When clicked</label>\n <Select\n value={outcome}\n onValueChange={(v) => {\n webhookTouchedRef.current = true;\n setOutcome(v as ActionOutcome);\n }}\n disabled={isLoading}\n >\n <SelectTrigger style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent style={selectContentStyle}>\n {OUTCOMES.map((o) => (\n <SelectItem key={o.value} value={o.value}>\n {o.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {activeOutcome && <p style={hintStyle}>{activeOutcome.hint}</p>}\n </div>\n\n {/* Webhook config (only for the WEBHOOK outcome) */}\n {outcome === 'WEBHOOK' && (\n <div\n style={{\n marginBottom: 'var(--space-formGap)',\n paddingLeft: 'var(--space-formGap)',\n borderLeft: '2px solid var(--color-border)',\n display: 'flex',\n flexDirection: 'column',\n gap: 'var(--space-controlGap)',\n }}\n >\n <div>\n <label style={labelStyle}>\n URL <span style={{ color: 'var(--color-status-error-text)' }}>*</span>\n </label>\n <Input\n value={webhookUrl}\n onChange={(e) => {\n webhookTouchedRef.current = true;\n setWebhookUrl(e.target.value);\n if (error) setError(null);\n }}\n placeholder=\"https://your-service.com/hook\"\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n <div style={{ maxWidth: '160px' }}>\n <label style={labelStyle}>Method</label>\n <Select\n value={webhookMethod}\n onValueChange={(v) => {\n webhookTouchedRef.current = true;\n setWebhookMethod(v as HttpMethod);\n }}\n disabled={isLoading}\n >\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent style={selectContentStyle}>\n {HTTP_METHODS.map((m) => (\n <SelectItem key={m} value={m}>\n {m}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <p style={hintStyle}>The widget's current data is sent as the request payload.</p>\n {/^http:\\/\\//i.test(webhookUrl.trim()) && (\n <p style={{ ...hintStyle, color: 'var(--color-status-warning-text)' }}>\n Warning: <code>http://</code> is unencrypted — the widget's data will be sent in plaintext. Use{' '}\n <code>https://</code> if it may contain anything sensitive.\n </p>\n )}\n </div>\n )}\n\n {/* Confirmation Section */}\n <div style={{ paddingTop: 'var(--space-formGap)', borderTop: '1px solid var(--color-border)' }}>\n <label\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n cursor: 'pointer',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <Checkbox\n checked={hasConfirmation}\n onCheckedChange={(c) => setHasConfirmation(c === true)}\n disabled={isLoading}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n Ask for confirmation first\n </span>\n </label>\n\n {hasConfirmation && (\n <div\n style={{\n paddingLeft: 'var(--space-formGap)',\n borderLeft: '2px solid var(--color-border)',\n display: 'flex',\n flexDirection: 'column',\n gap: 'var(--space-controlGap)',\n }}\n >\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Dialog Title\n </label>\n <Input\n value={confirmTitle}\n onChange={(e) => setConfirmTitle(e.target.value)}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-sm)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Message\n </label>\n <Textarea\n value={confirmMessage}\n onChange={(e) => setConfirmMessage(e.target.value)}\n rows={2}\n disabled={isLoading}\n style={{ fontSize: 'var(--font-size-body-sm)', resize: 'none' }}\n />\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'var(--space-controlGap)' }}>\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Confirm Button\n </label>\n <Input\n value={confirmLabel}\n onChange={(e) => setConfirmLabel(e.target.value)}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-sm)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Cancel Button\n </label>\n <Input\n value={cancelLabel}\n onChange={(e) => setCancelLabel(e.target.value)}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-sm)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n </div>\n </div>\n )}\n </div>\n\n {/* Advanced disclosure — event name + visibility */}\n <div style={{ paddingTop: 'var(--space-formGap)', borderTop: '1px solid var(--color-border)' }}>\n <button\n type=\"button\"\n onClick={() => setShowAdvanced((v) => !v)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n {showAdvanced ? (\n <ChevronDown style={{ height: '14px', width: '14px' }} />\n ) : (\n <ChevronRight style={{ height: '14px', width: '14px' }} />\n )}\n Advanced\n </button>\n\n {showAdvanced && (\n <div\n style={{\n marginTop: 'var(--space-formGap)',\n display: 'flex',\n flexDirection: 'column',\n gap: 'var(--space-formGap)',\n }}\n >\n <div>\n <label style={labelStyle}>Event name (id)</label>\n <Input\n value={isEditMode && action ? action.name : name}\n onChange={(e) => {\n setName(e.target.value);\n setNameEdited(true);\n }}\n placeholder=\"auto from label\"\n // The event id is the webhook/consumer contract; it is fixed\n // once the action exists and cannot be changed on edit (#1).\n disabled={isLoading || isEditMode}\n style={{\n height: 'var(--size-controlHeight-md)',\n fontSize: 'var(--font-size-body-sm)',\n fontFamily: 'var(--font-family-mono)',\n }}\n />\n <p style={hintStyle}>\n Emits{' '}\n <code>\n widget:{isEditMode && action ? action.name : slugifyName(name || label) || '<name>'}:clicked\n </code>\n . {isEditMode ? 'Fixed once created.' : 'Auto-derived from the label.'}\n </p>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-sectionGap)' }}>\n <label\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n cursor: 'pointer',\n }}\n >\n <Checkbox\n checked={disabled}\n onCheckedChange={(c) => setDisabled(c === true)}\n disabled={isLoading}\n />\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-primary)' }}>\n Disabled\n </span>\n </label>\n <label\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n cursor: 'pointer',\n }}\n >\n <Checkbox checked={hidden} onCheckedChange={(c) => setHidden(c === true)} disabled={isLoading} />\n <span style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-primary)' }}>\n Hidden\n </span>\n </label>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Footer */}\n <DialogFooter\n style={{\n padding: 'var(--space-formGap) var(--space-pagePadding)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 'var(--space-controlGap)',\n }}\n >\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n disabled={isLoading}\n style={{ height: 'var(--size-controlHeight-md)' }}\n >\n Cancel\n </Button>\n <Button\n type=\"submit\"\n disabled={isLoading || !label.trim()}\n style={{ height: 'var(--size-controlHeight-md)', backgroundColor: 'var(--color-action-primary-bg)' }}\n >\n {isLoading ? (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Spinner style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n Saving...\n </span>\n ) : (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n {isEditMode ? (\n <Pencil style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n ) : (\n <Plus style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n )}\n {isEditMode ? 'Update Button' : 'Add Button'}\n </span>\n )}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ActionConfigDialog;\n"],"mappings":"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"}
|