@dxos/react-ui-editor 0.3.11-main.3ac0bc5 → 0.3.11-main.3d4adea

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 (68) hide show
  1. package/dist/lib/browser/index.mjs +177 -313
  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 +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 +12 -17
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
  11. package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
  12. package/dist/types/src/components/TextEditor/yjs.stories.d.ts +1 -1
  13. package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
  14. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
  15. package/dist/types/src/extensions/automerge/index.d.ts +1 -0
  16. package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
  17. package/dist/types/src/extensions/code.d.ts.map +1 -1
  18. package/dist/types/src/extensions/comments.d.ts +2 -2
  19. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  20. package/dist/types/src/{util → extensions}/cursor.d.ts +9 -1
  21. package/dist/types/src/extensions/cursor.d.ts.map +1 -0
  22. package/dist/types/src/extensions/index.d.ts +1 -0
  23. package/dist/types/src/extensions/index.d.ts.map +1 -1
  24. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  25. package/dist/types/src/extensions/yjs/cursor.d.ts +1 -1
  26. package/dist/types/src/extensions/yjs/cursor.d.ts.map +1 -1
  27. package/dist/types/src/hooks/useTextModel.d.ts +0 -5
  28. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  29. package/dist/types/src/hooks/yjs.d.ts.map +1 -1
  30. package/dist/types/src/index.d.ts +2 -0
  31. package/dist/types/src/index.d.ts.map +1 -1
  32. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  33. package/dist/types/src/themes/default.d.ts.map +1 -1
  34. package/dist/types/src/util.d.ts.map +1 -0
  35. package/package.json +23 -22
  36. package/src/components/TextEditor/MarkdownEditor.stories.tsx +19 -16
  37. package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
  38. package/src/components/TextEditor/TextEditor.tsx +68 -64
  39. package/src/components/TextEditor/comments.stories.tsx +315 -0
  40. package/src/extensions/automerge/automerge.ts +2 -2
  41. package/src/extensions/automerge/cursor.ts +2 -1
  42. package/src/extensions/automerge/index.ts +1 -0
  43. package/src/extensions/awareness.ts +25 -32
  44. package/src/extensions/code.ts +10 -2
  45. package/src/extensions/comments.ts +20 -115
  46. package/src/extensions/cursor.ts +46 -0
  47. package/src/extensions/hr.ts +2 -2
  48. package/src/extensions/image.ts +2 -2
  49. package/src/extensions/index.ts +1 -0
  50. package/src/extensions/link.ts +4 -4
  51. package/src/extensions/markdown/highlight.ts +0 -8
  52. package/src/extensions/table.ts +2 -2
  53. package/src/extensions/tasklist.ts +2 -2
  54. package/src/extensions/yjs/cursor.ts +2 -1
  55. package/src/extensions/yjs/yjs.ts +2 -2
  56. package/src/hooks/useTextModel.ts +4 -7
  57. package/src/hooks/yjs.ts +1 -23
  58. package/src/index.ts +2 -0
  59. package/src/styles/markdown.ts +0 -2
  60. package/src/themes/default.ts +17 -50
  61. package/dist/types/src/util/cursor.d.ts.map +0 -1
  62. package/dist/types/src/util/index.d.ts +0 -3
  63. package/dist/types/src/util/index.d.ts.map +0 -1
  64. package/dist/types/src/util/util.d.ts.map +0 -1
  65. package/src/util/cursor.ts +0 -29
  66. package/src/util/index.ts +0 -6
  67. /package/dist/types/src/{util/util.d.ts → util.d.ts} +0 -0
  68. /package/src/{util/util.ts → util.ts} +0 -0
@@ -11,7 +11,7 @@ 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";
@@ -274,30 +274,39 @@ var PatchSemaphore = class {
274
274
  }
275
275
  };
276
276
 
277
- // packages/ui/react-ui-editor/src/util/cursor.ts
277
+ // packages/ui/react-ui-editor/src/extensions/cursor.ts
278
278
  import { Facet } from "@codemirror/state";
279
- var DEFAULT_CURSOR_CONVERTER = {
279
+ var defaultCursorConverter = {
280
280
  toCursor: (position) => position.toString(),
281
281
  fromCursor: (cursor) => parseInt(cursor)
282
282
  };
283
- var CursorConverter = Facet.define({
284
- combine: (providers) => providers[0] ?? DEFAULT_CURSOR_CONVERTER
285
- });
286
-
287
- // packages/ui/react-ui-editor/src/util/util.ts
288
- import { log } from "@dxos/log";
289
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
290
- var callbackWrapper = (fn) => (...args) => {
291
- try {
292
- return fn(...args);
293
- } catch (error) {
294
- log.catch(error, void 0, {
295
- F: __dxlog_file,
296
- L: 16,
297
- S: void 0,
298
- C: (f, a) => f(...a)
283
+ var Cursor = class {
284
+ static {
285
+ this.converter = Facet.define({
286
+ combine: (providers) => providers[0] ?? defaultCursorConverter
299
287
  });
300
288
  }
289
+ static {
290
+ this.getCursorFromRange = (cursorConverter3, range) => {
291
+ const from = cursorConverter3.toCursor(range.from);
292
+ const to = cursorConverter3.toCursor(range.to, -1);
293
+ return [
294
+ from,
295
+ to
296
+ ].join(":");
297
+ };
298
+ }
299
+ static {
300
+ this.getRangeFromCursor = (cursorConverter3, cursor) => {
301
+ const parts = cursor.split(":");
302
+ const from = cursorConverter3.fromCursor(parts[0]);
303
+ const to = cursorConverter3.fromCursor(parts[1]);
304
+ return from !== void 0 && to !== void 0 ? {
305
+ from,
306
+ to
307
+ } : void 0;
308
+ };
309
+ }
301
310
  };
302
311
 
303
312
  // packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
@@ -356,7 +365,7 @@ var automerge3 = ({ handle, path }) => {
356
365
  });
357
366
  return {
358
367
  extension: [
359
- CursorConverter.of(cursorConverter(handle, path)),
368
+ Cursor.converter.of(cursorConverter(handle, path)),
360
369
  semaphoreFacet.of(semaphore),
361
370
  stateField,
362
371
  viewPlugin
@@ -398,7 +407,7 @@ var RemoteSelectionsDecorator = class {
398
407
  this._ctx = new Context();
399
408
  this._lastAnchor = void 0;
400
409
  this._lastHead = void 0;
401
- this._cursorConverter = view.state.facet(CursorConverter);
410
+ this._cursorConverter = view.state.facet(Cursor.converter);
402
411
  this._provider = view.state.facet(AwarenessProvider);
403
412
  this._provider.open();
404
413
  this._provider.remoteStateChange.on(this._ctx, () => {
@@ -453,7 +462,7 @@ var RemoteSelectionsDecorator = class {
453
462
  attributes: {
454
463
  style: `background-color: ${lightColor}`
455
464
  },
456
- class: "cm-ySelection"
465
+ class: "cm-collab-selection"
457
466
  })
458
467
  });
459
468
  } else {
@@ -464,7 +473,7 @@ var RemoteSelectionsDecorator = class {
464
473
  attributes: {
465
474
  style: `background-color: ${color}`
466
475
  },
467
- class: "cm-ySelection"
476
+ class: "cm-collab-selection"
468
477
  })
469
478
  });
470
479
  decorations.push({
@@ -474,7 +483,7 @@ var RemoteSelectionsDecorator = class {
474
483
  attributes: {
475
484
  style: `background-color: ${color}`
476
485
  },
477
- class: "cm-ySelection"
486
+ class: "cm-collab-selection"
478
487
  })
479
488
  });
480
489
  for (let i = startLine.number + 1; i < endLine.number; i++) {
@@ -485,7 +494,7 @@ var RemoteSelectionsDecorator = class {
485
494
  value: Decoration.line({
486
495
  attributes: {
487
496
  style: `background-color: ${color}`,
488
- class: "cm-yLineSelection"
497
+ class: "cm-collab-selectionLine"
489
498
  }
490
499
  })
491
500
  });
@@ -505,23 +514,21 @@ var RemoteSelectionsDecorator = class {
505
514
  }
506
515
  };
507
516
  var RemoteCaretWidget = class extends WidgetType {
508
- constructor(name, color) {
517
+ constructor(_name, _color) {
509
518
  super();
510
- this.name = name;
511
- this.color = color;
512
- this.name = name;
513
- this.color = color;
519
+ this._name = _name;
520
+ this._color = _color;
514
521
  }
515
522
  toDOM() {
516
523
  const span = document.createElement("span");
517
- span.className = "cm-ySelectionCaret";
518
- span.style.backgroundColor = this.color;
519
- span.style.borderColor = this.color;
524
+ span.className = "cm-collab-selectionCaret";
525
+ span.style.backgroundColor = this._color;
526
+ span.style.borderColor = this._color;
520
527
  const dot = document.createElement("div");
521
- dot.className = "cm-ySelectionCaretDot";
528
+ dot.className = "cm-collab-selectionCaretDot";
522
529
  const info = document.createElement("div");
523
- info.className = "cm-ySelectionInfo";
524
- info.innerText = this.name;
530
+ info.className = "cm-collab-selectionInfo";
531
+ info.innerText = this._name;
525
532
  span.appendChild(document.createTextNode("\u2060"));
526
533
  span.appendChild(dot);
527
534
  span.appendChild(document.createTextNode("\u2060"));
@@ -529,15 +536,12 @@ var RemoteCaretWidget = class extends WidgetType {
529
536
  span.appendChild(document.createTextNode("\u2060"));
530
537
  return span;
531
538
  }
532
- eq(widget) {
533
- return widget.color === this.color;
534
- }
535
- compare(widget) {
536
- return widget.color === this.color;
537
- }
538
539
  updateDOM() {
539
540
  return false;
540
541
  }
542
+ eq(widget) {
543
+ return widget._color === this._color;
544
+ }
541
545
  get estimatedHeight() {
542
546
  return -1;
543
547
  }
@@ -546,12 +550,12 @@ var RemoteCaretWidget = class extends WidgetType {
546
550
  }
547
551
  };
548
552
  var styles = EditorView.baseTheme({
549
- ".cm-ySelection": {},
550
- ".cm-yLineSelection": {
553
+ ".cm-collab-selection": {},
554
+ ".cm-collab-selectionLine": {
551
555
  padding: 0,
552
556
  margin: "0px 2px 0px 4px"
553
557
  },
554
- ".cm-ySelectionCaret": {
558
+ ".cm-collab-selectionCaret": {
555
559
  position: "relative",
556
560
  borderLeft: "1px solid black",
557
561
  borderRight: "1px solid black",
@@ -560,7 +564,7 @@ var styles = EditorView.baseTheme({
560
564
  boxSizing: "border-box",
561
565
  display: "inline"
562
566
  },
563
- ".cm-ySelectionCaretDot": {
567
+ ".cm-collab-selectionCaretDot": {
564
568
  borderRadius: "50%",
565
569
  position: "absolute",
566
570
  width: ".4em",
@@ -571,11 +575,11 @@ var styles = EditorView.baseTheme({
571
575
  transition: "transform .3s ease-in-out",
572
576
  boxSizing: "border-box"
573
577
  },
574
- ".cm-ySelectionCaret:hover > .cm-ySelectionCaretDot": {
578
+ ".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
575
579
  transformOrigin: "bottom center",
576
580
  transform: "scale(0)"
577
581
  },
578
- ".cm-ySelectionInfo": {
582
+ ".cm-collab-selectionInfo": {
579
583
  position: "absolute",
580
584
  top: "-1.05em",
581
585
  left: "-1px",
@@ -596,7 +600,7 @@ var styles = EditorView.baseTheme({
596
600
  transitionDelay: "0s",
597
601
  whiteSpace: "nowrap"
598
602
  },
599
- ".cm-ySelectionCaret:hover > .cm-ySelectionInfo": {
603
+ ".cm-collab-selectionCaret:hover > .cm-collab-selectionInfo": {
600
604
  opacity: 1,
601
605
  transitionDelay: "0s"
602
606
  }
@@ -623,7 +627,7 @@ var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
623
627
  import { EditorView as EditorView3, keymap as keymap2 } from "@codemirror/view";
624
628
  import defaultsDeep from "lodash.defaultsdeep";
625
629
  import { invariant } from "@dxos/invariant";
626
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
630
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
627
631
  var defaultOptions = {
628
632
  effect: 2,
629
633
  maxParticles: 200,
@@ -750,7 +754,7 @@ var Blaster = class {
750
754
  }
751
755
  initialize() {
752
756
  invariant(!this._canvas && !this._ctx, void 0, {
753
- F: __dxlog_file2,
757
+ F: __dxlog_file,
754
758
  L: 138,
755
759
  S: this,
756
760
  A: [
@@ -787,7 +791,7 @@ var Blaster = class {
787
791
  }
788
792
  start() {
789
793
  invariant(this._canvas && this._ctx, void 0, {
790
- F: __dxlog_file2,
794
+ F: __dxlog_file,
791
795
  L: 177,
792
796
  S: this,
793
797
  A: [
@@ -1057,7 +1061,7 @@ var getLineRange = (lines, from, to) => {
1057
1061
  var code2 = () => {
1058
1062
  const getDecorations = (view) => {
1059
1063
  const decorations = [];
1060
- if (view.state.readOnly) {
1064
+ if (!view.hasFocus || view.state.readOnly) {
1061
1065
  const text = view.state.doc.sliceString(0);
1062
1066
  const matches = text.matchAll(CODE_REGEX);
1063
1067
  const blocks = view.viewportLineBlocks;
@@ -1076,10 +1080,15 @@ var code2 = () => {
1076
1080
  return [
1077
1081
  ViewPlugin3.fromClass(class {
1078
1082
  constructor(view) {
1083
+ this.hasFocus = false;
1079
1084
  this.decorations = getDecorations(view);
1080
1085
  }
1081
1086
  update(update2) {
1082
- if (update2.docChanged || update2.viewportChanged) {
1087
+ if (
1088
+ // TODO(burdon): Generalize for other extensions.
1089
+ this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
1090
+ ) {
1091
+ this.hasFocus = update2.view.hasFocus;
1083
1092
  this.decorations = getDecorations(update2.view);
1084
1093
  }
1085
1094
  }
@@ -1092,23 +1101,32 @@ var code2 = () => {
1092
1101
 
1093
1102
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1094
1103
  import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
1095
- import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
1104
+ import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
1096
1105
  import sortBy from "lodash.sortby";
1097
1106
  import { debounce } from "@dxos/async";
1098
1107
  import { invariant as invariant2 } from "@dxos/invariant";
1099
1108
  import { log as log2 } from "@dxos/log";
1100
1109
  import { nonNullable } from "@dxos/util";
1110
+
1111
+ // packages/ui/react-ui-editor/src/util.ts
1112
+ import { log } from "@dxos/log";
1113
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
1114
+ var callbackWrapper = (fn) => (...args) => {
1115
+ try {
1116
+ return fn(...args);
1117
+ } catch (error) {
1118
+ log.catch(error, void 0, {
1119
+ F: __dxlog_file2,
1120
+ L: 16,
1121
+ S: void 0,
1122
+ C: (f, a) => f(...a)
1123
+ });
1124
+ }
1125
+ };
1126
+
1127
+ // packages/ui/react-ui-editor/src/extensions/comments.ts
1101
1128
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
1102
1129
  var styles3 = EditorView5.baseTheme({
1103
- "& .cm-bookmark": {
1104
- cursor: "pointer",
1105
- margin: "4px",
1106
- padding: "4px",
1107
- backgroundColor: "yellow"
1108
- },
1109
- "& .cm-bookmark-selected": {
1110
- backgroundColor: "orange"
1111
- },
1112
1130
  "& .cm-comment": {
1113
1131
  backgroundColor: getToken("extend.colors.yellow.50")
1114
1132
  },
@@ -1147,7 +1165,7 @@ var commentsStateField = StateField2.define({
1147
1165
  ranges: []
1148
1166
  }),
1149
1167
  update: (value, tr) => {
1150
- const cursorConverter3 = tr.state.facet(CursorConverter);
1168
+ const cursorConverter3 = tr.state.facet(Cursor.converter);
1151
1169
  for (const effect of tr.effects) {
1152
1170
  if (effect.is(setSelection)) {
1153
1171
  return {
@@ -1158,7 +1176,7 @@ var commentsStateField = StateField2.define({
1158
1176
  if (effect.is(setCommentRange)) {
1159
1177
  const { comments: comments2 } = effect.value;
1160
1178
  const ranges = comments2.map((comment) => {
1161
- const range = getRangeFromCursor(cursorConverter3, comment.cursor);
1179
+ const range = Cursor.getRangeFromCursor(cursorConverter3, comment.cursor);
1162
1180
  return range && {
1163
1181
  ...comment,
1164
1182
  ...range
@@ -1196,42 +1214,14 @@ var highlightDecorations = EditorView5.decorations.compute([
1196
1214
  }).filter(nonNullable) ?? [];
1197
1215
  return Decoration3.set(decorations);
1198
1216
  });
1199
- var BookmarkWidget = class extends WidgetType2 {
1200
- constructor(_anchor, _id, _handleClick) {
1201
- super();
1202
- this._anchor = _anchor;
1203
- this._id = _id;
1204
- this._handleClick = _handleClick;
1205
- invariant2(this._id, void 0, {
1206
- F: __dxlog_file3,
1207
- L: 168,
1208
- S: this,
1209
- A: [
1210
- "this._id",
1211
- ""
1212
- ]
1213
- });
1214
- }
1215
- eq(other) {
1216
- return this._anchor === other._anchor && this._id === other._id;
1217
- }
1218
- toDOM() {
1219
- const span = document.createElement("span");
1220
- span.className = "cm-bookmark";
1221
- span.textContent = "\u203B";
1222
- if (this._handleClick) {
1223
- span.onclick = () => this._handleClick();
1224
- }
1225
- return span;
1226
- }
1227
- };
1228
1217
  var comments = (options = {}) => {
1218
+ const { key: shortcut = "meta-'" } = options;
1229
1219
  const handleSelect = debounce((state) => options.onSelect?.(state), 200);
1230
1220
  const createCommentThread = (view) => {
1231
- const cursorConverter3 = view.state.facet(CursorConverter);
1221
+ const cursorConverter3 = view.state.facet(Cursor.converter);
1232
1222
  invariant2(options.onCreate, void 0, {
1233
1223
  F: __dxlog_file3,
1234
- L: 224,
1224
+ L: 177,
1235
1225
  S: void 0,
1236
1226
  A: [
1237
1227
  "options.onCreate",
@@ -1242,12 +1232,12 @@ var comments = (options = {}) => {
1242
1232
  if (from === to) {
1243
1233
  return false;
1244
1234
  }
1245
- const relPos = getCursorFromRange(cursorConverter3, {
1235
+ const cursor = Cursor.getCursorFromRange(cursorConverter3, {
1246
1236
  from,
1247
1237
  to
1248
1238
  });
1249
- if (relPos) {
1250
- const id = callbackWrapper(options.onCreate)(relPos);
1239
+ if (cursor) {
1240
+ const id = callbackWrapper(options.onCreate)(cursor, view.coordsAtPos(from));
1251
1241
  if (id) {
1252
1242
  view.dispatch({
1253
1243
  effects: setSelection.of({
@@ -1274,35 +1264,7 @@ var comments = (options = {}) => {
1274
1264
  }
1275
1265
  return false;
1276
1266
  };
1277
- const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
1278
- static {
1279
- // Match markdown footnotes (option).
1280
- // https://www.markdownguide.org/extended-syntax/#footnotes
1281
- this.bookmarkMatcher = new MatchDecorator({
1282
- regexp: /\[\^(\w+)\]/g,
1283
- decoration: (match, view, pos) => {
1284
- const id = match[1];
1285
- return Decoration3.replace({
1286
- id,
1287
- widget: new BookmarkWidget(pos, id)
1288
- });
1289
- }
1290
- });
1291
- }
1292
- constructor(view) {
1293
- this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
1294
- }
1295
- update(update2) {
1296
- this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update2, this.bookmarks);
1297
- }
1298
- }, {
1299
- decorations: (instance) => instance.bookmarks,
1300
- provide: (plugin) => EditorView5.atomicRanges.of((view) => {
1301
- return view.plugin(plugin)?.bookmarks || Decoration3.none;
1302
- })
1303
- });
1304
1267
  return [
1305
- bookmarksViewPlugin,
1306
1268
  commentsStateField,
1307
1269
  highlightDecorations,
1308
1270
  styles3,
@@ -1311,7 +1273,7 @@ var comments = (options = {}) => {
1311
1273
  //
1312
1274
  options.onCreate ? keymap3.of([
1313
1275
  {
1314
- key: options?.key ?? "meta-'",
1276
+ key: shortcut,
1315
1277
  run: callbackWrapper(createCommentThread)
1316
1278
  }
1317
1279
  ]) : [],
@@ -1328,7 +1290,7 @@ var comments = (options = {}) => {
1328
1290
  above: true,
1329
1291
  create: () => {
1330
1292
  const el = document.createElement("div");
1331
- options.onHover?.(el);
1293
+ options.onHover?.(el, shortcut);
1332
1294
  return {
1333
1295
  dom: el,
1334
1296
  offset: {
@@ -1349,27 +1311,27 @@ var comments = (options = {}) => {
1349
1311
  // TODO(burdon): Is there a better (finer grained) way to do this?
1350
1312
  //
1351
1313
  EditorView5.updateListener.of(({ view, state, changes }) => {
1352
- const cursorConverter3 = view.state.facet(CursorConverter);
1314
+ const cursorConverter3 = view.state.facet(Cursor.converter);
1353
1315
  {
1354
1316
  let mod = false;
1355
1317
  const { active, ranges } = state.field(commentsStateField);
1356
1318
  changes.iterChanges((from, to, from2, to2) => {
1357
1319
  ranges.forEach((range) => {
1358
1320
  if (from2 === to2) {
1359
- const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
1321
+ const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
1360
1322
  if (!newRange || newRange.to - newRange.from === 0) {
1361
1323
  log2.info("deleted comment", {
1362
1324
  thread: range.id
1363
1325
  }, {
1364
1326
  F: __dxlog_file3,
1365
- L: 358,
1327
+ L: 274,
1366
1328
  S: void 0,
1367
1329
  C: (f, a) => f(...a)
1368
1330
  });
1369
1331
  }
1370
1332
  }
1371
1333
  if (from <= range.to) {
1372
- const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
1334
+ const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
1373
1335
  Object.assign(range, newRange);
1374
1336
  mod = true;
1375
1337
  }
@@ -1418,26 +1380,9 @@ var comments = (options = {}) => {
1418
1380
  })
1419
1381
  ];
1420
1382
  };
1421
- var getCursorFromRange = (cursorConverter3, range) => {
1422
- const from = cursorConverter3.toCursor(range.from);
1423
- const to = cursorConverter3.toCursor(range.to, -1);
1424
- return [
1425
- from,
1426
- to
1427
- ].join(":");
1428
- };
1429
- var getRangeFromCursor = (cursorConverter3, cursor) => {
1430
- const parts = cursor.split(":");
1431
- const from = cursorConverter3.fromCursor(parts[0]);
1432
- const to = cursorConverter3.fromCursor(parts[1]);
1433
- return from !== void 0 && to !== void 0 ? {
1434
- from,
1435
- to
1436
- } : void 0;
1437
- };
1438
1383
 
1439
1384
  // packages/ui/react-ui-editor/src/extensions/hr.ts
1440
- import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin5, WidgetType as WidgetType3 } from "@codemirror/view";
1385
+ import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
1441
1386
  var styles4 = EditorView6.baseTheme({
1442
1387
  "& .cm-hr": {
1443
1388
  // TODO(burdon): ???
@@ -1445,7 +1390,7 @@ var styles4 = EditorView6.baseTheme({
1445
1390
  borderBottom: `1px solid ${getToken("extend.colors.neutral.200")}`
1446
1391
  }
1447
1392
  });
1448
- var HorizontalRuleWidget = class extends WidgetType3 {
1393
+ var HorizontalRuleWidget = class extends WidgetType2 {
1449
1394
  constructor(_pos) {
1450
1395
  super();
1451
1396
  this._pos = _pos;
@@ -1459,7 +1404,7 @@ var HorizontalRuleWidget = class extends WidgetType3 {
1459
1404
  return el;
1460
1405
  }
1461
1406
  };
1462
- var placeholderMatcher = new MatchDecorator2({
1407
+ var placeholderMatcher = new MatchDecorator({
1463
1408
  regexp: /^---$/g,
1464
1409
  decoration: (match, view, pos) => Decoration4.replace({
1465
1410
  widget: new HorizontalRuleWidget(pos)
@@ -1467,7 +1412,7 @@ var placeholderMatcher = new MatchDecorator2({
1467
1412
  });
1468
1413
  var hr = () => [
1469
1414
  styles4,
1470
- ViewPlugin5.fromClass(class {
1415
+ ViewPlugin4.fromClass(class {
1471
1416
  constructor(view) {
1472
1417
  this.rules = placeholderMatcher.createDeco(view);
1473
1418
  }
@@ -1486,7 +1431,7 @@ var hr = () => [
1486
1431
  // packages/ui/react-ui-editor/src/extensions/image.ts
1487
1432
  import { syntaxTree } from "@codemirror/language";
1488
1433
  import { StateField as StateField3 } from "@codemirror/state";
1489
- import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
1434
+ import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
1490
1435
  var image = (options = {}) => {
1491
1436
  return StateField3.define({
1492
1437
  create: (state) => {
@@ -1538,7 +1483,7 @@ var buildDecorations = (from, to, state) => {
1538
1483
  });
1539
1484
  return decorations;
1540
1485
  };
1541
- var ImageWidget = class extends WidgetType4 {
1486
+ var ImageWidget = class extends WidgetType3 {
1542
1487
  constructor(_url) {
1543
1488
  super();
1544
1489
  this._url = _url;
@@ -1558,11 +1503,11 @@ var ImageWidget = class extends WidgetType4 {
1558
1503
  // packages/ui/react-ui-editor/src/extensions/link.ts
1559
1504
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
1560
1505
  import { RangeSetBuilder } from "@codemirror/state";
1561
- import { Decoration as Decoration6, WidgetType as WidgetType5, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
1506
+ import { Decoration as Decoration6, WidgetType as WidgetType4, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
1562
1507
  import { tooltipContent } from "@dxos/react-ui-theme";
1563
1508
  var link = (options = {}) => {
1564
1509
  const extensions = [
1565
- ViewPlugin6.fromClass(class {
1510
+ ViewPlugin5.fromClass(class {
1566
1511
  constructor(view) {
1567
1512
  this.decorations = buildDecorations2(view, options);
1568
1513
  }
@@ -1613,7 +1558,7 @@ var link = (options = {}) => {
1613
1558
  }
1614
1559
  return extensions;
1615
1560
  };
1616
- var LinkButton = class extends WidgetType5 {
1561
+ var LinkButton = class extends WidgetType4 {
1617
1562
  constructor(_url, _onAttach) {
1618
1563
  super();
1619
1564
  this._url = _url;
@@ -1628,7 +1573,7 @@ var LinkButton = class extends WidgetType5 {
1628
1573
  return el;
1629
1574
  }
1630
1575
  };
1631
- var LinkText = class extends WidgetType5 {
1576
+ var LinkText = class extends WidgetType4 {
1632
1577
  constructor(_text, _url) {
1633
1578
  super();
1634
1579
  this._text = _text;
@@ -1728,7 +1673,6 @@ var markdownTags = {
1728
1673
  CodeText: Tag.define(),
1729
1674
  EmphasisMark: Tag.define(),
1730
1675
  HeaderMark: Tag.define(),
1731
- // HorizontalRule: Tag.define(),
1732
1676
  InlineCode: Tag.define(),
1733
1677
  LinkLabel: Tag.define(),
1734
1678
  LinkReference: Tag.define(),
@@ -1892,12 +1836,6 @@ var markdownHighlightStyle = (readonly) => {
1892
1836
  ],
1893
1837
  class: blockquote
1894
1838
  },
1895
- // TODO(burdon): Replace with extension.
1896
- // {
1897
- // tag: [markdownTags.HorizontalRule],
1898
- // class: mx(horizontalRule, readonly && '-indent-[100rem]'),
1899
- // },
1900
- // TODO(burdon): Only if being edited.
1901
1839
  {
1902
1840
  tag: [
1903
1841
  markdownTags.TableCell
@@ -1991,7 +1929,7 @@ var mention = ({ onSearch }) => {
1991
1929
  // packages/ui/react-ui-editor/src/extensions/table.ts
1992
1930
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
1993
1931
  import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
1994
- import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType6 } from "@codemirror/view";
1932
+ import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType5 } from "@codemirror/view";
1995
1933
  var table = (options = {}) => {
1996
1934
  return StateField4.define({
1997
1935
  create: (state) => update(state, options),
@@ -2049,7 +1987,7 @@ var update = (state, options) => {
2049
1987
  });
2050
1988
  return builder.finish();
2051
1989
  };
2052
- var TableWidget = class extends WidgetType6 {
1990
+ var TableWidget = class extends WidgetType5 {
2053
1991
  constructor(_table) {
2054
1992
  super();
2055
1993
  this._table = _table;
@@ -2087,14 +2025,14 @@ var TableWidget = class extends WidgetType6 {
2087
2025
  };
2088
2026
 
2089
2027
  // packages/ui/react-ui-editor/src/extensions/tasklist.ts
2090
- import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType7, MatchDecorator as MatchDecorator3, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
2028
+ import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
2091
2029
  var styles5 = EditorView11.baseTheme({
2092
2030
  "& .cm-task-item": {
2093
2031
  paddingLeft: "4px",
2094
2032
  paddingRight: "8px"
2095
2033
  }
2096
2034
  });
2097
- var CheckboxWidget = class extends WidgetType7 {
2035
+ var CheckboxWidget = class extends WidgetType6 {
2098
2036
  constructor(_checked, _indent, _onCheck) {
2099
2037
  super();
2100
2038
  this._checked = _checked;
@@ -2128,7 +2066,7 @@ var CheckboxWidget = class extends WidgetType7 {
2128
2066
  }
2129
2067
  };
2130
2068
  var tasklist = (options = {}) => {
2131
- const taskMatcher = new MatchDecorator3({
2069
+ const taskMatcher = new MatchDecorator2({
2132
2070
  regexp: /^(\s*)- \[([ xX])\]\s/g,
2133
2071
  decoration: (match, view, pos) => {
2134
2072
  const indent = Math.floor(match[1].length / 2);
@@ -2151,7 +2089,7 @@ var tasklist = (options = {}) => {
2151
2089
  });
2152
2090
  }
2153
2091
  });
2154
- const tasks = ViewPlugin7.fromClass(class {
2092
+ const tasks = ViewPlugin6.fromClass(class {
2155
2093
  constructor(view) {
2156
2094
  this.tasks = taskMatcher.createDeco(view);
2157
2095
  }
@@ -2244,7 +2182,7 @@ var cursorConverter2 = (text) => ({
2244
2182
 
2245
2183
  // packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
2246
2184
  var yjs = (content, awareness2) => [
2247
- CursorConverter.of(cursorConverter2(content)),
2185
+ Cursor.converter.of(cursorConverter2(content)),
2248
2186
  yCollab(content, awareness2)
2249
2187
  ];
2250
2188
 
@@ -2341,33 +2279,6 @@ var defaultTheme = {
2341
2279
  backgroundColor: get3(tokens, "extend.colors.yellow.700")
2342
2280
  },
2343
2281
  //
2344
- // collaboration
2345
- // TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
2346
- //
2347
- "&light .cm-ySelection, &light .cm-yLineSelection": {
2348
- mixBlendMode: "multiply"
2349
- },
2350
- "&dark .cm-ySelection, &dark .cm-yLineSelection": {
2351
- mixBlendMode: "screen"
2352
- },
2353
- ".cm-ySelectionInfo": {
2354
- padding: "2px 4px",
2355
- marginBlockStart: "-4px"
2356
- },
2357
- ".cm-ySelection, & .cm-selectionMatch": {
2358
- paddingBlockStart: ".15em",
2359
- paddingBlockEnd: ".15em"
2360
- },
2361
- ".cm-ySelectionCaret": {
2362
- display: "inline-block",
2363
- insetBlockStart: ".1em",
2364
- blockSize: "1.4em",
2365
- verticalAlign: "top"
2366
- },
2367
- ".cm-yLineSelection": {
2368
- margin: 0
2369
- },
2370
- //
2371
2282
  // link
2372
2283
  //
2373
2284
  ".cm-link": {
@@ -2404,13 +2315,6 @@ var defaultTheme = {
2404
2315
  textDecoration: "none"
2405
2316
  },
2406
2317
  //
2407
- // widgets
2408
- //
2409
- ".cm-widgetBuffer": {
2410
- display: "none",
2411
- height: 0
2412
- },
2413
- //
2414
2318
  // table
2415
2319
  //
2416
2320
  ".cm-table *": {
@@ -2441,27 +2345,17 @@ var defaultTheme = {
2441
2345
  },
2442
2346
  //
2443
2347
  // font size
2444
- // TODO(thure): This appears to be the best or only way to set selection caret heights, but it's far more verbose than it needs to be.
2348
+ // TODO(thure): This appears to be the best or only way to set selection caret heights,
2349
+ // but it's far more verbose than it needs to be.
2445
2350
  //
2446
- ...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
2447
- const height = get3(tokens, [
2448
- "extend",
2449
- "fontSize",
2450
- fontSize,
2451
- 1,
2452
- "lineHeight"
2453
- ]);
2454
- acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
2455
- height
2456
- };
2457
- acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
2458
- height
2459
- };
2460
- acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
2461
- height
2462
- };
2463
- return acc;
2464
- }, {}),
2351
+ // ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
2352
+ // const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
2353
+ //
2354
+ // acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
2355
+ // acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
2356
+ // acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
2357
+ // return acc;
2358
+ // }, {}),
2465
2359
  /**
2466
2360
  * Panels
2467
2361
  * TODO(burdon): Needs styling attention (esp. dark mode).
@@ -2512,7 +2406,9 @@ var textTheme = {
2512
2406
  }
2513
2407
  };
2514
2408
  var markdownTheme = {
2515
- // NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
2409
+ ".cm-scroller": {
2410
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
2411
+ },
2516
2412
  ".cm-placeholder": {
2517
2413
  fontFamily: get3(tokens, "fontFamily.body", []).join(",")
2518
2414
  }
@@ -2531,21 +2427,23 @@ var EditorModes = [
2531
2427
  "default",
2532
2428
  "vim"
2533
2429
  ];
2534
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
2535
- const { themeMode } = useThemeContext();
2430
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, readonly, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
2536
2431
  const tabsterDOMAttribute = useFocusableGroup({
2537
2432
  tabBehavior: "limited"
2538
2433
  });
2539
- const [root, setRoot] = useState(null);
2540
- const [{ state = void 0, view = void 0 } = {}, setEditor] = useState();
2541
- useImperativeHandle(forwardedRef, () => ({
2542
- root,
2543
- state,
2434
+ const { themeMode } = useThemeContext();
2435
+ const rootRef = useRef(null);
2436
+ const [view, setView] = useState(null);
2437
+ useImperativeHandle(forwardedRef, () => view, [
2544
2438
  view
2545
- }), [
2439
+ ]);
2440
+ useEffect(() => {
2441
+ if (view && focus) {
2442
+ view.focus();
2443
+ }
2444
+ }, [
2546
2445
  view,
2547
- state,
2548
- root
2446
+ focus
2549
2447
  ]);
2550
2448
  const { awareness: awareness2, peer } = model;
2551
2449
  useEffect(() => {
@@ -2569,7 +2467,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2569
2467
  themeMode
2570
2468
  ]);
2571
2469
  useEffect(() => {
2572
- if (view && comments2?.length) {
2470
+ if (view && comments2 !== void 0) {
2573
2471
  view.dispatch({
2574
2472
  effects: setCommentRange.of({
2575
2473
  model,
@@ -2582,11 +2480,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2582
2480
  comments2
2583
2481
  ]);
2584
2482
  useEffect(() => {
2585
- if (!root) {
2483
+ if (!model || !rootRef.current) {
2586
2484
  return;
2587
2485
  }
2588
- const state2 = EditorState2.create({
2486
+ const state = EditorState2.create({
2589
2487
  doc: model.text(),
2488
+ // TODO(burdon): Composer should store and set selection when switching documents.
2489
+ selection,
2590
2490
  extensions: [
2591
2491
  readonly && EditorState2.readOnly.of(readonly),
2592
2492
  // TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
@@ -2594,7 +2494,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2594
2494
  // Theme.
2595
2495
  // TODO(burdon): Make theme configurable.
2596
2496
  EditorView12.baseTheme(defaultTheme),
2597
- EditorView12.theme(slots?.editor?.theme ?? {}),
2497
+ EditorView12.theme(theme ?? {}),
2598
2498
  EditorView12.darkTheme.of(themeMode === "dark"),
2599
2499
  // Storage and replication.
2600
2500
  model.extension,
@@ -2603,19 +2503,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2603
2503
  ].filter(Boolean)
2604
2504
  });
2605
2505
  view?.destroy();
2606
- setEditor({
2607
- state: state2,
2608
- view: new EditorView12({
2609
- state: state2,
2610
- parent: root
2611
- })
2506
+ const newView = new EditorView12({
2507
+ parent: rootRef.current,
2508
+ state
2612
2509
  });
2510
+ setView(newView);
2613
2511
  return () => {
2614
- view?.destroy();
2615
- setEditor(void 0);
2512
+ newView?.destroy();
2513
+ setView(null);
2616
2514
  };
2617
2515
  }, [
2618
- root,
2516
+ rootRef,
2619
2517
  model,
2620
2518
  readonly,
2621
2519
  editorMode,
@@ -2624,12 +2522,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2624
2522
  const handleKeyUp = useCallback((event) => {
2625
2523
  const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
2626
2524
  switch (key) {
2627
- case "Enter": {
2628
- view?.contentDOM.focus();
2629
- break;
2630
- }
2631
2525
  case "Escape": {
2632
- editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && root?.focus();
2526
+ editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
2633
2527
  break;
2634
2528
  }
2635
2529
  }
@@ -2639,16 +2533,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
2639
2533
  ]);
2640
2534
  return /* @__PURE__ */ React.createElement("div", {
2641
2535
  key: model.id,
2642
- ref: setRoot,
2536
+ role: "none",
2537
+ ref: rootRef,
2643
2538
  tabIndex: 0,
2644
- ...slots?.root,
2645
- ...editorMode !== "vim" && tabsterDOMAttribute,
2646
- onKeyUp: handleKeyUp
2539
+ onKeyUp: handleKeyUp,
2540
+ ...slots.root,
2541
+ ...editorMode !== "vim" && tabsterDOMAttribute
2647
2542
  });
2648
2543
  });
2649
- var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
2544
+ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = textTheme, slots, ...props }, forwardedRef) => {
2650
2545
  const { themeMode } = useThemeContext();
2651
- const slots = defaultsDeep2({}, _slots, defaultTextSlots);
2546
+ const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
2652
2547
  return /* @__PURE__ */ React.createElement(BaseTextEditor, {
2653
2548
  ref: forwardedRef,
2654
2549
  readonly,
@@ -2656,17 +2551,18 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
2656
2551
  basicBundle({
2657
2552
  readonly,
2658
2553
  themeMode,
2659
- placeholder: slots?.editor?.placeholder
2554
+ placeholder: placeholder3
2660
2555
  }),
2661
2556
  ...extensions
2662
2557
  ],
2663
- slots,
2558
+ theme,
2559
+ slots: updatedSlots,
2664
2560
  ...props
2665
2561
  });
2666
2562
  });
2667
- var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
2563
+ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = markdownTheme, slots, ...props }, forwardedRef) => {
2668
2564
  const { themeMode } = useThemeContext();
2669
- const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
2565
+ const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
2670
2566
  return /* @__PURE__ */ React.createElement(BaseTextEditor, {
2671
2567
  ref: forwardedRef,
2672
2568
  readonly,
@@ -2674,30 +2570,25 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
2674
2570
  markdownBundle({
2675
2571
  readonly,
2676
2572
  themeMode,
2677
- placeholder: slots?.editor?.placeholder
2573
+ placeholder: placeholder3
2678
2574
  }),
2679
2575
  ...extensions
2680
2576
  ],
2681
- slots,
2577
+ theme,
2578
+ slots: updatedSlots,
2682
2579
  ...props
2683
2580
  });
2684
2581
  });
2685
2582
  var defaultSlots = {
2686
2583
  root: {
2687
- className: mx3("p-2", inputSurface)
2584
+ className: mx3("p-2 overflow-y-auto", inputSurface)
2688
2585
  }
2689
2586
  };
2690
2587
  var defaultTextSlots = {
2691
- ...defaultSlots,
2692
- editor: {
2693
- theme: textTheme
2694
- }
2588
+ ...defaultSlots
2695
2589
  };
2696
2590
  var defaultMarkdownSlots = {
2697
- ...defaultSlots,
2698
- editor: {
2699
- theme: markdownTheme
2700
- }
2591
+ ...defaultSlots
2701
2592
  };
2702
2593
 
2703
2594
  // packages/ui/react-ui-editor/src/hooks/automerge.ts
@@ -2820,15 +2711,13 @@ import * as decoding from "lib0/decoding";
2820
2711
  import * as encoding from "lib0/encoding";
2821
2712
  import { Observable } from "lib0/observable";
2822
2713
  import * as YP from "y-protocols/awareness";
2823
- import * as Y2 from "yjs";
2824
2714
  import { invariant as invariant4 } from "@dxos/invariant";
2825
2715
  import { log as log4 } from "@dxos/log";
2826
- import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
2827
2716
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
2828
2717
  var createYjsModel = ({ identity, space, text }) => {
2829
2718
  invariant4(text?.doc && text?.content, void 0, {
2830
2719
  F: __dxlog_file5,
2831
- L: 23,
2720
+ L: 21,
2832
2721
  S: void 0,
2833
2722
  A: [
2834
2723
  "text?.doc && text?.content",
@@ -2844,34 +2733,6 @@ var createYjsModel = ({ identity, space, text }) => {
2844
2733
  id: text.doc.guid,
2845
2734
  content: text.content,
2846
2735
  text: () => text.content.toString(),
2847
- // https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
2848
- // TODO(dmaretskyi): Refactor as cursor-converter.
2849
- getCursorFromRange: (range) => {
2850
- const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
2851
- const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
2852
- return [
2853
- arrayToString2(from),
2854
- arrayToString2(to)
2855
- ].join(":");
2856
- },
2857
- getRangeFromCursor: (cursor) => {
2858
- invariant4(text.doc, void 0, {
2859
- F: __dxlog_file5,
2860
- L: 40,
2861
- S: void 0,
2862
- A: [
2863
- "text.doc",
2864
- ""
2865
- ]
2866
- });
2867
- const parts = cursor.split(":");
2868
- const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
2869
- const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
2870
- return from && to ? {
2871
- from: from.index,
2872
- to: to.index
2873
- } : void 0;
2874
- },
2875
2736
  extension: [
2876
2737
  modelState.init(() => model),
2877
2738
  yjs(text.content, provider?.awareness)
@@ -2921,7 +2782,7 @@ var YAwarenessProvider = class extends Observable {
2921
2782
  origin
2922
2783
  }, {
2923
2784
  F: __dxlog_file5,
2924
- L: 122,
2785
+ L: 100,
2925
2786
  S: this,
2926
2787
  C: (f, a) => f(...a)
2927
2788
  });
@@ -2934,7 +2795,7 @@ var YAwarenessProvider = class extends Observable {
2934
2795
  _handleSpaceMessage({ payload }) {
2935
2796
  log4("space message", payload, {
2936
2797
  F: __dxlog_file5,
2937
- L: 131,
2798
+ L: 109,
2938
2799
  S: this,
2939
2800
  C: (f, a) => f(...a)
2940
2801
  });
@@ -2984,7 +2845,7 @@ var modelState = StateField5.define({
2984
2845
  });
2985
2846
  var useTextModel = (props) => {
2986
2847
  const { identity, space, text } = props;
2987
- const [model, setModel] = useState2(() => createModel(props));
2848
+ const [model, setModel] = useState2();
2988
2849
  useEffect2(() => setModel(createModel(props)), [
2989
2850
  identity,
2990
2851
  space,
@@ -3043,6 +2904,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
3043
2904
  export {
3044
2905
  AwarenessProvider,
3045
2906
  BaseTextEditor,
2907
+ Cursor,
3046
2908
  Doc,
3047
2909
  EditorModes,
3048
2910
  MarkdownEditor,
@@ -3058,11 +2920,13 @@ export {
3058
2920
  awareness,
3059
2921
  basicBundle,
3060
2922
  blast,
2923
+ callbackWrapper,
3061
2924
  code2 as code,
3062
2925
  codeTheme,
3063
2926
  comments,
3064
2927
  createAutomergeModel,
3065
2928
  createYjsModel,
2929
+ cursorConverter,
3066
2930
  defaultMarkdownSlots,
3067
2931
  defaultOptions,
3068
2932
  defaultSlots,