@dxos/react-ui-editor 0.8.4-main.3f58842 → 0.8.4-main.548089c

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 (340) hide show
  1. package/dist/lib/browser/{chunk-22UMM3QJ.mjs → chunk-HL3YF6WC.mjs} +2 -2
  2. package/dist/lib/browser/chunk-HL3YF6WC.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +8004 -6623
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +71 -1
  7. package/dist/lib/browser/testing/index.mjs.map +4 -4
  8. package/dist/lib/browser/types/index.mjs +1 -1
  9. package/dist/lib/node-esm/{chunk-YXYQPV6R.mjs → chunk-YJZGD3LY.mjs} +2 -2
  10. package/dist/lib/node-esm/chunk-YJZGD3LY.mjs.map +7 -0
  11. package/dist/lib/node-esm/index.mjs +8004 -6623
  12. package/dist/lib/node-esm/index.mjs.map +4 -4
  13. package/dist/lib/node-esm/meta.json +1 -1
  14. package/dist/lib/node-esm/testing/index.mjs +71 -1
  15. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  16. package/dist/lib/node-esm/types/index.mjs +1 -1
  17. package/dist/types/src/components/Editor/Editor.d.ts +24 -9
  18. package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
  19. package/dist/types/src/components/Editor/Editor.stories.d.ts +27 -0
  20. package/dist/types/src/components/Editor/Editor.stories.d.ts.map +1 -0
  21. package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +17 -2
  22. package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
  23. package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
  24. package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
  25. package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
  26. package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -1
  27. package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -1
  28. package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -1
  29. package/dist/types/src/components/EditorToolbar/util.d.ts +8 -22
  30. package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -1
  31. package/dist/types/src/components/EditorToolbar/view-mode.d.ts +1 -1
  32. package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
  33. package/dist/types/src/components/index.d.ts +0 -1
  34. package/dist/types/src/components/index.d.ts.map +1 -1
  35. package/dist/types/src/defaults.d.ts.map +1 -1
  36. package/dist/types/src/extensions/autocomplete/autocomplete.d.ts +26 -0
  37. package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +1 -0
  38. package/dist/types/src/extensions/autocomplete/index.d.ts +5 -0
  39. package/dist/types/src/extensions/autocomplete/index.d.ts.map +1 -0
  40. package/dist/types/src/extensions/autocomplete/match.d.ts +13 -0
  41. package/dist/types/src/extensions/autocomplete/match.d.ts.map +1 -0
  42. package/dist/types/src/extensions/autocomplete/placeholder.d.ts +20 -0
  43. package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +1 -0
  44. package/dist/types/src/extensions/autocomplete/typeahead.d.ts +10 -0
  45. package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +1 -0
  46. package/dist/types/src/extensions/automerge/automerge.d.ts +1 -1
  47. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  48. package/dist/types/src/extensions/automerge/automerge.stories.d.ts +10 -19
  49. package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
  50. package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
  51. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
  52. package/dist/types/src/extensions/automerge/defs.d.ts +1 -1
  53. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
  54. package/dist/types/src/extensions/automerge/sync.d.ts +3 -3
  55. package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
  56. package/dist/types/src/extensions/automerge/update-automerge.d.ts +1 -1
  57. package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
  58. package/dist/types/src/extensions/autoscroll.d.ts +20 -0
  59. package/dist/types/src/extensions/autoscroll.d.ts.map +1 -0
  60. package/dist/types/src/extensions/awareness/awareness-provider.d.ts +1 -1
  61. package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -1
  62. package/dist/types/src/extensions/blocks.d.ts +2 -0
  63. package/dist/types/src/extensions/blocks.d.ts.map +1 -0
  64. package/dist/types/src/extensions/bookmarks.d.ts +12 -0
  65. package/dist/types/src/extensions/bookmarks.d.ts.map +1 -0
  66. package/dist/types/src/extensions/comments.d.ts +1 -1
  67. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  68. package/dist/types/src/extensions/dnd.d.ts.map +1 -1
  69. package/dist/types/src/extensions/factories.d.ts +11 -11
  70. package/dist/types/src/extensions/factories.d.ts.map +1 -1
  71. package/dist/types/src/extensions/focus.d.ts.map +1 -1
  72. package/dist/types/src/extensions/folding.d.ts.map +1 -1
  73. package/dist/types/src/extensions/index.d.ts +8 -1
  74. package/dist/types/src/extensions/index.d.ts.map +1 -1
  75. package/dist/types/src/extensions/json.d.ts +1 -1
  76. package/dist/types/src/extensions/json.d.ts.map +1 -1
  77. package/dist/types/src/extensions/listener.d.ts +8 -6
  78. package/dist/types/src/extensions/listener.d.ts.map +1 -1
  79. package/dist/types/src/extensions/markdown/action.d.ts.map +1 -1
  80. package/dist/types/src/extensions/markdown/bundle.d.ts +8 -2
  81. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  82. package/dist/types/src/extensions/markdown/changes.d.ts +1 -1
  83. package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -1
  84. package/dist/types/src/extensions/markdown/decorate.d.ts +9 -1
  85. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  86. package/dist/types/src/extensions/markdown/formatting.d.ts +2 -3
  87. package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
  88. package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -1
  89. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  90. package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
  91. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
  92. package/dist/types/src/extensions/modes.d.ts +1 -1
  93. package/dist/types/src/extensions/modes.d.ts.map +1 -1
  94. package/dist/types/src/extensions/outliner/menu.d.ts +8 -0
  95. package/dist/types/src/extensions/outliner/menu.d.ts.map +1 -0
  96. package/dist/types/src/extensions/outliner/outliner.d.ts +1 -1
  97. package/dist/types/src/extensions/outliner/outliner.d.ts.map +1 -1
  98. package/dist/types/src/extensions/outliner/selection.d.ts.map +1 -1
  99. package/dist/types/src/extensions/outliner/tree.d.ts +2 -2
  100. package/dist/types/src/extensions/outliner/tree.d.ts.map +1 -1
  101. package/dist/types/src/extensions/popover/PopoverMenuProvider.d.ts +36 -0
  102. package/dist/types/src/extensions/popover/PopoverMenuProvider.d.ts.map +1 -0
  103. package/dist/types/src/extensions/popover/index.d.ts +8 -0
  104. package/dist/types/src/extensions/popover/index.d.ts.map +1 -0
  105. package/dist/types/src/extensions/popover/menu-presets.d.ts +4 -0
  106. package/dist/types/src/extensions/popover/menu-presets.d.ts.map +1 -0
  107. package/dist/types/src/extensions/popover/menu.d.ts +24 -0
  108. package/dist/types/src/extensions/popover/menu.d.ts.map +1 -0
  109. package/dist/types/src/extensions/popover/modal.d.ts +7 -0
  110. package/dist/types/src/extensions/popover/modal.d.ts.map +1 -0
  111. package/dist/types/src/extensions/popover/popover.d.ts +47 -0
  112. package/dist/types/src/extensions/popover/popover.d.ts.map +1 -0
  113. package/dist/types/src/extensions/popover/usePopoverMenu.d.ts +34 -0
  114. package/dist/types/src/extensions/popover/usePopoverMenu.d.ts.map +1 -0
  115. package/dist/types/src/extensions/popover/util.d.ts +8 -0
  116. package/dist/types/src/extensions/popover/util.d.ts.map +1 -0
  117. package/dist/types/src/extensions/preview/preview.d.ts +8 -8
  118. package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
  119. package/dist/types/src/extensions/replacer.d.ts +21 -0
  120. package/dist/types/src/extensions/replacer.d.ts.map +1 -0
  121. package/dist/types/src/extensions/replacer.test.d.ts +2 -0
  122. package/dist/types/src/extensions/replacer.test.d.ts.map +1 -0
  123. package/dist/types/src/extensions/scrolling.d.ts +78 -0
  124. package/dist/types/src/extensions/scrolling.d.ts.map +1 -0
  125. package/dist/types/src/extensions/state.d.ts +2 -0
  126. package/dist/types/src/extensions/state.d.ts.map +1 -0
  127. package/dist/types/src/extensions/tags/extended-markdown.d.ts +10 -0
  128. package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +1 -0
  129. package/dist/types/src/extensions/tags/extended-markdown.test.d.ts +2 -0
  130. package/dist/types/src/extensions/tags/extended-markdown.test.d.ts.map +1 -0
  131. package/dist/types/src/extensions/tags/index.d.ts +4 -0
  132. package/dist/types/src/extensions/tags/index.d.ts.map +1 -0
  133. package/dist/types/src/extensions/tags/streamer.d.ts +12 -0
  134. package/dist/types/src/extensions/tags/streamer.d.ts.map +1 -0
  135. package/dist/types/src/extensions/tags/xml-tags.d.ts +97 -0
  136. package/dist/types/src/extensions/tags/xml-tags.d.ts.map +1 -0
  137. package/dist/types/src/extensions/tags/xml-util.d.ts +10 -0
  138. package/dist/types/src/extensions/tags/xml-util.d.ts.map +1 -0
  139. package/dist/types/src/hooks/useTextEditor.d.ts +4 -8
  140. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  141. package/dist/types/src/stories/CommandDialog.stories.d.ts +14 -0
  142. package/dist/types/src/stories/CommandDialog.stories.d.ts.map +1 -0
  143. package/dist/types/src/stories/Comments.stories.d.ts +21 -10
  144. package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
  145. package/dist/types/src/stories/EditorToolbar.stories.d.ts +39 -3
  146. package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
  147. package/dist/types/src/stories/Experimental.stories.d.ts +22 -13
  148. package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
  149. package/dist/types/src/stories/Markdown.stories.d.ts +32 -43
  150. package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
  151. package/dist/types/src/stories/Outliner.stories.d.ts +15 -21
  152. package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
  153. package/dist/types/src/stories/Popover.stories.d.ts +20 -0
  154. package/dist/types/src/stories/Popover.stories.d.ts.map +1 -0
  155. package/dist/types/src/stories/Preview.stories.d.ts +21 -7
  156. package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
  157. package/dist/types/src/stories/Tags.stories.d.ts +16 -0
  158. package/dist/types/src/stories/Tags.stories.d.ts.map +1 -0
  159. package/dist/types/src/stories/TextEditor.stories.d.ts +37 -52
  160. package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
  161. package/dist/types/src/stories/components/EditorStory.d.ts +6 -9
  162. package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
  163. package/dist/types/src/stories/components/util.d.ts.map +1 -1
  164. package/dist/types/src/styles/theme.d.ts.map +1 -1
  165. package/dist/types/src/testing/PreviewPopover.d.ts +20 -0
  166. package/dist/types/src/testing/PreviewPopover.d.ts.map +1 -0
  167. package/dist/types/src/testing/index.d.ts +1 -0
  168. package/dist/types/src/testing/index.d.ts.map +1 -1
  169. package/dist/types/src/testing/util.d.ts +1 -0
  170. package/dist/types/src/testing/util.d.ts.map +1 -1
  171. package/dist/types/src/translations.d.ts +1 -1
  172. package/dist/types/src/types/types.d.ts +2 -2
  173. package/dist/types/src/types/types.d.ts.map +1 -1
  174. package/dist/types/src/util/cursor.d.ts.map +1 -1
  175. package/dist/types/src/util/debug.d.ts +1 -1
  176. package/dist/types/src/util/debug.d.ts.map +1 -1
  177. package/dist/types/src/util/decorations.d.ts +4 -0
  178. package/dist/types/src/util/decorations.d.ts.map +1 -0
  179. package/dist/types/src/util/dom.d.ts +2 -12
  180. package/dist/types/src/util/dom.d.ts.map +1 -1
  181. package/dist/types/src/util/index.d.ts +1 -0
  182. package/dist/types/src/util/index.d.ts.map +1 -1
  183. package/dist/types/src/util/react.d.ts +1 -1
  184. package/dist/types/src/util/react.d.ts.map +1 -1
  185. package/dist/types/tsconfig.tsbuildinfo +1 -1
  186. package/package.json +73 -62
  187. package/src/components/Editor/Editor.stories.tsx +69 -0
  188. package/src/components/Editor/Editor.tsx +58 -15
  189. package/src/components/EditorToolbar/EditorToolbar.tsx +106 -95
  190. package/src/components/EditorToolbar/blocks.ts +21 -24
  191. package/src/components/EditorToolbar/formatting.ts +22 -25
  192. package/src/components/EditorToolbar/headings.ts +16 -9
  193. package/src/components/EditorToolbar/image.ts +8 -4
  194. package/src/components/EditorToolbar/lists.ts +16 -19
  195. package/src/components/EditorToolbar/search.ts +8 -4
  196. package/src/components/EditorToolbar/util.ts +20 -25
  197. package/src/components/EditorToolbar/view-mode.ts +11 -6
  198. package/src/components/index.ts +0 -1
  199. package/src/defaults.ts +5 -2
  200. package/src/extensions/autocomplete/autocomplete.ts +220 -0
  201. package/src/extensions/autocomplete/index.ts +8 -0
  202. package/src/extensions/autocomplete/match.ts +46 -0
  203. package/src/extensions/{command → autocomplete}/placeholder.ts +22 -18
  204. package/src/extensions/{command → autocomplete}/typeahead.ts +8 -50
  205. package/src/extensions/automerge/automerge.stories.tsx +32 -25
  206. package/src/extensions/automerge/automerge.ts +31 -11
  207. package/src/extensions/automerge/cursor.ts +1 -1
  208. package/src/extensions/automerge/defs.ts +1 -1
  209. package/src/extensions/automerge/sync.ts +9 -5
  210. package/src/extensions/automerge/update-automerge.ts +2 -2
  211. package/src/extensions/autoscroll.ts +163 -0
  212. package/src/extensions/awareness/awareness-provider.ts +2 -2
  213. package/src/extensions/awareness/awareness.ts +2 -2
  214. package/src/extensions/blocks.ts +131 -0
  215. package/src/extensions/bookmarks.ts +75 -0
  216. package/src/extensions/comments.ts +20 -14
  217. package/src/extensions/dnd.ts +1 -1
  218. package/src/extensions/factories.ts +54 -35
  219. package/src/extensions/focus.ts +5 -4
  220. package/src/extensions/folding.tsx +3 -6
  221. package/src/extensions/hashtag.tsx +2 -2
  222. package/src/extensions/index.ts +8 -1
  223. package/src/extensions/json.ts +1 -1
  224. package/src/extensions/listener.ts +14 -20
  225. package/src/extensions/markdown/action.ts +2 -1
  226. package/src/extensions/markdown/bundle.ts +40 -6
  227. package/src/extensions/markdown/changes.ts +1 -1
  228. package/src/extensions/markdown/decorate.ts +32 -22
  229. package/src/extensions/markdown/formatting.test.ts +6 -6
  230. package/src/extensions/markdown/formatting.ts +11 -11
  231. package/src/extensions/markdown/highlight.ts +2 -2
  232. package/src/extensions/markdown/image.ts +5 -6
  233. package/src/extensions/markdown/link.ts +3 -0
  234. package/src/extensions/markdown/table.ts +13 -7
  235. package/src/extensions/mention.ts +1 -1
  236. package/src/extensions/modes.ts +2 -2
  237. package/src/extensions/{command/floating-menu.ts → outliner/menu.ts} +16 -21
  238. package/src/extensions/outliner/outliner.test.ts +3 -2
  239. package/src/extensions/outliner/outliner.ts +7 -6
  240. package/src/extensions/outliner/selection.ts +1 -1
  241. package/src/extensions/outliner/tree.test.ts +2 -1
  242. package/src/extensions/outliner/tree.ts +2 -2
  243. package/src/extensions/popover/PopoverMenuProvider.tsx +220 -0
  244. package/src/extensions/popover/index.ts +12 -0
  245. package/src/extensions/popover/menu-presets.ts +124 -0
  246. package/src/extensions/popover/menu.ts +67 -0
  247. package/src/extensions/popover/modal.ts +24 -0
  248. package/src/extensions/popover/popover.ts +289 -0
  249. package/src/extensions/popover/usePopoverMenu.ts +173 -0
  250. package/src/extensions/popover/util.ts +29 -0
  251. package/src/extensions/preview/index.ts +1 -1
  252. package/src/extensions/preview/preview.ts +69 -69
  253. package/src/extensions/replacer.test.ts +75 -0
  254. package/src/extensions/replacer.ts +93 -0
  255. package/src/extensions/scrolling.ts +189 -0
  256. package/src/extensions/selection.ts +3 -3
  257. package/src/extensions/state.ts +7 -0
  258. package/src/extensions/tags/extended-markdown.test.ts +262 -0
  259. package/src/extensions/tags/extended-markdown.ts +78 -0
  260. package/src/extensions/tags/index.ts +7 -0
  261. package/src/extensions/tags/streamer.ts +243 -0
  262. package/src/extensions/tags/xml-tags.ts +500 -0
  263. package/src/extensions/tags/xml-util.ts +94 -0
  264. package/src/extensions/typewriter.ts +1 -1
  265. package/src/hooks/useTextEditor.ts +27 -39
  266. package/src/stories/CommandDialog.stories.tsx +83 -0
  267. package/src/stories/Comments.stories.tsx +15 -11
  268. package/src/stories/EditorToolbar.stories.tsx +17 -17
  269. package/src/stories/Experimental.stories.tsx +17 -13
  270. package/src/stories/Markdown.stories.tsx +25 -21
  271. package/src/stories/Outliner.stories.tsx +54 -35
  272. package/src/stories/Popover.stories.tsx +161 -0
  273. package/src/stories/Preview.stories.tsx +48 -40
  274. package/src/stories/Tags.stories.tsx +95 -0
  275. package/src/stories/TextEditor.stories.tsx +41 -60
  276. package/src/stories/components/EditorStory.tsx +19 -18
  277. package/src/stories/components/util.tsx +39 -6
  278. package/src/styles/markdown.ts +1 -1
  279. package/src/styles/theme.ts +16 -12
  280. package/src/testing/PreviewPopover.tsx +80 -0
  281. package/src/testing/index.ts +1 -0
  282. package/src/testing/util.ts +2 -0
  283. package/src/translations.ts +1 -1
  284. package/src/types/types.ts +1 -1
  285. package/src/util/cursor.ts +2 -1
  286. package/src/util/debug.ts +2 -2
  287. package/src/util/decorations.ts +21 -0
  288. package/src/util/dom.ts +5 -27
  289. package/src/util/index.ts +1 -0
  290. package/src/util/react.tsx +1 -1
  291. package/dist/lib/browser/chunk-22UMM3QJ.mjs.map +0 -7
  292. package/dist/lib/node-esm/chunk-YXYQPV6R.mjs.map +0 -7
  293. package/dist/types/src/components/Popover/CommandMenu.d.ts +0 -34
  294. package/dist/types/src/components/Popover/CommandMenu.d.ts.map +0 -1
  295. package/dist/types/src/components/Popover/RefDropdownMenu.d.ts +0 -21
  296. package/dist/types/src/components/Popover/RefDropdownMenu.d.ts.map +0 -1
  297. package/dist/types/src/components/Popover/RefPopover.d.ts +0 -34
  298. package/dist/types/src/components/Popover/RefPopover.d.ts.map +0 -1
  299. package/dist/types/src/components/Popover/index.d.ts +0 -4
  300. package/dist/types/src/components/Popover/index.d.ts.map +0 -1
  301. package/dist/types/src/extensions/autocomplete.d.ts +0 -13
  302. package/dist/types/src/extensions/autocomplete.d.ts.map +0 -1
  303. package/dist/types/src/extensions/command/action.d.ts +0 -17
  304. package/dist/types/src/extensions/command/action.d.ts.map +0 -1
  305. package/dist/types/src/extensions/command/command-menu.d.ts +0 -20
  306. package/dist/types/src/extensions/command/command-menu.d.ts.map +0 -1
  307. package/dist/types/src/extensions/command/command.d.ts +0 -6
  308. package/dist/types/src/extensions/command/command.d.ts.map +0 -1
  309. package/dist/types/src/extensions/command/floating-menu.d.ts +0 -7
  310. package/dist/types/src/extensions/command/floating-menu.d.ts.map +0 -1
  311. package/dist/types/src/extensions/command/hint.d.ts +0 -24
  312. package/dist/types/src/extensions/command/hint.d.ts.map +0 -1
  313. package/dist/types/src/extensions/command/index.d.ts +0 -7
  314. package/dist/types/src/extensions/command/index.d.ts.map +0 -1
  315. package/dist/types/src/extensions/command/placeholder.d.ts +0 -10
  316. package/dist/types/src/extensions/command/placeholder.d.ts.map +0 -1
  317. package/dist/types/src/extensions/command/state.d.ts +0 -16
  318. package/dist/types/src/extensions/command/state.d.ts.map +0 -1
  319. package/dist/types/src/extensions/command/typeahead.d.ts +0 -22
  320. package/dist/types/src/extensions/command/typeahead.d.ts.map +0 -1
  321. package/dist/types/src/extensions/command/useCommandMenu.d.ts +0 -26
  322. package/dist/types/src/extensions/command/useCommandMenu.d.ts.map +0 -1
  323. package/dist/types/src/stories/Command.stories.d.ts +0 -7
  324. package/dist/types/src/stories/Command.stories.d.ts.map +0 -1
  325. package/dist/types/src/stories/CommandMenu.stories.d.ts +0 -13
  326. package/dist/types/src/stories/CommandMenu.stories.d.ts.map +0 -1
  327. package/src/components/Popover/CommandMenu.tsx +0 -279
  328. package/src/components/Popover/RefDropdownMenu.tsx +0 -85
  329. package/src/components/Popover/RefPopover.tsx +0 -99
  330. package/src/components/Popover/index.ts +0 -7
  331. package/src/extensions/autocomplete.ts +0 -69
  332. package/src/extensions/command/action.ts +0 -56
  333. package/src/extensions/command/command-menu.ts +0 -210
  334. package/src/extensions/command/command.ts +0 -34
  335. package/src/extensions/command/hint.ts +0 -102
  336. package/src/extensions/command/index.ts +0 -10
  337. package/src/extensions/command/state.ts +0 -89
  338. package/src/extensions/command/useCommandMenu.ts +0 -118
  339. package/src/stories/Command.stories.tsx +0 -97
  340. package/src/stories/CommandMenu.stories.tsx +0 -159
@@ -0,0 +1,289 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type Extension, Prec, RangeSetBuilder, StateEffect, StateField } from '@codemirror/state';
6
+ import {
7
+ Decoration,
8
+ type DecorationSet,
9
+ EditorView,
10
+ type KeyBinding,
11
+ ViewPlugin,
12
+ type ViewUpdate,
13
+ keymap,
14
+ } from '@codemirror/view';
15
+
16
+ import { isNonNullable, isTruthy } from '@dxos/util';
17
+
18
+ import { type Range } from '../../types';
19
+ import { type PlaceholderOptions, placeholder } from '../autocomplete';
20
+
21
+ import { modalStateField } from './modal';
22
+
23
+ const DELIMITERS = [' ', ':'];
24
+
25
+ export type PopoverOptions = {
26
+ trigger?: string | string[];
27
+ triggerKey?: string;
28
+ placeholder?: Partial<PlaceholderOptions>;
29
+ delimiters?: string[];
30
+
31
+ // TODO(burdon): Auto.
32
+ // activateOnTyping?: boolean;
33
+
34
+ // Trigger update.
35
+ onTextChange?: (event: { view: EditorView; pos: number; text: string; trigger?: string }) => void;
36
+ onClose?: (event: { view: EditorView }) => void;
37
+
38
+ // Menu specific.
39
+ onEnter?: (event: { view: EditorView }) => void;
40
+ onArrowUp?: (event: { view: EditorView }) => void;
41
+ onArrowDown?: (event: { view: EditorView }) => void;
42
+ };
43
+
44
+ /**
45
+ * Creates a popover that appears when the trigger character is inserted.
46
+ * This can be used for context menus or autocompletion.
47
+ */
48
+ export const popover = (options: PopoverOptions = {}): Extension => {
49
+ return [
50
+ Prec.highest(popoverKeymap(options)),
51
+ popoverStateField,
52
+ popoverTriggerListener(options),
53
+ popoverAnchorDecoration(options),
54
+ modalStateField,
55
+ options.trigger &&
56
+ placeholder({
57
+ // TODO(burdon): Translations.
58
+ content: `Press '${Array.isArray(options.trigger) ? options.trigger[0] : options.trigger}' for commands`,
59
+ ...options.placeholder,
60
+ }),
61
+ ].filter(isTruthy);
62
+ };
63
+
64
+ /**
65
+ * Listen for selection and document changes.
66
+ */
67
+ const popoverTriggerListener = (options: PopoverOptions) =>
68
+ EditorView.updateListener.of(({ view, docChanged }) => {
69
+ const { range: activeRange, trigger } = view.state.field(popoverStateField) ?? {};
70
+ if (!activeRange) {
71
+ return;
72
+ }
73
+
74
+ const text = view.state.doc.sliceString(activeRange.from, activeRange.to);
75
+ const selection = view.state.selection.main;
76
+ const shouldClose =
77
+ // Trigger deleted.
78
+ (trigger ? trigger !== text[0] : false) ||
79
+ // Whitespace in text.
80
+ /\s/.test(trigger ? text.slice(1) : text) ||
81
+ // Cursor moved before the range.
82
+ selection.head < activeRange.from ||
83
+ // Cursor moved after the range (+1 to handle selection changing before doc).
84
+ selection.head > activeRange.to + 1;
85
+
86
+ const nextRange = shouldClose ? null : docChanged ? { from: activeRange.from, to: selection.head } : activeRange;
87
+ if (nextRange !== activeRange) {
88
+ view.dispatch({
89
+ effects: popoverRangeEffect.of(nextRange ? { range: nextRange, trigger } : null),
90
+ });
91
+ }
92
+
93
+ if (shouldClose) {
94
+ options.onClose?.({ view });
95
+ }
96
+ });
97
+
98
+ /**
99
+ * Popover navigation.
100
+ */
101
+ const popoverKeymap = (options: PopoverOptions) => {
102
+ const triggers = Array.isArray(options.trigger) ? options.trigger : [options.trigger];
103
+ return keymap.of(
104
+ [
105
+ // Prefix triggers.
106
+ ...triggers.filter(isNonNullable).map((trigger) => ({
107
+ key: trigger,
108
+ run: (view: EditorView) => {
109
+ // Determine if we should trigger the popover:
110
+ // 1. Empty lines or at the beginning of a line
111
+ // 2. When there's a preceding space
112
+ const selection = view.state.selection.main;
113
+ const line = view.state.doc.lineAt(selection.head);
114
+ if (
115
+ line.text.trim() === '' ||
116
+ selection.head === line.from ||
117
+ (selection.head > line.from && line.text[selection.head - line.from - 1] === ' ')
118
+ ) {
119
+ // Insert and select the trigger.
120
+ view.dispatch({
121
+ changes: { from: selection.head, insert: trigger },
122
+ selection: { anchor: selection.head + 1, head: selection.head + 1 },
123
+ effects: popoverRangeEffect.of({ trigger, range: { from: selection.head, to: selection.head + 1 } }),
124
+ });
125
+
126
+ return true;
127
+ }
128
+
129
+ return false;
130
+ },
131
+ })),
132
+
133
+ //
134
+ // Custom trigger.
135
+ //
136
+ options.triggerKey &&
137
+ ({
138
+ key: options.triggerKey,
139
+ run: (view: EditorView) => {
140
+ const selection = view.state.selection.main;
141
+ const line = view.state.doc.lineAt(selection.head);
142
+
143
+ // Get last word.
144
+ let str = line.text.slice(0, selection.head - line.from);
145
+ const idx = getLastIndexOf(str, options.delimiters ?? DELIMITERS);
146
+ if (idx !== -1) {
147
+ str = str.slice(idx + 1);
148
+ }
149
+
150
+ // Create anchor even if zero length (append space).
151
+ const from = line.from + idx;
152
+ view.dispatch({
153
+ effects: popoverRangeEffect.of({ range: { from: from + 1, to: selection.head } }),
154
+ changes:
155
+ selection.head === view.state.doc.length
156
+ ? { from: from + 1, to: selection.head, insert: ' ' }
157
+ : undefined,
158
+ });
159
+ return true;
160
+ },
161
+ } satisfies KeyBinding),
162
+
163
+ //
164
+ // Nav keys.
165
+ //
166
+ {
167
+ key: 'ArrowUp',
168
+ run: (view: EditorView) => {
169
+ const range = view.state.field(popoverStateField)?.range;
170
+ if (range) {
171
+ options.onArrowUp?.({ view });
172
+ return true;
173
+ }
174
+
175
+ return false;
176
+ },
177
+ },
178
+ {
179
+ key: 'ArrowDown',
180
+ run: (view: EditorView) => {
181
+ const range = view.state.field(popoverStateField)?.range;
182
+ if (range) {
183
+ options.onArrowDown?.({ view });
184
+ return true;
185
+ }
186
+
187
+ return false;
188
+ },
189
+ },
190
+ {
191
+ key: 'Enter',
192
+ run: (view: EditorView) => {
193
+ const range = view.state.field(popoverStateField)?.range;
194
+ if (range) {
195
+ view.dispatch({ changes: { from: range.from, to: range.to, insert: '' } });
196
+ options.onEnter?.({ view });
197
+ return true;
198
+ }
199
+
200
+ return false;
201
+ },
202
+ },
203
+ ].filter(isTruthy),
204
+ );
205
+ };
206
+
207
+ /**
208
+ * Creates a <dx-anchor> tag, which is used to anchor the Popver.
209
+ */
210
+ const popoverAnchorDecoration = (options: PopoverOptions) => {
211
+ return ViewPlugin.fromClass(
212
+ class {
213
+ _decorations: DecorationSet = Decoration.none;
214
+
215
+ constructor(readonly view: EditorView) {}
216
+
217
+ // TODO(wittjosiah): The decorations are repainted on every update, this occasionally causes menu to flicker.
218
+ update({ view, transactions }: ViewUpdate) {
219
+ const builder = new RangeSetBuilder<Decoration>();
220
+ const { range, trigger } = view.state.field(popoverStateField) ?? {};
221
+ if (range) {
222
+ // Check if we should show the widget (only if cursor is within the active command range).
223
+ const selection = view.state.selection.main;
224
+ const showWidget = selection.head >= range.from && selection.head <= range.to;
225
+ if (showWidget) {
226
+ builder.add(
227
+ range.from,
228
+ range.to + 1,
229
+ Decoration.mark({
230
+ tagName: 'dx-anchor',
231
+ class: 'cm-popover-trigger',
232
+ attributes: {
233
+ 'data-visible-focus': 'false',
234
+ 'data-auto-trigger': 'true',
235
+ 'data-trigger': trigger ?? options.triggerKey ?? '',
236
+ },
237
+ }),
238
+ );
239
+ }
240
+
241
+ const rangeChanged = transactions.some((tr) => tr.effects.some((effect) => effect.is(popoverRangeEffect)));
242
+ if (rangeChanged) {
243
+ // NOTE: Content skips the trigger character.
244
+ const content = view.state.sliceDoc(range.from + (trigger ? trigger.length : 0), range.to);
245
+ options.onTextChange?.({ view, pos: selection.head, text: content, trigger });
246
+ }
247
+ }
248
+
249
+ this._decorations = builder.finish();
250
+ }
251
+ },
252
+ {
253
+ decorations: (v) => v._decorations,
254
+ },
255
+ );
256
+ };
257
+
258
+ type PopoverState = {
259
+ /**
260
+ * Trigger prefix (in document).
261
+ */
262
+ trigger?: string;
263
+
264
+ /**
265
+ * Current document completion range.
266
+ */
267
+ range: Range;
268
+ };
269
+
270
+ // State effects for managing popover state.
271
+ export const popoverRangeEffect = StateEffect.define<PopoverState | null>();
272
+
273
+ // State field to track the active popover trigger range.
274
+ export const popoverStateField = StateField.define<PopoverState | null>({
275
+ create: () => null,
276
+ update: (value, tr) => {
277
+ let newValue = value;
278
+ for (const effect of tr.effects) {
279
+ if (effect.is(popoverRangeEffect)) {
280
+ newValue = effect.value;
281
+ }
282
+ }
283
+
284
+ return newValue;
285
+ },
286
+ });
287
+
288
+ const getLastIndexOf = (str: string, delimiters: string[]) =>
289
+ Math.max(...delimiters.map((delim) => str.lastIndexOf(delim)));
@@ -0,0 +1,173 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type Extension } from '@codemirror/state';
6
+ import { type EditorState } from '@codemirror/state';
7
+ import { type RefObject, useCallback, useMemo, useRef, useState } from 'react';
8
+
9
+ import { invariant } from '@dxos/invariant';
10
+ import { type MaybePromise } from '@dxos/util';
11
+
12
+ import { type PopoverMenuGroup, type PopoverMenuItem } from './menu';
13
+ import { filterMenuGroups, getMenuItem, getNextMenuItem, getPreviousMenuItem } from './menu';
14
+ import { modalStateEffect } from './modal';
15
+ import { type PopoverOptions, popover, popoverRangeEffect, popoverStateField } from './popover';
16
+ import { type PopoverMenuProviderProps } from './PopoverMenuProvider';
17
+
18
+ export type GetMenuContext = {
19
+ state: EditorState;
20
+ pos: number;
21
+ text: string;
22
+ trigger?: string;
23
+ };
24
+
25
+ export type UsePopoverMenuProps = {
26
+ filter?: boolean;
27
+ getMenu?: (context: GetMenuContext) => MaybePromise<PopoverMenuGroup[]>;
28
+ } & Pick<PopoverOptions, 'trigger' | 'triggerKey' | 'placeholder'>;
29
+
30
+ export type UsePopoverMenu = {
31
+ groupsRef: RefObject<PopoverMenuGroup[]>;
32
+ extension: Extension;
33
+ } & Pick<PopoverMenuProviderProps, 'currentItem' | 'open' | 'onOpenChange' | 'onActivate' | 'onSelect' | 'onCancel'>;
34
+
35
+ /**
36
+ * ```tsx
37
+ * const { groupsRef, extension, ...menuProps } = usePopoverMenu();
38
+ * const { parentRef, viewRef } = useTextEditor({ extensions: [extension] });
39
+ * return (
40
+ * <PopoverMenuProvider view={viewRef.current} groups={groupsRef.current} {...menuProps}>
41
+ * <div ref={parentRef} />
42
+ * </PopoverMenuProvider>
43
+ * );
44
+ * ```
45
+ */
46
+ export const usePopoverMenu = ({
47
+ trigger,
48
+ triggerKey,
49
+ placeholder,
50
+ filter = true,
51
+ getMenu,
52
+ }: UsePopoverMenuProps): UsePopoverMenu => {
53
+ const groupsRef = useRef<PopoverMenuGroup[]>([]);
54
+ const currentRef = useRef<PopoverMenuItem | null>(null);
55
+ const [currentItem, setCurrentItem] = useState<string>();
56
+ const [open, setOpen] = useState(false);
57
+ const [_, refresh] = useState({});
58
+
59
+ /**
60
+ * Get filtered options.
61
+ */
62
+ const getMenuOptions = useCallback<NonNullable<UsePopoverMenuProps['getMenu']>>(
63
+ async ({ text, trigger, ...props }) => {
64
+ const groups = (await getMenu?.({ text, trigger, ...props })) ?? [];
65
+ return filter
66
+ ? filterMenuGroups(groups, (item) =>
67
+ text ? (item.label as string).toLowerCase().startsWith(text.toLowerCase()) : true,
68
+ )
69
+ : groups;
70
+ },
71
+ [getMenu, filter],
72
+ );
73
+
74
+ const handleOpenChange = useCallback<NonNullable<UsePopoverMenu['onOpenChange']>>(
75
+ async ({ view, open }) => {
76
+ invariant(view);
77
+ setOpen(open);
78
+ if (!open) {
79
+ setCurrentItem(undefined);
80
+ view.dispatch({
81
+ effects: [popoverRangeEffect.of(null)],
82
+ });
83
+ }
84
+
85
+ // TODO(burdon): Possible race condition.
86
+ // useTextEditor.handleKeyDown will get called after this handler completes.
87
+ requestAnimationFrame(() => {
88
+ view.dispatch({
89
+ effects: [modalStateEffect.of(open)],
90
+ });
91
+ });
92
+ },
93
+ [getMenuOptions],
94
+ );
95
+
96
+ const handleActivate = useCallback<NonNullable<UsePopoverMenu['onActivate']>>(
97
+ async ({ view, trigger }) => {
98
+ const item = getMenuItem(groupsRef.current, currentItem);
99
+ if (item) {
100
+ currentRef.current = item;
101
+ }
102
+
103
+ if (!open) {
104
+ handleOpenChange({ view, open: true, trigger });
105
+ }
106
+ },
107
+ [open, handleOpenChange],
108
+ );
109
+
110
+ const handleSelect = useCallback<NonNullable<UsePopoverMenu['onSelect']>>(({ view, item }) => {
111
+ void item.onSelect?.(view, view.state.selection.main.head);
112
+ }, []);
113
+
114
+ const handleCancel = useCallback<NonNullable<UsePopoverMenu['onCancel']>>(({ view }) => {
115
+ // Delete trigger.
116
+ const { range, trigger } = view.state.field(popoverStateField) ?? {};
117
+ if (range && trigger) {
118
+ view.dispatch({
119
+ changes: { ...range, insert: '' },
120
+ });
121
+ }
122
+ }, []);
123
+
124
+ const serializedTrigger = Array.isArray(trigger) ? trigger.join(',') : trigger;
125
+ const extension = useMemo<Extension>(() => {
126
+ return popover({
127
+ trigger,
128
+ triggerKey,
129
+ placeholder,
130
+ onClose: ({ view }) => handleOpenChange({ view, open: false }),
131
+ onEnter: ({ view }) => {
132
+ if (currentRef.current) {
133
+ handleSelect({ view, item: currentRef.current });
134
+ }
135
+ },
136
+ onArrowUp: () => {
137
+ setCurrentItem((currentItem) => {
138
+ const previous = getPreviousMenuItem(groupsRef.current, currentItem);
139
+ currentRef.current = previous;
140
+ return previous.id;
141
+ });
142
+ },
143
+ onArrowDown: () => {
144
+ setCurrentItem((currentItem) => {
145
+ const next = getNextMenuItem(groupsRef.current, currentItem);
146
+ currentRef.current = next;
147
+ return next.id;
148
+ });
149
+ },
150
+ onTextChange: async ({ view, pos, text, trigger }) => {
151
+ groupsRef.current = (await getMenuOptions({ state: view.state, pos, text, trigger })) ?? [];
152
+ const firstItem = groupsRef.current.filter((group) => group.items.length > 0)[0]?.items[0];
153
+ if (firstItem) {
154
+ setCurrentItem(firstItem.id);
155
+ currentRef.current = firstItem;
156
+ }
157
+
158
+ refresh({});
159
+ },
160
+ });
161
+ }, [handleOpenChange, getMenuOptions, serializedTrigger, placeholder]);
162
+
163
+ return {
164
+ groupsRef,
165
+ extension,
166
+ currentItem,
167
+ open,
168
+ onOpenChange: handleOpenChange,
169
+ onActivate: handleActivate,
170
+ onSelect: handleSelect,
171
+ onCancel: handleCancel,
172
+ };
173
+ };
@@ -0,0 +1,29 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type EditorView } from '@codemirror/view';
6
+
7
+ export const insertAtCursor = (view: EditorView, from: number, insert: string) => {
8
+ view.dispatch({
9
+ changes: { from, to: from, insert },
10
+ selection: { anchor: from + insert.length, head: from + insert.length },
11
+ });
12
+ };
13
+
14
+ /**
15
+ * If the cursor is at the start of a line, insert the text at the cursor.
16
+ * Otherwise, insert the text on a new line.
17
+ */
18
+ export const insertAtLineStart = (view: EditorView, from: number, insert: string) => {
19
+ const line = view.state.doc.lineAt(from);
20
+ if (line.from === from) {
21
+ insertAtCursor(view, from, insert);
22
+ } else {
23
+ insert = '\n' + insert;
24
+ view.dispatch({
25
+ changes: { from: line.to, to: line.to, insert },
26
+ selection: { anchor: line.to + insert.length, head: line.to + insert.length },
27
+ });
28
+ }
29
+ };
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright 2024 DXOS.org
2
+ // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
5
  export * from './preview';