@burdenoff/microfe-bigconsole 2026.805.2 → 2026.812.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.
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js +118 -106
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js.map +1 -1
- package/dist/bigconsole/components/DrilldownModal.js +54 -50
- package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
- package/dist/bigconsole/components/builder/BuilderCanvas.js +2 -2
- package/dist/bigconsole/components/builder/BuilderCanvas.js.map +1 -1
- package/dist/bigconsole/components/builder/BuilderTopbar.js +3 -3
- package/dist/bigconsole/components/builder/BuilderTopbar.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/AdvancedSection.js +24 -25
- package/dist/bigconsole/components/builder/inspector/AdvancedSection.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/AppearanceSection.js +40 -29
- package/dist/bigconsole/components/builder/inspector/AppearanceSection.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +145 -111
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/GeneralSection.js +58 -44
- package/dist/bigconsole/components/builder/inspector/GeneralSection.js.map +1 -1
- package/dist/bigconsole/components/common/Section.js +70 -0
- package/dist/bigconsole/components/common/Section.js.map +1 -0
- package/dist/bigconsole/components/common/index.js +2 -0
- package/dist/bigconsole/components/common/sectionStyles.js +42 -0
- package/dist/bigconsole/components/common/sectionStyles.js.map +1 -0
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +269 -251
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +214 -223
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardGrid.js +12 -18
- package/dist/bigconsole/components/dashboard/DashboardGrid.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +110 -102
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +81 -68
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +125 -159
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +147 -144
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +154 -153
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +82 -79
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +171 -284
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +250 -273
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/LiveBoardBanner.js +45 -53
- package/dist/bigconsole/components/dashboard/LiveBoardBanner.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +157 -148
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +167 -161
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +181 -190
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +101 -95
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js +20 -18
- package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js.map +1 -1
- package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
- package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js +26 -58
- package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js.map +1 -1
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +307 -229
- package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +128 -129
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +78 -79
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js +33 -34
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +79 -61
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +75 -64
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +1 -1
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +20 -19
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js +127 -171
- package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +312 -307
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js +65 -66
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +121 -127
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +194 -189
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/SetupStateBadge.js +3 -3
- package/dist/bigconsole/components/datasink/SetupStateBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +95 -95
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +163 -131
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ExpressionEditor.js +3 -3
- package/dist/bigconsole/components/parser/ExpressionEditor.js.map +1 -1
- package/dist/bigconsole/components/parser/ImportParserDialog.js +205 -260
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js +133 -114
- package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +193 -174
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserStatusBadge.js +2 -2
- package/dist/bigconsole/components/parser/ParserStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserTypeBadge.js +4 -4
- package/dist/bigconsole/components/parser/ParserTypeBadge.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineCard.js +134 -89
- package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +77 -64
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +7 -10
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewContent.js +31 -32
- package/dist/bigconsole/components/preview/AiPreviewContent.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +152 -103
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +193 -148
- package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/previewShared.js +41 -23
- package/dist/bigconsole/components/preview/previewShared.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +405 -364
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +265 -237
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +764 -821
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js +7 -5
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetHeader.js +7 -8
- package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetWrapper.js +8 -7
- package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js +1 -1
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +46 -49
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js +154 -147
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +118 -101
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +244 -191
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
- package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
- package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +92 -76
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +89 -86
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js +2 -2
- package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +64 -63
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListConfig.js +65 -58
- package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListItem.js +1 -1
- package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +1 -1
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +79 -72
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +181 -180
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +100 -90
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +3 -3
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/EmptyState.js +6 -4
- package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/ErrorState.js +7 -5
- package/dist/bigconsole/components/widgets/states/ErrorState.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/LoadingState.js +5 -4
- package/dist/bigconsole/components/widgets/states/LoadingState.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +193 -172
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableHeader.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableWidget.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +3 -3
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js +2 -2
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js.map +1 -1
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +283 -249
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +28 -20
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js +92 -77
- package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +70 -51
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js +16 -17
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +46 -42
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +372 -348
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
- package/dist/bigconsole/hooks/useModalFocusTrap.js +53 -0
- package/dist/bigconsole/hooks/useModalFocusTrap.js.map +1 -0
- package/dist/bigconsole/pages/DashboardBuilderPage.js +153 -142
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +230 -220
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +832 -790
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +249 -304
- package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +324 -349
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +336 -323
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +356 -458
- package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSourcesPage.js +14 -8
- package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
- package/dist/bigconsole/pages/HomePage.js +186 -193
- package/dist/bigconsole/pages/HomePage.js.map +1 -1
- package/dist/bigconsole/pages/InsightsPage.js +901 -724
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +769 -675
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +382 -354
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +540 -420
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +416 -384
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +260 -309
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.js +177 -172
- package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +278 -142
- package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +382 -366
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +202 -316
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RetentionWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/retention/RetentionWidget.tsx"],"sourcesContent":["/**\n * RetentionWidget Component\n *\n * Retention cohort chart showing user retention over time.\n */\n\nimport { type FC, memo, useMemo, useCallback } from 'react';\nimport type { Widget, RetentionConfig } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface RetentionWidgetProps {\n widget: Widget;\n data?: RetentionData;\n onClick?: (cohort: string, period: number, value: number) => void;\n}\n\nexport interface RetentionCohort {\n /** Cohort identifier (e.g., \"Week 1\", \"Jan 2024\") */\n cohort: string;\n /** Initial cohort size */\n initialSize: number;\n /** Retention values for each period (percentages) */\n values: number[];\n}\n\nexport interface RetentionData {\n /** Period labels (e.g., [\"Day 0\", \"Day 1\", ...]) */\n periods: string[];\n /** Cohort data */\n cohorts: RetentionCohort[];\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getRetentionColor(value: number): string {\n // Green gradient based on retention percentage\n if (value >= 80) return 'bg-status-success-bg/90 text-white';\n if (value >= 60) return 'bg-status-success-bg/70 text-white';\n if (value >= 40) return 'bg-status-success-bg/50 text-text-primary';\n if (value >= 20) return 'bg-status-success-bg/30 text-text-primary';\n if (value > 0) return 'bg-status-success-bg/10 text-text-secondary';\n return 'bg-bg-sunken text-text-secondary';\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const RetentionWidget: FC<RetentionWidgetProps> = memo(function RetentionWidget({ widget, data, onClick }) {\n const config = widget.config as unknown as RetentionConfig | undefined;\n\n const handleCellClick = useCallback(\n (cohort: string, periodIndex: number, value: number) => {\n if (onClick && widget.drilldowns?.length) {\n onClick(cohort, periodIndex, value);\n }\n },\n [onClick, widget.drilldowns]\n );\n\n const isClickable = Boolean(onClick && widget.drilldowns?.length);\n\n // Calculate average retention per period\n const averages = useMemo(() => {\n if (!data?.cohorts?.length || !data?.periods?.length) return [];\n\n return data.periods.map((_, periodIndex) => {\n const values = data.cohorts\n .map((c) => c.values?.[periodIndex])\n .filter((v) => v !== undefined && v !== null) as number[];\n if (values.length === 0) return 0;\n return values.reduce((a, b) => a + b, 0) / values.length;\n });\n }, [data]);\n\n // Show retention-specific empty state when cohort data is missing.\n if (!data?.cohorts?.length || !data?.periods?.length) {\n return (\n <div className=\"flex items-center justify-center h-full text-text-secondary text-sm\">\n <div className=\"text-center\">\n <svg\n className=\"w-12 h-12 mx-auto mb-2 text-text-tertiary\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2\"\n />\n </svg>\n <p className=\"font-medium text-text-primary\">No retention cohort data</p>\n <p className=\"text-xs text-text-tertiary mt-1\">\n Connect a data source that returns <span className=\"font-mono\">periods</span> and{' '}\n <span className=\"font-mono\">cohorts</span>.\n </p>\n <p className=\"text-xs text-text-tertiary mt-2\">\n Expected shape: <span className=\"font-mono\">RetentionData</span>.\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col h-full p-4 overflow-auto\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr>\n <th className=\"p-2 text-xs font-medium text-text-secondary text-left sticky left-0 bg-bg-surface\">\n Cohort\n </th>\n <th className=\"p-2 text-xs font-medium text-text-secondary text-right\">Users</th>\n {data.periods.map((period, i) => (\n <th key={i} className=\"p-2 text-xs font-medium text-text-secondary text-center min-w-[60px]\">\n {period}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.cohorts.map((cohort, _cohortIndex) => (\n <tr key={cohort.cohort}>\n <td className=\"p-2 text-sm font-medium text-text-primary text-left sticky left-0 bg-bg-surface\">\n {cohort.cohort}\n </td>\n <td className=\"p-2 text-sm text-text-secondary text-right\">\n {new Intl.NumberFormat('en-US').format(cohort.initialSize)}\n </td>\n {cohort.values.map((value, periodIndex) => (\n <td\n key={periodIndex}\n className={`p-0 ${isClickable ? 'cursor-pointer' : ''}`}\n onClick={() => handleCellClick(cohort.cohort, periodIndex, value)}\n >\n <div\n className={`\n m-0.5 p-2 rounded text-center\n ${getRetentionColor(value)}\n ${isClickable ? 'hover:ring-2 hover:ring-action-primary-bg' : ''}\n transition-all\n `}\n title={`${cohort.cohort} - ${data.periods[periodIndex]}: ${value.toFixed(1)}%`}\n >\n <span className=\"text-xs font-medium\">{value.toFixed(config?.decimals ?? 0)}%</span>\n </div>\n </td>\n ))}\n </tr>\n ))}\n\n {/* Average row */}\n {config?.showAverages !== false && (\n <tr className=\"border-t-2 border-border-default\">\n <td className=\"p-2 text-sm font-medium text-text-primary sticky left-0 bg-bg-surface\">Average</td>\n <td className=\"p-2 text-sm text-text-secondary text-right\">—</td>\n {averages.map((avg, i) => (\n <td key={i} className=\"p-0\">\n <div className=\"m-0.5 p-2 rounded bg-bg-sunken text-center\">\n <span className=\"text-xs font-semibold text-text-primary\">\n {avg.toFixed(config?.decimals ?? 0)}%\n </span>\n </div>\n </td>\n ))}\n </tr>\n )}\n </tbody>\n </table>\n\n {/* Legend */}\n {config?.showLegend !== false && (\n <div className=\"flex items-center justify-center gap-2 mt-4\">\n <span className=\"text-xs text-text-secondary\">0%</span>\n <div className=\"flex gap-0.5\">\n {[10, 30, 50, 70, 90].map((opacity) => (\n <div key={opacity} className={`w-6 h-4 rounded bg-status-success-bg/${opacity}`} />\n ))}\n </div>\n <span className=\"text-xs text-text-secondary\">100%</span>\n </div>\n )}\n </div>\n );\n});\n\nexport default RetentionWidget;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RetentionWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/retention/RetentionWidget.tsx"],"sourcesContent":["/**\n * RetentionWidget Component\n *\n * Retention cohort chart showing user retention over time.\n */\n\nimport { type FC, memo, useMemo, useCallback } from 'react';\nimport type { Widget, RetentionConfig } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface RetentionWidgetProps {\n widget: Widget;\n data?: RetentionData;\n onClick?: (cohort: string, period: number, value: number) => void;\n}\n\nexport interface RetentionCohort {\n /** Cohort identifier (e.g., \"Week 1\", \"Jan 2024\") */\n cohort: string;\n /** Initial cohort size */\n initialSize: number;\n /** Retention values for each period (percentages) */\n values: number[];\n}\n\nexport interface RetentionData {\n /** Period labels (e.g., [\"Day 0\", \"Day 1\", ...]) */\n periods: string[];\n /** Cohort data */\n cohorts: RetentionCohort[];\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getRetentionColor(value: number): string {\n // Green gradient based on retention percentage\n if (value >= 80) return 'bg-status-success-bg/90 text-white';\n if (value >= 60) return 'bg-status-success-bg/70 text-white';\n if (value >= 40) return 'bg-status-success-bg/50 text-text-primary';\n if (value >= 20) return 'bg-status-success-bg/30 text-text-primary';\n if (value > 0) return 'bg-status-success-bg/10 text-text-secondary';\n return 'bg-bg-sunken text-text-secondary';\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const RetentionWidget: FC<RetentionWidgetProps> = memo(function RetentionWidget({ widget, data, onClick }) {\n const config = widget.config as unknown as RetentionConfig | undefined;\n\n const handleCellClick = useCallback(\n (cohort: string, periodIndex: number, value: number) => {\n if (onClick && widget.drilldowns?.length) {\n onClick(cohort, periodIndex, value);\n }\n },\n [onClick, widget.drilldowns]\n );\n\n const isClickable = Boolean(onClick && widget.drilldowns?.length);\n\n // Calculate average retention per period\n const averages = useMemo(() => {\n if (!data?.cohorts?.length || !data?.periods?.length) return [];\n\n return data.periods.map((_, periodIndex) => {\n const values = data.cohorts\n .map((c) => c.values?.[periodIndex])\n .filter((v) => v !== undefined && v !== null) as number[];\n if (values.length === 0) return 0;\n return values.reduce((a, b) => a + b, 0) / values.length;\n });\n }, [data]);\n\n // Show retention-specific empty state when cohort data is missing.\n if (!data?.cohorts?.length || !data?.periods?.length) {\n return (\n <div className=\"flex items-center justify-center h-full text-text-secondary text-sm\">\n <div className=\"text-center\">\n <svg className=\"w-12 h-12 mx-auto mb-2 text-text-muted\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2\"\n />\n </svg>\n <p className=\"font-medium text-text-primary\">No retention cohort data</p>\n <p className=\"text-xs text-text-muted mt-1\">\n Connect a data source that returns <span className=\"font-mono\">periods</span> and{' '}\n <span className=\"font-mono\">cohorts</span>.\n </p>\n <p className=\"text-xs text-text-muted mt-2\">\n Expected shape: <span className=\"font-mono\">RetentionData</span>.\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col h-full p-4 overflow-auto\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr>\n <th className=\"p-2 text-xs font-medium text-text-secondary text-left sticky left-0 bg-bg-surface\">\n Cohort\n </th>\n <th className=\"p-2 text-xs font-medium text-text-secondary text-right\">Users</th>\n {data.periods.map((period, i) => (\n <th key={i} className=\"p-2 text-xs font-medium text-text-secondary text-center min-w-[60px]\">\n {period}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.cohorts.map((cohort, _cohortIndex) => (\n <tr key={cohort.cohort}>\n <td className=\"p-2 text-sm font-medium text-text-primary text-left sticky left-0 bg-bg-surface\">\n {cohort.cohort}\n </td>\n <td className=\"p-2 text-sm text-text-secondary text-right\">\n {new Intl.NumberFormat('en-US').format(cohort.initialSize)}\n </td>\n {cohort.values.map((value, periodIndex) => (\n <td\n key={periodIndex}\n className={`p-0 ${isClickable ? 'cursor-pointer' : ''}`}\n onClick={() => handleCellClick(cohort.cohort, periodIndex, value)}\n >\n <div\n className={`\n m-0.5 p-2 rounded text-center\n ${getRetentionColor(value)}\n ${isClickable ? 'hover:ring-2 hover:ring-action-primary-bg' : ''}\n transition-all\n `}\n title={`${cohort.cohort} - ${data.periods[periodIndex]}: ${value.toFixed(1)}%`}\n >\n <span className=\"text-xs font-medium\">{value.toFixed(config?.decimals ?? 0)}%</span>\n </div>\n </td>\n ))}\n </tr>\n ))}\n\n {/* Average row */}\n {config?.showAverages !== false && (\n <tr className=\"border-t-2 border-border-default\">\n <td className=\"p-2 text-sm font-medium text-text-primary sticky left-0 bg-bg-surface\">Average</td>\n <td className=\"p-2 text-sm text-text-secondary text-right\">—</td>\n {averages.map((avg, i) => (\n <td key={i} className=\"p-0\">\n <div className=\"m-0.5 p-2 rounded bg-bg-sunken text-center\">\n <span className=\"text-xs font-semibold text-text-primary\">\n {avg.toFixed(config?.decimals ?? 0)}%\n </span>\n </div>\n </td>\n ))}\n </tr>\n )}\n </tbody>\n </table>\n\n {/* Legend */}\n {config?.showLegend !== false && (\n <div className=\"flex items-center justify-center gap-2 mt-4\">\n <span className=\"text-xs text-text-secondary\">0%</span>\n <div className=\"flex gap-0.5\">\n {[10, 30, 50, 70, 90].map((opacity) => (\n <div key={opacity} className={`w-6 h-4 rounded bg-status-success-bg/${opacity}`} />\n ))}\n </div>\n <span className=\"text-xs text-text-secondary\">100%</span>\n </div>\n )}\n </div>\n );\n});\n\nexport default RetentionWidget;\n"],"mappings":";;;AAuCA,SAAS,EAAkB,GAAuB;AAOhD,QALI,KAAS,KAAW,uCACpB,KAAS,KAAW,uCACpB,KAAS,KAAW,8CACpB,KAAS,KAAW,8CACpB,IAAQ,IAAU,gDACf;;AAOT,IAAa,IAA4C,EAAK,SAAyB,EAAE,WAAQ,SAAM,cAAW;CAChH,IAAM,IAAS,EAAO,QAEhB,IAAkB,GACrB,GAAgB,GAAqB,MAAkB;AACtD,EAAI,KAAW,EAAO,YAAY,UAChC,EAAQ,GAAQ,GAAa,EAAM;IAGvC,CAAC,GAAS,EAAO,WAAW,CAC7B,EAEK,IAAc,GAAQ,KAAW,EAAO,YAAY,SAGpD,IAAW,QACX,CAAC,GAAM,SAAS,UAAU,CAAC,GAAM,SAAS,SAAe,EAAE,GAExD,EAAK,QAAQ,KAAK,GAAG,MAAgB;EAC1C,IAAM,IAAS,EAAK,QACjB,KAAK,MAAM,EAAE,SAAS,GAAa,CACnC,QAAQ,MAAM,KAAyB,KAAK;AAE/C,SADI,EAAO,WAAW,IAAU,IACzB,EAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,EAAE,GAAG,EAAO;GAClD,EACD,CAAC,EAAK,CAAC;AA4BV,QAzBI,CAAC,GAAM,SAAS,UAAU,CAAC,GAAM,SAAS,SAE1C,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;KAAyC,MAAK;KAAO,QAAO;KAAe,SAAQ;eAChG,kBAAC,QAAD;MACE,eAAc;MACd,gBAAe;MACf,aAAa;MACb,GAAE;MACF,CAAA;KACE,CAAA;IACN,kBAAC,KAAD;KAAG,WAAU;eAAgC;KAA4B,CAAA;IACzE,kBAAC,KAAD;KAAG,WAAU;eAAb;MAA4C;MACP,kBAAC,QAAD;OAAM,WAAU;iBAAY;OAAc,CAAA;;MAAK;MAClF,kBAAC,QAAD;OAAM,WAAU;iBAAY;OAAc,CAAA;;MACxC;;IACJ,kBAAC,KAAD;KAAG,WAAU;eAAb;MAA4C;MAC1B,kBAAC,QAAD;OAAM,WAAU;iBAAY;OAAoB,CAAA;;MAC9D;;IACA;;EACF,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,SAAD;GAAO,WAAU;aAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eAAoF;KAE7F,CAAA;IACL,kBAAC,MAAD;KAAI,WAAU;eAAyD;KAAU,CAAA;IAChF,EAAK,QAAQ,KAAK,GAAQ,MACzB,kBAAC,MAAD;KAAY,WAAU;eACnB;KACE,EAFI,EAEJ,CACL;IACC,EAAA,CAAA,EACC,CAAA,EACR,kBAAC,SAAD,EAAA,UAAA,CACG,EAAK,QAAQ,KAAK,GAAQ,MACzB,kBAAC,MAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAO;KACL,CAAA;IACL,kBAAC,MAAD;KAAI,WAAU;eACX,IAAI,KAAK,aAAa,QAAQ,CAAC,OAAO,EAAO,YAAY;KACvD,CAAA;IACJ,EAAO,OAAO,KAAK,GAAO,MACzB,kBAAC,MAAD;KAEE,WAAW,OAAO,IAAc,mBAAmB;KACnD,eAAe,EAAgB,EAAO,QAAQ,GAAa,EAAM;eAEjE,kBAAC,OAAD;MACE,WAAW;;0BAEL,EAAkB,EAAM,CAAC;0BACzB,IAAc,8CAA8C,GAAG;;;MAGrE,OAAO,GAAG,EAAO,OAAO,KAAK,EAAK,QAAQ,GAAa,IAAI,EAAM,QAAQ,EAAE,CAAC;gBAE5E,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CAAuC,EAAM,QAAQ,GAAQ,YAAY,EAAE,EAAC,IAAQ;;MAChF,CAAA;KACH,EAfE,EAeF,CACL;IACC,EAAA,EA1BI,EAAO,OA0BX,CACL,EAGD,GAAQ,iBAAiB,MACxB,kBAAC,MAAD;IAAI,WAAU;cAAd;KACE,kBAAC,MAAD;MAAI,WAAU;gBAAwE;MAAY,CAAA;KAClG,kBAAC,MAAD;MAAI,WAAU;gBAA6C;MAAM,CAAA;KAChE,EAAS,KAAK,GAAK,MAClB,kBAAC,MAAD;MAAY,WAAU;gBACpB,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACG,EAAI,QAAQ,GAAQ,YAAY,EAAE,EAAC,IAC/B;;OACH,CAAA;MACH,EANI,EAMJ,CACL;KACC;MAED,EAAA,CAAA,CACF;MAGP,GAAQ,eAAe,MACtB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,QAAD;KAAM,WAAU;eAA8B;KAAS,CAAA;IACvD,kBAAC,OAAD;KAAK,WAAU;eACZ;MAAC;MAAI;MAAI;MAAI;MAAI;MAAG,CAAC,KAAK,MACzB,kBAAC,OAAD,EAAmB,WAAW,wCAAwC,KAAa,EAAzE,EAAyE,CACnF;KACE,CAAA;IACN,kBAAC,QAAD;KAAM,WAAU;eAA8B;KAAW,CAAA;IACrD;KAEJ;;EAER"}
|
|
@@ -4,11 +4,13 @@ import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
|
4
4
|
var r = e(function({ widgetType: e, hasDataSource: r = !1, message: a, templateSlot: o }) {
|
|
5
5
|
let s = a || (!r && o ? `Connect the "${o}" data source to finish setting up this widget` : r ? i(e) : "Connect a data source to display data");
|
|
6
6
|
return /* @__PURE__ */ n("div", {
|
|
7
|
-
className: "\n flex flex-col items-center justify-center\n h-full w-full min-h-[120px]\n text-center\n px-
|
|
7
|
+
className: "\n flex flex-col items-center justify-center\n h-full w-full min-w-0 min-h-[120px]\n text-center\n px-3\n ",
|
|
8
|
+
role: "status",
|
|
8
9
|
children: [
|
|
9
10
|
/* @__PURE__ */ t("div", {
|
|
10
|
-
className: "\n w-12 h-12 mb-3\n flex items-center justify-center\n rounded-full\n bg-bg-sunken\n text-text-secondary\n ",
|
|
11
|
+
className: "\n w-12 h-12 mb-3 shrink-0\n flex items-center justify-center\n rounded-full\n bg-bg-sunken\n text-text-secondary\n ",
|
|
11
12
|
children: /* @__PURE__ */ t("svg", {
|
|
13
|
+
"aria-hidden": "true",
|
|
12
14
|
className: "w-6 h-6",
|
|
13
15
|
fill: "none",
|
|
14
16
|
stroke: "currentColor",
|
|
@@ -22,11 +24,11 @@ var r = e(function({ widgetType: e, hasDataSource: r = !1, message: a, templateS
|
|
|
22
24
|
})
|
|
23
25
|
}),
|
|
24
26
|
/* @__PURE__ */ t("p", {
|
|
25
|
-
className: "text-sm text-text-
|
|
27
|
+
className: "max-w-[32ch] text-sm font-medium text-text-primary",
|
|
26
28
|
children: s
|
|
27
29
|
}),
|
|
28
30
|
!r && /* @__PURE__ */ t("p", {
|
|
29
|
-
className: "
|
|
31
|
+
className: "mt-2 max-w-[32ch] text-xs text-text-secondary",
|
|
30
32
|
children: "Click Edit to configure this widget"
|
|
31
33
|
})
|
|
32
34
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/states/EmptyState.tsx"],"sourcesContent":["/**\n * WidgetEmptyState Component\n *\n * Empty state displayed when widget has no data.\n */\n\nimport { type FC, memo } from 'react';\nimport type { WidgetType } from '../../../types';\n\nexport interface WidgetEmptyStateProps {\n /** Widget type for context-specific messaging */\n widgetType?: WidgetType;\n /** Whether a data source is configured */\n hasDataSource?: boolean;\n /** Custom message */\n message?: string;\n /**\n * Slot name when this widget came from a store template and its data source\n * has not been connected yet. Turns the generic empty state into an\n * explicitly unfinished-setup state, so it does not read as a broken widget.\n */\n templateSlot?: string | null;\n}\n\nexport const WidgetEmptyState: FC<WidgetEmptyStateProps> = memo(function WidgetEmptyState({\n widgetType,\n hasDataSource = false,\n message,\n templateSlot,\n}) {\n // A template widget awaiting its data source is a designed setup state, not\n // an absence of results — say so explicitly and name the slot to connect.\n const awaitingTemplateBinding = !hasDataSource && !!templateSlot;\n\n // Determine appropriate message\n const displayMessage =\n message ||\n (awaitingTemplateBinding\n ? `Connect the \"${templateSlot}\" data source to finish setting up this widget`\n : !hasDataSource\n ? 'Connect a data source to display data'\n : getEmptyMessageForType(widgetType));\n\n return (\n <div\n className=\"\n flex flex-col items-center justify-center\n h-full w-full min-h-[120px]\n text-center\n px-
|
|
1
|
+
{"version":3,"file":"EmptyState.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/states/EmptyState.tsx"],"sourcesContent":["/**\n * WidgetEmptyState Component\n *\n * Empty state displayed when widget has no data.\n */\n\nimport { type FC, memo } from 'react';\nimport type { WidgetType } from '../../../types';\n\nexport interface WidgetEmptyStateProps {\n /** Widget type for context-specific messaging */\n widgetType?: WidgetType;\n /** Whether a data source is configured */\n hasDataSource?: boolean;\n /** Custom message */\n message?: string;\n /**\n * Slot name when this widget came from a store template and its data source\n * has not been connected yet. Turns the generic empty state into an\n * explicitly unfinished-setup state, so it does not read as a broken widget.\n */\n templateSlot?: string | null;\n}\n\nexport const WidgetEmptyState: FC<WidgetEmptyStateProps> = memo(function WidgetEmptyState({\n widgetType,\n hasDataSource = false,\n message,\n templateSlot,\n}) {\n // A template widget awaiting its data source is a designed setup state, not\n // an absence of results — say so explicitly and name the slot to connect.\n const awaitingTemplateBinding = !hasDataSource && !!templateSlot;\n\n // Determine appropriate message\n const displayMessage =\n message ||\n (awaitingTemplateBinding\n ? `Connect the \"${templateSlot}\" data source to finish setting up this widget`\n : !hasDataSource\n ? 'Connect a data source to display data'\n : getEmptyMessageForType(widgetType));\n\n return (\n /*\n One shared recipe across the four widget states (empty / error / loading /\n crash): same icon chip, same copy width, same padding. Copy is capped in\n `ch` rather than a fixed 200px so it never overflows a narrow card\n (BOFF-5636).\n */\n <div\n className=\"\n flex flex-col items-center justify-center\n h-full w-full min-w-0 min-h-[120px]\n text-center\n px-3\n \"\n role=\"status\"\n >\n {/* Empty Icon */}\n <div\n className=\"\n w-12 h-12 mb-3 shrink-0\n flex items-center justify-center\n rounded-full\n bg-bg-sunken\n text-text-secondary\n \"\n >\n <svg aria-hidden=\"true\" className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4\"\n />\n </svg>\n </div>\n\n {/* Message */}\n <p className=\"max-w-[32ch] text-sm font-medium text-text-primary\">{displayMessage}</p>\n\n {/* Data source hint */}\n {!hasDataSource && (\n <p className=\"mt-2 max-w-[32ch] text-xs text-text-secondary\">Click Edit to configure this widget</p>\n )}\n </div>\n );\n});\n\n/**\n * Get context-specific empty message for widget type (v1.0 snake_case)\n */\nfunction getEmptyMessageForType(type?: WidgetType): string {\n switch (type) {\n case 'metric_card':\n case 'kpi_card_comparison':\n return 'No metrics available';\n case 'chart':\n case 'funnel_chart':\n return 'No chart data available';\n case 'table':\n case 'pivot_table':\n return 'No rows to display';\n case 'gauge':\n case 'progress':\n return 'No value available';\n case 'list':\n return 'No items to display';\n case 'heatmap':\n return 'No heatmap data available';\n case 'calendar':\n case 'timeline':\n case 'kanban':\n return 'No schedule data available';\n case 'map':\n return 'No location data available';\n case 'form':\n return 'Form not configured';\n case 'text':\n case 'iframe':\n return 'No content configured';\n case 'custom':\n return 'Custom widget not configured';\n default:\n return 'No data available';\n }\n}\n\nexport default WidgetEmptyState;\n"],"mappings":";;;AAwBA,IAAa,IAA8C,EAAK,SAA0B,EACxF,eACA,mBAAgB,IAChB,YACA,mBACC;CAMD,IAAM,IACJ,MAJ8B,CAAC,KAAmB,IAM9C,gBAAgB,EAAa,kDAC5B,IAEC,EAAuB,EAAW,GADlC;AAGR,QAOE,kBAAC,OAAD;EACE,WAAU;EAMV,MAAK;YAPP;GAUE,kBAAC,OAAD;IACE,WAAU;cAQV,kBAAC,OAAD;KAAK,eAAY;KAAO,WAAU;KAAU,MAAK;KAAO,QAAO;KAAe,SAAQ;eACpF,kBAAC,QAAD;MACE,eAAc;MACd,gBAAe;MACf,aAAa;MACb,GAAE;MACF,CAAA;KACE,CAAA;IACF,CAAA;GAGN,kBAAC,KAAD;IAAG,WAAU;cAAsD;IAAmB,CAAA;GAGrF,CAAC,KACA,kBAAC,KAAD;IAAG,WAAU;cAAgD;IAAuC,CAAA;GAElG;;EAER;AAKF,SAAS,EAAuB,GAA2B;AACzD,SAAQ,GAAR;EACE,KAAK;EACL,KAAK,sBACH,QAAO;EACT,KAAK;EACL,KAAK,eACH,QAAO;EACT,KAAK;EACL,KAAK,cACH,QAAO;EACT,KAAK;EACL,KAAK,WACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK,MACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,QACE,QAAO"}
|
|
@@ -3,12 +3,13 @@ import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
|
3
3
|
//#region src/bigconsole/components/widgets/states/ErrorState.tsx
|
|
4
4
|
var r = e(function({ error: e, onRetry: r }) {
|
|
5
5
|
return /* @__PURE__ */ n("div", {
|
|
6
|
-
className: "\n flex flex-col items-center justify-center\n h-full w-full min-h-[120px]\n text-center\n px-
|
|
6
|
+
className: "\n flex flex-col items-center justify-center\n h-full w-full min-w-0 min-h-[120px]\n text-center\n px-3\n ",
|
|
7
7
|
role: "alert",
|
|
8
8
|
children: [
|
|
9
9
|
/* @__PURE__ */ t("div", {
|
|
10
|
-
className: "\n w-12 h-12 mb-3\n flex items-center justify-center\n rounded-full\n bg-status-error-bg
|
|
10
|
+
className: "\n w-12 h-12 mb-3 shrink-0\n flex items-center justify-center\n rounded-full\n bg-status-error-bg-subtle\n text-[var(--color-status-error-text)]\n ",
|
|
11
11
|
children: /* @__PURE__ */ t("svg", {
|
|
12
|
+
"aria-hidden": "true",
|
|
12
13
|
className: "w-6 h-6",
|
|
13
14
|
fill: "none",
|
|
14
15
|
stroke: "currentColor",
|
|
@@ -22,19 +23,20 @@ var r = e(function({ error: e, onRetry: r }) {
|
|
|
22
23
|
})
|
|
23
24
|
}),
|
|
24
25
|
/* @__PURE__ */ t("p", {
|
|
25
|
-
className: "text-sm font-
|
|
26
|
+
className: "mb-1 text-sm font-semibold text-[var(--color-status-error-text)]",
|
|
26
27
|
children: "Failed to load data"
|
|
27
28
|
}),
|
|
28
29
|
/* @__PURE__ */ t("p", {
|
|
29
|
-
className: "
|
|
30
|
+
className: "mb-4 max-w-[32ch] break-words text-xs text-text-secondary",
|
|
30
31
|
title: e,
|
|
31
32
|
children: e.length > 100 ? `${e.substring(0, 100)}...` : e
|
|
32
33
|
}),
|
|
33
34
|
r && /* @__PURE__ */ n("button", {
|
|
34
35
|
type: "button",
|
|
35
36
|
onClick: r,
|
|
36
|
-
className: "\n inline-flex items-center gap-1.5\n px-3
|
|
37
|
+
className: "\n inline-flex items-center gap-1.5\n min-h-control-md px-3\n text-sm font-medium\n text-action-primary-text\n bg-action-primary-bg\n hover:bg-action-primary-bgHover\n rounded-button\n motion-safe:transition-colors\n focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg-surface\n ",
|
|
37
38
|
children: [/* @__PURE__ */ t("svg", {
|
|
39
|
+
"aria-hidden": "true",
|
|
38
40
|
className: "w-4 h-4",
|
|
39
41
|
fill: "none",
|
|
40
42
|
stroke: "currentColor",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorState.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/states/ErrorState.tsx"],"sourcesContent":["/**\n * WidgetErrorState Component\n *\n * Error state displayed when widget data fetch fails.\n */\n\nimport { type FC, memo } from 'react';\n\nexport interface WidgetErrorStateProps {\n /** Error message */\n error: string;\n /** Callback to retry loading */\n onRetry?: () => void;\n}\n\nexport const WidgetErrorState: FC<WidgetErrorStateProps> = memo(function WidgetErrorState({ error, onRetry }) {\n return (\n <div\n className=\"\n flex flex-col items-center justify-center\n h-full w-full min-h-[120px]\n text-center\n px-
|
|
1
|
+
{"version":3,"file":"ErrorState.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/states/ErrorState.tsx"],"sourcesContent":["/**\n * WidgetErrorState Component\n *\n * Error state displayed when widget data fetch fails.\n */\n\nimport { type FC, memo } from 'react';\n\nexport interface WidgetErrorStateProps {\n /** Error message */\n error: string;\n /** Callback to retry loading */\n onRetry?: () => void;\n}\n\nexport const WidgetErrorState: FC<WidgetErrorStateProps> = memo(function WidgetErrorState({ error, onRetry }) {\n return (\n /* Shares the empty-state recipe: same chip, same copy width, same padding. */\n <div\n className=\"\n flex flex-col items-center justify-center\n h-full w-full min-w-0 min-h-[120px]\n text-center\n px-3\n \"\n role=\"alert\"\n >\n {/* Error Icon */}\n <div\n className=\"\n w-12 h-12 mb-3 shrink-0\n flex items-center justify-center\n rounded-full\n bg-status-error-bg-subtle\n text-[var(--color-status-error-text)]\n \"\n >\n <svg aria-hidden=\"true\" className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n\n {/* Error Message */}\n <p className=\"mb-1 text-sm font-semibold text-[var(--color-status-error-text)]\">Failed to load data</p>\n <p className=\"mb-4 max-w-[32ch] break-words text-xs text-text-secondary\" title={error}>\n {error.length > 100 ? `${error.substring(0, 100)}...` : error}\n </p>\n\n {/* Retry Button */}\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"\n inline-flex items-center gap-1.5\n min-h-control-md px-3\n text-sm font-medium\n text-action-primary-text\n bg-action-primary-bg\n hover:bg-action-primary-bgHover\n rounded-button\n motion-safe:transition-colors\n focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg-surface\n \"\n >\n <svg aria-hidden=\"true\" className=\"w-4 h-4\" 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 Retry\n </button>\n )}\n </div>\n );\n});\n\nexport default WidgetErrorState;\n"],"mappings":";;;AAeA,IAAa,IAA8C,EAAK,SAA0B,EAAE,UAAO,cAAW;AAC5G,QAEE,kBAAC,OAAD;EACE,WAAU;EAMV,MAAK;YAPP;GAUE,kBAAC,OAAD;IACE,WAAU;cAQV,kBAAC,OAAD;KAAK,eAAY;KAAO,WAAU;KAAU,MAAK;KAAO,QAAO;KAAe,SAAQ;eACpF,kBAAC,QAAD;MACE,eAAc;MACd,gBAAe;MACf,aAAa;MACb,GAAE;MACF,CAAA;KACE,CAAA;IACF,CAAA;GAGN,kBAAC,KAAD;IAAG,WAAU;cAAmE;IAAuB,CAAA;GACvG,kBAAC,KAAD;IAAG,WAAU;IAA4D,OAAO;cAC7E,EAAM,SAAS,MAAM,GAAG,EAAM,UAAU,GAAG,IAAI,CAAC,OAAO;IACtD,CAAA;GAGH,KACC,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;cAHZ,CAeE,kBAAC,OAAD;KAAK,eAAY;KAAO,WAAU;KAAU,MAAK;KAAO,QAAO;KAAe,SAAQ;eACpF,kBAAC,QAAD;MACE,eAAc;MACd,gBAAe;MACf,aAAa;MACb,GAAE;MACF,CAAA;KACE,CAAA,EAAA,QAEC;;GAEP;;EAER"}
|
|
@@ -3,14 +3,15 @@ import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
|
3
3
|
//#region src/bigconsole/components/widgets/states/LoadingState.tsx
|
|
4
4
|
var r = e(function({ message: e = "Loading..." }) {
|
|
5
5
|
return /* @__PURE__ */ n("div", {
|
|
6
|
-
className: "\n flex flex-col items-center justify-center\n h-full w-full min-h-[120px]\n text-text-secondary\n ",
|
|
6
|
+
className: "\n flex flex-col items-center justify-center\n h-full w-full min-w-0 min-h-[120px]\n px-3 text-center text-text-secondary\n ",
|
|
7
7
|
role: "status",
|
|
8
8
|
"aria-live": "polite",
|
|
9
9
|
children: [/* @__PURE__ */ n("div", {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
"aria-hidden": "true",
|
|
11
|
+
className: "relative mb-3 h-12 w-12 shrink-0 p-1",
|
|
12
|
+
children: [/* @__PURE__ */ t("div", { className: "\n absolute inset-1\n border-4 border-[var(--color-border-subtle)]\n rounded-full\n " }), /* @__PURE__ */ t("div", { className: "\n absolute inset-1\n border-4 border-action-primary-bg\n border-t-transparent\n rounded-full\n motion-safe:animate-spin\n " })]
|
|
12
13
|
}), /* @__PURE__ */ t("p", {
|
|
13
|
-
className: "text-sm",
|
|
14
|
+
className: "max-w-[32ch] text-sm",
|
|
14
15
|
children: e
|
|
15
16
|
})]
|
|
16
17
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingState.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/states/LoadingState.tsx"],"sourcesContent":["/**\n * WidgetLoadingState Component\n *\n * Loading state displayed while widget data is being fetched.\n */\n\nimport { type FC, memo } from 'react';\n\nexport interface WidgetLoadingStateProps {\n /** Optional message to display */\n message?: string;\n}\n\nexport const WidgetLoadingState: FC<WidgetLoadingStateProps> = memo(function WidgetLoadingState({\n message = 'Loading...',\n}) {\n return (\n <div\n className=\"\n flex flex-col items-center justify-center\n h-full w-full min-h-[120px]\n text-text-secondary\n \"\n role=\"status\"\n aria-live=\"polite\"\n >\n {/* Spinner */}\n <div className=\"relative
|
|
1
|
+
{"version":3,"file":"LoadingState.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/states/LoadingState.tsx"],"sourcesContent":["/**\n * WidgetLoadingState Component\n *\n * Loading state displayed while widget data is being fetched.\n */\n\nimport { type FC, memo } from 'react';\n\nexport interface WidgetLoadingStateProps {\n /** Optional message to display */\n message?: string;\n}\n\nexport const WidgetLoadingState: FC<WidgetLoadingStateProps> = memo(function WidgetLoadingState({\n message = 'Loading...',\n}) {\n return (\n /* Shares the empty/error-state recipe so all four states read as one family. */\n <div\n className=\"\n flex flex-col items-center justify-center\n h-full w-full min-w-0 min-h-[120px]\n px-3 text-center text-text-secondary\n \"\n role=\"status\"\n aria-live=\"polite\"\n >\n {/* Spinner */}\n <div aria-hidden=\"true\" className=\"relative mb-3 h-12 w-12 shrink-0 p-1\">\n <div\n className=\"\n absolute inset-1\n border-4 border-[var(--color-border-subtle)]\n rounded-full\n \"\n />\n <div\n className=\"\n absolute inset-1\n border-4 border-action-primary-bg\n border-t-transparent\n rounded-full\n motion-safe:animate-spin\n \"\n />\n </div>\n\n {/* Message */}\n <p className=\"max-w-[32ch] text-sm\">{message}</p>\n </div>\n );\n});\n\nexport default WidgetLoadingState;\n"],"mappings":";;;AAaA,IAAa,IAAkD,EAAK,SAA4B,EAC9F,aAAU,gBACT;AACD,QAEE,kBAAC,OAAD;EACE,WAAU;EAKV,MAAK;EACL,aAAU;YAPZ,CAUE,kBAAC,OAAD;GAAK,eAAY;GAAO,WAAU;aAAlC,CACE,kBAAC,OAAD,EACE,WAAU,0IAKV,CAAA,EACF,kBAAC,OAAD,EACE,WAAU,2MAOV,CAAA,CACE;MAGN,kBAAC,KAAD;GAAG,WAAU;aAAwB;GAAY,CAAA,CAC7C;;EAER"}
|