@dxos/plugin-sheet 0.6.12-main.5cc132e → 0.6.12-main.78ddbdf
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-V4GCCZTX.mjs +261 -0
- package/dist/lib/browser/SheetContainer-V4GCCZTX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GNNVBNCX.mjs → chunk-6ZMQVB4Z.mjs} +358 -678
- package/dist/lib/browser/chunk-6ZMQVB4Z.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/{node-esm/chunk-WUPTZUTX.mjs → browser/chunk-T3NJFTD4.mjs} +4 -14
- package/dist/lib/browser/chunk-T3NJFTD4.mjs.map +7 -0
- package/dist/lib/browser/{SheetContainer-Y7ZMFBAP.mjs → chunk-U2JHW3L6.mjs} +819 -498
- package/dist/lib/browser/chunk-U2JHW3L6.mjs.map +7 -0
- package/dist/lib/browser/graph-T27BOBOV.mjs +21 -0
- package/dist/lib/browser/graph-T27BOBOV.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +58 -55
- 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-3ZY7MPWJ.cjs +279 -0
- package/dist/lib/node/SheetContainer-3ZY7MPWJ.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-ZRQZFV5T.cjs → chunk-DD6FIXWC.cjs} +359 -679
- package/dist/lib/node/chunk-DD6FIXWC.cjs.map +7 -0
- package/dist/lib/node/{SheetContainer-KEOKUKAQ.cjs → chunk-OTTD7FBK.cjs} +875 -551
- package/dist/lib/node/chunk-OTTD7FBK.cjs.map +7 -0
- package/dist/lib/node/{chunk-VJU3NPUJ.cjs → chunk-Q3HBHPRL.cjs} +8 -19
- package/dist/lib/node/chunk-Q3HBHPRL.cjs.map +7 -0
- package/dist/lib/node/graph-SPKGX7W4.cjs +43 -0
- package/dist/lib/node/graph-SPKGX7W4.cjs.map +7 -0
- package/dist/lib/node/index.cjs +75 -64
- 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-PXSJX6XK.mjs +262 -0
- package/dist/lib/node-esm/SheetContainer-PXSJX6XK.mjs.map +7 -0
- package/dist/lib/node-esm/{SheetContainer-Y7ZMFBAP.mjs → chunk-7HVSOTGA.mjs} +820 -498
- package/dist/lib/node-esm/chunk-7HVSOTGA.mjs.map +7 -0
- package/dist/lib/{browser/chunk-WUPTZUTX.mjs → node-esm/chunk-BMNA27EX.mjs} +5 -14
- package/dist/lib/node-esm/chunk-BMNA27EX.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-GNNVBNCX.mjs → chunk-D6KU5MI7.mjs} +359 -677
- package/dist/lib/node-esm/chunk-D6KU5MI7.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-JRL5LGCE.mjs → chunk-IU2L277A.mjs} +4 -5
- package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +7 -0
- package/dist/lib/node-esm/graph-U67IO4UC.mjs +22 -0
- package/dist/lib/node-esm/graph-U67IO4UC.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +59 -55
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/meta.mjs +2 -1
- package/dist/lib/node-esm/types.mjs +5 -6
- 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/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 +4 -5
- package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/threads.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer.d.ts +1 -1
- package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +1 -1
- package/dist/types/src/components/index.d.ts +2 -1
- 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/{model → defs}/util.d.ts +8 -4
- package/dist/types/src/defs/util.d.ts.map +1 -0
- package/dist/types/src/extensions/compute.d.ts +5 -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 +1 -1
- package/dist/types/src/graph/async-function.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.browser.test.d.ts +2 -0
- package/dist/types/src/graph/compute-graph.browser.test.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.d.ts +81 -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-node.d.ts +19 -0
- package/dist/types/src/graph/compute-node.d.ts.map +1 -0
- package/dist/types/src/{components/ComputeGraph/custom.d.ts → graph/custom-function.d.ts} +1 -1
- package/dist/types/src/graph/custom-function.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/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 -4
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/{model.d.ts → sheet-model.d.ts} +9 -48
- 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 +9 -0
- package/dist/types/src/testing/testing.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +12 -2
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/vendor/hyperformula.mjs +37145 -0
- package/package.json +41 -38
- package/src/SheetPlugin.tsx +39 -59
- package/src/components/CellEditor/CellEditor.stories.tsx +4 -3
- package/src/components/CellEditor/CellEditor.tsx +59 -9
- package/src/components/CellEditor/extension.test.ts +3 -3
- 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 +41 -82
- package/src/components/Sheet/Sheet.tsx +12 -10
- package/src/components/Sheet/grid.ts +3 -3
- package/src/components/Sheet/nav.ts +19 -19
- package/src/components/Sheet/sheet-context.tsx +10 -80
- package/src/components/Sheet/threads.tsx +10 -6
- package/src/components/SheetContainer.tsx +2 -2
- package/src/components/Toolbar/Toolbar.tsx +1 -2
- package/src/components/index.ts +1 -0
- package/src/defs/index.ts +6 -0
- package/src/{model → defs}/types.test.ts +7 -7
- package/src/{model → defs}/types.ts +23 -14
- package/src/{model → defs}/util.ts +49 -17
- package/src/extensions/compute.stories.tsx +151 -0
- package/src/extensions/compute.ts +98 -0
- package/src/extensions/index.ts +5 -0
- package/src/{components/ComputeGraph → graph}/async-function.ts +3 -1
- package/src/graph/compute-graph.browser.test.ts +104 -0
- package/src/graph/compute-graph.stories.tsx +92 -0
- package/src/graph/compute-graph.ts +290 -0
- package/src/graph/compute-node.ts +51 -0
- package/src/{components/ComputeGraph/custom.ts → graph/custom-function.ts} +2 -6
- package/src/{components/ComputeGraph → graph}/edge-function.ts +2 -1
- package/src/graph/hyperformula.test.ts +15 -0
- package/src/graph/index.ts +7 -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 +20 -0
- package/src/hooks/useFormattingModel.ts +11 -0
- package/src/hooks/useSheetModel.ts +43 -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 -4
- package/src/model/{model.ts → sheet-model.ts} +67 -184
- package/src/sanity.test.ts +40 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/testing.tsx +66 -0
- package/src/types.ts +14 -12
- package/dist/lib/browser/SheetContainer-Y7ZMFBAP.mjs.map +0 -7
- package/dist/lib/browser/chunk-GNNVBNCX.mjs.map +0 -7
- package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +0 -7
- package/dist/lib/browser/chunk-PGKZPKUD.mjs +0 -175
- package/dist/lib/browser/chunk-PGKZPKUD.mjs.map +0 -7
- package/dist/lib/browser/chunk-VBF7YENS.mjs +0 -8
- package/dist/lib/browser/chunk-VBF7YENS.mjs.map +0 -7
- package/dist/lib/browser/chunk-WUPTZUTX.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-KEOKUKAQ.cjs.map +0 -7
- package/dist/lib/node/chunk-57PB2HPY.cjs +0 -40
- package/dist/lib/node/chunk-57PB2HPY.cjs.map +0 -7
- package/dist/lib/node/chunk-6LWBQAQZ.cjs +0 -202
- package/dist/lib/node/chunk-6LWBQAQZ.cjs.map +0 -7
- package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +0 -7
- package/dist/lib/node/chunk-VJU3NPUJ.cjs.map +0 -7
- package/dist/lib/node/chunk-ZRQZFV5T.cjs.map +0 -7
- package/dist/lib/node/testing.cjs +0 -111
- package/dist/lib/node/testing.cjs.map +0 -7
- package/dist/lib/node-esm/SheetContainer-Y7ZMFBAP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GNNVBNCX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JRL5LGCE.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PGKZPKUD.mjs +0 -175
- package/dist/lib/node-esm/chunk-PGKZPKUD.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-VBF7YENS.mjs +0 -8
- package/dist/lib/node-esm/chunk-VBF7YENS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-WUPTZUTX.mjs.map +0 -7
- package/dist/lib/node-esm/testing.mjs +0 -92
- package/dist/lib/node-esm/testing.mjs.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.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 -49
- package/src/components/ComputeGraph/graph.ts +0 -62
- package/src/model/model.browser.test.ts +0 -99
- 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 { type Space } from '@dxos/client/echo';
|
|
8
|
+
import {
|
|
9
|
+
type DxGridElement,
|
|
10
|
+
Grid,
|
|
11
|
+
type GridContentProps,
|
|
12
|
+
type GridScopedProps,
|
|
13
|
+
useGridContext,
|
|
14
|
+
} from '@dxos/react-ui-grid';
|
|
15
|
+
|
|
16
|
+
import { dxGridCellIndexToSheetCellAddress, useSheetModelDxGridProps } from './util';
|
|
17
|
+
import { rangeToA1Notation, type CellRange } from '../../defs';
|
|
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 = { space?: Space; sheet?: SheetType } & UseSheetModelOptions;
|
|
140
|
+
|
|
141
|
+
export const GridSheet = ({ space, sheet, ...options }: GridSheetProps) => {
|
|
142
|
+
const model = useSheetModel(space, 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,32 +4,33 @@
|
|
|
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 { type Space, 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 { addressToIndex, rangeToIndex } from '../../
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
// TODO(wittjosiah): Refactor. This is not exported from ./components due to depending on ECHO.
|
|
26
|
-
import { ComputeGraphContext, ComputeGraphContextProvider, useComputeGraph } from '../ComputeGraph/graph-context';
|
|
19
|
+
import { addressToIndex, rangeToIndex } from '../../defs';
|
|
20
|
+
import { useComputeGraph } from '../../hooks';
|
|
21
|
+
import { useTestSheet, withGraphDecorator } from '../../testing';
|
|
22
|
+
import { SheetType, ValueTypeEnum } from '../../types';
|
|
27
23
|
import { Toolbar, type ToolbarActionHandler } from '../Toolbar';
|
|
28
24
|
|
|
29
25
|
// TODO(burdon): Allow toolbar to access sheet context; provide state for current cursor/range.
|
|
30
26
|
const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) => {
|
|
31
27
|
const { model, cursor, range } = useSheetContext();
|
|
32
28
|
|
|
29
|
+
const graph = useComputeGraph(space);
|
|
30
|
+
const handleRefresh = () => {
|
|
31
|
+
graph?.refresh();
|
|
32
|
+
};
|
|
33
|
+
|
|
33
34
|
// TODO(burdon): Factor out.
|
|
34
35
|
const handleAction: ToolbarActionHandler = ({ type }) => {
|
|
35
36
|
log.info('action', { type, cursor, range });
|
|
@@ -82,11 +83,6 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
|
|
|
82
83
|
}
|
|
83
84
|
};
|
|
84
85
|
|
|
85
|
-
const graph = useComputeGraph(space);
|
|
86
|
-
const handleRefresh = () => {
|
|
87
|
-
graph.refresh();
|
|
88
|
-
};
|
|
89
|
-
|
|
90
86
|
return (
|
|
91
87
|
<div className='flex flex-col overflow-hidden'>
|
|
92
88
|
<Toolbar.Root onAction={handleAction}>
|
|
@@ -103,56 +99,43 @@ const SheetWithToolbar = ({ debug, space }: { debug?: boolean; space: Space }) =
|
|
|
103
99
|
);
|
|
104
100
|
};
|
|
105
101
|
|
|
106
|
-
const withGraphDecorator: Decorator = (Story) => {
|
|
107
|
-
const [graphs, setGraphs] = useState<Record<string, ComputeGraph>>({});
|
|
108
|
-
|
|
109
|
-
const setGraph = (key: string, graph: ComputeGraph) => {
|
|
110
|
-
if (!graph.hf.doesSheetExist(testSheetName)) {
|
|
111
|
-
const sheetName = graph.hf.addSheet(testSheetName);
|
|
112
|
-
const sheet = graph.hf.getSheetId(sheetName)!;
|
|
113
|
-
graph.hf.setCellContents({ sheet, col: 0, row: 0 }, Math.random());
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
setGraphs((graphs) => ({ ...graphs, [key]: graph }));
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
return (
|
|
120
|
-
<ComputeGraphContextProvider graphs={graphs} setGraph={setGraph}>
|
|
121
|
-
<Story />
|
|
122
|
-
</ComputeGraphContextProvider>
|
|
123
|
-
);
|
|
124
|
-
};
|
|
125
|
-
|
|
126
102
|
export default {
|
|
127
103
|
title: 'plugin-sheet/Sheet',
|
|
128
104
|
component: Sheet,
|
|
129
|
-
decorators: [
|
|
105
|
+
decorators: [
|
|
106
|
+
withClientProvider({ types: [SheetType], createIdentity: true }),
|
|
107
|
+
withGraphDecorator,
|
|
108
|
+
withTheme,
|
|
109
|
+
withLayout({ fullscreen: true, tooltips: true, classNames: 'inset-4' }),
|
|
110
|
+
],
|
|
130
111
|
};
|
|
131
112
|
|
|
132
113
|
export const Default = () => {
|
|
133
114
|
const [debug, setDebug] = useState(false);
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
|
|
115
|
+
const space = useSpace();
|
|
116
|
+
const graph = useComputeGraph(space);
|
|
117
|
+
const sheet = useTestSheet(space, graph);
|
|
118
|
+
if (!space || !sheet) {
|
|
137
119
|
return null;
|
|
138
120
|
}
|
|
139
121
|
|
|
140
122
|
return (
|
|
141
|
-
<Sheet.Root
|
|
123
|
+
<Sheet.Root space={space} sheet={sheet} onInfo={() => setDebug((debug) => !debug)}>
|
|
142
124
|
<SheetWithToolbar debug={debug} space={space} />
|
|
143
125
|
</Sheet.Root>
|
|
144
126
|
);
|
|
145
127
|
};
|
|
146
128
|
|
|
147
129
|
export const Debug = () => {
|
|
148
|
-
const
|
|
149
|
-
const
|
|
130
|
+
const space = useSpace();
|
|
131
|
+
const graph = useComputeGraph(space);
|
|
132
|
+
const sheet = useTestSheet(space, graph);
|
|
150
133
|
if (!sheet || !space) {
|
|
151
134
|
return null;
|
|
152
135
|
}
|
|
153
136
|
|
|
154
137
|
return (
|
|
155
|
-
<Sheet.Root
|
|
138
|
+
<Sheet.Root space={space} sheet={sheet}>
|
|
156
139
|
<Sheet.Main />
|
|
157
140
|
<Sheet.Debug />
|
|
158
141
|
</Sheet.Root>
|
|
@@ -161,14 +144,15 @@ export const Debug = () => {
|
|
|
161
144
|
|
|
162
145
|
export const Rows = () => {
|
|
163
146
|
const [rowSizes, setRowSizes] = useState<SizeMap>({});
|
|
164
|
-
const
|
|
165
|
-
const
|
|
147
|
+
const space = useSpace();
|
|
148
|
+
const graph = useComputeGraph(space);
|
|
149
|
+
const sheet = useTestSheet(space, graph);
|
|
166
150
|
if (!sheet || !space) {
|
|
167
151
|
return null;
|
|
168
152
|
}
|
|
169
153
|
|
|
170
154
|
return (
|
|
171
|
-
<Sheet.Root
|
|
155
|
+
<Sheet.Root space={space} sheet={sheet}>
|
|
172
156
|
<Sheet.Rows
|
|
173
157
|
rows={sheet.rows}
|
|
174
158
|
sizes={rowSizes}
|
|
@@ -180,14 +164,15 @@ export const Rows = () => {
|
|
|
180
164
|
|
|
181
165
|
export const Columns = () => {
|
|
182
166
|
const [columnSizes, setColumnSizes] = useState<SizeMap>({});
|
|
183
|
-
const
|
|
184
|
-
const
|
|
167
|
+
const space = useSpace();
|
|
168
|
+
const graph = useComputeGraph(space);
|
|
169
|
+
const sheet = useTestSheet(space, graph);
|
|
185
170
|
if (!sheet || !space) {
|
|
186
171
|
return null;
|
|
187
172
|
}
|
|
188
173
|
|
|
189
174
|
return (
|
|
190
|
-
<Sheet.Root
|
|
175
|
+
<Sheet.Root space={space} sheet={sheet}>
|
|
191
176
|
<Sheet.Columns
|
|
192
177
|
columns={sheet.columns}
|
|
193
178
|
sizes={columnSizes}
|
|
@@ -198,18 +183,19 @@ export const Columns = () => {
|
|
|
198
183
|
};
|
|
199
184
|
|
|
200
185
|
export const Main = () => {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
186
|
+
const space = useSpace();
|
|
187
|
+
const graph = useComputeGraph(space);
|
|
188
|
+
const sheet = useTestSheet(space, graph);
|
|
203
189
|
if (!sheet || !space) {
|
|
204
190
|
return null;
|
|
205
191
|
}
|
|
206
192
|
|
|
207
193
|
return (
|
|
208
|
-
<Sheet.Root
|
|
194
|
+
<Sheet.Root space={space} sheet={sheet}>
|
|
209
195
|
<Sheet.Grid
|
|
210
196
|
size={{
|
|
211
197
|
numRows: 50,
|
|
212
|
-
|
|
198
|
+
numCols: 26,
|
|
213
199
|
}}
|
|
214
200
|
rows={sheet.rows}
|
|
215
201
|
columns={sheet.columns}
|
|
@@ -262,30 +248,3 @@ export const GridLayout = () => {
|
|
|
262
248
|
const Cell = ({ className, label }: { className?: string; label: string }) => (
|
|
263
249
|
<div className={mx('flex items-center justify-center border', className)}>{label}</div>
|
|
264
250
|
);
|
|
265
|
-
|
|
266
|
-
const useTestSheet = () => {
|
|
267
|
-
const { graphs, setGraph } = useContext(ComputeGraphContext);
|
|
268
|
-
const [sheet, setSheet] = useState<EchoReactiveObject<SheetType>>();
|
|
269
|
-
useEffect(() => {
|
|
270
|
-
const t = setTimeout(async () => {
|
|
271
|
-
const client = new Client();
|
|
272
|
-
await client.initialize();
|
|
273
|
-
await client.halo.createIdentity();
|
|
274
|
-
const space = await client.spaces.create();
|
|
275
|
-
client.addTypes([SheetType]);
|
|
276
|
-
|
|
277
|
-
const graph = graphs[space.id] ?? createComputeGraph();
|
|
278
|
-
if (!graphs[space.id]) {
|
|
279
|
-
setGraph(space.id, graph);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const sheet = await createTestSheet({ graph });
|
|
283
|
-
space.db.add(sheet);
|
|
284
|
-
setSheet(sheet);
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
return () => clearTimeout(t);
|
|
288
|
-
}, []);
|
|
289
|
-
|
|
290
|
-
return sheet;
|
|
291
|
-
};
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
rangeToA1Notation,
|
|
72
72
|
addressToIndex,
|
|
73
73
|
addressFromIndex,
|
|
74
|
-
} from '../../
|
|
74
|
+
} from '../../defs';
|
|
75
75
|
import {
|
|
76
76
|
CellEditor,
|
|
77
77
|
type CellRangeNotifier,
|
|
@@ -138,7 +138,7 @@ const SheetRoot = ({ children, ...props }: PropsWithChildren<SheetContextProps>)
|
|
|
138
138
|
|
|
139
139
|
type SheetMainProps = ThemedClassName<Partial<GridSize>>;
|
|
140
140
|
|
|
141
|
-
const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows,
|
|
141
|
+
const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows, numCols }, forwardRef) => {
|
|
142
142
|
const { model, cursor, setCursor, setRange, setEditing } = useSheetContext();
|
|
143
143
|
|
|
144
144
|
// Scrolling.
|
|
@@ -263,8 +263,8 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
263
263
|
ref={columnsRef}
|
|
264
264
|
columns={columns}
|
|
265
265
|
sizes={columnSizes}
|
|
266
|
-
selected={cursor?.
|
|
267
|
-
onSelect={(
|
|
266
|
+
selected={cursor?.col}
|
|
267
|
+
onSelect={(col) => setCursor(cursor?.col === col ? undefined : { row: -1, col })}
|
|
268
268
|
onResize={handleResizeColumn}
|
|
269
269
|
onMove={handleMoveColumns}
|
|
270
270
|
/>
|
|
@@ -274,13 +274,13 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
274
274
|
rows={rows}
|
|
275
275
|
sizes={rowSizes}
|
|
276
276
|
selected={cursor?.row}
|
|
277
|
-
onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row,
|
|
277
|
+
onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row, col: -1 })}
|
|
278
278
|
onResize={handleResizeRow}
|
|
279
279
|
onMove={handleMoveRows}
|
|
280
280
|
/>
|
|
281
281
|
<SheetGrid
|
|
282
282
|
ref={contentRef}
|
|
283
|
-
size={{ numRows: numRows ?? rows.length,
|
|
283
|
+
size={{ numRows: numRows ?? rows.length, numCols: numCols ?? columns.length }}
|
|
284
284
|
rows={rows}
|
|
285
285
|
columns={columns}
|
|
286
286
|
rowSizes={rowSizes}
|
|
@@ -885,9 +885,9 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
|
|
|
885
885
|
|
|
886
886
|
{/* Grid cells. */}
|
|
887
887
|
{rowRange.map(({ row, top, height }) => {
|
|
888
|
-
return columnRange.map(({
|
|
888
|
+
return columnRange.map(({ col, left, width }) => {
|
|
889
889
|
const style: CSSProperties = { position: 'absolute', top, left, width, height };
|
|
890
|
-
const cell = { row,
|
|
890
|
+
const cell: CellAddress = { row, col };
|
|
891
891
|
const id = addressToA1Notation(cell);
|
|
892
892
|
const idx = addressToIndex(model.sheet, cell);
|
|
893
893
|
const active = posEquals(cursor, cell);
|
|
@@ -1082,10 +1082,11 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
|
|
|
1082
1082
|
notifier.current?.(rangeToA1Notation(range));
|
|
1083
1083
|
}
|
|
1084
1084
|
}, [range]);
|
|
1085
|
+
|
|
1085
1086
|
const extension = useMemo(
|
|
1086
1087
|
() => [
|
|
1087
1088
|
editorKeys({ onNav, onClose }),
|
|
1088
|
-
sheetExtension({ functions: model.
|
|
1089
|
+
sheetExtension({ functions: model.graph.getFunctions() }),
|
|
1089
1090
|
rangeExtension((fn) => (notifier.current = fn)),
|
|
1090
1091
|
],
|
|
1091
1092
|
[model],
|
|
@@ -1109,12 +1110,13 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
|
|
|
1109
1110
|
|
|
1110
1111
|
const SheetStatusBar = () => {
|
|
1111
1112
|
const { model, cursor, range } = useSheetContext();
|
|
1113
|
+
|
|
1112
1114
|
let value;
|
|
1113
1115
|
let isFormula = false;
|
|
1114
1116
|
if (cursor) {
|
|
1115
1117
|
value = model.getCellValue(cursor);
|
|
1116
1118
|
if (typeof value === 'string' && value.charAt(0) === '=') {
|
|
1117
|
-
value = model.
|
|
1119
|
+
value = model.graph.mapFunctionBindingFromId(model.mapFormulaIndicesToRefs(value));
|
|
1118
1120
|
isFormula = true;
|
|
1119
1121
|
} else if (value != null) {
|
|
1120
1122
|
value = String(value);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type MouseEvent, useEffect, useState } from 'react';
|
|
6
6
|
|
|
7
|
-
import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Notation } from '../../
|
|
7
|
+
import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Notation } from '../../defs';
|
|
8
8
|
|
|
9
9
|
// export type Bounds = Pick<DOMRect, 'left' | 'top' | 'width' | 'height'>;
|
|
10
10
|
// export type Dimension = Pick<DOMRect, 'width' | 'height'>;
|
|
@@ -12,7 +12,7 @@ import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Not
|
|
|
12
12
|
export type SizeMap = Record<string, number>;
|
|
13
13
|
|
|
14
14
|
export type RowPosition = { row: number } & Pick<DOMRect, 'top' | 'height'>;
|
|
15
|
-
export type ColumnPosition = {
|
|
15
|
+
export type ColumnPosition = { col: number } & Pick<DOMRect, 'left' | 'width'>;
|
|
16
16
|
|
|
17
17
|
export const axisWidth = 'calc(var(--rail-size)-2px)';
|
|
18
18
|
export const axisHeight = 34;
|
|
@@ -88,7 +88,7 @@ export const useGridLayout = ({
|
|
|
88
88
|
const width = columnSizes?.[idx] ?? defaultWidth;
|
|
89
89
|
const left = x;
|
|
90
90
|
x += width - 1;
|
|
91
|
-
return {
|
|
91
|
+
return { col: i, left, width };
|
|
92
92
|
}),
|
|
93
93
|
);
|
|
94
94
|
}, [columns, columnSizes]);
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
import { type KeyboardEvent, type MouseEventHandler, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { getCellAtPointer } from './grid';
|
|
8
|
-
import { type CellAddress, type CellRange, posEquals } from '../../
|
|
8
|
+
import { type CellAddress, type CellRange, posEquals } from '../../defs';
|
|
9
9
|
|
|
10
10
|
export type GridSize = {
|
|
11
11
|
numRows: number;
|
|
12
|
-
|
|
12
|
+
numCols: number;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -38,14 +38,14 @@ export const handleNav = (
|
|
|
38
38
|
break;
|
|
39
39
|
}
|
|
40
40
|
case 'ArrowLeft': {
|
|
41
|
-
if (opposite.
|
|
42
|
-
opposite.
|
|
41
|
+
if (opposite.col > 0) {
|
|
42
|
+
opposite.col -= 1;
|
|
43
43
|
}
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
46
46
|
case 'ArrowRight': {
|
|
47
|
-
if (opposite.
|
|
48
|
-
opposite.
|
|
47
|
+
if (opposite.col < size.numCols - 1) {
|
|
48
|
+
opposite.col += 1;
|
|
49
49
|
}
|
|
50
50
|
break;
|
|
51
51
|
}
|
|
@@ -64,41 +64,41 @@ export const handleNav = (
|
|
|
64
64
|
export const handleArrowNav = (
|
|
65
65
|
ev: Pick<KeyboardEvent<HTMLInputElement>, 'key' | 'metaKey'>,
|
|
66
66
|
cursor: CellAddress | undefined,
|
|
67
|
-
{ numRows,
|
|
67
|
+
{ numRows, numCols }: GridSize,
|
|
68
68
|
): CellAddress | undefined => {
|
|
69
69
|
switch (ev.key) {
|
|
70
70
|
case 'ArrowUp':
|
|
71
71
|
if (cursor === undefined) {
|
|
72
|
-
return { row: 0,
|
|
72
|
+
return { row: 0, col: 0 };
|
|
73
73
|
} else if (cursor.row > 0) {
|
|
74
|
-
return { row: ev.metaKey ? 0 : cursor.row - 1,
|
|
74
|
+
return { row: ev.metaKey ? 0 : cursor.row - 1, col: cursor.col };
|
|
75
75
|
}
|
|
76
76
|
break;
|
|
77
77
|
case 'ArrowDown':
|
|
78
78
|
if (cursor === undefined) {
|
|
79
|
-
return { row: 0,
|
|
79
|
+
return { row: 0, col: 0 };
|
|
80
80
|
} else if (cursor.row < numRows - 1) {
|
|
81
|
-
return { row: ev.metaKey ? numRows - 1 : cursor.row + 1,
|
|
81
|
+
return { row: ev.metaKey ? numRows - 1 : cursor.row + 1, col: cursor.col };
|
|
82
82
|
}
|
|
83
83
|
break;
|
|
84
84
|
case 'ArrowLeft':
|
|
85
85
|
if (cursor === undefined) {
|
|
86
|
-
return { row: 0,
|
|
87
|
-
} else if (cursor.
|
|
88
|
-
return { row: cursor.row,
|
|
86
|
+
return { row: 0, col: 0 };
|
|
87
|
+
} else if (cursor.col > 0) {
|
|
88
|
+
return { row: cursor.row, col: ev.metaKey ? 0 : cursor.col - 1 };
|
|
89
89
|
}
|
|
90
90
|
break;
|
|
91
91
|
case 'ArrowRight':
|
|
92
92
|
if (cursor === undefined) {
|
|
93
|
-
return { row: 0,
|
|
94
|
-
} else if (cursor.
|
|
95
|
-
return { row: cursor.row,
|
|
93
|
+
return { row: 0, col: 0 };
|
|
94
|
+
} else if (cursor.col < numCols - 1) {
|
|
95
|
+
return { row: cursor.row, col: ev.metaKey ? numCols - 1 : cursor.col + 1 };
|
|
96
96
|
}
|
|
97
97
|
break;
|
|
98
98
|
case 'Home':
|
|
99
|
-
return { row: 0,
|
|
99
|
+
return { row: 0, col: 0 };
|
|
100
100
|
case 'End':
|
|
101
|
-
return { row: numRows - 1,
|
|
101
|
+
return { row: numRows - 1, col: numCols - 1 };
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
104
|
|