@rowsncolumns/spreadsheet 10.2.77 → 10.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/dist/cjs/api/insert-options.d.ts +67 -0
  2. package/dist/cjs/api/insert-options.d.ts.map +1 -0
  3. package/dist/cjs/api/insert-options.js +104 -0
  4. package/dist/cjs/api/move-overwrite.d.ts +14 -0
  5. package/dist/cjs/api/move-overwrite.d.ts.map +1 -0
  6. package/dist/cjs/api/move-overwrite.js +29 -0
  7. package/dist/cjs/api/multi-selection.d.ts +59 -0
  8. package/dist/cjs/api/multi-selection.d.ts.map +1 -0
  9. package/dist/cjs/api/multi-selection.js +166 -0
  10. package/dist/cjs/atoms/index.d.ts +3 -0
  11. package/dist/cjs/atoms/index.d.ts.map +1 -1
  12. package/dist/cjs/atoms/index.js +3 -0
  13. package/dist/cjs/atoms/insert-cells-dialog.atom.d.ts +36 -0
  14. package/dist/cjs/atoms/insert-cells-dialog.atom.d.ts.map +1 -0
  15. package/dist/cjs/atoms/insert-cells-dialog.atom.js +34 -0
  16. package/dist/cjs/atoms/insert-options.atom.d.ts +21 -0
  17. package/dist/cjs/atoms/insert-options.atom.d.ts.map +1 -0
  18. package/dist/cjs/atoms/insert-options.atom.js +11 -0
  19. package/dist/cjs/atoms/move-overwrite-confirm.atom.d.ts +24 -0
  20. package/dist/cjs/atoms/move-overwrite-confirm.atom.d.ts.map +1 -0
  21. package/dist/cjs/atoms/move-overwrite-confirm.atom.js +42 -0
  22. package/dist/cjs/atoms/sheet-context.atom.d.ts +2 -0
  23. package/dist/cjs/atoms/sheet-context.atom.d.ts.map +1 -1
  24. package/dist/cjs/atoms/sheet-context.atom.js +15 -2
  25. package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
  26. package/dist/cjs/components/canvas-grid/index.js +298 -68
  27. package/dist/cjs/components/canvas-grid/typings.d.ts +47 -5
  28. package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
  29. package/dist/cjs/components/cell-editor/formula-result-preview.d.ts +4 -1
  30. package/dist/cjs/components/cell-editor/formula-result-preview.d.ts.map +1 -1
  31. package/dist/cjs/components/cell-editor/formula-result-preview.js +2 -2
  32. package/dist/cjs/components/cell-editor/index.d.ts +7 -1
  33. package/dist/cjs/components/cell-editor/index.d.ts.map +1 -1
  34. package/dist/cjs/components/cell-editor/index.js +3 -3
  35. package/dist/cjs/components/cell-input/cell-input.d.ts +13 -0
  36. package/dist/cjs/components/cell-input/cell-input.d.ts.map +1 -1
  37. package/dist/cjs/components/cell-input/cell-input.js +8 -3
  38. package/dist/cjs/components/cell-input/formula-bar-cell-input.d.ts.map +1 -1
  39. package/dist/cjs/components/cell-input/formula-bar-cell-input.js +3 -1
  40. package/dist/cjs/components/context-menu/index.d.ts +16 -1
  41. package/dist/cjs/components/context-menu/index.d.ts.map +1 -1
  42. package/dist/cjs/components/context-menu/index.js +245 -24
  43. package/dist/cjs/components/embeds/embed-draggable.d.ts.map +1 -1
  44. package/dist/cjs/components/embeds/embed-draggable.js +4 -3
  45. package/dist/cjs/components/floating-cell-editor/index.d.ts.map +1 -1
  46. package/dist/cjs/components/floating-cell-editor/index.js +13 -5
  47. package/dist/cjs/components/insert-cells-dialog/index.d.ts +35 -0
  48. package/dist/cjs/components/insert-cells-dialog/index.d.ts.map +1 -0
  49. package/dist/cjs/components/insert-cells-dialog/index.js +84 -0
  50. package/dist/cjs/components/insert-options-smart-tag/index.d.ts +25 -0
  51. package/dist/cjs/components/insert-options-smart-tag/index.d.ts.map +1 -0
  52. package/dist/cjs/components/insert-options-smart-tag/index.js +41 -0
  53. package/dist/cjs/components/move-overwrite-confirm-dialog/index.d.ts +8 -0
  54. package/dist/cjs/components/move-overwrite-confirm-dialog/index.d.ts.map +1 -0
  55. package/dist/cjs/components/move-overwrite-confirm-dialog/index.js +34 -0
  56. package/dist/cjs/components/resizer/index.d.ts.map +1 -1
  57. package/dist/cjs/components/resizer/index.js +10 -5
  58. package/dist/cjs/components/selection/index.d.ts +1 -1
  59. package/dist/cjs/components/selection/index.d.ts.map +1 -1
  60. package/dist/cjs/components/selection/index.js +4 -2
  61. package/dist/cjs/components/selection/types.d.ts +8 -0
  62. package/dist/cjs/components/selection/types.d.ts.map +1 -1
  63. package/dist/cjs/components/sheet-search/index.d.ts.map +1 -1
  64. package/dist/cjs/components/sheet-search/index.js +6 -2
  65. package/dist/cjs/config.d.ts +6 -0
  66. package/dist/cjs/config.d.ts.map +1 -1
  67. package/dist/cjs/config.js +7 -1
  68. package/dist/cjs/hooks/use-cell-renderer.d.ts +7 -1
  69. package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -1
  70. package/dist/cjs/hooks/use-cell-renderer.js +8 -3
  71. package/dist/cjs/hooks/use-context-setter.d.ts.map +1 -1
  72. package/dist/cjs/hooks/use-context-setter.js +5 -1
  73. package/dist/cjs/hooks/use-copy-paste-cut.d.ts +5 -0
  74. package/dist/cjs/hooks/use-copy-paste-cut.d.ts.map +1 -1
  75. package/dist/cjs/hooks/use-copy-paste-cut.js +25 -3
  76. package/dist/cjs/hooks/use-editor-change.d.ts +4 -1
  77. package/dist/cjs/hooks/use-editor-change.d.ts.map +1 -1
  78. package/dist/cjs/hooks/use-editor-change.js +4 -3
  79. package/dist/cjs/hooks/use-editor-submit.d.ts +8 -1
  80. package/dist/cjs/hooks/use-editor-submit.d.ts.map +1 -1
  81. package/dist/cjs/hooks/use-editor-submit.js +9 -1
  82. package/dist/cjs/hooks/use-header-actions.d.ts.map +1 -1
  83. package/dist/cjs/hooks/use-header-actions.js +17 -10
  84. package/dist/cjs/hooks/use-move-columns-rows.d.ts.map +1 -1
  85. package/dist/cjs/hooks/use-move-columns-rows.js +27 -15
  86. package/dist/cjs/hooks/use-selection-move.d.ts.map +1 -1
  87. package/dist/cjs/hooks/use-selection-move.js +14 -6
  88. package/dist/cjs/hooks/use-selection-renderer.d.ts +9 -1
  89. package/dist/cjs/hooks/use-selection-renderer.d.ts.map +1 -1
  90. package/dist/cjs/hooks/use-selection-renderer.js +26 -2
  91. package/dist/cjs/hooks/use-selection-resize.d.ts.map +1 -1
  92. package/dist/cjs/hooks/use-selection-resize.js +13 -6
  93. package/dist/cjs/hooks/use-selection.d.ts +13 -5
  94. package/dist/cjs/hooks/use-selection.d.ts.map +1 -1
  95. package/dist/cjs/hooks/use-selection.js +107 -31
  96. package/dist/cjs/hooks/use-table-resizer.d.ts.map +1 -1
  97. package/dist/cjs/hooks/use-table-resizer.js +16 -8
  98. package/dist/cjs/hooks/use-touch.d.ts.map +1 -1
  99. package/dist/cjs/hooks/use-touch.js +16 -8
  100. package/dist/cjs/index.d.ts +7 -0
  101. package/dist/cjs/index.d.ts.map +1 -1
  102. package/dist/cjs/index.js +7 -0
  103. package/dist/cjs/release-date.js +1 -1
  104. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  105. package/dist/esm/api/insert-options.d.ts +67 -0
  106. package/dist/esm/api/insert-options.d.ts.map +1 -0
  107. package/dist/esm/api/insert-options.js +91 -0
  108. package/dist/esm/api/move-overwrite.d.ts +14 -0
  109. package/dist/esm/api/move-overwrite.d.ts.map +1 -0
  110. package/dist/esm/api/move-overwrite.js +25 -0
  111. package/dist/esm/api/multi-selection.d.ts +59 -0
  112. package/dist/esm/api/multi-selection.d.ts.map +1 -0
  113. package/dist/esm/api/multi-selection.js +92 -0
  114. package/dist/esm/atoms/index.d.ts +3 -0
  115. package/dist/esm/atoms/index.d.ts.map +1 -1
  116. package/dist/esm/atoms/index.js +3 -0
  117. package/dist/esm/atoms/insert-cells-dialog.atom.d.ts +36 -0
  118. package/dist/esm/atoms/insert-cells-dialog.atom.d.ts.map +1 -0
  119. package/dist/esm/atoms/insert-cells-dialog.atom.js +25 -0
  120. package/dist/esm/atoms/insert-options.atom.d.ts +21 -0
  121. package/dist/esm/atoms/insert-options.atom.d.ts.map +1 -0
  122. package/dist/esm/atoms/insert-options.atom.js +5 -0
  123. package/dist/esm/atoms/move-overwrite-confirm.atom.d.ts +24 -0
  124. package/dist/esm/atoms/move-overwrite-confirm.atom.d.ts.map +1 -0
  125. package/dist/esm/atoms/move-overwrite-confirm.atom.js +29 -0
  126. package/dist/esm/atoms/sheet-context.atom.d.ts +2 -0
  127. package/dist/esm/atoms/sheet-context.atom.d.ts.map +1 -1
  128. package/dist/esm/atoms/sheet-context.atom.js +10 -0
  129. package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
  130. package/dist/esm/components/canvas-grid/index.js +250 -24
  131. package/dist/esm/components/canvas-grid/typings.d.ts +47 -5
  132. package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
  133. package/dist/esm/components/cell-editor/formula-result-preview.d.ts +4 -1
  134. package/dist/esm/components/cell-editor/formula-result-preview.d.ts.map +1 -1
  135. package/dist/esm/components/cell-editor/formula-result-preview.js +3 -3
  136. package/dist/esm/components/cell-editor/index.d.ts +7 -1
  137. package/dist/esm/components/cell-editor/index.d.ts.map +1 -1
  138. package/dist/esm/components/cell-editor/index.js +3 -3
  139. package/dist/esm/components/cell-input/cell-input.d.ts +13 -0
  140. package/dist/esm/components/cell-input/cell-input.d.ts.map +1 -1
  141. package/dist/esm/components/cell-input/cell-input.js +10 -5
  142. package/dist/esm/components/cell-input/formula-bar-cell-input.d.ts.map +1 -1
  143. package/dist/esm/components/cell-input/formula-bar-cell-input.js +3 -1
  144. package/dist/esm/components/context-menu/index.d.ts +16 -1
  145. package/dist/esm/components/context-menu/index.d.ts.map +1 -1
  146. package/dist/esm/components/context-menu/index.js +193 -16
  147. package/dist/esm/components/embeds/embed-draggable.d.ts.map +1 -1
  148. package/dist/esm/components/embeds/embed-draggable.js +3 -2
  149. package/dist/esm/components/floating-cell-editor/index.d.ts.map +1 -1
  150. package/dist/esm/components/floating-cell-editor/index.js +12 -6
  151. package/dist/esm/components/insert-cells-dialog/index.d.ts +35 -0
  152. package/dist/esm/components/insert-cells-dialog/index.d.ts.map +1 -0
  153. package/dist/esm/components/insert-cells-dialog/index.js +79 -0
  154. package/dist/esm/components/insert-options-smart-tag/index.d.ts +25 -0
  155. package/dist/esm/components/insert-options-smart-tag/index.d.ts.map +1 -0
  156. package/dist/esm/components/insert-options-smart-tag/index.js +35 -0
  157. package/dist/esm/components/move-overwrite-confirm-dialog/index.d.ts +8 -0
  158. package/dist/esm/components/move-overwrite-confirm-dialog/index.d.ts.map +1 -0
  159. package/dist/esm/components/move-overwrite-confirm-dialog/index.js +30 -0
  160. package/dist/esm/components/resizer/index.d.ts.map +1 -1
  161. package/dist/esm/components/resizer/index.js +8 -4
  162. package/dist/esm/components/selection/index.d.ts +1 -1
  163. package/dist/esm/components/selection/index.d.ts.map +1 -1
  164. package/dist/esm/components/selection/index.js +4 -2
  165. package/dist/esm/components/selection/types.d.ts +8 -0
  166. package/dist/esm/components/selection/types.d.ts.map +1 -1
  167. package/dist/esm/components/sheet-search/index.d.ts.map +1 -1
  168. package/dist/esm/components/sheet-search/index.js +5 -2
  169. package/dist/esm/config.d.ts +6 -0
  170. package/dist/esm/config.d.ts.map +1 -1
  171. package/dist/esm/config.js +6 -0
  172. package/dist/esm/hooks/use-cell-renderer.d.ts +7 -1
  173. package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -1
  174. package/dist/esm/hooks/use-cell-renderer.js +9 -4
  175. package/dist/esm/hooks/use-context-setter.d.ts.map +1 -1
  176. package/dist/esm/hooks/use-context-setter.js +5 -1
  177. package/dist/esm/hooks/use-copy-paste-cut.d.ts +5 -0
  178. package/dist/esm/hooks/use-copy-paste-cut.d.ts.map +1 -1
  179. package/dist/esm/hooks/use-copy-paste-cut.js +25 -4
  180. package/dist/esm/hooks/use-editor-change.d.ts +4 -1
  181. package/dist/esm/hooks/use-editor-change.d.ts.map +1 -1
  182. package/dist/esm/hooks/use-editor-change.js +5 -4
  183. package/dist/esm/hooks/use-editor-submit.d.ts +8 -1
  184. package/dist/esm/hooks/use-editor-submit.d.ts.map +1 -1
  185. package/dist/esm/hooks/use-editor-submit.js +10 -2
  186. package/dist/esm/hooks/use-header-actions.d.ts.map +1 -1
  187. package/dist/esm/hooks/use-header-actions.js +11 -4
  188. package/dist/esm/hooks/use-move-columns-rows.d.ts.map +1 -1
  189. package/dist/esm/hooks/use-move-columns-rows.js +18 -6
  190. package/dist/esm/hooks/use-selection-move.d.ts.map +1 -1
  191. package/dist/esm/hooks/use-selection-move.js +11 -4
  192. package/dist/esm/hooks/use-selection-renderer.d.ts +9 -1
  193. package/dist/esm/hooks/use-selection-renderer.d.ts.map +1 -1
  194. package/dist/esm/hooks/use-selection-renderer.js +26 -2
  195. package/dist/esm/hooks/use-selection-resize.d.ts.map +1 -1
  196. package/dist/esm/hooks/use-selection-resize.js +11 -5
  197. package/dist/esm/hooks/use-selection.d.ts +13 -5
  198. package/dist/esm/hooks/use-selection.d.ts.map +1 -1
  199. package/dist/esm/hooks/use-selection.js +89 -27
  200. package/dist/esm/hooks/use-table-resizer.d.ts.map +1 -1
  201. package/dist/esm/hooks/use-table-resizer.js +15 -9
  202. package/dist/esm/hooks/use-touch.d.ts.map +1 -1
  203. package/dist/esm/hooks/use-touch.js +15 -7
  204. package/dist/esm/index.d.ts +7 -0
  205. package/dist/esm/index.d.ts.map +1 -1
  206. package/dist/esm/index.js +7 -0
  207. package/dist/esm/release-date.js +1 -1
  208. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  209. package/dist/spreadsheet.min.css +1 -1
  210. package/package.json +6 -6
@@ -1,17 +1,18 @@
1
1
  import { tokenize as defaultFormulaTokenizer } from "@rowsncolumns/calculator";
2
2
  import { cellToArea, Direction, isAreasEqual } from "@rowsncolumns/grid";
3
- import { canUseDOM } from "@rowsncolumns/grid";
3
+ import { canUseDOM, getOwnerDocument } from "@rowsncolumns/grid";
4
4
  import { getBoundedCells, MouseButtonCodes } from "@rowsncolumns/grid";
5
5
  import { isCellWithinBounds } from "@rowsncolumns/grid";
6
6
  import { cellIdentifier, Grid as BaseGrid, isEqualCells, } from "@rowsncolumns/grid";
7
7
  import { defaultCellCoords } from "@rowsncolumns/spreadsheet-state";
8
8
  import { cn, Skeleton, tryParseRichText } from "@rowsncolumns/ui";
9
- import { cellToAddress, getCellEffectiveFormat, getContrastColor, isConditionalFormatFormulaRule, isDataValidationFormulaRule, isNil, isNilOrBlank, iterateCellsInRange, log, resolveDefaultHorizontalAlignment, ssfFormatColor, uuid, } from "@rowsncolumns/utils";
9
+ import { cellToAddress, getCellEffectiveFormat, getContrastColor, getFormulaLocale, isConditionalFormatFormulaRule, isDataValidationFormulaRule, isNil, isNilOrBlank, iterateCellsInRange, localizeCellInput, localizeFormula, localizeFunctionDescriptions, log, resolveDefaultHorizontalAlignment, ssfFormatColor, uuid, } from "@rowsncolumns/utils";
10
10
  import { useStore } from "jotai";
11
11
  import merge from "lodash/merge";
12
12
  import throttle from "lodash/throttle";
13
13
  import React, { forwardRef, memo, startTransition, useCallback, useEffect, useMemo, useRef, useState, } from "react";
14
14
  import { getBandedCells } from "../../api/banded-ranges";
15
+ import { clearRangeForInsertedBand, formatsForInsertOption, insertedBandHasValues, } from "../../api/insert-options";
15
16
  import { CF_INITIAL_WINDOW, cfWindowForViewport, isSameCfWindow, } from "../../api/cf-window";
16
17
  import { generateSelectionsFromFormula } from "../../api/selections";
17
18
  import { SpreadsheetApi } from "../../api/spreadsheet-api";
@@ -20,7 +21,7 @@ import { getDataValidationTooltipContent } from "../../api/validation-tooltip";
20
21
  import { resolveGoToSpecial } from "../../api/go-to-special";
21
22
  import { checkExcelValidationValue, isFormulaEntry, } from "../../api/excel-validation-kinds";
22
23
  import { checkBooleanRule, decideValidationCommit, isCellLockedUnderProtection, isProtectedCell, isProtectedSheet, showValidationDropdownArrow, } from "../../api/validation";
23
- import { useFormulaModeValue, useIsEvaluateFormulaDialogMounted, useIsGoToDialogMounted, useIsPasteSpecialDialogMounted, useOpenEvaluateFormulaDialog, useOpenGoToDialog, useOpenPasteSpecialDialog, useSetNoteEditorCell, useSetPinnedTooltip, useFillOptionsState, useOpenFillSeriesDialog, useShowPasteMenu, useShowValidationAlert, } from "../../atoms";
24
+ import { useFormulaModeValue, useIsEvaluateFormulaDialogMounted, useIsGoToDialogMounted, useIsMoveOverwriteConfirmMounted, useIsPasteSpecialDialogMounted, useOpenEvaluateFormulaDialog, useOpenGoToDialog, useOpenMoveOverwriteConfirm, useOpenPasteSpecialDialog, useSetNoteEditorCell, useSetPinnedTooltip, useFillOptionsState, useInsertOptionsState, useOpenFillSeriesDialog, useShowPasteMenu, useShowValidationAlert, } from "../../atoms";
24
25
  import { useActiveEditor } from "../../atoms/active-editor.atom";
25
26
  import { useAddWatch, useIsWatchWindowMounted, useSetWatchWindowContext, } from "../../atoms/watch-window.atom";
26
27
  import { useEditingCell } from "../../atoms/editing-cell.atom";
@@ -105,7 +106,7 @@ import { getNestedPropertyNames } from "./helpers";
105
106
  * @returns
106
107
  */
107
108
  function CanvasGridComponent(props, forwardedRef) {
108
- 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,
109
+ 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, formulaLocale: formulaLocaleProp, 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, onInsertCutCells, 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,
109
110
  // Host-driven filter props. `hostHiddenRowRanges`
110
111
  // supplies compact [start, end] hidden-row tuples; `getFilterValues` supplies a
111
112
  // column's distinct values. Both let a million-row filter render without scanning
@@ -195,12 +196,21 @@ function CanvasGridComponent(props, forwardedRef) {
195
196
  const [showPasteMenu, setShowPasteMenu] = useShowPasteMenu();
196
197
  // Auto Fill Options smart tag / right-drag fill menu + Series dialog
197
198
  const [fillOptions, setFillOptions] = useFillOptionsState();
199
+ const [insertOptions, setInsertOptions] = useInsertOptionsState();
198
200
  const openFillSeriesDialog = useOpenFillSeriesDialog();
199
201
  // Shared state
200
202
  const formulaMode = useFormulaModeValue();
201
203
  const formulaSelections = useFormulaSelections();
202
204
  const [editingCellCoordinate, setEditingCellCoordinate] = useEditingCell();
203
205
  const setFormulabarEditorValue = useSetFormulabarEditorValue();
206
+ /**
207
+ * The formula SYNTAX the editor / formula bar speak (rowsncolumns/spreadsheet#655): Excel follows
208
+ * the user's language, so it defaults to `locale`. Everything that crosses the grid boundary stays
209
+ * canonical — see `formulaLocale` on `CanvasGridProps`.
210
+ */
211
+ const formulaLocale = useMemo(() => getFormulaLocale(formulaLocaleProp ?? locale), [formulaLocaleProp, locale]);
212
+ // Autocomplete + argument hints show the locale's function names and syntax.
213
+ const localizedFunctionDescriptions = useMemo(() => localizeFunctionDescriptions(functionDescriptions ?? undefined, formulaLocale), [functionDescriptions, formulaLocale]);
204
214
  const setFormulaBarTextFormatRuns = useSetFormulaBarTextFormatRuns();
205
215
  const canSelectCells = useFormulaCanSelectCells();
206
216
  const selectionMode = useFormulaSelectionMode();
@@ -650,10 +660,13 @@ function CanvasGridComponent(props, forwardedRef) {
650
660
  // user gesture on the grid focuses the tabIndex=0 container first, so
651
661
  // this only suppresses render-driven refocus; a null container ref
652
662
  // (mid mount/unmount) falls through to the original focus behavior.
653
- const activeElement = canUseDOM ? document.activeElement : null;
663
+ // The grid may render into a popout window: read focus from its own
664
+ // document, never from the bundle's global one.
665
+ const ownerDocument = getOwnerDocument(gridContainerRef.current);
666
+ const activeElement = ownerDocument?.activeElement ?? null;
654
667
  const gridContainer = gridContainerRef.current;
655
668
  if (activeElement &&
656
- activeElement !== document.body &&
669
+ activeElement !== ownerDocument?.body &&
657
670
  gridContainer &&
658
671
  !gridContainer.contains(activeElement)) {
659
672
  return;
@@ -782,7 +795,8 @@ function CanvasGridComponent(props, forwardedRef) {
782
795
  if (showFormulas && !protectFormulas) {
783
796
  const formulaValue = getFormulaValue(sheetId, rowIndex, columnIndex);
784
797
  if (formulaValue) {
785
- return formulaValue;
798
+ // "Show Formulas" paints the formula the way the editor would show it.
799
+ return localizeFormula(formulaValue, formulaLocale);
786
800
  }
787
801
  }
788
802
  const formattedValue = getFormattedValueProp
@@ -803,6 +817,7 @@ function CanvasGridComponent(props, forwardedRef) {
803
817
  isColumnHeader,
804
818
  getRowHeaderText,
805
819
  getColumnHeaderText,
820
+ formulaLocale,
806
821
  ]);
807
822
  /**
808
823
  * Get information about cell grouping
@@ -943,6 +958,15 @@ function CanvasGridComponent(props, forwardedRef) {
943
958
  ]);
944
959
  // Add a stable reference to get userEnteredString value
945
960
  const getUserEnteredStringValueStable = useCallbackRef(getUserEnteredStringValue);
961
+ /**
962
+ * What the cell editor / formula bar open with: the stored (canonical) entry rendered in the
963
+ * grid's formula locale — `=SUM(1.5,A1)` shows as `=СУММ(1,5;A1)` in ru-RU, a stored `#VALUE!`
964
+ * as `#ЗНАЧ!`. `useEditorSubmit` canonicalizes the text again on commit.
965
+ */
966
+ const getEditorDisplayValue = useCallback((sheetId, rowIndex, columnIndex) => {
967
+ const value = getUserEnteredStringValue(sheetId, rowIndex, columnIndex);
968
+ return isNil(value) ? value : localizeCellInput(value, formulaLocale);
969
+ }, [getUserEnteredStringValue, formulaLocale]);
946
970
  /**
947
971
  * Get cell value used for validations
948
972
  */
@@ -1216,6 +1240,20 @@ function CanvasGridComponent(props, forwardedRef) {
1216
1240
  activeCell,
1217
1241
  tokenizer: defaultTokenizer,
1218
1242
  });
1243
+ /**
1244
+ * The editor's text is in the formula locale's syntax; this tokenizer reads it as such (token
1245
+ * TYPES stay canonical, positions and images are the localized text's). The canonical
1246
+ * `tokenizer` above is what the state hooks and the public context keep using for stored formulas.
1247
+ */
1248
+ const localeTokenizerBase = useCallback((value, sheetName) => defaultTokenizer(value, sheetName, formulaLocale), [defaultTokenizer, formulaLocale]);
1249
+ const localeTokenizer = useCreateFormulaTokenizer({
1250
+ getSelectionFromNamedRange,
1251
+ getSelectionFromTable,
1252
+ editingCellCoordinate,
1253
+ sheetId,
1254
+ activeCell,
1255
+ tokenizer: formulaLocale.isCanonical ? defaultTokenizer : localeTokenizerBase,
1256
+ });
1219
1257
  // Helper function to convert a selection to readable selection address
1220
1258
  const [getAddressFromSelection, getR1C1AddressFromSelection] = useCreateAddressFromSelection({
1221
1259
  sheetId,
@@ -1254,12 +1292,12 @@ function CanvasGridComponent(props, forwardedRef) {
1254
1292
  const getSelectionsFromFormula = useCallbackRef(useCallback((value, cell) => {
1255
1293
  const editingSheetName = getSheetName?.(editingCellCoordinate?.sheetId ?? sheetId);
1256
1294
  const editingSheetId = editingCellCoordinate?.sheetId ?? sheetId;
1257
- return generateSelectionsFromFormula(value, editingSheetId, editingSheetName, cell, rowCount, columnCount, tokenizer, getSelectionFromTable, getSelectionFromNamedRange);
1295
+ return generateSelectionsFromFormula(value, editingSheetId, editingSheetName, cell, rowCount, columnCount, localeTokenizer, getSelectionFromTable, getSelectionFromNamedRange);
1258
1296
  }, [
1259
1297
  rowCount,
1260
1298
  columnCount,
1261
1299
  editingCellCoordinate,
1262
- tokenizer,
1300
+ localeTokenizer,
1263
1301
  getSelectionFromTable,
1264
1302
  getSheetName,
1265
1303
  getSelectionFromNamedRange,
@@ -1799,7 +1837,13 @@ function CanvasGridComponent(props, forwardedRef) {
1799
1837
  sheetId,
1800
1838
  ]);
1801
1839
  /* Check if sheet is focused */
1802
- const isSheetFocused = useCallback(() => canUseDOM ? document.activeElement === cellEditorInstance?.el() : false, [cellEditorInstance]);
1840
+ const isSheetFocused = useCallback(() => {
1841
+ const editorElement = cellEditorInstance?.el();
1842
+ if (!editorElement) {
1843
+ return false;
1844
+ }
1845
+ return getOwnerDocument(editorElement)?.activeElement === editorElement;
1846
+ }, [cellEditorInstance]);
1803
1847
  /**
1804
1848
  * Get Cell Editor
1805
1849
  */
@@ -1815,7 +1859,7 @@ function CanvasGridComponent(props, forwardedRef) {
1815
1859
  const editingSheetName = getSheetName?.(editingSheetId);
1816
1860
  const effectiveValue = getEffectiveValue(editingSheetId, rowIndex, columnIndex);
1817
1861
  const horizontalAlignment = getEditorHorizontalAlignment(editingSheetId, rowIndex, columnIndex);
1818
- return (React.createElement(CellEditor, { ...props, locale: locale, effectiveValue: effectiveValue, format: cellFormat, dataValidation: dataValidation, getRangeValues: getFormattedValuesFromAddress, getRangeValuesAsync: getFormattedValuesFromAddressAsync, scale: scale, sheetName: sheetName, editingSheetId: editingSheetId, sheetId: sheetId, editingSheetName: editingSheetName, address: address, theme: theme, tokenizer: tokenizer, horizontalAlignment: horizontalAlignment, defaultBackgroundColor: cellBackgroundColor, defaultTextColor: getStringifiedColor(cellColor, theme), functionDescriptions: functionDescriptions ?? undefined, getNamedRanges: getNamedRanges, getTableNames: getTableNames, getStructuredProperties: getStructuredProperties, getTableColumnNames: getTableColumnNames, showFormulaHelp: showFormulaHelp, onHideFormulaHelp: onHideFormulaHelp, onShowFormulaHelp: onShowFormulaHelp, onRequestCalculate: onRequestCalculate, SuggestionsDropdown: SuggestionsDropdown, stickyEditor: stickyEditor, defaultFontSizePoint: defaultFontSizePoint, getMentions: getMentions, getFunctionParameterSuggestions: getFunctionParameterSuggestions, shouldFetchFunctionParameters: shouldFetchFunctionParameters, MentionTagComponent: MentionTagComponent, MentionDropdownItemComponent: MentionDropdownItemComponent }));
1862
+ return (React.createElement(CellEditor, { ...props, locale: locale, effectiveValue: effectiveValue, format: cellFormat, dataValidation: dataValidation, getRangeValues: getFormattedValuesFromAddress, getRangeValuesAsync: getFormattedValuesFromAddressAsync, scale: scale, sheetName: sheetName, editingSheetId: editingSheetId, sheetId: sheetId, editingSheetName: editingSheetName, address: address, theme: theme, tokenizer: localeTokenizer, formulaLocale: formulaLocale, horizontalAlignment: horizontalAlignment, defaultBackgroundColor: cellBackgroundColor, defaultTextColor: getStringifiedColor(cellColor, theme), functionDescriptions: localizedFunctionDescriptions, getNamedRanges: getNamedRanges, getTableNames: getTableNames, getStructuredProperties: getStructuredProperties, getTableColumnNames: getTableColumnNames, showFormulaHelp: showFormulaHelp, onHideFormulaHelp: onHideFormulaHelp, onShowFormulaHelp: onShowFormulaHelp, onRequestCalculate: onRequestCalculate, SuggestionsDropdown: SuggestionsDropdown, stickyEditor: stickyEditor, defaultFontSizePoint: defaultFontSizePoint, getMentions: getMentions, getFunctionParameterSuggestions: getFunctionParameterSuggestions, shouldFetchFunctionParameters: shouldFetchFunctionParameters, MentionTagComponent: MentionTagComponent, MentionDropdownItemComponent: MentionDropdownItemComponent }));
1819
1863
  }, [
1820
1864
  scale,
1821
1865
  getEffectiveCellFormat,
@@ -1826,10 +1870,11 @@ function CanvasGridComponent(props, forwardedRef) {
1826
1870
  showFormulaHelp,
1827
1871
  onHideFormulaHelp,
1828
1872
  onShowFormulaHelp,
1829
- tokenizer,
1873
+ localeTokenizer,
1874
+ formulaLocale,
1830
1875
  cellBackgroundColor,
1831
1876
  cellColor,
1832
- functionDescriptions,
1877
+ localizedFunctionDescriptions,
1833
1878
  getNamedRanges,
1834
1879
  getTableNames,
1835
1880
  getStructuredProperties,
@@ -1963,6 +2008,119 @@ function CanvasGridComponent(props, forwardedRef) {
1963
2008
  if (fillOptions?.mode === "menu")
1964
2009
  setFillOptions(null);
1965
2010
  }, [fillOptions, setFillOptions]);
2011
+ /**
2012
+ * Row / column inserts driven from this grid (context menu, Insert dialog,
2013
+ * Ctrl+Shift+=) also arm Excel's Insert Options smart tag on the new band.
2014
+ * The engine already applied "Format Same As Above / Left" (#647 FMT-01/02);
2015
+ * the tag lets the user switch to the other neighbour or clear.
2016
+ */
2017
+ const insertRowWithOptions = useCallback((targetSheetId, rowIndex, numRows) => {
2018
+ if (!onInsertRow)
2019
+ return;
2020
+ onInsertRow(targetSheetId, rowIndex, numRows);
2021
+ if (numRows > 0) {
2022
+ setInsertOptions({
2023
+ sheetId: targetSheetId,
2024
+ axis: "row",
2025
+ start: rowIndex,
2026
+ count: numRows,
2027
+ option: "before",
2028
+ });
2029
+ }
2030
+ }, [onInsertRow, setInsertOptions]);
2031
+ const insertColumnWithOptions = useCallback((targetSheetId, columnIndex, numColumns) => {
2032
+ if (!onInsertColumn)
2033
+ return;
2034
+ onInsertColumn(targetSheetId, columnIndex, numColumns);
2035
+ if (numColumns > 0) {
2036
+ setInsertOptions({
2037
+ sheetId: targetSheetId,
2038
+ axis: "column",
2039
+ start: columnIndex,
2040
+ count: numColumns,
2041
+ option: "before",
2042
+ });
2043
+ }
2044
+ }, [onInsertColumn, setInsertOptions]);
2045
+ /**
2046
+ * User-entered format of a cell for the Insert Options re-format. A legacy
2047
+ * `StyleReference` (xlsx-imported style id) cannot be copied verbatim, so
2048
+ * it resolves through `getEffectiveFormat` instead.
2049
+ */
2050
+ const readInsertFormat = useCallback((rowIndex, columnIndex) => {
2051
+ const uf = getCellData?.(sheetId, rowIndex, columnIndex)?.uf;
2052
+ if (!uf)
2053
+ return undefined;
2054
+ const isStyleReference = "sid" in uf || "styleId" in uf;
2055
+ return isStyleReference
2056
+ ? getEffectiveFormat?.(sheetId, rowIndex, columnIndex)
2057
+ : uf;
2058
+ }, [getCellData, getEffectiveFormat, sheetId]);
2059
+ /**
2060
+ * Insert Options smart tag choice. "Same As Above / Below" (Left / Right)
2061
+ * re-paints the band with the neighbour's per-cell formats through the same
2062
+ * paint-format path both engines share (`onChangeFormatting` with a format
2063
+ * grid + `replace`), so the earlier choice does not linger; "Clear
2064
+ * Formatting" wipes the band. A band that already holds values was not
2065
+ * (or is no longer) a fresh insert — the refused-insert case — so the tag
2066
+ * just goes away instead of re-formatting live data.
2067
+ */
2068
+ const handleChooseInsertOption = useCallback((option) => {
2069
+ if (!insertOptions || insertOptions.sheetId !== sheetId)
2070
+ return;
2071
+ const band = {
2072
+ axis: insertOptions.axis,
2073
+ start: insertOptions.start,
2074
+ count: insertOptions.count,
2075
+ };
2076
+ const limit = band.axis === "row" ? columnCount : rowCount;
2077
+ const hasValue = (rowIndex, columnIndex) => {
2078
+ const cell = getCellData?.(sheetId, rowIndex, columnIndex);
2079
+ return !isNil(cell?.ue ?? cell?.userEnteredValue);
2080
+ };
2081
+ if (insertedBandHasValues(band, hasValue, limit)) {
2082
+ setInsertOptions(null);
2083
+ return;
2084
+ }
2085
+ const clearBand = () => {
2086
+ const range = clearRangeForInsertedBand(band, readInsertFormat, limit);
2087
+ if (range)
2088
+ onClearFormatting?.(sheetId, activeCell, [{ range }]);
2089
+ };
2090
+ if (option === "clear") {
2091
+ clearBand();
2092
+ }
2093
+ else {
2094
+ const plan = formatsForInsertOption(band, option, readInsertFormat, limit);
2095
+ if (plan) {
2096
+ // Both engines accept the paint-format shape (format grid + replace);
2097
+ // the grid prop type only names the key/value overload.
2098
+ onChangeFormatting?.(sheetId, activeCell, plan.selections, plan.formats, { replace: true });
2099
+ }
2100
+ else {
2101
+ clearBand();
2102
+ }
2103
+ }
2104
+ setInsertOptions({ ...insertOptions, option });
2105
+ focusSheet();
2106
+ }, [
2107
+ insertOptions,
2108
+ sheetId,
2109
+ columnCount,
2110
+ rowCount,
2111
+ getCellData,
2112
+ readInsertFormat,
2113
+ onClearFormatting,
2114
+ onChangeFormatting,
2115
+ activeCell,
2116
+ setInsertOptions,
2117
+ focusSheet,
2118
+ ]);
2119
+ // The smart tag belongs to one insert; moving on (a new active cell or
2120
+ // sheet) drops it. Keyed on coordinates like the fill-options tag.
2121
+ useEffect(() => {
2122
+ setInsertOptions(null);
2123
+ }, [activeCell.rowIndex, activeCell.columnIndex, sheetId, setInsertOptions]);
1966
2124
  /**
1967
2125
  * Run Excel's Series dialog result: the target range's first row (Series
1968
2126
  * in Columns) / first column (Rows) is the seed line; `stop` may shrink or
@@ -2034,6 +2192,14 @@ function CanvasGridComponent(props, forwardedRef) {
2034
2192
  useEffect(() => {
2035
2193
  setFillOptions(null);
2036
2194
  }, [activeCell.rowIndex, activeCell.columnIndex, sheetId, setFillOptions]);
2195
+ /**
2196
+ * Drag-move overwrite prompt ("There's already data here. Do you want to replace it?").
2197
+ * Routed to the host-mounted `MoveOverwriteConfirmDialogHost` when there is one; the
2198
+ * selection hook falls back to `window.confirm` otherwise.
2199
+ */
2200
+ const openMoveOverwriteConfirm = useOpenMoveOverwriteConfirm();
2201
+ const isMoveOverwriteConfirmMounted = useIsMoveOverwriteConfirmMounted();
2202
+ const confirmMoveOverwrite = useMemo(() => (isMoveOverwriteConfirmMounted ? openMoveOverwriteConfirm : undefined), [isMoveOverwriteConfirmMounted, openMoveOverwriteConfirm]);
2037
2203
  /**
2038
2204
  * Fill handle dragged BACK inside the selection (Excel): the dragged-over cells lose their
2039
2205
  * contents — formats stay unless Ctrl/Cmd was held — through the same `onDelete` path as the
@@ -2076,6 +2242,8 @@ function CanvasGridComponent(props, forwardedRef) {
2076
2242
  onFillHandleRelease: handleFillHandleRelease,
2077
2243
  onFillShrink: handleFillShrink,
2078
2244
  onMoveSelection,
2245
+ onInsertCutCells,
2246
+ confirmMoveOverwrite,
2079
2247
  isHiddenColumn,
2080
2248
  isHiddenRow,
2081
2249
  isRowHeader,
@@ -2086,7 +2254,7 @@ function CanvasGridComponent(props, forwardedRef) {
2086
2254
  /**
2087
2255
  * Copy, Paste and Cut hook
2088
2256
  */
2089
- const { copiedSelections, clearCopiedSelections, copy, cut, paste, onInternalCopy, onInternalCut, onInternalPaste, } = useCopyPasteCut({
2257
+ const { copiedSelections, isCutPending, copiedSheetId, cancelCut, clearCopiedSelections, copy, cut, paste, onInternalCopy, onInternalCut, onInternalPaste, } = useCopyPasteCut({
2090
2258
  activeCell,
2091
2259
  selections,
2092
2260
  sheetId,
@@ -2095,6 +2263,54 @@ function CanvasGridComponent(props, forwardedRef) {
2095
2263
  onCopy,
2096
2264
  onCut,
2097
2265
  });
2266
+ /**
2267
+ * Context menu "Insert Cut Cells" (Excel: Ctrl+X, right-click the destination). A cut of
2268
+ * whole rows / columns dropped on a row / column header inserts them BEFORE the clicked
2269
+ * header in pre-removal numbering (`insertBefore`); anything else inserts the cut block at
2270
+ * the active cell, displacing the cells there (`onInsertCutCells`). Consumes the cut.
2271
+ */
2272
+ const insertCutCellsFromMenu = useCallback((target) => {
2273
+ const from = copiedSelections[0];
2274
+ if (!from || !isCutPending)
2275
+ return;
2276
+ const { range } = from;
2277
+ const wholeRows = range.startColumnIndex <= 1 && range.endColumnIndex >= columnCount;
2278
+ const wholeColumns = range.startRowIndex <= 1 && range.endRowIndex >= rowCount;
2279
+ const span = (start, end) => Array.from({ length: end - start + 1 }, (_, i) => start + i);
2280
+ if (target === "rows" && wholeRows) {
2281
+ onMoveRows?.(sheetId, span(range.startRowIndex, range.endRowIndex), activeCell.rowIndex, {
2282
+ insertBefore: true,
2283
+ });
2284
+ }
2285
+ else if (target === "columns" && wholeColumns) {
2286
+ onMoveColumns?.(sheetId, span(range.startColumnIndex, range.endColumnIndex), activeCell.columnIndex, { insertBefore: true });
2287
+ }
2288
+ else {
2289
+ const to = {
2290
+ range: {
2291
+ startRowIndex: activeCell.rowIndex,
2292
+ startColumnIndex: activeCell.columnIndex,
2293
+ endRowIndex: activeCell.rowIndex + (range.endRowIndex - range.startRowIndex),
2294
+ endColumnIndex: activeCell.columnIndex + (range.endColumnIndex - range.startColumnIndex),
2295
+ },
2296
+ };
2297
+ onInsertCutCells?.(sheetId, from, to);
2298
+ }
2299
+ cancelCut();
2300
+ focusSheet();
2301
+ }, [
2302
+ copiedSelections,
2303
+ isCutPending,
2304
+ columnCount,
2305
+ rowCount,
2306
+ sheetId,
2307
+ activeCell,
2308
+ onMoveRows,
2309
+ onMoveColumns,
2310
+ onInsertCutCells,
2311
+ cancelCut,
2312
+ focusSheet,
2313
+ ]);
2098
2314
  /**
2099
2315
  * Paste Special dialog (context menu → Paste special…, Ctrl+Alt+V). The
2100
2316
  * dialog is host-mounted (`PasteSpecialDialogHost`); its request routes
@@ -2205,6 +2421,7 @@ function CanvasGridComponent(props, forwardedRef) {
2205
2421
  onChangeSelections,
2206
2422
  getSelectionsFromFormula,
2207
2423
  onChangeEditorValue,
2424
+ formulaLocale,
2208
2425
  });
2209
2426
  // Get final row height to expand to based on value of a cell
2210
2427
  const getFinalRowHeight = useCallbackRef(useCallback((sheetId, rowIndex, columnIndex, options) => {
@@ -2249,6 +2466,7 @@ function CanvasGridComponent(props, forwardedRef) {
2249
2466
  showValidationAlert,
2250
2467
  selections,
2251
2468
  onChangeBatch,
2469
+ formulaLocale,
2252
2470
  });
2253
2471
  /**
2254
2472
  * User cancels editing the cell
@@ -2337,7 +2555,7 @@ function CanvasGridComponent(props, forwardedRef) {
2337
2555
  * Get context Menu component
2338
2556
  */
2339
2557
  const getContextMenu = useCallback((cell) => {
2340
- 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 }));
2558
+ 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: insertRowWithOptions, onInsertColumn: insertColumnWithOptions, rowCount: rowCount, columnCount: columnCount, 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, hasCutSelection: isCutPending && copiedSheetId === sheetId, onInsertCutCells: insertCutCellsFromMenu, 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 }));
2341
2559
  }, [
2342
2560
  isRestricted,
2343
2561
  activeCell,
@@ -2350,8 +2568,10 @@ function CanvasGridComponent(props, forwardedRef) {
2350
2568
  onHideRow,
2351
2569
  onDeleteColumn,
2352
2570
  onDeleteRow,
2353
- onInsertColumn,
2354
- onInsertRow,
2571
+ insertColumnWithOptions,
2572
+ insertRowWithOptions,
2573
+ rowCount,
2574
+ columnCount,
2355
2575
  onInsertCellsShiftDown,
2356
2576
  onInsertCellsShiftRight,
2357
2577
  onDeleteCellsShiftLeft,
@@ -2489,7 +2709,7 @@ function CanvasGridComponent(props, forwardedRef) {
2489
2709
  onGroupColumns,
2490
2710
  onUngroupColumns,
2491
2711
  onDeleteRow,
2492
- onInsertRow,
2712
+ onInsertRow: insertRowWithOptions,
2493
2713
  onInsertAutoSum,
2494
2714
  onShowColumn,
2495
2715
  onShowRow,
@@ -2531,7 +2751,7 @@ function CanvasGridComponent(props, forwardedRef) {
2531
2751
  selections,
2532
2752
  getSheetColumnCount,
2533
2753
  getSheetRowCount,
2534
- getValue: getUserEnteredStringValue,
2754
+ getValue: getEditorDisplayValue,
2535
2755
  getTextFormatRuns,
2536
2756
  getBooleanValue,
2537
2757
  getDataValidation: getDataValidationRule,
@@ -3004,6 +3224,7 @@ function CanvasGridComponent(props, forwardedRef) {
3004
3224
  */
3005
3225
  const [cellBackgroundRenderer, cellRenderer, cellOverlayRenderer, headerCellRenderer,] = useCellRenderer({
3006
3226
  sheetId,
3227
+ formulaLocale,
3007
3228
  showGridLines,
3008
3229
  scale,
3009
3230
  enableTextOverflow,
@@ -3104,13 +3325,13 @@ function CanvasGridComponent(props, forwardedRef) {
3104
3325
  getCellBounds,
3105
3326
  getCellCoordsFromOffset,
3106
3327
  scrollToCell,
3107
- tokenizer,
3328
+ tokenizer: localeTokenizer,
3108
3329
  });
3109
3330
  // Selection move: drag a formula reference via its border covers
3110
3331
  const { onMouseDownMoveSelection, isDragging: isDraggingMoveSelection } = useSelectionMove({
3111
3332
  getCellCoordsFromOffset,
3112
3333
  scrollToCell,
3113
- tokenizer,
3334
+ tokenizer: localeTokenizer,
3114
3335
  });
3115
3336
  /**
3116
3337
  * Hide fill handle
@@ -3174,6 +3395,8 @@ function CanvasGridComponent(props, forwardedRef) {
3174
3395
  onChooseFillType: handleChooseFillType,
3175
3396
  onOpenFillSeriesDialog: handleOpenFillSeriesDialog,
3176
3397
  onCloseFillOptions: handleCloseFillOptions,
3398
+ insertOptions,
3399
+ onChooseInsertOption: handleChooseInsertOption,
3177
3400
  hoveredCell: delayedHoveredCell,
3178
3401
  onRemoveQuickEdit,
3179
3402
  onAddQuickEdit,
@@ -3345,6 +3568,8 @@ function CanvasGridComponent(props, forwardedRef) {
3345
3568
  getAddressFromSelection,
3346
3569
  getR1C1AddressFromSelection,
3347
3570
  tokenizer,
3571
+ localeTokenizer,
3572
+ formulaLocale,
3348
3573
  setEditorValue,
3349
3574
  getCellBounds,
3350
3575
  getNamedRanges,
@@ -3476,7 +3701,7 @@ function CanvasGridComponent(props, forwardedRef) {
3476
3701
  // Keep focus back on sheet
3477
3702
  // Check if user is focused on the context menu
3478
3703
  if (canUseDOM &&
3479
- document.activeElement?.getAttribute("role") !== "menu") {
3704
+ getOwnerDocument(gridContainerRef.current)?.activeElement?.getAttribute("role") !== "menu") {
3480
3705
  focusSheet();
3481
3706
  }
3482
3707
  }
@@ -3509,8 +3734,8 @@ function CanvasGridComponent(props, forwardedRef) {
3509
3734
  const { rowIndex, columnIndex } = activeCell;
3510
3735
  const value = getUserEnteredStringValue(sheetId, rowIndex, columnIndex);
3511
3736
  const textFormatRuns = getTextFormatRuns?.(sheetId, rowIndex, columnIndex);
3512
- // Update formula bar input
3513
- setFormulabarEditorValue(value ?? "");
3737
+ // Update formula bar input (in the grid's formula locale, like the cell editor)
3738
+ setFormulabarEditorValue(localizeCellInput(value ?? "", formulaLocale));
3514
3739
  setFormulaBarTextFormatRuns(textFormatRuns);
3515
3740
  }, [
3516
3741
  activeCell,
@@ -3518,6 +3743,7 @@ function CanvasGridComponent(props, forwardedRef) {
3518
3743
  sheetId,
3519
3744
  editingCellCoordinate,
3520
3745
  getUserEnteredStringValue,
3746
+ formulaLocale,
3521
3747
  setFormulabarEditorValue,
3522
3748
  setFormulaBarTextFormatRuns,
3523
3749
  ]);
@@ -1,5 +1,6 @@
1
1
  import type { CalculatorFunction } from "@rowsncolumns/common-types";
2
2
  import type { FormulaResult } from "@rowsncolumns/fast-formula-parser";
3
+ import type { FormulaLocale, FormulaLocaleInput } from "@rowsncolumns/utils";
3
4
  import type { Align, AreaStyle, CellInterface, CellPosition, Direction, GridProps, GridRange, GridRef, OptionalCellInterface, ScrollCoords, SelectionArea, Style, ViewPortProps } from "@rowsncolumns/grid";
4
5
  import type { Mention, MentionTagComponentProps, OptionItem, ProseMirrorEditorProps, TextFormatRun } from "@rowsncolumns/ui";
5
6
  import type { CellDiff } from "@rowsncolumns/version-comparison";
@@ -440,6 +441,20 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
440
441
  * Locale of the spreadsheet
441
442
  */
442
443
  locale?: string;
444
+ /**
445
+ * Formula SYNTAX locale for the cell editor, formula bar, autocomplete, argument hints, syntax
446
+ * highlighting and error display (rowsncolumns/spreadsheet#655) — Excel's behaviour: decimal and
447
+ * argument separators, function names and error values follow the user's language
448
+ * (`=СУММ(1,5;A1)` in ru-RU, `=SUMME(1,5;A1)` in de-DE) while every value that leaves the grid
449
+ * (`onChange`, `onChangeEditorValue`, `onRequestCalculate`, the stored cell) stays canonical
450
+ * (`=SUM(1.5,A1)`), so collaborators in different locales share one document.
451
+ *
452
+ * Accepts a BCP-47 tag, a resolved `FormulaLocale`, or an inline `FormulaLocaleDefinition`
453
+ * (`{ extends: "de", functions: { SUM: "SUMMEX" } }`); applications extend or override the
454
+ * built-in dictionaries globally with `registerFormulaLocale` from `@rowsncolumns/utils`.
455
+ * Defaults to `locale`; pass `"en"` to keep English syntax under a non-English `locale`.
456
+ */
457
+ formulaLocale?: FormulaLocaleInput;
443
458
  /**
444
459
  * Enable row and column resizer to overflow outside the container
445
460
  */
@@ -714,6 +729,16 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
714
729
  * @param to
715
730
  */
716
731
  onMoveSelection?(sheetId: number, from: SelectionArea<SelectionAttributes>, to: SelectionArea<SelectionAttributes>): void;
732
+ /**
733
+ * Excel "Insert Cut Cells" / Shift+drag of a cell range: the destination band
734
+ * opens (down for a vertical move, right for a horizontal one), the block is
735
+ * inserted there and the gap it left closes — nothing is overwritten and no
736
+ * blank is left behind. Plain drags call `onMoveSelection` (overwrite, after
737
+ * the data prompt) instead.
738
+ * @param from
739
+ * @param to
740
+ */
741
+ onInsertCutCells?(sheetId: number, from: SelectionArea<SelectionAttributes>, to: SelectionArea<SelectionAttributes>): void;
717
742
  /**
718
743
  * Callback when active cell changes
719
744
  */
@@ -884,13 +909,19 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
884
909
  * @param dims
885
910
  * @param toColumn
886
911
  */
887
- onMoveColumns?(sheetId: number, dims: number[], toColumn: number): void;
912
+ onMoveColumns?(sheetId: number, dims: number[], toColumn: number, options?: {
913
+ insertBefore?: boolean;
914
+ }): void;
888
915
  /**
889
- * Callback when rows are moved
916
+ * Callback when rows are moved. `toRow` is the block's final index; with
917
+ * `insertBefore` (context-menu "Insert Cut Cells") it is instead the row the
918
+ * block is inserted before in pre-removal numbering, as Excel counts it.
890
919
  * @param dims
891
920
  * @param toRow
892
921
  */
893
- onMoveRows?(sheetId: number, dims: number[], toRow: number): void;
922
+ onMoveRows?(sheetId: number, dims: number[], toRow: number, options?: {
923
+ insertBefore?: boolean;
924
+ }): void;
894
925
  /**
895
926
  * User pressed a key to select previous sheet
896
927
  */
@@ -1429,7 +1460,9 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
1429
1460
  * Parses a text value to return tokens
1430
1461
  * @param value
1431
1462
  */
1432
- tokenizer?(value: string | undefined, sheetName?: string): ParsedToken[];
1463
+ tokenizer?(value: string | undefined, sheetName?: string,
1464
+ /** The formula locale the text is written in; canonical syntax when omitted. */
1465
+ formulaLocale?: FormulaLocaleInput | null): ParsedToken[];
1433
1466
  /**
1434
1467
  * User is requesting to search a sheet
1435
1468
  */
@@ -1893,10 +1926,19 @@ export type CanvasGridMethods = {
1893
1926
  */
1894
1927
  updateSelectionStartEndReference?(cell: CellInterface | undefined, selections?: SelectionArea<SelectionAttributes>[] | undefined): void;
1895
1928
  /**
1896
- * Tokenize string
1929
+ * Tokenize string (canonical formula syntax — what the state hooks and stored cells use)
1897
1930
  * @param str
1898
1931
  */
1899
1932
  tokenizer(str: string): ParsedToken[];
1933
+ /**
1934
+ * Tokenize text written in the grid's formula locale (what the cell editor / formula bar hold).
1935
+ * @param str
1936
+ */
1937
+ localeTokenizer?(str: string): ParsedToken[];
1938
+ /**
1939
+ * The grid's resolved formula locale (see `CanvasGridProps.formulaLocale`).
1940
+ */
1941
+ formulaLocale?: FormulaLocale;
1900
1942
  /**
1901
1943
  * Get dimensions of a cell
1902
1944
  */