@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":"PipelinesPage.js","names":[],"sources":["../../../src/bigconsole/pages/PipelinesPage.tsx"],"sourcesContent":["/**\n * Pipelines Page\n *\n * List and manage Pipelines.\n *\n * Section ladder (BOFF-5635):\n * bare — page header band, filter/search toolbar (structure only)\n * primary — \"Your pipelines\" results region: the block this route exists for\n * muted — nested empty / no-match states inside the results region\n * danger — load failure, rendered under the header so navigation survives\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { usePipelineStore } from '../store/pipelineStore';\nimport { PipelineCard } from '../components/pipeline/PipelineCard';\nimport { PipelineDeleteDialog } from '../components/pipeline/PipelineDeleteDialog';\nimport { Section, SectionStack, SECTION_FOCUS_RING, sectionSurfaceClasses } from '../components/common';\nimport type { PipelineStatus } from '../types';\n\n// fe-libs RBAC\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\n\n// fe-libs UI components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { AuroraBackground, GradientText, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\n// Lucide icons\nimport { Plus, Search, GitBranch, AlertCircle } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ntype StatusFilter = 'all' | PipelineStatus;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelinesPage = memo(function PipelinesPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n\n // Permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_READ);\n // Create is gated inline via <PermissionButton permission=PIPELINE_CREATE>.\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_DELETE);\n const canTest = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_TEST);\n\n // Local state\n const [statusFilter, setStatusFilter] = useState<StatusFilter>('all');\n\n // Store state\n const searchQuery = usePipelineStore((state) => state.searchQuery);\n const setSearchQuery = usePipelineStore((state) => state.setSearchQuery);\n const deleteDialogOpen = usePipelineStore((state) => state.deleteDialogOpen);\n const currentPipeline = usePipelineStore((state) => state.currentPipeline);\n const openDeleteDialog = usePipelineStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = usePipelineStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, pipelines, deletePipeline, refetch } = usePipelineOperations({\n consoleId: 'default',\n });\n\n // Filter pipelines\n const filteredPipelines = useMemo(() => {\n let filtered = [...pipelines];\n\n // Apply status filter\n if (statusFilter !== 'all') {\n filtered = filtered.filter((p) => p.status === statusFilter);\n }\n\n // Apply search filter\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (p) => p.name.toLowerCase().includes(query) || p.description?.toLowerCase().includes(query)\n );\n }\n\n // Sort by updatedAt descending\n return filtered.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n }, [pipelines, statusFilter, searchQuery]);\n\n // Handlers\n const handleCreatePipeline = useCallback(() => {\n navigate('/pipelines/new');\n }, [navigate]);\n\n const handleViewPipeline = useCallback(\n (id: string) => {\n navigate(`/pipelines/${id}`);\n },\n [navigate]\n );\n\n const handleEditPipeline = useCallback(\n (id: string) => {\n navigate(`/pipelines/${id}/edit`);\n },\n [navigate]\n );\n\n const handleTestPipeline = useCallback(\n (id: string) => {\n navigate(`/pipelines/${id}?test=true`);\n },\n [navigate]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const pipeline = pipelines.find((p) => p.id === id);\n if (pipeline) {\n openDeleteDialog(pipeline);\n }\n },\n [pipelines, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentPipeline) {\n try {\n await deletePipeline(currentPipeline.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentPipeline, deletePipeline, closeDeleteDialog]);\n\n const handleClearFilters = useCallback(() => {\n setStatusFilter('all');\n setSearchQuery('');\n }, [setSearchQuery]);\n\n // Status filter options\n const statusOptions: { value: StatusFilter; label: string }[] = [\n { value: 'all', label: t('bigconsole.pipelines.filters.all', 'All') },\n { value: 'draft', label: t('bigconsole.pipelines.filters.draft', 'Draft') },\n { value: 'active', label: t('bigconsole.pipelines.filters.active', 'Active') },\n { value: 'inactive', label: t('bigconsole.pipelines.filters.inactive', 'Inactive') },\n { value: 'error', label: t('bigconsole.pipelines.filters.error', 'Error') },\n ];\n\n // Permission gate — wait for permissions to resolve, then block callers\n // without pipeline read access before rendering the page body.\n if (permissionsLoading) {\n return (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n }}\n />\n </div>\n );\n }\n\n if (!canRead) {\n return (\n <AccessDenied\n title={t('bigconsole.pipelines.errors.accessDeniedTitle', 'Access Denied')}\n description={t(\n 'bigconsole.pipelines.errors.accessDeniedListDescription',\n \"You don't have permission to view pipelines.\"\n )}\n />\n );\n }\n\n /**\n * Page header band. `bare` in the emphasis ladder: it carries the page\n * identity and the single create action, never a content surface. Rendered in\n * both the error and the normal branch so a failed load keeps its \"you are\n * here\" anchor instead of replacing the whole page.\n */\n const pageHeader = (\n <header className=\"relative overflow-hidden border-b border-[var(--color-border-seam)] bg-[image:var(--gradient-gloss-card)]\">\n <AuroraBackground intensity=\"subtle\" />\n <div\n className=\"flex flex-col gap-form-gap sm:flex-row sm:items-center sm:justify-between\"\n style={{ padding: 'var(--space-pagePadding)' }}\n >\n <div className=\"flex min-w-0 items-center gap-form-gap\">\n <span\n aria-hidden=\"true\"\n className=\"flex shrink-0 items-center justify-center rounded-card\"\n style={{\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <GitBranch\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </span>\n <div className=\"min-w-0\">\n <h1 className=\"text-2xl font-bold leading-tight text-text-primary\">\n <GradientText>{t('bigconsole.pipelines.list.heading', 'Pipelines')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.pipelines.list.subtitle',\n 'Create and manage sequential parser chains for data transformation'\n )}\n </p>\n </div>\n </div>\n\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.PIPELINE_CREATE} deniedBehavior=\"disable\">\n <Button\n onClick={handleCreatePipeline}\n className=\"w-full shrink-0 min-h-[var(--size-controlHeight-md)] sm:w-auto\"\n >\n <Plus className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.actions.createPipeline', 'Create Pipeline')}\n </Button>\n </PermissionButton>\n </div>\n </header>\n );\n\n // Error state — keep the header so the page never loses its context.\n if (error) {\n return (\n <div className=\"min-h-screen bg-bg-canvas\">\n {pageHeader}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Section\n tone=\"danger\"\n headingLevel={2}\n title={t('bigconsole.pipelines.errors.loadListTitle', 'Failed to load Pipelines')}\n description={error.message}\n icon={<AlertCircle className=\"h-icon-sm w-icon-sm\" />}\n actions={\n <Button size=\"sm\" onClick={() => refetch()}>\n {t('bigconsole.pipelines.actions.tryAgain', 'Try Again')}\n </Button>\n }\n data-testid=\"pipelines-error\"\n >\n <p className=\"text-sm text-text-secondary\">\n Nothing was changed. Retry once the console service is reachable again.\n </p>\n </Section>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"min-h-screen bg-bg-canvas\">\n {pageHeader}\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <SectionStack>\n <PagePurpose className=\"max-w-[75ch]\">\n {t(\n 'bigconsole.pipelines.list.purpose',\n 'Pipelines chain parsers and data sinks into a repeatable flow — they take raw input, run it through your parsers, and route the structured result into a sink. Use them to turn messy logs, files, or API payloads into clean, queryable data your dashboards can use.'\n )}\n </PagePurpose>\n\n {/* Toolbar — `bare` in the ladder: filters + search grouped so the eye\n reads one control row instead of two floating stripes. Written with\n `sectionSurfaceClasses` rather than <Section> because the block has\n no visible heading (see the ticket note on Section's required\n `title` prop). */}\n <section\n aria-label=\"Filter and search pipelines\"\n data-testid=\"pipelines-toolbar\"\n data-section-emphasis=\"bare\"\n className={sectionSurfaceClasses('bare', 'neutral', 'none')}\n >\n <div className=\"flex flex-col gap-control-gap md:flex-row md:items-center md:justify-between\">\n {/* `min-w-0`: the pills are `shrink-0`, so without it this scroller\n refuses to shrink in the md row and pushes the search field out. */}\n <div\n role=\"group\"\n aria-label=\"Filter by status\"\n className=\"flex min-w-0 max-w-full items-center gap-1 overflow-x-auto rounded-card bg-bg-sunken p-1\"\n >\n {statusOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n aria-pressed={statusFilter === option.value}\n onClick={() => setStatusFilter(option.value)}\n className={`shrink-0 whitespace-nowrap rounded-button text-sm font-medium motion-safe:transition-colors ${SECTION_FOCUS_RING}`}\n style={{\n minHeight: 'var(--size-controlHeight-md)',\n padding: '0 var(--space-formGap)',\n border: 'none',\n cursor: 'pointer',\n backgroundColor: statusFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color:\n statusFilter === option.value ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n boxShadow: statusFilter === option.value ? 'var(--shadow-elevation-1)' : 'none',\n }}\n >\n {option.label}\n </button>\n ))}\n </div>\n\n <div className=\"relative w-full md:max-w-[320px]\">\n <Search\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n aria-label={t('bigconsole.pipelines.list.searchPlaceholder', 'Search pipelines...')}\n placeholder={t('bigconsole.pipelines.list.searchPlaceholder', 'Search pipelines...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n </section>\n\n {/* Results — the one primary block on this route. */}\n <Section\n emphasis=\"primary\"\n headingLevel={2}\n title=\"Your pipelines\"\n description=\"Open one to review its stages, or run a quick test against sample input.\"\n meta={\n !loading || pipelines.length > 0 ? (\n <span className=\"rounded-pill bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {filteredPipelines.length}\n {filteredPipelines.length === pipelines.length ? '' : ` of ${pipelines.length}`}\n </span>\n ) : null\n }\n data-testid=\"pipelines-results\"\n >\n {/* Loading state */}\n {loading && pipelines.length === 0 && (\n <div className=\"flex items-center justify-center py-12\" role=\"status\">\n <div className=\"text-center\">\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p className=\"text-sm text-text-muted\">\n {t('bigconsole.pipelines.list.loading', 'Loading pipelines...')}\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state — nothing created yet (onboarding). */}\n {!loading && pipelines.length === 0 && (\n <div data-testid=\"pipelines-empty\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('bigconsole.pipelines.list.emptyTitle', 'No Pipelines yet')}\n description={t(\n 'bigconsole.pipelines.list.emptyDescription',\n 'Create a pipeline to chain parsers together for sequential data transformation. Each stage processes the output of the previous stage.'\n )}\n action={\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.PIPELINE_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreatePipeline} className=\"min-h-[var(--size-controlHeight-md)]\">\n <Plus className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.actions.createPipeline', 'Create Pipeline')}\n </Button>\n </PermissionButton>\n }\n />\n </div>\n )}\n\n {/* No results state — a filter problem, not an onboarding problem. */}\n {!loading && filteredPipelines.length === 0 && pipelines.length > 0 && (\n <Section\n emphasis=\"muted\"\n tone=\"info\"\n padding=\"compact\"\n headingLevel={3}\n title={t('bigconsole.pipelines.list.noResultsTitle', 'No matching pipelines')}\n description={t('bigconsole.pipelines.list.noResultsDescription', 'No pipelines match your filters')}\n actions={\n <Button size=\"sm\" variant=\"secondary\" onClick={handleClearFilters}>\n Clear filters\n </Button>\n }\n data-testid=\"pipelines-no-results\"\n />\n )}\n\n {/* Pipeline Grid */}\n {filteredPipelines.length > 0 && (\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2 xl:grid-cols-3\">\n {filteredPipelines.map((pipeline) => (\n <PipelineCard\n key={pipeline.id}\n pipeline={pipeline}\n onView={handleViewPipeline}\n onEdit={canUpdate ? handleEditPipeline : undefined}\n onTest={canTest ? handleTestPipeline : undefined}\n onDelete={canDelete ? handleDeleteClick : undefined}\n />\n ))}\n </div>\n )}\n </Section>\n </SectionStack>\n </div>\n\n {/* Delete Dialog */}\n {currentPipeline && (\n <PipelineDeleteDialog\n pipeline={currentPipeline}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default PipelinesPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"PipelinesPage.js","names":[],"sources":["../../../src/bigconsole/pages/PipelinesPage.tsx"],"sourcesContent":["/**\n * Pipelines Page\n *\n * List and manage Pipelines.\n *\n * Section ladder (BOFF-5635):\n * bare — page header band, filter/search toolbar (structure only)\n * primary — \"Your pipelines\" results region: the block this route exists for\n * muted — nested empty / no-match states inside the results region\n * danger — load failure, rendered under the header so navigation survives\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { usePipelineStore } from '../store/pipelineStore';\nimport { PipelineCard } from '../components/pipeline/PipelineCard';\nimport { PipelineDeleteDialog } from '../components/pipeline/PipelineDeleteDialog';\nimport { Section, SectionStack, SECTION_FOCUS_RING, sectionSurfaceClasses } from '../components/common';\nimport type { PipelineStatus } from '../types';\n\n// fe-libs RBAC\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\n\n// fe-libs UI components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { AuroraBackground, GradientText, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\n// Lucide icons\nimport { Plus, Search, GitBranch, AlertCircle } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ntype StatusFilter = 'all' | PipelineStatus;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelinesPage = memo(function PipelinesPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n\n // Permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_READ);\n // Create is gated inline via <PermissionButton permission=PIPELINE_CREATE>.\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_DELETE);\n const canTest = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_TEST);\n\n // Local state\n const [statusFilter, setStatusFilter] = useState<StatusFilter>('all');\n\n // Store state\n const searchQuery = usePipelineStore((state) => state.searchQuery);\n const setSearchQuery = usePipelineStore((state) => state.setSearchQuery);\n const deleteDialogOpen = usePipelineStore((state) => state.deleteDialogOpen);\n const currentPipeline = usePipelineStore((state) => state.currentPipeline);\n const openDeleteDialog = usePipelineStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = usePipelineStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, pipelines, deletePipeline, refetch } = usePipelineOperations({\n consoleId: 'default',\n });\n\n // Filter pipelines\n const filteredPipelines = useMemo(() => {\n let filtered = [...pipelines];\n\n // Apply status filter\n if (statusFilter !== 'all') {\n filtered = filtered.filter((p) => p.status === statusFilter);\n }\n\n // Apply search filter\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (p) => p.name.toLowerCase().includes(query) || p.description?.toLowerCase().includes(query)\n );\n }\n\n // Sort by updatedAt descending\n return filtered.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n }, [pipelines, statusFilter, searchQuery]);\n\n // Handlers\n const handleCreatePipeline = useCallback(() => {\n navigate('/pipelines/new');\n }, [navigate]);\n\n const handleViewPipeline = useCallback(\n (id: string) => {\n navigate(`/pipelines/${id}`);\n },\n [navigate]\n );\n\n const handleEditPipeline = useCallback(\n (id: string) => {\n navigate(`/pipelines/${id}/edit`);\n },\n [navigate]\n );\n\n const handleTestPipeline = useCallback(\n (id: string) => {\n navigate(`/pipelines/${id}?test=true`);\n },\n [navigate]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const pipeline = pipelines.find((p) => p.id === id);\n if (pipeline) {\n openDeleteDialog(pipeline);\n }\n },\n [pipelines, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentPipeline) {\n try {\n await deletePipeline(currentPipeline.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentPipeline, deletePipeline, closeDeleteDialog]);\n\n const handleClearFilters = useCallback(() => {\n setStatusFilter('all');\n setSearchQuery('');\n }, [setSearchQuery]);\n\n // Status filter options\n const statusOptions: { value: StatusFilter; label: string }[] = [\n { value: 'all', label: t('bigconsole.pipelines.filters.all', 'All') },\n { value: 'draft', label: t('bigconsole.pipelines.filters.draft', 'Draft') },\n { value: 'active', label: t('bigconsole.pipelines.filters.active', 'Active') },\n { value: 'inactive', label: t('bigconsole.pipelines.filters.inactive', 'Inactive') },\n { value: 'error', label: t('bigconsole.pipelines.filters.error', 'Error') },\n ];\n\n // Permission gate — wait for permissions to resolve, then block callers\n // without pipeline read access before rendering the page body.\n if (permissionsLoading) {\n return (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n }}\n />\n </div>\n );\n }\n\n if (!canRead) {\n return (\n <AccessDenied\n title={t('bigconsole.pipelines.errors.accessDeniedTitle', 'Access Denied')}\n description={t(\n 'bigconsole.pipelines.errors.accessDeniedListDescription',\n \"You don't have permission to view pipelines.\"\n )}\n />\n );\n }\n\n /**\n * Page header band. `bare` in the emphasis ladder: it carries the page\n * identity and the single create action, never a content surface. Rendered in\n * both the error and the normal branch so a failed load keeps its \"you are\n * here\" anchor instead of replacing the whole page.\n */\n const pageHeader = (\n <header className=\"relative overflow-hidden border-b border-[var(--color-border-seam)] bg-[image:var(--gradient-gloss-card)]\">\n <AuroraBackground intensity=\"subtle\" />\n <div\n className=\"flex flex-col gap-form-gap sm:flex-row sm:items-center sm:justify-between\"\n style={{ padding: 'var(--space-pagePadding)' }}\n >\n <div className=\"flex min-w-0 items-center gap-form-gap\">\n <span\n aria-hidden=\"true\"\n className=\"flex shrink-0 items-center justify-center rounded-card\"\n style={{\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <GitBranch\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </span>\n <div className=\"min-w-0\">\n <h1 className=\"text-2xl font-bold leading-tight text-text-primary\">\n <GradientText>{t('bigconsole.pipelines.list.heading', 'Pipelines')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.pipelines.list.subtitle',\n 'Create and manage sequential parser chains for data transformation'\n )}\n </p>\n </div>\n </div>\n\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.PIPELINE_CREATE} deniedBehavior=\"disable\">\n <Button\n onClick={handleCreatePipeline}\n className=\"w-full shrink-0 min-h-[var(--size-controlHeight-md)] sm:w-auto\"\n >\n <Plus className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.actions.createPipeline', 'Create Pipeline')}\n </Button>\n </PermissionButton>\n </div>\n </header>\n );\n\n // Error state — keep the header so the page never loses its context.\n if (error) {\n return (\n <div className=\"min-h-screen bg-bg-canvas\">\n {pageHeader}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Section\n tone=\"danger\"\n headingLevel={2}\n title={t('bigconsole.pipelines.errors.loadListTitle', 'Failed to load Pipelines')}\n description={error.message}\n icon={<AlertCircle className=\"h-icon-sm w-icon-sm\" />}\n actions={\n <Button size=\"sm\" onClick={() => refetch()}>\n {t('bigconsole.pipelines.actions.tryAgain', 'Try Again')}\n </Button>\n }\n data-testid=\"pipelines-error\"\n >\n <p className=\"text-sm text-text-secondary\">\n Nothing was changed. Retry once the console service is reachable again.\n </p>\n </Section>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"min-h-screen bg-bg-canvas\">\n {pageHeader}\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <SectionStack>\n <PagePurpose className=\"max-w-[75ch]\">\n {t(\n 'bigconsole.pipelines.list.purpose',\n 'Pipelines chain parsers and data sinks into a repeatable flow — they take raw input, run it through your parsers, and route the structured result into a sink. Use them to turn messy logs, files, or API payloads into clean, queryable data your dashboards can use.'\n )}\n </PagePurpose>\n\n {/* Toolbar — `bare` in the ladder: filters + search grouped so the eye\n reads one control row instead of two floating stripes. Written with\n `sectionSurfaceClasses` rather than <Section> because the block has\n no visible heading (see the ticket note on Section's required\n `title` prop). */}\n <section\n aria-label=\"Filter and search pipelines\"\n data-testid=\"pipelines-toolbar\"\n data-section-emphasis=\"bare\"\n className={sectionSurfaceClasses('bare', 'neutral', 'none')}\n >\n <div className=\"flex flex-col gap-control-gap md:flex-row md:items-center md:justify-between\">\n {/* `min-w-0`: the pills are `shrink-0`, so without it this scroller\n refuses to shrink in the md row and pushes the search field out. */}\n <div\n role=\"group\"\n aria-label=\"Filter by status\"\n className=\"flex min-w-0 max-w-full items-center gap-1 overflow-x-auto rounded-card bg-bg-sunken p-1\"\n >\n {statusOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n aria-pressed={statusFilter === option.value}\n onClick={() => setStatusFilter(option.value)}\n className={`shrink-0 whitespace-nowrap rounded-button text-sm font-medium motion-safe:transition-colors ${SECTION_FOCUS_RING}`}\n style={{\n minHeight: 'var(--size-controlHeight-md)',\n padding: '0 var(--space-formGap)',\n border: 'none',\n cursor: 'pointer',\n backgroundColor: statusFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color:\n statusFilter === option.value ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n boxShadow: statusFilter === option.value ? 'var(--shadow-elevation-1)' : 'none',\n }}\n >\n {option.label}\n </button>\n ))}\n </div>\n\n <div className=\"relative w-full md:max-w-[320px]\">\n <Search\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n aria-label={t('bigconsole.pipelines.list.searchPlaceholder', 'Search pipelines...')}\n placeholder={t('bigconsole.pipelines.list.searchPlaceholder', 'Search pipelines...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n </section>\n\n {/* Results — the one primary block on this route. */}\n <Section\n emphasis=\"primary\"\n headingLevel={2}\n title=\"Your pipelines\"\n description=\"Open one to review its stages, or run a quick test against sample input.\"\n meta={\n !loading || pipelines.length > 0 ? (\n <span className=\"rounded-pill bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {filteredPipelines.length}\n {filteredPipelines.length === pipelines.length ? '' : ` of ${pipelines.length}`}\n </span>\n ) : null\n }\n data-testid=\"pipelines-results\"\n >\n {/* Loading state */}\n {loading && pipelines.length === 0 && (\n <div className=\"flex items-center justify-center py-12\" role=\"status\">\n <div className=\"text-center\">\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p className=\"text-sm text-text-muted\">\n {t('bigconsole.pipelines.list.loading', 'Loading pipelines...')}\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state — nothing created yet (onboarding). */}\n {!loading && pipelines.length === 0 && (\n <div data-testid=\"pipelines-empty\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('bigconsole.pipelines.list.emptyTitle', 'No Pipelines yet')}\n description={t(\n 'bigconsole.pipelines.list.emptyDescription',\n 'Create a pipeline to chain parsers together for sequential data transformation. Each stage processes the output of the previous stage.'\n )}\n action={\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.PIPELINE_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreatePipeline} className=\"min-h-[var(--size-controlHeight-md)]\">\n <Plus className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.actions.createPipeline', 'Create Pipeline')}\n </Button>\n </PermissionButton>\n }\n />\n </div>\n )}\n\n {/* No results state — a filter problem, not an onboarding problem. */}\n {!loading && filteredPipelines.length === 0 && pipelines.length > 0 && (\n <Section\n emphasis=\"muted\"\n tone=\"info\"\n padding=\"compact\"\n headingLevel={3}\n title={t('bigconsole.pipelines.list.noResultsTitle', 'No matching pipelines')}\n description={t('bigconsole.pipelines.list.noResultsDescription', 'No pipelines match your filters')}\n actions={\n <Button size=\"sm\" variant=\"secondary\" onClick={handleClearFilters}>\n Clear filters\n </Button>\n }\n data-testid=\"pipelines-no-results\"\n />\n )}\n\n {/* Pipeline Grid */}\n {filteredPipelines.length > 0 && (\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2 xl:grid-cols-3\">\n {filteredPipelines.map((pipeline) => (\n <PipelineCard\n key={pipeline.id}\n pipeline={pipeline}\n onView={handleViewPipeline}\n onEdit={canUpdate ? handleEditPipeline : undefined}\n onTest={canTest ? handleTestPipeline : undefined}\n onDelete={canDelete ? handleDeleteClick : undefined}\n />\n ))}\n </div>\n )}\n </Section>\n </SectionStack>\n </div>\n\n {/* Delete Dialog */}\n {currentPipeline && (\n <PipelineDeleteDialog\n pipeline={currentPipeline}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default PipelinesPage;\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { memo as e, useCallback as t, useEffect as n, useState as r } from "react";
2
2
  import { RotateCcw as i, Save as a, Settings as o } from "lucide-react";
3
- import { useI18n as s } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
4
- import { AuroraBackground as c, EmphasisPanel as l, GradientText as u, PagePurpose as d } from "@burdenoff/fe-libs/ui";
5
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
3
+ import { AuroraBackground as s, EmphasisPanel as c, GradientText as l, PagePurpose as u } from "@burdenoff/fe-libs/ui";
4
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
+ import { useI18n as p } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
6
  //#region src/bigconsole/pages/SettingsPage.tsx
7
7
  var m = "bigconsole-settings", h = {
8
8
  defaultRefreshInterval: 0,
@@ -28,7 +28,7 @@ function _(e) {
28
28
  localStorage.setItem(m, JSON.stringify(e));
29
29
  }
30
30
  var v = e(function() {
31
- let { t: e } = s(), [m, v] = r(g), [y, b] = r(!1);
31
+ let { t: e } = p(), [m, v] = r(g), [y, b] = r(!1);
32
32
  n(() => {
33
33
  if (y) {
34
34
  let e = setTimeout(() => b(!1), 2e3);
@@ -71,19 +71,19 @@ var v = e(function() {
71
71
  marginBottom: "var(--space-sectionGap)",
72
72
  boxShadow: "var(--shadow-pop)"
73
73
  };
74
- return /* @__PURE__ */ f("div", {
74
+ return /* @__PURE__ */ d("div", {
75
75
  style: {
76
76
  minHeight: "100vh",
77
77
  backgroundColor: "var(--color-bg-canvas)"
78
78
  },
79
- children: /* @__PURE__ */ p("div", {
79
+ children: /* @__PURE__ */ f("div", {
80
80
  style: {
81
81
  padding: "var(--space-pagePadding)",
82
82
  maxWidth: 720,
83
83
  margin: "0 auto"
84
84
  },
85
85
  children: [
86
- /* @__PURE__ */ p("div", {
86
+ /* @__PURE__ */ f("div", {
87
87
  className: "relative overflow-hidden rounded-card border border-border-seam bg-gloss-card p-6",
88
88
  style: {
89
89
  display: "flex",
@@ -94,25 +94,25 @@ var v = e(function() {
94
94
  gap: "var(--space-formGap)"
95
95
  },
96
96
  children: [
97
- /* @__PURE__ */ f(c, { intensity: "subtle" }),
98
- /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ p("div", {
97
+ /* @__PURE__ */ d(s, { intensity: "subtle" }),
98
+ /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ f("div", {
99
99
  style: {
100
100
  display: "flex",
101
101
  alignItems: "center",
102
102
  gap: "var(--space-iconGap)"
103
103
  },
104
- children: [/* @__PURE__ */ f(o, {
104
+ children: [/* @__PURE__ */ d(o, {
105
105
  size: 24,
106
106
  style: { color: "var(--color-text-primary)" }
107
- }), /* @__PURE__ */ f("h1", {
107
+ }), /* @__PURE__ */ d("h1", {
108
108
  style: {
109
109
  fontSize: "var(--font-size-heading-h4)",
110
110
  fontWeight: "var(--font-weight-bold)",
111
111
  color: "var(--color-text-primary)"
112
112
  },
113
- children: /* @__PURE__ */ f(u, { children: e("bigconsole.settings.header.title", "Settings") })
113
+ children: /* @__PURE__ */ d(l, { children: e("bigconsole.settings.header.title", "Settings") })
114
114
  })]
115
- }), /* @__PURE__ */ f("p", {
115
+ }), /* @__PURE__ */ d("p", {
116
116
  style: {
117
117
  fontSize: "var(--font-size-body-md)",
118
118
  color: "var(--color-text-secondary)",
@@ -120,12 +120,12 @@ var v = e(function() {
120
120
  },
121
121
  children: e("bigconsole.settings.header.subtitle", "Configure BigConsole preferences")
122
122
  })] }),
123
- /* @__PURE__ */ p("div", {
123
+ /* @__PURE__ */ f("div", {
124
124
  style: {
125
125
  display: "flex",
126
126
  gap: 8
127
127
  },
128
- children: [/* @__PURE__ */ p("button", {
128
+ children: [/* @__PURE__ */ f("button", {
129
129
  onClick: C,
130
130
  style: {
131
131
  display: "flex",
@@ -140,11 +140,11 @@ var v = e(function() {
140
140
  cursor: "pointer"
141
141
  },
142
142
  children: [
143
- /* @__PURE__ */ f(i, { size: 14 }),
143
+ /* @__PURE__ */ d(i, { size: 14 }),
144
144
  " ",
145
145
  e("bigconsole.settings.actions.reset", "Reset")
146
146
  ]
147
- }), /* @__PURE__ */ p("button", {
147
+ }), /* @__PURE__ */ f("button", {
148
148
  onClick: S,
149
149
  style: {
150
150
  display: "flex",
@@ -161,7 +161,7 @@ var v = e(function() {
161
161
  transition: "background-color 200ms"
162
162
  },
163
163
  children: [
164
- /* @__PURE__ */ f(a, { size: 14 }),
164
+ /* @__PURE__ */ d(a, { size: 14 }),
165
165
  " ",
166
166
  y ? e("bigconsole.settings.actions.savedLocally", "Saved locally") : e("bigconsole.settings.actions.saveLocally", "Save locally")
167
167
  ]
@@ -169,13 +169,13 @@ var v = e(function() {
169
169
  })
170
170
  ]
171
171
  }),
172
- /* @__PURE__ */ f(d, {
172
+ /* @__PURE__ */ d(u, {
173
173
  className: "mb-[var(--space-sectionGap)]",
174
174
  children: e("bigconsole.settings.purpose", "Settings control the defaults BigConsole applies everywhere — how new dashboards are laid out, how aggressively widget data is cached, and how the UI is displayed. Tune these once to match how your team works; they apply across every dashboard you build. These preferences are saved locally in this browser until the backend settings API is available.")
175
175
  }),
176
- /* @__PURE__ */ p(l, {
176
+ /* @__PURE__ */ f(c, {
177
177
  className: "mb-[var(--space-sectionGap)] p-[var(--space-cardPadding)]",
178
- children: [/* @__PURE__ */ f("h2", {
178
+ children: [/* @__PURE__ */ d("h2", {
179
179
  style: {
180
180
  fontSize: "var(--font-size-body-md)",
181
181
  fontWeight: "var(--font-weight-semibold)",
@@ -183,19 +183,19 @@ var v = e(function() {
183
183
  marginBottom: 16
184
184
  },
185
185
  children: e("bigconsole.settings.dashboardDefaults.title", "Dashboard Defaults")
186
- }), /* @__PURE__ */ p("div", {
186
+ }), /* @__PURE__ */ f("div", {
187
187
  style: {
188
188
  display: "grid",
189
189
  gap: 16
190
190
  },
191
191
  children: [
192
- /* @__PURE__ */ p("div", { children: [
193
- /* @__PURE__ */ f("label", {
192
+ /* @__PURE__ */ f("div", { children: [
193
+ /* @__PURE__ */ d("label", {
194
194
  htmlFor: "grid-cols",
195
195
  style: T,
196
196
  children: e("bigconsole.settings.dashboardDefaults.gridColumns.label", "Grid Columns")
197
197
  }),
198
- /* @__PURE__ */ f("input", {
198
+ /* @__PURE__ */ d("input", {
199
199
  id: "grid-cols",
200
200
  type: "number",
201
201
  min: 4,
@@ -204,18 +204,18 @@ var v = e(function() {
204
204
  onChange: (e) => x("defaultGridColumns", parseInt(e.target.value) || 12),
205
205
  style: w
206
206
  }),
207
- /* @__PURE__ */ f("p", {
207
+ /* @__PURE__ */ d("p", {
208
208
  style: E,
209
209
  children: e("bigconsole.settings.dashboardDefaults.gridColumns.help", "Number of columns in the dashboard grid (4-24)")
210
210
  })
211
211
  ] }),
212
- /* @__PURE__ */ p("div", { children: [
213
- /* @__PURE__ */ f("label", {
212
+ /* @__PURE__ */ f("div", { children: [
213
+ /* @__PURE__ */ d("label", {
214
214
  htmlFor: "widget-height",
215
215
  style: T,
216
216
  children: e("bigconsole.settings.dashboardDefaults.widgetHeight.label", "Default Widget Height")
217
217
  }),
218
- /* @__PURE__ */ f("input", {
218
+ /* @__PURE__ */ d("input", {
219
219
  id: "widget-height",
220
220
  type: "number",
221
221
  min: 2,
@@ -224,50 +224,50 @@ var v = e(function() {
224
224
  onChange: (e) => x("defaultWidgetHeight", parseInt(e.target.value) || 4),
225
225
  style: w
226
226
  }),
227
- /* @__PURE__ */ f("p", {
227
+ /* @__PURE__ */ d("p", {
228
228
  style: E,
229
229
  children: e("bigconsole.settings.dashboardDefaults.widgetHeight.help", "Default height units for new widgets (2-12)")
230
230
  })
231
231
  ] }),
232
- /* @__PURE__ */ p("div", { children: [
233
- /* @__PURE__ */ f("label", {
232
+ /* @__PURE__ */ f("div", { children: [
233
+ /* @__PURE__ */ d("label", {
234
234
  htmlFor: "refresh-interval",
235
235
  style: T,
236
236
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.label", "Auto-Refresh Interval (seconds)")
237
237
  }),
238
- /* @__PURE__ */ p("select", {
238
+ /* @__PURE__ */ f("select", {
239
239
  id: "refresh-interval",
240
240
  value: m.defaultRefreshInterval,
241
241
  onChange: (e) => x("defaultRefreshInterval", parseInt(e.target.value)),
242
242
  style: w,
243
243
  children: [
244
- /* @__PURE__ */ f("option", {
244
+ /* @__PURE__ */ d("option", {
245
245
  value: 0,
246
246
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.disabled", "Disabled")
247
247
  }),
248
- /* @__PURE__ */ f("option", {
248
+ /* @__PURE__ */ d("option", {
249
249
  value: 10,
250
250
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.seconds10", "10 seconds")
251
251
  }),
252
- /* @__PURE__ */ f("option", {
252
+ /* @__PURE__ */ d("option", {
253
253
  value: 30,
254
254
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.seconds30", "30 seconds")
255
255
  }),
256
- /* @__PURE__ */ f("option", {
256
+ /* @__PURE__ */ d("option", {
257
257
  value: 60,
258
258
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.minute1", "1 minute")
259
259
  }),
260
- /* @__PURE__ */ f("option", {
260
+ /* @__PURE__ */ d("option", {
261
261
  value: 300,
262
262
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.minutes5", "5 minutes")
263
263
  }),
264
- /* @__PURE__ */ f("option", {
264
+ /* @__PURE__ */ d("option", {
265
265
  value: 600,
266
266
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.minutes10", "10 minutes")
267
267
  })
268
268
  ]
269
269
  }),
270
- /* @__PURE__ */ f("p", {
270
+ /* @__PURE__ */ d("p", {
271
271
  style: E,
272
272
  children: e("bigconsole.settings.dashboardDefaults.refreshInterval.help", "How often widgets refresh their data automatically")
273
273
  })
@@ -275,9 +275,9 @@ var v = e(function() {
275
275
  ]
276
276
  })]
277
277
  }),
278
- /* @__PURE__ */ p("div", {
278
+ /* @__PURE__ */ f("div", {
279
279
  style: D,
280
- children: [/* @__PURE__ */ f("h2", {
280
+ children: [/* @__PURE__ */ d("h2", {
281
281
  style: {
282
282
  fontSize: "var(--font-size-body-md)",
283
283
  fontWeight: "var(--font-weight-semibold)",
@@ -285,24 +285,24 @@ var v = e(function() {
285
285
  marginBottom: 16
286
286
  },
287
287
  children: e("bigconsole.settings.cache.title", "Cache")
288
- }), /* @__PURE__ */ p("div", {
288
+ }), /* @__PURE__ */ f("div", {
289
289
  style: {
290
290
  display: "grid",
291
291
  gap: 16
292
292
  },
293
- children: [/* @__PURE__ */ p("div", {
293
+ children: [/* @__PURE__ */ f("div", {
294
294
  style: {
295
295
  display: "flex",
296
296
  alignItems: "center",
297
297
  justifyContent: "space-between"
298
298
  },
299
- children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
299
+ children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
300
300
  style: T,
301
301
  children: e("bigconsole.settings.cache.enable.label", "Enable Cache")
302
- }), /* @__PURE__ */ f("p", {
302
+ }), /* @__PURE__ */ d("p", {
303
303
  style: E,
304
304
  children: e("bigconsole.settings.cache.enable.help", "Cache widget data to reduce API calls")
305
- })] }), /* @__PURE__ */ f("button", {
305
+ })] }), /* @__PURE__ */ d("button", {
306
306
  onClick: () => x("cacheEnabled", !m.cacheEnabled),
307
307
  role: "switch",
308
308
  "aria-checked": m.cacheEnabled,
@@ -317,7 +317,7 @@ var v = e(function() {
317
317
  position: "relative",
318
318
  transition: "background-color 200ms"
319
319
  },
320
- children: /* @__PURE__ */ f("div", { style: {
320
+ children: /* @__PURE__ */ d("div", { style: {
321
321
  width: 18,
322
322
  height: 18,
323
323
  borderRadius: "50%",
@@ -328,13 +328,13 @@ var v = e(function() {
328
328
  transition: "left 200ms"
329
329
  } })
330
330
  })]
331
- }), m.cacheEnabled && /* @__PURE__ */ p("div", { children: [
332
- /* @__PURE__ */ f("label", {
331
+ }), m.cacheEnabled && /* @__PURE__ */ f("div", { children: [
332
+ /* @__PURE__ */ d("label", {
333
333
  htmlFor: "cache-ttl",
334
334
  style: T,
335
335
  children: e("bigconsole.settings.cache.ttl.label", "Cache TTL (seconds)")
336
336
  }),
337
- /* @__PURE__ */ f("input", {
337
+ /* @__PURE__ */ d("input", {
338
338
  id: "cache-ttl",
339
339
  type: "number",
340
340
  min: 30,
@@ -343,16 +343,16 @@ var v = e(function() {
343
343
  onChange: (e) => x("cacheTTLSeconds", parseInt(e.target.value) || 300),
344
344
  style: w
345
345
  }),
346
- /* @__PURE__ */ f("p", {
346
+ /* @__PURE__ */ d("p", {
347
347
  style: E,
348
348
  children: e("bigconsole.settings.cache.ttl.help", "How long cached data is considered fresh (30-3600)")
349
349
  })
350
350
  ] })]
351
351
  })]
352
352
  }),
353
- /* @__PURE__ */ p("div", {
353
+ /* @__PURE__ */ f("div", {
354
354
  style: D,
355
- children: [/* @__PURE__ */ f("h2", {
355
+ children: [/* @__PURE__ */ d("h2", {
356
356
  style: {
357
357
  fontSize: "var(--font-size-body-md)",
358
358
  fontWeight: "var(--font-weight-semibold)",
@@ -360,25 +360,25 @@ var v = e(function() {
360
360
  marginBottom: 16
361
361
  },
362
362
  children: e("bigconsole.settings.display.title", "Display")
363
- }), /* @__PURE__ */ p("div", {
363
+ }), /* @__PURE__ */ f("div", {
364
364
  style: {
365
365
  display: "grid",
366
366
  gap: 16
367
367
  },
368
368
  children: [
369
- /* @__PURE__ */ p("div", {
369
+ /* @__PURE__ */ f("div", {
370
370
  style: {
371
371
  display: "flex",
372
372
  alignItems: "center",
373
373
  justifyContent: "space-between"
374
374
  },
375
- children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
375
+ children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
376
376
  style: T,
377
377
  children: e("bigconsole.settings.display.widgetBorders.label", "Show Widget Borders")
378
- }), /* @__PURE__ */ f("p", {
378
+ }), /* @__PURE__ */ d("p", {
379
379
  style: E,
380
380
  children: e("bigconsole.settings.display.widgetBorders.help", "Display borders around widgets in dashboards")
381
- })] }), /* @__PURE__ */ f("button", {
381
+ })] }), /* @__PURE__ */ d("button", {
382
382
  onClick: () => x("showWidgetBorders", !m.showWidgetBorders),
383
383
  role: "switch",
384
384
  "aria-checked": m.showWidgetBorders,
@@ -393,7 +393,7 @@ var v = e(function() {
393
393
  position: "relative",
394
394
  transition: "background-color 200ms"
395
395
  },
396
- children: /* @__PURE__ */ f("div", { style: {
396
+ children: /* @__PURE__ */ d("div", { style: {
397
397
  width: 18,
398
398
  height: 18,
399
399
  borderRadius: "50%",
@@ -405,19 +405,19 @@ var v = e(function() {
405
405
  } })
406
406
  })]
407
407
  }),
408
- /* @__PURE__ */ p("div", {
408
+ /* @__PURE__ */ f("div", {
409
409
  style: {
410
410
  display: "flex",
411
411
  alignItems: "center",
412
412
  justifyContent: "space-between"
413
413
  },
414
- children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
414
+ children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
415
415
  style: T,
416
416
  children: e("bigconsole.settings.display.compactMode.label", "Compact Mode")
417
- }), /* @__PURE__ */ f("p", {
417
+ }), /* @__PURE__ */ d("p", {
418
418
  style: E,
419
419
  children: e("bigconsole.settings.display.compactMode.help", "Reduce padding and spacing for more content")
420
- })] }), /* @__PURE__ */ f("button", {
420
+ })] }), /* @__PURE__ */ d("button", {
421
421
  onClick: () => x("compactMode", !m.compactMode),
422
422
  role: "switch",
423
423
  "aria-checked": m.compactMode,
@@ -432,7 +432,7 @@ var v = e(function() {
432
432
  position: "relative",
433
433
  transition: "background-color 200ms"
434
434
  },
435
- children: /* @__PURE__ */ f("div", { style: {
435
+ children: /* @__PURE__ */ d("div", { style: {
436
436
  width: 18,
437
437
  height: 18,
438
438
  borderRadius: "50%",
@@ -444,19 +444,19 @@ var v = e(function() {
444
444
  } })
445
445
  })]
446
446
  }),
447
- /* @__PURE__ */ p("div", {
447
+ /* @__PURE__ */ f("div", {
448
448
  style: {
449
449
  display: "flex",
450
450
  alignItems: "center",
451
451
  justifyContent: "space-between"
452
452
  },
453
- children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
453
+ children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("label", {
454
454
  style: T,
455
455
  children: e("bigconsole.settings.display.animations.label", "Animations")
456
- }), /* @__PURE__ */ f("p", {
456
+ }), /* @__PURE__ */ d("p", {
457
457
  style: E,
458
458
  children: e("bigconsole.settings.display.animations.help", "Enable transition animations and effects")
459
- })] }), /* @__PURE__ */ f("button", {
459
+ })] }), /* @__PURE__ */ d("button", {
460
460
  onClick: () => x("animationsEnabled", !m.animationsEnabled),
461
461
  role: "switch",
462
462
  "aria-checked": m.animationsEnabled,
@@ -471,7 +471,7 @@ var v = e(function() {
471
471
  position: "relative",
472
472
  transition: "background-color 200ms"
473
473
  },
474
- children: /* @__PURE__ */ f("div", { style: {
474
+ children: /* @__PURE__ */ d("div", { style: {
475
475
  width: 18,
476
476
  height: 18,
477
477
  borderRadius: "50%",