@dxos/plugin-sheet 0.6.12-staging.e11e696 → 0.6.13-main.041e8aa
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-NDNIS44E.mjs +265 -0
- package/dist/lib/browser/SheetContainer-NDNIS44E.mjs.map +7 -0
- package/dist/lib/browser/chunk-AQSGDA4X.mjs +1614 -0
- package/dist/lib/browser/chunk-AQSGDA4X.mjs.map +7 -0
- package/dist/lib/browser/{chunk-QILRZNE5.mjs → chunk-D3QTX46O.mjs} +4 -5
- package/dist/lib/browser/chunk-D3QTX46O.mjs.map +7 -0
- package/dist/lib/browser/{chunk-WZMOZKQZ.mjs → chunk-GKI67SEF.mjs} +19 -25
- package/dist/lib/browser/chunk-GKI67SEF.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +14 -19
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types.mjs +4 -8
- package/dist/lib/node/SheetContainer-YSQGJD7K.cjs +276 -0
- package/dist/lib/node/SheetContainer-YSQGJD7K.cjs.map +7 -0
- package/dist/lib/node/chunk-6F43RV45.cjs +1610 -0
- package/dist/lib/node/chunk-6F43RV45.cjs.map +7 -0
- package/dist/lib/node/{chunk-AOP42UAA.cjs → chunk-ER3PM7GD.cjs} +25 -33
- package/dist/lib/node/chunk-ER3PM7GD.cjs.map +7 -0
- package/dist/lib/node/{chunk-BNARJ5GM.cjs → chunk-QIFIGEKV.cjs} +6 -7
- package/dist/lib/node/chunk-QIFIGEKV.cjs.map +7 -0
- package/dist/lib/node/index.cjs +36 -40
- package/dist/lib/node/index.cjs.map +4 -4
- 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 +8 -12
- package/dist/lib/node/types.cjs.map +2 -2
- package/dist/lib/node-esm/SheetContainer-M7WRMZDU.mjs +266 -0
- package/dist/lib/node-esm/SheetContainer-M7WRMZDU.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-ELTFPX5B.mjs +1615 -0
- package/dist/lib/node-esm/chunk-ELTFPX5B.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-IU2L277A.mjs → chunk-VCYJWE3O.mjs} +4 -5
- package/dist/lib/node-esm/chunk-VCYJWE3O.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-RR2AO4SM.mjs → chunk-ZVLLQ2PJ.mjs} +19 -25
- package/dist/lib/node-esm/chunk-ZVLLQ2PJ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +14 -19
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/meta.mjs +1 -1
- package/dist/lib/node-esm/types.mjs +4 -8
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/components/FunctionEditor/FunctionEditor.d.ts +3 -0
- package/dist/types/src/components/FunctionEditor/FunctionEditor.d.ts.map +1 -0
- package/dist/types/src/components/FunctionEditor/index.d.ts +2 -0
- package/dist/types/src/components/FunctionEditor/index.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/GridSheet.d.ts +1 -8
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -1
- package/dist/types/src/components/{CellEditor/CellEditor.stories.d.ts → GridSheet/SheetCellEditor.stories.d.ts} +2 -2
- package/dist/types/src/components/GridSheet/SheetCellEditor.stories.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/index.d.ts +2 -0
- package/dist/types/src/components/GridSheet/index.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/util.d.ts +11 -2
- package/dist/types/src/components/GridSheet/util.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.d.ts +6 -0
- package/dist/types/src/components/SheetContainer/SheetContainer.d.ts.map +1 -0
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts +11 -0
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts.map +1 -0
- package/dist/types/src/components/SheetContainer/index.d.ts +3 -0
- package/dist/types/src/components/SheetContainer/index.d.ts.map +1 -0
- package/dist/types/src/components/SheetContext/SheetContext.d.ts +27 -0
- package/dist/types/src/components/SheetContext/SheetContext.d.ts.map +1 -0
- package/dist/types/src/components/SheetContext/index.d.ts +2 -0
- package/dist/types/src/components/SheetContext/index.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +31 -17
- 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 +3 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/editor/extension.d.ts.map +1 -0
- package/dist/types/src/extensions/editor/extension.test.d.ts.map +1 -0
- package/dist/types/src/extensions/editor/index.d.ts +2 -0
- package/dist/types/src/extensions/editor/index.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +1 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/threads.d.ts +8 -0
- package/dist/types/src/hooks/threads.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +3 -6
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/{components/Sheet → model}/decorations.d.ts +1 -0
- package/dist/types/src/model/decorations.d.ts.map +1 -0
- package/dist/types/src/model/formatting-model.d.ts +3 -0
- package/dist/types/src/model/formatting-model.d.ts.map +1 -1
- package/dist/types/src/model/index.d.ts +1 -0
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/sheet-model.d.ts +3 -2
- package/dist/types/src/model/sheet-model.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +13 -28
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +36 -39
- package/src/SheetPlugin.tsx +3 -2
- package/src/components/FunctionEditor/FunctionEditor.tsx +45 -0
- package/src/components/FunctionEditor/index.ts +5 -0
- package/src/components/GridSheet/GridSheet.stories.tsx +7 -2
- package/src/components/GridSheet/GridSheet.tsx +77 -69
- package/src/components/{CellEditor/CellEditor.stories.tsx → GridSheet/SheetCellEditor.stories.tsx} +2 -2
- package/src/components/{Sheet → GridSheet}/index.ts +1 -1
- package/src/components/GridSheet/util.ts +63 -27
- package/src/components/SheetContainer/SheetContainer.stories.tsx +40 -0
- package/src/components/SheetContainer/SheetContainer.tsx +52 -0
- package/src/components/SheetContainer/index.ts +7 -0
- package/src/components/{Sheet/sheet-context.tsx → SheetContext/SheetContext.tsx} +47 -27
- package/src/components/SheetContext/index.ts +5 -0
- package/src/components/Toolbar/Toolbar.tsx +127 -86
- package/src/components/index.ts +2 -1
- package/src/defs/util.ts +1 -1
- package/src/extensions/compute.stories.tsx +4 -4
- package/src/{components/CellEditor → extensions/editor}/index.ts +0 -1
- package/src/extensions/index.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/{components/Sheet/threads.tsx → hooks/threads.ts} +26 -84
- package/src/{meta.tsx → meta.ts} +3 -3
- package/src/{components/Sheet → model}/decorations.ts +2 -0
- package/src/model/formatting-model.ts +12 -9
- package/src/model/index.ts +1 -0
- package/src/model/sheet-model.test.ts +1 -3
- package/src/model/sheet-model.ts +13 -11
- package/src/types.ts +9 -35
- package/dist/lib/browser/SheetContainer-LG77O4RM.mjs +0 -262
- package/dist/lib/browser/SheetContainer-LG77O4RM.mjs.map +0 -7
- package/dist/lib/browser/chunk-CHQAW4F4.mjs +0 -2705
- package/dist/lib/browser/chunk-CHQAW4F4.mjs.map +0 -7
- package/dist/lib/browser/chunk-QILRZNE5.mjs.map +0 -7
- package/dist/lib/browser/chunk-WZMOZKQZ.mjs.map +0 -7
- package/dist/lib/node/SheetContainer-OZ7DHH4L.cjs +0 -280
- package/dist/lib/node/SheetContainer-OZ7DHH4L.cjs.map +0 -7
- package/dist/lib/node/chunk-5FTFZL5W.cjs +0 -2690
- package/dist/lib/node/chunk-5FTFZL5W.cjs.map +0 -7
- package/dist/lib/node/chunk-AOP42UAA.cjs.map +0 -7
- package/dist/lib/node/chunk-BNARJ5GM.cjs.map +0 -7
- package/dist/lib/node-esm/SheetContainer-4XS2G25Z.mjs +0 -263
- package/dist/lib/node-esm/SheetContainer-4XS2G25Z.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-KK3XL37M.mjs +0 -2706
- package/dist/lib/node-esm/chunk-KK3XL37M.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-RR2AO4SM.mjs.map +0 -7
- package/dist/types/src/components/CellEditor/CellEditor.d.ts +0 -34
- package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +0 -1
- package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +0 -1
- package/dist/types/src/components/CellEditor/extension.d.ts.map +0 -1
- package/dist/types/src/components/CellEditor/extension.test.d.ts.map +0 -1
- package/dist/types/src/components/CellEditor/index.d.ts +0 -3
- package/dist/types/src/components/CellEditor/index.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/Sheet.d.ts +0 -55
- package/dist/types/src/components/Sheet/Sheet.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/Sheet.stories.d.ts +0 -53
- package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/decorations.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/grid.d.ts +0 -52
- package/dist/types/src/components/Sheet/grid.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/index.d.ts +0 -2
- package/dist/types/src/components/Sheet/index.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/nav.d.ts +0 -29
- package/dist/types/src/components/Sheet/nav.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/sheet-context.d.ts +0 -26
- package/dist/types/src/components/Sheet/sheet-context.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/threads.d.ts +0 -2
- package/dist/types/src/components/Sheet/threads.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/util.d.ts +0 -18
- package/dist/types/src/components/Sheet/util.d.ts.map +0 -1
- package/dist/types/src/components/SheetContainer.d.ts +0 -8
- package/dist/types/src/components/SheetContainer.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/common.d.ts +0 -20
- package/dist/types/src/components/Toolbar/common.d.ts.map +0 -1
- package/src/components/CellEditor/CellEditor.tsx +0 -163
- package/src/components/Sheet/Sheet.stories.tsx +0 -251
- package/src/components/Sheet/Sheet.tsx +0 -1215
- package/src/components/Sheet/grid.ts +0 -191
- package/src/components/Sheet/nav.ts +0 -157
- package/src/components/Sheet/util.ts +0 -56
- package/src/components/SheetContainer.tsx +0 -86
- package/src/components/Toolbar/common.tsx +0 -72
- /package/dist/types/src/{components/CellEditor → extensions/editor}/extension.d.ts +0 -0
- /package/dist/types/src/{components/CellEditor → extensions/editor}/extension.test.d.ts +0 -0
- /package/src/{components/CellEditor → extensions/editor}/extension.test.ts +0 -0
- /package/src/{components/CellEditor → extensions/editor}/extension.ts +0 -0
|
@@ -2,70 +2,66 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { useCallback, useMemo, useRef } from 'react';
|
|
5
|
+
import React, { useCallback, useMemo, useRef, type FocusEvent, type WheelEvent } from 'react';
|
|
6
6
|
|
|
7
|
+
import { useAttention } from '@dxos/react-ui-attention';
|
|
7
8
|
import {
|
|
8
9
|
type DxGridElement,
|
|
9
10
|
Grid,
|
|
10
11
|
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
12
|
editorKeys,
|
|
26
13
|
type EditorKeysProps,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} from '
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
14
|
+
GridCellEditor,
|
|
15
|
+
closestCell,
|
|
16
|
+
} from '@dxos/react-ui-grid';
|
|
17
|
+
|
|
18
|
+
import { colLabelCell, dxGridCellIndexToSheetCellAddress, rowLabelCell, useSheetModelDxGridProps } from './util';
|
|
19
|
+
import { rangeToA1Notation, type CellRange, DEFAULT_COLUMNS, DEFAULT_ROWS } from '../../defs';
|
|
20
|
+
import { rangeExtension, sheetExtension, type CellRangeNotifier } from '../../extensions';
|
|
21
|
+
import { useUpdateFocusedCellOnThreadSelection } from '../../hooks';
|
|
22
|
+
import { useSheetContext } from '../SheetContext';
|
|
23
|
+
|
|
24
|
+
const initialCells = {
|
|
25
|
+
grid: {},
|
|
26
|
+
frozenColsStart: [...Array(64)].reduce((acc, _, i) => {
|
|
27
|
+
acc[`0,${i}`] = rowLabelCell(i);
|
|
28
|
+
return acc;
|
|
29
|
+
}, {}),
|
|
30
|
+
frozenRowsStart: [...Array(12)].reduce((acc, _, i) => {
|
|
31
|
+
acc[`${i},0`] = colLabelCell(i);
|
|
32
|
+
return acc;
|
|
33
|
+
}, {}),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const frozen = {
|
|
37
|
+
frozenColsStart: 1,
|
|
38
|
+
frozenRowsStart: 1,
|
|
50
39
|
};
|
|
51
40
|
|
|
52
|
-
const sheetRowDefault = { size: 32, resizeable: true };
|
|
53
|
-
const sheetColDefault = { size: 180, resizeable: true };
|
|
41
|
+
const sheetRowDefault = { grid: { size: 32, resizeable: true } };
|
|
42
|
+
const sheetColDefault = { frozenColsStart: { size: 48 }, grid: { size: 180, resizeable: true } };
|
|
54
43
|
|
|
55
|
-
const
|
|
56
|
-
model,
|
|
57
|
-
formatting,
|
|
58
|
-
__gridScope,
|
|
59
|
-
}: GridScopedProps<{ model: SheetModel; formatting: FormattingModel }>) => {
|
|
60
|
-
const { editing, setEditing } = useGridContext('GridSheetCellEditor', __gridScope);
|
|
44
|
+
export const GridSheet = () => {
|
|
45
|
+
const { id, model, formatting, editing, setEditing, setCursor, setRange } = useSheetContext();
|
|
61
46
|
const dxGrid = useRef<DxGridElement | null>(null);
|
|
62
47
|
const rangeNotifier = useRef<CellRangeNotifier>();
|
|
48
|
+
const { hasAttention } = useAttention(id);
|
|
49
|
+
|
|
50
|
+
const handleFocus = useCallback(
|
|
51
|
+
(event: FocusEvent) => {
|
|
52
|
+
if (!editing) {
|
|
53
|
+
const cell = closestCell(event.target);
|
|
54
|
+
setCursor(cell && cell.plane === 'grid' ? { col: cell.col, row: cell.row } : undefined);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
[editing],
|
|
58
|
+
);
|
|
63
59
|
|
|
64
60
|
// TODO(burdon): Validate formula before closing: hf.validateFormula();
|
|
65
61
|
const handleClose = useCallback<NonNullable<EditorKeysProps['onClose']> | NonNullable<EditorKeysProps['onNav']>>(
|
|
66
62
|
(value, { key, shift }) => {
|
|
67
63
|
if (value !== undefined) {
|
|
68
|
-
model.setValue(dxGridCellIndexToSheetCellAddress(editing)
|
|
64
|
+
model.setValue(dxGridCellIndexToSheetCellAddress(editing!.index), value);
|
|
69
65
|
}
|
|
70
66
|
setEditing(null);
|
|
71
67
|
const axis = ['Enter', 'ArrowUp', 'ArrowDown'].includes(key)
|
|
@@ -96,18 +92,30 @@ const GridSheetImpl = ({
|
|
|
96
92
|
|
|
97
93
|
const handleSelect = useCallback<NonNullable<GridContentProps['onSelect']>>(
|
|
98
94
|
({ minCol, maxCol, minRow, maxRow }) => {
|
|
95
|
+
const range: CellRange = { from: { col: minCol, row: minRow } };
|
|
96
|
+
if (minCol !== maxCol || minRow !== maxRow) {
|
|
97
|
+
range.to = { col: maxCol, row: maxRow };
|
|
98
|
+
}
|
|
99
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
100
|
// Update range selection in formula.
|
|
105
101
|
rangeNotifier.current?.(rangeToA1Notation(range));
|
|
102
|
+
} else {
|
|
103
|
+
// Setting range while editing causes focus to move to null, avoid doing so.
|
|
104
|
+
setRange(range.to ? range : undefined);
|
|
106
105
|
}
|
|
107
106
|
},
|
|
108
107
|
[editing],
|
|
109
108
|
);
|
|
110
109
|
|
|
110
|
+
const handleWheel = useCallback(
|
|
111
|
+
(event: WheelEvent) => {
|
|
112
|
+
if (!hasAttention) {
|
|
113
|
+
event.stopPropagation();
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
[hasAttention],
|
|
117
|
+
);
|
|
118
|
+
|
|
111
119
|
const { columns, rows } = useSheetModelDxGridProps(dxGrid, model, formatting);
|
|
112
120
|
|
|
113
121
|
const extension = useMemo(
|
|
@@ -119,35 +127,35 @@ const GridSheetImpl = ({
|
|
|
119
127
|
[model, handleClose, editing],
|
|
120
128
|
);
|
|
121
129
|
|
|
130
|
+
const getCellContent = useCallback(
|
|
131
|
+
(index: string) => {
|
|
132
|
+
const cell = dxGridCellIndexToSheetCellAddress(index);
|
|
133
|
+
return model.getCellText(cell);
|
|
134
|
+
},
|
|
135
|
+
[model],
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
useUpdateFocusedCellOnThreadSelection(model, dxGrid);
|
|
139
|
+
|
|
122
140
|
return (
|
|
123
141
|
<>
|
|
124
|
-
<
|
|
142
|
+
<GridCellEditor getCellContent={getCellContent} extension={extension} />
|
|
125
143
|
<Grid.Content
|
|
126
|
-
initialCells={
|
|
144
|
+
initialCells={initialCells}
|
|
145
|
+
limitColumns={DEFAULT_COLUMNS}
|
|
146
|
+
limitRows={DEFAULT_ROWS}
|
|
127
147
|
columns={columns}
|
|
128
148
|
rows={rows}
|
|
129
149
|
onAxisResize={handleAxisResize}
|
|
130
150
|
onSelect={handleSelect}
|
|
131
151
|
rowDefault={sheetRowDefault}
|
|
132
152
|
columnDefault={sheetColDefault}
|
|
153
|
+
frozen={frozen}
|
|
154
|
+
onFocus={handleFocus}
|
|
155
|
+
onWheelCapture={handleWheel}
|
|
156
|
+
className='[--dx-grid-base:var(--surface-bg)]'
|
|
133
157
|
ref={dxGrid}
|
|
134
158
|
/>
|
|
135
159
|
</>
|
|
136
160
|
);
|
|
137
161
|
};
|
|
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
|
-
};
|
package/src/components/{CellEditor/CellEditor.stories.tsx → GridSheet/SheetCellEditor.stories.tsx}
RENAMED
|
@@ -9,12 +9,12 @@ import React, { useEffect, useMemo, useState } from 'react';
|
|
|
9
9
|
import { Client } from '@dxos/client';
|
|
10
10
|
import { createDocAccessor, type EchoReactiveObject } from '@dxos/client/echo';
|
|
11
11
|
import { automerge } from '@dxos/react-ui-editor';
|
|
12
|
+
import { CellEditor, type CellEditorProps } from '@dxos/react-ui-grid';
|
|
12
13
|
import { withTheme } from '@dxos/storybook-utils';
|
|
13
14
|
|
|
14
15
|
import { HyperFormula } from '#hyperformula';
|
|
15
|
-
import { CellEditor, type CellEditorProps } from './CellEditor';
|
|
16
|
-
import { sheetExtension } from './extension';
|
|
17
16
|
import { createSheet } from '../../defs';
|
|
17
|
+
import { sheetExtension } from '../../extensions';
|
|
18
18
|
import { defaultFunctions } from '../../graph';
|
|
19
19
|
import { SheetType } from '../../types';
|
|
20
20
|
|
|
@@ -6,23 +6,22 @@ import { type MutableRefObject, useEffect, useLayoutEffect, useState } from 'rea
|
|
|
6
6
|
|
|
7
7
|
import { createDocAccessor } from '@dxos/react-client/echo';
|
|
8
8
|
import {
|
|
9
|
-
type GridEditing,
|
|
10
9
|
type GridContentProps,
|
|
11
10
|
type DxGridElement,
|
|
12
|
-
type DxGridCells,
|
|
13
11
|
type DxGridAxisMeta,
|
|
14
|
-
type
|
|
12
|
+
type DxGridPlane,
|
|
13
|
+
type DxGridPlaneRange,
|
|
14
|
+
type DxGridPlaneCells,
|
|
15
|
+
colToA1Notation,
|
|
16
|
+
rowToA1Notation,
|
|
15
17
|
} from '@dxos/react-ui-grid';
|
|
16
18
|
import { mx } from '@dxos/react-ui-theme';
|
|
17
19
|
|
|
18
20
|
import { type CellAddress } from '../../defs';
|
|
19
21
|
import { type SheetModel, type FormattingModel } from '../../model';
|
|
20
22
|
|
|
21
|
-
export const dxGridCellIndexToSheetCellAddress = (
|
|
22
|
-
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
const [colStr, rowStr] = gridEditing.index.split(',');
|
|
23
|
+
export const dxGridCellIndexToSheetCellAddress = (index: string): CellAddress => {
|
|
24
|
+
const [colStr, rowStr] = index.split(',');
|
|
26
25
|
return {
|
|
27
26
|
col: parseInt(colStr),
|
|
28
27
|
row: parseInt(rowStr),
|
|
@@ -30,40 +29,77 @@ export const dxGridCellIndexToSheetCellAddress = (gridEditing: GridEditing): Cel
|
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
const createDxGridColumns = (model: SheetModel): DxGridAxisMeta => {
|
|
33
|
-
return model.sheet.columns.reduce(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
return model.sheet.columns.reduce(
|
|
33
|
+
(acc: DxGridAxisMeta, columnId, numericIndex) => {
|
|
34
|
+
if (model.sheet.columnMeta[columnId] && model.sheet.columnMeta[columnId].size) {
|
|
35
|
+
acc.grid[numericIndex] = { size: model.sheet.columnMeta[columnId].size, resizeable: true };
|
|
36
|
+
}
|
|
37
|
+
return acc;
|
|
38
|
+
},
|
|
39
|
+
{ grid: {} },
|
|
40
|
+
);
|
|
39
41
|
};
|
|
40
42
|
|
|
41
43
|
const createDxGridRows = (model: SheetModel): DxGridAxisMeta => {
|
|
42
|
-
return model.sheet.rows.reduce(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
return model.sheet.rows.reduce(
|
|
45
|
+
(acc: DxGridAxisMeta, rowId, numericIndex) => {
|
|
46
|
+
if (model.sheet.rowMeta[rowId] && model.sheet.rowMeta[rowId].size) {
|
|
47
|
+
acc.grid[numericIndex] = { size: model.sheet.rowMeta[rowId].size, resizeable: true };
|
|
48
|
+
}
|
|
49
|
+
return acc;
|
|
50
|
+
},
|
|
51
|
+
{ grid: {} },
|
|
52
|
+
);
|
|
48
53
|
};
|
|
49
54
|
|
|
50
|
-
const
|
|
55
|
+
const gridCellGetter = (model: SheetModel, formatting: FormattingModel) => {
|
|
51
56
|
// TODO(thure): Actually use the cache.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return (nextBounds: DxGridRange): DxGridCells => {
|
|
57
|
+
const cachedGridCells: DxGridPlaneCells = {};
|
|
58
|
+
return (nextBounds: DxGridPlaneRange): DxGridPlaneCells => {
|
|
55
59
|
[...Array(nextBounds.end.col - nextBounds.start.col)].forEach((_, c0) => {
|
|
56
60
|
return [...Array(nextBounds.end.row - nextBounds.start.row)].forEach((_, r0) => {
|
|
57
61
|
const col = nextBounds.start.col + c0;
|
|
58
62
|
const row = nextBounds.start.row + r0;
|
|
59
63
|
const cell = formatting.getFormatting({ col, row });
|
|
60
64
|
if (cell.value) {
|
|
61
|
-
|
|
65
|
+
cachedGridCells;
|
|
66
|
+
cachedGridCells[`${col},${row}`] = { value: cell.value, className: mx(cell.classNames) };
|
|
62
67
|
}
|
|
63
68
|
});
|
|
64
69
|
});
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
return cachedGridCells;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const rowLabelCell = (row: number) => ({
|
|
75
|
+
value: rowToA1Notation(row),
|
|
76
|
+
className: 'text-end !pie-1',
|
|
77
|
+
resizeHandle: 'row',
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export const colLabelCell = (col: number) => ({ value: colToA1Notation(col), resizeHandle: 'col' });
|
|
81
|
+
|
|
82
|
+
const cellGetter = (model: SheetModel, formatting: FormattingModel) => {
|
|
83
|
+
const getGridCells = gridCellGetter(model, formatting);
|
|
84
|
+
return (nextBounds: DxGridPlaneRange, plane: DxGridPlane): DxGridPlaneCells => {
|
|
85
|
+
switch (plane) {
|
|
86
|
+
case 'grid':
|
|
87
|
+
return getGridCells(nextBounds);
|
|
88
|
+
case 'frozenColsStart':
|
|
89
|
+
return [...Array(nextBounds.end.row - nextBounds.start.row)].reduce((acc, _, r0) => {
|
|
90
|
+
const r = nextBounds.start.row + r0;
|
|
91
|
+
acc[`0,${r}`] = rowLabelCell(r);
|
|
92
|
+
return acc;
|
|
93
|
+
}, {});
|
|
94
|
+
case 'frozenRowsStart':
|
|
95
|
+
return [...Array(nextBounds.end.col - nextBounds.start.col)].reduce((acc, _, c0) => {
|
|
96
|
+
const c = nextBounds.start.col + c0;
|
|
97
|
+
acc[`${c},0`] = colLabelCell(c);
|
|
98
|
+
return acc;
|
|
99
|
+
}, {});
|
|
100
|
+
default:
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
67
103
|
};
|
|
68
104
|
};
|
|
69
105
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { useSpace } from '@dxos/react-client/echo';
|
|
8
|
+
import { withClientProvider } from '@dxos/react-client/testing';
|
|
9
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
10
|
+
|
|
11
|
+
import { SheetContainer } from './SheetContainer';
|
|
12
|
+
import { useComputeGraph } from '../../hooks';
|
|
13
|
+
import { useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
14
|
+
import { SheetType } from '../../types';
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
title: 'plugin-sheet/SheetContainer',
|
|
18
|
+
component: SheetContainer,
|
|
19
|
+
decorators: [
|
|
20
|
+
withClientProvider({ types: [SheetType], createSpace: true }),
|
|
21
|
+
withComputeGraphDecorator(),
|
|
22
|
+
withTheme,
|
|
23
|
+
withLayout({
|
|
24
|
+
fullscreen: true,
|
|
25
|
+
tooltips: true,
|
|
26
|
+
classNames: 'grid grid-cols-1 grid-rows-[min-content_minmax(0,1fr)_min-content]',
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Basic = () => {
|
|
32
|
+
const space = useSpace();
|
|
33
|
+
const graph = useComputeGraph(space);
|
|
34
|
+
const sheet = useTestSheet(space, graph);
|
|
35
|
+
if (!sheet || !graph) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return <SheetContainer graph={graph} sheet={sheet} role='article' />;
|
|
40
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
+
|
|
9
|
+
import { FunctionEditor } from '../FunctionEditor';
|
|
10
|
+
import { GridSheet } from '../GridSheet';
|
|
11
|
+
import { SheetProvider, type SheetProviderProps } from '../SheetContext';
|
|
12
|
+
import { Toolbar, type ToolbarAction } from '../Toolbar';
|
|
13
|
+
|
|
14
|
+
export const SheetContainer = ({ graph, sheet, role }: SheetProviderProps & { role?: string }) => {
|
|
15
|
+
const dispatch = useIntentDispatcher();
|
|
16
|
+
|
|
17
|
+
// TODO(Zan): Centralise the toolbar action handler. Current implementation in stories.
|
|
18
|
+
const handleAction = useCallback(
|
|
19
|
+
(action: ToolbarAction) => {
|
|
20
|
+
switch (action.type) {
|
|
21
|
+
case 'comment': {
|
|
22
|
+
// TODO(Zan): We shouldn't hardcode the action ID.
|
|
23
|
+
void dispatch({
|
|
24
|
+
action: 'dxos.org/plugin/thread/action/create',
|
|
25
|
+
data: {
|
|
26
|
+
cursor: action.anchor,
|
|
27
|
+
name: action.cellContent,
|
|
28
|
+
subject: sheet,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
[sheet, dispatch],
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<SheetProvider sheet={sheet} graph={graph}>
|
|
39
|
+
<Toolbar.Root onAction={handleAction} role={role}>
|
|
40
|
+
<Toolbar.Styles />
|
|
41
|
+
<Toolbar.Format />
|
|
42
|
+
<Toolbar.Alignment />
|
|
43
|
+
<Toolbar.Separator />
|
|
44
|
+
<Toolbar.Actions />
|
|
45
|
+
</Toolbar.Root>
|
|
46
|
+
<div role='none' className='border-bs border-separator grid cols-1 rows-[1fr_min-content] min-bs-0'>
|
|
47
|
+
<GridSheet />
|
|
48
|
+
<FunctionEditor />
|
|
49
|
+
</div>
|
|
50
|
+
</SheetProvider>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
@@ -5,15 +5,18 @@
|
|
|
5
5
|
import React, { type PropsWithChildren, createContext, useContext, useMemo, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
|
+
import { fullyQualifiedId } from '@dxos/react-client/echo';
|
|
9
|
+
import { Grid, useGridContext, type GridScopedProps, type GridEditing } from '@dxos/react-ui-grid';
|
|
8
10
|
|
|
9
|
-
import { createDecorations } from './decorations';
|
|
10
11
|
import { type CellAddress, type CellRange } from '../../defs';
|
|
11
12
|
import { type ComputeGraph } from '../../graph';
|
|
12
|
-
import { useSheetModel, useFormattingModel } from '../../hooks';
|
|
13
|
-
import { type FormattingModel, type SheetModel } from '../../model';
|
|
13
|
+
import { useSheetModel, useFormattingModel, useSelectThreadOnCellFocus, useThreadDecorations } from '../../hooks';
|
|
14
|
+
import { type FormattingModel, type SheetModel, createDecorations } from '../../model';
|
|
14
15
|
import { type SheetType } from '../../types';
|
|
15
16
|
|
|
16
|
-
export type
|
|
17
|
+
export type SheetContextValue = {
|
|
18
|
+
id: string;
|
|
19
|
+
|
|
17
20
|
model: SheetModel;
|
|
18
21
|
formatting: FormattingModel;
|
|
19
22
|
|
|
@@ -25,8 +28,8 @@ export type SheetContextType = {
|
|
|
25
28
|
setRange: (range: CellRange | undefined) => void;
|
|
26
29
|
|
|
27
30
|
// Editing state (undefined if not editing).
|
|
28
|
-
editing:
|
|
29
|
-
setEditing: (editing:
|
|
31
|
+
editing: GridEditing;
|
|
32
|
+
setEditing: (editing: GridEditing) => void;
|
|
30
33
|
|
|
31
34
|
// Events.
|
|
32
35
|
// TODO(burdon): Generalize.
|
|
@@ -36,47 +39,45 @@ export type SheetContextType = {
|
|
|
36
39
|
decorations: ReturnType<typeof createDecorations>;
|
|
37
40
|
};
|
|
38
41
|
|
|
39
|
-
const SheetContext = createContext<
|
|
42
|
+
const SheetContext = createContext<SheetContextValue | null>(null);
|
|
40
43
|
|
|
41
|
-
export const useSheetContext = ():
|
|
44
|
+
export const useSheetContext = (): SheetContextValue => {
|
|
42
45
|
const context = useContext(SheetContext);
|
|
43
46
|
invariant(context);
|
|
44
47
|
return context;
|
|
45
48
|
};
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
readonly?: boolean;
|
|
51
|
-
} & Pick<SheetContextType, 'onInfo'>;
|
|
52
|
-
|
|
53
|
-
export const SheetContextProvider = ({
|
|
54
|
-
children,
|
|
55
|
-
graph,
|
|
56
|
-
sheet,
|
|
57
|
-
readonly,
|
|
50
|
+
const SheetProviderImpl = ({
|
|
51
|
+
model,
|
|
52
|
+
formatting,
|
|
58
53
|
onInfo,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
children,
|
|
55
|
+
__gridScope,
|
|
56
|
+
}: GridScopedProps<PropsWithChildren<Pick<SheetContextValue, 'onInfo' | 'model' | 'formatting'>>>) => {
|
|
57
|
+
const { id, editing, setEditing } = useGridContext('SheetProvider', __gridScope);
|
|
62
58
|
|
|
63
59
|
// TODO(Zan): Impl. set range and set cursor that scrolls to that cell or range if it is not visible.
|
|
60
|
+
const decorations = useMemo(() => createDecorations(), []);
|
|
61
|
+
|
|
62
|
+
// TODO(thure): Reconnect these.
|
|
64
63
|
const [cursor, setCursor] = useState<CellAddress>();
|
|
65
64
|
const [range, setRange] = useState<CellRange>();
|
|
66
|
-
const [editing, setEditing] = useState<boolean>(false);
|
|
67
|
-
const decorations = useMemo(() => createDecorations(), []);
|
|
68
65
|
|
|
69
|
-
|
|
66
|
+
useSelectThreadOnCellFocus(model, cursor);
|
|
67
|
+
useThreadDecorations(model, decorations);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
70
|
<SheetContext.Provider
|
|
71
71
|
value={{
|
|
72
|
+
id,
|
|
72
73
|
model,
|
|
73
74
|
formatting,
|
|
75
|
+
editing,
|
|
76
|
+
setEditing,
|
|
74
77
|
cursor,
|
|
75
78
|
setCursor,
|
|
76
79
|
range,
|
|
77
80
|
setRange,
|
|
78
|
-
editing,
|
|
79
|
-
setEditing,
|
|
80
81
|
// TODO(burdon): Change to event.
|
|
81
82
|
onInfo,
|
|
82
83
|
decorations,
|
|
@@ -86,3 +87,22 @@ export const SheetContextProvider = ({
|
|
|
86
87
|
</SheetContext.Provider>
|
|
87
88
|
);
|
|
88
89
|
};
|
|
90
|
+
|
|
91
|
+
export type SheetProviderProps = {
|
|
92
|
+
graph: ComputeGraph;
|
|
93
|
+
sheet: SheetType;
|
|
94
|
+
readonly?: boolean;
|
|
95
|
+
} & Pick<SheetContextValue, 'onInfo'>;
|
|
96
|
+
|
|
97
|
+
export const SheetProvider = ({ children, graph, sheet, readonly, onInfo }: PropsWithChildren<SheetProviderProps>) => {
|
|
98
|
+
const model = useSheetModel(graph, sheet, { readonly });
|
|
99
|
+
const formatting = useFormattingModel(model);
|
|
100
|
+
|
|
101
|
+
return !model || !formatting ? null : (
|
|
102
|
+
<Grid.Root id={fullyQualifiedId(sheet)}>
|
|
103
|
+
<SheetProviderImpl model={model} formatting={formatting} onInfo={onInfo}>
|
|
104
|
+
{children}
|
|
105
|
+
</SheetProviderImpl>
|
|
106
|
+
</Grid.Root>
|
|
107
|
+
);
|
|
108
|
+
};
|