@dxos/react-ui-editor 0.3.11-main.6f25445 → 0.3.11-main.73ee990

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