@dxos/plugin-sheet 0.6.13-main.548ca8d → 0.6.13-main.ed424a1
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 → SheetContainer-RVRACGCZ.mjs} +107 -82
- package/dist/lib/browser/SheetContainer-RVRACGCZ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GKI67SEF.mjs → chunk-BWN5DZWZ.mjs} +16 -11
- package/dist/lib/browser/chunk-BWN5DZWZ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-AQSGDA4X.mjs → chunk-HOG37RYS.mjs} +92 -178
- package/dist/lib/browser/chunk-HOG37RYS.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types.mjs +3 -3
- package/dist/lib/node/{SheetContainer-YSQGJD7K.cjs → SheetContainer-J7XROAMN.cjs} +113 -89
- package/dist/lib/node/SheetContainer-J7XROAMN.cjs.map +7 -0
- package/dist/lib/node/{chunk-6F43RV45.cjs → chunk-AXQZA2YS.cjs} +103 -186
- package/dist/lib/node/chunk-AXQZA2YS.cjs.map +7 -0
- package/dist/lib/node/{chunk-ER3PM7GD.cjs → chunk-NZARD7UP.cjs} +20 -15
- package/dist/lib/node/chunk-NZARD7UP.cjs.map +7 -0
- package/dist/lib/node/index.cjs +18 -18
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +7 -7
- package/dist/lib/node/types.cjs.map +1 -1
- package/dist/lib/node-esm/{SheetContainer-M7WRMZDU.mjs → SheetContainer-YWQVKHQB.mjs} +107 -82
- package/dist/lib/node-esm/SheetContainer-YWQVKHQB.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-ELTFPX5B.mjs → chunk-BPXXIAOQ.mjs} +92 -178
- package/dist/lib/node-esm/chunk-BPXXIAOQ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-ZVLLQ2PJ.mjs → chunk-WFDTY3IC.mjs} +16 -11
- package/dist/lib/node-esm/chunk-WFDTY3IC.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +2 -2
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types.mjs +3 -3
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/util.d.ts +2 -2
- package/dist/types/src/components/GridSheet/util.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/SheetContext/SheetContext.d.ts +1 -2
- package/dist/types/src/components/SheetContext/SheetContext.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +11 -17
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +1 -2
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/defs/index.d.ts +1 -0
- package/dist/types/src/defs/index.d.ts.map +1 -1
- package/dist/types/src/defs/sheet-range-types.d.ts +13 -0
- package/dist/types/src/defs/sheet-range-types.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +0 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/model/index.d.ts +0 -1
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +39 -20
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +35 -34
- package/src/components/GridSheet/GridSheet.stories.tsx +2 -2
- package/src/components/GridSheet/GridSheet.tsx +5 -3
- package/src/components/GridSheet/util.ts +24 -10
- package/src/components/SheetContainer/SheetContainer.stories.tsx +2 -2
- package/src/components/SheetContainer/SheetContainer.tsx +3 -28
- package/src/components/SheetContext/SheetContext.tsx +5 -9
- package/src/components/Toolbar/Toolbar.tsx +116 -68
- package/src/defs/index.ts +1 -0
- package/src/defs/sheet-range-types.ts +46 -0
- package/src/defs/util.ts +1 -1
- package/src/hooks/index.ts +0 -1
- package/src/model/index.ts +0 -1
- package/src/types.ts +5 -11
- package/dist/lib/browser/SheetContainer-NDNIS44E.mjs.map +0 -7
- package/dist/lib/browser/chunk-AQSGDA4X.mjs.map +0 -7
- package/dist/lib/browser/chunk-GKI67SEF.mjs.map +0 -7
- package/dist/lib/node/SheetContainer-YSQGJD7K.cjs.map +0 -7
- package/dist/lib/node/chunk-6F43RV45.cjs.map +0 -7
- package/dist/lib/node/chunk-ER3PM7GD.cjs.map +0 -7
- package/dist/lib/node-esm/SheetContainer-M7WRMZDU.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ELTFPX5B.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZVLLQ2PJ.mjs.map +0 -7
- package/dist/types/src/hooks/useFormattingModel.d.ts +0 -3
- package/dist/types/src/hooks/useFormattingModel.d.ts.map +0 -1
- package/dist/types/src/model/formatting-model.d.ts +0 -19
- package/dist/types/src/model/formatting-model.d.ts.map +0 -1
- package/src/hooks/useFormattingModel.ts +0 -11
- package/src/model/formatting-model.ts +0 -116
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAe,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAe,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMxD,oBAAY,WAAW;IACrB,MAAM,wCAA2B;CAClC;AAKD,KAAK,cAAc,CAAC,CAAC,IAAI;IACvB,MAAM,EAAE;QACN,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC;QAClC,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;KAC9F,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAC/C,sBAAsB,GACtB,oBAAoB,GACpB,yBAAyB,GACzB,uBAAuB,GACvB,oBAAoB,GACpB,cAAc,GACd,iBAAiB,GACjB,aAAa,GACb,cAAc,CAAC,SAAS,CAAC,CAAC;AAE5B,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE/D,eAAO,MAAM,SAAS;;EAKpB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,SAAS,CAAC,CAAC;AAGxD,eAAO,MAAM,KAAK;;;;;;;;;;;;;EAIhB,CAAC;AAGH,eAAO,MAAM,aAAa;;EAExB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqCwN,CAAC;;oBAA8D,CAAC;uBAAyC,CAAC;wBAAwD,CAAC;;;;;;;;2BAAsP,CAAC;qBAAuC,CAAC;;iBAA8C,CAAC;sBAA4E,CAAC;;;mBAAwE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAvoB,CAAC;;oBAA8D,CAAC;uBAAyC,CAAC;wBAAwD,CAAC;;;;;;;;2BAAsP,CAAC;qBAAuC,CAAC;;iBAA8C,CAAC;sBAA4E,CAAC;;;mBAAwE,CAAC;;;;;;;;AAlCl2B,qBAAa,SAAU,SAAQ,cAuB7B;CAAG;AAEL,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACnC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-sheet",
|
|
3
|
-
"version": "0.6.13-main.
|
|
3
|
+
"version": "0.6.13-main.ed424a1",
|
|
4
4
|
"description": "Braneframe sketch plugin",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -77,30 +77,31 @@
|
|
|
77
77
|
"re-resizable": "^6.9.17",
|
|
78
78
|
"react-markdown": "^8.0.5",
|
|
79
79
|
"react-resize-detector": "^11.0.1",
|
|
80
|
-
"@dxos/
|
|
81
|
-
"@dxos/
|
|
82
|
-
"@dxos/
|
|
83
|
-
"@dxos/
|
|
84
|
-
"@dxos/
|
|
85
|
-
"@dxos/debug": "0.6.13-main.
|
|
86
|
-
"@dxos/
|
|
87
|
-
"@dxos/
|
|
88
|
-
"@dxos/
|
|
89
|
-
"@dxos/log": "0.6.13-main.
|
|
90
|
-
"@dxos/plugin-client": "0.6.13-main.
|
|
91
|
-
"@dxos/plugin-attention": "0.6.13-main.
|
|
92
|
-
"@dxos/plugin-graph": "0.6.13-main.
|
|
93
|
-
"@dxos/plugin-
|
|
94
|
-
"@dxos/plugin-
|
|
95
|
-
"@dxos/plugin-
|
|
96
|
-
"@dxos/plugin-
|
|
97
|
-
"@dxos/react-client": "0.6.13-main.
|
|
98
|
-
"@dxos/react-hooks": "0.6.13-main.
|
|
99
|
-
"@dxos/react-ui-attention": "0.6.13-main.
|
|
100
|
-
"@dxos/react-ui-
|
|
101
|
-
"@dxos/
|
|
102
|
-
"@dxos/
|
|
103
|
-
"@dxos/
|
|
80
|
+
"@dxos/async": "0.6.13-main.ed424a1",
|
|
81
|
+
"@dxos/app-framework": "0.6.13-main.ed424a1",
|
|
82
|
+
"@dxos/client": "0.6.13-main.ed424a1",
|
|
83
|
+
"@dxos/crypto": "0.6.13-main.ed424a1",
|
|
84
|
+
"@dxos/context": "0.6.13-main.ed424a1",
|
|
85
|
+
"@dxos/debug": "0.6.13-main.ed424a1",
|
|
86
|
+
"@dxos/echo-schema": "0.6.13-main.ed424a1",
|
|
87
|
+
"@dxos/invariant": "0.6.13-main.ed424a1",
|
|
88
|
+
"@dxos/keys": "0.6.13-main.ed424a1",
|
|
89
|
+
"@dxos/log": "0.6.13-main.ed424a1",
|
|
90
|
+
"@dxos/plugin-client": "0.6.13-main.ed424a1",
|
|
91
|
+
"@dxos/plugin-attention": "0.6.13-main.ed424a1",
|
|
92
|
+
"@dxos/plugin-graph": "0.6.13-main.ed424a1",
|
|
93
|
+
"@dxos/plugin-script": "0.6.13-main.ed424a1",
|
|
94
|
+
"@dxos/plugin-markdown": "0.6.13-main.ed424a1",
|
|
95
|
+
"@dxos/plugin-stack": "0.6.13-main.ed424a1",
|
|
96
|
+
"@dxos/plugin-space": "0.6.13-main.ed424a1",
|
|
97
|
+
"@dxos/react-client": "0.6.13-main.ed424a1",
|
|
98
|
+
"@dxos/react-hooks": "0.6.13-main.ed424a1",
|
|
99
|
+
"@dxos/react-ui-attention": "0.6.13-main.ed424a1",
|
|
100
|
+
"@dxos/react-ui-data": "0.6.13-main.ed424a1",
|
|
101
|
+
"@dxos/schema": "0.6.13-main.ed424a1",
|
|
102
|
+
"@dxos/react-ui-grid": "0.6.13-main.ed424a1",
|
|
103
|
+
"@dxos/react-ui-editor": "0.6.13-main.ed424a1",
|
|
104
|
+
"@dxos/util": "0.6.13-main.ed424a1"
|
|
104
105
|
},
|
|
105
106
|
"devDependencies": {
|
|
106
107
|
"@lezer/generator": "^1.7.1",
|
|
@@ -112,19 +113,19 @@
|
|
|
112
113
|
"react": "~18.2.0",
|
|
113
114
|
"react-dom": "~18.2.0",
|
|
114
115
|
"vite": "5.4.7",
|
|
115
|
-
"@dxos/
|
|
116
|
-
"@dxos/
|
|
117
|
-
"@dxos/react-ui": "0.6.13-main.
|
|
118
|
-
"@dxos/react-ui
|
|
119
|
-
"@dxos/react-ui-
|
|
120
|
-
"@dxos/
|
|
121
|
-
"@dxos/
|
|
116
|
+
"@dxos/random": "0.6.13-main.ed424a1",
|
|
117
|
+
"@dxos/echo-generator": "0.6.13-main.ed424a1",
|
|
118
|
+
"@dxos/react-ui-syntax-highlighter": "0.6.13-main.ed424a1",
|
|
119
|
+
"@dxos/react-ui": "0.6.13-main.ed424a1",
|
|
120
|
+
"@dxos/react-ui-theme": "0.6.13-main.ed424a1",
|
|
121
|
+
"@dxos/react-ui-types": "0.6.13-main.ed424a1",
|
|
122
|
+
"@dxos/storybook-utils": "0.6.13-main.ed424a1"
|
|
122
123
|
},
|
|
123
124
|
"peerDependencies": {
|
|
124
125
|
"react": "~18.2.0",
|
|
125
126
|
"react-dom": "~18.2.0",
|
|
126
|
-
"@dxos/react-ui": "0.6.13-main.
|
|
127
|
-
"@dxos/react-ui
|
|
127
|
+
"@dxos/react-ui-theme": "0.6.13-main.ed424a1",
|
|
128
|
+
"@dxos/react-ui": "0.6.13-main.ed424a1"
|
|
128
129
|
},
|
|
129
130
|
"publishConfig": {
|
|
130
131
|
"access": "public"
|
|
@@ -10,7 +10,7 @@ import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
|
10
10
|
|
|
11
11
|
import { GridSheet } from './GridSheet';
|
|
12
12
|
import { useComputeGraph } from '../../hooks';
|
|
13
|
-
import { useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
13
|
+
import { createTestCells, useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
14
14
|
import { SheetType } from '../../types';
|
|
15
15
|
import { SheetProvider } from '../SheetContext';
|
|
16
16
|
|
|
@@ -28,7 +28,7 @@ export default {
|
|
|
28
28
|
export const Basic = () => {
|
|
29
29
|
const space = useSpace();
|
|
30
30
|
const graph = useComputeGraph(space);
|
|
31
|
-
const sheet = useTestSheet(space, graph);
|
|
31
|
+
const sheet = useTestSheet(space, graph, { cells: createTestCells() });
|
|
32
32
|
if (!sheet || !graph) {
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
@@ -42,7 +42,7 @@ const sheetRowDefault = { grid: { size: 32, resizeable: true } };
|
|
|
42
42
|
const sheetColDefault = { frozenColsStart: { size: 48 }, grid: { size: 180, resizeable: true } };
|
|
43
43
|
|
|
44
44
|
export const GridSheet = () => {
|
|
45
|
-
const { id, model,
|
|
45
|
+
const { id, model, editing, setEditing, setCursor, setRange } = useSheetContext();
|
|
46
46
|
const dxGrid = useRef<DxGridElement | null>(null);
|
|
47
47
|
const rangeNotifier = useRef<CellRangeNotifier>();
|
|
48
48
|
const { hasAttention } = useAttention(id);
|
|
@@ -51,7 +51,9 @@ export const GridSheet = () => {
|
|
|
51
51
|
(event: FocusEvent) => {
|
|
52
52
|
if (!editing) {
|
|
53
53
|
const cell = closestCell(event.target);
|
|
54
|
-
|
|
54
|
+
if (cell && cell.plane === 'grid') {
|
|
55
|
+
setCursor({ col: cell.col, row: cell.row });
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
58
|
},
|
|
57
59
|
[editing],
|
|
@@ -116,7 +118,7 @@ export const GridSheet = () => {
|
|
|
116
118
|
[hasAttention],
|
|
117
119
|
);
|
|
118
120
|
|
|
119
|
-
const { columns, rows } = useSheetModelDxGridProps(dxGrid, model
|
|
121
|
+
const { columns, rows } = useSheetModelDxGridProps(dxGrid, model);
|
|
120
122
|
|
|
121
123
|
const extension = useMemo(
|
|
122
124
|
() => [
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { type MutableRefObject, useEffect, useLayoutEffect, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { createDocAccessor } from '@dxos/react-client/echo';
|
|
8
|
+
import { parseValue, cellClassesForFieldType } from '@dxos/react-ui-data';
|
|
8
9
|
import {
|
|
9
10
|
type GridContentProps,
|
|
10
11
|
type DxGridElement,
|
|
@@ -12,13 +13,14 @@ import {
|
|
|
12
13
|
type DxGridPlane,
|
|
13
14
|
type DxGridPlaneRange,
|
|
14
15
|
type DxGridPlaneCells,
|
|
16
|
+
type DxGridCellValue,
|
|
15
17
|
colToA1Notation,
|
|
16
18
|
rowToA1Notation,
|
|
17
19
|
} from '@dxos/react-ui-grid';
|
|
18
20
|
import { mx } from '@dxos/react-ui-theme';
|
|
19
21
|
|
|
20
|
-
import { type CellAddress } from '../../defs';
|
|
21
|
-
import { type SheetModel
|
|
22
|
+
import { type CellAddress, inRange, cellClassNameForRange } from '../../defs';
|
|
23
|
+
import { type SheetModel } from '../../model';
|
|
22
24
|
|
|
23
25
|
export const dxGridCellIndexToSheetCellAddress = (index: string): CellAddress => {
|
|
24
26
|
const [colStr, rowStr] = index.split(',');
|
|
@@ -52,7 +54,20 @@ const createDxGridRows = (model: SheetModel): DxGridAxisMeta => {
|
|
|
52
54
|
);
|
|
53
55
|
};
|
|
54
56
|
|
|
55
|
-
const
|
|
57
|
+
const projectCellProps = (model: SheetModel, col: number, row: number): DxGridCellValue => {
|
|
58
|
+
const address = { col, row };
|
|
59
|
+
const rawValue = model.getValue(address);
|
|
60
|
+
if (rawValue === undefined || rawValue === null) {
|
|
61
|
+
return { value: '' };
|
|
62
|
+
}
|
|
63
|
+
const ranges = model.sheet.ranges?.filter(({ range }) => inRange(range, address));
|
|
64
|
+
const type = model.getValueType(address);
|
|
65
|
+
const classNames = ranges?.map(cellClassNameForRange).reverse();
|
|
66
|
+
|
|
67
|
+
return { value: parseValue(type, rawValue), className: mx(cellClassesForFieldType(type), classNames) };
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const gridCellGetter = (model: SheetModel) => {
|
|
56
71
|
// TODO(thure): Actually use the cache.
|
|
57
72
|
const cachedGridCells: DxGridPlaneCells = {};
|
|
58
73
|
return (nextBounds: DxGridPlaneRange): DxGridPlaneCells => {
|
|
@@ -60,10 +75,10 @@ const gridCellGetter = (model: SheetModel, formatting: FormattingModel) => {
|
|
|
60
75
|
return [...Array(nextBounds.end.row - nextBounds.start.row)].forEach((_, r0) => {
|
|
61
76
|
const col = nextBounds.start.col + c0;
|
|
62
77
|
const row = nextBounds.start.row + r0;
|
|
63
|
-
const cell =
|
|
78
|
+
const cell = projectCellProps(model, col, row);
|
|
64
79
|
if (cell.value) {
|
|
65
80
|
cachedGridCells;
|
|
66
|
-
cachedGridCells[`${col},${row}`] =
|
|
81
|
+
cachedGridCells[`${col},${row}`] = cell;
|
|
67
82
|
}
|
|
68
83
|
});
|
|
69
84
|
});
|
|
@@ -79,8 +94,8 @@ export const rowLabelCell = (row: number) => ({
|
|
|
79
94
|
|
|
80
95
|
export const colLabelCell = (col: number) => ({ value: colToA1Notation(col), resizeHandle: 'col' });
|
|
81
96
|
|
|
82
|
-
const cellGetter = (model: SheetModel
|
|
83
|
-
const getGridCells = gridCellGetter(model
|
|
97
|
+
const cellGetter = (model: SheetModel) => {
|
|
98
|
+
const getGridCells = gridCellGetter(model);
|
|
84
99
|
return (nextBounds: DxGridPlaneRange, plane: DxGridPlane): DxGridPlaneCells => {
|
|
85
100
|
switch (plane) {
|
|
86
101
|
case 'grid':
|
|
@@ -106,7 +121,6 @@ const cellGetter = (model: SheetModel, formatting: FormattingModel) => {
|
|
|
106
121
|
export const useSheetModelDxGridProps = (
|
|
107
122
|
dxGridRef: MutableRefObject<DxGridElement | null>,
|
|
108
123
|
model: SheetModel,
|
|
109
|
-
formatting: FormattingModel,
|
|
110
124
|
): Pick<GridContentProps, 'columns' | 'rows'> => {
|
|
111
125
|
const [columns, setColumns] = useState<DxGridAxisMeta>(createDxGridColumns(model));
|
|
112
126
|
const [rows, setRows] = useState<DxGridAxisMeta>(createDxGridColumns(model));
|
|
@@ -114,14 +128,14 @@ export const useSheetModelDxGridProps = (
|
|
|
114
128
|
useLayoutEffect(() => {
|
|
115
129
|
const cellsAccessor = createDocAccessor(model.sheet, ['cells']);
|
|
116
130
|
if (dxGridRef.current) {
|
|
117
|
-
dxGridRef.current.getCells = cellGetter(model
|
|
131
|
+
dxGridRef.current.getCells = cellGetter(model);
|
|
118
132
|
}
|
|
119
133
|
const handleCellsUpdate = () => {
|
|
120
134
|
dxGridRef.current?.requestUpdate('initialCells');
|
|
121
135
|
};
|
|
122
136
|
cellsAccessor.handle.addListener('change', handleCellsUpdate);
|
|
123
137
|
return () => cellsAccessor.handle.removeListener('change', handleCellsUpdate);
|
|
124
|
-
}, [model
|
|
138
|
+
}, [model]);
|
|
125
139
|
|
|
126
140
|
useEffect(() => {
|
|
127
141
|
const columnMetaAccessor = createDocAccessor(model.sheet, ['columnMeta']);
|
|
@@ -10,7 +10,7 @@ import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
|
10
10
|
|
|
11
11
|
import { SheetContainer } from './SheetContainer';
|
|
12
12
|
import { useComputeGraph } from '../../hooks';
|
|
13
|
-
import { useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
13
|
+
import { createTestCells, useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
14
14
|
import { SheetType } from '../../types';
|
|
15
15
|
|
|
16
16
|
export default {
|
|
@@ -31,7 +31,7 @@ export default {
|
|
|
31
31
|
export const Basic = () => {
|
|
32
32
|
const space = useSpace();
|
|
33
33
|
const graph = useComputeGraph(space);
|
|
34
|
-
const sheet = useTestSheet(space, graph);
|
|
34
|
+
const sheet = useTestSheet(space, graph, { cells: createTestCells() });
|
|
35
35
|
if (!sheet || !graph) {
|
|
36
36
|
return null;
|
|
37
37
|
}
|
|
@@ -2,43 +2,18 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React
|
|
6
|
-
|
|
7
|
-
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
5
|
+
import React from 'react';
|
|
8
6
|
|
|
9
7
|
import { FunctionEditor } from '../FunctionEditor';
|
|
10
8
|
import { GridSheet } from '../GridSheet';
|
|
11
9
|
import { SheetProvider, type SheetProviderProps } from '../SheetContext';
|
|
12
|
-
import { Toolbar
|
|
10
|
+
import { Toolbar } from '../Toolbar';
|
|
13
11
|
|
|
14
12
|
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
13
|
return (
|
|
38
14
|
<SheetProvider sheet={sheet} graph={graph}>
|
|
39
|
-
<Toolbar.Root
|
|
15
|
+
<Toolbar.Root role={role}>
|
|
40
16
|
<Toolbar.Styles />
|
|
41
|
-
<Toolbar.Format />
|
|
42
17
|
<Toolbar.Alignment />
|
|
43
18
|
<Toolbar.Separator />
|
|
44
19
|
<Toolbar.Actions />
|
|
@@ -10,15 +10,14 @@ import { Grid, useGridContext, type GridScopedProps, type GridEditing } from '@d
|
|
|
10
10
|
|
|
11
11
|
import { type CellAddress, type CellRange } from '../../defs';
|
|
12
12
|
import { type ComputeGraph } from '../../graph';
|
|
13
|
-
import { useSheetModel,
|
|
14
|
-
import { type
|
|
13
|
+
import { useSheetModel, useSelectThreadOnCellFocus, useThreadDecorations } from '../../hooks';
|
|
14
|
+
import { type SheetModel, createDecorations } from '../../model';
|
|
15
15
|
import { type SheetType } from '../../types';
|
|
16
16
|
|
|
17
17
|
export type SheetContextValue = {
|
|
18
18
|
id: string;
|
|
19
19
|
|
|
20
20
|
model: SheetModel;
|
|
21
|
-
formatting: FormattingModel;
|
|
22
21
|
|
|
23
22
|
// Cursor state.
|
|
24
23
|
// TODO(burdon): Cursor and range should use indices.
|
|
@@ -49,11 +48,10 @@ export const useSheetContext = (): SheetContextValue => {
|
|
|
49
48
|
|
|
50
49
|
const SheetProviderImpl = ({
|
|
51
50
|
model,
|
|
52
|
-
formatting,
|
|
53
51
|
onInfo,
|
|
54
52
|
children,
|
|
55
53
|
__gridScope,
|
|
56
|
-
}: GridScopedProps<PropsWithChildren<Pick<SheetContextValue, 'onInfo' | 'model'
|
|
54
|
+
}: GridScopedProps<PropsWithChildren<Pick<SheetContextValue, 'onInfo' | 'model'>>>) => {
|
|
57
55
|
const { id, editing, setEditing } = useGridContext('SheetProvider', __gridScope);
|
|
58
56
|
|
|
59
57
|
// TODO(Zan): Impl. set range and set cursor that scrolls to that cell or range if it is not visible.
|
|
@@ -71,7 +69,6 @@ const SheetProviderImpl = ({
|
|
|
71
69
|
value={{
|
|
72
70
|
id,
|
|
73
71
|
model,
|
|
74
|
-
formatting,
|
|
75
72
|
editing,
|
|
76
73
|
setEditing,
|
|
77
74
|
cursor,
|
|
@@ -96,11 +93,10 @@ export type SheetProviderProps = {
|
|
|
96
93
|
|
|
97
94
|
export const SheetProvider = ({ children, graph, sheet, readonly, onInfo }: PropsWithChildren<SheetProviderProps>) => {
|
|
98
95
|
const model = useSheetModel(graph, sheet, { readonly });
|
|
99
|
-
const formatting = useFormattingModel(model);
|
|
100
96
|
|
|
101
|
-
return !model
|
|
97
|
+
return !model ? null : (
|
|
102
98
|
<Grid.Root id={fullyQualifiedId(sheet)}>
|
|
103
|
-
<SheetProviderImpl model={model}
|
|
99
|
+
<SheetProviderImpl model={model} onInfo={onInfo}>
|
|
104
100
|
{children}
|
|
105
101
|
</SheetProviderImpl>
|
|
106
102
|
</Grid.Root>
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { createContext } from '@radix-ui/react-context';
|
|
6
|
-
import React, { type PropsWithChildren } from 'react';
|
|
6
|
+
import React, { type PropsWithChildren, useCallback, useMemo } from 'react';
|
|
7
7
|
|
|
8
|
+
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
8
9
|
import {
|
|
9
10
|
Icon,
|
|
10
11
|
Toolbar as NaturalToolbar,
|
|
@@ -18,9 +19,18 @@ import {
|
|
|
18
19
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
19
20
|
import { nonNullable } from '@dxos/util';
|
|
20
21
|
|
|
21
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
addressToIndex,
|
|
24
|
+
type AlignKey,
|
|
25
|
+
type AlignValue,
|
|
26
|
+
type CommentKey,
|
|
27
|
+
type CommentValue,
|
|
28
|
+
inRange,
|
|
29
|
+
type StyleKey,
|
|
30
|
+
type StyleValue,
|
|
31
|
+
} from '../../defs';
|
|
22
32
|
import { SHEET_PLUGIN } from '../../meta';
|
|
23
|
-
import { type
|
|
33
|
+
import { type SheetType } from '../../types';
|
|
24
34
|
import { useSheetContext } from '../SheetContext';
|
|
25
35
|
|
|
26
36
|
//
|
|
@@ -71,42 +81,92 @@ export const ToolbarItem = ({ itemType, icon, children, ...props }: ToolbarItemP
|
|
|
71
81
|
// Root
|
|
72
82
|
//
|
|
73
83
|
|
|
74
|
-
type
|
|
75
|
-
type
|
|
76
|
-
|
|
77
|
-
type CommentAction = { type: 'comment'; anchor: string; cellContent?: string };
|
|
78
|
-
|
|
79
|
-
type FormatValue = 'date' | 'currency' | 'unset';
|
|
80
|
-
type FormatAction = { type: 'format'; value: FormatValue };
|
|
84
|
+
type AlignAction = { key: AlignKey; value: AlignValue };
|
|
85
|
+
type CommentAction = { key: CommentKey; value: CommentValue; cellContent?: string };
|
|
86
|
+
type StyleAction = { key: StyleKey; value: StyleValue };
|
|
81
87
|
|
|
82
|
-
type
|
|
83
|
-
type StyleAction = { type: 'style'; value: StyleValue };
|
|
88
|
+
export type ToolbarAction = StyleAction | AlignAction | CommentAction;
|
|
84
89
|
|
|
85
|
-
export type
|
|
86
|
-
|
|
87
|
-
export type ToolbarActionType = ToolbarAction['type'];
|
|
90
|
+
export type ToolbarActionType = ToolbarAction['key'];
|
|
88
91
|
|
|
89
92
|
export type ToolbarActionHandler = (action: ToolbarAction) => void;
|
|
90
93
|
|
|
91
94
|
export type ToolbarProps = ThemedClassName<
|
|
92
95
|
PropsWithChildren<{
|
|
93
|
-
onAction?: ToolbarActionHandler;
|
|
94
96
|
role?: string;
|
|
95
97
|
}>
|
|
96
98
|
>;
|
|
97
99
|
|
|
98
|
-
const [ToolbarContextProvider, useToolbarContext] = createContext<
|
|
100
|
+
const [ToolbarContextProvider, useToolbarContext] = createContext<{ onAction: (action: ToolbarAction) => void }>(
|
|
101
|
+
'Toolbar',
|
|
102
|
+
);
|
|
99
103
|
|
|
100
104
|
// TODO(Zan): Factor out, copied this from MarkdownPlugin.
|
|
101
105
|
const sectionToolbarLayout =
|
|
102
106
|
'bs-[--rail-action] bg-[--sticky-bg] sticky block-start-0 __-block-start-px transition-opacity';
|
|
103
107
|
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
type Range = SheetType['ranges'][number];
|
|
109
|
+
|
|
110
|
+
const ToolbarRoot = ({ children, role, classNames }: ToolbarProps) => {
|
|
111
|
+
const { id, model, range, cursor } = useSheetContext();
|
|
106
112
|
const { hasAttention } = useAttention(id);
|
|
113
|
+
const dispatch = useIntentDispatcher();
|
|
114
|
+
|
|
115
|
+
// TODO(Zan): Centralise the toolbar action handler. Current implementation in stories.
|
|
116
|
+
const handleAction = useCallback(
|
|
117
|
+
(action: ToolbarAction) => {
|
|
118
|
+
switch (action.key) {
|
|
119
|
+
case 'align':
|
|
120
|
+
if (cursor) {
|
|
121
|
+
const index = model.sheet.ranges?.findIndex(
|
|
122
|
+
(range) => range.key === action.key && inRange(range.range, cursor),
|
|
123
|
+
);
|
|
124
|
+
const nextRange = range ? { from: range.from, to: range.to ?? range.from } : { from: cursor, to: cursor };
|
|
125
|
+
const nextRangeEntity = {
|
|
126
|
+
range: nextRange as Range['range'],
|
|
127
|
+
key: action.key,
|
|
128
|
+
value: action.value,
|
|
129
|
+
};
|
|
130
|
+
if (index < 0) {
|
|
131
|
+
model.sheet.ranges?.push(nextRangeEntity);
|
|
132
|
+
} else {
|
|
133
|
+
model.sheet.ranges?.splice(index, 1, nextRangeEntity);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
case 'style':
|
|
138
|
+
if (action.value === 'unset') {
|
|
139
|
+
const index = model.sheet.ranges?.findIndex((range) => range.key === action.key);
|
|
140
|
+
if (index >= 0) {
|
|
141
|
+
model.sheet.ranges?.splice(index, 1);
|
|
142
|
+
}
|
|
143
|
+
} else if (range || cursor) {
|
|
144
|
+
const nextRange = range ? { from: range.from, to: range.to ?? range.from } : { from: cursor, to: cursor };
|
|
145
|
+
model.sheet.ranges?.push({
|
|
146
|
+
range: nextRange as Range['range'],
|
|
147
|
+
key: action.key,
|
|
148
|
+
value: action.value,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
case 'comment': {
|
|
153
|
+
// TODO(Zan): We shouldn't hardcode the action ID.
|
|
154
|
+
void dispatch({
|
|
155
|
+
action: 'dxos.org/plugin/thread/action/create',
|
|
156
|
+
data: {
|
|
157
|
+
cursor: action.value,
|
|
158
|
+
name: action.cellContent,
|
|
159
|
+
subject: model.sheet,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
[model.sheet, range, cursor, dispatch],
|
|
166
|
+
);
|
|
107
167
|
|
|
108
168
|
return (
|
|
109
|
-
<ToolbarContextProvider onAction={
|
|
169
|
+
<ToolbarContextProvider onAction={handleAction}>
|
|
110
170
|
<NaturalToolbar.Root
|
|
111
171
|
classNames={[
|
|
112
172
|
...(role === 'section'
|
|
@@ -126,61 +186,39 @@ const ToolbarRoot = ({ children, onAction, role, classNames }: ToolbarProps) =>
|
|
|
126
186
|
type ButtonProps<T> = {
|
|
127
187
|
value: T;
|
|
128
188
|
icon: string;
|
|
129
|
-
|
|
130
|
-
disabled?: (state: Formatting) => boolean;
|
|
189
|
+
disabled?: (state: Range) => boolean;
|
|
131
190
|
};
|
|
132
191
|
|
|
133
192
|
//
|
|
134
193
|
// Alignment
|
|
135
194
|
//
|
|
136
195
|
|
|
137
|
-
const formatOptions: ButtonProps<FormatValue>[] = [
|
|
138
|
-
{ value: 'date', icon: 'ph--calendar--regular', getState: (state) => false },
|
|
139
|
-
{ value: 'currency', icon: 'ph--currency-dollar--regular', getState: (state) => false },
|
|
140
|
-
];
|
|
141
|
-
|
|
142
|
-
const Format = () => {
|
|
143
|
-
const { onAction } = useToolbarContext('Format');
|
|
144
|
-
const { t } = useTranslation(SHEET_PLUGIN);
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<NaturalToolbar.ToggleGroup
|
|
148
|
-
type='single'
|
|
149
|
-
// value={cellStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)}
|
|
150
|
-
>
|
|
151
|
-
{formatOptions.map(({ value, getState, icon }) => (
|
|
152
|
-
<ToolbarItem
|
|
153
|
-
itemType='toggleGroupItem'
|
|
154
|
-
key={value}
|
|
155
|
-
value={value}
|
|
156
|
-
icon={icon}
|
|
157
|
-
onClick={() => onAction?.({ type: 'format', value })}
|
|
158
|
-
>
|
|
159
|
-
{t(`toolbar ${value} label`)}
|
|
160
|
-
</ToolbarItem>
|
|
161
|
-
))}
|
|
162
|
-
</NaturalToolbar.ToggleGroup>
|
|
163
|
-
);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
196
|
const alignmentOptions: ButtonProps<AlignValue>[] = [
|
|
167
|
-
{ value: '
|
|
168
|
-
{ value: 'center', icon: 'ph--text-align-center--regular'
|
|
169
|
-
{ value: '
|
|
197
|
+
{ value: 'start', icon: 'ph--text-align-left--regular' },
|
|
198
|
+
{ value: 'center', icon: 'ph--text-align-center--regular' },
|
|
199
|
+
{ value: 'end', icon: 'ph--text-align-right--regular' },
|
|
170
200
|
];
|
|
171
201
|
|
|
172
202
|
const Alignment = () => {
|
|
203
|
+
const { cursor, model } = useSheetContext();
|
|
173
204
|
const { onAction } = useToolbarContext('Alignment');
|
|
174
205
|
const { t } = useTranslation(SHEET_PLUGIN);
|
|
175
206
|
|
|
207
|
+
const value = useMemo(
|
|
208
|
+
() =>
|
|
209
|
+
cursor
|
|
210
|
+
? model.sheet.ranges?.find(({ range, key }) => key === 'alignment' && inRange(range, cursor))?.value
|
|
211
|
+
: undefined,
|
|
212
|
+
[cursor, model.sheet.ranges],
|
|
213
|
+
);
|
|
214
|
+
|
|
176
215
|
return (
|
|
177
216
|
<NaturalToolbar.ToggleGroup
|
|
178
217
|
type='single'
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
onValueChange={(value: AlignValue) => onAction?.({ type: 'align', value })}
|
|
218
|
+
value={value}
|
|
219
|
+
onValueChange={(value: AlignValue) => onAction?.({ key: 'align', value })}
|
|
182
220
|
>
|
|
183
|
-
{alignmentOptions.map(({ value,
|
|
221
|
+
{alignmentOptions.map(({ value, icon }) => (
|
|
184
222
|
<ToolbarItem itemType='toggleGroupItem' key={value} value={value} icon={icon}>
|
|
185
223
|
{t(`toolbar ${value} label`)}
|
|
186
224
|
</ToolbarItem>
|
|
@@ -189,23 +227,34 @@ const Alignment = () => {
|
|
|
189
227
|
);
|
|
190
228
|
};
|
|
191
229
|
|
|
192
|
-
const styleOptions: ButtonProps<StyleValue>[] = [
|
|
193
|
-
{ value: 'highlight', icon: 'ph--highlighter--regular', getState: (state) => false },
|
|
194
|
-
];
|
|
230
|
+
const styleOptions: ButtonProps<StyleValue>[] = [{ value: 'highlight', icon: 'ph--highlighter--regular' }];
|
|
195
231
|
|
|
196
232
|
const Styles = () => {
|
|
233
|
+
const { cursor, model } = useSheetContext();
|
|
197
234
|
const { onAction } = useToolbarContext('Styles');
|
|
198
235
|
const { t } = useTranslation(SHEET_PLUGIN);
|
|
199
236
|
|
|
237
|
+
const activeValues = useMemo(
|
|
238
|
+
() =>
|
|
239
|
+
cursor
|
|
240
|
+
? model.sheet.ranges
|
|
241
|
+
?.filter(({ range, key }) => key === 'style' && inRange(range, cursor))
|
|
242
|
+
.reduce((acc, { value }) => {
|
|
243
|
+
acc.add(value);
|
|
244
|
+
return acc;
|
|
245
|
+
}, new Set())
|
|
246
|
+
: undefined,
|
|
247
|
+
[cursor, model.sheet.ranges],
|
|
248
|
+
);
|
|
249
|
+
|
|
200
250
|
return (
|
|
201
251
|
<>
|
|
202
|
-
{styleOptions.map(({ value,
|
|
252
|
+
{styleOptions.map(({ value, icon }) => (
|
|
203
253
|
<ToolbarItem
|
|
204
254
|
itemType='toggle'
|
|
205
255
|
key={value}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
256
|
+
pressed={activeValues?.has(value)}
|
|
257
|
+
onPressedChange={(nextPressed: boolean) => onAction?.({ key: 'style', value: nextPressed ? value : 'unset' })}
|
|
209
258
|
icon={icon}
|
|
210
259
|
>
|
|
211
260
|
{t(`toolbar ${value} label`)}
|
|
@@ -256,8 +305,8 @@ const Actions = () => {
|
|
|
256
305
|
return;
|
|
257
306
|
}
|
|
258
307
|
return onAction?.({
|
|
259
|
-
|
|
260
|
-
|
|
308
|
+
key: 'comment',
|
|
309
|
+
value: addressToIndex(model.sheet, cursor),
|
|
261
310
|
cellContent: model.getCellText(cursor),
|
|
262
311
|
});
|
|
263
312
|
}}
|
|
@@ -272,7 +321,6 @@ export const Toolbar = {
|
|
|
272
321
|
Root: ToolbarRoot,
|
|
273
322
|
Separator: ToolbarSeparator,
|
|
274
323
|
Alignment,
|
|
275
|
-
Format,
|
|
276
324
|
Styles,
|
|
277
325
|
Actions,
|
|
278
326
|
};
|
package/src/defs/index.ts
CHANGED