@object-ui/plugin-report 17.7.0 → 18.0.0

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/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
- import { ComponentRegistry as e, FilterOperatorError as t, buildCategoryOrder as n, buildChartSeries as r, buildDatasetDrillFilter as i, buildDatasetFieldHelpers as a, buildOptionColorMap as o, chartConfigPresentation as s, deriveDimensionLabelMaps as c, dimensionOptionTranslator as l, formatDimensionValue as u, formatMeasure as d, localizeFieldOptions as f, mergeAuthoredSeries as p, mergeFilters as m, pivotBucketId as h, pivotCellKey as g, pivotDimensionValue as _, relabelDimensions as v, toDisplayDate as y } from "@object-ui/core";
2
- import * as b from "react";
3
- import x from "react";
4
- import { isSpecReport as S, specReportToPresentation as C } from "@object-ui/types";
5
- import { SchemaRenderer as w, SchemaRendererContext as T, toRenderableSchema as E, useDataInvalidation as D, useDatasetDimensionLabels as O, useDatasetDimensionMeta as k } from "@object-ui/react";
6
- import { Badge as A, Button as j, Card as M, CardContent as N, CardDescription as P, CardHeader as F, CardTitle as I, Skeleton as L, renderNodeSlot as ee } from "@object-ui/components";
1
+ import { ComponentRegistry as e, FilterOperatorError as t, buildCategoryOrder as n, buildCategoryRank as r, buildChartSeries as i, buildDatasetDrillFilter as a, buildDatasetFieldHelpers as o, buildOptionColorMap as s, chartConfigPresentation as c, deriveDimensionLabelMaps as l, dimensionOptionTranslator as u, formatDimensionValue as d, formatMeasure as f, localizeFieldOptions as p, mergeAuthoredSeries as m, mergeFilters as h, pivotBucketId as g, pivotCellKey as _, pivotDimensionValue as v, relabelDimensions as y, toDisplayDate as b } from "@object-ui/core";
2
+ import * as x from "react";
3
+ import S from "react";
4
+ import { isSpecReport as C, specReportToPresentation as w } from "@object-ui/types";
5
+ import { SchemaRenderer as T, SchemaRendererContext as E, classifyLoadError as D, toRenderableSchema as O, useDataInvalidation as k, useDatasetDimensionMeta as ee } from "@object-ui/react";
6
+ import { Badge as A, Button as j, Card as M, CardContent as N, CardDescription as P, CardHeader as F, CardTitle as I, Skeleton as L, renderNodeSlot as te } from "@object-ui/components";
7
7
  import { jsx as R, jsxs as z } from "react/jsx-runtime";
8
- import { AlertTriangle as te, Download as B, Loader2 as ne, Printer as re, RefreshCw as ie, Table2 as ae } from "lucide-react";
9
- import { getCellRenderer as oe, resolveCellRendererType as se } from "@object-ui/fields";
10
- import { builtinAggregateLabels as V, pickLocalized as ce, useDisplayLocale as H, useObjectTranslation as le, useSafeFieldLabel as U, useSafeTranslate as W } from "@object-ui/i18n";
8
+ import { AlertTriangle as ne, Download as B, Loader2 as re, Printer as ie, RefreshCw as ae, ShieldAlert as oe, Table2 as se } from "lucide-react";
9
+ import { getCellRenderer as ce, resolveCellRendererType as le } from "@object-ui/fields";
10
+ import { builtinAggregateLabels as V, pickLocalized as ue, useDisplayLocale as H, useObjectTranslation as de, useSafeFieldLabel as U, useSafeTranslate as W } from "@object-ui/i18n";
11
11
  //#region src/LegacyReportRenderer.tsx
12
- var ue = ({ schema: t }) => {
12
+ var fe = ({ schema: t }) => {
13
13
  let { title: n, description: r, data: i, columns: a } = t;
14
14
  t.chart?.type;
15
15
  let o = !!t.chart;
@@ -71,29 +71,29 @@ function G(e, t, n) {
71
71
  }
72
72
  //#endregion
73
73
  //#region src/ReportExportEngine.ts
74
- function de(e, t, n) {
74
+ function pe(e, t, n) {
75
75
  let r = e.fields || [], i = r.map((e) => e.label || e.name), a = t.map((e) => r.map((t) => {
76
76
  let n = e[t.name];
77
- return n = ge(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
77
+ return n = ye(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
78
78
  }));
79
- J([...n?.includeHeaders === !1 ? [] : [i.join(",")], ...a.map((e) => e.join(","))].join("\n"), n?.filename || `${e.title || "report"}.csv`, "text/csv");
79
+ q([...n?.includeHeaders === !1 ? [] : [i.join(",")], ...a.map((e) => e.join(","))].join("\n"), n?.filename || `${e.title || "report"}.csv`, "text/csv");
80
80
  }
81
- function fe(e, t, n) {
81
+ function me(e, t, n) {
82
82
  let r = {
83
83
  title: e.title,
84
84
  description: e.description,
85
85
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
86
86
  data: t
87
87
  };
88
- J(JSON.stringify(r, null, 2), n?.filename || `${e.title || "report"}.json`, "application/json");
88
+ q(JSON.stringify(r, null, 2), n?.filename || `${e.title || "report"}.json`, "application/json");
89
89
  }
90
- function K(e, t, n, r = "en") {
91
- let i = e.fields || [], a = ve(n?.orientation), o = _e(n?.pageSize);
92
- J(`<!DOCTYPE html>
90
+ function he(e, t, n, r = "en") {
91
+ let i = e.fields || [], a = xe(n?.orientation), o = be(n?.pageSize);
92
+ q(`<!DOCTYPE html>
93
93
  <html>
94
94
  <head>
95
95
  <meta charset="utf-8">
96
- <title>${q(e.title || "Report")}</title>
96
+ <title>${K(e.title || "Report")}</title>
97
97
  <style>
98
98
  @page { size: ${o} ${a}; margin: 20mm; }
99
99
  body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #333; }
@@ -107,20 +107,20 @@ function K(e, t, n, r = "en") {
107
107
  </style>
108
108
  </head>
109
109
  <body>
110
- <h1>${q(e.title || "Report")}</h1>
111
- ${e.description ? `<p class="description">${q(e.description)}</p>` : ""}
110
+ <h1>${K(e.title || "Report")}</h1>
111
+ ${e.description ? `<p class="description">${K(e.description)}</p>` : ""}
112
112
  <p class="meta">Generated: ${(/* @__PURE__ */ new Date()).toLocaleString(r)}</p>
113
113
  <table>
114
- <thead><tr>${i.map((e) => `<th>${q(e.label || e.name)}</th>`).join("")}</tr></thead>
115
- <tbody>${t.map((e) => `<tr>${i.map((t) => `<td>${q(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
114
+ <thead><tr>${i.map((e) => `<th>${K(e.label || e.name)}</th>`).join("")}</tr></thead>
115
+ <tbody>${t.map((e) => `<tr>${i.map((t) => `<td>${K(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
116
116
  </table>
117
117
  </body>
118
118
  </html>`, n?.filename || `${e.title || "report"}.html`, "text/html");
119
119
  }
120
- function pe(e, t, n, r = "en") {
121
- let i = e.fields || [], a = ve(n?.orientation), o = _e(n?.pageSize), s = window.open("", "_blank");
120
+ function ge(e, t, n, r = "en") {
121
+ let i = e.fields || [], a = xe(n?.orientation), o = be(n?.pageSize), s = window.open("", "_blank");
122
122
  if (!s) {
123
- K(e, t, {
123
+ he(e, t, {
124
124
  ...n,
125
125
  format: "html",
126
126
  filename: n?.filename?.replace(/\.pdf$/, ".html") || `${e.title || "report"}.html`
@@ -131,7 +131,7 @@ function pe(e, t, n, r = "en") {
131
131
  <html>
132
132
  <head>
133
133
  <meta charset="utf-8">
134
- <title>${q(e.title || "Report")}</title>
134
+ <title>${K(e.title || "Report")}</title>
135
135
  <style>
136
136
  @page { size: ${o} ${a}; margin: 20mm; }
137
137
  @media print { .no-print { display: none; } }
@@ -146,56 +146,56 @@ function pe(e, t, n, r = "en") {
146
146
  </style>
147
147
  </head>
148
148
  <body>
149
- <h1>${q(e.title || "Report")}</h1>
150
- ${e.description ? `<p class="description">${q(e.description)}</p>` : ""}
149
+ <h1>${K(e.title || "Report")}</h1>
150
+ ${e.description ? `<p class="description">${K(e.description)}</p>` : ""}
151
151
  <p class="meta">Generated: ${(/* @__PURE__ */ new Date()).toLocaleString(r)}</p>
152
152
  <table>
153
- <thead><tr>${i.map((e) => `<th>${q(e.label || e.name)}</th>`).join("")}</tr></thead>
154
- <tbody>${t.map((e) => `<tr>${i.map((t) => `<td>${q(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
153
+ <thead><tr>${i.map((e) => `<th>${K(e.label || e.name)}</th>`).join("")}</tr></thead>
154
+ <tbody>${t.map((e) => `<tr>${i.map((t) => `<td>${K(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
155
155
  </table>
156
156
  </body>
157
157
  </html>`), s.document.close(), s.onload = () => {
158
158
  s.print();
159
159
  };
160
160
  }
161
- function me(e, t, n) {
161
+ function _e(e, t, n) {
162
162
  let r = e.fields || [], i = r.map((e) => e.label || e.name), a = t.map((e) => r.map((t) => {
163
163
  let n = e[t.name];
164
- return n = ge(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n") || n.includes(" ")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
164
+ return n = ye(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n") || n.includes(" ")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
165
165
  }));
166
- J("" + [...n?.includeHeaders === !1 ? [] : [i.join(" ")], ...a.map((e) => e.join(" "))].join("\n"), n?.filename || `${e.title || "report"}.tsv`, "text/tab-separated-values");
166
+ q("" + [...n?.includeHeaders === !1 ? [] : [i.join(" ")], ...a.map((e) => e.join(" "))].join("\n"), n?.filename || `${e.title || "report"}.tsv`, "text/tab-separated-values");
167
167
  }
168
- function he(e, t, n, r, i = "en") {
168
+ function ve(e, t, n, r, i = "en") {
169
169
  switch (e) {
170
170
  case "csv":
171
- de(t, n, r);
171
+ pe(t, n, r);
172
172
  break;
173
173
  case "json":
174
- fe(t, n, r);
174
+ me(t, n, r);
175
175
  break;
176
176
  case "html":
177
- K(t, n, r, i);
177
+ he(t, n, r, i);
178
178
  break;
179
179
  case "pdf":
180
- pe(t, n, r, i);
180
+ ge(t, n, r, i);
181
181
  break;
182
182
  case "excel":
183
- me(t, n, r);
183
+ _e(t, n, r);
184
184
  break;
185
185
  default: console.warn(`Unsupported export format: ${e}`);
186
186
  }
187
187
  }
188
- function q(e) {
188
+ function K(e) {
189
189
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
190
190
  }
191
- function ge(e) {
191
+ function ye(e) {
192
192
  if (typeof e == "string" && e.length > 0) {
193
193
  let t = e.charAt(0);
194
194
  if (t === "=" || t === "+" || t === "-" || t === "@" || t === "|") return `\t${e}`;
195
195
  }
196
196
  return e;
197
197
  }
198
- function _e(e) {
198
+ function be(e) {
199
199
  return [
200
200
  "A4",
201
201
  "A3",
@@ -203,19 +203,19 @@ function _e(e) {
203
203
  "Legal"
204
204
  ].includes(e || "") ? e : "A4";
205
205
  }
206
- function ve(e) {
206
+ function xe(e) {
207
207
  return e === "landscape" ? "landscape" : "portrait";
208
208
  }
209
- function J(e, t, n) {
209
+ function q(e, t, n) {
210
210
  let r = new Blob([e], { type: `${n};charset=utf-8` }), i = URL.createObjectURL(r), a = document.createElement("a");
211
211
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
212
212
  }
213
213
  //#endregion
214
214
  //#region src/formatValue.ts
215
- function Y(e, t, n = "en") {
215
+ function J(e, t, n = "en") {
216
216
  if (e == null || e === "") return "";
217
217
  let r = t?.type, i = t?.format;
218
- if (r === "date" || i === "date" || ye(e)) return be(e);
218
+ if (r === "date" || i === "date" || Se(e)) return Ce(e);
219
219
  if (r === "number" || typeof e == "number") {
220
220
  let t = typeof e == "number" ? e : Number(e);
221
221
  return isNaN(t) ? String(e) : i === "currency" || i === "currency_cny" ? `¥${G(t, n, {
@@ -231,12 +231,12 @@ function Y(e, t, n = "en") {
231
231
  }
232
232
  return String(e);
233
233
  }
234
- function ye(e) {
234
+ function Se(e) {
235
235
  return typeof e == "string" && /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/.test(e);
236
236
  }
237
- function be(e) {
237
+ function Ce(e) {
238
238
  try {
239
- let t = y(e);
239
+ let t = b(e);
240
240
  return isNaN(t.getTime()) ? String(e) : `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`;
241
241
  } catch {
242
242
  return String(e);
@@ -244,7 +244,7 @@ function be(e) {
244
244
  }
245
245
  //#endregion
246
246
  //#region src/ReportViewer.tsx
247
- function xe(e, t) {
247
+ function we(e, t) {
248
248
  if (!t || t.length === 0 || !e || e.length === 0) return null;
249
249
  let n = t[0], r = n.field, i = /* @__PURE__ */ new Map();
250
250
  for (let t of e) {
@@ -260,7 +260,7 @@ function xe(e, t) {
260
260
  let o = n.sort === "desc" ? -1 : 1;
261
261
  return a.sort((e, t) => e.key.localeCompare(t.key) * o), a;
262
262
  }
263
- function Se(e, t, n) {
263
+ function Te(e, t, n) {
264
264
  if (!e) return 0;
265
265
  let r = e.map((e) => Number(e[t]) || 0);
266
266
  switch (n) {
@@ -273,18 +273,18 @@ function Se(e, t, n) {
273
273
  default: return "";
274
274
  }
275
275
  }
276
- var Ce = ({ schema: e, onRefresh: t }) => {
276
+ var Ee = ({ schema: e, onRefresh: t }) => {
277
277
  let { report: n, data: r, showToolbar: i = !0, allowExport: a = !0, allowPrint: o = !0, loading: s = !1 } = e, c = W(), l = H(), u = (e) => {
278
278
  if (!n) {
279
279
  console.warn("ReportViewer: Cannot export, no report defined");
280
280
  return;
281
281
  }
282
- he(e, n, r || [], n.exportConfigs?.[e], l);
282
+ ve(e, n, r || [], n.exportConfigs?.[e], l);
283
283
  }, d = c("common.printDialogHint", "Opens your browser’s print dialog (not a PDF export)"), f = () => {
284
284
  window.print();
285
285
  }, p = () => {
286
286
  t?.();
287
- }, m = (e, t) => Se(r, e, t), h = (e, t) => {
287
+ }, m = (e, t) => Te(r, e, t), h = (e, t) => {
288
288
  let r = n?.conditionalFormatting;
289
289
  if (r && Array.isArray(r)) for (let n of r) {
290
290
  if (n.field !== e) continue;
@@ -318,7 +318,7 @@ var Ce = ({ schema: e, onRefresh: t }) => {
318
318
  children: String(e)
319
319
  });
320
320
  }
321
- if (t.aggregation) return Y(e, t, l);
321
+ if (t.aggregation) return J(e, t, l);
322
322
  if (t.type) {
323
323
  let n = { ...t };
324
324
  t.colorMap && !n.options && (n.options = Object.entries(t.colorMap).map(([e, t]) => ({
@@ -326,13 +326,13 @@ var Ce = ({ schema: e, onRefresh: t }) => {
326
326
  label: e,
327
327
  color: t
328
328
  })));
329
- let r = oe(se(n));
329
+ let r = ce(le(n));
330
330
  return /* @__PURE__ */ R(r, {
331
331
  value: e,
332
332
  field: n
333
333
  });
334
334
  }
335
- return Y(e, t, l);
335
+ return J(e, t, l);
336
336
  };
337
337
  return n ? /* @__PURE__ */ z("div", {
338
338
  className: "space-y-4",
@@ -352,7 +352,7 @@ var Ce = ({ schema: e, onRefresh: t }) => {
352
352
  variant: "outline",
353
353
  size: "sm",
354
354
  onClick: p,
355
- children: [/* @__PURE__ */ R(ie, { className: "h-4 w-4 mr-2" }), "Refresh"]
355
+ children: [/* @__PURE__ */ R(ae, { className: "h-4 w-4 mr-2" }), "Refresh"]
356
356
  }),
357
357
  o && /* @__PURE__ */ z(j, {
358
358
  variant: "outline",
@@ -360,7 +360,7 @@ var Ce = ({ schema: e, onRefresh: t }) => {
360
360
  onClick: f,
361
361
  "aria-label": `Print: ${d}`,
362
362
  title: d,
363
- children: [/* @__PURE__ */ R(re, { className: "h-4 w-4 mr-2" }), "Print"]
363
+ children: [/* @__PURE__ */ R(ie, { className: "h-4 w-4 mr-2" }), "Print"]
364
364
  }),
365
365
  a && n.showExportButtons && /* @__PURE__ */ z("div", {
366
366
  className: "flex items-center gap-1",
@@ -433,7 +433,7 @@ var Ce = ({ schema: e, onRefresh: t }) => {
433
433
  children: e.label || e.name
434
434
  }), /* @__PURE__ */ R("div", {
435
435
  className: "text-2xl font-bold",
436
- children: Y(m(e.name, e.aggregation), e, l)
436
+ children: J(m(e.name, e.aggregation), e, l)
437
437
  })]
438
438
  }) }, t))
439
439
  }),
@@ -448,8 +448,8 @@ var Ce = ({ schema: e, onRefresh: t }) => {
448
448
  children: e.label || e.name
449
449
  }, t)) })
450
450
  }), /* @__PURE__ */ R("tbody", { children: (() => {
451
- let t = xe(r || [], n.groupBy || []);
452
- return t ? t.map((t) => /* @__PURE__ */ z(x.Fragment, { children: [/* @__PURE__ */ R("tr", {
451
+ let t = we(r || [], n.groupBy || []);
452
+ return t ? t.map((t) => /* @__PURE__ */ z(S.Fragment, { children: [/* @__PURE__ */ R("tr", {
453
453
  className: "bg-muted/60",
454
454
  children: /* @__PURE__ */ z("td", {
455
455
  colSpan: e.columns?.length || 1,
@@ -484,7 +484,7 @@ var Ce = ({ schema: e, onRefresh: t }) => {
484
484
  children: /* @__PURE__ */ R("p", { children: e.text })
485
485
  }),
486
486
  e.type === "page-break" && /* @__PURE__ */ R("div", { className: "border-t-2 border-dashed my-8 print:page-break-after-always" }),
487
- Array.isArray(e.content) ? e.content.map((e, t) => /* @__PURE__ */ R(w, { schema: E(e) }, t)) : ee(e.content, (e) => /* @__PURE__ */ R(w, { schema: E(e) }))
487
+ Array.isArray(e.content) ? e.content.map((e, t) => /* @__PURE__ */ R(T, { schema: O(e) }, t)) : te(e.content, (e) => /* @__PURE__ */ R(T, { schema: O(e) }))
488
488
  ]
489
489
  }, t)),
490
490
  !n.sections && r && r.length > 0 && /* @__PURE__ */ R("div", {
@@ -516,29 +516,29 @@ var Ce = ({ schema: e, onRefresh: t }) => {
516
516
  };
517
517
  //#endregion
518
518
  //#region src/DatasetReportRenderer.tsx
519
- function we(e) {
519
+ function De(e) {
520
520
  if (!e || typeof e != "object") return !1;
521
521
  let t = e;
522
522
  return typeof t.dataset == "string" && t.dataset.length > 0 || t.type === "joined" && Array.isArray(t.blocks) && t.blocks.some((e) => typeof e?.dataset == "string");
523
523
  }
524
- var Te = /* @__PURE__ */ new Set(), Ee = () => globalThis.process?.env?.NODE_ENV !== "production";
525
- function De(e, t) {
526
- if (!Ee()) return;
524
+ var Oe = /* @__PURE__ */ new Set(), ke = () => globalThis.process?.env?.NODE_ENV !== "production";
525
+ function Ae(e, t) {
526
+ if (!ke()) return;
527
527
  let n = e.filter;
528
528
  if (n === void 0) return;
529
529
  let r = `${t}:${n && typeof n == "object" ? Object.keys(n).sort().join(",") : String(n)}`;
530
- Te.has(r) || (Te.add(r), console.warn(`[ObjectUI] ${t} carries \`filter\`, which is not an authorable key. Did you mean \`filter\` → \`runtimeFilter\`? NO filter was applied — it renders UNFILTERED, showing rows the report was scoped to exclude. \`ReportSchema\` (\`@objectstack/spec\`) is strict and rejects \`filter\`, so this document did not come through the validated path; the renderer no longer reads it either. Fix the producer: rename \`filter\` to \`runtimeFilter\`. (objectui#5137)`));
530
+ Oe.has(r) || (Oe.add(r), console.warn(`[ObjectUI] ${t} carries \`filter\`, which is not an authorable key. Did you mean \`filter\` → \`runtimeFilter\`? NO filter was applied — it renders UNFILTERED, showing rows the report was scoped to exclude. \`ReportSchema\` (\`@objectstack/spec\`) is strict and rejects \`filter\`, so this document did not come through the validated path; the renderer no longer reads it either. Fix the producer: rename \`filter\` to \`runtimeFilter\`. (objectui#5137)`));
531
531
  }
532
- function Oe(e) {
532
+ function je(e) {
533
533
  return `Report \`${e.name ?? "(unnamed)"}\``;
534
534
  }
535
- function ke(e, t) {
535
+ function Me(e, t) {
536
536
  return e ? typeof e == "string" ? e : typeof e == "object" && typeof e.default == "string" ? e.default : t : t;
537
537
  }
538
- function X(e) {
538
+ function Y(e) {
539
539
  return Array.isArray(e) ? e.filter((e) => typeof e == "string" && !!e) : [];
540
540
  }
541
- function Ae(e) {
541
+ function Ne(e) {
542
542
  if (!Array.isArray(e)) return;
543
543
  let t = {};
544
544
  for (let n of e) {
@@ -547,18 +547,51 @@ function Ae(e) {
547
547
  }
548
548
  return Object.keys(t).length > 0 ? t : void 0;
549
549
  }
550
- function je(e, t, n) {
550
+ function X(e, t, n) {
551
551
  if (!e) return;
552
552
  let r = /* @__PURE__ */ new Set([...t, ...n]), i = {};
553
553
  for (let [t, n] of Object.entries(e)) r.has(t) && (i[t] = n);
554
554
  return Object.keys(i).length > 0 ? i : void 0;
555
555
  }
556
- function Z(e, t, n, r, i, a, o) {
557
- let [s, c] = b.useState({
556
+ function Pe(e, t) {
557
+ let i = l(e?.metaByPath, e?.relabel, t);
558
+ if (!e) return {
559
+ dimensionLabels: i,
560
+ dimensionRanks: null
561
+ };
562
+ let a = {}, o = !1;
563
+ for (let { dim: i, path: s } of e.relabel) {
564
+ let c = e.metaByPath[s], l = p(c?.options, u(c, t)), d = r(n(l));
565
+ a[i] = d, d && (o = !0);
566
+ }
567
+ return {
568
+ dimensionLabels: i,
569
+ dimensionRanks: o ? a : null
570
+ };
571
+ }
572
+ function Fe(e, t) {
573
+ return e == null || e === "" ? 2 ** 53 - 1 : t.get(String(e)) ?? 2 ** 53 - 1 - 1;
574
+ }
575
+ function Z(e, t, n, r) {
576
+ if (!r || !t.some((e) => r[e])) return null;
577
+ let i = (a, o) => {
578
+ if (o >= t.length || a.length < 2) return a;
579
+ let s = t[o], c = /* @__PURE__ */ new Map();
580
+ for (let t of a) {
581
+ let r = g([v(n(e[t], s))]), i = c.get(r);
582
+ i ? i.push(t) : c.set(r, [t]);
583
+ }
584
+ let l = [...c.values()], u = r[s];
585
+ return u && l.sort((t, r) => Fe(n(e[t[0]], s), u) - Fe(n(e[r[0]], s), u)), l.flatMap((e) => i(e, o + 1));
586
+ };
587
+ return i(e.map((e, t) => t), 0);
588
+ }
589
+ function Ie(e, t, n, r, i, a, o) {
590
+ let [s, c] = x.useState({
558
591
  status: "idle",
559
592
  rows: []
560
- }), l = je(o, t, n), u = JSON.stringify(r ?? null), d = JSON.stringify(a ?? null), f = JSON.stringify(l ?? null), p = `${e}|${t.join(",")}|${n.join(",")}|${u}|${d}|${f}`, [m, h] = b.useState(void 0), g = D(m), _ = b.useRef(null);
561
- return b.useEffect(() => {
593
+ }), l = X(o, t, n), u = JSON.stringify(r ?? null), d = JSON.stringify(a ?? null), f = JSON.stringify(l ?? null), p = `${e}|${t.join(",")}|${n.join(",")}|${u}|${d}|${f}`, [m, h] = x.useState(void 0), g = k(m), _ = x.useRef(null);
594
+ return x.useEffect(() => {
562
595
  let o = i;
563
596
  if (!o || typeof o.queryDataset != "function") {
564
597
  _.current = null, h(void 0), c({
@@ -597,25 +630,35 @@ function Z(e, t, n, r, i, a, o) {
597
630
  totals: Array.isArray(e?.totals) ? e.totals : void 0
598
631
  }));
599
632
  }).catch((e) => {
600
- s || c({
601
- status: "error",
602
- rows: [],
603
- error: String(e?.message ?? e)
604
- });
633
+ if (!s) {
634
+ if (D(e) === "forbidden") {
635
+ c({
636
+ status: "error",
637
+ rows: [],
638
+ forbidden: !0
639
+ });
640
+ return;
641
+ }
642
+ c({
643
+ status: "error",
644
+ rows: [],
645
+ error: String(e?.message ?? e)
646
+ });
647
+ }
605
648
  }), () => {
606
649
  s = !0;
607
650
  };
608
651
  }, [p, g]), s;
609
652
  }
610
- function Me(...e) {
653
+ function Le(...e) {
611
654
  try {
612
- return i(...e);
655
+ return a(...e);
613
656
  } catch (e) {
614
657
  if (!(e instanceof t)) throw e;
615
658
  return console.warn(`[DatasetReportRenderer] drill-down refused — the drilled list cannot be scoped: ${e.message}`), null;
616
659
  }
617
660
  }
618
- function Ne({ dataset: e }) {
661
+ function Re({ dataset: e }) {
619
662
  return /* @__PURE__ */ z("div", {
620
663
  className: "flex items-center justify-center rounded-md border border-dashed bg-muted/20 p-4 text-xs text-muted-foreground",
621
664
  children: [
@@ -625,86 +668,106 @@ function Ne({ dataset: e }) {
625
668
  ]
626
669
  });
627
670
  }
628
- function Q({ status: e, error: t }) {
629
- return e === "error" ? /* @__PURE__ */ z("div", {
671
+ function ze() {
672
+ let e = W();
673
+ return /* @__PURE__ */ z("div", {
674
+ role: "alert",
675
+ "data-testid": "dataset-report-forbidden",
676
+ className: "flex flex-col items-center justify-center gap-1 rounded-md border border-dashed bg-muted/20 p-6 text-center text-xs text-muted-foreground",
677
+ children: [
678
+ /* @__PURE__ */ R(oe, {
679
+ className: "h-5 w-5 text-muted-foreground/70",
680
+ "aria-hidden": "true"
681
+ }),
682
+ /* @__PURE__ */ R("span", {
683
+ className: "font-medium text-foreground/80",
684
+ children: e("dashboard.widgetForbiddenTitle", "You don’t have access")
685
+ }),
686
+ /* @__PURE__ */ R("span", { children: e("report.forbiddenMessage", "You don’t have permission to view the data behind this report.") })
687
+ ]
688
+ });
689
+ }
690
+ function Q({ status: e, error: t, forbidden: n }) {
691
+ return e === "error" && n ? /* @__PURE__ */ R(ze, {}) : e === "error" ? /* @__PURE__ */ z("div", {
630
692
  role: "alert",
631
693
  className: "flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive",
632
- children: [/* @__PURE__ */ R(te, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), /* @__PURE__ */ R("span", {
694
+ children: [/* @__PURE__ */ R(ne, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), /* @__PURE__ */ R("span", {
633
695
  className: "break-words",
634
696
  children: t
635
697
  })]
636
698
  }) : /* @__PURE__ */ z("div", {
637
699
  className: "flex items-center gap-2 p-4 text-xs text-muted-foreground",
638
- children: [/* @__PURE__ */ R(ne, { className: "h-4 w-4 animate-spin" }), " Running report…"]
700
+ children: [/* @__PURE__ */ R(re, { className: "h-4 w-4 animate-spin" }), " Running report…"]
639
701
  });
640
702
  }
641
- function Pe() {
703
+ function Be() {
642
704
  return /* @__PURE__ */ z("div", {
643
705
  className: "flex flex-col items-center justify-center gap-2 rounded-md border border-dashed bg-muted/20 p-6 text-xs text-muted-foreground",
644
- children: [/* @__PURE__ */ R(ae, { className: "h-6 w-6" }), " The dataset returned no rows for this report’s scope."]
706
+ children: [/* @__PURE__ */ R(se, { className: "h-6 w-6" }), " The dataset returned no rows for this report’s scope."]
645
707
  });
646
708
  }
647
- var Fe = "cursor-pointer hover:bg-accent/40";
648
- function Ie({ dataset: e, rows: t, values: n, runtimeFilter: r, dataSource: i, onDrill: o, order: s, withTotals: c }) {
649
- let l = Z(e, t, n, r, i, c && t.length > 0 ? [[]] : void 0, s), { fieldLabel: f } = U(), p = W(), m = H(), h = O(l.object, l.dimensionFields, t);
650
- if (n.length === 0) return /* @__PURE__ */ R(Ne, { dataset: e });
709
+ var Ve = "cursor-pointer hover:bg-accent/40";
710
+ function He({ dataset: e, rows: t, values: n, runtimeFilter: r, dataSource: i, onDrill: a, order: s, withTotals: c }) {
711
+ let l = Ie(e, t, n, r, i, c && t.length > 0 ? [[]] : void 0, s), { fieldLabel: u, fieldOptionLabel: p } = U(), m = W(), h = H(), g = ee(l.object, l.dimensionFields, t), { dimensionLabels: _, dimensionRanks: v } = x.useMemo(() => Pe(g, p), [g, p]);
712
+ if (n.length === 0) return /* @__PURE__ */ R(Re, { dataset: e });
651
713
  if (l.status === "loading" || l.status === "idle") return /* @__PURE__ */ R(Q, { status: l.status });
652
714
  if (l.status === "error") return /* @__PURE__ */ R(Q, {
653
715
  status: "error",
654
- error: l.error
716
+ error: l.error,
717
+ forbidden: l.forbidden
655
718
  });
656
- if (l.rows.length === 0) return /* @__PURE__ */ R(Pe, {});
657
- let g = !!o && t.length > 0, _ = l.dimensionFields ? t.filter((e) => e in l.dimensionFields) : [], y = (n, i) => {
658
- let a = {};
659
- for (let e of t) a[e] = n[e];
719
+ if (l.rows.length === 0) return /* @__PURE__ */ R(Be, {});
720
+ let b = !!a && t.length > 0, S = l.dimensionFields ? t.filter((e) => e in l.dimensionFields) : [], C = (n, i) => {
721
+ let o = {};
722
+ for (let e of t) o[e] = n[e];
660
723
  let s = l.drillRanges?.[i], c = !!s && Object.keys(s).length > 0, u;
661
- if (l.object && (_.length > 0 || c)) {
662
- let e = Me(l.drillRawRows?.[i], _, l.dimensionFields ?? {}, r, s);
724
+ if (l.object && (S.length > 0 || c)) {
725
+ let e = Le(l.drillRawRows?.[i], S, l.dimensionFields ?? {}, r, s);
663
726
  if (e === null) return;
664
727
  u = e;
665
728
  }
666
- o({
729
+ a({
667
730
  dataset: e,
668
- groupKey: a,
731
+ groupKey: o,
669
732
  runtimeFilter: r,
670
733
  object: l.object,
671
734
  objectFilter: u
672
735
  });
673
- }, { measureField: b, headerLabel: x } = a(l.fields, l.object, f, V(p)), S = [...t, ...n], C = v(l.rows, h), w = c ? l.totals?.find((e) => Array.isArray(e.dimensions) && e.dimensions.length === 0)?.rows?.[0] : void 0, T = p("report.total", "Total");
736
+ }, { measureField: w, headerLabel: T } = o(l.fields, l.object, u, V(m)), E = [...t, ...n], D = y(l.rows, _), O = Z(D, t, (e, t) => e[t], X(s, t, n) ? null : v) ?? D.map((e, t) => t), k = c ? l.totals?.find((e) => Array.isArray(e.dimensions) && e.dimensions.length === 0)?.rows?.[0] : void 0, A = m("report.total", "Total");
674
737
  return /* @__PURE__ */ R("div", {
675
738
  className: "overflow-auto max-h-[70vh] rounded-md border",
676
739
  children: /* @__PURE__ */ z("table", {
677
740
  className: "w-full text-xs",
678
741
  children: [/* @__PURE__ */ R("thead", {
679
742
  className: "bg-muted/40",
680
- children: /* @__PURE__ */ R("tr", { children: S.map((e) => /* @__PURE__ */ R("th", {
743
+ children: /* @__PURE__ */ R("tr", { children: E.map((e) => /* @__PURE__ */ R("th", {
681
744
  className: "px-2 py-1.5 text-left font-medium whitespace-nowrap",
682
- children: x(e)
745
+ children: T(e)
683
746
  }, e)) })
684
- }), /* @__PURE__ */ z("tbody", { children: [C.map((e, t) => /* @__PURE__ */ R("tr", {
685
- className: `border-t${g ? ` ${Fe}` : ""}`,
686
- "data-testid": g ? "dataset-drill-row" : void 0,
687
- onClick: g ? () => y(l.rows[t], t) : void 0,
688
- children: S.map((t) => /* @__PURE__ */ R("td", {
747
+ }), /* @__PURE__ */ z("tbody", { children: [O.map((e) => /* @__PURE__ */ R("tr", {
748
+ className: `border-t${b ? ` ${Ve}` : ""}`,
749
+ "data-testid": b ? "dataset-drill-row" : void 0,
750
+ onClick: b ? () => C(l.rows[e], e) : void 0,
751
+ children: E.map((t) => /* @__PURE__ */ R("td", {
689
752
  className: "px-2 py-1 tabular-nums whitespace-nowrap",
690
- children: n.includes(t) ? d(e[t], b(t)?.format, b(t)?.currency, b(t)?.percentScale, m) : u(e[t], m)
753
+ children: n.includes(t) ? f(D[e][t], w(t)?.format, w(t)?.currency, w(t)?.percentScale, h) : d(D[e][t], h)
691
754
  }, t))
692
- }, t)), w && /* @__PURE__ */ z("tr", {
755
+ }, e)), k && /* @__PURE__ */ z("tr", {
693
756
  className: "border-t bg-muted/30 font-medium",
694
757
  "data-testid": "dataset-report-total-row",
695
758
  children: [t.length > 0 && /* @__PURE__ */ R("td", {
696
759
  colSpan: t.length,
697
760
  className: "px-2 py-1 whitespace-nowrap",
698
- children: T
761
+ children: A
699
762
  }), n.map((e) => /* @__PURE__ */ R("td", {
700
763
  className: "px-2 py-1 tabular-nums whitespace-nowrap",
701
- children: d(w[e], b(e)?.format, b(e)?.currency, b(e)?.percentScale, m)
764
+ children: f(k[e], w(e)?.format, w(e)?.currency, w(e)?.percentScale, h)
702
765
  }, e))]
703
766
  })] })]
704
767
  })
705
768
  });
706
769
  }
707
- function Le(e) {
770
+ function Ue(e) {
708
771
  switch (e) {
709
772
  case "summary": return "summary";
710
773
  case "matrix": return "matrix";
@@ -712,7 +775,7 @@ function Le(e) {
712
775
  default: return "tabular";
713
776
  }
714
777
  }
715
- function Re(e) {
778
+ function We(e) {
716
779
  switch (e) {
717
780
  case "bar":
718
781
  case "column":
@@ -743,9 +806,9 @@ function Re(e) {
743
806
  };
744
807
  }
745
808
  }
746
- function ze(t) {
747
- let [, n] = b.useReducer((e) => e + 1, 0);
748
- return b.useEffect(() => {
809
+ function Ge(t) {
810
+ let [, n] = x.useReducer((e) => e + 1, 0);
811
+ return x.useEffect(() => {
749
812
  if (e.get(t)) return;
750
813
  let r = typeof e.subscribe == "function" ? e.subscribe(() => {
751
814
  e.get(t) && n();
@@ -753,105 +816,105 @@ function ze(t) {
753
816
  return i && typeof i.then == "function" && i.then(() => n()).catch(() => {}), r;
754
817
  }, [t]), e.get(t);
755
818
  }
756
- function Be(e, t, n) {
819
+ function Ke(e, t, n) {
757
820
  if (Array.isArray(e) && t) for (let r of e) {
758
821
  if (!r || typeof r != "object") continue;
759
822
  let { name: e, label: i } = r;
760
- if (e === t) return ce(i, n) || void 0;
823
+ if (e === t) return ue(i, n) || void 0;
761
824
  }
762
825
  }
763
- function Ve({ dataset: e, chart: t, runtimeFilter: i, dataSource: u, order: m }) {
764
- let h = typeof t.xAxis == "string" ? t.xAxis : "", g = typeof t.yAxis == "string" ? t.yAxis : "", _ = Re(t.type), y = _.kind === "series" || _.kind === "single_value", x = Z(e, _.kind === "series" && h ? [h] : [], y && g ? [g] : [], i, u, void 0, m), S = ze("chart"), { fieldLabel: C, fieldOptionLabel: w } = U(), T = W(), E = H(), { language: D } = le(), O = b.useMemo(() => h ? [h] : [], [h]), A = k(x.object, x.dimensionFields, O), { categoryColors: j, dimensionLabels: M, categoryOrder: N } = b.useMemo(() => {
765
- if (!A) return {
826
+ function qe({ dataset: e, chart: t, runtimeFilter: a, dataSource: d, order: h }) {
827
+ let g = typeof t.xAxis == "string" ? t.xAxis : "", _ = typeof t.yAxis == "string" ? t.yAxis : "", v = We(t.type), b = v.kind === "series" || v.kind === "single_value", S = v.kind === "series" && g ? [g] : [], C = b && _ ? [_] : [], w = Ie(e, S, C, a, d, void 0, h), T = Ge("chart"), { fieldLabel: E, fieldOptionLabel: D } = U(), O = W(), k = H(), { language: A } = de(), j = x.useMemo(() => g ? [g] : [], [g]), M = ee(w.object, w.dimensionFields, j), { categoryColors: N, dimensionLabels: P, categoryOrder: F } = x.useMemo(() => {
828
+ if (!M) return {
766
829
  categoryColors: null,
767
830
  dimensionLabels: null,
768
831
  categoryOrder: null
769
832
  };
770
- let { metaByPath: e, relabel: t } = A, r = t[0]?.path, i = r ? e[r] : void 0, a = r ? f(i?.options, l(i, w)) : void 0;
833
+ let { metaByPath: e, relabel: t } = M, r = t[0]?.path, i = r ? e[r] : void 0, a = r ? p(i?.options, u(i, D)) : void 0;
771
834
  return {
772
- categoryColors: o(a),
773
- dimensionLabels: c(e, t, w),
835
+ categoryColors: s(a),
836
+ dimensionLabels: l(e, t, D),
774
837
  categoryOrder: n(a)
775
838
  };
776
- }, [A, w]), P = ce(t.title, D) || void 0;
777
- if (_.kind === "tabular") return null;
778
- if (_.kind === "unsupported") return /* @__PURE__ */ z("div", {
839
+ }, [M, D]), I = ue(t.title, A) || void 0;
840
+ if (v.kind === "tabular") return null;
841
+ if (v.kind === "unsupported") return /* @__PURE__ */ z("div", {
779
842
  className: "rounded-md border border-dashed bg-muted/20 px-3 py-2 text-xs text-muted-foreground",
780
843
  "data-testid": "dataset-report-chart-unsupported",
781
844
  children: [
782
845
  "Chart type “",
783
- _.type,
846
+ v.type,
784
847
  "” is not a spec chart type — the report’s table carries its numbers."
785
848
  ]
786
849
  });
787
- if (_.kind === "series" && !h || !g) return null;
788
- if (x.status === "loading" || x.status === "idle") return /* @__PURE__ */ z("div", {
850
+ if (v.kind === "series" && !g || !_) return null;
851
+ if (w.status === "loading" || w.status === "idle") return /* @__PURE__ */ z("div", {
789
852
  className: "flex items-center gap-2 p-4 text-xs text-muted-foreground",
790
- children: [/* @__PURE__ */ R(ne, { className: "h-4 w-4 animate-spin" }), " Loading chart…"]
853
+ children: [/* @__PURE__ */ R(re, { className: "h-4 w-4 animate-spin" }), " Loading chart…"]
791
854
  });
792
- if (x.status === "error" || x.rows.length === 0) return null;
793
- let { measureField: F, headerLabel: I } = a(x.fields, x.object, C, V(T)), L = Be(t.series, g, D) ?? I(g);
794
- if (_.kind === "single_value") {
795
- let e = F(g);
855
+ if (w.status === "error" || w.rows.length === 0) return null;
856
+ let { measureField: L, headerLabel: te } = o(w.fields, w.object, E, V(O)), ne = Ke(t.series, _, A) ?? te(_);
857
+ if (v.kind === "single_value") {
858
+ let e = L(_);
796
859
  return /* @__PURE__ */ z("div", {
797
860
  className: "rounded-md border bg-card p-3",
798
861
  "data-testid": "dataset-report-metric",
799
- children: [P ? /* @__PURE__ */ R("h3", {
862
+ children: [I ? /* @__PURE__ */ R("h3", {
800
863
  className: "mb-2 text-sm font-semibold",
801
- children: P
864
+ children: I
802
865
  }) : null, /* @__PURE__ */ z("div", {
803
866
  className: "flex flex-col gap-0.5 py-2",
804
867
  children: [/* @__PURE__ */ R("span", {
805
868
  className: "text-2xl font-semibold tabular-nums",
806
- children: d(x.rows[0]?.[g], e?.format, e?.currency, e?.percentScale, E)
869
+ children: f(w.rows[0]?.[_], e?.format, e?.currency, e?.percentScale, k)
807
870
  }), /* @__PURE__ */ R("span", {
808
871
  className: "text-xs text-muted-foreground",
809
- children: L
872
+ children: ne
810
873
  })]
811
874
  })]
812
875
  });
813
876
  }
814
- if (!S) return null;
815
- let { data: ee, xAxisKey: te, series: B } = r(v(x.rows, M), [h], [g], x.fields, {
816
- nullCategoryLabel: T("chart.nullCategory", "(None)"),
817
- builtinAggregateLabels: V(T)
818
- }), re = p(B, t.series).map((e) => e.dataKey === g ? {
877
+ if (!T) return null;
878
+ let B = y(w.rows, P), ie = X(h, S, C) ? null : r(F), ae = Z(B, [g], (e, t) => e[t], ie ? { [g]: ie } : null), oe = ae ? ae.map((e) => B[e]) : B, { data: se, xAxisKey: ce, series: le } = i(oe, [g], [_], w.fields, {
879
+ nullCategoryLabel: O("chart.nullCategory", "(None)"),
880
+ builtinAggregateLabels: V(O)
881
+ }), fe = m(le, t.series).map((e) => e.dataKey === _ ? {
819
882
  ...e,
820
- label: L
821
- } : e), { title: ie, ...ae } = s(t, j);
883
+ label: ne
884
+ } : e), { title: G, ...pe } = c(t, N);
822
885
  return /* @__PURE__ */ z("div", {
823
886
  className: "rounded-md border bg-card p-3",
824
887
  "data-testid": "dataset-report-chart",
825
- children: [P ? /* @__PURE__ */ R("h3", {
888
+ children: [I ? /* @__PURE__ */ R("h3", {
826
889
  className: "mb-2 text-sm font-semibold",
827
- children: P
828
- }) : null, /* @__PURE__ */ R(S, { schema: {
829
- chartType: _.chartType,
830
- data: ee,
831
- xAxisKey: te,
832
- series: re,
890
+ children: I
891
+ }) : null, /* @__PURE__ */ R(T, { schema: {
892
+ chartType: v.chartType,
893
+ data: se,
894
+ xAxisKey: ce,
895
+ series: fe,
833
896
  height: 280,
834
897
  isAnimationActive: !1,
835
- ...ae,
836
- ...N ? { categoryOrder: N } : {}
898
+ ...pe,
899
+ ...F ? { categoryOrder: F } : {}
837
900
  } })]
838
901
  });
839
902
  }
840
903
  function $(e, t) {
841
- return h(e.map((e) => _(t[e])));
904
+ return g(e.map((e) => v(t[e])));
842
905
  }
843
- function He(e, t, n) {
844
- return e.map((e) => u(t[e], n)).join(" / ");
906
+ function Je(e, t, n) {
907
+ return e.map((e) => d(t[e], n)).join(" / ");
845
908
  }
846
- function Ue({ dataset: e, rows: t, columnsAcross: n, values: r, runtimeFilter: i, dataSource: o, onDrill: s, order: c }) {
847
- let l = Z(e, [...t, ...n], r, i, o, [
909
+ function Ye({ dataset: e, rows: t, columnsAcross: n, values: r, runtimeFilter: i, dataSource: a, onDrill: s, order: c }) {
910
+ let l = Ie(e, [...t, ...n], r, i, a, [
848
911
  t,
849
912
  n,
850
913
  []
851
- ], c), f = W(), { fieldLabel: p } = U(), m = H(), h = O(l.object, l.dimensionFields, [...t, ...n]), _ = b.useMemo(() => {
914
+ ], c), u = W(), { fieldLabel: p, fieldOptionLabel: m } = U(), h = H(), g = ee(l.object, l.dimensionFields, [...t, ...n]), { dimensionLabels: v, dimensionRanks: b } = x.useMemo(() => Pe(g, m), [g, m]), S = X(c, [...t, ...n], r) !== void 0, C = x.useMemo(() => {
852
915
  if (l.status !== "ok") return null;
853
916
  let e = [], r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map();
854
- return v(l.rows, h).forEach((s, c) => {
917
+ y(l.rows, v).forEach((s, c) => {
855
918
  let u = l.rows[c], d = $(t, s), f = $(n, s);
856
919
  if (!i.has(d)) {
857
920
  i.add(d);
@@ -859,7 +922,7 @@ function Ue({ dataset: e, rows: t, columnsAcross: n, values: r, runtimeFilter: i
859
922
  for (let e of t) n[e] = u[e], r[e] = s[e];
860
923
  e.push({
861
924
  id: d,
862
- label: He(t, s, m),
925
+ label: Je(t, s, h),
863
926
  key: n,
864
927
  display: r
865
928
  });
@@ -870,38 +933,43 @@ function Ue({ dataset: e, rows: t, columnsAcross: n, values: r, runtimeFilter: i
870
933
  for (let r of n) e[r] = u[r], t[r] = s[r];
871
934
  r.push({
872
935
  id: f,
873
- label: He(n, s, m),
936
+ label: Je(n, s, h),
874
937
  key: e,
875
938
  display: t
876
939
  });
877
940
  }
878
- o.set(g(d, f), {
941
+ o.set(_(d, f), {
879
942
  row: u,
880
943
  index: c
881
944
  });
882
- }), {
883
- rowHeaders: e,
884
- colHeaders: r,
945
+ });
946
+ let s = S ? null : b, c = Z(e, t, (e, t) => e.display[t], s), u = Z(r, n, (e, t) => e.display[t], s);
947
+ return {
948
+ rowHeaders: c ? c.map((t) => e[t]) : e,
949
+ colHeaders: u ? u.map((e) => r[e]) : r,
885
950
  cells: o
886
951
  };
887
952
  }, [
888
953
  l,
889
954
  t,
890
955
  n,
891
- h,
892
- m
956
+ v,
957
+ b,
958
+ S,
959
+ h
893
960
  ]);
894
- if (r.length === 0) return /* @__PURE__ */ R(Ne, { dataset: e });
961
+ if (r.length === 0) return /* @__PURE__ */ R(Re, { dataset: e });
895
962
  if (l.status === "loading" || l.status === "idle") return /* @__PURE__ */ R(Q, { status: l.status });
896
963
  if (l.status === "error") return /* @__PURE__ */ R(Q, {
897
964
  status: "error",
898
- error: l.error
965
+ error: l.error,
966
+ forbidden: l.forbidden
899
967
  });
900
- if (!_ || _.rowHeaders.length === 0) return /* @__PURE__ */ R(Pe, {});
901
- let { measureField: y, headerLabel: x } = a(l.fields, l.object, p, V(f)), S = f("report.total", "Total"), C = !!s, w = l.dimensionFields ? [...t, ...n].filter((e) => e in l.dimensionFields) : [], T = (t, n, r) => {
968
+ if (!C || C.rowHeaders.length === 0) return /* @__PURE__ */ R(Be, {});
969
+ let { measureField: w, headerLabel: T } = o(l.fields, l.object, p, V(u)), E = u("report.total", "Total"), D = !!s, O = l.dimensionFields ? [...t, ...n].filter((e) => e in l.dimensionFields) : [], k = (t, n, r) => {
902
970
  let a = l.drillRanges?.[r], o = !!a && Object.keys(a).length > 0, c;
903
- if (l.object && (w.length > 0 || o)) {
904
- let e = Me(l.drillRawRows?.[r], w, l.dimensionFields ?? {}, i, a);
971
+ if (l.object && (O.length > 0 || o)) {
972
+ let e = Le(l.drillRawRows?.[r], O, l.dimensionFields ?? {}, i, a);
905
973
  if (e === null) return;
906
974
  c = e;
907
975
  }
@@ -915,18 +983,18 @@ function Ue({ dataset: e, rows: t, columnsAcross: n, values: r, runtimeFilter: i
915
983
  object: l.object,
916
984
  objectFilter: c
917
985
  });
918
- }, E = _.colHeaders.flatMap((e) => r.map((t) => ({
986
+ }, A = C.colHeaders.flatMap((e) => r.map((t) => ({
919
987
  col: e,
920
988
  measure: t,
921
- header: r.length === 1 ? e.label : `${e.label} · ${x(t)}`
922
- }))), D = (e) => {
989
+ header: r.length === 1 ? e.label : `${e.label} · ${T(t)}`
990
+ }))), j = (e) => {
923
991
  let t = l.totals?.find((t) => Array.isArray(t.dimensions) && t.dimensions.join(",") === e.join(","))?.rows;
924
- return t && v(t, h);
925
- }, k = /* @__PURE__ */ new Map();
926
- for (let e of D(t) ?? []) k.set($(t, e), e);
927
- let A = /* @__PURE__ */ new Map();
928
- for (let e of D(n) ?? []) A.set($(n, e), e);
929
- let j = D([])?.[0], M = k.size > 0, N = A.size > 0;
992
+ return t && y(t, v);
993
+ }, M = /* @__PURE__ */ new Map();
994
+ for (let e of j(t) ?? []) M.set($(t, e), e);
995
+ let N = /* @__PURE__ */ new Map();
996
+ for (let e of j(n) ?? []) N.set($(n, e), e);
997
+ let P = j([])?.[0], F = M.size > 0, I = N.size > 0;
930
998
  return /* @__PURE__ */ R("div", {
931
999
  className: "overflow-auto max-h-[70vh] rounded-md border",
932
1000
  "data-testid": "dataset-matrix",
@@ -937,67 +1005,67 @@ function Ue({ dataset: e, rows: t, columnsAcross: n, values: r, runtimeFilter: i
937
1005
  children: /* @__PURE__ */ z("tr", { children: [
938
1006
  t.map((e) => /* @__PURE__ */ R("th", {
939
1007
  className: "px-2 py-1.5 text-left font-medium whitespace-nowrap",
940
- children: x(e)
1008
+ children: T(e)
941
1009
  }, e)),
942
- E.map((e) => /* @__PURE__ */ R("th", {
1010
+ A.map((e) => /* @__PURE__ */ R("th", {
943
1011
  className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
944
1012
  children: e.header
945
1013
  }, `${e.col.id}-${e.measure}`)),
946
- M && r.map((e) => /* @__PURE__ */ R("th", {
1014
+ F && r.map((e) => /* @__PURE__ */ R("th", {
947
1015
  className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
948
1016
  "data-testid": "matrix-total-col-header",
949
- children: r.length === 1 ? S : `${S} · ${x(e)}`
1017
+ children: r.length === 1 ? E : `${E} · ${T(e)}`
950
1018
  }, `total-${e}`))
951
1019
  ] })
952
- }), /* @__PURE__ */ z("tbody", { children: [_.rowHeaders.map((e) => /* @__PURE__ */ z("tr", {
1020
+ }), /* @__PURE__ */ z("tbody", { children: [C.rowHeaders.map((e) => /* @__PURE__ */ z("tr", {
953
1021
  className: "border-t",
954
1022
  children: [
955
1023
  t.map((t) => /* @__PURE__ */ R("td", {
956
1024
  className: "px-2 py-1 whitespace-nowrap font-medium",
957
- children: u(e.display[t], m)
1025
+ children: d(e.display[t], h)
958
1026
  }, t)),
959
- E.map((t) => {
960
- let n = _.cells.get(g(e.id, t.col.id)), r = n?.row[t.measure], i = C && n != null;
1027
+ A.map((t) => {
1028
+ let n = C.cells.get(_(e.id, t.col.id)), r = n?.row[t.measure], i = D && n != null;
961
1029
  return /* @__PURE__ */ R("td", {
962
- className: `px-2 py-1 text-right tabular-nums whitespace-nowrap${i ? ` ${Fe}` : ""}`,
1030
+ className: `px-2 py-1 text-right tabular-nums whitespace-nowrap${i ? ` ${Ve}` : ""}`,
963
1031
  "data-testid": i ? "dataset-drill-cell" : void 0,
964
- onClick: i ? () => T(e.key, t.col.key, n.index) : void 0,
965
- children: d(r, y(t.measure)?.format, y(t.measure)?.currency, y(t.measure)?.percentScale, m)
1032
+ onClick: i ? () => k(e.key, t.col.key, n.index) : void 0,
1033
+ children: f(r, w(t.measure)?.format, w(t.measure)?.currency, w(t.measure)?.percentScale, h)
966
1034
  }, `${t.col.id}-${t.measure}`);
967
1035
  }),
968
- M && r.map((t) => /* @__PURE__ */ R("td", {
1036
+ F && r.map((t) => /* @__PURE__ */ R("td", {
969
1037
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap font-medium",
970
1038
  "data-testid": "matrix-row-total",
971
- children: d(k.get(e.id)?.[t], y(t)?.format, y(t)?.currency, y(t)?.percentScale, m)
1039
+ children: f(M.get(e.id)?.[t], w(t)?.format, w(t)?.currency, w(t)?.percentScale, h)
972
1040
  }, `total-${t}`))
973
1041
  ]
974
- }, e.id)), N && /* @__PURE__ */ z("tr", {
1042
+ }, e.id)), I && /* @__PURE__ */ z("tr", {
975
1043
  className: "border-t bg-muted/30 font-medium",
976
1044
  "data-testid": "matrix-total-row",
977
1045
  children: [
978
1046
  t.length > 0 && /* @__PURE__ */ R("td", {
979
1047
  colSpan: t.length,
980
1048
  className: "px-2 py-1 whitespace-nowrap",
981
- children: S
1049
+ children: E
982
1050
  }),
983
- E.map((e) => /* @__PURE__ */ R("td", {
1051
+ A.map((e) => /* @__PURE__ */ R("td", {
984
1052
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
985
- children: d(A.get(e.col.id)?.[e.measure], y(e.measure)?.format, y(e.measure)?.currency, y(e.measure)?.percentScale, m)
1053
+ children: f(N.get(e.col.id)?.[e.measure], w(e.measure)?.format, w(e.measure)?.currency, w(e.measure)?.percentScale, h)
986
1054
  }, `${e.col.id}-${e.measure}`)),
987
- M && r.map((e) => /* @__PURE__ */ R("td", {
1055
+ F && r.map((e) => /* @__PURE__ */ R("td", {
988
1056
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
989
1057
  "data-testid": "matrix-grand-total",
990
- children: d(j?.[e], y(e)?.format, y(e)?.currency, y(e)?.percentScale, m)
1058
+ children: f(P?.[e], w(e)?.format, w(e)?.currency, w(e)?.percentScale, h)
991
1059
  }, `grand-${e}`))
992
1060
  ]
993
1061
  })] })]
994
1062
  })
995
1063
  });
996
1064
  }
997
- var We = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i }) => {
998
- let a = Oe(e);
999
- De(e, a);
1000
- let o = m(e.runtimeFilter, n), s = e.drilldown === !1 ? void 0 : r, c = Le(e.type);
1065
+ var Xe = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i }) => {
1066
+ let a = je(e);
1067
+ Ae(e, a);
1068
+ let o = h(e.runtimeFilter, n), s = e.drilldown === !1 ? void 0 : r, c = Ue(e.type);
1001
1069
  if (c === "joined" && Array.isArray(e.blocks)) return /* @__PURE__ */ R("div", {
1002
1070
  className: i,
1003
1071
  "data-testid": "dataset-joined-report",
@@ -1008,20 +1076,20 @@ var We = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i
1008
1076
  gap: 24
1009
1077
  },
1010
1078
  children: e.blocks.map((e, n) => {
1011
- De(e, `${a} block \`${e.name ?? n}\``);
1012
- let r = m(o, e.runtimeFilter), i = X(e.columns), c = Ae(e.order), l = Le(e.type), u = l === "matrix" && i.length > 0 ? /* @__PURE__ */ R(Ue, {
1079
+ Ae(e, `${a} block \`${e.name ?? n}\``);
1080
+ let r = h(o, e.runtimeFilter), i = Y(e.columns), c = Ne(e.order), l = Ue(e.type), u = l === "matrix" && i.length > 0 ? /* @__PURE__ */ R(Ye, {
1013
1081
  dataset: String(e.dataset ?? ""),
1014
- rows: X(e.rows),
1082
+ rows: Y(e.rows),
1015
1083
  columnsAcross: i,
1016
- values: X(e.values),
1084
+ values: Y(e.values),
1017
1085
  runtimeFilter: r,
1018
1086
  dataSource: t,
1019
1087
  onDrill: s,
1020
1088
  order: c
1021
- }) : /* @__PURE__ */ R(Ie, {
1089
+ }) : /* @__PURE__ */ R(He, {
1022
1090
  dataset: String(e.dataset ?? ""),
1023
- rows: X(e.rows),
1024
- values: X(e.values),
1091
+ rows: Y(e.rows),
1092
+ values: Y(e.values),
1025
1093
  runtimeFilter: r,
1026
1094
  dataSource: t,
1027
1095
  onDrill: s,
@@ -1036,34 +1104,34 @@ var We = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i
1036
1104
  className: "flex flex-col gap-0.5",
1037
1105
  children: [/* @__PURE__ */ R("h3", {
1038
1106
  className: "text-sm font-semibold",
1039
- children: ke(e.label, e.name ?? `Block ${n + 1}`)
1107
+ children: Me(e.label, e.name ?? `Block ${n + 1}`)
1040
1108
  }), e.description ? /* @__PURE__ */ R("p", {
1041
1109
  className: "text-xs text-muted-foreground",
1042
- children: ke(e.description, "")
1110
+ children: Me(e.description, "")
1043
1111
  }) : null]
1044
1112
  }), u]
1045
1113
  }, e.name ?? `block-${n}`);
1046
1114
  })
1047
1115
  });
1048
- let l = X(e.columns), u = Ae(e.order), d = c === "matrix" && l.length > 0, f = e.chart && typeof e.chart == "object" && e.chart.type ? e.chart : null, p = f ? /* @__PURE__ */ R(Ve, {
1116
+ let l = Y(e.columns), u = Ne(e.order), d = c === "matrix" && l.length > 0, f = e.chart && typeof e.chart == "object" && e.chart.type ? e.chart : null, p = f ? /* @__PURE__ */ R(qe, {
1049
1117
  dataset: String(e.dataset ?? ""),
1050
1118
  chart: f,
1051
1119
  runtimeFilter: o,
1052
1120
  dataSource: t,
1053
1121
  order: u
1054
- }) : null, h = d ? /* @__PURE__ */ R(Ue, {
1122
+ }) : null, m = d ? /* @__PURE__ */ R(Ye, {
1055
1123
  dataset: String(e.dataset ?? ""),
1056
- rows: X(e.rows),
1124
+ rows: Y(e.rows),
1057
1125
  columnsAcross: l,
1058
- values: X(e.values),
1126
+ values: Y(e.values),
1059
1127
  runtimeFilter: o,
1060
1128
  dataSource: t,
1061
1129
  onDrill: s,
1062
1130
  order: u
1063
- }) : /* @__PURE__ */ R(Ie, {
1131
+ }) : /* @__PURE__ */ R(He, {
1064
1132
  dataset: String(e.dataset ?? ""),
1065
- rows: X(e.rows),
1066
- values: X(e.values),
1133
+ rows: Y(e.rows),
1134
+ values: Y(e.values),
1067
1135
  runtimeFilter: o,
1068
1136
  dataSource: t,
1069
1137
  onDrill: s,
@@ -1075,39 +1143,39 @@ var We = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i
1075
1143
  "data-testid": "dataset-report",
1076
1144
  "data-report-name": e.name,
1077
1145
  "data-report-presentation": c,
1078
- children: [d ? h : p, d ? p : h]
1146
+ children: [d ? m : p, d ? p : m]
1079
1147
  });
1080
- }, Ge = (e) => {
1081
- let { dataSource: t, rows: n, runtimeFilter: r, onDrill: i, className: a } = e, o = b.useContext(T), s = t ?? o?.dataSource, c = e.schema;
1082
- if (c && typeof c == "object" && c.type === "report" && c.report && typeof c.report == "object" && (c = c.report), we(c)) return /* @__PURE__ */ R(We, {
1148
+ }, Ze = (e) => {
1149
+ let { dataSource: t, rows: n, runtimeFilter: r, onDrill: i, className: a } = e, o = x.useContext(E), s = t ?? o?.dataSource, c = e.schema;
1150
+ if (c && typeof c == "object" && c.type === "report" && c.report && typeof c.report == "object" && (c = c.report), De(c)) return /* @__PURE__ */ R(Xe, {
1083
1151
  report: c,
1084
1152
  dataSource: s,
1085
1153
  runtimeFilter: r,
1086
1154
  onDrill: i,
1087
1155
  className: a
1088
1156
  });
1089
- if (S(c)) {
1157
+ if (C(c)) {
1090
1158
  let e = {
1091
1159
  type: "report-viewer",
1092
- report: C(c),
1160
+ report: w(c),
1093
1161
  data: n ?? [],
1094
1162
  showToolbar: !1
1095
1163
  };
1096
1164
  return /* @__PURE__ */ R("div", {
1097
1165
  className: a,
1098
1166
  "data-testid": "report-presentation-bridge",
1099
- children: /* @__PURE__ */ R(Ce, { schema: e })
1167
+ children: /* @__PURE__ */ R(Ee, { schema: e })
1100
1168
  });
1101
1169
  }
1102
- return /* @__PURE__ */ R(ue, { schema: c });
1170
+ return /* @__PURE__ */ R(fe, { schema: c });
1103
1171
  };
1104
1172
  //#endregion
1105
1173
  //#region src/LiveReportExporter.ts
1106
- async function Ke(e, t) {
1174
+ async function Qe(e, t) {
1107
1175
  let { dataSource: n, resource: r, queryParams: i, format: a, exportConfig: o, locale: s } = t, c = a || e.defaultExportFormat || "pdf";
1108
1176
  try {
1109
1177
  let t = (await n.find(r, i)).data || [];
1110
- return he(c, e, t, {
1178
+ return ve(c, e, t, {
1111
1179
  format: c,
1112
1180
  ...e.exportConfigs?.[c],
1113
1181
  ...o
@@ -1125,17 +1193,17 @@ async function Ke(e, t) {
1125
1193
  };
1126
1194
  }
1127
1195
  }
1128
- function qe(e, t, n = {}) {
1129
- let { columns: r, filename: i, includeAggregationRow: a = !1, locale: o = "en" } = n, s = r || (e.fields || []).map(Ye), c = s.map((e) => e.header), l = t.map((e, t) => s.map((n) => {
1196
+ function $e(e, t, n = {}) {
1197
+ let { columns: r, filename: i, includeAggregationRow: a = !1, locale: o = "en" } = n, s = r || (e.fields || []).map(tt), c = s.map((e) => e.header), l = t.map((e, t) => s.map((n) => {
1130
1198
  if (n.formula) return n.formula.replace(/\{ROW\}/g, String(t + 2));
1131
1199
  let r = e[n.name];
1132
- return Xe(r, n.numberFormat, o);
1200
+ return nt(r, n.numberFormat, o);
1133
1201
  }));
1134
1202
  if (a && t.length > 0) {
1135
1203
  let n = s.map((n, r) => {
1136
1204
  let i = (e.fields || []).find((e) => e.name === n.name);
1137
1205
  if (i?.aggregation) {
1138
- let e = Qe(r), n = t.length + 1;
1206
+ let e = it(r), n = t.length + 1;
1139
1207
  switch (i.aggregation) {
1140
1208
  case "sum": return `=SUM(${e}2:${e}${n})`;
1141
1209
  case "avg": return `=AVERAGE(${e}2:${e}${n})`;
@@ -1149,15 +1217,15 @@ function qe(e, t, n = {}) {
1149
1217
  });
1150
1218
  l.push(n);
1151
1219
  }
1152
- et("" + [c.join(" "), ...l.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
1220
+ ot("" + [c.join(" "), ...l.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
1153
1221
  }
1154
- function Je(e, t, n, r) {
1222
+ function et(e, t, n, r) {
1155
1223
  return async () => {
1156
1224
  let i = e.schedule;
1157
1225
  if (!i?.enabled) return [];
1158
1226
  let a = i.formats || [e.defaultExportFormat || "pdf"], o = [];
1159
1227
  for (let r of a) {
1160
- let i = await Ke(e, {
1228
+ let i = await Qe(e, {
1161
1229
  dataSource: t,
1162
1230
  resource: n,
1163
1231
  format: r
@@ -1167,16 +1235,16 @@ function Je(e, t, n, r) {
1167
1235
  return r(e, i), o;
1168
1236
  };
1169
1237
  }
1170
- function Ye(e) {
1238
+ function tt(e) {
1171
1239
  return {
1172
1240
  name: e.name,
1173
1241
  header: e.label || e.name
1174
1242
  };
1175
1243
  }
1176
- function Xe(e, t, n = "en") {
1177
- return e == null ? "" : typeof e == "number" && t ? G(e, n, Ze(t)) : $e(String(e));
1244
+ function nt(e, t, n = "en") {
1245
+ return e == null ? "" : typeof e == "number" && t ? G(e, n, rt(t)) : at(String(e));
1178
1246
  }
1179
- function Ze(e) {
1247
+ function rt(e) {
1180
1248
  if (e.includes("%")) return {
1181
1249
  style: "percent",
1182
1250
  minimumFractionDigits: 0
@@ -1187,23 +1255,23 @@ function Ze(e) {
1187
1255
  maximumFractionDigits: Math.max(0, t - 1)
1188
1256
  };
1189
1257
  }
1190
- function Qe(e) {
1258
+ function it(e) {
1191
1259
  let t = "", n = e;
1192
1260
  for (; n >= 0;) t = String.fromCharCode(n % 26 + 65) + t, n = Math.floor(n / 26) - 1;
1193
1261
  return t;
1194
1262
  }
1195
- function $e(e) {
1263
+ function at(e) {
1196
1264
  if (e.length > 0) {
1197
1265
  let t = e.charAt(0);
1198
1266
  if (t === "=" || t === "+" || t === "-" || t === "@" || t === "|") return `'${e}`;
1199
1267
  }
1200
1268
  return e;
1201
1269
  }
1202
- function et(e, t, n) {
1270
+ function ot(e, t, n) {
1203
1271
  let r = new Blob([e], { type: `${n};charset=utf-8` }), i = URL.createObjectURL(r), a = document.createElement("a");
1204
1272
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
1205
1273
  }
1206
- e.register("report", Ge, {
1274
+ e.register("report", Ze, {
1207
1275
  namespace: "plugin-report",
1208
1276
  label: "Report",
1209
1277
  category: "Report",
@@ -1226,7 +1294,7 @@ e.register("report", Ge, {
1226
1294
  description: "The report to render, as `@objectstack/spec` declares it (`ReportSchema`: `name`, `label`, `type`, `dataset`, `rows`, `values`, …). When present, the block renders this report and reads none of its own presentation inputs."
1227
1295
  }
1228
1296
  ]
1229
- }), e.register("report-viewer", Ce, {
1297
+ }), e.register("report-viewer", Ee, {
1230
1298
  namespace: "plugin-report",
1231
1299
  label: "Report Viewer",
1232
1300
  category: "Report",
@@ -1239,4 +1307,4 @@ e.register("report", Ge, {
1239
1307
  }]
1240
1308
  });
1241
1309
  //#endregion
1242
- export { We as DatasetReportRenderer, ue as LegacyReportRenderer, Ge as ReportRenderer, Ce as ReportViewer, Je as createScheduleTrigger, de as exportAsCSV, me as exportAsExcel, K as exportAsHTML, fe as exportAsJSON, pe as exportAsPDF, qe as exportExcelWithFormulas, he as exportReport, Ke as exportWithLiveData, Y as formatValue, we as isDatasetReport, m as mergeFilters };
1310
+ export { Xe as DatasetReportRenderer, fe as LegacyReportRenderer, Ze as ReportRenderer, Ee as ReportViewer, et as createScheduleTrigger, pe as exportAsCSV, _e as exportAsExcel, he as exportAsHTML, me as exportAsJSON, ge as exportAsPDF, $e as exportExcelWithFormulas, ve as exportReport, Qe as exportWithLiveData, J as formatValue, De as isDatasetReport, h as mergeFilters };