@dxos/plugin-sheet 0.7.5-main.9d26e3a → 0.7.5-main.b19bfc8
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-IMHGS7Z4.mjs +370 -0
- package/dist/lib/browser/SheetContainer-IMHGS7Z4.mjs.map +7 -0
- package/dist/lib/browser/{chunk-A374JPWV.mjs → chunk-AT7F2WDW.mjs} +157 -391
- package/dist/lib/browser/chunk-AT7F2WDW.mjs.map +7 -0
- package/dist/lib/browser/chunk-FOO6NGBM.mjs +229 -0
- package/dist/lib/browser/chunk-FOO6NGBM.mjs.map +7 -0
- package/dist/lib/browser/chunk-GAFHJBCU.mjs +18 -0
- package/dist/lib/browser/chunk-GAFHJBCU.mjs.map +7 -0
- package/dist/lib/browser/chunk-LXHRT3CC.mjs +15 -0
- package/dist/lib/browser/chunk-LXHRT3CC.mjs.map +7 -0
- package/dist/lib/browser/{chunk-Q4XS4YWF.mjs → chunk-OOSRC36N.mjs} +2 -2
- package/dist/lib/browser/chunk-OOSRC36N.mjs.map +7 -0
- package/dist/lib/browser/compute-graph-registry-EGPD4HEX.mjs +27 -0
- package/dist/lib/browser/compute-graph-registry-EGPD4HEX.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +88 -218
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-resolver-6S2RMLQF.mjs +56 -0
- package/dist/lib/browser/intent-resolver-6S2RMLQF.mjs.map +7 -0
- package/dist/lib/browser/markdown-CFJIWHZX.mjs +26 -0
- package/dist/lib/browser/markdown-CFJIWHZX.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-surface-PHKJZYFB.mjs +52 -0
- package/dist/lib/browser/react-surface-PHKJZYFB.mjs.map +7 -0
- package/dist/lib/browser/thread-7ZWW5EA7.mjs +17 -0
- package/dist/lib/browser/thread-7ZWW5EA7.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -2
- package/dist/lib/node/SheetContainer-NNIZN4AK.cjs +364 -0
- package/dist/lib/node/SheetContainer-NNIZN4AK.cjs.map +7 -0
- package/dist/lib/node/{chunk-FDEQ2PGJ.cjs → chunk-2KCZUH72.cjs} +198 -428
- package/dist/lib/node/chunk-2KCZUH72.cjs.map +7 -0
- package/dist/lib/node/{chunk-TQOJ7DG2.cjs → chunk-4LSYTNS4.cjs} +6 -6
- package/dist/lib/node/chunk-4LSYTNS4.cjs.map +7 -0
- package/dist/lib/node/{chunk-2ZVZI2KJ.cjs → chunk-MLU6KRQN.cjs} +12 -9
- package/dist/lib/node/chunk-MLU6KRQN.cjs.map +7 -0
- package/dist/lib/node/chunk-P4KSGZSS.cjs +251 -0
- package/dist/lib/node/chunk-P4KSGZSS.cjs.map +7 -0
- package/dist/lib/node/{meta.cjs → chunk-ZV2RS3QH.cjs} +12 -8
- package/dist/lib/node/chunk-ZV2RS3QH.cjs.map +7 -0
- package/dist/lib/node/compute-graph-registry-GJK5H264.cjs +53 -0
- package/dist/lib/node/compute-graph-registry-GJK5H264.cjs.map +7 -0
- package/dist/lib/node/index.cjs +89 -215
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/intent-resolver-I25V7SBT.cjs +69 -0
- package/dist/lib/node/intent-resolver-I25V7SBT.cjs.map +7 -0
- package/dist/lib/node/markdown-YTCSW66K.cjs +40 -0
- package/dist/lib/node/markdown-YTCSW66K.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/react-surface-HLE6CRA6.cjs +70 -0
- package/dist/lib/node/react-surface-HLE6CRA6.cjs.map +7 -0
- package/dist/lib/node/thread-DRNYTR6M.cjs +32 -0
- package/dist/lib/node/thread-DRNYTR6M.cjs.map +7 -0
- package/dist/lib/node/types/index.cjs +30 -30
- package/dist/lib/node/types/index.cjs.map +1 -1
- package/dist/lib/node-esm/SheetContainer-PGDJKGTZ.mjs +371 -0
- package/dist/lib/node-esm/SheetContainer-PGDJKGTZ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-NYYIDVR7.mjs → chunk-HPAMZ6SP.mjs} +2 -2
- package/dist/lib/node-esm/chunk-HPAMZ6SP.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-PTOI45NK.mjs +231 -0
- package/dist/lib/node-esm/chunk-PTOI45NK.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-RTZXXOS2.mjs +20 -0
- package/dist/lib/node-esm/chunk-RTZXXOS2.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-SX3S7UKU.mjs +16 -0
- package/dist/lib/node-esm/chunk-SX3S7UKU.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-L5PQHVTX.mjs → chunk-ZM7XLUGL.mjs} +157 -391
- package/dist/lib/node-esm/chunk-ZM7XLUGL.mjs.map +7 -0
- package/dist/lib/node-esm/compute-graph-registry-3F5JCYEN.mjs +28 -0
- package/dist/lib/node-esm/compute-graph-registry-3F5JCYEN.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +88 -218
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/intent-resolver-IPRSINII.mjs +57 -0
- package/dist/lib/node-esm/intent-resolver-IPRSINII.mjs.map +7 -0
- package/dist/lib/node-esm/markdown-CGSK44XJ.mjs +27 -0
- package/dist/lib/node-esm/markdown-CGSK44XJ.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/react-surface-PFRJ7V5N.mjs +53 -0
- package/dist/lib/node-esm/react-surface-PFRJ7V5N.mjs.map +7 -0
- package/dist/lib/node-esm/thread-6T5VXPAF.mjs +18 -0
- package/dist/lib/node-esm/thread-6T5VXPAF.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +2 -2
- package/dist/types/src/SheetPlugin.d.ts +1 -3
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +5 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/compute-graph-registry.d.ts +4 -0
- package/dist/types/src/capabilities/compute-graph-registry.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +12 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/markdown.d.ts +6 -0
- package/dist/types/src/capabilities/markdown.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/thread.d.ts +6 -0
- package/dist/types/src/capabilities/thread.d.ts.map +1 -0
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +1 -1
- package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +1 -1
- package/dist/types/src/components/FunctionEditor/FunctionEditor.d.ts +1 -2
- package/dist/types/src/components/FunctionEditor/FunctionEditor.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.d.ts +1 -2
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +1 -2
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/SheetCellEditor.stories.d.ts +1 -2
- package/dist/types/src/components/GridSheet/SheetCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/RangeList/RangeList.d.ts +1 -2
- package/dist/types/src/components/RangeList/RangeList.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.d.ts +1 -2
- package/dist/types/src/components/SheetContainer/SheetContainer.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts +2 -3
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/SheetContext/SheetContext.d.ts +2 -2
- package/dist/types/src/components/SheetContext/SheetContext.d.ts.map +1 -1
- package/dist/types/src/components/SheetToolbar/SheetToolbar.d.ts +7 -0
- package/dist/types/src/components/SheetToolbar/SheetToolbar.d.ts.map +1 -0
- package/dist/types/src/components/SheetToolbar/SheetToolbar.stories.d.ts +6 -0
- package/dist/types/src/components/SheetToolbar/SheetToolbar.stories.d.ts.map +1 -0
- package/dist/types/src/components/SheetToolbar/align.d.ts +28 -0
- package/dist/types/src/components/SheetToolbar/align.d.ts.map +1 -0
- package/dist/types/src/components/SheetToolbar/comment.d.ts +23 -0
- package/dist/types/src/components/SheetToolbar/comment.d.ts.map +1 -0
- package/dist/types/src/components/SheetToolbar/index.d.ts +2 -0
- package/dist/types/src/components/SheetToolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/SheetToolbar/style.d.ts +26 -0
- package/dist/types/src/components/SheetToolbar/style.d.ts.map +1 -0
- package/dist/types/src/components/SheetToolbar/useToolbarAction.d.ts +8 -0
- package/dist/types/src/components/SheetToolbar/useToolbarAction.d.ts.map +1 -0
- package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts +6 -0
- package/dist/types/src/components/SheetToolbar/useToolbarState.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +3 -4
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/compute.stories.d.ts +2 -3
- package/dist/types/src/extensions/compute.stories.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/integrations/thread-ranges.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/testing/testing.d.ts +1 -1
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +14 -14
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/types/sheet-range-types.d.ts +1 -1
- package/dist/types/src/types/sheet-range-types.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +0 -11
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +46 -52
- package/src/SheetPlugin.tsx +68 -105
- package/src/capabilities/capabilities.ts +14 -0
- package/src/capabilities/compute-graph-registry.ts +25 -0
- package/src/capabilities/index.ts +13 -0
- package/src/capabilities/intent-resolver.ts +38 -0
- package/src/capabilities/markdown.ts +22 -0
- package/src/capabilities/react-surface.tsx +37 -0
- package/src/capabilities/thread.ts +14 -0
- package/src/components/GridSheet/GridSheet.stories.tsx +2 -0
- package/src/components/GridSheet/util.ts +1 -1
- package/src/components/SheetContainer/SheetContainer.stories.tsx +28 -22
- package/src/components/SheetContainer/SheetContainer.tsx +3 -8
- package/src/components/{Toolbar/Toolbar.stories.tsx → SheetToolbar/SheetToolbar.stories.tsx} +4 -8
- package/src/components/SheetToolbar/SheetToolbar.tsx +48 -0
- package/src/components/SheetToolbar/align.ts +68 -0
- package/src/components/SheetToolbar/comment.ts +56 -0
- package/src/components/{Toolbar → SheetToolbar}/index.ts +1 -1
- package/src/components/SheetToolbar/style.ts +72 -0
- package/src/components/SheetToolbar/useToolbarAction.ts +87 -0
- package/src/components/SheetToolbar/useToolbarState.ts +17 -0
- package/src/components/index.ts +0 -1
- package/src/extensions/compute.stories.tsx +2 -2
- package/src/index.ts +2 -5
- package/src/integrations/thread-ranges.ts +21 -10
- package/src/meta.ts +4 -2
- package/src/types/sheet-range-types.ts +1 -1
- package/src/types/types.ts +0 -26
- package/dist/lib/browser/SheetContainer-S4NCLUYL.mjs +0 -290
- package/dist/lib/browser/SheetContainer-S4NCLUYL.mjs.map +0 -7
- package/dist/lib/browser/chunk-A374JPWV.mjs.map +0 -7
- package/dist/lib/browser/chunk-Q4XS4YWF.mjs.map +0 -7
- package/dist/lib/browser/chunk-RABELMEQ.mjs +0 -15
- package/dist/lib/browser/chunk-RABELMEQ.mjs.map +0 -7
- package/dist/lib/browser/meta.mjs +0 -9
- package/dist/lib/browser/meta.mjs.map +0 -7
- package/dist/lib/node/SheetContainer-TP4GYXZB.cjs +0 -296
- package/dist/lib/node/SheetContainer-TP4GYXZB.cjs.map +0 -7
- package/dist/lib/node/chunk-2ZVZI2KJ.cjs.map +0 -7
- package/dist/lib/node/chunk-FDEQ2PGJ.cjs.map +0 -7
- package/dist/lib/node/chunk-TQOJ7DG2.cjs.map +0 -7
- package/dist/lib/node/meta.cjs.map +0 -7
- package/dist/lib/node-esm/SheetContainer-YB3JBVPZ.mjs +0 -291
- package/dist/lib/node-esm/SheetContainer-YB3JBVPZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-BM2Q3FFC.mjs +0 -17
- package/dist/lib/node-esm/chunk-BM2Q3FFC.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-L5PQHVTX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NYYIDVR7.mjs.map +0 -7
- package/dist/lib/node-esm/meta.mjs +0 -10
- package/dist/lib/node-esm/meta.mjs.map +0 -7
- package/dist/types/src/components/SheetObjectSettings.d.ts +0 -7
- package/dist/types/src/components/SheetObjectSettings.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -48
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +0 -7
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/index.d.ts +0 -2
- package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
- package/dist/types/src/testing/playwright/playwright.config.d.ts +0 -3
- package/dist/types/src/testing/playwright/playwright.config.d.ts.map +0 -1
- package/src/components/SheetObjectSettings.tsx +0 -38
- package/src/components/Toolbar/Toolbar.tsx +0 -344
- /package/src/testing/playwright/{playwright.config.ts → playwright.config.cts} +0 -0
package/src/components/{Toolbar/Toolbar.stories.tsx → SheetToolbar/SheetToolbar.stories.tsx}
RENAMED
|
@@ -10,22 +10,18 @@ import React from 'react';
|
|
|
10
10
|
import { textBlockWidth } from '@dxos/react-ui-theme';
|
|
11
11
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { SheetToolbar } from './SheetToolbar';
|
|
14
14
|
import translations from '../../translations';
|
|
15
15
|
|
|
16
16
|
const DefaultStory = () => {
|
|
17
|
-
return
|
|
18
|
-
<Toolbar.Root classNames={textBlockWidth}>
|
|
19
|
-
<Toolbar.Alignment />
|
|
20
|
-
</Toolbar.Root>
|
|
21
|
-
);
|
|
17
|
+
return <SheetToolbar classNames={textBlockWidth} />;
|
|
22
18
|
};
|
|
23
19
|
|
|
24
20
|
export const Default = {};
|
|
25
21
|
|
|
26
|
-
const meta: Meta
|
|
22
|
+
const meta: Meta = {
|
|
27
23
|
title: 'plugins/plugin-sheet/Toolbar',
|
|
28
|
-
component:
|
|
24
|
+
component: SheetToolbar,
|
|
29
25
|
render: DefaultStory,
|
|
30
26
|
decorators: [withTheme, withLayout({ tooltips: true })],
|
|
31
27
|
parameters: { translations, layout: 'fullscreen' },
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { type PropsWithChildren, useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
8
|
+
import { createGapSeparator, MenuProvider, ToolbarMenu, useMenuActions } from '@dxos/react-ui-menu';
|
|
9
|
+
|
|
10
|
+
import { createAlign, useAlignState } from './align';
|
|
11
|
+
import { createComment, useCommentState } from './comment';
|
|
12
|
+
import { createStyle, useStyleState } from './style';
|
|
13
|
+
import { useToolbarAction } from './useToolbarAction';
|
|
14
|
+
import { type ToolbarState, useToolbarState } from './useToolbarState';
|
|
15
|
+
|
|
16
|
+
//
|
|
17
|
+
// Root
|
|
18
|
+
//
|
|
19
|
+
|
|
20
|
+
export type SheetToolbarProps = ThemedClassName<PropsWithChildren<{ attendableId?: string }>>;
|
|
21
|
+
|
|
22
|
+
const createToolbarActions = (state: ToolbarState) => {
|
|
23
|
+
const align = createAlign(state);
|
|
24
|
+
const style = createStyle(state);
|
|
25
|
+
const gap = createGapSeparator();
|
|
26
|
+
const comment = createComment(state);
|
|
27
|
+
return {
|
|
28
|
+
nodes: [...align.nodes, ...style.nodes, ...gap.nodes, ...comment.nodes],
|
|
29
|
+
edges: [...align.edges, ...style.edges, ...gap.edges, ...comment.edges],
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const SheetToolbar = ({ attendableId, classNames }: SheetToolbarProps) => {
|
|
34
|
+
const state = useToolbarState({});
|
|
35
|
+
useAlignState(state);
|
|
36
|
+
useStyleState(state);
|
|
37
|
+
useCommentState(state);
|
|
38
|
+
|
|
39
|
+
const actionsCreator = useCallback(() => createToolbarActions(state), [state]);
|
|
40
|
+
const menu = useMenuActions(actionsCreator);
|
|
41
|
+
const handleAction = useToolbarAction(state);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<MenuProvider {...menu} attendableId={attendableId} onAction={handleAction}>
|
|
45
|
+
<ToolbarMenu classNames={classNames} />
|
|
46
|
+
</MenuProvider>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
|
+
|
|
7
|
+
import { inRange } from '@dxos/compute';
|
|
8
|
+
import { createMenuAction, createMenuItemGroup, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
|
9
|
+
|
|
10
|
+
import { SHEET_PLUGIN } from '../../meta';
|
|
11
|
+
import { type AlignKey, alignKey, type AlignValue, rangeFromIndex } from '../../types';
|
|
12
|
+
import { useSheetContext } from '../SheetContext';
|
|
13
|
+
|
|
14
|
+
export type AlignAction = { key: AlignKey; value: AlignValue };
|
|
15
|
+
|
|
16
|
+
export type AlignState = { [alignKey]: AlignValue | undefined };
|
|
17
|
+
|
|
18
|
+
const aligns: Record<AlignValue, string> = {
|
|
19
|
+
start: 'ph--text-align-left--regular',
|
|
20
|
+
center: 'ph--text-align-center--regular',
|
|
21
|
+
end: 'ph--text-align-right--regular',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const useAlignState = (state: Partial<AlignState>) => {
|
|
25
|
+
const { cursor, model } = useSheetContext();
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
// TODO(thure): Can this O(n) call be memoized?
|
|
28
|
+
state[alignKey] = (
|
|
29
|
+
cursor
|
|
30
|
+
? model.sheet.ranges?.findLast(
|
|
31
|
+
({ range, key }) => key === alignKey && inRange(rangeFromIndex(model.sheet, range), cursor),
|
|
32
|
+
)?.value
|
|
33
|
+
: undefined
|
|
34
|
+
) as AlignValue | undefined;
|
|
35
|
+
}, [cursor, model.sheet]);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const createAlignGroupAction = (value?: AlignValue) =>
|
|
39
|
+
createMenuItemGroup('align', {
|
|
40
|
+
label: ['align label', { ns: SHEET_PLUGIN }],
|
|
41
|
+
variant: 'toggleGroup',
|
|
42
|
+
selectCardinality: 'single',
|
|
43
|
+
value: `${alignKey}--${value}`,
|
|
44
|
+
} as ToolbarMenuActionGroupProperties);
|
|
45
|
+
|
|
46
|
+
const createAlignActions = (value?: AlignValue) =>
|
|
47
|
+
Object.entries(aligns).map(([alignValue, icon]) => {
|
|
48
|
+
return createMenuAction<AlignAction>(`${alignKey}--${alignValue}`, {
|
|
49
|
+
key: alignKey,
|
|
50
|
+
value: alignValue as AlignValue,
|
|
51
|
+
checked: value === alignValue,
|
|
52
|
+
label: [`range value ${alignValue} label`, { ns: SHEET_PLUGIN }],
|
|
53
|
+
icon,
|
|
54
|
+
testId: `grid.toolbar.${alignKey}.${alignValue}`,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export const createAlign = ({ [alignKey]: alignValue }: Partial<AlignState>) => {
|
|
59
|
+
const alignGroup = createAlignGroupAction(alignValue);
|
|
60
|
+
const alignActions = createAlignActions(alignValue);
|
|
61
|
+
return {
|
|
62
|
+
nodes: [alignGroup, ...alignActions],
|
|
63
|
+
edges: [
|
|
64
|
+
{ source: 'root', target: 'align' },
|
|
65
|
+
...alignActions.map(({ id }) => ({ source: alignGroup.id, target: id })),
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useEffect, useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { RefArray } from '@dxos/live-object';
|
|
8
|
+
import { createMenuAction } from '@dxos/react-ui-menu';
|
|
9
|
+
|
|
10
|
+
import { SHEET_PLUGIN } from '../../meta';
|
|
11
|
+
import { commentKey, type CommentKey, type CommentValue, rangeToIndex } from '../../types';
|
|
12
|
+
import { useSheetContext } from '../SheetContext';
|
|
13
|
+
|
|
14
|
+
export type CommentAction = { key: CommentKey; value: CommentValue; cellContent?: string };
|
|
15
|
+
|
|
16
|
+
export type CommentState = { commentEnabled: 'comment' | 'no cursor' | 'selection overlaps existing comment' };
|
|
17
|
+
|
|
18
|
+
export const useCommentState = (state: Partial<CommentState>) => {
|
|
19
|
+
const { cursorFallbackRange, model } = useSheetContext();
|
|
20
|
+
|
|
21
|
+
// TODO(thure): Can this O(n) call be memoized?
|
|
22
|
+
const overlapsCommentAnchor = useMemo(
|
|
23
|
+
() =>
|
|
24
|
+
RefArray.allResolvedTargets(model.sheet.threads ?? [])
|
|
25
|
+
.filter((thread) => thread.status !== 'resolved')
|
|
26
|
+
.some((thread) => {
|
|
27
|
+
if (!cursorFallbackRange) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return rangeToIndex(model.sheet, cursorFallbackRange) === thread.anchor;
|
|
31
|
+
}),
|
|
32
|
+
[cursorFallbackRange, model.sheet],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
state.commentEnabled = !cursorFallbackRange
|
|
37
|
+
? 'no cursor'
|
|
38
|
+
: overlapsCommentAnchor
|
|
39
|
+
? 'selection overlaps existing comment'
|
|
40
|
+
: 'comment';
|
|
41
|
+
}, [overlapsCommentAnchor, cursorFallbackRange]);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const createCommentAction = (state: Partial<CommentState>) =>
|
|
45
|
+
createMenuAction<Pick<CommentAction, 'key'>>('comment', {
|
|
46
|
+
key: commentKey,
|
|
47
|
+
testId: 'editor.toolbar.comment',
|
|
48
|
+
icon: 'ph--chat-text--regular',
|
|
49
|
+
label: [`${state.commentEnabled} label`, { ns: SHEET_PLUGIN }],
|
|
50
|
+
disabled: state.commentEnabled !== 'comment',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const createComment = (state: Partial<CommentState>) => ({
|
|
54
|
+
nodes: [createCommentAction(state)],
|
|
55
|
+
edges: [{ source: 'root', target: 'comment' }],
|
|
56
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
|
+
|
|
7
|
+
import { inRange } from '@dxos/compute';
|
|
8
|
+
import { createMenuAction, createMenuItemGroup, type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
|
9
|
+
|
|
10
|
+
import { SHEET_PLUGIN } from '../../meta';
|
|
11
|
+
import { rangeFromIndex, type StyleKey, type StyleValue } from '../../types';
|
|
12
|
+
import { useSheetContext } from '../SheetContext';
|
|
13
|
+
|
|
14
|
+
export type StyleState = Partial<Record<StyleValue, boolean>>;
|
|
15
|
+
|
|
16
|
+
export type StyleAction = { key: StyleKey; value: StyleValue };
|
|
17
|
+
|
|
18
|
+
const styles: Record<StyleValue, string> = {
|
|
19
|
+
highlight: 'ph--highlighter--regular',
|
|
20
|
+
softwrap: 'ph--paragraph--regular',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const useStyleState = (state: StyleState) => {
|
|
24
|
+
const { cursorFallbackRange, model } = useSheetContext();
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
state.highlight = false;
|
|
28
|
+
state.softwrap = false;
|
|
29
|
+
if (cursorFallbackRange && model.sheet.ranges) {
|
|
30
|
+
model.sheet.ranges
|
|
31
|
+
.filter(
|
|
32
|
+
({ range, key }) => key === 'style' && inRange(rangeFromIndex(model.sheet, range), cursorFallbackRange.from),
|
|
33
|
+
)
|
|
34
|
+
.forEach(({ value }) => {
|
|
35
|
+
state[value as StyleValue] = true;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}, [cursorFallbackRange, model.sheet]);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const createStyleGroup = (state: StyleState) => {
|
|
42
|
+
return createMenuItemGroup('style', {
|
|
43
|
+
variant: 'toggleGroup',
|
|
44
|
+
selectCardinality: 'multiple',
|
|
45
|
+
value: Object.keys(styles)
|
|
46
|
+
.filter((key) => !!state[key as StyleValue])
|
|
47
|
+
.map((styleValue) => `style--${styleValue}`),
|
|
48
|
+
} as ToolbarMenuActionGroupProperties);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const createStyleActions = (state: StyleState) =>
|
|
52
|
+
Object.entries(styles).map(([styleValue, icon]) => {
|
|
53
|
+
return createMenuAction<StyleAction>(`style--${styleValue}`, {
|
|
54
|
+
key: 'style',
|
|
55
|
+
value: styleValue as StyleValue,
|
|
56
|
+
icon,
|
|
57
|
+
label: [`range value ${styleValue} label`, { ns: SHEET_PLUGIN }],
|
|
58
|
+
checked: !!state[styleValue as StyleValue],
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const createStyle = (state: StyleState) => {
|
|
63
|
+
const styleGroupAction = createStyleGroup(state);
|
|
64
|
+
const styleActions = createStyleActions(state);
|
|
65
|
+
return {
|
|
66
|
+
nodes: [styleGroupAction, ...styleActions],
|
|
67
|
+
edges: [
|
|
68
|
+
{ source: 'root', target: 'style' },
|
|
69
|
+
...styleActions.map(({ id }) => ({ source: styleGroupAction.id, target: id })),
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
+
import { inRange } from '@dxos/compute';
|
|
9
|
+
import { ThreadAction } from '@dxos/plugin-thread/types';
|
|
10
|
+
import type { MenuAction, MenuActionHandler } from '@dxos/react-ui-menu';
|
|
11
|
+
|
|
12
|
+
import { type AlignAction } from './align';
|
|
13
|
+
import { type CommentAction } from './comment';
|
|
14
|
+
import { type StyleAction } from './style';
|
|
15
|
+
import { type ToolbarState } from './useToolbarState';
|
|
16
|
+
import { completeCellRangeToThreadCursor } from '../../integrations';
|
|
17
|
+
import { alignKey, rangeFromIndex, rangeToIndex } from '../../types';
|
|
18
|
+
import { useSheetContext } from '../SheetContext';
|
|
19
|
+
|
|
20
|
+
export type ToolbarAction = StyleAction | AlignAction | CommentAction;
|
|
21
|
+
|
|
22
|
+
export const useToolbarAction = (state: ToolbarState) => {
|
|
23
|
+
const { model, cursorFallbackRange, cursor } = useSheetContext();
|
|
24
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
25
|
+
|
|
26
|
+
// TODO(Zan): Externalize the toolbar action handler. E.g., Toolbar/keys should both fire events.
|
|
27
|
+
return useCallback(
|
|
28
|
+
(action: MenuAction<ToolbarAction>) => {
|
|
29
|
+
const { key, value } = action.properties;
|
|
30
|
+
if (cursorFallbackRange) {
|
|
31
|
+
const index =
|
|
32
|
+
model.sheet.ranges?.findIndex(
|
|
33
|
+
(range) => range.key === key && inRange(rangeFromIndex(model.sheet, range.range), cursorFallbackRange.from),
|
|
34
|
+
) ?? -1;
|
|
35
|
+
const nextRangeEntity = {
|
|
36
|
+
range: rangeToIndex(model.sheet, cursorFallbackRange),
|
|
37
|
+
key,
|
|
38
|
+
value,
|
|
39
|
+
};
|
|
40
|
+
switch (key) {
|
|
41
|
+
case 'alignment':
|
|
42
|
+
if (index < 0) {
|
|
43
|
+
model.sheet.ranges?.push(nextRangeEntity);
|
|
44
|
+
state[alignKey] = value;
|
|
45
|
+
} else if (model.sheet.ranges![index].value === value) {
|
|
46
|
+
model.sheet.ranges?.splice(index, 1);
|
|
47
|
+
state[alignKey] = undefined;
|
|
48
|
+
} else {
|
|
49
|
+
model.sheet.ranges?.splice(index, 1, nextRangeEntity);
|
|
50
|
+
state[alignKey] = value;
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
case 'style':
|
|
54
|
+
if (
|
|
55
|
+
model.sheet.ranges
|
|
56
|
+
.filter(
|
|
57
|
+
({ range, key: rangeKey }) =>
|
|
58
|
+
rangeKey === 'style' && inRange(rangeFromIndex(model.sheet, range), cursorFallbackRange.from),
|
|
59
|
+
)
|
|
60
|
+
.some(({ value: rangeValue }) => rangeValue === value)
|
|
61
|
+
) {
|
|
62
|
+
// this value should be unset
|
|
63
|
+
if (index >= 0) {
|
|
64
|
+
model.sheet.ranges?.splice(index, 1);
|
|
65
|
+
}
|
|
66
|
+
state[value] = false;
|
|
67
|
+
} else {
|
|
68
|
+
model.sheet.ranges?.push(nextRangeEntity);
|
|
69
|
+
state[value] = true;
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case 'comment': {
|
|
73
|
+
const cellContent = model.getCellText(cursorFallbackRange.from);
|
|
74
|
+
void dispatch(
|
|
75
|
+
createIntent(ThreadAction.Create, {
|
|
76
|
+
cursor: completeCellRangeToThreadCursor(cursorFallbackRange),
|
|
77
|
+
name: cellContent,
|
|
78
|
+
subject: model.sheet,
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
[model.sheet, cursorFallbackRange, cursor, dispatch],
|
|
86
|
+
) as MenuActionHandler;
|
|
87
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { create } from '@dxos/live-object';
|
|
8
|
+
|
|
9
|
+
import { type AlignState } from './align';
|
|
10
|
+
import { type CommentState } from './comment';
|
|
11
|
+
import { type StyleState } from './style';
|
|
12
|
+
|
|
13
|
+
export type ToolbarState = Partial<StyleState & AlignState & CommentState>;
|
|
14
|
+
|
|
15
|
+
export const useToolbarState = (initialState: ToolbarState = {}) => {
|
|
16
|
+
return useMemo(() => create<ToolbarState>(initialState), []);
|
|
17
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
useTextEditor,
|
|
21
21
|
} from '@dxos/react-ui-editor';
|
|
22
22
|
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
23
|
-
import {
|
|
23
|
+
import { isNonNullable } from '@dxos/util';
|
|
24
24
|
|
|
25
25
|
import { compute, computeGraphFacet } from './compute';
|
|
26
26
|
import { GridSheet, SheetProvider, useComputeGraph } from '../components';
|
|
@@ -57,7 +57,7 @@ const EditorStory = ({ text }: EditorProps) => {
|
|
|
57
57
|
computeGraph && computeGraphFacet.of(computeGraph),
|
|
58
58
|
compute(),
|
|
59
59
|
decorateMarkdown(),
|
|
60
|
-
].filter(
|
|
60
|
+
].filter(isNonNullable),
|
|
61
61
|
}),
|
|
62
62
|
[computeGraph, themeMode],
|
|
63
63
|
);
|
package/src/index.ts
CHANGED
|
@@ -8,14 +8,15 @@ import {
|
|
|
8
8
|
createIntent,
|
|
9
9
|
createResolver,
|
|
10
10
|
LayoutAction,
|
|
11
|
-
useIntentDispatcher,
|
|
12
11
|
useIntentResolver,
|
|
12
|
+
useIntentDispatcher,
|
|
13
13
|
} from '@dxos/app-framework';
|
|
14
14
|
import { debounce } from '@dxos/async';
|
|
15
15
|
import { type CellAddress, type CompleteCellRange, inRange } from '@dxos/compute';
|
|
16
|
+
import { S } from '@dxos/echo-schema';
|
|
16
17
|
import { ThreadAction } from '@dxos/plugin-thread/types';
|
|
17
18
|
import { fullyQualifiedId } from '@dxos/react-client/echo';
|
|
18
|
-
import { type DxGridElement, type DxGridPosition } from '@dxos/react-ui-grid';
|
|
19
|
+
import { type DxGridElement, type DxGridPosition, type GridContentProps } from '@dxos/react-ui-grid';
|
|
19
20
|
|
|
20
21
|
import { useSheetContext } from '../components';
|
|
21
22
|
import { SHEET_PLUGIN } from '../meta';
|
|
@@ -41,19 +42,29 @@ export const useUpdateFocusedCellOnThreadSelection = (grid: DxGridElement | null
|
|
|
41
42
|
const { model, setActiveRefs } = useSheetContext();
|
|
42
43
|
const scrollIntoViewResolver = useMemo(
|
|
43
44
|
() =>
|
|
44
|
-
createResolver(
|
|
45
|
-
LayoutAction.ScrollIntoView,
|
|
46
|
-
|
|
45
|
+
createResolver({
|
|
46
|
+
intent: LayoutAction.ScrollIntoView,
|
|
47
|
+
position: 'hoist',
|
|
48
|
+
filter: (
|
|
49
|
+
data,
|
|
50
|
+
): data is {
|
|
51
|
+
part: 'current';
|
|
52
|
+
subject: string;
|
|
53
|
+
options: { cursor: string; ref: GridContentProps['activeRefs'] };
|
|
54
|
+
} => {
|
|
55
|
+
if (!S.is(LayoutAction.ScrollIntoView.fields.input)(data)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return data.subject === fullyQualifiedId(model.sheet) && !!data.options?.cursor;
|
|
60
|
+
},
|
|
61
|
+
resolve: ({ options: { cursor, ref } }) => {
|
|
47
62
|
setActiveRefs(ref);
|
|
48
63
|
// TODO(Zan): Everywhere we refer to the cursor in a thread context should change to `anchor`.
|
|
49
64
|
const range = parseThreadAnchorAsCellRange(cursor!);
|
|
50
65
|
range && grid?.setFocus({ ...range.to, plane: 'grid' }, true);
|
|
51
66
|
},
|
|
52
|
-
|
|
53
|
-
disposition: 'hoist',
|
|
54
|
-
filter: (data) => data.id === fullyQualifiedId(model.sheet) && !!data.cursor,
|
|
55
|
-
},
|
|
56
|
-
),
|
|
67
|
+
}),
|
|
57
68
|
[model.sheet, setActiveRefs],
|
|
58
69
|
);
|
|
59
70
|
|
package/src/meta.ts
CHANGED
|
@@ -6,10 +6,12 @@ import { type PluginMeta } from '@dxos/app-framework';
|
|
|
6
6
|
|
|
7
7
|
export const SHEET_PLUGIN = 'dxos.org/plugin/sheet';
|
|
8
8
|
|
|
9
|
-
export
|
|
9
|
+
export const meta = {
|
|
10
10
|
id: SHEET_PLUGIN,
|
|
11
11
|
name: 'Sheet',
|
|
12
|
-
description:
|
|
12
|
+
description:
|
|
13
|
+
'Sheets in Composer are simple spreadsheets which allow you to leverage custom functions inside of cell grids. Leverage more than 400 pre-built formulas like Sum, Average, Count, Max, Min along with many others. You can also deploy your own custom functions using the Scripts plugin. ',
|
|
13
14
|
icon: 'ph--grid-nine--regular',
|
|
14
15
|
source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-sheet',
|
|
16
|
+
screenshots: ['https://dxos.network/plugin-details-sheet-dark.png'],
|
|
15
17
|
} satisfies PluginMeta;
|
|
@@ -8,7 +8,7 @@ import { type SheetType } from '../types';
|
|
|
8
8
|
|
|
9
9
|
export const alignKey = 'alignment';
|
|
10
10
|
export type AlignKey = typeof alignKey;
|
|
11
|
-
export type AlignValue = 'start' | 'center' | 'end'
|
|
11
|
+
export type AlignValue = 'start' | 'center' | 'end';
|
|
12
12
|
|
|
13
13
|
export const commentKey = 'comment';
|
|
14
14
|
export type CommentKey = typeof commentKey;
|
package/src/types/types.ts
CHANGED
|
@@ -2,38 +2,12 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import type {
|
|
6
|
-
IntentResolverProvides,
|
|
7
|
-
MetadataRecordsProvides,
|
|
8
|
-
SurfaceProvides,
|
|
9
|
-
TranslationsProvides,
|
|
10
|
-
} from '@dxos/app-framework';
|
|
11
5
|
import { S } from '@dxos/echo-schema';
|
|
12
|
-
import { type MarkdownExtensionProvides } from '@dxos/plugin-markdown';
|
|
13
|
-
import { type SchemaProvides } from '@dxos/plugin-space';
|
|
14
6
|
|
|
15
7
|
import { type CellValue, RowColumnMeta, SheetType } from './schema';
|
|
16
8
|
import { SHEET_PLUGIN } from '../meta';
|
|
17
9
|
import { SheetModel } from '../model';
|
|
18
10
|
|
|
19
|
-
// TODO(Zan): Move this to the plugin-space plugin or another common location
|
|
20
|
-
// when we implement comments in sheets.
|
|
21
|
-
// This is currently duplicated in a few places.
|
|
22
|
-
type ThreadProvides<T> = {
|
|
23
|
-
thread: {
|
|
24
|
-
predicate: (obj: any) => obj is T;
|
|
25
|
-
createSort: (obj: T) => (anchorA: string | undefined, anchorB: string | undefined) => number;
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export type SheetPluginProvides = SurfaceProvides &
|
|
30
|
-
IntentResolverProvides &
|
|
31
|
-
MarkdownExtensionProvides &
|
|
32
|
-
MetadataRecordsProvides &
|
|
33
|
-
TranslationsProvides &
|
|
34
|
-
SchemaProvides &
|
|
35
|
-
ThreadProvides<SheetType>;
|
|
36
|
-
|
|
37
11
|
export type SheetSize = {
|
|
38
12
|
rows: number;
|
|
39
13
|
columns: number;
|