@rowsncolumns/spreadsheet-state 28.0.76 → 29.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (633) hide show
  1. package/dist/cjs/api/anchored-objects.d.ts +122 -6
  2. package/dist/cjs/api/anchored-objects.d.ts.map +1 -1
  3. package/dist/cjs/api/anchored-objects.js +464 -43
  4. package/dist/cjs/api/copy-paste.d.ts +8 -2
  5. package/dist/cjs/api/copy-paste.d.ts.map +1 -1
  6. package/dist/cjs/api/copy-paste.js +4 -4
  7. package/dist/cjs/api/filter.d.ts +15 -1
  8. package/dist/cjs/api/filter.d.ts.map +1 -1
  9. package/dist/cjs/api/filter.js +32 -2
  10. package/dist/cjs/api/formula.d.ts +63 -0
  11. package/dist/cjs/api/formula.d.ts.map +1 -1
  12. package/dist/cjs/api/formula.js +278 -8
  13. package/dist/cjs/api/immer-utils.d.ts +11 -1
  14. package/dist/cjs/api/immer-utils.d.ts.map +1 -1
  15. package/dist/cjs/api/immer-utils.js +17 -1
  16. package/dist/cjs/api/insert-cut-cells.d.ts +35 -0
  17. package/dist/cjs/api/insert-cut-cells.d.ts.map +1 -0
  18. package/dist/cjs/api/insert-cut-cells.js +60 -0
  19. package/dist/cjs/api/merges.d.ts +8 -0
  20. package/dist/cjs/api/merges.d.ts.map +1 -1
  21. package/dist/cjs/api/merges.js +11 -0
  22. package/dist/cjs/api/paint-format.d.ts +22 -1
  23. package/dist/cjs/api/paint-format.d.ts.map +1 -1
  24. package/dist/cjs/api/paint-format.js +57 -1
  25. package/dist/cjs/api/sort.d.ts +23 -1
  26. package/dist/cjs/api/sort.d.ts.map +1 -1
  27. package/dist/cjs/api/sort.js +52 -6
  28. package/dist/cjs/api/structural-guards.d.ts +57 -0
  29. package/dist/cjs/api/structural-guards.d.ts.map +1 -1
  30. package/dist/cjs/api/structural-guards.js +93 -1
  31. package/dist/cjs/api/structural-table-refs.d.ts +58 -3
  32. package/dist/cjs/api/structural-table-refs.d.ts.map +1 -1
  33. package/dist/cjs/api/structural-table-refs.js +177 -16
  34. package/dist/cjs/api/subtotal.d.ts +20 -13
  35. package/dist/cjs/api/subtotal.d.ts.map +1 -1
  36. package/dist/cjs/api/subtotal.js +26 -19
  37. package/dist/cjs/api/table.d.ts +26 -2
  38. package/dist/cjs/api/table.d.ts.map +1 -1
  39. package/dist/cjs/api/table.js +93 -60
  40. package/dist/cjs/api/validation.d.ts.map +1 -1
  41. package/dist/cjs/api/validation.js +53 -8
  42. package/dist/cjs/atoms/creating-table.atom.d.ts +22 -0
  43. package/dist/cjs/atoms/creating-table.atom.d.ts.map +1 -0
  44. package/dist/cjs/atoms/creating-table.atom.js +4 -0
  45. package/dist/cjs/atoms/dialog-state.atom.d.ts +8 -0
  46. package/dist/cjs/atoms/dialog-state.atom.d.ts.map +1 -1
  47. package/dist/cjs/atoms/dialog-state.atom.js +28 -0
  48. package/dist/cjs/atoms/editing-slicer.atom.d.ts +9 -0
  49. package/dist/cjs/atoms/editing-slicer.atom.d.ts.map +1 -0
  50. package/dist/cjs/atoms/editing-slicer.atom.js +6 -0
  51. package/dist/cjs/atoms/index.d.ts +4 -0
  52. package/dist/cjs/atoms/index.d.ts.map +1 -1
  53. package/dist/cjs/atoms/index.js +4 -0
  54. package/dist/cjs/atoms/inserting-slicer.atom.d.ts +8 -0
  55. package/dist/cjs/atoms/inserting-slicer.atom.d.ts.map +1 -0
  56. package/dist/cjs/atoms/inserting-slicer.atom.js +5 -0
  57. package/dist/cjs/atoms/resizing-table.atom.d.ts +8 -0
  58. package/dist/cjs/atoms/resizing-table.atom.d.ts.map +1 -0
  59. package/dist/cjs/atoms/resizing-table.atom.js +5 -0
  60. package/dist/cjs/commands.d.ts +138 -2
  61. package/dist/cjs/commands.d.ts.map +1 -1
  62. package/dist/cjs/components/editors/embed-editor.d.ts +4 -2
  63. package/dist/cjs/components/editors/embed-editor.d.ts.map +1 -1
  64. package/dist/cjs/components/editors/embed-editor.js +38 -9
  65. package/dist/cjs/components/editors/slicer-editor.d.ts +15 -0
  66. package/dist/cjs/components/editors/slicer-editor.d.ts.map +1 -0
  67. package/dist/cjs/components/editors/slicer-editor.js +87 -0
  68. package/dist/cjs/components/editors/table-editor.d.ts +58 -2
  69. package/dist/cjs/components/editors/table-editor.d.ts.map +1 -1
  70. package/dist/cjs/components/editors/table-editor.js +261 -20
  71. package/dist/cjs/components/index.d.ts +1 -0
  72. package/dist/cjs/components/index.d.ts.map +1 -1
  73. package/dist/cjs/components/index.js +1 -0
  74. package/dist/cjs/constants.d.ts +9 -1
  75. package/dist/cjs/constants.d.ts.map +1 -1
  76. package/dist/cjs/constants.js +12 -0
  77. package/dist/cjs/generated-names.d.ts +13 -3
  78. package/dist/cjs/generated-names.d.ts.map +1 -1
  79. package/dist/cjs/generated-names.js +3 -1
  80. package/dist/cjs/helpers.d.ts +5 -0
  81. package/dist/cjs/helpers.d.ts.map +1 -1
  82. package/dist/cjs/helpers.js +10 -1
  83. package/dist/cjs/hooks/use-on-change-batch.d.ts +19 -2
  84. package/dist/cjs/hooks/use-on-change-batch.d.ts.map +1 -1
  85. package/dist/cjs/hooks/use-on-change-batch.js +43 -35
  86. package/dist/cjs/hooks/use-on-change-calculated-column.d.ts +10 -1
  87. package/dist/cjs/hooks/use-on-change-calculated-column.d.ts.map +1 -1
  88. package/dist/cjs/hooks/use-on-change-calculated-column.js +17 -5
  89. package/dist/cjs/hooks/use-on-change-table-column.d.ts +6 -1
  90. package/dist/cjs/hooks/use-on-change-table-column.d.ts.map +1 -1
  91. package/dist/cjs/hooks/use-on-change-table-column.js +17 -5
  92. package/dist/cjs/hooks/use-on-change.d.ts +36 -3
  93. package/dist/cjs/hooks/use-on-change.d.ts.map +1 -1
  94. package/dist/cjs/hooks/use-on-change.js +218 -136
  95. package/dist/cjs/hooks/use-on-copy.d.ts +1 -1
  96. package/dist/cjs/hooks/use-on-copy.d.ts.map +1 -1
  97. package/dist/cjs/hooks/use-on-copy.js +2 -3
  98. package/dist/cjs/hooks/use-on-create-custom-table-style.d.ts +17 -0
  99. package/dist/cjs/hooks/use-on-create-custom-table-style.d.ts.map +1 -0
  100. package/dist/cjs/hooks/use-on-create-custom-table-style.js +28 -0
  101. package/dist/cjs/hooks/use-on-create-named-range.d.ts +4 -2
  102. package/dist/cjs/hooks/use-on-create-named-range.d.ts.map +1 -1
  103. package/dist/cjs/hooks/use-on-create-named-range.js +11 -1
  104. package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts +2 -1
  105. package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
  106. package/dist/cjs/hooks/use-on-delete-cells-shift-left.js +3 -1
  107. package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts +2 -1
  108. package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
  109. package/dist/cjs/hooks/use-on-delete-cells-shift-up.js +3 -1
  110. package/dist/cjs/hooks/use-on-delete-column.d.ts +2 -1
  111. package/dist/cjs/hooks/use-on-delete-column.d.ts.map +1 -1
  112. package/dist/cjs/hooks/use-on-delete-column.js +3 -1
  113. package/dist/cjs/hooks/use-on-delete-row.d.ts +2 -1
  114. package/dist/cjs/hooks/use-on-delete-row.d.ts.map +1 -1
  115. package/dist/cjs/hooks/use-on-delete-row.js +3 -1
  116. package/dist/cjs/hooks/use-on-delete-sheet.d.ts +9 -1
  117. package/dist/cjs/hooks/use-on-delete-sheet.d.ts.map +1 -1
  118. package/dist/cjs/hooks/use-on-delete-sheet.js +17 -1
  119. package/dist/cjs/hooks/use-on-delete-table-row.d.ts +4 -1
  120. package/dist/cjs/hooks/use-on-delete-table-row.d.ts.map +1 -1
  121. package/dist/cjs/hooks/use-on-delete-table-row.js +19 -1
  122. package/dist/cjs/hooks/use-on-delete.d.ts +5 -2
  123. package/dist/cjs/hooks/use-on-delete.d.ts.map +1 -1
  124. package/dist/cjs/hooks/use-on-delete.js +5 -1
  125. package/dist/cjs/hooks/use-on-embeds.d.ts +7 -4
  126. package/dist/cjs/hooks/use-on-embeds.d.ts.map +1 -1
  127. package/dist/cjs/hooks/use-on-embeds.js +26 -24
  128. package/dist/cjs/hooks/use-on-fill.d.ts +17 -2
  129. package/dist/cjs/hooks/use-on-fill.d.ts.map +1 -1
  130. package/dist/cjs/hooks/use-on-fill.js +29 -15
  131. package/dist/cjs/hooks/use-on-filter-table.d.ts.map +1 -1
  132. package/dist/cjs/hooks/use-on-filter-table.js +209 -103
  133. package/dist/cjs/hooks/use-on-import-excel.d.ts +2 -1
  134. package/dist/cjs/hooks/use-on-import-excel.d.ts.map +1 -1
  135. package/dist/cjs/hooks/use-on-import-excel.js +22 -19
  136. package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts +2 -1
  137. package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
  138. package/dist/cjs/hooks/use-on-insert-cells-shift-down.js +3 -1
  139. package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts +2 -1
  140. package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
  141. package/dist/cjs/hooks/use-on-insert-cells-shift-right.js +3 -1
  142. package/dist/cjs/hooks/use-on-insert-column.d.ts +2 -1
  143. package/dist/cjs/hooks/use-on-insert-column.d.ts.map +1 -1
  144. package/dist/cjs/hooks/use-on-insert-column.js +3 -1
  145. package/dist/cjs/hooks/use-on-insert-row.d.ts +2 -1
  146. package/dist/cjs/hooks/use-on-insert-row.d.ts.map +1 -1
  147. package/dist/cjs/hooks/use-on-insert-row.js +3 -1
  148. package/dist/cjs/hooks/use-on-insert-table-row.d.ts +5 -2
  149. package/dist/cjs/hooks/use-on-insert-table-row.d.ts.map +1 -1
  150. package/dist/cjs/hooks/use-on-insert-table-row.js +19 -1
  151. package/dist/cjs/hooks/use-on-merge-unmerge-cells.d.ts +3 -2
  152. package/dist/cjs/hooks/use-on-merge-unmerge-cells.d.ts.map +1 -1
  153. package/dist/cjs/hooks/use-on-merge-unmerge-cells.js +14 -1
  154. package/dist/cjs/hooks/use-on-move-columns.d.ts +4 -1
  155. package/dist/cjs/hooks/use-on-move-columns.d.ts.map +1 -1
  156. package/dist/cjs/hooks/use-on-move-columns.js +28 -6
  157. package/dist/cjs/hooks/use-on-move-rows.d.ts +18 -1
  158. package/dist/cjs/hooks/use-on-move-rows.d.ts.map +1 -1
  159. package/dist/cjs/hooks/use-on-move-rows.js +44 -6
  160. package/dist/cjs/hooks/use-on-move-selection.d.ts +9 -2
  161. package/dist/cjs/hooks/use-on-move-selection.d.ts.map +1 -1
  162. package/dist/cjs/hooks/use-on-move-selection.js +101 -25
  163. package/dist/cjs/hooks/use-on-paste.d.ts +33 -2
  164. package/dist/cjs/hooks/use-on-paste.d.ts.map +1 -1
  165. package/dist/cjs/hooks/use-on-paste.js +1005 -740
  166. package/dist/cjs/hooks/use-on-remove-duplicates.d.ts +5 -2
  167. package/dist/cjs/hooks/use-on-remove-duplicates.d.ts.map +1 -1
  168. package/dist/cjs/hooks/use-on-remove-duplicates.js +5 -1
  169. package/dist/cjs/hooks/use-on-request-create-table.d.ts +13 -0
  170. package/dist/cjs/hooks/use-on-request-create-table.d.ts.map +1 -0
  171. package/dist/cjs/hooks/use-on-request-create-table.js +44 -0
  172. package/dist/cjs/hooks/use-on-request-insert-slicer.d.ts +7 -0
  173. package/dist/cjs/hooks/use-on-request-insert-slicer.d.ts.map +1 -0
  174. package/dist/cjs/hooks/use-on-request-insert-slicer.js +15 -0
  175. package/dist/cjs/hooks/use-on-request-resize-table.d.ts +7 -0
  176. package/dist/cjs/hooks/use-on-request-resize-table.d.ts.map +1 -0
  177. package/dist/cjs/hooks/use-on-request-resize-table.js +15 -0
  178. package/dist/cjs/hooks/use-on-resize-table.d.ts +5 -1
  179. package/dist/cjs/hooks/use-on-resize-table.d.ts.map +1 -1
  180. package/dist/cjs/hooks/use-on-resize-table.js +110 -33
  181. package/dist/cjs/hooks/use-on-sort-column.d.ts +28 -3
  182. package/dist/cjs/hooks/use-on-sort-column.d.ts.map +1 -1
  183. package/dist/cjs/hooks/use-on-sort-column.js +136 -90
  184. package/dist/cjs/hooks/use-on-sort-range.d.ts +26 -3
  185. package/dist/cjs/hooks/use-on-sort-range.d.ts.map +1 -1
  186. package/dist/cjs/hooks/use-on-sort-range.js +113 -67
  187. package/dist/cjs/hooks/use-on-sort-table.d.ts +18 -1
  188. package/dist/cjs/hooks/use-on-sort-table.d.ts.map +1 -1
  189. package/dist/cjs/hooks/use-on-sort-table.js +128 -98
  190. package/dist/cjs/hooks/use-on-subtotal.d.ts +10 -3
  191. package/dist/cjs/hooks/use-on-subtotal.d.ts.map +1 -1
  192. package/dist/cjs/hooks/use-on-subtotal.js +13 -9
  193. package/dist/cjs/hooks/use-on-table.d.ts +39 -7
  194. package/dist/cjs/hooks/use-on-table.d.ts.map +1 -1
  195. package/dist/cjs/hooks/use-on-table.js +257 -49
  196. package/dist/cjs/hooks/use-on-undo-calculated-column.d.ts +23 -0
  197. package/dist/cjs/hooks/use-on-undo-calculated-column.d.ts.map +1 -0
  198. package/dist/cjs/hooks/use-on-undo-calculated-column.js +70 -0
  199. package/dist/cjs/hooks/use-on-undo-table-auto-expansion.d.ts +28 -0
  200. package/dist/cjs/hooks/use-on-undo-table-auto-expansion.d.ts.map +1 -0
  201. package/dist/cjs/hooks/use-on-undo-table-auto-expansion.js +96 -0
  202. package/dist/cjs/hooks/use-on-update-named-range.d.ts +4 -2
  203. package/dist/cjs/hooks/use-on-update-named-range.d.ts.map +1 -1
  204. package/dist/cjs/hooks/use-on-update-named-range.js +13 -1
  205. package/dist/cjs/hooks/use-sheet-properties.d.ts +1 -0
  206. package/dist/cjs/hooks/use-sheet-properties.d.ts.map +1 -1
  207. package/dist/cjs/hooks/use-sheet-properties.js +54 -34
  208. package/dist/cjs/hooks/use-slicers.d.ts +2 -2
  209. package/dist/cjs/hooks/use-slicers.d.ts.map +1 -1
  210. package/dist/cjs/hooks/use-slicers.js +17 -26
  211. package/dist/cjs/hooks/use-sparkline-groups.d.ts +50 -0
  212. package/dist/cjs/hooks/use-sparkline-groups.d.ts.map +1 -0
  213. package/dist/cjs/hooks/use-sparkline-groups.js +192 -0
  214. package/dist/cjs/hooks/use-spreadsheet-state.d.ts +69 -12
  215. package/dist/cjs/hooks/use-spreadsheet-state.d.ts.map +1 -1
  216. package/dist/cjs/hooks/use-spreadsheet-state.js +383 -84
  217. package/dist/cjs/hooks/use-structured-reference.d.ts.map +1 -1
  218. package/dist/cjs/hooks/use-structured-reference.js +17 -0
  219. package/dist/cjs/hooks/use-undo-redo-actions.d.ts +2 -1
  220. package/dist/cjs/hooks/use-undo-redo-actions.d.ts.map +1 -1
  221. package/dist/cjs/hooks/use-undo-redo-actions.js +10 -2
  222. package/dist/cjs/hooks/use-undo-redo.d.ts +12 -0
  223. package/dist/cjs/hooks/use-undo-redo.d.ts.map +1 -1
  224. package/dist/cjs/hooks/use-undo-redo.js +169 -10
  225. package/dist/cjs/hooks/utils/sort-rows.d.ts.map +1 -1
  226. package/dist/cjs/hooks/utils/sort-rows.js +4 -3
  227. package/dist/cjs/index.d.ts +8 -0
  228. package/dist/cjs/index.d.ts.map +1 -1
  229. package/dist/cjs/index.js +9 -0
  230. package/dist/cjs/interface/apply-fill.d.ts +26 -3
  231. package/dist/cjs/interface/apply-fill.d.ts.map +1 -1
  232. package/dist/cjs/interface/apply-fill.js +207 -98
  233. package/dist/cjs/interface/change-batch.d.ts +1 -1
  234. package/dist/cjs/interface/change-batch.d.ts.map +1 -1
  235. package/dist/cjs/interface/change-batch.js +112 -15
  236. package/dist/cjs/interface/change-calculated-column.d.ts +6 -2
  237. package/dist/cjs/interface/change-calculated-column.d.ts.map +1 -1
  238. package/dist/cjs/interface/change-calculated-column.js +87 -17
  239. package/dist/cjs/interface/change-table-column.d.ts +81 -7
  240. package/dist/cjs/interface/change-table-column.d.ts.map +1 -1
  241. package/dist/cjs/interface/change-table-column.js +336 -76
  242. package/dist/cjs/interface/create-table.d.ts +15 -3
  243. package/dist/cjs/interface/create-table.d.ts.map +1 -1
  244. package/dist/cjs/interface/create-table.js +100 -25
  245. package/dist/cjs/interface/delete-cells-shift-left.d.ts +1 -1
  246. package/dist/cjs/interface/delete-cells-shift-left.d.ts.map +1 -1
  247. package/dist/cjs/interface/delete-cells-shift-left.js +10 -1
  248. package/dist/cjs/interface/delete-cells-shift-up.d.ts +1 -1
  249. package/dist/cjs/interface/delete-cells-shift-up.d.ts.map +1 -1
  250. package/dist/cjs/interface/delete-cells-shift-up.js +10 -1
  251. package/dist/cjs/interface/delete-cells.d.ts +1 -1
  252. package/dist/cjs/interface/delete-cells.d.ts.map +1 -1
  253. package/dist/cjs/interface/delete-cells.js +81 -25
  254. package/dist/cjs/interface/delete-column.d.ts +1 -1
  255. package/dist/cjs/interface/delete-column.d.ts.map +1 -1
  256. package/dist/cjs/interface/delete-column.js +29 -22
  257. package/dist/cjs/interface/delete-row.d.ts +1 -1
  258. package/dist/cjs/interface/delete-row.d.ts.map +1 -1
  259. package/dist/cjs/interface/delete-row.js +244 -39
  260. package/dist/cjs/interface/delete-sheet.d.ts +2 -2
  261. package/dist/cjs/interface/delete-sheet.d.ts.map +1 -1
  262. package/dist/cjs/interface/delete-sheet.js +118 -1
  263. package/dist/cjs/interface/delete-table-column.d.ts +1 -1
  264. package/dist/cjs/interface/delete-table-column.d.ts.map +1 -1
  265. package/dist/cjs/interface/delete-table-column.js +11 -1
  266. package/dist/cjs/interface/delete-table-row.d.ts +1 -1
  267. package/dist/cjs/interface/delete-table-row.d.ts.map +1 -1
  268. package/dist/cjs/interface/delete-table-row.js +361 -275
  269. package/dist/cjs/interface/duplicate-sheet.d.ts.map +1 -1
  270. package/dist/cjs/interface/duplicate-sheet.js +83 -31
  271. package/dist/cjs/interface/embeds.d.ts +10 -1
  272. package/dist/cjs/interface/embeds.d.ts.map +1 -1
  273. package/dist/cjs/interface/embeds.js +120 -6
  274. package/dist/cjs/interface/insert-cells-shift-down.d.ts +1 -1
  275. package/dist/cjs/interface/insert-cells-shift-down.d.ts.map +1 -1
  276. package/dist/cjs/interface/insert-cells-shift-down.js +10 -1
  277. package/dist/cjs/interface/insert-cells-shift-right.d.ts +1 -1
  278. package/dist/cjs/interface/insert-cells-shift-right.d.ts.map +1 -1
  279. package/dist/cjs/interface/insert-cells-shift-right.js +10 -1
  280. package/dist/cjs/interface/insert-column.d.ts +2 -2
  281. package/dist/cjs/interface/insert-column.d.ts.map +1 -1
  282. package/dist/cjs/interface/insert-column.js +101 -56
  283. package/dist/cjs/interface/insert-row.d.ts +1 -1
  284. package/dist/cjs/interface/insert-row.d.ts.map +1 -1
  285. package/dist/cjs/interface/insert-row.js +25 -7
  286. package/dist/cjs/interface/insert-table-row.d.ts +2 -1
  287. package/dist/cjs/interface/insert-table-row.d.ts.map +1 -1
  288. package/dist/cjs/interface/insert-table-row.js +70 -19
  289. package/dist/cjs/interface/remove-duplicates.d.ts +1 -1
  290. package/dist/cjs/interface/remove-duplicates.d.ts.map +1 -1
  291. package/dist/cjs/interface/remove-duplicates.js +46 -6
  292. package/dist/cjs/interface/remove-table.d.ts +1 -1
  293. package/dist/cjs/interface/remove-table.d.ts.map +1 -1
  294. package/dist/cjs/interface/remove-table.js +72 -16
  295. package/dist/cjs/interface/slicers.d.ts +12 -1
  296. package/dist/cjs/interface/slicers.d.ts.map +1 -1
  297. package/dist/cjs/interface/slicers.js +47 -2
  298. package/dist/cjs/interface/spreadsheet-interface.d.ts +1 -1
  299. package/dist/cjs/interface/spreadsheet-interface.d.ts.map +1 -1
  300. package/dist/cjs/interface/spreadsheet-interface.js +64 -1
  301. package/dist/cjs/interface/table-totalrow.d.ts +13 -1
  302. package/dist/cjs/interface/table-totalrow.d.ts.map +1 -1
  303. package/dist/cjs/interface/table-totalrow.js +107 -73
  304. package/dist/cjs/interface/table-utils.d.ts +59 -6
  305. package/dist/cjs/interface/table-utils.d.ts.map +1 -1
  306. package/dist/cjs/interface/table-utils.js +211 -15
  307. package/dist/cjs/interface/update-table.d.ts +16 -1
  308. package/dist/cjs/interface/update-table.d.ts.map +1 -1
  309. package/dist/cjs/interface/update-table.js +190 -44
  310. package/dist/cjs/sheet-cell.d.ts.map +1 -1
  311. package/dist/cjs/test-setup.d.ts.map +1 -1
  312. package/dist/cjs/test-setup.js +6 -0
  313. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  314. package/dist/cjs/validation-schema/table.schema.d.ts +11 -0
  315. package/dist/cjs/validation-schema/table.schema.d.ts.map +1 -1
  316. package/dist/cjs/validation-schema/table.schema.js +20 -3
  317. package/dist/esm/api/anchored-objects.d.ts +122 -6
  318. package/dist/esm/api/anchored-objects.d.ts.map +1 -1
  319. package/dist/esm/api/anchored-objects.js +375 -15
  320. package/dist/esm/api/copy-paste.d.ts +8 -2
  321. package/dist/esm/api/copy-paste.d.ts.map +1 -1
  322. package/dist/esm/api/copy-paste.js +4 -4
  323. package/dist/esm/api/filter.d.ts +15 -1
  324. package/dist/esm/api/filter.d.ts.map +1 -1
  325. package/dist/esm/api/filter.js +28 -0
  326. package/dist/esm/api/formula.d.ts +63 -0
  327. package/dist/esm/api/formula.d.ts.map +1 -1
  328. package/dist/esm/api/formula.js +235 -8
  329. package/dist/esm/api/immer-utils.d.ts +11 -1
  330. package/dist/esm/api/immer-utils.d.ts.map +1 -1
  331. package/dist/esm/api/immer-utils.js +16 -0
  332. package/dist/esm/api/insert-cut-cells.d.ts +35 -0
  333. package/dist/esm/api/insert-cut-cells.d.ts.map +1 -0
  334. package/dist/esm/api/insert-cut-cells.js +67 -0
  335. package/dist/esm/api/merges.d.ts +8 -0
  336. package/dist/esm/api/merges.d.ts.map +1 -1
  337. package/dist/esm/api/merges.js +9 -0
  338. package/dist/esm/api/paint-format.d.ts +22 -1
  339. package/dist/esm/api/paint-format.d.ts.map +1 -1
  340. package/dist/esm/api/paint-format.js +44 -1
  341. package/dist/esm/api/sort.d.ts +23 -1
  342. package/dist/esm/api/sort.d.ts.map +1 -1
  343. package/dist/esm/api/sort.js +45 -6
  344. package/dist/esm/api/structural-guards.d.ts +57 -0
  345. package/dist/esm/api/structural-guards.d.ts.map +1 -1
  346. package/dist/esm/api/structural-guards.js +85 -0
  347. package/dist/esm/api/structural-table-refs.d.ts +58 -3
  348. package/dist/esm/api/structural-table-refs.d.ts.map +1 -1
  349. package/dist/esm/api/structural-table-refs.js +126 -6
  350. package/dist/esm/api/subtotal.d.ts +20 -13
  351. package/dist/esm/api/subtotal.d.ts.map +1 -1
  352. package/dist/esm/api/subtotal.js +15 -8
  353. package/dist/esm/api/table.d.ts +26 -2
  354. package/dist/esm/api/table.d.ts.map +1 -1
  355. package/dist/esm/api/table.js +70 -48
  356. package/dist/esm/api/validation.d.ts.map +1 -1
  357. package/dist/esm/api/validation.js +53 -8
  358. package/dist/esm/atoms/creating-table.atom.d.ts +22 -0
  359. package/dist/esm/atoms/creating-table.atom.d.ts.map +1 -0
  360. package/dist/esm/atoms/creating-table.atom.js +4 -0
  361. package/dist/esm/atoms/dialog-state.atom.d.ts +8 -0
  362. package/dist/esm/atoms/dialog-state.atom.d.ts.map +1 -1
  363. package/dist/esm/atoms/dialog-state.atom.js +12 -0
  364. package/dist/esm/atoms/editing-slicer.atom.d.ts +9 -0
  365. package/dist/esm/atoms/editing-slicer.atom.d.ts.map +1 -0
  366. package/dist/esm/atoms/editing-slicer.atom.js +6 -0
  367. package/dist/esm/atoms/index.d.ts +4 -0
  368. package/dist/esm/atoms/index.d.ts.map +1 -1
  369. package/dist/esm/atoms/index.js +4 -0
  370. package/dist/esm/atoms/inserting-slicer.atom.d.ts +8 -0
  371. package/dist/esm/atoms/inserting-slicer.atom.d.ts.map +1 -0
  372. package/dist/esm/atoms/inserting-slicer.atom.js +5 -0
  373. package/dist/esm/atoms/resizing-table.atom.d.ts +8 -0
  374. package/dist/esm/atoms/resizing-table.atom.d.ts.map +1 -0
  375. package/dist/esm/atoms/resizing-table.atom.js +5 -0
  376. package/dist/esm/commands.d.ts +138 -2
  377. package/dist/esm/commands.d.ts.map +1 -1
  378. package/dist/esm/components/editors/embed-editor.d.ts +4 -2
  379. package/dist/esm/components/editors/embed-editor.d.ts.map +1 -1
  380. package/dist/esm/components/editors/embed-editor.js +40 -6
  381. package/dist/esm/components/editors/slicer-editor.d.ts +15 -0
  382. package/dist/esm/components/editors/slicer-editor.d.ts.map +1 -0
  383. package/dist/esm/components/editors/slicer-editor.js +85 -0
  384. package/dist/esm/components/editors/table-editor.d.ts +58 -2
  385. package/dist/esm/components/editors/table-editor.d.ts.map +1 -1
  386. package/dist/esm/components/editors/table-editor.js +243 -19
  387. package/dist/esm/components/index.d.ts +1 -0
  388. package/dist/esm/components/index.d.ts.map +1 -1
  389. package/dist/esm/components/index.js +1 -0
  390. package/dist/esm/constants.d.ts +9 -1
  391. package/dist/esm/constants.d.ts.map +1 -1
  392. package/dist/esm/constants.js +12 -0
  393. package/dist/esm/generated-names.d.ts +13 -3
  394. package/dist/esm/generated-names.d.ts.map +1 -1
  395. package/dist/esm/generated-names.js +3 -1
  396. package/dist/esm/helpers.d.ts +5 -0
  397. package/dist/esm/helpers.d.ts.map +1 -1
  398. package/dist/esm/helpers.js +7 -1
  399. package/dist/esm/hooks/use-on-change-batch.d.ts +19 -2
  400. package/dist/esm/hooks/use-on-change-batch.d.ts.map +1 -1
  401. package/dist/esm/hooks/use-on-change-batch.js +19 -3
  402. package/dist/esm/hooks/use-on-change-calculated-column.d.ts +10 -1
  403. package/dist/esm/hooks/use-on-change-calculated-column.d.ts.map +1 -1
  404. package/dist/esm/hooks/use-on-change-calculated-column.js +17 -5
  405. package/dist/esm/hooks/use-on-change-table-column.d.ts +6 -1
  406. package/dist/esm/hooks/use-on-change-table-column.d.ts.map +1 -1
  407. package/dist/esm/hooks/use-on-change-table-column.js +17 -5
  408. package/dist/esm/hooks/use-on-change.d.ts +36 -3
  409. package/dist/esm/hooks/use-on-change.d.ts.map +1 -1
  410. package/dist/esm/hooks/use-on-change.js +214 -124
  411. package/dist/esm/hooks/use-on-copy.d.ts +1 -1
  412. package/dist/esm/hooks/use-on-copy.d.ts.map +1 -1
  413. package/dist/esm/hooks/use-on-copy.js +2 -3
  414. package/dist/esm/hooks/use-on-create-custom-table-style.d.ts +17 -0
  415. package/dist/esm/hooks/use-on-create-custom-table-style.d.ts.map +1 -0
  416. package/dist/esm/hooks/use-on-create-custom-table-style.js +26 -0
  417. package/dist/esm/hooks/use-on-create-named-range.d.ts +4 -2
  418. package/dist/esm/hooks/use-on-create-named-range.d.ts.map +1 -1
  419. package/dist/esm/hooks/use-on-create-named-range.js +11 -1
  420. package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts +2 -1
  421. package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
  422. package/dist/esm/hooks/use-on-delete-cells-shift-left.js +3 -1
  423. package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts +2 -1
  424. package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
  425. package/dist/esm/hooks/use-on-delete-cells-shift-up.js +3 -1
  426. package/dist/esm/hooks/use-on-delete-column.d.ts +2 -1
  427. package/dist/esm/hooks/use-on-delete-column.d.ts.map +1 -1
  428. package/dist/esm/hooks/use-on-delete-column.js +3 -1
  429. package/dist/esm/hooks/use-on-delete-row.d.ts +2 -1
  430. package/dist/esm/hooks/use-on-delete-row.d.ts.map +1 -1
  431. package/dist/esm/hooks/use-on-delete-row.js +3 -1
  432. package/dist/esm/hooks/use-on-delete-sheet.d.ts +9 -1
  433. package/dist/esm/hooks/use-on-delete-sheet.d.ts.map +1 -1
  434. package/dist/esm/hooks/use-on-delete-sheet.js +17 -1
  435. package/dist/esm/hooks/use-on-delete-table-row.d.ts +4 -1
  436. package/dist/esm/hooks/use-on-delete-table-row.d.ts.map +1 -1
  437. package/dist/esm/hooks/use-on-delete-table-row.js +19 -1
  438. package/dist/esm/hooks/use-on-delete.d.ts +5 -2
  439. package/dist/esm/hooks/use-on-delete.d.ts.map +1 -1
  440. package/dist/esm/hooks/use-on-delete.js +5 -1
  441. package/dist/esm/hooks/use-on-embeds.d.ts +7 -4
  442. package/dist/esm/hooks/use-on-embeds.d.ts.map +1 -1
  443. package/dist/esm/hooks/use-on-embeds.js +23 -6
  444. package/dist/esm/hooks/use-on-fill.d.ts +17 -2
  445. package/dist/esm/hooks/use-on-fill.d.ts.map +1 -1
  446. package/dist/esm/hooks/use-on-fill.js +27 -1
  447. package/dist/esm/hooks/use-on-filter-table.d.ts.map +1 -1
  448. package/dist/esm/hooks/use-on-filter-table.js +97 -26
  449. package/dist/esm/hooks/use-on-import-excel.d.ts +2 -1
  450. package/dist/esm/hooks/use-on-import-excel.d.ts.map +1 -1
  451. package/dist/esm/hooks/use-on-import-excel.js +4 -1
  452. package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts +2 -1
  453. package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
  454. package/dist/esm/hooks/use-on-insert-cells-shift-down.js +3 -1
  455. package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts +2 -1
  456. package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
  457. package/dist/esm/hooks/use-on-insert-cells-shift-right.js +3 -1
  458. package/dist/esm/hooks/use-on-insert-column.d.ts +2 -1
  459. package/dist/esm/hooks/use-on-insert-column.d.ts.map +1 -1
  460. package/dist/esm/hooks/use-on-insert-column.js +3 -1
  461. package/dist/esm/hooks/use-on-insert-row.d.ts +2 -1
  462. package/dist/esm/hooks/use-on-insert-row.d.ts.map +1 -1
  463. package/dist/esm/hooks/use-on-insert-row.js +3 -1
  464. package/dist/esm/hooks/use-on-insert-table-row.d.ts +5 -2
  465. package/dist/esm/hooks/use-on-insert-table-row.d.ts.map +1 -1
  466. package/dist/esm/hooks/use-on-insert-table-row.js +19 -1
  467. package/dist/esm/hooks/use-on-merge-unmerge-cells.d.ts +3 -2
  468. package/dist/esm/hooks/use-on-merge-unmerge-cells.d.ts.map +1 -1
  469. package/dist/esm/hooks/use-on-merge-unmerge-cells.js +12 -1
  470. package/dist/esm/hooks/use-on-move-columns.d.ts +4 -1
  471. package/dist/esm/hooks/use-on-move-columns.d.ts.map +1 -1
  472. package/dist/esm/hooks/use-on-move-columns.js +28 -6
  473. package/dist/esm/hooks/use-on-move-rows.d.ts +18 -1
  474. package/dist/esm/hooks/use-on-move-rows.d.ts.map +1 -1
  475. package/dist/esm/hooks/use-on-move-rows.js +44 -6
  476. package/dist/esm/hooks/use-on-move-selection.d.ts +9 -2
  477. package/dist/esm/hooks/use-on-move-selection.d.ts.map +1 -1
  478. package/dist/esm/hooks/use-on-move-selection.js +57 -1
  479. package/dist/esm/hooks/use-on-paste.d.ts +33 -2
  480. package/dist/esm/hooks/use-on-paste.d.ts.map +1 -1
  481. package/dist/esm/hooks/use-on-paste.js +825 -643
  482. package/dist/esm/hooks/use-on-remove-duplicates.d.ts +5 -2
  483. package/dist/esm/hooks/use-on-remove-duplicates.d.ts.map +1 -1
  484. package/dist/esm/hooks/use-on-remove-duplicates.js +5 -1
  485. package/dist/esm/hooks/use-on-request-create-table.d.ts +13 -0
  486. package/dist/esm/hooks/use-on-request-create-table.d.ts.map +1 -0
  487. package/dist/esm/hooks/use-on-request-create-table.js +43 -0
  488. package/dist/esm/hooks/use-on-request-insert-slicer.d.ts +7 -0
  489. package/dist/esm/hooks/use-on-request-insert-slicer.d.ts.map +1 -0
  490. package/dist/esm/hooks/use-on-request-insert-slicer.js +15 -0
  491. package/dist/esm/hooks/use-on-request-resize-table.d.ts +7 -0
  492. package/dist/esm/hooks/use-on-request-resize-table.d.ts.map +1 -0
  493. package/dist/esm/hooks/use-on-request-resize-table.js +15 -0
  494. package/dist/esm/hooks/use-on-resize-table.d.ts +5 -1
  495. package/dist/esm/hooks/use-on-resize-table.d.ts.map +1 -1
  496. package/dist/esm/hooks/use-on-resize-table.js +107 -27
  497. package/dist/esm/hooks/use-on-sort-column.d.ts +28 -3
  498. package/dist/esm/hooks/use-on-sort-column.d.ts.map +1 -1
  499. package/dist/esm/hooks/use-on-sort-column.js +105 -68
  500. package/dist/esm/hooks/use-on-sort-range.d.ts +26 -3
  501. package/dist/esm/hooks/use-on-sort-range.d.ts.map +1 -1
  502. package/dist/esm/hooks/use-on-sort-range.js +100 -64
  503. package/dist/esm/hooks/use-on-sort-table.d.ts +18 -1
  504. package/dist/esm/hooks/use-on-sort-table.d.ts.map +1 -1
  505. package/dist/esm/hooks/use-on-sort-table.js +107 -86
  506. package/dist/esm/hooks/use-on-subtotal.d.ts +10 -3
  507. package/dist/esm/hooks/use-on-subtotal.d.ts.map +1 -1
  508. package/dist/esm/hooks/use-on-subtotal.js +7 -5
  509. package/dist/esm/hooks/use-on-table.d.ts +39 -7
  510. package/dist/esm/hooks/use-on-table.d.ts.map +1 -1
  511. package/dist/esm/hooks/use-on-table.js +234 -26
  512. package/dist/esm/hooks/use-on-undo-calculated-column.d.ts +23 -0
  513. package/dist/esm/hooks/use-on-undo-calculated-column.d.ts.map +1 -0
  514. package/dist/esm/hooks/use-on-undo-calculated-column.js +62 -0
  515. package/dist/esm/hooks/use-on-undo-table-auto-expansion.d.ts +28 -0
  516. package/dist/esm/hooks/use-on-undo-table-auto-expansion.d.ts.map +1 -0
  517. package/dist/esm/hooks/use-on-undo-table-auto-expansion.js +75 -0
  518. package/dist/esm/hooks/use-on-update-named-range.d.ts +4 -2
  519. package/dist/esm/hooks/use-on-update-named-range.d.ts.map +1 -1
  520. package/dist/esm/hooks/use-on-update-named-range.js +13 -1
  521. package/dist/esm/hooks/use-sheet-properties.d.ts +1 -0
  522. package/dist/esm/hooks/use-sheet-properties.d.ts.map +1 -1
  523. package/dist/esm/hooks/use-sheet-properties.js +38 -19
  524. package/dist/esm/hooks/use-slicers.d.ts +2 -2
  525. package/dist/esm/hooks/use-slicers.d.ts.map +1 -1
  526. package/dist/esm/hooks/use-slicers.js +16 -8
  527. package/dist/esm/hooks/use-sparkline-groups.d.ts +50 -0
  528. package/dist/esm/hooks/use-sparkline-groups.d.ts.map +1 -0
  529. package/dist/esm/hooks/use-sparkline-groups.js +146 -0
  530. package/dist/esm/hooks/use-spreadsheet-state.d.ts +69 -12
  531. package/dist/esm/hooks/use-spreadsheet-state.d.ts.map +1 -1
  532. package/dist/esm/hooks/use-spreadsheet-state.js +321 -14
  533. package/dist/esm/hooks/use-structured-reference.d.ts.map +1 -1
  534. package/dist/esm/hooks/use-structured-reference.js +17 -0
  535. package/dist/esm/hooks/use-undo-redo-actions.d.ts +2 -1
  536. package/dist/esm/hooks/use-undo-redo-actions.d.ts.map +1 -1
  537. package/dist/esm/hooks/use-undo-redo-actions.js +8 -2
  538. package/dist/esm/hooks/use-undo-redo.d.ts +12 -0
  539. package/dist/esm/hooks/use-undo-redo.d.ts.map +1 -1
  540. package/dist/esm/hooks/use-undo-redo.js +158 -7
  541. package/dist/esm/hooks/utils/sort-rows.d.ts.map +1 -1
  542. package/dist/esm/hooks/utils/sort-rows.js +4 -3
  543. package/dist/esm/index.d.ts +8 -0
  544. package/dist/esm/index.d.ts.map +1 -1
  545. package/dist/esm/index.js +9 -0
  546. package/dist/esm/interface/apply-fill.d.ts +26 -3
  547. package/dist/esm/interface/apply-fill.d.ts.map +1 -1
  548. package/dist/esm/interface/apply-fill.js +188 -88
  549. package/dist/esm/interface/change-batch.d.ts +1 -1
  550. package/dist/esm/interface/change-batch.d.ts.map +1 -1
  551. package/dist/esm/interface/change-batch.js +89 -8
  552. package/dist/esm/interface/change-calculated-column.d.ts +6 -2
  553. package/dist/esm/interface/change-calculated-column.d.ts.map +1 -1
  554. package/dist/esm/interface/change-calculated-column.js +81 -16
  555. package/dist/esm/interface/change-table-column.d.ts +81 -7
  556. package/dist/esm/interface/change-table-column.d.ts.map +1 -1
  557. package/dist/esm/interface/change-table-column.js +295 -67
  558. package/dist/esm/interface/create-table.d.ts +15 -3
  559. package/dist/esm/interface/create-table.d.ts.map +1 -1
  560. package/dist/esm/interface/create-table.js +103 -27
  561. package/dist/esm/interface/delete-cells-shift-left.d.ts +1 -1
  562. package/dist/esm/interface/delete-cells-shift-left.d.ts.map +1 -1
  563. package/dist/esm/interface/delete-cells-shift-left.js +10 -1
  564. package/dist/esm/interface/delete-cells-shift-up.d.ts +1 -1
  565. package/dist/esm/interface/delete-cells-shift-up.d.ts.map +1 -1
  566. package/dist/esm/interface/delete-cells-shift-up.js +10 -1
  567. package/dist/esm/interface/delete-cells.d.ts +1 -1
  568. package/dist/esm/interface/delete-cells.d.ts.map +1 -1
  569. package/dist/esm/interface/delete-cells.js +47 -14
  570. package/dist/esm/interface/delete-column.d.ts +1 -1
  571. package/dist/esm/interface/delete-column.d.ts.map +1 -1
  572. package/dist/esm/interface/delete-column.js +26 -30
  573. package/dist/esm/interface/delete-row.d.ts +1 -1
  574. package/dist/esm/interface/delete-row.d.ts.map +1 -1
  575. package/dist/esm/interface/delete-row.js +191 -44
  576. package/dist/esm/interface/delete-sheet.d.ts +2 -2
  577. package/dist/esm/interface/delete-sheet.d.ts.map +1 -1
  578. package/dist/esm/interface/delete-sheet.js +113 -1
  579. package/dist/esm/interface/delete-table-column.d.ts +1 -1
  580. package/dist/esm/interface/delete-table-column.d.ts.map +1 -1
  581. package/dist/esm/interface/delete-table-column.js +11 -1
  582. package/dist/esm/interface/delete-table-row.d.ts +1 -1
  583. package/dist/esm/interface/delete-table-row.d.ts.map +1 -1
  584. package/dist/esm/interface/delete-table-row.js +312 -232
  585. package/dist/esm/interface/duplicate-sheet.d.ts.map +1 -1
  586. package/dist/esm/interface/duplicate-sheet.js +73 -26
  587. package/dist/esm/interface/embeds.d.ts +10 -1
  588. package/dist/esm/interface/embeds.d.ts.map +1 -1
  589. package/dist/esm/interface/embeds.js +84 -5
  590. package/dist/esm/interface/insert-cells-shift-down.d.ts +1 -1
  591. package/dist/esm/interface/insert-cells-shift-down.d.ts.map +1 -1
  592. package/dist/esm/interface/insert-cells-shift-down.js +10 -1
  593. package/dist/esm/interface/insert-cells-shift-right.d.ts +1 -1
  594. package/dist/esm/interface/insert-cells-shift-right.d.ts.map +1 -1
  595. package/dist/esm/interface/insert-cells-shift-right.js +10 -1
  596. package/dist/esm/interface/insert-column.d.ts +2 -2
  597. package/dist/esm/interface/insert-column.d.ts.map +1 -1
  598. package/dist/esm/interface/insert-column.js +70 -33
  599. package/dist/esm/interface/insert-row.d.ts +1 -1
  600. package/dist/esm/interface/insert-row.d.ts.map +1 -1
  601. package/dist/esm/interface/insert-row.js +22 -6
  602. package/dist/esm/interface/insert-table-row.d.ts +2 -1
  603. package/dist/esm/interface/insert-table-row.d.ts.map +1 -1
  604. package/dist/esm/interface/insert-table-row.js +67 -12
  605. package/dist/esm/interface/remove-duplicates.d.ts +1 -1
  606. package/dist/esm/interface/remove-duplicates.d.ts.map +1 -1
  607. package/dist/esm/interface/remove-duplicates.js +41 -6
  608. package/dist/esm/interface/remove-table.d.ts +1 -1
  609. package/dist/esm/interface/remove-table.d.ts.map +1 -1
  610. package/dist/esm/interface/remove-table.js +58 -10
  611. package/dist/esm/interface/slicers.d.ts +12 -1
  612. package/dist/esm/interface/slicers.d.ts.map +1 -1
  613. package/dist/esm/interface/slicers.js +44 -2
  614. package/dist/esm/interface/spreadsheet-interface.d.ts +1 -1
  615. package/dist/esm/interface/spreadsheet-interface.d.ts.map +1 -1
  616. package/dist/esm/interface/spreadsheet-interface.js +73 -1
  617. package/dist/esm/interface/table-totalrow.d.ts +13 -1
  618. package/dist/esm/interface/table-totalrow.d.ts.map +1 -1
  619. package/dist/esm/interface/table-totalrow.js +98 -68
  620. package/dist/esm/interface/table-utils.d.ts +59 -6
  621. package/dist/esm/interface/table-utils.d.ts.map +1 -1
  622. package/dist/esm/interface/table-utils.js +155 -14
  623. package/dist/esm/interface/update-table.d.ts +16 -1
  624. package/dist/esm/interface/update-table.d.ts.map +1 -1
  625. package/dist/esm/interface/update-table.js +203 -42
  626. package/dist/esm/sheet-cell.d.ts.map +1 -1
  627. package/dist/esm/test-setup.d.ts.map +1 -1
  628. package/dist/esm/test-setup.js +6 -0
  629. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  630. package/dist/esm/validation-schema/table.schema.d.ts +11 -0
  631. package/dist/esm/validation-schema/table.schema.d.ts.map +1 -1
  632. package/dist/esm/validation-schema/table.schema.js +15 -2
  633. package/package.json +25 -17
@@ -1,18 +1,25 @@
1
1
  import { isStaticNode } from "@rowsncolumns/dag";
2
- import { areaIntersects, isAreasEqual } from "@rowsncolumns/grid";
2
+ import { areaInsideArea, areaIntersects, isAreasEqual } from "@rowsncolumns/grid";
3
3
  import { selectionFromActiveCell } from "@rowsncolumns/grid";
4
4
  import { DEFAULT_COLUMN_COUNT, DEFAULT_ROW_COUNT, findActiveTableWithinCell, loadWebFont, MAX_COLUMN_COUNT, MAX_ROW_COUNT, useFocusEmbedOrChart, useGetFinalRowHeight, useRedrawGrid, } from "@rowsncolumns/spreadsheet";
5
5
  import { isSelectionACell, useGetEffectiveValuesFromRange, } from "@rowsncolumns/spreadsheet";
6
6
  import { error, getCellFormattedValue, getCellUserEnteredFormat, getCellUserEnteredValue, getExtendedValueBool, getExtendedValueFormula, getExtendedValueNumber, getExtendedValueString, isNil, iterateCellsInRange, uuidString, } from "@rowsncolumns/utils";
7
7
  import { produceWithPatches } from "immer";
8
8
  import { useCallback } from "react";
9
+ import { moveChartsOnRangeMove } from "../api/anchored-objects";
9
10
  import { processSideEffectDependentCells } from "../api/dependency";
10
11
  import { createSheetCellIdentifier } from "../api/formula";
11
12
  import { createSheetDraft } from "../api/immer-utils";
13
+ import { findPartiallyCoveredMerge, MERGED_CELL_MOVE_ERROR } from "../api/merges";
14
+ import { moveRange } from "../api/selection";
15
+ import { useShowError } from "../atoms/error-state.atom";
12
16
  import { applyPasteOperation, isBlankClipboardCell, resolvePasteSpecialOptions, } from "../api/paste-special";
13
- import { findAdjacentTable, findTableColumnIndex } from "../api/table";
14
- import { addCalculatedColumnsForRowExpansion } from "../interface/change-table-column";
17
+ import { getMoveRangeRefusal } from "../api/structural-guards";
18
+ import { renameHeaderCellsInFormulas } from "../api/structural-table-refs";
19
+ import { findAdjacentTable } from "../api/table";
20
+ import { getNextTableTitle } from "../helpers";
15
21
  import { collectDataValidationTarget, extendDataValidationRanges, } from "../interface/data-validation-utils";
22
+ import { planHeaderCellRenames } from "../interface/change-table-column";
16
23
  import { SheetCell } from "../sheet-cell";
17
24
  import { extractFontFamily, generateDataFromClipboard, pickFormatting, pickFormula, pickValue, transpose, } from "./../api/copy-paste";
18
25
  import { useCalculationQueue } from "./use-calculation-queue";
@@ -33,8 +40,9 @@ export const buildDestinationRowAssignments = (sheetId, startRowIndex, endRowInd
33
40
  }
34
41
  return assignments;
35
42
  };
36
- export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: currentTables, maxRowCount = MAX_ROW_COUNT, maxColumnCount = MAX_COLUMN_COUNT, isHiddenByFilterRow, onRequestFonts, idCreationStrategy, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeSelections, onChangeActiveCell, getDependents, getActiveCell, getUserEnteredValue, onChangeDataValidations, preserveFormatting = true, cellXfsRegistry, sharedStringRegistry, getDataValidationById, getSheetName, onError, citations, onChangeCitations, sanitizeHtml, onCommand, generatedNames, }) => {
43
+ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: currentTables, maxRowCount = MAX_ROW_COUNT, maxColumnCount = MAX_COLUMN_COUNT, isHiddenByFilterRow, onRequestFonts, idCreationStrategy, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeSelections, onChangeActiveCell, getDependents, getActiveCell, getUserEnteredValue, onChangeDataValidations, onChangeNamedRanges, onChangeCharts, getSheetMerges, preserveFormatting = true, cellXfsRegistry, sharedStringRegistry, getDataValidationById, getSheetName, onError, citations, onChangeCitations, sanitizeHtml, onCommand, generatedNames, batchHistory = (action) => action(), autoExpandTables = true, autoCalculatedColumns = true, }) => {
37
44
  const canEditCellRange = useCanEditCellRange();
45
+ const showError = useShowError();
38
46
  // Allowed values
39
47
  const getEffectiveValuesFromRange = useGetEffectiveValuesFromRange();
40
48
  const focusEmbedOrChart = useFocusEmbedOrChart();
@@ -47,6 +55,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
47
55
  onChangeTables,
48
56
  getSheetName,
49
57
  onCommand,
58
+ autoCalculatedColumns,
50
59
  });
51
60
  const onChangeTableColumn = useOnChangeTableColumn({
52
61
  locale,
@@ -55,9 +64,11 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
55
64
  enqueueGraphOperation,
56
65
  onChangeSheetData,
57
66
  onChangeTables,
67
+ onChangeCharts,
58
68
  getDependents,
59
69
  onCommand,
60
70
  generatedNames,
71
+ tables: currentTables,
61
72
  });
62
73
  const redrawGrid = useRedrawGrid();
63
74
  const getFinalRowHeight = useGetFinalRowHeight();
@@ -97,7 +108,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
97
108
  }
98
109
  }
99
110
  else {
100
- const pasteResults = await generateDataFromClipboard(e, activeCell, destinationSheetId, activeSheetName, preserveFormatting, locale, idCreationStrategy, forcePlainText, sanitizeHtml, generatedNames);
111
+ const pasteResults = await generateDataFromClipboard(e, activeCell, destinationSheetId, activeSheetName, preserveFormatting, locale, idCreationStrategy, forcePlainText, sanitizeHtml);
101
112
  selectedRowValues = pasteResults?.results ?? [];
102
113
  merges = pasteResults?.merges;
103
114
  embeds = pasteResults?.embeds;
@@ -121,8 +132,6 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
121
132
  else if (pasteMode === "values") {
122
133
  selectedRowValues = pickValue(selectedRowValues, destinationSheetId, locale);
123
134
  }
124
- const saveHistory = createHistory();
125
- const dataValidationTargets = new Map();
126
135
  const fontFamilies = extractFontFamily(selectedRowValues);
127
136
  // Wait for fonts to load
128
137
  if (fontFamilies.length && preserveFormatting) {
@@ -142,721 +151,887 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
142
151
  error("Error loading webfonts", fontFamilies, err);
143
152
  }
144
153
  }
145
- const [rowSpan, colSpan] = [
146
- selectedRowValues?.length ?? 0,
147
- // For cut operations, use range dimensions since data may be sparse
148
- isCutOperation && from
149
- ? from.range.endColumnIndex - from.range.startColumnIndex + 1
150
- : selectedRowValues[0]?.length ?? 0,
151
- ];
152
- const to = selections?.[selections?.length - 1] ??
153
- selectionFromActiveCell(activeCell)[0];
154
- const rowDelta = from && to ? to.range.startRowIndex - from.range.startRowIndex : -1;
155
- const columnDelta = from && to
156
- ? to.range.startColumnIndex - from.range.startColumnIndex
157
- : -1;
158
- // When user enters a value in the last row of a
159
- // table and if the entire row is empty
160
- const [adjacentTable, isRowExpansion, isColumnExpansion] = findAdjacentTable(destinationSheetId, activeCell, currentTables, getUserEnteredValue);
161
- const currentTable = isColumnExpansion && adjacentTable
162
- ? adjacentTable
163
- : findActiveTableWithinCell(destinationSheetId, activeCell, currentTables);
164
- // Next selections
165
- const nextSelections = finalSelections?.length ? finalSelections : [to];
166
- // Update range based on length of data
167
- to.range.endRowIndex = Math.min(maxRowCount, Math.max(to.range.endRowIndex, to.range.startRowIndex + rowSpan - 1));
168
- to.range.endColumnIndex = Math.min(maxColumnCount, Math.max(to.range.endColumnIndex, to.range.startColumnIndex + colSpan - 1));
169
- // Check for protected range
170
- if (!canEditCellRange(destinationSheetId, to.range)) {
171
- console.debug("Protected range, You cannot paste on to protected cells.");
172
- return;
173
- }
174
- // Check if pasting a table would overlap with an existing table
175
- if (tables?.length) {
176
- const existingTable = currentTables?.find((table) => table.sheetId === destinationSheetId &&
177
- areaIntersects(to.range, table.range));
178
- if (existingTable) {
179
- onError?.("Cannot paste a table over another table. The paste range overlaps with an existing table.");
154
+ // From here on the paste is synchronous: its writes and the table growth / calculated-column
155
+ // fill they trigger open ONE undo entry.
156
+ batchHistory(() => {
157
+ const saveHistory = createHistory();
158
+ const dataValidationTargets = new Map();
159
+ const [rowSpan, colSpan] = [
160
+ selectedRowValues?.length ?? 0,
161
+ // For cut operations, use range dimensions since data may be sparse
162
+ isCutOperation && from
163
+ ? from.range.endColumnIndex - from.range.startColumnIndex + 1
164
+ : selectedRowValues[0]?.length ?? 0,
165
+ ];
166
+ const to = selections?.[selections?.length - 1] ??
167
+ selectionFromActiveCell(activeCell)[0];
168
+ const rowDelta = from && to ? to.range.startRowIndex - from.range.startRowIndex : -1;
169
+ const columnDelta = from && to
170
+ ? to.range.startColumnIndex - from.range.startColumnIndex
171
+ : -1;
172
+ // A cut is a move: a table the cut block covers whole travels with it (Excel; the rnc
173
+ // engine's `move-range` does the same), so it is neither the table the paste writes into
174
+ // nor one the paste grows.
175
+ const movedTables = isCutOperation && from && !isNil(sourceSheetId)
176
+ ? currentTables?.filter((table) => table.sheetId === sourceSheetId &&
177
+ areaInsideArea(table.range, from.range)) ?? []
178
+ : [];
179
+ const stayingTables = movedTables.length
180
+ ? currentTables?.filter((table) => !movedTables.includes(table))
181
+ : currentTables;
182
+ // When user enters a value in the last row of a
183
+ // table and if the entire row is empty
184
+ const [adjacentTable, isRowExpansion, isColumnExpansion] = autoExpandTables
185
+ ? findAdjacentTable(destinationSheetId, activeCell, stayingTables, getUserEnteredValue)
186
+ : [undefined, false, false];
187
+ const currentTable = isColumnExpansion && adjacentTable
188
+ ? adjacentTable
189
+ : findActiveTableWithinCell(destinationSheetId, activeCell, stayingTables);
190
+ // Next selections
191
+ const nextSelections = finalSelections?.length ? finalSelections : [to];
192
+ // Update range based on length of data
193
+ to.range.endRowIndex = Math.min(maxRowCount, Math.max(to.range.endRowIndex, to.range.startRowIndex + rowSpan - 1));
194
+ to.range.endColumnIndex = Math.min(maxColumnCount, Math.max(to.range.endColumnIndex, to.range.startColumnIndex + colSpan - 1));
195
+ // Check for protected range
196
+ if (!canEditCellRange(destinationSheetId, to.range)) {
197
+ console.debug("Protected range, You cannot paste on to protected cells.");
180
198
  return;
181
199
  }
182
- }
183
- const destinationRows = buildDestinationRowAssignments(destinationSheetId, to.range.startRowIndex, to.range.endRowIndex, rowSpan, isHiddenByFilterRow);
184
- if (!destinationRows.length) {
185
- return;
186
- }
187
- // Paste writes through `onChangeSheetData` directly, so the
188
- // calculator's per-cell invalidation never fires for the
189
- // destination cells. Invalidate the destination rect — and the
190
- // source on cut, since those cells are cleared too.
191
- enqueueStructureChange?.({
192
- kind: "invalidate-range",
193
- sheetId: destinationSheetId,
194
- startRowIndex: to.range.startRowIndex,
195
- endRowIndex: to.range.endRowIndex,
196
- startColumnIndex: to.range.startColumnIndex,
197
- endColumnIndex: to.range.endColumnIndex,
198
- });
199
- if (isCutOperation && from && !isNil(sourceSheetId)) {
200
+ // A cut is a move: Excel refuses it when the destination (or the source) covers a merged
201
+ // cell only partially — writing into a non-anchor cell of a merge would tear it.
202
+ if (isCutOperation &&
203
+ from &&
204
+ !isNil(sourceSheetId) &&
205
+ (findPartiallyCoveredMerge(to.range, getSheetMerges?.(destinationSheetId)) ||
206
+ findPartiallyCoveredMerge(from.range, getSheetMerges?.(sourceSheetId)))) {
207
+ showError({ message: MERGED_CELL_MOVE_ERROR });
208
+ return;
209
+ }
210
+ // …and Excel never moves PART of a table, nor lands a block on another table's cells — the
211
+ // drag-move refusals (T-46) apply to a cut + paste too, across sheets (T-79).
212
+ if (isCutOperation && from && !isNil(sourceSheetId)) {
213
+ const tableRefusal = getMoveRangeRefusal({
214
+ sheetId: sourceSheetId,
215
+ from: from.range,
216
+ to: to.range,
217
+ toSheetId: destinationSheetId,
218
+ tables: currentTables,
219
+ });
220
+ if (tableRefusal) {
221
+ showError({ title: tableRefusal.title, message: tableRefusal.message });
222
+ return;
223
+ }
224
+ }
225
+ // Check if pasting a table would overlap with an existing table
226
+ if (tables?.length) {
227
+ const existingTable = currentTables?.find((table) => table.sheetId === destinationSheetId &&
228
+ areaIntersects(to.range, table.range));
229
+ if (existingTable) {
230
+ onError?.("Cannot paste a table over another table. The paste range overlaps with an existing table.");
231
+ return;
232
+ }
233
+ }
234
+ const destinationRows = buildDestinationRowAssignments(destinationSheetId, to.range.startRowIndex, to.range.endRowIndex, rowSpan, isHiddenByFilterRow);
235
+ if (!destinationRows.length) {
236
+ return;
237
+ }
238
+ // Paste writes through `onChangeSheetData` directly, so the
239
+ // calculator's per-cell invalidation never fires for the
240
+ // destination cells. Invalidate the destination rect — and the
241
+ // source on cut, since those cells are cleared too.
200
242
  enqueueStructureChange?.({
201
243
  kind: "invalidate-range",
202
- sheetId: sourceSheetId,
203
- startRowIndex: from.range.startRowIndex,
204
- endRowIndex: from.range.endRowIndex,
205
- startColumnIndex: from.range.startColumnIndex,
206
- endColumnIndex: from.range.endColumnIndex,
244
+ sheetId: destinationSheetId,
245
+ startRowIndex: to.range.startRowIndex,
246
+ endRowIndex: to.range.endRowIndex,
247
+ startColumnIndex: to.range.startColumnIndex,
248
+ endColumnIndex: to.range.endColumnIndex,
207
249
  });
208
- }
209
- const visibleRowIndexes = destinationRows.map(({ rowIndex }) => rowIndex);
210
- // Check if the user is editing a table column
211
- const tableHeaderColumnIndex = findTableColumnIndex(destinationSheetId, activeCell, currentTables);
212
- // Adds new column to table and cell to sheet
213
- const cellValue = selectedRowValues?.[0]?.[0];
214
- const formattedValue = getCellFormattedValue(cellValue);
215
- const sharedStrings = sharedStringRegistry?.getSharedStrings();
216
- const sharedStringValue = cellValue?.ss == null || !sharedStrings
217
- ? undefined
218
- : sharedStrings.get(String(cellValue.ss));
219
- const activeCellValue = typeof formattedValue === "string"
220
- ? formattedValue
221
- : typeof sharedStringValue === "string"
222
- ? sharedStringValue
250
+ if (isCutOperation && from && !isNil(sourceSheetId)) {
251
+ enqueueStructureChange?.({
252
+ kind: "invalidate-range",
253
+ sheetId: sourceSheetId,
254
+ startRowIndex: from.range.startRowIndex,
255
+ endRowIndex: from.range.endRowIndex,
256
+ startColumnIndex: from.range.startColumnIndex,
257
+ endColumnIndex: from.range.endColumnIndex,
258
+ });
259
+ }
260
+ const visibleRowIndexes = destinationRows.map(({ rowIndex }) => rowIndex);
261
+ // Adds new column to table and cell to sheet
262
+ const sharedStrings = sharedStringRegistry?.getSharedStrings();
263
+ const pastedCellText = (cellValue) => {
264
+ const formattedValue = getCellFormattedValue(cellValue);
265
+ const sharedStringValue = cellValue?.ss == null || !sharedStrings
266
+ ? undefined
267
+ : sharedStrings.get(String(cellValue.ss));
268
+ return typeof formattedValue === "string"
269
+ ? formattedValue
270
+ : typeof sharedStringValue === "string"
271
+ ? sharedStringValue
272
+ : undefined;
273
+ };
274
+ const activeCellValue = pastedCellText(selectedRowValues?.[0]?.[0]);
275
+ // A block pasted right of the table names every new column from its own header cell.
276
+ const pastedHeaderValues = isColumnExpansion &&
277
+ adjacentTable &&
278
+ activeCell.rowIndex === adjacentTable.range.startRowIndex
279
+ ? selectedRowValues?.[0]?.map(pastedCellText)
223
280
  : undefined;
224
- // We need to track this for history. Precedent cells
225
- const recalcCells = new Map();
226
- // Expand table if user is pasting
227
- // table data
228
- // Same undo history
229
- if (!isNil(currentTable) && !isRowExpansion) {
230
- const newEndRowIndex = Math.max(currentTable.range.endRowIndex, activeCell.rowIndex + rowSpan - 1 + (currentTable.totalRow ? 1 : 0));
231
- // Update table range
232
- onChangeTables?.((prevTableData) => {
233
- const [nextState, patches, inversePatches] = produceWithPatches(prevTableData, (draft) => {
234
- const table = draft.find((table) => currentTable?.id === table.id);
235
- if (table) {
236
- table.range.endRowIndex = newEndRowIndex;
237
- // Update table name
238
- if (!isNil(tableHeaderColumnIndex)) {
239
- if (table.columns?.length) {
240
- if (!table.columns[tableHeaderColumnIndex]) {
241
- table.columns[tableHeaderColumnIndex] = {
242
- name: String(activeCellValue),
243
- };
244
- }
245
- else {
246
- // Update name
247
- table.columns[tableHeaderColumnIndex].name =
248
- String(activeCellValue);
249
- }
250
- }
251
- }
281
+ // Header cells of existing tables the paste lands on take the typed-header
282
+ // rule (text, de-duplicated, structured references following); a cut moves
283
+ // cells as they are and a formats-only paste writes no values.
284
+ const headerRenames = !isCutOperation && pasteMode !== "formats"
285
+ ? planHeaderCellRenames({
286
+ sheetId: destinationSheetId,
287
+ tables: stayingTables,
288
+ generatedNames,
289
+ cells: destinationRows.flatMap(({ rowIndex, dataRowIndex }) => Array.from({
290
+ length: to.range.endColumnIndex - to.range.startColumnIndex + 1,
291
+ }, (_, cursor) => ({
292
+ rowIndex,
293
+ columnIndex: to.range.startColumnIndex + cursor,
294
+ value: pastedCellText(selectedRowValues[dataRowIndex]?.[colSpan > 0 ? cursor % colSpan : 0]),
295
+ }))),
296
+ })
297
+ : [];
298
+ const headerRenameAt = new Map(headerRenames.map((rename) => [
299
+ `${rename.rowIndex}:${rename.columnIndex}`,
300
+ rename,
301
+ ]));
302
+ // We need to track this for history. Precedent cells
303
+ const recalcCells = new Map();
304
+ // Expand table if user is pasting
305
+ // table data
306
+ // Same undo history
307
+ if (!isNil(currentTable) && !isRowExpansion) {
308
+ // The overflow grows the table row by row and stops at the first row another table
309
+ // occupies (Excel; same rule as the adjacent-row growth in `changeTableColumn`). Cells
310
+ // pasted past that row stay plain cells.
311
+ let newEndRowIndex = currentTable.range.endRowIndex;
312
+ const lastOverflowRowIndex = activeCell.rowIndex + rowSpan - 1 + (currentTable.totalRow ? 1 : 0);
313
+ for (let rowIndex = currentTable.range.endRowIndex + 1; rowIndex <= lastOverflowRowIndex; rowIndex++) {
314
+ const line = {
315
+ ...currentTable.range,
316
+ startRowIndex: rowIndex,
317
+ endRowIndex: rowIndex,
318
+ };
319
+ if (stayingTables?.some((other) => other.id !== currentTable.id &&
320
+ other.sheetId === destinationSheetId &&
321
+ areaIntersects(other.range, line))) {
322
+ break;
252
323
  }
253
- });
254
- saveHistory({
255
- tables: { patches, inversePatches },
256
- });
257
- return nextState;
258
- });
259
- }
260
- // Update sheetdata
261
- // Capture the produced state so we can stream the exact written cells to an engine
262
- // consumer afterwards (branch-agnostic across cut / pure-paste / paste-special).
263
- let pastedSheetData;
264
- if (selectedRowValues.length) {
265
- onChangeSheetData?.((prevSheetData) => {
266
- const [nextState, patches, inversePatches] = produceWithPatches(prevSheetData, (draft) => {
267
- // For cut operation
268
- const movedKeys = new Set();
269
- /**
270
- * If user is deleting source cells,
271
- * let update its dependents and mark it as dirty
272
- */
273
- if (isCutOperation && from && to && !isNil(sourceSheetId)) {
274
- const sheetId = sourceSheetId;
275
- for (const [rowIndex, columnIndex] of iterateCellsInRange(from.range)) {
276
- // Process dependents
277
- processSideEffectDependentCells({
278
- draft,
279
- rowIndex,
280
- columnIndex,
281
- sheetId,
282
- destinationSheetId,
283
- columnDelta,
284
- enqueueGraphOperation,
285
- enqueueCalculation: enqueue,
286
- getDependents,
287
- recalcCells,
288
- rowDelta,
289
- sourceRange: from.range,
290
- movedKeys,
291
- locale,
292
- rowCount,
293
- columnCount,
294
- });
295
- }
296
- // Snapshot source after dependent/formula rewrites, before
297
- // clearing it. The pre-cut clipboard snapshot still contains
298
- // stale formulas, so writing that snapshot would discard the
299
- // reference updates performed above.
300
- const movedRowValues = [];
301
- const sourceStartColumn = from.range.startColumnIndex;
302
- const sourceEndColumn = from.range.endColumnIndex + 1;
303
- for (let rowIndex = from.range.startRowIndex; rowIndex <= from.range.endRowIndex; rowIndex++) {
304
- movedRowValues.push((draft[sheetId]?.[rowIndex]?.values?.slice(sourceStartColumn, sourceEndColumn) ?? []));
324
+ newEndRowIndex = rowIndex;
325
+ }
326
+ // Update table range
327
+ onChangeTables?.((prevTableData) => {
328
+ const [nextState, patches, inversePatches] = produceWithPatches(prevTableData, (draft) => {
329
+ const table = draft.find((table) => currentTable?.id === table.id);
330
+ if (table) {
331
+ table.range.endRowIndex = newEndRowIndex;
305
332
  }
306
- // Delete source if required
307
- // Move values
308
- for (let rowIndex = from.range.startRowIndex; rowIndex <= from.range.endRowIndex; rowIndex++) {
309
- for (let columnIndex = from.range.startColumnIndex; columnIndex <= from.range.endColumnIndex; columnIndex++) {
310
- if (!draft[sheetId][rowIndex]?.values?.[columnIndex]) {
311
- continue;
312
- }
313
- draft[sheetId][rowIndex].values[columnIndex] =
314
- {};
333
+ });
334
+ saveHistory({
335
+ tables: { patches, inversePatches },
336
+ });
337
+ return nextState;
338
+ });
339
+ }
340
+ if (headerRenames.length) {
341
+ onChangeTables?.((prevTables) => {
342
+ const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
343
+ for (const { table, dimensionIndex, newName } of headerRenames) {
344
+ const current = draft.find((candidate) => candidate.id === table.id);
345
+ if (!current)
346
+ continue;
347
+ current.columns ??= [];
348
+ if (current.columns[dimensionIndex]) {
349
+ current.columns[dimensionIndex].name = newName;
350
+ }
351
+ else {
352
+ current.columns[dimensionIndex] = { name: newName };
315
353
  }
316
354
  }
317
- for (const { rowIndex, dataRowIndex } of destinationRows) {
318
- const currentSheet = createSheetDraft(draft, destinationSheetId, rowIndex);
319
- let columnCursor = 0;
320
- for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
321
- const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
322
- currentSheet[rowIndex].values[columnIndex] =
323
- movedRowValues[dataRowIndex]?.[dataColumnIndex];
324
- for (const dependent of getDependents({
355
+ });
356
+ saveHistory({ tables: { patches, inversePatches } });
357
+ return nextState;
358
+ });
359
+ }
360
+ // Update sheetdata
361
+ // Capture the produced state so we can stream the exact written cells to an engine
362
+ // consumer afterwards (branch-agnostic across cut / pure-paste / paste-special).
363
+ let pastedSheetData;
364
+ if (selectedRowValues.length) {
365
+ onChangeSheetData?.((prevSheetData) => {
366
+ const [nextState, patches, inversePatches] = produceWithPatches(prevSheetData, (draft) => {
367
+ // For cut operation
368
+ const movedKeys = new Set();
369
+ /**
370
+ * If user is deleting source cells,
371
+ * let update its dependents and mark it as dirty
372
+ */
373
+ if (isCutOperation && from && to && !isNil(sourceSheetId)) {
374
+ const sheetId = sourceSheetId;
375
+ for (const [rowIndex, columnIndex] of iterateCellsInRange(from.range)) {
376
+ // Process dependents
377
+ processSideEffectDependentCells({
378
+ draft,
325
379
  rowIndex,
326
380
  columnIndex,
327
- sheetId: destinationSheetId,
328
- })) {
329
- if (isStaticNode(dependent)) {
381
+ sheetId,
382
+ destinationSheetId,
383
+ columnDelta,
384
+ enqueueGraphOperation,
385
+ enqueueCalculation: enqueue,
386
+ getDependents,
387
+ recalcCells,
388
+ rowDelta,
389
+ sourceRange: from.range,
390
+ movedKeys,
391
+ locale,
392
+ rowCount,
393
+ columnCount,
394
+ });
395
+ }
396
+ // Snapshot source after dependent/formula rewrites, before
397
+ // clearing it. The pre-cut clipboard snapshot still contains
398
+ // stale formulas, so writing that snapshot would discard the
399
+ // reference updates performed above.
400
+ const movedRowValues = [];
401
+ const sourceStartColumn = from.range.startColumnIndex;
402
+ const sourceEndColumn = from.range.endColumnIndex + 1;
403
+ for (let rowIndex = from.range.startRowIndex; rowIndex <= from.range.endRowIndex; rowIndex++) {
404
+ movedRowValues.push((draft[sheetId]?.[rowIndex]?.values?.slice(sourceStartColumn, sourceEndColumn) ?? []));
405
+ }
406
+ // Delete source if required
407
+ // Move values
408
+ for (let rowIndex = from.range.startRowIndex; rowIndex <= from.range.endRowIndex; rowIndex++) {
409
+ for (let columnIndex = from.range.startColumnIndex; columnIndex <= from.range.endColumnIndex; columnIndex++) {
410
+ if (!draft[sheetId][rowIndex]?.values?.[columnIndex]) {
330
411
  continue;
331
412
  }
332
- const { position } = dependent;
333
- enqueue({
334
- type: "add",
335
- position,
336
- force: true,
337
- });
338
- recalcCells.set(createSheetCellIdentifier(position.sheetId, position.rowIndex, position.columnIndex), position);
413
+ draft[sheetId][rowIndex].values[columnIndex] =
414
+ {};
339
415
  }
340
- collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
341
416
  }
342
- }
343
- }
344
- if (currentTable && !isRowExpansion) {
345
- addCalculatedColumnsForRowExpansion({
346
- sheetId: destinationSheetId,
347
- currentTable,
348
- draft,
349
- enqueueCalculation: enqueue,
350
- recalcCells,
351
- locale,
352
- range: to.range,
353
- getDependents,
354
- });
355
- }
356
- // TBD: Move totalrow for tables
357
- // We are doing pure paste operation
358
- if (!isCutOperation) {
359
- const sheetCell = new SheetCell();
360
- const sourceCell = {
361
- rowIndex: to.range.startRowIndex,
362
- columnIndex: to.range.startColumnIndex,
363
- };
364
- for (const { rowIndex, dataRowIndex } of destinationRows) {
365
- const currentSheet = createSheetDraft(draft, destinationSheetId, rowIndex);
366
- let columnCursor = 0;
367
- for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
368
- const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
369
- let cellValue = selectedRowValues[dataRowIndex]?.[dataColumnIndex];
370
- // Skip blanks: an empty clipboard cell leaves the
371
- // destination (value and format) untouched.
372
- if (pasteSpecial.skipBlanks &&
373
- isBlankClipboardCell(cellValue)) {
374
- continue;
375
- }
376
- // Operation: combine the pasted cell with the cell it
377
- // lands on. The clipboard is anchored at the FIRST tile,
378
- // so a source formula is relocated to the tile it lands
379
- // on first (the same `moveFormula` shift the plain paste
380
- // applies below); the composed `=(dest)op(source)` is
381
- // then anchored at the destination and must not be moved
382
- // again (that would shift the destination fragment too).
383
- if (pasteOperation) {
384
- const sourceFormula = getExtendedValueFormula(getCellUserEnteredValue(cellValue));
385
- if (!isNil(sourceFormula) &&
386
- dataRowIndex === 0 &&
387
- dataColumnIndex === 0 &&
388
- (rowIndex !== sourceCell.rowIndex ||
389
- columnIndex !== sourceCell.columnIndex)) {
390
- const tileCell = new SheetCell();
391
- tileCell.setLocale(locale);
392
- tileCell.assign(destinationSheetId, sourceCell, cellValue);
393
- tileCell.moveFormula(sourceCell, { rowIndex, columnIndex }, activeSheetName, { preserveAbsolutes: true });
394
- cellValue = {
395
- ...cellValue,
396
- ue: { ...cellValue?.ue, fv: tileCell.formula },
397
- };
417
+ for (const { rowIndex, dataRowIndex } of destinationRows) {
418
+ const currentSheet = createSheetDraft(draft, destinationSheetId, rowIndex);
419
+ let columnCursor = 0;
420
+ for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
421
+ const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
422
+ currentSheet[rowIndex].values[columnIndex] =
423
+ movedRowValues[dataRowIndex]?.[dataColumnIndex];
424
+ for (const dependent of getDependents({
425
+ rowIndex,
426
+ columnIndex,
427
+ sheetId: destinationSheetId,
428
+ })) {
429
+ if (isStaticNode(dependent)) {
430
+ continue;
431
+ }
432
+ const { position } = dependent;
433
+ enqueue({
434
+ type: "add",
435
+ position,
436
+ force: true,
437
+ });
438
+ recalcCells.set(createSheetCellIdentifier(position.sheetId, position.rowIndex, position.columnIndex), position);
398
439
  }
399
- cellValue = applyPasteOperation(cellValue, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], pasteOperation, destinationSheetId, locale);
400
- }
401
- if (pasteMode === "formats") {
402
- const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
403
- cellValue = { ...existingCellData, ...cellValue };
404
- sheetCell.extendCellData(cellValue);
440
+ collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
405
441
  }
406
- if (pasteMode === "values" || forcePlainText) {
407
- const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
408
- // Remove ss from existingCellData since we're replacing the value
409
- const { ss: _ss, ...existingWithoutSs } = existingCellData ?? {};
410
- cellValue = { ...existingWithoutSs, ...cellValue };
411
- sheetCell.extendCellData(cellValue);
412
- }
413
- if (pasteSpecial.transpose && pasteMode === "all") {
414
- sheetCell.assign(destinationSheetId, { rowIndex, columnIndex }, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], {
415
- locale,
416
- cellXfsRegistry,
417
- getDataValidationById,
418
- sharedStringRegistry,
419
- });
420
- const existingCellData = sheetCell.getUserCellData();
421
- cellValue = { ...existingCellData, ...cellValue };
422
- sheetCell.extendCellData(cellValue);
423
- }
424
- else {
425
- sheetCell.assign(destinationSheetId, { rowIndex, columnIndex }, typeof cellValue === "object"
426
- ? cellValue
427
- : undefined, {
428
- getRangeValues: getEffectiveValuesFromRange,
429
- locale,
430
- cellXfsRegistry,
431
- getDataValidationById,
432
- sharedStringRegistry,
433
- });
434
- }
435
- if (pasteMode === "formats") {
436
- sheetCell.refreshFormattedValue();
437
- }
438
- if (sheetCell.isFormula()) {
439
- if (dataRowIndex === 0 &&
440
- dataColumnIndex === 0 &&
441
- !pasteOperation) {
442
- sheetCell.moveFormula(sourceCell, {
443
- rowIndex,
444
- columnIndex,
445
- }, activeSheetName, { preserveAbsolutes: true });
442
+ }
443
+ }
444
+ // TBD: Move totalrow for tables
445
+ // We are doing pure paste operation
446
+ if (!isCutOperation) {
447
+ renameHeaderCellsInFormulas({
448
+ draft,
449
+ headerRenames,
450
+ enqueueCalculation: enqueue,
451
+ enqueueGraphOperation,
452
+ recalcCells,
453
+ locale,
454
+ cellXfsRegistry,
455
+ sharedStringRegistry,
456
+ });
457
+ const sheetCell = new SheetCell();
458
+ const sourceCell = {
459
+ rowIndex: to.range.startRowIndex,
460
+ columnIndex: to.range.startColumnIndex,
461
+ };
462
+ for (const { rowIndex, dataRowIndex } of destinationRows) {
463
+ const currentSheet = createSheetDraft(draft, destinationSheetId, rowIndex);
464
+ let columnCursor = 0;
465
+ for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
466
+ const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
467
+ let cellValue = selectedRowValues[dataRowIndex]?.[dataColumnIndex];
468
+ // Skip blanks: an empty clipboard cell leaves the
469
+ // destination (value and format) untouched.
470
+ if (pasteSpecial.skipBlanks &&
471
+ isBlankClipboardCell(cellValue)) {
472
+ continue;
446
473
  }
447
- sheetCell.setLoading();
448
- enqueue({
449
- type: "add",
450
- position: {
474
+ // Operation: combine the pasted cell with the cell it
475
+ // lands on. The clipboard is anchored at the FIRST tile,
476
+ // so a source formula is relocated to the tile it lands
477
+ // on first (the same `moveFormula` shift the plain paste
478
+ // applies below); the composed `=(dest)op(source)` is
479
+ // then anchored at the destination and must not be moved
480
+ // again (that would shift the destination fragment too).
481
+ if (pasteOperation) {
482
+ const sourceFormula = getExtendedValueFormula(getCellUserEnteredValue(cellValue));
483
+ if (!isNil(sourceFormula) &&
484
+ dataRowIndex === 0 &&
485
+ dataColumnIndex === 0 &&
486
+ (rowIndex !== sourceCell.rowIndex ||
487
+ columnIndex !== sourceCell.columnIndex)) {
488
+ const tileCell = new SheetCell();
489
+ tileCell.setLocale(locale);
490
+ tileCell.assign(destinationSheetId, sourceCell, cellValue);
491
+ tileCell.moveFormula(sourceCell, { rowIndex, columnIndex }, activeSheetName, { preserveAbsolutes: true });
492
+ cellValue = {
493
+ ...cellValue,
494
+ ue: { ...cellValue?.ue, fv: tileCell.formula },
495
+ };
496
+ }
497
+ cellValue = applyPasteOperation(cellValue, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], pasteOperation, destinationSheetId, locale);
498
+ }
499
+ if (pasteMode === "formats") {
500
+ const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
501
+ cellValue = { ...existingCellData, ...cellValue };
502
+ sheetCell.extendCellData(cellValue);
503
+ }
504
+ if (pasteMode === "values" || forcePlainText) {
505
+ const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
506
+ // Remove ss from existingCellData since we're replacing the value
507
+ const { ss: _ss, ...existingWithoutSs } = existingCellData ?? {};
508
+ cellValue = { ...existingWithoutSs, ...cellValue };
509
+ sheetCell.extendCellData(cellValue);
510
+ }
511
+ if (pasteSpecial.transpose && pasteMode === "all") {
512
+ sheetCell.assign(destinationSheetId, { rowIndex, columnIndex }, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], {
513
+ locale,
514
+ cellXfsRegistry,
515
+ getDataValidationById,
516
+ sharedStringRegistry,
517
+ });
518
+ const existingCellData = sheetCell.getUserCellData();
519
+ cellValue = { ...existingCellData, ...cellValue };
520
+ sheetCell.extendCellData(cellValue);
521
+ }
522
+ else {
523
+ sheetCell.assign(destinationSheetId, { rowIndex, columnIndex }, typeof cellValue === "object"
524
+ ? cellValue
525
+ : undefined, {
526
+ getRangeValues: getEffectiveValuesFromRange,
527
+ locale,
528
+ cellXfsRegistry,
529
+ getDataValidationById,
530
+ sharedStringRegistry,
531
+ });
532
+ }
533
+ if (pasteMode === "formats") {
534
+ sheetCell.refreshFormattedValue();
535
+ }
536
+ if (sheetCell.isFormula()) {
537
+ if (dataRowIndex === 0 &&
538
+ dataColumnIndex === 0 &&
539
+ !pasteOperation) {
540
+ sheetCell.moveFormula(sourceCell, {
541
+ rowIndex,
542
+ columnIndex,
543
+ }, activeSheetName, { preserveAbsolutes: true });
544
+ }
545
+ sheetCell.setLoading();
546
+ enqueue({
547
+ type: "add",
548
+ position: {
549
+ rowIndex,
550
+ columnIndex,
551
+ sheetId: destinationSheetId,
552
+ },
553
+ force: true,
554
+ });
555
+ recalcCells.set(createSheetCellIdentifier(destinationSheetId, rowIndex, columnIndex), {
451
556
  rowIndex,
452
557
  columnIndex,
453
558
  sheetId: destinationSheetId,
454
- },
455
- force: true,
456
- });
457
- recalcCells.set(createSheetCellIdentifier(destinationSheetId, rowIndex, columnIndex), {
559
+ });
560
+ }
561
+ for (const dependent of getDependents({
458
562
  rowIndex,
459
563
  columnIndex,
460
564
  sheetId: destinationSheetId,
461
- });
462
- }
463
- for (const dependent of getDependents({
464
- rowIndex,
465
- columnIndex,
466
- sheetId: destinationSheetId,
467
- })) {
468
- if (isStaticNode(dependent)) {
469
- continue;
565
+ })) {
566
+ if (isStaticNode(dependent)) {
567
+ continue;
568
+ }
569
+ const { position } = dependent;
570
+ enqueue({
571
+ type: "add",
572
+ position,
573
+ force: true,
574
+ });
575
+ recalcCells.set(createSheetCellIdentifier(position.sheetId, position.rowIndex, position.columnIndex), position);
470
576
  }
471
- const { position } = dependent;
472
- enqueue({
473
- type: "add",
474
- position,
475
- force: true,
476
- });
477
- recalcCells.set(createSheetCellIdentifier(position.sheetId, position.rowIndex, position.columnIndex), position);
577
+ const headerRename = headerRenameAt.get(`${rowIndex}:${columnIndex}`);
578
+ if (headerRename) {
579
+ // A table header cell holds its column name as text.
580
+ sheetCell.setUserEnteredValue(headerRename.newName, undefined, { disableTypeInference: true });
581
+ }
582
+ sharedStringRegistry?.registerCell(sheetCell);
583
+ currentSheet[rowIndex].values[columnIndex] =
584
+ sheetCell.getCellData();
585
+ collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
586
+ cellXfsRegistry?.registerCellXfs(sheetCell);
478
587
  }
479
- sharedStringRegistry?.registerCell(sheetCell);
480
- currentSheet[rowIndex].values[columnIndex] =
481
- sheetCell.getCellData();
482
- collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
483
- cellXfsRegistry?.registerCellXfs(sheetCell);
484
588
  }
485
589
  }
486
- }
487
- });
488
- saveHistory({
489
- sheetData: { patches, inversePatches },
490
- recalcCells: { undo: recalcCells, redo: recalcCells },
491
- activeCell: {
492
- undo: getActiveCell(),
493
- redo: getActiveCell(),
494
- },
495
- selections: {
496
- undo: undefined,
497
- redo: isSelectionACell(nextSelections) ? undefined : [to],
498
- },
590
+ });
591
+ saveHistory({
592
+ sheetData: { patches, inversePatches },
593
+ recalcCells: { undo: recalcCells, redo: recalcCells },
594
+ activeCell: {
595
+ undo: getActiveCell(),
596
+ redo: getActiveCell(),
597
+ },
598
+ selections: {
599
+ undo: undefined,
600
+ redo: isSelectionACell(nextSelections) ? undefined : [to],
601
+ },
602
+ });
603
+ extendDataValidationRanges(dataValidationTargets, onChangeDataValidations, saveHistory);
604
+ processQueue();
605
+ pastedSheetData = nextState;
606
+ return nextState;
499
607
  });
500
- extendDataValidationRanges(dataValidationTargets, onChangeDataValidations, saveHistory);
501
- processQueue();
502
- pastedSheetData = nextState;
503
- return nextState;
504
- });
505
- // Save registries
506
- cellXfsRegistry?.getPatches(saveHistory);
507
- sharedStringRegistry?.getPatches(saveHistory);
508
- // Update row or column count
509
- // Change sheets
510
- onChangeSheets?.((prevSheets) => {
511
- const [nextState, patches, inversePatches] = produceWithPatches(prevSheets, (draft) => {
512
- const sheet = draft.find((sheet) => sheet.sheetId === destinationSheetId);
513
- if (sheet) {
514
- sheet.rowCount = Math.min(maxRowCount, Math.max(sheet.rowCount ?? DEFAULT_ROW_COUNT, to.range.endRowIndex));
515
- sheet.columnCount = Math.min(maxColumnCount, Math.max(sheet.columnCount ?? DEFAULT_COLUMN_COUNT, to.range.endColumnIndex));
516
- // Handle merges for cut operations
517
- let mergesToAdd = merges;
518
- if (isCutOperation && from && !isNil(sourceSheetId)) {
519
- const sourceSheet = prevSheets.find((s) => s.sheetId === sourceSheetId);
520
- if (sourceSheet?.merges) {
521
- // Extract merged cells from source range
522
- const cutMerges = [];
523
- for (const merge of sourceSheet.merges) {
524
- // Check if merge intersects with the cut range
525
- if (areaIntersects(merge, from.range)) {
526
- // Calculate new merge coordinates relative to destination
527
- cutMerges.push({
528
- startRowIndex: merge.startRowIndex + rowDelta,
529
- startColumnIndex: merge.startColumnIndex + columnDelta,
530
- endRowIndex: merge.endRowIndex + rowDelta,
531
- endColumnIndex: merge.endColumnIndex + columnDelta,
532
- });
608
+ // Save registries
609
+ cellXfsRegistry?.getPatches(saveHistory);
610
+ sharedStringRegistry?.getPatches(saveHistory);
611
+ // Update row or column count
612
+ // Change sheets
613
+ onChangeSheets?.((prevSheets) => {
614
+ const [nextState, patches, inversePatches] = produceWithPatches(prevSheets, (draft) => {
615
+ const sheet = draft.find((sheet) => sheet.sheetId === destinationSheetId);
616
+ if (sheet) {
617
+ sheet.rowCount = Math.min(maxRowCount, Math.max(sheet.rowCount ?? DEFAULT_ROW_COUNT, to.range.endRowIndex));
618
+ sheet.columnCount = Math.min(maxColumnCount, Math.max(sheet.columnCount ?? DEFAULT_COLUMN_COUNT, to.range.endColumnIndex));
619
+ // Handle merges for cut operations
620
+ let mergesToAdd = merges;
621
+ if (isCutOperation && from && !isNil(sourceSheetId)) {
622
+ const sourceSheet = prevSheets.find((s) => s.sheetId === sourceSheetId);
623
+ if (sourceSheet?.merges) {
624
+ // Extract merged cells from source range
625
+ const cutMerges = [];
626
+ for (const merge of sourceSheet.merges) {
627
+ // Check if merge intersects with the cut range
628
+ if (areaIntersects(merge, from.range)) {
629
+ // Calculate new merge coordinates relative to destination
630
+ cutMerges.push({
631
+ startRowIndex: merge.startRowIndex + rowDelta,
632
+ startColumnIndex: merge.startColumnIndex + columnDelta,
633
+ endRowIndex: merge.endRowIndex + rowDelta,
634
+ endColumnIndex: merge.endColumnIndex + columnDelta,
635
+ });
636
+ }
637
+ }
638
+ if (cutMerges.length > 0) {
639
+ mergesToAdd = cutMerges;
640
+ }
641
+ // Remove merges from source sheet
642
+ const sourceSheetDraft = draft.find((s) => s.sheetId === sourceSheetId);
643
+ if (sourceSheetDraft?.merges) {
644
+ sourceSheetDraft.merges = sourceSheetDraft.merges.filter((merge) => !areaIntersects(merge, from.range));
533
645
  }
534
- }
535
- if (cutMerges.length > 0) {
536
- mergesToAdd = cutMerges;
537
- }
538
- // Remove merges from source sheet
539
- const sourceSheetDraft = draft.find((s) => s.sheetId === sourceSheetId);
540
- if (sourceSheetDraft?.merges) {
541
- sourceSheetDraft.merges = sourceSheetDraft.merges.filter((merge) => !areaIntersects(merge, from.range));
542
646
  }
543
647
  }
544
- }
545
- // Update merges
546
- if (mergesToAdd) {
547
- sheet.merges = sheet.merges ?? [];
548
- for (const merge of mergesToAdd) {
549
- const exists = sheet.merges.find((range) => isAreasEqual(range, merge));
550
- if (!exists) {
551
- sheet.merges.push(merge);
648
+ // Update merges
649
+ if (mergesToAdd) {
650
+ sheet.merges = sheet.merges ?? [];
651
+ for (const merge of mergesToAdd) {
652
+ const exists = sheet.merges.find((range) => isAreasEqual(range, merge));
653
+ if (!exists) {
654
+ sheet.merges.push(merge);
655
+ }
552
656
  }
553
657
  }
554
- }
555
- // Row heights
556
- const clipboardSizedRows = new Set();
557
- if (rowHeights) {
558
- if (!sheet.rowMetadata) {
559
- sheet.rowMetadata = [];
560
- }
561
- for (let index = 0; index < rowHeights.length; index++) {
562
- const curHeight = rowHeights[index];
563
- if (isNil(curHeight) || curHeight === 0) {
564
- continue;
565
- }
566
- const rowIndex = visibleRowIndexes[index];
567
- if (isNil(rowIndex)) {
568
- break;
658
+ // Row heights
659
+ const clipboardSizedRows = new Set();
660
+ if (rowHeights) {
661
+ if (!sheet.rowMetadata) {
662
+ sheet.rowMetadata = [];
569
663
  }
570
- if (!sheet.rowMetadata[rowIndex]) {
571
- sheet.rowMetadata[rowIndex] = {};
572
- }
573
- sheet.rowMetadata[rowIndex].size = curHeight;
574
- clipboardSizedRows.add(rowIndex);
575
- }
576
- }
577
- // Auto-resize rows whose pasted content needs more room
578
- // (multi-line text or wrap). Mirrors use-on-change's
579
- // adjustRowHeight, but batched into this immer pass so the
580
- // whole paste collapses to one undo entry. Skip conditions
581
- // make the common single-line-text paste do zero work.
582
- // Skipped for paste-special variants since the destination
583
- // cell ends up as a merge of existing + pasted data, not
584
- // the raw pasted value we can read from selectedRowValues.
585
- const skipAutoResize = pasteSpecial.isSpecial;
586
- if (!skipAutoResize &&
587
- getFinalRowHeight &&
588
- selectedRowValues.length &&
589
- colSpan > 0) {
590
- for (const { rowIndex, dataRowIndex } of destinationRows) {
591
- // Clipboard-provided row heights win.
592
- if (clipboardSizedRows.has(rowIndex))
593
- continue;
594
- const rowData = selectedRowValues[dataRowIndex];
595
- if (!rowData)
596
- continue;
597
- // Find the cell most likely to drive row height —
598
- // most lines first, then any wrap. If no cell in
599
- // the row needs more than one line and no cell is
600
- // wrapped, the row's existing height already fits.
601
- let bestLines = 1;
602
- let bestColumnIndex;
603
- let bestCell;
604
- let bestHasWrap = false;
605
- let columnCursor = 0;
606
- for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
607
- const dataColumnIndex = columnCursor % colSpan;
608
- const cellValue = rowData[dataColumnIndex];
609
- if (!cellValue || typeof cellValue !== "object")
664
+ for (let index = 0; index < rowHeights.length; index++) {
665
+ const curHeight = rowHeights[index];
666
+ if (isNil(curHeight) || curHeight === 0) {
610
667
  continue;
611
- const ue = getCellUserEnteredValue(cellValue);
612
- const text = getExtendedValueString(ue);
613
- const lines = typeof text === "string" && text.includes("\n")
614
- ? text.split("\n").length
615
- : 1;
616
- const uf = getCellUserEnteredFormat(cellValue);
617
- const wrap = uf
618
- ?.wrapStrategy === "wrap";
619
- if (lines > bestLines ||
620
- (lines === bestLines && wrap && !bestHasWrap)) {
621
- bestLines = lines;
622
- bestCell = cellValue;
623
- bestColumnIndex = columnIndex;
624
- bestHasWrap = wrap;
625
668
  }
626
- }
627
- if (!bestCell ||
628
- bestColumnIndex === undefined ||
629
- (bestLines === 1 && !bestHasWrap)) {
630
- continue;
631
- }
632
- const ue = getCellUserEnteredValue(bestCell);
633
- const overrideText = getExtendedValueString(ue) ?? "";
634
- const uf = getCellUserEnteredFormat(bestCell);
635
- const height = getFinalRowHeight(destinationSheetId, rowIndex, bestColumnIndex, {
636
- textOverride: String(overrideText),
637
- textFormatOverride: uf?.textFormat,
638
- shouldWrapOverride: bestHasWrap,
639
- });
640
- if (typeof height === "number" && height > 0) {
641
- if (!sheet.rowMetadata)
642
- sheet.rowMetadata = [];
669
+ const rowIndex = visibleRowIndexes[index];
670
+ if (isNil(rowIndex)) {
671
+ break;
672
+ }
643
673
  if (!sheet.rowMetadata[rowIndex]) {
644
674
  sheet.rowMetadata[rowIndex] = {};
645
675
  }
646
- sheet.rowMetadata[rowIndex].size = height;
647
- sheet.rowMetadata[rowIndex].resizedByUser = false;
676
+ sheet.rowMetadata[rowIndex].size = curHeight;
677
+ clipboardSizedRows.add(rowIndex);
648
678
  }
649
679
  }
650
- }
651
- // column widths
652
- if (columnWidths) {
653
- if (!sheet.columnMetadata) {
654
- sheet.columnMetadata = [];
680
+ // Auto-resize rows whose pasted content needs more room
681
+ // (multi-line text or wrap). Mirrors use-on-change's
682
+ // adjustRowHeight, but batched into this immer pass so the
683
+ // whole paste collapses to one undo entry. Skip conditions
684
+ // make the common single-line-text paste do zero work.
685
+ // Skipped for paste-special variants since the destination
686
+ // cell ends up as a merge of existing + pasted data, not
687
+ // the raw pasted value we can read from selectedRowValues.
688
+ const skipAutoResize = pasteSpecial.isSpecial;
689
+ if (!skipAutoResize &&
690
+ getFinalRowHeight &&
691
+ selectedRowValues.length &&
692
+ colSpan > 0) {
693
+ for (const { rowIndex, dataRowIndex } of destinationRows) {
694
+ // Clipboard-provided row heights win.
695
+ if (clipboardSizedRows.has(rowIndex))
696
+ continue;
697
+ const rowData = selectedRowValues[dataRowIndex];
698
+ if (!rowData)
699
+ continue;
700
+ // Find the cell most likely to drive row height —
701
+ // most lines first, then any wrap. If no cell in
702
+ // the row needs more than one line and no cell is
703
+ // wrapped, the row's existing height already fits.
704
+ let bestLines = 1;
705
+ let bestColumnIndex;
706
+ let bestCell;
707
+ let bestHasWrap = false;
708
+ let columnCursor = 0;
709
+ for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
710
+ const dataColumnIndex = columnCursor % colSpan;
711
+ const cellValue = rowData[dataColumnIndex];
712
+ if (!cellValue || typeof cellValue !== "object")
713
+ continue;
714
+ const ue = getCellUserEnteredValue(cellValue);
715
+ const text = getExtendedValueString(ue);
716
+ const lines = typeof text === "string" && text.includes("\n")
717
+ ? text.split("\n").length
718
+ : 1;
719
+ const uf = getCellUserEnteredFormat(cellValue);
720
+ const wrap = uf
721
+ ?.wrapStrategy === "wrap";
722
+ if (lines > bestLines ||
723
+ (lines === bestLines && wrap && !bestHasWrap)) {
724
+ bestLines = lines;
725
+ bestCell = cellValue;
726
+ bestColumnIndex = columnIndex;
727
+ bestHasWrap = wrap;
728
+ }
729
+ }
730
+ if (!bestCell ||
731
+ bestColumnIndex === undefined ||
732
+ (bestLines === 1 && !bestHasWrap)) {
733
+ continue;
734
+ }
735
+ const ue = getCellUserEnteredValue(bestCell);
736
+ const overrideText = getExtendedValueString(ue) ?? "";
737
+ const uf = getCellUserEnteredFormat(bestCell);
738
+ const height = getFinalRowHeight(destinationSheetId, rowIndex, bestColumnIndex, {
739
+ textOverride: String(overrideText),
740
+ textFormatOverride: uf?.textFormat,
741
+ shouldWrapOverride: bestHasWrap,
742
+ });
743
+ if (typeof height === "number" && height > 0) {
744
+ if (!sheet.rowMetadata)
745
+ sheet.rowMetadata = [];
746
+ if (!sheet.rowMetadata[rowIndex]) {
747
+ sheet.rowMetadata[rowIndex] = {};
748
+ }
749
+ sheet.rowMetadata[rowIndex].size = height;
750
+ sheet.rowMetadata[rowIndex].resizedByUser = false;
751
+ }
752
+ }
655
753
  }
656
- for (let index = 0; index < columnWidths.length; index++) {
657
- const curWidth = columnWidths[index];
658
- if (isNil(curWidth) || curWidth === 0) {
659
- continue;
754
+ // column widths
755
+ if (columnWidths) {
756
+ if (!sheet.columnMetadata) {
757
+ sheet.columnMetadata = [];
660
758
  }
661
- const columnIndex = to.range.startColumnIndex + index;
662
- if (!sheet.columnMetadata?.[columnIndex]) {
663
- sheet.columnMetadata[columnIndex] = {};
759
+ for (let index = 0; index < columnWidths.length; index++) {
760
+ const curWidth = columnWidths[index];
761
+ if (isNil(curWidth) || curWidth === 0) {
762
+ continue;
763
+ }
764
+ const columnIndex = to.range.startColumnIndex + index;
765
+ if (!sheet.columnMetadata?.[columnIndex]) {
766
+ sheet.columnMetadata[columnIndex] = {};
767
+ }
768
+ sheet.columnMetadata[columnIndex].size =
769
+ columnWidths[index];
664
770
  }
665
- sheet.columnMetadata[columnIndex].size =
666
- columnWidths[index];
667
771
  }
668
772
  }
669
- }
670
- });
671
- saveHistory({
672
- sheets: { patches, inversePatches },
773
+ });
774
+ saveHistory({
775
+ sheets: { patches, inversePatches },
776
+ });
777
+ return nextState;
673
778
  });
674
- return nextState;
675
- });
676
- // For row expansions, add columns
677
- onChangeTableColumn(destinationSheetId, activeCell, activeCellValue ?? undefined, adjacentTable, isRowExpansion, isColumnExpansion, to.range);
678
- // Add calculated column
679
- onChangeCalculatedColumn(destinationSheetId, activeCell, activeCellValue ?? undefined, currentTable);
680
- // Update new selections
681
- if (!isSelectionACell(nextSelections)) {
682
- onChangeSelections?.(destinationSheetId, [to]);
683
- }
684
- // Update active cell
685
- onChangeActiveCell(destinationSheetId, { ...getActiveCell() });
686
- // Stream the paste to an engine consumer. The clipboard is a bounded payload (not
687
- // windowed), so paste can resolve the destination cells UI-side; we read back the
688
- // user-entered values the paste actually produced — relocated formulas, paste-special
689
- // merges, shared-string text — and replay them as a `change-batch` the engine recomputes
690
- // from. Reading the produced state (rather than re-deriving) keeps this correct across the
691
- // cut / pure-paste / paste-special branches without duplicating their logic.
692
- if (onCommand && pastedSheetData) {
693
- const values = [];
694
- for (let rowIndex = to.range.startRowIndex; rowIndex <= to.range.endRowIndex; rowIndex++) {
695
- const row = [];
696
- for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++) {
697
- const cell = pastedSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
698
- const ue = cell ? getCellUserEnteredValue(cell) : undefined;
699
- // Formula text wins (e.g. "=SUM(A1:A2)"), else the literal string / number / bool.
700
- // `??` (not `||`) so 0 and false survive; `null` clears the cell.
701
- row.push(getExtendedValueFormula(ue) ??
702
- getExtendedValueString(ue) ??
703
- getExtendedValueNumber(ue) ??
704
- getExtendedValueBool(ue) ??
705
- null);
706
- }
707
- values.push(row);
779
+ // For row expansions, add columns
780
+ onChangeTableColumn(destinationSheetId, activeCell, activeCellValue ?? undefined, adjacentTable, isRowExpansion, isColumnExpansion, to.range, pastedHeaderValues);
781
+ // Add calculated column
782
+ onChangeCalculatedColumn(destinationSheetId, activeCell, activeCellValue ?? undefined, currentTable);
783
+ // Update new selections
784
+ if (!isSelectionACell(nextSelections)) {
785
+ onChangeSelections?.(destinationSheetId, [to]);
708
786
  }
709
- onCommand({
710
- command: "change-batch",
711
- sheetId: destinationSheetId,
712
- ranges: to.range,
713
- values,
714
- });
715
- // On cut, the source cells were cleared — mirror that so the engine drops them too.
716
- if (isCutOperation && from && !isNil(sourceSheetId)) {
787
+ // Update active cell
788
+ onChangeActiveCell(destinationSheetId, { ...getActiveCell() });
789
+ // Stream the paste to an engine consumer. The clipboard is a bounded payload (not
790
+ // windowed), so paste can resolve the destination cells UI-side; we read back the
791
+ // user-entered values the paste actually produced — relocated formulas, paste-special
792
+ // merges, shared-string text — and replay them as a `change-batch` the engine recomputes
793
+ // from. Reading the produced state (rather than re-deriving) keeps this correct across the
794
+ // cut / pure-paste / paste-special branches without duplicating their logic.
795
+ if (onCommand && pastedSheetData) {
796
+ const values = [];
797
+ for (let rowIndex = to.range.startRowIndex; rowIndex <= to.range.endRowIndex; rowIndex++) {
798
+ const row = [];
799
+ for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++) {
800
+ const cell = pastedSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
801
+ const ue = cell ? getCellUserEnteredValue(cell) : undefined;
802
+ // Formula text wins (e.g. "=SUM(A1:A2)"), else the literal string / number / bool.
803
+ // `??` (not `||`) so 0 and false survive; `null` clears the cell.
804
+ row.push(getExtendedValueFormula(ue) ??
805
+ getExtendedValueString(ue) ??
806
+ getExtendedValueNumber(ue) ??
807
+ getExtendedValueBool(ue) ??
808
+ null);
809
+ }
810
+ values.push(row);
811
+ }
717
812
  onCommand({
718
- command: "delete-cells",
719
- sheetId: sourceSheetId,
720
- activeCell: {
721
- rowIndex: from.range.startRowIndex,
722
- columnIndex: from.range.startColumnIndex,
723
- },
724
- selections: [{ range: from.range }],
813
+ command: "change-batch",
814
+ sheetId: destinationSheetId,
815
+ ranges: to.range,
816
+ values,
817
+ ...(autoExpandTables ? {} : { autoExpandTables }),
818
+ ...(autoCalculatedColumns ? {} : { autoCalculatedColumns }),
725
819
  });
726
- }
727
- }
728
- }
729
- // Embeds
730
- if (embeds?.length) {
731
- const firstEmbedId = embeds[0].embedId;
732
- onChangeEmbeds?.((prevEmbeds) => {
733
- const [nextState, patches, inversePatches] = produceWithPatches(prevEmbeds, (draft) => {
734
- draft.push(...embeds);
735
- });
736
- saveHistory({
737
- embeds: { patches, inversePatches },
738
- selectedEmbedOrChart: { redo: firstEmbedId, undo: undefined },
739
- });
740
- return nextState;
741
- });
742
- // Selected first embed
743
- focusEmbedOrChart(embeds[0].embedId);
744
- }
745
- // Tables
746
- if (tables?.length) {
747
- onChangeTables?.((prevTables) => {
748
- const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
749
- draft.push(...tables);
750
- });
751
- saveHistory({
752
- tables: { patches, inversePatches },
753
- });
754
- return nextState;
755
- });
756
- }
757
- // Handle citations
758
- if (selectedRowValues.length && onChangeCitations) {
759
- // Collect citationIds from pasted cells
760
- const citationIdMap = new Map();
761
- for (let dataRowIndex = 0; dataRowIndex < rowSpan; dataRowIndex++) {
762
- const rowData = selectedRowValues[dataRowIndex];
763
- if (!rowData)
764
- continue;
765
- for (let dataColumnIndex = 0; dataColumnIndex < colSpan; dataColumnIndex++) {
766
- const cellValue = rowData[dataColumnIndex];
767
- if (cellValue &&
768
- typeof cellValue === "object" &&
769
- "citationId" in cellValue &&
770
- cellValue.citationId) {
771
- citationIdMap.set(cellValue.citationId, {
772
- sourceRowIndex: dataRowIndex,
773
- sourceColumnIndex: dataColumnIndex,
820
+ // On cut, the source cells were cleared — mirror that so the engine drops them too.
821
+ if (isCutOperation && from && !isNil(sourceSheetId)) {
822
+ onCommand({
823
+ command: "delete-cells",
824
+ sheetId: sourceSheetId,
825
+ activeCell: {
826
+ rowIndex: from.range.startRowIndex,
827
+ columnIndex: from.range.startColumnIndex,
828
+ },
829
+ selections: [{ range: from.range }],
774
830
  });
775
831
  }
776
832
  }
777
833
  }
778
- if (citationIdMap.size > 0) {
779
- if (isCutOperation && from && !isNil(sourceSheetId)) {
780
- // For cut operation: Move citations to new position
781
- onChangeCitations((prevCitations) => {
782
- const [nextState, patches, inversePatches] = produceWithPatches(prevCitations, (draft) => {
783
- for (const citationId of citationIdMap.keys()) {
784
- const citation = draft.find((c) => c.id === citationId);
785
- if (citation) {
786
- // Update citation range to new position
787
- citation.range.sheetId = destinationSheetId;
788
- citation.range.startRowIndex += rowDelta;
789
- citation.range.endRowIndex += rowDelta;
790
- citation.range.startColumnIndex += columnDelta;
791
- citation.range.endColumnIndex += columnDelta;
834
+ // Defined names wholly inside the cut block follow it (Excel move semantics); a name the
835
+ // block covers only partially keeps referring to its original area.
836
+ if (isCutOperation && from && !isNil(sourceSheetId)) {
837
+ onChangeNamedRanges?.((prevNamedRanges) => {
838
+ const [nextState, patches, inversePatches] = produceWithPatches(prevNamedRanges, (draft) => {
839
+ for (const namedRange of draft) {
840
+ if (namedRange.range?.sheetId === sourceSheetId &&
841
+ areaInsideArea(namedRange.range, from.range)) {
842
+ namedRange.range = {
843
+ ...moveRange(namedRange.range, from.range, to.range),
844
+ sheetId: destinationSheetId,
845
+ };
846
+ }
847
+ }
848
+ });
849
+ if (!patches.length) {
850
+ return prevNamedRanges;
851
+ }
852
+ saveHistory({ namedRanges: { patches, inversePatches } });
853
+ return nextState;
854
+ });
855
+ onChangeCharts?.((prevCharts) => {
856
+ const [nextState, patches, inversePatches] = produceWithPatches(prevCharts, (draft) => {
857
+ moveChartsOnRangeMove(draft, sourceSheetId, from.range, destinationSheetId, to.range);
858
+ });
859
+ if (!patches.length) {
860
+ return prevCharts;
861
+ }
862
+ saveHistory({ charts: { patches, inversePatches } });
863
+ return nextState;
864
+ });
865
+ // The tables the cut block covers whole move with their cells (same history step): the
866
+ // range lands at the destination — on another sheet too — and the column-indexed filter
867
+ // and sort specs follow it, so the table's filters and its structured references keep
868
+ // resolving there.
869
+ if (movedTables.length) {
870
+ const columnDelta = to.range.startColumnIndex - from.range.startColumnIndex;
871
+ onChangeTables?.((prevTables) => {
872
+ const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
873
+ for (const table of draft) {
874
+ if (!movedTables.some((moved) => moved.id === table.id)) {
875
+ continue;
876
+ }
877
+ table.sheetId = destinationSheetId;
878
+ const range = moveRange(table.range, from.range, to.range);
879
+ table.range =
880
+ "sheetId" in range
881
+ ? { ...range, sheetId: destinationSheetId }
882
+ : range;
883
+ for (const spec of table.filterSpecs ?? []) {
884
+ spec.columnIndex += columnDelta;
885
+ }
886
+ for (const spec of table.sortSpecs ?? []) {
887
+ spec.dimensionIndex += columnDelta;
792
888
  }
793
889
  }
794
890
  });
795
- saveHistory({
796
- citations: { patches, inversePatches },
797
- });
891
+ saveHistory({ tables: { patches, inversePatches } });
798
892
  return nextState;
799
893
  });
800
894
  }
801
- else if (!isCutOperation) {
802
- // For paste (copy) operation: Create new citations with new IDs
803
- const newCitations = [];
804
- const citationIdRemap = new Map();
805
- for (const [oldCitationId, { sourceRowIndex, sourceColumnIndex },] of citationIdMap.entries()) {
806
- const originalCitation = citations?.find((c) => c.id === oldCitationId);
807
- if (originalCitation) {
808
- const newId = uuidString();
809
- citationIdRemap.set(oldCitationId, newId);
810
- // Calculate the new range based on paste destination
811
- const newCitation = {
812
- ...originalCitation,
813
- id: newId,
814
- range: {
815
- sheetId: destinationSheetId,
816
- startRowIndex: to.range.startRowIndex + sourceRowIndex,
817
- endRowIndex: to.range.startRowIndex + sourceRowIndex,
818
- startColumnIndex: to.range.startColumnIndex + sourceColumnIndex,
819
- endColumnIndex: to.range.startColumnIndex + sourceColumnIndex,
820
- },
821
- };
822
- newCitations.push(newCitation);
895
+ }
896
+ // Embeds
897
+ if (embeds?.length) {
898
+ const firstEmbedId = embeds[0].embedId;
899
+ onChangeEmbeds?.((prevEmbeds) => {
900
+ const [nextState, patches, inversePatches] = produceWithPatches(prevEmbeds, (draft) => {
901
+ draft.push(...embeds);
902
+ });
903
+ saveHistory({
904
+ embeds: { patches, inversePatches },
905
+ selectedEmbedOrChart: { redo: firstEmbedId, undo: undefined },
906
+ });
907
+ return nextState;
908
+ });
909
+ // Selected first embed
910
+ focusEmbedOrChart(embeds[0].embedId);
911
+ }
912
+ // Tables
913
+ if (tables?.length) {
914
+ onChangeTables?.((prevTables) => {
915
+ const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
916
+ // Excel names a pasted table like a new one — the next free `TableN` — never
917
+ // `Copy of <title>`, which is not a valid table name (it has a space).
918
+ for (const table of tables) {
919
+ draft.push({
920
+ ...table,
921
+ title: getNextTableTitle(draft, generatedNames),
922
+ });
923
+ }
924
+ });
925
+ saveHistory({
926
+ tables: { patches, inversePatches },
927
+ });
928
+ return nextState;
929
+ });
930
+ }
931
+ // Handle citations
932
+ if (selectedRowValues.length && onChangeCitations) {
933
+ // Collect citationIds from pasted cells
934
+ const citationIdMap = new Map();
935
+ for (let dataRowIndex = 0; dataRowIndex < rowSpan; dataRowIndex++) {
936
+ const rowData = selectedRowValues[dataRowIndex];
937
+ if (!rowData)
938
+ continue;
939
+ for (let dataColumnIndex = 0; dataColumnIndex < colSpan; dataColumnIndex++) {
940
+ const cellValue = rowData[dataColumnIndex];
941
+ if (cellValue &&
942
+ typeof cellValue === "object" &&
943
+ "citationId" in cellValue &&
944
+ cellValue.citationId) {
945
+ citationIdMap.set(cellValue.citationId, {
946
+ sourceRowIndex: dataRowIndex,
947
+ sourceColumnIndex: dataColumnIndex,
948
+ });
823
949
  }
824
950
  }
825
- if (newCitations.length > 0) {
826
- // Add new citations
951
+ }
952
+ if (citationIdMap.size > 0) {
953
+ if (isCutOperation && from && !isNil(sourceSheetId)) {
954
+ // For cut operation: Move citations to new position
827
955
  onChangeCitations((prevCitations) => {
828
956
  const [nextState, patches, inversePatches] = produceWithPatches(prevCitations, (draft) => {
829
- draft.push(...newCitations);
957
+ for (const citationId of citationIdMap.keys()) {
958
+ const citation = draft.find((c) => c.id === citationId);
959
+ if (citation) {
960
+ // Update citation range to new position
961
+ citation.range.sheetId = destinationSheetId;
962
+ citation.range.startRowIndex += rowDelta;
963
+ citation.range.endRowIndex += rowDelta;
964
+ citation.range.startColumnIndex += columnDelta;
965
+ citation.range.endColumnIndex += columnDelta;
966
+ }
967
+ }
830
968
  });
831
969
  saveHistory({
832
970
  citations: { patches, inversePatches },
833
971
  });
834
972
  return nextState;
835
973
  });
836
- // Update cell citationIds to point to new citations
837
- onChangeSheetData?.((prevSheetData) => {
838
- const [nextState, patches, inversePatches] = produceWithPatches(prevSheetData, (draft) => {
839
- for (const { rowIndex } of destinationRows) {
840
- for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++) {
841
- const cellData = draft[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
842
- if (cellData?.citationId) {
843
- const newCitationId = citationIdRemap.get(cellData.citationId);
844
- if (newCitationId) {
845
- cellData.citationId = newCitationId;
974
+ }
975
+ else if (!isCutOperation) {
976
+ // For paste (copy) operation: Create new citations with new IDs
977
+ const newCitations = [];
978
+ const citationIdRemap = new Map();
979
+ for (const [oldCitationId, { sourceRowIndex, sourceColumnIndex },] of citationIdMap.entries()) {
980
+ const originalCitation = citations?.find((c) => c.id === oldCitationId);
981
+ if (originalCitation) {
982
+ const newId = uuidString();
983
+ citationIdRemap.set(oldCitationId, newId);
984
+ // Calculate the new range based on paste destination
985
+ const newCitation = {
986
+ ...originalCitation,
987
+ id: newId,
988
+ range: {
989
+ sheetId: destinationSheetId,
990
+ startRowIndex: to.range.startRowIndex + sourceRowIndex,
991
+ endRowIndex: to.range.startRowIndex + sourceRowIndex,
992
+ startColumnIndex: to.range.startColumnIndex + sourceColumnIndex,
993
+ endColumnIndex: to.range.startColumnIndex + sourceColumnIndex,
994
+ },
995
+ };
996
+ newCitations.push(newCitation);
997
+ }
998
+ }
999
+ if (newCitations.length > 0) {
1000
+ // Add new citations
1001
+ onChangeCitations((prevCitations) => {
1002
+ const [nextState, patches, inversePatches] = produceWithPatches(prevCitations, (draft) => {
1003
+ draft.push(...newCitations);
1004
+ });
1005
+ saveHistory({
1006
+ citations: { patches, inversePatches },
1007
+ });
1008
+ return nextState;
1009
+ });
1010
+ // Update cell citationIds to point to new citations
1011
+ onChangeSheetData?.((prevSheetData) => {
1012
+ const [nextState, patches, inversePatches] = produceWithPatches(prevSheetData, (draft) => {
1013
+ for (const { rowIndex } of destinationRows) {
1014
+ for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++) {
1015
+ const cellData = draft[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
1016
+ if (cellData?.citationId) {
1017
+ const newCitationId = citationIdRemap.get(cellData.citationId);
1018
+ if (newCitationId) {
1019
+ cellData.citationId = newCitationId;
1020
+ }
846
1021
  }
847
1022
  }
848
1023
  }
849
- }
850
- });
851
- saveHistory({
852
- sheetData: { patches, inversePatches },
1024
+ });
1025
+ saveHistory({
1026
+ sheetData: { patches, inversePatches },
1027
+ });
1028
+ return nextState;
853
1029
  });
854
- return nextState;
855
- });
1030
+ }
856
1031
  }
857
1032
  }
858
1033
  }
859
- }
1034
+ });
860
1035
  }, [
861
1036
  rowCount,
862
1037
  columnCount,
@@ -873,6 +1048,9 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
873
1048
  onRequestFonts,
874
1049
  idCreationStrategy,
875
1050
  createHistory,
1051
+ batchHistory,
1052
+ autoExpandTables,
1053
+ autoCalculatedColumns,
876
1054
  enqueueStructureChange,
877
1055
  enqueueGraphOperation,
878
1056
  onChangeCalculatedColumn,
@@ -899,5 +1077,9 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
899
1077
  getFinalRowHeight,
900
1078
  onCommand,
901
1079
  generatedNames,
1080
+ onChangeNamedRanges,
1081
+ onChangeCharts,
1082
+ getSheetMerges,
1083
+ showError,
902
1084
  ]);
903
1085
  };