@veltra/sheet 2.0.1 → 2.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.
Files changed (339) hide show
  1. package/dist/components/report/binding-badge.js +76 -0
  2. package/dist/components/report/designer/cell-coords.js +46 -0
  3. package/dist/components/report/designer/col-widths.js +15 -0
  4. package/dist/components/report/designer/conditional-rules/helpers.js +139 -0
  5. package/dist/components/report/designer/drop-highlight-overlay.js +76 -0
  6. package/dist/components/report/designer/float-panel.js +385 -0
  7. package/dist/components/report/designer/role.js +17 -0
  8. package/dist/components/report/designer/rule-preview.js +33 -0
  9. package/dist/components/report/designer/rule-row.js +269 -0
  10. package/dist/components/report/designer/rules-dialog.js +135 -0
  11. package/dist/components/report/designer/topology-overlay.js +122 -0
  12. package/dist/components/report/designer/topology.js +64 -0
  13. package/dist/components/report/designer/use-grid-overlay.js +75 -0
  14. package/dist/components/report/designer-hub.js +177 -0
  15. package/dist/components/report/field-panel-helpers.js +33 -0
  16. package/dist/components/report/field-panel.js +132 -0
  17. package/dist/components/report/filter-bar.js +74 -0
  18. package/dist/components/report/hub-connection-form.js +145 -0
  19. package/dist/components/report/hub-dataset-editor.js +394 -0
  20. package/dist/components/report/report-designer.js +343 -0
  21. package/dist/components/report/report-viewer.js +111 -0
  22. package/dist/components/report/style.d.ts +17 -0
  23. package/dist/components/report/style.js +18 -0
  24. package/dist/components/report/style2.css +869 -0
  25. package/dist/components/report/use-report-designer.js +360 -0
  26. package/dist/components/report/use-report-viewer.js +50 -0
  27. package/dist/components/sheet/formula-bar.js +393 -0
  28. package/dist/components/sheet/formula-suggest-list.js +66 -0
  29. package/dist/components/sheet/import-file.js +140 -0
  30. package/dist/components/sheet/insert-count-menu-item.js +68 -0
  31. package/dist/components/sheet/insert-image.js +79 -0
  32. package/dist/components/sheet/popup-helpers.js +73 -0
  33. package/dist/components/sheet/popups/border-popup.js +75 -0
  34. package/dist/components/sheet/popups/border-preset-glyph.js +106 -0
  35. package/dist/components/sheet/popups/export-popup.js +51 -0
  36. package/dist/components/sheet/popups/fill-color-popup.js +37 -0
  37. package/dist/components/sheet/popups/find-popup.js +113 -0
  38. package/dist/components/sheet/popups/font-color-popup.js +37 -0
  39. package/dist/components/sheet/popups/font-size-popup.js +63 -0
  40. package/dist/components/sheet/popups/import.worker.d.ts +21 -0
  41. package/dist/components/sheet/popups/import.worker.js +41 -0
  42. package/dist/components/sheet/popups/insert-image-popup.js +38 -0
  43. package/dist/components/sheet/sheet-context-menu.js +200 -0
  44. package/dist/components/sheet/sheet-tabs.js +162 -0
  45. package/dist/components/sheet/sheet-toolbar.js +106 -0
  46. package/dist/components/sheet/sheet.js +198 -0
  47. package/dist/components/sheet/style.d.ts +11 -0
  48. package/dist/components/sheet/style.js +12 -0
  49. package/dist/components/sheet/style2.css +654 -0
  50. package/dist/components/sheet/use-find-replace.js +161 -0
  51. package/dist/components/sheet/use-formula-ref-select.js +37 -0
  52. package/dist/components/sheet/use-formula-suggest.js +126 -0
  53. package/dist/components/sheet/use-sheet-grid.js +188 -0
  54. package/dist/components/sheet/use-sheet-state.js +122 -0
  55. package/dist/components/sheet/use-sheet-tabs-bar.js +90 -0
  56. package/dist/components/sheet/use-tool-groups.js +42 -0
  57. package/dist/components/sheet/use-tool-popup.js +123 -0
  58. package/dist/components/sheet/use-toolbar-scroll.js +72 -0
  59. package/dist/index.d.ts +18 -26
  60. package/dist/index.js +14 -24
  61. package/dist/report/binding.d.ts +45 -0
  62. package/dist/report/binding.js +175 -0
  63. package/dist/report/connector.d.ts +66 -0
  64. package/dist/report/connector.js +159 -0
  65. package/dist/report/export-xlsx.d.ts +19 -0
  66. package/dist/report/export-xlsx.js +95 -0
  67. package/dist/report/filter-bar.d.ts +10 -0
  68. package/dist/report/filter-bar.js +31 -0
  69. package/dist/report/index.d.ts +12 -0
  70. package/dist/report/params.d.ts +13 -0
  71. package/dist/report/params.js +61 -0
  72. package/dist/report/render/aggregate.js +157 -0
  73. package/dist/report/render/builder.d.ts +12 -0
  74. package/dist/report/render/builder.js +139 -0
  75. package/dist/report/render/coordinate.d.ts +25 -0
  76. package/dist/report/render/coordinate.js +733 -0
  77. package/dist/report/render/index.d.ts +14 -0
  78. package/dist/report/render/index.js +21 -0
  79. package/dist/report/render/style-resolver.js +50 -0
  80. package/dist/report/render/template-index.d.ts +24 -0
  81. package/dist/report/render/template-index.js +137 -0
  82. package/dist/report/rules/evaluate.d.ts +25 -0
  83. package/dist/report/rules/evaluate.js +82 -0
  84. package/dist/report/rules/index.d.ts +2 -0
  85. package/dist/report/template.d.ts +59 -0
  86. package/dist/report/template.js +80 -0
  87. package/dist/report/types.d.ts +85 -0
  88. package/dist/tools/builtin.js +279 -8
  89. package/dist/tools/context.d.ts +54 -11
  90. package/dist/tools/context.js +28 -5
  91. package/dist/tools/download.js +68 -0
  92. package/dist/tools/export.worker.d.ts +16 -0
  93. package/dist/tools/export.worker.js +29 -0
  94. package/dist/tools/registry.d.ts +7 -4
  95. package/dist/tools/registry.js +1 -3
  96. package/dist/types/index.d.ts +3 -1
  97. package/dist/types/report-designer.d.ts +36 -0
  98. package/dist/types/report-viewer.d.ts +38 -0
  99. package/dist/types/sheet.d.ts +22 -5
  100. package/package.json +10 -7
  101. package/src/components/report/__test__/conditional-rules-helpers.test.ts +87 -0
  102. package/src/components/report/__test__/field-panel-helpers.test.ts +65 -0
  103. package/src/components/report/__test__/float-panel-position.test.ts +45 -0
  104. package/src/components/report/__test__/report-designer.test.ts +388 -0
  105. package/src/components/report/__test__/report-viewer.test.ts +334 -0
  106. package/src/components/report/__test__/topology.test.ts +143 -0
  107. package/src/components/report/__test__/use-report-designer.test.ts +565 -0
  108. package/src/components/report/binding-badge.ts +73 -0
  109. package/src/components/report/designer/cell-coords.ts +94 -0
  110. package/src/components/report/designer/col-widths.ts +33 -0
  111. package/src/components/report/designer/conditional-rules/helpers.ts +186 -0
  112. package/src/components/report/designer/drop-highlight-overlay.vue +74 -0
  113. package/src/components/report/designer/float-panel.vue +387 -0
  114. package/src/components/report/designer/role.ts +32 -0
  115. package/src/components/report/designer/rule-preview.vue +40 -0
  116. package/src/components/report/designer/rule-row.vue +252 -0
  117. package/src/components/report/designer/rules-dialog.vue +126 -0
  118. package/src/components/report/designer/topology-overlay.vue +127 -0
  119. package/src/components/report/designer/topology.ts +124 -0
  120. package/src/components/report/designer/use-grid-overlay.ts +113 -0
  121. package/src/components/report/designer-hub.vue +198 -0
  122. package/src/components/report/field-panel-helpers.ts +44 -0
  123. package/src/components/report/field-panel.vue +136 -0
  124. package/src/components/report/filter-bar.vue +77 -0
  125. package/src/components/report/hub-connection-form.vue +124 -0
  126. package/src/components/report/hub-dataset-editor.vue +369 -0
  127. package/src/components/report/index.ts +2 -0
  128. package/src/components/report/report-designer.vue +356 -0
  129. package/src/components/report/report-viewer.vue +128 -0
  130. package/src/components/report/style-designer.scss +583 -0
  131. package/src/components/report/style-hub.scss +292 -0
  132. package/src/components/report/style-viewer.scss +104 -0
  133. package/src/components/report/style.scss +3 -0
  134. package/src/components/report/style.ts +20 -0
  135. package/src/components/report/use-report-designer.ts +547 -0
  136. package/src/components/report/use-report-viewer.ts +79 -0
  137. package/src/components/sheet/__test__/formula-bar.test.ts +474 -0
  138. package/src/components/sheet/__test__/import-file.test.ts +183 -0
  139. package/src/components/sheet/__test__/insert-count-menu-item.test.ts +123 -0
  140. package/src/components/sheet/__test__/insert-image-popup.test.ts +89 -0
  141. package/src/components/sheet/__test__/insert-image.test.ts +100 -0
  142. package/src/components/sheet/__test__/sheet-component.test.ts +993 -0
  143. package/src/components/sheet/__test__/sheet-context-menu.test.ts +206 -0
  144. package/src/components/sheet/__test__/use-formula-ref-select.test.ts +35 -0
  145. package/src/components/sheet/__test__/use-formula-suggest.test.ts +83 -0
  146. package/src/components/sheet/formula-bar.vue +473 -0
  147. package/src/components/sheet/formula-suggest-list.vue +64 -0
  148. package/src/components/sheet/import-file.ts +173 -0
  149. package/src/components/sheet/insert-count-menu-item.vue +69 -0
  150. package/src/components/sheet/insert-image.ts +90 -0
  151. package/src/components/sheet/parsing.ts +11 -0
  152. package/src/components/sheet/popup-helpers.ts +50 -0
  153. package/src/components/sheet/popups/border-popup.vue +93 -0
  154. package/src/components/sheet/popups/border-preset-glyph.vue +111 -0
  155. package/src/components/sheet/popups/export-popup.vue +52 -0
  156. package/src/components/sheet/popups/fill-color-popup.vue +39 -0
  157. package/src/components/sheet/popups/find-popup.vue +111 -0
  158. package/src/components/sheet/popups/font-color-popup.vue +39 -0
  159. package/src/components/sheet/popups/font-size-popup.vue +52 -0
  160. package/src/components/sheet/popups/import.worker.ts +66 -0
  161. package/src/components/sheet/popups/insert-image-popup.vue +39 -0
  162. package/src/components/sheet/sheet-context-menu.ts +229 -0
  163. package/src/components/sheet/sheet-tabs.vue +162 -0
  164. package/src/components/sheet/sheet-toolbar.vue +91 -0
  165. package/src/components/sheet/sheet.vue +211 -0
  166. package/src/components/sheet/style.scss +737 -0
  167. package/src/components/sheet/style.ts +13 -0
  168. package/src/components/sheet/use-find-replace.ts +200 -0
  169. package/src/components/sheet/use-formula-ref-select.ts +34 -0
  170. package/src/components/sheet/use-formula-suggest.ts +150 -0
  171. package/src/components/sheet/use-sheet-grid.ts +247 -0
  172. package/src/components/sheet/use-sheet-state.ts +161 -0
  173. package/src/components/sheet/use-sheet-tabs-bar.ts +115 -0
  174. package/src/components/sheet/use-tool-groups.ts +61 -0
  175. package/src/components/sheet/use-tool-popup.ts +150 -0
  176. package/src/components/sheet/use-toolbar-scroll.ts +95 -0
  177. package/src/env.d.ts +11 -0
  178. package/src/index.ts +39 -14
  179. package/src/report/__test__/binding.test.ts +218 -0
  180. package/src/report/__test__/connector.test.ts +218 -0
  181. package/src/report/__test__/export-xlsx.test.ts +118 -0
  182. package/src/report/__test__/filter-bar.test.ts +58 -0
  183. package/src/report/__test__/params.test.ts +156 -0
  184. package/src/report/__test__/render.test.ts +728 -0
  185. package/src/report/__test__/rules.test.ts +131 -0
  186. package/src/report/__test__/template.test.ts +355 -0
  187. package/src/report/binding.ts +243 -0
  188. package/src/report/connector.ts +205 -0
  189. package/src/report/export-xlsx.ts +118 -0
  190. package/src/report/filter-bar.ts +36 -0
  191. package/src/report/index.ts +13 -0
  192. package/src/report/params.ts +96 -0
  193. package/src/report/render/__test__/aggregate.test.ts +16 -0
  194. package/src/report/render/__test__/coordinate.test.ts +405 -0
  195. package/src/report/render/aggregate.ts +240 -0
  196. package/src/report/render/builder.ts +211 -0
  197. package/src/report/render/coordinate.ts +1239 -0
  198. package/src/report/render/index.ts +30 -0
  199. package/src/report/render/style-resolver.ts +68 -0
  200. package/src/report/render/template-index.ts +200 -0
  201. package/src/report/rules/evaluate.ts +113 -0
  202. package/src/report/rules/index.ts +7 -0
  203. package/src/report/template.ts +141 -0
  204. package/src/report/types.ts +96 -0
  205. package/src/tools/__test__/builtin.test.ts +208 -66
  206. package/src/tools/__test__/context.test.ts +62 -2
  207. package/src/tools/builtin.ts +350 -6
  208. package/src/tools/context.ts +89 -11
  209. package/src/tools/download.ts +82 -0
  210. package/src/tools/export.worker.ts +61 -0
  211. package/src/tools/registry.ts +16 -1
  212. package/src/types/index.ts +2 -0
  213. package/src/types/report-designer.ts +36 -0
  214. package/src/types/report-viewer.ts +37 -0
  215. package/src/types/sheet.ts +26 -3
  216. package/dist/core/address.d.ts +0 -60
  217. package/dist/core/address.js +0 -142
  218. package/dist/core/address.js.map +0 -1
  219. package/dist/core/cell-store.d.ts +0 -61
  220. package/dist/core/cell-store.js +0 -135
  221. package/dist/core/cell-store.js.map +0 -1
  222. package/dist/core/command/default-registry.d.ts +0 -10
  223. package/dist/core/command/default-registry.js +0 -18
  224. package/dist/core/command/default-registry.js.map +0 -1
  225. package/dist/core/command/history.d.ts +0 -64
  226. package/dist/core/command/history.js +0 -127
  227. package/dist/core/command/history.js.map +0 -1
  228. package/dist/core/command/merge-cells.d.ts +0 -21
  229. package/dist/core/command/merge-cells.js +0 -74
  230. package/dist/core/command/merge-cells.js.map +0 -1
  231. package/dist/core/command/registry.d.ts +0 -17
  232. package/dist/core/command/registry.js +0 -26
  233. package/dist/core/command/registry.js.map +0 -1
  234. package/dist/core/command/set-cell-formula.d.ts +0 -17
  235. package/dist/core/command/set-cell-formula.js +0 -29
  236. package/dist/core/command/set-cell-formula.js.map +0 -1
  237. package/dist/core/command/set-cell-value.d.ts +0 -22
  238. package/dist/core/command/set-cell-value.js +0 -35
  239. package/dist/core/command/set-cell-value.js.map +0 -1
  240. package/dist/core/command/types.d.ts +0 -68
  241. package/dist/core/events.js +0 -29
  242. package/dist/core/events.js.map +0 -1
  243. package/dist/core/fill.d.ts +0 -34
  244. package/dist/core/fill.js +0 -320
  245. package/dist/core/fill.js.map +0 -1
  246. package/dist/core/formula/ast.d.ts +0 -58
  247. package/dist/core/formula/ast.js +0 -38
  248. package/dist/core/formula/ast.js.map +0 -1
  249. package/dist/core/formula/dependency-graph.d.ts +0 -70
  250. package/dist/core/formula/dependency-graph.js +0 -269
  251. package/dist/core/formula/dependency-graph.js.map +0 -1
  252. package/dist/core/formula/errors.d.ts +0 -25
  253. package/dist/core/formula/errors.js +0 -36
  254. package/dist/core/formula/errors.js.map +0 -1
  255. package/dist/core/formula/evaluator.d.ts +0 -41
  256. package/dist/core/formula/evaluator.js +0 -154
  257. package/dist/core/formula/evaluator.js.map +0 -1
  258. package/dist/core/formula/functions.d.ts +0 -30
  259. package/dist/core/formula/functions.js +0 -209
  260. package/dist/core/formula/functions.js.map +0 -1
  261. package/dist/core/formula/parser.d.ts +0 -7
  262. package/dist/core/formula/parser.js +0 -208
  263. package/dist/core/formula/parser.js.map +0 -1
  264. package/dist/core/formula/tokenizer.d.ts +0 -37
  265. package/dist/core/formula/tokenizer.js +0 -146
  266. package/dist/core/formula/tokenizer.js.map +0 -1
  267. package/dist/core/merge-manager.d.ts +0 -64
  268. package/dist/core/merge-manager.js +0 -111
  269. package/dist/core/merge-manager.js.map +0 -1
  270. package/dist/core/selection.d.ts +0 -31
  271. package/dist/core/selection.js +0 -62
  272. package/dist/core/selection.js.map +0 -1
  273. package/dist/core/sheet.d.ts +0 -116
  274. package/dist/core/sheet.js +0 -224
  275. package/dist/core/sheet.js.map +0 -1
  276. package/dist/core/workbook.d.ts +0 -43
  277. package/dist/core/workbook.js +0 -77
  278. package/dist/core/workbook.js.map +0 -1
  279. package/dist/grid/sheet-grid.d.ts +0 -81
  280. package/dist/grid/sheet-grid.js +0 -331
  281. package/dist/grid/sheet-grid.js.map +0 -1
  282. package/dist/grid/vtable-theme.js +0 -80
  283. package/dist/grid/vtable-theme.js.map +0 -1
  284. package/dist/tools/builtin.js.map +0 -1
  285. package/dist/tools/context.js.map +0 -1
  286. package/dist/tools/registry.js.map +0 -1
  287. package/dist/vue/index.d.ts +0 -2
  288. package/dist/vue/sheet.js +0 -211
  289. package/dist/vue/sheet.js.map +0 -1
  290. package/dist/vue/sheet.vue.d.ts +0 -24
  291. package/dist/vue/style.d.ts +0 -1
  292. package/dist/vue/style.js +0 -2
  293. package/dist/vue/style2.css +0 -93
  294. package/src/core/__test__/address.test.ts +0 -113
  295. package/src/core/__test__/cell-store.test.ts +0 -97
  296. package/src/core/__test__/command.test.ts +0 -377
  297. package/src/core/__test__/fill.test.ts +0 -140
  298. package/src/core/__test__/formula-adversarial.test.ts +0 -265
  299. package/src/core/__test__/formula-engine.test.ts +0 -470
  300. package/src/core/__test__/formula-functions.test.ts +0 -178
  301. package/src/core/__test__/formula-parser.test.ts +0 -160
  302. package/src/core/__test__/history.test.ts +0 -225
  303. package/src/core/__test__/merge-manager.test.ts +0 -106
  304. package/src/core/__test__/sheet.test.ts +0 -142
  305. package/src/core/address.ts +0 -166
  306. package/src/core/cell-store.ts +0 -173
  307. package/src/core/command/default-registry.ts +0 -15
  308. package/src/core/command/history.ts +0 -167
  309. package/src/core/command/index.ts +0 -7
  310. package/src/core/command/merge-cells.ts +0 -74
  311. package/src/core/command/registry.ts +0 -30
  312. package/src/core/command/set-cell-formula.ts +0 -29
  313. package/src/core/command/set-cell-value.ts +0 -38
  314. package/src/core/command/types.ts +0 -73
  315. package/src/core/events.ts +0 -37
  316. package/src/core/fill.ts +0 -314
  317. package/src/core/formula/ast.ts +0 -66
  318. package/src/core/formula/dependency-graph.ts +0 -329
  319. package/src/core/formula/errors.ts +0 -41
  320. package/src/core/formula/evaluator.ts +0 -219
  321. package/src/core/formula/functions.ts +0 -266
  322. package/src/core/formula/index.ts +0 -7
  323. package/src/core/formula/parser.ts +0 -198
  324. package/src/core/formula/tokenizer.ts +0 -160
  325. package/src/core/merge-manager.ts +0 -158
  326. package/src/core/selection.ts +0 -66
  327. package/src/core/sheet.ts +0 -282
  328. package/src/core/workbook.ts +0 -99
  329. package/src/grid/__test__/canvas-mock.ts +0 -49
  330. package/src/grid/__test__/setup.ts +0 -3
  331. package/src/grid/__test__/sheet-grid-formula.test.ts +0 -140
  332. package/src/grid/__test__/sheet-grid.test.ts +0 -275
  333. package/src/grid/sheet-grid.ts +0 -407
  334. package/src/grid/vtable-theme.ts +0 -61
  335. package/src/vue/__test__/sheet-component.test.ts +0 -267
  336. package/src/vue/sheet.vue +0 -235
  337. package/src/vue/style.scss +0 -94
  338. package/src/vue/style.ts +0 -2
  339. /package/src/{vue → components/sheet}/index.ts +0 -0
@@ -0,0 +1,733 @@
1
+ import { sameAddress } from "./template-index.js";
2
+ import { cellKey, createRange } from "@veltra/sheet-core";
3
+ //#region src/report/render/coordinate.ts
4
+ function isRowExpanding(binding) {
5
+ return binding.expand === "down" && (binding.aggregate === "group" || binding.aggregate === "list");
6
+ }
7
+ function isColExpanding(binding) {
8
+ return binding.expand === "right" && (binding.aggregate === "group" || binding.aggregate === "list");
9
+ }
10
+ function mergeSpanEnabled(binding) {
11
+ return binding?.mergeSpan !== false;
12
+ }
13
+ function filterRows(rows, filter) {
14
+ if (Object.keys(filter).length === 0) return rows;
15
+ return rows.filter((row) => Object.entries(filter).every(([field, value]) => row[field] === value));
16
+ }
17
+ function distinctFieldValues(rows, field) {
18
+ const seen = /* @__PURE__ */ new Set();
19
+ const values = [];
20
+ for (const row of rows) {
21
+ const key = JSON.stringify(row[field]);
22
+ if (seen.has(key)) continue;
23
+ seen.add(key);
24
+ values.push(row[field]);
25
+ }
26
+ return values;
27
+ }
28
+ function sortValues(values, sort) {
29
+ if (sort === "asc") return [...values].sort((a, b) => String(a).localeCompare(String(b), "zh-CN"));
30
+ if (sort === "desc") return [...values].sort((a, b) => String(b).localeCompare(String(a), "zh-CN"));
31
+ return values;
32
+ }
33
+ function singleCellRange(row, col) {
34
+ return {
35
+ start: {
36
+ row,
37
+ col
38
+ },
39
+ end: {
40
+ row,
41
+ col
42
+ }
43
+ };
44
+ }
45
+ function rangeRows(range) {
46
+ return range.end.row - range.start.row + 1;
47
+ }
48
+ function rangeCols(range) {
49
+ return range.end.col - range.start.col + 1;
50
+ }
51
+ function mergeFilters(rowFilter, colFilter) {
52
+ return {
53
+ ...rowFilter,
54
+ ...colFilter
55
+ };
56
+ }
57
+ function parentFilterForBinding(binding, index, rowFilter, colFilter) {
58
+ const filter = {};
59
+ if (binding.rowParent) {
60
+ const parent = index.bindingAt(binding.rowParent);
61
+ if (parent && parent.dataset === binding.dataset) Object.assign(filter, rowFilter);
62
+ }
63
+ if (binding.colParent) {
64
+ const parent = index.bindingAt(binding.colParent);
65
+ if (parent && parent.dataset === binding.dataset) Object.assign(filter, colFilter);
66
+ }
67
+ return filter;
68
+ }
69
+ /** 枚举扩展格实例 */
70
+ function enumerateExpansionInstances(binding, data, filter) {
71
+ const rows = filterRows(data[binding.dataset] ?? [], filter);
72
+ if (!isRowExpanding(binding) && !isColExpanding(binding)) return [{
73
+ index: 0,
74
+ filter
75
+ }];
76
+ if (binding.aggregate === "group") return sortValues(distinctFieldValues(rows, binding.field), binding.sort).map((value, index) => ({
77
+ index,
78
+ value,
79
+ filter: {
80
+ ...filter,
81
+ [binding.field]: value
82
+ }
83
+ }));
84
+ if (binding.aggregate === "list") return rows.map((_, index) => ({
85
+ index,
86
+ filter
87
+ }));
88
+ return [{
89
+ index: 0,
90
+ filter
91
+ }];
92
+ }
93
+ function isRowSubtreeRoot(binding, index) {
94
+ if (!isRowExpanding(binding)) return false;
95
+ if (!binding.rowParent) return true;
96
+ const parent = index.bindingAt(binding.rowParent);
97
+ return !parent || !isRowExpanding(parent);
98
+ }
99
+ function isColSubtreeRoot(binding, index) {
100
+ if (!isColExpanding(binding)) return false;
101
+ if (!binding.colParent) return true;
102
+ const parent = index.bindingAt(binding.colParent);
103
+ return !parent || !isColExpanding(parent);
104
+ }
105
+ function isNestedRowExpander(binding, index) {
106
+ return isRowExpanding(binding) && binding.aggregate === "group" && !!binding.rowParent && !isRowSubtreeRoot(binding, index);
107
+ }
108
+ function isNestedColExpander(binding, index) {
109
+ return isColExpanding(binding) && binding.aggregate === "group" && !!binding.colParent && !isColSubtreeRoot(binding, index);
110
+ }
111
+ function rowSubtreeRows(rootAddr, index) {
112
+ let maxRow = rootAddr.row;
113
+ const walk = (addr) => {
114
+ maxRow = Math.max(maxRow, addr.row);
115
+ for (const child of index.rowChildren.get(cellKey(addr)) ?? []) walk(child);
116
+ };
117
+ walk(rootAddr);
118
+ return index.logicalRows.filter((row) => row >= rootAddr.row && row <= maxRow);
119
+ }
120
+ function colSubtreeCols(rootAddr, index) {
121
+ let maxCol = rootAddr.col;
122
+ const walk = (addr) => {
123
+ maxCol = Math.max(maxCol, addr.col);
124
+ for (const child of index.colChildren.get(cellKey(addr)) ?? []) walk(child);
125
+ };
126
+ walk(rootAddr);
127
+ return index.logicalCols.filter((col) => col >= rootAddr.col && col <= maxCol);
128
+ }
129
+ function columnsOnRow(index, row) {
130
+ const cols = /* @__PURE__ */ new Set();
131
+ for (const entry of index.bindingsOnRow(row)) cols.add(entry.addr.col);
132
+ for (const cell of index.staticCells.values()) if (cell.row === row) cols.add(cell.col);
133
+ return [...cols].sort((a, b) => a - b);
134
+ }
135
+ function findRowSubtreeRootOnRow(index, row) {
136
+ for (const entry of index.bindingsOnRow(row)) if (isRowSubtreeRoot(entry.binding, index)) return entry.addr;
137
+ return null;
138
+ }
139
+ /** 扩展带终止行:新的纵向子树根,或无父格的汇总行(如总计) */
140
+ function isExpansionBandTerminatorRow(index, row, rootRow) {
141
+ if (row <= rootRow) return false;
142
+ const rowRoot = findRowSubtreeRootOnRow(index, row);
143
+ if (rowRoot && rowRoot.row !== rootRow) return true;
144
+ return !isCompanionRow(index, row);
145
+ }
146
+ /** 扩展带内随行:全部绑定均带 rowParent(纯静态行不算带内行) */
147
+ function isCompanionRow(index, row) {
148
+ const bindings = index.bindingsOnRow(row);
149
+ if (bindings.length === 0) return false;
150
+ return bindings.every(({ binding }) => binding.rowParent !== void 0);
151
+ }
152
+ /** 纵向扩展带覆盖的模板行:子树行 + 紧随其后的带内汇总行 */
153
+ function expansionBandRows(rootAddr, index) {
154
+ const subtreeRows = rowSubtreeRows(rootAddr, index);
155
+ const maxSubtreeRow = Math.max(...subtreeRows);
156
+ const rows = new Set(subtreeRows);
157
+ for (const row of index.logicalRows) {
158
+ if (row <= maxSubtreeRow) continue;
159
+ if (isExpansionBandTerminatorRow(index, row, rootAddr.row)) break;
160
+ if (!isCompanionRow(index, row)) break;
161
+ rows.add(row);
162
+ }
163
+ return index.logicalRows.filter((row) => rows.has(row));
164
+ }
165
+ function findNestedColChild(rootAddr, index) {
166
+ for (const child of index.colChildren.get(cellKey(rootAddr)) ?? []) {
167
+ const binding = index.bindingAt(child);
168
+ if (binding && isColExpanding(binding) && child.row > rootAddr.row) return child;
169
+ }
170
+ return null;
171
+ }
172
+ var CoordinateEngine = class {
173
+ index;
174
+ data;
175
+ constructor(index, data) {
176
+ this.index = index;
177
+ this.data = data;
178
+ }
179
+ compute() {
180
+ const placements = [];
181
+ const consumedRows = /* @__PURE__ */ new Set();
182
+ let physRow = 0;
183
+ let maxCol = 0;
184
+ for (const logicalRow of this.index.logicalRows) {
185
+ if (consumedRows.has(logicalRow)) continue;
186
+ const rowRoot = findRowSubtreeRootOnRow(this.index, logicalRow);
187
+ if (rowRoot) {
188
+ const result = this.layoutRowSubtree(rowRoot, emptyCtx(), physRow, 0);
189
+ placements.push(...result.placements);
190
+ physRow += result.rowSpan;
191
+ maxCol = Math.max(maxCol, result.colSpan);
192
+ for (const row of expansionBandRows(rowRoot, this.index)) consumedRows.add(row);
193
+ continue;
194
+ }
195
+ const result = this.layoutStandaloneRow(logicalRow, emptyCtx(), physRow, 0);
196
+ placements.push(...result.placements);
197
+ physRow += result.rowSpan;
198
+ maxCol = Math.max(maxCol, result.colSpan);
199
+ }
200
+ return {
201
+ rowCount: physRow,
202
+ colCount: Math.max(maxCol, this.baseColCount()),
203
+ placements,
204
+ mappedMerges: mapTemplateMerges(this.index, placements)
205
+ };
206
+ }
207
+ baseColCount() {
208
+ if (this.index.logicalCols.length === 0) return 0;
209
+ return Math.max(...this.index.logicalCols) + 1;
210
+ }
211
+ layoutRowSubtree(rootAddr, ctx, physRowStart, physColStart) {
212
+ const rootBinding = this.index.bindingAt(rootAddr);
213
+ const parentFilter = parentFilterForBinding(rootBinding, this.index, ctx.rowFilter, ctx.colFilter);
214
+ const instances = enumerateExpansionInstances(rootBinding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
215
+ const bandRows = expansionBandRows(rootAddr, this.index);
216
+ if (instances.length === 0) return {
217
+ rowSpan: 0,
218
+ colSpan: 0,
219
+ placements: []
220
+ };
221
+ if (rootBinding.aggregate === "list") {
222
+ const listCtx = {
223
+ rowFilter: mergeFilters(parentFilter, ctx.rowFilter),
224
+ colFilter: ctx.colFilter,
225
+ rowPath: ctx.rowPath,
226
+ colPath: ctx.colPath
227
+ };
228
+ const rowResult = this.layoutTemplateRow(rootAddr.row, listCtx, physRowStart, physColStart, rootAddr, instances.length);
229
+ const placements = [...rowResult.placements];
230
+ let totalRowSpan = instances.length;
231
+ for (const templateRow of bandRows) {
232
+ if (templateRow === rootAddr.row) continue;
233
+ const companionResult = this.layoutTemplateRow(templateRow, listCtx, physRowStart + totalRowSpan, physColStart, null, 1);
234
+ placements.push(...companionResult.placements);
235
+ totalRowSpan += companionResult.rowSpan;
236
+ }
237
+ return {
238
+ rowSpan: totalRowSpan,
239
+ colSpan: rowResult.colSpan,
240
+ placements
241
+ };
242
+ }
243
+ const placements = [];
244
+ let totalRowSpan = 0;
245
+ let maxColSpan = 0;
246
+ for (const instance of instances) {
247
+ const instanceCtx = {
248
+ rowFilter: instance.filter,
249
+ colFilter: ctx.colFilter,
250
+ rowPath: [...ctx.rowPath, instance.index],
251
+ colPath: ctx.colPath
252
+ };
253
+ const instanceHeight = this.measureSubtreeInstanceHeight(bandRows, rootAddr, instanceCtx);
254
+ const groupMergeHeight = this.measureTemplateRowHeight(rootAddr.row, instanceCtx, null);
255
+ if (this.bandHasMultiRowList(bandRows, instanceCtx)) {
256
+ const bandResult = this.layoutMultiRowListBand(bandRows, rootAddr, instanceCtx, physRowStart + totalRowSpan, physColStart, groupMergeHeight);
257
+ placements.push(...bandResult.placements);
258
+ maxColSpan = Math.max(maxColSpan, bandResult.colSpan);
259
+ totalRowSpan += instanceHeight;
260
+ continue;
261
+ }
262
+ let rowOffset = 0;
263
+ for (const templateRow of bandRows) {
264
+ const rowHeight = this.measureTemplateRowHeight(templateRow, instanceCtx, rootAddr);
265
+ const mergeHeight = templateRow === rootAddr.row ? groupMergeHeight : instanceHeight - rowOffset;
266
+ const rowResult = this.layoutTemplateRow(templateRow, instanceCtx, physRowStart + totalRowSpan + rowOffset, physColStart, rootAddr, mergeHeight);
267
+ placements.push(...rowResult.placements);
268
+ rowOffset += rowHeight;
269
+ maxColSpan = Math.max(maxColSpan, rowResult.colSpan);
270
+ }
271
+ totalRowSpan += instanceHeight;
272
+ }
273
+ return {
274
+ rowSpan: totalRowSpan,
275
+ colSpan: maxColSpan,
276
+ placements
277
+ };
278
+ }
279
+ measureSubtreeInstanceHeight(bandRows, rootAddr, ctx) {
280
+ let listDrivenHeight = 0;
281
+ let companionHeight = 0;
282
+ for (const row of bandRows) {
283
+ const listCount = this.listInstanceCountOnRow(row, ctx);
284
+ if (listCount > 0) {
285
+ listDrivenHeight = Math.max(listDrivenHeight, listCount);
286
+ continue;
287
+ }
288
+ if (row === rootAddr.row) continue;
289
+ companionHeight += this.measureTemplateRowHeight(row, ctx, rootAddr);
290
+ }
291
+ if (listDrivenHeight === 0) return this.measureTemplateRowHeight(rootAddr.row, ctx, null);
292
+ return listDrivenHeight + companionHeight;
293
+ }
294
+ bandHasMultiRowList(bandRows, ctx) {
295
+ let count = 0;
296
+ for (const row of bandRows) {
297
+ if (this.listInstanceCountOnRow(row, ctx) > 0) count++;
298
+ if (count > 1) return true;
299
+ }
300
+ return false;
301
+ }
302
+ layoutMultiRowListBand(bandRows, rootAddr, ctx, physRowStart, physColStart, groupMergeHeight) {
303
+ const listRows = bandRows.filter((row) => this.listInstanceCountOnRow(row, ctx) > 0);
304
+ const companionRows = bandRows.filter((row) => !listRows.includes(row));
305
+ const listCount = Math.max(...listRows.map((row) => this.listInstanceCountOnRow(row, ctx)), 1);
306
+ const placements = [];
307
+ let maxColSpan = 0;
308
+ for (let listIndex = 0; listIndex < listCount; listIndex++) for (const templateRow of listRows) {
309
+ const rowResult = this.layoutTemplateRow(templateRow, ctx, physRowStart + listIndex, physColStart, templateRow === rootAddr.row ? rootAddr : null, groupMergeHeight, false, listIndex, listCount);
310
+ placements.push(...rowResult.placements);
311
+ maxColSpan = Math.max(maxColSpan, rowResult.colSpan);
312
+ }
313
+ let rowOffset = listCount;
314
+ for (const templateRow of companionRows) {
315
+ const rowResult = this.layoutTemplateRow(templateRow, ctx, physRowStart + rowOffset, physColStart, null, 1);
316
+ placements.push(...rowResult.placements);
317
+ maxColSpan = Math.max(maxColSpan, rowResult.colSpan);
318
+ rowOffset += rowResult.rowSpan;
319
+ }
320
+ return {
321
+ rowSpan: rowOffset,
322
+ colSpan: maxColSpan,
323
+ placements
324
+ };
325
+ }
326
+ measureTemplateRowHeight(templateRow, ctx, rootAddr) {
327
+ for (const entry of this.index.bindingsOnRow(templateRow)) if (isNestedRowExpander(entry.binding, this.index)) return this.measureNestedRowBandHeight(entry.addr, entry.binding, templateRow, ctx);
328
+ const listCount = this.listInstanceCountOnRow(templateRow, ctx);
329
+ if (listCount > 0) return listCount;
330
+ if (rootAddr && templateRow === rootAddr.row) return 0;
331
+ return 1;
332
+ }
333
+ measureNestedRowBandHeight(groupAddr, groupBinding, templateRow, ctx) {
334
+ const parentFilter = parentFilterForBinding(groupBinding, this.index, ctx.rowFilter, ctx.colFilter);
335
+ const instances = enumerateExpansionInstances(groupBinding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
336
+ if (instances.length === 0) return 0;
337
+ let total = 0;
338
+ for (const instance of instances) {
339
+ const instanceCtx = {
340
+ ...ctx,
341
+ rowFilter: instance.filter,
342
+ rowPath: [...ctx.rowPath, instance.index]
343
+ };
344
+ total += this.listInstanceCountOnRow(templateRow, instanceCtx) || 1;
345
+ }
346
+ return total;
347
+ }
348
+ layoutStandaloneRow(templateRow, ctx, physRowStart, physColStart) {
349
+ return this.layoutTemplateRow(templateRow, ctx, physRowStart, physColStart, null, 1, !this.rowUsesPackedColumns(templateRow));
350
+ }
351
+ rowUsesPackedColumns(templateRow) {
352
+ for (const entry of this.index.bindingsOnRow(templateRow)) {
353
+ if (isColSubtreeRoot(entry.binding, this.index)) return true;
354
+ if (isNestedColExpander(entry.binding, this.index)) return true;
355
+ if (entry.binding.colParent) {
356
+ const parent = this.index.bindingAt(entry.binding.colParent);
357
+ if (parent && isColExpanding(parent)) return true;
358
+ }
359
+ }
360
+ return false;
361
+ }
362
+ layoutTemplateRow(templateRow, ctx, physRowStart, physColStart, rowSubtreeRoot, groupMergeHeight, preserveLogicalCols = false, fixedListIndex, mergeListCount) {
363
+ for (const entry of this.index.bindingsOnRow(templateRow)) if (isNestedRowExpander(entry.binding, this.index)) return this.layoutNestedRowBand(templateRow, entry.addr, entry.binding, ctx, physRowStart, physColStart);
364
+ const cols = columnsOnRow(this.index, templateRow);
365
+ const placements = [];
366
+ let physCol = physColStart;
367
+ const packedCols = !preserveLogicalCols && this.rowUsesPackedColumns(templateRow);
368
+ const listCount = this.listInstanceCountOnRow(templateRow, ctx);
369
+ const rowSpan = fixedListIndex !== void 0 ? 1 : Math.max(listCount, 1);
370
+ const leadingGap = cols.length > 0 && cols[0] > physColStart;
371
+ for (const col of cols) {
372
+ const addr = {
373
+ row: templateRow,
374
+ col
375
+ };
376
+ const binding = this.index.bindingAt(addr);
377
+ const targetCol = packedCols && !leadingGap ? physCol : col;
378
+ if (binding && isColSubtreeRoot(binding, this.index)) {
379
+ const colResult = this.layoutColSubtree(addr, ctx, physRowStart, targetCol);
380
+ placements.push(...colResult.placements);
381
+ if (packedCols) physCol = leadingGap ? targetCol + colResult.colSpan : physCol + colResult.colSpan;
382
+ continue;
383
+ }
384
+ if (binding && isNestedColExpander(binding, this.index)) {
385
+ const colResult = this.layoutNestedColBand(addr, binding, ctx, physRowStart, targetCol);
386
+ placements.push(...colResult.placements);
387
+ if (packedCols) physCol = leadingGap ? targetCol + colResult.colSpan : physCol + colResult.colSpan;
388
+ continue;
389
+ }
390
+ if (binding && this.isInlineColChild(templateRow, col)) continue;
391
+ if (binding && binding.colParent && !isColExpanding(binding)) {
392
+ const colResult = this.layoutColParentAlignedCell(addr, binding, ctx, physRowStart, targetCol, rowSpan);
393
+ placements.push(...colResult.placements);
394
+ if (packedCols) physCol = leadingGap ? targetCol + colResult.colSpan : physCol + colResult.colSpan;
395
+ continue;
396
+ }
397
+ if (binding) {
398
+ const cellResult = this.layoutBindingCell(addr, binding, ctx, physRowStart, targetCol, rowSpan, rowSubtreeRoot, groupMergeHeight, fixedListIndex, mergeListCount);
399
+ placements.push(...cellResult.placements);
400
+ if (packedCols) physCol = leadingGap ? targetCol + cellResult.colSpan : physCol + cellResult.colSpan;
401
+ continue;
402
+ }
403
+ if (this.index.cellAt(addr)) {
404
+ if (rowSpan > 1) for (let i = 0; i < rowSpan; i++) placements.push(this.makePlacement(addr, singleCellRange(physRowStart + i, targetCol), ctx, void 0, i, false));
405
+ else placements.push(this.makePlacement(addr, singleCellRange(physRowStart, targetCol), ctx, void 0, 0, false));
406
+ if (packedCols) physCol = leadingGap ? targetCol + 1 : physCol + 1;
407
+ }
408
+ }
409
+ const effectiveColSpan = packedCols ? leadingGap && cols.length > 0 ? Math.max(...cols) + 1 - physColStart : physCol - physColStart : cols.length > 0 ? Math.max(...cols) + 1 - physColStart : 0;
410
+ return {
411
+ rowSpan: rowSubtreeRoot && templateRow === rowSubtreeRoot.row && listCount === 0 ? 0 : rowSpan,
412
+ colSpan: effectiveColSpan,
413
+ placements
414
+ };
415
+ }
416
+ layoutNestedRowBand(templateRow, groupAddr, groupBinding, ctx, physRowStart, physColStart) {
417
+ const parentFilter = parentFilterForBinding(groupBinding, this.index, ctx.rowFilter, ctx.colFilter);
418
+ const instances = enumerateExpansionInstances(groupBinding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
419
+ if (instances.length === 0) return {
420
+ rowSpan: 0,
421
+ colSpan: 0,
422
+ placements: []
423
+ };
424
+ const placements = [];
425
+ let rowOffset = 0;
426
+ let maxColSpan = 0;
427
+ const colOffsets = this.rowLogicalColOffsets(templateRow, physColStart);
428
+ for (const instance of instances) {
429
+ const instanceCtx = {
430
+ ...ctx,
431
+ rowFilter: instance.filter,
432
+ rowPath: [...ctx.rowPath, instance.index]
433
+ };
434
+ const detailCount = this.listInstanceCountOnRow(templateRow, instanceCtx) || 1;
435
+ if (mergeSpanEnabled(groupBinding)) placements.push(this.makePlacement(groupAddr, createRange({
436
+ row: physRowStart + rowOffset,
437
+ col: physColStart
438
+ }, {
439
+ row: physRowStart + rowOffset + detailCount - 1,
440
+ col: physColStart
441
+ }), instanceCtx, groupBinding, 0, true));
442
+ else for (let i = 0; i < detailCount; i++) placements.push(this.makePlacement(groupAddr, singleCellRange(physRowStart + rowOffset + i, physColStart), instanceCtx, groupBinding, i, false));
443
+ for (const entry of this.index.bindingsOnRow(templateRow)) {
444
+ if (sameAddress(entry.addr, groupAddr)) continue;
445
+ if (!isRowExpanding(entry.binding) || entry.binding.aggregate !== "list") continue;
446
+ for (let i = 0; i < detailCount; i++) placements.push(this.makePlacement(entry.addr, singleCellRange(physRowStart + rowOffset + i, colOffsets.get(entry.addr.col)), instanceCtx, entry.binding, i, false));
447
+ }
448
+ for (const col of columnsOnRow(this.index, templateRow)) {
449
+ if (this.index.bindingAt({
450
+ row: templateRow,
451
+ col
452
+ })) continue;
453
+ if (!this.index.cellAt({
454
+ row: templateRow,
455
+ col
456
+ })) continue;
457
+ for (let i = 0; i < detailCount; i++) placements.push(this.makePlacement({
458
+ row: templateRow,
459
+ col
460
+ }, singleCellRange(physRowStart + rowOffset + i, colOffsets.get(col)), instanceCtx, void 0, i, false));
461
+ }
462
+ maxColSpan = Math.max(maxColSpan, colOffsets.size);
463
+ rowOffset += detailCount;
464
+ }
465
+ return {
466
+ rowSpan: rowOffset,
467
+ colSpan: maxColSpan,
468
+ placements
469
+ };
470
+ }
471
+ layoutBindingCell(addr, binding, ctx, physRowStart, physColStart, rowSpan, rowSubtreeRoot, groupMergeHeight, fixedListIndex, mergeListCount) {
472
+ if (rowSubtreeRoot && isRowExpanding(binding) && binding.aggregate === "group" && sameAddress(addr, rowSubtreeRoot)) {
473
+ if (fixedListIndex !== void 0 && fixedListIndex > 0) return {
474
+ rowSpan: 0,
475
+ colSpan: 1,
476
+ placements: []
477
+ };
478
+ const mergeRows = Math.max(fixedListIndex !== void 0 ? mergeListCount ?? groupMergeHeight : groupMergeHeight, 1);
479
+ if (!mergeSpanEnabled(binding)) return {
480
+ rowSpan: 0,
481
+ colSpan: 1,
482
+ placements: Array.from({ length: mergeRows }, (_, listIndex) => this.makePlacement(addr, singleCellRange(physRowStart + listIndex, physColStart), ctx, binding, listIndex, false))
483
+ };
484
+ const range = createRange({
485
+ row: physRowStart,
486
+ col: physColStart
487
+ }, {
488
+ row: physRowStart + mergeRows - 1,
489
+ col: physColStart
490
+ });
491
+ return {
492
+ rowSpan: 0,
493
+ colSpan: 1,
494
+ placements: [this.makePlacement(addr, range, ctx, binding, 0, true)]
495
+ };
496
+ }
497
+ if (isRowExpanding(binding) && binding.aggregate === "list") {
498
+ if (fixedListIndex !== void 0) return {
499
+ rowSpan: 0,
500
+ colSpan: 1,
501
+ placements: [this.makePlacement(addr, singleCellRange(physRowStart, physColStart), ctx, binding, fixedListIndex, false)]
502
+ };
503
+ return {
504
+ rowSpan: 0,
505
+ colSpan: 1,
506
+ placements: Array.from({ length: rowSpan }, (_, listIndex) => this.makePlacement(addr, singleCellRange(physRowStart + listIndex, physColStart), ctx, binding, listIndex, false))
507
+ };
508
+ }
509
+ return {
510
+ rowSpan: 0,
511
+ colSpan: 1,
512
+ placements: [this.makePlacement(addr, expandRows(singleCellRange(physRowStart, physColStart), rowSpan), ctx, binding, 0, mergeSpanEnabled(binding) && rowSpan > 1)]
513
+ };
514
+ }
515
+ layoutColSubtree(rootAddr, ctx, physRowStart, physColStart) {
516
+ const rootBinding = this.index.bindingAt(rootAddr);
517
+ const parentFilter = parentFilterForBinding(rootBinding, this.index, ctx.rowFilter, ctx.colFilter);
518
+ const instances = enumerateExpansionInstances(rootBinding, this.data, mergeFilters(parentFilter, ctx.colFilter));
519
+ if (instances.length === 0) return {
520
+ rowSpan: 0,
521
+ colSpan: 0,
522
+ placements: []
523
+ };
524
+ const placements = [];
525
+ let totalColSpan = 0;
526
+ for (const instance of instances) {
527
+ const instanceCtx = {
528
+ rowFilter: ctx.rowFilter,
529
+ colFilter: instance.filter,
530
+ rowPath: ctx.rowPath,
531
+ colPath: [...ctx.colPath, instance.index]
532
+ };
533
+ const width = this.colInstanceWidth(rootAddr, instanceCtx);
534
+ const range = createRange({
535
+ row: physRowStart,
536
+ col: physColStart + totalColSpan
537
+ }, {
538
+ row: physRowStart,
539
+ col: physColStart + totalColSpan + width - 1
540
+ });
541
+ placements.push(this.makePlacement(rootAddr, range, instanceCtx, rootBinding, rootBinding.aggregate === "list" ? instance.index : 0, mergeSpanEnabled(rootBinding)));
542
+ totalColSpan += width;
543
+ }
544
+ return {
545
+ rowSpan: 1,
546
+ colSpan: totalColSpan,
547
+ placements
548
+ };
549
+ }
550
+ layoutNestedColBand(addr, binding, ctx, physRowStart, physColStart) {
551
+ const parentAddr = binding.colParent;
552
+ const parentBinding = this.index.bindingAt(parentAddr);
553
+ const parentFilter = parentFilterForBinding(parentBinding, this.index, ctx.rowFilter, ctx.colFilter);
554
+ const parentInstances = enumerateExpansionInstances(parentBinding, this.data, mergeFilters(parentFilter, ctx.colFilter));
555
+ const placements = [];
556
+ let colOffset = 0;
557
+ for (const parentInstance of parentInstances) {
558
+ const bandCtx = {
559
+ ...ctx,
560
+ colFilter: parentInstance.filter,
561
+ colPath: [...ctx.colPath, parentInstance.index]
562
+ };
563
+ const childFilter = parentFilterForBinding(binding, this.index, bandCtx.rowFilter, bandCtx.colFilter);
564
+ const childInstances = enumerateExpansionInstances(binding, this.data, mergeFilters(childFilter, bandCtx.colFilter));
565
+ for (const childInstance of childInstances) {
566
+ const childCtx = {
567
+ ...bandCtx,
568
+ colFilter: childInstance.filter,
569
+ colPath: [...bandCtx.colPath, childInstance.index]
570
+ };
571
+ placements.push(this.makePlacement(addr, singleCellRange(physRowStart, physColStart + colOffset), childCtx, binding, 0, false));
572
+ colOffset++;
573
+ }
574
+ }
575
+ return {
576
+ rowSpan: 1,
577
+ colSpan: colOffset,
578
+ placements
579
+ };
580
+ }
581
+ colInstanceWidth(rootAddr, ctx) {
582
+ const nestedChild = findNestedColChild(rootAddr, this.index);
583
+ if (nestedChild) {
584
+ const binding = this.index.bindingAt(nestedChild);
585
+ const parentFilter = parentFilterForBinding(binding, this.index, ctx.rowFilter, ctx.colFilter);
586
+ const instances = enumerateExpansionInstances(binding, this.data, mergeFilters(parentFilter, ctx.colFilter));
587
+ return Math.max(instances.length, 1);
588
+ }
589
+ if (!mergeSpanEnabled(this.index.bindingAt(rootAddr))) return 1;
590
+ let width = 0;
591
+ for (const col of colSubtreeCols(rootAddr, this.index)) {
592
+ if (col <= rootAddr.col) continue;
593
+ if (this.index.bindingAt({
594
+ row: rootAddr.row,
595
+ col
596
+ }) || this.index.cellAt({
597
+ row: rootAddr.row,
598
+ col
599
+ })) width++;
600
+ }
601
+ return Math.max(width, 1);
602
+ }
603
+ layoutColParentAlignedCell(addr, binding, ctx, physRowStart, physColStart, rowSpan) {
604
+ const colParent = binding.colParent;
605
+ const parentBinding = this.index.bindingAt(colParent);
606
+ const parentFilter = parentFilterForBinding(parentBinding, this.index, ctx.rowFilter, ctx.colFilter);
607
+ const instances = enumerateExpansionInstances(parentBinding, this.data, mergeFilters(parentFilter, ctx.colFilter));
608
+ if (instances.length === 0) return {
609
+ rowSpan: 0,
610
+ colSpan: 0,
611
+ placements: []
612
+ };
613
+ const placements = [];
614
+ let colOffset = 0;
615
+ for (const instance of instances) {
616
+ const instanceCtx = {
617
+ rowFilter: ctx.rowFilter,
618
+ colFilter: instance.filter,
619
+ rowPath: ctx.rowPath,
620
+ colPath: [...ctx.colPath, instance.index]
621
+ };
622
+ const width = this.colInstanceWidth(colParent, instanceCtx);
623
+ placements.push(this.makePlacement(addr, expandRows(singleCellRange(physRowStart, physColStart + colOffset), rowSpan), instanceCtx, binding, 0, mergeSpanEnabled(binding) && rowSpan > 1));
624
+ colOffset += width;
625
+ }
626
+ return {
627
+ rowSpan: 0,
628
+ colSpan: colOffset,
629
+ placements
630
+ };
631
+ }
632
+ isInlineColChild(row, col) {
633
+ const binding = this.index.bindingAt({
634
+ row,
635
+ col
636
+ });
637
+ if (!binding?.colParent) return false;
638
+ const parent = this.index.bindingAt(binding.colParent);
639
+ if (!parent || !isColExpanding(parent)) return false;
640
+ return binding.colParent.row === row;
641
+ }
642
+ listInstanceCountOnRow(templateRow, ctx) {
643
+ let count = 0;
644
+ for (const entry of this.index.bindingsOnRow(templateRow)) {
645
+ if (!isRowExpanding(entry.binding) || entry.binding.aggregate !== "list") continue;
646
+ const parentFilter = parentFilterForBinding(entry.binding, this.index, ctx.rowFilter, ctx.colFilter);
647
+ const instances = enumerateExpansionInstances(entry.binding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
648
+ count = Math.max(count, instances.length);
649
+ }
650
+ return count;
651
+ }
652
+ rowLogicalColOffsets(templateRow, physColStart) {
653
+ const offsets = /* @__PURE__ */ new Map();
654
+ let physCol = physColStart;
655
+ for (const col of columnsOnRow(this.index, templateRow)) {
656
+ offsets.set(col, physCol);
657
+ physCol++;
658
+ }
659
+ return offsets;
660
+ }
661
+ makePlacement(logical, physical, ctx, binding, listIndex, mergeSpan) {
662
+ return {
663
+ logical,
664
+ physical,
665
+ rowPath: ctx.rowPath,
666
+ colPath: ctx.colPath,
667
+ mergeSpan,
668
+ binding,
669
+ listIndex
670
+ };
671
+ }
672
+ };
673
+ function emptyCtx() {
674
+ return {
675
+ rowFilter: {},
676
+ colFilter: {},
677
+ rowPath: [],
678
+ colPath: []
679
+ };
680
+ }
681
+ function expandRows(range, rowSpan) {
682
+ if (rowSpan <= 1) return range;
683
+ return createRange(range.start, {
684
+ row: range.start.row + rowSpan - 1,
685
+ col: range.end.col
686
+ });
687
+ }
688
+ /** 将模板合并区域映射到物理网格(基于锚点格的物理落点) */
689
+ function mapTemplateMerges(index, placements) {
690
+ const layout = {
691
+ rowCount: 0,
692
+ colCount: 0,
693
+ placements,
694
+ mappedMerges: []
695
+ };
696
+ const mapped = [];
697
+ for (const merge of index.merges) {
698
+ const mappedRange = mapLogicalMerge(merge, layout);
699
+ if (mappedRange) mapped.push(mappedRange);
700
+ }
701
+ return mapped;
702
+ }
703
+ function mapLogicalMerge(merge, layout) {
704
+ const startHits = placementsAt(layout, merge.start);
705
+ if (startHits.length === 0) return null;
706
+ const startPlacement = startHits[0];
707
+ const endHits = placementsAt(layout, merge.end);
708
+ if (endHits.length > 0) return createRange(startPlacement.physical.start, endHits[endHits.length - 1].physical.end);
709
+ const logicalRowSpan = merge.end.row - merge.start.row;
710
+ const logicalColSpan = merge.end.col - merge.start.col;
711
+ return createRange(startPlacement.physical.start, {
712
+ row: startPlacement.physical.start.row + logicalRowSpan,
713
+ col: startPlacement.physical.start.col + logicalColSpan
714
+ });
715
+ }
716
+ /** 计算扩展坐标系:逻辑格 → 物理区间映射(纯计算、无快照输出) */
717
+ function computeExpansionLayout(index, data) {
718
+ return new CoordinateEngine(index, data).compute();
719
+ }
720
+ /** 按逻辑地址查找全部物理落点 */
721
+ function placementsAt(layout, addr) {
722
+ return layout.placements.filter((p) => sameAddress(p.logical, addr));
723
+ }
724
+ /** 物理区间行高(含合并) */
725
+ function physicalRowSpan(placement) {
726
+ return rangeRows(placement.physical);
727
+ }
728
+ /** 物理区间列宽(含合并) */
729
+ function physicalColSpan(placement) {
730
+ return rangeCols(placement.physical);
731
+ }
732
+ //#endregion
733
+ export { computeExpansionLayout, enumerateExpansionInstances, mapTemplateMerges, physicalColSpan, physicalRowSpan, placementsAt };