@rowsncolumns/spreadsheet 10.2.73 → 10.2.75

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 (270) hide show
  1. package/dist/cjs/api/evaluate-formula.d.ts +17 -0
  2. package/dist/cjs/api/evaluate-formula.d.ts.map +1 -0
  3. package/dist/cjs/api/evaluate-formula.js +141 -0
  4. package/dist/cjs/api/excel-validation-kinds.d.ts +71 -0
  5. package/dist/cjs/api/excel-validation-kinds.d.ts.map +1 -0
  6. package/dist/cjs/api/excel-validation-kinds.js +304 -0
  7. package/dist/cjs/api/go-to-special.d.ts +32 -0
  8. package/dist/cjs/api/go-to-special.d.ts.map +1 -0
  9. package/dist/cjs/api/go-to-special.js +111 -0
  10. package/dist/cjs/api/go-to.d.ts +19 -0
  11. package/dist/cjs/api/go-to.d.ts.map +1 -0
  12. package/dist/cjs/api/go-to.js +49 -0
  13. package/dist/cjs/api/validation-tooltip.d.ts +17 -0
  14. package/dist/cjs/api/validation-tooltip.d.ts.map +1 -0
  15. package/dist/cjs/api/validation-tooltip.js +42 -0
  16. package/dist/cjs/atoms/advanced-filter-dialog.atom.d.ts +28 -0
  17. package/dist/cjs/atoms/advanced-filter-dialog.atom.d.ts.map +1 -0
  18. package/dist/cjs/atoms/advanced-filter-dialog.atom.js +32 -0
  19. package/dist/cjs/atoms/evaluate-formula-dialog.atom.d.ts +36 -0
  20. package/dist/cjs/atoms/evaluate-formula-dialog.atom.d.ts.map +1 -0
  21. package/dist/cjs/atoms/evaluate-formula-dialog.atom.js +36 -0
  22. package/dist/cjs/atoms/go-to-dialog.atom.d.ts +46 -0
  23. package/dist/cjs/atoms/go-to-dialog.atom.d.ts.map +1 -0
  24. package/dist/cjs/atoms/go-to-dialog.atom.js +34 -0
  25. package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts +29 -0
  26. package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts.map +1 -0
  27. package/dist/cjs/atoms/goal-seek-dialog.atom.js +30 -0
  28. package/dist/cjs/atoms/index.d.ts +5 -0
  29. package/dist/cjs/atoms/index.d.ts.map +1 -1
  30. package/dist/cjs/atoms/index.js +5 -0
  31. package/dist/cjs/atoms/paste-special-dialog.atom.d.ts +29 -0
  32. package/dist/cjs/atoms/paste-special-dialog.atom.d.ts.map +1 -0
  33. package/dist/cjs/atoms/paste-special-dialog.atom.js +34 -0
  34. package/dist/cjs/atoms/remove-duplicates-dialog.atom.d.ts +45 -0
  35. package/dist/cjs/atoms/remove-duplicates-dialog.atom.d.ts.map +1 -0
  36. package/dist/cjs/atoms/remove-duplicates-dialog.atom.js +37 -0
  37. package/dist/cjs/atoms/subtotal-dialog.atom.d.ts +39 -0
  38. package/dist/cjs/atoms/subtotal-dialog.atom.d.ts.map +1 -0
  39. package/dist/cjs/atoms/subtotal-dialog.atom.js +30 -0
  40. package/dist/cjs/atoms/text-to-columns-dialog.atom.d.ts +34 -0
  41. package/dist/cjs/atoms/text-to-columns-dialog.atom.d.ts.map +1 -0
  42. package/dist/cjs/atoms/text-to-columns-dialog.atom.js +36 -0
  43. package/dist/cjs/atoms/watch-window.atom.d.ts +37 -0
  44. package/dist/cjs/atoms/watch-window.atom.d.ts.map +1 -0
  45. package/dist/cjs/atoms/watch-window.atom.js +61 -0
  46. package/dist/cjs/components/advanced-filter-dialog/index.d.ts +28 -0
  47. package/dist/cjs/components/advanced-filter-dialog/index.d.ts.map +1 -0
  48. package/dist/cjs/components/advanced-filter-dialog/index.js +134 -0
  49. package/dist/cjs/components/calculation-options-dialog/index.d.ts +33 -0
  50. package/dist/cjs/components/calculation-options-dialog/index.d.ts.map +1 -0
  51. package/dist/cjs/components/calculation-options-dialog/index.js +69 -0
  52. package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
  53. package/dist/cjs/components/canvas-grid/index.js +208 -19
  54. package/dist/cjs/components/canvas-grid/typings.d.ts +72 -9
  55. package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
  56. package/dist/cjs/components/cell/alignment.d.ts +30 -0
  57. package/dist/cjs/components/cell/alignment.d.ts.map +1 -1
  58. package/dist/cjs/components/cell/alignment.js +56 -1
  59. package/dist/cjs/components/cell/index.d.ts.map +1 -1
  60. package/dist/cjs/components/cell/index.js +15 -7
  61. package/dist/cjs/components/cell-diff/index.d.ts +3 -2
  62. package/dist/cjs/components/cell-diff/index.d.ts.map +1 -1
  63. package/dist/cjs/components/cell-editor/index.d.ts.map +1 -1
  64. package/dist/cjs/components/cell-editor/index.js +2 -1
  65. package/dist/cjs/components/context-menu/index.d.ts +21 -3
  66. package/dist/cjs/components/context-menu/index.d.ts.map +1 -1
  67. package/dist/cjs/components/context-menu/index.js +256 -6
  68. package/dist/cjs/components/context-menu/total-row-functions.d.ts +32 -0
  69. package/dist/cjs/components/context-menu/total-row-functions.d.ts.map +1 -0
  70. package/dist/cjs/components/context-menu/total-row-functions.js +62 -0
  71. package/dist/cjs/components/embeds/embed-component.d.ts.map +1 -1
  72. package/dist/cjs/components/embeds/embed-component.js +16 -1
  73. package/dist/cjs/components/evaluate-formula-dialog/index.d.ts +34 -0
  74. package/dist/cjs/components/evaluate-formula-dialog/index.d.ts.map +1 -0
  75. package/dist/cjs/components/evaluate-formula-dialog/index.js +106 -0
  76. package/dist/cjs/components/go-to-dialog/index.d.ts +45 -0
  77. package/dist/cjs/components/go-to-dialog/index.d.ts.map +1 -0
  78. package/dist/cjs/components/go-to-dialog/index.js +136 -0
  79. package/dist/cjs/components/goal-seek-dialog/index.d.ts +32 -0
  80. package/dist/cjs/components/goal-seek-dialog/index.d.ts.map +1 -0
  81. package/dist/cjs/components/goal-seek-dialog/index.js +149 -0
  82. package/dist/cjs/components/paste-special-dialog/index.d.ts +29 -0
  83. package/dist/cjs/components/paste-special-dialog/index.d.ts.map +1 -0
  84. package/dist/cjs/components/paste-special-dialog/index.js +99 -0
  85. package/dist/cjs/components/remove-duplicates-dialog/index.d.ts +37 -0
  86. package/dist/cjs/components/remove-duplicates-dialog/index.d.ts.map +1 -0
  87. package/dist/cjs/components/remove-duplicates-dialog/index.js +91 -0
  88. package/dist/cjs/components/subtotal-dialog/index.d.ts +30 -0
  89. package/dist/cjs/components/subtotal-dialog/index.d.ts.map +1 -0
  90. package/dist/cjs/components/subtotal-dialog/index.js +126 -0
  91. package/dist/cjs/components/text-to-columns-dialog/index.d.ts +37 -0
  92. package/dist/cjs/components/text-to-columns-dialog/index.d.ts.map +1 -0
  93. package/dist/cjs/components/text-to-columns-dialog/index.js +166 -0
  94. package/dist/cjs/components/toolbar/background-color-selector.d.ts +13 -1
  95. package/dist/cjs/components/toolbar/background-color-selector.d.ts.map +1 -1
  96. package/dist/cjs/components/toolbar/background-color-selector.js +57 -11
  97. package/dist/cjs/components/toolbar/cell-style-selector.d.ts +15 -2
  98. package/dist/cjs/components/toolbar/cell-style-selector.d.ts.map +1 -1
  99. package/dist/cjs/components/toolbar/cell-style-selector.js +56 -3
  100. package/dist/cjs/components/toolbar/fill-selectors.d.ts +49 -0
  101. package/dist/cjs/components/toolbar/fill-selectors.d.ts.map +1 -0
  102. package/dist/cjs/components/toolbar/fill-selectors.js +196 -0
  103. package/dist/cjs/components/toolbar/index.d.ts +2 -0
  104. package/dist/cjs/components/toolbar/index.d.ts.map +1 -1
  105. package/dist/cjs/components/toolbar/index.js +2 -0
  106. package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts +8 -0
  107. package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -1
  108. package/dist/cjs/components/toolbar/text-horizontal-align-selector.js +23 -4
  109. package/dist/cjs/components/toolbar/text-rotation-selector.d.ts +29 -0
  110. package/dist/cjs/components/toolbar/text-rotation-selector.d.ts.map +1 -0
  111. package/dist/cjs/components/toolbar/text-rotation-selector.js +78 -0
  112. package/dist/cjs/components/toolbar/text-wrap-selector.d.ts +7 -1
  113. package/dist/cjs/components/toolbar/text-wrap-selector.d.ts.map +1 -1
  114. package/dist/cjs/components/toolbar/text-wrap-selector.js +10 -3
  115. package/dist/cjs/components/watch-window/index.d.ts +25 -0
  116. package/dist/cjs/components/watch-window/index.d.ts.map +1 -0
  117. package/dist/cjs/components/watch-window/index.js +63 -0
  118. package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -1
  119. package/dist/cjs/hooks/use-cell-renderer.js +17 -6
  120. package/dist/cjs/hooks/use-copy-paste-cut.d.ts +20 -1
  121. package/dist/cjs/hooks/use-copy-paste-cut.d.ts.map +1 -1
  122. package/dist/cjs/hooks/use-copy-paste-cut.js +25 -20
  123. package/dist/cjs/hooks/use-get-tooltip.d.ts.map +1 -1
  124. package/dist/cjs/hooks/use-get-tooltip.js +7 -2
  125. package/dist/cjs/hooks/use-keyboard-handler.d.ts +17 -2
  126. package/dist/cjs/hooks/use-keyboard-handler.d.ts.map +1 -1
  127. package/dist/cjs/hooks/use-keyboard-handler.js +206 -31
  128. package/dist/cjs/index.d.ts +14 -1
  129. package/dist/cjs/index.d.ts.map +1 -1
  130. package/dist/cjs/index.js +15 -1
  131. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  132. package/dist/cjs/types.d.ts +289 -4
  133. package/dist/cjs/types.d.ts.map +1 -1
  134. package/dist/cjs/types.js +19 -1
  135. package/dist/esm/api/evaluate-formula.d.ts +17 -0
  136. package/dist/esm/api/evaluate-formula.d.ts.map +1 -0
  137. package/dist/esm/api/evaluate-formula.js +109 -0
  138. package/dist/esm/api/excel-validation-kinds.d.ts +71 -0
  139. package/dist/esm/api/excel-validation-kinds.d.ts.map +1 -0
  140. package/dist/esm/api/excel-validation-kinds.js +287 -0
  141. package/dist/esm/api/go-to-special.d.ts +32 -0
  142. package/dist/esm/api/go-to-special.d.ts.map +1 -0
  143. package/dist/esm/api/go-to-special.js +96 -0
  144. package/dist/esm/api/go-to.d.ts +19 -0
  145. package/dist/esm/api/go-to.d.ts.map +1 -0
  146. package/dist/esm/api/go-to.js +41 -0
  147. package/dist/esm/api/validation-tooltip.d.ts +17 -0
  148. package/dist/esm/api/validation-tooltip.d.ts.map +1 -0
  149. package/dist/esm/api/validation-tooltip.js +34 -0
  150. package/dist/esm/atoms/advanced-filter-dialog.atom.d.ts +28 -0
  151. package/dist/esm/atoms/advanced-filter-dialog.atom.d.ts.map +1 -0
  152. package/dist/esm/atoms/advanced-filter-dialog.atom.js +21 -0
  153. package/dist/esm/atoms/evaluate-formula-dialog.atom.d.ts +36 -0
  154. package/dist/esm/atoms/evaluate-formula-dialog.atom.d.ts.map +1 -0
  155. package/dist/esm/atoms/evaluate-formula-dialog.atom.js +25 -0
  156. package/dist/esm/atoms/go-to-dialog.atom.d.ts +46 -0
  157. package/dist/esm/atoms/go-to-dialog.atom.d.ts.map +1 -0
  158. package/dist/esm/atoms/go-to-dialog.atom.js +25 -0
  159. package/dist/esm/atoms/goal-seek-dialog.atom.d.ts +29 -0
  160. package/dist/esm/atoms/goal-seek-dialog.atom.d.ts.map +1 -0
  161. package/dist/esm/atoms/goal-seek-dialog.atom.js +21 -0
  162. package/dist/esm/atoms/index.d.ts +5 -0
  163. package/dist/esm/atoms/index.d.ts.map +1 -1
  164. package/dist/esm/atoms/index.js +5 -0
  165. package/dist/esm/atoms/paste-special-dialog.atom.d.ts +29 -0
  166. package/dist/esm/atoms/paste-special-dialog.atom.d.ts.map +1 -0
  167. package/dist/esm/atoms/paste-special-dialog.atom.js +25 -0
  168. package/dist/esm/atoms/remove-duplicates-dialog.atom.d.ts +45 -0
  169. package/dist/esm/atoms/remove-duplicates-dialog.atom.d.ts.map +1 -0
  170. package/dist/esm/atoms/remove-duplicates-dialog.atom.js +26 -0
  171. package/dist/esm/atoms/subtotal-dialog.atom.d.ts +39 -0
  172. package/dist/esm/atoms/subtotal-dialog.atom.d.ts.map +1 -0
  173. package/dist/esm/atoms/subtotal-dialog.atom.js +21 -0
  174. package/dist/esm/atoms/text-to-columns-dialog.atom.d.ts +34 -0
  175. package/dist/esm/atoms/text-to-columns-dialog.atom.d.ts.map +1 -0
  176. package/dist/esm/atoms/text-to-columns-dialog.atom.js +25 -0
  177. package/dist/esm/atoms/watch-window.atom.d.ts +37 -0
  178. package/dist/esm/atoms/watch-window.atom.d.ts.map +1 -0
  179. package/dist/esm/atoms/watch-window.atom.js +37 -0
  180. package/dist/esm/components/advanced-filter-dialog/index.d.ts +28 -0
  181. package/dist/esm/components/advanced-filter-dialog/index.d.ts.map +1 -0
  182. package/dist/esm/components/advanced-filter-dialog/index.js +125 -0
  183. package/dist/esm/components/calculation-options-dialog/index.d.ts +33 -0
  184. package/dist/esm/components/calculation-options-dialog/index.d.ts.map +1 -0
  185. package/dist/esm/components/calculation-options-dialog/index.js +61 -0
  186. package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
  187. package/dist/esm/components/canvas-grid/index.js +202 -19
  188. package/dist/esm/components/canvas-grid/typings.d.ts +72 -9
  189. package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
  190. package/dist/esm/components/cell/alignment.d.ts +30 -0
  191. package/dist/esm/components/cell/alignment.d.ts.map +1 -1
  192. package/dist/esm/components/cell/alignment.js +51 -0
  193. package/dist/esm/components/cell/index.d.ts.map +1 -1
  194. package/dist/esm/components/cell/index.js +16 -8
  195. package/dist/esm/components/cell-diff/index.d.ts +3 -2
  196. package/dist/esm/components/cell-diff/index.d.ts.map +1 -1
  197. package/dist/esm/components/cell-editor/index.d.ts.map +1 -1
  198. package/dist/esm/components/cell-editor/index.js +2 -1
  199. package/dist/esm/components/context-menu/index.d.ts +21 -3
  200. package/dist/esm/components/context-menu/index.d.ts.map +1 -1
  201. package/dist/esm/components/context-menu/index.js +251 -9
  202. package/dist/esm/components/context-menu/total-row-functions.d.ts +32 -0
  203. package/dist/esm/components/context-menu/total-row-functions.d.ts.map +1 -0
  204. package/dist/esm/components/context-menu/total-row-functions.js +50 -0
  205. package/dist/esm/components/embeds/embed-component.d.ts.map +1 -1
  206. package/dist/esm/components/embeds/embed-component.js +17 -1
  207. package/dist/esm/components/evaluate-formula-dialog/index.d.ts +34 -0
  208. package/dist/esm/components/evaluate-formula-dialog/index.d.ts.map +1 -0
  209. package/dist/esm/components/evaluate-formula-dialog/index.js +86 -0
  210. package/dist/esm/components/go-to-dialog/index.d.ts +45 -0
  211. package/dist/esm/components/go-to-dialog/index.d.ts.map +1 -0
  212. package/dist/esm/components/go-to-dialog/index.js +124 -0
  213. package/dist/esm/components/goal-seek-dialog/index.d.ts +32 -0
  214. package/dist/esm/components/goal-seek-dialog/index.d.ts.map +1 -0
  215. package/dist/esm/components/goal-seek-dialog/index.js +125 -0
  216. package/dist/esm/components/paste-special-dialog/index.d.ts +29 -0
  217. package/dist/esm/components/paste-special-dialog/index.d.ts.map +1 -0
  218. package/dist/esm/components/paste-special-dialog/index.js +90 -0
  219. package/dist/esm/components/remove-duplicates-dialog/index.d.ts +37 -0
  220. package/dist/esm/components/remove-duplicates-dialog/index.d.ts.map +1 -0
  221. package/dist/esm/components/remove-duplicates-dialog/index.js +82 -0
  222. package/dist/esm/components/subtotal-dialog/index.d.ts +30 -0
  223. package/dist/esm/components/subtotal-dialog/index.d.ts.map +1 -0
  224. package/dist/esm/components/subtotal-dialog/index.js +115 -0
  225. package/dist/esm/components/text-to-columns-dialog/index.d.ts +37 -0
  226. package/dist/esm/components/text-to-columns-dialog/index.d.ts.map +1 -0
  227. package/dist/esm/components/text-to-columns-dialog/index.js +147 -0
  228. package/dist/esm/components/toolbar/background-color-selector.d.ts +13 -1
  229. package/dist/esm/components/toolbar/background-color-selector.d.ts.map +1 -1
  230. package/dist/esm/components/toolbar/background-color-selector.js +61 -11
  231. package/dist/esm/components/toolbar/cell-style-selector.d.ts +15 -2
  232. package/dist/esm/components/toolbar/cell-style-selector.d.ts.map +1 -1
  233. package/dist/esm/components/toolbar/cell-style-selector.js +46 -2
  234. package/dist/esm/components/toolbar/fill-selectors.d.ts +49 -0
  235. package/dist/esm/components/toolbar/fill-selectors.d.ts.map +1 -0
  236. package/dist/esm/components/toolbar/fill-selectors.js +162 -0
  237. package/dist/esm/components/toolbar/index.d.ts +2 -0
  238. package/dist/esm/components/toolbar/index.d.ts.map +1 -1
  239. package/dist/esm/components/toolbar/index.js +2 -0
  240. package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts +8 -0
  241. package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -1
  242. package/dist/esm/components/toolbar/text-horizontal-align-selector.js +21 -5
  243. package/dist/esm/components/toolbar/text-rotation-selector.d.ts +29 -0
  244. package/dist/esm/components/toolbar/text-rotation-selector.d.ts.map +1 -0
  245. package/dist/esm/components/toolbar/text-rotation-selector.js +71 -0
  246. package/dist/esm/components/toolbar/text-wrap-selector.d.ts +7 -1
  247. package/dist/esm/components/toolbar/text-wrap-selector.d.ts.map +1 -1
  248. package/dist/esm/components/toolbar/text-wrap-selector.js +10 -3
  249. package/dist/esm/components/watch-window/index.d.ts +25 -0
  250. package/dist/esm/components/watch-window/index.d.ts.map +1 -0
  251. package/dist/esm/components/watch-window/index.js +54 -0
  252. package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -1
  253. package/dist/esm/hooks/use-cell-renderer.js +17 -6
  254. package/dist/esm/hooks/use-copy-paste-cut.d.ts +20 -1
  255. package/dist/esm/hooks/use-copy-paste-cut.d.ts.map +1 -1
  256. package/dist/esm/hooks/use-copy-paste-cut.js +8 -3
  257. package/dist/esm/hooks/use-get-tooltip.d.ts.map +1 -1
  258. package/dist/esm/hooks/use-get-tooltip.js +7 -2
  259. package/dist/esm/hooks/use-keyboard-handler.d.ts +17 -2
  260. package/dist/esm/hooks/use-keyboard-handler.d.ts.map +1 -1
  261. package/dist/esm/hooks/use-keyboard-handler.js +193 -31
  262. package/dist/esm/index.d.ts +14 -1
  263. package/dist/esm/index.d.ts.map +1 -1
  264. package/dist/esm/index.js +13 -0
  265. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  266. package/dist/esm/types.d.ts +289 -4
  267. package/dist/esm/types.d.ts.map +1 -1
  268. package/dist/esm/types.js +18 -0
  269. package/dist/spreadsheet.min.css +1 -1
  270. package/package.json +6 -6
@@ -16,9 +16,13 @@ import { CF_INITIAL_WINDOW, cfWindowForViewport, isSameCfWindow, } from "../../a
16
16
  import { generateSelectionsFromFormula } from "../../api/selections";
17
17
  import { SpreadsheetApi } from "../../api/spreadsheet-api";
18
18
  import { findActiveTableWithinCell } from "../../api/table";
19
+ import { getDataValidationTooltipContent } from "../../api/validation-tooltip";
20
+ import { resolveGoToSpecial } from "../../api/go-to-special";
21
+ import { checkExcelValidationValue, isFormulaEntry, } from "../../api/excel-validation-kinds";
19
22
  import { checkBooleanRule, decideValidationCommit, isCellLockedUnderProtection, isProtectedCell, isProtectedSheet, showValidationDropdownArrow, } from "../../api/validation";
20
- import { useFormulaModeValue, useSetNoteEditorCell, useSetPinnedTooltip, useShowPasteMenu, useShowValidationAlert, } from "../../atoms";
23
+ import { useFormulaModeValue, useIsEvaluateFormulaDialogMounted, useIsGoToDialogMounted, useIsPasteSpecialDialogMounted, useOpenEvaluateFormulaDialog, useOpenGoToDialog, useOpenPasteSpecialDialog, useSetNoteEditorCell, useSetPinnedTooltip, useShowPasteMenu, useShowValidationAlert, } from "../../atoms";
21
24
  import { useActiveEditor } from "../../atoms/active-editor.atom";
25
+ import { useAddWatch, useIsWatchWindowMounted, useSetWatchWindowContext, } from "../../atoms/watch-window.atom";
22
26
  import { useEditingCell } from "../../atoms/editing-cell.atom";
23
27
  import { useCellEditorInstance, useSetFormulabarEditorValue, useSetFormulaBarTextFormatRuns, } from "../../atoms/formula-bar-editor-value.atom";
24
28
  import { useFormulaCanSelectCells, useFormulaSelectionMode, useSetFormulaSelectionState, } from "../../atoms/formula-selection-state.atom";
@@ -60,6 +64,7 @@ import { useKeyboardHandler } from "../../hooks/use-keyboard-handler";
60
64
  import { useLicenseKeyValidator } from "../../hooks/use-licensekey-validator";
61
65
  import { useMoveColumnsAndRows } from "../../hooks/use-move-columns-rows";
62
66
  import { useNavigateToSheetRange } from "../../hooks/use-navigate-sheet-range";
67
+ import { createExpressionEvaluator } from "../../api/evaluate-formula";
63
68
  import { useRaf } from "../../hooks/use-raf";
64
69
  import { useResizeObserver } from "../../hooks/use-resize-observer";
65
70
  import { useScaleListener } from "../../hooks/use-scale-listener";
@@ -99,7 +104,7 @@ import { getNestedPropertyNames } from "./helpers";
99
104
  * @returns
100
105
  */
101
106
  function CanvasGridComponent(props, forwardedRef) {
102
- const { licenseKey, sheetId, instanceId, activeCell = DEFAULT_ACTIVE_CELL, selections = DEFAULT_ARRAY, frozenColumnCount = 0, frozenRowCount = 0, rowCount = DEFAULT_ROW_COUNT, columnCount = DEFAULT_COLUMN_COUNT, autoFocus, basicFilter, tables, namedRanges, bandedRanges = DEFAULT_ARRAY, tableBorderColor = "#008000", filterIconColor = "#008000", conditionalFormats, showFilterIcon = true, showCalculatedColumnIcon = true, showHeaders = true, defaultColumnWidth = DEFAULT_COLUMN_WIDTH, defaultRowHeight = DEFAULT_ROW_HEIGHT, columnHeaderHeight = COLUMN_HEADER_HEIGHT, rowHeaderWidth = ROW_HEADER_WIDTH, gridLineColor = GRIDLINE_COLOR, cellBackgroundColor = DEFAULT_CELL_BACKGROUND_COLOR, cellColor = DEFAULT_CELL_COLOR, headerBorderColor = DEFAULT_HEADER_BORDER_COLOR, headerBackgroundColor = DEFAULT_HEADER_BG, headerColor = DEFAULT_HEADER_COLOR, headerActiveBackgroundColor = DEFAULT_HEADER_ACTIVE_BG, headerSelectedBackgroundColor = DEFAULT_HEADER_SELECTED_BG, headerSelectedColor = "white", headerTableBackgroundColor = DEFAULT_HEADER_TABLE_BG, headerTableActiveBackgroundColor = DEFAULT_HEADER_ACTIVE_TABLE_BG, headerTableSelectedBackgroundColor = DEFAULT_HEADER_SELECTED_TABLE_BG, frozenShadowColor = headerBorderColor, frozenShadowThickness = 1, selectionBackgroundColor = SELECTION_BG, selectionBorderColor = SELECTION_BORDER, selectionDragBorderColor = SELECTION_BORDER, chartSelectedColor, chipBackgroundColor = CHIP_COLOR, merges = DEFAULT_ARRAY, borderStyles, protectedRanges, isWorkbookProtected: isWorkbookProtectedProp = false, getSheetProtection, pivotTables, charts, embeds, slicers, rowMetadata = DEFAULT_ARRAY, columnMetadata = DEFAULT_ARRAY, scale = 1, zoomSpeed = 1, overscanCount = 3, enableEditOnEnterKey = true, enableTextOverflow = true, showGridLines: _showGridLines, showFormulas = false, protectFormulas = false, showFrozenSeparator = true, HeaderCell = DefaultHeaderCell, Cell = DefaultCell, SelectionTitleComponent = SelectionTitle, CellEditor = DefaultCellEditor, CellTooltip, ContextMenu = DefaultContextMenu, ContextMenuWrapper = DefaultContextMenuWrapper, FilterBox = DefaultFilterBox, HeaderMoveDragComponent = DefaultHeaderMoveDragComponent, SuggestionsDropdown, stickyEditor = true, scrollSnap = false, scrollThrottleTimeout, preventBrowserDefaultScroll, mouseMoveThrottleTimeout = 60, tooltipIntentInterval = 60, selectionPolicy, users, userId, renderCollaboratorCursor, functionDescriptions, showHeaderMenuButton = true, scrollbarSize = SCROLLBAR_SIZE, theme = defaultSpreadsheetTheme, showNotes = true, showComments = true, locale, agentSuggestions, onReviewSuggestion, onShowFormulas, getDataRowCount, getChartComponent, getEmbedComponent, getSlicerComponent, onChange, onChangeBatch, onExpandCollapse, onPivotDrillDown, onDelete, onChangeEditorValue, onFill, onRequestCalculate, onChangeActiveCell, onChangeActiveSheet, onChangeSelections, getSheetName, getSheetId, getCellData, getNote: getNoteProp, getTextFormatRuns, getDataValidation, getEffectiveFormat, getFormattedValue: getFormattedValueProp, getTooltipContent, errorResolutionComponent, getEffectiveValue: getEffectiveValueProp, getUserEnteredExtendedValue, getEffectiveExtendedValue, getSheetRowCount, getSheetColumnCount, getCellPopoverContent, onScroll, onViewPortChange, windowConditionalFormats = false, engineConditionalFormatResults = false, onResize, onAutoResize, onHideColumn, onHideRow, onShowColumn, onShowRow, onGroupRows, onUngroupRows, onCollapseRowGroup, onExpandRowGroup, onGroupColumns, onUngroupColumns, onCollapseColumnGroup, onExpandColumnGroup, onSetOutlineDepth, onDeleteRow, onDeleteColumn, onInsertRow, onInsertColumn, onInsertCellsShiftDown, onInsertCellsShiftRight, onDeleteCellsShiftLeft, onDeleteCellsShiftUp, onClearContents, onMoveColumns, onMoveRows, onSelectNextSheet, onSelectPreviousSheet, onCreateNewSheet, onKeyDown, onChangeFormatting, onRepeatFormatting, onClearFormatting, onRequestEditProtectedRange, onMoveChart, onResizeChart, onDeleteChart, onMoveEmbed, onResizeEmbed, onDeleteEmbed, onRequestEditEmbed, onMoveSlicer, onResizeSlicer, onDeleteSlicer, onRequestEditSlicer, onFillRange, disableFillRightShortcut, onMoveSelection, onInsertTime, onInsertDate, onInsertDateTime, onInsertAutoSum, onUndo, onRedo, onPaste, onCopy, onCut, onSortColumn, onSortTable, onFilterTable, onFilterPivot, onResizeTable, onRequestEditTable, onRequestEditPivotTable, onRequestDeletePivotTable, onRemoveTable, onCreateTable, onInsertTableColumn, onDeleteTableColumn, onInsertTableRow, onDeleteTableRow, onCreateBasicFilter, onRequestDefineNamedRange, onRequestFormatCells, onRequestConditionalFormat, onRequestDataValidation, onRequestInsertComment, onRequestInsertLink, onFreezeColumn, onFreezeRow, onUpdateNote, onProtectRange, onUnProtectRange, onSortRange, onRequestSearch, onRequestReplace, onRequestResize, getRowHeaderText = getDefaultRowHeader, getColumnHeaderText = getDefaultColumnHeader, getAdditionalCellSpacing, tokenizer: defaultTokenizer = defaultFormulaTokenizer, onChangeScale, onRemoveLink, onSelectLink, onSplitTextToColumns, onRemoveDuplicates, onRequestExpand, cellExpandPredicate, StructuredResult = DefaultStructuredResult, getMentions, getStructuredProperties: getStructuredPropertiesProp, getFunctionParameterSuggestions, shouldFetchFunctionParameters, MentionTagComponent, MentionDropdownItemComponent, showSelectionResizeHandles = true, enableMagicFill, enableQuickEdit = true, MagicFillComponent, MagicFillContent, QuickEdit, PasteMenu, SuggestionAction, HiddenRowMarkers, HiddenColumnMarkers, enableResizerOverflow, className, defaultFontSizePoint = DEFAULT_FONT_SIZE_PT, readonly, isComparing = false, getCellDiff, enableDataBoundaryNavigation, footerHeight, footerComponent, arrowComponents,
107
+ const { licenseKey, sheetId, instanceId, activeCell = DEFAULT_ACTIVE_CELL, selections = DEFAULT_ARRAY, frozenColumnCount = 0, frozenRowCount = 0, rowCount = DEFAULT_ROW_COUNT, columnCount = DEFAULT_COLUMN_COUNT, autoFocus, basicFilter, tables, namedRanges, bandedRanges = DEFAULT_ARRAY, tableBorderColor = "#008000", filterIconColor = "#008000", conditionalFormats, showFilterIcon = true, showCalculatedColumnIcon = true, showHeaders = true, defaultColumnWidth = DEFAULT_COLUMN_WIDTH, defaultRowHeight = DEFAULT_ROW_HEIGHT, columnHeaderHeight = COLUMN_HEADER_HEIGHT, rowHeaderWidth = ROW_HEADER_WIDTH, gridLineColor = GRIDLINE_COLOR, cellBackgroundColor = DEFAULT_CELL_BACKGROUND_COLOR, cellColor = DEFAULT_CELL_COLOR, headerBorderColor = DEFAULT_HEADER_BORDER_COLOR, headerBackgroundColor = DEFAULT_HEADER_BG, headerColor = DEFAULT_HEADER_COLOR, headerActiveBackgroundColor = DEFAULT_HEADER_ACTIVE_BG, headerSelectedBackgroundColor = DEFAULT_HEADER_SELECTED_BG, headerSelectedColor = "white", headerTableBackgroundColor = DEFAULT_HEADER_TABLE_BG, headerTableActiveBackgroundColor = DEFAULT_HEADER_ACTIVE_TABLE_BG, headerTableSelectedBackgroundColor = DEFAULT_HEADER_SELECTED_TABLE_BG, frozenShadowColor = headerBorderColor, frozenShadowThickness = 1, selectionBackgroundColor = SELECTION_BG, selectionBorderColor = SELECTION_BORDER, selectionDragBorderColor = SELECTION_BORDER, chartSelectedColor, chipBackgroundColor = CHIP_COLOR, merges = DEFAULT_ARRAY, borderStyles, protectedRanges, isWorkbookProtected: isWorkbookProtectedProp = false, getSheetProtection, pivotTables, charts, embeds, slicers, rowMetadata = DEFAULT_ARRAY, columnMetadata = DEFAULT_ARRAY, scale = 1, zoomSpeed = 1, overscanCount = 3, enableEditOnEnterKey = true, enableTextOverflow = true, showGridLines: _showGridLines, showFormulas = false, protectFormulas = false, showFrozenSeparator = true, HeaderCell = DefaultHeaderCell, Cell = DefaultCell, SelectionTitleComponent = SelectionTitle, CellEditor = DefaultCellEditor, CellTooltip, ContextMenu = DefaultContextMenu, ContextMenuWrapper = DefaultContextMenuWrapper, FilterBox = DefaultFilterBox, HeaderMoveDragComponent = DefaultHeaderMoveDragComponent, SuggestionsDropdown, stickyEditor = true, scrollSnap = false, scrollThrottleTimeout, preventBrowserDefaultScroll, mouseMoveThrottleTimeout = 60, tooltipIntentInterval = 60, selectionPolicy, users, userId, renderCollaboratorCursor, functionDescriptions, showHeaderMenuButton = true, scrollbarSize = SCROLLBAR_SIZE, theme = defaultSpreadsheetTheme, showNotes = true, showComments = true, locale, agentSuggestions, onReviewSuggestion, onShowFormulas, getDataRowCount, getChartComponent, getEmbedComponent, getSlicerComponent, onChange, onChangeBatch, onExpandCollapse, onPivotDrillDown, onDelete, onChangeEditorValue, onFill, onRequestCalculate, onChangeActiveCell, onChangeActiveSheet, onChangeSelections, getSheetName, getSheetId, getCellData, getNote: getNoteProp, getTextFormatRuns, getDataValidation, getEffectiveFormat, getFormattedValue: getFormattedValueProp, getTooltipContent, errorResolutionComponent, getEffectiveValue: getEffectiveValueProp, getUserEnteredExtendedValue, getEffectiveExtendedValue, getSheetRowCount, getSheetColumnCount, getCellPopoverContent, onScroll, onViewPortChange, windowConditionalFormats = false, engineConditionalFormatResults = false, onResize, onAutoResize, onHideColumn, onHideRow, onShowColumn, onShowRow, onGroupRows, onUngroupRows, onCollapseRowGroup, onExpandRowGroup, onGroupColumns, onUngroupColumns, onCollapseColumnGroup, onExpandColumnGroup, onSetOutlineDepth, onDeleteRow, onDeleteColumn, onInsertRow, onInsertColumn, onInsertCellsShiftDown, onInsertCellsShiftRight, onDeleteCellsShiftLeft, onDeleteCellsShiftUp, onClearContents, onMoveColumns, onMoveRows, onSelectNextSheet, onSelectPreviousSheet, onCreateNewSheet, onKeyDown, onChangeFormatting, onRepeatFormatting, onClearFormatting, onRequestEditProtectedRange, onMoveChart, onResizeChart, onDeleteChart, onMoveEmbed, onResizeEmbed, onDeleteEmbed, onRequestEditEmbed, onMoveSlicer, onResizeSlicer, onDeleteSlicer, onRequestEditSlicer, onFillRange, disableFillRightShortcut, keymap, onCalculateNow, onRequestGoTo, onMoveSelection, onInsertTime, onInsertDate, onInsertDateTime, onInsertAutoSum, onUndo, onRedo, onPaste, onCopy, onCut, onSortColumn, onSortTable, onFilterTable, onFilterPivot, onResizeTable, onRequestEditTable, onRequestEditPivotTable, onRequestDeletePivotTable, onRemoveTable, onCreateTable, onInsertTableColumn, onDeleteTableColumn, onInsertTableRow, onDeleteTableRow, onCreateBasicFilter, onRequestDefineNamedRange, onRequestFormatCells, onRequestConditionalFormat, onRequestDataValidation, onRequestInsertComment, onRequestInsertLink, onFreezeColumn, onFreezeRow, onUpdateNote, onProtectRange, onUnProtectRange, onSortRange, onRequestSearch, onRequestReplace, onRequestResize, getRowHeaderText = getDefaultRowHeader, getColumnHeaderText = getDefaultColumnHeader, getAdditionalCellSpacing, tokenizer: defaultTokenizer = defaultFormulaTokenizer, onChangeScale, onRemoveLink, onSelectLink, onSplitTextToColumns, onRemoveDuplicates, onGoalSeek, onSubtotal, onAdvancedFilter, onRequestExpand, cellExpandPredicate, StructuredResult = DefaultStructuredResult, getMentions, getStructuredProperties: getStructuredPropertiesProp, getFunctionParameterSuggestions, shouldFetchFunctionParameters, MentionTagComponent, MentionDropdownItemComponent, showSelectionResizeHandles = true, enableMagicFill, enableQuickEdit = true, MagicFillComponent, MagicFillContent, QuickEdit, PasteMenu, SuggestionAction, HiddenRowMarkers, HiddenColumnMarkers, enableResizerOverflow, className, defaultFontSizePoint = DEFAULT_FONT_SIZE_PT, readonly, isComparing = false, getCellDiff, enableDataBoundaryNavigation, footerHeight, footerComponent, arrowComponents,
103
108
  // Host-driven filter props. `hostHiddenRowRanges`
104
109
  // supplies compact [start, end] hidden-row tuples; `getFilterValues` supplies a
105
110
  // column's distinct values. Both let a million-row filter render without scanning
@@ -1303,6 +1308,23 @@ function CanvasGridComponent(props, forwardedRef) {
1303
1308
  if (rule.allowBlank && isBlank) {
1304
1309
  return undefined;
1305
1310
  }
1311
+ // A typed formula is validated on its RESULT once the calculator has
1312
+ // run (Excel enters `=5` into a whole-number cell and checks the 5) —
1313
+ // its text can never be decided here, so it stays flag-only.
1314
+ if (isFormulaEntry(value)) {
1315
+ return undefined;
1316
+ }
1317
+ // Excel's Whole number / Time / Text length kinds (authored or imported
1318
+ // with `xlsxSource`) are decided synchronously from the typed text when
1319
+ // their bounds are literals — Excel blocks a decimal in a whole-number
1320
+ // cell at entry, not after a recalc.
1321
+ const excelKindVerdict = checkExcelValidationValue(rule, value);
1322
+ if (excelKindVerdict !== undefined) {
1323
+ const excelDecision = decideValidationCommit(alert, excelKindVerdict);
1324
+ return excelDecision === "proceed"
1325
+ ? undefined
1326
+ : { decision: excelDecision, alert };
1327
+ }
1306
1328
  if (isDataValidationFormulaRule(rule)) {
1307
1329
  // Enforce synchronously only where `checkBooleanRule` can decide the typed
1308
1330
  // value without the calculator: CUSTOM_FORMULA's sync branch is a stub, the
@@ -1840,28 +1862,17 @@ function CanvasGridComponent(props, forwardedRef) {
1840
1862
  * shown in tooltip
1841
1863
  */
1842
1864
  /**
1843
- * Compose host tooltip content with the data-validation input message.
1844
- * Host-provided content wins; otherwise, when the cell is not already showing
1845
- * an error / invalid marker, surface the rule's input message (Excel's
1846
- * "show input message when cell is selected").
1865
+ * Compose host tooltip content with the data-validation messages. Host-
1866
+ * provided content wins; otherwise the rule's input message (Excel's "show
1867
+ * input message when cell is selected") or, on an Invalid cell, the rule's
1868
+ * custom error alert text see `getDataValidationTooltipContent`.
1847
1869
  */
1848
1870
  const getTooltipContentWithValidation = useCallback((tooltipSheetId, rowIndex, columnIndex) => {
1849
1871
  const hostContent = getTooltipContent?.(tooltipSheetId, rowIndex, columnIndex);
1850
1872
  if (hostContent != null) {
1851
1873
  return hostContent;
1852
1874
  }
1853
- const error = getErrorValue(tooltipSheetId, rowIndex, columnIndex);
1854
- if (error?.type === "Error" || error?.type === "Invalid") {
1855
- return undefined;
1856
- }
1857
- const rule = getDataValidationRule(tooltipSheetId, rowIndex, columnIndex);
1858
- const inputMessage = rule?.inputMessage;
1859
- if (!inputMessage || (!inputMessage.title && !inputMessage.message)) {
1860
- return undefined;
1861
- }
1862
- return (React.createElement("div", { className: "bg-rnc-background text-rnc-foreground p-2 shadow-md rounded-md border-l-4 border-solid border-l-blue-700 max-w-[300px] flex flex-col gap-0.5" },
1863
- inputMessage.title ? (React.createElement("div", { className: "font-bold font-system text-sm" }, inputMessage.title)) : null,
1864
- inputMessage.message ? (React.createElement("div", { className: "text-xs font-system whitespace-pre-wrap" }, inputMessage.message)) : null));
1875
+ return getDataValidationTooltipContent(getDataValidationRule(tooltipSheetId, rowIndex, columnIndex), getErrorValue(tooltipSheetId, rowIndex, columnIndex));
1865
1876
  }, [getTooltipContent, getErrorValue, getDataValidationRule]);
1866
1877
  const getTooltip = useGetTooltip({
1867
1878
  sheetId,
@@ -1937,6 +1948,90 @@ function CanvasGridComponent(props, forwardedRef) {
1937
1948
  onCopy,
1938
1949
  onCut,
1939
1950
  });
1951
+ /**
1952
+ * Paste Special dialog (context menu → Paste special…, Ctrl+Alt+V). The
1953
+ * dialog is host-mounted (`PasteSpecialDialogHost`); its request routes
1954
+ * back through the same `paste()` the submenu uses. Without a mounted host
1955
+ * the trigger stays undefined so the menu item is not shown and the
1956
+ * shortcut is not claimed (a host that has not adopted the dialog keeps
1957
+ * its previous behaviour instead of a dead action).
1958
+ */
1959
+ const openPasteSpecialDialog = useOpenPasteSpecialDialog();
1960
+ const isPasteSpecialDialogMounted = useIsPasteSpecialDialogMounted();
1961
+ const requestPasteSpecial = useMemo(() => {
1962
+ if (!isPasteSpecialDialogMounted)
1963
+ return undefined;
1964
+ return () => {
1965
+ if (readonly)
1966
+ return;
1967
+ openPasteSpecialDialog({
1968
+ onApply: (options) => {
1969
+ void paste(options);
1970
+ },
1971
+ });
1972
+ };
1973
+ }, [isPasteSpecialDialogMounted, openPasteSpecialDialog, paste, readonly]);
1974
+ /**
1975
+ * Evaluate Formula dialog (context menu → Evaluate formula) for a formula
1976
+ * cell. Steps are scratch-evaluated through `onRequestCalculate`, the cell
1977
+ * editor's live-preview calculator, so nothing is written to the sheet.
1978
+ * Only offered while an `EvaluateFormulaDialogHost` is mounted.
1979
+ */
1980
+ const openEvaluateFormulaDialog = useOpenEvaluateFormulaDialog();
1981
+ const isEvaluateFormulaDialogMounted = useIsEvaluateFormulaDialogMounted();
1982
+ const requestEvaluateFormula = useMemo(() => {
1983
+ if (!isEvaluateFormulaDialogMounted || !onRequestCalculate)
1984
+ return undefined;
1985
+ return (evaluateSheetId, cell) => {
1986
+ const formula = getFormulaValue(evaluateSheetId, cell.rowIndex, cell.columnIndex);
1987
+ if (!formula)
1988
+ return;
1989
+ openEvaluateFormulaDialog({
1990
+ sheetId: evaluateSheetId,
1991
+ cell,
1992
+ sheetName: getSheetName?.(evaluateSheetId),
1993
+ formula,
1994
+ evaluate: createExpressionEvaluator(onRequestCalculate, evaluateSheetId, cell),
1995
+ });
1996
+ };
1997
+ }, [
1998
+ isEvaluateFormulaDialogMounted,
1999
+ openEvaluateFormulaDialog,
2000
+ getFormulaValue,
2001
+ getSheetName,
2002
+ onRequestCalculate,
2003
+ ]);
2004
+ /**
2005
+ * Watch Window: "Add to Watch Window" is offered only while a
2006
+ * `WatchWindowHost` is mounted; the live getters are published below once
2007
+ * `navigateToSheetRange` exists.
2008
+ */
2009
+ const addWatch = useAddWatch();
2010
+ const isWatchWindowMounted = useIsWatchWindowMounted();
2011
+ const setWatchWindowContext = useSetWatchWindowContext();
2012
+ const requestAddWatch = useMemo(() => {
2013
+ if (!isWatchWindowMounted)
2014
+ return undefined;
2015
+ return (watchSheetId, cell) => addWatch({ sheetId: watchSheetId, ...cell });
2016
+ }, [isWatchWindowMounted, addWatch]);
2017
+ /**
2018
+ * Go To (Ctrl+G / F5). A host `onRequestGoTo` wins; otherwise the built-in
2019
+ * dialog opens — but only while a `GoToDialogHost` is mounted, so a host
2020
+ * without one keeps the browser's own Ctrl+G / F5 (the keyboard handler
2021
+ * claims the keys only when this is defined). The built-in opener needs
2022
+ * `navigateToSheetRange`, which is created further down, so it is reached
2023
+ * through a ref.
2024
+ */
2025
+ const openGoToDialog = useOpenGoToDialog();
2026
+ const isGoToDialogMounted = useIsGoToDialogMounted();
2027
+ const builtInGoToRef = useRef(() => undefined);
2028
+ const requestGoTo = useMemo(() => {
2029
+ if (onRequestGoTo)
2030
+ return onRequestGoTo;
2031
+ if (!isGoToDialogMounted)
2032
+ return undefined;
2033
+ return (goToSheetId, goToActiveCell, goToSelections) => builtInGoToRef.current(goToSheetId, goToActiveCell, goToSelections);
2034
+ }, [onRequestGoTo, isGoToDialogMounted]);
1940
2035
  /**
1941
2036
  * After formula mode
1942
2037
  * Recover old selections
@@ -2093,7 +2188,7 @@ function CanvasGridComponent(props, forwardedRef) {
2093
2188
  * Get context Menu component
2094
2189
  */
2095
2190
  const getContextMenu = useCallback((cell) => {
2096
- return (React.createElement(ContextMenu, { activeCell: activeCell, selections: selections, sheetId: sheetId, frozenRows: frozenRows, frozenColumns: frozenColumns, onHideColumn: isRestricted ? undefined : onHideColumn, onShowColumn: isRestricted ? undefined : onShowColumn, onShowRow: isRestricted ? undefined : onShowRow, onHideRow: isRestricted ? undefined : onHideRow, onGroupRows: isRestricted ? undefined : onGroupRows, onUngroupRows: isRestricted ? undefined : onUngroupRows, onGroupColumns: isRestricted ? undefined : onGroupColumns, onUngroupColumns: isRestricted ? undefined : onUngroupColumns, isHiddenColumn: isHiddenColumn, isHiddenRow: isHiddenRow, onDeleteColumn: onDeleteColumn, onDeleteRow: onDeleteRow, onInsertRow: onInsertRow, onInsertColumn: onInsertColumn, onInsertCellsShiftDown: onInsertCellsShiftDown, onInsertCellsShiftRight: onInsertCellsShiftRight, onDeleteCellsShiftLeft: onDeleteCellsShiftLeft, onDeleteCellsShiftUp: onDeleteCellsShiftUp, onClearContents: onClearContents, onFreezeColumn: onFreezeColumn, onFreezeRow: onFreezeRow, focusSheet: focusSheet, onSortColumn: onSortColumn, onInsertNote: onInsertNote, onProtectRange: onProtectRange, onUnProtectRange: onUnProtectRange, onSortRange: onSortRange, onRequestDefineNamedRange: onRequestDefineNamedRange, protectedRanges: protectedRanges, isRowHeader: isRowHeader(cell.columnIndex), isColumnHeader: isColumnHeader(cell.rowIndex), selectedRowHeadersIds: selectedRowHeadersIds, selectedColumnHeadersIds: selectedColumnHeadersIds, onCopy: copy, onCut: cut, onPaste: paste, onRequestResize: onRequestResize, isSheetFocused: isSheetFocused, tables: activeTables, pivotTables: pivotTables, basicFilter: basicFilter, onRequestEditTable: onRequestEditTable, onRequestEditPivotTable: onRequestEditPivotTable, onRemoveTable: onRemoveTable, onRequestDeletePivotTable: onRequestDeletePivotTable, onPivotDrillDown: onPivotDrillDown, onRequestFormatCells: onRequestFormatCells, onRequestConditionalFormat: onRequestConditionalFormat, onRequestDataValidation: onRequestDataValidation, onClearFormatting: onClearFormatting, onCreateTable: onCreateTable, onCreateBasicFilter: onCreateBasicFilter, onInsertTableColumn: onInsertTableColumn, onDeleteTableColumn: onDeleteTableColumn, onInsertTableRow: onInsertTableRow, onDeleteTableRow: onDeleteTableRow, onFilterTable: onFilterTable, onSortTable: onSortTable, getFormattedValue: getFormattedValue, getFormattedValuesFromRange: getFormattedValuesFromRange, isTableHeader: isTableHeader, readonly: readonly, onSplitTextToColumns: onSplitTextToColumns, onRemoveDuplicates: onRemoveDuplicates, onAddQuickEdit: onAddQuickEdit, enableMagicFill: enableMagicFill }));
2191
+ return (React.createElement(ContextMenu, { activeCell: activeCell, selections: selections, sheetId: sheetId, frozenRows: frozenRows, frozenColumns: frozenColumns, onHideColumn: isRestricted ? undefined : onHideColumn, onShowColumn: isRestricted ? undefined : onShowColumn, onShowRow: isRestricted ? undefined : onShowRow, onHideRow: isRestricted ? undefined : onHideRow, onGroupRows: isRestricted ? undefined : onGroupRows, onUngroupRows: isRestricted ? undefined : onUngroupRows, onGroupColumns: isRestricted ? undefined : onGroupColumns, onUngroupColumns: isRestricted ? undefined : onUngroupColumns, isHiddenColumn: isHiddenColumn, isHiddenRow: isHiddenRow, onDeleteColumn: onDeleteColumn, onDeleteRow: onDeleteRow, onInsertRow: onInsertRow, onInsertColumn: onInsertColumn, onInsertCellsShiftDown: onInsertCellsShiftDown, onInsertCellsShiftRight: onInsertCellsShiftRight, onDeleteCellsShiftLeft: onDeleteCellsShiftLeft, onDeleteCellsShiftUp: onDeleteCellsShiftUp, onClearContents: onClearContents, onFreezeColumn: onFreezeColumn, onFreezeRow: onFreezeRow, focusSheet: focusSheet, onSortColumn: onSortColumn, onInsertNote: onInsertNote, onProtectRange: onProtectRange, onUnProtectRange: onUnProtectRange, onSortRange: onSortRange, onRequestDefineNamedRange: onRequestDefineNamedRange, protectedRanges: protectedRanges, isRowHeader: isRowHeader(cell.columnIndex), isColumnHeader: isColumnHeader(cell.rowIndex), selectedRowHeadersIds: selectedRowHeadersIds, selectedColumnHeadersIds: selectedColumnHeadersIds, onCopy: copy, onCut: cut, onPaste: paste, onRequestPasteSpecial: requestPasteSpecial, onRequestEvaluateFormula: requestEvaluateFormula, onRequestAddWatch: requestAddWatch, isActiveCellFormula: Boolean(getFormulaValue(sheetId, activeCell.rowIndex, activeCell.columnIndex)), onRequestResize: onRequestResize, isSheetFocused: isSheetFocused, tables: activeTables, pivotTables: pivotTables, basicFilter: basicFilter, onRequestEditTable: onRequestEditTable, onRequestEditPivotTable: onRequestEditPivotTable, onRemoveTable: onRemoveTable, onRequestDeletePivotTable: onRequestDeletePivotTable, onPivotDrillDown: onPivotDrillDown, onRequestFormatCells: onRequestFormatCells, onRequestConditionalFormat: onRequestConditionalFormat, onRequestDataValidation: onRequestDataValidation, onClearFormatting: onClearFormatting, onCreateTable: onCreateTable, onCreateBasicFilter: onCreateBasicFilter, onInsertTableColumn: onInsertTableColumn, onDeleteTableColumn: onDeleteTableColumn, onInsertTableRow: onInsertTableRow, onDeleteTableRow: onDeleteTableRow, onFilterTable: onFilterTable, onSortTable: onSortTable, getFormattedValue: getFormattedValue, getFormattedValuesFromRange: getFormattedValuesFromRange, isTableHeader: isTableHeader, readonly: readonly, onSplitTextToColumns: onSplitTextToColumns, onRemoveDuplicates: onRemoveDuplicates, onGoalSeek: onGoalSeek, onSubtotal: onSubtotal, onAdvancedFilter: onAdvancedFilter, onChange: onChange, getCellData: getCellData, onAddQuickEdit: onAddQuickEdit, enableMagicFill: enableMagicFill }));
2097
2192
  }, [
2098
2193
  isRestricted,
2099
2194
  activeCell,
@@ -2120,6 +2215,9 @@ function CanvasGridComponent(props, forwardedRef) {
2120
2215
  copy,
2121
2216
  paste,
2122
2217
  cut,
2218
+ requestPasteSpecial,
2219
+ requestEvaluateFormula,
2220
+ getFormulaValue,
2123
2221
  onInsertNote,
2124
2222
  onProtectRange,
2125
2223
  onUnProtectRange,
@@ -2158,6 +2256,11 @@ function CanvasGridComponent(props, forwardedRef) {
2158
2256
  enableMagicFill,
2159
2257
  onSplitTextToColumns,
2160
2258
  onRemoveDuplicates,
2259
+ onGoalSeek,
2260
+ onSubtotal,
2261
+ onAdvancedFilter,
2262
+ onChange,
2263
+ getCellData,
2161
2264
  onRequestDeletePivotTable,
2162
2265
  isHiddenColumn,
2163
2266
  isHiddenRow,
@@ -2198,6 +2301,8 @@ function CanvasGridComponent(props, forwardedRef) {
2198
2301
  selections,
2199
2302
  selectedColumns,
2200
2303
  selectedRows,
2304
+ selectedColumnHeadersIds,
2305
+ selectedRowHeadersIds,
2201
2306
  onChangeFormatting,
2202
2307
  onRepeatFormatting,
2203
2308
  onInsertNote,
@@ -2207,6 +2312,13 @@ function CanvasGridComponent(props, forwardedRef) {
2207
2312
  onCreateNewSheet,
2208
2313
  onFillRange,
2209
2314
  disableFillRightShortcut,
2315
+ keymap,
2316
+ onCalculateNow,
2317
+ onRequestGoTo: requestGoTo,
2318
+ onRequestPasteSpecial: requestPasteSpecial,
2319
+ onChangeBatch,
2320
+ getUserEnteredValue: getUserEnteredStringValue,
2321
+ getEffectiveValue,
2210
2322
  onInsertTime,
2211
2323
  onInsertDate,
2212
2324
  onInsertDateTime,
@@ -2976,6 +3088,77 @@ function CanvasGridComponent(props, forwardedRef) {
2976
3088
  setActiveCell,
2977
3089
  flash,
2978
3090
  });
3091
+ // Built-in Go To: resolve against the workbook, then select + scroll. Go
3092
+ // To Special scans the current selection (the whole sheet for a single
3093
+ // cell) through the host's `getCellData`.
3094
+ useIsomorphicLayoutEffect(() => {
3095
+ builtInGoToRef.current = (goToSheetId, goToActiveCell, goToSelections) => {
3096
+ const scanRange = goToSelections?.length && goToSelections[0]
3097
+ ? goToSelections[0].range
3098
+ : {
3099
+ startRowIndex: 1,
3100
+ endRowIndex: Math.max(1, sheetRowCount - 1),
3101
+ startColumnIndex: 1,
3102
+ endColumnIndex: Math.max(1, sheetColumnCount - 1),
3103
+ };
3104
+ openGoToDialog({
3105
+ sheetId: goToSheetId,
3106
+ activeCell: goToActiveCell,
3107
+ namedRanges,
3108
+ getSheetId,
3109
+ getSheetName,
3110
+ rowCount,
3111
+ columnCount,
3112
+ onNavigate: (range) => {
3113
+ navigateToSheetRange(range, { enableFlash: false });
3114
+ focusSheet();
3115
+ },
3116
+ special: getCellData
3117
+ ? {
3118
+ resolve: (kind) => resolveGoToSpecial(kind, {
3119
+ sheetId: goToSheetId,
3120
+ range: scanRange,
3121
+ getCellData,
3122
+ isRowHidden: isHiddenRow,
3123
+ isColumnHidden: isHiddenColumn,
3124
+ }),
3125
+ onSelectRanges: (ranges) => {
3126
+ const first = ranges[0];
3127
+ if (!first)
3128
+ return;
3129
+ setActiveCell(goToSheetId, {
3130
+ rowIndex: first.startRowIndex,
3131
+ columnIndex: first.startColumnIndex,
3132
+ });
3133
+ onChangeSelections?.(goToSheetId, ranges.map((range) => ({ range })));
3134
+ focusSheet();
3135
+ },
3136
+ }
3137
+ : undefined,
3138
+ });
3139
+ };
3140
+ });
3141
+ // Watch Window live getters — republished per render while a host is
3142
+ // mounted so the panel tracks recalculation.
3143
+ useIsomorphicLayoutEffect(() => {
3144
+ if (!isWatchWindowMounted)
3145
+ return;
3146
+ setWatchWindowContext({
3147
+ getSheetName,
3148
+ getFormattedValue,
3149
+ getFormula: getFormulaValue,
3150
+ onNavigate: (cell) => {
3151
+ navigateToSheetRange({
3152
+ sheetId: cell.sheetId,
3153
+ startRowIndex: cell.rowIndex,
3154
+ endRowIndex: cell.rowIndex,
3155
+ startColumnIndex: cell.columnIndex,
3156
+ endColumnIndex: cell.columnIndex,
3157
+ }, { enableFlash: false });
3158
+ focusSheet();
3159
+ },
3160
+ });
3161
+ });
2979
3162
  // Dispatch keyboard event
2980
3163
  const dispatchEvent = useCallback((event) => {
2981
3164
  gridRef.current?.container?.dispatchEvent(event);
@@ -6,14 +6,14 @@ import type { CellDiff } from "@rowsncolumns/version-comparison";
6
6
  import type { ElementType } from "react";
7
7
  import type React from "react";
8
8
  import type { ContextMenuWrapperProps } from "../../hooks/use-context-menu";
9
- import type { PasteSpecialType } from "../../hooks/use-copy-paste-cut";
9
+ import type { PasteSpecialRequest } from "../../hooks/use-copy-paste-cut";
10
10
  import type { MakeEditableOptions } from "../../hooks/use-editable";
11
11
  import type { ExportRangeOutput } from "../../hooks/use-export-range";
12
12
  import type { useFlash } from "../../hooks/use-flash";
13
13
  import type { useNavigateToSheetRange } from "../../hooks/use-navigate-sheet-range";
14
14
  import type { UseSelectionOptions } from "../../hooks/use-selection";
15
15
  import type { GetCellDimensionsOptions as SizerGetCellDimensionsOptions, useSizer } from "../../hooks/use-sizer";
16
- import type { AgentSuggestion, BandedDefinition, BandedRange, BorderStyle, CellFormat, Collaborator, Color, ColorFilterCriteria, ConditionType, ConditionValue, DataValidationRule, DataValidationRuleRecord, EmbeddedObject, IconFilterCriteria, Maybe, NamedRange, ParsedToken, PivotTable, ProtectedRange, Sheet, SheetCoordinate, SheetProtection, SheetRange, Slicer, SortOrder, SortSpecs, TableTheme, TableView } from "../../types";
16
+ import type { AgentSuggestion, BandedDefinition, BandedRange, BorderStyle, CellFormat, Collaborator, Color, ColorFilterCriteria, ConditionType, ConditionValue, DataValidationRule, DataValidationRuleRecord, EmbeddedObject, IconFilterCriteria, Maybe, NamedRange, ParsedToken, PivotTable, ProtectedRange, RemoveDuplicatesOptions, AdvancedFilterOptions, AdvancedFilterResult, GoalSeekResult, SplitTextOptions, SubtotalOptions, SubtotalResult, Sheet, SheetCoordinate, SheetProtection, SheetRange, Slicer, SortOrder, SortSpecs, TableTheme, TableView } from "../../types";
17
17
  import type { AXIS, CellData, ConditionalFormatRule, EmbeddedChart, FilterView } from "../../types";
18
18
  import type { CellProps } from "../cell/typings";
19
19
  import type { CellEditorProps } from "../cell-editor";
@@ -33,6 +33,11 @@ import type { SuggestionActionProps } from "../selection/suggestion-action";
33
33
  import type { SelectionTitleProps } from "../selection/title";
34
34
  import type { BorderLocation } from "../toolbar";
35
35
  export type ExtractMentionType<T> = T extends CellData<any, infer M> ? M : Mention;
36
+ /**
37
+ * Keyboard shortcut flavour for the combos Excel and Google Sheets bind
38
+ * differently. See `CanvasGridProps["keymap"]`.
39
+ */
40
+ export type SpreadsheetKeymap = "sheets" | "excel";
36
41
  /**
37
42
  * Color / icon / custom-list sort options shared by the column-, table-
38
43
  * and range-sort callbacks. Mirrors the engine's `DimensionSortSpec`
@@ -1044,6 +1049,45 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
1044
1049
  * When true, key combo falls through to the browser default.
1045
1050
  */
1046
1051
  disableFillRightShortcut?: boolean;
1052
+ /**
1053
+ * Which product's shortcuts win where Excel and Google Sheets disagree.
1054
+ *
1055
+ * Both keymaps share every non-conflicting binding (Excel's `Ctrl+R`,
1056
+ * `Ctrl+T`, `Ctrl+1`, `Ctrl+5`, `F9`, `Ctrl+'`, `Ctrl+G` are always on,
1057
+ * as are Sheets' `Ctrl+Alt+T`, `Ctrl+Alt+1`, `Ctrl+Alt+9/0`, and the
1058
+ * unhide combos both products share, `Ctrl+Shift+9` / `Ctrl+Shift+0`).
1059
+ * The keymap only decides the combos the two products bind differently:
1060
+ *
1061
+ * | Shortcut | `"sheets"` (default) | `"excel"` |
1062
+ * | ---------------- | -------------------- | --------------------- |
1063
+ * | Ctrl+Shift+L | Align left | Toggle AutoFilter |
1064
+ * | Ctrl+9 / Ctrl+0 | (browser) | Hide rows / columns |
1065
+ *
1066
+ * Hide / unhide act on the rows / columns selected through their headers
1067
+ * plus the rows / columns of the selected cell ranges (what the context
1068
+ * menu's Hide item uses). With the other axis fully selected there is
1069
+ * nothing to act on and the shortcut is a no-op (Excel would hide every
1070
+ * row / column).
1071
+ */
1072
+ keymap?: SpreadsheetKeymap;
1073
+ /**
1074
+ * Excel `F9` (workbook) / `Shift+F9` (active sheet): recalculate now.
1075
+ * Hosts wire this to `calculateNow` from `useSpreadsheetState` /
1076
+ * `useSpreadsheetEngine`; the shortcut is inert when omitted.
1077
+ * @param sheetId
1078
+ * @param scope
1079
+ */
1080
+ onCalculateNow?(sheetId: number, scope: "workbook" | "sheet"): void | Promise<void>;
1081
+ /**
1082
+ * Excel `Ctrl+G` / `F5`: the user wants the Go To dialog (or the Name
1083
+ * Box focused). When omitted the grid opens its built-in Go To dialog —
1084
+ * mount `<GoToDialogHost />` in the host next to the other editor
1085
+ * dialogs. Provide this to replace it with your own UI.
1086
+ * @param sheetId
1087
+ * @param activeCell
1088
+ * @param selections
1089
+ */
1090
+ onRequestGoTo?(sheetId: number, activeCell: CellInterface, selections: SelectionArea<SelectionAttributes>[]): void;
1047
1091
  /**
1048
1092
  * User is creating a new chart
1049
1093
  * @param sheetId
@@ -1282,9 +1326,9 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
1282
1326
  */
1283
1327
  onDeleteTableRow?(table: TableView, rowIndexes: number[]): void;
1284
1328
  /**
1285
- * Create a basic filter
1286
- * Ctrl+Shift+F
1287
- * Cmd+Shift+F
1329
+ * Create a basic filter, or remove the sheet's existing one when the
1330
+ * selection touches it (a toggle).
1331
+ * Ctrl+Shift+F / Cmd+Shift+F, and Ctrl+Shift+L under `keymap="excel"`
1288
1332
  * @param sheetId
1289
1333
  * @param activeCell
1290
1334
  * @param selections
@@ -1483,7 +1527,7 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
1483
1527
  * @param delimiter
1484
1528
  * @returns
1485
1529
  */
1486
- onSplitTextToColumns?: (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[], delimiter?: string) => void;
1530
+ onSplitTextToColumns?: (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[], delimiter?: string, options?: SplitTextOptions) => void;
1487
1531
  /**
1488
1532
  * Remove duplicate rows
1489
1533
  * @param sheetId
@@ -1491,7 +1535,24 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
1491
1535
  * @param selections
1492
1536
  * @returns
1493
1537
  */
1494
- onRemoveDuplicates?: (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[]) => void;
1538
+ onRemoveDuplicates?: (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[], options?: RemoveDuplicatesOptions) => void;
1539
+ /**
1540
+ * Excel's Goal Seek: find the `changingCell` value that makes the formula in
1541
+ * `setCell` evaluate to `targetValue`, then commit it. Resolves to the
1542
+ * search result (status + value), or `undefined` when the engine reports
1543
+ * no result (the rnc engine iterates natively) or the set cell has no formula.
1544
+ */
1545
+ onGoalSeek?: (sheetId: number, setCell: CellInterface, targetValue: number, changingCell: CellInterface) => Promise<GoalSeekResult | undefined>;
1546
+ /**
1547
+ * Excel's Data → Subtotal: insert "<group> Total" / "Grand Total" rows with
1548
+ * `SUBTOTAL(...)` formulas and outline the groups.
1549
+ */
1550
+ onSubtotal?: (sheetId: number, options: SubtotalOptions) => SubtotalResult | undefined;
1551
+ /**
1552
+ * Excel's Data → Advanced filter: filter a list in place (hide non-matching
1553
+ * rows) or copy the matching records elsewhere, driven by a criteria range.
1554
+ */
1555
+ onAdvancedFilter?: (sheetId: number, options: AdvancedFilterOptions) => AdvancedFilterResult | undefined;
1495
1556
  /**
1496
1557
  * Callback to get effective value of a cell
1497
1558
  * @param sheetId
@@ -1980,10 +2041,12 @@ export type CanvasGridMethods = {
1980
2041
  */
1981
2042
  cut?: () => void;
1982
2043
  /**
1983
- * Copies current selections
2044
+ * Pastes the clipboard at the active cell. Pass a legacy single mode
2045
+ * (`"Value"`, `"Transposed"`, …) or a full `PasteSpecialOptions` request
2046
+ * (paste what / operation / skip blanks / transpose).
1984
2047
  * @returns
1985
2048
  */
1986
- paste?: (pasteSpecial?: PasteSpecialType) => void;
2049
+ paste?: (pasteSpecial?: PasteSpecialRequest) => void;
1987
2050
  };
1988
2051
  export type SelectionAttributes = RangeStyle & {
1989
2052
  sheetName?: string;