@rowsncolumns/spreadsheet 10.2.68
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/LICENSE.md +100 -0
- package/Readme.md +9 -0
- package/dist/cjs/api/animate.d.ts +36 -0
- package/dist/cjs/api/animate.d.ts.map +1 -0
- package/dist/cjs/api/animate.js +123 -0
- package/dist/cjs/api/banded-ranges.d.ts +16 -0
- package/dist/cjs/api/banded-ranges.d.ts.map +1 -0
- package/dist/cjs/api/banded-ranges.js +134 -0
- package/dist/cjs/api/cf-engine.d.ts +36 -0
- package/dist/cjs/api/cf-engine.d.ts.map +1 -0
- package/dist/cjs/api/cf-engine.js +73 -0
- package/dist/cjs/api/cf-overlays.d.ts +7 -0
- package/dist/cjs/api/cf-overlays.d.ts.map +1 -0
- package/dist/cjs/api/cf-overlays.js +136 -0
- package/dist/cjs/api/cf-window.d.ts +45 -0
- package/dist/cjs/api/cf-window.d.ts.map +1 -0
- package/dist/cjs/api/cf-window.js +143 -0
- package/dist/cjs/api/colors.d.ts +8 -0
- package/dist/cjs/api/colors.d.ts.map +1 -0
- package/dist/cjs/api/colors.js +31 -0
- package/dist/cjs/api/copy-paste.d.ts +10 -0
- package/dist/cjs/api/copy-paste.d.ts.map +1 -0
- package/dist/cjs/api/copy-paste.js +28 -0
- package/dist/cjs/api/fill-patterns.d.ts +5 -0
- package/dist/cjs/api/fill-patterns.d.ts.map +1 -0
- package/dist/cjs/api/fill-patterns.js +202 -0
- package/dist/cjs/api/font-loader.d.ts +8 -0
- package/dist/cjs/api/font-loader.d.ts.map +1 -0
- package/dist/cjs/api/font-loader.js +162 -0
- package/dist/cjs/api/heatmap.d.ts +4 -0
- package/dist/cjs/api/heatmap.d.ts.map +1 -0
- package/dist/cjs/api/heatmap.js +177 -0
- package/dist/cjs/api/scheduler.d.ts +8 -0
- package/dist/cjs/api/scheduler.d.ts.map +1 -0
- package/dist/cjs/api/scheduler.js +19 -0
- package/dist/cjs/api/scroller.d.ts +134 -0
- package/dist/cjs/api/scroller.d.ts.map +1 -0
- package/dist/cjs/api/scroller.js +702 -0
- package/dist/cjs/api/selections.d.ts +111 -0
- package/dist/cjs/api/selections.d.ts.map +1 -0
- package/dist/cjs/api/selections.js +407 -0
- package/dist/cjs/api/spreadsheet-api.d.ts +271 -0
- package/dist/cjs/api/spreadsheet-api.d.ts.map +1 -0
- package/dist/cjs/api/spreadsheet-api.js +811 -0
- package/dist/cjs/api/table.d.ts +11 -0
- package/dist/cjs/api/table.d.ts.map +1 -0
- package/dist/cjs/api/table.js +17 -0
- package/dist/cjs/api/validation.d.ts +98 -0
- package/dist/cjs/api/validation.d.ts.map +1 -0
- package/dist/cjs/api/validation.js +506 -0
- package/dist/cjs/atoms/active-editor.atom.d.ts +8 -0
- package/dist/cjs/atoms/active-editor.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/active-editor.atom.js +12 -0
- package/dist/cjs/atoms/cell-input-context.atom.d.ts +15 -0
- package/dist/cjs/atoms/cell-input-context.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/cell-input-context.atom.js +24 -0
- package/dist/cjs/atoms/editing-cell.atom.d.ts +7 -0
- package/dist/cjs/atoms/editing-cell.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/editing-cell.atom.js +9 -0
- package/dist/cjs/atoms/formula-bar-editor-value.atom.d.ts +19 -0
- package/dist/cjs/atoms/formula-bar-editor-value.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/formula-bar-editor-value.atom.js +44 -0
- package/dist/cjs/atoms/formula-mode.atom.d.ts +7 -0
- package/dist/cjs/atoms/formula-mode.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/formula-mode.atom.js +11 -0
- package/dist/cjs/atoms/formula-selection-state.atom.d.ts +16 -0
- package/dist/cjs/atoms/formula-selection-state.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/formula-selection-state.atom.js +32 -0
- package/dist/cjs/atoms/formula-selections.atom.d.ts +8 -0
- package/dist/cjs/atoms/formula-selections.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/formula-selections.atom.js +9 -0
- package/dist/cjs/atoms/index.d.ts +18 -0
- package/dist/cjs/atoms/index.d.ts.map +1 -0
- package/dist/cjs/atoms/index.js +22 -0
- package/dist/cjs/atoms/loading-indicator.atom.d.ts +12 -0
- package/dist/cjs/atoms/loading-indicator.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/loading-indicator.atom.js +22 -0
- package/dist/cjs/atoms/magic-fill-state.atom.d.ts +5 -0
- package/dist/cjs/atoms/magic-fill-state.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/magic-fill-state.atom.js +12 -0
- package/dist/cjs/atoms/paste-menu.atom.d.ts +6 -0
- package/dist/cjs/atoms/paste-menu.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/paste-menu.atom.js +9 -0
- package/dist/cjs/atoms/persistent-tooltip.atom.d.ts +11 -0
- package/dist/cjs/atoms/persistent-tooltip.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/persistent-tooltip.atom.js +34 -0
- package/dist/cjs/atoms/popover.atom.d.ts +7 -0
- package/dist/cjs/atoms/popover.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/popover.atom.js +9 -0
- package/dist/cjs/atoms/range-selector.atom.d.ts +6 -0
- package/dist/cjs/atoms/range-selector.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/range-selector.atom.js +11 -0
- package/dist/cjs/atoms/selected-chart-embed.atom.d.ts +6 -0
- package/dist/cjs/atoms/selected-chart-embed.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/selected-chart-embed.atom.js +9 -0
- package/dist/cjs/atoms/sheet-context.atom.d.ts +66 -0
- package/dist/cjs/atoms/sheet-context.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/sheet-context.atom.js +142 -0
- package/dist/cjs/atoms/sheet-status-display.atom.d.ts +15 -0
- package/dist/cjs/atoms/sheet-status-display.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/sheet-status-display.atom.js +18 -0
- package/dist/cjs/atoms/show-formula-help.atom.d.ts +8 -0
- package/dist/cjs/atoms/show-formula-help.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/show-formula-help.atom.js +20 -0
- package/dist/cjs/atoms/sort-dialog.atom.d.ts +22 -0
- package/dist/cjs/atoms/sort-dialog.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/sort-dialog.atom.js +14 -0
- package/dist/cjs/atoms/spreadsheet-api.atom.d.ts +5 -0
- package/dist/cjs/atoms/spreadsheet-api.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/spreadsheet-api.atom.js +11 -0
- package/dist/cjs/atoms/validation-alert.atom.d.ts +27 -0
- package/dist/cjs/atoms/validation-alert.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/validation-alert.atom.js +23 -0
- package/dist/cjs/components/bottom-bar/index.d.ts +7 -0
- package/dist/cjs/components/bottom-bar/index.d.ts.map +1 -0
- package/dist/cjs/components/bottom-bar/index.js +11 -0
- package/dist/cjs/components/canvas-grid/helpers.d.ts +15 -0
- package/dist/cjs/components/canvas-grid/helpers.d.ts.map +1 -0
- package/dist/cjs/components/canvas-grid/helpers.js +53 -0
- package/dist/cjs/components/canvas-grid/index.d.ts +7 -0
- package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -0
- package/dist/cjs/components/canvas-grid/index.js +3413 -0
- package/dist/cjs/components/canvas-grid/typings.d.ts +2027 -0
- package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -0
- package/dist/cjs/components/canvas-grid/typings.js +9 -0
- package/dist/cjs/components/cell/alignment.d.ts +70 -0
- package/dist/cjs/components/cell/alignment.d.ts.map +1 -0
- package/dist/cjs/components/cell/alignment.js +137 -0
- package/dist/cjs/components/cell/cell-background.d.ts +15 -0
- package/dist/cjs/components/cell/cell-background.d.ts.map +1 -0
- package/dist/cjs/components/cell/cell-background.js +171 -0
- package/dist/cjs/components/cell/cell-text-runs.d.ts +98 -0
- package/dist/cjs/components/cell/cell-text-runs.d.ts.map +1 -0
- package/dist/cjs/components/cell/cell-text-runs.js +470 -0
- package/dist/cjs/components/cell/helpers.d.ts +3 -0
- package/dist/cjs/components/cell/helpers.d.ts.map +1 -0
- package/dist/cjs/components/cell/helpers.js +20 -0
- package/dist/cjs/components/cell/index.d.ts +4 -0
- package/dist/cjs/components/cell/index.d.ts.map +1 -0
- package/dist/cjs/components/cell/index.js +272 -0
- package/dist/cjs/components/cell/rich-text.d.ts +82 -0
- package/dist/cjs/components/cell/rich-text.d.ts.map +1 -0
- package/dist/cjs/components/cell/rich-text.js +211 -0
- package/dist/cjs/components/cell/typings.d.ts +190 -0
- package/dist/cjs/components/cell/typings.d.ts.map +1 -0
- package/dist/cjs/components/cell/typings.js +2 -0
- package/dist/cjs/components/cell-arrow/index.d.ts +14 -0
- package/dist/cjs/components/cell-arrow/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-arrow/index.js +28 -0
- package/dist/cjs/components/cell-calculated/index.d.ts +17 -0
- package/dist/cjs/components/cell-calculated/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-calculated/index.js +20 -0
- package/dist/cjs/components/cell-checkbox/index.d.ts +14 -0
- package/dist/cjs/components/cell-checkbox/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-checkbox/index.js +29 -0
- package/dist/cjs/components/cell-diff/index.d.ts +42 -0
- package/dist/cjs/components/cell-diff/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-diff/index.js +94 -0
- package/dist/cjs/components/cell-editor/calendar-popup.d.ts +9 -0
- package/dist/cjs/components/cell-editor/calendar-popup.d.ts.map +1 -0
- package/dist/cjs/components/cell-editor/calendar-popup.js +25 -0
- package/dist/cjs/components/cell-editor/formula-result-preview.d.ts +9 -0
- package/dist/cjs/components/cell-editor/formula-result-preview.d.ts.map +1 -0
- package/dist/cjs/components/cell-editor/formula-result-preview.js +26 -0
- package/dist/cjs/components/cell-editor/helpers.d.ts +11 -0
- package/dist/cjs/components/cell-editor/helpers.d.ts.map +1 -0
- package/dist/cjs/components/cell-editor/helpers.js +41 -0
- package/dist/cjs/components/cell-editor/helpers.spec.d.ts +2 -0
- package/dist/cjs/components/cell-editor/helpers.spec.d.ts.map +1 -0
- package/dist/cjs/components/cell-editor/helpers.spec.js +18 -0
- package/dist/cjs/components/cell-editor/index.d.ts +146 -0
- package/dist/cjs/components/cell-editor/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-editor/index.js +268 -0
- package/dist/cjs/components/cell-editor/style.d.ts +9 -0
- package/dist/cjs/components/cell-editor/style.d.ts.map +1 -0
- package/dist/cjs/components/cell-editor/style.js +31 -0
- package/dist/cjs/components/cell-error/index.d.ts +14 -0
- package/dist/cjs/components/cell-error/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-error/index.js +24 -0
- package/dist/cjs/components/cell-expand/index.d.ts +15 -0
- package/dist/cjs/components/cell-expand/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-expand/index.js +31 -0
- package/dist/cjs/components/cell-filter/index.d.ts +21 -0
- package/dist/cjs/components/cell-filter/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-filter/index.js +40 -0
- package/dist/cjs/components/cell-group/index.d.ts +17 -0
- package/dist/cjs/components/cell-group/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-group/index.js +32 -0
- package/dist/cjs/components/cell-input/cell-input.d.ts +123 -0
- package/dist/cjs/components/cell-input/cell-input.d.ts.map +1 -0
- package/dist/cjs/components/cell-input/cell-input.js +68 -0
- package/dist/cjs/components/cell-input/formula-bar-cell-input.d.ts +21 -0
- package/dist/cjs/components/cell-input/formula-bar-cell-input.d.ts.map +1 -0
- package/dist/cjs/components/cell-input/formula-bar-cell-input.js +63 -0
- package/dist/cjs/components/cell-input/index.d.ts +3 -0
- package/dist/cjs/components/cell-input/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-input/index.js +5 -0
- package/dist/cjs/components/cell-input/style.d.ts +6 -0
- package/dist/cjs/components/cell-input/style.d.ts.map +1 -0
- package/dist/cjs/components/cell-input/style.js +14 -0
- package/dist/cjs/components/cell-overlay/index.d.ts +25 -0
- package/dist/cjs/components/cell-overlay/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-overlay/index.js +161 -0
- package/dist/cjs/components/cell-structured/index.d.ts +8 -0
- package/dist/cjs/components/cell-structured/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-structured/index.js +21 -0
- package/dist/cjs/components/cell-structured/sparkline-math.d.ts +54 -0
- package/dist/cjs/components/cell-structured/sparkline-math.d.ts.map +1 -0
- package/dist/cjs/components/cell-structured/sparkline-math.js +111 -0
- package/dist/cjs/components/cell-structured/sparkline.d.ts +6 -0
- package/dist/cjs/components/cell-structured/sparkline.d.ts.map +1 -0
- package/dist/cjs/components/cell-structured/sparkline.js +256 -0
- package/dist/cjs/components/cell-structured/types.d.ts +23 -0
- package/dist/cjs/components/cell-structured/types.d.ts.map +1 -0
- package/dist/cjs/components/cell-structured/types.js +2 -0
- package/dist/cjs/components/cell-tooltip/index.d.ts +28 -0
- package/dist/cjs/components/cell-tooltip/index.d.ts.map +1 -0
- package/dist/cjs/components/cell-tooltip/index.js +55 -0
- package/dist/cjs/components/cell-tooltip/note-editor.d.ts +12 -0
- package/dist/cjs/components/cell-tooltip/note-editor.d.ts.map +1 -0
- package/dist/cjs/components/cell-tooltip/note-editor.js +26 -0
- package/dist/cjs/components/cell-tooltip/style.d.ts +3 -0
- package/dist/cjs/components/cell-tooltip/style.d.ts.map +1 -0
- package/dist/cjs/components/cell-tooltip/style.js +11 -0
- package/dist/cjs/components/context-menu/index.d.ts +80 -0
- package/dist/cjs/components/context-menu/index.d.ts.map +1 -0
- package/dist/cjs/components/context-menu/index.js +666 -0
- package/dist/cjs/components/context-menu/menu.d.ts +10 -0
- package/dist/cjs/components/context-menu/menu.d.ts.map +1 -0
- package/dist/cjs/components/context-menu/menu.js +15 -0
- package/dist/cjs/components/context-menu/style.d.ts +6 -0
- package/dist/cjs/components/context-menu/style.d.ts.map +1 -0
- package/dist/cjs/components/context-menu/style.js +16 -0
- package/dist/cjs/components/embeds/chart-component.d.ts +16 -0
- package/dist/cjs/components/embeds/chart-component.d.ts.map +1 -0
- package/dist/cjs/components/embeds/chart-component.js +12 -0
- package/dist/cjs/components/embeds/embed-component.d.ts +17 -0
- package/dist/cjs/components/embeds/embed-component.d.ts.map +1 -0
- package/dist/cjs/components/embeds/embed-component.js +128 -0
- package/dist/cjs/components/embeds/embed-draggable.d.ts +43 -0
- package/dist/cjs/components/embeds/embed-draggable.d.ts.map +1 -0
- package/dist/cjs/components/embeds/embed-draggable.js +117 -0
- package/dist/cjs/components/embeds/index.d.ts +5 -0
- package/dist/cjs/components/embeds/index.d.ts.map +1 -0
- package/dist/cjs/components/embeds/index.js +7 -0
- package/dist/cjs/components/embeds/shape-geometry.d.ts +10 -0
- package/dist/cjs/components/embeds/shape-geometry.d.ts.map +1 -0
- package/dist/cjs/components/embeds/shape-geometry.js +265 -0
- package/dist/cjs/components/embeds/shape-svg.d.ts +56 -0
- package/dist/cjs/components/embeds/shape-svg.d.ts.map +1 -0
- package/dist/cjs/components/embeds/shape-svg.js +165 -0
- package/dist/cjs/components/embeds/slicer-component.d.ts +27 -0
- package/dist/cjs/components/embeds/slicer-component.d.ts.map +1 -0
- package/dist/cjs/components/embeds/slicer-component.js +283 -0
- package/dist/cjs/components/fill-handle/index.d.ts +7 -0
- package/dist/cjs/components/fill-handle/index.d.ts.map +1 -0
- package/dist/cjs/components/fill-handle/index.js +19 -0
- package/dist/cjs/components/filter-box/filter-by-color.d.ts +28 -0
- package/dist/cjs/components/filter-box/filter-by-color.d.ts.map +1 -0
- package/dist/cjs/components/filter-box/filter-by-color.js +104 -0
- package/dist/cjs/components/filter-box/filter-by-condition.d.ts +13 -0
- package/dist/cjs/components/filter-box/filter-by-condition.d.ts.map +1 -0
- package/dist/cjs/components/filter-box/filter-by-condition.js +47 -0
- package/dist/cjs/components/filter-box/filter-by-value.d.ts +9 -0
- package/dist/cjs/components/filter-box/filter-by-value.d.ts.map +1 -0
- package/dist/cjs/components/filter-box/filter-by-value.js +86 -0
- package/dist/cjs/components/filter-box/index.d.ts +50 -0
- package/dist/cjs/components/filter-box/index.d.ts.map +1 -0
- package/dist/cjs/components/filter-box/index.js +357 -0
- package/dist/cjs/components/floating-cell-editor/index.d.ts +83 -0
- package/dist/cjs/components/floating-cell-editor/index.d.ts.map +1 -0
- package/dist/cjs/components/floating-cell-editor/index.js +180 -0
- package/dist/cjs/components/formula-bar/index.d.ts +11 -0
- package/dist/cjs/components/formula-bar/index.d.ts.map +1 -0
- package/dist/cjs/components/formula-bar/index.js +19 -0
- package/dist/cjs/components/formula-bar/style.d.ts +4 -0
- package/dist/cjs/components/formula-bar/style.d.ts.map +1 -0
- package/dist/cjs/components/formula-bar/style.js +16 -0
- package/dist/cjs/components/formula-input/index.d.ts +17 -0
- package/dist/cjs/components/formula-input/index.d.ts.map +1 -0
- package/dist/cjs/components/formula-input/index.js +92 -0
- package/dist/cjs/components/grid-footer/index.d.ts +14 -0
- package/dist/cjs/components/grid-footer/index.d.ts.map +1 -0
- package/dist/cjs/components/grid-footer/index.js +40 -0
- package/dist/cjs/components/header-cell/index.d.ts +10 -0
- package/dist/cjs/components/header-cell/index.d.ts.map +1 -0
- package/dist/cjs/components/header-cell/index.js +25 -0
- package/dist/cjs/components/header-menu/index.d.ts +13 -0
- package/dist/cjs/components/header-menu/index.d.ts.map +1 -0
- package/dist/cjs/components/header-menu/index.js +19 -0
- package/dist/cjs/components/header-move/index.d.ts +23 -0
- package/dist/cjs/components/header-move/index.d.ts.map +1 -0
- package/dist/cjs/components/header-move/index.js +46 -0
- package/dist/cjs/components/header-resizer/index.d.ts +19 -0
- package/dist/cjs/components/header-resizer/index.d.ts.map +1 -0
- package/dist/cjs/components/header-resizer/index.js +38 -0
- package/dist/cjs/components/hidden-markers/index.d.ts +15 -0
- package/dist/cjs/components/hidden-markers/index.d.ts.map +1 -0
- package/dist/cjs/components/hidden-markers/index.js +47 -0
- package/dist/cjs/components/hidden-markers/style.d.ts +5 -0
- package/dist/cjs/components/hidden-markers/style.d.ts.map +1 -0
- package/dist/cjs/components/hidden-markers/style.js +11 -0
- package/dist/cjs/components/insert-function-dialog/index.d.ts +32 -0
- package/dist/cjs/components/insert-function-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/insert-function-dialog/index.js +84 -0
- package/dist/cjs/components/loading-indicator/index.d.ts +7 -0
- package/dist/cjs/components/loading-indicator/index.d.ts.map +1 -0
- package/dist/cjs/components/loading-indicator/index.js +14 -0
- package/dist/cjs/components/outline-gutter/index.d.ts +44 -0
- package/dist/cjs/components/outline-gutter/index.d.ts.map +1 -0
- package/dist/cjs/components/outline-gutter/index.js +450 -0
- package/dist/cjs/components/pivot-placeholder/index.d.ts +12 -0
- package/dist/cjs/components/pivot-placeholder/index.d.ts.map +1 -0
- package/dist/cjs/components/pivot-placeholder/index.js +24 -0
- package/dist/cjs/components/print-preview/cell-styles.d.ts +18 -0
- package/dist/cjs/components/print-preview/cell-styles.d.ts.map +1 -0
- package/dist/cjs/components/print-preview/cell-styles.js +181 -0
- package/dist/cjs/components/print-preview/index.d.ts +5 -0
- package/dist/cjs/components/print-preview/index.d.ts.map +1 -0
- package/dist/cjs/components/print-preview/index.js +9 -0
- package/dist/cjs/components/print-preview/page-block.d.ts +62 -0
- package/dist/cjs/components/print-preview/page-block.d.ts.map +1 -0
- package/dist/cjs/components/print-preview/page-block.js +322 -0
- package/dist/cjs/components/print-preview/print-preview-dialog.d.ts +49 -0
- package/dist/cjs/components/print-preview/print-preview-dialog.d.ts.map +1 -0
- package/dist/cjs/components/print-preview/print-preview-dialog.js +374 -0
- package/dist/cjs/components/print-preview/run-print.d.ts +11 -0
- package/dist/cjs/components/print-preview/run-print.d.ts.map +1 -0
- package/dist/cjs/components/print-preview/run-print.js +72 -0
- package/dist/cjs/components/print-preview/settings.d.ts +130 -0
- package/dist/cjs/components/print-preview/settings.d.ts.map +1 -0
- package/dist/cjs/components/print-preview/settings.js +236 -0
- package/dist/cjs/components/print-preview/use-page-layout.d.ts +60 -0
- package/dist/cjs/components/print-preview/use-page-layout.d.ts.map +1 -0
- package/dist/cjs/components/print-preview/use-page-layout.js +161 -0
- package/dist/cjs/components/range-selector/index.d.ts +25 -0
- package/dist/cjs/components/range-selector/index.d.ts.map +1 -0
- package/dist/cjs/components/range-selector/index.js +250 -0
- package/dist/cjs/components/resizer/index.d.ts +9 -0
- package/dist/cjs/components/resizer/index.d.ts.map +1 -0
- package/dist/cjs/components/resizer/index.js +46 -0
- package/dist/cjs/components/selection/avatar.d.ts +14 -0
- package/dist/cjs/components/selection/avatar.d.ts.map +1 -0
- package/dist/cjs/components/selection/avatar.js +17 -0
- package/dist/cjs/components/selection/index.d.ts +9 -0
- package/dist/cjs/components/selection/index.d.ts.map +1 -0
- package/dist/cjs/components/selection/index.js +179 -0
- package/dist/cjs/components/selection/magic-fill.d.ts +26 -0
- package/dist/cjs/components/selection/magic-fill.d.ts.map +1 -0
- package/dist/cjs/components/selection/magic-fill.js +60 -0
- package/dist/cjs/components/selection/paste-menu.d.ts +10 -0
- package/dist/cjs/components/selection/paste-menu.d.ts.map +1 -0
- package/dist/cjs/components/selection/paste-menu.js +35 -0
- package/dist/cjs/components/selection/quick-edit.d.ts +14 -0
- package/dist/cjs/components/selection/quick-edit.d.ts.map +1 -0
- package/dist/cjs/components/selection/quick-edit.js +41 -0
- package/dist/cjs/components/selection/style.d.ts +15 -0
- package/dist/cjs/components/selection/style.d.ts.map +1 -0
- package/dist/cjs/components/selection/style.js +47 -0
- package/dist/cjs/components/selection/suggestion-action.d.ts +22 -0
- package/dist/cjs/components/selection/suggestion-action.d.ts.map +1 -0
- package/dist/cjs/components/selection/suggestion-action.js +61 -0
- package/dist/cjs/components/selection/title.d.ts +45 -0
- package/dist/cjs/components/selection/title.d.ts.map +1 -0
- package/dist/cjs/components/selection/title.js +93 -0
- package/dist/cjs/components/selection/types.d.ts +43 -0
- package/dist/cjs/components/selection/types.d.ts.map +1 -0
- package/dist/cjs/components/selection/types.js +2 -0
- package/dist/cjs/components/selection-input/index.d.ts +19 -0
- package/dist/cjs/components/selection-input/index.d.ts.map +1 -0
- package/dist/cjs/components/selection-input/index.js +30 -0
- package/dist/cjs/components/selection-input/style.d.ts +3 -0
- package/dist/cjs/components/selection-input/style.d.ts.map +1 -0
- package/dist/cjs/components/selection-input/style.js +11 -0
- package/dist/cjs/components/sheet-search/index.d.ts +41 -0
- package/dist/cjs/components/sheet-search/index.d.ts.map +1 -0
- package/dist/cjs/components/sheet-search/index.js +115 -0
- package/dist/cjs/components/sheet-status/index.d.ts +40 -0
- package/dist/cjs/components/sheet-status/index.d.ts.map +1 -0
- package/dist/cjs/components/sheet-status/index.js +154 -0
- package/dist/cjs/components/sheet-status/style.d.ts +4 -0
- package/dist/cjs/components/sheet-status/style.d.ts.map +1 -0
- package/dist/cjs/components/sheet-status/style.js +17 -0
- package/dist/cjs/components/sheet-switcher/index.d.ts +12 -0
- package/dist/cjs/components/sheet-switcher/index.d.ts.map +1 -0
- package/dist/cjs/components/sheet-switcher/index.js +39 -0
- package/dist/cjs/components/sheet-switcher/new-sheet-button.d.ts +4 -0
- package/dist/cjs/components/sheet-switcher/new-sheet-button.d.ts.map +1 -0
- package/dist/cjs/components/sheet-switcher/new-sheet-button.js +12 -0
- package/dist/cjs/components/sheet-tabs/context-menu.d.ts +43 -0
- package/dist/cjs/components/sheet-tabs/context-menu.d.ts.map +1 -0
- package/dist/cjs/components/sheet-tabs/context-menu.js +58 -0
- package/dist/cjs/components/sheet-tabs/index.d.ts +18 -0
- package/dist/cjs/components/sheet-tabs/index.d.ts.map +1 -0
- package/dist/cjs/components/sheet-tabs/index.js +231 -0
- package/dist/cjs/components/sheet-tabs/sheet-tab.d.ts +21 -0
- package/dist/cjs/components/sheet-tabs/sheet-tab.d.ts.map +1 -0
- package/dist/cjs/components/sheet-tabs/sheet-tab.js +135 -0
- package/dist/cjs/components/sheet-tabs/style.d.ts +10 -0
- package/dist/cjs/components/sheet-tabs/style.d.ts.map +1 -0
- package/dist/cjs/components/sheet-tabs/style.js +38 -0
- package/dist/cjs/components/sheet-tabs/types.d.ts +45 -0
- package/dist/cjs/components/sheet-tabs/types.d.ts.map +1 -0
- package/dist/cjs/components/sheet-tabs/types.js +2 -0
- package/dist/cjs/components/sort-range-dialog/index.d.ts +66 -0
- package/dist/cjs/components/sort-range-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/sort-range-dialog/index.js +260 -0
- package/dist/cjs/components/toolbar/background-color-selector.d.ts +19 -0
- package/dist/cjs/components/toolbar/background-color-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/background-color-selector.js +34 -0
- package/dist/cjs/components/toolbar/border-color-selector.d.ts +18 -0
- package/dist/cjs/components/toolbar/border-color-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/border-color-selector.js +31 -0
- package/dist/cjs/components/toolbar/border-line-style-options.d.ts +9 -0
- package/dist/cjs/components/toolbar/border-line-style-options.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/border-line-style-options.js +48 -0
- package/dist/cjs/components/toolbar/border-line-style-selector.d.ts +9 -0
- package/dist/cjs/components/toolbar/border-line-style-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/border-line-style-selector.js +25 -0
- package/dist/cjs/components/toolbar/border-location-options.d.ts +11 -0
- package/dist/cjs/components/toolbar/border-location-options.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/border-location-options.js +71 -0
- package/dist/cjs/components/toolbar/border-selector.d.ts +20 -0
- package/dist/cjs/components/toolbar/border-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/border-selector.js +65 -0
- package/dist/cjs/components/toolbar/buttons.d.ts +55 -0
- package/dist/cjs/components/toolbar/buttons.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/buttons.js +216 -0
- package/dist/cjs/components/toolbar/cell-style-selector.d.ts +25 -0
- package/dist/cjs/components/toolbar/cell-style-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/cell-style-selector.js +531 -0
- package/dist/cjs/components/toolbar/color-selector.d.ts +13 -0
- package/dist/cjs/components/toolbar/color-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/color-selector.js +57 -0
- package/dist/cjs/components/toolbar/font-family-selector.d.ts +22 -0
- package/dist/cjs/components/toolbar/font-family-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/font-family-selector.js +183 -0
- package/dist/cjs/components/toolbar/font-size-selector.d.ts +10 -0
- package/dist/cjs/components/toolbar/font-size-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/font-size-selector.js +149 -0
- package/dist/cjs/components/toolbar/index.d.ts +25 -0
- package/dist/cjs/components/toolbar/index.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/index.js +27 -0
- package/dist/cjs/components/toolbar/insert-menu.d.ts +22 -0
- package/dist/cjs/components/toolbar/insert-menu.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/insert-menu.js +146 -0
- package/dist/cjs/components/toolbar/merge-cells-selector.d.ts +15 -0
- package/dist/cjs/components/toolbar/merge-cells-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/merge-cells-selector.js +56 -0
- package/dist/cjs/components/toolbar/scale-selector.d.ts +13 -0
- package/dist/cjs/components/toolbar/scale-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/scale-selector.js +78 -0
- package/dist/cjs/components/toolbar/style.d.ts +3 -0
- package/dist/cjs/components/toolbar/style.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/style.js +11 -0
- package/dist/cjs/components/toolbar/table-actions.d.ts +15 -0
- package/dist/cjs/components/toolbar/table-actions.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/table-actions.js +47 -0
- package/dist/cjs/components/toolbar/table-style-selector.d.ts +25 -0
- package/dist/cjs/components/toolbar/table-style-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/table-style-selector.js +494 -0
- package/dist/cjs/components/toolbar/text-color-selector.d.ts +20 -0
- package/dist/cjs/components/toolbar/text-color-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/text-color-selector.js +34 -0
- package/dist/cjs/components/toolbar/text-format-selector.d.ts +23 -0
- package/dist/cjs/components/toolbar/text-format-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/text-format-selector.js +263 -0
- package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts +10 -0
- package/dist/cjs/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/text-horizontal-align-selector.js +42 -0
- package/dist/cjs/components/toolbar/text-vertical-align-selector.d.ts +9 -0
- package/dist/cjs/components/toolbar/text-vertical-align-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/text-vertical-align-selector.js +42 -0
- package/dist/cjs/components/toolbar/text-wrap-selector.d.ts +9 -0
- package/dist/cjs/components/toolbar/text-wrap-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/text-wrap-selector.js +41 -0
- package/dist/cjs/components/toolbar/theme-selector.d.ts +10 -0
- package/dist/cjs/components/toolbar/theme-selector.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/theme-selector.js +32 -0
- package/dist/cjs/components/toolbar/toolbar.d.ts +12 -0
- package/dist/cjs/components/toolbar/toolbar.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/toolbar.js +145 -0
- package/dist/cjs/components/toolbar/types.d.ts +2 -0
- package/dist/cjs/components/toolbar/types.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/types.js +2 -0
- package/dist/cjs/components/toolbar/view-menu.d.ts +25 -0
- package/dist/cjs/components/toolbar/view-menu.d.ts.map +1 -0
- package/dist/cjs/components/toolbar/view-menu.js +46 -0
- package/dist/cjs/components/validation-alert-dialog/index.d.ts +15 -0
- package/dist/cjs/components/validation-alert-dialog/index.d.ts.map +1 -0
- package/dist/cjs/components/validation-alert-dialog/index.js +69 -0
- package/dist/cjs/config.d.ts +107 -0
- package/dist/cjs/config.d.ts.map +1 -0
- package/dist/cjs/config.js +270 -0
- package/dist/cjs/helpers/merged-cell-borders.d.ts +26 -0
- package/dist/cjs/helpers/merged-cell-borders.d.ts.map +1 -0
- package/dist/cjs/helpers/merged-cell-borders.js +44 -0
- package/dist/cjs/helpers.d.ts +118 -0
- package/dist/cjs/helpers.d.ts.map +1 -0
- package/dist/cjs/helpers.js +524 -0
- package/dist/cjs/hooks/index.d.ts +11 -0
- package/dist/cjs/hooks/index.d.ts.map +1 -0
- package/dist/cjs/hooks/index.js +13 -0
- package/dist/cjs/hooks/show-zeros.d.ts +13 -0
- package/dist/cjs/hooks/show-zeros.d.ts.map +1 -0
- package/dist/cjs/hooks/show-zeros.js +24 -0
- package/dist/cjs/hooks/use-async.d.ts +2 -0
- package/dist/cjs/hooks/use-async.d.ts.map +1 -0
- package/dist/cjs/hooks/use-async.js +37 -0
- package/dist/cjs/hooks/use-border-styles.d.ts +31 -0
- package/dist/cjs/hooks/use-border-styles.d.ts.map +1 -0
- package/dist/cjs/hooks/use-border-styles.js +433 -0
- package/dist/cjs/hooks/use-callback-ref.d.ts +6 -0
- package/dist/cjs/hooks/use-callback-ref.d.ts.map +1 -0
- package/dist/cjs/hooks/use-callback-ref.js +27 -0
- package/dist/cjs/hooks/use-cell-diff-highlight.d.ts +43 -0
- package/dist/cjs/hooks/use-cell-diff-highlight.d.ts.map +1 -0
- package/dist/cjs/hooks/use-cell-diff-highlight.js +83 -0
- package/dist/cjs/hooks/use-cell-popover.d.ts +55 -0
- package/dist/cjs/hooks/use-cell-popover.d.ts.map +1 -0
- package/dist/cjs/hooks/use-cell-popover.js +99 -0
- package/dist/cjs/hooks/use-cell-renderer.d.ts +226 -0
- package/dist/cjs/hooks/use-cell-renderer.d.ts.map +1 -0
- package/dist/cjs/hooks/use-cell-renderer.js +361 -0
- package/dist/cjs/hooks/use-column-color-icons.d.ts +43 -0
- package/dist/cjs/hooks/use-column-color-icons.d.ts.map +1 -0
- package/dist/cjs/hooks/use-column-color-icons.js +86 -0
- package/dist/cjs/hooks/use-conditional-formatting.d.ts +35 -0
- package/dist/cjs/hooks/use-conditional-formatting.d.ts.map +1 -0
- package/dist/cjs/hooks/use-conditional-formatting.js +720 -0
- package/dist/cjs/hooks/use-context-menu.d.ts +52 -0
- package/dist/cjs/hooks/use-context-menu.d.ts.map +1 -0
- package/dist/cjs/hooks/use-context-menu.js +83 -0
- package/dist/cjs/hooks/use-context-setter.d.ts +3 -0
- package/dist/cjs/hooks/use-context-setter.d.ts.map +1 -0
- package/dist/cjs/hooks/use-context-setter.js +132 -0
- package/dist/cjs/hooks/use-copy-paste-cut.d.ts +45 -0
- package/dist/cjs/hooks/use-copy-paste-cut.d.ts.map +1 -0
- package/dist/cjs/hooks/use-copy-paste-cut.js +329 -0
- package/dist/cjs/hooks/use-create-address-from-selection.d.ts +15 -0
- package/dist/cjs/hooks/use-create-address-from-selection.d.ts.map +1 -0
- package/dist/cjs/hooks/use-create-address-from-selection.js +75 -0
- package/dist/cjs/hooks/use-create-formula-tokenizer.d.ts +15 -0
- package/dist/cjs/hooks/use-create-formula-tokenizer.d.ts.map +1 -0
- package/dist/cjs/hooks/use-create-formula-tokenizer.js +67 -0
- package/dist/cjs/hooks/use-delayed-value.d.ts +8 -0
- package/dist/cjs/hooks/use-delayed-value.d.ts.map +1 -0
- package/dist/cjs/hooks/use-delayed-value.js +34 -0
- package/dist/cjs/hooks/use-editable.d.ts +366 -0
- package/dist/cjs/hooks/use-editable.d.ts.map +1 -0
- package/dist/cjs/hooks/use-editable.js +823 -0
- package/dist/cjs/hooks/use-editor-cancel.d.ts +25 -0
- package/dist/cjs/hooks/use-editor-cancel.d.ts.map +1 -0
- package/dist/cjs/hooks/use-editor-cancel.js +51 -0
- package/dist/cjs/hooks/use-editor-change.d.ts +13 -0
- package/dist/cjs/hooks/use-editor-change.d.ts.map +1 -0
- package/dist/cjs/hooks/use-editor-change.js +72 -0
- package/dist/cjs/hooks/use-editor-keydown.d.ts +11 -0
- package/dist/cjs/hooks/use-editor-keydown.d.ts.map +1 -0
- package/dist/cjs/hooks/use-editor-keydown.js +47 -0
- package/dist/cjs/hooks/use-editor-submit.d.ts +58 -0
- package/dist/cjs/hooks/use-editor-submit.d.ts.map +1 -0
- package/dist/cjs/hooks/use-editor-submit.js +97 -0
- package/dist/cjs/hooks/use-embeds-charts.d.ts +193 -0
- package/dist/cjs/hooks/use-embeds-charts.d.ts.map +1 -0
- package/dist/cjs/hooks/use-embeds-charts.js +284 -0
- package/dist/cjs/hooks/use-expand-cell.d.ts +35 -0
- package/dist/cjs/hooks/use-expand-cell.d.ts.map +1 -0
- package/dist/cjs/hooks/use-expand-cell.js +53 -0
- package/dist/cjs/hooks/use-export-range.d.ts +36 -0
- package/dist/cjs/hooks/use-export-range.d.ts.map +1 -0
- package/dist/cjs/hooks/use-export-range.js +259 -0
- package/dist/cjs/hooks/use-filter.d.ts +46 -0
- package/dist/cjs/hooks/use-filter.d.ts.map +1 -0
- package/dist/cjs/hooks/use-filter.js +181 -0
- package/dist/cjs/hooks/use-flash.d.ts +18 -0
- package/dist/cjs/hooks/use-flash.d.ts.map +1 -0
- package/dist/cjs/hooks/use-flash.js +77 -0
- package/dist/cjs/hooks/use-fonts.d.ts +8 -0
- package/dist/cjs/hooks/use-fonts.d.ts.map +1 -0
- package/dist/cjs/hooks/use-fonts.js +24 -0
- package/dist/cjs/hooks/use-formula-range-helpers.d.ts +21 -0
- package/dist/cjs/hooks/use-formula-range-helpers.d.ts.map +1 -0
- package/dist/cjs/hooks/use-formula-range-helpers.js +67 -0
- package/dist/cjs/hooks/use-get-tooltip.d.ts +52 -0
- package/dist/cjs/hooks/use-get-tooltip.d.ts.map +1 -0
- package/dist/cjs/hooks/use-get-tooltip.js +64 -0
- package/dist/cjs/hooks/use-get-values-from-range.d.ts +44 -0
- package/dist/cjs/hooks/use-get-values-from-range.d.ts.map +1 -0
- package/dist/cjs/hooks/use-get-values-from-range.js +194 -0
- package/dist/cjs/hooks/use-grid-children.d.ts +31 -0
- package/dist/cjs/hooks/use-grid-children.d.ts.map +1 -0
- package/dist/cjs/hooks/use-grid-children.js +139 -0
- package/dist/cjs/hooks/use-header-actions.d.ts +70 -0
- package/dist/cjs/hooks/use-header-actions.d.ts.map +1 -0
- package/dist/cjs/hooks/use-header-actions.js +256 -0
- package/dist/cjs/hooks/use-hidden-dimension-markers.d.ts +20 -0
- package/dist/cjs/hooks/use-hidden-dimension-markers.d.ts.map +1 -0
- package/dist/cjs/hooks/use-hidden-dimension-markers.js +138 -0
- package/dist/cjs/hooks/use-hidden-dimensions.d.ts +7 -0
- package/dist/cjs/hooks/use-hidden-dimensions.d.ts.map +1 -0
- package/dist/cjs/hooks/use-hidden-dimensions.js +60 -0
- package/dist/cjs/hooks/use-hovered-selection-ids.d.ts +9 -0
- package/dist/cjs/hooks/use-hovered-selection-ids.d.ts.map +1 -0
- package/dist/cjs/hooks/use-hovered-selection-ids.js +30 -0
- package/dist/cjs/hooks/use-isomorphic-layout-effect.d.ts +6 -0
- package/dist/cjs/hooks/use-isomorphic-layout-effect.d.ts.map +1 -0
- package/dist/cjs/hooks/use-isomorphic-layout-effect.js +11 -0
- package/dist/cjs/hooks/use-keyboard-handler.d.ts +57 -0
- package/dist/cjs/hooks/use-keyboard-handler.d.ts.map +1 -0
- package/dist/cjs/hooks/use-keyboard-handler.js +472 -0
- package/dist/cjs/hooks/use-licensekey-validator.d.ts +16 -0
- package/dist/cjs/hooks/use-licensekey-validator.d.ts.map +1 -0
- package/dist/cjs/hooks/use-licensekey-validator.js +180 -0
- package/dist/cjs/hooks/use-memo-compare.d.ts +2 -0
- package/dist/cjs/hooks/use-memo-compare.d.ts.map +1 -0
- package/dist/cjs/hooks/use-memo-compare.js +18 -0
- package/dist/cjs/hooks/use-merge.refs.d.ts +4 -0
- package/dist/cjs/hooks/use-merge.refs.d.ts.map +1 -0
- package/dist/cjs/hooks/use-merge.refs.js +29 -0
- package/dist/cjs/hooks/use-move-columns-rows.d.ts +46 -0
- package/dist/cjs/hooks/use-move-columns-rows.d.ts.map +1 -0
- package/dist/cjs/hooks/use-move-columns-rows.js +344 -0
- package/dist/cjs/hooks/use-navigate-sheet-range.d.ts +16 -0
- package/dist/cjs/hooks/use-navigate-sheet-range.d.ts.map +1 -0
- package/dist/cjs/hooks/use-navigate-sheet-range.js +36 -0
- package/dist/cjs/hooks/use-previous.d.ts +3 -0
- package/dist/cjs/hooks/use-previous.d.ts.map +1 -0
- package/dist/cjs/hooks/use-previous.js +12 -0
- package/dist/cjs/hooks/use-raf.d.ts +6 -0
- package/dist/cjs/hooks/use-raf.d.ts.map +1 -0
- package/dist/cjs/hooks/use-raf.js +35 -0
- package/dist/cjs/hooks/use-resize-observer.d.ts +6 -0
- package/dist/cjs/hooks/use-resize-observer.d.ts.map +1 -0
- package/dist/cjs/hooks/use-resize-observer.js +46 -0
- package/dist/cjs/hooks/use-scale-listener.d.ts +11 -0
- package/dist/cjs/hooks/use-scale-listener.d.ts.map +1 -0
- package/dist/cjs/hooks/use-scale-listener.js +52 -0
- package/dist/cjs/hooks/use-selected-rows-columns.d.ts +21 -0
- package/dist/cjs/hooks/use-selected-rows-columns.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selected-rows-columns.js +74 -0
- package/dist/cjs/hooks/use-selection-aware-formatting.d.ts +13 -0
- package/dist/cjs/hooks/use-selection-aware-formatting.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selection-aware-formatting.js +49 -0
- package/dist/cjs/hooks/use-selection-change.d.ts +10 -0
- package/dist/cjs/hooks/use-selection-change.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selection-change.js +63 -0
- package/dist/cjs/hooks/use-selection-interceptors.d.ts +34 -0
- package/dist/cjs/hooks/use-selection-interceptors.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selection-interceptors.js +131 -0
- package/dist/cjs/hooks/use-selection-move.d.ts +31 -0
- package/dist/cjs/hooks/use-selection-move.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selection-move.js +155 -0
- package/dist/cjs/hooks/use-selection-renderer.d.ts +46 -0
- package/dist/cjs/hooks/use-selection-renderer.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selection-renderer.js +145 -0
- package/dist/cjs/hooks/use-selection-resize.d.ts +30 -0
- package/dist/cjs/hooks/use-selection-resize.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selection-resize.js +180 -0
- package/dist/cjs/hooks/use-selection.d.ts +185 -0
- package/dist/cjs/hooks/use-selection.d.ts.map +1 -0
- package/dist/cjs/hooks/use-selection.js +1515 -0
- package/dist/cjs/hooks/use-sheet-change-handler.d.ts +3 -0
- package/dist/cjs/hooks/use-sheet-change-handler.d.ts.map +1 -0
- package/dist/cjs/hooks/use-sheet-change-handler.js +38 -0
- package/dist/cjs/hooks/use-sizer.d.ts +164 -0
- package/dist/cjs/hooks/use-sizer.d.ts.map +1 -0
- package/dist/cjs/hooks/use-sizer.js +424 -0
- package/dist/cjs/hooks/use-spreadsheet-theme.d.ts +17 -0
- package/dist/cjs/hooks/use-spreadsheet-theme.d.ts.map +1 -0
- package/dist/cjs/hooks/use-spreadsheet-theme.js +55 -0
- package/dist/cjs/hooks/use-stable-ref.d.ts +2 -0
- package/dist/cjs/hooks/use-stable-ref.d.ts.map +1 -0
- package/dist/cjs/hooks/use-stable-ref.js +14 -0
- package/dist/cjs/hooks/use-structured-reference-selection.d.ts +23 -0
- package/dist/cjs/hooks/use-structured-reference-selection.d.ts.map +1 -0
- package/dist/cjs/hooks/use-structured-reference-selection.js +103 -0
- package/dist/cjs/hooks/use-table-resizer.d.ts +23 -0
- package/dist/cjs/hooks/use-table-resizer.d.ts.map +1 -0
- package/dist/cjs/hooks/use-table-resizer.js +112 -0
- package/dist/cjs/hooks/use-text-dimensions.d.ts +16 -0
- package/dist/cjs/hooks/use-text-dimensions.d.ts.map +1 -0
- package/dist/cjs/hooks/use-text-dimensions.js +40 -0
- package/dist/cjs/hooks/use-tooltip.d.ts +70 -0
- package/dist/cjs/hooks/use-tooltip.d.ts.map +1 -0
- package/dist/cjs/hooks/use-tooltip.js +79 -0
- package/dist/cjs/hooks/use-touch.d.ts +16 -0
- package/dist/cjs/hooks/use-touch.d.ts.map +1 -0
- package/dist/cjs/hooks/use-touch.js +237 -0
- package/dist/cjs/index.d.ts +69 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +81 -0
- package/dist/cjs/providers/spreadsheet-provider.d.ts +25 -0
- package/dist/cjs/providers/spreadsheet-provider.d.ts.map +1 -0
- package/dist/cjs/providers/spreadsheet-provider.js +40 -0
- package/dist/cjs/release-date.d.ts +2 -0
- package/dist/cjs/release-date.d.ts.map +1 -0
- package/dist/cjs/release-date.js +7 -0
- package/dist/cjs/signals/scroll-subscriber.d.ts +4 -0
- package/dist/cjs/signals/scroll-subscriber.d.ts.map +1 -0
- package/dist/cjs/signals/scroll-subscriber.js +5 -0
- package/dist/cjs/test-setup.d.ts +2 -0
- package/dist/cjs/test-setup.d.ts.map +1 -0
- package/dist/cjs/test-setup.js +17 -0
- package/dist/cjs/themes.d.ts +13 -0
- package/dist/cjs/themes.d.ts.map +1 -0
- package/dist/cjs/themes.js +251 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/cjs/types.d.ts +1215 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +12 -0
- package/dist/cjs/utils/maybe.d.ts +12 -0
- package/dist/cjs/utils/maybe.d.ts.map +1 -0
- package/dist/cjs/utils/maybe.js +19 -0
- package/dist/cjs/vitest.config.d.ts +3 -0
- package/dist/cjs/vitest.config.d.ts.map +1 -0
- package/dist/cjs/vitest.config.js +24 -0
- package/dist/esm/api/animate.d.ts +36 -0
- package/dist/esm/api/animate.d.ts.map +1 -0
- package/dist/esm/api/animate.js +117 -0
- package/dist/esm/api/banded-ranges.d.ts +16 -0
- package/dist/esm/api/banded-ranges.d.ts.map +1 -0
- package/dist/esm/api/banded-ranges.js +118 -0
- package/dist/esm/api/cf-engine.d.ts +36 -0
- package/dist/esm/api/cf-engine.d.ts.map +1 -0
- package/dist/esm/api/cf-engine.js +54 -0
- package/dist/esm/api/cf-overlays.d.ts +7 -0
- package/dist/esm/api/cf-overlays.d.ts.map +1 -0
- package/dist/esm/api/cf-overlays.js +118 -0
- package/dist/esm/api/cf-window.d.ts +45 -0
- package/dist/esm/api/cf-window.d.ts.map +1 -0
- package/dist/esm/api/cf-window.js +109 -0
- package/dist/esm/api/colors.d.ts +8 -0
- package/dist/esm/api/colors.d.ts.map +1 -0
- package/dist/esm/api/colors.js +27 -0
- package/dist/esm/api/copy-paste.d.ts +10 -0
- package/dist/esm/api/copy-paste.d.ts.map +1 -0
- package/dist/esm/api/copy-paste.js +23 -0
- package/dist/esm/api/fill-patterns.d.ts +5 -0
- package/dist/esm/api/fill-patterns.d.ts.map +1 -0
- package/dist/esm/api/fill-patterns.js +196 -0
- package/dist/esm/api/font-loader.d.ts +8 -0
- package/dist/esm/api/font-loader.d.ts.map +1 -0
- package/dist/esm/api/font-loader.js +67 -0
- package/dist/esm/api/heatmap.d.ts +4 -0
- package/dist/esm/api/heatmap.d.ts.map +1 -0
- package/dist/esm/api/heatmap.js +167 -0
- package/dist/esm/api/scheduler.d.ts +8 -0
- package/dist/esm/api/scheduler.d.ts.map +1 -0
- package/dist/esm/api/scheduler.js +6 -0
- package/dist/esm/api/scroller.d.ts +134 -0
- package/dist/esm/api/scroller.d.ts.map +1 -0
- package/dist/esm/api/scroller.js +704 -0
- package/dist/esm/api/selections.d.ts +111 -0
- package/dist/esm/api/selections.d.ts.map +1 -0
- package/dist/esm/api/selections.js +365 -0
- package/dist/esm/api/spreadsheet-api.d.ts +271 -0
- package/dist/esm/api/spreadsheet-api.d.ts.map +1 -0
- package/dist/esm/api/spreadsheet-api.js +649 -0
- package/dist/esm/api/table.d.ts +11 -0
- package/dist/esm/api/table.d.ts.map +1 -0
- package/dist/esm/api/table.js +11 -0
- package/dist/esm/api/validation.d.ts +98 -0
- package/dist/esm/api/validation.d.ts.map +1 -0
- package/dist/esm/api/validation.js +470 -0
- package/dist/esm/atoms/active-editor.atom.d.ts +8 -0
- package/dist/esm/atoms/active-editor.atom.d.ts.map +1 -0
- package/dist/esm/atoms/active-editor.atom.js +6 -0
- package/dist/esm/atoms/cell-input-context.atom.d.ts +15 -0
- package/dist/esm/atoms/cell-input-context.atom.d.ts.map +1 -0
- package/dist/esm/atoms/cell-input-context.atom.js +20 -0
- package/dist/esm/atoms/editing-cell.atom.d.ts +7 -0
- package/dist/esm/atoms/editing-cell.atom.d.ts.map +1 -0
- package/dist/esm/atoms/editing-cell.atom.js +4 -0
- package/dist/esm/atoms/formula-bar-editor-value.atom.d.ts +19 -0
- package/dist/esm/atoms/formula-bar-editor-value.atom.d.ts.map +1 -0
- package/dist/esm/atoms/formula-bar-editor-value.atom.js +17 -0
- package/dist/esm/atoms/formula-mode.atom.d.ts +7 -0
- package/dist/esm/atoms/formula-mode.atom.d.ts.map +1 -0
- package/dist/esm/atoms/formula-mode.atom.js +5 -0
- package/dist/esm/atoms/formula-selection-state.atom.d.ts +16 -0
- package/dist/esm/atoms/formula-selection-state.atom.d.ts.map +1 -0
- package/dist/esm/atoms/formula-selection-state.atom.js +14 -0
- package/dist/esm/atoms/formula-selections.atom.d.ts +8 -0
- package/dist/esm/atoms/formula-selections.atom.d.ts.map +1 -0
- package/dist/esm/atoms/formula-selections.atom.js +4 -0
- package/dist/esm/atoms/index.d.ts +18 -0
- package/dist/esm/atoms/index.d.ts.map +1 -0
- package/dist/esm/atoms/index.js +17 -0
- package/dist/esm/atoms/loading-indicator.atom.d.ts +12 -0
- package/dist/esm/atoms/loading-indicator.atom.d.ts.map +1 -0
- package/dist/esm/atoms/loading-indicator.atom.js +17 -0
- package/dist/esm/atoms/magic-fill-state.atom.d.ts +5 -0
- package/dist/esm/atoms/magic-fill-state.atom.d.ts.map +1 -0
- package/dist/esm/atoms/magic-fill-state.atom.js +6 -0
- package/dist/esm/atoms/paste-menu.atom.d.ts +6 -0
- package/dist/esm/atoms/paste-menu.atom.d.ts.map +1 -0
- package/dist/esm/atoms/paste-menu.atom.js +4 -0
- package/dist/esm/atoms/persistent-tooltip.atom.d.ts +11 -0
- package/dist/esm/atoms/persistent-tooltip.atom.d.ts.map +1 -0
- package/dist/esm/atoms/persistent-tooltip.atom.js +13 -0
- package/dist/esm/atoms/popover.atom.d.ts +7 -0
- package/dist/esm/atoms/popover.atom.d.ts.map +1 -0
- package/dist/esm/atoms/popover.atom.js +4 -0
- package/dist/esm/atoms/range-selector.atom.d.ts +6 -0
- package/dist/esm/atoms/range-selector.atom.d.ts.map +1 -0
- package/dist/esm/atoms/range-selector.atom.js +7 -0
- package/dist/esm/atoms/selected-chart-embed.atom.d.ts +6 -0
- package/dist/esm/atoms/selected-chart-embed.atom.d.ts.map +1 -0
- package/dist/esm/atoms/selected-chart-embed.atom.js +4 -0
- package/dist/esm/atoms/sheet-context.atom.d.ts +66 -0
- package/dist/esm/atoms/sheet-context.atom.d.ts.map +1 -0
- package/dist/esm/atoms/sheet-context.atom.js +73 -0
- package/dist/esm/atoms/sheet-status-display.atom.d.ts +15 -0
- package/dist/esm/atoms/sheet-status-display.atom.d.ts.map +1 -0
- package/dist/esm/atoms/sheet-status-display.atom.js +11 -0
- package/dist/esm/atoms/show-formula-help.atom.d.ts +8 -0
- package/dist/esm/atoms/show-formula-help.atom.d.ts.map +1 -0
- package/dist/esm/atoms/show-formula-help.atom.js +13 -0
- package/dist/esm/atoms/sort-dialog.atom.d.ts +22 -0
- package/dist/esm/atoms/sort-dialog.atom.d.ts.map +1 -0
- package/dist/esm/atoms/sort-dialog.atom.js +9 -0
- package/dist/esm/atoms/spreadsheet-api.atom.d.ts +5 -0
- package/dist/esm/atoms/spreadsheet-api.atom.d.ts.map +1 -0
- package/dist/esm/atoms/spreadsheet-api.atom.js +4 -0
- package/dist/esm/atoms/validation-alert.atom.d.ts +27 -0
- package/dist/esm/atoms/validation-alert.atom.d.ts.map +1 -0
- package/dist/esm/atoms/validation-alert.atom.js +15 -0
- package/dist/esm/components/bottom-bar/index.d.ts +7 -0
- package/dist/esm/components/bottom-bar/index.d.ts.map +1 -0
- package/dist/esm/components/bottom-bar/index.js +5 -0
- package/dist/esm/components/canvas-grid/helpers.d.ts +15 -0
- package/dist/esm/components/canvas-grid/helpers.d.ts.map +1 -0
- package/dist/esm/components/canvas-grid/helpers.js +36 -0
- package/dist/esm/components/canvas-grid/index.d.ts +7 -0
- package/dist/esm/components/canvas-grid/index.d.ts.map +1 -0
- package/dist/esm/components/canvas-grid/index.js +3260 -0
- package/dist/esm/components/canvas-grid/typings.d.ts +2027 -0
- package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -0
- package/dist/esm/components/canvas-grid/typings.js +8 -0
- package/dist/esm/components/cell/alignment.d.ts +70 -0
- package/dist/esm/components/cell/alignment.d.ts.map +1 -0
- package/dist/esm/components/cell/alignment.js +127 -0
- package/dist/esm/components/cell/cell-background.d.ts +15 -0
- package/dist/esm/components/cell/cell-background.d.ts.map +1 -0
- package/dist/esm/components/cell/cell-background.js +142 -0
- package/dist/esm/components/cell/cell-text-runs.d.ts +98 -0
- package/dist/esm/components/cell/cell-text-runs.d.ts.map +1 -0
- package/dist/esm/components/cell/cell-text-runs.js +379 -0
- package/dist/esm/components/cell/helpers.d.ts +3 -0
- package/dist/esm/components/cell/helpers.d.ts.map +1 -0
- package/dist/esm/components/cell/helpers.js +11 -0
- package/dist/esm/components/cell/index.d.ts +4 -0
- package/dist/esm/components/cell/index.d.ts.map +1 -0
- package/dist/esm/components/cell/index.js +257 -0
- package/dist/esm/components/cell/rich-text.d.ts +82 -0
- package/dist/esm/components/cell/rich-text.d.ts.map +1 -0
- package/dist/esm/components/cell/rich-text.js +167 -0
- package/dist/esm/components/cell/typings.d.ts +190 -0
- package/dist/esm/components/cell/typings.d.ts.map +1 -0
- package/dist/esm/components/cell/typings.js +1 -0
- package/dist/esm/components/cell-arrow/index.d.ts +14 -0
- package/dist/esm/components/cell-arrow/index.d.ts.map +1 -0
- package/dist/esm/components/cell-arrow/index.js +22 -0
- package/dist/esm/components/cell-calculated/index.d.ts +17 -0
- package/dist/esm/components/cell-calculated/index.d.ts.map +1 -0
- package/dist/esm/components/cell-calculated/index.js +14 -0
- package/dist/esm/components/cell-checkbox/index.d.ts +14 -0
- package/dist/esm/components/cell-checkbox/index.d.ts.map +1 -0
- package/dist/esm/components/cell-checkbox/index.js +23 -0
- package/dist/esm/components/cell-diff/index.d.ts +42 -0
- package/dist/esm/components/cell-diff/index.d.ts.map +1 -0
- package/dist/esm/components/cell-diff/index.js +90 -0
- package/dist/esm/components/cell-editor/calendar-popup.d.ts +9 -0
- package/dist/esm/components/cell-editor/calendar-popup.d.ts.map +1 -0
- package/dist/esm/components/cell-editor/calendar-popup.js +19 -0
- package/dist/esm/components/cell-editor/formula-result-preview.d.ts +9 -0
- package/dist/esm/components/cell-editor/formula-result-preview.d.ts.map +1 -0
- package/dist/esm/components/cell-editor/formula-result-preview.js +20 -0
- package/dist/esm/components/cell-editor/helpers.d.ts +11 -0
- package/dist/esm/components/cell-editor/helpers.d.ts.map +1 -0
- package/dist/esm/components/cell-editor/helpers.js +34 -0
- package/dist/esm/components/cell-editor/helpers.spec.d.ts +2 -0
- package/dist/esm/components/cell-editor/helpers.spec.d.ts.map +1 -0
- package/dist/esm/components/cell-editor/helpers.spec.js +16 -0
- package/dist/esm/components/cell-editor/index.d.ts +146 -0
- package/dist/esm/components/cell-editor/index.d.ts.map +1 -0
- package/dist/esm/components/cell-editor/index.js +266 -0
- package/dist/esm/components/cell-editor/style.d.ts +9 -0
- package/dist/esm/components/cell-editor/style.d.ts.map +1 -0
- package/dist/esm/components/cell-editor/style.js +11 -0
- package/dist/esm/components/cell-error/index.d.ts +14 -0
- package/dist/esm/components/cell-error/index.d.ts.map +1 -0
- package/dist/esm/components/cell-error/index.js +18 -0
- package/dist/esm/components/cell-expand/index.d.ts +15 -0
- package/dist/esm/components/cell-expand/index.d.ts.map +1 -0
- package/dist/esm/components/cell-expand/index.js +25 -0
- package/dist/esm/components/cell-filter/index.d.ts +21 -0
- package/dist/esm/components/cell-filter/index.d.ts.map +1 -0
- package/dist/esm/components/cell-filter/index.js +34 -0
- package/dist/esm/components/cell-group/index.d.ts +17 -0
- package/dist/esm/components/cell-group/index.d.ts.map +1 -0
- package/dist/esm/components/cell-group/index.js +26 -0
- package/dist/esm/components/cell-input/cell-input.d.ts +123 -0
- package/dist/esm/components/cell-input/cell-input.d.ts.map +1 -0
- package/dist/esm/components/cell-input/cell-input.js +63 -0
- package/dist/esm/components/cell-input/formula-bar-cell-input.d.ts +21 -0
- package/dist/esm/components/cell-input/formula-bar-cell-input.d.ts.map +1 -0
- package/dist/esm/components/cell-input/formula-bar-cell-input.js +57 -0
- package/dist/esm/components/cell-input/index.d.ts +3 -0
- package/dist/esm/components/cell-input/index.d.ts.map +1 -0
- package/dist/esm/components/cell-input/index.js +2 -0
- package/dist/esm/components/cell-input/style.d.ts +6 -0
- package/dist/esm/components/cell-input/style.d.ts.map +1 -0
- package/dist/esm/components/cell-input/style.js +6 -0
- package/dist/esm/components/cell-overlay/index.d.ts +25 -0
- package/dist/esm/components/cell-overlay/index.d.ts.map +1 -0
- package/dist/esm/components/cell-overlay/index.js +155 -0
- package/dist/esm/components/cell-structured/index.d.ts +8 -0
- package/dist/esm/components/cell-structured/index.d.ts.map +1 -0
- package/dist/esm/components/cell-structured/index.js +16 -0
- package/dist/esm/components/cell-structured/sparkline-math.d.ts +54 -0
- package/dist/esm/components/cell-structured/sparkline-math.d.ts.map +1 -0
- package/dist/esm/components/cell-structured/sparkline-math.js +80 -0
- package/dist/esm/components/cell-structured/sparkline.d.ts +6 -0
- package/dist/esm/components/cell-structured/sparkline.d.ts.map +1 -0
- package/dist/esm/components/cell-structured/sparkline.js +246 -0
- package/dist/esm/components/cell-structured/types.d.ts +23 -0
- package/dist/esm/components/cell-structured/types.d.ts.map +1 -0
- package/dist/esm/components/cell-structured/types.js +1 -0
- package/dist/esm/components/cell-tooltip/index.d.ts +28 -0
- package/dist/esm/components/cell-tooltip/index.d.ts.map +1 -0
- package/dist/esm/components/cell-tooltip/index.js +50 -0
- package/dist/esm/components/cell-tooltip/note-editor.d.ts +12 -0
- package/dist/esm/components/cell-tooltip/note-editor.d.ts.map +1 -0
- package/dist/esm/components/cell-tooltip/note-editor.js +19 -0
- package/dist/esm/components/cell-tooltip/style.d.ts +3 -0
- package/dist/esm/components/cell-tooltip/style.d.ts.map +1 -0
- package/dist/esm/components/cell-tooltip/style.js +4 -0
- package/dist/esm/components/context-menu/index.d.ts +80 -0
- package/dist/esm/components/context-menu/index.d.ts.map +1 -0
- package/dist/esm/components/context-menu/index.js +591 -0
- package/dist/esm/components/context-menu/menu.d.ts +10 -0
- package/dist/esm/components/context-menu/menu.d.ts.map +1 -0
- package/dist/esm/components/context-menu/menu.js +9 -0
- package/dist/esm/components/context-menu/style.d.ts +6 -0
- package/dist/esm/components/context-menu/style.d.ts.map +1 -0
- package/dist/esm/components/context-menu/style.js +7 -0
- package/dist/esm/components/embeds/chart-component.d.ts +16 -0
- package/dist/esm/components/embeds/chart-component.d.ts.map +1 -0
- package/dist/esm/components/embeds/chart-component.js +7 -0
- package/dist/esm/components/embeds/embed-component.d.ts +17 -0
- package/dist/esm/components/embeds/embed-component.d.ts.map +1 -0
- package/dist/esm/components/embeds/embed-component.js +124 -0
- package/dist/esm/components/embeds/embed-draggable.d.ts +43 -0
- package/dist/esm/components/embeds/embed-draggable.d.ts.map +1 -0
- package/dist/esm/components/embeds/embed-draggable.js +115 -0
- package/dist/esm/components/embeds/index.d.ts +5 -0
- package/dist/esm/components/embeds/index.d.ts.map +1 -0
- package/dist/esm/components/embeds/index.js +4 -0
- package/dist/esm/components/embeds/shape-geometry.d.ts +10 -0
- package/dist/esm/components/embeds/shape-geometry.d.ts.map +1 -0
- package/dist/esm/components/embeds/shape-geometry.js +224 -0
- package/dist/esm/components/embeds/shape-svg.d.ts +56 -0
- package/dist/esm/components/embeds/shape-svg.d.ts.map +1 -0
- package/dist/esm/components/embeds/shape-svg.js +149 -0
- package/dist/esm/components/embeds/slicer-component.d.ts +27 -0
- package/dist/esm/components/embeds/slicer-component.d.ts.map +1 -0
- package/dist/esm/components/embeds/slicer-component.js +231 -0
- package/dist/esm/components/fill-handle/index.d.ts +7 -0
- package/dist/esm/components/fill-handle/index.d.ts.map +1 -0
- package/dist/esm/components/fill-handle/index.js +13 -0
- package/dist/esm/components/filter-box/filter-by-color.d.ts +28 -0
- package/dist/esm/components/filter-box/filter-by-color.d.ts.map +1 -0
- package/dist/esm/components/filter-box/filter-by-color.js +88 -0
- package/dist/esm/components/filter-box/filter-by-condition.d.ts +13 -0
- package/dist/esm/components/filter-box/filter-by-condition.d.ts.map +1 -0
- package/dist/esm/components/filter-box/filter-by-condition.js +34 -0
- package/dist/esm/components/filter-box/filter-by-value.d.ts +9 -0
- package/dist/esm/components/filter-box/filter-by-value.d.ts.map +1 -0
- package/dist/esm/components/filter-box/filter-by-value.js +76 -0
- package/dist/esm/components/filter-box/index.d.ts +50 -0
- package/dist/esm/components/filter-box/index.d.ts.map +1 -0
- package/dist/esm/components/filter-box/index.js +337 -0
- package/dist/esm/components/floating-cell-editor/index.d.ts +83 -0
- package/dist/esm/components/floating-cell-editor/index.d.ts.map +1 -0
- package/dist/esm/components/floating-cell-editor/index.js +168 -0
- package/dist/esm/components/formula-bar/index.d.ts +11 -0
- package/dist/esm/components/formula-bar/index.d.ts.map +1 -0
- package/dist/esm/components/formula-bar/index.js +14 -0
- package/dist/esm/components/formula-bar/style.d.ts +4 -0
- package/dist/esm/components/formula-bar/style.d.ts.map +1 -0
- package/dist/esm/components/formula-bar/style.js +6 -0
- package/dist/esm/components/formula-input/index.d.ts +17 -0
- package/dist/esm/components/formula-input/index.d.ts.map +1 -0
- package/dist/esm/components/formula-input/index.js +85 -0
- package/dist/esm/components/grid-footer/index.d.ts +14 -0
- package/dist/esm/components/grid-footer/index.d.ts.map +1 -0
- package/dist/esm/components/grid-footer/index.js +33 -0
- package/dist/esm/components/header-cell/index.d.ts +10 -0
- package/dist/esm/components/header-cell/index.d.ts.map +1 -0
- package/dist/esm/components/header-cell/index.js +21 -0
- package/dist/esm/components/header-menu/index.d.ts +13 -0
- package/dist/esm/components/header-menu/index.d.ts.map +1 -0
- package/dist/esm/components/header-menu/index.js +13 -0
- package/dist/esm/components/header-move/index.d.ts +23 -0
- package/dist/esm/components/header-move/index.d.ts.map +1 -0
- package/dist/esm/components/header-move/index.js +48 -0
- package/dist/esm/components/header-resizer/index.d.ts +19 -0
- package/dist/esm/components/header-resizer/index.d.ts.map +1 -0
- package/dist/esm/components/header-resizer/index.js +33 -0
- package/dist/esm/components/hidden-markers/index.d.ts +15 -0
- package/dist/esm/components/hidden-markers/index.d.ts.map +1 -0
- package/dist/esm/components/hidden-markers/index.js +39 -0
- package/dist/esm/components/hidden-markers/style.d.ts +5 -0
- package/dist/esm/components/hidden-markers/style.d.ts.map +1 -0
- package/dist/esm/components/hidden-markers/style.js +4 -0
- package/dist/esm/components/insert-function-dialog/index.d.ts +32 -0
- package/dist/esm/components/insert-function-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/insert-function-dialog/index.js +75 -0
- package/dist/esm/components/loading-indicator/index.d.ts +7 -0
- package/dist/esm/components/loading-indicator/index.d.ts.map +1 -0
- package/dist/esm/components/loading-indicator/index.js +8 -0
- package/dist/esm/components/outline-gutter/index.d.ts +44 -0
- package/dist/esm/components/outline-gutter/index.d.ts.map +1 -0
- package/dist/esm/components/outline-gutter/index.js +395 -0
- package/dist/esm/components/pivot-placeholder/index.d.ts +12 -0
- package/dist/esm/components/pivot-placeholder/index.d.ts.map +1 -0
- package/dist/esm/components/pivot-placeholder/index.js +18 -0
- package/dist/esm/components/print-preview/cell-styles.d.ts +18 -0
- package/dist/esm/components/print-preview/cell-styles.d.ts.map +1 -0
- package/dist/esm/components/print-preview/cell-styles.js +174 -0
- package/dist/esm/components/print-preview/index.d.ts +5 -0
- package/dist/esm/components/print-preview/index.d.ts.map +1 -0
- package/dist/esm/components/print-preview/index.js +2 -0
- package/dist/esm/components/print-preview/page-block.d.ts +62 -0
- package/dist/esm/components/print-preview/page-block.d.ts.map +1 -0
- package/dist/esm/components/print-preview/page-block.js +308 -0
- package/dist/esm/components/print-preview/print-preview-dialog.d.ts +49 -0
- package/dist/esm/components/print-preview/print-preview-dialog.d.ts.map +1 -0
- package/dist/esm/components/print-preview/print-preview-dialog.js +322 -0
- package/dist/esm/components/print-preview/run-print.d.ts +11 -0
- package/dist/esm/components/print-preview/run-print.d.ts.map +1 -0
- package/dist/esm/components/print-preview/run-print.js +107 -0
- package/dist/esm/components/print-preview/settings.d.ts +130 -0
- package/dist/esm/components/print-preview/settings.d.ts.map +1 -0
- package/dist/esm/components/print-preview/settings.js +227 -0
- package/dist/esm/components/print-preview/use-page-layout.d.ts +60 -0
- package/dist/esm/components/print-preview/use-page-layout.d.ts.map +1 -0
- package/dist/esm/components/print-preview/use-page-layout.js +133 -0
- package/dist/esm/components/range-selector/index.d.ts +25 -0
- package/dist/esm/components/range-selector/index.d.ts.map +1 -0
- package/dist/esm/components/range-selector/index.js +236 -0
- package/dist/esm/components/resizer/index.d.ts +9 -0
- package/dist/esm/components/resizer/index.d.ts.map +1 -0
- package/dist/esm/components/resizer/index.js +39 -0
- package/dist/esm/components/selection/avatar.d.ts +14 -0
- package/dist/esm/components/selection/avatar.d.ts.map +1 -0
- package/dist/esm/components/selection/avatar.js +15 -0
- package/dist/esm/components/selection/index.d.ts +9 -0
- package/dist/esm/components/selection/index.d.ts.map +1 -0
- package/dist/esm/components/selection/index.js +192 -0
- package/dist/esm/components/selection/magic-fill.d.ts +26 -0
- package/dist/esm/components/selection/magic-fill.d.ts.map +1 -0
- package/dist/esm/components/selection/magic-fill.js +52 -0
- package/dist/esm/components/selection/paste-menu.d.ts +10 -0
- package/dist/esm/components/selection/paste-menu.d.ts.map +1 -0
- package/dist/esm/components/selection/paste-menu.js +29 -0
- package/dist/esm/components/selection/quick-edit.d.ts +14 -0
- package/dist/esm/components/selection/quick-edit.d.ts.map +1 -0
- package/dist/esm/components/selection/quick-edit.js +41 -0
- package/dist/esm/components/selection/style.d.ts +15 -0
- package/dist/esm/components/selection/style.d.ts.map +1 -0
- package/dist/esm/components/selection/style.js +22 -0
- package/dist/esm/components/selection/suggestion-action.d.ts +22 -0
- package/dist/esm/components/selection/suggestion-action.d.ts.map +1 -0
- package/dist/esm/components/selection/suggestion-action.js +53 -0
- package/dist/esm/components/selection/title.d.ts +45 -0
- package/dist/esm/components/selection/title.d.ts.map +1 -0
- package/dist/esm/components/selection/title.js +95 -0
- package/dist/esm/components/selection/types.d.ts +43 -0
- package/dist/esm/components/selection/types.d.ts.map +1 -0
- package/dist/esm/components/selection/types.js +1 -0
- package/dist/esm/components/selection-input/index.d.ts +19 -0
- package/dist/esm/components/selection-input/index.d.ts.map +1 -0
- package/dist/esm/components/selection-input/index.js +27 -0
- package/dist/esm/components/selection-input/style.d.ts +3 -0
- package/dist/esm/components/selection-input/style.d.ts.map +1 -0
- package/dist/esm/components/selection-input/style.js +4 -0
- package/dist/esm/components/sheet-search/index.d.ts +41 -0
- package/dist/esm/components/sheet-search/index.d.ts.map +1 -0
- package/dist/esm/components/sheet-search/index.js +106 -0
- package/dist/esm/components/sheet-status/index.d.ts +40 -0
- package/dist/esm/components/sheet-status/index.d.ts.map +1 -0
- package/dist/esm/components/sheet-status/index.js +155 -0
- package/dist/esm/components/sheet-status/style.d.ts +4 -0
- package/dist/esm/components/sheet-status/style.d.ts.map +1 -0
- package/dist/esm/components/sheet-status/style.js +7 -0
- package/dist/esm/components/sheet-switcher/index.d.ts +12 -0
- package/dist/esm/components/sheet-switcher/index.d.ts.map +1 -0
- package/dist/esm/components/sheet-switcher/index.js +33 -0
- package/dist/esm/components/sheet-switcher/new-sheet-button.d.ts +4 -0
- package/dist/esm/components/sheet-switcher/new-sheet-button.d.ts.map +1 -0
- package/dist/esm/components/sheet-switcher/new-sheet-button.js +7 -0
- package/dist/esm/components/sheet-tabs/context-menu.d.ts +43 -0
- package/dist/esm/components/sheet-tabs/context-menu.d.ts.map +1 -0
- package/dist/esm/components/sheet-tabs/context-menu.js +50 -0
- package/dist/esm/components/sheet-tabs/index.d.ts +18 -0
- package/dist/esm/components/sheet-tabs/index.d.ts.map +1 -0
- package/dist/esm/components/sheet-tabs/index.js +217 -0
- package/dist/esm/components/sheet-tabs/sheet-tab.d.ts +21 -0
- package/dist/esm/components/sheet-tabs/sheet-tab.d.ts.map +1 -0
- package/dist/esm/components/sheet-tabs/sheet-tab.js +131 -0
- package/dist/esm/components/sheet-tabs/style.d.ts +10 -0
- package/dist/esm/components/sheet-tabs/style.d.ts.map +1 -0
- package/dist/esm/components/sheet-tabs/style.js +16 -0
- package/dist/esm/components/sheet-tabs/types.d.ts +45 -0
- package/dist/esm/components/sheet-tabs/types.d.ts.map +1 -0
- package/dist/esm/components/sheet-tabs/types.js +1 -0
- package/dist/esm/components/sort-range-dialog/index.d.ts +66 -0
- package/dist/esm/components/sort-range-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/sort-range-dialog/index.js +215 -0
- package/dist/esm/components/toolbar/background-color-selector.d.ts +19 -0
- package/dist/esm/components/toolbar/background-color-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/background-color-selector.js +28 -0
- package/dist/esm/components/toolbar/border-color-selector.d.ts +18 -0
- package/dist/esm/components/toolbar/border-color-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/border-color-selector.js +25 -0
- package/dist/esm/components/toolbar/border-line-style-options.d.ts +9 -0
- package/dist/esm/components/toolbar/border-line-style-options.d.ts.map +1 -0
- package/dist/esm/components/toolbar/border-line-style-options.js +42 -0
- package/dist/esm/components/toolbar/border-line-style-selector.d.ts +9 -0
- package/dist/esm/components/toolbar/border-line-style-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/border-line-style-selector.js +19 -0
- package/dist/esm/components/toolbar/border-location-options.d.ts +11 -0
- package/dist/esm/components/toolbar/border-location-options.d.ts.map +1 -0
- package/dist/esm/components/toolbar/border-location-options.js +64 -0
- package/dist/esm/components/toolbar/border-selector.d.ts +20 -0
- package/dist/esm/components/toolbar/border-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/border-selector.js +59 -0
- package/dist/esm/components/toolbar/buttons.d.ts +55 -0
- package/dist/esm/components/toolbar/buttons.d.ts.map +1 -0
- package/dist/esm/components/toolbar/buttons.js +165 -0
- package/dist/esm/components/toolbar/cell-style-selector.d.ts +25 -0
- package/dist/esm/components/toolbar/cell-style-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/cell-style-selector.js +521 -0
- package/dist/esm/components/toolbar/color-selector.d.ts +13 -0
- package/dist/esm/components/toolbar/color-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/color-selector.js +52 -0
- package/dist/esm/components/toolbar/font-family-selector.d.ts +22 -0
- package/dist/esm/components/toolbar/font-family-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/font-family-selector.js +167 -0
- package/dist/esm/components/toolbar/font-size-selector.d.ts +10 -0
- package/dist/esm/components/toolbar/font-size-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/font-size-selector.js +139 -0
- package/dist/esm/components/toolbar/index.d.ts +25 -0
- package/dist/esm/components/toolbar/index.d.ts.map +1 -0
- package/dist/esm/components/toolbar/index.js +24 -0
- package/dist/esm/components/toolbar/insert-menu.d.ts +22 -0
- package/dist/esm/components/toolbar/insert-menu.d.ts.map +1 -0
- package/dist/esm/components/toolbar/insert-menu.js +143 -0
- package/dist/esm/components/toolbar/merge-cells-selector.d.ts +15 -0
- package/dist/esm/components/toolbar/merge-cells-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/merge-cells-selector.js +48 -0
- package/dist/esm/components/toolbar/scale-selector.d.ts +13 -0
- package/dist/esm/components/toolbar/scale-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/scale-selector.js +72 -0
- package/dist/esm/components/toolbar/style.d.ts +3 -0
- package/dist/esm/components/toolbar/style.d.ts.map +1 -0
- package/dist/esm/components/toolbar/style.js +5 -0
- package/dist/esm/components/toolbar/table-actions.d.ts +15 -0
- package/dist/esm/components/toolbar/table-actions.d.ts.map +1 -0
- package/dist/esm/components/toolbar/table-actions.js +37 -0
- package/dist/esm/components/toolbar/table-style-selector.d.ts +25 -0
- package/dist/esm/components/toolbar/table-style-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/table-style-selector.js +501 -0
- package/dist/esm/components/toolbar/text-color-selector.d.ts +20 -0
- package/dist/esm/components/toolbar/text-color-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/text-color-selector.js +28 -0
- package/dist/esm/components/toolbar/text-format-selector.d.ts +23 -0
- package/dist/esm/components/toolbar/text-format-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/text-format-selector.js +257 -0
- package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts +10 -0
- package/dist/esm/components/toolbar/text-horizontal-align-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/text-horizontal-align-selector.js +36 -0
- package/dist/esm/components/toolbar/text-vertical-align-selector.d.ts +9 -0
- package/dist/esm/components/toolbar/text-vertical-align-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/text-vertical-align-selector.js +36 -0
- package/dist/esm/components/toolbar/text-wrap-selector.d.ts +9 -0
- package/dist/esm/components/toolbar/text-wrap-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/text-wrap-selector.js +35 -0
- package/dist/esm/components/toolbar/theme-selector.d.ts +10 -0
- package/dist/esm/components/toolbar/theme-selector.d.ts.map +1 -0
- package/dist/esm/components/toolbar/theme-selector.js +27 -0
- package/dist/esm/components/toolbar/toolbar.d.ts +12 -0
- package/dist/esm/components/toolbar/toolbar.d.ts.map +1 -0
- package/dist/esm/components/toolbar/toolbar.js +133 -0
- package/dist/esm/components/toolbar/types.d.ts +2 -0
- package/dist/esm/components/toolbar/types.d.ts.map +1 -0
- package/dist/esm/components/toolbar/types.js +1 -0
- package/dist/esm/components/toolbar/view-menu.d.ts +25 -0
- package/dist/esm/components/toolbar/view-menu.d.ts.map +1 -0
- package/dist/esm/components/toolbar/view-menu.js +41 -0
- package/dist/esm/components/validation-alert-dialog/index.d.ts +15 -0
- package/dist/esm/components/validation-alert-dialog/index.d.ts.map +1 -0
- package/dist/esm/components/validation-alert-dialog/index.js +63 -0
- package/dist/esm/config.d.ts +107 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +266 -0
- package/dist/esm/helpers/merged-cell-borders.d.ts +26 -0
- package/dist/esm/helpers/merged-cell-borders.d.ts.map +1 -0
- package/dist/esm/helpers/merged-cell-borders.js +42 -0
- package/dist/esm/helpers.d.ts +118 -0
- package/dist/esm/helpers.d.ts.map +1 -0
- package/dist/esm/helpers.js +455 -0
- package/dist/esm/hooks/index.d.ts +11 -0
- package/dist/esm/hooks/index.d.ts.map +1 -0
- package/dist/esm/hooks/index.js +10 -0
- package/dist/esm/hooks/show-zeros.d.ts +13 -0
- package/dist/esm/hooks/show-zeros.d.ts.map +1 -0
- package/dist/esm/hooks/show-zeros.js +19 -0
- package/dist/esm/hooks/use-async.d.ts +2 -0
- package/dist/esm/hooks/use-async.d.ts.map +1 -0
- package/dist/esm/hooks/use-async.js +22 -0
- package/dist/esm/hooks/use-border-styles.d.ts +31 -0
- package/dist/esm/hooks/use-border-styles.d.ts.map +1 -0
- package/dist/esm/hooks/use-border-styles.js +423 -0
- package/dist/esm/hooks/use-callback-ref.d.ts +6 -0
- package/dist/esm/hooks/use-callback-ref.d.ts.map +1 -0
- package/dist/esm/hooks/use-callback-ref.js +15 -0
- package/dist/esm/hooks/use-cell-diff-highlight.d.ts +43 -0
- package/dist/esm/hooks/use-cell-diff-highlight.d.ts.map +1 -0
- package/dist/esm/hooks/use-cell-diff-highlight.js +84 -0
- package/dist/esm/hooks/use-cell-popover.d.ts +55 -0
- package/dist/esm/hooks/use-cell-popover.d.ts.map +1 -0
- package/dist/esm/hooks/use-cell-popover.js +91 -0
- package/dist/esm/hooks/use-cell-renderer.d.ts +226 -0
- package/dist/esm/hooks/use-cell-renderer.d.ts.map +1 -0
- package/dist/esm/hooks/use-cell-renderer.js +372 -0
- package/dist/esm/hooks/use-column-color-icons.d.ts +43 -0
- package/dist/esm/hooks/use-column-color-icons.d.ts.map +1 -0
- package/dist/esm/hooks/use-column-color-icons.js +83 -0
- package/dist/esm/hooks/use-conditional-formatting.d.ts +35 -0
- package/dist/esm/hooks/use-conditional-formatting.d.ts.map +1 -0
- package/dist/esm/hooks/use-conditional-formatting.js +497 -0
- package/dist/esm/hooks/use-context-menu.d.ts +52 -0
- package/dist/esm/hooks/use-context-menu.d.ts.map +1 -0
- package/dist/esm/hooks/use-context-menu.js +75 -0
- package/dist/esm/hooks/use-context-setter.d.ts +3 -0
- package/dist/esm/hooks/use-context-setter.d.ts.map +1 -0
- package/dist/esm/hooks/use-context-setter.js +128 -0
- package/dist/esm/hooks/use-copy-paste-cut.d.ts +45 -0
- package/dist/esm/hooks/use-copy-paste-cut.d.ts.map +1 -0
- package/dist/esm/hooks/use-copy-paste-cut.js +253 -0
- package/dist/esm/hooks/use-create-address-from-selection.d.ts +15 -0
- package/dist/esm/hooks/use-create-address-from-selection.d.ts.map +1 -0
- package/dist/esm/hooks/use-create-address-from-selection.js +69 -0
- package/dist/esm/hooks/use-create-formula-tokenizer.d.ts +15 -0
- package/dist/esm/hooks/use-create-formula-tokenizer.d.ts.map +1 -0
- package/dist/esm/hooks/use-create-formula-tokenizer.js +48 -0
- package/dist/esm/hooks/use-delayed-value.d.ts +8 -0
- package/dist/esm/hooks/use-delayed-value.d.ts.map +1 -0
- package/dist/esm/hooks/use-delayed-value.js +30 -0
- package/dist/esm/hooks/use-editable.d.ts +366 -0
- package/dist/esm/hooks/use-editable.d.ts.map +1 -0
- package/dist/esm/hooks/use-editable.js +803 -0
- package/dist/esm/hooks/use-editor-cancel.d.ts +25 -0
- package/dist/esm/hooks/use-editor-cancel.d.ts.map +1 -0
- package/dist/esm/hooks/use-editor-cancel.js +45 -0
- package/dist/esm/hooks/use-editor-change.d.ts +13 -0
- package/dist/esm/hooks/use-editor-change.d.ts.map +1 -0
- package/dist/esm/hooks/use-editor-change.js +67 -0
- package/dist/esm/hooks/use-editor-keydown.d.ts +11 -0
- package/dist/esm/hooks/use-editor-keydown.d.ts.map +1 -0
- package/dist/esm/hooks/use-editor-keydown.js +42 -0
- package/dist/esm/hooks/use-editor-submit.d.ts +58 -0
- package/dist/esm/hooks/use-editor-submit.d.ts.map +1 -0
- package/dist/esm/hooks/use-editor-submit.js +83 -0
- package/dist/esm/hooks/use-embeds-charts.d.ts +193 -0
- package/dist/esm/hooks/use-embeds-charts.d.ts.map +1 -0
- package/dist/esm/hooks/use-embeds-charts.js +276 -0
- package/dist/esm/hooks/use-expand-cell.d.ts +35 -0
- package/dist/esm/hooks/use-expand-cell.d.ts.map +1 -0
- package/dist/esm/hooks/use-expand-cell.js +46 -0
- package/dist/esm/hooks/use-export-range.d.ts +36 -0
- package/dist/esm/hooks/use-export-range.d.ts.map +1 -0
- package/dist/esm/hooks/use-export-range.js +227 -0
- package/dist/esm/hooks/use-filter.d.ts +46 -0
- package/dist/esm/hooks/use-filter.d.ts.map +1 -0
- package/dist/esm/hooks/use-filter.js +184 -0
- package/dist/esm/hooks/use-flash.d.ts +18 -0
- package/dist/esm/hooks/use-flash.d.ts.map +1 -0
- package/dist/esm/hooks/use-flash.js +68 -0
- package/dist/esm/hooks/use-fonts.d.ts +8 -0
- package/dist/esm/hooks/use-fonts.d.ts.map +1 -0
- package/dist/esm/hooks/use-fonts.js +14 -0
- package/dist/esm/hooks/use-formula-range-helpers.d.ts +21 -0
- package/dist/esm/hooks/use-formula-range-helpers.d.ts.map +1 -0
- package/dist/esm/hooks/use-formula-range-helpers.js +60 -0
- package/dist/esm/hooks/use-get-tooltip.d.ts +52 -0
- package/dist/esm/hooks/use-get-tooltip.d.ts.map +1 -0
- package/dist/esm/hooks/use-get-tooltip.js +57 -0
- package/dist/esm/hooks/use-get-values-from-range.d.ts +44 -0
- package/dist/esm/hooks/use-get-values-from-range.d.ts.map +1 -0
- package/dist/esm/hooks/use-get-values-from-range.js +108 -0
- package/dist/esm/hooks/use-grid-children.d.ts +31 -0
- package/dist/esm/hooks/use-grid-children.d.ts.map +1 -0
- package/dist/esm/hooks/use-grid-children.js +129 -0
- package/dist/esm/hooks/use-header-actions.d.ts +70 -0
- package/dist/esm/hooks/use-header-actions.d.ts.map +1 -0
- package/dist/esm/hooks/use-header-actions.js +248 -0
- package/dist/esm/hooks/use-hidden-dimension-markers.d.ts +20 -0
- package/dist/esm/hooks/use-hidden-dimension-markers.d.ts.map +1 -0
- package/dist/esm/hooks/use-hidden-dimension-markers.js +128 -0
- package/dist/esm/hooks/use-hidden-dimensions.d.ts +7 -0
- package/dist/esm/hooks/use-hidden-dimensions.d.ts.map +1 -0
- package/dist/esm/hooks/use-hidden-dimensions.js +56 -0
- package/dist/esm/hooks/use-hovered-selection-ids.d.ts +9 -0
- package/dist/esm/hooks/use-hovered-selection-ids.d.ts.map +1 -0
- package/dist/esm/hooks/use-hovered-selection-ids.js +25 -0
- package/dist/esm/hooks/use-isomorphic-layout-effect.d.ts +6 -0
- package/dist/esm/hooks/use-isomorphic-layout-effect.d.ts.map +1 -0
- package/dist/esm/hooks/use-isomorphic-layout-effect.js +8 -0
- package/dist/esm/hooks/use-keyboard-handler.d.ts +57 -0
- package/dist/esm/hooks/use-keyboard-handler.d.ts.map +1 -0
- package/dist/esm/hooks/use-keyboard-handler.js +472 -0
- package/dist/esm/hooks/use-licensekey-validator.d.ts +16 -0
- package/dist/esm/hooks/use-licensekey-validator.d.ts.map +1 -0
- package/dist/esm/hooks/use-licensekey-validator.js +140 -0
- package/dist/esm/hooks/use-memo-compare.d.ts +2 -0
- package/dist/esm/hooks/use-memo-compare.d.ts.map +1 -0
- package/dist/esm/hooks/use-memo-compare.js +13 -0
- package/dist/esm/hooks/use-merge.refs.d.ts +4 -0
- package/dist/esm/hooks/use-merge.refs.d.ts.map +1 -0
- package/dist/esm/hooks/use-merge.refs.js +16 -0
- package/dist/esm/hooks/use-move-columns-rows.d.ts +46 -0
- package/dist/esm/hooks/use-move-columns-rows.d.ts.map +1 -0
- package/dist/esm/hooks/use-move-columns-rows.js +333 -0
- package/dist/esm/hooks/use-navigate-sheet-range.d.ts +16 -0
- package/dist/esm/hooks/use-navigate-sheet-range.d.ts.map +1 -0
- package/dist/esm/hooks/use-navigate-sheet-range.js +30 -0
- package/dist/esm/hooks/use-previous.d.ts +3 -0
- package/dist/esm/hooks/use-previous.d.ts.map +1 -0
- package/dist/esm/hooks/use-previous.js +9 -0
- package/dist/esm/hooks/use-raf.d.ts +6 -0
- package/dist/esm/hooks/use-raf.d.ts.map +1 -0
- package/dist/esm/hooks/use-raf.js +27 -0
- package/dist/esm/hooks/use-resize-observer.d.ts +6 -0
- package/dist/esm/hooks/use-resize-observer.d.ts.map +1 -0
- package/dist/esm/hooks/use-resize-observer.js +40 -0
- package/dist/esm/hooks/use-scale-listener.d.ts +11 -0
- package/dist/esm/hooks/use-scale-listener.d.ts.map +1 -0
- package/dist/esm/hooks/use-scale-listener.js +47 -0
- package/dist/esm/hooks/use-selected-rows-columns.d.ts +21 -0
- package/dist/esm/hooks/use-selected-rows-columns.d.ts.map +1 -0
- package/dist/esm/hooks/use-selected-rows-columns.js +69 -0
- package/dist/esm/hooks/use-selection-aware-formatting.d.ts +13 -0
- package/dist/esm/hooks/use-selection-aware-formatting.d.ts.map +1 -0
- package/dist/esm/hooks/use-selection-aware-formatting.js +39 -0
- package/dist/esm/hooks/use-selection-change.d.ts +10 -0
- package/dist/esm/hooks/use-selection-change.d.ts.map +1 -0
- package/dist/esm/hooks/use-selection-change.js +57 -0
- package/dist/esm/hooks/use-selection-interceptors.d.ts +34 -0
- package/dist/esm/hooks/use-selection-interceptors.d.ts.map +1 -0
- package/dist/esm/hooks/use-selection-interceptors.js +129 -0
- package/dist/esm/hooks/use-selection-move.d.ts +31 -0
- package/dist/esm/hooks/use-selection-move.d.ts.map +1 -0
- package/dist/esm/hooks/use-selection-move.js +136 -0
- package/dist/esm/hooks/use-selection-renderer.d.ts +46 -0
- package/dist/esm/hooks/use-selection-renderer.d.ts.map +1 -0
- package/dist/esm/hooks/use-selection-renderer.js +139 -0
- package/dist/esm/hooks/use-selection-resize.d.ts +30 -0
- package/dist/esm/hooks/use-selection-resize.d.ts.map +1 -0
- package/dist/esm/hooks/use-selection-resize.js +160 -0
- package/dist/esm/hooks/use-selection.d.ts +185 -0
- package/dist/esm/hooks/use-selection.d.ts.map +1 -0
- package/dist/esm/hooks/use-selection.js +1559 -0
- package/dist/esm/hooks/use-sheet-change-handler.d.ts +3 -0
- package/dist/esm/hooks/use-sheet-change-handler.d.ts.map +1 -0
- package/dist/esm/hooks/use-sheet-change-handler.js +33 -0
- package/dist/esm/hooks/use-sizer.d.ts +164 -0
- package/dist/esm/hooks/use-sizer.d.ts.map +1 -0
- package/dist/esm/hooks/use-sizer.js +357 -0
- package/dist/esm/hooks/use-spreadsheet-theme.d.ts +17 -0
- package/dist/esm/hooks/use-spreadsheet-theme.d.ts.map +1 -0
- package/dist/esm/hooks/use-spreadsheet-theme.js +50 -0
- package/dist/esm/hooks/use-stable-ref.d.ts +2 -0
- package/dist/esm/hooks/use-stable-ref.d.ts.map +1 -0
- package/dist/esm/hooks/use-stable-ref.js +10 -0
- package/dist/esm/hooks/use-structured-reference-selection.d.ts +23 -0
- package/dist/esm/hooks/use-structured-reference-selection.d.ts.map +1 -0
- package/dist/esm/hooks/use-structured-reference-selection.js +118 -0
- package/dist/esm/hooks/use-table-resizer.d.ts +23 -0
- package/dist/esm/hooks/use-table-resizer.d.ts.map +1 -0
- package/dist/esm/hooks/use-table-resizer.js +108 -0
- package/dist/esm/hooks/use-text-dimensions.d.ts +16 -0
- package/dist/esm/hooks/use-text-dimensions.d.ts.map +1 -0
- package/dist/esm/hooks/use-text-dimensions.js +35 -0
- package/dist/esm/hooks/use-tooltip.d.ts +70 -0
- package/dist/esm/hooks/use-tooltip.d.ts.map +1 -0
- package/dist/esm/hooks/use-tooltip.js +83 -0
- package/dist/esm/hooks/use-touch.d.ts +16 -0
- package/dist/esm/hooks/use-touch.d.ts.map +1 -0
- package/dist/esm/hooks/use-touch.js +224 -0
- package/dist/esm/index.d.ts +69 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +75 -0
- package/dist/esm/providers/spreadsheet-provider.d.ts +25 -0
- package/dist/esm/providers/spreadsheet-provider.d.ts.map +1 -0
- package/dist/esm/providers/spreadsheet-provider.js +27 -0
- package/dist/esm/release-date.d.ts +2 -0
- package/dist/esm/release-date.d.ts.map +1 -0
- package/dist/esm/release-date.js +3 -0
- package/dist/esm/signals/scroll-subscriber.d.ts +4 -0
- package/dist/esm/signals/scroll-subscriber.d.ts.map +1 -0
- package/dist/esm/signals/scroll-subscriber.js +2 -0
- package/dist/esm/test-setup.d.ts +2 -0
- package/dist/esm/test-setup.d.ts.map +1 -0
- package/dist/esm/test-setup.js +15 -0
- package/dist/esm/themes.d.ts +13 -0
- package/dist/esm/themes.d.ts.map +1 -0
- package/dist/esm/themes.js +264 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/esm/types.d.ts +1215 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +8 -0
- package/dist/esm/utils/maybe.d.ts +12 -0
- package/dist/esm/utils/maybe.d.ts.map +1 -0
- package/dist/esm/utils/maybe.js +14 -0
- package/dist/esm/vitest.config.d.ts +3 -0
- package/dist/esm/vitest.config.d.ts.map +1 -0
- package/dist/esm/vitest.config.js +22 -0
- package/dist/spreadsheet.min.css +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,3260 @@
|
|
|
1
|
+
import { tokenize as defaultFormulaTokenizer } from "@rowsncolumns/calculator";
|
|
2
|
+
import { Direction, isAreasEqual } from "@rowsncolumns/grid";
|
|
3
|
+
import { canUseDOM } from "@rowsncolumns/grid";
|
|
4
|
+
import { getBoundedCells, MouseButtonCodes } from "@rowsncolumns/grid";
|
|
5
|
+
import { isCellWithinBounds } from "@rowsncolumns/grid";
|
|
6
|
+
import { cellIdentifier, Grid as BaseGrid, isEqualCells, } from "@rowsncolumns/grid";
|
|
7
|
+
import { defaultCellCoords } from "@rowsncolumns/spreadsheet-state";
|
|
8
|
+
import { cn, Skeleton, tryParseRichText } from "@rowsncolumns/ui";
|
|
9
|
+
import { cellToAddress, getCellEffectiveFormat, getContrastColor, isConditionalFormatFormulaRule, isDataValidationFormulaRule, isNil, isNilOrBlank, iterateCellsInRange, log, ssfFormatColor, uuid, } from "@rowsncolumns/utils";
|
|
10
|
+
import { useStore } from "jotai";
|
|
11
|
+
import merge from "lodash/merge";
|
|
12
|
+
import throttle from "lodash/throttle";
|
|
13
|
+
import React, { forwardRef, memo, startTransition, useCallback, useMemo, useRef, useState, } from "react";
|
|
14
|
+
import { getBandedCells } from "../../api/banded-ranges";
|
|
15
|
+
import { CF_INITIAL_WINDOW, cfWindowForViewport, isSameCfWindow, } from "../../api/cf-window";
|
|
16
|
+
import { generateSelectionsFromFormula } from "../../api/selections";
|
|
17
|
+
import { SpreadsheetApi } from "../../api/spreadsheet-api";
|
|
18
|
+
import { findActiveTableWithinCell } from "../../api/table";
|
|
19
|
+
import { checkBooleanRule, decideValidationCommit, isCellLockedUnderProtection, isProtectedCell, isProtectedSheet, showValidationDropdownArrow, } from "../../api/validation";
|
|
20
|
+
import { useFormulaModeValue, useSetNoteEditorCell, useSetPinnedTooltip, useShowPasteMenu, useShowValidationAlert, } from "../../atoms";
|
|
21
|
+
import { useActiveEditor } from "../../atoms/active-editor.atom";
|
|
22
|
+
import { useEditingCell } from "../../atoms/editing-cell.atom";
|
|
23
|
+
import { useCellEditorInstance, useSetFormulabarEditorValue, useSetFormulaBarTextFormatRuns, } from "../../atoms/formula-bar-editor-value.atom";
|
|
24
|
+
import { useFormulaCanSelectCells, useFormulaSelectionMode, useSetFormulaSelectionState, } from "../../atoms/formula-selection-state.atom";
|
|
25
|
+
import { useFormulaSelections } from "../../atoms/formula-selections.atom";
|
|
26
|
+
import { useQuickEditState } from "../../atoms/magic-fill-state.atom";
|
|
27
|
+
import { useOnHideFormulaHelp, useOnShowFormulaHelp, useShowFormulaHelpValue, } from "../../atoms/show-formula-help.atom";
|
|
28
|
+
import { useSetSpreadsheetApi } from "../../atoms/spreadsheet-api.atom";
|
|
29
|
+
import { ARROW_DOWN_WIDTH, CALCULATED_ICON_WIDTH, CELL_HORIZONTAL_ALIGNMENT, CF_ICON_SPACING, CF_ICON_WIDTH, CHIP_COLOR, CHIP_SPACING, COLUMN_HEADER_HEIGHT, DEFAULT_ACTIVE_CELL, DEFAULT_ARRAY, DEFAULT_CELL_BACKGROUND_COLOR, DEFAULT_CELL_COLOR, DEFAULT_CELL_SPACING, DEFAULT_COLUMN_COUNT, DEFAULT_COLUMN_WIDTH, DEFAULT_FONT_SIZE_PT, DEFAULT_HEADER_ACTIVE_BG, DEFAULT_HEADER_ACTIVE_TABLE_BG, DEFAULT_HEADER_BG, DEFAULT_HEADER_BORDER_COLOR, DEFAULT_HEADER_COLOR, DEFAULT_HEADER_SELECTED_BG, DEFAULT_HEADER_SELECTED_TABLE_BG, DEFAULT_HEADER_TABLE_BG, DEFAULT_ROW_COUNT, DEFAULT_ROW_HEIGHT, DEFAULT_SCROLL_POSITION, DEFAULT_TEXT_FORMAT, defaultSpreadsheetTheme, EXPAND_COLLAPSE_ICON_WIDTH, FILTER_ICON_WIDTH, GRIDLINE_COLOR, HEADER_TEXT_FORMAT, INDENT_SPACING, MAX_COLUMN_COUNT, MAX_ROW_COUNT, MIN_COLUMN_WIDTH, ROW_HEADER_WIDTH, SCROLLBAR_SIZE, SELECTION_BG, SELECTION_BORDER, } from "../../config";
|
|
30
|
+
import { definedProps, getCellEffectiveValue, getCellFormattedValue, getCellUserEnteredValue, getDefaultColumnHeader, getDefaultRowHeader, getExtendedValueBool, getExtendedValueError, getExtendedValueFormula, getExtendedValueNumber, getExtendedValueString, getTableHeaderCells, isFirefox, isStyleReference, isTouchDevice, } from "../../helpers";
|
|
31
|
+
import { useBorderStyles } from "../../hooks/use-border-styles";
|
|
32
|
+
import { useCallbackRef } from "../../hooks/use-callback-ref";
|
|
33
|
+
import { useCellPopover } from "../../hooks/use-cell-popover";
|
|
34
|
+
import { useCellRenderer } from "../../hooks/use-cell-renderer";
|
|
35
|
+
import { useConditionalFormatting } from "../../hooks/use-conditional-formatting";
|
|
36
|
+
import { DefaultContextMenuWrapper, useContextMenu, } from "../../hooks/use-context-menu";
|
|
37
|
+
import { useContextSetter } from "../../hooks/use-context-setter";
|
|
38
|
+
import { useCopyPasteCut } from "../../hooks/use-copy-paste-cut";
|
|
39
|
+
import { useCreateAddressFromSelection } from "../../hooks/use-create-address-from-selection";
|
|
40
|
+
import { useCreateFormulaTokenizer } from "../../hooks/use-create-formula-tokenizer";
|
|
41
|
+
import { useEditable } from "../../hooks/use-editable";
|
|
42
|
+
import { useEditorCancel } from "../../hooks/use-editor-cancel";
|
|
43
|
+
import { useEditorChange } from "../../hooks/use-editor-change";
|
|
44
|
+
import { useEditorKeydown } from "../../hooks/use-editor-keydown";
|
|
45
|
+
import { useEditorSubmit } from "../../hooks/use-editor-submit";
|
|
46
|
+
import { useEmbedsCharts } from "../../hooks/use-embeds-charts";
|
|
47
|
+
import { useExpandCell } from "../../hooks/use-expand-cell";
|
|
48
|
+
import { useExportRange } from "../../hooks/use-export-range";
|
|
49
|
+
import { useFilter } from "../../hooks/use-filter";
|
|
50
|
+
import { useFlash } from "../../hooks/use-flash";
|
|
51
|
+
import { useGetTooltip } from "../../hooks/use-get-tooltip";
|
|
52
|
+
import { useGetValuesFromRange } from "../../hooks/use-get-values-from-range";
|
|
53
|
+
import { useGridChildren } from "../../hooks/use-grid-children";
|
|
54
|
+
import { useHeaderActions } from "../../hooks/use-header-actions";
|
|
55
|
+
import { useHiddenDimensionMarkers } from "../../hooks/use-hidden-dimension-markers";
|
|
56
|
+
import { useHiddenDimensions } from "../../hooks/use-hidden-dimensions";
|
|
57
|
+
import { useHoveredSelectionIds } from "../../hooks/use-hovered-selection-ids";
|
|
58
|
+
import { useIsomorphicLayoutEffect } from "../../hooks/use-isomorphic-layout-effect";
|
|
59
|
+
import { useKeyboardHandler } from "../../hooks/use-keyboard-handler";
|
|
60
|
+
import { useLicenseKeyValidator } from "../../hooks/use-licensekey-validator";
|
|
61
|
+
import { useMoveColumnsAndRows } from "../../hooks/use-move-columns-rows";
|
|
62
|
+
import { useNavigateToSheetRange } from "../../hooks/use-navigate-sheet-range";
|
|
63
|
+
import { useRaf } from "../../hooks/use-raf";
|
|
64
|
+
import { useResizeObserver } from "../../hooks/use-resize-observer";
|
|
65
|
+
import { useScaleListener } from "../../hooks/use-scale-listener";
|
|
66
|
+
import { useSelectedRowsColumns } from "../../hooks/use-selected-rows-columns";
|
|
67
|
+
import { useSelection } from "../../hooks/use-selection";
|
|
68
|
+
import { useSelectionChange } from "../../hooks/use-selection-change";
|
|
69
|
+
import { useSelectionInterceptors } from "../../hooks/use-selection-interceptors";
|
|
70
|
+
import { useSelectionMove } from "../../hooks/use-selection-move";
|
|
71
|
+
import { useSelectionRenderer } from "../../hooks/use-selection-renderer";
|
|
72
|
+
import { useSelectionResize } from "../../hooks/use-selection-resize";
|
|
73
|
+
import { useSheetChangeHandler } from "../../hooks/use-sheet-change-handler";
|
|
74
|
+
import { useSizer } from "../../hooks/use-sizer";
|
|
75
|
+
import { useStableRef } from "../../hooks/use-stable-ref";
|
|
76
|
+
import { useOnStructuredReferenceSelection } from "../../hooks/use-structured-reference-selection";
|
|
77
|
+
import { useTableResizer } from "../../hooks/use-table-resizer";
|
|
78
|
+
import { useDelayedValue } from "../../hooks/use-delayed-value";
|
|
79
|
+
import { useTooltip } from "../../hooks/use-tooltip";
|
|
80
|
+
import { useTouch } from "../../hooks/use-touch";
|
|
81
|
+
import { multiInstanceStore } from "../../providers/spreadsheet-provider";
|
|
82
|
+
import { scrollSubscriber } from "../../signals/scroll-subscriber";
|
|
83
|
+
import { getStringifiedColor } from "../../themes";
|
|
84
|
+
import { Cell as DefaultCell } from "../cell";
|
|
85
|
+
import { CellEditor as DefaultCellEditor } from "../cell-editor";
|
|
86
|
+
import { ContextMenu as DefaultContextMenu } from "../context-menu";
|
|
87
|
+
import { FillHandle } from "../fill-handle";
|
|
88
|
+
import { FilterBox as DefaultFilterBox } from "../filter-box";
|
|
89
|
+
import { HeaderCell as DefaultHeaderCell } from "../header-cell";
|
|
90
|
+
import { HeaderMoveDragComponent as DefaultHeaderMoveDragComponent } from "../header-move";
|
|
91
|
+
import { PivotPlaceholder } from "../pivot-placeholder";
|
|
92
|
+
import { SelectionTitle } from "../selection/title";
|
|
93
|
+
import { StructuredResultRenderer as DefaultStructuredResult } from "./../cell-structured";
|
|
94
|
+
import { getNestedPropertyNames } from "./helpers";
|
|
95
|
+
/**
|
|
96
|
+
* CanvasGrid Component
|
|
97
|
+
* @param ShetGridProps
|
|
98
|
+
* @param CanvasGridMethods
|
|
99
|
+
* @returns
|
|
100
|
+
*/
|
|
101
|
+
function CanvasGridComponent(props, forwardedRef) {
|
|
102
|
+
const { licenseKey, sheetId, instanceId, activeCell = DEFAULT_ACTIVE_CELL, selections = DEFAULT_ARRAY, frozenColumnCount = 0, frozenRowCount = 0, rowCount = DEFAULT_ROW_COUNT, columnCount = DEFAULT_COLUMN_COUNT, autoFocus, basicFilter, tables, namedRanges, bandedRanges = DEFAULT_ARRAY, tableBorderColor = "#008000", filterIconColor = "#008000", conditionalFormats, showFilterIcon = true, showCalculatedColumnIcon = true, showHeaders = true, defaultColumnWidth = DEFAULT_COLUMN_WIDTH, defaultRowHeight = DEFAULT_ROW_HEIGHT, columnHeaderHeight = COLUMN_HEADER_HEIGHT, rowHeaderWidth = ROW_HEADER_WIDTH, gridLineColor = GRIDLINE_COLOR, cellBackgroundColor = DEFAULT_CELL_BACKGROUND_COLOR, cellColor = DEFAULT_CELL_COLOR, headerBorderColor = DEFAULT_HEADER_BORDER_COLOR, headerBackgroundColor = DEFAULT_HEADER_BG, headerColor = DEFAULT_HEADER_COLOR, headerActiveBackgroundColor = DEFAULT_HEADER_ACTIVE_BG, headerSelectedBackgroundColor = DEFAULT_HEADER_SELECTED_BG, headerSelectedColor = "white", headerTableBackgroundColor = DEFAULT_HEADER_TABLE_BG, headerTableActiveBackgroundColor = DEFAULT_HEADER_ACTIVE_TABLE_BG, headerTableSelectedBackgroundColor = DEFAULT_HEADER_SELECTED_TABLE_BG, frozenShadowColor = headerBorderColor, frozenShadowThickness = 1, selectionBackgroundColor = SELECTION_BG, selectionBorderColor = SELECTION_BORDER, selectionDragBorderColor = SELECTION_BORDER, chartSelectedColor, chipBackgroundColor = CHIP_COLOR, merges = DEFAULT_ARRAY, borderStyles, protectedRanges, isWorkbookProtected: isWorkbookProtectedProp = false, getSheetProtection, pivotTables, charts, embeds, slicers, rowMetadata = DEFAULT_ARRAY, columnMetadata = DEFAULT_ARRAY, scale = 1, zoomSpeed = 1, overscanCount = 3, enableEditOnEnterKey = true, enableTextOverflow = true, showGridLines: _showGridLines, showFormulas = false, protectFormulas = false, showFrozenSeparator = true, HeaderCell = DefaultHeaderCell, Cell = DefaultCell, SelectionTitleComponent = SelectionTitle, CellEditor = DefaultCellEditor, CellTooltip, ContextMenu = DefaultContextMenu, ContextMenuWrapper = DefaultContextMenuWrapper, FilterBox = DefaultFilterBox, HeaderMoveDragComponent = DefaultHeaderMoveDragComponent, SuggestionsDropdown, stickyEditor = true, scrollSnap = false, scrollThrottleTimeout, preventBrowserDefaultScroll, mouseMoveThrottleTimeout = 60, tooltipIntentInterval = 60, selectionPolicy, users, userId, renderCollaboratorCursor, functionDescriptions, showHeaderMenuButton = true, scrollbarSize = SCROLLBAR_SIZE, theme = defaultSpreadsheetTheme, showNotes = true, showComments = true, locale, agentSuggestions, onReviewSuggestion, onShowFormulas, getDataRowCount, getChartComponent, getEmbedComponent, getSlicerComponent, onChange, onChangeBatch, onExpandCollapse, onPivotDrillDown, onDelete, onChangeEditorValue, onFill, onRequestCalculate, onChangeActiveCell, onChangeActiveSheet, onChangeSelections, getSheetName, getSheetId, getCellData, getNote: getNoteProp, getTextFormatRuns, getDataValidation, getEffectiveFormat, getFormattedValue: getFormattedValueProp, getTooltipContent, errorResolutionComponent, getEffectiveValue: getEffectiveValueProp, getUserEnteredExtendedValue, getEffectiveExtendedValue, getSheetRowCount, getSheetColumnCount, getCellPopoverContent, onScroll, onViewPortChange, windowConditionalFormats = false, engineConditionalFormatResults = false, onResize, onAutoResize, onHideColumn, onHideRow, onShowColumn, onShowRow, onGroupRows, onUngroupRows, onCollapseRowGroup, onExpandRowGroup, onGroupColumns, onUngroupColumns, onCollapseColumnGroup, onExpandColumnGroup, onSetOutlineDepth, onDeleteRow, onDeleteColumn, onInsertRow, onInsertColumn, onInsertCellsShiftDown, onInsertCellsShiftRight, onDeleteCellsShiftLeft, onDeleteCellsShiftUp, onClearContents, onMoveColumns, onMoveRows, onSelectNextSheet, onSelectPreviousSheet, onCreateNewSheet, onKeyDown, onChangeFormatting, onRepeatFormatting, onClearFormatting, onRequestEditProtectedRange, onMoveChart, onResizeChart, onDeleteChart, onMoveEmbed, onResizeEmbed, onDeleteEmbed, onRequestEditEmbed, onMoveSlicer, onResizeSlicer, onDeleteSlicer, onRequestEditSlicer, onFillRange, disableFillRightShortcut, onMoveSelection, onInsertTime, onInsertDate, onInsertDateTime, onInsertAutoSum, onUndo, onRedo, onPaste, onCopy, onCut, onSortColumn, onSortTable, onFilterTable, onFilterPivot, onResizeTable, onRequestEditTable, onRequestEditPivotTable, onRequestDeletePivotTable, onRemoveTable, onCreateTable, onInsertTableColumn, onDeleteTableColumn, onInsertTableRow, onDeleteTableRow, onCreateBasicFilter, onRequestDefineNamedRange, onRequestFormatCells, onRequestConditionalFormat, onRequestDataValidation, onRequestInsertComment, onRequestInsertLink, onFreezeColumn, onFreezeRow, onUpdateNote, onProtectRange, onUnProtectRange, onSortRange, onRequestSearch, onRequestReplace, onRequestResize, getRowHeaderText = getDefaultRowHeader, getColumnHeaderText = getDefaultColumnHeader, getAdditionalCellSpacing, tokenizer: defaultTokenizer = defaultFormulaTokenizer, onChangeScale, onRemoveLink, onSelectLink, onSplitTextToColumns, onRemoveDuplicates, onRequestExpand, cellExpandPredicate, StructuredResult = DefaultStructuredResult, getMentions, getStructuredProperties: getStructuredPropertiesProp, getFunctionParameterSuggestions, shouldFetchFunctionParameters, MentionTagComponent, MentionDropdownItemComponent, showSelectionResizeHandles = true, enableMagicFill, enableQuickEdit = true, MagicFillComponent, MagicFillContent, QuickEdit, PasteMenu, SuggestionAction, HiddenRowMarkers, HiddenColumnMarkers, enableResizerOverflow, className, defaultFontSizePoint = DEFAULT_FONT_SIZE_PT, readonly, isComparing = false, getCellDiff, enableDataBoundaryNavigation, footerHeight, footerComponent, arrowComponents,
|
|
103
|
+
// Host-driven filter props. `hostHiddenRowRanges`
|
|
104
|
+
// supplies compact [start, end] hidden-row tuples; `getFilterValues` supplies a
|
|
105
|
+
// column's distinct values. Both let a million-row filter render without scanning
|
|
106
|
+
// or materializing per-row state. Destructured here so they're excluded from
|
|
107
|
+
// `...rest` (never spread onto BaseGrid).
|
|
108
|
+
hostHiddenRowRanges, getFilterValues, getFilterColors,
|
|
109
|
+
// Optional full-store per-cell reader for data-validation source ranges (dropdown
|
|
110
|
+
// options + commit-time checks). Windowed hosts supply an off-window-safe reader;
|
|
111
|
+
// defaults to `getFormattedValue` inside `useGetValuesFromRange`.
|
|
112
|
+
getValidationSourceValue,
|
|
113
|
+
// Unused props only for api
|
|
114
|
+
onChangeBorder, onDuplicateSheet, onCreateConditionalFormattingRule, onDeleteConditionalFormattingRule, onUpdateConditionalFormattingRule, onCreateDataValidationRule, onUpdateDataValidationRule, onDeleteDataValidationRule, onCreateChart, onDeleteSheet, onCreateEmbed, onDecreaseIndent, onIncreaseIndent, onChangeTheme, onChangeDecimals, onUpdateSheet, onChangeBatchStream, onBlur, ...rest } = props;
|
|
115
|
+
/**
|
|
116
|
+
* Fire onBlur only when the cell editor blurs to an element outside the
|
|
117
|
+
* spreadsheet. Routed through `useEditable` so we hook the always-focused
|
|
118
|
+
* cell editor rather than relying on descendant blur bubbling.
|
|
119
|
+
*/
|
|
120
|
+
const handleEditorBlur = useCallback((e, isEditing) => {
|
|
121
|
+
if (gridContainerRef.current?.contains(e.relatedTarget)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
onBlur?.(e, isEditing);
|
|
125
|
+
}, [onBlur]);
|
|
126
|
+
const showGridLines = _showGridLines ?? true;
|
|
127
|
+
const gridRef = useRef(null);
|
|
128
|
+
// Hovered cell state (immediate, updated on mousemove)
|
|
129
|
+
const [hoveredCell, setHoveredCell] = useState();
|
|
130
|
+
// Delayed hovered cell for tooltips and selection titles
|
|
131
|
+
const delayedHoveredCell = useDelayedValue(hoveredCell, tooltipIntentInterval);
|
|
132
|
+
// Text overflow functionality
|
|
133
|
+
// Store overflow width AND the x-offset of the cell to avoid recalculating on scroll
|
|
134
|
+
const overflowMapRef = useRef(new Map());
|
|
135
|
+
// Calculate overflow buffer JIT to avoid re-renders
|
|
136
|
+
const getOverflowBuffer = useCallback((scrollLeft) => {
|
|
137
|
+
const map = overflowMapRef.current;
|
|
138
|
+
let maxBuffer = 0;
|
|
139
|
+
for (const { width, x: cellX } of map.values()) {
|
|
140
|
+
// Check if the overflowing content intersects with the viewport
|
|
141
|
+
if (cellX < scrollLeft && cellX + width > scrollLeft) {
|
|
142
|
+
const requiredBuffer = scrollLeft - cellX;
|
|
143
|
+
if (requiredBuffer > maxBuffer) {
|
|
144
|
+
maxBuffer = requiredBuffer;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return maxBuffer;
|
|
149
|
+
}, []);
|
|
150
|
+
// Get frozen column cells that overflow into the body area
|
|
151
|
+
// These need to be rendered in the body cells so the overflow scrolls with the body
|
|
152
|
+
// Caches the previous Set and returns the same reference when membership is unchanged
|
|
153
|
+
// so downstream consumers can rely on referential equality.
|
|
154
|
+
const frozenColumnOverflowCellsRef = useRef(new Set());
|
|
155
|
+
const getFrozenColumnOverflowCells = useCallback((frozenColumnWidth, frozenCols) => {
|
|
156
|
+
const map = overflowMapRef.current;
|
|
157
|
+
const next = new Set();
|
|
158
|
+
for (const [cellId, { width, x: cellX }] of map.entries()) {
|
|
159
|
+
// cellIdentifier format: "rowIndex,columnIndex"
|
|
160
|
+
const [, colStr] = cellId.split(",");
|
|
161
|
+
const columnIndex = parseInt(colStr, 10);
|
|
162
|
+
// Only include cells in frozen columns that overflow beyond the frozen boundary
|
|
163
|
+
if (columnIndex < frozenCols && cellX + width > frozenColumnWidth) {
|
|
164
|
+
next.add(cellId);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const prev = frozenColumnOverflowCellsRef.current;
|
|
168
|
+
if (prev.size === next.size) {
|
|
169
|
+
let same = true;
|
|
170
|
+
for (const id of next) {
|
|
171
|
+
if (!prev.has(id)) {
|
|
172
|
+
same = false;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (same)
|
|
177
|
+
return prev;
|
|
178
|
+
}
|
|
179
|
+
frozenColumnOverflowCellsRef.current = next;
|
|
180
|
+
return next;
|
|
181
|
+
}, []);
|
|
182
|
+
// Show formula help dropdown
|
|
183
|
+
const showFormulaHelp = useShowFormulaHelpValue();
|
|
184
|
+
const onHideFormulaHelp = useOnHideFormulaHelp();
|
|
185
|
+
const onShowFormulaHelp = useOnShowFormulaHelp();
|
|
186
|
+
// Cell editor
|
|
187
|
+
const cellEditorInstance = useCellEditorInstance();
|
|
188
|
+
// Paste menu
|
|
189
|
+
const [showPasteMenu, setShowPasteMenu] = useShowPasteMenu();
|
|
190
|
+
// Shared state
|
|
191
|
+
const formulaMode = useFormulaModeValue();
|
|
192
|
+
const formulaSelections = useFormulaSelections();
|
|
193
|
+
const [editingCellCoordinate, setEditingCellCoordinate] = useEditingCell();
|
|
194
|
+
const setFormulabarEditorValue = useSetFormulabarEditorValue();
|
|
195
|
+
const setFormulaBarTextFormatRuns = useSetFormulaBarTextFormatRuns();
|
|
196
|
+
const canSelectCells = useFormulaCanSelectCells();
|
|
197
|
+
const selectionMode = useFormulaSelectionMode();
|
|
198
|
+
const setFormulaState = useSetFormulaSelectionState();
|
|
199
|
+
const activeEditor = useActiveEditor();
|
|
200
|
+
// Magic fill state
|
|
201
|
+
const [quickEditValues, setQuickEditState] = useQuickEditState();
|
|
202
|
+
const setNoteEditorCell = useSetNoteEditorCell();
|
|
203
|
+
const setPinnedTooltip = useSetPinnedTooltip();
|
|
204
|
+
const setSpreadsheetApi = useSetSpreadsheetApi();
|
|
205
|
+
const propsReferenceRef = useRef(null);
|
|
206
|
+
const lastScheduledScrollRef = useRef(0);
|
|
207
|
+
// Spreadsheet jotai store
|
|
208
|
+
const store = useStore();
|
|
209
|
+
const instanceStore = useStore({ store: multiInstanceStore });
|
|
210
|
+
// To access closures
|
|
211
|
+
const hoveredCellRef = useStableRef(hoveredCell);
|
|
212
|
+
const [gridContainerRef, { width, height }] = useResizeObserver();
|
|
213
|
+
const defaultFrozenDims = showHeaders ? 1 : 0;
|
|
214
|
+
const frozenRows = Math.max(defaultFrozenDims, (frozenRowCount ?? 0) + defaultFrozenDims);
|
|
215
|
+
const frozenColumns = Math.max(defaultFrozenDims, (frozenColumnCount ?? 0) + defaultFrozenDims);
|
|
216
|
+
const selectionTopBound = 1;
|
|
217
|
+
const selectionLeftBound = 1;
|
|
218
|
+
const fillHandleSize = 8;
|
|
219
|
+
// Clamp to max allowable columns/rows in excel
|
|
220
|
+
// Rows start with zero index. Header is considered 1 row. Hence + 1
|
|
221
|
+
const sheetRowCount = Math.min(MAX_ROW_COUNT + 1, rowCount + 1);
|
|
222
|
+
const sheetColumnCount = Math.min(MAX_COLUMN_COUNT + 1, columnCount + 1);
|
|
223
|
+
// License key validator
|
|
224
|
+
const [_, licenseType, validatorResult] = useLicenseKeyValidator({
|
|
225
|
+
licenseKey,
|
|
226
|
+
});
|
|
227
|
+
const isRestricted = licenseType === "solo";
|
|
228
|
+
// Grid line width
|
|
229
|
+
const gridLineWidth = 1 * scale;
|
|
230
|
+
// When sheet is changed, we have to scroll to the last saved scroll
|
|
231
|
+
// position of the sheet
|
|
232
|
+
// It can happen that user switched to a sheet
|
|
233
|
+
// And triggered a scroll to a cell in an inactive sheet
|
|
234
|
+
// scrollToCell() + onChangeActiveSheet()
|
|
235
|
+
// This triggers multiple scrolls, one that happens immediately and another in useEffect
|
|
236
|
+
// So we check if introduce a simple hack to check if there is enough interval
|
|
237
|
+
// between scrollToCell and sheet-change scroll
|
|
238
|
+
const isSheetScrollScheduled = useCallback(() => {
|
|
239
|
+
return Date.now() - lastScheduledScrollRef.current > 100;
|
|
240
|
+
}, []);
|
|
241
|
+
// Get sheet dimensions
|
|
242
|
+
const getSheetDimensions = useCallbackRef(useCallback(() => {
|
|
243
|
+
return [
|
|
244
|
+
width - scrollbarSize - rowHeaderWidth,
|
|
245
|
+
height - scrollbarSize - columnHeaderHeight,
|
|
246
|
+
];
|
|
247
|
+
}, [width, height, rowHeaderWidth, columnHeaderHeight, scrollbarSize]));
|
|
248
|
+
// Row header
|
|
249
|
+
const isRowHeader = useCallback((columnIndex) => columnIndex === 0, []);
|
|
250
|
+
// Column header header
|
|
251
|
+
const isColumnHeader = useCallback((rowIndex) => rowIndex === 0, []);
|
|
252
|
+
/**
|
|
253
|
+
* Hidden rows for
|
|
254
|
+
* Used for basicFilter + tables + manual show hide of cols/rows
|
|
255
|
+
*/
|
|
256
|
+
// When the host supplies the basic filter's hidden
|
|
257
|
+
// body-row ranges as compact sorted [start, end] (inclusive, grid row-index space)
|
|
258
|
+
// tuples, derive row-hidden state via binary search instead of materializing a
|
|
259
|
+
// per-row `hiddenByFilter` flag for every hidden row in `rowMetadata`. This lets a
|
|
260
|
+
// million-row filter render without ~1M rowMetadata entries. `undefined` = host is
|
|
261
|
+
// not driving filter visibility, so the original `rowMetadata.hiddenByFilter` path
|
|
262
|
+
// is used unchanged.
|
|
263
|
+
const isRowHiddenByHostFilter = useCallback((rowIndex) => {
|
|
264
|
+
const ranges = hostHiddenRowRanges;
|
|
265
|
+
if (!ranges) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
let lo = 0;
|
|
269
|
+
let hi = ranges.length - 1;
|
|
270
|
+
while (lo <= hi) {
|
|
271
|
+
const mid = (lo + hi) >> 1;
|
|
272
|
+
const range = ranges[mid];
|
|
273
|
+
if (rowIndex < range[0]) {
|
|
274
|
+
hi = mid - 1;
|
|
275
|
+
}
|
|
276
|
+
else if (rowIndex > range[1]) {
|
|
277
|
+
lo = mid + 1;
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return false;
|
|
284
|
+
}, [hostHiddenRowRanges]);
|
|
285
|
+
const isHiddenRow = useCallback((rowIndex) => {
|
|
286
|
+
if (isColumnHeader(rowIndex)) {
|
|
287
|
+
return !showHeaders;
|
|
288
|
+
}
|
|
289
|
+
// Host filter ranges replace per-row hiddenByFilter when supplied.
|
|
290
|
+
if (hostHiddenRowRanges) {
|
|
291
|
+
return !!(isRowHiddenByHostFilter(rowIndex) ||
|
|
292
|
+
rowMetadata?.[rowIndex]?.hiddenByUser ||
|
|
293
|
+
rowMetadata?.[rowIndex]?.hiddenByGroup);
|
|
294
|
+
}
|
|
295
|
+
return !!(rowMetadata?.[rowIndex]?.hiddenByFilter ||
|
|
296
|
+
rowMetadata?.[rowIndex]?.hiddenByUser ||
|
|
297
|
+
rowMetadata?.[rowIndex]?.hiddenByGroup);
|
|
298
|
+
}, [
|
|
299
|
+
rowMetadata,
|
|
300
|
+
isColumnHeader,
|
|
301
|
+
showHeaders,
|
|
302
|
+
hostHiddenRowRanges,
|
|
303
|
+
isRowHiddenByHostFilter,
|
|
304
|
+
]);
|
|
305
|
+
/**
|
|
306
|
+
* Check if a row is hidden by filter
|
|
307
|
+
*/
|
|
308
|
+
const isHiddenRowByFilter = useCallback((rowIndex) => {
|
|
309
|
+
if (isColumnHeader(rowIndex)) {
|
|
310
|
+
return !showHeaders;
|
|
311
|
+
}
|
|
312
|
+
// Host filter ranges replace per-row hiddenByFilter when supplied.
|
|
313
|
+
if (hostHiddenRowRanges) {
|
|
314
|
+
return isRowHiddenByHostFilter(rowIndex);
|
|
315
|
+
}
|
|
316
|
+
return !!rowMetadata?.[rowIndex]?.hiddenByFilter;
|
|
317
|
+
}, [
|
|
318
|
+
rowMetadata,
|
|
319
|
+
isColumnHeader,
|
|
320
|
+
showHeaders,
|
|
321
|
+
hostHiddenRowRanges,
|
|
322
|
+
isRowHiddenByHostFilter,
|
|
323
|
+
]);
|
|
324
|
+
/**
|
|
325
|
+
* For hidden columns
|
|
326
|
+
* Grid skips rendering gridlines and cell rendering
|
|
327
|
+
* Used for basicFilter + tables + manual show hide of cols/rows
|
|
328
|
+
*/
|
|
329
|
+
const isHiddenColumn = useCallback((columnIndex) => {
|
|
330
|
+
if (isRowHeader(columnIndex)) {
|
|
331
|
+
return !showHeaders;
|
|
332
|
+
}
|
|
333
|
+
return !!(columnMetadata?.[columnIndex]?.hiddenByFilter ||
|
|
334
|
+
columnMetadata?.[columnIndex]?.hiddenByUser ||
|
|
335
|
+
columnMetadata?.[columnIndex]?.hiddenByGroup);
|
|
336
|
+
}, [columnMetadata, isRowHeader, showHeaders]);
|
|
337
|
+
/**
|
|
338
|
+
* Compute visible row ranges for efficient Grid iteration.
|
|
339
|
+
* Instead of checking isHiddenRow for each row (O(n)),
|
|
340
|
+
* we compute ranges from the sparse rowMetadata (O(h log h) where h = hidden rows).
|
|
341
|
+
*/
|
|
342
|
+
const visibleRowRanges = useMemo(() => {
|
|
343
|
+
// When the host supplies compact filter-hidden
|
|
344
|
+
// ranges, build visible ranges by complementing them merged with the SPARSE
|
|
345
|
+
// user/group hides — no per-row hiddenByFilter materialization, so a million-row
|
|
346
|
+
// filter doesn't allocate ~1M rowMetadata entries.
|
|
347
|
+
if (hostHiddenRowRanges) {
|
|
348
|
+
const hidden = [];
|
|
349
|
+
for (const range of hostHiddenRowRanges) {
|
|
350
|
+
hidden.push([range[0], range[1]]);
|
|
351
|
+
}
|
|
352
|
+
for (const key of Object.keys(rowMetadata ?? {})) {
|
|
353
|
+
const i = Number(key);
|
|
354
|
+
if (rowMetadata?.[i]?.hiddenByUser || rowMetadata?.[i]?.hiddenByGroup) {
|
|
355
|
+
hidden.push([i, i]);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
hidden.sort((a, b) => a[0] - b[0]);
|
|
359
|
+
const visible = [];
|
|
360
|
+
let cursor = 0;
|
|
361
|
+
for (const [s, e] of hidden) {
|
|
362
|
+
if (s > cursor) {
|
|
363
|
+
visible.push({ start: cursor, end: s - 1 });
|
|
364
|
+
}
|
|
365
|
+
cursor = Math.max(cursor, e + 1);
|
|
366
|
+
}
|
|
367
|
+
if (cursor <= sheetRowCount - 1) {
|
|
368
|
+
visible.push({ start: cursor, end: sheetRowCount - 1 });
|
|
369
|
+
}
|
|
370
|
+
return visible.length ? visible : [{ start: 0, end: sheetRowCount - 1 }];
|
|
371
|
+
}
|
|
372
|
+
// Get sorted hidden row indices from rowMetadata. Must include
|
|
373
|
+
// `hiddenByGroup` (outline collapse) — without it BaseGrid skips
|
|
374
|
+
// the row-iteration fast path and still calls the cell renderer
|
|
375
|
+
// with height=0, which makes overlays like conditional-format icon
|
|
376
|
+
// sets stack on top of each other at the collapse boundary.
|
|
377
|
+
const hiddenRows = Object.keys(rowMetadata ?? {})
|
|
378
|
+
.map(Number)
|
|
379
|
+
.filter((i) => rowMetadata?.[i]?.hiddenByFilter ||
|
|
380
|
+
rowMetadata?.[i]?.hiddenByUser ||
|
|
381
|
+
rowMetadata?.[i]?.hiddenByGroup)
|
|
382
|
+
.sort((a, b) => a - b);
|
|
383
|
+
// Use `sheetRowCount - 1` (not `rowCount - 1`) as the upper bound.
|
|
384
|
+
// BaseGrid is fed `sheetRowCount = rowCount + 1` so index 0 can hold
|
|
385
|
+
// the column-header row; data rows shift to 1..rowCount. Capping at
|
|
386
|
+
// `rowCount - 1` here drops the last data row from the visible
|
|
387
|
+
// ranges — BaseGrid is told the slot exists but `getVisibleRowIndices`
|
|
388
|
+
// never emits it, so the renderer skips it and selections that clamp
|
|
389
|
+
// to that index hang in empty space below the last painted row.
|
|
390
|
+
if (hiddenRows.length === 0) {
|
|
391
|
+
return [{ start: 0, end: sheetRowCount - 1 }];
|
|
392
|
+
}
|
|
393
|
+
// Build visible ranges from gaps between hidden rows
|
|
394
|
+
const ranges = [];
|
|
395
|
+
let prevEnd = -1;
|
|
396
|
+
for (const hiddenRow of hiddenRows) {
|
|
397
|
+
if (hiddenRow > prevEnd + 1) {
|
|
398
|
+
ranges.push({ start: prevEnd + 1, end: hiddenRow - 1 });
|
|
399
|
+
}
|
|
400
|
+
prevEnd = hiddenRow;
|
|
401
|
+
}
|
|
402
|
+
// Add final range if there are visible rows after the last hidden row
|
|
403
|
+
if (prevEnd < sheetRowCount - 1) {
|
|
404
|
+
ranges.push({ start: prevEnd + 1, end: sheetRowCount - 1 });
|
|
405
|
+
}
|
|
406
|
+
return ranges;
|
|
407
|
+
}, [hostHiddenRowRanges, rowMetadata, sheetRowCount]);
|
|
408
|
+
/**
|
|
409
|
+
* The pivot table (if any) whose output range covers a cell on the
|
|
410
|
+
* given sheet. Used to make pivot output read-only and to offer the
|
|
411
|
+
* drill-down context-menu action.
|
|
412
|
+
*/
|
|
413
|
+
const getPivotTableAtCell = useCallback((sheetId, rowIndex, columnIndex) => pivotTables?.find((pv) => pv.pivotRange?.sheetId === sheetId &&
|
|
414
|
+
isCellWithinBounds({ rowIndex, columnIndex }, pv.pivotRange)), [pivotTables]);
|
|
415
|
+
/**
|
|
416
|
+
* Worksheet-protection lookup, identity-stable so it can ride the grid
|
|
417
|
+
* context without churning it on re-renders.
|
|
418
|
+
*/
|
|
419
|
+
const getSheetProtectionStable = useCallbackRef(getSheetProtection);
|
|
420
|
+
/**
|
|
421
|
+
* Check if the cell can be edited
|
|
422
|
+
*/
|
|
423
|
+
const canEditCell = useCallbackRef(useCallback((sheetId, cell) => {
|
|
424
|
+
// Readonly mode
|
|
425
|
+
if (readonly) {
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
const { rowIndex, columnIndex } = cell;
|
|
429
|
+
if (isRowHeader(columnIndex) || isColumnHeader(rowIndex)) {
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
// Pivot output is read-only in Excel — you can't type into a
|
|
433
|
+
// pivot cell. Treat every cell inside a pivot range as
|
|
434
|
+
// non-editable; mutations happen through the pivot editor.
|
|
435
|
+
if (getPivotTableAtCell(sheetId, rowIndex, columnIndex)) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
// Excel worksheet protection: while `<sheetProtection sheet>` is
|
|
439
|
+
// active, LOCKED cells refuse edits — a cell is locked unless its
|
|
440
|
+
// `protection.locked` is `false` (Excel's default) — and unlocked
|
|
441
|
+
// cells stay editable.
|
|
442
|
+
const lockedBySheetProtection = isCellLockedUnderProtection(getSheetProtection?.(sheetId), getCellData?.(sheetId, rowIndex, columnIndex)?.protection);
|
|
443
|
+
const canEdit = !lockedBySheetProtection &&
|
|
444
|
+
(protectedRanges
|
|
445
|
+
? !isProtectedCell(sheetId, cell, protectedRanges)
|
|
446
|
+
: true);
|
|
447
|
+
// User is trying to edit a protected cell
|
|
448
|
+
if (!canEdit) {
|
|
449
|
+
onRequestEditProtectedRange?.(sheetId, cell);
|
|
450
|
+
}
|
|
451
|
+
return canEdit;
|
|
452
|
+
}, [
|
|
453
|
+
readonly,
|
|
454
|
+
protectedRanges,
|
|
455
|
+
getSheetProtection,
|
|
456
|
+
getCellData,
|
|
457
|
+
isRowHeader,
|
|
458
|
+
isColumnHeader,
|
|
459
|
+
onRequestEditProtectedRange,
|
|
460
|
+
getPivotTableAtCell,
|
|
461
|
+
]));
|
|
462
|
+
/**
|
|
463
|
+
* Can edit sheet
|
|
464
|
+
*/
|
|
465
|
+
const isSheetProtected = useCallbackRef(useCallback((sheetId) => {
|
|
466
|
+
// Protected sheet
|
|
467
|
+
if (readonly) {
|
|
468
|
+
return true;
|
|
469
|
+
}
|
|
470
|
+
return isProtectedSheet(sheetId, protectedRanges ?? undefined);
|
|
471
|
+
}, [protectedRanges, readonly]));
|
|
472
|
+
/**
|
|
473
|
+
* Workbook-level structural protection. Readonly mode implies
|
|
474
|
+
* workbook protection too — nothing structural should mutate.
|
|
475
|
+
*/
|
|
476
|
+
const isWorkbookProtected = useCallbackRef(useCallback(() => readonly || isWorkbookProtectedProp, [readonly, isWorkbookProtectedProp]));
|
|
477
|
+
// Active sheet tables
|
|
478
|
+
const activeTables = useMemo(() => tables?.filter((table) => table.sheetId === sheetId), [tables, sheetId]);
|
|
479
|
+
/**
|
|
480
|
+
* Get filter header cells for both
|
|
481
|
+
* basicFilter + tables
|
|
482
|
+
*/
|
|
483
|
+
const tableHeaderCells = useMemo(() => {
|
|
484
|
+
return getTableHeaderCells(activeTables, basicFilter);
|
|
485
|
+
}, [activeTables, basicFilter]);
|
|
486
|
+
/**
|
|
487
|
+
* Retrieve banded cells
|
|
488
|
+
*/
|
|
489
|
+
const bandedCells = useMemo(() => {
|
|
490
|
+
return getBandedCells((bandedRanges ?? undefined) || [], theme, sheetId, isHiddenRow, isHiddenColumn);
|
|
491
|
+
}, [bandedRanges, theme, sheetId, isHiddenRow, isHiddenColumn]);
|
|
492
|
+
/**
|
|
493
|
+
* Focus active editor
|
|
494
|
+
*/
|
|
495
|
+
const focusActiveEditor = useCallback((moveSelectionToEnd = true) => {
|
|
496
|
+
if (!activeEditor) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
// Slate editor looses focus on Formula bar input otherwise
|
|
500
|
+
// Edit: Remove scheduleNormalPriorityCallback(() => {
|
|
501
|
+
activeEditor?.focus(moveSelectionToEnd);
|
|
502
|
+
}, [activeEditor]);
|
|
503
|
+
/**
|
|
504
|
+
* Scroll to cell in the grid
|
|
505
|
+
* @param cell
|
|
506
|
+
* @returns
|
|
507
|
+
*/
|
|
508
|
+
const scrollToCell = useCallback((cell, align) => {
|
|
509
|
+
lastScheduledScrollRef.current = Date.now();
|
|
510
|
+
gridRef.current?.scrollToCell(cell, align);
|
|
511
|
+
}, []);
|
|
512
|
+
/**
|
|
513
|
+
* Scroll to bottom of the sheet
|
|
514
|
+
*/
|
|
515
|
+
const scrollToBottom = useCallback(() => {
|
|
516
|
+
gridRef.current?.scrollToBottom();
|
|
517
|
+
}, []);
|
|
518
|
+
/**
|
|
519
|
+
* Get current grid ref
|
|
520
|
+
*/
|
|
521
|
+
const getGridRef = useCallback(() => gridRef.current, []);
|
|
522
|
+
/**
|
|
523
|
+
* Redraws a grid
|
|
524
|
+
*/
|
|
525
|
+
const redrawGrid = useCallback(() => {
|
|
526
|
+
gridRef.current?.redrawGrid();
|
|
527
|
+
}, []);
|
|
528
|
+
/**
|
|
529
|
+
* Scroll to a portion of the grid
|
|
530
|
+
*/
|
|
531
|
+
const scrollTo = useCallback((scrollCoords, immediate) => gridRef.current?.scrollTo(scrollCoords, immediate), []);
|
|
532
|
+
/**
|
|
533
|
+
* Get Absolute position (to document)
|
|
534
|
+
*/
|
|
535
|
+
const getAbsolutePositionFromOffset = useCallback((x, y) => gridRef.current?.getAbsolutePositionFromOffset(x, y), []);
|
|
536
|
+
/**
|
|
537
|
+
* Get row offset
|
|
538
|
+
*/
|
|
539
|
+
const getRowOffset = useCallback((rowIndex) => gridRef.current?.getRowOffset(rowIndex) ?? 0, []);
|
|
540
|
+
/**
|
|
541
|
+
* Get column offset
|
|
542
|
+
*/
|
|
543
|
+
const getColumnOffset = useCallback((columnIndex) => gridRef.current?.getColumnOffset(columnIndex) ?? 0, []);
|
|
544
|
+
// Handle text overflow
|
|
545
|
+
const handleOverflow = useCallback((rowIndex, columnIndex, overflow) => {
|
|
546
|
+
const id = cellIdentifier(rowIndex, columnIndex);
|
|
547
|
+
const map = overflowMapRef.current;
|
|
548
|
+
const current = map.get(id)?.width ?? 0;
|
|
549
|
+
if (current !== overflow) {
|
|
550
|
+
if (overflow === 0) {
|
|
551
|
+
map.delete(id);
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
// Only fetch column offset when the overflow state *changes*, not on every scroll
|
|
555
|
+
const cellX = getColumnOffset(columnIndex);
|
|
556
|
+
map.set(id, { width: overflow, x: cellX });
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}, [getColumnOffset]);
|
|
560
|
+
const mergedCellMap = useMemo(() => {
|
|
561
|
+
const mergedCellMap = new Map();
|
|
562
|
+
if (merges) {
|
|
563
|
+
for (let i = 0; i < merges.length; i++) {
|
|
564
|
+
const bounds = merges[i];
|
|
565
|
+
for (const cell of getBoundedCells(bounds)) {
|
|
566
|
+
mergedCellMap.set(cell, bounds);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return mergedCellMap;
|
|
571
|
+
}, [merges]);
|
|
572
|
+
/**
|
|
573
|
+
* Check if a cell is merged cell
|
|
574
|
+
*/
|
|
575
|
+
const isMergedCell = useCallback(({ rowIndex, columnIndex }) => {
|
|
576
|
+
return mergedCellMap.has(cellIdentifier(rowIndex, columnIndex));
|
|
577
|
+
}, [mergedCellMap]);
|
|
578
|
+
/**
|
|
579
|
+
* Get cell bounds
|
|
580
|
+
* @param cell
|
|
581
|
+
* @returns
|
|
582
|
+
*/
|
|
583
|
+
const getCellBounds = useCallback(({ rowIndex, columnIndex }, spanMerges = true) => {
|
|
584
|
+
if (spanMerges) {
|
|
585
|
+
const isMerged = isMergedCell({ rowIndex, columnIndex });
|
|
586
|
+
if (isMerged)
|
|
587
|
+
return mergedCellMap.get(cellIdentifier(rowIndex, columnIndex));
|
|
588
|
+
}
|
|
589
|
+
return {
|
|
590
|
+
startRowIndex: rowIndex,
|
|
591
|
+
startColumnIndex: columnIndex,
|
|
592
|
+
endColumnIndex: columnIndex,
|
|
593
|
+
endRowIndex: rowIndex,
|
|
594
|
+
};
|
|
595
|
+
// gridRef.current?.getCellBounds(cell) ?? convertCellToRange(cell),
|
|
596
|
+
}, [mergedCellMap, isMergedCell]);
|
|
597
|
+
/* Get viewport of the grid */
|
|
598
|
+
const getViewPort = useCallback(() => gridRef.current?.getViewPort() ?? {
|
|
599
|
+
rowStartIndex: 0,
|
|
600
|
+
rowStopIndex: 0,
|
|
601
|
+
columnStartIndex: 0,
|
|
602
|
+
columnStopIndex: 0,
|
|
603
|
+
visibleRowStartIndex: 0,
|
|
604
|
+
visibleRowStopIndex: 0,
|
|
605
|
+
visibleColumnStartIndex: 0,
|
|
606
|
+
visibleColumnStopIndex: 0,
|
|
607
|
+
}, [scale]);
|
|
608
|
+
/**
|
|
609
|
+
* Get cell coordinates from x and y position
|
|
610
|
+
* @param x
|
|
611
|
+
* @param y
|
|
612
|
+
* @returns
|
|
613
|
+
*/
|
|
614
|
+
const getCellCoordsFromOffset = useCallback((x, y, includeFrozen) => gridRef.current?.getCellCoordsFromOffset(x, y, includeFrozen), [scale]);
|
|
615
|
+
/**
|
|
616
|
+
* Get cells coords
|
|
617
|
+
* caters to merged cells
|
|
618
|
+
*/
|
|
619
|
+
const getActualCellCoords = useCallback((coords) => gridRef.current?.getActualCellCoords(coords), [scale]);
|
|
620
|
+
/**
|
|
621
|
+
* Get cell offset from cell coords. Readonly mode, so
|
|
622
|
+
* lastMeasuredColumnIndex or lastMeasuredRowIndex will
|
|
623
|
+
* not get updated
|
|
624
|
+
* @param cell
|
|
625
|
+
* @returns
|
|
626
|
+
*/
|
|
627
|
+
const getCellOffsetFromCoords = useCallback((cell) => gridRef.current?.getCellOffsetFromCoords(cell, true), [scale]);
|
|
628
|
+
/**
|
|
629
|
+
* Canvas grid keeps track of lastMeasuredColumnIndex and
|
|
630
|
+
* lastMeasuredRowIndex so that it does not recalc grid
|
|
631
|
+
* dimension on every render
|
|
632
|
+
*/
|
|
633
|
+
const resetLastMeasuredIndices = useCallback((cell) => gridRef.current?.resetAfterIndices(cell, false), [scale]);
|
|
634
|
+
/**
|
|
635
|
+
* Focus sheet
|
|
636
|
+
*/
|
|
637
|
+
const focusSheet = useRaf(() => {
|
|
638
|
+
// Only suppress refocus when we're certain focus moved to a focusable
|
|
639
|
+
// element outside the grid (e.g. another asset pane in a split view).
|
|
640
|
+
// Mirrors the relatedTarget-outside-grid guard in handleEditorBlur. A
|
|
641
|
+
// user gesture on the grid focuses the tabIndex=0 container first, so
|
|
642
|
+
// this only suppresses render-driven refocus; a null container ref
|
|
643
|
+
// (mid mount/unmount) falls through to the original focus behavior.
|
|
644
|
+
const activeElement = canUseDOM ? document.activeElement : null;
|
|
645
|
+
const gridContainer = gridContainerRef.current;
|
|
646
|
+
if (activeElement &&
|
|
647
|
+
activeElement !== document.body &&
|
|
648
|
+
gridContainer &&
|
|
649
|
+
!gridContainer.contains(activeElement)) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
if (!activeEditor || activeEditor === cellEditorInstance) {
|
|
653
|
+
cellEditorInstance?.focus();
|
|
654
|
+
}
|
|
655
|
+
}, [activeEditor, cellEditorInstance]);
|
|
656
|
+
/**
|
|
657
|
+
* Canvas layers
|
|
658
|
+
*/
|
|
659
|
+
const getCanvasLayers = useCallback(() => gridRef.current?.stage?.getLayers(), []);
|
|
660
|
+
/**
|
|
661
|
+
* Row Header canvas layer layers
|
|
662
|
+
*/
|
|
663
|
+
const getRowHeaderCanvasLayer = useCallback(() => gridRef.current?.rowHeaderStage?.getLayers(), []);
|
|
664
|
+
/**
|
|
665
|
+
* Column Header canvas layer layers
|
|
666
|
+
*/
|
|
667
|
+
const getColumnHeaderCanvasLayer = useCallback(() => gridRef.current?.columnHeaderStage?.getLayers(), []);
|
|
668
|
+
/**
|
|
669
|
+
* Get relative position from
|
|
670
|
+
* position offset
|
|
671
|
+
*/
|
|
672
|
+
const getRelativePositionFromOffset = useCallback((x, y) => {
|
|
673
|
+
return gridRef.current?.getRelativePositionFromOffset(x, y);
|
|
674
|
+
}, []);
|
|
675
|
+
/**
|
|
676
|
+
* Get scroll position
|
|
677
|
+
* @returns ScrollCoords
|
|
678
|
+
*/
|
|
679
|
+
const getScrollPosition = useCallback(() => gridRef.current?.getScrollPosition() ?? DEFAULT_SCROLL_POSITION, []);
|
|
680
|
+
// Does the column contains a table
|
|
681
|
+
const columnContainsTable = useCallback((columnIndex) => {
|
|
682
|
+
const [_, tableColumnHeaderIds] = tableHeaderCells;
|
|
683
|
+
return tableColumnHeaderIds.get(columnIndex);
|
|
684
|
+
}, [tableHeaderCells]);
|
|
685
|
+
// Does the row contains a table
|
|
686
|
+
const rowsContainsTable = useCallback((rowIndex) => {
|
|
687
|
+
const [_, , tableRowHeaderIds] = tableHeaderCells;
|
|
688
|
+
return tableRowHeaderIds.get(rowIndex);
|
|
689
|
+
}, [tableHeaderCells]);
|
|
690
|
+
// Is table header
|
|
691
|
+
const isTableHeader = useCallback((rowIndex, columnIndex) => {
|
|
692
|
+
const [headerCells] = tableHeaderCells;
|
|
693
|
+
return headerCells.has(cellIdentifier(rowIndex, columnIndex));
|
|
694
|
+
}, [tableHeaderCells]);
|
|
695
|
+
// Is table header filter active
|
|
696
|
+
const isTableHeaderFilterActive = useCallback((rowIndex, columnIndex) => {
|
|
697
|
+
const [headerCells] = tableHeaderCells;
|
|
698
|
+
return headerCells.get(cellIdentifier(rowIndex, columnIndex))
|
|
699
|
+
?.isFilterActive;
|
|
700
|
+
}, [tableHeaderCells]);
|
|
701
|
+
// Is table header filter active
|
|
702
|
+
const getTableHeaderSortOrder = useCallback((rowIndex, columnIndex) => {
|
|
703
|
+
const [headerCells] = tableHeaderCells;
|
|
704
|
+
return headerCells.get(cellIdentifier(rowIndex, columnIndex))?.sortOrder;
|
|
705
|
+
}, [tableHeaderCells]);
|
|
706
|
+
// Is calculated column header
|
|
707
|
+
const isCalculatedColumnHeader = useCallback((rowIndex, columnIndex) => {
|
|
708
|
+
const [, , , calculatedColumnHeaders] = tableHeaderCells;
|
|
709
|
+
return calculatedColumnHeaders.has(cellIdentifier(rowIndex, columnIndex));
|
|
710
|
+
}, [tableHeaderCells]);
|
|
711
|
+
// Check if table header is themed
|
|
712
|
+
// So it will not be displayed in bold font
|
|
713
|
+
const isTableHeaderThemed = useCallback((rowIndex, columnIndex) => {
|
|
714
|
+
const [headerCells] = tableHeaderCells;
|
|
715
|
+
const cell = headerCells.get(cellIdentifier(rowIndex, columnIndex));
|
|
716
|
+
return cell?.theme && cell?.theme !== "None";
|
|
717
|
+
}, [tableHeaderCells]);
|
|
718
|
+
// Is Filter icon visible
|
|
719
|
+
const isTableFilterVisible = useCallback((rowIndex, columnIndex) => {
|
|
720
|
+
const [headerCells] = tableHeaderCells;
|
|
721
|
+
return showFilterIcon
|
|
722
|
+
? headerCells.get(cellIdentifier(rowIndex, columnIndex))?.filterButton
|
|
723
|
+
: false;
|
|
724
|
+
}, [tableHeaderCells, showFilterIcon]);
|
|
725
|
+
// Frozen row
|
|
726
|
+
const isFrozenRow = useCallback((rowIndex) => rowIndex < frozenRows, [frozenRows]);
|
|
727
|
+
// Frozen column
|
|
728
|
+
const isFrozenColumn = useCallback((columnIndex) => columnIndex < frozenColumns, [frozenColumns]);
|
|
729
|
+
/**
|
|
730
|
+
* Get hyperlink of a cell
|
|
731
|
+
*/
|
|
732
|
+
const getCellMetaType = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
733
|
+
return getCellData?.(sheetId, rowIndex, columnIndex)?.metaType;
|
|
734
|
+
}, [getCellData]);
|
|
735
|
+
/**
|
|
736
|
+
* Get hyperlink of a cell
|
|
737
|
+
*/
|
|
738
|
+
const getHyperlink = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
739
|
+
return (getCellData?.(sheetId, rowIndex, columnIndex)?.hyperlink ?? undefined);
|
|
740
|
+
}, [getCellData]);
|
|
741
|
+
/**
|
|
742
|
+
* Get value entered by the user in a cell
|
|
743
|
+
*/
|
|
744
|
+
const getUserEnteredValue = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
745
|
+
return getUserEnteredExtendedValue
|
|
746
|
+
? getUserEnteredExtendedValue(sheetId, rowIndex, columnIndex)
|
|
747
|
+
: getCellUserEnteredValue(getCellData?.(sheetId, rowIndex, columnIndex));
|
|
748
|
+
}, [getUserEnteredExtendedValue, getCellData]);
|
|
749
|
+
/**
|
|
750
|
+
* Get boolean value
|
|
751
|
+
*/
|
|
752
|
+
const getBooleanValue = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
753
|
+
return getExtendedValueBool(getUserEnteredValue?.(sheetId, rowIndex, columnIndex));
|
|
754
|
+
}, [getUserEnteredValue]);
|
|
755
|
+
/**
|
|
756
|
+
* Get formula value entered by user
|
|
757
|
+
*/
|
|
758
|
+
const getFormulaValue = useCallbackRef(useCallback((sheetId, rowIndex, columnIndex) => {
|
|
759
|
+
return getExtendedValueFormula(getUserEnteredValue?.(sheetId, rowIndex, columnIndex));
|
|
760
|
+
}, [getUserEnteredValue]));
|
|
761
|
+
/**
|
|
762
|
+
* Get cell display value
|
|
763
|
+
*/
|
|
764
|
+
const getFormattedValue = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
765
|
+
// Row header (~1,2)
|
|
766
|
+
if (isRowHeader(columnIndex)) {
|
|
767
|
+
return getRowHeaderText(rowIndex);
|
|
768
|
+
}
|
|
769
|
+
// Column header (~A,B)
|
|
770
|
+
if (isColumnHeader(rowIndex)) {
|
|
771
|
+
return getColumnHeaderText(columnIndex);
|
|
772
|
+
}
|
|
773
|
+
if (showFormulas && !protectFormulas) {
|
|
774
|
+
const formulaValue = getFormulaValue(sheetId, rowIndex, columnIndex);
|
|
775
|
+
if (formulaValue) {
|
|
776
|
+
return formulaValue;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
const formattedValue = getFormattedValueProp
|
|
780
|
+
? getFormattedValueProp?.(sheetId, rowIndex, columnIndex)
|
|
781
|
+
: getCellFormattedValue(getCellData?.(sheetId, rowIndex, columnIndex));
|
|
782
|
+
// Temporary workaround for `richText`
|
|
783
|
+
if (!isNil(formattedValue) && typeof formattedValue === "object") {
|
|
784
|
+
return tryParseRichText(formattedValue);
|
|
785
|
+
}
|
|
786
|
+
return formattedValue ?? undefined;
|
|
787
|
+
}, [
|
|
788
|
+
getFormattedValueProp,
|
|
789
|
+
getCellData,
|
|
790
|
+
getFormulaValue,
|
|
791
|
+
showFormulas,
|
|
792
|
+
protectFormulas,
|
|
793
|
+
isRowHeader,
|
|
794
|
+
isColumnHeader,
|
|
795
|
+
getRowHeaderText,
|
|
796
|
+
getColumnHeaderText,
|
|
797
|
+
]);
|
|
798
|
+
/**
|
|
799
|
+
* Get information about cell grouping
|
|
800
|
+
*/
|
|
801
|
+
const getCellGroupingInfo = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
802
|
+
const cellData = getCellData?.(sheetId, rowIndex, columnIndex);
|
|
803
|
+
return [
|
|
804
|
+
cellData?.expandable ?? undefined,
|
|
805
|
+
cellData?.expanded ?? undefined,
|
|
806
|
+
];
|
|
807
|
+
}, [getCellData]);
|
|
808
|
+
/**
|
|
809
|
+
* Get effective value of a cell
|
|
810
|
+
*/
|
|
811
|
+
const getEffectiveValue = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
812
|
+
return getEffectiveExtendedValue
|
|
813
|
+
? getEffectiveExtendedValue(sheetId, rowIndex, columnIndex)
|
|
814
|
+
: getCellEffectiveValue(getCellData?.(sheetId, rowIndex, columnIndex));
|
|
815
|
+
}, [getEffectiveExtendedValue, getCellData]);
|
|
816
|
+
/**
|
|
817
|
+
* Get validation value of a cell
|
|
818
|
+
*/
|
|
819
|
+
const getFormulaValidationValue = useCallback((sheetId, rowIndex, columnIndex, ruleId) => {
|
|
820
|
+
return getCellData?.(sheetId, rowIndex, columnIndex)
|
|
821
|
+
?.conditionalFormattingResultById?.[ruleId];
|
|
822
|
+
}, [getCellData]);
|
|
823
|
+
/**
|
|
824
|
+
* Get formula error value entered by user
|
|
825
|
+
*/
|
|
826
|
+
const getErrorValue = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
827
|
+
return getExtendedValueError(getEffectiveValue?.(sheetId, rowIndex, columnIndex));
|
|
828
|
+
}, [getEffectiveValue]);
|
|
829
|
+
/**
|
|
830
|
+
* Get notes. The host's `getNote` wins when provided — engines that keep
|
|
831
|
+
* notes off the cell data (rnc serves notes over their own channel) have
|
|
832
|
+
* no `.note` on `getCellData` cells to fall back to.
|
|
833
|
+
*/
|
|
834
|
+
const getNote = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
835
|
+
return (getNoteProp?.(sheetId, rowIndex, columnIndex) ??
|
|
836
|
+
getCellData?.(sheetId, rowIndex, columnIndex)?.note ??
|
|
837
|
+
undefined);
|
|
838
|
+
}, [getNoteProp, getCellData]);
|
|
839
|
+
/**
|
|
840
|
+
* Get comment
|
|
841
|
+
*/
|
|
842
|
+
const getComment = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
843
|
+
return (getCellData?.(sheetId, rowIndex, columnIndex)?.commentThreadId ??
|
|
844
|
+
undefined);
|
|
845
|
+
}, [getCellData]);
|
|
846
|
+
/**
|
|
847
|
+
* Get citation
|
|
848
|
+
*/
|
|
849
|
+
const getCitation = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
850
|
+
return (getCellData?.(sheetId, rowIndex, columnIndex)?.citationId ?? undefined);
|
|
851
|
+
}, [getCellData]);
|
|
852
|
+
/**
|
|
853
|
+
* Get Image url in a cell
|
|
854
|
+
* Users can add images in a cell using imageUrl property
|
|
855
|
+
*/
|
|
856
|
+
const getCellImageUrl = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
857
|
+
return (getCellData?.(sheetId, rowIndex, columnIndex)?.imageUrl ?? undefined);
|
|
858
|
+
}, [getCellData]);
|
|
859
|
+
/**
|
|
860
|
+
* Returns cellFormat of a cell
|
|
861
|
+
* cellFormat = userEnteredFormat + formatFromFormulaCalculation
|
|
862
|
+
* Readable field.
|
|
863
|
+
*
|
|
864
|
+
* Use userEnteredFormat for write and generate effectiveFormat
|
|
865
|
+
*/
|
|
866
|
+
const getCellFormat = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
867
|
+
if (getEffectiveFormat) {
|
|
868
|
+
return getEffectiveFormat?.(sheetId, rowIndex, columnIndex);
|
|
869
|
+
}
|
|
870
|
+
// For backwards compatiblity
|
|
871
|
+
const cellData = getCellData?.(sheetId, rowIndex, columnIndex);
|
|
872
|
+
const effectiveFormat = getCellEffectiveFormat(cellData);
|
|
873
|
+
if (!isStyleReference(effectiveFormat)) {
|
|
874
|
+
return effectiveFormat;
|
|
875
|
+
}
|
|
876
|
+
return undefined;
|
|
877
|
+
}, [getEffectiveFormat, getCellData]);
|
|
878
|
+
/**
|
|
879
|
+
* Get cell indent
|
|
880
|
+
*/
|
|
881
|
+
const getCellIndent = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
882
|
+
const fmt = getCellFormat(sheetId, rowIndex, columnIndex);
|
|
883
|
+
const indent = (fmt?.indent ?? 0) + (fmt?.relativeIndent ?? 0);
|
|
884
|
+
return indent || undefined;
|
|
885
|
+
}, [getCellFormat]);
|
|
886
|
+
/**
|
|
887
|
+
* Check if a cell data is a number
|
|
888
|
+
*/
|
|
889
|
+
const isNumberValue = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
890
|
+
const cellFormat = getCellFormat?.(sheetId, rowIndex, columnIndex);
|
|
891
|
+
return !!cellFormat?.numberFormat?.type;
|
|
892
|
+
}, [getCellFormat]);
|
|
893
|
+
/**
|
|
894
|
+
* Get value entered by the user in a cell
|
|
895
|
+
* If its a formula cell, formulaValue is used
|
|
896
|
+
* Order of retrieval
|
|
897
|
+
* 1. formulaValue
|
|
898
|
+
* 2. numberValue
|
|
899
|
+
* 3. stringValue
|
|
900
|
+
* 4. formattedValue
|
|
901
|
+
* If number -> trim formatted value
|
|
902
|
+
*/
|
|
903
|
+
const getUserEnteredStringValue = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
904
|
+
const formulaValue = getFormulaValue(sheetId, rowIndex, columnIndex);
|
|
905
|
+
if (formulaValue && !protectFormulas) {
|
|
906
|
+
return formulaValue;
|
|
907
|
+
}
|
|
908
|
+
const userEnteredValue = getUserEnteredValue(sheetId, rowIndex, columnIndex);
|
|
909
|
+
// Look for sv
|
|
910
|
+
const stringValue = getExtendedValueString(userEnteredValue);
|
|
911
|
+
if (stringValue) {
|
|
912
|
+
return stringValue;
|
|
913
|
+
}
|
|
914
|
+
// Check for date value
|
|
915
|
+
const numberFormatType = getCellFormat(sheetId, rowIndex, columnIndex)
|
|
916
|
+
?.numberFormat?.type;
|
|
917
|
+
if (numberFormatType === "DATE" || numberFormatType === "DATE_TIME") {
|
|
918
|
+
return getFormattedValue(sheetId, rowIndex, columnIndex);
|
|
919
|
+
}
|
|
920
|
+
// If the cell is of type number, fallback to number
|
|
921
|
+
const numberValue = getExtendedValueNumber(userEnteredValue);
|
|
922
|
+
if (!isNil(numberValue)) {
|
|
923
|
+
return String(numberValue);
|
|
924
|
+
}
|
|
925
|
+
// This is used for Array return values, which do not have
|
|
926
|
+
// formula value or user entered value
|
|
927
|
+
return getFormattedValue(sheetId, rowIndex, columnIndex);
|
|
928
|
+
}, [
|
|
929
|
+
getUserEnteredValue,
|
|
930
|
+
getFormulaValue,
|
|
931
|
+
getFormattedValue,
|
|
932
|
+
getCellFormat,
|
|
933
|
+
protectFormulas,
|
|
934
|
+
]);
|
|
935
|
+
// Add a stable reference to get userEnteredString value
|
|
936
|
+
const getUserEnteredStringValueStable = useCallbackRef(getUserEnteredStringValue);
|
|
937
|
+
/**
|
|
938
|
+
* Get cell value used for validations
|
|
939
|
+
*/
|
|
940
|
+
const getValidationValue = useCallback((sheetId, rowIndex, columnIndex, rule) => {
|
|
941
|
+
// Formula-backed rules use the custom formula path
|
|
942
|
+
if (rule && isConditionalFormatFormulaRule(rule)) {
|
|
943
|
+
return getFormulaValidationValue(sheetId, rowIndex, columnIndex, rule.id);
|
|
944
|
+
}
|
|
945
|
+
const effectiveValue = getEffectiveValue(sheetId, rowIndex, columnIndex);
|
|
946
|
+
if (rule?.booleanRule?.condition?.type === "ERROR" ||
|
|
947
|
+
rule?.booleanRule?.condition?.type === "NOT_ERROR") {
|
|
948
|
+
return getExtendedValueError(effectiveValue);
|
|
949
|
+
}
|
|
950
|
+
return (getExtendedValueBool(effectiveValue) ??
|
|
951
|
+
getExtendedValueNumber(effectiveValue) ??
|
|
952
|
+
getExtendedValueString(effectiveValue));
|
|
953
|
+
}, [getEffectiveValue, getFormulaValidationValue]);
|
|
954
|
+
/**
|
|
955
|
+
* Touch support
|
|
956
|
+
* Mainly for scrolling
|
|
957
|
+
*/
|
|
958
|
+
const { onTouchStart, onDimensionsChange, scrollToTouchDevice, onAfterScrollToCell, } = useTouch({
|
|
959
|
+
scrollTo,
|
|
960
|
+
scale,
|
|
961
|
+
onChangeScale,
|
|
962
|
+
});
|
|
963
|
+
/**
|
|
964
|
+
* Conditional-formatting evaluation window: the padded, tile-quantized
|
|
965
|
+
* viewport. The raw viewport lives in a ref (no render per scroll frame);
|
|
966
|
+
* state only updates when a tile boundary is crossed, inside
|
|
967
|
+
* `startTransition` so the CF recompute is low-priority and interruptible —
|
|
968
|
+
* scrolling never blocks on it.
|
|
969
|
+
*/
|
|
970
|
+
const [cfWindow, setCfWindow] = useState(CF_INITIAL_WINDOW);
|
|
971
|
+
const cfWindowRef = useRef(null);
|
|
972
|
+
const handleViewPortChange = useCallback((viewport) => {
|
|
973
|
+
onViewPortChange?.(viewport);
|
|
974
|
+
if (!windowConditionalFormats)
|
|
975
|
+
return;
|
|
976
|
+
const next = cfWindowForViewport(viewport);
|
|
977
|
+
if (!isSameCfWindow(cfWindowRef.current, next)) {
|
|
978
|
+
cfWindowRef.current = next;
|
|
979
|
+
startTransition(() => setCfWindow(next));
|
|
980
|
+
}
|
|
981
|
+
}, [onViewPortChange, windowConditionalFormats]);
|
|
982
|
+
/**
|
|
983
|
+
* Conditional Styles that should be applied to cell
|
|
984
|
+
*/
|
|
985
|
+
const conditionalFormatByCell = useConditionalFormatting({
|
|
986
|
+
locale,
|
|
987
|
+
sheetId,
|
|
988
|
+
conditionalFormats: conditionalFormats ?? undefined,
|
|
989
|
+
getValidationValue,
|
|
990
|
+
isNumberValue,
|
|
991
|
+
theme,
|
|
992
|
+
getSheetRowCount,
|
|
993
|
+
getSheetColumnCount,
|
|
994
|
+
window: windowConditionalFormats ? cfWindow : undefined,
|
|
995
|
+
// Aggregate rules (TOP/BOTTOM-N, DUPLICATE/UNIQUE, above/below-average)
|
|
996
|
+
// consume the engine's per-cell stamps when the host declares them.
|
|
997
|
+
getConditionalFormatResult: engineConditionalFormatResults
|
|
998
|
+
? getFormulaValidationValue
|
|
999
|
+
: undefined,
|
|
1000
|
+
});
|
|
1001
|
+
/**
|
|
1002
|
+
* Get conditional format of a cell
|
|
1003
|
+
*/
|
|
1004
|
+
const getConditionalCellFormat = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1005
|
+
return conditionalFormatByCell.get(cellIdentifier(rowIndex, columnIndex));
|
|
1006
|
+
}, [conditionalFormatByCell]);
|
|
1007
|
+
/**
|
|
1008
|
+
* Get conditional format of a cell
|
|
1009
|
+
*/
|
|
1010
|
+
const getBandedCellFormat = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1011
|
+
return bandedCells.get(cellIdentifier(rowIndex, columnIndex));
|
|
1012
|
+
}, [bandedCells]);
|
|
1013
|
+
/**
|
|
1014
|
+
* Get data validation of a cell
|
|
1015
|
+
*/
|
|
1016
|
+
const getDataValidationRule = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1017
|
+
return getDataValidation
|
|
1018
|
+
? getDataValidation(sheetId, rowIndex, columnIndex)
|
|
1019
|
+
: getCellData?.(sheetId, rowIndex, columnIndex)
|
|
1020
|
+
?.dataValidation;
|
|
1021
|
+
}, [getCellData, getDataValidation]);
|
|
1022
|
+
// Get default horizontal alignment
|
|
1023
|
+
const getDefaultHorizontalAlignment = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1024
|
+
const isBoolean = !isNil(getBooleanValue(sheetId, rowIndex, columnIndex));
|
|
1025
|
+
const errorValue = getErrorValue(sheetId, rowIndex, columnIndex);
|
|
1026
|
+
// A checkbox cell centers regardless of its VALUE (Google Sheets):
|
|
1027
|
+
// a blank checkbox (no `ue` at all) and a windowed host whose lean
|
|
1028
|
+
// read reconstructs the boolean as text both miss the `bv` probe.
|
|
1029
|
+
const isCheckbox = getDataValidationRule(sheetId, rowIndex, columnIndex)?.condition
|
|
1030
|
+
?.type === "BOOLEAN";
|
|
1031
|
+
const nv = getExtendedValueNumber(getEffectiveValue(sheetId, rowIndex, columnIndex));
|
|
1032
|
+
if (errorValue || isBoolean || isCheckbox) {
|
|
1033
|
+
return "center";
|
|
1034
|
+
}
|
|
1035
|
+
if (typeof nv !== "undefined") {
|
|
1036
|
+
return "right";
|
|
1037
|
+
}
|
|
1038
|
+
return undefined;
|
|
1039
|
+
}, [getBooleanValue, getDataValidationRule, getEffectiveValue, getErrorValue]);
|
|
1040
|
+
/**
|
|
1041
|
+
* Get format specified in the cellData = effectiveFormat + conditonalFormat
|
|
1042
|
+
* https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/cells#effectiveFormat
|
|
1043
|
+
*
|
|
1044
|
+
* More work to be done with effectiveFormat
|
|
1045
|
+
* G and MS combines effectiveformat
|
|
1046
|
+
* effectiveFormat = cellFormat (effective + user entered + formula) + conditionalFormatting
|
|
1047
|
+
*
|
|
1048
|
+
* We are generating conditionalFormatting on the component level,
|
|
1049
|
+
*/
|
|
1050
|
+
const getEffectiveCellFormat = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1051
|
+
const cellFormat = getCellFormat(sheetId, rowIndex, columnIndex);
|
|
1052
|
+
const isHyperlink = Boolean(getHyperlink(sheetId, rowIndex, columnIndex));
|
|
1053
|
+
const conditionalCellFormat = getConditionalCellFormat(sheetId, rowIndex, columnIndex);
|
|
1054
|
+
const bandedCellFormat = getBandedCellFormat(sheetId, rowIndex, columnIndex);
|
|
1055
|
+
// Conditional format cell color for
|
|
1056
|
+
// light and dark themes
|
|
1057
|
+
const conditionalFormatColor = conditionalCellFormat?.backgroundColor &&
|
|
1058
|
+
!conditionalCellFormat?.textFormat?.color
|
|
1059
|
+
? getContrastColor(getStringifiedColor(conditionalCellFormat.backgroundColor, theme), getStringifiedColor({ theme: 1 }, theme), getStringifiedColor({ theme: 1, tint: 1 }, theme))
|
|
1060
|
+
: undefined;
|
|
1061
|
+
// Excel / Google Sheets: a number-format pattern can carry per-section
|
|
1062
|
+
// color directives like `[Blue]#,##0.00;[Red]-#,##0.00;[Green]"zero";[Magenta]@`.
|
|
1063
|
+
// The section is picked by the effective value's sign / type — section
|
|
1064
|
+
// 3 (the `@` branch) applies to string values. Excel applies the
|
|
1065
|
+
// matched section's color OVER the cell's font color at display time
|
|
1066
|
+
// (only conditional-format font colors rank higher), so the resolved
|
|
1067
|
+
// color is layered on top of `uf.textFormat.color` after the merge
|
|
1068
|
+
// below — the import path stores the cell's real font color and relies
|
|
1069
|
+
// on this value-current resolution for `[Red]`-style display colors.
|
|
1070
|
+
//
|
|
1071
|
+
// Prefer the string branch when both are present so non-numeric text
|
|
1072
|
+
// picks the `@` section instead of a number section computed from a
|
|
1073
|
+
// coerced NaN.
|
|
1074
|
+
const numberFormatPattern = cellFormat?.numberFormat?.pattern;
|
|
1075
|
+
const effectiveValueForColor = numberFormatPattern
|
|
1076
|
+
? getEffectiveValue(sheetId, rowIndex, columnIndex)
|
|
1077
|
+
: undefined;
|
|
1078
|
+
const valueForColor = effectiveValueForColor
|
|
1079
|
+
? getExtendedValueString(effectiveValueForColor) ??
|
|
1080
|
+
getExtendedValueNumber(effectiveValueForColor) ??
|
|
1081
|
+
getExtendedValueBool(effectiveValueForColor)
|
|
1082
|
+
: undefined;
|
|
1083
|
+
const patternColor = numberFormatPattern && valueForColor !== undefined
|
|
1084
|
+
? ssfFormatColor(numberFormatPattern, valueForColor)
|
|
1085
|
+
: undefined;
|
|
1086
|
+
// Final text format. Hyperlink cells auto-derive underline at paint
|
|
1087
|
+
// time — `uf.textFormat.underline` is merged on top below, so a user
|
|
1088
|
+
// who explicitly sets underline=false still wins.
|
|
1089
|
+
const defaultTextFormat = {
|
|
1090
|
+
bold: isTableHeader(rowIndex, columnIndex) &&
|
|
1091
|
+
isTableHeaderThemed(rowIndex, columnIndex)
|
|
1092
|
+
? true
|
|
1093
|
+
: undefined,
|
|
1094
|
+
fontFamily: theme.primaryFontFamily,
|
|
1095
|
+
color: isHyperlink
|
|
1096
|
+
? theme.themeColors.hyperlink
|
|
1097
|
+
: patternColor ??
|
|
1098
|
+
bandedCellFormat?.textFormat?.color ??
|
|
1099
|
+
conditionalFormatColor ??
|
|
1100
|
+
getStringifiedColor(cellColor, theme),
|
|
1101
|
+
underline: isHyperlink ? true : undefined,
|
|
1102
|
+
};
|
|
1103
|
+
const mergedFormat = merge({
|
|
1104
|
+
textFormat: defaultTextFormat,
|
|
1105
|
+
}, definedProps(cellFormat), conditionalCellFormat);
|
|
1106
|
+
// Number-format section colors beat the cell's font color (Excel
|
|
1107
|
+
// parity), but never a conditional-format font color or the
|
|
1108
|
+
// hyperlink color.
|
|
1109
|
+
if (patternColor &&
|
|
1110
|
+
!isHyperlink &&
|
|
1111
|
+
!conditionalCellFormat?.textFormat?.color) {
|
|
1112
|
+
mergedFormat.textFormat = {
|
|
1113
|
+
...mergedFormat.textFormat,
|
|
1114
|
+
color: patternColor,
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
return {
|
|
1118
|
+
...bandedCellFormat,
|
|
1119
|
+
...mergedFormat,
|
|
1120
|
+
};
|
|
1121
|
+
}, [
|
|
1122
|
+
getCellFormat,
|
|
1123
|
+
getConditionalCellFormat,
|
|
1124
|
+
getBandedCellFormat,
|
|
1125
|
+
getHyperlink,
|
|
1126
|
+
isTableHeader,
|
|
1127
|
+
isTableHeaderThemed,
|
|
1128
|
+
getEffectiveValue,
|
|
1129
|
+
theme,
|
|
1130
|
+
cellColor,
|
|
1131
|
+
]);
|
|
1132
|
+
/**
|
|
1133
|
+
* Get horizontal alignment of editor
|
|
1134
|
+
*/
|
|
1135
|
+
const getEditorHorizontalAlignment = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1136
|
+
const isFormula = !!getFormulaValue(sheetId, rowIndex, columnIndex);
|
|
1137
|
+
const isBoolean = !isNil(getBooleanValue(sheetId, rowIndex, columnIndex));
|
|
1138
|
+
// Boolean cell: Center align text
|
|
1139
|
+
// Formula cell: Always left align text in editor
|
|
1140
|
+
return isFormula
|
|
1141
|
+
? "left"
|
|
1142
|
+
: isBoolean
|
|
1143
|
+
? "center"
|
|
1144
|
+
: getEffectiveCellFormat(sheetId, rowIndex, columnIndex)
|
|
1145
|
+
?.horizontalAlignment ??
|
|
1146
|
+
getDefaultHorizontalAlignment(sheetId, rowIndex, columnIndex) ??
|
|
1147
|
+
CELL_HORIZONTAL_ALIGNMENT;
|
|
1148
|
+
}, [
|
|
1149
|
+
getFormulaValue,
|
|
1150
|
+
getBooleanValue,
|
|
1151
|
+
getEffectiveCellFormat,
|
|
1152
|
+
getDefaultHorizontalAlignment,
|
|
1153
|
+
]);
|
|
1154
|
+
// Check if we need to wrap a cell
|
|
1155
|
+
const shouldWrapCell = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1156
|
+
return (getEffectiveCellFormat(sheetId, rowIndex, columnIndex)?.wrapStrategy ===
|
|
1157
|
+
"wrap");
|
|
1158
|
+
}, [getEffectiveCellFormat]);
|
|
1159
|
+
/**
|
|
1160
|
+
* Get formatting applied to a cell
|
|
1161
|
+
*/
|
|
1162
|
+
const getTextFormat = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1163
|
+
if (isRowHeader(columnIndex) || isColumnHeader(rowIndex)) {
|
|
1164
|
+
return HEADER_TEXT_FORMAT;
|
|
1165
|
+
}
|
|
1166
|
+
return (getEffectiveCellFormat?.(sheetId, rowIndex, columnIndex)?.textFormat ??
|
|
1167
|
+
DEFAULT_TEXT_FORMAT);
|
|
1168
|
+
}, [getEffectiveCellFormat, isRowHeader, isColumnHeader]);
|
|
1169
|
+
/**
|
|
1170
|
+
* Get cell selections from structured tables
|
|
1171
|
+
*/
|
|
1172
|
+
const getSelectionFromTable = useOnStructuredReferenceSelection({
|
|
1173
|
+
tables: tables ?? undefined,
|
|
1174
|
+
getSheetName,
|
|
1175
|
+
});
|
|
1176
|
+
// Build case-insensitive lookup map for O(1) named range access
|
|
1177
|
+
const namedRangeMap = useMemo(() => {
|
|
1178
|
+
const map = new Map();
|
|
1179
|
+
namedRanges?.forEach((range) => {
|
|
1180
|
+
map.set(range.name.toLowerCase(), range);
|
|
1181
|
+
});
|
|
1182
|
+
return map;
|
|
1183
|
+
}, [namedRanges]);
|
|
1184
|
+
/**
|
|
1185
|
+
* Get cell selections from named ranges
|
|
1186
|
+
*/
|
|
1187
|
+
const getSelectionFromNamedRange = useCallback((variableName) => {
|
|
1188
|
+
// O(1) hash lookup instead of O(n) linear search
|
|
1189
|
+
const namedRange = namedRangeMap.get(variableName.toLowerCase());
|
|
1190
|
+
// Only return selection for names with ranges
|
|
1191
|
+
if (namedRange?.range) {
|
|
1192
|
+
return {
|
|
1193
|
+
range: namedRange.range,
|
|
1194
|
+
sheetName: getSheetName?.(namedRange.range.sheetId),
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
// Get static or formula value
|
|
1198
|
+
const result = namedRange?.value;
|
|
1199
|
+
if (!isNil(result)) {
|
|
1200
|
+
return result;
|
|
1201
|
+
}
|
|
1202
|
+
return undefined;
|
|
1203
|
+
}, [namedRangeMap, getSheetName]);
|
|
1204
|
+
/**
|
|
1205
|
+
* Create a tokenizer for Rich text editor
|
|
1206
|
+
*/
|
|
1207
|
+
const tokenizer = useCreateFormulaTokenizer({
|
|
1208
|
+
getSelectionFromNamedRange,
|
|
1209
|
+
getSelectionFromTable,
|
|
1210
|
+
editingCellCoordinate,
|
|
1211
|
+
sheetId,
|
|
1212
|
+
activeCell,
|
|
1213
|
+
tokenizer: defaultTokenizer,
|
|
1214
|
+
});
|
|
1215
|
+
// Helper function to convert a selection to readable selection address
|
|
1216
|
+
const [getAddressFromSelection, getR1C1AddressFromSelection] = useCreateAddressFromSelection({
|
|
1217
|
+
sheetId,
|
|
1218
|
+
rowCount,
|
|
1219
|
+
columnCount,
|
|
1220
|
+
tables: tables ?? undefined,
|
|
1221
|
+
namedRanges: namedRanges ?? undefined,
|
|
1222
|
+
merges,
|
|
1223
|
+
});
|
|
1224
|
+
/**
|
|
1225
|
+
* Exports a data region as image
|
|
1226
|
+
*/
|
|
1227
|
+
const exportRange = useExportRange({
|
|
1228
|
+
sheetId,
|
|
1229
|
+
cellBackgroundColor,
|
|
1230
|
+
gridLineWidth,
|
|
1231
|
+
getCanvasLayers,
|
|
1232
|
+
getRowHeaderCanvasLayer,
|
|
1233
|
+
getColumnHeaderCanvasLayer,
|
|
1234
|
+
getCellOffsetFromCoords,
|
|
1235
|
+
getR1C1AddressFromSelection,
|
|
1236
|
+
getSheetName,
|
|
1237
|
+
getScrollPosition,
|
|
1238
|
+
getViewPort,
|
|
1239
|
+
getRowOffset,
|
|
1240
|
+
getColumnOffset,
|
|
1241
|
+
getSheetDimensions,
|
|
1242
|
+
scrollTo,
|
|
1243
|
+
scrollToCell,
|
|
1244
|
+
scale,
|
|
1245
|
+
onChangeScale,
|
|
1246
|
+
});
|
|
1247
|
+
/**
|
|
1248
|
+
* Get all cell selections from formula string
|
|
1249
|
+
*/
|
|
1250
|
+
const getSelectionsFromFormula = useCallbackRef(useCallback((value, cell) => {
|
|
1251
|
+
const editingSheetName = getSheetName?.(editingCellCoordinate?.sheetId ?? sheetId);
|
|
1252
|
+
const editingSheetId = editingCellCoordinate?.sheetId ?? sheetId;
|
|
1253
|
+
return generateSelectionsFromFormula(value, editingSheetId, editingSheetName, cell, rowCount, columnCount, tokenizer, getSelectionFromTable, getSelectionFromNamedRange);
|
|
1254
|
+
}, [
|
|
1255
|
+
rowCount,
|
|
1256
|
+
columnCount,
|
|
1257
|
+
editingCellCoordinate,
|
|
1258
|
+
tokenizer,
|
|
1259
|
+
getSelectionFromTable,
|
|
1260
|
+
getSheetName,
|
|
1261
|
+
getSelectionFromNamedRange,
|
|
1262
|
+
sheetId,
|
|
1263
|
+
]));
|
|
1264
|
+
/**
|
|
1265
|
+
* Get user entered value from a range
|
|
1266
|
+
* of cells
|
|
1267
|
+
*/
|
|
1268
|
+
const [getFormattedValuesFromAddress, getEffectiveValuesFromRange, getFormattedValuesFromAddressAsync,] = useGetValuesFromRange({
|
|
1269
|
+
sheetId,
|
|
1270
|
+
getSelectionsFromFormula,
|
|
1271
|
+
getFormattedValue,
|
|
1272
|
+
getValidationValue,
|
|
1273
|
+
getSheetId,
|
|
1274
|
+
onRequestCalculate,
|
|
1275
|
+
getValidationSourceValue,
|
|
1276
|
+
});
|
|
1277
|
+
/**
|
|
1278
|
+
* Get all formatted values from range as a single 1d array
|
|
1279
|
+
*/
|
|
1280
|
+
const getFormattedValuesFromRange = useCallback((sheetId, selections) => {
|
|
1281
|
+
const values = new Set();
|
|
1282
|
+
for (const { range } of selections) {
|
|
1283
|
+
for (const [rowIndex, columnIndex] of iterateCellsInRange(range)) {
|
|
1284
|
+
const formattedValue = getFormattedValue(sheetId, rowIndex, columnIndex);
|
|
1285
|
+
if (!isNil(formattedValue)) {
|
|
1286
|
+
values.add(formattedValue);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return [...values];
|
|
1291
|
+
}, [getFormattedValue]);
|
|
1292
|
+
/**
|
|
1293
|
+
* Resolve commit-time data validation enforcement for a value being entered.
|
|
1294
|
+
* Returns the alert + decision when the value is invalid and the rule has an
|
|
1295
|
+
* error alert; otherwise `undefined` (no enforcement — the cell still gets the
|
|
1296
|
+
* flag-only red marker via `SheetCell.validate`). Formula-backed rules resolve
|
|
1297
|
+
* asynchronously through the calculator, so they fall back to flag-only here.
|
|
1298
|
+
*/
|
|
1299
|
+
const getCommitValidation = useCallback((validationSheetId, rowIndex, columnIndex, value, previousValue) => {
|
|
1300
|
+
const rule = getDataValidationRule(validationSheetId, rowIndex, columnIndex);
|
|
1301
|
+
const alert = rule?.alert;
|
|
1302
|
+
if (!rule || !alert) {
|
|
1303
|
+
return undefined;
|
|
1304
|
+
}
|
|
1305
|
+
const isBlank = value === undefined ||
|
|
1306
|
+
value === null ||
|
|
1307
|
+
(typeof value === "string" && value === "");
|
|
1308
|
+
if (rule.allowBlank && isBlank) {
|
|
1309
|
+
return undefined;
|
|
1310
|
+
}
|
|
1311
|
+
if (isDataValidationFormulaRule(rule)) {
|
|
1312
|
+
// Enforce synchronously only where `checkBooleanRule` can decide the typed
|
|
1313
|
+
// value without the calculator: CUSTOM_FORMULA's sync branch is a stub, the
|
|
1314
|
+
// DATE_* comparisons expect serial values (commit hands us the raw typed
|
|
1315
|
+
// string), and literal bounds may themselves be formulas/references. Those
|
|
1316
|
+
// stay flag-only via the async calc path; everything else (dropdown
|
|
1317
|
+
// lists/ranges, number/text bounds, blank/boolean/email/url) blocks or
|
|
1318
|
+
// warns at commit like Excel.
|
|
1319
|
+
const conditionType = rule.condition?.type;
|
|
1320
|
+
const conditionValues = rule.condition?.values ?? [];
|
|
1321
|
+
const hasFormulaBound = conditionValues.some((entry) => typeof entry?.userEnteredValue === "string" &&
|
|
1322
|
+
entry.userEnteredValue.trim().startsWith("="));
|
|
1323
|
+
const syncEnforceable = conditionType !== "CUSTOM_FORMULA" &&
|
|
1324
|
+
!conditionType?.startsWith("DATE_") &&
|
|
1325
|
+
(conditionType === "ONE_OF_RANGE" || !hasFormulaBound);
|
|
1326
|
+
if (!syncEnforceable) {
|
|
1327
|
+
return undefined;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
const isValid = checkBooleanRule(rule, value, previousValue ?? undefined, getFormattedValuesFromAddress, { locale });
|
|
1331
|
+
const decision = decideValidationCommit(alert, Boolean(isValid));
|
|
1332
|
+
if (decision === "proceed") {
|
|
1333
|
+
return undefined;
|
|
1334
|
+
}
|
|
1335
|
+
return { decision, alert };
|
|
1336
|
+
}, [getDataValidationRule, getFormattedValuesFromAddress, locale]);
|
|
1337
|
+
/**
|
|
1338
|
+
* Opens the blocking data-validation alert dialog (Excel error alert).
|
|
1339
|
+
*/
|
|
1340
|
+
const showValidationAlert = useShowValidationAlert();
|
|
1341
|
+
/**
|
|
1342
|
+
* Screen-reader announcement for the active cell (address + value). Rendered
|
|
1343
|
+
* into a visually-hidden aria-live region below so keyboard navigation of the
|
|
1344
|
+
* canvas grid is audible to assistive technology.
|
|
1345
|
+
*/
|
|
1346
|
+
const activeCellAnnouncement = useMemo(() => {
|
|
1347
|
+
if (!activeCell)
|
|
1348
|
+
return "";
|
|
1349
|
+
const address = cellToAddress(activeCell) ?? "";
|
|
1350
|
+
const value = getFormattedValue(sheetId, activeCell.rowIndex, activeCell.columnIndex);
|
|
1351
|
+
return !isNilOrBlank(value) ? `${address} ${value}` : address;
|
|
1352
|
+
}, [activeCell, getFormattedValue, sheetId]);
|
|
1353
|
+
/**
|
|
1354
|
+
* Has the row been resized by user
|
|
1355
|
+
*/
|
|
1356
|
+
const isRowResizedByUser = useCallback((rowIndex) => !!rowMetadata?.[rowIndex]?.resizedByUser, [rowMetadata]);
|
|
1357
|
+
/**
|
|
1358
|
+
* Check if the cell is banded
|
|
1359
|
+
*/
|
|
1360
|
+
const isBandedCell = useCallback((rowIndex, columnIndex) => {
|
|
1361
|
+
return bandedCells.has(cellIdentifier(rowIndex, columnIndex));
|
|
1362
|
+
}, [bandedCells]);
|
|
1363
|
+
/**
|
|
1364
|
+
* Check if table header cell is calculated column
|
|
1365
|
+
*/
|
|
1366
|
+
const isCalculatedColumnHeaderCell = useCallback((rowIndex, columnIndex) => {
|
|
1367
|
+
/* Table header cells, Cell has filter icon */
|
|
1368
|
+
const [, , , calculatedHeaderCell] = tableHeaderCells;
|
|
1369
|
+
return calculatedHeaderCell.has(cellIdentifier(rowIndex, columnIndex));
|
|
1370
|
+
}, [tableHeaderCells]);
|
|
1371
|
+
/**
|
|
1372
|
+
* If a cell is hidden,
|
|
1373
|
+
* We tell the grid to skip rendering
|
|
1374
|
+
*/
|
|
1375
|
+
const isHiddenCell = useCallback((rowIndex, columnIndex) => {
|
|
1376
|
+
if (isRowHeader(columnIndex) || isColumnHeader(rowIndex)) {
|
|
1377
|
+
return false;
|
|
1378
|
+
}
|
|
1379
|
+
if (isTableHeader(rowIndex, columnIndex)) {
|
|
1380
|
+
return false;
|
|
1381
|
+
}
|
|
1382
|
+
if (isBandedCell(rowIndex, columnIndex)) {
|
|
1383
|
+
return false;
|
|
1384
|
+
}
|
|
1385
|
+
if (getDataValidationRule(sheetId, rowIndex, columnIndex)) {
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
// Show cells with diffs when comparing (including deleted cells)
|
|
1389
|
+
if (isComparing && getCellDiff?.(sheetId, rowIndex, columnIndex)) {
|
|
1390
|
+
return false;
|
|
1391
|
+
}
|
|
1392
|
+
const effectiveCellFormat = getEffectiveCellFormat(sheetId, rowIndex, columnIndex);
|
|
1393
|
+
const formattedValue = getFormattedValue?.(sheetId, rowIndex, columnIndex);
|
|
1394
|
+
// Structured result
|
|
1395
|
+
const structuredValue = getEffectiveValue(sheetId, rowIndex, columnIndex)?.structuredValue;
|
|
1396
|
+
return (getNote(sheetId, rowIndex, columnIndex) === undefined &&
|
|
1397
|
+
getComment(sheetId, rowIndex, columnIndex) === undefined &&
|
|
1398
|
+
getCitation(sheetId, rowIndex, columnIndex) === undefined &&
|
|
1399
|
+
isNilOrBlank(formattedValue) &&
|
|
1400
|
+
isNil(structuredValue) &&
|
|
1401
|
+
getCellImageUrl(sheetId, rowIndex, columnIndex) === undefined &&
|
|
1402
|
+
effectiveCellFormat?.backgroundColor === undefined &&
|
|
1403
|
+
effectiveCellFormat?.borders === undefined);
|
|
1404
|
+
}, [
|
|
1405
|
+
sheetId,
|
|
1406
|
+
getFormattedValue,
|
|
1407
|
+
getCellImageUrl,
|
|
1408
|
+
getNote,
|
|
1409
|
+
getComment,
|
|
1410
|
+
getCitation,
|
|
1411
|
+
getEffectiveCellFormat,
|
|
1412
|
+
getDataValidationRule,
|
|
1413
|
+
getEffectiveValue,
|
|
1414
|
+
isRowHeader,
|
|
1415
|
+
isColumnHeader,
|
|
1416
|
+
isTableHeader,
|
|
1417
|
+
isBandedCell,
|
|
1418
|
+
isComparing,
|
|
1419
|
+
getCellDiff,
|
|
1420
|
+
]);
|
|
1421
|
+
/**
|
|
1422
|
+
* Can a cell overflow to adjoining cell
|
|
1423
|
+
*/
|
|
1424
|
+
const canOverflowToNextCell = useCallback(({ rowIndex, columnIndex }) => {
|
|
1425
|
+
if (isRowHeader(columnIndex) || isColumnHeader(rowIndex)) {
|
|
1426
|
+
return false;
|
|
1427
|
+
}
|
|
1428
|
+
if (isTableHeader(rowIndex, columnIndex)) {
|
|
1429
|
+
return false;
|
|
1430
|
+
}
|
|
1431
|
+
if (isBandedCell(rowIndex, columnIndex)) {
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
1434
|
+
if (getDataValidationRule(sheetId, rowIndex, columnIndex)) {
|
|
1435
|
+
return false;
|
|
1436
|
+
}
|
|
1437
|
+
const [expandable] = getCellGroupingInfo(sheetId, rowIndex, columnIndex);
|
|
1438
|
+
if (expandable) {
|
|
1439
|
+
return false;
|
|
1440
|
+
}
|
|
1441
|
+
const formattedValue = getFormattedValue?.(sheetId, rowIndex, columnIndex);
|
|
1442
|
+
return (getNote(sheetId, rowIndex, columnIndex) === undefined &&
|
|
1443
|
+
isNilOrBlank(formattedValue) &&
|
|
1444
|
+
getCellImageUrl(sheetId, rowIndex, columnIndex) === undefined);
|
|
1445
|
+
}, [
|
|
1446
|
+
sheetId,
|
|
1447
|
+
getFormattedValue,
|
|
1448
|
+
getCellGroupingInfo,
|
|
1449
|
+
getCellImageUrl,
|
|
1450
|
+
getNote,
|
|
1451
|
+
getDataValidationRule,
|
|
1452
|
+
isRowHeader,
|
|
1453
|
+
isColumnHeader,
|
|
1454
|
+
isTableHeader,
|
|
1455
|
+
isBandedCell,
|
|
1456
|
+
]);
|
|
1457
|
+
/**
|
|
1458
|
+
* If a cell is hidden,
|
|
1459
|
+
* We tell the grid to skip rendering
|
|
1460
|
+
*/
|
|
1461
|
+
const isHiddenOverlay = useCallback((rowIndex, columnIndex) => {
|
|
1462
|
+
if (isRowHeader(columnIndex) || isColumnHeader(rowIndex)) {
|
|
1463
|
+
return true;
|
|
1464
|
+
}
|
|
1465
|
+
return (getEffectiveCellFormat(sheetId, rowIndex, columnIndex)?.borders ===
|
|
1466
|
+
undefined);
|
|
1467
|
+
}, [getEffectiveCellFormat, isRowHeader, isColumnHeader, sheetId]);
|
|
1468
|
+
/**
|
|
1469
|
+
* If a cell is hidden,
|
|
1470
|
+
* We tell the grid to skip rendering
|
|
1471
|
+
*/
|
|
1472
|
+
const isHiddenBackground = useCallback((rowIndex, columnIndex) => {
|
|
1473
|
+
if (isRowHeader(columnIndex) || isColumnHeader(rowIndex)) {
|
|
1474
|
+
return true;
|
|
1475
|
+
}
|
|
1476
|
+
if (isMergedCell({ rowIndex, columnIndex })) {
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
// Skip the bg shape only when the cell has NO visible fill at all.
|
|
1480
|
+
// A cell counts as "has fill" if any of these are present:
|
|
1481
|
+
// - backgroundColor (solid)
|
|
1482
|
+
// - fillPattern (other than "none")
|
|
1483
|
+
// - gradient (with at least one stop)
|
|
1484
|
+
// The earlier version only checked backgroundColor, which
|
|
1485
|
+
// incorrectly hid pattern-only and gradient-only cells.
|
|
1486
|
+
const fmt = getEffectiveCellFormat(sheetId, rowIndex, columnIndex);
|
|
1487
|
+
if (!fmt)
|
|
1488
|
+
return true;
|
|
1489
|
+
if (!isNil(fmt.backgroundColor)) {
|
|
1490
|
+
return false;
|
|
1491
|
+
}
|
|
1492
|
+
if (fmt.fillPattern && fmt.fillPattern !== "none") {
|
|
1493
|
+
return false;
|
|
1494
|
+
}
|
|
1495
|
+
if (fmt.gradient && (fmt.gradient.stops?.length ?? 0) > 0) {
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
1498
|
+
return true;
|
|
1499
|
+
}, [
|
|
1500
|
+
getEffectiveCellFormat,
|
|
1501
|
+
isRowHeader,
|
|
1502
|
+
isColumnHeader,
|
|
1503
|
+
isMergedCell,
|
|
1504
|
+
sheetId,
|
|
1505
|
+
]);
|
|
1506
|
+
/**
|
|
1507
|
+
* Row height getter
|
|
1508
|
+
*/
|
|
1509
|
+
const rowHeight = useCallback((rowIndex) => {
|
|
1510
|
+
if (isColumnHeader(rowIndex)) {
|
|
1511
|
+
return showHeaders ? columnHeaderHeight : 0;
|
|
1512
|
+
}
|
|
1513
|
+
if (isHiddenRow(rowIndex)) {
|
|
1514
|
+
return 0;
|
|
1515
|
+
}
|
|
1516
|
+
return rowMetadata?.[rowIndex]?.size ?? defaultRowHeight;
|
|
1517
|
+
}, [
|
|
1518
|
+
isHiddenRow,
|
|
1519
|
+
isColumnHeader,
|
|
1520
|
+
rowMetadata,
|
|
1521
|
+
columnHeaderHeight,
|
|
1522
|
+
defaultRowHeight,
|
|
1523
|
+
showHeaders,
|
|
1524
|
+
]);
|
|
1525
|
+
/**
|
|
1526
|
+
* Column width getter
|
|
1527
|
+
*/
|
|
1528
|
+
const columnWidth = useCallback((columnIndex) => {
|
|
1529
|
+
if (isRowHeader(columnIndex)) {
|
|
1530
|
+
return showHeaders ? rowHeaderWidth : 0;
|
|
1531
|
+
}
|
|
1532
|
+
if (isHiddenColumn(columnIndex)) {
|
|
1533
|
+
return 0;
|
|
1534
|
+
}
|
|
1535
|
+
return columnMetadata?.[columnIndex]?.size ?? defaultColumnWidth;
|
|
1536
|
+
}, [
|
|
1537
|
+
isHiddenColumn,
|
|
1538
|
+
isRowHeader,
|
|
1539
|
+
columnMetadata,
|
|
1540
|
+
rowHeaderWidth,
|
|
1541
|
+
defaultColumnWidth,
|
|
1542
|
+
showHeaders,
|
|
1543
|
+
]);
|
|
1544
|
+
/**
|
|
1545
|
+
* Get actual cell width with merged cells
|
|
1546
|
+
*/
|
|
1547
|
+
const getActualCellWidth = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
1548
|
+
const actualBounds = mergedCellMap.get(cellIdentifier(rowIndex, columnIndex));
|
|
1549
|
+
let cellWidth = columnWidth(columnIndex);
|
|
1550
|
+
if (actualBounds) {
|
|
1551
|
+
let left = actualBounds.startColumnIndex + 1;
|
|
1552
|
+
while (left <= actualBounds.endColumnIndex) {
|
|
1553
|
+
cellWidth += columnWidth(left);
|
|
1554
|
+
left++;
|
|
1555
|
+
}
|
|
1556
|
+
return cellWidth;
|
|
1557
|
+
}
|
|
1558
|
+
return cellWidth;
|
|
1559
|
+
}, [columnWidth, mergedCellMap]);
|
|
1560
|
+
/**
|
|
1561
|
+
* Gather selected headers
|
|
1562
|
+
* O(n)
|
|
1563
|
+
* Reduces Space Complexity by using `all`
|
|
1564
|
+
*/
|
|
1565
|
+
const [selectedRows, selectedColumns, selectedRowHeaders, selectedColumnHeaders, selectedRowHeadersIds, selectedColumnHeadersIds,] = useSelectedRowsColumns({
|
|
1566
|
+
activeCell,
|
|
1567
|
+
selections,
|
|
1568
|
+
selectionLeftBound,
|
|
1569
|
+
selectionTopBound,
|
|
1570
|
+
rowCount,
|
|
1571
|
+
columnCount,
|
|
1572
|
+
getCellBounds,
|
|
1573
|
+
});
|
|
1574
|
+
// Named ranges for editor dropdown
|
|
1575
|
+
const getNamedRanges = useCallbackRef(useCallback(() => namedRanges?.map((range) => ({
|
|
1576
|
+
title: range.name,
|
|
1577
|
+
category: "namedrange",
|
|
1578
|
+
})), [namedRanges]));
|
|
1579
|
+
// Get cell properties
|
|
1580
|
+
const getStructuredProperties = useCallback((sheetName, rowIndex, columnIndex) => {
|
|
1581
|
+
const newSheetId = sheetName
|
|
1582
|
+
? getSheetId?.(sheetName) ?? sheetId
|
|
1583
|
+
: sheetId;
|
|
1584
|
+
// Pass it along to parent prop
|
|
1585
|
+
if (getStructuredPropertiesProp) {
|
|
1586
|
+
return getStructuredPropertiesProp(newSheetId, rowIndex, columnIndex);
|
|
1587
|
+
}
|
|
1588
|
+
// Get cell data
|
|
1589
|
+
const structuredValue = getEffectiveValue(newSheetId, rowIndex, columnIndex)?.structuredValue;
|
|
1590
|
+
const propertyNames = structuredValue
|
|
1591
|
+
? getNestedPropertyNames(structuredValue)
|
|
1592
|
+
: [];
|
|
1593
|
+
return propertyNames.map((title) => {
|
|
1594
|
+
return {
|
|
1595
|
+
title,
|
|
1596
|
+
category: "property",
|
|
1597
|
+
};
|
|
1598
|
+
});
|
|
1599
|
+
}, [
|
|
1600
|
+
getSheetId,
|
|
1601
|
+
getEffectiveValue,
|
|
1602
|
+
getCellData,
|
|
1603
|
+
sheetId,
|
|
1604
|
+
getStructuredPropertiesProp,
|
|
1605
|
+
]);
|
|
1606
|
+
// Table names for editor dropdown
|
|
1607
|
+
const getTableNames = useCallbackRef(useCallback(() => {
|
|
1608
|
+
return tables?.map(({ title }) => ({ title, category: "table" }));
|
|
1609
|
+
}, [tables]));
|
|
1610
|
+
// Column names for editor dropdown
|
|
1611
|
+
const getTableColumnNames = useCallbackRef(useCallback((tableName) => {
|
|
1612
|
+
const editingCell = editingCellCoordinate;
|
|
1613
|
+
const editingSheetId = editingCellCoordinate?.sheetId;
|
|
1614
|
+
const table = tables?.find((table) => {
|
|
1615
|
+
if (tableName) {
|
|
1616
|
+
return table.title === tableName;
|
|
1617
|
+
}
|
|
1618
|
+
return editingCell
|
|
1619
|
+
? isCellWithinBounds(editingCell, table.range) &&
|
|
1620
|
+
table.sheetId === editingSheetId
|
|
1621
|
+
: true;
|
|
1622
|
+
});
|
|
1623
|
+
if (!table) {
|
|
1624
|
+
return DEFAULT_ARRAY;
|
|
1625
|
+
}
|
|
1626
|
+
return table.columns?.map((column) => ({
|
|
1627
|
+
title: column.name,
|
|
1628
|
+
category: "column",
|
|
1629
|
+
}));
|
|
1630
|
+
}, [tables, editingCellCoordinate]));
|
|
1631
|
+
/**
|
|
1632
|
+
* Mosue down interceptors for useSelection hook so
|
|
1633
|
+
* user can select entire column or row when selecting
|
|
1634
|
+
* header cells
|
|
1635
|
+
*/
|
|
1636
|
+
const { onMouseDownInterceptor, onMouseMoveInterceptor } = useSelectionInterceptors({
|
|
1637
|
+
sheetId,
|
|
1638
|
+
rowCount,
|
|
1639
|
+
columnCount,
|
|
1640
|
+
frozenColumns,
|
|
1641
|
+
frozenRows,
|
|
1642
|
+
selectionLeftBound,
|
|
1643
|
+
selectionTopBound,
|
|
1644
|
+
isHiddenColumn,
|
|
1645
|
+
isHiddenRow,
|
|
1646
|
+
isRowHeader,
|
|
1647
|
+
isColumnHeader,
|
|
1648
|
+
getViewPort,
|
|
1649
|
+
onChangeActiveCell,
|
|
1650
|
+
scrollToCell,
|
|
1651
|
+
isMergedCell,
|
|
1652
|
+
});
|
|
1653
|
+
/**
|
|
1654
|
+
* When user selections full rows
|
|
1655
|
+
* or columns, we have to ignore
|
|
1656
|
+
* merged cells
|
|
1657
|
+
*/
|
|
1658
|
+
const canSelectionSpanMergedCells = useCallback((start, end) => {
|
|
1659
|
+
if (start.rowIndex < selectionTopBound && end.rowIndex === rowCount) {
|
|
1660
|
+
return false;
|
|
1661
|
+
}
|
|
1662
|
+
if (start.columnIndex < selectionLeftBound &&
|
|
1663
|
+
end.columnIndex === columnCount) {
|
|
1664
|
+
return false;
|
|
1665
|
+
}
|
|
1666
|
+
return true;
|
|
1667
|
+
}, [rowCount, columnCount, selectionTopBound, selectionLeftBound]);
|
|
1668
|
+
/**
|
|
1669
|
+
* For autofitting text, extra space is
|
|
1670
|
+
* added for filter icon, dropdown icon etc
|
|
1671
|
+
*/
|
|
1672
|
+
const getCellSpacing = useCallback((sheetId, rowIndex, columnIndex, axis) => {
|
|
1673
|
+
/**
|
|
1674
|
+
* Icons in cells do not affect
|
|
1675
|
+
* height of the rows. Explore later
|
|
1676
|
+
*/
|
|
1677
|
+
if (axis === "x") {
|
|
1678
|
+
return 0;
|
|
1679
|
+
}
|
|
1680
|
+
/* Data validation arrow */
|
|
1681
|
+
const dataValidation = getDataValidationRule(sheetId, rowIndex, columnIndex);
|
|
1682
|
+
const additionalCellSpacing = getAdditionalCellSpacing?.(sheetId, rowIndex, columnIndex) ?? 0;
|
|
1683
|
+
const showArrow = showValidationDropdownArrow(dataValidation);
|
|
1684
|
+
const showChip = getCellMetaType(sheetId, rowIndex, columnIndex) === "people";
|
|
1685
|
+
const [expandable] = getCellGroupingInfo(sheetId, rowIndex, columnIndex);
|
|
1686
|
+
const iconSpacing = DEFAULT_CELL_SPACING;
|
|
1687
|
+
const expandableSpacing = expandable
|
|
1688
|
+
? (EXPAND_COLLAPSE_ICON_WIDTH + iconSpacing) * scale
|
|
1689
|
+
: 0;
|
|
1690
|
+
const indentSpacing = (getCellIndent(sheetId, rowIndex, columnIndex) ?? 0) * INDENT_SPACING;
|
|
1691
|
+
// Cell has dropdown icon
|
|
1692
|
+
const arrowSpacing = showArrow
|
|
1693
|
+
? (ARROW_DOWN_WIDTH + iconSpacing) * scale
|
|
1694
|
+
: 0;
|
|
1695
|
+
// Cell has chip
|
|
1696
|
+
const chipSpacing = showChip ? (CHIP_SPACING + iconSpacing) * scale : 0;
|
|
1697
|
+
/* Calculated column icon */
|
|
1698
|
+
const calculatedIconWidth = showCalculatedColumnIcon &&
|
|
1699
|
+
isTableHeader(rowIndex, columnIndex) &&
|
|
1700
|
+
isCalculatedColumnHeaderCell(rowIndex, columnIndex)
|
|
1701
|
+
? (CALCULATED_ICON_WIDTH + iconSpacing) * scale
|
|
1702
|
+
: 0;
|
|
1703
|
+
/* Table header cells, Cell has filter icon */
|
|
1704
|
+
const tableFilterSpacing = isTableFilterVisible(rowIndex, columnIndex)
|
|
1705
|
+
? (FILTER_ICON_WIDTH + iconSpacing) * scale
|
|
1706
|
+
: 0;
|
|
1707
|
+
/* Conditional-format iconSet glyph reserved on the left of the cell.
|
|
1708
|
+
The cell renderer subtracts this from the text area, so row-height
|
|
1709
|
+
autofit must include it to measure wrapped text at the same width. */
|
|
1710
|
+
const conditionalIconSpacing = getEffectiveCellFormat(sheetId, rowIndex, columnIndex)?.conditionalIcon
|
|
1711
|
+
? (CF_ICON_WIDTH + CF_ICON_SPACING) * scale
|
|
1712
|
+
: 0;
|
|
1713
|
+
return (arrowSpacing +
|
|
1714
|
+
chipSpacing +
|
|
1715
|
+
indentSpacing +
|
|
1716
|
+
expandableSpacing +
|
|
1717
|
+
calculatedIconWidth +
|
|
1718
|
+
tableFilterSpacing +
|
|
1719
|
+
conditionalIconSpacing +
|
|
1720
|
+
additionalCellSpacing);
|
|
1721
|
+
}, [
|
|
1722
|
+
isTableFilterVisible,
|
|
1723
|
+
getDataValidationRule,
|
|
1724
|
+
getCellMetaType,
|
|
1725
|
+
getCellIndent,
|
|
1726
|
+
showCalculatedColumnIcon,
|
|
1727
|
+
isTableHeader,
|
|
1728
|
+
isCalculatedColumnHeaderCell,
|
|
1729
|
+
scale,
|
|
1730
|
+
getCellGroupingInfo,
|
|
1731
|
+
getAdditionalCellSpacing,
|
|
1732
|
+
getEffectiveCellFormat,
|
|
1733
|
+
]);
|
|
1734
|
+
/**
|
|
1735
|
+
* Column resizer
|
|
1736
|
+
* Enables auto resizing
|
|
1737
|
+
* rows and columns
|
|
1738
|
+
*/
|
|
1739
|
+
const { getColumnWidth, getRowHeight, getCellDimensions, getCellDimensionsStable, getTextDimension, } = useSizer({
|
|
1740
|
+
frozenRows,
|
|
1741
|
+
frozenColumns,
|
|
1742
|
+
scale,
|
|
1743
|
+
minColumnDimension: MIN_COLUMN_WIDTH,
|
|
1744
|
+
minRowDimension: defaultRowHeight,
|
|
1745
|
+
cellHorizontalSpacing: 5, // 2 + 2 + (padding) + 1 border
|
|
1746
|
+
cellVerticalSpacing: 5, // 2 + 2 (padding) + 1 border
|
|
1747
|
+
isHiddenRow,
|
|
1748
|
+
isHiddenColumn,
|
|
1749
|
+
getTextFormat,
|
|
1750
|
+
getTextFormatRuns,
|
|
1751
|
+
getTextValue: getFormattedValue,
|
|
1752
|
+
getSpacing: getCellSpacing,
|
|
1753
|
+
getActualCellWidth,
|
|
1754
|
+
shouldWrapCell,
|
|
1755
|
+
columnWidth,
|
|
1756
|
+
getViewPort,
|
|
1757
|
+
columnCount,
|
|
1758
|
+
rowCount,
|
|
1759
|
+
getDataRowCount,
|
|
1760
|
+
fontSize: defaultFontSizePoint,
|
|
1761
|
+
resizeStrategy: "full",
|
|
1762
|
+
});
|
|
1763
|
+
/**
|
|
1764
|
+
* Called when user tries to
|
|
1765
|
+
* autofit a column or row
|
|
1766
|
+
*/
|
|
1767
|
+
const handleAutoFit = useCallback((index, axis) => {
|
|
1768
|
+
const indexes = axis === "x" ? selectedRowHeadersIds : selectedColumnHeadersIds;
|
|
1769
|
+
// Callback
|
|
1770
|
+
onAutoResize?.(sheetId, indexes.length && indexes.includes(index) ? indexes : [index], axis);
|
|
1771
|
+
// Keep the focus back
|
|
1772
|
+
focusSheet();
|
|
1773
|
+
}, [
|
|
1774
|
+
onAutoResize,
|
|
1775
|
+
focusSheet,
|
|
1776
|
+
selectedColumnHeadersIds,
|
|
1777
|
+
selectedRowHeadersIds,
|
|
1778
|
+
sheetId,
|
|
1779
|
+
]);
|
|
1780
|
+
/* Check if sheet is focused */
|
|
1781
|
+
const isSheetFocused = useCallback(() => canUseDOM ? document.activeElement === cellEditorInstance?.el() : false, [cellEditorInstance]);
|
|
1782
|
+
/**
|
|
1783
|
+
* Get Cell Editor
|
|
1784
|
+
*/
|
|
1785
|
+
const getEditor = useCallback((props) => {
|
|
1786
|
+
const { cell = defaultCellCoords, sheetId, editingSheetId = sheetId, } = props;
|
|
1787
|
+
const { rowIndex, columnIndex } = cell ?? defaultCellCoords;
|
|
1788
|
+
const cellFormat = !isNil(props.editingSheetId)
|
|
1789
|
+
? getEffectiveCellFormat(props.editingSheetId, rowIndex, columnIndex)
|
|
1790
|
+
: undefined;
|
|
1791
|
+
const dataValidation = getDataValidationRule(editingSheetId, rowIndex, columnIndex);
|
|
1792
|
+
const address = cellToAddress(cell);
|
|
1793
|
+
const sheetName = getSheetName?.(sheetId);
|
|
1794
|
+
const editingSheetName = getSheetName?.(editingSheetId);
|
|
1795
|
+
const effectiveValue = getEffectiveValue(editingSheetId, rowIndex, columnIndex);
|
|
1796
|
+
const horizontalAlignment = getEditorHorizontalAlignment(editingSheetId, rowIndex, columnIndex);
|
|
1797
|
+
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 }));
|
|
1798
|
+
}, [
|
|
1799
|
+
scale,
|
|
1800
|
+
getEffectiveCellFormat,
|
|
1801
|
+
getDataValidationRule,
|
|
1802
|
+
getFormattedValuesFromAddress,
|
|
1803
|
+
CellEditor,
|
|
1804
|
+
getSheetName,
|
|
1805
|
+
showFormulaHelp,
|
|
1806
|
+
onHideFormulaHelp,
|
|
1807
|
+
onShowFormulaHelp,
|
|
1808
|
+
tokenizer,
|
|
1809
|
+
cellBackgroundColor,
|
|
1810
|
+
cellColor,
|
|
1811
|
+
functionDescriptions,
|
|
1812
|
+
getNamedRanges,
|
|
1813
|
+
getTableNames,
|
|
1814
|
+
getStructuredProperties,
|
|
1815
|
+
getTableColumnNames,
|
|
1816
|
+
onRequestCalculate,
|
|
1817
|
+
getEffectiveValue,
|
|
1818
|
+
getEditorHorizontalAlignment,
|
|
1819
|
+
locale,
|
|
1820
|
+
theme,
|
|
1821
|
+
SuggestionsDropdown,
|
|
1822
|
+
stickyEditor,
|
|
1823
|
+
defaultFontSizePoint,
|
|
1824
|
+
getMentions,
|
|
1825
|
+
getFunctionParameterSuggestions,
|
|
1826
|
+
shouldFetchFunctionParameters,
|
|
1827
|
+
MentionTagComponent,
|
|
1828
|
+
MentionDropdownItemComponent,
|
|
1829
|
+
]);
|
|
1830
|
+
/**
|
|
1831
|
+
* Popover cell
|
|
1832
|
+
*/
|
|
1833
|
+
const { popoverComponent, popoverRange, showCellPopover, hideCellPopover } = useCellPopover({
|
|
1834
|
+
sheetId,
|
|
1835
|
+
getCellPopoverContent: getCellPopoverContent ?? getFormattedValue,
|
|
1836
|
+
getCellOffsetFromCoords,
|
|
1837
|
+
getScrollPosition,
|
|
1838
|
+
isFrozenColumn,
|
|
1839
|
+
isFrozenRow,
|
|
1840
|
+
onChangeActiveSheet,
|
|
1841
|
+
});
|
|
1842
|
+
/**
|
|
1843
|
+
* Get tooltip component of a cell
|
|
1844
|
+
* Only error, invalid values are
|
|
1845
|
+
* shown in tooltip
|
|
1846
|
+
*/
|
|
1847
|
+
/**
|
|
1848
|
+
* Compose host tooltip content with the data-validation input message.
|
|
1849
|
+
* Host-provided content wins; otherwise, when the cell is not already showing
|
|
1850
|
+
* an error / invalid marker, surface the rule's input message (Excel's
|
|
1851
|
+
* "show input message when cell is selected").
|
|
1852
|
+
*/
|
|
1853
|
+
const getTooltipContentWithValidation = useCallback((tooltipSheetId, rowIndex, columnIndex) => {
|
|
1854
|
+
const hostContent = getTooltipContent?.(tooltipSheetId, rowIndex, columnIndex);
|
|
1855
|
+
if (hostContent != null) {
|
|
1856
|
+
return hostContent;
|
|
1857
|
+
}
|
|
1858
|
+
const error = getErrorValue(tooltipSheetId, rowIndex, columnIndex);
|
|
1859
|
+
if (error?.type === "Error" || error?.type === "Invalid") {
|
|
1860
|
+
return undefined;
|
|
1861
|
+
}
|
|
1862
|
+
const rule = getDataValidationRule(tooltipSheetId, rowIndex, columnIndex);
|
|
1863
|
+
const inputMessage = rule?.inputMessage;
|
|
1864
|
+
if (!inputMessage || (!inputMessage.title && !inputMessage.message)) {
|
|
1865
|
+
return undefined;
|
|
1866
|
+
}
|
|
1867
|
+
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" },
|
|
1868
|
+
inputMessage.title ? (React.createElement("div", { className: "font-bold font-system text-sm" }, inputMessage.title)) : null,
|
|
1869
|
+
inputMessage.message ? (React.createElement("div", { className: "text-xs font-system whitespace-pre-wrap" }, inputMessage.message)) : null));
|
|
1870
|
+
}, [getTooltipContent, getErrorValue, getDataValidationRule]);
|
|
1871
|
+
const getTooltip = useGetTooltip({
|
|
1872
|
+
sheetId,
|
|
1873
|
+
getErrorValue,
|
|
1874
|
+
getNote,
|
|
1875
|
+
getFormattedValue,
|
|
1876
|
+
getHyperlink,
|
|
1877
|
+
getTooltipContent: getTooltipContentWithValidation,
|
|
1878
|
+
errorResolutionComponent,
|
|
1879
|
+
CellTooltip,
|
|
1880
|
+
showNotes,
|
|
1881
|
+
});
|
|
1882
|
+
/**
|
|
1883
|
+
* Selection change handler
|
|
1884
|
+
*/
|
|
1885
|
+
const onSelectionChange = useSelectionChange({
|
|
1886
|
+
onChangeSelections,
|
|
1887
|
+
getSheetName,
|
|
1888
|
+
sheetId,
|
|
1889
|
+
});
|
|
1890
|
+
// DataRegion boundaries for selection
|
|
1891
|
+
const dataRegionBoundaries = useMemo(() => tables
|
|
1892
|
+
?.filter((table) => table.sheetId === sheetId)
|
|
1893
|
+
.map((table) => table.range), [tables, sheetId]);
|
|
1894
|
+
/**
|
|
1895
|
+
* Handle grid selections
|
|
1896
|
+
*/
|
|
1897
|
+
const { onMouseDown: onMouseDownSelection, onPointerDown: onPointerDownSelection, onKeyDown: onKeyDownSelection, fillSelection, onFillHandleMouseDown, onFillHandleDoubleClick, isDragging, isFilling, isSelectionInProgress, draggedSelection, onSelectionMouseDown, setActiveCell, initialDraggedSelection, updateSelectionStartEndReference, selectColumn, getContentfulGridRangeAroundCell, newSelection, modifySelection, clearSelections, } = useSelection({
|
|
1898
|
+
sheetId,
|
|
1899
|
+
getDataRowCount,
|
|
1900
|
+
enableDataBoundaryNavigation,
|
|
1901
|
+
allowDeselectSelection: false,
|
|
1902
|
+
formulaMode,
|
|
1903
|
+
enableSelectOnEnterKey: !enableEditOnEnterKey,
|
|
1904
|
+
newSelectionMode: formulaMode && canSelectCells ? selectionMode : "clear",
|
|
1905
|
+
activeCell,
|
|
1906
|
+
selections,
|
|
1907
|
+
onChangeSelections: onSelectionChange,
|
|
1908
|
+
onChangeActiveCell,
|
|
1909
|
+
columnCount,
|
|
1910
|
+
rowCount,
|
|
1911
|
+
getValue: getUserEnteredStringValue,
|
|
1912
|
+
selectionLeftBound,
|
|
1913
|
+
selectionTopBound,
|
|
1914
|
+
canSelectionSpanMergedCells,
|
|
1915
|
+
mouseDownInterceptor: onMouseDownInterceptor,
|
|
1916
|
+
mouseMoveInterceptor: onMouseMoveInterceptor,
|
|
1917
|
+
selectionPolicy,
|
|
1918
|
+
getCellCoordsFromOffset,
|
|
1919
|
+
getCellBounds,
|
|
1920
|
+
getViewPort,
|
|
1921
|
+
focus: focusSheet,
|
|
1922
|
+
scrollToCell,
|
|
1923
|
+
isMergedCell,
|
|
1924
|
+
onFill,
|
|
1925
|
+
onMoveSelection,
|
|
1926
|
+
isHiddenColumn,
|
|
1927
|
+
isHiddenRow,
|
|
1928
|
+
isRowHeader,
|
|
1929
|
+
isColumnHeader,
|
|
1930
|
+
isTouchDevice,
|
|
1931
|
+
dataRegionBoundaries,
|
|
1932
|
+
});
|
|
1933
|
+
/**
|
|
1934
|
+
* Copy, Paste and Cut hook
|
|
1935
|
+
*/
|
|
1936
|
+
const { copiedSelections, clearCopiedSelections, copy, cut, paste, onInternalCopy, onInternalCut, onInternalPaste, } = useCopyPasteCut({
|
|
1937
|
+
activeCell,
|
|
1938
|
+
selections,
|
|
1939
|
+
sheetId,
|
|
1940
|
+
focusSheet,
|
|
1941
|
+
onPaste,
|
|
1942
|
+
onCopy,
|
|
1943
|
+
onCut,
|
|
1944
|
+
});
|
|
1945
|
+
/**
|
|
1946
|
+
* After formula mode
|
|
1947
|
+
* Recover old selections
|
|
1948
|
+
*/
|
|
1949
|
+
const restoreSelections = useCallbackRef(useCallback(() => {
|
|
1950
|
+
if (!formulaMode || !formulaSelections.length) {
|
|
1951
|
+
return;
|
|
1952
|
+
}
|
|
1953
|
+
const len = selections.length - formulaSelections.length;
|
|
1954
|
+
onChangeSelections?.(sheetId, selections.filter((_, i) => i < len));
|
|
1955
|
+
}, [
|
|
1956
|
+
sheetId,
|
|
1957
|
+
selections,
|
|
1958
|
+
formulaMode,
|
|
1959
|
+
formulaSelections,
|
|
1960
|
+
onChangeSelections,
|
|
1961
|
+
]));
|
|
1962
|
+
/**
|
|
1963
|
+
* Callback when editor value changes
|
|
1964
|
+
*/
|
|
1965
|
+
const onEditorChange = useEditorChange({
|
|
1966
|
+
selections,
|
|
1967
|
+
onChangeActiveCell,
|
|
1968
|
+
onChangeSelections,
|
|
1969
|
+
getSelectionsFromFormula,
|
|
1970
|
+
onChangeEditorValue,
|
|
1971
|
+
});
|
|
1972
|
+
// Get final row height to expand to based on value of a cell
|
|
1973
|
+
const getFinalRowHeight = useCallbackRef(useCallback((sheetId, rowIndex, columnIndex, options) => {
|
|
1974
|
+
if (isRowResizedByUser(rowIndex)) {
|
|
1975
|
+
return undefined;
|
|
1976
|
+
}
|
|
1977
|
+
const { height } = getCellDimensions(sheetId, rowIndex, columnIndex, "x", options);
|
|
1978
|
+
// The rest of the row's required height — the max content height
|
|
1979
|
+
// over every OTHER cell in the row (the edited column is excluded;
|
|
1980
|
+
// its requirement is the freshly measured `height` above). Already
|
|
1981
|
+
// floored at the default row height by `getRowHeight`.
|
|
1982
|
+
const currentRowHeight = getRowHeight?.(sheetId, rowIndex,
|
|
1983
|
+
// Exclude columns within the selection
|
|
1984
|
+
(colIndex) => colIndex >= columnIndex && colIndex <= columnIndex) ?? defaultRowHeight;
|
|
1985
|
+
// Row auto-height = max requirement across ALL cells in the row —
|
|
1986
|
+
// committing a short value into one cell must not shrink a row that
|
|
1987
|
+
// another cell's wrapped/multi-line content keeps tall. Rows pinned
|
|
1988
|
+
// by a user drag never reach this point (`isRowResizedByUser` above).
|
|
1989
|
+
const finalHeight = Math.max(currentRowHeight, height / scale);
|
|
1990
|
+
if (finalHeight !== rowHeight(rowIndex)) {
|
|
1991
|
+
return finalHeight;
|
|
1992
|
+
}
|
|
1993
|
+
}, [
|
|
1994
|
+
scale,
|
|
1995
|
+
defaultRowHeight,
|
|
1996
|
+
isRowResizedByUser,
|
|
1997
|
+
getCellDimensions,
|
|
1998
|
+
rowHeight,
|
|
1999
|
+
getRowHeight,
|
|
2000
|
+
]));
|
|
2001
|
+
/**
|
|
2002
|
+
* Called when user submits a value
|
|
2003
|
+
* from the cell editor
|
|
2004
|
+
*/
|
|
2005
|
+
const onEditorSubmit = useEditorSubmit({
|
|
2006
|
+
sheetId,
|
|
2007
|
+
onChangeActiveSheet,
|
|
2008
|
+
setActiveCell,
|
|
2009
|
+
onComplete: restoreSelections,
|
|
2010
|
+
onChange,
|
|
2011
|
+
getCommitValidation,
|
|
2012
|
+
showValidationAlert,
|
|
2013
|
+
});
|
|
2014
|
+
/**
|
|
2015
|
+
* User cancels editing the cell
|
|
2016
|
+
*/
|
|
2017
|
+
const onEditorCancel = useEditorCancel({
|
|
2018
|
+
sheetId,
|
|
2019
|
+
onChangeActiveSheet,
|
|
2020
|
+
setActiveCell,
|
|
2021
|
+
onComplete: restoreSelections,
|
|
2022
|
+
});
|
|
2023
|
+
/**
|
|
2024
|
+
* Use before edit to store editing cell reference
|
|
2025
|
+
*/
|
|
2026
|
+
const handleBeforeEdit = useCallback((sheetId, cell) => {
|
|
2027
|
+
setEditingCellCoordinate({
|
|
2028
|
+
...cell,
|
|
2029
|
+
sheetId,
|
|
2030
|
+
});
|
|
2031
|
+
}, [setEditingCellCoordinate]);
|
|
2032
|
+
/**
|
|
2033
|
+
* Callback on editor keydown
|
|
2034
|
+
* User can navigate between sheets
|
|
2035
|
+
* In formula mode, user can select cells
|
|
2036
|
+
*/
|
|
2037
|
+
const onEditorKeyDown = useEditorKeydown({
|
|
2038
|
+
sheetId,
|
|
2039
|
+
onSelectNextSheet,
|
|
2040
|
+
onSelectPreviousSheet,
|
|
2041
|
+
onKeyDownSelection,
|
|
2042
|
+
});
|
|
2043
|
+
/**
|
|
2044
|
+
* Get bounds of chart overlay
|
|
2045
|
+
* Within the grid body
|
|
2046
|
+
*/
|
|
2047
|
+
const getChartBounds = useCallback(() => {
|
|
2048
|
+
return {
|
|
2049
|
+
left: getColumnOffset(1),
|
|
2050
|
+
top: getRowOffset(1),
|
|
2051
|
+
};
|
|
2052
|
+
}, [getRowOffset, getColumnOffset]);
|
|
2053
|
+
// Show notes editor
|
|
2054
|
+
const onInsertNote = useCallback((sheetId, cell) => {
|
|
2055
|
+
setNoteEditorCell({
|
|
2056
|
+
...cell,
|
|
2057
|
+
sheetId,
|
|
2058
|
+
});
|
|
2059
|
+
}, [setNoteEditorCell]);
|
|
2060
|
+
// Show pinned tooltip
|
|
2061
|
+
const onPinToolTip = useCallback((sheetId, cell) => {
|
|
2062
|
+
setPinnedTooltip({
|
|
2063
|
+
sheetId,
|
|
2064
|
+
...cell,
|
|
2065
|
+
});
|
|
2066
|
+
}, [setPinnedTooltip]);
|
|
2067
|
+
// Unpin tooltip
|
|
2068
|
+
const onUnpinTooltip = useCallback(() => {
|
|
2069
|
+
setPinnedTooltip(undefined);
|
|
2070
|
+
}, [setPinnedTooltip]);
|
|
2071
|
+
/**
|
|
2072
|
+
* Add quick edit range
|
|
2073
|
+
*/
|
|
2074
|
+
const onAddQuickEdit = useCallback((range) => {
|
|
2075
|
+
if (!enableQuickEdit) {
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
setQuickEditState((prev) => {
|
|
2079
|
+
return [...prev, { id: uuid(), range }];
|
|
2080
|
+
});
|
|
2081
|
+
}, [setQuickEditState, enableQuickEdit]);
|
|
2082
|
+
/**
|
|
2083
|
+
* Remove quick edit
|
|
2084
|
+
*/
|
|
2085
|
+
const onRemoveQuickEdit = useCallback((range) => {
|
|
2086
|
+
if (!enableQuickEdit) {
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
setQuickEditState((prev) => {
|
|
2090
|
+
return prev.filter((item) => {
|
|
2091
|
+
return !(range.sheetId === item.range.sheetId &&
|
|
2092
|
+
isAreasEqual(item.range, range));
|
|
2093
|
+
});
|
|
2094
|
+
});
|
|
2095
|
+
focusSheet();
|
|
2096
|
+
}, [setQuickEditState, enableQuickEdit, focusSheet]);
|
|
2097
|
+
/**
|
|
2098
|
+
* Get context Menu component
|
|
2099
|
+
*/
|
|
2100
|
+
const getContextMenu = useCallback((cell) => {
|
|
2101
|
+
return (React.createElement(ContextMenu, { activeCell: activeCell, selections: selections, sheetId: sheetId, frozenRows: frozenRows, frozenColumns: frozenColumns, onHideColumn: isRestricted ? undefined : onHideColumn, onShowColumn: isRestricted ? undefined : onShowColumn, onShowRow: isRestricted ? undefined : onShowRow, onHideRow: isRestricted ? undefined : onHideRow, onGroupRows: isRestricted ? undefined : onGroupRows, onUngroupRows: isRestricted ? undefined : onUngroupRows, onGroupColumns: isRestricted ? undefined : onGroupColumns, onUngroupColumns: isRestricted ? undefined : onUngroupColumns, isHiddenColumn: isHiddenColumn, isHiddenRow: isHiddenRow, onDeleteColumn: onDeleteColumn, onDeleteRow: onDeleteRow, onInsertRow: onInsertRow, onInsertColumn: onInsertColumn, onInsertCellsShiftDown: onInsertCellsShiftDown, onInsertCellsShiftRight: onInsertCellsShiftRight, onDeleteCellsShiftLeft: onDeleteCellsShiftLeft, onDeleteCellsShiftUp: onDeleteCellsShiftUp, onClearContents: onClearContents, onFreezeColumn: onFreezeColumn, onFreezeRow: onFreezeRow, focusSheet: focusSheet, onSortColumn: onSortColumn, onInsertNote: onInsertNote, onProtectRange: onProtectRange, onUnProtectRange: onUnProtectRange, onSortRange: onSortRange, onRequestDefineNamedRange: onRequestDefineNamedRange, protectedRanges: protectedRanges, isRowHeader: isRowHeader(cell.columnIndex), isColumnHeader: isColumnHeader(cell.rowIndex), selectedRowHeadersIds: selectedRowHeadersIds, selectedColumnHeadersIds: selectedColumnHeadersIds, onCopy: copy, onCut: cut, onPaste: paste, onRequestResize: onRequestResize, isSheetFocused: isSheetFocused, tables: activeTables, pivotTables: pivotTables, basicFilter: basicFilter, onRequestEditTable: onRequestEditTable, onRequestEditPivotTable: onRequestEditPivotTable, onRemoveTable: onRemoveTable, onRequestDeletePivotTable: onRequestDeletePivotTable, onPivotDrillDown: onPivotDrillDown, onRequestFormatCells: onRequestFormatCells, onRequestConditionalFormat: onRequestConditionalFormat, onRequestDataValidation: onRequestDataValidation, onClearFormatting: onClearFormatting, onCreateTable: onCreateTable, onCreateBasicFilter: onCreateBasicFilter, onInsertTableColumn: onInsertTableColumn, onDeleteTableColumn: onDeleteTableColumn, onInsertTableRow: onInsertTableRow, onDeleteTableRow: onDeleteTableRow, onFilterTable: onFilterTable, onSortTable: onSortTable, getFormattedValue: getFormattedValue, getFormattedValuesFromRange: getFormattedValuesFromRange, isTableHeader: isTableHeader, readonly: readonly, onSplitTextToColumns: onSplitTextToColumns, onRemoveDuplicates: onRemoveDuplicates, onAddQuickEdit: onAddQuickEdit, enableMagicFill: enableMagicFill }));
|
|
2102
|
+
}, [
|
|
2103
|
+
isRestricted,
|
|
2104
|
+
activeCell,
|
|
2105
|
+
sheetId,
|
|
2106
|
+
selections,
|
|
2107
|
+
frozenRows,
|
|
2108
|
+
frozenColumns,
|
|
2109
|
+
onHideColumn,
|
|
2110
|
+
ContextMenu,
|
|
2111
|
+
onHideRow,
|
|
2112
|
+
onDeleteColumn,
|
|
2113
|
+
onDeleteRow,
|
|
2114
|
+
onInsertColumn,
|
|
2115
|
+
onInsertRow,
|
|
2116
|
+
onInsertCellsShiftDown,
|
|
2117
|
+
onInsertCellsShiftRight,
|
|
2118
|
+
onDeleteCellsShiftLeft,
|
|
2119
|
+
onDeleteCellsShiftUp,
|
|
2120
|
+
onClearContents,
|
|
2121
|
+
onFreezeColumn,
|
|
2122
|
+
onFreezeRow,
|
|
2123
|
+
focusSheet,
|
|
2124
|
+
onSortColumn,
|
|
2125
|
+
copy,
|
|
2126
|
+
paste,
|
|
2127
|
+
cut,
|
|
2128
|
+
onInsertNote,
|
|
2129
|
+
onProtectRange,
|
|
2130
|
+
onUnProtectRange,
|
|
2131
|
+
onSortRange,
|
|
2132
|
+
onRequestDefineNamedRange,
|
|
2133
|
+
onRequestResize,
|
|
2134
|
+
isRowHeader,
|
|
2135
|
+
isColumnHeader,
|
|
2136
|
+
selectedRowHeadersIds,
|
|
2137
|
+
selectedColumnHeadersIds,
|
|
2138
|
+
protectedRanges,
|
|
2139
|
+
isSheetFocused,
|
|
2140
|
+
activeTables,
|
|
2141
|
+
basicFilter,
|
|
2142
|
+
pivotTables,
|
|
2143
|
+
isTableHeader,
|
|
2144
|
+
onFilterTable,
|
|
2145
|
+
onSortTable,
|
|
2146
|
+
onRequestEditTable,
|
|
2147
|
+
onRequestEditPivotTable,
|
|
2148
|
+
onRemoveTable,
|
|
2149
|
+
onRequestFormatCells,
|
|
2150
|
+
onClearFormatting,
|
|
2151
|
+
onRequestConditionalFormat,
|
|
2152
|
+
onRequestDataValidation,
|
|
2153
|
+
onCreateBasicFilter,
|
|
2154
|
+
onCreateTable,
|
|
2155
|
+
onDeleteTableColumn,
|
|
2156
|
+
onInsertTableRow,
|
|
2157
|
+
getFormattedValue,
|
|
2158
|
+
getFormattedValuesFromRange,
|
|
2159
|
+
onInsertTableColumn,
|
|
2160
|
+
onDeleteTableRow,
|
|
2161
|
+
readonly,
|
|
2162
|
+
onAddQuickEdit,
|
|
2163
|
+
enableMagicFill,
|
|
2164
|
+
onSplitTextToColumns,
|
|
2165
|
+
onRemoveDuplicates,
|
|
2166
|
+
onRequestDeletePivotTable,
|
|
2167
|
+
isHiddenColumn,
|
|
2168
|
+
isHiddenRow,
|
|
2169
|
+
onShowColumn,
|
|
2170
|
+
onShowRow,
|
|
2171
|
+
onGroupRows,
|
|
2172
|
+
onUngroupRows,
|
|
2173
|
+
onGroupColumns,
|
|
2174
|
+
onUngroupColumns,
|
|
2175
|
+
]);
|
|
2176
|
+
/**
|
|
2177
|
+
* Context menu hook
|
|
2178
|
+
* Displays Context menu when user right clicks
|
|
2179
|
+
* the grid
|
|
2180
|
+
*/
|
|
2181
|
+
const { onContextMenu, contextMenuComponent, onRequestClose: onRequestCloseContextMenu, showContextMenu, } = useContextMenu({
|
|
2182
|
+
getCellCoordsFromOffset,
|
|
2183
|
+
getRelativePositionFromOffset,
|
|
2184
|
+
isRowHeader,
|
|
2185
|
+
isColumnHeader,
|
|
2186
|
+
getContextMenu,
|
|
2187
|
+
getCellOffsetFromCoords,
|
|
2188
|
+
getScrollPosition,
|
|
2189
|
+
ContextMenuWrapper,
|
|
2190
|
+
});
|
|
2191
|
+
/**
|
|
2192
|
+
* Shortcut handlers for formatting
|
|
2193
|
+
* TODO: Decide on the output
|
|
2194
|
+
*/
|
|
2195
|
+
const onKeyDownFormatting = useKeyboardHandler({
|
|
2196
|
+
sheetId,
|
|
2197
|
+
locale,
|
|
2198
|
+
showFormulas,
|
|
2199
|
+
canEditCell,
|
|
2200
|
+
onShowFormulas,
|
|
2201
|
+
getCellFormat: getEffectiveCellFormat,
|
|
2202
|
+
activeCell,
|
|
2203
|
+
selections,
|
|
2204
|
+
selectedColumns,
|
|
2205
|
+
selectedRows,
|
|
2206
|
+
onChangeFormatting,
|
|
2207
|
+
onRepeatFormatting,
|
|
2208
|
+
onInsertNote,
|
|
2209
|
+
onClearFormatting,
|
|
2210
|
+
onSelectNextSheet,
|
|
2211
|
+
onSelectPreviousSheet,
|
|
2212
|
+
onCreateNewSheet,
|
|
2213
|
+
onFillRange,
|
|
2214
|
+
disableFillRightShortcut,
|
|
2215
|
+
onInsertTime,
|
|
2216
|
+
onInsertDate,
|
|
2217
|
+
onInsertDateTime,
|
|
2218
|
+
onUndo,
|
|
2219
|
+
onRedo,
|
|
2220
|
+
onCreateTable,
|
|
2221
|
+
onCreateBasicFilter,
|
|
2222
|
+
clearCopiedSelections,
|
|
2223
|
+
onRequestSearch,
|
|
2224
|
+
onRequestReplace,
|
|
2225
|
+
onRequestFormatCells,
|
|
2226
|
+
onRequestInsertComment,
|
|
2227
|
+
onRequestInsertLink,
|
|
2228
|
+
onShowContextMenu: showContextMenu,
|
|
2229
|
+
onHideColumn,
|
|
2230
|
+
onHideRow,
|
|
2231
|
+
onGroupRows,
|
|
2232
|
+
onUngroupRows,
|
|
2233
|
+
onGroupColumns,
|
|
2234
|
+
onUngroupColumns,
|
|
2235
|
+
onDeleteRow,
|
|
2236
|
+
onInsertRow,
|
|
2237
|
+
onInsertAutoSum,
|
|
2238
|
+
onShowColumn,
|
|
2239
|
+
onShowRow,
|
|
2240
|
+
onAddQuickEdit,
|
|
2241
|
+
isSheetFocused,
|
|
2242
|
+
defaultFontSizePoint,
|
|
2243
|
+
});
|
|
2244
|
+
/**
|
|
2245
|
+
* Bind to keydown events
|
|
2246
|
+
* in the grid
|
|
2247
|
+
*/
|
|
2248
|
+
const handleKeyDown = useCallback((e) => {
|
|
2249
|
+
// For moving around in the sheet
|
|
2250
|
+
onKeyDownSelection(e);
|
|
2251
|
+
// Disable all keys
|
|
2252
|
+
if (readonly) {
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2255
|
+
onKeyDown?.(e);
|
|
2256
|
+
onKeyDownFormatting?.(e);
|
|
2257
|
+
}, [onKeyDownSelection, onKeyDown, onKeyDownFormatting, readonly]);
|
|
2258
|
+
/**
|
|
2259
|
+
* Allow grid to be ediable
|
|
2260
|
+
*/
|
|
2261
|
+
const { onMouseDown: onMouseDownEditable, onDoubleClick: onDoubleClickEditable, editorComponent, isEditInProgress, makeEditable, editCell, setEditorValue, hideEditor, getNextFocusableCell, submitEditor, cancelEditor, commit, } = useEditable({
|
|
2262
|
+
sheetId,
|
|
2263
|
+
enableEditOnEnterKey,
|
|
2264
|
+
canEdit: canEditCell,
|
|
2265
|
+
sticky: stickyEditor,
|
|
2266
|
+
getScrollPosition,
|
|
2267
|
+
hideOnBlur: formulaMode && canSelectCells ? false : true,
|
|
2268
|
+
isHiddenRow,
|
|
2269
|
+
isHiddenColumn,
|
|
2270
|
+
columnCount,
|
|
2271
|
+
rowCount,
|
|
2272
|
+
frozenColumns,
|
|
2273
|
+
frozenRows,
|
|
2274
|
+
activeCell,
|
|
2275
|
+
selections,
|
|
2276
|
+
getSheetColumnCount,
|
|
2277
|
+
getSheetRowCount,
|
|
2278
|
+
getValue: getUserEnteredStringValue,
|
|
2279
|
+
getTextFormatRuns,
|
|
2280
|
+
getBooleanValue,
|
|
2281
|
+
getDataValidation: getDataValidationRule,
|
|
2282
|
+
selectionLeftBound,
|
|
2283
|
+
selectionTopBound,
|
|
2284
|
+
editorBorderColor: selectionBorderColor,
|
|
2285
|
+
getEditor,
|
|
2286
|
+
onBeforeEdit: handleBeforeEdit,
|
|
2287
|
+
onSubmit: onEditorSubmit,
|
|
2288
|
+
onCancel: onEditorCancel,
|
|
2289
|
+
onBlur: handleEditorBlur,
|
|
2290
|
+
onChange: onEditorChange,
|
|
2291
|
+
onChangeBatch,
|
|
2292
|
+
setActiveCell,
|
|
2293
|
+
onDelete,
|
|
2294
|
+
onKeyDown: handleKeyDown,
|
|
2295
|
+
onEditorKeyDown,
|
|
2296
|
+
getCellOffsetFromCoords,
|
|
2297
|
+
getCellCoordsFromOffset,
|
|
2298
|
+
getCellBounds,
|
|
2299
|
+
getRowOffset,
|
|
2300
|
+
getColumnOffset,
|
|
2301
|
+
getEditorAlignment: getEditorHorizontalAlignment,
|
|
2302
|
+
focus: focusSheet,
|
|
2303
|
+
getActualCellCoords,
|
|
2304
|
+
scrollToCell,
|
|
2305
|
+
containerWidth: width,
|
|
2306
|
+
containerHeight: height,
|
|
2307
|
+
onCopy: onInternalCopy,
|
|
2308
|
+
onPaste: onInternalPaste,
|
|
2309
|
+
onCut: onInternalCut,
|
|
2310
|
+
});
|
|
2311
|
+
/**
|
|
2312
|
+
* Move rows and columns
|
|
2313
|
+
*/
|
|
2314
|
+
const { draggableColumns, draggableRows, isDragging: isDraggingRowsAndColumns, } = useMoveColumnsAndRows({
|
|
2315
|
+
getCellOffsetFromCoords,
|
|
2316
|
+
getCellCoordsFromOffset,
|
|
2317
|
+
getRelativePositionFromOffset,
|
|
2318
|
+
scrollToCell,
|
|
2319
|
+
focusSheet,
|
|
2320
|
+
columns: formulaMode ? undefined : selectedColumnHeadersIds,
|
|
2321
|
+
rows: formulaMode ? undefined : selectedRowHeadersIds,
|
|
2322
|
+
selectionLeftBound,
|
|
2323
|
+
selectionTopBound,
|
|
2324
|
+
onMoveColumns,
|
|
2325
|
+
onMoveRows,
|
|
2326
|
+
containerWidth: width - scrollbarSize,
|
|
2327
|
+
containerHeight: height - scrollbarSize,
|
|
2328
|
+
getScrollPosition,
|
|
2329
|
+
onChangeSelections,
|
|
2330
|
+
onChangeActiveCell,
|
|
2331
|
+
activeCell,
|
|
2332
|
+
rowCount,
|
|
2333
|
+
columnCount,
|
|
2334
|
+
sheetId,
|
|
2335
|
+
disabled: isRestricted,
|
|
2336
|
+
HeaderMoveDragComponent,
|
|
2337
|
+
});
|
|
2338
|
+
/**
|
|
2339
|
+
* Header actions
|
|
2340
|
+
*/
|
|
2341
|
+
const { headerMenuComponent, isHeaderMenuInFrozenColumn, headerResizer, isDragging: isDraggingHeader, } = useHeaderActions({
|
|
2342
|
+
activeCell: isSelectionInProgress || isFilling || isDragging ? null : hoveredCell,
|
|
2343
|
+
getScrollPosition,
|
|
2344
|
+
getCellOffsetFromCoords,
|
|
2345
|
+
getRelativePositionFromOffset,
|
|
2346
|
+
showContextMenu,
|
|
2347
|
+
selectColumn,
|
|
2348
|
+
setActiveCell,
|
|
2349
|
+
getViewPort,
|
|
2350
|
+
frozenRows,
|
|
2351
|
+
frozenColumns,
|
|
2352
|
+
selectionTopBound,
|
|
2353
|
+
showHeaderMenuButton,
|
|
2354
|
+
scale,
|
|
2355
|
+
onResize,
|
|
2356
|
+
focusSheet,
|
|
2357
|
+
isRowHeader,
|
|
2358
|
+
isColumnHeader,
|
|
2359
|
+
isHiddenColumn,
|
|
2360
|
+
containerWidth: width - scrollbarSize,
|
|
2361
|
+
containerHeight: height - scrollbarSize,
|
|
2362
|
+
onAutoFit: handleAutoFit,
|
|
2363
|
+
backgroundColor: selectionBorderColor,
|
|
2364
|
+
sheetId,
|
|
2365
|
+
selectedRowHeadersIds,
|
|
2366
|
+
selectedColumnHeadersIds,
|
|
2367
|
+
enableResizerOverflow,
|
|
2368
|
+
});
|
|
2369
|
+
/**
|
|
2370
|
+
* Close tooltip
|
|
2371
|
+
*/
|
|
2372
|
+
const onRequestCloseTooltip = useCallback(() => {
|
|
2373
|
+
setHoveredCell(undefined);
|
|
2374
|
+
}, []);
|
|
2375
|
+
// Scroll subscriber
|
|
2376
|
+
const handleScroll = useCallback((scrollPosition) => {
|
|
2377
|
+
// Pass it to rxjs subscriber
|
|
2378
|
+
if (!isEditInProgress) {
|
|
2379
|
+
scrollSubscriber.next(scrollPosition);
|
|
2380
|
+
}
|
|
2381
|
+
onScroll?.(scrollPosition);
|
|
2382
|
+
}, [onScroll, isEditInProgress]);
|
|
2383
|
+
/**
|
|
2384
|
+
* Tooltips
|
|
2385
|
+
*/
|
|
2386
|
+
const { tooltipComponent } = useTooltip({
|
|
2387
|
+
sheetId,
|
|
2388
|
+
getCellOffsetFromCoords,
|
|
2389
|
+
activeCell: isDraggingHeader || isSelectionInProgress || isFilling || isDragging
|
|
2390
|
+
? null
|
|
2391
|
+
: delayedHoveredCell,
|
|
2392
|
+
getScrollPosition,
|
|
2393
|
+
getTooltip,
|
|
2394
|
+
isFrozenColumn,
|
|
2395
|
+
isFrozenRow,
|
|
2396
|
+
onUpdateNote,
|
|
2397
|
+
onRemoveLink,
|
|
2398
|
+
onSelectLink,
|
|
2399
|
+
onRequestClose: onRequestCloseTooltip,
|
|
2400
|
+
});
|
|
2401
|
+
/**
|
|
2402
|
+
* Get filter component
|
|
2403
|
+
*/
|
|
2404
|
+
const getFilterComponent = useCallback((props) => {
|
|
2405
|
+
return React.createElement(FilterBox, { ...props, sheetId: sheetId });
|
|
2406
|
+
}, [sheetId, FilterBox]);
|
|
2407
|
+
/**
|
|
2408
|
+
* Show basicFilter panels
|
|
2409
|
+
*/
|
|
2410
|
+
const { showFilter, hideFilter, filterComponent } = useFilter({
|
|
2411
|
+
sheetId,
|
|
2412
|
+
scale,
|
|
2413
|
+
theme,
|
|
2414
|
+
getActualCellCoords,
|
|
2415
|
+
getScrollPosition,
|
|
2416
|
+
getCellOffsetFromCoords,
|
|
2417
|
+
getFilterComponent,
|
|
2418
|
+
getFormattedValue,
|
|
2419
|
+
getEffectiveFormat,
|
|
2420
|
+
conditionalFormatByCell,
|
|
2421
|
+
isFrozenColumn,
|
|
2422
|
+
isFrozenRow,
|
|
2423
|
+
isHiddenRowByFilter,
|
|
2424
|
+
onSortTable,
|
|
2425
|
+
onFilterTable,
|
|
2426
|
+
onInsertTableColumn,
|
|
2427
|
+
onDeleteTableColumn,
|
|
2428
|
+
// Host-computed distinct values for the checklist.
|
|
2429
|
+
getFilterValues,
|
|
2430
|
+
// Host-computed swatches for the "Filter by color" picker (windowed engines).
|
|
2431
|
+
getFilterColors,
|
|
2432
|
+
// Live filter state so the open popup tracks Auto-apply spec changes.
|
|
2433
|
+
basicFilter,
|
|
2434
|
+
tables: activeTables,
|
|
2435
|
+
});
|
|
2436
|
+
// Table resize
|
|
2437
|
+
const { tableResizers, isResizingTable } = useTableResizer({
|
|
2438
|
+
sheetId,
|
|
2439
|
+
tables: tables ?? undefined,
|
|
2440
|
+
theme,
|
|
2441
|
+
newSelection,
|
|
2442
|
+
modifySelection,
|
|
2443
|
+
clearSelections,
|
|
2444
|
+
getCellCoordsFromOffset,
|
|
2445
|
+
scrollToCell,
|
|
2446
|
+
onResizeTable,
|
|
2447
|
+
focusSheet,
|
|
2448
|
+
});
|
|
2449
|
+
/**
|
|
2450
|
+
* Displays resizable/draggable charts
|
|
2451
|
+
*/
|
|
2452
|
+
const { chartComponents, embedComponents, slicerComponents, onMouseDown: onMouseDownCharts, } = useEmbedsCharts({
|
|
2453
|
+
charts,
|
|
2454
|
+
embeds,
|
|
2455
|
+
slicers,
|
|
2456
|
+
sheetId,
|
|
2457
|
+
scale,
|
|
2458
|
+
frozenRows,
|
|
2459
|
+
frozenColumns,
|
|
2460
|
+
getCellOffsetFromCoords,
|
|
2461
|
+
getAbsolutePositionFromOffset,
|
|
2462
|
+
getCellCoordsFromOffset,
|
|
2463
|
+
getScrollPosition,
|
|
2464
|
+
selectedColor: chartSelectedColor,
|
|
2465
|
+
onMoveChart,
|
|
2466
|
+
onResizeChart,
|
|
2467
|
+
onMoveEmbed,
|
|
2468
|
+
onResizeEmbed,
|
|
2469
|
+
onDeleteEmbed,
|
|
2470
|
+
onDeleteChart,
|
|
2471
|
+
onRequestEditEmbed,
|
|
2472
|
+
onMoveSlicer,
|
|
2473
|
+
onResizeSlicer,
|
|
2474
|
+
onDeleteSlicer,
|
|
2475
|
+
onRequestEditSlicer,
|
|
2476
|
+
onFilterTable,
|
|
2477
|
+
onFilterPivot,
|
|
2478
|
+
tables,
|
|
2479
|
+
pivotTables,
|
|
2480
|
+
getFormattedValue,
|
|
2481
|
+
getChartComponent,
|
|
2482
|
+
getEmbedComponent,
|
|
2483
|
+
getSlicerComponent,
|
|
2484
|
+
getBounds: getChartBounds,
|
|
2485
|
+
theme,
|
|
2486
|
+
backgroundColor: cellBackgroundColor,
|
|
2487
|
+
disabled: isRestricted,
|
|
2488
|
+
readonly,
|
|
2489
|
+
});
|
|
2490
|
+
/**
|
|
2491
|
+
* Callback when user clicks Filter icon
|
|
2492
|
+
* Show Filter dropdown here
|
|
2493
|
+
*/
|
|
2494
|
+
const handleFilterClick = useCallback((cell) => {
|
|
2495
|
+
const activeFilter = basicFilter && isCellWithinBounds(cell, basicFilter?.range)
|
|
2496
|
+
? basicFilter
|
|
2497
|
+
: activeTables?.find((table) => isCellWithinBounds(cell, table.range));
|
|
2498
|
+
if (activeFilter) {
|
|
2499
|
+
showFilter(cell, activeFilter);
|
|
2500
|
+
}
|
|
2501
|
+
}, [showFilter, basicFilter, activeTables]);
|
|
2502
|
+
/**
|
|
2503
|
+
* Callback when user checks a cell
|
|
2504
|
+
*/
|
|
2505
|
+
const onChangeRef = useCallbackRef(onChange);
|
|
2506
|
+
const handleCheckboxClick = useCallback((cell, checked) => {
|
|
2507
|
+
// If the checkbox is derived from a formula calculation
|
|
2508
|
+
// do not let users change it by toggling the checkbox
|
|
2509
|
+
const { rowIndex, columnIndex } = cell;
|
|
2510
|
+
const isFormula = !!getFormulaValue(sheetId, rowIndex, columnIndex);
|
|
2511
|
+
if (isFormula) {
|
|
2512
|
+
log("Checkbox selection is disabled for formula cells.");
|
|
2513
|
+
}
|
|
2514
|
+
else {
|
|
2515
|
+
onChangeRef?.(sheetId, cell, checked, undefined, !checked, true);
|
|
2516
|
+
}
|
|
2517
|
+
}, [sheetId, getFormulaValue, onChangeRef]);
|
|
2518
|
+
/**
|
|
2519
|
+
* Get group keys of a cell
|
|
2520
|
+
*/
|
|
2521
|
+
const getCellGroupKeys = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
2522
|
+
return getCellData?.(sheetId, rowIndex, columnIndex)?.groupKeys;
|
|
2523
|
+
}, [getCellData]);
|
|
2524
|
+
/**
|
|
2525
|
+
* Get children count
|
|
2526
|
+
*/
|
|
2527
|
+
const getChildrenCount = useCallback((sheetId, rowIndex, columnIndex) => {
|
|
2528
|
+
return getCellData?.(sheetId, rowIndex, columnIndex)?.childrenCount ?? 0;
|
|
2529
|
+
}, [getCellData]);
|
|
2530
|
+
/**
|
|
2531
|
+
* Callback when user checks a cell
|
|
2532
|
+
*/
|
|
2533
|
+
const handleExpandCollapse = useCallback((sheetId, cell, newExpandedState) => {
|
|
2534
|
+
const groupKeys = getCellGroupKeys(sheetId, cell.rowIndex, cell.columnIndex);
|
|
2535
|
+
const childrenCount = getChildrenCount(sheetId, cell.rowIndex, cell.columnIndex);
|
|
2536
|
+
if (groupKeys?.length) {
|
|
2537
|
+
onExpandCollapse?.(sheetId, cell, groupKeys, newExpandedState, childrenCount);
|
|
2538
|
+
}
|
|
2539
|
+
}, [onExpandCollapse, getCellGroupKeys, getChildrenCount]);
|
|
2540
|
+
/**
|
|
2541
|
+
* Capture mouse move events
|
|
2542
|
+
*/
|
|
2543
|
+
const handleMouseMove = useCallback((e) => {
|
|
2544
|
+
// A little bit of optimization here
|
|
2545
|
+
if (isDragging ||
|
|
2546
|
+
isDraggingRowsAndColumns ||
|
|
2547
|
+
isDraggingHeader ||
|
|
2548
|
+
isSelectionInProgress ||
|
|
2549
|
+
isFilling) {
|
|
2550
|
+
return;
|
|
2551
|
+
}
|
|
2552
|
+
const coords = getCellCoordsFromOffset(e.clientX, e.clientY);
|
|
2553
|
+
if (!coords || isEqualCells(hoveredCellRef.current, coords)) {
|
|
2554
|
+
return;
|
|
2555
|
+
}
|
|
2556
|
+
setHoveredCell(coords);
|
|
2557
|
+
}, [
|
|
2558
|
+
getCellCoordsFromOffset,
|
|
2559
|
+
isDragging,
|
|
2560
|
+
isDraggingRowsAndColumns,
|
|
2561
|
+
isDraggingHeader,
|
|
2562
|
+
isSelectionInProgress,
|
|
2563
|
+
isFilling,
|
|
2564
|
+
hoveredCellRef,
|
|
2565
|
+
]);
|
|
2566
|
+
// Mouse move throttler
|
|
2567
|
+
const mouseMoveThrottler = useCallbackRef(throttle(handleMouseMove, mouseMoveThrottleTimeout, {
|
|
2568
|
+
trailing: true,
|
|
2569
|
+
leading: true,
|
|
2570
|
+
}));
|
|
2571
|
+
/**
|
|
2572
|
+
* Bind to mousedown events
|
|
2573
|
+
* in the grid
|
|
2574
|
+
*/
|
|
2575
|
+
const handleMouseDown = useCallback((e) => {
|
|
2576
|
+
// Ignore mousedown for touch devices
|
|
2577
|
+
// since we use onPointerDown
|
|
2578
|
+
if (isTouchDevice) {
|
|
2579
|
+
return;
|
|
2580
|
+
}
|
|
2581
|
+
const isMetaKey = e.nativeEvent.metaKey || e.nativeEvent.ctrlKey;
|
|
2582
|
+
const isRightClick = e.button === MouseButtonCodes.right || e.ctrlKey;
|
|
2583
|
+
// Keep focus on grid
|
|
2584
|
+
if (!isRightClick && !e.isDefaultPrevented()) {
|
|
2585
|
+
focusSheet();
|
|
2586
|
+
}
|
|
2587
|
+
/**
|
|
2588
|
+
* In use-selection, we use a scheduler to append
|
|
2589
|
+
* cells
|
|
2590
|
+
*
|
|
2591
|
+
* This state update is queued, and update only
|
|
2592
|
+
* happens after selection changes.
|
|
2593
|
+
*
|
|
2594
|
+
*/
|
|
2595
|
+
if (formulaMode && isMetaKey) {
|
|
2596
|
+
setFormulaState((prev) => ({
|
|
2597
|
+
...prev,
|
|
2598
|
+
selectionMode: "append",
|
|
2599
|
+
}));
|
|
2600
|
+
}
|
|
2601
|
+
// Pass it on to use selection hook
|
|
2602
|
+
onMouseDownSelection(e);
|
|
2603
|
+
// Charts
|
|
2604
|
+
onMouseDownCharts?.();
|
|
2605
|
+
/**
|
|
2606
|
+
* Only hide contextmenu if user
|
|
2607
|
+
* is not pressing right click
|
|
2608
|
+
*/
|
|
2609
|
+
if (!isRightClick) {
|
|
2610
|
+
onRequestCloseContextMenu();
|
|
2611
|
+
}
|
|
2612
|
+
// Hide filter
|
|
2613
|
+
hideFilter();
|
|
2614
|
+
// Hide popover
|
|
2615
|
+
hideCellPopover();
|
|
2616
|
+
// Hide paste mnenu
|
|
2617
|
+
setShowPasteMenu(false);
|
|
2618
|
+
// Remove pinned tooltip
|
|
2619
|
+
onUnpinTooltip();
|
|
2620
|
+
}, [
|
|
2621
|
+
onMouseDownSelection,
|
|
2622
|
+
onRequestCloseContextMenu,
|
|
2623
|
+
hideFilter,
|
|
2624
|
+
onMouseDownCharts,
|
|
2625
|
+
formulaMode,
|
|
2626
|
+
setFormulaState,
|
|
2627
|
+
hideCellPopover,
|
|
2628
|
+
setShowPasteMenu,
|
|
2629
|
+
onUnpinTooltip,
|
|
2630
|
+
focusSheet,
|
|
2631
|
+
]);
|
|
2632
|
+
/**
|
|
2633
|
+
* Only for touch devices
|
|
2634
|
+
*/
|
|
2635
|
+
const handlePointerDown = useCallback((event) => {
|
|
2636
|
+
onPointerDownSelection?.(event);
|
|
2637
|
+
// // // Charts
|
|
2638
|
+
onMouseDownCharts?.();
|
|
2639
|
+
// // // Pass it on to use editable hook
|
|
2640
|
+
onMouseDownEditable(event);
|
|
2641
|
+
// // Hide filter
|
|
2642
|
+
hideFilter();
|
|
2643
|
+
}, [
|
|
2644
|
+
hideFilter,
|
|
2645
|
+
onPointerDownSelection,
|
|
2646
|
+
onMouseDownEditable,
|
|
2647
|
+
onMouseDownCharts,
|
|
2648
|
+
]);
|
|
2649
|
+
/**
|
|
2650
|
+
* Keep focus on the editor
|
|
2651
|
+
*/
|
|
2652
|
+
const handlePointerUp = useCallback((event) => {
|
|
2653
|
+
const isRightClick = event.button === MouseButtonCodes.right || event.ctrlKey;
|
|
2654
|
+
// Always keep the focus on
|
|
2655
|
+
// on cell editor
|
|
2656
|
+
// If another editor is active, keep that
|
|
2657
|
+
if (!isRightClick) {
|
|
2658
|
+
focusSheet();
|
|
2659
|
+
}
|
|
2660
|
+
}, [focusSheet]);
|
|
2661
|
+
/**
|
|
2662
|
+
* Handle double clicks in the grid
|
|
2663
|
+
*/
|
|
2664
|
+
const handleDoubleClick = useCallback((e) => {
|
|
2665
|
+
// Excel "Show Details": double-clicking a pivot VALUE cell drills
|
|
2666
|
+
// into the source rows behind it instead of entering edit mode. We
|
|
2667
|
+
// gate on a numeric effective value so only data / total cells
|
|
2668
|
+
// trigger it — text row-labels and headers fall through to the
|
|
2669
|
+
// editor (which is a no-op for pivot cells anyway).
|
|
2670
|
+
if (onPivotDrillDown) {
|
|
2671
|
+
const coords = getCellCoordsFromOffset(e.clientX, e.clientY);
|
|
2672
|
+
if (coords) {
|
|
2673
|
+
// Resolve the owning pivot from its range, not cellData.pivotId
|
|
2674
|
+
// — not every pivot cell carries that field, but range
|
|
2675
|
+
// containment is authoritative (same check canEditCell uses).
|
|
2676
|
+
const pivotTable = getPivotTableAtCell(sheetId, coords.rowIndex, coords.columnIndex);
|
|
2677
|
+
const numericValue = getExtendedValueNumber(getEffectiveValue(sheetId, coords.rowIndex, coords.columnIndex));
|
|
2678
|
+
if (pivotTable && !isNil(numericValue)) {
|
|
2679
|
+
onPivotDrillDown(pivotTable.pivotId, coords.rowIndex, coords.columnIndex);
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
// Pass it on to editor
|
|
2685
|
+
onDoubleClickEditable?.(e);
|
|
2686
|
+
}, [
|
|
2687
|
+
onDoubleClickEditable,
|
|
2688
|
+
onPivotDrillDown,
|
|
2689
|
+
getCellCoordsFromOffset,
|
|
2690
|
+
getPivotTableAtCell,
|
|
2691
|
+
getEffectiveValue,
|
|
2692
|
+
sheetId,
|
|
2693
|
+
]);
|
|
2694
|
+
/**
|
|
2695
|
+
* Get maximum text width
|
|
2696
|
+
* before it overflows into next cell
|
|
2697
|
+
*/
|
|
2698
|
+
const getMaximumOverflowTextWidth = useCallback((formattedValue, sheetId, rowIndex, columnIndex, canOverflowToNextCell, textFormat, shouldWrapOverride, direction = Direction.Right) => {
|
|
2699
|
+
// A format override makes the sizer measure the whole text
|
|
2700
|
+
// uniformly, ignoring per-segment rich-text runs. For cells that
|
|
2701
|
+
// carry runs (e.g. imported xlsx titles with mixed font sizes),
|
|
2702
|
+
// skip the override so run-aware measurement is used.
|
|
2703
|
+
const hasRichRuns = (getTextFormatRuns?.(sheetId, rowIndex, columnIndex)?.length ?? 0) > 0;
|
|
2704
|
+
const textWidth = getCellDimensions(sheetId, rowIndex, columnIndex, "y", {
|
|
2705
|
+
textOverride: formattedValue,
|
|
2706
|
+
...(hasRichRuns ? {} : { textFormatOverride: textFormat }),
|
|
2707
|
+
shouldWrapOverride,
|
|
2708
|
+
}).width;
|
|
2709
|
+
let colWidth = columnWidth(columnIndex) * scale;
|
|
2710
|
+
if (textWidth < colWidth) {
|
|
2711
|
+
return [textWidth, DEFAULT_ARRAY];
|
|
2712
|
+
}
|
|
2713
|
+
let start = columnIndex;
|
|
2714
|
+
const columnSpans = [];
|
|
2715
|
+
const isMovingRight = direction === Direction.Right;
|
|
2716
|
+
while (canOverflowToNextCell({
|
|
2717
|
+
rowIndex,
|
|
2718
|
+
columnIndex: isMovingRight ? ++start : --start,
|
|
2719
|
+
}) &&
|
|
2720
|
+
colWidth < textWidth) {
|
|
2721
|
+
const prev = isMovingRight ? start - 1 : start + 1;
|
|
2722
|
+
// For right aligned texts
|
|
2723
|
+
const borderColor = getEffectiveCellFormat(sheetId, rowIndex, isMovingRight ? start : prev)?.backgroundColor ??
|
|
2724
|
+
getEffectiveCellFormat(sheetId, rowIndex, isMovingRight ? prev : start)?.backgroundColor;
|
|
2725
|
+
const nextColWidth = columnWidth(start) * scale;
|
|
2726
|
+
columnSpans.push([
|
|
2727
|
+
start,
|
|
2728
|
+
getColumnOffset(start),
|
|
2729
|
+
nextColWidth,
|
|
2730
|
+
borderColor,
|
|
2731
|
+
]);
|
|
2732
|
+
colWidth += nextColWidth;
|
|
2733
|
+
}
|
|
2734
|
+
return [Math.min(textWidth, colWidth), columnSpans];
|
|
2735
|
+
}, [
|
|
2736
|
+
scale,
|
|
2737
|
+
getCellDimensions,
|
|
2738
|
+
getTextFormatRuns,
|
|
2739
|
+
columnWidth,
|
|
2740
|
+
getColumnOffset,
|
|
2741
|
+
getEffectiveCellFormat,
|
|
2742
|
+
]);
|
|
2743
|
+
/**
|
|
2744
|
+
* Render Cells in the grid
|
|
2745
|
+
*/
|
|
2746
|
+
const [cellBackgroundRenderer, cellRenderer, cellOverlayRenderer, headerCellRenderer,] = useCellRenderer({
|
|
2747
|
+
sheetId,
|
|
2748
|
+
showGridLines,
|
|
2749
|
+
scale,
|
|
2750
|
+
enableTextOverflow,
|
|
2751
|
+
isRowHeader,
|
|
2752
|
+
isColumnHeader,
|
|
2753
|
+
canOverflowToNextCell,
|
|
2754
|
+
getDefaultHorizontalAlignment,
|
|
2755
|
+
selectedRows,
|
|
2756
|
+
selectedColumns,
|
|
2757
|
+
selectedRowHeaders,
|
|
2758
|
+
selectedColumnHeaders,
|
|
2759
|
+
cellBackgroundColor,
|
|
2760
|
+
headerBorderColor,
|
|
2761
|
+
headerBackgroundColor,
|
|
2762
|
+
headerColor,
|
|
2763
|
+
headerActiveBackgroundColor,
|
|
2764
|
+
headerSelectedBackgroundColor,
|
|
2765
|
+
headerSelectedColor,
|
|
2766
|
+
headerTableBackgroundColor,
|
|
2767
|
+
headerTableActiveBackgroundColor,
|
|
2768
|
+
headerTableSelectedBackgroundColor,
|
|
2769
|
+
chipBackgroundColor,
|
|
2770
|
+
filterIconColor,
|
|
2771
|
+
columnContainsTable,
|
|
2772
|
+
rowsContainsTable,
|
|
2773
|
+
isTableHeader,
|
|
2774
|
+
isCalculatedColumnHeader,
|
|
2775
|
+
isTableHeaderFilterActive,
|
|
2776
|
+
isTableFilterVisible,
|
|
2777
|
+
getTableHeaderSortOrder,
|
|
2778
|
+
showCalculatedColumnIcon,
|
|
2779
|
+
showHeaders,
|
|
2780
|
+
getDataValidation: getDataValidationRule,
|
|
2781
|
+
getErrorValue,
|
|
2782
|
+
getNote,
|
|
2783
|
+
getComment,
|
|
2784
|
+
getEffectiveValue,
|
|
2785
|
+
getFormattedValue,
|
|
2786
|
+
getCellImageUrl,
|
|
2787
|
+
getEffectiveCellFormat,
|
|
2788
|
+
getCellBounds,
|
|
2789
|
+
getCellMetaType,
|
|
2790
|
+
getRowHeaderText,
|
|
2791
|
+
getColumnHeaderText,
|
|
2792
|
+
getMaximumOverflowTextWidth,
|
|
2793
|
+
getTextDimension,
|
|
2794
|
+
getCellGroupingInfo,
|
|
2795
|
+
getTextFormatRuns,
|
|
2796
|
+
onRequestEdit: makeEditable,
|
|
2797
|
+
onFilterClick: handleFilterClick,
|
|
2798
|
+
onCheckboxClick: handleCheckboxClick,
|
|
2799
|
+
onExpandCollapse: handleExpandCollapse,
|
|
2800
|
+
defaultFontSizePoint,
|
|
2801
|
+
Cell,
|
|
2802
|
+
HeaderCell,
|
|
2803
|
+
theme,
|
|
2804
|
+
gridLineWidth,
|
|
2805
|
+
showNotes,
|
|
2806
|
+
showComments,
|
|
2807
|
+
StructuredResult,
|
|
2808
|
+
readonly,
|
|
2809
|
+
onOverflow: handleOverflow,
|
|
2810
|
+
isComparing,
|
|
2811
|
+
getCellDiff,
|
|
2812
|
+
});
|
|
2813
|
+
/**
|
|
2814
|
+
* When user selects a selection for moving
|
|
2815
|
+
* If its a table, we select the entire column
|
|
2816
|
+
* if user selects a table header column
|
|
2817
|
+
*/
|
|
2818
|
+
const onSelectionElementMouseDown = useCallback((e, cell, selection, index, shouldClamp) => {
|
|
2819
|
+
// Find the first cell in selection and
|
|
2820
|
+
// Check if its a table column
|
|
2821
|
+
// Disabled for now
|
|
2822
|
+
const firstCell = cell;
|
|
2823
|
+
const table = firstCell && isTableHeader(firstCell.rowIndex, firstCell.columnIndex)
|
|
2824
|
+
? findActiveTableWithinCell(sheetId, firstCell, tables)
|
|
2825
|
+
: undefined;
|
|
2826
|
+
if (firstCell && table) {
|
|
2827
|
+
const columnSelection = {
|
|
2828
|
+
range: {
|
|
2829
|
+
...table.range,
|
|
2830
|
+
startColumnIndex: firstCell.columnIndex,
|
|
2831
|
+
endColumnIndex: Math.max(firstCell.columnIndex, selection?.range.endColumnIndex ?? 0),
|
|
2832
|
+
},
|
|
2833
|
+
};
|
|
2834
|
+
// Update column selection
|
|
2835
|
+
onChangeSelections?.(sheetId, [columnSelection]);
|
|
2836
|
+
// Pass column
|
|
2837
|
+
onSelectionMouseDown?.(e, cell, columnSelection, index, shouldClamp);
|
|
2838
|
+
}
|
|
2839
|
+
else {
|
|
2840
|
+
onSelectionMouseDown?.(e, cell, selection, index, shouldClamp);
|
|
2841
|
+
}
|
|
2842
|
+
}, [onSelectionMouseDown, onChangeSelections, isTableHeader, tables, sheetId]);
|
|
2843
|
+
// Selection resize
|
|
2844
|
+
const onMouseDownResizeHandle = useSelectionResize({
|
|
2845
|
+
getCellBounds,
|
|
2846
|
+
getCellCoordsFromOffset,
|
|
2847
|
+
scrollToCell,
|
|
2848
|
+
tokenizer,
|
|
2849
|
+
});
|
|
2850
|
+
// Selection move: drag a formula reference via its border covers
|
|
2851
|
+
const { onMouseDownMoveSelection, isDragging: isDraggingMoveSelection } = useSelectionMove({
|
|
2852
|
+
getCellCoordsFromOffset,
|
|
2853
|
+
scrollToCell,
|
|
2854
|
+
tokenizer,
|
|
2855
|
+
});
|
|
2856
|
+
/**
|
|
2857
|
+
* Hide fill handle
|
|
2858
|
+
* 1. When user is in edit mode
|
|
2859
|
+
* 2. When user is in formula mode and user has made selections
|
|
2860
|
+
*/
|
|
2861
|
+
const showFillHandle = !isSelectionInProgress &&
|
|
2862
|
+
!isEditInProgress &&
|
|
2863
|
+
!isResizingTable &&
|
|
2864
|
+
!(formulaMode && formulaSelections.length);
|
|
2865
|
+
/**
|
|
2866
|
+
* Flashing
|
|
2867
|
+
*/
|
|
2868
|
+
const { flash, mark, unmark, onFlashEnd, flashingBorders } = useFlash({
|
|
2869
|
+
theme,
|
|
2870
|
+
});
|
|
2871
|
+
// Cache hover ids
|
|
2872
|
+
const cachedHoveredSelectionIds = useHoveredSelectionIds({
|
|
2873
|
+
selections,
|
|
2874
|
+
hoveredCell: delayedHoveredCell,
|
|
2875
|
+
activeCell,
|
|
2876
|
+
});
|
|
2877
|
+
/**
|
|
2878
|
+
* Selection Renderer
|
|
2879
|
+
*/
|
|
2880
|
+
const selectionRenderer = useSelectionRenderer({
|
|
2881
|
+
sheetId,
|
|
2882
|
+
scale,
|
|
2883
|
+
onSelectionMouseDown: onSelectionElementMouseDown,
|
|
2884
|
+
onMouseDownResizeHandle: onMouseDownResizeHandle,
|
|
2885
|
+
onMouseDownMoveSelection: onMouseDownMoveSelection,
|
|
2886
|
+
isDraggingMoveSelection: isDraggingMoveSelection,
|
|
2887
|
+
onChangeActiveCell,
|
|
2888
|
+
onChangeSelections,
|
|
2889
|
+
SelectionTitleComponent,
|
|
2890
|
+
selectionCount: (formulaMode ? formulaSelections : selections).length,
|
|
2891
|
+
selectionBackgroundColor,
|
|
2892
|
+
selectionBorderColor,
|
|
2893
|
+
getSheetName,
|
|
2894
|
+
onRequestEditTable,
|
|
2895
|
+
onRequestEditPivotTable,
|
|
2896
|
+
isResizingTable,
|
|
2897
|
+
resizeHandleBorderColor: cellBackgroundColor,
|
|
2898
|
+
showSelectionResizeHandles,
|
|
2899
|
+
fillHandleSize,
|
|
2900
|
+
showFillHandle,
|
|
2901
|
+
onFlashEnd,
|
|
2902
|
+
enableMagicFill: enableMagicFill && !isEditInProgress,
|
|
2903
|
+
MagicFillComponent,
|
|
2904
|
+
MagicFillContent,
|
|
2905
|
+
QuickEdit,
|
|
2906
|
+
PasteMenu,
|
|
2907
|
+
SuggestionAction,
|
|
2908
|
+
readonly,
|
|
2909
|
+
onSplitTextToColumns,
|
|
2910
|
+
showPasteMenu,
|
|
2911
|
+
hoveredCell: delayedHoveredCell,
|
|
2912
|
+
onRemoveQuickEdit,
|
|
2913
|
+
onAddQuickEdit,
|
|
2914
|
+
cachedHoveredSelectionIds,
|
|
2915
|
+
});
|
|
2916
|
+
/**
|
|
2917
|
+
* Create Range borders in the Grid
|
|
2918
|
+
* Used for
|
|
2919
|
+
* 1. Tables and basicFilter - check
|
|
2920
|
+
* 2. Selection drag/drop - check
|
|
2921
|
+
* 3. Collaborators - check
|
|
2922
|
+
*/
|
|
2923
|
+
const finalBorderStyles = useBorderStyles({
|
|
2924
|
+
sheetId,
|
|
2925
|
+
activeCell,
|
|
2926
|
+
hoveredCell: delayedHoveredCell,
|
|
2927
|
+
tables: activeTables,
|
|
2928
|
+
pivotTables,
|
|
2929
|
+
basicFilter,
|
|
2930
|
+
borderStyles,
|
|
2931
|
+
copiedSelections,
|
|
2932
|
+
flashingBorders,
|
|
2933
|
+
draggedSelection,
|
|
2934
|
+
initialDraggedSelection,
|
|
2935
|
+
selectionDragBorderColor,
|
|
2936
|
+
selectionBorderColor,
|
|
2937
|
+
tableBorderColor,
|
|
2938
|
+
users: isRestricted ? DEFAULT_ARRAY : users,
|
|
2939
|
+
userId,
|
|
2940
|
+
renderCollaboratorCursor,
|
|
2941
|
+
theme,
|
|
2942
|
+
agentSuggestions,
|
|
2943
|
+
quickEditValues,
|
|
2944
|
+
});
|
|
2945
|
+
// Hidden column markers
|
|
2946
|
+
const [hiddenColumnMarkers, frozenHiddenColumnMarkers, hiddenRowMarkers, frozenHiddenRowMarkers,] = useHiddenDimensionMarkers({
|
|
2947
|
+
sheetId,
|
|
2948
|
+
columnMetadata,
|
|
2949
|
+
rowMetadata,
|
|
2950
|
+
onShowColumn,
|
|
2951
|
+
onShowRow,
|
|
2952
|
+
isFrozenColumn,
|
|
2953
|
+
isFrozenRow,
|
|
2954
|
+
focusSheet,
|
|
2955
|
+
rowCount,
|
|
2956
|
+
columnCount,
|
|
2957
|
+
HiddenRowMarkers,
|
|
2958
|
+
HiddenColumnMarkers,
|
|
2959
|
+
});
|
|
2960
|
+
// Zoom lister
|
|
2961
|
+
const onMouseWheel = useScaleListener({
|
|
2962
|
+
zoomSpeed,
|
|
2963
|
+
scale,
|
|
2964
|
+
onChangeScale,
|
|
2965
|
+
});
|
|
2966
|
+
/**
|
|
2967
|
+
* Frozen shadow settings
|
|
2968
|
+
*/
|
|
2969
|
+
const shadowSettings = useMemo(() => {
|
|
2970
|
+
return {
|
|
2971
|
+
stroke: frozenShadowColor,
|
|
2972
|
+
strokeWidth: frozenShadowThickness,
|
|
2973
|
+
};
|
|
2974
|
+
}, [frozenShadowColor, frozenShadowThickness]);
|
|
2975
|
+
/**
|
|
2976
|
+
* Helper function to navigate to sheet range
|
|
2977
|
+
*/
|
|
2978
|
+
const navigateToSheetRange = useNavigateToSheetRange({
|
|
2979
|
+
onChangeActiveSheet,
|
|
2980
|
+
onChangeSelections,
|
|
2981
|
+
setActiveCell,
|
|
2982
|
+
flash,
|
|
2983
|
+
});
|
|
2984
|
+
// Dispatch keyboard event
|
|
2985
|
+
const dispatchEvent = useCallback((event) => {
|
|
2986
|
+
gridRef.current?.container?.dispatchEvent(event);
|
|
2987
|
+
}, []);
|
|
2988
|
+
// --- START SIDE EFFECTS ---
|
|
2989
|
+
// Expose grid methods in context and ref
|
|
2990
|
+
// Make sure these are useCallbackRef, so re-render
|
|
2991
|
+
// dont trigger infinite loop
|
|
2992
|
+
useContextSetter(forwardedRef, {
|
|
2993
|
+
submitEditor,
|
|
2994
|
+
cancelEditor,
|
|
2995
|
+
commit,
|
|
2996
|
+
makeEditable,
|
|
2997
|
+
editCell,
|
|
2998
|
+
getNextFocusableCell,
|
|
2999
|
+
onEditorKeyDown,
|
|
3000
|
+
scrollToCell,
|
|
3001
|
+
scrollToBottom,
|
|
3002
|
+
focusSheet,
|
|
3003
|
+
canEditCell,
|
|
3004
|
+
isSheetProtected,
|
|
3005
|
+
isWorkbookProtected,
|
|
3006
|
+
getSheetProtection: getSheetProtectionStable,
|
|
3007
|
+
getSelectionsFromFormula,
|
|
3008
|
+
getAddressFromSelection,
|
|
3009
|
+
getR1C1AddressFromSelection,
|
|
3010
|
+
tokenizer,
|
|
3011
|
+
setEditorValue,
|
|
3012
|
+
getCellBounds,
|
|
3013
|
+
getNamedRanges,
|
|
3014
|
+
getTableNames,
|
|
3015
|
+
getStructuredProperties,
|
|
3016
|
+
getMentions,
|
|
3017
|
+
getSheetName,
|
|
3018
|
+
getSheetId,
|
|
3019
|
+
getTableColumnNames,
|
|
3020
|
+
updateSelectionStartEndReference,
|
|
3021
|
+
getCellDimensions: getCellDimensionsStable,
|
|
3022
|
+
getRowHeight,
|
|
3023
|
+
getColumnWidth,
|
|
3024
|
+
getContentfulGridRangeAroundCell,
|
|
3025
|
+
getCellCoordsFromOffset,
|
|
3026
|
+
getCellOffsetFromCoords,
|
|
3027
|
+
getEffectiveValuesFromRange,
|
|
3028
|
+
getSheetDimensions,
|
|
3029
|
+
getFinalRowHeight,
|
|
3030
|
+
onInsertNote,
|
|
3031
|
+
onPinToolTip,
|
|
3032
|
+
onUnpinTooltip,
|
|
3033
|
+
showCellPopover,
|
|
3034
|
+
redrawGrid,
|
|
3035
|
+
flash,
|
|
3036
|
+
navigateToSheetRange,
|
|
3037
|
+
mark,
|
|
3038
|
+
unmark,
|
|
3039
|
+
exportRange,
|
|
3040
|
+
getViewPort,
|
|
3041
|
+
setActiveCell,
|
|
3042
|
+
getGridRef,
|
|
3043
|
+
dispatchEvent,
|
|
3044
|
+
splitTextToColumns: onSplitTextToColumns,
|
|
3045
|
+
copy,
|
|
3046
|
+
paste,
|
|
3047
|
+
cut,
|
|
3048
|
+
});
|
|
3049
|
+
const cellExpandComponent = useExpandCell({
|
|
3050
|
+
sheetId,
|
|
3051
|
+
theme,
|
|
3052
|
+
activeCell: hoveredCell,
|
|
3053
|
+
iconColor: filterIconColor,
|
|
3054
|
+
onRequestExpand,
|
|
3055
|
+
cellExpandPredicate,
|
|
3056
|
+
getCellSpacing,
|
|
3057
|
+
onChangeActiveCell,
|
|
3058
|
+
getCellOffsetFromCoords,
|
|
3059
|
+
getScrollPosition,
|
|
3060
|
+
isFrozenColumn,
|
|
3061
|
+
isFrozenRow,
|
|
3062
|
+
});
|
|
3063
|
+
// Pivot placeholders
|
|
3064
|
+
const pivotPlaceholders = useMemo(() => {
|
|
3065
|
+
const placeholders = [];
|
|
3066
|
+
let displayIdx = 0;
|
|
3067
|
+
for (const pivotTable of pivotTables ?? []) {
|
|
3068
|
+
if (!pivotTable.pivotRange &&
|
|
3069
|
+
pivotTable.targetPosition.sheetId === sheetId) {
|
|
3070
|
+
displayIdx++;
|
|
3071
|
+
const cellOffset = getCellOffsetFromCoords?.(pivotTable.targetPosition);
|
|
3072
|
+
const displayName = pivotTable.name || `PivotTable${displayIdx}`;
|
|
3073
|
+
placeholders.push(React.createElement(PivotPlaceholder, { pivotTable: pivotTable, onRequestEditPivotTable: onRequestEditPivotTable, left: cellOffset?.x ?? 0, top: cellOffset?.y ?? 0, displayName: displayName, key: pivotTable.pivotId }));
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
3076
|
+
return placeholders;
|
|
3077
|
+
}, [pivotTables, sheetId, onRequestEditPivotTable, getCellOffsetFromCoords]);
|
|
3078
|
+
/**
|
|
3079
|
+
* Helper function to reset grid cache if column or
|
|
3080
|
+
* row dimension changes
|
|
3081
|
+
*/
|
|
3082
|
+
useHiddenDimensions(columnMetadata, rowMetadata, sheetId, scale, resetLastMeasuredIndices, hostHiddenRowRanges, visibleRowRanges);
|
|
3083
|
+
// Callback when sheet changes
|
|
3084
|
+
useSheetChangeHandler(sheetId,
|
|
3085
|
+
// Immediate callback for imperative methods
|
|
3086
|
+
() => {
|
|
3087
|
+
if (activeCell && selections) {
|
|
3088
|
+
updateSelectionStartEndReference(activeCell, selections);
|
|
3089
|
+
}
|
|
3090
|
+
// Clear text overflow values
|
|
3091
|
+
overflowMapRef.current.clear();
|
|
3092
|
+
},
|
|
3093
|
+
// Effects callbacks
|
|
3094
|
+
(newScrollPosition) => {
|
|
3095
|
+
// Update scrollPosition
|
|
3096
|
+
if (newScrollPosition && isSheetScrollScheduled()) {
|
|
3097
|
+
if (isTouchDevice) {
|
|
3098
|
+
scrollToTouchDevice(newScrollPosition);
|
|
3099
|
+
}
|
|
3100
|
+
else {
|
|
3101
|
+
scrollTo(newScrollPosition);
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
// Wait for sheet change to finish
|
|
3105
|
+
requestAnimationFrame(() => {
|
|
3106
|
+
// If user is not in formula mode and changing sheet.
|
|
3107
|
+
// The edit belongs to the sheet it was started on, so flush it —
|
|
3108
|
+
// `hideEditor()` alone threw the typed value away, leaving the cell
|
|
3109
|
+
// empty while the formula bar kept showing the abandoned text. Hosts
|
|
3110
|
+
// no longer need to call `commit()` before switching sheets.
|
|
3111
|
+
// `preserveActiveSheet` keeps the user on the sheet they moved to; the
|
|
3112
|
+
// value is still written back to the sheet it was typed on.
|
|
3113
|
+
// Formula mode is excluded: switching sheets mid-formula is how a
|
|
3114
|
+
// cross-sheet range is picked, so the editor has to stay open.
|
|
3115
|
+
//
|
|
3116
|
+
// Ordering here is load-bearing in both directions. It has to run
|
|
3117
|
+
// inside the rAF, after the sheet-change render has committed:
|
|
3118
|
+
// `useSpreadsheetState`'s `onChange` mints the shared-string id inside
|
|
3119
|
+
// the `onChangeSheetData` updater and flushes the registry right
|
|
3120
|
+
// after, which only lines up because React evaluates an updater
|
|
3121
|
+
// eagerly when the component has no pending update. Flushing from the
|
|
3122
|
+
// layout effect — while the host's active-sheet update is still in
|
|
3123
|
+
// flight — defers that updater past the flush, and the cell keeps an
|
|
3124
|
+
// `ss` pointer to an entry that never reaches the shared-strings table
|
|
3125
|
+
// and renders blank. It also has to run before the focus handling
|
|
3126
|
+
// below, so a throw in `focusSheet()` can't cost the user their edit.
|
|
3127
|
+
if (!formulaMode && !commit({ preserveActiveSheet: true })) {
|
|
3128
|
+
// Nothing was being edited — keep the original reset.
|
|
3129
|
+
hideEditor();
|
|
3130
|
+
}
|
|
3131
|
+
// Focus editor
|
|
3132
|
+
if (formulaMode && !activeEditor?.isFocused()) {
|
|
3133
|
+
// When sheet is changed, we
|
|
3134
|
+
// need to keep the focus in the current
|
|
3135
|
+
// cursor
|
|
3136
|
+
focusActiveEditor(false);
|
|
3137
|
+
}
|
|
3138
|
+
else {
|
|
3139
|
+
// Keep focus back on sheet
|
|
3140
|
+
// Check if user is focused on the context menu
|
|
3141
|
+
if (canUseDOM &&
|
|
3142
|
+
document.activeElement?.getAttribute("role") !== "menu") {
|
|
3143
|
+
focusSheet();
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
});
|
|
3147
|
+
});
|
|
3148
|
+
// props reference for spreadsheet api
|
|
3149
|
+
propsReferenceRef.current = props;
|
|
3150
|
+
// Expose a spreadsheet API
|
|
3151
|
+
useIsomorphicLayoutEffect(() => {
|
|
3152
|
+
const stableMethods = {
|
|
3153
|
+
getUserEnteredValue: getUserEnteredStringValueStable,
|
|
3154
|
+
scrollToCell,
|
|
3155
|
+
commit,
|
|
3156
|
+
};
|
|
3157
|
+
setSpreadsheetApi(new SpreadsheetApi(propsReferenceRef, stableMethods, store, instanceStore, instanceId));
|
|
3158
|
+
}, []);
|
|
3159
|
+
// Update formulabar input value when activecell changes
|
|
3160
|
+
useIsomorphicLayoutEffect(() => {
|
|
3161
|
+
if (formulaMode) {
|
|
3162
|
+
return;
|
|
3163
|
+
}
|
|
3164
|
+
if (editingCellCoordinate ||
|
|
3165
|
+
isEqualCells(editingCellCoordinate, activeCell)) {
|
|
3166
|
+
// We are currently in edit mode
|
|
3167
|
+
// We should only update if the editing value changes
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
const { rowIndex, columnIndex } = activeCell;
|
|
3171
|
+
const value = getUserEnteredStringValue(sheetId, rowIndex, columnIndex);
|
|
3172
|
+
const textFormatRuns = getTextFormatRuns?.(sheetId, rowIndex, columnIndex);
|
|
3173
|
+
// Update formula bar input
|
|
3174
|
+
setFormulabarEditorValue(value ?? "");
|
|
3175
|
+
setFormulaBarTextFormatRuns(textFormatRuns);
|
|
3176
|
+
}, [
|
|
3177
|
+
activeCell,
|
|
3178
|
+
formulaMode,
|
|
3179
|
+
sheetId,
|
|
3180
|
+
editingCellCoordinate,
|
|
3181
|
+
getUserEnteredStringValue,
|
|
3182
|
+
setFormulabarEditorValue,
|
|
3183
|
+
setFormulaBarTextFormatRuns,
|
|
3184
|
+
]);
|
|
3185
|
+
// Keep active editor in focus
|
|
3186
|
+
// When user shows and hides the formula help
|
|
3187
|
+
useIsomorphicLayoutEffect(() => {
|
|
3188
|
+
focusActiveEditor(false);
|
|
3189
|
+
}, [showFormulaHelp]);
|
|
3190
|
+
// --- END SIDE EFFECTS ---
|
|
3191
|
+
/**
|
|
3192
|
+
* Insert components inside the grid viewport
|
|
3193
|
+
*/
|
|
3194
|
+
const gridChildren = useGridChildren({
|
|
3195
|
+
stickyEditor,
|
|
3196
|
+
editorComponent,
|
|
3197
|
+
chartComponents,
|
|
3198
|
+
embedComponents,
|
|
3199
|
+
slicerComponents,
|
|
3200
|
+
pivotPlaceholders,
|
|
3201
|
+
tableResizers,
|
|
3202
|
+
hiddenColumnMarkers,
|
|
3203
|
+
frozenHiddenColumnMarkers,
|
|
3204
|
+
hiddenRowMarkers,
|
|
3205
|
+
frozenHiddenRowMarkers,
|
|
3206
|
+
frozenRows,
|
|
3207
|
+
frozenColumns,
|
|
3208
|
+
headerMenuComponent,
|
|
3209
|
+
isHeaderMenuInFrozenColumn,
|
|
3210
|
+
popoverComponent,
|
|
3211
|
+
popoverRange,
|
|
3212
|
+
cellExpandComponent,
|
|
3213
|
+
});
|
|
3214
|
+
/**
|
|
3215
|
+
* Only enable selection drag if user is not editing and not
|
|
3216
|
+
* in formula mode
|
|
3217
|
+
*/
|
|
3218
|
+
const enableSelectionDrag = !isSelectionInProgress && !isEditInProgress && !formulaMode;
|
|
3219
|
+
return (React.createElement("div", { className: cn("rnc-canvas-wrapper after:box-border before:box-border [&_*]:box-border flex min-h-0 min-w-0 relative z-[1] flex-1 bg-rnc-background", className), ref: gridContainerRef,
|
|
3220
|
+
// The grid paints to <canvas>, so there is no per-cell DOM for a screen
|
|
3221
|
+
// reader to traverse. role="application" passes keystrokes through to our
|
|
3222
|
+
// custom keyboard handling, and the aria-live region below announces the
|
|
3223
|
+
// active cell on navigation. (A full off-screen role=grid/gridcell mirror
|
|
3224
|
+
// is a larger follow-up.)
|
|
3225
|
+
role: "application", "aria-label": "Spreadsheet grid",
|
|
3226
|
+
// css={{
|
|
3227
|
+
// backgroundColor: cellBackgroundColor,
|
|
3228
|
+
// }}
|
|
3229
|
+
onContextMenu: onContextMenu,
|
|
3230
|
+
// Bind to outer container, so it always takes
|
|
3231
|
+
// priority over other components
|
|
3232
|
+
// generated by hooks
|
|
3233
|
+
onMouseMove: mouseMoveThrottler, onWheel: onMouseWheel, ...rest },
|
|
3234
|
+
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" },
|
|
3235
|
+
React.createElement("div", { className: "space-y-2" },
|
|
3236
|
+
React.createElement(Skeleton, { className: "h-4 w-[250px]" }),
|
|
3237
|
+
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,
|
|
3238
|
+
// Dimension of fill handle
|
|
3239
|
+
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 })),
|
|
3240
|
+
tooltipComponent,
|
|
3241
|
+
stickyEditor ? editorComponent : null,
|
|
3242
|
+
draggableColumns,
|
|
3243
|
+
draggableRows,
|
|
3244
|
+
contextMenuComponent,
|
|
3245
|
+
filterComponent,
|
|
3246
|
+
headerResizer,
|
|
3247
|
+
validatorResult,
|
|
3248
|
+
React.createElement("div", { "aria-live": "polite", "aria-atomic": "true", style: {
|
|
3249
|
+
position: "absolute",
|
|
3250
|
+
width: 1,
|
|
3251
|
+
height: 1,
|
|
3252
|
+
margin: -1,
|
|
3253
|
+
padding: 0,
|
|
3254
|
+
overflow: "hidden",
|
|
3255
|
+
clip: "rect(0, 0, 0, 0)",
|
|
3256
|
+
whiteSpace: "nowrap",
|
|
3257
|
+
border: 0,
|
|
3258
|
+
} }, activeCellAnnouncement)));
|
|
3259
|
+
}
|
|
3260
|
+
export const CanvasGrid = memo(forwardRef(CanvasGridComponent));
|