@burdenoff/microfe-bigconsole 2026.1013.3 → 2026.1013.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.
package/README.md CHANGED
@@ -35,6 +35,14 @@ import { WorkflowsRoot } from '@burdenoff/micro-fe/workflows';
35
35
 
36
36
  Widget configuration and parser output are rendered as data:
37
37
 
38
+ Explicit data and connected/parser data take priority. For an unbound widget or a
39
+ mock-only binding, existing `config.mockData` and generated `config.data` can supply
40
+ intentional examples; the selected example data carries a **Sample data** badge.
41
+ An explicitly supplied empty result remains empty, and a connected empty/error
42
+ response never switches to fictional samples. Concrete sink/parser/dataset bindings
43
+ remain connected even if a stale canonical binding says MOCK. Table filters and
44
+ CSV exports select the same envelope and rows as the table renderer.
45
+
38
46
  - **Text widgets** render markdown through the shared fe-libs `Markdown`
39
47
  component (raw HTML inside markdown is not rendered, images show their alt
40
48
  text). The `html` format is available only when the widget is configured for
@@ -33,8 +33,8 @@ var a = t(function({ previewOnly: t = !1, widget: a, definition: s, isSelected:
33
33
  }),
34
34
  d && /* @__PURE__ */ r("span", {
35
35
  className: "\n flex-shrink-0\n px-1.5 py-0.5\n rounded\n text-[10px] font-medium uppercase tracking-wide\n bg-status-info-bg-subtle text-status-info-text\n ",
36
- title: "Example values from the template. Connect a data source to see your own data.",
37
- children: "Sample"
36
+ title: "Example values supplied with this widget. Connect a data source to see your own data.",
37
+ children: "Sample data"
38
38
  }),
39
39
  p && /* @__PURE__ */ i("span", {
40
40
  className: "\n flex-shrink-0 inline-flex items-center gap-0.5\n px-1.5 py-0.5 rounded-md\n bg-action-primary-bg/10 text-action-primary-text\n text-[10px] font-medium\n ",
@@ -9,52 +9,53 @@ import ne from "../../hooks/useWidgetComments.js";
9
9
  import re from "../../hooks/useWidgetExport.js";
10
10
  import ie from "../../hooks/useDrilldown.js";
11
11
  import "../../hooks/index.js";
12
- import { resolveTextData as ae } from "./text-widget/textData.js";
13
- import oe from "./WidgetHeader.js";
14
- import { useBigConsoleSettings as se } from "../../hooks/useBigConsoleSettings.js";
15
- import ce from "./states/LoadingState.js";
16
- import le from "./states/ErrorState.js";
17
- import c from "./states/EmptyState.js";
12
+ import { resolveTextData as c } from "./text-widget/textData.js";
13
+ import ae from "./WidgetHeader.js";
14
+ import { useBigConsoleSettings as oe } from "../../hooks/useBigConsoleSettings.js";
15
+ import se from "./states/LoadingState.js";
16
+ import ce from "./states/ErrorState.js";
17
+ import le from "./states/EmptyState.js";
18
18
  import ue from "./WidgetErrorBoundary.js";
19
19
  import { hasCustomIframeConfig as de, hasRenderableCustomConfig as fe } from "./custom/config.js";
20
20
  import { getBindingForWidget as pe } from "../../utils/widgetBinding.js";
21
- import me from "../../renderers/factory/WidgetRendererFactory.js";
22
- import he from "./widget-actions/WidgetActions.js";
21
+ import { isUsableWidgetData as me, resolveWidgetDisplayData as he, widgetDataSourcePolicy as ge, widgetExportRows as _e } from "../../utils/widgetDisplayData.js";
22
+ import ve from "../../renderers/factory/WidgetRendererFactory.js";
23
+ import ye from "./widget-actions/WidgetActions.js";
23
24
  import "./widget-actions/index.js";
24
- import { Suspense as l, lazy as u, memo as d, useCallback as f, useEffect as ge, useMemo as p, useRef as m, useState as h } from "react";
25
- import { useApolloClient as _e } from "@apollo/client/react";
26
- import { jsx as g, jsxs as ve } from "react/jsx-runtime";
25
+ import { Suspense as be, lazy as l, memo as u, useCallback as d, useEffect as xe, useMemo as f, useRef as p, useState as Se } from "react";
26
+ import { useApolloClient as Ce } from "@apollo/client/react";
27
+ import { jsx as m, jsxs as we } from "react/jsx-runtime";
27
28
  //#region src/bigconsole/components/widgets/WidgetWrapper.tsx
28
- var ye = u(() => import("./metric-card/index.js").then((e) => ({ default: e.MetricCardWidget }))), be = u(() => import("./chart/index.js").then((e) => ({ default: e.ChartWidget }))), xe = u(() => import("./table/index.js").then((e) => ({ default: e.TableWidget }))), Se = u(() => import("./pivot-table/index.js").then((e) => ({ default: e.PivotTableWidget }))), Ce = u(() => import("./gauge/index.js").then((e) => ({ default: e.GaugeWidget }))), we = u(() => import("./progress/index.js").then((e) => ({ default: e.ProgressWidget }))), Te = u(() => import("./list/index.js").then((e) => ({ default: e.ListWidget }))), Ee = u(() => import("./heatmap/index.js").then((e) => ({ default: e.HeatmapWidget }))), De = u(() => import("./retention/index.js").then((e) => ({ default: e.RetentionWidget }))), Oe = u(() => import("./calendar/index.js").then((e) => ({ default: e.CalendarWidget }))), ke = u(() => import("./kanban/index.js").then((e) => ({ default: e.KanbanWidget }))), Ae = u(() => import("./timeline/index.js").then((e) => ({ default: e.TimelineWidget }))), je = u(() => import("./kpi-comparison/index.js").then((e) => ({ default: e.KPIComparisonWidget }))), Me = u(() => import("./text-widget/index.js").then((e) => ({ default: e.TextWidget }))), Ne = u(() => import("./map-widget/index.js").then((e) => ({ default: e.MapWidget }))), Pe = u(() => import("./iframe-widget/index.js").then((e) => ({ default: e.IframeWidget }))), Fe = u(() => import("./custom/index.js").then((e) => ({ default: e.CustomWidget })));
29
- u(() => import("./adaptive-card/index.js").then((e) => ({ default: e.AdaptiveCardWidget })));
30
- var Ie = u(() => import("./form/index.js").then((e) => ({ default: e.FormWidget }))), Le = u(() => import("./advanced/AdvancedWidgets.js").then((e) => ({ default: e.SankeyWidget }))), Re = u(() => import("./advanced/AdvancedWidgets.js").then((e) => ({ default: e.BoxPlotWidget }))), ze = u(() => import("./advanced/AdvancedWidgets.js").then((e) => ({ default: e.WaterfallWidget }))), Be = u(() => import("./comments/WidgetComments.js").then((e) => ({ default: e.WidgetComments })));
31
- function _(e, t) {
29
+ var Te = l(() => import("./metric-card/index.js").then((e) => ({ default: e.MetricCardWidget }))), Ee = l(() => import("./chart/index.js").then((e) => ({ default: e.ChartWidget }))), De = l(() => import("./table/index.js").then((e) => ({ default: e.TableWidget }))), Oe = l(() => import("./pivot-table/index.js").then((e) => ({ default: e.PivotTableWidget }))), ke = l(() => import("./gauge/index.js").then((e) => ({ default: e.GaugeWidget }))), Ae = l(() => import("./progress/index.js").then((e) => ({ default: e.ProgressWidget }))), je = l(() => import("./list/index.js").then((e) => ({ default: e.ListWidget }))), Me = l(() => import("./heatmap/index.js").then((e) => ({ default: e.HeatmapWidget }))), Ne = l(() => import("./retention/index.js").then((e) => ({ default: e.RetentionWidget }))), Pe = l(() => import("./calendar/index.js").then((e) => ({ default: e.CalendarWidget }))), Fe = l(() => import("./kanban/index.js").then((e) => ({ default: e.KanbanWidget }))), Ie = l(() => import("./timeline/index.js").then((e) => ({ default: e.TimelineWidget }))), Le = l(() => import("./kpi-comparison/index.js").then((e) => ({ default: e.KPIComparisonWidget }))), Re = l(() => import("./text-widget/index.js").then((e) => ({ default: e.TextWidget }))), ze = l(() => import("./map-widget/index.js").then((e) => ({ default: e.MapWidget }))), Be = l(() => import("./iframe-widget/index.js").then((e) => ({ default: e.IframeWidget }))), Ve = l(() => import("./custom/index.js").then((e) => ({ default: e.CustomWidget })));
30
+ l(() => import("./adaptive-card/index.js").then((e) => ({ default: e.AdaptiveCardWidget })));
31
+ var He = l(() => import("./form/index.js").then((e) => ({ default: e.FormWidget }))), Ue = l(() => import("./advanced/AdvancedWidgets.js").then((e) => ({ default: e.SankeyWidget }))), We = l(() => import("./advanced/AdvancedWidgets.js").then((e) => ({ default: e.BoxPlotWidget }))), Ge = l(() => import("./advanced/AdvancedWidgets.js").then((e) => ({ default: e.WaterfallWidget }))), Ke = l(() => import("./comments/WidgetComments.js").then((e) => ({ default: e.WidgetComments })));
32
+ function h(e, t) {
32
33
  return !(e.previewOnly !== t.previewOnly || e.widget.id !== t.widget.id || e.widget.updatedAt !== t.widget.updatedAt || e.isLoading !== t.isLoading || e.error !== t.error || e.actions !== t.actions || e.data !== t.data || JSON.stringify(e.filterValues) !== JSON.stringify(t.filterValues));
33
34
  }
34
- var v = d(function({ widget: u, children: d, data: _, className: v = "", isLoading: Ve, error: He, onRefresh: y, onDrilldown: Ue, actions: b, onAction: x, filterValues: S, previewOnly: C = !1 }) {
35
- let w = se(), We = r((e) => e.viewMode === "edit"), T = !C && We, E = t((e) => e.selectWidget), D = e(u.id), O = n(u.id), k = i(), A = _e(), j = u.dashboardId, M = p(() => {
36
- if (!j) return {};
35
+ var g = u(function({ widget: l, children: u, data: h, className: g = "", isLoading: qe, error: Je, onRefresh: _, onDrilldown: Ye, actions: v, onAction: y, filterValues: b, previewOnly: x = !1 }) {
36
+ let S = oe(), Xe = r((e) => e.viewMode === "edit"), C = !x && Xe, w = t((e) => e.selectWidget), T = e(l.id), Ze = n(l.id), E = i(), D = Ce(), O = l.dashboardId, k = f(() => {
37
+ if (!O) return {};
37
38
  try {
38
- let e = A.readQuery({
39
+ let e = D.readQuery({
39
40
  query: a,
40
- variables: { id: j }
41
+ variables: { id: O }
41
42
  }), t = {};
42
43
  for (let n of e?.getDashboard?.globalFilters ?? []) {
43
44
  let e = n.config?.field;
44
- typeof e == "string" && e && Object.hasOwn(k, n.id) && (t[n.id] = e);
45
+ typeof e == "string" && e && Object.hasOwn(E, n.id) && (t[n.id] = e);
45
46
  }
46
47
  return t;
47
48
  } catch {
48
49
  return {};
49
50
  }
50
51
  }, [
51
- A,
52
- j,
53
- k
54
- ]), N = p(() => pe(u), [u]), P = N.source.kind !== "DATASINK" || !!N.source.ref || !!N.parserId || !!u.datasetId, { data: F, loading: Ge } = o(u.id, {
55
- skip: C || !P,
56
- pollInterval: (u.refreshInterval ?? 0) * 1e3 || 0
57
- }), I = p(() => {
52
+ D,
53
+ O,
54
+ E
55
+ ]), A = f(() => pe(l), [l]), { hasDataSource: Qe, allowSamples: j, mockSource: M } = ge(l, A), { data: N, loading: $e, error: et } = o(l.id, {
56
+ skip: x || !Qe,
57
+ pollInterval: (l.refreshInterval ?? 0) * 1e3 || 0
58
+ }), P = f(() => {
58
59
  if (typeof window > "u") return {};
59
60
  let e = new URLSearchParams(window.location.search), t = {};
60
61
  return e.forEach((e, n) => {
@@ -63,56 +64,30 @@ var v = d(function({ widget: u, children: d, data: _, className: v = "", isLoadi
63
64
  r.startsWith("__") || (t[r] = e);
64
65
  }
65
66
  }), t;
66
- }, []), L = p(() => {
67
+ }, []), F = f(() => {
67
68
  let e = {};
68
- return I && Object.keys(I).length > 0 && Object.assign(e, I), k && Object.keys(k).length > 0 && Object.assign(e, k), S && Object.keys(S).length > 0 && Object.assign(e, S), e;
69
+ return P && Object.keys(P).length > 0 && Object.assign(e, P), E && Object.keys(E).length > 0 && Object.assign(e, E), b && Object.keys(b).length > 0 && Object.assign(e, b), e;
69
70
  }, [
70
- I,
71
- k,
72
- S
73
- ]), R = Object.keys(L).length > 0, z = Ve ?? (Ge && !F) ?? O.isLoading, B = He ?? O.errorMessage, Ke = s(u.type), V = m(y);
74
- ge(() => {
75
- V.current = y;
76
- }, [y]);
77
- let qe = f(async () => {
78
- V.current && await V.current();
79
- }, []), { timeUntilRefresh: Je, isPaused: Ye } = te({
80
- widgetId: u.id,
81
- refreshInterval: u.refreshInterval,
82
- onRefresh: qe,
83
- enabled: !C && !T && !!u.refreshInterval
84
- }), H = m(null), [U, W] = h(!1), [Xe, Ze] = h(!1), { count: Qe } = ne(u.id, Xe), $e = f(() => {
85
- W((e) => {
86
- let t = !e;
87
- return t && Ze(!0), t;
88
- });
89
- }, []), et = p(() => {
90
- if (_ && Array.isArray(_)) return _;
91
- let e = u.data;
92
- if (e?.processed && Array.isArray(e.processed)) return e.processed;
93
- if (e?.raw) {
94
- let t = typeof e.raw == "string" ? JSON.parse(e.raw) : e.raw;
95
- if (Array.isArray(t)) return t;
96
- }
97
- return null;
98
- }, [_, u]), { exportCSV: tt, exportPNG: nt } = re(u, {
99
- data: et,
100
- containerRef: H
101
- }), G = f((e) => {
102
- if (e == null) return !1;
103
- if (Array.isArray(e)) return e.length > 0;
104
- if (typeof e == "object") {
105
- let t = e, n = Object.keys(t);
106
- return n.length === 0 ? !1 : n.some((e) => {
107
- let n = t[e];
108
- return n == null || n === "" ? !1 : Array.isArray(n) ? n.length > 0 : typeof n == "object" ? G(n) : !0;
109
- });
110
- }
111
- return !0;
112
- }, []), rt = f((e) => {
113
- if (!R || !e) return e;
71
+ P,
72
+ E,
73
+ b
74
+ ]), I = Object.keys(F).length > 0, L = qe ?? ($e && !N) ?? Ze.isLoading, R = Je ?? et?.message ?? Ze.errorMessage, tt = s(l.type), z = p(_);
75
+ xe(() => {
76
+ z.current = _;
77
+ }, [_]);
78
+ let nt = d(async () => {
79
+ z.current && await z.current();
80
+ }, []), { timeUntilRefresh: rt, isPaused: it } = te({
81
+ widgetId: l.id,
82
+ refreshInterval: l.refreshInterval,
83
+ onRefresh: nt,
84
+ enabled: !x && !C && !!l.refreshInterval
85
+ }), B = p(null), [V, H] = Se(!1), [U, at] = Se(!1), { count: ot } = ne(l.id, U), st = d(() => {
86
+ at(!0), H((e) => !e);
87
+ }, []), W = d((e) => {
88
+ if (!I || !e) return e;
114
89
  let t = {}, n = {};
115
- Object.entries(L || {}).forEach(([e, r]) => {
90
+ Object.entries(F || {}).forEach(([e, r]) => {
116
91
  if (e.startsWith("ctx_")) {
117
92
  let n = e.slice(4);
118
93
  t[n] = r;
@@ -174,7 +149,7 @@ var v = d(function({ widget: u, children: d, data: _, className: v = "", isLoadi
174
149
  }
175
150
  }
176
151
  if (typeof a == "object" && a && !Array.isArray(a)) continue;
177
- let n = M[t];
152
+ let n = k[t];
178
153
  if (n) {
179
154
  let t = i(e, n);
180
155
  if (t !== void 0) {
@@ -208,7 +183,18 @@ var v = d(function({ widget: u, children: d, data: _, className: v = "", isLoadi
208
183
  });
209
184
  if (Array.isArray(e)) return a(e);
210
185
  if (e && typeof e == "object") {
211
- for (let t of [
186
+ let t = [
187
+ ...l.type === "table" ? [
188
+ "data",
189
+ "items",
190
+ "rows",
191
+ "results",
192
+ "records",
193
+ "list",
194
+ "sales",
195
+ "entries",
196
+ "values"
197
+ ] : l.type === "pivot_table" ? ["rows"] : [],
212
198
  "kpis",
213
199
  "rows",
214
200
  "items",
@@ -222,343 +208,391 @@ var v = d(function({ widget: u, children: d, data: _, className: v = "", isLoadi
222
208
  "values",
223
209
  "series",
224
210
  "datasets"
225
- ]) if (e[t] && Array.isArray(e[t])) {
226
- let n = a(e[t]);
211
+ ];
212
+ for (let n of t) if (e[n] && Array.isArray(e[n])) {
213
+ let t = a(e[n]);
227
214
  return {
228
215
  ...e,
229
- [t]: n,
230
- ...t === "rows" ? { totalRows: n.length } : {}
216
+ [n]: t,
217
+ ...n === "rows" ? { totalRows: t.length } : {}
231
218
  };
232
219
  }
233
- let t = Object.entries(e).filter(([e, t]) => Array.isArray(t));
234
- if (t.length > 0) {
235
- let [n, r] = t[0], i = a(r);
220
+ let n = Object.entries(e).filter(([e, t]) => Array.isArray(t));
221
+ if (n.length > 0) {
222
+ let [t, r] = n[0], i = a(r);
236
223
  return {
237
224
  ...e,
238
- [n]: i
225
+ [t]: i
239
226
  };
240
227
  }
241
228
  }
242
229
  return e;
243
230
  }, [
244
- R,
245
- L,
246
- u.id,
231
+ I,
232
+ F,
233
+ k,
234
+ l.type
235
+ ]), G = f(() => he({
236
+ explicit: h,
237
+ fetched: N,
238
+ persisted: l.data,
239
+ config: l.config,
240
+ allowSamples: j,
241
+ mockSource: M
242
+ }), [
243
+ h,
244
+ N,
245
+ l,
246
+ j,
247
247
  M
248
- ]), K = p(() => {
249
- let e = null;
250
- if (_ && G(_)) e = _;
251
- else if (F) {
252
- let t = F;
253
- if (t?.processed && G(t.processed)) e = t.processed;
254
- else if (t?.raw) try {
255
- let n = typeof t.raw == "string" ? JSON.parse(t.raw) : t.raw;
256
- G(n) && (e = n);
257
- } catch {}
258
- } else {
259
- let t = u.data;
260
- if (t?.processed && G(t.processed)) e = t.processed;
261
- else if (t?.raw) try {
262
- let n = typeof t.raw == "string" ? JSON.parse(t.raw) : t.raw;
263
- G(n) && (e = n);
264
- } catch {}
265
- }
266
- if (!e) {
267
- let t = u.config?.mockData;
268
- if (t) try {
269
- let n = typeof t == "string" ? JSON.parse(t) : t;
270
- G(n) && (e = n);
271
- } catch {}
272
- }
248
+ ]), K = f(() => {
249
+ let e = G.data;
273
250
  if (e && typeof e == "object" && !Array.isArray(e)) {
274
- let t = u.config, n = t?.dataKey ?? t?.dataPath ?? t?.seriesPath;
251
+ let t = l.config, n = t?.dataKey ?? t?.dataPath ?? t?.seriesPath;
275
252
  if (n && typeof n == "string") {
276
253
  let t = n.split(".").reduce((e, t) => e && typeof e == "object" ? e[t] : void 0, e);
277
- t != null && G(t) && (e = t);
254
+ t != null && me(t) && (e = t);
278
255
  }
279
256
  }
280
- return R && e ? rt(e) : e;
257
+ return I && e ? W(e) : e;
281
258
  }, [
282
- _,
283
- u,
284
- F,
285
- R,
286
- rt,
287
- L,
288
- G
289
- ]), q = p(() => K ?? null, [K]), it = p(() => !q || P ? !1 : u.config?.mockData != null, [
290
- q,
291
- P,
292
- u.config
293
- ]), { executeDrilldown: at, canDrilldown: ot } = ie({ onDrilldown: (e, t) => {
294
- Ue?.(e);
295
- } }), J = p(() => ot(u), [u, ot]), st = f((e) => {
296
- if (!u.drilldown?.enabled) return;
259
+ G,
260
+ l.config,
261
+ I,
262
+ W
263
+ ]), ct = K !== null && G.isSample, q = f(() => _e(K, l.type), [K, l.type]), { exportCSV: lt, exportPNG: ut } = re(l, {
264
+ data: q,
265
+ containerRef: B
266
+ }), { executeDrilldown: J, canDrilldown: dt } = ie({ onDrilldown: (e, t) => {
267
+ Ye?.(e);
268
+ } }), Y = f(() => dt(l), [l, dt]), ft = d((e) => {
269
+ if (!l.drilldown?.enabled) return;
297
270
  let t = {
298
271
  selectedData: e || {},
299
- globalFilters: k || {},
300
- widgetData: q || {},
272
+ globalFilters: E || {},
273
+ widgetData: K || {},
301
274
  metadata: {
302
- widgetId: u.id,
303
- widgetType: u.type,
304
- widgetTitle: u.title
275
+ widgetId: l.id,
276
+ widgetType: l.type,
277
+ widgetTitle: l.title
305
278
  },
306
- sourceDashboardId: u.dashboardId
279
+ sourceDashboardId: l.dashboardId
307
280
  };
308
- at(u.drilldown, t);
281
+ J(l.drilldown, t);
309
282
  }, [
310
- u,
311
- q,
312
- k,
313
- at
314
- ]), Y = J && !T ? st : void 0, X = m(null), ct = f((e) => {
315
- X.current = {
283
+ l,
284
+ K,
285
+ E,
286
+ J
287
+ ]), X = Y && !C ? ft : void 0, Z = p(null), pt = d((e) => {
288
+ Z.current = {
316
289
  x: e.clientX,
317
290
  y: e.clientY
318
291
  };
319
- }, []), lt = f((e) => {
320
- if (e.stopPropagation(), X.current) {
321
- let t = Math.abs(e.clientX - X.current.x), n = Math.abs(e.clientY - X.current.y);
292
+ }, []), mt = d((e) => {
293
+ if (e.stopPropagation(), Z.current) {
294
+ let t = Math.abs(e.clientX - Z.current.x), n = Math.abs(e.clientY - Z.current.y);
322
295
  if (t > 5 || n > 5) {
323
- X.current = null;
296
+ Z.current = null;
324
297
  return;
325
298
  }
326
299
  }
327
- X.current = null, T && E(u.id);
300
+ Z.current = null, C && w(l.id);
328
301
  }, [
329
- T,
330
- E,
331
- u.id
332
- ]), ut = f((e) => {
333
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), T && E(u.id));
302
+ C,
303
+ w,
304
+ l.id
305
+ ]), ht = d((e) => {
306
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), C && w(l.id));
334
307
  }, [
335
- T,
336
- E,
337
- u.id
338
- ]), dt = p(() => u.type === "custom" && fe(u.config), [u.type, u.config]), ft = p(() => u.type === "custom" && de(u.config), [u.type, u.config]), Z = J && !ft, pt = p(() => u.type === "text" ? ae(u.config, q).hasContent : !1, [
339
- u.type,
340
- u.config,
341
- q
342
- ]), mt = !z && !B && !q && !dt && !pt, Q = p(() => u.renderer, [u]), ht = p(() => Q && Q !== "BIGCONSOLE", [Q]), gt = p(() => ({
343
- widgetId: u.id,
344
- data: q || {}
345
- }), [u.id, q]), $ = f((e, t) => {
346
- if (!x) return;
347
- let n = b?.find((t) => t.name === e.name);
348
- x(n || e, t);
349
- }, [x, b]), _t = f(() => {
350
- let e = {
351
- widget: u,
352
- data: (() => {
353
- if (!q) return q;
354
- if (u.type === "table" || u.type === "pivot_table") {
355
- if (Array.isArray(q)) return q;
356
- if (q && typeof q == "object" && "rows" in q) return q.rows;
357
- }
358
- if (u.type === "list") {
359
- if (Array.isArray(q)) return q;
360
- if (q && typeof q == "object" && "items" in q) return q.items;
361
- }
362
- if (u.type === "funnel_chart") {
363
- if (Array.isArray(q)) return q;
364
- if (q && typeof q == "object" && "stages" in q) return q.stages;
365
- }
366
- if (u.type === "chart") {
367
- if (Array.isArray(q)) return q;
368
- if (q && typeof q == "object" && "datasets" in q) {
369
- let e = q;
370
- if (e.labels && e.datasets) return e.labels.map((t, n) => {
371
- let r = { name: t };
372
- return e.datasets?.forEach((e) => {
373
- r[e.name.toLowerCase()] = e.data[n];
374
- }), r;
375
- });
376
- }
308
+ C,
309
+ w,
310
+ l.id
311
+ ]), gt = f(() => l.type === "custom" && fe(l.config), [l.type, l.config]), _t = f(() => l.type === "custom" && de(l.config), [l.type, l.config]), Q = Y && !_t, vt = f(() => l.type === "text" ? c(l.config, K).hasContent : !1, [
312
+ l.type,
313
+ l.config,
314
+ K
315
+ ]), yt = !L && !R && !K && !gt && !vt, $ = f(() => l.renderer, [l]), bt = f(() => $ && $ !== "BIGCONSOLE", [$]), xt = f(() => ({
316
+ widgetId: l.id,
317
+ data: K || {}
318
+ }), [l.id, K]), St = d((e, t) => {
319
+ if (!y) return;
320
+ let n = v?.find((t) => t.name === e.name);
321
+ y(n || e, t);
322
+ }, [y, v]), Ct = d(() => {
323
+ let e = (() => {
324
+ if (!K) return K;
325
+ if (l.type === "pivot_table") {
326
+ if (Array.isArray(K)) return K;
327
+ if (K && typeof K == "object" && "rows" in K) return K.rows;
328
+ }
329
+ if (l.type === "list") {
330
+ if (Array.isArray(K)) return K;
331
+ if (K && typeof K == "object" && "items" in K) return K.items;
332
+ }
333
+ if (l.type === "funnel_chart") {
334
+ if (Array.isArray(K)) return K;
335
+ if (K && typeof K == "object" && "stages" in K) return K.stages;
336
+ }
337
+ if (l.type === "chart") {
338
+ if (Array.isArray(K)) return K;
339
+ if (K && typeof K == "object" && "datasets" in K) {
340
+ let e = K;
341
+ if (e.labels && e.datasets) return e.labels.map((t, n) => {
342
+ let r = { name: t };
343
+ return e.datasets?.forEach((e) => {
344
+ r[e.name.toLowerCase()] = e.data[n];
345
+ }), r;
346
+ });
377
347
  }
378
- if (u.type === "text") {
379
- let e = ae(u.config, q);
380
- return {
381
- content: e.content,
382
- format: e.format,
383
- alignment: e.alignment
348
+ }
349
+ if (l.type === "text") {
350
+ let e = c(l.config, K);
351
+ return {
352
+ content: e.content,
353
+ format: e.format,
354
+ alignment: e.alignment
355
+ };
356
+ }
357
+ if (l.type === "custom") {
358
+ let e = l.config?.valueField;
359
+ if (e && K && typeof K == "object" && !Array.isArray(K)) {
360
+ let t = K;
361
+ if (e in t) return {
362
+ value: t[e],
363
+ label: l.title,
364
+ data: t
384
365
  };
385
366
  }
386
- if (u.type === "custom") {
387
- let e = u.config?.valueField;
388
- if (e && q && typeof q == "object" && !Array.isArray(q)) {
389
- let t = q;
390
- if (e in t) return {
391
- value: t[e],
392
- label: u.title,
393
- data: t
394
- };
395
- }
396
- }
397
- return q;
398
- })(),
399
- onDrilldown: Y
367
+ }
368
+ return K;
369
+ })(), t = {
370
+ widget: l,
371
+ onDrilldown: X
400
372
  };
401
- if (ht) {
373
+ if (bt) {
402
374
  let e = {};
403
- if (K && typeof K == "object" && !Array.isArray(K) && Object.keys(K).length > 0 && (e = { ...K }), u.config?._internalWidgetType === "custom" && Object.keys(e).length > 0) {
404
- let t = u.config?.valueField;
375
+ if (K && typeof K == "object" && !Array.isArray(K) && Object.keys(K).length > 0 && (e = { ...K }), l.config?._internalWidgetType === "custom" && Object.keys(e).length > 0) {
376
+ let t = l.config?.valueField;
405
377
  if (t && t in e) {
406
378
  let n = e[t], r = typeof n == "number" ? n.toLocaleString() : String(n);
407
379
  e = {
408
380
  ...e,
409
381
  value: n,
410
382
  title: e.title || r,
411
- description: e.description || u.title || "",
383
+ description: e.description || l.title || "",
412
384
  text: e.text || r
413
385
  };
414
386
  }
415
387
  }
416
- return /* @__PURE__ */ g(me, {
417
- widget: u,
388
+ return /* @__PURE__ */ m(ve, {
389
+ widget: l,
418
390
  data: e,
419
- isEditMode: T,
420
- isSelected: D,
421
- isLoading: z,
422
- error: B,
423
- onDrilldown: Y,
424
- onAction: $
391
+ isEditMode: C,
392
+ isSelected: T,
393
+ isLoading: L,
394
+ error: R,
395
+ onDrilldown: X,
396
+ onAction: St
425
397
  });
426
398
  }
427
- switch (u.type?.toLowerCase() || "") {
428
- case "metric_card": return /* @__PURE__ */ g(ye, { ...e });
429
- case "kpi_card_comparison": return /* @__PURE__ */ g(je, { ...e });
399
+ switch (l.type?.toLowerCase() || "") {
400
+ case "metric_card": return /* @__PURE__ */ m(Te, {
401
+ ...t,
402
+ data: e
403
+ });
404
+ case "kpi_card_comparison": return /* @__PURE__ */ m(Le, {
405
+ ...t,
406
+ data: e
407
+ });
430
408
  case "chart":
431
- case "funnel_chart": return /* @__PURE__ */ g(be, { ...e });
432
- case "waterfall": return /* @__PURE__ */ g(ze, { ...e });
433
- case "sankey": return /* @__PURE__ */ g(Le, { ...e });
434
- case "box_plot": return /* @__PURE__ */ g(Re, { ...e });
435
- case "table": return /* @__PURE__ */ g(xe, { ...e });
436
- case "pivot_table": return /* @__PURE__ */ g(Se, { ...e });
437
- case "gauge": return /* @__PURE__ */ g(Ce, { ...e });
438
- case "progress": return /* @__PURE__ */ g(we, { ...e });
439
- case "list": return /* @__PURE__ */ g(Te, { ...e });
440
- case "heatmap": return /* @__PURE__ */ g(Ee, { ...e });
441
- case "retention": return /* @__PURE__ */ g(De, { ...e });
442
- case "calendar": return /* @__PURE__ */ g(Oe, { ...e });
443
- case "timeline": return /* @__PURE__ */ g(Ae, { ...e });
444
- case "kanban": return /* @__PURE__ */ g(ke, { ...e });
445
- case "form": return /* @__PURE__ */ g(Ie, { ...e });
446
- case "text": return /* @__PURE__ */ g(Me, { ...e });
447
- case "iframe": return /* @__PURE__ */ g(Pe, { ...e });
448
- case "map": return /* @__PURE__ */ g(Ne, { ...e });
449
- case "custom": return /* @__PURE__ */ g(Fe, { ...e });
450
- default: return d || /* @__PURE__ */ g(c, { widgetType: u.type });
409
+ case "funnel_chart": return /* @__PURE__ */ m(Ee, {
410
+ ...t,
411
+ data: e
412
+ });
413
+ case "waterfall": return /* @__PURE__ */ m(Ge, {
414
+ ...t,
415
+ data: e
416
+ });
417
+ case "sankey": return /* @__PURE__ */ m(Ue, {
418
+ ...t,
419
+ data: e
420
+ });
421
+ case "box_plot": return /* @__PURE__ */ m(We, {
422
+ ...t,
423
+ data: e
424
+ });
425
+ case "table": return /* @__PURE__ */ m(De, {
426
+ ...t,
427
+ data: e
428
+ });
429
+ case "pivot_table": return /* @__PURE__ */ m(Oe, {
430
+ ...t,
431
+ data: e
432
+ });
433
+ case "gauge": return /* @__PURE__ */ m(ke, {
434
+ ...t,
435
+ data: e
436
+ });
437
+ case "progress": return /* @__PURE__ */ m(Ae, {
438
+ ...t,
439
+ data: e
440
+ });
441
+ case "list": return /* @__PURE__ */ m(je, {
442
+ ...t,
443
+ data: e
444
+ });
445
+ case "heatmap": return /* @__PURE__ */ m(Me, {
446
+ ...t,
447
+ data: e
448
+ });
449
+ case "retention": return /* @__PURE__ */ m(Ne, {
450
+ ...t,
451
+ data: e
452
+ });
453
+ case "calendar": return /* @__PURE__ */ m(Pe, {
454
+ ...t,
455
+ data: e
456
+ });
457
+ case "timeline": return /* @__PURE__ */ m(Ie, {
458
+ ...t,
459
+ data: e
460
+ });
461
+ case "kanban": return /* @__PURE__ */ m(Fe, {
462
+ ...t,
463
+ data: e
464
+ });
465
+ case "form": return /* @__PURE__ */ m(He, {
466
+ ...t,
467
+ data: e
468
+ });
469
+ case "text": return /* @__PURE__ */ m(Re, {
470
+ ...t,
471
+ data: e
472
+ });
473
+ case "iframe": return /* @__PURE__ */ m(Be, {
474
+ ...t,
475
+ data: e
476
+ });
477
+ case "map": return /* @__PURE__ */ m(ze, {
478
+ ...t,
479
+ data: e
480
+ });
481
+ case "custom": return /* @__PURE__ */ m(Ve, {
482
+ ...t,
483
+ data: e
484
+ });
485
+ default: return u || /* @__PURE__ */ m(le, { widgetType: l.type });
451
486
  }
452
487
  }, [
488
+ l,
489
+ K,
453
490
  u,
454
- q,
455
- d,
456
- Y,
457
- ht,
491
+ X,
492
+ bt,
493
+ C,
458
494
  T,
459
- D,
460
- z,
461
- B,
462
- $,
463
- K
495
+ L,
496
+ R,
497
+ St
464
498
  ]);
465
- return /* @__PURE__ */ ve("div", {
466
- ref: H,
499
+ return /* @__PURE__ */ we("div", {
500
+ ref: B,
467
501
  className: `
468
502
  group relative flex flex-col
469
503
  h-full w-full min-w-0
470
504
  rounded-card border
471
505
  bg-bg-surface
472
506
  shadow-[var(--shadow-elevation-1)]
473
- ${w.animationsEnabled ? "motion-safe:transition-[box-shadow,border-color] motion-safe:duration-200" : ""}
474
- ${D && T ? "border-[var(--color-action-primary-border)] ring-2 ring-[var(--color-action-primary-border)]/30 shadow-[var(--shadow-elevation-2)]" : w.showWidgetBorders ? "border-[var(--color-border-subtle)] hover:border-action-primary-bg hover:shadow-[var(--shadow-elevation-2)]" : "border-transparent"}
475
- ${T ? "cursor-pointer" : ""}
476
- ${v}
507
+ ${S.animationsEnabled ? "motion-safe:transition-[box-shadow,border-color] motion-safe:duration-200" : ""}
508
+ ${T && C ? "border-[var(--color-action-primary-border)] ring-2 ring-[var(--color-action-primary-border)]/30 shadow-[var(--shadow-elevation-2)]" : S.showWidgetBorders ? "border-[var(--color-border-subtle)] hover:border-action-primary-bg hover:shadow-[var(--shadow-elevation-2)]" : "border-transparent"}
509
+ ${C ? "cursor-pointer" : ""}
510
+ ${g}
477
511
  `,
478
- onMouseDown: ct,
479
- onClick: lt,
480
- onKeyDown: ut,
481
- tabIndex: T ? 0 : -1,
482
- role: T ? "button" : void 0,
483
- "aria-selected": D,
484
- "aria-label": `Widget: ${u.title}`,
485
- "data-widget-id": u.id,
486
- "data-widget-type": u.type,
512
+ onMouseDown: pt,
513
+ onClick: mt,
514
+ onKeyDown: ht,
515
+ tabIndex: C ? 0 : -1,
516
+ role: C ? "button" : void 0,
517
+ "aria-selected": T,
518
+ "aria-label": `Widget: ${l.title}`,
519
+ "data-widget-id": l.id,
520
+ "data-widget-type": l.type,
487
521
  children: [
488
- /* @__PURE__ */ g(oe, {
489
- widget: u,
490
- previewOnly: C,
491
- definition: Ke,
492
- isSelected: D,
493
- isEditMode: T,
494
- isLoading: z,
495
- isSampleData: it,
496
- timeUntilRefresh: u.refreshInterval && !Ye ? ee(Je) : void 0,
497
- hasDrilldown: J,
498
- onRefresh: y,
499
- onExportCSV: et ? tt : void 0,
500
- onExportPNG: nt,
501
- onDrilldown: Y ? () => Y() : void 0,
502
- onToggleComments: C ? void 0 : $e,
503
- commentsOpen: U,
504
- commentCount: Xe ? Qe : void 0
522
+ /* @__PURE__ */ m(ae, {
523
+ widget: l,
524
+ previewOnly: x,
525
+ definition: tt,
526
+ isSelected: T,
527
+ isEditMode: C,
528
+ isLoading: L,
529
+ isSampleData: ct,
530
+ timeUntilRefresh: l.refreshInterval && !it ? ee(rt) : void 0,
531
+ hasDrilldown: Y,
532
+ onRefresh: _,
533
+ onExportCSV: q ? lt : void 0,
534
+ onExportPNG: ut,
535
+ onDrilldown: X ? () => X() : void 0,
536
+ onToggleComments: x ? void 0 : st,
537
+ commentsOpen: V,
538
+ commentCount: U ? ot : void 0
505
539
  }),
506
- /* @__PURE__ */ g("div", {
540
+ /* @__PURE__ */ m("div", {
507
541
  className: `
508
542
  flex-1 overflow-hidden min-h-0 min-w-0
509
- ${w.compactMode ? "p-2" : "p-3 sm:p-4"}
510
- ${Z && !T ? "cursor-pointer" : ""}
543
+ ${S.compactMode ? "p-2" : "p-3 sm:p-4"}
544
+ ${Q && !C ? "cursor-pointer" : ""}
511
545
  `,
512
- title: Z && !T ? "Click data to drill down" : void 0,
513
- children: /* @__PURE__ */ g("div", {
546
+ title: Q && !C ? "Click data to drill down" : void 0,
547
+ children: /* @__PURE__ */ m("div", {
514
548
  className: "h-full min-w-0 overflow-auto",
515
549
  children: (() => {
516
- if (z) return /* @__PURE__ */ g(ce, {});
517
- if (B) return /* @__PURE__ */ g(le, {
518
- error: B,
519
- onRetry: y
550
+ if (L) return /* @__PURE__ */ m(se, {});
551
+ if (R) return /* @__PURE__ */ m(ce, {
552
+ error: R,
553
+ onRetry: _
520
554
  });
521
- if (mt && !d) return /* @__PURE__ */ g(c, {
522
- widgetType: u.type,
523
- hideEditHint: C,
524
- hasDataSource: P,
525
- templateSlot: typeof u.metadata?.templateDataSinkSlot == "string" ? u.metadata.templateDataSinkSlot : null
555
+ if (yt && !u) return /* @__PURE__ */ m(le, {
556
+ widgetType: l.type,
557
+ hideEditHint: x,
558
+ hasDataSource: Qe,
559
+ templateSlot: typeof l.metadata?.templateDataSinkSlot == "string" ? l.metadata.templateDataSinkSlot : null
526
560
  });
527
- let e = `${N.source.kind}|${N.source.ref ?? ""}|${N.parserId ?? ""}|${u.updatedAt ?? ""}`;
528
- return /* @__PURE__ */ g(ue, {
529
- widgetId: u.id,
530
- widgetType: u.type,
531
- widgetTitle: u.title,
561
+ let e = `${A.source.kind}|${A.source.ref ?? ""}|${A.parserId ?? ""}|${l.updatedAt ?? ""}`;
562
+ return /* @__PURE__ */ m(ue, {
563
+ widgetId: l.id,
564
+ widgetType: l.type,
565
+ widgetTitle: l.title,
532
566
  resetKey: e,
533
- children: d ?? /* @__PURE__ */ g(l, {
534
- fallback: /* @__PURE__ */ g(ce, {}),
535
- children: _t()
567
+ children: u ?? /* @__PURE__ */ m(be, {
568
+ fallback: /* @__PURE__ */ m(se, {}),
569
+ children: Ct()
536
570
  })
537
571
  });
538
572
  })()
539
573
  })
540
574
  }),
541
- b && b.length > 0 && !z && !B && /* @__PURE__ */ g("div", {
575
+ v && v.length > 0 && !L && !R && /* @__PURE__ */ m("div", {
542
576
  className: "min-w-0 border-t border-[var(--color-border-subtle)] bg-bg-sunken px-3 py-2 sm:px-4",
543
577
  style: { flexShrink: 0 },
544
- children: /* @__PURE__ */ g(he, {
545
- actions: b,
546
- context: gt,
547
- onAction: x,
548
- disabled: T,
578
+ children: /* @__PURE__ */ m(ye, {
579
+ actions: v,
580
+ context: xt,
581
+ onAction: y,
582
+ disabled: C,
549
583
  layout: "horizontal",
550
584
  size: "sm"
551
585
  })
552
586
  }),
553
- Z && !T && /* @__PURE__ */ g("div", {
587
+ Q && !C && /* @__PURE__ */ m("div", {
554
588
  className: "\n absolute bottom-2 right-2\n opacity-0 group-hover:opacity-100\n transition-opacity duration-200\n ",
555
589
  title: "Click to drill down",
556
- children: /* @__PURE__ */ g("svg", {
590
+ children: /* @__PURE__ */ m("svg", {
557
591
  className: "w-4 h-4 text-text-secondary",
558
592
  fill: "none",
559
593
  stroke: "currentColor",
560
594
  viewBox: "0 0 24 24",
561
- children: /* @__PURE__ */ g("path", {
595
+ children: /* @__PURE__ */ m("path", {
562
596
  strokeLinecap: "round",
563
597
  strokeLinejoin: "round",
564
598
  strokeWidth: 2,
@@ -566,15 +600,15 @@ var v = d(function({ widget: u, children: d, data: _, className: v = "", isLoadi
566
600
  })
567
601
  })
568
602
  }),
569
- U && /* @__PURE__ */ g(l, {
603
+ V && /* @__PURE__ */ m(be, {
570
604
  fallback: null,
571
- children: /* @__PURE__ */ g(Be, {
572
- widgetId: u.id,
573
- onClose: () => W(!1)
605
+ children: /* @__PURE__ */ m(Ke, {
606
+ widgetId: l.id,
607
+ onClose: () => H(!1)
574
608
  })
575
609
  })
576
610
  ]
577
611
  });
578
- }, _);
612
+ }, h);
579
613
  //#endregion
580
- export { v as default };
614
+ export { g as default };
@@ -0,0 +1,30 @@
1
+ import { WidgetBinding } from '../types';
2
+
3
+ /** Resolve explicit and connected data before intentional embedded samples. */
4
+ export interface WidgetDisplayData {
5
+ data: unknown;
6
+ isSample: boolean;
7
+ }
8
+ export declare function isUsableWidgetData(value: unknown): boolean;
9
+ export declare function resolveWidgetDisplayData(input: {
10
+ explicit?: unknown;
11
+ fetched?: unknown;
12
+ persisted?: unknown;
13
+ config?: Record<string, unknown>;
14
+ allowSamples: boolean;
15
+ mockSource?: boolean;
16
+ }): WidgetDisplayData;
17
+ /** Export the same resolved and filtered rows the renderer receives. */
18
+ export declare function widgetExportRows(value: unknown, widgetType?: string): Record<string, unknown>[] | null;
19
+ /** Legacy concrete sources remain authoritative when a stale canonical binding says MOCK. */
20
+ export declare function widgetDataSourcePolicy(widget: {
21
+ dataSinkId?: string | null;
22
+ parserId?: string | null;
23
+ datasetId?: string | null;
24
+ dataSourceId?: string | null;
25
+ config?: Record<string, unknown>;
26
+ }, binding: WidgetBinding): {
27
+ hasDataSource: boolean;
28
+ allowSamples: boolean;
29
+ mockSource: boolean;
30
+ };
@@ -0,0 +1,80 @@
1
+ //#region src/bigconsole/utils/widgetDisplayData.ts
2
+ function e(e) {
3
+ return typeof e == "object" && !!e && !Array.isArray(e);
4
+ }
5
+ function t(n) {
6
+ return n == null || n === "" ? !1 : Array.isArray(n) ? n.length > 0 : e(n) ? Object.values(n).some(t) : !0;
7
+ }
8
+ function n(e) {
9
+ if (typeof e != "string") return e;
10
+ try {
11
+ return JSON.parse(e);
12
+ } catch {
13
+ return null;
14
+ }
15
+ }
16
+ function r(r) {
17
+ if (!e(r)) return null;
18
+ let i = n(r.processed);
19
+ if (t(i)) return i;
20
+ let a = n(r.raw);
21
+ return t(a) ? a : null;
22
+ }
23
+ function i(i) {
24
+ if (i.explicit !== void 0 && i.explicit !== null) return {
25
+ data: i.explicit,
26
+ isSample: !1
27
+ };
28
+ for (let e of [i.fetched, i.persisted]) {
29
+ let t = r(e);
30
+ if (t !== null) return {
31
+ data: t,
32
+ isSample: i.mockSource === !0
33
+ };
34
+ }
35
+ if (i.allowSamples) {
36
+ let r = n(i.config?.mockData);
37
+ if (t(r)) return {
38
+ data: r,
39
+ isSample: !0
40
+ };
41
+ let a = n(i.config?.data);
42
+ if ((Array.isArray(a) && a.every(e) || e(a)) && t(a)) return {
43
+ data: a,
44
+ isSample: !0
45
+ };
46
+ }
47
+ return {
48
+ data: null,
49
+ isSample: !1
50
+ };
51
+ }
52
+ function a(t, n = "table") {
53
+ let r = t;
54
+ if (e(t)) {
55
+ let e = [
56
+ ...n === "pivot_table" ? ["rows"] : n === "list" ? ["items"] : n === "funnel_chart" ? ["stages"] : [],
57
+ "data",
58
+ "items",
59
+ "rows",
60
+ "results",
61
+ "records",
62
+ "list",
63
+ "sales",
64
+ "entries",
65
+ "values"
66
+ ].find((e) => Array.isArray(t[e]));
67
+ r = e ? t[e] : Object.values(t).find(Array.isArray);
68
+ }
69
+ return !Array.isArray(r) || r.length === 0 || !r.every(e) ? null : r;
70
+ }
71
+ function o(e, t) {
72
+ let n = e.config?.dataSourceType === "DATASINK" && typeof e.config.dataSinkKey == "string" && e.config.dataSinkKey.length > 0, r = !!(e.dataSinkId || e.parserId || e.datasetId || e.dataSourceId || t.parserId || n), i = t.source.kind !== "DATASINK" || !!t.source.ref, a = t.source.kind === "MOCK" && !r, o = i || r;
73
+ return {
74
+ hasDataSource: o,
75
+ allowSamples: !o || a,
76
+ mockSource: a
77
+ };
78
+ }
79
+ //#endregion
80
+ export { t as isUsableWidgetData, i as resolveWidgetDisplayData, o as widgetDataSourcePolicy, a as widgetExportRows };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-bigconsole",
3
- "version": "2026.1013.3",
3
+ "version": "2026.1013.4",
4
4
  "description": "BigConsole - AI-powered analytics and dashboard platform",
5
5
  "type": "module",
6
6
  "files": [