@dxos/react-ui-editor 0.8.4-main.ef1bc66f44 → 0.8.4-main.effb148878
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/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/browser/index.mjs +796 -755
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +39 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +796 -755
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/translations.mjs +41 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/types/src/components/Editor/Editor.d.ts +36 -25
- package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
- package/dist/types/src/components/Editor/Editor.stories.d.ts +4 -4
- package/dist/types/src/components/Editor/Editor.stories.d.ts.map +1 -1
- package/dist/types/src/components/{EditorContent/EditorContent.d.ts → Editor/EditorView.d.ts} +5 -5
- package/dist/types/src/components/Editor/EditorView.d.ts.map +1 -0
- package/dist/types/src/components/Editor/controller.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts +1 -3
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts +2 -1
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts.map +1 -1
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts.map +1 -1
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +2 -2
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +4 -18
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +4 -18
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/headings.d.ts +4 -18
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/image.d.ts +3 -8
- package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/index.d.ts +1 -2
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/lists.d.ts +6 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/search.d.ts +3 -8
- package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/types.d.ts +6 -0
- package/dist/types/src/components/EditorToolbar/types.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +5 -19
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/Assistant.stories.d.ts +10 -0
- package/dist/types/src/extensions/Assistant.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/assistant-extension.d.ts +24 -0
- package/dist/types/src/extensions/assistant-extension.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +2 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useBasicMarkdownExtensions.d.ts +25 -0
- package/dist/types/src/hooks/useBasicMarkdownExtensions.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/stories/Automerge.stories.d.ts +25 -24
- package/dist/types/src/stories/Automerge.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Comments.stories.d.ts +2 -2
- package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/stories/EditorToolbar.stories.d.ts +28 -26
- package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Experimental.stories.d.ts +3 -3
- package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Markdown.stories.d.ts +2 -2
- package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Outliner.stories.d.ts +2 -2
- package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Popover.stories.d.ts +2 -2
- package/dist/types/src/stories/Popover.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Preview.stories.d.ts +2 -2
- package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Tags.stories.d.ts.map +1 -1
- package/dist/types/src/stories/TextEditor.stories.d.ts +2 -2
- package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Theme.stories.d.ts.map +1 -1
- package/dist/types/src/stories/components/EditorStory.d.ts +4 -4
- package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
- package/dist/types/src/stories/components/util.d.ts +3 -2
- package/dist/types/src/stories/components/util.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +24 -24
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/react.d.ts +2 -5
- package/dist/types/src/util/react.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +77 -68
- package/src/components/Editor/Editor.stories.tsx +15 -21
- package/src/components/Editor/Editor.tsx +54 -53
- package/src/components/Editor/EditorView.tsx +102 -0
- package/src/components/EditorMenuProvider/EditorMenuProvider.tsx +19 -24
- package/src/components/EditorMenuProvider/menu-presets.ts +1 -0
- package/src/components/EditorMenuProvider/popover.ts +3 -1
- package/src/components/EditorMenuProvider/useEditorMenu.ts +8 -1
- package/src/components/EditorPreviewProvider/EditorPreviewProvider.tsx +1 -1
- package/src/components/EditorToolbar/EditorToolbar.tsx +31 -65
- package/src/components/EditorToolbar/blocks.ts +54 -46
- package/src/components/EditorToolbar/formatting.ts +44 -45
- package/src/components/EditorToolbar/headings.ts +44 -50
- package/src/components/EditorToolbar/image.ts +16 -21
- package/src/components/EditorToolbar/index.ts +2 -3
- package/src/components/EditorToolbar/lists.ts +58 -0
- package/src/components/EditorToolbar/search.ts +16 -21
- package/src/components/EditorToolbar/types.ts +8 -0
- package/src/components/EditorToolbar/view-mode.ts +37 -43
- package/src/components/index.ts +0 -3
- package/src/extensions/Assistant.stories.tsx +112 -0
- package/src/extensions/assistant-extension.tsx +223 -0
- package/src/extensions/index.ts +5 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useBasicMarkdownExtensions.ts +55 -0
- package/src/index.ts +1 -4
- package/src/stories/Automerge.stories.tsx +18 -16
- package/src/stories/Comments.stories.tsx +6 -6
- package/src/stories/EditorToolbar.stories.tsx +37 -65
- package/src/stories/Experimental.stories.tsx +12 -12
- package/src/stories/Markdown.stories.tsx +2 -2
- package/src/stories/Outliner.stories.tsx +4 -5
- package/src/stories/Popover.stories.tsx +10 -11
- package/src/stories/Preview.stories.tsx +51 -43
- package/src/stories/Tags.stories.tsx +5 -5
- package/src/stories/TextEditor.stories.tsx +2 -2
- package/src/stories/Theme.stories.tsx +4 -4
- package/src/stories/components/EditorStory.tsx +19 -12
- package/src/stories/components/util.tsx +49 -50
- package/src/translations.ts +29 -24
- package/src/util/react.tsx +4 -13
- package/dist/types/src/components/EditorContent/EditorContent.d.ts.map +0 -1
- package/dist/types/src/components/EditorContent/controller.d.ts.map +0 -1
- package/dist/types/src/components/EditorContent/index.d.ts +0 -3
- package/dist/types/src/components/EditorContent/index.d.ts.map +0 -1
- package/dist/types/src/components/EditorToolbar/actions.d.ts +0 -24
- package/dist/types/src/components/EditorToolbar/actions.d.ts.map +0 -1
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts +0 -11
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts.map +0 -1
- package/dist/types/src/stories/CommandDialog.stories.d.ts +0 -14
- package/dist/types/src/stories/CommandDialog.stories.d.ts.map +0 -1
- package/src/components/EditorContent/EditorContent.tsx +0 -83
- package/src/components/EditorContent/index.ts +0 -6
- package/src/components/EditorToolbar/actions.ts +0 -87
- package/src/components/EditorToolbar/useEditorToolbar.ts +0 -20
- package/src/stories/CommandDialog.stories.tsx +0 -81
- /package/dist/types/src/components/{EditorContent → Editor}/controller.d.ts +0 -0
- /package/src/components/{EditorContent → Editor}/controller.ts +0 -0
|
@@ -2,26 +2,26 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Repo } from '@automerge/automerge-repo';
|
|
5
|
+
import { Repo, initSubduction } from '@automerge/automerge-repo';
|
|
6
6
|
import { BroadcastChannelNetworkAdapter } from '@automerge/automerge-repo-network-broadcastchannel';
|
|
7
7
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
8
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
9
9
|
|
|
10
|
-
import { Obj, Ref } from '@dxos/echo';
|
|
11
|
-
import { TestSchema } from '@dxos/echo/testing';
|
|
10
|
+
import { Obj, Query, Ref } from '@dxos/echo';
|
|
12
11
|
import { DocAccessor, createDocAccessor } from '@dxos/echo-db';
|
|
12
|
+
import { TestSchema } from '@dxos/echo/testing';
|
|
13
13
|
import { log } from '@dxos/log';
|
|
14
14
|
import { type Messenger } from '@dxos/protocols';
|
|
15
|
-
import {
|
|
15
|
+
import { useQuery, useSpace } from '@dxos/react-client/echo';
|
|
16
16
|
import { type Identity, useIdentity } from '@dxos/react-client/halo';
|
|
17
17
|
import { useClientStory, withMultiClientProvider } from '@dxos/react-client/testing';
|
|
18
18
|
import { Button, useThemeContext } from '@dxos/react-ui';
|
|
19
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
20
|
-
import { render } from '@dxos/storybook-utils';
|
|
19
|
+
import { withLayout, withTheme, Loading } from '@dxos/react-ui/testing';
|
|
21
20
|
import { createBasicExtensions, createDataExtensions, createThemeExtensions } from '@dxos/ui-editor';
|
|
22
21
|
|
|
22
|
+
import { translations } from '#translations';
|
|
23
|
+
|
|
23
24
|
import { useTextEditor } from '../hooks';
|
|
24
|
-
import { translations } from '../translations';
|
|
25
25
|
|
|
26
26
|
const initialContent = 'Hello world!';
|
|
27
27
|
|
|
@@ -44,14 +44,14 @@ const Editor = ({ source, messenger, identity, autoFocus }: EditorProps) => {
|
|
|
44
44
|
initialValue: DocAccessor.getValue(source),
|
|
45
45
|
extensions: [
|
|
46
46
|
createBasicExtensions({ placeholder: 'Type here...', search: true }),
|
|
47
|
-
createThemeExtensions({ themeMode, slots: {
|
|
47
|
+
createThemeExtensions({ themeMode, slots: { scroller: { className: 'p-2' } } }),
|
|
48
48
|
createDataExtensions({ id: 'test', text: source, messenger, identity }),
|
|
49
49
|
],
|
|
50
50
|
}),
|
|
51
51
|
[source, themeMode],
|
|
52
52
|
);
|
|
53
53
|
|
|
54
|
-
return <div ref={parentRef} className='flex
|
|
54
|
+
return <div ref={parentRef} className='flex w-full' />;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
const DefaultStory = () => {
|
|
@@ -60,6 +60,9 @@ const DefaultStory = () => {
|
|
|
60
60
|
|
|
61
61
|
useEffect(() => {
|
|
62
62
|
queueMicrotask(async () => {
|
|
63
|
+
// Subduction-fork `Repo` constructs a `MemorySigner` internally; WASM must be
|
|
64
|
+
// initialized first or the constructor throws `'set_subduction_logger' of undefined`.
|
|
65
|
+
await initSubduction();
|
|
63
66
|
const repo1 = new Repo({ network: [new BroadcastChannelNetworkAdapter()] });
|
|
64
67
|
const repo2 = new Repo({ network: [new BroadcastChannelNetworkAdapter()] });
|
|
65
68
|
|
|
@@ -77,11 +80,11 @@ const DefaultStory = () => {
|
|
|
77
80
|
}, []);
|
|
78
81
|
|
|
79
82
|
if (!object1 || !object2) {
|
|
80
|
-
return
|
|
83
|
+
return <Loading data={{ object1: !!object1, object2: !!object2 }} />;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
return (
|
|
84
|
-
<div className='
|
|
87
|
+
<div className='h-full w-full grid grid-cols-2 gap-4'>
|
|
85
88
|
<Editor source={object1} autoFocus />
|
|
86
89
|
<Editor source={object2} />
|
|
87
90
|
</div>
|
|
@@ -117,7 +120,7 @@ const EchoStory = () => {
|
|
|
117
120
|
}, [objects, source]);
|
|
118
121
|
|
|
119
122
|
return (
|
|
120
|
-
<div className='
|
|
123
|
+
<div className='h-full w-full flex flex-col overflow-hidden'>
|
|
121
124
|
<pre className='p-2 text-xs text-subdued'>
|
|
122
125
|
{JSON.stringify({ index, identity: identity?.identityKey.truncate(), spaceId, objects }, null, 2)}
|
|
123
126
|
</pre>
|
|
@@ -137,6 +140,7 @@ const EchoStory = () => {
|
|
|
137
140
|
const meta = {
|
|
138
141
|
title: 'ui/react-ui-editor/Automerge',
|
|
139
142
|
component: Editor as any,
|
|
143
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
140
144
|
parameters: {
|
|
141
145
|
layout: 'fullscreen',
|
|
142
146
|
translations,
|
|
@@ -149,14 +153,12 @@ type Story = StoryObj<typeof meta>;
|
|
|
149
153
|
|
|
150
154
|
// TODO(burdon): ERROR: factories.ts:126 Error: Non-base58 character
|
|
151
155
|
export const Default: Story = {
|
|
152
|
-
|
|
153
|
-
render: render(DefaultStory),
|
|
156
|
+
render: DefaultStory,
|
|
154
157
|
};
|
|
155
158
|
|
|
156
159
|
// TODO(burdon): Failing (doesn't sync)
|
|
157
160
|
export const WithEcho: Story = {
|
|
158
161
|
decorators: [
|
|
159
|
-
withTheme(),
|
|
160
162
|
withMultiClientProvider({
|
|
161
163
|
numClients: 2,
|
|
162
164
|
createIdentity: true,
|
|
@@ -171,5 +173,5 @@ export const WithEcho: Story = {
|
|
|
171
173
|
},
|
|
172
174
|
}),
|
|
173
175
|
],
|
|
174
|
-
render:
|
|
176
|
+
render: EchoStory,
|
|
175
177
|
};
|
|
@@ -9,18 +9,18 @@ import React, { type FC, useContext, useMemo } from 'react';
|
|
|
9
9
|
import { keySymbols, parseShortcut } from '@dxos/keyboard';
|
|
10
10
|
import { PublicKey } from '@dxos/keys';
|
|
11
11
|
import { log } from '@dxos/log';
|
|
12
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
12
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
13
13
|
import { withRegistry } from '@dxos/storybook-utils';
|
|
14
|
-
import {
|
|
14
|
+
import { annotations, comments, createExternalCommentSync } from '@dxos/ui-editor';
|
|
15
|
+
import { type Comment } from '@dxos/ui-editor/types';
|
|
15
16
|
|
|
16
17
|
import { createRenderer, str } from '../util';
|
|
17
|
-
|
|
18
18
|
import { EditorStory, content, longText } from './components';
|
|
19
19
|
|
|
20
20
|
const meta = {
|
|
21
21
|
title: 'ui/react-ui-editor/Comments',
|
|
22
22
|
component: EditorStory,
|
|
23
|
-
decorators: [withRegistry, withTheme()],
|
|
23
|
+
decorators: [withRegistry, withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
24
24
|
parameters: {
|
|
25
25
|
layout: 'fullscreen',
|
|
26
26
|
},
|
|
@@ -77,14 +77,14 @@ export const Comments: Story = {
|
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
const Key: FC<{ char: string }> = ({ char }) => (
|
|
80
|
-
<span className='flex justify-center items-center
|
|
80
|
+
<span className='flex justify-center items-center w-[24px] h-[24px] rounded-sm text-xs bg-neutral-200 text-black'>
|
|
81
81
|
{char}
|
|
82
82
|
</span>
|
|
83
83
|
);
|
|
84
84
|
|
|
85
85
|
const CommentTooltip: FC<{ shortcut: string }> = ({ shortcut }) => {
|
|
86
86
|
return (
|
|
87
|
-
<div className='flex items-center gap-2
|
|
87
|
+
<div className='flex items-center gap-2 px-2 py-2 bg-neutral-700 text-white text-xs rounded-sm'>
|
|
88
88
|
<div>Create comment</div>
|
|
89
89
|
<div className='flex gap-1'>
|
|
90
90
|
{keySymbols(parseShortcut(shortcut)).map((char) => (
|
|
@@ -2,96 +2,68 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { RegistryContext, useAtomValue } from '@effect-atom/atom-react';
|
|
6
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
7
|
-
import React, {
|
|
6
|
+
import React, { useMemo } from 'react';
|
|
8
7
|
|
|
9
|
-
import { invariant } from '@dxos/invariant';
|
|
10
8
|
import { useThemeContext } from '@dxos/react-ui';
|
|
11
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
9
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
10
|
import { withRegistry } from '@dxos/storybook-utils';
|
|
13
11
|
import {
|
|
14
|
-
type EditorInputMode,
|
|
15
|
-
type EditorViewMode,
|
|
16
|
-
InputModeExtensions,
|
|
17
12
|
createBasicExtensions,
|
|
18
13
|
createMarkdownExtensions,
|
|
19
14
|
createThemeExtensions,
|
|
20
15
|
decorateMarkdown,
|
|
21
|
-
|
|
16
|
+
documentSlots,
|
|
22
17
|
formattingKeymap,
|
|
23
|
-
formattingListener,
|
|
24
18
|
} from '@dxos/ui-editor';
|
|
25
|
-
import {
|
|
19
|
+
import { type EditorViewMode } from '@dxos/ui-editor/types';
|
|
26
20
|
|
|
27
|
-
import {
|
|
28
|
-
import { type UseTextEditorProps, useTextEditor } from '../hooks';
|
|
29
|
-
import { translations } from '../translations';
|
|
21
|
+
import { translations } from '#translations';
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
import { Editor } from '../components';
|
|
24
|
+
import { type UseTextEditorProps } from '../hooks';
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
const { themeMode } = useThemeContext();
|
|
35
|
-
const registry = useContext(RegistryContext);
|
|
36
|
-
|
|
37
|
-
const toolbarState = useEditorToolbar({ viewMode: 'source' });
|
|
38
|
-
const { viewMode } = useAtomValue(toolbarState);
|
|
39
|
-
|
|
40
|
-
const updateToolbarState = useCallback(
|
|
41
|
-
(formatting: EditorToolbarState) => {
|
|
42
|
-
registry.update(toolbarState, (state) => ({ ...state, ...formatting }));
|
|
43
|
-
},
|
|
44
|
-
[registry, toolbarState],
|
|
45
|
-
);
|
|
26
|
+
type DefaultStoryProps = { placeholder?: string; viewMode?: EditorViewMode } & UseTextEditorProps;
|
|
46
27
|
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
const { parentRef, view } = useTextEditor(
|
|
50
|
-
() => ({
|
|
51
|
-
autoFocus,
|
|
52
|
-
initialValue,
|
|
53
|
-
selectionEnd: true,
|
|
54
|
-
extensions: [
|
|
55
|
-
editorInputMode ? InputModeExtensions[editorInputMode] : [],
|
|
56
|
-
createBasicExtensions({ placeholder, lineWrapping: true, readOnly: viewMode === 'readonly', search: true }),
|
|
57
|
-
createMarkdownExtensions(),
|
|
58
|
-
createThemeExtensions({ themeMode, syntaxHighlighting: true }),
|
|
59
|
-
viewMode === 'source' ? [] : decorateMarkdown(),
|
|
60
|
-
formattingKeymap(),
|
|
61
|
-
formattingListener(updateToolbarState),
|
|
62
|
-
],
|
|
63
|
-
}),
|
|
64
|
-
[editorInputMode, viewMode, themeMode, placeholder],
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
const getView = useCallback(() => {
|
|
68
|
-
invariant(view);
|
|
69
|
-
return view;
|
|
70
|
-
}, [view]);
|
|
28
|
+
const DefaultStory = ({ autoFocus, initialValue, placeholder, viewMode = 'source' }: DefaultStoryProps) => {
|
|
29
|
+
const { themeMode } = useThemeContext();
|
|
71
30
|
|
|
72
|
-
const
|
|
73
|
-
(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
31
|
+
const extensions = useMemo(
|
|
32
|
+
() => [
|
|
33
|
+
createBasicExtensions({
|
|
34
|
+
placeholder,
|
|
35
|
+
lineWrapping: true,
|
|
36
|
+
readOnly: viewMode === 'readonly',
|
|
37
|
+
search: true,
|
|
38
|
+
}),
|
|
39
|
+
createThemeExtensions({
|
|
40
|
+
themeMode,
|
|
41
|
+
syntaxHighlighting: true,
|
|
42
|
+
slots: documentSlots,
|
|
43
|
+
}),
|
|
44
|
+
createMarkdownExtensions(),
|
|
45
|
+
viewMode === 'source' ? [] : decorateMarkdown(),
|
|
46
|
+
formattingKeymap(),
|
|
47
|
+
],
|
|
48
|
+
[viewMode, themeMode, placeholder],
|
|
77
49
|
);
|
|
78
50
|
|
|
79
|
-
// TODO(marijn): This doesn't update the state on view changes.
|
|
80
|
-
// Also not sure if view is even guaranteed to exist at this point.
|
|
81
51
|
return (
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<div className=
|
|
86
|
-
|
|
87
|
-
|
|
52
|
+
<Editor.Root extensions={extensions} viewMode={viewMode}>
|
|
53
|
+
<Editor.Content>
|
|
54
|
+
<Editor.Toolbar classNames='dx-document' />
|
|
55
|
+
<div className='dx-container dx-document bg-base-surface'>
|
|
56
|
+
<Editor.View autoFocus={autoFocus} initialValue={initialValue} selectionEnd />
|
|
57
|
+
</div>
|
|
58
|
+
</Editor.Content>
|
|
59
|
+
</Editor.Root>
|
|
88
60
|
);
|
|
89
61
|
};
|
|
90
62
|
|
|
91
63
|
const meta = {
|
|
92
64
|
title: 'ui/react-ui-editor/EditorToolbar',
|
|
93
65
|
render: DefaultStory,
|
|
94
|
-
decorators: [withRegistry, withTheme()],
|
|
66
|
+
decorators: [withRegistry, withTheme(), withLayout({ layout: 'fullscreen', classNames: 'bg-sidebar-surface' })],
|
|
95
67
|
parameters: {
|
|
96
68
|
layout: 'fullscreen',
|
|
97
69
|
translations,
|
|
@@ -7,16 +7,16 @@ import defaultsDeep from 'lodash.defaultsdeep';
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
|
-
import {
|
|
11
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
12
|
-
import { blast, defaultOptions, dropFile, join,
|
|
10
|
+
import { random } from '@dxos/random';
|
|
11
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
|
+
import { blast, defaultOptions, dropFile, join, snippets } from '@dxos/ui-editor';
|
|
13
13
|
|
|
14
14
|
import { EditorStory, content } from './components';
|
|
15
15
|
|
|
16
16
|
const meta = {
|
|
17
17
|
title: 'ui/react-ui-editor/Experimental',
|
|
18
18
|
component: EditorStory,
|
|
19
|
-
decorators: [withTheme()],
|
|
19
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
20
20
|
parameters: {
|
|
21
21
|
layout: 'fullscreen',
|
|
22
22
|
},
|
|
@@ -27,16 +27,16 @@ export default meta;
|
|
|
27
27
|
type Story = StoryObj<typeof meta>;
|
|
28
28
|
|
|
29
29
|
//
|
|
30
|
-
//
|
|
30
|
+
// Snippets
|
|
31
31
|
//
|
|
32
32
|
|
|
33
|
-
const
|
|
33
|
+
const snippetItems = localStorage.getItem('org.dxos.testing.snippets')?.split(',');
|
|
34
34
|
|
|
35
|
-
export const
|
|
35
|
+
export const Snippets: Story = {
|
|
36
36
|
render: () => (
|
|
37
37
|
<EditorStory
|
|
38
|
-
text={join('#
|
|
39
|
-
extensions={[
|
|
38
|
+
text={join('# Snippets', '', content.paragraphs, content.footer)}
|
|
39
|
+
extensions={[snippets({ items: snippetItems })]}
|
|
40
40
|
/>
|
|
41
41
|
),
|
|
42
42
|
};
|
|
@@ -50,15 +50,15 @@ export const Blast: Story = {
|
|
|
50
50
|
<EditorStory
|
|
51
51
|
text={join('# Blast', '', content.paragraphs, content.codeblocks, content.paragraphs)}
|
|
52
52
|
extensions={[
|
|
53
|
-
|
|
53
|
+
snippets({ items: snippetItems }),
|
|
54
54
|
blast(
|
|
55
55
|
defaultsDeep(
|
|
56
56
|
{
|
|
57
57
|
effect: 2,
|
|
58
58
|
particleGravity: 0.2,
|
|
59
59
|
particleShrinkRate: 0.995,
|
|
60
|
-
color: () => [
|
|
61
|
-
// color: () => [
|
|
60
|
+
color: () => [random.number.int({ min: 100, max: 200 }), 0, 0],
|
|
61
|
+
// color: () => [random.number.int(256), random.number.int(256), random.number.int(256)],
|
|
62
62
|
},
|
|
63
63
|
defaultOptions,
|
|
64
64
|
),
|
|
@@ -6,7 +6,7 @@ import { markdown } from '@codemirror/lang-markdown';
|
|
|
6
6
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
7
7
|
import React from 'react';
|
|
8
8
|
|
|
9
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
9
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
10
10
|
import { decorateMarkdown, image, join, linkTooltip, table } from '@dxos/ui-editor';
|
|
11
11
|
|
|
12
12
|
import { EditorStory, content, defaultExtensions, headings, renderLinkTooltip, text } from './components';
|
|
@@ -14,7 +14,7 @@ import { EditorStory, content, defaultExtensions, headings, renderLinkTooltip, t
|
|
|
14
14
|
const meta = {
|
|
15
15
|
title: 'ui/react-ui-editor/Markdown',
|
|
16
16
|
component: EditorStory,
|
|
17
|
-
decorators: [withTheme()],
|
|
17
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
18
18
|
parameters: {
|
|
19
19
|
layout: 'fullscreen',
|
|
20
20
|
},
|
|
@@ -5,19 +5,18 @@
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
6
|
import React, { useMemo, useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
9
8
|
import { withAttention } from '@dxos/react-ui-attention/testing';
|
|
9
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
10
10
|
import { deleteItem, hashtag, join, listItemToString, outliner, treeFacet } from '@dxos/ui-editor';
|
|
11
11
|
|
|
12
12
|
import { type EditorController, type EditorMenuGroup, EditorMenuProvider } from '../components';
|
|
13
|
-
|
|
14
13
|
import { EditorStory } from './components';
|
|
15
14
|
|
|
16
|
-
type
|
|
15
|
+
type DefaultStoryProps = {
|
|
17
16
|
text?: string;
|
|
18
17
|
};
|
|
19
18
|
|
|
20
|
-
const DefaultStory = ({ text }:
|
|
19
|
+
const DefaultStory = ({ text }: DefaultStoryProps) => {
|
|
21
20
|
const [controller, setController] = useState<EditorController | null>(null);
|
|
22
21
|
|
|
23
22
|
const extensions = useMemo(() => [outliner(), hashtag()], []);
|
|
@@ -68,7 +67,7 @@ const DefaultStory = ({ text }: StoryProps) => {
|
|
|
68
67
|
const meta = {
|
|
69
68
|
title: 'ui/react-ui-editor/Outliner',
|
|
70
69
|
render: DefaultStory,
|
|
71
|
-
decorators: [withTheme(), withAttention()],
|
|
70
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' }), withAttention()],
|
|
72
71
|
parameters: {
|
|
73
72
|
layout: 'fullscreen',
|
|
74
73
|
},
|
|
@@ -6,9 +6,9 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React, { useCallback, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { Obj, Query } from '@dxos/echo';
|
|
9
|
-
import {
|
|
9
|
+
import { random } from '@dxos/random';
|
|
10
10
|
import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
|
|
11
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
11
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
12
|
import { TestSchema, type ValueGenerator, createObjectFactory } from '@dxos/schema/testing';
|
|
13
13
|
import { Domino, mx } from '@dxos/ui';
|
|
14
14
|
import { insertAtCursor, insertAtLineStart, join } from '@dxos/ui-editor';
|
|
@@ -25,10 +25,9 @@ import {
|
|
|
25
25
|
linkSlashCommands,
|
|
26
26
|
useEditorMenu,
|
|
27
27
|
} from '../components';
|
|
28
|
-
|
|
29
28
|
import { EditorStory } from './components';
|
|
30
29
|
|
|
31
|
-
const generator: ValueGenerator =
|
|
30
|
+
const generator: ValueGenerator = random as any;
|
|
32
31
|
|
|
33
32
|
const customCompletions: EditorMenuGroup = createMenuGroup({
|
|
34
33
|
id: 'test',
|
|
@@ -38,15 +37,15 @@ const customCompletions: EditorMenuGroup = createMenuGroup({
|
|
|
38
37
|
const placeholder = (trigger: string[]) => {
|
|
39
38
|
const pressEl = Domino.of('span').text('Press');
|
|
40
39
|
const triggerEls = trigger.map((trigger) =>
|
|
41
|
-
Domino.of('span').classNames(mx('border border-separator rounded-
|
|
40
|
+
Domino.of('span').classNames(mx('border border-separator rounded-xs mx-1 px-1 py-[2px] pb-[3px]')).text(trigger),
|
|
42
41
|
);
|
|
43
42
|
const forCommandsEl = Domino.of('span').text('for commands');
|
|
44
|
-
return Domino.of('div').
|
|
43
|
+
return Domino.of('div').append(pressEl, ...triggerEls, forCommandsEl).root;
|
|
45
44
|
};
|
|
46
45
|
|
|
47
|
-
type
|
|
46
|
+
type DefaultStoryProps = Omit<UseEditorMenuProps, 'viewRef'> & { text: string };
|
|
48
47
|
|
|
49
|
-
const DefaultStory = ({ text, ...props }:
|
|
48
|
+
const DefaultStory = ({ text, ...props }: DefaultStoryProps) => {
|
|
50
49
|
const [controller, setController] = useState<EditorController | null>(null);
|
|
51
50
|
const { groupsRef, extension, ...menuProps } = useEditorMenu(props);
|
|
52
51
|
|
|
@@ -57,7 +56,7 @@ const DefaultStory = ({ text, ...props }: StoryProps) => {
|
|
|
57
56
|
);
|
|
58
57
|
};
|
|
59
58
|
|
|
60
|
-
const LinkStory = (args:
|
|
59
|
+
const LinkStory = (args: DefaultStoryProps) => {
|
|
61
60
|
const { space } = useClientStory();
|
|
62
61
|
|
|
63
62
|
const getMenu = useCallback<NonNullable<UseEditorMenuProps['getMenu']>>(
|
|
@@ -82,7 +81,7 @@ const LinkStory = (args: StoryProps) => {
|
|
|
82
81
|
label: object.name,
|
|
83
82
|
icon: 'ph--user--regular',
|
|
84
83
|
onSelect: ({ view, head }) => {
|
|
85
|
-
const link = `[${object.name}](${Obj.
|
|
84
|
+
const link = `[${object.name}](${Obj.getURI(object)})`;
|
|
86
85
|
if (text?.startsWith('@')) {
|
|
87
86
|
insertAtLineStart(view, head, `!${link}\n`);
|
|
88
87
|
} else {
|
|
@@ -103,7 +102,7 @@ const LinkStory = (args: StoryProps) => {
|
|
|
103
102
|
const meta = {
|
|
104
103
|
title: 'ui/react-ui-editor/Popover',
|
|
105
104
|
render: DefaultStory,
|
|
106
|
-
decorators: [withTheme()],
|
|
105
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
107
106
|
parameters: {
|
|
108
107
|
layout: 'fullscreen',
|
|
109
108
|
},
|
|
@@ -9,10 +9,10 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
|
9
9
|
import { createPortal } from 'react-dom';
|
|
10
10
|
|
|
11
11
|
import { invariant } from '@dxos/invariant';
|
|
12
|
-
import {
|
|
13
|
-
import { Popover } from '@dxos/react-ui';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
12
|
+
import { random } from '@dxos/random';
|
|
13
|
+
import { Card, Popover, Toolbar } from '@dxos/react-ui';
|
|
14
|
+
import { Menu, createMenuAction } from '@dxos/react-ui-menu';
|
|
15
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
16
16
|
import {
|
|
17
17
|
type PreviewBlock,
|
|
18
18
|
type PreviewLinkRef,
|
|
@@ -22,16 +22,15 @@ import {
|
|
|
22
22
|
preview,
|
|
23
23
|
} from '@dxos/ui-editor';
|
|
24
24
|
import { hoverableControls } from '@dxos/ui-theme';
|
|
25
|
-
import {
|
|
25
|
+
import { trim } from '@dxos/util';
|
|
26
26
|
|
|
27
27
|
import { type EditorController, EditorPreviewProvider, useEditorPreview } from '../components';
|
|
28
|
-
|
|
29
28
|
import { EditorStory } from './components';
|
|
30
29
|
|
|
31
30
|
const handlePreviewLookup = async ({ dxn, label }: PreviewLinkRef): Promise<PreviewLinkTarget> => {
|
|
32
31
|
// Random text.
|
|
33
|
-
|
|
34
|
-
const text = Array.from({ length: 2 }, () =>
|
|
32
|
+
random.seed(dxn.split('').reduce((acc: number, char: string) => acc + char.charCodeAt(0), 1));
|
|
33
|
+
const text = Array.from({ length: 2 }, () => random.lorem.paragraphs()).join('\n\n');
|
|
35
34
|
return {
|
|
36
35
|
label,
|
|
37
36
|
text,
|
|
@@ -58,15 +57,15 @@ const PreviewCard = () => {
|
|
|
58
57
|
return (
|
|
59
58
|
<Popover.Portal>
|
|
60
59
|
<Popover.Content onOpenAutoFocus={(event) => event.preventDefault()}>
|
|
61
|
-
<Popover.Viewport classNames='
|
|
60
|
+
<Popover.Viewport classNames='dx-card-popover-width'>
|
|
62
61
|
<Card.Root border={false}>
|
|
63
|
-
<Card.
|
|
64
|
-
<Card.Icon
|
|
62
|
+
<Card.Header>
|
|
63
|
+
<Card.Icon icon='ph--file-text--regular' />
|
|
65
64
|
<Card.Title>{target.label}</Card.Title>
|
|
66
65
|
<Popover.Close asChild>
|
|
67
|
-
<Card.
|
|
66
|
+
<Card.ActionIconButton action='close' />
|
|
68
67
|
</Popover.Close>
|
|
69
|
-
</Card.
|
|
68
|
+
</Card.Header>
|
|
70
69
|
<Card.Row>
|
|
71
70
|
<Card.Text variant='description'>{target.text}</Card.Text>
|
|
72
71
|
</Card.Row>
|
|
@@ -144,36 +143,45 @@ const PreviewBlockComponent = ({ link, el, view }: { link: PreviewLinkRef; el: H
|
|
|
144
143
|
}
|
|
145
144
|
}, [handleAction, link, target]);
|
|
146
145
|
|
|
146
|
+
const menuItems = useMemo(
|
|
147
|
+
() => [
|
|
148
|
+
createMenuAction('delete', handleDelete, {
|
|
149
|
+
label: link.suggest ? 'Discard' : 'Delete',
|
|
150
|
+
icon: 'ph--x--regular',
|
|
151
|
+
}),
|
|
152
|
+
...(target
|
|
153
|
+
? [
|
|
154
|
+
createMenuAction('apply', handleInsert, {
|
|
155
|
+
label: 'Apply',
|
|
156
|
+
icon: 'ph--check--regular',
|
|
157
|
+
}),
|
|
158
|
+
]
|
|
159
|
+
: []),
|
|
160
|
+
],
|
|
161
|
+
[handleDelete, handleInsert, link.suggest, target],
|
|
162
|
+
);
|
|
163
|
+
|
|
147
164
|
return createPortal(
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
<Card.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
/>
|
|
169
|
-
</Card.Toolbar>
|
|
170
|
-
)}
|
|
171
|
-
{target && (
|
|
172
|
-
<Card.Row>
|
|
173
|
-
<Card.Text className='text-description'>{target.text}</Card.Text>
|
|
174
|
-
</Card.Row>
|
|
175
|
-
)}
|
|
176
|
-
</Card.Root>,
|
|
165
|
+
<Menu.Root>
|
|
166
|
+
<Card.Root classNames={hoverableControls}>
|
|
167
|
+
{!view?.state.readOnly && (
|
|
168
|
+
<Card.Header>
|
|
169
|
+
<Card.Icon icon='ph--bookmark--regular' />
|
|
170
|
+
<Card.Title>{link.label}</Card.Title>
|
|
171
|
+
{/* TODO(wittjosiah): Reconcile with Card.Menu. */}
|
|
172
|
+
<Menu.Trigger asChild disabled={!menuItems?.length}>
|
|
173
|
+
<Toolbar.IconButton iconOnly variant='ghost' icon='ph--dots-three-vertical--regular' label='Menu' />
|
|
174
|
+
</Menu.Trigger>
|
|
175
|
+
<Menu.Content items={menuItems} />
|
|
176
|
+
</Card.Header>
|
|
177
|
+
)}
|
|
178
|
+
{target && (
|
|
179
|
+
<Card.Row>
|
|
180
|
+
<Card.Text className='text-description'>{target.text}</Card.Text>
|
|
181
|
+
</Card.Row>
|
|
182
|
+
)}
|
|
183
|
+
</Card.Root>
|
|
184
|
+
</Menu.Root>,
|
|
177
185
|
el,
|
|
178
186
|
);
|
|
179
187
|
};
|
|
@@ -181,7 +189,7 @@ const PreviewBlockComponent = ({ link, el, view }: { link: PreviewLinkRef; el: H
|
|
|
181
189
|
const meta = {
|
|
182
190
|
title: 'ui/react-ui-editor/Preview',
|
|
183
191
|
component: EditorStory,
|
|
184
|
-
decorators: [withTheme()],
|
|
192
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
185
193
|
parameters: {
|
|
186
194
|
layout: 'fullscreen',
|
|
187
195
|
},
|
|
@@ -7,7 +7,7 @@ import React, { useEffect, useState } from 'react';
|
|
|
7
7
|
import { createPortal } from 'react-dom';
|
|
8
8
|
|
|
9
9
|
import { useThemeContext } from '@dxos/react-ui';
|
|
10
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
10
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
11
|
import {
|
|
12
12
|
type XmlWidgetRegistry,
|
|
13
13
|
type XmlWidgetState,
|
|
@@ -25,7 +25,7 @@ const registry = {
|
|
|
25
25
|
/**
|
|
26
26
|
* Custom tag: <test/>
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
test: {
|
|
29
29
|
block: true,
|
|
30
30
|
Component: ({ start = '0' }) => {
|
|
31
31
|
const [count, setCount] = useState<number>(safeParseInt(start, 0));
|
|
@@ -43,7 +43,7 @@ const registry = {
|
|
|
43
43
|
return () => clearInterval(interval);
|
|
44
44
|
}, []);
|
|
45
45
|
|
|
46
|
-
return <div className='p-2 border border-separator rounded'>Test {count}</div>;
|
|
46
|
+
return <div className='p-2 border border-separator rounded-sm'>Test {count}</div>;
|
|
47
47
|
},
|
|
48
48
|
},
|
|
49
49
|
} satisfies XmlWidgetRegistry;
|
|
@@ -64,7 +64,7 @@ const DefaultStory = ({ text }: { text?: string }) => {
|
|
|
64
64
|
|
|
65
65
|
return (
|
|
66
66
|
<>
|
|
67
|
-
<div ref={parentRef} className='
|
|
67
|
+
<div ref={parentRef} className='w-full p-4' />
|
|
68
68
|
{widgets.map(({ id, root, Component, props }) => (
|
|
69
69
|
<div key={id}>{createPortal(<Component {...props} />, root)}</div>
|
|
70
70
|
))}
|
|
@@ -87,7 +87,7 @@ const text = trim`
|
|
|
87
87
|
const meta = {
|
|
88
88
|
title: 'ui/react-ui-editor/Tags',
|
|
89
89
|
render: DefaultStory,
|
|
90
|
-
decorators: [withTheme()],
|
|
90
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
91
91
|
parameters: {
|
|
92
92
|
layout: 'fullscreen',
|
|
93
93
|
},
|