@veltra/sheet 2.0.0 → 2.1.1

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 (203) hide show
  1. package/dist/index.d.ts +4 -25
  2. package/dist/index.js +3 -22
  3. package/dist/tools/builtin.js +279 -8
  4. package/dist/tools/context.d.ts +54 -11
  5. package/dist/tools/context.js +28 -5
  6. package/dist/tools/download.js +68 -0
  7. package/dist/tools/export.worker.d.ts +16 -0
  8. package/dist/tools/export.worker.js +29 -0
  9. package/dist/tools/registry.d.ts +7 -4
  10. package/dist/tools/registry.js +1 -3
  11. package/dist/types/index.d.ts +1 -0
  12. package/dist/types/sheet.d.ts +6 -5
  13. package/dist/vue/formula-bar.js +393 -0
  14. package/dist/vue/formula-suggest-list.js +66 -0
  15. package/dist/vue/import-file.js +140 -0
  16. package/dist/vue/insert-count-menu-item.js +68 -0
  17. package/dist/vue/insert-image.js +79 -0
  18. package/dist/vue/popup-helpers.js +73 -0
  19. package/dist/vue/popups/border-popup.js +75 -0
  20. package/dist/vue/popups/border-preset-glyph.js +106 -0
  21. package/dist/vue/popups/export-popup.js +51 -0
  22. package/dist/vue/popups/fill-color-popup.js +37 -0
  23. package/dist/vue/popups/find-popup.js +113 -0
  24. package/dist/vue/popups/font-color-popup.js +37 -0
  25. package/dist/vue/popups/font-size-popup.js +63 -0
  26. package/dist/vue/popups/import.worker.d.ts +21 -0
  27. package/dist/vue/popups/import.worker.js +41 -0
  28. package/dist/vue/popups/insert-image-popup.js +38 -0
  29. package/dist/vue/sheet-context-menu.js +200 -0
  30. package/dist/vue/sheet-tabs.js +162 -0
  31. package/dist/vue/sheet-toolbar.js +106 -0
  32. package/dist/vue/sheet.js +144 -138
  33. package/dist/vue/style.d.ts +11 -1
  34. package/dist/vue/style.js +11 -0
  35. package/dist/vue/style2.css +564 -3
  36. package/dist/vue/use-find-replace.js +161 -0
  37. package/dist/vue/use-formula-ref-select.js +37 -0
  38. package/dist/vue/use-formula-suggest.js +126 -0
  39. package/dist/vue/use-sheet-grid.js +180 -0
  40. package/dist/vue/use-sheet-state.js +122 -0
  41. package/dist/vue/use-sheet-tabs-bar.js +90 -0
  42. package/dist/vue/use-tool-groups.js +42 -0
  43. package/dist/vue/use-tool-popup.js +123 -0
  44. package/dist/vue/use-toolbar-scroll.js +72 -0
  45. package/package.json +12 -6
  46. package/src/env.d.ts +14 -0
  47. package/src/index.ts +203 -13
  48. package/src/tools/__test__/builtin.test.ts +208 -66
  49. package/src/tools/__test__/context.test.ts +62 -2
  50. package/src/tools/builtin.ts +350 -6
  51. package/src/tools/context.ts +89 -11
  52. package/src/tools/download.ts +82 -0
  53. package/src/tools/export.worker.ts +61 -0
  54. package/src/tools/registry.ts +16 -1
  55. package/src/types/index.ts +6 -0
  56. package/src/types/sheet.ts +5 -3
  57. package/src/vue/__test__/formula-bar.test.ts +455 -0
  58. package/src/vue/__test__/import-file.test.ts +183 -0
  59. package/src/vue/__test__/insert-count-menu-item.test.ts +123 -0
  60. package/src/vue/__test__/insert-image-popup.test.ts +89 -0
  61. package/src/vue/__test__/insert-image.test.ts +100 -0
  62. package/src/vue/__test__/sheet-component.test.ts +716 -27
  63. package/src/vue/__test__/sheet-context-menu.test.ts +206 -0
  64. package/src/vue/__test__/use-formula-ref-select.test.ts +35 -0
  65. package/src/vue/__test__/use-formula-suggest.test.ts +83 -0
  66. package/src/vue/formula-bar.vue +473 -0
  67. package/src/vue/formula-suggest-list.vue +64 -0
  68. package/src/vue/import-file.ts +173 -0
  69. package/src/vue/insert-count-menu-item.vue +69 -0
  70. package/src/vue/insert-image.ts +90 -0
  71. package/src/vue/parsing.ts +11 -0
  72. package/src/vue/popup-helpers.ts +50 -0
  73. package/src/vue/popups/border-popup.vue +93 -0
  74. package/src/vue/popups/border-preset-glyph.vue +111 -0
  75. package/src/vue/popups/export-popup.vue +52 -0
  76. package/src/vue/popups/fill-color-popup.vue +39 -0
  77. package/src/vue/popups/find-popup.vue +111 -0
  78. package/src/vue/popups/font-color-popup.vue +39 -0
  79. package/src/vue/popups/font-size-popup.vue +52 -0
  80. package/src/vue/popups/import.worker.ts +66 -0
  81. package/src/vue/popups/insert-image-popup.vue +39 -0
  82. package/src/vue/sheet-context-menu.ts +229 -0
  83. package/src/vue/sheet-tabs.vue +162 -0
  84. package/src/vue/sheet-toolbar.vue +91 -0
  85. package/src/vue/sheet.vue +163 -148
  86. package/src/vue/style.scss +646 -3
  87. package/src/vue/style.ts +12 -0
  88. package/src/vue/use-find-replace.ts +200 -0
  89. package/src/vue/use-formula-ref-select.ts +34 -0
  90. package/src/vue/use-formula-suggest.ts +150 -0
  91. package/src/vue/use-sheet-grid.ts +243 -0
  92. package/src/vue/use-sheet-state.ts +161 -0
  93. package/src/vue/use-sheet-tabs-bar.ts +115 -0
  94. package/src/vue/use-tool-groups.ts +61 -0
  95. package/src/vue/use-tool-popup.ts +150 -0
  96. package/src/vue/use-toolbar-scroll.ts +95 -0
  97. package/dist/core/address.d.ts +0 -60
  98. package/dist/core/address.js +0 -142
  99. package/dist/core/address.js.map +0 -1
  100. package/dist/core/cell-store.d.ts +0 -61
  101. package/dist/core/cell-store.js +0 -135
  102. package/dist/core/cell-store.js.map +0 -1
  103. package/dist/core/command/default-registry.d.ts +0 -10
  104. package/dist/core/command/default-registry.js +0 -18
  105. package/dist/core/command/default-registry.js.map +0 -1
  106. package/dist/core/command/history.d.ts +0 -64
  107. package/dist/core/command/history.js +0 -127
  108. package/dist/core/command/history.js.map +0 -1
  109. package/dist/core/command/merge-cells.d.ts +0 -21
  110. package/dist/core/command/merge-cells.js +0 -74
  111. package/dist/core/command/merge-cells.js.map +0 -1
  112. package/dist/core/command/registry.d.ts +0 -17
  113. package/dist/core/command/registry.js +0 -26
  114. package/dist/core/command/registry.js.map +0 -1
  115. package/dist/core/command/set-cell-formula.d.ts +0 -17
  116. package/dist/core/command/set-cell-formula.js +0 -29
  117. package/dist/core/command/set-cell-formula.js.map +0 -1
  118. package/dist/core/command/set-cell-value.d.ts +0 -22
  119. package/dist/core/command/set-cell-value.js +0 -35
  120. package/dist/core/command/set-cell-value.js.map +0 -1
  121. package/dist/core/command/types.d.ts +0 -68
  122. package/dist/core/events.js +0 -29
  123. package/dist/core/events.js.map +0 -1
  124. package/dist/core/formula/ast.d.ts +0 -58
  125. package/dist/core/formula/ast.js +0 -38
  126. package/dist/core/formula/ast.js.map +0 -1
  127. package/dist/core/formula/dependency-graph.d.ts +0 -70
  128. package/dist/core/formula/dependency-graph.js +0 -269
  129. package/dist/core/formula/dependency-graph.js.map +0 -1
  130. package/dist/core/formula/errors.d.ts +0 -25
  131. package/dist/core/formula/errors.js +0 -36
  132. package/dist/core/formula/errors.js.map +0 -1
  133. package/dist/core/formula/evaluator.d.ts +0 -41
  134. package/dist/core/formula/evaluator.js +0 -154
  135. package/dist/core/formula/evaluator.js.map +0 -1
  136. package/dist/core/formula/functions.d.ts +0 -30
  137. package/dist/core/formula/functions.js +0 -209
  138. package/dist/core/formula/functions.js.map +0 -1
  139. package/dist/core/formula/parser.d.ts +0 -7
  140. package/dist/core/formula/parser.js +0 -208
  141. package/dist/core/formula/parser.js.map +0 -1
  142. package/dist/core/formula/tokenizer.d.ts +0 -37
  143. package/dist/core/formula/tokenizer.js +0 -146
  144. package/dist/core/formula/tokenizer.js.map +0 -1
  145. package/dist/core/merge-manager.d.ts +0 -64
  146. package/dist/core/merge-manager.js +0 -111
  147. package/dist/core/merge-manager.js.map +0 -1
  148. package/dist/core/selection.d.ts +0 -31
  149. package/dist/core/selection.js +0 -62
  150. package/dist/core/selection.js.map +0 -1
  151. package/dist/core/sheet.d.ts +0 -105
  152. package/dist/core/sheet.js +0 -202
  153. package/dist/core/sheet.js.map +0 -1
  154. package/dist/core/workbook.d.ts +0 -43
  155. package/dist/core/workbook.js +0 -77
  156. package/dist/core/workbook.js.map +0 -1
  157. package/dist/grid/sheet-grid.d.ts +0 -59
  158. package/dist/grid/sheet-grid.js +0 -230
  159. package/dist/grid/sheet-grid.js.map +0 -1
  160. package/dist/tools/builtin.js.map +0 -1
  161. package/dist/tools/context.js.map +0 -1
  162. package/dist/tools/registry.js.map +0 -1
  163. package/dist/vue/index.d.ts +0 -2
  164. package/dist/vue/sheet.js.map +0 -1
  165. package/dist/vue/sheet.vue.d.ts +0 -24
  166. package/src/core/__test__/address.test.ts +0 -113
  167. package/src/core/__test__/cell-store.test.ts +0 -97
  168. package/src/core/__test__/command.test.ts +0 -377
  169. package/src/core/__test__/formula-adversarial.test.ts +0 -265
  170. package/src/core/__test__/formula-engine.test.ts +0 -470
  171. package/src/core/__test__/formula-functions.test.ts +0 -178
  172. package/src/core/__test__/formula-parser.test.ts +0 -160
  173. package/src/core/__test__/history.test.ts +0 -225
  174. package/src/core/__test__/merge-manager.test.ts +0 -106
  175. package/src/core/__test__/sheet.test.ts +0 -142
  176. package/src/core/address.ts +0 -166
  177. package/src/core/cell-store.ts +0 -173
  178. package/src/core/command/default-registry.ts +0 -15
  179. package/src/core/command/history.ts +0 -167
  180. package/src/core/command/index.ts +0 -7
  181. package/src/core/command/merge-cells.ts +0 -74
  182. package/src/core/command/registry.ts +0 -30
  183. package/src/core/command/set-cell-formula.ts +0 -29
  184. package/src/core/command/set-cell-value.ts +0 -38
  185. package/src/core/command/types.ts +0 -73
  186. package/src/core/events.ts +0 -37
  187. package/src/core/formula/ast.ts +0 -66
  188. package/src/core/formula/dependency-graph.ts +0 -329
  189. package/src/core/formula/errors.ts +0 -41
  190. package/src/core/formula/evaluator.ts +0 -219
  191. package/src/core/formula/functions.ts +0 -266
  192. package/src/core/formula/index.ts +0 -7
  193. package/src/core/formula/parser.ts +0 -198
  194. package/src/core/formula/tokenizer.ts +0 -160
  195. package/src/core/merge-manager.ts +0 -158
  196. package/src/core/selection.ts +0 -66
  197. package/src/core/sheet.ts +0 -257
  198. package/src/core/workbook.ts +0 -99
  199. package/src/grid/__test__/canvas-mock.ts +0 -49
  200. package/src/grid/__test__/setup.ts +0 -3
  201. package/src/grid/__test__/sheet-grid-formula.test.ts +0 -140
  202. package/src/grid/__test__/sheet-grid.test.ts +0 -177
  203. package/src/grid/sheet-grid.ts +0 -283
@@ -1,142 +0,0 @@
1
- //#region src/core/address.ts
2
- /**
3
- * cellKey 的列基数(2^20)。
4
- * key = row * COL_KEY_BASE + col,要求 col < COL_KEY_BASE;
5
- * JS 安全整数范围内可容纳约 8.5e9 行,远超实际使用。
6
- */
7
- const COL_KEY_BASE = 2 ** 20;
8
- /** 地址 → 数值 key(Map 索引用) */
9
- function cellKey(addr) {
10
- return addr.row * COL_KEY_BASE + addr.col;
11
- }
12
- /** 数值 key → 地址 */
13
- function addressFromKey(key) {
14
- return {
15
- row: Math.floor(key / COL_KEY_BASE),
16
- col: key % COL_KEY_BASE
17
- };
18
- }
19
- /** 列号(0-based)→ 列名:0 → 'A',25 → 'Z',26 → 'AA' */
20
- function colIndexToName(col) {
21
- if (!Number.isInteger(col) || col < 0) throw new RangeError(`列号必须是非负整数: ${col}`);
22
- let name = "";
23
- let n = col;
24
- do {
25
- name = String.fromCharCode(65 + n % 26) + name;
26
- n = Math.floor(n / 26) - 1;
27
- } while (n >= 0);
28
- return name;
29
- }
30
- /** 列名 → 列号(0-based):'A' → 0,'AA' → 26;非法列名返回 -1 */
31
- function colNameToIndex(name) {
32
- if (!/^[A-Za-z]+$/.test(name)) return -1;
33
- let index = 0;
34
- for (const ch of name.toUpperCase()) index = index * 26 + (ch.charCodeAt(0) - 64);
35
- return index - 1;
36
- }
37
- const ADDRESS_RE = /^\$?([A-Za-z]+)\$?([1-9]\d*)$/;
38
- /** 解析 A1 记法(兼容 `$A$1` 绝对引用写法)→ 地址;非法返回 null */
39
- function parseAddress(text) {
40
- const match = ADDRESS_RE.exec(text.trim());
41
- if (!match) return null;
42
- const col = colNameToIndex(match[1]);
43
- return {
44
- row: Number.parseInt(match[2], 10) - 1,
45
- col
46
- };
47
- }
48
- /** 地址 → A1 记法:{ row: 1, col: 1 } → 'B2' */
49
- function formatAddress(addr) {
50
- return `${colIndexToName(addr.col)}${addr.row + 1}`;
51
- }
52
- /** 由两个角点构造规范化区域(start ≤ end) */
53
- function createRange(a, b) {
54
- return {
55
- start: {
56
- row: Math.min(a.row, b.row),
57
- col: Math.min(a.col, b.col)
58
- },
59
- end: {
60
- row: Math.max(a.row, b.row),
61
- col: Math.max(a.col, b.col)
62
- }
63
- };
64
- }
65
- /** 解析区域记法:'B2' 或 'B2:D5'(兼容绝对引用);非法返回 null */
66
- function parseRange(text) {
67
- const parts = text.trim().split(":");
68
- if (parts.length > 2) return null;
69
- const start = parseAddress(parts[0]);
70
- if (!start) return null;
71
- if (parts.length === 1) return {
72
- start,
73
- end: { ...start }
74
- };
75
- const end = parseAddress(parts[1]);
76
- if (!end) return null;
77
- return createRange(start, end);
78
- }
79
- /** 区域 → 记法:单格 → 'B2',多格 → 'B2:D5' */
80
- function formatRange(range) {
81
- const start = formatAddress(range.start);
82
- if (range.start.row === range.end.row && range.start.col === range.end.col) return start;
83
- return `${start}:${formatAddress(range.end)}`;
84
- }
85
- /** 地址相等 */
86
- function addressesEqual(a, b) {
87
- return a.row === b.row && a.col === b.col;
88
- }
89
- /** 区域相等 */
90
- function rangesEqual(a, b) {
91
- return addressesEqual(a.start, b.start) && addressesEqual(a.end, b.end);
92
- }
93
- /** 两区域是否相交 */
94
- function rangesIntersect(a, b) {
95
- return a.start.row <= b.end.row && a.end.row >= b.start.row && a.start.col <= b.end.col && a.end.col >= b.start.col;
96
- }
97
- /** 区域是否包含地址 */
98
- function rangeContainsAddress(range, addr) {
99
- return addr.row >= range.start.row && addr.row <= range.end.row && addr.col >= range.start.col && addr.col <= range.end.col;
100
- }
101
- /** 区域是否完整包含另一区域 */
102
- function rangeContainsRange(outer, inner) {
103
- return rangeContainsAddress(outer, inner.start) && rangeContainsAddress(outer, inner.end);
104
- }
105
- /** 一组区域的最小包围盒(至少传入一个区域) */
106
- function boundingBox(ranges) {
107
- let minRow = Infinity;
108
- let minCol = Infinity;
109
- let maxRow = -Infinity;
110
- let maxCol = -Infinity;
111
- for (const range of ranges) {
112
- minRow = Math.min(minRow, range.start.row);
113
- minCol = Math.min(minCol, range.start.col);
114
- maxRow = Math.max(maxRow, range.end.row);
115
- maxCol = Math.max(maxCol, range.end.col);
116
- }
117
- return {
118
- start: {
119
- row: minRow,
120
- col: minCol
121
- },
122
- end: {
123
- row: maxRow,
124
- col: maxCol
125
- }
126
- };
127
- }
128
- /** 按行主序遍历区域内的所有地址 */
129
- function* iterateRange(range) {
130
- for (let row = range.start.row; row <= range.end.row; row++) for (let col = range.start.col; col <= range.end.col; col++) yield {
131
- row,
132
- col
133
- };
134
- }
135
- /** 区域内的单元格数量 */
136
- function rangeSize(range) {
137
- return (range.end.row - range.start.row + 1) * (range.end.col - range.start.col + 1);
138
- }
139
- //#endregion
140
- export { COL_KEY_BASE, addressFromKey, addressesEqual, boundingBox, cellKey, colIndexToName, colNameToIndex, createRange, formatAddress, formatRange, iterateRange, parseAddress, parseRange, rangeContainsAddress, rangeContainsRange, rangeSize, rangesEqual, rangesIntersect };
141
-
142
- //# sourceMappingURL=address.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"address.js","names":[],"sources":["../../src/core/address.ts"],"sourcesContent":["/**\n * A1 地址系统(纯函数)。\n *\n * 坐标统一 0-based:`{ row: 0, col: 0 }` 即 A1。\n * 区域为闭区间,且经过规范化:start 恒为左上角,end 恒为右下角。\n */\n\n/** 单元格地址(0-based) */\nexport interface CellAddress {\n row: number\n col: number\n}\n\n/** 单元格区域(闭区间,start 左上角,end 右下角) */\nexport interface CellRange {\n start: CellAddress\n end: CellAddress\n}\n\n/**\n * cellKey 的列基数(2^20)。\n * key = row * COL_KEY_BASE + col,要求 col < COL_KEY_BASE;\n * JS 安全整数范围内可容纳约 8.5e9 行,远超实际使用。\n */\nexport const COL_KEY_BASE = 2 ** 20\n\n/** 地址 → 数值 key(Map 索引用) */\nexport function cellKey(addr: CellAddress): number {\n return addr.row * COL_KEY_BASE + addr.col\n}\n\n/** 数值 key → 地址 */\nexport function addressFromKey(key: number): CellAddress {\n return { row: Math.floor(key / COL_KEY_BASE), col: key % COL_KEY_BASE }\n}\n\n/** 列号(0-based)→ 列名:0 → 'A',25 → 'Z',26 → 'AA' */\nexport function colIndexToName(col: number): string {\n if (!Number.isInteger(col) || col < 0) {\n throw new RangeError(`列号必须是非负整数: ${col}`)\n }\n let name = ''\n let n = col\n do {\n name = String.fromCharCode(65 + (n % 26)) + name\n n = Math.floor(n / 26) - 1\n } while (n >= 0)\n return name\n}\n\n/** 列名 → 列号(0-based):'A' → 0,'AA' → 26;非法列名返回 -1 */\nexport function colNameToIndex(name: string): number {\n if (!/^[A-Za-z]+$/.test(name)) return -1\n let index = 0\n for (const ch of name.toUpperCase()) {\n index = index * 26 + (ch.charCodeAt(0) - 64)\n }\n return index - 1\n}\n\nconst ADDRESS_RE = /^\\$?([A-Za-z]+)\\$?([1-9]\\d*)$/\n\n/** 解析 A1 记法(兼容 `$A$1` 绝对引用写法)→ 地址;非法返回 null */\nexport function parseAddress(text: string): CellAddress | null {\n const match = ADDRESS_RE.exec(text.trim())\n if (!match) return null\n const col = colNameToIndex(match[1]!)\n const row = Number.parseInt(match[2]!, 10) - 1\n return { row, col }\n}\n\n/** 地址 → A1 记法:{ row: 1, col: 1 } → 'B2' */\nexport function formatAddress(addr: CellAddress): string {\n return `${colIndexToName(addr.col)}${addr.row + 1}`\n}\n\n/** 由两个角点构造规范化区域(start ≤ end) */\nexport function createRange(a: CellAddress, b: CellAddress): CellRange {\n return {\n start: { row: Math.min(a.row, b.row), col: Math.min(a.col, b.col) },\n end: { row: Math.max(a.row, b.row), col: Math.max(a.col, b.col) }\n }\n}\n\n/** 解析区域记法:'B2' 或 'B2:D5'(兼容绝对引用);非法返回 null */\nexport function parseRange(text: string): CellRange | null {\n const parts = text.trim().split(':')\n if (parts.length > 2) return null\n const start = parseAddress(parts[0]!)\n if (!start) return null\n if (parts.length === 1) return { start, end: { ...start } }\n const end = parseAddress(parts[1]!)\n if (!end) return null\n return createRange(start, end)\n}\n\n/** 区域 → 记法:单格 → 'B2',多格 → 'B2:D5' */\nexport function formatRange(range: CellRange): string {\n const start = formatAddress(range.start)\n if (range.start.row === range.end.row && range.start.col === range.end.col) return start\n return `${start}:${formatAddress(range.end)}`\n}\n\n/** 地址相等 */\nexport function addressesEqual(a: CellAddress, b: CellAddress): boolean {\n return a.row === b.row && a.col === b.col\n}\n\n/** 区域相等 */\nexport function rangesEqual(a: CellRange, b: CellRange): boolean {\n return addressesEqual(a.start, b.start) && addressesEqual(a.end, b.end)\n}\n\n/** 两区域是否相交 */\nexport function rangesIntersect(a: CellRange, b: CellRange): boolean {\n return (\n a.start.row <= b.end.row &&\n a.end.row >= b.start.row &&\n a.start.col <= b.end.col &&\n a.end.col >= b.start.col\n )\n}\n\n/** 区域是否包含地址 */\nexport function rangeContainsAddress(range: CellRange, addr: CellAddress): boolean {\n return (\n addr.row >= range.start.row &&\n addr.row <= range.end.row &&\n addr.col >= range.start.col &&\n addr.col <= range.end.col\n )\n}\n\n/** 区域是否完整包含另一区域 */\nexport function rangeContainsRange(outer: CellRange, inner: CellRange): boolean {\n return rangeContainsAddress(outer, inner.start) && rangeContainsAddress(outer, inner.end)\n}\n\n/** 一组区域的最小包围盒(至少传入一个区域) */\nexport function boundingBox(ranges: readonly [CellRange, ...CellRange[]]): CellRange {\n let minRow = Infinity\n let minCol = Infinity\n let maxRow = -Infinity\n let maxCol = -Infinity\n for (const range of ranges) {\n minRow = Math.min(minRow, range.start.row)\n minCol = Math.min(minCol, range.start.col)\n maxRow = Math.max(maxRow, range.end.row)\n maxCol = Math.max(maxCol, range.end.col)\n }\n return { start: { row: minRow, col: minCol }, end: { row: maxRow, col: maxCol } }\n}\n\n/** 按行主序遍历区域内的所有地址 */\nexport function* iterateRange(range: CellRange): Generator<CellAddress, void, undefined> {\n for (let row = range.start.row; row <= range.end.row; row++) {\n for (let col = range.start.col; col <= range.end.col; col++) {\n yield { row, col }\n }\n }\n}\n\n/** 区域内的单元格数量 */\nexport function rangeSize(range: CellRange): number {\n return (range.end.row - range.start.row + 1) * (range.end.col - range.start.col + 1)\n}\n"],"mappings":"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"}
@@ -1,61 +0,0 @@
1
- import { CellAddress, CellRange } from "./address.js";
2
- //#region src/core/cell-store.d.ts
3
- /**
4
- * 稀疏矩阵存储:`Map<row, Map<col, CellData>>`。
5
- * 空单元格 = 存储中不存在该 key(稀疏的第一原则);
6
- * rowCount/colCount 只是高水位,用于渲染行数,不分配空间。
7
- */
8
- /** 单元格值类型:n=数字 s=字符串 b=布尔 str=公式结果字符串 e=错误 d=日期(序列数) */
9
- type CellType = 'n' | 's' | 'b' | 'str' | 'e' | 'd';
10
- /** 单元格原始值 */
11
- type CellValue = string | number | boolean | null;
12
- /** 单元格数据(参考 univer ICellData 裁剪版) */
13
- interface CellData {
14
- /** 原始值(公式格为计算缓存值) */
15
- v?: CellValue;
16
- /** 值类型,缺省按 v 推断 */
17
- t?: CellType;
18
- /** 公式文本(不含 '='),如 'SUM(A1:B2)+Sheet2!C3' */
19
- f?: string;
20
- }
21
- /** 序列化条目(snapshot/restore 用) */
22
- interface CellSnapshotItem extends CellData {
23
- row: number;
24
- col: number;
25
- }
26
- /** 按原始值推断类型 */
27
- declare function inferCellType(v: CellValue): CellType | undefined;
28
- /** 判定为空:无公式且值为 null/undefined/'' */
29
- declare function isEmptyCellData(data: CellData | undefined): boolean;
30
- /** CellData 相等(v/t/f 三字段逐一比较;命令系统据此跳过无实际变更的补丁) */
31
- declare function cellDataEqual(a: CellData | undefined, b: CellData | undefined): boolean;
32
- declare class CellStore {
33
- private cells;
34
- private _rowCount;
35
- private _colCount;
36
- /** 行数高水位(只增不减,restore 时重算) */
37
- get rowCount(): number;
38
- /** 列数高水位 */
39
- get colCount(): number;
40
- /** 真实存在的单元格数量 */
41
- get size(): number;
42
- /** 读取(返回副本,外部修改不影响存储) */
43
- getCell(addr: CellAddress): CellData | undefined;
44
- /** 写入(存储副本);空数据等价于删除 */
45
- setCell(addr: CellAddress, data?: CellData): void;
46
- /** 便捷写入原始值,类型自动推断;空值等价于删除 */
47
- setCellValue(addr: CellAddress, value: CellValue): void;
48
- deleteCell(addr: CellAddress): boolean;
49
- /** 只遍历真实存在的单元格(行主序) */
50
- entries(): Generator<[CellAddress, CellData], void, undefined>;
51
- /** 只遍历区域内真实存在的单元格(行主序;公式区域展开用,空行/空格不分配不访问) */
52
- entriesInRange(range: CellRange): Generator<[CellAddress, CellData], void, undefined>;
53
- /** 序列化(只含真实存在的格) */
54
- snapshot(): CellSnapshotItem[];
55
- /** 从序列化恢复(清空重建,重算高水位) */
56
- restore(items: readonly CellSnapshotItem[]): void;
57
- clear(): void;
58
- }
59
- //#endregion
60
- export { CellData, CellSnapshotItem, CellStore, CellType, CellValue, cellDataEqual, inferCellType, isEmptyCellData };
61
- //# sourceMappingURL=cell-store.d.ts.map
@@ -1,135 +0,0 @@
1
- //#region src/core/cell-store.ts
2
- /** 按原始值推断类型 */
3
- function inferCellType(v) {
4
- switch (typeof v) {
5
- case "number": return "n";
6
- case "boolean": return "b";
7
- case "string": return "s";
8
- default: return;
9
- }
10
- }
11
- /** 判定为空:无公式且值为 null/undefined/'' */
12
- function isEmptyCellData(data) {
13
- if (!data) return true;
14
- if (data.f != null && data.f !== "") return false;
15
- return data.v == null || data.v === "";
16
- }
17
- /** CellData 相等(v/t/f 三字段逐一比较;命令系统据此跳过无实际变更的补丁) */
18
- function cellDataEqual(a, b) {
19
- if (a === b) return true;
20
- if (!a || !b) return false;
21
- return a.v === b.v && a.t === b.t && a.f === b.f;
22
- }
23
- var CellStore = class {
24
- cells = /* @__PURE__ */ new Map();
25
- _rowCount = 0;
26
- _colCount = 0;
27
- /** 行数高水位(只增不减,restore 时重算) */
28
- get rowCount() {
29
- return this._rowCount;
30
- }
31
- /** 列数高水位 */
32
- get colCount() {
33
- return this._colCount;
34
- }
35
- /** 真实存在的单元格数量 */
36
- get size() {
37
- let size = 0;
38
- for (const rowMap of this.cells.values()) size += rowMap.size;
39
- return size;
40
- }
41
- /** 读取(返回副本,外部修改不影响存储) */
42
- getCell(addr) {
43
- const data = this.cells.get(addr.row)?.get(addr.col);
44
- return data ? { ...data } : void 0;
45
- }
46
- /** 写入(存储副本);空数据等价于删除 */
47
- setCell(addr, data) {
48
- if (isEmptyCellData(data)) {
49
- this.deleteCell(addr);
50
- return;
51
- }
52
- let rowMap = this.cells.get(addr.row);
53
- if (!rowMap) {
54
- rowMap = /* @__PURE__ */ new Map();
55
- this.cells.set(addr.row, rowMap);
56
- }
57
- rowMap.set(addr.col, { ...data });
58
- this._rowCount = Math.max(this._rowCount, addr.row + 1);
59
- this._colCount = Math.max(this._colCount, addr.col + 1);
60
- }
61
- /** 便捷写入原始值,类型自动推断;空值等价于删除 */
62
- setCellValue(addr, value) {
63
- if (value == null || value === "") {
64
- this.deleteCell(addr);
65
- return;
66
- }
67
- this.setCell(addr, {
68
- v: value,
69
- t: inferCellType(value)
70
- });
71
- }
72
- deleteCell(addr) {
73
- const rowMap = this.cells.get(addr.row);
74
- if (!rowMap) return false;
75
- const deleted = rowMap.delete(addr.col);
76
- if (rowMap.size === 0) this.cells.delete(addr.row);
77
- return deleted;
78
- }
79
- /** 只遍历真实存在的单元格(行主序) */
80
- *entries() {
81
- for (const [row, rowMap] of this.cells) for (const [col, data] of rowMap) yield [{
82
- row,
83
- col
84
- }, { ...data }];
85
- }
86
- /** 只遍历区域内真实存在的单元格(行主序;公式区域展开用,空行/空格不分配不访问) */
87
- *entriesInRange(range) {
88
- for (let row = range.start.row; row <= range.end.row; row++) {
89
- const rowMap = this.cells.get(row);
90
- if (!rowMap) continue;
91
- for (let col = range.start.col; col <= range.end.col; col++) {
92
- const data = rowMap.get(col);
93
- if (data) yield [{
94
- row,
95
- col
96
- }, { ...data }];
97
- }
98
- }
99
- }
100
- /** 序列化(只含真实存在的格) */
101
- snapshot() {
102
- const items = [];
103
- for (const [addr, data] of this.entries()) items.push({
104
- row: addr.row,
105
- col: addr.col,
106
- ...data
107
- });
108
- return items;
109
- }
110
- /** 从序列化恢复(清空重建,重算高水位) */
111
- restore(items) {
112
- this.clear();
113
- for (const item of items) {
114
- const { row, col, ...data } = item;
115
- if (isEmptyCellData(data)) continue;
116
- let rowMap = this.cells.get(row);
117
- if (!rowMap) {
118
- rowMap = /* @__PURE__ */ new Map();
119
- this.cells.set(row, rowMap);
120
- }
121
- rowMap.set(col, { ...data });
122
- this._rowCount = Math.max(this._rowCount, row + 1);
123
- this._colCount = Math.max(this._colCount, col + 1);
124
- }
125
- }
126
- clear() {
127
- this.cells.clear();
128
- this._rowCount = 0;
129
- this._colCount = 0;
130
- }
131
- };
132
- //#endregion
133
- export { CellStore, cellDataEqual, inferCellType, isEmptyCellData };
134
-
135
- //# sourceMappingURL=cell-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cell-store.js","names":[],"sources":["../../src/core/cell-store.ts"],"sourcesContent":["import type { CellAddress, CellRange } from './address'\n\n/**\n * 稀疏矩阵存储:`Map<row, Map<col, CellData>>`。\n * 空单元格 = 存储中不存在该 key(稀疏的第一原则);\n * rowCount/colCount 只是高水位,用于渲染行数,不分配空间。\n */\n\n/** 单元格值类型:n=数字 s=字符串 b=布尔 str=公式结果字符串 e=错误 d=日期(序列数) */\nexport type CellType = 'n' | 's' | 'b' | 'str' | 'e' | 'd'\n\n/** 单元格原始值 */\nexport type CellValue = string | number | boolean | null\n\n/** 单元格数据(参考 univer ICellData 裁剪版) */\nexport interface CellData {\n /** 原始值(公式格为计算缓存值) */\n v?: CellValue\n /** 值类型,缺省按 v 推断 */\n t?: CellType\n /** 公式文本(不含 '='),如 'SUM(A1:B2)+Sheet2!C3' */\n f?: string\n // s?: StyleId —— 预留样式位,本期不实现\n}\n\n/** 序列化条目(snapshot/restore 用) */\nexport interface CellSnapshotItem extends CellData {\n row: number\n col: number\n}\n\n/** 按原始值推断类型 */\nexport function inferCellType(v: CellValue): CellType | undefined {\n switch (typeof v) {\n case 'number':\n return 'n'\n case 'boolean':\n return 'b'\n case 'string':\n return 's'\n default:\n return undefined\n }\n}\n\n/** 判定为空:无公式且值为 null/undefined/'' */\nexport function isEmptyCellData(data: CellData | undefined): boolean {\n if (!data) return true\n if (data.f != null && data.f !== '') return false\n return data.v == null || data.v === ''\n}\n\n/** CellData 相等(v/t/f 三字段逐一比较;命令系统据此跳过无实际变更的补丁) */\nexport function cellDataEqual(a: CellData | undefined, b: CellData | undefined): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return a.v === b.v && a.t === b.t && a.f === b.f\n}\n\nexport class CellStore {\n private cells = new Map<number, Map<number, CellData>>()\n private _rowCount = 0\n private _colCount = 0\n\n /** 行数高水位(只增不减,restore 时重算) */\n get rowCount(): number {\n return this._rowCount\n }\n\n /** 列数高水位 */\n get colCount(): number {\n return this._colCount\n }\n\n /** 真实存在的单元格数量 */\n get size(): number {\n let size = 0\n for (const rowMap of this.cells.values()) size += rowMap.size\n return size\n }\n\n /** 读取(返回副本,外部修改不影响存储) */\n getCell(addr: CellAddress): CellData | undefined {\n const data = this.cells.get(addr.row)?.get(addr.col)\n return data ? { ...data } : undefined\n }\n\n /** 写入(存储副本);空数据等价于删除 */\n setCell(addr: CellAddress, data?: CellData): void {\n if (isEmptyCellData(data)) {\n this.deleteCell(addr)\n return\n }\n let rowMap = this.cells.get(addr.row)\n if (!rowMap) {\n rowMap = new Map()\n this.cells.set(addr.row, rowMap)\n }\n rowMap.set(addr.col, { ...data })\n this._rowCount = Math.max(this._rowCount, addr.row + 1)\n this._colCount = Math.max(this._colCount, addr.col + 1)\n }\n\n /** 便捷写入原始值,类型自动推断;空值等价于删除 */\n setCellValue(addr: CellAddress, value: CellValue): void {\n if (value == null || value === '') {\n this.deleteCell(addr)\n return\n }\n this.setCell(addr, { v: value, t: inferCellType(value) })\n }\n\n deleteCell(addr: CellAddress): boolean {\n const rowMap = this.cells.get(addr.row)\n if (!rowMap) return false\n const deleted = rowMap.delete(addr.col)\n if (rowMap.size === 0) this.cells.delete(addr.row)\n return deleted\n }\n\n /** 只遍历真实存在的单元格(行主序) */\n *entries(): Generator<[CellAddress, CellData], void, undefined> {\n for (const [row, rowMap] of this.cells) {\n for (const [col, data] of rowMap) {\n yield [{ row, col }, { ...data }]\n }\n }\n }\n\n /** 只遍历区域内真实存在的单元格(行主序;公式区域展开用,空行/空格不分配不访问) */\n *entriesInRange(range: CellRange): Generator<[CellAddress, CellData], void, undefined> {\n for (let row = range.start.row; row <= range.end.row; row++) {\n const rowMap = this.cells.get(row)\n if (!rowMap) continue\n for (let col = range.start.col; col <= range.end.col; col++) {\n const data = rowMap.get(col)\n if (data) yield [{ row, col }, { ...data }]\n }\n }\n }\n\n /** 序列化(只含真实存在的格) */\n snapshot(): CellSnapshotItem[] {\n const items: CellSnapshotItem[] = []\n for (const [addr, data] of this.entries()) {\n items.push({ row: addr.row, col: addr.col, ...data })\n }\n return items\n }\n\n /** 从序列化恢复(清空重建,重算高水位) */\n restore(items: readonly CellSnapshotItem[]): void {\n this.clear()\n for (const item of items) {\n const { row, col, ...data } = item\n if (isEmptyCellData(data)) continue\n let rowMap = this.cells.get(row)\n if (!rowMap) {\n rowMap = new Map()\n this.cells.set(row, rowMap)\n }\n rowMap.set(col, { ...data })\n this._rowCount = Math.max(this._rowCount, row + 1)\n this._colCount = Math.max(this._colCount, col + 1)\n }\n }\n\n clear(): void {\n this.cells.clear()\n this._rowCount = 0\n this._colCount = 0\n }\n}\n"],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- import { CommandRegistry } from "./registry.js";
2
- //#region src/core/command/default-registry.d.ts
3
- /**
4
- * 默认命令注册表:内置命令模块加载时注册一次,全局共享(命令无状态)。
5
- * Sheet 默认经此表执行命令;阶段 4 工具扩展可继续注册自定义命令。
6
- */
7
- declare const defaultCommandRegistry: CommandRegistry;
8
- //#endregion
9
- export { defaultCommandRegistry };
10
- //# sourceMappingURL=default-registry.d.ts.map
@@ -1,18 +0,0 @@
1
- import { MergeCellsCommand, UnmergeCellsCommand } from "./merge-cells.js";
2
- import { CommandRegistry } from "./registry.js";
3
- import { SetCellFormulaCommand } from "./set-cell-formula.js";
4
- import { SetCellValueCommand } from "./set-cell-value.js";
5
- //#region src/core/command/default-registry.ts
6
- /**
7
- * 默认命令注册表:内置命令模块加载时注册一次,全局共享(命令无状态)。
8
- * Sheet 默认经此表执行命令;阶段 4 工具扩展可继续注册自定义命令。
9
- */
10
- const defaultCommandRegistry = new CommandRegistry();
11
- defaultCommandRegistry.register(SetCellValueCommand);
12
- defaultCommandRegistry.register(SetCellFormulaCommand);
13
- defaultCommandRegistry.register(MergeCellsCommand);
14
- defaultCommandRegistry.register(UnmergeCellsCommand);
15
- //#endregion
16
- export { defaultCommandRegistry };
17
-
18
- //# sourceMappingURL=default-registry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"default-registry.js","names":[],"sources":["../../../src/core/command/default-registry.ts"],"sourcesContent":["import { MergeCellsCommand, UnmergeCellsCommand } from './merge-cells'\nimport { CommandRegistry } from './registry'\nimport { SetCellFormulaCommand } from './set-cell-formula'\nimport { SetCellValueCommand } from './set-cell-value'\n\n/**\n * 默认命令注册表:内置命令模块加载时注册一次,全局共享(命令无状态)。\n * Sheet 默认经此表执行命令;阶段 4 工具扩展可继续注册自定义命令。\n */\nexport const defaultCommandRegistry = new CommandRegistry()\n\ndefaultCommandRegistry.register(SetCellValueCommand)\ndefaultCommandRegistry.register(SetCellFormulaCommand)\ndefaultCommandRegistry.register(MergeCellsCommand)\ndefaultCommandRegistry.register(UnmergeCellsCommand)\n"],"mappings":";;;;;;;;;AASA,MAAa,yBAAyB,IAAI,gBAAgB;AAE1D,uBAAuB,SAAS,mBAAmB;AACnD,uBAAuB,SAAS,qBAAqB;AACrD,uBAAuB,SAAS,iBAAiB;AACjD,uBAAuB,SAAS,mBAAmB"}
@@ -1,64 +0,0 @@
1
- import { Mutation, Patch, PatchDirection } from "./types.js";
2
- //#region src/core/command/history.d.ts
3
- /**
4
- * HistoryManager:undo/redo 栈 + 事务。
5
- *
6
- * - 一个 undo 单元 = 一次命令(或一次事务)的全部 Mutation
7
- * - 事务:beginTransaction / commit,支持嵌套(深度计数,拍平到最外层);
8
- * rollback 回滚缓冲区中已应用的变更并放弃事务
9
- * - 容量上限(默认 200):超出淘汰最旧条目
10
- * - 新命令入栈即清空 redo 栈
11
- */
12
- /** 历史栈容量默认值 */
13
- declare const DEFAULT_HISTORY_CAPACITY = 200;
14
- /** 历史状态(history-change 事件负载) */
15
- interface HistoryState {
16
- canUndo: boolean;
17
- canRedo: boolean;
18
- }
19
- declare class HistoryManager {
20
- /** 补丁应用器(由 Sheet 注入,命令执行与回放共用) */
21
- private readonly applyPatch;
22
- private readonly capacity;
23
- private undoStack;
24
- private redoStack;
25
- /** 事务深度(>0 表示事务进行中) */
26
- private transactionDepth;
27
- /** 事务缓冲:commit 时合并为一个 undo 单元 */
28
- private transactionBuffer;
29
- private emitter;
30
- constructor(
31
- /** 补丁应用器(由 Sheet 注入,命令执行与回放共用) */
32
- applyPatch: (patch: Patch, direction: PatchDirection) => void, capacity?: number);
33
- get canUndo(): boolean;
34
- get canRedo(): boolean;
35
- /** undo 栈深度(调试/测试用) */
36
- get undoSize(): number;
37
- /** redo 栈深度(调试/测试用) */
38
- get redoSize(): number;
39
- /** 是否处于事务中 */
40
- get inTransaction(): boolean;
41
- /** 命令执行产生的 mutation 入栈(事务中则缓冲);空列表直接忽略 */
42
- push(mutations: Mutation[]): void;
43
- /** 开启事务(可嵌套,拍平到最外层) */
44
- beginTransaction(): void;
45
- /** 提交事务:缓冲的 mutation 合并为一个 undo 单元入栈 */
46
- commit(): void;
47
- /**
48
- * 回滚事务:逆序应用缓冲区中各 mutation 的 undo 补丁还原模型,
49
- * 丢弃缓冲并结束事务(含嵌套);不动 undo/redo 栈。
50
- */
51
- rollback(): void;
52
- /** 撤销一个单元;事务进行中或栈空时返回 false */
53
- undo(): boolean;
54
- /** 重做一个单元;事务进行中或栈空时返回 false */
55
- redo(): boolean;
56
- /** 清空全部历史(含事务缓冲) */
57
- clear(): void;
58
- onChange(handler: (state: HistoryState) => void): () => void;
59
- private pushEntry;
60
- private emitChange;
61
- }
62
- //#endregion
63
- export { DEFAULT_HISTORY_CAPACITY, HistoryManager, HistoryState };
64
- //# sourceMappingURL=history.d.ts.map
@@ -1,127 +0,0 @@
1
- import { TypedEventEmitter } from "../events.js";
2
- //#region src/core/command/history.ts
3
- /**
4
- * HistoryManager:undo/redo 栈 + 事务。
5
- *
6
- * - 一个 undo 单元 = 一次命令(或一次事务)的全部 Mutation
7
- * - 事务:beginTransaction / commit,支持嵌套(深度计数,拍平到最外层);
8
- * rollback 回滚缓冲区中已应用的变更并放弃事务
9
- * - 容量上限(默认 200):超出淘汰最旧条目
10
- * - 新命令入栈即清空 redo 栈
11
- */
12
- /** 历史栈容量默认值 */
13
- const DEFAULT_HISTORY_CAPACITY = 200;
14
- var HistoryManager = class {
15
- applyPatch;
16
- capacity;
17
- undoStack = [];
18
- redoStack = [];
19
- /** 事务深度(>0 表示事务进行中) */
20
- transactionDepth = 0;
21
- /** 事务缓冲:commit 时合并为一个 undo 单元 */
22
- transactionBuffer = [];
23
- emitter = new TypedEventEmitter();
24
- constructor(applyPatch, capacity = 200) {
25
- this.applyPatch = applyPatch;
26
- this.capacity = capacity;
27
- }
28
- get canUndo() {
29
- return this.undoStack.length > 0;
30
- }
31
- get canRedo() {
32
- return this.redoStack.length > 0;
33
- }
34
- /** undo 栈深度(调试/测试用) */
35
- get undoSize() {
36
- return this.undoStack.length;
37
- }
38
- /** redo 栈深度(调试/测试用) */
39
- get redoSize() {
40
- return this.redoStack.length;
41
- }
42
- /** 是否处于事务中 */
43
- get inTransaction() {
44
- return this.transactionDepth > 0;
45
- }
46
- /** 命令执行产生的 mutation 入栈(事务中则缓冲);空列表直接忽略 */
47
- push(mutations) {
48
- if (mutations.length === 0) return;
49
- if (this.transactionDepth > 0) {
50
- this.transactionBuffer.push(...mutations);
51
- return;
52
- }
53
- this.pushEntry(mutations);
54
- }
55
- /** 开启事务(可嵌套,拍平到最外层) */
56
- beginTransaction() {
57
- this.transactionDepth++;
58
- }
59
- /** 提交事务:缓冲的 mutation 合并为一个 undo 单元入栈 */
60
- commit() {
61
- if (this.transactionDepth === 0) throw new Error("HistoryManager.commit:没有进行中的事务");
62
- this.transactionDepth--;
63
- if (this.transactionDepth === 0 && this.transactionBuffer.length > 0) {
64
- const entry = this.transactionBuffer;
65
- this.transactionBuffer = [];
66
- this.pushEntry(entry);
67
- }
68
- }
69
- /**
70
- * 回滚事务:逆序应用缓冲区中各 mutation 的 undo 补丁还原模型,
71
- * 丢弃缓冲并结束事务(含嵌套);不动 undo/redo 栈。
72
- */
73
- rollback() {
74
- if (this.transactionDepth === 0) return;
75
- const buffer = this.transactionBuffer;
76
- this.transactionBuffer = [];
77
- this.transactionDepth = 0;
78
- for (let i = buffer.length - 1; i >= 0; i--) for (const patch of buffer[i].undo) this.applyPatch(patch, "undo");
79
- }
80
- /** 撤销一个单元;事务进行中或栈空时返回 false */
81
- undo() {
82
- if (this.transactionDepth > 0) return false;
83
- const entry = this.undoStack.pop();
84
- if (!entry) return false;
85
- for (let i = entry.length - 1; i >= 0; i--) for (const patch of entry[i].undo) this.applyPatch(patch, "undo");
86
- this.redoStack.push(entry);
87
- this.emitChange();
88
- return true;
89
- }
90
- /** 重做一个单元;事务进行中或栈空时返回 false */
91
- redo() {
92
- if (this.transactionDepth > 0) return false;
93
- const entry = this.redoStack.pop();
94
- if (!entry) return false;
95
- for (const mutation of entry) for (const patch of mutation.redo) this.applyPatch(patch, "redo");
96
- this.undoStack.push(entry);
97
- this.emitChange();
98
- return true;
99
- }
100
- /** 清空全部历史(含事务缓冲) */
101
- clear() {
102
- this.undoStack = [];
103
- this.redoStack = [];
104
- this.transactionBuffer = [];
105
- this.transactionDepth = 0;
106
- this.emitChange();
107
- }
108
- onChange(handler) {
109
- return this.emitter.on("change", handler);
110
- }
111
- pushEntry(entry) {
112
- this.undoStack.push(entry);
113
- if (this.undoStack.length > this.capacity) this.undoStack.shift();
114
- this.redoStack = [];
115
- this.emitChange();
116
- }
117
- emitChange() {
118
- this.emitter.emit("change", {
119
- canUndo: this.canUndo,
120
- canRedo: this.canRedo
121
- });
122
- }
123
- };
124
- //#endregion
125
- export { DEFAULT_HISTORY_CAPACITY, HistoryManager };
126
-
127
- //# sourceMappingURL=history.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"history.js","names":[],"sources":["../../../src/core/command/history.ts"],"sourcesContent":["import { TypedEventEmitter } from '../events'\nimport type { Mutation, Patch, PatchDirection } from './types'\n\n/**\n * HistoryManager:undo/redo 栈 + 事务。\n *\n * - 一个 undo 单元 = 一次命令(或一次事务)的全部 Mutation\n * - 事务:beginTransaction / commit,支持嵌套(深度计数,拍平到最外层);\n * rollback 回滚缓冲区中已应用的变更并放弃事务\n * - 容量上限(默认 200):超出淘汰最旧条目\n * - 新命令入栈即清空 redo 栈\n */\n\n/** 历史栈容量默认值 */\nexport const DEFAULT_HISTORY_CAPACITY = 200\n\n/** 历史状态(history-change 事件负载) */\nexport interface HistoryState {\n canUndo: boolean\n canRedo: boolean\n}\n\ntype HistoryEvents = { change: HistoryState }\n\n/** 一个 undo 单元 = 一组 Mutation */\ntype HistoryEntry = Mutation[]\n\nexport class HistoryManager {\n private undoStack: HistoryEntry[] = []\n private redoStack: HistoryEntry[] = []\n /** 事务深度(>0 表示事务进行中) */\n private transactionDepth = 0\n /** 事务缓冲:commit 时合并为一个 undo 单元 */\n private transactionBuffer: Mutation[] = []\n private emitter = new TypedEventEmitter<HistoryEvents>()\n\n constructor(\n /** 补丁应用器(由 Sheet 注入,命令执行与回放共用) */\n private readonly applyPatch: (patch: Patch, direction: PatchDirection) => void,\n private readonly capacity: number = DEFAULT_HISTORY_CAPACITY\n ) {}\n\n get canUndo(): boolean {\n return this.undoStack.length > 0\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0\n }\n\n /** undo 栈深度(调试/测试用) */\n get undoSize(): number {\n return this.undoStack.length\n }\n\n /** redo 栈深度(调试/测试用) */\n get redoSize(): number {\n return this.redoStack.length\n }\n\n /** 是否处于事务中 */\n get inTransaction(): boolean {\n return this.transactionDepth > 0\n }\n\n /** 命令执行产生的 mutation 入栈(事务中则缓冲);空列表直接忽略 */\n push(mutations: Mutation[]): void {\n if (mutations.length === 0) return\n if (this.transactionDepth > 0) {\n this.transactionBuffer.push(...mutations)\n return\n }\n this.pushEntry(mutations)\n }\n\n /** 开启事务(可嵌套,拍平到最外层) */\n beginTransaction(): void {\n this.transactionDepth++\n }\n\n /** 提交事务:缓冲的 mutation 合并为一个 undo 单元入栈 */\n commit(): void {\n if (this.transactionDepth === 0) {\n throw new Error('HistoryManager.commit:没有进行中的事务')\n }\n this.transactionDepth--\n if (this.transactionDepth === 0 && this.transactionBuffer.length > 0) {\n const entry = this.transactionBuffer\n this.transactionBuffer = []\n this.pushEntry(entry)\n }\n }\n\n /**\n * 回滚事务:逆序应用缓冲区中各 mutation 的 undo 补丁还原模型,\n * 丢弃缓冲并结束事务(含嵌套);不动 undo/redo 栈。\n */\n rollback(): void {\n if (this.transactionDepth === 0) return\n const buffer = this.transactionBuffer\n this.transactionBuffer = []\n this.transactionDepth = 0\n for (let i = buffer.length - 1; i >= 0; i--) {\n for (const patch of buffer[i]!.undo) {\n this.applyPatch(patch, 'undo')\n }\n }\n }\n\n /** 撤销一个单元;事务进行中或栈空时返回 false */\n undo(): boolean {\n if (this.transactionDepth > 0) return false\n const entry = this.undoStack.pop()\n if (!entry) return false\n for (let i = entry.length - 1; i >= 0; i--) {\n for (const patch of entry[i]!.undo) {\n this.applyPatch(patch, 'undo')\n }\n }\n this.redoStack.push(entry)\n this.emitChange()\n return true\n }\n\n /** 重做一个单元;事务进行中或栈空时返回 false */\n redo(): boolean {\n if (this.transactionDepth > 0) return false\n const entry = this.redoStack.pop()\n if (!entry) return false\n for (const mutation of entry) {\n for (const patch of mutation.redo) {\n this.applyPatch(patch, 'redo')\n }\n }\n this.undoStack.push(entry)\n this.emitChange()\n return true\n }\n\n /** 清空全部历史(含事务缓冲) */\n clear(): void {\n this.undoStack = []\n this.redoStack = []\n this.transactionBuffer = []\n this.transactionDepth = 0\n this.emitChange()\n }\n\n onChange(handler: (state: HistoryState) => void): () => void {\n return this.emitter.on('change', handler)\n }\n\n private pushEntry(entry: HistoryEntry): void {\n this.undoStack.push(entry)\n if (this.undoStack.length > this.capacity) {\n // 淘汰最旧条目;redo 栈不受影响(淘汰只发生在 undo 栈底部)\n this.undoStack.shift()\n }\n // 新命令清空 redo 栈\n this.redoStack = []\n this.emitChange()\n }\n\n private emitChange(): void {\n this.emitter.emit('change', { canUndo: this.canUndo, canRedo: this.canRedo })\n }\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAa,2BAA2B;AAaxC,IAAa,iBAAb,MAA4B;CAWP;CACA;CAXnB,YAAoC,CAAC;CACrC,YAAoC,CAAC;;CAErC,mBAA2B;;CAE3B,oBAAwC,CAAC;CACzC,UAAkB,IAAI,kBAAiC;CAEvD,YAEE,YACA,WAAiB,KACjB;EAFiB,KAAA,aAAA;EACA,KAAA,WAAA;CAChB;CAEH,IAAI,UAAmB;EACrB,OAAO,KAAK,UAAU,SAAS;CACjC;CAEA,IAAI,UAAmB;EACrB,OAAO,KAAK,UAAU,SAAS;CACjC;;CAGA,IAAI,WAAmB;EACrB,OAAO,KAAK,UAAU;CACxB;;CAGA,IAAI,WAAmB;EACrB,OAAO,KAAK,UAAU;CACxB;;CAGA,IAAI,gBAAyB;EAC3B,OAAO,KAAK,mBAAmB;CACjC;;CAGA,KAAK,WAA6B;EAChC,IAAI,UAAU,WAAW,GAAG;EAC5B,IAAI,KAAK,mBAAmB,GAAG;GAC7B,KAAK,kBAAkB,KAAK,GAAG,SAAS;GACxC;EACF;EACA,KAAK,UAAU,SAAS;CAC1B;;CAGA,mBAAyB;EACvB,KAAK;CACP;;CAGA,SAAe;EACb,IAAI,KAAK,qBAAqB,GAC5B,MAAM,IAAI,MAAM,gCAAgC;EAElD,KAAK;EACL,IAAI,KAAK,qBAAqB,KAAK,KAAK,kBAAkB,SAAS,GAAG;GACpE,MAAM,QAAQ,KAAK;GACnB,KAAK,oBAAoB,CAAC;GAC1B,KAAK,UAAU,KAAK;EACtB;CACF;;;;;CAMA,WAAiB;EACf,IAAI,KAAK,qBAAqB,GAAG;EACjC,MAAM,SAAS,KAAK;EACpB,KAAK,oBAAoB,CAAC;EAC1B,KAAK,mBAAmB;EACxB,KAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KACtC,KAAK,MAAM,SAAS,OAAO,EAAE,CAAE,MAC7B,KAAK,WAAW,OAAO,MAAM;CAGnC;;CAGA,OAAgB;EACd,IAAI,KAAK,mBAAmB,GAAG,OAAO;EACtC,MAAM,QAAQ,KAAK,UAAU,IAAI;EACjC,IAAI,CAAC,OAAO,OAAO;EACnB,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KACrC,KAAK,MAAM,SAAS,MAAM,EAAE,CAAE,MAC5B,KAAK,WAAW,OAAO,MAAM;EAGjC,KAAK,UAAU,KAAK,KAAK;EACzB,KAAK,WAAW;EAChB,OAAO;CACT;;CAGA,OAAgB;EACd,IAAI,KAAK,mBAAmB,GAAG,OAAO;EACtC,MAAM,QAAQ,KAAK,UAAU,IAAI;EACjC,IAAI,CAAC,OAAO,OAAO;EACnB,KAAK,MAAM,YAAY,OACrB,KAAK,MAAM,SAAS,SAAS,MAC3B,KAAK,WAAW,OAAO,MAAM;EAGjC,KAAK,UAAU,KAAK,KAAK;EACzB,KAAK,WAAW;EAChB,OAAO;CACT;;CAGA,QAAc;EACZ,KAAK,YAAY,CAAC;EAClB,KAAK,YAAY,CAAC;EAClB,KAAK,oBAAoB,CAAC;EAC1B,KAAK,mBAAmB;EACxB,KAAK,WAAW;CAClB;CAEA,SAAS,SAAoD;EAC3D,OAAO,KAAK,QAAQ,GAAG,UAAU,OAAO;CAC1C;CAEA,UAAkB,OAA2B;EAC3C,KAAK,UAAU,KAAK,KAAK;EACzB,IAAI,KAAK,UAAU,SAAS,KAAK,UAE/B,KAAK,UAAU,MAAM;EAGvB,KAAK,YAAY,CAAC;EAClB,KAAK,WAAW;CAClB;CAEA,aAA2B;EACzB,KAAK,QAAQ,KAAK,UAAU;GAAE,SAAS,KAAK;GAAS,SAAS,KAAK;EAAQ,CAAC;CAC9E;AACF"}
@@ -1,21 +0,0 @@
1
- import { CellRange } from "../address.js";
2
- import { Command } from "./types.js";
3
- //#region src/core/command/merge-cells.d.ts
4
- interface MergeCellsParams {
5
- range: CellRange;
6
- }
7
- /**
8
- * 合并命令。Patch 捕获完整 before 状态:
9
- * - 被解除的既有合并记录(undo 时逐一恢复)
10
- * - 包围盒内每一格的原数据(undo 时连被清空的值一起还原)
11
- * 值保留规则同 Excel/univer:行主序第一个有值格的值写入新锚点,其余清空。
12
- */
13
- declare const MergeCellsCommand: Command<MergeCellsParams, CellRange>;
14
- interface UnmergeCellsParams {
15
- range: CellRange;
16
- }
17
- /** 取消合并命令:解除与 range 相交的所有合并;undo 恢复合并记录 */
18
- declare const UnmergeCellsCommand: Command<UnmergeCellsParams>;
19
- //#endregion
20
- export { MergeCellsCommand, MergeCellsParams, UnmergeCellsCommand, UnmergeCellsParams };
21
- //# sourceMappingURL=merge-cells.d.ts.map