@burdenoff/microfe-bigconsole 2026.924.2 → 2026.925.1

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 (134) hide show
  1. package/dist/bigconsole/BigConsoleRoot.js +94 -84
  2. package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
  3. package/dist/bigconsole/BigConsoleRoutes.js +137 -138
  4. package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
  5. package/dist/bigconsole/assistant/previewController.js +7 -7
  6. package/dist/bigconsole/components/DrilldownDashboardRenderer.js +17 -17
  7. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +32 -32
  8. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +52 -52
  9. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  10. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +7 -7
  11. package/dist/bigconsole/components/dashboard/DashboardStatusPill.js +53 -0
  12. package/dist/bigconsole/components/dashboard/DashboardStatusPill.js.map +1 -0
  13. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +60 -60
  14. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +21 -21
  15. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +30 -30
  16. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +36 -36
  17. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +34 -34
  18. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +38 -38
  19. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  20. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +121 -121
  21. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  22. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +22 -22
  23. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +46 -46
  24. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +53 -53
  25. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -1
  26. package/dist/bigconsole/components/dashboard/WidgetPalette.js +47 -47
  27. package/dist/bigconsole/components/dashboard/index.js +1 -0
  28. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +35 -35
  29. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +18 -18
  30. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +20 -20
  31. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +30 -29
  32. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
  33. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +48 -48
  34. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +126 -114
  35. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  36. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +35 -35
  37. package/dist/bigconsole/components/overview/DashboardGuide.js +214 -0
  38. package/dist/bigconsole/components/overview/DashboardGuide.js.map +1 -0
  39. package/dist/bigconsole/components/overview/DataHealthCard.js +97 -0
  40. package/dist/bigconsole/components/overview/DataHealthCard.js.map +1 -0
  41. package/dist/bigconsole/components/overview/OverviewQuickActions.js +32 -0
  42. package/dist/bigconsole/components/overview/OverviewQuickActions.js.map +1 -0
  43. package/dist/bigconsole/components/overview/OverviewStatCard.js +57 -0
  44. package/dist/bigconsole/components/overview/OverviewStatCard.js.map +1 -0
  45. package/dist/bigconsole/components/overview/RecentDashboardsPanel.js +107 -0
  46. package/dist/bigconsole/components/overview/RecentDashboardsPanel.js.map +1 -0
  47. package/dist/bigconsole/components/overview/dashboardGuideSteps.js +119 -0
  48. package/dist/bigconsole/components/overview/dashboardGuideSteps.js.map +1 -0
  49. package/dist/bigconsole/components/overview/index.js +8 -0
  50. package/dist/bigconsole/components/overview/overviewModel.js +119 -0
  51. package/dist/bigconsole/components/overview/overviewModel.js.map +1 -0
  52. package/dist/bigconsole/components/overview/useOverviewData.js +48 -0
  53. package/dist/bigconsole/components/overview/useOverviewData.js.map +1 -0
  54. package/dist/bigconsole/components/parser/DataSinkSelector.js +40 -40
  55. package/dist/bigconsole/components/parser/ImportParserDialog.js +127 -127
  56. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  57. package/dist/bigconsole/components/parser/ParserSelector.js +51 -51
  58. package/dist/bigconsole/components/preview/AiPreviewContent.js +5 -5
  59. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +32 -32
  60. package/dist/bigconsole/components/preview/AiPreviewPanel.js +37 -37
  61. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +13 -13
  62. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +70 -70
  63. package/dist/bigconsole/components/widgets/PropertiesPanel.js +28 -28
  64. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +25 -25
  65. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +48 -48
  66. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +46 -46
  67. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +61 -61
  68. package/dist/bigconsole/components/widgets/form/FormWidget.js +36 -36
  69. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +42 -42
  70. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +25 -25
  71. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +21 -21
  72. package/dist/bigconsole/components/widgets/list/ListConfig.js +30 -30
  73. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +38 -38
  74. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +9 -9
  75. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +9 -9
  76. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +49 -49
  77. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +39 -39
  78. package/dist/bigconsole/components/widgets/table/TableConfig.js +73 -73
  79. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +64 -64
  80. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +10 -10
  81. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +68 -68
  82. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  83. package/dist/bigconsole/hooks/useDataSinkOperations.js +92 -89
  84. package/dist/bigconsole/hooks/useDataSinkOperations.js.map +1 -1
  85. package/dist/bigconsole/hooks/useImportDataSink.js +96 -91
  86. package/dist/bigconsole/hooks/useImportDataSink.js.map +1 -1
  87. package/dist/bigconsole/pages/AdminPage.js +136 -136
  88. package/dist/bigconsole/pages/DashboardBuilderPage.js +10 -10
  89. package/dist/bigconsole/pages/DashboardViewPage.js +61 -61
  90. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  91. package/dist/bigconsole/pages/DashboardsPage.js +327 -348
  92. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  93. package/dist/bigconsole/pages/DataParsersPage.js +5 -5
  94. package/dist/bigconsole/pages/DataSinkBuilderPage.js +82 -80
  95. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  96. package/dist/bigconsole/pages/DataSinkViewPage.js +83 -83
  97. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  98. package/dist/bigconsole/pages/DataSinksPage.js +11 -11
  99. package/dist/bigconsole/pages/DataSourcesPage.js +5 -5
  100. package/dist/bigconsole/pages/InsightsPage.js +315 -315
  101. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  102. package/dist/bigconsole/pages/OverviewPage.js +244 -0
  103. package/dist/bigconsole/pages/OverviewPage.js.map +1 -0
  104. package/dist/bigconsole/pages/ParserBuilderPage.js +5 -5
  105. package/dist/bigconsole/pages/ParserViewPage.js +98 -98
  106. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  107. package/dist/bigconsole/pages/PipelineBuilderPage.js +8 -8
  108. package/dist/bigconsole/pages/PipelineViewPage.js +46 -46
  109. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  110. package/dist/bigconsole/pages/PipelinesPage.js +80 -80
  111. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  112. package/dist/bigconsole/pages/SettingsPage.js +70 -70
  113. package/dist/bigconsole/pages/WidgetDemoPage.js +42 -42
  114. package/dist/bigconsole/pages/WorkflowViewPage.js +200 -200
  115. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  116. package/dist/bigconsole/pages/WorkflowsPage.js +78 -78
  117. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  118. package/dist/bigconsole/providers/BigConsoleQuotaProvider.js +36 -35
  119. package/dist/bigconsole/providers/BigConsoleQuotaProvider.js.map +1 -1
  120. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +34 -34
  121. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +79 -79
  122. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +46 -46
  123. package/dist/bigconsole/utils/createDialogParam.js +14 -0
  124. package/dist/bigconsole/utils/createDialogParam.js.map +1 -0
  125. package/dist/bigconsole/utils/quota.js +51 -23
  126. package/dist/bigconsole/utils/quota.js.map +1 -1
  127. package/dist/generated/global-operations.js +1 -1
  128. package/dist/generated/wspace-operations.js +285 -222
  129. package/dist/generated/wspace-operations.js.map +1 -1
  130. package/dist/shared/hooks/useTr.js +10 -7
  131. package/dist/shared/hooks/useTr.js.map +1 -1
  132. package/package.json +1 -1
  133. package/dist/bigconsole/pages/HomePage.js +0 -318
  134. package/dist/bigconsole/pages/HomePage.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"CreateDashboardDialog.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/CreateDashboardDialog.tsx"],"sourcesContent":["/**\n * CreateDashboardDialog Component\n *\n * Modal dialog for creating a new dashboard with name and description.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n * Phase 2: Added TemplatePicker integration for creating from templates.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef, type KeyboardEvent } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Textarea } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Plus, LayoutDashboard, Copy, X, Tag } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { StoreTemplatePicker } from './StoreTemplatePicker';\nimport { Section } from '../common';\nimport { useStoreDashboardTemplates, type StoreDashboardTemplate } from '../../hooks/useStoreDashboardTemplates';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CreateDashboardDialogProps {\n isOpen: boolean;\n isCreating?: boolean;\n onClose: () => void;\n onCreate: (data: {\n name: string;\n description: string;\n category: string;\n tags?: string[];\n templateId?: string;\n }) => void | Promise<void>;\n /** Whether to show the template picker option */\n showTemplates?: boolean;\n /**\n * Called after a store template has been installed. Receives the new\n * dashboard id and how many widgets still need a data source, so the host can\n * navigate and surface the \"connect your data\" prompts.\n */\n onTemplateInstalled?: (result: { dashboardId: string; widgetsNeedingData: number }) => void;\n}\n\ntype CreateMode = 'blank' | 'template';\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const CreateDashboardDialog: FC<CreateDashboardDialogProps> = memo(function CreateDashboardDialog({\n isOpen,\n isCreating = false,\n onClose,\n onCreate,\n showTemplates = true,\n onTemplateInstalled,\n}) {\n const { t } = useI18n();\n const {\n templates,\n loading: templatesLoading,\n error: templatesError,\n fetchTemplateContent,\n installTemplate,\n } = useStoreDashboardTemplates({ autoLoad: showTemplates });\n const [installing, setInstalling] = useState(false);\n const [mode, setMode] = useState<CreateMode>('blank');\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [tags, setTags] = useState<string[]>([]);\n const [tagInput, setTagInput] = useState('');\n const [selectedTemplate, setSelectedTemplate] = useState<StoreDashboardTemplate | null>(null);\n const [error, setError] = useState<string | null>(null);\n const nameInputRef = useRef<HTMLInputElement>(null);\n\n // Reset form when dialog opens\n useEffect(() => {\n if (isOpen) {\n setMode('blank');\n setName('');\n setDescription('');\n setTags([]);\n setTagInput('');\n setSelectedTemplate(null);\n setError(null);\n setTimeout(() => {\n nameInputRef.current?.focus();\n }, 100);\n }\n }, [isOpen]);\n\n // Handle adding a tag\n const handleAddTag = useCallback(() => {\n const trimmedTag = tagInput.trim().toLowerCase();\n if (trimmedTag && !tags.includes(trimmedTag) && tags.length < 10) {\n setTags((prev) => [...prev, trimmedTag]);\n setTagInput('');\n }\n }, [tagInput, tags]);\n\n // Handle removing a tag\n const handleRemoveTag = useCallback((tagToRemove: string) => {\n setTags((prev) => prev.filter((tag) => tag !== tagToRemove));\n }, []);\n\n // Handle tag input key press\n const handleTagKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n } else if (e.key === 'Backspace' && !tagInput && tags.length > 0) {\n // Remove last tag when backspace is pressed on empty input\n setTags((prev) => prev.slice(0, -1));\n }\n },\n [handleAddTag, tagInput, tags.length]\n );\n\n // Handle template selection\n const handleTemplateSelect = useCallback((template: StoreDashboardTemplate) => {\n setSelectedTemplate(template);\n // Pre-fill name and description from template\n setName(template.name);\n setDescription(template.description || '');\n }, []);\n\n // Handle form submission\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n // For template mode without selection, show error\n if (mode === 'template' && !selectedTemplate) {\n setError(t('bigconsole.dashboards.createDialog.error.selectTemplate', 'Please select a template'));\n return;\n }\n\n const trimmedName = name.trim();\n if (!trimmedName) {\n setError(t('bigconsole.dashboards.createDialog.error.nameRequired', 'Dashboard name is required'));\n nameInputRef.current?.focus();\n return;\n }\n\n if (trimmedName.length < 3) {\n setError(\n t('bigconsole.dashboards.createDialog.error.nameTooShort', 'Dashboard name must be at least 3 characters')\n );\n nameInputRef.current?.focus();\n return;\n }\n\n if (trimmedName.length > 100) {\n setError(\n t('bigconsole.dashboards.createDialog.error.nameTooLong', 'Dashboard name must be less than 100 characters')\n );\n nameInputRef.current?.focus();\n return;\n }\n\n setError(null);\n\n // Store templates are installed here rather than through onCreate: the\n // install carries data-sink bindings and returns which slots are still\n // unconnected, neither of which the plain create path models.\n if (mode === 'template' && selectedTemplate) {\n setInstalling(true);\n try {\n const content = await fetchTemplateContent(selectedTemplate.id);\n if (!content) {\n setError(\n t(\n 'bigconsole.dashboards.createDialog.error.noDefinition',\n 'This template has no dashboard definition attached and cannot be installed.'\n )\n );\n return;\n }\n\n const result = await installTemplate({\n templateId: selectedTemplate.id,\n templateName: selectedTemplate.name,\n content,\n name: trimmedName,\n });\n\n if (!result.success) {\n setError(\n result.errorMessage ??\n t('bigconsole.dashboards.createDialog.error.installFailed', 'Failed to create dashboard from template.')\n );\n return;\n }\n\n if (result.dashboardId) {\n onTemplateInstalled?.({\n dashboardId: result.dashboardId,\n widgetsNeedingData: result.widgetsNeedingData,\n });\n }\n onClose();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : t('bigconsole.dashboards.createDialog.error.installFailed', 'Failed to create dashboard from template.')\n );\n } finally {\n setInstalling(false);\n }\n return;\n }\n\n try {\n await onCreate({\n name: trimmedName,\n description: description.trim(),\n category: 'CUSTOM',\n tags: tags.length > 0 ? tags : undefined,\n });\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : t(\n 'bigconsole.dashboards.createDialog.error.createFailed',\n 'Failed to create dashboard. Please try again.'\n )\n );\n }\n },\n [\n name,\n description,\n tags,\n mode,\n selectedTemplate,\n onCreate,\n onClose,\n fetchTemplateContent,\n installTemplate,\n onTemplateInstalled,\n t,\n ]\n );\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && !isCreating && onClose()}>\n <DialogContent style={{ maxWidth: mode === 'template' ? '900px' : '480px', width: '100%', padding: 0 }}>\n {/* Header */}\n <DialogHeader style={{ padding: 'var(--space-pagePadding) var(--space-pagePadding) 0' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-bg-accentSubtle)',\n }}\n >\n <LayoutDashboard\n aria-hidden=\"true\"\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-bg)',\n }}\n />\n </div>\n <div>\n <DialogTitle\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n color: 'var(--color-text-primary)',\n margin: 0,\n }}\n >\n {t('bigconsole.dashboards.createDialog.title', 'Create New Dashboard')}\n </DialogTitle>\n <DialogDescription\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n margin: 'var(--space-controlGap) 0 0 0',\n }}\n >\n {t('bigconsole.dashboards.createDialog.subtitle', 'Create a new dashboard to visualize your data')}\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <form onSubmit={handleSubmit}>\n {/* Mode Selection Tabs */}\n {showTemplates && (\n <div style={{ padding: 'var(--space-pagePadding) var(--space-pagePadding) 0' }}>\n <div\n role=\"group\"\n aria-label=\"How to start\"\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n <button\n type=\"button\"\n onClick={() => {\n setMode('blank');\n setSelectedTemplate(null);\n }}\n style={{\n flex: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n backgroundColor: mode === 'blank' ? 'var(--color-bg-surface)' : 'transparent',\n color: mode === 'blank' ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n fontWeight: mode === 'blank' ? 'var(--font-weight-semibold)' : 'var(--font-weight-regular)',\n fontSize: 'var(--font-size-body-sm)',\n cursor: 'pointer',\n boxShadow: mode === 'blank' ? 'var(--shadow-elevation-1)' : 'none',\n transition: 'all 0.15s ease',\n }}\n >\n <Plus style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.tab.blank', 'Blank Dashboard')}\n </button>\n <button\n type=\"button\"\n onClick={() => setMode('template')}\n style={{\n flex: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n backgroundColor: mode === 'template' ? 'var(--color-bg-surface)' : 'transparent',\n color: mode === 'template' ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n fontWeight: mode === 'template' ? 'var(--font-weight-semibold)' : 'var(--font-weight-regular)',\n fontSize: 'var(--font-size-body-sm)',\n cursor: 'pointer',\n boxShadow: mode === 'template' ? 'var(--shadow-elevation-1)' : 'none',\n transition: 'all 0.15s ease',\n }}\n >\n <Copy style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.tab.template', 'From Template')}\n </button>\n </div>\n </div>\n )}\n\n {/* Template Picker (when in template mode) */}\n {mode === 'template' && (\n <div style={{ padding: 'var(--space-pagePadding)', maxHeight: '400px', overflowY: 'auto' }}>\n <StoreTemplatePicker\n templates={templates}\n loading={templatesLoading}\n error={templatesError}\n selectedTemplateId={selectedTemplate?.id}\n onSelect={handleTemplateSelect}\n />\n </div>\n )}\n\n {/* Form Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n {/*\n The fields carry no surface of their own — the dialog is already a\n raised surface — but they still need a name, so the group is a `bare`\n section. It gives the form a heading screen readers can land on and\n tells the eye where the template picker ends and the form begins.\n */}\n <Section\n headingLevel={3}\n emphasis=\"bare\"\n padding=\"none\"\n title=\"Dashboard details\"\n description=\"Name it now — everything else can change later.\"\n data-testid=\"create-dashboard-details\"\n >\n {/* Name Field */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label\n htmlFor=\"dashboard-name\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.name', 'Dashboard Name')}\n <span style={{ color: 'var(--color-status-error-text)', marginLeft: 'var(--space-controlGap)' }}>\n *\n </span>\n </label>\n <Input\n ref={nameInputRef}\n id=\"dashboard-name\"\n type=\"text\"\n value={name}\n onChange={(e) => {\n setName(e.target.value);\n if (error) setError(null);\n }}\n placeholder={t('bigconsole.dashboards.createDialog.field.namePlaceholder', 'Enter dashboard name')}\n disabled={isCreating || installing}\n style={{\n height: 'var(--size-controlHeight-md)',\n fontSize: 'var(--font-size-body-sm)',\n borderColor: error ? 'var(--color-status-error-border)' : undefined,\n }}\n />\n {error && (\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n marginTop: 'var(--space-controlGap)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n {error}\n </p>\n )}\n </div>\n\n {/* Description Field */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label\n htmlFor=\"dashboard-description\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.description', 'Description')}\n <span\n style={{\n color: 'var(--color-text-muted)',\n fontWeight: 'var(--font-weight-regular)',\n marginLeft: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.optional', '(optional)')}\n </span>\n </label>\n <Textarea\n id=\"dashboard-description\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\n 'bigconsole.dashboards.createDialog.field.descriptionPlaceholder',\n 'Enter a brief description for this dashboard'\n )}\n rows={3}\n disabled={isCreating || installing}\n style={{\n fontSize: 'var(--font-size-body-sm)',\n resize: 'none',\n }}\n />\n </div>\n\n {/* Tags Field */}\n <div>\n <label\n htmlFor=\"dashboard-tags\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n <Tag style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.field.tags', 'Tags')}\n <span\n style={{\n color: 'var(--color-text-muted)',\n fontWeight: 'var(--font-weight-regular)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.tagsOptional', '(optional, max 10)')}\n </span>\n </label>\n {/* Tag chips display */}\n {tags.length > 0 && (\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: 'var(--space-controlGap)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {tags.map((tag) => (\n <Badge\n key={tag}\n variant=\"secondary\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n paddingRight: '4px',\n }}\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => handleRemoveTag(tag)}\n disabled={isCreating || installing}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n padding: '2px',\n borderRadius: '50%',\n color: 'inherit',\n opacity: 0.7,\n }}\n onMouseOver={(e) => (e.currentTarget.style.opacity = '1')}\n onMouseOut={(e) => (e.currentTarget.style.opacity = '0.7')}\n >\n <X style={{ height: '12px', width: '12px' }} />\n </button>\n </Badge>\n ))}\n </div>\n )}\n {/* Tag input */}\n <div style={{ display: 'flex', gap: 'var(--space-controlGap)' }}>\n <Input\n id=\"dashboard-tags\"\n type=\"text\"\n value={tagInput}\n onChange={(e) => setTagInput(e.target.value)}\n onKeyDown={handleTagKeyDown}\n placeholder={\n tags.length >= 10\n ? t('bigconsole.dashboards.createDialog.field.tagsMaxReached', 'Max tags reached')\n : t(\n 'bigconsole.dashboards.createDialog.field.tagsInputPlaceholder',\n 'Type a tag and press Enter'\n )\n }\n disabled={isCreating || installing || tags.length >= 10}\n style={{\n flex: 1,\n height: 'var(--size-controlHeight-md)',\n fontSize: 'var(--font-size-body-sm)',\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleAddTag}\n disabled={isCreating || installing || !tagInput.trim() || tags.length >= 10}\n style={{ height: 'var(--size-controlHeight-md)' }}\n >\n {t('bigconsole.dashboards.createDialog.action.addTag', 'Add')}\n </Button>\n </div>\n <p\n style={{\n // `--font-size-body-xs` is not a real token — the declaration is\n // dropped and the hint inherits body size. `--font-size-xs` is.\n fontSize: 'var(--font-size-xs)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.tagsHelp', 'Press Enter to add a tag, or click Add')}\n </p>\n </div>\n </Section>\n </div>\n\n {/* Footer */}\n <DialogFooter\n style={{\n padding: 'var(--space-formGap) var(--space-pagePadding)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 'var(--space-controlGap)',\n }}\n >\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n disabled={isCreating || installing}\n style={{ height: 'var(--size-controlHeight-md)' }}\n >\n {t('bigconsole.dashboards.createDialog.action.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"submit\"\n disabled={isCreating || installing || !name.trim()}\n style={{\n height: 'var(--size-controlHeight-md)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n {isCreating || installing ? (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Spinner style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.action.creating', 'Creating...')}\n </span>\n ) : (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Plus style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.action.create', 'Create Dashboard')}\n </span>\n )}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default CreateDashboardDialog;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CreateDashboardDialog.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/CreateDashboardDialog.tsx"],"sourcesContent":["/**\n * CreateDashboardDialog Component\n *\n * Modal dialog for creating a new dashboard with name and description.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n * Phase 2: Added TemplatePicker integration for creating from templates.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef, type KeyboardEvent } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Textarea } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Plus, LayoutDashboard, Copy, X, Tag } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { StoreTemplatePicker } from './StoreTemplatePicker';\nimport { Section } from '../common';\nimport { useStoreDashboardTemplates, type StoreDashboardTemplate } from '../../hooks/useStoreDashboardTemplates';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CreateDashboardDialogProps {\n isOpen: boolean;\n isCreating?: boolean;\n onClose: () => void;\n onCreate: (data: {\n name: string;\n description: string;\n category: string;\n tags?: string[];\n templateId?: string;\n }) => void | Promise<void>;\n /** Whether to show the template picker option */\n showTemplates?: boolean;\n /**\n * Called after a store template has been installed. Receives the new\n * dashboard id and how many widgets still need a data source, so the host can\n * navigate and surface the \"connect your data\" prompts.\n */\n onTemplateInstalled?: (result: { dashboardId: string; widgetsNeedingData: number }) => void;\n}\n\ntype CreateMode = 'blank' | 'template';\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const CreateDashboardDialog: FC<CreateDashboardDialogProps> = memo(function CreateDashboardDialog({\n isOpen,\n isCreating = false,\n onClose,\n onCreate,\n showTemplates = true,\n onTemplateInstalled,\n}) {\n const { t } = useI18n();\n const {\n templates,\n loading: templatesLoading,\n error: templatesError,\n fetchTemplateContent,\n installTemplate,\n } = useStoreDashboardTemplates({ autoLoad: showTemplates });\n const [installing, setInstalling] = useState(false);\n const [mode, setMode] = useState<CreateMode>('blank');\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [tags, setTags] = useState<string[]>([]);\n const [tagInput, setTagInput] = useState('');\n const [selectedTemplate, setSelectedTemplate] = useState<StoreDashboardTemplate | null>(null);\n const [error, setError] = useState<string | null>(null);\n const nameInputRef = useRef<HTMLInputElement>(null);\n\n // Reset form when dialog opens\n useEffect(() => {\n if (isOpen) {\n setMode('blank');\n setName('');\n setDescription('');\n setTags([]);\n setTagInput('');\n setSelectedTemplate(null);\n setError(null);\n setTimeout(() => {\n nameInputRef.current?.focus();\n }, 100);\n }\n }, [isOpen]);\n\n // Handle adding a tag\n const handleAddTag = useCallback(() => {\n const trimmedTag = tagInput.trim().toLowerCase();\n if (trimmedTag && !tags.includes(trimmedTag) && tags.length < 10) {\n setTags((prev) => [...prev, trimmedTag]);\n setTagInput('');\n }\n }, [tagInput, tags]);\n\n // Handle removing a tag\n const handleRemoveTag = useCallback((tagToRemove: string) => {\n setTags((prev) => prev.filter((tag) => tag !== tagToRemove));\n }, []);\n\n // Handle tag input key press\n const handleTagKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n } else if (e.key === 'Backspace' && !tagInput && tags.length > 0) {\n // Remove last tag when backspace is pressed on empty input\n setTags((prev) => prev.slice(0, -1));\n }\n },\n [handleAddTag, tagInput, tags.length]\n );\n\n // Handle template selection\n const handleTemplateSelect = useCallback((template: StoreDashboardTemplate) => {\n setSelectedTemplate(template);\n // Pre-fill name and description from template\n setName(template.name);\n setDescription(template.description || '');\n }, []);\n\n // Handle form submission\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n // For template mode without selection, show error\n if (mode === 'template' && !selectedTemplate) {\n setError(t('bigconsole.dashboards.createDialog.error.selectTemplate', 'Please select a template'));\n return;\n }\n\n const trimmedName = name.trim();\n if (!trimmedName) {\n setError(t('bigconsole.dashboards.createDialog.error.nameRequired', 'Dashboard name is required'));\n nameInputRef.current?.focus();\n return;\n }\n\n if (trimmedName.length < 3) {\n setError(\n t('bigconsole.dashboards.createDialog.error.nameTooShort', 'Dashboard name must be at least 3 characters')\n );\n nameInputRef.current?.focus();\n return;\n }\n\n if (trimmedName.length > 100) {\n setError(\n t('bigconsole.dashboards.createDialog.error.nameTooLong', 'Dashboard name must be less than 100 characters')\n );\n nameInputRef.current?.focus();\n return;\n }\n\n setError(null);\n\n // Store templates are installed here rather than through onCreate: the\n // install carries data-sink bindings and returns which slots are still\n // unconnected, neither of which the plain create path models.\n if (mode === 'template' && selectedTemplate) {\n setInstalling(true);\n try {\n const content = await fetchTemplateContent(selectedTemplate.id);\n if (!content) {\n setError(\n t(\n 'bigconsole.dashboards.createDialog.error.noDefinition',\n 'This template has no dashboard definition attached and cannot be installed.'\n )\n );\n return;\n }\n\n const result = await installTemplate({\n templateId: selectedTemplate.id,\n templateName: selectedTemplate.name,\n content,\n name: trimmedName,\n });\n\n if (!result.success) {\n setError(\n result.errorMessage ??\n t('bigconsole.dashboards.createDialog.error.installFailed', 'Failed to create dashboard from template.')\n );\n return;\n }\n\n if (result.dashboardId) {\n onTemplateInstalled?.({\n dashboardId: result.dashboardId,\n widgetsNeedingData: result.widgetsNeedingData,\n });\n }\n onClose();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : t('bigconsole.dashboards.createDialog.error.installFailed', 'Failed to create dashboard from template.')\n );\n } finally {\n setInstalling(false);\n }\n return;\n }\n\n try {\n await onCreate({\n name: trimmedName,\n description: description.trim(),\n category: 'CUSTOM',\n tags: tags.length > 0 ? tags : undefined,\n });\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : t(\n 'bigconsole.dashboards.createDialog.error.createFailed',\n 'Failed to create dashboard. Please try again.'\n )\n );\n }\n },\n [\n name,\n description,\n tags,\n mode,\n selectedTemplate,\n onCreate,\n onClose,\n fetchTemplateContent,\n installTemplate,\n onTemplateInstalled,\n t,\n ]\n );\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && !isCreating && onClose()}>\n <DialogContent style={{ maxWidth: mode === 'template' ? '900px' : '480px', width: '100%', padding: 0 }}>\n {/* Header */}\n <DialogHeader style={{ padding: 'var(--space-pagePadding) var(--space-pagePadding) 0' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-bg-accentSubtle)',\n }}\n >\n <LayoutDashboard\n aria-hidden=\"true\"\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-bg)',\n }}\n />\n </div>\n <div>\n <DialogTitle\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n color: 'var(--color-text-primary)',\n margin: 0,\n }}\n >\n {t('bigconsole.dashboards.createDialog.title', 'Create New Dashboard')}\n </DialogTitle>\n <DialogDescription\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n margin: 'var(--space-controlGap) 0 0 0',\n }}\n >\n {t('bigconsole.dashboards.createDialog.subtitle', 'Create a new dashboard to visualize your data')}\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <form onSubmit={handleSubmit}>\n {/* Mode Selection Tabs */}\n {showTemplates && (\n <div style={{ padding: 'var(--space-pagePadding) var(--space-pagePadding) 0' }}>\n <div\n role=\"group\"\n aria-label=\"How to start\"\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n <button\n type=\"button\"\n onClick={() => {\n setMode('blank');\n setSelectedTemplate(null);\n }}\n style={{\n flex: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n backgroundColor: mode === 'blank' ? 'var(--color-bg-surface)' : 'transparent',\n color: mode === 'blank' ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n fontWeight: mode === 'blank' ? 'var(--font-weight-semibold)' : 'var(--font-weight-regular)',\n fontSize: 'var(--font-size-body-sm)',\n cursor: 'pointer',\n boxShadow: mode === 'blank' ? 'var(--shadow-elevation-1)' : 'none',\n transition: 'all 0.15s ease',\n }}\n >\n <Plus style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.tab.blank', 'Blank Dashboard')}\n </button>\n <button\n type=\"button\"\n onClick={() => setMode('template')}\n style={{\n flex: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n backgroundColor: mode === 'template' ? 'var(--color-bg-surface)' : 'transparent',\n color: mode === 'template' ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n fontWeight: mode === 'template' ? 'var(--font-weight-semibold)' : 'var(--font-weight-regular)',\n fontSize: 'var(--font-size-body-sm)',\n cursor: 'pointer',\n boxShadow: mode === 'template' ? 'var(--shadow-elevation-1)' : 'none',\n transition: 'all 0.15s ease',\n }}\n >\n <Copy style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.tab.template', 'From Template')}\n </button>\n </div>\n </div>\n )}\n\n {/* Template Picker (when in template mode) */}\n {mode === 'template' && (\n <div style={{ padding: 'var(--space-pagePadding)', maxHeight: '400px', overflowY: 'auto' }}>\n <StoreTemplatePicker\n templates={templates}\n loading={templatesLoading}\n error={templatesError}\n selectedTemplateId={selectedTemplate?.id}\n onSelect={handleTemplateSelect}\n />\n </div>\n )}\n\n {/* Form Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n {/*\n The fields carry no surface of their own — the dialog is already a\n raised surface — but they still need a name, so the group is a `bare`\n section. It gives the form a heading screen readers can land on and\n tells the eye where the template picker ends and the form begins.\n */}\n <Section\n headingLevel={3}\n emphasis=\"bare\"\n padding=\"none\"\n title=\"Dashboard details\"\n description=\"Name it now — everything else can change later.\"\n data-testid=\"create-dashboard-details\"\n >\n {/* Name Field */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label\n htmlFor=\"dashboard-name\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.name', 'Dashboard Name')}\n <span style={{ color: 'var(--color-status-error-text)', marginLeft: 'var(--space-controlGap)' }}>\n *\n </span>\n </label>\n <Input\n ref={nameInputRef}\n id=\"dashboard-name\"\n type=\"text\"\n value={name}\n onChange={(e) => {\n setName(e.target.value);\n if (error) setError(null);\n }}\n placeholder={t('bigconsole.dashboards.createDialog.field.namePlaceholder', 'Enter dashboard name')}\n disabled={isCreating || installing}\n style={{\n height: 'var(--size-controlHeight-md)',\n fontSize: 'var(--font-size-body-sm)',\n borderColor: error ? 'var(--color-status-error-border)' : undefined,\n }}\n />\n {error && (\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n marginTop: 'var(--space-controlGap)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n {error}\n </p>\n )}\n </div>\n\n {/* Description Field */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <label\n htmlFor=\"dashboard-description\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.description', 'Description')}\n <span\n style={{\n color: 'var(--color-text-muted)',\n fontWeight: 'var(--font-weight-regular)',\n marginLeft: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.optional', '(optional)')}\n </span>\n </label>\n <Textarea\n id=\"dashboard-description\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\n 'bigconsole.dashboards.createDialog.field.descriptionPlaceholder',\n 'Enter a brief description for this dashboard'\n )}\n rows={3}\n disabled={isCreating || installing}\n style={{\n fontSize: 'var(--font-size-body-sm)',\n resize: 'none',\n }}\n />\n </div>\n\n {/* Tags Field */}\n <div>\n <label\n htmlFor=\"dashboard-tags\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n <Tag style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.field.tags', 'Tags')}\n <span\n style={{\n color: 'var(--color-text-muted)',\n fontWeight: 'var(--font-weight-regular)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.tagsOptional', '(optional, max 10)')}\n </span>\n </label>\n {/* Tag chips display */}\n {tags.length > 0 && (\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: 'var(--space-controlGap)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {tags.map((tag) => (\n <Badge\n key={tag}\n variant=\"secondary\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n paddingRight: '4px',\n }}\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => handleRemoveTag(tag)}\n disabled={isCreating || installing}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n padding: '2px',\n borderRadius: '50%',\n color: 'inherit',\n opacity: 0.7,\n }}\n onMouseOver={(e) => (e.currentTarget.style.opacity = '1')}\n onMouseOut={(e) => (e.currentTarget.style.opacity = '0.7')}\n >\n <X style={{ height: '12px', width: '12px' }} />\n </button>\n </Badge>\n ))}\n </div>\n )}\n {/* Tag input */}\n <div style={{ display: 'flex', gap: 'var(--space-controlGap)' }}>\n <Input\n id=\"dashboard-tags\"\n type=\"text\"\n value={tagInput}\n onChange={(e) => setTagInput(e.target.value)}\n onKeyDown={handleTagKeyDown}\n placeholder={\n tags.length >= 10\n ? t('bigconsole.dashboards.createDialog.field.tagsMaxReached', 'Max tags reached')\n : t(\n 'bigconsole.dashboards.createDialog.field.tagsInputPlaceholder',\n 'Type a tag and press Enter'\n )\n }\n disabled={isCreating || installing || tags.length >= 10}\n style={{\n flex: 1,\n height: 'var(--size-controlHeight-md)',\n fontSize: 'var(--font-size-body-sm)',\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleAddTag}\n disabled={isCreating || installing || !tagInput.trim() || tags.length >= 10}\n style={{ height: 'var(--size-controlHeight-md)' }}\n >\n {t('bigconsole.dashboards.createDialog.action.addTag', 'Add')}\n </Button>\n </div>\n <p\n style={{\n // `--font-size-body-xs` is not a real token — the declaration is\n // dropped and the hint inherits body size. `--font-size-xs` is.\n fontSize: 'var(--font-size-xs)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.createDialog.field.tagsHelp', 'Press Enter to add a tag, or click Add')}\n </p>\n </div>\n </Section>\n </div>\n\n {/* Footer */}\n <DialogFooter\n style={{\n padding: 'var(--space-formGap) var(--space-pagePadding)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 'var(--space-controlGap)',\n }}\n >\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n disabled={isCreating || installing}\n style={{ height: 'var(--size-controlHeight-md)' }}\n >\n {t('bigconsole.dashboards.createDialog.action.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"submit\"\n disabled={isCreating || installing || !name.trim()}\n style={{\n height: 'var(--size-controlHeight-md)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n {isCreating || installing ? (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Spinner style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.action.creating', 'Creating...')}\n </span>\n ) : (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Plus style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n {t('bigconsole.dashboards.createDialog.action.create', 'Create Dashboard')}\n </span>\n )}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default CreateDashboardDialog;\n"],"mappings":"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"}
@@ -3,10 +3,10 @@ import { useDashboardStore as t } from "../../store/dashboardStore.js";
3
3
  import "../../store/index.js";
4
4
  import { CrossFilterProvider as n } from "../../contexts/CrossFilterContext.js";
5
5
  import "../../contexts/index.js";
6
- import { Section as r } from "../common/Section.js";
7
- import "../common/index.js";
8
- import { useBigConsole as i } from "../../context/BigConsoleContext.js";
6
+ import { useBigConsole as r } from "../../context/BigConsoleContext.js";
9
7
  import "../../context/index.js";
8
+ import { Section as i } from "../common/Section.js";
9
+ import "../common/index.js";
10
10
  import { getWidgetDefinition as a } from "../widgets/WidgetRegistry.js";
11
11
  import o from "../../hooks/useWidgetCatalog.js";
12
12
  import s from "../../hooks/useWidgetOperations.js";
@@ -31,9 +31,9 @@ import "../builder/index.js";
31
31
  import { memo as f, useCallback as p, useEffect as de, useMemo as fe, useRef as m, useState as h } from "react";
32
32
  import { usePermissions as pe } from "@burdenoff/fe-libs/shared/providers/shell";
33
33
  import { Plus as me } from "lucide-react";
34
- import { useI18n as he } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
35
34
  import { Button as g } from "@burdenoff/fe-libs/ui";
36
35
  import { jsx as _, jsxs as v } from "react/jsx-runtime";
36
+ import { useI18n as he } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
37
37
  //#region src/bigconsole/components/dashboard/DashboardCanvas.tsx
38
38
  var y = f(function({ dashboardId: f, pageId: y, title: b, onPaste: ge, onSave: _e, isSaving: ve = !1, onExport: ye, onPublishTemplate: be, pages: x = [], activePageId: xe, onPageChange: Se, onPagesReorder: S, onPageAdd: Ce, onPageRename: we, onPageDuplicate: Te, onPageDelete: Ee, showFilters: De = !0, showPageTabs: Oe = !0, enableCrossFilter: ke = !0 }) {
39
39
  let { t: C } = he(), w = m(null), T = m(null), [E, Ae] = h(1200), [je, D] = h(!1), [O, k] = h(null), [A, j] = h(!1), [Me, M] = h(null), [N, Ne] = h(null), P = t((e) => e.viewMode === "edit"), F = t((e) => e.currentDashboard), { updateDashboard: I } = c({ skipFetch: !0 }), { hasPermission: Pe } = pe(), Fe = Pe(u.DASHBOARD_UPDATE), Ie = N?.id === f ? N.value : F?.id === f ? F.visibility : void 0, Le = p(async (e) => {
@@ -46,7 +46,7 @@ var y = f(function({ dashboardId: f, pageId: y, title: b, onPaste: ge, onSave: _
46
46
  id: f,
47
47
  value: t.visibility ?? e
48
48
  });
49
- }, [f, I]), { workspaceId: L, apiGatewayUrl: R, authToken: z } = i(), { installedWidgets: Re, loading: ze } = d({
49
+ }, [f, I]), { workspaceId: L, apiGatewayUrl: R, authToken: z } = r(), { installedWidgets: Re, loading: ze } = d({
50
50
  workspaceId: L,
51
51
  apiGatewayUrl: R,
52
52
  authToken: z,
@@ -246,7 +246,7 @@ var y = f(function({ dashboardId: f, pageId: y, title: b, onPaste: ge, onSave: _
246
246
  O && /* @__PURE__ */ _("div", {
247
247
  role: "alert",
248
248
  className: "mx-card-padding mt-control-gap flex-shrink-0",
249
- children: /* @__PURE__ */ _(r, {
249
+ children: /* @__PURE__ */ _(i, {
250
250
  tone: "danger",
251
251
  padding: "compact",
252
252
  headingLevel: 3,
@@ -364,7 +364,7 @@ var y = f(function({ dashboardId: f, pageId: y, title: b, onPaste: ge, onSave: _
364
364
  })
365
365
  }) : /* @__PURE__ */ _("div", {
366
366
  className: "flex min-h-[min(400px,60vh)] items-center justify-center p-card-padding",
367
- children: /* @__PURE__ */ _(r, {
367
+ children: /* @__PURE__ */ _(i, {
368
368
  headingLevel: 3,
369
369
  className: "w-full max-w-md",
370
370
  "data-testid": "dashboard-empty-board",
@@ -0,0 +1,53 @@
1
+ import { useTr as e } from "../../../shared/hooks/useTr.js";
2
+ import { memo as t, useCallback as n } from "react";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
+ //#region src/bigconsole/components/dashboard/DashboardStatusPill.tsx
5
+ var a = {
6
+ PUBLISHED: "var(--color-status-success-bg)",
7
+ DRAFT: "var(--color-text-muted)",
8
+ ARCHIVED: "var(--color-status-warning-bg)"
9
+ };
10
+ function o() {
11
+ let t = e();
12
+ return n((e) => {
13
+ switch (e) {
14
+ case "PUBLISHED": return t("bigconsole.dashboards.status.published", "Published");
15
+ case "ARCHIVED": return t("bigconsole.dashboards.status.archived", "Archived");
16
+ default: return t("bigconsole.dashboards.status.draft", "Draft");
17
+ }
18
+ }, [t]);
19
+ }
20
+ var s = t(function({ status: e, label: t }) {
21
+ return /* @__PURE__ */ i("span", {
22
+ "data-testid": "dashboard-status",
23
+ style: {
24
+ display: "inline-flex",
25
+ alignItems: "center",
26
+ gap: "var(--space-iconGap)",
27
+ padding: "2px 8px",
28
+ borderRadius: "var(--radius-pill)",
29
+ backgroundColor: "var(--color-bg-sunken)",
30
+ border: "1px solid var(--color-border-subtle)",
31
+ fontSize: "10px",
32
+ fontWeight: "var(--font-weight-semibold)",
33
+ textTransform: "uppercase",
34
+ letterSpacing: "0.02em",
35
+ color: "var(--color-text-secondary)",
36
+ whiteSpace: "nowrap"
37
+ },
38
+ children: [/* @__PURE__ */ r("span", {
39
+ "aria-hidden": "true",
40
+ style: {
41
+ width: 6,
42
+ height: 6,
43
+ borderRadius: "50%",
44
+ backgroundColor: a[e],
45
+ flexShrink: 0
46
+ }
47
+ }), t]
48
+ });
49
+ });
50
+ //#endregion
51
+ export { s as default, o as useDashboardStatusLabel };
52
+
53
+ //# sourceMappingURL=DashboardStatusPill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardStatusPill.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/DashboardStatusPill.tsx"],"sourcesContent":["/**\n * DashboardStatusPill\n *\n * Compact lifecycle badge for a dashboard (Draft / Published / Archived).\n * Shared by the Dashboards list and the Overview's recent dashboards so the\n * same state always reads the same way.\n */\n\nimport { type FC, memo, useCallback } from 'react';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport type { DashboardListStatus } from '../../hooks/useDashboardOperations';\n\n/**\n * Lifecycle status of a dashboard.\n *\n * Backed by `Dashboard.status` (DashboardStatus: DRAFT | PUBLISHED | ARCHIVED).\n * Whether a board is a published surface or still a draft is the fact a list of\n * boards is most often scanned for.\n */\nconst DASHBOARD_STATUS_DOT: Record<DashboardListStatus, string> = {\n PUBLISHED: 'var(--color-status-success-bg)',\n DRAFT: 'var(--color-text-muted)',\n ARCHIVED: 'var(--color-status-warning-bg)',\n};\n\n/** Translated label for a dashboard lifecycle status. */\nexport function useDashboardStatusLabel(): (status: DashboardListStatus) => string {\n const tr = useTr();\n return useCallback(\n (status: DashboardListStatus) => {\n switch (status) {\n case 'PUBLISHED':\n return tr('bigconsole.dashboards.status.published', 'Published');\n case 'ARCHIVED':\n return tr('bigconsole.dashboards.status.archived', 'Archived');\n default:\n return tr('bigconsole.dashboards.status.draft', 'Draft');\n }\n },\n [tr]\n );\n}\n\nexport interface DashboardStatusPillProps {\n status: DashboardListStatus;\n label: string;\n}\n\nexport const DashboardStatusPill: FC<DashboardStatusPillProps> = memo(function DashboardStatusPill({ status, label }) {\n return (\n <span\n data-testid=\"dashboard-status\"\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: '2px 8px',\n borderRadius: 'var(--radius-pill)',\n backgroundColor: 'var(--color-bg-sunken)',\n border: '1px solid var(--color-border-subtle)',\n fontSize: '10px',\n fontWeight: 'var(--font-weight-semibold)',\n textTransform: 'uppercase',\n letterSpacing: '0.02em',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n <span\n aria-hidden=\"true\"\n style={{\n width: 6,\n height: 6,\n borderRadius: '50%',\n backgroundColor: DASHBOARD_STATUS_DOT[status],\n flexShrink: 0,\n }}\n />\n {label}\n </span>\n );\n});\n\nexport default DashboardStatusPill;\n"],"mappings":";;;;AAmBA,IAAM,IAA4D;CAChE,WAAW;CACX,OAAO;CACP,UAAU;CACX;AAGD,SAAgB,IAAmE;CACjF,IAAM,IAAK,GAAO;AAClB,QAAO,GACJ,MAAgC;AAC/B,UAAQ,GAAR;GACE,KAAK,YACH,QAAO,EAAG,0CAA0C,YAAY;GAClE,KAAK,WACH,QAAO,EAAG,yCAAyC,WAAW;GAChE,QACE,QAAO,EAAG,sCAAsC,QAAQ;;IAG9D,CAAC,EAAG,CACL;;AAQH,IAAa,IAAoD,EAAK,SAA6B,EAAE,WAAQ,YAAS;AACpH,QACE,kBAAC,QAAD;EACE,eAAY;EACZ,OAAO;GACL,SAAS;GACT,YAAY;GACZ,KAAK;GACL,SAAS;GACT,cAAc;GACd,iBAAiB;GACjB,QAAQ;GACR,UAAU;GACV,YAAY;GACZ,eAAe;GACf,eAAe;GACf,OAAO;GACP,YAAY;GACb;YAhBH,CAkBE,kBAAC,QAAD;GACE,eAAY;GACZ,OAAO;IACL,OAAO;IACP,QAAQ;IACR,cAAc;IACd,iBAAiB,EAAqB;IACtC,YAAY;IACb;GACD,CAAA,EACD,EACI;;EAET"}
@@ -10,15 +10,15 @@ import { memo as a, useCallback as o } from "react";
10
10
  import { PermissionButton as s } from "@burdenoff/fe-libs/shared/components";
11
11
  import { usePermissions as c } from "@burdenoff/fe-libs/shared/providers/shell";
12
12
  import { Clipboard as l, Download as u, Eye as d, FileText as f, Image as p, Minus as m, PanelLeft as h, PanelLeftClose as g, Pencil as _, Plus as v, RotateCcw as y, Save as b, Share2 as x, Store as S } from "lucide-react";
13
- import { useI18n as C } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
14
- import { Button as w, Spinner as T, Tooltip as E, TooltipContent as D, TooltipProvider as O, TooltipTrigger as k } from "@burdenoff/fe-libs/ui";
15
- import { Fragment as A, jsx as j, jsxs as M } from "react/jsx-runtime";
13
+ import { Button as C, Spinner as w, Tooltip as T, TooltipContent as E, TooltipProvider as D, TooltipTrigger as O } from "@burdenoff/fe-libs/ui";
14
+ import { Fragment as k, jsx as A, jsxs as j } from "react/jsx-runtime";
15
+ import { useI18n as M } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
16
16
  //#region src/bigconsole/components/dashboard/DashboardToolbar.tsx
17
17
  var N = a(function({ dashboardId: a, title: N, onAddWidget: P, onTogglePalette: F, isPaletteOpen: I = !1, onPaste: L, onSave: R, isSaving: z = !1, onExport: B, onPublishTemplate: V, onExportImage: H, onExportPdf: U, isExportingImage: W = !1, onShare: G }) {
18
- let { hasPermission: K } = c(), { t: q } = C(), J = t((e) => e.viewMode === "edit"), Y = t((e) => e.toggleViewMode), X = t((e) => e.zoomLevel), Z = t((e) => e.setZoomLevel), Q = !!e((e) => e.clipboardWidgetId), $ = o(() => {
18
+ let { hasPermission: K } = c(), { t: q } = M(), J = t((e) => e.viewMode === "edit"), Y = t((e) => e.toggleViewMode), X = t((e) => e.zoomLevel), Z = t((e) => e.setZoomLevel), Q = !!e((e) => e.clipboardWidgetId), $ = o(() => {
19
19
  Q && L && L();
20
20
  }, [Q, L]);
21
- return /* @__PURE__ */ j(O, { children: /* @__PURE__ */ M(n, {
21
+ return /* @__PURE__ */ A(D, { children: /* @__PURE__ */ j(n, {
22
22
  emphasis: "bare",
23
23
  padding: "none",
24
24
  "aria-label": N ? `Board toolbar — ${N}` : "Board toolbar",
@@ -26,156 +26,156 @@ var N = a(function({ dashboardId: a, title: N, onAddWidget: P, onTogglePalette:
26
26
  className: "flex-shrink-0 border-b border-[var(--color-border-subtle)] bg-bg-surface px-4 py-2",
27
27
  bodyClassName: "flex flex-wrap items-center justify-between gap-x-4 gap-y-2",
28
28
  children: [
29
- /* @__PURE__ */ j("div", {
29
+ /* @__PURE__ */ A("div", {
30
30
  className: "flex min-w-0 items-center gap-4",
31
- children: a && /* @__PURE__ */ j(i, { dashboardId: a })
31
+ children: a && /* @__PURE__ */ A(i, { dashboardId: a })
32
32
  }),
33
- /* @__PURE__ */ M("div", {
33
+ /* @__PURE__ */ j("div", {
34
34
  role: "group",
35
35
  "aria-label": "Zoom",
36
36
  className: "flex min-w-0 items-center gap-1 border-l border-[var(--color-border-subtle)] pl-4",
37
37
  children: [
38
- /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
38
+ /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
39
39
  asChild: !0,
40
- children: /* @__PURE__ */ j(w, {
40
+ children: /* @__PURE__ */ A(C, {
41
41
  variant: "ghost",
42
42
  size: "icon-sm",
43
43
  onClick: () => Z(Math.max(50, X - 10)),
44
44
  disabled: X <= 50,
45
- children: /* @__PURE__ */ j(m, { className: "size-4" })
45
+ children: /* @__PURE__ */ A(m, { className: "size-4" })
46
46
  })
47
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.zoomOut", "Zoom out") })] }),
48
- /* @__PURE__ */ M("span", {
47
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.zoomOut", "Zoom out") })] }),
48
+ /* @__PURE__ */ j("span", {
49
49
  className: "text-sm text-text-secondary w-12 text-center",
50
50
  children: [X, "%"]
51
51
  }),
52
- /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
52
+ /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
53
53
  asChild: !0,
54
- children: /* @__PURE__ */ j(w, {
54
+ children: /* @__PURE__ */ A(C, {
55
55
  variant: "ghost",
56
56
  size: "icon-sm",
57
57
  onClick: () => Z(Math.min(200, X + 10)),
58
58
  disabled: X >= 200,
59
- children: /* @__PURE__ */ j(v, { className: "size-4" })
59
+ children: /* @__PURE__ */ A(v, { className: "size-4" })
60
60
  })
61
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.zoomIn", "Zoom in") })] }),
62
- /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
61
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.zoomIn", "Zoom in") })] }),
62
+ /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
63
63
  asChild: !0,
64
- children: /* @__PURE__ */ M(w, {
64
+ children: /* @__PURE__ */ j(C, {
65
65
  variant: "ghost",
66
66
  size: "sm",
67
67
  onClick: () => Z(100),
68
- children: [/* @__PURE__ */ j(y, { className: "size-3.5 mr-1" }), q("bigconsole.dashboards.toolbar.reset", "Reset")]
68
+ children: [/* @__PURE__ */ A(y, { className: "size-3.5 mr-1" }), q("bigconsole.dashboards.toolbar.reset", "Reset")]
69
69
  })
70
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.resetZoomTooltip", "Reset zoom to 100%") })] })
70
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.resetZoomTooltip", "Reset zoom to 100%") })] })
71
71
  ]
72
72
  }),
73
- /* @__PURE__ */ M("div", {
73
+ /* @__PURE__ */ j("div", {
74
74
  role: "group",
75
75
  "aria-label": "Board actions",
76
76
  className: "flex min-w-0 flex-wrap items-center justify-end gap-2 border-l border-[var(--color-border-subtle)] pl-4",
77
77
  children: [
78
- J && /* @__PURE__ */ M(A, { children: [
79
- F && /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
78
+ J && /* @__PURE__ */ j(k, { children: [
79
+ F && /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
80
80
  asChild: !0,
81
- children: /* @__PURE__ */ M(w, {
81
+ children: /* @__PURE__ */ j(C, {
82
82
  variant: I ? "secondary" : "outline",
83
83
  size: "sm",
84
84
  onClick: F,
85
- children: [j(I ? g : h, { className: "size-4" }), q("bigconsole.dashboards.toolbar.widgets", "Widgets")]
85
+ children: [A(I ? g : h, { className: "size-4" }), q("bigconsole.dashboards.toolbar.widgets", "Widgets")]
86
86
  })
87
- }), /* @__PURE__ */ j(D, { children: I ? q("bigconsole.dashboards.toolbar.hidePalette", "Hide widget palette") : q("bigconsole.dashboards.toolbar.showPalette", "Show widget palette for drag & drop") })] }),
88
- /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
87
+ }), /* @__PURE__ */ A(E, { children: I ? q("bigconsole.dashboards.toolbar.hidePalette", "Hide widget palette") : q("bigconsole.dashboards.toolbar.showPalette", "Show widget palette for drag & drop") })] }),
88
+ /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
89
89
  asChild: !0,
90
- children: /* @__PURE__ */ M(w, {
90
+ children: /* @__PURE__ */ j(C, {
91
91
  variant: "ghost",
92
92
  size: "sm",
93
93
  onClick: $,
94
94
  disabled: !Q,
95
- children: [/* @__PURE__ */ j(l, { className: "size-4" }), q("bigconsole.dashboards.toolbar.paste", "Paste")]
95
+ children: [/* @__PURE__ */ A(l, { className: "size-4" }), q("bigconsole.dashboards.toolbar.paste", "Paste")]
96
96
  })
97
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.pasteTooltip", "Paste widget from clipboard") })] }),
98
- /* @__PURE__ */ j(s, {
97
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.pasteTooltip", "Paste widget from clipboard") })] }),
98
+ /* @__PURE__ */ A(s, {
99
99
  permission: r.WIDGET_CREATE,
100
100
  deniedBehavior: "hide",
101
- children: /* @__PURE__ */ M(w, {
101
+ children: /* @__PURE__ */ j(C, {
102
102
  size: "sm",
103
103
  onClick: P,
104
- children: [/* @__PURE__ */ j(v, { className: "size-4" }), q("bigconsole.dashboards.toolbar.addWidget", "Add Widget")]
104
+ children: [/* @__PURE__ */ A(v, { className: "size-4" }), q("bigconsole.dashboards.toolbar.addWidget", "Add Widget")]
105
105
  })
106
106
  })
107
107
  ] }),
108
- /* @__PURE__ */ j(w, {
108
+ /* @__PURE__ */ A(C, {
109
109
  variant: J ? "secondary" : "outline",
110
110
  size: "sm",
111
111
  onClick: Y,
112
- children: J ? /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j(d, { className: "size-4" }), q("bigconsole.dashboards.toolbar.preview", "Preview")] }) : /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j(_, { className: "size-4" }), q("bigconsole.dashboards.toolbar.edit", "Edit")] })
112
+ children: J ? /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(d, { className: "size-4" }), q("bigconsole.dashboards.toolbar.preview", "Preview")] }) : /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(_, { className: "size-4" }), q("bigconsole.dashboards.toolbar.edit", "Edit")] })
113
113
  }),
114
- R && /* @__PURE__ */ j(w, {
114
+ R && /* @__PURE__ */ A(C, {
115
115
  variant: "outline",
116
116
  size: "sm",
117
117
  onClick: R,
118
118
  disabled: z,
119
- children: z ? /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j(T, { className: "size-4" }), q("bigconsole.dashboards.toolbar.saving", "Saving...")] }) : /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j(b, { className: "size-4" }), q("bigconsole.dashboards.toolbar.save", "Save")] })
119
+ children: z ? /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(w, { className: "size-4" }), q("bigconsole.dashboards.toolbar.saving", "Saving...")] }) : /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(b, { className: "size-4" }), q("bigconsole.dashboards.toolbar.save", "Save")] })
120
120
  }),
121
- G && /* @__PURE__ */ j(s, {
121
+ G && /* @__PURE__ */ A(s, {
122
122
  permission: r.DASHBOARD_SHARE,
123
123
  deniedBehavior: "hide",
124
- children: /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
124
+ children: /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
125
125
  asChild: !0,
126
- children: /* @__PURE__ */ M(w, {
126
+ children: /* @__PURE__ */ j(C, {
127
127
  variant: "outline",
128
128
  size: "sm",
129
129
  onClick: G,
130
- children: [/* @__PURE__ */ j(x, { className: "size-4" }), q("bigconsole.dashboards.toolbar.share", "Share")]
130
+ children: [/* @__PURE__ */ A(x, { className: "size-4" }), q("bigconsole.dashboards.toolbar.share", "Share")]
131
131
  })
132
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.shareTooltip", "Share dashboard with others") })] })
132
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.shareTooltip", "Share dashboard with others") })] })
133
133
  }),
134
- V && /* @__PURE__ */ j(s, {
134
+ V && /* @__PURE__ */ A(s, {
135
135
  permission: r.DASHBOARD_PUBLISH,
136
136
  deniedBehavior: "hide",
137
- children: /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
137
+ children: /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
138
138
  asChild: !0,
139
- children: /* @__PURE__ */ M(w, {
139
+ children: /* @__PURE__ */ j(C, {
140
140
  variant: "outline",
141
141
  size: "sm",
142
142
  onClick: V,
143
- children: [/* @__PURE__ */ j(S, { className: "size-4" }), /* @__PURE__ */ j("span", {
143
+ children: [/* @__PURE__ */ A(S, { className: "size-4" }), /* @__PURE__ */ A("span", {
144
144
  className: "hidden sm:inline",
145
145
  children: q("bigconsole.dashboards.toolbar.publish", "Publish")
146
146
  })]
147
147
  })
148
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.publishTooltip", "Publish this dashboard as a reusable template") })] })
148
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.publishTooltip", "Publish this dashboard as a reusable template") })] })
149
149
  }),
150
- B && /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
150
+ B && /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
151
151
  asChild: !0,
152
- children: /* @__PURE__ */ M(w, {
152
+ children: /* @__PURE__ */ j(C, {
153
153
  variant: "outline",
154
154
  size: "sm",
155
155
  onClick: B,
156
- children: [/* @__PURE__ */ j(u, { className: "size-4" }), q("bigconsole.dashboards.toolbar.export", "Export")]
156
+ children: [/* @__PURE__ */ A(u, { className: "size-4" }), q("bigconsole.dashboards.toolbar.export", "Export")]
157
157
  })
158
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.exportTooltip", "Export dashboard to JSON") })] }),
159
- H && /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
158
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.exportTooltip", "Export dashboard to JSON") })] }),
159
+ H && /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
160
160
  asChild: !0,
161
- children: /* @__PURE__ */ j(w, {
161
+ children: /* @__PURE__ */ A(C, {
162
162
  variant: "outline",
163
163
  size: "icon-sm",
164
164
  onClick: H,
165
165
  disabled: W,
166
- children: j(W ? T : p, { className: "size-4" })
166
+ children: A(W ? w : p, { className: "size-4" })
167
167
  })
168
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.exportPngTooltip", "Export board as PNG image") })] }),
169
- U && /* @__PURE__ */ M(E, { children: [/* @__PURE__ */ j(k, {
168
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.exportPngTooltip", "Export board as PNG image") })] }),
169
+ U && /* @__PURE__ */ j(T, { children: [/* @__PURE__ */ A(O, {
170
170
  asChild: !0,
171
- children: /* @__PURE__ */ j(w, {
171
+ children: /* @__PURE__ */ A(C, {
172
172
  variant: "outline",
173
173
  size: "icon-sm",
174
174
  onClick: U,
175
175
  disabled: W,
176
- children: /* @__PURE__ */ j(f, { className: "size-4" })
176
+ children: /* @__PURE__ */ A(f, { className: "size-4" })
177
177
  })
178
- }), /* @__PURE__ */ j(D, { children: q("bigconsole.dashboards.toolbar.exportPdfTooltip", "Export board as PDF") })] })
178
+ }), /* @__PURE__ */ A(E, { children: q("bigconsole.dashboards.toolbar.exportPdfTooltip", "Export board as PDF") })] })
179
179
  ]
180
180
  })
181
181
  ]