@burdenoff/microfe-bigconsole 2026.729.1 → 2026.729.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js +1 -1
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +4 -4
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +5 -5
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +3 -3
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +4 -4
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +6 -6
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +9 -9
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +2 -2
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/SetupStateBadge.js +8 -8
- package/dist/bigconsole/components/datasink/SetupStateBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +13 -13
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +2 -2
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ExpressionEditor.js +1 -1
- package/dist/bigconsole/components/parser/ExpressionEditor.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +2 -2
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserStatusBadge.js +2 -2
- package/dist/bigconsole/components/parser/ParserStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineCard.js +2 -2
- package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +5 -5
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +3 -3
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +3 -3
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js +2 -2
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js +3 -3
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +3 -3
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/heatmap/HeatmapWidget.js +52 -32
- package/dist/bigconsole/components/widgets/heatmap/HeatmapWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +3 -3
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi/KPIWidget.js +1 -1
- package/dist/bigconsole/components/widgets/kpi/KPIWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListItem.js +3 -3
- package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js +1 -1
- package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +6 -6
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +1 -1
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressBar.js +4 -4
- package/dist/bigconsole/components/widgets/progress/ProgressBar.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +2 -2
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/ErrorState.js +2 -2
- package/dist/bigconsole/components/widgets/states/ErrorState.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +2 -2
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +6 -6
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +5 -5
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js +6 -6
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +17 -17
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +2 -2
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +24 -24
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +8 -8
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +9 -9
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +12 -12
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +6 -6
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +2 -2
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetActions.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/widget-actions/WidgetActions.tsx"],"sourcesContent":["/**\n * Widget Actions Component (v2.0)\n *\n * Renders interactive action buttons for widgets.\n * Supports multiple action types, styles, confirmation dialogs, and icons.\n */\n\nimport React, { memo, useCallback, useState, useMemo, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { WidgetAction, ActionContext, ActionResult } from '../../../renderers/types/renderer';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetActionsProps {\n /** List of actions to render */\n actions: WidgetAction[];\n /** Action context (widget ID, data, etc.) */\n context: ActionContext;\n /** Callback when action is triggered */\n onAction?: (action: WidgetAction, context: ActionContext) => Promise<ActionResult | void>;\n /** Whether actions are disabled */\n disabled?: boolean;\n /** Layout direction */\n layout?: 'horizontal' | 'vertical';\n /** Size of action buttons */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show labels */\n showLabels?: boolean;\n /** Maximum number of visible actions (rest go to overflow menu) */\n maxVisible?: number;\n /** Custom class name */\n className?: string;\n}\n\ninterface ConfirmationDialogProps {\n title: string;\n message: string;\n confirmLabel: string;\n cancelLabel: string;\n style: WidgetAction['style'];\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n// ============================================================================\n// Style Utilities\n// ============================================================================\n\nfunction getButtonClasses(\n style: WidgetAction['style'] | undefined,\n size: 'sm' | 'md' | 'lg',\n disabled: boolean\n): string {\n const baseClasses =\n 'inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';\n\n const sizeClasses = {\n sm: 'px-2.5 py-1.5 text-xs',\n md: 'px-4 py-2 text-sm',\n lg: 'px-6 py-3 text-base',\n };\n\n const styleClasses: Record<string, string> = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90 focus:ring-action-primary/50 transition-colors',\n SECONDARY: 'bg-bg-sunken text-primary hover:bg-bg-sunken/80 focus:ring-muted transition-colors',\n DANGER: 'bg-state-error text-white hover:bg-state-error/90 focus:ring-state-error/50 transition-colors',\n SUCCESS: 'bg-state-success text-white hover:bg-state-success/90 focus:ring-state-success/50 transition-colors',\n WARNING: 'bg-state-warning text-white hover:bg-state-warning/90 focus:ring-state-warning/50 transition-colors',\n };\n\n const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';\n\n // Default to SECONDARY if style is undefined\n const effectiveStyle = style || 'SECONDARY';\n const styleClass = styleClasses[effectiveStyle] || styleClasses.SECONDARY;\n\n return `${baseClasses} ${sizeClasses[size]} ${styleClass} ${disabledClasses}`;\n}\n\n// Get inline styles as fallback for button visibility\nfunction getButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: { backgroundColor: 'var(--color-action-primary-bg)', color: 'var(--color-action-primary-text)' },\n SECONDARY: { backgroundColor: 'var(--color-bg-muted)', color: 'var(--color-text-primary)' },\n DANGER: { backgroundColor: 'var(--color-status-error-bg)', color: 'var(--color-action-primary-text)' },\n SUCCESS: { backgroundColor: 'var(--color-status-success-bg)', color: 'var(--color-action-primary-text)' },\n WARNING: { backgroundColor: 'var(--color-status-warning-bg)', color: 'var(--color-action-primary-text)' },\n };\n const effectiveStyle = style || 'SECONDARY';\n return styles[effectiveStyle] || styles.SECONDARY;\n}\n\nfunction getConfirmButtonClasses(style: WidgetAction['style']): string {\n const styleClasses = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90',\n SECONDARY: 'bg-secondary text-white hover:bg-secondary/90',\n DANGER: 'bg-state-error text-white hover:bg-state-error/90',\n SUCCESS: 'bg-state-success text-white hover:bg-state-success/90',\n WARNING: 'bg-state-warning text-white hover:bg-state-warning/90',\n };\n\n const effectiveStyle = style || 'PRIMARY';\n return `px-4 py-2 text-sm font-medium rounded-md transition-colors ${styleClasses[effectiveStyle] || styleClasses.PRIMARY}`;\n}\n\n// Get inline styles for confirm button to ensure visibility\nfunction getConfirmButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: {\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SECONDARY: {\n backgroundColor: 'var(--color-text-secondary)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n DANGER: {\n backgroundColor: 'var(--color-status-error-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SUCCESS: {\n backgroundColor: 'var(--color-status-success-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n WARNING: {\n backgroundColor: 'var(--color-status-warning-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n };\n const effectiveStyle = style || 'PRIMARY';\n return styles[effectiveStyle] || styles.PRIMARY;\n}\n\n// ============================================================================\n// Icon Component\n// ============================================================================\n\ninterface ActionIconProps {\n name: string;\n className?: string;\n}\n\nconst ActionIcon: React.FC<ActionIconProps> = memo(function ActionIcon({ name, className = 'w-4 h-4' }) {\n // Common icons used in actions\n const icons: Record<string, React.ReactNode> = {\n 'external-link': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\n />\n </svg>\n ),\n save: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"\n />\n </svg>\n ),\n trash: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n ),\n edit: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n refresh: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n ),\n download: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n ),\n upload: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12\"\n />\n </svg>\n ),\n plus: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n ),\n check: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n x: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n 'more-horizontal': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z\"\n />\n </svg>\n ),\n };\n\n return icons[name] || null;\n});\n\n// ============================================================================\n// Confirmation Dialog\n// ============================================================================\n\nconst ConfirmationDialog: React.FC<ConfirmationDialogProps> = memo(function ConfirmationDialog({\n title,\n message,\n confirmLabel,\n cancelLabel,\n style,\n onConfirm,\n onCancel,\n}) {\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50\"\n style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)' }}\n onClick={onCancel}\n />\n\n {/* Dialog */}\n <div\n className=\"relative bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6 animate-in fade-in zoom-in-95 duration-200\"\n style={{\n position: 'relative',\n backgroundColor: 'var(--color-bg-surface)',\n borderRadius: '8px',\n boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',\n maxWidth: '28rem',\n width: '100%',\n margin: '0 16px',\n padding: '24px',\n zIndex: 10000,\n }}\n >\n <h3\n className=\"text-lg font-semibold text-primary\"\n style={{ fontSize: '18px', fontWeight: 600, color: 'var(--color-text-primary)', margin: 0 }}\n >\n {title}\n </h3>\n <p\n className=\"mt-2 text-sm text-secondary\"\n style={{ marginTop: '8px', fontSize: '14px', color: 'var(--color-text-secondary)' }}\n >\n {message}\n </p>\n <div\n className=\"mt-4 flex justify-end gap-3\"\n style={{ marginTop: '16px', display: 'flex', justifyContent: 'flex-end', gap: '12px' }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-secondary bg-bg-sunken hover:bg-bg-sunken/80 rounded-md transition-colors\"\n style={{\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--color-text-secondary)',\n backgroundColor: 'var(--color-bg-muted)',\n borderRadius: '6px',\n border: 'none',\n cursor: 'pointer',\n }}\n >\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={getConfirmButtonClasses(style)}\n style={getConfirmButtonInlineStyles(style)}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Overflow Menu\n// ============================================================================\n\ninterface OverflowMenuProps {\n actions: WidgetAction[];\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n}\n\nconst OverflowMenu: React.FC<OverflowMenuProps> = memo(function OverflowMenu({\n actions,\n context: _context,\n onAction,\n disabled,\n size,\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });\n\n const handleToggle = useCallback(() => {\n if (!disabled) {\n setIsOpen((prev) => !prev);\n }\n }, [disabled]);\n\n const handleAction = useCallback(\n (action: WidgetAction) => {\n setIsOpen(false);\n onAction(action);\n },\n [onAction]\n );\n\n const handleClickOutside = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n // Calculate menu position when opening\n useEffect(() => {\n if (isOpen && buttonRef.current) {\n const rect = buttonRef.current.getBoundingClientRect();\n setMenuPosition({\n top: rect.bottom + 4, // 4px gap below button\n left: rect.right - 192, // 192px = w-48, align right edge\n });\n }\n }, [isOpen]);\n\n if (actions.length === 0) return null;\n\n return (\n <div className=\"relative\">\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={handleToggle}\n disabled={disabled}\n className={getButtonClasses('SECONDARY', size, disabled ?? false)}\n aria-label=\"More actions\"\n >\n <ActionIcon name=\"more-horizontal\" />\n </button>\n\n {isOpen &&\n createPortal(\n <>\n {/* Click-outside handler */}\n <div className=\"fixed inset-0 z-[9998]\" onClick={handleClickOutside} />\n\n {/* Menu - rendered via portal at body level */}\n <div\n className=\"fixed w-48 bg-surface rounded-md shadow-lg ring-1 ring-border z-[9999] animate-in fade-in slide-in-from-top-2 duration-150\"\n style={{\n top: menuPosition.top,\n left: Math.max(8, menuPosition.left), // Ensure at least 8px from left edge\n }}\n >\n <div className=\"py-1\">\n {actions.map((action) => (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => handleAction(action)}\n disabled={action.disabled}\n className=\"w-full text-left px-4 py-2 text-sm text-secondary hover:bg-bg-sunken hover:text-primary disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2 transition-colors\"\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4\" />}\n {action.label}\n </button>\n ))}\n </div>\n </div>\n </>,\n document.body\n )}\n </div>\n );\n});\n\n// ============================================================================\n// Action Button\n// ============================================================================\n\ninterface ActionButtonProps {\n action: WidgetAction;\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n showLabel?: boolean;\n}\n\nconst ActionButton: React.FC<ActionButtonProps> = memo(function ActionButton({\n action,\n context: _context,\n onAction,\n disabled,\n size,\n showLabel = true,\n}) {\n const isDisabled = disabled || action.disabled;\n\n const handleClick = useCallback(() => {\n if (!isDisabled) {\n onAction(action);\n }\n }, [action, isDisabled, onAction]);\n\n // Get both classes and inline styles for guaranteed visibility\n const buttonClasses = getButtonClasses(action.style, size, isDisabled);\n const buttonInlineStyles = getButtonInlineStyles(action.style);\n\n // Handle LINK type\n if (action.type === 'LINK' && action.metadata?.url) {\n return (\n <a\n href={action.metadata.url as string}\n target={(action.metadata.target as string) || '_blank'}\n rel=\"noopener noreferrer\"\n className={buttonClasses}\n style={buttonInlineStyles}\n aria-disabled={isDisabled}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n {!action.icon && <ActionIcon name=\"external-link\" className=\"w-4 h-4 ml-1.5\" />}\n </a>\n );\n }\n\n return (\n <button\n type={action.type === 'SUBMIT' ? 'submit' : 'button'}\n onClick={handleClick}\n disabled={isDisabled}\n className={buttonClasses}\n style={buttonInlineStyles}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n </button>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WidgetActions: React.FC<WidgetActionsProps> = memo(function WidgetActions({\n actions,\n context,\n onAction,\n disabled = false,\n layout = 'horizontal',\n size = 'md',\n showLabels = true,\n maxVisible = 3,\n className = '',\n}) {\n const [pendingAction, setPendingAction] = useState<WidgetAction | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Filter visible actions (not hidden)\n const visibleActions = useMemo(() => {\n return actions.filter((a) => !a.hidden).sort((a, b) => a.order - b.order);\n }, [actions]);\n\n // Split into main and overflow actions\n const { mainActions, overflowActions } = useMemo(() => {\n if (visibleActions.length <= maxVisible) {\n return { mainActions: visibleActions, overflowActions: [] };\n }\n return {\n mainActions: visibleActions.slice(0, maxVisible - 1),\n overflowActions: visibleActions.slice(maxVisible - 1),\n };\n }, [visibleActions, maxVisible]);\n\n // Execute action\n const executeAction = useCallback(\n async (action: WidgetAction) => {\n if (!onAction) return;\n\n setIsLoading(true);\n try {\n await onAction(action, context);\n } catch (error) {\n } finally {\n setIsLoading(false);\n }\n },\n [onAction, context]\n );\n\n // Handle action trigger\n const handleTriggerAction = useCallback(\n (action: WidgetAction) => {\n // If action has confirmation, show dialog\n if (action.confirmation) {\n setPendingAction(action);\n return;\n }\n\n // Execute action immediately\n executeAction(action);\n },\n [executeAction]\n );\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n if (pendingAction) {\n executeAction(pendingAction);\n setPendingAction(null);\n }\n }, [pendingAction, executeAction]);\n\n const handleCancel = useCallback(() => {\n setPendingAction(null);\n }, []);\n\n // No actions to render\n if (visibleActions.length === 0) {\n return null;\n }\n\n const layoutClasses = layout === 'horizontal' ? 'flex flex-row flex-wrap gap-2' : 'flex flex-col gap-2';\n\n return (\n <>\n <div className={`${layoutClasses} ${className}`}>\n {mainActions.map((action) => (\n <ActionButton\n key={action.id}\n action={action}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n showLabel={showLabels}\n />\n ))}\n\n {overflowActions.length > 0 && (\n <OverflowMenu\n actions={overflowActions}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n />\n )}\n </div>\n\n {/* Confirmation Dialog */}\n {pendingAction?.confirmation && (\n <ConfirmationDialog\n title={pendingAction.confirmation.title || 'Confirm Action'}\n message={pendingAction.confirmation.message || 'Are you sure you want to proceed?'}\n confirmLabel={pendingAction.confirmation.confirmLabel || 'OK'}\n cancelLabel={pendingAction.confirmation.cancelLabel || 'Cancel'}\n style={pendingAction.style}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n />\n )}\n </>\n );\n});\n\nexport default WidgetActions;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetActions.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/widget-actions/WidgetActions.tsx"],"sourcesContent":["/**\n * Widget Actions Component (v2.0)\n *\n * Renders interactive action buttons for widgets.\n * Supports multiple action types, styles, confirmation dialogs, and icons.\n */\n\nimport React, { memo, useCallback, useState, useMemo, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { WidgetAction, ActionContext, ActionResult } from '../../../renderers/types/renderer';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetActionsProps {\n /** List of actions to render */\n actions: WidgetAction[];\n /** Action context (widget ID, data, etc.) */\n context: ActionContext;\n /** Callback when action is triggered */\n onAction?: (action: WidgetAction, context: ActionContext) => Promise<ActionResult | void>;\n /** Whether actions are disabled */\n disabled?: boolean;\n /** Layout direction */\n layout?: 'horizontal' | 'vertical';\n /** Size of action buttons */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show labels */\n showLabels?: boolean;\n /** Maximum number of visible actions (rest go to overflow menu) */\n maxVisible?: number;\n /** Custom class name */\n className?: string;\n}\n\ninterface ConfirmationDialogProps {\n title: string;\n message: string;\n confirmLabel: string;\n cancelLabel: string;\n style: WidgetAction['style'];\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n// ============================================================================\n// Style Utilities\n// ============================================================================\n\nfunction getButtonClasses(\n style: WidgetAction['style'] | undefined,\n size: 'sm' | 'md' | 'lg',\n disabled: boolean\n): string {\n const baseClasses =\n 'inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';\n\n const sizeClasses = {\n sm: 'px-2.5 py-1.5 text-xs',\n md: 'px-4 py-2 text-sm',\n lg: 'px-6 py-3 text-base',\n };\n\n const styleClasses: Record<string, string> = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90 focus:ring-action-primary/50 transition-colors',\n SECONDARY: 'bg-bg-sunken text-primary hover:bg-bg-sunken/80 focus:ring-muted transition-colors',\n DANGER:\n 'bg-status-error-bg text-white hover:bg-status-error-bg/90 focus:ring-status-error-border/50 transition-colors',\n SUCCESS:\n 'bg-status-success-bg text-white hover:bg-status-success-bg/90 focus:ring-status-success-border/50 transition-colors',\n WARNING:\n 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90 focus:ring-status-warning-border/50 transition-colors',\n };\n\n const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';\n\n // Default to SECONDARY if style is undefined\n const effectiveStyle = style || 'SECONDARY';\n const styleClass = styleClasses[effectiveStyle] || styleClasses.SECONDARY;\n\n return `${baseClasses} ${sizeClasses[size]} ${styleClass} ${disabledClasses}`;\n}\n\n// Get inline styles as fallback for button visibility\nfunction getButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: { backgroundColor: 'var(--color-action-primary-bg)', color: 'var(--color-action-primary-text)' },\n SECONDARY: { backgroundColor: 'var(--color-bg-muted)', color: 'var(--color-text-primary)' },\n DANGER: { backgroundColor: 'var(--color-status-error-bg)', color: 'var(--color-action-primary-text)' },\n SUCCESS: { backgroundColor: 'var(--color-status-success-bg)', color: 'var(--color-action-primary-text)' },\n WARNING: { backgroundColor: 'var(--color-status-warning-bg)', color: 'var(--color-action-primary-text)' },\n };\n const effectiveStyle = style || 'SECONDARY';\n return styles[effectiveStyle] || styles.SECONDARY;\n}\n\nfunction getConfirmButtonClasses(style: WidgetAction['style']): string {\n const styleClasses = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90',\n SECONDARY: 'bg-secondary text-white hover:bg-secondary/90',\n DANGER: 'bg-status-error-bg text-white hover:bg-status-error-bg/90',\n SUCCESS: 'bg-status-success-bg text-white hover:bg-status-success-bg/90',\n WARNING: 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90',\n };\n\n const effectiveStyle = style || 'PRIMARY';\n return `px-4 py-2 text-sm font-medium rounded-md transition-colors ${styleClasses[effectiveStyle] || styleClasses.PRIMARY}`;\n}\n\n// Get inline styles for confirm button to ensure visibility\nfunction getConfirmButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: {\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SECONDARY: {\n backgroundColor: 'var(--color-text-secondary)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n DANGER: {\n backgroundColor: 'var(--color-status-error-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SUCCESS: {\n backgroundColor: 'var(--color-status-success-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n WARNING: {\n backgroundColor: 'var(--color-status-warning-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n };\n const effectiveStyle = style || 'PRIMARY';\n return styles[effectiveStyle] || styles.PRIMARY;\n}\n\n// ============================================================================\n// Icon Component\n// ============================================================================\n\ninterface ActionIconProps {\n name: string;\n className?: string;\n}\n\nconst ActionIcon: React.FC<ActionIconProps> = memo(function ActionIcon({ name, className = 'w-4 h-4' }) {\n // Common icons used in actions\n const icons: Record<string, React.ReactNode> = {\n 'external-link': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\n />\n </svg>\n ),\n save: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"\n />\n </svg>\n ),\n trash: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n ),\n edit: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n refresh: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n ),\n download: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n ),\n upload: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12\"\n />\n </svg>\n ),\n plus: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n ),\n check: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n x: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n 'more-horizontal': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z\"\n />\n </svg>\n ),\n };\n\n return icons[name] || null;\n});\n\n// ============================================================================\n// Confirmation Dialog\n// ============================================================================\n\nconst ConfirmationDialog: React.FC<ConfirmationDialogProps> = memo(function ConfirmationDialog({\n title,\n message,\n confirmLabel,\n cancelLabel,\n style,\n onConfirm,\n onCancel,\n}) {\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50\"\n style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)' }}\n onClick={onCancel}\n />\n\n {/* Dialog */}\n <div\n className=\"relative bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6 animate-in fade-in zoom-in-95 duration-200\"\n style={{\n position: 'relative',\n backgroundColor: 'var(--color-bg-surface)',\n borderRadius: '8px',\n boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',\n maxWidth: '28rem',\n width: '100%',\n margin: '0 16px',\n padding: '24px',\n zIndex: 10000,\n }}\n >\n <h3\n className=\"text-lg font-semibold text-primary\"\n style={{ fontSize: '18px', fontWeight: 600, color: 'var(--color-text-primary)', margin: 0 }}\n >\n {title}\n </h3>\n <p\n className=\"mt-2 text-sm text-secondary\"\n style={{ marginTop: '8px', fontSize: '14px', color: 'var(--color-text-secondary)' }}\n >\n {message}\n </p>\n <div\n className=\"mt-4 flex justify-end gap-3\"\n style={{ marginTop: '16px', display: 'flex', justifyContent: 'flex-end', gap: '12px' }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-secondary bg-bg-sunken hover:bg-bg-sunken/80 rounded-md transition-colors\"\n style={{\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--color-text-secondary)',\n backgroundColor: 'var(--color-bg-muted)',\n borderRadius: '6px',\n border: 'none',\n cursor: 'pointer',\n }}\n >\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={getConfirmButtonClasses(style)}\n style={getConfirmButtonInlineStyles(style)}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Overflow Menu\n// ============================================================================\n\ninterface OverflowMenuProps {\n actions: WidgetAction[];\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n}\n\nconst OverflowMenu: React.FC<OverflowMenuProps> = memo(function OverflowMenu({\n actions,\n context: _context,\n onAction,\n disabled,\n size,\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });\n\n const handleToggle = useCallback(() => {\n if (!disabled) {\n setIsOpen((prev) => !prev);\n }\n }, [disabled]);\n\n const handleAction = useCallback(\n (action: WidgetAction) => {\n setIsOpen(false);\n onAction(action);\n },\n [onAction]\n );\n\n const handleClickOutside = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n // Calculate menu position when opening\n useEffect(() => {\n if (isOpen && buttonRef.current) {\n const rect = buttonRef.current.getBoundingClientRect();\n setMenuPosition({\n top: rect.bottom + 4, // 4px gap below button\n left: rect.right - 192, // 192px = w-48, align right edge\n });\n }\n }, [isOpen]);\n\n if (actions.length === 0) return null;\n\n return (\n <div className=\"relative\">\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={handleToggle}\n disabled={disabled}\n className={getButtonClasses('SECONDARY', size, disabled ?? false)}\n aria-label=\"More actions\"\n >\n <ActionIcon name=\"more-horizontal\" />\n </button>\n\n {isOpen &&\n createPortal(\n <>\n {/* Click-outside handler */}\n <div className=\"fixed inset-0 z-[9998]\" onClick={handleClickOutside} />\n\n {/* Menu - rendered via portal at body level */}\n <div\n className=\"fixed w-48 bg-surface rounded-md shadow-lg ring-1 ring-border z-[9999] animate-in fade-in slide-in-from-top-2 duration-150\"\n style={{\n top: menuPosition.top,\n left: Math.max(8, menuPosition.left), // Ensure at least 8px from left edge\n }}\n >\n <div className=\"py-1\">\n {actions.map((action) => (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => handleAction(action)}\n disabled={action.disabled}\n className=\"w-full text-left px-4 py-2 text-sm text-secondary hover:bg-bg-sunken hover:text-primary disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2 transition-colors\"\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4\" />}\n {action.label}\n </button>\n ))}\n </div>\n </div>\n </>,\n document.body\n )}\n </div>\n );\n});\n\n// ============================================================================\n// Action Button\n// ============================================================================\n\ninterface ActionButtonProps {\n action: WidgetAction;\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n showLabel?: boolean;\n}\n\nconst ActionButton: React.FC<ActionButtonProps> = memo(function ActionButton({\n action,\n context: _context,\n onAction,\n disabled,\n size,\n showLabel = true,\n}) {\n const isDisabled = disabled || action.disabled;\n\n const handleClick = useCallback(() => {\n if (!isDisabled) {\n onAction(action);\n }\n }, [action, isDisabled, onAction]);\n\n // Get both classes and inline styles for guaranteed visibility\n const buttonClasses = getButtonClasses(action.style, size, isDisabled);\n const buttonInlineStyles = getButtonInlineStyles(action.style);\n\n // Handle LINK type\n if (action.type === 'LINK' && action.metadata?.url) {\n return (\n <a\n href={action.metadata.url as string}\n target={(action.metadata.target as string) || '_blank'}\n rel=\"noopener noreferrer\"\n className={buttonClasses}\n style={buttonInlineStyles}\n aria-disabled={isDisabled}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n {!action.icon && <ActionIcon name=\"external-link\" className=\"w-4 h-4 ml-1.5\" />}\n </a>\n );\n }\n\n return (\n <button\n type={action.type === 'SUBMIT' ? 'submit' : 'button'}\n onClick={handleClick}\n disabled={isDisabled}\n className={buttonClasses}\n style={buttonInlineStyles}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n </button>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WidgetActions: React.FC<WidgetActionsProps> = memo(function WidgetActions({\n actions,\n context,\n onAction,\n disabled = false,\n layout = 'horizontal',\n size = 'md',\n showLabels = true,\n maxVisible = 3,\n className = '',\n}) {\n const [pendingAction, setPendingAction] = useState<WidgetAction | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Filter visible actions (not hidden)\n const visibleActions = useMemo(() => {\n return actions.filter((a) => !a.hidden).sort((a, b) => a.order - b.order);\n }, [actions]);\n\n // Split into main and overflow actions\n const { mainActions, overflowActions } = useMemo(() => {\n if (visibleActions.length <= maxVisible) {\n return { mainActions: visibleActions, overflowActions: [] };\n }\n return {\n mainActions: visibleActions.slice(0, maxVisible - 1),\n overflowActions: visibleActions.slice(maxVisible - 1),\n };\n }, [visibleActions, maxVisible]);\n\n // Execute action\n const executeAction = useCallback(\n async (action: WidgetAction) => {\n if (!onAction) return;\n\n setIsLoading(true);\n try {\n await onAction(action, context);\n } catch (error) {\n } finally {\n setIsLoading(false);\n }\n },\n [onAction, context]\n );\n\n // Handle action trigger\n const handleTriggerAction = useCallback(\n (action: WidgetAction) => {\n // If action has confirmation, show dialog\n if (action.confirmation) {\n setPendingAction(action);\n return;\n }\n\n // Execute action immediately\n executeAction(action);\n },\n [executeAction]\n );\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n if (pendingAction) {\n executeAction(pendingAction);\n setPendingAction(null);\n }\n }, [pendingAction, executeAction]);\n\n const handleCancel = useCallback(() => {\n setPendingAction(null);\n }, []);\n\n // No actions to render\n if (visibleActions.length === 0) {\n return null;\n }\n\n const layoutClasses = layout === 'horizontal' ? 'flex flex-row flex-wrap gap-2' : 'flex flex-col gap-2';\n\n return (\n <>\n <div className={`${layoutClasses} ${className}`}>\n {mainActions.map((action) => (\n <ActionButton\n key={action.id}\n action={action}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n showLabel={showLabels}\n />\n ))}\n\n {overflowActions.length > 0 && (\n <OverflowMenu\n actions={overflowActions}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n />\n )}\n </div>\n\n {/* Confirmation Dialog */}\n {pendingAction?.confirmation && (\n <ConfirmationDialog\n title={pendingAction.confirmation.title || 'Confirm Action'}\n message={pendingAction.confirmation.message || 'Are you sure you want to proceed?'}\n confirmLabel={pendingAction.confirmation.confirmLabel || 'OK'}\n cancelLabel={pendingAction.confirmation.cancelLabel || 'Cancel'}\n style={pendingAction.style}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n />\n )}\n </>\n );\n});\n\nexport default WidgetActions;\n"],"mappings":"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"}
|
|
@@ -115,7 +115,7 @@ var o = ({ className: e }) => /* @__PURE__ */ r("svg", {
|
|
|
115
115
|
}), p && /* @__PURE__ */ r("button", {
|
|
116
116
|
type: "button",
|
|
117
117
|
onClick: v,
|
|
118
|
-
className: "\n p-1 rounded-md\n text-text-secondary\n hover:text-
|
|
118
|
+
className: "\n p-1 rounded-md\n text-text-secondary\n hover:text-status-error-text\n hover:bg-status-error-bg/10\n transition-colors\n ",
|
|
119
119
|
title: "Delete Workflow",
|
|
120
120
|
children: /* @__PURE__ */ r(c, { className: "w-4 h-4" })
|
|
121
121
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowCard.js","names":[],"sources":["../../../../src/bigconsole/components/workflow/WorkflowCard.tsx"],"sourcesContent":["/**\n * WorkflowCard Component\n *\n * Card component displaying a FluidGrids Workflow summary.\n * Shows name, status, linked DataSinks count, and execution stats.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { WorkflowStatusBadge } from './WorkflowStatusBadge';\nimport type { FluidGridsWorkflow } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface WorkflowCardProps {\n workflow: FluidGridsWorkflow;\n onView?: (id: string) => void;\n onEdit?: (id: string) => void;\n onDelete?: (id: string) => void;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst WorkflowIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1.5} d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n);\n\nconst EditIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n);\n\nconst DeleteIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n);\n\nconst DataSinkIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"\n />\n </svg>\n);\n\nconst PlayIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowCard = memo(function WorkflowCard({ workflow, onView, onEdit, onDelete }: WorkflowCardProps) {\n // Calculate linked DataSinks count\n const linkedDataSinkCount = workflow.dataSinkLinks?.length ?? workflow.linkedDataSinkCount ?? 0;\n\n // Format last executed time\n const formatLastExecuted = useCallback((dateStr: string | null): string => {\n if (!dateStr) return 'Never';\n try {\n const date = new Date(dateStr);\n return formatDistanceToNow(date, { addSuffix: true });\n } catch {\n return 'Unknown';\n }\n }, []);\n\n // Event handlers\n const handleCardClick = useCallback(() => {\n onView?.(workflow.id);\n }, [onView, workflow.id]);\n\n const handleEditClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(workflow.id);\n },\n [onEdit, workflow.id]\n );\n\n const handleDeleteClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(workflow.id);\n },\n [onDelete, workflow.id]\n );\n\n return (\n <div\n onClick={handleCardClick}\n className=\"\n bg-bg-surface\n border border-border-default\n rounded-lg\n overflow-hidden\n cursor-pointer\n hover:border-action-primary-bg\n transition-colors\n \"\n >\n {/* Header with Icon */}\n <div className=\"h-24 bg-bg-sunken flex items-center justify-center relative\">\n <WorkflowIcon className=\"w-10 h-10 text-text-secondary/50\" />\n <div className=\"absolute top-2 right-2\">\n <WorkflowStatusBadge status={workflow.status} size=\"sm\" />\n </div>\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n {/* Title and Actions */}\n <div className=\"flex items-start justify-between mb-2\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-sm font-semibold text-text-primary truncate\">{workflow.name}</h3>\n <p className=\"text-xs text-text-secondary truncate mt-0.5\">{workflow.key}</p>\n </div>\n\n <div className=\"flex items-center gap-1 ml-2\">\n {onEdit && (\n <button\n type=\"button\"\n onClick={handleEditClick}\n className=\"\n p-1 rounded-md\n text-text-secondary\n hover:text-text-primary\n hover:bg-bg-sunken\n transition-colors\n \"\n title=\"Edit Workflow\"\n >\n <EditIcon className=\"w-4 h-4\" />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={handleDeleteClick}\n className=\"\n p-1 rounded-md\n text-text-secondary\n hover:text-state-error\n hover:bg-state-error/10\n transition-colors\n \"\n title=\"Delete Workflow\"\n >\n <DeleteIcon className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Description */}\n {workflow.description && (\n <p className=\"text-xs text-text-secondary mb-3 line-clamp-2\">{workflow.description}</p>\n )}\n\n {/* Stats Footer */}\n <div className=\"flex items-center justify-between text-xs text-text-secondary\">\n <div className=\"flex items-center gap-3\">\n {/* DataSinks Count */}\n <span className=\"flex items-center gap-1\" title={`${linkedDataSinkCount} linked DataSinks`}>\n <DataSinkIcon className=\"w-3.5 h-3.5\" />\n {linkedDataSinkCount} DataSink{linkedDataSinkCount !== 1 ? 's' : ''}\n </span>\n\n {/* Execution Count */}\n <span className=\"flex items-center gap-1\" title={`${workflow.executionCount} executions`}>\n <PlayIcon className=\"w-3.5 h-3.5\" />\n {workflow.executionCount}\n </span>\n </div>\n\n {/* Last Executed */}\n <span\n title={\n workflow.lastExecutedAt\n ? `Last executed: ${new Date(workflow.lastExecutedAt).toLocaleString()}`\n : 'Never executed'\n }\n >\n {formatLastExecuted(workflow.lastExecutedAt)}\n </span>\n </div>\n </div>\n </div>\n );\n});\n\nexport default WorkflowCard;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkflowCard.js","names":[],"sources":["../../../../src/bigconsole/components/workflow/WorkflowCard.tsx"],"sourcesContent":["/**\n * WorkflowCard Component\n *\n * Card component displaying a FluidGrids Workflow summary.\n * Shows name, status, linked DataSinks count, and execution stats.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { WorkflowStatusBadge } from './WorkflowStatusBadge';\nimport type { FluidGridsWorkflow } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface WorkflowCardProps {\n workflow: FluidGridsWorkflow;\n onView?: (id: string) => void;\n onEdit?: (id: string) => void;\n onDelete?: (id: string) => void;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst WorkflowIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1.5} d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n);\n\nconst EditIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n);\n\nconst DeleteIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n);\n\nconst DataSinkIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"\n />\n </svg>\n);\n\nconst PlayIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowCard = memo(function WorkflowCard({ workflow, onView, onEdit, onDelete }: WorkflowCardProps) {\n // Calculate linked DataSinks count\n const linkedDataSinkCount = workflow.dataSinkLinks?.length ?? workflow.linkedDataSinkCount ?? 0;\n\n // Format last executed time\n const formatLastExecuted = useCallback((dateStr: string | null): string => {\n if (!dateStr) return 'Never';\n try {\n const date = new Date(dateStr);\n return formatDistanceToNow(date, { addSuffix: true });\n } catch {\n return 'Unknown';\n }\n }, []);\n\n // Event handlers\n const handleCardClick = useCallback(() => {\n onView?.(workflow.id);\n }, [onView, workflow.id]);\n\n const handleEditClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(workflow.id);\n },\n [onEdit, workflow.id]\n );\n\n const handleDeleteClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(workflow.id);\n },\n [onDelete, workflow.id]\n );\n\n return (\n <div\n onClick={handleCardClick}\n className=\"\n bg-bg-surface\n border border-border-default\n rounded-lg\n overflow-hidden\n cursor-pointer\n hover:border-action-primary-bg\n transition-colors\n \"\n >\n {/* Header with Icon */}\n <div className=\"h-24 bg-bg-sunken flex items-center justify-center relative\">\n <WorkflowIcon className=\"w-10 h-10 text-text-secondary/50\" />\n <div className=\"absolute top-2 right-2\">\n <WorkflowStatusBadge status={workflow.status} size=\"sm\" />\n </div>\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n {/* Title and Actions */}\n <div className=\"flex items-start justify-between mb-2\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-sm font-semibold text-text-primary truncate\">{workflow.name}</h3>\n <p className=\"text-xs text-text-secondary truncate mt-0.5\">{workflow.key}</p>\n </div>\n\n <div className=\"flex items-center gap-1 ml-2\">\n {onEdit && (\n <button\n type=\"button\"\n onClick={handleEditClick}\n className=\"\n p-1 rounded-md\n text-text-secondary\n hover:text-text-primary\n hover:bg-bg-sunken\n transition-colors\n \"\n title=\"Edit Workflow\"\n >\n <EditIcon className=\"w-4 h-4\" />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={handleDeleteClick}\n className=\"\n p-1 rounded-md\n text-text-secondary\n hover:text-status-error-text\n hover:bg-status-error-bg/10\n transition-colors\n \"\n title=\"Delete Workflow\"\n >\n <DeleteIcon className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Description */}\n {workflow.description && (\n <p className=\"text-xs text-text-secondary mb-3 line-clamp-2\">{workflow.description}</p>\n )}\n\n {/* Stats Footer */}\n <div className=\"flex items-center justify-between text-xs text-text-secondary\">\n <div className=\"flex items-center gap-3\">\n {/* DataSinks Count */}\n <span className=\"flex items-center gap-1\" title={`${linkedDataSinkCount} linked DataSinks`}>\n <DataSinkIcon className=\"w-3.5 h-3.5\" />\n {linkedDataSinkCount} DataSink{linkedDataSinkCount !== 1 ? 's' : ''}\n </span>\n\n {/* Execution Count */}\n <span className=\"flex items-center gap-1\" title={`${workflow.executionCount} executions`}>\n <PlayIcon className=\"w-3.5 h-3.5\" />\n {workflow.executionCount}\n </span>\n </div>\n\n {/* Last Executed */}\n <span\n title={\n workflow.lastExecutedAt\n ? `Last executed: ${new Date(workflow.lastExecutedAt).toLocaleString()}`\n : 'Never executed'\n }\n >\n {formatLastExecuted(workflow.lastExecutedAt)}\n </span>\n </div>\n </div>\n </div>\n );\n});\n\nexport default WorkflowCard;\n"],"mappings":"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"}
|
|
@@ -29,8 +29,8 @@ var i = ({ className: e }) => /* @__PURE__ */ n("svg", {
|
|
|
29
29
|
/* @__PURE__ */ r("div", {
|
|
30
30
|
className: "flex items-center gap-3 mb-4",
|
|
31
31
|
children: [/* @__PURE__ */ n("div", {
|
|
32
|
-
className: "p-2 rounded-full bg-
|
|
33
|
-
children: /* @__PURE__ */ n(i, { className: "w-6 h-6 text-
|
|
32
|
+
className: "p-2 rounded-full bg-status-error-bg/10",
|
|
33
|
+
children: /* @__PURE__ */ n(i, { className: "w-6 h-6 text-status-error-text" })
|
|
34
34
|
}), /* @__PURE__ */ n("h2", {
|
|
35
35
|
className: "text-lg font-semibold text-text-primary",
|
|
36
36
|
children: "Delete Workflow"
|
|
@@ -52,9 +52,9 @@ var i = ({ className: e }) => /* @__PURE__ */ n("svg", {
|
|
|
52
52
|
]
|
|
53
53
|
}),
|
|
54
54
|
c > 0 && /* @__PURE__ */ n("div", {
|
|
55
|
-
className: "p-3 bg-
|
|
55
|
+
className: "p-3 bg-status-warning-bg/10 rounded-md",
|
|
56
56
|
children: /* @__PURE__ */ r("p", {
|
|
57
|
-
className: "text-sm text-
|
|
57
|
+
className: "text-sm text-status-warning-text",
|
|
58
58
|
children: [
|
|
59
59
|
"This workflow has ",
|
|
60
60
|
c,
|
|
@@ -80,7 +80,7 @@ var i = ({ className: e }) => /* @__PURE__ */ n("svg", {
|
|
|
80
80
|
}), /* @__PURE__ */ n("button", {
|
|
81
81
|
type: "button",
|
|
82
82
|
onClick: u,
|
|
83
|
-
className: "\n px-4 py-2\n text-sm font-medium\n text-white\n bg-
|
|
83
|
+
className: "\n px-4 py-2\n text-sm font-medium\n text-white\n bg-status-error-bg\n hover:bg-status-error-bg/90\n rounded-md\n transition-colors\n ",
|
|
84
84
|
children: "Delete Workflow"
|
|
85
85
|
})]
|
|
86
86
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowDeleteDialog.js","names":[],"sources":["../../../../src/bigconsole/components/workflow/WorkflowDeleteDialog.tsx"],"sourcesContent":["/**\n * WorkflowDeleteDialog Component\n *\n * Confirmation dialog for deleting a FluidGrids Workflow.\n * Shows warning about linked DataSinks before deletion.\n */\n\nimport { memo, useCallback } from 'react';\nimport type { FluidGridsWorkflow } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface WorkflowDeleteDialogProps {\n workflow: FluidGridsWorkflow;\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void | Promise<void>;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst WarningIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowDeleteDialog = memo(function WorkflowDeleteDialog({\n workflow,\n isOpen,\n onClose,\n onConfirm,\n}: WorkflowDeleteDialogProps) {\n // Calculate linked DataSinks count\n const linkedDataSinkCount = workflow.dataSinkLinks?.length ?? workflow.linkedDataSinkCount ?? 0;\n\n // Event handlers\n const handleBackdropClick = useCallback(() => {\n onClose();\n }, [onClose]);\n\n const handleConfirmClick = useCallback(() => {\n onConfirm();\n }, [onConfirm]);\n\n // Don't render if not open\n if (!isOpen) {\n return null;\n }\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-black/50\" onClick={handleBackdropClick} />\n\n {/* Dialog */}\n <div className=\"relative bg-bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6\">\n {/* Header */}\n <div className=\"flex items-center gap-3 mb-4\">\n <div className=\"p-2 rounded-full bg-
|
|
1
|
+
{"version":3,"file":"WorkflowDeleteDialog.js","names":[],"sources":["../../../../src/bigconsole/components/workflow/WorkflowDeleteDialog.tsx"],"sourcesContent":["/**\n * WorkflowDeleteDialog Component\n *\n * Confirmation dialog for deleting a FluidGrids Workflow.\n * Shows warning about linked DataSinks before deletion.\n */\n\nimport { memo, useCallback } from 'react';\nimport type { FluidGridsWorkflow } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface WorkflowDeleteDialogProps {\n workflow: FluidGridsWorkflow;\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void | Promise<void>;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst WarningIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowDeleteDialog = memo(function WorkflowDeleteDialog({\n workflow,\n isOpen,\n onClose,\n onConfirm,\n}: WorkflowDeleteDialogProps) {\n // Calculate linked DataSinks count\n const linkedDataSinkCount = workflow.dataSinkLinks?.length ?? workflow.linkedDataSinkCount ?? 0;\n\n // Event handlers\n const handleBackdropClick = useCallback(() => {\n onClose();\n }, [onClose]);\n\n const handleConfirmClick = useCallback(() => {\n onConfirm();\n }, [onConfirm]);\n\n // Don't render if not open\n if (!isOpen) {\n return null;\n }\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-black/50\" onClick={handleBackdropClick} />\n\n {/* Dialog */}\n <div className=\"relative bg-bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6\">\n {/* Header */}\n <div className=\"flex items-center gap-3 mb-4\">\n <div className=\"p-2 rounded-full bg-status-error-bg/10\">\n <WarningIcon className=\"w-6 h-6 text-status-error-text\" />\n </div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Delete Workflow</h2>\n </div>\n\n {/* Content */}\n <div className=\"mb-6\">\n <p className=\"text-sm text-text-secondary mb-3\">\n Are you sure you want to delete the workflow{' '}\n <span className=\"font-medium text-text-primary\">{workflow.name}</span>?\n </p>\n\n {/* Warning about linked DataSinks */}\n {linkedDataSinkCount > 0 && (\n <div className=\"p-3 bg-status-warning-bg/10 rounded-md\">\n <p className=\"text-sm text-status-warning-text\">\n This workflow has {linkedDataSinkCount} linked DataSink\n {linkedDataSinkCount !== 1 ? 's' : ''}. Deleting this workflow will remove the links, but the DataSinks\n will not be deleted.\n </p>\n </div>\n )}\n\n <p className=\"text-sm text-text-secondary mt-3\">This action cannot be undone.</p>\n </div>\n\n {/* Actions */}\n <div className=\"flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"\n px-4 py-2\n text-sm font-medium\n text-text-primary\n bg-bg-sunken\n hover:bg-border-default\n rounded-md\n transition-colors\n \"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleConfirmClick}\n className=\"\n px-4 py-2\n text-sm font-medium\n text-white\n bg-status-error-bg\n hover:bg-status-error-bg/90\n rounded-md\n transition-colors\n \"\n >\n Delete Workflow\n </button>\n </div>\n </div>\n </div>\n );\n});\n\nexport default WorkflowDeleteDialog;\n"],"mappings":";;;AAyBA,IAAM,KAAe,EAAE,mBACrB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAOK,IAAuB,EAAK,SAA8B,EACrE,aACA,WACA,YACA,gBAC4B;CAE5B,IAAM,IAAsB,EAAS,eAAe,UAAU,EAAS,uBAAuB,GAGxF,IAAsB,QAAkB;AAC5C,KAAS;IACR,CAAC,EAAQ,CAAC,EAEP,IAAqB,QAAkB;AAC3C,KAAW;IACV,CAAC,EAAU,CAAC;AAOf,QAJK,IAKH,kBAAC,OAAD;EAAK,WAAU;YAAf,CAEE,kBAAC,OAAD;GAAK,WAAU;GAA+B,SAAS;GAAuB,CAAA,EAG9E,kBAAC,OAAD;GAAK,WAAU;aAAf;IAEE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAa,WAAU,kCAAmC,CAAA;MACtD,CAAA,EACN,kBAAC,MAAD;MAAI,WAAU;gBAA0C;MAAoB,CAAA,CACxE;;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,KAAD;OAAG,WAAU;iBAAb;QAAgD;QACD;QAC7C,kBAAC,QAAD;SAAM,WAAU;mBAAiC,EAAS;SAAY,CAAA;;QACpE;;MAGH,IAAsB,KACrB,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,KAAD;QAAG,WAAU;kBAAb;SAAgD;SAC3B;SAAoB;SACtC,MAAwB,IAAU,KAAN;SAAS;SAEpC;;OACA,CAAA;MAGR,kBAAC,KAAD;OAAG,WAAU;iBAAmC;OAAiC,CAAA;MAC7E;;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBASX;MAEQ,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBASX;MAEQ,CAAA,CACL;;IACF;KACF;MAzEC;EA2ET"}
|
|
@@ -29,8 +29,8 @@ var r = e(function({ status: e, size: r = "md", showIcon: i = !0 }) {
|
|
|
29
29
|
label: "Draft"
|
|
30
30
|
},
|
|
31
31
|
active: {
|
|
32
|
-
bg: "bg-
|
|
33
|
-
text: "text-
|
|
32
|
+
bg: "bg-status-success-bg/10",
|
|
33
|
+
text: "text-status-success-text",
|
|
34
34
|
icon: /* @__PURE__ */ t("svg", {
|
|
35
35
|
className: o[r],
|
|
36
36
|
fill: "none",
|
|
@@ -46,8 +46,8 @@ var r = e(function({ status: e, size: r = "md", showIcon: i = !0 }) {
|
|
|
46
46
|
label: "Active"
|
|
47
47
|
},
|
|
48
48
|
paused: {
|
|
49
|
-
bg: "bg-
|
|
50
|
-
text: "text-
|
|
49
|
+
bg: "bg-status-warning-bg/10",
|
|
50
|
+
text: "text-status-warning-text",
|
|
51
51
|
icon: /* @__PURE__ */ t("svg", {
|
|
52
52
|
className: o[r],
|
|
53
53
|
fill: "none",
|
|
@@ -63,8 +63,8 @@ var r = e(function({ status: e, size: r = "md", showIcon: i = !0 }) {
|
|
|
63
63
|
label: "Paused"
|
|
64
64
|
},
|
|
65
65
|
error: {
|
|
66
|
-
bg: "bg-
|
|
67
|
-
text: "text-
|
|
66
|
+
bg: "bg-status-error-bg/10",
|
|
67
|
+
text: "text-status-error-text",
|
|
68
68
|
icon: /* @__PURE__ */ t("svg", {
|
|
69
69
|
className: o[r],
|
|
70
70
|
fill: "none",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowStatusBadge.js","names":[],"sources":["../../../../src/bigconsole/components/workflow/WorkflowStatusBadge.tsx"],"sourcesContent":["/**\n * Workflow Status Badge\n *\n * Display badge showing workflow status with icon and color coding.\n */\n\nimport { memo, type ReactNode } from 'react';\nimport type { FluidGridsWorkflowStatus } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface WorkflowStatusBadgeProps {\n /** Workflow status */\n status: FluidGridsWorkflowStatus;\n /** Badge size */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show icon */\n showIcon?: boolean;\n}\n\ninterface StatusConfig {\n bg: string;\n text: string;\n icon: ReactNode;\n label: string;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowStatusBadge = memo(function WorkflowStatusBadge({\n status,\n size = 'md',\n showIcon = true,\n}: WorkflowStatusBadgeProps) {\n const sizeClasses: Record<string, string> = {\n sm: 'px-2 py-0.5 text-xs',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1.5 text-base',\n };\n\n const iconSizes: Record<string, string> = {\n sm: 'w-3 h-3',\n md: 'w-4 h-4',\n lg: 'w-5 h-5',\n };\n\n const statusConfigs: Record<FluidGridsWorkflowStatus, StatusConfig> = {\n draft: {\n bg: 'bg-text-secondary/10',\n text: 'text-text-secondary',\n icon: (\n <svg className={iconSizes[size]} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n label: 'Draft',\n },\n active: {\n bg: 'bg-
|
|
1
|
+
{"version":3,"file":"WorkflowStatusBadge.js","names":[],"sources":["../../../../src/bigconsole/components/workflow/WorkflowStatusBadge.tsx"],"sourcesContent":["/**\n * Workflow Status Badge\n *\n * Display badge showing workflow status with icon and color coding.\n */\n\nimport { memo, type ReactNode } from 'react';\nimport type { FluidGridsWorkflowStatus } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface WorkflowStatusBadgeProps {\n /** Workflow status */\n status: FluidGridsWorkflowStatus;\n /** Badge size */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show icon */\n showIcon?: boolean;\n}\n\ninterface StatusConfig {\n bg: string;\n text: string;\n icon: ReactNode;\n label: string;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowStatusBadge = memo(function WorkflowStatusBadge({\n status,\n size = 'md',\n showIcon = true,\n}: WorkflowStatusBadgeProps) {\n const sizeClasses: Record<string, string> = {\n sm: 'px-2 py-0.5 text-xs',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1.5 text-base',\n };\n\n const iconSizes: Record<string, string> = {\n sm: 'w-3 h-3',\n md: 'w-4 h-4',\n lg: 'w-5 h-5',\n };\n\n const statusConfigs: Record<FluidGridsWorkflowStatus, StatusConfig> = {\n draft: {\n bg: 'bg-text-secondary/10',\n text: 'text-text-secondary',\n icon: (\n <svg className={iconSizes[size]} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n label: 'Draft',\n },\n active: {\n bg: 'bg-status-success-bg/10',\n text: 'text-status-success-text',\n icon: (\n <svg className={iconSizes[size]} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n label: 'Active',\n },\n paused: {\n bg: 'bg-status-warning-bg/10',\n text: 'text-status-warning-text',\n icon: (\n <svg className={iconSizes[size]} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 9v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n ),\n label: 'Paused',\n },\n error: {\n bg: 'bg-status-error-bg/10',\n text: 'text-status-error-text',\n icon: (\n <svg className={iconSizes[size]} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n ),\n label: 'Error',\n },\n archived: {\n bg: 'bg-text-secondary/10',\n text: 'text-text-secondary',\n icon: (\n <svg className={iconSizes[size]} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4\"\n />\n </svg>\n ),\n label: 'Archived',\n },\n };\n\n const config = statusConfigs[status];\n\n return (\n <span\n className={`\n inline-flex items-center gap-1.5\n ${sizeClasses[size]}\n ${config.bg}\n ${config.text}\n rounded-full\n font-medium\n `}\n >\n {showIcon && config.icon}\n <span>{config.label}</span>\n </span>\n );\n});\n\nexport default WorkflowStatusBadge;\n"],"mappings":";;;AAiCA,IAAa,IAAsB,EAAK,SAA6B,EACnE,WACA,UAAO,MACP,cAAW,MACgB;CAC3B,IAAM,IAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACL,EAEK,IAAoC;EACxC,IAAI;EACJ,IAAI;EACJ,IAAI;EACL,EA2EK,IAzEgE;EACpE,OAAO;GACL,IAAI;GACJ,MAAM;GACN,MACE,kBAAC,OAAD;IAAK,WAAW,EAAU;IAAO,MAAK;IAAO,QAAO;IAAe,SAAQ;cACzE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,OAAO;GACR;EACD,QAAQ;GACN,IAAI;GACJ,MAAM;GACN,MACE,kBAAC,OAAD;IAAK,WAAW,EAAU;IAAO,MAAK;IAAO,QAAO;IAAe,SAAQ;cACzE,kBAAC,QAAD;KAAM,eAAc;KAAQ,gBAAe;KAAQ,aAAa;KAAG,GAAE;KAAmB,CAAA;IACpF,CAAA;GAER,OAAO;GACR;EACD,QAAQ;GACN,IAAI;GACJ,MAAM;GACN,MACE,kBAAC,OAAD;IAAK,WAAW,EAAU;IAAO,MAAK;IAAO,QAAO;IAAe,SAAQ;cACzE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,OAAO;GACR;EACD,OAAO;GACL,IAAI;GACJ,MAAM;GACN,MACE,kBAAC,OAAD;IAAK,WAAW,EAAU;IAAO,MAAK;IAAO,QAAO;IAAe,SAAQ;cACzE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,OAAO;GACR;EACD,UAAU;GACR,IAAI;GACJ,MAAM;GACN,MACE,kBAAC,OAAD;IAAK,WAAW,EAAU;IAAO,MAAK;IAAO,QAAO;IAAe,SAAQ;cACzE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,OAAO;GACR;EACF,CAE4B;AAE7B,QACE,kBAAC,QAAD;EACE,WAAW;;UAEP,EAAY,GAAM;UAClB,EAAO,GAAG;UACV,EAAO,KAAK;;;;YALlB,CAUG,KAAY,EAAO,MACpB,kBAAC,QAAD,EAAA,UAAO,EAAO,OAAa,CAAA,CACtB;;EAET"}
|
|
@@ -222,9 +222,9 @@ var E = i(function() {
|
|
|
222
222
|
children: /* @__PURE__ */ w("div", {
|
|
223
223
|
className: "text-center",
|
|
224
224
|
children: [
|
|
225
|
-
/* @__PURE__ */ C(c, { className: "w-12 h-12 text-
|
|
225
|
+
/* @__PURE__ */ C(c, { className: "w-12 h-12 text-status-error-text mx-auto mb-4" }),
|
|
226
226
|
/* @__PURE__ */ C("p", {
|
|
227
|
-
className: "text-
|
|
227
|
+
className: "text-status-error-text text-body-sm font-medium mb-2",
|
|
228
228
|
children: "Failed to load DataSink"
|
|
229
229
|
}),
|
|
230
230
|
/* @__PURE__ */ C("p", {
|
|
@@ -259,12 +259,12 @@ var E = i(function() {
|
|
|
259
259
|
]
|
|
260
260
|
}),
|
|
261
261
|
I && /* @__PURE__ */ w("div", {
|
|
262
|
-
className: "mb-6 p-4 bg-
|
|
263
|
-
children: [/* @__PURE__ */ C(c, { className: "w-5 h-5 text-
|
|
264
|
-
className: "text-sm font-medium text-
|
|
262
|
+
className: "mb-6 p-4 bg-status-error-bg/10 border border-status-error-border/30 rounded-lg flex items-start gap-3",
|
|
263
|
+
children: [/* @__PURE__ */ C(c, { className: "w-5 h-5 text-status-error-text flex-shrink-0 mt-0.5" }), /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("p", {
|
|
264
|
+
className: "text-sm font-medium text-status-error-text",
|
|
265
265
|
children: "Failed to save DataSink"
|
|
266
266
|
}), /* @__PURE__ */ C("p", {
|
|
267
|
-
className: "text-xs text-
|
|
267
|
+
className: "text-xs text-status-error-text/80 mt-1",
|
|
268
268
|
children: I
|
|
269
269
|
})] })]
|
|
270
270
|
}),
|
|
@@ -303,7 +303,7 @@ var E = i(function() {
|
|
|
303
303
|
/* @__PURE__ */ w(b, {
|
|
304
304
|
htmlFor: "name",
|
|
305
305
|
children: ["Name ", /* @__PURE__ */ C("span", {
|
|
306
|
-
className: "text-
|
|
306
|
+
className: "text-status-error-text",
|
|
307
307
|
children: "*"
|
|
308
308
|
})]
|
|
309
309
|
}),
|
|
@@ -313,10 +313,10 @@ var E = i(function() {
|
|
|
313
313
|
value: O.name,
|
|
314
314
|
onChange: he,
|
|
315
315
|
placeholder: "e.g., Sales Metrics",
|
|
316
|
-
className: A.name ? "border-
|
|
316
|
+
className: A.name ? "border-status-error-border" : ""
|
|
317
317
|
}),
|
|
318
318
|
A.name && /* @__PURE__ */ C("p", {
|
|
319
|
-
className: "text-body-xs text-
|
|
319
|
+
className: "text-body-xs text-status-error-text",
|
|
320
320
|
children: A.name
|
|
321
321
|
})
|
|
322
322
|
]
|
|
@@ -327,7 +327,7 @@ var E = i(function() {
|
|
|
327
327
|
/* @__PURE__ */ w(b, {
|
|
328
328
|
htmlFor: "key",
|
|
329
329
|
children: ["Unique Key ", /* @__PURE__ */ C("span", {
|
|
330
|
-
className: "text-
|
|
330
|
+
className: "text-status-error-text",
|
|
331
331
|
children: "*"
|
|
332
332
|
})]
|
|
333
333
|
}),
|
|
@@ -340,18 +340,18 @@ var E = i(function() {
|
|
|
340
340
|
onChange: ge,
|
|
341
341
|
placeholder: "sales_metrics",
|
|
342
342
|
disabled: D,
|
|
343
|
-
className: `font-mono flex-1 ${A.key ? "border-
|
|
343
|
+
className: `font-mono flex-1 ${A.key ? "border-status-error-border" : ""}`
|
|
344
344
|
}), O.key && /* @__PURE__ */ C(p, {
|
|
345
345
|
type: "button",
|
|
346
346
|
onClick: Se,
|
|
347
347
|
variant: "outline",
|
|
348
348
|
size: "sm",
|
|
349
349
|
className: "px-3",
|
|
350
|
-
children: R ? /* @__PURE__ */ C(ae, { className: "w-4 h-4 text-
|
|
350
|
+
children: R ? /* @__PURE__ */ C(ae, { className: "w-4 h-4 text-status-success-text" }) : /* @__PURE__ */ C(oe, { className: "w-4 h-4" })
|
|
351
351
|
})]
|
|
352
352
|
}),
|
|
353
353
|
A.key && /* @__PURE__ */ C("p", {
|
|
354
|
-
className: "text-body-xs text-
|
|
354
|
+
className: "text-body-xs text-status-error-text",
|
|
355
355
|
children: A.key
|
|
356
356
|
}),
|
|
357
357
|
/* @__PURE__ */ C("p", {
|
|
@@ -444,10 +444,10 @@ var E = i(function() {
|
|
|
444
444
|
onChange: be,
|
|
445
445
|
placeholder: "{\"key\": \"value\"}",
|
|
446
446
|
rows: 10,
|
|
447
|
-
className: `font-mono text-xs resize-y ${A.data ? "border-
|
|
447
|
+
className: `font-mono text-xs resize-y ${A.data ? "border-status-error-border" : ""}`
|
|
448
448
|
}),
|
|
449
449
|
A.data && /* @__PURE__ */ C("p", {
|
|
450
|
-
className: "text-body-xs text-
|
|
450
|
+
className: "text-body-xs text-status-error-text",
|
|
451
451
|
children: A.data
|
|
452
452
|
}),
|
|
453
453
|
/* @__PURE__ */ C("p", {
|
|
@@ -482,9 +482,9 @@ var E = i(function() {
|
|
|
482
482
|
})]
|
|
483
483
|
})
|
|
484
484
|
}), (H || W) && /* @__PURE__ */ C(h, { children: W ? /* @__PURE__ */ C("div", {
|
|
485
|
-
className: "p-4 bg-
|
|
485
|
+
className: "p-4 bg-status-error-bg/10 border border-status-error-border/30 rounded-md",
|
|
486
486
|
children: /* @__PURE__ */ C("p", {
|
|
487
|
-
className: "text-sm text-
|
|
487
|
+
className: "text-sm text-status-error-text",
|
|
488
488
|
children: W
|
|
489
489
|
})
|
|
490
490
|
}) : H && H.length > 0 ? /* @__PURE__ */ C("pre", {
|