@dxos/react-ui-editor 0.3.11-main.00a28cb → 0.3.11-main.08776d7
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.
- package/dist/lib/browser/index.mjs +258 -252
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +4 -2
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +5 -7
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +5 -4
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +12 -12
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor.d.ts +3 -3
- package/dist/types/src/extensions/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +1 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/sync.d.ts +7 -0
- package/dist/types/src/extensions/sync.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge.d.ts +2 -1
- package/dist/types/src/hooks/automerge.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +28 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +2 -27
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/hooks/yjs.d.ts +2 -1
- package/dist/types/src/hooks/yjs.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +5 -5
- package/src/components/TextEditor/TextEditor.tsx +46 -38
- package/src/components/TextEditor/comments.stories.tsx +35 -28
- package/src/extensions/automerge/automerge.ts +10 -39
- package/src/extensions/automerge/defs.ts +8 -13
- package/src/extensions/automerge/semaphore.ts +14 -7
- package/src/extensions/comments.ts +137 -126
- package/src/extensions/cursor.ts +7 -3
- package/src/extensions/index.ts +1 -0
- package/src/extensions/sync.ts +15 -0
- package/src/hooks/automerge.ts +2 -1
- package/src/hooks/defs.ts +47 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useTextModel.ts +2 -45
- package/src/hooks/yjs.ts +2 -1
|
@@ -52,7 +52,6 @@ var autocomplete = ({ onSearch }) => {
|
|
|
52
52
|
|
|
53
53
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
54
54
|
import { StateField } from "@codemirror/state";
|
|
55
|
-
import { ViewPlugin } from "@codemirror/view";
|
|
56
55
|
import { next as A } from "@dxos/automerge/automerge";
|
|
57
56
|
|
|
58
57
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
@@ -92,18 +91,15 @@ var cursorConverter = (handle, path) => ({
|
|
|
92
91
|
});
|
|
93
92
|
|
|
94
93
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
95
|
-
import { Annotation, StateEffect
|
|
94
|
+
import { Annotation, StateEffect } from "@codemirror/state";
|
|
96
95
|
var effectType = StateEffect.define({});
|
|
96
|
+
var reconcileAnnotationType = Annotation.define();
|
|
97
|
+
var getPath = (state, field) => state.field(field).path;
|
|
98
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
97
99
|
var updateHeads = (newHeads) => effectType.of({
|
|
98
100
|
newHeads
|
|
99
101
|
});
|
|
100
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
101
|
-
var getPath = (state, field) => state.field(field).path;
|
|
102
|
-
var reconcileAnnotationType = Annotation.define();
|
|
103
102
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
104
|
-
var semaphoreFacet = Facet.define({
|
|
105
|
-
combine: (values) => values.at(-1)
|
|
106
|
-
});
|
|
107
103
|
|
|
108
104
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
109
105
|
import { next as automerge2 } from "@dxos/automerge/automerge";
|
|
@@ -240,57 +236,60 @@ var charPath = (textPath, candidatePath) => {
|
|
|
240
236
|
|
|
241
237
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
242
238
|
var PatchSemaphore = class {
|
|
239
|
+
// prettier-ignore
|
|
243
240
|
constructor(_handle, _field) {
|
|
244
241
|
this._handle = _handle;
|
|
245
242
|
this._field = _field;
|
|
246
243
|
this._inReconcile = false;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
annotations: reconcileAnnotationType.of(true)
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
let newHeads = updateAutomerge(this._field, this._handle, transactions, view.state);
|
|
266
|
-
if (newHeads === null || newHeads === void 0) {
|
|
267
|
-
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
268
|
-
}
|
|
269
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
270
|
-
updateCodeMirror(view, selection, path, diff);
|
|
244
|
+
}
|
|
245
|
+
// NOTE: Cannot destruct view.state.
|
|
246
|
+
reconcile(view) {
|
|
247
|
+
if (this._inReconcile) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this._inReconcile = true;
|
|
251
|
+
const path = getPath(view.state, this._field);
|
|
252
|
+
const oldHeads = getLastHeads(view.state, this._field);
|
|
253
|
+
let selection = view.state.selection;
|
|
254
|
+
const transactions = view.state.field(this._field).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
255
|
+
const toInvert = transactions.slice().reverse();
|
|
256
|
+
for (const tx of toInvert) {
|
|
257
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
258
|
+
selection = selection.map(inverted);
|
|
271
259
|
view.dispatch({
|
|
272
|
-
|
|
273
|
-
annotations: reconcileAnnotationType.of(
|
|
260
|
+
changes: inverted,
|
|
261
|
+
annotations: reconcileAnnotationType.of(true)
|
|
274
262
|
});
|
|
275
|
-
|
|
276
|
-
|
|
263
|
+
}
|
|
264
|
+
let newHeads = updateAutomerge(this._field, this._handle, transactions, view.state);
|
|
265
|
+
if (newHeads === null || newHeads === void 0) {
|
|
266
|
+
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
267
|
+
}
|
|
268
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
269
|
+
updateCodeMirror(view, selection, path, diff);
|
|
270
|
+
view.dispatch({
|
|
271
|
+
effects: updateHeads(newHeads),
|
|
272
|
+
annotations: reconcileAnnotationType.of({})
|
|
273
|
+
});
|
|
274
|
+
this._inReconcile = false;
|
|
277
275
|
}
|
|
278
276
|
};
|
|
279
277
|
|
|
280
278
|
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
281
|
-
import { Facet
|
|
279
|
+
import { Facet } from "@codemirror/state";
|
|
282
280
|
var defaultCursorConverter = {
|
|
283
281
|
toCursor: (position) => position.toString(),
|
|
284
282
|
fromCursor: (cursor) => parseInt(cursor)
|
|
285
283
|
};
|
|
286
|
-
var Cursor = class {
|
|
284
|
+
var Cursor = class _Cursor {
|
|
287
285
|
static {
|
|
288
|
-
this.converter =
|
|
286
|
+
this.converter = Facet.define({
|
|
289
287
|
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
290
288
|
});
|
|
291
289
|
}
|
|
292
290
|
static {
|
|
293
|
-
this.getCursorFromRange = (
|
|
291
|
+
this.getCursorFromRange = (state, range) => {
|
|
292
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
294
293
|
const from = cursorConverter3.toCursor(range.from);
|
|
295
294
|
const to = cursorConverter3.toCursor(range.to, -1);
|
|
296
295
|
return [
|
|
@@ -300,7 +299,8 @@ var Cursor = class {
|
|
|
300
299
|
};
|
|
301
300
|
}
|
|
302
301
|
static {
|
|
303
|
-
this.getRangeFromCursor = (
|
|
302
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
303
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
304
304
|
const parts = cursor.split(":");
|
|
305
305
|
const from = cursorConverter3.fromCursor(parts[0]);
|
|
306
306
|
const to = cursorConverter3.fromCursor(parts[1]);
|
|
@@ -312,19 +312,25 @@ var Cursor = class {
|
|
|
312
312
|
}
|
|
313
313
|
};
|
|
314
314
|
|
|
315
|
+
// packages/ui/react-ui-editor/src/extensions/sync.ts
|
|
316
|
+
import { Facet as Facet2 } from "@codemirror/state";
|
|
317
|
+
var syncFacet = Facet2.define({
|
|
318
|
+
combine: (values) => values.at(-1)
|
|
319
|
+
});
|
|
320
|
+
|
|
315
321
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
316
322
|
var automerge3 = ({ handle, path }) => {
|
|
317
323
|
const stateField = StateField.define({
|
|
318
324
|
create: () => ({
|
|
325
|
+
path: path.slice(),
|
|
319
326
|
lastHeads: A.getHeads(handle.docSync()),
|
|
320
|
-
unreconciledTransactions: []
|
|
321
|
-
path: path.slice()
|
|
327
|
+
unreconciledTransactions: []
|
|
322
328
|
}),
|
|
323
329
|
update: (value, tr) => {
|
|
324
330
|
const result = {
|
|
331
|
+
path: path.slice(),
|
|
325
332
|
lastHeads: value.lastHeads,
|
|
326
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
327
|
-
path: path.slice()
|
|
333
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
328
334
|
};
|
|
329
335
|
let clearUnreconciled = false;
|
|
330
336
|
for (const effect of tr.effects) {
|
|
@@ -344,38 +350,18 @@ var automerge3 = ({ handle, path }) => {
|
|
|
344
350
|
}
|
|
345
351
|
});
|
|
346
352
|
const semaphore = new PatchSemaphore(handle, stateField);
|
|
347
|
-
const viewPlugin = ViewPlugin.fromClass(class AutomergeViewPlugin {
|
|
348
|
-
constructor(_view) {
|
|
349
|
-
this._view = _view;
|
|
350
|
-
this._handleChange = () => {
|
|
351
|
-
this._view.state.facet(semaphoreFacet).reconcile(this._view);
|
|
352
|
-
};
|
|
353
|
-
handle.addListener("change", this._handleChange);
|
|
354
|
-
}
|
|
355
|
-
update(update2) {
|
|
356
|
-
if (update2.transactions.length > 0 && update2.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
357
|
-
queueMicrotask(() => {
|
|
358
|
-
this._view.state.facet(semaphoreFacet).reconcile(this._view);
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
destroy() {
|
|
363
|
-
handle.addListener("change", this._handleChange);
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
353
|
return {
|
|
367
354
|
extension: [
|
|
368
355
|
Cursor.converter.of(cursorConverter(handle, path)),
|
|
369
|
-
|
|
370
|
-
stateField
|
|
371
|
-
viewPlugin
|
|
356
|
+
syncFacet.of(semaphore),
|
|
357
|
+
stateField
|
|
372
358
|
]
|
|
373
359
|
};
|
|
374
360
|
};
|
|
375
361
|
|
|
376
362
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
377
363
|
import { Annotation as Annotation2, Facet as Facet3, RangeSet } from "@codemirror/state";
|
|
378
|
-
import { Decoration, EditorView, ViewPlugin
|
|
364
|
+
import { Decoration, EditorView, ViewPlugin, WidgetType } from "@codemirror/view";
|
|
379
365
|
import { Event } from "@dxos/async";
|
|
380
366
|
import { Context } from "@dxos/context";
|
|
381
367
|
var dummyProvider = {
|
|
@@ -395,7 +381,7 @@ var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
|
395
381
|
var awareness = (provider = dummyProvider) => {
|
|
396
382
|
return [
|
|
397
383
|
AwarenessProvider.of(provider),
|
|
398
|
-
|
|
384
|
+
ViewPlugin.fromClass(RemoteSelectionsDecorator, {
|
|
399
385
|
decorations: (value) => value.decorations
|
|
400
386
|
}),
|
|
401
387
|
styles
|
|
@@ -934,7 +920,7 @@ var random = (min, max) => {
|
|
|
934
920
|
};
|
|
935
921
|
|
|
936
922
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
937
|
-
import { ViewPlugin as
|
|
923
|
+
import { ViewPlugin as ViewPlugin2, EditorView as EditorView4, Decoration as Decoration2 } from "@codemirror/view";
|
|
938
924
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
939
925
|
|
|
940
926
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1076,7 +1062,7 @@ var code2 = () => {
|
|
|
1076
1062
|
return Decoration2.set(decorations);
|
|
1077
1063
|
};
|
|
1078
1064
|
return [
|
|
1079
|
-
|
|
1065
|
+
ViewPlugin2.fromClass(class {
|
|
1080
1066
|
constructor(view) {
|
|
1081
1067
|
this.hasFocus = false;
|
|
1082
1068
|
this.decorations = buildDecorations4(view);
|
|
@@ -1140,8 +1126,8 @@ var marks = {
|
|
|
1140
1126
|
})
|
|
1141
1127
|
};
|
|
1142
1128
|
var setFocus = (view, thread) => {
|
|
1143
|
-
const
|
|
1144
|
-
if (!
|
|
1129
|
+
const comment = view.state.field(commentsState).comments.find((range) => range.comment.id === thread);
|
|
1130
|
+
if (!comment) {
|
|
1145
1131
|
return;
|
|
1146
1132
|
}
|
|
1147
1133
|
view.dispatch({
|
|
@@ -1149,39 +1135,41 @@ var setFocus = (view, thread) => {
|
|
|
1149
1135
|
active: thread
|
|
1150
1136
|
}),
|
|
1151
1137
|
selection: {
|
|
1152
|
-
anchor: range.from
|
|
1138
|
+
anchor: comment.range.from
|
|
1153
1139
|
},
|
|
1154
1140
|
scrollIntoView: true
|
|
1155
1141
|
});
|
|
1156
1142
|
};
|
|
1157
|
-
var
|
|
1143
|
+
var setComments = StateEffect2.define();
|
|
1158
1144
|
var setSelection = StateEffect2.define();
|
|
1159
1145
|
var setCommentState = StateEffect2.define();
|
|
1160
|
-
var
|
|
1146
|
+
var commentsState = StateField2.define({
|
|
1161
1147
|
create: () => ({
|
|
1162
|
-
|
|
1148
|
+
comments: [],
|
|
1149
|
+
selection: {}
|
|
1163
1150
|
}),
|
|
1164
1151
|
update: (value, tr) => {
|
|
1165
|
-
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1166
1152
|
for (const effect of tr.effects) {
|
|
1167
1153
|
if (effect.is(setSelection)) {
|
|
1168
1154
|
return {
|
|
1169
1155
|
...value,
|
|
1170
|
-
|
|
1156
|
+
selection: effect.value
|
|
1171
1157
|
};
|
|
1172
1158
|
}
|
|
1173
|
-
if (effect.is(
|
|
1174
|
-
const
|
|
1175
|
-
|
|
1176
|
-
|
|
1159
|
+
if (effect.is(setComments)) {
|
|
1160
|
+
const comments2 = effect.value.map((comment) => {
|
|
1161
|
+
if (!comment.cursor) {
|
|
1162
|
+
return void 0;
|
|
1163
|
+
}
|
|
1164
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1177
1165
|
return range && {
|
|
1178
|
-
|
|
1179
|
-
|
|
1166
|
+
comment,
|
|
1167
|
+
range
|
|
1180
1168
|
};
|
|
1181
1169
|
}).filter(nonNullable);
|
|
1182
1170
|
return {
|
|
1183
1171
|
...value,
|
|
1184
|
-
|
|
1172
|
+
comments: comments2
|
|
1185
1173
|
};
|
|
1186
1174
|
}
|
|
1187
1175
|
if (effect.is(setCommentState)) {
|
|
@@ -1192,38 +1180,36 @@ var commentsStateField = StateField2.define({
|
|
|
1192
1180
|
}
|
|
1193
1181
|
});
|
|
1194
1182
|
var highlightDecorations = EditorView5.decorations.compute([
|
|
1195
|
-
|
|
1183
|
+
commentsState
|
|
1196
1184
|
], (state) => {
|
|
1197
|
-
const { active,
|
|
1198
|
-
const decorations = sortBy(
|
|
1199
|
-
|
|
1185
|
+
const { selection: { active }, comments: comments2 } = state.field(commentsState);
|
|
1186
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1187
|
+
const range = comment.range;
|
|
1188
|
+
if (!range || range.from === range.to) {
|
|
1189
|
+
console.warn("Invalid range:", range);
|
|
1200
1190
|
return void 0;
|
|
1201
1191
|
}
|
|
1202
|
-
|
|
1203
|
-
from: selection.from,
|
|
1204
|
-
to: selection.to
|
|
1205
|
-
};
|
|
1206
|
-
if (selection.id === active) {
|
|
1192
|
+
if (comment.comment.id === active) {
|
|
1207
1193
|
return marks.highlightActive.range(range.from, range.to);
|
|
1208
1194
|
} else {
|
|
1209
1195
|
return marks.highlight.range(range.from, range.to);
|
|
1210
1196
|
}
|
|
1211
|
-
}).filter(nonNullable)
|
|
1197
|
+
}).filter(nonNullable);
|
|
1212
1198
|
return Decoration3.set(decorations);
|
|
1213
1199
|
});
|
|
1214
1200
|
var trackPastedComments = (onUpdate) => {
|
|
1215
1201
|
let tracked = null;
|
|
1216
1202
|
const handleTrack = (event, view) => {
|
|
1217
|
-
const comments2 = view.state.field(
|
|
1203
|
+
const comments2 = view.state.field(commentsState);
|
|
1218
1204
|
const { main } = view.state.selection;
|
|
1219
|
-
const selectedRanges = comments2.
|
|
1205
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1220
1206
|
if (!selectedRanges.length) {
|
|
1221
1207
|
tracked = null;
|
|
1222
1208
|
} else {
|
|
1223
1209
|
tracked = {
|
|
1224
1210
|
text: view.state.doc.slice(main.from, main.to),
|
|
1225
|
-
comments: selectedRanges.map((range) => ({
|
|
1226
|
-
id:
|
|
1211
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1212
|
+
id: comment.id,
|
|
1227
1213
|
from: range.from - main.from,
|
|
1228
1214
|
to: range.to - main.from
|
|
1229
1215
|
}))
|
|
@@ -1250,18 +1236,14 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1250
1236
|
}
|
|
1251
1237
|
});
|
|
1252
1238
|
if (found > -1) {
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
};
|
|
1262
|
-
const cursor = Cursor.getCursorFromRange(state.facet(Cursor.converter), range);
|
|
1263
|
-
onUpdate(moved.id, cursor);
|
|
1264
|
-
}
|
|
1239
|
+
state.facet(syncFacet)?.reconcile(view);
|
|
1240
|
+
for (const moved of tracked.comments) {
|
|
1241
|
+
const range = {
|
|
1242
|
+
from: found + moved.from,
|
|
1243
|
+
to: found + moved.to
|
|
1244
|
+
};
|
|
1245
|
+
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1246
|
+
onUpdate(moved.id, cursor);
|
|
1265
1247
|
}
|
|
1266
1248
|
}
|
|
1267
1249
|
tracked = null;
|
|
@@ -1274,10 +1256,9 @@ var comments = (options = {}) => {
|
|
|
1274
1256
|
const { key: shortcut = "meta-'" } = options;
|
|
1275
1257
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1276
1258
|
const createCommentThread = (view) => {
|
|
1277
|
-
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1278
1259
|
invariant2(options.onCreate, void 0, {
|
|
1279
1260
|
F: __dxlog_file3,
|
|
1280
|
-
L:
|
|
1261
|
+
L: 262,
|
|
1281
1262
|
S: void 0,
|
|
1282
1263
|
A: [
|
|
1283
1264
|
"options.onCreate",
|
|
@@ -1288,7 +1269,15 @@ var comments = (options = {}) => {
|
|
|
1288
1269
|
if (from === to) {
|
|
1289
1270
|
return false;
|
|
1290
1271
|
}
|
|
1291
|
-
|
|
1272
|
+
if (to === view.state.doc.length) {
|
|
1273
|
+
view.dispatch({
|
|
1274
|
+
changes: {
|
|
1275
|
+
from: to,
|
|
1276
|
+
insert: "\n"
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1292
1281
|
from,
|
|
1293
1282
|
to
|
|
1294
1283
|
});
|
|
@@ -1309,7 +1298,7 @@ var comments = (options = {}) => {
|
|
|
1309
1298
|
return false;
|
|
1310
1299
|
};
|
|
1311
1300
|
return [
|
|
1312
|
-
|
|
1301
|
+
commentsState,
|
|
1313
1302
|
highlightDecorations,
|
|
1314
1303
|
styles3,
|
|
1315
1304
|
//
|
|
@@ -1318,6 +1307,7 @@ var comments = (options = {}) => {
|
|
|
1318
1307
|
options.onCreate ? keymap3.of([
|
|
1319
1308
|
{
|
|
1320
1309
|
key: shortcut,
|
|
1310
|
+
// TODO(burdon): Check if there's a better way?
|
|
1321
1311
|
run: callbackWrapper(createCommentThread)
|
|
1322
1312
|
}
|
|
1323
1313
|
]) : [],
|
|
@@ -1352,68 +1342,68 @@ var comments = (options = {}) => {
|
|
|
1352
1342
|
hoverTime: 1e3
|
|
1353
1343
|
}) : [],
|
|
1354
1344
|
//
|
|
1355
|
-
//
|
|
1356
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1345
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1357
1346
|
//
|
|
1358
1347
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1359
|
-
|
|
1360
|
-
{
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
if (
|
|
1366
|
-
|
|
1367
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1368
|
-
options.onDelete?.(range.id);
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
if (from <= range.to) {
|
|
1372
|
-
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1373
|
-
Object.assign(range, newRange);
|
|
1374
|
-
mod = true;
|
|
1348
|
+
let mod = false;
|
|
1349
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1350
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1351
|
+
comments2.forEach(({ comment, range }) => {
|
|
1352
|
+
if (from2 === to2) {
|
|
1353
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1354
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1355
|
+
options.onDelete?.(comment.id);
|
|
1375
1356
|
}
|
|
1376
|
-
}
|
|
1357
|
+
}
|
|
1358
|
+
if (from <= range.to) {
|
|
1359
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1360
|
+
Object.assign(range, newRange);
|
|
1361
|
+
mod = true;
|
|
1362
|
+
}
|
|
1363
|
+
});
|
|
1364
|
+
});
|
|
1365
|
+
if (mod) {
|
|
1366
|
+
view.dispatch({
|
|
1367
|
+
effects: setCommentState.of({
|
|
1368
|
+
comments: comments2,
|
|
1369
|
+
...value
|
|
1370
|
+
})
|
|
1377
1371
|
});
|
|
1378
|
-
if (mod) {
|
|
1379
|
-
view.dispatch({
|
|
1380
|
-
effects: setCommentState.of({
|
|
1381
|
-
active,
|
|
1382
|
-
ranges
|
|
1383
|
-
})
|
|
1384
|
-
});
|
|
1385
|
-
}
|
|
1386
1372
|
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1373
|
+
}),
|
|
1374
|
+
//
|
|
1375
|
+
// Track selection/proximity.
|
|
1376
|
+
//
|
|
1377
|
+
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1378
|
+
let min = Infinity;
|
|
1379
|
+
const { selection: { active, closest }, comments: comments2 } = state.field(commentsState);
|
|
1380
|
+
const { head } = state.selection.main;
|
|
1381
|
+
const selection = {};
|
|
1382
|
+
comments2.forEach(({ comment, range }) => {
|
|
1383
|
+
if (head >= range.from && head <= range.to) {
|
|
1384
|
+
selection.active = comment.id;
|
|
1385
|
+
selection.closest = void 0;
|
|
1386
|
+
}
|
|
1387
|
+
if (!selection.active) {
|
|
1388
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1400
1389
|
if (d < min) {
|
|
1401
|
-
|
|
1390
|
+
selection.closest = comment.id;
|
|
1402
1391
|
min = d;
|
|
1403
1392
|
}
|
|
1404
|
-
});
|
|
1405
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1406
|
-
view.dispatch({
|
|
1407
|
-
effects: setSelection.of(selected)
|
|
1408
|
-
});
|
|
1409
|
-
handleSelect({
|
|
1410
|
-
...selected,
|
|
1411
|
-
ranges: ranges.map((range) => ({
|
|
1412
|
-
...range,
|
|
1413
|
-
location: view.coordsAtPos(range.from)
|
|
1414
|
-
}))
|
|
1415
|
-
});
|
|
1416
1393
|
}
|
|
1394
|
+
});
|
|
1395
|
+
if (selection.active !== active || selection.closest !== closest) {
|
|
1396
|
+
view.dispatch({
|
|
1397
|
+
effects: setSelection.of(selection)
|
|
1398
|
+
});
|
|
1399
|
+
handleSelect({
|
|
1400
|
+
selection,
|
|
1401
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1402
|
+
comment,
|
|
1403
|
+
range,
|
|
1404
|
+
location: view.coordsAtPos(range.from)
|
|
1405
|
+
}))
|
|
1406
|
+
});
|
|
1417
1407
|
}
|
|
1418
1408
|
}),
|
|
1419
1409
|
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
@@ -1421,7 +1411,7 @@ var comments = (options = {}) => {
|
|
|
1421
1411
|
};
|
|
1422
1412
|
|
|
1423
1413
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1424
|
-
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator, ViewPlugin as
|
|
1414
|
+
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1425
1415
|
var styles4 = EditorView6.baseTheme({
|
|
1426
1416
|
"& .cm-hr": {
|
|
1427
1417
|
// TODO(burdon): ???
|
|
@@ -1452,7 +1442,7 @@ var placeholderMatcher = new MatchDecorator({
|
|
|
1452
1442
|
});
|
|
1453
1443
|
var hr = () => [
|
|
1454
1444
|
styles4,
|
|
1455
|
-
|
|
1445
|
+
ViewPlugin3.fromClass(class {
|
|
1456
1446
|
constructor(view) {
|
|
1457
1447
|
this.rules = placeholderMatcher.createDeco(view);
|
|
1458
1448
|
}
|
|
@@ -1539,11 +1529,11 @@ var ImageWidget = class extends WidgetType3 {
|
|
|
1539
1529
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1540
1530
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1541
1531
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
1542
|
-
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as
|
|
1532
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin4, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1543
1533
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1544
1534
|
var link = (options = {}) => {
|
|
1545
1535
|
const extensions = [
|
|
1546
|
-
|
|
1536
|
+
ViewPlugin4.fromClass(class {
|
|
1547
1537
|
constructor(view) {
|
|
1548
1538
|
this.decorations = buildDecorations2(view, options);
|
|
1549
1539
|
}
|
|
@@ -2068,7 +2058,7 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2068
2058
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2069
2059
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2070
2060
|
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
2071
|
-
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as
|
|
2061
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
2072
2062
|
var CheckboxWidget = class extends WidgetType6 {
|
|
2073
2063
|
constructor(_checked) {
|
|
2074
2064
|
super();
|
|
@@ -2112,7 +2102,7 @@ var uncheckedDeco = Decoration8.replace({
|
|
|
2112
2102
|
widget: new CheckboxWidget(false)
|
|
2113
2103
|
});
|
|
2114
2104
|
var tasklist = (options = {}) => {
|
|
2115
|
-
return
|
|
2105
|
+
return ViewPlugin5.fromClass(class {
|
|
2116
2106
|
constructor(view) {
|
|
2117
2107
|
this.decorations = buildDecorations3(view);
|
|
2118
2108
|
}
|
|
@@ -2467,25 +2457,20 @@ var EditorModes = [
|
|
|
2467
2457
|
"default",
|
|
2468
2458
|
"vim"
|
|
2469
2459
|
];
|
|
2470
|
-
var
|
|
2471
|
-
const tabsterDOMAttribute = useFocusableGroup({
|
|
2472
|
-
tabBehavior: "limited"
|
|
2473
|
-
});
|
|
2474
|
-
const { themeMode } = useThemeContext();
|
|
2475
|
-
const rootRef = useRef(null);
|
|
2476
|
-
const [view, setView] = useState(null);
|
|
2477
|
-
useImperativeHandle(forwardedRef, () => view, [
|
|
2478
|
-
view
|
|
2479
|
-
]);
|
|
2460
|
+
var useComments = (view, comments2) => {
|
|
2480
2461
|
useEffect(() => {
|
|
2481
|
-
if (
|
|
2482
|
-
view
|
|
2462
|
+
if (view && comments2 !== void 0) {
|
|
2463
|
+
view.dispatch({
|
|
2464
|
+
effects: setComments.of(comments2)
|
|
2465
|
+
});
|
|
2483
2466
|
}
|
|
2484
2467
|
}, [
|
|
2485
|
-
|
|
2486
|
-
|
|
2468
|
+
view,
|
|
2469
|
+
comments2
|
|
2487
2470
|
]);
|
|
2488
|
-
|
|
2471
|
+
};
|
|
2472
|
+
var useAwareness = ({ awareness: awareness2, peer }) => {
|
|
2473
|
+
const { themeMode } = useThemeContext();
|
|
2489
2474
|
useEffect(() => {
|
|
2490
2475
|
if (awareness2 && peer) {
|
|
2491
2476
|
awareness2.setLocalStateField("user", {
|
|
@@ -2506,19 +2491,27 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
|
|
|
2506
2491
|
peer,
|
|
2507
2492
|
themeMode
|
|
2508
2493
|
]);
|
|
2494
|
+
};
|
|
2495
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, selection, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
|
|
2496
|
+
const tabsterDOMAttribute = useFocusableGroup({
|
|
2497
|
+
tabBehavior: "limited"
|
|
2498
|
+
});
|
|
2499
|
+
const { themeMode } = useThemeContext();
|
|
2500
|
+
const rootRef = useRef(null);
|
|
2501
|
+
const [view, setView] = useState(null);
|
|
2502
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2503
|
+
view
|
|
2504
|
+
]);
|
|
2509
2505
|
useEffect(() => {
|
|
2510
|
-
if (
|
|
2511
|
-
view
|
|
2512
|
-
effects: setCommentRange.of({
|
|
2513
|
-
model,
|
|
2514
|
-
comments: comments2
|
|
2515
|
-
})
|
|
2516
|
-
});
|
|
2506
|
+
if (autofocus) {
|
|
2507
|
+
view?.focus();
|
|
2517
2508
|
}
|
|
2518
2509
|
}, [
|
|
2519
2510
|
view,
|
|
2520
|
-
|
|
2511
|
+
autofocus
|
|
2521
2512
|
]);
|
|
2513
|
+
useAwareness(model);
|
|
2514
|
+
useComments(view, comments2);
|
|
2522
2515
|
useEffect(() => {
|
|
2523
2516
|
if (!model || !rootRef.current) {
|
|
2524
2517
|
return;
|
|
@@ -2529,14 +2522,14 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
|
|
|
2529
2522
|
selection,
|
|
2530
2523
|
extensions: [
|
|
2531
2524
|
readonly && EditorState2.readOnly.of(readonly),
|
|
2532
|
-
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
2533
|
-
editorMode === "vim" && vim(),
|
|
2534
2525
|
// Theme.
|
|
2535
2526
|
// TODO(burdon): Make theme configurable.
|
|
2536
2527
|
EditorView12.baseTheme(defaultTheme),
|
|
2537
2528
|
EditorView12.theme(theme ?? {}),
|
|
2538
2529
|
EditorView12.darkTheme.of(themeMode === "dark"),
|
|
2539
|
-
//
|
|
2530
|
+
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
2531
|
+
editorMode === "vim" && vim(),
|
|
2532
|
+
// Storage and replication (NOTE: must come before other extensions).
|
|
2540
2533
|
model.extension,
|
|
2541
2534
|
// Custom.
|
|
2542
2535
|
...extensions
|
|
@@ -2545,7 +2538,15 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
|
|
|
2545
2538
|
view?.destroy();
|
|
2546
2539
|
const newView = new EditorView12({
|
|
2547
2540
|
parent: rootRef.current,
|
|
2548
|
-
state
|
|
2541
|
+
state,
|
|
2542
|
+
// NOTE: Uncomment to spy on all transactions.
|
|
2543
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2544
|
+
dispatch: (transaction, view2) => {
|
|
2545
|
+
view2.update([
|
|
2546
|
+
transaction
|
|
2547
|
+
]);
|
|
2548
|
+
view2.state.facet(syncFacet)?.reconcile(view2);
|
|
2549
|
+
}
|
|
2549
2550
|
});
|
|
2550
2551
|
setView(newView);
|
|
2551
2552
|
return () => {
|
|
@@ -2563,7 +2564,9 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
|
|
|
2563
2564
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2564
2565
|
switch (key) {
|
|
2565
2566
|
case "Escape": {
|
|
2566
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2567
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2568
|
+
rootRef.current?.focus();
|
|
2569
|
+
}
|
|
2567
2570
|
break;
|
|
2568
2571
|
}
|
|
2569
2572
|
}
|
|
@@ -2741,10 +2744,50 @@ var SpaceAwarenessProvider = class {
|
|
|
2741
2744
|
}
|
|
2742
2745
|
};
|
|
2743
2746
|
|
|
2744
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2747
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2745
2748
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2746
|
-
|
|
2747
|
-
|
|
2749
|
+
var modelState = StateField5.define({
|
|
2750
|
+
create: () => void 0,
|
|
2751
|
+
update: (model) => model
|
|
2752
|
+
});
|
|
2753
|
+
|
|
2754
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2755
|
+
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2756
|
+
const obj = text;
|
|
2757
|
+
const doc = getRawDoc(obj, [
|
|
2758
|
+
obj.field
|
|
2759
|
+
]);
|
|
2760
|
+
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2761
|
+
space,
|
|
2762
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
2763
|
+
info: {
|
|
2764
|
+
displayName: identity?.profile?.displayName ?? "",
|
|
2765
|
+
color: cursorColor.color,
|
|
2766
|
+
lightColor: cursorColor.light
|
|
2767
|
+
},
|
|
2768
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2769
|
+
});
|
|
2770
|
+
const model = {
|
|
2771
|
+
id: obj.id,
|
|
2772
|
+
content: doc,
|
|
2773
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2774
|
+
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2775
|
+
extension: [
|
|
2776
|
+
modelState.init(() => model),
|
|
2777
|
+
automerge3({
|
|
2778
|
+
handle: doc.handle,
|
|
2779
|
+
path: doc.path
|
|
2780
|
+
}),
|
|
2781
|
+
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2782
|
+
awareness()
|
|
2783
|
+
].filter(isNotNullOrUndefined),
|
|
2784
|
+
peer: identity ? {
|
|
2785
|
+
id: identity.identityKey.toHex(),
|
|
2786
|
+
name: identity.profile?.displayName
|
|
2787
|
+
} : void 0
|
|
2788
|
+
};
|
|
2789
|
+
return model;
|
|
2790
|
+
};
|
|
2748
2791
|
|
|
2749
2792
|
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2750
2793
|
import * as decoding from "lib0/decoding";
|
|
@@ -2757,7 +2800,7 @@ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src
|
|
|
2757
2800
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2758
2801
|
invariant4(text?.doc && text?.content, void 0, {
|
|
2759
2802
|
F: __dxlog_file5,
|
|
2760
|
-
L:
|
|
2803
|
+
L: 22,
|
|
2761
2804
|
S: void 0,
|
|
2762
2805
|
A: [
|
|
2763
2806
|
"text?.doc && text?.content",
|
|
@@ -2822,7 +2865,7 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2822
2865
|
origin
|
|
2823
2866
|
}, {
|
|
2824
2867
|
F: __dxlog_file5,
|
|
2825
|
-
L:
|
|
2868
|
+
L: 101,
|
|
2826
2869
|
S: this,
|
|
2827
2870
|
C: (f, a) => f(...a)
|
|
2828
2871
|
});
|
|
@@ -2835,7 +2878,7 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2835
2878
|
_handleSpaceMessage({ payload }) {
|
|
2836
2879
|
log3("space message", payload, {
|
|
2837
2880
|
F: __dxlog_file5,
|
|
2838
|
-
L:
|
|
2881
|
+
L: 110,
|
|
2839
2882
|
S: this,
|
|
2840
2883
|
C: (f, a) => f(...a)
|
|
2841
2884
|
});
|
|
@@ -2879,10 +2922,8 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2879
2922
|
};
|
|
2880
2923
|
|
|
2881
2924
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
update: (model) => model
|
|
2885
|
-
});
|
|
2925
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2926
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2886
2927
|
var useTextModel = (props) => {
|
|
2887
2928
|
const { identity, space, text } = props;
|
|
2888
2929
|
const [model, setModel] = useState2();
|
|
@@ -2903,44 +2944,6 @@ var createModel = (props) => {
|
|
|
2903
2944
|
return void 0;
|
|
2904
2945
|
}
|
|
2905
2946
|
};
|
|
2906
|
-
|
|
2907
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2908
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2909
|
-
const obj = text;
|
|
2910
|
-
const doc = getRawDoc(obj, [
|
|
2911
|
-
obj.field
|
|
2912
|
-
]);
|
|
2913
|
-
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2914
|
-
space,
|
|
2915
|
-
channel: `automerge.awareness.${obj.id}`,
|
|
2916
|
-
info: {
|
|
2917
|
-
displayName: identity?.profile?.displayName ?? "",
|
|
2918
|
-
color: cursorColor.color,
|
|
2919
|
-
lightColor: cursorColor.light
|
|
2920
|
-
},
|
|
2921
|
-
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2922
|
-
});
|
|
2923
|
-
const model = {
|
|
2924
|
-
id: obj.id,
|
|
2925
|
-
content: doc,
|
|
2926
|
-
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2927
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2928
|
-
extension: [
|
|
2929
|
-
modelState.init(() => model),
|
|
2930
|
-
automerge3({
|
|
2931
|
-
handle: doc.handle,
|
|
2932
|
-
path: doc.path
|
|
2933
|
-
}),
|
|
2934
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2935
|
-
awareness()
|
|
2936
|
-
].filter(isNotNullOrUndefined),
|
|
2937
|
-
peer: identity ? {
|
|
2938
|
-
id: identity.identityKey.toHex(),
|
|
2939
|
-
name: identity.profile?.displayName
|
|
2940
|
-
} : void 0
|
|
2941
|
-
};
|
|
2942
|
-
return model;
|
|
2943
|
-
};
|
|
2944
2947
|
export {
|
|
2945
2948
|
AwarenessProvider,
|
|
2946
2949
|
BaseTextEditor,
|
|
@@ -2984,14 +2987,17 @@ export {
|
|
|
2984
2987
|
mention,
|
|
2985
2988
|
modelState,
|
|
2986
2989
|
outliner,
|
|
2987
|
-
|
|
2990
|
+
setComments,
|
|
2988
2991
|
setFocus,
|
|
2989
2992
|
setSelection,
|
|
2993
|
+
syncFacet,
|
|
2990
2994
|
table,
|
|
2991
2995
|
tags2 as tags,
|
|
2992
2996
|
tasklist,
|
|
2993
2997
|
textTheme,
|
|
2994
2998
|
typewriter,
|
|
2999
|
+
useAwareness,
|
|
3000
|
+
useComments,
|
|
2995
3001
|
useTextModel,
|
|
2996
3002
|
yjs
|
|
2997
3003
|
};
|