@dxos/plugin-sheet 0.6.11 → 0.6.12-main.5a87ad5
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/lib/browser/SheetContainer-VISF3VUB.mjs +261 -0
- package/dist/lib/browser/SheetContainer-VISF3VUB.mjs.map +7 -0
- package/dist/lib/browser/{chunk-JRL5LGCE.mjs → chunk-QILRZNE5.mjs} +2 -5
- package/dist/lib/browser/chunk-QILRZNE5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FUAGSXA4.mjs → chunk-WZMOZKQZ.mjs} +9 -16
- package/dist/lib/browser/chunk-WZMOZKQZ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-D5AGLXJP.mjs → chunk-Z2XOOC2R.mjs} +385 -678
- package/dist/lib/browser/chunk-Z2XOOC2R.mjs.map +7 -0
- package/dist/lib/browser/{SheetContainer-U4H5D34A.mjs → chunk-ZLJ2GRE2.mjs} +1151 -240
- package/dist/lib/browser/chunk-ZLJ2GRE2.mjs.map +7 -0
- package/dist/lib/browser/graph-4XFKIHRL.mjs +21 -0
- package/dist/lib/browser/graph-4XFKIHRL.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +74 -60
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types.mjs +4 -6
- package/dist/lib/node/SheetContainer-2MEALQWW.cjs +279 -0
- package/dist/lib/node/SheetContainer-2MEALQWW.cjs.map +7 -0
- package/dist/lib/node/{SheetContainer-AXQV3ZT5.cjs → chunk-6DQABRGJ.cjs} +1182 -279
- package/dist/lib/node/chunk-6DQABRGJ.cjs.map +7 -0
- package/dist/lib/node/{chunk-DSYKOI4E.cjs → chunk-AOP42UAA.cjs} +13 -21
- package/dist/lib/node/chunk-AOP42UAA.cjs.map +7 -0
- package/dist/lib/node/{chunk-BJ6ZD7MN.cjs → chunk-BNARJ5GM.cjs} +5 -18
- package/dist/lib/node/chunk-BNARJ5GM.cjs.map +7 -0
- package/dist/lib/node/{chunk-5KKJ4NPP.cjs → chunk-P5QYYEHQ.cjs} +388 -676
- package/dist/lib/node/chunk-P5QYYEHQ.cjs.map +7 -0
- package/dist/lib/node/graph-2LRDUXBZ.cjs +43 -0
- package/dist/lib/node/graph-2LRDUXBZ.cjs.map +7 -0
- package/dist/lib/node/index.cjs +86 -66
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.cjs +3 -3
- package/dist/lib/node/meta.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +10 -12
- package/dist/lib/node/types.cjs.map +2 -2
- package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs +262 -0
- package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-4MM7THJW.mjs +2944 -0
- package/dist/lib/node-esm/chunk-4MM7THJW.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-5RLTCIE2.mjs +2684 -0
- package/dist/lib/node-esm/chunk-5RLTCIE2.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-IU2L277A.mjs +17 -0
- package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-RR2AO4SM.mjs +76 -0
- package/dist/lib/node-esm/chunk-RR2AO4SM.mjs.map +7 -0
- package/dist/lib/node-esm/graph-WG5EKOMO.mjs +22 -0
- package/dist/lib/node-esm/graph-WG5EKOMO.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +263 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/meta.mjs +10 -0
- package/dist/lib/node-esm/meta.mjs.map +7 -0
- package/dist/lib/node-esm/types.mjs +21 -0
- package/dist/lib/node-esm/types.mjs.map +7 -0
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/components/CellEditor/CellEditor.d.ts +23 -3
- package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +1 -1
- package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts +2 -2
- package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/CellEditor/extension.d.ts +1 -1
- package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -1
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +11 -0
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/index.d.ts +1 -3
- package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.d.ts +10 -0
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +9 -0
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/util.d.ts +7 -0
- package/dist/types/src/components/GridSheet/util.d.ts.map +1 -0
- package/dist/types/src/components/Sheet/Sheet.d.ts +1 -1
- package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/Sheet.stories.d.ts +5 -6
- package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/decorations.d.ts +24 -0
- package/dist/types/src/components/Sheet/decorations.d.ts.map +1 -0
- package/dist/types/src/components/Sheet/grid.d.ts +2 -2
- package/dist/types/src/components/Sheet/grid.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/nav.d.ts +3 -3
- package/dist/types/src/components/Sheet/nav.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/sheet-context.d.ts +8 -7
- package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/threads.d.ts +2 -0
- package/dist/types/src/components/Sheet/threads.d.ts.map +1 -0
- package/dist/types/src/components/SheetContainer.d.ts +2 -3
- package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +19 -3
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +18 -13
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/defs/index.d.ts +3 -0
- package/dist/types/src/defs/index.d.ts.map +1 -0
- package/dist/types/src/{model → defs}/types.d.ts +8 -3
- package/dist/types/src/defs/types.d.ts.map +1 -0
- package/dist/types/src/defs/types.test.d.ts.map +1 -0
- package/dist/types/src/defs/util.d.ts +43 -0
- package/dist/types/src/defs/util.d.ts.map +1 -0
- package/dist/types/src/extensions/compute.d.ts +9 -0
- package/dist/types/src/extensions/compute.d.ts.map +1 -0
- package/dist/types/src/extensions/compute.stories.d.ts +26 -0
- package/dist/types/src/extensions/compute.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +2 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/{components/ComputeGraph → graph}/async-function.d.ts +8 -2
- package/dist/types/src/graph/async-function.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.d.ts +84 -0
- package/dist/types/src/graph/compute-graph.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.stories.d.ts +10 -0
- package/dist/types/src/graph/compute-graph.stories.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.test.d.ts +2 -0
- package/dist/types/src/graph/compute-graph.test.d.ts.map +1 -0
- package/dist/types/src/graph/compute-node.d.ts +26 -0
- package/dist/types/src/graph/compute-node.d.ts.map +1 -0
- package/dist/types/src/graph/edge-function.d.ts.map +1 -0
- package/dist/types/src/{model/functions.d.ts → graph/function-defs.d.ts} +1 -1
- package/dist/types/src/graph/function-defs.d.ts.map +1 -0
- package/dist/types/src/graph/hyperformula.test.d.ts +2 -0
- package/dist/types/src/graph/hyperformula.test.d.ts.map +1 -0
- package/dist/types/src/graph/index.d.ts +4 -0
- package/dist/types/src/graph/index.d.ts.map +1 -0
- package/dist/types/src/{components/ComputeGraph/custom.d.ts → graph/testing/custom-function.d.ts} +4 -2
- package/dist/types/src/graph/testing/custom-function.d.ts.map +1 -0
- package/dist/types/src/graph/testing/index.d.ts +2 -0
- package/dist/types/src/graph/testing/index.d.ts.map +1 -0
- package/dist/types/src/graph/util.d.ts +2 -0
- package/dist/types/src/graph/util.d.ts.map +1 -0
- package/dist/types/src/hooks/hooks.stories.d.ts +11 -0
- package/dist/types/src/hooks/hooks.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useComputeGraph.d.ts +7 -0
- package/dist/types/src/hooks/useComputeGraph.d.ts.map +1 -0
- package/dist/types/src/hooks/useFormattingModel.d.ts +3 -0
- package/dist/types/src/hooks/useFormattingModel.d.ts.map +1 -0
- package/dist/types/src/hooks/useSheetModel.d.ts +8 -0
- package/dist/types/src/hooks/useSheetModel.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +1 -4
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/model/formatting-model.d.ts +16 -0
- package/dist/types/src/model/formatting-model.d.ts.map +1 -0
- package/dist/types/src/model/index.d.ts +2 -3
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/{model.d.ts → sheet-model.d.ts} +10 -65
- package/dist/types/src/model/sheet-model.d.ts.map +1 -0
- package/dist/types/src/sanity.test.d.ts +2 -0
- package/dist/types/src/sanity.test.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/testing.d.ts +8 -0
- package/dist/types/src/testing/testing.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +17 -12
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +86 -5
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/vendor/hyperformula.mjs +37145 -0
- package/package.json +48 -41
- package/src/SheetPlugin.tsx +48 -73
- package/src/components/CellEditor/CellEditor.stories.tsx +5 -4
- package/src/components/CellEditor/CellEditor.tsx +59 -9
- package/src/components/CellEditor/extension.test.ts +4 -5
- package/src/components/CellEditor/extension.ts +1 -3
- package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +20 -0
- package/src/components/ComputeGraph/index.ts +1 -3
- package/src/components/GridSheet/GridSheet.stories.tsx +36 -0
- package/src/components/GridSheet/GridSheet.tsx +153 -0
- package/src/components/GridSheet/util.ts +108 -0
- package/src/components/Sheet/Sheet.stories.tsx +52 -88
- package/src/components/Sheet/Sheet.tsx +57 -18
- package/src/components/Sheet/decorations.ts +62 -0
- package/src/components/Sheet/grid.ts +3 -3
- package/src/components/Sheet/nav.ts +19 -19
- package/src/components/Sheet/sheet-context.tsx +18 -80
- package/src/components/Sheet/threads.tsx +205 -0
- package/src/components/SheetContainer.tsx +73 -19
- package/src/components/Toolbar/Toolbar.tsx +53 -12
- package/src/components/index.ts +1 -0
- package/src/defs/index.ts +6 -0
- package/src/{model → defs}/types.test.ts +8 -9
- package/src/{model → defs}/types.ts +24 -14
- package/src/defs/util.ts +151 -0
- package/src/extensions/compute.stories.tsx +153 -0
- package/src/extensions/compute.ts +131 -0
- package/src/extensions/index.ts +5 -0
- package/src/{components/ComputeGraph → graph}/async-function.ts +15 -6
- package/src/graph/compute-graph.stories.tsx +93 -0
- package/src/graph/compute-graph.test.ts +127 -0
- package/src/graph/compute-graph.ts +313 -0
- package/src/graph/compute-node.ts +62 -0
- package/src/{components/ComputeGraph → graph}/edge-function.ts +3 -3
- package/src/graph/hyperformula.test.ts +15 -0
- package/src/graph/index.ts +7 -0
- package/src/{components/ComputeGraph/custom.ts → graph/testing/custom-function.ts} +11 -7
- package/src/graph/testing/index.ts +5 -0
- package/src/graph/util.ts +8 -0
- package/src/hooks/hooks.stories.tsx +50 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useComputeGraph.ts +21 -0
- package/src/hooks/useFormattingModel.ts +11 -0
- package/src/hooks/useSheetModel.ts +40 -0
- package/src/meta.tsx +1 -5
- package/src/{components/Sheet/formatting.ts → model/formatting-model.ts} +20 -13
- package/src/model/index.ts +2 -3
- package/src/model/sheet-model.ts +414 -0
- package/src/sanity.test.ts +40 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/testing.tsx +68 -0
- package/src/translations.ts +6 -1
- package/src/types.ts +31 -6
- package/dist/lib/browser/SheetContainer-U4H5D34A.mjs.map +0 -7
- package/dist/lib/browser/chunk-APHOLYUB.mjs +0 -175
- package/dist/lib/browser/chunk-APHOLYUB.mjs.map +0 -7
- package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +0 -7
- package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +0 -7
- package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +0 -7
- package/dist/lib/browser/chunk-NU4PBN33.mjs +0 -8
- package/dist/lib/browser/chunk-NU4PBN33.mjs.map +0 -7
- package/dist/lib/browser/testing.mjs +0 -92
- package/dist/lib/browser/testing.mjs.map +0 -7
- package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +0 -7
- package/dist/lib/node/chunk-5KKJ4NPP.cjs.map +0 -7
- package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +0 -7
- package/dist/lib/node/chunk-CN3RPESU.cjs +0 -202
- package/dist/lib/node/chunk-CN3RPESU.cjs.map +0 -7
- package/dist/lib/node/chunk-DSYKOI4E.cjs.map +0 -7
- package/dist/lib/node/chunk-PYXHNAAK.cjs +0 -40
- package/dist/lib/node/chunk-PYXHNAAK.cjs.map +0 -7
- package/dist/lib/node/testing.cjs +0 -111
- package/dist/lib/node/testing.cjs.map +0 -7
- package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/custom.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/graph-context.d.ts +0 -12
- package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +0 -2
- package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/graph.d.ts +0 -26
- package/dist/types/src/components/ComputeGraph/graph.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/formatting.d.ts +0 -14
- package/dist/types/src/components/Sheet/formatting.d.ts.map +0 -1
- package/dist/types/src/model/functions.d.ts.map +0 -1
- package/dist/types/src/model/model.browser.test.d.ts +0 -2
- package/dist/types/src/model/model.browser.test.d.ts.map +0 -1
- package/dist/types/src/model/model.d.ts.map +0 -1
- package/dist/types/src/model/types.d.ts.map +0 -1
- package/dist/types/src/model/types.test.d.ts.map +0 -1
- package/dist/types/src/model/util.d.ts +0 -15
- package/dist/types/src/model/util.d.ts.map +0 -1
- package/dist/types/src/testing.d.ts +0 -9
- package/dist/types/src/testing.d.ts.map +0 -1
- package/src/components/ComputeGraph/graph-context.tsx +0 -50
- package/src/components/ComputeGraph/graph.browser.test.ts +0 -50
- package/src/components/ComputeGraph/graph.ts +0 -62
- package/src/model/model.browser.test.ts +0 -100
- package/src/model/model.ts +0 -550
- package/src/model/util.ts +0 -36
- package/src/testing.ts +0 -50
- /package/dist/types/src/{model → defs}/types.test.d.ts +0 -0
- /package/dist/types/src/{components/ComputeGraph → graph}/edge-function.d.ts +0 -0
- /package/src/{model/functions.ts → graph/function-defs.ts} +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback, useMemo, useRef } from 'react';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
type DxGridElement,
|
|
9
|
+
Grid,
|
|
10
|
+
type GridContentProps,
|
|
11
|
+
type GridScopedProps,
|
|
12
|
+
useGridContext,
|
|
13
|
+
} from '@dxos/react-ui-grid';
|
|
14
|
+
|
|
15
|
+
import { dxGridCellIndexToSheetCellAddress, useSheetModelDxGridProps } from './util';
|
|
16
|
+
import { rangeToA1Notation, type CellRange } from '../../defs';
|
|
17
|
+
import { type ComputeGraph } from '../../graph';
|
|
18
|
+
import { useFormattingModel, useSheetModel, type UseSheetModelOptions } from '../../hooks';
|
|
19
|
+
import { type SheetModel, type FormattingModel } from '../../model';
|
|
20
|
+
import { type SheetType } from '../../types';
|
|
21
|
+
import {
|
|
22
|
+
CellEditor,
|
|
23
|
+
type CellEditorProps,
|
|
24
|
+
type CellRangeNotifier,
|
|
25
|
+
editorKeys,
|
|
26
|
+
type EditorKeysProps,
|
|
27
|
+
rangeExtension,
|
|
28
|
+
sheetExtension,
|
|
29
|
+
} from '../CellEditor';
|
|
30
|
+
|
|
31
|
+
const GridSheetCellEditor = ({
|
|
32
|
+
model,
|
|
33
|
+
extension,
|
|
34
|
+
__gridScope,
|
|
35
|
+
}: GridScopedProps<Pick<CellEditorProps, 'extension'> & { model: SheetModel }>) => {
|
|
36
|
+
const { id, editing, setEditing, editBox } = useGridContext('GridSheetCellEditor', __gridScope);
|
|
37
|
+
const cell = dxGridCellIndexToSheetCellAddress(editing);
|
|
38
|
+
|
|
39
|
+
return editing ? (
|
|
40
|
+
<CellEditor
|
|
41
|
+
variant='grid'
|
|
42
|
+
value={editing.initialContent ?? (cell ? model.getCellText(cell) : undefined)}
|
|
43
|
+
autoFocus
|
|
44
|
+
box={editBox}
|
|
45
|
+
onBlur={() => setEditing(null)}
|
|
46
|
+
extension={extension}
|
|
47
|
+
gridId={id}
|
|
48
|
+
/>
|
|
49
|
+
) : null;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const sheetRowDefault = { size: 32, resizeable: true };
|
|
53
|
+
const sheetColDefault = { size: 180, resizeable: true };
|
|
54
|
+
|
|
55
|
+
const GridSheetImpl = ({
|
|
56
|
+
model,
|
|
57
|
+
formatting,
|
|
58
|
+
__gridScope,
|
|
59
|
+
}: GridScopedProps<{ model: SheetModel; formatting: FormattingModel }>) => {
|
|
60
|
+
const { editing, setEditing } = useGridContext('GridSheetCellEditor', __gridScope);
|
|
61
|
+
const dxGrid = useRef<DxGridElement | null>(null);
|
|
62
|
+
const rangeNotifier = useRef<CellRangeNotifier>();
|
|
63
|
+
|
|
64
|
+
// TODO(burdon): Validate formula before closing: hf.validateFormula();
|
|
65
|
+
const handleClose = useCallback<NonNullable<EditorKeysProps['onClose']> | NonNullable<EditorKeysProps['onNav']>>(
|
|
66
|
+
(value, { key, shift }) => {
|
|
67
|
+
if (value !== undefined) {
|
|
68
|
+
model.setValue(dxGridCellIndexToSheetCellAddress(editing)!, value);
|
|
69
|
+
}
|
|
70
|
+
setEditing(null);
|
|
71
|
+
const axis = ['Enter', 'ArrowUp', 'ArrowDown'].includes(key)
|
|
72
|
+
? 'row'
|
|
73
|
+
: ['Tab', 'ArrowLeft', 'ArrowRight'].includes(key)
|
|
74
|
+
? 'col'
|
|
75
|
+
: undefined;
|
|
76
|
+
const delta = key.startsWith('Arrow') ? (['ArrowUp', 'ArrowLeft'].includes(key) ? -1 : 1) : shift ? -1 : 1;
|
|
77
|
+
dxGrid.current?.refocus(axis, delta);
|
|
78
|
+
},
|
|
79
|
+
[model, editing, setEditing],
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const handleAxisResize = useCallback<NonNullable<GridContentProps['onAxisResize']>>(
|
|
83
|
+
({ axis, size, index: numericIndex }) => {
|
|
84
|
+
if (axis === 'row') {
|
|
85
|
+
const rowId = model.sheet.rows[parseInt(numericIndex)];
|
|
86
|
+
model.sheet.rowMeta[rowId] ??= {};
|
|
87
|
+
model.sheet.rowMeta[rowId].size = size;
|
|
88
|
+
} else {
|
|
89
|
+
const columnId = model.sheet.columns[parseInt(numericIndex)];
|
|
90
|
+
model.sheet.columnMeta[columnId] ??= {};
|
|
91
|
+
model.sheet.columnMeta[columnId].size = size;
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
[model],
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const handleSelect = useCallback<NonNullable<GridContentProps['onSelect']>>(
|
|
98
|
+
({ minCol, maxCol, minRow, maxRow }) => {
|
|
99
|
+
if (editing) {
|
|
100
|
+
const range: CellRange = { from: { col: minCol, row: minRow } };
|
|
101
|
+
if (minCol !== maxCol || minRow !== maxRow) {
|
|
102
|
+
range.to = { col: maxCol, row: maxRow };
|
|
103
|
+
}
|
|
104
|
+
// Update range selection in formula.
|
|
105
|
+
rangeNotifier.current?.(rangeToA1Notation(range));
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
[editing],
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const { columns, rows } = useSheetModelDxGridProps(dxGrid, model, formatting);
|
|
112
|
+
|
|
113
|
+
const extension = useMemo(
|
|
114
|
+
() => [
|
|
115
|
+
editorKeys({ onClose: handleClose, ...(editing?.initialContent && { onNav: handleClose }) }),
|
|
116
|
+
sheetExtension({ functions: model.graph.getFunctions() }),
|
|
117
|
+
rangeExtension((fn) => (rangeNotifier.current = fn)),
|
|
118
|
+
],
|
|
119
|
+
[model, handleClose, editing],
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<>
|
|
124
|
+
<GridSheetCellEditor model={model} extension={extension} />
|
|
125
|
+
<Grid.Content
|
|
126
|
+
initialCells={{}}
|
|
127
|
+
columns={columns}
|
|
128
|
+
rows={rows}
|
|
129
|
+
onAxisResize={handleAxisResize}
|
|
130
|
+
onSelect={handleSelect}
|
|
131
|
+
rowDefault={sheetRowDefault}
|
|
132
|
+
columnDefault={sheetColDefault}
|
|
133
|
+
ref={dxGrid}
|
|
134
|
+
/>
|
|
135
|
+
</>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export type GridSheetProps = { graph?: ComputeGraph; sheet?: SheetType } & UseSheetModelOptions;
|
|
140
|
+
|
|
141
|
+
export const GridSheet = ({ graph, sheet, ...options }: GridSheetProps) => {
|
|
142
|
+
const model = useSheetModel(graph, sheet, options);
|
|
143
|
+
const formatting = useFormattingModel(model);
|
|
144
|
+
if (!model || !formatting) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<Grid.Root id={model.id}>
|
|
150
|
+
<GridSheetImpl model={model} formatting={formatting} />
|
|
151
|
+
</Grid.Root>
|
|
152
|
+
);
|
|
153
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type MutableRefObject, useEffect, useLayoutEffect, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { createDocAccessor } from '@dxos/react-client/echo';
|
|
8
|
+
import {
|
|
9
|
+
type GridEditing,
|
|
10
|
+
type GridContentProps,
|
|
11
|
+
type DxGridElement,
|
|
12
|
+
type DxGridCells,
|
|
13
|
+
type DxGridAxisMeta,
|
|
14
|
+
type DxGridRange,
|
|
15
|
+
} from '@dxos/react-ui-grid';
|
|
16
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
17
|
+
|
|
18
|
+
import { type CellAddress } from '../../defs';
|
|
19
|
+
import { type SheetModel, type FormattingModel } from '../../model';
|
|
20
|
+
|
|
21
|
+
export const dxGridCellIndexToSheetCellAddress = (gridEditing: GridEditing): CellAddress | null => {
|
|
22
|
+
if (!gridEditing) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const [colStr, rowStr] = gridEditing.index.split(',');
|
|
26
|
+
return {
|
|
27
|
+
col: parseInt(colStr),
|
|
28
|
+
row: parseInt(rowStr),
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const createDxGridColumns = (model: SheetModel): DxGridAxisMeta => {
|
|
33
|
+
return model.sheet.columns.reduce((acc: DxGridAxisMeta, columnId, numericIndex) => {
|
|
34
|
+
if (model.sheet.columnMeta[columnId] && model.sheet.columnMeta[columnId].size) {
|
|
35
|
+
acc[numericIndex] = { size: model.sheet.columnMeta[columnId].size, resizeable: true };
|
|
36
|
+
}
|
|
37
|
+
return acc;
|
|
38
|
+
}, {});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const createDxGridRows = (model: SheetModel): DxGridAxisMeta => {
|
|
42
|
+
return model.sheet.rows.reduce((acc: DxGridAxisMeta, rowId, numericIndex) => {
|
|
43
|
+
if (model.sheet.rowMeta[rowId] && model.sheet.rowMeta[rowId].size) {
|
|
44
|
+
acc[numericIndex] = { size: model.sheet.rowMeta[rowId].size, resizeable: true };
|
|
45
|
+
}
|
|
46
|
+
return acc;
|
|
47
|
+
}, {});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const cellGetter = (model: SheetModel, formatting: FormattingModel) => {
|
|
51
|
+
// TODO(thure): Actually use the cache.
|
|
52
|
+
let _cachedBounds: DxGridRange | null = null;
|
|
53
|
+
const cachedCells: DxGridCells = {};
|
|
54
|
+
return (nextBounds: DxGridRange): DxGridCells => {
|
|
55
|
+
[...Array(nextBounds.end.col - nextBounds.start.col)].forEach((_, c0) => {
|
|
56
|
+
return [...Array(nextBounds.end.row - nextBounds.start.row)].forEach((_, r0) => {
|
|
57
|
+
const col = nextBounds.start.col + c0;
|
|
58
|
+
const row = nextBounds.start.row + r0;
|
|
59
|
+
const cell = formatting.getFormatting({ col, row });
|
|
60
|
+
if (cell.value) {
|
|
61
|
+
cachedCells[`${col},${row}`] = { value: cell.value, className: mx(cell.classNames) };
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
_cachedBounds = nextBounds;
|
|
66
|
+
return cachedCells;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const useSheetModelDxGridProps = (
|
|
71
|
+
dxGridRef: MutableRefObject<DxGridElement | null>,
|
|
72
|
+
model: SheetModel,
|
|
73
|
+
formatting: FormattingModel,
|
|
74
|
+
): Pick<GridContentProps, 'columns' | 'rows'> => {
|
|
75
|
+
const [columns, setColumns] = useState<DxGridAxisMeta>(createDxGridColumns(model));
|
|
76
|
+
const [rows, setRows] = useState<DxGridAxisMeta>(createDxGridColumns(model));
|
|
77
|
+
|
|
78
|
+
useLayoutEffect(() => {
|
|
79
|
+
const cellsAccessor = createDocAccessor(model.sheet, ['cells']);
|
|
80
|
+
if (dxGridRef.current) {
|
|
81
|
+
dxGridRef.current.getCells = cellGetter(model, formatting);
|
|
82
|
+
}
|
|
83
|
+
const handleCellsUpdate = () => {
|
|
84
|
+
dxGridRef.current?.requestUpdate('initialCells');
|
|
85
|
+
};
|
|
86
|
+
cellsAccessor.handle.addListener('change', handleCellsUpdate);
|
|
87
|
+
return () => cellsAccessor.handle.removeListener('change', handleCellsUpdate);
|
|
88
|
+
}, [model, formatting]);
|
|
89
|
+
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
const columnMetaAccessor = createDocAccessor(model.sheet, ['columnMeta']);
|
|
92
|
+
const rowMetaAccessor = createDocAccessor(model.sheet, ['rowMeta']);
|
|
93
|
+
const handleColumnMetaUpdate = () => {
|
|
94
|
+
setColumns(createDxGridColumns(model));
|
|
95
|
+
};
|
|
96
|
+
const handleRowMetaUpdate = () => {
|
|
97
|
+
setRows(createDxGridRows(model));
|
|
98
|
+
};
|
|
99
|
+
columnMetaAccessor.handle.addListener('change', handleColumnMetaUpdate);
|
|
100
|
+
rowMetaAccessor.handle.addListener('change', handleRowMetaUpdate);
|
|
101
|
+
return () => {
|
|
102
|
+
columnMetaAccessor.handle.removeListener('change', handleColumnMetaUpdate);
|
|
103
|
+
rowMetaAccessor.handle.removeListener('change', handleRowMetaUpdate);
|
|
104
|
+
};
|
|
105
|
+
}, [model]);
|
|
106
|
+
|
|
107
|
+
return { columns, rows };
|
|
108
|
+
};
|
|
@@ -4,31 +4,34 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import React, { useContext, useEffect, useState } from 'react';
|
|
7
|
+
import React, { useState } from 'react';
|
|
9
8
|
|
|
10
|
-
import { Client } from '@dxos/client';
|
|
11
|
-
import { type EchoReactiveObject } from '@dxos/echo-schema';
|
|
12
9
|
import { log } from '@dxos/log';
|
|
13
|
-
import {
|
|
10
|
+
import { useSpace } from '@dxos/react-client/echo';
|
|
11
|
+
import { withClientProvider } from '@dxos/react-client/testing';
|
|
14
12
|
import { Button } from '@dxos/react-ui';
|
|
15
13
|
import { mx } from '@dxos/react-ui-theme';
|
|
16
|
-
import {
|
|
14
|
+
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
17
15
|
|
|
18
16
|
import { Sheet } from './Sheet';
|
|
19
17
|
import { type SizeMap } from './grid';
|
|
20
18
|
import { useSheetContext } from './sheet-context';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
import {
|
|
19
|
+
import { addressToIndex, rangeToIndex } from '../../defs';
|
|
20
|
+
import { type ComputeGraph } from '../../graph';
|
|
21
|
+
import { testPlugins } from '../../graph/testing';
|
|
22
|
+
import { useComputeGraph } from '../../hooks';
|
|
23
|
+
import { createTestCells, useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
24
|
+
import { SheetType, ValueTypeEnum } from '../../types';
|
|
26
25
|
import { Toolbar, type ToolbarActionHandler } from '../Toolbar';
|
|
27
26
|
|
|
28
27
|
// TODO(burdon): Allow toolbar to access sheet context; provide state for current cursor/range.
|
|
29
|
-
const SheetWithToolbar = ({
|
|
28
|
+
const SheetWithToolbar = ({ graph, debug }: { graph: ComputeGraph; debug?: boolean }) => {
|
|
30
29
|
const { model, cursor, range } = useSheetContext();
|
|
31
30
|
|
|
31
|
+
const handleRefresh = () => {
|
|
32
|
+
// graph?.refresh(); // TODO(burdon): ???
|
|
33
|
+
};
|
|
34
|
+
|
|
32
35
|
// TODO(burdon): Factor out.
|
|
33
36
|
const handleAction: ToolbarActionHandler = ({ type }) => {
|
|
34
37
|
log.info('action', { type, cursor, range });
|
|
@@ -36,7 +39,7 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
|
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
const idx = range ? model.
|
|
42
|
+
const idx = range ? rangeToIndex(model.sheet, range) : addressToIndex(model.sheet, cursor);
|
|
40
43
|
model.sheet.formatting[idx] ??= {};
|
|
41
44
|
const format = model.sheet.formatting[idx];
|
|
42
45
|
|
|
@@ -75,14 +78,12 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
|
|
|
75
78
|
format.precision = 2;
|
|
76
79
|
break;
|
|
77
80
|
}
|
|
81
|
+
case 'comment': {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
78
84
|
}
|
|
79
85
|
};
|
|
80
86
|
|
|
81
|
-
const graph = useComputeGraph(space);
|
|
82
|
-
const handleRefresh = () => {
|
|
83
|
-
graph.refresh();
|
|
84
|
-
};
|
|
85
|
-
|
|
86
87
|
return (
|
|
87
88
|
<div className='flex flex-col overflow-hidden'>
|
|
88
89
|
<Toolbar.Root onAction={handleAction}>
|
|
@@ -99,56 +100,43 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
|
|
|
99
100
|
);
|
|
100
101
|
};
|
|
101
102
|
|
|
102
|
-
const withGraphDecorator: Decorator = (Story) => {
|
|
103
|
-
const [graphs, setGraphs] = useState<Record<string, ComputeGraph>>({});
|
|
104
|
-
|
|
105
|
-
const setGraph = (key: string, graph: ComputeGraph) => {
|
|
106
|
-
if (!graph.hf.doesSheetExist(testSheetName)) {
|
|
107
|
-
const sheetName = graph.hf.addSheet(testSheetName);
|
|
108
|
-
const sheet = graph.hf.getSheetId(sheetName)!;
|
|
109
|
-
graph.hf.setCellContents({ sheet, col: 0, row: 0 }, Math.random());
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
setGraphs((graphs) => ({ ...graphs, [key]: graph }));
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
return (
|
|
116
|
-
<ComputeGraphContextProvider graphs={graphs} setGraph={setGraph}>
|
|
117
|
-
<Story />
|
|
118
|
-
</ComputeGraphContextProvider>
|
|
119
|
-
);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
103
|
export default {
|
|
123
104
|
title: 'plugin-sheet/Sheet',
|
|
124
105
|
component: Sheet,
|
|
125
|
-
decorators: [
|
|
106
|
+
decorators: [
|
|
107
|
+
withClientProvider({ types: [SheetType], createIdentity: true }),
|
|
108
|
+
withComputeGraphDecorator({ plugins: testPlugins }),
|
|
109
|
+
withTheme,
|
|
110
|
+
withLayout({ fullscreen: true, tooltips: true, classNames: 'inset-4' }),
|
|
111
|
+
],
|
|
126
112
|
};
|
|
127
113
|
|
|
128
114
|
export const Default = () => {
|
|
129
115
|
const [debug, setDebug] = useState(false);
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
|
|
116
|
+
const space = useSpace();
|
|
117
|
+
const graph = useComputeGraph(space);
|
|
118
|
+
const sheet = useTestSheet(space, graph, { cells: createTestCells() });
|
|
119
|
+
if (!graph || !sheet) {
|
|
133
120
|
return null;
|
|
134
121
|
}
|
|
135
122
|
|
|
136
123
|
return (
|
|
137
|
-
<Sheet.Root
|
|
138
|
-
<SheetWithToolbar
|
|
124
|
+
<Sheet.Root graph={graph} sheet={sheet} onInfo={() => setDebug((debug) => !debug)}>
|
|
125
|
+
<SheetWithToolbar graph={graph} debug={debug} />
|
|
139
126
|
</Sheet.Root>
|
|
140
127
|
);
|
|
141
128
|
};
|
|
142
129
|
|
|
143
130
|
export const Debug = () => {
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
|
|
131
|
+
const space = useSpace();
|
|
132
|
+
const graph = useComputeGraph(space);
|
|
133
|
+
const sheet = useTestSheet(space, graph, { cells: createTestCells() });
|
|
134
|
+
if (!graph || !sheet) {
|
|
147
135
|
return null;
|
|
148
136
|
}
|
|
149
137
|
|
|
150
138
|
return (
|
|
151
|
-
<Sheet.Root
|
|
139
|
+
<Sheet.Root graph={graph} sheet={sheet}>
|
|
152
140
|
<Sheet.Main />
|
|
153
141
|
<Sheet.Debug />
|
|
154
142
|
</Sheet.Root>
|
|
@@ -157,14 +145,15 @@ export const Debug = () => {
|
|
|
157
145
|
|
|
158
146
|
export const Rows = () => {
|
|
159
147
|
const [rowSizes, setRowSizes] = useState<SizeMap>({});
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
|
|
148
|
+
const space = useSpace();
|
|
149
|
+
const graph = useComputeGraph(space);
|
|
150
|
+
const sheet = useTestSheet(space, graph);
|
|
151
|
+
if (!graph || !sheet) {
|
|
163
152
|
return null;
|
|
164
153
|
}
|
|
165
154
|
|
|
166
155
|
return (
|
|
167
|
-
<Sheet.Root
|
|
156
|
+
<Sheet.Root graph={graph} sheet={sheet}>
|
|
168
157
|
<Sheet.Rows
|
|
169
158
|
rows={sheet.rows}
|
|
170
159
|
sizes={rowSizes}
|
|
@@ -176,14 +165,15 @@ export const Rows = () => {
|
|
|
176
165
|
|
|
177
166
|
export const Columns = () => {
|
|
178
167
|
const [columnSizes, setColumnSizes] = useState<SizeMap>({});
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
|
|
168
|
+
const space = useSpace();
|
|
169
|
+
const graph = useComputeGraph(space);
|
|
170
|
+
const sheet = useTestSheet(space, graph);
|
|
171
|
+
if (!graph || !sheet) {
|
|
182
172
|
return null;
|
|
183
173
|
}
|
|
184
174
|
|
|
185
175
|
return (
|
|
186
|
-
<Sheet.Root
|
|
176
|
+
<Sheet.Root graph={graph} sheet={sheet}>
|
|
187
177
|
<Sheet.Columns
|
|
188
178
|
columns={sheet.columns}
|
|
189
179
|
sizes={columnSizes}
|
|
@@ -194,18 +184,19 @@ export const Columns = () => {
|
|
|
194
184
|
};
|
|
195
185
|
|
|
196
186
|
export const Main = () => {
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
|
|
187
|
+
const space = useSpace();
|
|
188
|
+
const graph = useComputeGraph(space);
|
|
189
|
+
const sheet = useTestSheet(space, graph, { cells: createTestCells() });
|
|
190
|
+
if (!graph || !sheet) {
|
|
200
191
|
return null;
|
|
201
192
|
}
|
|
202
193
|
|
|
203
194
|
return (
|
|
204
|
-
<Sheet.Root
|
|
195
|
+
<Sheet.Root graph={graph} sheet={sheet}>
|
|
205
196
|
<Sheet.Grid
|
|
206
197
|
size={{
|
|
207
198
|
numRows: 50,
|
|
208
|
-
|
|
199
|
+
numCols: 26,
|
|
209
200
|
}}
|
|
210
201
|
rows={sheet.rows}
|
|
211
202
|
columns={sheet.columns}
|
|
@@ -258,30 +249,3 @@ export const GridLayout = () => {
|
|
|
258
249
|
const Cell = ({ className, label }: { className?: string; label: string }) => (
|
|
259
250
|
<div className={mx('flex items-center justify-center border', className)}>{label}</div>
|
|
260
251
|
);
|
|
261
|
-
|
|
262
|
-
const useTestSheet = () => {
|
|
263
|
-
const { graphs, setGraph } = useContext(ComputeGraphContext);
|
|
264
|
-
const [sheet, setSheet] = useState<EchoReactiveObject<SheetType>>();
|
|
265
|
-
useEffect(() => {
|
|
266
|
-
const t = setTimeout(async () => {
|
|
267
|
-
const client = new Client();
|
|
268
|
-
await client.initialize();
|
|
269
|
-
await client.halo.createIdentity();
|
|
270
|
-
const space = await client.spaces.create();
|
|
271
|
-
client.addTypes([SheetType]);
|
|
272
|
-
|
|
273
|
-
const graph = graphs[space.id] ?? createComputeGraph();
|
|
274
|
-
if (!graphs[space.id]) {
|
|
275
|
-
setGraph(space.id, graph);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const sheet = await createTestSheet({ graph });
|
|
279
|
-
space.db.add(sheet);
|
|
280
|
-
setSheet(sheet);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
return () => clearTimeout(t);
|
|
284
|
-
}, []);
|
|
285
|
-
|
|
286
|
-
return sheet;
|
|
287
|
-
};
|
|
@@ -60,6 +60,7 @@ import {
|
|
|
60
60
|
} from './grid';
|
|
61
61
|
import { type GridSize, handleArrowNav, handleNav, useRangeSelect } from './nav';
|
|
62
62
|
import { type SheetContextProps, SheetContextProvider, useSheetContext } from './sheet-context';
|
|
63
|
+
import { useThreads } from './threads';
|
|
63
64
|
import { getRectUnion, getRelativeClientRect, scrollIntoView } from './util';
|
|
64
65
|
import {
|
|
65
66
|
type CellIndex,
|
|
@@ -68,7 +69,9 @@ import {
|
|
|
68
69
|
columnLetter,
|
|
69
70
|
posEquals,
|
|
70
71
|
rangeToA1Notation,
|
|
71
|
-
|
|
72
|
+
addressToIndex,
|
|
73
|
+
addressFromIndex,
|
|
74
|
+
} from '../../defs';
|
|
72
75
|
import {
|
|
73
76
|
CellEditor,
|
|
74
77
|
type CellRangeNotifier,
|
|
@@ -135,12 +138,16 @@ const SheetRoot = ({ children, ...props }: PropsWithChildren<SheetContextProps>)
|
|
|
135
138
|
|
|
136
139
|
type SheetMainProps = ThemedClassName<Partial<GridSize>>;
|
|
137
140
|
|
|
138
|
-
const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows,
|
|
141
|
+
const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows, numCols }, forwardRef) => {
|
|
139
142
|
const { model, cursor, setCursor, setRange, setEditing } = useSheetContext();
|
|
140
143
|
|
|
141
144
|
// Scrolling.
|
|
142
145
|
const { rowsRef, columnsRef, contentRef } = useScrollHandlers();
|
|
143
146
|
|
|
147
|
+
// Threads.
|
|
148
|
+
// TODO(Zan): Move this to an extension once we have an extension model.
|
|
149
|
+
useThreads();
|
|
150
|
+
|
|
144
151
|
//
|
|
145
152
|
// Order of Row/columns.
|
|
146
153
|
//
|
|
@@ -170,21 +177,21 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
170
177
|
}, [rows, columns]);
|
|
171
178
|
|
|
172
179
|
const handleMoveRows: SheetRowsProps['onMove'] = (from, to, num = 1) => {
|
|
173
|
-
const cursorIdx = cursor ? model.
|
|
180
|
+
const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : undefined;
|
|
174
181
|
const [rows] = model.sheet.rows.splice(from, num);
|
|
175
182
|
model.sheet.rows.splice(to, 0, rows);
|
|
176
183
|
if (cursorIdx) {
|
|
177
|
-
setCursor(model.
|
|
184
|
+
setCursor(addressFromIndex(model.sheet, cursorIdx));
|
|
178
185
|
}
|
|
179
186
|
setRows([...model.sheet.rows]);
|
|
180
187
|
};
|
|
181
188
|
|
|
182
189
|
const handleMoveColumns: SheetColumnsProps['onMove'] = (from, to, num = 1) => {
|
|
183
|
-
const cursorIdx = cursor ? model.
|
|
190
|
+
const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : undefined;
|
|
184
191
|
const columns = model.sheet.columns.splice(from, num);
|
|
185
192
|
model.sheet.columns.splice(to, 0, ...columns);
|
|
186
193
|
if (cursorIdx) {
|
|
187
|
-
setCursor(model.
|
|
194
|
+
setCursor(addressFromIndex(model.sheet, cursorIdx));
|
|
188
195
|
}
|
|
189
196
|
setColumns([...model.sheet.columns]);
|
|
190
197
|
};
|
|
@@ -256,8 +263,8 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
256
263
|
ref={columnsRef}
|
|
257
264
|
columns={columns}
|
|
258
265
|
sizes={columnSizes}
|
|
259
|
-
selected={cursor?.
|
|
260
|
-
onSelect={(
|
|
266
|
+
selected={cursor?.col}
|
|
267
|
+
onSelect={(col) => setCursor(cursor?.col === col ? undefined : { row: -1, col })}
|
|
261
268
|
onResize={handleResizeColumn}
|
|
262
269
|
onMove={handleMoveColumns}
|
|
263
270
|
/>
|
|
@@ -267,13 +274,13 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
267
274
|
rows={rows}
|
|
268
275
|
sizes={rowSizes}
|
|
269
276
|
selected={cursor?.row}
|
|
270
|
-
onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row,
|
|
277
|
+
onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row, col: -1 })}
|
|
271
278
|
onResize={handleResizeRow}
|
|
272
279
|
onMove={handleMoveRows}
|
|
273
280
|
/>
|
|
274
281
|
<SheetGrid
|
|
275
282
|
ref={contentRef}
|
|
276
|
-
size={{ numRows: numRows ?? rows.length,
|
|
283
|
+
size={{ numRows: numRows ?? rows.length, numCols: numCols ?? columns.length }}
|
|
277
284
|
rows={rows}
|
|
278
285
|
columns={columns}
|
|
279
286
|
rowSizes={rowSizes}
|
|
@@ -878,11 +885,11 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
|
|
|
878
885
|
|
|
879
886
|
{/* Grid cells. */}
|
|
880
887
|
{rowRange.map(({ row, top, height }) => {
|
|
881
|
-
return columnRange.map(({
|
|
888
|
+
return columnRange.map(({ col, left, width }) => {
|
|
882
889
|
const style: CSSProperties = { position: 'absolute', top, left, width, height };
|
|
883
|
-
const cell = { row,
|
|
890
|
+
const cell: CellAddress = { row, col };
|
|
884
891
|
const id = addressToA1Notation(cell);
|
|
885
|
-
const idx = model.
|
|
892
|
+
const idx = addressToIndex(model.sheet, cell);
|
|
886
893
|
const active = posEquals(cursor, cell);
|
|
887
894
|
if (active && editing) {
|
|
888
895
|
const value = initialText.current ?? model.getCellText(cell) ?? '';
|
|
@@ -1003,16 +1010,46 @@ type SheetCellProps = {
|
|
|
1003
1010
|
};
|
|
1004
1011
|
|
|
1005
1012
|
const SheetCell = ({ id, cell, style, active, onSelect }: SheetCellProps) => {
|
|
1006
|
-
const {
|
|
1013
|
+
const {
|
|
1014
|
+
formatting,
|
|
1015
|
+
editing,
|
|
1016
|
+
setRange,
|
|
1017
|
+
decorations,
|
|
1018
|
+
model: { sheet },
|
|
1019
|
+
} = useSheetContext();
|
|
1007
1020
|
const { value, classNames } = formatting.getFormatting(cell);
|
|
1008
1021
|
|
|
1022
|
+
const decorationsForCell = decorations.getDecorationsForCell(addressToIndex(sheet, cell)) ?? [];
|
|
1023
|
+
const decorationAddedClasses = useMemo(
|
|
1024
|
+
() => decorationsForCell.flatMap((d) => d.classNames ?? []),
|
|
1025
|
+
[decorationsForCell],
|
|
1026
|
+
);
|
|
1027
|
+
const decoratedContent = decorationsForCell.reduce(
|
|
1028
|
+
(children, { decorate }) => {
|
|
1029
|
+
if (!decorate) {
|
|
1030
|
+
return children;
|
|
1031
|
+
}
|
|
1032
|
+
const DecoratorComponent = decorate;
|
|
1033
|
+
return <DecoratorComponent>{children}</DecoratorComponent>;
|
|
1034
|
+
},
|
|
1035
|
+
<div
|
|
1036
|
+
role='none'
|
|
1037
|
+
className={mx(
|
|
1038
|
+
'flex flex-grow bs-full is-full px-2 items-center truncate cursor-pointer',
|
|
1039
|
+
...decorationAddedClasses,
|
|
1040
|
+
)}
|
|
1041
|
+
>
|
|
1042
|
+
{value}
|
|
1043
|
+
</div>,
|
|
1044
|
+
);
|
|
1045
|
+
|
|
1009
1046
|
return (
|
|
1010
1047
|
<div
|
|
1011
1048
|
{...{ [`data-${CELL_DATA_KEY}`]: id }}
|
|
1012
1049
|
role='cell'
|
|
1013
1050
|
style={style}
|
|
1014
1051
|
className={mx(
|
|
1015
|
-
'
|
|
1052
|
+
'border border-gridLine cursor-pointer',
|
|
1016
1053
|
fragments.cell,
|
|
1017
1054
|
active && ['z-20', fragments.cellSelected],
|
|
1018
1055
|
classNames,
|
|
@@ -1026,7 +1063,7 @@ const SheetCell = ({ id, cell, style, active, onSelect }: SheetCellProps) => {
|
|
|
1026
1063
|
}}
|
|
1027
1064
|
onDoubleClick={() => onSelect?.(cell, true)}
|
|
1028
1065
|
>
|
|
1029
|
-
{
|
|
1066
|
+
{decoratedContent}
|
|
1030
1067
|
</div>
|
|
1031
1068
|
);
|
|
1032
1069
|
};
|
|
@@ -1045,10 +1082,11 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
|
|
|
1045
1082
|
notifier.current?.(rangeToA1Notation(range));
|
|
1046
1083
|
}
|
|
1047
1084
|
}, [range]);
|
|
1085
|
+
|
|
1048
1086
|
const extension = useMemo(
|
|
1049
1087
|
() => [
|
|
1050
1088
|
editorKeys({ onNav, onClose }),
|
|
1051
|
-
sheetExtension({ functions: model.
|
|
1089
|
+
sheetExtension({ functions: model.graph.getFunctions() }),
|
|
1052
1090
|
rangeExtension((fn) => (notifier.current = fn)),
|
|
1053
1091
|
],
|
|
1054
1092
|
[model],
|
|
@@ -1072,12 +1110,13 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
|
|
|
1072
1110
|
|
|
1073
1111
|
const SheetStatusBar = () => {
|
|
1074
1112
|
const { model, cursor, range } = useSheetContext();
|
|
1113
|
+
|
|
1075
1114
|
let value;
|
|
1076
1115
|
let isFormula = false;
|
|
1077
1116
|
if (cursor) {
|
|
1078
1117
|
value = model.getCellValue(cursor);
|
|
1079
1118
|
if (typeof value === 'string' && value.charAt(0) === '=') {
|
|
1080
|
-
value = model.
|
|
1119
|
+
value = model.graph.mapFunctionBindingFromId(model.mapFormulaIndicesToRefs(value));
|
|
1081
1120
|
isFormula = true;
|
|
1082
1121
|
} else if (value != null) {
|
|
1083
1122
|
value = String(value);
|