@dxos/react-ui-editor 0.4.2-main.da7c8c5 → 0.4.2-main.ec5936e

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.
Files changed (49) hide show
  1. package/dist/lib/browser/index.mjs +440 -326
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +24 -1
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  7. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +20 -0
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/TextEditor/automerge.stories.d.ts +22 -2
  10. package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/TextEditor/hooks.stories.d.ts +20 -0
  12. package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -1
  13. package/dist/types/src/components/Toolbar/Toolbar.d.ts +7 -10
  14. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  15. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +23 -6
  16. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  17. package/dist/types/src/extensions/annotations.d.ts +6 -0
  18. package/dist/types/src/extensions/annotations.d.ts.map +1 -0
  19. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  20. package/dist/types/src/extensions/automerge/{semaphore.d.ts → sync.d.ts} +6 -5
  21. package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -0
  22. package/dist/types/src/extensions/index.d.ts +1 -0
  23. package/dist/types/src/extensions/index.d.ts.map +1 -1
  24. package/dist/types/src/index.d.ts +1 -1
  25. package/dist/types/src/index.d.ts.map +1 -1
  26. package/dist/types/src/styles/index.d.ts +1 -0
  27. package/dist/types/src/styles/index.d.ts.map +1 -1
  28. package/dist/types/src/styles/layout.d.ts +2 -0
  29. package/dist/types/src/styles/layout.d.ts.map +1 -0
  30. package/dist/types/src/translations.d.ts +20 -0
  31. package/dist/types/src/translations.d.ts.map +1 -0
  32. package/package.json +24 -24
  33. package/src/components/TextEditor/MarkdownEditor.stories.tsx +20 -10
  34. package/src/components/TextEditor/TextEditor.stories.tsx +11 -8
  35. package/src/components/TextEditor/TextEditor.tsx +4 -3
  36. package/src/components/TextEditor/automerge.stories.tsx +40 -50
  37. package/src/components/TextEditor/hooks.stories.tsx +15 -16
  38. package/src/components/Toolbar/Toolbar.stories.tsx +17 -13
  39. package/src/components/Toolbar/Toolbar.tsx +156 -129
  40. package/src/extensions/annotations.ts +78 -0
  41. package/src/extensions/automerge/automerge.ts +5 -21
  42. package/src/extensions/automerge/{semaphore.ts → sync.ts} +32 -34
  43. package/src/extensions/index.ts +1 -0
  44. package/src/hooks/useTextModel.ts +5 -5
  45. package/src/index.ts +1 -1
  46. package/src/styles/index.ts +1 -0
  47. package/src/styles/layout.ts +6 -0
  48. package/src/translations.ts +25 -0
  49. package/dist/types/src/extensions/automerge/semaphore.d.ts.map +0 -1
@@ -1,3 +1,4 @@
1
+ export * from './annotations';
1
2
  export * from './autocomplete';
2
3
  export * from './automerge';
3
4
  export * from './awareness';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extensions/index.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extensions/index.ts"],"names":[],"mappings":"AAIA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
@@ -5,7 +5,7 @@ export { type EditorView, keymap } from '@codemirror/view';
5
5
  export * from './components';
6
6
  export * from './extensions';
7
7
  export * from './hooks';
8
- export { getToken } from './styles';
8
+ export { getToken, editorWithToolbarLayout } from './styles';
9
9
  export * from './themes';
10
10
  export * from './util';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,4CAA4C,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE3D,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,4CAA4C,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE3D,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAC7D,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from './cursors';
2
2
  export * from './markdown';
3
3
  export * from './tokens';
4
+ export * from './layout';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/styles/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/styles/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const editorWithToolbarLayout = "fixed inset-0 grid grid-cols-1 grid-rows-[min-content_1fr] justify-center content-start overflow-hidden";
2
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../src/styles/layout.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,4GACuE,CAAC"}
@@ -0,0 +1,20 @@
1
+ export declare const translationKey = "react-ui-editor";
2
+ declare const _default: {
3
+ 'en-US': {
4
+ "react-ui-editor": {
5
+ 'strong label': string;
6
+ 'emphasis label': string;
7
+ 'strikethrough label': string;
8
+ 'code label': string;
9
+ 'bullet label': string;
10
+ 'ordered label': string;
11
+ 'task label': string;
12
+ 'blockquote label': string;
13
+ 'codeblock label': string;
14
+ 'comment label': string;
15
+ 'heading label': string;
16
+ };
17
+ };
18
+ }[];
19
+ export default _default;
20
+ //# sourceMappingURL=translations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../src/translations.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,oBAAoB,CAAC;;;;;;;;;;;;;;;;;;AAEhD,wBAkBE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-editor",
3
- "version": "0.4.2-main.da7c8c5",
3
+ "version": "0.4.2-main.ec5936e",
4
4
  "description": "Document editing experience within a DXOS shell.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -36,20 +36,20 @@
36
36
  "lodash.pick": "^4.4.0",
37
37
  "lodash.sortby": "^4.7.0",
38
38
  "style-mod": "^4.1.0",
39
- "@dxos/context": "0.4.2-main.da7c8c5",
40
- "@dxos/async": "0.4.2-main.da7c8c5",
41
- "@dxos/automerge": "0.4.2-main.da7c8c5",
42
- "@dxos/debug": "0.4.2-main.da7c8c5",
43
- "@dxos/display-name": "0.4.2-main.da7c8c5",
44
- "@dxos/echo-schema": "0.4.2-main.da7c8c5",
45
- "@dxos/invariant": "0.4.2-main.da7c8c5",
46
- "@dxos/log": "0.4.2-main.da7c8c5",
47
- "@dxos/react-async": "0.4.2-main.da7c8c5",
48
- "@dxos/protocols": "0.4.2-main.da7c8c5",
49
- "@dxos/react-ui": "0.4.2-main.da7c8c5",
50
- "@dxos/react-ui-theme": "0.4.2-main.da7c8c5",
51
- "@dxos/text-model": "0.4.2-main.da7c8c5",
52
- "@dxos/util": "0.4.2-main.da7c8c5"
39
+ "@dxos/async": "0.4.2-main.ec5936e",
40
+ "@dxos/display-name": "0.4.2-main.ec5936e",
41
+ "@dxos/context": "0.4.2-main.ec5936e",
42
+ "@dxos/debug": "0.4.2-main.ec5936e",
43
+ "@dxos/automerge": "0.4.2-main.ec5936e",
44
+ "@dxos/echo-schema": "0.4.2-main.ec5936e",
45
+ "@dxos/invariant": "0.4.2-main.ec5936e",
46
+ "@dxos/protocols": "0.4.2-main.ec5936e",
47
+ "@dxos/log": "0.4.2-main.ec5936e",
48
+ "@dxos/react-async": "0.4.2-main.ec5936e",
49
+ "@dxos/react-ui-theme": "0.4.2-main.ec5936e",
50
+ "@dxos/text-model": "0.4.2-main.ec5936e",
51
+ "@dxos/util": "0.4.2-main.ec5936e",
52
+ "@dxos/react-ui": "0.4.2-main.ec5936e"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@automerge/automerge-repo-network-broadcastchannel": "^1.1.0",
@@ -76,20 +76,20 @@
76
76
  "vite-plugin-top-level-await": "^1.4.1",
77
77
  "vite-plugin-wasm": "^3.3.0",
78
78
  "vitest": "^1.2.1",
79
- "@dxos/echo-signals": "0.4.2-main.da7c8c5",
80
- "@dxos/config": "0.4.2-main.da7c8c5",
81
- "@dxos/echo-typegen": "0.4.2-main.da7c8c5",
82
- "@dxos/keyboard": "0.4.2-main.da7c8c5",
83
- "@dxos/react-client": "0.4.2-main.da7c8c5",
84
- "@dxos/storybook-utils": "0.4.2-main.da7c8c5",
85
- "@dxos/react-ui": "0.4.2-main.da7c8c5",
86
- "@dxos/random": "0.4.2-main.da7c8c5"
79
+ "@dxos/config": "0.4.2-main.ec5936e",
80
+ "@dxos/echo-signals": "0.4.2-main.ec5936e",
81
+ "@dxos/echo-typegen": "0.4.2-main.ec5936e",
82
+ "@dxos/keyboard": "0.4.2-main.ec5936e",
83
+ "@dxos/random": "0.4.2-main.ec5936e",
84
+ "@dxos/react-client": "0.4.2-main.ec5936e",
85
+ "@dxos/react-ui": "0.4.2-main.ec5936e",
86
+ "@dxos/storybook-utils": "0.4.2-main.ec5936e"
87
87
  },
88
88
  "peerDependencies": {
89
89
  "@phosphor-icons/react": "^2.0.5",
90
90
  "react": "^18.2.0",
91
91
  "react-dom": "^18.2.0",
92
- "@dxos/react-client": "0.4.2-main.da7c8c5"
92
+ "@dxos/react-client": "0.4.2-main.ec5936e"
93
93
  },
94
94
  "publishConfig": {
95
95
  "access": "public"
@@ -14,7 +14,7 @@ import { TextObject } from '@dxos/echo-schema';
14
14
  import { keySymbols, parseShortcut } from '@dxos/keyboard';
15
15
  import { PublicKey } from '@dxos/keys';
16
16
  import { faker } from '@dxos/random';
17
- import { fixedInsetFlexLayout, getSize, groupSurface, mx } from '@dxos/react-ui-theme';
17
+ import { getSize, mx, textBlockWidth } from '@dxos/react-ui-theme';
18
18
  import { withTheme } from '@dxos/storybook-utils';
19
19
 
20
20
  import { MarkdownEditor, type TextEditorProps } from './TextEditor';
@@ -36,8 +36,10 @@ import {
36
36
  typewriter,
37
37
  useComments,
38
38
  formatting,
39
+ annotations,
39
40
  } from '../../extensions';
40
41
  import { type Comment, useTextModel } from '../../hooks';
42
+ import translations from '../../translations';
41
43
 
42
44
  faker.seed(101);
43
45
 
@@ -110,7 +112,7 @@ const text = {
110
112
  `| ${num().padStart(12)} | ${num().padStart(12)} | ${num().padStart(12)} |`,
111
113
  `| ${num().padStart(12)} | ${num().padStart(12)} | ${num().padStart(12)} |`,
112
114
  `| ${num().padStart(12)} | ${num().padStart(12)} | ${num().padStart(12)} |`,
113
- '', // TODO(burdon): Possible GFM parsing bug if no newline?
115
+ '',
114
116
  ),
115
117
 
116
118
  image: str('# Image', '', '![dxos](https://pbs.twimg.com/profile_banners/1268328127673044992/1684766689/1500x500)'),
@@ -211,7 +213,7 @@ const onRenderLink: LinkOptions['onRender'] = (el, url) => {
211
213
  type StoryProps = {
212
214
  text?: string;
213
215
  comments?: Comment[];
214
- } & Pick<TextEditorProps, 'readonly' | 'placeholder' | 'slots' | 'extensions'>;
216
+ } & Pick<TextEditorProps, 'readonly' | 'placeholder' | 'extensions'>;
215
217
 
216
218
  const Story = ({ text, comments, placeholder = 'New document.', ...props }: StoryProps) => {
217
219
  const [item] = useState({ text: new TextObject(text) });
@@ -223,13 +225,16 @@ const Story = ({ text, comments, placeholder = 'New document.', ...props }: Stor
223
225
  }
224
226
 
225
227
  return (
226
- <div className={mx(fixedInsetFlexLayout, groupSurface)}>
227
- <div className='flex h-full justify-center'>
228
- <div className='flex flex-col h-full w-[800px]'>
229
- <MarkdownEditor ref={view} model={model} placeholder={placeholder} {...props} />
230
- </div>
231
- </div>
232
- </div>
228
+ <MarkdownEditor
229
+ ref={view}
230
+ model={model}
231
+ placeholder={placeholder}
232
+ slots={{
233
+ root: { className: mx(textBlockWidth, 'min-bs-dvh') },
234
+ editor: { className: 'min-bs-dvh p-2 bg-white dark:bg-black' },
235
+ }}
236
+ {...props}
237
+ />
233
238
  );
234
239
  };
235
240
 
@@ -238,6 +243,7 @@ export default {
238
243
  component: MarkdownEditor,
239
244
  decorators: [withTheme],
240
245
  render: Story,
246
+ parameters: { translations, layout: 'fullscreen' },
241
247
  };
242
248
 
243
249
  const defaults = [
@@ -384,6 +390,10 @@ export const HorizontalRule = {
384
390
  ),
385
391
  };
386
392
 
393
+ export const Annotations = {
394
+ render: () => <Story text={str('# Annotations', '', large)} extensions={[annotations({ match: /volup/gi })]} />,
395
+ };
396
+
387
397
  const typewriterItems = localStorage.getItem('dxos.org/plugin/markdown/typewriter')?.split(',');
388
398
 
389
399
  export const Typewriter = {
@@ -7,12 +7,13 @@ import '@dxosTheme';
7
7
  import React, { useState } from 'react';
8
8
 
9
9
  import { TextObject } from '@dxos/echo-schema';
10
- import { fixedInsetFlexLayout, groupSurface, mx } from '@dxos/react-ui-theme';
10
+ import { mx, textBlockWidth } from '@dxos/react-ui-theme';
11
11
  import { withTheme } from '@dxos/storybook-utils';
12
12
 
13
13
  import { TextEditor, type TextEditorProps } from './TextEditor';
14
14
  import { listener } from '../../extensions';
15
15
  import { useTextModel } from '../../hooks';
16
+ import translations from '../../translations';
16
17
 
17
18
  const initialText = [
18
19
  '# TextEditor',
@@ -36,13 +37,14 @@ const Story = ({
36
37
  }
37
38
 
38
39
  return (
39
- <div className={mx(fixedInsetFlexLayout, groupSurface)}>
40
- <div className='flex justify-center'>
41
- <div className='flex flex-col w-[800px] py-16'>
42
- <TextEditor model={model} {...props} />
43
- </div>
44
- </div>
45
- </div>
40
+ <TextEditor
41
+ model={model}
42
+ slots={{
43
+ root: { className: mx(textBlockWidth, 'min-bs-dvh') },
44
+ editor: { className: 'min-bs-dvh p-2 bg-white dark:bg-black' },
45
+ }}
46
+ {...props}
47
+ />
46
48
  );
47
49
  };
48
50
 
@@ -51,6 +53,7 @@ export default {
51
53
  component: TextEditor,
52
54
  decorators: [withTheme],
53
55
  render: Story,
56
+ parameters: { translations, layout: 'fullscreen' },
54
57
  };
55
58
 
56
59
  export const Default = {
@@ -20,7 +20,7 @@ import React, {
20
20
 
21
21
  import { log } from '@dxos/log';
22
22
  import { useThemeContext } from '@dxos/react-ui';
23
- import { focusRing, mx } from '@dxos/react-ui-theme';
23
+ import { focusRing } from '@dxos/react-ui-theme';
24
24
  import { isNotFalsy } from '@dxos/util';
25
25
 
26
26
  import { createBasicBundle, createMarkdownExtensions } from '../../extensions';
@@ -71,6 +71,7 @@ export type TextEditorProps = {
71
71
  /**
72
72
  * Base text editor.
73
73
  */
74
+ // TODO(burdon): Replace with useTextEditor.
74
75
  export const BaseTextEditor = forwardRef<EditorView, TextEditorProps>(
75
76
  (
76
77
  {
@@ -258,10 +259,10 @@ export const MarkdownEditor = forwardRef<EditorView, TextEditorProps>(
258
259
 
259
260
  export const defaultSlots: TextEditorSlots = {
260
261
  root: {
261
- className: mx('grow', focusRing),
262
+ className: focusRing,
262
263
  },
263
264
  editor: {
264
- className: 'bs-full',
265
+ className: 'min-bs-full',
265
266
  },
266
267
  };
267
268
 
@@ -5,11 +5,10 @@
5
5
  import '@dxosTheme';
6
6
 
7
7
  import { BroadcastChannelNetworkAdapter } from '@automerge/automerge-repo-network-broadcastchannel';
8
- import { EditorView } from '@codemirror/view';
9
- import '@preact/signals-react'; // Register react integration
10
- import { basicSetup } from 'codemirror';
8
+ import '@preact/signals-react';
9
+ import { EditorView } from '@codemirror/view'; // Register react integration.
11
10
  import get from 'lodash.get';
12
- import React, { useEffect, useRef, useState } from 'react';
11
+ import React, { useEffect, useState } from 'react';
13
12
 
14
13
  import { type Prop } from '@dxos/automerge/automerge';
15
14
  import { Repo, type DocHandle } from '@dxos/automerge/automerge-repo';
@@ -21,38 +20,42 @@ import { ClientRepeater } from '@dxos/react-client/testing';
21
20
  import { withTheme } from '@dxos/storybook-utils';
22
21
 
23
22
  import { MarkdownEditor } from './TextEditor';
24
- import { type IDocHandle, automerge, awareness } from '../../extensions';
25
- import { useTextModel } from '../../hooks';
23
+ import { type IDocHandle, automerge, awareness, createBasicBundle } from '../../extensions';
24
+ import { useTextEditor, useTextModel } from '../../hooks';
25
+ import { defaultTheme } from '../../themes';
26
+ import translations from '../../translations';
26
27
 
27
- // TODO(burdon): Move to components.
28
+ const initialContent = 'Hello world!';
29
+
30
+ type TestObject = {
31
+ text: string;
32
+ };
28
33
 
29
34
  type EditorProps = {
30
35
  handle: IDocHandle;
31
- path: Prop[];
36
+ path?: Prop[];
32
37
  };
33
38
 
34
- const Editor = ({ handle, path }: EditorProps) => {
35
- const containerRef = useRef<HTMLDivElement | null>(null);
36
- const editorRoot = useRef<EditorView>();
37
-
38
- useEffect(() => {
39
- const view = (editorRoot.current = new EditorView({
40
- doc: get(handle.docSync()!, path),
41
- extensions: [basicSetup, automerge({ handle, path }), awareness()],
42
- parent: containerRef.current as any,
43
- }));
44
-
45
- return () => {
46
- view.destroy();
47
- };
48
- }, []);
39
+ const Editor = ({ handle, path = ['text'] }: EditorProps) => {
40
+ const { parentRef } = useTextEditor({
41
+ autoFocus: true,
42
+ doc: get(handle.docSync()!, path),
43
+ extensions: [
44
+ //
45
+ EditorView.baseTheme(defaultTheme),
46
+ EditorView.editorAttributes.of({ class: 'p-2 bg-white' }),
47
+ createBasicBundle({ placeholder: 'Type here...' }),
48
+ automerge({ handle, path }),
49
+ awareness(),
50
+ ],
51
+ });
49
52
 
50
- return <div className='codemirror-editor' ref={containerRef} onKeyDown={(evt) => evt.stopPropagation()} />;
53
+ return <div ref={parentRef} />;
51
54
  };
52
55
 
53
56
  const Story = () => {
54
- const [object1, setObject1] = useState<DocHandle<any> | null>(null);
55
- const [object2, setObject2] = useState<DocHandle<any> | null>(null);
57
+ const [object1, setObject1] = useState<DocHandle<TestObject>>();
58
+ const [object2, setObject2] = useState<DocHandle<TestObject>>();
56
59
 
57
60
  useEffect(() => {
58
61
  queueMicrotask(async () => {
@@ -64,8 +67,8 @@ const Story = () => {
64
67
  });
65
68
 
66
69
  const object1 = repo1.create();
67
- object1.change((doc: any) => {
68
- doc.text = 'Hello world!';
70
+ object1.change((doc: TestObject) => {
71
+ doc.text = initialContent;
69
72
  });
70
73
 
71
74
  const object2 = repo2.find(object1.url);
@@ -81,13 +84,9 @@ const Story = () => {
81
84
  }
82
85
 
83
86
  return (
84
- <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', width: '100vw' }}>
85
- <div>
86
- <Editor handle={object1} path={['text']} />
87
- </div>
88
- <div>
89
- <Editor handle={object2} path={['text']} />
90
- </div>
87
+ <div role='none' className='grid grid-cols-2 bs-full is-full gap-2'>
88
+ <Editor handle={object1} path={['text']} />
89
+ <Editor handle={object2} path={['text']} />
91
90
  </div>
92
91
  );
93
92
  };
@@ -96,39 +95,31 @@ export default {
96
95
  title: 'react-ui-editor/Automerge',
97
96
  component: Editor,
98
97
  render: () => <Story />,
98
+ parameters: { translations, layout: 'fullscreen' },
99
99
  };
100
100
 
101
101
  export const Default = {};
102
102
 
103
- const EchoStory = ({ id, spaceKey }: { id: number; spaceKey: PublicKey }) => {
103
+ const EchoStory = ({ spaceKey }: { spaceKey: PublicKey }) => {
104
104
  const identity = useIdentity();
105
105
  const space = useSpace(spaceKey);
106
106
  // TODO(dmaretskyi): useQuery doesn't work.
107
107
  const [obj] = space?.db.query(Filter.from({ type: 'test' })).objects ?? [];
108
-
109
108
  const model = useTextModel({
110
- text: obj?.content,
111
109
  identity,
112
110
  space,
111
+ text: obj?.content,
113
112
  });
114
113
 
115
114
  if (!model) {
116
115
  return null;
117
116
  }
118
117
 
119
- return (
120
- // <div className={mx(fixedInsetFlexLayout, groupSurface)}>
121
- <div className='flex justify-center overflow-y-scroll'>
122
- <div className='flex flex-col w-[800px] py-16'>
123
- <MarkdownEditor model={model} />
124
- <div className='flex shrink-0 h-[300px]'></div>
125
- </div>
126
- </div>
127
- // </div>
128
- );
118
+ return <MarkdownEditor model={model} />;
129
119
  };
130
120
 
131
121
  export const WithEcho = {
122
+ decorators: [withTheme],
132
123
  render: () => {
133
124
  return (
134
125
  <ClientRepeater
@@ -138,7 +129,7 @@ export const WithEcho = {
138
129
  space.db.add(
139
130
  new Expando({
140
131
  type: 'test',
141
- content: new TextObject('Hello world!'),
132
+ content: new TextObject(initialContent),
142
133
  }),
143
134
  );
144
135
  }}
@@ -146,5 +137,4 @@ export const WithEcho = {
146
137
  />
147
138
  );
148
139
  },
149
- decorators: [withTheme],
150
140
  };
@@ -7,7 +7,7 @@ import '@dxosTheme';
7
7
  import React from 'react';
8
8
 
9
9
  import { useThemeContext } from '@dxos/react-ui';
10
- import { fixedInsetFlexLayout, groupSurface, mx } from '@dxos/react-ui-theme';
10
+ import { mx, textBlockWidth } from '@dxos/react-ui-theme';
11
11
  import { withTheme } from '@dxos/storybook-utils';
12
12
 
13
13
  import { TextEditor } from './TextEditor';
@@ -24,7 +24,9 @@ import {
24
24
  useFormattingState,
25
25
  } from '../../extensions';
26
26
  import { createDataExtensions, createThemeExtensions, useActionHandler, useTextEditor } from '../../hooks';
27
+ import { editorWithToolbarLayout } from '../../styles/layout';
27
28
  import { markdownTheme } from '../../themes';
29
+ import translations from '../../translations';
28
30
  import { Toolbar } from '../Toolbar';
29
31
 
30
32
  // TODO(burdon): Demo toolbar with hooks.
@@ -53,11 +55,7 @@ const Story = ({ autoFocus, placeholder, doc, readonly }: StoryProps) => {
53
55
  themeMode,
54
56
  theme: markdownTheme,
55
57
  slots: {
56
- // TODO(burdon): Document classes re base theme.
57
- // Semantic tokens (e.g., replacement of input surface).
58
- editor: {
59
- className: 'h-full p-4 bg-white text-black dark:bg-black dark:text-white',
60
- },
58
+ editor: { className: 'min-bs-full' },
61
59
  },
62
60
  }),
63
61
  // TODO(burdon): Move lineWrapping.
@@ -80,16 +78,16 @@ const Story = ({ autoFocus, placeholder, doc, readonly }: StoryProps) => {
80
78
  // FIXME This doesn't update the state on view changes. Also not
81
79
  // sure if view is even guaranteed to exist at this point.
82
80
  return (
83
- <div className={mx(fixedInsetFlexLayout, groupSurface)}>
84
- <div className='flex h-full justify-center'>
85
- <div className='flex flex-col h-full w-[800px]'>
86
- <Toolbar.Root onAction={handleAction} state={formattingState}>
87
- <Toolbar.Markdown />
88
- </Toolbar.Root>
89
-
90
- {/* TODO(burdon): Handle scrolling in component wrapper (like this). */}
91
- <div role='none' className='h-full overflow-y-auto' ref={parentRef} />
92
- </div>
81
+ <div role='none' className={mx('fixed inset-0', editorWithToolbarLayout)}>
82
+ <Toolbar.Root onAction={handleAction} state={formattingState} classNames={textBlockWidth}>
83
+ <Toolbar.Markdown />
84
+ </Toolbar.Root>
85
+ <div role='none' className='overflow-y-auto'>
86
+ <div
87
+ role='textbox'
88
+ className={mx(textBlockWidth, 'min-bs-full p-4 surface-attention fg-base')}
89
+ ref={parentRef}
90
+ />
93
91
  </div>
94
92
  </div>
95
93
  );
@@ -100,6 +98,7 @@ export default {
100
98
  component: TextEditor,
101
99
  decorators: [withTheme],
102
100
  render: (args: StoryProps) => <Story {...args} />,
101
+ parameters: { translations, layout: 'fullscreen' },
103
102
  };
104
103
 
105
104
  export const Default = {
@@ -9,7 +9,7 @@ import React, { type FC, useMemo, useState } from 'react';
9
9
  import { TextObject } from '@dxos/echo-schema';
10
10
  import { PublicKey } from '@dxos/keys';
11
11
  import { faker } from '@dxos/random';
12
- import { fixedInsetFlexLayout, groupSurface, mx } from '@dxos/react-ui-theme';
12
+ import { mx, textBlockWidth } from '@dxos/react-ui-theme';
13
13
  import { withTheme } from '@dxos/storybook-utils';
14
14
 
15
15
  import { Toolbar } from './Toolbar';
@@ -25,6 +25,8 @@ import {
25
25
  useFormattingState,
26
26
  } from '../../extensions';
27
27
  import { type Comment, useActionHandler, useEditorView, useTextModel } from '../../hooks';
28
+ import { editorWithToolbarLayout } from '../../styles';
29
+ import translations from '../../translations';
28
30
  import { MarkdownEditor } from '../TextEditor';
29
31
 
30
32
  faker.seed(101);
@@ -63,17 +65,18 @@ const Story: FC<{ content: string }> = ({ content }) => {
63
65
  }
64
66
 
65
67
  return (
66
- <div className={mx(fixedInsetFlexLayout, groupSurface)}>
67
- <div className='flex h-full justify-center'>
68
- <div className='flex flex-col h-full w-[800px]'>
69
- <Toolbar.Root onAction={handleAction} state={formattingState}>
70
- <Toolbar.Markdown />
71
- <Toolbar.Separator />
72
- <Toolbar.Extended />
73
- </Toolbar.Root>
74
- <MarkdownEditor ref={editorRef} model={model} extensions={extensions} />
75
- </div>
76
- </div>
68
+ <div role='none' className={mx('fixed inset-0', editorWithToolbarLayout)}>
69
+ <Toolbar.Root onAction={handleAction} state={formattingState} classNames={textBlockWidth}>
70
+ <Toolbar.Markdown />
71
+ <Toolbar.Separator />
72
+ <Toolbar.Extended />
73
+ </Toolbar.Root>
74
+ <MarkdownEditor
75
+ ref={editorRef}
76
+ model={model}
77
+ extensions={extensions}
78
+ slots={{ root: { className: mx(textBlockWidth, 'pli-2') } }}
79
+ />
77
80
  </div>
78
81
  );
79
82
  };
@@ -83,10 +86,11 @@ export default {
83
86
  component: Toolbar,
84
87
  render: (args: any) => <Story {...args} />,
85
88
  decorators: [withTheme],
89
+ parameters: { translations, layout: 'fullscreen' },
86
90
  };
87
91
 
88
92
  const content = [
89
- 'Demo',
93
+ '# Demo',
90
94
  '',
91
95
  'The editor supports **Markdown** styles.',
92
96
  '',