@dxos/react-ui-editor 0.3.11-main.dd122a6 → 0.3.11-main.e0dc42b

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 (34) hide show
  1. package/dist/lib/browser/index.mjs +93 -86
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +6 -2
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +10 -10
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +2 -2
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/yjs.stories.d.ts +1 -1
  11. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  12. package/dist/types/src/extensions/automerge/index.d.ts +1 -0
  13. package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
  14. package/dist/types/src/extensions/code.d.ts.map +1 -1
  15. package/dist/types/src/extensions/comments.d.ts +1 -1
  16. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  17. package/dist/types/src/index.d.ts +2 -0
  18. package/dist/types/src/index.d.ts.map +1 -1
  19. package/package.json +23 -22
  20. package/src/components/TextEditor/MarkdownEditor.stories.tsx +12 -8
  21. package/src/components/TextEditor/TextEditor.stories.tsx +3 -4
  22. package/src/components/TextEditor/TextEditor.tsx +59 -45
  23. package/src/extensions/autocomplete.ts +18 -17
  24. package/src/extensions/automerge/index.ts +1 -0
  25. package/src/extensions/awareness.ts +14 -15
  26. package/src/extensions/code.ts +10 -2
  27. package/src/extensions/comments.ts +41 -42
  28. package/src/extensions/hr.ts +2 -2
  29. package/src/extensions/image.ts +2 -2
  30. package/src/extensions/link.ts +4 -4
  31. package/src/extensions/table.ts +6 -3
  32. package/src/extensions/tasklist.ts +2 -2
  33. package/src/hooks/useTextModel.ts +1 -1
  34. package/src/index.ts +2 -0
@@ -11,40 +11,41 @@ import { EditorView as EditorView12 } from "@codemirror/view";
11
11
  import { useFocusableGroup } from "@fluentui/react-tabster";
12
12
  import { vim } from "@replit/codemirror-vim";
13
13
  import defaultsDeep2 from "lodash.defaultsdeep";
14
- import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
14
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState, useRef } from "react";
15
15
  import { generateName } from "@dxos/display-name";
16
16
  import { useThemeContext } from "@dxos/react-ui";
17
17
  import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
18
18
 
19
19
  // packages/ui/react-ui-editor/src/extensions/autocomplete.ts
20
20
  import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
21
+ import { markdownLanguage } from "@codemirror/lang-markdown";
21
22
  import { keymap } from "@codemirror/view";
22
23
  var autocomplete = ({ onSearch }) => {
23
24
  return [
24
25
  // https://codemirror.net/docs/ref/#view.keymap
25
26
  // https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
27
+ // TODO(burdon): Set custom keymap.
26
28
  keymap.of(completionKeymap),
27
29
  // https://codemirror.net/examples/autocompletion
28
30
  // https://codemirror.net/docs/ref/#autocomplete.autocompletion
29
31
  autocompletion({
30
- // TODO(burdon): Set custom keymap.
31
- // defaultKeymap: false,
32
+ defaultKeymap: false,
32
33
  // Don't start unless key press.
33
- activateOnTyping: false,
34
- // TODO(burdon): Option to create new page?
35
- // TODO(burdon): Optional decoration via addToOptions
36
- override: [
37
- (context) => {
38
- const match = context.matchBefore(/\w*/);
39
- if (!match || match.from === match.to && !context.explicit) {
40
- return null;
41
- }
42
- return {
43
- from: match.from,
44
- options: onSearch(match.text.toLowerCase())
45
- };
34
+ activateOnTyping: false
35
+ }),
36
+ // TODO(burdon): Option to create new page?
37
+ // TODO(burdon): Optional decoration via addToOptions
38
+ markdownLanguage.data.of({
39
+ autocomplete: (context) => {
40
+ const match = context.matchBefore(/\w*/);
41
+ if (!match || match.from === match.to && !context.explicit) {
42
+ return null;
46
43
  }
47
- ]
44
+ return {
45
+ from: match.from,
46
+ options: onSearch(match.text.toLowerCase())
47
+ };
48
+ }
48
49
  })
49
50
  ];
50
51
  };
@@ -504,23 +505,21 @@ var RemoteSelectionsDecorator = class {
504
505
  }
505
506
  };
506
507
  var RemoteCaretWidget = class extends WidgetType {
507
- constructor(name, color) {
508
+ constructor(_name, _color) {
508
509
  super();
509
- this.name = name;
510
- this.color = color;
511
- this.name = name;
512
- this.color = color;
510
+ this._name = _name;
511
+ this._color = _color;
513
512
  }
514
513
  toDOM() {
515
514
  const span = document.createElement("span");
516
515
  span.className = "cm-ySelectionCaret";
517
- span.style.backgroundColor = this.color;
518
- span.style.borderColor = this.color;
516
+ span.style.backgroundColor = this._color;
517
+ span.style.borderColor = this._color;
519
518
  const dot = document.createElement("div");
520
519
  dot.className = "cm-ySelectionCaretDot";
521
520
  const info = document.createElement("div");
522
521
  info.className = "cm-ySelectionInfo";
523
- info.innerText = this.name;
522
+ info.innerText = this._name;
524
523
  span.appendChild(document.createTextNode("\u2060"));
525
524
  span.appendChild(dot);
526
525
  span.appendChild(document.createTextNode("\u2060"));
@@ -528,21 +527,22 @@ var RemoteCaretWidget = class extends WidgetType {
528
527
  span.appendChild(document.createTextNode("\u2060"));
529
528
  return span;
530
529
  }
531
- eq(widget) {
532
- return widget.color === this.color;
533
- }
534
- compare(widget) {
535
- return widget.color === this.color;
536
- }
537
530
  updateDOM() {
538
531
  return false;
539
532
  }
533
+ eq(widget) {
534
+ return widget._color === this._color;
535
+ }
540
536
  get estimatedHeight() {
541
537
  return -1;
542
538
  }
543
539
  ignoreEvent() {
544
540
  return true;
545
541
  }
542
+ // TODO(burdon): Not used?
543
+ compare(widget) {
544
+ return widget._color === this._color;
545
+ }
546
546
  };
547
547
  var styles = EditorView.baseTheme({
548
548
  ".cm-ySelection": {},
@@ -1056,7 +1056,7 @@ var getLineRange = (lines, from, to) => {
1056
1056
  var code2 = () => {
1057
1057
  const getDecorations = (view) => {
1058
1058
  const decorations = [];
1059
- if (view.state.readOnly) {
1059
+ if (!view.hasFocus || view.state.readOnly) {
1060
1060
  const text = view.state.doc.sliceString(0);
1061
1061
  const matches = text.matchAll(CODE_REGEX);
1062
1062
  const blocks = view.viewportLineBlocks;
@@ -1075,10 +1075,15 @@ var code2 = () => {
1075
1075
  return [
1076
1076
  ViewPlugin3.fromClass(class {
1077
1077
  constructor(view) {
1078
+ this.hasFocus = false;
1078
1079
  this.decorations = getDecorations(view);
1079
1080
  }
1080
1081
  update(update2) {
1081
- if (update2.docChanged || update2.viewportChanged) {
1082
+ if (
1083
+ // TODO(burdon): Generalize for other extensions.
1084
+ this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
1085
+ ) {
1086
+ this.hasFocus = update2.view.hasFocus;
1082
1087
  this.decorations = getDecorations(update2.view);
1083
1088
  }
1084
1089
  }
@@ -1196,14 +1201,13 @@ var highlightDecorations = EditorView5.decorations.compute([
1196
1201
  return Decoration3.set(decorations);
1197
1202
  });
1198
1203
  var BookmarkWidget = class extends WidgetType2 {
1199
- constructor(_anchor, _id, _handleClick) {
1204
+ constructor(_id, _handleClick) {
1200
1205
  super();
1201
- this._anchor = _anchor;
1202
1206
  this._id = _id;
1203
1207
  this._handleClick = _handleClick;
1204
1208
  invariant2(this._id, void 0, {
1205
1209
  F: __dxlog_file3,
1206
- L: 168,
1210
+ L: 164,
1207
1211
  S: this,
1208
1212
  A: [
1209
1213
  "this._id",
@@ -1212,7 +1216,7 @@ var BookmarkWidget = class extends WidgetType2 {
1212
1216
  });
1213
1217
  }
1214
1218
  eq(other) {
1215
- return this._anchor === other._anchor && this._id === other._id;
1219
+ return this._id === other._id;
1216
1220
  }
1217
1221
  toDOM() {
1218
1222
  const span = document.createElement("span");
@@ -1225,12 +1229,13 @@ var BookmarkWidget = class extends WidgetType2 {
1225
1229
  }
1226
1230
  };
1227
1231
  var comments = (options = {}) => {
1232
+ const { key: shortcut = "meta-'" } = options;
1228
1233
  const handleSelect = debounce((state) => options.onSelect?.(state), 200);
1229
1234
  const createCommentThread = (view) => {
1230
1235
  const cursorConverter3 = view.state.facet(CursorConverter);
1231
1236
  invariant2(options.onCreate, void 0, {
1232
1237
  F: __dxlog_file3,
1233
- L: 224,
1238
+ L: 222,
1234
1239
  S: void 0,
1235
1240
  A: [
1236
1241
  "options.onCreate",
@@ -1273,17 +1278,17 @@ var comments = (options = {}) => {
1273
1278
  }
1274
1279
  return false;
1275
1280
  };
1276
- const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
1281
+ const bookmarksViewPlugin = options.footnote ? ViewPlugin4.fromClass(class BookmarkViewPlugin {
1277
1282
  static {
1278
1283
  // Match markdown footnotes (option).
1279
1284
  // https://www.markdownguide.org/extended-syntax/#footnotes
1280
1285
  this.bookmarkMatcher = new MatchDecorator({
1281
1286
  regexp: /\[\^(\w+)\]/g,
1282
- decoration: (match, view, pos) => {
1287
+ decoration: (match) => {
1283
1288
  const id = match[1];
1284
1289
  return Decoration3.replace({
1285
1290
  id,
1286
- widget: new BookmarkWidget(pos, id)
1291
+ widget: new BookmarkWidget(id)
1287
1292
  });
1288
1293
  }
1289
1294
  });
@@ -1299,7 +1304,7 @@ var comments = (options = {}) => {
1299
1304
  provide: (plugin) => EditorView5.atomicRanges.of((view) => {
1300
1305
  return view.plugin(plugin)?.bookmarks || Decoration3.none;
1301
1306
  })
1302
- });
1307
+ }) : [];
1303
1308
  return [
1304
1309
  bookmarksViewPlugin,
1305
1310
  commentsStateField,
@@ -1310,7 +1315,7 @@ var comments = (options = {}) => {
1310
1315
  //
1311
1316
  options.onCreate ? keymap3.of([
1312
1317
  {
1313
- key: options?.key ?? "meta-'",
1318
+ key: shortcut,
1314
1319
  run: callbackWrapper(createCommentThread)
1315
1320
  }
1316
1321
  ]) : [],
@@ -1327,7 +1332,7 @@ var comments = (options = {}) => {
1327
1332
  above: true,
1328
1333
  create: () => {
1329
1334
  const el = document.createElement("div");
1330
- options.onHover?.(el);
1335
+ options.onHover?.(el, shortcut);
1331
1336
  return {
1332
1337
  dom: el,
1333
1338
  offset: {
@@ -1361,7 +1366,7 @@ var comments = (options = {}) => {
1361
1366
  thread: range.id
1362
1367
  }, {
1363
1368
  F: __dxlog_file3,
1364
- L: 358,
1369
+ L: 355,
1365
1370
  S: void 0,
1366
1371
  C: (f, a) => f(...a)
1367
1372
  });
@@ -1708,7 +1713,7 @@ var listener = ({ onFocus, onChange }) => {
1708
1713
  // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
1709
1714
  import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
1710
1715
  import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
1711
- import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
1716
+ import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
1712
1717
  import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
1713
1718
  import { languages } from "@codemirror/language-data";
1714
1719
  import { searchKeymap } from "@codemirror/search";
@@ -1717,7 +1722,7 @@ import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/the
1717
1722
  import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
1718
1723
 
1719
1724
  // packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
1720
- import { markdownLanguage } from "@codemirror/lang-markdown";
1725
+ import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
1721
1726
  import { HighlightStyle } from "@codemirror/language";
1722
1727
  import { tags, styleTags, Tag } from "@lezer/highlight";
1723
1728
  import { Table } from "@lezer/markdown";
@@ -1904,7 +1909,7 @@ var markdownHighlightStyle = (readonly) => {
1904
1909
  class: "font-mono"
1905
1910
  }
1906
1911
  ], {
1907
- scope: markdownLanguage,
1912
+ scope: markdownLanguage2,
1908
1913
  all: {
1909
1914
  fontFamily: getToken("fontFamily.body", []).join(",")
1910
1915
  }
@@ -1936,7 +1941,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
1936
1941
  // NOTE: This extends the parser; it doesn't affect rendering.
1937
1942
  // https://github.github.com/gfm
1938
1943
  // https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
1939
- base: markdownLanguage2,
1944
+ base: markdownLanguage3,
1940
1945
  // Languages for syntax highlighting fenced code blocks.
1941
1946
  codeLanguages: languages,
1942
1947
  // Parser extensions.
@@ -2040,7 +2045,6 @@ var update = (state, options) => {
2040
2045
  tables.forEach((table2) => {
2041
2046
  const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
2042
2047
  hide && builder.add(table2.from, table2.to, Decoration7.replace({
2043
- block: true,
2044
2048
  widget: new TableWidget(table2)
2045
2049
  }));
2046
2050
  builder.add(table2.from, table2.to, Decoration7.mark({
@@ -2081,6 +2085,9 @@ var TableWidget = class extends WidgetType6 {
2081
2085
  }
2082
2086
  return table2;
2083
2087
  }
2088
+ ignoreEvent(e) {
2089
+ return !/^mouse/.test(e.type);
2090
+ }
2084
2091
  };
2085
2092
 
2086
2093
  // packages/ui/react-ui-editor/src/extensions/tasklist.ts
@@ -2528,21 +2535,23 @@ var EditorModes = [
2528
2535
  "default",
2529
2536
  "vim"
2530
2537
  ];
2531
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
2532
- const { themeMode } = useThemeContext();
2538
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
2533
2539
  const tabsterDOMAttribute = useFocusableGroup({
2534
2540
  tabBehavior: "limited"
2535
2541
  });
2536
- const [root, setRoot] = useState(null);
2537
- const [{ state = void 0, view = void 0 } = {}, setEditor] = useState();
2538
- useImperativeHandle(forwardedRef, () => ({
2539
- root,
2540
- state,
2542
+ const { themeMode } = useThemeContext();
2543
+ const rootRef = useRef(null);
2544
+ const [view, setView] = useState(null);
2545
+ useImperativeHandle(forwardedRef, () => view, [
2541
2546
  view
2542
- }), [
2547
+ ]);
2548
+ useEffect(() => {
2549
+ if (view && focus) {
2550
+ view.focus();
2551
+ }
2552
+ }, [
2543
2553
  view,
2544
- state,
2545
- root
2554
+ focus
2546
2555
  ]);
2547
2556
  const { awareness: awareness2, peer } = model;
2548
2557
  useEffect(() => {
@@ -2579,11 +2588,12 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2579
2588
  comments2
2580
2589
  ]);
2581
2590
  useEffect(() => {
2582
- if (!root) {
2591
+ if (!model || !rootRef.current) {
2583
2592
  return;
2584
2593
  }
2585
- const state2 = EditorState2.create({
2594
+ const state = EditorState2.create({
2586
2595
  doc: model.text(),
2596
+ selection,
2587
2597
  extensions: [
2588
2598
  readonly && EditorState2.readOnly.of(readonly),
2589
2599
  // TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
@@ -2600,19 +2610,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2600
2610
  ].filter(Boolean)
2601
2611
  });
2602
2612
  view?.destroy();
2603
- setEditor({
2604
- state: state2,
2605
- view: new EditorView12({
2606
- state: state2,
2607
- parent: root
2608
- })
2613
+ const newView = new EditorView12({
2614
+ parent: rootRef.current,
2615
+ state
2609
2616
  });
2617
+ setView(newView);
2610
2618
  return () => {
2611
- view?.destroy();
2612
- setEditor(void 0);
2619
+ newView?.destroy();
2620
+ setView(null);
2613
2621
  };
2614
2622
  }, [
2615
- root,
2623
+ rootRef,
2616
2624
  model,
2617
2625
  readonly,
2618
2626
  editorMode,
@@ -2621,12 +2629,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2621
2629
  const handleKeyUp = useCallback((event) => {
2622
2630
  const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
2623
2631
  switch (key) {
2624
- case "Enter": {
2625
- view?.contentDOM.focus();
2626
- break;
2627
- }
2628
2632
  case "Escape": {
2629
- editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && root?.focus();
2633
+ editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
2630
2634
  break;
2631
2635
  }
2632
2636
  }
@@ -2636,16 +2640,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2636
2640
  ]);
2637
2641
  return /* @__PURE__ */ React.createElement("div", {
2638
2642
  key: model.id,
2639
- ref: setRoot,
2643
+ ref: rootRef,
2640
2644
  tabIndex: 0,
2641
2645
  ...slots?.root,
2642
2646
  ...editorMode !== "vim" && tabsterDOMAttribute,
2643
2647
  onKeyUp: handleKeyUp
2644
2648
  });
2645
2649
  });
2646
- var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
2650
+ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots, ...props }, forwardedRef) => {
2647
2651
  const { themeMode } = useThemeContext();
2648
- const slots = defaultsDeep2({}, _slots, defaultTextSlots);
2652
+ const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
2649
2653
  return /* @__PURE__ */ React.createElement(BaseTextEditor, {
2650
2654
  ref: forwardedRef,
2651
2655
  readonly,
@@ -2653,17 +2657,17 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
2653
2657
  basicBundle({
2654
2658
  readonly,
2655
2659
  themeMode,
2656
- placeholder: slots?.editor?.placeholder
2660
+ placeholder: updatedSlots?.editor?.placeholder
2657
2661
  }),
2658
2662
  ...extensions
2659
2663
  ],
2660
- slots,
2664
+ slots: updatedSlots,
2661
2665
  ...props
2662
2666
  });
2663
2667
  });
2664
- var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
2668
+ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots, ...props }, forwardedRef) => {
2665
2669
  const { themeMode } = useThemeContext();
2666
- const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
2670
+ const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
2667
2671
  return /* @__PURE__ */ React.createElement(BaseTextEditor, {
2668
2672
  ref: forwardedRef,
2669
2673
  readonly,
@@ -2671,11 +2675,11 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
2671
2675
  markdownBundle({
2672
2676
  readonly,
2673
2677
  themeMode,
2674
- placeholder: slots?.editor?.placeholder
2678
+ placeholder: updatedSlots?.editor?.placeholder
2675
2679
  }),
2676
2680
  ...extensions
2677
2681
  ],
2678
- slots,
2682
+ slots: updatedSlots,
2679
2683
  ...props
2680
2684
  });
2681
2685
  });
@@ -2981,7 +2985,7 @@ var modelState = StateField5.define({
2981
2985
  });
2982
2986
  var useTextModel = (props) => {
2983
2987
  const { identity, space, text } = props;
2984
- const [model, setModel] = useState2(() => createModel(props));
2988
+ const [model, setModel] = useState2();
2985
2989
  useEffect2(() => setModel(createModel(props)), [
2986
2990
  identity,
2987
2991
  space,
@@ -3040,6 +3044,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
3040
3044
  export {
3041
3045
  AwarenessProvider,
3042
3046
  BaseTextEditor,
3047
+ CursorConverter,
3043
3048
  Doc,
3044
3049
  EditorModes,
3045
3050
  MarkdownEditor,
@@ -3055,11 +3060,13 @@ export {
3055
3060
  awareness,
3056
3061
  basicBundle,
3057
3062
  blast,
3063
+ callbackWrapper,
3058
3064
  code2 as code,
3059
3065
  codeTheme,
3060
3066
  comments,
3061
3067
  createAutomergeModel,
3062
3068
  createYjsModel,
3069
+ cursorConverter,
3063
3070
  defaultMarkdownSlots,
3064
3071
  defaultOptions,
3065
3072
  defaultSlots,