@rowsncolumns/spreadsheet 10.2.76 → 10.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) 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 +284 -63
  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/floating-cell-editor/index.d.ts.map +1 -1
  44. package/dist/cjs/components/floating-cell-editor/index.js +13 -5
  45. package/dist/cjs/components/insert-cells-dialog/index.d.ts +35 -0
  46. package/dist/cjs/components/insert-cells-dialog/index.d.ts.map +1 -0
  47. package/dist/cjs/components/insert-cells-dialog/index.js +84 -0
  48. package/dist/cjs/components/insert-options-smart-tag/index.d.ts +25 -0
  49. package/dist/cjs/components/insert-options-smart-tag/index.d.ts.map +1 -0
  50. package/dist/cjs/components/insert-options-smart-tag/index.js +41 -0
  51. package/dist/cjs/components/move-overwrite-confirm-dialog/index.d.ts +8 -0
  52. package/dist/cjs/components/move-overwrite-confirm-dialog/index.d.ts.map +1 -0
  53. package/dist/cjs/components/move-overwrite-confirm-dialog/index.js +34 -0
  54. package/dist/cjs/components/selection/index.d.ts +1 -1
  55. package/dist/cjs/components/selection/index.d.ts.map +1 -1
  56. package/dist/cjs/components/selection/index.js +4 -2
  57. package/dist/cjs/components/selection/types.d.ts +8 -0
  58. package/dist/cjs/components/selection/types.d.ts.map +1 -1
  59. package/dist/cjs/config.d.ts +6 -0
  60. package/dist/cjs/config.d.ts.map +1 -1
  61. package/dist/cjs/config.js +7 -1
  62. package/dist/cjs/hooks/use-cell-renderer.d.ts +7 -1
  63. package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -1
  64. package/dist/cjs/hooks/use-cell-renderer.js +8 -3
  65. package/dist/cjs/hooks/use-context-setter.d.ts.map +1 -1
  66. package/dist/cjs/hooks/use-context-setter.js +5 -1
  67. package/dist/cjs/hooks/use-copy-paste-cut.d.ts +5 -0
  68. package/dist/cjs/hooks/use-copy-paste-cut.d.ts.map +1 -1
  69. package/dist/cjs/hooks/use-copy-paste-cut.js +19 -0
  70. package/dist/cjs/hooks/use-editor-change.d.ts +4 -1
  71. package/dist/cjs/hooks/use-editor-change.d.ts.map +1 -1
  72. package/dist/cjs/hooks/use-editor-change.js +4 -3
  73. package/dist/cjs/hooks/use-editor-submit.d.ts +8 -1
  74. package/dist/cjs/hooks/use-editor-submit.d.ts.map +1 -1
  75. package/dist/cjs/hooks/use-editor-submit.js +9 -1
  76. package/dist/cjs/hooks/use-move-columns-rows.d.ts.map +1 -1
  77. package/dist/cjs/hooks/use-move-columns-rows.js +6 -0
  78. package/dist/cjs/hooks/use-selection-renderer.d.ts +9 -1
  79. package/dist/cjs/hooks/use-selection-renderer.d.ts.map +1 -1
  80. package/dist/cjs/hooks/use-selection-renderer.js +26 -2
  81. package/dist/cjs/hooks/use-selection.d.ts +13 -5
  82. package/dist/cjs/hooks/use-selection.d.ts.map +1 -1
  83. package/dist/cjs/hooks/use-selection.js +48 -6
  84. package/dist/cjs/index.d.ts +7 -0
  85. package/dist/cjs/index.d.ts.map +1 -1
  86. package/dist/cjs/index.js +7 -0
  87. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  88. package/dist/cjs/types.d.ts +8 -0
  89. package/dist/cjs/types.d.ts.map +1 -1
  90. package/dist/esm/api/insert-options.d.ts +67 -0
  91. package/dist/esm/api/insert-options.d.ts.map +1 -0
  92. package/dist/esm/api/insert-options.js +91 -0
  93. package/dist/esm/api/move-overwrite.d.ts +14 -0
  94. package/dist/esm/api/move-overwrite.d.ts.map +1 -0
  95. package/dist/esm/api/move-overwrite.js +25 -0
  96. package/dist/esm/api/multi-selection.d.ts +59 -0
  97. package/dist/esm/api/multi-selection.d.ts.map +1 -0
  98. package/dist/esm/api/multi-selection.js +92 -0
  99. package/dist/esm/atoms/index.d.ts +3 -0
  100. package/dist/esm/atoms/index.d.ts.map +1 -1
  101. package/dist/esm/atoms/index.js +3 -0
  102. package/dist/esm/atoms/insert-cells-dialog.atom.d.ts +36 -0
  103. package/dist/esm/atoms/insert-cells-dialog.atom.d.ts.map +1 -0
  104. package/dist/esm/atoms/insert-cells-dialog.atom.js +25 -0
  105. package/dist/esm/atoms/insert-options.atom.d.ts +21 -0
  106. package/dist/esm/atoms/insert-options.atom.d.ts.map +1 -0
  107. package/dist/esm/atoms/insert-options.atom.js +5 -0
  108. package/dist/esm/atoms/move-overwrite-confirm.atom.d.ts +24 -0
  109. package/dist/esm/atoms/move-overwrite-confirm.atom.d.ts.map +1 -0
  110. package/dist/esm/atoms/move-overwrite-confirm.atom.js +29 -0
  111. package/dist/esm/atoms/sheet-context.atom.d.ts +2 -0
  112. package/dist/esm/atoms/sheet-context.atom.d.ts.map +1 -1
  113. package/dist/esm/atoms/sheet-context.atom.js +10 -0
  114. package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
  115. package/dist/esm/components/canvas-grid/index.js +236 -19
  116. package/dist/esm/components/canvas-grid/typings.d.ts +47 -5
  117. package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
  118. package/dist/esm/components/cell-editor/formula-result-preview.d.ts +4 -1
  119. package/dist/esm/components/cell-editor/formula-result-preview.d.ts.map +1 -1
  120. package/dist/esm/components/cell-editor/formula-result-preview.js +3 -3
  121. package/dist/esm/components/cell-editor/index.d.ts +7 -1
  122. package/dist/esm/components/cell-editor/index.d.ts.map +1 -1
  123. package/dist/esm/components/cell-editor/index.js +3 -3
  124. package/dist/esm/components/cell-input/cell-input.d.ts +13 -0
  125. package/dist/esm/components/cell-input/cell-input.d.ts.map +1 -1
  126. package/dist/esm/components/cell-input/cell-input.js +10 -5
  127. package/dist/esm/components/cell-input/formula-bar-cell-input.d.ts.map +1 -1
  128. package/dist/esm/components/cell-input/formula-bar-cell-input.js +3 -1
  129. package/dist/esm/components/context-menu/index.d.ts +16 -1
  130. package/dist/esm/components/context-menu/index.d.ts.map +1 -1
  131. package/dist/esm/components/context-menu/index.js +193 -16
  132. package/dist/esm/components/floating-cell-editor/index.d.ts.map +1 -1
  133. package/dist/esm/components/floating-cell-editor/index.js +12 -6
  134. package/dist/esm/components/insert-cells-dialog/index.d.ts +35 -0
  135. package/dist/esm/components/insert-cells-dialog/index.d.ts.map +1 -0
  136. package/dist/esm/components/insert-cells-dialog/index.js +79 -0
  137. package/dist/esm/components/insert-options-smart-tag/index.d.ts +25 -0
  138. package/dist/esm/components/insert-options-smart-tag/index.d.ts.map +1 -0
  139. package/dist/esm/components/insert-options-smart-tag/index.js +35 -0
  140. package/dist/esm/components/move-overwrite-confirm-dialog/index.d.ts +8 -0
  141. package/dist/esm/components/move-overwrite-confirm-dialog/index.d.ts.map +1 -0
  142. package/dist/esm/components/move-overwrite-confirm-dialog/index.js +30 -0
  143. package/dist/esm/components/selection/index.d.ts +1 -1
  144. package/dist/esm/components/selection/index.d.ts.map +1 -1
  145. package/dist/esm/components/selection/index.js +4 -2
  146. package/dist/esm/components/selection/types.d.ts +8 -0
  147. package/dist/esm/components/selection/types.d.ts.map +1 -1
  148. package/dist/esm/config.d.ts +6 -0
  149. package/dist/esm/config.d.ts.map +1 -1
  150. package/dist/esm/config.js +6 -0
  151. package/dist/esm/hooks/use-cell-renderer.d.ts +7 -1
  152. package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -1
  153. package/dist/esm/hooks/use-cell-renderer.js +9 -4
  154. package/dist/esm/hooks/use-context-setter.d.ts.map +1 -1
  155. package/dist/esm/hooks/use-context-setter.js +5 -1
  156. package/dist/esm/hooks/use-copy-paste-cut.d.ts +5 -0
  157. package/dist/esm/hooks/use-copy-paste-cut.d.ts.map +1 -1
  158. package/dist/esm/hooks/use-copy-paste-cut.js +19 -0
  159. package/dist/esm/hooks/use-editor-change.d.ts +4 -1
  160. package/dist/esm/hooks/use-editor-change.d.ts.map +1 -1
  161. package/dist/esm/hooks/use-editor-change.js +5 -4
  162. package/dist/esm/hooks/use-editor-submit.d.ts +8 -1
  163. package/dist/esm/hooks/use-editor-submit.d.ts.map +1 -1
  164. package/dist/esm/hooks/use-editor-submit.js +10 -2
  165. package/dist/esm/hooks/use-move-columns-rows.d.ts.map +1 -1
  166. package/dist/esm/hooks/use-move-columns-rows.js +6 -0
  167. package/dist/esm/hooks/use-selection-renderer.d.ts +9 -1
  168. package/dist/esm/hooks/use-selection-renderer.d.ts.map +1 -1
  169. package/dist/esm/hooks/use-selection-renderer.js +26 -2
  170. package/dist/esm/hooks/use-selection.d.ts +13 -5
  171. package/dist/esm/hooks/use-selection.d.ts.map +1 -1
  172. package/dist/esm/hooks/use-selection.js +39 -3
  173. package/dist/esm/index.d.ts +7 -0
  174. package/dist/esm/index.d.ts.map +1 -1
  175. package/dist/esm/index.js +7 -0
  176. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  177. package/dist/esm/types.d.ts +8 -0
  178. package/dist/esm/types.d.ts.map +1 -1
  179. package/dist/spreadsheet.min.css +1 -1
  180. package/package.json +8 -7
@@ -6,12 +6,13 @@ 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();
@@ -782,7 +792,8 @@ function CanvasGridComponent(props, forwardedRef) {
782
792
  if (showFormulas && !protectFormulas) {
783
793
  const formulaValue = getFormulaValue(sheetId, rowIndex, columnIndex);
784
794
  if (formulaValue) {
785
- return formulaValue;
795
+ // "Show Formulas" paints the formula the way the editor would show it.
796
+ return localizeFormula(formulaValue, formulaLocale);
786
797
  }
787
798
  }
788
799
  const formattedValue = getFormattedValueProp
@@ -803,6 +814,7 @@ function CanvasGridComponent(props, forwardedRef) {
803
814
  isColumnHeader,
804
815
  getRowHeaderText,
805
816
  getColumnHeaderText,
817
+ formulaLocale,
806
818
  ]);
807
819
  /**
808
820
  * Get information about cell grouping
@@ -943,6 +955,15 @@ function CanvasGridComponent(props, forwardedRef) {
943
955
  ]);
944
956
  // Add a stable reference to get userEnteredString value
945
957
  const getUserEnteredStringValueStable = useCallbackRef(getUserEnteredStringValue);
958
+ /**
959
+ * What the cell editor / formula bar open with: the stored (canonical) entry rendered in the
960
+ * grid's formula locale — `=SUM(1.5,A1)` shows as `=СУММ(1,5;A1)` in ru-RU, a stored `#VALUE!`
961
+ * as `#ЗНАЧ!`. `useEditorSubmit` canonicalizes the text again on commit.
962
+ */
963
+ const getEditorDisplayValue = useCallback((sheetId, rowIndex, columnIndex) => {
964
+ const value = getUserEnteredStringValue(sheetId, rowIndex, columnIndex);
965
+ return isNil(value) ? value : localizeCellInput(value, formulaLocale);
966
+ }, [getUserEnteredStringValue, formulaLocale]);
946
967
  /**
947
968
  * Get cell value used for validations
948
969
  */
@@ -1216,6 +1237,20 @@ function CanvasGridComponent(props, forwardedRef) {
1216
1237
  activeCell,
1217
1238
  tokenizer: defaultTokenizer,
1218
1239
  });
1240
+ /**
1241
+ * The editor's text is in the formula locale's syntax; this tokenizer reads it as such (token
1242
+ * TYPES stay canonical, positions and images are the localized text's). The canonical
1243
+ * `tokenizer` above is what the state hooks and the public context keep using for stored formulas.
1244
+ */
1245
+ const localeTokenizerBase = useCallback((value, sheetName) => defaultTokenizer(value, sheetName, formulaLocale), [defaultTokenizer, formulaLocale]);
1246
+ const localeTokenizer = useCreateFormulaTokenizer({
1247
+ getSelectionFromNamedRange,
1248
+ getSelectionFromTable,
1249
+ editingCellCoordinate,
1250
+ sheetId,
1251
+ activeCell,
1252
+ tokenizer: formulaLocale.isCanonical ? defaultTokenizer : localeTokenizerBase,
1253
+ });
1219
1254
  // Helper function to convert a selection to readable selection address
1220
1255
  const [getAddressFromSelection, getR1C1AddressFromSelection] = useCreateAddressFromSelection({
1221
1256
  sheetId,
@@ -1254,12 +1289,12 @@ function CanvasGridComponent(props, forwardedRef) {
1254
1289
  const getSelectionsFromFormula = useCallbackRef(useCallback((value, cell) => {
1255
1290
  const editingSheetName = getSheetName?.(editingCellCoordinate?.sheetId ?? sheetId);
1256
1291
  const editingSheetId = editingCellCoordinate?.sheetId ?? sheetId;
1257
- return generateSelectionsFromFormula(value, editingSheetId, editingSheetName, cell, rowCount, columnCount, tokenizer, getSelectionFromTable, getSelectionFromNamedRange);
1292
+ return generateSelectionsFromFormula(value, editingSheetId, editingSheetName, cell, rowCount, columnCount, localeTokenizer, getSelectionFromTable, getSelectionFromNamedRange);
1258
1293
  }, [
1259
1294
  rowCount,
1260
1295
  columnCount,
1261
1296
  editingCellCoordinate,
1262
- tokenizer,
1297
+ localeTokenizer,
1263
1298
  getSelectionFromTable,
1264
1299
  getSheetName,
1265
1300
  getSelectionFromNamedRange,
@@ -1815,7 +1850,7 @@ function CanvasGridComponent(props, forwardedRef) {
1815
1850
  const editingSheetName = getSheetName?.(editingSheetId);
1816
1851
  const effectiveValue = getEffectiveValue(editingSheetId, rowIndex, columnIndex);
1817
1852
  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 }));
1853
+ 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
1854
  }, [
1820
1855
  scale,
1821
1856
  getEffectiveCellFormat,
@@ -1826,10 +1861,11 @@ function CanvasGridComponent(props, forwardedRef) {
1826
1861
  showFormulaHelp,
1827
1862
  onHideFormulaHelp,
1828
1863
  onShowFormulaHelp,
1829
- tokenizer,
1864
+ localeTokenizer,
1865
+ formulaLocale,
1830
1866
  cellBackgroundColor,
1831
1867
  cellColor,
1832
- functionDescriptions,
1868
+ localizedFunctionDescriptions,
1833
1869
  getNamedRanges,
1834
1870
  getTableNames,
1835
1871
  getStructuredProperties,
@@ -1963,6 +1999,119 @@ function CanvasGridComponent(props, forwardedRef) {
1963
1999
  if (fillOptions?.mode === "menu")
1964
2000
  setFillOptions(null);
1965
2001
  }, [fillOptions, setFillOptions]);
2002
+ /**
2003
+ * Row / column inserts driven from this grid (context menu, Insert dialog,
2004
+ * Ctrl+Shift+=) also arm Excel's Insert Options smart tag on the new band.
2005
+ * The engine already applied "Format Same As Above / Left" (#647 FMT-01/02);
2006
+ * the tag lets the user switch to the other neighbour or clear.
2007
+ */
2008
+ const insertRowWithOptions = useCallback((targetSheetId, rowIndex, numRows) => {
2009
+ if (!onInsertRow)
2010
+ return;
2011
+ onInsertRow(targetSheetId, rowIndex, numRows);
2012
+ if (numRows > 0) {
2013
+ setInsertOptions({
2014
+ sheetId: targetSheetId,
2015
+ axis: "row",
2016
+ start: rowIndex,
2017
+ count: numRows,
2018
+ option: "before",
2019
+ });
2020
+ }
2021
+ }, [onInsertRow, setInsertOptions]);
2022
+ const insertColumnWithOptions = useCallback((targetSheetId, columnIndex, numColumns) => {
2023
+ if (!onInsertColumn)
2024
+ return;
2025
+ onInsertColumn(targetSheetId, columnIndex, numColumns);
2026
+ if (numColumns > 0) {
2027
+ setInsertOptions({
2028
+ sheetId: targetSheetId,
2029
+ axis: "column",
2030
+ start: columnIndex,
2031
+ count: numColumns,
2032
+ option: "before",
2033
+ });
2034
+ }
2035
+ }, [onInsertColumn, setInsertOptions]);
2036
+ /**
2037
+ * User-entered format of a cell for the Insert Options re-format. A legacy
2038
+ * `StyleReference` (xlsx-imported style id) cannot be copied verbatim, so
2039
+ * it resolves through `getEffectiveFormat` instead.
2040
+ */
2041
+ const readInsertFormat = useCallback((rowIndex, columnIndex) => {
2042
+ const uf = getCellData?.(sheetId, rowIndex, columnIndex)?.uf;
2043
+ if (!uf)
2044
+ return undefined;
2045
+ const isStyleReference = "sid" in uf || "styleId" in uf;
2046
+ return isStyleReference
2047
+ ? getEffectiveFormat?.(sheetId, rowIndex, columnIndex)
2048
+ : uf;
2049
+ }, [getCellData, getEffectiveFormat, sheetId]);
2050
+ /**
2051
+ * Insert Options smart tag choice. "Same As Above / Below" (Left / Right)
2052
+ * re-paints the band with the neighbour's per-cell formats through the same
2053
+ * paint-format path both engines share (`onChangeFormatting` with a format
2054
+ * grid + `replace`), so the earlier choice does not linger; "Clear
2055
+ * Formatting" wipes the band. A band that already holds values was not
2056
+ * (or is no longer) a fresh insert — the refused-insert case — so the tag
2057
+ * just goes away instead of re-formatting live data.
2058
+ */
2059
+ const handleChooseInsertOption = useCallback((option) => {
2060
+ if (!insertOptions || insertOptions.sheetId !== sheetId)
2061
+ return;
2062
+ const band = {
2063
+ axis: insertOptions.axis,
2064
+ start: insertOptions.start,
2065
+ count: insertOptions.count,
2066
+ };
2067
+ const limit = band.axis === "row" ? columnCount : rowCount;
2068
+ const hasValue = (rowIndex, columnIndex) => {
2069
+ const cell = getCellData?.(sheetId, rowIndex, columnIndex);
2070
+ return !isNil(cell?.ue ?? cell?.userEnteredValue);
2071
+ };
2072
+ if (insertedBandHasValues(band, hasValue, limit)) {
2073
+ setInsertOptions(null);
2074
+ return;
2075
+ }
2076
+ const clearBand = () => {
2077
+ const range = clearRangeForInsertedBand(band, readInsertFormat, limit);
2078
+ if (range)
2079
+ onClearFormatting?.(sheetId, activeCell, [{ range }]);
2080
+ };
2081
+ if (option === "clear") {
2082
+ clearBand();
2083
+ }
2084
+ else {
2085
+ const plan = formatsForInsertOption(band, option, readInsertFormat, limit);
2086
+ if (plan) {
2087
+ // Both engines accept the paint-format shape (format grid + replace);
2088
+ // the grid prop type only names the key/value overload.
2089
+ onChangeFormatting?.(sheetId, activeCell, plan.selections, plan.formats, { replace: true });
2090
+ }
2091
+ else {
2092
+ clearBand();
2093
+ }
2094
+ }
2095
+ setInsertOptions({ ...insertOptions, option });
2096
+ focusSheet();
2097
+ }, [
2098
+ insertOptions,
2099
+ sheetId,
2100
+ columnCount,
2101
+ rowCount,
2102
+ getCellData,
2103
+ readInsertFormat,
2104
+ onClearFormatting,
2105
+ onChangeFormatting,
2106
+ activeCell,
2107
+ setInsertOptions,
2108
+ focusSheet,
2109
+ ]);
2110
+ // The smart tag belongs to one insert; moving on (a new active cell or
2111
+ // sheet) drops it. Keyed on coordinates like the fill-options tag.
2112
+ useEffect(() => {
2113
+ setInsertOptions(null);
2114
+ }, [activeCell.rowIndex, activeCell.columnIndex, sheetId, setInsertOptions]);
1966
2115
  /**
1967
2116
  * Run Excel's Series dialog result: the target range's first row (Series
1968
2117
  * in Columns) / first column (Rows) is the seed line; `stop` may shrink or
@@ -2034,6 +2183,14 @@ function CanvasGridComponent(props, forwardedRef) {
2034
2183
  useEffect(() => {
2035
2184
  setFillOptions(null);
2036
2185
  }, [activeCell.rowIndex, activeCell.columnIndex, sheetId, setFillOptions]);
2186
+ /**
2187
+ * Drag-move overwrite prompt ("There's already data here. Do you want to replace it?").
2188
+ * Routed to the host-mounted `MoveOverwriteConfirmDialogHost` when there is one; the
2189
+ * selection hook falls back to `window.confirm` otherwise.
2190
+ */
2191
+ const openMoveOverwriteConfirm = useOpenMoveOverwriteConfirm();
2192
+ const isMoveOverwriteConfirmMounted = useIsMoveOverwriteConfirmMounted();
2193
+ const confirmMoveOverwrite = useMemo(() => (isMoveOverwriteConfirmMounted ? openMoveOverwriteConfirm : undefined), [isMoveOverwriteConfirmMounted, openMoveOverwriteConfirm]);
2037
2194
  /**
2038
2195
  * Fill handle dragged BACK inside the selection (Excel): the dragged-over cells lose their
2039
2196
  * contents — formats stay unless Ctrl/Cmd was held — through the same `onDelete` path as the
@@ -2076,6 +2233,8 @@ function CanvasGridComponent(props, forwardedRef) {
2076
2233
  onFillHandleRelease: handleFillHandleRelease,
2077
2234
  onFillShrink: handleFillShrink,
2078
2235
  onMoveSelection,
2236
+ onInsertCutCells,
2237
+ confirmMoveOverwrite,
2079
2238
  isHiddenColumn,
2080
2239
  isHiddenRow,
2081
2240
  isRowHeader,
@@ -2086,7 +2245,7 @@ function CanvasGridComponent(props, forwardedRef) {
2086
2245
  /**
2087
2246
  * Copy, Paste and Cut hook
2088
2247
  */
2089
- const { copiedSelections, clearCopiedSelections, copy, cut, paste, onInternalCopy, onInternalCut, onInternalPaste, } = useCopyPasteCut({
2248
+ const { copiedSelections, isCutPending, copiedSheetId, cancelCut, clearCopiedSelections, copy, cut, paste, onInternalCopy, onInternalCut, onInternalPaste, } = useCopyPasteCut({
2090
2249
  activeCell,
2091
2250
  selections,
2092
2251
  sheetId,
@@ -2095,6 +2254,54 @@ function CanvasGridComponent(props, forwardedRef) {
2095
2254
  onCopy,
2096
2255
  onCut,
2097
2256
  });
2257
+ /**
2258
+ * Context menu "Insert Cut Cells" (Excel: Ctrl+X, right-click the destination). A cut of
2259
+ * whole rows / columns dropped on a row / column header inserts them BEFORE the clicked
2260
+ * header in pre-removal numbering (`insertBefore`); anything else inserts the cut block at
2261
+ * the active cell, displacing the cells there (`onInsertCutCells`). Consumes the cut.
2262
+ */
2263
+ const insertCutCellsFromMenu = useCallback((target) => {
2264
+ const from = copiedSelections[0];
2265
+ if (!from || !isCutPending)
2266
+ return;
2267
+ const { range } = from;
2268
+ const wholeRows = range.startColumnIndex <= 1 && range.endColumnIndex >= columnCount;
2269
+ const wholeColumns = range.startRowIndex <= 1 && range.endRowIndex >= rowCount;
2270
+ const span = (start, end) => Array.from({ length: end - start + 1 }, (_, i) => start + i);
2271
+ if (target === "rows" && wholeRows) {
2272
+ onMoveRows?.(sheetId, span(range.startRowIndex, range.endRowIndex), activeCell.rowIndex, {
2273
+ insertBefore: true,
2274
+ });
2275
+ }
2276
+ else if (target === "columns" && wholeColumns) {
2277
+ onMoveColumns?.(sheetId, span(range.startColumnIndex, range.endColumnIndex), activeCell.columnIndex, { insertBefore: true });
2278
+ }
2279
+ else {
2280
+ const to = {
2281
+ range: {
2282
+ startRowIndex: activeCell.rowIndex,
2283
+ startColumnIndex: activeCell.columnIndex,
2284
+ endRowIndex: activeCell.rowIndex + (range.endRowIndex - range.startRowIndex),
2285
+ endColumnIndex: activeCell.columnIndex + (range.endColumnIndex - range.startColumnIndex),
2286
+ },
2287
+ };
2288
+ onInsertCutCells?.(sheetId, from, to);
2289
+ }
2290
+ cancelCut();
2291
+ focusSheet();
2292
+ }, [
2293
+ copiedSelections,
2294
+ isCutPending,
2295
+ columnCount,
2296
+ rowCount,
2297
+ sheetId,
2298
+ activeCell,
2299
+ onMoveRows,
2300
+ onMoveColumns,
2301
+ onInsertCutCells,
2302
+ cancelCut,
2303
+ focusSheet,
2304
+ ]);
2098
2305
  /**
2099
2306
  * Paste Special dialog (context menu → Paste special…, Ctrl+Alt+V). The
2100
2307
  * dialog is host-mounted (`PasteSpecialDialogHost`); its request routes
@@ -2205,6 +2412,7 @@ function CanvasGridComponent(props, forwardedRef) {
2205
2412
  onChangeSelections,
2206
2413
  getSelectionsFromFormula,
2207
2414
  onChangeEditorValue,
2415
+ formulaLocale,
2208
2416
  });
2209
2417
  // Get final row height to expand to based on value of a cell
2210
2418
  const getFinalRowHeight = useCallbackRef(useCallback((sheetId, rowIndex, columnIndex, options) => {
@@ -2249,6 +2457,7 @@ function CanvasGridComponent(props, forwardedRef) {
2249
2457
  showValidationAlert,
2250
2458
  selections,
2251
2459
  onChangeBatch,
2460
+ formulaLocale,
2252
2461
  });
2253
2462
  /**
2254
2463
  * User cancels editing the cell
@@ -2337,7 +2546,7 @@ function CanvasGridComponent(props, forwardedRef) {
2337
2546
  * Get context Menu component
2338
2547
  */
2339
2548
  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 }));
2549
+ 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
2550
  }, [
2342
2551
  isRestricted,
2343
2552
  activeCell,
@@ -2350,8 +2559,10 @@ function CanvasGridComponent(props, forwardedRef) {
2350
2559
  onHideRow,
2351
2560
  onDeleteColumn,
2352
2561
  onDeleteRow,
2353
- onInsertColumn,
2354
- onInsertRow,
2562
+ insertColumnWithOptions,
2563
+ insertRowWithOptions,
2564
+ rowCount,
2565
+ columnCount,
2355
2566
  onInsertCellsShiftDown,
2356
2567
  onInsertCellsShiftRight,
2357
2568
  onDeleteCellsShiftLeft,
@@ -2489,7 +2700,7 @@ function CanvasGridComponent(props, forwardedRef) {
2489
2700
  onGroupColumns,
2490
2701
  onUngroupColumns,
2491
2702
  onDeleteRow,
2492
- onInsertRow,
2703
+ onInsertRow: insertRowWithOptions,
2493
2704
  onInsertAutoSum,
2494
2705
  onShowColumn,
2495
2706
  onShowRow,
@@ -2531,7 +2742,7 @@ function CanvasGridComponent(props, forwardedRef) {
2531
2742
  selections,
2532
2743
  getSheetColumnCount,
2533
2744
  getSheetRowCount,
2534
- getValue: getUserEnteredStringValue,
2745
+ getValue: getEditorDisplayValue,
2535
2746
  getTextFormatRuns,
2536
2747
  getBooleanValue,
2537
2748
  getDataValidation: getDataValidationRule,
@@ -3004,6 +3215,7 @@ function CanvasGridComponent(props, forwardedRef) {
3004
3215
  */
3005
3216
  const [cellBackgroundRenderer, cellRenderer, cellOverlayRenderer, headerCellRenderer,] = useCellRenderer({
3006
3217
  sheetId,
3218
+ formulaLocale,
3007
3219
  showGridLines,
3008
3220
  scale,
3009
3221
  enableTextOverflow,
@@ -3104,13 +3316,13 @@ function CanvasGridComponent(props, forwardedRef) {
3104
3316
  getCellBounds,
3105
3317
  getCellCoordsFromOffset,
3106
3318
  scrollToCell,
3107
- tokenizer,
3319
+ tokenizer: localeTokenizer,
3108
3320
  });
3109
3321
  // Selection move: drag a formula reference via its border covers
3110
3322
  const { onMouseDownMoveSelection, isDragging: isDraggingMoveSelection } = useSelectionMove({
3111
3323
  getCellCoordsFromOffset,
3112
3324
  scrollToCell,
3113
- tokenizer,
3325
+ tokenizer: localeTokenizer,
3114
3326
  });
3115
3327
  /**
3116
3328
  * Hide fill handle
@@ -3174,6 +3386,8 @@ function CanvasGridComponent(props, forwardedRef) {
3174
3386
  onChooseFillType: handleChooseFillType,
3175
3387
  onOpenFillSeriesDialog: handleOpenFillSeriesDialog,
3176
3388
  onCloseFillOptions: handleCloseFillOptions,
3389
+ insertOptions,
3390
+ onChooseInsertOption: handleChooseInsertOption,
3177
3391
  hoveredCell: delayedHoveredCell,
3178
3392
  onRemoveQuickEdit,
3179
3393
  onAddQuickEdit,
@@ -3345,6 +3559,8 @@ function CanvasGridComponent(props, forwardedRef) {
3345
3559
  getAddressFromSelection,
3346
3560
  getR1C1AddressFromSelection,
3347
3561
  tokenizer,
3562
+ localeTokenizer,
3563
+ formulaLocale,
3348
3564
  setEditorValue,
3349
3565
  getCellBounds,
3350
3566
  getNamedRanges,
@@ -3509,8 +3725,8 @@ function CanvasGridComponent(props, forwardedRef) {
3509
3725
  const { rowIndex, columnIndex } = activeCell;
3510
3726
  const value = getUserEnteredStringValue(sheetId, rowIndex, columnIndex);
3511
3727
  const textFormatRuns = getTextFormatRuns?.(sheetId, rowIndex, columnIndex);
3512
- // Update formula bar input
3513
- setFormulabarEditorValue(value ?? "");
3728
+ // Update formula bar input (in the grid's formula locale, like the cell editor)
3729
+ setFormulabarEditorValue(localizeCellInput(value ?? "", formulaLocale));
3514
3730
  setFormulaBarTextFormatRuns(textFormatRuns);
3515
3731
  }, [
3516
3732
  activeCell,
@@ -3518,6 +3734,7 @@ function CanvasGridComponent(props, forwardedRef) {
3518
3734
  sheetId,
3519
3735
  editingCellCoordinate,
3520
3736
  getUserEnteredStringValue,
3737
+ formulaLocale,
3521
3738
  setFormulabarEditorValue,
3522
3739
  setFormulaBarTextFormatRuns,
3523
3740
  ]);
@@ -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
  */