@dxos/react-ui-editor 0.8.4-main.fffef41 → 0.8.4-staging.60fe92afc8

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 (436) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/index.mjs +1126 -8845
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/translations.mjs +39 -0
  7. package/dist/lib/browser/translations.mjs.map +7 -0
  8. package/dist/lib/node-esm/index.mjs +1126 -8844
  9. package/dist/lib/node-esm/index.mjs.map +4 -4
  10. package/dist/lib/node-esm/meta.json +1 -1
  11. package/dist/lib/node-esm/translations.mjs +41 -0
  12. package/dist/lib/node-esm/translations.mjs.map +7 -0
  13. package/dist/types/src/components/Editor/Editor.d.ts +41 -24
  14. package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
  15. package/dist/types/src/components/Editor/Editor.stories.d.ts +7 -4
  16. package/dist/types/src/components/Editor/Editor.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/{EditorContent/EditorContent.d.ts → Editor/EditorView.d.ts} +9 -7
  18. package/dist/types/src/components/Editor/EditorView.d.ts.map +1 -0
  19. package/dist/types/src/components/Editor/controller.d.ts.map +1 -0
  20. package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts +3 -5
  21. package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts.map +1 -1
  22. package/dist/types/src/components/EditorMenuProvider/index.d.ts +0 -1
  23. package/dist/types/src/components/EditorMenuProvider/index.d.ts.map +1 -1
  24. package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts.map +1 -1
  25. package/dist/types/src/components/EditorMenuProvider/menu.d.ts.map +1 -1
  26. package/dist/types/src/components/EditorMenuProvider/popover.d.ts +9 -3
  27. package/dist/types/src/components/EditorMenuProvider/popover.d.ts.map +1 -1
  28. package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts +3 -3
  29. package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts.map +1 -1
  30. package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts +1 -1
  31. package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts.map +1 -1
  32. package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +8 -6
  33. package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
  34. package/dist/types/src/components/EditorToolbar/blocks.d.ts +4 -17
  35. package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
  36. package/dist/types/src/components/EditorToolbar/formatting.d.ts +4 -17
  37. package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
  38. package/dist/types/src/components/EditorToolbar/headings.d.ts +4 -17
  39. package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
  40. package/dist/types/src/components/EditorToolbar/image.d.ts +3 -15
  41. package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -1
  42. package/dist/types/src/components/EditorToolbar/index.d.ts +1 -2
  43. package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
  44. package/dist/types/src/components/EditorToolbar/lists.d.ts +6 -0
  45. package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -0
  46. package/dist/types/src/components/EditorToolbar/search.d.ts +3 -15
  47. package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -1
  48. package/dist/types/src/components/EditorToolbar/types.d.ts +6 -0
  49. package/dist/types/src/components/EditorToolbar/types.d.ts.map +1 -0
  50. package/dist/types/src/components/EditorToolbar/view-mode.d.ts +5 -18
  51. package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
  52. package/dist/types/src/components/index.d.ts +0 -2
  53. package/dist/types/src/components/index.d.ts.map +1 -1
  54. package/dist/types/src/extensions/Assistant.stories.d.ts +10 -0
  55. package/dist/types/src/extensions/Assistant.stories.d.ts.map +1 -0
  56. package/dist/types/src/extensions/assistant-extension.d.ts +24 -0
  57. package/dist/types/src/extensions/assistant-extension.d.ts.map +1 -0
  58. package/dist/types/src/extensions/index.d.ts +1 -31
  59. package/dist/types/src/extensions/index.d.ts.map +1 -1
  60. package/dist/types/src/hooks/index.d.ts +1 -0
  61. package/dist/types/src/hooks/index.d.ts.map +1 -1
  62. package/dist/types/src/hooks/useBasicMarkdownExtensions.d.ts +25 -0
  63. package/dist/types/src/hooks/useBasicMarkdownExtensions.d.ts.map +1 -0
  64. package/dist/types/src/hooks/useTextEditor.d.ts +1 -1
  65. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  66. package/dist/types/src/index.d.ts +0 -9
  67. package/dist/types/src/index.d.ts.map +1 -1
  68. package/dist/types/src/stories/Automerge.stories.d.ts +44 -0
  69. package/dist/types/src/stories/Automerge.stories.d.ts.map +1 -0
  70. package/dist/types/src/stories/Comments.stories.d.ts +3 -2
  71. package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
  72. package/dist/types/src/stories/EditorToolbar.stories.d.ts +29 -27
  73. package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
  74. package/dist/types/src/stories/Experimental.stories.d.ts +4 -3
  75. package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
  76. package/dist/types/src/stories/Markdown.stories.d.ts +3 -2
  77. package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
  78. package/dist/types/src/stories/Outliner.stories.d.ts +2 -2
  79. package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
  80. package/dist/types/src/stories/Popover.stories.d.ts +2 -2
  81. package/dist/types/src/stories/Popover.stories.d.ts.map +1 -1
  82. package/dist/types/src/stories/Preview.stories.d.ts +3 -2
  83. package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
  84. package/dist/types/src/stories/Tags.stories.d.ts.map +1 -1
  85. package/dist/types/src/stories/TextEditor.stories.d.ts +3 -2
  86. package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
  87. package/dist/types/src/stories/Theme.stories.d.ts +8 -0
  88. package/dist/types/src/stories/Theme.stories.d.ts.map +1 -0
  89. package/dist/types/src/stories/components/EditorStory.d.ts +9 -20
  90. package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
  91. package/dist/types/src/stories/components/util.d.ts +4 -3
  92. package/dist/types/src/stories/components/util.d.ts.map +1 -1
  93. package/dist/types/src/translations.d.ts +26 -26
  94. package/dist/types/src/translations.d.ts.map +1 -1
  95. package/dist/types/src/util/index.d.ts +0 -5
  96. package/dist/types/src/util/index.d.ts.map +1 -1
  97. package/dist/types/src/util/react.d.ts +6 -5
  98. package/dist/types/src/util/react.d.ts.map +1 -1
  99. package/dist/types/tsconfig.tsbuildinfo +1 -1
  100. package/package.json +93 -86
  101. package/src/components/Editor/Editor.stories.tsx +26 -26
  102. package/src/components/Editor/Editor.tsx +68 -55
  103. package/src/components/Editor/EditorView.tsx +99 -0
  104. package/src/components/{EditorContent → Editor}/controller.ts +13 -4
  105. package/src/components/EditorMenuProvider/EditorMenuProvider.tsx +40 -39
  106. package/src/components/EditorMenuProvider/index.ts +0 -1
  107. package/src/components/EditorMenuProvider/menu-presets.ts +3 -1
  108. package/src/components/EditorMenuProvider/menu.ts +1 -2
  109. package/src/components/EditorMenuProvider/popover.ts +42 -9
  110. package/src/components/EditorMenuProvider/useEditorMenu.ts +21 -7
  111. package/src/components/EditorPreviewProvider/EditorPreviewProvider.tsx +6 -9
  112. package/src/components/EditorToolbar/EditorToolbar.tsx +37 -68
  113. package/src/components/EditorToolbar/blocks.ts +55 -48
  114. package/src/components/EditorToolbar/formatting.ts +44 -46
  115. package/src/components/EditorToolbar/headings.ts +45 -51
  116. package/src/components/EditorToolbar/image.ts +16 -14
  117. package/src/components/EditorToolbar/index.ts +2 -3
  118. package/src/components/EditorToolbar/lists.ts +58 -0
  119. package/src/components/EditorToolbar/search.ts +16 -14
  120. package/src/components/EditorToolbar/types.ts +8 -0
  121. package/src/components/EditorToolbar/view-mode.ts +37 -43
  122. package/src/components/index.ts +0 -5
  123. package/src/extensions/Assistant.stories.tsx +112 -0
  124. package/src/extensions/assistant-extension.tsx +223 -0
  125. package/src/extensions/index.ts +2 -32
  126. package/src/hooks/index.ts +1 -0
  127. package/src/hooks/useBasicMarkdownExtensions.ts +55 -0
  128. package/src/hooks/useTextEditor.ts +9 -3
  129. package/src/index.ts +0 -13
  130. package/src/stories/Automerge.stories.tsx +177 -0
  131. package/src/stories/Comments.stories.tsx +48 -43
  132. package/src/stories/EditorToolbar.stories.tsx +40 -53
  133. package/src/stories/Experimental.stories.tsx +14 -16
  134. package/src/stories/Markdown.stories.tsx +16 -16
  135. package/src/stories/Outliner.stories.tsx +11 -12
  136. package/src/stories/Popover.stories.tsx +30 -34
  137. package/src/stories/Preview.stories.tsx +72 -58
  138. package/src/stories/Tags.stories.tsx +24 -15
  139. package/src/stories/TextEditor.stories.tsx +13 -19
  140. package/src/stories/Theme.stories.tsx +61 -0
  141. package/src/stories/components/EditorStory.tsx +33 -30
  142. package/src/stories/components/util.tsx +51 -52
  143. package/src/translations.ts +30 -25
  144. package/src/util/index.ts +1 -6
  145. package/src/util/react.tsx +8 -13
  146. package/dist/lib/browser/chunk-HL3YF6WC.mjs +0 -22
  147. package/dist/lib/browser/chunk-HL3YF6WC.mjs.map +0 -7
  148. package/dist/lib/browser/types/index.mjs +0 -13
  149. package/dist/lib/browser/types/index.mjs.map +0 -7
  150. package/dist/lib/node-esm/chunk-YJZGD3LY.mjs +0 -24
  151. package/dist/lib/node-esm/chunk-YJZGD3LY.mjs.map +0 -7
  152. package/dist/lib/node-esm/types/index.mjs +0 -14
  153. package/dist/lib/node-esm/types/index.mjs.map +0 -7
  154. package/dist/types/src/components/EditorContent/EditorContent.d.ts.map +0 -1
  155. package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts +0 -26
  156. package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts.map +0 -1
  157. package/dist/types/src/components/EditorContent/controller.d.ts.map +0 -1
  158. package/dist/types/src/components/EditorContent/index.d.ts +0 -3
  159. package/dist/types/src/components/EditorContent/index.d.ts.map +0 -1
  160. package/dist/types/src/components/EditorMenuProvider/util.d.ts +0 -8
  161. package/dist/types/src/components/EditorMenuProvider/util.d.ts.map +0 -1
  162. package/dist/types/src/components/EditorToolbar/actions.d.ts +0 -39
  163. package/dist/types/src/components/EditorToolbar/actions.d.ts.map +0 -1
  164. package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts +0 -11
  165. package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts.map +0 -1
  166. package/dist/types/src/defaults.d.ts +0 -14
  167. package/dist/types/src/defaults.d.ts.map +0 -1
  168. package/dist/types/src/extensions/annotations.d.ts +0 -9
  169. package/dist/types/src/extensions/annotations.d.ts.map +0 -1
  170. package/dist/types/src/extensions/autocomplete/autocomplete.d.ts +0 -17
  171. package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +0 -1
  172. package/dist/types/src/extensions/autocomplete/index.d.ts +0 -5
  173. package/dist/types/src/extensions/autocomplete/index.d.ts.map +0 -1
  174. package/dist/types/src/extensions/autocomplete/match.d.ts +0 -13
  175. package/dist/types/src/extensions/autocomplete/match.d.ts.map +0 -1
  176. package/dist/types/src/extensions/autocomplete/placeholder.d.ts +0 -20
  177. package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +0 -1
  178. package/dist/types/src/extensions/autocomplete/typeahead.d.ts +0 -10
  179. package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +0 -1
  180. package/dist/types/src/extensions/automerge/automerge.d.ts +0 -4
  181. package/dist/types/src/extensions/automerge/automerge.d.ts.map +0 -1
  182. package/dist/types/src/extensions/automerge/automerge.stories.d.ts +0 -47
  183. package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +0 -1
  184. package/dist/types/src/extensions/automerge/automerge.test.d.ts +0 -2
  185. package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +0 -1
  186. package/dist/types/src/extensions/automerge/cursor.d.ts +0 -4
  187. package/dist/types/src/extensions/automerge/cursor.d.ts.map +0 -1
  188. package/dist/types/src/extensions/automerge/defs.d.ts +0 -17
  189. package/dist/types/src/extensions/automerge/defs.d.ts.map +0 -1
  190. package/dist/types/src/extensions/automerge/index.d.ts +0 -2
  191. package/dist/types/src/extensions/automerge/index.d.ts.map +0 -1
  192. package/dist/types/src/extensions/automerge/sync.d.ts +0 -17
  193. package/dist/types/src/extensions/automerge/sync.d.ts.map +0 -1
  194. package/dist/types/src/extensions/automerge/update-automerge.d.ts +0 -6
  195. package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +0 -1
  196. package/dist/types/src/extensions/automerge/update-codemirror.d.ts +0 -5
  197. package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +0 -1
  198. package/dist/types/src/extensions/autoscroll.d.ts +0 -20
  199. package/dist/types/src/extensions/autoscroll.d.ts.map +0 -1
  200. package/dist/types/src/extensions/awareness/awareness-provider.d.ts +0 -31
  201. package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +0 -1
  202. package/dist/types/src/extensions/awareness/awareness.d.ts +0 -46
  203. package/dist/types/src/extensions/awareness/awareness.d.ts.map +0 -1
  204. package/dist/types/src/extensions/awareness/index.d.ts +0 -3
  205. package/dist/types/src/extensions/awareness/index.d.ts.map +0 -1
  206. package/dist/types/src/extensions/blast.d.ts +0 -25
  207. package/dist/types/src/extensions/blast.d.ts.map +0 -1
  208. package/dist/types/src/extensions/blocks.d.ts +0 -2
  209. package/dist/types/src/extensions/blocks.d.ts.map +0 -1
  210. package/dist/types/src/extensions/bookmarks.d.ts +0 -12
  211. package/dist/types/src/extensions/bookmarks.d.ts.map +0 -1
  212. package/dist/types/src/extensions/comments.d.ts +0 -95
  213. package/dist/types/src/extensions/comments.d.ts.map +0 -1
  214. package/dist/types/src/extensions/debug.d.ts +0 -3
  215. package/dist/types/src/extensions/debug.d.ts.map +0 -1
  216. package/dist/types/src/extensions/dnd.d.ts +0 -9
  217. package/dist/types/src/extensions/dnd.d.ts.map +0 -1
  218. package/dist/types/src/extensions/factories.d.ts +0 -83
  219. package/dist/types/src/extensions/factories.d.ts.map +0 -1
  220. package/dist/types/src/extensions/focus.d.ts +0 -7
  221. package/dist/types/src/extensions/focus.d.ts.map +0 -1
  222. package/dist/types/src/extensions/folding.d.ts +0 -7
  223. package/dist/types/src/extensions/folding.d.ts.map +0 -1
  224. package/dist/types/src/extensions/hashtag.d.ts +0 -3
  225. package/dist/types/src/extensions/hashtag.d.ts.map +0 -1
  226. package/dist/types/src/extensions/json.d.ts +0 -7
  227. package/dist/types/src/extensions/json.d.ts.map +0 -1
  228. package/dist/types/src/extensions/listener.d.ts +0 -13
  229. package/dist/types/src/extensions/listener.d.ts.map +0 -1
  230. package/dist/types/src/extensions/markdown/action.d.ts +0 -12
  231. package/dist/types/src/extensions/markdown/action.d.ts.map +0 -1
  232. package/dist/types/src/extensions/markdown/bundle.d.ts +0 -22
  233. package/dist/types/src/extensions/markdown/bundle.d.ts.map +0 -1
  234. package/dist/types/src/extensions/markdown/changes.d.ts +0 -10
  235. package/dist/types/src/extensions/markdown/changes.d.ts.map +0 -1
  236. package/dist/types/src/extensions/markdown/changes.test.d.ts +0 -2
  237. package/dist/types/src/extensions/markdown/changes.test.d.ts.map +0 -1
  238. package/dist/types/src/extensions/markdown/debug.d.ts +0 -11
  239. package/dist/types/src/extensions/markdown/debug.d.ts.map +0 -1
  240. package/dist/types/src/extensions/markdown/decorate.d.ts +0 -25
  241. package/dist/types/src/extensions/markdown/decorate.d.ts.map +0 -1
  242. package/dist/types/src/extensions/markdown/formatting.d.ts +0 -61
  243. package/dist/types/src/extensions/markdown/formatting.d.ts.map +0 -1
  244. package/dist/types/src/extensions/markdown/formatting.test.d.ts +0 -3
  245. package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +0 -1
  246. package/dist/types/src/extensions/markdown/highlight.d.ts +0 -37
  247. package/dist/types/src/extensions/markdown/highlight.d.ts.map +0 -1
  248. package/dist/types/src/extensions/markdown/image.d.ts +0 -7
  249. package/dist/types/src/extensions/markdown/image.d.ts.map +0 -1
  250. package/dist/types/src/extensions/markdown/index.d.ts +0 -10
  251. package/dist/types/src/extensions/markdown/index.d.ts.map +0 -1
  252. package/dist/types/src/extensions/markdown/link.d.ts +0 -7
  253. package/dist/types/src/extensions/markdown/link.d.ts.map +0 -1
  254. package/dist/types/src/extensions/markdown/parser.test.d.ts +0 -2
  255. package/dist/types/src/extensions/markdown/parser.test.d.ts.map +0 -1
  256. package/dist/types/src/extensions/markdown/styles.d.ts +0 -4
  257. package/dist/types/src/extensions/markdown/styles.d.ts.map +0 -1
  258. package/dist/types/src/extensions/markdown/table.d.ts +0 -8
  259. package/dist/types/src/extensions/markdown/table.d.ts.map +0 -1
  260. package/dist/types/src/extensions/mention.d.ts +0 -7
  261. package/dist/types/src/extensions/mention.d.ts.map +0 -1
  262. package/dist/types/src/extensions/modal.d.ts +0 -7
  263. package/dist/types/src/extensions/modal.d.ts.map +0 -1
  264. package/dist/types/src/extensions/modes.d.ts +0 -10
  265. package/dist/types/src/extensions/modes.d.ts.map +0 -1
  266. package/dist/types/src/extensions/outliner/commands.d.ts +0 -10
  267. package/dist/types/src/extensions/outliner/commands.d.ts.map +0 -1
  268. package/dist/types/src/extensions/outliner/editor.d.ts +0 -5
  269. package/dist/types/src/extensions/outliner/editor.d.ts.map +0 -1
  270. package/dist/types/src/extensions/outliner/editor.test.d.ts +0 -2
  271. package/dist/types/src/extensions/outliner/editor.test.d.ts.map +0 -1
  272. package/dist/types/src/extensions/outliner/index.d.ts +0 -4
  273. package/dist/types/src/extensions/outliner/index.d.ts.map +0 -1
  274. package/dist/types/src/extensions/outliner/menu.d.ts +0 -8
  275. package/dist/types/src/extensions/outliner/menu.d.ts.map +0 -1
  276. package/dist/types/src/extensions/outliner/outliner.d.ts +0 -11
  277. package/dist/types/src/extensions/outliner/outliner.d.ts.map +0 -1
  278. package/dist/types/src/extensions/outliner/outliner.test.d.ts +0 -2
  279. package/dist/types/src/extensions/outliner/outliner.test.d.ts.map +0 -1
  280. package/dist/types/src/extensions/outliner/selection.d.ts +0 -12
  281. package/dist/types/src/extensions/outliner/selection.d.ts.map +0 -1
  282. package/dist/types/src/extensions/outliner/tree.d.ts +0 -79
  283. package/dist/types/src/extensions/outliner/tree.d.ts.map +0 -1
  284. package/dist/types/src/extensions/outliner/tree.test.d.ts +0 -2
  285. package/dist/types/src/extensions/outliner/tree.test.d.ts.map +0 -1
  286. package/dist/types/src/extensions/preview/index.d.ts +0 -2
  287. package/dist/types/src/extensions/preview/index.d.ts.map +0 -1
  288. package/dist/types/src/extensions/preview/preview.d.ts +0 -32
  289. package/dist/types/src/extensions/preview/preview.d.ts.map +0 -1
  290. package/dist/types/src/extensions/replacer.d.ts +0 -21
  291. package/dist/types/src/extensions/replacer.d.ts.map +0 -1
  292. package/dist/types/src/extensions/replacer.test.d.ts +0 -2
  293. package/dist/types/src/extensions/replacer.test.d.ts.map +0 -1
  294. package/dist/types/src/extensions/scrolling.d.ts +0 -78
  295. package/dist/types/src/extensions/scrolling.d.ts.map +0 -1
  296. package/dist/types/src/extensions/selection.d.ts +0 -24
  297. package/dist/types/src/extensions/selection.d.ts.map +0 -1
  298. package/dist/types/src/extensions/state.d.ts +0 -2
  299. package/dist/types/src/extensions/state.d.ts.map +0 -1
  300. package/dist/types/src/extensions/submit.d.ts +0 -10
  301. package/dist/types/src/extensions/submit.d.ts.map +0 -1
  302. package/dist/types/src/extensions/tab.d.ts +0 -4
  303. package/dist/types/src/extensions/tab.d.ts.map +0 -1
  304. package/dist/types/src/extensions/tags/extended-markdown.d.ts +0 -10
  305. package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +0 -1
  306. package/dist/types/src/extensions/tags/extended-markdown.test.d.ts +0 -2
  307. package/dist/types/src/extensions/tags/extended-markdown.test.d.ts.map +0 -1
  308. package/dist/types/src/extensions/tags/index.d.ts +0 -4
  309. package/dist/types/src/extensions/tags/index.d.ts.map +0 -1
  310. package/dist/types/src/extensions/tags/streamer.d.ts +0 -12
  311. package/dist/types/src/extensions/tags/streamer.d.ts.map +0 -1
  312. package/dist/types/src/extensions/tags/xml-tags.d.ts +0 -97
  313. package/dist/types/src/extensions/tags/xml-tags.d.ts.map +0 -1
  314. package/dist/types/src/extensions/tags/xml-util.d.ts +0 -10
  315. package/dist/types/src/extensions/tags/xml-util.d.ts.map +0 -1
  316. package/dist/types/src/extensions/typewriter.d.ts +0 -10
  317. package/dist/types/src/extensions/typewriter.d.ts.map +0 -1
  318. package/dist/types/src/stories/CommandDialog.stories.d.ts +0 -14
  319. package/dist/types/src/stories/CommandDialog.stories.d.ts.map +0 -1
  320. package/dist/types/src/styles/index.d.ts +0 -4
  321. package/dist/types/src/styles/index.d.ts.map +0 -1
  322. package/dist/types/src/styles/markdown.d.ts +0 -8
  323. package/dist/types/src/styles/markdown.d.ts.map +0 -1
  324. package/dist/types/src/styles/theme.d.ts +0 -38
  325. package/dist/types/src/styles/theme.d.ts.map +0 -1
  326. package/dist/types/src/styles/tokens.d.ts +0 -3
  327. package/dist/types/src/styles/tokens.d.ts.map +0 -1
  328. package/dist/types/src/types/index.d.ts +0 -2
  329. package/dist/types/src/types/index.d.ts.map +0 -1
  330. package/dist/types/src/types/types.d.ts +0 -21
  331. package/dist/types/src/types/types.d.ts.map +0 -1
  332. package/dist/types/src/util/cursor.d.ts +0 -31
  333. package/dist/types/src/util/cursor.d.ts.map +0 -1
  334. package/dist/types/src/util/debug.d.ts +0 -21
  335. package/dist/types/src/util/debug.d.ts.map +0 -1
  336. package/dist/types/src/util/decorations.d.ts +0 -4
  337. package/dist/types/src/util/decorations.d.ts.map +0 -1
  338. package/dist/types/src/util/dom.d.ts +0 -10
  339. package/dist/types/src/util/dom.d.ts.map +0 -1
  340. package/dist/types/src/util/facet.d.ts +0 -3
  341. package/dist/types/src/util/facet.d.ts.map +0 -1
  342. package/src/components/EditorContent/EditorContent.stories.tsx +0 -70
  343. package/src/components/EditorContent/EditorContent.tsx +0 -70
  344. package/src/components/EditorContent/index.ts +0 -6
  345. package/src/components/EditorMenuProvider/util.ts +0 -31
  346. package/src/components/EditorToolbar/actions.ts +0 -86
  347. package/src/components/EditorToolbar/useEditorToolbar.ts +0 -20
  348. package/src/defaults.ts +0 -52
  349. package/src/extensions/annotations.ts +0 -55
  350. package/src/extensions/autocomplete/autocomplete.ts +0 -151
  351. package/src/extensions/autocomplete/index.ts +0 -8
  352. package/src/extensions/autocomplete/match.ts +0 -46
  353. package/src/extensions/autocomplete/placeholder.ts +0 -117
  354. package/src/extensions/autocomplete/typeahead.ts +0 -87
  355. package/src/extensions/automerge/automerge.stories.tsx +0 -149
  356. package/src/extensions/automerge/automerge.test.tsx +0 -78
  357. package/src/extensions/automerge/automerge.ts +0 -105
  358. package/src/extensions/automerge/cursor.ts +0 -28
  359. package/src/extensions/automerge/defs.ts +0 -31
  360. package/src/extensions/automerge/index.ts +0 -5
  361. package/src/extensions/automerge/sync.ts +0 -79
  362. package/src/extensions/automerge/update-automerge.ts +0 -50
  363. package/src/extensions/automerge/update-codemirror.ts +0 -115
  364. package/src/extensions/autoscroll.ts +0 -163
  365. package/src/extensions/awareness/awareness-provider.ts +0 -127
  366. package/src/extensions/awareness/awareness.ts +0 -315
  367. package/src/extensions/awareness/index.ts +0 -6
  368. package/src/extensions/blast.ts +0 -363
  369. package/src/extensions/blocks.ts +0 -131
  370. package/src/extensions/bookmarks.ts +0 -75
  371. package/src/extensions/comments.ts +0 -598
  372. package/src/extensions/debug.ts +0 -15
  373. package/src/extensions/dnd.ts +0 -37
  374. package/src/extensions/factories.ts +0 -278
  375. package/src/extensions/focus.ts +0 -36
  376. package/src/extensions/folding.tsx +0 -43
  377. package/src/extensions/hashtag.tsx +0 -68
  378. package/src/extensions/json.ts +0 -57
  379. package/src/extensions/listener.ts +0 -32
  380. package/src/extensions/markdown/action.ts +0 -117
  381. package/src/extensions/markdown/bundle.ts +0 -105
  382. package/src/extensions/markdown/changes.test.ts +0 -26
  383. package/src/extensions/markdown/changes.ts +0 -149
  384. package/src/extensions/markdown/debug.ts +0 -44
  385. package/src/extensions/markdown/decorate.ts +0 -601
  386. package/src/extensions/markdown/formatting.test.ts +0 -498
  387. package/src/extensions/markdown/formatting.ts +0 -1265
  388. package/src/extensions/markdown/highlight.ts +0 -183
  389. package/src/extensions/markdown/image.ts +0 -118
  390. package/src/extensions/markdown/index.ts +0 -13
  391. package/src/extensions/markdown/link.ts +0 -50
  392. package/src/extensions/markdown/parser.test.ts +0 -75
  393. package/src/extensions/markdown/styles.ts +0 -135
  394. package/src/extensions/markdown/table.ts +0 -150
  395. package/src/extensions/mention.ts +0 -41
  396. package/src/extensions/modal.ts +0 -24
  397. package/src/extensions/modes.ts +0 -41
  398. package/src/extensions/outliner/commands.ts +0 -270
  399. package/src/extensions/outliner/editor.test.ts +0 -33
  400. package/src/extensions/outliner/editor.ts +0 -184
  401. package/src/extensions/outliner/index.ts +0 -7
  402. package/src/extensions/outliner/menu.ts +0 -128
  403. package/src/extensions/outliner/outliner.test.ts +0 -100
  404. package/src/extensions/outliner/outliner.ts +0 -167
  405. package/src/extensions/outliner/selection.ts +0 -50
  406. package/src/extensions/outliner/tree.test.ts +0 -168
  407. package/src/extensions/outliner/tree.ts +0 -317
  408. package/src/extensions/preview/index.ts +0 -5
  409. package/src/extensions/preview/preview.ts +0 -193
  410. package/src/extensions/replacer.test.ts +0 -75
  411. package/src/extensions/replacer.ts +0 -93
  412. package/src/extensions/scrolling.ts +0 -189
  413. package/src/extensions/selection.ts +0 -100
  414. package/src/extensions/state.ts +0 -7
  415. package/src/extensions/submit.ts +0 -62
  416. package/src/extensions/tab.ts +0 -29
  417. package/src/extensions/tags/extended-markdown.test.ts +0 -262
  418. package/src/extensions/tags/extended-markdown.ts +0 -78
  419. package/src/extensions/tags/index.ts +0 -7
  420. package/src/extensions/tags/streamer.ts +0 -243
  421. package/src/extensions/tags/xml-tags.ts +0 -500
  422. package/src/extensions/tags/xml-util.ts +0 -94
  423. package/src/extensions/typewriter.ts +0 -68
  424. package/src/stories/CommandDialog.stories.tsx +0 -83
  425. package/src/styles/index.ts +0 -7
  426. package/src/styles/markdown.ts +0 -26
  427. package/src/styles/theme.ts +0 -269
  428. package/src/styles/tokens.ts +0 -17
  429. package/src/types/index.ts +0 -5
  430. package/src/types/types.ts +0 -32
  431. package/src/util/cursor.ts +0 -56
  432. package/src/util/debug.ts +0 -69
  433. package/src/util/decorations.ts +0 -21
  434. package/src/util/dom.ts +0 -34
  435. package/src/util/facet.ts +0 -13
  436. /package/dist/types/src/components/{EditorContent → Editor}/controller.d.ts +0 -0
@@ -0,0 +1,99 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Transaction } from '@codemirror/state';
6
+ import { EditorView as NaturalEditorView } from '@codemirror/view';
7
+ import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
8
+
9
+ import { type ThemedClassName } from '@dxos/react-ui';
10
+ import { initialSync } from '@dxos/ui-editor';
11
+ import { mx } from '@dxos/ui-theme';
12
+
13
+ import { type UseTextEditorProps, useTextEditor } from '../../hooks';
14
+ import { type EditorController, createEditorController, noopController } from './controller';
15
+
16
+ export type EditorViewProps = ThemedClassName<
17
+ {
18
+ focusable?: boolean;
19
+ value?: string;
20
+ onChange?: (value: string) => void;
21
+ } & UseTextEditorProps
22
+ >;
23
+
24
+ /**
25
+ * Minimal text editor.
26
+ * NOTE: This shouold not be used with the automerge extension.
27
+ */
28
+ // TODO(burdon): Move controller to Root component, then make composable.
29
+ export const EditorView = forwardRef<EditorController, EditorViewProps>(
30
+ ({ classNames, id, extensions, selectionEnd, focusable = true, value, onChange, ...props }, forwardedRef) => {
31
+ // Hold the latest onChange in a ref so callers may pass an inline callback
32
+ // without forcing the underlying editor to be destroyed and recreated on
33
+ // every render — which would blur the focused input on each keystroke.
34
+ const onChangeRef = useRef(onChange);
35
+ onChangeRef.current = onChange;
36
+
37
+ const { parentRef, focusAttributes, view } = useTextEditor(
38
+ () => ({
39
+ id,
40
+ initialValue: value,
41
+ selectionEnd,
42
+ extensions: [
43
+ extensions ?? [],
44
+ NaturalEditorView.updateListener.of(({ view, docChanged, transactions }) => {
45
+ const isInitialSync = transactions.some((tr) => tr.annotation(Transaction.userEvent) === initialSync.value);
46
+ if (!isInitialSync && docChanged) {
47
+ onChangeRef.current?.(view.state.doc.toString());
48
+ }
49
+ }),
50
+ ],
51
+ ...props,
52
+ }),
53
+ [id, extensions, selectionEnd],
54
+ );
55
+
56
+ // External controller.
57
+ useImperativeHandle(forwardedRef, () => {
58
+ return createEditorController(view);
59
+ }, [id, view]);
60
+
61
+ // Sync the editor doc to the controlled `value` prop, but only when they
62
+ // disagree. After internal typing the prop will already match the editor's
63
+ // doc, and dispatching anyway would race fast keystrokes — a stale rAF
64
+ // closure can replace doc content with an older value, dropping characters.
65
+ useEffect(() => {
66
+ if (!view) {
67
+ return;
68
+ }
69
+ const next = value ?? '';
70
+ if (view.state.doc.toString() === next) {
71
+ return;
72
+ }
73
+ requestAnimationFrame(() => {
74
+ if (view.state.doc.toString() === next) {
75
+ return;
76
+ }
77
+ view.dispatch({
78
+ annotations: initialSync,
79
+ changes: [{ from: 0, to: view.state.doc.length, insert: next }],
80
+ selection: selectionEnd ? { anchor: next.length } : undefined,
81
+ });
82
+
83
+ if (selectionEnd) {
84
+ view.focus();
85
+ }
86
+ });
87
+ }, [view, value, selectionEnd]);
88
+
89
+ return (
90
+ <div
91
+ className={mx('w-full outline-hidden focus:border-accent-bg focus-within:border-focus-ring-subtle', classNames)}
92
+ {...(focusable ? focusAttributes : {})}
93
+ ref={parentRef}
94
+ />
95
+ );
96
+ },
97
+ );
98
+
99
+ export { type EditorController, createEditorController, noopController };
@@ -11,17 +11,26 @@ export interface EditorController {
11
11
  focus: () => void;
12
12
  }
13
13
 
14
- export const noopController: EditorController = {
14
+ // Hide `view` from own-enumerable traversal. Controllers are passed through React props/context, and the
15
+ // live `EditorView` reaches the global `window` via `view.observer.win` (CodeMirror's DOMObserver). React
16
+ // 19.2's dev render-logger walks changed props' object graphs and would otherwise descend into `window`,
17
+ // enumerate `window[0]` (a cross-origin iframe) and throw SecurityError. Direct access is unaffected.
18
+ const withHiddenView = (controller: EditorController): EditorController => {
19
+ Object.defineProperty(controller, 'view', { enumerable: false });
20
+ return controller;
21
+ };
22
+
23
+ export const noopController: EditorController = withHiddenView({
15
24
  get view() {
16
25
  return null;
17
26
  },
18
27
  getText: () => '',
19
28
  setText: () => {},
20
29
  focus: () => {},
21
- };
30
+ });
22
31
 
23
32
  export const createEditorController = (view: EditorView | null): EditorController => {
24
- return {
33
+ return withHiddenView({
25
34
  get view() {
26
35
  return view;
27
36
  },
@@ -46,5 +55,5 @@ export const createEditorController = (view: EditorView | null): EditorControlle
46
55
  }
47
56
  },
48
57
  focus: () => view?.focus(),
49
- };
58
+ });
50
59
  };
@@ -13,6 +13,7 @@ import {
13
13
  type DxAnchorActivate,
14
14
  Icon,
15
15
  Popover,
16
+ ScrollArea,
16
17
  toLocalizedString,
17
18
  useDynamicRef,
18
19
  useThemeContext,
@@ -22,7 +23,9 @@ import {
22
23
  import { type EditorMenuGroup, type EditorMenuItem } from './menu';
23
24
 
24
25
  export type EditorMenuProviderProps = PropsWithChildren<{
25
- view?: EditorView | null;
26
+ // Provided as a getter (not a value prop) so the live `EditorView` is never carried in a React prop that
27
+ // the dev render-logger would walk into a cross-origin frame. See `controller.ts` for the full rationale.
28
+ getView?: () => EditorView | null;
26
29
  groups?: EditorMenuGroup[];
27
30
  currentItem?: string;
28
31
  open?: boolean;
@@ -35,18 +38,16 @@ export type EditorMenuProviderProps = PropsWithChildren<{
35
38
  }>;
36
39
 
37
40
  /**
38
- * Implements the Popover and listens for the `dx-anchor-activate` event from the
39
- * `popover` extension's decoration.
40
- *
41
+ * Implements the Popover and listens for the `dx-anchor-activate` event from the `popover` extension's decoration.
41
42
  * NOTE: We don't use DropdownMenu because the command menu needs to manage focus explicitly.
42
43
  * I.e., focus must remain in the editor while displaying the menu (for type-ahead).
43
44
  */
44
45
  export const EditorMenuProvider = ({
45
46
  children,
46
- view,
47
+ getView,
47
48
  groups,
48
49
  currentItem,
49
- open: openParam,
50
+ open: openProp,
50
51
  defaultOpen,
51
52
  numItems = 8,
52
53
  onOpenChange,
@@ -57,13 +58,15 @@ export const EditorMenuProvider = ({
57
58
  const { tx } = useThemeContext();
58
59
  const triggerRef = useRef<HTMLButtonElement | null>(null);
59
60
 
60
- const viewRef = useDynamicRef(view);
61
+ // Hold the latest `getView` so callbacks/effects always read the current view without re-subscribing.
62
+ const getViewRef = useDynamicRef(getView);
61
63
  const [open, setOpen] = useControllableState({
62
- prop: openParam,
64
+ prop: openProp,
63
65
  defaultProp: defaultOpen,
64
66
  onChange: (open) => {
65
- invariant(viewRef.current);
66
- onOpenChange?.({ view: viewRef.current, open });
67
+ const view = getViewRef.current?.();
68
+ invariant(view);
69
+ onOpenChange?.({ view, open });
67
70
  },
68
71
  });
69
72
 
@@ -78,13 +81,14 @@ export const EditorMenuProvider = ({
78
81
  root,
79
82
  DX_ANCHOR_ACTIVATE as any,
80
83
  (event: DxAnchorActivate) => {
81
- const { trigger, refId } = event;
82
-
83
- // If this has a `refId`, then it’s probably a URL or DXN and out of scope for this component.
84
- if (!refId) {
84
+ const { trigger, dxn } = event;
85
+ if (!dxn) {
85
86
  triggerRef.current = trigger as HTMLButtonElement;
86
87
  if (onActivate) {
87
- onActivate({ view: viewRef.current!, trigger: trigger.getAttribute('data-trigger') ?? undefined });
88
+ const view = getViewRef.current?.();
89
+ if (view) {
90
+ onActivate({ view, trigger: trigger.getAttribute('data-trigger') ?? undefined });
91
+ }
88
92
  } else {
89
93
  requestAnimationFrame(() => setOpen(true));
90
94
  }
@@ -99,10 +103,11 @@ export const EditorMenuProvider = ({
99
103
 
100
104
  const handleSelect = useCallback<NonNullable<MenuProps['onSelect']>>(
101
105
  (item) => {
102
- invariant(viewRef.current);
103
- onSelect?.({ view: viewRef.current, item });
106
+ const view = getViewRef.current?.();
107
+ invariant(view);
108
+ onSelect?.({ view, item });
104
109
  },
105
- [viewRef, onSelect],
110
+ [getViewRef, onSelect],
106
111
  );
107
112
 
108
113
  const menuGroups = groups?.filter((group) => group.items.length > 0) ?? [];
@@ -115,32 +120,32 @@ export const EditorMenuProvider = ({
115
120
  <Popover.Portal>
116
121
  <Popover.Content
117
122
  align='start'
118
- classNames={tx('menu.content', 'menu--exotic-unfocusable', { elevation: 'positioned' }, [
119
- 'overflow-y-auto',
120
- !menuGroups.length && 'hidden',
121
- ])}
123
+ classNames={['flex flex-col', !menuGroups.length && 'hidden']}
122
124
  style={{
123
125
  maxBlockSize: 36 * numItems + 10,
124
126
  }}
125
- /**
126
- * NOTE: We keep the focus in the editor, but Radix routes escape key.
127
- */
127
+ // NOTE: We keep the focus in the editor, but Radix routes escape key.
128
128
  onEscapeKeyDown={() => {
129
- // NOTE: Able to cancel if not in valid state.
130
- // event.preventDefault();
131
- onCancel?.({ view: view! });
129
+ const currentView = getViewRef.current?.();
130
+ if (currentView) {
131
+ onCancel?.({ view: currentView });
132
+ }
132
133
  }}
133
134
  onOpenAutoFocus={(event) => event.preventDefault()}
134
135
  >
135
- <Popover.Viewport classNames={tx('menu.viewport', 'menu__viewport--exotic-unfocusable', {})}>
136
- <Menu groups={menuGroups} currentItem={currentItem} onSelect={handleSelect} />
136
+ <Popover.Viewport asChild classNames='dx-container'>
137
+ <ScrollArea.Root thin>
138
+ <ScrollArea.Viewport>
139
+ <Menu groups={menuGroups} currentItem={currentItem} onSelect={handleSelect} />
140
+ </ScrollArea.Viewport>
141
+ </ScrollArea.Root>
137
142
  </Popover.Viewport>
138
143
  <Popover.Arrow />
139
144
  </Popover.Content>
140
145
  </Popover.Portal>
141
146
 
142
147
  {/* Content */}
143
- <div ref={setRoot} role='none' className='contents'>
148
+ <div className='contents' ref={setRoot}>
144
149
  {children}
145
150
  </div>
146
151
  </Popover.Root>
@@ -162,7 +167,7 @@ const Menu = ({ groups, currentItem, onSelect }: MenuProps) => {
162
167
  {groups.map((group, index) => (
163
168
  <Fragment key={group.id}>
164
169
  <MenuGroup group={group} currentItem={currentItem} onSelect={onSelect} />
165
- {index < groups.length - 1 && <div className={tx('menu.separator', 'menu__item', {})} />}
170
+ {index < groups.length - 1 && <div className={tx('menu.separator', {})} />}
166
171
  </Fragment>
167
172
  ))}
168
173
  </ul>
@@ -185,7 +190,7 @@ const MenuGroup = ({ group, currentItem, onSelect }: MenuGroupProps) => {
185
190
  return (
186
191
  <>
187
192
  {group.label && (
188
- <div className={tx('menu.groupLabel', 'menu__group__label', {})}>
193
+ <div className={tx('menu.groupLabel', {})}>
189
194
  <span>{toLocalizedString(group.label, t)}</span>
190
195
  </div>
191
196
  )}
@@ -221,12 +226,8 @@ const MenuItem = ({ item, current, onSelect }: MenuItemProps) => {
221
226
  const handleSelect = useCallback(() => onSelect?.(item), [item, onSelect]);
222
227
 
223
228
  return (
224
- <li
225
- ref={listRef}
226
- className={tx('menu.item', 'menu__item--exotic-unfocusable', {}, [current && 'bg-hoverSurface'])}
227
- onClick={handleSelect}
228
- >
229
- {item.icon && <Icon icon={item.icon} size={5} />}
229
+ <li ref={listRef} className={tx('menu.item', {}, [current && 'bg-hover-surface'])} onClick={handleSelect}>
230
+ {item.icon && <Icon icon={item.icon} />}
230
231
  <span className='grow truncate'>{toLocalizedString(item.label, t)}</span>
231
232
  </li>
232
233
  );
@@ -5,7 +5,6 @@
5
5
  export * from './menu';
6
6
  export * from './menu-presets';
7
7
  export * from './popover';
8
- export * from './util';
9
8
 
10
9
  export * from './EditorMenuProvider';
11
10
  export * from './useEditorMenu';
@@ -2,9 +2,10 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { insertAtLineStart } from '@dxos/ui-editor';
6
+
5
7
  import { type EditorMenuGroup } from './menu';
6
8
  import { popoverRangeEffect } from './popover';
7
- import { insertAtLineStart } from './util';
8
9
 
9
10
  export const formattingCommands: EditorMenuGroup = {
10
11
  id: 'markdown',
@@ -109,6 +110,7 @@ export const linkSlashCommands: EditorMenuGroup = {
109
110
  label: 'Block embed',
110
111
  icon: 'ph--lego--regular',
111
112
  onSelect: ({ view, head }) => {
113
+ // Seed the same query shape as typing "@@" manually.
112
114
  view.dispatch({
113
115
  changes: { from: head, insert: '@@' },
114
116
  selection: { anchor: head + 2, head: head + 2 },
@@ -5,10 +5,9 @@
5
5
  import { type EditorView } from '@codemirror/view';
6
6
 
7
7
  import { type Label } from '@dxos/react-ui';
8
+ import { insertAtCursor } from '@dxos/ui-editor';
8
9
  import { type MaybePromise } from '@dxos/util';
9
10
 
10
- import { insertAtCursor } from './util';
11
-
12
11
  export type EditorMenuGroup = {
13
12
  id: string;
14
13
  label?: Label;
@@ -13,11 +13,10 @@ import {
13
13
  keymap,
14
14
  } from '@codemirror/view';
15
15
 
16
+ import { type PlaceholderOptions, modalStateField, placeholder } from '@dxos/ui-editor';
17
+ import { type Range } from '@dxos/ui-editor/types';
16
18
  import { isNonNullable, isTruthy } from '@dxos/util';
17
19
 
18
- import { type PlaceholderOptions, modalStateField, placeholder } from '../../extensions';
19
- import { type Range } from '../../types';
20
-
21
20
  const DELIMITERS = [' ', ':'];
22
21
 
23
22
  export type PopoverOptions = {
@@ -26,15 +25,19 @@ export type PopoverOptions = {
26
25
  placeholder?: Partial<PlaceholderOptions>;
27
26
  delimiters?: string[];
28
27
 
29
- // TODO(burdon): Auto.
30
- // activateOnTyping?: boolean;
28
+ /**
29
+ * Open the popover automatically while typing a word (no trigger character required).
30
+ * The completion range covers the word under the cursor (delimited by {@link PopoverOptions.delimiters}).
31
+ */
32
+ activateOnTyping?: boolean;
31
33
 
32
34
  // Trigger update.
33
35
  onTextChange?: (event: { view: EditorView; pos: number; text: string; trigger?: string }) => void;
34
36
  onClose?: (event: { view: EditorView }) => void;
35
37
 
36
38
  // Menu specific.
37
- onEnter?: (event: { view: EditorView }) => void;
39
+ /** Returns true when the menu consumed the key (an item was selected); false falls through. */
40
+ onEnter?: (event: { view: EditorView }) => boolean | void;
38
41
  onArrowUp?: (event: { view: EditorView }) => void;
39
42
  onArrowDown?: (event: { view: EditorView }) => void;
40
43
  };
@@ -48,12 +51,14 @@ export const popover = (options: PopoverOptions = {}): Extension => {
48
51
  Prec.highest(popoverKeymap(options)),
49
52
  popoverStateField,
50
53
  popoverTriggerListener(options),
54
+ options.activateOnTyping && popoverAutoActivate(options),
51
55
  popoverAnchorDecoration(options),
52
56
  modalStateField,
53
57
  options.trigger &&
54
58
  placeholder({
55
59
  // TODO(burdon): Translations.
56
60
  content: `Press '${Array.isArray(options.trigger) ? options.trigger[0] : options.trigger}' for commands`,
61
+ focusOnly: true,
57
62
  ...options.placeholder,
58
63
  }),
59
64
  ].filter(isTruthy);
@@ -93,6 +98,33 @@ const popoverTriggerListener = (options: PopoverOptions) =>
93
98
  }
94
99
  });
95
100
 
101
+ /**
102
+ * Open the popover while typing a word, without requiring a trigger character. Once a range is
103
+ * active, {@link popoverTriggerListener} keeps it in sync and closes it (whitespace, cursor moves).
104
+ */
105
+ const popoverAutoActivate = (options: PopoverOptions) =>
106
+ EditorView.updateListener.of(({ view, docChanged, transactions }) => {
107
+ // Only user input opens the popover — programmatic syncs (e.g. a controlled `value` update on
108
+ // mount) must not pop the menu.
109
+ if (!docChanged || !transactions.some((tr) => tr.isUserEvent('input')) || view.state.field(popoverStateField)) {
110
+ return;
111
+ }
112
+ const selection = view.state.selection.main;
113
+ if (!selection.empty) {
114
+ return;
115
+ }
116
+ const line = view.state.doc.lineAt(selection.head);
117
+ const before = line.text.slice(0, selection.head - line.from);
118
+ const idx = getLastIndexOf(before, options.delimiters ?? DELIMITERS);
119
+ const token = before.slice(idx + 1);
120
+ if (token.length === 0) {
121
+ return;
122
+ }
123
+ view.dispatch({
124
+ effects: popoverRangeEffect.of({ range: { from: line.from + idx + 1, to: selection.head } }),
125
+ });
126
+ });
127
+
96
128
  /**
97
129
  * Popover navigation.
98
130
  */
@@ -190,9 +222,10 @@ const popoverKeymap = (options: PopoverOptions) => {
190
222
  run: (view: EditorView) => {
191
223
  const range = view.state.field(popoverStateField)?.range;
192
224
  if (range) {
193
- view.dispatch({ changes: { from: range.from, to: range.to, insert: '' } });
194
- options.onEnter?.({ view });
195
- return true;
225
+ // The consumer deletes the range when it selects an item; when nothing is selectable
226
+ // (empty menu over an `activateOnTyping` range) the key must fall through so the
227
+ // typed text is preserved.
228
+ return options.onEnter?.({ view }) ?? false;
196
229
  }
197
230
 
198
231
  return false;
@@ -7,10 +7,9 @@ import { type EditorState } from '@codemirror/state';
7
7
  import { type RefObject, useCallback, useMemo, useRef, useState } from 'react';
8
8
 
9
9
  import { invariant } from '@dxos/invariant';
10
+ import { modalStateEffect } from '@dxos/ui-editor';
10
11
  import { type MaybePromise } from '@dxos/util';
11
12
 
12
- import { modalStateEffect } from '../../extensions';
13
-
14
13
  import { type EditorMenuProviderProps } from './EditorMenuProvider';
15
14
  import { type EditorMenuGroup, type EditorMenuItem } from './menu';
16
15
  import { filterMenuGroups, getMenuItem, getNextMenuItem, getPreviousMenuItem } from './menu';
@@ -26,7 +25,7 @@ export type GetMenuContext = {
26
25
  export type UseEditorMenuProps = {
27
26
  filter?: boolean;
28
27
  getMenu?: (context: GetMenuContext) => MaybePromise<EditorMenuGroup[]>;
29
- } & Pick<PopoverOptions, 'trigger' | 'triggerKey' | 'placeholder'>;
28
+ } & Pick<PopoverOptions, 'trigger' | 'triggerKey' | 'placeholder' | 'activateOnTyping'>;
30
29
 
31
30
  export type UseEditorMenu = {
32
31
  groupsRef: RefObject<EditorMenuGroup[]>;
@@ -38,7 +37,7 @@ export type UseEditorMenu = {
38
37
  * const { groupsRef, extension, ...menuProps } = useEditorMenu();
39
38
  * const { parentRef, viewRef } = useTextEditor({ extensions: [extension] });
40
39
  * return (
41
- * <EditorMenuProvider view={viewRef.current} groups={groupsRef.current} {...menuProps}>
40
+ * <EditorMenuProvider getView={() => viewRef.current} groups={groupsRef.current} {...menuProps}>
42
41
  * <div ref={parentRef} />
43
42
  * </EditorMenuProvider>
44
43
  * );
@@ -48,6 +47,7 @@ export const useEditorMenu = ({
48
47
  trigger,
49
48
  triggerKey,
50
49
  placeholder,
50
+ activateOnTyping,
51
51
  filter = true,
52
52
  getMenu,
53
53
  }: UseEditorMenuProps): UseEditorMenu => {
@@ -63,7 +63,8 @@ export const useEditorMenu = ({
63
63
  const getMenuOptions = useCallback<NonNullable<UseEditorMenuProps['getMenu']>>(
64
64
  async ({ text, trigger, ...props }) => {
65
65
  const groups = (await getMenu?.({ text, trigger, ...props })) ?? [];
66
- return filter
66
+ // The "@" menu can use "@@" as syntax for block embeds, so it owns its own query filtering.
67
+ return filter && trigger !== '@'
67
68
  ? filterMenuGroups(groups, (item) =>
68
69
  text ? (item.label as string).toLowerCase().startsWith(text.toLowerCase()) : true,
69
70
  )
@@ -74,7 +75,6 @@ export const useEditorMenu = ({
74
75
 
75
76
  const handleOpenChange = useCallback<NonNullable<UseEditorMenu['onOpenChange']>>(
76
77
  async ({ view, open }) => {
77
- console.log(view, open);
78
78
  invariant(view);
79
79
  setOpen(open);
80
80
  if (!open) {
@@ -110,7 +110,13 @@ export const useEditorMenu = ({
110
110
  );
111
111
 
112
112
  const handleSelect = useCallback<NonNullable<UseEditorMenu['onSelect']>>(({ view, item }) => {
113
+ // Delete trigger range (e.g., "/" and any typed filter text).
114
+ const { range } = view.state.field(popoverStateField) ?? {};
115
+ if (range) {
116
+ view.dispatch({ changes: { from: range.from, to: range.to, insert: '' } });
117
+ }
113
118
  void item.onSelect?.({ view, head: view.state.selection.main.head });
119
+ view.focus();
114
120
  }, []);
115
121
 
116
122
  const handleCancel = useCallback<NonNullable<UseEditorMenu['onCancel']>>(({ view }) => {
@@ -129,11 +135,14 @@ export const useEditorMenu = ({
129
135
  trigger,
130
136
  triggerKey,
131
137
  placeholder,
138
+ activateOnTyping,
132
139
  onClose: ({ view }) => handleOpenChange({ view, open: false }),
133
140
  onEnter: ({ view }) => {
134
141
  if (currentRef.current) {
135
142
  handleSelect({ view, item: currentRef.current });
143
+ return true;
136
144
  }
145
+ return false;
137
146
  },
138
147
  onArrowUp: () => {
139
148
  setCurrentItem((currentItem) => {
@@ -155,12 +164,17 @@ export const useEditorMenu = ({
155
164
  if (firstItem) {
156
165
  setCurrentItem(firstItem.id);
157
166
  currentRef.current = firstItem;
167
+ } else {
168
+ // No matches: clear the selection so Enter falls through instead of
169
+ // selecting a stale item from a previous query.
170
+ setCurrentItem(undefined);
171
+ currentRef.current = null;
158
172
  }
159
173
 
160
174
  refresh({});
161
175
  },
162
176
  });
163
- }, [handleOpenChange, getMenuOptions, serializedTrigger, placeholder]);
177
+ }, [handleOpenChange, getMenuOptions, serializedTrigger, placeholder, activateOnTyping]);
164
178
 
165
179
  return {
166
180
  groupsRef,
@@ -7,8 +7,7 @@ import React, { type PropsWithChildren, type RefObject, useCallback, useEffect,
7
7
 
8
8
  import { addEventListener } from '@dxos/async';
9
9
  import { DX_ANCHOR_ACTIVATE, type DxAnchorActivate, Popover } from '@dxos/react-ui';
10
-
11
- import { type PreviewLinkRef, type PreviewLinkTarget } from '../../extensions';
10
+ import { type PreviewLinkRef, type PreviewLinkTarget } from '@dxos/ui-editor';
12
11
 
13
12
  type EditorPreviewPopoverValue = Partial<{
14
13
  link: PreviewLinkRef;
@@ -33,16 +32,16 @@ export const EditorPreviewProvider = ({ children, onLookup }: EditorPreviewProvi
33
32
 
34
33
  const handleActivate = useCallback(
35
34
  (event: DxAnchorActivate) => {
36
- const { refId, label, trigger: dxTrigger } = event;
35
+ const { dxn, label, trigger } = event;
37
36
  setValue((value) => ({
38
37
  ...value,
39
- link: { label, ref: refId },
38
+ link: { label, dxn },
40
39
  pending: true,
41
40
  }));
42
41
 
43
- triggerRef.current = dxTrigger;
42
+ triggerRef.current = trigger;
44
43
  queueMicrotask(() => setOpen(true));
45
- void onLookup?.({ label, ref: refId }).then((target) =>
44
+ void onLookup?.({ label, dxn }).then((target) =>
46
45
  setValue((value) => ({
47
46
  ...value,
48
47
  target: target ?? undefined,
@@ -69,9 +68,7 @@ export const EditorPreviewProvider = ({ children, onLookup }: EditorPreviewProvi
69
68
  <EditorPreviewContextProvider pending={value.pending} link={value.link} target={value.target}>
70
69
  <Popover.Root open={open} onOpenChange={setOpen}>
71
70
  <Popover.VirtualTrigger virtualRef={triggerRef as unknown as RefObject<HTMLButtonElement>} />
72
-
73
- {/* Content */}
74
- <div ref={setRoot} role='none' className='contents'>
71
+ <div className='contents' ref={setRoot}>
75
72
  {children}
76
73
  </div>
77
74
  </Popover.Root>