@rowsncolumns/spreadsheet-state 28.0.76 → 29.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/api/anchored-objects.d.ts +122 -6
- package/dist/cjs/api/anchored-objects.d.ts.map +1 -1
- package/dist/cjs/api/anchored-objects.js +464 -43
- package/dist/cjs/api/copy-paste.d.ts +8 -2
- package/dist/cjs/api/copy-paste.d.ts.map +1 -1
- package/dist/cjs/api/copy-paste.js +4 -4
- package/dist/cjs/api/filter.d.ts +15 -1
- package/dist/cjs/api/filter.d.ts.map +1 -1
- package/dist/cjs/api/filter.js +32 -2
- package/dist/cjs/api/formula.d.ts +63 -0
- package/dist/cjs/api/formula.d.ts.map +1 -1
- package/dist/cjs/api/formula.js +278 -8
- package/dist/cjs/api/immer-utils.d.ts +11 -1
- package/dist/cjs/api/immer-utils.d.ts.map +1 -1
- package/dist/cjs/api/immer-utils.js +17 -1
- package/dist/cjs/api/insert-cut-cells.d.ts +35 -0
- package/dist/cjs/api/insert-cut-cells.d.ts.map +1 -0
- package/dist/cjs/api/insert-cut-cells.js +60 -0
- package/dist/cjs/api/merges.d.ts +8 -0
- package/dist/cjs/api/merges.d.ts.map +1 -1
- package/dist/cjs/api/merges.js +11 -0
- package/dist/cjs/api/paint-format.d.ts +22 -1
- package/dist/cjs/api/paint-format.d.ts.map +1 -1
- package/dist/cjs/api/paint-format.js +57 -1
- package/dist/cjs/api/sort.d.ts +23 -1
- package/dist/cjs/api/sort.d.ts.map +1 -1
- package/dist/cjs/api/sort.js +52 -6
- package/dist/cjs/api/structural-guards.d.ts +57 -0
- package/dist/cjs/api/structural-guards.d.ts.map +1 -1
- package/dist/cjs/api/structural-guards.js +93 -1
- package/dist/cjs/api/structural-table-refs.d.ts +58 -3
- package/dist/cjs/api/structural-table-refs.d.ts.map +1 -1
- package/dist/cjs/api/structural-table-refs.js +177 -16
- package/dist/cjs/api/subtotal.d.ts +20 -13
- package/dist/cjs/api/subtotal.d.ts.map +1 -1
- package/dist/cjs/api/subtotal.js +26 -19
- package/dist/cjs/api/table.d.ts +26 -2
- package/dist/cjs/api/table.d.ts.map +1 -1
- package/dist/cjs/api/table.js +93 -60
- package/dist/cjs/api/validation.d.ts.map +1 -1
- package/dist/cjs/api/validation.js +53 -8
- package/dist/cjs/atoms/creating-table.atom.d.ts +22 -0
- package/dist/cjs/atoms/creating-table.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/creating-table.atom.js +4 -0
- package/dist/cjs/atoms/dialog-state.atom.d.ts +8 -0
- package/dist/cjs/atoms/dialog-state.atom.d.ts.map +1 -1
- package/dist/cjs/atoms/dialog-state.atom.js +28 -0
- package/dist/cjs/atoms/editing-slicer.atom.d.ts +9 -0
- package/dist/cjs/atoms/editing-slicer.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/editing-slicer.atom.js +6 -0
- package/dist/cjs/atoms/index.d.ts +4 -0
- package/dist/cjs/atoms/index.d.ts.map +1 -1
- package/dist/cjs/atoms/index.js +4 -0
- package/dist/cjs/atoms/inserting-slicer.atom.d.ts +8 -0
- package/dist/cjs/atoms/inserting-slicer.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/inserting-slicer.atom.js +5 -0
- package/dist/cjs/atoms/resizing-table.atom.d.ts +8 -0
- package/dist/cjs/atoms/resizing-table.atom.d.ts.map +1 -0
- package/dist/cjs/atoms/resizing-table.atom.js +5 -0
- package/dist/cjs/commands.d.ts +138 -2
- package/dist/cjs/commands.d.ts.map +1 -1
- package/dist/cjs/components/editors/embed-editor.d.ts +4 -2
- package/dist/cjs/components/editors/embed-editor.d.ts.map +1 -1
- package/dist/cjs/components/editors/embed-editor.js +38 -9
- package/dist/cjs/components/editors/slicer-editor.d.ts +15 -0
- package/dist/cjs/components/editors/slicer-editor.d.ts.map +1 -0
- package/dist/cjs/components/editors/slicer-editor.js +87 -0
- package/dist/cjs/components/editors/table-editor.d.ts +58 -2
- package/dist/cjs/components/editors/table-editor.d.ts.map +1 -1
- package/dist/cjs/components/editors/table-editor.js +261 -20
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/index.d.ts.map +1 -1
- package/dist/cjs/components/index.js +1 -0
- package/dist/cjs/constants.d.ts +9 -1
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +12 -0
- package/dist/cjs/generated-names.d.ts +13 -3
- package/dist/cjs/generated-names.d.ts.map +1 -1
- package/dist/cjs/generated-names.js +3 -1
- package/dist/cjs/helpers.d.ts +5 -0
- package/dist/cjs/helpers.d.ts.map +1 -1
- package/dist/cjs/helpers.js +10 -1
- package/dist/cjs/hooks/use-on-change-batch.d.ts +19 -2
- package/dist/cjs/hooks/use-on-change-batch.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-change-batch.js +43 -35
- package/dist/cjs/hooks/use-on-change-calculated-column.d.ts +10 -1
- package/dist/cjs/hooks/use-on-change-calculated-column.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-change-calculated-column.js +17 -5
- package/dist/cjs/hooks/use-on-change-table-column.d.ts +6 -1
- package/dist/cjs/hooks/use-on-change-table-column.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-change-table-column.js +17 -5
- package/dist/cjs/hooks/use-on-change.d.ts +36 -3
- package/dist/cjs/hooks/use-on-change.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-change.js +218 -136
- package/dist/cjs/hooks/use-on-copy.d.ts +1 -1
- package/dist/cjs/hooks/use-on-copy.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-copy.js +2 -3
- package/dist/cjs/hooks/use-on-create-custom-table-style.d.ts +17 -0
- package/dist/cjs/hooks/use-on-create-custom-table-style.d.ts.map +1 -0
- package/dist/cjs/hooks/use-on-create-custom-table-style.js +28 -0
- package/dist/cjs/hooks/use-on-create-named-range.d.ts +4 -2
- package/dist/cjs/hooks/use-on-create-named-range.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-create-named-range.js +11 -1
- package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts +2 -1
- package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-delete-cells-shift-left.js +3 -1
- package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts +2 -1
- package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-delete-cells-shift-up.js +3 -1
- package/dist/cjs/hooks/use-on-delete-column.d.ts +2 -1
- package/dist/cjs/hooks/use-on-delete-column.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-delete-column.js +3 -1
- package/dist/cjs/hooks/use-on-delete-row.d.ts +2 -1
- package/dist/cjs/hooks/use-on-delete-row.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-delete-row.js +3 -1
- package/dist/cjs/hooks/use-on-delete-sheet.d.ts +9 -1
- package/dist/cjs/hooks/use-on-delete-sheet.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-delete-sheet.js +17 -1
- package/dist/cjs/hooks/use-on-delete-table-row.d.ts +4 -1
- package/dist/cjs/hooks/use-on-delete-table-row.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-delete-table-row.js +19 -1
- package/dist/cjs/hooks/use-on-delete.d.ts +5 -2
- package/dist/cjs/hooks/use-on-delete.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-delete.js +5 -1
- package/dist/cjs/hooks/use-on-embeds.d.ts +7 -4
- package/dist/cjs/hooks/use-on-embeds.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-embeds.js +26 -24
- package/dist/cjs/hooks/use-on-fill.d.ts +17 -2
- package/dist/cjs/hooks/use-on-fill.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-fill.js +29 -15
- package/dist/cjs/hooks/use-on-filter-table.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-filter-table.js +209 -103
- package/dist/cjs/hooks/use-on-import-excel.d.ts +2 -1
- package/dist/cjs/hooks/use-on-import-excel.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-import-excel.js +22 -19
- package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts +2 -1
- package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-insert-cells-shift-down.js +3 -1
- package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts +2 -1
- package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-insert-cells-shift-right.js +3 -1
- package/dist/cjs/hooks/use-on-insert-column.d.ts +2 -1
- package/dist/cjs/hooks/use-on-insert-column.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-insert-column.js +3 -1
- package/dist/cjs/hooks/use-on-insert-row.d.ts +2 -1
- package/dist/cjs/hooks/use-on-insert-row.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-insert-row.js +3 -1
- package/dist/cjs/hooks/use-on-insert-table-row.d.ts +5 -2
- package/dist/cjs/hooks/use-on-insert-table-row.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-insert-table-row.js +19 -1
- package/dist/cjs/hooks/use-on-merge-unmerge-cells.d.ts +3 -2
- package/dist/cjs/hooks/use-on-merge-unmerge-cells.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-merge-unmerge-cells.js +14 -1
- package/dist/cjs/hooks/use-on-move-columns.d.ts +4 -1
- package/dist/cjs/hooks/use-on-move-columns.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-move-columns.js +28 -6
- package/dist/cjs/hooks/use-on-move-rows.d.ts +18 -1
- package/dist/cjs/hooks/use-on-move-rows.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-move-rows.js +44 -6
- package/dist/cjs/hooks/use-on-move-selection.d.ts +9 -2
- package/dist/cjs/hooks/use-on-move-selection.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-move-selection.js +101 -25
- package/dist/cjs/hooks/use-on-paste.d.ts +33 -2
- package/dist/cjs/hooks/use-on-paste.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-paste.js +1005 -740
- package/dist/cjs/hooks/use-on-remove-duplicates.d.ts +5 -2
- package/dist/cjs/hooks/use-on-remove-duplicates.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-remove-duplicates.js +5 -1
- package/dist/cjs/hooks/use-on-request-create-table.d.ts +13 -0
- package/dist/cjs/hooks/use-on-request-create-table.d.ts.map +1 -0
- package/dist/cjs/hooks/use-on-request-create-table.js +44 -0
- package/dist/cjs/hooks/use-on-request-insert-slicer.d.ts +7 -0
- package/dist/cjs/hooks/use-on-request-insert-slicer.d.ts.map +1 -0
- package/dist/cjs/hooks/use-on-request-insert-slicer.js +15 -0
- package/dist/cjs/hooks/use-on-request-resize-table.d.ts +7 -0
- package/dist/cjs/hooks/use-on-request-resize-table.d.ts.map +1 -0
- package/dist/cjs/hooks/use-on-request-resize-table.js +15 -0
- package/dist/cjs/hooks/use-on-resize-table.d.ts +5 -1
- package/dist/cjs/hooks/use-on-resize-table.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-resize-table.js +110 -33
- package/dist/cjs/hooks/use-on-sort-column.d.ts +28 -3
- package/dist/cjs/hooks/use-on-sort-column.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-sort-column.js +136 -90
- package/dist/cjs/hooks/use-on-sort-range.d.ts +26 -3
- package/dist/cjs/hooks/use-on-sort-range.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-sort-range.js +113 -67
- package/dist/cjs/hooks/use-on-sort-table.d.ts +18 -1
- package/dist/cjs/hooks/use-on-sort-table.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-sort-table.js +128 -98
- package/dist/cjs/hooks/use-on-subtotal.d.ts +10 -3
- package/dist/cjs/hooks/use-on-subtotal.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-subtotal.js +13 -9
- package/dist/cjs/hooks/use-on-table.d.ts +39 -7
- package/dist/cjs/hooks/use-on-table.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-table.js +257 -49
- package/dist/cjs/hooks/use-on-undo-calculated-column.d.ts +23 -0
- package/dist/cjs/hooks/use-on-undo-calculated-column.d.ts.map +1 -0
- package/dist/cjs/hooks/use-on-undo-calculated-column.js +70 -0
- package/dist/cjs/hooks/use-on-undo-table-auto-expansion.d.ts +28 -0
- package/dist/cjs/hooks/use-on-undo-table-auto-expansion.d.ts.map +1 -0
- package/dist/cjs/hooks/use-on-undo-table-auto-expansion.js +96 -0
- package/dist/cjs/hooks/use-on-update-named-range.d.ts +4 -2
- package/dist/cjs/hooks/use-on-update-named-range.d.ts.map +1 -1
- package/dist/cjs/hooks/use-on-update-named-range.js +13 -1
- package/dist/cjs/hooks/use-sheet-properties.d.ts +1 -0
- package/dist/cjs/hooks/use-sheet-properties.d.ts.map +1 -1
- package/dist/cjs/hooks/use-sheet-properties.js +54 -34
- package/dist/cjs/hooks/use-slicers.d.ts +2 -2
- package/dist/cjs/hooks/use-slicers.d.ts.map +1 -1
- package/dist/cjs/hooks/use-slicers.js +17 -26
- package/dist/cjs/hooks/use-sparkline-groups.d.ts +50 -0
- package/dist/cjs/hooks/use-sparkline-groups.d.ts.map +1 -0
- package/dist/cjs/hooks/use-sparkline-groups.js +192 -0
- package/dist/cjs/hooks/use-spreadsheet-state.d.ts +69 -12
- package/dist/cjs/hooks/use-spreadsheet-state.d.ts.map +1 -1
- package/dist/cjs/hooks/use-spreadsheet-state.js +383 -84
- package/dist/cjs/hooks/use-structured-reference.d.ts.map +1 -1
- package/dist/cjs/hooks/use-structured-reference.js +17 -0
- package/dist/cjs/hooks/use-undo-redo-actions.d.ts +2 -1
- package/dist/cjs/hooks/use-undo-redo-actions.d.ts.map +1 -1
- package/dist/cjs/hooks/use-undo-redo-actions.js +10 -2
- package/dist/cjs/hooks/use-undo-redo.d.ts +12 -0
- package/dist/cjs/hooks/use-undo-redo.d.ts.map +1 -1
- package/dist/cjs/hooks/use-undo-redo.js +169 -10
- package/dist/cjs/hooks/utils/sort-rows.d.ts.map +1 -1
- package/dist/cjs/hooks/utils/sort-rows.js +4 -3
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +9 -0
- package/dist/cjs/interface/apply-fill.d.ts +26 -3
- package/dist/cjs/interface/apply-fill.d.ts.map +1 -1
- package/dist/cjs/interface/apply-fill.js +207 -98
- package/dist/cjs/interface/change-batch.d.ts +1 -1
- package/dist/cjs/interface/change-batch.d.ts.map +1 -1
- package/dist/cjs/interface/change-batch.js +112 -15
- package/dist/cjs/interface/change-calculated-column.d.ts +6 -2
- package/dist/cjs/interface/change-calculated-column.d.ts.map +1 -1
- package/dist/cjs/interface/change-calculated-column.js +87 -17
- package/dist/cjs/interface/change-table-column.d.ts +81 -7
- package/dist/cjs/interface/change-table-column.d.ts.map +1 -1
- package/dist/cjs/interface/change-table-column.js +336 -76
- package/dist/cjs/interface/create-table.d.ts +15 -3
- package/dist/cjs/interface/create-table.d.ts.map +1 -1
- package/dist/cjs/interface/create-table.js +100 -25
- package/dist/cjs/interface/delete-cells-shift-left.d.ts +1 -1
- package/dist/cjs/interface/delete-cells-shift-left.d.ts.map +1 -1
- package/dist/cjs/interface/delete-cells-shift-left.js +10 -1
- package/dist/cjs/interface/delete-cells-shift-up.d.ts +1 -1
- package/dist/cjs/interface/delete-cells-shift-up.d.ts.map +1 -1
- package/dist/cjs/interface/delete-cells-shift-up.js +10 -1
- package/dist/cjs/interface/delete-cells.d.ts +1 -1
- package/dist/cjs/interface/delete-cells.d.ts.map +1 -1
- package/dist/cjs/interface/delete-cells.js +81 -25
- package/dist/cjs/interface/delete-column.d.ts +1 -1
- package/dist/cjs/interface/delete-column.d.ts.map +1 -1
- package/dist/cjs/interface/delete-column.js +29 -22
- package/dist/cjs/interface/delete-row.d.ts +1 -1
- package/dist/cjs/interface/delete-row.d.ts.map +1 -1
- package/dist/cjs/interface/delete-row.js +244 -39
- package/dist/cjs/interface/delete-sheet.d.ts +2 -2
- package/dist/cjs/interface/delete-sheet.d.ts.map +1 -1
- package/dist/cjs/interface/delete-sheet.js +118 -1
- package/dist/cjs/interface/delete-table-column.d.ts +1 -1
- package/dist/cjs/interface/delete-table-column.d.ts.map +1 -1
- package/dist/cjs/interface/delete-table-column.js +11 -1
- package/dist/cjs/interface/delete-table-row.d.ts +1 -1
- package/dist/cjs/interface/delete-table-row.d.ts.map +1 -1
- package/dist/cjs/interface/delete-table-row.js +361 -275
- package/dist/cjs/interface/duplicate-sheet.d.ts.map +1 -1
- package/dist/cjs/interface/duplicate-sheet.js +83 -31
- package/dist/cjs/interface/embeds.d.ts +10 -1
- package/dist/cjs/interface/embeds.d.ts.map +1 -1
- package/dist/cjs/interface/embeds.js +120 -6
- package/dist/cjs/interface/insert-cells-shift-down.d.ts +1 -1
- package/dist/cjs/interface/insert-cells-shift-down.d.ts.map +1 -1
- package/dist/cjs/interface/insert-cells-shift-down.js +10 -1
- package/dist/cjs/interface/insert-cells-shift-right.d.ts +1 -1
- package/dist/cjs/interface/insert-cells-shift-right.d.ts.map +1 -1
- package/dist/cjs/interface/insert-cells-shift-right.js +10 -1
- package/dist/cjs/interface/insert-column.d.ts +2 -2
- package/dist/cjs/interface/insert-column.d.ts.map +1 -1
- package/dist/cjs/interface/insert-column.js +101 -56
- package/dist/cjs/interface/insert-row.d.ts +1 -1
- package/dist/cjs/interface/insert-row.d.ts.map +1 -1
- package/dist/cjs/interface/insert-row.js +25 -7
- package/dist/cjs/interface/insert-table-row.d.ts +2 -1
- package/dist/cjs/interface/insert-table-row.d.ts.map +1 -1
- package/dist/cjs/interface/insert-table-row.js +70 -19
- package/dist/cjs/interface/remove-duplicates.d.ts +1 -1
- package/dist/cjs/interface/remove-duplicates.d.ts.map +1 -1
- package/dist/cjs/interface/remove-duplicates.js +46 -6
- package/dist/cjs/interface/remove-table.d.ts +1 -1
- package/dist/cjs/interface/remove-table.d.ts.map +1 -1
- package/dist/cjs/interface/remove-table.js +72 -16
- package/dist/cjs/interface/slicers.d.ts +12 -1
- package/dist/cjs/interface/slicers.d.ts.map +1 -1
- package/dist/cjs/interface/slicers.js +47 -2
- package/dist/cjs/interface/spreadsheet-interface.d.ts +1 -1
- package/dist/cjs/interface/spreadsheet-interface.d.ts.map +1 -1
- package/dist/cjs/interface/spreadsheet-interface.js +64 -1
- package/dist/cjs/interface/table-totalrow.d.ts +13 -1
- package/dist/cjs/interface/table-totalrow.d.ts.map +1 -1
- package/dist/cjs/interface/table-totalrow.js +107 -73
- package/dist/cjs/interface/table-utils.d.ts +59 -6
- package/dist/cjs/interface/table-utils.d.ts.map +1 -1
- package/dist/cjs/interface/table-utils.js +211 -15
- package/dist/cjs/interface/update-table.d.ts +16 -1
- package/dist/cjs/interface/update-table.d.ts.map +1 -1
- package/dist/cjs/interface/update-table.js +190 -44
- package/dist/cjs/sheet-cell.d.ts.map +1 -1
- package/dist/cjs/test-setup.d.ts.map +1 -1
- package/dist/cjs/test-setup.js +6 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/validation-schema/table.schema.d.ts +11 -0
- package/dist/cjs/validation-schema/table.schema.d.ts.map +1 -1
- package/dist/cjs/validation-schema/table.schema.js +20 -3
- package/dist/esm/api/anchored-objects.d.ts +122 -6
- package/dist/esm/api/anchored-objects.d.ts.map +1 -1
- package/dist/esm/api/anchored-objects.js +375 -15
- package/dist/esm/api/copy-paste.d.ts +8 -2
- package/dist/esm/api/copy-paste.d.ts.map +1 -1
- package/dist/esm/api/copy-paste.js +4 -4
- package/dist/esm/api/filter.d.ts +15 -1
- package/dist/esm/api/filter.d.ts.map +1 -1
- package/dist/esm/api/filter.js +28 -0
- package/dist/esm/api/formula.d.ts +63 -0
- package/dist/esm/api/formula.d.ts.map +1 -1
- package/dist/esm/api/formula.js +235 -8
- package/dist/esm/api/immer-utils.d.ts +11 -1
- package/dist/esm/api/immer-utils.d.ts.map +1 -1
- package/dist/esm/api/immer-utils.js +16 -0
- package/dist/esm/api/insert-cut-cells.d.ts +35 -0
- package/dist/esm/api/insert-cut-cells.d.ts.map +1 -0
- package/dist/esm/api/insert-cut-cells.js +67 -0
- package/dist/esm/api/merges.d.ts +8 -0
- package/dist/esm/api/merges.d.ts.map +1 -1
- package/dist/esm/api/merges.js +9 -0
- package/dist/esm/api/paint-format.d.ts +22 -1
- package/dist/esm/api/paint-format.d.ts.map +1 -1
- package/dist/esm/api/paint-format.js +44 -1
- package/dist/esm/api/sort.d.ts +23 -1
- package/dist/esm/api/sort.d.ts.map +1 -1
- package/dist/esm/api/sort.js +45 -6
- package/dist/esm/api/structural-guards.d.ts +57 -0
- package/dist/esm/api/structural-guards.d.ts.map +1 -1
- package/dist/esm/api/structural-guards.js +85 -0
- package/dist/esm/api/structural-table-refs.d.ts +58 -3
- package/dist/esm/api/structural-table-refs.d.ts.map +1 -1
- package/dist/esm/api/structural-table-refs.js +126 -6
- package/dist/esm/api/subtotal.d.ts +20 -13
- package/dist/esm/api/subtotal.d.ts.map +1 -1
- package/dist/esm/api/subtotal.js +15 -8
- package/dist/esm/api/table.d.ts +26 -2
- package/dist/esm/api/table.d.ts.map +1 -1
- package/dist/esm/api/table.js +70 -48
- package/dist/esm/api/validation.d.ts.map +1 -1
- package/dist/esm/api/validation.js +53 -8
- package/dist/esm/atoms/creating-table.atom.d.ts +22 -0
- package/dist/esm/atoms/creating-table.atom.d.ts.map +1 -0
- package/dist/esm/atoms/creating-table.atom.js +4 -0
- package/dist/esm/atoms/dialog-state.atom.d.ts +8 -0
- package/dist/esm/atoms/dialog-state.atom.d.ts.map +1 -1
- package/dist/esm/atoms/dialog-state.atom.js +12 -0
- package/dist/esm/atoms/editing-slicer.atom.d.ts +9 -0
- package/dist/esm/atoms/editing-slicer.atom.d.ts.map +1 -0
- package/dist/esm/atoms/editing-slicer.atom.js +6 -0
- package/dist/esm/atoms/index.d.ts +4 -0
- package/dist/esm/atoms/index.d.ts.map +1 -1
- package/dist/esm/atoms/index.js +4 -0
- package/dist/esm/atoms/inserting-slicer.atom.d.ts +8 -0
- package/dist/esm/atoms/inserting-slicer.atom.d.ts.map +1 -0
- package/dist/esm/atoms/inserting-slicer.atom.js +5 -0
- package/dist/esm/atoms/resizing-table.atom.d.ts +8 -0
- package/dist/esm/atoms/resizing-table.atom.d.ts.map +1 -0
- package/dist/esm/atoms/resizing-table.atom.js +5 -0
- package/dist/esm/commands.d.ts +138 -2
- package/dist/esm/commands.d.ts.map +1 -1
- package/dist/esm/components/editors/embed-editor.d.ts +4 -2
- package/dist/esm/components/editors/embed-editor.d.ts.map +1 -1
- package/dist/esm/components/editors/embed-editor.js +40 -6
- package/dist/esm/components/editors/slicer-editor.d.ts +15 -0
- package/dist/esm/components/editors/slicer-editor.d.ts.map +1 -0
- package/dist/esm/components/editors/slicer-editor.js +85 -0
- package/dist/esm/components/editors/table-editor.d.ts +58 -2
- package/dist/esm/components/editors/table-editor.d.ts.map +1 -1
- package/dist/esm/components/editors/table-editor.js +243 -19
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/index.d.ts.map +1 -1
- package/dist/esm/components/index.js +1 -0
- package/dist/esm/constants.d.ts +9 -1
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +12 -0
- package/dist/esm/generated-names.d.ts +13 -3
- package/dist/esm/generated-names.d.ts.map +1 -1
- package/dist/esm/generated-names.js +3 -1
- package/dist/esm/helpers.d.ts +5 -0
- package/dist/esm/helpers.d.ts.map +1 -1
- package/dist/esm/helpers.js +7 -1
- package/dist/esm/hooks/use-on-change-batch.d.ts +19 -2
- package/dist/esm/hooks/use-on-change-batch.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-change-batch.js +19 -3
- package/dist/esm/hooks/use-on-change-calculated-column.d.ts +10 -1
- package/dist/esm/hooks/use-on-change-calculated-column.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-change-calculated-column.js +17 -5
- package/dist/esm/hooks/use-on-change-table-column.d.ts +6 -1
- package/dist/esm/hooks/use-on-change-table-column.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-change-table-column.js +17 -5
- package/dist/esm/hooks/use-on-change.d.ts +36 -3
- package/dist/esm/hooks/use-on-change.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-change.js +214 -124
- package/dist/esm/hooks/use-on-copy.d.ts +1 -1
- package/dist/esm/hooks/use-on-copy.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-copy.js +2 -3
- package/dist/esm/hooks/use-on-create-custom-table-style.d.ts +17 -0
- package/dist/esm/hooks/use-on-create-custom-table-style.d.ts.map +1 -0
- package/dist/esm/hooks/use-on-create-custom-table-style.js +26 -0
- package/dist/esm/hooks/use-on-create-named-range.d.ts +4 -2
- package/dist/esm/hooks/use-on-create-named-range.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-create-named-range.js +11 -1
- package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts +2 -1
- package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-delete-cells-shift-left.js +3 -1
- package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts +2 -1
- package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-delete-cells-shift-up.js +3 -1
- package/dist/esm/hooks/use-on-delete-column.d.ts +2 -1
- package/dist/esm/hooks/use-on-delete-column.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-delete-column.js +3 -1
- package/dist/esm/hooks/use-on-delete-row.d.ts +2 -1
- package/dist/esm/hooks/use-on-delete-row.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-delete-row.js +3 -1
- package/dist/esm/hooks/use-on-delete-sheet.d.ts +9 -1
- package/dist/esm/hooks/use-on-delete-sheet.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-delete-sheet.js +17 -1
- package/dist/esm/hooks/use-on-delete-table-row.d.ts +4 -1
- package/dist/esm/hooks/use-on-delete-table-row.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-delete-table-row.js +19 -1
- package/dist/esm/hooks/use-on-delete.d.ts +5 -2
- package/dist/esm/hooks/use-on-delete.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-delete.js +5 -1
- package/dist/esm/hooks/use-on-embeds.d.ts +7 -4
- package/dist/esm/hooks/use-on-embeds.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-embeds.js +23 -6
- package/dist/esm/hooks/use-on-fill.d.ts +17 -2
- package/dist/esm/hooks/use-on-fill.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-fill.js +27 -1
- package/dist/esm/hooks/use-on-filter-table.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-filter-table.js +97 -26
- package/dist/esm/hooks/use-on-import-excel.d.ts +2 -1
- package/dist/esm/hooks/use-on-import-excel.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-import-excel.js +4 -1
- package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts +2 -1
- package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-insert-cells-shift-down.js +3 -1
- package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts +2 -1
- package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-insert-cells-shift-right.js +3 -1
- package/dist/esm/hooks/use-on-insert-column.d.ts +2 -1
- package/dist/esm/hooks/use-on-insert-column.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-insert-column.js +3 -1
- package/dist/esm/hooks/use-on-insert-row.d.ts +2 -1
- package/dist/esm/hooks/use-on-insert-row.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-insert-row.js +3 -1
- package/dist/esm/hooks/use-on-insert-table-row.d.ts +5 -2
- package/dist/esm/hooks/use-on-insert-table-row.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-insert-table-row.js +19 -1
- package/dist/esm/hooks/use-on-merge-unmerge-cells.d.ts +3 -2
- package/dist/esm/hooks/use-on-merge-unmerge-cells.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-merge-unmerge-cells.js +12 -1
- package/dist/esm/hooks/use-on-move-columns.d.ts +4 -1
- package/dist/esm/hooks/use-on-move-columns.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-move-columns.js +28 -6
- package/dist/esm/hooks/use-on-move-rows.d.ts +18 -1
- package/dist/esm/hooks/use-on-move-rows.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-move-rows.js +44 -6
- package/dist/esm/hooks/use-on-move-selection.d.ts +9 -2
- package/dist/esm/hooks/use-on-move-selection.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-move-selection.js +57 -1
- package/dist/esm/hooks/use-on-paste.d.ts +33 -2
- package/dist/esm/hooks/use-on-paste.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-paste.js +825 -643
- package/dist/esm/hooks/use-on-remove-duplicates.d.ts +5 -2
- package/dist/esm/hooks/use-on-remove-duplicates.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-remove-duplicates.js +5 -1
- package/dist/esm/hooks/use-on-request-create-table.d.ts +13 -0
- package/dist/esm/hooks/use-on-request-create-table.d.ts.map +1 -0
- package/dist/esm/hooks/use-on-request-create-table.js +43 -0
- package/dist/esm/hooks/use-on-request-insert-slicer.d.ts +7 -0
- package/dist/esm/hooks/use-on-request-insert-slicer.d.ts.map +1 -0
- package/dist/esm/hooks/use-on-request-insert-slicer.js +15 -0
- package/dist/esm/hooks/use-on-request-resize-table.d.ts +7 -0
- package/dist/esm/hooks/use-on-request-resize-table.d.ts.map +1 -0
- package/dist/esm/hooks/use-on-request-resize-table.js +15 -0
- package/dist/esm/hooks/use-on-resize-table.d.ts +5 -1
- package/dist/esm/hooks/use-on-resize-table.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-resize-table.js +107 -27
- package/dist/esm/hooks/use-on-sort-column.d.ts +28 -3
- package/dist/esm/hooks/use-on-sort-column.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-sort-column.js +105 -68
- package/dist/esm/hooks/use-on-sort-range.d.ts +26 -3
- package/dist/esm/hooks/use-on-sort-range.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-sort-range.js +100 -64
- package/dist/esm/hooks/use-on-sort-table.d.ts +18 -1
- package/dist/esm/hooks/use-on-sort-table.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-sort-table.js +107 -86
- package/dist/esm/hooks/use-on-subtotal.d.ts +10 -3
- package/dist/esm/hooks/use-on-subtotal.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-subtotal.js +7 -5
- package/dist/esm/hooks/use-on-table.d.ts +39 -7
- package/dist/esm/hooks/use-on-table.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-table.js +234 -26
- package/dist/esm/hooks/use-on-undo-calculated-column.d.ts +23 -0
- package/dist/esm/hooks/use-on-undo-calculated-column.d.ts.map +1 -0
- package/dist/esm/hooks/use-on-undo-calculated-column.js +62 -0
- package/dist/esm/hooks/use-on-undo-table-auto-expansion.d.ts +28 -0
- package/dist/esm/hooks/use-on-undo-table-auto-expansion.d.ts.map +1 -0
- package/dist/esm/hooks/use-on-undo-table-auto-expansion.js +75 -0
- package/dist/esm/hooks/use-on-update-named-range.d.ts +4 -2
- package/dist/esm/hooks/use-on-update-named-range.d.ts.map +1 -1
- package/dist/esm/hooks/use-on-update-named-range.js +13 -1
- package/dist/esm/hooks/use-sheet-properties.d.ts +1 -0
- package/dist/esm/hooks/use-sheet-properties.d.ts.map +1 -1
- package/dist/esm/hooks/use-sheet-properties.js +38 -19
- package/dist/esm/hooks/use-slicers.d.ts +2 -2
- package/dist/esm/hooks/use-slicers.d.ts.map +1 -1
- package/dist/esm/hooks/use-slicers.js +16 -8
- package/dist/esm/hooks/use-sparkline-groups.d.ts +50 -0
- package/dist/esm/hooks/use-sparkline-groups.d.ts.map +1 -0
- package/dist/esm/hooks/use-sparkline-groups.js +146 -0
- package/dist/esm/hooks/use-spreadsheet-state.d.ts +69 -12
- package/dist/esm/hooks/use-spreadsheet-state.d.ts.map +1 -1
- package/dist/esm/hooks/use-spreadsheet-state.js +321 -14
- package/dist/esm/hooks/use-structured-reference.d.ts.map +1 -1
- package/dist/esm/hooks/use-structured-reference.js +17 -0
- package/dist/esm/hooks/use-undo-redo-actions.d.ts +2 -1
- package/dist/esm/hooks/use-undo-redo-actions.d.ts.map +1 -1
- package/dist/esm/hooks/use-undo-redo-actions.js +8 -2
- package/dist/esm/hooks/use-undo-redo.d.ts +12 -0
- package/dist/esm/hooks/use-undo-redo.d.ts.map +1 -1
- package/dist/esm/hooks/use-undo-redo.js +158 -7
- package/dist/esm/hooks/utils/sort-rows.d.ts.map +1 -1
- package/dist/esm/hooks/utils/sort-rows.js +4 -3
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +9 -0
- package/dist/esm/interface/apply-fill.d.ts +26 -3
- package/dist/esm/interface/apply-fill.d.ts.map +1 -1
- package/dist/esm/interface/apply-fill.js +188 -88
- package/dist/esm/interface/change-batch.d.ts +1 -1
- package/dist/esm/interface/change-batch.d.ts.map +1 -1
- package/dist/esm/interface/change-batch.js +89 -8
- package/dist/esm/interface/change-calculated-column.d.ts +6 -2
- package/dist/esm/interface/change-calculated-column.d.ts.map +1 -1
- package/dist/esm/interface/change-calculated-column.js +81 -16
- package/dist/esm/interface/change-table-column.d.ts +81 -7
- package/dist/esm/interface/change-table-column.d.ts.map +1 -1
- package/dist/esm/interface/change-table-column.js +295 -67
- package/dist/esm/interface/create-table.d.ts +15 -3
- package/dist/esm/interface/create-table.d.ts.map +1 -1
- package/dist/esm/interface/create-table.js +103 -27
- package/dist/esm/interface/delete-cells-shift-left.d.ts +1 -1
- package/dist/esm/interface/delete-cells-shift-left.d.ts.map +1 -1
- package/dist/esm/interface/delete-cells-shift-left.js +10 -1
- package/dist/esm/interface/delete-cells-shift-up.d.ts +1 -1
- package/dist/esm/interface/delete-cells-shift-up.d.ts.map +1 -1
- package/dist/esm/interface/delete-cells-shift-up.js +10 -1
- package/dist/esm/interface/delete-cells.d.ts +1 -1
- package/dist/esm/interface/delete-cells.d.ts.map +1 -1
- package/dist/esm/interface/delete-cells.js +47 -14
- package/dist/esm/interface/delete-column.d.ts +1 -1
- package/dist/esm/interface/delete-column.d.ts.map +1 -1
- package/dist/esm/interface/delete-column.js +26 -30
- package/dist/esm/interface/delete-row.d.ts +1 -1
- package/dist/esm/interface/delete-row.d.ts.map +1 -1
- package/dist/esm/interface/delete-row.js +191 -44
- package/dist/esm/interface/delete-sheet.d.ts +2 -2
- package/dist/esm/interface/delete-sheet.d.ts.map +1 -1
- package/dist/esm/interface/delete-sheet.js +113 -1
- package/dist/esm/interface/delete-table-column.d.ts +1 -1
- package/dist/esm/interface/delete-table-column.d.ts.map +1 -1
- package/dist/esm/interface/delete-table-column.js +11 -1
- package/dist/esm/interface/delete-table-row.d.ts +1 -1
- package/dist/esm/interface/delete-table-row.d.ts.map +1 -1
- package/dist/esm/interface/delete-table-row.js +312 -232
- package/dist/esm/interface/duplicate-sheet.d.ts.map +1 -1
- package/dist/esm/interface/duplicate-sheet.js +73 -26
- package/dist/esm/interface/embeds.d.ts +10 -1
- package/dist/esm/interface/embeds.d.ts.map +1 -1
- package/dist/esm/interface/embeds.js +84 -5
- package/dist/esm/interface/insert-cells-shift-down.d.ts +1 -1
- package/dist/esm/interface/insert-cells-shift-down.d.ts.map +1 -1
- package/dist/esm/interface/insert-cells-shift-down.js +10 -1
- package/dist/esm/interface/insert-cells-shift-right.d.ts +1 -1
- package/dist/esm/interface/insert-cells-shift-right.d.ts.map +1 -1
- package/dist/esm/interface/insert-cells-shift-right.js +10 -1
- package/dist/esm/interface/insert-column.d.ts +2 -2
- package/dist/esm/interface/insert-column.d.ts.map +1 -1
- package/dist/esm/interface/insert-column.js +70 -33
- package/dist/esm/interface/insert-row.d.ts +1 -1
- package/dist/esm/interface/insert-row.d.ts.map +1 -1
- package/dist/esm/interface/insert-row.js +22 -6
- package/dist/esm/interface/insert-table-row.d.ts +2 -1
- package/dist/esm/interface/insert-table-row.d.ts.map +1 -1
- package/dist/esm/interface/insert-table-row.js +67 -12
- package/dist/esm/interface/remove-duplicates.d.ts +1 -1
- package/dist/esm/interface/remove-duplicates.d.ts.map +1 -1
- package/dist/esm/interface/remove-duplicates.js +41 -6
- package/dist/esm/interface/remove-table.d.ts +1 -1
- package/dist/esm/interface/remove-table.d.ts.map +1 -1
- package/dist/esm/interface/remove-table.js +58 -10
- package/dist/esm/interface/slicers.d.ts +12 -1
- package/dist/esm/interface/slicers.d.ts.map +1 -1
- package/dist/esm/interface/slicers.js +44 -2
- package/dist/esm/interface/spreadsheet-interface.d.ts +1 -1
- package/dist/esm/interface/spreadsheet-interface.d.ts.map +1 -1
- package/dist/esm/interface/spreadsheet-interface.js +73 -1
- package/dist/esm/interface/table-totalrow.d.ts +13 -1
- package/dist/esm/interface/table-totalrow.d.ts.map +1 -1
- package/dist/esm/interface/table-totalrow.js +98 -68
- package/dist/esm/interface/table-utils.d.ts +59 -6
- package/dist/esm/interface/table-utils.d.ts.map +1 -1
- package/dist/esm/interface/table-utils.js +155 -14
- package/dist/esm/interface/update-table.d.ts +16 -1
- package/dist/esm/interface/update-table.d.ts.map +1 -1
- package/dist/esm/interface/update-table.js +203 -42
- package/dist/esm/sheet-cell.d.ts.map +1 -1
- package/dist/esm/test-setup.d.ts.map +1 -1
- package/dist/esm/test-setup.js +6 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/validation-schema/table.schema.d.ts +11 -0
- package/dist/esm/validation-schema/table.schema.d.ts.map +1 -1
- package/dist/esm/validation-schema/table.schema.js +15 -2
- package/package.json +25 -17
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { isStaticNode } from "@rowsncolumns/dag";
|
|
2
|
-
import { areaIntersects, isAreasEqual } from "@rowsncolumns/grid";
|
|
2
|
+
import { areaInsideArea, areaIntersects, isAreasEqual } from "@rowsncolumns/grid";
|
|
3
3
|
import { selectionFromActiveCell } from "@rowsncolumns/grid";
|
|
4
4
|
import { DEFAULT_COLUMN_COUNT, DEFAULT_ROW_COUNT, findActiveTableWithinCell, loadWebFont, MAX_COLUMN_COUNT, MAX_ROW_COUNT, useFocusEmbedOrChart, useGetFinalRowHeight, useRedrawGrid, } from "@rowsncolumns/spreadsheet";
|
|
5
5
|
import { isSelectionACell, useGetEffectiveValuesFromRange, } from "@rowsncolumns/spreadsheet";
|
|
6
6
|
import { error, getCellFormattedValue, getCellUserEnteredFormat, getCellUserEnteredValue, getExtendedValueBool, getExtendedValueFormula, getExtendedValueNumber, getExtendedValueString, isNil, iterateCellsInRange, uuidString, } from "@rowsncolumns/utils";
|
|
7
7
|
import { produceWithPatches } from "immer";
|
|
8
8
|
import { useCallback } from "react";
|
|
9
|
+
import { moveChartsOnRangeMove } from "../api/anchored-objects";
|
|
9
10
|
import { processSideEffectDependentCells } from "../api/dependency";
|
|
10
11
|
import { createSheetCellIdentifier } from "../api/formula";
|
|
11
12
|
import { createSheetDraft } from "../api/immer-utils";
|
|
13
|
+
import { findPartiallyCoveredMerge, MERGED_CELL_MOVE_ERROR } from "../api/merges";
|
|
14
|
+
import { moveRange } from "../api/selection";
|
|
15
|
+
import { useShowError } from "../atoms/error-state.atom";
|
|
12
16
|
import { applyPasteOperation, isBlankClipboardCell, resolvePasteSpecialOptions, } from "../api/paste-special";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
17
|
+
import { getMoveRangeRefusal } from "../api/structural-guards";
|
|
18
|
+
import { renameHeaderCellsInFormulas } from "../api/structural-table-refs";
|
|
19
|
+
import { findAdjacentTable } from "../api/table";
|
|
20
|
+
import { getNextTableTitle } from "../helpers";
|
|
15
21
|
import { collectDataValidationTarget, extendDataValidationRanges, } from "../interface/data-validation-utils";
|
|
22
|
+
import { planHeaderCellRenames } from "../interface/change-table-column";
|
|
16
23
|
import { SheetCell } from "../sheet-cell";
|
|
17
24
|
import { extractFontFamily, generateDataFromClipboard, pickFormatting, pickFormula, pickValue, transpose, } from "./../api/copy-paste";
|
|
18
25
|
import { useCalculationQueue } from "./use-calculation-queue";
|
|
@@ -33,8 +40,9 @@ export const buildDestinationRowAssignments = (sheetId, startRowIndex, endRowInd
|
|
|
33
40
|
}
|
|
34
41
|
return assignments;
|
|
35
42
|
};
|
|
36
|
-
export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: currentTables, maxRowCount = MAX_ROW_COUNT, maxColumnCount = MAX_COLUMN_COUNT, isHiddenByFilterRow, onRequestFonts, idCreationStrategy, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeSelections, onChangeActiveCell, getDependents, getActiveCell, getUserEnteredValue, onChangeDataValidations, preserveFormatting = true, cellXfsRegistry, sharedStringRegistry, getDataValidationById, getSheetName, onError, citations, onChangeCitations, sanitizeHtml, onCommand, generatedNames, }) => {
|
|
43
|
+
export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: currentTables, maxRowCount = MAX_ROW_COUNT, maxColumnCount = MAX_COLUMN_COUNT, isHiddenByFilterRow, onRequestFonts, idCreationStrategy, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeSelections, onChangeActiveCell, getDependents, getActiveCell, getUserEnteredValue, onChangeDataValidations, onChangeNamedRanges, onChangeCharts, getSheetMerges, preserveFormatting = true, cellXfsRegistry, sharedStringRegistry, getDataValidationById, getSheetName, onError, citations, onChangeCitations, sanitizeHtml, onCommand, generatedNames, batchHistory = (action) => action(), autoExpandTables = true, autoCalculatedColumns = true, }) => {
|
|
37
44
|
const canEditCellRange = useCanEditCellRange();
|
|
45
|
+
const showError = useShowError();
|
|
38
46
|
// Allowed values
|
|
39
47
|
const getEffectiveValuesFromRange = useGetEffectiveValuesFromRange();
|
|
40
48
|
const focusEmbedOrChart = useFocusEmbedOrChart();
|
|
@@ -47,6 +55,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
|
|
|
47
55
|
onChangeTables,
|
|
48
56
|
getSheetName,
|
|
49
57
|
onCommand,
|
|
58
|
+
autoCalculatedColumns,
|
|
50
59
|
});
|
|
51
60
|
const onChangeTableColumn = useOnChangeTableColumn({
|
|
52
61
|
locale,
|
|
@@ -55,9 +64,11 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
|
|
|
55
64
|
enqueueGraphOperation,
|
|
56
65
|
onChangeSheetData,
|
|
57
66
|
onChangeTables,
|
|
67
|
+
onChangeCharts,
|
|
58
68
|
getDependents,
|
|
59
69
|
onCommand,
|
|
60
70
|
generatedNames,
|
|
71
|
+
tables: currentTables,
|
|
61
72
|
});
|
|
62
73
|
const redrawGrid = useRedrawGrid();
|
|
63
74
|
const getFinalRowHeight = useGetFinalRowHeight();
|
|
@@ -97,7 +108,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
|
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
else {
|
|
100
|
-
const pasteResults = await generateDataFromClipboard(e, activeCell, destinationSheetId, activeSheetName, preserveFormatting, locale, idCreationStrategy, forcePlainText, sanitizeHtml
|
|
111
|
+
const pasteResults = await generateDataFromClipboard(e, activeCell, destinationSheetId, activeSheetName, preserveFormatting, locale, idCreationStrategy, forcePlainText, sanitizeHtml);
|
|
101
112
|
selectedRowValues = pasteResults?.results ?? [];
|
|
102
113
|
merges = pasteResults?.merges;
|
|
103
114
|
embeds = pasteResults?.embeds;
|
|
@@ -121,8 +132,6 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
|
|
|
121
132
|
else if (pasteMode === "values") {
|
|
122
133
|
selectedRowValues = pickValue(selectedRowValues, destinationSheetId, locale);
|
|
123
134
|
}
|
|
124
|
-
const saveHistory = createHistory();
|
|
125
|
-
const dataValidationTargets = new Map();
|
|
126
135
|
const fontFamilies = extractFontFamily(selectedRowValues);
|
|
127
136
|
// Wait for fonts to load
|
|
128
137
|
if (fontFamilies.length && preserveFormatting) {
|
|
@@ -142,721 +151,887 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
|
|
|
142
151
|
error("Error loading webfonts", fontFamilies, err);
|
|
143
152
|
}
|
|
144
153
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
:
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
154
|
+
// From here on the paste is synchronous: its writes and the table growth / calculated-column
|
|
155
|
+
// fill they trigger open ONE undo entry.
|
|
156
|
+
batchHistory(() => {
|
|
157
|
+
const saveHistory = createHistory();
|
|
158
|
+
const dataValidationTargets = new Map();
|
|
159
|
+
const [rowSpan, colSpan] = [
|
|
160
|
+
selectedRowValues?.length ?? 0,
|
|
161
|
+
// For cut operations, use range dimensions since data may be sparse
|
|
162
|
+
isCutOperation && from
|
|
163
|
+
? from.range.endColumnIndex - from.range.startColumnIndex + 1
|
|
164
|
+
: selectedRowValues[0]?.length ?? 0,
|
|
165
|
+
];
|
|
166
|
+
const to = selections?.[selections?.length - 1] ??
|
|
167
|
+
selectionFromActiveCell(activeCell)[0];
|
|
168
|
+
const rowDelta = from && to ? to.range.startRowIndex - from.range.startRowIndex : -1;
|
|
169
|
+
const columnDelta = from && to
|
|
170
|
+
? to.range.startColumnIndex - from.range.startColumnIndex
|
|
171
|
+
: -1;
|
|
172
|
+
// A cut is a move: a table the cut block covers whole travels with it (Excel; the rnc
|
|
173
|
+
// engine's `move-range` does the same), so it is neither the table the paste writes into
|
|
174
|
+
// nor one the paste grows.
|
|
175
|
+
const movedTables = isCutOperation && from && !isNil(sourceSheetId)
|
|
176
|
+
? currentTables?.filter((table) => table.sheetId === sourceSheetId &&
|
|
177
|
+
areaInsideArea(table.range, from.range)) ?? []
|
|
178
|
+
: [];
|
|
179
|
+
const stayingTables = movedTables.length
|
|
180
|
+
? currentTables?.filter((table) => !movedTables.includes(table))
|
|
181
|
+
: currentTables;
|
|
182
|
+
// When user enters a value in the last row of a
|
|
183
|
+
// table and if the entire row is empty
|
|
184
|
+
const [adjacentTable, isRowExpansion, isColumnExpansion] = autoExpandTables
|
|
185
|
+
? findAdjacentTable(destinationSheetId, activeCell, stayingTables, getUserEnteredValue)
|
|
186
|
+
: [undefined, false, false];
|
|
187
|
+
const currentTable = isColumnExpansion && adjacentTable
|
|
188
|
+
? adjacentTable
|
|
189
|
+
: findActiveTableWithinCell(destinationSheetId, activeCell, stayingTables);
|
|
190
|
+
// Next selections
|
|
191
|
+
const nextSelections = finalSelections?.length ? finalSelections : [to];
|
|
192
|
+
// Update range based on length of data
|
|
193
|
+
to.range.endRowIndex = Math.min(maxRowCount, Math.max(to.range.endRowIndex, to.range.startRowIndex + rowSpan - 1));
|
|
194
|
+
to.range.endColumnIndex = Math.min(maxColumnCount, Math.max(to.range.endColumnIndex, to.range.startColumnIndex + colSpan - 1));
|
|
195
|
+
// Check for protected range
|
|
196
|
+
if (!canEditCellRange(destinationSheetId, to.range)) {
|
|
197
|
+
console.debug("Protected range, You cannot paste on to protected cells.");
|
|
180
198
|
return;
|
|
181
199
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
+
// A cut is a move: Excel refuses it when the destination (or the source) covers a merged
|
|
201
|
+
// cell only partially — writing into a non-anchor cell of a merge would tear it.
|
|
202
|
+
if (isCutOperation &&
|
|
203
|
+
from &&
|
|
204
|
+
!isNil(sourceSheetId) &&
|
|
205
|
+
(findPartiallyCoveredMerge(to.range, getSheetMerges?.(destinationSheetId)) ||
|
|
206
|
+
findPartiallyCoveredMerge(from.range, getSheetMerges?.(sourceSheetId)))) {
|
|
207
|
+
showError({ message: MERGED_CELL_MOVE_ERROR });
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
// …and Excel never moves PART of a table, nor lands a block on another table's cells — the
|
|
211
|
+
// drag-move refusals (T-46) apply to a cut + paste too, across sheets (T-79).
|
|
212
|
+
if (isCutOperation && from && !isNil(sourceSheetId)) {
|
|
213
|
+
const tableRefusal = getMoveRangeRefusal({
|
|
214
|
+
sheetId: sourceSheetId,
|
|
215
|
+
from: from.range,
|
|
216
|
+
to: to.range,
|
|
217
|
+
toSheetId: destinationSheetId,
|
|
218
|
+
tables: currentTables,
|
|
219
|
+
});
|
|
220
|
+
if (tableRefusal) {
|
|
221
|
+
showError({ title: tableRefusal.title, message: tableRefusal.message });
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Check if pasting a table would overlap with an existing table
|
|
226
|
+
if (tables?.length) {
|
|
227
|
+
const existingTable = currentTables?.find((table) => table.sheetId === destinationSheetId &&
|
|
228
|
+
areaIntersects(to.range, table.range));
|
|
229
|
+
if (existingTable) {
|
|
230
|
+
onError?.("Cannot paste a table over another table. The paste range overlaps with an existing table.");
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const destinationRows = buildDestinationRowAssignments(destinationSheetId, to.range.startRowIndex, to.range.endRowIndex, rowSpan, isHiddenByFilterRow);
|
|
235
|
+
if (!destinationRows.length) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// Paste writes through `onChangeSheetData` directly, so the
|
|
239
|
+
// calculator's per-cell invalidation never fires for the
|
|
240
|
+
// destination cells. Invalidate the destination rect — and the
|
|
241
|
+
// source on cut, since those cells are cleared too.
|
|
200
242
|
enqueueStructureChange?.({
|
|
201
243
|
kind: "invalidate-range",
|
|
202
|
-
sheetId:
|
|
203
|
-
startRowIndex:
|
|
204
|
-
endRowIndex:
|
|
205
|
-
startColumnIndex:
|
|
206
|
-
endColumnIndex:
|
|
244
|
+
sheetId: destinationSheetId,
|
|
245
|
+
startRowIndex: to.range.startRowIndex,
|
|
246
|
+
endRowIndex: to.range.endRowIndex,
|
|
247
|
+
startColumnIndex: to.range.startColumnIndex,
|
|
248
|
+
endColumnIndex: to.range.endColumnIndex,
|
|
207
249
|
});
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
250
|
+
if (isCutOperation && from && !isNil(sourceSheetId)) {
|
|
251
|
+
enqueueStructureChange?.({
|
|
252
|
+
kind: "invalidate-range",
|
|
253
|
+
sheetId: sourceSheetId,
|
|
254
|
+
startRowIndex: from.range.startRowIndex,
|
|
255
|
+
endRowIndex: from.range.endRowIndex,
|
|
256
|
+
startColumnIndex: from.range.startColumnIndex,
|
|
257
|
+
endColumnIndex: from.range.endColumnIndex,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
const visibleRowIndexes = destinationRows.map(({ rowIndex }) => rowIndex);
|
|
261
|
+
// Adds new column to table and cell to sheet
|
|
262
|
+
const sharedStrings = sharedStringRegistry?.getSharedStrings();
|
|
263
|
+
const pastedCellText = (cellValue) => {
|
|
264
|
+
const formattedValue = getCellFormattedValue(cellValue);
|
|
265
|
+
const sharedStringValue = cellValue?.ss == null || !sharedStrings
|
|
266
|
+
? undefined
|
|
267
|
+
: sharedStrings.get(String(cellValue.ss));
|
|
268
|
+
return typeof formattedValue === "string"
|
|
269
|
+
? formattedValue
|
|
270
|
+
: typeof sharedStringValue === "string"
|
|
271
|
+
? sharedStringValue
|
|
272
|
+
: undefined;
|
|
273
|
+
};
|
|
274
|
+
const activeCellValue = pastedCellText(selectedRowValues?.[0]?.[0]);
|
|
275
|
+
// A block pasted right of the table names every new column from its own header cell.
|
|
276
|
+
const pastedHeaderValues = isColumnExpansion &&
|
|
277
|
+
adjacentTable &&
|
|
278
|
+
activeCell.rowIndex === adjacentTable.range.startRowIndex
|
|
279
|
+
? selectedRowValues?.[0]?.map(pastedCellText)
|
|
223
280
|
: undefined;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
281
|
+
// Header cells of existing tables the paste lands on take the typed-header
|
|
282
|
+
// rule (text, de-duplicated, structured references following); a cut moves
|
|
283
|
+
// cells as they are and a formats-only paste writes no values.
|
|
284
|
+
const headerRenames = !isCutOperation && pasteMode !== "formats"
|
|
285
|
+
? planHeaderCellRenames({
|
|
286
|
+
sheetId: destinationSheetId,
|
|
287
|
+
tables: stayingTables,
|
|
288
|
+
generatedNames,
|
|
289
|
+
cells: destinationRows.flatMap(({ rowIndex, dataRowIndex }) => Array.from({
|
|
290
|
+
length: to.range.endColumnIndex - to.range.startColumnIndex + 1,
|
|
291
|
+
}, (_, cursor) => ({
|
|
292
|
+
rowIndex,
|
|
293
|
+
columnIndex: to.range.startColumnIndex + cursor,
|
|
294
|
+
value: pastedCellText(selectedRowValues[dataRowIndex]?.[colSpan > 0 ? cursor % colSpan : 0]),
|
|
295
|
+
}))),
|
|
296
|
+
})
|
|
297
|
+
: [];
|
|
298
|
+
const headerRenameAt = new Map(headerRenames.map((rename) => [
|
|
299
|
+
`${rename.rowIndex}:${rename.columnIndex}`,
|
|
300
|
+
rename,
|
|
301
|
+
]));
|
|
302
|
+
// We need to track this for history. Precedent cells
|
|
303
|
+
const recalcCells = new Map();
|
|
304
|
+
// Expand table if user is pasting
|
|
305
|
+
// table data
|
|
306
|
+
// Same undo history
|
|
307
|
+
if (!isNil(currentTable) && !isRowExpansion) {
|
|
308
|
+
// The overflow grows the table row by row and stops at the first row another table
|
|
309
|
+
// occupies (Excel; same rule as the adjacent-row growth in `changeTableColumn`). Cells
|
|
310
|
+
// pasted past that row stay plain cells.
|
|
311
|
+
let newEndRowIndex = currentTable.range.endRowIndex;
|
|
312
|
+
const lastOverflowRowIndex = activeCell.rowIndex + rowSpan - 1 + (currentTable.totalRow ? 1 : 0);
|
|
313
|
+
for (let rowIndex = currentTable.range.endRowIndex + 1; rowIndex <= lastOverflowRowIndex; rowIndex++) {
|
|
314
|
+
const line = {
|
|
315
|
+
...currentTable.range,
|
|
316
|
+
startRowIndex: rowIndex,
|
|
317
|
+
endRowIndex: rowIndex,
|
|
318
|
+
};
|
|
319
|
+
if (stayingTables?.some((other) => other.id !== currentTable.id &&
|
|
320
|
+
other.sheetId === destinationSheetId &&
|
|
321
|
+
areaIntersects(other.range, line))) {
|
|
322
|
+
break;
|
|
252
323
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
// Capture the produced state so we can stream the exact written cells to an engine
|
|
262
|
-
// consumer afterwards (branch-agnostic across cut / pure-paste / paste-special).
|
|
263
|
-
let pastedSheetData;
|
|
264
|
-
if (selectedRowValues.length) {
|
|
265
|
-
onChangeSheetData?.((prevSheetData) => {
|
|
266
|
-
const [nextState, patches, inversePatches] = produceWithPatches(prevSheetData, (draft) => {
|
|
267
|
-
// For cut operation
|
|
268
|
-
const movedKeys = new Set();
|
|
269
|
-
/**
|
|
270
|
-
* If user is deleting source cells,
|
|
271
|
-
* let update its dependents and mark it as dirty
|
|
272
|
-
*/
|
|
273
|
-
if (isCutOperation && from && to && !isNil(sourceSheetId)) {
|
|
274
|
-
const sheetId = sourceSheetId;
|
|
275
|
-
for (const [rowIndex, columnIndex] of iterateCellsInRange(from.range)) {
|
|
276
|
-
// Process dependents
|
|
277
|
-
processSideEffectDependentCells({
|
|
278
|
-
draft,
|
|
279
|
-
rowIndex,
|
|
280
|
-
columnIndex,
|
|
281
|
-
sheetId,
|
|
282
|
-
destinationSheetId,
|
|
283
|
-
columnDelta,
|
|
284
|
-
enqueueGraphOperation,
|
|
285
|
-
enqueueCalculation: enqueue,
|
|
286
|
-
getDependents,
|
|
287
|
-
recalcCells,
|
|
288
|
-
rowDelta,
|
|
289
|
-
sourceRange: from.range,
|
|
290
|
-
movedKeys,
|
|
291
|
-
locale,
|
|
292
|
-
rowCount,
|
|
293
|
-
columnCount,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
// Snapshot source after dependent/formula rewrites, before
|
|
297
|
-
// clearing it. The pre-cut clipboard snapshot still contains
|
|
298
|
-
// stale formulas, so writing that snapshot would discard the
|
|
299
|
-
// reference updates performed above.
|
|
300
|
-
const movedRowValues = [];
|
|
301
|
-
const sourceStartColumn = from.range.startColumnIndex;
|
|
302
|
-
const sourceEndColumn = from.range.endColumnIndex + 1;
|
|
303
|
-
for (let rowIndex = from.range.startRowIndex; rowIndex <= from.range.endRowIndex; rowIndex++) {
|
|
304
|
-
movedRowValues.push((draft[sheetId]?.[rowIndex]?.values?.slice(sourceStartColumn, sourceEndColumn) ?? []));
|
|
324
|
+
newEndRowIndex = rowIndex;
|
|
325
|
+
}
|
|
326
|
+
// Update table range
|
|
327
|
+
onChangeTables?.((prevTableData) => {
|
|
328
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevTableData, (draft) => {
|
|
329
|
+
const table = draft.find((table) => currentTable?.id === table.id);
|
|
330
|
+
if (table) {
|
|
331
|
+
table.range.endRowIndex = newEndRowIndex;
|
|
305
332
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
333
|
+
});
|
|
334
|
+
saveHistory({
|
|
335
|
+
tables: { patches, inversePatches },
|
|
336
|
+
});
|
|
337
|
+
return nextState;
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
if (headerRenames.length) {
|
|
341
|
+
onChangeTables?.((prevTables) => {
|
|
342
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
|
|
343
|
+
for (const { table, dimensionIndex, newName } of headerRenames) {
|
|
344
|
+
const current = draft.find((candidate) => candidate.id === table.id);
|
|
345
|
+
if (!current)
|
|
346
|
+
continue;
|
|
347
|
+
current.columns ??= [];
|
|
348
|
+
if (current.columns[dimensionIndex]) {
|
|
349
|
+
current.columns[dimensionIndex].name = newName;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
current.columns[dimensionIndex] = { name: newName };
|
|
315
353
|
}
|
|
316
354
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
355
|
+
});
|
|
356
|
+
saveHistory({ tables: { patches, inversePatches } });
|
|
357
|
+
return nextState;
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
// Update sheetdata
|
|
361
|
+
// Capture the produced state so we can stream the exact written cells to an engine
|
|
362
|
+
// consumer afterwards (branch-agnostic across cut / pure-paste / paste-special).
|
|
363
|
+
let pastedSheetData;
|
|
364
|
+
if (selectedRowValues.length) {
|
|
365
|
+
onChangeSheetData?.((prevSheetData) => {
|
|
366
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevSheetData, (draft) => {
|
|
367
|
+
// For cut operation
|
|
368
|
+
const movedKeys = new Set();
|
|
369
|
+
/**
|
|
370
|
+
* If user is deleting source cells,
|
|
371
|
+
* let update its dependents and mark it as dirty
|
|
372
|
+
*/
|
|
373
|
+
if (isCutOperation && from && to && !isNil(sourceSheetId)) {
|
|
374
|
+
const sheetId = sourceSheetId;
|
|
375
|
+
for (const [rowIndex, columnIndex] of iterateCellsInRange(from.range)) {
|
|
376
|
+
// Process dependents
|
|
377
|
+
processSideEffectDependentCells({
|
|
378
|
+
draft,
|
|
325
379
|
rowIndex,
|
|
326
380
|
columnIndex,
|
|
327
|
-
sheetId
|
|
328
|
-
|
|
329
|
-
|
|
381
|
+
sheetId,
|
|
382
|
+
destinationSheetId,
|
|
383
|
+
columnDelta,
|
|
384
|
+
enqueueGraphOperation,
|
|
385
|
+
enqueueCalculation: enqueue,
|
|
386
|
+
getDependents,
|
|
387
|
+
recalcCells,
|
|
388
|
+
rowDelta,
|
|
389
|
+
sourceRange: from.range,
|
|
390
|
+
movedKeys,
|
|
391
|
+
locale,
|
|
392
|
+
rowCount,
|
|
393
|
+
columnCount,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
// Snapshot source after dependent/formula rewrites, before
|
|
397
|
+
// clearing it. The pre-cut clipboard snapshot still contains
|
|
398
|
+
// stale formulas, so writing that snapshot would discard the
|
|
399
|
+
// reference updates performed above.
|
|
400
|
+
const movedRowValues = [];
|
|
401
|
+
const sourceStartColumn = from.range.startColumnIndex;
|
|
402
|
+
const sourceEndColumn = from.range.endColumnIndex + 1;
|
|
403
|
+
for (let rowIndex = from.range.startRowIndex; rowIndex <= from.range.endRowIndex; rowIndex++) {
|
|
404
|
+
movedRowValues.push((draft[sheetId]?.[rowIndex]?.values?.slice(sourceStartColumn, sourceEndColumn) ?? []));
|
|
405
|
+
}
|
|
406
|
+
// Delete source if required
|
|
407
|
+
// Move values
|
|
408
|
+
for (let rowIndex = from.range.startRowIndex; rowIndex <= from.range.endRowIndex; rowIndex++) {
|
|
409
|
+
for (let columnIndex = from.range.startColumnIndex; columnIndex <= from.range.endColumnIndex; columnIndex++) {
|
|
410
|
+
if (!draft[sheetId][rowIndex]?.values?.[columnIndex]) {
|
|
330
411
|
continue;
|
|
331
412
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
type: "add",
|
|
335
|
-
position,
|
|
336
|
-
force: true,
|
|
337
|
-
});
|
|
338
|
-
recalcCells.set(createSheetCellIdentifier(position.sheetId, position.rowIndex, position.columnIndex), position);
|
|
413
|
+
draft[sheetId][rowIndex].values[columnIndex] =
|
|
414
|
+
{};
|
|
339
415
|
}
|
|
340
|
-
collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
|
|
341
416
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
for (const { rowIndex, dataRowIndex } of destinationRows) {
|
|
365
|
-
const currentSheet = createSheetDraft(draft, destinationSheetId, rowIndex);
|
|
366
|
-
let columnCursor = 0;
|
|
367
|
-
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
|
|
368
|
-
const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
|
|
369
|
-
let cellValue = selectedRowValues[dataRowIndex]?.[dataColumnIndex];
|
|
370
|
-
// Skip blanks: an empty clipboard cell leaves the
|
|
371
|
-
// destination (value and format) untouched.
|
|
372
|
-
if (pasteSpecial.skipBlanks &&
|
|
373
|
-
isBlankClipboardCell(cellValue)) {
|
|
374
|
-
continue;
|
|
375
|
-
}
|
|
376
|
-
// Operation: combine the pasted cell with the cell it
|
|
377
|
-
// lands on. The clipboard is anchored at the FIRST tile,
|
|
378
|
-
// so a source formula is relocated to the tile it lands
|
|
379
|
-
// on first (the same `moveFormula` shift the plain paste
|
|
380
|
-
// applies below); the composed `=(dest)op(source)` is
|
|
381
|
-
// then anchored at the destination and must not be moved
|
|
382
|
-
// again (that would shift the destination fragment too).
|
|
383
|
-
if (pasteOperation) {
|
|
384
|
-
const sourceFormula = getExtendedValueFormula(getCellUserEnteredValue(cellValue));
|
|
385
|
-
if (!isNil(sourceFormula) &&
|
|
386
|
-
dataRowIndex === 0 &&
|
|
387
|
-
dataColumnIndex === 0 &&
|
|
388
|
-
(rowIndex !== sourceCell.rowIndex ||
|
|
389
|
-
columnIndex !== sourceCell.columnIndex)) {
|
|
390
|
-
const tileCell = new SheetCell();
|
|
391
|
-
tileCell.setLocale(locale);
|
|
392
|
-
tileCell.assign(destinationSheetId, sourceCell, cellValue);
|
|
393
|
-
tileCell.moveFormula(sourceCell, { rowIndex, columnIndex }, activeSheetName, { preserveAbsolutes: true });
|
|
394
|
-
cellValue = {
|
|
395
|
-
...cellValue,
|
|
396
|
-
ue: { ...cellValue?.ue, fv: tileCell.formula },
|
|
397
|
-
};
|
|
417
|
+
for (const { rowIndex, dataRowIndex } of destinationRows) {
|
|
418
|
+
const currentSheet = createSheetDraft(draft, destinationSheetId, rowIndex);
|
|
419
|
+
let columnCursor = 0;
|
|
420
|
+
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
|
|
421
|
+
const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
|
|
422
|
+
currentSheet[rowIndex].values[columnIndex] =
|
|
423
|
+
movedRowValues[dataRowIndex]?.[dataColumnIndex];
|
|
424
|
+
for (const dependent of getDependents({
|
|
425
|
+
rowIndex,
|
|
426
|
+
columnIndex,
|
|
427
|
+
sheetId: destinationSheetId,
|
|
428
|
+
})) {
|
|
429
|
+
if (isStaticNode(dependent)) {
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
const { position } = dependent;
|
|
433
|
+
enqueue({
|
|
434
|
+
type: "add",
|
|
435
|
+
position,
|
|
436
|
+
force: true,
|
|
437
|
+
});
|
|
438
|
+
recalcCells.set(createSheetCellIdentifier(position.sheetId, position.rowIndex, position.columnIndex), position);
|
|
398
439
|
}
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
if (pasteMode === "formats") {
|
|
402
|
-
const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
|
|
403
|
-
cellValue = { ...existingCellData, ...cellValue };
|
|
404
|
-
sheetCell.extendCellData(cellValue);
|
|
440
|
+
collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
|
|
405
441
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
if (sheetCell.isFormula()) {
|
|
439
|
-
if (dataRowIndex === 0 &&
|
|
440
|
-
dataColumnIndex === 0 &&
|
|
441
|
-
!pasteOperation) {
|
|
442
|
-
sheetCell.moveFormula(sourceCell, {
|
|
443
|
-
rowIndex,
|
|
444
|
-
columnIndex,
|
|
445
|
-
}, activeSheetName, { preserveAbsolutes: true });
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
// TBD: Move totalrow for tables
|
|
445
|
+
// We are doing pure paste operation
|
|
446
|
+
if (!isCutOperation) {
|
|
447
|
+
renameHeaderCellsInFormulas({
|
|
448
|
+
draft,
|
|
449
|
+
headerRenames,
|
|
450
|
+
enqueueCalculation: enqueue,
|
|
451
|
+
enqueueGraphOperation,
|
|
452
|
+
recalcCells,
|
|
453
|
+
locale,
|
|
454
|
+
cellXfsRegistry,
|
|
455
|
+
sharedStringRegistry,
|
|
456
|
+
});
|
|
457
|
+
const sheetCell = new SheetCell();
|
|
458
|
+
const sourceCell = {
|
|
459
|
+
rowIndex: to.range.startRowIndex,
|
|
460
|
+
columnIndex: to.range.startColumnIndex,
|
|
461
|
+
};
|
|
462
|
+
for (const { rowIndex, dataRowIndex } of destinationRows) {
|
|
463
|
+
const currentSheet = createSheetDraft(draft, destinationSheetId, rowIndex);
|
|
464
|
+
let columnCursor = 0;
|
|
465
|
+
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
|
|
466
|
+
const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
|
|
467
|
+
let cellValue = selectedRowValues[dataRowIndex]?.[dataColumnIndex];
|
|
468
|
+
// Skip blanks: an empty clipboard cell leaves the
|
|
469
|
+
// destination (value and format) untouched.
|
|
470
|
+
if (pasteSpecial.skipBlanks &&
|
|
471
|
+
isBlankClipboardCell(cellValue)) {
|
|
472
|
+
continue;
|
|
446
473
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
474
|
+
// Operation: combine the pasted cell with the cell it
|
|
475
|
+
// lands on. The clipboard is anchored at the FIRST tile,
|
|
476
|
+
// so a source formula is relocated to the tile it lands
|
|
477
|
+
// on first (the same `moveFormula` shift the plain paste
|
|
478
|
+
// applies below); the composed `=(dest)op(source)` is
|
|
479
|
+
// then anchored at the destination and must not be moved
|
|
480
|
+
// again (that would shift the destination fragment too).
|
|
481
|
+
if (pasteOperation) {
|
|
482
|
+
const sourceFormula = getExtendedValueFormula(getCellUserEnteredValue(cellValue));
|
|
483
|
+
if (!isNil(sourceFormula) &&
|
|
484
|
+
dataRowIndex === 0 &&
|
|
485
|
+
dataColumnIndex === 0 &&
|
|
486
|
+
(rowIndex !== sourceCell.rowIndex ||
|
|
487
|
+
columnIndex !== sourceCell.columnIndex)) {
|
|
488
|
+
const tileCell = new SheetCell();
|
|
489
|
+
tileCell.setLocale(locale);
|
|
490
|
+
tileCell.assign(destinationSheetId, sourceCell, cellValue);
|
|
491
|
+
tileCell.moveFormula(sourceCell, { rowIndex, columnIndex }, activeSheetName, { preserveAbsolutes: true });
|
|
492
|
+
cellValue = {
|
|
493
|
+
...cellValue,
|
|
494
|
+
ue: { ...cellValue?.ue, fv: tileCell.formula },
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
cellValue = applyPasteOperation(cellValue, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], pasteOperation, destinationSheetId, locale);
|
|
498
|
+
}
|
|
499
|
+
if (pasteMode === "formats") {
|
|
500
|
+
const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
|
|
501
|
+
cellValue = { ...existingCellData, ...cellValue };
|
|
502
|
+
sheetCell.extendCellData(cellValue);
|
|
503
|
+
}
|
|
504
|
+
if (pasteMode === "values" || forcePlainText) {
|
|
505
|
+
const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
|
|
506
|
+
// Remove ss from existingCellData since we're replacing the value
|
|
507
|
+
const { ss: _ss, ...existingWithoutSs } = existingCellData ?? {};
|
|
508
|
+
cellValue = { ...existingWithoutSs, ...cellValue };
|
|
509
|
+
sheetCell.extendCellData(cellValue);
|
|
510
|
+
}
|
|
511
|
+
if (pasteSpecial.transpose && pasteMode === "all") {
|
|
512
|
+
sheetCell.assign(destinationSheetId, { rowIndex, columnIndex }, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], {
|
|
513
|
+
locale,
|
|
514
|
+
cellXfsRegistry,
|
|
515
|
+
getDataValidationById,
|
|
516
|
+
sharedStringRegistry,
|
|
517
|
+
});
|
|
518
|
+
const existingCellData = sheetCell.getUserCellData();
|
|
519
|
+
cellValue = { ...existingCellData, ...cellValue };
|
|
520
|
+
sheetCell.extendCellData(cellValue);
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
sheetCell.assign(destinationSheetId, { rowIndex, columnIndex }, typeof cellValue === "object"
|
|
524
|
+
? cellValue
|
|
525
|
+
: undefined, {
|
|
526
|
+
getRangeValues: getEffectiveValuesFromRange,
|
|
527
|
+
locale,
|
|
528
|
+
cellXfsRegistry,
|
|
529
|
+
getDataValidationById,
|
|
530
|
+
sharedStringRegistry,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
if (pasteMode === "formats") {
|
|
534
|
+
sheetCell.refreshFormattedValue();
|
|
535
|
+
}
|
|
536
|
+
if (sheetCell.isFormula()) {
|
|
537
|
+
if (dataRowIndex === 0 &&
|
|
538
|
+
dataColumnIndex === 0 &&
|
|
539
|
+
!pasteOperation) {
|
|
540
|
+
sheetCell.moveFormula(sourceCell, {
|
|
541
|
+
rowIndex,
|
|
542
|
+
columnIndex,
|
|
543
|
+
}, activeSheetName, { preserveAbsolutes: true });
|
|
544
|
+
}
|
|
545
|
+
sheetCell.setLoading();
|
|
546
|
+
enqueue({
|
|
547
|
+
type: "add",
|
|
548
|
+
position: {
|
|
549
|
+
rowIndex,
|
|
550
|
+
columnIndex,
|
|
551
|
+
sheetId: destinationSheetId,
|
|
552
|
+
},
|
|
553
|
+
force: true,
|
|
554
|
+
});
|
|
555
|
+
recalcCells.set(createSheetCellIdentifier(destinationSheetId, rowIndex, columnIndex), {
|
|
451
556
|
rowIndex,
|
|
452
557
|
columnIndex,
|
|
453
558
|
sheetId: destinationSheetId,
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
recalcCells.set(createSheetCellIdentifier(destinationSheetId, rowIndex, columnIndex), {
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
for (const dependent of getDependents({
|
|
458
562
|
rowIndex,
|
|
459
563
|
columnIndex,
|
|
460
564
|
sheetId: destinationSheetId,
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
565
|
+
})) {
|
|
566
|
+
if (isStaticNode(dependent)) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
const { position } = dependent;
|
|
570
|
+
enqueue({
|
|
571
|
+
type: "add",
|
|
572
|
+
position,
|
|
573
|
+
force: true,
|
|
574
|
+
});
|
|
575
|
+
recalcCells.set(createSheetCellIdentifier(position.sheetId, position.rowIndex, position.columnIndex), position);
|
|
470
576
|
}
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
577
|
+
const headerRename = headerRenameAt.get(`${rowIndex}:${columnIndex}`);
|
|
578
|
+
if (headerRename) {
|
|
579
|
+
// A table header cell holds its column name as text.
|
|
580
|
+
sheetCell.setUserEnteredValue(headerRename.newName, undefined, { disableTypeInference: true });
|
|
581
|
+
}
|
|
582
|
+
sharedStringRegistry?.registerCell(sheetCell);
|
|
583
|
+
currentSheet[rowIndex].values[columnIndex] =
|
|
584
|
+
sheetCell.getCellData();
|
|
585
|
+
collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
|
|
586
|
+
cellXfsRegistry?.registerCellXfs(sheetCell);
|
|
478
587
|
}
|
|
479
|
-
sharedStringRegistry?.registerCell(sheetCell);
|
|
480
|
-
currentSheet[rowIndex].values[columnIndex] =
|
|
481
|
-
sheetCell.getCellData();
|
|
482
|
-
collectDataValidationTarget(dataValidationTargets, destinationSheetId, rowIndex, columnIndex, currentSheet[rowIndex].values[columnIndex]);
|
|
483
|
-
cellXfsRegistry?.registerCellXfs(sheetCell);
|
|
484
588
|
}
|
|
485
589
|
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
}
|
|
590
|
+
});
|
|
591
|
+
saveHistory({
|
|
592
|
+
sheetData: { patches, inversePatches },
|
|
593
|
+
recalcCells: { undo: recalcCells, redo: recalcCells },
|
|
594
|
+
activeCell: {
|
|
595
|
+
undo: getActiveCell(),
|
|
596
|
+
redo: getActiveCell(),
|
|
597
|
+
},
|
|
598
|
+
selections: {
|
|
599
|
+
undo: undefined,
|
|
600
|
+
redo: isSelectionACell(nextSelections) ? undefined : [to],
|
|
601
|
+
},
|
|
602
|
+
});
|
|
603
|
+
extendDataValidationRanges(dataValidationTargets, onChangeDataValidations, saveHistory);
|
|
604
|
+
processQueue();
|
|
605
|
+
pastedSheetData = nextState;
|
|
606
|
+
return nextState;
|
|
499
607
|
});
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
608
|
+
// Save registries
|
|
609
|
+
cellXfsRegistry?.getPatches(saveHistory);
|
|
610
|
+
sharedStringRegistry?.getPatches(saveHistory);
|
|
611
|
+
// Update row or column count
|
|
612
|
+
// Change sheets
|
|
613
|
+
onChangeSheets?.((prevSheets) => {
|
|
614
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevSheets, (draft) => {
|
|
615
|
+
const sheet = draft.find((sheet) => sheet.sheetId === destinationSheetId);
|
|
616
|
+
if (sheet) {
|
|
617
|
+
sheet.rowCount = Math.min(maxRowCount, Math.max(sheet.rowCount ?? DEFAULT_ROW_COUNT, to.range.endRowIndex));
|
|
618
|
+
sheet.columnCount = Math.min(maxColumnCount, Math.max(sheet.columnCount ?? DEFAULT_COLUMN_COUNT, to.range.endColumnIndex));
|
|
619
|
+
// Handle merges for cut operations
|
|
620
|
+
let mergesToAdd = merges;
|
|
621
|
+
if (isCutOperation && from && !isNil(sourceSheetId)) {
|
|
622
|
+
const sourceSheet = prevSheets.find((s) => s.sheetId === sourceSheetId);
|
|
623
|
+
if (sourceSheet?.merges) {
|
|
624
|
+
// Extract merged cells from source range
|
|
625
|
+
const cutMerges = [];
|
|
626
|
+
for (const merge of sourceSheet.merges) {
|
|
627
|
+
// Check if merge intersects with the cut range
|
|
628
|
+
if (areaIntersects(merge, from.range)) {
|
|
629
|
+
// Calculate new merge coordinates relative to destination
|
|
630
|
+
cutMerges.push({
|
|
631
|
+
startRowIndex: merge.startRowIndex + rowDelta,
|
|
632
|
+
startColumnIndex: merge.startColumnIndex + columnDelta,
|
|
633
|
+
endRowIndex: merge.endRowIndex + rowDelta,
|
|
634
|
+
endColumnIndex: merge.endColumnIndex + columnDelta,
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (cutMerges.length > 0) {
|
|
639
|
+
mergesToAdd = cutMerges;
|
|
640
|
+
}
|
|
641
|
+
// Remove merges from source sheet
|
|
642
|
+
const sourceSheetDraft = draft.find((s) => s.sheetId === sourceSheetId);
|
|
643
|
+
if (sourceSheetDraft?.merges) {
|
|
644
|
+
sourceSheetDraft.merges = sourceSheetDraft.merges.filter((merge) => !areaIntersects(merge, from.range));
|
|
533
645
|
}
|
|
534
|
-
}
|
|
535
|
-
if (cutMerges.length > 0) {
|
|
536
|
-
mergesToAdd = cutMerges;
|
|
537
|
-
}
|
|
538
|
-
// Remove merges from source sheet
|
|
539
|
-
const sourceSheetDraft = draft.find((s) => s.sheetId === sourceSheetId);
|
|
540
|
-
if (sourceSheetDraft?.merges) {
|
|
541
|
-
sourceSheetDraft.merges = sourceSheetDraft.merges.filter((merge) => !areaIntersects(merge, from.range));
|
|
542
646
|
}
|
|
543
647
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
648
|
+
// Update merges
|
|
649
|
+
if (mergesToAdd) {
|
|
650
|
+
sheet.merges = sheet.merges ?? [];
|
|
651
|
+
for (const merge of mergesToAdd) {
|
|
652
|
+
const exists = sheet.merges.find((range) => isAreasEqual(range, merge));
|
|
653
|
+
if (!exists) {
|
|
654
|
+
sheet.merges.push(merge);
|
|
655
|
+
}
|
|
552
656
|
}
|
|
553
657
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
sheet.rowMetadata = [];
|
|
560
|
-
}
|
|
561
|
-
for (let index = 0; index < rowHeights.length; index++) {
|
|
562
|
-
const curHeight = rowHeights[index];
|
|
563
|
-
if (isNil(curHeight) || curHeight === 0) {
|
|
564
|
-
continue;
|
|
565
|
-
}
|
|
566
|
-
const rowIndex = visibleRowIndexes[index];
|
|
567
|
-
if (isNil(rowIndex)) {
|
|
568
|
-
break;
|
|
658
|
+
// Row heights
|
|
659
|
+
const clipboardSizedRows = new Set();
|
|
660
|
+
if (rowHeights) {
|
|
661
|
+
if (!sheet.rowMetadata) {
|
|
662
|
+
sheet.rowMetadata = [];
|
|
569
663
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
sheet.rowMetadata[rowIndex].size = curHeight;
|
|
574
|
-
clipboardSizedRows.add(rowIndex);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
// Auto-resize rows whose pasted content needs more room
|
|
578
|
-
// (multi-line text or wrap). Mirrors use-on-change's
|
|
579
|
-
// adjustRowHeight, but batched into this immer pass so the
|
|
580
|
-
// whole paste collapses to one undo entry. Skip conditions
|
|
581
|
-
// make the common single-line-text paste do zero work.
|
|
582
|
-
// Skipped for paste-special variants since the destination
|
|
583
|
-
// cell ends up as a merge of existing + pasted data, not
|
|
584
|
-
// the raw pasted value we can read from selectedRowValues.
|
|
585
|
-
const skipAutoResize = pasteSpecial.isSpecial;
|
|
586
|
-
if (!skipAutoResize &&
|
|
587
|
-
getFinalRowHeight &&
|
|
588
|
-
selectedRowValues.length &&
|
|
589
|
-
colSpan > 0) {
|
|
590
|
-
for (const { rowIndex, dataRowIndex } of destinationRows) {
|
|
591
|
-
// Clipboard-provided row heights win.
|
|
592
|
-
if (clipboardSizedRows.has(rowIndex))
|
|
593
|
-
continue;
|
|
594
|
-
const rowData = selectedRowValues[dataRowIndex];
|
|
595
|
-
if (!rowData)
|
|
596
|
-
continue;
|
|
597
|
-
// Find the cell most likely to drive row height —
|
|
598
|
-
// most lines first, then any wrap. If no cell in
|
|
599
|
-
// the row needs more than one line and no cell is
|
|
600
|
-
// wrapped, the row's existing height already fits.
|
|
601
|
-
let bestLines = 1;
|
|
602
|
-
let bestColumnIndex;
|
|
603
|
-
let bestCell;
|
|
604
|
-
let bestHasWrap = false;
|
|
605
|
-
let columnCursor = 0;
|
|
606
|
-
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
|
|
607
|
-
const dataColumnIndex = columnCursor % colSpan;
|
|
608
|
-
const cellValue = rowData[dataColumnIndex];
|
|
609
|
-
if (!cellValue || typeof cellValue !== "object")
|
|
664
|
+
for (let index = 0; index < rowHeights.length; index++) {
|
|
665
|
+
const curHeight = rowHeights[index];
|
|
666
|
+
if (isNil(curHeight) || curHeight === 0) {
|
|
610
667
|
continue;
|
|
611
|
-
const ue = getCellUserEnteredValue(cellValue);
|
|
612
|
-
const text = getExtendedValueString(ue);
|
|
613
|
-
const lines = typeof text === "string" && text.includes("\n")
|
|
614
|
-
? text.split("\n").length
|
|
615
|
-
: 1;
|
|
616
|
-
const uf = getCellUserEnteredFormat(cellValue);
|
|
617
|
-
const wrap = uf
|
|
618
|
-
?.wrapStrategy === "wrap";
|
|
619
|
-
if (lines > bestLines ||
|
|
620
|
-
(lines === bestLines && wrap && !bestHasWrap)) {
|
|
621
|
-
bestLines = lines;
|
|
622
|
-
bestCell = cellValue;
|
|
623
|
-
bestColumnIndex = columnIndex;
|
|
624
|
-
bestHasWrap = wrap;
|
|
625
668
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
continue;
|
|
631
|
-
}
|
|
632
|
-
const ue = getCellUserEnteredValue(bestCell);
|
|
633
|
-
const overrideText = getExtendedValueString(ue) ?? "";
|
|
634
|
-
const uf = getCellUserEnteredFormat(bestCell);
|
|
635
|
-
const height = getFinalRowHeight(destinationSheetId, rowIndex, bestColumnIndex, {
|
|
636
|
-
textOverride: String(overrideText),
|
|
637
|
-
textFormatOverride: uf?.textFormat,
|
|
638
|
-
shouldWrapOverride: bestHasWrap,
|
|
639
|
-
});
|
|
640
|
-
if (typeof height === "number" && height > 0) {
|
|
641
|
-
if (!sheet.rowMetadata)
|
|
642
|
-
sheet.rowMetadata = [];
|
|
669
|
+
const rowIndex = visibleRowIndexes[index];
|
|
670
|
+
if (isNil(rowIndex)) {
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
643
673
|
if (!sheet.rowMetadata[rowIndex]) {
|
|
644
674
|
sheet.rowMetadata[rowIndex] = {};
|
|
645
675
|
}
|
|
646
|
-
sheet.rowMetadata[rowIndex].size =
|
|
647
|
-
|
|
676
|
+
sheet.rowMetadata[rowIndex].size = curHeight;
|
|
677
|
+
clipboardSizedRows.add(rowIndex);
|
|
648
678
|
}
|
|
649
679
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
680
|
+
// Auto-resize rows whose pasted content needs more room
|
|
681
|
+
// (multi-line text or wrap). Mirrors use-on-change's
|
|
682
|
+
// adjustRowHeight, but batched into this immer pass so the
|
|
683
|
+
// whole paste collapses to one undo entry. Skip conditions
|
|
684
|
+
// make the common single-line-text paste do zero work.
|
|
685
|
+
// Skipped for paste-special variants since the destination
|
|
686
|
+
// cell ends up as a merge of existing + pasted data, not
|
|
687
|
+
// the raw pasted value we can read from selectedRowValues.
|
|
688
|
+
const skipAutoResize = pasteSpecial.isSpecial;
|
|
689
|
+
if (!skipAutoResize &&
|
|
690
|
+
getFinalRowHeight &&
|
|
691
|
+
selectedRowValues.length &&
|
|
692
|
+
colSpan > 0) {
|
|
693
|
+
for (const { rowIndex, dataRowIndex } of destinationRows) {
|
|
694
|
+
// Clipboard-provided row heights win.
|
|
695
|
+
if (clipboardSizedRows.has(rowIndex))
|
|
696
|
+
continue;
|
|
697
|
+
const rowData = selectedRowValues[dataRowIndex];
|
|
698
|
+
if (!rowData)
|
|
699
|
+
continue;
|
|
700
|
+
// Find the cell most likely to drive row height —
|
|
701
|
+
// most lines first, then any wrap. If no cell in
|
|
702
|
+
// the row needs more than one line and no cell is
|
|
703
|
+
// wrapped, the row's existing height already fits.
|
|
704
|
+
let bestLines = 1;
|
|
705
|
+
let bestColumnIndex;
|
|
706
|
+
let bestCell;
|
|
707
|
+
let bestHasWrap = false;
|
|
708
|
+
let columnCursor = 0;
|
|
709
|
+
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
|
|
710
|
+
const dataColumnIndex = columnCursor % colSpan;
|
|
711
|
+
const cellValue = rowData[dataColumnIndex];
|
|
712
|
+
if (!cellValue || typeof cellValue !== "object")
|
|
713
|
+
continue;
|
|
714
|
+
const ue = getCellUserEnteredValue(cellValue);
|
|
715
|
+
const text = getExtendedValueString(ue);
|
|
716
|
+
const lines = typeof text === "string" && text.includes("\n")
|
|
717
|
+
? text.split("\n").length
|
|
718
|
+
: 1;
|
|
719
|
+
const uf = getCellUserEnteredFormat(cellValue);
|
|
720
|
+
const wrap = uf
|
|
721
|
+
?.wrapStrategy === "wrap";
|
|
722
|
+
if (lines > bestLines ||
|
|
723
|
+
(lines === bestLines && wrap && !bestHasWrap)) {
|
|
724
|
+
bestLines = lines;
|
|
725
|
+
bestCell = cellValue;
|
|
726
|
+
bestColumnIndex = columnIndex;
|
|
727
|
+
bestHasWrap = wrap;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (!bestCell ||
|
|
731
|
+
bestColumnIndex === undefined ||
|
|
732
|
+
(bestLines === 1 && !bestHasWrap)) {
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
const ue = getCellUserEnteredValue(bestCell);
|
|
736
|
+
const overrideText = getExtendedValueString(ue) ?? "";
|
|
737
|
+
const uf = getCellUserEnteredFormat(bestCell);
|
|
738
|
+
const height = getFinalRowHeight(destinationSheetId, rowIndex, bestColumnIndex, {
|
|
739
|
+
textOverride: String(overrideText),
|
|
740
|
+
textFormatOverride: uf?.textFormat,
|
|
741
|
+
shouldWrapOverride: bestHasWrap,
|
|
742
|
+
});
|
|
743
|
+
if (typeof height === "number" && height > 0) {
|
|
744
|
+
if (!sheet.rowMetadata)
|
|
745
|
+
sheet.rowMetadata = [];
|
|
746
|
+
if (!sheet.rowMetadata[rowIndex]) {
|
|
747
|
+
sheet.rowMetadata[rowIndex] = {};
|
|
748
|
+
}
|
|
749
|
+
sheet.rowMetadata[rowIndex].size = height;
|
|
750
|
+
sheet.rowMetadata[rowIndex].resizedByUser = false;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
655
753
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
if (
|
|
659
|
-
|
|
754
|
+
// column widths
|
|
755
|
+
if (columnWidths) {
|
|
756
|
+
if (!sheet.columnMetadata) {
|
|
757
|
+
sheet.columnMetadata = [];
|
|
660
758
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
759
|
+
for (let index = 0; index < columnWidths.length; index++) {
|
|
760
|
+
const curWidth = columnWidths[index];
|
|
761
|
+
if (isNil(curWidth) || curWidth === 0) {
|
|
762
|
+
continue;
|
|
763
|
+
}
|
|
764
|
+
const columnIndex = to.range.startColumnIndex + index;
|
|
765
|
+
if (!sheet.columnMetadata?.[columnIndex]) {
|
|
766
|
+
sheet.columnMetadata[columnIndex] = {};
|
|
767
|
+
}
|
|
768
|
+
sheet.columnMetadata[columnIndex].size =
|
|
769
|
+
columnWidths[index];
|
|
664
770
|
}
|
|
665
|
-
sheet.columnMetadata[columnIndex].size =
|
|
666
|
-
columnWidths[index];
|
|
667
771
|
}
|
|
668
772
|
}
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
773
|
+
});
|
|
774
|
+
saveHistory({
|
|
775
|
+
sheets: { patches, inversePatches },
|
|
776
|
+
});
|
|
777
|
+
return nextState;
|
|
673
778
|
});
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
if (!isSelectionACell(nextSelections)) {
|
|
682
|
-
onChangeSelections?.(destinationSheetId, [to]);
|
|
683
|
-
}
|
|
684
|
-
// Update active cell
|
|
685
|
-
onChangeActiveCell(destinationSheetId, { ...getActiveCell() });
|
|
686
|
-
// Stream the paste to an engine consumer. The clipboard is a bounded payload (not
|
|
687
|
-
// windowed), so paste can resolve the destination cells UI-side; we read back the
|
|
688
|
-
// user-entered values the paste actually produced — relocated formulas, paste-special
|
|
689
|
-
// merges, shared-string text — and replay them as a `change-batch` the engine recomputes
|
|
690
|
-
// from. Reading the produced state (rather than re-deriving) keeps this correct across the
|
|
691
|
-
// cut / pure-paste / paste-special branches without duplicating their logic.
|
|
692
|
-
if (onCommand && pastedSheetData) {
|
|
693
|
-
const values = [];
|
|
694
|
-
for (let rowIndex = to.range.startRowIndex; rowIndex <= to.range.endRowIndex; rowIndex++) {
|
|
695
|
-
const row = [];
|
|
696
|
-
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++) {
|
|
697
|
-
const cell = pastedSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
|
|
698
|
-
const ue = cell ? getCellUserEnteredValue(cell) : undefined;
|
|
699
|
-
// Formula text wins (e.g. "=SUM(A1:A2)"), else the literal string / number / bool.
|
|
700
|
-
// `??` (not `||`) so 0 and false survive; `null` clears the cell.
|
|
701
|
-
row.push(getExtendedValueFormula(ue) ??
|
|
702
|
-
getExtendedValueString(ue) ??
|
|
703
|
-
getExtendedValueNumber(ue) ??
|
|
704
|
-
getExtendedValueBool(ue) ??
|
|
705
|
-
null);
|
|
706
|
-
}
|
|
707
|
-
values.push(row);
|
|
779
|
+
// For row expansions, add columns
|
|
780
|
+
onChangeTableColumn(destinationSheetId, activeCell, activeCellValue ?? undefined, adjacentTable, isRowExpansion, isColumnExpansion, to.range, pastedHeaderValues);
|
|
781
|
+
// Add calculated column
|
|
782
|
+
onChangeCalculatedColumn(destinationSheetId, activeCell, activeCellValue ?? undefined, currentTable);
|
|
783
|
+
// Update new selections
|
|
784
|
+
if (!isSelectionACell(nextSelections)) {
|
|
785
|
+
onChangeSelections?.(destinationSheetId, [to]);
|
|
708
786
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
//
|
|
716
|
-
|
|
787
|
+
// Update active cell
|
|
788
|
+
onChangeActiveCell(destinationSheetId, { ...getActiveCell() });
|
|
789
|
+
// Stream the paste to an engine consumer. The clipboard is a bounded payload (not
|
|
790
|
+
// windowed), so paste can resolve the destination cells UI-side; we read back the
|
|
791
|
+
// user-entered values the paste actually produced — relocated formulas, paste-special
|
|
792
|
+
// merges, shared-string text — and replay them as a `change-batch` the engine recomputes
|
|
793
|
+
// from. Reading the produced state (rather than re-deriving) keeps this correct across the
|
|
794
|
+
// cut / pure-paste / paste-special branches without duplicating their logic.
|
|
795
|
+
if (onCommand && pastedSheetData) {
|
|
796
|
+
const values = [];
|
|
797
|
+
for (let rowIndex = to.range.startRowIndex; rowIndex <= to.range.endRowIndex; rowIndex++) {
|
|
798
|
+
const row = [];
|
|
799
|
+
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++) {
|
|
800
|
+
const cell = pastedSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
|
|
801
|
+
const ue = cell ? getCellUserEnteredValue(cell) : undefined;
|
|
802
|
+
// Formula text wins (e.g. "=SUM(A1:A2)"), else the literal string / number / bool.
|
|
803
|
+
// `??` (not `||`) so 0 and false survive; `null` clears the cell.
|
|
804
|
+
row.push(getExtendedValueFormula(ue) ??
|
|
805
|
+
getExtendedValueString(ue) ??
|
|
806
|
+
getExtendedValueNumber(ue) ??
|
|
807
|
+
getExtendedValueBool(ue) ??
|
|
808
|
+
null);
|
|
809
|
+
}
|
|
810
|
+
values.push(row);
|
|
811
|
+
}
|
|
717
812
|
onCommand({
|
|
718
|
-
command: "
|
|
719
|
-
sheetId:
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
},
|
|
724
|
-
selections: [{ range: from.range }],
|
|
813
|
+
command: "change-batch",
|
|
814
|
+
sheetId: destinationSheetId,
|
|
815
|
+
ranges: to.range,
|
|
816
|
+
values,
|
|
817
|
+
...(autoExpandTables ? {} : { autoExpandTables }),
|
|
818
|
+
...(autoCalculatedColumns ? {} : { autoCalculatedColumns }),
|
|
725
819
|
});
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
saveHistory({
|
|
737
|
-
embeds: { patches, inversePatches },
|
|
738
|
-
selectedEmbedOrChart: { redo: firstEmbedId, undo: undefined },
|
|
739
|
-
});
|
|
740
|
-
return nextState;
|
|
741
|
-
});
|
|
742
|
-
// Selected first embed
|
|
743
|
-
focusEmbedOrChart(embeds[0].embedId);
|
|
744
|
-
}
|
|
745
|
-
// Tables
|
|
746
|
-
if (tables?.length) {
|
|
747
|
-
onChangeTables?.((prevTables) => {
|
|
748
|
-
const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
|
|
749
|
-
draft.push(...tables);
|
|
750
|
-
});
|
|
751
|
-
saveHistory({
|
|
752
|
-
tables: { patches, inversePatches },
|
|
753
|
-
});
|
|
754
|
-
return nextState;
|
|
755
|
-
});
|
|
756
|
-
}
|
|
757
|
-
// Handle citations
|
|
758
|
-
if (selectedRowValues.length && onChangeCitations) {
|
|
759
|
-
// Collect citationIds from pasted cells
|
|
760
|
-
const citationIdMap = new Map();
|
|
761
|
-
for (let dataRowIndex = 0; dataRowIndex < rowSpan; dataRowIndex++) {
|
|
762
|
-
const rowData = selectedRowValues[dataRowIndex];
|
|
763
|
-
if (!rowData)
|
|
764
|
-
continue;
|
|
765
|
-
for (let dataColumnIndex = 0; dataColumnIndex < colSpan; dataColumnIndex++) {
|
|
766
|
-
const cellValue = rowData[dataColumnIndex];
|
|
767
|
-
if (cellValue &&
|
|
768
|
-
typeof cellValue === "object" &&
|
|
769
|
-
"citationId" in cellValue &&
|
|
770
|
-
cellValue.citationId) {
|
|
771
|
-
citationIdMap.set(cellValue.citationId, {
|
|
772
|
-
sourceRowIndex: dataRowIndex,
|
|
773
|
-
sourceColumnIndex: dataColumnIndex,
|
|
820
|
+
// On cut, the source cells were cleared — mirror that so the engine drops them too.
|
|
821
|
+
if (isCutOperation && from && !isNil(sourceSheetId)) {
|
|
822
|
+
onCommand({
|
|
823
|
+
command: "delete-cells",
|
|
824
|
+
sheetId: sourceSheetId,
|
|
825
|
+
activeCell: {
|
|
826
|
+
rowIndex: from.range.startRowIndex,
|
|
827
|
+
columnIndex: from.range.startColumnIndex,
|
|
828
|
+
},
|
|
829
|
+
selections: [{ range: from.range }],
|
|
774
830
|
});
|
|
775
831
|
}
|
|
776
832
|
}
|
|
777
833
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
834
|
+
// Defined names wholly inside the cut block follow it (Excel move semantics); a name the
|
|
835
|
+
// block covers only partially keeps referring to its original area.
|
|
836
|
+
if (isCutOperation && from && !isNil(sourceSheetId)) {
|
|
837
|
+
onChangeNamedRanges?.((prevNamedRanges) => {
|
|
838
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevNamedRanges, (draft) => {
|
|
839
|
+
for (const namedRange of draft) {
|
|
840
|
+
if (namedRange.range?.sheetId === sourceSheetId &&
|
|
841
|
+
areaInsideArea(namedRange.range, from.range)) {
|
|
842
|
+
namedRange.range = {
|
|
843
|
+
...moveRange(namedRange.range, from.range, to.range),
|
|
844
|
+
sheetId: destinationSheetId,
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
if (!patches.length) {
|
|
850
|
+
return prevNamedRanges;
|
|
851
|
+
}
|
|
852
|
+
saveHistory({ namedRanges: { patches, inversePatches } });
|
|
853
|
+
return nextState;
|
|
854
|
+
});
|
|
855
|
+
onChangeCharts?.((prevCharts) => {
|
|
856
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevCharts, (draft) => {
|
|
857
|
+
moveChartsOnRangeMove(draft, sourceSheetId, from.range, destinationSheetId, to.range);
|
|
858
|
+
});
|
|
859
|
+
if (!patches.length) {
|
|
860
|
+
return prevCharts;
|
|
861
|
+
}
|
|
862
|
+
saveHistory({ charts: { patches, inversePatches } });
|
|
863
|
+
return nextState;
|
|
864
|
+
});
|
|
865
|
+
// The tables the cut block covers whole move with their cells (same history step): the
|
|
866
|
+
// range lands at the destination — on another sheet too — and the column-indexed filter
|
|
867
|
+
// and sort specs follow it, so the table's filters and its structured references keep
|
|
868
|
+
// resolving there.
|
|
869
|
+
if (movedTables.length) {
|
|
870
|
+
const columnDelta = to.range.startColumnIndex - from.range.startColumnIndex;
|
|
871
|
+
onChangeTables?.((prevTables) => {
|
|
872
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
|
|
873
|
+
for (const table of draft) {
|
|
874
|
+
if (!movedTables.some((moved) => moved.id === table.id)) {
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
877
|
+
table.sheetId = destinationSheetId;
|
|
878
|
+
const range = moveRange(table.range, from.range, to.range);
|
|
879
|
+
table.range =
|
|
880
|
+
"sheetId" in range
|
|
881
|
+
? { ...range, sheetId: destinationSheetId }
|
|
882
|
+
: range;
|
|
883
|
+
for (const spec of table.filterSpecs ?? []) {
|
|
884
|
+
spec.columnIndex += columnDelta;
|
|
885
|
+
}
|
|
886
|
+
for (const spec of table.sortSpecs ?? []) {
|
|
887
|
+
spec.dimensionIndex += columnDelta;
|
|
792
888
|
}
|
|
793
889
|
}
|
|
794
890
|
});
|
|
795
|
-
saveHistory({
|
|
796
|
-
citations: { patches, inversePatches },
|
|
797
|
-
});
|
|
891
|
+
saveHistory({ tables: { patches, inversePatches } });
|
|
798
892
|
return nextState;
|
|
799
893
|
});
|
|
800
894
|
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
895
|
+
}
|
|
896
|
+
// Embeds
|
|
897
|
+
if (embeds?.length) {
|
|
898
|
+
const firstEmbedId = embeds[0].embedId;
|
|
899
|
+
onChangeEmbeds?.((prevEmbeds) => {
|
|
900
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevEmbeds, (draft) => {
|
|
901
|
+
draft.push(...embeds);
|
|
902
|
+
});
|
|
903
|
+
saveHistory({
|
|
904
|
+
embeds: { patches, inversePatches },
|
|
905
|
+
selectedEmbedOrChart: { redo: firstEmbedId, undo: undefined },
|
|
906
|
+
});
|
|
907
|
+
return nextState;
|
|
908
|
+
});
|
|
909
|
+
// Selected first embed
|
|
910
|
+
focusEmbedOrChart(embeds[0].embedId);
|
|
911
|
+
}
|
|
912
|
+
// Tables
|
|
913
|
+
if (tables?.length) {
|
|
914
|
+
onChangeTables?.((prevTables) => {
|
|
915
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevTables, (draft) => {
|
|
916
|
+
// Excel names a pasted table like a new one — the next free `TableN` — never
|
|
917
|
+
// `Copy of <title>`, which is not a valid table name (it has a space).
|
|
918
|
+
for (const table of tables) {
|
|
919
|
+
draft.push({
|
|
920
|
+
...table,
|
|
921
|
+
title: getNextTableTitle(draft, generatedNames),
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
saveHistory({
|
|
926
|
+
tables: { patches, inversePatches },
|
|
927
|
+
});
|
|
928
|
+
return nextState;
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
// Handle citations
|
|
932
|
+
if (selectedRowValues.length && onChangeCitations) {
|
|
933
|
+
// Collect citationIds from pasted cells
|
|
934
|
+
const citationIdMap = new Map();
|
|
935
|
+
for (let dataRowIndex = 0; dataRowIndex < rowSpan; dataRowIndex++) {
|
|
936
|
+
const rowData = selectedRowValues[dataRowIndex];
|
|
937
|
+
if (!rowData)
|
|
938
|
+
continue;
|
|
939
|
+
for (let dataColumnIndex = 0; dataColumnIndex < colSpan; dataColumnIndex++) {
|
|
940
|
+
const cellValue = rowData[dataColumnIndex];
|
|
941
|
+
if (cellValue &&
|
|
942
|
+
typeof cellValue === "object" &&
|
|
943
|
+
"citationId" in cellValue &&
|
|
944
|
+
cellValue.citationId) {
|
|
945
|
+
citationIdMap.set(cellValue.citationId, {
|
|
946
|
+
sourceRowIndex: dataRowIndex,
|
|
947
|
+
sourceColumnIndex: dataColumnIndex,
|
|
948
|
+
});
|
|
823
949
|
}
|
|
824
950
|
}
|
|
825
|
-
|
|
826
|
-
|
|
951
|
+
}
|
|
952
|
+
if (citationIdMap.size > 0) {
|
|
953
|
+
if (isCutOperation && from && !isNil(sourceSheetId)) {
|
|
954
|
+
// For cut operation: Move citations to new position
|
|
827
955
|
onChangeCitations((prevCitations) => {
|
|
828
956
|
const [nextState, patches, inversePatches] = produceWithPatches(prevCitations, (draft) => {
|
|
829
|
-
|
|
957
|
+
for (const citationId of citationIdMap.keys()) {
|
|
958
|
+
const citation = draft.find((c) => c.id === citationId);
|
|
959
|
+
if (citation) {
|
|
960
|
+
// Update citation range to new position
|
|
961
|
+
citation.range.sheetId = destinationSheetId;
|
|
962
|
+
citation.range.startRowIndex += rowDelta;
|
|
963
|
+
citation.range.endRowIndex += rowDelta;
|
|
964
|
+
citation.range.startColumnIndex += columnDelta;
|
|
965
|
+
citation.range.endColumnIndex += columnDelta;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
830
968
|
});
|
|
831
969
|
saveHistory({
|
|
832
970
|
citations: { patches, inversePatches },
|
|
833
971
|
});
|
|
834
972
|
return nextState;
|
|
835
973
|
});
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
974
|
+
}
|
|
975
|
+
else if (!isCutOperation) {
|
|
976
|
+
// For paste (copy) operation: Create new citations with new IDs
|
|
977
|
+
const newCitations = [];
|
|
978
|
+
const citationIdRemap = new Map();
|
|
979
|
+
for (const [oldCitationId, { sourceRowIndex, sourceColumnIndex },] of citationIdMap.entries()) {
|
|
980
|
+
const originalCitation = citations?.find((c) => c.id === oldCitationId);
|
|
981
|
+
if (originalCitation) {
|
|
982
|
+
const newId = uuidString();
|
|
983
|
+
citationIdRemap.set(oldCitationId, newId);
|
|
984
|
+
// Calculate the new range based on paste destination
|
|
985
|
+
const newCitation = {
|
|
986
|
+
...originalCitation,
|
|
987
|
+
id: newId,
|
|
988
|
+
range: {
|
|
989
|
+
sheetId: destinationSheetId,
|
|
990
|
+
startRowIndex: to.range.startRowIndex + sourceRowIndex,
|
|
991
|
+
endRowIndex: to.range.startRowIndex + sourceRowIndex,
|
|
992
|
+
startColumnIndex: to.range.startColumnIndex + sourceColumnIndex,
|
|
993
|
+
endColumnIndex: to.range.startColumnIndex + sourceColumnIndex,
|
|
994
|
+
},
|
|
995
|
+
};
|
|
996
|
+
newCitations.push(newCitation);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (newCitations.length > 0) {
|
|
1000
|
+
// Add new citations
|
|
1001
|
+
onChangeCitations((prevCitations) => {
|
|
1002
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevCitations, (draft) => {
|
|
1003
|
+
draft.push(...newCitations);
|
|
1004
|
+
});
|
|
1005
|
+
saveHistory({
|
|
1006
|
+
citations: { patches, inversePatches },
|
|
1007
|
+
});
|
|
1008
|
+
return nextState;
|
|
1009
|
+
});
|
|
1010
|
+
// Update cell citationIds to point to new citations
|
|
1011
|
+
onChangeSheetData?.((prevSheetData) => {
|
|
1012
|
+
const [nextState, patches, inversePatches] = produceWithPatches(prevSheetData, (draft) => {
|
|
1013
|
+
for (const { rowIndex } of destinationRows) {
|
|
1014
|
+
for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++) {
|
|
1015
|
+
const cellData = draft[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
|
|
1016
|
+
if (cellData?.citationId) {
|
|
1017
|
+
const newCitationId = citationIdRemap.get(cellData.citationId);
|
|
1018
|
+
if (newCitationId) {
|
|
1019
|
+
cellData.citationId = newCitationId;
|
|
1020
|
+
}
|
|
846
1021
|
}
|
|
847
1022
|
}
|
|
848
1023
|
}
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
1024
|
+
});
|
|
1025
|
+
saveHistory({
|
|
1026
|
+
sheetData: { patches, inversePatches },
|
|
1027
|
+
});
|
|
1028
|
+
return nextState;
|
|
853
1029
|
});
|
|
854
|
-
|
|
855
|
-
});
|
|
1030
|
+
}
|
|
856
1031
|
}
|
|
857
1032
|
}
|
|
858
1033
|
}
|
|
859
|
-
}
|
|
1034
|
+
});
|
|
860
1035
|
}, [
|
|
861
1036
|
rowCount,
|
|
862
1037
|
columnCount,
|
|
@@ -873,6 +1048,9 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
|
|
|
873
1048
|
onRequestFonts,
|
|
874
1049
|
idCreationStrategy,
|
|
875
1050
|
createHistory,
|
|
1051
|
+
batchHistory,
|
|
1052
|
+
autoExpandTables,
|
|
1053
|
+
autoCalculatedColumns,
|
|
876
1054
|
enqueueStructureChange,
|
|
877
1055
|
enqueueGraphOperation,
|
|
878
1056
|
onChangeCalculatedColumn,
|
|
@@ -899,5 +1077,9 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
|
|
|
899
1077
|
getFinalRowHeight,
|
|
900
1078
|
onCommand,
|
|
901
1079
|
generatedNames,
|
|
1080
|
+
onChangeNamedRanges,
|
|
1081
|
+
onChangeCharts,
|
|
1082
|
+
getSheetMerges,
|
|
1083
|
+
showError,
|
|
902
1084
|
]);
|
|
903
1085
|
};
|