@dxos/plugin-sheet 0.6.11 → 0.6.12-main.15a606f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/SheetContainer-V4GCCZTX.mjs +261 -0
- package/dist/lib/browser/SheetContainer-V4GCCZTX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-D5AGLXJP.mjs → chunk-6ZMQVB4Z.mjs} +359 -671
- package/dist/lib/browser/chunk-6ZMQVB4Z.mjs.map +7 -0
- package/dist/lib/browser/{chunk-JRL5LGCE.mjs → chunk-QILRZNE5.mjs} +2 -5
- package/dist/lib/browser/chunk-QILRZNE5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FUAGSXA4.mjs → chunk-T3NJFTD4.mjs} +8 -15
- package/dist/lib/browser/chunk-T3NJFTD4.mjs.map +7 -0
- package/dist/lib/browser/{SheetContainer-U4H5D34A.mjs → chunk-U2JHW3L6.mjs} +1020 -240
- package/dist/lib/browser/chunk-U2JHW3L6.mjs.map +7 -0
- package/dist/lib/browser/graph-T27BOBOV.mjs +21 -0
- package/dist/lib/browser/graph-T27BOBOV.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +68 -56
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types.mjs +4 -6
- package/dist/lib/node/SheetContainer-3ZY7MPWJ.cjs +279 -0
- package/dist/lib/node/SheetContainer-3ZY7MPWJ.cjs.map +7 -0
- package/dist/lib/node/{chunk-BJ6ZD7MN.cjs → chunk-BNARJ5GM.cjs} +5 -18
- package/dist/lib/node/chunk-BNARJ5GM.cjs.map +7 -0
- package/dist/lib/node/{chunk-5KKJ4NPP.cjs → chunk-DD6FIXWC.cjs} +360 -667
- package/dist/lib/node/chunk-DD6FIXWC.cjs.map +7 -0
- package/dist/lib/node/{SheetContainer-AXQV3ZT5.cjs → chunk-OTTD7FBK.cjs} +1050 -279
- package/dist/lib/node/chunk-OTTD7FBK.cjs.map +7 -0
- package/dist/lib/node/{chunk-DSYKOI4E.cjs → chunk-Q3HBHPRL.cjs} +12 -20
- package/dist/lib/node/chunk-Q3HBHPRL.cjs.map +7 -0
- package/dist/lib/node/graph-SPKGX7W4.cjs +43 -0
- package/dist/lib/node/graph-SPKGX7W4.cjs.map +7 -0
- package/dist/lib/node/index.cjs +83 -64
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.cjs +3 -3
- package/dist/lib/node/meta.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +10 -12
- package/dist/lib/node/types.cjs.map +2 -2
- package/dist/lib/node-esm/SheetContainer-PXSJX6XK.mjs +262 -0
- package/dist/lib/node-esm/SheetContainer-PXSJX6XK.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-7HVSOTGA.mjs +2553 -0
- package/dist/lib/node-esm/chunk-7HVSOTGA.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-BMNA27EX.mjs +76 -0
- package/dist/lib/node-esm/chunk-BMNA27EX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-D6KU5MI7.mjs +2925 -0
- package/dist/lib/node-esm/chunk-D6KU5MI7.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-IU2L277A.mjs +17 -0
- package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +7 -0
- package/dist/lib/node-esm/graph-U67IO4UC.mjs +22 -0
- package/dist/lib/node-esm/graph-U67IO4UC.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +261 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/meta.mjs +10 -0
- package/dist/lib/node-esm/meta.mjs.map +7 -0
- package/dist/lib/node-esm/types.mjs +21 -0
- package/dist/lib/node-esm/types.mjs.map +7 -0
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/components/CellEditor/CellEditor.d.ts +23 -3
- package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +1 -1
- package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts +2 -2
- package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/CellEditor/extension.d.ts +1 -1
- package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -1
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +11 -0
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/index.d.ts +1 -3
- package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.d.ts +10 -0
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +9 -0
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -0
- package/dist/types/src/components/GridSheet/util.d.ts +6 -0
- package/dist/types/src/components/GridSheet/util.d.ts.map +1 -0
- package/dist/types/src/components/Sheet/Sheet.d.ts +1 -1
- package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/Sheet.stories.d.ts +5 -6
- package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/decorations.d.ts +24 -0
- package/dist/types/src/components/Sheet/decorations.d.ts.map +1 -0
- package/dist/types/src/components/Sheet/grid.d.ts +2 -2
- package/dist/types/src/components/Sheet/grid.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/nav.d.ts +3 -3
- package/dist/types/src/components/Sheet/nav.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/sheet-context.d.ts +6 -5
- package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/threads.d.ts +2 -0
- package/dist/types/src/components/Sheet/threads.d.ts.map +1 -0
- package/dist/types/src/components/SheetContainer.d.ts +2 -3
- package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +19 -3
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +18 -13
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/defs/index.d.ts +3 -0
- package/dist/types/src/defs/index.d.ts.map +1 -0
- package/dist/types/src/{model → defs}/types.d.ts +8 -3
- package/dist/types/src/defs/types.d.ts.map +1 -0
- package/dist/types/src/defs/types.test.d.ts.map +1 -0
- package/dist/types/src/defs/util.d.ts +43 -0
- package/dist/types/src/defs/util.d.ts.map +1 -0
- package/dist/types/src/extensions/compute.d.ts +5 -0
- package/dist/types/src/extensions/compute.d.ts.map +1 -0
- package/dist/types/src/extensions/compute.stories.d.ts +26 -0
- package/dist/types/src/extensions/compute.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +2 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/{components/ComputeGraph → graph}/async-function.d.ts +1 -1
- package/dist/types/src/graph/async-function.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.browser.test.d.ts +2 -0
- package/dist/types/src/graph/compute-graph.browser.test.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.d.ts +81 -0
- package/dist/types/src/graph/compute-graph.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.stories.d.ts +10 -0
- package/dist/types/src/graph/compute-graph.stories.d.ts.map +1 -0
- package/dist/types/src/graph/compute-node.d.ts +19 -0
- package/dist/types/src/graph/compute-node.d.ts.map +1 -0
- package/dist/types/src/{components/ComputeGraph/custom.d.ts → graph/custom-function.d.ts} +1 -1
- package/dist/types/src/graph/custom-function.d.ts.map +1 -0
- package/dist/types/src/graph/edge-function.d.ts.map +1 -0
- package/dist/types/src/{model/functions.d.ts → graph/function-defs.d.ts} +1 -1
- package/dist/types/src/graph/function-defs.d.ts.map +1 -0
- package/dist/types/src/graph/hyperformula.test.d.ts +2 -0
- package/dist/types/src/graph/hyperformula.test.d.ts.map +1 -0
- package/dist/types/src/graph/index.d.ts +4 -0
- package/dist/types/src/graph/index.d.ts.map +1 -0
- package/dist/types/src/graph/util.d.ts +2 -0
- package/dist/types/src/graph/util.d.ts.map +1 -0
- package/dist/types/src/hooks/hooks.stories.d.ts +11 -0
- package/dist/types/src/hooks/hooks.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useComputeGraph.d.ts +7 -0
- package/dist/types/src/hooks/useComputeGraph.d.ts.map +1 -0
- package/dist/types/src/hooks/useFormattingModel.d.ts +3 -0
- package/dist/types/src/hooks/useFormattingModel.d.ts.map +1 -0
- package/dist/types/src/hooks/useSheetModel.d.ts +8 -0
- package/dist/types/src/hooks/useSheetModel.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +1 -4
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/model/formatting-model.d.ts +16 -0
- package/dist/types/src/model/formatting-model.d.ts.map +1 -0
- package/dist/types/src/model/index.d.ts +2 -3
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/{model.d.ts → sheet-model.d.ts} +9 -64
- package/dist/types/src/model/sheet-model.d.ts.map +1 -0
- package/dist/types/src/sanity.test.d.ts +2 -0
- package/dist/types/src/sanity.test.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/testing.d.ts +9 -0
- package/dist/types/src/testing/testing.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +17 -12
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +83 -3
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/vendor/hyperformula.mjs +37145 -0
- package/package.json +48 -41
- package/src/SheetPlugin.tsx +43 -70
- package/src/components/CellEditor/CellEditor.stories.tsx +4 -3
- package/src/components/CellEditor/CellEditor.tsx +59 -9
- package/src/components/CellEditor/extension.test.ts +4 -5
- package/src/components/CellEditor/extension.ts +1 -3
- package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +20 -0
- package/src/components/ComputeGraph/index.ts +1 -3
- package/src/components/GridSheet/GridSheet.stories.tsx +35 -0
- package/src/components/GridSheet/GridSheet.tsx +153 -0
- package/src/components/GridSheet/util.ts +89 -0
- package/src/components/Sheet/Sheet.stories.tsx +45 -82
- package/src/components/Sheet/Sheet.tsx +57 -18
- package/src/components/Sheet/decorations.ts +62 -0
- package/src/components/Sheet/grid.ts +3 -3
- package/src/components/Sheet/nav.ts +19 -19
- package/src/components/Sheet/sheet-context.tsx +16 -78
- package/src/components/Sheet/threads.tsx +205 -0
- package/src/components/SheetContainer.tsx +73 -19
- package/src/components/Toolbar/Toolbar.tsx +53 -12
- package/src/components/index.ts +1 -0
- package/src/defs/index.ts +6 -0
- package/src/{model → defs}/types.test.ts +8 -9
- package/src/{model → defs}/types.ts +23 -14
- package/src/defs/util.ts +135 -0
- package/src/extensions/compute.stories.tsx +151 -0
- package/src/extensions/compute.ts +98 -0
- package/src/extensions/index.ts +5 -0
- package/src/{components/ComputeGraph → graph}/async-function.ts +3 -1
- package/src/graph/compute-graph.browser.test.ts +104 -0
- package/src/graph/compute-graph.stories.tsx +92 -0
- package/src/graph/compute-graph.ts +290 -0
- package/src/graph/compute-node.ts +51 -0
- package/src/{components/ComputeGraph/custom.ts → graph/custom-function.ts} +2 -6
- package/src/{components/ComputeGraph → graph}/edge-function.ts +2 -1
- package/src/graph/hyperformula.test.ts +15 -0
- package/src/graph/index.ts +7 -0
- package/src/graph/util.ts +8 -0
- package/src/hooks/hooks.stories.tsx +50 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useComputeGraph.ts +20 -0
- package/src/hooks/useFormattingModel.ts +11 -0
- package/src/hooks/useSheetModel.ts +43 -0
- package/src/meta.tsx +1 -5
- package/src/{components/Sheet/formatting.ts → model/formatting-model.ts} +20 -13
- package/src/model/index.ts +2 -3
- package/src/model/sheet-model.ts +399 -0
- package/src/sanity.test.ts +40 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/testing.tsx +66 -0
- package/src/translations.ts +6 -1
- package/src/types.ts +30 -5
- package/dist/lib/browser/SheetContainer-U4H5D34A.mjs.map +0 -7
- package/dist/lib/browser/chunk-APHOLYUB.mjs +0 -175
- package/dist/lib/browser/chunk-APHOLYUB.mjs.map +0 -7
- package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +0 -7
- package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +0 -7
- package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +0 -7
- package/dist/lib/browser/chunk-NU4PBN33.mjs +0 -8
- package/dist/lib/browser/chunk-NU4PBN33.mjs.map +0 -7
- package/dist/lib/browser/testing.mjs +0 -92
- package/dist/lib/browser/testing.mjs.map +0 -7
- package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +0 -7
- package/dist/lib/node/chunk-5KKJ4NPP.cjs.map +0 -7
- package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +0 -7
- package/dist/lib/node/chunk-CN3RPESU.cjs +0 -202
- package/dist/lib/node/chunk-CN3RPESU.cjs.map +0 -7
- package/dist/lib/node/chunk-DSYKOI4E.cjs.map +0 -7
- package/dist/lib/node/chunk-PYXHNAAK.cjs +0 -40
- package/dist/lib/node/chunk-PYXHNAAK.cjs.map +0 -7
- package/dist/lib/node/testing.cjs +0 -111
- package/dist/lib/node/testing.cjs.map +0 -7
- package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/custom.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/graph-context.d.ts +0 -12
- package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +0 -2
- package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/graph.d.ts +0 -26
- package/dist/types/src/components/ComputeGraph/graph.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/formatting.d.ts +0 -14
- package/dist/types/src/components/Sheet/formatting.d.ts.map +0 -1
- package/dist/types/src/model/functions.d.ts.map +0 -1
- package/dist/types/src/model/model.browser.test.d.ts +0 -2
- package/dist/types/src/model/model.browser.test.d.ts.map +0 -1
- package/dist/types/src/model/model.d.ts.map +0 -1
- package/dist/types/src/model/types.d.ts.map +0 -1
- package/dist/types/src/model/types.test.d.ts.map +0 -1
- package/dist/types/src/model/util.d.ts +0 -15
- package/dist/types/src/model/util.d.ts.map +0 -1
- package/dist/types/src/testing.d.ts +0 -9
- package/dist/types/src/testing.d.ts.map +0 -1
- package/src/components/ComputeGraph/graph-context.tsx +0 -50
- package/src/components/ComputeGraph/graph.browser.test.ts +0 -50
- package/src/components/ComputeGraph/graph.ts +0 -62
- package/src/model/model.browser.test.ts +0 -100
- package/src/model/model.ts +0 -550
- package/src/model/util.ts +0 -36
- package/src/testing.ts +0 -50
- /package/dist/types/src/{model → defs}/types.test.d.ts +0 -0
- /package/dist/types/src/{components/ComputeGraph → graph}/edge-function.d.ts +0 -0
- /package/src/{model/functions.ts → graph/function-defs.ts} +0 -0
|
@@ -23,22 +23,31 @@ import {
|
|
|
23
23
|
type ThemedClassName,
|
|
24
24
|
useTranslation,
|
|
25
25
|
} from '@dxos/react-ui';
|
|
26
|
+
import { nonNullable } from '@dxos/util';
|
|
26
27
|
|
|
27
28
|
import { ToolbarButton, ToolbarSeparator, ToolbarToggleButton } from './common';
|
|
29
|
+
import { addressToIndex } from '../../defs';
|
|
28
30
|
import { SHEET_PLUGIN } from '../../meta';
|
|
29
31
|
import { type Formatting } from '../../types';
|
|
32
|
+
import { useSheetContext } from '../Sheet/sheet-context';
|
|
30
33
|
|
|
31
34
|
//
|
|
32
35
|
// Root
|
|
33
36
|
//
|
|
34
37
|
|
|
35
|
-
export type
|
|
38
|
+
export type ToolbarAction =
|
|
39
|
+
| { type: 'clear' }
|
|
40
|
+
| { type: 'highlight' }
|
|
41
|
+
| { type: 'left' }
|
|
42
|
+
| { type: 'center' }
|
|
43
|
+
| { type: 'right' }
|
|
44
|
+
| { type: 'date' }
|
|
45
|
+
| { type: 'currency' }
|
|
46
|
+
| { type: 'comment'; anchor: string; cellContent?: string };
|
|
36
47
|
|
|
37
|
-
export type
|
|
38
|
-
type: ToolbarActionType;
|
|
39
|
-
};
|
|
48
|
+
export type ToolbarActionType = ToolbarAction['type'];
|
|
40
49
|
|
|
41
|
-
export type ToolbarActionHandler = (
|
|
50
|
+
export type ToolbarActionHandler = (action: ToolbarAction) => void;
|
|
42
51
|
|
|
43
52
|
export type ToolbarProps = ThemedClassName<
|
|
44
53
|
PropsWithChildren<{
|
|
@@ -96,7 +105,7 @@ const Format = () => {
|
|
|
96
105
|
Icon={Icon}
|
|
97
106
|
// disabled={state?.blockType === 'codeblock'}
|
|
98
107
|
// onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
|
|
99
|
-
onClick={() => onAction?.({ type })}
|
|
108
|
+
onClick={() => onAction?.({ type: type as Exclude<typeof type, 'comment'> })}
|
|
100
109
|
>
|
|
101
110
|
{t(`toolbar ${type} label`)}
|
|
102
111
|
</ToolbarToggleButton>
|
|
@@ -127,7 +136,7 @@ const Alignment = () => {
|
|
|
127
136
|
Icon={Icon}
|
|
128
137
|
// disabled={state?.blockType === 'codeblock'}
|
|
129
138
|
// onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
|
|
130
|
-
onClick={() => onAction?.({ type })}
|
|
139
|
+
onClick={() => onAction?.({ type: type as Exclude<typeof type, 'comment'> })}
|
|
131
140
|
>
|
|
132
141
|
{t(`toolbar ${type} label`)}
|
|
133
142
|
</ToolbarToggleButton>
|
|
@@ -157,7 +166,7 @@ const Styles = () => {
|
|
|
157
166
|
Icon={Icon}
|
|
158
167
|
// disabled={state?.blockType === 'codeblock'}
|
|
159
168
|
// onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
|
|
160
|
-
onClick={() => onAction?.({ type })}
|
|
169
|
+
onClick={() => onAction?.({ type: type as Exclude<typeof type, 'comment'> })}
|
|
161
170
|
>
|
|
162
171
|
{t(`toolbar ${type} label`)}
|
|
163
172
|
</ToolbarToggleButton>
|
|
@@ -171,17 +180,49 @@ const Styles = () => {
|
|
|
171
180
|
//
|
|
172
181
|
|
|
173
182
|
const Actions = () => {
|
|
174
|
-
|
|
183
|
+
const { onAction } = useToolbarContext('Actions');
|
|
184
|
+
const { cursor, range, model } = useSheetContext();
|
|
175
185
|
const { t } = useTranslation(SHEET_PLUGIN);
|
|
186
|
+
|
|
187
|
+
const overlapsCommentAnchor = (model.sheet.threads ?? [])
|
|
188
|
+
.filter(nonNullable)
|
|
189
|
+
.filter((thread) => thread.status !== 'resolved')
|
|
190
|
+
.some((thread) => {
|
|
191
|
+
if (!cursor) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
return addressToIndex(model.sheet, cursor) === thread.anchor;
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const hasCursor = !!cursor;
|
|
198
|
+
const cursorOnly = hasCursor && !range && !overlapsCommentAnchor;
|
|
199
|
+
|
|
200
|
+
const tooltipLabelKey = !hasCursor
|
|
201
|
+
? 'no cursor label'
|
|
202
|
+
: overlapsCommentAnchor
|
|
203
|
+
? 'selection overlaps existing comment label'
|
|
204
|
+
: range
|
|
205
|
+
? 'comment ranges not supported label'
|
|
206
|
+
: 'comment label';
|
|
207
|
+
|
|
176
208
|
return (
|
|
177
209
|
<ToolbarButton
|
|
178
210
|
value='comment'
|
|
179
211
|
Icon={ChatText}
|
|
180
212
|
data-testid='editor.toolbar.comment'
|
|
181
|
-
|
|
182
|
-
|
|
213
|
+
onClick={() => {
|
|
214
|
+
if (!cursor) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
return onAction?.({
|
|
218
|
+
type: 'comment',
|
|
219
|
+
anchor: addressToIndex(model.sheet, cursor),
|
|
220
|
+
cellContent: model.getCellText(cursor),
|
|
221
|
+
});
|
|
222
|
+
}}
|
|
223
|
+
disabled={!cursorOnly || overlapsCommentAnchor}
|
|
183
224
|
>
|
|
184
|
-
{t(
|
|
225
|
+
{t(tooltipLabelKey)}
|
|
185
226
|
</ToolbarButton>
|
|
186
227
|
);
|
|
187
228
|
};
|
package/src/components/index.ts
CHANGED
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { getIndices, sortByIndex, getIndicesBelow, getIndicesAbove, getIndicesBetween } from '@tldraw/indices';
|
|
6
|
-
import { expect } from '
|
|
7
|
-
import { describe, test } from 'vitest';
|
|
6
|
+
import { describe, expect, test } from 'vitest';
|
|
8
7
|
|
|
9
8
|
import { inRange, addressFromA1Notation, addressToA1Notation, rangeFromA1Notation, rangeToA1Notation } from './types';
|
|
10
9
|
|
|
11
10
|
describe('cell', () => {
|
|
12
11
|
test('posToA1Notation', () => {
|
|
13
|
-
expect(addressToA1Notation({
|
|
14
|
-
expect(addressFromA1Notation('C2')).to.deep.eq({
|
|
12
|
+
expect(addressToA1Notation({ col: 0, row: 0 })).to.eq('A1');
|
|
13
|
+
expect(addressFromA1Notation('C2')).to.deep.eq({ col: 2, row: 1 });
|
|
15
14
|
});
|
|
16
15
|
|
|
17
16
|
test('rangeToA1Notation', () => {
|
|
@@ -56,19 +55,19 @@ describe('cell', () => {
|
|
|
56
55
|
// Values.
|
|
57
56
|
const cells: Record<string, any> = {};
|
|
58
57
|
const setCell = (cell: string, value: any) => {
|
|
59
|
-
const {
|
|
58
|
+
const { col, row } = addressFromA1Notation(cell);
|
|
60
59
|
// Reallocate if > current bounds.
|
|
61
|
-
if (
|
|
62
|
-
insertIndex(columns,
|
|
60
|
+
if (col >= columns.length) {
|
|
61
|
+
insertIndex(columns, col);
|
|
63
62
|
}
|
|
64
63
|
if (row >= rows.length) {
|
|
65
64
|
insertIndex(rows, row);
|
|
66
65
|
}
|
|
67
|
-
const index = `${columns[
|
|
66
|
+
const index = `${columns[col]}@${rows[row]}`;
|
|
68
67
|
cells[index] = value;
|
|
69
68
|
};
|
|
70
69
|
|
|
71
|
-
expect(addressFromA1Notation('A1')).to.deep.eq({
|
|
70
|
+
expect(addressFromA1Notation('A1')).to.deep.eq({ col: 0, row: 0 });
|
|
72
71
|
|
|
73
72
|
expect(columns).to.deep.eq(['a1', 'a2', 'a3', 'a4', 'a5']);
|
|
74
73
|
insertIndex(columns, 7);
|
|
@@ -4,25 +4,34 @@
|
|
|
4
4
|
|
|
5
5
|
import { invariant } from '@dxos/invariant';
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const DEFAULT_ROWS = 50;
|
|
8
|
+
export const DEFAULT_COLUMNS = 26;
|
|
9
|
+
|
|
10
|
+
export const MAX_ROWS = 500;
|
|
11
|
+
export const MAX_COLUMNS = 26 * 2;
|
|
12
|
+
|
|
13
|
+
export type CellAddress = { col: number; row: number };
|
|
8
14
|
|
|
9
|
-
export type CellAddress = { column: number; row: number };
|
|
10
15
|
export type CellRange = { from: CellAddress; to?: CellAddress };
|
|
11
16
|
|
|
17
|
+
export type CellIndex = string;
|
|
18
|
+
|
|
19
|
+
export type CellContentValue = number | string | boolean | null;
|
|
20
|
+
|
|
12
21
|
export const posEquals = (a: CellAddress | undefined, b: CellAddress | undefined) => {
|
|
13
|
-
return a?.
|
|
22
|
+
return a?.col === b?.col && a?.row === b?.row;
|
|
14
23
|
};
|
|
15
24
|
|
|
16
|
-
export const columnLetter = (
|
|
17
|
-
invariant(
|
|
25
|
+
export const columnLetter = (col: number): string => {
|
|
26
|
+
invariant(col < MAX_COLUMNS, `Invalid column: ${col}`);
|
|
18
27
|
return (
|
|
19
|
-
(
|
|
20
|
-
String.fromCharCode('A'.charCodeAt(0) + (
|
|
28
|
+
(col >= 26 ? String.fromCharCode('A'.charCodeAt(0) + Math.floor(col / 26) - 1) : '') +
|
|
29
|
+
String.fromCharCode('A'.charCodeAt(0) + (col % 26))
|
|
21
30
|
);
|
|
22
31
|
};
|
|
23
32
|
|
|
24
|
-
export const addressToA1Notation = ({
|
|
25
|
-
return `${columnLetter(
|
|
33
|
+
export const addressToA1Notation = ({ col, row }: CellAddress): string => {
|
|
34
|
+
return `${columnLetter(col)}${row + 1}`;
|
|
26
35
|
};
|
|
27
36
|
|
|
28
37
|
export const addressFromA1Notation = (ref: string): CellAddress => {
|
|
@@ -30,7 +39,7 @@ export const addressFromA1Notation = (ref: string): CellAddress => {
|
|
|
30
39
|
invariant(match, `Invalid notation: ${ref}`);
|
|
31
40
|
return {
|
|
32
41
|
row: parseInt(match[2], 10) - 1,
|
|
33
|
-
|
|
42
|
+
col: match[1].split('').reduce((acc, c) => acc * 26 + c.charCodeAt(0) - 'A'.charCodeAt(0) + 1, 0) - 1,
|
|
34
43
|
};
|
|
35
44
|
};
|
|
36
45
|
|
|
@@ -59,13 +68,13 @@ export const inRange = (range: CellRange | undefined, cell: CellAddress): boolea
|
|
|
59
68
|
return false;
|
|
60
69
|
}
|
|
61
70
|
|
|
62
|
-
const {
|
|
63
|
-
const {
|
|
71
|
+
const { col: c1, row: r1 } = from;
|
|
72
|
+
const { col: c2, row: r2 } = to;
|
|
64
73
|
const cMin = Math.min(c1, c2);
|
|
65
74
|
const cMax = Math.max(c1, c2);
|
|
66
75
|
const rMin = Math.min(r1, r2);
|
|
67
76
|
const rMax = Math.max(r1, r2);
|
|
68
77
|
|
|
69
|
-
const {
|
|
70
|
-
return
|
|
78
|
+
const { col, row } = cell;
|
|
79
|
+
return col >= cMin && col <= cMax && row >= rMin && row <= rMax;
|
|
71
80
|
};
|
package/src/defs/util.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { randomBytes } from '@dxos/crypto';
|
|
6
|
+
import { create } from '@dxos/echo-schema';
|
|
7
|
+
|
|
8
|
+
import { type CellAddress, type CellRange, DEFAULT_COLUMNS, DEFAULT_ROWS, MAX_COLUMNS, MAX_ROWS } from './types';
|
|
9
|
+
import { type CreateSheetOptions, type SheetSize, SheetType } from '../types';
|
|
10
|
+
|
|
11
|
+
// TODO(burdon): Factor out from dxos/protocols to new common package.
|
|
12
|
+
export class ApiError extends Error {}
|
|
13
|
+
|
|
14
|
+
export class ReadonlyException extends ApiError {}
|
|
15
|
+
|
|
16
|
+
export class RangeException extends ApiError {
|
|
17
|
+
constructor(n: number) {
|
|
18
|
+
super();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* With a string length of 8, the chance of a collision is 0.02% for a sheet with 10,000 strings.
|
|
24
|
+
*/
|
|
25
|
+
export const createIndex = (length = 8): string => {
|
|
26
|
+
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
27
|
+
const charactersLength = characters.length;
|
|
28
|
+
const randomBuffer = randomBytes(length);
|
|
29
|
+
return Array.from(randomBuffer, (byte) => characters[byte % charactersLength]).join('');
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const createIndices = (length: number): string[] => Array.from({ length }).map(() => createIndex());
|
|
33
|
+
|
|
34
|
+
export const insertIndices = (indices: string[], i: number, n: number, max: number) => {
|
|
35
|
+
if (i + n > max) {
|
|
36
|
+
throw new RangeException(i + n);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const idx = createIndices(n);
|
|
40
|
+
indices.splice(i, 0, ...idx);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const initialize = (
|
|
44
|
+
sheet: SheetType,
|
|
45
|
+
{ rows = DEFAULT_ROWS, columns = DEFAULT_COLUMNS }: Partial<SheetSize> = {},
|
|
46
|
+
) => {
|
|
47
|
+
if (!sheet.rows.length) {
|
|
48
|
+
insertIndices(sheet.rows, 0, rows, MAX_ROWS);
|
|
49
|
+
}
|
|
50
|
+
if (!sheet.columns.length) {
|
|
51
|
+
insertIndices(sheet.columns, 0, columns, MAX_COLUMNS);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const createSheet = ({ title, ...size }: CreateSheetOptions = {}): SheetType => {
|
|
56
|
+
const sheet = create(SheetType, {
|
|
57
|
+
title,
|
|
58
|
+
cells: {},
|
|
59
|
+
rows: [],
|
|
60
|
+
columns: [],
|
|
61
|
+
rowMeta: {},
|
|
62
|
+
columnMeta: {},
|
|
63
|
+
formatting: {},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
initialize(sheet, size);
|
|
67
|
+
return sheet;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* E.g., "A1" => "CA2@CB3".
|
|
72
|
+
*/
|
|
73
|
+
export const addressToIndex = (sheet: SheetType, cell: CellAddress): string => {
|
|
74
|
+
return `${sheet.columns[cell.col]}@${sheet.rows[cell.row]}`;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* E.g., "CA2@CB3" => "A1".
|
|
79
|
+
*/
|
|
80
|
+
export const addressFromIndex = (sheet: SheetType, idx: string): CellAddress => {
|
|
81
|
+
const [column, row] = idx.split('@');
|
|
82
|
+
return {
|
|
83
|
+
col: sheet.columns.indexOf(column),
|
|
84
|
+
row: sheet.rows.indexOf(row),
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* E.g., "A1:B2" => "CA2@CB3:CC4@CD5".
|
|
90
|
+
*/
|
|
91
|
+
export const rangeToIndex = (sheet: SheetType, range: CellRange): string => {
|
|
92
|
+
return [range.from, range.to ?? range.from].map((cell) => addressToIndex(sheet, cell)).join(':');
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* E.g., "CA2@CB3:CC4@CD5" => "A1:B2".
|
|
97
|
+
*/
|
|
98
|
+
export const rangeFromIndex = (sheet: SheetType, idx: string): CellRange => {
|
|
99
|
+
const [from, to] = idx.split(':').map((index) => addressFromIndex(sheet, index));
|
|
100
|
+
return { from, to };
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Find closest cell to cursor.
|
|
105
|
+
*/
|
|
106
|
+
export const closest = (cursor: CellAddress, cells: CellAddress[]): CellAddress | undefined => {
|
|
107
|
+
let closestCell: CellAddress | undefined;
|
|
108
|
+
let closestDistance = Number.MAX_SAFE_INTEGER;
|
|
109
|
+
|
|
110
|
+
for (const cell of cells) {
|
|
111
|
+
const distance = Math.abs(cell.row - cursor.row) + Math.abs(cell.col - cursor.col);
|
|
112
|
+
if (distance < closestDistance) {
|
|
113
|
+
closestCell = cell;
|
|
114
|
+
closestDistance = distance;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return closestCell;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Compares the positions of two cell indexes in a sheet.
|
|
123
|
+
* Sorts primarily by row, then by column if rows are equal.
|
|
124
|
+
*/
|
|
125
|
+
export const compareIndexPositions = (sheet: SheetType, indexA: string, indexB: string): number => {
|
|
126
|
+
const { row: rowA, col: columnA } = addressFromIndex(sheet, indexA);
|
|
127
|
+
const { row: rowB, col: columnB } = addressFromIndex(sheet, indexB);
|
|
128
|
+
|
|
129
|
+
// Sort by row first, then by column.
|
|
130
|
+
if (rowA !== rowB) {
|
|
131
|
+
return rowA - rowB;
|
|
132
|
+
} else {
|
|
133
|
+
return columnA - columnB;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
import React, { useEffect, useState } from 'react';
|
|
7
|
+
|
|
8
|
+
import { useSpace } from '@dxos/react-client/echo';
|
|
9
|
+
import { withClientProvider } from '@dxos/react-client/testing';
|
|
10
|
+
import { useThemeContext } from '@dxos/react-ui';
|
|
11
|
+
import {
|
|
12
|
+
createBasicExtensions,
|
|
13
|
+
createMarkdownExtensions,
|
|
14
|
+
createThemeExtensions,
|
|
15
|
+
decorateMarkdown,
|
|
16
|
+
useTextEditor,
|
|
17
|
+
} from '@dxos/react-ui-editor';
|
|
18
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
19
|
+
import { nonNullable } from '@dxos/util';
|
|
20
|
+
|
|
21
|
+
import { compute } from './compute';
|
|
22
|
+
import { Sheet } from '../components';
|
|
23
|
+
import { type ComputeNode } from '../graph';
|
|
24
|
+
import { useComputeGraph, useSheetModel } from '../hooks';
|
|
25
|
+
import { useTestSheet, withGraphDecorator } from '../testing';
|
|
26
|
+
import { SheetType } from '../types';
|
|
27
|
+
|
|
28
|
+
const str = (...lines: string[]) => lines.join('\n');
|
|
29
|
+
|
|
30
|
+
type EditorProps = {
|
|
31
|
+
text?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// TODO(burdon): Implement named expressions.
|
|
35
|
+
// https://hyperformula.handsontable.com/guide/cell-references.html
|
|
36
|
+
|
|
37
|
+
const DOC_NAME = 'Test Doc';
|
|
38
|
+
const SHEET_NAME = 'Test Sheet';
|
|
39
|
+
|
|
40
|
+
const Editor = ({ text }: EditorProps) => {
|
|
41
|
+
const { themeMode } = useThemeContext();
|
|
42
|
+
const space = useSpace();
|
|
43
|
+
const graph = useComputeGraph(space);
|
|
44
|
+
const [node, setNode] = useState<ComputeNode>();
|
|
45
|
+
// TODO(burdon): Virtualize SheetModel.
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (graph) {
|
|
48
|
+
setNode(graph.getOrCreateNode(DOC_NAME));
|
|
49
|
+
}
|
|
50
|
+
}, [graph]);
|
|
51
|
+
const { parentRef, focusAttributes } = useTextEditor(
|
|
52
|
+
() => ({
|
|
53
|
+
initialValue: text,
|
|
54
|
+
extensions: [
|
|
55
|
+
createBasicExtensions(),
|
|
56
|
+
createMarkdownExtensions({ themeMode }),
|
|
57
|
+
createThemeExtensions({ themeMode, syntaxHighlighting: true }),
|
|
58
|
+
node && compute(node),
|
|
59
|
+
decorateMarkdown(),
|
|
60
|
+
].filter(nonNullable),
|
|
61
|
+
}),
|
|
62
|
+
[node, themeMode],
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return <div className='w-[40rem] overflow-hidden' ref={parentRef} {...focusAttributes} />;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const Grid = () => {
|
|
69
|
+
const space = useSpace();
|
|
70
|
+
const graph = useComputeGraph(space);
|
|
71
|
+
const sheet = useTestSheet(space, graph, { title: SHEET_NAME });
|
|
72
|
+
const model = useSheetModel(space, sheet);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (model) {
|
|
75
|
+
model.setValues({ A1: { value: 100 }, A2: { value: 200 }, A3: { value: 300 }, A5: { value: '=SUM(A1:A3)' } });
|
|
76
|
+
}
|
|
77
|
+
}, [model]);
|
|
78
|
+
|
|
79
|
+
if (!space || !sheet) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div className='flex w-[40rem] overflow-hidden'>
|
|
85
|
+
<Sheet.Root space={space} sheet={sheet}>
|
|
86
|
+
<Sheet.Main classNames='border border-separator' />
|
|
87
|
+
</Sheet.Root>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const Story = (props: EditorProps) => {
|
|
93
|
+
return (
|
|
94
|
+
<div className='grid grid-rows-2'>
|
|
95
|
+
<Editor {...props} />
|
|
96
|
+
<Grid />
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export default {
|
|
102
|
+
title: 'plugin-sheet/extensions',
|
|
103
|
+
decorators: [
|
|
104
|
+
withClientProvider({ types: [SheetType], createIdentity: true, createSpace: true }),
|
|
105
|
+
withGraphDecorator,
|
|
106
|
+
withTheme,
|
|
107
|
+
withLayout({ fullscreen: true, classNames: 'justify-center' }),
|
|
108
|
+
],
|
|
109
|
+
parameters: { layout: 'fullscreen' },
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const Default = {
|
|
113
|
+
render: Editor,
|
|
114
|
+
args: {
|
|
115
|
+
text: str(
|
|
116
|
+
//
|
|
117
|
+
'# Compute Graph',
|
|
118
|
+
'',
|
|
119
|
+
'This is a compute expression:',
|
|
120
|
+
'',
|
|
121
|
+
'```dx',
|
|
122
|
+
'=SUM(1, 2)',
|
|
123
|
+
'```',
|
|
124
|
+
'',
|
|
125
|
+
'It should change in realtime.',
|
|
126
|
+
'',
|
|
127
|
+
'```dx',
|
|
128
|
+
'=SUM(3, 5)',
|
|
129
|
+
'```',
|
|
130
|
+
'',
|
|
131
|
+
'',
|
|
132
|
+
),
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const Graph = {
|
|
137
|
+
render: Story,
|
|
138
|
+
args: {
|
|
139
|
+
text: str(
|
|
140
|
+
//
|
|
141
|
+
'# Compute Graph',
|
|
142
|
+
'',
|
|
143
|
+
'The total projected cost is:',
|
|
144
|
+
'',
|
|
145
|
+
'```dx',
|
|
146
|
+
`="${SHEET_NAME}"!A5`,
|
|
147
|
+
'```',
|
|
148
|
+
'',
|
|
149
|
+
),
|
|
150
|
+
},
|
|
151
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { syntaxTree } from '@codemirror/language';
|
|
6
|
+
import {
|
|
7
|
+
type EditorState,
|
|
8
|
+
type Extension,
|
|
9
|
+
type RangeSet,
|
|
10
|
+
RangeSetBuilder,
|
|
11
|
+
StateEffect,
|
|
12
|
+
StateField,
|
|
13
|
+
type Transaction,
|
|
14
|
+
} from '@codemirror/state';
|
|
15
|
+
import { Decoration, EditorView, ViewPlugin, WidgetType } from '@codemirror/view';
|
|
16
|
+
|
|
17
|
+
import { type ComputeNode } from '../graph';
|
|
18
|
+
|
|
19
|
+
const LANGUAGE_TAG = 'dx';
|
|
20
|
+
|
|
21
|
+
// TODO(burdon): Create marker just for our decorator?
|
|
22
|
+
const updateAllDecorations = StateEffect.define<void>();
|
|
23
|
+
|
|
24
|
+
export type ComputeOptions = {};
|
|
25
|
+
|
|
26
|
+
export const compute = (computeNode: ComputeNode, options: ComputeOptions = {}): Extension => {
|
|
27
|
+
const update = (state: EditorState) => {
|
|
28
|
+
const builder = new RangeSetBuilder();
|
|
29
|
+
syntaxTree(state).iterate({
|
|
30
|
+
enter: (node) => {
|
|
31
|
+
if (node.name === 'FencedCode') {
|
|
32
|
+
const cursor = state.selection.main.head;
|
|
33
|
+
if (state.readOnly || cursor < node.from || cursor > node.to) {
|
|
34
|
+
const info = node.node.getChild('CodeInfo');
|
|
35
|
+
if (info) {
|
|
36
|
+
const type = state.sliceDoc(info.from, info.to);
|
|
37
|
+
const text = node.node.getChild('CodeText');
|
|
38
|
+
if (type === LANGUAGE_TAG && text) {
|
|
39
|
+
const content = state.sliceDoc(text.from, text.to);
|
|
40
|
+
// TODO(burdon): Map unique reference onto cell; e.g., track ordered list?
|
|
41
|
+
computeNode.setValue({ col: 0, row: 0 }, content);
|
|
42
|
+
const value = computeNode.getValue({ col: 0, row: 0 });
|
|
43
|
+
builder.add(
|
|
44
|
+
node.from,
|
|
45
|
+
node.to,
|
|
46
|
+
Decoration.replace({
|
|
47
|
+
widget: new DxWidget(String(value)),
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return builder.finish();
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return [
|
|
61
|
+
// Graph subscription.
|
|
62
|
+
ViewPlugin.fromClass(
|
|
63
|
+
class {
|
|
64
|
+
private readonly _subscription: any;
|
|
65
|
+
constructor(view: EditorView) {
|
|
66
|
+
this._subscription = computeNode.graph.update.on(() => {
|
|
67
|
+
view.dispatch({
|
|
68
|
+
effects: updateAllDecorations.of(),
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
destroy() {
|
|
74
|
+
this._subscription();
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
),
|
|
78
|
+
|
|
79
|
+
// Decorations.
|
|
80
|
+
StateField.define<RangeSet<any>>({
|
|
81
|
+
create: (state) => update(state),
|
|
82
|
+
update: (_: RangeSet<any>, tr: Transaction) => update(tr.state),
|
|
83
|
+
provide: (field) => EditorView.decorations.from(field),
|
|
84
|
+
}),
|
|
85
|
+
];
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
class DxWidget extends WidgetType {
|
|
89
|
+
constructor(private readonly value: string) {
|
|
90
|
+
super();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override toDOM(view: EditorView) {
|
|
94
|
+
const div = document.createElement('div');
|
|
95
|
+
div.innerText = this.value;
|
|
96
|
+
return div;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { CellError, ErrorType, EmptyValue, FunctionPlugin, type HyperFormula } from 'hyperformula';
|
|
6
5
|
import { type InterpreterState } from 'hyperformula/typings/interpreter/InterpreterState';
|
|
7
6
|
import { type InterpreterValue } from 'hyperformula/typings/interpreter/InterpreterValue';
|
|
8
7
|
import { type ProcedureAst } from 'hyperformula/typings/parser';
|
|
@@ -12,6 +11,8 @@ import { debounce, type UnsubscribeCallback } from '@dxos/async';
|
|
|
12
11
|
import { type Space } from '@dxos/client/echo';
|
|
13
12
|
import { log } from '@dxos/log';
|
|
14
13
|
|
|
14
|
+
import { CellError, ErrorType, EmptyValue, FunctionPlugin, type HyperFormula } from '#hyperformula';
|
|
15
|
+
|
|
15
16
|
// TODO(burdon): API gateways!
|
|
16
17
|
// https://publicapis.io
|
|
17
18
|
// https://api-ninjas.com/api/cryptoprice
|
|
@@ -82,6 +83,7 @@ export class FunctionContext {
|
|
|
82
83
|
}, this._options.recalculationDelay);
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
// TODO(burdon): Remove?
|
|
85
87
|
get space() {
|
|
86
88
|
return this._space;
|
|
87
89
|
}
|