@object-ui/plugin-report 17.1.0 → 17.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,125 @@
1
1
  # @object-ui/plugin-report
2
2
 
3
+ ## 17.2.0
4
+
5
+ ### Patch Changes
6
+
7
+ - d9668a7: Honor the server's declared percent scale, so a ratio of exactly 1 renders as 100.0% (#3136)
8
+
9
+ A dataset measure declared `format: '0.0%'` rendered every ratio below 1
10
+ correctly and got the single most consequential one wrong: a rate of exactly
11
+ `1` printed as **`1.0%`**. On an SLA / pass-rate dashboard that turns
12
+ "everything met the SLA" into "1% met the SLA", on both surfaces the issue
13
+ names — the KPI card and the dataset-bound table (they share `formatMeasure`).
14
+
15
+ The cause was never a bad multiplier; it was a missing fact. `formatMeasure`
16
+ scaled by magnitude — `percentDisplayValue` multiplies by 100 only strictly
17
+ inside `(-1, 1)` — because the column arrived with a `%` format string and
18
+ nothing saying what scale its numbers were on. That guess is undecidable at
19
+ exactly 1, which is both a full-compliance ratio ("100%") and one percentage
20
+ point ("1%"), and it resolved to the reading almost nobody means.
21
+
22
+ The server now answers the question instead (framework: `percentScaleOf` +
23
+ `AnalyticsResult.fields[].percentScale`, the sibling of the ADR-0053 currency
24
+ chain): a `derived: { op: 'ratio' }` measure is a `fraction` by definition, and
25
+ a measure over a `percent` field inherits that field's scale. `formatMeasure`
26
+ takes the declared scale as a fourth argument and, when present, scales by it —
27
+ `fraction` ×100, `whole` verbatim — instead of inspecting the value. Every
28
+ dataset-bound call site passes the column's `percentScale`: the dashboard
29
+ metric/table/pivot cells, the report renderer's cells, totals and KPI, and the
30
+ dataset preview.
31
+
32
+ `percentDisplayValue` is untouched and still the fallback for a column that
33
+ arrives without the annotation (an older server, or a non-dataset percent cell
34
+ in a list view), so nothing that renders correctly today changes.
35
+
36
+ - 022e4c3: Upgrade to `@objectstack/spec@17.0.0-rc.1`, stop offering the retired `wait` timeout fields (#3101), and route the newly-adopted `combo` chart type.
37
+
38
+ **Breaking for authoring, and the reason to do it now**: the `wait` panel no longer offers
39
+ `waitEventConfig.timeoutMs` or `.onTimeout`. Both are `retiredKey()` tombstones as of spec
40
+ 17.0.0-rc.1 (framework#4158), which means a value written there is **rejected at load** —
41
+ so until this lands, Studio can produce flow metadata the author's own runtime refuses.
42
+ That hazard opened the moment rc.1 published, independent of when this repo bumps.
43
+
44
+ `wait` never had a timeout: `onTimeout` had zero readers, so neither `'fail'` nor
45
+ `'continue'` ever happened, and `timeoutMs`'s only reader used it as the timer **duration**
46
+ when `timerDuration` was absent. Use **Duration** — it accepts a bare number as
47
+ milliseconds, making the old `timeoutMs: 60000` and `timerDuration: '60000'` the same wait.
48
+ Stored flows are converted by framework's D2 conversion; the designer simply stops offering
49
+ the entry. The two `zh` label overrides go with the fields.
50
+
51
+ #3101 asked for this to ride along with the bump rather than land alone, and that is
52
+ load-bearing: the sibling-block assertion is **bidirectional**, so deleting the fields
53
+ against a spec that still declares them fails in the other direction.
54
+
55
+ **`combo` is now a spec chart type** — the sole addition to `ChartTypeSchema` in rc.1 (19
56
+ members → 20). It had been a renderer-local family the chart renderer derived from the
57
+ series, so nothing classified it on the two surfaces that route a _spec_ chart type: a
58
+ spec-valid `combo` fell through to the red "Unknown component type" panel on a dashboard
59
+ and to the out-of-spec notice on a report. Both now route it
60
+ (`widgetDispatch.SERIES_CHART_TYPES`, `planReportChart`). The renderer-local derivation
61
+ stays — it is what makes an authored `type: 'combo'` render rather than merely validate.
62
+
63
+ **Retired spec exports this repo bound to**, all removed upstream in spec 17.0.0:
64
+
65
+ - `JoinStrategy` / `WindowFunction` (framework#4286 tombstoned `query.joins` and
66
+ `query.windowFunctions`: no engine or driver ever read either on the query path). They
67
+ were derived off the spec enums under objectstack#4115's "come off the spec enum, not a
68
+ restatement" rule; with no enum left, `data-protocol.ts` now restates the members locally
69
+ — verbatim from the last spec that published them — as the objectui query-AST vocabulary
70
+ they have become. The AST itself is unchanged.
71
+ - `PerformanceConfig`, retired with `dashboard.performance` (framework#3896). Nothing bound
72
+ to it — `@object-ui/react`'s `usePerformance` declares its own interface and is untouched.
73
+ The dashboard form is derived from the spec's own `dashboardForm`, so the field
74
+ disappears from the inspector for free; its test now pins the absence.
75
+
76
+ **Three inverted pins fired, and are recorded rather than resolved.** objectstack#4171's
77
+ tripwires asserted that `NavigationItem`, `FormField` and `ConditionalValidation`'s branches
78
+ still erased to `any`/`unknown` upstream — the premise that justified objectui keeping local
79
+ declarations. rc.1 types them properly, so the assertions are inverted to state the new
80
+ fact. The burn-down each one asks for — deriving those types from the spec — touches
81
+ widely-used public types and is deliberately **not** bundled into a version bump; it is
82
+ tracked in #3177. `JoinNode`'s pin is gone outright: the symbol no longer exists.
83
+
84
+ **What the bump arms.** The reconciliation ledger's `subflow` and `decision` panels
85
+ feature-detect their spec exports and had never actually run — rc.0 predates the exports
86
+ (framework#4278). They now execute and pass. The `script` panel's full bidirectional check
87
+ stays deliberately skipped: rc.1 predates framework#4343, so the retired dispatch branches
88
+ are still contract keys there, and only the "offers nothing the executor ignores" direction
89
+ is meaningful. It arms itself on the next rc.
90
+
91
+ - Updated dependencies [4ae0ac4]
92
+ - Updated dependencies [696e3c1]
93
+ - Updated dependencies [bca45cc]
94
+ - Updated dependencies [a889e31]
95
+ - Updated dependencies [09d30a4]
96
+ - Updated dependencies [4bf612c]
97
+ - Updated dependencies [335041c]
98
+ - Updated dependencies [b414983]
99
+ - Updated dependencies [256f8cc]
100
+ - Updated dependencies [d9668a7]
101
+ - Updated dependencies [4b470b9]
102
+ - Updated dependencies [785b8a5]
103
+ - Updated dependencies [cb82705]
104
+ - Updated dependencies [f572849]
105
+ - Updated dependencies [4a51e77]
106
+ - Updated dependencies [f6e8d78]
107
+ - Updated dependencies [ea96284]
108
+ - Updated dependencies [d3584c6]
109
+ - Updated dependencies [a8ad6c0]
110
+ - Updated dependencies [444457c]
111
+ - Updated dependencies [850033c]
112
+ - Updated dependencies [022e4c3]
113
+ - Updated dependencies [009e25d]
114
+ - Updated dependencies [726b89c]
115
+ - @object-ui/types@17.2.0
116
+ - @object-ui/components@17.2.0
117
+ - @object-ui/core@17.2.0
118
+ - @object-ui/react@17.2.0
119
+ - @object-ui/i18n@17.2.0
120
+ - @object-ui/plugin-grid@17.2.0
121
+ - @object-ui/fields@17.2.0
122
+
3
123
  ## 17.1.0
4
124
 
5
125
  ### Minor Changes
@@ -167,6 +167,11 @@ export type ReportChartPlan =
167
167
  * renders beneath the chart slot is exactly the tabular presentation;
168
168
  * - anything else is out-of-spec and gets a visible notice.
169
169
  *
170
+ * `combo` joined `ChartTypeSchema` in spec 17.0.0-rc.1 and routes as a series
171
+ * chart. It was renderer-local until then — the chart renderer derives the base
172
+ * family from the series — so nothing here classified it, and a spec-valid combo
173
+ * report hit the out-of-spec notice the moment the spec started accepting one.
174
+ *
170
175
  * Exported for the spec-parity test, which fails the moment `ChartTypeSchema`
171
176
  * and this classification drift in either direction.
172
177
  */
package/dist/index.js CHANGED
@@ -650,7 +650,7 @@ function ue({ dataset: e, rows: a, values: o, runtimeFilter: s, dataSource: c, o
650
650
  onClick: h ? () => _(e, t) : void 0,
651
651
  children: S.map((t) => /* @__PURE__ */ b("td", {
652
652
  className: "px-2 py-1 tabular-nums whitespace-nowrap",
653
- children: o.includes(t) ? i(e[t], v(t)?.format, v(t)?.currency) : r(e[t])
653
+ children: o.includes(t) ? i(e[t], v(t)?.format, v(t)?.currency, v(t)?.percentScale) : r(e[t])
654
654
  }, t))
655
655
  }, t)), C && /* @__PURE__ */ x("tr", {
656
656
  className: "border-t bg-muted/30 font-medium",
@@ -661,7 +661,7 @@ function ue({ dataset: e, rows: a, values: o, runtimeFilter: s, dataSource: c, o
661
661
  children: w
662
662
  }), o.map((e) => /* @__PURE__ */ b("td", {
663
663
  className: "px-2 py-1 tabular-nums whitespace-nowrap",
664
- children: i(C[e], v(e)?.format, v(e)?.currency)
664
+ children: i(C[e], v(e)?.format, v(e)?.currency, v(e)?.percentScale)
665
665
  }, e))]
666
666
  })] })]
667
667
  })
@@ -688,7 +688,8 @@ function fe(e) {
688
688
  case "scatter":
689
689
  case "treemap":
690
690
  case "sankey":
691
- case "radar": return {
691
+ case "radar":
692
+ case "combo": return {
692
693
  kind: "series",
693
694
  chartType: e
694
695
  };
@@ -745,7 +746,7 @@ function me({ dataset: e, chart: t, runtimeFilter: r, dataSource: a, order: o })
745
746
  className: "flex flex-col gap-0.5 py-2",
746
747
  children: [/* @__PURE__ */ b("span", {
747
748
  className: "text-2xl font-semibold tabular-nums",
748
- children: i(d.rows[0]?.[c], r?.format, r?.currency)
749
+ children: i(d.rows[0]?.[c], r?.format, r?.currency, r?.percentScale)
749
750
  }), /* @__PURE__ */ b("span", {
750
751
  className: "text-xs text-muted-foreground",
751
752
  children: t(c)
@@ -882,13 +883,13 @@ function Z({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l,
882
883
  className: `px-2 py-1 text-right tabular-nums whitespace-nowrap${a ? ` ${le}` : ""}`,
883
884
  "data-testid": a ? "dataset-drill-cell" : void 0,
884
885
  onClick: a ? () => w(e.key, t.col.key, n.index) : void 0,
885
- children: i(r, _(t.measure)?.format, _(t.measure)?.currency)
886
+ children: i(r, _(t.measure)?.format, _(t.measure)?.currency, _(t.measure)?.percentScale)
886
887
  }, `${t.col.id}-${t.measure}`);
887
888
  }),
888
889
  j && c.map((t) => /* @__PURE__ */ b("td", {
889
890
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap font-medium",
890
891
  "data-testid": "matrix-row-total",
891
- children: i(D.get(e.id)?.[t], _(t)?.format, _(t)?.currency)
892
+ children: i(D.get(e.id)?.[t], _(t)?.format, _(t)?.currency, _(t)?.percentScale)
892
893
  }, `total-${t}`))
893
894
  ]
894
895
  }, e.id)), M && /* @__PURE__ */ x("tr", {
@@ -902,12 +903,12 @@ function Z({ dataset: e, rows: a, columnsAcross: s, values: c, runtimeFilter: l,
902
903
  }),
903
904
  T.map((e) => /* @__PURE__ */ b("td", {
904
905
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
905
- children: i(O.get(e.col.id)?.[e.measure], _(e.measure)?.format, _(e.measure)?.currency)
906
+ children: i(O.get(e.col.id)?.[e.measure], _(e.measure)?.format, _(e.measure)?.currency, _(e.measure)?.percentScale)
906
907
  }, `${e.col.id}-${e.measure}`)),
907
908
  j && c.map((e) => /* @__PURE__ */ b("td", {
908
909
  className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
909
910
  "data-testid": "matrix-grand-total",
910
- children: i(ee?.[e], _(e)?.format, _(e)?.currency)
911
+ children: i(ee?.[e], _(e)?.format, _(e)?.currency, _(e)?.percentScale)
911
912
  }, `grand-${e}`))
912
913
  ]
913
914
  })] })]
@@ -55,5 +55,5 @@ ${e.description?`<p class="description">${w(e.description)}</p>`:``}
55
55
  </body>
56
56
  </html>`),o.document.close(),o.onload=()=>{o.print()}}function S(e,t,n){let r=e.fields||[],i=r.map(e=>e.label||e.name),a=t.map(e=>r.map(t=>{let n=e[t.name];return n=T(n),typeof n==`string`&&(n.includes(`,`)||n.includes(`"`)||n.includes(`
57
57
  `)||n.includes(` `))?`"${n.replace(/"/g,`""`)}"`:n??``}));O(``+[...n?.includeHeaders===!1?[]:[i.join(` `)],...a.map(e=>e.join(` `))].join(`
58
- `),n?.filename||`${e.title||`report`}.tsv`,`text/tab-separated-values`)}function C(e,t,n,r){switch(e){case`csv`:v(t,n,r);break;case`json`:y(t,n,r);break;case`html`:b(t,n,r);break;case`pdf`:x(t,n,r);break;case`excel`:S(t,n,r);break;default:console.warn(`Unsupported export format: ${e}`)}}function w(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#039;`)}function T(e){if(typeof e==`string`&&e.length>0){let t=e.charAt(0);if(t===`=`||t===`+`||t===`-`||t===`@`||t===`|`)return`\t${e}`}return e}function E(e){return[`A4`,`A3`,`Letter`,`Legal`].includes(e||``)?e:`A4`}function D(e){return e===`landscape`?`landscape`:`portrait`}function O(e,t,n){let r=new Blob([e],{type:`${n};charset=utf-8`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=t,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(i)}function k(e,t){if(e==null||e===``)return``;let n=t?.type,r=t?.format;if(n===`date`||r===`date`||A(e))return j(e);if(n===`number`||typeof e==`number`){let t=typeof e==`number`?e:Number(e);return isNaN(t)?String(e):r===`currency`||r===`currency_cny`?`¥${t.toLocaleString(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0})}`:r===`currency_usd`?`$${t.toLocaleString(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0})}`:r===`percent`?`${t.toLocaleString(`en-US`,{minimumFractionDigits:1,maximumFractionDigits:1})}%`:t.toLocaleString(`en-US`)}return String(e)}function A(e){return typeof e==`string`&&/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/.test(e)}function j(e){try{let t=new Date(e);return isNaN(t.getTime())?String(e):`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`}catch{return String(e)}}function ee(e,t){if(!t||t.length===0||!e||e.length===0)return null;let n=t[0],r=n.field,i=new Map;for(let t of e){let e=String(t[r]??`(empty)`);i.has(e)||i.set(e,[]),i.get(e).push(t)}let a=[];for(let[e,t]of i)a.push({key:e,label:`${n.label||r}: ${e}`,rows:t});let o=n.sort===`desc`?-1:1;return a.sort((e,t)=>e.key.localeCompare(t.key)*o),a}function M(e,t,n){if(!e)return 0;let r=e.map(e=>Number(e[t])||0);switch(n){case`count`:return e.length;case`sum`:return r.reduce((e,t)=>e+t,0);case`avg`:return r.length>0?(r.reduce((e,t)=>e+t,0)/r.length).toFixed(2):0;case`min`:return r.length>0?Math.min(...r):0;case`max`:return r.length>0?Math.max(...r):0;case`distinct`:return new Set(e.map(e=>e[t])).size;default:return``}}var N=({schema:e,onRefresh:t})=>{let{report:r,data:l,showToolbar:u=!0,allowExport:d=!0,allowPrint:f=!0,loading:p=!1}=e,m=e=>{if(!r){console.warn(`ReportViewer: Cannot export, no report defined`);return}C(e,r,l||[],r.exportConfigs?.[e])},h=()=>{window.print()},g=()=>{t?.()},_=(e,t)=>M(l,e,t),v=(e,t)=>{let n=r?.conditionalFormatting;if(!(!n||!Array.isArray(n)))for(let r of n){if(r.field!==e)continue;let n=String(t??``),i=String(r.value??``),a=!1;switch(r.operator){case`equals`:a=n===i;break;case`not_equals`:a=n!==i;break;case`contains`:a=n.includes(i);break;case`greater_than`:a=Number(t)>Number(r.value);break;case`less_than`:a=Number(t)<Number(r.value);break}if(a){let e={};return r.backgroundColor&&(e.backgroundColor=r.backgroundColor),r.textColor&&(e.color=r.textColor),e}}},y=(e,t)=>{if(e==null||e===``)return``;if(t.renderAs===`badge`&&(!t.type||t.type===`string`||t.type===`text`))return(0,o.jsx)(a.Badge,{className:t.colorMap?.[String(e)]||``,children:String(e)});if(t.aggregation)return k(e,t);if(t.type){let n={...t};return t.colorMap&&!n.options&&(n.options=Object.entries(t.colorMap).map(([e,t])=>({value:e,label:e,color:t}))),(0,o.jsx)((0,c.getCellRenderer)((0,c.resolveCellRendererType)(n)),{value:e,field:n})}return k(e,t)};return r?(0,o.jsxs)(`div`,{className:`space-y-4`,children:[u&&(0,o.jsxs)(`div`,{className:`flex items-center justify-between gap-2 p-4 bg-card rounded-lg border`,children:[(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h2`,{className:`text-lg font-semibold`,children:r.title}),r.description&&(0,o.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:r.description})]}),(0,o.jsxs)(`div`,{className:`flex items-center gap-2`,children:[r.refreshInterval&&(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:g,children:[(0,o.jsx)(s.RefreshCw,{className:`h-4 w-4 mr-2`}),`Refresh`]}),f&&(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:h,children:[(0,o.jsx)(s.Printer,{className:`h-4 w-4 mr-2`}),`Print`]}),d&&r.showExportButtons&&(0,o.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:()=>m(`pdf`),children:[(0,o.jsx)(s.Download,{className:`h-4 w-4 mr-2`}),`PDF`]}),(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:()=>m(`excel`),children:[(0,o.jsx)(s.Download,{className:`h-4 w-4 mr-2`}),`Excel`]}),(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:()=>m(`csv`),children:[(0,o.jsx)(s.Download,{className:`h-4 w-4 mr-2`}),`CSV`]})]})]})]}),(0,o.jsxs)(a.Card,{children:[(0,o.jsxs)(a.CardHeader,{children:[!u&&r.title&&(0,o.jsx)(a.CardTitle,{children:r.title}),!u&&r.description&&(0,o.jsx)(a.CardDescription,{children:r.description})]}),(0,o.jsxs)(a.CardContent,{className:`space-y-6`,children:[p&&(0,o.jsxs)(`div`,{className:`space-y-6`,children:[(0,o.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:[1,2,3].map(e=>(0,o.jsx)(a.Card,{children:(0,o.jsxs)(a.CardContent,{className:`p-4 space-y-2`,children:[(0,o.jsx)(a.Skeleton,{className:`h-4 w-20`}),(0,o.jsx)(a.Skeleton,{className:`h-8 w-28`})]})},e))}),(0,o.jsxs)(`div`,{className:`space-y-2`,children:[(0,o.jsx)(a.Skeleton,{className:`h-10 w-full`}),[1,2,3,4,5].map(e=>(0,o.jsx)(a.Skeleton,{className:`h-8 w-full`},e))]})]}),!p&&r.sections?.map((e,t)=>e.visible===!1?null:(0,o.jsxs)(`div`,{className:`space-y-2`,children:[e.title&&e.type!==`header`&&(0,o.jsx)(`h3`,{className:`text-lg font-semibold border-b pb-2`,children:e.title}),e.type===`header`&&e.title&&(0,o.jsx)(`div`,{className:`text-2xl font-bold py-4`,children:e.title}),e.type===`summary`&&(0,o.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:r.fields?.filter(e=>e.showInSummary).map((e,t)=>(0,o.jsx)(a.Card,{children:(0,o.jsxs)(a.CardContent,{className:`p-4`,children:[(0,o.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:e.label||e.name}),(0,o.jsx)(`div`,{className:`text-2xl font-bold`,children:k(_(e.name,e.aggregation),e)})]})},t))}),e.type===`table`&&(0,o.jsx)(`div`,{className:`border rounded-lg overflow-x-auto`,children:(0,o.jsxs)(`table`,{className:`w-full text-sm min-w-[600px]`,children:[(0,o.jsx)(`thead`,{className:`bg-muted`,children:(0,o.jsx)(`tr`,{children:e.columns?.map((e,t)=>(0,o.jsx)(`th`,{className:`px-4 py-2 font-medium ${e.type===`number`?`text-right`:`text-left`}`,children:e.label||e.name},t))})}),(0,o.jsx)(`tbody`,{children:(()=>{let t=ee(l||[],r.groupBy||[]);return t?t.map(t=>(0,o.jsxs)(n.default.Fragment,{children:[(0,o.jsx)(`tr`,{className:`bg-muted/60`,children:(0,o.jsxs)(`td`,{colSpan:e.columns?.length||1,className:`px-4 py-2 font-semibold text-sm`,children:[t.label,` (`,t.rows.length,`)`]})}),t.rows.map((t,n)=>(0,o.jsx)(`tr`,{className:`border-t hover:bg-muted/50 even:bg-muted/20`,children:e.columns?.map((e,n)=>(0,o.jsx)(`td`,{className:`px-4 py-2 ${e.type===`number`?`text-right tabular-nums`:``}`,style:v(e.name,t[e.name]),children:y(t[e.name],e)},n))},n))]},t.key)):l?.map((t,n)=>(0,o.jsx)(`tr`,{className:`border-t hover:bg-muted/50 even:bg-muted/20`,children:e.columns?.map((e,n)=>(0,o.jsx)(`td`,{className:`px-4 py-2 ${e.type===`number`?`text-right tabular-nums`:``}`,style:v(e.name,t[e.name]),children:y(t[e.name],e)},n))},n))})()})]})}),e.type===`text`&&e.text&&(0,o.jsx)(`div`,{className:`prose max-w-none`,children:(0,o.jsx)(`p`,{children:e.text})}),e.type===`page-break`&&(0,o.jsx)(`div`,{className:`border-t-2 border-dashed my-8 print:page-break-after-always`}),e.content&&(0,o.jsx)(i.SchemaRenderer,{schema:e.content})]},t)),!r.sections&&l&&l.length>0&&(0,o.jsx)(`div`,{className:`border rounded-lg overflow-x-auto`,children:(0,o.jsxs)(`table`,{className:`w-full text-sm min-w-[600px]`,children:[(0,o.jsx)(`thead`,{className:`bg-muted`,children:(0,o.jsx)(`tr`,{children:r.fields?.map((e,t)=>(0,o.jsx)(`th`,{className:`px-4 py-2 font-medium ${e.type===`number`?`text-right`:`text-left`}`,children:e.label||e.name},t))})}),(0,o.jsx)(`tbody`,{children:l.map((e,t)=>(0,o.jsx)(`tr`,{className:`border-t hover:bg-muted/50 even:bg-muted/20`,children:r.fields?.map((t,n)=>(0,o.jsx)(`td`,{className:`px-4 py-2 ${t.type===`number`?`text-right tabular-nums`:``}`,style:v(t.name,e[t.name]),children:y(e[t.name],t)},n))},t))})]})})]})]})]}):(0,o.jsx)(a.Card,{children:(0,o.jsx)(a.CardContent,{className:`p-8 text-center text-muted-foreground`,children:`No report to display`})})};function P(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.dataset==`string`&&t.dataset.length>0||t.type===`joined`&&Array.isArray(t.blocks)&&t.blocks.some(e=>typeof e?.dataset==`string`)}function F(e,t){return e?typeof e==`string`?e:typeof e==`object`&&typeof e.default==`string`?e.default:t:t}function I(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&!!e):[]}function L(e){if(!Array.isArray(e))return;let t={};for(let n of e){let e=n&&typeof n==`object`?n.by:void 0;typeof e!=`string`||!e||(t[e]=n.direction===`desc`?`desc`:`asc`)}return Object.keys(t).length>0?t:void 0}function R(e,t,n){if(!e)return;let r=new Set([...t,...n]),i={};for(let[t,n]of Object.entries(e))r.has(t)&&(i[t]=n);return Object.keys(i).length>0?i:void 0}function z(e,t,r,i,a,o,s){let[c,l]=n.useState({status:`idle`,rows:[]}),u=R(s,t,r),d=JSON.stringify(i??null),f=JSON.stringify(o??null),p=JSON.stringify(u??null),m=`${e}|${t.join(`,`)}|${r.join(`,`)}|${d}|${f}|${p}`;return n.useEffect(()=>{let n=a;if(!n||typeof n.queryDataset!=`function`){l({status:`error`,rows:[],error:`This data source does not support dataset queries.`});return}if(!e||r.length===0){l({status:`idle`,rows:[]});return}let s=!1;return l({status:`loading`,rows:[]}),n.queryDataset(e,{dimensions:t,measures:r,...i&&Object.keys(i).length>0?{runtimeFilter:i}:{},...o?{totals:{groupings:o}}:{},...u?{order:u}:{}}).then(e=>{s||l({status:`ok`,rows:Array.isArray(e?.rows)?e.rows:[],fields:Array.isArray(e?.fields)?e.fields:[],object:e?.object,dimensionFields:e?.dimensionFields,drillRawRows:Array.isArray(e?.drillRawRows)?e.drillRawRows:void 0,drillRanges:Array.isArray(e?.drillRanges)?e.drillRanges:void 0,totals:Array.isArray(e?.totals)?e.totals:void 0})}).catch(e=>{s||l({status:`error`,rows:[],error:String(e?.message??e)})}),()=>{s=!0}},[m]),c}function B({dataset:e}){return(0,o.jsxs)(`div`,{className:`flex items-center justify-center rounded-md border border-dashed bg-muted/20 p-4 text-xs text-muted-foreground`,children:[`This report binds the “`,e,`” dataset — choose at least one measure (values) to render.`]})}function V({status:e,error:t}){return e===`error`?(0,o.jsxs)(`div`,{role:`alert`,className:`flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive`,children:[(0,o.jsx)(s.AlertTriangle,{className:`h-3.5 w-3.5 mt-0.5 shrink-0`}),(0,o.jsx)(`span`,{className:`break-words`,children:t})]}):(0,o.jsxs)(`div`,{className:`flex items-center gap-2 p-4 text-xs text-muted-foreground`,children:[(0,o.jsx)(s.Loader2,{className:`h-4 w-4 animate-spin`}),` Running report…`]})}function H(){return(0,o.jsxs)(`div`,{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`,children:[(0,o.jsx)(s.Table2,{className:`h-6 w-6`}),` The dataset returned no rows for this report’s scope.`]})}var U=`cursor-pointer hover:bg-accent/40`;function W({dataset:e,rows:n,values:r,runtimeFilter:i,dataSource:a,onDrill:s,order:c,withTotals:u}){let d=z(e,n,r,i,a,u&&n.length>0?[[]]:void 0,c),{fieldLabel:f}=(0,l.useSafeFieldLabel)(),p=(0,l.useSafeTranslate)();if(r.length===0)return(0,o.jsx)(B,{dataset:e});if(d.status===`loading`||d.status===`idle`)return(0,o.jsx)(V,{status:d.status});if(d.status===`error`)return(0,o.jsx)(V,{status:`error`,error:d.error});if(d.rows.length===0)return(0,o.jsx)(H,{});let m=!!s&&n.length>0,h=d.dimensionFields?n.filter(e=>e in d.dimensionFields):[],g=(r,a)=>{let o={};for(let e of n)o[e]=r[e];let c=d.drillRanges?.[a],l=!!c&&Object.keys(c).length>0,u=d.object&&(h.length>0||l)?(0,t.buildDatasetDrillFilter)(d.drillRawRows?.[a],h,d.dimensionFields??{},i,c):void 0;s({dataset:e,groupKey:o,runtimeFilter:i,object:d.object,objectFilter:u})},{measureField:_,headerLabel:v}=(0,t.buildDatasetFieldHelpers)(d.fields,d.object,f),y=[...n,...r],b=u?d.totals?.find(e=>Array.isArray(e.dimensions)&&e.dimensions.length===0)?.rows?.[0]:void 0,x=p(`report.total`,`Total`);return(0,o.jsx)(`div`,{className:`overflow-auto max-h-[70vh] rounded-md border`,children:(0,o.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,o.jsx)(`thead`,{className:`bg-muted/40`,children:(0,o.jsx)(`tr`,{children:y.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-left font-medium whitespace-nowrap`,children:v(e)},e))})}),(0,o.jsxs)(`tbody`,{children:[d.rows.map((e,n)=>(0,o.jsx)(`tr`,{className:`border-t${m?` ${U}`:``}`,"data-testid":m?`dataset-drill-row`:void 0,onClick:m?()=>g(e,n):void 0,children:y.map(n=>(0,o.jsx)(`td`,{className:`px-2 py-1 tabular-nums whitespace-nowrap`,children:r.includes(n)?(0,t.formatMeasure)(e[n],_(n)?.format,_(n)?.currency):(0,t.formatDimensionValue)(e[n])},n))},n)),b&&(0,o.jsxs)(`tr`,{className:`border-t bg-muted/30 font-medium`,"data-testid":`dataset-report-total-row`,children:[n.length>0&&(0,o.jsx)(`td`,{colSpan:n.length,className:`px-2 py-1 whitespace-nowrap`,children:x}),r.map(e=>(0,o.jsx)(`td`,{className:`px-2 py-1 tabular-nums whitespace-nowrap`,children:(0,t.formatMeasure)(b[e],_(e)?.format,_(e)?.currency)},e))]})]})]})})}function G(e){switch(e){case`summary`:return`summary`;case`matrix`:return`matrix`;case`joined`:return`joined`;default:return`tabular`}}function te(e){switch(e){case`bar`:case`column`:case`horizontal-bar`:case`line`:case`area`:case`pie`:case`donut`:case`funnel`:case`scatter`:case`treemap`:case`sankey`:case`radar`:return{kind:`series`,chartType:e};case`gauge`:case`solid-gauge`:case`metric`:case`kpi`:case`bullet`:return{kind:`single_value`};case`table`:case`pivot`:return{kind:`tabular`};default:return{kind:`unsupported`,type:String(e)}}}function ne(e){let[,r]=n.useReducer(e=>e+1,0);return n.useEffect(()=>{if(t.ComponentRegistry.get(e))return;let n=typeof t.ComponentRegistry.subscribe==`function`?t.ComponentRegistry.subscribe(()=>{t.ComponentRegistry.get(e)&&r()}):void 0,i=t.ComponentRegistry.loadLazy?.(e);return i&&typeof i.then==`function`&&i.then(()=>r()).catch(()=>{}),n},[e]),t.ComponentRegistry.get(e)}function K({dataset:e,chart:n,runtimeFilter:r,dataSource:i,order:a}){let c=typeof n.xAxis==`string`?n.xAxis:``,u=typeof n.yAxis==`string`?n.yAxis:``,d=te(n.type),f=d.kind===`series`||d.kind===`single_value`,p=z(e,d.kind===`series`&&c?[c]:[],f&&u?[u]:[],r,i,void 0,a),m=ne(`chart`),{fieldLabel:h}=(0,l.useSafeFieldLabel)(),g=typeof n.title==`string`?n.title:void 0;if(d.kind===`tabular`)return null;if(d.kind===`unsupported`)return(0,o.jsxs)(`div`,{className:`rounded-md border border-dashed bg-muted/20 px-3 py-2 text-xs text-muted-foreground`,"data-testid":`dataset-report-chart-unsupported`,children:[`Chart type “`,d.type,`” is not a spec chart type — the grouped table below carries this report’s numbers.`]});if(d.kind===`series`&&!c||!u)return null;if(p.status===`loading`||p.status===`idle`)return(0,o.jsxs)(`div`,{className:`flex items-center gap-2 p-4 text-xs text-muted-foreground`,children:[(0,o.jsx)(s.Loader2,{className:`h-4 w-4 animate-spin`}),` Loading chart…`]});if(p.status===`error`||p.rows.length===0)return null;if(d.kind===`single_value`){let{measureField:e,headerLabel:n}=(0,t.buildDatasetFieldHelpers)(p.fields,p.object,h),r=e(u);return(0,o.jsxs)(`div`,{className:`rounded-md border bg-card p-3`,"data-testid":`dataset-report-metric`,children:[g?(0,o.jsx)(`h3`,{className:`mb-2 text-sm font-semibold`,children:g}):null,(0,o.jsxs)(`div`,{className:`flex flex-col gap-0.5 py-2`,children:[(0,o.jsx)(`span`,{className:`text-2xl font-semibold tabular-nums`,children:(0,t.formatMeasure)(p.rows[0]?.[u],r?.format,r?.currency)}),(0,o.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:n(u)})]})]})}return m?(0,o.jsxs)(`div`,{className:`rounded-md border bg-card p-3`,"data-testid":`dataset-report-chart`,children:[g?(0,o.jsx)(`h3`,{className:`mb-2 text-sm font-semibold`,children:g}):null,(0,o.jsx)(m,{schema:{chartType:d.chartType,data:p.rows,xAxisKey:c,series:[{dataKey:u}],height:typeof n.height==`number`?n.height:280,isAnimationActive:!1}})]}):null}function q(e,t){return e.map(e=>String(t[e]??`∅`)).join(``)}function J(e,n){return e.map(e=>(0,t.formatDimensionValue)(n[e])).join(` / `)}function Y({dataset:e,rows:r,columnsAcross:i,values:a,runtimeFilter:s,dataSource:c,onDrill:u,order:d}){let f=z(e,[...r,...i],a,s,c,[r,i,[]],d),p=(0,l.useSafeTranslate)(),{fieldLabel:m}=(0,l.useSafeFieldLabel)(),h=n.useMemo(()=>{if(f.status!==`ok`)return null;let e=[],t=[],n=new Set,a=new Set,o=new Map;return f.rows.forEach((s,c)=>{let l=q(r,s),u=q(i,s);if(!n.has(l)){n.add(l);let t={};for(let e of r)t[e]=s[e];e.push({id:l,label:J(r,s),key:t})}if(!a.has(u)){a.add(u);let e={};for(let t of i)e[t]=s[t];t.push({id:u,label:J(i,s),key:e})}o.set(`${l} ${u}`,{row:s,index:c})}),{rowHeaders:e,colHeaders:t,cells:o}},[f,r,i]);if(a.length===0)return(0,o.jsx)(B,{dataset:e});if(f.status===`loading`||f.status===`idle`)return(0,o.jsx)(V,{status:f.status});if(f.status===`error`)return(0,o.jsx)(V,{status:`error`,error:f.error});if(!h||h.rowHeaders.length===0)return(0,o.jsx)(H,{});let{measureField:g,headerLabel:_}=(0,t.buildDatasetFieldHelpers)(f.fields,f.object,m),v=p(`report.total`,`Total`),y=!!u,b=f.dimensionFields?[...r,...i].filter(e=>e in f.dimensionFields):[],x=(n,r,i)=>{let a=f.drillRanges?.[i],o=!!a&&Object.keys(a).length>0,c=f.object&&(b.length>0||o)?(0,t.buildDatasetDrillFilter)(f.drillRawRows?.[i],b,f.dimensionFields??{},s,a):void 0;u({dataset:e,groupKey:{...n,...r},runtimeFilter:s,object:f.object,objectFilter:c})},S=h.colHeaders.flatMap(e=>a.map(t=>({col:e,measure:t,header:a.length===1?e.label:`${e.label} · ${_(t)}`}))),C=e=>f.totals?.find(t=>Array.isArray(t.dimensions)&&t.dimensions.join(`,`)===e.join(`,`))?.rows,w=new Map;for(let e of C(r)??[])w.set(q(r,e),e);let T=new Map;for(let e of C(i)??[])T.set(q(i,e),e);let E=C([])?.[0],D=w.size>0,O=T.size>0;return(0,o.jsx)(`div`,{className:`overflow-auto max-h-[70vh] rounded-md border`,"data-testid":`dataset-matrix`,children:(0,o.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,o.jsx)(`thead`,{className:`bg-muted/40`,children:(0,o.jsxs)(`tr`,{children:[r.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-left font-medium whitespace-nowrap`,children:_(e)},e)),S.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-right font-medium whitespace-nowrap`,children:e.header},`${e.col.id}-${e.measure}`)),D&&a.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-right font-medium whitespace-nowrap`,"data-testid":`matrix-total-col-header`,children:a.length===1?v:`${v} · ${_(e)}`},`total-${e}`))]})}),(0,o.jsxs)(`tbody`,{children:[h.rowHeaders.map(e=>(0,o.jsxs)(`tr`,{className:`border-t`,children:[r.map(n=>(0,o.jsx)(`td`,{className:`px-2 py-1 whitespace-nowrap font-medium`,children:(0,t.formatDimensionValue)(e.key[n])},n)),S.map(n=>{let r=h.cells.get(`${e.id} ${n.col.id}`),i=r?.row[n.measure],a=y&&r!=null;return(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap${a?` ${U}`:``}`,"data-testid":a?`dataset-drill-cell`:void 0,onClick:a?()=>x(e.key,n.col.key,r.index):void 0,children:(0,t.formatMeasure)(i,g(n.measure)?.format,g(n.measure)?.currency)},`${n.col.id}-${n.measure}`)}),D&&a.map(n=>(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap font-medium`,"data-testid":`matrix-row-total`,children:(0,t.formatMeasure)(w.get(e.id)?.[n],g(n)?.format,g(n)?.currency)},`total-${n}`))]},e.id)),O&&(0,o.jsxs)(`tr`,{className:`border-t bg-muted/30 font-medium`,"data-testid":`matrix-total-row`,children:[r.length>0&&(0,o.jsx)(`td`,{colSpan:r.length,className:`px-2 py-1 whitespace-nowrap`,children:v}),S.map(e=>(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap`,children:(0,t.formatMeasure)(T.get(e.col.id)?.[e.measure],g(e.measure)?.format,g(e.measure)?.currency)},`${e.col.id}-${e.measure}`)),D&&a.map(e=>(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap`,"data-testid":`matrix-grand-total`,children:(0,t.formatMeasure)(E?.[e],g(e)?.format,g(e)?.currency)},`grand-${e}`))]})]})]})})}var X=({report:e,dataSource:n,runtimeFilter:r,onDrill:i,className:a})=>{let s=(0,t.mergeFilters)(e.runtimeFilter??e.filter,r),c=e.drilldown===!1?void 0:i,l=G(e.type);if(l===`joined`&&Array.isArray(e.blocks))return(0,o.jsx)(`div`,{className:a,"data-testid":`dataset-joined-report`,"data-report-name":e.name,style:{display:`flex`,flexDirection:`column`,gap:24},children:e.blocks.map((e,r)=>{let i=(0,t.mergeFilters)(s,e.runtimeFilter??e.filter),a=I(e.columns),l=L(e.order),u=G(e.type),d=u===`matrix`&&a.length>0?(0,o.jsx)(Y,{dataset:String(e.dataset??``),rows:I(e.rows),columnsAcross:a,values:I(e.values),runtimeFilter:i,dataSource:n,onDrill:c,order:l}):(0,o.jsx)(W,{dataset:String(e.dataset??``),rows:I(e.rows),values:I(e.values),runtimeFilter:i,dataSource:n,onDrill:c,order:l,withTotals:u===`summary`||u===`matrix`});return(0,o.jsxs)(`section`,{"data-testid":`dataset-report-block`,"data-block-id":e.name??`block-${r}`,className:`flex flex-col gap-2 rounded-lg border bg-card p-4`,children:[(0,o.jsxs)(`header`,{className:`flex flex-col gap-0.5`,children:[(0,o.jsx)(`h3`,{className:`text-sm font-semibold`,children:F(e.label,e.name??`Block ${r+1}`)}),e.description?(0,o.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:F(e.description,``)}):null]}),d]},e.name??`block-${r}`)})});let u=I(e.columns),d=L(e.order);if(l===`matrix`&&u.length>0)return(0,o.jsx)(`div`,{className:a,"data-testid":`dataset-report`,"data-report-name":e.name,children:(0,o.jsx)(Y,{dataset:String(e.dataset??``),rows:I(e.rows),columnsAcross:u,values:I(e.values),runtimeFilter:s,dataSource:n,onDrill:c,order:d})});let f=e.chart&&typeof e.chart==`object`&&e.chart.type?e.chart:null;return(0,o.jsxs)(`div`,{className:`${a??``} flex flex-col gap-3`,"data-testid":`dataset-report`,"data-report-name":e.name,"data-report-presentation":l,children:[f?(0,o.jsx)(K,{dataset:String(e.dataset??``),chart:f,runtimeFilter:s,dataSource:n,order:d}):null,(0,o.jsx)(W,{dataset:String(e.dataset??``),rows:I(e.rows),values:I(e.values),runtimeFilter:s,dataSource:n,onDrill:c,order:d,withTotals:l===`summary`||l===`matrix`})]})},Z=e=>{let{dataSource:t,rows:a,runtimeFilter:s,onDrill:c,className:l}=e,u=n.useContext(i.SchemaRendererContext),d=t??u?.dataSource,f=e.schema;return f&&typeof f==`object`&&f.type===`spec-report`&&f.report&&typeof f.report==`object`&&(f=f.report),P(f)?(0,o.jsx)(X,{report:f,dataSource:d,runtimeFilter:s,onDrill:c,className:l}):(0,r.isSpecReport)(f)?(0,o.jsx)(`div`,{className:l,"data-testid":`report-presentation-bridge`,children:(0,o.jsx)(N,{schema:{type:`report-viewer`,report:(0,r.specReportToPresentation)(f),data:a??[],showToolbar:!1}})}):(0,o.jsx)(_,{schema:f})};async function Q(e,t){let{dataSource:n,resource:r,queryParams:i,format:a,exportConfig:o}=t,s=a||e.defaultExportFormat||`pdf`;try{let t=(await n.find(r,i)).data||[];return C(s,e,t,{format:s,...e.exportConfigs?.[s],...o}),{success:!0,recordCount:t.length,format:s}}catch(e){return{success:!1,recordCount:0,format:s,error:e.message}}}function re(e,t,n={}){let{columns:r,filename:i,includeAggregationRow:a=!1}=n,o=r||(e.fields||[]).map(ae),s=o.map(e=>e.header),c=t.map((e,t)=>o.map(n=>{if(n.formula)return n.formula.replace(/\{ROW\}/g,String(t+2));let r=e[n.name];return oe(r,n.numberFormat)}));if(a&&t.length>0){let n=o.map((n,r)=>{let i=(e.fields||[]).find(e=>e.name===n.name);if(i?.aggregation){let e=se(r),n=t.length+1;switch(i.aggregation){case`sum`:return`=SUM(${e}2:${e}${n})`;case`avg`:return`=AVERAGE(${e}2:${e}${n})`;case`count`:return`=COUNTA(${e}2:${e}${n})`;case`min`:return`=MIN(${e}2:${e}${n})`;case`max`:return`=MAX(${e}2:${e}${n})`;default:return``}}return``});c.push(n)}le(``+[s.join(` `),...c.map(e=>e.join(` `))].join(`
58
+ `),n?.filename||`${e.title||`report`}.tsv`,`text/tab-separated-values`)}function C(e,t,n,r){switch(e){case`csv`:v(t,n,r);break;case`json`:y(t,n,r);break;case`html`:b(t,n,r);break;case`pdf`:x(t,n,r);break;case`excel`:S(t,n,r);break;default:console.warn(`Unsupported export format: ${e}`)}}function w(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#039;`)}function T(e){if(typeof e==`string`&&e.length>0){let t=e.charAt(0);if(t===`=`||t===`+`||t===`-`||t===`@`||t===`|`)return`\t${e}`}return e}function E(e){return[`A4`,`A3`,`Letter`,`Legal`].includes(e||``)?e:`A4`}function D(e){return e===`landscape`?`landscape`:`portrait`}function O(e,t,n){let r=new Blob([e],{type:`${n};charset=utf-8`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=t,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(i)}function k(e,t){if(e==null||e===``)return``;let n=t?.type,r=t?.format;if(n===`date`||r===`date`||A(e))return j(e);if(n===`number`||typeof e==`number`){let t=typeof e==`number`?e:Number(e);return isNaN(t)?String(e):r===`currency`||r===`currency_cny`?`¥${t.toLocaleString(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0})}`:r===`currency_usd`?`$${t.toLocaleString(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0})}`:r===`percent`?`${t.toLocaleString(`en-US`,{minimumFractionDigits:1,maximumFractionDigits:1})}%`:t.toLocaleString(`en-US`)}return String(e)}function A(e){return typeof e==`string`&&/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/.test(e)}function j(e){try{let t=new Date(e);return isNaN(t.getTime())?String(e):`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`}catch{return String(e)}}function ee(e,t){if(!t||t.length===0||!e||e.length===0)return null;let n=t[0],r=n.field,i=new Map;for(let t of e){let e=String(t[r]??`(empty)`);i.has(e)||i.set(e,[]),i.get(e).push(t)}let a=[];for(let[e,t]of i)a.push({key:e,label:`${n.label||r}: ${e}`,rows:t});let o=n.sort===`desc`?-1:1;return a.sort((e,t)=>e.key.localeCompare(t.key)*o),a}function M(e,t,n){if(!e)return 0;let r=e.map(e=>Number(e[t])||0);switch(n){case`count`:return e.length;case`sum`:return r.reduce((e,t)=>e+t,0);case`avg`:return r.length>0?(r.reduce((e,t)=>e+t,0)/r.length).toFixed(2):0;case`min`:return r.length>0?Math.min(...r):0;case`max`:return r.length>0?Math.max(...r):0;case`distinct`:return new Set(e.map(e=>e[t])).size;default:return``}}var N=({schema:e,onRefresh:t})=>{let{report:r,data:l,showToolbar:u=!0,allowExport:d=!0,allowPrint:f=!0,loading:p=!1}=e,m=e=>{if(!r){console.warn(`ReportViewer: Cannot export, no report defined`);return}C(e,r,l||[],r.exportConfigs?.[e])},h=()=>{window.print()},g=()=>{t?.()},_=(e,t)=>M(l,e,t),v=(e,t)=>{let n=r?.conditionalFormatting;if(!(!n||!Array.isArray(n)))for(let r of n){if(r.field!==e)continue;let n=String(t??``),i=String(r.value??``),a=!1;switch(r.operator){case`equals`:a=n===i;break;case`not_equals`:a=n!==i;break;case`contains`:a=n.includes(i);break;case`greater_than`:a=Number(t)>Number(r.value);break;case`less_than`:a=Number(t)<Number(r.value);break}if(a){let e={};return r.backgroundColor&&(e.backgroundColor=r.backgroundColor),r.textColor&&(e.color=r.textColor),e}}},y=(e,t)=>{if(e==null||e===``)return``;if(t.renderAs===`badge`&&(!t.type||t.type===`string`||t.type===`text`))return(0,o.jsx)(a.Badge,{className:t.colorMap?.[String(e)]||``,children:String(e)});if(t.aggregation)return k(e,t);if(t.type){let n={...t};return t.colorMap&&!n.options&&(n.options=Object.entries(t.colorMap).map(([e,t])=>({value:e,label:e,color:t}))),(0,o.jsx)((0,c.getCellRenderer)((0,c.resolveCellRendererType)(n)),{value:e,field:n})}return k(e,t)};return r?(0,o.jsxs)(`div`,{className:`space-y-4`,children:[u&&(0,o.jsxs)(`div`,{className:`flex items-center justify-between gap-2 p-4 bg-card rounded-lg border`,children:[(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h2`,{className:`text-lg font-semibold`,children:r.title}),r.description&&(0,o.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:r.description})]}),(0,o.jsxs)(`div`,{className:`flex items-center gap-2`,children:[r.refreshInterval&&(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:g,children:[(0,o.jsx)(s.RefreshCw,{className:`h-4 w-4 mr-2`}),`Refresh`]}),f&&(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:h,children:[(0,o.jsx)(s.Printer,{className:`h-4 w-4 mr-2`}),`Print`]}),d&&r.showExportButtons&&(0,o.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:()=>m(`pdf`),children:[(0,o.jsx)(s.Download,{className:`h-4 w-4 mr-2`}),`PDF`]}),(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:()=>m(`excel`),children:[(0,o.jsx)(s.Download,{className:`h-4 w-4 mr-2`}),`Excel`]}),(0,o.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:()=>m(`csv`),children:[(0,o.jsx)(s.Download,{className:`h-4 w-4 mr-2`}),`CSV`]})]})]})]}),(0,o.jsxs)(a.Card,{children:[(0,o.jsxs)(a.CardHeader,{children:[!u&&r.title&&(0,o.jsx)(a.CardTitle,{children:r.title}),!u&&r.description&&(0,o.jsx)(a.CardDescription,{children:r.description})]}),(0,o.jsxs)(a.CardContent,{className:`space-y-6`,children:[p&&(0,o.jsxs)(`div`,{className:`space-y-6`,children:[(0,o.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:[1,2,3].map(e=>(0,o.jsx)(a.Card,{children:(0,o.jsxs)(a.CardContent,{className:`p-4 space-y-2`,children:[(0,o.jsx)(a.Skeleton,{className:`h-4 w-20`}),(0,o.jsx)(a.Skeleton,{className:`h-8 w-28`})]})},e))}),(0,o.jsxs)(`div`,{className:`space-y-2`,children:[(0,o.jsx)(a.Skeleton,{className:`h-10 w-full`}),[1,2,3,4,5].map(e=>(0,o.jsx)(a.Skeleton,{className:`h-8 w-full`},e))]})]}),!p&&r.sections?.map((e,t)=>e.visible===!1?null:(0,o.jsxs)(`div`,{className:`space-y-2`,children:[e.title&&e.type!==`header`&&(0,o.jsx)(`h3`,{className:`text-lg font-semibold border-b pb-2`,children:e.title}),e.type===`header`&&e.title&&(0,o.jsx)(`div`,{className:`text-2xl font-bold py-4`,children:e.title}),e.type===`summary`&&(0,o.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:r.fields?.filter(e=>e.showInSummary).map((e,t)=>(0,o.jsx)(a.Card,{children:(0,o.jsxs)(a.CardContent,{className:`p-4`,children:[(0,o.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:e.label||e.name}),(0,o.jsx)(`div`,{className:`text-2xl font-bold`,children:k(_(e.name,e.aggregation),e)})]})},t))}),e.type===`table`&&(0,o.jsx)(`div`,{className:`border rounded-lg overflow-x-auto`,children:(0,o.jsxs)(`table`,{className:`w-full text-sm min-w-[600px]`,children:[(0,o.jsx)(`thead`,{className:`bg-muted`,children:(0,o.jsx)(`tr`,{children:e.columns?.map((e,t)=>(0,o.jsx)(`th`,{className:`px-4 py-2 font-medium ${e.type===`number`?`text-right`:`text-left`}`,children:e.label||e.name},t))})}),(0,o.jsx)(`tbody`,{children:(()=>{let t=ee(l||[],r.groupBy||[]);return t?t.map(t=>(0,o.jsxs)(n.default.Fragment,{children:[(0,o.jsx)(`tr`,{className:`bg-muted/60`,children:(0,o.jsxs)(`td`,{colSpan:e.columns?.length||1,className:`px-4 py-2 font-semibold text-sm`,children:[t.label,` (`,t.rows.length,`)`]})}),t.rows.map((t,n)=>(0,o.jsx)(`tr`,{className:`border-t hover:bg-muted/50 even:bg-muted/20`,children:e.columns?.map((e,n)=>(0,o.jsx)(`td`,{className:`px-4 py-2 ${e.type===`number`?`text-right tabular-nums`:``}`,style:v(e.name,t[e.name]),children:y(t[e.name],e)},n))},n))]},t.key)):l?.map((t,n)=>(0,o.jsx)(`tr`,{className:`border-t hover:bg-muted/50 even:bg-muted/20`,children:e.columns?.map((e,n)=>(0,o.jsx)(`td`,{className:`px-4 py-2 ${e.type===`number`?`text-right tabular-nums`:``}`,style:v(e.name,t[e.name]),children:y(t[e.name],e)},n))},n))})()})]})}),e.type===`text`&&e.text&&(0,o.jsx)(`div`,{className:`prose max-w-none`,children:(0,o.jsx)(`p`,{children:e.text})}),e.type===`page-break`&&(0,o.jsx)(`div`,{className:`border-t-2 border-dashed my-8 print:page-break-after-always`}),e.content&&(0,o.jsx)(i.SchemaRenderer,{schema:e.content})]},t)),!r.sections&&l&&l.length>0&&(0,o.jsx)(`div`,{className:`border rounded-lg overflow-x-auto`,children:(0,o.jsxs)(`table`,{className:`w-full text-sm min-w-[600px]`,children:[(0,o.jsx)(`thead`,{className:`bg-muted`,children:(0,o.jsx)(`tr`,{children:r.fields?.map((e,t)=>(0,o.jsx)(`th`,{className:`px-4 py-2 font-medium ${e.type===`number`?`text-right`:`text-left`}`,children:e.label||e.name},t))})}),(0,o.jsx)(`tbody`,{children:l.map((e,t)=>(0,o.jsx)(`tr`,{className:`border-t hover:bg-muted/50 even:bg-muted/20`,children:r.fields?.map((t,n)=>(0,o.jsx)(`td`,{className:`px-4 py-2 ${t.type===`number`?`text-right tabular-nums`:``}`,style:v(t.name,e[t.name]),children:y(e[t.name],t)},n))},t))})]})})]})]})]}):(0,o.jsx)(a.Card,{children:(0,o.jsx)(a.CardContent,{className:`p-8 text-center text-muted-foreground`,children:`No report to display`})})};function P(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.dataset==`string`&&t.dataset.length>0||t.type===`joined`&&Array.isArray(t.blocks)&&t.blocks.some(e=>typeof e?.dataset==`string`)}function F(e,t){return e?typeof e==`string`?e:typeof e==`object`&&typeof e.default==`string`?e.default:t:t}function I(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&!!e):[]}function L(e){if(!Array.isArray(e))return;let t={};for(let n of e){let e=n&&typeof n==`object`?n.by:void 0;typeof e!=`string`||!e||(t[e]=n.direction===`desc`?`desc`:`asc`)}return Object.keys(t).length>0?t:void 0}function R(e,t,n){if(!e)return;let r=new Set([...t,...n]),i={};for(let[t,n]of Object.entries(e))r.has(t)&&(i[t]=n);return Object.keys(i).length>0?i:void 0}function z(e,t,r,i,a,o,s){let[c,l]=n.useState({status:`idle`,rows:[]}),u=R(s,t,r),d=JSON.stringify(i??null),f=JSON.stringify(o??null),p=JSON.stringify(u??null),m=`${e}|${t.join(`,`)}|${r.join(`,`)}|${d}|${f}|${p}`;return n.useEffect(()=>{let n=a;if(!n||typeof n.queryDataset!=`function`){l({status:`error`,rows:[],error:`This data source does not support dataset queries.`});return}if(!e||r.length===0){l({status:`idle`,rows:[]});return}let s=!1;return l({status:`loading`,rows:[]}),n.queryDataset(e,{dimensions:t,measures:r,...i&&Object.keys(i).length>0?{runtimeFilter:i}:{},...o?{totals:{groupings:o}}:{},...u?{order:u}:{}}).then(e=>{s||l({status:`ok`,rows:Array.isArray(e?.rows)?e.rows:[],fields:Array.isArray(e?.fields)?e.fields:[],object:e?.object,dimensionFields:e?.dimensionFields,drillRawRows:Array.isArray(e?.drillRawRows)?e.drillRawRows:void 0,drillRanges:Array.isArray(e?.drillRanges)?e.drillRanges:void 0,totals:Array.isArray(e?.totals)?e.totals:void 0})}).catch(e=>{s||l({status:`error`,rows:[],error:String(e?.message??e)})}),()=>{s=!0}},[m]),c}function B({dataset:e}){return(0,o.jsxs)(`div`,{className:`flex items-center justify-center rounded-md border border-dashed bg-muted/20 p-4 text-xs text-muted-foreground`,children:[`This report binds the “`,e,`” dataset — choose at least one measure (values) to render.`]})}function V({status:e,error:t}){return e===`error`?(0,o.jsxs)(`div`,{role:`alert`,className:`flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive`,children:[(0,o.jsx)(s.AlertTriangle,{className:`h-3.5 w-3.5 mt-0.5 shrink-0`}),(0,o.jsx)(`span`,{className:`break-words`,children:t})]}):(0,o.jsxs)(`div`,{className:`flex items-center gap-2 p-4 text-xs text-muted-foreground`,children:[(0,o.jsx)(s.Loader2,{className:`h-4 w-4 animate-spin`}),` Running report…`]})}function H(){return(0,o.jsxs)(`div`,{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`,children:[(0,o.jsx)(s.Table2,{className:`h-6 w-6`}),` The dataset returned no rows for this report’s scope.`]})}var U=`cursor-pointer hover:bg-accent/40`;function W({dataset:e,rows:n,values:r,runtimeFilter:i,dataSource:a,onDrill:s,order:c,withTotals:u}){let d=z(e,n,r,i,a,u&&n.length>0?[[]]:void 0,c),{fieldLabel:f}=(0,l.useSafeFieldLabel)(),p=(0,l.useSafeTranslate)();if(r.length===0)return(0,o.jsx)(B,{dataset:e});if(d.status===`loading`||d.status===`idle`)return(0,o.jsx)(V,{status:d.status});if(d.status===`error`)return(0,o.jsx)(V,{status:`error`,error:d.error});if(d.rows.length===0)return(0,o.jsx)(H,{});let m=!!s&&n.length>0,h=d.dimensionFields?n.filter(e=>e in d.dimensionFields):[],g=(r,a)=>{let o={};for(let e of n)o[e]=r[e];let c=d.drillRanges?.[a],l=!!c&&Object.keys(c).length>0,u=d.object&&(h.length>0||l)?(0,t.buildDatasetDrillFilter)(d.drillRawRows?.[a],h,d.dimensionFields??{},i,c):void 0;s({dataset:e,groupKey:o,runtimeFilter:i,object:d.object,objectFilter:u})},{measureField:_,headerLabel:v}=(0,t.buildDatasetFieldHelpers)(d.fields,d.object,f),y=[...n,...r],b=u?d.totals?.find(e=>Array.isArray(e.dimensions)&&e.dimensions.length===0)?.rows?.[0]:void 0,x=p(`report.total`,`Total`);return(0,o.jsx)(`div`,{className:`overflow-auto max-h-[70vh] rounded-md border`,children:(0,o.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,o.jsx)(`thead`,{className:`bg-muted/40`,children:(0,o.jsx)(`tr`,{children:y.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-left font-medium whitespace-nowrap`,children:v(e)},e))})}),(0,o.jsxs)(`tbody`,{children:[d.rows.map((e,n)=>(0,o.jsx)(`tr`,{className:`border-t${m?` ${U}`:``}`,"data-testid":m?`dataset-drill-row`:void 0,onClick:m?()=>g(e,n):void 0,children:y.map(n=>(0,o.jsx)(`td`,{className:`px-2 py-1 tabular-nums whitespace-nowrap`,children:r.includes(n)?(0,t.formatMeasure)(e[n],_(n)?.format,_(n)?.currency,_(n)?.percentScale):(0,t.formatDimensionValue)(e[n])},n))},n)),b&&(0,o.jsxs)(`tr`,{className:`border-t bg-muted/30 font-medium`,"data-testid":`dataset-report-total-row`,children:[n.length>0&&(0,o.jsx)(`td`,{colSpan:n.length,className:`px-2 py-1 whitespace-nowrap`,children:x}),r.map(e=>(0,o.jsx)(`td`,{className:`px-2 py-1 tabular-nums whitespace-nowrap`,children:(0,t.formatMeasure)(b[e],_(e)?.format,_(e)?.currency,_(e)?.percentScale)},e))]})]})]})})}function G(e){switch(e){case`summary`:return`summary`;case`matrix`:return`matrix`;case`joined`:return`joined`;default:return`tabular`}}function te(e){switch(e){case`bar`:case`column`:case`horizontal-bar`:case`line`:case`area`:case`pie`:case`donut`:case`funnel`:case`scatter`:case`treemap`:case`sankey`:case`radar`:case`combo`:return{kind:`series`,chartType:e};case`gauge`:case`solid-gauge`:case`metric`:case`kpi`:case`bullet`:return{kind:`single_value`};case`table`:case`pivot`:return{kind:`tabular`};default:return{kind:`unsupported`,type:String(e)}}}function ne(e){let[,r]=n.useReducer(e=>e+1,0);return n.useEffect(()=>{if(t.ComponentRegistry.get(e))return;let n=typeof t.ComponentRegistry.subscribe==`function`?t.ComponentRegistry.subscribe(()=>{t.ComponentRegistry.get(e)&&r()}):void 0,i=t.ComponentRegistry.loadLazy?.(e);return i&&typeof i.then==`function`&&i.then(()=>r()).catch(()=>{}),n},[e]),t.ComponentRegistry.get(e)}function K({dataset:e,chart:n,runtimeFilter:r,dataSource:i,order:a}){let c=typeof n.xAxis==`string`?n.xAxis:``,u=typeof n.yAxis==`string`?n.yAxis:``,d=te(n.type),f=d.kind===`series`||d.kind===`single_value`,p=z(e,d.kind===`series`&&c?[c]:[],f&&u?[u]:[],r,i,void 0,a),m=ne(`chart`),{fieldLabel:h}=(0,l.useSafeFieldLabel)(),g=typeof n.title==`string`?n.title:void 0;if(d.kind===`tabular`)return null;if(d.kind===`unsupported`)return(0,o.jsxs)(`div`,{className:`rounded-md border border-dashed bg-muted/20 px-3 py-2 text-xs text-muted-foreground`,"data-testid":`dataset-report-chart-unsupported`,children:[`Chart type “`,d.type,`” is not a spec chart type — the grouped table below carries this report’s numbers.`]});if(d.kind===`series`&&!c||!u)return null;if(p.status===`loading`||p.status===`idle`)return(0,o.jsxs)(`div`,{className:`flex items-center gap-2 p-4 text-xs text-muted-foreground`,children:[(0,o.jsx)(s.Loader2,{className:`h-4 w-4 animate-spin`}),` Loading chart…`]});if(p.status===`error`||p.rows.length===0)return null;if(d.kind===`single_value`){let{measureField:e,headerLabel:n}=(0,t.buildDatasetFieldHelpers)(p.fields,p.object,h),r=e(u);return(0,o.jsxs)(`div`,{className:`rounded-md border bg-card p-3`,"data-testid":`dataset-report-metric`,children:[g?(0,o.jsx)(`h3`,{className:`mb-2 text-sm font-semibold`,children:g}):null,(0,o.jsxs)(`div`,{className:`flex flex-col gap-0.5 py-2`,children:[(0,o.jsx)(`span`,{className:`text-2xl font-semibold tabular-nums`,children:(0,t.formatMeasure)(p.rows[0]?.[u],r?.format,r?.currency,r?.percentScale)}),(0,o.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:n(u)})]})]})}return m?(0,o.jsxs)(`div`,{className:`rounded-md border bg-card p-3`,"data-testid":`dataset-report-chart`,children:[g?(0,o.jsx)(`h3`,{className:`mb-2 text-sm font-semibold`,children:g}):null,(0,o.jsx)(m,{schema:{chartType:d.chartType,data:p.rows,xAxisKey:c,series:[{dataKey:u}],height:typeof n.height==`number`?n.height:280,isAnimationActive:!1}})]}):null}function q(e,t){return e.map(e=>String(t[e]??`∅`)).join(``)}function J(e,n){return e.map(e=>(0,t.formatDimensionValue)(n[e])).join(` / `)}function Y({dataset:e,rows:r,columnsAcross:i,values:a,runtimeFilter:s,dataSource:c,onDrill:u,order:d}){let f=z(e,[...r,...i],a,s,c,[r,i,[]],d),p=(0,l.useSafeTranslate)(),{fieldLabel:m}=(0,l.useSafeFieldLabel)(),h=n.useMemo(()=>{if(f.status!==`ok`)return null;let e=[],t=[],n=new Set,a=new Set,o=new Map;return f.rows.forEach((s,c)=>{let l=q(r,s),u=q(i,s);if(!n.has(l)){n.add(l);let t={};for(let e of r)t[e]=s[e];e.push({id:l,label:J(r,s),key:t})}if(!a.has(u)){a.add(u);let e={};for(let t of i)e[t]=s[t];t.push({id:u,label:J(i,s),key:e})}o.set(`${l} ${u}`,{row:s,index:c})}),{rowHeaders:e,colHeaders:t,cells:o}},[f,r,i]);if(a.length===0)return(0,o.jsx)(B,{dataset:e});if(f.status===`loading`||f.status===`idle`)return(0,o.jsx)(V,{status:f.status});if(f.status===`error`)return(0,o.jsx)(V,{status:`error`,error:f.error});if(!h||h.rowHeaders.length===0)return(0,o.jsx)(H,{});let{measureField:g,headerLabel:_}=(0,t.buildDatasetFieldHelpers)(f.fields,f.object,m),v=p(`report.total`,`Total`),y=!!u,b=f.dimensionFields?[...r,...i].filter(e=>e in f.dimensionFields):[],x=(n,r,i)=>{let a=f.drillRanges?.[i],o=!!a&&Object.keys(a).length>0,c=f.object&&(b.length>0||o)?(0,t.buildDatasetDrillFilter)(f.drillRawRows?.[i],b,f.dimensionFields??{},s,a):void 0;u({dataset:e,groupKey:{...n,...r},runtimeFilter:s,object:f.object,objectFilter:c})},S=h.colHeaders.flatMap(e=>a.map(t=>({col:e,measure:t,header:a.length===1?e.label:`${e.label} · ${_(t)}`}))),C=e=>f.totals?.find(t=>Array.isArray(t.dimensions)&&t.dimensions.join(`,`)===e.join(`,`))?.rows,w=new Map;for(let e of C(r)??[])w.set(q(r,e),e);let T=new Map;for(let e of C(i)??[])T.set(q(i,e),e);let E=C([])?.[0],D=w.size>0,O=T.size>0;return(0,o.jsx)(`div`,{className:`overflow-auto max-h-[70vh] rounded-md border`,"data-testid":`dataset-matrix`,children:(0,o.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,o.jsx)(`thead`,{className:`bg-muted/40`,children:(0,o.jsxs)(`tr`,{children:[r.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-left font-medium whitespace-nowrap`,children:_(e)},e)),S.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-right font-medium whitespace-nowrap`,children:e.header},`${e.col.id}-${e.measure}`)),D&&a.map(e=>(0,o.jsx)(`th`,{className:`px-2 py-1.5 text-right font-medium whitespace-nowrap`,"data-testid":`matrix-total-col-header`,children:a.length===1?v:`${v} · ${_(e)}`},`total-${e}`))]})}),(0,o.jsxs)(`tbody`,{children:[h.rowHeaders.map(e=>(0,o.jsxs)(`tr`,{className:`border-t`,children:[r.map(n=>(0,o.jsx)(`td`,{className:`px-2 py-1 whitespace-nowrap font-medium`,children:(0,t.formatDimensionValue)(e.key[n])},n)),S.map(n=>{let r=h.cells.get(`${e.id} ${n.col.id}`),i=r?.row[n.measure],a=y&&r!=null;return(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap${a?` ${U}`:``}`,"data-testid":a?`dataset-drill-cell`:void 0,onClick:a?()=>x(e.key,n.col.key,r.index):void 0,children:(0,t.formatMeasure)(i,g(n.measure)?.format,g(n.measure)?.currency,g(n.measure)?.percentScale)},`${n.col.id}-${n.measure}`)}),D&&a.map(n=>(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap font-medium`,"data-testid":`matrix-row-total`,children:(0,t.formatMeasure)(w.get(e.id)?.[n],g(n)?.format,g(n)?.currency,g(n)?.percentScale)},`total-${n}`))]},e.id)),O&&(0,o.jsxs)(`tr`,{className:`border-t bg-muted/30 font-medium`,"data-testid":`matrix-total-row`,children:[r.length>0&&(0,o.jsx)(`td`,{colSpan:r.length,className:`px-2 py-1 whitespace-nowrap`,children:v}),S.map(e=>(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap`,children:(0,t.formatMeasure)(T.get(e.col.id)?.[e.measure],g(e.measure)?.format,g(e.measure)?.currency,g(e.measure)?.percentScale)},`${e.col.id}-${e.measure}`)),D&&a.map(e=>(0,o.jsx)(`td`,{className:`px-2 py-1 text-right tabular-nums whitespace-nowrap`,"data-testid":`matrix-grand-total`,children:(0,t.formatMeasure)(E?.[e],g(e)?.format,g(e)?.currency,g(e)?.percentScale)},`grand-${e}`))]})]})]})})}var X=({report:e,dataSource:n,runtimeFilter:r,onDrill:i,className:a})=>{let s=(0,t.mergeFilters)(e.runtimeFilter??e.filter,r),c=e.drilldown===!1?void 0:i,l=G(e.type);if(l===`joined`&&Array.isArray(e.blocks))return(0,o.jsx)(`div`,{className:a,"data-testid":`dataset-joined-report`,"data-report-name":e.name,style:{display:`flex`,flexDirection:`column`,gap:24},children:e.blocks.map((e,r)=>{let i=(0,t.mergeFilters)(s,e.runtimeFilter??e.filter),a=I(e.columns),l=L(e.order),u=G(e.type),d=u===`matrix`&&a.length>0?(0,o.jsx)(Y,{dataset:String(e.dataset??``),rows:I(e.rows),columnsAcross:a,values:I(e.values),runtimeFilter:i,dataSource:n,onDrill:c,order:l}):(0,o.jsx)(W,{dataset:String(e.dataset??``),rows:I(e.rows),values:I(e.values),runtimeFilter:i,dataSource:n,onDrill:c,order:l,withTotals:u===`summary`||u===`matrix`});return(0,o.jsxs)(`section`,{"data-testid":`dataset-report-block`,"data-block-id":e.name??`block-${r}`,className:`flex flex-col gap-2 rounded-lg border bg-card p-4`,children:[(0,o.jsxs)(`header`,{className:`flex flex-col gap-0.5`,children:[(0,o.jsx)(`h3`,{className:`text-sm font-semibold`,children:F(e.label,e.name??`Block ${r+1}`)}),e.description?(0,o.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:F(e.description,``)}):null]}),d]},e.name??`block-${r}`)})});let u=I(e.columns),d=L(e.order);if(l===`matrix`&&u.length>0)return(0,o.jsx)(`div`,{className:a,"data-testid":`dataset-report`,"data-report-name":e.name,children:(0,o.jsx)(Y,{dataset:String(e.dataset??``),rows:I(e.rows),columnsAcross:u,values:I(e.values),runtimeFilter:s,dataSource:n,onDrill:c,order:d})});let f=e.chart&&typeof e.chart==`object`&&e.chart.type?e.chart:null;return(0,o.jsxs)(`div`,{className:`${a??``} flex flex-col gap-3`,"data-testid":`dataset-report`,"data-report-name":e.name,"data-report-presentation":l,children:[f?(0,o.jsx)(K,{dataset:String(e.dataset??``),chart:f,runtimeFilter:s,dataSource:n,order:d}):null,(0,o.jsx)(W,{dataset:String(e.dataset??``),rows:I(e.rows),values:I(e.values),runtimeFilter:s,dataSource:n,onDrill:c,order:d,withTotals:l===`summary`||l===`matrix`})]})},Z=e=>{let{dataSource:t,rows:a,runtimeFilter:s,onDrill:c,className:l}=e,u=n.useContext(i.SchemaRendererContext),d=t??u?.dataSource,f=e.schema;return f&&typeof f==`object`&&f.type===`spec-report`&&f.report&&typeof f.report==`object`&&(f=f.report),P(f)?(0,o.jsx)(X,{report:f,dataSource:d,runtimeFilter:s,onDrill:c,className:l}):(0,r.isSpecReport)(f)?(0,o.jsx)(`div`,{className:l,"data-testid":`report-presentation-bridge`,children:(0,o.jsx)(N,{schema:{type:`report-viewer`,report:(0,r.specReportToPresentation)(f),data:a??[],showToolbar:!1}})}):(0,o.jsx)(_,{schema:f})};async function Q(e,t){let{dataSource:n,resource:r,queryParams:i,format:a,exportConfig:o}=t,s=a||e.defaultExportFormat||`pdf`;try{let t=(await n.find(r,i)).data||[];return C(s,e,t,{format:s,...e.exportConfigs?.[s],...o}),{success:!0,recordCount:t.length,format:s}}catch(e){return{success:!1,recordCount:0,format:s,error:e.message}}}function re(e,t,n={}){let{columns:r,filename:i,includeAggregationRow:a=!1}=n,o=r||(e.fields||[]).map(ae),s=o.map(e=>e.header),c=t.map((e,t)=>o.map(n=>{if(n.formula)return n.formula.replace(/\{ROW\}/g,String(t+2));let r=e[n.name];return oe(r,n.numberFormat)}));if(a&&t.length>0){let n=o.map((n,r)=>{let i=(e.fields||[]).find(e=>e.name===n.name);if(i?.aggregation){let e=se(r),n=t.length+1;switch(i.aggregation){case`sum`:return`=SUM(${e}2:${e}${n})`;case`avg`:return`=AVERAGE(${e}2:${e}${n})`;case`count`:return`=COUNTA(${e}2:${e}${n})`;case`min`:return`=MIN(${e}2:${e}${n})`;case`max`:return`=MAX(${e}2:${e}${n})`;default:return``}}return``});c.push(n)}le(``+[s.join(` `),...c.map(e=>e.join(` `))].join(`
59
59
  `),i||`${e.title||`report`}.tsv`,`text/tab-separated-values`)}function ie(e,t,n,r){return async()=>{let i=e.schedule;if(!i?.enabled)return[];let a=i.formats||[e.defaultExportFormat||`pdf`],o=[];for(let r of a){let i=await Q(e,{dataSource:t,resource:n,format:r});o.push(i)}return r(e,i),o}}function ae(e){return{name:e.name,header:e.label||e.name}}function oe(e,t){return e==null?``:typeof e==`number`&&t?e.toLocaleString(`en-US`,$(t)):ce(String(e))}function $(e){if(e.includes(`%`))return{style:`percent`,minimumFractionDigits:0};let t=(e.match(/0/g)||[]).length;return{minimumFractionDigits:Math.max(0,t-1),maximumFractionDigits:Math.max(0,t-1)}}function se(e){let t=``,n=e;for(;n>=0;)t=String.fromCharCode(n%26+65)+t,n=Math.floor(n/26)-1;return t}function ce(e){if(e.length>0){let t=e.charAt(0);if(t===`=`||t===`+`||t===`-`||t===`@`||t===`|`)return`'${e}`}return e}function le(e,t,n){let r=new Blob([e],{type:`${n};charset=utf-8`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=t,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(i)}t.ComponentRegistry.register(`report`,Z,{namespace:`report`,label:`Report`,category:`Report`,inputs:[{name:`title`,type:`string`,label:`Title`},{name:`description`,type:`string`,label:`Description`},{name:`chart`,type:`code`,label:`Chart Configuration`}]}),t.ComponentRegistry.register(`spec-report`,Z,{namespace:`report`,label:`Spec Report`,category:`Report`,inputs:[{name:`dataset`,type:`string`,label:`Dataset`},{name:`type`,type:`string`,label:`Report Type`}]}),t.ComponentRegistry.register(`report-viewer`,N,{namespace:`report`,label:`Report Viewer`,category:`Report`,inputs:[{name:`report`,type:`code`,label:`Report Definition`},{name:`showToolbar`,type:`boolean`,label:`Show Toolbar`}]}),e.DatasetReportRenderer=X,e.LegacyReportRenderer=_,e.ReportRenderer=Z,e.ReportViewer=N,e.createScheduleTrigger=ie,e.exportAsCSV=v,e.exportAsExcel=S,e.exportAsHTML=b,e.exportAsJSON=y,e.exportAsPDF=x,e.exportExcelWithFormulas=re,e.exportReport=C,e.exportWithLiveData=Q,e.formatValue=k,e.isDatasetReport=P,Object.defineProperty(e,"mergeFilters",{enumerable:!0,get:function(){return t.mergeFilters}})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-report",
3
- "version": "17.1.0",
3
+ "version": "17.2.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.umd.cjs",
6
6
  "module": "dist/index.js",
@@ -23,20 +23,20 @@
23
23
  "lucide-react": "^1.25.0",
24
24
  "react-i18next": "^17.0.11",
25
25
  "tailwind-merge": "^3.6.0",
26
- "@object-ui/components": "17.1.0",
27
- "@object-ui/core": "17.1.0",
28
- "@object-ui/fields": "17.1.0",
29
- "@object-ui/i18n": "17.1.0",
30
- "@object-ui/plugin-grid": "17.1.0",
31
- "@object-ui/react": "17.1.0",
32
- "@object-ui/types": "17.1.0"
26
+ "@object-ui/components": "17.2.0",
27
+ "@object-ui/core": "17.2.0",
28
+ "@object-ui/fields": "17.2.0",
29
+ "@object-ui/i18n": "17.2.0",
30
+ "@object-ui/plugin-grid": "17.2.0",
31
+ "@object-ui/react": "17.2.0",
32
+ "@object-ui/types": "17.2.0"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "react": "^18.0.0",
36
36
  "react-dom": "^18.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@objectstack/spec": "^17.0.0-rc.0",
39
+ "@objectstack/spec": "^17.0.0-rc.1",
40
40
  "@types/node": "^26.1.1",
41
41
  "@types/react": "19.2.17",
42
42
  "@types/react-dom": "19.2.3",