@object-ui/plugin-report 16.1.0 → 17.1.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
@@ -6,10 +6,10 @@ import { SchemaRenderer as u, SchemaRendererContext as d } from "@object-ui/reac
6
6
  import { Badge as f, Button as p, Card as m, CardContent as h, CardDescription as g, CardHeader as _, CardTitle as v, Skeleton as y } from "@object-ui/components";
7
7
  import { jsx as b, jsxs as x } from "react/jsx-runtime";
8
8
  import { AlertTriangle as S, Download as C, Loader2 as w, Printer as T, RefreshCw as E, Table2 as D } from "lucide-react";
9
- import { getCellRenderer as O, resolveCellRendererType as k } from "@object-ui/fields";
10
- import { useSafeFieldLabel as A, useSafeTranslate as j } from "@object-ui/i18n";
9
+ import { getCellRenderer as O, resolveCellRendererType as ee } from "@object-ui/fields";
10
+ import { useSafeFieldLabel as k, useSafeTranslate as A } from "@object-ui/i18n";
11
11
  //#region src/LegacyReportRenderer.tsx
12
- var M = ({ schema: t }) => {
12
+ var j = ({ 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;
@@ -64,29 +64,29 @@ var M = ({ schema: t }) => {
64
64
  };
65
65
  //#endregion
66
66
  //#region src/ReportExportEngine.ts
67
- function N(e, t, n) {
67
+ function M(e, t, n) {
68
68
  let r = e.fields || [], i = r.map((e) => e.label || e.name), a = t.map((e) => r.map((t) => {
69
69
  let n = e[t.name];
70
- return n = z(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
70
+ return n = R(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
71
71
  }));
72
- V([...n?.includeHeaders === !1 ? [] : [i.join(",")], ...a.map((e) => e.join(","))].join("\n"), n?.filename || `${e.title || "report"}.csv`, "text/csv");
72
+ z([...n?.includeHeaders === !1 ? [] : [i.join(",")], ...a.map((e) => e.join(","))].join("\n"), n?.filename || `${e.title || "report"}.csv`, "text/csv");
73
73
  }
74
- function P(e, t, n) {
74
+ function N(e, t, n) {
75
75
  let r = {
76
76
  title: e.title,
77
77
  description: e.description,
78
78
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
79
79
  data: t
80
80
  };
81
- V(JSON.stringify(r, null, 2), n?.filename || `${e.title || "report"}.json`, "application/json");
81
+ z(JSON.stringify(r, null, 2), n?.filename || `${e.title || "report"}.json`, "application/json");
82
82
  }
83
- function F(e, t, n) {
84
- let r = e.fields || [], i = te(n?.orientation), a = B(n?.pageSize);
85
- V(`<!DOCTYPE html>
83
+ function P(e, t, n) {
84
+ let r = e.fields || [], i = re(n?.orientation), a = ne(n?.pageSize);
85
+ z(`<!DOCTYPE html>
86
86
  <html>
87
87
  <head>
88
88
  <meta charset="utf-8">
89
- <title>${R(e.title || "Report")}</title>
89
+ <title>${L(e.title || "Report")}</title>
90
90
  <style>
91
91
  @page { size: ${a} ${i}; margin: 20mm; }
92
92
  body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #333; }
@@ -100,20 +100,20 @@ function F(e, t, n) {
100
100
  </style>
101
101
  </head>
102
102
  <body>
103
- <h1>${R(e.title || "Report")}</h1>
104
- ${e.description ? `<p class="description">${R(e.description)}</p>` : ""}
103
+ <h1>${L(e.title || "Report")}</h1>
104
+ ${e.description ? `<p class="description">${L(e.description)}</p>` : ""}
105
105
  <p class="meta">Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}</p>
106
106
  <table>
107
- <thead><tr>${r.map((e) => `<th>${R(e.label || e.name)}</th>`).join("")}</tr></thead>
108
- <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${R(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
107
+ <thead><tr>${r.map((e) => `<th>${L(e.label || e.name)}</th>`).join("")}</tr></thead>
108
+ <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${L(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
109
109
  </table>
110
110
  </body>
111
111
  </html>`, n?.filename || `${e.title || "report"}.html`, "text/html");
112
112
  }
113
- function ee(e, t, n) {
114
- let r = e.fields || [], i = te(n?.orientation), a = B(n?.pageSize), o = window.open("", "_blank");
113
+ function te(e, t, n) {
114
+ let r = e.fields || [], i = re(n?.orientation), a = ne(n?.pageSize), o = window.open("", "_blank");
115
115
  if (!o) {
116
- F(e, t, {
116
+ P(e, t, {
117
117
  ...n,
118
118
  format: "html",
119
119
  filename: n?.filename?.replace(/\.pdf$/, ".html") || `${e.title || "report"}.html`
@@ -124,7 +124,7 @@ function ee(e, t, n) {
124
124
  <html>
125
125
  <head>
126
126
  <meta charset="utf-8">
127
- <title>${R(e.title || "Report")}</title>
127
+ <title>${L(e.title || "Report")}</title>
128
128
  <style>
129
129
  @page { size: ${a} ${i}; margin: 20mm; }
130
130
  @media print { .no-print { display: none; } }
@@ -139,56 +139,56 @@ function ee(e, t, n) {
139
139
  </style>
140
140
  </head>
141
141
  <body>
142
- <h1>${R(e.title || "Report")}</h1>
143
- ${e.description ? `<p class="description">${R(e.description)}</p>` : ""}
142
+ <h1>${L(e.title || "Report")}</h1>
143
+ ${e.description ? `<p class="description">${L(e.description)}</p>` : ""}
144
144
  <p class="meta">Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}</p>
145
145
  <table>
146
- <thead><tr>${r.map((e) => `<th>${R(e.label || e.name)}</th>`).join("")}</tr></thead>
147
- <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${R(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
146
+ <thead><tr>${r.map((e) => `<th>${L(e.label || e.name)}</th>`).join("")}</tr></thead>
147
+ <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${L(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
148
148
  </table>
149
149
  </body>
150
150
  </html>`), o.document.close(), o.onload = () => {
151
151
  o.print();
152
152
  };
153
153
  }
154
- function I(e, t, n) {
154
+ function F(e, t, n) {
155
155
  let r = e.fields || [], i = r.map((e) => e.label || e.name), a = t.map((e) => r.map((t) => {
156
156
  let n = e[t.name];
157
- return n = z(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n") || n.includes(" ")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
157
+ return n = R(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n") || n.includes(" ")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
158
158
  }));
159
- V("" + [...n?.includeHeaders === !1 ? [] : [i.join(" ")], ...a.map((e) => e.join(" "))].join("\n"), n?.filename || `${e.title || "report"}.tsv`, "text/tab-separated-values");
159
+ z("" + [...n?.includeHeaders === !1 ? [] : [i.join(" ")], ...a.map((e) => e.join(" "))].join("\n"), n?.filename || `${e.title || "report"}.tsv`, "text/tab-separated-values");
160
160
  }
161
- function L(e, t, n, r) {
161
+ function I(e, t, n, r) {
162
162
  switch (e) {
163
163
  case "csv":
164
- N(t, n, r);
164
+ M(t, n, r);
165
165
  break;
166
166
  case "json":
167
- P(t, n, r);
167
+ N(t, n, r);
168
168
  break;
169
169
  case "html":
170
- F(t, n, r);
170
+ P(t, n, r);
171
171
  break;
172
172
  case "pdf":
173
- ee(t, n, r);
173
+ te(t, n, r);
174
174
  break;
175
175
  case "excel":
176
- I(t, n, r);
176
+ F(t, n, r);
177
177
  break;
178
178
  default: console.warn(`Unsupported export format: ${e}`);
179
179
  }
180
180
  }
181
- function R(e) {
181
+ function L(e) {
182
182
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
183
183
  }
184
- function z(e) {
184
+ function R(e) {
185
185
  if (typeof e == "string" && e.length > 0) {
186
186
  let t = e.charAt(0);
187
187
  if (t === "=" || t === "+" || t === "-" || t === "@" || t === "|") return `\t${e}`;
188
188
  }
189
189
  return e;
190
190
  }
191
- function B(e) {
191
+ function ne(e) {
192
192
  return [
193
193
  "A4",
194
194
  "A3",
@@ -196,19 +196,19 @@ function B(e) {
196
196
  "Legal"
197
197
  ].includes(e || "") ? e : "A4";
198
198
  }
199
- function te(e) {
199
+ function re(e) {
200
200
  return e === "landscape" ? "landscape" : "portrait";
201
201
  }
202
- function V(e, t, n) {
202
+ function z(e, t, n) {
203
203
  let r = new Blob([e], { type: `${n};charset=utf-8` }), i = URL.createObjectURL(r), a = document.createElement("a");
204
204
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
205
205
  }
206
206
  //#endregion
207
207
  //#region src/formatValue.ts
208
- function H(e, t) {
208
+ function B(e, t) {
209
209
  if (e == null || e === "") return "";
210
210
  let n = t?.type, r = t?.format;
211
- if (n === "date" || r === "date" || ne(e)) return re(e);
211
+ if (n === "date" || r === "date" || ie(e)) return ae(e);
212
212
  if (n === "number" || typeof e == "number") {
213
213
  let t = typeof e == "number" ? e : Number(e);
214
214
  return isNaN(t) ? String(e) : r === "currency" || r === "currency_cny" ? `¥${t.toLocaleString("en-US", {
@@ -224,10 +224,10 @@ function H(e, t) {
224
224
  }
225
225
  return String(e);
226
226
  }
227
- function ne(e) {
227
+ function ie(e) {
228
228
  return typeof e == "string" && /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/.test(e);
229
229
  }
230
- function re(e) {
230
+ function ae(e) {
231
231
  try {
232
232
  let t = new Date(e);
233
233
  return isNaN(t.getTime()) ? String(e) : `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`;
@@ -237,7 +237,7 @@ function re(e) {
237
237
  }
238
238
  //#endregion
239
239
  //#region src/ReportViewer.tsx
240
- function ie(e, t) {
240
+ function oe(e, t) {
241
241
  if (!t || t.length === 0 || !e || e.length === 0) return null;
242
242
  let n = t[0], r = n.field, i = /* @__PURE__ */ new Map();
243
243
  for (let t of e) {
@@ -253,129 +253,131 @@ function ie(e, t) {
253
253
  let o = n.sort === "desc" ? -1 : 1;
254
254
  return a.sort((e, t) => e.key.localeCompare(t.key) * o), a;
255
255
  }
256
- var U = ({ schema: t, onRefresh: n }) => {
257
- let { report: r, data: i, showToolbar: a = !0, allowExport: o = !0, allowPrint: c = !0, loading: l = !1 } = t, d = (e) => {
258
- if (!r) {
256
+ function se(e, t, n) {
257
+ if (!e) return 0;
258
+ let r = e.map((e) => Number(e[t]) || 0);
259
+ switch (n) {
260
+ case "count": return e.length;
261
+ case "sum": return r.reduce((e, t) => e + t, 0);
262
+ case "avg": return r.length > 0 ? (r.reduce((e, t) => e + t, 0) / r.length).toFixed(2) : 0;
263
+ case "min": return r.length > 0 ? Math.min(...r) : 0;
264
+ case "max": return r.length > 0 ? Math.max(...r) : 0;
265
+ case "distinct": return new Set(e.map((e) => e[t])).size;
266
+ default: return "";
267
+ }
268
+ }
269
+ var V = ({ schema: e, onRefresh: t }) => {
270
+ let { report: n, data: r, showToolbar: i = !0, allowExport: a = !0, allowPrint: o = !0, loading: c = !1 } = e, l = (e) => {
271
+ if (!n) {
259
272
  console.warn("ReportViewer: Cannot export, no report defined");
260
273
  return;
261
274
  }
262
- L(e, r, i || [], r.exportConfigs?.[e]);
263
- }, S = () => {
275
+ I(e, n, r || [], n.exportConfigs?.[e]);
276
+ }, d = () => {
264
277
  window.print();
265
- }, w = () => {
266
- n?.();
267
- }, D = (e, t) => {
268
- if (!i) return 0;
269
- let n = i.map((t) => Number(t[e]) || 0);
270
- switch (t) {
271
- case "count": return i.length;
272
- case "sum": return n.reduce((e, t) => e + t, 0);
273
- case "avg": return n.length > 0 ? (n.reduce((e, t) => e + t, 0) / n.length).toFixed(2) : 0;
274
- case "min": return n.length > 0 ? Math.min(...n) : 0;
275
- case "max": return n.length > 0 ? Math.max(...n) : 0;
276
- default: return "";
277
- }
278
- }, A = (e, t) => {
279
- let n = r?.conditionalFormatting;
280
- if (!(!n || !Array.isArray(n))) for (let r of n) {
281
- if (r.field !== e) continue;
282
- let n = String(t ?? ""), i = String(r.value ?? ""), a = !1;
283
- switch (r.operator) {
278
+ }, S = () => {
279
+ t?.();
280
+ }, w = (e, t) => se(r, e, t), D = (e, t) => {
281
+ let r = n?.conditionalFormatting;
282
+ if (!(!r || !Array.isArray(r))) for (let n of r) {
283
+ if (n.field !== e) continue;
284
+ let r = String(t ?? ""), i = String(n.value ?? ""), a = !1;
285
+ switch (n.operator) {
284
286
  case "equals":
285
- a = n === i;
287
+ a = r === i;
286
288
  break;
287
289
  case "not_equals":
288
- a = n !== i;
290
+ a = r !== i;
289
291
  break;
290
292
  case "contains":
291
- a = n.includes(i);
293
+ a = r.includes(i);
292
294
  break;
293
295
  case "greater_than":
294
- a = Number(t) > Number(r.value);
296
+ a = Number(t) > Number(n.value);
295
297
  break;
296
298
  case "less_than":
297
- a = Number(t) < Number(r.value);
299
+ a = Number(t) < Number(n.value);
298
300
  break;
299
301
  }
300
302
  if (a) {
301
303
  let e = {};
302
- return r.backgroundColor && (e.backgroundColor = r.backgroundColor), r.textColor && (e.color = r.textColor), e;
304
+ return n.backgroundColor && (e.backgroundColor = n.backgroundColor), n.textColor && (e.color = n.textColor), e;
303
305
  }
304
306
  }
305
- }, j = (e, t) => {
307
+ }, k = (e, t) => {
306
308
  if (e == null || e === "") return "";
307
309
  if (t.renderAs === "badge" && (!t.type || t.type === "string" || t.type === "text")) return /* @__PURE__ */ b(f, {
308
310
  className: t.colorMap?.[String(e)] || "",
309
311
  children: String(e)
310
312
  });
311
- if (t.aggregation) return H(e, t);
313
+ if (t.aggregation) return B(e, t);
312
314
  if (t.type) {
313
315
  let n = { ...t };
314
316
  return t.colorMap && !n.options && (n.options = Object.entries(t.colorMap).map(([e, t]) => ({
315
317
  value: e,
316
318
  label: e,
317
319
  color: t
318
- }))), /* @__PURE__ */ b(O(k(n)), {
320
+ }))), /* @__PURE__ */ b(O(ee(n)), {
319
321
  value: e,
320
322
  field: n
321
323
  });
322
324
  }
323
- return H(e, t);
325
+ return B(e, t);
324
326
  };
325
- return r ? /* @__PURE__ */ x("div", {
327
+ return n ? /* @__PURE__ */ x("div", {
326
328
  className: "space-y-4",
327
- children: [a && /* @__PURE__ */ x("div", {
329
+ children: [i && /* @__PURE__ */ x("div", {
328
330
  className: "flex items-center justify-between gap-2 p-4 bg-card rounded-lg border",
329
331
  children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h2", {
330
332
  className: "text-lg font-semibold",
331
- children: r.title
332
- }), r.description && /* @__PURE__ */ b("p", {
333
+ children: n.title
334
+ }), n.description && /* @__PURE__ */ b("p", {
333
335
  className: "text-sm text-muted-foreground",
334
- children: r.description
336
+ children: n.description
335
337
  })] }), /* @__PURE__ */ x("div", {
336
338
  className: "flex items-center gap-2",
337
339
  children: [
338
- r.refreshInterval && /* @__PURE__ */ x(p, {
340
+ n.refreshInterval && /* @__PURE__ */ x(p, {
339
341
  variant: "outline",
340
342
  size: "sm",
341
- onClick: w,
343
+ onClick: S,
342
344
  children: [/* @__PURE__ */ b(E, { className: "h-4 w-4 mr-2" }), "Refresh"]
343
345
  }),
344
- c && /* @__PURE__ */ x(p, {
346
+ o && /* @__PURE__ */ x(p, {
345
347
  variant: "outline",
346
348
  size: "sm",
347
- onClick: S,
349
+ onClick: d,
348
350
  children: [/* @__PURE__ */ b(T, { className: "h-4 w-4 mr-2" }), "Print"]
349
351
  }),
350
- o && r.showExportButtons && /* @__PURE__ */ x("div", {
352
+ a && n.showExportButtons && /* @__PURE__ */ x("div", {
351
353
  className: "flex items-center gap-1",
352
354
  children: [
353
355
  /* @__PURE__ */ x(p, {
354
356
  variant: "outline",
355
357
  size: "sm",
356
- onClick: () => d("pdf"),
358
+ onClick: () => l("pdf"),
357
359
  children: [/* @__PURE__ */ b(C, { className: "h-4 w-4 mr-2" }), "PDF"]
358
360
  }),
359
361
  /* @__PURE__ */ x(p, {
360
362
  variant: "outline",
361
363
  size: "sm",
362
- onClick: () => d("excel"),
364
+ onClick: () => l("excel"),
363
365
  children: [/* @__PURE__ */ b(C, { className: "h-4 w-4 mr-2" }), "Excel"]
364
366
  }),
365
367
  /* @__PURE__ */ x(p, {
366
368
  variant: "outline",
367
369
  size: "sm",
368
- onClick: () => d("csv"),
370
+ onClick: () => l("csv"),
369
371
  children: [/* @__PURE__ */ b(C, { className: "h-4 w-4 mr-2" }), "CSV"]
370
372
  })
371
373
  ]
372
374
  })
373
375
  ]
374
376
  })]
375
- }), /* @__PURE__ */ x(m, { children: [/* @__PURE__ */ x(_, { children: [!a && r.title && /* @__PURE__ */ b(v, { children: r.title }), !a && r.description && /* @__PURE__ */ b(g, { children: r.description })] }), /* @__PURE__ */ x(h, {
377
+ }), /* @__PURE__ */ x(m, { children: [/* @__PURE__ */ x(_, { children: [!i && n.title && /* @__PURE__ */ b(v, { children: n.title }), !i && n.description && /* @__PURE__ */ b(g, { children: n.description })] }), /* @__PURE__ */ x(h, {
376
378
  className: "space-y-6",
377
379
  children: [
378
- l && /* @__PURE__ */ x("div", {
380
+ c && /* @__PURE__ */ x("div", {
379
381
  className: "space-y-6",
380
382
  children: [/* @__PURE__ */ b("div", {
381
383
  className: "grid grid-cols-1 md:grid-cols-3 gap-4",
@@ -398,115 +400,96 @@ var U = ({ schema: t, onRefresh: n }) => {
398
400
  ].map((e) => /* @__PURE__ */ b(y, { className: "h-8 w-full" }, e))]
399
401
  })]
400
402
  }),
401
- !l && r.sections?.map((t, n) => t.visible === !1 ? null : /* @__PURE__ */ x("div", {
403
+ !c && n.sections?.map((e, t) => e.visible === !1 ? null : /* @__PURE__ */ x("div", {
402
404
  className: "space-y-2",
403
405
  children: [
404
- t.title && t.type !== "header" && /* @__PURE__ */ b("h3", {
406
+ e.title && e.type !== "header" && /* @__PURE__ */ b("h3", {
405
407
  className: "text-lg font-semibold border-b pb-2",
406
- children: t.title
408
+ children: e.title
407
409
  }),
408
- t.type === "header" && t.title && /* @__PURE__ */ b("div", {
410
+ e.type === "header" && e.title && /* @__PURE__ */ b("div", {
409
411
  className: "text-2xl font-bold py-4",
410
- children: t.title
412
+ children: e.title
411
413
  }),
412
- t.type === "summary" && /* @__PURE__ */ b("div", {
414
+ e.type === "summary" && /* @__PURE__ */ b("div", {
413
415
  className: "grid grid-cols-1 md:grid-cols-3 gap-4",
414
- children: r.fields?.filter((e) => e.showInSummary).map((e, t) => /* @__PURE__ */ b(m, { children: /* @__PURE__ */ x(h, {
416
+ children: n.fields?.filter((e) => e.showInSummary).map((e, t) => /* @__PURE__ */ b(m, { children: /* @__PURE__ */ x(h, {
415
417
  className: "p-4",
416
418
  children: [/* @__PURE__ */ b("div", {
417
419
  className: "text-sm text-muted-foreground",
418
420
  children: e.label || e.name
419
421
  }), /* @__PURE__ */ b("div", {
420
422
  className: "text-2xl font-bold",
421
- children: H(D(e.name, e.aggregation), e)
423
+ children: B(w(e.name, e.aggregation), e)
422
424
  })]
423
425
  }) }, t))
424
426
  }),
425
- t.type === "chart" && t.chart && /* @__PURE__ */ b("div", {
426
- className: "min-h-[300px]",
427
- children: (() => {
428
- let n = t.chart.type, r = !!t.chart.chartType;
429
- !n && r && (n = "chart"), n && e.get(n) || (n = "chart");
430
- let a = n === "chart" ? {
431
- xAxisKey: t.chart.xAxisKey || t.chart.xAxisField || "name",
432
- series: t.chart.series || (t.chart.yAxisFields ? t.chart.yAxisFields.map((e) => ({ dataKey: e })) : []),
433
- chartType: t.chart.chartType || "bar"
434
- } : {};
435
- return /* @__PURE__ */ b(u, { schema: {
436
- ...t.chart,
437
- type: n,
438
- ...a,
439
- data: i || t.chart.data,
440
- className: t.chart.className || "w-full h-[350px]"
441
- } });
442
- })()
443
- }),
444
- t.type === "table" && /* @__PURE__ */ b("div", {
427
+ e.type === "table" && /* @__PURE__ */ b("div", {
445
428
  className: "border rounded-lg overflow-x-auto",
446
429
  children: /* @__PURE__ */ x("table", {
447
430
  className: "w-full text-sm min-w-[600px]",
448
431
  children: [/* @__PURE__ */ b("thead", {
449
432
  className: "bg-muted",
450
- children: /* @__PURE__ */ b("tr", { children: t.columns?.map((e, t) => /* @__PURE__ */ b("th", {
433
+ children: /* @__PURE__ */ b("tr", { children: e.columns?.map((e, t) => /* @__PURE__ */ b("th", {
451
434
  className: `px-4 py-2 font-medium ${e.type === "number" ? "text-right" : "text-left"}`,
452
435
  children: e.label || e.name
453
436
  }, t)) })
454
437
  }), /* @__PURE__ */ b("tbody", { children: (() => {
455
- let e = ie(i || [], r.groupBy || []);
456
- return e ? e.map((e) => /* @__PURE__ */ x(s.Fragment, { children: [/* @__PURE__ */ b("tr", {
438
+ let t = oe(r || [], n.groupBy || []);
439
+ return t ? t.map((t) => /* @__PURE__ */ x(s.Fragment, { children: [/* @__PURE__ */ b("tr", {
457
440
  className: "bg-muted/60",
458
441
  children: /* @__PURE__ */ x("td", {
459
- colSpan: t.columns?.length || 1,
442
+ colSpan: e.columns?.length || 1,
460
443
  className: "px-4 py-2 font-semibold text-sm",
461
444
  children: [
462
- e.label,
445
+ t.label,
463
446
  " (",
464
- e.rows.length,
447
+ t.rows.length,
465
448
  ")"
466
449
  ]
467
450
  })
468
- }), e.rows.map((e, n) => /* @__PURE__ */ b("tr", {
451
+ }), t.rows.map((t, n) => /* @__PURE__ */ b("tr", {
469
452
  className: "border-t hover:bg-muted/50 even:bg-muted/20",
470
- children: t.columns?.map((t, n) => /* @__PURE__ */ b("td", {
471
- className: `px-4 py-2 ${t.type === "number" ? "text-right tabular-nums" : ""}`,
472
- style: A(t.name, e[t.name]),
473
- children: j(e[t.name], t)
453
+ children: e.columns?.map((e, n) => /* @__PURE__ */ b("td", {
454
+ className: `px-4 py-2 ${e.type === "number" ? "text-right tabular-nums" : ""}`,
455
+ style: D(e.name, t[e.name]),
456
+ children: k(t[e.name], e)
474
457
  }, n))
475
- }, n))] }, e.key)) : i?.map((e, n) => /* @__PURE__ */ b("tr", {
458
+ }, n))] }, t.key)) : r?.map((t, n) => /* @__PURE__ */ b("tr", {
476
459
  className: "border-t hover:bg-muted/50 even:bg-muted/20",
477
- children: t.columns?.map((t, n) => /* @__PURE__ */ b("td", {
478
- className: `px-4 py-2 ${t.type === "number" ? "text-right tabular-nums" : ""}`,
479
- style: A(t.name, e[t.name]),
480
- children: j(e[t.name], t)
460
+ children: e.columns?.map((e, n) => /* @__PURE__ */ b("td", {
461
+ className: `px-4 py-2 ${e.type === "number" ? "text-right tabular-nums" : ""}`,
462
+ style: D(e.name, t[e.name]),
463
+ children: k(t[e.name], e)
481
464
  }, n))
482
465
  }, n));
483
466
  })() })]
484
467
  })
485
468
  }),
486
- t.type === "text" && t.text && /* @__PURE__ */ b("div", {
469
+ e.type === "text" && e.text && /* @__PURE__ */ b("div", {
487
470
  className: "prose max-w-none",
488
- children: /* @__PURE__ */ b("p", { children: t.text })
471
+ children: /* @__PURE__ */ b("p", { children: e.text })
489
472
  }),
490
- t.type === "page-break" && /* @__PURE__ */ b("div", { className: "border-t-2 border-dashed my-8 print:page-break-after-always" }),
491
- t.content && /* @__PURE__ */ b(u, { schema: t.content })
473
+ e.type === "page-break" && /* @__PURE__ */ b("div", { className: "border-t-2 border-dashed my-8 print:page-break-after-always" }),
474
+ e.content && /* @__PURE__ */ b(u, { schema: e.content })
492
475
  ]
493
- }, n)),
494
- !r.sections && i && i.length > 0 && /* @__PURE__ */ b("div", {
476
+ }, t)),
477
+ !n.sections && r && r.length > 0 && /* @__PURE__ */ b("div", {
495
478
  className: "border rounded-lg overflow-x-auto",
496
479
  children: /* @__PURE__ */ x("table", {
497
480
  className: "w-full text-sm min-w-[600px]",
498
481
  children: [/* @__PURE__ */ b("thead", {
499
482
  className: "bg-muted",
500
- children: /* @__PURE__ */ b("tr", { children: r.fields?.map((e, t) => /* @__PURE__ */ b("th", {
483
+ children: /* @__PURE__ */ b("tr", { children: n.fields?.map((e, t) => /* @__PURE__ */ b("th", {
501
484
  className: `px-4 py-2 font-medium ${e.type === "number" ? "text-right" : "text-left"}`,
502
485
  children: e.label || e.name
503
486
  }, t)) })
504
- }), /* @__PURE__ */ b("tbody", { children: i.map((e, t) => /* @__PURE__ */ b("tr", {
487
+ }), /* @__PURE__ */ b("tbody", { children: r.map((e, t) => /* @__PURE__ */ b("tr", {
505
488
  className: "border-t hover:bg-muted/50 even:bg-muted/20",
506
- children: r.fields?.map((t, n) => /* @__PURE__ */ b("td", {
489
+ children: n.fields?.map((t, n) => /* @__PURE__ */ b("td", {
507
490
  className: `px-4 py-2 ${t.type === "number" ? "text-right tabular-nums" : ""}`,
508
- style: A(t.name, e[t.name]),
509
- children: j(e[t.name], t)
491
+ style: D(t.name, e[t.name]),
492
+ children: k(e[t.name], t)
510
493
  }, n))
511
494
  }, t)) })]
512
495
  })
@@ -520,26 +503,41 @@ var U = ({ schema: t, onRefresh: n }) => {
520
503
  };
521
504
  //#endregion
522
505
  //#region src/DatasetReportRenderer.tsx
523
- function W(e) {
506
+ function H(e) {
524
507
  if (!e || typeof e != "object") return !1;
525
508
  let t = e;
526
509
  return typeof t.dataset == "string" && t.dataset.length > 0 || t.type === "joined" && Array.isArray(t.blocks) && t.blocks.some((e) => typeof e?.dataset == "string");
527
510
  }
528
- function G(e, t) {
511
+ function U(e, t) {
529
512
  return e ? typeof e == "string" ? e : typeof e == "object" && typeof e.default == "string" ? e.default : t : t;
530
513
  }
531
- function K(e) {
514
+ function W(e) {
532
515
  return Array.isArray(e) ? e.filter((e) => typeof e == "string" && !!e) : [];
533
516
  }
534
- function q(e, t, n, r, i, a) {
535
- let [s, c] = o.useState({
517
+ function G(e) {
518
+ if (!Array.isArray(e)) return;
519
+ let t = {};
520
+ for (let n of e) {
521
+ let e = n && typeof n == "object" ? n.by : void 0;
522
+ typeof e != "string" || !e || (t[e] = n.direction === "desc" ? "desc" : "asc");
523
+ }
524
+ return Object.keys(t).length > 0 ? t : void 0;
525
+ }
526
+ function ce(e, t, n) {
527
+ if (!e) return;
528
+ let r = /* @__PURE__ */ new Set([...t, ...n]), i = {};
529
+ for (let [t, n] of Object.entries(e)) r.has(t) && (i[t] = n);
530
+ return Object.keys(i).length > 0 ? i : void 0;
531
+ }
532
+ function K(e, t, n, r, i, a, s) {
533
+ let [c, l] = o.useState({
536
534
  status: "idle",
537
535
  rows: []
538
- }), l = JSON.stringify(r ?? null), u = JSON.stringify(a ?? null), d = `${e}|${t.join(",")}|${n.join(",")}|${l}|${u}`;
536
+ }), u = ce(s, t, n), d = JSON.stringify(r ?? null), f = JSON.stringify(a ?? null), p = JSON.stringify(u ?? null), m = `${e}|${t.join(",")}|${n.join(",")}|${d}|${f}|${p}`;
539
537
  return o.useEffect(() => {
540
538
  let o = i;
541
539
  if (!o || typeof o.queryDataset != "function") {
542
- c({
540
+ l({
543
541
  status: "error",
544
542
  rows: [],
545
543
  error: "This data source does not support dataset queries."
@@ -547,23 +545,24 @@ function q(e, t, n, r, i, a) {
547
545
  return;
548
546
  }
549
547
  if (!e || n.length === 0) {
550
- c({
548
+ l({
551
549
  status: "idle",
552
550
  rows: []
553
551
  });
554
552
  return;
555
553
  }
556
554
  let s = !1;
557
- return c({
555
+ return l({
558
556
  status: "loading",
559
557
  rows: []
560
558
  }), o.queryDataset(e, {
561
559
  dimensions: t,
562
560
  measures: n,
563
561
  ...r && Object.keys(r).length > 0 ? { runtimeFilter: r } : {},
564
- ...a ? { totals: { groupings: a } } : {}
562
+ ...a ? { totals: { groupings: a } } : {},
563
+ ...u ? { order: u } : {}
565
564
  }).then((e) => {
566
- s || c({
565
+ s || l({
567
566
  status: "ok",
568
567
  rows: Array.isArray(e?.rows) ? e.rows : [],
569
568
  fields: Array.isArray(e?.fields) ? e.fields : [],
@@ -574,7 +573,7 @@ function q(e, t, n, r, i, a) {
574
573
  totals: Array.isArray(e?.totals) ? e.totals : void 0
575
574
  });
576
575
  }).catch((e) => {
577
- s || c({
576
+ s || l({
578
577
  status: "error",
579
578
  rows: [],
580
579
  error: String(e?.message ?? e)
@@ -582,9 +581,9 @@ function q(e, t, n, r, i, a) {
582
581
  }), () => {
583
582
  s = !0;
584
583
  };
585
- }, [d]), s;
584
+ }, [m]), c;
586
585
  }
587
- function J({ dataset: e }) {
586
+ function q({ dataset: e }) {
588
587
  return /* @__PURE__ */ x("div", {
589
588
  className: "flex items-center justify-center rounded-md border border-dashed bg-muted/20 p-4 text-xs text-muted-foreground",
590
589
  children: [
@@ -594,7 +593,7 @@ function J({ dataset: e }) {
594
593
  ]
595
594
  });
596
595
  }
597
- function Y({ status: e, error: t }) {
596
+ function J({ status: e, error: t }) {
598
597
  return e === "error" ? /* @__PURE__ */ x("div", {
599
598
  role: "alert",
600
599
  className: "flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive",
@@ -607,68 +606,106 @@ function Y({ status: e, error: t }) {
607
606
  children: [/* @__PURE__ */ b(w, { className: "h-4 w-4 animate-spin" }), " Running report…"]
608
607
  });
609
608
  }
610
- function X() {
609
+ function Y() {
611
610
  return /* @__PURE__ */ x("div", {
612
611
  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",
613
612
  children: [/* @__PURE__ */ b(D, { className: "h-6 w-6" }), " The dataset returned no rows for this report’s scope."]
614
613
  });
615
614
  }
616
- var Z = "cursor-pointer hover:bg-accent/40";
617
- function ae({ dataset: e, rows: a, values: o, runtimeFilter: s, dataSource: c, onDrill: l }) {
618
- let u = q(e, a, o, s, c), { fieldLabel: d } = A();
619
- if (o.length === 0) return /* @__PURE__ */ b(J, { dataset: e });
620
- if (u.status === "loading" || u.status === "idle") return /* @__PURE__ */ b(Y, { status: u.status });
621
- if (u.status === "error") return /* @__PURE__ */ b(Y, {
615
+ var le = "cursor-pointer hover:bg-accent/40";
616
+ function ue({ dataset: e, rows: a, values: o, runtimeFilter: s, dataSource: c, onDrill: l, order: u, withTotals: d }) {
617
+ let f = K(e, a, o, s, c, d && a.length > 0 ? [[]] : void 0, u), { fieldLabel: p } = k(), m = A();
618
+ if (o.length === 0) return /* @__PURE__ */ b(q, { dataset: e });
619
+ if (f.status === "loading" || f.status === "idle") return /* @__PURE__ */ b(J, { status: f.status });
620
+ if (f.status === "error") return /* @__PURE__ */ b(J, {
622
621
  status: "error",
623
- error: u.error
622
+ error: f.error
624
623
  });
625
- if (u.rows.length === 0) return /* @__PURE__ */ b(X, {});
626
- let f = !!l && a.length > 0, p = u.dimensionFields ? a.filter((e) => e in u.dimensionFields) : [], m = (n, r) => {
624
+ if (f.rows.length === 0) return /* @__PURE__ */ b(Y, {});
625
+ let h = !!l && a.length > 0, g = f.dimensionFields ? a.filter((e) => e in f.dimensionFields) : [], _ = (n, r) => {
627
626
  let i = {};
628
627
  for (let e of a) i[e] = n[e];
629
- let o = u.drillRanges?.[r], c = !!o && Object.keys(o).length > 0, d = u.object && (p.length > 0 || c) ? t(u.drillRawRows?.[r], p, u.dimensionFields ?? {}, s, o) : void 0;
628
+ let o = f.drillRanges?.[r], c = !!o && Object.keys(o).length > 0, u = f.object && (g.length > 0 || c) ? t(f.drillRawRows?.[r], g, f.dimensionFields ?? {}, s, o) : void 0;
630
629
  l({
631
630
  dataset: e,
632
631
  groupKey: i,
633
632
  runtimeFilter: s,
634
- object: u.object,
635
- objectFilter: d
633
+ object: f.object,
634
+ objectFilter: u
636
635
  });
637
- }, { measureField: h, headerLabel: g } = n(u.fields, u.object, d), _ = [...a, ...o];
636
+ }, { measureField: v, headerLabel: y } = n(f.fields, f.object, p), S = [...a, ...o], C = d ? f.totals?.find((e) => Array.isArray(e.dimensions) && e.dimensions.length === 0)?.rows?.[0] : void 0, w = m("report.total", "Total");
638
637
  return /* @__PURE__ */ b("div", {
639
638
  className: "overflow-auto max-h-[70vh] rounded-md border",
640
639
  children: /* @__PURE__ */ x("table", {
641
640
  className: "w-full text-xs",
642
641
  children: [/* @__PURE__ */ b("thead", {
643
642
  className: "bg-muted/40",
644
- children: /* @__PURE__ */ b("tr", { children: _.map((e) => /* @__PURE__ */ b("th", {
643
+ children: /* @__PURE__ */ b("tr", { children: S.map((e) => /* @__PURE__ */ b("th", {
645
644
  className: "px-2 py-1.5 text-left font-medium whitespace-nowrap",
646
- children: g(e)
645
+ children: y(e)
647
646
  }, e)) })
648
- }), /* @__PURE__ */ b("tbody", { children: u.rows.map((e, t) => /* @__PURE__ */ b("tr", {
649
- className: `border-t${f ? ` ${Z}` : ""}`,
650
- "data-testid": f ? "dataset-drill-row" : void 0,
651
- onClick: f ? () => m(e, t) : void 0,
652
- children: _.map((t) => /* @__PURE__ */ b("td", {
647
+ }), /* @__PURE__ */ x("tbody", { children: [f.rows.map((e, t) => /* @__PURE__ */ b("tr", {
648
+ className: `border-t${h ? ` ${le}` : ""}`,
649
+ "data-testid": h ? "dataset-drill-row" : void 0,
650
+ onClick: h ? () => _(e, t) : void 0,
651
+ children: S.map((t) => /* @__PURE__ */ b("td", {
653
652
  className: "px-2 py-1 tabular-nums whitespace-nowrap",
654
- children: o.includes(t) ? i(e[t], h(t)?.format, h(t)?.currency) : r(e[t])
653
+ children: o.includes(t) ? i(e[t], v(t)?.format, v(t)?.currency) : r(e[t])
655
654
  }, t))
656
- }, t)) })]
655
+ }, t)), C && /* @__PURE__ */ x("tr", {
656
+ className: "border-t bg-muted/30 font-medium",
657
+ "data-testid": "dataset-report-total-row",
658
+ children: [a.length > 0 && /* @__PURE__ */ b("td", {
659
+ colSpan: a.length,
660
+ className: "px-2 py-1 whitespace-nowrap",
661
+ children: w
662
+ }), o.map((e) => /* @__PURE__ */ b("td", {
663
+ className: "px-2 py-1 tabular-nums whitespace-nowrap",
664
+ children: i(C[e], v(e)?.format, v(e)?.currency)
665
+ }, e))]
666
+ })] })]
657
667
  })
658
668
  });
659
669
  }
660
- function oe(e) {
670
+ function de(e) {
661
671
  switch (e) {
662
- case "line": return "line";
663
- case "area": return "area";
664
- case "pie": return "pie";
665
- case "donut": return "donut";
666
- case "radar": return "radar";
667
- case "scatter": return "scatter";
668
- default: return "bar";
672
+ case "summary": return "summary";
673
+ case "matrix": return "matrix";
674
+ case "joined": return "joined";
675
+ default: return "tabular";
676
+ }
677
+ }
678
+ function fe(e) {
679
+ switch (e) {
680
+ case "bar":
681
+ case "column":
682
+ case "horizontal-bar":
683
+ case "line":
684
+ case "area":
685
+ case "pie":
686
+ case "donut":
687
+ case "funnel":
688
+ case "scatter":
689
+ case "treemap":
690
+ case "sankey":
691
+ case "radar": return {
692
+ kind: "series",
693
+ chartType: e
694
+ };
695
+ case "gauge":
696
+ case "solid-gauge":
697
+ case "metric":
698
+ case "kpi":
699
+ case "bullet": return { kind: "single_value" };
700
+ case "table":
701
+ case "pivot": return { kind: "tabular" };
702
+ default: return {
703
+ kind: "unsupported",
704
+ type: String(e)
705
+ };
669
706
  }
670
707
  }
671
- function se(t) {
708
+ function pe(t) {
672
709
  let [, n] = o.useReducer((e) => e + 1, 0);
673
710
  return o.useEffect(() => {
674
711
  if (e.get(t)) return;
@@ -678,54 +715,83 @@ function se(t) {
678
715
  return i && typeof i.then == "function" && i.then(() => n()).catch(() => {}), r;
679
716
  }, [t]), e.get(t);
680
717
  }
681
- function ce({ dataset: e, chart: t, runtimeFilter: n, dataSource: r }) {
682
- let i = typeof t.xAxis == "string" ? t.xAxis : "", a = typeof t.yAxis == "string" ? t.yAxis : "", o = q(e, i ? [i] : [], a ? [a] : [], n, r), s = se("chart");
683
- if (!i || !a) return null;
684
- if (o.status === "loading" || o.status === "idle") return /* @__PURE__ */ x("div", {
718
+ function me({ dataset: e, chart: t, runtimeFilter: r, dataSource: a, order: o }) {
719
+ let s = typeof t.xAxis == "string" ? t.xAxis : "", c = typeof t.yAxis == "string" ? t.yAxis : "", l = fe(t.type), u = l.kind === "series" || l.kind === "single_value", d = K(e, l.kind === "series" && s ? [s] : [], u && c ? [c] : [], r, a, void 0, o), f = pe("chart"), { fieldLabel: p } = k(), m = typeof t.title == "string" ? t.title : void 0;
720
+ if (l.kind === "tabular") return null;
721
+ if (l.kind === "unsupported") return /* @__PURE__ */ x("div", {
722
+ className: "rounded-md border border-dashed bg-muted/20 px-3 py-2 text-xs text-muted-foreground",
723
+ "data-testid": "dataset-report-chart-unsupported",
724
+ children: [
725
+ "Chart type “",
726
+ l.type,
727
+ "” is not a spec chart type — the grouped table below carries this report’s numbers."
728
+ ]
729
+ });
730
+ if (l.kind === "series" && !s || !c) return null;
731
+ if (d.status === "loading" || d.status === "idle") return /* @__PURE__ */ x("div", {
685
732
  className: "flex items-center gap-2 p-4 text-xs text-muted-foreground",
686
733
  children: [/* @__PURE__ */ b(w, { className: "h-4 w-4 animate-spin" }), " Loading chart…"]
687
734
  });
688
- if (o.status === "error" || o.rows.length === 0 || !s) return null;
689
- let c = typeof t.title == "string" ? t.title : void 0;
690
- return /* @__PURE__ */ x("div", {
735
+ if (d.status === "error" || d.rows.length === 0) return null;
736
+ if (l.kind === "single_value") {
737
+ let { measureField: e, headerLabel: t } = n(d.fields, d.object, p), r = e(c);
738
+ return /* @__PURE__ */ x("div", {
739
+ className: "rounded-md border bg-card p-3",
740
+ "data-testid": "dataset-report-metric",
741
+ children: [m ? /* @__PURE__ */ b("h3", {
742
+ className: "mb-2 text-sm font-semibold",
743
+ children: m
744
+ }) : null, /* @__PURE__ */ x("div", {
745
+ className: "flex flex-col gap-0.5 py-2",
746
+ children: [/* @__PURE__ */ b("span", {
747
+ className: "text-2xl font-semibold tabular-nums",
748
+ children: i(d.rows[0]?.[c], r?.format, r?.currency)
749
+ }), /* @__PURE__ */ b("span", {
750
+ className: "text-xs text-muted-foreground",
751
+ children: t(c)
752
+ })]
753
+ })]
754
+ });
755
+ }
756
+ return f ? /* @__PURE__ */ x("div", {
691
757
  className: "rounded-md border bg-card p-3",
692
758
  "data-testid": "dataset-report-chart",
693
- children: [c ? /* @__PURE__ */ b("h3", {
759
+ children: [m ? /* @__PURE__ */ b("h3", {
694
760
  className: "mb-2 text-sm font-semibold",
695
- children: c
696
- }) : null, /* @__PURE__ */ b(s, { schema: {
697
- chartType: oe(t.type),
698
- data: o.rows,
699
- xAxisKey: i,
700
- series: [{ dataKey: a }],
761
+ children: m
762
+ }) : null, /* @__PURE__ */ b(f, { schema: {
763
+ chartType: l.chartType,
764
+ data: d.rows,
765
+ xAxisKey: s,
766
+ series: [{ dataKey: c }],
701
767
  height: typeof t.height == "number" ? t.height : 280,
702
768
  isAnimationActive: !1
703
769
  } })]
704
- });
770
+ }) : null;
705
771
  }
706
- function Q(e, t) {
772
+ function X(e, t) {
707
773
  return e.map((e) => String(t[e] ?? "∅")).join("");
708
774
  }
709
- function le(e, t) {
775
+ function he(e, t) {
710
776
  return e.map((e) => r(t[e])).join(" / ");
711
777
  }
712
- function ue({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l, dataSource: u, onDrill: d }) {
713
- let f = q(e, [...a, ...s], c, l, u, [
778
+ function Z({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l, dataSource: u, onDrill: d, order: f }) {
779
+ let p = K(e, [...a, ...s], c, l, u, [
714
780
  a,
715
781
  s,
716
782
  []
717
- ]), p = j(), { fieldLabel: m } = A(), h = o.useMemo(() => {
718
- if (f.status !== "ok") return null;
783
+ ], f), m = A(), { fieldLabel: h } = k(), g = o.useMemo(() => {
784
+ if (p.status !== "ok") return null;
719
785
  let e = [], t = [], n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map();
720
- return f.rows.forEach((o, c) => {
721
- let l = Q(a, o), u = Q(s, o);
786
+ return p.rows.forEach((o, c) => {
787
+ let l = X(a, o), u = X(s, o);
722
788
  if (!n.has(l)) {
723
789
  n.add(l);
724
790
  let t = {};
725
791
  for (let e of a) t[e] = o[e];
726
792
  e.push({
727
793
  id: l,
728
- label: le(a, o),
794
+ label: he(a, o),
729
795
  key: t
730
796
  });
731
797
  }
@@ -735,7 +801,7 @@ function ue({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l
735
801
  for (let t of s) e[t] = o[t];
736
802
  t.push({
737
803
  id: u,
738
- label: le(s, o),
804
+ label: he(s, o),
739
805
  key: e
740
806
  });
741
807
  }
@@ -749,19 +815,19 @@ function ue({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l
749
815
  cells: i
750
816
  };
751
817
  }, [
752
- f,
818
+ p,
753
819
  a,
754
820
  s
755
821
  ]);
756
- if (c.length === 0) return /* @__PURE__ */ b(J, { dataset: e });
757
- if (f.status === "loading" || f.status === "idle") return /* @__PURE__ */ b(Y, { status: f.status });
758
- if (f.status === "error") return /* @__PURE__ */ b(Y, {
822
+ if (c.length === 0) return /* @__PURE__ */ b(q, { dataset: e });
823
+ if (p.status === "loading" || p.status === "idle") return /* @__PURE__ */ b(J, { status: p.status });
824
+ if (p.status === "error") return /* @__PURE__ */ b(J, {
759
825
  status: "error",
760
- error: f.error
826
+ error: p.error
761
827
  });
762
- if (!h || h.rowHeaders.length === 0) return /* @__PURE__ */ b(X, {});
763
- let { measureField: g, headerLabel: _ } = n(f.fields, f.object, m), v = p("report.total", "Total"), y = !!d, S = f.dimensionFields ? [...a, ...s].filter((e) => e in f.dimensionFields) : [], C = (n, r, i) => {
764
- let a = f.drillRanges?.[i], o = !!a && Object.keys(a).length > 0, s = f.object && (S.length > 0 || o) ? t(f.drillRawRows?.[i], S, f.dimensionFields ?? {}, l, a) : void 0;
828
+ if (!g || g.rowHeaders.length === 0) return /* @__PURE__ */ b(Y, {});
829
+ let { measureField: _, headerLabel: v } = n(p.fields, p.object, h), y = m("report.total", "Total"), S = !!d, C = p.dimensionFields ? [...a, ...s].filter((e) => e in p.dimensionFields) : [], w = (n, r, i) => {
830
+ let a = p.drillRanges?.[i], o = !!a && Object.keys(a).length > 0, s = p.object && (C.length > 0 || o) ? t(p.drillRawRows?.[i], C, p.dimensionFields ?? {}, l, a) : void 0;
765
831
  d({
766
832
  dataset: e,
767
833
  groupKey: {
@@ -769,18 +835,18 @@ function ue({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l
769
835
  ...r
770
836
  },
771
837
  runtimeFilter: l,
772
- object: f.object,
838
+ object: p.object,
773
839
  objectFilter: s
774
840
  });
775
- }, w = h.colHeaders.flatMap((e) => c.map((t) => ({
841
+ }, T = g.colHeaders.flatMap((e) => c.map((t) => ({
776
842
  col: e,
777
843
  measure: t,
778
- header: c.length === 1 ? e.label : `${e.label} · ${_(t)}`
779
- }))), T = (e) => f.totals?.find((t) => Array.isArray(t.dimensions) && t.dimensions.join(",") === e.join(","))?.rows, E = /* @__PURE__ */ new Map();
780
- for (let e of T(a) ?? []) E.set(Q(a, e), e);
781
- let D = /* @__PURE__ */ new Map();
782
- for (let e of T(s) ?? []) D.set(Q(s, e), e);
783
- let O = T([])?.[0], k = E.size > 0, M = D.size > 0;
844
+ header: c.length === 1 ? e.label : `${e.label} · ${v(t)}`
845
+ }))), E = (e) => p.totals?.find((t) => Array.isArray(t.dimensions) && t.dimensions.join(",") === e.join(","))?.rows, D = /* @__PURE__ */ new Map();
846
+ for (let e of E(a) ?? []) D.set(X(a, e), e);
847
+ let O = /* @__PURE__ */ new Map();
848
+ for (let e of E(s) ?? []) O.set(X(s, e), e);
849
+ let ee = E([])?.[0], j = D.size > 0, M = O.size > 0;
784
850
  return /* @__PURE__ */ b("div", {
785
851
  className: "overflow-auto max-h-[70vh] rounded-md border",
786
852
  "data-testid": "dataset-matrix",
@@ -791,38 +857,38 @@ function ue({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l
791
857
  children: /* @__PURE__ */ x("tr", { children: [
792
858
  a.map((e) => /* @__PURE__ */ b("th", {
793
859
  className: "px-2 py-1.5 text-left font-medium whitespace-nowrap",
794
- children: _(e)
860
+ children: v(e)
795
861
  }, e)),
796
- w.map((e) => /* @__PURE__ */ b("th", {
862
+ T.map((e) => /* @__PURE__ */ b("th", {
797
863
  className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
798
864
  children: e.header
799
865
  }, `${e.col.id}-${e.measure}`)),
800
- k && c.map((e) => /* @__PURE__ */ b("th", {
866
+ j && c.map((e) => /* @__PURE__ */ b("th", {
801
867
  className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
802
868
  "data-testid": "matrix-total-col-header",
803
- children: c.length === 1 ? v : `${v} · ${_(e)}`
869
+ children: c.length === 1 ? y : `${y} · ${v(e)}`
804
870
  }, `total-${e}`))
805
871
  ] })
806
- }), /* @__PURE__ */ x("tbody", { children: [h.rowHeaders.map((e) => /* @__PURE__ */ x("tr", {
872
+ }), /* @__PURE__ */ x("tbody", { children: [g.rowHeaders.map((e) => /* @__PURE__ */ x("tr", {
807
873
  className: "border-t",
808
874
  children: [
809
875
  a.map((t) => /* @__PURE__ */ b("td", {
810
876
  className: "px-2 py-1 whitespace-nowrap font-medium",
811
877
  children: r(e.key[t])
812
878
  }, t)),
813
- w.map((t) => {
814
- let n = h.cells.get(`${e.id} ${t.col.id}`), r = n?.row[t.measure], a = y && n != null;
879
+ T.map((t) => {
880
+ let n = g.cells.get(`${e.id} ${t.col.id}`), r = n?.row[t.measure], a = S && n != null;
815
881
  return /* @__PURE__ */ b("td", {
816
- className: `px-2 py-1 text-right tabular-nums whitespace-nowrap${a ? ` ${Z}` : ""}`,
882
+ className: `px-2 py-1 text-right tabular-nums whitespace-nowrap${a ? ` ${le}` : ""}`,
817
883
  "data-testid": a ? "dataset-drill-cell" : void 0,
818
- onClick: a ? () => C(e.key, t.col.key, n.index) : void 0,
819
- children: i(r, g(t.measure)?.format, g(t.measure)?.currency)
884
+ onClick: a ? () => w(e.key, t.col.key, n.index) : void 0,
885
+ children: i(r, _(t.measure)?.format, _(t.measure)?.currency)
820
886
  }, `${t.col.id}-${t.measure}`);
821
887
  }),
822
- k && c.map((t) => /* @__PURE__ */ b("td", {
888
+ j && c.map((t) => /* @__PURE__ */ b("td", {
823
889
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap font-medium",
824
890
  "data-testid": "matrix-row-total",
825
- children: i(E.get(e.id)?.[t], g(t)?.format, g(t)?.currency)
891
+ children: i(D.get(e.id)?.[t], _(t)?.format, _(t)?.currency)
826
892
  }, `total-${t}`))
827
893
  ]
828
894
  }, e.id)), M && /* @__PURE__ */ x("tr", {
@@ -832,25 +898,25 @@ function ue({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l
832
898
  a.length > 0 && /* @__PURE__ */ b("td", {
833
899
  colSpan: a.length,
834
900
  className: "px-2 py-1 whitespace-nowrap",
835
- children: v
901
+ children: y
836
902
  }),
837
- w.map((e) => /* @__PURE__ */ b("td", {
903
+ T.map((e) => /* @__PURE__ */ b("td", {
838
904
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
839
- children: i(D.get(e.col.id)?.[e.measure], g(e.measure)?.format, g(e.measure)?.currency)
905
+ children: i(O.get(e.col.id)?.[e.measure], _(e.measure)?.format, _(e.measure)?.currency)
840
906
  }, `${e.col.id}-${e.measure}`)),
841
- k && c.map((e) => /* @__PURE__ */ b("td", {
907
+ j && c.map((e) => /* @__PURE__ */ b("td", {
842
908
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
843
909
  "data-testid": "matrix-grand-total",
844
- children: i(O?.[e], g(e)?.format, g(e)?.currency)
910
+ children: i(ee?.[e], _(e)?.format, _(e)?.currency)
845
911
  }, `grand-${e}`))
846
912
  ]
847
913
  })] })]
848
914
  })
849
915
  });
850
916
  }
851
- var de = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i }) => {
852
- let o = a(e.runtimeFilter ?? e.filter, n), s = e.drilldown === !1 ? void 0 : r;
853
- if (e.type === "joined" && Array.isArray(e.blocks)) return /* @__PURE__ */ b("div", {
917
+ var ge = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i }) => {
918
+ let o = a(e.runtimeFilter ?? e.filter, n), s = e.drilldown === !1 ? void 0 : r, c = de(e.type);
919
+ if (c === "joined" && Array.isArray(e.blocks)) return /* @__PURE__ */ b("div", {
854
920
  className: i,
855
921
  "data-testid": "dataset-joined-report",
856
922
  "data-report-name": e.name,
@@ -860,21 +926,24 @@ var de = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i
860
926
  gap: 24
861
927
  },
862
928
  children: e.blocks.map((e, n) => {
863
- let r = a(o, e.runtimeFilter ?? e.filter), i = K(e.columns), c = e.type === "matrix" && i.length > 0 ? /* @__PURE__ */ b(ue, {
929
+ let r = a(o, e.runtimeFilter ?? e.filter), i = W(e.columns), c = G(e.order), l = de(e.type), u = l === "matrix" && i.length > 0 ? /* @__PURE__ */ b(Z, {
864
930
  dataset: String(e.dataset ?? ""),
865
- rows: K(e.rows),
931
+ rows: W(e.rows),
866
932
  columnsAcross: i,
867
- values: K(e.values),
933
+ values: W(e.values),
868
934
  runtimeFilter: r,
869
935
  dataSource: t,
870
- onDrill: s
871
- }) : /* @__PURE__ */ b(ae, {
936
+ onDrill: s,
937
+ order: c
938
+ }) : /* @__PURE__ */ b(ue, {
872
939
  dataset: String(e.dataset ?? ""),
873
- rows: K(e.rows),
874
- values: K(e.values),
940
+ rows: W(e.rows),
941
+ values: W(e.values),
875
942
  runtimeFilter: r,
876
943
  dataSource: t,
877
- onDrill: s
944
+ onDrill: s,
945
+ order: c,
946
+ withTotals: l === "summary" || l === "matrix"
878
947
  });
879
948
  return /* @__PURE__ */ x("section", {
880
949
  "data-testid": "dataset-report-block",
@@ -884,52 +953,57 @@ var de = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i
884
953
  className: "flex flex-col gap-0.5",
885
954
  children: [/* @__PURE__ */ b("h3", {
886
955
  className: "text-sm font-semibold",
887
- children: G(e.label, e.name ?? `Block ${n + 1}`)
956
+ children: U(e.label, e.name ?? `Block ${n + 1}`)
888
957
  }), e.description ? /* @__PURE__ */ b("p", {
889
958
  className: "text-xs text-muted-foreground",
890
- children: G(e.description, "")
959
+ children: U(e.description, "")
891
960
  }) : null]
892
- }), c]
961
+ }), u]
893
962
  }, e.name ?? `block-${n}`);
894
963
  })
895
964
  });
896
- let c = K(e.columns);
897
- if (e.type === "matrix" && c.length > 0) return /* @__PURE__ */ b("div", {
965
+ let l = W(e.columns), u = G(e.order);
966
+ if (c === "matrix" && l.length > 0) return /* @__PURE__ */ b("div", {
898
967
  className: i,
899
968
  "data-testid": "dataset-report",
900
969
  "data-report-name": e.name,
901
- children: /* @__PURE__ */ b(ue, {
970
+ children: /* @__PURE__ */ b(Z, {
902
971
  dataset: String(e.dataset ?? ""),
903
- rows: K(e.rows),
904
- columnsAcross: c,
905
- values: K(e.values),
972
+ rows: W(e.rows),
973
+ columnsAcross: l,
974
+ values: W(e.values),
906
975
  runtimeFilter: o,
907
976
  dataSource: t,
908
- onDrill: s
977
+ onDrill: s,
978
+ order: u
909
979
  })
910
980
  });
911
- let l = e.chart && typeof e.chart == "object" && e.chart.type ? e.chart : null;
981
+ let d = e.chart && typeof e.chart == "object" && e.chart.type ? e.chart : null;
912
982
  return /* @__PURE__ */ x("div", {
913
983
  className: `${i ?? ""} flex flex-col gap-3`,
914
984
  "data-testid": "dataset-report",
915
985
  "data-report-name": e.name,
916
- children: [l ? /* @__PURE__ */ b(ce, {
986
+ "data-report-presentation": c,
987
+ children: [d ? /* @__PURE__ */ b(me, {
917
988
  dataset: String(e.dataset ?? ""),
918
- chart: l,
989
+ chart: d,
919
990
  runtimeFilter: o,
920
- dataSource: t
921
- }) : null, /* @__PURE__ */ b(ae, {
991
+ dataSource: t,
992
+ order: u
993
+ }) : null, /* @__PURE__ */ b(ue, {
922
994
  dataset: String(e.dataset ?? ""),
923
- rows: K(e.rows),
924
- values: K(e.values),
995
+ rows: W(e.rows),
996
+ values: W(e.values),
925
997
  runtimeFilter: o,
926
998
  dataSource: t,
927
- onDrill: s
999
+ onDrill: s,
1000
+ order: u,
1001
+ withTotals: c === "summary" || c === "matrix"
928
1002
  })]
929
1003
  });
930
- }, $ = (e) => {
1004
+ }, Q = (e) => {
931
1005
  let { dataSource: t, rows: n, runtimeFilter: r, onDrill: i, className: a } = e, s = o.useContext(d), u = t ?? s?.dataSource, f = e.schema;
932
- return f && typeof f == "object" && f.type === "spec-report" && f.report && typeof f.report == "object" && (f = f.report), W(f) ? /* @__PURE__ */ b(de, {
1006
+ return f && typeof f == "object" && f.type === "spec-report" && f.report && typeof f.report == "object" && (f = f.report), H(f) ? /* @__PURE__ */ b(ge, {
933
1007
  report: f,
934
1008
  dataSource: u,
935
1009
  runtimeFilter: r,
@@ -938,21 +1012,21 @@ var de = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i
938
1012
  }) : c(f) ? /* @__PURE__ */ b("div", {
939
1013
  className: a,
940
1014
  "data-testid": "report-presentation-bridge",
941
- children: /* @__PURE__ */ b(U, { schema: {
1015
+ children: /* @__PURE__ */ b(V, { schema: {
942
1016
  type: "report-viewer",
943
1017
  report: l(f),
944
1018
  data: n ?? [],
945
1019
  showToolbar: !1
946
1020
  } })
947
- }) : /* @__PURE__ */ b(M, { schema: f });
1021
+ }) : /* @__PURE__ */ b(j, { schema: f });
948
1022
  };
949
1023
  //#endregion
950
1024
  //#region src/LiveReportExporter.ts
951
- async function fe(e, t) {
1025
+ async function $(e, t) {
952
1026
  let { dataSource: n, resource: r, queryParams: i, format: a, exportConfig: o } = t, s = a || e.defaultExportFormat || "pdf";
953
1027
  try {
954
1028
  let t = (await n.find(r, i)).data || [];
955
- return L(s, e, t, {
1029
+ return I(s, e, t, {
956
1030
  format: s,
957
1031
  ...e.exportConfigs?.[s],
958
1032
  ...o
@@ -970,17 +1044,17 @@ async function fe(e, t) {
970
1044
  };
971
1045
  }
972
1046
  }
973
- function pe(e, t, n = {}) {
974
- let { columns: r, filename: i, includeAggregationRow: a = !1 } = n, o = r || (e.fields || []).map(he), s = o.map((e) => e.header), c = t.map((e, t) => o.map((n) => {
1047
+ function _e(e, t, n = {}) {
1048
+ let { columns: r, filename: i, includeAggregationRow: a = !1 } = n, o = r || (e.fields || []).map(ye), s = o.map((e) => e.header), c = t.map((e, t) => o.map((n) => {
975
1049
  if (n.formula) return n.formula.replace(/\{ROW\}/g, String(t + 2));
976
1050
  let r = e[n.name];
977
- return ge(r, n.numberFormat);
1051
+ return be(r, n.numberFormat);
978
1052
  }));
979
1053
  if (a && t.length > 0) {
980
1054
  let n = o.map((n, r) => {
981
1055
  let i = (e.fields || []).find((e) => e.name === n.name);
982
1056
  if (i?.aggregation) {
983
- let e = ve(r), n = t.length + 1;
1057
+ let e = Se(r), n = t.length + 1;
984
1058
  switch (i.aggregation) {
985
1059
  case "sum": return `=SUM(${e}2:${e}${n})`;
986
1060
  case "avg": return `=AVERAGE(${e}2:${e}${n})`;
@@ -994,15 +1068,15 @@ function pe(e, t, n = {}) {
994
1068
  });
995
1069
  c.push(n);
996
1070
  }
997
- be("" + [s.join(" "), ...c.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
1071
+ we("" + [s.join(" "), ...c.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
998
1072
  }
999
- function me(e, t, n, r) {
1073
+ function ve(e, t, n, r) {
1000
1074
  return async () => {
1001
1075
  let i = e.schedule;
1002
1076
  if (!i?.enabled) return [];
1003
1077
  let a = i.formats || [e.defaultExportFormat || "pdf"], o = [];
1004
1078
  for (let r of a) {
1005
- let i = await fe(e, {
1079
+ let i = await $(e, {
1006
1080
  dataSource: t,
1007
1081
  resource: n,
1008
1082
  format: r
@@ -1012,16 +1086,16 @@ function me(e, t, n, r) {
1012
1086
  return r(e, i), o;
1013
1087
  };
1014
1088
  }
1015
- function he(e) {
1089
+ function ye(e) {
1016
1090
  return {
1017
1091
  name: e.name,
1018
1092
  header: e.label || e.name
1019
1093
  };
1020
1094
  }
1021
- function ge(e, t) {
1022
- return e == null ? "" : typeof e == "number" && t ? e.toLocaleString("en-US", _e(t)) : ye(String(e));
1095
+ function be(e, t) {
1096
+ return e == null ? "" : typeof e == "number" && t ? e.toLocaleString("en-US", xe(t)) : Ce(String(e));
1023
1097
  }
1024
- function _e(e) {
1098
+ function xe(e) {
1025
1099
  if (e.includes("%")) return {
1026
1100
  style: "percent",
1027
1101
  minimumFractionDigits: 0
@@ -1032,23 +1106,23 @@ function _e(e) {
1032
1106
  maximumFractionDigits: Math.max(0, t - 1)
1033
1107
  };
1034
1108
  }
1035
- function ve(e) {
1109
+ function Se(e) {
1036
1110
  let t = "", n = e;
1037
1111
  for (; n >= 0;) t = String.fromCharCode(n % 26 + 65) + t, n = Math.floor(n / 26) - 1;
1038
1112
  return t;
1039
1113
  }
1040
- function ye(e) {
1114
+ function Ce(e) {
1041
1115
  if (e.length > 0) {
1042
1116
  let t = e.charAt(0);
1043
1117
  if (t === "=" || t === "+" || t === "-" || t === "@" || t === "|") return `'${e}`;
1044
1118
  }
1045
1119
  return e;
1046
1120
  }
1047
- function be(e, t, n) {
1121
+ function we(e, t, n) {
1048
1122
  let r = new Blob([e], { type: `${n};charset=utf-8` }), i = URL.createObjectURL(r), a = document.createElement("a");
1049
1123
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
1050
1124
  }
1051
- e.register("report", $, {
1125
+ e.register("report", Q, {
1052
1126
  namespace: "report",
1053
1127
  label: "Report",
1054
1128
  category: "Report",
@@ -1069,7 +1143,7 @@ e.register("report", $, {
1069
1143
  label: "Chart Configuration"
1070
1144
  }
1071
1145
  ]
1072
- }), e.register("spec-report", $, {
1146
+ }), e.register("spec-report", Q, {
1073
1147
  namespace: "report",
1074
1148
  label: "Spec Report",
1075
1149
  category: "Report",
@@ -1082,7 +1156,7 @@ e.register("report", $, {
1082
1156
  type: "string",
1083
1157
  label: "Report Type"
1084
1158
  }]
1085
- }), e.register("report-viewer", U, {
1159
+ }), e.register("report-viewer", V, {
1086
1160
  namespace: "report",
1087
1161
  label: "Report Viewer",
1088
1162
  category: "Report",
@@ -1097,4 +1171,4 @@ e.register("report", $, {
1097
1171
  }]
1098
1172
  });
1099
1173
  //#endregion
1100
- export { de as DatasetReportRenderer, M as LegacyReportRenderer, $ as ReportRenderer, U as ReportViewer, me as createScheduleTrigger, N as exportAsCSV, I as exportAsExcel, F as exportAsHTML, P as exportAsJSON, ee as exportAsPDF, pe as exportExcelWithFormulas, L as exportReport, fe as exportWithLiveData, H as formatValue, W as isDatasetReport, a as mergeFilters };
1174
+ export { ge as DatasetReportRenderer, j as LegacyReportRenderer, Q as ReportRenderer, V as ReportViewer, ve as createScheduleTrigger, M as exportAsCSV, F as exportAsExcel, P as exportAsHTML, N as exportAsJSON, te as exportAsPDF, _e as exportExcelWithFormulas, I as exportReport, $ as exportWithLiveData, B as formatValue, H as isDatasetReport, a as mergeFilters };