@dxos/plugin-sheet 0.8.4-main.3c1ae3b → 0.8.4-main.3eb6e50203
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-6DNFC4TY.mjs +397 -0
- package/dist/lib/browser/SheetContainer-6DNFC4TY.mjs.map +7 -0
- package/dist/lib/browser/{anchor-sort-OWOAGQM6.mjs → anchor-sort-AMMLA66W.mjs} +8 -7
- package/dist/lib/browser/anchor-sort-AMMLA66W.mjs.map +7 -0
- package/dist/lib/browser/chunk-EDWHV64N.mjs +1473 -0
- package/dist/lib/browser/chunk-EDWHV64N.mjs.map +7 -0
- package/dist/lib/browser/{chunk-7VEWYJJN.mjs → chunk-IFLWVS2V.mjs} +5 -5
- package/dist/lib/browser/chunk-IFLWVS2V.mjs.map +7 -0
- package/dist/lib/browser/chunk-KE3AKN5W.mjs +397 -0
- package/dist/lib/browser/chunk-KE3AKN5W.mjs.map +7 -0
- package/dist/lib/browser/compute-graph-registry-RC5L7RE4.mjs +21 -0
- package/dist/lib/browser/compute-graph-registry-RC5L7RE4.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +67 -76
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/markdown-D2T2DOVX.mjs +29 -0
- package/dist/lib/browser/markdown-D2T2DOVX.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/operation-resolver-P2RX75DA.mjs +79 -0
- package/dist/lib/browser/operation-resolver-P2RX75DA.mjs.map +7 -0
- package/dist/lib/browser/{react-surface-OAPAEL36.mjs → react-surface-45CRAB5G.mjs} +17 -20
- package/dist/lib/browser/react-surface-45CRAB5G.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +5 -2
- package/dist/lib/node-esm/SheetContainer-7H5R7M54.mjs +398 -0
- package/dist/lib/node-esm/SheetContainer-7H5R7M54.mjs.map +7 -0
- package/dist/lib/node-esm/{anchor-sort-FG3DS4HM.mjs → anchor-sort-VHMBRX2E.mjs} +8 -7
- package/dist/lib/node-esm/anchor-sort-VHMBRX2E.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-6J5L47IB.mjs +398 -0
- package/dist/lib/node-esm/chunk-6J5L47IB.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-AYSEWH7N.mjs +1474 -0
- package/dist/lib/node-esm/chunk-AYSEWH7N.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-4QV4AGWK.mjs → chunk-PPOYR7DK.mjs} +5 -5
- package/dist/lib/node-esm/chunk-PPOYR7DK.mjs.map +7 -0
- package/dist/lib/node-esm/compute-graph-registry-ZGXVLVGD.mjs +22 -0
- package/dist/lib/node-esm/compute-graph-registry-ZGXVLVGD.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +67 -76
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/markdown-PTV72DLO.mjs +30 -0
- package/dist/lib/node-esm/markdown-PTV72DLO.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/operation-resolver-WPIWQ5IO.mjs +80 -0
- package/dist/lib/node-esm/operation-resolver-WPIWQ5IO.mjs.map +7 -0
- package/dist/lib/node-esm/{react-surface-6LO5MPFK.mjs → react-surface-ITV2L6HK.mjs} +17 -20
- package/dist/lib/node-esm/react-surface-ITV2L6HK.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +5 -2
- package/dist/types/src/SheetPlugin.d.ts +2 -1
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/anchor-sort/anchor-sort.d.ts +6 -0
- package/dist/types/src/capabilities/anchor-sort/anchor-sort.d.ts.map +1 -0
- package/dist/types/src/capabilities/anchor-sort/index.d.ts +3 -0
- package/dist/types/src/capabilities/anchor-sort/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/compute-graph-registry/compute-graph-registry.d.ts +5 -0
- package/dist/types/src/capabilities/compute-graph-registry/compute-graph-registry.d.ts.map +1 -0
- package/dist/types/src/capabilities/compute-graph-registry/index.d.ts +3 -0
- package/dist/types/src/capabilities/compute-graph-registry/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +5 -6
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/markdown/index.d.ts +3 -0
- package/dist/types/src/capabilities/markdown/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/markdown/markdown.d.ts +5 -0
- package/dist/types/src/capabilities/markdown/markdown.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/SheetCellEditor.stories.d.ts +1 -1
- package/dist/types/src/components/GridSheet/SheetCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/RangeList/RangeList.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.d.ts +4 -5
- package/dist/types/src/components/SheetContainer/SheetContainer.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts +2 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/SheetToolbar/SheetToolbar.d.ts.map +1 -1
- package/dist/types/src/components/SheetToolbar/align.d.ts +12 -19
- package/dist/types/src/components/SheetToolbar/align.d.ts.map +1 -1
- package/dist/types/src/components/SheetToolbar/style.d.ts +12 -18
- package/dist/types/src/components/SheetToolbar/style.d.ts.map +1 -1
- package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts +14 -1
- package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/compute.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/editor/sheet-extension.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/integrations/thread-ranges.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/model/sheet-model.d.ts.map +1 -1
- package/dist/types/src/testing/testing.d.ts +13 -13
- package/dist/types/src/types/Sheet.d.ts +38 -32
- package/dist/types/src/types/Sheet.d.ts.map +1 -1
- package/dist/types/src/types/capabilities.d.ts +6 -0
- package/dist/types/src/types/capabilities.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +1 -0
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +91 -65
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/types/util.d.ts +2 -1
- package/dist/types/src/types/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +76 -70
- package/src/SheetPlugin.tsx +43 -58
- package/src/capabilities/anchor-sort/anchor-sort.ts +27 -0
- package/src/capabilities/anchor-sort/index.ts +7 -0
- package/src/capabilities/compute-graph-registry/compute-graph-registry.ts +27 -0
- package/src/capabilities/compute-graph-registry/index.ts +7 -0
- package/src/capabilities/index.ts +5 -9
- package/src/capabilities/markdown/index.ts +7 -0
- package/src/capabilities/markdown/markdown.ts +30 -0
- package/src/capabilities/operation-resolver/index.ts +7 -0
- package/src/capabilities/operation-resolver/operation-resolver.ts +77 -0
- package/src/capabilities/react-surface/index.ts +7 -0
- package/src/capabilities/react-surface/react-surface.tsx +43 -0
- package/src/components/ComputeGraph/compute-graph.stories.tsx +1 -1
- package/src/components/GridSheet/GridSheet.stories.tsx +3 -3
- package/src/components/GridSheet/GridSheet.tsx +26 -28
- package/src/components/GridSheet/SheetCellEditor.stories.tsx +7 -4
- package/src/components/GridSheet/util.ts +1 -1
- package/src/components/RangeList/RangeList.tsx +5 -2
- package/src/components/SheetContainer/SheetContainer.stories.tsx +42 -22
- package/src/components/SheetContainer/SheetContainer.tsx +27 -20
- package/src/components/SheetToolbar/SheetToolbar.stories.tsx +1 -1
- package/src/components/SheetToolbar/SheetToolbar.tsx +30 -19
- package/src/components/SheetToolbar/align.ts +41 -16
- package/src/components/SheetToolbar/style.ts +45 -15
- package/src/components/SheetToolbar/useToolbarState.ts +22 -5
- package/src/extensions/compute.stories.tsx +16 -7
- package/src/extensions/compute.ts +1 -1
- package/src/extensions/editor/sheet-extension.ts +7 -4
- package/src/index.ts +1 -1
- package/src/integrations/thread-ranges.ts +36 -40
- package/src/meta.ts +2 -2
- package/src/model/sheet-model.ts +69 -37
- package/src/playwright/playwright.config.ts +1 -1
- package/src/playwright/sheet.spec.ts +1 -0
- package/src/types/Sheet.ts +22 -28
- package/src/{capabilities → types}/capabilities.ts +2 -2
- package/src/types/index.ts +1 -0
- package/src/types/types.ts +81 -37
- package/src/types/util.ts +2 -1
- package/dist/lib/browser/SheetContainer-UAOTJWSB.mjs +0 -349
- package/dist/lib/browser/SheetContainer-UAOTJWSB.mjs.map +0 -7
- package/dist/lib/browser/anchor-sort-OWOAGQM6.mjs.map +0 -7
- package/dist/lib/browser/chunk-73AV3NH6.mjs +0 -15
- package/dist/lib/browser/chunk-73AV3NH6.mjs.map +0 -7
- package/dist/lib/browser/chunk-7VEWYJJN.mjs.map +0 -7
- package/dist/lib/browser/chunk-B7YJQ6NY.mjs +0 -852
- package/dist/lib/browser/chunk-B7YJQ6NY.mjs.map +0 -7
- package/dist/lib/browser/chunk-FWFAAGXL.mjs +0 -28
- package/dist/lib/browser/chunk-FWFAAGXL.mjs.map +0 -7
- package/dist/lib/browser/chunk-GBK6OLCY.mjs +0 -907
- package/dist/lib/browser/chunk-GBK6OLCY.mjs.map +0 -7
- package/dist/lib/browser/compute-graph-registry-AP5RA7W3.mjs +0 -21
- package/dist/lib/browser/compute-graph-registry-AP5RA7W3.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-OMHQGXFL.mjs +0 -56
- package/dist/lib/browser/intent-resolver-OMHQGXFL.mjs.map +0 -7
- package/dist/lib/browser/markdown-B6VKYY2S.mjs +0 -26
- package/dist/lib/browser/markdown-B6VKYY2S.mjs.map +0 -7
- package/dist/lib/browser/react-surface-OAPAEL36.mjs.map +0 -7
- package/dist/lib/node-esm/SheetContainer-37DHGRQD.mjs +0 -350
- package/dist/lib/node-esm/SheetContainer-37DHGRQD.mjs.map +0 -7
- package/dist/lib/node-esm/anchor-sort-FG3DS4HM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2D5E4MPO.mjs +0 -853
- package/dist/lib/node-esm/chunk-2D5E4MPO.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-44YTKTMP.mjs +0 -16
- package/dist/lib/node-esm/chunk-44YTKTMP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4QV4AGWK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HILDMVPL.mjs +0 -29
- package/dist/lib/node-esm/chunk-HILDMVPL.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-KSHCRK5J.mjs +0 -908
- package/dist/lib/node-esm/chunk-KSHCRK5J.mjs.map +0 -7
- package/dist/lib/node-esm/compute-graph-registry-UMQ5UYCL.mjs +0 -22
- package/dist/lib/node-esm/compute-graph-registry-UMQ5UYCL.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-DHEHYV3B.mjs +0 -57
- package/dist/lib/node-esm/intent-resolver-DHEHYV3B.mjs.map +0 -7
- package/dist/lib/node-esm/markdown-VKY7HXU2.mjs +0 -27
- package/dist/lib/node-esm/markdown-VKY7HXU2.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-6LO5MPFK.mjs.map +0 -7
- package/dist/types/src/capabilities/anchor-sort.d.ts +0 -4
- package/dist/types/src/capabilities/anchor-sort.d.ts.map +0 -1
- package/dist/types/src/capabilities/capabilities.d.ts +0 -5
- package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
- package/dist/types/src/capabilities/compute-graph-registry.d.ts +0 -4
- package/dist/types/src/capabilities/compute-graph-registry.d.ts.map +0 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
- package/dist/types/src/capabilities/markdown.d.ts +0 -4
- package/dist/types/src/capabilities/markdown.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-surface.d.ts +0 -4
- package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
- package/src/capabilities/anchor-sort.ts +0 -21
- package/src/capabilities/compute-graph-registry.ts +0 -23
- package/src/capabilities/intent-resolver.ts +0 -38
- package/src/capabilities/markdown.ts +0 -23
- package/src/capabilities/react-surface.tsx +0 -41
|
@@ -2,16 +2,25 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type Registry, RegistryContext } from '@effect-atom/atom-react';
|
|
6
|
+
import { useContext, useEffect } from 'react';
|
|
6
7
|
|
|
7
8
|
import { type CompleteCellRange, inRange } from '@dxos/compute';
|
|
8
|
-
import {
|
|
9
|
+
import { Obj } from '@dxos/echo';
|
|
10
|
+
import {
|
|
11
|
+
type ActionGraphProps,
|
|
12
|
+
type ToolbarMenuActionGroupProperties,
|
|
13
|
+
createMenuAction,
|
|
14
|
+
createMenuItemGroup,
|
|
15
|
+
} from '@dxos/react-ui-menu';
|
|
9
16
|
|
|
10
17
|
import { meta } from '../../meta';
|
|
11
18
|
import { type SheetModel } from '../../model';
|
|
12
19
|
import { type StyleKey, type StyleValue, rangeFromIndex, rangeToIndex } from '../../types';
|
|
13
20
|
import { useSheetContext } from '../SheetContext';
|
|
14
21
|
|
|
22
|
+
import { type ToolbarState, type ToolbarStateAtom } from './useToolbarState';
|
|
23
|
+
|
|
15
24
|
export type StyleState = Partial<Record<StyleValue, boolean>>;
|
|
16
25
|
|
|
17
26
|
export type StyleAction = { key: StyleKey; value: StyleValue };
|
|
@@ -21,22 +30,30 @@ const styles: Record<StyleValue, string> = {
|
|
|
21
30
|
softwrap: 'ph--paragraph--regular',
|
|
22
31
|
};
|
|
23
32
|
|
|
24
|
-
export const useStyleState = (
|
|
33
|
+
export const useStyleState = (stateAtom: ToolbarStateAtom) => {
|
|
34
|
+
const registry = useContext(RegistryContext);
|
|
25
35
|
const { cursorFallbackRange, model } = useSheetContext();
|
|
26
36
|
|
|
27
37
|
useEffect(() => {
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
let highlight = false;
|
|
39
|
+
let softwrap = false;
|
|
30
40
|
if (cursorFallbackRange && model.sheet.ranges) {
|
|
31
41
|
model.sheet.ranges
|
|
32
42
|
.filter(
|
|
33
43
|
({ range, key }) => key === 'style' && inRange(rangeFromIndex(model.sheet, range), cursorFallbackRange.from),
|
|
34
44
|
)
|
|
35
45
|
.forEach(({ value }) => {
|
|
36
|
-
|
|
46
|
+
if (value === 'highlight') {
|
|
47
|
+
highlight = true;
|
|
48
|
+
}
|
|
49
|
+
if (value === 'softwrap') {
|
|
50
|
+
softwrap = true;
|
|
51
|
+
}
|
|
37
52
|
});
|
|
38
53
|
}
|
|
39
|
-
|
|
54
|
+
const prev = registry.get(stateAtom);
|
|
55
|
+
registry.set(stateAtom, { ...prev, highlight, softwrap });
|
|
56
|
+
}, [cursorFallbackRange, model.sheet, registry, stateAtom]);
|
|
40
57
|
};
|
|
41
58
|
|
|
42
59
|
const createStyleGroup = (state: StyleState) => {
|
|
@@ -49,7 +66,15 @@ const createStyleGroup = (state: StyleState) => {
|
|
|
49
66
|
} as ToolbarMenuActionGroupProperties);
|
|
50
67
|
};
|
|
51
68
|
|
|
52
|
-
|
|
69
|
+
type StyleActionsContext = {
|
|
70
|
+
model: SheetModel;
|
|
71
|
+
state: ToolbarState;
|
|
72
|
+
stateAtom: ToolbarStateAtom;
|
|
73
|
+
registry: Registry.Registry;
|
|
74
|
+
cursorFallbackRange?: CompleteCellRange;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const createStyleActions = ({ model, state, stateAtom, registry, cursorFallbackRange }: StyleActionsContext) =>
|
|
53
78
|
Object.entries(styles).map(([styleValue, icon]) => {
|
|
54
79
|
return createMenuAction<StyleAction>(
|
|
55
80
|
`style--${styleValue}`,
|
|
@@ -67,6 +92,7 @@ const createStyleActions = (model: SheetModel, state: StyleState, cursorFallback
|
|
|
67
92
|
key: 'style',
|
|
68
93
|
value: styleValue as StyleValue,
|
|
69
94
|
};
|
|
95
|
+
const currentState = registry.get(stateAtom);
|
|
70
96
|
if (
|
|
71
97
|
model.sheet.ranges
|
|
72
98
|
.filter(
|
|
@@ -77,12 +103,16 @@ const createStyleActions = (model: SheetModel, state: StyleState, cursorFallback
|
|
|
77
103
|
) {
|
|
78
104
|
// this value should be unset
|
|
79
105
|
if (index >= 0) {
|
|
80
|
-
model.sheet
|
|
106
|
+
Obj.change(model.sheet, (obj) => {
|
|
107
|
+
obj.ranges?.splice(index, 1);
|
|
108
|
+
});
|
|
81
109
|
}
|
|
82
|
-
|
|
110
|
+
registry.set(stateAtom, { ...currentState, [nextRangeEntity.value]: false });
|
|
83
111
|
} else {
|
|
84
|
-
model.sheet
|
|
85
|
-
|
|
112
|
+
Obj.change(model.sheet, (obj) => {
|
|
113
|
+
obj.ranges?.push(nextRangeEntity);
|
|
114
|
+
});
|
|
115
|
+
registry.set(stateAtom, { ...currentState, [nextRangeEntity.value]: true });
|
|
86
116
|
}
|
|
87
117
|
},
|
|
88
118
|
{
|
|
@@ -95,9 +125,9 @@ const createStyleActions = (model: SheetModel, state: StyleState, cursorFallback
|
|
|
95
125
|
);
|
|
96
126
|
});
|
|
97
127
|
|
|
98
|
-
export const createStyle = (
|
|
99
|
-
const styleGroupAction = createStyleGroup(state);
|
|
100
|
-
const styleActions = createStyleActions(
|
|
128
|
+
export const createStyle = (context: StyleActionsContext): ActionGraphProps => {
|
|
129
|
+
const styleGroupAction = createStyleGroup(context.state);
|
|
130
|
+
const styleActions = createStyleActions(context);
|
|
101
131
|
return {
|
|
102
132
|
nodes: [styleGroupAction, ...styleActions],
|
|
103
133
|
edges: [
|
|
@@ -2,15 +2,32 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import { live } from '@dxos/live-object';
|
|
5
|
+
import { Atom, type Registry, RegistryContext, useAtomValue } from '@effect-atom/atom-react';
|
|
6
|
+
import { useContext, useMemo } from 'react';
|
|
8
7
|
|
|
9
8
|
import { type AlignState } from './align';
|
|
10
9
|
import { type StyleState } from './style';
|
|
11
10
|
|
|
12
11
|
export type ToolbarState = Partial<StyleState & AlignState>;
|
|
12
|
+
export type ToolbarStateAtom = Atom.Writable<ToolbarState>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a reactive toolbar state Atom.
|
|
16
|
+
*/
|
|
17
|
+
export const useToolbarState = (initialState: ToolbarState = {}): ToolbarStateAtom => {
|
|
18
|
+
return useMemo(() => Atom.make<ToolbarState>(initialState).pipe(Atom.keepAlive), []);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook to read the current toolbar state value.
|
|
23
|
+
*/
|
|
24
|
+
export const useToolbarStateValue = (stateAtom: ToolbarStateAtom): ToolbarState => {
|
|
25
|
+
return useAtomValue(stateAtom);
|
|
26
|
+
};
|
|
13
27
|
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Hook to get the registry for updating toolbar state.
|
|
30
|
+
*/
|
|
31
|
+
export const useToolbarStateRegistry = (): Registry.Registry => {
|
|
32
|
+
return useContext(RegistryContext);
|
|
16
33
|
};
|
|
@@ -5,21 +5,21 @@
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
6
|
import React, { useEffect, useMemo } from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { OperationPlugin, RuntimePlugin } from '@dxos/app-framework';
|
|
9
9
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
10
10
|
import { PublicKey } from '@dxos/keys';
|
|
11
11
|
import { useSpace } from '@dxos/react-client/echo';
|
|
12
12
|
import { withClientProvider } from '@dxos/react-client/testing';
|
|
13
13
|
import { useThemeContext } from '@dxos/react-ui';
|
|
14
14
|
import { withTheme } from '@dxos/react-ui/testing';
|
|
15
|
+
import { useTextEditor } from '@dxos/react-ui-editor';
|
|
15
16
|
import {
|
|
16
17
|
createBasicExtensions,
|
|
17
18
|
createMarkdownExtensions,
|
|
18
19
|
createThemeExtensions,
|
|
19
20
|
decorateMarkdown,
|
|
20
21
|
documentId,
|
|
21
|
-
|
|
22
|
-
} from '@dxos/react-ui-editor';
|
|
22
|
+
} from '@dxos/ui-editor';
|
|
23
23
|
import { isNonNullable } from '@dxos/util';
|
|
24
24
|
|
|
25
25
|
import { GridSheet, SheetProvider, useComputeGraph } from '../components';
|
|
@@ -73,7 +73,12 @@ const Grid = () => {
|
|
|
73
73
|
const model = useSheetModel(graph, sheet);
|
|
74
74
|
useEffect(() => {
|
|
75
75
|
if (model) {
|
|
76
|
-
model.setValues({
|
|
76
|
+
model.setValues({
|
|
77
|
+
A1: { value: 100 },
|
|
78
|
+
A2: { value: 200 },
|
|
79
|
+
A3: { value: 300 },
|
|
80
|
+
A5: { value: '=SUM(A1:A3)' },
|
|
81
|
+
});
|
|
77
82
|
}
|
|
78
83
|
}, [model]);
|
|
79
84
|
|
|
@@ -102,10 +107,14 @@ const GraphStory = (props: EditorProps) => {
|
|
|
102
107
|
const meta = {
|
|
103
108
|
title: 'plugins/plugin-sheet/extensions',
|
|
104
109
|
decorators: [
|
|
105
|
-
withTheme,
|
|
106
|
-
withClientProvider({
|
|
110
|
+
withTheme(),
|
|
111
|
+
withClientProvider({
|
|
112
|
+
types: [Sheet.Sheet],
|
|
113
|
+
createIdentity: true,
|
|
114
|
+
createSpace: true,
|
|
115
|
+
}),
|
|
107
116
|
// TODO(wittjosiah): Try to write story which does not depend on plugin manager.
|
|
108
|
-
withPluginManager({ plugins: [
|
|
117
|
+
withPluginManager({ plugins: [OperationPlugin(), RuntimePlugin()] }),
|
|
109
118
|
withComputeGraphDecorator(),
|
|
110
119
|
],
|
|
111
120
|
parameters: {
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
createSheetName,
|
|
24
24
|
} from '@dxos/compute';
|
|
25
25
|
import { invariant } from '@dxos/invariant';
|
|
26
|
-
import { documentId, singleValueFacet } from '@dxos/
|
|
26
|
+
import { documentId, singleValueFacet } from '@dxos/ui-editor';
|
|
27
27
|
|
|
28
28
|
const LANGUAGE_TAG = 'dx';
|
|
29
29
|
|
|
@@ -20,8 +20,8 @@ import { spreadsheet } from 'codemirror-lang-spreadsheet';
|
|
|
20
20
|
|
|
21
21
|
import { type FunctionDefinition } from '@dxos/compute';
|
|
22
22
|
import { RANGE_NOTATION } from '@dxos/compute';
|
|
23
|
-
import { singleValueFacet } from '@dxos/
|
|
24
|
-
import { mx } from '@dxos/
|
|
23
|
+
import { singleValueFacet } from '@dxos/ui-editor';
|
|
24
|
+
import { mx } from '@dxos/ui-theme';
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* https://codemirror.net/examples/styling
|
|
@@ -75,7 +75,10 @@ export type SheetExtensionOptions = {
|
|
|
75
75
|
* https://hyperformula.handsontable.com/guide/key-concepts.html#grammar
|
|
76
76
|
*/
|
|
77
77
|
export const sheetExtension = ({ debug, functions = [] }: SheetExtensionOptions): Extension => {
|
|
78
|
-
const { extension, language } = spreadsheet({
|
|
78
|
+
const { extension, language } = spreadsheet({
|
|
79
|
+
idiom: 'en-US',
|
|
80
|
+
decimalSeparator: '.',
|
|
81
|
+
});
|
|
79
82
|
|
|
80
83
|
const createCompletion = (name: string) => {
|
|
81
84
|
const { section = 'Custom', description, syntax } = functions.find((value) => value.name === name) ?? {};
|
|
@@ -166,7 +169,7 @@ export const sheetExtension = ({ debug, functions = [] }: SheetExtensionOptions)
|
|
|
166
169
|
icons: false,
|
|
167
170
|
tooltipClass: () =>
|
|
168
171
|
mx(
|
|
169
|
-
'!-left-[1px] !top-[33px] !-m-0 border !border-
|
|
172
|
+
'!-left-[1px] !top-[33px] !-m-0 border !border-bs-0 [&>ul]:!min-w-[198px]',
|
|
170
173
|
'[&>ul>li[aria-selected]]:!bg-accentSurface',
|
|
171
174
|
'border-separator',
|
|
172
175
|
),
|
package/src/index.ts
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import * as
|
|
6
|
-
import * as Schema from 'effect/Schema';
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
7
6
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
8
7
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { useOperationInvoker, useOperationResolver } from '@dxos/app-framework/ui';
|
|
9
|
+
import { LayoutOperation } from '@dxos/app-toolkit';
|
|
11
10
|
import { debounce } from '@dxos/async';
|
|
12
11
|
import { type CellAddress, type CompleteCellRange, inRange } from '@dxos/compute';
|
|
13
12
|
import { Obj, Relation } from '@dxos/echo';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
13
|
+
import { OperationResolver } from '@dxos/operation';
|
|
14
|
+
import { ATTENDABLE_PATH_SEPARATOR, DeckOperation } from '@dxos/plugin-deck/types';
|
|
15
|
+
import { ThreadOperation } from '@dxos/plugin-thread/types';
|
|
16
|
+
import { Filter, Query, useQuery } from '@dxos/react-client/echo';
|
|
17
17
|
import { type DxGridElement, type GridContentProps } from '@dxos/react-ui-grid';
|
|
18
18
|
import { AnchoredTo, Thread } from '@dxos/types';
|
|
19
19
|
|
|
@@ -39,43 +39,37 @@ export const parseThreadAnchorAsCellRange = (cursor: string): CompleteCellRange
|
|
|
39
39
|
|
|
40
40
|
export const useUpdateFocusedCellOnThreadSelection = (grid: DxGridElement | null) => {
|
|
41
41
|
const { model, setActiveRefs } = useSheetContext();
|
|
42
|
-
const
|
|
42
|
+
const sheetId = Obj.getDXN(model.sheet).toString();
|
|
43
|
+
|
|
44
|
+
const scrollIntoViewHandler = useMemo(
|
|
43
45
|
() =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
OperationResolver.make({
|
|
47
|
+
operation: LayoutOperation.ScrollIntoView,
|
|
46
48
|
position: 'hoist',
|
|
47
|
-
filter: (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return data.subject === Obj.getDXN(model.sheet).toString() && !!data.options?.cursor;
|
|
59
|
-
},
|
|
60
|
-
resolve: ({ options: { cursor, ref } }) => {
|
|
61
|
-
setActiveRefs(ref);
|
|
62
|
-
// TODO(Zan): Everywhere we refer to the cursor in a thread context should change to `anchor`.
|
|
63
|
-
const range = parseThreadAnchorAsCellRange(cursor!);
|
|
64
|
-
range && grid?.setFocus({ ...range.to, plane: 'grid' }, true);
|
|
65
|
-
},
|
|
49
|
+
filter: (input) => input.subject === sheetId && !!input.cursor,
|
|
50
|
+
handler: (input) =>
|
|
51
|
+
Effect.sync(() => {
|
|
52
|
+
const { cursor, ref } = input;
|
|
53
|
+
if (cursor) {
|
|
54
|
+
setActiveRefs(ref as GridContentProps['activeRefs']);
|
|
55
|
+
// TODO(Zan): Everywhere we refer to the cursor in a thread context should change to `anchor`.
|
|
56
|
+
const range = parseThreadAnchorAsCellRange(cursor);
|
|
57
|
+
range && grid?.setFocus({ ...range.to, plane: 'grid' }, true);
|
|
58
|
+
}
|
|
59
|
+
}),
|
|
66
60
|
}),
|
|
67
|
-
[
|
|
61
|
+
[sheetId, setActiveRefs, grid],
|
|
68
62
|
);
|
|
69
63
|
|
|
70
|
-
|
|
64
|
+
useOperationResolver(meta.id, scrollIntoViewHandler);
|
|
71
65
|
};
|
|
72
66
|
|
|
73
67
|
export const useSelectThreadOnCellFocus = () => {
|
|
74
68
|
const { model, cursor } = useSheetContext();
|
|
75
|
-
const {
|
|
69
|
+
const { invokePromise } = useOperationInvoker();
|
|
76
70
|
|
|
77
|
-
const
|
|
78
|
-
const anchors = useQuery(
|
|
71
|
+
const db = Obj.getDatabase(model.sheet);
|
|
72
|
+
const anchors = useQuery(db, Query.select(Filter.id(model.sheet.id)).targetOf(AnchoredTo.AnchoredTo));
|
|
79
73
|
|
|
80
74
|
const selectClosestThread = useCallback(
|
|
81
75
|
(cellAddress: CellAddress) => {
|
|
@@ -95,14 +89,16 @@ export const useSelectThreadOnCellFocus = () => {
|
|
|
95
89
|
|
|
96
90
|
if (closestThread) {
|
|
97
91
|
const primary = Obj.getDXN(model.sheet).toString();
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
void (async () => {
|
|
93
|
+
await invokePromise(ThreadOperation.Select, { current: Relation.getDXN(closestThread).toString() });
|
|
94
|
+
await invokePromise(DeckOperation.ChangeCompanion, {
|
|
95
|
+
primary,
|
|
96
|
+
companion: `${primary}${ATTENDABLE_PATH_SEPARATOR}comments`,
|
|
97
|
+
});
|
|
98
|
+
})();
|
|
103
99
|
}
|
|
104
100
|
},
|
|
105
|
-
[
|
|
101
|
+
[invokePromise, anchors],
|
|
106
102
|
);
|
|
107
103
|
|
|
108
104
|
const debounced = useMemo(() => {
|
package/src/meta.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type
|
|
5
|
+
import { type Plugin } from '@dxos/app-framework';
|
|
6
6
|
import { trim } from '@dxos/util';
|
|
7
7
|
|
|
8
|
-
export const meta:
|
|
8
|
+
export const meta: Plugin.Meta = {
|
|
9
9
|
id: 'dxos.org/plugin/sheet',
|
|
10
10
|
name: 'Sheet',
|
|
11
11
|
description: trim`
|
package/src/model/sheet-model.ts
CHANGED
|
@@ -122,7 +122,9 @@ export class SheetModel extends Resource {
|
|
|
122
122
|
*/
|
|
123
123
|
protected override async _open(): Promise<void> {
|
|
124
124
|
log('initialize', { id: this.id });
|
|
125
|
-
|
|
125
|
+
Obj.change(this._sheet, (obj) => {
|
|
126
|
+
initialize(obj);
|
|
127
|
+
});
|
|
126
128
|
|
|
127
129
|
this._graph.update.on((event) => {
|
|
128
130
|
if (event.type === 'functionsUpdated') {
|
|
@@ -181,13 +183,19 @@ export class SheetModel extends Resource {
|
|
|
181
183
|
}
|
|
182
184
|
|
|
183
185
|
insertRows(i: number, n = 1): string[] {
|
|
184
|
-
|
|
186
|
+
let idx: string[] = [];
|
|
187
|
+
Obj.change(this._sheet, (obj) => {
|
|
188
|
+
idx = insertIndices(obj.rows, i, n, MAX_ROWS);
|
|
189
|
+
});
|
|
185
190
|
this.reset();
|
|
186
191
|
return idx;
|
|
187
192
|
}
|
|
188
193
|
|
|
189
194
|
insertColumns(i: number, n = 1): string[] {
|
|
190
|
-
|
|
195
|
+
let idx: string[] = [];
|
|
196
|
+
Obj.change(this._sheet, (obj) => {
|
|
197
|
+
idx = insertIndices(obj.columns, i, n, MAX_COLS);
|
|
198
|
+
});
|
|
191
199
|
this.reset();
|
|
192
200
|
return idx;
|
|
193
201
|
}
|
|
@@ -200,8 +208,10 @@ export class SheetModel extends Resource {
|
|
|
200
208
|
const values = this.getCellValues(range).flat();
|
|
201
209
|
const index = this._sheet.rows.indexOf(rowIndex);
|
|
202
210
|
this.clear(range);
|
|
203
|
-
this._sheet
|
|
204
|
-
|
|
211
|
+
Obj.change(this._sheet, (obj) => {
|
|
212
|
+
obj.rows.splice(index, 1);
|
|
213
|
+
delete obj.rowMeta[rowIndex];
|
|
214
|
+
});
|
|
205
215
|
this.reset();
|
|
206
216
|
return { axis: 'row', index, axisIndex: rowIndex, axisMeta: this._sheet.rowMeta[rowIndex], values };
|
|
207
217
|
}
|
|
@@ -214,35 +224,43 @@ export class SheetModel extends Resource {
|
|
|
214
224
|
const values = this.getCellValues(range).flat();
|
|
215
225
|
const index = this._sheet.columns.indexOf(colIndex);
|
|
216
226
|
this.clear(range);
|
|
217
|
-
this._sheet
|
|
218
|
-
|
|
227
|
+
Obj.change(this._sheet, (obj) => {
|
|
228
|
+
obj.columns.splice(index, 1);
|
|
229
|
+
delete obj.columnMeta[colIndex];
|
|
230
|
+
});
|
|
219
231
|
this.reset();
|
|
220
232
|
return { axis: 'col', index, axisIndex: colIndex, axisMeta: this._sheet.rowMeta[colIndex], values };
|
|
221
233
|
}
|
|
222
234
|
|
|
223
235
|
restoreRow({ index, axisIndex, axisMeta, values }: SheetAction.RestoreAxis): void {
|
|
224
|
-
this._sheet
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
236
|
+
Obj.change(this._sheet, (obj) => {
|
|
237
|
+
obj.rows.splice(index, 0, axisIndex);
|
|
238
|
+
values.forEach((value, col) => {
|
|
239
|
+
if (value) {
|
|
240
|
+
obj.cells[`${obj.columns[col]}@${axisIndex}`] = { value };
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
if (axisMeta) {
|
|
245
|
+
obj.rowMeta[axisIndex] = axisMeta;
|
|
228
246
|
}
|
|
229
247
|
});
|
|
230
|
-
if (axisMeta) {
|
|
231
|
-
this._sheet.rowMeta[axisIndex] = axisMeta;
|
|
232
|
-
}
|
|
233
248
|
this.reset();
|
|
234
249
|
}
|
|
235
250
|
|
|
236
251
|
restoreColumn({ index, axisIndex, axisMeta, values }: SheetAction.RestoreAxis): void {
|
|
237
|
-
this._sheet
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
252
|
+
Obj.change(this._sheet, (obj) => {
|
|
253
|
+
obj.columns.splice(index, 0, axisIndex);
|
|
254
|
+
values.forEach((value, row) => {
|
|
255
|
+
if (value) {
|
|
256
|
+
obj.cells[`${axisIndex}@${obj.rows[row]}`] = { value };
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
if (axisMeta) {
|
|
261
|
+
obj.columnMeta[axisIndex] = axisMeta;
|
|
241
262
|
}
|
|
242
263
|
});
|
|
243
|
-
if (axisMeta) {
|
|
244
|
-
this._sheet.columnMeta[axisIndex] = axisMeta;
|
|
245
|
-
}
|
|
246
264
|
this.reset();
|
|
247
265
|
}
|
|
248
266
|
|
|
@@ -259,18 +277,22 @@ export class SheetModel extends Resource {
|
|
|
259
277
|
const topLeft = getTopLeft(range);
|
|
260
278
|
const values = this._iterRange(range, () => null);
|
|
261
279
|
this._node.graph.hf.setCellContents(toSimpleCellAddress(this._node.sheetId, topLeft), values);
|
|
262
|
-
this.
|
|
263
|
-
|
|
264
|
-
|
|
280
|
+
Obj.change(this._sheet, (obj) => {
|
|
281
|
+
this._iterRange(range, (cell) => {
|
|
282
|
+
const idx = addressToIndex(this._sheet, cell);
|
|
283
|
+
delete obj.cells[idx];
|
|
284
|
+
});
|
|
265
285
|
});
|
|
266
286
|
}
|
|
267
287
|
|
|
268
288
|
cut(range: CellRange): void {
|
|
269
289
|
invariant(this._node);
|
|
270
290
|
this._node.graph.hf.cut(toModelRange(this._node.sheetId, range));
|
|
271
|
-
this.
|
|
272
|
-
|
|
273
|
-
|
|
291
|
+
Obj.change(this._sheet, (obj) => {
|
|
292
|
+
this._iterRange(range, (cell) => {
|
|
293
|
+
const idx = addressToIndex(this._sheet, cell);
|
|
294
|
+
delete obj.cells[idx];
|
|
295
|
+
});
|
|
274
296
|
});
|
|
275
297
|
}
|
|
276
298
|
|
|
@@ -283,13 +305,15 @@ export class SheetModel extends Resource {
|
|
|
283
305
|
invariant(this._node);
|
|
284
306
|
if (!this._node.graph.hf.isClipboardEmpty()) {
|
|
285
307
|
const changes = this._node.graph.hf.paste(toSimpleCellAddress(this._node.sheetId, cell));
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
308
|
+
Obj.change(this._sheet, (obj) => {
|
|
309
|
+
for (const change of changes) {
|
|
310
|
+
if (change instanceof ExportedCellChange) {
|
|
311
|
+
const { address, newValue } = change;
|
|
312
|
+
const idx = addressToIndex(this._sheet, { row: address.row, col: address.col });
|
|
313
|
+
obj.cells[idx] = { value: newValue };
|
|
314
|
+
}
|
|
291
315
|
}
|
|
292
|
-
}
|
|
316
|
+
});
|
|
293
317
|
}
|
|
294
318
|
}
|
|
295
319
|
|
|
@@ -380,11 +404,15 @@ export class SheetModel extends Resource {
|
|
|
380
404
|
// Reallocate if > current bounds.
|
|
381
405
|
let refresh = false;
|
|
382
406
|
if (cell.row >= this._sheet.rows.length) {
|
|
383
|
-
|
|
407
|
+
Obj.change(this._sheet, (obj) => {
|
|
408
|
+
insertIndices(obj.rows, cell.row, 1, MAX_ROWS);
|
|
409
|
+
});
|
|
384
410
|
refresh = true;
|
|
385
411
|
}
|
|
386
412
|
if (cell.col >= this._sheet.columns.length) {
|
|
387
|
-
|
|
413
|
+
Obj.change(this._sheet, (obj) => {
|
|
414
|
+
insertIndices(obj.columns, cell.col, 1, MAX_COLS);
|
|
415
|
+
});
|
|
388
416
|
refresh = true;
|
|
389
417
|
}
|
|
390
418
|
|
|
@@ -401,13 +429,17 @@ export class SheetModel extends Resource {
|
|
|
401
429
|
// Insert into sheet.
|
|
402
430
|
const idx = addressToIndex(this._sheet, cell);
|
|
403
431
|
if (value === undefined || value === null) {
|
|
404
|
-
|
|
432
|
+
Obj.change(this._sheet, (obj) => {
|
|
433
|
+
delete obj.cells[idx];
|
|
434
|
+
});
|
|
405
435
|
} else {
|
|
406
436
|
if (isFormula(value)) {
|
|
407
437
|
value = this._graph.mapFunctionBindingToId(mapFormulaRefsToIndices(this._sheet, value));
|
|
408
438
|
}
|
|
409
439
|
|
|
410
|
-
this._sheet
|
|
440
|
+
Obj.change(this._sheet, (obj) => {
|
|
441
|
+
obj.cells[idx] = { value };
|
|
442
|
+
});
|
|
411
443
|
}
|
|
412
444
|
}
|
|
413
445
|
|
|
@@ -10,7 +10,7 @@ export default defineConfig({
|
|
|
10
10
|
...e2ePreset(import.meta.dirname),
|
|
11
11
|
// TODO(wittjosiah): Avoid hard-coding ports.
|
|
12
12
|
webServer: {
|
|
13
|
-
command: 'moon run storybook:serve-e2e -- --port=9005',
|
|
13
|
+
command: 'moon run storybook-react:serve-e2e -- --port=9005',
|
|
14
14
|
port: 9005,
|
|
15
15
|
reuseExistingServer: false,
|
|
16
16
|
},
|
|
@@ -16,6 +16,7 @@ test.describe('plugin-sheet', () => {
|
|
|
16
16
|
test.beforeEach(async ({ browser }) => {
|
|
17
17
|
const setup = await setupPage(browser, {
|
|
18
18
|
url: storybookUrl('plugins-plugin-sheet-sheetcontainer--spec', 9005),
|
|
19
|
+
viewportSize: { width: 1280, height: 720 },
|
|
19
20
|
});
|
|
20
21
|
page = setup.page;
|
|
21
22
|
sheet = new SheetManager(page);
|