@burdenoff/microfe-bigconsole 2026.1012.8 → 2026.1012.9

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.
@@ -87,7 +87,7 @@ var _ = i()((r, i) => ({
87
87
  }),
88
88
  applyProgress: (e) => r((t) => {
89
89
  let n = { ...t.steps }, r = { ...t.entityIds }, i = (e, t) => {
90
- n[e] = m(n[e], "done"), t && e !== "widget" && (r[e] = t);
90
+ n[e] = m(n[e], "done"), t && e !== "widget" && (e === "dashboard" && r.dashboard !== t && (delete r.widget, n.widget = "pending"), r[e] = t);
91
91
  };
92
92
  for (let t of e.matchAll(c)) {
93
93
  let e = d[t[1] ?? ""];
@@ -110,11 +110,11 @@ var _ = i()((r, i) => ({
110
110
  if (r.completedResultIds.includes(t)) return r;
111
111
  let a = e(n);
112
112
  if (a.length === 0) return r;
113
- let o = { ...r.steps }, s = { ...r.entityIds }, c = { ...r.entityResultOrder }, l = !1, u = (e, t) => {
114
- let n = c[e];
115
- i !== void 0 && n !== void 0 && i < n || (i !== void 0 && (c[e] = i), o[e] = "done", s[e] = t, l = !0);
113
+ let o = { ...r.steps }, s = { ...r.entityIds }, c = { ...r.entityResultOrder }, l = !1, u = (e, t, n = !1) => {
114
+ let r = c[e];
115
+ i !== void 0 && r !== void 0 && i < r || (e === "dashboard" && !n && s.dashboard !== t && (delete s.widget, delete c.widget, o.widget = "pending"), i !== void 0 && (c[e] = i), o[e] = "done", s[e] = t, l = !0);
116
116
  };
117
- for (let e of a) u(e.step, e.id), e.dashboardId && u("dashboard", e.dashboardId), e.parserId && u("parser", e.parserId);
117
+ for (let e of a) u(e.step, e.id), e.dashboardId && u("dashboard", e.dashboardId, e.step === "widget"), e.parserId && u("parser", e.parserId);
118
118
  let d = [...r.completedResultIds, t];
119
119
  return l ? {
120
120
  steps: o,
@@ -5,6 +5,9 @@ export interface DrilldownDashboardRendererProps {
5
5
  dashboardId: string;
6
6
  live?: boolean;
7
7
  refreshRevision?: number;
8
+ /** AI preview read-after-write expectation; ordinary drilldowns leave this unset. */
9
+ expectedWidgetId?: string;
10
+ requestWorkspaceId?: string;
8
11
  /** Parameters passed from drilldown (can be used for filtering) */
9
12
  params: Record<string, unknown>;
10
13
  }
@@ -1,21 +1,24 @@
1
1
  import { GetDashboardDocument as e, ListWidgetsByDashboardDocument as t } from "../../generated/wspace-operations.js";
2
- import { Section as n, SectionStack as r } from "./common/Section.js";
2
+ import { loadConfirmedPreviewWidgets as n } from "./preview/confirmedPreviewWidgets.js";
3
+ import { Section as r, SectionStack as i } from "./common/Section.js";
3
4
  import "./common/index.js";
4
- import { mapFromFederationWidgetType as i } from "../utils/widgetTypeMapping.js";
5
- import { MODAL_TARGET_PAGE_PARAM as a } from "../hooks/useDrilldown.js";
6
- import o from "./widgets/WidgetWrapper.js";
7
- import { getVisibleDrilldownParams as s } from "../utils/drilldownParams.js";
8
- import { memo as c, useEffect as l, useState as u } from "react";
9
- import { useApolloClient as d } from "@apollo/client/react";
10
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
5
+ import { mapFromFederationWidgetType as a } from "../utils/widgetTypeMapping.js";
6
+ import { MODAL_TARGET_PAGE_PARAM as o } from "../hooks/useDrilldown.js";
7
+ import s from "./widgets/WidgetWrapper.js";
8
+ import { getVisibleDrilldownParams as c } from "../utils/drilldownParams.js";
9
+ import { memo as l, useEffect as u, useState as d } from "react";
10
+ import { Button as f } from "@burdenoff/fe-libs/ui";
11
+ import { useI18n as p } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
12
+ import { useApolloClient as m } from "@apollo/client/react";
13
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
11
14
  //#region src/bigconsole/components/DrilldownDashboardRenderer.tsx
12
- function m(e, t) {
15
+ function _(e, t) {
13
16
  let n = t * 4, r = {
14
17
  x: 0,
15
18
  y: n,
16
19
  width: 12,
17
20
  height: 4
18
- }, a = e.config || {}, o = a._internalWidgetType || i(e.type || "KPI");
21
+ }, i = e.config || {}, o = i._internalWidgetType || a(e.type || "KPI");
19
22
  return {
20
23
  id: e.id ?? "",
21
24
  pageId: e.pageId || "",
@@ -28,7 +31,7 @@ function m(e, t) {
28
31
  datasetId: e.datasetId || null,
29
32
  parserId: e.parserId || null,
30
33
  parserRules: e.parserRules || null,
31
- config: a,
34
+ config: i,
32
35
  position: r,
33
36
  positionX: 0,
34
37
  positionY: n,
@@ -49,7 +52,7 @@ function m(e, t) {
49
52
  updatedAt: e.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
50
53
  };
51
54
  }
52
- function h(e, t) {
55
+ function v(e, t) {
53
56
  let n = {
54
57
  x: 0,
55
58
  y: t * 4,
@@ -65,163 +68,178 @@ function h(e, t) {
65
68
  positionHeight: 4
66
69
  };
67
70
  }
68
- var g = c(function({ dashboardId: i, params: o, live: c = !1, refreshRevision: g = 0 }) {
69
- let v = d(), [y, b] = u(!0), [x, S] = u(null), [C, w] = u(null), [T, E] = u([]);
70
- if (l(() => {
71
- if (!i) {
72
- b(!1);
71
+ var y = l(function({ dashboardId: a, params: s, live: l = !1, refreshRevision: y = 0, expectedWidgetId: x, requestWorkspaceId: S }) {
72
+ let C = m(), { t: w } = p(), [T, E] = d(0), [D, O] = d(!0), [k, A] = d(null), [j, M] = d(null), [N, P] = d([]);
73
+ if (u(() => {
74
+ if (!a) {
75
+ O(!1);
73
76
  return;
74
77
  }
75
- let n = !1, r = !1;
76
- b(!0);
77
- async function a() {
78
- if (!r) {
79
- r = !0, S(null);
78
+ let r = !1, i = new AbortController(), o = S ? {
79
+ requiredWorkspaceAuth: !0,
80
+ requiredWorkspaceId: S,
81
+ queryDeduplication: !1,
82
+ fetchOptions: { signal: i.signal }
83
+ } : void 0, s = !1, c = !1;
84
+ O(!0);
85
+ async function u() {
86
+ if (!(s || c)) {
87
+ s = !0, A(null);
80
88
  try {
81
- let r = await v.query({
89
+ let s = await C.query({
82
90
  query: e,
83
- variables: { id: i },
84
- fetchPolicy: "network-only"
91
+ variables: { id: a },
92
+ fetchPolicy: S ? "no-cache" : "network-only",
93
+ ...o ? { context: o } : {}
85
94
  });
86
- if (n) return;
87
- let a = r.data?.getDashboard;
88
- if (!a) {
89
- S("Dashboard not found"), b(!1);
95
+ if (r) return;
96
+ let c = s.data?.getDashboard;
97
+ if (!c) {
98
+ A("Dashboard not found"), O(!1);
90
99
  return;
91
100
  }
92
- let o = a.pages?.edges?.map((e) => ({
101
+ let l = c.pages?.edges?.map((e) => ({
93
102
  id: e.node.id,
94
103
  name: e.node.name || "Page 1"
95
104
  })) || [];
96
- w({
97
- id: a.id,
98
- name: a.name,
99
- description: a.description,
100
- pages: o
105
+ M({
106
+ id: c.id,
107
+ name: c.name,
108
+ description: c.description,
109
+ pages: l
101
110
  });
102
- let s = await v.query({
111
+ let u = await n(async () => ((await C.query({
103
112
  query: t,
104
- variables: { dashboardId: i },
105
- fetchPolicy: "network-only"
106
- });
107
- if (n) return;
108
- E((s.data?.listWidgetsByDashboard || []).map((e, t) => m(e, t)));
113
+ variables: { dashboardId: a },
114
+ fetchPolicy: S ? "no-cache" : "network-only",
115
+ ...o ? { context: o } : {}
116
+ })).data?.listWidgetsByDashboard || []).map((e, t) => _(e, t)), x, i.signal);
117
+ if (r) return;
118
+ P(u);
109
119
  } catch (e) {
110
- n || S(e instanceof Error ? e.message : "Failed to load dashboard");
120
+ r || A(e instanceof Error ? e.message : "Failed to load dashboard"), x && (c = !0);
111
121
  } finally {
112
- r = !1, n || b(!1);
122
+ s = !1, r || O(!1);
113
123
  }
114
124
  }
115
125
  }
116
- a();
117
- let o = c ? window.setInterval(() => {
118
- document.visibilityState === "visible" && a();
126
+ u();
127
+ let d = l ? window.setInterval(() => {
128
+ document.visibilityState === "visible" && u();
119
129
  }, 4e3) : void 0;
120
130
  return () => {
121
- n = !0, o !== void 0 && window.clearInterval(o);
131
+ r = !0, i.abort(), d !== void 0 && window.clearInterval(d);
122
132
  };
123
133
  }, [
124
- i,
125
- v,
126
- c,
127
- g
128
- ]), y) return /* @__PURE__ */ f("div", {
134
+ a,
135
+ C,
136
+ l,
137
+ y,
138
+ x,
139
+ S,
140
+ T
141
+ ]), D) return /* @__PURE__ */ h("div", {
129
142
  className: "flex items-center justify-center h-full",
130
- children: /* @__PURE__ */ p("div", {
143
+ children: /* @__PURE__ */ g("div", {
131
144
  className: "flex flex-col items-center gap-3",
132
- children: [/* @__PURE__ */ f("div", { className: "w-8 h-8 border-2 border-action-primary-bg border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ f("p", {
145
+ children: [/* @__PURE__ */ h("div", { className: "w-8 h-8 border-2 border-action-primary-bg border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ h("p", {
133
146
  className: "text-sm text-text-secondary",
134
147
  children: "Loading dashboard..."
135
148
  })]
136
149
  })
137
150
  });
138
- if (x) return /* @__PURE__ */ f("div", {
139
- className: "flex h-full items-center justify-center",
151
+ if (k) return /* @__PURE__ */ g("div", {
152
+ className: "flex h-full flex-col items-center justify-center gap-3",
140
153
  role: "alert",
141
- children: /* @__PURE__ */ f(n, {
154
+ children: [/* @__PURE__ */ h(r, {
142
155
  headingLevel: 3,
143
156
  tone: "danger",
144
157
  className: "w-full max-w-md",
145
158
  "data-testid": "drilldown-error",
146
159
  title: "Could not load this dashboard",
147
- description: x,
148
- icon: /* @__PURE__ */ f("svg", {
160
+ description: k,
161
+ icon: /* @__PURE__ */ h("svg", {
149
162
  className: "h-icon-md w-icon-md",
150
163
  fill: "none",
151
164
  stroke: "currentColor",
152
165
  viewBox: "0 0 24 24",
153
- children: /* @__PURE__ */ f("path", {
166
+ children: /* @__PURE__ */ h("path", {
154
167
  strokeLinecap: "round",
155
168
  strokeLinejoin: "round",
156
169
  strokeWidth: 1.5,
157
170
  d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
158
171
  })
159
172
  })
160
- })
173
+ }), x && S ? /* @__PURE__ */ h(f, {
174
+ onClick: () => E((e) => e + 1),
175
+ variant: "outline",
176
+ size: "sm",
177
+ children: w("bigconsole.widget.customWidget.action.retry", "Retry")
178
+ }) : null]
161
179
  });
162
- if (!C || T.length === 0) return /* @__PURE__ */ f("div", {
180
+ if (!j || N.length === 0) return /* @__PURE__ */ h("div", {
163
181
  className: "flex items-center justify-center h-full",
164
- children: /* @__PURE__ */ p("div", {
182
+ children: /* @__PURE__ */ g("div", {
165
183
  className: "flex flex-col items-center gap-3 text-center",
166
- children: [/* @__PURE__ */ f("svg", {
184
+ children: [/* @__PURE__ */ h("svg", {
167
185
  className: "w-12 h-12 text-text-muted",
168
186
  fill: "none",
169
187
  stroke: "currentColor",
170
188
  viewBox: "0 0 24 24",
171
- children: /* @__PURE__ */ f("path", {
189
+ children: /* @__PURE__ */ h("path", {
172
190
  strokeLinecap: "round",
173
191
  strokeLinejoin: "round",
174
192
  strokeWidth: 1.5,
175
193
  d: "M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
176
194
  })
177
- }), /* @__PURE__ */ f("p", {
195
+ }), /* @__PURE__ */ h("p", {
178
196
  className: "text-sm text-text-secondary",
179
- children: C ? "This dashboard has no widgets" : "Dashboard not found"
197
+ children: j ? "This dashboard has no widgets" : "Dashboard not found"
180
198
  })]
181
199
  })
182
200
  });
183
- let D = s(o), O = o[a], k = C.pages.find((e) => e.id === O) ?? C.pages[0] ?? null, A = (k ? T.filter((e) => !e.pageId || e.pageId === k.id) : T).map((e, t) => h(e, t));
184
- return /* @__PURE__ */ p(r, {
201
+ let F = c(s), I = s[o], L = j.pages.find((e) => e.id === I) ?? j.pages[0] ?? null, R = (L ? N.filter((e) => !e.pageId || e.pageId === L.id) : N).map((e, t) => v(e, t));
202
+ return /* @__PURE__ */ g(i, {
185
203
  className: "w-full",
186
204
  children: [
187
- /* @__PURE__ */ f(n, {
205
+ /* @__PURE__ */ h(r, {
188
206
  emphasis: "bare",
189
207
  padding: "none",
190
208
  headingLevel: 3,
191
- title: C.name,
192
- description: C.pages.length > 1 && k ? /* @__PURE__ */ f("span", {
209
+ title: j.name,
210
+ description: j.pages.length > 1 && L ? /* @__PURE__ */ h("span", {
193
211
  "data-testid": "drilldown-dashboard-page",
194
- children: k.name
195
- }) : C.description,
212
+ children: L.name
213
+ }) : j.description,
196
214
  "data-testid": "drilldown-dashboard-header"
197
215
  }),
198
- D.length > 0 && /* @__PURE__ */ f(n, {
216
+ F.length > 0 && /* @__PURE__ */ h(r, {
199
217
  emphasis: "muted",
200
218
  padding: "compact",
201
219
  headingLevel: 3,
202
220
  title: "Filtered by",
203
221
  "data-testid": "drilldown-params",
204
222
  bodyClassName: "flex flex-wrap gap-control-gap",
205
- children: D.map(([e, t]) => /* @__PURE__ */ p("span", {
223
+ children: F.map(([e, t]) => /* @__PURE__ */ g("span", {
206
224
  className: "inline-flex items-center rounded-pill bg-bg-surface px-2 py-1 text-xs text-text-secondary",
207
- children: [/* @__PURE__ */ p("span", {
225
+ children: [/* @__PURE__ */ g("span", {
208
226
  className: "font-medium text-text-primary",
209
227
  children: [e, ":"]
210
- }), /* @__PURE__ */ f("span", {
228
+ }), /* @__PURE__ */ h("span", {
211
229
  className: "ml-1",
212
230
  children: typeof t == "object" && t ? JSON.stringify(t) : String(t)
213
231
  })]
214
232
  }, e))
215
233
  }),
216
- /* @__PURE__ */ p("div", {
234
+ /* @__PURE__ */ g("div", {
217
235
  className: "flex flex-col gap-form-gap",
218
- children: [A.length === 0 && /* @__PURE__ */ f("p", {
236
+ children: [R.length === 0 && /* @__PURE__ */ h("p", {
219
237
  className: "text-sm text-text-secondary",
220
238
  "data-testid": "drilldown-page-empty",
221
239
  children: "This page has no widgets"
222
- }), A.map((e) => {
240
+ }), R.map((e) => {
223
241
  let t = e.config?._internalWidgetType, n = e.type;
224
- return /* @__PURE__ */ f("div", {
242
+ return /* @__PURE__ */ h("div", {
225
243
  className: "min-w-0 overflow-hidden rounded-card border border-[var(--color-border-subtle)] bg-bg-surface",
226
244
  style: n === "LINE_CHART" || n === "chart" || t === "chart" || t === "funnel_chart" ? { height: "clamp(220px, 45vh, 350px)" } : n === "TABLE" || n === "table" || t === "table" || t === "list" || t === "pivot_table" ? {
227
245
  minHeight: "min(250px, 40vh)",
@@ -230,19 +248,19 @@ var g = c(function({ dashboardId: i, params: o, live: c = !1, refreshRevision: g
230
248
  minHeight: "min(120px, 25vh)",
231
249
  maxHeight: "min(300px, 50vh)"
232
250
  },
233
- children: /* @__PURE__ */ f(_, {
251
+ children: /* @__PURE__ */ h(b, {
234
252
  widget: e,
235
- filterValues: o
253
+ filterValues: s
236
254
  })
237
255
  }, e.id);
238
256
  })]
239
257
  })
240
258
  ]
241
259
  });
242
- }), _ = c(function({ widget: e, filterValues: t }) {
243
- return /* @__PURE__ */ f("div", {
260
+ }), b = l(function({ widget: e, filterValues: t }) {
261
+ return /* @__PURE__ */ h("div", {
244
262
  className: "h-full [&_[data-widget-id]]:border-transparent [&_[data-widget-id]:hover]:border-transparent",
245
- children: /* @__PURE__ */ f(o, {
263
+ children: /* @__PURE__ */ h(s, {
246
264
  widget: e,
247
265
  isLoading: !1,
248
266
  error: null,
@@ -251,4 +269,4 @@ var g = c(function({ dashboardId: i, params: o, live: c = !1, refreshRevision: g
251
269
  });
252
270
  });
253
271
  //#endregion
254
- export { g as default };
272
+ export { y as default };
@@ -2,9 +2,10 @@ export declare function DataSinkContent({ id, live }: {
2
2
  id?: string;
3
3
  live: boolean;
4
4
  }): import("react").JSX.Element;
5
- export declare function DashboardContent({ dashboardId, live }: {
5
+ export declare function DashboardContent({ dashboardId, live, expectedWidgetId, }: {
6
6
  dashboardId?: string;
7
7
  live?: boolean;
8
+ expectedWidgetId?: string;
8
9
  }): import("react").JSX.Element;
9
10
  /**
10
11
  * Read-only evaluation of the saved expression against up to 50 current source
@@ -15,7 +16,8 @@ export declare function ParserContent({ parserId, live }: {
15
16
  parserId?: string;
16
17
  live: boolean;
17
18
  }): import("react").JSX.Element;
18
- export declare function WidgetsContent({ dashboardId, live }: {
19
+ export declare function WidgetsContent({ dashboardId, live, expectedWidgetId, }: {
19
20
  dashboardId?: string;
20
21
  live: boolean;
22
+ expectedWidgetId?: string;
21
23
  }): import("react").JSX.Element;
@@ -1,180 +1,208 @@
1
1
  import { ListWidgetsByDashboardDocument as e } from "../../../generated/wspace-operations.js";
2
- import { useAssistantRunStore as t } from "../../assistant/assistantRunStore.js";
3
- import n from "../datasink/DataSinkTableViewer.js";
4
- import { normalizeWidget as r } from "../../hooks/useWidgetOperations.js";
5
- import i from "../../hooks/useDataSinkOperations.js";
6
- import a from "../widgets/WidgetWrapper.js";
7
- import o from "../DrilldownDashboardRenderer.js";
8
- import { loadParserPreview as s, parserSampleCaption as c } from "./parserPreview.js";
9
- import { useEffect as l, useRef as u, useState as d } from "react";
10
- import { Spinner as f } from "@burdenoff/fe-libs/ui";
11
- import { useApolloClient as p } from "@apollo/client/react";
12
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
2
+ import { useBigConsole as t } from "../../context/BigConsoleContext.js";
3
+ import "../../context/index.js";
4
+ import { useAssistantRunStore as n } from "../../assistant/assistantRunStore.js";
5
+ import { loadConfirmedPreviewWidgets as r } from "./confirmedPreviewWidgets.js";
6
+ import i from "../datasink/DataSinkTableViewer.js";
7
+ import { normalizeWidget as a } from "../../hooks/useWidgetOperations.js";
8
+ import o from "../../hooks/useDataSinkOperations.js";
9
+ import s from "../widgets/WidgetWrapper.js";
10
+ import c from "../DrilldownDashboardRenderer.js";
11
+ import { loadParserPreview as l, parserSampleCaption as u } from "./parserPreview.js";
12
+ import { useEffect as d, useRef as f, useState as p } from "react";
13
+ import { Button as m, Spinner as h } from "@burdenoff/fe-libs/ui";
14
+ import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
+ import { useApolloClient as _ } from "@apollo/client/react";
16
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
13
17
  //#region src/bigconsole/components/preview/AiPreviewContent.tsx
14
- var g = 4e3, _ = "flex min-h-[6rem] min-w-0 items-center justify-center gap-2 rounded-card bg-bg-sunken px-3 py-6 text-center text-sm text-text-muted";
15
- function v({ label: e, testId: t }) {
16
- return /* @__PURE__ */ h("div", {
17
- className: _,
18
+ var b = 4e3, x = "flex min-h-[6rem] min-w-0 items-center justify-center gap-2 rounded-card bg-bg-sunken px-3 py-6 text-center text-sm text-text-muted";
19
+ function S({ label: e, testId: t }) {
20
+ return /* @__PURE__ */ y("div", {
21
+ className: x,
18
22
  "data-testid": t,
19
- children: [/* @__PURE__ */ m(f, { className: "size-4 shrink-0" }), e]
23
+ children: [/* @__PURE__ */ v(h, { className: "size-4 shrink-0" }), e]
20
24
  });
21
25
  }
22
- function y({ text: e, testId: t }) {
23
- return /* @__PURE__ */ m("p", {
24
- className: _,
26
+ function C({ text: e, testId: t }) {
27
+ return /* @__PURE__ */ v("p", {
28
+ className: x,
25
29
  "data-testid": t,
26
30
  children: e
27
31
  });
28
32
  }
29
- function b({ text: e, testId: t }) {
30
- return /* @__PURE__ */ m("p", {
31
- className: `${_} text-status-error-text`,
33
+ function w({ text: e, testId: t }) {
34
+ return /* @__PURE__ */ v("p", {
35
+ className: `${x} text-status-error-text`,
32
36
  "data-testid": t,
33
37
  children: e
34
38
  });
35
39
  }
36
- function x(e, n, r) {
37
- let i = t((e) => e.contentRevision), [a, o] = d(null), [s, c] = d(!!n), [f, p] = d(null), [m, h] = d(n), _ = u(e);
38
- return _.current = e, n !== m && (h(n), o(null), p(null), c(!!n)), l(() => {
39
- if (!n) return;
40
- let e = !1, t = !1, i = async () => {
41
- if (!t) {
42
- t = !0;
40
+ function T(e, t, r, i, a = !1) {
41
+ let o = n((e) => e.contentRevision), [s, c] = p(0), [l, u] = p(null), [m, h] = p(!!t), [g, _] = p(null), [v, y] = p(t), x = f(e);
42
+ return x.current = e, t !== v && (y(t), u(null), _(null), h(!!t)), d(() => {
43
+ if (!t) return;
44
+ let e = !1, n = new AbortController(), i = !1, o = !1, s = async () => {
45
+ if (!(i || o)) {
46
+ i = !0;
43
47
  try {
44
- let t = await _.current();
48
+ let t = await x.current(n.signal);
45
49
  if (e) return;
46
- o(t ?? null), p(null);
50
+ u(t ?? null), _(null);
47
51
  } catch (t) {
48
52
  if (e) return;
49
- p(t instanceof Error ? t : /* @__PURE__ */ Error("Failed to load preview content"));
53
+ _(t instanceof Error ? t : /* @__PURE__ */ Error("Failed to load preview content")), a && (o = !0);
50
54
  } finally {
51
- t = !1, e || c(!1);
55
+ i = !1, e || h(!1);
52
56
  }
53
57
  }
54
58
  };
55
- i();
56
- let a = window.setInterval(() => {
57
- r && (typeof document < "u" && document.visibilityState !== "visible" || i());
58
- }, g);
59
+ s();
60
+ let c = window.setInterval(() => {
61
+ r && (typeof document < "u" && document.visibilityState !== "visible" || s());
62
+ }, b);
59
63
  return () => {
60
- e = !0, window.clearInterval(a);
64
+ e = !0, n.abort(), window.clearInterval(c);
61
65
  };
62
66
  }, [
63
- n,
67
+ t,
64
68
  r,
65
- i
69
+ o,
70
+ i,
71
+ s,
72
+ a
66
73
  ]), {
67
- data: a,
68
- loading: s,
69
- error: f
74
+ data: l,
75
+ loading: m,
76
+ error: g,
77
+ reload: () => c((e) => e + 1)
70
78
  };
71
79
  }
72
- function S({ id: e, live: t }) {
73
- let { getDataSinkData: r } = i({ skipFetch: !0 }), { data: a, loading: o, error: s } = x(async () => {
74
- let t = await r({ id: e }, { limit: 50 });
80
+ function E({ id: e, live: t }) {
81
+ let { getDataSinkData: n } = o({ skipFetch: !0 }), { data: r, loading: a, error: s } = T(async () => {
82
+ let t = await n({ id: e }, { limit: 50 });
75
83
  return t ? t.raw : null;
76
84
  }, e, t);
77
- return e ? s ? /* @__PURE__ */ m(b, {
85
+ return e ? s ? /* @__PURE__ */ v(w, {
78
86
  text: "Could not load the data sink's rows.",
79
87
  testId: "ai-preview-datasink-error"
80
- }) : o ? /* @__PURE__ */ m(v, {
88
+ }) : a ? /* @__PURE__ */ v(S, {
81
89
  label: "Loading the data sink’s data…",
82
90
  testId: "ai-preview-datasink-loading"
83
- }) : /* @__PURE__ */ m("div", {
91
+ }) : /* @__PURE__ */ v("div", {
84
92
  "data-testid": "ai-preview-content-datasink",
85
93
  className: "min-w-0",
86
- children: /* @__PURE__ */ m(n, {
87
- data: a,
94
+ children: /* @__PURE__ */ v(i, {
95
+ data: r,
88
96
  maxHeight: "300px"
89
97
  })
90
- }) : /* @__PURE__ */ m(y, {
98
+ }) : /* @__PURE__ */ v(C, {
91
99
  text: "Waiting for the data sink to be created…",
92
100
  testId: "ai-preview-datasink-waiting"
93
101
  });
94
102
  }
95
- function C({ dashboardId: e, live: n = !1 }) {
96
- let r = t((e) => e.contentRevision);
97
- return e ? /* @__PURE__ */ m("div", {
103
+ function D({ dashboardId: e, live: r = !1, expectedWidgetId: i }) {
104
+ let a = n((e) => e.contentRevision), { workspaceId: o, currentUser: s } = t();
105
+ return e ? !o || !s?.id ? /* @__PURE__ */ v(S, { label: "Loading dashboard…" }) : /* @__PURE__ */ v("div", {
98
106
  "data-testid": "ai-preview-content-dashboard",
99
107
  className: "min-w-0",
100
- children: /* @__PURE__ */ m(o, {
108
+ children: /* @__PURE__ */ v(c, {
101
109
  dashboardId: e,
102
110
  params: {},
103
- live: n,
104
- refreshRevision: r
105
- }, e)
106
- }) : /* @__PURE__ */ m(y, {
111
+ live: r,
112
+ refreshRevision: a,
113
+ expectedWidgetId: i,
114
+ requestWorkspaceId: o
115
+ }, `${o}|${s.id}|${e}`)
116
+ }) : /* @__PURE__ */ v(C, {
107
117
  text: "Waiting for the dashboard to be created…",
108
118
  testId: "ai-preview-dashboard-waiting"
109
119
  });
110
120
  }
111
- function w({ parserId: e, live: t }) {
112
- let r = p(), { data: i, loading: a, error: o } = x(() => e ? s(r, e) : Promise.resolve(null), e, t), l = c(i);
113
- return e ? o ? /* @__PURE__ */ m(b, {
121
+ function O({ parserId: e, live: t }) {
122
+ let n = _(), { data: r, loading: a, error: o } = T(() => e ? l(n, e) : Promise.resolve(null), e, t), s = u(r);
123
+ return e ? o ? /* @__PURE__ */ v(w, {
114
124
  text: "Could not read the parser's output.",
115
125
  testId: "ai-preview-parser-error"
116
- }) : a ? /* @__PURE__ */ m(v, {
126
+ }) : a ? /* @__PURE__ */ v(S, {
117
127
  label: "Loading the parser’s output…",
118
128
  testId: "ai-preview-parser-loading"
119
- }) : /* @__PURE__ */ h("div", {
129
+ }) : /* @__PURE__ */ y("div", {
120
130
  "data-testid": "ai-preview-content-parser",
121
131
  className: "min-w-0",
122
- children: [l && /* @__PURE__ */ m("p", {
132
+ children: [s && /* @__PURE__ */ v("p", {
123
133
  "data-testid": "ai-preview-parser-sample",
124
134
  className: "mb-2 text-xs text-text-muted",
125
- children: l
126
- }), /* @__PURE__ */ m(n, {
127
- data: i?.output ?? null,
135
+ children: s
136
+ }), /* @__PURE__ */ v(i, {
137
+ data: r?.output ?? null,
128
138
  maxHeight: "280px"
129
139
  })]
130
- }) : /* @__PURE__ */ m(y, {
140
+ }) : /* @__PURE__ */ v(C, {
131
141
  text: "Waiting for the parser to be created…",
132
142
  testId: "ai-preview-parser-waiting"
133
143
  });
134
144
  }
135
- function T(e) {
145
+ function k(e) {
136
146
  let t = e.toUpperCase();
137
147
  return t.includes("METRIC") || t.includes("KPI") || t.includes("CARD") || t.includes("STAT") ? "min(160px, 40vh)" : t.includes("TABLE") || t.includes("LIST") ? "min(280px, 50vh)" : "min(320px, 50vh)";
138
148
  }
139
- function E(t, n) {
140
- let i = p(), { data: a, loading: o, error: s } = x(async () => t ? ((await i.query({
149
+ function A(n, i, o) {
150
+ let s = _(), { workspaceId: c, currentUser: l } = t(), u = n && c && l?.id ? `${c}|${l.id}|${n}` : void 0, { data: d, loading: f, error: p, reload: m } = T(async (t) => !n || !c || !l?.id ? null : r(async () => ((await s.query({
141
151
  query: e,
142
- variables: { dashboardId: t },
143
- fetchPolicy: "network-only"
144
- })).data?.listWidgetsByDashboard || []).map(r) : null, t, n);
152
+ variables: { dashboardId: n },
153
+ fetchPolicy: "no-cache",
154
+ context: {
155
+ requiredWorkspaceAuth: !0,
156
+ requiredWorkspaceId: c,
157
+ queryDeduplication: !1,
158
+ fetchOptions: { signal: t }
159
+ }
160
+ })).data?.listWidgetsByDashboard || []).map(a), o, t), u, i, o, !0);
145
161
  return {
146
- widgets: a ?? [],
147
- loading: o,
148
- error: s
162
+ widgets: d ?? [],
163
+ loading: !!(n && !u) || f,
164
+ error: p,
165
+ reload: m
149
166
  };
150
167
  }
151
- function D({ dashboardId: e, live: t }) {
152
- let { widgets: n, loading: r, error: i } = E(e, t);
153
- return e ? i ? /* @__PURE__ */ m(b, {
154
- text: "Could not load this dashboard's widgets.",
155
- testId: "ai-preview-widget-error"
156
- }) : r && n.length === 0 ? /* @__PURE__ */ m(v, {
168
+ function j({ dashboardId: e, live: t, expectedWidgetId: n }) {
169
+ let { t: r } = g(), { widgets: i, loading: a, error: o, reload: c } = A(e, t, n), l = !!(n && !i.some((e) => e.id === n)), u = o ? /* @__PURE__ */ y("div", {
170
+ role: "alert",
171
+ children: [/* @__PURE__ */ v(w, {
172
+ text: "Could not load this dashboard's widgets.",
173
+ testId: "ai-preview-widget-error"
174
+ }), /* @__PURE__ */ v(m, {
175
+ onClick: c,
176
+ variant: "outline",
177
+ size: "sm",
178
+ children: r("bigconsole.widget.customWidget.action.retry", "Retry")
179
+ })]
180
+ }) : null;
181
+ return e ? u && i.length === 0 ? u : (a || l) && i.length === 0 ? /* @__PURE__ */ v(S, {
157
182
  label: "Loading widgets…",
158
183
  testId: "ai-preview-widget-loading"
159
- }) : n.length === 0 ? /* @__PURE__ */ m(y, {
184
+ }) : i.length === 0 ? /* @__PURE__ */ v(C, {
160
185
  text: "No widgets on this dashboard yet.",
161
186
  testId: "ai-preview-widget-empty"
162
- }) : /* @__PURE__ */ m("div", {
187
+ }) : /* @__PURE__ */ y("div", {
163
188
  "data-testid": "ai-preview-content-widget",
164
189
  className: "flex min-w-0 flex-col gap-list-gap",
165
- children: n.map((e) => /* @__PURE__ */ m("div", {
190
+ children: [u ?? (l ? /* @__PURE__ */ v(S, {
191
+ label: "Loading widgets…",
192
+ testId: "ai-preview-widget-loading"
193
+ }) : null), i.map((e) => /* @__PURE__ */ v("div", {
166
194
  className: "min-w-0 overflow-hidden rounded-card border border-[var(--color-border-subtle)] bg-bg-canvas",
167
- style: { height: T(e.type) },
168
- children: /* @__PURE__ */ m(a, {
195
+ style: { height: k(e.type) },
196
+ children: /* @__PURE__ */ v(s, {
169
197
  widget: e,
170
198
  error: null,
171
199
  filterValues: {}
172
200
  })
173
- }, e.id))
174
- }) : /* @__PURE__ */ m(y, {
201
+ }, e.id))]
202
+ }) : /* @__PURE__ */ v(C, {
175
203
  text: "Waiting for the dashboard — widgets live on it.",
176
204
  testId: "ai-preview-widget-waiting"
177
205
  });
178
206
  }
179
207
  //#endregion
180
- export { C as DashboardContent, S as DataSinkContent, w as ParserContent, D as WidgetsContent };
208
+ export { D as DashboardContent, E as DataSinkContent, O as ParserContent, j as WidgetsContent };
@@ -4,182 +4,185 @@ import { PREVIEW_STEPS as t, useAssistantRunStore as n } from "../../assistant/a
4
4
  import { useBigConsolePreviewControl as r } from "../../assistant/usePreviewControl.js";
5
5
  import { useAssistantRunWorkspace as i } from "../../assistant/useAssistantRunWorkspace.js";
6
6
  import { usePreviewWidgetDashboard as a } from "../../assistant/usePreviewWidgetDashboard.js";
7
- import { Section as o } from "../common/Section.js";
7
+ import { expectedPreviewWidgetId as o } from "./confirmedPreviewWidgets.js";
8
+ import { Section as s } from "../common/Section.js";
8
9
  import "../common/index.js";
9
- import { DOCK_CLEARANCE as s, PreviewMeta as c, STEP_LABEL as l, formatAgo as u, previewLabels as d } from "./previewShared.js";
10
- import { DashboardContent as f, DataSinkContent as p, ParserContent as m, WidgetsContent as h } from "./AiPreviewContent.js";
11
- import { useEffect as g, useRef as _, useState as v } from "react";
12
- import { ArrowUpRight as y, Loader2 as b, Sparkles as x, X as S } from "lucide-react";
13
- import { Button as C } from "@burdenoff/fe-libs/ui";
14
- import { useI18n as w } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
- import { jsx as T, jsxs as E } from "react/jsx-runtime";
16
- import { AssistantEntityPreview as D } from "@burdenoff/fe-libs/shared/assistant";
10
+ import { DOCK_CLEARANCE as c, PreviewMeta as l, STEP_LABEL as u, formatAgo as d, previewLabels as f } from "./previewShared.js";
11
+ import { DashboardContent as p, DataSinkContent as m, ParserContent as h, WidgetsContent as g } from "./AiPreviewContent.js";
12
+ import { useEffect as _, useRef as v, useState as y } from "react";
13
+ import { ArrowUpRight as b, Loader2 as x, Sparkles as S, X as C } from "lucide-react";
14
+ import { Button as w } from "@burdenoff/fe-libs/ui";
15
+ import { useI18n as T } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
16
+ import { jsx as E, jsxs as D } from "react/jsx-runtime";
17
+ import { AssistantEntityPreview as O } from "@burdenoff/fe-libs/shared/assistant";
17
18
  //#region src/bigconsole/components/preview/AiPreviewPanel.tsx
18
- function O({ children: e }) {
19
- return /* @__PURE__ */ T("div", {
19
+ function k({ children: e }) {
20
+ return /* @__PURE__ */ E("div", {
20
21
  className: "min-w-0 overflow-y-auto p-3",
21
22
  style: { maxHeight: "min(440px, 60vh)" },
22
23
  children: e
23
24
  });
24
25
  }
25
- function k({ onOpen: e }) {
26
- let { t } = w();
27
- return /* @__PURE__ */ E(C, {
26
+ function A({ onOpen: e }) {
27
+ let { t } = T();
28
+ return /* @__PURE__ */ D(w, {
28
29
  size: "sm",
29
30
  variant: "outline",
30
31
  onClick: e,
31
32
  "data-testid": "ai-preview-open-entity",
32
- children: [t("bigconsole.widget.aiPreview.open", "Open"), /* @__PURE__ */ T(y, { className: "ml-1 size-3.5" })]
33
+ children: [t("bigconsole.widget.aiPreview.open", "Open"), /* @__PURE__ */ E(b, { className: "ml-1 size-3.5" })]
33
34
  });
34
35
  }
35
- function A() {
36
- let { t: y } = w();
36
+ function j() {
37
+ let { t: b } = T();
37
38
  i();
38
- let A = a();
39
+ let j = a();
39
40
  r();
40
- let j = e(), M = n((e) => e.isRunning), N = n((e) => e.previewOpen), P = n((e) => e.hasRun), F = n((e) => e.steps), I = n((e) => e.entityIds), L = n((e) => e.caption), R = n((e) => e.error), z = n((e) => e.updatedAt), B = n((e) => e.openPreview), V = n((e) => e.closePreview), H = n((e) => e.setRichMounted);
41
- g(() => (H(!0), () => {
42
- H(!1);
43
- }), [H]);
44
- let [U, W] = v(0), G = _(!1);
45
- if (g(() => {
46
- M && !G.current && W((e) => e + 1), G.current = M;
47
- }, [M]), !P) return null;
48
- if (!N) return /* @__PURE__ */ E("div", {
41
+ let M = e(), N = n((e) => e.isRunning), P = n((e) => e.previewOpen), F = n((e) => e.hasRun), I = n((e) => e.steps), L = n((e) => e.entityIds), R = n((e) => e.entityResultOrder), z = n((e) => e.caption), B = n((e) => e.error), V = n((e) => e.updatedAt), H = n((e) => e.openPreview), U = n((e) => e.closePreview), W = n((e) => e.setRichMounted);
42
+ _(() => (W(!0), () => {
43
+ W(!1);
44
+ }), [W]);
45
+ let [G, K] = y(0), q = v(!1);
46
+ if (_(() => {
47
+ N && !q.current && K((e) => e + 1), q.current = N;
48
+ }, [N]), !F) return null;
49
+ if (!P) return /* @__PURE__ */ D("div", {
49
50
  className: "flex flex-wrap items-center justify-end gap-control-gap px-4 pt-3 md:px-6",
50
- style: { marginRight: s },
51
- children: [/* @__PURE__ */ T("span", {
51
+ style: { marginRight: c },
52
+ children: [/* @__PURE__ */ E("span", {
52
53
  className: "text-xs text-text-muted",
53
- children: M ? y("bigconsole.widget.aiPreview.buildRunning", "AI build running") : y("bigconsole.widget.aiPreview.buildFinished", "AI build finished")
54
- }), /* @__PURE__ */ E(C, {
54
+ children: N ? b("bigconsole.widget.aiPreview.buildRunning", "AI build running") : b("bigconsole.widget.aiPreview.buildFinished", "AI build finished")
55
+ }), /* @__PURE__ */ D(w, {
55
56
  size: "sm",
56
57
  variant: "outline",
57
- onClick: B,
58
+ onClick: H,
58
59
  "data-testid": "ai-preview-open",
59
60
  children: [
60
- /* @__PURE__ */ T(x, { className: "mr-1.5 size-4" }),
61
- y("bigconsole.widget.aiPreview.previewButton", "Preview"),
62
- M ? /* @__PURE__ */ T(b, { className: "ml-1.5 size-3.5 animate-spin" }) : null
61
+ /* @__PURE__ */ E(S, { className: "mr-1.5 size-4" }),
62
+ b("bigconsole.widget.aiPreview.previewButton", "Preview"),
63
+ N ? /* @__PURE__ */ E(x, { className: "ml-1.5 size-3.5 animate-spin" }) : null
63
64
  ]
64
65
  })]
65
66
  });
66
- let K = I.dashboard, q = A.error ? /* @__PURE__ */ E("div", {
67
+ let J = L.dashboard, Y = o(L.widget, R.widget, R.dashboard), X = j.error ? /* @__PURE__ */ D("div", {
67
68
  role: "alert",
68
69
  "data-testid": "ai-preview-widget-parent-error",
69
- children: [/* @__PURE__ */ T("p", { children: y("bigconsole.widget.aiPreview.widgetParentError", "Could not load this widget’s dashboard. It may be unavailable or you may no longer have access.") }), /* @__PURE__ */ T(C, {
70
+ children: [/* @__PURE__ */ E("p", { children: b("bigconsole.widget.aiPreview.widgetParentError", "Could not load this widget’s dashboard. It may be unavailable or you may no longer have access.") }), /* @__PURE__ */ E(w, {
70
71
  variant: "outline",
71
72
  size: "sm",
72
- onClick: A.retry,
73
- children: y("bigconsole.widget.customWidget.action.retry", "Retry")
73
+ onClick: j.retry,
74
+ children: b("bigconsole.widget.customWidget.action.retry", "Retry")
74
75
  })]
75
- }) : A.loading && !K ? /* @__PURE__ */ E("div", {
76
+ }) : j.loading && !J ? /* @__PURE__ */ D("div", {
76
77
  role: "status",
77
78
  "data-testid": "ai-preview-widget-parent-loading",
78
79
  className: "flex items-center gap-2",
79
- children: [/* @__PURE__ */ T(b, { className: "size-4 animate-spin" }), y("bigconsole.widget.aiPreview.widgetParentLoading", "Loading this widget’s dashboard…")]
80
- }) : null, J = t.map((e) => ({
80
+ children: [/* @__PURE__ */ E(x, { className: "size-4 animate-spin" }), b("bigconsole.widget.aiPreview.widgetParentLoading", "Loading this widget’s dashboard…")]
81
+ }) : null, Z = t.map((e) => ({
81
82
  id: e,
82
- label: y(l[e].key, l[e].fallback),
83
- status: F[e]
84
- })), Y = [
83
+ label: b(u[e].key, u[e].fallback),
84
+ status: I[e]
85
+ })), Q = [
85
86
  {
86
87
  id: "datasink",
87
- label: y("bigconsole.widget.aiPreview.tab.dataSink", "Data Sink"),
88
- render: () => /* @__PURE__ */ T(O, { children: /* @__PURE__ */ T(o, {
88
+ label: b("bigconsole.widget.aiPreview.tab.dataSink", "Data Sink"),
89
+ render: () => /* @__PURE__ */ E(k, { children: /* @__PURE__ */ E(s, {
89
90
  emphasis: "standard",
90
91
  padding: "compact",
91
92
  headingLevel: 3,
92
- title: y("bigconsole.widget.aiPreview.dataSinkRows", "Data sink rows"),
93
- description: y("bigconsole.widget.aiPreview.dataSinkRowsHint", "The rows the assistant just landed, straight from the sink."),
94
- actions: I.datasink ? /* @__PURE__ */ T(k, { onOpen: () => j(`/datasinks/${I.datasink}`) }) : void 0,
95
- children: /* @__PURE__ */ T(p, {
96
- id: I.datasink,
97
- live: M
93
+ title: b("bigconsole.widget.aiPreview.dataSinkRows", "Data sink rows"),
94
+ description: b("bigconsole.widget.aiPreview.dataSinkRowsHint", "The rows the assistant just landed, straight from the sink."),
95
+ actions: L.datasink ? /* @__PURE__ */ E(A, { onOpen: () => M(`/datasinks/${L.datasink}`) }) : void 0,
96
+ children: /* @__PURE__ */ E(m, {
97
+ id: L.datasink,
98
+ live: N
98
99
  })
99
100
  }) })
100
101
  },
101
102
  {
102
103
  id: "dashboard",
103
- label: y("bigconsole.widget.aiPreview.tab.dashboard", "Dashboard"),
104
- render: () => /* @__PURE__ */ T(O, { children: /* @__PURE__ */ T(o, {
104
+ label: b("bigconsole.widget.aiPreview.tab.dashboard", "Dashboard"),
105
+ render: () => /* @__PURE__ */ E(k, { children: /* @__PURE__ */ E(s, {
105
106
  emphasis: "standard",
106
107
  padding: "compact",
107
108
  headingLevel: 3,
108
- title: y("bigconsole.widget.aiPreview.tab.dashboard", "Dashboard"),
109
- description: y("bigconsole.widget.aiPreview.dashboardHint", "The live board, rendered exactly as the real page renders it."),
110
- actions: K ? /* @__PURE__ */ T(k, { onOpen: () => j(`/dashboards/${K}`) }) : void 0,
111
- children: q ?? /* @__PURE__ */ T(f, {
112
- dashboardId: K,
113
- live: M
109
+ title: b("bigconsole.widget.aiPreview.tab.dashboard", "Dashboard"),
110
+ description: b("bigconsole.widget.aiPreview.dashboardHint", "The live board, rendered exactly as the real page renders it."),
111
+ actions: J ? /* @__PURE__ */ E(A, { onOpen: () => M(`/dashboards/${J}`) }) : void 0,
112
+ children: X ?? /* @__PURE__ */ E(p, {
113
+ dashboardId: J,
114
+ live: N,
115
+ expectedWidgetId: Y
114
116
  })
115
117
  }) })
116
118
  },
117
119
  {
118
120
  id: "parser",
119
- label: y("bigconsole.widget.aiPreview.tab.parser", "Parser"),
120
- render: () => /* @__PURE__ */ T(O, { children: /* @__PURE__ */ T(o, {
121
+ label: b("bigconsole.widget.aiPreview.tab.parser", "Parser"),
122
+ render: () => /* @__PURE__ */ E(k, { children: /* @__PURE__ */ E(s, {
121
123
  emphasis: "standard",
122
124
  padding: "compact",
123
125
  headingLevel: 3,
124
- title: y("bigconsole.widget.aiPreview.parserOutput", "Parser output"),
125
- description: y("bigconsole.widget.aiPreview.parserOutputHint", "The rows after the parser's transform, so you can check the shape."),
126
- actions: I.parser ? /* @__PURE__ */ T(k, { onOpen: () => j(`/parsers/${I.parser}`) }) : void 0,
127
- children: /* @__PURE__ */ T(m, {
128
- parserId: I.parser,
129
- live: M
126
+ title: b("bigconsole.widget.aiPreview.parserOutput", "Parser output"),
127
+ description: b("bigconsole.widget.aiPreview.parserOutputHint", "The rows after the parser's transform, so you can check the shape."),
128
+ actions: L.parser ? /* @__PURE__ */ E(A, { onOpen: () => M(`/parsers/${L.parser}`) }) : void 0,
129
+ children: /* @__PURE__ */ E(h, {
130
+ parserId: L.parser,
131
+ live: N
130
132
  })
131
133
  }) })
132
134
  },
133
135
  {
134
136
  id: "widget",
135
- label: y("bigconsole.widget.aiPreview.tab.widget", "Widget"),
136
- render: () => /* @__PURE__ */ T(O, { children: /* @__PURE__ */ T(o, {
137
+ label: b("bigconsole.widget.aiPreview.tab.widget", "Widget"),
138
+ render: () => /* @__PURE__ */ E(k, { children: /* @__PURE__ */ E(s, {
137
139
  emphasis: "standard",
138
140
  padding: "compact",
139
141
  headingLevel: 3,
140
- title: y("bigconsole.widget.aiPreview.widgets", "Widgets"),
141
- description: y("bigconsole.widget.aiPreview.widgetsHint", "Every widget on the new dashboard, rendered live."),
142
- actions: K ? /* @__PURE__ */ T(k, { onOpen: () => j(`/dashboards/${K}`) }) : void 0,
143
- children: q ?? /* @__PURE__ */ T(h, {
144
- dashboardId: K,
145
- live: M
142
+ title: b("bigconsole.widget.aiPreview.widgets", "Widgets"),
143
+ description: b("bigconsole.widget.aiPreview.widgetsHint", "Every widget on the new dashboard, rendered live."),
144
+ actions: J ? /* @__PURE__ */ E(A, { onOpen: () => M(`/dashboards/${J}`) }) : void 0,
145
+ children: X ?? /* @__PURE__ */ E(g, {
146
+ dashboardId: J,
147
+ live: N,
148
+ expectedWidgetId: Y
146
149
  })
147
150
  }) })
148
151
  }
149
152
  ];
150
- return /* @__PURE__ */ E("div", {
153
+ return /* @__PURE__ */ D("div", {
151
154
  "data-testid": "ai-preview-panel",
152
- style: { paddingRight: s },
155
+ style: { paddingRight: c },
153
156
  className: "mx-4 mt-3 min-w-0 md:mx-6",
154
- children: [/* @__PURE__ */ T("h2", {
157
+ children: [/* @__PURE__ */ E("h2", {
155
158
  className: "sr-only",
156
- children: y("bigconsole.widget.aiPreview.title", "AI Preview")
157
- }), /* @__PURE__ */ T(D, {
158
- title: y("bigconsole.widget.aiPreview.title", "AI Preview"),
159
- runKey: String(U),
160
- steps: J,
161
- tabs: Y,
159
+ children: b("bigconsole.widget.aiPreview.title", "AI Preview")
160
+ }), /* @__PURE__ */ E(O, {
161
+ title: b("bigconsole.widget.aiPreview.title", "AI Preview"),
162
+ runKey: String(G),
163
+ steps: Z,
164
+ tabs: Q,
162
165
  follow: "produced",
163
- caption: M ? L || y("bigconsole.widget.aiPreview.working", "Working…") : y("bigconsole.widget.aiPreview.done", "Done"),
164
- error: R,
165
- meta: /* @__PURE__ */ T(c, {
166
- state: M ? "running" : R ? "stopped" : "idle",
167
- stateLabel: M ? y("bigconsole.widget.aiPreview.live", "Live") : R ? y("bigconsole.widget.aiPreview.stopped", "Stopped") : null,
168
- updatedLabel: y("bigconsole.widget.aiPreview.updated", "updated"),
169
- updatedAt: z,
170
- ago: (e) => u(e, y)
166
+ caption: N ? z || b("bigconsole.widget.aiPreview.working", "Working…") : b("bigconsole.widget.aiPreview.done", "Done"),
167
+ error: B,
168
+ meta: /* @__PURE__ */ E(l, {
169
+ state: N ? "running" : B ? "stopped" : "idle",
170
+ stateLabel: N ? b("bigconsole.widget.aiPreview.live", "Live") : B ? b("bigconsole.widget.aiPreview.stopped", "Stopped") : null,
171
+ updatedLabel: b("bigconsole.widget.aiPreview.updated", "updated"),
172
+ updatedAt: V,
173
+ ago: (e) => d(e, b)
171
174
  }),
172
- headerActions: /* @__PURE__ */ T(C, {
175
+ headerActions: /* @__PURE__ */ E(w, {
173
176
  size: "sm",
174
177
  variant: "ghost",
175
- onClick: V,
176
- "aria-label": y("bigconsole.widget.aiPreview.closeAriaLabel", "Close preview"),
178
+ onClick: U,
179
+ "aria-label": b("bigconsole.widget.aiPreview.closeAriaLabel", "Close preview"),
177
180
  "data-testid": "ai-preview-close",
178
- children: /* @__PURE__ */ T(S, { className: "size-4" })
181
+ children: /* @__PURE__ */ E(C, { className: "size-4" })
179
182
  }),
180
- labels: d(y)
183
+ labels: f(b)
181
184
  })]
182
185
  });
183
186
  }
184
187
  //#endregion
185
- export { A as AiPreviewPanel };
188
+ export { j as AiPreviewPanel };
@@ -0,0 +1,5 @@
1
+ export declare function loadConfirmedPreviewWidgets<T extends {
2
+ id: string;
3
+ }>(load: () => Promise<T[]>, expectedId: string | undefined, signal: AbortSignal, wait?: (ms: number, signal: AbortSignal) => Promise<void>): Promise<T[]>;
4
+ /** A newer dashboard starts a separate target; do not await its predecessor's widget. */
5
+ export declare function expectedPreviewWidgetId(widgetId: string | undefined, widgetOrder: number | undefined, dashboardOrder: number | undefined): string | undefined;
@@ -0,0 +1,27 @@
1
+ //#region src/bigconsole/components/preview/confirmedPreviewWidgets.ts
2
+ var e = 6, t = 1e3;
3
+ function n(e, t) {
4
+ return new Promise((n, r) => {
5
+ let i = () => {
6
+ clearTimeout(a), r(/* @__PURE__ */ Error("Preview read cancelled"));
7
+ }, a = setTimeout(() => {
8
+ t.removeEventListener("abort", i), n();
9
+ }, e);
10
+ t.addEventListener("abort", i, { once: !0 }), t.aborted && i();
11
+ });
12
+ }
13
+ async function r(r, i, a, o = n) {
14
+ for (let n = 0; n < e; n += 1) {
15
+ if (a.aborted) throw Error("Preview read cancelled");
16
+ let s = await r();
17
+ if (a.aborted) throw Error("Preview read cancelled");
18
+ if (!i || s.some((e) => e.id === i)) return s;
19
+ n < e - 1 && await o(t, a);
20
+ }
21
+ throw Error("Confirmed widget is not available on this dashboard");
22
+ }
23
+ function i(e, t, n) {
24
+ return t !== void 0 && n !== void 0 && t < n ? void 0 : e;
25
+ }
26
+ //#endregion
27
+ export { i as expectedPreviewWidgetId, r as loadConfirmedPreviewWidgets };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-bigconsole",
3
- "version": "2026.1012.8",
3
+ "version": "2026.1012.9",
4
4
  "description": "BigConsole - AI-powered analytics and dashboard platform",
5
5
  "type": "module",
6
6
  "files": [