@burdenoff/microfe-bigconsole 2026.1004.3 → 2026.1004.4

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 (150) hide show
  1. package/dist/bigconsole/BigConsoleRoutes.d.ts +1 -1
  2. package/dist/bigconsole/BigConsoleRoutes.d.ts.map +1 -1
  3. package/dist/bigconsole/BigConsoleRoutes.js +15 -1
  4. package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
  5. package/dist/bigconsole/components/DrilldownModal.d.ts.map +1 -1
  6. package/dist/bigconsole/components/DrilldownModal.js +54 -53
  7. package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
  8. package/dist/bigconsole/components/builder/inspector/DataBindingSection.d.ts +3 -1
  9. package/dist/bigconsole/components/builder/inspector/DataBindingSection.d.ts.map +1 -1
  10. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +40 -39
  11. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
  12. package/dist/bigconsole/components/dashboard/DashboardCanvas.d.ts.map +1 -1
  13. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +184 -177
  14. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  15. package/dist/bigconsole/components/dashboard/DashboardGrid.d.ts.map +1 -1
  16. package/dist/bigconsole/components/dashboard/DashboardGrid.js +40 -22
  17. package/dist/bigconsole/components/dashboard/DashboardGrid.js.map +1 -1
  18. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.d.ts.map +1 -1
  19. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +31 -25
  20. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js.map +1 -1
  21. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.d.ts +1 -1
  22. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.d.ts.map +1 -1
  23. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +115 -80
  24. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
  25. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.d.ts.map +1 -1
  26. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +177 -146
  27. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  28. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.d.ts +1 -1
  29. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.d.ts.map +1 -1
  30. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +375 -325
  31. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
  32. package/dist/bigconsole/components/datasink/CacheTTLSelector.d.ts.map +1 -1
  33. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +7 -1
  34. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  35. package/dist/bigconsole/components/parser/ParserSelector.d.ts +3 -1
  36. package/dist/bigconsole/components/parser/ParserSelector.d.ts.map +1 -1
  37. package/dist/bigconsole/components/parser/ParserSelector.js +94 -94
  38. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  39. package/dist/bigconsole/components/pipeline/PipelineCard.d.ts.map +1 -1
  40. package/dist/bigconsole/components/pipeline/PipelineCard.js +111 -89
  41. package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
  42. package/dist/bigconsole/components/pipeline/PipelineScopePicker.d.ts +8 -0
  43. package/dist/bigconsole/components/pipeline/PipelineScopePicker.d.ts.map +1 -0
  44. package/dist/bigconsole/components/pipeline/PipelineScopePicker.js +52 -0
  45. package/dist/bigconsole/components/pipeline/PipelineScopePicker.js.map +1 -0
  46. package/dist/bigconsole/components/widgets/PropertiesPanel.d.ts.map +1 -1
  47. package/dist/bigconsole/components/widgets/PropertiesPanel.js +257 -221
  48. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  49. package/dist/bigconsole/components/widgets/WidgetHeader.d.ts +1 -0
  50. package/dist/bigconsole/components/widgets/WidgetHeader.d.ts.map +1 -1
  51. package/dist/bigconsole/components/widgets/WidgetHeader.js +29 -29
  52. package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
  53. package/dist/bigconsole/components/widgets/WidgetWrapper.d.ts +2 -0
  54. package/dist/bigconsole/components/widgets/WidgetWrapper.d.ts.map +1 -1
  55. package/dist/bigconsole/components/widgets/WidgetWrapper.js +247 -239
  56. package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
  57. package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.d.ts.map +1 -1
  58. package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js +6 -4
  59. package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
  60. package/dist/bigconsole/components/widgets/states/EmptyState.d.ts +1 -0
  61. package/dist/bigconsole/components/widgets/states/EmptyState.d.ts.map +1 -1
  62. package/dist/bigconsole/components/widgets/states/EmptyState.js +4 -4
  63. package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
  64. package/dist/bigconsole/components/workflow/WorkflowDesignPreview.d.ts +7 -0
  65. package/dist/bigconsole/components/workflow/WorkflowDesignPreview.d.ts.map +1 -0
  66. package/dist/bigconsole/components/workflow/WorkflowDesignPreview.js +94 -0
  67. package/dist/bigconsole/components/workflow/WorkflowDesignPreview.js.map +1 -0
  68. package/dist/bigconsole/components/workflow/WorkflowSinkLinkForm.d.ts +7 -0
  69. package/dist/bigconsole/components/workflow/WorkflowSinkLinkForm.d.ts.map +1 -0
  70. package/dist/bigconsole/components/workflow/WorkflowSinkLinkForm.js +101 -0
  71. package/dist/bigconsole/components/workflow/WorkflowSinkLinkForm.js.map +1 -0
  72. package/dist/bigconsole/hooks/useBigConsoleSettings.d.ts +16 -0
  73. package/dist/bigconsole/hooks/useBigConsoleSettings.d.ts.map +1 -0
  74. package/dist/bigconsole/hooks/useBigConsoleSettings.js +57 -0
  75. package/dist/bigconsole/hooks/useBigConsoleSettings.js.map +1 -0
  76. package/dist/bigconsole/hooks/useDashboardOperations.d.ts.map +1 -1
  77. package/dist/bigconsole/hooks/useDashboardOperations.js +102 -79
  78. package/dist/bigconsole/hooks/useDashboardOperations.js.map +1 -1
  79. package/dist/bigconsole/hooks/useExportDashboard.d.ts +3 -1
  80. package/dist/bigconsole/hooks/useExportDashboard.d.ts.map +1 -1
  81. package/dist/bigconsole/hooks/useExportDashboard.js +23 -13
  82. package/dist/bigconsole/hooks/useExportDashboard.js.map +1 -1
  83. package/dist/bigconsole/hooks/useFilterUrlSync.d.ts +18 -0
  84. package/dist/bigconsole/hooks/useFilterUrlSync.d.ts.map +1 -1
  85. package/dist/bigconsole/hooks/useFilterUrlSync.js +87 -57
  86. package/dist/bigconsole/hooks/useFilterUrlSync.js.map +1 -1
  87. package/dist/bigconsole/hooks/useGlobalFilters.d.ts.map +1 -1
  88. package/dist/bigconsole/hooks/useGlobalFilters.js +39 -29
  89. package/dist/bigconsole/hooks/useGlobalFilters.js.map +1 -1
  90. package/dist/bigconsole/hooks/usePageOperations.d.ts.map +1 -1
  91. package/dist/bigconsole/hooks/usePageOperations.js +1 -0
  92. package/dist/bigconsole/hooks/usePageOperations.js.map +1 -1
  93. package/dist/bigconsole/hooks/usePipelineOperations.d.ts.map +1 -1
  94. package/dist/bigconsole/hooks/usePipelineOperations.js +114 -112
  95. package/dist/bigconsole/hooks/usePipelineOperations.js.map +1 -1
  96. package/dist/bigconsole/hooks/useShareRecipients.d.ts +22 -0
  97. package/dist/bigconsole/hooks/useShareRecipients.d.ts.map +1 -0
  98. package/dist/bigconsole/hooks/useShareRecipients.js +198 -0
  99. package/dist/bigconsole/hooks/useShareRecipients.js.map +1 -0
  100. package/dist/bigconsole/pages/DashboardBuilderPage.d.ts.map +1 -1
  101. package/dist/bigconsole/pages/DashboardBuilderPage.js +198 -193
  102. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  103. package/dist/bigconsole/pages/DashboardViewPage.d.ts.map +1 -1
  104. package/dist/bigconsole/pages/DashboardViewPage.js +171 -167
  105. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  106. package/dist/bigconsole/pages/DashboardsPage.d.ts.map +1 -1
  107. package/dist/bigconsole/pages/DashboardsPage.js +313 -266
  108. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  109. package/dist/bigconsole/pages/DataSinkBuilderPage.d.ts.map +1 -1
  110. package/dist/bigconsole/pages/DataSinkBuilderPage.js +84 -79
  111. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  112. package/dist/bigconsole/pages/DataSinkViewPage.d.ts.map +1 -1
  113. package/dist/bigconsole/pages/DataSinkViewPage.js +267 -257
  114. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  115. package/dist/bigconsole/pages/InsightsPage.d.ts.map +1 -1
  116. package/dist/bigconsole/pages/InsightsPage.js +465 -402
  117. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  118. package/dist/bigconsole/pages/PipelineBuilderPage.d.ts.map +1 -1
  119. package/dist/bigconsole/pages/PipelineBuilderPage.js +169 -157
  120. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  121. package/dist/bigconsole/pages/PipelineViewPage.d.ts.map +1 -1
  122. package/dist/bigconsole/pages/PipelineViewPage.js +370 -230
  123. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  124. package/dist/bigconsole/pages/PipelinesPage.d.ts.map +1 -1
  125. package/dist/bigconsole/pages/PipelinesPage.js +181 -151
  126. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  127. package/dist/bigconsole/pages/SettingsPage.d.ts.map +1 -1
  128. package/dist/bigconsole/pages/SettingsPage.js +188 -208
  129. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  130. package/dist/bigconsole/pages/WidgetDemoPage.d.ts.map +1 -1
  131. package/dist/bigconsole/pages/WidgetDemoPage.js +134 -117
  132. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  133. package/dist/bigconsole/pages/WorkflowViewPage.d.ts.map +1 -1
  134. package/dist/bigconsole/pages/WorkflowViewPage.js +315 -267
  135. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  136. package/dist/bigconsole/pages/WorkflowsPage.d.ts.map +1 -1
  137. package/dist/bigconsole/pages/WorkflowsPage.js +4 -3
  138. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  139. package/dist/bigconsole/types/index.d.ts +4 -0
  140. package/dist/bigconsole/types/index.d.ts.map +1 -1
  141. package/dist/generated/wspace-operations.d.ts +148 -0
  142. package/dist/generated/wspace-operations.d.ts.map +1 -1
  143. package/dist/generated/wspace-operations.js +172 -133
  144. package/dist/generated/wspace-operations.js.map +1 -1
  145. package/dist/generated/wspace-types.d.ts +21 -0
  146. package/dist/generated/wspace-types.d.ts.map +1 -1
  147. package/dist/generated/wspace-types.js.map +1 -1
  148. package/dist/microfe-bigconsole.css +1 -1
  149. package/dist/translations/en.d.ts.map +1 -1
  150. package/package.json +1 -1
@@ -1,171 +1,202 @@
1
- import { SECTION_FOCUS_RING as e } from "../../common/sectionStyles.js";
1
+ import { useDashboardStore as e, useGlobalFilterValues as t } from "../../../store/dashboardStore.js";
2
+ import "../../../store/index.js";
3
+ import { SECTION_FOCUS_RING as n } from "../../common/sectionStyles.js";
2
4
  import "../../common/index.js";
3
- import t from "../../../hooks/useGlobalFilters.js";
4
- import n from "../../../hooks/useFilterUrlSync.js";
5
- import ee from "../../../hooks/useFilterPresets.js";
5
+ import ee from "../../../hooks/useGlobalFilters.js";
6
+ import r from "../../../hooks/useFilterUrlSync.js";
7
+ import i from "../../../hooks/useFilterPresets.js";
6
8
  import "../../../hooks/index.js";
7
- import { SEMANTIC_COLORS as r } from "../../../utils/semanticTokens.js";
8
- import i from "./FilterChip.js";
9
- import a from "./FilterEditor.js";
10
- import o from "./FilterPresetSelector.js";
11
- import { useCallback as s, useEffect as c, useState as l } from "react";
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";
9
+ import { SEMANTIC_COLORS as a } from "../../../utils/semanticTokens.js";
10
+ import o from "./FilterChip.js";
11
+ import s from "./FilterEditor.js";
12
+ import c from "./FilterPresetSelector.js";
13
+ import { useCallback as l, useEffect as u, useState as d } from "react";
14
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
15
+ import { useI18n as m } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
14
16
  //#region src/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.tsx
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
- function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className: _ = "", enableUrlSync: v = !0, enablePresets: y = !0 }) {
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
- enabled: v,
17
+ var h = `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 ${n}`, g = `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 ${n}`;
18
+ function _({ dashboardId: n, onFilterChange: _, collapsible: v = !0, className: y = "", enableUrlSync: b = !0, enablePresets: x = !0 }) {
19
+ let { t: S } = m(), { filters: C, loading: te, error: ne, fetchFilters: w, createFilter: T, updateFilter: E, deleteFilter: D } = ee(), O = t(), k = e((e) => e.setGlobalFilterValue), A = e((e) => e.setGlobalFilterValues), j = e((e) => e.clearGlobalFilterValue);
20
+ u(() => {
21
+ let t = e.getState().globalFilterValues, n = Object.fromEntries(C.filter((e) => e.defaultValue !== void 0 && !(e.id in t)).map((e) => [e.id, e.defaultValue]));
22
+ Object.keys(n).length && A({
23
+ ...n,
24
+ ...t
25
+ });
26
+ }, [
27
+ C,
28
+ O,
29
+ A
30
+ ]);
31
+ let { getShareableUrl: M, clearUrlParams: N } = r({
32
+ enabled: b,
19
33
  paramPrefix: "filter_",
20
34
  debounceMs: 300
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
- c(() => {
23
- e && (w(e), y && P(e));
35
+ }), { presets: P, activePresetId: F, loadPresets: I, applyPreset: L, saveCurrentAsPreset: R, deletePreset: z, clearActivePreset: B } = i(n), [V, re] = d(!1), [H, U] = d(!1), [W, G] = d(null), [K, q] = d(!1);
36
+ u(() => {
37
+ n && (w(n), x && I(n));
24
38
  }, [
25
- e,
39
+ n,
26
40
  w,
27
- P,
28
- y
29
- ]), c(() => {
30
- h && h(S);
31
- }, [S, h]), c(() => {
32
- if (N && Object.keys(S).length > 0) {
33
- let e = M.find((e) => e.id === N);
34
- e && JSON.stringify(e.values) !== JSON.stringify(S) && R();
41
+ I,
42
+ x
43
+ ]), u(() => {
44
+ _ && _(e.getState().globalFilterValues);
45
+ }, [O, _]), u(() => {
46
+ if (F && Object.keys(O).length > 0) {
47
+ let e = P.find((e) => e.id === F);
48
+ e && JSON.stringify(e.values) !== JSON.stringify(O) && B();
35
49
  }
36
50
  }, [
37
- S,
38
- N,
39
- M,
40
- R
51
+ O,
52
+ F,
53
+ P,
54
+ B
41
55
  ]);
42
- let q = s((e, t) => {
43
- O(e, t);
44
- }, [O]), J = s(() => {
45
- W(null), H(!0);
46
- }, []), Y = s((e) => {
47
- W(e), H(!0);
48
- }, []), X = s(async (t) => {
49
- U ? await E({
50
- id: U.id,
51
- name: t.name,
52
- config: t.config,
53
- defaultValue: t.defaultValue,
54
- isRequired: t.isRequired
55
- }) : await T({
56
- dashboardId: e,
57
- name: t.name,
58
- type: t.type,
59
- config: t.config,
60
- defaultValue: t.defaultValue,
61
- isRequired: t.isRequired
62
- }), H(!1), W(null);
56
+ let J = l((e, t) => {
57
+ k(e, t);
58
+ }, [k]), Y = l(() => {
59
+ G(null), U(!0);
60
+ }, []), ie = l((e) => {
61
+ G(e), U(!0);
62
+ }, []), X = l(async (e) => {
63
+ if (W) {
64
+ if (!await E({
65
+ id: W.id,
66
+ name: e.name,
67
+ config: e.config,
68
+ defaultValue: e.defaultValue,
69
+ isRequired: e.isRequired
70
+ })) throw Error("Filter save failed");
71
+ } else if (!await T({
72
+ dashboardId: n,
73
+ name: e.name,
74
+ type: e.type,
75
+ config: e.config,
76
+ defaultValue: e.defaultValue,
77
+ isRequired: e.isRequired
78
+ })) throw Error("Filter save failed");
79
+ U(!1), G(null);
63
80
  }, [
64
- e,
65
- U,
81
+ n,
82
+ W,
66
83
  T,
67
84
  E
68
- ]), Z = s(async (e) => {
69
- await D(e);
70
- }, [D]), Q = s(() => {
71
- k(), j(), R();
85
+ ]), ae = l(async (e) => {
86
+ await D(e) && j(e);
87
+ }, [D, j]), oe = l(() => {
88
+ A(Object.fromEntries(C.filter((e) => e.defaultValue !== void 0).map((e) => [e.id, e.defaultValue]))), N(), B();
72
89
  }, [
73
- k,
74
- j,
75
- R
76
- ]), te = s(async () => {
77
- let e = A();
90
+ C,
91
+ A,
92
+ N,
93
+ B
94
+ ]), se = l(async () => {
95
+ let e = M();
78
96
  try {
79
- await navigator.clipboard.writeText(e), K(!0), setTimeout(() => K(!1), 2e3);
97
+ await navigator.clipboard.writeText(e), q(!0), setTimeout(() => q(!1), 2e3);
80
98
  } catch {}
81
- }, [A]), ne = s((e) => {
82
- F(e);
83
- }, [F]), re = s((e, t) => {
84
- I(e, t);
85
- }, [I]), ie = s((e) => {
99
+ }, [M]), ce = l((e) => {
86
100
  L(e);
87
- }, [L]), ae = s(() => {
88
- B((e) => !e);
89
- }, []), $ = Object.keys(S).filter((e) => S[e] !== void 0 && S[e] !== null && S[e] !== "").length;
90
- return C && x.length === 0 ? /* @__PURE__ */ d("div", {
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 ${_}`,
101
+ }, [L]), Z = l((e, t) => {
102
+ R(e, t);
103
+ }, [R]), le = l((e) => {
104
+ z(e);
105
+ }, [z]), ue = l(() => {
106
+ re((e) => !e);
107
+ }, []), Q = C.filter((e) => O[e.id] !== void 0 && O[e.id] !== null && O[e.id] !== "").length;
108
+ if (te && C.length === 0 && !H) return /* @__PURE__ */ p("div", {
109
+ 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 ${y}`,
92
110
  role: "status",
93
111
  "aria-live": "polite",
94
112
  "data-testid": "global-filters-loading",
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", {
113
+ children: [/* @__PURE__ */ f("span", { className: "h-icon-sm w-icon-sm animate-spin rounded-full border-2 border-action-primary-bg border-t-transparent" }), /* @__PURE__ */ f("span", {
96
114
  className: "text-sm text-text-secondary",
97
- children: b("bigconsole.filters.bar.loading", "Loading filters...")
115
+ children: S("bigconsole.filters.bar.loading", "Loading filters...")
116
+ })]
117
+ });
118
+ let $ = ne && /* @__PURE__ */ p("div", {
119
+ role: "alert",
120
+ className: "flex flex-wrap items-center gap-2 px-3 py-2 text-sm text-status-error-text",
121
+ children: [/* @__PURE__ */ f("span", { children: S("bigconsole.filters.bar.requestFailed", "Filters could not be loaded or saved. Try again.") }), /* @__PURE__ */ f("button", {
122
+ type: "button",
123
+ onClick: () => void w(n),
124
+ className: g,
125
+ children: S("bigconsole.filters.bar.retry", "Retry")
98
126
  })]
99
- }) : x.length === 0 ? /* @__PURE__ */ d("div", {
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 ${_}`,
127
+ });
128
+ return C.length === 0 ? /* @__PURE__ */ p("div", {
129
+ 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 ${y}`,
101
130
  "data-testid": "global-filters-empty",
102
131
  children: [
103
- /* @__PURE__ */ d("div", {
132
+ /* @__PURE__ */ p("div", {
104
133
  className: "flex min-w-0 flex-wrap items-center gap-icon-gap",
105
- children: [/* @__PURE__ */ u("h2", {
134
+ children: [/* @__PURE__ */ f("h2", {
106
135
  className: "text-sm font-semibold text-text-primary",
107
- children: b("bigconsole.filters.bar.title", "Filters")
108
- }), /* @__PURE__ */ u("span", {
136
+ children: S("bigconsole.filters.bar.title", "Filters")
137
+ }), /* @__PURE__ */ f("span", {
109
138
  className: "text-sm text-text-muted",
110
- children: b("bigconsole.filters.bar.noFiltersConfigured", "No filters configured")
139
+ children: S("bigconsole.filters.bar.noFiltersConfigured", "No filters configured")
111
140
  })]
112
141
  }),
113
- /* @__PURE__ */ u("button", {
142
+ /* @__PURE__ */ f("button", {
114
143
  type: "button",
115
- onClick: J,
116
- className: p,
117
- children: b("bigconsole.filters.bar.addFilter", "+ Add Filter")
144
+ onClick: Y,
145
+ className: h,
146
+ children: S("bigconsole.filters.bar.addFilter", "+ Add Filter")
118
147
  }),
119
- V && /* @__PURE__ */ u(a, {
120
- filter: U,
148
+ $,
149
+ H && /* @__PURE__ */ f(s, {
150
+ filter: W,
121
151
  onSave: X,
122
152
  onClose: () => {
123
- H(!1), W(null);
153
+ U(!1), G(null);
124
154
  }
125
155
  })
126
156
  ]
127
- }) : /* @__PURE__ */ d("section", {
128
- className: `flex min-w-0 flex-col border-b border-[var(--color-border-subtle)] bg-bg-sunken ${_}`,
157
+ }) : /* @__PURE__ */ p("section", {
158
+ className: `flex min-w-0 flex-col border-b border-[var(--color-border-subtle)] bg-bg-sunken ${y}`,
129
159
  "aria-labelledby": "global-filters-heading",
130
160
  "data-testid": "global-filters-bar",
131
161
  children: [
132
- /* @__PURE__ */ d("div", {
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__ */ d("div", {
162
+ $,
163
+ /* @__PURE__ */ p("div", {
164
+ className: `flex flex-wrap items-center justify-between gap-control-gap px-card-padding py-control-gap ${V ? "" : "border-b border-[var(--color-border-subtle)]"}`,
165
+ children: [/* @__PURE__ */ p("div", {
135
166
  className: "flex min-w-0 flex-wrap items-center gap-icon-gap",
136
167
  children: [
137
- /* @__PURE__ */ u("h2", {
168
+ /* @__PURE__ */ f("h2", {
138
169
  id: "global-filters-heading",
139
170
  className: "text-sm font-semibold text-text-primary",
140
- children: b("bigconsole.filters.bar.title", "Filters")
171
+ children: S("bigconsole.filters.bar.title", "Filters")
141
172
  }),
142
- /* @__PURE__ */ u("span", {
173
+ /* @__PURE__ */ f("span", {
143
174
  className: "rounded-pill bg-bg-surface px-2 py-0.5 text-xs font-medium text-text-secondary",
144
- children: x.length
175
+ children: C.length
145
176
  }),
146
- $ > 0 && /* @__PURE__ */ u("span", {
177
+ Q > 0 && /* @__PURE__ */ f("span", {
147
178
  className: "rounded-pill bg-[var(--color-status-success-bgSubtle)] px-2 py-0.5 text-xs font-medium text-status-success-text",
148
- children: b("bigconsole.filters.bar.activeCount", "{{count}} active", { count: $ ?? "" })
179
+ children: S("bigconsole.filters.bar.activeCount", "{{count}} active", { count: Q ?? "" })
149
180
  })
150
181
  ]
151
- }), /* @__PURE__ */ d("div", {
182
+ }), /* @__PURE__ */ p("div", {
152
183
  className: "flex min-w-0 flex-wrap items-center justify-end gap-control-gap",
153
184
  children: [
154
- y && /* @__PURE__ */ u(o, {
155
- presets: M,
156
- activePresetId: N,
157
- onApplyPreset: ne,
158
- onSavePreset: re,
159
- onDeletePreset: ie
185
+ x && /* @__PURE__ */ f(c, {
186
+ presets: P,
187
+ activePresetId: F,
188
+ onApplyPreset: ce,
189
+ onSavePreset: Z,
190
+ onDeletePreset: le
160
191
  }),
161
- v && $ > 0 && /* @__PURE__ */ d("div", {
192
+ b && Q > 0 && /* @__PURE__ */ p("div", {
162
193
  style: { position: "relative" },
163
- children: [/* @__PURE__ */ d("button", {
194
+ children: [/* @__PURE__ */ p("button", {
164
195
  type: "button",
165
- onClick: te,
166
- title: b("bigconsole.filters.bar.shareUrlTitle", "Copy shareable URL with filters"),
167
- className: p,
168
- children: [/* @__PURE__ */ d("svg", {
196
+ onClick: se,
197
+ title: S("bigconsole.filters.bar.shareUrlTitle", "Copy shareable URL with filters"),
198
+ className: h,
199
+ children: [/* @__PURE__ */ p("svg", {
169
200
  width: "14",
170
201
  height: "14",
171
202
  viewBox: "0 0 24 24",
@@ -173,17 +204,17 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
173
204
  stroke: "currentColor",
174
205
  strokeWidth: "2",
175
206
  children: [
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", {
207
+ /* @__PURE__ */ f("path", { d: "M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8" }),
208
+ /* @__PURE__ */ f("polyline", { points: "16,6 12,2 8,6" }),
209
+ /* @__PURE__ */ f("line", {
179
210
  x1: "12",
180
211
  y1: "2",
181
212
  x2: "12",
182
213
  y2: "15"
183
214
  })
184
215
  ]
185
- }), b("bigconsole.filters.bar.share", "Share")]
186
- }), G && /* @__PURE__ */ u("div", {
216
+ }), S("bigconsole.filters.bar.share", "Share")]
217
+ }), K && /* @__PURE__ */ f("div", {
187
218
  style: {
188
219
  position: "absolute",
189
220
  top: "100%",
@@ -191,62 +222,62 @@ function h({ dashboardId: e, onFilterChange: h, collapsible: g = !0, className:
191
222
  transform: "translateX(-50%)",
192
223
  marginTop: "4px",
193
224
  padding: "6px 12px",
194
- backgroundColor: r.textPrimary,
195
- color: r.bgPrimary,
225
+ backgroundColor: a.textPrimary,
226
+ color: a.bgPrimary,
196
227
  fontSize: "12px",
197
228
  borderRadius: "4px",
198
229
  whiteSpace: "nowrap",
199
230
  zIndex: 100001
200
231
  },
201
- children: b("bigconsole.filters.bar.urlCopied", "URL copied!")
232
+ children: S("bigconsole.filters.bar.urlCopied", "URL copied!")
202
233
  })]
203
234
  }),
204
- $ > 0 && /* @__PURE__ */ u("button", {
235
+ Q > 0 && /* @__PURE__ */ f("button", {
205
236
  type: "button",
206
- onClick: Q,
207
- className: `${m} text-status-error-text`,
208
- children: b("bigconsole.filters.bar.resetAll", "Reset all")
237
+ onClick: oe,
238
+ className: `${g} text-status-error-text`,
239
+ children: S("bigconsole.filters.bar.resetAll", "Reset all")
209
240
  }),
210
- /* @__PURE__ */ u("button", {
241
+ /* @__PURE__ */ f("button", {
211
242
  type: "button",
212
- onClick: J,
213
- className: p,
214
- children: b("bigconsole.filters.bar.addFilter", "+ Add Filter")
243
+ onClick: Y,
244
+ className: h,
245
+ children: S("bigconsole.filters.bar.addFilter", "+ Add Filter")
215
246
  }),
216
- g && /* @__PURE__ */ u("button", {
247
+ v && /* @__PURE__ */ f("button", {
217
248
  type: "button",
218
- onClick: ae,
219
- "aria-expanded": !z,
220
- "aria-controls": z ? void 0 : "global-filters-chips",
221
- className: m,
222
- children: z ? b("bigconsole.filters.bar.expand", "▼ Expand") : b("bigconsole.filters.bar.collapse", "▲ Collapse")
249
+ onClick: ue,
250
+ "aria-expanded": !V,
251
+ "aria-controls": V ? void 0 : "global-filters-chips",
252
+ className: g,
253
+ children: V ? S("bigconsole.filters.bar.expand", "▼ Expand") : S("bigconsole.filters.bar.collapse", "▲ Collapse")
223
254
  })
224
255
  ]
225
256
  })]
226
257
  }),
227
- !z && /* @__PURE__ */ u("div", {
258
+ !V && /* @__PURE__ */ f("div", {
228
259
  id: "global-filters-chips",
229
260
  className: "relative flex flex-wrap gap-control-gap px-card-padding py-control-gap",
230
261
  style: { overflow: "visible" },
231
- children: x.map((e) => /* @__PURE__ */ u(i, {
262
+ children: C.map((e) => /* @__PURE__ */ f(o, {
232
263
  filter: e,
233
- value: S[e.id],
234
- onChange: (t) => q(e.id, t),
235
- onEdit: () => Y(e),
236
- onDelete: () => Z(e.id)
264
+ value: O[e.id],
265
+ onChange: (t) => J(e.id, t),
266
+ onEdit: () => ie(e),
267
+ onDelete: () => ae(e.id)
237
268
  }, e.id))
238
269
  }),
239
- V && /* @__PURE__ */ u(a, {
240
- filter: U,
270
+ H && /* @__PURE__ */ f(s, {
271
+ filter: W,
241
272
  onSave: X,
242
273
  onClose: () => {
243
- H(!1), W(null);
274
+ U(!1), G(null);
244
275
  }
245
276
  })
246
277
  ]
247
278
  });
248
279
  }
249
280
  //#endregion
250
- export { h as default };
281
+ export { _ as default };
251
282
 
252
283
  //# sourceMappingURL=GlobalFiltersBar.js.map
@@ -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 { useDashboardStore, useGlobalFilterValues } from '../../../store';\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 { filters, loading, error, fetchFilters, createFilter, updateFilter, deleteFilter } = useGlobalFilters();\n\n // Widgets, presets, URL hydration and the controls share one value store.\n // The definition hook's private defaults must never replace hydrated values.\n const activeValues = useGlobalFilterValues();\n const setFilterValue = useDashboardStore((state) => state.setGlobalFilterValue);\n const setFilterValues = useDashboardStore((state) => state.setGlobalFilterValues);\n const clearFilterValue = useDashboardStore((state) => state.clearGlobalFilterValue);\n\n useEffect(() => {\n const current = useDashboardStore.getState().globalFilterValues;\n const defaults = Object.fromEntries(\n filters\n .filter((filter) => filter.defaultValue !== undefined && !(filter.id in current))\n .map((filter) => [filter.id, filter.defaultValue])\n );\n if (Object.keys(defaults).length) setFilterValues({ ...defaults, ...current });\n }, [filters, activeValues, setFilterValues]);\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 // URL hydration/default initialization can update the store after this\n // render. Notify with its current values, never an old empty snapshot.\n onFilterChange(useDashboardStore.getState().globalFilterValues);\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 const saved = await updateFilter({\n id: editingFilter.id,\n name: data.name,\n config: data.config,\n defaultValue: data.defaultValue,\n isRequired: data.isRequired,\n });\n if (!saved) throw new Error('Filter save failed');\n } else {\n const saved = 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 if (!saved) throw new Error('Filter save failed');\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 if (await deleteFilter(filterId)) clearFilterValue(filterId);\n },\n [deleteFilter, clearFilterValue]\n );\n\n // Handle reset all filters\n const handleResetAll = useCallback(() => {\n setFilterValues(\n Object.fromEntries(\n filters.filter((filter) => filter.defaultValue !== undefined).map((filter) => [filter.id, filter.defaultValue])\n )\n );\n clearUrlParams();\n clearActivePreset();\n }, [filters, setFilterValues, 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 = filters.filter(\n (filter) =>\n activeValues[filter.id] !== undefined && activeValues[filter.id] !== null && activeValues[filter.id] !== ''\n ).length;\n\n if (loading && filters.length === 0 && !isEditorOpen) {\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 const errorFeedback = error && (\n <div role=\"alert\" className=\"flex flex-wrap items-center gap-2 px-3 py-2 text-sm text-status-error-text\">\n <span>{t('bigconsole.filters.bar.requestFailed', 'Filters could not be loaded or saved. Try again.')}</span>\n <button type=\"button\" onClick={() => void fetchFilters(dashboardId)} className={QUIET_BUTTON_CLASSES}>\n {t('bigconsole.filters.bar.retry', 'Retry')}\n </button>\n </div>\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 {errorFeedback}\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 {errorFeedback}\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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"}
@@ -18,6 +18,6 @@ export interface ShareDialogProps {
18
18
  /** False when the actor lacks `bigconsole-dashboard:update`; the control is then read-only. */
19
19
  canChangeVisibility?: boolean;
20
20
  }
21
- export declare function ShareDialog({ dashboardId, dashboardName, isOpen, onClose, visibility, onVisibilityChange, canChangeVisibility, }: ShareDialogProps): React.ReactPortal | null;
21
+ export declare function ShareDialog(props: ShareDialogProps): React.JSX.Element;
22
22
  export default ShareDialog;
23
23
  //# sourceMappingURL=ShareDialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ShareDialog.d.ts","sourceRoot":"","sources":["../../../../../src/bigconsole/components/dashboard/ShareDialog/ShareDialog.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AASzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAuB1D,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,6EAA6E;IAC7E,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,+FAA+F;IAC/F,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAmCD,wBAAgB,WAAW,CAAC,EAC1B,WAAW,EACX,aAAa,EACb,MAAM,EACN,OAAO,EACP,UAAU,EACV,kBAAkB,EAClB,mBAA0B,GAC3B,EAAE,gBAAgB,4BAohBlB;AA2HD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"ShareDialog.d.ts","sourceRoot":"","sources":["../../../../../src/bigconsole/components/dashboard/ShareDialog/ShareDialog.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AASxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AA0B1D,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,6EAA6E;IAC7E,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,+FAA+F;IAC/F,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA4BD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,qBAYlD;AAkuBD,eAAe,WAAW,CAAC"}