@dxos/plugin-sheet 0.6.12-main.f9d0246 → 0.6.12-staging.0b4bb48
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/{chunk-ZLJ2GRE2.mjs → SheetContainer-U4H5D34A.mjs} +240 -1151
- package/dist/lib/browser/SheetContainer-U4H5D34A.mjs.map +7 -0
- package/dist/lib/browser/chunk-APHOLYUB.mjs +175 -0
- package/dist/lib/browser/chunk-APHOLYUB.mjs.map +7 -0
- package/dist/lib/browser/{chunk-Z2XOOC2R.mjs → chunk-D5AGLXJP.mjs} +678 -385
- package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +7 -0
- package/dist/lib/browser/{chunk-WZMOZKQZ.mjs → chunk-FUAGSXA4.mjs} +16 -9
- package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +7 -0
- package/dist/lib/{node-esm/chunk-IU2L277A.mjs → browser/chunk-JRL5LGCE.mjs} +5 -4
- package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +7 -0
- package/dist/lib/browser/chunk-NU4PBN33.mjs +8 -0
- package/dist/lib/browser/chunk-NU4PBN33.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +60 -74
- 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/testing.mjs +92 -0
- package/dist/lib/browser/testing.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +6 -4
- package/dist/lib/node/{chunk-6DQABRGJ.cjs → SheetContainer-AXQV3ZT5.cjs} +279 -1182
- package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +7 -0
- package/dist/lib/node/{chunk-P5QYYEHQ.cjs → chunk-5KKJ4NPP.cjs} +676 -388
- package/dist/lib/node/chunk-5KKJ4NPP.cjs.map +7 -0
- package/dist/lib/node/{chunk-BNARJ5GM.cjs → chunk-BJ6ZD7MN.cjs} +18 -5
- package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +7 -0
- package/dist/lib/node/chunk-CN3RPESU.cjs +202 -0
- package/dist/lib/node/chunk-CN3RPESU.cjs.map +7 -0
- package/dist/lib/node/{chunk-AOP42UAA.cjs → chunk-DSYKOI4E.cjs} +21 -13
- package/dist/lib/node/chunk-DSYKOI4E.cjs.map +7 -0
- package/dist/lib/node/chunk-PYXHNAAK.cjs +40 -0
- package/dist/lib/node/chunk-PYXHNAAK.cjs.map +7 -0
- package/dist/lib/node/index.cjs +66 -86
- 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/testing.cjs +111 -0
- package/dist/lib/node/testing.cjs.map +7 -0
- package/dist/lib/node/types.cjs +12 -10
- package/dist/lib/node/types.cjs.map +2 -2
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/components/CellEditor/CellEditor.d.ts +3 -23
- 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/{graph → components/ComputeGraph}/async-function.d.ts +2 -8
- package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +1 -0
- package/dist/types/src/{graph/testing/custom-function.d.ts → components/ComputeGraph/custom.d.ts} +2 -4
- package/dist/types/src/components/ComputeGraph/custom.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/graph-context.d.ts +12 -0
- package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +2 -0
- package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/graph.d.ts +26 -0
- package/dist/types/src/components/ComputeGraph/graph.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/index.d.ts +3 -1
- package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
- 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 +6 -5
- package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
- package/dist/types/src/components/Sheet/formatting.d.ts +14 -0
- package/dist/types/src/components/Sheet/formatting.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 +7 -8
- package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer.d.ts +3 -2
- package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +3 -19
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +13 -18
- 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/meta.d.ts +4 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/{graph/function-defs.d.ts → model/functions.d.ts} +1 -1
- package/dist/types/src/model/functions.d.ts.map +1 -0
- package/dist/types/src/model/index.d.ts +3 -2
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/model.browser.test.d.ts +2 -0
- package/dist/types/src/model/model.browser.test.d.ts.map +1 -0
- package/dist/types/src/model/{sheet-model.d.ts → model.d.ts} +65 -10
- package/dist/types/src/model/model.d.ts.map +1 -0
- package/dist/types/src/{defs → model}/types.d.ts +3 -8
- package/dist/types/src/model/types.d.ts.map +1 -0
- package/dist/types/src/model/types.test.d.ts.map +1 -0
- package/dist/types/src/model/util.d.ts +15 -0
- package/dist/types/src/model/util.d.ts.map +1 -0
- package/dist/types/src/testing.d.ts +9 -0
- package/dist/types/src/testing.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +12 -17
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +5 -86
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +41 -48
- package/src/SheetPlugin.tsx +73 -48
- package/src/components/CellEditor/CellEditor.stories.tsx +4 -5
- package/src/components/CellEditor/CellEditor.tsx +9 -59
- package/src/components/CellEditor/extension.test.ts +5 -4
- package/src/components/CellEditor/extension.ts +3 -1
- package/src/{graph → components/ComputeGraph}/async-function.ts +6 -15
- package/src/{graph/testing/custom-function.ts → components/ComputeGraph/custom.ts} +7 -11
- package/src/{graph → components/ComputeGraph}/edge-function.ts +3 -3
- package/src/components/ComputeGraph/graph-context.tsx +50 -0
- package/src/components/ComputeGraph/graph.browser.test.ts +50 -0
- package/src/components/ComputeGraph/graph.ts +62 -0
- package/src/components/ComputeGraph/index.ts +3 -1
- package/src/components/Sheet/Sheet.stories.tsx +88 -52
- package/src/components/Sheet/Sheet.tsx +18 -57
- package/src/{model/formatting-model.ts → components/Sheet/formatting.ts} +13 -20
- package/src/components/Sheet/grid.ts +3 -3
- package/src/components/Sheet/nav.ts +19 -19
- package/src/components/Sheet/sheet-context.tsx +80 -18
- package/src/components/SheetContainer.tsx +19 -73
- package/src/components/Toolbar/Toolbar.tsx +12 -53
- package/src/components/index.ts +0 -1
- package/src/meta.tsx +5 -1
- package/src/model/index.ts +3 -2
- package/src/model/model.browser.test.ts +100 -0
- package/src/model/model.ts +550 -0
- package/src/{defs → model}/types.test.ts +9 -8
- package/src/{defs → model}/types.ts +14 -24
- package/src/model/util.ts +36 -0
- package/src/testing.ts +50 -0
- package/src/translations.ts +1 -6
- package/src/types.ts +6 -31
- package/dist/lib/browser/SheetContainer-VISF3VUB.mjs +0 -261
- package/dist/lib/browser/SheetContainer-VISF3VUB.mjs.map +0 -7
- package/dist/lib/browser/chunk-QILRZNE5.mjs +0 -15
- package/dist/lib/browser/chunk-QILRZNE5.mjs.map +0 -7
- package/dist/lib/browser/chunk-WZMOZKQZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-Z2XOOC2R.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZLJ2GRE2.mjs.map +0 -7
- package/dist/lib/browser/graph-4XFKIHRL.mjs +0 -21
- package/dist/lib/browser/graph-4XFKIHRL.mjs.map +0 -7
- package/dist/lib/node/SheetContainer-2MEALQWW.cjs +0 -279
- package/dist/lib/node/SheetContainer-2MEALQWW.cjs.map +0 -7
- package/dist/lib/node/chunk-6DQABRGJ.cjs.map +0 -7
- package/dist/lib/node/chunk-AOP42UAA.cjs.map +0 -7
- package/dist/lib/node/chunk-BNARJ5GM.cjs.map +0 -7
- package/dist/lib/node/chunk-P5QYYEHQ.cjs.map +0 -7
- package/dist/lib/node/graph-2LRDUXBZ.cjs +0 -43
- package/dist/lib/node/graph-2LRDUXBZ.cjs.map +0 -7
- package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs +0 -262
- package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4MM7THJW.mjs +0 -2944
- package/dist/lib/node-esm/chunk-4MM7THJW.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-5RLTCIE2.mjs +0 -2684
- package/dist/lib/node-esm/chunk-5RLTCIE2.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-RR2AO4SM.mjs +0 -76
- package/dist/lib/node-esm/chunk-RR2AO4SM.mjs.map +0 -7
- package/dist/lib/node-esm/graph-WG5EKOMO.mjs +0 -22
- package/dist/lib/node-esm/graph-WG5EKOMO.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -263
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/meta.mjs +0 -10
- package/dist/lib/node-esm/meta.mjs.map +0 -7
- package/dist/lib/node-esm/types.mjs +0 -21
- package/dist/lib/node-esm/types.mjs.map +0 -7
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +0 -11
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +0 -1
- package/dist/types/src/components/GridSheet/GridSheet.d.ts +0 -10
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +0 -1
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +0 -9
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +0 -1
- package/dist/types/src/components/GridSheet/util.d.ts +0 -7
- package/dist/types/src/components/GridSheet/util.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/decorations.d.ts +0 -24
- package/dist/types/src/components/Sheet/decorations.d.ts.map +0 -1
- package/dist/types/src/components/Sheet/threads.d.ts +0 -2
- package/dist/types/src/components/Sheet/threads.d.ts.map +0 -1
- package/dist/types/src/defs/index.d.ts +0 -3
- package/dist/types/src/defs/index.d.ts.map +0 -1
- package/dist/types/src/defs/types.d.ts.map +0 -1
- package/dist/types/src/defs/types.test.d.ts.map +0 -1
- package/dist/types/src/defs/util.d.ts +0 -43
- package/dist/types/src/defs/util.d.ts.map +0 -1
- package/dist/types/src/extensions/compute.d.ts +0 -9
- package/dist/types/src/extensions/compute.d.ts.map +0 -1
- package/dist/types/src/extensions/compute.stories.d.ts +0 -26
- package/dist/types/src/extensions/compute.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/index.d.ts +0 -2
- package/dist/types/src/extensions/index.d.ts.map +0 -1
- package/dist/types/src/graph/async-function.d.ts.map +0 -1
- package/dist/types/src/graph/compute-graph.d.ts +0 -84
- package/dist/types/src/graph/compute-graph.d.ts.map +0 -1
- package/dist/types/src/graph/compute-graph.stories.d.ts +0 -10
- package/dist/types/src/graph/compute-graph.stories.d.ts.map +0 -1
- package/dist/types/src/graph/compute-graph.test.d.ts +0 -2
- package/dist/types/src/graph/compute-graph.test.d.ts.map +0 -1
- package/dist/types/src/graph/compute-node.d.ts +0 -26
- package/dist/types/src/graph/compute-node.d.ts.map +0 -1
- package/dist/types/src/graph/edge-function.d.ts.map +0 -1
- package/dist/types/src/graph/function-defs.d.ts.map +0 -1
- package/dist/types/src/graph/hyperformula.test.d.ts +0 -2
- package/dist/types/src/graph/hyperformula.test.d.ts.map +0 -1
- package/dist/types/src/graph/index.d.ts +0 -4
- package/dist/types/src/graph/index.d.ts.map +0 -1
- package/dist/types/src/graph/testing/custom-function.d.ts.map +0 -1
- package/dist/types/src/graph/testing/index.d.ts +0 -2
- package/dist/types/src/graph/testing/index.d.ts.map +0 -1
- package/dist/types/src/graph/util.d.ts +0 -2
- package/dist/types/src/graph/util.d.ts.map +0 -1
- package/dist/types/src/hooks/hooks.stories.d.ts +0 -11
- 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/useComputeGraph.d.ts +0 -7
- package/dist/types/src/hooks/useComputeGraph.d.ts.map +0 -1
- package/dist/types/src/hooks/useFormattingModel.d.ts +0 -3
- package/dist/types/src/hooks/useFormattingModel.d.ts.map +0 -1
- package/dist/types/src/hooks/useSheetModel.d.ts +0 -8
- package/dist/types/src/hooks/useSheetModel.d.ts.map +0 -1
- package/dist/types/src/model/formatting-model.d.ts +0 -16
- package/dist/types/src/model/formatting-model.d.ts.map +0 -1
- package/dist/types/src/model/sheet-model.d.ts.map +0 -1
- package/dist/types/src/sanity.test.d.ts +0 -2
- package/dist/types/src/sanity.test.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -2
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/testing.d.ts +0 -8
- package/dist/types/src/testing/testing.d.ts.map +0 -1
- package/dist/vendor/hyperformula.mjs +0 -37145
- package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +0 -20
- package/src/components/GridSheet/GridSheet.stories.tsx +0 -36
- package/src/components/GridSheet/GridSheet.tsx +0 -153
- package/src/components/GridSheet/util.ts +0 -108
- package/src/components/Sheet/decorations.ts +0 -62
- package/src/components/Sheet/threads.tsx +0 -205
- package/src/defs/index.ts +0 -6
- package/src/defs/util.ts +0 -151
- package/src/extensions/compute.stories.tsx +0 -153
- package/src/extensions/compute.ts +0 -131
- package/src/extensions/index.ts +0 -5
- package/src/graph/compute-graph.stories.tsx +0 -93
- package/src/graph/compute-graph.test.ts +0 -127
- package/src/graph/compute-graph.ts +0 -313
- package/src/graph/compute-node.ts +0 -62
- package/src/graph/hyperformula.test.ts +0 -15
- package/src/graph/index.ts +0 -7
- package/src/graph/testing/index.ts +0 -5
- package/src/graph/util.ts +0 -8
- package/src/hooks/hooks.stories.tsx +0 -50
- package/src/hooks/index.ts +0 -7
- package/src/hooks/useComputeGraph.ts +0 -21
- package/src/hooks/useFormattingModel.ts +0 -11
- package/src/hooks/useSheetModel.ts +0 -40
- package/src/model/sheet-model.ts +0 -414
- package/src/sanity.test.ts +0 -40
- package/src/testing/index.ts +0 -5
- package/src/testing/testing.tsx +0 -68
- /package/dist/types/src/{graph → components/ComputeGraph}/edge-function.d.ts +0 -0
- /package/dist/types/src/{defs → model}/types.test.d.ts +0 -0
- /package/src/{graph/function-defs.ts → model/functions.ts} +0 -0
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { createContext, type PropsWithChildren } from 'react';
|
|
6
|
-
|
|
7
|
-
import { type ComputeGraphRegistry } from '../../graph';
|
|
8
|
-
|
|
9
|
-
export type ComputeGraphContextType = {
|
|
10
|
-
registry: ComputeGraphRegistry;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The compute graph context manages a ComputeGraph for each space.
|
|
15
|
-
*/
|
|
16
|
-
export const ComputeGraphContext = createContext<ComputeGraphContextType | undefined>(undefined);
|
|
17
|
-
|
|
18
|
-
export const ComputeGraphContextProvider = ({ registry, children }: PropsWithChildren<ComputeGraphContextType>) => {
|
|
19
|
-
return <ComputeGraphContext.Provider value={{ registry }}>{children}</ComputeGraphContext.Provider>;
|
|
20
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React from 'react';
|
|
6
|
-
|
|
7
|
-
import { useSpace } from '@dxos/react-client/echo';
|
|
8
|
-
import { withClientProvider } from '@dxos/react-client/testing';
|
|
9
|
-
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
10
|
-
|
|
11
|
-
import { GridSheet } from './GridSheet';
|
|
12
|
-
import { useComputeGraph } from '../../hooks';
|
|
13
|
-
import { useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
14
|
-
import { SheetType } from '../../types';
|
|
15
|
-
|
|
16
|
-
export default {
|
|
17
|
-
title: 'plugin-sheet/GridSheet',
|
|
18
|
-
component: GridSheet,
|
|
19
|
-
decorators: [
|
|
20
|
-
withClientProvider({ types: [SheetType], createSpace: true }),
|
|
21
|
-
withComputeGraphDecorator(),
|
|
22
|
-
withTheme,
|
|
23
|
-
withLayout({ fullscreen: true, tooltips: true }),
|
|
24
|
-
],
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const Basic = () => {
|
|
28
|
-
const space = useSpace();
|
|
29
|
-
const graph = useComputeGraph(space);
|
|
30
|
-
const sheet = useTestSheet(space, graph);
|
|
31
|
-
if (!sheet || !space) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return <GridSheet graph={graph} sheet={sheet} />;
|
|
36
|
-
};
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { useCallback, useMemo, useRef } from 'react';
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
type DxGridElement,
|
|
9
|
-
Grid,
|
|
10
|
-
type GridContentProps,
|
|
11
|
-
type GridScopedProps,
|
|
12
|
-
useGridContext,
|
|
13
|
-
} from '@dxos/react-ui-grid';
|
|
14
|
-
|
|
15
|
-
import { dxGridCellIndexToSheetCellAddress, useSheetModelDxGridProps } from './util';
|
|
16
|
-
import { rangeToA1Notation, type CellRange } from '../../defs';
|
|
17
|
-
import { type ComputeGraph } from '../../graph';
|
|
18
|
-
import { useFormattingModel, useSheetModel, type UseSheetModelOptions } from '../../hooks';
|
|
19
|
-
import { type SheetModel, type FormattingModel } from '../../model';
|
|
20
|
-
import { type SheetType } from '../../types';
|
|
21
|
-
import {
|
|
22
|
-
CellEditor,
|
|
23
|
-
type CellEditorProps,
|
|
24
|
-
type CellRangeNotifier,
|
|
25
|
-
editorKeys,
|
|
26
|
-
type EditorKeysProps,
|
|
27
|
-
rangeExtension,
|
|
28
|
-
sheetExtension,
|
|
29
|
-
} from '../CellEditor';
|
|
30
|
-
|
|
31
|
-
const GridSheetCellEditor = ({
|
|
32
|
-
model,
|
|
33
|
-
extension,
|
|
34
|
-
__gridScope,
|
|
35
|
-
}: GridScopedProps<Pick<CellEditorProps, 'extension'> & { model: SheetModel }>) => {
|
|
36
|
-
const { id, editing, setEditing, editBox } = useGridContext('GridSheetCellEditor', __gridScope);
|
|
37
|
-
const cell = dxGridCellIndexToSheetCellAddress(editing);
|
|
38
|
-
|
|
39
|
-
return editing ? (
|
|
40
|
-
<CellEditor
|
|
41
|
-
variant='grid'
|
|
42
|
-
value={editing.initialContent ?? (cell ? model.getCellText(cell) : undefined)}
|
|
43
|
-
autoFocus
|
|
44
|
-
box={editBox}
|
|
45
|
-
onBlur={() => setEditing(null)}
|
|
46
|
-
extension={extension}
|
|
47
|
-
gridId={id}
|
|
48
|
-
/>
|
|
49
|
-
) : null;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const sheetRowDefault = { size: 32, resizeable: true };
|
|
53
|
-
const sheetColDefault = { size: 180, resizeable: true };
|
|
54
|
-
|
|
55
|
-
const GridSheetImpl = ({
|
|
56
|
-
model,
|
|
57
|
-
formatting,
|
|
58
|
-
__gridScope,
|
|
59
|
-
}: GridScopedProps<{ model: SheetModel; formatting: FormattingModel }>) => {
|
|
60
|
-
const { editing, setEditing } = useGridContext('GridSheetCellEditor', __gridScope);
|
|
61
|
-
const dxGrid = useRef<DxGridElement | null>(null);
|
|
62
|
-
const rangeNotifier = useRef<CellRangeNotifier>();
|
|
63
|
-
|
|
64
|
-
// TODO(burdon): Validate formula before closing: hf.validateFormula();
|
|
65
|
-
const handleClose = useCallback<NonNullable<EditorKeysProps['onClose']> | NonNullable<EditorKeysProps['onNav']>>(
|
|
66
|
-
(value, { key, shift }) => {
|
|
67
|
-
if (value !== undefined) {
|
|
68
|
-
model.setValue(dxGridCellIndexToSheetCellAddress(editing)!, value);
|
|
69
|
-
}
|
|
70
|
-
setEditing(null);
|
|
71
|
-
const axis = ['Enter', 'ArrowUp', 'ArrowDown'].includes(key)
|
|
72
|
-
? 'row'
|
|
73
|
-
: ['Tab', 'ArrowLeft', 'ArrowRight'].includes(key)
|
|
74
|
-
? 'col'
|
|
75
|
-
: undefined;
|
|
76
|
-
const delta = key.startsWith('Arrow') ? (['ArrowUp', 'ArrowLeft'].includes(key) ? -1 : 1) : shift ? -1 : 1;
|
|
77
|
-
dxGrid.current?.refocus(axis, delta);
|
|
78
|
-
},
|
|
79
|
-
[model, editing, setEditing],
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
const handleAxisResize = useCallback<NonNullable<GridContentProps['onAxisResize']>>(
|
|
83
|
-
({ axis, size, index: numericIndex }) => {
|
|
84
|
-
if (axis === 'row') {
|
|
85
|
-
const rowId = model.sheet.rows[parseInt(numericIndex)];
|
|
86
|
-
model.sheet.rowMeta[rowId] ??= {};
|
|
87
|
-
model.sheet.rowMeta[rowId].size = size;
|
|
88
|
-
} else {
|
|
89
|
-
const columnId = model.sheet.columns[parseInt(numericIndex)];
|
|
90
|
-
model.sheet.columnMeta[columnId] ??= {};
|
|
91
|
-
model.sheet.columnMeta[columnId].size = size;
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
[model],
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const handleSelect = useCallback<NonNullable<GridContentProps['onSelect']>>(
|
|
98
|
-
({ minCol, maxCol, minRow, maxRow }) => {
|
|
99
|
-
if (editing) {
|
|
100
|
-
const range: CellRange = { from: { col: minCol, row: minRow } };
|
|
101
|
-
if (minCol !== maxCol || minRow !== maxRow) {
|
|
102
|
-
range.to = { col: maxCol, row: maxRow };
|
|
103
|
-
}
|
|
104
|
-
// Update range selection in formula.
|
|
105
|
-
rangeNotifier.current?.(rangeToA1Notation(range));
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
[editing],
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
const { columns, rows } = useSheetModelDxGridProps(dxGrid, model, formatting);
|
|
112
|
-
|
|
113
|
-
const extension = useMemo(
|
|
114
|
-
() => [
|
|
115
|
-
editorKeys({ onClose: handleClose, ...(editing?.initialContent && { onNav: handleClose }) }),
|
|
116
|
-
sheetExtension({ functions: model.graph.getFunctions() }),
|
|
117
|
-
rangeExtension((fn) => (rangeNotifier.current = fn)),
|
|
118
|
-
],
|
|
119
|
-
[model, handleClose, editing],
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<>
|
|
124
|
-
<GridSheetCellEditor model={model} extension={extension} />
|
|
125
|
-
<Grid.Content
|
|
126
|
-
initialCells={{}}
|
|
127
|
-
columns={columns}
|
|
128
|
-
rows={rows}
|
|
129
|
-
onAxisResize={handleAxisResize}
|
|
130
|
-
onSelect={handleSelect}
|
|
131
|
-
rowDefault={sheetRowDefault}
|
|
132
|
-
columnDefault={sheetColDefault}
|
|
133
|
-
ref={dxGrid}
|
|
134
|
-
/>
|
|
135
|
-
</>
|
|
136
|
-
);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export type GridSheetProps = { graph?: ComputeGraph; sheet?: SheetType } & UseSheetModelOptions;
|
|
140
|
-
|
|
141
|
-
export const GridSheet = ({ graph, sheet, ...options }: GridSheetProps) => {
|
|
142
|
-
const model = useSheetModel(graph, sheet, options);
|
|
143
|
-
const formatting = useFormattingModel(model);
|
|
144
|
-
if (!model || !formatting) {
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return (
|
|
149
|
-
<Grid.Root id={model.id}>
|
|
150
|
-
<GridSheetImpl model={model} formatting={formatting} />
|
|
151
|
-
</Grid.Root>
|
|
152
|
-
);
|
|
153
|
-
};
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type MutableRefObject, useEffect, useLayoutEffect, useState } from 'react';
|
|
6
|
-
|
|
7
|
-
import { createDocAccessor } from '@dxos/react-client/echo';
|
|
8
|
-
import {
|
|
9
|
-
type GridEditing,
|
|
10
|
-
type GridContentProps,
|
|
11
|
-
type DxGridElement,
|
|
12
|
-
type DxGridCells,
|
|
13
|
-
type DxGridAxisMeta,
|
|
14
|
-
type DxGridRange,
|
|
15
|
-
} from '@dxos/react-ui-grid';
|
|
16
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
17
|
-
|
|
18
|
-
import { type CellAddress } from '../../defs';
|
|
19
|
-
import { type SheetModel, type FormattingModel } from '../../model';
|
|
20
|
-
|
|
21
|
-
export const dxGridCellIndexToSheetCellAddress = (gridEditing: GridEditing): CellAddress | null => {
|
|
22
|
-
if (!gridEditing) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
const [colStr, rowStr] = gridEditing.index.split(',');
|
|
26
|
-
return {
|
|
27
|
-
col: parseInt(colStr),
|
|
28
|
-
row: parseInt(rowStr),
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const createDxGridColumns = (model: SheetModel): DxGridAxisMeta => {
|
|
33
|
-
return model.sheet.columns.reduce((acc: DxGridAxisMeta, columnId, numericIndex) => {
|
|
34
|
-
if (model.sheet.columnMeta[columnId] && model.sheet.columnMeta[columnId].size) {
|
|
35
|
-
acc[numericIndex] = { size: model.sheet.columnMeta[columnId].size, resizeable: true };
|
|
36
|
-
}
|
|
37
|
-
return acc;
|
|
38
|
-
}, {});
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const createDxGridRows = (model: SheetModel): DxGridAxisMeta => {
|
|
42
|
-
return model.sheet.rows.reduce((acc: DxGridAxisMeta, rowId, numericIndex) => {
|
|
43
|
-
if (model.sheet.rowMeta[rowId] && model.sheet.rowMeta[rowId].size) {
|
|
44
|
-
acc[numericIndex] = { size: model.sheet.rowMeta[rowId].size, resizeable: true };
|
|
45
|
-
}
|
|
46
|
-
return acc;
|
|
47
|
-
}, {});
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const cellGetter = (model: SheetModel, formatting: FormattingModel) => {
|
|
51
|
-
// TODO(thure): Actually use the cache.
|
|
52
|
-
let _cachedBounds: DxGridRange | null = null;
|
|
53
|
-
const cachedCells: DxGridCells = {};
|
|
54
|
-
return (nextBounds: DxGridRange): DxGridCells => {
|
|
55
|
-
[...Array(nextBounds.end.col - nextBounds.start.col)].forEach((_, c0) => {
|
|
56
|
-
return [...Array(nextBounds.end.row - nextBounds.start.row)].forEach((_, r0) => {
|
|
57
|
-
const col = nextBounds.start.col + c0;
|
|
58
|
-
const row = nextBounds.start.row + r0;
|
|
59
|
-
const cell = formatting.getFormatting({ col, row });
|
|
60
|
-
if (cell.value) {
|
|
61
|
-
cachedCells[`${col},${row}`] = { value: cell.value, className: mx(cell.classNames) };
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
_cachedBounds = nextBounds;
|
|
66
|
-
return cachedCells;
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export const useSheetModelDxGridProps = (
|
|
71
|
-
dxGridRef: MutableRefObject<DxGridElement | null>,
|
|
72
|
-
model: SheetModel,
|
|
73
|
-
formatting: FormattingModel,
|
|
74
|
-
): Pick<GridContentProps, 'columns' | 'rows'> => {
|
|
75
|
-
const [columns, setColumns] = useState<DxGridAxisMeta>(createDxGridColumns(model));
|
|
76
|
-
const [rows, setRows] = useState<DxGridAxisMeta>(createDxGridColumns(model));
|
|
77
|
-
|
|
78
|
-
useLayoutEffect(() => {
|
|
79
|
-
const cellsAccessor = createDocAccessor(model.sheet, ['cells']);
|
|
80
|
-
if (dxGridRef.current) {
|
|
81
|
-
dxGridRef.current.getCells = cellGetter(model, formatting);
|
|
82
|
-
}
|
|
83
|
-
const handleCellsUpdate = () => {
|
|
84
|
-
dxGridRef.current?.requestUpdate('initialCells');
|
|
85
|
-
};
|
|
86
|
-
cellsAccessor.handle.addListener('change', handleCellsUpdate);
|
|
87
|
-
return () => cellsAccessor.handle.removeListener('change', handleCellsUpdate);
|
|
88
|
-
}, [model, formatting]);
|
|
89
|
-
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
const columnMetaAccessor = createDocAccessor(model.sheet, ['columnMeta']);
|
|
92
|
-
const rowMetaAccessor = createDocAccessor(model.sheet, ['rowMeta']);
|
|
93
|
-
const handleColumnMetaUpdate = () => {
|
|
94
|
-
setColumns(createDxGridColumns(model));
|
|
95
|
-
};
|
|
96
|
-
const handleRowMetaUpdate = () => {
|
|
97
|
-
setRows(createDxGridRows(model));
|
|
98
|
-
};
|
|
99
|
-
columnMetaAccessor.handle.addListener('change', handleColumnMetaUpdate);
|
|
100
|
-
rowMetaAccessor.handle.addListener('change', handleRowMetaUpdate);
|
|
101
|
-
return () => {
|
|
102
|
-
columnMetaAccessor.handle.removeListener('change', handleColumnMetaUpdate);
|
|
103
|
-
rowMetaAccessor.handle.removeListener('change', handleRowMetaUpdate);
|
|
104
|
-
};
|
|
105
|
-
}, [model]);
|
|
106
|
-
|
|
107
|
-
return { columns, rows };
|
|
108
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { effect } from '@preact/signals-core';
|
|
6
|
-
import React, { type PropsWithChildren, useCallback, useEffect, useMemo } from 'react';
|
|
7
|
-
|
|
8
|
-
import { type IntentResolver, LayoutAction, useIntentDispatcher, useIntentResolver } from '@dxos/app-framework';
|
|
9
|
-
import { debounce } from '@dxos/async';
|
|
10
|
-
import { fullyQualifiedId } from '@dxos/react-client/echo';
|
|
11
|
-
import { Icon, useTranslation } from '@dxos/react-ui';
|
|
12
|
-
|
|
13
|
-
import { type Decoration } from './decorations';
|
|
14
|
-
import { useSheetContext } from './sheet-context';
|
|
15
|
-
import { addressFromIndex, addressToIndex, type CellAddress, closest } from '../../defs';
|
|
16
|
-
import { SHEET_PLUGIN } from '../../meta';
|
|
17
|
-
|
|
18
|
-
// TODO(burdon): Move into folder; split hooks.
|
|
19
|
-
|
|
20
|
-
const CommentIndicator = () => {
|
|
21
|
-
return (
|
|
22
|
-
<div
|
|
23
|
-
role='none'
|
|
24
|
-
className='absolute top-0 right-0 w-0 h-0 border-t-8 border-l-8 border-t-cmCommentSurface border-l-transparent'
|
|
25
|
-
/>
|
|
26
|
-
);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const ThreadedCellWrapper = ({ children }: PropsWithChildren) => {
|
|
30
|
-
const dispatch = useIntentDispatcher();
|
|
31
|
-
const [isHovered, setIsHovered] = React.useState(false);
|
|
32
|
-
const { t } = useTranslation(SHEET_PLUGIN);
|
|
33
|
-
|
|
34
|
-
const handleClick = React.useCallback(
|
|
35
|
-
(_event: React.MouseEvent) => {
|
|
36
|
-
void dispatch({ action: LayoutAction.SET_LAYOUT, data: { element: 'complementary', state: true } });
|
|
37
|
-
},
|
|
38
|
-
[dispatch],
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<div
|
|
43
|
-
role='none'
|
|
44
|
-
className='relative h-full is-full'
|
|
45
|
-
onMouseEnter={() => {
|
|
46
|
-
setIsHovered(true);
|
|
47
|
-
}}
|
|
48
|
-
onMouseLeave={() => {
|
|
49
|
-
setIsHovered(false);
|
|
50
|
-
}}
|
|
51
|
-
>
|
|
52
|
-
<CommentIndicator />
|
|
53
|
-
{isHovered && (
|
|
54
|
-
<div className='absolute inset-0 flex items-center justify-end pr-1'>
|
|
55
|
-
<button
|
|
56
|
-
className='ch-button text-xs min-bs-0 p-1'
|
|
57
|
-
onClick={handleClick}
|
|
58
|
-
aria-label={t('open comment for sheet cell')}
|
|
59
|
-
>
|
|
60
|
-
<Icon icon='ph--chat--regular' aria-hidden={true} />
|
|
61
|
-
</button>
|
|
62
|
-
</div>
|
|
63
|
-
)}
|
|
64
|
-
{children}
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const createThreadDecoration = (cellIndex: string, threadId: string, sheetId: string): Decoration => {
|
|
70
|
-
return {
|
|
71
|
-
type: 'comment',
|
|
72
|
-
cellIndex,
|
|
73
|
-
decorate: (props) => <ThreadedCellWrapper {...props} />,
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// TODO(burdon): Factor out hooks.
|
|
78
|
-
|
|
79
|
-
const useUpdateCursorOnThreadSelection = () => {
|
|
80
|
-
const { setCursor, model } = useSheetContext();
|
|
81
|
-
|
|
82
|
-
const handleScrollIntoView: IntentResolver = useCallback(
|
|
83
|
-
({ action, data }) => {
|
|
84
|
-
switch (action) {
|
|
85
|
-
case LayoutAction.SCROLL_INTO_VIEW: {
|
|
86
|
-
if (!data?.id || data?.cursor === undefined || data?.id !== fullyQualifiedId(model.sheet)) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// TODO(Zan): Everywhere we refer to the cursor in a thread context should change to `anchor`.
|
|
91
|
-
const cellAddress = addressFromIndex(model.sheet, data.cursor);
|
|
92
|
-
setCursor(cellAddress);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
[model.sheet, setCursor],
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
useIntentResolver(SHEET_PLUGIN, handleScrollIntoView);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const useSelectThreadOnCursorChange = () => {
|
|
103
|
-
const { cursor, model } = useSheetContext();
|
|
104
|
-
const dispatch = useIntentDispatcher();
|
|
105
|
-
|
|
106
|
-
const activeThreads = useMemo(
|
|
107
|
-
() =>
|
|
108
|
-
model.sheet.threads?.filter(
|
|
109
|
-
(thread): thread is NonNullable<typeof thread> => !!thread && thread.status === 'active',
|
|
110
|
-
) ?? [],
|
|
111
|
-
[JSON.stringify(model.sheet.threads)],
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const activeThreadAddresses = useMemo(
|
|
115
|
-
() =>
|
|
116
|
-
activeThreads
|
|
117
|
-
.map((thread) => thread.anchor)
|
|
118
|
-
.filter((anchor): anchor is NonNullable<typeof anchor> => anchor !== undefined)
|
|
119
|
-
.map((anchor) => addressFromIndex(model.sheet, anchor)),
|
|
120
|
-
[activeThreads, model.sheet],
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
const selectClosestThread = useCallback(
|
|
124
|
-
(cellAddress: CellAddress) => {
|
|
125
|
-
if (!cellAddress || !activeThreads) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const closestThreadAnchor = closest(cellAddress, activeThreadAddresses);
|
|
130
|
-
if (closestThreadAnchor) {
|
|
131
|
-
const closestThread = activeThreads.find(
|
|
132
|
-
(thread) => thread && thread.anchor === addressToIndex(model.sheet, closestThreadAnchor),
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
if (closestThread) {
|
|
136
|
-
void dispatch([
|
|
137
|
-
{ action: 'dxos.org/plugin/thread/action/select', data: { current: fullyQualifiedId(closestThread) } },
|
|
138
|
-
]);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
[dispatch, activeThreads, activeThreadAddresses, model.sheet],
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
const debounced = useMemo(() => {
|
|
146
|
-
return debounce((cursor: CellAddress) => requestAnimationFrame(() => selectClosestThread(cursor)), 50);
|
|
147
|
-
}, [selectClosestThread]);
|
|
148
|
-
|
|
149
|
-
useEffect(() => {
|
|
150
|
-
if (!cursor) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
debounced(cursor);
|
|
154
|
-
}, [cursor, selectClosestThread]);
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const useThreadDecorations = () => {
|
|
158
|
-
const { decorations, model } = useSheetContext();
|
|
159
|
-
const sheet = useMemo(() => model.sheet, [model.sheet]);
|
|
160
|
-
const sheetId = useMemo(() => fullyQualifiedId(sheet), [sheet]);
|
|
161
|
-
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
const unsubscribe = effect(() => {
|
|
164
|
-
const activeThreadAnchors = new Set<string>();
|
|
165
|
-
if (!sheet.threads) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Process active threads
|
|
170
|
-
for (const thread of sheet.threads) {
|
|
171
|
-
if (!thread || thread.anchor === undefined || thread.status === 'resolved') {
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
activeThreadAnchors.add(thread.anchor);
|
|
176
|
-
const index = thread.anchor;
|
|
177
|
-
|
|
178
|
-
// Add decoration only if it doesn't already exist
|
|
179
|
-
const existingDecorations = decorations.getDecorationsForCell(index);
|
|
180
|
-
if (!existingDecorations || !existingDecorations.some((d) => d.type === 'comment')) {
|
|
181
|
-
decorations.addDecoration(index, createThreadDecoration(index, thread.id, sheetId));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Remove decorations for resolved or deleted threads
|
|
186
|
-
for (const decoration of decorations.getAllDecorations()) {
|
|
187
|
-
if (decoration.type !== 'comment') {
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (!activeThreadAnchors.has(decoration.cellIndex)) {
|
|
192
|
-
decorations.removeDecoration(decoration.cellIndex, 'comment');
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
return () => unsubscribe();
|
|
198
|
-
});
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export const useThreads = () => {
|
|
202
|
-
useUpdateCursorOnThreadSelection();
|
|
203
|
-
useSelectThreadOnCursorChange();
|
|
204
|
-
useThreadDecorations();
|
|
205
|
-
};
|