@dxos/react-ui-editor 0.3.11-main.42059c4 → 0.3.11-main.47875f3

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.
@@ -51,7 +51,7 @@ var autocomplete = ({ onSearch }) => {
51
51
  };
52
52
 
53
53
  // packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
54
- import { StateField } from "@codemirror/state";
54
+ import { Facet as Facet2, StateField } from "@codemirror/state";
55
55
  import { ViewPlugin } from "@codemirror/view";
56
56
  import { next as A } from "@dxos/automerge/automerge";
57
57
 
@@ -92,7 +92,7 @@ var cursorConverter = (handle, path) => ({
92
92
  });
93
93
 
94
94
  // packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
95
- import { Annotation, StateEffect, Facet } from "@codemirror/state";
95
+ import { Annotation, StateEffect } from "@codemirror/state";
96
96
  var effectType = StateEffect.define({});
97
97
  var updateHeads = (newHeads) => effectType.of({
98
98
  newHeads
@@ -101,9 +101,6 @@ var getLastHeads = (state, field) => state.field(field).lastHeads;
101
101
  var getPath = (state, field) => state.field(field).path;
102
102
  var reconcileAnnotationType = Annotation.define();
103
103
  var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
104
- var semaphoreFacet = Facet.define({
105
- combine: (values) => values.at(-1)
106
- });
107
104
 
108
105
  // packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
109
106
  import { next as automerge2 } from "@dxos/automerge/automerge";
@@ -240,11 +237,11 @@ var charPath = (textPath, candidatePath) => {
240
237
 
241
238
  // packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
242
239
  var PatchSemaphore = class {
243
- constructor(_handle, _field) {
244
- this._handle = _handle;
240
+ constructor(_field) {
245
241
  this._field = _field;
246
242
  this._inReconcile = false;
247
- this.reconcile = (view) => {
243
+ this._queue = [];
244
+ this.reconcile = (handle, view) => {
248
245
  if (this._inReconcile) {
249
246
  return;
250
247
  }
@@ -262,11 +259,11 @@ var PatchSemaphore = class {
262
259
  annotations: reconcileAnnotationType.of(true)
263
260
  });
264
261
  }
265
- let newHeads = updateAutomerge(this._field, this._handle, transactions, view.state);
262
+ let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
266
263
  if (newHeads === null || newHeads === void 0) {
267
- newHeads = automerge2.getHeads(this._handle.docSync());
264
+ newHeads = automerge2.getHeads(handle.docSync());
268
265
  }
269
- const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
266
+ const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
270
267
  updateCodeMirror(view, selection, path, diff);
271
268
  view.dispatch({
272
269
  effects: updateHeads(newHeads),
@@ -278,14 +275,14 @@ var PatchSemaphore = class {
278
275
  };
279
276
 
280
277
  // packages/ui/react-ui-editor/src/extensions/cursor.ts
281
- import { Facet as Facet2 } from "@codemirror/state";
278
+ import { Facet } from "@codemirror/state";
282
279
  var defaultCursorConverter = {
283
280
  toCursor: (position) => position.toString(),
284
281
  fromCursor: (cursor) => parseInt(cursor)
285
282
  };
286
283
  var Cursor = class {
287
284
  static {
288
- this.converter = Facet2.define({
285
+ this.converter = Facet.define({
289
286
  combine: (providers) => providers[0] ?? defaultCursorConverter
290
287
  });
291
288
  }
@@ -313,6 +310,9 @@ var Cursor = class {
313
310
  };
314
311
 
315
312
  // packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
313
+ var semaphoreFacet = Facet2.define({
314
+ combine: (values) => values.at(-1)
315
+ });
316
316
  var automerge3 = ({ handle, path }) => {
317
317
  const stateField = StateField.define({
318
318
  create: () => ({
@@ -343,19 +343,19 @@ var automerge3 = ({ handle, path }) => {
343
343
  return result;
344
344
  }
345
345
  });
346
- const semaphore = new PatchSemaphore(handle, stateField);
347
- const viewPlugin = ViewPlugin.fromClass(class AutomergeViewPlugin {
346
+ const semaphore = new PatchSemaphore(stateField);
347
+ const viewPlugin = ViewPlugin.fromClass(class AutomergeCodemirrorViewPlugin {
348
348
  constructor(_view) {
349
349
  this._view = _view;
350
350
  this._handleChange = () => {
351
- this._view.state.facet(semaphoreFacet).reconcile(this._view);
351
+ this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
352
352
  };
353
353
  handle.addListener("change", this._handleChange);
354
354
  }
355
355
  update(update2) {
356
356
  if (update2.transactions.length > 0 && update2.transactions.some((tr) => !isReconcileTx(tr))) {
357
357
  queueMicrotask(() => {
358
- this._view.state.facet(semaphoreFacet).reconcile(this._view);
358
+ this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
359
359
  });
360
360
  }
361
361
  }
@@ -1105,6 +1105,7 @@ import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView
1105
1105
  import sortBy from "lodash.sortby";
1106
1106
  import { debounce } from "@dxos/async";
1107
1107
  import { invariant as invariant2 } from "@dxos/invariant";
1108
+ import { log as log2 } from "@dxos/log";
1108
1109
  import { nonNullable } from "@dxos/util";
1109
1110
 
1110
1111
  // packages/ui/react-ui-editor/src/util.ts
@@ -1172,7 +1173,7 @@ var commentsStateField = StateField2.define({
1172
1173
  ...effect.value
1173
1174
  };
1174
1175
  }
1175
- if (effect.is(setCommentRange) && effect.value.comments.length > 0) {
1176
+ if (effect.is(setCommentRange)) {
1176
1177
  const { comments: comments2 } = effect.value;
1177
1178
  const ranges = comments2.map((comment) => {
1178
1179
  const range = Cursor.getRangeFromCursor(cursorConverter3, comment.cursor);
@@ -1213,56 +1214,51 @@ var highlightDecorations = EditorView5.decorations.compute([
1213
1214
  }).filter(nonNullable) ?? [];
1214
1215
  return Decoration3.set(decorations);
1215
1216
  });
1216
- var trackPastedComments = (onUpdate) => {
1217
+ var trackPastedComments = (onMove) => {
1217
1218
  let tracked = null;
1218
- const handleTrack = (event, view) => {
1219
+ const registerCopy = (event, view) => {
1219
1220
  const comments2 = view.state.field(commentsStateField);
1220
1221
  const { main } = view.state.selection;
1221
- const selectedRanges = comments2.ranges.filter((range) => range.from >= main.from && range.to <= main.to && range.from < range.to);
1222
- if (!selectedRanges.length) {
1222
+ const inSel = comments2.ranges.filter((range) => range.from >= main.from && range.to <= main.to && range.from < range.to);
1223
+ if (!inSel.length) {
1223
1224
  tracked = null;
1224
1225
  } else {
1225
1226
  tracked = {
1226
1227
  text: view.state.doc.slice(main.from, main.to),
1227
- comments: selectedRanges.map((range) => ({
1228
- id: range.id,
1228
+ comments: inSel.map((range) => ({
1229
1229
  from: range.from - main.from,
1230
- to: range.to - main.from
1230
+ to: range.to - main.from,
1231
+ id: range.id
1231
1232
  }))
1232
1233
  };
1233
1234
  }
1234
1235
  };
1235
1236
  return [
1236
1237
  EditorView5.domEventHandlers({
1237
- cut: handleTrack,
1238
- copy: handleTrack
1238
+ cut: registerCopy,
1239
+ copy: registerCopy
1239
1240
  }),
1240
- // Handle paste.
1241
- EditorView5.updateListener.of(({ view, state, transactions }) => {
1241
+ EditorView5.updateListener.of((update2) => {
1242
1242
  if (tracked) {
1243
- const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
1243
+ const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
1244
1244
  if (paste) {
1245
1245
  let found = -1;
1246
1246
  paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
1247
1247
  if (text.eq(tracked.text)) {
1248
- for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
1249
- fromB = transactions[i].changes.mapPos(fromB);
1248
+ for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
1249
+ fromB = update2.transactions[i].changes.mapPos(fromB);
1250
1250
  }
1251
1251
  found = fromB;
1252
1252
  }
1253
1253
  });
1254
1254
  if (found > -1) {
1255
- const comments2 = tracked.comments;
1256
- view.state.facet(semaphoreFacet).reconcile(view);
1257
- const active = state.field(commentsStateField).ranges;
1258
- for (const moved of comments2) {
1255
+ const active = update2.view.state.field(commentsStateField).ranges;
1256
+ for (const moved of tracked.comments) {
1259
1257
  if (active.some((range) => range.id === moved.id && range.from === range.to)) {
1260
- const range = {
1258
+ onMove(moved.id, Cursor.getCursorFromRange(update2.view.state.facet(Cursor.converter), {
1261
1259
  from: found + moved.from,
1262
1260
  to: found + moved.to
1263
- };
1264
- const cursor = Cursor.getCursorFromRange(state.facet(Cursor.converter), range);
1265
- onUpdate(moved.id, cursor);
1261
+ }));
1266
1262
  }
1267
1263
  }
1268
1264
  }
@@ -1279,14 +1275,14 @@ var comments = (options = {}) => {
1279
1275
  const cursorConverter3 = view.state.facet(Cursor.converter);
1280
1276
  invariant2(options.onCreate, void 0, {
1281
1277
  F: __dxlog_file3,
1282
- L: 262,
1278
+ L: 240,
1283
1279
  S: void 0,
1284
1280
  A: [
1285
1281
  "options.onCreate",
1286
1282
  ""
1287
1283
  ]
1288
1284
  });
1289
- const { from, to } = view.state.selection.main;
1285
+ const { head, from, to } = view.state.selection.main;
1290
1286
  if (from === to) {
1291
1287
  return false;
1292
1288
  }
@@ -1305,6 +1301,18 @@ var comments = (options = {}) => {
1305
1301
  anchor: from
1306
1302
  }
1307
1303
  });
1304
+ if (options.footnote) {
1305
+ const tag = `[^${id}]`;
1306
+ view.dispatch({
1307
+ changes: {
1308
+ from: head,
1309
+ insert: tag
1310
+ },
1311
+ selection: {
1312
+ anchor: head + tag.length
1313
+ }
1314
+ });
1315
+ }
1308
1316
  return true;
1309
1317
  }
1310
1318
  }
@@ -1366,7 +1374,14 @@ var comments = (options = {}) => {
1366
1374
  if (from2 === to2) {
1367
1375
  const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
1368
1376
  if (!newRange || newRange.to - newRange.from === 0) {
1369
- options.onDelete?.(range.id);
1377
+ log2.info("deleted comment", {
1378
+ thread: range.id
1379
+ }, {
1380
+ F: __dxlog_file3,
1381
+ L: 337,
1382
+ S: void 0,
1383
+ C: (f, a) => f(...a)
1384
+ });
1370
1385
  }
1371
1386
  }
1372
1387
  if (from <= range.to) {
@@ -1417,7 +1432,7 @@ var comments = (options = {}) => {
1417
1432
  }
1418
1433
  }
1419
1434
  }),
1420
- options.onUpdate ? trackPastedComments(options.onUpdate) : []
1435
+ options.onMove ? trackPastedComments(options.onMove) : []
1421
1436
  ];
1422
1437
  };
1423
1438
 
@@ -2465,7 +2480,7 @@ var EditorModes = [
2465
2480
  "default",
2466
2481
  "vim"
2467
2482
  ];
2468
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, selection, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
2483
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, readonly, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
2469
2484
  const tabsterDOMAttribute = useFocusableGroup({
2470
2485
  tabBehavior: "limited"
2471
2486
  });
@@ -2476,12 +2491,12 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
2476
2491
  view
2477
2492
  ]);
2478
2493
  useEffect(() => {
2479
- if (autofocus) {
2480
- view?.focus();
2494
+ if (view && focus) {
2495
+ view.focus();
2481
2496
  }
2482
2497
  }, [
2483
- autofocus,
2484
- view
2498
+ view,
2499
+ focus
2485
2500
  ]);
2486
2501
  const { awareness: awareness2, peer } = model;
2487
2502
  useEffect(() => {
@@ -2572,11 +2587,11 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
2572
2587
  return /* @__PURE__ */ React.createElement("div", {
2573
2588
  key: model.id,
2574
2589
  role: "none",
2590
+ ref: rootRef,
2575
2591
  tabIndex: 0,
2576
2592
  onKeyUp: handleKeyUp,
2577
2593
  ...slots.root,
2578
- ...editorMode !== "vim" && tabsterDOMAttribute,
2579
- ref: rootRef
2594
+ ...editorMode !== "vim" && tabsterDOMAttribute
2580
2595
  });
2581
2596
  });
2582
2597
  var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = textTheme, slots, ...props }, forwardedRef) => {
@@ -2619,7 +2634,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
2619
2634
  });
2620
2635
  var defaultSlots = {
2621
2636
  root: {
2622
- className: mx3("w-full p-2 overflow-y-auto", inputSurface)
2637
+ className: mx3("p-2 overflow-y-auto", inputSurface)
2623
2638
  }
2624
2639
  };
2625
2640
  var defaultTextSlots = {
@@ -2638,7 +2653,7 @@ import { isNotNullOrUndefined } from "@dxos/util";
2638
2653
  import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
2639
2654
  import { Context as Context2 } from "@dxos/context";
2640
2655
  import { invariant as invariant3 } from "@dxos/invariant";
2641
- import { log as log2 } from "@dxos/log";
2656
+ import { log as log3 } from "@dxos/log";
2642
2657
  var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
2643
2658
  var DEBOUNCE_INTERVAL = 100;
2644
2659
  var SpaceAwarenessProvider = class {
@@ -2677,7 +2692,7 @@ var SpaceAwarenessProvider = class {
2677
2692
  void this._space.postMessage(this._channel, {
2678
2693
  kind: "query"
2679
2694
  }).catch((err) => {
2680
- log2.debug("failed to query awareness", {
2695
+ log3.debug("failed to query awareness", {
2681
2696
  err
2682
2697
  }, {
2683
2698
  F: __dxlog_file4,
@@ -2750,7 +2765,7 @@ import * as encoding from "lib0/encoding";
2750
2765
  import { Observable } from "lib0/observable";
2751
2766
  import * as YP from "y-protocols/awareness";
2752
2767
  import { invariant as invariant4 } from "@dxos/invariant";
2753
- import { log as log3 } from "@dxos/log";
2768
+ import { log as log4 } from "@dxos/log";
2754
2769
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
2755
2770
  var createYjsModel = ({ identity, space, text }) => {
2756
2771
  invariant4(text?.doc && text?.content, void 0, {
@@ -2813,7 +2828,7 @@ var YAwarenessProvider = class extends Observable {
2813
2828
  return this._awareness;
2814
2829
  }
2815
2830
  _handleAwarenessUpdate({ added, updated, removed }, origin) {
2816
- log3("awareness update", {
2831
+ log4("awareness update", {
2817
2832
  added,
2818
2833
  updated,
2819
2834
  removed,
@@ -2831,7 +2846,7 @@ var YAwarenessProvider = class extends Observable {
2831
2846
  void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
2832
2847
  }
2833
2848
  _handleSpaceMessage({ payload }) {
2834
- log3("space message", payload, {
2849
+ log4("space message", payload, {
2835
2850
  F: __dxlog_file5,
2836
2851
  L: 109,
2837
2852
  S: this,