@burdenoff/microfe-bigconsole 2026.805.3 → 2026.812.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 +118 -106
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js.map +1 -1
- package/dist/bigconsole/components/DrilldownModal.js +54 -50
- package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
- package/dist/bigconsole/components/builder/BuilderCanvas.js +2 -2
- package/dist/bigconsole/components/builder/BuilderCanvas.js.map +1 -1
- package/dist/bigconsole/components/builder/BuilderTopbar.js +3 -3
- package/dist/bigconsole/components/builder/BuilderTopbar.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/AdvancedSection.js +24 -25
- package/dist/bigconsole/components/builder/inspector/AdvancedSection.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/AppearanceSection.js +40 -29
- package/dist/bigconsole/components/builder/inspector/AppearanceSection.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +135 -97
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/GeneralSection.js +58 -44
- package/dist/bigconsole/components/builder/inspector/GeneralSection.js.map +1 -1
- package/dist/bigconsole/components/common/Section.js +70 -0
- package/dist/bigconsole/components/common/Section.js.map +1 -0
- package/dist/bigconsole/components/common/index.js +2 -0
- package/dist/bigconsole/components/common/sectionStyles.js +42 -0
- package/dist/bigconsole/components/common/sectionStyles.js.map +1 -0
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +209 -193
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +213 -231
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardGrid.js +12 -18
- package/dist/bigconsole/components/dashboard/DashboardGrid.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +109 -102
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +81 -70
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +125 -159
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +25 -23
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +3 -3
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +5 -3
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +170 -284
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +147 -151
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/LiveBoardBanner.js +45 -53
- package/dist/bigconsole/components/dashboard/LiveBoardBanner.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +157 -148
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +17 -8
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +101 -95
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js +20 -18
- package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js.map +1 -1
- package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js +26 -58
- package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js.map +1 -1
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +307 -231
- package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +29 -29
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +78 -79
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js +33 -34
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +79 -56
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +75 -65
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +1 -1
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +20 -19
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js +127 -171
- package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +263 -243
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js +65 -66
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +121 -127
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +33 -26
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/SetupStateBadge.js +3 -3
- package/dist/bigconsole/components/datasink/SetupStateBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +95 -95
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +154 -123
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ExpressionEditor.js +3 -3
- package/dist/bigconsole/components/parser/ExpressionEditor.js.map +1 -1
- package/dist/bigconsole/components/parser/ImportParserDialog.js +235 -275
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js +133 -114
- package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +191 -174
- 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/parser/ParserTypeBadge.js +4 -4
- package/dist/bigconsole/components/parser/ParserTypeBadge.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineCard.js +134 -89
- package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +77 -64
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +7 -10
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewContent.js +31 -32
- package/dist/bigconsole/components/preview/AiPreviewContent.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +152 -106
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +193 -152
- package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/previewShared.js +41 -23
- package/dist/bigconsole/components/preview/previewShared.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +342 -308
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +262 -238
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +783 -867
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js +7 -5
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetHeader.js +7 -8
- package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetRegistry.js +4 -4
- package/dist/bigconsole/components/widgets/WidgetRegistry.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetWrapper.js +8 -7
- package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js +1 -1
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +2 -2
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js +11 -5
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +19 -15
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +154 -102
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/CircularGauge.js +36 -32
- package/dist/bigconsole/components/widgets/gauge/CircularGauge.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +85 -60
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js +64 -35
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/LinearGauge.js +46 -45
- package/dist/bigconsole/components/widgets/gauge/LinearGauge.js.map +1 -1
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +35 -24
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js +2 -2
- package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +4 -4
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +153 -90
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListConfig.js +8 -2
- package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListItem.js +1 -1
- package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +1 -1
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +14 -4
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js +112 -89
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +21 -13
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/index.js +4 -4
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +3 -3
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +34 -25
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js +129 -114
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +3 -3
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/EmptyState.js +6 -4
- package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/ErrorState.js +7 -5
- package/dist/bigconsole/components/widgets/states/ErrorState.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/LoadingState.js +5 -4
- package/dist/bigconsole/components/widgets/states/LoadingState.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +10 -4
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableHeader.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableWidget.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +3 -3
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js +2 -2
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js.map +1 -1
- package/dist/bigconsole/components/widgets/utils/targetProgress.js +13 -0
- package/dist/bigconsole/components/widgets/utils/targetProgress.js.map +1 -0
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +112 -85
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +28 -20
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js +92 -77
- package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +70 -51
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js +16 -17
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +6 -4
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +360 -338
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
- package/dist/bigconsole/hooks/useModalFocusTrap.js +53 -0
- package/dist/bigconsole/hooks/useModalFocusTrap.js.map +1 -0
- package/dist/bigconsole/pages/DashboardBuilderPage.js +209 -203
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +126 -120
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +838 -800
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +263 -315
- package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +301 -341
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +346 -339
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +356 -458
- package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSourcesPage.js +7 -2
- package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
- package/dist/bigconsole/pages/HomePage.js +186 -193
- package/dist/bigconsole/pages/HomePage.js.map +1 -1
- package/dist/bigconsole/pages/InsightsPage.js +887 -740
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +679 -637
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +368 -342
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +537 -444
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +412 -377
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +248 -298
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +251 -153
- package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +381 -371
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +171 -286
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebhookConfigPanel.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.tsx"],"sourcesContent":["/**\n * WebhookConfigPanel Component (v2.0)\n *\n * Panel for managing event webhook mappings.\n * Allows creating, editing, testing, and deleting webhooks.\n */\n\nimport React, { memo, useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useEventWebhooks,\n type HttpMethod,\n type EventWebhookMapping,\n type CreateEventWebhookMappingInput,\n type UpdateEventWebhookMappingInput,\n type WebhookTestResult,\n} from '../../../hooks/useEventWebhooks';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WebhookConfigPanelProps {\n /** Dashboard ID for webhook scope */\n dashboardId?: string;\n /** Widget ID for webhook scope */\n widgetId?: string;\n /** Callback when webhook is created */\n onWebhookCreated?: (webhook: EventWebhookMapping) => void;\n /** Callback when webhook is deleted */\n onWebhookDeleted?: (id: string) => void;\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\nconst styles = {\n container: {\n padding: '16px',\n backgroundColor: 'var(--color-bg-surface)',\n borderRadius: '8px',\n } as React.CSSProperties,\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: '16px',\n } as React.CSSProperties,\n title: {\n fontSize: '16px',\n fontWeight: 600,\n color: 'var(--color-text-primary)',\n margin: 0,\n } as React.CSSProperties,\n addButton: {\n padding: '8px 16px',\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-text-inverse)',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n webhookList: {\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n } as React.CSSProperties,\n webhookCard: {\n padding: '16px',\n backgroundColor: 'var(--color-bg-subtle)',\n borderRadius: '8px',\n border: '1px solid var(--color-border-subtle)',\n } as React.CSSProperties,\n webhookHeader: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n marginBottom: '8px',\n } as React.CSSProperties,\n webhookTitle: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n } as React.CSSProperties,\n webhookName: {\n fontSize: '14px',\n fontWeight: 600,\n color: 'var(--color-text-primary)',\n } as React.CSSProperties,\n statusBadge: {\n padding: '2px 8px',\n borderRadius: '12px',\n fontSize: '12px',\n fontWeight: 500,\n } as React.CSSProperties,\n activeBadge: {\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n color: 'var(--color-status-success-text)',\n } as React.CSSProperties,\n inactiveBadge: {\n backgroundColor: 'var(--color-status-warning-bgSubtle)',\n color: 'var(--color-status-warning-text)',\n } as React.CSSProperties,\n webhookDetails: {\n fontSize: '13px',\n color: 'var(--color-text-muted)',\n marginBottom: '4px',\n } as React.CSSProperties,\n webhookUrl: {\n fontSize: '12px',\n color: 'var(--color-text-placeholder)',\n fontFamily: 'monospace',\n wordBreak: 'break-all',\n } as React.CSSProperties,\n webhookActions: {\n display: 'flex',\n gap: '8px',\n marginTop: '12px',\n } as React.CSSProperties,\n actionButton: {\n padding: '6px 12px',\n fontSize: '12px',\n fontWeight: 500,\n borderRadius: '4px',\n border: 'none',\n cursor: 'pointer',\n } as React.CSSProperties,\n editButton: {\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-primary)',\n } as React.CSSProperties,\n testButton: {\n backgroundColor: 'var(--color-status-info-bgSubtle)',\n color: 'var(--color-status-info-text)',\n } as React.CSSProperties,\n deleteButton: {\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n color: 'var(--color-status-error-text)',\n } as React.CSSProperties,\n toggleButton: {\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-muted)',\n } as React.CSSProperties,\n emptyState: {\n textAlign: 'center',\n padding: '32px',\n color: 'var(--color-text-placeholder)',\n } as React.CSSProperties,\n form: {\n padding: '16px',\n backgroundColor: 'var(--color-bg-subtle)',\n borderRadius: '8px',\n marginBottom: '16px',\n } as React.CSSProperties,\n formGroup: {\n marginBottom: '12px',\n } as React.CSSProperties,\n label: {\n display: 'block',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--color-text-primary)',\n marginBottom: '4px',\n } as React.CSSProperties,\n input: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n boxSizing: 'border-box',\n } as React.CSSProperties,\n select: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n boxSizing: 'border-box',\n backgroundColor: 'var(--color-bg-surface)',\n } as React.CSSProperties,\n textarea: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n boxSizing: 'border-box',\n fontFamily: 'monospace',\n minHeight: '80px',\n resize: 'vertical',\n } as React.CSSProperties,\n formActions: {\n display: 'flex',\n gap: '8px',\n justifyContent: 'flex-end',\n marginTop: '16px',\n } as React.CSSProperties,\n cancelButton: {\n padding: '8px 16px',\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-primary)',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n cursor: 'pointer',\n } as React.CSSProperties,\n saveButton: {\n padding: '8px 16px',\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-text-inverse)',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n testResult: {\n marginTop: '12px',\n padding: '12px',\n borderRadius: '6px',\n fontSize: '13px',\n } as React.CSSProperties,\n testSuccess: {\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n color: 'var(--color-status-success-text)',\n } as React.CSSProperties,\n testFailure: {\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n color: 'var(--color-status-error-text)',\n } as React.CSSProperties,\n helpText: {\n fontSize: '12px',\n color: 'var(--color-text-placeholder)',\n marginTop: '4px',\n } as React.CSSProperties,\n};\n\n// ============================================================================\n// Webhook Form Component\n// ============================================================================\n\ninterface WebhookFormProps {\n webhook?: EventWebhookMapping;\n dashboardId?: string;\n widgetId?: string;\n onSave: (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => Promise<void>;\n onCancel: () => void;\n loading?: boolean;\n}\n\nconst WebhookForm: React.FC<WebhookFormProps> = memo(function WebhookForm({\n webhook,\n dashboardId,\n widgetId,\n onSave,\n onCancel,\n loading,\n}) {\n const { t } = useI18n();\n const [eventPattern, setEventPattern] = useState(webhook?.eventPattern || 'widget:*:clicked');\n const [webhookUrl, setWebhookUrl] = useState(webhook?.webhookUrl || '');\n const [method, setMethod] = useState(webhook?.method || 'POST');\n const [headers, setHeaders] = useState(webhook?.headers ? JSON.stringify(webhook.headers, null, 2) : '');\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n let parsedHeaders: Record<string, string> | undefined;\n if (headers.trim()) {\n try {\n parsedHeaders = JSON.parse(headers);\n } catch {\n alert(t('bigconsole.widget.webhookConfig.invalidJson', 'Invalid JSON in headers field'));\n return;\n }\n }\n\n if (webhook) {\n // Update\n await onSave({\n id: webhook.id,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders || null,\n });\n } else {\n // Create\n await onSave({\n dashboardId,\n widgetId,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders,\n });\n }\n };\n\n return (\n <form style={styles.form} onSubmit={handleSubmit}>\n <div style={styles.formGroup}>\n <label style={styles.label}>{t('bigconsole.widget.webhookConfig.eventPatternLabel', 'Event Pattern *')}</label>\n <input\n type=\"text\"\n value={eventPattern}\n onChange={(e) => setEventPattern(e.target.value)}\n placeholder=\"widget:*:clicked\"\n style={styles.input}\n required\n />\n <p style={styles.helpText}>\n {t(\n 'bigconsole.widget.webhookConfig.eventPatternHelp',\n 'Use * as wildcard. Examples: widget:*:clicked, *:submit, button:save:*'\n )}\n </p>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>{t('bigconsole.widget.webhookConfig.webhookUrlLabel', 'Webhook URL *')}</label>\n <input\n type=\"url\"\n value={webhookUrl}\n onChange={(e) => setWebhookUrl(e.target.value)}\n placeholder=\"https://your-api.com/webhooks/bigconsole\"\n style={styles.input}\n required\n />\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>{t('bigconsole.widget.webhookConfig.httpMethodLabel', 'HTTP Method')}</label>\n <select value={method} onChange={(e) => setMethod(e.target.value as HttpMethod)} style={styles.select}>\n <option value=\"POST\">POST</option>\n <option value=\"PUT\">PUT</option>\n <option value=\"PATCH\">PATCH</option>\n <option value=\"GET\">GET</option>\n <option value=\"DELETE\">DELETE</option>\n </select>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>\n {t('bigconsole.widget.webhookConfig.customHeadersLabel', 'Custom Headers (JSON)')}\n </label>\n <textarea\n value={headers}\n onChange={(e) => setHeaders(e.target.value)}\n placeholder={'{\\n \"Authorization\": \"Bearer your-token\"\\n}'}\n style={styles.textarea as React.CSSProperties}\n />\n </div>\n\n <div style={styles.formActions}>\n <button type=\"button\" onClick={onCancel} style={styles.cancelButton}>\n {t('bigconsole.widget.webhookConfig.cancel', 'Cancel')}\n </button>\n <button type=\"submit\" disabled={loading} style={styles.saveButton}>\n {loading\n ? t('bigconsole.widget.webhookConfig.saving', 'Saving...')\n : webhook\n ? t('bigconsole.widget.webhookConfig.updateWebhook', 'Update Webhook')\n : t('bigconsole.widget.webhookConfig.createWebhook', 'Create Webhook')}\n </button>\n </div>\n </form>\n );\n});\n\n// ============================================================================\n// Webhook Card Component\n// ============================================================================\n\ninterface WebhookCardProps {\n webhook: EventWebhookMapping;\n onEdit: () => void;\n onDelete: () => void;\n onToggle: () => void;\n onTest: () => void;\n testResult?: WebhookTestResult | null;\n testing?: boolean;\n}\n\nconst WebhookCard: React.FC<WebhookCardProps> = memo(function WebhookCard({\n webhook,\n onEdit,\n onDelete,\n onToggle,\n onTest,\n testResult,\n testing,\n}) {\n const { t } = useI18n();\n return (\n <div style={styles.webhookCard}>\n <div style={styles.webhookHeader}>\n <div style={styles.webhookTitle}>\n <span style={{ fontSize: '16px' }}>📡</span>\n <span style={styles.webhookName}>{webhook.eventPattern}</span>\n <span\n style={{\n ...styles.statusBadge,\n ...(webhook.isActive ? styles.activeBadge : styles.inactiveBadge),\n }}\n >\n {webhook.isActive\n ? t('bigconsole.widget.webhookConfig.active', 'Active')\n : t('bigconsole.widget.webhookConfig.inactive', 'Inactive')}\n </span>\n </div>\n </div>\n\n <div style={styles.webhookDetails}>\n {t('bigconsole.widget.webhookConfig.methodLabel', 'Method:')} <strong>{webhook.method}</strong>\n </div>\n <div style={styles.webhookUrl}>{webhook.webhookUrl}</div>\n\n {testResult && (\n <div\n style={{\n ...styles.testResult,\n ...(testResult.success ? styles.testSuccess : styles.testFailure),\n }}\n >\n {testResult.success ? (\n <>\n {t(\n 'bigconsole.widget.webhookConfig.testSuccess',\n '✅ Test successful! Status: {{statusCode}}, Latency: {{latencyMs}}ms',\n { statusCode: testResult.statusCode ?? '', latencyMs: testResult.latencyMs ?? '' }\n )}\n </>\n ) : (\n <>\n {t('bigconsole.widget.webhookConfig.testFailure', '❌ Test failed: {{error}}', {\n error: testResult.errorMessage || t('bigconsole.widget.webhookConfig.unknownError', 'Unknown error'),\n })}\n </>\n )}\n </div>\n )}\n\n <div style={styles.webhookActions}>\n <button onClick={onEdit} style={{ ...styles.actionButton, ...styles.editButton }}>\n {t('bigconsole.widget.webhookConfig.edit', 'Edit')}\n </button>\n <button onClick={onTest} disabled={testing} style={{ ...styles.actionButton, ...styles.testButton }}>\n {testing\n ? t('bigconsole.widget.webhookConfig.testing', 'Testing...')\n : t('bigconsole.widget.webhookConfig.test', 'Test')}\n </button>\n <button onClick={onToggle} style={{ ...styles.actionButton, ...styles.toggleButton }}>\n {webhook.isActive\n ? t('bigconsole.widget.webhookConfig.disable', 'Disable')\n : t('bigconsole.widget.webhookConfig.enable', 'Enable')}\n </button>\n <button onClick={onDelete} style={{ ...styles.actionButton, ...styles.deleteButton }}>\n {t('bigconsole.widget.webhookConfig.delete', 'Delete')}\n </button>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WebhookConfigPanel: React.FC<WebhookConfigPanelProps> = memo(function WebhookConfigPanel({\n dashboardId,\n widgetId,\n onWebhookCreated,\n onWebhookDeleted,\n}) {\n const { t } = useI18n();\n const [showForm, setShowForm] = useState(false);\n const [editingWebhook, setEditingWebhook] = useState<EventWebhookMapping | null>(null);\n const [testResults, setTestResults] = useState<Record<string, WebhookTestResult | null>>({});\n const [testingId, setTestingId] = useState<string | null>(null);\n\n const { webhooks, loading, createWebhook, updateWebhook, deleteWebhook, toggleWebhook, testWebhook } =\n useEventWebhooks({ dashboardId, widgetId });\n\n const handleSave = useCallback(\n async (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => {\n if ('id' in data) {\n const result = await updateWebhook(data);\n if (result) {\n setEditingWebhook(null);\n setShowForm(false);\n }\n } else {\n const result = await createWebhook(data);\n if (result) {\n setShowForm(false);\n onWebhookCreated?.(result);\n }\n }\n },\n [createWebhook, updateWebhook, onWebhookCreated]\n );\n\n const handleDelete = useCallback(\n async (id: string) => {\n if (\n confirm(t('bigconsole.widget.webhookConfig.deleteConfirm', 'Are you sure you want to delete this webhook?'))\n ) {\n const success = await deleteWebhook(id);\n if (success) {\n onWebhookDeleted?.(id);\n }\n }\n },\n [deleteWebhook, onWebhookDeleted, t]\n );\n\n const handleToggle = useCallback(\n async (webhook: EventWebhookMapping) => {\n await toggleWebhook(webhook.id, !webhook.isActive);\n },\n [toggleWebhook]\n );\n\n const handleTest = useCallback(\n async (id: string) => {\n setTestingId(id);\n const result = await testWebhook(id);\n setTestResults((prev) => ({ ...prev, [id]: result }));\n setTestingId(null);\n },\n [testWebhook]\n );\n\n const handleEdit = useCallback((webhook: EventWebhookMapping) => {\n setEditingWebhook(webhook);\n setShowForm(true);\n }, []);\n\n const handleCancel = useCallback(() => {\n setShowForm(false);\n setEditingWebhook(null);\n }, []);\n\n return (\n <div style={styles.container}>\n <div style={styles.header}>\n <h3 style={styles.title}>{t('bigconsole.widget.webhookConfig.title', 'Webhook Configuration')}</h3>\n {!showForm && (\n <button onClick={() => setShowForm(true)} style={styles.addButton}>\n {t('bigconsole.widget.webhookConfig.addWebhook', '+ Add Webhook')}\n </button>\n )}\n </div>\n\n {showForm && (\n <WebhookForm\n webhook={editingWebhook || undefined}\n dashboardId={dashboardId}\n widgetId={widgetId}\n onSave={handleSave}\n onCancel={handleCancel}\n loading={loading}\n />\n )}\n\n {loading && webhooks.length === 0 ? (\n <div style={styles.emptyState}>{t('bigconsole.widget.webhookConfig.loading', 'Loading...')}</div>\n ) : webhooks.length === 0 ? (\n <div style={styles.emptyState}>\n <p>{t('bigconsole.widget.webhookConfig.noWebhooks', 'No webhooks configured')}</p>\n <p style={{ fontSize: '13px', marginTop: '8px' }}>\n {t(\n 'bigconsole.widget.webhookConfig.noWebhooksHelp',\n 'Add a webhook to receive events when actions are triggered.'\n )}\n </p>\n </div>\n ) : (\n <div style={styles.webhookList as React.CSSProperties}>\n {webhooks.map((webhook) => (\n <WebhookCard\n key={webhook.id}\n webhook={webhook}\n onEdit={() => handleEdit(webhook)}\n onDelete={() => handleDelete(webhook.id)}\n onToggle={() => handleToggle(webhook)}\n onTest={() => handleTest(webhook.id)}\n testResult={testResults[webhook.id]}\n testing={testingId === webhook.id}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nexport default WebhookConfigPanel;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WebhookConfigPanel.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.tsx"],"sourcesContent":["/**\n * WebhookConfigPanel Component (v2.0)\n *\n * Panel for managing event webhook mappings.\n * Allows creating, editing, testing, and deleting webhooks.\n */\n\nimport React, { memo, useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useEventWebhooks,\n type HttpMethod,\n type EventWebhookMapping,\n type CreateEventWebhookMappingInput,\n type UpdateEventWebhookMappingInput,\n type WebhookTestResult,\n} from '../../../hooks/useEventWebhooks';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WebhookConfigPanelProps {\n /** Dashboard ID for webhook scope */\n dashboardId?: string;\n /** Widget ID for webhook scope */\n widgetId?: string;\n /** Callback when webhook is created */\n onWebhookCreated?: (webhook: EventWebhookMapping) => void;\n /** Callback when webhook is deleted */\n onWebhookDeleted?: (id: string) => void;\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\n/**\n * Section emphasis (BOFF-5636). This panel used to draw its own card (16px\n * padding, surface fill, 8px radius) and its own 16px `<h3>Webhook\n * Configuration</h3>` — directly beneath the inspector's own 14px \"Webhooks\"\n * heading, so the child heading was larger than its parent. The owning\n * `<Section>` now supplies the surface, the heading and the description; this\n * component supplies only the toolbar, the list and the form.\n */\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n gap: 'var(--space-formGap)',\n minWidth: 0,\n } as React.CSSProperties,\n header: {\n display: 'flex',\n flexWrap: 'wrap',\n justifyContent: 'flex-end',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n } as React.CSSProperties,\n addButton: {\n minHeight: 'var(--size-controlHeight-md)',\n padding: '0 var(--space-formGap)',\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-action-primary-text)',\n border: 'none',\n borderRadius: 'var(--radius-button)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n webhookList: {\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n } as React.CSSProperties,\n webhookCard: {\n padding: 'var(--space-cardPadding)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-card)',\n border: '1px solid var(--color-border-subtle)',\n minWidth: 0,\n } as React.CSSProperties,\n webhookHeader: {\n display: 'flex',\n flexWrap: 'wrap',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n gap: 'var(--space-iconGap)',\n marginBottom: '8px',\n minWidth: 0,\n } as React.CSSProperties,\n webhookTitle: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '8px',\n minWidth: 0,\n } as React.CSSProperties,\n webhookName: {\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 600,\n color: 'var(--color-text-primary)',\n wordBreak: 'break-word',\n } as React.CSSProperties,\n statusBadge: {\n padding: '2px 8px',\n borderRadius: '12px',\n fontSize: '12px',\n fontWeight: 500,\n } as React.CSSProperties,\n activeBadge: {\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n color: 'var(--color-status-success-text)',\n } as React.CSSProperties,\n inactiveBadge: {\n backgroundColor: 'var(--color-status-warning-bgSubtle)',\n color: 'var(--color-status-warning-text)',\n } as React.CSSProperties,\n webhookDetails: {\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginBottom: '4px',\n } as React.CSSProperties,\n webhookUrl: {\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n fontFamily: 'var(--font-family-mono)',\n wordBreak: 'break-all',\n } as React.CSSProperties,\n // Four buttons in a 420px sheet: they wrap rather than overflow the panel.\n webhookActions: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: '8px',\n marginTop: '12px',\n } as React.CSSProperties,\n actionButton: {\n minHeight: 'var(--size-controlHeight-md)',\n padding: '0 12px',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 500,\n borderRadius: 'var(--radius-button)',\n border: 'none',\n cursor: 'pointer',\n } as React.CSSProperties,\n editButton: {\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-primary)',\n } as React.CSSProperties,\n testButton: {\n backgroundColor: 'var(--color-status-info-bgSubtle)',\n color: 'var(--color-status-info-text)',\n } as React.CSSProperties,\n deleteButton: {\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n color: 'var(--color-status-error-text)',\n } as React.CSSProperties,\n toggleButton: {\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-muted)',\n } as React.CSSProperties,\n emptyState: {\n textAlign: 'center',\n padding: 'var(--space-pagePadding) var(--space-formGap)',\n color: 'var(--color-text-secondary)',\n backgroundColor: 'var(--color-status-info-bgSubtle)',\n border: '1px solid var(--color-status-info-border)',\n borderRadius: 'var(--radius-card)',\n } as React.CSSProperties,\n emptyTitle: {\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 600,\n color: 'var(--color-status-info-text)',\n margin: 0,\n } as React.CSSProperties,\n form: {\n padding: 'var(--space-cardPadding)',\n backgroundColor: 'var(--color-bg-sunken)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 'var(--radius-card)',\n minWidth: 0,\n } as React.CSSProperties,\n formGroup: {\n marginBottom: '12px',\n } as React.CSSProperties,\n label: {\n display: 'block',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--color-text-primary)',\n marginBottom: '4px',\n } as React.CSSProperties,\n input: {\n width: '100%',\n minHeight: 'var(--size-controlHeight-md)',\n padding: '8px 12px',\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-primary)',\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 'var(--radius-input)',\n boxSizing: 'border-box',\n } as React.CSSProperties,\n select: {\n width: '100%',\n minHeight: 'var(--size-controlHeight-md)',\n padding: '8px 12px',\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-primary)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 'var(--radius-input)',\n boxSizing: 'border-box',\n backgroundColor: 'var(--color-bg-surface)',\n } as React.CSSProperties,\n textarea: {\n width: '100%',\n padding: '8px 12px',\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-primary)',\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 'var(--radius-input)',\n boxSizing: 'border-box',\n fontFamily: 'var(--font-family-mono)',\n minHeight: '80px',\n resize: 'vertical',\n } as React.CSSProperties,\n formActions: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: '8px',\n justifyContent: 'flex-end',\n marginTop: 'var(--space-formGap)',\n } as React.CSSProperties,\n cancelButton: {\n minHeight: 'var(--size-controlHeight-md)',\n padding: '0 var(--space-formGap)',\n backgroundColor: 'var(--color-bg-surface)',\n color: 'var(--color-text-primary)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 'var(--radius-button)',\n fontSize: 'var(--font-size-body-sm)',\n cursor: 'pointer',\n } as React.CSSProperties,\n saveButton: {\n minHeight: 'var(--size-controlHeight-md)',\n padding: '0 var(--space-formGap)',\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-action-primary-text)',\n border: 'none',\n borderRadius: 'var(--radius-button)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n testResult: {\n marginTop: '12px',\n padding: '12px',\n borderRadius: '6px',\n fontSize: '13px',\n } as React.CSSProperties,\n testSuccess: {\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n color: 'var(--color-status-success-text)',\n } as React.CSSProperties,\n testFailure: {\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n color: 'var(--color-status-error-text)',\n } as React.CSSProperties,\n helpText: {\n fontSize: '12px',\n color: 'var(--color-text-placeholder)',\n marginTop: '4px',\n } as React.CSSProperties,\n};\n\n// ============================================================================\n// Webhook Form Component\n// ============================================================================\n\ninterface WebhookFormProps {\n webhook?: EventWebhookMapping;\n dashboardId?: string;\n widgetId?: string;\n onSave: (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => Promise<void>;\n onCancel: () => void;\n loading?: boolean;\n}\n\nconst WebhookForm: React.FC<WebhookFormProps> = memo(function WebhookForm({\n webhook,\n dashboardId,\n widgetId,\n onSave,\n onCancel,\n loading,\n}) {\n const { t } = useI18n();\n const [eventPattern, setEventPattern] = useState(webhook?.eventPattern || 'widget:*:clicked');\n const [webhookUrl, setWebhookUrl] = useState(webhook?.webhookUrl || '');\n const [method, setMethod] = useState(webhook?.method || 'POST');\n const [headers, setHeaders] = useState(webhook?.headers ? JSON.stringify(webhook.headers, null, 2) : '');\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n let parsedHeaders: Record<string, string> | undefined;\n if (headers.trim()) {\n try {\n parsedHeaders = JSON.parse(headers);\n } catch {\n alert(t('bigconsole.widget.webhookConfig.invalidJson', 'Invalid JSON in headers field'));\n return;\n }\n }\n\n if (webhook) {\n // Update\n await onSave({\n id: webhook.id,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders || null,\n });\n } else {\n // Create\n await onSave({\n dashboardId,\n widgetId,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders,\n });\n }\n };\n\n return (\n <form style={styles.form} onSubmit={handleSubmit}>\n <div style={styles.formGroup}>\n <label style={styles.label}>{t('bigconsole.widget.webhookConfig.eventPatternLabel', 'Event Pattern *')}</label>\n <input\n type=\"text\"\n value={eventPattern}\n onChange={(e) => setEventPattern(e.target.value)}\n placeholder=\"widget:*:clicked\"\n style={styles.input}\n required\n />\n <p style={styles.helpText}>\n {t(\n 'bigconsole.widget.webhookConfig.eventPatternHelp',\n 'Use * as wildcard. Examples: widget:*:clicked, *:submit, button:save:*'\n )}\n </p>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>{t('bigconsole.widget.webhookConfig.webhookUrlLabel', 'Webhook URL *')}</label>\n <input\n type=\"url\"\n value={webhookUrl}\n onChange={(e) => setWebhookUrl(e.target.value)}\n placeholder=\"https://your-api.com/webhooks/bigconsole\"\n style={styles.input}\n required\n />\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>{t('bigconsole.widget.webhookConfig.httpMethodLabel', 'HTTP Method')}</label>\n <select value={method} onChange={(e) => setMethod(e.target.value as HttpMethod)} style={styles.select}>\n <option value=\"POST\">POST</option>\n <option value=\"PUT\">PUT</option>\n <option value=\"PATCH\">PATCH</option>\n <option value=\"GET\">GET</option>\n <option value=\"DELETE\">DELETE</option>\n </select>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>\n {t('bigconsole.widget.webhookConfig.customHeadersLabel', 'Custom Headers (JSON)')}\n </label>\n <textarea\n value={headers}\n onChange={(e) => setHeaders(e.target.value)}\n placeholder={'{\\n \"Authorization\": \"Bearer your-token\"\\n}'}\n style={styles.textarea as React.CSSProperties}\n />\n </div>\n\n <div style={styles.formActions}>\n <button type=\"button\" onClick={onCancel} style={styles.cancelButton}>\n {t('bigconsole.widget.webhookConfig.cancel', 'Cancel')}\n </button>\n <button type=\"submit\" disabled={loading} style={styles.saveButton}>\n {loading\n ? t('bigconsole.widget.webhookConfig.saving', 'Saving...')\n : webhook\n ? t('bigconsole.widget.webhookConfig.updateWebhook', 'Update Webhook')\n : t('bigconsole.widget.webhookConfig.createWebhook', 'Create Webhook')}\n </button>\n </div>\n </form>\n );\n});\n\n// ============================================================================\n// Webhook Card Component\n// ============================================================================\n\ninterface WebhookCardProps {\n webhook: EventWebhookMapping;\n onEdit: () => void;\n onDelete: () => void;\n onToggle: () => void;\n onTest: () => void;\n testResult?: WebhookTestResult | null;\n testing?: boolean;\n}\n\nconst WebhookCard: React.FC<WebhookCardProps> = memo(function WebhookCard({\n webhook,\n onEdit,\n onDelete,\n onToggle,\n onTest,\n testResult,\n testing,\n}) {\n const { t } = useI18n();\n return (\n <div style={styles.webhookCard}>\n <div style={styles.webhookHeader}>\n <div style={styles.webhookTitle}>\n <span style={styles.webhookName}>{webhook.eventPattern}</span>\n <span\n style={{\n ...styles.statusBadge,\n ...(webhook.isActive ? styles.activeBadge : styles.inactiveBadge),\n }}\n >\n {webhook.isActive\n ? t('bigconsole.widget.webhookConfig.active', 'Active')\n : t('bigconsole.widget.webhookConfig.inactive', 'Inactive')}\n </span>\n </div>\n </div>\n\n <div style={styles.webhookDetails}>\n {t('bigconsole.widget.webhookConfig.methodLabel', 'Method:')} <strong>{webhook.method}</strong>\n </div>\n <div style={styles.webhookUrl}>{webhook.webhookUrl}</div>\n\n {testResult && (\n <div\n role=\"status\"\n style={{\n ...styles.testResult,\n ...(testResult.success ? styles.testSuccess : styles.testFailure),\n }}\n >\n {testResult.success ? (\n <>\n {t(\n 'bigconsole.widget.webhookConfig.testSuccess',\n 'Test successful! Status: {{statusCode}}, Latency: {{latencyMs}}ms',\n { statusCode: testResult.statusCode ?? '', latencyMs: testResult.latencyMs ?? '' }\n )}\n </>\n ) : (\n <>\n {t('bigconsole.widget.webhookConfig.testFailure', 'Test failed: {{error}}', {\n error: testResult.errorMessage || t('bigconsole.widget.webhookConfig.unknownError', 'Unknown error'),\n })}\n </>\n )}\n </div>\n )}\n\n <div style={styles.webhookActions}>\n <button onClick={onEdit} style={{ ...styles.actionButton, ...styles.editButton }}>\n {t('bigconsole.widget.webhookConfig.edit', 'Edit')}\n </button>\n <button onClick={onTest} disabled={testing} style={{ ...styles.actionButton, ...styles.testButton }}>\n {testing\n ? t('bigconsole.widget.webhookConfig.testing', 'Testing...')\n : t('bigconsole.widget.webhookConfig.test', 'Test')}\n </button>\n <button onClick={onToggle} style={{ ...styles.actionButton, ...styles.toggleButton }}>\n {webhook.isActive\n ? t('bigconsole.widget.webhookConfig.disable', 'Disable')\n : t('bigconsole.widget.webhookConfig.enable', 'Enable')}\n </button>\n <button onClick={onDelete} style={{ ...styles.actionButton, ...styles.deleteButton }}>\n {t('bigconsole.widget.webhookConfig.delete', 'Delete')}\n </button>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WebhookConfigPanel: React.FC<WebhookConfigPanelProps> = memo(function WebhookConfigPanel({\n dashboardId,\n widgetId,\n onWebhookCreated,\n onWebhookDeleted,\n}) {\n const { t } = useI18n();\n const [showForm, setShowForm] = useState(false);\n const [editingWebhook, setEditingWebhook] = useState<EventWebhookMapping | null>(null);\n const [testResults, setTestResults] = useState<Record<string, WebhookTestResult | null>>({});\n const [testingId, setTestingId] = useState<string | null>(null);\n\n const { webhooks, loading, createWebhook, updateWebhook, deleteWebhook, toggleWebhook, testWebhook } =\n useEventWebhooks({ dashboardId, widgetId });\n\n const handleSave = useCallback(\n async (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => {\n if ('id' in data) {\n const result = await updateWebhook(data);\n if (result) {\n setEditingWebhook(null);\n setShowForm(false);\n }\n } else {\n const result = await createWebhook(data);\n if (result) {\n setShowForm(false);\n onWebhookCreated?.(result);\n }\n }\n },\n [createWebhook, updateWebhook, onWebhookCreated]\n );\n\n const handleDelete = useCallback(\n async (id: string) => {\n if (\n confirm(t('bigconsole.widget.webhookConfig.deleteConfirm', 'Are you sure you want to delete this webhook?'))\n ) {\n const success = await deleteWebhook(id);\n if (success) {\n onWebhookDeleted?.(id);\n }\n }\n },\n [deleteWebhook, onWebhookDeleted, t]\n );\n\n const handleToggle = useCallback(\n async (webhook: EventWebhookMapping) => {\n await toggleWebhook(webhook.id, !webhook.isActive);\n },\n [toggleWebhook]\n );\n\n const handleTest = useCallback(\n async (id: string) => {\n setTestingId(id);\n const result = await testWebhook(id);\n setTestResults((prev) => ({ ...prev, [id]: result }));\n setTestingId(null);\n },\n [testWebhook]\n );\n\n const handleEdit = useCallback((webhook: EventWebhookMapping) => {\n setEditingWebhook(webhook);\n setShowForm(true);\n }, []);\n\n const handleCancel = useCallback(() => {\n setShowForm(false);\n setEditingWebhook(null);\n }, []);\n\n return (\n <div style={styles.container} data-testid=\"webhook-config-panel\">\n {!showForm && (\n <div style={styles.header}>\n <button type=\"button\" onClick={() => setShowForm(true)} style={styles.addButton}>\n {t('bigconsole.widget.webhookConfig.addWebhook', '+ Add Webhook')}\n </button>\n </div>\n )}\n\n {showForm && (\n <WebhookForm\n webhook={editingWebhook || undefined}\n dashboardId={dashboardId}\n widgetId={widgetId}\n onSave={handleSave}\n onCancel={handleCancel}\n loading={loading}\n />\n )}\n\n {loading && webhooks.length === 0 ? (\n <div style={styles.emptyState} role=\"status\">\n <p style={styles.emptyTitle}>{t('bigconsole.widget.webhookConfig.loading', 'Loading...')}</p>\n </div>\n ) : webhooks.length === 0 ? (\n <div style={styles.emptyState} role=\"status\">\n <p style={styles.emptyTitle}>{t('bigconsole.widget.webhookConfig.noWebhooks', 'No webhooks configured')}</p>\n <p style={{ fontSize: 'var(--font-size-body-sm)', marginTop: '8px' }}>\n {t(\n 'bigconsole.widget.webhookConfig.noWebhooksHelp',\n 'Add a webhook to receive events when actions are triggered.'\n )}\n </p>\n </div>\n ) : (\n <div style={styles.webhookList as React.CSSProperties}>\n {webhooks.map((webhook) => (\n <WebhookCard\n key={webhook.id}\n webhook={webhook}\n onEdit={() => handleEdit(webhook)}\n onDelete={() => handleDelete(webhook.id)}\n onToggle={() => handleToggle(webhook)}\n onTest={() => handleTest(webhook.id)}\n testResult={testResults[webhook.id]}\n testing={testingId === webhook.id}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nexport default WebhookConfigPanel;\n"],"mappings":"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"}
|
|
@@ -243,34 +243,36 @@ var g = t(function({ name: e, className: t = "w-4 h-4" }) {
|
|
|
243
243
|
justifyContent: "center"
|
|
244
244
|
},
|
|
245
245
|
children: [/* @__PURE__ */ l("div", {
|
|
246
|
-
className: "absolute inset-0
|
|
246
|
+
className: "absolute inset-0",
|
|
247
247
|
style: {
|
|
248
248
|
position: "absolute",
|
|
249
249
|
top: 0,
|
|
250
250
|
left: 0,
|
|
251
251
|
right: 0,
|
|
252
252
|
bottom: 0,
|
|
253
|
-
backgroundColor: "
|
|
253
|
+
backgroundColor: "var(--color-overlay-scrim, var(--color-bg-canvas))",
|
|
254
|
+
opacity: .6
|
|
254
255
|
},
|
|
255
256
|
onClick: o
|
|
256
257
|
}), /* @__PURE__ */ u("div", {
|
|
257
|
-
className: "relative
|
|
258
|
+
className: "relative mx-4 w-full max-w-md rounded-card p-6",
|
|
258
259
|
style: {
|
|
259
260
|
position: "relative",
|
|
260
261
|
backgroundColor: "var(--color-bg-surface)",
|
|
261
|
-
|
|
262
|
-
|
|
262
|
+
border: "1px solid var(--color-border-subtle)",
|
|
263
|
+
borderRadius: "var(--radius-card)",
|
|
264
|
+
boxShadow: "var(--shadow-elevation-3)",
|
|
263
265
|
maxWidth: "28rem",
|
|
264
266
|
width: "100%",
|
|
265
267
|
margin: "0 16px",
|
|
266
|
-
padding: "
|
|
268
|
+
padding: "var(--space-cardPadding)",
|
|
267
269
|
zIndex: 1e4
|
|
268
270
|
},
|
|
269
271
|
children: [
|
|
270
272
|
/* @__PURE__ */ l("h3", {
|
|
271
|
-
className: "text-
|
|
273
|
+
className: "text-base font-semibold text-text-primary",
|
|
272
274
|
style: {
|
|
273
|
-
fontSize: "
|
|
275
|
+
fontSize: "var(--font-size-body-lg)",
|
|
274
276
|
fontWeight: 600,
|
|
275
277
|
color: "var(--color-text-primary)",
|
|
276
278
|
margin: 0
|
|
@@ -278,34 +280,36 @@ var g = t(function({ name: e, className: t = "w-4 h-4" }) {
|
|
|
278
280
|
children: e
|
|
279
281
|
}),
|
|
280
282
|
/* @__PURE__ */ l("p", {
|
|
281
|
-
className: "mt-2 text-sm text-secondary",
|
|
283
|
+
className: "mt-2 text-sm text-text-secondary",
|
|
282
284
|
style: {
|
|
283
285
|
marginTop: "8px",
|
|
284
|
-
fontSize: "
|
|
286
|
+
fontSize: "var(--font-size-body-sm)",
|
|
285
287
|
color: "var(--color-text-secondary)"
|
|
286
288
|
},
|
|
287
289
|
children: t
|
|
288
290
|
}),
|
|
289
291
|
/* @__PURE__ */ u("div", {
|
|
290
|
-
className: "mt-4 flex justify-end gap-3",
|
|
292
|
+
className: "mt-4 flex flex-wrap justify-end gap-3",
|
|
291
293
|
style: {
|
|
292
294
|
marginTop: "16px",
|
|
293
295
|
display: "flex",
|
|
296
|
+
flexWrap: "wrap",
|
|
294
297
|
justifyContent: "flex-end",
|
|
295
298
|
gap: "12px"
|
|
296
299
|
},
|
|
297
300
|
children: [/* @__PURE__ */ l("button", {
|
|
298
301
|
type: "button",
|
|
299
302
|
onClick: o,
|
|
300
|
-
className: "px-4
|
|
303
|
+
className: "min-h-control-md rounded-button px-4 text-sm font-medium text-text-secondary hover:text-text-primary motion-safe:transition-colors",
|
|
301
304
|
style: {
|
|
302
|
-
|
|
303
|
-
|
|
305
|
+
minHeight: "var(--size-controlHeight-md)",
|
|
306
|
+
padding: "0 16px",
|
|
307
|
+
fontSize: "var(--font-size-body-sm)",
|
|
304
308
|
fontWeight: 500,
|
|
305
309
|
color: "var(--color-text-secondary)",
|
|
306
|
-
backgroundColor: "var(--color-bg-
|
|
307
|
-
borderRadius: "
|
|
308
|
-
border: "
|
|
310
|
+
backgroundColor: "var(--color-bg-sunken)",
|
|
311
|
+
borderRadius: "var(--radius-button)",
|
|
312
|
+
border: "1px solid var(--color-border-subtle)",
|
|
309
313
|
cursor: "pointer"
|
|
310
314
|
},
|
|
311
315
|
children: r
|
|
@@ -353,10 +357,14 @@ var g = t(function({ name: e, className: t = "w-4 h-4" }) {
|
|
|
353
357
|
className: "fixed inset-0 z-[9998]",
|
|
354
358
|
onClick: S
|
|
355
359
|
}), /* @__PURE__ */ l("div", {
|
|
356
|
-
className: "fixed
|
|
360
|
+
className: "fixed z-[9999] w-48 max-w-[calc(100vw-1rem)] rounded-card",
|
|
357
361
|
style: {
|
|
358
362
|
top: v.top,
|
|
359
|
-
left: Math.max(8, v.left)
|
|
363
|
+
left: Math.max(8, v.left),
|
|
364
|
+
backgroundColor: "var(--color-bg-surface)",
|
|
365
|
+
border: "1px solid var(--color-border-subtle)",
|
|
366
|
+
borderRadius: "var(--radius-card)",
|
|
367
|
+
boxShadow: "var(--shadow-elevation-3)"
|
|
360
368
|
},
|
|
361
369
|
children: /* @__PURE__ */ l("div", {
|
|
362
370
|
className: "py-1",
|
|
@@ -364,7 +372,7 @@ var g = t(function({ name: e, className: t = "w-4 h-4" }) {
|
|
|
364
372
|
type: "button",
|
|
365
373
|
onClick: () => x(e),
|
|
366
374
|
disabled: e.disabled,
|
|
367
|
-
className: "w-full
|
|
375
|
+
className: "flex min-h-control-md w-full items-center gap-2 px-4 text-left text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-50 motion-safe:transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
|
|
368
376
|
children: [e.icon && /* @__PURE__ */ l(g, {
|
|
369
377
|
name: e.icon,
|
|
370
378
|
className: "w-4 h-4"
|
|
@@ -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 { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport type { WidgetAction, ActionContext, ActionResult } from '../../../renderers/types/renderer';\nimport { BIGCONSOLE_PERMISSIONS } from '../../../../constants/permissions';\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 // Triggering a widget action emits `widget:<name>:clicked` (and may fire a bound\n // webhook), which is gateway-enforced by `execute`. Gate the emitting buttons on\n // the same permission. LINK actions are pure client-side navigation (they render\n // an <a> that bypasses onAction), so they stay available regardless.\n const { hasPermission } = usePermissions();\n const canExecute = hasPermission(BIGCONSOLE_PERMISSIONS.WIDGET_ACTION_EXECUTE);\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 // LINK actions only navigate, so they aren't execute-gated; every\n // other action emits an event on click and requires `execute`.\n disabled={disabled || isLoading || (!canExecute && action.type !== 'LINK')}\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 // Overflow items always route through onAction (never a raw <a>), so\n // the whole menu is disabled when the caller can't execute actions.\n disabled={disabled || isLoading || !canExecute}\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 { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport type { WidgetAction, ActionContext, ActionResult } from '../../../renderers/types/renderer';\nimport { BIGCONSOLE_PERMISSIONS } from '../../../../constants/permissions';\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 {/*\n Scrim + panel. The raw `bg-black/50` and the `animate-in fade-in\n zoom-in-95` utilities are gone: the first is a literal colour, the second\n is an unregistered class set that emitted no CSS in this shell\n (BOFF-5636). The scrim now uses the overlay token and the panel uses the\n elevation scale.\n */}\n <div\n className=\"absolute inset-0\"\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: 'var(--color-overlay-scrim, var(--color-bg-canvas))',\n opacity: 0.6,\n }}\n onClick={onCancel}\n />\n\n {/* Dialog */}\n <div\n className=\"relative mx-4 w-full max-w-md rounded-card p-6\"\n style={{\n position: 'relative',\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 'var(--radius-card)',\n boxShadow: 'var(--shadow-elevation-3)',\n maxWidth: '28rem',\n width: '100%',\n margin: '0 16px',\n padding: 'var(--space-cardPadding)',\n zIndex: 10000,\n }}\n >\n <h3\n className=\"text-base font-semibold text-text-primary\"\n style={{\n fontSize: 'var(--font-size-body-lg)',\n fontWeight: 600,\n color: 'var(--color-text-primary)',\n margin: 0,\n }}\n >\n {title}\n </h3>\n <p\n className=\"mt-2 text-sm text-text-secondary\"\n style={{ marginTop: '8px', fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)' }}\n >\n {message}\n </p>\n <div\n className=\"mt-4 flex flex-wrap justify-end gap-3\"\n style={{ marginTop: '16px', display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: '12px' }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"min-h-control-md rounded-button px-4 text-sm font-medium text-text-secondary hover:text-text-primary motion-safe:transition-colors\"\n style={{\n minHeight: 'var(--size-controlHeight-md)',\n padding: '0 16px',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 500,\n color: 'var(--color-text-secondary)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-border-subtle)',\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 z-[9999] w-48 max-w-[calc(100vw-1rem)] rounded-card\"\n style={{\n top: menuPosition.top,\n left: Math.max(8, menuPosition.left), // Ensure at least 8px from left edge\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 'var(--radius-card)',\n boxShadow: 'var(--shadow-elevation-3)',\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=\"flex min-h-control-md w-full items-center gap-2 px-4 text-left text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-50 motion-safe:transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset\"\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 // Triggering a widget action emits `widget:<name>:clicked` (and may fire a bound\n // webhook), which is gateway-enforced by `execute`. Gate the emitting buttons on\n // the same permission. LINK actions are pure client-side navigation (they render\n // an <a> that bypasses onAction), so they stay available regardless.\n const { hasPermission } = usePermissions();\n const canExecute = hasPermission(BIGCONSOLE_PERMISSIONS.WIDGET_ACTION_EXECUTE);\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 // LINK actions only navigate, so they aren't execute-gated; every\n // other action emits an event on click and requires `execute`.\n disabled={disabled || isLoading || (!canExecute && action.type !== 'LINK')}\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 // Overflow items always route through onAction (never a raw <a>), so\n // the whole menu is disabled when the caller can't execute actions.\n disabled={disabled || isLoading || !canExecute}\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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"}
|