@agile-team/mach-report 2.8.3 → 2.9.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.
Files changed (95) hide show
  1. package/README.md +28 -10
  2. package/dist/ExcelBindingWizard-DiaxvWpQ.cjs +1 -0
  3. package/dist/ExcelBindingWizard-RLJIXKKG.js +816 -0
  4. package/dist/{ReportPreview-DRBAUkxj.js → ReportPreview-B5ZNEasW.js} +23 -22
  5. package/dist/ReportPreview-DRtVPUYo.cjs +6 -0
  6. package/dist/RuleEditor-N4qnMZ-Z.cjs +1 -0
  7. package/dist/RuleEditor-ynnUEK0s.js +1575 -0
  8. package/dist/TemplateReviewPanel-C_Lmzis6.cjs +1 -0
  9. package/dist/TemplateReviewPanel-Cn32OY4_.js +173 -0
  10. package/dist/{_plugin-vue_export-helper-DPbiz14D.js → _plugin-vue_export-helper-8SL1F89S.js} +2 -2
  11. package/dist/analytics.cjs +1 -1
  12. package/dist/analytics.d.cts +188 -5
  13. package/dist/analytics.d.ts +188 -5
  14. package/dist/analytics.js +68 -202
  15. package/dist/{assets-B9qJku3V.js → assets-DDsfEi8R.js} +3 -3
  16. package/dist/{assets-RZan7EyL.cjs → assets-ahTRUXRk.cjs} +1 -1
  17. package/dist/binding-preview-B5834rml.cjs +2 -0
  18. package/dist/binding-preview-ChXjN5L5.js +649 -0
  19. package/dist/{capabilities-joSutDF8.js → capabilities-Cm9hZ3uV.js} +5 -5
  20. package/dist/{capabilities-xGTpnPjJ.cjs → capabilities-DYzWL7KS.cjs} +1 -1
  21. package/dist/dataset-BkRmwgeJ.cjs +1 -0
  22. package/dist/dataset-H5pFuQGU.js +121 -0
  23. package/dist/defaults-DXhiM1ZD.js +10 -0
  24. package/dist/defaults-xhmcLLrf.cjs +1 -0
  25. package/dist/designer.cjs +2 -1
  26. package/dist/designer.d.cts +1391 -6
  27. package/dist/designer.d.ts +1391 -6
  28. package/dist/designer.js +2636 -673
  29. package/dist/grid-geometry-BNptEcMm.js +65 -0
  30. package/dist/grid-geometry-CZ_cYB6O.cjs +1 -0
  31. package/dist/import-template-CNMLJSQw.js +23030 -0
  32. package/dist/import-template-CpxunKVp.cjs +29 -0
  33. package/dist/index.cjs +7 -7
  34. package/dist/index.d.cts +202 -3
  35. package/dist/index.d.ts +202 -3
  36. package/dist/index.js +554 -535
  37. package/dist/matrix-CNPDJxED.js +745 -0
  38. package/dist/matrix-Div9Ilh3.cjs +1 -0
  39. package/dist/pdf.cjs +46 -46
  40. package/dist/pdf.d.cts +2 -0
  41. package/dist/pdf.d.ts +2 -0
  42. package/dist/pdf.js +17 -16
  43. package/dist/{plugin-BurDDMcd.js → plugin-BWwIgZXV.js} +1 -1
  44. package/dist/{plugin-DSFu51Ua.cjs → plugin-Dg-J1Rbm.cjs} +1 -1
  45. package/dist/progress-7OSZbFok.js +39 -0
  46. package/dist/progress-BnLiS5eH.cjs +1 -0
  47. package/dist/render-plan-7xpGrCEl.cjs +1 -0
  48. package/dist/render-plan-Ck6koX9L.js +13 -0
  49. package/dist/server/node.d.cts +62 -0
  50. package/dist/server/node.d.ts +62 -0
  51. package/dist/server-node.cjs +1 -1
  52. package/dist/server-node.js +373 -145
  53. package/dist/server.cjs +1 -1
  54. package/dist/server.d.cts +311 -0
  55. package/dist/server.d.ts +311 -0
  56. package/dist/server.js +590 -186
  57. package/dist/{style-Dv5o_x6b.js → style-CQ1PK8ZB.js} +5 -5
  58. package/dist/style-UgIJSA1F.cjs +1 -0
  59. package/dist/style.css +1 -1
  60. package/dist/template-registry-CHMYZ7SD.cjs +1 -0
  61. package/dist/template-registry-R61AMCr0.js +433 -0
  62. package/dist/template-review-hvWWQFsi.js +1027 -0
  63. package/dist/template-review-jEcOfmGr.cjs +1 -0
  64. package/dist/textwrap-CWHyzkBH.cjs +4 -0
  65. package/dist/{textwrap-DOl04hCQ.js → textwrap-DE1kgcJB.js} +1 -1
  66. package/dist/{validate-DfHPD8wX.cjs → validate-BDiMqkJC.cjs} +1 -1
  67. package/dist/{validate-S6CgIm5d.js → validate-DWPF7icl.js} +13 -13
  68. package/dist/vue/async.d.cts +186 -0
  69. package/dist/vue/async.d.ts +186 -0
  70. package/dist/vue/index.d.cts +271 -3
  71. package/dist/vue/index.d.ts +271 -3
  72. package/dist/vue-async.cjs +1 -1
  73. package/dist/vue-async.js +3 -3
  74. package/dist/vue.cjs +1 -1
  75. package/dist/vue.js +4 -4
  76. package/dist/worker.cjs +1 -1
  77. package/dist/worker.d.cts +2 -0
  78. package/dist/worker.d.ts +2 -0
  79. package/dist/worker.js +1 -1
  80. package/dist/xlsx.cjs +2 -30
  81. package/dist/xlsx.d.cts +268 -0
  82. package/dist/xlsx.d.ts +268 -0
  83. package/dist/xlsx.js +220 -23440
  84. package/package.json +1 -1
  85. package/dist/ReportPreview-DjGeWHY-.cjs +0 -6
  86. package/dist/progress-DD964VAB.js +0 -102
  87. package/dist/progress-KvhwXZ1Q.cjs +0 -1
  88. package/dist/render-plan-CckPEQyf.cjs +0 -1
  89. package/dist/render-plan-uzZYYSy1.js +0 -19
  90. package/dist/report-source-BXHNy_AD.js +0 -755
  91. package/dist/report-source-CCAvFE3t.cjs +0 -1
  92. package/dist/style-CpwiOPyB.cjs +0 -1
  93. package/dist/template-registry-DWExx0gU.cjs +0 -1
  94. package/dist/template-registry-NpOakidD.js +0 -354
  95. package/dist/textwrap-CnGsEum6.cjs +0 -4
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),S=require("@agile-team/mach-report"),V=require("./designer.cjs"),N=require("./_plugin-vue_export-helper-BLmdZLlg.cjs"),h=["aria-label","aria-busy"],B=["disabled"],D={class:"mr-review-controls"},b=["aria-label","disabled"],f={value:"0"},w={value:"20"},C={value:"100"},T={value:"-1"},x={key:0,class:"mr-review-note"},F={class:"mr-review-summary",role:"status"},R={key:0,class:"mr-review-note"},I={key:1,class:"mr-review-note"},M={key:2,class:"mr-review-list"},q={key:0},L=["onClick"],P={key:3,class:"mr-review-note"},$={key:4,class:"mr-review-ack"},j={key:0,class:"mr-review-note"},z={key:1,class:"mr-review-list"},O=["onClick"],U={key:0},A={class:"mr-review-note"},G=e.defineComponent({__name:"TemplateReviewPanel",props:{document:{},previous:{},datasets:{},dataSchemas:{},formats:{},messages:{}},emits:["locate"],setup(p,{emit:g}){const r=p,v=g,t=e.computed(()=>({...V.TEMPLATE_REVIEW_MESSAGES,...r.messages})),o=e.shallowRef(),m=e.ref("20"),c=e.ref(!1),s=e.ref(!1),d=e.computed(()=>o.value?.issues.filter(a=>a.severity==="error").length??0);let u;function k(){clearTimeout(u),s.value=!1,o.value=void 0,c.value=!1}e.watch(()=>r.document,k),e.onBeforeUnmount(()=>clearTimeout(u));function y(){clearTimeout(u),s.value=!0,u=setTimeout(()=>{const a=Number(m.value),n=Object.fromEntries(Object.entries(r.datasets??{}).map(([l,i])=>[l,a<0?i:i.slice(0,a)]));o.value=S.reviewReportTemplate(r.document,{previous:r.previous,dataSchemas:r.dataSchemas,formats:r.formats,allowBreakingChanges:c.value,fixtures:a===0?[]:[{name:a<0?t.value.all:`${a} ${t.value.rows} / dataset`,datasets:n}]}),s.value=!1},0)}function E(a){const n=/\.pages\[(\d+)\]\.components\[(\d+)\]/.exec(a);v("locate",{path:a,...n?{pageIndex:Number(n[1]),componentIndex:Number(n[2])}:{}})}return(a,n)=>(e.openBlock(),e.createElementBlock("section",{class:"mr-template-review","aria-label":t.value.title,"aria-busy":s.value},[e.createElementVNode("header",null,[e.createElementVNode("strong",null,e.toDisplayString(t.value.title),1),e.createElementVNode("button",{type:"button",disabled:s.value,onClick:y},e.toDisplayString(s.value?t.value.running:t.value.run),9,B)]),e.createElementVNode("div",D,[e.createElementVNode("label",null,[e.createTextVNode(e.toDisplayString(t.value.samples),1),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":n[0]||(n[0]=l=>m.value=l),"aria-label":t.value.samples,disabled:s.value},[e.createElementVNode("option",f,e.toDisplayString(t.value.none),1),e.createElementVNode("option",w,e.toDisplayString(t.value.first20),1),e.createElementVNode("option",C,e.toDisplayString(t.value.first100),1),e.createElementVNode("option",T,e.toDisplayString(t.value.all),1)],8,b),[[e.vModelSelect,m.value]])])]),o.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("div",F,[e.createElementVNode("span",{class:e.normalizeClass({"is-error":d.value})},e.toDisplayString(d.value)+" "+e.toDisplayString(t.value.errors),3),e.createElementVNode("span",null,e.toDisplayString(o.value.issues.length-d.value)+" "+e.toDisplayString(t.value.warnings),1)]),e.createElementVNode("section",null,[e.createElementVNode("h3",null,[e.createTextVNode(e.toDisplayString(t.value.changes)+" ",1),e.createElementVNode("small",null,e.toDisplayString(o.value.changes?.totalChanges??0),1)]),p.previous?o.value.changes?.totalChanges?(e.openBlock(),e.createElementBlock("ol",M,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.value.changes?.changes,(l,i)=>(e.openBlock(),e.createElementBlock("li",{key:i},[e.createElementVNode("div",null,[e.createElementVNode("span",null,e.toDisplayString(t.value.categories[l.category])+" · "+e.toDisplayString(t.value.kinds[l.kind]),1),l.breaking?(e.openBlock(),e.createElementBlock("b",q,e.toDisplayString(t.value.breaking),1)):e.createCommentVNode("",!0),e.createElementVNode("button",{type:"button",onClick:_=>E(l.path)},e.toDisplayString(t.value.locate),9,L)]),e.createElementVNode("code",null,e.toDisplayString(l.path),1),e.createElementVNode("dl",null,[l.before!==void 0?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("dt",null,e.toDisplayString(t.value.before),1),e.createElementVNode("dd",null,e.toDisplayString(l.before),1)],64)):e.createCommentVNode("",!0),l.after!==void 0?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("dt",null,e.toDisplayString(t.value.after),1),e.createElementVNode("dd",null,e.toDisplayString(l.after),1)],64)):e.createCommentVNode("",!0)])]))),128))])):(e.openBlock(),e.createElementBlock("p",I,e.toDisplayString(t.value.noChanges),1)):(e.openBlock(),e.createElementBlock("p",R,e.toDisplayString(t.value.baseline),1)),o.value.changes?.truncated?(e.openBlock(),e.createElementBlock("p",P,e.toDisplayString(t.value.truncated),1)):e.createCommentVNode("",!0),o.value.changes?.breakingChanges?(e.openBlock(),e.createElementBlock("label",$,[e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":n[1]||(n[1]=l=>c.value=l),type:"checkbox"},null,512),[[e.vModelCheckbox,c.value]]),e.createTextVNode(e.toDisplayString(t.value.acknowledge),1)])):e.createCommentVNode("",!0)]),e.createElementVNode("section",null,[e.createElementVNode("h3",null,e.toDisplayString(t.value.issues),1),o.value.issues.length?(e.openBlock(),e.createElementBlock("ol",z,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.value.issues,(l,i)=>(e.openBlock(),e.createElementBlock("li",{key:i},[e.createElementVNode("div",null,[e.createElementVNode("span",{class:e.normalizeClass({"is-error":l.severity==="error"})},e.toDisplayString(l.severity==="error"?t.value.errors:t.value.warnings),3),e.createElementVNode("button",{type:"button",onClick:_=>v("locate",l)},e.toDisplayString(t.value.locate),9,O)]),e.createElementVNode("p",null,e.toDisplayString(l.message),1),e.createElementVNode("code",null,e.toDisplayString(l.path),1)]))),128))])):(e.openBlock(),e.createElementBlock("p",j,e.toDisplayString(t.value.noIssues),1))]),o.value.samples.length?(e.openBlock(),e.createElementBlock("section",U,[e.createElementVNode("h3",null,e.toDisplayString(t.value.results),1),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.value.samples,l=>(e.openBlock(),e.createElementBlock("p",{key:l.name},e.toDisplayString(l.name)+" · "+e.toDisplayString(l.rows)+" "+e.toDisplayString(t.value.rows)+" · "+e.toDisplayString(l.pages)+" "+e.toDisplayString(t.value.pages),1))),128))])):e.createCommentVNode("",!0),e.createElementVNode("p",A,e.toDisplayString(t.value.checked),1)],64)):(e.openBlock(),e.createElementBlock("p",x,e.toDisplayString(t.value.empty),1))],8,h))}}),H=N._export_sfc(G,[["__scopeId","data-v-57cb15cb"]]);exports.default=H;
@@ -0,0 +1,173 @@
1
+ import { defineComponent as R, computed as C, shallowRef as B, ref as k, watch as M, onBeforeUnmount as $, openBlock as s, createElementBlock as o, createElementVNode as t, toDisplayString as e, createTextVNode as f, withDirectives as x, vModelSelect as P, Fragment as d, normalizeClass as T, renderList as g, createCommentVNode as m, vModelCheckbox as U } from "vue";
2
+ import { reviewReportTemplate as j } from "@agile-team/mach-report";
3
+ import { TEMPLATE_REVIEW_MESSAGES as z } from "./designer.js";
4
+ import { _ as A } from "./_plugin-vue_export-helper-8SL1F89S.js";
5
+ const D = ["aria-label", "aria-busy"], L = ["disabled"], O = { class: "mr-review-controls" }, F = ["aria-label", "disabled"], G = { value: "0" }, W = { value: "20" }, q = { value: "100" }, H = { value: "-1" }, J = {
6
+ key: 0,
7
+ class: "mr-review-note"
8
+ }, K = {
9
+ class: "mr-review-summary",
10
+ role: "status"
11
+ }, Q = {
12
+ key: 0,
13
+ class: "mr-review-note"
14
+ }, X = {
15
+ key: 1,
16
+ class: "mr-review-note"
17
+ }, Y = {
18
+ key: 2,
19
+ class: "mr-review-list"
20
+ }, Z = { key: 0 }, ee = ["onClick"], le = {
21
+ key: 3,
22
+ class: "mr-review-note"
23
+ }, te = {
24
+ key: 4,
25
+ class: "mr-review-ack"
26
+ }, ae = {
27
+ key: 0,
28
+ class: "mr-review-note"
29
+ }, se = {
30
+ key: 1,
31
+ class: "mr-review-list"
32
+ }, oe = ["onClick"], ne = { key: 0 }, re = { class: "mr-review-note" }, ue = /* @__PURE__ */ R({
33
+ __name: "TemplateReviewPanel",
34
+ props: {
35
+ document: {},
36
+ previous: {},
37
+ datasets: {},
38
+ dataSchemas: {},
39
+ formats: {},
40
+ messages: {}
41
+ },
42
+ emits: ["locate"],
43
+ setup(y, { emit: E }) {
44
+ const i = y, w = E, l = C(() => ({ ...z, ...i.messages })), n = B(), h = k("20"), p = k(!1), c = k(!1), b = C(() => n.value?.issues.filter((r) => r.severity === "error").length ?? 0);
45
+ let _;
46
+ function S() {
47
+ clearTimeout(_), c.value = !1, n.value = void 0, p.value = !1;
48
+ }
49
+ M(() => i.document, S), $(() => clearTimeout(_));
50
+ function N() {
51
+ clearTimeout(_), c.value = !0, _ = setTimeout(() => {
52
+ const r = Number(h.value), u = Object.fromEntries(Object.entries(i.datasets ?? {}).map(([a, v]) => [a, r < 0 ? v : v.slice(0, r)]));
53
+ n.value = j(i.document, {
54
+ previous: i.previous,
55
+ dataSchemas: i.dataSchemas,
56
+ formats: i.formats,
57
+ allowBreakingChanges: p.value,
58
+ fixtures: r === 0 ? [] : [{ name: r < 0 ? l.value.all : `${r} ${l.value.rows} / dataset`, datasets: u }]
59
+ }), c.value = !1;
60
+ }, 0);
61
+ }
62
+ function V(r) {
63
+ const u = /\.pages\[(\d+)\]\.components\[(\d+)\]/.exec(r);
64
+ w("locate", { path: r, ...u ? { pageIndex: Number(u[1]), componentIndex: Number(u[2]) } : {} });
65
+ }
66
+ return (r, u) => (s(), o("section", {
67
+ class: "mr-template-review",
68
+ "aria-label": l.value.title,
69
+ "aria-busy": c.value
70
+ }, [
71
+ t("header", null, [
72
+ t("strong", null, e(l.value.title), 1),
73
+ t("button", {
74
+ type: "button",
75
+ disabled: c.value,
76
+ onClick: N
77
+ }, e(c.value ? l.value.running : l.value.run), 9, L)
78
+ ]),
79
+ t("div", O, [
80
+ t("label", null, [
81
+ f(e(l.value.samples), 1),
82
+ x(t("select", {
83
+ "onUpdate:modelValue": u[0] || (u[0] = (a) => h.value = a),
84
+ "aria-label": l.value.samples,
85
+ disabled: c.value
86
+ }, [
87
+ t("option", G, e(l.value.none), 1),
88
+ t("option", W, e(l.value.first20), 1),
89
+ t("option", q, e(l.value.first100), 1),
90
+ t("option", H, e(l.value.all), 1)
91
+ ], 8, F), [
92
+ [P, h.value]
93
+ ])
94
+ ])
95
+ ]),
96
+ n.value ? (s(), o(d, { key: 1 }, [
97
+ t("div", K, [
98
+ t("span", {
99
+ class: T({ "is-error": b.value })
100
+ }, e(b.value) + " " + e(l.value.errors), 3),
101
+ t("span", null, e(n.value.issues.length - b.value) + " " + e(l.value.warnings), 1)
102
+ ]),
103
+ t("section", null, [
104
+ t("h3", null, [
105
+ f(e(l.value.changes) + " ", 1),
106
+ t("small", null, e(n.value.changes?.totalChanges ?? 0), 1)
107
+ ]),
108
+ y.previous ? n.value.changes?.totalChanges ? (s(), o("ol", Y, [
109
+ (s(!0), o(d, null, g(n.value.changes?.changes, (a, v) => (s(), o("li", { key: v }, [
110
+ t("div", null, [
111
+ t("span", null, e(l.value.categories[a.category]) + " · " + e(l.value.kinds[a.kind]), 1),
112
+ a.breaking ? (s(), o("b", Z, e(l.value.breaking), 1)) : m("", !0),
113
+ t("button", {
114
+ type: "button",
115
+ onClick: (I) => V(a.path)
116
+ }, e(l.value.locate), 9, ee)
117
+ ]),
118
+ t("code", null, e(a.path), 1),
119
+ t("dl", null, [
120
+ a.before !== void 0 ? (s(), o(d, { key: 0 }, [
121
+ t("dt", null, e(l.value.before), 1),
122
+ t("dd", null, e(a.before), 1)
123
+ ], 64)) : m("", !0),
124
+ a.after !== void 0 ? (s(), o(d, { key: 1 }, [
125
+ t("dt", null, e(l.value.after), 1),
126
+ t("dd", null, e(a.after), 1)
127
+ ], 64)) : m("", !0)
128
+ ])
129
+ ]))), 128))
130
+ ])) : (s(), o("p", X, e(l.value.noChanges), 1)) : (s(), o("p", Q, e(l.value.baseline), 1)),
131
+ n.value.changes?.truncated ? (s(), o("p", le, e(l.value.truncated), 1)) : m("", !0),
132
+ n.value.changes?.breakingChanges ? (s(), o("label", te, [
133
+ x(t("input", {
134
+ "onUpdate:modelValue": u[1] || (u[1] = (a) => p.value = a),
135
+ type: "checkbox"
136
+ }, null, 512), [
137
+ [U, p.value]
138
+ ]),
139
+ f(e(l.value.acknowledge), 1)
140
+ ])) : m("", !0)
141
+ ]),
142
+ t("section", null, [
143
+ t("h3", null, e(l.value.issues), 1),
144
+ n.value.issues.length ? (s(), o("ol", se, [
145
+ (s(!0), o(d, null, g(n.value.issues, (a, v) => (s(), o("li", { key: v }, [
146
+ t("div", null, [
147
+ t("span", {
148
+ class: T({ "is-error": a.severity === "error" })
149
+ }, e(a.severity === "error" ? l.value.errors : l.value.warnings), 3),
150
+ t("button", {
151
+ type: "button",
152
+ onClick: (I) => w("locate", a)
153
+ }, e(l.value.locate), 9, oe)
154
+ ]),
155
+ t("p", null, e(a.message), 1),
156
+ t("code", null, e(a.path), 1)
157
+ ]))), 128))
158
+ ])) : (s(), o("p", ae, e(l.value.noIssues), 1))
159
+ ]),
160
+ n.value.samples.length ? (s(), o("section", ne, [
161
+ t("h3", null, e(l.value.results), 1),
162
+ (s(!0), o(d, null, g(n.value.samples, (a) => (s(), o("p", {
163
+ key: a.name
164
+ }, e(a.name) + " · " + e(a.rows) + " " + e(l.value.rows) + " · " + e(a.pages) + " " + e(l.value.pages), 1))), 128))
165
+ ])) : m("", !0),
166
+ t("p", re, e(l.value.checked), 1)
167
+ ], 64)) : (s(), o("p", J, e(l.value.empty), 1))
168
+ ], 8, D));
169
+ }
170
+ }), me = /* @__PURE__ */ A(ue, [["__scopeId", "data-v-57cb15cb"]]);
171
+ export {
172
+ me as default
173
+ };
@@ -48,6 +48,6 @@ const c = ["width", "height"], i = ["d"], a = /* @__PURE__ */ r({
48
48
  return h;
49
49
  };
50
50
  export {
51
- a as _,
52
- l as a
51
+ l as _,
52
+ a
53
53
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=["#2563eb","#0d9488","#d97706","#7c3aed","#dc2626","#0284c7"];function $(e){if(e.type!=="bar"&&e.type!=="line")throw new Error("图表 type 应为 bar 或 line");if(!Array.isArray(e.categories)||!Array.isArray(e.series)||!e.categories.length||e.categories.length>200||!e.series.length||e.series.length>12)throw new Error("图表支持 1–200 个分类、1–12 个系列;大数据应先聚合");if(e.categories.some(r=>typeof r!="string"))throw new Error("图表分类应为字符串");j(e);for(const r of e.series)z(r,e.categories.length)}function j(e){for(const r of["leftMm","topMm","widthMm","heightMm"])if(!Number.isFinite(e[r])||e[r]<0)throw new Error(`${r} 应为有限非负数`);if(e.widthMm<45||e.heightMm<35)throw new Error("图表至少需要 45×35mm");if(!Number.isFinite(e.leftMm+e.widthMm)||!Number.isFinite(e.topMm+e.heightMm))throw new Error("图表几何范围溢出")}function z(e,r){if(!e||typeof e.name!="string"||!Array.isArray(e.values)||e.values.length!==r||e.values.some(t=>t!==null&&!Number.isFinite(t)))throw new Error("图表系列应提供名称及逐分类的有限数字或 null");if(e.color!==void 0&&!/^#[\da-f]{6}$/i.test(e.color))throw new Error("图表颜色应为 #RRGGBB")}function F(e,r,t,n,i,l=.8){return{kind:"line",leftMm:Math.min(e,t),topMm:Math.min(r,n),widthMm:Math.abs(t-e),heightMm:Math.abs(n-r),lineDirection:n<r?"up":"down",style:{lineColor:i,lineWidthPt:l}}}function d(e,r,t,n,i="center"){return{kind:"text",text:e,leftMm:r,topMm:t,widthMm:n,heightMm:5,style:{fontSize:8,color:"#475569",align:i,verticalAlign:"middle"}}}function C(e){return Number(e.toPrecision(5)).toString()}function L(e){let r=0,t=0;for(const s of e.series)for(const a of s.values)a!==null&&(r=Math.min(r,a),t=Math.max(t,a));r===t&&(t=r+1);const n=e.leftMm+13,i=e.topMm+8,l=e.widthMm-17,c=e.heightMm-23,f=Math.max(Math.abs(r),Math.abs(t),1),o=r/f,u=t/f-o;return{left:n,top:i,width:l,height:c,min:r,max:t,y:s=>i+c*(1-(s/f-o)/u)}}function x(e,r){const t=[];e.title&&t.push({...d(e.title,e.leftMm,e.topMm,e.widthMm),style:{fontSize:10,bold:!0,align:"left"}});for(let l=0;l<=4;l++){const c=l/4,f=r.min*(1-c)+r.max*c,o=r.y(f);t.push(F(r.left,o,r.left+r.width,o,"#e2e8f0",.4),d(C(f),e.leftMm,o-2.5,11,"right"))}t.push(F(r.left,r.top,r.left,r.top+r.height,"#94a3b8"));const n=Math.max(1,Math.ceil(e.categories.length/Math.max(1,Math.floor(r.width/14))));e.categories.forEach((l,c)=>{c%n===0&&t.push(d(l,r.left+(c+.5)*r.width/e.categories.length-7,r.top+r.height+1,14))});const i=r.width/e.series.length;return e.series.forEach((l,c)=>{t.push({...d(l.name,r.left+c*i,e.topMm+e.heightMm-5,i),style:{fontSize:8,color:l.color??E[c%E.length],align:"center"}})}),t}function P(e,r,t,n){const i=[],l=t.color??E[n%E.length],c=r.width/e.categories.length,f=c*.75/e.series.length;let o;return t.values.forEach((u,s)=>{if(u===null){o=void 0;return}const a=r.left+(s+.5)*c,m=r.y(u);e.type==="bar"?i.push({kind:"rect",leftMm:r.left+s*c+c*.125+n*f,topMm:Math.min(m,r.y(0)),widthMm:f,heightMm:Math.abs(r.y(0)-m),style:{backgroundColor:l,borderTop:!1,borderRight:!1,borderBottom:!1,borderLeft:!1}}):(o&&i.push(F(o.x,o.y,a,m,l,1.2)),i.push({kind:"ellipse",leftMm:a-.7,topMm:m-.7,widthMm:1.4,heightMm:1.4,style:{backgroundColor:l,borderColor:l}}),o={x:a,y:m}),e.showValues&&i.push({...d(C(u),a-c/2,Math.max(r.top,m-5),c),style:{fontSize:7,color:l,align:"center"}})}),i}function T(e){$(e);const r=L(e);return[...x(e,r),...e.series.flatMap((t,n)=>P(e,r,t,n))]}function b(){return{count:0,sum:0,correction:0,min:1/0,max:-1/0}}function w(e,r){return Object.prototype.hasOwnProperty.call(e,r)?e[r]:void 0}function S(e){if(e==null)return"null";if(typeof e!="string"&&typeof e!="boolean"&&!(typeof e=="number"&&Number.isFinite(e)))throw new Error("交叉表维度应为字符串、布尔、有限数字或空值");return JSON.stringify([typeof e,e])}function A(e){return e==null?"":String(e)}function W(e,r,t){const n=t==="count";if(!n&&r==null)return;if(!n&&(typeof r!="number"||!Number.isFinite(r)))throw new Error("交叉表度量必须是有限数字;编号和小数文本不能隐式转为数字");const i=n?1:r;(t==="sum"||t==="avg")&&_(e,i),e.count++,e.min=Math.min(e.min,i),e.max=Math.max(e.max,i)}function _(e,r){const t=r-e.correction,n=e.sum+t;if(!Number.isFinite(n))throw new Error("交叉表聚合溢出");e.correction=n-e.sum-t,e.sum=n}function y(e,r){return e?.count?r==="count"?e.count:r==="avg"?e.sum/e.count:r==="sum"?e.sum:e[r]:r==="count"?0:null}function M(e,r){const t=e??r;if(!Number.isInteger(t)||t<1)throw new Error("交叉表预算应为正整数");return t}function B(e,r,t,n){const i=t?1:0;if((e+i)*(r+1+i)>n)throw new Error("交叉表输出单元格超出 maxCells 预算,请减少维度或服务端预聚合")}function D(e,r){const t=r.aggregate??"sum";if(!["sum","count","avg","min","max"].includes(t))throw new Error("未知交叉表聚合类型");if(!r.rowField||!r.columnField||t!=="count"&&!r.valueField)throw new Error("交叉表需要明确的行维度、列维度和度量字段");if(e.length>M(r.maxInputRows,1e5))throw new Error("交叉表输入超出预算,请在服务端预聚合");const n=M(r.maxRows,1e3),i=M(r.maxColumns,200),l=M(r.maxCells,2e6),c=new Map,f=new Map,o=new Map,u=b();for(const a of e){const m=S(w(a,r.rowField)),h=S(w(a,r.columnField));if(c.has(h)||c.set(h,A(w(a,r.columnField))),f.has(m)||f.set(m,{label:A(w(a,r.rowField)),cells:new Map,total:b()}),c.size>i||f.size>n)throw new Error("交叉表维度数量超出预算");B(f.size,c.size,r.totals,l);const g=f.get(m);g.cells.has(h)||g.cells.set(h,b()),o.has(h)||o.set(h,b());const k=r.valueField?w(a,r.valueField):void 0;for(const R of[g.cells.get(h),g.total,o.get(h),u])W(R,k,t)}const s={columns:[{header:r.rowHeader??r.rowField,field:"rowLabel",semanticRole:"dimension"},...[...c.values()].map((a,m)=>({header:a,field:`c${m}`,semanticRole:"measure"}))],rows:[...f.values()].map(a=>({rowLabel:a.label,...Object.fromEntries([...c.keys()].map((m,h)=>[`c${h}`,y(a.cells.get(m),t)])),...r.totals?{total:y(a.total,t)}:{}}))};return r.totals&&(s.columns.push({header:"合计",field:"total",semanticRole:"measure"}),e.length&&s.rows.push({rowLabel:"合计",...Object.fromEntries([...c.keys()].map((a,m)=>[`c${m}`,y(o.get(a),t)])),total:y(u,t)})),s}const G=new Set(["__proto__","prototype","constructor"]);function N(e){if(typeof e!="string"||!e.trim()||G.has(e))throw new Error("计算字段应为安全的非空字段名")}function v(e){return e===null||["string","boolean"].includes(typeof e)||typeof e=="number"&&Number.isFinite(e)}function I(e){if(e.some(r=>typeof r!="number"||!Number.isFinite(r)))throw new Error("算术参数必须是有限数字;空值和小数文本不会隐式转换");return e}function J(e,r){const t=I(r);let n;if(e==="add")n=t.reduce((i,l)=>i+l,0);else if(e==="multiply")n=t.reduce((i,l)=>i*l,1);else if(e==="subtract")n=t[0]-t[1];else{if(t[1]===0)throw new Error("不能除以零");n=t[0]/t[1]}if(!Number.isFinite(n))throw new Error("计算结果不是有限数字");return n}function O(e,r,t=0){if(++r.nodes>256||t>16)throw new Error("计算表达式超出深度或节点预算");if(!e||typeof e!="object"||Array.isArray(e))throw new Error("计算表达式应为声明式对象");if("field"in e){N(e.field);const i=e.field;return l=>Object.prototype.hasOwnProperty.call(l,i)?l[i]:void 0}if("value"in e){if(!v(e.value))throw new Error("常量应为有限 JSON 标量");return()=>e.value}if(!["add","subtract","multiply","divide","coalesce"].includes(e.op)||!Array.isArray(e.args))throw new Error("未知计算操作");if(e.args.length<2||["subtract","divide"].includes(e.op)&&e.args.length!==2)throw new Error("运算参数数量不正确");const n=e.args.map(i=>O(i,r,t+1));return e.op==="coalesce"?(i,l)=>H(n,i,l):(i,l)=>J(e.op,n.map(c=>c(i,l)))}function H(e,r,t){for(const n of e){const i=n(r,t);if(i!=null)return i}return null}function U(e){const r=new Set;return e.fields.map(t=>{if(N(t.field),r.has(t.field))throw new Error(`计算字段重复:${t.field}`);r.add(t.field);const n=t.expression;let i;if(typeof n=="string"){if(!e.formula)throw new Error("字符串公式需要显式配置 formula adapter");i=(l,c)=>e.formula.evaluate(n,{row:l,rowIndex:c})}else i=O(n,{nodes:0});return{field:t.field,read:i}})}function V(e,r){const t=r.maxRows??1e5,n=r.maxCells??2e6;if(!Array.isArray(e)||!Number.isSafeInteger(t)||t<1||e.length>t)throw new Error("计算数据行数超出预算或输入不是数组");if(!Array.isArray(r.fields)||r.fields.length>2048)throw new Error("计算字段应为数组且最多2048项");if(!Number.isSafeInteger(n)||n<1||e.length*r.fields.length>n)throw new Error("计算单元格超出 maxCells 预算")}function q(e,r){V(e,r);const t=U(r),n=[];return{rows:e.map((l,c)=>{if(!l||typeof l!="object"||Array.isArray(l))throw new Error(`第 ${c+1} 行应为对象`);if(r.signal?.aborted){const o=new Error("数据计算已取消");throw o.name="AbortError",o}const f={...l};for(const o of t)try{const u=o.read(f,c);if(u!==void 0&&!v(u))throw new Error("计算结果应为有限 JSON 标量,异步公式请先在数据源中求值");f[o.field]=u??null}catch(u){const s=u instanceof Error?u.message:String(u);if(r.onError!=="null")throw Object.assign(new Error(`第 ${c+1} 行 ${o.field}:${s}`),{cause:u});f[o.field]=null,n.push({rowIndex:c,field:o.field,message:s})}return f}),issues:n}}exports.computeDataset=q;exports.createChartComponents=T;exports.createCrossTable=D;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("./matrix-Div9Ilh3.cjs"),u=["#2563eb","#0d9488","#d97706","#7c3aed","#dc2626","#0284c7"];function w(e){if(e.type!=="bar"&&e.type!=="line")throw new Error("图表 type 应为 bar 或 line");if(!Array.isArray(e.categories)||!Array.isArray(e.series)||!e.categories.length||e.categories.length>200||!e.series.length||e.series.length>12)throw new Error("图表支持 1–200 个分类、1–12 个系列;大数据应先聚合");if(e.categories.some(t=>typeof t!="string"))throw new Error("图表分类应为字符串");y(e);for(const t of e.series)D(t,e.categories.length)}function y(e){for(const t of["leftMm","topMm","widthMm","heightMm"])if(!Number.isFinite(e[t])||e[t]<0)throw new Error(`${t} 应为有限非负数`);if(e.widthMm<45||e.heightMm<35)throw new Error("图表至少需要 45×35mm");if(!Number.isFinite(e.leftMm+e.widthMm)||!Number.isFinite(e.topMm+e.heightMm))throw new Error("图表几何范围溢出")}function D(e,t){if(!e||typeof e.name!="string"||!Array.isArray(e.values)||e.values.length!==t||e.values.some(r=>r!==null&&!Number.isFinite(r)))throw new Error("图表系列应提供名称及逐分类的有限数字或 null");if(e.color!==void 0&&!/^#[\da-f]{6}$/i.test(e.color))throw new Error("图表颜色应为 #RRGGBB")}function M(e,t,r,m,c,a=.8){return{kind:"line",leftMm:Math.min(e,r),topMm:Math.min(t,m),widthMm:Math.abs(r-e),heightMm:Math.abs(m-t),lineDirection:m<t?"up":"down",style:{lineColor:c,lineWidthPt:a}}}function d(e,t,r,m,c="center"){return{kind:"text",text:e,leftMm:t,topMm:r,widthMm:m,heightMm:5,style:{fontSize:8,color:"#475569",align:c,verticalAlign:"middle"}}}function b(e){return Number(e.toPrecision(5)).toString()}function C(e){let t=0,r=0;for(const s of e.series)for(const f of s.values)f!==null&&(t=Math.min(t,f),r=Math.max(r,f));t===r&&(r=t+1);const m=e.leftMm+13,c=e.topMm+8,a=e.widthMm-17,i=e.heightMm-23,n=Math.max(Math.abs(t),Math.abs(r),1),h=t/n,o=r/n-h;return{left:m,top:c,width:a,height:i,min:t,max:r,y:s=>c+i*(1-(s/n-h)/o)}}function v(e,t){const r=[];e.title&&r.push({...d(e.title,e.leftMm,e.topMm,e.widthMm),style:{fontSize:10,bold:!0,align:"left"}});for(let a=0;a<=4;a++){const i=a/4,n=t.min*(1-i)+t.max*i,h=t.y(n);r.push(M(t.left,h,t.left+t.width,h,"#e2e8f0",.4),d(b(n),e.leftMm,h-2.5,11,"right"))}r.push(M(t.left,t.top,t.left,t.top+t.height,"#94a3b8"));const m=Math.max(1,Math.ceil(e.categories.length/Math.max(1,Math.floor(t.width/14))));e.categories.forEach((a,i)=>{i%m===0&&r.push(d(a,t.left+(i+.5)*t.width/e.categories.length-7,t.top+t.height+1,14))});const c=t.width/e.series.length;return e.series.forEach((a,i)=>{r.push({...d(a.name,t.left+i*c,e.topMm+e.heightMm-5,c),style:{fontSize:8,color:a.color??u[i%u.length],align:"center"}})}),r}function x(e,t,r,m){const c=[],a=r.color??u[m%u.length],i=t.width/e.categories.length,n=i*.75/e.series.length;let h;return r.values.forEach((o,s)=>{if(o===null){h=void 0;return}const f=t.left+(s+.5)*i,g=t.y(o);e.type==="bar"?c.push({kind:"rect",leftMm:t.left+s*i+i*.125+m*n,topMm:Math.min(g,t.y(0)),widthMm:n,heightMm:Math.abs(t.y(0)-g),style:{backgroundColor:a,borderTop:!1,borderRight:!1,borderBottom:!1,borderLeft:!1}}):(h&&c.push(M(h.x,h.y,f,g,a,1.2)),c.push({kind:"ellipse",leftMm:f-.7,topMm:g-.7,widthMm:1.4,heightMm:1.4,style:{backgroundColor:a,borderColor:a}}),h={x:f,y:g}),e.showValues&&c.push({...d(b(o),f-i/2,Math.max(t.top,g-5),i),style:{fontSize:7,color:a,align:"center"}})}),c}function k(e){w(e);const t=C(e);return[...v(e,t),...e.series.flatMap((r,m)=>x(e,t,r,m))]}exports.addDecimal=l.addDecimal;exports.aggregateRows=l.aggregateRows;exports.compareDecimal=l.compareDecimal;exports.computeDataset=l.computeDataset;exports.createAggregateAccumulator=l.createAggregateAccumulator;exports.createCrossTable=l.createCrossTable;exports.createMatrixTable=l.createMatrixTable;exports.decimalDigits=l.decimalDigits;exports.divideDecimal=l.divideDecimal;exports.estimateMatrixTable=l.estimateMatrixTable;exports.formatDecimal=l.formatDecimal;exports.getComputationMetadata=l.getComputationMetadata;exports.multiplyDecimal=l.multiplyDecimal;exports.parseDecimal=l.parseDecimal;exports.printDecimal=l.printDecimal;exports.validateComputedFields=l.validateComputedFields;exports.validateMatrixOptions=l.validateMatrixOptions;exports.createChartComponents=k;
@@ -1,3 +1,32 @@
1
+ export declare function addDecimal(a: DecimalValue, b: DecimalValue): DecimalValue;
2
+
3
+ export declare interface AggregateAccumulator {
4
+ add(row: Readonly<Record<string, unknown>>): void;
5
+ value(): number | string | null;
6
+ }
7
+
8
+ export declare interface AggregateDefinition {
9
+ /** Output column; valueField defaults to this field. */
10
+ field: string;
11
+ op: AggregateOperation;
12
+ valueField?: string;
13
+ weightField?: string;
14
+ numeric?: "number" | "decimal";
15
+ digits?: number;
16
+ }
17
+
18
+ export declare type AggregateOperation = "sum" | "count" | "avg" | "min" | "max" | "weightedAvg";
19
+
20
+ export declare interface AggregateRequest {
21
+ op: AggregateOperation;
22
+ field?: string;
23
+ weightField?: string;
24
+ numeric?: "number" | "decimal";
25
+ digits?: number;
26
+ }
27
+
28
+ export declare function aggregateRows(rows: readonly Record<string, unknown>[], request: AggregateRequest): number | string | null;
29
+
1
30
  /**
2
31
  * 列值格式化(声明式、JSON 可序列化)。
3
32
  * 在 paginate 的 cellText 出口统一消费:格式化发生在进 RenderPlan 之前,
@@ -21,6 +50,8 @@ declare type ColumnFormat = {
21
50
  pattern?: string;
22
51
  };
23
52
 
53
+ export declare function compareDecimal(a: DecimalValue, b: DecimalValue): number;
54
+
24
55
  declare type ComponentKind = "text" | "image" | "barcode" | "qrcode" | "chart" | "line" | "rect" | "ellipse";
25
56
 
26
57
  declare interface ComponentStyle {
@@ -53,7 +84,14 @@ export declare interface ComputationIssue {
53
84
  message: string;
54
85
  }
55
86
 
56
- /** 纯数据计算与界面解耦;字段按声明顺序计算,可供后续字段引用,不修改输入数据。 */
87
+ export declare interface ComputationValidation {
88
+ valid: boolean;
89
+ errors: string[];
90
+ fields: ComputedFieldDiagnostic[];
91
+ order: string[];
92
+ }
93
+
94
+ /** Topologically ordered column passes keep aggregate dependencies correct and avoid quadratic group scans. */
57
95
  export declare function computeDataset(input: readonly Record<string, unknown>[], options: ComputedDatasetOptions): {
58
96
  rows: Record<string, unknown>[];
59
97
  issues: ComputationIssue[];
@@ -63,30 +101,51 @@ export declare interface ComputedDatasetOptions {
63
101
  fields: readonly ComputedField[];
64
102
  formula?: FormulaAdapter;
65
103
  maxRows?: number;
66
- /** Calculated cells (rows × fields), default 2 million; at most 2048 field definitions. */
67
104
  maxCells?: number;
68
105
  signal?: AbortSignal;
69
106
  onError?: "throw" | "null";
70
107
  }
71
108
 
72
- export declare interface ComputedField {
109
+ export declare interface ComputedField extends ExpressionOptions {
73
110
  field: string;
74
111
  expression: ReportExpression | string;
112
+ /** Scope controls aggregate inputs; row expressions may reference the current row in any scope. */
113
+ scope?: "row" | "group" | "dataset";
114
+ groupBy?: readonly string[];
115
+ /** String adapter expressions cannot be inspected; declare dependencies explicitly. */
116
+ dependsOn?: readonly string[];
75
117
  }
76
118
 
119
+ export declare interface ComputedFieldDiagnostic {
120
+ field: string;
121
+ dependencies: string[];
122
+ scope: "row" | "group" | "dataset";
123
+ }
124
+
125
+ /** Nulls are skipped; count with no field counts rows, all-null numeric aggregates stay null. */
126
+ export declare function createAggregateAccumulator(request: AggregateRequest): AggregateAccumulator;
127
+
77
128
  /** 轻量柱/折线图展开为共用基础图元,无外部图表依赖,DOM/Canvas/PDF 使用同一计划。 */
78
129
  export declare function createChartComponents(options: ReportChartOptions): PlanComponent[];
79
130
 
80
131
  /** 通用交叉聚合;合计直接累计原始度量,平均值不会错误地平均各分组合计。 */
81
132
  export declare function createCrossTable(input: readonly Record<string, unknown>[], options: CrossTableOptions): CrossTableResult;
82
133
 
134
+ /** Multi-dimension/multi-measure pivot; each total aggregates original rows, never averages averages. */
135
+ export declare function createMatrixTable(input: readonly Record<string, unknown>[], options: MatrixTableOptions): CrossTableResult;
136
+
83
137
  export declare interface CrossTableOptions {
84
138
  rowField: string;
85
139
  columnField: string;
86
140
  valueField?: string;
87
- aggregate?: "sum" | "count" | "avg" | "min" | "max";
141
+ aggregate?: AggregateOperation;
142
+ weightField?: string;
143
+ numeric?: "number" | "decimal";
144
+ digits?: number;
88
145
  totals?: boolean;
89
146
  rowHeader?: string;
147
+ /** Existing count defaults to row counts; opt-in SQL COUNT(field) skips nulls. */
148
+ countMode?: "rows" | "nonNull";
90
149
  maxRows?: number;
91
150
  maxColumns?: number;
92
151
  maxInputRows?: number;
@@ -99,14 +158,94 @@ export declare interface CrossTableResult {
99
158
  rows: Record<string, unknown>[];
100
159
  }
101
160
 
161
+ export declare function decimalDigits(digits: number): void;
162
+
163
+ /** Bounded base-ten arithmetic. Decimal strings never pass through IEEE-754 numbers. */
164
+ export declare interface DecimalValue {
165
+ coefficient: bigint;
166
+ scale: number;
167
+ }
168
+
169
+ export declare function divideDecimal(a: DecimalValue, b: DecimalValue, digits?: number): DecimalValue;
170
+
171
+ /** Cardinality pass checks expansion budgets before allocating the dense pivot output. */
172
+ export declare function estimateMatrixTable(input: readonly Record<string, unknown>[], options: MatrixTableOptions): MatrixTableShape;
173
+
174
+ declare interface ExpressionOptions {
175
+ numeric?: "number" | "decimal";
176
+ digits?: number;
177
+ nulls?: "propagate" | "error";
178
+ divisionByZero?: "null" | "error";
179
+ }
180
+
181
+ /** Formats decimal data exactly while preserving it as text in Excel. */
182
+ export declare function formatDecimal(input: string, digits?: number, thousands?: boolean, percent?: boolean): string;
183
+
102
184
  export declare interface FormulaAdapter {
103
- /** 显式注入受信任的公式引擎;核心不执行 eval、宏或外部工作簿引用。 */
185
+ /** Explicit trusted engine; core never evaluates source code/macros/external workbook references. */
104
186
  evaluate(expression: string, context: {
105
187
  row: Readonly<Record<string, unknown>>;
106
188
  rowIndex: number;
189
+ rows: readonly Record<string, unknown>[];
107
190
  }): unknown;
108
191
  }
109
192
 
193
+ export declare function getComputationMetadata(fields?: readonly {
194
+ field: string;
195
+ type: string;
196
+ label?: string;
197
+ }[]): {
198
+ fields: {
199
+ field: string;
200
+ type: string;
201
+ label?: string;
202
+ }[];
203
+ functions: readonly [{
204
+ readonly name: "add";
205
+ readonly minArgs: 2;
206
+ readonly maxArgs: 256;
207
+ readonly input: "numeric";
208
+ readonly output: "numeric";
209
+ }, {
210
+ readonly name: "subtract";
211
+ readonly minArgs: 2;
212
+ readonly maxArgs: 2;
213
+ readonly input: "numeric";
214
+ readonly output: "numeric";
215
+ }, {
216
+ readonly name: "multiply";
217
+ readonly minArgs: 2;
218
+ readonly maxArgs: 256;
219
+ readonly input: "numeric";
220
+ readonly output: "numeric";
221
+ }, {
222
+ readonly name: "divide";
223
+ readonly minArgs: 2;
224
+ readonly maxArgs: 2;
225
+ readonly input: "numeric";
226
+ readonly output: "numeric";
227
+ }, {
228
+ readonly name: "coalesce";
229
+ readonly minArgs: 2;
230
+ readonly maxArgs: 256;
231
+ readonly input: "scalar";
232
+ readonly output: "scalar";
233
+ }];
234
+ operations: readonly ["add", "subtract", "multiply", "divide", "coalesce"];
235
+ aggregates: readonly ["sum", "count", "avg", "min", "max", "weightedAvg"];
236
+ scopes: readonly ["row", "group", "dataset"];
237
+ numericModes: readonly ["number", "decimal"];
238
+ rules: {
239
+ readonly nulls: "propagate";
240
+ readonly aggregateNulls: "skip";
241
+ readonly emptyAggregate: null;
242
+ readonly countEmpty: 0;
243
+ readonly divisionByZero: "error";
244
+ readonly decimalOutput: "string";
245
+ readonly rounding: "half-away-from-zero";
246
+ };
247
+ };
248
+
110
249
  declare interface GridCell {
111
250
  text?: string;
112
251
  rawText?: string;
@@ -151,9 +290,40 @@ declare interface ListColumn {
151
290
  valueType?: GridCell["valueType"];
152
291
  /** 字段语义用于 auto 对齐;明确声明编号,避免把数字编号当成度量。 */
153
292
  semanticRole?: "identifier" | "dimension" | "measure" | "date" | "text";
293
+ hidden?: boolean;
294
+ /** Condition hides cell content, preserving its physical layout in preview and exports. */
295
+ visibleWhen?: StyleRule["when"];
154
296
  }
155
297
 
298
+ export declare interface MatrixTableOptions {
299
+ rowFields: readonly string[];
300
+ columnFields: readonly string[];
301
+ measures: readonly (AggregateDefinition & {
302
+ label?: string;
303
+ })[];
304
+ totals?: boolean;
305
+ rowHeader?: string;
306
+ columnWidthMm?: number;
307
+ rowWidthMm?: number;
308
+ maxRows?: number;
309
+ maxColumns?: number;
310
+ maxInputRows?: number;
311
+ maxCells?: number;
312
+ }
313
+
314
+ export declare interface MatrixTableShape {
315
+ rowCount: number;
316
+ columnCount: number;
317
+ cells: number;
318
+ }
319
+
320
+ export declare function multiplyDecimal(a: DecimalValue, b: DecimalValue): DecimalValue;
321
+
322
+ export declare function parseDecimal(input: unknown): DecimalValue;
323
+
156
324
  declare interface PlanComponent {
325
+ /** Template page furniture repeats per page and reserves its vertical band. */
326
+ pageAnchor?: "header" | "footer";
157
327
  kind: ComponentKind;
158
328
  leftMm: number;
159
329
  topMm: number;
@@ -203,6 +373,8 @@ declare interface PlanTableFragment {
203
373
  };
204
374
  }
205
375
 
376
+ export declare function printDecimal(value: DecimalValue, digits?: number): string;
377
+
206
378
  /** 可持久化的业务身份与计划坐标独立;权限及并发校验仍由业务服务器执行。 */
207
379
  declare interface ReportCellSource {
208
380
  datasetId: string;
@@ -234,6 +406,10 @@ export declare type ReportExpression = {
234
406
  field: string;
235
407
  } | {
236
408
  value: string | number | boolean | null;
409
+ } | {
410
+ aggregate: AggregateOperation;
411
+ field?: string;
412
+ weightField?: string;
237
413
  } | {
238
414
  op: "add" | "subtract" | "multiply" | "divide" | "coalesce";
239
415
  args: readonly ReportExpression[];
@@ -261,6 +437,8 @@ declare interface StyleRule {
261
437
  field: string;
262
438
  op: ">" | ">=" | "<" | "<=" | "==" | "!=";
263
439
  value: number | string;
440
+ /** Explicit decimal comparisons retain decimal thresholds as text. */
441
+ numeric?: "number" | "decimal";
264
442
  };
265
443
  /** 命中时合并进单元格样式(color/bold/backgroundColor 等) */
266
444
  style: Record<string, unknown>;
@@ -273,4 +451,9 @@ declare type TableTemplateColumn = Omit<ListColumn, "widthMm"> & {
273
451
  flex?: number;
274
452
  };
275
453
 
454
+ /** Design-time validation: no input data, adapters, evaluation or DOM required. */
455
+ export declare function validateComputedFields(definitions: readonly ComputedField[]): ComputationValidation;
456
+
457
+ export declare function validateMatrixOptions(options: MatrixTableOptions): void;
458
+
276
459
  export { }