@dxos/react-ui-editor 0.8.2-staging.7ac8446 → 0.8.3-main.672df60

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 (279) hide show
  1. package/dist/lib/browser/index.mjs +4505 -3151
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/testing/index.mjs +6 -0
  5. package/dist/lib/browser/testing/index.mjs.map +7 -0
  6. package/dist/lib/node/index.cjs +3360 -1998
  7. package/dist/lib/node/index.cjs.map +4 -4
  8. package/dist/lib/node/meta.json +1 -1
  9. package/dist/lib/node/testing/index.cjs +29 -0
  10. package/dist/lib/node/testing/index.cjs.map +7 -0
  11. package/dist/lib/node-esm/index.mjs +4505 -3151
  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 +8 -0
  15. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  16. package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +1 -1
  17. package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
  18. package/dist/types/src/components/EditorToolbar/blocks.d.ts +4 -3
  19. package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
  20. package/dist/types/src/components/EditorToolbar/formatting.d.ts +4 -3
  21. package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
  22. package/dist/types/src/components/EditorToolbar/headings.d.ts +4 -3
  23. package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
  24. package/dist/types/src/components/EditorToolbar/{comment.d.ts → image.d.ts} +4 -5
  25. package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -0
  26. package/dist/types/src/components/EditorToolbar/index.d.ts +1 -1
  27. package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
  28. package/dist/types/src/components/EditorToolbar/lists.d.ts +4 -3
  29. package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -1
  30. package/dist/types/src/components/EditorToolbar/search.d.ts +17 -0
  31. package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -0
  32. package/dist/types/src/components/EditorToolbar/util.d.ts +17 -25
  33. package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -1
  34. package/dist/types/src/components/EditorToolbar/{viewMode.d.ts → view-mode.d.ts} +5 -4
  35. package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -0
  36. package/dist/types/src/components/Popover/RefDropdownMenu.d.ts +21 -0
  37. package/dist/types/src/components/Popover/RefDropdownMenu.d.ts.map +1 -0
  38. package/dist/types/src/components/Popover/RefPopover.d.ts +21 -0
  39. package/dist/types/src/components/Popover/RefPopover.d.ts.map +1 -0
  40. package/dist/types/src/components/Popover/index.d.ts +3 -0
  41. package/dist/types/src/components/Popover/index.d.ts.map +1 -0
  42. package/dist/types/src/components/index.d.ts +1 -0
  43. package/dist/types/src/components/index.d.ts.map +1 -1
  44. package/dist/types/src/defaults.d.ts +3 -5
  45. package/dist/types/src/defaults.d.ts.map +1 -1
  46. package/dist/types/src/extensions/annotations.d.ts +4 -1
  47. package/dist/types/src/extensions/annotations.d.ts.map +1 -1
  48. package/dist/types/src/extensions/autocomplete.d.ts +1 -2
  49. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  50. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  51. package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
  52. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
  53. package/dist/types/src/extensions/automerge/defs.d.ts +1 -1
  54. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
  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/automerge/update-codemirror.d.ts +1 -1
  59. package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +1 -1
  60. package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -1
  61. package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -1
  62. package/dist/types/src/extensions/blast.d.ts.map +1 -1
  63. package/dist/types/src/extensions/command/action.d.ts +17 -0
  64. package/dist/types/src/extensions/command/action.d.ts.map +1 -0
  65. package/dist/types/src/extensions/command/command.d.ts +4 -10
  66. package/dist/types/src/extensions/command/command.d.ts.map +1 -1
  67. package/dist/types/src/extensions/command/hint.d.ts +18 -4
  68. package/dist/types/src/extensions/command/hint.d.ts.map +1 -1
  69. package/dist/types/src/extensions/command/index.d.ts +3 -0
  70. package/dist/types/src/extensions/command/index.d.ts.map +1 -1
  71. package/dist/types/src/extensions/command/menu.d.ts +6 -11
  72. package/dist/types/src/extensions/command/menu.d.ts.map +1 -1
  73. package/dist/types/src/extensions/command/state.d.ts +9 -11
  74. package/dist/types/src/extensions/command/state.d.ts.map +1 -1
  75. package/dist/types/src/extensions/command/typeahead.d.ts +17 -0
  76. package/dist/types/src/extensions/command/typeahead.d.ts.map +1 -0
  77. package/dist/types/src/extensions/comments.d.ts +9 -17
  78. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  79. package/dist/types/src/extensions/debug.d.ts.map +1 -1
  80. package/dist/types/src/extensions/dnd.d.ts.map +1 -1
  81. package/dist/types/src/extensions/factories.d.ts +4 -0
  82. package/dist/types/src/extensions/factories.d.ts.map +1 -1
  83. package/dist/types/src/extensions/folding.d.ts.map +1 -1
  84. package/dist/types/src/extensions/hashtag.d.ts +3 -0
  85. package/dist/types/src/extensions/hashtag.d.ts.map +1 -0
  86. package/dist/types/src/extensions/index.d.ts +4 -0
  87. package/dist/types/src/extensions/index.d.ts.map +1 -1
  88. package/dist/types/src/extensions/json.d.ts +7 -0
  89. package/dist/types/src/extensions/json.d.ts.map +1 -0
  90. package/dist/types/src/extensions/listener.d.ts.map +1 -1
  91. package/dist/types/src/extensions/markdown/{editorAction.d.ts → action.d.ts} +1 -1
  92. package/dist/types/src/extensions/markdown/action.d.ts.map +1 -0
  93. package/dist/types/src/extensions/markdown/bundle.d.ts +2 -1
  94. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  95. package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -1
  96. package/dist/types/src/extensions/markdown/debug.d.ts +2 -2
  97. package/dist/types/src/extensions/markdown/debug.d.ts.map +1 -1
  98. package/dist/types/src/extensions/markdown/decorate.d.ts +5 -1
  99. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  100. package/dist/types/src/extensions/markdown/formatting.d.ts +3 -3
  101. package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
  102. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  103. package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
  104. package/dist/types/src/extensions/markdown/index.d.ts +1 -1
  105. package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
  106. package/dist/types/src/extensions/markdown/link.d.ts +4 -1
  107. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
  108. package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
  109. package/dist/types/src/extensions/markdown/table.d.ts.map +1 -1
  110. package/dist/types/src/extensions/mention.d.ts.map +1 -1
  111. package/dist/types/src/extensions/modes.d.ts +5 -5
  112. package/dist/types/src/extensions/modes.d.ts.map +1 -1
  113. package/dist/types/src/extensions/outliner/commands.d.ts +10 -0
  114. package/dist/types/src/extensions/outliner/commands.d.ts.map +1 -0
  115. package/dist/types/src/extensions/outliner/editor.d.ts +5 -0
  116. package/dist/types/src/extensions/outliner/editor.d.ts.map +1 -0
  117. package/dist/types/src/extensions/outliner/editor.test.d.ts +2 -0
  118. package/dist/types/src/extensions/outliner/editor.test.d.ts.map +1 -0
  119. package/dist/types/src/extensions/outliner/index.d.ts +4 -0
  120. package/dist/types/src/extensions/outliner/index.d.ts.map +1 -0
  121. package/dist/types/src/extensions/outliner/outliner.d.ts +11 -0
  122. package/dist/types/src/extensions/outliner/outliner.d.ts.map +1 -0
  123. package/dist/types/src/extensions/outliner/outliner.test.d.ts +2 -0
  124. package/dist/types/src/extensions/outliner/outliner.test.d.ts.map +1 -0
  125. package/dist/types/src/extensions/outliner/selection.d.ts +12 -0
  126. package/dist/types/src/extensions/outliner/selection.d.ts.map +1 -0
  127. package/dist/types/src/extensions/outliner/tree.d.ts +79 -0
  128. package/dist/types/src/extensions/outliner/tree.d.ts.map +1 -0
  129. package/dist/types/src/extensions/outliner/tree.test.d.ts +2 -0
  130. package/dist/types/src/extensions/outliner/tree.test.d.ts.map +1 -0
  131. package/dist/types/src/extensions/preview/index.d.ts +2 -0
  132. package/dist/types/src/extensions/preview/index.d.ts.map +1 -0
  133. package/dist/types/src/extensions/preview/preview.d.ts +39 -0
  134. package/dist/types/src/extensions/preview/preview.d.ts.map +1 -0
  135. package/dist/types/src/extensions/selection.d.ts.map +1 -1
  136. package/dist/types/src/extensions/typewriter.d.ts.map +1 -1
  137. package/dist/types/src/hooks/index.d.ts +0 -1
  138. package/dist/types/src/hooks/index.d.ts.map +1 -1
  139. package/dist/types/src/hooks/useTextEditor.d.ts +2 -1
  140. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  141. package/dist/types/src/stories/Command.stories.d.ts +7 -0
  142. package/dist/types/src/stories/Command.stories.d.ts.map +1 -0
  143. package/dist/types/src/stories/Comments.stories.d.ts +13 -0
  144. package/dist/types/src/stories/Comments.stories.d.ts.map +1 -0
  145. package/dist/types/src/stories/EditorToolbar.stories.d.ts +12 -0
  146. package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -0
  147. package/dist/types/src/stories/Experimental.stories.d.ts +16 -0
  148. package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -0
  149. package/dist/types/src/stories/Markdown.stories.d.ts +46 -0
  150. package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -0
  151. package/dist/types/src/stories/Outliner.stories.d.ts +26 -0
  152. package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -0
  153. package/dist/types/src/stories/Preview.stories.d.ts +10 -0
  154. package/dist/types/src/stories/Preview.stories.d.ts.map +1 -0
  155. package/dist/types/src/stories/TextEditor.stories.d.ts +55 -0
  156. package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -0
  157. package/dist/types/src/stories/components/EditorStory.d.ts +43 -0
  158. package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -0
  159. package/dist/types/src/stories/components/index.d.ts +3 -0
  160. package/dist/types/src/stories/components/index.d.ts.map +1 -0
  161. package/dist/types/src/stories/components/util.d.ts +38 -0
  162. package/dist/types/src/stories/components/util.d.ts.map +1 -0
  163. package/dist/types/src/styles/theme.d.ts.map +1 -1
  164. package/dist/types/src/styles/tokens.d.ts.map +1 -1
  165. package/dist/types/src/testing/index.d.ts +2 -0
  166. package/dist/types/src/testing/index.d.ts.map +1 -0
  167. package/dist/types/src/testing/util.d.ts +2 -0
  168. package/dist/types/src/testing/util.d.ts.map +1 -0
  169. package/dist/types/src/types.d.ts +5 -0
  170. package/dist/types/src/types.d.ts.map +1 -1
  171. package/dist/types/src/util/cursor.d.ts.map +1 -1
  172. package/dist/types/src/util/debug.d.ts.map +1 -1
  173. package/dist/types/src/util/dom.d.ts.map +1 -1
  174. package/dist/types/src/util/facet.d.ts.map +1 -1
  175. package/dist/types/src/util/react.d.ts +6 -1
  176. package/dist/types/src/util/react.d.ts.map +1 -1
  177. package/dist/types/tsconfig.tsbuildinfo +1 -1
  178. package/package.json +47 -30
  179. package/src/components/EditorToolbar/EditorToolbar.tsx +95 -72
  180. package/src/components/EditorToolbar/blocks.ts +27 -6
  181. package/src/components/EditorToolbar/formatting.ts +34 -7
  182. package/src/components/EditorToolbar/headings.ts +9 -8
  183. package/src/components/EditorToolbar/image.ts +16 -0
  184. package/src/components/EditorToolbar/index.ts +7 -1
  185. package/src/components/EditorToolbar/lists.ts +26 -7
  186. package/src/components/EditorToolbar/search.ts +19 -0
  187. package/src/components/EditorToolbar/util.ts +19 -20
  188. package/src/components/EditorToolbar/{viewMode.ts → view-mode.ts} +9 -8
  189. package/src/components/Popover/RefDropdownMenu.tsx +77 -0
  190. package/src/components/Popover/RefPopover.tsx +75 -0
  191. package/src/components/Popover/index.ts +6 -0
  192. package/src/components/index.ts +1 -0
  193. package/src/defaults.ts +12 -13
  194. package/src/extensions/annotations.ts +41 -64
  195. package/src/extensions/autocomplete.ts +5 -6
  196. package/src/extensions/automerge/automerge.stories.tsx +13 -24
  197. package/src/extensions/automerge/automerge.test.tsx +6 -5
  198. package/src/extensions/automerge/automerge.ts +2 -2
  199. package/src/extensions/automerge/defs.ts +1 -2
  200. package/src/extensions/automerge/sync.ts +7 -7
  201. package/src/extensions/automerge/update-automerge.ts +1 -1
  202. package/src/extensions/automerge/update-codemirror.ts +3 -4
  203. package/src/extensions/awareness/awareness-provider.ts +4 -4
  204. package/src/extensions/awareness/awareness.ts +7 -7
  205. package/src/extensions/blast.ts +9 -9
  206. package/src/extensions/command/action.ts +49 -0
  207. package/src/extensions/command/command.ts +7 -27
  208. package/src/extensions/command/hint.ts +36 -33
  209. package/src/extensions/command/index.ts +3 -0
  210. package/src/extensions/command/menu.ts +91 -54
  211. package/src/extensions/command/state.ts +41 -61
  212. package/src/extensions/command/typeahead.ts +116 -0
  213. package/src/extensions/comments.ts +11 -76
  214. package/src/extensions/factories.ts +13 -0
  215. package/src/extensions/folding.tsx +1 -1
  216. package/src/extensions/hashtag.tsx +68 -0
  217. package/src/extensions/index.ts +4 -0
  218. package/src/extensions/json.ts +57 -0
  219. package/src/extensions/markdown/bundle.ts +13 -9
  220. package/src/extensions/markdown/changes.ts +3 -2
  221. package/src/extensions/markdown/debug.ts +2 -2
  222. package/src/extensions/markdown/decorate.ts +19 -17
  223. package/src/extensions/markdown/formatting.ts +6 -6
  224. package/src/extensions/markdown/image.ts +14 -13
  225. package/src/extensions/markdown/index.ts +1 -1
  226. package/src/extensions/markdown/link.ts +33 -24
  227. package/src/extensions/markdown/styles.ts +4 -3
  228. package/src/extensions/markdown/table.ts +3 -3
  229. package/src/extensions/modes.ts +5 -6
  230. package/src/extensions/outliner/commands.ts +270 -0
  231. package/src/extensions/outliner/editor.test.ts +33 -0
  232. package/src/extensions/outliner/editor.ts +184 -0
  233. package/src/extensions/outliner/index.ts +7 -0
  234. package/src/extensions/outliner/outliner.test.ts +99 -0
  235. package/src/extensions/outliner/outliner.ts +169 -0
  236. package/src/extensions/outliner/selection.ts +50 -0
  237. package/src/extensions/outliner/tree.test.ts +164 -0
  238. package/src/extensions/outliner/tree.ts +315 -0
  239. package/src/extensions/preview/index.ts +5 -0
  240. package/src/extensions/preview/preview.ts +271 -0
  241. package/src/hooks/index.ts +0 -1
  242. package/src/hooks/useTextEditor.ts +4 -3
  243. package/src/stories/Command.stories.tsx +97 -0
  244. package/src/stories/Comments.stories.tsx +98 -0
  245. package/src/stories/EditorToolbar.stories.tsx +96 -0
  246. package/src/stories/Experimental.stories.tsx +86 -0
  247. package/src/stories/Markdown.stories.tsx +121 -0
  248. package/src/stories/Outliner.stories.tsx +120 -0
  249. package/src/stories/Preview.stories.tsx +149 -0
  250. package/src/stories/TextEditor.stories.tsx +256 -0
  251. package/src/stories/components/EditorStory.tsx +135 -0
  252. package/src/stories/components/index.ts +6 -0
  253. package/src/stories/components/util.tsx +231 -0
  254. package/src/styles/theme.ts +15 -5
  255. package/src/styles/tokens.ts +1 -2
  256. package/src/testing/index.ts +5 -0
  257. package/src/testing/util.ts +5 -0
  258. package/src/types.ts +7 -0
  259. package/src/util/react.tsx +20 -2
  260. package/dist/types/src/InputMode.stories.d.ts +0 -57
  261. package/dist/types/src/InputMode.stories.d.ts.map +0 -1
  262. package/dist/types/src/TextEditor.stories.d.ts +0 -115
  263. package/dist/types/src/TextEditor.stories.d.ts.map +0 -1
  264. package/dist/types/src/components/EditorToolbar/comment.d.ts.map +0 -1
  265. package/dist/types/src/components/EditorToolbar/viewMode.d.ts.map +0 -1
  266. package/dist/types/src/extensions/command/preview.d.ts +0 -12
  267. package/dist/types/src/extensions/command/preview.d.ts.map +0 -1
  268. package/dist/types/src/extensions/markdown/editorAction.d.ts.map +0 -1
  269. package/dist/types/src/fragments.d.ts +0 -3
  270. package/dist/types/src/fragments.d.ts.map +0 -1
  271. package/dist/types/src/hooks/useActionHandler.d.ts +0 -4
  272. package/dist/types/src/hooks/useActionHandler.d.ts.map +0 -1
  273. package/src/InputMode.stories.tsx +0 -124
  274. package/src/TextEditor.stories.tsx +0 -856
  275. package/src/components/EditorToolbar/comment.ts +0 -23
  276. package/src/extensions/command/preview.ts +0 -79
  277. package/src/fragments.ts +0 -19
  278. package/src/hooks/useActionHandler.ts +0 -12
  279. /package/src/extensions/markdown/{editorAction.ts → action.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-editor",
3
- "version": "0.8.2-staging.7ac8446",
3
+ "version": "0.8.3-main.672df60",
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,6 +13,11 @@
13
13
  "types": "./dist/types/src/index.d.ts",
14
14
  "browser": "./dist/lib/browser/index.mjs",
15
15
  "node": "./dist/lib/node-esm/index.mjs"
16
+ },
17
+ "./testing": {
18
+ "types": "./dist/types/src/testing/index.d.ts",
19
+ "browser": "./dist/lib/browser/testing/index.mjs",
20
+ "node": "./dist/lib/node-esm/testing/index.mjs"
16
21
  }
17
22
  },
18
23
  "types": "dist/types/src/index.d.ts",
@@ -24,9 +29,11 @@
24
29
  "src"
25
30
  ],
26
31
  "dependencies": {
32
+ "@automerge/automerge": "3.0.0-beta.4",
27
33
  "@codemirror/autocomplete": "^6.18.1",
28
34
  "@codemirror/commands": "^6.6.2",
29
35
  "@codemirror/lang-javascript": "^6.2.2",
36
+ "@codemirror/lang-json": "^6.0.1",
30
37
  "@codemirror/lang-markdown": "^6.3.0",
31
38
  "@codemirror/language": "^6.10.3",
32
39
  "@codemirror/language-data": "^6.5.1",
@@ -40,38 +47,43 @@
40
47
  "@lezer/generator": "^1.7.1",
41
48
  "@lezer/highlight": "^1.2.1",
42
49
  "@lezer/markdown": "^1.3.1",
43
- "@preact/signals-react": "^1.3.8",
50
+ "@preact-signals/safe-react": "^0.9.0",
51
+ "@preact/signals-react": "^3.2.0",
44
52
  "@radix-ui/react-context": "1.1.1",
45
53
  "@replit/codemirror-vim": "^6.2.1",
46
54
  "@replit/codemirror-vscode-keymap": "^6.0.2",
55
+ "ajv": "^8.17.1",
47
56
  "codemirror": "^6.0.1",
48
57
  "lib0": "^0.2.65",
49
58
  "lodash.defaultsdeep": "^4.6.1",
50
- "lodash.get": "^4.4.2",
51
59
  "lodash.merge": "^4.6.2",
52
60
  "lodash.sortby": "^4.7.0",
53
61
  "style-mod": "^4.1.0",
54
- "@dxos/app-graph": "0.8.2-staging.7ac8446",
55
- "@dxos/automerge": "0.8.2-staging.7ac8446",
56
- "@dxos/async": "0.8.2-staging.7ac8446",
57
- "@dxos/context": "0.8.2-staging.7ac8446",
58
- "@dxos/debug": "0.8.2-staging.7ac8446",
59
- "@dxos/echo-schema": "0.8.2-staging.7ac8446",
60
- "@dxos/display-name": "0.8.2-staging.7ac8446",
61
- "@dxos/invariant": "0.8.2-staging.7ac8446",
62
- "@dxos/live-object": "0.8.2-staging.7ac8446",
63
- "@dxos/log": "0.8.2-staging.7ac8446",
64
- "@dxos/protocols": "0.8.2-staging.7ac8446",
65
- "@dxos/react-hooks": "0.8.2-staging.7ac8446",
66
- "@dxos/react-ui-menu": "0.8.2-staging.7ac8446",
67
- "@dxos/util": "0.8.2-staging.7ac8446"
62
+ "@dxos/app-graph": "0.8.3-main.672df60",
63
+ "@dxos/async": "0.8.3-main.672df60",
64
+ "@dxos/context": "0.8.3-main.672df60",
65
+ "@dxos/debug": "0.8.3-main.672df60",
66
+ "@dxos/display-name": "0.8.3-main.672df60",
67
+ "@dxos/echo-schema": "0.8.3-main.672df60",
68
+ "@dxos/invariant": "0.8.3-main.672df60",
69
+ "@dxos/lit-ui": "0.8.3-main.672df60",
70
+ "@dxos/live-object": "0.8.3-main.672df60",
71
+ "@dxos/log": "0.8.3-main.672df60",
72
+ "@dxos/protocols": "0.8.3-main.672df60",
73
+ "@dxos/react-hooks": "0.8.3-main.672df60",
74
+ "@dxos/util": "0.8.3-main.672df60",
75
+ "@dxos/react-ui-menu": "0.8.3-main.672df60"
68
76
  },
69
77
  "devDependencies": {
78
+ "@automerge/automerge": "3.0.0-beta.4",
79
+ "@automerge/automerge-repo": "2.0.1",
80
+ "@automerge/automerge-repo-network-broadcastchannel": "2.0.1",
81
+ "@effect-rx/rx-react": "^0.34.1",
82
+ "@effect/platform": "0.80.12",
70
83
  "@phosphor-icons/react": "^2.1.5",
71
84
  "@types/chai": "^4.2.15",
72
85
  "@types/chai-dom": "^1.11.0",
73
86
  "@types/lodash.defaultsdeep": "^4.6.6",
74
- "@types/lodash.get": "^4.4.7",
75
87
  "@types/lodash.merge": "^4.6.6",
76
88
  "@types/lodash.sortby": "^4.7.7",
77
89
  "@types/react": "~18.2.0",
@@ -79,6 +91,7 @@
79
91
  "@types/react-test-renderer": "^17.0.2",
80
92
  "chai": "^4.4.1",
81
93
  "chai-dom": "^1.11.0",
94
+ "effect": "3.14.21",
82
95
  "happy-dom": "^13.3.1",
83
96
  "jsdom": "^24.0.0",
84
97
  "mocha": "^10.6.0",
@@ -88,23 +101,27 @@
88
101
  "vite": "5.4.7",
89
102
  "vite-plugin-top-level-await": "^1.4.1",
90
103
  "vite-plugin-wasm": "^3.3.0",
91
- "@dxos/automerge": "0.8.2-staging.7ac8446",
92
- "@dxos/config": "0.8.2-staging.7ac8446",
93
- "@dxos/echo-signals": "0.8.2-staging.7ac8446",
94
- "@dxos/keyboard": "0.8.2-staging.7ac8446",
95
- "@dxos/random": "0.8.2-staging.7ac8446",
96
- "@dxos/react-client": "0.8.2-staging.7ac8446",
97
- "@dxos/react-ui": "0.8.2-staging.7ac8446",
98
- "@dxos/storybook-utils": "0.8.2-staging.7ac8446",
99
- "@dxos/react-ui-theme": "0.8.2-staging.7ac8446"
104
+ "@dxos/config": "0.8.3-main.672df60",
105
+ "@dxos/keyboard": "0.8.3-main.672df60",
106
+ "@dxos/random": "0.8.3-main.672df60",
107
+ "@dxos/echo-signals": "0.8.3-main.672df60",
108
+ "@dxos/react-client": "0.8.3-main.672df60",
109
+ "@dxos/react-ui-attention": "0.8.3-main.672df60",
110
+ "@dxos/react-ui": "0.8.3-main.672df60",
111
+ "@dxos/react-ui-syntax-highlighter": "0.8.3-main.672df60",
112
+ "@dxos/storybook-utils": "0.8.3-main.672df60",
113
+ "@dxos/react-ui-theme": "0.8.3-main.672df60"
100
114
  },
101
115
  "peerDependencies": {
116
+ "@effect-rx/rx-react": "^0.34.1",
117
+ "@effect/platform": "0.80.12",
102
118
  "@phosphor-icons/react": "^2.1.5",
119
+ "effect": "^3.13.3",
103
120
  "react": "~18.2.0",
104
121
  "react-dom": "~18.2.0",
105
- "@dxos/react-client": "0.8.2-staging.7ac8446",
106
- "@dxos/react-ui-theme": "0.8.2-staging.7ac8446",
107
- "@dxos/react-ui": "0.8.2-staging.7ac8446"
122
+ "@dxos/react-ui": "0.8.3-main.672df60",
123
+ "@dxos/react-client": "0.8.3-main.672df60",
124
+ "@dxos/react-ui-theme": "0.8.3-main.672df60"
108
125
  },
109
126
  "publishConfig": {
110
127
  "access": "public"
@@ -2,104 +2,127 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback } from 'react';
5
+ import { Rx } from '@effect-rx/rx-react';
6
+ import React, { memo, useMemo } from 'react';
6
7
 
7
- import { type NodeArg } from '@dxos/app-graph';
8
+ import { rxFromSignal, type NodeArg } from '@dxos/app-graph';
8
9
  import { ElevationProvider } from '@dxos/react-ui';
9
- import {
10
- type MenuActionHandler,
11
- MenuProvider,
12
- ToolbarMenu,
13
- createGapSeparator,
14
- useMenuActions,
15
- } from '@dxos/react-ui-menu';
10
+ import { MenuProvider, ToolbarMenu, createGapSeparator, useMenuActions } from '@dxos/react-ui-menu';
16
11
  import { textBlockWidth } from '@dxos/react-ui-theme';
17
12
 
18
13
  import { createBlocks } from './blocks';
19
- import { createComment } from './comment';
20
14
  import { createFormatting } from './formatting';
21
15
  import { createHeadings } from './headings';
16
+ import { createImageUpload } from './image';
22
17
  import { createLists } from './lists';
23
- import {
24
- type EditorToolbarActionGraphProps,
25
- type EditorToolbarFeatureFlags,
26
- type EditorToolbarProps,
27
- editorToolbarSearch,
28
- } from './util';
29
- import { createViewMode } from './viewMode';
30
- import { stackItemContentToolbarClassNames } from '../../fragments';
18
+ import { createSearch } from './search';
19
+ import { type EditorToolbarActionGraphProps, type EditorToolbarFeatureFlags, type EditorToolbarProps } from './util';
20
+ import { createViewMode } from './view-mode';
21
+ import { stackItemContentToolbarClassNames } from '../../defaults';
31
22
 
32
23
  const createToolbar = ({
24
+ getView,
33
25
  state,
34
26
  customActions,
35
27
  ...features
36
- }: EditorToolbarFeatureFlags & Pick<EditorToolbarActionGraphProps, 'state' | 'customActions'>): {
28
+ }: EditorToolbarFeatureFlags & Pick<EditorToolbarActionGraphProps, 'getView' | 'state' | 'customActions'>): Rx.Rx<{
37
29
  nodes: NodeArg<any>[];
38
30
  edges: { source: string; target: string }[];
39
- } => {
40
- const nodes = [];
41
- const edges = [];
42
- if (features.headings ?? true) {
43
- const headings = createHeadings(state);
44
- nodes.push(...headings.nodes);
45
- edges.push(...headings.edges);
46
- }
47
- if (features.formatting ?? true) {
48
- const formatting = createFormatting(state);
49
- nodes.push(...formatting.nodes);
50
- edges.push(...formatting.edges);
51
- }
52
- if (features.lists ?? true) {
53
- const lists = createLists(state);
54
- nodes.push(...lists.nodes);
55
- edges.push(...lists.edges);
56
- }
57
- if (features.blocks ?? true) {
58
- const blocks = createBlocks(state);
59
- nodes.push(...blocks.nodes);
60
- edges.push(...blocks.edges);
61
- }
62
- if (customActions) {
63
- const custom = customActions();
64
- nodes.push(...custom.nodes);
65
- edges.push(...custom.edges);
66
- }
67
- const editorToolbarGap = createGapSeparator();
68
- nodes.push(...editorToolbarGap.nodes);
69
- edges.push(...editorToolbarGap.edges);
70
- if (features.comment ?? true) {
71
- const comment = createComment(state);
72
- nodes.push(...comment.nodes);
73
- edges.push(...comment.edges);
74
- }
75
- if (features.search ?? true) {
76
- nodes.push(editorToolbarSearch);
77
- edges.push({ source: 'root', target: editorToolbarSearch.id });
78
- }
79
- if (features.viewMode ?? true) {
80
- const viewMode = createViewMode(state);
81
- nodes.push(...viewMode.nodes);
82
- edges.push(...viewMode.edges);
83
- }
84
- return { nodes, edges };
31
+ }> => {
32
+ return Rx.make((get) => {
33
+ const nodes = [];
34
+ const edges = [];
35
+ if (features.headings ?? true) {
36
+ const headings = get(rxFromSignal(() => createHeadings(state, getView)));
37
+ nodes.push(...headings.nodes);
38
+ edges.push(...headings.edges);
39
+ }
40
+ if (features.formatting ?? true) {
41
+ const formatting = get(rxFromSignal(() => createFormatting(state, getView)));
42
+ nodes.push(...formatting.nodes);
43
+ edges.push(...formatting.edges);
44
+ }
45
+ if (features.lists ?? true) {
46
+ const lists = get(rxFromSignal(() => createLists(state, getView)));
47
+ nodes.push(...lists.nodes);
48
+ edges.push(...lists.edges);
49
+ }
50
+ if (features.blocks ?? true) {
51
+ const blocks = get(rxFromSignal(() => createBlocks(state, getView)));
52
+ nodes.push(...blocks.nodes);
53
+ edges.push(...blocks.edges);
54
+ }
55
+ if (features.image) {
56
+ const image = get(rxFromSignal(() => createImageUpload(features.image!)));
57
+ nodes.push(...image.nodes);
58
+ edges.push(...image.edges);
59
+ }
60
+ const editorToolbarGap = createGapSeparator();
61
+ nodes.push(...editorToolbarGap.nodes);
62
+ edges.push(...editorToolbarGap.edges);
63
+ if (customActions) {
64
+ const custom = get(customActions);
65
+ nodes.push(...custom.nodes);
66
+ edges.push(...custom.edges);
67
+ }
68
+ if (features.search ?? true) {
69
+ const search = get(rxFromSignal(() => createSearch(getView)));
70
+ nodes.push(...search.nodes);
71
+ edges.push(...search.edges);
72
+ }
73
+ if (features.viewMode) {
74
+ const viewMode = get(rxFromSignal(() => createViewMode(state, features.viewMode!)));
75
+ nodes.push(...viewMode.nodes);
76
+ edges.push(...viewMode.edges);
77
+ }
78
+ return { nodes, edges };
79
+ });
85
80
  };
86
81
 
87
- const useEditorToolbarActionGraph = ({ onAction, ...props }: EditorToolbarProps) => {
88
- const menuCreator = useCallback(() => createToolbar(props), [props]);
89
- const { resolveGroupItems } = useMenuActions(menuCreator);
82
+ // TODO(wittjosiah): Toolbar re-rendering is causing this graph to be recreated and breaking reactivity in some cases.
83
+ // E.g. for toolbar dropdowns which use active icon, the icon is not updated when the active item changes.
84
+ // This is currently only happening in the markdown plugin usage and should be reproduced in an editor story.
85
+ const useEditorToolbarActionGraph = (props: EditorToolbarProps) => {
86
+ const menuCreator = useMemo(
87
+ () =>
88
+ createToolbar({
89
+ getView: props.getView,
90
+ state: props.state,
91
+ customActions: props.customActions,
92
+ headings: props.headings,
93
+ formatting: props.formatting,
94
+ lists: props.lists,
95
+ blocks: props.blocks,
96
+ image: props.image,
97
+ search: props.search,
98
+ viewMode: props.viewMode,
99
+ }),
100
+ [
101
+ props.getView,
102
+ props.state,
103
+ props.customActions,
104
+ props.headings,
105
+ props.formatting,
106
+ props.lists,
107
+ props.blocks,
108
+ props.image,
109
+ props.search,
110
+ props.viewMode,
111
+ ],
112
+ );
90
113
 
91
- return { resolveGroupItems, onAction: onAction as MenuActionHandler };
114
+ return useMenuActions(menuCreator);
92
115
  };
93
116
 
94
- export const EditorToolbar = ({ classNames, attendableId, role, ...props }: EditorToolbarProps) => {
117
+ export const EditorToolbar = memo(({ classNames, attendableId, role, ...props }: EditorToolbarProps) => {
95
118
  const menuProps = useEditorToolbarActionGraph(props);
96
119
  return (
97
120
  <div role='none' className={stackItemContentToolbarClassNames(role)}>
98
121
  <ElevationProvider elevation={role === 'section' ? 'positioned' : 'base'}>
99
122
  <MenuProvider {...menuProps} attendableId={attendableId}>
100
- <ToolbarMenu classNames={[textBlockWidth, '!bg-transparent', classNames]} />
123
+ <ToolbarMenu classNames={[textBlockWidth, classNames]} />
101
124
  </MenuProvider>
102
125
  </ElevationProvider>
103
126
  </div>
104
127
  );
105
- };
128
+ });
@@ -2,11 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { type EditorView } from '@codemirror/view';
6
+
5
7
  import { type NodeArg } from '@dxos/app-graph';
6
8
  import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
7
9
 
8
10
  import { createEditorAction, createEditorActionGroup, type EditorToolbarState } from './util';
9
- import { type PayloadType } from '../../extensions';
11
+ import { removeBlockquote, addBlockquote, removeCodeblock, addCodeblock, insertTable } from '../../extensions';
10
12
 
11
13
  const createBlockGroupAction = (value: string) =>
12
14
  createEditorActionGroup('block', {
@@ -15,22 +17,41 @@ const createBlockGroupAction = (value: string) =>
15
17
  value,
16
18
  } as ToolbarMenuActionGroupProperties);
17
19
 
18
- const createBlockActions = (value: string, blankLine?: boolean) =>
20
+ const createBlockActions = (value: string, getView: () => EditorView, blankLine?: boolean) =>
19
21
  Object.entries({
20
22
  blockquote: 'ph--quotes--regular',
21
23
  codeblock: 'ph--code-block--regular',
22
24
  table: 'ph--table--regular',
23
25
  }).map(([type, icon]) => {
26
+ const checked = type === value;
24
27
  return createEditorAction(
25
- { type: type as PayloadType, checked: type === value, ...(type === 'table' && { disabled: !!blankLine }) },
26
- icon,
28
+ type,
29
+ () => {
30
+ const view = getView();
31
+ if (!view) {
32
+ return;
33
+ }
34
+
35
+ switch (type) {
36
+ case 'blockquote':
37
+ checked ? removeBlockquote(view) : addBlockquote(view);
38
+ break;
39
+ case 'codeblock':
40
+ checked ? removeCodeblock(view) : addCodeblock(view);
41
+ break;
42
+ case 'table':
43
+ insertTable(view);
44
+ break;
45
+ }
46
+ },
47
+ { checked, ...(type === 'table' && { disabled: !!blankLine }), icon },
27
48
  );
28
49
  });
29
50
 
30
- export const createBlocks = (state: EditorToolbarState) => {
51
+ export const createBlocks = (state: EditorToolbarState, getView: () => EditorView) => {
31
52
  const value = state?.blockQuote ? 'blockquote' : state.blockType ?? '';
32
53
  const blockGroupAction = createBlockGroupAction(value);
33
- const blockActions = createBlockActions(value, state.blankLine);
54
+ const blockActions = createBlockActions(value, getView, state.blankLine);
34
55
  return {
35
56
  nodes: [blockGroupAction as NodeArg<any>, ...blockActions],
36
57
  edges: [
@@ -2,11 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { type EditorView } from '@codemirror/view';
6
+
5
7
  import { type NodeArg } from '@dxos/app-graph';
6
8
  import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
7
9
 
8
10
  import { createEditorAction, createEditorActionGroup, type EditorToolbarState } from './util';
9
- import { type Formatting, type PayloadType } from '../../extensions';
11
+ import { addLink, Inline, removeLink, setStyle, type Formatting } from '../../extensions';
10
12
 
11
13
  const formats = {
12
14
  strong: 'ph--text-b--regular',
@@ -23,14 +25,39 @@ const createFormattingGroup = (formatting: Formatting) =>
23
25
  value: Object.keys(formats).filter((key) => !!formatting[key as keyof Formatting]),
24
26
  } as ToolbarMenuActionGroupProperties);
25
27
 
26
- const createFormattingActions = (formatting: Formatting) =>
27
- Object.entries(formats).map(([type, icon]) =>
28
- createEditorAction({ type: type as PayloadType, checked: !!formatting[type as keyof Formatting] }, icon),
29
- );
28
+ const createFormattingActions = (formatting: Formatting, getView: () => EditorView) =>
29
+ Object.entries(formats).map(([type, icon]) => {
30
+ const checked = !!formatting[type as keyof Formatting];
31
+ return createEditorAction(
32
+ type,
33
+ () => {
34
+ const view = getView();
35
+ if (!view) {
36
+ return;
37
+ }
38
+
39
+ if (type === 'link') {
40
+ checked ? removeLink(view) : addLink()(view);
41
+ return;
42
+ }
43
+
44
+ const inlineType =
45
+ type === 'strong'
46
+ ? Inline.Strong
47
+ : type === 'emphasis'
48
+ ? Inline.Emphasis
49
+ : type === 'strikethrough'
50
+ ? Inline.Strikethrough
51
+ : Inline.Code;
52
+ setStyle(inlineType, !checked)(view);
53
+ },
54
+ { checked, icon },
55
+ );
56
+ });
30
57
 
31
- export const createFormatting = (state: EditorToolbarState) => {
58
+ export const createFormatting = (state: EditorToolbarState, getView: () => EditorView) => {
32
59
  const formattingGroupAction = createFormattingGroup(state);
33
- const formattingActions = createFormattingActions(state);
60
+ const formattingActions = createFormattingActions(state, getView);
34
61
  return {
35
62
  nodes: [formattingGroupAction as NodeArg<any>, ...formattingActions],
36
63
  edges: [
@@ -2,10 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { type EditorView } from '@codemirror/view';
6
+
5
7
  import { type NodeArg } from '@dxos/app-graph';
6
8
  import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
7
9
 
8
10
  import { createEditorAction, createEditorActionGroup, type EditorToolbarState } from './util';
11
+ import { setHeading } from '../../extensions';
9
12
  import { translationKey } from '../../translations';
10
13
 
11
14
  const createHeadingGroupAction = (value: string) =>
@@ -20,7 +23,7 @@ const createHeadingGroupAction = (value: string) =>
20
23
  'ph--text-h--regular',
21
24
  );
22
25
 
23
- const createHeadingActions = (value: string) =>
26
+ const createHeadingActions = (getView: () => EditorView) =>
24
27
  Object.entries({
25
28
  '0': 'ph--paragraph--regular',
26
29
  '1': 'ph--text-h-one--regular',
@@ -31,12 +34,10 @@ const createHeadingActions = (value: string) =>
31
34
  '6': 'ph--text-h-six--regular',
32
35
  }).map(([levelStr, icon]) => {
33
36
  const level = parseInt(levelStr);
34
- return createEditorAction(
35
- { type: 'heading', data: level, checked: value === levelStr },
37
+ return createEditorAction(`heading--${levelStr}`, () => setHeading(level)(getView()), {
38
+ label: ['heading level label', { count: level, ns: translationKey }],
36
39
  icon,
37
- ['heading level label', { count: level, ns: translationKey }],
38
- `heading--${levelStr}`,
39
- );
40
+ });
40
41
  });
41
42
 
42
43
  const computeHeadingValue = (state: EditorToolbarState) => {
@@ -45,10 +46,10 @@ const computeHeadingValue = (state: EditorToolbarState) => {
45
46
  return header ? header[1] : blockType === 'paragraph' || !blockType ? '0' : '';
46
47
  };
47
48
 
48
- export const createHeadings = (state: EditorToolbarState) => {
49
+ export const createHeadings = (state: EditorToolbarState, getView: () => EditorView) => {
49
50
  const headingValue = computeHeadingValue(state);
50
51
  const headingGroupAction = createHeadingGroupAction(headingValue);
51
- const headingActions = createHeadingActions(headingValue);
52
+ const headingActions = createHeadingActions(getView);
52
53
  return {
53
54
  nodes: [headingGroupAction as NodeArg<any>, ...headingActions],
54
55
  edges: [
@@ -0,0 +1,16 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { createEditorAction } from './util';
6
+
7
+ const createImageUploadAction = (onImageUpload: () => void) =>
8
+ createEditorAction('image', onImageUpload, {
9
+ testId: 'editor.toolbar.image',
10
+ icon: 'ph--image-square--regular',
11
+ });
12
+
13
+ export const createImageUpload = (onImageUpload: () => void) => ({
14
+ nodes: [createImageUploadAction(onImageUpload)],
15
+ edges: [{ source: 'root', target: 'image' }],
16
+ });
@@ -3,4 +3,10 @@
3
3
  //
4
4
 
5
5
  export * from './EditorToolbar';
6
- export { type EditorToolbarState, useEditorToolbarState, createEditorAction, createEditorActionGroup } from './util';
6
+ export {
7
+ type EditorToolbarState,
8
+ type EditorToolbarActionGraphProps,
9
+ useEditorToolbarState,
10
+ createEditorAction,
11
+ createEditorActionGroup,
12
+ } from './util';
@@ -2,11 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { type EditorView } from '@codemirror/view';
6
+
5
7
  import { type NodeArg } from '@dxos/app-graph';
6
8
  import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
7
9
 
8
10
  import { createEditorAction, createEditorActionGroup, type EditorToolbarState } from './util';
9
- import { type PayloadType } from '../../extensions';
11
+ import { addList, List, removeList } from '../../extensions';
10
12
 
11
13
  const listStyles = {
12
14
  bullet: 'ph--list-bullets--regular',
@@ -21,15 +23,32 @@ const createListGroupAction = (value: string) =>
21
23
  value,
22
24
  } as ToolbarMenuActionGroupProperties);
23
25
 
24
- const createListActions = (value: string) =>
25
- Object.entries(listStyles).map(([listStyle, icon]) =>
26
- createEditorAction({ type: `list-${listStyle}` as PayloadType, checked: value === listStyle }, icon),
27
- );
26
+ const createListActions = (value: string, getView: () => EditorView) =>
27
+ Object.entries(listStyles).map(([listStyle, icon]) => {
28
+ const checked = value === listStyle;
29
+ return createEditorAction(
30
+ `list-${listStyle}`,
31
+ () => {
32
+ const view = getView();
33
+ if (!view) {
34
+ return;
35
+ }
36
+
37
+ const listType = listStyle === 'ordered' ? List.Ordered : listStyle === 'bullet' ? List.Bullet : List.Task;
38
+ if (checked) {
39
+ removeList(listType)(view);
40
+ } else {
41
+ addList(listType)(view);
42
+ }
43
+ },
44
+ { checked, icon },
45
+ );
46
+ });
28
47
 
29
- export const createLists = (state: EditorToolbarState) => {
48
+ export const createLists = (state: EditorToolbarState, getView: () => EditorView) => {
30
49
  const value = state.listStyle ?? '';
31
50
  const listGroupAction = createListGroupAction(value);
32
- const listActionsMap = createListActions(value);
51
+ const listActionsMap = createListActions(value, getView);
33
52
  return {
34
53
  nodes: [listGroupAction as NodeArg<any>, ...listActionsMap],
35
54
  edges: [
@@ -0,0 +1,19 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { openSearchPanel } from '@codemirror/search';
6
+ import { type EditorView } from '@codemirror/view';
7
+
8
+ import { createEditorAction } from './util';
9
+
10
+ const createSearchAction = (getView: () => EditorView) =>
11
+ createEditorAction('search', () => openSearchPanel(getView()), {
12
+ testId: 'editor.toolbar.search',
13
+ icon: 'ph--magnifying-glass--regular',
14
+ });
15
+
16
+ export const createSearch = (getView: () => EditorView) => ({
17
+ nodes: [createSearchAction(getView)],
18
+ edges: [{ source: 'root', target: 'search' }],
19
+ });