@burdenoff/microfe-bigconsole 2026.805.1 → 2026.805.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/dist/bigconsole/AdminRoot.js +21 -16
  2. package/dist/bigconsole/AdminRoot.js.map +1 -1
  3. package/dist/bigconsole/BigConsoleRoot.js +44 -39
  4. package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
  5. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +109 -113
  6. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
  7. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +115 -113
  8. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  9. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +71 -62
  10. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  11. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +116 -100
  12. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  13. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +56 -54
  14. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  15. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +126 -125
  16. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
  17. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +151 -150
  18. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
  19. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +77 -76
  20. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
  21. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +97 -96
  22. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  23. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +172 -191
  24. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  25. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +100 -98
  26. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
  27. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
  28. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
  29. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +151 -154
  30. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
  31. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +187 -193
  32. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
  33. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
  34. package/dist/bigconsole/components/dashboard/WidgetPalette.js +110 -108
  35. package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
  36. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +102 -103
  37. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  38. package/dist/bigconsole/components/datasink/DataSinkCard.js +20 -20
  39. package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
  40. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +36 -41
  41. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
  42. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +38 -37
  43. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
  44. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
  45. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
  46. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +182 -197
  47. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  48. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +166 -168
  49. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
  50. package/dist/bigconsole/components/parser/DataSinkSelector.js +87 -86
  51. package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
  52. package/dist/bigconsole/components/parser/ImportParserDialog.js +196 -211
  53. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  54. package/dist/bigconsole/components/parser/ParserSelector.js +130 -128
  55. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  56. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +66 -63
  57. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
  58. package/dist/bigconsole/components/preview/AiPreviewPanel.js +95 -91
  59. package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
  60. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +243 -230
  61. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  62. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +149 -145
  63. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  64. package/dist/bigconsole/components/widgets/PropertiesPanel.js +504 -470
  65. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  66. package/dist/bigconsole/components/widgets/WidgetMenu.js +87 -76
  67. package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
  68. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +44 -47
  69. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
  70. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +143 -142
  71. package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
  72. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +101 -88
  73. package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
  74. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +135 -134
  75. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  76. package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
  77. package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
  78. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +69 -68
  79. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
  80. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +64 -72
  81. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
  82. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +60 -59
  83. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  84. package/dist/bigconsole/components/widgets/list/ListConfig.js +57 -56
  85. package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
  86. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +70 -69
  87. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
  88. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
  89. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
  90. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
  91. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
  92. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +178 -177
  93. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
  94. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +76 -75
  95. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
  96. package/dist/bigconsole/components/widgets/table/TableConfig.js +183 -168
  97. package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
  98. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +187 -180
  99. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  100. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +120 -118
  101. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
  102. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +40 -38
  103. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
  104. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +150 -148
  105. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  106. package/dist/bigconsole/pages/DashboardBuilderPage.js +189 -175
  107. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  108. package/dist/bigconsole/pages/DashboardViewPage.js +200 -187
  109. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  110. package/dist/bigconsole/pages/DashboardsPage.js +379 -324
  111. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  112. package/dist/bigconsole/pages/DataParsersPage.js +185 -178
  113. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  114. package/dist/bigconsole/pages/DataSinkBuilderPage.js +195 -170
  115. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  116. package/dist/bigconsole/pages/DataSinkViewPage.js +224 -200
  117. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  118. package/dist/bigconsole/pages/DataSinksPage.js +281 -268
  119. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  120. package/dist/bigconsole/pages/DataSourcesPage.js +8 -7
  121. package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
  122. package/dist/bigconsole/pages/InsightsPage.js +238 -208
  123. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  124. package/dist/bigconsole/pages/ParserBuilderPage.js +480 -413
  125. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  126. package/dist/bigconsole/pages/ParserViewPage.js +192 -172
  127. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  128. package/dist/bigconsole/pages/PipelineBuilderPage.js +198 -163
  129. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  130. package/dist/bigconsole/pages/PipelineViewPage.js +138 -133
  131. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  132. package/dist/bigconsole/pages/PipelinesPage.js +162 -136
  133. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  134. package/dist/bigconsole/pages/SettingsPage.js +177 -172
  135. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  136. package/dist/bigconsole/pages/WidgetDemoPage.js +121 -83
  137. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  138. package/dist/bigconsole/pages/WorkflowViewPage.js +269 -242
  139. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  140. package/dist/bigconsole/pages/WorkflowsPage.js +153 -138
  141. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  142. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
  143. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
  144. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
  145. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
  146. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
  147. package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
  148. package/dist/constants/permissions.js +83 -0
  149. package/dist/constants/permissions.js.map +1 -0
  150. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetActions.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/widget-actions/WidgetActions.tsx"],"sourcesContent":["/**\n * Widget Actions Component (v2.0)\n *\n * Renders interactive action buttons for widgets.\n * Supports multiple action types, styles, confirmation dialogs, and icons.\n */\n\nimport React, { memo, useCallback, useState, useMemo, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { WidgetAction, ActionContext, ActionResult } from '../../../renderers/types/renderer';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetActionsProps {\n /** List of actions to render */\n actions: WidgetAction[];\n /** Action context (widget ID, data, etc.) */\n context: ActionContext;\n /** Callback when action is triggered */\n onAction?: (action: WidgetAction, context: ActionContext) => Promise<ActionResult | void>;\n /** Whether actions are disabled */\n disabled?: boolean;\n /** Layout direction */\n layout?: 'horizontal' | 'vertical';\n /** Size of action buttons */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show labels */\n showLabels?: boolean;\n /** Maximum number of visible actions (rest go to overflow menu) */\n maxVisible?: number;\n /** Custom class name */\n className?: string;\n}\n\ninterface ConfirmationDialogProps {\n title: string;\n message: string;\n confirmLabel: string;\n cancelLabel: string;\n style: WidgetAction['style'];\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n// ============================================================================\n// Style Utilities\n// ============================================================================\n\nfunction getButtonClasses(\n style: WidgetAction['style'] | undefined,\n size: 'sm' | 'md' | 'lg',\n disabled: boolean\n): string {\n const baseClasses =\n 'inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';\n\n const sizeClasses = {\n sm: 'px-2.5 py-1.5 text-xs',\n md: 'px-4 py-2 text-sm',\n lg: 'px-6 py-3 text-base',\n };\n\n const styleClasses: Record<string, string> = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90 focus:ring-action-primary/50 transition-colors',\n SECONDARY: 'bg-bg-sunken text-primary hover:bg-bg-sunken/80 focus:ring-muted transition-colors',\n DANGER:\n 'bg-status-error-bg text-white hover:bg-status-error-bg/90 focus:ring-status-error-border/50 transition-colors',\n SUCCESS:\n 'bg-status-success-bg text-white hover:bg-status-success-bg/90 focus:ring-status-success-border/50 transition-colors',\n WARNING:\n 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90 focus:ring-status-warning-border/50 transition-colors',\n };\n\n const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';\n\n // Default to SECONDARY if style is undefined\n const effectiveStyle = style || 'SECONDARY';\n const styleClass = styleClasses[effectiveStyle] || styleClasses.SECONDARY;\n\n return `${baseClasses} ${sizeClasses[size]} ${styleClass} ${disabledClasses}`;\n}\n\n// Get inline styles as fallback for button visibility\nfunction getButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: { backgroundColor: 'var(--color-action-primary-bg)', color: 'var(--color-action-primary-text)' },\n SECONDARY: { backgroundColor: 'var(--color-bg-muted)', color: 'var(--color-text-primary)' },\n DANGER: { backgroundColor: 'var(--color-status-error-bg)', color: 'var(--color-action-primary-text)' },\n SUCCESS: { backgroundColor: 'var(--color-status-success-bg)', color: 'var(--color-action-primary-text)' },\n WARNING: { backgroundColor: 'var(--color-status-warning-bg)', color: 'var(--color-action-primary-text)' },\n };\n const effectiveStyle = style || 'SECONDARY';\n return styles[effectiveStyle] || styles.SECONDARY;\n}\n\nfunction getConfirmButtonClasses(style: WidgetAction['style']): string {\n const styleClasses = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90',\n SECONDARY: 'bg-secondary text-white hover:bg-secondary/90',\n DANGER: 'bg-status-error-bg text-white hover:bg-status-error-bg/90',\n SUCCESS: 'bg-status-success-bg text-white hover:bg-status-success-bg/90',\n WARNING: 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90',\n };\n\n const effectiveStyle = style || 'PRIMARY';\n return `px-4 py-2 text-sm font-medium rounded-md transition-colors ${styleClasses[effectiveStyle] || styleClasses.PRIMARY}`;\n}\n\n// Get inline styles for confirm button to ensure visibility\nfunction getConfirmButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: {\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SECONDARY: {\n backgroundColor: 'var(--color-text-secondary)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n DANGER: {\n backgroundColor: 'var(--color-status-error-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SUCCESS: {\n backgroundColor: 'var(--color-status-success-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n WARNING: {\n backgroundColor: 'var(--color-status-warning-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n };\n const effectiveStyle = style || 'PRIMARY';\n return styles[effectiveStyle] || styles.PRIMARY;\n}\n\n// ============================================================================\n// Icon Component\n// ============================================================================\n\ninterface ActionIconProps {\n name: string;\n className?: string;\n}\n\nconst ActionIcon: React.FC<ActionIconProps> = memo(function ActionIcon({ name, className = 'w-4 h-4' }) {\n // Common icons used in actions\n const icons: Record<string, React.ReactNode> = {\n 'external-link': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\n />\n </svg>\n ),\n save: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"\n />\n </svg>\n ),\n trash: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n ),\n edit: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n refresh: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n ),\n download: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n ),\n upload: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12\"\n />\n </svg>\n ),\n plus: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n ),\n check: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n x: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n 'more-horizontal': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z\"\n />\n </svg>\n ),\n };\n\n return icons[name] || null;\n});\n\n// ============================================================================\n// Confirmation Dialog\n// ============================================================================\n\nconst ConfirmationDialog: React.FC<ConfirmationDialogProps> = memo(function ConfirmationDialog({\n title,\n message,\n confirmLabel,\n cancelLabel,\n style,\n onConfirm,\n onCancel,\n}) {\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50\"\n style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)' }}\n onClick={onCancel}\n />\n\n {/* Dialog */}\n <div\n className=\"relative bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6 animate-in fade-in zoom-in-95 duration-200\"\n style={{\n position: 'relative',\n backgroundColor: 'var(--color-bg-surface)',\n borderRadius: '8px',\n boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',\n maxWidth: '28rem',\n width: '100%',\n margin: '0 16px',\n padding: '24px',\n zIndex: 10000,\n }}\n >\n <h3\n className=\"text-lg font-semibold text-primary\"\n style={{ fontSize: '18px', fontWeight: 600, color: 'var(--color-text-primary)', margin: 0 }}\n >\n {title}\n </h3>\n <p\n className=\"mt-2 text-sm text-secondary\"\n style={{ marginTop: '8px', fontSize: '14px', color: 'var(--color-text-secondary)' }}\n >\n {message}\n </p>\n <div\n className=\"mt-4 flex justify-end gap-3\"\n style={{ marginTop: '16px', display: 'flex', justifyContent: 'flex-end', gap: '12px' }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-secondary bg-bg-sunken hover:bg-bg-sunken/80 rounded-md transition-colors\"\n style={{\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--color-text-secondary)',\n backgroundColor: 'var(--color-bg-muted)',\n borderRadius: '6px',\n border: 'none',\n cursor: 'pointer',\n }}\n >\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={getConfirmButtonClasses(style)}\n style={getConfirmButtonInlineStyles(style)}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Overflow Menu\n// ============================================================================\n\ninterface OverflowMenuProps {\n actions: WidgetAction[];\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n}\n\nconst OverflowMenu: React.FC<OverflowMenuProps> = memo(function OverflowMenu({\n actions,\n context: _context,\n onAction,\n disabled,\n size,\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });\n\n const handleToggle = useCallback(() => {\n if (!disabled) {\n setIsOpen((prev) => !prev);\n }\n }, [disabled]);\n\n const handleAction = useCallback(\n (action: WidgetAction) => {\n setIsOpen(false);\n onAction(action);\n },\n [onAction]\n );\n\n const handleClickOutside = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n // Calculate menu position when opening\n useEffect(() => {\n if (isOpen && buttonRef.current) {\n const rect = buttonRef.current.getBoundingClientRect();\n setMenuPosition({\n top: rect.bottom + 4, // 4px gap below button\n left: rect.right - 192, // 192px = w-48, align right edge\n });\n }\n }, [isOpen]);\n\n if (actions.length === 0) return null;\n\n return (\n <div className=\"relative\">\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={handleToggle}\n disabled={disabled}\n className={getButtonClasses('SECONDARY', size, disabled ?? false)}\n aria-label=\"More actions\"\n >\n <ActionIcon name=\"more-horizontal\" />\n </button>\n\n {isOpen &&\n createPortal(\n <>\n {/* Click-outside handler */}\n <div className=\"fixed inset-0 z-[9998]\" onClick={handleClickOutside} />\n\n {/* Menu - rendered via portal at body level */}\n <div\n className=\"fixed w-48 bg-surface rounded-md shadow-lg ring-1 ring-border z-[9999] animate-in fade-in slide-in-from-top-2 duration-150\"\n style={{\n top: menuPosition.top,\n left: Math.max(8, menuPosition.left), // Ensure at least 8px from left edge\n }}\n >\n <div className=\"py-1\">\n {actions.map((action) => (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => handleAction(action)}\n disabled={action.disabled}\n className=\"w-full text-left px-4 py-2 text-sm text-secondary hover:bg-bg-sunken hover:text-primary disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2 transition-colors\"\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4\" />}\n {action.label}\n </button>\n ))}\n </div>\n </div>\n </>,\n document.body\n )}\n </div>\n );\n});\n\n// ============================================================================\n// Action Button\n// ============================================================================\n\ninterface ActionButtonProps {\n action: WidgetAction;\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n showLabel?: boolean;\n}\n\nconst ActionButton: React.FC<ActionButtonProps> = memo(function ActionButton({\n action,\n context: _context,\n onAction,\n disabled,\n size,\n showLabel = true,\n}) {\n const isDisabled = disabled || action.disabled;\n\n const handleClick = useCallback(() => {\n if (!isDisabled) {\n onAction(action);\n }\n }, [action, isDisabled, onAction]);\n\n // Get both classes and inline styles for guaranteed visibility\n const buttonClasses = getButtonClasses(action.style, size, isDisabled);\n const buttonInlineStyles = getButtonInlineStyles(action.style);\n\n // Handle LINK type\n if (action.type === 'LINK' && action.metadata?.url) {\n return (\n <a\n href={action.metadata.url as string}\n target={(action.metadata.target as string) || '_blank'}\n rel=\"noopener noreferrer\"\n className={buttonClasses}\n style={buttonInlineStyles}\n aria-disabled={isDisabled}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n {!action.icon && <ActionIcon name=\"external-link\" className=\"w-4 h-4 ml-1.5\" />}\n </a>\n );\n }\n\n return (\n <button\n type={action.type === 'SUBMIT' ? 'submit' : 'button'}\n onClick={handleClick}\n disabled={isDisabled}\n className={buttonClasses}\n style={buttonInlineStyles}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n </button>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WidgetActions: React.FC<WidgetActionsProps> = memo(function WidgetActions({\n actions,\n context,\n onAction,\n disabled = false,\n layout = 'horizontal',\n size = 'md',\n showLabels = true,\n maxVisible = 3,\n className = '',\n}) {\n const [pendingAction, setPendingAction] = useState<WidgetAction | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Filter visible actions (not hidden)\n const visibleActions = useMemo(() => {\n return actions.filter((a) => !a.hidden).sort((a, b) => a.order - b.order);\n }, [actions]);\n\n // Split into main and overflow actions\n const { mainActions, overflowActions } = useMemo(() => {\n if (visibleActions.length <= maxVisible) {\n return { mainActions: visibleActions, overflowActions: [] };\n }\n return {\n mainActions: visibleActions.slice(0, maxVisible - 1),\n overflowActions: visibleActions.slice(maxVisible - 1),\n };\n }, [visibleActions, maxVisible]);\n\n // Execute action\n const executeAction = useCallback(\n async (action: WidgetAction) => {\n if (!onAction) return;\n\n setIsLoading(true);\n try {\n await onAction(action, context);\n } catch (error) {\n } finally {\n setIsLoading(false);\n }\n },\n [onAction, context]\n );\n\n // Handle action trigger\n const handleTriggerAction = useCallback(\n (action: WidgetAction) => {\n // If action has confirmation, show dialog\n if (action.confirmation) {\n setPendingAction(action);\n return;\n }\n\n // Execute action immediately\n executeAction(action);\n },\n [executeAction]\n );\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n if (pendingAction) {\n executeAction(pendingAction);\n setPendingAction(null);\n }\n }, [pendingAction, executeAction]);\n\n const handleCancel = useCallback(() => {\n setPendingAction(null);\n }, []);\n\n // No actions to render\n if (visibleActions.length === 0) {\n return null;\n }\n\n const layoutClasses = layout === 'horizontal' ? 'flex flex-row flex-wrap gap-2' : 'flex flex-col gap-2';\n\n return (\n <>\n <div className={`${layoutClasses} ${className}`}>\n {mainActions.map((action) => (\n <ActionButton\n key={action.id}\n action={action}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n showLabel={showLabels}\n />\n ))}\n\n {overflowActions.length > 0 && (\n <OverflowMenu\n actions={overflowActions}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n />\n )}\n </div>\n\n {/* Confirmation Dialog */}\n {pendingAction?.confirmation && (\n <ConfirmationDialog\n title={pendingAction.confirmation.title || 'Confirm Action'}\n message={pendingAction.confirmation.message || 'Are you sure you want to proceed?'}\n confirmLabel={pendingAction.confirmation.confirmLabel || 'OK'}\n cancelLabel={pendingAction.confirmation.cancelLabel || 'Cancel'}\n style={pendingAction.style}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n />\n )}\n </>\n );\n});\n\nexport default WidgetActions;\n"],"mappings":"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"}
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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"}
@@ -4,41 +4,42 @@ import n from "../hooks/useParserOperations.js";
4
4
  import "../hooks/index.js";
5
5
  import r from "./CustomWidgetProposalPanel.js";
6
6
  import { memo as i, useCallback as a, useMemo as o } from "react";
7
- import { Sheet as s, SheetContent as c, SheetDescription as l, SheetHeader as u, SheetTitle as d } from "@burdenoff/fe-libs/ui";
8
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
7
+ import { useI18n as s } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
8
+ import { Sheet as c, SheetContent as l, SheetDescription as u, SheetHeader as d, SheetTitle as f } from "@burdenoff/fe-libs/ui";
9
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
9
10
  //#region src/bigconsole/customWidget/CustomWidgetBuilderSheet.tsx
10
- var m = {
11
+ var h = {
11
12
  x: 0,
12
13
  y: 0,
13
14
  width: 6,
14
15
  height: 4
15
- }, h = "default", g = i(function({ isOpen: i, onClose: g, dashboardId: _, pageId: v, source: y }) {
16
- let { dataSinks: b } = t({ skipFetch: !i }), { createWidget: x } = e(v, _, { skipFetch: !0 }), S = _ === h, { parsers: C, executeParser: w } = n({
17
- consoleId: _,
16
+ }, g = "default", _ = i(function({ isOpen: i, onClose: _, dashboardId: v, pageId: y, source: b }) {
17
+ let { t: x } = s(), { dataSinks: S } = t({ skipFetch: !i }), { createWidget: C } = e(y, v, { skipFetch: !0 }), w = v === g, { parsers: T, executeParser: E } = n({
18
+ consoleId: v,
18
19
  skipFetch: !i
19
- }), { parsers: T } = n({
20
- consoleId: h,
21
- skipFetch: !i || S
22
- }), E = o(() => b.map((e) => ({
20
+ }), { parsers: D } = n({
21
+ consoleId: g,
22
+ skipFetch: !i || w
23
+ }), O = o(() => S.map((e) => ({
23
24
  id: e.id,
24
25
  key: e.key,
25
26
  name: e.name
26
- })), [b]), D = o(() => {
27
- let e = new Set(C.map((e) => e.id));
28
- return [...C, ...T.filter((t) => !e.has(t.id))].map((e) => ({
27
+ })), [S]), k = o(() => {
28
+ let e = new Set(T.map((e) => e.id));
29
+ return [...T, ...D.filter((t) => !e.has(t.id))].map((e) => ({
29
30
  id: e.id,
30
31
  name: e.name,
31
32
  inputSinkKey: e.inputSinkKey
32
33
  }));
33
- }, [C, T]), O = a(async (e) => {
34
+ }, [T, D]), A = a(async (e) => {
34
35
  if (!e.binding.parserId) return;
35
- let t = await w(e.binding.parserId);
36
- if (!t || !t.success) throw Error(t?.error || "Could not resolve the binding.");
36
+ let t = await E(e.binding.parserId);
37
+ if (!t || !t.success) throw Error(t?.error || x("bigconsole.widget.customWidget.error.couldNotResolveBinding", "Could not resolve the binding."));
37
38
  return t.output;
38
- }, [w]), k = a(async (e) => {
39
- if (!await x({
40
- pageId: v,
41
- dashboardId: _,
39
+ }, [E, x]), j = a(async (e) => {
40
+ if (!await C({
41
+ pageId: y,
42
+ dashboardId: v,
42
43
  type: e.widgetType,
43
44
  title: e.presentation.title,
44
45
  description: e.presentation.description,
@@ -51,17 +52,18 @@ var m = {
51
52
  sourcePrompt: e.sourcePrompt,
52
53
  proposalVersion: e.version
53
54
  },
54
- position: { ...m }
55
- })) throw Error("The widget could not be created.");
55
+ position: { ...h }
56
+ })) throw Error(x("bigconsole.widget.customWidget.error.widgetNotCreated", "The widget could not be created."));
56
57
  }, [
57
- x,
58
+ C,
59
+ y,
58
60
  v,
59
- _
61
+ x
60
62
  ]);
61
- return /* @__PURE__ */ f(s, {
63
+ return /* @__PURE__ */ p(c, {
62
64
  open: i,
63
- onOpenChange: (e) => !e && g(),
64
- children: /* @__PURE__ */ p(c, {
65
+ onOpenChange: (e) => !e && _(),
66
+ children: /* @__PURE__ */ m(l, {
65
67
  style: {
66
68
  width: 480,
67
69
  maxWidth: "95vw",
@@ -69,30 +71,30 @@ var m = {
69
71
  display: "flex",
70
72
  flexDirection: "column"
71
73
  },
72
- children: [/* @__PURE__ */ p(u, {
74
+ children: [/* @__PURE__ */ m(d, {
73
75
  style: {
74
76
  padding: 16,
75
77
  paddingBottom: 0
76
78
  },
77
- children: [/* @__PURE__ */ f(d, { children: "AI custom widget" }), /* @__PURE__ */ f(l, { children: "Describe a widget, review the proposal, then approve it onto the dashboard." })]
78
- }), /* @__PURE__ */ f("div", {
79
+ children: [/* @__PURE__ */ p(f, { children: x("bigconsole.widget.customWidget.sheet.title", "AI custom widget") }), /* @__PURE__ */ p(u, { children: x("bigconsole.widget.customWidget.sheet.description", "Describe a widget, review the proposal, then approve it onto the dashboard.") })]
80
+ }), /* @__PURE__ */ p("div", {
79
81
  style: {
80
82
  flex: 1,
81
83
  minHeight: 0
82
84
  },
83
- children: /* @__PURE__ */ f(r, {
84
- sinks: E,
85
- parsers: D,
86
- resolvePreviewData: O,
87
- onApprove: k,
88
- onClose: g,
89
- source: y
85
+ children: /* @__PURE__ */ p(r, {
86
+ sinks: O,
87
+ parsers: k,
88
+ resolvePreviewData: A,
89
+ onApprove: j,
90
+ onClose: _,
91
+ source: b
90
92
  })
91
93
  })]
92
94
  })
93
95
  });
94
96
  });
95
97
  //#endregion
96
- export { g as default };
98
+ export { _ as default };
97
99
 
98
100
  //# sourceMappingURL=CustomWidgetBuilderSheet.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CustomWidgetBuilderSheet.js","names":[],"sources":["../../../src/bigconsole/customWidget/CustomWidgetBuilderSheet.tsx"],"sourcesContent":["/**\n * Container that wires the custom-widget proposal panel to real workspace data\n * (BOFF-5532).\n *\n * Supplies the panel with the user's actual permitted DataSinks and parsers,\n * resolves previews by running the real parser, and persists an approved\n * proposal through the normal `createWidget` path — so an approved widget is an\n * ordinary widget, editable afterwards through the standard inspector.\n */\n\nimport { type FC, memo, useCallback, useMemo } from 'react';\nimport { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@burdenoff/fe-libs/ui';\n\nimport { useDataSinkOperations, useParserOperations, useWidgetOperations } from '../hooks';\nimport { CustomWidgetProposalPanel } from './CustomWidgetProposalPanel';\nimport type { CustomWidgetProposal } from './proposalContract';\nimport type { CustomWidgetProposalSource, ProposalCandidateParser, ProposalCandidateSink } from './proposalSource';\n\nexport interface CustomWidgetBuilderSheetProps {\n isOpen: boolean;\n onClose: () => void;\n dashboardId: string;\n pageId: string;\n /** Swap for the GraphQL-backed source once BOFF-3021's backend half lands. */\n source?: CustomWidgetProposalSource;\n}\n\n/** Grid slot for an approved widget; the reviewer can move it afterwards. */\nconst DEFAULT_POSITION = { x: 0, y: 0, width: 6, height: 4 } as const;\n\n/** Sentinel consoleId under which workspace-global parsers are stored. */\nconst GLOBAL_CONSOLE_ID = 'default';\n\nexport const CustomWidgetBuilderSheet: FC<CustomWidgetBuilderSheetProps> = memo(function CustomWidgetBuilderSheet({\n isOpen,\n onClose,\n dashboardId,\n pageId,\n source,\n}) {\n const { dataSinks } = useDataSinkOperations({ skipFetch: !isOpen });\n const { createWidget } = useWidgetOperations(pageId, dashboardId, { skipFetch: true });\n\n // Parsers are either dashboard-scoped or workspace-global (`consoleId: 'default'`),\n // and the widget inspector offers both. Fetch both here too, otherwise a proposal\n // can never bind to a global parser — which is what the parser builder creates by\n // default, so the picker would look empty in a typical workspace.\n const isGlobalConsole = dashboardId === GLOBAL_CONSOLE_ID;\n const { parsers: dashboardParsers, executeParser } = useParserOperations({\n consoleId: dashboardId,\n skipFetch: !isOpen,\n });\n const { parsers: globalParsers } = useParserOperations({\n consoleId: GLOBAL_CONSOLE_ID,\n skipFetch: !isOpen || isGlobalConsole,\n });\n\n const sinks: ProposalCandidateSink[] = useMemo(\n () => dataSinks.map((sink) => ({ id: sink.id, key: sink.key, name: sink.name })),\n [dataSinks]\n );\n\n const parserCandidates: ProposalCandidateParser[] = useMemo(() => {\n const seen = new Set(dashboardParsers.map((parser) => parser.id));\n const merged = [...dashboardParsers, ...globalParsers.filter((parser) => !seen.has(parser.id))];\n return merged.map((parser) => ({ id: parser.id, name: parser.name, inputSinkKey: parser.inputSinkKey }));\n }, [dashboardParsers, globalParsers]);\n\n /**\n * Resolves what the binding actually produces. Rejects on failure so the\n * panel can distinguish \"no data\" from \"you cannot read this\".\n */\n const resolvePreviewData = useCallback(\n async (proposal: CustomWidgetProposal): Promise<unknown> => {\n if (!proposal.binding.parserId) return undefined;\n const execution = await executeParser(proposal.binding.parserId);\n if (!execution || !execution.success) {\n throw new Error(execution?.error || 'Could not resolve the binding.');\n }\n return execution.output;\n },\n [executeParser]\n );\n\n const handleApprove = useCallback(\n async (proposal: CustomWidgetProposal) => {\n const widget = await createWidget({\n pageId,\n dashboardId,\n type: proposal.widgetType,\n title: proposal.presentation.title,\n description: proposal.presentation.description,\n dataSinkId: proposal.binding.dataSinkId || undefined,\n parserId: proposal.binding.parserId,\n config: {\n ...proposal.presentation.config,\n ...proposal.fieldMapping,\n // Provenance, so an approved widget can be traced back to its prompt\n // and survives export/import and clone with its origin intact.\n generatedBy: proposal.generatedBy,\n sourcePrompt: proposal.sourcePrompt,\n proposalVersion: proposal.version,\n },\n position: { ...DEFAULT_POSITION },\n });\n\n if (!widget) throw new Error('The widget could not be created.');\n },\n [createWidget, pageId, dashboardId]\n );\n\n return (\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <SheetContent style={{ width: 480, maxWidth: '95vw', padding: 0, display: 'flex', flexDirection: 'column' }}>\n <SheetHeader style={{ padding: 16, paddingBottom: 0 }}>\n <SheetTitle>AI custom widget</SheetTitle>\n <SheetDescription>\n Describe a widget, review the proposal, then approve it onto the dashboard.\n </SheetDescription>\n </SheetHeader>\n\n <div style={{ flex: 1, minHeight: 0 }}>\n <CustomWidgetProposalPanel\n sinks={sinks}\n parsers={parserCandidates}\n resolvePreviewData={resolvePreviewData}\n onApprove={handleApprove}\n onClose={onClose}\n source={source}\n />\n </div>\n </SheetContent>\n </Sheet>\n );\n});\n\nexport default CustomWidgetBuilderSheet;\n"],"mappings":";;;;;;;;;AA4BA,IAAM,IAAmB;CAAE,GAAG;CAAG,GAAG;CAAG,OAAO;CAAG,QAAQ;CAAG,EAGtD,IAAoB,WAEb,IAA8D,EAAK,SAAkC,EAChH,WACA,YACA,gBACA,WACA,aACC;CACD,IAAM,EAAE,iBAAc,EAAsB,EAAE,WAAW,CAAC,GAAQ,CAAC,EAC7D,EAAE,oBAAiB,EAAoB,GAAQ,GAAa,EAAE,WAAW,IAAM,CAAC,EAMhF,IAAkB,MAAgB,GAClC,EAAE,SAAS,GAAkB,qBAAkB,EAAoB;EACvE,WAAW;EACX,WAAW,CAAC;EACb,CAAC,EACI,EAAE,SAAS,MAAkB,EAAoB;EACrD,WAAW;EACX,WAAW,CAAC,KAAU;EACvB,CAAC,EAEI,IAAiC,QAC/B,EAAU,KAAK,OAAU;EAAE,IAAI,EAAK;EAAI,KAAK,EAAK;EAAK,MAAM,EAAK;EAAM,EAAE,EAChF,CAAC,EAAU,CACZ,EAEK,IAA8C,QAAc;EAChE,IAAM,IAAO,IAAI,IAAI,EAAiB,KAAK,MAAW,EAAO,GAAG,CAAC;AAEjE,SADe,CAAC,GAAG,GAAkB,GAAG,EAAc,QAAQ,MAAW,CAAC,EAAK,IAAI,EAAO,GAAG,CAAC,CAAC,CACjF,KAAK,OAAY;GAAE,IAAI,EAAO;GAAI,MAAM,EAAO;GAAM,cAAc,EAAO;GAAc,EAAE;IACvG,CAAC,GAAkB,EAAc,CAAC,EAM/B,IAAqB,EACzB,OAAO,MAAqD;AAC1D,MAAI,CAAC,EAAS,QAAQ,SAAU;EAChC,IAAM,IAAY,MAAM,EAAc,EAAS,QAAQ,SAAS;AAChE,MAAI,CAAC,KAAa,CAAC,EAAU,QAC3B,OAAU,MAAM,GAAW,SAAS,iCAAiC;AAEvE,SAAO,EAAU;IAEnB,CAAC,EAAc,CAChB,EAEK,IAAgB,EACpB,OAAO,MAAmC;AAqBxC,MAAI,CApBW,MAAM,EAAa;GAChC;GACA;GACA,MAAM,EAAS;GACf,OAAO,EAAS,aAAa;GAC7B,aAAa,EAAS,aAAa;GACnC,YAAY,EAAS,QAAQ,cAAc,KAAA;GAC3C,UAAU,EAAS,QAAQ;GAC3B,QAAQ;IACN,GAAG,EAAS,aAAa;IACzB,GAAG,EAAS;IAGZ,aAAa,EAAS;IACtB,cAAc,EAAS;IACvB,iBAAiB,EAAS;IAC3B;GACD,UAAU,EAAE,GAAG,GAAkB;GAClC,CAAC,CAEW,OAAU,MAAM,mCAAmC;IAElE;EAAC;EAAc;EAAQ;EAAY,CACpC;AAED,QACE,kBAAC,GAAD;EAAO,MAAM;EAAQ,eAAe,MAAS,CAAC,KAAQ,GAAS;YAC7D,kBAAC,GAAD;GAAc,OAAO;IAAE,OAAO;IAAK,UAAU;IAAQ,SAAS;IAAG,SAAS;IAAQ,eAAe;IAAU;aAA3G,CACE,kBAAC,GAAD;IAAa,OAAO;KAAE,SAAS;KAAI,eAAe;KAAG;cAArD,CACE,kBAAC,GAAD,EAAA,UAAY,oBAA6B,CAAA,EACzC,kBAAC,GAAD,EAAA,UAAkB,+EAEC,CAAA,CACP;OAEd,kBAAC,OAAD;IAAK,OAAO;KAAE,MAAM;KAAG,WAAW;KAAG;cACnC,kBAAC,GAAD;KACS;KACP,SAAS;KACW;KACpB,WAAW;KACF;KACD;KACR,CAAA;IACE,CAAA,CACO;;EACT,CAAA;EAEV"}
1
+ {"version":3,"file":"CustomWidgetBuilderSheet.js","names":[],"sources":["../../../src/bigconsole/customWidget/CustomWidgetBuilderSheet.tsx"],"sourcesContent":["/**\n * Container that wires the custom-widget proposal panel to real workspace data\n * (BOFF-5532).\n *\n * Supplies the panel with the user's actual permitted DataSinks and parsers,\n * resolves previews by running the real parser, and persists an approved\n * proposal through the normal `createWidget` path — so an approved widget is an\n * ordinary widget, editable afterwards through the standard inspector.\n */\n\nimport { type FC, memo, useCallback, useMemo } from 'react';\nimport { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nimport { useDataSinkOperations, useParserOperations, useWidgetOperations } from '../hooks';\nimport { CustomWidgetProposalPanel } from './CustomWidgetProposalPanel';\nimport type { CustomWidgetProposal } from './proposalContract';\nimport type { CustomWidgetProposalSource, ProposalCandidateParser, ProposalCandidateSink } from './proposalSource';\n\nexport interface CustomWidgetBuilderSheetProps {\n isOpen: boolean;\n onClose: () => void;\n dashboardId: string;\n pageId: string;\n /** Swap for the GraphQL-backed source once BOFF-3021's backend half lands. */\n source?: CustomWidgetProposalSource;\n}\n\n/** Grid slot for an approved widget; the reviewer can move it afterwards. */\nconst DEFAULT_POSITION = { x: 0, y: 0, width: 6, height: 4 } as const;\n\n/** Sentinel consoleId under which workspace-global parsers are stored. */\nconst GLOBAL_CONSOLE_ID = 'default';\n\nexport const CustomWidgetBuilderSheet: FC<CustomWidgetBuilderSheetProps> = memo(function CustomWidgetBuilderSheet({\n isOpen,\n onClose,\n dashboardId,\n pageId,\n source,\n}) {\n const { t } = useI18n();\n const { dataSinks } = useDataSinkOperations({ skipFetch: !isOpen });\n const { createWidget } = useWidgetOperations(pageId, dashboardId, { skipFetch: true });\n\n // Parsers are either dashboard-scoped or workspace-global (`consoleId: 'default'`),\n // and the widget inspector offers both. Fetch both here too, otherwise a proposal\n // can never bind to a global parser — which is what the parser builder creates by\n // default, so the picker would look empty in a typical workspace.\n const isGlobalConsole = dashboardId === GLOBAL_CONSOLE_ID;\n const { parsers: dashboardParsers, executeParser } = useParserOperations({\n consoleId: dashboardId,\n skipFetch: !isOpen,\n });\n const { parsers: globalParsers } = useParserOperations({\n consoleId: GLOBAL_CONSOLE_ID,\n skipFetch: !isOpen || isGlobalConsole,\n });\n\n const sinks: ProposalCandidateSink[] = useMemo(\n () => dataSinks.map((sink) => ({ id: sink.id, key: sink.key, name: sink.name })),\n [dataSinks]\n );\n\n const parserCandidates: ProposalCandidateParser[] = useMemo(() => {\n const seen = new Set(dashboardParsers.map((parser) => parser.id));\n const merged = [...dashboardParsers, ...globalParsers.filter((parser) => !seen.has(parser.id))];\n return merged.map((parser) => ({ id: parser.id, name: parser.name, inputSinkKey: parser.inputSinkKey }));\n }, [dashboardParsers, globalParsers]);\n\n /**\n * Resolves what the binding actually produces. Rejects on failure so the\n * panel can distinguish \"no data\" from \"you cannot read this\".\n */\n const resolvePreviewData = useCallback(\n async (proposal: CustomWidgetProposal): Promise<unknown> => {\n if (!proposal.binding.parserId) return undefined;\n const execution = await executeParser(proposal.binding.parserId);\n if (!execution || !execution.success) {\n throw new Error(\n execution?.error ||\n t('bigconsole.widget.customWidget.error.couldNotResolveBinding', 'Could not resolve the binding.')\n );\n }\n return execution.output;\n },\n [executeParser, t]\n );\n\n const handleApprove = useCallback(\n async (proposal: CustomWidgetProposal) => {\n const widget = await createWidget({\n pageId,\n dashboardId,\n type: proposal.widgetType,\n title: proposal.presentation.title,\n description: proposal.presentation.description,\n dataSinkId: proposal.binding.dataSinkId || undefined,\n parserId: proposal.binding.parserId,\n config: {\n ...proposal.presentation.config,\n ...proposal.fieldMapping,\n // Provenance, so an approved widget can be traced back to its prompt\n // and survives export/import and clone with its origin intact.\n generatedBy: proposal.generatedBy,\n sourcePrompt: proposal.sourcePrompt,\n proposalVersion: proposal.version,\n },\n position: { ...DEFAULT_POSITION },\n });\n\n if (!widget)\n throw new Error(t('bigconsole.widget.customWidget.error.widgetNotCreated', 'The widget could not be created.'));\n },\n [createWidget, pageId, dashboardId, t]\n );\n\n return (\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <SheetContent style={{ width: 480, maxWidth: '95vw', padding: 0, display: 'flex', flexDirection: 'column' }}>\n <SheetHeader style={{ padding: 16, paddingBottom: 0 }}>\n <SheetTitle>{t('bigconsole.widget.customWidget.sheet.title', 'AI custom widget')}</SheetTitle>\n <SheetDescription>\n {t(\n 'bigconsole.widget.customWidget.sheet.description',\n 'Describe a widget, review the proposal, then approve it onto the dashboard.'\n )}\n </SheetDescription>\n </SheetHeader>\n\n <div style={{ flex: 1, minHeight: 0 }}>\n <CustomWidgetProposalPanel\n sinks={sinks}\n parsers={parserCandidates}\n resolvePreviewData={resolvePreviewData}\n onApprove={handleApprove}\n onClose={onClose}\n source={source}\n />\n </div>\n </SheetContent>\n </Sheet>\n );\n});\n\nexport default CustomWidgetBuilderSheet;\n"],"mappings":";;;;;;;;;;AA6BA,IAAM,IAAmB;CAAE,GAAG;CAAG,GAAG;CAAG,OAAO;CAAG,QAAQ;CAAG,EAGtD,IAAoB,WAEb,IAA8D,EAAK,SAAkC,EAChH,WACA,YACA,gBACA,WACA,aACC;CACD,IAAM,EAAE,SAAM,GAAS,EACjB,EAAE,iBAAc,EAAsB,EAAE,WAAW,CAAC,GAAQ,CAAC,EAC7D,EAAE,oBAAiB,EAAoB,GAAQ,GAAa,EAAE,WAAW,IAAM,CAAC,EAMhF,IAAkB,MAAgB,GAClC,EAAE,SAAS,GAAkB,qBAAkB,EAAoB;EACvE,WAAW;EACX,WAAW,CAAC;EACb,CAAC,EACI,EAAE,SAAS,MAAkB,EAAoB;EACrD,WAAW;EACX,WAAW,CAAC,KAAU;EACvB,CAAC,EAEI,IAAiC,QAC/B,EAAU,KAAK,OAAU;EAAE,IAAI,EAAK;EAAI,KAAK,EAAK;EAAK,MAAM,EAAK;EAAM,EAAE,EAChF,CAAC,EAAU,CACZ,EAEK,IAA8C,QAAc;EAChE,IAAM,IAAO,IAAI,IAAI,EAAiB,KAAK,MAAW,EAAO,GAAG,CAAC;AAEjE,SADe,CAAC,GAAG,GAAkB,GAAG,EAAc,QAAQ,MAAW,CAAC,EAAK,IAAI,EAAO,GAAG,CAAC,CAAC,CACjF,KAAK,OAAY;GAAE,IAAI,EAAO;GAAI,MAAM,EAAO;GAAM,cAAc,EAAO;GAAc,EAAE;IACvG,CAAC,GAAkB,EAAc,CAAC,EAM/B,IAAqB,EACzB,OAAO,MAAqD;AAC1D,MAAI,CAAC,EAAS,QAAQ,SAAU;EAChC,IAAM,IAAY,MAAM,EAAc,EAAS,QAAQ,SAAS;AAChE,MAAI,CAAC,KAAa,CAAC,EAAU,QAC3B,OAAU,MACR,GAAW,SACT,EAAE,+DAA+D,iCAAiC,CACrG;AAEH,SAAO,EAAU;IAEnB,CAAC,GAAe,EAAE,CACnB,EAEK,IAAgB,EACpB,OAAO,MAAmC;AAqBxC,MAAI,CApBW,MAAM,EAAa;GAChC;GACA;GACA,MAAM,EAAS;GACf,OAAO,EAAS,aAAa;GAC7B,aAAa,EAAS,aAAa;GACnC,YAAY,EAAS,QAAQ,cAAc,KAAA;GAC3C,UAAU,EAAS,QAAQ;GAC3B,QAAQ;IACN,GAAG,EAAS,aAAa;IACzB,GAAG,EAAS;IAGZ,aAAa,EAAS;IACtB,cAAc,EAAS;IACvB,iBAAiB,EAAS;IAC3B;GACD,UAAU,EAAE,GAAG,GAAkB;GAClC,CAAC,CAGA,OAAU,MAAM,EAAE,yDAAyD,mCAAmC,CAAC;IAEnH;EAAC;EAAc;EAAQ;EAAa;EAAE,CACvC;AAED,QACE,kBAAC,GAAD;EAAO,MAAM;EAAQ,eAAe,MAAS,CAAC,KAAQ,GAAS;YAC7D,kBAAC,GAAD;GAAc,OAAO;IAAE,OAAO;IAAK,UAAU;IAAQ,SAAS;IAAG,SAAS;IAAQ,eAAe;IAAU;aAA3G,CACE,kBAAC,GAAD;IAAa,OAAO;KAAE,SAAS;KAAI,eAAe;KAAG;cAArD,CACE,kBAAC,GAAD,EAAA,UAAa,EAAE,8CAA8C,mBAAmB,EAAc,CAAA,EAC9F,kBAAC,GAAD,EAAA,UACG,EACC,oDACA,8EACD,EACgB,CAAA,CACP;OAEd,kBAAC,OAAD;IAAK,OAAO;KAAE,MAAM;KAAG,WAAW;KAAG;cACnC,kBAAC,GAAD;KACS;KACP,SAAS;KACW;KACpB,WAAW;KACF;KACD;KACR,CAAA;IACE,CAAA,CACO;;EACT,CAAA;EAEV"}