@dxos/plugin-sheet 0.7.1 → 0.7.2-main.f1adc9f
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-YAMIOFC6.mjs → SheetContainer-DBDIZU6U.mjs} +4 -3
- package/dist/lib/browser/{SheetContainer-YAMIOFC6.mjs.map → SheetContainer-DBDIZU6U.mjs.map} +3 -3
- package/dist/lib/browser/{chunk-QHQFM7LV.mjs → chunk-IXA5HC36.mjs} +48 -22
- package/dist/lib/browser/{chunk-QHQFM7LV.mjs.map → chunk-IXA5HC36.mjs.map} +4 -4
- package/dist/lib/browser/index.mjs +8 -13
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/{SheetContainer-BSDHHYXE.cjs → SheetContainer-3373SORI.cjs} +16 -15
- package/dist/lib/node/{SheetContainer-BSDHHYXE.cjs.map → SheetContainer-3373SORI.cjs.map} +3 -3
- package/dist/lib/node/{chunk-J5ZFWMOD.cjs → chunk-TS6IBEPZ.cjs} +34 -10
- package/dist/lib/node/{chunk-J5ZFWMOD.cjs.map → chunk-TS6IBEPZ.cjs.map} +4 -4
- package/dist/lib/node/index.cjs +10 -15
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/{SheetContainer-T47T2NYJ.mjs → SheetContainer-CH2RYBXJ.mjs} +4 -3
- package/dist/lib/node-esm/{SheetContainer-T47T2NYJ.mjs.map → SheetContainer-CH2RYBXJ.mjs.map} +3 -3
- package/dist/lib/node-esm/{chunk-6GSTEN7N.mjs → chunk-7F3BRKP7.mjs} +48 -22
- package/dist/lib/node-esm/{chunk-6GSTEN7N.mjs.map → chunk-7F3BRKP7.mjs.map} +4 -4
- package/dist/lib/node-esm/index.mjs +8 -13
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/SheetPlugin.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -1
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +1 -0
- package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -1
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts +2 -0
- package/dist/types/src/components/SheetContainer/SheetContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/SheetObjectSettings.d.ts +7 -0
- package/dist/types/src/components/SheetObjectSettings.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/integrations/thread-ranges.d.ts.map +1 -1
- package/dist/types/src/testing/playwright/playwright.config.d.ts +3 -0
- package/dist/types/src/testing/playwright/playwright.config.d.ts.map +1 -0
- package/dist/types/src/testing/playwright/sheet-manager.d.ts +24 -0
- package/dist/types/src/testing/playwright/sheet-manager.d.ts.map +1 -0
- package/dist/types/src/testing/playwright/sheet.spec.d.ts +2 -0
- package/dist/types/src/testing/playwright/sheet.spec.d.ts.map +1 -0
- package/package.json +39 -37
- package/src/SheetPlugin.tsx +5 -13
- package/src/components/GridSheet/GridSheet.stories.tsx +2 -0
- package/src/components/GridSheet/GridSheet.tsx +12 -3
- package/src/components/GridSheet/SheetCellEditor.stories.tsx +2 -2
- package/src/components/SheetContainer/SheetContainer.stories.tsx +44 -2
- package/src/components/SheetObjectSettings.tsx +38 -0
- package/src/components/Toolbar/Toolbar.tsx +7 -1
- package/src/components/index.ts +1 -0
- package/src/compute-graph/compute-graph.stories.tsx +1 -1
- package/src/compute-graph/compute-graph.test.ts +1 -1
- package/src/integrations/thread-ranges.ts +2 -0
- package/src/sanity.test.ts +1 -1
- package/src/testing/playwright/playwright.config.ts +18 -0
- package/src/testing/playwright/sheet-manager.ts +91 -0
- package/src/testing/playwright/sheet.spec.ts +78 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-sheet",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2-main.f1adc9f",
|
|
4
4
|
"description": "Braneframe sketch plugin",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -69,33 +69,33 @@
|
|
|
69
69
|
"re-resizable": "^6.9.17",
|
|
70
70
|
"react-markdown": "^8.0.5",
|
|
71
71
|
"react-resize-detector": "^11.0.1",
|
|
72
|
-
"@dxos/
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/
|
|
75
|
-
"@dxos/
|
|
76
|
-
"@dxos/
|
|
77
|
-
"@dxos/
|
|
78
|
-
"@dxos/
|
|
79
|
-
"@dxos/
|
|
80
|
-
"@dxos/
|
|
81
|
-
"@dxos/
|
|
82
|
-
"@dxos/plugin-client": "0.7.
|
|
83
|
-
"@dxos/
|
|
84
|
-
"@dxos/plugin-
|
|
85
|
-
"@dxos/plugin-
|
|
86
|
-
"@dxos/plugin-
|
|
87
|
-
"@dxos/plugin-
|
|
88
|
-
"@dxos/plugin-
|
|
89
|
-
"@dxos/react-client": "0.7.
|
|
90
|
-
"@dxos/react-
|
|
91
|
-
"@dxos/react-
|
|
92
|
-
"@dxos/react-ui-
|
|
93
|
-
"@dxos/react-ui-
|
|
94
|
-
"@dxos/react-ui-
|
|
95
|
-
"@dxos/react-ui-
|
|
96
|
-
"@dxos/
|
|
97
|
-
"@dxos/react-ui-
|
|
98
|
-
"@dxos/
|
|
72
|
+
"@dxos/app-framework": "0.7.2-main.f1adc9f",
|
|
73
|
+
"@dxos/client": "0.7.2-main.f1adc9f",
|
|
74
|
+
"@dxos/context": "0.7.2-main.f1adc9f",
|
|
75
|
+
"@dxos/async": "0.7.2-main.f1adc9f",
|
|
76
|
+
"@dxos/crypto": "0.7.2-main.f1adc9f",
|
|
77
|
+
"@dxos/debug": "0.7.2-main.f1adc9f",
|
|
78
|
+
"@dxos/invariant": "0.7.2-main.f1adc9f",
|
|
79
|
+
"@dxos/echo-schema": "0.7.2-main.f1adc9f",
|
|
80
|
+
"@dxos/keys": "0.7.2-main.f1adc9f",
|
|
81
|
+
"@dxos/log": "0.7.2-main.f1adc9f",
|
|
82
|
+
"@dxos/plugin-client": "0.7.2-main.f1adc9f",
|
|
83
|
+
"@dxos/plugin-attention": "0.7.2-main.f1adc9f",
|
|
84
|
+
"@dxos/plugin-graph": "0.7.2-main.f1adc9f",
|
|
85
|
+
"@dxos/plugin-script": "0.7.2-main.f1adc9f",
|
|
86
|
+
"@dxos/plugin-markdown": "0.7.2-main.f1adc9f",
|
|
87
|
+
"@dxos/plugin-space": "0.7.2-main.f1adc9f",
|
|
88
|
+
"@dxos/plugin-stack": "0.7.2-main.f1adc9f",
|
|
89
|
+
"@dxos/react-client": "0.7.2-main.f1adc9f",
|
|
90
|
+
"@dxos/react-hooks": "0.7.2-main.f1adc9f",
|
|
91
|
+
"@dxos/react-ui-attention": "0.7.2-main.f1adc9f",
|
|
92
|
+
"@dxos/react-ui-editor": "0.7.2-main.f1adc9f",
|
|
93
|
+
"@dxos/react-ui-list": "0.7.2-main.f1adc9f",
|
|
94
|
+
"@dxos/react-ui-grid": "0.7.2-main.f1adc9f",
|
|
95
|
+
"@dxos/react-ui-stack": "0.7.2-main.f1adc9f",
|
|
96
|
+
"@dxos/util": "0.7.2-main.f1adc9f",
|
|
97
|
+
"@dxos/react-ui-form": "0.7.2-main.f1adc9f",
|
|
98
|
+
"@dxos/schema": "0.7.2-main.f1adc9f"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
101
|
"@lezer/generator": "^1.7.1",
|
|
@@ -107,19 +107,21 @@
|
|
|
107
107
|
"react": "~18.2.0",
|
|
108
108
|
"react-dom": "~18.2.0",
|
|
109
109
|
"vite": "5.4.7",
|
|
110
|
-
"@dxos/
|
|
111
|
-
"@dxos/
|
|
112
|
-
"@dxos/
|
|
113
|
-
"@dxos/
|
|
114
|
-
"@dxos/react-ui
|
|
115
|
-
"@dxos/
|
|
116
|
-
"@dxos/react-ui-
|
|
110
|
+
"@dxos/lit-grid": "0.7.2-main.f1adc9f",
|
|
111
|
+
"@dxos/random": "0.7.2-main.f1adc9f",
|
|
112
|
+
"@dxos/echo-generator": "0.7.2-main.f1adc9f",
|
|
113
|
+
"@dxos/react-ui-syntax-highlighter": "0.7.2-main.f1adc9f",
|
|
114
|
+
"@dxos/react-ui": "0.7.2-main.f1adc9f",
|
|
115
|
+
"@dxos/react-ui-theme": "0.7.2-main.f1adc9f",
|
|
116
|
+
"@dxos/react-ui-types": "0.7.2-main.f1adc9f",
|
|
117
|
+
"@dxos/storybook-utils": "0.7.2-main.f1adc9f",
|
|
118
|
+
"@dxos/test-utils": "0.7.2-main.f1adc9f"
|
|
117
119
|
},
|
|
118
120
|
"peerDependencies": {
|
|
119
121
|
"react": "~18.2.0",
|
|
120
122
|
"react-dom": "~18.2.0",
|
|
121
|
-
"@dxos/react-ui": "0.7.
|
|
122
|
-
"@dxos/react-ui
|
|
123
|
+
"@dxos/react-ui-theme": "0.7.2-main.f1adc9f",
|
|
124
|
+
"@dxos/react-ui": "0.7.2-main.f1adc9f"
|
|
123
125
|
},
|
|
124
126
|
"publishConfig": {
|
|
125
127
|
"access": "public"
|
package/src/SheetPlugin.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import { SpaceAction } from '@dxos/plugin-space';
|
|
|
13
13
|
import { getSpace, isEchoObject } from '@dxos/react-client/echo';
|
|
14
14
|
import { Icon } from '@dxos/react-ui';
|
|
15
15
|
|
|
16
|
-
import { ComputeGraphContextProvider,
|
|
16
|
+
import { ComputeGraphContextProvider, SheetContainer, SheetObjectSettings } from './components';
|
|
17
17
|
import { type ComputeGraphRegistry } from './compute-graph';
|
|
18
18
|
import { compareIndexPositions, createSheet } from './defs';
|
|
19
19
|
import { computeGraphFacet } from './extensions';
|
|
@@ -144,26 +144,18 @@ export const SheetPlugin = (): PluginDefinition<SheetPluginProvides> => {
|
|
|
144
144
|
surface: {
|
|
145
145
|
component: ({ data, role }) => {
|
|
146
146
|
const space = isEchoObject(data.object) ? getSpace(data.object) : undefined;
|
|
147
|
-
if (!space) {
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
147
|
switch (role) {
|
|
152
148
|
case 'article':
|
|
153
149
|
case 'section':
|
|
154
|
-
if (data.object instanceof SheetType) {
|
|
150
|
+
if (space && data.object instanceof SheetType) {
|
|
155
151
|
return <SheetContainer space={space} sheet={data.object} role={role} />;
|
|
156
152
|
}
|
|
157
|
-
|
|
158
|
-
return null;
|
|
153
|
+
break;
|
|
159
154
|
case 'complementary--settings':
|
|
160
155
|
if (data.subject instanceof SheetType) {
|
|
161
|
-
return {
|
|
162
|
-
node: <RangeList sheet={data.subject} />,
|
|
163
|
-
};
|
|
156
|
+
return <SheetObjectSettings sheet={data.subject} />;
|
|
164
157
|
}
|
|
165
|
-
|
|
166
|
-
return null;
|
|
158
|
+
break;
|
|
167
159
|
}
|
|
168
160
|
|
|
169
161
|
return null;
|
|
@@ -335,21 +335,30 @@ export const GridSheet = () => {
|
|
|
335
335
|
<DropdownMenu.VirtualTrigger virtualRef={contextMenuAnchorRef} />
|
|
336
336
|
<DropdownMenu.Content side={contextMenuAxis === 'col' ? 'bottom' : 'right'} sideOffset={4} collisionPadding={8}>
|
|
337
337
|
<DropdownMenu.Viewport>
|
|
338
|
-
<DropdownMenu.Item
|
|
338
|
+
<DropdownMenu.Item
|
|
339
|
+
onClick={() => handleAxisMenuAction('insert-before')}
|
|
340
|
+
data-testid={`grid.${contextMenuAxis}.insert-before`}
|
|
341
|
+
>
|
|
339
342
|
<Icon
|
|
340
343
|
size={5}
|
|
341
344
|
icon={contextMenuAxis === 'col' ? 'ph--columns-plus-left--regular' : 'ph--rows-plus-top--regular'}
|
|
342
345
|
/>
|
|
343
346
|
<span>{t(`add ${contextMenuAxis} before label`)}</span>
|
|
344
347
|
</DropdownMenu.Item>
|
|
345
|
-
<DropdownMenu.Item
|
|
348
|
+
<DropdownMenu.Item
|
|
349
|
+
onClick={() => handleAxisMenuAction('insert-after')}
|
|
350
|
+
data-testid={`grid.${contextMenuAxis}.insert-after`}
|
|
351
|
+
>
|
|
346
352
|
<Icon
|
|
347
353
|
size={5}
|
|
348
354
|
icon={contextMenuAxis === 'col' ? 'ph--columns-plus-right--regular' : 'ph--rows-plus-bottom--regular'}
|
|
349
355
|
/>
|
|
350
356
|
<span>{t(`add ${contextMenuAxis} after label`)}</span>
|
|
351
357
|
</DropdownMenu.Item>
|
|
352
|
-
<DropdownMenu.Item
|
|
358
|
+
<DropdownMenu.Item
|
|
359
|
+
onClick={() => handleAxisMenuAction('drop')}
|
|
360
|
+
data-testid={`grid.${contextMenuAxis}.drop`}
|
|
361
|
+
>
|
|
353
362
|
<Icon size={5} icon='ph--backspace--regular' />
|
|
354
363
|
<span>{t(`delete ${contextMenuAxis} label`)}</span>
|
|
355
364
|
</DropdownMenu.Item>
|
|
@@ -8,7 +8,7 @@ import { type Meta } from '@storybook/react';
|
|
|
8
8
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
9
9
|
|
|
10
10
|
import { Client } from '@dxos/client';
|
|
11
|
-
import { createDocAccessor, type
|
|
11
|
+
import { createDocAccessor, type ReactiveEchoObject } from '@dxos/client/echo';
|
|
12
12
|
import { automerge } from '@dxos/react-ui-editor';
|
|
13
13
|
import { CellEditor, type CellEditorProps } from '@dxos/react-ui-grid';
|
|
14
14
|
import { withTheme } from '@dxos/storybook-utils';
|
|
@@ -33,7 +33,7 @@ const Story = ({ value, ...props }: StoryProps) => {
|
|
|
33
33
|
|
|
34
34
|
const AutomergeStory = ({ value, ...props }: StoryProps) => {
|
|
35
35
|
const cell = 'A1';
|
|
36
|
-
const [object, setObject] = useState<
|
|
36
|
+
const [object, setObject] = useState<ReactiveEchoObject<SheetType>>();
|
|
37
37
|
useEffect(() => {
|
|
38
38
|
setTimeout(async () => {
|
|
39
39
|
const client = new Client({ types: [SheetType] });
|
|
@@ -2,18 +2,40 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
5
7
|
import { type Meta } from '@storybook/react';
|
|
6
8
|
import React from 'react';
|
|
7
9
|
|
|
8
|
-
import {
|
|
10
|
+
import { type Intent, IntentProvider } from '@dxos/app-framework';
|
|
11
|
+
import { useSpace, create } from '@dxos/react-client/echo';
|
|
9
12
|
import { withClientProvider } from '@dxos/react-client/testing';
|
|
10
13
|
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
11
14
|
|
|
12
15
|
import { SheetContainer } from './SheetContainer';
|
|
13
16
|
import { createTestCells, useTestSheet, withComputeGraphDecorator } from '../../testing';
|
|
14
17
|
import translations from '../../translations';
|
|
15
|
-
import { SheetType } from '../../types';
|
|
18
|
+
import { SheetAction, SheetType } from '../../types';
|
|
16
19
|
import { useComputeGraph } from '../ComputeGraph';
|
|
20
|
+
import { RangeList } from '../RangeList';
|
|
21
|
+
|
|
22
|
+
// TODO(thure via wittjosiah): stories/components should be written such that the dependency on intents is external and provided via callback and then the story can implement it differently.
|
|
23
|
+
const storybookIntentValue = create({
|
|
24
|
+
dispatch: async (intents: Intent | Intent[]) => {
|
|
25
|
+
const intent = Array.isArray(intents) ? intents[0] : intents;
|
|
26
|
+
switch (intent.action) {
|
|
27
|
+
case SheetAction.DROP_AXIS: {
|
|
28
|
+
if (!intent.undo) {
|
|
29
|
+
const { model, axis, axisIndex } = intent.data as SheetAction.DropAxis;
|
|
30
|
+
model[axis === 'col' ? 'dropColumn' : 'dropRow'](axisIndex);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
undo: async () => ({}),
|
|
36
|
+
history: [],
|
|
37
|
+
registerResolver: () => () => {},
|
|
38
|
+
});
|
|
17
39
|
|
|
18
40
|
export const Basic = () => {
|
|
19
41
|
const space = useSpace();
|
|
@@ -26,6 +48,26 @@ export const Basic = () => {
|
|
|
26
48
|
return <SheetContainer space={space} sheet={sheet} role='article' ignoreAttention />;
|
|
27
49
|
};
|
|
28
50
|
|
|
51
|
+
export const Spec = () => {
|
|
52
|
+
const space = useSpace();
|
|
53
|
+
const graph = useComputeGraph(space);
|
|
54
|
+
const sheet = useTestSheet(space, graph, { cells: { A1: { value: 'Ready' } } });
|
|
55
|
+
if (!sheet || !space) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<IntentProvider value={storybookIntentValue}>
|
|
61
|
+
<div role='none' className='grid grid-rows-[66%_33%] grid-cols-1'>
|
|
62
|
+
<SheetContainer space={space} sheet={sheet} role='article' ignoreAttention />
|
|
63
|
+
<div role='none' data-testid='grid.range-list'>
|
|
64
|
+
<RangeList sheet={sheet} />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</IntentProvider>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
29
71
|
const meta: Meta = {
|
|
30
72
|
title: 'plugins/plugin-sheet/SheetContainer',
|
|
31
73
|
component: SheetContainer,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { SPACE_PLUGIN } from '@dxos/plugin-space/meta';
|
|
8
|
+
import { Input, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
|
|
10
|
+
import { RangeList } from './RangeList';
|
|
11
|
+
import { type SheetType } from '../types';
|
|
12
|
+
|
|
13
|
+
export type SheetObjectSettingsProps = {
|
|
14
|
+
sheet: SheetType;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const SheetObjectSettings = ({ sheet }: SheetObjectSettingsProps) => {
|
|
18
|
+
const { t } = useTranslation(SPACE_PLUGIN);
|
|
19
|
+
|
|
20
|
+
// TODO(burdon): Standardize forms.
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<div role='form' className='flex flex-col w-full p-2 gap-1'>
|
|
24
|
+
<Input.Root>
|
|
25
|
+
<Input.Label>{t('name label')}</Input.Label>
|
|
26
|
+
<Input.TextInput
|
|
27
|
+
placeholder={t('name placeholder')}
|
|
28
|
+
value={sheet.name ?? ''}
|
|
29
|
+
onChange={(event) => {
|
|
30
|
+
sheet.name = event.target.value;
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
</Input.Root>
|
|
34
|
+
</div>
|
|
35
|
+
<RangeList sheet={sheet} />
|
|
36
|
+
</>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
@@ -225,7 +225,13 @@ const Alignment = () => {
|
|
|
225
225
|
onValueChange={(value: AlignValue) => onAction?.({ key: alignKey, value })}
|
|
226
226
|
>
|
|
227
227
|
{alignmentOptions.map(({ value, icon }) => (
|
|
228
|
-
<ToolbarItem
|
|
228
|
+
<ToolbarItem
|
|
229
|
+
itemType='toggleGroupItem'
|
|
230
|
+
key={value}
|
|
231
|
+
value={value}
|
|
232
|
+
icon={icon}
|
|
233
|
+
data-testid={`grid.toolbar.${alignKey}.${value}`}
|
|
234
|
+
>
|
|
229
235
|
{t('toolbar action label', {
|
|
230
236
|
key: t(`range key ${alignKey} label`),
|
|
231
237
|
value: t(`range value ${value} label`),
|
package/src/components/index.ts
CHANGED
|
@@ -45,7 +45,7 @@ const Story = () => {
|
|
|
45
45
|
setResult({ functions: { standard: f1.length, echo: f2.length } });
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
space.db.add(create(FunctionType, { version: 1, binding: FUNCTION_NAME }));
|
|
48
|
+
space.db.add(create(FunctionType, { name: 'test', version: 1, binding: FUNCTION_NAME }));
|
|
49
49
|
}
|
|
50
50
|
}, [space, graph]);
|
|
51
51
|
|
|
@@ -30,7 +30,7 @@ describe('ComputeGraph', () => {
|
|
|
30
30
|
// Create script.
|
|
31
31
|
const trigger = new Trigger();
|
|
32
32
|
graph.update.once(() => trigger.wake());
|
|
33
|
-
const functionObject = space.db.add(create(FunctionType, { version: 1, binding: 'TEST' }));
|
|
33
|
+
const functionObject = space.db.add(create(FunctionType, { name: 'test', version: 1, binding: 'TEST' }));
|
|
34
34
|
await trigger.wait();
|
|
35
35
|
const functions = graph.getFunctions({ echo: true });
|
|
36
36
|
expect(functions).to.toHaveLength(1);
|
|
@@ -43,6 +43,8 @@ export const useUpdateFocusedCellOnThreadSelection = (grid: DxGridElement | null
|
|
|
43
43
|
// TODO(Zan): Everywhere we refer to the cursor in a thread context should change to `anchor`.
|
|
44
44
|
const range = parseThreadAnchorAsCellRange(data.cursor);
|
|
45
45
|
range && grid?.setFocus({ ...range.to, plane: 'grid' }, true);
|
|
46
|
+
|
|
47
|
+
return { data: true };
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
},
|
package/src/sanity.test.ts
CHANGED
|
@@ -34,7 +34,7 @@ describe('test', () => {
|
|
|
34
34
|
// - ERROR "process.nextTick is not a function"
|
|
35
35
|
// - ERROR "Identifier 'Buffer' has already been declared" if { nodeExternal: true }
|
|
36
36
|
const space = await client.spaces.create();
|
|
37
|
-
const fn = space.db.add(create(FunctionType, { version: 1, binding: 'HELLO' }));
|
|
37
|
+
const fn = space.db.add(create(FunctionType, { name: 'test', version: 1, binding: 'HELLO' }));
|
|
38
38
|
expect(fn).to.exist;
|
|
39
39
|
});
|
|
40
40
|
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { nxE2EPreset } from '@nx/playwright/preset';
|
|
6
|
+
import { defineConfig } from '@playwright/test';
|
|
7
|
+
|
|
8
|
+
import { e2ePreset } from '@dxos/test-utils/playwright';
|
|
9
|
+
|
|
10
|
+
export default defineConfig({
|
|
11
|
+
...nxE2EPreset(__filename, { testDir: __dirname }),
|
|
12
|
+
...e2ePreset(__dirname),
|
|
13
|
+
webServer: {
|
|
14
|
+
command: 'pnpm -w nx storybook stories',
|
|
15
|
+
port: 9009,
|
|
16
|
+
reuseExistingServer: !process.env.CI,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Locator, type Page } from '@playwright/test';
|
|
6
|
+
|
|
7
|
+
import { DxGridManager } from '@dxos/lit-grid/testing';
|
|
8
|
+
import { type DxGridPosition, type DxGridAxis } from '@dxos/react-ui-grid';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Test helper for managing dx-grid interactions and assertions in Playwright tests.
|
|
12
|
+
* Provides utilities for cell selection, grid navigation, virtualization checks and event handling.
|
|
13
|
+
*/
|
|
14
|
+
export class SheetManager {
|
|
15
|
+
constructor(page: Page, grid?: Locator) {
|
|
16
|
+
this.grid = new DxGridManager(page, grid);
|
|
17
|
+
this.page = page;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
grid: DxGridManager;
|
|
21
|
+
page: Page;
|
|
22
|
+
|
|
23
|
+
async ready() {
|
|
24
|
+
await this.grid.ready();
|
|
25
|
+
return this.cellByText('Ready').waitFor({ state: 'visible' });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async fill(text: string) {
|
|
29
|
+
// TODO(thure): Do these timeouts help with test flakiness?
|
|
30
|
+
await this.page.waitForTimeout(200);
|
|
31
|
+
await this.cellEditor().fill(text);
|
|
32
|
+
await this.page.waitForTimeout(200);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async press(key: string) {
|
|
36
|
+
// TODO(thure): Does these timeouts help with test flakiness?
|
|
37
|
+
await this.page.waitForTimeout(200);
|
|
38
|
+
await this.page.keyboard.press(key);
|
|
39
|
+
await this.page.waitForTimeout(200);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async commit(key: string) {
|
|
43
|
+
// TODO(thure): Why do we need to wait? Enter is ignored otherwise…
|
|
44
|
+
await this.page.waitForTimeout(500);
|
|
45
|
+
await this.press(key);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
cellByText(text: string) {
|
|
49
|
+
return this.grid.grid.getByText(text);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async setFocusedCellValue(text: string, commitKey: string) {
|
|
53
|
+
const mode = await this.grid.mode();
|
|
54
|
+
if (mode === 'browse') {
|
|
55
|
+
await this.commit('Enter');
|
|
56
|
+
}
|
|
57
|
+
await this.fill(text);
|
|
58
|
+
await this.commit(commitKey);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async selectRange(start: DxGridPosition, end: DxGridPosition) {
|
|
62
|
+
const startCell = this.grid.cell(start.col, start.row, start.plane);
|
|
63
|
+
const endCell = this.grid.cell(end.col, end.row, end.plane);
|
|
64
|
+
const startBox = await startCell.boundingBox();
|
|
65
|
+
const endBox = await endCell.boundingBox();
|
|
66
|
+
await startCell.dragTo(endCell, {
|
|
67
|
+
sourcePosition: { x: startBox!.width / 2, y: startBox!.height / 2 },
|
|
68
|
+
targetPosition: { x: endBox!.width / 2, y: endBox!.height / 2 },
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async deleteAxis(axis: DxGridAxis, position: number) {
|
|
73
|
+
const col = axis === 'row' ? 0 : position;
|
|
74
|
+
const row = axis === 'row' ? position : 0;
|
|
75
|
+
const plane = axis === 'row' ? 'frozenColsStart' : 'frozenRowsStart';
|
|
76
|
+
await this.grid.cell(col, row, plane).click({ button: 'right' });
|
|
77
|
+
await this.page.getByTestId(`grid.${axis}.drop`).click();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
toolbarAction(key: string, value: string) {
|
|
81
|
+
return this.page.getByTestId(`grid.toolbar.${key}.${value}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
cellEditor() {
|
|
85
|
+
return this.page.getByTestId('grid.cell-editor').getByRole('textbox');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
rangeInList(a1Coords: string) {
|
|
89
|
+
return this.page.getByTestId('grid.range-list').getByText(a1Coords);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2021 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { expect, test, type Page } from '@playwright/test';
|
|
6
|
+
|
|
7
|
+
import { faker } from '@dxos/random';
|
|
8
|
+
import { setupPage, storybookUrl } from '@dxos/test-utils/playwright';
|
|
9
|
+
|
|
10
|
+
import { SheetManager } from './sheet-manager';
|
|
11
|
+
|
|
12
|
+
test.describe('plugin-sheet', () => {
|
|
13
|
+
let page: Page;
|
|
14
|
+
let sheet: SheetManager;
|
|
15
|
+
|
|
16
|
+
test.beforeEach(async ({ browser }) => {
|
|
17
|
+
const setup = await setupPage(browser, {
|
|
18
|
+
url: storybookUrl('plugins-plugin-sheet-sheetcontainer--spec'),
|
|
19
|
+
});
|
|
20
|
+
page = setup.page;
|
|
21
|
+
sheet = new SheetManager(page);
|
|
22
|
+
await sheet.ready();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test.afterEach(async () => {
|
|
26
|
+
await page.close();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('basic interactions', async () => {
|
|
30
|
+
// Cell editor should initially be hidden
|
|
31
|
+
await expect(sheet.cellEditor()).not.toBeVisible();
|
|
32
|
+
// Click on cell to focus it
|
|
33
|
+
await sheet.grid.cell(0, 0, 'grid').click();
|
|
34
|
+
// Cell editor should still be hidden
|
|
35
|
+
await expect(sheet.cellEditor()).not.toBeVisible();
|
|
36
|
+
// Click again to edit it
|
|
37
|
+
await sheet.grid.cell(0, 0, 'grid').click();
|
|
38
|
+
// Confirm editor displays
|
|
39
|
+
await expect(sheet.cellEditor()).toBeVisible();
|
|
40
|
+
// Type in a value and press enter
|
|
41
|
+
const testString = faker.string.uuid();
|
|
42
|
+
await sheet.setFocusedCellValue(testString, 'Enter');
|
|
43
|
+
// Expect that value to now show in the grid
|
|
44
|
+
await expect(sheet.cellByText(testString)).toBeVisible();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('functions, row deletion, indexed positions', async () => {
|
|
48
|
+
const firstNumber = 123;
|
|
49
|
+
const secondNumber = 789;
|
|
50
|
+
const thirdNumber = 567;
|
|
51
|
+
// Input numbers
|
|
52
|
+
await sheet.grid.cell(0, 2, 'grid').click();
|
|
53
|
+
await sheet.setFocusedCellValue(`${firstNumber}`, 'Enter');
|
|
54
|
+
await sheet.setFocusedCellValue(`${secondNumber}`, 'Enter');
|
|
55
|
+
await sheet.setFocusedCellValue(`${thirdNumber}`, 'Enter');
|
|
56
|
+
|
|
57
|
+
// Test range input
|
|
58
|
+
await sheet.press('Enter');
|
|
59
|
+
await sheet.fill('=SUM(');
|
|
60
|
+
await sheet.selectRange({ col: 0, row: 2, plane: 'grid' }, { col: 0, row: 4, plane: 'grid' });
|
|
61
|
+
await sheet.press(')');
|
|
62
|
+
await sheet.commit('Enter');
|
|
63
|
+
// Check sum
|
|
64
|
+
await expect(sheet.grid.cell(0, 5, 'grid')).toHaveText(`${firstNumber + secondNumber + thirdNumber}`);
|
|
65
|
+
// Delete row of second number
|
|
66
|
+
await sheet.deleteAxis('row', 3);
|
|
67
|
+
// Check sum again, it should be one cell up and reflect the updated range.
|
|
68
|
+
await expect(sheet.grid.cell(0, 4, 'grid')).toHaveText(`${firstNumber + thirdNumber}`);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('ranges', async () => {
|
|
72
|
+
await sheet.selectRange({ col: 1, row: 0, plane: 'grid' }, { col: 1, row: 1, plane: 'grid' });
|
|
73
|
+
await sheet.toolbarAction('alignment', 'center').click();
|
|
74
|
+
expect(await sheet.grid.cell(1, 0, 'grid')).toHaveAttribute('class', /text-center/);
|
|
75
|
+
expect(await sheet.grid.cell(1, 1, 'grid')).toHaveAttribute('class', /text-center/);
|
|
76
|
+
await expect(sheet.rangeInList('B1:B2')).toBeVisible();
|
|
77
|
+
});
|
|
78
|
+
});
|