@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
@@ -4,27 +4,56 @@ import { unwrapRows as n } from "../utils/inferFields.js";
4
4
  import { memo as r, useCallback as i, useMemo as a } from "react";
5
5
  import { jsx as o, jsxs as s } from "react/jsx-runtime";
6
6
  //#region src/bigconsole/components/widgets/gauge/GaugeWidget.tsx
7
- var c = [
7
+ var c = {
8
+ success: "var(--color-status-success-bg)",
9
+ warning: "var(--color-status-warning-bg)",
10
+ error: "var(--color-status-error-bg)"
11
+ }, l = {
12
+ red: "error",
13
+ "#ef4444": "error",
14
+ "#dc2626": "error",
15
+ yellow: "warning",
16
+ amber: "warning",
17
+ orange: "warning",
18
+ "#f59e0b": "warning",
19
+ "#eab308": "warning",
20
+ green: "success",
21
+ "#22c55e": "success",
22
+ "#059669": "success"
23
+ };
24
+ function u(e) {
25
+ return e in c;
26
+ }
27
+ function d(e) {
28
+ return /^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(e) || /^(rgb|rgba|hsl|hsla|color|oklch|lab)\(/i.test(e);
29
+ }
30
+ function f(e) {
31
+ let t = e.trim().toLowerCase();
32
+ if (u(t)) return c[t];
33
+ let n = l[t];
34
+ return n ? c[n] : t.startsWith("var(") || d(t) ? e : "var(--color-action-primary-bg)";
35
+ }
36
+ var p = [
8
37
  {
9
38
  value: 33,
10
- color: "var(--color-state-error)"
39
+ color: c.error
11
40
  },
12
41
  {
13
42
  value: 66,
14
- color: "var(--color-state-warning)"
43
+ color: c.warning
15
44
  },
16
45
  {
17
46
  value: 100,
18
- color: "var(--color-state-success)"
47
+ color: c.success
19
48
  }
20
49
  ];
21
- function l(e) {
50
+ function m(e) {
22
51
  return e?.thresholds?.length ? e.thresholds.map((e) => ({
23
52
  value: e.value,
24
- color: e.color === "success" ? "var(--color-state-success)" : e.color === "warning" ? "var(--color-state-warning)" : e.color === "error" ? "var(--color-state-error)" : e.color
25
- })) : c;
53
+ color: f(e.color)
54
+ })) : p;
26
55
  }
27
- function u(e, t) {
56
+ function h(e, t) {
28
57
  switch (t?.format || "number") {
29
58
  case "percentage": return `${e.toFixed(0)}%`;
30
59
  case "currency": return new Intl.NumberFormat("en-US", {
@@ -35,8 +64,8 @@ function u(e, t) {
35
64
  default: return new Intl.NumberFormat("en-US", { maximumFractionDigits: t?.decimals || 0 }).format(e);
36
65
  }
37
66
  }
38
- var d = r(function({ widget: r, data: c, onClick: d, onDrilldown: f }) {
39
- let p = r.config, m = a(() => l(p), [p]), h = i((e) => u(e, p), [p]), g = !!r.drilldown?.enabled, _ = p?.variant === "linear", v = a(() => {
67
+ var g = r(function({ widget: r, data: c, onClick: l, onDrilldown: u }) {
68
+ let d = r.config, f = a(() => m(d), [d]), p = i((e) => h(e, d), [d]), g = !!r.drilldown?.enabled, _ = d?.variant === "linear", v = a(() => {
40
69
  if (!c) return null;
41
70
  if (c && typeof c == "object" && !Array.isArray(c)) {
42
71
  let e = c;
@@ -50,7 +79,7 @@ var d = r(function({ widget: r, data: c, onClick: d, onDrilldown: f }) {
50
79
  r && r.length > 0 && (e = r);
51
80
  }
52
81
  }
53
- let t = p?.valueField || p?.value_field || "value";
82
+ let t = d?.valueField || d?.value_field || "value";
54
83
  if (Array.isArray(e) && e.length > 0) {
55
84
  let n = e[0];
56
85
  if (typeof n[t] == "number") return {
@@ -122,21 +151,21 @@ var d = r(function({ widget: r, data: c, onClick: d, onDrilldown: f }) {
122
151
  if (!isNaN(t)) return { value: t };
123
152
  }
124
153
  return null;
125
- }, [c, p]), y = i(() => {
126
- f && v ? f({
154
+ }, [c, d]), y = i(() => {
155
+ u && v ? u({
127
156
  value: v.value,
128
157
  label: v.label,
129
- min: p?.min,
130
- max: p?.max
131
- }) : d && r.drilldowns?.length && d();
158
+ min: d?.min,
159
+ max: d?.max
160
+ }) : l && r.drilldowns?.length && l();
132
161
  }, [
133
- d,
134
- f,
162
+ l,
163
+ u,
135
164
  r.drilldowns,
136
165
  v,
137
- p?.min,
138
- p?.max
139
- ]), b = !!(g || d && r.drilldowns?.length);
166
+ d?.min,
167
+ d?.max
168
+ ]), b = !!(g || l && r.drilldowns?.length);
140
169
  return v ? /* @__PURE__ */ s("div", {
141
170
  className: `
142
171
  flex flex-col items-center justify-center h-full p-4
@@ -157,20 +186,20 @@ var d = r(function({ widget: r, data: c, onClick: d, onDrilldown: f }) {
157
186
  className: `${_ ? "w-full max-w-xs" : ""}`,
158
187
  children: _ ? /* @__PURE__ */ o(t, {
159
188
  value: v.value,
160
- min: p?.min,
161
- max: p?.max,
162
- thresholds: m,
163
- unit: p?.unit,
164
- formatValue: h,
165
- showZones: p?.showZones
189
+ min: d?.min,
190
+ max: d?.max,
191
+ thresholds: f,
192
+ unit: d?.unit,
193
+ formatValue: p,
194
+ showZones: d?.showZones
166
195
  }) : /* @__PURE__ */ o(e, {
167
196
  value: v.value,
168
- min: p?.min,
169
- max: p?.max,
170
- thresholds: m,
171
- unit: p?.unit,
172
- formatValue: h,
173
- size: p?.size === "sm" ? 100 : p?.size === "md" ? 140 : p?.size === "lg" ? 180 : 140
197
+ min: d?.min,
198
+ max: d?.max,
199
+ thresholds: f,
200
+ unit: d?.unit,
201
+ formatValue: p,
202
+ size: d?.size === "sm" ? 100 : d?.size === "md" ? 140 : d?.size === "lg" ? 180 : 140
174
203
  })
175
204
  }),
176
205
  b && /* @__PURE__ */ o("div", {
@@ -197,7 +226,7 @@ var d = r(function({ widget: r, data: c, onClick: d, onDrilldown: f }) {
197
226
  children: /* @__PURE__ */ s("div", {
198
227
  className: "text-center",
199
228
  children: [/* @__PURE__ */ o("svg", {
200
- className: "w-12 h-12 mx-auto mb-2 text-text-tertiary",
229
+ className: "w-12 h-12 mx-auto mb-2 text-text-muted",
201
230
  fill: "none",
202
231
  stroke: "currentColor",
203
232
  viewBox: "0 0 24 24",
@@ -212,6 +241,6 @@ var d = r(function({ widget: r, data: c, onClick: d, onDrilldown: f }) {
212
241
  });
213
242
  });
214
243
  //#endregion
215
- export { d as default };
244
+ export { g as default };
216
245
 
217
246
  //# sourceMappingURL=GaugeWidget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GaugeWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/gauge/GaugeWidget.tsx"],"sourcesContent":["/**\n * GaugeWidget Component\n *\n * Gauge widget with circular and linear variants.\n */\n\nimport { type FC, memo, useMemo, useCallback } from 'react';\nimport type { Widget, GaugeConfig } from '../../../types';\nimport { CircularGauge, type ThresholdConfig } from './CircularGauge';\nimport { LinearGauge } from './LinearGauge';\nimport { unwrapRows } from '../utils/inferFields';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GaugeWidgetProps {\n /** Widget configuration */\n widget: Widget;\n /** Gauge data */\n data?: GaugeData;\n /** Click handler for drilldown */\n onClick?: () => void;\n /** Drilldown handler - receives gauge data */\n onDrilldown?: (selectedData: Record<string, unknown>) => void;\n}\n\nexport interface GaugeData {\n /** Current value */\n value: number;\n /** Optional label */\n label?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst DEFAULT_THRESHOLDS: ThresholdConfig[] = [\n { value: 33, color: 'var(--color-state-error)' },\n { value: 66, color: 'var(--color-state-warning)' },\n { value: 100, color: 'var(--color-state-success)' },\n];\n\nfunction buildThresholds(config?: GaugeConfig): ThresholdConfig[] {\n if (!config?.thresholds?.length) {\n return DEFAULT_THRESHOLDS;\n }\n\n return config.thresholds.map((t) => ({\n value: t.value,\n color:\n t.color === 'success'\n ? 'var(--color-state-success)'\n : t.color === 'warning'\n ? 'var(--color-state-warning)'\n : t.color === 'error'\n ? 'var(--color-state-error)'\n : t.color,\n }));\n}\n\nfunction formatGaugeValue(value: number, config?: GaugeConfig): string {\n const format = config?.format || 'number';\n\n switch (format) {\n case 'percentage':\n return `${value.toFixed(0)}%`;\n case 'currency':\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n maximumFractionDigits: 0,\n }).format(value);\n case 'number':\n default:\n return new Intl.NumberFormat('en-US', {\n maximumFractionDigits: config?.decimals || 0,\n }).format(value);\n }\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const GaugeWidget: FC<GaugeWidgetProps> = memo(function GaugeWidget({\n widget,\n data: rawData,\n onClick,\n onDrilldown,\n}) {\n const config = widget.config as unknown as GaugeConfig | undefined;\n\n const thresholds = useMemo(() => buildThresholds(config), [config]);\n\n const formatValue = useCallback((value: number) => formatGaugeValue(value, config), [config]);\n\n const hasDrilldown = !!widget.drilldown?.enabled;\n const isLinear = config?.variant === 'linear';\n\n // Normalize data from different formats (DataSink array, single object, etc.)\n const normalizedData = useMemo((): GaugeData | null => {\n if (!rawData) return null;\n\n // Explicit top-level `value` always wins — even if a sibling envelope\n // key exists (`{value: 42, data: [...]}` is a common summary+detail\n // shape) we prefer the summary value rather than coercing to array mode.\n if (rawData && typeof rawData === 'object' && !Array.isArray(rawData)) {\n const asRecord = rawData as unknown as Record<string, unknown>;\n if ('value' in asRecord && typeof asRecord.value === 'number') {\n return rawData as GaugeData;\n }\n }\n\n // BOFF-2246: unwrap common envelopes so the existing array handler below\n // (with its rich common-field heuristics) runs for parsers emitting\n // `{data: [...]}` / `{items: [...]}` — previously those payloads hit\n // \"No gauge data\" because no handler matched.\n //\n // Caveat: summary+detail payloads like `{ totalSales: 120, data: [...] }`\n // should keep the top-level numeric (the existing single-object handler\n // below has a generic \"any numeric field\" last-resort scan that would\n // otherwise surface it). Skip the unwrap whenever ANY numeric sibling\n // exists alongside the envelope key — matches the scope of the generic\n // scan so we don't regress previously-working payloads.\n let data: unknown = rawData;\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n const obj = data as Record<string, unknown>;\n const hasTopLevelNumericSibling = Object.entries(obj).some(([k, v]) => {\n if (k === 'data' || k === 'items' || k === 'rows') return false;\n return typeof v === 'number';\n });\n\n if (!hasTopLevelNumericSibling) {\n // Array-aware unwrap — picks the first envelope key that's actually\n // an array, so payloads like `{data: {page: 1}, items: [...]}` still\n // reach the array handler below.\n const maybe = unwrapRows(obj);\n if (maybe && maybe.length > 0) data = maybe;\n }\n }\n\n // Get configured value field from widget config\n const valueField =\n ((config as Record<string, unknown> | undefined)?.valueField as string) ||\n ((config as Record<string, unknown> | undefined)?.value_field as string) ||\n 'value';\n\n // Handle array from DataSink - extract value from first item\n if (Array.isArray(data) && data.length > 0) {\n const firstItem = data[0] as Record<string, unknown>;\n\n // Try configured field first\n if (typeof firstItem[valueField] === 'number') {\n return {\n value: firstItem[valueField] as number,\n label: typeof firstItem.label === 'string' ? firstItem.label : undefined,\n };\n }\n\n // Try common numeric field names\n const numericFields = [\n 'value',\n 'growth',\n 'percentage',\n 'percent',\n 'progress',\n 'score',\n 'rate',\n 'amount',\n 'total',\n ];\n for (const field of numericFields) {\n if (typeof firstItem[field] === 'number') {\n return {\n value: firstItem[field] as number,\n label:\n typeof firstItem.label === 'string'\n ? firstItem.label\n : typeof firstItem.name === 'string'\n ? firstItem.name\n : undefined,\n };\n }\n }\n\n // Find any numeric field\n const numericEntry = Object.entries(firstItem).find(([, v]) => typeof v === 'number');\n if (numericEntry) {\n return {\n value: numericEntry[1] as number,\n label: `${numericEntry[0].charAt(0).toUpperCase()}${numericEntry[0].slice(1)}`,\n };\n }\n\n // Try to aggregate (average) across all rows if single item didn't work\n if (data.length > 1) {\n const allNumericFields = Object.entries(firstItem).filter(([, v]) => typeof v === 'number');\n if (allNumericFields.length > 0) {\n const [fieldName] = allNumericFields[0];\n const avg =\n data.reduce((sum, row) => {\n const val = (row as Record<string, unknown>)[fieldName];\n return sum + (typeof val === 'number' ? val : 0);\n }, 0) / data.length;\n\n return {\n value: Math.round(avg * 100) / 100,\n label: `Avg ${fieldName.charAt(0).toUpperCase()}${fieldName.slice(1)}`,\n };\n }\n }\n }\n\n // Handle single object without 'value' property\n if (typeof data === 'object' && !Array.isArray(data)) {\n const dataObj = data as unknown as Record<string, unknown>;\n\n // Try configured field\n if (typeof dataObj[valueField] === 'number') {\n return {\n value: dataObj[valueField] as number,\n label: typeof dataObj.label === 'string' ? dataObj.label : undefined,\n };\n }\n\n // Try common field names\n const numericFields = [\n 'value',\n 'growth',\n 'percentage',\n 'percent',\n 'progress',\n 'score',\n 'rate',\n 'amount',\n 'total',\n ];\n for (const field of numericFields) {\n if (typeof dataObj[field] === 'number') {\n return {\n value: dataObj[field] as number,\n label: typeof dataObj.label === 'string' ? dataObj.label : undefined,\n };\n }\n }\n\n // Find any numeric field\n const numericEntry = Object.entries(dataObj).find(([, v]) => typeof v === 'number');\n if (numericEntry) {\n return {\n value: numericEntry[1] as number,\n label: `${numericEntry[0].charAt(0).toUpperCase()}${numericEntry[0].slice(1)}`,\n };\n }\n }\n\n // Handle direct number\n if (typeof data === 'number') {\n return { value: data };\n }\n\n // Handle string that can be parsed as number\n if (typeof data === 'string') {\n const parsed = parseFloat(data);\n if (!isNaN(parsed)) {\n return { value: parsed };\n }\n }\n\n return null;\n }, [rawData, config]);\n\n // Handle drilldown click - must be after normalizedData is computed\n const handleClick = useCallback(() => {\n // Support both legacy onClick and new onDrilldown\n if (onDrilldown && normalizedData) {\n onDrilldown({\n value: normalizedData.value,\n label: normalizedData.label,\n min: config?.min,\n max: config?.max,\n });\n } else if (onClick && widget.drilldowns?.length) {\n onClick();\n }\n }, [onClick, onDrilldown, widget.drilldowns, normalizedData, config?.min, config?.max]);\n\n const isClickable = Boolean(hasDrilldown || (onClick && widget.drilldowns?.length));\n\n if (!normalizedData) {\n return (\n <div className=\"flex items-center justify-center h-full text-text-secondary text-sm\">\n <div className=\"text-center\">\n <svg\n className=\"w-12 h-12 mx-auto mb-2 text-text-tertiary\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n <p>No gauge data</p>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`\n flex flex-col items-center justify-center h-full p-4\n ${isClickable ? 'cursor-pointer hover:bg-bg-sunken/50 transition-colors' : ''}\n `}\n onClick={handleClick}\n role={isClickable ? 'button' : undefined}\n tabIndex={isClickable ? 0 : undefined}\n onKeyDown={(e) => {\n if (isClickable && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n handleClick();\n }\n }}\n >\n {/* Label */}\n {normalizedData.label && <p className=\"text-sm text-text-secondary mb-3 text-center\">{normalizedData.label}</p>}\n\n {/* Gauge */}\n <div className={`${isLinear ? 'w-full max-w-xs' : ''}`}>\n {isLinear ? (\n <LinearGauge\n value={normalizedData.value}\n min={config?.min}\n max={config?.max}\n thresholds={thresholds}\n unit={config?.unit}\n formatValue={formatValue}\n showZones={config?.showZones}\n />\n ) : (\n <CircularGauge\n value={normalizedData.value}\n min={config?.min}\n max={config?.max}\n thresholds={thresholds}\n unit={config?.unit}\n formatValue={formatValue}\n size={config?.size === 'sm' ? 100 : config?.size === 'md' ? 140 : config?.size === 'lg' ? 180 : 140}\n />\n )}\n </div>\n\n {/* Drilldown indicator */}\n {isClickable && (\n <div className=\"mt-3 flex items-center justify-center\">\n <span className=\"text-xs text-text-secondary flex items-center gap-1\">\n View details\n <svg className=\"w-3 h-3\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </span>\n </div>\n )}\n </div>\n );\n});\n\nexport default GaugeWidget;\n"],"mappings":";;;;;;AAsCA,IAAM,IAAwC;CAC5C;EAAE,OAAO;EAAI,OAAO;EAA4B;CAChD;EAAE,OAAO;EAAI,OAAO;EAA8B;CAClD;EAAE,OAAO;EAAK,OAAO;EAA8B;CACpD;AAED,SAAS,EAAgB,GAAyC;AAKhE,QAJK,GAAQ,YAAY,SAIlB,EAAO,WAAW,KAAK,OAAO;EACnC,OAAO,EAAE;EACT,OACE,EAAE,UAAU,YACR,+BACA,EAAE,UAAU,YACV,+BACA,EAAE,UAAU,UACV,6BACA,EAAE;EACb,EAAE,GAbM;;AAgBX,SAAS,EAAiB,GAAe,GAA8B;AAGrE,SAFe,GAAQ,UAAU,UAEjC;EACE,KAAK,aACH,QAAO,GAAG,EAAM,QAAQ,EAAE,CAAC;EAC7B,KAAK,WACH,QAAO,IAAI,KAAK,aAAa,SAAS;GACpC,OAAO;GACP,UAAU;GACV,uBAAuB;GACxB,CAAC,CAAC,OAAO,EAAM;EAElB,QACE,QAAO,IAAI,KAAK,aAAa,SAAS,EACpC,uBAAuB,GAAQ,YAAY,GAC5C,CAAC,CAAC,OAAO,EAAM;;;AAQtB,IAAa,IAAoC,EAAK,SAAqB,EACzE,WACA,MAAM,GACN,YACA,kBACC;CACD,IAAM,IAAS,EAAO,QAEhB,IAAa,QAAc,EAAgB,EAAO,EAAE,CAAC,EAAO,CAAC,EAE7D,IAAc,GAAa,MAAkB,EAAiB,GAAO,EAAO,EAAE,CAAC,EAAO,CAAC,EAEvF,IAAe,CAAC,CAAC,EAAO,WAAW,SACnC,IAAW,GAAQ,YAAY,UAG/B,IAAiB,QAAgC;AACrD,MAAI,CAAC,EAAS,QAAO;AAKrB,MAAI,KAAW,OAAO,KAAY,YAAY,CAAC,MAAM,QAAQ,EAAQ,EAAE;GACrE,IAAM,IAAW;AACjB,OAAI,WAAW,KAAY,OAAO,EAAS,SAAU,SACnD,QAAO;;EAeX,IAAI,IAAgB;AACpB,MAAI,KAAQ,OAAO,KAAS,YAAY,CAAC,MAAM,QAAQ,EAAK,EAAE;GAC5D,IAAM,IAAM;AAMZ,OAAI,CAL8B,OAAO,QAAQ,EAAI,CAAC,MAAM,CAAC,GAAG,OAC1D,MAAM,UAAU,MAAM,WAAW,MAAM,SAAe,KACnD,OAAO,KAAM,SACpB,EAE8B;IAI9B,IAAM,IAAQ,EAAW,EAAI;AAC7B,IAAI,KAAS,EAAM,SAAS,MAAG,IAAO;;;EAK1C,IAAM,IACF,GAAgD,cAChD,GAAgD,eAClD;AAGF,MAAI,MAAM,QAAQ,EAAK,IAAI,EAAK,SAAS,GAAG;GAC1C,IAAM,IAAY,EAAK;AAGvB,OAAI,OAAO,EAAU,MAAgB,SACnC,QAAO;IACL,OAAO,EAAU;IACjB,OAAO,OAAO,EAAU,SAAU,WAAW,EAAU,QAAQ,KAAA;IAChE;AAeH,QAAK,IAAM,KAXW;IACpB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD,CAEC,KAAI,OAAO,EAAU,MAAW,SAC9B,QAAO;IACL,OAAO,EAAU;IACjB,OACE,OAAO,EAAU,SAAU,WACvB,EAAU,QACV,OAAO,EAAU,QAAS,WACxB,EAAU,OACV,KAAA;IACT;GAKL,IAAM,IAAe,OAAO,QAAQ,EAAU,CAAC,MAAM,GAAG,OAAO,OAAO,KAAM,SAAS;AACrF,OAAI,EACF,QAAO;IACL,OAAO,EAAa;IACpB,OAAO,GAAG,EAAa,GAAG,OAAO,EAAE,CAAC,aAAa,GAAG,EAAa,GAAG,MAAM,EAAE;IAC7E;AAIH,OAAI,EAAK,SAAS,GAAG;IACnB,IAAM,IAAmB,OAAO,QAAQ,EAAU,CAAC,QAAQ,GAAG,OAAO,OAAO,KAAM,SAAS;AAC3F,QAAI,EAAiB,SAAS,GAAG;KAC/B,IAAM,CAAC,KAAa,EAAiB,IAC/B,IACJ,EAAK,QAAQ,GAAK,MAAQ;MACxB,IAAM,IAAO,EAAgC;AAC7C,aAAO,KAAO,OAAO,KAAQ,WAAW,IAAM;QAC7C,EAAE,GAAG,EAAK;AAEf,YAAO;MACL,OAAO,KAAK,MAAM,IAAM,IAAI,GAAG;MAC/B,OAAO,OAAO,EAAU,OAAO,EAAE,CAAC,aAAa,GAAG,EAAU,MAAM,EAAE;MACrE;;;;AAMP,MAAI,OAAO,KAAS,YAAY,CAAC,MAAM,QAAQ,EAAK,EAAE;GACpD,IAAM,IAAU;AAGhB,OAAI,OAAO,EAAQ,MAAgB,SACjC,QAAO;IACL,OAAO,EAAQ;IACf,OAAO,OAAO,EAAQ,SAAU,WAAW,EAAQ,QAAQ,KAAA;IAC5D;AAeH,QAAK,IAAM,KAXW;IACpB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD,CAEC,KAAI,OAAO,EAAQ,MAAW,SAC5B,QAAO;IACL,OAAO,EAAQ;IACf,OAAO,OAAO,EAAQ,SAAU,WAAW,EAAQ,QAAQ,KAAA;IAC5D;GAKL,IAAM,IAAe,OAAO,QAAQ,EAAQ,CAAC,MAAM,GAAG,OAAO,OAAO,KAAM,SAAS;AACnF,OAAI,EACF,QAAO;IACL,OAAO,EAAa;IACpB,OAAO,GAAG,EAAa,GAAG,OAAO,EAAE,CAAC,aAAa,GAAG,EAAa,GAAG,MAAM,EAAE;IAC7E;;AAKL,MAAI,OAAO,KAAS,SAClB,QAAO,EAAE,OAAO,GAAM;AAIxB,MAAI,OAAO,KAAS,UAAU;GAC5B,IAAM,IAAS,WAAW,EAAK;AAC/B,OAAI,CAAC,MAAM,EAAO,CAChB,QAAO,EAAE,OAAO,GAAQ;;AAI5B,SAAO;IACN,CAAC,GAAS,EAAO,CAAC,EAGf,IAAc,QAAkB;AAEpC,EAAI,KAAe,IACjB,EAAY;GACV,OAAO,EAAe;GACtB,OAAO,EAAe;GACtB,KAAK,GAAQ;GACb,KAAK,GAAQ;GACd,CAAC,GACO,KAAW,EAAO,YAAY,UACvC,GAAS;IAEV;EAAC;EAAS;EAAa,EAAO;EAAY;EAAgB,GAAQ;EAAK,GAAQ;EAAI,CAAC,EAEjF,IAAc,GAAQ,KAAiB,KAAW,EAAO,YAAY;AAyB3E,QAvBK,IAwBH,kBAAC,OAAD;EACE,WAAW;;UAEP,IAAc,2DAA2D,GAAG;;EAEhF,SAAS;EACT,MAAM,IAAc,WAAW,KAAA;EAC/B,UAAU,IAAc,IAAI,KAAA;EAC5B,YAAY,MAAM;AAChB,GAAI,MAAgB,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjD,EAAE,gBAAgB,EAClB,GAAa;;YAXnB;GAgBG,EAAe,SAAS,kBAAC,KAAD;IAAG,WAAU;cAAgD,EAAe;IAAU,CAAA;GAG/G,kBAAC,OAAD;IAAK,WAAW,GAAG,IAAW,oBAAoB;cAC/C,IACC,kBAAC,GAAD;KACE,OAAO,EAAe;KACtB,KAAK,GAAQ;KACb,KAAK,GAAQ;KACD;KACZ,MAAM,GAAQ;KACD;KACb,WAAW,GAAQ;KACnB,CAAA,GAEF,kBAAC,GAAD;KACE,OAAO,EAAe;KACtB,KAAK,GAAQ;KACb,KAAK,GAAQ;KACD;KACZ,MAAM,GAAQ;KACD;KACb,MAAM,GAAQ,SAAS,OAAO,MAAM,GAAQ,SAAS,OAAO,MAAM,GAAQ,SAAS,OAAO,MAAM;KAChG,CAAA;IAEA,CAAA;GAGL,KACC,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,QAAD;KAAM,WAAU;eAAhB,CAAsE,gBAEpE,kBAAC,OAAD;MAAK,WAAU;MAAU,MAAK;MAAO,QAAO;MAAe,SAAQ;gBACjE,kBAAC,QAAD;OAAM,eAAc;OAAQ,gBAAe;OAAQ,aAAa;OAAG,GAAE;OAAiB,CAAA;MAClF,CAAA,CACD;;IACH,CAAA;GAEJ;MA5EJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,QAAO;IACP,SAAQ;cAER,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA,EACN,kBAAC,KAAD,EAAA,UAAG,iBAAiB,CAAA,CAChB;;EACF,CAAA;EA6DV"}
1
+ {"version":3,"file":"GaugeWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/gauge/GaugeWidget.tsx"],"sourcesContent":["/**\n * GaugeWidget Component\n *\n * Gauge widget with circular and linear variants.\n */\n\nimport { type FC, memo, useMemo, useCallback } from 'react';\nimport type { Widget, GaugeConfig } from '../../../types';\nimport { CircularGauge, type ThresholdConfig } from './CircularGauge';\nimport { LinearGauge } from './LinearGauge';\nimport { unwrapRows } from '../utils/inferFields';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GaugeWidgetProps {\n /** Widget configuration */\n widget: Widget;\n /** Gauge data */\n data?: GaugeData;\n /** Click handler for drilldown */\n onClick?: () => void;\n /** Drilldown handler - receives gauge data */\n onDrilldown?: (selectedData: Record<string, unknown>) => void;\n}\n\nexport interface GaugeData {\n /** Current value */\n value: number;\n /** Optional label */\n label?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Semantic threshold colours.\n *\n * These MUST reference custom properties that actually exist in\n * `@burdenoff/fe-libs` (`--color-status-*`, see fe-libs\n * `src/shared/tokens/build/semantic.css`). An undefined custom property is\n * invalid-at-computed-value-time, so the browser drops the declaration\n * entirely: the SVG arc falls back to `stroke: none` and the linear bar to\n * `background-color: transparent` — i.e. the gauge renders permanently empty.\n */\nconst THRESHOLD_TOKENS = {\n success: 'var(--color-status-success-bg)',\n warning: 'var(--color-status-warning-bg)',\n error: 'var(--color-status-error-bg)',\n} as const;\n\ntype ThresholdToken = keyof typeof THRESHOLD_TOKENS;\n\n/**\n * Raw colours that already exist in persisted widget configs, mapped onto the\n * semantic token carrying the same meaning.\n *\n * Two sources produce these: older bundled-registry defaults ('red'/'yellow'/\n * 'green') and the BACKEND widget catalog, whose gauge `defaultConfig` seeds\n * hex (`#ef4444`/`#f59e0b`/`#22c55e`) and wins wholesale over the bundled\n * defaults on create (DashboardCanvas: `widgetData.defaultConfig || definition.defaultConfig`).\n * Translating them keeps existing gauges painting the intended colour *and*\n * makes them theme-aware, instead of being stuck on a fixed light-mode hex.\n */\nconst LEGACY_COLOR_ALIASES: Readonly<Record<string, ThresholdToken>> = {\n red: 'error',\n '#ef4444': 'error',\n '#dc2626': 'error',\n yellow: 'warning',\n amber: 'warning',\n orange: 'warning',\n '#f59e0b': 'warning',\n '#eab308': 'warning',\n green: 'success',\n '#22c55e': 'success',\n '#059669': 'success',\n};\n\nfunction isThresholdToken(color: string): color is ThresholdToken {\n return color in THRESHOLD_TOKENS;\n}\n\n/** Any CSS colour a persisted config might legitimately carry. */\nfunction looksLikeCssColor(color: string): boolean {\n // Valid hex lengths are 3, 4, 6 and 8 — a `{3,8}` range would also admit\n // 5- and 7-digit strings, which are not colours and should fall back rather\n // than reach the DOM.\n return (\n /^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color) ||\n /^(rgb|rgba|hsl|hsla|color|oklch|lab)\\(/i.test(color)\n );\n}\n\n/**\n * Resolve a configured threshold colour to a paintable value.\n *\n * Order matters. Semantic names and known legacy colours become tokens so they\n * theme correctly. An explicit `var(--…)` passes through. An unrecognised but\n * valid *hex or function-syntax* CSS colour also passes through: it is\n * user/backend data rather than source code, and substituting a token would\n * silently repaint a red band blue — worse than the theming smell it would fix.\n *\n * Bare CSS named colours are deliberately NOT passed through. The ones that\n * historically appear in gauge configs are covered by `LEGACY_COLOR_ALIASES`;\n * anything else is far likelier a misconfiguration than an intent, so it falls\n * back to a token (with a dev warning) rather than reaching the DOM.\n */\nfunction resolveThresholdColor(color: string): string {\n const normalized = color.trim().toLowerCase();\n\n if (isThresholdToken(normalized)) return THRESHOLD_TOKENS[normalized];\n\n const alias = LEGACY_COLOR_ALIASES[normalized];\n if (alias) return THRESHOLD_TOKENS[alias];\n\n // Already a token reference — pass through untouched.\n if (normalized.startsWith('var(')) return color;\n\n if (looksLikeCssColor(normalized)) {\n if (import.meta.env.DEV) {\n console.warn(\n `[GaugeWidget] Threshold colour \"${color}\" is a raw CSS colour and will not ` +\n 'adapt to the active theme. Prefer success/warning/error, which map to fe-libs tokens.'\n );\n }\n return color;\n }\n\n if (import.meta.env.DEV) {\n console.warn(\n `[GaugeWidget] Unrecognised threshold colour \"${color}\" — expected one of ` +\n `${Object.keys(THRESHOLD_TOKENS).join('/')}, a CSS colour, or a var(--color-…) token. ` +\n 'Falling back to the primary token so the gauge still paints.'\n );\n }\n\n return 'var(--color-action-primary-bg)';\n}\n\nconst DEFAULT_THRESHOLDS: ThresholdConfig[] = [\n { value: 33, color: THRESHOLD_TOKENS.error },\n { value: 66, color: THRESHOLD_TOKENS.warning },\n { value: 100, color: THRESHOLD_TOKENS.success },\n];\n\nfunction buildThresholds(config?: GaugeConfig): ThresholdConfig[] {\n if (!config?.thresholds?.length) {\n return DEFAULT_THRESHOLDS;\n }\n\n return config.thresholds.map((t) => ({\n value: t.value,\n color: resolveThresholdColor(t.color),\n }));\n}\n\nfunction formatGaugeValue(value: number, config?: GaugeConfig): string {\n const format = config?.format || 'number';\n\n switch (format) {\n case 'percentage':\n return `${value.toFixed(0)}%`;\n case 'currency':\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n maximumFractionDigits: 0,\n }).format(value);\n case 'number':\n default:\n return new Intl.NumberFormat('en-US', {\n maximumFractionDigits: config?.decimals || 0,\n }).format(value);\n }\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const GaugeWidget: FC<GaugeWidgetProps> = memo(function GaugeWidget({\n widget,\n data: rawData,\n onClick,\n onDrilldown,\n}) {\n const config = widget.config as unknown as GaugeConfig | undefined;\n\n const thresholds = useMemo(() => buildThresholds(config), [config]);\n\n const formatValue = useCallback((value: number) => formatGaugeValue(value, config), [config]);\n\n const hasDrilldown = !!widget.drilldown?.enabled;\n const isLinear = config?.variant === 'linear';\n\n // Normalize data from different formats (DataSink array, single object, etc.)\n const normalizedData = useMemo((): GaugeData | null => {\n if (!rawData) return null;\n\n // Explicit top-level `value` always wins — even if a sibling envelope\n // key exists (`{value: 42, data: [...]}` is a common summary+detail\n // shape) we prefer the summary value rather than coercing to array mode.\n if (rawData && typeof rawData === 'object' && !Array.isArray(rawData)) {\n const asRecord = rawData as unknown as Record<string, unknown>;\n if ('value' in asRecord && typeof asRecord.value === 'number') {\n return rawData as GaugeData;\n }\n }\n\n // BOFF-2246: unwrap common envelopes so the existing array handler below\n // (with its rich common-field heuristics) runs for parsers emitting\n // `{data: [...]}` / `{items: [...]}` — previously those payloads hit\n // \"No gauge data\" because no handler matched.\n //\n // Caveat: summary+detail payloads like `{ totalSales: 120, data: [...] }`\n // should keep the top-level numeric (the existing single-object handler\n // below has a generic \"any numeric field\" last-resort scan that would\n // otherwise surface it). Skip the unwrap whenever ANY numeric sibling\n // exists alongside the envelope key — matches the scope of the generic\n // scan so we don't regress previously-working payloads.\n let data: unknown = rawData;\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n const obj = data as Record<string, unknown>;\n const hasTopLevelNumericSibling = Object.entries(obj).some(([k, v]) => {\n if (k === 'data' || k === 'items' || k === 'rows') return false;\n return typeof v === 'number';\n });\n\n if (!hasTopLevelNumericSibling) {\n // Array-aware unwrap — picks the first envelope key that's actually\n // an array, so payloads like `{data: {page: 1}, items: [...]}` still\n // reach the array handler below.\n const maybe = unwrapRows(obj);\n if (maybe && maybe.length > 0) data = maybe;\n }\n }\n\n // Get configured value field from widget config\n const valueField =\n ((config as Record<string, unknown> | undefined)?.valueField as string) ||\n ((config as Record<string, unknown> | undefined)?.value_field as string) ||\n 'value';\n\n // Handle array from DataSink - extract value from first item\n if (Array.isArray(data) && data.length > 0) {\n const firstItem = data[0] as Record<string, unknown>;\n\n // Try configured field first\n if (typeof firstItem[valueField] === 'number') {\n return {\n value: firstItem[valueField] as number,\n label: typeof firstItem.label === 'string' ? firstItem.label : undefined,\n };\n }\n\n // Try common numeric field names\n const numericFields = [\n 'value',\n 'growth',\n 'percentage',\n 'percent',\n 'progress',\n 'score',\n 'rate',\n 'amount',\n 'total',\n ];\n for (const field of numericFields) {\n if (typeof firstItem[field] === 'number') {\n return {\n value: firstItem[field] as number,\n label:\n typeof firstItem.label === 'string'\n ? firstItem.label\n : typeof firstItem.name === 'string'\n ? firstItem.name\n : undefined,\n };\n }\n }\n\n // Find any numeric field\n const numericEntry = Object.entries(firstItem).find(([, v]) => typeof v === 'number');\n if (numericEntry) {\n return {\n value: numericEntry[1] as number,\n label: `${numericEntry[0].charAt(0).toUpperCase()}${numericEntry[0].slice(1)}`,\n };\n }\n\n // Try to aggregate (average) across all rows if single item didn't work\n if (data.length > 1) {\n const allNumericFields = Object.entries(firstItem).filter(([, v]) => typeof v === 'number');\n if (allNumericFields.length > 0) {\n const [fieldName] = allNumericFields[0];\n const avg =\n data.reduce((sum, row) => {\n const val = (row as Record<string, unknown>)[fieldName];\n return sum + (typeof val === 'number' ? val : 0);\n }, 0) / data.length;\n\n return {\n value: Math.round(avg * 100) / 100,\n label: `Avg ${fieldName.charAt(0).toUpperCase()}${fieldName.slice(1)}`,\n };\n }\n }\n }\n\n // Handle single object without 'value' property\n if (typeof data === 'object' && !Array.isArray(data)) {\n const dataObj = data as unknown as Record<string, unknown>;\n\n // Try configured field\n if (typeof dataObj[valueField] === 'number') {\n return {\n value: dataObj[valueField] as number,\n label: typeof dataObj.label === 'string' ? dataObj.label : undefined,\n };\n }\n\n // Try common field names\n const numericFields = [\n 'value',\n 'growth',\n 'percentage',\n 'percent',\n 'progress',\n 'score',\n 'rate',\n 'amount',\n 'total',\n ];\n for (const field of numericFields) {\n if (typeof dataObj[field] === 'number') {\n return {\n value: dataObj[field] as number,\n label: typeof dataObj.label === 'string' ? dataObj.label : undefined,\n };\n }\n }\n\n // Find any numeric field\n const numericEntry = Object.entries(dataObj).find(([, v]) => typeof v === 'number');\n if (numericEntry) {\n return {\n value: numericEntry[1] as number,\n label: `${numericEntry[0].charAt(0).toUpperCase()}${numericEntry[0].slice(1)}`,\n };\n }\n }\n\n // Handle direct number\n if (typeof data === 'number') {\n return { value: data };\n }\n\n // Handle string that can be parsed as number\n if (typeof data === 'string') {\n const parsed = parseFloat(data);\n if (!isNaN(parsed)) {\n return { value: parsed };\n }\n }\n\n return null;\n }, [rawData, config]);\n\n // Handle drilldown click - must be after normalizedData is computed\n const handleClick = useCallback(() => {\n // Support both legacy onClick and new onDrilldown\n if (onDrilldown && normalizedData) {\n onDrilldown({\n value: normalizedData.value,\n label: normalizedData.label,\n min: config?.min,\n max: config?.max,\n });\n } else if (onClick && widget.drilldowns?.length) {\n onClick();\n }\n }, [onClick, onDrilldown, widget.drilldowns, normalizedData, config?.min, config?.max]);\n\n const isClickable = Boolean(hasDrilldown || (onClick && widget.drilldowns?.length));\n\n if (!normalizedData) {\n return (\n <div className=\"flex items-center justify-center h-full text-text-secondary text-sm\">\n <div className=\"text-center\">\n <svg className=\"w-12 h-12 mx-auto mb-2 text-text-muted\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n <p>No gauge data</p>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`\n flex flex-col items-center justify-center h-full p-4\n ${isClickable ? 'cursor-pointer hover:bg-bg-sunken/50 transition-colors' : ''}\n `}\n onClick={handleClick}\n role={isClickable ? 'button' : undefined}\n tabIndex={isClickable ? 0 : undefined}\n onKeyDown={(e) => {\n if (isClickable && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n handleClick();\n }\n }}\n >\n {/* Label */}\n {normalizedData.label && <p className=\"text-sm text-text-secondary mb-3 text-center\">{normalizedData.label}</p>}\n\n {/* Gauge */}\n <div className={`${isLinear ? 'w-full max-w-xs' : ''}`}>\n {isLinear ? (\n <LinearGauge\n value={normalizedData.value}\n min={config?.min}\n max={config?.max}\n thresholds={thresholds}\n unit={config?.unit}\n formatValue={formatValue}\n showZones={config?.showZones}\n />\n ) : (\n <CircularGauge\n value={normalizedData.value}\n min={config?.min}\n max={config?.max}\n thresholds={thresholds}\n unit={config?.unit}\n formatValue={formatValue}\n size={config?.size === 'sm' ? 100 : config?.size === 'md' ? 140 : config?.size === 'lg' ? 180 : 140}\n />\n )}\n </div>\n\n {/* Drilldown indicator */}\n {isClickable && (\n <div className=\"mt-3 flex items-center justify-center\">\n <span className=\"text-xs text-text-secondary flex items-center gap-1\">\n View details\n <svg className=\"w-3 h-3\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </span>\n </div>\n )}\n </div>\n );\n});\n\nexport default GaugeWidget;\n"],"mappings":"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"}
@@ -1,55 +1,56 @@
1
- import { memo as e, useMemo as t } from "react";
2
- import { jsx as n, jsxs as r } from "react/jsx-runtime";
1
+ import { gaugeSpan as e } from "./CircularGauge.js";
2
+ import { memo as t, useMemo as n } from "react";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
3
4
  //#region src/bigconsole/components/widgets/gauge/LinearGauge.tsx
4
- function i(e, t) {
5
+ function a(e, t) {
5
6
  if (!t?.length) return "var(--color-action-primary-bg)";
6
7
  let n = [...t].sort((e, t) => e.value - t.value);
7
8
  for (let t of n) if (e <= t.value) return t.color;
8
9
  return n[n.length - 1].color;
9
10
  }
10
- var a = e(function({ value: e, min: a = 0, max: o = 100, height: s = 12, thresholds: c, unit: l, showValue: u = !0, showRange: d = !0, formatValue: f = (e) => e.toFixed(0), showZones: p = !1 }) {
11
- let m = t(() => (Math.max(a, Math.min(o, e)) - a) / (o - a) * 100, [
12
- e,
13
- a,
14
- o
15
- ]), h = i(e, c), g = t(() => {
16
- if (!p || !c?.length) return null;
17
- let e = [...c].sort((e, t) => e.value - t.value), t = [], n = a;
18
- for (let r of e) {
19
- let e = (r.value - n) / (o - a) * 100;
20
- t.push({
21
- width: e,
22
- color: r.color
23
- }), n = r.value;
11
+ var o = t(function({ value: t, min: o = 0, max: s = 100, height: c = 12, thresholds: l, unit: u, showValue: d = !0, showRange: f = !0, formatValue: p = (e) => e.toFixed(0), showZones: m = !1 }) {
12
+ let h = n(() => (Math.max(o, Math.min(s, t)) - o) / e(o, s) * 100, [
13
+ t,
14
+ o,
15
+ s
16
+ ]), g = a(t, l), _ = n(() => {
17
+ if (!m || !l?.length) return null;
18
+ let t = [...l].sort((e, t) => e.value - t.value), n = [], r = o;
19
+ for (let i of t) {
20
+ let t = (i.value - r) / e(o, s) * 100;
21
+ n.push({
22
+ width: t,
23
+ color: i.color
24
+ }), r = i.value;
24
25
  }
25
- return t;
26
+ return n;
26
27
  }, [
27
- p,
28
- c,
29
- a,
30
- o
28
+ m,
29
+ l,
30
+ o,
31
+ s
31
32
  ]);
32
- return /* @__PURE__ */ r("div", {
33
+ return /* @__PURE__ */ i("div", {
33
34
  className: "w-full",
34
35
  children: [
35
- u && /* @__PURE__ */ r("div", {
36
+ d && /* @__PURE__ */ i("div", {
36
37
  className: "flex items-baseline gap-1 mb-2",
37
- children: [/* @__PURE__ */ n("span", {
38
+ children: [/* @__PURE__ */ r("span", {
38
39
  className: "text-2xl font-bold",
39
- style: { color: h },
40
- children: f(e)
41
- }), l && /* @__PURE__ */ n("span", {
40
+ style: { color: g },
41
+ children: p(t)
42
+ }), u && /* @__PURE__ */ r("span", {
42
43
  className: "text-sm text-text-secondary",
43
- children: l
44
+ children: u
44
45
  })]
45
46
  }),
46
- /* @__PURE__ */ r("div", {
47
+ /* @__PURE__ */ i("div", {
47
48
  className: "relative w-full rounded-full overflow-hidden bg-bg-sunken",
48
- style: { height: s },
49
+ style: { height: c },
49
50
  children: [
50
- g && /* @__PURE__ */ n("div", {
51
+ _ && /* @__PURE__ */ r("div", {
51
52
  className: "absolute inset-0 flex",
52
- children: g.map((e, t) => /* @__PURE__ */ n("div", {
53
+ children: _.map((e, t) => /* @__PURE__ */ r("div", {
53
54
  className: "h-full opacity-20",
54
55
  style: {
55
56
  width: `${e.width}%`,
@@ -57,36 +58,36 @@ var a = e(function({ value: e, min: a = 0, max: o = 100, height: s = 12, thresho
57
58
  }
58
59
  }, t))
59
60
  }),
60
- /* @__PURE__ */ n("div", {
61
+ /* @__PURE__ */ r("div", {
61
62
  className: "absolute inset-y-0 left-0 rounded-full transition-all duration-500 ease-out",
62
63
  style: {
63
- width: `${m}%`,
64
- backgroundColor: h
64
+ width: `${h}%`,
65
+ backgroundColor: g
65
66
  }
66
67
  }),
67
- /* @__PURE__ */ n("div", {
68
+ /* @__PURE__ */ r("div", {
68
69
  className: "absolute top-1/2 -translate-y-1/2 w-1 bg-bg-surface transition-all duration-500",
69
70
  style: {
70
- left: `calc(${m}% - 2px)`,
71
- height: s + 4
71
+ left: `calc(${h}% - 2px)`,
72
+ height: c + 4
72
73
  }
73
74
  })
74
75
  ]
75
76
  }),
76
- d && /* @__PURE__ */ r("div", {
77
+ f && /* @__PURE__ */ i("div", {
77
78
  className: "flex justify-between mt-1",
78
- children: [/* @__PURE__ */ n("span", {
79
+ children: [/* @__PURE__ */ r("span", {
79
80
  className: "text-xs text-text-secondary",
80
- children: f(a)
81
- }), /* @__PURE__ */ n("span", {
81
+ children: p(o)
82
+ }), /* @__PURE__ */ r("span", {
82
83
  className: "text-xs text-text-secondary",
83
- children: f(o)
84
+ children: p(s)
84
85
  })]
85
86
  })
86
87
  ]
87
88
  });
88
89
  });
89
90
  //#endregion
90
- export { a as default };
91
+ export { o as default };
91
92
 
92
93
  //# sourceMappingURL=LinearGauge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinearGauge.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/gauge/LinearGauge.tsx"],"sourcesContent":["/**\n * LinearGauge Component\n *\n * Horizontal linear gauge visualization.\n */\n\nimport { type FC, memo, useMemo } from 'react';\nimport type { ThresholdConfig } from './CircularGauge';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface LinearGaugeProps {\n /** Current value */\n value: number;\n /** Minimum value */\n min?: number;\n /** Maximum value */\n max?: number;\n /** Height of the gauge bar */\n height?: number;\n /** Thresholds for color zones */\n thresholds?: ThresholdConfig[];\n /** Unit label */\n unit?: string;\n /** Whether to show the value */\n showValue?: boolean;\n /** Whether to show min/max labels */\n showRange?: boolean;\n /** Value format function */\n formatValue?: (value: number) => string;\n /** Whether to show color zones */\n showZones?: boolean;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getColorForValue(value: number, thresholds?: ThresholdConfig[]): string {\n if (!thresholds?.length) {\n return 'var(--color-action-primary-bg)';\n }\n\n const sorted = [...thresholds].sort((a, b) => a.value - b.value);\n\n for (const threshold of sorted) {\n if (value <= threshold.value) {\n return threshold.color;\n }\n }\n\n return sorted[sorted.length - 1].color;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const LinearGauge: FC<LinearGaugeProps> = memo(function LinearGauge({\n value,\n min = 0,\n max = 100,\n height = 12,\n thresholds,\n unit,\n showValue = true,\n showRange = true,\n formatValue = (v: number) => v.toFixed(0),\n showZones = false,\n}) {\n // Calculate percentage\n const percentage = useMemo(() => {\n const clampedValue = Math.max(min, Math.min(max, value));\n return ((clampedValue - min) / (max - min)) * 100;\n }, [value, min, max]);\n\n const color = getColorForValue(value, thresholds);\n\n // Calculate zone widths for background\n const zones = useMemo(() => {\n if (!showZones || !thresholds?.length) return null;\n\n const sorted = [...thresholds].sort((a, b) => a.value - b.value);\n const zones: { width: number; color: string }[] = [];\n let prevValue = min;\n\n for (const threshold of sorted) {\n const width = ((threshold.value - prevValue) / (max - min)) * 100;\n zones.push({ width, color: threshold.color });\n prevValue = threshold.value;\n }\n\n return zones;\n }, [showZones, thresholds, min, max]);\n\n return (\n <div className=\"w-full\">\n {/* Value display */}\n {showValue && (\n <div className=\"flex items-baseline gap-1 mb-2\">\n <span className=\"text-2xl font-bold\" style={{ color }}>\n {formatValue(value)}\n </span>\n {unit && <span className=\"text-sm text-text-secondary\">{unit}</span>}\n </div>\n )}\n\n {/* Gauge bar */}\n <div className=\"relative w-full rounded-full overflow-hidden bg-bg-sunken\" style={{ height }}>\n {/* Zone backgrounds */}\n {zones && (\n <div className=\"absolute inset-0 flex\">\n {zones.map((zone, index) => (\n <div\n key={index}\n className=\"h-full opacity-20\"\n style={{ width: `${zone.width}%`, backgroundColor: zone.color }}\n />\n ))}\n </div>\n )}\n\n {/* Value bar */}\n <div\n className=\"absolute inset-y-0 left-0 rounded-full transition-all duration-500 ease-out\"\n style={{\n width: `${percentage}%`,\n backgroundColor: color,\n }}\n />\n\n {/* Value marker */}\n <div\n className=\"absolute top-1/2 -translate-y-1/2 w-1 bg-bg-surface transition-all duration-500\"\n style={{\n left: `calc(${percentage}% - 2px)`,\n height: height + 4,\n }}\n />\n </div>\n\n {/* Range labels */}\n {showRange && (\n <div className=\"flex justify-between mt-1\">\n <span className=\"text-xs text-text-secondary\">{formatValue(min)}</span>\n <span className=\"text-xs text-text-secondary\">{formatValue(max)}</span>\n </div>\n )}\n </div>\n );\n});\n\nexport default LinearGauge;\n"],"mappings":";;;AAwCA,SAAS,EAAiB,GAAe,GAAwC;AAC/E,KAAI,CAAC,GAAY,OACf,QAAO;CAGT,IAAM,IAAS,CAAC,GAAG,EAAW,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAEhE,MAAK,IAAM,KAAa,EACtB,KAAI,KAAS,EAAU,MACrB,QAAO,EAAU;AAIrB,QAAO,EAAO,EAAO,SAAS,GAAG;;AAOnC,IAAa,IAAoC,EAAK,SAAqB,EACzE,UACA,SAAM,GACN,SAAM,KACN,YAAS,IACT,eACA,SACA,eAAY,IACZ,eAAY,IACZ,kBAAe,MAAc,EAAE,QAAQ,EAAE,EACzC,eAAY,MACX;CAED,IAAM,IAAa,SACI,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,EAAM,CAAC,GAChC,MAAQ,IAAM,KAAQ,KAC7C;EAAC;EAAO;EAAK;EAAI,CAAC,EAEf,IAAQ,EAAiB,GAAO,EAAW,EAG3C,IAAQ,QAAc;AAC1B,MAAI,CAAC,KAAa,CAAC,GAAY,OAAQ,QAAO;EAE9C,IAAM,IAAS,CAAC,GAAG,EAAW,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,EAC1D,IAA4C,EAAE,EAChD,IAAY;AAEhB,OAAK,IAAM,KAAa,GAAQ;GAC9B,IAAM,KAAU,EAAU,QAAQ,MAAc,IAAM,KAAQ;AAE9D,GADA,EAAM,KAAK;IAAE;IAAO,OAAO,EAAU;IAAO,CAAC,EAC7C,IAAY,EAAU;;AAGxB,SAAO;IACN;EAAC;EAAW;EAAY;EAAK;EAAI,CAAC;AAErC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEG,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;KAAqB,OAAO,EAAE,UAAO;eAClD,EAAY,EAAM;KACd,CAAA,EACN,KAAQ,kBAAC,QAAD;KAAM,WAAU;eAA+B;KAAY,CAAA,CAChE;;GAIR,kBAAC,OAAD;IAAK,WAAU;IAA4D,OAAO,EAAE,WAAQ;cAA5F;KAEG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAM,KAAK,GAAM,MAChB,kBAAC,OAAD;OAEE,WAAU;OACV,OAAO;QAAE,OAAO,GAAG,EAAK,MAAM;QAAI,iBAAiB,EAAK;QAAO;OAC/D,EAHK,EAGL,CACF;MACE,CAAA;KAIR,kBAAC,OAAD;MACE,WAAU;MACV,OAAO;OACL,OAAO,GAAG,EAAW;OACrB,iBAAiB;OAClB;MACD,CAAA;KAGF,kBAAC,OAAD;MACE,WAAU;MACV,OAAO;OACL,MAAM,QAAQ,EAAW;OACzB,QAAQ,IAAS;OAClB;MACD,CAAA;KACE;;GAGL,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAA+B,EAAY,EAAI;KAAQ,CAAA,EACvE,kBAAC,QAAD;KAAM,WAAU;eAA+B,EAAY,EAAI;KAAQ,CAAA,CACnE;;GAEJ;;EAER"}
1
+ {"version":3,"file":"LinearGauge.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/gauge/LinearGauge.tsx"],"sourcesContent":["/**\n * LinearGauge Component\n *\n * Horizontal linear gauge visualization.\n */\n\nimport { type FC, memo, useMemo } from 'react';\nimport { gaugeSpan, type ThresholdConfig } from './CircularGauge';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface LinearGaugeProps {\n /** Current value */\n value: number;\n /** Minimum value */\n min?: number;\n /** Maximum value */\n max?: number;\n /** Height of the gauge bar */\n height?: number;\n /** Thresholds for color zones */\n thresholds?: ThresholdConfig[];\n /** Unit label */\n unit?: string;\n /** Whether to show the value */\n showValue?: boolean;\n /** Whether to show min/max labels */\n showRange?: boolean;\n /** Value format function */\n formatValue?: (value: number) => string;\n /** Whether to show color zones */\n showZones?: boolean;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getColorForValue(value: number, thresholds?: ThresholdConfig[]): string {\n if (!thresholds?.length) {\n return 'var(--color-action-primary-bg)';\n }\n\n const sorted = [...thresholds].sort((a, b) => a.value - b.value);\n\n for (const threshold of sorted) {\n if (value <= threshold.value) {\n return threshold.color;\n }\n }\n\n return sorted[sorted.length - 1].color;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const LinearGauge: FC<LinearGaugeProps> = memo(function LinearGauge({\n value,\n min = 0,\n max = 100,\n height = 12,\n thresholds,\n unit,\n showValue = true,\n showRange = true,\n formatValue = (v: number) => v.toFixed(0),\n showZones = false,\n}) {\n // Calculate percentage\n const percentage = useMemo(() => {\n const clampedValue = Math.max(min, Math.min(max, value));\n return ((clampedValue - min) / gaugeSpan(min, max)) * 100;\n }, [value, min, max]);\n\n const color = getColorForValue(value, thresholds);\n\n // Calculate zone widths for background\n const zones = useMemo(() => {\n if (!showZones || !thresholds?.length) return null;\n\n const sorted = [...thresholds].sort((a, b) => a.value - b.value);\n const zones: { width: number; color: string }[] = [];\n let prevValue = min;\n\n for (const threshold of sorted) {\n const width = ((threshold.value - prevValue) / gaugeSpan(min, max)) * 100;\n zones.push({ width, color: threshold.color });\n prevValue = threshold.value;\n }\n\n return zones;\n }, [showZones, thresholds, min, max]);\n\n return (\n <div className=\"w-full\">\n {/* Value display */}\n {showValue && (\n <div className=\"flex items-baseline gap-1 mb-2\">\n <span className=\"text-2xl font-bold\" style={{ color }}>\n {formatValue(value)}\n </span>\n {unit && <span className=\"text-sm text-text-secondary\">{unit}</span>}\n </div>\n )}\n\n {/* Gauge bar */}\n <div className=\"relative w-full rounded-full overflow-hidden bg-bg-sunken\" style={{ height }}>\n {/* Zone backgrounds */}\n {zones && (\n <div className=\"absolute inset-0 flex\">\n {zones.map((zone, index) => (\n <div\n key={index}\n className=\"h-full opacity-20\"\n style={{ width: `${zone.width}%`, backgroundColor: zone.color }}\n />\n ))}\n </div>\n )}\n\n {/* Value bar */}\n <div\n className=\"absolute inset-y-0 left-0 rounded-full transition-all duration-500 ease-out\"\n style={{\n width: `${percentage}%`,\n backgroundColor: color,\n }}\n />\n\n {/* Value marker */}\n <div\n className=\"absolute top-1/2 -translate-y-1/2 w-1 bg-bg-surface transition-all duration-500\"\n style={{\n left: `calc(${percentage}% - 2px)`,\n height: height + 4,\n }}\n />\n </div>\n\n {/* Range labels */}\n {showRange && (\n <div className=\"flex justify-between mt-1\">\n <span className=\"text-xs text-text-secondary\">{formatValue(min)}</span>\n <span className=\"text-xs text-text-secondary\">{formatValue(max)}</span>\n </div>\n )}\n </div>\n );\n});\n\nexport default LinearGauge;\n"],"mappings":";;;;AAwCA,SAAS,EAAiB,GAAe,GAAwC;AAC/E,KAAI,CAAC,GAAY,OACf,QAAO;CAGT,IAAM,IAAS,CAAC,GAAG,EAAW,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAEhE,MAAK,IAAM,KAAa,EACtB,KAAI,KAAS,EAAU,MACrB,QAAO,EAAU;AAIrB,QAAO,EAAO,EAAO,SAAS,GAAG;;AAOnC,IAAa,IAAoC,EAAK,SAAqB,EACzE,UACA,SAAM,GACN,SAAM,KACN,YAAS,IACT,eACA,SACA,eAAY,IACZ,eAAY,IACZ,kBAAe,MAAc,EAAE,QAAQ,EAAE,EACzC,eAAY,MACX;CAED,IAAM,IAAa,SACI,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,EAAM,CAAC,GAChC,KAAO,EAAU,GAAK,EAAI,GAAI,KACrD;EAAC;EAAO;EAAK;EAAI,CAAC,EAEf,IAAQ,EAAiB,GAAO,EAAW,EAG3C,IAAQ,QAAc;AAC1B,MAAI,CAAC,KAAa,CAAC,GAAY,OAAQ,QAAO;EAE9C,IAAM,IAAS,CAAC,GAAG,EAAW,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,EAC1D,IAA4C,EAAE,EAChD,IAAY;AAEhB,OAAK,IAAM,KAAa,GAAQ;GAC9B,IAAM,KAAU,EAAU,QAAQ,KAAa,EAAU,GAAK,EAAI,GAAI;AAEtE,GADA,EAAM,KAAK;IAAE;IAAO,OAAO,EAAU;IAAO,CAAC,EAC7C,IAAY,EAAU;;AAGxB,SAAO;IACN;EAAC;EAAW;EAAY;EAAK;EAAI,CAAC;AAErC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEG,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;KAAqB,OAAO,EAAE,UAAO;eAClD,EAAY,EAAM;KACd,CAAA,EACN,KAAQ,kBAAC,QAAD;KAAM,WAAU;eAA+B;KAAY,CAAA,CAChE;;GAIR,kBAAC,OAAD;IAAK,WAAU;IAA4D,OAAO,EAAE,WAAQ;cAA5F;KAEG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAM,KAAK,GAAM,MAChB,kBAAC,OAAD;OAEE,WAAU;OACV,OAAO;QAAE,OAAO,GAAG,EAAK,MAAM;QAAI,iBAAiB,EAAK;QAAO;OAC/D,EAHK,EAGL,CACF;MACE,CAAA;KAIR,kBAAC,OAAD;MACE,WAAU;MACV,OAAO;OACL,OAAO,GAAG,EAAW;OACrB,iBAAiB;OAClB;MACD,CAAA;KAGF,kBAAC,OAAD;MACE,WAAU;MACV,OAAO;OACL,MAAM,QAAQ,EAAW;OACzB,QAAQ,IAAS;OAClB;MACD,CAAA;KACE;;GAGL,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAA+B,EAAY,EAAI;KAAQ,CAAA,EACvE,kBAAC,QAAD;KAAM,WAAU;eAA+B,EAAY,EAAI;KAAQ,CAAA,CACnE;;GAEJ;;EAER"}
@@ -23,7 +23,7 @@ var o = "\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n b
23
23
  });
24
24
  }, [e, s]);
25
25
  return /* @__PURE__ */ a("div", {
26
- className: "space-y-4",
26
+ className: "min-w-0 space-y-form-gap",
27
27
  children: [
28
28
  /* @__PURE__ */ a("div", { children: [/* @__PURE__ */ i("label", {
29
29
  className: "block text-sm font-medium text-text-primary mb-1",
@@ -85,29 +85,40 @@ var o = "\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n b
85
85
  onChange: (e) => u("decimals", Number(e.target.value)),
86
86
  className: o
87
87
  })] }),
88
- /* @__PURE__ */ a("label", {
89
- className: "flex items-center gap-3",
90
- children: [/* @__PURE__ */ i("input", {
91
- type: "checkbox",
92
- checked: e.showValues !== !1,
93
- onChange: (e) => u("showValues", e.target.checked),
94
- className: "\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n "
95
- }), /* @__PURE__ */ i("span", {
96
- className: "text-sm text-text-primary",
97
- children: c("bigconsole.widget.config.heatmap.showValues", "Show cell values")
98
- })]
99
- }),
100
- /* @__PURE__ */ a("label", {
101
- className: "flex items-center gap-3",
102
- children: [/* @__PURE__ */ i("input", {
103
- type: "checkbox",
104
- checked: e.showLegend !== !1,
105
- onChange: (e) => u("showLegend", e.target.checked),
106
- className: "\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n "
107
- }), /* @__PURE__ */ i("span", {
108
- className: "text-sm text-text-primary",
109
- children: c("bigconsole.widget.config.heatmap.showLegend", "Show color legend")
110
- })]
88
+ /* @__PURE__ */ a("div", {
89
+ role: "group",
90
+ "aria-label": "Display options",
91
+ className: "space-y-3 border-t border-[var(--color-border-subtle)] pt-form-gap",
92
+ children: [
93
+ /* @__PURE__ */ i("p", {
94
+ className: "text-xs font-bold uppercase tracking-wider text-text-secondary",
95
+ children: "Display options"
96
+ }),
97
+ /* @__PURE__ */ a("label", {
98
+ className: "flex items-center gap-3",
99
+ children: [/* @__PURE__ */ i("input", {
100
+ type: "checkbox",
101
+ checked: e.showValues !== !1,
102
+ onChange: (e) => u("showValues", e.target.checked),
103
+ className: "\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n "
104
+ }), /* @__PURE__ */ i("span", {
105
+ className: "text-sm text-text-primary",
106
+ children: c("bigconsole.widget.config.heatmap.showValues", "Show cell values")
107
+ })]
108
+ }),
109
+ /* @__PURE__ */ a("label", {
110
+ className: "flex items-center gap-3",
111
+ children: [/* @__PURE__ */ i("input", {
112
+ type: "checkbox",
113
+ checked: e.showLegend !== !1,
114
+ onChange: (e) => u("showLegend", e.target.checked),
115
+ className: "\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n "
116
+ }), /* @__PURE__ */ i("span", {
117
+ className: "text-sm text-text-primary",
118
+ children: c("bigconsole.widget.config.heatmap.showLegend", "Show color legend")
119
+ })]
120
+ })
121
+ ]
111
122
  })
112
123
  ]
113
124
  });
@@ -1 +1 @@
1
- {"version":3,"file":"HeatmapConfig.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/heatmap/HeatmapConfig.tsx"],"sourcesContent":["/**\n * HeatmapConfig Component\n *\n * Configuration panel for Heatmap widgets.\n */\n\nimport { type FC, memo, useCallback, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type { HeatmapConfig as ConfigType } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface HeatmapConfigProps {\n /** Current configuration */\n config: ConfigType;\n /** Callback when config changes */\n onChange: (config: ConfigType) => void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst FIELD_CLASSES = `\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n`;\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const HeatmapConfig: FC<HeatmapConfigProps> = memo(function HeatmapConfig({ config, onChange }) {\n const { t } = useI18n();\n\n const COLOR_SCHEMES = useMemo(\n () => [\n { value: 'blue', label: t('bigconsole.widget.config.heatmap.colorScheme.blue', 'Blue') },\n { value: 'green', label: t('bigconsole.widget.config.heatmap.colorScheme.green', 'Green') },\n { value: 'red', label: t('bigconsole.widget.config.heatmap.colorScheme.red', 'Red') },\n ],\n [t]\n );\n\n const handleChange = useCallback(\n <K extends keyof ConfigType>(key: K, value: ConfigType[K]) => {\n onChange({ ...config, [key]: value });\n },\n [config, onChange]\n );\n\n return (\n <div className=\"space-y-4\">\n {/* Axis + value fields */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.xAxisFieldLabel', 'X-Axis Field')}\n </label>\n <input\n type=\"text\"\n value={config.xAxisField || ''}\n onChange={(e) => handleChange('xAxisField', e.target.value)}\n placeholder={t('bigconsole.widget.config.heatmap.xAxisFieldPlaceholder', 'e.g., hour, column')}\n className={FIELD_CLASSES}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.yAxisFieldLabel', 'Y-Axis Field')}\n </label>\n <input\n type=\"text\"\n value={config.yAxisField || ''}\n onChange={(e) => handleChange('yAxisField', e.target.value)}\n placeholder={t('bigconsole.widget.config.heatmap.yAxisFieldPlaceholder', 'e.g., day, row')}\n className={FIELD_CLASSES}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.valueFieldLabel', 'Value Field')}\n </label>\n <input\n type=\"text\"\n value={config.valueField || ''}\n onChange={(e) => handleChange('valueField', e.target.value)}\n placeholder={t('bigconsole.widget.config.heatmap.valueFieldPlaceholder', 'e.g., tickets, count')}\n className={FIELD_CLASSES}\n />\n <p className=\"mt-1 text-xs text-text-secondary\">\n {t(\n 'bigconsole.widget.config.heatmap.valueFieldHelp',\n \"Left empty, the widget reads the parser's rows / columns / cells output directly.\"\n )}\n </p>\n </div>\n\n {/* Color scheme */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.colorSchemeLabel', 'Color Scheme')}\n </label>\n <select\n value={config.colorScheme || 'blue'}\n onChange={(e) => handleChange('colorScheme', e.target.value)}\n className={FIELD_CLASSES}\n >\n {COLOR_SCHEMES.map((scheme) => (\n <option key={scheme.value} value={scheme.value}>\n {scheme.label}\n </option>\n ))}\n </select>\n </div>\n\n {/* Decimals */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.decimalPlacesLabel', 'Decimal Places')}\n </label>\n <input\n type=\"number\"\n min={0}\n max={6}\n value={config.decimals ?? 0}\n onChange={(e) => handleChange('decimals', Number(e.target.value))}\n className={FIELD_CLASSES}\n />\n </div>\n\n {/* Toggles */}\n <label className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={config.showValues !== false}\n onChange={(e) => handleChange('showValues', e.target.checked)}\n className=\"\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n \"\n />\n <span className=\"text-sm text-text-primary\">\n {t('bigconsole.widget.config.heatmap.showValues', 'Show cell values')}\n </span>\n </label>\n\n <label className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={config.showLegend !== false}\n onChange={(e) => handleChange('showLegend', e.target.checked)}\n className=\"\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n \"\n />\n <span className=\"text-sm text-text-primary\">\n {t('bigconsole.widget.config.heatmap.showLegend', 'Show color legend')}\n </span>\n </label>\n </div>\n );\n});\n\nexport default HeatmapConfig;\n"],"mappings":"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"}
1
+ {"version":3,"file":"HeatmapConfig.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/heatmap/HeatmapConfig.tsx"],"sourcesContent":["/**\n * HeatmapConfig Component\n *\n * Configuration panel for Heatmap widgets.\n */\n\nimport { type FC, memo, useCallback, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type { HeatmapConfig as ConfigType } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface HeatmapConfigProps {\n /** Current configuration */\n config: ConfigType;\n /** Callback when config changes */\n onChange: (config: ConfigType) => void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst FIELD_CLASSES = `\n w-full px-3 py-2\n text-sm text-text-primary\n bg-bg-surface\n border border-border-default\n rounded-md\n focus:outline-none focus:ring-2 focus:ring-action-primary-bg\n`;\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const HeatmapConfig: FC<HeatmapConfigProps> = memo(function HeatmapConfig({ config, onChange }) {\n const { t } = useI18n();\n\n const COLOR_SCHEMES = useMemo(\n () => [\n { value: 'blue', label: t('bigconsole.widget.config.heatmap.colorScheme.blue', 'Blue') },\n { value: 'green', label: t('bigconsole.widget.config.heatmap.colorScheme.green', 'Green') },\n { value: 'red', label: t('bigconsole.widget.config.heatmap.colorScheme.red', 'Red') },\n ],\n [t]\n );\n\n const handleChange = useCallback(\n <K extends keyof ConfigType>(key: K, value: ConfigType[K]) => {\n onChange({ ...config, [key]: value });\n },\n [config, onChange]\n );\n\n return (\n <div className=\"min-w-0 space-y-form-gap\">\n {/* Axis + value fields */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.xAxisFieldLabel', 'X-Axis Field')}\n </label>\n <input\n type=\"text\"\n value={config.xAxisField || ''}\n onChange={(e) => handleChange('xAxisField', e.target.value)}\n placeholder={t('bigconsole.widget.config.heatmap.xAxisFieldPlaceholder', 'e.g., hour, column')}\n className={FIELD_CLASSES}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.yAxisFieldLabel', 'Y-Axis Field')}\n </label>\n <input\n type=\"text\"\n value={config.yAxisField || ''}\n onChange={(e) => handleChange('yAxisField', e.target.value)}\n placeholder={t('bigconsole.widget.config.heatmap.yAxisFieldPlaceholder', 'e.g., day, row')}\n className={FIELD_CLASSES}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.valueFieldLabel', 'Value Field')}\n </label>\n <input\n type=\"text\"\n value={config.valueField || ''}\n onChange={(e) => handleChange('valueField', e.target.value)}\n placeholder={t('bigconsole.widget.config.heatmap.valueFieldPlaceholder', 'e.g., tickets, count')}\n className={FIELD_CLASSES}\n />\n <p className=\"mt-1 text-xs text-text-secondary\">\n {t(\n 'bigconsole.widget.config.heatmap.valueFieldHelp',\n \"Left empty, the widget reads the parser's rows / columns / cells output directly.\"\n )}\n </p>\n </div>\n\n {/* Color scheme */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.colorSchemeLabel', 'Color Scheme')}\n </label>\n <select\n value={config.colorScheme || 'blue'}\n onChange={(e) => handleChange('colorScheme', e.target.value)}\n className={FIELD_CLASSES}\n >\n {COLOR_SCHEMES.map((scheme) => (\n <option key={scheme.value} value={scheme.value}>\n {scheme.label}\n </option>\n ))}\n </select>\n </div>\n\n {/* Decimals */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.widget.config.heatmap.decimalPlacesLabel', 'Decimal Places')}\n </label>\n <input\n type=\"number\"\n min={0}\n max={6}\n value={config.decimals ?? 0}\n onChange={(e) => handleChange('decimals', Number(e.target.value))}\n className={FIELD_CLASSES}\n />\n </div>\n\n {/* Toggles */}\n <div\n role=\"group\"\n aria-label=\"Display options\"\n className=\"space-y-3 border-t border-[var(--color-border-subtle)] pt-form-gap\"\n >\n {/* Toggles are a different KIND of control from the field stack above, so they\n get their own labelled group instead of being visually identical to it\n (BOFF-5636). */}\n <p className=\"text-xs font-bold uppercase tracking-wider text-text-secondary\">Display options</p>\n <label className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={config.showValues !== false}\n onChange={(e) => handleChange('showValues', e.target.checked)}\n className=\"\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n \"\n />\n <span className=\"text-sm text-text-primary\">\n {t('bigconsole.widget.config.heatmap.showValues', 'Show cell values')}\n </span>\n </label>\n\n <label className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={config.showLegend !== false}\n onChange={(e) => handleChange('showLegend', e.target.checked)}\n className=\"\n w-4 h-4\n text-action-primary-bg\n bg-bg-surface\n border-border-default\n rounded\n focus:ring-action-primary-bg\n \"\n />\n <span className=\"text-sm text-text-primary\">\n {t('bigconsole.widget.config.heatmap.showLegend', 'Show color legend')}\n </span>\n </label>\n </div>\n </div>\n );\n});\n\nexport default HeatmapConfig;\n"],"mappings":"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"}
@@ -33,7 +33,7 @@ var a = e(function({ widget: e, data: a }) {
33
33
  className: "text-center",
34
34
  children: [
35
35
  /* @__PURE__ */ n("svg", {
36
- className: "w-12 h-12 mx-auto mb-2 text-text-tertiary",
36
+ className: "w-12 h-12 mx-auto mb-2 text-text-muted",
37
37
  fill: "none",
38
38
  stroke: "currentColor",
39
39
  viewBox: "0 0 24 24",
@@ -46,7 +46,7 @@ var a = e(function({ widget: e, data: a }) {
46
46
  }),
47
47
  /* @__PURE__ */ n("p", { children: "No URL configured" }),
48
48
  /* @__PURE__ */ n("p", {
49
- className: "text-xs text-text-tertiary mt-1",
49
+ className: "text-xs text-text-muted mt-1",
50
50
  children: "Configure a URL to embed content"
51
51
  })
52
52
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"IframeWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/iframe-widget/IframeWidget.tsx"],"sourcesContent":["/**\n * IframeWidget Component\n *\n * Displays embedded iframe content.\n *\n * Data flow: DataSink → Parser → Widget\n * - Static configuration lives in `widget.config` (url, sandbox, allowFullscreen, title).\n * - Dynamic parser output is passed in `data` and overrides matching config keys.\n * - This lets the iframe render from manual configuration, parser-driven data, or both.\n */\n\nimport { type FC, memo, useMemo } from 'react';\nimport type { Widget } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface IframeWidgetProps {\n widget: Widget;\n data?: IframeData;\n}\n\nexport interface IframeData {\n url?: string;\n title?: string;\n allowFullscreen?: boolean;\n sandbox?: string;\n loading?: 'lazy' | 'eager';\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Resolve the effective iframe configuration.\n *\n * Priority (highest first):\n * 1. Parser-provided `data` fields\n * 2. User-configured `widget.config` fields\n * 3. Safe defaults (empty URL, restricted sandbox, no fullscreen)\n *\n * This is the function the widget tests exercise directly; keeping the merge\n * logic pure makes the DataSink → Parser → Widget contract explicit.\n */\nexport function resolveIframeConfig(\n widgetConfig: Record<string, unknown> | undefined,\n data: IframeData | undefined\n): Required<IframeData> & { hasUrl: boolean } {\n const cfg = widgetConfig ?? {};\n\n const coercedBoolean = (value: unknown): boolean | undefined => {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return undefined;\n };\n\n const coercedLoading = (value: unknown): 'lazy' | 'eager' => {\n if (value === 'eager' || value === 'lazy') return value;\n return 'lazy';\n };\n\n const url = (data?.url ?? cfg.url ?? '') as string;\n const title = (data?.title ?? cfg.title ?? 'Embedded Content') as string;\n const allowFullscreen = coercedBoolean(data?.allowFullscreen ?? cfg.allowFullscreen) ?? false;\n const sandbox = ((data?.sandbox ?? cfg.sandbox) as string | undefined) ?? 'allow-scripts allow-same-origin';\n const loading = coercedLoading(data?.loading ?? cfg.loading);\n\n return {\n url,\n title,\n allowFullscreen,\n sandbox,\n loading,\n hasUrl: typeof url === 'string' && url.length > 0,\n };\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const IframeWidget: FC<IframeWidgetProps> = memo(function IframeWidget({ widget, data }) {\n const config = useMemo(() => resolveIframeConfig(widget.config, data), [widget.config, data]);\n\n if (!config.hasUrl) {\n return (\n <div className=\"flex items-center justify-center h-full text-text-secondary text-sm\">\n <div className=\"text-center\">\n <svg\n className=\"w-12 h-12 mx-auto mb-2 text-text-tertiary\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\n />\n </svg>\n <p>No URL configured</p>\n <p className=\"text-xs text-text-tertiary mt-1\">Configure a URL to embed content</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"h-full w-full\">\n <iframe\n src={config.url}\n title={config.title}\n className=\"w-full h-full border-0 rounded\"\n allowFullScreen={config.allowFullscreen}\n sandbox={config.sandbox}\n loading={config.loading}\n />\n </div>\n );\n});\n\nexport default IframeWidget;\n"],"mappings":";;;AA8CA,SAAgB,EACd,GACA,GAC4C;CAC5C,IAAM,IAAM,KAAgB,EAAE,EAExB,KAAkB,MAAwC;AAC9D,MAAI,OAAO,KAAU,UAAW,QAAO;AACvC,MAAI,OAAO,KAAU,SAAU,QAAO,EAAM,aAAa,KAAK;IAI1D,KAAkB,MAClB,MAAU,WAAW,MAAU,SAAe,IAC3C,QAGH,IAAO,GAAM,OAAO,EAAI,OAAO;AAMrC,QAAO;EACL;EACA,OAPa,GAAM,SAAS,EAAI,SAAS;EAQzC,iBAPsB,EAAe,GAAM,mBAAmB,EAAI,gBAAgB,IAAI;EAQtF,SAPgB,GAAM,WAAW,EAAI,WAAmC;EAQxE,SAPc,EAAe,GAAM,WAAW,EAAI,QAAQ;EAQ1D,QAAQ,OAAO,KAAQ,YAAY,EAAI,SAAS;EACjD;;AAOH,IAAa,IAAsC,EAAK,SAAsB,EAAE,WAAQ,WAAQ;CAC9F,IAAM,IAAS,QAAc,EAAoB,EAAO,QAAQ,EAAK,EAAE,CAAC,EAAO,QAAQ,EAAK,CAAC;AA0B7F,QAxBK,EAAO,SAyBV,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,UAAD;GACE,KAAK,EAAO;GACZ,OAAO,EAAO;GACd,WAAU;GACV,iBAAiB,EAAO;GACxB,SAAS,EAAO;GAChB,SAAS,EAAO;GAChB,CAAA;EACE,CAAA,GAhCJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KACE,WAAU;KACV,MAAK;KACL,QAAO;KACP,SAAQ;eAER,kBAAC,QAAD;MACE,eAAc;MACd,gBAAe;MACf,aAAa;MACb,GAAE;MACF,CAAA;KACE,CAAA;IACN,kBAAC,KAAD,EAAA,UAAG,qBAAqB,CAAA;IACxB,kBAAC,KAAD;KAAG,WAAU;eAAkC;KAAoC,CAAA;IAC/E;;EACF,CAAA;EAgBV"}
1
+ {"version":3,"file":"IframeWidget.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/iframe-widget/IframeWidget.tsx"],"sourcesContent":["/**\n * IframeWidget Component\n *\n * Displays embedded iframe content.\n *\n * Data flow: DataSink → Parser → Widget\n * - Static configuration lives in `widget.config` (url, sandbox, allowFullscreen, title).\n * - Dynamic parser output is passed in `data` and overrides matching config keys.\n * - This lets the iframe render from manual configuration, parser-driven data, or both.\n */\n\nimport { type FC, memo, useMemo } from 'react';\nimport type { Widget } from '../../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface IframeWidgetProps {\n widget: Widget;\n data?: IframeData;\n}\n\nexport interface IframeData {\n url?: string;\n title?: string;\n allowFullscreen?: boolean;\n sandbox?: string;\n loading?: 'lazy' | 'eager';\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Resolve the effective iframe configuration.\n *\n * Priority (highest first):\n * 1. Parser-provided `data` fields\n * 2. User-configured `widget.config` fields\n * 3. Safe defaults (empty URL, restricted sandbox, no fullscreen)\n *\n * This is the function the widget tests exercise directly; keeping the merge\n * logic pure makes the DataSink → Parser → Widget contract explicit.\n */\nexport function resolveIframeConfig(\n widgetConfig: Record<string, unknown> | undefined,\n data: IframeData | undefined\n): Required<IframeData> & { hasUrl: boolean } {\n const cfg = widgetConfig ?? {};\n\n const coercedBoolean = (value: unknown): boolean | undefined => {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') return value.toLowerCase() === 'true';\n return undefined;\n };\n\n const coercedLoading = (value: unknown): 'lazy' | 'eager' => {\n if (value === 'eager' || value === 'lazy') return value;\n return 'lazy';\n };\n\n const url = (data?.url ?? cfg.url ?? '') as string;\n const title = (data?.title ?? cfg.title ?? 'Embedded Content') as string;\n const allowFullscreen = coercedBoolean(data?.allowFullscreen ?? cfg.allowFullscreen) ?? false;\n const sandbox = ((data?.sandbox ?? cfg.sandbox) as string | undefined) ?? 'allow-scripts allow-same-origin';\n const loading = coercedLoading(data?.loading ?? cfg.loading);\n\n return {\n url,\n title,\n allowFullscreen,\n sandbox,\n loading,\n hasUrl: typeof url === 'string' && url.length > 0,\n };\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const IframeWidget: FC<IframeWidgetProps> = memo(function IframeWidget({ widget, data }) {\n const config = useMemo(() => resolveIframeConfig(widget.config, data), [widget.config, data]);\n\n if (!config.hasUrl) {\n return (\n <div className=\"flex items-center justify-center h-full text-text-secondary text-sm\">\n <div className=\"text-center\">\n <svg className=\"w-12 h-12 mx-auto mb-2 text-text-muted\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\n />\n </svg>\n <p>No URL configured</p>\n <p className=\"text-xs text-text-muted mt-1\">Configure a URL to embed content</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"h-full w-full\">\n <iframe\n src={config.url}\n title={config.title}\n className=\"w-full h-full border-0 rounded\"\n allowFullScreen={config.allowFullscreen}\n sandbox={config.sandbox}\n loading={config.loading}\n />\n </div>\n );\n});\n\nexport default IframeWidget;\n"],"mappings":";;;AA8CA,SAAgB,EACd,GACA,GAC4C;CAC5C,IAAM,IAAM,KAAgB,EAAE,EAExB,KAAkB,MAAwC;AAC9D,MAAI,OAAO,KAAU,UAAW,QAAO;AACvC,MAAI,OAAO,KAAU,SAAU,QAAO,EAAM,aAAa,KAAK;IAI1D,KAAkB,MAClB,MAAU,WAAW,MAAU,SAAe,IAC3C,QAGH,IAAO,GAAM,OAAO,EAAI,OAAO;AAMrC,QAAO;EACL;EACA,OAPa,GAAM,SAAS,EAAI,SAAS;EAQzC,iBAPsB,EAAe,GAAM,mBAAmB,EAAI,gBAAgB,IAAI;EAQtF,SAPgB,GAAM,WAAW,EAAI,WAAmC;EAQxE,SAPc,EAAe,GAAM,WAAW,EAAI,QAAQ;EAQ1D,QAAQ,OAAO,KAAQ,YAAY,EAAI,SAAS;EACjD;;AAOH,IAAa,IAAsC,EAAK,SAAsB,EAAE,WAAQ,WAAQ;CAC9F,IAAM,IAAS,QAAc,EAAoB,EAAO,QAAQ,EAAK,EAAE,CAAC,EAAO,QAAQ,EAAK,CAAC;AAqB7F,QAnBK,EAAO,SAoBV,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,UAAD;GACE,KAAK,EAAO;GACZ,OAAO,EAAO;GACd,WAAU;GACV,iBAAiB,EAAO;GACxB,SAAS,EAAO;GAChB,SAAS,EAAO;GAChB,CAAA;EACE,CAAA,GA3BJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;KAAyC,MAAK;KAAO,QAAO;KAAe,SAAQ;eAChG,kBAAC,QAAD;MACE,eAAc;MACd,gBAAe;MACf,aAAa;MACb,GAAE;MACF,CAAA;KACE,CAAA;IACN,kBAAC,KAAD,EAAA,UAAG,qBAAqB,CAAA;IACxB,kBAAC,KAAD;KAAG,WAAU;eAA+B;KAAoC,CAAA;IAC5E;;EACF,CAAA;EAgBV"}