@dxos/react-ui-editor 0.3.10-main.8aaa303 → 0.3.10-main.8fd45da

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 (39) hide show
  1. package/dist/lib/browser/index.mjs +258 -124
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +3 -0
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +1 -0
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts +3 -2
  9. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/extensions/comments.d.ts +14 -0
  11. package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -0
  12. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -1
  13. package/dist/types/src/components/TextEditor/extensions/index.d.ts +1 -0
  14. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
  15. package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +1 -1
  16. package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -1
  17. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
  18. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
  19. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +1 -4
  20. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -1
  21. package/dist/types/src/components/TextEditor/themes/default.d.ts +3 -0
  22. package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
  23. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  24. package/dist/types/src/testing/replicator.d.ts.map +1 -1
  25. package/package.json +19 -19
  26. package/src/components/TextEditor/MarkdownEditor.stories.tsx +37 -6
  27. package/src/components/TextEditor/TextEditor.tsx +14 -7
  28. package/src/components/TextEditor/extensions/autocomplete.ts +5 -3
  29. package/src/components/TextEditor/extensions/comments.ts +173 -0
  30. package/src/components/TextEditor/extensions/experimental.tsx +1 -0
  31. package/src/components/TextEditor/extensions/index.ts +1 -0
  32. package/src/components/TextEditor/extensions/link.ts +10 -2
  33. package/src/components/TextEditor/extensions/listener.ts +1 -0
  34. package/src/components/TextEditor/extensions/markdown/bundle.ts +6 -14
  35. package/src/components/TextEditor/extensions/markdown/highlight.ts +2 -1
  36. package/src/components/TextEditor/extensions/tasklist.ts +73 -79
  37. package/src/components/TextEditor/themes/default.ts +15 -0
  38. package/src/hooks/useTextModel.ts +11 -8
  39. package/src/testing/replicator.ts +5 -5
@@ -8,7 +8,7 @@ import { tags as tags2 } from "@lezer/highlight";
8
8
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/autocomplete.ts
9
9
  import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
10
10
  import { keymap } from "@codemirror/view";
11
- var autocomplete = ({ getOptions }) => {
11
+ var autocomplete = ({ onSearch }) => {
12
12
  return [
13
13
  // https://codemirror.net/docs/ref/#view.keymap
14
14
  // https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
@@ -30,7 +30,7 @@ var autocomplete = ({ getOptions }) => {
30
30
  }
31
31
  return {
32
32
  from: word.from,
33
- options: getOptions(word.text.toLowerCase())
33
+ options: onSearch(word.text.toLowerCase())
34
34
  };
35
35
  }
36
36
  ]
@@ -54,11 +54,130 @@ var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
54
54
  themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
55
55
  ].filter(Boolean);
56
56
 
57
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
58
+ import { Decoration, EditorView as EditorView2, keymap as keymap2, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
59
+ import { invariant } from "@dxos/invariant";
60
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
61
+ var BookmarkWidget = class extends WidgetType {
62
+ constructor(_pos, _id) {
63
+ super();
64
+ this._pos = _pos;
65
+ this._id = _id;
66
+ invariant(this._id, void 0, {
67
+ F: __dxlog_file,
68
+ L: 40,
69
+ S: this,
70
+ A: [
71
+ "this._id",
72
+ ""
73
+ ]
74
+ });
75
+ }
76
+ eq(other) {
77
+ return this._id === other._id;
78
+ }
79
+ // TODO(burdon): Click to select.
80
+ toDOM() {
81
+ const span = document.createElement("span");
82
+ span.className = "cm-bookmark";
83
+ span.textContent = "\u{1F4AC}";
84
+ return span;
85
+ }
86
+ };
87
+ var styles = EditorView2.baseTheme({
88
+ "& .cm-bookmark": {
89
+ cursor: "pointer",
90
+ margin: "4px",
91
+ padding: "4px",
92
+ backgroundColor: "yellow"
93
+ }
94
+ });
95
+ var comments = (options = {}) => {
96
+ const bookmarkMatcher = new MatchDecorator({
97
+ regexp: /\[\^(\w+)\]/g,
98
+ decoration: (match, view, pos) => {
99
+ const id = match[1];
100
+ return Decoration.replace({
101
+ id,
102
+ widget: new BookmarkWidget(pos, id)
103
+ });
104
+ }
105
+ });
106
+ const bookmarks = ViewPlugin.fromClass(class {
107
+ constructor(view) {
108
+ this.bookmarks = bookmarkMatcher.createDeco(view);
109
+ }
110
+ update(update2) {
111
+ this.bookmarks = bookmarkMatcher.updateDeco(update2, this.bookmarks);
112
+ }
113
+ }, {
114
+ decorations: (instance) => instance.bookmarks,
115
+ provide: (plugin) => EditorView2.atomicRanges.of((view) => {
116
+ return view.plugin(plugin)?.bookmarks || Decoration.none;
117
+ })
118
+ });
119
+ return [
120
+ keymap2.of([
121
+ {
122
+ key: options?.key ?? "alt-meta-c",
123
+ run: (view) => {
124
+ const id = options.onCreate?.();
125
+ if (id) {
126
+ const pos = view.state.selection.main.head;
127
+ const tag = `[^${id}]`;
128
+ view.dispatch({
129
+ changes: {
130
+ from: pos,
131
+ insert: tag
132
+ },
133
+ selection: {
134
+ anchor: pos + tag.length
135
+ }
136
+ });
137
+ return true;
138
+ }
139
+ return false;
140
+ }
141
+ }
142
+ ]),
143
+ bookmarks,
144
+ // Monitor cursor movement.
145
+ EditorView2.updateListener.of((update2) => {
146
+ const view = update2.view;
147
+ const pos = view.state.selection.main.head;
148
+ const decorations = [];
149
+ const rangeSet = view.plugin(bookmarks)?.bookmarks;
150
+ rangeSet?.between(pos, pos + 1, (from, to, value) => {
151
+ if (value.spec.widget) {
152
+ decorations.push({
153
+ from,
154
+ to,
155
+ value
156
+ });
157
+ }
158
+ });
159
+ if (decorations.length) {
160
+ const { from, value: { spec: { id } } } = decorations[0];
161
+ const location = view.coordsAtPos(from);
162
+ if (location) {
163
+ options.onUpdate?.({
164
+ items: decorations.map(({ value: { spec: { id: id2 } } }) => id2),
165
+ active: id,
166
+ pos,
167
+ location
168
+ });
169
+ }
170
+ }
171
+ }),
172
+ styles
173
+ ];
174
+ };
175
+
57
176
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
58
177
  import { syntaxTree } from "@codemirror/language";
59
178
  import { RangeSetBuilder, StateField } from "@codemirror/state";
60
- import { Decoration, EditorView as EditorView2, WidgetType } from "@codemirror/view";
61
- var LinkButton = class extends WidgetType {
179
+ import { Decoration as Decoration2, EditorView as EditorView3, WidgetType as WidgetType2 } from "@codemirror/view";
180
+ var LinkButton = class extends WidgetType2 {
62
181
  constructor(_pos, _url, _onAttach) {
63
182
  super();
64
183
  this._pos = _pos;
@@ -74,7 +193,7 @@ var LinkButton = class extends WidgetType {
74
193
  return el;
75
194
  }
76
195
  };
77
- var LinkText = class extends WidgetType {
196
+ var LinkText = class extends WidgetType2 {
78
197
  constructor(_pos, _text, _url) {
79
198
  super();
80
199
  this._pos = _pos;
@@ -114,18 +233,21 @@ var update = (state, options) => {
114
233
  const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
115
234
  const urlNode = node.node.getChild("URL");
116
235
  const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
236
+ if (!url) {
237
+ return false;
238
+ }
117
239
  if (cursor < node.from || cursor > node.to) {
118
- builder.add(node.from, node.to, Decoration.replace({
240
+ builder.add(node.from, node.to, Decoration2.replace({
119
241
  widget: new LinkText(node.from, text, options.link ? url : void 0)
120
242
  }));
121
243
  }
122
244
  if (options.onRender) {
123
- builder.add(node.to, node.to, Decoration.replace({
245
+ builder.add(node.to, node.to, Decoration2.replace({
124
246
  widget: new LinkButton(node.from, url, options.onRender)
125
247
  }));
126
248
  }
249
+ return false;
127
250
  }
128
- return true;
129
251
  }
130
252
  });
131
253
  return builder.finish();
@@ -134,7 +256,7 @@ var link = (options = {}) => {
134
256
  return StateField.define({
135
257
  create: (state) => update(state, options),
136
258
  update: (_, tr) => update(tr.state, options),
137
- provide: (field) => EditorView2.decorations.from(field)
259
+ provide: (field) => EditorView3.decorations.from(field)
138
260
  });
139
261
  };
140
262
 
@@ -152,15 +274,14 @@ var listener = (onChange) => StateField2.define({
152
274
 
153
275
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
154
276
  import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
155
- import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
277
+ import { defaultKeymap, history, indentWithTab } from "@codemirror/commands";
156
278
  import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
157
- import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, foldKeymap, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
279
+ import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
158
280
  import { languages } from "@codemirror/language-data";
159
- import { lintKeymap } from "@codemirror/lint";
160
281
  import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
161
282
  import { EditorState } from "@codemirror/state";
162
283
  import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
163
- import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView3, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap2, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
284
+ import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView4, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap3, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
164
285
 
165
286
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
166
287
  import { markdownLanguage } from "@codemirror/lang-markdown";
@@ -320,10 +441,11 @@ var markdownHighlightStyle = HighlightStyle.define([
320
441
  ],
321
442
  class: codeMark
322
443
  },
323
- // The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
444
+ // NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
324
445
  // However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
325
446
  // when a language is specified. In this case, the syntax highlighting extensions will colorize
326
447
  // the code, but all other CSS properties will be inherited.
448
+ // IMPORTANT: Therefore, the fenced code block will use the base editor font.
327
449
  {
328
450
  tag: [
329
451
  markdownTags.CodeText,
@@ -357,8 +479,7 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
357
479
  closeBrackets2(),
358
480
  _placeholder && placeholder2(_placeholder),
359
481
  EditorState.allowMultipleSelections.of(true),
360
- EditorView3.lineWrapping,
361
- // autocompletion(),
482
+ EditorView4.lineWrapping,
362
483
  crosshairCursor(),
363
484
  dropCursor(),
364
485
  drawSelection(),
@@ -369,13 +490,13 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
369
490
  history(),
370
491
  indentOnInput(),
371
492
  rectangularSelection(),
372
- keymap2.of([
493
+ // TODO(burdon): Review.
494
+ keymap3.of([
373
495
  ...closeBracketsKeymap,
374
- // ...completionKeymap,
375
496
  ...defaultKeymap,
376
- ...foldKeymap,
377
- ...historyKeymap,
378
- ...lintKeymap,
497
+ // ...foldKeymap,
498
+ // ...historyKeymap,
499
+ // ...lintKeymap,
379
500
  ...searchKeymap,
380
501
  indentWithTab
381
502
  ]),
@@ -405,90 +526,84 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
405
526
  };
406
527
 
407
528
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
408
- import { syntaxTree as syntaxTree2 } from "@codemirror/language";
409
- import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
410
- import { EditorView as EditorView4, Decoration as Decoration2, WidgetType as WidgetType2 } from "@codemirror/view";
411
- var CheckboxWidget = class extends WidgetType2 {
412
- constructor(_pos, _getCursor, _checked) {
529
+ import { EditorView as EditorView5, Decoration as Decoration3, WidgetType as WidgetType3, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin2 } from "@codemirror/view";
530
+ var CheckboxWidget = class extends WidgetType3 {
531
+ constructor(_pos, _checked, _indent, _onCheck) {
413
532
  super();
414
533
  this._pos = _pos;
415
- this._getCursor = _getCursor;
416
534
  this._checked = _checked;
535
+ this._indent = _indent;
536
+ this._onCheck = _onCheck;
417
537
  }
418
538
  eq(other) {
419
- return this._pos === other._pos && this._checked === other._checked;
539
+ return this._pos === other._pos && this._checked === other._checked && this._indent === other._indent;
420
540
  }
421
541
  toDOM(view) {
422
542
  const wrap = document.createElement("span");
423
- wrap.setAttribute("aria-hidden", "true");
424
543
  wrap.className = "cm-task-item";
425
- const box = wrap.appendChild(document.createElement("input"));
426
- box.type = "checkbox";
427
- box.checked = this._checked;
428
- box.onclick = (event) => {
429
- this._checked = !isChecked(view.state, this._pos);
430
- view.dispatch({
431
- changes: {
432
- from: this._pos + 1,
433
- to: this._pos + 2,
434
- insert: this._checked ? "x" : " "
435
- },
436
- // TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
437
- selection: {
438
- anchor: this._pos + 4
439
- }
440
- });
544
+ wrap.setAttribute("aria-hidden", "true");
545
+ wrap.style.setProperty("margin-left", this._indent * 24 + "px");
546
+ const input = wrap.appendChild(document.createElement("input"));
547
+ input.type = "checkbox";
548
+ input.checked = this._checked;
549
+ input.onchange = (event) => {
550
+ this._onCheck(event.target.checked);
441
551
  return true;
442
552
  };
443
553
  return wrap;
444
554
  }
445
- // TODO(burdon): Remove listener?
446
- // override destroy() {
447
- // console.log('destroy', this._pos);
448
- // }
449
555
  ignoreEvent() {
450
556
  return false;
451
557
  }
452
558
  };
453
- var isChecked = (state, pos) => {
454
- return state.sliceDoc(pos, pos + 3).toLowerCase() === "[x]";
455
- };
456
- var statefield = () => {
457
- let lastPosition = 0;
458
- const listener2 = EditorView4.updateListener.of((update2) => {
459
- lastPosition = update2.startState.selection.main.head;
559
+ var styles2 = EditorView5.baseTheme({
560
+ "& .cm-task-item": {
561
+ paddingLeft: "4px",
562
+ paddingRight: "8px"
563
+ }
564
+ });
565
+ var tasklist = () => {
566
+ const taskMatcher = new MatchDecorator2({
567
+ regexp: /^(\s*)- \[([ xX])\]\s/g,
568
+ decoration: (match, view, pos) => {
569
+ const indent = Math.floor(match[1].length / 2);
570
+ const checked = match[2] === "x" || match[2] === "X";
571
+ return Decoration3.replace({
572
+ widget: new CheckboxWidget(pos, checked, indent, (checked2) => {
573
+ const idx = pos + match[0].indexOf("[") + 1;
574
+ view.dispatch({
575
+ changes: {
576
+ from: idx,
577
+ to: idx + 1,
578
+ insert: checked2 ? "x" : " "
579
+ },
580
+ // TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
581
+ selection: {
582
+ anchor: idx + 3
583
+ }
584
+ });
585
+ })
586
+ });
587
+ }
460
588
  });
461
- const checkbox = (state) => {
462
- const builder = new RangeSetBuilder2();
463
- syntaxTree2(state).iterate({
464
- enter: (node) => {
465
- if (node.name === "TaskMarker") {
466
- builder.add(node.from, node.to, Decoration2.replace({
467
- widget: new CheckboxWidget(node.from, () => lastPosition, isChecked(state, node.from))
468
- }));
469
- }
470
- }
471
- });
472
- return builder.finish();
473
- };
474
- return [
475
- listener2,
476
- StateField3.define({
477
- create: (state) => checkbox(state),
478
- update: (_, tr) => checkbox(tr.state),
479
- provide: (field) => EditorView4.decorations.from(field)
589
+ const tasks = ViewPlugin2.fromClass(class {
590
+ constructor(view) {
591
+ this.tasks = taskMatcher.createDeco(view);
592
+ }
593
+ update(update2) {
594
+ this.tasks = taskMatcher.updateDeco(update2, this.tasks);
595
+ }
596
+ }, {
597
+ decorations: (instance) => instance.tasks,
598
+ provide: (plugin) => EditorView5.atomicRanges.of((view) => {
599
+ return view.plugin(plugin)?.tasks || Decoration3.none;
480
600
  })
601
+ });
602
+ return [
603
+ tasks,
604
+ styles2
481
605
  ];
482
606
  };
483
- var styles = EditorView4.baseTheme({
484
- "& .cm-task-item": {
485
- padding: "0 4px"
486
- }
487
- });
488
- var tasklist = () => [
489
- statefield(),
490
- styles
491
- ];
492
607
 
493
608
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tooltip.tsx
494
609
  import { hoverTooltip } from "@codemirror/view";
@@ -677,17 +792,29 @@ var defaultTheme = {
677
792
  var textTheme = {
678
793
  "& .cm-scroller": {
679
794
  fontFamily: get2(tokens, "fontFamily.body", []).join(",")
795
+ },
796
+ "& .cm-placeholder": {
797
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
798
+ }
799
+ };
800
+ var markdownTheme = {
801
+ // NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
802
+ "& .cm-placeholder": {
803
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
680
804
  }
681
805
  };
682
806
  var codeTheme = {
683
807
  "& .cm-scroller": {
684
808
  fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
809
+ },
810
+ "& .cm-placeholder": {
811
+ fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
685
812
  }
686
813
  };
687
814
 
688
815
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
689
816
  import { EditorState as EditorState2 } from "@codemirror/state";
690
- import { EditorView as EditorView5 } from "@codemirror/view";
817
+ import { EditorView as EditorView6 } from "@codemirror/view";
691
818
  import { useFocusableGroup } from "@fluentui/react-tabster";
692
819
  import { vim } from "@replit/codemirror-vim";
693
820
  import defaultsDeep from "lodash.defaultsdeep";
@@ -704,6 +831,18 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
704
831
  const tabsterDOMAttribute = useFocusableGroup({
705
832
  tabBehavior: "limited"
706
833
  });
834
+ const [root, setRoot] = useState(null);
835
+ const [state, setState] = useState();
836
+ const [view, setView] = useState();
837
+ useImperativeHandle(forwardedRef, () => ({
838
+ root,
839
+ state,
840
+ view
841
+ }), [
842
+ view,
843
+ state,
844
+ root
845
+ ]);
707
846
  const { awareness, peer } = model;
708
847
  useEffect(() => {
709
848
  if (awareness && peer) {
@@ -725,18 +864,6 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
725
864
  peer,
726
865
  themeMode
727
866
  ]);
728
- const [root, setRoot] = useState(null);
729
- const [state, setState] = useState();
730
- const [view, setView] = useState();
731
- useImperativeHandle(forwardedRef, () => ({
732
- root,
733
- state,
734
- view
735
- }), [
736
- view,
737
- state,
738
- root
739
- ]);
740
867
  useEffect(() => {
741
868
  if (!root) {
742
869
  return;
@@ -747,10 +874,10 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
747
874
  // TODO(burdon): Factor out VIM mode?
748
875
  editorMode === "vim" && vim(),
749
876
  // Theme.
750
- EditorView5.baseTheme(defaultTheme),
751
- EditorView5.theme(slots?.editor?.theme ?? {}),
877
+ EditorView6.baseTheme(defaultTheme),
878
+ EditorView6.theme(slots?.editor?.theme ?? {}),
752
879
  // TODO(burdon): themeMode doesn't change in storybooks.
753
- EditorView5.darkTheme.of(themeMode === "dark"),
880
+ EditorView6.darkTheme.of(themeMode === "dark"),
754
881
  // Storage and replication.
755
882
  model.extension,
756
883
  // Custom.
@@ -758,7 +885,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
758
885
  ].filter(Boolean)
759
886
  });
760
887
  view?.destroy();
761
- setView(new EditorView5({
888
+ setView(new EditorView6({
762
889
  state: state2,
763
890
  parent: root
764
891
  }));
@@ -817,7 +944,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, .
817
944
  });
818
945
  var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
819
946
  const { themeMode } = useThemeContext();
820
- const slots = defaultsDeep({}, _slots, defaultSlots);
947
+ const slots = defaultsDeep({}, _slots, defaultMarkdownSlots);
821
948
  return /* @__PURE__ */ React.createElement(BaseTextEditor, {
822
949
  ref: forwardedRef,
823
950
  extensions: [
@@ -842,17 +969,23 @@ var defaultTextSlots = {
842
969
  theme: textTheme
843
970
  }
844
971
  };
972
+ var defaultMarkdownSlots = {
973
+ ...defaultSlots,
974
+ editor: {
975
+ theme: markdownTheme
976
+ }
977
+ };
845
978
 
846
979
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
847
980
  import get3 from "lodash.get";
848
981
  import { useEffect as useEffect2, useState as useState2 } from "react";
849
982
  import { yCollab } from "y-codemirror.next";
850
- import { invariant } from "@dxos/invariant";
983
+ import { invariant as invariant2 } from "@dxos/invariant";
851
984
  import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
852
985
 
853
986
  // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
854
- import { Annotation, Facet, StateEffect, StateField as StateField4 } from "@codemirror/state";
855
- import { ViewPlugin } from "@codemirror/view";
987
+ import { Annotation, Facet, StateEffect, StateField as StateField3 } from "@codemirror/state";
988
+ import { ViewPlugin as ViewPlugin3 } from "@codemirror/view";
856
989
  import * as automerge2 from "@dxos/automerge/automerge";
857
990
 
858
991
  // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
@@ -1040,7 +1173,7 @@ var semaphoreFacet = Facet.define({
1040
1173
  combine: (values) => values.at(-1)
1041
1174
  });
1042
1175
  var automergePlugin = (handle, path) => {
1043
- const stateField = StateField4.define({
1176
+ const stateField = StateField3.define({
1044
1177
  create: () => ({
1045
1178
  lastHeads: automerge2.getHeads(handle.docSync()),
1046
1179
  unreconciledTransactions: [],
@@ -1070,7 +1203,7 @@ var automergePlugin = (handle, path) => {
1070
1203
  }
1071
1204
  });
1072
1205
  const semaphore = new PatchSemaphore(stateField);
1073
- const viewPlugin = ViewPlugin.fromClass(class AutomergeCodemirrorViewPlugin {
1206
+ const viewPlugin = ViewPlugin3.fromClass(class AutomergeCodemirrorViewPlugin {
1074
1207
  constructor(view) {
1075
1208
  this._handleChange = () => {
1076
1209
  this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
@@ -1144,7 +1277,7 @@ import * as encoding from "lib0/encoding";
1144
1277
  import { Observable } from "lib0/observable";
1145
1278
  import * as awarenessProtocol from "y-protocols/awareness";
1146
1279
  import { log } from "@dxos/log";
1147
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
1280
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
1148
1281
  var messageAwareness = 1;
1149
1282
  var messageQueryAwareness = 3;
1150
1283
  var SpaceAwarenessProvider = class extends Observable {
@@ -1181,7 +1314,7 @@ var SpaceAwarenessProvider = class extends Observable {
1181
1314
  removed,
1182
1315
  origin
1183
1316
  }, {
1184
- F: __dxlog_file,
1317
+ F: __dxlog_file2,
1185
1318
  L: 67,
1186
1319
  S: this,
1187
1320
  C: (f, a) => f(...a)
@@ -1194,7 +1327,7 @@ var SpaceAwarenessProvider = class extends Observable {
1194
1327
  }
1195
1328
  _handleSpaceMessage({ payload }) {
1196
1329
  log("space message", payload, {
1197
- F: __dxlog_file,
1330
+ F: __dxlog_file2,
1198
1331
  L: 79,
1199
1332
  S: this,
1200
1333
  C: (f, a) => f(...a)
@@ -1239,7 +1372,7 @@ var SpaceAwarenessProvider = class extends Observable {
1239
1372
  };
1240
1373
 
1241
1374
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
1242
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
1375
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
1243
1376
  var useTextModel = ({ identity, space, text }) => {
1244
1377
  const [model, setModel] = useState2(() => createModel({
1245
1378
  identity,
@@ -1260,44 +1393,44 @@ var useTextModel = ({ identity, space, text }) => {
1260
1393
  return model;
1261
1394
  };
1262
1395
  var createModel = (options) => {
1263
- const { space, text } = options;
1396
+ const { text } = options;
1264
1397
  if (isActualAutomergeObject(text)) {
1265
1398
  return createAutomergeModel(options);
1266
1399
  } else {
1267
- if (!space || !text?.doc || !text?.content) {
1400
+ if (!text?.doc) {
1268
1401
  return void 0;
1269
1402
  }
1270
1403
  return createYjsModel(options);
1271
1404
  }
1272
1405
  };
1273
1406
  var createYjsModel = ({ identity, space, text }) => {
1274
- invariant(space && text?.doc && text?.content, void 0, {
1275
- F: __dxlog_file2,
1276
- L: 73,
1407
+ invariant2(text?.doc && text?.content, void 0, {
1408
+ F: __dxlog_file3,
1409
+ L: 74,
1277
1410
  S: void 0,
1278
1411
  A: [
1279
- "space && text?.doc && text?.content",
1412
+ "text?.doc && text?.content",
1280
1413
  ""
1281
1414
  ]
1282
1415
  });
1283
- const provider = new SpaceAwarenessProvider({
1416
+ const provider = space ? new SpaceAwarenessProvider({
1284
1417
  space,
1285
1418
  doc: text.doc,
1286
1419
  channel: `yjs.awareness.${text.id}`
1287
- });
1420
+ }) : void 0;
1288
1421
  return {
1289
1422
  id: text.doc.guid,
1290
1423
  content: text.content,
1291
1424
  text: () => text.content.toString(),
1292
- extension: yCollab(text.content, provider.awareness),
1293
- awareness: provider.awareness,
1425
+ extension: yCollab(text.content, provider?.awareness),
1426
+ awareness: provider?.awareness,
1294
1427
  peer: identity ? {
1295
1428
  id: identity.identityKey.toHex(),
1296
1429
  name: identity.profile?.displayName
1297
1430
  } : void 0
1298
1431
  };
1299
1432
  };
1300
- var createAutomergeModel = ({ identity, space, text }) => {
1433
+ var createAutomergeModel = ({ identity, text }) => {
1301
1434
  const obj = text;
1302
1435
  const doc = getRawDoc(obj, [
1303
1436
  obj.field
@@ -1326,7 +1459,9 @@ export {
1326
1459
  autocomplete,
1327
1460
  basicBundle,
1328
1461
  codeTheme,
1462
+ comments,
1329
1463
  cursorColor,
1464
+ defaultMarkdownSlots,
1330
1465
  defaultSlots,
1331
1466
  defaultTextSlots,
1332
1467
  defaultTheme,
@@ -1336,8 +1471,7 @@ export {
1336
1471
  markdownHighlightStyle,
1337
1472
  markdownTags,
1338
1473
  markdownTagsExtension,
1339
- statefield,
1340
- styles,
1474
+ markdownTheme,
1341
1475
  tags2 as tags,
1342
1476
  tasklist,
1343
1477
  textTheme,