@rowsncolumns/spreadsheet 10.2.74 → 10.2.76
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.
- package/dist/cjs/api/excel-validation-kinds.d.ts +71 -0
- package/dist/cjs/api/excel-validation-kinds.d.ts.map +1 -0
- package/dist/cjs/api/excel-validation-kinds.js +304 -0
- package/dist/cjs/api/fill-series.d.ts +38 -0
- package/dist/cjs/api/fill-series.d.ts.map +1 -0
- package/dist/cjs/api/fill-series.js +89 -0
- package/dist/cjs/api/go-to-special.d.ts +32 -0
- package/dist/cjs/api/go-to-special.d.ts.map +1 -0
- package/dist/cjs/api/go-to-special.js +111 -0
- package/dist/cjs/api/spreadsheet-api.d.ts +6 -2
- package/dist/cjs/api/spreadsheet-api.d.ts.map +1 -1
- package/dist/cjs/api/spreadsheet-api.js +9 -3
- package/dist/cjs/api/validation-tooltip.d.ts +17 -0
- package/dist/cjs/api/validation-tooltip.d.ts.map +1 -0
- package/dist/cjs/api/validation-tooltip.js +42 -0
- package/dist/cjs/atoms/advanced-filter-dialog.atom.d.ts +28 -0
- package/dist/cjs/atoms/advanced-filter-dialog.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/advanced-filter-dialog.atom.js +32 -0
- package/dist/cjs/atoms/fill-options.atom.d.ts +36 -0
- package/dist/cjs/atoms/fill-options.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/fill-options.atom.js +11 -0
- package/dist/cjs/atoms/fill-series-dialog.atom.d.ts +26 -0
- package/dist/cjs/atoms/fill-series-dialog.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/fill-series-dialog.atom.js +14 -0
- package/dist/cjs/atoms/go-to-dialog.atom.d.ts +11 -1
- package/dist/cjs/atoms/go-to-dialog.atom.d.ts.map +1 -1
- package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts +29 -0
- package/dist/cjs/atoms/goal-seek-dialog.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/goal-seek-dialog.atom.js +30 -0
- package/dist/cjs/atoms/index.d.ts +3 -0
- package/dist/cjs/atoms/index.d.ts.map +1 -1
- package/dist/cjs/atoms/index.js +3 -0
- package/dist/cjs/atoms/subtotal-dialog.atom.d.ts +39 -0
- package/dist/cjs/atoms/subtotal-dialog.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/subtotal-dialog.atom.js +30 -0
- package/dist/cjs/atoms/text-to-columns-dialog.atom.d.ts +34 -0
- package/dist/cjs/atoms/text-to-columns-dialog.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/text-to-columns-dialog.atom.js +36 -0
- package/dist/cjs/atoms/watch-window.atom.d.ts +37 -0
- package/dist/cjs/atoms/watch-window.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/watch-window.atom.js +61 -0
- package/dist/cjs/components/advanced-filter-dialog/index.d.ts +28 -0
- package/dist/cjs/components/advanced-filter-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/advanced-filter-dialog/index.js +134 -0
- package/dist/cjs/components/calculation-options-dialog/index.d.ts +33 -0
- package/dist/cjs/components/calculation-options-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/calculation-options-dialog/index.js +69 -0
- package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
- package/dist/cjs/components/canvas-grid/index.js +328 -71
- package/dist/cjs/components/canvas-grid/typings.d.ts +31 -5
- package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
- package/dist/cjs/components/cell/alignment.d.ts +30 -0
- package/dist/cjs/components/cell/alignment.d.ts.map +1 -1
- package/dist/cjs/components/cell/alignment.js +56 -1
- package/dist/cjs/components/cell/index.d.ts.map +1 -1
- package/dist/cjs/components/cell/index.js +15 -7
- package/dist/cjs/components/cell-diff/index.d.ts +3 -2
- package/dist/cjs/components/cell-diff/index.d.ts.map +1 -1
- package/dist/cjs/components/cell-editor/helpers.d.ts +9 -0
- package/dist/cjs/components/cell-editor/helpers.d.ts.map +1 -1
- package/dist/cjs/components/cell-editor/helpers.js +8 -1
- package/dist/cjs/components/cell-editor/helpers.spec.js +14 -0
- package/dist/cjs/components/cell-editor/index.d.ts.map +1 -1
- package/dist/cjs/components/cell-editor/index.js +7 -3
- package/dist/cjs/components/context-menu/index.d.ts +6 -1
- package/dist/cjs/components/context-menu/index.d.ts.map +1 -1
- package/dist/cjs/components/context-menu/index.js +146 -3
- package/dist/cjs/components/embeds/embed-component.d.ts.map +1 -1
- package/dist/cjs/components/embeds/embed-component.js +16 -1
- package/dist/cjs/components/fill-series-dialog/index.d.ts +29 -0
- package/dist/cjs/components/fill-series-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/fill-series-dialog/index.js +156 -0
- package/dist/cjs/components/go-to-dialog/index.d.ts +11 -1
- package/dist/cjs/components/go-to-dialog/index.d.ts.map +1 -1
- package/dist/cjs/components/go-to-dialog/index.js +67 -24
- package/dist/cjs/components/goal-seek-dialog/index.d.ts +32 -0
- package/dist/cjs/components/goal-seek-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/goal-seek-dialog/index.js +149 -0
- package/dist/cjs/components/selection/fill-options-menu.d.ts +32 -0
- package/dist/cjs/components/selection/fill-options-menu.d.ts.map +1 -0
- package/dist/cjs/components/selection/fill-options-menu.js +65 -0
- package/dist/cjs/components/selection/index.d.ts +1 -1
- package/dist/cjs/components/selection/index.d.ts.map +1 -1
- package/dist/cjs/components/selection/index.js +4 -2
- package/dist/cjs/components/selection/types.d.ts +11 -1
- package/dist/cjs/components/selection/types.d.ts.map +1 -1
- package/dist/cjs/components/subtotal-dialog/index.d.ts +30 -0
- package/dist/cjs/components/subtotal-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/subtotal-dialog/index.js +126 -0
- package/dist/cjs/components/text-to-columns-dialog/index.d.ts +37 -0
- package/dist/cjs/components/text-to-columns-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/text-to-columns-dialog/index.js +166 -0
- package/dist/cjs/components/toolbar/background-color-selector.d.ts +13 -1
- package/dist/cjs/components/toolbar/background-color-selector.d.ts.map +1 -1
- package/dist/cjs/components/toolbar/background-color-selector.js +57 -11
- package/dist/cjs/components/toolbar/cell-style-selector.d.ts +15 -2
- package/dist/cjs/components/toolbar/cell-style-selector.d.ts.map +1 -1
- package/dist/cjs/components/toolbar/cell-style-selector.js +56 -3
- package/dist/cjs/components/toolbar/fill-selectors.d.ts +49 -0
- package/dist/cjs/components/toolbar/fill-selectors.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/fill-selectors.js +196 -0
- package/dist/cjs/components/toolbar/index.d.ts +1 -0
- package/dist/cjs/components/toolbar/index.d.ts.map +1 -1
- package/dist/cjs/components/toolbar/index.js +1 -0
- package/dist/cjs/components/toolbar/text-format-selector.d.ts +9 -0
- package/dist/cjs/components/toolbar/text-format-selector.d.ts.map +1 -1
- package/dist/cjs/components/toolbar/text-format-selector.js +15 -3
- package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts +8 -0
- package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -1
- package/dist/cjs/components/toolbar/text-horizontal-align-selector.js +23 -4
- package/dist/cjs/components/watch-window/index.d.ts +25 -0
- package/dist/cjs/components/watch-window/index.d.ts.map +1 -0
- package/dist/cjs/components/watch-window/index.js +63 -0
- package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -1
- package/dist/cjs/hooks/use-cell-renderer.js +17 -6
- package/dist/cjs/hooks/use-editable.d.ts +11 -2
- package/dist/cjs/hooks/use-editable.d.ts.map +1 -1
- package/dist/cjs/hooks/use-editable.js +8 -0
- package/dist/cjs/hooks/use-editor-submit.d.ts +32 -3
- package/dist/cjs/hooks/use-editor-submit.d.ts.map +1 -1
- package/dist/cjs/hooks/use-editor-submit.js +111 -2
- package/dist/cjs/hooks/use-get-tooltip.d.ts.map +1 -1
- package/dist/cjs/hooks/use-get-tooltip.js +7 -2
- package/dist/cjs/hooks/use-keyboard-handler.d.ts.map +1 -1
- package/dist/cjs/hooks/use-keyboard-handler.js +27 -14
- package/dist/cjs/hooks/use-selection-renderer.d.ts +13 -2
- package/dist/cjs/hooks/use-selection-renderer.d.ts.map +1 -1
- package/dist/cjs/hooks/use-selection-renderer.js +21 -4
- package/dist/cjs/hooks/use-selection.d.ts +54 -4
- package/dist/cjs/hooks/use-selection.d.ts.map +1 -1
- package/dist/cjs/hooks/use-selection.js +232 -37
- package/dist/cjs/index.d.ts +12 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +11 -0
- package/dist/cjs/release-date.js +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +156 -5
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js +19 -1
- package/dist/esm/api/excel-validation-kinds.d.ts +71 -0
- package/dist/esm/api/excel-validation-kinds.d.ts.map +1 -0
- package/dist/esm/api/excel-validation-kinds.js +287 -0
- package/dist/esm/api/fill-series.d.ts +38 -0
- package/dist/esm/api/fill-series.d.ts.map +1 -0
- package/dist/esm/api/fill-series.js +78 -0
- package/dist/esm/api/go-to-special.d.ts +32 -0
- package/dist/esm/api/go-to-special.d.ts.map +1 -0
- package/dist/esm/api/go-to-special.js +96 -0
- package/dist/esm/api/spreadsheet-api.d.ts +6 -2
- package/dist/esm/api/spreadsheet-api.d.ts.map +1 -1
- package/dist/esm/api/spreadsheet-api.js +8 -3
- package/dist/esm/api/validation-tooltip.d.ts +17 -0
- package/dist/esm/api/validation-tooltip.d.ts.map +1 -0
- package/dist/esm/api/validation-tooltip.js +34 -0
- package/dist/esm/atoms/advanced-filter-dialog.atom.d.ts +28 -0
- package/dist/esm/atoms/advanced-filter-dialog.atom.d.ts.map +1 -0
- package/dist/esm/atoms/advanced-filter-dialog.atom.js +21 -0
- package/dist/esm/atoms/fill-options.atom.d.ts +36 -0
- package/dist/esm/atoms/fill-options.atom.d.ts.map +1 -0
- package/dist/esm/atoms/fill-options.atom.js +5 -0
- package/dist/esm/atoms/fill-series-dialog.atom.d.ts +26 -0
- package/dist/esm/atoms/fill-series-dialog.atom.d.ts.map +1 -0
- package/dist/esm/atoms/fill-series-dialog.atom.js +9 -0
- package/dist/esm/atoms/go-to-dialog.atom.d.ts +11 -1
- package/dist/esm/atoms/go-to-dialog.atom.d.ts.map +1 -1
- package/dist/esm/atoms/goal-seek-dialog.atom.d.ts +29 -0
- package/dist/esm/atoms/goal-seek-dialog.atom.d.ts.map +1 -0
- package/dist/esm/atoms/goal-seek-dialog.atom.js +21 -0
- package/dist/esm/atoms/index.d.ts +3 -0
- package/dist/esm/atoms/index.d.ts.map +1 -1
- package/dist/esm/atoms/index.js +3 -0
- package/dist/esm/atoms/subtotal-dialog.atom.d.ts +39 -0
- package/dist/esm/atoms/subtotal-dialog.atom.d.ts.map +1 -0
- package/dist/esm/atoms/subtotal-dialog.atom.js +21 -0
- package/dist/esm/atoms/text-to-columns-dialog.atom.d.ts +34 -0
- package/dist/esm/atoms/text-to-columns-dialog.atom.d.ts.map +1 -0
- package/dist/esm/atoms/text-to-columns-dialog.atom.js +25 -0
- package/dist/esm/atoms/watch-window.atom.d.ts +37 -0
- package/dist/esm/atoms/watch-window.atom.d.ts.map +1 -0
- package/dist/esm/atoms/watch-window.atom.js +37 -0
- package/dist/esm/components/advanced-filter-dialog/index.d.ts +28 -0
- package/dist/esm/components/advanced-filter-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/advanced-filter-dialog/index.js +125 -0
- package/dist/esm/components/calculation-options-dialog/index.d.ts +33 -0
- package/dist/esm/components/calculation-options-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/calculation-options-dialog/index.js +61 -0
- package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
- package/dist/esm/components/canvas-grid/index.js +266 -26
- package/dist/esm/components/canvas-grid/typings.d.ts +31 -5
- package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
- package/dist/esm/components/cell/alignment.d.ts +30 -0
- package/dist/esm/components/cell/alignment.d.ts.map +1 -1
- package/dist/esm/components/cell/alignment.js +51 -0
- package/dist/esm/components/cell/index.d.ts.map +1 -1
- package/dist/esm/components/cell/index.js +16 -8
- package/dist/esm/components/cell-diff/index.d.ts +3 -2
- package/dist/esm/components/cell-diff/index.d.ts.map +1 -1
- package/dist/esm/components/cell-editor/helpers.d.ts +9 -0
- package/dist/esm/components/cell-editor/helpers.d.ts.map +1 -1
- package/dist/esm/components/cell-editor/helpers.js +6 -0
- package/dist/esm/components/cell-editor/helpers.spec.js +15 -1
- package/dist/esm/components/cell-editor/index.d.ts.map +1 -1
- package/dist/esm/components/cell-editor/index.js +8 -4
- package/dist/esm/components/context-menu/index.d.ts +6 -1
- package/dist/esm/components/context-menu/index.d.ts.map +1 -1
- package/dist/esm/components/context-menu/index.js +139 -4
- package/dist/esm/components/embeds/embed-component.d.ts.map +1 -1
- package/dist/esm/components/embeds/embed-component.js +17 -1
- package/dist/esm/components/fill-series-dialog/index.d.ts +29 -0
- package/dist/esm/components/fill-series-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/fill-series-dialog/index.js +151 -0
- package/dist/esm/components/go-to-dialog/index.d.ts +11 -1
- package/dist/esm/components/go-to-dialog/index.d.ts.map +1 -1
- package/dist/esm/components/go-to-dialog/index.js +63 -23
- package/dist/esm/components/goal-seek-dialog/index.d.ts +32 -0
- package/dist/esm/components/goal-seek-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/goal-seek-dialog/index.js +125 -0
- package/dist/esm/components/selection/fill-options-menu.d.ts +32 -0
- package/dist/esm/components/selection/fill-options-menu.d.ts.map +1 -0
- package/dist/esm/components/selection/fill-options-menu.js +63 -0
- package/dist/esm/components/selection/index.d.ts +1 -1
- package/dist/esm/components/selection/index.d.ts.map +1 -1
- package/dist/esm/components/selection/index.js +4 -2
- package/dist/esm/components/selection/types.d.ts +11 -1
- package/dist/esm/components/selection/types.d.ts.map +1 -1
- package/dist/esm/components/subtotal-dialog/index.d.ts +30 -0
- package/dist/esm/components/subtotal-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/subtotal-dialog/index.js +115 -0
- package/dist/esm/components/text-to-columns-dialog/index.d.ts +37 -0
- package/dist/esm/components/text-to-columns-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/text-to-columns-dialog/index.js +147 -0
- package/dist/esm/components/toolbar/background-color-selector.d.ts +13 -1
- package/dist/esm/components/toolbar/background-color-selector.d.ts.map +1 -1
- package/dist/esm/components/toolbar/background-color-selector.js +61 -11
- package/dist/esm/components/toolbar/cell-style-selector.d.ts +15 -2
- package/dist/esm/components/toolbar/cell-style-selector.d.ts.map +1 -1
- package/dist/esm/components/toolbar/cell-style-selector.js +46 -2
- package/dist/esm/components/toolbar/fill-selectors.d.ts +49 -0
- package/dist/esm/components/toolbar/fill-selectors.d.ts.map +1 -0
- package/dist/esm/components/toolbar/fill-selectors.js +162 -0
- package/dist/esm/components/toolbar/index.d.ts +1 -0
- package/dist/esm/components/toolbar/index.d.ts.map +1 -1
- package/dist/esm/components/toolbar/index.js +1 -0
- package/dist/esm/components/toolbar/text-format-selector.d.ts +9 -0
- package/dist/esm/components/toolbar/text-format-selector.d.ts.map +1 -1
- package/dist/esm/components/toolbar/text-format-selector.js +14 -2
- package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts +8 -0
- package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -1
- package/dist/esm/components/toolbar/text-horizontal-align-selector.js +21 -5
- package/dist/esm/components/watch-window/index.d.ts +25 -0
- package/dist/esm/components/watch-window/index.d.ts.map +1 -0
- package/dist/esm/components/watch-window/index.js +54 -0
- package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -1
- package/dist/esm/hooks/use-cell-renderer.js +17 -6
- package/dist/esm/hooks/use-editable.d.ts +11 -2
- package/dist/esm/hooks/use-editable.d.ts.map +1 -1
- package/dist/esm/hooks/use-editable.js +8 -0
- package/dist/esm/hooks/use-editor-submit.d.ts +32 -3
- package/dist/esm/hooks/use-editor-submit.d.ts.map +1 -1
- package/dist/esm/hooks/use-editor-submit.js +82 -3
- package/dist/esm/hooks/use-get-tooltip.d.ts.map +1 -1
- package/dist/esm/hooks/use-get-tooltip.js +7 -2
- package/dist/esm/hooks/use-keyboard-handler.d.ts.map +1 -1
- package/dist/esm/hooks/use-keyboard-handler.js +27 -14
- package/dist/esm/hooks/use-selection-renderer.d.ts +13 -2
- package/dist/esm/hooks/use-selection-renderer.d.ts.map +1 -1
- package/dist/esm/hooks/use-selection-renderer.js +22 -5
- package/dist/esm/hooks/use-selection.d.ts +54 -4
- package/dist/esm/hooks/use-selection.d.ts.map +1 -1
- package/dist/esm/hooks/use-selection.js +220 -36
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +11 -0
- package/dist/esm/release-date.js +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +156 -5
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +18 -0
- package/dist/spreadsheet.min.css +1 -1
- package/package.json +7 -7
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tokenize as defaultFormulaTokenizer } from "@rowsncolumns/calculator";
|
|
2
|
-
import { Direction, isAreasEqual } from "@rowsncolumns/grid";
|
|
2
|
+
import { cellToArea, Direction, isAreasEqual } from "@rowsncolumns/grid";
|
|
3
3
|
import { canUseDOM } from "@rowsncolumns/grid";
|
|
4
4
|
import { getBoundedCells, MouseButtonCodes } from "@rowsncolumns/grid";
|
|
5
5
|
import { isCellWithinBounds } from "@rowsncolumns/grid";
|
|
@@ -10,15 +10,19 @@ import { cellToAddress, getCellEffectiveFormat, getContrastColor, isConditionalF
|
|
|
10
10
|
import { useStore } from "jotai";
|
|
11
11
|
import merge from "lodash/merge";
|
|
12
12
|
import throttle from "lodash/throttle";
|
|
13
|
-
import React, { forwardRef, memo, startTransition, useCallback, useMemo, useRef, useState, } from "react";
|
|
13
|
+
import React, { forwardRef, memo, startTransition, useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
14
14
|
import { getBandedCells } from "../../api/banded-ranges";
|
|
15
15
|
import { CF_INITIAL_WINDOW, cfWindowForViewport, isSameCfWindow, } from "../../api/cf-window";
|
|
16
16
|
import { generateSelectionsFromFormula } from "../../api/selections";
|
|
17
17
|
import { SpreadsheetApi } from "../../api/spreadsheet-api";
|
|
18
18
|
import { findActiveTableWithinCell } from "../../api/table";
|
|
19
|
+
import { getDataValidationTooltipContent } from "../../api/validation-tooltip";
|
|
20
|
+
import { resolveGoToSpecial } from "../../api/go-to-special";
|
|
21
|
+
import { checkExcelValidationValue, isFormulaEntry, } from "../../api/excel-validation-kinds";
|
|
19
22
|
import { checkBooleanRule, decideValidationCommit, isCellLockedUnderProtection, isProtectedCell, isProtectedSheet, showValidationDropdownArrow, } from "../../api/validation";
|
|
20
|
-
import { useFormulaModeValue, useIsEvaluateFormulaDialogMounted, useIsGoToDialogMounted, useIsPasteSpecialDialogMounted, useOpenEvaluateFormulaDialog, useOpenGoToDialog, useOpenPasteSpecialDialog, useSetNoteEditorCell, useSetPinnedTooltip, useShowPasteMenu, useShowValidationAlert, } from "../../atoms";
|
|
23
|
+
import { useFormulaModeValue, useIsEvaluateFormulaDialogMounted, useIsGoToDialogMounted, useIsPasteSpecialDialogMounted, useOpenEvaluateFormulaDialog, useOpenGoToDialog, useOpenPasteSpecialDialog, useSetNoteEditorCell, useSetPinnedTooltip, useFillOptionsState, useOpenFillSeriesDialog, useShowPasteMenu, useShowValidationAlert, } from "../../atoms";
|
|
21
24
|
import { useActiveEditor } from "../../atoms/active-editor.atom";
|
|
25
|
+
import { useAddWatch, useIsWatchWindowMounted, useSetWatchWindowContext, } from "../../atoms/watch-window.atom";
|
|
22
26
|
import { useEditingCell } from "../../atoms/editing-cell.atom";
|
|
23
27
|
import { useCellEditorInstance, useSetFormulabarEditorValue, useSetFormulaBarTextFormatRuns, } from "../../atoms/formula-bar-editor-value.atom";
|
|
24
28
|
import { useFormulaCanSelectCells, useFormulaSelectionMode, useSetFormulaSelectionState, } from "../../atoms/formula-selection-state.atom";
|
|
@@ -65,7 +69,7 @@ import { useRaf } from "../../hooks/use-raf";
|
|
|
65
69
|
import { useResizeObserver } from "../../hooks/use-resize-observer";
|
|
66
70
|
import { useScaleListener } from "../../hooks/use-scale-listener";
|
|
67
71
|
import { useSelectedRowsColumns } from "../../hooks/use-selected-rows-columns";
|
|
68
|
-
import { useSelection } from "../../hooks/use-selection";
|
|
72
|
+
import { useSelection, } from "../../hooks/use-selection";
|
|
69
73
|
import { useSelectionChange } from "../../hooks/use-selection-change";
|
|
70
74
|
import { useSelectionInterceptors } from "../../hooks/use-selection-interceptors";
|
|
71
75
|
import { useSelectionMove } from "../../hooks/use-selection-move";
|
|
@@ -82,6 +86,7 @@ import { useTouch } from "../../hooks/use-touch";
|
|
|
82
86
|
import { multiInstanceStore } from "../../providers/spreadsheet-provider";
|
|
83
87
|
import { scrollSubscriber } from "../../signals/scroll-subscriber";
|
|
84
88
|
import { getStringifiedColor } from "../../themes";
|
|
89
|
+
import { fillRangeForSeriesSpec, seedRangeForSeriesSpec } from "../../api/fill-series";
|
|
85
90
|
import { Cell as DefaultCell } from "../cell";
|
|
86
91
|
import { CellEditor as DefaultCellEditor } from "../cell-editor";
|
|
87
92
|
import { ContextMenu as DefaultContextMenu } from "../context-menu";
|
|
@@ -100,7 +105,7 @@ import { getNestedPropertyNames } from "./helpers";
|
|
|
100
105
|
* @returns
|
|
101
106
|
*/
|
|
102
107
|
function CanvasGridComponent(props, forwardedRef) {
|
|
103
|
-
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, 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,
|
|
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,
|
|
104
109
|
// Host-driven filter props. `hostHiddenRowRanges`
|
|
105
110
|
// supplies compact [start, end] hidden-row tuples; `getFilterValues` supplies a
|
|
106
111
|
// column's distinct values. Both let a million-row filter render without scanning
|
|
@@ -188,6 +193,9 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
188
193
|
const cellEditorInstance = useCellEditorInstance();
|
|
189
194
|
// Paste menu
|
|
190
195
|
const [showPasteMenu, setShowPasteMenu] = useShowPasteMenu();
|
|
196
|
+
// Auto Fill Options smart tag / right-drag fill menu + Series dialog
|
|
197
|
+
const [fillOptions, setFillOptions] = useFillOptionsState();
|
|
198
|
+
const openFillSeriesDialog = useOpenFillSeriesDialog();
|
|
191
199
|
// Shared state
|
|
192
200
|
const formulaMode = useFormulaModeValue();
|
|
193
201
|
const formulaSelections = useFormulaSelections();
|
|
@@ -1304,6 +1312,23 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
1304
1312
|
if (rule.allowBlank && isBlank) {
|
|
1305
1313
|
return undefined;
|
|
1306
1314
|
}
|
|
1315
|
+
// A typed formula is validated on its RESULT once the calculator has
|
|
1316
|
+
// run (Excel enters `=5` into a whole-number cell and checks the 5) —
|
|
1317
|
+
// its text can never be decided here, so it stays flag-only.
|
|
1318
|
+
if (isFormulaEntry(value)) {
|
|
1319
|
+
return undefined;
|
|
1320
|
+
}
|
|
1321
|
+
// Excel's Whole number / Time / Text length kinds (authored or imported
|
|
1322
|
+
// with `xlsxSource`) are decided synchronously from the typed text when
|
|
1323
|
+
// their bounds are literals — Excel blocks a decimal in a whole-number
|
|
1324
|
+
// cell at entry, not after a recalc.
|
|
1325
|
+
const excelKindVerdict = checkExcelValidationValue(rule, value);
|
|
1326
|
+
if (excelKindVerdict !== undefined) {
|
|
1327
|
+
const excelDecision = decideValidationCommit(alert, excelKindVerdict);
|
|
1328
|
+
return excelDecision === "proceed"
|
|
1329
|
+
? undefined
|
|
1330
|
+
: { decision: excelDecision, alert };
|
|
1331
|
+
}
|
|
1307
1332
|
if (isDataValidationFormulaRule(rule)) {
|
|
1308
1333
|
// Enforce synchronously only where `checkBooleanRule` can decide the typed
|
|
1309
1334
|
// value without the calculator: CUSTOM_FORMULA's sync branch is a stub, the
|
|
@@ -1841,28 +1866,17 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
1841
1866
|
* shown in tooltip
|
|
1842
1867
|
*/
|
|
1843
1868
|
/**
|
|
1844
|
-
* Compose host tooltip content with the data-validation
|
|
1845
|
-
*
|
|
1846
|
-
*
|
|
1847
|
-
*
|
|
1869
|
+
* Compose host tooltip content with the data-validation messages. Host-
|
|
1870
|
+
* provided content wins; otherwise the rule's input message (Excel's "show
|
|
1871
|
+
* input message when cell is selected") or, on an Invalid cell, the rule's
|
|
1872
|
+
* custom error alert text — see `getDataValidationTooltipContent`.
|
|
1848
1873
|
*/
|
|
1849
1874
|
const getTooltipContentWithValidation = useCallback((tooltipSheetId, rowIndex, columnIndex) => {
|
|
1850
1875
|
const hostContent = getTooltipContent?.(tooltipSheetId, rowIndex, columnIndex);
|
|
1851
1876
|
if (hostContent != null) {
|
|
1852
1877
|
return hostContent;
|
|
1853
1878
|
}
|
|
1854
|
-
|
|
1855
|
-
if (error?.type === "Error" || error?.type === "Invalid") {
|
|
1856
|
-
return undefined;
|
|
1857
|
-
}
|
|
1858
|
-
const rule = getDataValidationRule(tooltipSheetId, rowIndex, columnIndex);
|
|
1859
|
-
const inputMessage = rule?.inputMessage;
|
|
1860
|
-
if (!inputMessage || (!inputMessage.title && !inputMessage.message)) {
|
|
1861
|
-
return undefined;
|
|
1862
|
-
}
|
|
1863
|
-
return (React.createElement("div", { className: "bg-rnc-background text-rnc-foreground p-2 shadow-md rounded-md border-l-4 border-solid border-l-blue-700 max-w-[300px] flex flex-col gap-0.5" },
|
|
1864
|
-
inputMessage.title ? (React.createElement("div", { className: "font-bold font-system text-sm" }, inputMessage.title)) : null,
|
|
1865
|
-
inputMessage.message ? (React.createElement("div", { className: "text-xs font-system whitespace-pre-wrap" }, inputMessage.message)) : null));
|
|
1879
|
+
return getDataValidationTooltipContent(getDataValidationRule(tooltipSheetId, rowIndex, columnIndex), getErrorValue(tooltipSheetId, rowIndex, columnIndex));
|
|
1866
1880
|
}, [getTooltipContent, getErrorValue, getDataValidationRule]);
|
|
1867
1881
|
const getTooltip = useGetTooltip({
|
|
1868
1882
|
sheetId,
|
|
@@ -1887,10 +1901,151 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
1887
1901
|
const dataRegionBoundaries = useMemo(() => tables
|
|
1888
1902
|
?.filter((table) => table.sheetId === sheetId)
|
|
1889
1903
|
.map((table) => table.range), [tables, sheetId]);
|
|
1904
|
+
/**
|
|
1905
|
+
* True when a source cell of a fill is date-formatted — the fill menu then
|
|
1906
|
+
* adds Fill Days / Weekdays / Months / Years (Excel shows them only for
|
|
1907
|
+
* date sources). Reads the cell's own format first, then the effective
|
|
1908
|
+
* (style-plane) format so rnc-backed cells count too.
|
|
1909
|
+
*/
|
|
1910
|
+
const sourceHasDates = useCallback((fillSheetId, sources) => {
|
|
1911
|
+
let visited = 0;
|
|
1912
|
+
for (const { range } of sources) {
|
|
1913
|
+
for (let r = range.startRowIndex; r <= range.endRowIndex; r++) {
|
|
1914
|
+
for (let c = range.startColumnIndex; c <= range.endColumnIndex; c++) {
|
|
1915
|
+
// Bounded scan: a whole-column source would otherwise cost a full walk.
|
|
1916
|
+
if (++visited > 256)
|
|
1917
|
+
return false;
|
|
1918
|
+
const uf = getCellData?.(fillSheetId, r, c)?.userEnteredFormat;
|
|
1919
|
+
const type = (uf && "numberFormat" in uf ? uf.numberFormat?.type : undefined) ??
|
|
1920
|
+
getEffectiveFormat?.(fillSheetId, r, c)?.numberFormat?.type;
|
|
1921
|
+
if (type === "DATE" || type === "DATE_TIME")
|
|
1922
|
+
return true;
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
return false;
|
|
1927
|
+
}, [getCellData, getEffectiveFormat]);
|
|
1928
|
+
/**
|
|
1929
|
+
* A fill-handle drag ended: park the gesture so the Auto Fill Options smart
|
|
1930
|
+
* tag (left drag — already filled) or the right-drag fill menu (nothing
|
|
1931
|
+
* filled yet) can re-choose the fill type.
|
|
1932
|
+
*/
|
|
1933
|
+
const handleFillHandleRelease = useCallback((release) => {
|
|
1934
|
+
if (readonly)
|
|
1935
|
+
return;
|
|
1936
|
+
setFillOptions({
|
|
1937
|
+
sheetId: release.sheetId,
|
|
1938
|
+
activeCell: release.activeCell,
|
|
1939
|
+
fillSelection: release.fillSelection,
|
|
1940
|
+
selections: release.selections,
|
|
1941
|
+
fillType: undefined,
|
|
1942
|
+
hasDates: sourceHasDates(release.sheetId, release.selections.length
|
|
1943
|
+
? release.selections
|
|
1944
|
+
: [{ range: cellToArea(release.activeCell) }]),
|
|
1945
|
+
mode: release.button === "right" ? "menu" : "smart-tag",
|
|
1946
|
+
});
|
|
1947
|
+
}, [readonly, setFillOptions, sourceHasDates]);
|
|
1948
|
+
/**
|
|
1949
|
+
* An entry of the fill menu was picked: re-issue the fill from the (still
|
|
1950
|
+
* intact) source with the explicit type. The target is simply overwritten
|
|
1951
|
+
* with the new result — no undo round-trip needed because the source
|
|
1952
|
+
* selection is never touched by a fill.
|
|
1953
|
+
*/
|
|
1954
|
+
const handleChooseFillType = useCallback((fillType) => {
|
|
1955
|
+
if (!fillOptions)
|
|
1956
|
+
return;
|
|
1957
|
+
onFill?.(fillOptions.sheetId, fillOptions.activeCell, fillOptions.fillSelection, fillOptions.selections, undefined, fillType);
|
|
1958
|
+
setFillOptions({ ...fillOptions, fillType, mode: "smart-tag" });
|
|
1959
|
+
focusSheet();
|
|
1960
|
+
}, [fillOptions, onFill, setFillOptions, focusSheet]);
|
|
1961
|
+
const handleCloseFillOptions = useCallback(() => {
|
|
1962
|
+
// Only the right-drag menu is "cancel on close"; the smart tag stays.
|
|
1963
|
+
if (fillOptions?.mode === "menu")
|
|
1964
|
+
setFillOptions(null);
|
|
1965
|
+
}, [fillOptions, setFillOptions]);
|
|
1966
|
+
/**
|
|
1967
|
+
* Run Excel's Series dialog result: the target range's first row (Series
|
|
1968
|
+
* in Columns) / first column (Rows) is the seed line; `stop` may shrink or
|
|
1969
|
+
* extend the target along the axis from the seed's last value.
|
|
1970
|
+
*/
|
|
1971
|
+
const applyFillSeriesSpec = useCallback((fillSheetId, cell, target, spec) => {
|
|
1972
|
+
const seed = seedRangeForSeriesSpec(target.range, spec);
|
|
1973
|
+
const fillRange = fillRangeForSeriesSpec({
|
|
1974
|
+
target: target.range,
|
|
1975
|
+
seed,
|
|
1976
|
+
spec,
|
|
1977
|
+
getSeedValue: (r, c) => {
|
|
1978
|
+
const value = getEffectiveValue(fillSheetId, r, c);
|
|
1979
|
+
return typeof value === "number" ? value : undefined;
|
|
1980
|
+
},
|
|
1981
|
+
rowCount,
|
|
1982
|
+
columnCount,
|
|
1983
|
+
});
|
|
1984
|
+
if (!fillRange)
|
|
1985
|
+
return;
|
|
1986
|
+
const fillType = spec.type === "linear"
|
|
1987
|
+
? spec.trend
|
|
1988
|
+
? "LinearTrend"
|
|
1989
|
+
: "FillSeries"
|
|
1990
|
+
: spec.type === "growth"
|
|
1991
|
+
? "GrowthTrend"
|
|
1992
|
+
: spec.type === "date"
|
|
1993
|
+
? spec.dateUnit === "weekday"
|
|
1994
|
+
? "FillWeekdays"
|
|
1995
|
+
: spec.dateUnit === "month"
|
|
1996
|
+
? "FillMonths"
|
|
1997
|
+
: spec.dateUnit === "year"
|
|
1998
|
+
? "FillYears"
|
|
1999
|
+
: "FillDays"
|
|
2000
|
+
: undefined;
|
|
2001
|
+
onFill?.(fillSheetId, cell, { range: fillRange }, [{ ...target, range: seed }], undefined, fillType, { series: spec });
|
|
2002
|
+
onChangeSelections?.(fillSheetId, [{ ...target, range: fillRange }]);
|
|
2003
|
+
}, [getEffectiveValue, onFill, onChangeSelections, rowCount, columnCount]);
|
|
2004
|
+
/** Open the Series dialog for a range (the current selection by default). */
|
|
2005
|
+
const openFillSeriesDialogFor = useCallback((target, initialIn) => {
|
|
2006
|
+
const selection = target ??
|
|
2007
|
+
selections[selections.length - 1] ??
|
|
2008
|
+
{ range: cellToArea(activeCell) };
|
|
2009
|
+
openFillSeriesDialog({
|
|
2010
|
+
sheetId,
|
|
2011
|
+
activeCell,
|
|
2012
|
+
selection,
|
|
2013
|
+
initialIn,
|
|
2014
|
+
onApply: (spec) => applyFillSeriesSpec(sheetId, activeCell, selection, spec),
|
|
2015
|
+
});
|
|
2016
|
+
}, [selections, activeCell, sheetId, openFillSeriesDialog, applyFillSeriesSpec]);
|
|
2017
|
+
/** "Series…" on the right-drag fill menu: the drag's target is the range, its axis the default. */
|
|
2018
|
+
const handleOpenFillSeriesDialog = useCallback(() => {
|
|
2019
|
+
if (!fillOptions)
|
|
2020
|
+
return;
|
|
2021
|
+
const { range } = fillOptions.fillSelection;
|
|
2022
|
+
const source = fillOptions.selections[0]?.range;
|
|
2023
|
+
const initialIn = source &&
|
|
2024
|
+
(range.endRowIndex > source.endRowIndex ||
|
|
2025
|
+
range.startRowIndex < source.startRowIndex)
|
|
2026
|
+
? "columns"
|
|
2027
|
+
: "rows";
|
|
2028
|
+
setFillOptions(null);
|
|
2029
|
+
openFillSeriesDialogFor({ range }, initialIn);
|
|
2030
|
+
}, [fillOptions, setFillOptions, openFillSeriesDialogFor]);
|
|
2031
|
+
// The smart tag belongs to one fill; moving on (a new active cell) drops it.
|
|
2032
|
+
// Keyed on the cell's coordinates, not the object — a re-created `activeCell`
|
|
2033
|
+
// with the same coordinates must not dismiss it.
|
|
2034
|
+
useEffect(() => {
|
|
2035
|
+
setFillOptions(null);
|
|
2036
|
+
}, [activeCell.rowIndex, activeCell.columnIndex, sheetId, setFillOptions]);
|
|
2037
|
+
/**
|
|
2038
|
+
* Fill handle dragged BACK inside the selection (Excel): the dragged-over cells lose their
|
|
2039
|
+
* contents — formats stay unless Ctrl/Cmd was held — through the same `onDelete` path as the
|
|
2040
|
+
* Delete key, so both engines (legacy `useOnDelete`, rnc `delete-cells`) clear identically.
|
|
2041
|
+
*/
|
|
2042
|
+
const handleFillShrink = useCallback((sheetId, activeCell, clearRange, options) => {
|
|
2043
|
+
onDelete?.(sheetId, activeCell, [{ range: clearRange }], options?.modifier === "toggle" ? "all" : "contents");
|
|
2044
|
+
}, [onDelete]);
|
|
1890
2045
|
/**
|
|
1891
2046
|
* Handle grid selections
|
|
1892
2047
|
*/
|
|
1893
|
-
const { onMouseDown: onMouseDownSelection, onPointerDown: onPointerDownSelection, onKeyDown: onKeyDownSelection, fillSelection, onFillHandleMouseDown, onFillHandleDoubleClick, isDragging, isFilling, isSelectionInProgress, draggedSelection, onSelectionMouseDown, setActiveCell, initialDraggedSelection, updateSelectionStartEndReference, selectColumn, getContentfulGridRangeAroundCell, newSelection, modifySelection, clearSelections, } = useSelection({
|
|
2048
|
+
const { onMouseDown: onMouseDownSelection, onPointerDown: onPointerDownSelection, onKeyDown: onKeyDownSelection, fillSelection, fillShrink, onFillHandleMouseDown, onFillHandleDoubleClick, isDragging, isFilling, isSelectionInProgress, draggedSelection, onSelectionMouseDown, setActiveCell, initialDraggedSelection, updateSelectionStartEndReference, selectColumn, getContentfulGridRangeAroundCell, newSelection, modifySelection, clearSelections, } = useSelection({
|
|
1894
2049
|
sheetId,
|
|
1895
2050
|
getDataRowCount,
|
|
1896
2051
|
enableDataBoundaryNavigation,
|
|
@@ -1918,6 +2073,8 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
1918
2073
|
scrollToCell,
|
|
1919
2074
|
isMergedCell,
|
|
1920
2075
|
onFill,
|
|
2076
|
+
onFillHandleRelease: handleFillHandleRelease,
|
|
2077
|
+
onFillShrink: handleFillShrink,
|
|
1921
2078
|
onMoveSelection,
|
|
1922
2079
|
isHiddenColumn,
|
|
1923
2080
|
isHiddenRow,
|
|
@@ -1991,6 +2148,19 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
1991
2148
|
getSheetName,
|
|
1992
2149
|
onRequestCalculate,
|
|
1993
2150
|
]);
|
|
2151
|
+
/**
|
|
2152
|
+
* Watch Window: "Add to Watch Window" is offered only while a
|
|
2153
|
+
* `WatchWindowHost` is mounted; the live getters are published below once
|
|
2154
|
+
* `navigateToSheetRange` exists.
|
|
2155
|
+
*/
|
|
2156
|
+
const addWatch = useAddWatch();
|
|
2157
|
+
const isWatchWindowMounted = useIsWatchWindowMounted();
|
|
2158
|
+
const setWatchWindowContext = useSetWatchWindowContext();
|
|
2159
|
+
const requestAddWatch = useMemo(() => {
|
|
2160
|
+
if (!isWatchWindowMounted)
|
|
2161
|
+
return undefined;
|
|
2162
|
+
return (watchSheetId, cell) => addWatch({ sheetId: watchSheetId, ...cell });
|
|
2163
|
+
}, [isWatchWindowMounted, addWatch]);
|
|
1994
2164
|
/**
|
|
1995
2165
|
* Go To (Ctrl+G / F5). A host `onRequestGoTo` wins; otherwise the built-in
|
|
1996
2166
|
* dialog opens — but only while a `GoToDialogHost` is mounted, so a host
|
|
@@ -2077,6 +2247,8 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
2077
2247
|
onChange,
|
|
2078
2248
|
getCommitValidation,
|
|
2079
2249
|
showValidationAlert,
|
|
2250
|
+
selections,
|
|
2251
|
+
onChangeBatch,
|
|
2080
2252
|
});
|
|
2081
2253
|
/**
|
|
2082
2254
|
* User cancels editing the cell
|
|
@@ -2165,7 +2337,7 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
2165
2337
|
* Get context Menu component
|
|
2166
2338
|
*/
|
|
2167
2339
|
const getContextMenu = useCallback((cell) => {
|
|
2168
|
-
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, 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, onChange: onChange, getCellData: getCellData, onAddQuickEdit: onAddQuickEdit, enableMagicFill: enableMagicFill }));
|
|
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 }));
|
|
2169
2341
|
}, [
|
|
2170
2342
|
isRestricted,
|
|
2171
2343
|
activeCell,
|
|
@@ -2233,6 +2405,9 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
2233
2405
|
enableMagicFill,
|
|
2234
2406
|
onSplitTextToColumns,
|
|
2235
2407
|
onRemoveDuplicates,
|
|
2408
|
+
onGoalSeek,
|
|
2409
|
+
onSubtotal,
|
|
2410
|
+
onAdvancedFilter,
|
|
2236
2411
|
onChange,
|
|
2237
2412
|
getCellData,
|
|
2238
2413
|
onRequestDeletePivotTable,
|
|
@@ -2696,6 +2871,8 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
2696
2871
|
hideCellPopover();
|
|
2697
2872
|
// Hide paste mnenu
|
|
2698
2873
|
setShowPasteMenu(false);
|
|
2874
|
+
// Hide the Auto Fill Options smart tag (its own mousedown never reaches here)
|
|
2875
|
+
setFillOptions(null);
|
|
2699
2876
|
// Remove pinned tooltip
|
|
2700
2877
|
onUnpinTooltip();
|
|
2701
2878
|
}, [
|
|
@@ -2707,6 +2884,7 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
2707
2884
|
setFormulaState,
|
|
2708
2885
|
hideCellPopover,
|
|
2709
2886
|
setShowPasteMenu,
|
|
2887
|
+
setFillOptions,
|
|
2710
2888
|
onUnpinTooltip,
|
|
2711
2889
|
focusSheet,
|
|
2712
2890
|
]);
|
|
@@ -2958,9 +3136,12 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
2958
3136
|
/**
|
|
2959
3137
|
* Selection Renderer
|
|
2960
3138
|
*/
|
|
3139
|
+
// The drag-back preview reuses the fill overlay geometry but greys the cells about to be cleared.
|
|
3140
|
+
const fillShrinkOverlay = useMemo(() => (fillShrink ? { range: fillShrink.clearRange } : undefined), [fillShrink]);
|
|
2961
3141
|
const selectionRenderer = useSelectionRenderer({
|
|
2962
3142
|
sheetId,
|
|
2963
3143
|
scale,
|
|
3144
|
+
isFillShrink: fillShrink !== undefined,
|
|
2964
3145
|
onSelectionMouseDown: onSelectionElementMouseDown,
|
|
2965
3146
|
onMouseDownResizeHandle: onMouseDownResizeHandle,
|
|
2966
3147
|
onMouseDownMoveSelection: onMouseDownMoveSelection,
|
|
@@ -2989,6 +3170,10 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
2989
3170
|
readonly,
|
|
2990
3171
|
onSplitTextToColumns,
|
|
2991
3172
|
showPasteMenu,
|
|
3173
|
+
fillOptions,
|
|
3174
|
+
onChooseFillType: handleChooseFillType,
|
|
3175
|
+
onOpenFillSeriesDialog: handleOpenFillSeriesDialog,
|
|
3176
|
+
onCloseFillOptions: handleCloseFillOptions,
|
|
2992
3177
|
hoveredCell: delayedHoveredCell,
|
|
2993
3178
|
onRemoveQuickEdit,
|
|
2994
3179
|
onAddQuickEdit,
|
|
@@ -3062,9 +3247,19 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
3062
3247
|
setActiveCell,
|
|
3063
3248
|
flash,
|
|
3064
3249
|
});
|
|
3065
|
-
// Built-in Go To: resolve against the workbook, then select + scroll.
|
|
3250
|
+
// Built-in Go To: resolve against the workbook, then select + scroll. Go
|
|
3251
|
+
// To Special scans the current selection (the whole sheet for a single
|
|
3252
|
+
// cell) through the host's `getCellData`.
|
|
3066
3253
|
useIsomorphicLayoutEffect(() => {
|
|
3067
|
-
builtInGoToRef.current = (goToSheetId, goToActiveCell) => {
|
|
3254
|
+
builtInGoToRef.current = (goToSheetId, goToActiveCell, goToSelections) => {
|
|
3255
|
+
const scanRange = goToSelections?.length && goToSelections[0]
|
|
3256
|
+
? goToSelections[0].range
|
|
3257
|
+
: {
|
|
3258
|
+
startRowIndex: 1,
|
|
3259
|
+
endRowIndex: Math.max(1, sheetRowCount - 1),
|
|
3260
|
+
startColumnIndex: 1,
|
|
3261
|
+
endColumnIndex: Math.max(1, sheetColumnCount - 1),
|
|
3262
|
+
};
|
|
3068
3263
|
openGoToDialog({
|
|
3069
3264
|
sheetId: goToSheetId,
|
|
3070
3265
|
activeCell: goToActiveCell,
|
|
@@ -3077,9 +3272,52 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
3077
3272
|
navigateToSheetRange(range, { enableFlash: false });
|
|
3078
3273
|
focusSheet();
|
|
3079
3274
|
},
|
|
3275
|
+
special: getCellData
|
|
3276
|
+
? {
|
|
3277
|
+
resolve: (kind) => resolveGoToSpecial(kind, {
|
|
3278
|
+
sheetId: goToSheetId,
|
|
3279
|
+
range: scanRange,
|
|
3280
|
+
getCellData,
|
|
3281
|
+
isRowHidden: isHiddenRow,
|
|
3282
|
+
isColumnHidden: isHiddenColumn,
|
|
3283
|
+
}),
|
|
3284
|
+
onSelectRanges: (ranges) => {
|
|
3285
|
+
const first = ranges[0];
|
|
3286
|
+
if (!first)
|
|
3287
|
+
return;
|
|
3288
|
+
setActiveCell(goToSheetId, {
|
|
3289
|
+
rowIndex: first.startRowIndex,
|
|
3290
|
+
columnIndex: first.startColumnIndex,
|
|
3291
|
+
});
|
|
3292
|
+
onChangeSelections?.(goToSheetId, ranges.map((range) => ({ range })));
|
|
3293
|
+
focusSheet();
|
|
3294
|
+
},
|
|
3295
|
+
}
|
|
3296
|
+
: undefined,
|
|
3080
3297
|
});
|
|
3081
3298
|
};
|
|
3082
3299
|
});
|
|
3300
|
+
// Watch Window live getters — republished per render while a host is
|
|
3301
|
+
// mounted so the panel tracks recalculation.
|
|
3302
|
+
useIsomorphicLayoutEffect(() => {
|
|
3303
|
+
if (!isWatchWindowMounted)
|
|
3304
|
+
return;
|
|
3305
|
+
setWatchWindowContext({
|
|
3306
|
+
getSheetName,
|
|
3307
|
+
getFormattedValue,
|
|
3308
|
+
getFormula: getFormulaValue,
|
|
3309
|
+
onNavigate: (cell) => {
|
|
3310
|
+
navigateToSheetRange({
|
|
3311
|
+
sheetId: cell.sheetId,
|
|
3312
|
+
startRowIndex: cell.rowIndex,
|
|
3313
|
+
endRowIndex: cell.rowIndex,
|
|
3314
|
+
startColumnIndex: cell.columnIndex,
|
|
3315
|
+
endColumnIndex: cell.columnIndex,
|
|
3316
|
+
}, { enableFlash: false });
|
|
3317
|
+
focusSheet();
|
|
3318
|
+
},
|
|
3319
|
+
});
|
|
3320
|
+
});
|
|
3083
3321
|
// Dispatch keyboard event
|
|
3084
3322
|
const dispatchEvent = useCallback((event) => {
|
|
3085
3323
|
gridRef.current?.container?.dispatchEvent(event);
|
|
@@ -3246,12 +3484,14 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
3246
3484
|
});
|
|
3247
3485
|
// props reference for spreadsheet api
|
|
3248
3486
|
propsReferenceRef.current = props;
|
|
3487
|
+
const openFillSeriesDialogForRef = useStableRef(openFillSeriesDialogFor);
|
|
3249
3488
|
// Expose a spreadsheet API
|
|
3250
3489
|
useIsomorphicLayoutEffect(() => {
|
|
3251
3490
|
const stableMethods = {
|
|
3252
3491
|
getUserEnteredValue: getUserEnteredStringValueStable,
|
|
3253
3492
|
scrollToCell,
|
|
3254
3493
|
commit,
|
|
3494
|
+
openFillSeriesDialog: () => openFillSeriesDialogForRef.current?.(),
|
|
3255
3495
|
};
|
|
3256
3496
|
setSpreadsheetApi(new SpreadsheetApi(propsReferenceRef, stableMethods, store, instanceStore, instanceId));
|
|
3257
3497
|
}, []);
|
|
@@ -3333,7 +3573,7 @@ function CanvasGridComponent(props, forwardedRef) {
|
|
|
3333
3573
|
width === 0 || height === 0 ? (React.createElement("div", { className: "flex border-solid border-rnc-border border border-t border-b flex-1 justify-center items-center" },
|
|
3334
3574
|
React.createElement("div", { className: "space-y-2" },
|
|
3335
3575
|
React.createElement(Skeleton, { className: "h-4 w-[250px]" }),
|
|
3336
|
-
React.createElement(Skeleton, { className: "h-4 w-[250px]" })))) : (React.createElement(BaseGrid, { ref: gridRef, overscanCount: overscanCount, rowCount: sheetRowCount, columnCount: sheetColumnCount, rowHeight: rowHeight, columnWidth: columnWidth, itemRenderer: cellRenderer, headerRenderer: headerCellRenderer, selectionRenderer: selectionRenderer, gridLineColor: gridLineColor, gridLineWidth: gridLineWidth, borderStyles: finalBorderStyles, mergedCells: merges, scale: scale, width: width, height: height, frozenColumns: frozenColumns, frozenRows: frozenRows, activeCell: activeCell, selections: formulaMode ? formulaSelections : selections, FillHandle: FillHandle, showFillHandle: showFillHandle, fillHandleSize: fillHandleSize, showGridLines: showGridLines, enableCellOverlay: true, enableCellBackground: true, enableSelectionDrag: enableSelectionDrag, showFrozenColumnShadow: showFrozenSeparator, showFrozenRowShadow: showFrozenSeparator, selectionBorderColor: selectionBorderColor, selectionBackgroundColor: selectionBackgroundColor, fillhandleBorderColor: cellBackgroundColor, isDraggingSelection: isDragging, fillSelection: fillSelection, onPointerDown: handlePointerDown, onPointerUp: handlePointerUp, onMouseDown: handleMouseDown, onDoubleClick: handleDoubleClick, onFillHandleMouseDown: onFillHandleMouseDown, onFillHandleDoubleClick: onFillHandleDoubleClick,
|
|
3576
|
+
React.createElement(Skeleton, { className: "h-4 w-[250px]" })))) : (React.createElement(BaseGrid, { ref: gridRef, overscanCount: overscanCount, rowCount: sheetRowCount, columnCount: sheetColumnCount, rowHeight: rowHeight, columnWidth: columnWidth, itemRenderer: cellRenderer, headerRenderer: headerCellRenderer, selectionRenderer: selectionRenderer, gridLineColor: gridLineColor, gridLineWidth: gridLineWidth, borderStyles: finalBorderStyles, mergedCells: merges, scale: scale, width: width, height: height, frozenColumns: frozenColumns, frozenRows: frozenRows, activeCell: activeCell, selections: formulaMode ? formulaSelections : selections, FillHandle: FillHandle, showFillHandle: showFillHandle, fillHandleSize: fillHandleSize, showGridLines: showGridLines, enableCellOverlay: true, enableCellBackground: true, enableSelectionDrag: enableSelectionDrag, showFrozenColumnShadow: showFrozenSeparator, showFrozenRowShadow: showFrozenSeparator, selectionBorderColor: selectionBorderColor, selectionBackgroundColor: selectionBackgroundColor, fillhandleBorderColor: cellBackgroundColor, isDraggingSelection: isDragging, fillSelection: fillShrinkOverlay ?? fillSelection, onPointerDown: handlePointerDown, onPointerUp: handlePointerUp, onMouseDown: handleMouseDown, onDoubleClick: handleDoubleClick, onFillHandleMouseDown: onFillHandleMouseDown, onFillHandleDoubleClick: onFillHandleDoubleClick,
|
|
3337
3577
|
// Dimension of fill handle
|
|
3338
3578
|
scrollToCellOffset: 4, scrollbarSize: scrollbarSize, isHiddenCell: isHiddenCell, isHiddenColumn: isHiddenColumn, isHiddenRow: isHiddenRow, visibleRowRanges: visibleRowRanges, isHiddenOverlay: isHiddenOverlay, isHiddenBackground: isHiddenBackground, overlayRenderer: cellOverlayRenderer, backgroundRenderer: cellBackgroundRenderer, shadowSettings: shadowSettings, onScroll: handleScroll, onViewPortChange: handleViewPortChange, autoFocus: autoFocus, snap: scrollSnap, scrollThrottleTimeout: scrollThrottleTimeout, preventBrowserDefaultScroll: preventBrowserDefaultScroll, showHeaders: showHeaders, gridChildren: gridChildren, onTouchStart: onTouchStart, onDimensionsChange: onDimensionsChange, extendScrollSize: isTouchDevice || isFirefox, isTouchDevice: isTouchDevice, frozenShadowThickness: frozenShadowThickness, onAfterScrollToCell: onAfterScrollToCell, estimatedRowHeight: defaultRowHeight, estimatedColumnWidth: defaultColumnWidth, footerHeight: footerHeight, footerComponent: footerComponent, getOverflowBuffer: getOverflowBuffer, getFrozenColumnOverflowCells: getFrozenColumnOverflowCells })),
|
|
3339
3579
|
tooltipComponent,
|
|
@@ -13,8 +13,8 @@ import type { useFlash } from "../../hooks/use-flash";
|
|
|
13
13
|
import type { useNavigateToSheetRange } from "../../hooks/use-navigate-sheet-range";
|
|
14
14
|
import type { UseSelectionOptions } from "../../hooks/use-selection";
|
|
15
15
|
import type { GetCellDimensionsOptions as SizerGetCellDimensionsOptions, useSizer } from "../../hooks/use-sizer";
|
|
16
|
-
import type { AgentSuggestion, BandedDefinition, BandedRange, BorderStyle, CellFormat, Collaborator, Color, ColorFilterCriteria, ConditionType, ConditionValue, DataValidationRule, DataValidationRuleRecord, EmbeddedObject, IconFilterCriteria, Maybe, NamedRange, ParsedToken, PivotTable, ProtectedRange, RemoveDuplicatesOptions, Sheet, SheetCoordinate, SheetProtection, SheetRange, Slicer, SortOrder, SortSpecs, TableTheme, TableView } from "../../types";
|
|
17
|
-
import type { AXIS, CellData, ConditionalFormatRule, EmbeddedChart, FilterView } from "../../types";
|
|
16
|
+
import type { AgentSuggestion, BandedDefinition, BandedRange, BorderStyle, CellFormat, Collaborator, Color, ColorFilterCriteria, ConditionType, ConditionValue, DataValidationRule, DataValidationRuleRecord, EmbeddedObject, IconFilterCriteria, Maybe, NamedRange, ParsedToken, PivotTable, ProtectedRange, RemoveDuplicatesOptions, AdvancedFilterOptions, AdvancedFilterResult, GoalSeekResult, SplitTextOptions, SubtotalOptions, SubtotalResult, Sheet, SheetCoordinate, SheetProtection, SheetRange, Slicer, SortOrder, SortSpecs, TableTheme, TableView } from "../../types";
|
|
17
|
+
import type { AXIS, AutoFillType, CellData, ConditionalFormatRule, EmbeddedChart, FillOptions, FilterView } from "../../types";
|
|
18
18
|
import type { CellProps } from "../cell/typings";
|
|
19
19
|
import type { CellEditorProps } from "../cell-editor";
|
|
20
20
|
import type { StructuredResultProps } from "../cell-structured/types";
|
|
@@ -670,8 +670,11 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
|
|
|
670
670
|
* @param sheetId
|
|
671
671
|
* @param cell
|
|
672
672
|
* @param selections
|
|
673
|
+
* @param clearType what to clear — `"contents"` (default; values/formulas, formats kept),
|
|
674
|
+
* `"formats"`, or `"all"`. A fill-handle drag-back inside the selection clears `"contents"`
|
|
675
|
+
* (`"all"` with Ctrl), matching Excel.
|
|
673
676
|
*/
|
|
674
|
-
onDelete?(sheetId: number, cell: CellInterface, selections: SelectionArea<SelectionAttributes>[]): void;
|
|
677
|
+
onDelete?(sheetId: number, cell: CellInterface, selections: SelectionArea<SelectionAttributes>[], clearType?: "all" | "contents" | "formats"): void;
|
|
675
678
|
/**
|
|
676
679
|
* When user changes editor value
|
|
677
680
|
* @param value
|
|
@@ -697,8 +700,14 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
|
|
|
697
700
|
* Fill
|
|
698
701
|
* @param cell
|
|
699
702
|
* @param selections
|
|
703
|
+
* @param fillableSelections Optional pre-drag selections (used for undo
|
|
704
|
+
* bookkeeping by the state layer); the grid passes `undefined`.
|
|
705
|
+
* @param fillType Explicit fill type — from the Auto Fill Options / right-drag
|
|
706
|
+
* menu. Omitted for a plain drag (the engine auto-detects).
|
|
707
|
+
* @param options Modifier held on the handle (`{ modifier: "toggle" }` for
|
|
708
|
+
* Ctrl/Cmd+drag) and/or the Series dialog's parameters.
|
|
700
709
|
*/
|
|
701
|
-
onFill?(sheetId: number, cell: CellInterface, fillSelection: SelectionArea<SelectionAttributes>, selections: SelectionArea<SelectionAttributes>[]): void;
|
|
710
|
+
onFill?(sheetId: number, cell: CellInterface, fillSelection: SelectionArea<SelectionAttributes>, selections: SelectionArea<SelectionAttributes>[], fillableSelections?: SelectionArea<SelectionAttributes>[], fillType?: AutoFillType, options?: FillOptions): void;
|
|
702
711
|
/**
|
|
703
712
|
* Callback when user moves a selection
|
|
704
713
|
* @param from
|
|
@@ -1527,7 +1536,7 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
|
|
|
1527
1536
|
* @param delimiter
|
|
1528
1537
|
* @returns
|
|
1529
1538
|
*/
|
|
1530
|
-
onSplitTextToColumns?: (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[], delimiter?: string) => void;
|
|
1539
|
+
onSplitTextToColumns?: (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[], delimiter?: string, options?: SplitTextOptions) => void;
|
|
1531
1540
|
/**
|
|
1532
1541
|
* Remove duplicate rows
|
|
1533
1542
|
* @param sheetId
|
|
@@ -1536,6 +1545,23 @@ export type CanvasGridProps<T extends CellData = CellData<any, any>> = {
|
|
|
1536
1545
|
* @returns
|
|
1537
1546
|
*/
|
|
1538
1547
|
onRemoveDuplicates?: (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[], options?: RemoveDuplicatesOptions) => void;
|
|
1548
|
+
/**
|
|
1549
|
+
* Excel's Goal Seek: find the `changingCell` value that makes the formula in
|
|
1550
|
+
* `setCell` evaluate to `targetValue`, then commit it. Resolves to the
|
|
1551
|
+
* search result (status + value), or `undefined` when the engine reports
|
|
1552
|
+
* no result (the rnc engine iterates natively) or the set cell has no formula.
|
|
1553
|
+
*/
|
|
1554
|
+
onGoalSeek?: (sheetId: number, setCell: CellInterface, targetValue: number, changingCell: CellInterface) => Promise<GoalSeekResult | undefined>;
|
|
1555
|
+
/**
|
|
1556
|
+
* Excel's Data → Subtotal: insert "<group> Total" / "Grand Total" rows with
|
|
1557
|
+
* `SUBTOTAL(...)` formulas and outline the groups.
|
|
1558
|
+
*/
|
|
1559
|
+
onSubtotal?: (sheetId: number, options: SubtotalOptions) => SubtotalResult | undefined;
|
|
1560
|
+
/**
|
|
1561
|
+
* Excel's Data → Advanced filter: filter a list in place (hide non-matching
|
|
1562
|
+
* rows) or copy the matching records elsewhere, driven by a criteria range.
|
|
1563
|
+
*/
|
|
1564
|
+
onAdvancedFilter?: (sheetId: number, options: AdvancedFilterOptions) => AdvancedFilterResult | undefined;
|
|
1539
1565
|
/**
|
|
1540
1566
|
* Callback to get effective value of a cell
|
|
1541
1567
|
* @param sheetId
|