@burdenoff/microfe-bigconsole 2026.805.3 → 2026.812.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/dist/bigconsole/components/DrilldownDashboardRenderer.js +118 -106
  2. package/dist/bigconsole/components/DrilldownDashboardRenderer.js.map +1 -1
  3. package/dist/bigconsole/components/DrilldownModal.js +54 -50
  4. package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
  5. package/dist/bigconsole/components/builder/BuilderCanvas.js +2 -2
  6. package/dist/bigconsole/components/builder/BuilderCanvas.js.map +1 -1
  7. package/dist/bigconsole/components/builder/BuilderTopbar.js +3 -3
  8. package/dist/bigconsole/components/builder/BuilderTopbar.js.map +1 -1
  9. package/dist/bigconsole/components/builder/inspector/AdvancedSection.js +24 -25
  10. package/dist/bigconsole/components/builder/inspector/AdvancedSection.js.map +1 -1
  11. package/dist/bigconsole/components/builder/inspector/AppearanceSection.js +40 -29
  12. package/dist/bigconsole/components/builder/inspector/AppearanceSection.js.map +1 -1
  13. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +135 -97
  14. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
  15. package/dist/bigconsole/components/builder/inspector/GeneralSection.js +58 -44
  16. package/dist/bigconsole/components/builder/inspector/GeneralSection.js.map +1 -1
  17. package/dist/bigconsole/components/common/Section.js +70 -0
  18. package/dist/bigconsole/components/common/Section.js.map +1 -0
  19. package/dist/bigconsole/components/common/index.js +2 -0
  20. package/dist/bigconsole/components/common/sectionStyles.js +42 -0
  21. package/dist/bigconsole/components/common/sectionStyles.js.map +1 -0
  22. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +209 -193
  23. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  24. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +213 -231
  25. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  26. package/dist/bigconsole/components/dashboard/DashboardGrid.js +12 -18
  27. package/dist/bigconsole/components/dashboard/DashboardGrid.js.map +1 -1
  28. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +109 -102
  29. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  30. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +81 -70
  31. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  32. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +125 -159
  33. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js.map +1 -1
  34. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +25 -23
  35. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
  36. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +3 -3
  37. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
  38. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +5 -3
  39. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
  40. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +170 -284
  41. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  42. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +147 -151
  43. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  44. package/dist/bigconsole/components/dashboard/LiveBoardBanner.js +45 -53
  45. package/dist/bigconsole/components/dashboard/LiveBoardBanner.js.map +1 -1
  46. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +157 -148
  47. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
  48. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +17 -8
  49. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
  50. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +101 -95
  51. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
  52. package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js +20 -18
  53. package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js.map +1 -1
  54. package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js +26 -58
  55. package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js.map +1 -1
  56. package/dist/bigconsole/components/dashboard/WidgetPalette.js +307 -231
  57. package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
  58. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +29 -29
  59. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  60. package/dist/bigconsole/components/datasink/DataSinkCard.js +78 -79
  61. package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
  62. package/dist/bigconsole/components/datasink/DataSinkDataViewer.js +33 -34
  63. package/dist/bigconsole/components/datasink/DataSinkDataViewer.js.map +1 -1
  64. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +79 -56
  65. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
  66. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +75 -65
  67. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
  68. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +1 -1
  69. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
  70. package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +20 -19
  71. package/dist/bigconsole/components/datasink/DataSinkTableViewer.js.map +1 -1
  72. package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js +127 -171
  73. package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js.map +1 -1
  74. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +263 -243
  75. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  76. package/dist/bigconsole/components/datasink/LinkedParsersPanel.js +65 -66
  77. package/dist/bigconsole/components/datasink/LinkedParsersPanel.js.map +1 -1
  78. package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +121 -127
  79. package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
  80. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +33 -26
  81. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
  82. package/dist/bigconsole/components/datasink/SetupStateBadge.js +3 -3
  83. package/dist/bigconsole/components/datasink/SetupStateBadge.js.map +1 -1
  84. package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +95 -95
  85. package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
  86. package/dist/bigconsole/components/parser/DataSinkSelector.js +154 -123
  87. package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
  88. package/dist/bigconsole/components/parser/ExpressionEditor.js +3 -3
  89. package/dist/bigconsole/components/parser/ExpressionEditor.js.map +1 -1
  90. package/dist/bigconsole/components/parser/ImportParserDialog.js +235 -275
  91. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  92. package/dist/bigconsole/components/parser/ParserCard.js +133 -114
  93. package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
  94. package/dist/bigconsole/components/parser/ParserSelector.js +191 -174
  95. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  96. package/dist/bigconsole/components/parser/ParserStatusBadge.js +2 -2
  97. package/dist/bigconsole/components/parser/ParserStatusBadge.js.map +1 -1
  98. package/dist/bigconsole/components/parser/ParserTypeBadge.js +4 -4
  99. package/dist/bigconsole/components/parser/ParserTypeBadge.js.map +1 -1
  100. package/dist/bigconsole/components/pipeline/PipelineCard.js +134 -89
  101. package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
  102. package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +77 -64
  103. package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
  104. package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +7 -10
  105. package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
  106. package/dist/bigconsole/components/preview/AiPreviewContent.js +31 -32
  107. package/dist/bigconsole/components/preview/AiPreviewContent.js.map +1 -1
  108. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +152 -106
  109. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
  110. package/dist/bigconsole/components/preview/AiPreviewPanel.js +193 -152
  111. package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
  112. package/dist/bigconsole/components/preview/previewShared.js +41 -23
  113. package/dist/bigconsole/components/preview/previewShared.js.map +1 -1
  114. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +342 -308
  115. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  116. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +262 -238
  117. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  118. package/dist/bigconsole/components/widgets/PropertiesPanel.js +783 -867
  119. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  120. package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js +7 -5
  121. package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js.map +1 -1
  122. package/dist/bigconsole/components/widgets/WidgetHeader.js +7 -8
  123. package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
  124. package/dist/bigconsole/components/widgets/WidgetRegistry.js +4 -4
  125. package/dist/bigconsole/components/widgets/WidgetRegistry.js.map +1 -1
  126. package/dist/bigconsole/components/widgets/WidgetWrapper.js +8 -7
  127. package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
  128. package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js +1 -1
  129. package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js.map +1 -1
  130. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +2 -2
  131. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
  132. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +11 -5
  133. package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
  134. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +19 -15
  135. package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
  136. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +154 -102
  137. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  138. package/dist/bigconsole/components/widgets/gauge/CircularGauge.js +36 -32
  139. package/dist/bigconsole/components/widgets/gauge/CircularGauge.js.map +1 -1
  140. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +85 -60
  141. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
  142. package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js +64 -35
  143. package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js.map +1 -1
  144. package/dist/bigconsole/components/widgets/gauge/LinearGauge.js +46 -45
  145. package/dist/bigconsole/components/widgets/gauge/LinearGauge.js.map +1 -1
  146. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +35 -24
  147. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
  148. package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js +2 -2
  149. package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js.map +1 -1
  150. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +4 -4
  151. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  152. package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +153 -90
  153. package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
  154. package/dist/bigconsole/components/widgets/list/ListConfig.js +8 -2
  155. package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
  156. package/dist/bigconsole/components/widgets/list/ListItem.js +1 -1
  157. package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
  158. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +1 -1
  159. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
  160. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +14 -4
  161. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
  162. package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js +112 -89
  163. package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
  164. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +21 -13
  165. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
  166. package/dist/bigconsole/components/widgets/metric-card/index.js +4 -4
  167. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +3 -3
  168. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
  169. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +34 -25
  170. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
  171. package/dist/bigconsole/components/widgets/progress/ProgressWidget.js +129 -114
  172. package/dist/bigconsole/components/widgets/progress/ProgressWidget.js.map +1 -1
  173. package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +3 -3
  174. package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
  175. package/dist/bigconsole/components/widgets/states/EmptyState.js +6 -4
  176. package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
  177. package/dist/bigconsole/components/widgets/states/ErrorState.js +7 -5
  178. package/dist/bigconsole/components/widgets/states/ErrorState.js.map +1 -1
  179. package/dist/bigconsole/components/widgets/states/LoadingState.js +5 -4
  180. package/dist/bigconsole/components/widgets/states/LoadingState.js.map +1 -1
  181. package/dist/bigconsole/components/widgets/table/TableConfig.js +10 -4
  182. package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
  183. package/dist/bigconsole/components/widgets/table/TableHeader.js +1 -1
  184. package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
  185. package/dist/bigconsole/components/widgets/table/TableWidget.js +1 -1
  186. package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
  187. package/dist/bigconsole/components/widgets/text-widget/TextWidget.js +1 -1
  188. package/dist/bigconsole/components/widgets/text-widget/TextWidget.js.map +1 -1
  189. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +3 -3
  190. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
  191. package/dist/bigconsole/components/widgets/utils/conditionalFormat.js +2 -2
  192. package/dist/bigconsole/components/widgets/utils/conditionalFormat.js.map +1 -1
  193. package/dist/bigconsole/components/widgets/utils/targetProgress.js +13 -0
  194. package/dist/bigconsole/components/widgets/utils/targetProgress.js.map +1 -0
  195. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +112 -85
  196. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  197. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +28 -20
  198. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
  199. package/dist/bigconsole/components/workflow/WorkflowCard.js +92 -77
  200. package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
  201. package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +70 -51
  202. package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
  203. package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js +16 -17
  204. package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js.map +1 -1
  205. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +6 -4
  206. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
  207. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +360 -338
  208. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  209. package/dist/bigconsole/hooks/useModalFocusTrap.js +53 -0
  210. package/dist/bigconsole/hooks/useModalFocusTrap.js.map +1 -0
  211. package/dist/bigconsole/pages/DashboardBuilderPage.js +209 -203
  212. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  213. package/dist/bigconsole/pages/DashboardViewPage.js +126 -120
  214. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  215. package/dist/bigconsole/pages/DashboardsPage.js +838 -800
  216. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  217. package/dist/bigconsole/pages/DataParsersPage.js +263 -315
  218. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  219. package/dist/bigconsole/pages/DataSinkBuilderPage.js +301 -341
  220. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  221. package/dist/bigconsole/pages/DataSinkViewPage.js +346 -339
  222. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  223. package/dist/bigconsole/pages/DataSinksPage.js +356 -458
  224. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  225. package/dist/bigconsole/pages/DataSourcesPage.js +7 -2
  226. package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
  227. package/dist/bigconsole/pages/HomePage.js +186 -193
  228. package/dist/bigconsole/pages/HomePage.js.map +1 -1
  229. package/dist/bigconsole/pages/InsightsPage.js +887 -740
  230. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  231. package/dist/bigconsole/pages/ParserBuilderPage.js +679 -637
  232. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  233. package/dist/bigconsole/pages/ParserViewPage.js +368 -342
  234. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  235. package/dist/bigconsole/pages/PipelineBuilderPage.js +537 -444
  236. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  237. package/dist/bigconsole/pages/PipelineViewPage.js +412 -377
  238. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  239. package/dist/bigconsole/pages/PipelinesPage.js +248 -298
  240. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  241. package/dist/bigconsole/pages/WidgetDemoPage.js +251 -153
  242. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  243. package/dist/bigconsole/pages/WorkflowViewPage.js +381 -371
  244. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  245. package/dist/bigconsole/pages/WorkflowsPage.js +171 -286
  246. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  247. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ParserSelector.js","names":[],"sources":["../../../../src/bigconsole/components/parser/ParserSelector.tsx"],"sourcesContent":["/**\n * Parser Selector\n *\n * Dropdown component for selecting a parser.\n * Shows both dashboard-specific parsers and global parsers.\n */\n\nimport { memo, useState, useEffect, useCallback, Fragment, useMemo } from 'react';\nimport { Plus } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useParserOperations } from '../../hooks/useParserOperations';\nimport { useBuildPath } from '../../contexts';\nimport { ParserTypeBadge } from './ParserTypeBadge';\nimport { ParserStatusBadge } from './ParserStatusBadge';\nimport type { ParserType, ParserStatus } from '../../types';\n\n// Default console ID for global parsers\nconst DEFAULT_CONSOLE_ID = 'default';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserSelectorProps {\n /** Console ID */\n consoleId: string;\n /** Currently selected parser ID */\n value: string | null;\n /** Callback when selection changes */\n onChange: (id: string | null) => void;\n /** Filter by type */\n filterType?: ParserType;\n /** Filter by status */\n filterStatus?: ParserStatus;\n /** Filter by input DataSink key */\n filterInputSinkKey?: string | null;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Whether to show error state */\n error?: boolean;\n /** Error message to display */\n errorMessage?: string;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst ChevronDownIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\nconst GlobeIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 21a9 9 0 100-18 9 9 0 000 18z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M3.6 9h16.8M3.6 15h16.8\" />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 3a15 15 0 014 9 15 15 0 01-4 9 15 15 0 01-4-9 15 15 0 014-9z\"\n />\n </svg>\n);\n\n// ============================================================================\n// PARSER OPTION BUTTON\n// ============================================================================\n\ninterface ParserOptionButtonProps {\n parser: {\n id: string;\n name: string;\n description: string | null;\n type: 'jq' | 'jsonata';\n inputSinkKey: string;\n outputKey: string;\n status: 'active' | 'inactive';\n };\n isSelected: boolean;\n onSelect: (id: string) => void;\n isGlobal?: boolean;\n}\n\nconst ParserOptionButton = memo(function ParserOptionButton({\n parser,\n isSelected,\n onSelect,\n isGlobal = false,\n}: ParserOptionButtonProps) {\n const { t } = useI18n();\n return (\n <button\n type=\"button\"\n onClick={() => onSelect(parser.id)}\n className={`\n w-full px-3 py-2.5\n text-left\n hover:bg-bg-sunken\n transition-colors\n border-b border-border-default last:border-b-0\n ${isSelected ? 'bg-action-primary-bg/10' : ''}\n `}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n {/* Name and type */}\n <div className=\"flex items-center gap-2 mb-1\">\n <ParserTypeBadge type={parser.type} size=\"sm\" />\n <span className=\"text-sm font-medium text-text-primary truncate\">{parser.name}</span>\n {isGlobal && (\n <span className=\"inline-flex items-center gap-1 px-1.5 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\">\n <GlobeIcon className=\"w-3 h-3\" />\n {t('bigconsole.parsers.selector.globalBadge', 'Global')}\n </span>\n )}\n </div>\n\n {/* Description */}\n {parser.description && <p className=\"text-xs text-text-secondary line-clamp-1 mb-1\">{parser.description}</p>}\n\n {/* Data flow */}\n <div className=\"flex items-center gap-2 text-xs text-text-tertiary\">\n <span>\n {parser.inputSinkKey} → {parser.outputKey}\n </span>\n </div>\n </div>\n\n {/* Status badge */}\n <div>\n <ParserStatusBadge status={parser.status} size=\"sm\" showIcon={false} />\n </div>\n </div>\n </button>\n );\n});\n\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nexport const ParserSelector = memo(function ParserSelector({\n consoleId,\n value,\n onChange,\n filterType,\n filterStatus = 'active',\n filterInputSinkKey,\n placeholder,\n disabled = false,\n error = false,\n errorMessage,\n}: ParserSelectorProps) {\n const { t } = useI18n();\n const [isOpen, setIsOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n\n const resolvedPlaceholder = placeholder ?? t('bigconsole.parsers.selector.placeholder', 'Select a parser...');\n\n const buildPath = useBuildPath();\n\n // Determine if we need to fetch global parsers separately\n const isGlobalConsole = consoleId === DEFAULT_CONSOLE_ID;\n\n // Fetch dashboard-specific parsers\n const {\n parsers: dashboardParsers,\n loading: dashboardLoading,\n fetchParsers: fetchDashboardParsers,\n } = useParserOperations({\n consoleId,\n skipFetch: isGlobalConsole, // Skip if already fetching global\n });\n\n // Fetch global parsers (only if consoleId is not already 'default')\n const {\n parsers: globalParsers,\n loading: globalLoading,\n fetchParsers: fetchGlobalParsers,\n } = useParserOperations({\n consoleId: DEFAULT_CONSOLE_ID,\n skipFetch: isGlobalConsole, // Skip if consoleId is already 'default'\n });\n\n // Combine parsers: dashboard-specific + global (avoiding duplicates)\n const allParsers = useMemo(() => {\n if (isGlobalConsole) {\n // If we're already on global console, just return dashboard parsers\n return dashboardParsers;\n }\n\n // Combine both, with dashboard parsers first\n const parserIds = new Set(dashboardParsers.map((p) => p.id));\n const uniqueGlobalParsers = globalParsers.filter((p) => !parserIds.has(p.id));\n\n return [...dashboardParsers, ...uniqueGlobalParsers];\n }, [dashboardParsers, globalParsers, isGlobalConsole]);\n\n // Combined loading state\n const loading = dashboardLoading || globalLoading;\n\n // Filter parsers\n const filteredParsers = useMemo(() => {\n return allParsers.filter((p) => {\n // Filter by type if specified\n if (filterType && p.type !== filterType) return false;\n\n // Filter by status if specified\n if (filterStatus && p.status !== filterStatus) return false;\n\n // Filter by input DataSink key if specified\n if (filterInputSinkKey && p.inputSinkKey !== filterInputSinkKey) return false;\n\n // Filter by search query\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n return (\n p.name.toLowerCase().includes(query) ||\n p.description?.toLowerCase().includes(query) ||\n p.inputSinkKey.toLowerCase().includes(query) ||\n p.outputKey.toLowerCase().includes(query)\n );\n }\n\n return true;\n });\n }, [allParsers, filterType, filterStatus, filterInputSinkKey, searchQuery]);\n\n // Group parsers by scope for display\n const { dashboardScopedParsers, globalScopedParsers } = useMemo(() => {\n const dashboard = filteredParsers.filter((p) => p.consoleId !== DEFAULT_CONSOLE_ID);\n const global = filteredParsers.filter((p) => p.consoleId === DEFAULT_CONSOLE_ID);\n return { dashboardScopedParsers: dashboard, globalScopedParsers: global };\n }, [filteredParsers]);\n\n // Find selected parser\n const selectedParser = allParsers.find((p) => p.id === value);\n\n // Fetch parsers when console changes or DataSink filter changes\n useEffect(() => {\n if (consoleId) {\n fetchDashboardParsers({ type: filterType, status: filterStatus ?? undefined });\n\n // Also fetch global parsers if not already on global console\n if (!isGlobalConsole) {\n fetchGlobalParsers({ type: filterType, status: filterStatus ?? undefined });\n }\n }\n }, [\n consoleId,\n filterType,\n filterStatus,\n filterInputSinkKey,\n fetchDashboardParsers,\n fetchGlobalParsers,\n isGlobalConsole,\n ]);\n\n // Handle selection\n const handleSelect = useCallback(\n (id: string | null) => {\n onChange(id);\n setIsOpen(false);\n setSearchQuery('');\n },\n [onChange]\n );\n\n // Toggle dropdown\n const handleToggle = useCallback(() => {\n if (disabled) return;\n const next = !isOpen;\n // Refetch on open so a parser created via the \"Create new\" tab shows\n // up here without needing a full page reload.\n if (next) {\n void fetchDashboardParsers({ type: filterType, status: filterStatus ?? undefined });\n if (!isGlobalConsole) {\n void fetchGlobalParsers({ type: filterType, status: filterStatus ?? undefined });\n }\n }\n setIsOpen(next);\n }, [disabled, isOpen, fetchDashboardParsers, fetchGlobalParsers, filterType, filterStatus, isGlobalConsole]);\n\n // Close dropdown\n const handleClose = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n // Open the create-Parser page in a new tab so the current editing\n // context (e.g. an unsaved widget in the dashboard builder) is preserved.\n // Preserve the dashboard scope so the new parser is created for this\n // console rather than as a global parser.\n const handleCreateNew = useCallback(() => {\n setIsOpen(false);\n const path = isGlobalConsole ? '/parsers/new' : `/dashboards/${consoleId}/parsers/new`;\n window.open(buildPath(path), '_blank', 'noopener,noreferrer');\n }, [buildPath, consoleId, isGlobalConsole]);\n\n return (\n <div className=\"relative\">\n {/* Trigger button */}\n <button\n type=\"button\"\n onClick={handleToggle}\n disabled={disabled}\n className={`\n w-full\n px-3 py-2\n bg-bg-surface\n border rounded-md\n text-left\n flex items-center justify-between gap-2\n transition-colors\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-action-primary-bg cursor-pointer'}\n ${error ? 'border-status-error-border' : 'border-border-default'}\n ${isOpen ? 'border-action-primary-bg ring-2 ring-action-primary-bg/20' : ''}\n `}\n >\n <div className=\"flex-1 min-w-0\">\n {selectedParser ? (\n <div className=\"flex items-center gap-2\">\n <ParserTypeBadge type={selectedParser.type} size=\"sm\" />\n <span className=\"text-sm text-text-primary truncate\">{selectedParser.name}</span>\n </div>\n ) : (\n <span className=\"text-sm text-text-tertiary\">{resolvedPlaceholder}</span>\n )}\n </div>\n\n <ChevronDownIcon\n className={`w-4 h-4 text-text-secondary transition-transform ${isOpen ? 'transform rotate-180' : ''}`}\n />\n </button>\n\n {/* Error message */}\n {error && errorMessage && <p className=\"mt-1 text-xs text-status-error-text\">{errorMessage}</p>}\n\n {/* Dropdown */}\n {isOpen && (\n <Fragment>\n {/* Backdrop */}\n <div className=\"fixed inset-0 z-10\" onClick={handleClose} />\n\n {/* Dropdown content */}\n <div className=\"absolute left-0 right-0 top-full mt-1 z-20 bg-bg-surface border border-border-default rounded-md shadow-lg max-h-80 flex flex-col overflow-hidden\">\n {/* Search input */}\n <div className=\"p-2 border-b border-border-default\">\n <input\n type=\"text\"\n placeholder={t('bigconsole.parsers.selector.searchPlaceholder', 'Search parsers...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className={`\n w-full px-3 py-2\n bg-bg-sunken\n border border-border-default\n rounded-md\n text-sm text-text-primary\n placeholder-text-tertiary\n focus:outline-none\n focus:border-action-primary-bg\n focus:ring-2\n focus:ring-action-primary-bg/20\n `}\n />\n </div>\n\n {/* Options list */}\n <div className=\"overflow-y-auto flex-1\">\n {loading ? (\n <div className=\"p-4 text-center text-sm text-text-secondary\">\n {t('bigconsole.parsers.selector.loading', 'Loading parsers...')}\n </div>\n ) : filteredParsers.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-text-secondary\">\n {t('bigconsole.parsers.selector.empty', 'No parsers found')}\n </div>\n ) : (\n <Fragment>\n {/* None option */}\n <button\n type=\"button\"\n onClick={() => handleSelect(null)}\n className={`\n w-full px-3 py-2\n text-left text-sm\n hover:bg-bg-sunken\n transition-colors\n ${value === null ? 'bg-action-primary-bg/10 text-action-primary-bg' : 'text-text-secondary'}\n `}\n >\n <span className=\"italic\">{t('bigconsole.parsers.selector.none', 'None')}</span>\n </button>\n\n {/* Dashboard-scoped parsers section */}\n {dashboardScopedParsers.length > 0 && (\n <Fragment>\n <div className=\"px-3 py-1.5 bg-bg-sunken border-y border-border-default\">\n <span className=\"text-xs font-medium text-text-secondary uppercase tracking-wide\">\n {t('bigconsole.parsers.selector.dashboardParsers', 'Dashboard Parsers')}\n </span>\n </div>\n {dashboardScopedParsers.map((parser) => (\n <ParserOptionButton\n key={parser.id}\n parser={parser}\n isSelected={value === parser.id}\n onSelect={handleSelect}\n />\n ))}\n </Fragment>\n )}\n\n {/* Global parsers section */}\n {globalScopedParsers.length > 0 && (\n <Fragment>\n <div className=\"px-3 py-1.5 bg-bg-sunken border-y border-border-default\">\n <span className=\"text-xs font-medium text-text-secondary uppercase tracking-wide\">\n {t('bigconsole.parsers.selector.globalParsers', 'Global Parsers')}\n </span>\n </div>\n {globalScopedParsers.map((parser) => (\n <ParserOptionButton\n key={parser.id}\n parser={parser}\n isSelected={value === parser.id}\n onSelect={handleSelect}\n isGlobal\n />\n ))}\n </Fragment>\n )}\n </Fragment>\n )}\n </div>\n\n {/* Create new — persistent footer action (opens in a new tab) */}\n <div className=\"p-2 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={handleCreateNew}\n className=\"\n w-full flex items-center gap-2\n px-3 py-2\n text-sm font-medium text-action-primary-bg\n rounded-md\n hover:bg-action-primary-bg/10\n transition-colors\n \"\n >\n <Plus className=\"w-4 h-4\" />\n {t('bigconsole.parsers.selector.createNew', 'Create new parser')}\n </button>\n </div>\n </div>\n </Fragment>\n )}\n </div>\n );\n});\n\nexport default ParserSelector;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ParserSelector.js","names":[],"sources":["../../../../src/bigconsole/components/parser/ParserSelector.tsx"],"sourcesContent":["/**\n * Parser Selector\n *\n * Dropdown component for selecting a parser.\n * Shows both dashboard-specific parsers and global parsers.\n */\n\nimport { memo, useState, useEffect, useCallback, Fragment, useMemo } from 'react';\nimport { Plus } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useParserOperations } from '../../hooks/useParserOperations';\nimport { useBuildPath } from '../../contexts';\nimport { ParserTypeBadge } from './ParserTypeBadge';\nimport { ParserStatusBadge } from './ParserStatusBadge';\nimport { SECTION_FOCUS_RING } from '../common';\nimport type { ParserType, ParserStatus } from '../../types';\n\n// Default console ID for global parsers\nconst DEFAULT_CONSOLE_ID = 'default';\n\n/**\n * Group header inside the dropdown. This sunken, bordered, uppercase strip is the\n * module's section-header idiom at list scale — it is kept in step with the\n * `Section` primitive so a grouped dropdown reads like a grouped page.\n */\nconst GROUP_HEADER = 'sticky top-0 z-[1] bg-bg-sunken px-3 py-1.5 border-y border-[var(--color-border-default)]';\nconst GROUP_HEADER_LABEL = 'text-xs font-semibold uppercase tracking-wide text-text-secondary';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserSelectorProps {\n /** Console ID */\n consoleId: string;\n /** Currently selected parser ID */\n value: string | null;\n /** Callback when selection changes */\n onChange: (id: string | null) => void;\n /** Filter by type */\n filterType?: ParserType;\n /** Filter by status */\n filterStatus?: ParserStatus;\n /** Filter by input DataSink key */\n filterInputSinkKey?: string | null;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Whether to show error state */\n error?: boolean;\n /** Error message to display */\n errorMessage?: string;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst ChevronDownIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\nconst GlobeIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 21a9 9 0 100-18 9 9 0 000 18z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M3.6 9h16.8M3.6 15h16.8\" />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 3a15 15 0 014 9 15 15 0 01-4 9 15 15 0 01-4-9 15 15 0 014-9z\"\n />\n </svg>\n);\n\n// ============================================================================\n// PARSER OPTION BUTTON\n// ============================================================================\n\ninterface ParserOptionButtonProps {\n parser: {\n id: string;\n name: string;\n description: string | null;\n type: 'jq' | 'jsonata';\n inputSinkKey: string;\n outputKey: string;\n status: 'active' | 'inactive';\n };\n isSelected: boolean;\n onSelect: (id: string) => void;\n isGlobal?: boolean;\n}\n\nconst ParserOptionButton = memo(function ParserOptionButton({\n parser,\n isSelected,\n onSelect,\n isGlobal = false,\n}: ParserOptionButtonProps) {\n const { t } = useI18n();\n return (\n <button\n type=\"button\"\n onClick={() => onSelect(parser.id)}\n className={`\n w-full min-h-control-md px-3 py-2.5\n text-left\n hover:bg-bg-sunken\n motion-safe:transition-colors\n border-b border-[var(--color-border-default)] last:border-b-0\n ${SECTION_FOCUS_RING}\n ${isSelected ? 'bg-action-primary-bg/10' : ''}\n `}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n {/* Name and type */}\n <div className=\"flex items-center gap-2 mb-1\">\n <ParserTypeBadge type={parser.type} size=\"sm\" />\n <span className=\"text-sm font-medium text-text-primary truncate\">{parser.name}</span>\n {isGlobal && (\n <span className=\"inline-flex items-center gap-1 px-1.5 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\">\n <GlobeIcon className=\"w-3 h-3\" />\n {t('bigconsole.parsers.selector.globalBadge', 'Global')}\n </span>\n )}\n </div>\n\n {/* Description */}\n {parser.description && <p className=\"text-xs text-text-secondary line-clamp-1 mb-1\">{parser.description}</p>}\n\n {/* Data flow */}\n <div className=\"flex min-w-0 items-center gap-2 text-xs text-text-muted\">\n <span className=\"truncate font-mono\">\n {parser.inputSinkKey} → {parser.outputKey}\n </span>\n </div>\n </div>\n\n {/* Status badge */}\n <div className=\"shrink-0\">\n <ParserStatusBadge status={parser.status} size=\"sm\" showIcon={false} />\n </div>\n </div>\n </button>\n );\n});\n\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nexport const ParserSelector = memo(function ParserSelector({\n consoleId,\n value,\n onChange,\n filterType,\n filterStatus = 'active',\n filterInputSinkKey,\n placeholder,\n disabled = false,\n error = false,\n errorMessage,\n}: ParserSelectorProps) {\n const { t } = useI18n();\n const [isOpen, setIsOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n\n const resolvedPlaceholder = placeholder ?? t('bigconsole.parsers.selector.placeholder', 'Select a parser...');\n\n const buildPath = useBuildPath();\n\n // Determine if we need to fetch global parsers separately\n const isGlobalConsole = consoleId === DEFAULT_CONSOLE_ID;\n\n // Fetch dashboard-specific parsers\n const {\n parsers: dashboardParsers,\n loading: dashboardLoading,\n fetchParsers: fetchDashboardParsers,\n } = useParserOperations({\n consoleId,\n skipFetch: isGlobalConsole, // Skip if already fetching global\n });\n\n // Fetch global parsers (only if consoleId is not already 'default')\n const {\n parsers: globalParsers,\n loading: globalLoading,\n fetchParsers: fetchGlobalParsers,\n } = useParserOperations({\n consoleId: DEFAULT_CONSOLE_ID,\n skipFetch: isGlobalConsole, // Skip if consoleId is already 'default'\n });\n\n // Combine parsers: dashboard-specific + global (avoiding duplicates)\n const allParsers = useMemo(() => {\n if (isGlobalConsole) {\n // If we're already on global console, just return dashboard parsers\n return dashboardParsers;\n }\n\n // Combine both, with dashboard parsers first\n const parserIds = new Set(dashboardParsers.map((p) => p.id));\n const uniqueGlobalParsers = globalParsers.filter((p) => !parserIds.has(p.id));\n\n return [...dashboardParsers, ...uniqueGlobalParsers];\n }, [dashboardParsers, globalParsers, isGlobalConsole]);\n\n // Combined loading state\n const loading = dashboardLoading || globalLoading;\n\n // Filter parsers\n const filteredParsers = useMemo(() => {\n return allParsers.filter((p) => {\n // Filter by type if specified\n if (filterType && p.type !== filterType) return false;\n\n // Filter by status if specified\n if (filterStatus && p.status !== filterStatus) return false;\n\n // Filter by input DataSink key if specified\n if (filterInputSinkKey && p.inputSinkKey !== filterInputSinkKey) return false;\n\n // Filter by search query\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n return (\n p.name.toLowerCase().includes(query) ||\n p.description?.toLowerCase().includes(query) ||\n p.inputSinkKey.toLowerCase().includes(query) ||\n p.outputKey.toLowerCase().includes(query)\n );\n }\n\n return true;\n });\n }, [allParsers, filterType, filterStatus, filterInputSinkKey, searchQuery]);\n\n // Group parsers by scope for display\n const { dashboardScopedParsers, globalScopedParsers } = useMemo(() => {\n const dashboard = filteredParsers.filter((p) => p.consoleId !== DEFAULT_CONSOLE_ID);\n const global = filteredParsers.filter((p) => p.consoleId === DEFAULT_CONSOLE_ID);\n return { dashboardScopedParsers: dashboard, globalScopedParsers: global };\n }, [filteredParsers]);\n\n // Find selected parser\n const selectedParser = allParsers.find((p) => p.id === value);\n\n // Fetch parsers when console changes or DataSink filter changes\n useEffect(() => {\n if (consoleId) {\n fetchDashboardParsers({ type: filterType, status: filterStatus ?? undefined });\n\n // Also fetch global parsers if not already on global console\n if (!isGlobalConsole) {\n fetchGlobalParsers({ type: filterType, status: filterStatus ?? undefined });\n }\n }\n }, [\n consoleId,\n filterType,\n filterStatus,\n filterInputSinkKey,\n fetchDashboardParsers,\n fetchGlobalParsers,\n isGlobalConsole,\n ]);\n\n // Handle selection\n const handleSelect = useCallback(\n (id: string | null) => {\n onChange(id);\n setIsOpen(false);\n setSearchQuery('');\n },\n [onChange]\n );\n\n // Toggle dropdown\n const handleToggle = useCallback(() => {\n if (disabled) return;\n const next = !isOpen;\n // Refetch on open so a parser created via the \"Create new\" tab shows\n // up here without needing a full page reload.\n if (next) {\n void fetchDashboardParsers({ type: filterType, status: filterStatus ?? undefined });\n if (!isGlobalConsole) {\n void fetchGlobalParsers({ type: filterType, status: filterStatus ?? undefined });\n }\n }\n setIsOpen(next);\n }, [disabled, isOpen, fetchDashboardParsers, fetchGlobalParsers, filterType, filterStatus, isGlobalConsole]);\n\n // Close dropdown\n const handleClose = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n // Open the create-Parser page in a new tab so the current editing\n // context (e.g. an unsaved widget in the dashboard builder) is preserved.\n // Preserve the dashboard scope so the new parser is created for this\n // console rather than as a global parser.\n const handleCreateNew = useCallback(() => {\n setIsOpen(false);\n const path = isGlobalConsole ? '/parsers/new' : `/dashboards/${consoleId}/parsers/new`;\n window.open(buildPath(path), '_blank', 'noopener,noreferrer');\n }, [buildPath, consoleId, isGlobalConsole]);\n\n return (\n <div className=\"relative\">\n {/* Trigger button */}\n <button\n type=\"button\"\n onClick={handleToggle}\n disabled={disabled}\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n className={`\n w-full min-w-0 min-h-control-md\n px-3 py-2\n bg-bg-surface\n border rounded-md\n text-left\n flex items-center justify-between gap-2\n motion-safe:transition-colors\n ${SECTION_FOCUS_RING}\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-action-primary-bg cursor-pointer'}\n ${error ? 'border-status-error-border' : 'border-[var(--color-border-default)]'}\n ${isOpen ? 'border-action-primary-bg ring-2 ring-action-primary-bg/20' : ''}\n `}\n >\n <div className=\"flex-1 min-w-0\">\n {selectedParser ? (\n <div className=\"flex min-w-0 items-center gap-2\">\n <ParserTypeBadge type={selectedParser.type} size=\"sm\" />\n <span className=\"text-sm text-text-primary truncate\">{selectedParser.name}</span>\n </div>\n ) : (\n <span className=\"text-sm text-text-muted\">{resolvedPlaceholder}</span>\n )}\n </div>\n\n <ChevronDownIcon\n aria-hidden=\"true\"\n className={`w-4 h-4 shrink-0 text-text-secondary motion-safe:transition-transform ${isOpen ? 'transform rotate-180' : ''}`}\n />\n </button>\n\n {/* Error message */}\n {error && errorMessage && <p className=\"mt-1 text-xs text-status-error-text\">{errorMessage}</p>}\n\n {/* Dropdown */}\n {isOpen && (\n <Fragment>\n {/* Backdrop */}\n <div className=\"fixed inset-0 z-10\" onClick={handleClose} />\n\n {/* Dropdown content */}\n <div className=\"absolute left-0 right-0 top-full mt-1 z-20 bg-bg-surface border border-[var(--color-border-default)] rounded-md shadow-lg max-h-80 flex flex-col overflow-hidden\">\n {/* Search input */}\n <div className=\"p-2 border-b border-[var(--color-border-default)]\">\n <input\n type=\"text\"\n aria-label={t('bigconsole.parsers.selector.searchPlaceholder', 'Search parsers...')}\n placeholder={t('bigconsole.parsers.selector.searchPlaceholder', 'Search parsers...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className={`\n w-full min-w-0 min-h-control-md px-3 py-2\n bg-bg-sunken\n border border-[var(--color-border-default)]\n rounded-md\n text-sm text-text-primary\n placeholder:text-text-muted\n focus:outline-none\n focus:border-action-primary-bg\n focus:ring-2\n focus:ring-action-primary-bg/20\n `}\n />\n </div>\n\n {/* Options list */}\n <div className=\"overflow-y-auto flex-1\">\n {loading ? (\n <div className=\"p-4 text-center text-sm text-text-secondary\">\n {t('bigconsole.parsers.selector.loading', 'Loading parsers...')}\n </div>\n ) : filteredParsers.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-text-secondary\">\n {t('bigconsole.parsers.selector.empty', 'No parsers found')}\n </div>\n ) : (\n <Fragment>\n {/* None option */}\n <button\n type=\"button\"\n onClick={() => handleSelect(null)}\n className={`\n w-full min-h-control-md px-3 py-2\n text-left text-sm\n hover:bg-bg-sunken\n motion-safe:transition-colors\n ${SECTION_FOCUS_RING}\n ${value === null ? 'bg-action-primary-bg/10 text-action-primary-bg' : 'text-text-secondary'}\n `}\n >\n <span className=\"italic\">{t('bigconsole.parsers.selector.none', 'None')}</span>\n </button>\n\n {/* Dashboard-scoped parsers section */}\n {dashboardScopedParsers.length > 0 && (\n <Fragment>\n <div className={GROUP_HEADER}>\n <span className={GROUP_HEADER_LABEL}>\n {t('bigconsole.parsers.selector.dashboardParsers', 'Dashboard Parsers')}\n </span>\n </div>\n {dashboardScopedParsers.map((parser) => (\n <ParserOptionButton\n key={parser.id}\n parser={parser}\n isSelected={value === parser.id}\n onSelect={handleSelect}\n />\n ))}\n </Fragment>\n )}\n\n {/* Global parsers section */}\n {globalScopedParsers.length > 0 && (\n <Fragment>\n <div className={GROUP_HEADER}>\n <span className={GROUP_HEADER_LABEL}>\n {t('bigconsole.parsers.selector.globalParsers', 'Global Parsers')}\n </span>\n </div>\n {globalScopedParsers.map((parser) => (\n <ParserOptionButton\n key={parser.id}\n parser={parser}\n isSelected={value === parser.id}\n onSelect={handleSelect}\n isGlobal\n />\n ))}\n </Fragment>\n )}\n </Fragment>\n )}\n </div>\n\n {/* Create new — persistent footer action (opens in a new tab) */}\n <div className=\"p-2 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={handleCreateNew}\n className=\"\n w-full flex items-center gap-2\n px-3 py-2\n text-sm font-medium text-action-primary-bg\n rounded-md\n hover:bg-action-primary-bg/10\n transition-colors\n \"\n >\n <Plus className=\"w-4 h-4\" />\n {t('bigconsole.parsers.selector.createNew', 'Create new parser')}\n </button>\n </div>\n </div>\n </Fragment>\n )}\n </div>\n );\n});\n\nexport default ParserSelector;\n"],"mappings":"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"}
@@ -40,8 +40,8 @@ var r = {
40
40
  label: "Active"
41
41
  },
42
42
  inactive: {
43
- bg: "bg-text-tertiary/10",
44
- text: "text-text-tertiary",
43
+ bg: "bg-bg-sunken",
44
+ text: "text-text-muted",
45
45
  icon: /* @__PURE__ */ t(o, { className: u }),
46
46
  label: "Inactive"
47
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ParserStatusBadge.js","names":[],"sources":["../../../../src/bigconsole/components/parser/ParserStatusBadge.tsx"],"sourcesContent":["/**\n * Parser Status Badge\n *\n * Badge component displaying parser status (active, inactive).\n */\n\nimport { memo } from 'react';\nimport type { ParserStatus } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserStatusBadgeProps {\n /** Parser status */\n status: ParserStatus;\n /** Badge size */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show icon */\n showIcon?: boolean;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst SIZE_CLASSES = {\n sm: 'px-2 py-0.5 text-xs',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1.5 text-base',\n};\n\nconst ICON_SIZE_CLASSES = {\n sm: 'w-3 h-3',\n md: 'w-4 h-4',\n lg: 'w-5 h-5',\n};\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n);\n\nconst XCircleIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const ParserStatusBadge = memo(function ParserStatusBadge({\n status,\n size = 'md',\n showIcon = true,\n}: ParserStatusBadgeProps) {\n const sizeClass = SIZE_CLASSES[size];\n const iconSizeClass = ICON_SIZE_CLASSES[size];\n\n const config = {\n active: {\n bg: 'bg-status-success-bg/10',\n text: 'text-status-success-text',\n icon: <CheckIcon className={iconSizeClass} />,\n label: 'Active',\n },\n inactive: {\n bg: 'bg-text-tertiary/10',\n text: 'text-text-tertiary',\n icon: <XCircleIcon className={iconSizeClass} />,\n label: 'Inactive',\n },\n }[status];\n\n if (!config) {\n return (\n <span\n className={`\n inline-flex items-center gap-1.5\n ${sizeClass}\n bg-bg-sunken\n text-text-secondary\n rounded-full\n font-medium\n `}\n >\n {status}\n </span>\n );\n }\n\n return (\n <span\n className={`\n inline-flex items-center gap-1.5\n ${sizeClass}\n ${config.bg}\n ${config.text}\n rounded-full\n font-medium\n `}\n >\n {showIcon && config.icon}\n <span>{config.label}</span>\n </span>\n );\n});\n\nexport default ParserStatusBadge;\n"],"mappings":";;;AA0BA,IAAM,IAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAEK,IAAoB;CACxB,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAMK,KAAa,EAAE,mBACnB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAmB,CAAA;CACpF,CAAA,EAGF,KAAe,EAAE,mBACrB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAOK,IAAoB,EAAK,SAA2B,EAC/D,WACA,UAAO,MACP,cAAW,MACc;CACzB,IAAM,IAAY,EAAa,IACzB,IAAgB,EAAkB,IAElC,IAAS;EACb,QAAQ;GACN,IAAI;GACJ,MAAM;GACN,MAAM,kBAAC,GAAD,EAAW,WAAW,GAAiB,CAAA;GAC7C,OAAO;GACR;EACD,UAAU;GACR,IAAI;GACJ,MAAM;GACN,MAAM,kBAAC,GAAD,EAAa,WAAW,GAAiB,CAAA;GAC/C,OAAO;GACR;EACF,CAAC;AAmBF,QAjBK,IAkBH,kBAAC,QAAD;EACE,WAAW;;UAEP,EAAU;UACV,EAAO,GAAG;UACV,EAAO,KAAK;;;;YALlB,CAUG,KAAY,EAAO,MACpB,kBAAC,QAAD,EAAA,UAAO,EAAO,OAAa,CAAA,CACtB;MA5BL,kBAAC,QAAD;EACE,WAAW;;YAEP,EAAU;;;;;;YAOb;EACI,CAAA;EAmBX"}
1
+ {"version":3,"file":"ParserStatusBadge.js","names":[],"sources":["../../../../src/bigconsole/components/parser/ParserStatusBadge.tsx"],"sourcesContent":["/**\n * Parser Status Badge\n *\n * Badge component displaying parser status (active, inactive).\n */\n\nimport { memo } from 'react';\nimport type { ParserStatus } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserStatusBadgeProps {\n /** Parser status */\n status: ParserStatus;\n /** Badge size */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show icon */\n showIcon?: boolean;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst SIZE_CLASSES = {\n sm: 'px-2 py-0.5 text-xs',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1.5 text-base',\n};\n\nconst ICON_SIZE_CLASSES = {\n sm: 'w-3 h-3',\n md: 'w-4 h-4',\n lg: 'w-5 h-5',\n};\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n);\n\nconst XCircleIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const ParserStatusBadge = memo(function ParserStatusBadge({\n status,\n size = 'md',\n showIcon = true,\n}: ParserStatusBadgeProps) {\n const sizeClass = SIZE_CLASSES[size];\n const iconSizeClass = ICON_SIZE_CLASSES[size];\n\n const config = {\n active: {\n bg: 'bg-status-success-bg/10',\n text: 'text-status-success-text',\n icon: <CheckIcon className={iconSizeClass} />,\n label: 'Active',\n },\n inactive: {\n // `bg-text-tertiary` / `text-text-tertiary` are unregistered in this shell\n // and emitted no CSS, so the inactive pill rendered with no fill at all.\n bg: 'bg-bg-sunken',\n text: 'text-text-muted',\n icon: <XCircleIcon className={iconSizeClass} />,\n label: 'Inactive',\n },\n }[status];\n\n if (!config) {\n return (\n <span\n className={`\n inline-flex items-center gap-1.5\n ${sizeClass}\n bg-bg-sunken\n text-text-secondary\n rounded-full\n font-medium\n `}\n >\n {status}\n </span>\n );\n }\n\n return (\n <span\n className={`\n inline-flex items-center gap-1.5\n ${sizeClass}\n ${config.bg}\n ${config.text}\n rounded-full\n font-medium\n `}\n >\n {showIcon && config.icon}\n <span>{config.label}</span>\n </span>\n );\n});\n\nexport default ParserStatusBadge;\n"],"mappings":";;;AA0BA,IAAM,IAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAEK,IAAoB;CACxB,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAMK,KAAa,EAAE,mBACnB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAmB,CAAA;CACpF,CAAA,EAGF,KAAe,EAAE,mBACrB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAOK,IAAoB,EAAK,SAA2B,EAC/D,WACA,UAAO,MACP,cAAW,MACc;CACzB,IAAM,IAAY,EAAa,IACzB,IAAgB,EAAkB,IAElC,IAAS;EACb,QAAQ;GACN,IAAI;GACJ,MAAM;GACN,MAAM,kBAAC,GAAD,EAAW,WAAW,GAAiB,CAAA;GAC7C,OAAO;GACR;EACD,UAAU;GAGR,IAAI;GACJ,MAAM;GACN,MAAM,kBAAC,GAAD,EAAa,WAAW,GAAiB,CAAA;GAC/C,OAAO;GACR;EACF,CAAC;AAmBF,QAjBK,IAkBH,kBAAC,QAAD;EACE,WAAW;;UAEP,EAAU;UACV,EAAO,GAAG;UACV,EAAO,KAAK;;;;YALlB,CAUG,KAAY,EAAO,MACpB,kBAAC,QAAD,EAAA,UAAO,EAAO,OAAa,CAAA,CACtB;MA5BL,kBAAC,QAAD;EACE,WAAW;;YAEP,EAAU;;;;;;YAOb;EACI,CAAA;EAmBX"}
@@ -7,13 +7,13 @@ var n = {
7
7
  lg: "px-3 py-1.5 text-base"
8
8
  }, r = {
9
9
  jq: {
10
- bg: "bg-blue-500/10",
11
- text: "text-blue-600 dark:text-blue-400",
10
+ bg: "bg-[var(--color-status-info-bgSubtle)]",
11
+ text: "text-[var(--color-status-info-text)]",
12
12
  label: "JQ"
13
13
  },
14
14
  jsonata: {
15
- bg: "bg-purple-500/10",
16
- text: "text-purple-600 dark:text-purple-400",
15
+ bg: "bg-bg-accentSubtle",
16
+ text: "text-text-link",
17
17
  label: "JSONata"
18
18
  }
19
19
  }, i = e(function({ type: e, size: i = "md" }) {
@@ -1 +1 @@
1
- {"version":3,"file":"ParserTypeBadge.js","names":[],"sources":["../../../../src/bigconsole/components/parser/ParserTypeBadge.tsx"],"sourcesContent":["/**\n * Parser Type Badge\n *\n * Badge component displaying parser type (JQ, JSONata).\n */\n\nimport { memo } from 'react';\nimport type { ParserType } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserTypeBadgeProps {\n /** Parser type */\n type: ParserType;\n /** Badge size */\n size?: 'sm' | 'md' | 'lg';\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst SIZE_CLASSES = {\n sm: 'px-2 py-0.5 text-xs',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1.5 text-base',\n};\n\nconst TYPE_CONFIG: Record<ParserType, { bg: string; text: string; label: string }> = {\n jq: {\n bg: 'bg-blue-500/10',\n text: 'text-blue-600 dark:text-blue-400',\n label: 'JQ',\n },\n jsonata: {\n bg: 'bg-purple-500/10',\n text: 'text-purple-600 dark:text-purple-400',\n label: 'JSONata',\n },\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const ParserTypeBadge = memo(function ParserTypeBadge({ type, size = 'md' }: ParserTypeBadgeProps) {\n const sizeClass = SIZE_CLASSES[size];\n const config = TYPE_CONFIG[type];\n\n if (!config) {\n return (\n <span\n className={`\n inline-flex items-center\n ${sizeClass}\n bg-bg-sunken\n text-text-secondary\n rounded-md\n font-mono\n font-semibold\n `}\n >\n {type}\n </span>\n );\n }\n\n return (\n <span\n className={`\n inline-flex items-center\n ${sizeClass}\n ${config.bg}\n ${config.text}\n rounded-md\n font-mono\n font-semibold\n `}\n >\n {config.label}\n </span>\n );\n});\n\nexport default ParserTypeBadge;\n"],"mappings":";;;AAwBA,IAAM,IAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAEK,IAA+E;CACnF,IAAI;EACF,IAAI;EACJ,MAAM;EACN,OAAO;EACR;CACD,SAAS;EACP,IAAI;EACJ,MAAM;EACN,OAAO;EACR;CACF,EAMY,IAAkB,EAAK,SAAyB,EAAE,SAAM,UAAO,QAA8B;CACxG,IAAM,IAAY,EAAa,IACzB,IAAS,EAAY;AAoB3B,QAlBK,IAmBH,kBAAC,QAAD;EACE,WAAW;;UAEP,EAAU;UACV,EAAO,GAAG;UACV,EAAO,KAAK;;;;;YAMf,EAAO;EACH,CAAA,GA7BL,kBAAC,QAAD;EACE,WAAW;;YAEP,EAAU;;;;;;;YAQb;EACI,CAAA;EAmBX"}
1
+ {"version":3,"file":"ParserTypeBadge.js","names":[],"sources":["../../../../src/bigconsole/components/parser/ParserTypeBadge.tsx"],"sourcesContent":["/**\n * Parser Type Badge\n *\n * Badge component displaying parser type (JQ, JSONata).\n */\n\nimport { memo } from 'react';\nimport type { ParserType } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserTypeBadgeProps {\n /** Parser type */\n type: ParserType;\n /** Badge size */\n size?: 'sm' | 'md' | 'lg';\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst SIZE_CLASSES = {\n sm: 'px-2 py-0.5 text-xs',\n md: 'px-2.5 py-1 text-sm',\n lg: 'px-3 py-1.5 text-base',\n};\n\n/**\n * Type accents use semantic tokens only — the previous raw `blue-500`/`purple-500`\n * palette classes were not theme-aware and disagreed with the duplicate badge on\n * the DataSink detail page. `info` and `accent` are the two neutral-safe accents\n * available in every BigConsole theme.\n */\nconst TYPE_CONFIG: Record<ParserType, { bg: string; text: string; label: string }> = {\n jq: {\n bg: 'bg-[var(--color-status-info-bgSubtle)]',\n text: 'text-[var(--color-status-info-text)]',\n label: 'JQ',\n },\n jsonata: {\n bg: 'bg-bg-accentSubtle',\n text: 'text-text-link',\n label: 'JSONata',\n },\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const ParserTypeBadge = memo(function ParserTypeBadge({ type, size = 'md' }: ParserTypeBadgeProps) {\n const sizeClass = SIZE_CLASSES[size];\n const config = TYPE_CONFIG[type];\n\n if (!config) {\n return (\n <span\n className={`\n inline-flex items-center\n ${sizeClass}\n bg-bg-sunken\n text-text-secondary\n rounded-md\n font-mono\n font-semibold\n `}\n >\n {type}\n </span>\n );\n }\n\n return (\n <span\n className={`\n inline-flex items-center\n ${sizeClass}\n ${config.bg}\n ${config.text}\n rounded-md\n font-mono\n font-semibold\n `}\n >\n {config.label}\n </span>\n );\n});\n\nexport default ParserTypeBadge;\n"],"mappings":";;;AAwBA,IAAM,IAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAQK,IAA+E;CACnF,IAAI;EACF,IAAI;EACJ,MAAM;EACN,OAAO;EACR;CACD,SAAS;EACP,IAAI;EACJ,MAAM;EACN,OAAO;EACR;CACF,EAMY,IAAkB,EAAK,SAAyB,EAAE,SAAM,UAAO,QAA8B;CACxG,IAAM,IAAY,EAAa,IACzB,IAAS,EAAY;AAoB3B,QAlBK,IAmBH,kBAAC,QAAD;EACE,WAAW;;UAEP,EAAU;UACV,EAAO,GAAG;UACV,EAAO,KAAK;;;;;YAMf,EAAO;EACH,CAAA,GA7BL,kBAAC,QAAD;EACE,WAAW;;YAEP,EAAU;;;;;;;YAQb;EACI,CAAA;EAmBX"}
@@ -1,159 +1,204 @@
1
- import e from "./PipelineStatusBadge.js";
2
- import { memo as t, useCallback as n } from "react";
3
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
- import { formatDistanceToNow as a } from "date-fns";
1
+ import { SECTION_FOCUS_RING as e } from "../common/sectionStyles.js";
2
+ import "../common/index.js";
3
+ import t from "./PipelineStatusBadge.js";
4
+ import { memo as n, useCallback as r } from "react";
5
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
+ import { formatDistanceToNow as o } from "date-fns";
5
7
  //#region src/bigconsole/components/pipeline/PipelineCard.tsx
6
- var o = ({ className: e }) => /* @__PURE__ */ r("svg", {
8
+ var s = `inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-button text-text-secondary motion-safe:transition-colors ${e}`, c = ({ className: e }) => /* @__PURE__ */ i("svg", {
7
9
  className: e,
8
10
  fill: "none",
9
11
  stroke: "currentColor",
10
12
  viewBox: "0 0 24 24",
11
- children: /* @__PURE__ */ r("path", {
13
+ children: /* @__PURE__ */ i("path", {
12
14
  strokeLinecap: "round",
13
15
  strokeLinejoin: "round",
14
16
  strokeWidth: 1.5,
15
17
  d: "M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 00-3.7-3.7 48.678 48.678 0 00-7.324 0 4.006 4.006 0 00-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3l-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 003.7 3.7 48.656 48.656 0 007.324 0 4.006 4.006 0 003.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3l-3 3"
16
18
  })
17
- }), s = ({ className: e }) => /* @__PURE__ */ r("svg", {
19
+ }), l = ({ className: e }) => /* @__PURE__ */ i("svg", {
18
20
  className: e,
19
21
  fill: "none",
20
22
  stroke: "currentColor",
21
23
  viewBox: "0 0 24 24",
22
- children: /* @__PURE__ */ r("path", {
24
+ children: /* @__PURE__ */ i("path", {
23
25
  strokeLinecap: "round",
24
26
  strokeLinejoin: "round",
25
27
  strokeWidth: 2,
26
28
  d: "M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
27
29
  })
28
- }), c = ({ className: e }) => /* @__PURE__ */ i("svg", {
30
+ }), u = ({ className: e }) => /* @__PURE__ */ a("svg", {
29
31
  className: e,
30
32
  fill: "none",
31
33
  stroke: "currentColor",
32
34
  viewBox: "0 0 24 24",
33
- children: [/* @__PURE__ */ r("path", {
35
+ children: [/* @__PURE__ */ i("path", {
34
36
  strokeLinecap: "round",
35
37
  strokeLinejoin: "round",
36
38
  strokeWidth: 2,
37
39
  d: "M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"
38
- }), /* @__PURE__ */ r("path", {
40
+ }), /* @__PURE__ */ i("path", {
39
41
  strokeLinecap: "round",
40
42
  strokeLinejoin: "round",
41
43
  strokeWidth: 2,
42
44
  d: "M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
43
45
  })]
44
- }), l = ({ className: e }) => /* @__PURE__ */ r("svg", {
46
+ }), d = ({ className: e }) => /* @__PURE__ */ i("svg", {
45
47
  className: e,
46
48
  fill: "none",
47
49
  stroke: "currentColor",
48
50
  viewBox: "0 0 24 24",
49
- children: /* @__PURE__ */ r("path", {
51
+ children: /* @__PURE__ */ i("path", {
50
52
  strokeLinecap: "round",
51
53
  strokeLinejoin: "round",
52
54
  strokeWidth: 2,
53
55
  d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
54
56
  })
55
- }), u = ({ className: e }) => /* @__PURE__ */ r("svg", {
57
+ }), f = ({ className: e }) => /* @__PURE__ */ i("svg", {
56
58
  className: e,
57
59
  fill: "none",
58
60
  stroke: "currentColor",
59
61
  viewBox: "0 0 24 24",
60
- children: /* @__PURE__ */ r("path", {
62
+ children: /* @__PURE__ */ i("path", {
61
63
  strokeLinecap: "round",
62
64
  strokeLinejoin: "round",
63
65
  strokeWidth: 2,
64
66
  d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
65
67
  })
66
- }), d = t(function({ pipeline: t, onView: d, onEdit: f, onTest: p, onDelete: m }) {
67
- let h = t.stages?.length ?? 0, g = n((e) => {
68
- if (!e) return "Never";
68
+ }), p = ({ className: e }) => /* @__PURE__ */ i("svg", {
69
+ className: e,
70
+ fill: "none",
71
+ stroke: "currentColor",
72
+ viewBox: "0 0 24 24",
73
+ children: /* @__PURE__ */ i("path", {
74
+ strokeLinecap: "round",
75
+ strokeLinejoin: "round",
76
+ strokeWidth: 2,
77
+ d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
78
+ })
79
+ }), m = n(function({ pipeline: n, onView: m, onEdit: h, onTest: g, onDelete: _ }) {
80
+ let v = n.stages?.length ?? 0, y = r((e) => {
81
+ if (!e) return "Never run";
69
82
  try {
70
- return a(new Date(e), { addSuffix: !0 });
83
+ return o(new Date(e), { addSuffix: !0 });
71
84
  } catch {
72
85
  return "Unknown";
73
86
  }
74
- }, []), _ = n(() => {
75
- d?.(t.id);
76
- }, [d, t.id]), v = n((e) => {
77
- e.stopPropagation(), f?.(t.id);
78
- }, [f, t.id]), y = n((e) => {
79
- e.stopPropagation(), p?.(t.id);
80
- }, [p, t.id]), b = n((e) => {
81
- e.stopPropagation(), m?.(t.id);
82
- }, [m, t.id]);
83
- return /* @__PURE__ */ i("div", {
84
- onClick: _,
85
- className: "\n bg-bg-surface\n border border-border-default\n rounded-lg\n overflow-hidden\n cursor-pointer\n hover:border-action-primary-bg\n transition-colors\n ",
86
- children: [/* @__PURE__ */ i("div", {
87
- className: "h-24 bg-bg-sunken flex items-center justify-center relative",
88
- children: [/* @__PURE__ */ r(o, { className: "w-10 h-10 text-text-secondary/50" }), /* @__PURE__ */ r("div", {
89
- className: "absolute top-2 right-2",
90
- children: /* @__PURE__ */ r(e, {
91
- status: t.status,
87
+ }, []), b = r(() => {
88
+ m?.(n.id);
89
+ }, [m, n.id]), x = r((e) => {
90
+ e.stopPropagation(), m?.(n.id);
91
+ }, [m, n.id]), S = r((e) => {
92
+ e.stopPropagation(), h?.(n.id);
93
+ }, [h, n.id]), C = r((e) => {
94
+ e.stopPropagation(), g?.(n.id);
95
+ }, [g, n.id]), w = r((e) => {
96
+ e.stopPropagation(), _?.(n.id);
97
+ }, [_, n.id]);
98
+ return /* @__PURE__ */ a("article", {
99
+ onClick: b,
100
+ "data-testid": "pipeline-card",
101
+ className: "group flex min-w-0 cursor-pointer flex-col rounded-card border border-[var(--color-border-subtle)] bg-bg-surface shadow-[var(--shadow-elevation-1)] motion-safe:transition-[box-shadow,border-color] hover:border-[var(--color-border-strong)] hover:shadow-[var(--shadow-elevation-2)]",
102
+ children: [/* @__PURE__ */ a("div", {
103
+ className: "flex min-w-0 items-start gap-icon-gap border-b border-[var(--color-border-subtle)] p-4",
104
+ children: [
105
+ /* @__PURE__ */ i("span", {
106
+ "aria-hidden": "true",
107
+ className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-button bg-bg-sunken text-text-secondary",
108
+ children: /* @__PURE__ */ i(c, { className: "h-icon-md w-icon-md" })
109
+ }),
110
+ /* @__PURE__ */ a("div", {
111
+ className: "min-w-0 flex-1",
112
+ children: [/* @__PURE__ */ i("h3", {
113
+ className: "min-w-0 text-base font-semibold leading-tight text-text-primary",
114
+ children: /* @__PURE__ */ i("button", {
115
+ type: "button",
116
+ onClick: x,
117
+ title: n.name,
118
+ className: `block w-full truncate rounded-button text-left ${e}`,
119
+ children: n.name
120
+ })
121
+ }), n.description && /* @__PURE__ */ i("p", {
122
+ className: "mt-0.5 line-clamp-2 text-sm text-text-secondary",
123
+ children: n.description
124
+ })]
125
+ }),
126
+ /* @__PURE__ */ i(t, {
127
+ status: n.status,
92
128
  size: "sm"
93
129
  })
94
- })]
95
- }), /* @__PURE__ */ i("div", {
96
- className: "p-4",
97
- children: [/* @__PURE__ */ i("div", {
98
- className: "flex items-start justify-between mb-2",
99
- children: [/* @__PURE__ */ i("div", {
100
- className: "flex-1 min-w-0",
101
- children: [/* @__PURE__ */ r("h3", {
102
- className: "text-sm font-semibold text-text-primary truncate",
103
- children: t.name
104
- }), t.description && /* @__PURE__ */ r("p", {
105
- className: "text-xs text-text-secondary truncate mt-0.5",
106
- children: t.description
107
- })]
108
- }), /* @__PURE__ */ i("div", {
109
- className: "flex items-center gap-1 ml-2",
130
+ ]
131
+ }), /* @__PURE__ */ a("div", {
132
+ className: "flex flex-wrap items-center justify-between gap-control-gap p-4",
133
+ children: [/* @__PURE__ */ a("dl", {
134
+ className: "flex min-w-0 flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary",
135
+ children: [/* @__PURE__ */ a("div", {
136
+ className: "flex items-center gap-1",
110
137
  children: [
111
- p && /* @__PURE__ */ r("button", {
112
- type: "button",
113
- onClick: y,
114
- className: "\n p-1 rounded-md\n text-text-secondary\n hover:text-status-success-text\n hover:bg-status-success-bg/10\n transition-colors\n ",
115
- title: "Test Pipeline",
116
- children: /* @__PURE__ */ r(c, { className: "w-4 h-4" })
138
+ /* @__PURE__ */ i("dt", {
139
+ className: "sr-only",
140
+ children: "Stages"
117
141
  }),
118
- f && /* @__PURE__ */ r("button", {
119
- type: "button",
120
- onClick: v,
121
- className: "\n p-1 rounded-md\n text-text-secondary\n hover:text-text-primary\n hover:bg-bg-sunken\n transition-colors\n ",
122
- title: "Edit Pipeline",
123
- children: /* @__PURE__ */ r(s, { className: "w-4 h-4" })
142
+ /* @__PURE__ */ i(f, {
143
+ className: "h-3.5 w-3.5 shrink-0",
144
+ "aria-hidden": "true"
124
145
  }),
125
- m && /* @__PURE__ */ r("button", {
126
- type: "button",
127
- onClick: b,
128
- className: "\n p-1 rounded-md\n text-text-secondary\n hover:text-status-error-text\n hover:bg-status-error-bg/10\n transition-colors\n ",
129
- title: "Delete Pipeline",
130
- children: /* @__PURE__ */ r(l, { className: "w-4 h-4" })
146
+ /* @__PURE__ */ a("dd", { children: [
147
+ v,
148
+ " stage",
149
+ v === 1 ? "" : "s"
150
+ ] })
151
+ ]
152
+ }), /* @__PURE__ */ a("div", {
153
+ className: "flex items-center gap-1",
154
+ children: [
155
+ /* @__PURE__ */ i("dt", {
156
+ className: "sr-only",
157
+ children: "Last run"
158
+ }),
159
+ /* @__PURE__ */ i(p, {
160
+ className: "h-3.5 w-3.5 shrink-0",
161
+ "aria-hidden": "true"
162
+ }),
163
+ /* @__PURE__ */ i("dd", {
164
+ title: n.lastExecutedAt ? `Last executed: ${new Date(n.lastExecutedAt).toLocaleString()}` : "Never executed",
165
+ children: y(n.lastExecutedAt)
131
166
  })
132
167
  ]
133
168
  })]
134
- }), /* @__PURE__ */ i("div", {
135
- className: "flex items-center justify-between text-xs text-text-secondary mt-3",
136
- children: [/* @__PURE__ */ r("div", {
137
- className: "flex items-center gap-3",
138
- children: /* @__PURE__ */ i("span", {
139
- className: "flex items-center gap-1",
140
- title: `${h} stages`,
141
- children: [
142
- /* @__PURE__ */ r(u, { className: "w-3.5 h-3.5" }),
143
- h,
144
- " stage",
145
- h === 1 ? "" : "s"
146
- ]
169
+ }), /* @__PURE__ */ a("div", {
170
+ className: "flex shrink-0 items-center gap-1",
171
+ children: [
172
+ g && /* @__PURE__ */ i("button", {
173
+ type: "button",
174
+ onClick: C,
175
+ className: `${s} hover:bg-[var(--color-status-success-bgSubtle)] hover:text-status-success-text`,
176
+ title: "Test Pipeline",
177
+ "aria-label": `Test ${n.name}`,
178
+ children: /* @__PURE__ */ i(u, { className: "h-icon-sm w-icon-sm" })
179
+ }),
180
+ h && /* @__PURE__ */ i("button", {
181
+ type: "button",
182
+ onClick: S,
183
+ className: `${s} hover:bg-bg-sunken hover:text-text-primary`,
184
+ title: "Edit Pipeline",
185
+ "aria-label": `Edit ${n.name}`,
186
+ children: /* @__PURE__ */ i(l, { className: "h-icon-sm w-icon-sm" })
187
+ }),
188
+ _ && /* @__PURE__ */ i("button", {
189
+ type: "button",
190
+ onClick: w,
191
+ className: `${s} hover:bg-[var(--color-status-error-bgSubtle)] hover:text-status-error-text`,
192
+ title: "Delete Pipeline",
193
+ "aria-label": `Delete ${n.name}`,
194
+ children: /* @__PURE__ */ i(d, { className: "h-icon-sm w-icon-sm" })
147
195
  })
148
- }), /* @__PURE__ */ r("span", {
149
- title: t.lastExecutedAt ? `Last executed: ${new Date(t.lastExecutedAt).toLocaleString()}` : "Never executed",
150
- children: g(t.lastExecutedAt)
151
- })]
196
+ ]
152
197
  })]
153
198
  })]
154
199
  });
155
200
  });
156
201
  //#endregion
157
- export { d as default };
202
+ export { m as default };
158
203
 
159
204
  //# sourceMappingURL=PipelineCard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PipelineCard.js","names":[],"sources":["../../../../src/bigconsole/components/pipeline/PipelineCard.tsx"],"sourcesContent":["/**\n * PipelineCard Component\n *\n * Card component displaying a Pipeline summary.\n * Shows name, status, stage count, and execution stats.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { PipelineStatusBadge } from './PipelineStatusBadge';\nimport type { Pipeline } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface PipelineCardProps {\n pipeline: Pipeline;\n onView?: (id: string) => void;\n onEdit?: (id: string) => void;\n onTest?: (id: string) => void;\n onDelete?: (id: string) => void;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst PipelineIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 00-3.7-3.7 48.678 48.678 0 00-7.324 0 4.006 4.006 0 00-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3l-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 003.7 3.7 48.656 48.656 0 007.324 0 4.006 4.006 0 003.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3l-3 3\"\n />\n </svg>\n);\n\nconst EditIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n);\n\nconst PlayIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n);\n\nconst DeleteIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n);\n\nconst LayersIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelineCard = memo(function PipelineCard({\n pipeline,\n onView,\n onEdit,\n onTest,\n onDelete,\n}: PipelineCardProps) {\n // Calculate stage count\n const stageCount = pipeline.stages?.length ?? 0;\n\n // Format last executed time\n const formatLastExecuted = useCallback((dateStr: string | null): string => {\n if (!dateStr) return 'Never';\n try {\n const date = new Date(dateStr);\n return formatDistanceToNow(date, { addSuffix: true });\n } catch {\n return 'Unknown';\n }\n }, []);\n\n // Event handlers\n const handleCardClick = useCallback(() => {\n onView?.(pipeline.id);\n }, [onView, pipeline.id]);\n\n const handleEditClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(pipeline.id);\n },\n [onEdit, pipeline.id]\n );\n\n const handleTestClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onTest?.(pipeline.id);\n },\n [onTest, pipeline.id]\n );\n\n const handleDeleteClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(pipeline.id);\n },\n [onDelete, pipeline.id]\n );\n\n return (\n <div\n onClick={handleCardClick}\n className=\"\n bg-bg-surface\n border border-border-default\n rounded-lg\n overflow-hidden\n cursor-pointer\n hover:border-action-primary-bg\n transition-colors\n \"\n >\n {/* Header with Icon */}\n <div className=\"h-24 bg-bg-sunken flex items-center justify-center relative\">\n <PipelineIcon className=\"w-10 h-10 text-text-secondary/50\" />\n <div className=\"absolute top-2 right-2\">\n <PipelineStatusBadge status={pipeline.status} size=\"sm\" />\n </div>\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n {/* Title and Actions */}\n <div className=\"flex items-start justify-between mb-2\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-sm font-semibold text-text-primary truncate\">{pipeline.name}</h3>\n {pipeline.description && (\n <p className=\"text-xs text-text-secondary truncate mt-0.5\">{pipeline.description}</p>\n )}\n </div>\n\n <div className=\"flex items-center gap-1 ml-2\">\n {onTest && (\n <button\n type=\"button\"\n onClick={handleTestClick}\n className=\"\n p-1 rounded-md\n text-text-secondary\n hover:text-status-success-text\n hover:bg-status-success-bg/10\n transition-colors\n \"\n title=\"Test Pipeline\"\n >\n <PlayIcon className=\"w-4 h-4\" />\n </button>\n )}\n {onEdit && (\n <button\n type=\"button\"\n onClick={handleEditClick}\n className=\"\n p-1 rounded-md\n text-text-secondary\n hover:text-text-primary\n hover:bg-bg-sunken\n transition-colors\n \"\n title=\"Edit Pipeline\"\n >\n <EditIcon className=\"w-4 h-4\" />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={handleDeleteClick}\n className=\"\n p-1 rounded-md\n text-text-secondary\n hover:text-status-error-text\n hover:bg-status-error-bg/10\n transition-colors\n \"\n title=\"Delete Pipeline\"\n >\n <DeleteIcon className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Stats Footer */}\n <div className=\"flex items-center justify-between text-xs text-text-secondary mt-3\">\n <div className=\"flex items-center gap-3\">\n {/* Stage Count */}\n <span className=\"flex items-center gap-1\" title={`${stageCount} stages`}>\n <LayersIcon className=\"w-3.5 h-3.5\" />\n {stageCount} stage{stageCount !== 1 ? 's' : ''}\n </span>\n </div>\n\n {/* Last Executed */}\n <span\n title={\n pipeline.lastExecutedAt\n ? `Last executed: ${new Date(pipeline.lastExecutedAt).toLocaleString()}`\n : 'Never executed'\n }\n >\n {formatLastExecuted(pipeline.lastExecutedAt)}\n </span>\n </div>\n </div>\n </div>\n );\n});\n\nexport default PipelineCard;\n"],"mappings":"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"}
1
+ {"version":3,"file":"PipelineCard.js","names":[],"sources":["../../../../src/bigconsole/components/pipeline/PipelineCard.tsx"],"sourcesContent":["/**\n * PipelineCard Component\n *\n * Card component displaying a Pipeline summary.\n * Shows name, status, stage count, and execution stats.\n *\n * Hierarchy (BOFF-5635): the card is a tile inside the list page's `primary`\n * results section, so it carries a raised surface (border + elevation) and puts\n * its identity first. The old 96px decorative banner was the largest mass in the\n * card and carried no information — the icon is now a small puck on the identity\n * row, which roughly doubles the number of pipelines visible per screen.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { PipelineStatusBadge } from './PipelineStatusBadge';\nimport { SECTION_FOCUS_RING } from '../common';\nimport type { Pipeline } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface PipelineCardProps {\n pipeline: Pipeline;\n onView?: (id: string) => void;\n onEdit?: (id: string) => void;\n onTest?: (id: string) => void;\n onDelete?: (id: string) => void;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** Icon action button: 40px touch target, visible focus ring, no colour of its own. */\nconst ICON_ACTION = `inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-button text-text-secondary motion-safe:transition-colors ${SECTION_FOCUS_RING}`;\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst PipelineIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 00-3.7-3.7 48.678 48.678 0 00-7.324 0 4.006 4.006 0 00-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3l-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 003.7 3.7 48.656 48.656 0 007.324 0 4.006 4.006 0 003.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3l-3 3\"\n />\n </svg>\n);\n\nconst EditIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n);\n\nconst PlayIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n);\n\nconst DeleteIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n);\n\nconst LayersIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n);\n\nconst ClockIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelineCard = memo(function PipelineCard({\n pipeline,\n onView,\n onEdit,\n onTest,\n onDelete,\n}: PipelineCardProps) {\n // Calculate stage count\n const stageCount = pipeline.stages?.length ?? 0;\n\n // Format last executed time\n const formatLastExecuted = useCallback((dateStr: string | null): string => {\n if (!dateStr) return 'Never run';\n try {\n const date = new Date(dateStr);\n return formatDistanceToNow(date, { addSuffix: true });\n } catch {\n return 'Unknown';\n }\n }, []);\n\n // Event handlers\n const handleCardClick = useCallback(() => {\n onView?.(pipeline.id);\n }, [onView, pipeline.id]);\n\n const handleTitleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onView?.(pipeline.id);\n },\n [onView, pipeline.id]\n );\n\n const handleEditClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(pipeline.id);\n },\n [onEdit, pipeline.id]\n );\n\n const handleTestClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onTest?.(pipeline.id);\n },\n [onTest, pipeline.id]\n );\n\n const handleDeleteClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(pipeline.id);\n },\n [onDelete, pipeline.id]\n );\n\n return (\n <article\n onClick={handleCardClick}\n data-testid=\"pipeline-card\"\n className=\"group flex min-w-0 cursor-pointer flex-col rounded-card border border-[var(--color-border-subtle)] bg-bg-surface shadow-[var(--shadow-elevation-1)] motion-safe:transition-[box-shadow,border-color] hover:border-[var(--color-border-strong)] hover:shadow-[var(--shadow-elevation-2)]\"\n >\n {/* Identity — name first, status right, icon reduced to a puck */}\n <div className=\"flex min-w-0 items-start gap-icon-gap border-b border-[var(--color-border-subtle)] p-4\">\n <span\n aria-hidden=\"true\"\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-button bg-bg-sunken text-text-secondary\"\n >\n <PipelineIcon className=\"h-icon-md w-icon-md\" />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"min-w-0 text-base font-semibold leading-tight text-text-primary\">\n <button\n type=\"button\"\n onClick={handleTitleClick}\n title={pipeline.name}\n className={`block w-full truncate rounded-button text-left ${SECTION_FOCUS_RING}`}\n >\n {pipeline.name}\n </button>\n </h3>\n {pipeline.description && (\n <p className=\"mt-0.5 line-clamp-2 text-sm text-text-secondary\">{pipeline.description}</p>\n )}\n </div>\n\n <PipelineStatusBadge status={pipeline.status} size=\"sm\" />\n </div>\n\n {/* Supporting facts + row actions */}\n <div className=\"flex flex-wrap items-center justify-between gap-control-gap p-4\">\n <dl className=\"flex min-w-0 flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary\">\n <div className=\"flex items-center gap-1\">\n <dt className=\"sr-only\">Stages</dt>\n <LayersIcon className=\"h-3.5 w-3.5 shrink-0\" aria-hidden=\"true\" />\n <dd>\n {stageCount} stage{stageCount !== 1 ? 's' : ''}\n </dd>\n </div>\n <div className=\"flex items-center gap-1\">\n <dt className=\"sr-only\">Last run</dt>\n <ClockIcon className=\"h-3.5 w-3.5 shrink-0\" aria-hidden=\"true\" />\n <dd\n title={\n pipeline.lastExecutedAt\n ? `Last executed: ${new Date(pipeline.lastExecutedAt).toLocaleString()}`\n : 'Never executed'\n }\n >\n {formatLastExecuted(pipeline.lastExecutedAt)}\n </dd>\n </div>\n </dl>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n {onTest && (\n <button\n type=\"button\"\n onClick={handleTestClick}\n className={`${ICON_ACTION} hover:bg-[var(--color-status-success-bgSubtle)] hover:text-status-success-text`}\n title=\"Test Pipeline\"\n aria-label={`Test ${pipeline.name}`}\n >\n <PlayIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n )}\n {onEdit && (\n <button\n type=\"button\"\n onClick={handleEditClick}\n className={`${ICON_ACTION} hover:bg-bg-sunken hover:text-text-primary`}\n title=\"Edit Pipeline\"\n aria-label={`Edit ${pipeline.name}`}\n >\n <EditIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={handleDeleteClick}\n className={`${ICON_ACTION} hover:bg-[var(--color-status-error-bgSubtle)] hover:text-status-error-text`}\n title=\"Delete Pipeline\"\n aria-label={`Delete ${pipeline.name}`}\n >\n <DeleteIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n )}\n </div>\n </div>\n </article>\n );\n});\n\nexport default PipelineCard;\n"],"mappings":"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"}