@burdenoff/microfe-bigconsole 2026.924.2 → 2026.925.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/bigconsole/BigConsoleRoot.js +94 -84
  2. package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
  3. package/dist/bigconsole/BigConsoleRoutes.js +137 -138
  4. package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
  5. package/dist/bigconsole/assistant/previewController.js +7 -7
  6. package/dist/bigconsole/components/DrilldownDashboardRenderer.js +17 -17
  7. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +32 -32
  8. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +52 -52
  9. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  10. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +7 -7
  11. package/dist/bigconsole/components/dashboard/DashboardStatusPill.js +53 -0
  12. package/dist/bigconsole/components/dashboard/DashboardStatusPill.js.map +1 -0
  13. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +60 -60
  14. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +21 -21
  15. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +30 -30
  16. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +36 -36
  17. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +34 -34
  18. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +38 -38
  19. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  20. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +121 -121
  21. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  22. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +22 -22
  23. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +46 -46
  24. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +53 -53
  25. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -1
  26. package/dist/bigconsole/components/dashboard/WidgetPalette.js +47 -47
  27. package/dist/bigconsole/components/dashboard/index.js +1 -0
  28. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +35 -35
  29. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +18 -18
  30. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +20 -20
  31. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +30 -29
  32. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
  33. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +48 -48
  34. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +126 -114
  35. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  36. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +35 -35
  37. package/dist/bigconsole/components/overview/DashboardGuide.js +214 -0
  38. package/dist/bigconsole/components/overview/DashboardGuide.js.map +1 -0
  39. package/dist/bigconsole/components/overview/DataHealthCard.js +97 -0
  40. package/dist/bigconsole/components/overview/DataHealthCard.js.map +1 -0
  41. package/dist/bigconsole/components/overview/OverviewQuickActions.js +32 -0
  42. package/dist/bigconsole/components/overview/OverviewQuickActions.js.map +1 -0
  43. package/dist/bigconsole/components/overview/OverviewStatCard.js +57 -0
  44. package/dist/bigconsole/components/overview/OverviewStatCard.js.map +1 -0
  45. package/dist/bigconsole/components/overview/RecentDashboardsPanel.js +107 -0
  46. package/dist/bigconsole/components/overview/RecentDashboardsPanel.js.map +1 -0
  47. package/dist/bigconsole/components/overview/dashboardGuideSteps.js +119 -0
  48. package/dist/bigconsole/components/overview/dashboardGuideSteps.js.map +1 -0
  49. package/dist/bigconsole/components/overview/index.js +8 -0
  50. package/dist/bigconsole/components/overview/overviewModel.js +119 -0
  51. package/dist/bigconsole/components/overview/overviewModel.js.map +1 -0
  52. package/dist/bigconsole/components/overview/useOverviewData.js +48 -0
  53. package/dist/bigconsole/components/overview/useOverviewData.js.map +1 -0
  54. package/dist/bigconsole/components/parser/DataSinkSelector.js +40 -40
  55. package/dist/bigconsole/components/parser/ImportParserDialog.js +127 -127
  56. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  57. package/dist/bigconsole/components/parser/ParserSelector.js +51 -51
  58. package/dist/bigconsole/components/preview/AiPreviewContent.js +5 -5
  59. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +32 -32
  60. package/dist/bigconsole/components/preview/AiPreviewPanel.js +37 -37
  61. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +13 -13
  62. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +70 -70
  63. package/dist/bigconsole/components/widgets/PropertiesPanel.js +28 -28
  64. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +25 -25
  65. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +48 -48
  66. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +46 -46
  67. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +61 -61
  68. package/dist/bigconsole/components/widgets/form/FormWidget.js +36 -36
  69. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +42 -42
  70. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +25 -25
  71. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +21 -21
  72. package/dist/bigconsole/components/widgets/list/ListConfig.js +30 -30
  73. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +38 -38
  74. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +9 -9
  75. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +9 -9
  76. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +49 -49
  77. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +39 -39
  78. package/dist/bigconsole/components/widgets/table/TableConfig.js +73 -73
  79. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +64 -64
  80. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +10 -10
  81. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +68 -68
  82. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  83. package/dist/bigconsole/hooks/useDataSinkOperations.js +92 -89
  84. package/dist/bigconsole/hooks/useDataSinkOperations.js.map +1 -1
  85. package/dist/bigconsole/hooks/useImportDataSink.js +96 -91
  86. package/dist/bigconsole/hooks/useImportDataSink.js.map +1 -1
  87. package/dist/bigconsole/pages/AdminPage.js +136 -136
  88. package/dist/bigconsole/pages/DashboardBuilderPage.js +10 -10
  89. package/dist/bigconsole/pages/DashboardViewPage.js +61 -61
  90. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  91. package/dist/bigconsole/pages/DashboardsPage.js +327 -348
  92. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  93. package/dist/bigconsole/pages/DataParsersPage.js +5 -5
  94. package/dist/bigconsole/pages/DataSinkBuilderPage.js +82 -80
  95. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  96. package/dist/bigconsole/pages/DataSinkViewPage.js +83 -83
  97. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  98. package/dist/bigconsole/pages/DataSinksPage.js +11 -11
  99. package/dist/bigconsole/pages/DataSourcesPage.js +5 -5
  100. package/dist/bigconsole/pages/InsightsPage.js +315 -315
  101. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  102. package/dist/bigconsole/pages/OverviewPage.js +244 -0
  103. package/dist/bigconsole/pages/OverviewPage.js.map +1 -0
  104. package/dist/bigconsole/pages/ParserBuilderPage.js +5 -5
  105. package/dist/bigconsole/pages/ParserViewPage.js +98 -98
  106. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  107. package/dist/bigconsole/pages/PipelineBuilderPage.js +8 -8
  108. package/dist/bigconsole/pages/PipelineViewPage.js +46 -46
  109. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  110. package/dist/bigconsole/pages/PipelinesPage.js +80 -80
  111. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  112. package/dist/bigconsole/pages/SettingsPage.js +70 -70
  113. package/dist/bigconsole/pages/WidgetDemoPage.js +42 -42
  114. package/dist/bigconsole/pages/WorkflowViewPage.js +200 -200
  115. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  116. package/dist/bigconsole/pages/WorkflowsPage.js +78 -78
  117. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  118. package/dist/bigconsole/providers/BigConsoleQuotaProvider.js +36 -35
  119. package/dist/bigconsole/providers/BigConsoleQuotaProvider.js.map +1 -1
  120. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +34 -34
  121. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +79 -79
  122. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +46 -46
  123. package/dist/bigconsole/utils/createDialogParam.js +14 -0
  124. package/dist/bigconsole/utils/createDialogParam.js.map +1 -0
  125. package/dist/bigconsole/utils/quota.js +51 -23
  126. package/dist/bigconsole/utils/quota.js.map +1 -1
  127. package/dist/generated/global-operations.js +1 -1
  128. package/dist/generated/wspace-operations.js +285 -222
  129. package/dist/generated/wspace-operations.js.map +1 -1
  130. package/dist/shared/hooks/useTr.js +10 -7
  131. package/dist/shared/hooks/useTr.js.map +1 -1
  132. package/package.json +1 -1
  133. package/dist/bigconsole/pages/HomePage.js +0 -318
  134. package/dist/bigconsole/pages/HomePage.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { SEMANTIC_COLORS as e } from "../../../utils/semanticTokens.js";
2
2
  import { useEffect as t, useRef as n, useState as r } from "react";
3
- import { useI18n as i } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
4
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ import { useI18n as o } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
5
5
  //#region src/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.tsx
6
6
  function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, onDeletePreset: d, disabled: f = !1 }) {
7
- let { t: p } = i(), [m, h] = r(!1), [g, _] = r(!1), [v, y] = r(""), [b, x] = r(""), S = n(null), C = s.find((e) => e.id === c);
7
+ let { t: p } = o(), [m, h] = r(!1), [g, _] = r(!1), [v, y] = r(""), [b, x] = r(""), S = n(null), C = s.find((e) => e.id === c);
8
8
  t(() => {
9
9
  function e(e) {
10
10
  S.current && !S.current.contains(e.target) && (h(!1), _(!1));
@@ -16,13 +16,13 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
16
16
  }, T = (e, t) => {
17
17
  e.stopPropagation(), window.confirm(p("bigconsole.filters.presets.deleteConfirm", "Are you sure you want to delete this preset?")) && d(t);
18
18
  };
19
- return /* @__PURE__ */ o("div", {
19
+ return /* @__PURE__ */ a("div", {
20
20
  ref: S,
21
21
  style: {
22
22
  position: "relative",
23
23
  display: "inline-block"
24
24
  },
25
- children: [/* @__PURE__ */ o("button", {
25
+ children: [/* @__PURE__ */ a("button", {
26
26
  onClick: () => !f && h(!m),
27
27
  disabled: f,
28
28
  style: {
@@ -42,13 +42,13 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
42
42
  maxWidth: "100%",
43
43
  justifyContent: "space-between"
44
44
  },
45
- children: [/* @__PURE__ */ o("span", {
45
+ children: [/* @__PURE__ */ a("span", {
46
46
  style: {
47
47
  display: "flex",
48
48
  alignItems: "center",
49
49
  gap: "6px"
50
50
  },
51
- children: [/* @__PURE__ */ o("svg", {
51
+ children: [/* @__PURE__ */ a("svg", {
52
52
  width: "14",
53
53
  height: "14",
54
54
  viewBox: "0 0 24 24",
@@ -56,12 +56,12 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
56
56
  stroke: "currentColor",
57
57
  strokeWidth: "2",
58
58
  children: [
59
- /* @__PURE__ */ a("path", { d: "M19 21H5a2 2 0 01-2-2V5a2 2 0 012-2h11l5 5v11a2 2 0 01-2 2z" }),
60
- /* @__PURE__ */ a("polyline", { points: "17,21 17,13 7,13 7,21" }),
61
- /* @__PURE__ */ a("polyline", { points: "7,3 7,8 15,8" })
59
+ /* @__PURE__ */ i("path", { d: "M19 21H5a2 2 0 01-2-2V5a2 2 0 012-2h11l5 5v11a2 2 0 01-2 2z" }),
60
+ /* @__PURE__ */ i("polyline", { points: "17,21 17,13 7,13 7,21" }),
61
+ /* @__PURE__ */ i("polyline", { points: "7,3 7,8 15,8" })
62
62
  ]
63
63
  }), C ? C.name : p("bigconsole.filters.presets.buttonLabel", "Presets")]
64
- }), /* @__PURE__ */ a("svg", {
64
+ }), /* @__PURE__ */ i("svg", {
65
65
  width: "12",
66
66
  height: "12",
67
67
  viewBox: "0 0 24 24",
@@ -72,9 +72,9 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
72
72
  transform: m ? "rotate(180deg)" : "rotate(0deg)",
73
73
  transition: "transform 0.2s ease"
74
74
  },
75
- children: /* @__PURE__ */ a("polyline", { points: "6,9 12,15 18,9" })
75
+ children: /* @__PURE__ */ i("polyline", { points: "6,9 12,15 18,9" })
76
76
  })]
77
- }), m && /* @__PURE__ */ o("div", {
77
+ }), m && /* @__PURE__ */ a("div", {
78
78
  style: {
79
79
  position: "absolute",
80
80
  top: "100%",
@@ -90,7 +90,7 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
90
90
  overflow: "hidden"
91
91
  },
92
92
  children: [
93
- /* @__PURE__ */ o("div", {
93
+ /* @__PURE__ */ a("div", {
94
94
  style: {
95
95
  padding: "12px 16px",
96
96
  borderBottom: `1px solid ${e.borderDefault}`,
@@ -99,14 +99,14 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
99
99
  justifyContent: "space-between",
100
100
  alignItems: "center"
101
101
  },
102
- children: [/* @__PURE__ */ a("span", {
102
+ children: [/* @__PURE__ */ i("span", {
103
103
  style: {
104
104
  fontWeight: 600,
105
105
  fontSize: "13px",
106
106
  color: e.textPrimary
107
107
  },
108
108
  children: p("bigconsole.filters.presets.header", "Filter Presets")
109
- }), /* @__PURE__ */ a("button", {
109
+ }), /* @__PURE__ */ i("button", {
110
110
  onClick: () => _(!0),
111
111
  style: {
112
112
  padding: "4px 10px",
@@ -121,14 +121,14 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
121
121
  children: p("bigconsole.filters.presets.saveCurrent", "+ Save Current")
122
122
  })]
123
123
  }),
124
- g && /* @__PURE__ */ o("div", {
124
+ g && /* @__PURE__ */ a("div", {
125
125
  style: {
126
126
  padding: "12px 16px",
127
127
  borderBottom: `1px solid ${e.borderDefault}`,
128
128
  backgroundColor: e.bgSecondary
129
129
  },
130
130
  children: [
131
- /* @__PURE__ */ a("input", {
131
+ /* @__PURE__ */ i("input", {
132
132
  type: "text",
133
133
  value: v,
134
134
  onChange: (e) => y(e.target.value),
@@ -146,7 +146,7 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
146
146
  color: e.textPrimary
147
147
  }
148
148
  }),
149
- /* @__PURE__ */ a("input", {
149
+ /* @__PURE__ */ i("input", {
150
150
  type: "text",
151
151
  value: b,
152
152
  onChange: (e) => x(e.target.value),
@@ -163,13 +163,13 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
163
163
  color: e.textPrimary
164
164
  }
165
165
  }),
166
- /* @__PURE__ */ o("div", {
166
+ /* @__PURE__ */ a("div", {
167
167
  style: {
168
168
  display: "flex",
169
169
  gap: "8px",
170
170
  justifyContent: "flex-end"
171
171
  },
172
- children: [/* @__PURE__ */ a("button", {
172
+ children: [/* @__PURE__ */ i("button", {
173
173
  onClick: () => {
174
174
  _(!1), y(""), x("");
175
175
  },
@@ -183,7 +183,7 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
183
183
  color: e.textSecondary
184
184
  },
185
185
  children: p("bigconsole.filters.presets.cancel", "Cancel")
186
- }), /* @__PURE__ */ a("button", {
186
+ }), /* @__PURE__ */ i("button", {
187
187
  onClick: w,
188
188
  disabled: !v.trim(),
189
189
  style: {
@@ -201,12 +201,12 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
201
201
  })
202
202
  ]
203
203
  }),
204
- /* @__PURE__ */ o("div", {
204
+ /* @__PURE__ */ a("div", {
205
205
  style: {
206
206
  maxHeight: "300px",
207
207
  overflowY: "auto"
208
208
  },
209
- children: [s.map((t) => /* @__PURE__ */ o("div", {
209
+ children: [s.map((t) => /* @__PURE__ */ a("div", {
210
210
  onClick: () => {
211
211
  l(t.id), h(!1);
212
212
  },
@@ -227,9 +227,9 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
227
227
  c !== t.id && (e.currentTarget.style.backgroundColor = "transparent");
228
228
  },
229
229
  children: [
230
- /* @__PURE__ */ o("div", {
230
+ /* @__PURE__ */ a("div", {
231
231
  style: { flex: 1 },
232
- children: [/* @__PURE__ */ o("div", {
232
+ children: [/* @__PURE__ */ a("div", {
233
233
  style: {
234
234
  fontSize: "13px",
235
235
  fontWeight: 500,
@@ -238,7 +238,7 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
238
238
  alignItems: "center",
239
239
  gap: "6px"
240
240
  },
241
- children: [t.name, t.isDefault && /* @__PURE__ */ a("span", {
241
+ children: [t.name, t.isDefault && /* @__PURE__ */ i("span", {
242
242
  style: {
243
243
  fontSize: "10px",
244
244
  padding: "2px 6px",
@@ -248,7 +248,7 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
248
248
  },
249
249
  children: p("bigconsole.filters.presets.defaultBadge", "Default")
250
250
  })]
251
- }), t.description && /* @__PURE__ */ a("div", {
251
+ }), t.description && /* @__PURE__ */ i("div", {
252
252
  style: {
253
253
  fontSize: "11px",
254
254
  color: e.textTertiary,
@@ -257,7 +257,7 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
257
257
  children: t.description
258
258
  })]
259
259
  }),
260
- !t.isDefault && !t.id.startsWith("preset-last") && !t.id.startsWith("preset-this") && /* @__PURE__ */ a("button", {
260
+ !t.isDefault && !t.id.startsWith("preset-last") && !t.id.startsWith("preset-this") && /* @__PURE__ */ i("button", {
261
261
  onClick: (e) => T(e, t.id),
262
262
  style: {
263
263
  padding: "4px",
@@ -277,17 +277,17 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
277
277
  t.currentTarget.style.backgroundColor = "transparent", t.currentTarget.style.color = e.textTertiary;
278
278
  },
279
279
  title: p("bigconsole.filters.presets.deletePresetTitle", "Delete preset"),
280
- children: /* @__PURE__ */ o("svg", {
280
+ children: /* @__PURE__ */ a("svg", {
281
281
  width: "14",
282
282
  height: "14",
283
283
  viewBox: "0 0 24 24",
284
284
  fill: "none",
285
285
  stroke: "currentColor",
286
286
  strokeWidth: "2",
287
- children: [/* @__PURE__ */ a("polyline", { points: "3,6 5,6 21,6" }), /* @__PURE__ */ a("path", { d: "M19,6v14a2,2,0,01-2,2H7a2,2,0,01-2-2V6m3,0V4a2,2,0,012-2h4a2,2,0,012,2v2" })]
287
+ children: [/* @__PURE__ */ i("polyline", { points: "3,6 5,6 21,6" }), /* @__PURE__ */ i("path", { d: "M19,6v14a2,2,0,01-2,2H7a2,2,0,01-2-2V6m3,0V4a2,2,0,012-2h4a2,2,0,012,2v2" })]
288
288
  })
289
289
  }),
290
- c === t.id && /* @__PURE__ */ a("svg", {
290
+ c === t.id && /* @__PURE__ */ i("svg", {
291
291
  width: "16",
292
292
  height: "16",
293
293
  viewBox: "0 0 24 24",
@@ -295,10 +295,10 @@ function s({ presets: s, activePresetId: c, onApplyPreset: l, onSavePreset: u, o
295
295
  stroke: e.actionPrimaryBg,
296
296
  strokeWidth: "3",
297
297
  style: { marginLeft: "8px" },
298
- children: /* @__PURE__ */ a("polyline", { points: "20,6 9,17 4,12" })
298
+ children: /* @__PURE__ */ i("polyline", { points: "20,6 9,17 4,12" })
299
299
  })
300
300
  ]
301
- }, t.id)), s.length === 0 && /* @__PURE__ */ a("div", {
301
+ }, t.id)), s.length === 0 && /* @__PURE__ */ i("div", {
302
302
  style: {
303
303
  padding: "20px 16px",
304
304
  textAlign: "center",
@@ -2,23 +2,23 @@ import { SECTION_FOCUS_RING as e } from "../../common/sectionStyles.js";
2
2
  import "../../common/index.js";
3
3
  import t from "../../../hooks/useGlobalFilters.js";
4
4
  import n from "../../../hooks/useFilterUrlSync.js";
5
- import r from "../../../hooks/useFilterPresets.js";
5
+ import ee from "../../../hooks/useFilterPresets.js";
6
6
  import "../../../hooks/index.js";
7
- import { SEMANTIC_COLORS as i } from "../../../utils/semanticTokens.js";
8
- import ee from "./FilterChip.js";
7
+ import { SEMANTIC_COLORS as r } from "../../../utils/semanticTokens.js";
8
+ import i from "./FilterChip.js";
9
9
  import a from "./FilterEditor.js";
10
10
  import o from "./FilterPresetSelector.js";
11
11
  import { useCallback as s, useEffect as c, useState as l } from "react";
12
- import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
12
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
13
+ import { useI18n as f } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
14
14
  //#region src/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.tsx
15
15
  var p = `inline-flex min-h-control-sm items-center gap-icon-gap rounded-button border border-[var(--color-border-subtle)] bg-bg-surface px-3 py-1 text-sm font-medium text-text-primary motion-safe:transition-colors hover:bg-bg-accentSubtle ${e}`, m = `inline-flex min-h-control-sm items-center gap-icon-gap rounded-button px-2 py-1 text-sm font-medium text-text-secondary motion-safe:transition-colors hover:bg-bg-accentSubtle ${e}`;
16
16
  function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className: _ = "", enableUrlSync: v = !0, enablePresets: y = !0 }) {
17
- let { t: b } = u(), { filters: x, activeValues: S, loading: C, fetchFilters: w, createFilter: T, updateFilter: E, deleteFilter: D, setFilterValue: O, resetFilters: k } = t(), { getShareableUrl: A, clearUrlParams: j } = n({
17
+ let { t: b } = f(), { filters: x, activeValues: S, loading: C, fetchFilters: w, createFilter: T, updateFilter: E, deleteFilter: D, setFilterValue: O, resetFilters: k } = t(), { getShareableUrl: A, clearUrlParams: j } = n({
18
18
  enabled: v,
19
19
  paramPrefix: "filter_",
20
20
  debounceMs: 300
21
- }), { presets: M, activePresetId: N, loadPresets: P, applyPreset: F, saveCurrentAsPreset: I, deletePreset: L, clearActivePreset: R } = r(e), [z, B] = l(!1), [V, H] = l(!1), [U, W] = l(null), [G, K] = l(!1);
21
+ }), { presets: M, activePresetId: N, loadPresets: P, applyPreset: F, saveCurrentAsPreset: I, deletePreset: L, clearActivePreset: R } = ee(e), [z, B] = l(!1), [V, H] = l(!1), [U, W] = l(null), [G, K] = l(!1);
22
22
  c(() => {
23
23
  e && (w(e), y && P(e));
24
24
  }, [
@@ -87,36 +87,36 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
87
87
  }, [L]), ae = s(() => {
88
88
  B((e) => !e);
89
89
  }, []), $ = Object.keys(S).filter((e) => S[e] !== void 0 && S[e] !== null && S[e] !== "").length;
90
- return C && x.length === 0 ? /* @__PURE__ */ f("div", {
90
+ return C && x.length === 0 ? /* @__PURE__ */ d("div", {
91
91
  className: `flex flex-wrap items-center gap-control-gap border-b border-[var(--color-border-subtle)] bg-bg-sunken px-card-padding py-control-gap ${_}`,
92
92
  role: "status",
93
93
  "aria-live": "polite",
94
94
  "data-testid": "global-filters-loading",
95
- children: [/* @__PURE__ */ d("span", { className: "h-icon-sm w-icon-sm animate-spin rounded-full border-2 border-action-primary-bg border-t-transparent" }), /* @__PURE__ */ d("span", {
95
+ children: [/* @__PURE__ */ u("span", { className: "h-icon-sm w-icon-sm animate-spin rounded-full border-2 border-action-primary-bg border-t-transparent" }), /* @__PURE__ */ u("span", {
96
96
  className: "text-sm text-text-secondary",
97
97
  children: b("bigconsole.filters.bar.loading", "Loading filters...")
98
98
  })]
99
- }) : x.length === 0 ? /* @__PURE__ */ f("div", {
99
+ }) : x.length === 0 ? /* @__PURE__ */ d("div", {
100
100
  className: `flex flex-wrap items-center justify-between gap-control-gap border-b border-[var(--color-border-subtle)] bg-bg-sunken px-card-padding py-control-gap ${_}`,
101
101
  "data-testid": "global-filters-empty",
102
102
  children: [
103
- /* @__PURE__ */ f("div", {
103
+ /* @__PURE__ */ d("div", {
104
104
  className: "flex min-w-0 flex-wrap items-center gap-icon-gap",
105
- children: [/* @__PURE__ */ d("h2", {
105
+ children: [/* @__PURE__ */ u("h2", {
106
106
  className: "text-sm font-semibold text-text-primary",
107
107
  children: b("bigconsole.filters.bar.title", "Filters")
108
- }), /* @__PURE__ */ d("span", {
108
+ }), /* @__PURE__ */ u("span", {
109
109
  className: "text-sm text-text-muted",
110
110
  children: b("bigconsole.filters.bar.noFiltersConfigured", "No filters configured")
111
111
  })]
112
112
  }),
113
- /* @__PURE__ */ d("button", {
113
+ /* @__PURE__ */ u("button", {
114
114
  type: "button",
115
115
  onClick: J,
116
116
  className: p,
117
117
  children: b("bigconsole.filters.bar.addFilter", "+ Add Filter")
118
118
  }),
119
- V && /* @__PURE__ */ d(a, {
119
+ V && /* @__PURE__ */ u(a, {
120
120
  filter: U,
121
121
  onSave: X,
122
122
  onClose: () => {
@@ -124,48 +124,48 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
124
124
  }
125
125
  })
126
126
  ]
127
- }) : /* @__PURE__ */ f("section", {
127
+ }) : /* @__PURE__ */ d("section", {
128
128
  className: `flex min-w-0 flex-col border-b border-[var(--color-border-subtle)] bg-bg-sunken ${_}`,
129
129
  "aria-labelledby": "global-filters-heading",
130
130
  "data-testid": "global-filters-bar",
131
131
  children: [
132
- /* @__PURE__ */ f("div", {
132
+ /* @__PURE__ */ d("div", {
133
133
  className: `flex flex-wrap items-center justify-between gap-control-gap px-card-padding py-control-gap ${z ? "" : "border-b border-[var(--color-border-subtle)]"}`,
134
- children: [/* @__PURE__ */ f("div", {
134
+ children: [/* @__PURE__ */ d("div", {
135
135
  className: "flex min-w-0 flex-wrap items-center gap-icon-gap",
136
136
  children: [
137
- /* @__PURE__ */ d("h2", {
137
+ /* @__PURE__ */ u("h2", {
138
138
  id: "global-filters-heading",
139
139
  className: "text-sm font-semibold text-text-primary",
140
140
  children: b("bigconsole.filters.bar.title", "Filters")
141
141
  }),
142
- /* @__PURE__ */ d("span", {
142
+ /* @__PURE__ */ u("span", {
143
143
  className: "rounded-pill bg-bg-surface px-2 py-0.5 text-xs font-medium text-text-secondary",
144
144
  children: x.length
145
145
  }),
146
- $ > 0 && /* @__PURE__ */ d("span", {
146
+ $ > 0 && /* @__PURE__ */ u("span", {
147
147
  className: "rounded-pill bg-[var(--color-status-success-bgSubtle)] px-2 py-0.5 text-xs font-medium text-status-success-text",
148
148
  children: b("bigconsole.filters.bar.activeCount", "{{count}} active", { count: $ ?? "" })
149
149
  })
150
150
  ]
151
- }), /* @__PURE__ */ f("div", {
151
+ }), /* @__PURE__ */ d("div", {
152
152
  className: "flex min-w-0 flex-wrap items-center justify-end gap-control-gap",
153
153
  children: [
154
- y && /* @__PURE__ */ d(o, {
154
+ y && /* @__PURE__ */ u(o, {
155
155
  presets: M,
156
156
  activePresetId: N,
157
157
  onApplyPreset: ne,
158
158
  onSavePreset: re,
159
159
  onDeletePreset: ie
160
160
  }),
161
- v && $ > 0 && /* @__PURE__ */ f("div", {
161
+ v && $ > 0 && /* @__PURE__ */ d("div", {
162
162
  style: { position: "relative" },
163
- children: [/* @__PURE__ */ f("button", {
163
+ children: [/* @__PURE__ */ d("button", {
164
164
  type: "button",
165
165
  onClick: te,
166
166
  title: b("bigconsole.filters.bar.shareUrlTitle", "Copy shareable URL with filters"),
167
167
  className: p,
168
- children: [/* @__PURE__ */ f("svg", {
168
+ children: [/* @__PURE__ */ d("svg", {
169
169
  width: "14",
170
170
  height: "14",
171
171
  viewBox: "0 0 24 24",
@@ -173,9 +173,9 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
173
173
  stroke: "currentColor",
174
174
  strokeWidth: "2",
175
175
  children: [
176
- /* @__PURE__ */ d("path", { d: "M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8" }),
177
- /* @__PURE__ */ d("polyline", { points: "16,6 12,2 8,6" }),
178
- /* @__PURE__ */ d("line", {
176
+ /* @__PURE__ */ u("path", { d: "M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8" }),
177
+ /* @__PURE__ */ u("polyline", { points: "16,6 12,2 8,6" }),
178
+ /* @__PURE__ */ u("line", {
179
179
  x1: "12",
180
180
  y1: "2",
181
181
  x2: "12",
@@ -183,7 +183,7 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
183
183
  })
184
184
  ]
185
185
  }), b("bigconsole.filters.bar.share", "Share")]
186
- }), G && /* @__PURE__ */ d("div", {
186
+ }), G && /* @__PURE__ */ u("div", {
187
187
  style: {
188
188
  position: "absolute",
189
189
  top: "100%",
@@ -191,8 +191,8 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
191
191
  transform: "translateX(-50%)",
192
192
  marginTop: "4px",
193
193
  padding: "6px 12px",
194
- backgroundColor: i.textPrimary,
195
- color: i.bgPrimary,
194
+ backgroundColor: r.textPrimary,
195
+ color: r.bgPrimary,
196
196
  fontSize: "12px",
197
197
  borderRadius: "4px",
198
198
  whiteSpace: "nowrap",
@@ -201,19 +201,19 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
201
201
  children: b("bigconsole.filters.bar.urlCopied", "URL copied!")
202
202
  })]
203
203
  }),
204
- $ > 0 && /* @__PURE__ */ d("button", {
204
+ $ > 0 && /* @__PURE__ */ u("button", {
205
205
  type: "button",
206
206
  onClick: Q,
207
207
  className: `${m} text-status-error-text`,
208
208
  children: b("bigconsole.filters.bar.resetAll", "Reset all")
209
209
  }),
210
- /* @__PURE__ */ d("button", {
210
+ /* @__PURE__ */ u("button", {
211
211
  type: "button",
212
212
  onClick: J,
213
213
  className: p,
214
214
  children: b("bigconsole.filters.bar.addFilter", "+ Add Filter")
215
215
  }),
216
- g && /* @__PURE__ */ d("button", {
216
+ g && /* @__PURE__ */ u("button", {
217
217
  type: "button",
218
218
  onClick: ae,
219
219
  "aria-expanded": !z,
@@ -224,11 +224,11 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
224
224
  ]
225
225
  })]
226
226
  }),
227
- !z && /* @__PURE__ */ d("div", {
227
+ !z && /* @__PURE__ */ u("div", {
228
228
  id: "global-filters-chips",
229
229
  className: "relative flex flex-wrap gap-control-gap px-card-padding py-control-gap",
230
230
  style: { overflow: "visible" },
231
- children: x.map((e) => /* @__PURE__ */ d(ee, {
231
+ children: x.map((e) => /* @__PURE__ */ u(i, {
232
232
  filter: e,
233
233
  value: S[e.id],
234
234
  onChange: (t) => q(e.id, t),
@@ -236,7 +236,7 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
236
236
  onDelete: () => Z(e.id)
237
237
  }, e.id))
238
238
  }),
239
- V && /* @__PURE__ */ d(a, {
239
+ V && /* @__PURE__ */ u(a, {
240
240
  filter: U,
241
241
  onSave: X,
242
242
  onClose: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"GlobalFiltersBar.js","names":[],"sources":["../../../../../src/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.tsx"],"sourcesContent":["/**\n * GlobalFiltersBar Component\n *\n * Displays and manages global dashboard filters.\n * v2.0: Added URL persistence and filter presets support.\n */\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport {\n useGlobalFilters,\n useFilterUrlSync,\n useFilterPresets,\n type GlobalFilter,\n type FilterType,\n} from '../../../hooks';\nimport { FilterChip } from './FilterChip';\nimport { FilterEditor } from './FilterEditor';\nimport { FilterPresetSelector } from './FilterPresetSelector';\nimport { SEMANTIC_COLORS } from '../../../utils/semanticTokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { SECTION_FOCUS_RING } from '../../common';\n\n// ============================================================================\n// Local class vocabulary\n// ============================================================================\n\n/**\n * The filters bar configures the board below it. Before this it shipped a\n * saturated primary \"+ Add Filter\" with an indigo glow and a drop-shadowed\n * container, which made the configuration louder than the data it filtered.\n * Everything here is deliberately secondary weight.\n */\nconst SECONDARY_BUTTON_CLASSES = `inline-flex min-h-control-sm items-center gap-icon-gap rounded-button border border-[var(--color-border-subtle)] bg-bg-surface px-3 py-1 text-sm font-medium text-text-primary motion-safe:transition-colors hover:bg-bg-accentSubtle ${SECTION_FOCUS_RING}`;\n\n/** Text-only affordances (reset, collapse) sit a step below that again. */\nconst QUIET_BUTTON_CLASSES = `inline-flex min-h-control-sm items-center gap-icon-gap rounded-button px-2 py-1 text-sm font-medium text-text-secondary motion-safe:transition-colors hover:bg-bg-accentSubtle ${SECTION_FOCUS_RING}`;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GlobalFiltersBarProps {\n dashboardId: string;\n onFilterChange?: (values: Record<string, unknown>) => void;\n collapsible?: boolean;\n className?: string;\n /** Enable URL sync for shareable filtered views */\n enableUrlSync?: boolean;\n /** Enable filter presets */\n enablePresets?: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function GlobalFiltersBar({\n dashboardId,\n onFilterChange,\n collapsible = true,\n className = '',\n enableUrlSync = true,\n enablePresets = true,\n}: GlobalFiltersBarProps) {\n const { t } = useI18n();\n const {\n filters,\n activeValues,\n loading,\n fetchFilters,\n createFilter,\n updateFilter,\n deleteFilter,\n setFilterValue,\n resetFilters,\n } = useGlobalFilters();\n\n // URL Sync hook\n const { getShareableUrl, clearUrlParams } = useFilterUrlSync({\n enabled: enableUrlSync,\n paramPrefix: 'filter_',\n debounceMs: 300,\n });\n\n // Filter Presets hook\n const {\n presets,\n activePresetId,\n loadPresets,\n applyPreset,\n saveCurrentAsPreset,\n deletePreset: removePreset,\n clearActivePreset,\n } = useFilterPresets(dashboardId);\n\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [isEditorOpen, setIsEditorOpen] = useState(false);\n const [editingFilter, setEditingFilter] = useState<GlobalFilter | null>(null);\n const [showShareTooltip, setShowShareTooltip] = useState(false);\n\n // Fetch filters on mount\n useEffect(() => {\n if (dashboardId) {\n fetchFilters(dashboardId);\n if (enablePresets) {\n loadPresets(dashboardId);\n }\n }\n }, [dashboardId, fetchFilters, loadPresets, enablePresets]);\n\n // Notify parent of filter changes\n useEffect(() => {\n if (onFilterChange) {\n onFilterChange(activeValues);\n }\n }, [activeValues, onFilterChange]);\n\n // Clear active preset when filter values change manually\n useEffect(() => {\n if (activePresetId && Object.keys(activeValues).length > 0) {\n // Check if current values differ from active preset\n const preset = presets.find((p) => p.id === activePresetId);\n if (preset) {\n const presetStr = JSON.stringify(preset.values);\n const currentStr = JSON.stringify(activeValues);\n if (presetStr !== currentStr) {\n clearActivePreset();\n }\n }\n }\n }, [activeValues, activePresetId, presets, clearActivePreset]);\n\n // Handle filter value change\n const handleFilterChange = useCallback(\n (filterId: string, value: unknown) => {\n setFilterValue(filterId, value);\n },\n [setFilterValue]\n );\n\n // Handle add new filter\n const handleAddFilter = useCallback(() => {\n setEditingFilter(null);\n setIsEditorOpen(true);\n }, []);\n\n // Handle edit filter\n const handleEditFilter = useCallback((filter: GlobalFilter) => {\n setEditingFilter(filter);\n setIsEditorOpen(true);\n }, []);\n\n // Handle save filter\n const handleSaveFilter = useCallback(\n async (data: {\n name: string;\n type: FilterType;\n config: Record<string, unknown>;\n defaultValue?: unknown;\n isRequired?: boolean;\n }) => {\n if (editingFilter) {\n await updateFilter({\n id: editingFilter.id,\n name: data.name,\n config: data.config,\n defaultValue: data.defaultValue,\n isRequired: data.isRequired,\n });\n } else {\n await createFilter({\n dashboardId,\n name: data.name,\n type: data.type,\n config: data.config,\n defaultValue: data.defaultValue,\n isRequired: data.isRequired,\n });\n }\n setIsEditorOpen(false);\n setEditingFilter(null);\n },\n [dashboardId, editingFilter, createFilter, updateFilter]\n );\n\n // Handle delete filter\n const handleDeleteFilter = useCallback(\n async (filterId: string) => {\n await deleteFilter(filterId);\n },\n [deleteFilter]\n );\n\n // Handle reset all filters\n const handleResetAll = useCallback(() => {\n resetFilters();\n clearUrlParams();\n clearActivePreset();\n }, [resetFilters, clearUrlParams, clearActivePreset]);\n\n // Handle copy shareable URL\n const handleCopyShareableUrl = useCallback(async () => {\n const url = getShareableUrl();\n try {\n await navigator.clipboard.writeText(url);\n setShowShareTooltip(true);\n setTimeout(() => setShowShareTooltip(false), 2000);\n } catch {\n // Failed to copy URL to clipboard\n }\n }, [getShareableUrl]);\n\n // Handle apply preset\n const handleApplyPreset = useCallback(\n (presetId: string) => {\n applyPreset(presetId);\n },\n [applyPreset]\n );\n\n // Handle save current as preset\n const handleSavePreset = useCallback(\n (name: string, description?: string) => {\n saveCurrentAsPreset(name, description);\n },\n [saveCurrentAsPreset]\n );\n\n // Handle delete preset\n const handleDeletePreset = useCallback(\n (presetId: string) => {\n removePreset(presetId);\n },\n [removePreset]\n );\n\n // Toggle collapse\n const toggleCollapse = useCallback(() => {\n setIsCollapsed((prev) => !prev);\n }, []);\n\n // Count active filters\n const activeFilterCount = Object.keys(activeValues).filter(\n (key) => activeValues[key] !== undefined && activeValues[key] !== null && activeValues[key] !== ''\n ).length;\n\n if (loading && filters.length === 0) {\n return (\n <div\n className={`flex flex-wrap items-center gap-control-gap border-b border-[var(--color-border-subtle)] bg-bg-sunken px-card-padding py-control-gap ${className}`}\n role=\"status\"\n aria-live=\"polite\"\n data-testid=\"global-filters-loading\"\n >\n <span className=\"h-icon-sm w-icon-sm animate-spin rounded-full border-2 border-action-primary-bg border-t-transparent\" />\n <span className=\"text-sm text-text-secondary\">{t('bigconsole.filters.bar.loading', 'Loading filters...')}</span>\n </div>\n );\n }\n\n // Show empty state with \"Add Filter\" button when no filters exist\n if (filters.length === 0) {\n return (\n <div\n className={`flex flex-wrap items-center justify-between gap-control-gap border-b border-[var(--color-border-subtle)] bg-bg-sunken px-card-padding py-control-gap ${className}`}\n data-testid=\"global-filters-empty\"\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-icon-gap\">\n <h2 className=\"text-sm font-semibold text-text-primary\">{t('bigconsole.filters.bar.title', 'Filters')}</h2>\n <span className=\"text-sm text-text-muted\">\n {t('bigconsole.filters.bar.noFiltersConfigured', 'No filters configured')}\n </span>\n </div>\n <button type=\"button\" onClick={handleAddFilter} className={SECONDARY_BUTTON_CLASSES}>\n {t('bigconsole.filters.bar.addFilter', '+ Add Filter')}\n </button>\n\n {/* Filter Editor Modal */}\n {isEditorOpen && (\n <FilterEditor\n filter={editingFilter}\n onSave={handleSaveFilter}\n onClose={() => {\n setIsEditorOpen(false);\n setEditingFilter(null);\n }}\n />\n )}\n </div>\n );\n }\n\n return (\n <section\n // A configuration band, not a result: recessed surface, no drop shadow,\n // secondary-weight controls. It sits directly above the board and must\n // stay quieter than it.\n className={`flex min-w-0 flex-col border-b border-[var(--color-border-subtle)] bg-bg-sunken ${className}`}\n aria-labelledby=\"global-filters-heading\"\n data-testid=\"global-filters-bar\"\n >\n {/* Header */}\n <div\n className={`flex flex-wrap items-center justify-between gap-control-gap px-card-padding py-control-gap ${\n isCollapsed ? '' : 'border-b border-[var(--color-border-subtle)]'\n }`}\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-icon-gap\">\n <h2 id=\"global-filters-heading\" className=\"text-sm font-semibold text-text-primary\">\n {t('bigconsole.filters.bar.title', 'Filters')}\n </h2>\n <span className=\"rounded-pill bg-bg-surface px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {filters.length}\n </span>\n {activeFilterCount > 0 && (\n <span className=\"rounded-pill bg-[var(--color-status-success-bgSubtle)] px-2 py-0.5 text-xs font-medium text-status-success-text\">\n {t('bigconsole.filters.bar.activeCount', '{{count}} active', {\n count: activeFilterCount ?? '',\n })}\n </span>\n )}\n </div>\n\n <div className=\"flex min-w-0 flex-wrap items-center justify-end gap-control-gap\">\n {/* Filter Presets Selector */}\n {enablePresets && (\n <FilterPresetSelector\n presets={presets}\n activePresetId={activePresetId}\n onApplyPreset={handleApplyPreset}\n onSavePreset={handleSavePreset}\n onDeletePreset={handleDeletePreset}\n />\n )}\n\n {/* Share URL Button */}\n {enableUrlSync && activeFilterCount > 0 && (\n <div style={{ position: 'relative' }}>\n <button\n type=\"button\"\n onClick={handleCopyShareableUrl}\n title={t('bigconsole.filters.bar.shareUrlTitle', 'Copy shareable URL with filters')}\n className={SECONDARY_BUTTON_CLASSES}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8\" />\n <polyline points=\"16,6 12,2 8,6\" />\n <line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"15\" />\n </svg>\n {t('bigconsole.filters.bar.share', 'Share')}\n </button>\n {showShareTooltip && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: '50%',\n transform: 'translateX(-50%)',\n marginTop: '4px',\n padding: '6px 12px',\n backgroundColor: SEMANTIC_COLORS.textPrimary,\n color: SEMANTIC_COLORS.bgPrimary,\n fontSize: '12px',\n borderRadius: '4px',\n whiteSpace: 'nowrap',\n zIndex: 100001,\n }}\n >\n {t('bigconsole.filters.bar.urlCopied', 'URL copied!')}\n </div>\n )}\n </div>\n )}\n\n {/* Reset Button */}\n {activeFilterCount > 0 && (\n <button type=\"button\" onClick={handleResetAll} className={`${QUIET_BUTTON_CLASSES} text-status-error-text`}>\n {t('bigconsole.filters.bar.resetAll', 'Reset all')}\n </button>\n )}\n\n {/* Add Filter Button */}\n <button type=\"button\" onClick={handleAddFilter} className={SECONDARY_BUTTON_CLASSES}>\n {t('bigconsole.filters.bar.addFilter', '+ Add Filter')}\n </button>\n\n {/* Collapse Button */}\n {collapsible && (\n <button\n type=\"button\"\n onClick={toggleCollapse}\n aria-expanded={!isCollapsed}\n // The chips container is unmounted while collapsed; pointing\n // aria-controls at a missing id is an invalid reference, so only\n // advertise it when the target actually exists.\n aria-controls={isCollapsed ? undefined : 'global-filters-chips'}\n className={QUIET_BUTTON_CLASSES}\n >\n {isCollapsed\n ? t('bigconsole.filters.bar.expand', '▼ Expand')\n : t('bigconsole.filters.bar.collapse', '▲ Collapse')}\n </button>\n )}\n </div>\n </div>\n\n {/* Filters List */}\n {!isCollapsed && (\n <div\n id=\"global-filters-chips\"\n className=\"relative flex flex-wrap gap-control-gap px-card-padding py-control-gap\"\n style={{ overflow: 'visible' }}\n >\n {filters.map((filter) => (\n <FilterChip\n key={filter.id}\n filter={filter}\n value={activeValues[filter.id]}\n onChange={(value) => handleFilterChange(filter.id, value)}\n onEdit={() => handleEditFilter(filter)}\n onDelete={() => handleDeleteFilter(filter.id)}\n />\n ))}\n </div>\n )}\n\n {/* Filter Editor Modal */}\n {isEditorOpen && (\n <FilterEditor\n filter={editingFilter}\n onSave={handleSaveFilter}\n onClose={() => {\n setIsEditorOpen(false);\n setEditingFilter(null);\n }}\n />\n )}\n </section>\n );\n}\n\nexport default GlobalFiltersBar;\n"],"mappings":"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"}
1
+ {"version":3,"file":"GlobalFiltersBar.js","names":[],"sources":["../../../../../src/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.tsx"],"sourcesContent":["/**\n * GlobalFiltersBar Component\n *\n * Displays and manages global dashboard filters.\n * v2.0: Added URL persistence and filter presets support.\n */\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport {\n useGlobalFilters,\n useFilterUrlSync,\n useFilterPresets,\n type GlobalFilter,\n type FilterType,\n} from '../../../hooks';\nimport { FilterChip } from './FilterChip';\nimport { FilterEditor } from './FilterEditor';\nimport { FilterPresetSelector } from './FilterPresetSelector';\nimport { SEMANTIC_COLORS } from '../../../utils/semanticTokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { SECTION_FOCUS_RING } from '../../common';\n\n// ============================================================================\n// Local class vocabulary\n// ============================================================================\n\n/**\n * The filters bar configures the board below it. Before this it shipped a\n * saturated primary \"+ Add Filter\" with an indigo glow and a drop-shadowed\n * container, which made the configuration louder than the data it filtered.\n * Everything here is deliberately secondary weight.\n */\nconst SECONDARY_BUTTON_CLASSES = `inline-flex min-h-control-sm items-center gap-icon-gap rounded-button border border-[var(--color-border-subtle)] bg-bg-surface px-3 py-1 text-sm font-medium text-text-primary motion-safe:transition-colors hover:bg-bg-accentSubtle ${SECTION_FOCUS_RING}`;\n\n/** Text-only affordances (reset, collapse) sit a step below that again. */\nconst QUIET_BUTTON_CLASSES = `inline-flex min-h-control-sm items-center gap-icon-gap rounded-button px-2 py-1 text-sm font-medium text-text-secondary motion-safe:transition-colors hover:bg-bg-accentSubtle ${SECTION_FOCUS_RING}`;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GlobalFiltersBarProps {\n dashboardId: string;\n onFilterChange?: (values: Record<string, unknown>) => void;\n collapsible?: boolean;\n className?: string;\n /** Enable URL sync for shareable filtered views */\n enableUrlSync?: boolean;\n /** Enable filter presets */\n enablePresets?: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function GlobalFiltersBar({\n dashboardId,\n onFilterChange,\n collapsible = true,\n className = '',\n enableUrlSync = true,\n enablePresets = true,\n}: GlobalFiltersBarProps) {\n const { t } = useI18n();\n const {\n filters,\n activeValues,\n loading,\n fetchFilters,\n createFilter,\n updateFilter,\n deleteFilter,\n setFilterValue,\n resetFilters,\n } = useGlobalFilters();\n\n // URL Sync hook\n const { getShareableUrl, clearUrlParams } = useFilterUrlSync({\n enabled: enableUrlSync,\n paramPrefix: 'filter_',\n debounceMs: 300,\n });\n\n // Filter Presets hook\n const {\n presets,\n activePresetId,\n loadPresets,\n applyPreset,\n saveCurrentAsPreset,\n deletePreset: removePreset,\n clearActivePreset,\n } = useFilterPresets(dashboardId);\n\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [isEditorOpen, setIsEditorOpen] = useState(false);\n const [editingFilter, setEditingFilter] = useState<GlobalFilter | null>(null);\n const [showShareTooltip, setShowShareTooltip] = useState(false);\n\n // Fetch filters on mount\n useEffect(() => {\n if (dashboardId) {\n fetchFilters(dashboardId);\n if (enablePresets) {\n loadPresets(dashboardId);\n }\n }\n }, [dashboardId, fetchFilters, loadPresets, enablePresets]);\n\n // Notify parent of filter changes\n useEffect(() => {\n if (onFilterChange) {\n onFilterChange(activeValues);\n }\n }, [activeValues, onFilterChange]);\n\n // Clear active preset when filter values change manually\n useEffect(() => {\n if (activePresetId && Object.keys(activeValues).length > 0) {\n // Check if current values differ from active preset\n const preset = presets.find((p) => p.id === activePresetId);\n if (preset) {\n const presetStr = JSON.stringify(preset.values);\n const currentStr = JSON.stringify(activeValues);\n if (presetStr !== currentStr) {\n clearActivePreset();\n }\n }\n }\n }, [activeValues, activePresetId, presets, clearActivePreset]);\n\n // Handle filter value change\n const handleFilterChange = useCallback(\n (filterId: string, value: unknown) => {\n setFilterValue(filterId, value);\n },\n [setFilterValue]\n );\n\n // Handle add new filter\n const handleAddFilter = useCallback(() => {\n setEditingFilter(null);\n setIsEditorOpen(true);\n }, []);\n\n // Handle edit filter\n const handleEditFilter = useCallback((filter: GlobalFilter) => {\n setEditingFilter(filter);\n setIsEditorOpen(true);\n }, []);\n\n // Handle save filter\n const handleSaveFilter = useCallback(\n async (data: {\n name: string;\n type: FilterType;\n config: Record<string, unknown>;\n defaultValue?: unknown;\n isRequired?: boolean;\n }) => {\n if (editingFilter) {\n await updateFilter({\n id: editingFilter.id,\n name: data.name,\n config: data.config,\n defaultValue: data.defaultValue,\n isRequired: data.isRequired,\n });\n } else {\n await createFilter({\n dashboardId,\n name: data.name,\n type: data.type,\n config: data.config,\n defaultValue: data.defaultValue,\n isRequired: data.isRequired,\n });\n }\n setIsEditorOpen(false);\n setEditingFilter(null);\n },\n [dashboardId, editingFilter, createFilter, updateFilter]\n );\n\n // Handle delete filter\n const handleDeleteFilter = useCallback(\n async (filterId: string) => {\n await deleteFilter(filterId);\n },\n [deleteFilter]\n );\n\n // Handle reset all filters\n const handleResetAll = useCallback(() => {\n resetFilters();\n clearUrlParams();\n clearActivePreset();\n }, [resetFilters, clearUrlParams, clearActivePreset]);\n\n // Handle copy shareable URL\n const handleCopyShareableUrl = useCallback(async () => {\n const url = getShareableUrl();\n try {\n await navigator.clipboard.writeText(url);\n setShowShareTooltip(true);\n setTimeout(() => setShowShareTooltip(false), 2000);\n } catch {\n // Failed to copy URL to clipboard\n }\n }, [getShareableUrl]);\n\n // Handle apply preset\n const handleApplyPreset = useCallback(\n (presetId: string) => {\n applyPreset(presetId);\n },\n [applyPreset]\n );\n\n // Handle save current as preset\n const handleSavePreset = useCallback(\n (name: string, description?: string) => {\n saveCurrentAsPreset(name, description);\n },\n [saveCurrentAsPreset]\n );\n\n // Handle delete preset\n const handleDeletePreset = useCallback(\n (presetId: string) => {\n removePreset(presetId);\n },\n [removePreset]\n );\n\n // Toggle collapse\n const toggleCollapse = useCallback(() => {\n setIsCollapsed((prev) => !prev);\n }, []);\n\n // Count active filters\n const activeFilterCount = Object.keys(activeValues).filter(\n (key) => activeValues[key] !== undefined && activeValues[key] !== null && activeValues[key] !== ''\n ).length;\n\n if (loading && filters.length === 0) {\n return (\n <div\n className={`flex flex-wrap items-center gap-control-gap border-b border-[var(--color-border-subtle)] bg-bg-sunken px-card-padding py-control-gap ${className}`}\n role=\"status\"\n aria-live=\"polite\"\n data-testid=\"global-filters-loading\"\n >\n <span className=\"h-icon-sm w-icon-sm animate-spin rounded-full border-2 border-action-primary-bg border-t-transparent\" />\n <span className=\"text-sm text-text-secondary\">{t('bigconsole.filters.bar.loading', 'Loading filters...')}</span>\n </div>\n );\n }\n\n // Show empty state with \"Add Filter\" button when no filters exist\n if (filters.length === 0) {\n return (\n <div\n className={`flex flex-wrap items-center justify-between gap-control-gap border-b border-[var(--color-border-subtle)] bg-bg-sunken px-card-padding py-control-gap ${className}`}\n data-testid=\"global-filters-empty\"\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-icon-gap\">\n <h2 className=\"text-sm font-semibold text-text-primary\">{t('bigconsole.filters.bar.title', 'Filters')}</h2>\n <span className=\"text-sm text-text-muted\">\n {t('bigconsole.filters.bar.noFiltersConfigured', 'No filters configured')}\n </span>\n </div>\n <button type=\"button\" onClick={handleAddFilter} className={SECONDARY_BUTTON_CLASSES}>\n {t('bigconsole.filters.bar.addFilter', '+ Add Filter')}\n </button>\n\n {/* Filter Editor Modal */}\n {isEditorOpen && (\n <FilterEditor\n filter={editingFilter}\n onSave={handleSaveFilter}\n onClose={() => {\n setIsEditorOpen(false);\n setEditingFilter(null);\n }}\n />\n )}\n </div>\n );\n }\n\n return (\n <section\n // A configuration band, not a result: recessed surface, no drop shadow,\n // secondary-weight controls. It sits directly above the board and must\n // stay quieter than it.\n className={`flex min-w-0 flex-col border-b border-[var(--color-border-subtle)] bg-bg-sunken ${className}`}\n aria-labelledby=\"global-filters-heading\"\n data-testid=\"global-filters-bar\"\n >\n {/* Header */}\n <div\n className={`flex flex-wrap items-center justify-between gap-control-gap px-card-padding py-control-gap ${\n isCollapsed ? '' : 'border-b border-[var(--color-border-subtle)]'\n }`}\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-icon-gap\">\n <h2 id=\"global-filters-heading\" className=\"text-sm font-semibold text-text-primary\">\n {t('bigconsole.filters.bar.title', 'Filters')}\n </h2>\n <span className=\"rounded-pill bg-bg-surface px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {filters.length}\n </span>\n {activeFilterCount > 0 && (\n <span className=\"rounded-pill bg-[var(--color-status-success-bgSubtle)] px-2 py-0.5 text-xs font-medium text-status-success-text\">\n {t('bigconsole.filters.bar.activeCount', '{{count}} active', {\n count: activeFilterCount ?? '',\n })}\n </span>\n )}\n </div>\n\n <div className=\"flex min-w-0 flex-wrap items-center justify-end gap-control-gap\">\n {/* Filter Presets Selector */}\n {enablePresets && (\n <FilterPresetSelector\n presets={presets}\n activePresetId={activePresetId}\n onApplyPreset={handleApplyPreset}\n onSavePreset={handleSavePreset}\n onDeletePreset={handleDeletePreset}\n />\n )}\n\n {/* Share URL Button */}\n {enableUrlSync && activeFilterCount > 0 && (\n <div style={{ position: 'relative' }}>\n <button\n type=\"button\"\n onClick={handleCopyShareableUrl}\n title={t('bigconsole.filters.bar.shareUrlTitle', 'Copy shareable URL with filters')}\n className={SECONDARY_BUTTON_CLASSES}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8\" />\n <polyline points=\"16,6 12,2 8,6\" />\n <line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"15\" />\n </svg>\n {t('bigconsole.filters.bar.share', 'Share')}\n </button>\n {showShareTooltip && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: '50%',\n transform: 'translateX(-50%)',\n marginTop: '4px',\n padding: '6px 12px',\n backgroundColor: SEMANTIC_COLORS.textPrimary,\n color: SEMANTIC_COLORS.bgPrimary,\n fontSize: '12px',\n borderRadius: '4px',\n whiteSpace: 'nowrap',\n zIndex: 100001,\n }}\n >\n {t('bigconsole.filters.bar.urlCopied', 'URL copied!')}\n </div>\n )}\n </div>\n )}\n\n {/* Reset Button */}\n {activeFilterCount > 0 && (\n <button type=\"button\" onClick={handleResetAll} className={`${QUIET_BUTTON_CLASSES} text-status-error-text`}>\n {t('bigconsole.filters.bar.resetAll', 'Reset all')}\n </button>\n )}\n\n {/* Add Filter Button */}\n <button type=\"button\" onClick={handleAddFilter} className={SECONDARY_BUTTON_CLASSES}>\n {t('bigconsole.filters.bar.addFilter', '+ Add Filter')}\n </button>\n\n {/* Collapse Button */}\n {collapsible && (\n <button\n type=\"button\"\n onClick={toggleCollapse}\n aria-expanded={!isCollapsed}\n // The chips container is unmounted while collapsed; pointing\n // aria-controls at a missing id is an invalid reference, so only\n // advertise it when the target actually exists.\n aria-controls={isCollapsed ? undefined : 'global-filters-chips'}\n className={QUIET_BUTTON_CLASSES}\n >\n {isCollapsed\n ? t('bigconsole.filters.bar.expand', '▼ Expand')\n : t('bigconsole.filters.bar.collapse', '▲ Collapse')}\n </button>\n )}\n </div>\n </div>\n\n {/* Filters List */}\n {!isCollapsed && (\n <div\n id=\"global-filters-chips\"\n className=\"relative flex flex-wrap gap-control-gap px-card-padding py-control-gap\"\n style={{ overflow: 'visible' }}\n >\n {filters.map((filter) => (\n <FilterChip\n key={filter.id}\n filter={filter}\n value={activeValues[filter.id]}\n onChange={(value) => handleFilterChange(filter.id, value)}\n onEdit={() => handleEditFilter(filter)}\n onDelete={() => handleDeleteFilter(filter.id)}\n />\n ))}\n </div>\n )}\n\n {/* Filter Editor Modal */}\n {isEditorOpen && (\n <FilterEditor\n filter={editingFilter}\n onSave={handleSaveFilter}\n onClose={() => {\n setIsEditorOpen(false);\n setEditingFilter(null);\n }}\n />\n )}\n </section>\n );\n}\n\nexport default GlobalFiltersBar;\n"],"mappings":"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"}