@rowsncolumns/spreadsheet 10.6.4 → 10.7.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 (308) hide show
  1. package/dist/cjs/api/autocomplete.d.ts +42 -0
  2. package/dist/cjs/api/autocomplete.d.ts.map +1 -0
  3. package/dist/cjs/api/autocomplete.js +114 -0
  4. package/dist/cjs/api/banded-ranges.d.ts.map +1 -1
  5. package/dist/cjs/api/banded-ranges.js +51 -1
  6. package/dist/cjs/api/error-checking.d.ts +82 -0
  7. package/dist/cjs/api/error-checking.d.ts.map +1 -0
  8. package/dist/cjs/api/error-checking.js +207 -0
  9. package/dist/cjs/api/move-overwrite.d.ts +8 -2
  10. package/dist/cjs/api/move-overwrite.d.ts.map +1 -1
  11. package/dist/cjs/api/move-overwrite.js +19 -3
  12. package/dist/cjs/api/selections.d.ts +2 -2
  13. package/dist/cjs/api/validation.d.ts +39 -1
  14. package/dist/cjs/api/validation.d.ts.map +1 -1
  15. package/dist/cjs/api/validation.js +87 -1
  16. package/dist/cjs/atoms/cell-input-context.atom.d.ts +4 -1
  17. package/dist/cjs/atoms/cell-input-context.atom.d.ts.map +1 -1
  18. package/dist/cjs/atoms/enter-key-direction.atom.d.ts +11 -0
  19. package/dist/cjs/atoms/enter-key-direction.atom.d.ts.map +1 -0
  20. package/dist/cjs/atoms/enter-key-direction.atom.js +13 -0
  21. package/dist/cjs/atoms/index.d.ts +1 -0
  22. package/dist/cjs/atoms/index.d.ts.map +1 -1
  23. package/dist/cjs/atoms/index.js +1 -0
  24. package/dist/cjs/atoms/paste-menu.atom.d.ts +22 -0
  25. package/dist/cjs/atoms/paste-menu.atom.d.ts.map +1 -1
  26. package/dist/cjs/atoms/paste-menu.atom.js +13 -1
  27. package/dist/cjs/atoms/pick-list.atom.d.ts +15 -0
  28. package/dist/cjs/atoms/pick-list.atom.d.ts.map +1 -0
  29. package/dist/cjs/atoms/pick-list.atom.js +7 -0
  30. package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
  31. package/dist/cjs/components/canvas-grid/index.js +305 -70
  32. package/dist/cjs/components/canvas-grid/typings.d.ts +96 -11
  33. package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
  34. package/dist/cjs/components/cell/alignment.d.ts +25 -0
  35. package/dist/cjs/components/cell/alignment.d.ts.map +1 -1
  36. package/dist/cjs/components/cell/alignment.js +39 -1
  37. package/dist/cjs/components/cell/cell-background.d.ts +16 -0
  38. package/dist/cjs/components/cell/cell-background.d.ts.map +1 -1
  39. package/dist/cjs/components/cell/cell-background.js +141 -54
  40. package/dist/cjs/components/cell/cell-text-runs.d.ts +12 -5
  41. package/dist/cjs/components/cell/cell-text-runs.d.ts.map +1 -1
  42. package/dist/cjs/components/cell/cell-text-runs.js +18 -20
  43. package/dist/cjs/components/cell/index.d.ts.map +1 -1
  44. package/dist/cjs/components/cell/index.js +26 -21
  45. package/dist/cjs/components/cell/typings.d.ts +9 -0
  46. package/dist/cjs/components/cell/typings.d.ts.map +1 -1
  47. package/dist/cjs/components/cell-editor/helpers.d.ts +22 -2
  48. package/dist/cjs/components/cell-editor/helpers.d.ts.map +1 -1
  49. package/dist/cjs/components/cell-editor/helpers.js +32 -8
  50. package/dist/cjs/components/cell-editor/index.d.ts +7 -1
  51. package/dist/cjs/components/cell-editor/index.d.ts.map +1 -1
  52. package/dist/cjs/components/cell-editor/index.js +85 -13
  53. package/dist/cjs/components/cell-indicator/index.d.ts +41 -0
  54. package/dist/cjs/components/cell-indicator/index.d.ts.map +1 -0
  55. package/dist/cjs/components/cell-indicator/index.js +90 -0
  56. package/dist/cjs/components/cell-input/cell-input.d.ts +10 -2
  57. package/dist/cjs/components/cell-input/cell-input.d.ts.map +1 -1
  58. package/dist/cjs/components/cell-input/cell-input.js +5 -3
  59. package/dist/cjs/components/cell-input/formula-bar-cell-input.d.ts.map +1 -1
  60. package/dist/cjs/components/cell-input/formula-bar-cell-input.js +9 -2
  61. package/dist/cjs/components/cell-structured/sparkline-math.d.ts +27 -1
  62. package/dist/cjs/components/cell-structured/sparkline-math.d.ts.map +1 -1
  63. package/dist/cjs/components/cell-structured/sparkline-math.js +48 -1
  64. package/dist/cjs/components/cell-structured/sparkline.d.ts +1 -1
  65. package/dist/cjs/components/cell-structured/sparkline.d.ts.map +1 -1
  66. package/dist/cjs/components/cell-structured/sparkline.js +36 -92
  67. package/dist/cjs/components/cell-structured/types.d.ts +6 -0
  68. package/dist/cjs/components/cell-structured/types.d.ts.map +1 -1
  69. package/dist/cjs/components/data-table-dialog/index.d.ts +22 -0
  70. package/dist/cjs/components/data-table-dialog/index.d.ts.map +1 -0
  71. package/dist/cjs/components/data-table-dialog/index.js +93 -0
  72. package/dist/cjs/components/error-check-smart-tag/index.d.ts +27 -0
  73. package/dist/cjs/components/error-check-smart-tag/index.d.ts.map +1 -0
  74. package/dist/cjs/components/error-check-smart-tag/index.js +39 -0
  75. package/dist/cjs/components/forecast-sheet-dialog/index.d.ts +26 -0
  76. package/dist/cjs/components/forecast-sheet-dialog/index.d.ts.map +1 -0
  77. package/dist/cjs/components/forecast-sheet-dialog/index.js +92 -0
  78. package/dist/cjs/components/paste-special-dialog/index.d.ts +3 -3
  79. package/dist/cjs/components/paste-special-dialog/index.d.ts.map +1 -1
  80. package/dist/cjs/components/paste-special-dialog/index.js +61 -23
  81. package/dist/cjs/components/protect-sheet-dialog/allow-edit-ranges-dialog.d.ts +57 -0
  82. package/dist/cjs/components/protect-sheet-dialog/allow-edit-ranges-dialog.d.ts.map +1 -0
  83. package/dist/cjs/components/protect-sheet-dialog/allow-edit-ranges-dialog.js +196 -0
  84. package/dist/cjs/components/protect-sheet-dialog/constants.d.ts +3 -0
  85. package/dist/cjs/components/protect-sheet-dialog/constants.d.ts.map +1 -0
  86. package/dist/cjs/components/protect-sheet-dialog/constants.js +5 -0
  87. package/dist/cjs/components/protect-sheet-dialog/index.d.ts +2 -2
  88. package/dist/cjs/components/protect-sheet-dialog/index.d.ts.map +1 -1
  89. package/dist/cjs/components/protect-sheet-dialog/index.js +5 -3
  90. package/dist/cjs/components/scenario-manager-dialog/index.d.ts +51 -0
  91. package/dist/cjs/components/scenario-manager-dialog/index.d.ts.map +1 -0
  92. package/dist/cjs/components/scenario-manager-dialog/index.js +257 -0
  93. package/dist/cjs/components/selection/index.d.ts +1 -1
  94. package/dist/cjs/components/selection/index.d.ts.map +1 -1
  95. package/dist/cjs/components/selection/index.js +9 -4
  96. package/dist/cjs/components/selection/paste-menu.d.ts +14 -1
  97. package/dist/cjs/components/selection/paste-menu.d.ts.map +1 -1
  98. package/dist/cjs/components/selection/paste-menu.js +78 -6
  99. package/dist/cjs/components/selection/paste-options.d.ts +28 -0
  100. package/dist/cjs/components/selection/paste-options.d.ts.map +1 -0
  101. package/dist/cjs/components/selection/paste-options.js +70 -0
  102. package/dist/cjs/components/selection/types.d.ts +12 -1
  103. package/dist/cjs/components/selection/types.d.ts.map +1 -1
  104. package/dist/cjs/components/selection-drop-menu/index.d.ts +18 -0
  105. package/dist/cjs/components/selection-drop-menu/index.d.ts.map +1 -0
  106. package/dist/cjs/components/selection-drop-menu/index.js +62 -0
  107. package/dist/cjs/components/solver-dialog/index.d.ts +57 -0
  108. package/dist/cjs/components/solver-dialog/index.d.ts.map +1 -0
  109. package/dist/cjs/components/solver-dialog/index.js +204 -0
  110. package/dist/cjs/components/toolbar/sparkline-actions.d.ts +3 -2
  111. package/dist/cjs/components/toolbar/sparkline-actions.d.ts.map +1 -1
  112. package/dist/cjs/components/toolbar/sparkline-actions.js +6 -2
  113. package/dist/cjs/components/toolbar/table-style-selector.d.ts.map +1 -1
  114. package/dist/cjs/components/toolbar/table-style-selector.js +33 -2
  115. package/dist/cjs/config.d.ts +5 -4
  116. package/dist/cjs/config.d.ts.map +1 -1
  117. package/dist/cjs/config.js +13 -9
  118. package/dist/cjs/helpers.d.ts +5 -0
  119. package/dist/cjs/helpers.d.ts.map +1 -1
  120. package/dist/cjs/helpers.js +8 -4
  121. package/dist/cjs/hooks/use-cell-renderer.d.ts +12 -1
  122. package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -1
  123. package/dist/cjs/hooks/use-cell-renderer.js +6 -3
  124. package/dist/cjs/hooks/use-copy-paste-cut.d.ts +36 -2
  125. package/dist/cjs/hooks/use-copy-paste-cut.d.ts.map +1 -1
  126. package/dist/cjs/hooks/use-copy-paste-cut.js +131 -5
  127. package/dist/cjs/hooks/use-editable.d.ts +6 -0
  128. package/dist/cjs/hooks/use-editable.d.ts.map +1 -1
  129. package/dist/cjs/hooks/use-editor-submit.d.ts +45 -3
  130. package/dist/cjs/hooks/use-editor-submit.d.ts.map +1 -1
  131. package/dist/cjs/hooks/use-editor-submit.js +91 -7
  132. package/dist/cjs/hooks/use-keyboard-handler.d.ts +5 -1
  133. package/dist/cjs/hooks/use-keyboard-handler.d.ts.map +1 -1
  134. package/dist/cjs/hooks/use-keyboard-handler.js +10 -1
  135. package/dist/cjs/hooks/use-selection-drag-copy.d.ts +55 -0
  136. package/dist/cjs/hooks/use-selection-drag-copy.d.ts.map +1 -0
  137. package/dist/cjs/hooks/use-selection-drag-copy.js +274 -0
  138. package/dist/cjs/hooks/use-selection-renderer.d.ts +8 -1
  139. package/dist/cjs/hooks/use-selection-renderer.d.ts.map +1 -1
  140. package/dist/cjs/hooks/use-selection-renderer.js +7 -2
  141. package/dist/cjs/hooks/use-selection.d.ts +59 -1
  142. package/dist/cjs/hooks/use-selection.d.ts.map +1 -1
  143. package/dist/cjs/hooks/use-selection.js +270 -61
  144. package/dist/cjs/index.d.ts +6 -1
  145. package/dist/cjs/index.d.ts.map +1 -1
  146. package/dist/cjs/index.js +5 -0
  147. package/dist/cjs/release-date.js +1 -1
  148. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  149. package/dist/cjs/types.d.ts +50 -1
  150. package/dist/cjs/types.d.ts.map +1 -1
  151. package/dist/esm/api/autocomplete.d.ts +42 -0
  152. package/dist/esm/api/autocomplete.d.ts.map +1 -0
  153. package/dist/esm/api/autocomplete.js +91 -0
  154. package/dist/esm/api/banded-ranges.d.ts.map +1 -1
  155. package/dist/esm/api/banded-ranges.js +52 -2
  156. package/dist/esm/api/error-checking.d.ts +82 -0
  157. package/dist/esm/api/error-checking.d.ts.map +1 -0
  158. package/dist/esm/api/error-checking.js +156 -0
  159. package/dist/esm/api/move-overwrite.d.ts +8 -2
  160. package/dist/esm/api/move-overwrite.d.ts.map +1 -1
  161. package/dist/esm/api/move-overwrite.js +17 -2
  162. package/dist/esm/api/selections.d.ts +2 -2
  163. package/dist/esm/api/validation.d.ts +39 -1
  164. package/dist/esm/api/validation.d.ts.map +1 -1
  165. package/dist/esm/api/validation.js +70 -0
  166. package/dist/esm/atoms/cell-input-context.atom.d.ts +4 -1
  167. package/dist/esm/atoms/cell-input-context.atom.d.ts.map +1 -1
  168. package/dist/esm/atoms/enter-key-direction.atom.d.ts +11 -0
  169. package/dist/esm/atoms/enter-key-direction.atom.d.ts.map +1 -0
  170. package/dist/esm/atoms/enter-key-direction.atom.js +8 -0
  171. package/dist/esm/atoms/index.d.ts +1 -0
  172. package/dist/esm/atoms/index.d.ts.map +1 -1
  173. package/dist/esm/atoms/index.js +1 -0
  174. package/dist/esm/atoms/paste-menu.atom.d.ts +22 -0
  175. package/dist/esm/atoms/paste-menu.atom.d.ts.map +1 -1
  176. package/dist/esm/atoms/paste-menu.atom.js +10 -1
  177. package/dist/esm/atoms/pick-list.atom.d.ts +15 -0
  178. package/dist/esm/atoms/pick-list.atom.d.ts.map +1 -0
  179. package/dist/esm/atoms/pick-list.atom.js +3 -0
  180. package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
  181. package/dist/esm/components/canvas-grid/index.js +239 -13
  182. package/dist/esm/components/canvas-grid/typings.d.ts +96 -11
  183. package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
  184. package/dist/esm/components/cell/alignment.d.ts +25 -0
  185. package/dist/esm/components/cell/alignment.d.ts.map +1 -1
  186. package/dist/esm/components/cell/alignment.js +33 -0
  187. package/dist/esm/components/cell/cell-background.d.ts +16 -0
  188. package/dist/esm/components/cell/cell-background.d.ts.map +1 -1
  189. package/dist/esm/components/cell/cell-background.js +106 -36
  190. package/dist/esm/components/cell/cell-text-runs.d.ts +12 -5
  191. package/dist/esm/components/cell/cell-text-runs.d.ts.map +1 -1
  192. package/dist/esm/components/cell/cell-text-runs.js +17 -22
  193. package/dist/esm/components/cell/index.d.ts.map +1 -1
  194. package/dist/esm/components/cell/index.js +25 -20
  195. package/dist/esm/components/cell/typings.d.ts +9 -0
  196. package/dist/esm/components/cell/typings.d.ts.map +1 -1
  197. package/dist/esm/components/cell-editor/helpers.d.ts +22 -2
  198. package/dist/esm/components/cell-editor/helpers.d.ts.map +1 -1
  199. package/dist/esm/components/cell-editor/helpers.js +25 -7
  200. package/dist/esm/components/cell-editor/index.d.ts +7 -1
  201. package/dist/esm/components/cell-editor/index.d.ts.map +1 -1
  202. package/dist/esm/components/cell-editor/index.js +80 -9
  203. package/dist/esm/components/cell-indicator/index.d.ts +41 -0
  204. package/dist/esm/components/cell-indicator/index.d.ts.map +1 -0
  205. package/dist/esm/components/cell-indicator/index.js +76 -0
  206. package/dist/esm/components/cell-input/cell-input.d.ts +10 -2
  207. package/dist/esm/components/cell-input/cell-input.d.ts.map +1 -1
  208. package/dist/esm/components/cell-input/cell-input.js +5 -3
  209. package/dist/esm/components/cell-input/formula-bar-cell-input.d.ts.map +1 -1
  210. package/dist/esm/components/cell-input/formula-bar-cell-input.js +9 -2
  211. package/dist/esm/components/cell-structured/sparkline-math.d.ts +27 -1
  212. package/dist/esm/components/cell-structured/sparkline-math.d.ts.map +1 -1
  213. package/dist/esm/components/cell-structured/sparkline-math.js +35 -0
  214. package/dist/esm/components/cell-structured/sparkline.d.ts +1 -1
  215. package/dist/esm/components/cell-structured/sparkline.d.ts.map +1 -1
  216. package/dist/esm/components/cell-structured/sparkline.js +34 -88
  217. package/dist/esm/components/cell-structured/types.d.ts +6 -0
  218. package/dist/esm/components/cell-structured/types.d.ts.map +1 -1
  219. package/dist/esm/components/data-table-dialog/index.d.ts +22 -0
  220. package/dist/esm/components/data-table-dialog/index.d.ts.map +1 -0
  221. package/dist/esm/components/data-table-dialog/index.js +75 -0
  222. package/dist/esm/components/error-check-smart-tag/index.d.ts +27 -0
  223. package/dist/esm/components/error-check-smart-tag/index.d.ts.map +1 -0
  224. package/dist/esm/components/error-check-smart-tag/index.js +33 -0
  225. package/dist/esm/components/forecast-sheet-dialog/index.d.ts +26 -0
  226. package/dist/esm/components/forecast-sheet-dialog/index.d.ts.map +1 -0
  227. package/dist/esm/components/forecast-sheet-dialog/index.js +83 -0
  228. package/dist/esm/components/paste-special-dialog/index.d.ts +3 -3
  229. package/dist/esm/components/paste-special-dialog/index.d.ts.map +1 -1
  230. package/dist/esm/components/paste-special-dialog/index.js +58 -23
  231. package/dist/esm/components/protect-sheet-dialog/allow-edit-ranges-dialog.d.ts +57 -0
  232. package/dist/esm/components/protect-sheet-dialog/allow-edit-ranges-dialog.d.ts.map +1 -0
  233. package/dist/esm/components/protect-sheet-dialog/allow-edit-ranges-dialog.js +177 -0
  234. package/dist/esm/components/protect-sheet-dialog/constants.d.ts +3 -0
  235. package/dist/esm/components/protect-sheet-dialog/constants.d.ts.map +1 -0
  236. package/dist/esm/components/protect-sheet-dialog/constants.js +2 -0
  237. package/dist/esm/components/protect-sheet-dialog/index.d.ts +2 -2
  238. package/dist/esm/components/protect-sheet-dialog/index.d.ts.map +1 -1
  239. package/dist/esm/components/protect-sheet-dialog/index.js +3 -2
  240. package/dist/esm/components/scenario-manager-dialog/index.d.ts +51 -0
  241. package/dist/esm/components/scenario-manager-dialog/index.d.ts.map +1 -0
  242. package/dist/esm/components/scenario-manager-dialog/index.js +213 -0
  243. package/dist/esm/components/selection/index.d.ts +1 -1
  244. package/dist/esm/components/selection/index.d.ts.map +1 -1
  245. package/dist/esm/components/selection/index.js +9 -4
  246. package/dist/esm/components/selection/paste-menu.d.ts +14 -1
  247. package/dist/esm/components/selection/paste-menu.d.ts.map +1 -1
  248. package/dist/esm/components/selection/paste-menu.js +76 -8
  249. package/dist/esm/components/selection/paste-options.d.ts +28 -0
  250. package/dist/esm/components/selection/paste-options.d.ts.map +1 -0
  251. package/dist/esm/components/selection/paste-options.js +62 -0
  252. package/dist/esm/components/selection/types.d.ts +12 -1
  253. package/dist/esm/components/selection/types.d.ts.map +1 -1
  254. package/dist/esm/components/selection-drop-menu/index.d.ts +18 -0
  255. package/dist/esm/components/selection-drop-menu/index.d.ts.map +1 -0
  256. package/dist/esm/components/selection-drop-menu/index.js +56 -0
  257. package/dist/esm/components/solver-dialog/index.d.ts +57 -0
  258. package/dist/esm/components/solver-dialog/index.d.ts.map +1 -0
  259. package/dist/esm/components/solver-dialog/index.js +176 -0
  260. package/dist/esm/components/toolbar/sparkline-actions.d.ts +3 -2
  261. package/dist/esm/components/toolbar/sparkline-actions.d.ts.map +1 -1
  262. package/dist/esm/components/toolbar/sparkline-actions.js +6 -2
  263. package/dist/esm/components/toolbar/table-style-selector.d.ts.map +1 -1
  264. package/dist/esm/components/toolbar/table-style-selector.js +29 -3
  265. package/dist/esm/config.d.ts +5 -4
  266. package/dist/esm/config.d.ts.map +1 -1
  267. package/dist/esm/config.js +12 -8
  268. package/dist/esm/helpers.d.ts +5 -0
  269. package/dist/esm/helpers.d.ts.map +1 -1
  270. package/dist/esm/helpers.js +8 -4
  271. package/dist/esm/hooks/use-cell-renderer.d.ts +12 -1
  272. package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -1
  273. package/dist/esm/hooks/use-cell-renderer.js +5 -2
  274. package/dist/esm/hooks/use-copy-paste-cut.d.ts +36 -2
  275. package/dist/esm/hooks/use-copy-paste-cut.d.ts.map +1 -1
  276. package/dist/esm/hooks/use-copy-paste-cut.js +117 -6
  277. package/dist/esm/hooks/use-editable.d.ts +6 -0
  278. package/dist/esm/hooks/use-editable.d.ts.map +1 -1
  279. package/dist/esm/hooks/use-editor-submit.d.ts +45 -3
  280. package/dist/esm/hooks/use-editor-submit.d.ts.map +1 -1
  281. package/dist/esm/hooks/use-editor-submit.js +81 -6
  282. package/dist/esm/hooks/use-keyboard-handler.d.ts +5 -1
  283. package/dist/esm/hooks/use-keyboard-handler.d.ts.map +1 -1
  284. package/dist/esm/hooks/use-keyboard-handler.js +10 -1
  285. package/dist/esm/hooks/use-selection-drag-copy.d.ts +55 -0
  286. package/dist/esm/hooks/use-selection-drag-copy.d.ts.map +1 -0
  287. package/dist/esm/hooks/use-selection-drag-copy.js +245 -0
  288. package/dist/esm/hooks/use-selection-renderer.d.ts +8 -1
  289. package/dist/esm/hooks/use-selection-renderer.d.ts.map +1 -1
  290. package/dist/esm/hooks/use-selection-renderer.js +7 -2
  291. package/dist/esm/hooks/use-selection.d.ts +59 -1
  292. package/dist/esm/hooks/use-selection.d.ts.map +1 -1
  293. package/dist/esm/hooks/use-selection.js +245 -52
  294. package/dist/esm/index.d.ts +6 -1
  295. package/dist/esm/index.d.ts.map +1 -1
  296. package/dist/esm/index.js +5 -0
  297. package/dist/esm/release-date.js +1 -1
  298. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  299. package/dist/esm/types.d.ts +50 -1
  300. package/dist/esm/types.d.ts.map +1 -1
  301. package/dist/spreadsheet.min.css +1 -1
  302. package/package.json +6 -5
  303. package/dist/cjs/components/cell-error/index.d.ts +0 -14
  304. package/dist/cjs/components/cell-error/index.d.ts.map +0 -1
  305. package/dist/cjs/components/cell-error/index.js +0 -24
  306. package/dist/esm/components/cell-error/index.d.ts +0 -14
  307. package/dist/esm/components/cell-error/index.d.ts.map +0 -1
  308. package/dist/esm/components/cell-error/index.js +0 -18
@@ -2,16 +2,25 @@ import { findLastContentfulCell, isCellWithinBounds, isNull, } from "@rowsncolum
2
2
  import { cellToArea } from "@rowsncolumns/grid";
3
3
  import { getOwnerDocument, useIsomorphicLayoutEffect } from "@rowsncolumns/grid";
4
4
  import { Align, cellIdentifier, cellRangeToBounds, clampCellCoords, clampIndex, Direction, findNextCellInDataRegion, findNextCellWithinBounds, getBoundedCells, isAreasEqual, isEqualCells, MouseButtonCodes, newSelectionFromDrag, selectionSpansCells, } from "@rowsncolumns/grid";
5
- import { useCallback, useReducer, useRef, useState } from "react";
5
+ import { useCallback, useMemo, useReducer, useRef, useState } from "react";
6
6
  import { scheduleImmediatePriorityCallback, scheduleNormalPriorityCallback, } from "../api/scheduler";
7
- import { MOVE_OVERWRITE_PROMPT, needsOverwritePrompt } from "../api/move-overwrite";
7
+ import { MOVE_OVERWRITE_PROMPT, needsCopyOverwritePrompt, needsOverwritePrompt, } from "../api/move-overwrite";
8
8
  import { findActiveTableWithinCell, getNextCellInTable, getTableColumnSelectRange, getTableRowSelectRange, getTableSelectAllRange, } from "../api/table";
9
+ import { getEnterKeyDirection, } from "../components/cell-editor/helpers";
9
10
  import { DEFAULT_ARRAY } from "../config";
10
11
  import { isMac } from "../helpers";
12
+ import { isMacPlatform } from "../platform";
11
13
  import { useCallbackRef } from "./use-callback-ref";
14
+ /**
15
+ * The copy modifier of a selection-border drag, read at release like Excel: Ctrl on
16
+ * Windows / Linux, Option (⌥) on macOS (Excel for Mac; ⌃-click is the Mac context menu).
17
+ */
18
+ export const isSelectionCopyModifier = (e) => (isMacPlatform() ? e.altKey : e.ctrlKey);
12
19
  /** Ctrl on every platform; Cmd is accepted as an alias on macOS (Excel for Mac uses Ctrl). */
13
20
  const isFillToggleModifier = (e) => e.ctrlKey || e.metaKey;
14
21
  const fillGestureOptions = (e) => e.ctrlKey || e.metaKey ? { modifier: "toggle" } : undefined;
22
+ /** How far an arrow key looks past unselectable cells for the next selectable one. */
23
+ const SELECTABLE_SEARCH_LIMIT = 10_000;
15
24
  const defaultIsHidden = () => false;
16
25
  const defaultSelectionSpan = () => true;
17
26
  const getPossibleActiveCellFromSelections = (selections) => {
@@ -86,7 +95,41 @@ const fillShrinkFor = (selection, coords) => {
86
95
  const defaultConfirmMoveOverwrite = (message) => typeof window === "undefined" || typeof window.confirm !== "function"
87
96
  ? true
88
97
  : window.confirm(message);
89
- export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selections, onChangeSelections, columnCount = 0, rowCount = 0, selectionPolicy = "multiple", newSelectionMode = "clear", allowDeselectSelection = true, onFill, onFillHandleRelease, onFillShrink, onInsertCutCells, confirmMoveOverwrite = defaultConfirmMoveOverwrite, isHiddenRow = defaultIsHidden, isHiddenColumn = defaultIsHidden, alwaysScrollToActiveCell = true, selectionTopBound = 0, selectionBottomBound = rowCount, selectionLeftBound = 0, selectionRightBound = columnCount, mouseDownInterceptor, mouseMoveInterceptor, mergedCells = DEFAULT_ARRAY, canSelectionSpanMergedCells = defaultSelectionSpan, getValue, onMoveSelection, getCellCoordsFromOffset, getCellBounds, getViewPort, focus, scrollToCell, isMergedCell, enableSelectOnEnterKey, formulaMode, isTouchDevice, getDataRowCount, getDataRegion, isRowHeader, isColumnHeader, enableDataBoundaryNavigation = false, tables, onInsertTableRow, }) => {
98
+ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell: onChangeActiveCellProp, selections, onChangeSelections: onChangeSelectionsProp, columnCount = 0, rowCount = 0, selectionPolicy = "multiple", newSelectionMode = "clear", allowDeselectSelection = true, onFill, onFillHandleRelease, onFillShrink, onInsertCutCells, onCopySelection, onInsertCopiedCells, onSelectionDragMenu, confirmMoveOverwrite = defaultConfirmMoveOverwrite, isHiddenRow = defaultIsHidden, isHiddenColumn = defaultIsHidden, alwaysScrollToActiveCell = true, selectionTopBound = 0, selectionBottomBound = rowCount, selectionLeftBound = 0, selectionRightBound = columnCount, mouseDownInterceptor, mouseMoveInterceptor, mergedCells = DEFAULT_ARRAY, canSelectionSpanMergedCells = defaultSelectionSpan, getValue, onMoveSelection, getCellCoordsFromOffset, getCellBounds, getViewPort, focus, scrollToCell, isMergedCell, enableSelectOnEnterKey, enterKeyDirection = "down", formulaMode, isTouchDevice, getDataRowCount, getDataRegion, isRowHeader, isColumnHeader, enableDataBoundaryNavigation = false, tables, onInsertTableRow, isRangeSelectable: isRangeSelectableProp, }) => {
99
+ /**
100
+ * Selectability gate (Excel's Select locked / unlocked cells). Every
101
+ * gesture checks it before it moves anything, and the two emitters below
102
+ * refuse an active cell or a selection that covers an unselectable range —
103
+ * the backstop for row / column / select-all paths that emit directly.
104
+ */
105
+ const isRangeSelectableRef = useRef(isRangeSelectableProp);
106
+ isRangeSelectableRef.current = isRangeSelectableProp;
107
+ const isSelectable = useCallback((range) => {
108
+ const predicate = isRangeSelectableRef.current;
109
+ return !predicate || !range || predicate(range);
110
+ }, []);
111
+ const isCellSelectable = useCallback((cell) => !cell ||
112
+ isSelectable({
113
+ startRowIndex: cell.rowIndex,
114
+ endRowIndex: cell.rowIndex,
115
+ startColumnIndex: cell.columnIndex,
116
+ endColumnIndex: cell.columnIndex,
117
+ }), [isSelectable]);
118
+ const onChangeActiveCell = useMemo(() => onChangeActiveCellProp
119
+ ? (...args) => {
120
+ if (!isCellSelectable(args[1]))
121
+ return;
122
+ onChangeActiveCellProp(...args);
123
+ }
124
+ : undefined, [onChangeActiveCellProp, isCellSelectable]);
125
+ const onChangeSelections = useMemo(() => onChangeSelectionsProp
126
+ ? (...args) => {
127
+ if (args[0]?.some((selection) => !isSelectable(selection.range))) {
128
+ return;
129
+ }
130
+ onChangeSelectionsProp(...args);
131
+ }
132
+ : undefined, [onChangeSelectionsProp, isSelectable]);
90
133
  const [fillSelection, setFillSelection] = useState();
91
134
  const [fillShrink, setFillShrink] = useState();
92
135
  const fillShrinkRef = useRef(undefined);
@@ -124,10 +167,10 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
124
167
  contextMenuSuppressorRef.current = null;
125
168
  suppressor.ownerDocument.removeEventListener("contextmenu", suppressor.handler, true);
126
169
  }, []);
127
- const suppressNextContextMenu = useCallback(() => {
170
+ const suppressNextContextMenu = useCallback((target) => {
128
171
  if (contextMenuSuppressorRef.current)
129
172
  return;
130
- const ownerDocument = fillDocumentRef.current ?? document;
173
+ const ownerDocument = target ?? fillDocumentRef.current ?? document;
131
174
  const handler = (e) => {
132
175
  e.preventDefault();
133
176
  e.stopPropagation();
@@ -148,6 +191,12 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
148
191
  const initialDraggedCell = useRef(undefined);
149
192
  const draggedSelection = useRef(undefined);
150
193
  const draggedSelectionIndex = useRef(undefined);
194
+ /** Mouse button that grabbed the selection border (right = Excel's drop menu on release). */
195
+ const dragButtonRef = useRef("left");
196
+ /** Border element the gesture started on: a right-click that never moved re-opens the context menu there. */
197
+ const dragTargetRef = useRef(null);
198
+ /** Copy modifier held during the drag (Ctrl / ⌥) — drives the copy cursor; the drop re-reads it. */
199
+ const [isDragCopy, setIsDragCopy] = useState(false);
151
200
  /**
152
201
  * Need to store in ref because on mousemove and mouseup event that are
153
202
  * registered in document
@@ -257,6 +306,9 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
257
306
  ) {
258
307
  return;
259
308
  }
309
+ if (!isSelectable(selectionFromStartEnd(selectionStart.current, coords))) {
310
+ return;
311
+ }
260
312
  selectionEnd.current = coords;
261
313
  // If user is navigation to the same cell
262
314
  // lets clear all selections
@@ -300,6 +352,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
300
352
  selectionPolicy,
301
353
  formulaMode,
302
354
  clearSelections,
355
+ isSelectable,
303
356
  ]);
304
357
  /* Adds a new selection, CMD key */
305
358
  const appendSelection = useCallback((start, end = start) => {
@@ -308,12 +361,12 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
308
361
  isCellOutOfBounds(start)) {
309
362
  return;
310
363
  }
311
- selectionStart.current = start;
312
- selectionEnd.current = end;
313
364
  const range = selectionFromStartEnd(start, end);
314
- if (!range) {
365
+ if (!range || !isSelectable(range)) {
315
366
  return;
316
367
  }
368
+ selectionStart.current = start;
369
+ selectionEnd.current = end;
317
370
  emitActiveCell(sheetId, {
318
371
  rowIndex: range.startRowIndex,
319
372
  columnIndex: range.startColumnIndex,
@@ -328,6 +381,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
328
381
  selectionFromStartEnd,
329
382
  isCellOutOfBounds,
330
383
  selectionPolicy,
384
+ isSelectable,
331
385
  ]);
332
386
  const removeSelectionByIndex = useCallback((index) => {
333
387
  const newSelection = selections.filter((_, idx) => idx !== index);
@@ -340,11 +394,11 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
340
394
  if (isCellOutOfBounds(start)) {
341
395
  return;
342
396
  }
343
- selectionStart.current = start;
344
- selectionEnd.current = end;
345
397
  const bounds = selectionFromStartEnd(start, end);
346
- if (!bounds)
398
+ if (!bounds || !isSelectable(bounds))
347
399
  return;
400
+ selectionStart.current = start;
401
+ selectionEnd.current = end;
348
402
  const coords = {
349
403
  rowIndex: bounds.startRowIndex,
350
404
  columnIndex: bounds.startColumnIndex,
@@ -369,6 +423,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
369
423
  emitActiveCell,
370
424
  selectionFromStartEnd,
371
425
  isCellOutOfBounds,
426
+ isSelectable,
372
427
  ]);
373
428
  /**
374
429
  * Mousemove handler
@@ -552,10 +607,48 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
552
607
  }
553
608
  break;
554
609
  }
555
- const newBounds = getCellBounds({
610
+ let newBounds = getCellBounds({
556
611
  rowIndex,
557
612
  columnIndex,
558
613
  });
614
+ // Protection makes the target unselectable: Shift+Arrow does not extend
615
+ // onto it, and a plain move keeps going the same way until it reaches a
616
+ // selectable cell — or stays put when there is none (Excel).
617
+ if (!isCellSelectable({ rowIndex, columnIndex })) {
618
+ if (modify)
619
+ return;
620
+ const vertical = direction === Direction.Up || direction === Direction.Down;
621
+ const step = direction === Direction.Up || direction === Direction.Left ? -1 : 1;
622
+ const lower = vertical ? selectionTopBound : selectionLeftBound;
623
+ const upper = vertical ? selectionBottomBound : selectionRightBound;
624
+ const isHidden = vertical ? isHiddenRow : isHiddenColumn;
625
+ let index = vertical ? rowIndex : columnIndex;
626
+ let found = false;
627
+ for (let tries = 0; tries < SELECTABLE_SEARCH_LIMIT; tries++) {
628
+ const edge = step > 0 ? newBounds.endRowIndex : newBounds.startRowIndex;
629
+ const edgeColumn = step > 0 ? newBounds.endColumnIndex : newBounds.startColumnIndex;
630
+ index = (vertical ? edge : edgeColumn) + step;
631
+ while (index >= lower && index <= upper && isHidden(index)) {
632
+ index += step;
633
+ }
634
+ if (index < lower || index > upper)
635
+ break;
636
+ if (vertical)
637
+ rowIndex = index;
638
+ else
639
+ columnIndex = index;
640
+ newBounds = getCellBounds({ rowIndex, columnIndex });
641
+ if (isCellSelectable({
642
+ rowIndex: newBounds.startRowIndex,
643
+ columnIndex: newBounds.startColumnIndex,
644
+ })) {
645
+ found = true;
646
+ break;
647
+ }
648
+ }
649
+ if (!found)
650
+ return;
651
+ }
559
652
  const coords = {
560
653
  rowIndex: newBounds.startRowIndex,
561
654
  columnIndex: newBounds.startColumnIndex,
@@ -590,6 +683,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
590
683
  modifySelection,
591
684
  newSelection,
592
685
  selectionBottomBound,
686
+ isCellSelectable,
593
687
  selectionRightBound,
594
688
  isMergedCell,
595
689
  getDataRowCount,
@@ -1026,6 +1120,13 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1026
1120
  const coords = getCellCoordsFromOffset(e.clientX, e.clientY, true);
1027
1121
  if (!coords)
1028
1122
  return;
1123
+ // A press on a cell the protection makes unselectable does nothing, and
1124
+ // starts no drag that could extend the old selection onto it.
1125
+ if (!isCellSelectable(coords) &&
1126
+ !isRowHeader(coords.columnIndex) &&
1127
+ !isColumnHeader(coords.rowIndex)) {
1128
+ return;
1129
+ }
1029
1130
  /* Check if its context menu click */
1030
1131
  const isContextMenuClick = e.button === MouseButtonCodes.right ||
1031
1132
  (e.button == MouseButtonCodes.left && e.ctrlKey && isMac);
@@ -1160,6 +1261,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1160
1261
  scrollToCell,
1161
1262
  selectAll,
1162
1263
  formulaMode,
1264
+ isCellSelectable,
1163
1265
  ]);
1164
1266
  // Keydown handler
1165
1267
  const handleKeyDown = useCallback((e) => {
@@ -1230,11 +1332,14 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1230
1332
  }
1231
1333
  break;
1232
1334
  // Add support for cycling multiple selections
1233
- case "Enter":
1335
+ case "Enter": {
1336
+ const direction = getEnterKeyDirection(isShiftKey, enterKeyDirection);
1337
+ if (!direction) {
1338
+ break;
1339
+ }
1234
1340
  if (selections.length && activeCell) {
1235
1341
  const { range } = selections[selections.length - 1];
1236
1342
  const activeCellBounds = getCellBounds(activeCell);
1237
- const direction = isShiftKey ? Direction.Up : Direction.Down;
1238
1343
  const nextCell = findNextCellWithinBounds(activeCellBounds, range, direction);
1239
1344
  if (nextCell) {
1240
1345
  emitActiveCell(sheetId, nextCell);
@@ -1242,14 +1347,10 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1242
1347
  }
1243
1348
  }
1244
1349
  else if (enableSelectOnEnterKey) {
1245
- if (isShiftKey) {
1246
- keyNavigate(Direction.Up);
1247
- }
1248
- else {
1249
- keyNavigate(Direction.Down);
1250
- }
1350
+ keyNavigate(direction);
1251
1351
  }
1252
1352
  break;
1353
+ }
1253
1354
  case "Tab":
1254
1355
  /* Cycle through the selections if selections.length > 0 */
1255
1356
  if (selections.length && activeCell) {
@@ -1325,6 +1426,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1325
1426
  selectFirstCellInSheet,
1326
1427
  selectLastCellInSheet,
1327
1428
  enableSelectOnEnterKey,
1429
+ enterKeyDirection,
1328
1430
  newSelection,
1329
1431
  isHiddenRow,
1330
1432
  isHiddenColumn,
@@ -1558,6 +1660,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1558
1660
  * Ond drag move
1559
1661
  */
1560
1662
  const handleSelectionMouseMove = useCallback((e) => {
1663
+ setIsDragCopy(dragButtonRef.current === "left" && isSelectionCopyModifier(e));
1561
1664
  const coords = getCellCoordsFromOffset(e.clientX, e.clientY, false);
1562
1665
  if (!coords) {
1563
1666
  return;
@@ -1600,15 +1703,70 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1600
1703
  const handleSelectionMouseUp = useCallback((e) => {
1601
1704
  const fromSelection = initialDraggedSelection.current;
1602
1705
  const toSelection = draggedSelection.current;
1603
- // Excel reads the modifier at RELEASE: Shift → insert between existing cells (I-beam),
1604
- // no modifier → overwrite (after the data prompt).
1706
+ const button = dragButtonRef.current;
1707
+ const borderTarget = dragTargetRef.current;
1708
+ const moved = !!fromSelection &&
1709
+ !!toSelection &&
1710
+ !isAreasEqual(toSelection.range, fromSelection.range);
1711
+ /* Remove event handlers from the document the gesture started on */
1712
+ const ownerDocument = dragSelectionDocumentRef.current ?? document;
1713
+ const resetGesture = () => {
1714
+ isDragging.current = false;
1715
+ draggedSelection.current = void 0;
1716
+ draggedSelectionIndex.current = void 0;
1717
+ hasUserMovedSelection.current = false;
1718
+ dragButtonRef.current = "left";
1719
+ dragTargetRef.current = null;
1720
+ setIsDragCopy(false);
1721
+ dragSelectionDocumentRef.current = null;
1722
+ ownerDocument.removeEventListener("mouseup", handleSelectionMouseUp);
1723
+ ownerDocument.removeEventListener("pointerup", handleSelectionMouseUp);
1724
+ ownerDocument.removeEventListener("mousemove", handleSelectionMouseMove);
1725
+ ownerDocument.removeEventListener("pointermove", handleSelectionMouseMove);
1726
+ };
1727
+ if (button === "right") {
1728
+ // Right-button drag (Excel): nothing changes on release — the grid opens the drop
1729
+ // menu and runs the entry the user picks. The right-button `contextmenu` follows this
1730
+ // release on Windows (on macOS it fired at press); keep swallowing it for one tick.
1731
+ // A right-click that never left the source is an ordinary right-click: the context
1732
+ // menu the press swallowed opens at the release point instead.
1733
+ const { clientX, clientY } = e;
1734
+ setTimeout(() => {
1735
+ releaseContextMenuSuppressor();
1736
+ if (!moved && borderTarget && "dispatchEvent" in borderTarget) {
1737
+ borderTarget.dispatchEvent(new MouseEvent("contextmenu", {
1738
+ bubbles: true,
1739
+ cancelable: true,
1740
+ clientX,
1741
+ clientY,
1742
+ button: MouseButtonCodes.right,
1743
+ }));
1744
+ }
1745
+ }, 0);
1746
+ if (moved && fromSelection && toSelection) {
1747
+ onSelectionDragMenu?.({
1748
+ sheetId,
1749
+ from: fromSelection,
1750
+ to: toSelection,
1751
+ clientX,
1752
+ clientY,
1753
+ });
1754
+ }
1755
+ resetGesture();
1756
+ forceRender();
1757
+ return;
1758
+ }
1759
+ // Excel reads the modifiers at RELEASE: Shift → insert between existing cells (I-beam),
1760
+ // Ctrl (⌥ on macOS) → copy instead of move, both → insert a copy; none → move
1761
+ // (overwriting after the data prompt).
1605
1762
  const insertMode = e.shiftKey;
1763
+ const copyMode = isSelectionCopyModifier(e);
1764
+ // Snapshot before the selection follows the drop, so a refusal / Cancel can restore it.
1765
+ const previousSelections = selectionsRef.current;
1606
1766
  /**
1607
1767
  * If the from and to selection area
1608
1768
  */
1609
- if (toSelection &&
1610
- fromSelection &&
1611
- !isAreasEqual(toSelection.range, fromSelection.range)) {
1769
+ if (moved && toSelection) {
1612
1770
  /* Select the first cell in the selection area */
1613
1771
  const coords = {
1614
1772
  rowIndex: toSelection.range.startRowIndex,
@@ -1634,31 +1792,58 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1634
1792
  };
1635
1793
  }
1636
1794
  }
1795
+ // Put the selection back on the source (Cancel, or a gesture the host can't run).
1796
+ const restoreSource = (source, dropped) => {
1797
+ emitActiveCell(sheetId, {
1798
+ rowIndex: source.range.startRowIndex,
1799
+ columnIndex: source.range.startColumnIndex,
1800
+ });
1801
+ onChangeSelections?.(selectionSpansCells(source.range)
1802
+ ? previousSelections.map((cur) => isAreasEqual(cur.range, dropped.range) ? source : cur)
1803
+ : previousSelections.filter((cur) => !isAreasEqual(cur.range, dropped.range)));
1804
+ focus();
1805
+ };
1806
+ const hasValue = (rowIndex, columnIndex) => !isNull(getValue(sheetId, rowIndex, columnIndex));
1637
1807
  // Callback
1638
- if (fromSelection &&
1639
- toSelection &&
1640
- !isAreasEqual(fromSelection.range, toSelection.range)) {
1641
- if (insertMode && onInsertCutCells) {
1808
+ if (moved && fromSelection && toSelection) {
1809
+ if (copyMode && insertMode) {
1810
+ // Ctrl+Shift+drag inserts a copy (destination band shifts) — Excel shows no prompt.
1811
+ if (!onInsertCopiedCells ||
1812
+ onInsertCopiedCells(sheetId, fromSelection, toSelection) === false) {
1813
+ restoreSource(fromSelection, toSelection);
1814
+ }
1815
+ }
1816
+ else if (copyMode) {
1817
+ if (!onCopySelection) {
1818
+ restoreSource(fromSelection, toSelection);
1819
+ }
1820
+ else if (needsCopyOverwritePrompt(toSelection.range, hasValue)) {
1821
+ // The copy would replace data: Excel asks first, Cancel puts the selection back.
1822
+ Promise.resolve(confirmMoveOverwrite(MOVE_OVERWRITE_PROMPT)).then((replace) => {
1823
+ if (replace &&
1824
+ onCopySelection(sheetId, fromSelection, toSelection) !== false) {
1825
+ return;
1826
+ }
1827
+ restoreSource(fromSelection, toSelection);
1828
+ });
1829
+ }
1830
+ else if (onCopySelection(sheetId, fromSelection, toSelection) === false) {
1831
+ restoreSource(fromSelection, toSelection);
1832
+ }
1833
+ }
1834
+ else if (insertMode && onInsertCutCells) {
1642
1835
  // Shift+drag inserts (displaces the destination band) — Excel shows no prompt.
1643
1836
  onInsertCutCells(sheetId, fromSelection, toSelection);
1644
1837
  }
1645
- else if (needsOverwritePrompt(fromSelection.range, toSelection.range, (rowIndex, columnIndex) => !isNull(getValue(sheetId, rowIndex, columnIndex)))) {
1838
+ else if (needsOverwritePrompt(fromSelection.range, toSelection.range, hasValue)) {
1646
1839
  // The destination holds data the block would overwrite: Excel asks first. The
1647
1840
  // selection has already followed the drop; Cancel puts it back on the source.
1648
- const previousSelections = selectionsRef.current;
1649
1841
  Promise.resolve(confirmMoveOverwrite(MOVE_OVERWRITE_PROMPT)).then((replace) => {
1650
1842
  if (replace) {
1651
1843
  onMoveSelection?.(sheetId, fromSelection, toSelection);
1652
1844
  return;
1653
1845
  }
1654
- emitActiveCell(sheetId, {
1655
- rowIndex: fromSelection.range.startRowIndex,
1656
- columnIndex: fromSelection.range.startColumnIndex,
1657
- });
1658
- onChangeSelections?.(selectionSpansCells(fromSelection.range)
1659
- ? previousSelections.map((cur) => isAreasEqual(cur.range, toSelection.range) ? fromSelection : cur)
1660
- : previousSelections.filter((cur) => !isAreasEqual(cur.range, toSelection.range)));
1661
- focus();
1846
+ restoreSource(fromSelection, toSelection);
1662
1847
  });
1663
1848
  }
1664
1849
  else {
@@ -1668,29 +1853,23 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1668
1853
  /* Focus on the grid */
1669
1854
  focus();
1670
1855
  /* Reset all references */
1671
- isDragging.current = false;
1672
- draggedSelection.current = void 0;
1673
- draggedSelectionIndex.current = void 0;
1674
- hasUserMovedSelection.current = false;
1675
- /* Remove event handlers from the document the gesture started on */
1676
- const ownerDocument = dragSelectionDocumentRef.current ?? document;
1677
- dragSelectionDocumentRef.current = null;
1678
- ownerDocument.removeEventListener("mouseup", handleSelectionMouseUp);
1679
- ownerDocument.removeEventListener("pointerup", handleSelectionMouseUp);
1680
- ownerDocument.removeEventListener("mousemove", handleSelectionMouseMove);
1681
- ownerDocument.removeEventListener("pointermove", handleSelectionMouseMove);
1856
+ resetGesture();
1682
1857
  /* Force render */
1683
1858
  forceRender();
1684
1859
  }, [
1685
1860
  sheetId,
1686
1861
  onMoveSelection,
1687
1862
  onInsertCutCells,
1863
+ onCopySelection,
1864
+ onInsertCopiedCells,
1865
+ onSelectionDragMenu,
1688
1866
  confirmMoveOverwrite,
1689
1867
  getValue,
1690
1868
  handleSelectionMouseMove,
1691
1869
  focus,
1692
1870
  emitActiveCell,
1693
1871
  onChangeSelections,
1872
+ releaseContextMenuSuppressor,
1694
1873
  ]);
1695
1874
  /**
1696
1875
  * When user mouse downs on selection
@@ -1699,8 +1878,10 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1699
1878
  if (e.isDefaultPrevented()) {
1700
1879
  return;
1701
1880
  }
1702
- const isContextMenu = e.button === MouseButtonCodes.right || e.ctrlKey;
1703
- if (isContextMenu) {
1881
+ // ⌃-click is the macOS context-menu gesture; on Windows Ctrl+drag copies (read at
1882
+ // release). A right-button drag opens Excel's drop menu when the host offers one.
1883
+ const isRightButton = e.button === MouseButtonCodes.right;
1884
+ if (isRightButton ? !onSelectionDragMenu : e.ctrlKey && isMacPlatform()) {
1704
1885
  return;
1705
1886
  }
1706
1887
  // Keep keyboard focus in the grid. The selection border is rendered OUTSIDE the tabIndex=0
@@ -1733,6 +1914,9 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1733
1914
  }
1734
1915
  /* Set dragging flag */
1735
1916
  isDragging.current = true;
1917
+ dragButtonRef.current = isRightButton ? "right" : "left";
1918
+ dragTargetRef.current = e.currentTarget ?? null;
1919
+ setIsDragCopy(!isRightButton && isSelectionCopyModifier(e));
1736
1920
  /* Listen on the document the gesture started on. The border cover starts
1737
1921
  * the gesture from `pointerdown`, and the preventDefault above cancels it —
1738
1922
  * a browser then withholds the compatibility mouse events (mousemove /
@@ -1742,6 +1926,11 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1742
1926
  * four, so the release runs once. */
1743
1927
  const ownerDocument = getOwnerDocument(e.currentTarget) ?? document;
1744
1928
  dragSelectionDocumentRef.current = ownerDocument;
1929
+ if (isRightButton) {
1930
+ // The right-button `contextmenu` (at press on macOS, at release on Windows) must not
1931
+ // open the cell context menu over the drag; the release decides what opens.
1932
+ suppressNextContextMenu(ownerDocument);
1933
+ }
1745
1934
  ownerDocument.addEventListener("mouseup", handleSelectionMouseUp);
1746
1935
  ownerDocument.addEventListener("pointerup", handleSelectionMouseUp);
1747
1936
  ownerDocument.addEventListener("mousemove", handleSelectionMouseMove);
@@ -1753,6 +1942,8 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1753
1942
  getCellBounds,
1754
1943
  handleSelectionMouseMove,
1755
1944
  handleSelectionMouseUp,
1945
+ onSelectionDragMenu,
1946
+ suppressNextContextMenu,
1756
1947
  ]);
1757
1948
  /**
1758
1949
  * Set selection start and end reference
@@ -1974,6 +2165,8 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1974
2165
  ]);
1975
2166
  return {
1976
2167
  isDragging: isDragging.current,
2168
+ /** True while a selection-border drag would copy on release (Ctrl / ⌥ held). */
2169
+ isDragCopy,
1977
2170
  draggedSelection: draggedSelection.current,
1978
2171
  initialDraggedSelection: initialDraggedSelection.current,
1979
2172
  isFilling: isFilling.current,
@@ -30,6 +30,10 @@ export * from "./components/remove-duplicates-dialog";
30
30
  export * from "./components/text-to-columns-dialog";
31
31
  export * from "./components/subtotal-dialog";
32
32
  export * from "./components/goal-seek-dialog";
33
+ export * from "./components/data-table-dialog";
34
+ export * from "./components/scenario-manager-dialog";
35
+ export * from "./components/solver-dialog";
36
+ export * from "./components/forecast-sheet-dialog";
33
37
  export * from "./components/advanced-filter-dialog";
34
38
  export * from "./components/validation-alert-dialog";
35
39
  export * from "./components/insert-cells-dialog";
@@ -73,6 +77,7 @@ export * from "./api/cf-overlays";
73
77
  export * from "./api/cf-icons";
74
78
  export * from "./api/cf-engine";
75
79
  export * from "./api/cf-priority";
80
+ export * from "./api/error-checking";
76
81
  export * from "./api/fill-patterns";
77
82
  export type { AvailableIcon } from "./components/filter-box";
78
83
  export * from "./hooks";
@@ -92,7 +97,7 @@ export { type ContextMenuWrapperProps } from "./hooks/use-context-menu";
92
97
  export * from "./api/scheduler";
93
98
  export * from "./themes";
94
99
  export * from "./signals/scroll-subscriber";
95
- export type { PasteSpecialOperation, PasteSpecialOptions, PasteSpecialRequest, PasteSpecialType, } from "./hooks/use-copy-paste-cut";
100
+ export type { PasteSpecialMode, PasteSpecialOperation, PasteSpecialOptions, PasteSpecialRequest, PasteSpecialType, } from "./hooks/use-copy-paste-cut";
96
101
  export { CHART_CLIPBOARD_MIME, CHART_PASTE_OFFSET_PIXELS, type UseChartClipboardProps, useChartClipboard, } from "./hooks/use-chart-clipboard";
97
102
  export * from "./hooks/use-formula-range-helpers";
98
103
  export * from "./utils/z-order";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.tsx"],"names":[],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -29,6 +29,10 @@ export * from "./components/remove-duplicates-dialog";
29
29
  export * from "./components/text-to-columns-dialog";
30
30
  export * from "./components/subtotal-dialog";
31
31
  export * from "./components/goal-seek-dialog";
32
+ export * from "./components/data-table-dialog";
33
+ export * from "./components/scenario-manager-dialog";
34
+ export * from "./components/solver-dialog";
35
+ export * from "./components/forecast-sheet-dialog";
32
36
  export * from "./components/advanced-filter-dialog";
33
37
  export * from "./components/validation-alert-dialog";
34
38
  export * from "./components/insert-cells-dialog";
@@ -72,6 +76,7 @@ export * from "./api/cf-overlays";
72
76
  export * from "./api/cf-icons";
73
77
  export * from "./api/cf-engine";
74
78
  export * from "./api/cf-priority";
79
+ export * from "./api/error-checking";
75
80
  export * from "./api/fill-patterns";
76
81
  export * from "./hooks";
77
82
  export * from "./components/cell/typings";
@@ -1,3 +1,3 @@
1
1
  export const releaseDate =
2
2
  // @ts-ignore
3
- new Date("2026-11-02") ?? new Date("2025-06-18");
3
+ new Date("2026-11-03") ?? new Date("2025-06-18");