@dxos/plugin-sheet 0.6.11 → 0.6.12-main.568932b
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-T2QWJOFD.mjs +262 -0
- package/dist/lib/browser/SheetContainer-T2QWJOFD.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FUAGSXA4.mjs → chunk-5ZMVZYGB.mjs} +24 -19
- package/dist/lib/browser/chunk-5ZMVZYGB.mjs.map +7 -0
- package/dist/lib/browser/chunk-GSV5QNLD.mjs +2966 -0
- package/dist/lib/browser/chunk-GSV5QNLD.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/{SheetContainer-U4H5D34A.mjs → chunk-ZL2V5UJR.mjs} +1182 -249
- package/dist/lib/browser/chunk-ZL2V5UJR.mjs.map +7 -0
- package/dist/lib/browser/graph-M4IQ76QX.mjs +33 -0
- package/dist/lib/browser/graph-M4IQ76QX.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +96 -60
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types.mjs +4 -6
- package/dist/lib/node/SheetContainer-PV5ET4UJ.cjs +280 -0
- package/dist/lib/node/SheetContainer-PV5ET4UJ.cjs.map +7 -0
- package/dist/lib/node/{SheetContainer-AXQV3ZT5.cjs → chunk-2K53Z2TU.cjs} +1212 -287
- package/dist/lib/node/chunk-2K53Z2TU.cjs.map +7 -0
- package/dist/lib/node/{chunk-5KKJ4NPP.cjs → chunk-5XPK2V4A.cjs} +418 -678
- package/dist/lib/node/chunk-5XPK2V4A.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-DSYKOI4E.cjs → chunk-STAVQ2JE.cjs} +28 -24
- package/dist/lib/node/chunk-STAVQ2JE.cjs.map +7 -0
- package/dist/lib/node/graph-Q3N2X26H.cjs +55 -0
- package/dist/lib/node/graph-Q3N2X26H.cjs.map +7 -0
- package/dist/lib/node/index.cjs +106 -66
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.cjs +3 -3
- package/dist/lib/node/meta.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +10 -12
- package/dist/lib/node/types.cjs.map +2 -2
- package/dist/lib/node-esm/SheetContainer-FOZD2WLT.mjs +263 -0
- package/dist/lib/node-esm/SheetContainer-FOZD2WLT.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-2HAM45RC.mjs +88 -0
- package/dist/lib/node-esm/chunk-2HAM45RC.mjs.map +7 -0
- package/dist/lib/{browser/chunk-D5AGLXJP.mjs → node-esm/chunk-5WPZCXNS.mjs} +411 -678
- package/dist/lib/node-esm/chunk-5WPZCXNS.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/chunk-QEUCIHIN.mjs +2706 -0
- package/dist/lib/node-esm/chunk-QEUCIHIN.mjs.map +7 -0
- package/dist/lib/node-esm/graph-SMPUMOV2.mjs +34 -0
- package/dist/lib/node-esm/graph-SMPUMOV2.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +285 -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 +16 -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 +8 -7
- 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 +6 -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/graph/compute-graph-registry.d.ts +34 -0
- package/dist/types/src/graph/compute-graph-registry.d.ts.map +1 -0
- package/dist/types/src/graph/compute-graph.d.ts +64 -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-graph.test.d.ts +2 -0
- package/dist/types/src/graph/compute-graph.test.d.ts.map +1 -0
- package/dist/types/src/graph/compute-node.d.ts +26 -0
- package/dist/types/src/graph/compute-node.d.ts.map +1 -0
- package/dist/types/src/{components/ComputeGraph → graph/functions}/async-function.d.ts +14 -5
- package/dist/types/src/graph/functions/async-function.d.ts.map +1 -0
- package/dist/types/src/graph/functions/edge-function.d.ts +21 -0
- package/dist/types/src/graph/functions/edge-function.d.ts.map +1 -0
- package/dist/types/src/{model/functions.d.ts → graph/functions/function-defs.d.ts} +1 -1
- package/dist/types/src/graph/functions/function-defs.d.ts.map +1 -0
- package/dist/types/src/graph/functions/index.d.ts +4 -0
- package/dist/types/src/graph/functions/index.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 +5 -0
- package/dist/types/src/graph/index.d.ts.map +1 -0
- package/dist/types/src/graph/testing/index.d.ts +3 -0
- package/dist/types/src/graph/testing/index.d.ts.map +1 -0
- package/dist/types/src/graph/testing/test-builder.d.ts +15 -0
- package/dist/types/src/graph/testing/test-builder.d.ts.map +1 -0
- package/dist/types/src/graph/testing/test-plugin.d.ts +36 -0
- package/dist/types/src/graph/testing/test-plugin.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} +10 -65
- package/dist/types/src/model/sheet-model.d.ts.map +1 -0
- package/dist/types/src/model/sheet-model.test.d.ts +2 -0
- package/dist/types/src/model/sheet-model.test.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 +8 -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 +86 -5
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/vendor/hyperformula.mjs +37145 -0
- package/package.json +55 -47
- package/src/SheetPlugin.tsx +50 -73
- package/src/components/CellEditor/CellEditor.stories.tsx +6 -6
- package/src/components/CellEditor/CellEditor.tsx +59 -9
- package/src/components/CellEditor/extension.test.ts +4 -6
- package/src/components/CellEditor/extension.ts +5 -6
- package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +20 -0
- package/src/components/ComputeGraph/index.ts +1 -3
- package/src/components/GridSheet/GridSheet.stories.tsx +36 -0
- package/src/components/GridSheet/GridSheet.tsx +171 -0
- package/src/components/GridSheet/util.ts +148 -0
- package/src/components/Sheet/Sheet.stories.tsx +52 -88
- package/src/components/Sheet/Sheet.tsx +87 -32
- 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 +18 -80
- package/src/components/Sheet/threads.tsx +205 -0
- package/src/components/SheetContainer.tsx +68 -16
- 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 +24 -14
- package/src/defs/util.ts +151 -0
- package/src/extensions/compute.stories.tsx +151 -0
- package/src/extensions/compute.ts +147 -0
- package/src/extensions/index.ts +5 -0
- package/src/graph/compute-graph-registry.ts +90 -0
- package/src/graph/compute-graph.stories.tsx +93 -0
- package/src/graph/compute-graph.test.ts +87 -0
- package/src/graph/compute-graph.ts +242 -0
- package/src/graph/compute-node.ts +63 -0
- package/src/{components/ComputeGraph → graph/functions}/async-function.ts +25 -15
- package/src/{components/ComputeGraph → graph/functions}/edge-function.ts +16 -14
- package/src/graph/functions/index.ts +7 -0
- package/src/graph/hyperformula.test.ts +14 -0
- package/src/graph/index.ts +8 -0
- package/src/graph/testing/index.ts +6 -0
- package/src/graph/testing/test-builder.ts +54 -0
- package/src/{components/ComputeGraph/custom.ts → graph/testing/test-plugin.ts} +44 -14
- 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 +28 -0
- package/src/hooks/useFormattingModel.ts +11 -0
- package/src/hooks/useSheetModel.ts +40 -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.test.ts +57 -0
- package/src/model/sheet-model.ts +416 -0
- package/src/sanity.test.ts +40 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/testing.tsx +68 -0
- package/src/translations.ts +6 -1
- package/src/types.ts +35 -10
- 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 +0 -21
- package/dist/types/src/components/ComputeGraph/custom.d.ts.map +0 -1
- package/dist/types/src/components/ComputeGraph/edge-function.d.ts +0 -20
- 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/src/{model/functions.ts → graph/functions/function-defs.ts} +0 -0
|
@@ -25,6 +25,7 @@ import { Resizable, type ResizeCallback, type ResizeStartCallback } from 're-res
|
|
|
25
25
|
import React, {
|
|
26
26
|
type CSSProperties,
|
|
27
27
|
type DOMAttributes,
|
|
28
|
+
type KeyboardEventHandler,
|
|
28
29
|
type PropsWithChildren,
|
|
29
30
|
forwardRef,
|
|
30
31
|
useEffect,
|
|
@@ -40,7 +41,7 @@ import { debounce } from '@dxos/async';
|
|
|
40
41
|
import { fullyQualifiedId, createDocAccessor } from '@dxos/client/echo';
|
|
41
42
|
import { log } from '@dxos/log';
|
|
42
43
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
43
|
-
import {
|
|
44
|
+
import { ATTENABLE_ATTRIBUTE, useAttendableAttributes, useAttention, useAttentionPath } from '@dxos/react-ui-attention';
|
|
44
45
|
import { mx } from '@dxos/react-ui-theme';
|
|
45
46
|
|
|
46
47
|
import {
|
|
@@ -60,6 +61,7 @@ import {
|
|
|
60
61
|
} from './grid';
|
|
61
62
|
import { type GridSize, handleArrowNav, handleNav, useRangeSelect } from './nav';
|
|
62
63
|
import { type SheetContextProps, SheetContextProvider, useSheetContext } from './sheet-context';
|
|
64
|
+
import { useThreads } from './threads';
|
|
63
65
|
import { getRectUnion, getRelativeClientRect, scrollIntoView } from './util';
|
|
64
66
|
import {
|
|
65
67
|
type CellIndex,
|
|
@@ -68,7 +70,9 @@ import {
|
|
|
68
70
|
columnLetter,
|
|
69
71
|
posEquals,
|
|
70
72
|
rangeToA1Notation,
|
|
71
|
-
|
|
73
|
+
addressToIndex,
|
|
74
|
+
addressFromIndex,
|
|
75
|
+
} from '../../defs';
|
|
72
76
|
import {
|
|
73
77
|
CellEditor,
|
|
74
78
|
type CellRangeNotifier,
|
|
@@ -135,12 +139,16 @@ const SheetRoot = ({ children, ...props }: PropsWithChildren<SheetContextProps>)
|
|
|
135
139
|
|
|
136
140
|
type SheetMainProps = ThemedClassName<Partial<GridSize>>;
|
|
137
141
|
|
|
138
|
-
const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows,
|
|
142
|
+
const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numRows, numCols }, forwardRef) => {
|
|
139
143
|
const { model, cursor, setCursor, setRange, setEditing } = useSheetContext();
|
|
140
144
|
|
|
141
145
|
// Scrolling.
|
|
142
146
|
const { rowsRef, columnsRef, contentRef } = useScrollHandlers();
|
|
143
147
|
|
|
148
|
+
// Threads.
|
|
149
|
+
// TODO(Zan): Move this to an extension once we have an extension model.
|
|
150
|
+
useThreads();
|
|
151
|
+
|
|
144
152
|
//
|
|
145
153
|
// Order of Row/columns.
|
|
146
154
|
//
|
|
@@ -170,21 +178,21 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
170
178
|
}, [rows, columns]);
|
|
171
179
|
|
|
172
180
|
const handleMoveRows: SheetRowsProps['onMove'] = (from, to, num = 1) => {
|
|
173
|
-
const cursorIdx = cursor ? model.
|
|
181
|
+
const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : undefined;
|
|
174
182
|
const [rows] = model.sheet.rows.splice(from, num);
|
|
175
183
|
model.sheet.rows.splice(to, 0, rows);
|
|
176
184
|
if (cursorIdx) {
|
|
177
|
-
setCursor(model.
|
|
185
|
+
setCursor(addressFromIndex(model.sheet, cursorIdx));
|
|
178
186
|
}
|
|
179
187
|
setRows([...model.sheet.rows]);
|
|
180
188
|
};
|
|
181
189
|
|
|
182
190
|
const handleMoveColumns: SheetColumnsProps['onMove'] = (from, to, num = 1) => {
|
|
183
|
-
const cursorIdx = cursor ? model.
|
|
191
|
+
const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : undefined;
|
|
184
192
|
const columns = model.sheet.columns.splice(from, num);
|
|
185
193
|
model.sheet.columns.splice(to, 0, ...columns);
|
|
186
194
|
if (cursorIdx) {
|
|
187
|
-
setCursor(model.
|
|
195
|
+
setCursor(addressFromIndex(model.sheet, cursorIdx));
|
|
188
196
|
}
|
|
189
197
|
setColumns([...model.sheet.columns]);
|
|
190
198
|
};
|
|
@@ -256,8 +264,8 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
256
264
|
ref={columnsRef}
|
|
257
265
|
columns={columns}
|
|
258
266
|
sizes={columnSizes}
|
|
259
|
-
selected={cursor?.
|
|
260
|
-
onSelect={(
|
|
267
|
+
selected={cursor?.col}
|
|
268
|
+
onSelect={(col) => setCursor(cursor?.col === col ? undefined : { row: -1, col })}
|
|
261
269
|
onResize={handleResizeColumn}
|
|
262
270
|
onMove={handleMoveColumns}
|
|
263
271
|
/>
|
|
@@ -267,13 +275,13 @@ const SheetMain = forwardRef<HTMLDivElement, SheetMainProps>(({ classNames, numR
|
|
|
267
275
|
rows={rows}
|
|
268
276
|
sizes={rowSizes}
|
|
269
277
|
selected={cursor?.row}
|
|
270
|
-
onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row,
|
|
278
|
+
onSelect={(row) => setCursor(cursor?.row === row ? undefined : { row, col: -1 })}
|
|
271
279
|
onResize={handleResizeRow}
|
|
272
280
|
onMove={handleMoveRows}
|
|
273
281
|
/>
|
|
274
282
|
<SheetGrid
|
|
275
283
|
ref={contentRef}
|
|
276
|
-
size={{ numRows: numRows ?? rows.length,
|
|
284
|
+
size={{ numRows: numRows ?? rows.length, numCols: numCols ?? columns.length }}
|
|
277
285
|
rows={rows}
|
|
278
286
|
columns={columns}
|
|
279
287
|
rowSizes={rowSizes}
|
|
@@ -854,10 +862,8 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
|
|
|
854
862
|
columnSizes,
|
|
855
863
|
});
|
|
856
864
|
|
|
857
|
-
// TODO(burdon): Prevent scroll if not attended.
|
|
858
865
|
const id = fullyQualifiedId(model.sheet);
|
|
859
|
-
const
|
|
860
|
-
const hasAttention = useHasAttention(id);
|
|
866
|
+
const { hasAttention } = useAttention(id);
|
|
861
867
|
|
|
862
868
|
return (
|
|
863
869
|
<div ref={containerRef} role='grid' className='relative flex grow overflow-hidden'>
|
|
@@ -865,6 +871,7 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
|
|
|
865
871
|
<div className={mx('z-20 absolute inset-0 border border-gridLine pointer-events-none')} />
|
|
866
872
|
|
|
867
873
|
{/* Grid scroll container. */}
|
|
874
|
+
{/* NOTE: Prevents scroll if not attended. */}
|
|
868
875
|
<div ref={scrollerRef} className={mx('grow', hasAttention && 'overflow-auto scrollbar-thin')}>
|
|
869
876
|
{/* Scroll content. */}
|
|
870
877
|
<div
|
|
@@ -878,11 +885,11 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
|
|
|
878
885
|
|
|
879
886
|
{/* Grid cells. */}
|
|
880
887
|
{rowRange.map(({ row, top, height }) => {
|
|
881
|
-
return columnRange.map(({
|
|
888
|
+
return columnRange.map(({ col, left, width }) => {
|
|
882
889
|
const style: CSSProperties = { position: 'absolute', top, left, width, height };
|
|
883
|
-
const cell = { row,
|
|
890
|
+
const cell: CellAddress = { row, col };
|
|
884
891
|
const id = addressToA1Notation(cell);
|
|
885
|
-
const idx = model.
|
|
892
|
+
const idx = addressToIndex(model.sheet, cell);
|
|
886
893
|
const active = posEquals(cursor, cell);
|
|
887
894
|
if (active && editing) {
|
|
888
895
|
const value = initialText.current ?? model.getCellText(cell) ?? '';
|
|
@@ -945,21 +952,37 @@ const SheetGrid = forwardRef<HTMLDivElement, SheetGridProps>(
|
|
|
945
952
|
</div>
|
|
946
953
|
|
|
947
954
|
{/* Hidden input for key navigation. */}
|
|
948
|
-
{createPortal(
|
|
949
|
-
<input
|
|
950
|
-
ref={inputRef}
|
|
951
|
-
autoFocus
|
|
952
|
-
className='absolute w-[1px] h-[1px] bg-transparent outline-none border-none caret-transparent'
|
|
953
|
-
onKeyDown={handleKeyDown}
|
|
954
|
-
{...attendableAttrs}
|
|
955
|
-
/>,
|
|
956
|
-
document.body,
|
|
957
|
-
)}
|
|
955
|
+
{createPortal(<SheetInput ref={inputRef} id={id} onKeyDown={handleKeyDown} />, document.body)}
|
|
958
956
|
</div>
|
|
959
957
|
);
|
|
960
958
|
},
|
|
961
959
|
);
|
|
962
960
|
|
|
961
|
+
type SheetInputProps = {
|
|
962
|
+
id: string;
|
|
963
|
+
onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
|
|
964
|
+
};
|
|
965
|
+
|
|
966
|
+
const SheetInput = forwardRef<HTMLInputElement, SheetInputProps>(({ id, onKeyDown }, forwardedRef) => {
|
|
967
|
+
const path = useAttentionPath();
|
|
968
|
+
const attendableAttrs = useAttendableAttributes(id);
|
|
969
|
+
|
|
970
|
+
// TODO(wittjosiah): Consider factoring out as an attention util.
|
|
971
|
+
// Wrap input in attendable divs for each part of the path.
|
|
972
|
+
// This ensures that the sheet stays attended when the input is focused.
|
|
973
|
+
return path.toReversed().reduce(
|
|
974
|
+
(acc, part) => {
|
|
975
|
+
return <div {...{ [ATTENABLE_ATTRIBUTE]: part }}>{acc}</div>;
|
|
976
|
+
},
|
|
977
|
+
<input
|
|
978
|
+
ref={forwardedRef}
|
|
979
|
+
className='absolute w-[1px] h-[1px] bg-transparent outline-none border-none caret-transparent'
|
|
980
|
+
onKeyDown={onKeyDown}
|
|
981
|
+
{...attendableAttrs}
|
|
982
|
+
/>,
|
|
983
|
+
);
|
|
984
|
+
});
|
|
985
|
+
|
|
963
986
|
//
|
|
964
987
|
// Selection
|
|
965
988
|
//
|
|
@@ -1003,16 +1026,46 @@ type SheetCellProps = {
|
|
|
1003
1026
|
};
|
|
1004
1027
|
|
|
1005
1028
|
const SheetCell = ({ id, cell, style, active, onSelect }: SheetCellProps) => {
|
|
1006
|
-
const {
|
|
1029
|
+
const {
|
|
1030
|
+
formatting,
|
|
1031
|
+
editing,
|
|
1032
|
+
setRange,
|
|
1033
|
+
decorations,
|
|
1034
|
+
model: { sheet },
|
|
1035
|
+
} = useSheetContext();
|
|
1007
1036
|
const { value, classNames } = formatting.getFormatting(cell);
|
|
1008
1037
|
|
|
1038
|
+
const decorationsForCell = decorations.getDecorationsForCell(addressToIndex(sheet, cell)) ?? [];
|
|
1039
|
+
const decorationAddedClasses = useMemo(
|
|
1040
|
+
() => decorationsForCell.flatMap((d) => d.classNames ?? []),
|
|
1041
|
+
[decorationsForCell],
|
|
1042
|
+
);
|
|
1043
|
+
const decoratedContent = decorationsForCell.reduce(
|
|
1044
|
+
(children, { decorate }) => {
|
|
1045
|
+
if (!decorate) {
|
|
1046
|
+
return children;
|
|
1047
|
+
}
|
|
1048
|
+
const DecoratorComponent = decorate;
|
|
1049
|
+
return <DecoratorComponent>{children}</DecoratorComponent>;
|
|
1050
|
+
},
|
|
1051
|
+
<div
|
|
1052
|
+
role='none'
|
|
1053
|
+
className={mx(
|
|
1054
|
+
'flex flex-grow bs-full is-full px-2 items-center truncate cursor-pointer',
|
|
1055
|
+
...decorationAddedClasses,
|
|
1056
|
+
)}
|
|
1057
|
+
>
|
|
1058
|
+
{value}
|
|
1059
|
+
</div>,
|
|
1060
|
+
);
|
|
1061
|
+
|
|
1009
1062
|
return (
|
|
1010
1063
|
<div
|
|
1011
1064
|
{...{ [`data-${CELL_DATA_KEY}`]: id }}
|
|
1012
1065
|
role='cell'
|
|
1013
1066
|
style={style}
|
|
1014
1067
|
className={mx(
|
|
1015
|
-
'
|
|
1068
|
+
'border border-gridLine cursor-pointer',
|
|
1016
1069
|
fragments.cell,
|
|
1017
1070
|
active && ['z-20', fragments.cellSelected],
|
|
1018
1071
|
classNames,
|
|
@@ -1026,7 +1079,7 @@ const SheetCell = ({ id, cell, style, active, onSelect }: SheetCellProps) => {
|
|
|
1026
1079
|
}}
|
|
1027
1080
|
onDoubleClick={() => onSelect?.(cell, true)}
|
|
1028
1081
|
>
|
|
1029
|
-
{
|
|
1082
|
+
{decoratedContent}
|
|
1030
1083
|
</div>
|
|
1031
1084
|
);
|
|
1032
1085
|
};
|
|
@@ -1045,10 +1098,11 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
|
|
|
1045
1098
|
notifier.current?.(rangeToA1Notation(range));
|
|
1046
1099
|
}
|
|
1047
1100
|
}, [range]);
|
|
1101
|
+
|
|
1048
1102
|
const extension = useMemo(
|
|
1049
1103
|
() => [
|
|
1050
1104
|
editorKeys({ onNav, onClose }),
|
|
1051
|
-
sheetExtension({ functions: model.
|
|
1105
|
+
sheetExtension({ functions: model.graph.getFunctions() }),
|
|
1052
1106
|
rangeExtension((fn) => (notifier.current = fn)),
|
|
1053
1107
|
],
|
|
1054
1108
|
[model],
|
|
@@ -1072,12 +1126,13 @@ const GridCellEditor = ({ style, value, onNav, onClose }: GridCellEditorProps) =
|
|
|
1072
1126
|
|
|
1073
1127
|
const SheetStatusBar = () => {
|
|
1074
1128
|
const { model, cursor, range } = useSheetContext();
|
|
1129
|
+
|
|
1075
1130
|
let value;
|
|
1076
1131
|
let isFormula = false;
|
|
1077
1132
|
if (cursor) {
|
|
1078
1133
|
value = model.getCellValue(cursor);
|
|
1079
1134
|
if (typeof value === 'string' && value.charAt(0) === '=') {
|
|
1080
|
-
value = model.
|
|
1135
|
+
value = model.graph.mapFunctionBindingFromId(model.mapFormulaIndicesToRefs(value));
|
|
1081
1136
|
isFormula = true;
|
|
1082
1137
|
} else if (value != null) {
|
|
1083
1138
|
value = String(value);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { create } from '@dxos/echo-schema';
|
|
6
|
+
|
|
7
|
+
export type Decoration = {
|
|
8
|
+
type: string;
|
|
9
|
+
/**
|
|
10
|
+
* A wrapping render function to encapsulate cell content. This function is applied between
|
|
11
|
+
* the cell's border and its padding/layout/content, allowing for custom rendering or
|
|
12
|
+
* additional elements to be inserted around the cell's main content.
|
|
13
|
+
*/
|
|
14
|
+
decorate?: (props: { children: React.ReactNode }) => React.ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* An array of CSS class names to be applied to the content of the SheetCell.
|
|
17
|
+
* These classes can be used to style the cell's content independently of its structure.
|
|
18
|
+
*/
|
|
19
|
+
classNames?: string[];
|
|
20
|
+
cellIndex: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const createDecorations = () => {
|
|
24
|
+
// Reactive object to hold decorations
|
|
25
|
+
// TODO(Zan): Use CELL ID's to key the decoration map.
|
|
26
|
+
// TODO(Zan): Consider maintaining an index of decorations by type.
|
|
27
|
+
const { decorations } = create<{ decorations: Record<string, Decoration[]> }>({ decorations: {} });
|
|
28
|
+
|
|
29
|
+
const addDecoration = (cellIndex: string, decorator: Decoration) => {
|
|
30
|
+
decorations[cellIndex] = [...(decorations[cellIndex] || []), decorator];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const removeDecoration = (cellIndex: string, type?: string) => {
|
|
34
|
+
if (type) {
|
|
35
|
+
decorations[cellIndex] = (decorations[cellIndex] || []).filter((d) => d.type !== type);
|
|
36
|
+
} else {
|
|
37
|
+
delete decorations[cellIndex];
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// TODO(Zan): I should check if returning the a value from a map in a deep signal is a reactive slice.
|
|
42
|
+
const getDecorationsForCell = (cellIndex: string): Decoration[] | undefined => {
|
|
43
|
+
return decorations[cellIndex];
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const getAllDecorations = (): Decoration[] => {
|
|
47
|
+
const result: Decoration[] = [];
|
|
48
|
+
for (const decoratorArray of Object.values(decorations)) {
|
|
49
|
+
for (const decorator of decoratorArray) {
|
|
50
|
+
result.push(decorator);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
addDecoration,
|
|
58
|
+
removeDecoration,
|
|
59
|
+
getDecorationsForCell,
|
|
60
|
+
getAllDecorations,
|
|
61
|
+
} as const;
|
|
62
|
+
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type MouseEvent, useEffect, useState } from 'react';
|
|
6
6
|
|
|
7
|
-
import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Notation } from '../../
|
|
7
|
+
import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Notation } from '../../defs';
|
|
8
8
|
|
|
9
9
|
// export type Bounds = Pick<DOMRect, 'left' | 'top' | 'width' | 'height'>;
|
|
10
10
|
// export type Dimension = Pick<DOMRect, 'width' | 'height'>;
|
|
@@ -12,7 +12,7 @@ import { type CellAddress, type CellIndex, addressFromA1Notation, addressToA1Not
|
|
|
12
12
|
export type SizeMap = Record<string, number>;
|
|
13
13
|
|
|
14
14
|
export type RowPosition = { row: number } & Pick<DOMRect, 'top' | 'height'>;
|
|
15
|
-
export type ColumnPosition = {
|
|
15
|
+
export type ColumnPosition = { col: number } & Pick<DOMRect, 'left' | 'width'>;
|
|
16
16
|
|
|
17
17
|
export const axisWidth = 'calc(var(--rail-size)-2px)';
|
|
18
18
|
export const axisHeight = 34;
|
|
@@ -88,7 +88,7 @@ export const useGridLayout = ({
|
|
|
88
88
|
const width = columnSizes?.[idx] ?? defaultWidth;
|
|
89
89
|
const left = x;
|
|
90
90
|
x += width - 1;
|
|
91
|
-
return {
|
|
91
|
+
return { col: i, left, width };
|
|
92
92
|
}),
|
|
93
93
|
);
|
|
94
94
|
}, [columns, columnSizes]);
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
import { type KeyboardEvent, type MouseEventHandler, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { getCellAtPointer } from './grid';
|
|
8
|
-
import { type CellAddress, type CellRange, posEquals } from '../../
|
|
8
|
+
import { type CellAddress, type CellRange, posEquals } from '../../defs';
|
|
9
9
|
|
|
10
10
|
export type GridSize = {
|
|
11
11
|
numRows: number;
|
|
12
|
-
|
|
12
|
+
numCols: number;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -38,14 +38,14 @@ export const handleNav = (
|
|
|
38
38
|
break;
|
|
39
39
|
}
|
|
40
40
|
case 'ArrowLeft': {
|
|
41
|
-
if (opposite.
|
|
42
|
-
opposite.
|
|
41
|
+
if (opposite.col > 0) {
|
|
42
|
+
opposite.col -= 1;
|
|
43
43
|
}
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
46
46
|
case 'ArrowRight': {
|
|
47
|
-
if (opposite.
|
|
48
|
-
opposite.
|
|
47
|
+
if (opposite.col < size.numCols - 1) {
|
|
48
|
+
opposite.col += 1;
|
|
49
49
|
}
|
|
50
50
|
break;
|
|
51
51
|
}
|
|
@@ -64,41 +64,41 @@ export const handleNav = (
|
|
|
64
64
|
export const handleArrowNav = (
|
|
65
65
|
ev: Pick<KeyboardEvent<HTMLInputElement>, 'key' | 'metaKey'>,
|
|
66
66
|
cursor: CellAddress | undefined,
|
|
67
|
-
{ numRows,
|
|
67
|
+
{ numRows, numCols }: GridSize,
|
|
68
68
|
): CellAddress | undefined => {
|
|
69
69
|
switch (ev.key) {
|
|
70
70
|
case 'ArrowUp':
|
|
71
71
|
if (cursor === undefined) {
|
|
72
|
-
return { row: 0,
|
|
72
|
+
return { row: 0, col: 0 };
|
|
73
73
|
} else if (cursor.row > 0) {
|
|
74
|
-
return { row: ev.metaKey ? 0 : cursor.row - 1,
|
|
74
|
+
return { row: ev.metaKey ? 0 : cursor.row - 1, col: cursor.col };
|
|
75
75
|
}
|
|
76
76
|
break;
|
|
77
77
|
case 'ArrowDown':
|
|
78
78
|
if (cursor === undefined) {
|
|
79
|
-
return { row: 0,
|
|
79
|
+
return { row: 0, col: 0 };
|
|
80
80
|
} else if (cursor.row < numRows - 1) {
|
|
81
|
-
return { row: ev.metaKey ? numRows - 1 : cursor.row + 1,
|
|
81
|
+
return { row: ev.metaKey ? numRows - 1 : cursor.row + 1, col: cursor.col };
|
|
82
82
|
}
|
|
83
83
|
break;
|
|
84
84
|
case 'ArrowLeft':
|
|
85
85
|
if (cursor === undefined) {
|
|
86
|
-
return { row: 0,
|
|
87
|
-
} else if (cursor.
|
|
88
|
-
return { row: cursor.row,
|
|
86
|
+
return { row: 0, col: 0 };
|
|
87
|
+
} else if (cursor.col > 0) {
|
|
88
|
+
return { row: cursor.row, col: ev.metaKey ? 0 : cursor.col - 1 };
|
|
89
89
|
}
|
|
90
90
|
break;
|
|
91
91
|
case 'ArrowRight':
|
|
92
92
|
if (cursor === undefined) {
|
|
93
|
-
return { row: 0,
|
|
94
|
-
} else if (cursor.
|
|
95
|
-
return { row: cursor.row,
|
|
93
|
+
return { row: 0, col: 0 };
|
|
94
|
+
} else if (cursor.col < numCols - 1) {
|
|
95
|
+
return { row: cursor.row, col: ev.metaKey ? numCols - 1 : cursor.col + 1 };
|
|
96
96
|
}
|
|
97
97
|
break;
|
|
98
98
|
case 'Home':
|
|
99
|
-
return { row: 0,
|
|
99
|
+
return { row: 0, col: 0 };
|
|
100
100
|
case 'End':
|
|
101
|
-
return { row: numRows - 1,
|
|
101
|
+
return { row: numRows - 1, col: numCols - 1 };
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
104
|
|
|
@@ -2,21 +2,16 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { type PropsWithChildren, createContext, useContext,
|
|
5
|
+
import React, { type PropsWithChildren, createContext, useContext, useMemo, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
|
-
import { type FunctionType } from '@dxos/plugin-script';
|
|
9
|
-
import { fullyQualifiedId, type Space } from '@dxos/react-client/echo';
|
|
10
8
|
|
|
11
|
-
import {
|
|
12
|
-
import { type CellAddress, type CellRange
|
|
9
|
+
import { createDecorations } from './decorations';
|
|
10
|
+
import { type CellAddress, type CellRange } from '../../defs';
|
|
11
|
+
import { type ComputeGraph } from '../../graph';
|
|
12
|
+
import { useSheetModel, useFormattingModel } from '../../hooks';
|
|
13
|
+
import { type FormattingModel, type SheetModel } from '../../model';
|
|
13
14
|
import { type SheetType } from '../../types';
|
|
14
|
-
import { type FunctionContextOptions } from '../ComputeGraph';
|
|
15
|
-
// TODO(wittjosiah): Refactor. This is not exported from ./components due to depending on ECHO.
|
|
16
|
-
import { useComputeGraph } from '../ComputeGraph/graph-context';
|
|
17
|
-
|
|
18
|
-
// TODO(wittjosiah): Factor out.
|
|
19
|
-
const OBJECT_ID_LENGTH = 60; // 33 (space id) + 26 (object id) + 1 (separator).
|
|
20
15
|
|
|
21
16
|
export type SheetContextType = {
|
|
22
17
|
model: SheetModel;
|
|
@@ -36,6 +31,9 @@ export type SheetContextType = {
|
|
|
36
31
|
// Events.
|
|
37
32
|
// TODO(burdon): Generalize.
|
|
38
33
|
onInfo?: () => void;
|
|
34
|
+
|
|
35
|
+
// Decorations.
|
|
36
|
+
decorations: ReturnType<typeof createDecorations>;
|
|
39
37
|
};
|
|
40
38
|
|
|
41
39
|
const SheetContext = createContext<SheetContextType | null>(null);
|
|
@@ -47,89 +45,28 @@ export const useSheetContext = (): SheetContextType => {
|
|
|
47
45
|
};
|
|
48
46
|
|
|
49
47
|
export type SheetContextProps = {
|
|
48
|
+
graph: ComputeGraph;
|
|
50
49
|
sheet: SheetType;
|
|
51
|
-
space: Space;
|
|
52
50
|
readonly?: boolean;
|
|
53
|
-
} & Pick<SheetContextType, 'onInfo'
|
|
54
|
-
Partial<FunctionContextOptions>;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Map from binding to fully qualified ECHO ID.
|
|
58
|
-
*/
|
|
59
|
-
const mapFormulaBindingToId =
|
|
60
|
-
(functions: FunctionType[]) =>
|
|
61
|
-
(formula: string): string => {
|
|
62
|
-
return formula.replace(/([a-zA-Z0-9]+)\((.*)\)/g, (match, binding, args) => {
|
|
63
|
-
if (defaultFunctions.find((fn) => fn.name === binding) || binding === 'EDGE') {
|
|
64
|
-
return match;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const fn = functions.find((fn) => fn.binding === binding);
|
|
68
|
-
if (fn) {
|
|
69
|
-
return `${fullyQualifiedId(fn)}(${args})`;
|
|
70
|
-
} else {
|
|
71
|
-
return match;
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Map from fully qualified ECHO ID to binding.
|
|
78
|
-
*/
|
|
79
|
-
const mapFormulaBindingFromId =
|
|
80
|
-
(functions: FunctionType[]) =>
|
|
81
|
-
(formula: string): string => {
|
|
82
|
-
return formula.replace(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)\((.*)\)/g, (match, spaceId, objectId, args) => {
|
|
83
|
-
const id = `${spaceId}:${objectId}`;
|
|
84
|
-
if (id.length !== OBJECT_ID_LENGTH) {
|
|
85
|
-
return match;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const fn = functions.find((fn) => fullyQualifiedId(fn) === id);
|
|
89
|
-
if (fn?.binding) {
|
|
90
|
-
return `${fn.binding}(${args})`;
|
|
91
|
-
} else {
|
|
92
|
-
return match;
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
};
|
|
51
|
+
} & Pick<SheetContextType, 'onInfo'>;
|
|
96
52
|
|
|
97
53
|
export const SheetContextProvider = ({
|
|
98
54
|
children,
|
|
55
|
+
graph,
|
|
99
56
|
sheet,
|
|
100
|
-
space,
|
|
101
57
|
readonly,
|
|
102
58
|
onInfo,
|
|
103
|
-
...options
|
|
104
59
|
}: PropsWithChildren<SheetContextProps>) => {
|
|
105
|
-
const
|
|
60
|
+
const model = useSheetModel(graph, sheet, { readonly });
|
|
61
|
+
const formatting = useFormattingModel(model);
|
|
106
62
|
|
|
63
|
+
// TODO(Zan): Impl. set range and set cursor that scrolls to that cell or range if it is not visible.
|
|
107
64
|
const [cursor, setCursor] = useState<CellAddress>();
|
|
108
65
|
const [range, setRange] = useState<CellRange>();
|
|
109
66
|
const [editing, setEditing] = useState<boolean>(false);
|
|
67
|
+
const decorations = useMemo(() => createDecorations(), []);
|
|
110
68
|
|
|
111
|
-
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
let model: SheetModel | undefined;
|
|
114
|
-
let formatting;
|
|
115
|
-
const t = setTimeout(async () => {
|
|
116
|
-
model = new SheetModel(graph, sheet, space, { readonly, mapFormulaBindingToId, mapFormulaBindingFromId });
|
|
117
|
-
await model.initialize();
|
|
118
|
-
formatting = new FormattingModel(model);
|
|
119
|
-
setModels([model, formatting]);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
return () => {
|
|
123
|
-
clearTimeout(t);
|
|
124
|
-
void model?.destroy();
|
|
125
|
-
};
|
|
126
|
-
}, [graph, readonly]);
|
|
127
|
-
|
|
128
|
-
if (!model || !formatting) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return (
|
|
69
|
+
return !model || !formatting ? null : (
|
|
133
70
|
<SheetContext.Provider
|
|
134
71
|
value={{
|
|
135
72
|
model,
|
|
@@ -142,6 +79,7 @@ export const SheetContextProvider = ({
|
|
|
142
79
|
setEditing,
|
|
143
80
|
// TODO(burdon): Change to event.
|
|
144
81
|
onInfo,
|
|
82
|
+
decorations,
|
|
145
83
|
}}
|
|
146
84
|
>
|
|
147
85
|
{children}
|