@dxos/plugin-sheet 0.6.14-main.7bd9c89 → 0.6.14-staging.9e90729
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-AKWROARP.mjs → SheetContainer-JBB7W52Y.mjs} +42 -52
- package/dist/lib/browser/SheetContainer-JBB7W52Y.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GSV5QNLD.mjs → chunk-2ZK3YMZG.mjs} +248 -33
- package/dist/lib/browser/{chunk-GSV5QNLD.mjs.map → chunk-2ZK3YMZG.mjs.map} +4 -4
- package/dist/lib/browser/{chunk-BWN5DZWZ.mjs → chunk-3QWIMZZJ.mjs} +2 -11
- package/dist/lib/browser/chunk-3QWIMZZJ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FGMFOW6U.mjs → chunk-XXDHBYZQ.mjs} +553 -668
- package/dist/lib/browser/chunk-XXDHBYZQ.mjs.map +7 -0
- package/dist/lib/browser/{graph-M4IQ76QX.mjs → compute-graph-ZQKB6QVP.mjs} +4 -2
- package/dist/lib/browser/index.mjs +57 -14
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types.mjs +1 -1
- package/dist/lib/node/{SheetContainer-N5IQGEFL.cjs → SheetContainer-L37HUFCF.cjs} +44 -58
- package/dist/lib/node/SheetContainer-L37HUFCF.cjs.map +7 -0
- package/dist/lib/node/{chunk-53BMSUIK.cjs → chunk-7AWAC3R3.cjs} +517 -645
- package/dist/lib/node/chunk-7AWAC3R3.cjs.map +7 -0
- package/dist/lib/node/{chunk-5XPK2V4A.cjs → chunk-QNFMTK3X.cjs} +252 -28
- package/dist/lib/node/{chunk-5XPK2V4A.cjs.map → chunk-QNFMTK3X.cjs.map} +4 -4
- package/dist/lib/node/{chunk-NZARD7UP.cjs → chunk-V7E5JZBD.cjs} +5 -14
- package/dist/lib/node/chunk-V7E5JZBD.cjs.map +7 -0
- package/dist/lib/node/{graph-Q3N2X26H.cjs → compute-graph-RJB6OVW6.cjs} +21 -19
- package/dist/lib/node/compute-graph-RJB6OVW6.cjs.map +7 -0
- package/dist/lib/node/index.cjs +66 -27
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +6 -6
- package/dist/lib/node/types.cjs.map +1 -1
- package/dist/lib/node-esm/{SheetContainer-46PBMF2E.mjs → SheetContainer-CLKFEM35.mjs} +42 -52
- package/dist/lib/node-esm/SheetContainer-CLKFEM35.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-T3PRH7QS.mjs → chunk-3JYJEOCF.mjs} +553 -668
- package/dist/lib/node-esm/chunk-3JYJEOCF.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-5WPZCXNS.mjs → chunk-JBTORSST.mjs} +247 -33
- package/dist/lib/node-esm/{chunk-5WPZCXNS.mjs.map → chunk-JBTORSST.mjs.map} +4 -4
- package/dist/lib/node-esm/{chunk-WFDTY3IC.mjs → chunk-SPQFLYC2.mjs} +2 -11
- package/dist/lib/node-esm/chunk-SPQFLYC2.mjs.map +7 -0
- package/dist/lib/node-esm/{graph-SMPUMOV2.mjs → compute-graph-VKRG526N.mjs} +4 -2
- package/dist/lib/node-esm/index.mjs +57 -14
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types.mjs +1 -1
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +3 -1
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +1 -1
- 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/util.d.ts.map +1 -1
- package/dist/types/src/components/RangeList/RangeList.d.ts +9 -0
- package/dist/types/src/components/RangeList/RangeList.d.ts.map +1 -0
- package/dist/types/src/components/RangeList/index.d.ts +2 -0
- package/dist/types/src/components/RangeList/index.d.ts.map +1 -0
- package/dist/types/src/components/SheetContext/SheetContext.d.ts +7 -5
- package/dist/types/src/components/SheetContext/SheetContext.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/compute-graph/compute-graph-registry.d.ts.map +1 -0
- package/dist/types/src/{graph → compute-graph}/compute-graph.d.ts +1 -1
- package/dist/types/src/compute-graph/compute-graph.d.ts.map +1 -0
- package/dist/types/src/compute-graph/compute-graph.stories.d.ts.map +1 -0
- package/dist/types/src/compute-graph/compute-graph.test.d.ts.map +1 -0
- package/dist/types/src/compute-graph/compute-node.d.ts.map +1 -0
- package/dist/types/src/compute-graph/functions/async-function.d.ts.map +1 -0
- package/dist/types/src/compute-graph/functions/edge-function.d.ts.map +1 -0
- package/dist/types/src/compute-graph/functions/function-defs.d.ts.map +1 -0
- package/dist/types/src/compute-graph/functions/index.d.ts.map +1 -0
- package/dist/types/src/compute-graph/hyperformula.test.d.ts.map +1 -0
- package/dist/types/src/compute-graph/index.d.ts.map +1 -0
- package/dist/types/src/compute-graph/testing/index.d.ts.map +1 -0
- package/dist/types/src/compute-graph/testing/test-builder.d.ts.map +1 -0
- package/dist/types/src/compute-graph/testing/test-plugin.d.ts.map +1 -0
- package/dist/types/src/compute-graph/util.d.ts.map +1 -0
- package/dist/types/src/defs/index.d.ts +1 -1
- package/dist/types/src/defs/index.d.ts.map +1 -1
- package/dist/types/src/defs/sheet-range-types.d.ts.map +1 -1
- package/dist/types/src/defs/types.d.ts +6 -0
- package/dist/types/src/defs/types.d.ts.map +1 -1
- package/dist/types/src/defs/util.d.ts +2 -6
- package/dist/types/src/defs/util.d.ts.map +1 -1
- package/dist/types/src/extensions/compute.d.ts +1 -1
- package/dist/types/src/extensions/compute.d.ts.map +1 -1
- package/dist/types/src/extensions/editor/extension.d.ts +23 -3
- package/dist/types/src/extensions/editor/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/index.d.ts +2 -0
- package/dist/types/src/integrations/index.d.ts.map +1 -0
- package/dist/types/src/integrations/thread-ranges.d.ts +8 -0
- package/dist/types/src/integrations/thread-ranges.d.ts.map +1 -0
- package/dist/types/src/model/index.d.ts +1 -1
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/sheet-model.d.ts +1 -1
- package/dist/types/src/model/sheet-model.d.ts.map +1 -1
- package/dist/types/src/{hooks → model}/useSheetModel.d.ts +1 -1
- package/dist/types/src/model/useSheetModel.d.ts.map +1 -0
- package/dist/types/src/serializer.d.ts +4 -0
- package/dist/types/src/serializer.d.ts.map +1 -0
- package/dist/types/src/testing/testing.d.ts +1 -1
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +6 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +4 -30
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +43 -50
- package/src/SheetPlugin.tsx +23 -10
- package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +19 -2
- package/src/components/FunctionEditor/FunctionEditor.tsx +5 -5
- package/src/components/GridSheet/GridSheet.stories.tsx +3 -1
- package/src/components/GridSheet/GridSheet.tsx +114 -19
- package/src/components/GridSheet/SheetCellEditor.stories.tsx +1 -1
- package/src/components/GridSheet/util.ts +17 -7
- package/src/components/RangeList/RangeList.tsx +38 -0
- package/src/components/RangeList/index.ts +5 -0
- package/src/components/SheetContainer/SheetContainer.stories.tsx +1 -1
- package/src/components/SheetContext/SheetContext.tsx +43 -20
- package/src/components/Toolbar/Toolbar.tsx +34 -35
- package/src/components/index.ts +1 -0
- package/src/{graph → compute-graph}/compute-graph.stories.tsx +2 -1
- package/src/{graph → compute-graph}/compute-graph.ts +5 -2
- package/src/{graph → compute-graph}/compute-node.ts +2 -3
- package/src/defs/index.ts +1 -1
- package/src/defs/sheet-range-types.ts +1 -0
- package/src/defs/types.ts +6 -1
- package/src/defs/util.ts +3 -19
- package/src/extensions/compute.stories.tsx +2 -2
- package/src/extensions/compute.ts +2 -2
- package/src/extensions/editor/extension.test.ts +1 -1
- package/src/extensions/editor/extension.ts +48 -23
- package/src/index.ts +2 -2
- package/src/integrations/index.ts +5 -0
- package/src/integrations/thread-ranges.ts +101 -0
- package/src/model/index.ts +1 -1
- package/src/model/sheet-model.test.ts +1 -1
- package/src/model/sheet-model.ts +13 -8
- package/src/{hooks → model}/useSheetModel.ts +1 -1
- package/src/serializer.ts +27 -0
- package/src/testing/testing.tsx +1 -1
- package/src/translations.ts +6 -0
- package/src/types.ts +3 -1
- package/dist/lib/browser/SheetContainer-AKWROARP.mjs.map +0 -7
- package/dist/lib/browser/chunk-BWN5DZWZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-FGMFOW6U.mjs.map +0 -7
- package/dist/lib/node/SheetContainer-N5IQGEFL.cjs.map +0 -7
- package/dist/lib/node/chunk-53BMSUIK.cjs.map +0 -7
- package/dist/lib/node/chunk-NZARD7UP.cjs.map +0 -7
- package/dist/lib/node/graph-Q3N2X26H.cjs.map +0 -7
- package/dist/lib/node-esm/SheetContainer-46PBMF2E.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-T3PRH7QS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-WFDTY3IC.mjs.map +0 -7
- package/dist/types/src/graph/compute-graph-registry.d.ts.map +0 -1
- package/dist/types/src/graph/compute-graph.d.ts.map +0 -1
- package/dist/types/src/graph/compute-graph.stories.d.ts.map +0 -1
- package/dist/types/src/graph/compute-graph.test.d.ts.map +0 -1
- package/dist/types/src/graph/compute-node.d.ts.map +0 -1
- package/dist/types/src/graph/functions/async-function.d.ts.map +0 -1
- package/dist/types/src/graph/functions/edge-function.d.ts.map +0 -1
- package/dist/types/src/graph/functions/function-defs.d.ts.map +0 -1
- package/dist/types/src/graph/functions/index.d.ts.map +0 -1
- package/dist/types/src/graph/hyperformula.test.d.ts.map +0 -1
- package/dist/types/src/graph/index.d.ts.map +0 -1
- package/dist/types/src/graph/testing/index.d.ts.map +0 -1
- package/dist/types/src/graph/testing/test-builder.d.ts.map +0 -1
- package/dist/types/src/graph/testing/test-plugin.d.ts.map +0 -1
- package/dist/types/src/graph/util.d.ts.map +0 -1
- package/dist/types/src/hooks/hooks.stories.d.ts +0 -6
- package/dist/types/src/hooks/hooks.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/index.d.ts +0 -4
- package/dist/types/src/hooks/index.d.ts.map +0 -1
- package/dist/types/src/hooks/threads.d.ts +0 -8
- package/dist/types/src/hooks/threads.d.ts.map +0 -1
- package/dist/types/src/hooks/useComputeGraph.d.ts +0 -7
- package/dist/types/src/hooks/useComputeGraph.d.ts.map +0 -1
- package/dist/types/src/hooks/useSheetModel.d.ts.map +0 -1
- package/dist/types/src/model/decorations.d.ts +0 -26
- package/dist/types/src/model/decorations.d.ts.map +0 -1
- package/src/hooks/hooks.stories.tsx +0 -53
- package/src/hooks/index.ts +0 -7
- package/src/hooks/threads.ts +0 -147
- package/src/hooks/useComputeGraph.ts +0 -28
- package/src/model/decorations.ts +0 -66
- /package/dist/lib/browser/{graph-M4IQ76QX.mjs.map → compute-graph-ZQKB6QVP.mjs.map} +0 -0
- /package/dist/lib/node-esm/{graph-SMPUMOV2.mjs.map → compute-graph-VKRG526N.mjs.map} +0 -0
- /package/dist/types/src/{graph → compute-graph}/compute-graph-registry.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/compute-graph.stories.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/compute-graph.test.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/compute-node.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/functions/async-function.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/functions/edge-function.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/functions/function-defs.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/functions/index.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/hyperformula.test.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/index.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/testing/index.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/testing/test-builder.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/testing/test-plugin.d.ts +0 -0
- /package/dist/types/src/{graph → compute-graph}/util.d.ts +0 -0
- /package/src/{graph → compute-graph}/compute-graph-registry.ts +0 -0
- /package/src/{graph → compute-graph}/compute-graph.test.ts +0 -0
- /package/src/{graph → compute-graph}/functions/async-function.ts +0 -0
- /package/src/{graph → compute-graph}/functions/edge-function.ts +0 -0
- /package/src/{graph → compute-graph}/functions/function-defs.ts +0 -0
- /package/src/{graph → compute-graph}/functions/index.ts +0 -0
- /package/src/{graph → compute-graph}/hyperformula.test.ts +0 -0
- /package/src/{graph → compute-graph}/index.ts +0 -0
- /package/src/{graph → compute-graph}/testing/index.ts +0 -0
- /package/src/{graph → compute-graph}/testing/test-builder.ts +0 -0
- /package/src/{graph → compute-graph}/testing/test-plugin.ts +0 -0
- /package/src/{graph → compute-graph}/util.ts +0 -0
|
@@ -2,16 +2,21 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { type PropsWithChildren, createContext,
|
|
5
|
+
import React, { type PropsWithChildren, createContext, useCallback, useContext, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
import { fullyQualifiedId } from '@dxos/react-client/echo';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
import {
|
|
10
|
+
Grid,
|
|
11
|
+
type GridContentProps,
|
|
12
|
+
type GridEditing,
|
|
13
|
+
type GridScopedProps,
|
|
14
|
+
useGridContext,
|
|
15
|
+
} from '@dxos/react-ui-grid';
|
|
16
|
+
|
|
17
|
+
import { type ComputeGraph } from '../../compute-graph';
|
|
18
|
+
import { type CellAddress, type CellRange, type CompleteCellRange } from '../../defs';
|
|
19
|
+
import { type SheetModel, useSheetModel } from '../../model';
|
|
15
20
|
import { type SheetType } from '../../types';
|
|
16
21
|
|
|
17
22
|
export type SheetContextValue = {
|
|
@@ -25,17 +30,19 @@ export type SheetContextValue = {
|
|
|
25
30
|
setCursor: (cell: CellAddress | undefined) => void;
|
|
26
31
|
range?: CellRange;
|
|
27
32
|
setRange: (range: CellRange | undefined) => void;
|
|
33
|
+
cursorFallbackRange?: CompleteCellRange;
|
|
28
34
|
|
|
29
35
|
// Editing state (undefined if not editing).
|
|
30
36
|
editing: GridEditing;
|
|
31
37
|
setEditing: (editing: GridEditing) => void;
|
|
32
38
|
|
|
39
|
+
// Active refs
|
|
40
|
+
activeRefs: GridContentProps['activeRefs'];
|
|
41
|
+
setActiveRefs: (activeRefs: GridContentProps['activeRefs']) => void;
|
|
42
|
+
|
|
33
43
|
// Events.
|
|
34
44
|
// TODO(burdon): Generalize.
|
|
35
45
|
onInfo?: () => void;
|
|
36
|
-
|
|
37
|
-
// Decorations.
|
|
38
|
-
decorations: ReturnType<typeof createDecorations>;
|
|
39
46
|
};
|
|
40
47
|
|
|
41
48
|
const SheetContext = createContext<SheetContextValue | undefined>(undefined);
|
|
@@ -54,15 +61,29 @@ const SheetProviderImpl = ({
|
|
|
54
61
|
}: GridScopedProps<PropsWithChildren<Pick<SheetContextValue, 'onInfo' | 'model'>>>) => {
|
|
55
62
|
const { id, editing, setEditing } = useGridContext('SheetProvider', __gridScope);
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
const [cursor, setCursorInternal] = useState<CellAddress>();
|
|
65
|
+
const [range, setRangeInternal] = useState<CellRange>();
|
|
66
|
+
const [cursorFallbackRange, setCursorFallbackRange] = useState<CompleteCellRange>();
|
|
67
|
+
const [activeRefs, setActiveRefs] = useState<GridContentProps['activeRefs']>('');
|
|
68
|
+
|
|
69
|
+
const setCursor = useCallback(
|
|
70
|
+
(nextCursor?: CellAddress) => {
|
|
71
|
+
setCursorInternal(nextCursor);
|
|
72
|
+
setCursorFallbackRange(
|
|
73
|
+
range?.to ? (range as CompleteCellRange) : nextCursor ? { from: nextCursor!, to: nextCursor! } : undefined,
|
|
74
|
+
);
|
|
75
|
+
},
|
|
76
|
+
[range],
|
|
77
|
+
);
|
|
78
|
+
const setRange = useCallback(
|
|
79
|
+
(nextRange?: CellRange) => {
|
|
80
|
+
setRangeInternal(nextRange);
|
|
81
|
+
setCursorFallbackRange(
|
|
82
|
+
nextRange?.to ? (nextRange as CompleteCellRange) : cursor ? { from: cursor!, to: cursor! } : undefined,
|
|
83
|
+
);
|
|
84
|
+
},
|
|
85
|
+
[cursor],
|
|
86
|
+
);
|
|
66
87
|
|
|
67
88
|
return (
|
|
68
89
|
<SheetContext.Provider
|
|
@@ -75,9 +96,11 @@ const SheetProviderImpl = ({
|
|
|
75
96
|
setCursor,
|
|
76
97
|
range,
|
|
77
98
|
setRange,
|
|
99
|
+
cursorFallbackRange,
|
|
100
|
+
activeRefs,
|
|
101
|
+
setActiveRefs,
|
|
78
102
|
// TODO(burdon): Change to event.
|
|
79
103
|
onInfo,
|
|
80
|
-
decorations,
|
|
81
104
|
}}
|
|
82
105
|
>
|
|
83
106
|
{children}
|
|
@@ -9,26 +9,28 @@ import { useIntentDispatcher } from '@dxos/app-framework';
|
|
|
9
9
|
import {
|
|
10
10
|
Icon,
|
|
11
11
|
Toolbar as NaturalToolbar,
|
|
12
|
-
useTranslation,
|
|
13
12
|
Tooltip,
|
|
14
13
|
type ToolbarToggleGroupItemProps as NaturalToolbarToggleGroupItemProps,
|
|
15
14
|
type ToolbarButtonProps as NaturalToolbarButtonProps,
|
|
16
15
|
type ToolbarToggleProps as NaturalToolbarToggleProps,
|
|
17
16
|
type ThemedClassName,
|
|
17
|
+
useTranslation,
|
|
18
18
|
} from '@dxos/react-ui';
|
|
19
19
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
20
20
|
import { nonNullable } from '@dxos/util';
|
|
21
21
|
|
|
22
22
|
import {
|
|
23
|
-
addressToIndex,
|
|
24
23
|
type AlignKey,
|
|
25
24
|
type AlignValue,
|
|
26
25
|
type CommentKey,
|
|
27
26
|
type CommentValue,
|
|
28
27
|
inRange,
|
|
28
|
+
rangeFromIndex,
|
|
29
|
+
rangeToIndex,
|
|
29
30
|
type StyleKey,
|
|
30
31
|
type StyleValue,
|
|
31
32
|
} from '../../defs';
|
|
33
|
+
import { completeCellRangeToThreadCursor } from '../../integrations';
|
|
32
34
|
import { SHEET_PLUGIN } from '../../meta';
|
|
33
35
|
import { type SheetType } from '../../types';
|
|
34
36
|
import { useSheetContext } from '../SheetContext';
|
|
@@ -108,22 +110,21 @@ const sectionToolbarLayout =
|
|
|
108
110
|
type Range = SheetType['ranges'][number];
|
|
109
111
|
|
|
110
112
|
const ToolbarRoot = ({ children, role, classNames }: ToolbarProps) => {
|
|
111
|
-
const { id, model,
|
|
113
|
+
const { id, model, cursorFallbackRange, cursor } = useSheetContext();
|
|
112
114
|
const { hasAttention } = useAttention(id);
|
|
113
115
|
const dispatch = useIntentDispatcher();
|
|
114
116
|
|
|
115
|
-
// TODO(Zan):
|
|
117
|
+
// TODO(Zan): Externalize the toolbar action handler. E.g., Toolbar/keys should both fire events.
|
|
116
118
|
const handleAction = useCallback(
|
|
117
119
|
(action: ToolbarAction) => {
|
|
118
120
|
switch (action.key) {
|
|
119
121
|
case 'align':
|
|
120
|
-
if (cursor) {
|
|
122
|
+
if (cursor && cursorFallbackRange) {
|
|
121
123
|
const index = model.sheet.ranges?.findIndex(
|
|
122
|
-
(range) => range.key === action.key && inRange(range.range, cursor),
|
|
124
|
+
(range) => range.key === action.key && inRange(rangeFromIndex(model.sheet, range.range), cursor),
|
|
123
125
|
);
|
|
124
|
-
const nextRange = range ? { from: range.from, to: range.to ?? range.from } : { from: cursor, to: cursor };
|
|
125
126
|
const nextRangeEntity = {
|
|
126
|
-
range:
|
|
127
|
+
range: rangeToIndex(model.sheet, cursorFallbackRange),
|
|
127
128
|
key: action.key,
|
|
128
129
|
value: action.value,
|
|
129
130
|
};
|
|
@@ -140,10 +141,9 @@ const ToolbarRoot = ({ children, role, classNames }: ToolbarProps) => {
|
|
|
140
141
|
if (index >= 0) {
|
|
141
142
|
model.sheet.ranges?.splice(index, 1);
|
|
142
143
|
}
|
|
143
|
-
} else if (
|
|
144
|
-
const nextRange = range ? { from: range.from, to: range.to ?? range.from } : { from: cursor, to: cursor };
|
|
144
|
+
} else if (cursorFallbackRange) {
|
|
145
145
|
model.sheet.ranges?.push({
|
|
146
|
-
range:
|
|
146
|
+
range: rangeToIndex(model.sheet, cursorFallbackRange),
|
|
147
147
|
key: action.key,
|
|
148
148
|
value: action.value,
|
|
149
149
|
});
|
|
@@ -151,18 +151,20 @@ const ToolbarRoot = ({ children, role, classNames }: ToolbarProps) => {
|
|
|
151
151
|
break;
|
|
152
152
|
case 'comment': {
|
|
153
153
|
// TODO(Zan): We shouldn't hardcode the action ID.
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
154
|
+
if (cursorFallbackRange) {
|
|
155
|
+
void dispatch({
|
|
156
|
+
action: 'dxos.org/plugin/thread/action/create',
|
|
157
|
+
data: {
|
|
158
|
+
cursor: completeCellRangeToThreadCursor(cursorFallbackRange),
|
|
159
|
+
name: action.cellContent,
|
|
160
|
+
subject: model.sheet,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
}
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
166
|
},
|
|
165
|
-
[model.sheet,
|
|
167
|
+
[model.sheet, cursorFallbackRange, cursor, dispatch],
|
|
166
168
|
);
|
|
167
169
|
|
|
168
170
|
return (
|
|
@@ -207,7 +209,9 @@ const Alignment = () => {
|
|
|
207
209
|
const value = useMemo(
|
|
208
210
|
() =>
|
|
209
211
|
cursor
|
|
210
|
-
? model.sheet.ranges?.find(
|
|
212
|
+
? model.sheet.ranges?.find(
|
|
213
|
+
({ range, key }) => key === 'alignment' && inRange(rangeFromIndex(model.sheet, range), cursor),
|
|
214
|
+
)?.value
|
|
211
215
|
: undefined,
|
|
212
216
|
[cursor, model.sheet.ranges],
|
|
213
217
|
);
|
|
@@ -238,7 +242,7 @@ const Styles = () => {
|
|
|
238
242
|
() =>
|
|
239
243
|
cursor
|
|
240
244
|
? model.sheet.ranges
|
|
241
|
-
?.filter(({ range, key }) => key === 'style' && inRange(range, cursor))
|
|
245
|
+
?.filter(({ range, key }) => key === 'style' && inRange(rangeFromIndex(model.sheet, range), cursor))
|
|
242
246
|
.reduce((acc, { value }) => {
|
|
243
247
|
acc.add(value);
|
|
244
248
|
return acc;
|
|
@@ -270,29 +274,24 @@ const Styles = () => {
|
|
|
270
274
|
|
|
271
275
|
const Actions = () => {
|
|
272
276
|
const { onAction } = useToolbarContext('Actions');
|
|
273
|
-
const {
|
|
277
|
+
const { cursorFallbackRange, cursor, model } = useSheetContext();
|
|
274
278
|
const { t } = useTranslation(SHEET_PLUGIN);
|
|
275
279
|
|
|
276
280
|
const overlapsCommentAnchor = (model.sheet.threads ?? [])
|
|
277
281
|
.filter(nonNullable)
|
|
278
282
|
.filter((thread) => thread.status !== 'resolved')
|
|
279
283
|
.some((thread) => {
|
|
280
|
-
if (!
|
|
284
|
+
if (!cursorFallbackRange) {
|
|
281
285
|
return false;
|
|
282
286
|
}
|
|
283
|
-
return
|
|
287
|
+
return rangeToIndex(model.sheet, cursorFallbackRange) === thread.anchor;
|
|
284
288
|
});
|
|
285
289
|
|
|
286
|
-
const
|
|
287
|
-
const cursorOnly = hasCursor && !range && !overlapsCommentAnchor;
|
|
288
|
-
|
|
289
|
-
const tooltipLabelKey = !hasCursor
|
|
290
|
+
const tooltipLabelKey = !cursor
|
|
290
291
|
? 'no cursor label'
|
|
291
292
|
: overlapsCommentAnchor
|
|
292
293
|
? 'selection overlaps existing comment label'
|
|
293
|
-
:
|
|
294
|
-
? 'comment ranges not supported label'
|
|
295
|
-
: 'comment label';
|
|
294
|
+
: 'comment label';
|
|
296
295
|
|
|
297
296
|
return (
|
|
298
297
|
<ToolbarItem
|
|
@@ -301,16 +300,16 @@ const Actions = () => {
|
|
|
301
300
|
icon='ph--chat-text--regular'
|
|
302
301
|
data-testid='editor.toolbar.comment'
|
|
303
302
|
onClick={() => {
|
|
304
|
-
if (!cursor) {
|
|
303
|
+
if (!(cursorFallbackRange && cursor)) {
|
|
305
304
|
return;
|
|
306
305
|
}
|
|
307
306
|
return onAction?.({
|
|
308
307
|
key: 'comment',
|
|
309
|
-
value:
|
|
308
|
+
value: rangeToIndex(model.sheet, cursorFallbackRange),
|
|
310
309
|
cellContent: model.getCellText(cursor),
|
|
311
310
|
});
|
|
312
311
|
}}
|
|
313
|
-
disabled={!
|
|
312
|
+
disabled={!cursor || overlapsCommentAnchor}
|
|
314
313
|
>
|
|
315
314
|
{t(tooltipLabelKey)}
|
|
316
315
|
</ToolbarItem>
|
package/src/components/index.ts
CHANGED
|
@@ -15,8 +15,9 @@ import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
|
|
|
15
15
|
import { withTheme } from '@dxos/storybook-utils';
|
|
16
16
|
|
|
17
17
|
import { testFunctionPlugins } from './testing';
|
|
18
|
+
import { useComputeGraph } from '../components';
|
|
18
19
|
import { createSheet } from '../defs';
|
|
19
|
-
import {
|
|
20
|
+
import { useSheetModel } from '../model';
|
|
20
21
|
import { withComputeGraphDecorator } from '../testing';
|
|
21
22
|
import { SheetType } from '../types';
|
|
22
23
|
|
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
EDGE_FUNCTION_NAME,
|
|
25
25
|
} from './functions';
|
|
26
26
|
|
|
27
|
+
// TODO(burdon): Factor out compute-graph.
|
|
28
|
+
|
|
27
29
|
// TODO(wittjosiah): Factor out.
|
|
28
30
|
const OBJECT_ID_LENGTH = 60; // 33 (space id) + 1 (separator) + 26 (object id).
|
|
29
31
|
|
|
@@ -71,6 +73,7 @@ export class ComputeGraph extends Resource {
|
|
|
71
73
|
) {
|
|
72
74
|
super();
|
|
73
75
|
this._hf.updateConfig({ context: this.context });
|
|
76
|
+
|
|
74
77
|
// TODO(burdon): If debounce then aggregate changes.
|
|
75
78
|
const onValuesUpdate: Listeners['valuesUpdated'] = (changes) => {
|
|
76
79
|
for (const change of changes) {
|
|
@@ -116,7 +119,7 @@ export class ComputeGraph extends Resource {
|
|
|
116
119
|
getOrCreateNode(name: string): ComputeNode {
|
|
117
120
|
invariant(name.length);
|
|
118
121
|
if (!this._hf.doesSheetExist(name)) {
|
|
119
|
-
log
|
|
122
|
+
log('created node', { space: this._space?.id, sheet: name });
|
|
120
123
|
this._hf.addSheet(name);
|
|
121
124
|
}
|
|
122
125
|
|
|
@@ -130,7 +133,7 @@ export class ComputeGraph extends Resource {
|
|
|
130
133
|
|
|
131
134
|
/**
|
|
132
135
|
* Map bound value to custom function invocation.
|
|
133
|
-
* E.g., "HELLO(...args)" => "
|
|
136
|
+
* E.g., "HELLO(...args)" => "DX("HELLO", ...args)".
|
|
134
137
|
*/
|
|
135
138
|
mapFormulaToNative(formula: string): string {
|
|
136
139
|
return (
|
|
@@ -10,7 +10,7 @@ import { Resource } from '@dxos/context';
|
|
|
10
10
|
|
|
11
11
|
import { DetailedCellError } from '#hyperformula';
|
|
12
12
|
import { type ComputeGraph } from './compute-graph';
|
|
13
|
-
import { type CellAddress } from '../defs';
|
|
13
|
+
import { type CellAddress, isFormula } from '../defs';
|
|
14
14
|
import { type CellScalarValue } from '../types';
|
|
15
15
|
|
|
16
16
|
export type ComputeNodeEvent = {
|
|
@@ -50,8 +50,7 @@ export class ComputeNode extends Resource {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
setValue(cell: CellAddress, value: CellScalarValue) {
|
|
53
|
-
const mappedValue =
|
|
54
|
-
typeof value === 'string' && value.charAt(0) === '=' ? this._graph.mapFormulaToNative(value) : value;
|
|
53
|
+
const mappedValue = isFormula(value) ? this._graph.mapFormulaToNative(value) : value;
|
|
55
54
|
this._graph.hf.setCellContents({ sheet: this.sheetId, row: cell.row, col: cell.col }, [[mappedValue]]);
|
|
56
55
|
}
|
|
57
56
|
|
package/src/defs/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export const styleKey = 'style';
|
|
|
18
18
|
export type StyleKey = typeof styleKey;
|
|
19
19
|
export type StyleValue = 'highlight' | 'unset';
|
|
20
20
|
|
|
21
|
+
// TODO(burdon): Reconcile with plugin-table.
|
|
21
22
|
export const cellClassNameForRange = ({ key, value }: SheetType['ranges'][number]): ClassNameValue => {
|
|
22
23
|
switch (key) {
|
|
23
24
|
case 'align':
|
package/src/defs/types.ts
CHANGED
|
@@ -13,11 +13,16 @@ export const MAX_COLUMNS = 26 * 2;
|
|
|
13
13
|
export type CellAddress = { col: number; row: number };
|
|
14
14
|
|
|
15
15
|
export type CellRange = { from: CellAddress; to?: CellAddress };
|
|
16
|
+
export type CompleteCellRange = { from: CellAddress; to: CellAddress };
|
|
16
17
|
|
|
17
18
|
export type CellIndex = string;
|
|
18
19
|
|
|
19
20
|
export type CellContentValue = number | string | boolean | null;
|
|
20
21
|
|
|
22
|
+
export const RANGE_NOTATION = /^[A-Z]+[0-9]+(:[A-Z]+[0-9]+)?$/;
|
|
23
|
+
|
|
24
|
+
export const isFormula = (value: any): value is string => typeof value === 'string' && value.charAt(0) === '=';
|
|
25
|
+
|
|
21
26
|
export const posEquals = (a: CellAddress | undefined, b: CellAddress | undefined) => {
|
|
22
27
|
return a?.col === b?.col && a?.row === b?.row;
|
|
23
28
|
};
|
|
@@ -34,7 +39,7 @@ export const addressToA1Notation = ({ col, row }: CellAddress): string => {
|
|
|
34
39
|
return `${columnLetter(col)}${row + 1}`;
|
|
35
40
|
};
|
|
36
41
|
|
|
37
|
-
// TODO(burdon): See simpleCellAddressFromString
|
|
42
|
+
// TODO(burdon): See (HF) simpleCellAddressFromString.
|
|
38
43
|
export const addressFromA1Notation = (ref: string): CellAddress => {
|
|
39
44
|
const match = ref.match(/([A-Z]+)(\d+)/);
|
|
40
45
|
invariant(match, `Invalid notation: ${ref}`);
|
package/src/defs/util.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
addressFromA1Notation,
|
|
10
10
|
type CellAddress,
|
|
11
11
|
type CellRange,
|
|
12
|
+
type CompleteCellRange,
|
|
12
13
|
DEFAULT_COLUMNS,
|
|
13
14
|
DEFAULT_ROWS,
|
|
14
15
|
MAX_COLUMNS,
|
|
@@ -69,6 +70,7 @@ export const createSheet = ({ name, cells, ...size }: CreateSheetOptions = {}):
|
|
|
69
70
|
rowMeta: {},
|
|
70
71
|
columnMeta: {},
|
|
71
72
|
ranges: [],
|
|
73
|
+
threads: [],
|
|
72
74
|
});
|
|
73
75
|
|
|
74
76
|
initialize(sheet, size);
|
|
@@ -111,29 +113,11 @@ export const rangeToIndex = (sheet: SheetType, range: CellRange): string => {
|
|
|
111
113
|
/**
|
|
112
114
|
* E.g., "CA2@CB3:CC4@CD5" => "A1:B2".
|
|
113
115
|
*/
|
|
114
|
-
export const rangeFromIndex = (sheet: SheetType, idx: string):
|
|
116
|
+
export const rangeFromIndex = (sheet: SheetType, idx: string): CompleteCellRange => {
|
|
115
117
|
const [from, to] = idx.split(':').map((index) => addressFromIndex(sheet, index));
|
|
116
118
|
return { from, to };
|
|
117
119
|
};
|
|
118
120
|
|
|
119
|
-
/**
|
|
120
|
-
* Find closest cell to cursor.
|
|
121
|
-
*/
|
|
122
|
-
export const closest = (cursor: CellAddress, cells: CellAddress[]): CellAddress | undefined => {
|
|
123
|
-
let closestCell: CellAddress | undefined;
|
|
124
|
-
let closestDistance = Number.MAX_SAFE_INTEGER;
|
|
125
|
-
|
|
126
|
-
for (const cell of cells) {
|
|
127
|
-
const distance = Math.abs(cell.row - cursor.row) + Math.abs(cell.col - cursor.col);
|
|
128
|
-
if (distance < closestDistance) {
|
|
129
|
-
closestCell = cell;
|
|
130
|
-
closestDistance = distance;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return closestCell;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
121
|
/**
|
|
138
122
|
* Compares the positions of two cell indexes in a sheet.
|
|
139
123
|
* Sorts primarily by row, then by column if rows are equal.
|
|
@@ -23,8 +23,8 @@ import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
|
23
23
|
import { nonNullable } from '@dxos/util';
|
|
24
24
|
|
|
25
25
|
import { compute, computeGraphFacet } from './compute';
|
|
26
|
-
import { GridSheet, SheetProvider } from '../components';
|
|
27
|
-
import {
|
|
26
|
+
import { GridSheet, SheetProvider, useComputeGraph } from '../components';
|
|
27
|
+
import { useSheetModel } from '../model';
|
|
28
28
|
import { useTestSheet, withComputeGraphDecorator } from '../testing';
|
|
29
29
|
import { SheetType } from '../types';
|
|
30
30
|
|
|
@@ -16,10 +16,10 @@ import { Decoration, EditorView, ViewPlugin, WidgetType } from '@codemirror/view
|
|
|
16
16
|
|
|
17
17
|
import { type UnsubscribeCallback, debounce } from '@dxos/async';
|
|
18
18
|
import { invariant } from '@dxos/invariant';
|
|
19
|
-
import { documentId, singleValueFacet } from '@dxos/react-ui-editor
|
|
19
|
+
import { documentId, singleValueFacet } from '@dxos/react-ui-editor';
|
|
20
20
|
|
|
21
|
+
import { type ComputeGraph, type ComputeNode, createSheetName } from '../compute-graph';
|
|
21
22
|
import { type CellAddress } from '../defs';
|
|
22
|
-
import { type ComputeGraph, type ComputeNode, createSheetName } from '../graph';
|
|
23
23
|
import { type CellScalarValue } from '../types';
|
|
24
24
|
|
|
25
25
|
const LANGUAGE_TAG = 'dx';
|
|
@@ -9,7 +9,7 @@ import { spreadsheet } from 'codemirror-lang-spreadsheet';
|
|
|
9
9
|
import { describe, expect, test } from 'vitest';
|
|
10
10
|
|
|
11
11
|
import { sheetExtension } from './extension';
|
|
12
|
-
import { defaultFunctions } from '../../graph';
|
|
12
|
+
import { defaultFunctions } from '../../compute-graph';
|
|
13
13
|
|
|
14
14
|
describe('formula parser', () => {
|
|
15
15
|
const {
|
|
@@ -18,10 +18,11 @@ import { type SyntaxNode } from '@lezer/common';
|
|
|
18
18
|
import { tags } from '@lezer/highlight';
|
|
19
19
|
import { spreadsheet } from 'codemirror-lang-spreadsheet';
|
|
20
20
|
|
|
21
|
-
import { singleValueFacet } from '@dxos/react-ui-editor
|
|
21
|
+
import { singleValueFacet } from '@dxos/react-ui-editor';
|
|
22
22
|
import { mx } from '@dxos/react-ui-theme';
|
|
23
23
|
|
|
24
|
-
import { type FunctionDefinition } from '../../graph';
|
|
24
|
+
import { type FunctionDefinition } from '../../compute-graph';
|
|
25
|
+
import { RANGE_NOTATION } from '../../defs';
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* https://codemirror.net/examples/styling
|
|
@@ -195,34 +196,53 @@ export const sheetExtension = ({ functions = [] }: SheetExtensionOptions): Exten
|
|
|
195
196
|
];
|
|
196
197
|
};
|
|
197
198
|
|
|
198
|
-
export type
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
export type SelectionRange = { from: number; to: number };
|
|
200
|
+
|
|
201
|
+
export interface RangeController {
|
|
202
|
+
setRange(range: string): void;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export type RangeExtensionOptions = {
|
|
206
|
+
/**
|
|
207
|
+
* Provides controller callback when extension is initialized.
|
|
208
|
+
*/
|
|
209
|
+
onInit?: (controller: RangeController) => void;
|
|
210
|
+
/**
|
|
211
|
+
* Called when the active range changes.
|
|
212
|
+
* @param state The current state.
|
|
213
|
+
* @param state.activeRange undefined if no range is active, otherwise a possibly partially defined range.
|
|
214
|
+
*/
|
|
215
|
+
onStateChange?: (state: { activeRange: string | undefined }) => void;
|
|
216
|
+
};
|
|
201
217
|
|
|
202
218
|
/**
|
|
203
219
|
* Tracks the currently active cell within a formula and provides a callback to modify it.
|
|
204
220
|
*/
|
|
205
|
-
export const rangeExtension = (onInit
|
|
221
|
+
export const rangeExtension = ({ onInit, onStateChange }: RangeExtensionOptions): Extension => {
|
|
206
222
|
let view: EditorView;
|
|
207
|
-
let activeRange:
|
|
208
|
-
const provider: CellRangeNotifier = (range: string) => {
|
|
209
|
-
if (activeRange) {
|
|
210
|
-
view.dispatch(
|
|
211
|
-
view.state.update({
|
|
212
|
-
changes: { ...activeRange, insert: range.toString() },
|
|
213
|
-
selection: { anchor: activeRange.from + range.length },
|
|
214
|
-
}),
|
|
215
|
-
);
|
|
216
|
-
}
|
|
223
|
+
let activeRange: SelectionRange | undefined;
|
|
217
224
|
|
|
218
|
-
|
|
225
|
+
// Called externally to provide current range.
|
|
226
|
+
const notifier: RangeController = {
|
|
227
|
+
setRange: (range: string) => {
|
|
228
|
+
if (activeRange) {
|
|
229
|
+
view.dispatch(
|
|
230
|
+
view.state.update({
|
|
231
|
+
changes: { ...activeRange, insert: range.toString() },
|
|
232
|
+
selection: { anchor: activeRange.from + range.length },
|
|
233
|
+
}),
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
view.focus();
|
|
238
|
+
},
|
|
219
239
|
};
|
|
220
240
|
|
|
221
241
|
return ViewPlugin.fromClass(
|
|
222
242
|
class {
|
|
223
243
|
constructor(_view: EditorView) {
|
|
224
244
|
view = _view;
|
|
225
|
-
onInit(
|
|
245
|
+
onInit?.(notifier);
|
|
226
246
|
}
|
|
227
247
|
|
|
228
248
|
update(view: ViewUpdate) {
|
|
@@ -235,17 +255,15 @@ export const rangeExtension = (onInit: (notifier: CellRangeNotifier) => void): E
|
|
|
235
255
|
visitTree(topNode, ({ type, from, to }) => {
|
|
236
256
|
if (from <= anchor && to >= anchor) {
|
|
237
257
|
switch (type.name) {
|
|
238
|
-
case 'Function':
|
|
258
|
+
case 'Function':
|
|
239
259
|
// Mark but keep looking.
|
|
240
260
|
activeRange = { from: to, to };
|
|
241
261
|
break;
|
|
242
|
-
}
|
|
243
262
|
|
|
244
|
-
case 'CloseParen':
|
|
263
|
+
case 'CloseParen':
|
|
245
264
|
// Mark but keep looking.
|
|
246
265
|
activeRange = { from, to: from };
|
|
247
266
|
break;
|
|
248
|
-
}
|
|
249
267
|
|
|
250
268
|
case 'RangeToken':
|
|
251
269
|
case 'CellToken':
|
|
@@ -259,8 +277,15 @@ export const rangeExtension = (onInit: (notifier: CellRangeNotifier) => void): E
|
|
|
259
277
|
|
|
260
278
|
// Allow start of formula.
|
|
261
279
|
if (!activeRange && view.state.doc.toString()[0] === '=') {
|
|
262
|
-
|
|
280
|
+
const str = view.state.doc.sliceString(1);
|
|
281
|
+
if (RANGE_NOTATION.test(str)) {
|
|
282
|
+
activeRange = { from: 1, to: str.length + 1 };
|
|
283
|
+
}
|
|
263
284
|
}
|
|
285
|
+
|
|
286
|
+
onStateChange?.({
|
|
287
|
+
activeRange: activeRange ? view.state.doc.sliceString(activeRange.from, activeRange.to) : undefined,
|
|
288
|
+
});
|
|
264
289
|
}
|
|
265
290
|
},
|
|
266
291
|
);
|
package/src/index.ts
CHANGED