@dxos/react-ui-editor 0.3.11-main.4eab977 → 0.3.11-main.4faaf44

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 (163) hide show
  1. package/dist/lib/browser/index.mjs +1134 -1241
  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 +16 -13
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
  11. package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
  12. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  13. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  14. package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
  15. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
  16. package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
  17. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
  18. package/dist/types/src/extensions/automerge/index.d.ts +0 -1
  19. package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
  20. package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -12
  21. package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
  22. package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
  23. package/dist/types/src/extensions/awareness.d.ts +1 -1
  24. package/dist/types/src/extensions/awareness.d.ts.map +1 -1
  25. package/dist/types/src/extensions/basic.d.ts +4 -5
  26. package/dist/types/src/extensions/basic.d.ts.map +1 -1
  27. package/dist/types/src/extensions/comments.d.ts +32 -19
  28. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  29. package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
  30. package/dist/types/src/extensions/cursor.d.ts.map +1 -0
  31. package/dist/types/src/extensions/index.d.ts +2 -7
  32. package/dist/types/src/extensions/index.d.ts.map +1 -1
  33. package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
  34. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  35. package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
  36. package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
  37. package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
  38. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  39. package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
  40. package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
  41. package/dist/types/src/extensions/markdown/index.d.ts +7 -0
  42. package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
  43. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
  44. package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
  45. package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
  46. package/dist/types/src/extensions/mention.d.ts.map +1 -1
  47. package/dist/types/src/extensions/outliner.d.ts +4 -0
  48. package/dist/types/src/extensions/outliner.d.ts.map +1 -0
  49. package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
  50. package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
  51. package/dist/types/src/hooks/defs.d.ts +25 -0
  52. package/dist/types/src/hooks/defs.d.ts.map +1 -0
  53. package/dist/types/src/hooks/index.d.ts +2 -2
  54. package/dist/types/src/hooks/index.d.ts.map +1 -1
  55. package/dist/types/src/hooks/useTextEditor.d.ts +17 -0
  56. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
  57. package/dist/types/src/hooks/useTextModel.d.ts +2 -32
  58. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  59. package/dist/types/src/index.d.ts +1 -0
  60. package/dist/types/src/index.d.ts.map +1 -1
  61. package/dist/types/src/styles/markdown.d.ts +2 -2
  62. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  63. package/dist/types/src/themes/default.d.ts.map +1 -1
  64. package/dist/types/src/util.d.ts +7 -0
  65. package/dist/types/src/util.d.ts.map +1 -0
  66. package/package.json +34 -36
  67. package/src/components/TextEditor/MarkdownEditor.stories.tsx +82 -82
  68. package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
  69. package/src/components/TextEditor/TextEditor.tsx +122 -93
  70. package/src/components/TextEditor/comments.stories.tsx +357 -0
  71. package/src/extensions/autocomplete.ts +6 -3
  72. package/src/extensions/automerge/automerge.ts +40 -46
  73. package/src/extensions/automerge/cursor.ts +2 -1
  74. package/src/extensions/automerge/defs.ts +10 -31
  75. package/src/extensions/automerge/index.ts +0 -1
  76. package/src/extensions/automerge/semaphore.ts +23 -20
  77. package/src/extensions/automerge/update-automerge.ts +2 -2
  78. package/src/extensions/awareness.ts +40 -46
  79. package/src/extensions/basic.ts +22 -17
  80. package/src/extensions/comments.ts +246 -238
  81. package/src/extensions/cursor.ts +50 -0
  82. package/src/extensions/index.ts +2 -7
  83. package/src/extensions/markdown/bundle.ts +20 -30
  84. package/src/extensions/markdown/code.ts +127 -0
  85. package/src/extensions/markdown/heading.ts +59 -0
  86. package/src/extensions/markdown/highlight.ts +9 -23
  87. package/src/extensions/markdown/hr.ts +71 -0
  88. package/src/extensions/{image.ts → markdown/image.ts} +2 -2
  89. package/src/extensions/markdown/index.ts +7 -0
  90. package/src/extensions/{link.ts → markdown/link.ts} +8 -9
  91. package/src/extensions/{table.ts → markdown/table.ts} +2 -2
  92. package/src/extensions/markdown/tasklist.ts +110 -0
  93. package/src/extensions/mention.ts +9 -2
  94. package/src/extensions/outliner.ts +12 -0
  95. package/src/hooks/awareness-provider.ts +24 -20
  96. package/src/hooks/defs.ts +42 -0
  97. package/src/hooks/index.ts +3 -2
  98. package/src/hooks/useTextEditor.ts +29 -0
  99. package/src/hooks/useTextModel.ts +48 -60
  100. package/src/index.ts +1 -0
  101. package/src/styles/markdown.ts +9 -12
  102. package/src/themes/default.ts +15 -50
  103. package/src/util.ts +41 -0
  104. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
  105. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
  106. package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
  107. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
  108. package/dist/types/src/extensions/code.d.ts.map +0 -1
  109. package/dist/types/src/extensions/hr.d.ts.map +0 -1
  110. package/dist/types/src/extensions/image.d.ts.map +0 -1
  111. package/dist/types/src/extensions/link.d.ts.map +0 -1
  112. package/dist/types/src/extensions/table.d.ts.map +0 -1
  113. package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
  114. package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
  115. package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
  116. package/dist/types/src/extensions/yjs/index.d.ts +0 -2
  117. package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
  118. package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
  119. package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
  120. package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
  121. package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
  122. package/dist/types/src/hooks/automerge.d.ts +0 -3
  123. package/dist/types/src/hooks/automerge.d.ts.map +0 -1
  124. package/dist/types/src/hooks/yjs.d.ts +0 -27
  125. package/dist/types/src/hooks/yjs.d.ts.map +0 -1
  126. package/dist/types/src/testing/index.d.ts +0 -3
  127. package/dist/types/src/testing/index.d.ts.map +0 -1
  128. package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
  129. package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
  130. package/dist/types/src/testing/proto/index.d.ts +0 -2
  131. package/dist/types/src/testing/proto/index.d.ts.map +0 -1
  132. package/dist/types/src/testing/replicator.d.ts +0 -45
  133. package/dist/types/src/testing/replicator.d.ts.map +0 -1
  134. package/dist/types/src/util/cursor.d.ts.map +0 -1
  135. package/dist/types/src/util/index.d.ts +0 -3
  136. package/dist/types/src/util/index.d.ts.map +0 -1
  137. package/dist/types/src/util/util.d.ts +0 -5
  138. package/dist/types/src/util/util.d.ts.map +0 -1
  139. package/src/components/TextEditor/codemirror.stories.ts +0 -115
  140. package/src/components/TextEditor/yjs.stories.tsx +0 -56
  141. package/src/extensions/code.ts +0 -98
  142. package/src/extensions/hr.ts +0 -73
  143. package/src/extensions/tasklist.ts +0 -119
  144. package/src/extensions/yjs/cursor.ts +0 -21
  145. package/src/extensions/yjs/index.ts +0 -5
  146. package/src/extensions/yjs/yjs.test.ts +0 -35
  147. package/src/extensions/yjs/yjs.ts +0 -16
  148. package/src/hooks/automerge.ts +0 -52
  149. package/src/hooks/yjs.ts +0 -178
  150. package/src/testing/index.ts +0 -6
  151. package/src/testing/proto/gen/schema.ts +0 -49
  152. package/src/testing/proto/index.ts +0 -5
  153. package/src/testing/proto/schema.proto +0 -15
  154. package/src/testing/replicator.ts +0 -184
  155. package/src/util/cursor.ts +0 -29
  156. package/src/util/index.ts +0 -6
  157. package/src/util/util.ts +0 -18
  158. /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
  159. /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
  160. /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
  161. /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
  162. /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
  163. /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-editor",
3
- "version": "0.3.11-main.4eab977",
3
+ "version": "0.3.11-main.4faaf44",
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",
@@ -13,20 +13,20 @@
13
13
  "src"
14
14
  ],
15
15
  "dependencies": {
16
- "@codemirror/autocomplete": "^6.11.1",
17
- "@codemirror/commands": "^6.3.2",
18
- "@codemirror/lang-markdown": "^6.2.3",
19
- "@codemirror/language": "^6.9.3",
16
+ "@codemirror/autocomplete": "^6.12.0",
17
+ "@codemirror/commands": "^6.3.3",
18
+ "@codemirror/lang-markdown": "^6.2.4",
19
+ "@codemirror/language": "^6.10.0",
20
20
  "@codemirror/language-data": "^6.3.1",
21
21
  "@codemirror/lint": "^6.4.2",
22
22
  "@codemirror/search": "^6.5.5",
23
- "@codemirror/state": "^6.3.3",
23
+ "@codemirror/state": "^6.4.0",
24
24
  "@codemirror/theme-one-dark": "^6.1.2",
25
- "@codemirror/view": "^6.22.2",
25
+ "@codemirror/view": "^6.23.0",
26
26
  "@fluentui/react-tabster": "^9.16.1",
27
- "@lezer/common": "^1.1.1",
27
+ "@lezer/common": "^1.2.1",
28
28
  "@lezer/highlight": "^1.2.0",
29
- "@lezer/markdown": "^1.1.1",
29
+ "@lezer/markdown": "^1.2.0",
30
30
  "@replit/codemirror-vim": "^6.0.14",
31
31
  "codemirror": "6.0.1",
32
32
  "lib0": "^0.2.65",
@@ -35,27 +35,24 @@
35
35
  "lodash.pick": "^4.4.0",
36
36
  "lodash.sortby": "^4.7.0",
37
37
  "style-mod": "^4.1.0",
38
- "y-codemirror.next": "^0.3.2",
39
- "y-protocols": "^1.0.5",
40
- "yjs": "^13.6.10",
41
- "@dxos/async": "0.3.11-main.4eab977",
42
- "@dxos/automerge": "0.3.11-main.4eab977",
43
- "@dxos/context": "0.3.11-main.4eab977",
44
- "@dxos/debug": "0.3.11-main.4eab977",
45
- "@dxos/display-name": "0.3.11-main.4eab977",
46
- "@dxos/invariant": "0.3.11-main.4eab977",
47
- "@dxos/log": "0.3.11-main.4eab977",
48
- "@dxos/echo-schema": "0.3.11-main.4eab977",
49
- "@dxos/protocols": "0.3.11-main.4eab977",
50
- "@dxos/react-async": "0.3.11-main.4eab977",
51
- "@dxos/react-ui-theme": "0.3.11-main.4eab977",
52
- "@dxos/react-ui": "0.3.11-main.4eab977",
53
- "@dxos/text-model": "0.3.11-main.4eab977",
54
- "@dxos/util": "0.3.11-main.4eab977"
38
+ "@dxos/automerge": "0.3.11-main.4faaf44",
39
+ "@dxos/async": "0.3.11-main.4faaf44",
40
+ "@dxos/debug": "0.3.11-main.4faaf44",
41
+ "@dxos/context": "0.3.11-main.4faaf44",
42
+ "@dxos/display-name": "0.3.11-main.4faaf44",
43
+ "@dxos/invariant": "0.3.11-main.4faaf44",
44
+ "@dxos/log": "0.3.11-main.4faaf44",
45
+ "@dxos/protocols": "0.3.11-main.4faaf44",
46
+ "@dxos/react-ui": "0.3.11-main.4faaf44",
47
+ "@dxos/echo-schema": "0.3.11-main.4faaf44",
48
+ "@dxos/react-async": "0.3.11-main.4faaf44",
49
+ "@dxos/react-ui-theme": "0.3.11-main.4faaf44",
50
+ "@dxos/util": "0.3.11-main.4faaf44",
51
+ "@dxos/text-model": "0.3.11-main.4faaf44"
55
52
  },
56
53
  "devDependencies": {
57
- "@automerge/automerge-repo-network-broadcastchannel": "^1.0.19",
58
- "@faker-js/faker": "^8.0.2",
54
+ "@automerge/automerge-repo-network-broadcastchannel": "^1.1.0",
55
+ "@faker-js/faker": "^8.3.1",
59
56
  "@phosphor-icons/react": "^2.0.5",
60
57
  "@preact/signals-react": "^1.3.6",
61
58
  "@types/lodash.defaultsdeep": "^4.6.6",
@@ -67,23 +64,24 @@
67
64
  "deepsignal": "1.4.0-shallow.0",
68
65
  "react": "^18.2.0",
69
66
  "react-dom": "^18.2.0",
70
- "@dxos/config": "0.3.11-main.4eab977",
71
- "@dxos/react-client": "0.3.11-main.4eab977",
72
- "@dxos/storybook-utils": "0.3.11-main.4eab977",
73
- "@dxos/react-ui": "0.3.11-main.4eab977",
74
- "@dxos/echo-typegen": "0.3.11-main.4eab977",
75
- "@dxos/echo-signals": "0.3.11-main.4eab977"
67
+ "@dxos/echo-signals": "0.3.11-main.4faaf44",
68
+ "@dxos/config": "0.3.11-main.4faaf44",
69
+ "@dxos/echo-typegen": "0.3.11-main.4faaf44",
70
+ "@dxos/keyboard": "0.3.11-main.4faaf44",
71
+ "@dxos/react-client": "0.3.11-main.4faaf44",
72
+ "@dxos/react-ui": "0.3.11-main.4faaf44",
73
+ "@dxos/storybook-utils": "0.3.11-main.4faaf44"
76
74
  },
77
75
  "peerDependencies": {
78
76
  "@phosphor-icons/react": "^2.0.5",
79
77
  "react": "^18.2.0",
80
78
  "react-dom": "^18.2.0",
81
- "@dxos/react-client": "0.3.11-main.4eab977"
79
+ "@dxos/react-client": "0.3.11-main.4faaf44"
82
80
  },
83
81
  "publishConfig": {
84
82
  "access": "public"
85
83
  },
86
84
  "scripts": {
87
- "prebuild": "dxtype src/testing/proto/schema.proto src/testing/proto/gen/schema.ts"
85
+ "test": "true"
88
86
  }
89
87
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  import '@dxosTheme';
6
6
 
7
- import { EditorView } from '@codemirror/view';
7
+ import { type EditorView } from '@codemirror/view';
8
8
  import { faker } from '@faker-js/faker';
9
9
  import { ArrowSquareOut } from '@phosphor-icons/react';
10
10
  import defaultsDeep from 'lodash.defaultsdeep';
@@ -12,11 +12,12 @@ import React, { type FC, StrictMode, useRef, useState } from 'react';
12
12
  import { createRoot } from 'react-dom/client';
13
13
 
14
14
  import { TextObject } from '@dxos/echo-schema';
15
+ import { keySymbols, parseShortcut } from '@dxos/keyboard';
15
16
  import { PublicKey } from '@dxos/keys';
16
17
  import { fixedInsetFlexLayout, getSize, groupSurface, mx } from '@dxos/react-ui-theme';
17
18
  import { withTheme } from '@dxos/storybook-utils';
18
19
 
19
- import { MarkdownEditor, type TextEditorProps, type TextEditorRef } from './TextEditor';
20
+ import { MarkdownEditor, type TextEditorProps } from './TextEditor';
20
21
  import {
21
22
  autocomplete,
22
23
  blast,
@@ -25,7 +26,6 @@ import {
25
26
  defaultOptions,
26
27
  hr,
27
28
  image,
28
- listener,
29
29
  link,
30
30
  mention,
31
31
  table,
@@ -33,8 +33,10 @@ import {
33
33
  typewriter,
34
34
  type CommentsOptions,
35
35
  type LinkOptions,
36
+ useComments,
37
+ heading,
36
38
  } from '../../extensions';
37
- import { type CommentRange, useTextModel } from '../../hooks';
39
+ import { type Comment, useTextModel } from '../../hooks';
38
40
 
39
41
  // Extensions:
40
42
  // TODO(burdon): Table of contents.
@@ -54,8 +56,8 @@ const text = {
54
56
  '- [x] decorator',
55
57
  '- [ ] checkbox',
56
58
  ' - [ ] state',
57
- ' - [ ] indent',
58
- ' - [x] style',
59
+ ' - [ ] indent',
60
+ ' - [x] style',
59
61
  '',
60
62
  ),
61
63
 
@@ -81,7 +83,7 @@ const text = {
81
83
  '## Code',
82
84
  '',
83
85
  '```',
84
- 'const x = 100;',
86
+ '$ ls -las',
85
87
  '```',
86
88
  '',
87
89
  '```tsx',
@@ -161,6 +163,8 @@ const links = [
161
163
  { label: 'StackEdit', apply: '[StackEdit](https://stackedit.io/app)' },
162
164
  ];
163
165
 
166
+ const names = ['adam', 'alice', 'alison', 'bob', 'carol', 'charlie', 'sayuri', 'shoko'];
167
+
164
168
  const hover =
165
169
  'rounded-sm text-base text-primary-600 hover:text-primary-500 dark:text-primary-300 hover:dark:text-primary-200';
166
170
 
@@ -182,15 +186,15 @@ const Key: FC<{ char: string }> = ({ char }) => (
182
186
  </span>
183
187
  );
184
188
 
185
- const onCommentsHover: CommentsOptions['onHover'] = (el) => {
189
+ const onCommentsHover: CommentsOptions['onHover'] = (el, shortcut) => {
186
190
  createRoot(el).render(
187
191
  <StrictMode>
188
192
  <div className='flex items-center gap-2 px-2 py-2 bg-neutral-700 text-white text-xs rounded'>
189
193
  <div>Create comment</div>
190
- {/* TODO(burdon): Unify shortcuts. */}
191
194
  <div className='flex gap-1'>
192
- <Key char='⌘' />
193
- <Key char="'" />
195
+ {keySymbols(parseShortcut(shortcut)).map((char) => (
196
+ <Key key={char} char={char} />
197
+ ))}
194
198
  </div>
195
199
  </div>
196
200
  </StrictMode>,
@@ -201,7 +205,7 @@ const onRenderLink: LinkOptions['onRender'] = (el, url) => {
201
205
  createRoot(el).render(
202
206
  <StrictMode>
203
207
  <a href={url} target='_blank' rel='noreferrer' className={hover}>
204
- <ArrowSquareOut weight='bold' className={mx(getSize(4), 'inline-block leading-none mis-1 mb-1')} />
208
+ <ArrowSquareOut weight='bold' className={mx(getSize(4), 'inline-block leading-none mis-1 mb-[2px]')} />
205
209
  </a>
206
210
  </StrictMode>,
207
211
  );
@@ -209,23 +213,24 @@ const onRenderLink: LinkOptions['onRender'] = (el, url) => {
209
213
 
210
214
  type StoryProps = {
211
215
  text?: string;
216
+ comments?: Comment[];
212
217
  automerge?: boolean;
213
- } & Pick<TextEditorProps, 'comments' | 'readonly' | 'extensions' | 'slots'>;
218
+ } & Pick<TextEditorProps, 'readonly' | 'placeholder' | 'slots' | 'extensions'>;
214
219
 
215
- const Story = ({ text, automerge, ...props }: StoryProps) => {
216
- const ref = useRef<TextEditorRef>(null);
220
+ const Story = ({ text, comments, automerge, placeholder = 'New document.', ...props }: StoryProps) => {
217
221
  const [item] = useState({ text: new TextObject(text, undefined, undefined, { automerge }) });
222
+ const view = useRef<EditorView>(null);
218
223
  const model = useTextModel({ text: item.text });
224
+ useComments(view.current, comments);
219
225
  if (!model) {
220
226
  return null;
221
227
  }
222
228
 
223
229
  return (
224
230
  <div className={mx(fixedInsetFlexLayout, groupSurface)}>
225
- <div className='flex justify-center overflow-y-scroll'>
226
- <div className='flex flex-col w-[800px] py-16'>
227
- <MarkdownEditor ref={ref} model={model} {...props} />
228
- <div className='flex shrink-0 h-[300px]'></div>
231
+ <div className='flex h-full justify-center'>
232
+ <div className='flex flex-col h-full w-[800px]'>
233
+ <MarkdownEditor ref={view} model={model} placeholder={placeholder} {...props} />
229
234
  </div>
230
235
  </div>
231
236
  </div>
@@ -239,44 +244,42 @@ export default {
239
244
  render: Story,
240
245
  };
241
246
 
242
- const extensions = [
247
+ const defaults = [
243
248
  autocomplete({
244
249
  onSearch: (text) => links.filter(({ label }) => label.toLowerCase().includes(text.toLowerCase())),
245
250
  }),
246
251
  code(),
252
+ heading(),
247
253
  hr(),
248
254
  image(),
249
255
  link({ onRender: onRenderLink, onHover: onHoverLinkTooltip }),
256
+ // mention({
257
+ // onSearch: (text) => names.filter((name) => name.toLowerCase().startsWith(text.toLowerCase())),
258
+ // }),
250
259
  table(),
251
260
  tasklist(),
252
261
  ];
253
262
 
254
263
  export const Default = {
255
- render: () => <Story text={document} extensions={extensions} />,
264
+ render: () => <Story text={document} extensions={defaults} />,
256
265
  };
257
266
 
258
267
  export const Readonly = {
259
- render: () => <Story text={document} extensions={extensions} readonly />,
260
- };
261
-
262
- const large = faker.helpers.multiple(() => faker.lorem.paragraph({ min: 8, max: 16 }), { count: 20 }).join('\n\n');
263
-
264
- export const Large = {
265
- render: () => <Story text={str('# Large Document', '', large)} extensions={[]} />,
268
+ render: () => <Story text={document} extensions={defaults} readonly />,
266
269
  };
267
270
 
268
271
  export const NoExtensions = {
269
272
  render: () => <Story text={document} />,
270
273
  };
271
274
 
272
- // TODO(burdon): Cursor bug if no newline after BR (cursor down just loops back to start of each paragraph).
273
- export const HorizontalRule = {
274
- render: () => (
275
- <Story
276
- text={str('# Horizontal Rule', '', text.paragraphs, '---', '', text.paragraphs, '---', '', text.paragraphs)}
277
- extensions={[hr()]}
278
- />
279
- ),
275
+ const large = faker.helpers.multiple(() => faker.lorem.paragraph({ min: 8, max: 16 }), { count: 20 }).join('\n\n');
276
+
277
+ export const Empty = {
278
+ render: () => <Story />,
279
+ };
280
+
281
+ export const Scrolling = {
282
+ render: () => <Story text={str('# Large Document', '', large)} extensions={[]} />,
280
283
  };
281
284
 
282
285
  export const Links = {
@@ -289,37 +292,36 @@ export const Links = {
289
292
  };
290
293
 
291
294
  export const Code = {
292
- render: () => <Story text={str(text.code, text.footer)} extensions={[code()]} readonly />,
293
- };
294
-
295
- export const Table = {
296
- render: () => <Story text={str(text.table, text.footer)} extensions={[table()]} />,
295
+ render: () => <Story text={str(text.code, text.footer)} extensions={[code()]} />,
297
296
  };
298
297
 
299
298
  export const Image = {
300
- render: () => <Story text={str(text.image, text.footer)} readonly extensions={[image()]} />,
299
+ render: () => <Story text={str(text.image, text.footer)} extensions={[image()]} />,
301
300
  };
302
301
 
303
- export const Tasklist = {
302
+ export const Lists = {
304
303
  render: () => (
305
- <Story
306
- text={str(text.tasks, '', text.list, text.footer)}
307
- extensions={[
308
- tasklist(),
309
- listener({
310
- onChange: (text) => {
311
- console.log(text);
312
- },
313
- }),
314
- ]}
315
- />
304
+ <Story text={str(text.tasks, '', text.list, '', text.numbered, text.footer)} extensions={[tasklist()]} />
316
305
  ),
317
306
  };
318
307
 
308
+ export const Table = {
309
+ render: () => <Story text={str(text.table, text.footer)} extensions={[table()]} />,
310
+ };
311
+
312
+ // export const Outliner = {
313
+ // render: () => (
314
+ // <Story
315
+ // text={str('# Outliner', '', 'Block', ': this is a block', ': with multiple lines', text.footer)}
316
+ // extensions={[outliner()]}
317
+ // />
318
+ // ),
319
+ // };
320
+
319
321
  export const Autocomplete = {
320
322
  render: () => (
321
323
  <Story
322
- text={str('# Autocomplete', '', 'Press CTRL-SPACE', text.footer)}
324
+ text={str('# Autocomplete', '', 'Press Ctrl-Space...', text.footer)}
323
325
  extensions={[
324
326
  link({ onRender: onRenderLink }),
325
327
  autocomplete({
@@ -330,8 +332,6 @@ export const Autocomplete = {
330
332
  ),
331
333
  };
332
334
 
333
- const names = ['adam', 'alice', 'alison', 'bob', 'carol', 'charlie', 'sayuri', 'shoko'];
334
-
335
335
  export const Mention = {
336
336
  render: () => (
337
337
  <Story
@@ -347,18 +347,18 @@ export const Mention = {
347
347
 
348
348
  export const Comments = {
349
349
  render: () => {
350
- const [commentsStates, setCommentStates] = useState<CommentRange[]>([]);
350
+ const [commentRanges, setCommentRanges] = useState<Comment[]>([]);
351
351
 
352
352
  return (
353
353
  <Story
354
354
  text={str('# Comments', '', text.paragraphs, text.footer)}
355
- comments={commentsStates}
355
+ comments={commentRanges}
356
356
  extensions={[
357
357
  comments({
358
358
  onHover: onCommentsHover,
359
- onCreate: (relPos) => {
359
+ onCreate: (range) => {
360
360
  const id = PublicKey.random().toHex();
361
- setCommentStates((comments) => [...comments, { id, cursor: relPos }]);
361
+ setCommentRanges((commentRanges) => [...commentRanges, { id, cursor: range }]);
362
362
  return id;
363
363
  },
364
364
  onSelect: (state) => {
@@ -367,9 +367,9 @@ export const Comments = {
367
367
  console.log(
368
368
  'update',
369
369
  JSON.stringify({
370
- active: state.active?.slice(0, 8),
371
- closest: state.closest?.slice(0, 8),
372
- ranges: state.ranges.length,
370
+ comments: state.comments.length,
371
+ active: state.selection.current?.slice(0, 8),
372
+ closest: state.selection.closest?.slice(0, 8),
373
373
  }),
374
374
  );
375
375
  }
@@ -381,8 +381,24 @@ export const Comments = {
381
381
  },
382
382
  };
383
383
 
384
+ export const HorizontalRule = {
385
+ render: () => (
386
+ <Story
387
+ text={str('# Horizontal Rule', '', text.paragraphs, '---', text.paragraphs, '---', text.paragraphs)}
388
+ extensions={[hr()]}
389
+ />
390
+ ),
391
+ };
392
+
393
+ const typewriterItems = localStorage.getItem('dxos.org/plugin/markdown/typewriter')?.split(',');
394
+
384
395
  export const Typewriter = {
385
- render: () => <Story text={str('# Typewriter', '', text.paragraphs, text.footer)} extensions={[typewriter()]} />,
396
+ render: () => (
397
+ <Story
398
+ text={str('# Typewriter', '', text.paragraphs, text.footer)}
399
+ extensions={[typewriter({ items: typewriterItems })]}
400
+ />
401
+ ),
386
402
  };
387
403
 
388
404
  export const Blast = {
@@ -390,9 +406,7 @@ export const Blast = {
390
406
  <Story
391
407
  text={str('# Blast', '', text.paragraphs, text.code, text.paragraphs)}
392
408
  extensions={[
393
- typewriter({
394
- items: localStorage.getItem('dxos.composer.extension.demo')?.split(','),
395
- }),
409
+ typewriter({ items: typewriterItems }),
396
410
  blast(
397
411
  defaultsDeep(
398
412
  {
@@ -409,17 +423,3 @@ export const Blast = {
409
423
  />
410
424
  ),
411
425
  };
412
-
413
- export const Diagnostics = {
414
- render: () => (
415
- <Story
416
- text={document}
417
- extensions={[
418
- // Cursor moved.
419
- EditorView.updateListener.of((update) => {
420
- console.log('update', update.view.state.selection.main.head);
421
- }),
422
- ]}
423
- />
424
- ),
425
- };
@@ -4,17 +4,15 @@
4
4
 
5
5
  import '@dxosTheme';
6
6
 
7
- import defaultsDeep from 'lodash.defaultsdeep';
8
- import React, { useRef, useState } from 'react';
7
+ import React, { useState } from 'react';
9
8
 
10
9
  import { TextObject } from '@dxos/echo-schema';
11
10
  import { fixedInsetFlexLayout, groupSurface, mx } from '@dxos/react-ui-theme';
12
11
  import { withTheme } from '@dxos/storybook-utils';
13
12
 
14
- import { defaultSlots, TextEditor, type TextEditorProps, type TextEditorRef, type TextEditorSlots } from './TextEditor';
13
+ import { TextEditor, type TextEditorProps } from './TextEditor';
15
14
  import { listener } from '../../extensions';
16
15
  import { useTextModel } from '../../hooks';
17
- import { textTheme } from '../../themes';
18
16
 
19
17
  const initialText = [
20
18
  '# TextEditor',
@@ -30,8 +28,7 @@ const Story = ({
30
28
  text,
31
29
  automerge,
32
30
  ...props
33
- }: { text?: string; automerge?: boolean } & Pick<TextEditorProps, 'extensions' | 'slots'>) => {
34
- const ref = useRef<TextEditorRef>(null);
31
+ }: { text?: string; automerge?: boolean } & Pick<TextEditorProps, 'extensions' | 'placeholder' | 'slots'>) => {
35
32
  const [item] = useState({ text: new TextObject(text, undefined, undefined, { automerge }) });
36
33
  const model = useTextModel({ text: item.text });
37
34
  if (!model) {
@@ -40,10 +37,9 @@ const Story = ({
40
37
 
41
38
  return (
42
39
  <div className={mx(fixedInsetFlexLayout, groupSurface)}>
43
- <div className='flex justify-center overflow-y-scroll'>
40
+ <div className='flex justify-center'>
44
41
  <div className='flex flex-col w-[800px] py-16'>
45
- <TextEditor ref={ref} model={model} {...props} />
46
- <div className='flex shrink-0 h-[300px]'></div>
42
+ <TextEditor model={model} {...props} />
47
43
  </div>
48
44
  </div>
49
45
  </div>
@@ -58,49 +54,19 @@ export default {
58
54
  };
59
55
 
60
56
  export const Default = {
61
- render: () => (
62
- <Story
63
- slots={defaultsDeep(
64
- { editor: { theme: textTheme, placeholder: 'Enter text...' } } satisfies TextEditorSlots,
65
- defaultSlots,
66
- )}
67
- />
68
- ),
69
- };
70
-
71
- export const Listener = {
72
- render: () => (
73
- <Story
74
- slots={defaultsDeep(
75
- { editor: { theme: textTheme, placeholder: 'Enter text...' } } satisfies TextEditorSlots,
76
- defaultSlots,
77
- )}
78
- extensions={[listener({ onChange: (text) => console.log(text) })]}
79
- />
80
- ),
57
+ render: () => <Story placeholder='Enter text...' />,
81
58
  };
82
59
 
83
60
  export const Text = {
84
- render: () => (
85
- <Story
86
- text={initialText}
87
- slots={defaultsDeep(
88
- { editor: { theme: textTheme, placeholder: 'Enter text...' } } satisfies TextEditorSlots,
89
- defaultSlots,
90
- )}
91
- />
92
- ),
61
+ render: () => <Story text={initialText} placeholder='Enter text...' />,
93
62
  };
94
63
 
95
64
  export const Automerge = {
65
+ render: () => <Story text={initialText} placeholder='Enter text...' automerge />,
66
+ };
67
+
68
+ export const Listener = {
96
69
  render: () => (
97
- <Story
98
- automerge
99
- text={initialText}
100
- slots={defaultsDeep(
101
- { editor: { theme: textTheme, placeholder: 'Enter text...' } } satisfies TextEditorSlots,
102
- defaultSlots,
103
- )}
104
- />
70
+ <Story placeholder='Enter text...' extensions={[listener({ onChange: (text) => console.log(text) })]} />
105
71
  ),
106
72
  };