@dxos/react-ui-editor 0.3.11-main.d56f337 → 0.3.11-main.da09c3c
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 +574 -493
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +13 -14
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +13 -6
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.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 +7 -9
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/index.d.ts +0 -1
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -12
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
- package/dist/types/src/extensions/awareness.d.ts +2 -0
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +4 -5
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/code.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +26 -17
- 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/hr.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/markdown/bundle.d.ts +2 -5
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/extensions/tasklist.d.ts +1 -5
- package/dist/types/src/extensions/tasklist.d.ts.map +1 -1
- 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 +2 -1
- 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/dist/types/src/util.d.ts +2 -0
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +30 -30
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +64 -69
- package/src/components/TextEditor/TextEditor.tsx +85 -68
- package/src/components/TextEditor/comments.stories.tsx +103 -75
- package/src/extensions/autocomplete.ts +6 -3
- package/src/extensions/automerge/automerge.ts +23 -48
- package/src/extensions/automerge/defs.ts +10 -31
- package/src/extensions/automerge/index.ts +0 -1
- package/src/extensions/automerge/semaphore.ts +23 -20
- package/src/extensions/automerge/update-automerge.ts +2 -2
- package/src/extensions/awareness.ts +20 -2
- package/src/extensions/basic.ts +22 -17
- package/src/extensions/code.ts +15 -17
- package/src/extensions/comments.ts +195 -157
- package/src/extensions/cursor.ts +7 -3
- package/src/extensions/hr.ts +49 -50
- package/src/extensions/index.ts +1 -0
- package/src/extensions/link.ts +3 -3
- package/src/extensions/markdown/bundle.ts +18 -24
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/extensions/tasklist.ts +49 -33
- package/src/hooks/automerge.ts +2 -1
- package/src/hooks/defs.ts +47 -0
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useTextModel.ts +2 -45
- package/src/hooks/yjs.ts +2 -1
- package/src/util.ts +26 -3
|
@@ -7,14 +7,14 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
7
7
|
|
|
8
8
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
9
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
-
import { EditorView as
|
|
10
|
+
import { EditorView as EditorView13 } 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,
|
|
15
|
-
import {
|
|
16
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useRef, useState } from "react";
|
|
15
|
+
import { log as log2 } from "@dxos/log";
|
|
16
|
+
import { useThemeContext as useThemeContext2 } from "@dxos/react-ui";
|
|
17
|
+
import { inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
18
|
|
|
19
19
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
@@ -29,9 +29,11 @@ var autocomplete = ({ onSearch }) => {
|
|
|
29
29
|
// https://codemirror.net/examples/autocompletion
|
|
30
30
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
31
31
|
autocompletion({
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
32
|
+
activateOnTyping: true,
|
|
33
|
+
// closeOnBlur: false,
|
|
34
|
+
// defaultKeymap: false,
|
|
35
|
+
// TODO(burdon): Styles/fragments.
|
|
36
|
+
tooltipClass: () => "shadow rounded"
|
|
35
37
|
}),
|
|
36
38
|
// TODO(burdon): Option to create new page?
|
|
37
39
|
// TODO(burdon): Optional decoration via addToOptions
|
|
@@ -51,8 +53,8 @@ var autocomplete = ({ onSearch }) => {
|
|
|
51
53
|
};
|
|
52
54
|
|
|
53
55
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
56
|
+
import { StateField } from "@codemirror/state";
|
|
57
|
+
import { EditorView } from "@codemirror/view";
|
|
56
58
|
import { next as A } from "@dxos/automerge/automerge";
|
|
57
59
|
|
|
58
60
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
@@ -94,12 +96,12 @@ var cursorConverter = (handle, path) => ({
|
|
|
94
96
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
95
97
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
96
98
|
var effectType = StateEffect.define({});
|
|
99
|
+
var reconcileAnnotationType = Annotation.define();
|
|
100
|
+
var getPath = (state, field) => state.field(field).path;
|
|
101
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
97
102
|
var updateHeads = (newHeads) => effectType.of({
|
|
98
103
|
newHeads
|
|
99
104
|
});
|
|
100
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
101
|
-
var getPath = (state, field) => state.field(field).path;
|
|
102
|
-
var reconcileAnnotationType = Annotation.define();
|
|
103
105
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
104
106
|
|
|
105
107
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
@@ -237,40 +239,42 @@ var charPath = (textPath, candidatePath) => {
|
|
|
237
239
|
|
|
238
240
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
239
241
|
var PatchSemaphore = class {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
+
// prettier-ignore
|
|
243
|
+
constructor(_handle, _state) {
|
|
244
|
+
this._handle = _handle;
|
|
245
|
+
this._state = _state;
|
|
242
246
|
this._inReconcile = false;
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
changes: inverted,
|
|
259
|
-
annotations: reconcileAnnotationType.of(true)
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
263
|
-
if (newHeads === null || newHeads === void 0) {
|
|
264
|
-
newHeads = automerge2.getHeads(handle.docSync());
|
|
265
|
-
}
|
|
266
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
|
|
267
|
-
updateCodeMirror(view, selection, path, diff);
|
|
247
|
+
}
|
|
248
|
+
// NOTE: Cannot destruct view.state.
|
|
249
|
+
reconcile(view) {
|
|
250
|
+
if (this._inReconcile) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
this._inReconcile = true;
|
|
254
|
+
const path = getPath(view.state, this._state);
|
|
255
|
+
const oldHeads = getLastHeads(view.state, this._state);
|
|
256
|
+
let selection = view.state.selection;
|
|
257
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
258
|
+
const toInvert = transactions.slice().reverse();
|
|
259
|
+
for (const tx of toInvert) {
|
|
260
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
261
|
+
selection = selection.map(inverted);
|
|
268
262
|
view.dispatch({
|
|
269
|
-
|
|
270
|
-
annotations: reconcileAnnotationType.of(
|
|
263
|
+
changes: inverted,
|
|
264
|
+
annotations: reconcileAnnotationType.of(true)
|
|
271
265
|
});
|
|
272
|
-
|
|
273
|
-
|
|
266
|
+
}
|
|
267
|
+
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
268
|
+
if (newHeads === null || newHeads === void 0) {
|
|
269
|
+
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
270
|
+
}
|
|
271
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
272
|
+
updateCodeMirror(view, selection, path, diff);
|
|
273
|
+
view.dispatch({
|
|
274
|
+
effects: updateHeads(newHeads),
|
|
275
|
+
annotations: reconcileAnnotationType.of({})
|
|
276
|
+
});
|
|
277
|
+
this._inReconcile = false;
|
|
274
278
|
}
|
|
275
279
|
};
|
|
276
280
|
|
|
@@ -280,14 +284,15 @@ var defaultCursorConverter = {
|
|
|
280
284
|
toCursor: (position) => position.toString(),
|
|
281
285
|
fromCursor: (cursor) => parseInt(cursor)
|
|
282
286
|
};
|
|
283
|
-
var Cursor = class {
|
|
287
|
+
var Cursor = class _Cursor {
|
|
284
288
|
static {
|
|
285
289
|
this.converter = Facet.define({
|
|
286
290
|
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
287
291
|
});
|
|
288
292
|
}
|
|
289
293
|
static {
|
|
290
|
-
this.getCursorFromRange = (
|
|
294
|
+
this.getCursorFromRange = (state, range) => {
|
|
295
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
291
296
|
const from = cursorConverter3.toCursor(range.from);
|
|
292
297
|
const to = cursorConverter3.toCursor(range.to, -1);
|
|
293
298
|
return [
|
|
@@ -297,7 +302,8 @@ var Cursor = class {
|
|
|
297
302
|
};
|
|
298
303
|
}
|
|
299
304
|
static {
|
|
300
|
-
this.getRangeFromCursor = (
|
|
305
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
306
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
301
307
|
const parts = cursor.split(":");
|
|
302
308
|
const from = cursorConverter3.fromCursor(parts[0]);
|
|
303
309
|
const to = cursorConverter3.fromCursor(parts[1]);
|
|
@@ -310,21 +316,18 @@ var Cursor = class {
|
|
|
310
316
|
};
|
|
311
317
|
|
|
312
318
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
313
|
-
var semaphoreFacet = Facet2.define({
|
|
314
|
-
combine: (values) => values.at(-1)
|
|
315
|
-
});
|
|
316
319
|
var automerge3 = ({ handle, path }) => {
|
|
317
|
-
const
|
|
320
|
+
const state = StateField.define({
|
|
318
321
|
create: () => ({
|
|
322
|
+
path: path.slice(),
|
|
319
323
|
lastHeads: A.getHeads(handle.docSync()),
|
|
320
|
-
unreconciledTransactions: []
|
|
321
|
-
path: path.slice()
|
|
324
|
+
unreconciledTransactions: []
|
|
322
325
|
}),
|
|
323
326
|
update: (value, tr) => {
|
|
324
327
|
const result = {
|
|
328
|
+
path: path.slice(),
|
|
325
329
|
lastHeads: value.lastHeads,
|
|
326
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
327
|
-
path: path.slice()
|
|
330
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
328
331
|
};
|
|
329
332
|
let clearUnreconciled = false;
|
|
330
333
|
for (const effect of tr.effects) {
|
|
@@ -343,41 +346,27 @@ var automerge3 = ({ handle, path }) => {
|
|
|
343
346
|
return result;
|
|
344
347
|
}
|
|
345
348
|
});
|
|
346
|
-
const semaphore = new PatchSemaphore(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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(handle, this._view);
|
|
359
|
-
});
|
|
349
|
+
const semaphore = new PatchSemaphore(handle, state);
|
|
350
|
+
return [
|
|
351
|
+
Cursor.converter.of(cursorConverter(handle, path)),
|
|
352
|
+
EditorView.updateListener.of(({ view, changes }) => {
|
|
353
|
+
if (!changes.empty) {
|
|
354
|
+
semaphore.reconcile(view);
|
|
360
355
|
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
return {
|
|
367
|
-
extension: [
|
|
368
|
-
Cursor.converter.of(cursorConverter(handle, path)),
|
|
369
|
-
semaphoreFacet.of(semaphore),
|
|
370
|
-
stateField,
|
|
371
|
-
viewPlugin
|
|
372
|
-
]
|
|
373
|
-
};
|
|
356
|
+
}),
|
|
357
|
+
state
|
|
358
|
+
];
|
|
374
359
|
};
|
|
375
360
|
|
|
376
361
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
377
|
-
import { Annotation as Annotation2, Facet as
|
|
378
|
-
import { Decoration, EditorView
|
|
362
|
+
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
363
|
+
import { Decoration, EditorView as EditorView2, ViewPlugin, WidgetType } from "@codemirror/view";
|
|
364
|
+
import { useEffect } from "react";
|
|
379
365
|
import { Event } from "@dxos/async";
|
|
380
366
|
import { Context } from "@dxos/context";
|
|
367
|
+
import { generateName } from "@dxos/display-name";
|
|
368
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
369
|
+
import { getColorForValue } from "@dxos/react-ui-theme";
|
|
381
370
|
var dummyProvider = {
|
|
382
371
|
remoteStateChange: new Event(),
|
|
383
372
|
open: () => {
|
|
@@ -388,19 +377,42 @@ var dummyProvider = {
|
|
|
388
377
|
},
|
|
389
378
|
getRemoteStates: () => []
|
|
390
379
|
};
|
|
391
|
-
var AwarenessProvider =
|
|
380
|
+
var AwarenessProvider = Facet2.define({
|
|
392
381
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
393
382
|
});
|
|
394
383
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
395
384
|
var awareness = (provider = dummyProvider) => {
|
|
396
385
|
return [
|
|
397
386
|
AwarenessProvider.of(provider),
|
|
398
|
-
|
|
387
|
+
ViewPlugin.fromClass(RemoteSelectionsDecorator, {
|
|
399
388
|
decorations: (value) => value.decorations
|
|
400
389
|
}),
|
|
401
390
|
styles
|
|
402
391
|
];
|
|
403
392
|
};
|
|
393
|
+
var useAwareness = ({ awareness: awareness2, peer }) => {
|
|
394
|
+
const { themeMode } = useThemeContext();
|
|
395
|
+
useEffect(() => {
|
|
396
|
+
if (awareness2 && peer) {
|
|
397
|
+
awareness2.setLocalStateField("user", {
|
|
398
|
+
name: peer.name ?? generateName(peer.id),
|
|
399
|
+
color: getColorForValue({
|
|
400
|
+
value: peer.id,
|
|
401
|
+
type: "color"
|
|
402
|
+
}),
|
|
403
|
+
colorLight: getColorForValue({
|
|
404
|
+
value: peer.id,
|
|
405
|
+
themeMode,
|
|
406
|
+
type: "highlight"
|
|
407
|
+
})
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}, [
|
|
411
|
+
awareness2,
|
|
412
|
+
peer,
|
|
413
|
+
themeMode
|
|
414
|
+
]);
|
|
415
|
+
};
|
|
404
416
|
var RemoteSelectionsDecorator = class {
|
|
405
417
|
constructor(view) {
|
|
406
418
|
this.decorations = RangeSet.of([]);
|
|
@@ -549,7 +561,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
549
561
|
return true;
|
|
550
562
|
}
|
|
551
563
|
};
|
|
552
|
-
var styles =
|
|
564
|
+
var styles = EditorView2.baseTheme({
|
|
553
565
|
".cm-collab-selection": {},
|
|
554
566
|
".cm-collab-selectionLine": {
|
|
555
567
|
padding: 0,
|
|
@@ -595,7 +607,7 @@ var styles = EditorView.baseTheme({
|
|
|
595
607
|
zIndex: 101,
|
|
596
608
|
transition: "opacity .3s ease-in-out",
|
|
597
609
|
backgroundColor: "inherit",
|
|
598
|
-
//
|
|
610
|
+
// These should be separate.
|
|
599
611
|
opacity: 0,
|
|
600
612
|
transitionDelay: "0s",
|
|
601
613
|
whiteSpace: "nowrap"
|
|
@@ -608,23 +620,25 @@ var styles = EditorView.baseTheme({
|
|
|
608
620
|
|
|
609
621
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
610
622
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
623
|
+
import { history } from "@codemirror/commands";
|
|
611
624
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
612
625
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
613
|
-
import { drawSelection, EditorView as
|
|
614
|
-
var basicBundle = ({
|
|
615
|
-
|
|
616
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
626
|
+
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
627
|
+
var basicBundle = ({ themeMode, placeholder: _placeholder, multiline = true }) => [
|
|
628
|
+
multiline ? EditorView3.lineWrapping : [],
|
|
617
629
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
618
630
|
bracketMatching(),
|
|
619
631
|
closeBrackets(),
|
|
620
632
|
drawSelection(),
|
|
621
|
-
|
|
622
|
-
|
|
633
|
+
highlightActiveLine(),
|
|
634
|
+
history(),
|
|
635
|
+
_placeholder ? placeholder(_placeholder) : [],
|
|
636
|
+
// https://github.com/codemirror/theme-one-dark
|
|
623
637
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
624
|
-
]
|
|
638
|
+
];
|
|
625
639
|
|
|
626
640
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
627
|
-
import { EditorView as
|
|
641
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
628
642
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
629
643
|
import { invariant } from "@dxos/invariant";
|
|
630
644
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
@@ -672,7 +686,7 @@ var blast = (options = defaultOptions) => {
|
|
|
672
686
|
};
|
|
673
687
|
return [
|
|
674
688
|
// Cursor moved.
|
|
675
|
-
|
|
689
|
+
EditorView4.updateListener.of((update2) => {
|
|
676
690
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
677
691
|
if (blaster) {
|
|
678
692
|
blaster.destroy();
|
|
@@ -934,7 +948,7 @@ var random = (min, max) => {
|
|
|
934
948
|
};
|
|
935
949
|
|
|
936
950
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
937
|
-
import { ViewPlugin as
|
|
951
|
+
import { ViewPlugin as ViewPlugin2, EditorView as EditorView5, Decoration as Decoration2 } from "@codemirror/view";
|
|
938
952
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
939
953
|
|
|
940
954
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1025,7 +1039,7 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
|
|
|
1025
1039
|
|
|
1026
1040
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1027
1041
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1028
|
-
var styles2 =
|
|
1042
|
+
var styles2 = EditorView5.baseTheme({
|
|
1029
1043
|
"& .cm-codeblock": {
|
|
1030
1044
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1031
1045
|
},
|
|
@@ -1059,29 +1073,27 @@ var getLineRange = (lines, from, to) => {
|
|
|
1059
1073
|
];
|
|
1060
1074
|
};
|
|
1061
1075
|
var code2 = () => {
|
|
1062
|
-
const
|
|
1076
|
+
const buildDecorations5 = (view) => {
|
|
1063
1077
|
const decorations = [];
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}).range(block.from));
|
|
1075
|
-
}
|
|
1078
|
+
const text = view.state.doc.sliceString(0);
|
|
1079
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1080
|
+
const blocks = view.viewportLineBlocks;
|
|
1081
|
+
for (const match of matches) {
|
|
1082
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1083
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1084
|
+
const block = blocks[i];
|
|
1085
|
+
decorations.push(Decoration2.line({
|
|
1086
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1087
|
+
}).range(block.from));
|
|
1076
1088
|
}
|
|
1077
1089
|
}
|
|
1078
1090
|
return Decoration2.set(decorations);
|
|
1079
1091
|
};
|
|
1080
1092
|
return [
|
|
1081
|
-
|
|
1093
|
+
ViewPlugin2.fromClass(class {
|
|
1082
1094
|
constructor(view) {
|
|
1083
1095
|
this.hasFocus = false;
|
|
1084
|
-
this.decorations =
|
|
1096
|
+
this.decorations = buildDecorations5(view);
|
|
1085
1097
|
}
|
|
1086
1098
|
update(update2) {
|
|
1087
1099
|
if (
|
|
@@ -1089,7 +1101,7 @@ var code2 = () => {
|
|
|
1089
1101
|
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1090
1102
|
) {
|
|
1091
1103
|
this.hasFocus = update2.view.hasFocus;
|
|
1092
|
-
this.decorations =
|
|
1104
|
+
this.decorations = buildDecorations5(update2.view);
|
|
1093
1105
|
}
|
|
1094
1106
|
}
|
|
1095
1107
|
}, {
|
|
@@ -1101,11 +1113,11 @@ var code2 = () => {
|
|
|
1101
1113
|
|
|
1102
1114
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1103
1115
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1104
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as
|
|
1116
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
|
|
1105
1117
|
import sortBy from "lodash.sortby";
|
|
1118
|
+
import { useEffect as useEffect2 } from "react";
|
|
1106
1119
|
import { debounce } from "@dxos/async";
|
|
1107
1120
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1108
|
-
import { log as log2 } from "@dxos/log";
|
|
1109
1121
|
import { nonNullable } from "@dxos/util";
|
|
1110
1122
|
|
|
1111
1123
|
// packages/ui/react-ui-editor/src/util.ts
|
|
@@ -1114,19 +1126,38 @@ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src
|
|
|
1114
1126
|
var callbackWrapper = (fn) => (...args) => {
|
|
1115
1127
|
try {
|
|
1116
1128
|
return fn(...args);
|
|
1117
|
-
} catch (
|
|
1118
|
-
log.catch(
|
|
1129
|
+
} catch (err) {
|
|
1130
|
+
log.catch(err, void 0, {
|
|
1119
1131
|
F: __dxlog_file2,
|
|
1120
|
-
L:
|
|
1132
|
+
L: 18,
|
|
1121
1133
|
S: void 0,
|
|
1122
1134
|
C: (f, a) => f(...a)
|
|
1123
1135
|
});
|
|
1124
1136
|
}
|
|
1125
1137
|
};
|
|
1138
|
+
var logChanges = (trs) => {
|
|
1139
|
+
const changes = trs.flatMap((tr) => {
|
|
1140
|
+
if (tr.changes.empty) {
|
|
1141
|
+
return void 0;
|
|
1142
|
+
}
|
|
1143
|
+
const changes2 = [];
|
|
1144
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1145
|
+
fromA,
|
|
1146
|
+
toA,
|
|
1147
|
+
fromB,
|
|
1148
|
+
toB,
|
|
1149
|
+
inserted: inserted.toString()
|
|
1150
|
+
})));
|
|
1151
|
+
return changes2;
|
|
1152
|
+
}).filter(Boolean);
|
|
1153
|
+
if (changes.length) {
|
|
1154
|
+
console.log("changes", changes);
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1126
1157
|
|
|
1127
1158
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1128
1159
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1129
|
-
var styles3 =
|
|
1160
|
+
var styles3 = EditorView6.baseTheme({
|
|
1130
1161
|
"& .cm-comment": {
|
|
1131
1162
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1132
1163
|
},
|
|
@@ -1142,49 +1173,59 @@ var marks = {
|
|
|
1142
1173
|
class: "cm-comment-active"
|
|
1143
1174
|
})
|
|
1144
1175
|
};
|
|
1145
|
-
var setFocus = (view,
|
|
1146
|
-
const
|
|
1147
|
-
if (!
|
|
1176
|
+
var setFocus = (view, id, center = true) => {
|
|
1177
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1178
|
+
if (!comment?.comment.cursor) {
|
|
1148
1179
|
return;
|
|
1149
1180
|
}
|
|
1150
|
-
view.
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1181
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1182
|
+
if (range) {
|
|
1183
|
+
view.dispatch({
|
|
1184
|
+
selection: {
|
|
1185
|
+
anchor: range.from
|
|
1186
|
+
},
|
|
1187
|
+
effects: [
|
|
1188
|
+
//
|
|
1189
|
+
EditorView6.scrollIntoView(range.from, center ? {
|
|
1190
|
+
y: "center"
|
|
1191
|
+
} : void 0),
|
|
1192
|
+
setSelection.of({
|
|
1193
|
+
active: id
|
|
1194
|
+
})
|
|
1195
|
+
]
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1159
1198
|
};
|
|
1160
|
-
var
|
|
1199
|
+
var setComments = StateEffect2.define();
|
|
1161
1200
|
var setSelection = StateEffect2.define();
|
|
1162
1201
|
var setCommentState = StateEffect2.define();
|
|
1163
|
-
var
|
|
1202
|
+
var commentsState = StateField2.define({
|
|
1164
1203
|
create: () => ({
|
|
1165
|
-
|
|
1204
|
+
comments: [],
|
|
1205
|
+
selection: {}
|
|
1166
1206
|
}),
|
|
1167
1207
|
update: (value, tr) => {
|
|
1168
|
-
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1169
1208
|
for (const effect of tr.effects) {
|
|
1170
1209
|
if (effect.is(setSelection)) {
|
|
1171
1210
|
return {
|
|
1172
1211
|
...value,
|
|
1173
|
-
|
|
1212
|
+
selection: effect.value
|
|
1174
1213
|
};
|
|
1175
1214
|
}
|
|
1176
|
-
if (effect.is(
|
|
1177
|
-
const
|
|
1178
|
-
|
|
1179
|
-
|
|
1215
|
+
if (effect.is(setComments)) {
|
|
1216
|
+
const comments2 = effect.value.map((comment) => {
|
|
1217
|
+
if (!comment.cursor) {
|
|
1218
|
+
return void 0;
|
|
1219
|
+
}
|
|
1220
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1180
1221
|
return range && {
|
|
1181
|
-
|
|
1182
|
-
|
|
1222
|
+
comment,
|
|
1223
|
+
range
|
|
1183
1224
|
};
|
|
1184
1225
|
}).filter(nonNullable);
|
|
1185
1226
|
return {
|
|
1186
1227
|
...value,
|
|
1187
|
-
|
|
1228
|
+
comments: comments2
|
|
1188
1229
|
};
|
|
1189
1230
|
}
|
|
1190
1231
|
if (effect.is(setCommentState)) {
|
|
@@ -1194,72 +1235,70 @@ var commentsStateField = StateField2.define({
|
|
|
1194
1235
|
return value;
|
|
1195
1236
|
}
|
|
1196
1237
|
});
|
|
1197
|
-
var highlightDecorations =
|
|
1198
|
-
|
|
1238
|
+
var highlightDecorations = EditorView6.decorations.compute([
|
|
1239
|
+
commentsState
|
|
1199
1240
|
], (state) => {
|
|
1200
|
-
const { active,
|
|
1201
|
-
const decorations = sortBy(
|
|
1202
|
-
|
|
1241
|
+
const { selection: { active }, comments: comments2 } = state.field(commentsState);
|
|
1242
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1243
|
+
const range = comment.range;
|
|
1244
|
+
if (!range || range.from === range.to) {
|
|
1245
|
+
console.warn("Invalid range:", range);
|
|
1203
1246
|
return void 0;
|
|
1204
1247
|
}
|
|
1205
|
-
|
|
1206
|
-
from: selection.from,
|
|
1207
|
-
to: selection.to
|
|
1208
|
-
};
|
|
1209
|
-
if (selection.id === active) {
|
|
1248
|
+
if (comment.comment.id === active) {
|
|
1210
1249
|
return marks.highlightActive.range(range.from, range.to);
|
|
1211
1250
|
} else {
|
|
1212
1251
|
return marks.highlight.range(range.from, range.to);
|
|
1213
1252
|
}
|
|
1214
|
-
}).filter(nonNullable)
|
|
1253
|
+
}).filter(nonNullable);
|
|
1215
1254
|
return Decoration3.set(decorations);
|
|
1216
1255
|
});
|
|
1217
|
-
var trackPastedComments = (
|
|
1256
|
+
var trackPastedComments = (onUpdate) => {
|
|
1218
1257
|
let tracked = null;
|
|
1219
|
-
const
|
|
1220
|
-
const comments2 = view.state.field(
|
|
1258
|
+
const handleTrack = (event, view) => {
|
|
1259
|
+
const comments2 = view.state.field(commentsState);
|
|
1221
1260
|
const { main } = view.state.selection;
|
|
1222
|
-
const
|
|
1223
|
-
if (!
|
|
1261
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1262
|
+
if (!selectedRanges.length) {
|
|
1224
1263
|
tracked = null;
|
|
1225
1264
|
} else {
|
|
1226
1265
|
tracked = {
|
|
1227
1266
|
text: view.state.doc.slice(main.from, main.to),
|
|
1228
|
-
comments:
|
|
1267
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1268
|
+
id: comment.id,
|
|
1229
1269
|
from: range.from - main.from,
|
|
1230
|
-
to: range.to - main.from
|
|
1231
|
-
id: range.id
|
|
1270
|
+
to: range.to - main.from
|
|
1232
1271
|
}))
|
|
1233
1272
|
};
|
|
1234
1273
|
}
|
|
1235
1274
|
};
|
|
1236
1275
|
return [
|
|
1237
|
-
|
|
1238
|
-
cut:
|
|
1239
|
-
copy:
|
|
1276
|
+
EditorView6.domEventHandlers({
|
|
1277
|
+
cut: handleTrack,
|
|
1278
|
+
copy: handleTrack
|
|
1240
1279
|
}),
|
|
1241
|
-
|
|
1280
|
+
// Handle paste.
|
|
1281
|
+
EditorView6.updateListener.of(({ view, state, transactions }) => {
|
|
1242
1282
|
if (tracked) {
|
|
1243
|
-
const paste =
|
|
1283
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1244
1284
|
if (paste) {
|
|
1245
1285
|
let found = -1;
|
|
1246
1286
|
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1247
1287
|
if (text.eq(tracked.text)) {
|
|
1248
|
-
for (let i =
|
|
1249
|
-
fromB =
|
|
1288
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1289
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1250
1290
|
}
|
|
1251
1291
|
found = fromB;
|
|
1252
1292
|
}
|
|
1253
1293
|
});
|
|
1254
1294
|
if (found > -1) {
|
|
1255
|
-
const active = update2.view.state.field(commentsStateField).ranges;
|
|
1256
1295
|
for (const moved of tracked.comments) {
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1296
|
+
const range = {
|
|
1297
|
+
from: found + moved.from,
|
|
1298
|
+
to: found + moved.to
|
|
1299
|
+
};
|
|
1300
|
+
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1301
|
+
onUpdate(moved.id, cursor);
|
|
1263
1302
|
}
|
|
1264
1303
|
}
|
|
1265
1304
|
tracked = null;
|
|
@@ -1272,26 +1311,33 @@ var comments = (options = {}) => {
|
|
|
1272
1311
|
const { key: shortcut = "meta-'" } = options;
|
|
1273
1312
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1274
1313
|
const createCommentThread = (view) => {
|
|
1275
|
-
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1276
1314
|
invariant2(options.onCreate, void 0, {
|
|
1277
1315
|
F: __dxlog_file3,
|
|
1278
|
-
L:
|
|
1316
|
+
L: 259,
|
|
1279
1317
|
S: void 0,
|
|
1280
1318
|
A: [
|
|
1281
1319
|
"options.onCreate",
|
|
1282
1320
|
""
|
|
1283
1321
|
]
|
|
1284
1322
|
});
|
|
1285
|
-
const {
|
|
1323
|
+
const { from, to } = view.state.selection.main;
|
|
1286
1324
|
if (from === to) {
|
|
1287
1325
|
return false;
|
|
1288
1326
|
}
|
|
1289
|
-
|
|
1327
|
+
if (to === view.state.doc.length) {
|
|
1328
|
+
view.dispatch({
|
|
1329
|
+
changes: {
|
|
1330
|
+
from: to,
|
|
1331
|
+
insert: "\n"
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1290
1336
|
from,
|
|
1291
1337
|
to
|
|
1292
1338
|
});
|
|
1293
1339
|
if (cursor) {
|
|
1294
|
-
const id =
|
|
1340
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1295
1341
|
if (id) {
|
|
1296
1342
|
view.dispatch({
|
|
1297
1343
|
effects: setSelection.of({
|
|
@@ -1301,25 +1347,13 @@ var comments = (options = {}) => {
|
|
|
1301
1347
|
anchor: from
|
|
1302
1348
|
}
|
|
1303
1349
|
});
|
|
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
|
-
}
|
|
1316
1350
|
return true;
|
|
1317
1351
|
}
|
|
1318
1352
|
}
|
|
1319
1353
|
return false;
|
|
1320
1354
|
};
|
|
1321
1355
|
return [
|
|
1322
|
-
|
|
1356
|
+
commentsState,
|
|
1323
1357
|
highlightDecorations,
|
|
1324
1358
|
styles3,
|
|
1325
1359
|
//
|
|
@@ -1344,7 +1378,7 @@ var comments = (options = {}) => {
|
|
|
1344
1378
|
above: true,
|
|
1345
1379
|
create: () => {
|
|
1346
1380
|
const el = document.createElement("div");
|
|
1347
|
-
options.onHover
|
|
1381
|
+
options.onHover(el, shortcut);
|
|
1348
1382
|
return {
|
|
1349
1383
|
dom: el,
|
|
1350
1384
|
offset: {
|
|
@@ -1357,140 +1391,154 @@ var comments = (options = {}) => {
|
|
|
1357
1391
|
}
|
|
1358
1392
|
return null;
|
|
1359
1393
|
}, {
|
|
1360
|
-
|
|
1394
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1395
|
+
// hideOnChange: true,
|
|
1361
1396
|
hoverTime: 1e3
|
|
1362
1397
|
}) : [],
|
|
1363
1398
|
//
|
|
1364
|
-
//
|
|
1365
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1399
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1366
1400
|
//
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
{
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
if (
|
|
1375
|
-
|
|
1376
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
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
|
-
});
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
if (from <= range.to) {
|
|
1388
|
-
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1389
|
-
Object.assign(range, newRange);
|
|
1390
|
-
mod = true;
|
|
1401
|
+
EditorView6.updateListener.of(({ view, state, changes }) => {
|
|
1402
|
+
let mod = false;
|
|
1403
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1404
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1405
|
+
comments2.forEach(({ comment, range }) => {
|
|
1406
|
+
if (from2 === to2) {
|
|
1407
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1408
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1409
|
+
options.onDelete?.(comment.id);
|
|
1391
1410
|
}
|
|
1392
|
-
}
|
|
1411
|
+
}
|
|
1412
|
+
if (from <= range.to) {
|
|
1413
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1414
|
+
Object.assign(range, newRange);
|
|
1415
|
+
mod = true;
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
});
|
|
1419
|
+
if (mod) {
|
|
1420
|
+
view.dispatch({
|
|
1421
|
+
effects: setCommentState.of({
|
|
1422
|
+
comments: comments2,
|
|
1423
|
+
...value
|
|
1424
|
+
})
|
|
1393
1425
|
});
|
|
1394
|
-
if (mod) {
|
|
1395
|
-
view.dispatch({
|
|
1396
|
-
effects: setCommentState.of({
|
|
1397
|
-
active,
|
|
1398
|
-
ranges
|
|
1399
|
-
})
|
|
1400
|
-
});
|
|
1401
|
-
}
|
|
1402
1426
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1427
|
+
}),
|
|
1428
|
+
//
|
|
1429
|
+
// Track selection/proximity.
|
|
1430
|
+
//
|
|
1431
|
+
EditorView6.updateListener.of(({ view, state, changes }) => {
|
|
1432
|
+
let min = Infinity;
|
|
1433
|
+
const { selection: { active, closest }, comments: comments2 } = state.field(commentsState);
|
|
1434
|
+
const { head } = state.selection.main;
|
|
1435
|
+
const selection = {};
|
|
1436
|
+
comments2.forEach(({ comment, range }) => {
|
|
1437
|
+
if (head >= range.from && head <= range.to) {
|
|
1438
|
+
selection.active = comment.id;
|
|
1439
|
+
selection.closest = void 0;
|
|
1440
|
+
}
|
|
1441
|
+
if (!selection.active) {
|
|
1442
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1416
1443
|
if (d < min) {
|
|
1417
|
-
|
|
1444
|
+
selection.closest = comment.id;
|
|
1418
1445
|
min = d;
|
|
1419
1446
|
}
|
|
1420
|
-
});
|
|
1421
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1422
|
-
view.dispatch({
|
|
1423
|
-
effects: setSelection.of(selected)
|
|
1424
|
-
});
|
|
1425
|
-
handleSelect({
|
|
1426
|
-
...selected,
|
|
1427
|
-
ranges: ranges.map((range) => ({
|
|
1428
|
-
...range,
|
|
1429
|
-
location: view.coordsAtPos(range.from)
|
|
1430
|
-
}))
|
|
1431
|
-
});
|
|
1432
1447
|
}
|
|
1448
|
+
});
|
|
1449
|
+
if (selection.active !== active || selection.closest !== closest) {
|
|
1450
|
+
view.dispatch({
|
|
1451
|
+
effects: setSelection.of(selection)
|
|
1452
|
+
});
|
|
1453
|
+
handleSelect({
|
|
1454
|
+
selection,
|
|
1455
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1456
|
+
comment,
|
|
1457
|
+
range,
|
|
1458
|
+
location: view.coordsAtPos(range.from)
|
|
1459
|
+
}))
|
|
1460
|
+
});
|
|
1433
1461
|
}
|
|
1434
1462
|
}),
|
|
1435
|
-
options.
|
|
1463
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1436
1464
|
];
|
|
1437
1465
|
};
|
|
1466
|
+
var useComments = (view, comments2) => {
|
|
1467
|
+
useEffect2(() => {
|
|
1468
|
+
if (view && comments2) {
|
|
1469
|
+
view.dispatch({
|
|
1470
|
+
effects: setComments.of(comments2)
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
}, [
|
|
1474
|
+
view,
|
|
1475
|
+
comments2
|
|
1476
|
+
]);
|
|
1477
|
+
};
|
|
1438
1478
|
|
|
1439
1479
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1440
|
-
import {
|
|
1441
|
-
|
|
1480
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1481
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1482
|
+
import { Decoration as Decoration4, EditorView as EditorView7, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1483
|
+
var styles4 = EditorView7.baseTheme({
|
|
1442
1484
|
"& .cm-hr": {
|
|
1443
|
-
// TODO(burdon): ???
|
|
1444
1485
|
// Note that block-level decorations should not have vertical margins,
|
|
1445
|
-
|
|
1486
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1446
1487
|
}
|
|
1447
1488
|
});
|
|
1448
1489
|
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1449
|
-
|
|
1450
|
-
super();
|
|
1451
|
-
this._pos = _pos;
|
|
1452
|
-
}
|
|
1453
|
-
eq(other) {
|
|
1454
|
-
return this._pos === other._pos;
|
|
1455
|
-
}
|
|
1456
|
-
toDOM(view) {
|
|
1490
|
+
toDOM() {
|
|
1457
1491
|
const el = document.createElement("div");
|
|
1458
1492
|
el.className = "cm-hr";
|
|
1459
1493
|
return el;
|
|
1460
1494
|
}
|
|
1461
1495
|
};
|
|
1462
|
-
var
|
|
1463
|
-
|
|
1464
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1466
|
-
})
|
|
1496
|
+
var decoration = Decoration4.replace({
|
|
1497
|
+
widget: new HorizontalRuleWidget()
|
|
1467
1498
|
});
|
|
1468
|
-
var
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1499
|
+
var buildDecorations = (view) => {
|
|
1500
|
+
const builder = new RangeSetBuilder();
|
|
1501
|
+
const { state } = view;
|
|
1502
|
+
const cursor = state.selection.main.head;
|
|
1503
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1504
|
+
syntaxTree(state).iterate({
|
|
1505
|
+
enter: (node) => {
|
|
1506
|
+
if (node.name === "HorizontalRule") {
|
|
1507
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1508
|
+
builder.add(node.from, node.to, decoration);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
},
|
|
1512
|
+
from,
|
|
1513
|
+
to
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
return builder.finish();
|
|
1517
|
+
};
|
|
1518
|
+
var hr = () => {
|
|
1519
|
+
return [
|
|
1520
|
+
styles4,
|
|
1521
|
+
ViewPlugin3.fromClass(class {
|
|
1522
|
+
constructor(view) {
|
|
1523
|
+
this.decorations = buildDecorations(view);
|
|
1524
|
+
}
|
|
1525
|
+
update(update2) {
|
|
1526
|
+
this.decorations = buildDecorations(update2.view);
|
|
1527
|
+
}
|
|
1528
|
+
}, {
|
|
1529
|
+
decorations: (v) => v.decorations
|
|
1482
1530
|
})
|
|
1483
|
-
|
|
1484
|
-
|
|
1531
|
+
];
|
|
1532
|
+
};
|
|
1485
1533
|
|
|
1486
1534
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1535
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1488
1536
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
1489
|
-
import { Decoration as Decoration5, EditorView as
|
|
1537
|
+
import { Decoration as Decoration5, EditorView as EditorView8, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1490
1538
|
var image = (options = {}) => {
|
|
1491
1539
|
return StateField3.define({
|
|
1492
1540
|
create: (state) => {
|
|
1493
|
-
return Decoration5.set(
|
|
1541
|
+
return Decoration5.set(buildDecorations2(0, state.doc.length, state));
|
|
1494
1542
|
},
|
|
1495
1543
|
update: (value, tr) => {
|
|
1496
1544
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -1510,16 +1558,16 @@ var image = (options = {}) => {
|
|
|
1510
1558
|
filterFrom: from,
|
|
1511
1559
|
filterTo: to,
|
|
1512
1560
|
filter: () => false,
|
|
1513
|
-
add:
|
|
1561
|
+
add: buildDecorations2(from, to, tr.state)
|
|
1514
1562
|
});
|
|
1515
1563
|
},
|
|
1516
|
-
provide: (field) =>
|
|
1564
|
+
provide: (field) => EditorView8.decorations.from(field)
|
|
1517
1565
|
});
|
|
1518
1566
|
};
|
|
1519
|
-
var
|
|
1567
|
+
var buildDecorations2 = (from, to, state) => {
|
|
1520
1568
|
const decorations = [];
|
|
1521
1569
|
const cursor = state.selection.main.head;
|
|
1522
|
-
|
|
1570
|
+
syntaxTree2(state).iterate({
|
|
1523
1571
|
enter: (node) => {
|
|
1524
1572
|
if (node.name === "Image") {
|
|
1525
1573
|
const urlNode = node.node.getChild("URL");
|
|
@@ -1556,19 +1604,19 @@ var ImageWidget = class extends WidgetType3 {
|
|
|
1556
1604
|
};
|
|
1557
1605
|
|
|
1558
1606
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1559
|
-
import { syntaxTree as
|
|
1560
|
-
import { RangeSetBuilder } from "@codemirror/state";
|
|
1561
|
-
import {
|
|
1607
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1608
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1609
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin4, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1562
1610
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1563
1611
|
var link = (options = {}) => {
|
|
1564
1612
|
const extensions = [
|
|
1565
|
-
|
|
1613
|
+
ViewPlugin4.fromClass(class {
|
|
1566
1614
|
constructor(view) {
|
|
1567
|
-
this.decorations =
|
|
1615
|
+
this.decorations = buildDecorations3(view, options);
|
|
1568
1616
|
}
|
|
1569
1617
|
update(update2) {
|
|
1570
1618
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1571
|
-
this.decorations =
|
|
1619
|
+
this.decorations = buildDecorations3(update2.view, options);
|
|
1572
1620
|
}
|
|
1573
1621
|
}
|
|
1574
1622
|
}, {
|
|
@@ -1581,7 +1629,7 @@ var link = (options = {}) => {
|
|
|
1581
1629
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1582
1630
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1583
1631
|
hoverTooltip2((view, pos, side) => {
|
|
1584
|
-
const syntax =
|
|
1632
|
+
const syntax = syntaxTree3(view.state).resolveInner(pos, side);
|
|
1585
1633
|
let link2 = null;
|
|
1586
1634
|
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1587
1635
|
link2 = node.name === "Link" ? node : null;
|
|
@@ -1657,12 +1705,12 @@ var LinkText = class extends WidgetType4 {
|
|
|
1657
1705
|
return link2;
|
|
1658
1706
|
}
|
|
1659
1707
|
};
|
|
1660
|
-
var
|
|
1661
|
-
const builder = new
|
|
1708
|
+
var buildDecorations3 = (view, options) => {
|
|
1709
|
+
const builder = new RangeSetBuilder2();
|
|
1662
1710
|
const { state } = view;
|
|
1663
1711
|
const cursor = state.selection.main.head;
|
|
1664
1712
|
for (const { from, to } of view.visibleRanges) {
|
|
1665
|
-
|
|
1713
|
+
syntaxTree3(state).iterate({
|
|
1666
1714
|
enter: (node) => {
|
|
1667
1715
|
if (node.name === "Link") {
|
|
1668
1716
|
const marks2 = node.node.getChildren("LinkMark");
|
|
@@ -1693,14 +1741,14 @@ var buildDecorations2 = (view, options) => {
|
|
|
1693
1741
|
};
|
|
1694
1742
|
|
|
1695
1743
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1696
|
-
import { EditorView as
|
|
1744
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1697
1745
|
var listener = ({ onFocus, onChange }) => {
|
|
1698
1746
|
const extensions = [];
|
|
1699
|
-
onFocus && extensions.push(
|
|
1747
|
+
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1700
1748
|
onFocus(focused);
|
|
1701
1749
|
return null;
|
|
1702
1750
|
}));
|
|
1703
|
-
onChange && extensions.push(
|
|
1751
|
+
onChange && extensions.push(EditorView9.updateListener.of((update2) => {
|
|
1704
1752
|
onChange(update2.state.doc.toString());
|
|
1705
1753
|
}));
|
|
1706
1754
|
return extensions;
|
|
@@ -1708,14 +1756,14 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1708
1756
|
|
|
1709
1757
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1710
1758
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1711
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1759
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1712
1760
|
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1713
1761
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1714
1762
|
import { languages } from "@codemirror/language-data";
|
|
1715
1763
|
import { searchKeymap } from "@codemirror/search";
|
|
1716
1764
|
import { EditorState } from "@codemirror/state";
|
|
1717
1765
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1718
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1766
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1719
1767
|
|
|
1720
1768
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1721
1769
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1910,17 +1958,17 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1910
1958
|
return [
|
|
1911
1959
|
EditorState.allowMultipleSelections.of(true),
|
|
1912
1960
|
EditorState.tabSize.of(2),
|
|
1913
|
-
|
|
1914
|
-
|
|
1961
|
+
EditorView10.lineWrapping,
|
|
1962
|
+
// https://github.com/codemirror/basic-setup
|
|
1915
1963
|
bracketMatching2(),
|
|
1916
1964
|
closeBrackets2(),
|
|
1917
1965
|
crosshairCursor(),
|
|
1918
1966
|
dropCursor(),
|
|
1919
1967
|
drawSelection2(),
|
|
1920
|
-
|
|
1921
|
-
|
|
1968
|
+
highlightActiveLine2(),
|
|
1969
|
+
history2(),
|
|
1922
1970
|
indentOnInput(),
|
|
1923
|
-
_placeholder
|
|
1971
|
+
_placeholder ? placeholder2(_placeholder) : [],
|
|
1924
1972
|
// Main extension.
|
|
1925
1973
|
// https://github.com/codemirror/lang-markdown
|
|
1926
1974
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1942,34 +1990,40 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1942
1990
|
// https://github.com/codemirror/theme-one-dark
|
|
1943
1991
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1944
1992
|
// Custom styles.
|
|
1945
|
-
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1993
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly)),
|
|
1994
|
+
keymap4.of([
|
|
1995
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1996
|
+
indentWithTab,
|
|
1997
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1998
|
+
...closeBracketsKeymap,
|
|
1999
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2000
|
+
...historyKeymap,
|
|
2001
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2002
|
+
...searchKeymap,
|
|
2003
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2004
|
+
...standardKeymap
|
|
2005
|
+
])
|
|
2006
|
+
];
|
|
2007
|
+
};
|
|
1960
2008
|
|
|
1961
2009
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1962
2010
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1963
2011
|
var mention = ({ onSearch }) => {
|
|
1964
2012
|
return autocompletion2({
|
|
2013
|
+
// TODO(burdon): Not working.
|
|
2014
|
+
activateOnTyping: true,
|
|
2015
|
+
// activateOnTypingDelay: 100,
|
|
2016
|
+
// selectOnOpen: true,
|
|
1965
2017
|
closeOnBlur: false,
|
|
2018
|
+
// defaultKeymap: false,
|
|
2019
|
+
icons: false,
|
|
1966
2020
|
override: [
|
|
1967
2021
|
(context) => {
|
|
2022
|
+
console.log(context);
|
|
1968
2023
|
const match = context.matchBefore(/@(\w+)?/);
|
|
1969
2024
|
if (!match || match.from === match.to && !context.explicit) {
|
|
1970
2025
|
return null;
|
|
1971
2026
|
}
|
|
1972
|
-
console.log(match);
|
|
1973
2027
|
return {
|
|
1974
2028
|
from: match.from,
|
|
1975
2029
|
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
@@ -1981,19 +2035,24 @@ var mention = ({ onSearch }) => {
|
|
|
1981
2035
|
});
|
|
1982
2036
|
};
|
|
1983
2037
|
|
|
2038
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2039
|
+
var outliner = (options = {}) => {
|
|
2040
|
+
return [];
|
|
2041
|
+
};
|
|
2042
|
+
|
|
1984
2043
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1985
|
-
import { syntaxTree as
|
|
1986
|
-
import { RangeSetBuilder as
|
|
1987
|
-
import { Decoration as Decoration7, EditorView as
|
|
2044
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2045
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField4 } from "@codemirror/state";
|
|
2046
|
+
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1988
2047
|
var table = (options = {}) => {
|
|
1989
2048
|
return StateField4.define({
|
|
1990
2049
|
create: (state) => update(state, options),
|
|
1991
2050
|
update: (_, tr) => update(tr.state, options),
|
|
1992
|
-
provide: (field) =>
|
|
2051
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
1993
2052
|
});
|
|
1994
2053
|
};
|
|
1995
2054
|
var update = (state, options) => {
|
|
1996
|
-
const builder = new
|
|
2055
|
+
const builder = new RangeSetBuilder3();
|
|
1997
2056
|
const cursor = state.selection.main.head;
|
|
1998
2057
|
const tables = [];
|
|
1999
2058
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2001,7 +2060,7 @@ var update = (state, options) => {
|
|
|
2001
2060
|
const table2 = getTable();
|
|
2002
2061
|
return table2.rows?.[table2.rows.length - 1];
|
|
2003
2062
|
};
|
|
2004
|
-
|
|
2063
|
+
syntaxTree4(state).iterate({
|
|
2005
2064
|
enter: (node) => {
|
|
2006
2065
|
switch (node.name) {
|
|
2007
2066
|
case "Table": {
|
|
@@ -2080,9 +2139,18 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2080
2139
|
};
|
|
2081
2140
|
|
|
2082
2141
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2083
|
-
import { syntaxTree as
|
|
2084
|
-
import { RangeSetBuilder as
|
|
2085
|
-
import { EditorView as
|
|
2142
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2143
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2144
|
+
import { EditorView as EditorView12, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
2145
|
+
var styles5 = EditorView12.baseTheme({
|
|
2146
|
+
"& .cm-task": {
|
|
2147
|
+
color: getToken("extend.colors.blue.500")
|
|
2148
|
+
},
|
|
2149
|
+
"& .cm-task-checkbox": {
|
|
2150
|
+
marginLeft: "4px",
|
|
2151
|
+
marginRight: "4px"
|
|
2152
|
+
}
|
|
2153
|
+
});
|
|
2086
2154
|
var CheckboxWidget = class extends WidgetType6 {
|
|
2087
2155
|
constructor(_checked) {
|
|
2088
2156
|
super();
|
|
@@ -2093,6 +2161,7 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2093
2161
|
}
|
|
2094
2162
|
toDOM(view) {
|
|
2095
2163
|
const input = document.createElement("input");
|
|
2164
|
+
input.className = "cm-task-checkbox";
|
|
2096
2165
|
input.type = "checkbox";
|
|
2097
2166
|
input.checked = this._checked;
|
|
2098
2167
|
if (view.state.readOnly) {
|
|
@@ -2119,39 +2188,27 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2119
2188
|
return false;
|
|
2120
2189
|
}
|
|
2121
2190
|
};
|
|
2122
|
-
var
|
|
2191
|
+
var checkedDecoration = Decoration8.replace({
|
|
2123
2192
|
widget: new CheckboxWidget(true)
|
|
2124
2193
|
});
|
|
2125
|
-
var
|
|
2194
|
+
var uncheckedDecoration = Decoration8.replace({
|
|
2126
2195
|
widget: new CheckboxWidget(false)
|
|
2127
2196
|
});
|
|
2128
|
-
var
|
|
2129
|
-
|
|
2130
|
-
constructor(view) {
|
|
2131
|
-
this.decorations = buildDecorations3(view);
|
|
2132
|
-
}
|
|
2133
|
-
update(update2) {
|
|
2134
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2135
|
-
this.decorations = buildDecorations3(update2.view);
|
|
2136
|
-
}
|
|
2137
|
-
}
|
|
2138
|
-
}, {
|
|
2139
|
-
decorations: (v) => v.decorations,
|
|
2140
|
-
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2141
|
-
return view.plugin(plugin)?.decorations || Decoration8.none;
|
|
2142
|
-
})
|
|
2143
|
-
});
|
|
2144
|
-
};
|
|
2145
|
-
var buildDecorations3 = (view) => {
|
|
2146
|
-
const builder = new RangeSetBuilder3();
|
|
2197
|
+
var buildDecorations4 = (view) => {
|
|
2198
|
+
const builder = new RangeSetBuilder4();
|
|
2147
2199
|
const { state } = view;
|
|
2148
2200
|
const cursor = state.selection.main.head;
|
|
2149
2201
|
for (const { from, to } of view.visibleRanges) {
|
|
2150
|
-
|
|
2202
|
+
syntaxTree5(state).iterate({
|
|
2151
2203
|
enter: (node) => {
|
|
2152
|
-
if (node.name === "TaskMarker"
|
|
2153
|
-
|
|
2154
|
-
|
|
2204
|
+
if (node.name === "TaskMarker") {
|
|
2205
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2206
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2207
|
+
builder.add(node.from - 2, node.from - 1, Decoration8.mark({
|
|
2208
|
+
class: "cm-task"
|
|
2209
|
+
}));
|
|
2210
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2211
|
+
}
|
|
2155
2212
|
}
|
|
2156
2213
|
},
|
|
2157
2214
|
from,
|
|
@@ -2160,6 +2217,23 @@ var buildDecorations3 = (view) => {
|
|
|
2160
2217
|
}
|
|
2161
2218
|
return builder.finish();
|
|
2162
2219
|
};
|
|
2220
|
+
var tasklist = (options = {}) => {
|
|
2221
|
+
return [
|
|
2222
|
+
ViewPlugin5.fromClass(class {
|
|
2223
|
+
constructor(view) {
|
|
2224
|
+
this.decorations = buildDecorations4(view);
|
|
2225
|
+
}
|
|
2226
|
+
update(update2) {
|
|
2227
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2228
|
+
this.decorations = buildDecorations4(update2.view);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
}, {
|
|
2232
|
+
decorations: (v) => v.decorations
|
|
2233
|
+
}),
|
|
2234
|
+
styles5
|
|
2235
|
+
];
|
|
2236
|
+
};
|
|
2163
2237
|
|
|
2164
2238
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2165
2239
|
import { keymap as keymap5 } from "@codemirror/view";
|
|
@@ -2476,90 +2550,84 @@ var codeTheme = {
|
|
|
2476
2550
|
};
|
|
2477
2551
|
|
|
2478
2552
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2553
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2479
2554
|
var EditorModes = [
|
|
2480
2555
|
"default",
|
|
2481
2556
|
"vim"
|
|
2482
2557
|
];
|
|
2483
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model,
|
|
2558
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [] }, forwardedRef) => {
|
|
2484
2559
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2485
2560
|
tabBehavior: "limited"
|
|
2486
2561
|
});
|
|
2487
|
-
const { themeMode } =
|
|
2562
|
+
const { themeMode } = useThemeContext2();
|
|
2488
2563
|
const rootRef = useRef(null);
|
|
2489
2564
|
const [view, setView] = useState(null);
|
|
2490
2565
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2491
2566
|
view
|
|
2492
2567
|
]);
|
|
2493
|
-
|
|
2494
|
-
if (
|
|
2495
|
-
view
|
|
2568
|
+
useEffect3(() => {
|
|
2569
|
+
if (autofocus) {
|
|
2570
|
+
view?.focus();
|
|
2496
2571
|
}
|
|
2497
2572
|
}, [
|
|
2498
2573
|
view,
|
|
2499
|
-
|
|
2574
|
+
autofocus
|
|
2500
2575
|
]);
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
if (awareness2 && peer) {
|
|
2504
|
-
awareness2.setLocalStateField("user", {
|
|
2505
|
-
name: peer.name ?? generateName(peer.id),
|
|
2506
|
-
color: getColorForValue({
|
|
2507
|
-
value: peer.id,
|
|
2508
|
-
type: "color"
|
|
2509
|
-
}),
|
|
2510
|
-
colorLight: getColorForValue({
|
|
2511
|
-
value: peer.id,
|
|
2512
|
-
themeMode,
|
|
2513
|
-
type: "highlight"
|
|
2514
|
-
})
|
|
2515
|
-
});
|
|
2516
|
-
}
|
|
2517
|
-
}, [
|
|
2518
|
-
awareness2,
|
|
2519
|
-
peer,
|
|
2520
|
-
themeMode
|
|
2521
|
-
]);
|
|
2522
|
-
useEffect(() => {
|
|
2523
|
-
if (view && comments2 !== void 0) {
|
|
2524
|
-
view.dispatch({
|
|
2525
|
-
effects: setCommentRange.of({
|
|
2526
|
-
model,
|
|
2527
|
-
comments: comments2
|
|
2528
|
-
})
|
|
2529
|
-
});
|
|
2530
|
-
}
|
|
2531
|
-
}, [
|
|
2532
|
-
view,
|
|
2533
|
-
comments2
|
|
2534
|
-
]);
|
|
2535
|
-
useEffect(() => {
|
|
2576
|
+
useAwareness(model);
|
|
2577
|
+
useEffect3(() => {
|
|
2536
2578
|
if (!model || !rootRef.current) {
|
|
2537
2579
|
return;
|
|
2538
2580
|
}
|
|
2539
2581
|
const state = EditorState2.create({
|
|
2540
2582
|
doc: model.text(),
|
|
2541
|
-
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2542
2583
|
selection,
|
|
2543
2584
|
extensions: [
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2585
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2586
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2587
|
+
log2.catch(err, void 0, {
|
|
2588
|
+
F: __dxlog_file4,
|
|
2589
|
+
L: 114,
|
|
2590
|
+
S: void 0,
|
|
2591
|
+
C: (f, a) => f(...a)
|
|
2592
|
+
});
|
|
2593
|
+
}),
|
|
2547
2594
|
// Theme.
|
|
2548
|
-
// TODO(burdon): Make
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2595
|
+
// TODO(burdon): Make configurable.
|
|
2596
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2597
|
+
EditorView13.theme(theme ?? {}),
|
|
2598
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2599
|
+
EditorView13.editorAttributes.of({
|
|
2600
|
+
class: slots.editor?.className ?? ""
|
|
2601
|
+
}),
|
|
2602
|
+
EditorView13.contentAttributes.of({
|
|
2603
|
+
class: slots.content?.className ?? ""
|
|
2604
|
+
}),
|
|
2605
|
+
// State.
|
|
2606
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2552
2607
|
// Storage and replication.
|
|
2608
|
+
// NOTE: This must come before user extensions.
|
|
2553
2609
|
model.extension,
|
|
2610
|
+
// TODO(burdon): Factor out (requires special handling for Escape/focus).
|
|
2611
|
+
editorMode === "vim" && vim(),
|
|
2554
2612
|
// Custom.
|
|
2555
2613
|
...extensions
|
|
2556
2614
|
].filter(Boolean)
|
|
2557
2615
|
});
|
|
2558
|
-
|
|
2559
|
-
|
|
2616
|
+
const newView = new EditorView13({
|
|
2617
|
+
state,
|
|
2560
2618
|
parent: rootRef.current,
|
|
2561
|
-
|
|
2619
|
+
scrollTo,
|
|
2620
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2621
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2622
|
+
dispatchTransactions: (trs, view2) => {
|
|
2623
|
+
view2.update(trs);
|
|
2624
|
+
const debug = false;
|
|
2625
|
+
if (debug) {
|
|
2626
|
+
logChanges(trs);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2562
2629
|
});
|
|
2630
|
+
view?.destroy();
|
|
2563
2631
|
setView(newView);
|
|
2564
2632
|
return () => {
|
|
2565
2633
|
newView?.destroy();
|
|
@@ -2575,8 +2643,14 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, read
|
|
|
2575
2643
|
const handleKeyUp = useCallback((event) => {
|
|
2576
2644
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2577
2645
|
switch (key) {
|
|
2646
|
+
case "Enter": {
|
|
2647
|
+
view?.focus();
|
|
2648
|
+
break;
|
|
2649
|
+
}
|
|
2578
2650
|
case "Escape": {
|
|
2579
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2651
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2652
|
+
rootRef.current?.focus();
|
|
2653
|
+
}
|
|
2580
2654
|
break;
|
|
2581
2655
|
}
|
|
2582
2656
|
}
|
|
@@ -2587,24 +2661,24 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, read
|
|
|
2587
2661
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2588
2662
|
key: model.id,
|
|
2589
2663
|
role: "none",
|
|
2590
|
-
ref: rootRef,
|
|
2591
2664
|
tabIndex: 0,
|
|
2592
2665
|
onKeyUp: handleKeyUp,
|
|
2593
2666
|
...slots.root,
|
|
2594
|
-
...editorMode !== "vim" && tabsterDOMAttribute
|
|
2667
|
+
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2668
|
+
ref: rootRef
|
|
2595
2669
|
});
|
|
2596
2670
|
});
|
|
2597
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2598
|
-
const { themeMode } =
|
|
2671
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, multiline, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2672
|
+
const { themeMode } = useThemeContext2();
|
|
2599
2673
|
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2600
2674
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2601
2675
|
ref: forwardedRef,
|
|
2602
2676
|
readonly,
|
|
2603
2677
|
extensions: [
|
|
2604
2678
|
basicBundle({
|
|
2605
|
-
readonly,
|
|
2606
2679
|
themeMode,
|
|
2607
|
-
placeholder: placeholder3
|
|
2680
|
+
placeholder: placeholder3,
|
|
2681
|
+
multiline
|
|
2608
2682
|
}),
|
|
2609
2683
|
...extensions
|
|
2610
2684
|
],
|
|
@@ -2613,16 +2687,16 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2613
2687
|
...props
|
|
2614
2688
|
});
|
|
2615
2689
|
});
|
|
2616
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2617
|
-
const { themeMode } =
|
|
2690
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2691
|
+
const { themeMode } = useThemeContext2();
|
|
2618
2692
|
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2619
2693
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2620
2694
|
ref: forwardedRef,
|
|
2621
2695
|
readonly,
|
|
2622
2696
|
extensions: [
|
|
2623
2697
|
markdownBundle({
|
|
2624
|
-
readonly,
|
|
2625
2698
|
themeMode,
|
|
2699
|
+
readonly,
|
|
2626
2700
|
placeholder: placeholder3
|
|
2627
2701
|
}),
|
|
2628
2702
|
...extensions
|
|
@@ -2634,7 +2708,11 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2634
2708
|
});
|
|
2635
2709
|
var defaultSlots = {
|
|
2636
2710
|
root: {
|
|
2637
|
-
|
|
2711
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
2712
|
+
className: mx3("flex flex-col grow overflow-y-auto", inputSurface)
|
|
2713
|
+
},
|
|
2714
|
+
editor: {
|
|
2715
|
+
className: "h-full p-2"
|
|
2638
2716
|
}
|
|
2639
2717
|
};
|
|
2640
2718
|
var defaultTextSlots = {
|
|
@@ -2654,7 +2732,7 @@ import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
|
2654
2732
|
import { Context as Context2 } from "@dxos/context";
|
|
2655
2733
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2656
2734
|
import { log as log3 } from "@dxos/log";
|
|
2657
|
-
var
|
|
2735
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2658
2736
|
var DEBOUNCE_INTERVAL = 100;
|
|
2659
2737
|
var SpaceAwarenessProvider = class {
|
|
2660
2738
|
constructor(params) {
|
|
@@ -2695,7 +2773,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2695
2773
|
log3.debug("failed to query awareness", {
|
|
2696
2774
|
err
|
|
2697
2775
|
}, {
|
|
2698
|
-
F:
|
|
2776
|
+
F: __dxlog_file5,
|
|
2699
2777
|
L: 85,
|
|
2700
2778
|
S: this,
|
|
2701
2779
|
C: (f, a) => f(...a)
|
|
@@ -2709,7 +2787,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2709
2787
|
}
|
|
2710
2788
|
update(position) {
|
|
2711
2789
|
invariant3(this._postTask, void 0, {
|
|
2712
|
-
F:
|
|
2790
|
+
F: __dxlog_file5,
|
|
2713
2791
|
L: 96,
|
|
2714
2792
|
S: this,
|
|
2715
2793
|
A: [
|
|
@@ -2729,7 +2807,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2729
2807
|
}
|
|
2730
2808
|
_handleQueryMessage() {
|
|
2731
2809
|
invariant3(this._postTask, void 0, {
|
|
2732
|
-
F:
|
|
2810
|
+
F: __dxlog_file5,
|
|
2733
2811
|
L: 111,
|
|
2734
2812
|
S: this,
|
|
2735
2813
|
A: [
|
|
@@ -2741,7 +2819,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2741
2819
|
}
|
|
2742
2820
|
_handlePostMessage(message) {
|
|
2743
2821
|
invariant3(message.kind === "post", void 0, {
|
|
2744
|
-
F:
|
|
2822
|
+
F: __dxlog_file5,
|
|
2745
2823
|
L: 116,
|
|
2746
2824
|
S: this,
|
|
2747
2825
|
A: [
|
|
@@ -2754,10 +2832,50 @@ var SpaceAwarenessProvider = class {
|
|
|
2754
2832
|
}
|
|
2755
2833
|
};
|
|
2756
2834
|
|
|
2757
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2835
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2758
2836
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2759
|
-
|
|
2760
|
-
|
|
2837
|
+
var modelState = StateField5.define({
|
|
2838
|
+
create: () => void 0,
|
|
2839
|
+
update: (model) => model
|
|
2840
|
+
});
|
|
2841
|
+
|
|
2842
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2843
|
+
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2844
|
+
const obj = text;
|
|
2845
|
+
const doc = getRawDoc(obj, [
|
|
2846
|
+
obj.field
|
|
2847
|
+
]);
|
|
2848
|
+
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2849
|
+
space,
|
|
2850
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
2851
|
+
info: {
|
|
2852
|
+
displayName: identity?.profile?.displayName ?? "",
|
|
2853
|
+
color: cursorColor.color,
|
|
2854
|
+
lightColor: cursorColor.light
|
|
2855
|
+
},
|
|
2856
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2857
|
+
});
|
|
2858
|
+
const model = {
|
|
2859
|
+
id: obj.id,
|
|
2860
|
+
content: doc,
|
|
2861
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2862
|
+
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2863
|
+
extension: [
|
|
2864
|
+
modelState.init(() => model),
|
|
2865
|
+
automerge3({
|
|
2866
|
+
handle: doc.handle,
|
|
2867
|
+
path: doc.path
|
|
2868
|
+
}),
|
|
2869
|
+
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2870
|
+
awareness()
|
|
2871
|
+
].filter(isNotNullOrUndefined),
|
|
2872
|
+
peer: identity ? {
|
|
2873
|
+
id: identity.identityKey.toHex(),
|
|
2874
|
+
name: identity.profile?.displayName
|
|
2875
|
+
} : void 0
|
|
2876
|
+
};
|
|
2877
|
+
return model;
|
|
2878
|
+
};
|
|
2761
2879
|
|
|
2762
2880
|
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2763
2881
|
import * as decoding from "lib0/decoding";
|
|
@@ -2766,11 +2884,11 @@ import { Observable } from "lib0/observable";
|
|
|
2766
2884
|
import * as YP from "y-protocols/awareness";
|
|
2767
2885
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2768
2886
|
import { log as log4 } from "@dxos/log";
|
|
2769
|
-
var
|
|
2887
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2770
2888
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2771
2889
|
invariant4(text?.doc && text?.content, void 0, {
|
|
2772
|
-
F:
|
|
2773
|
-
L:
|
|
2890
|
+
F: __dxlog_file6,
|
|
2891
|
+
L: 22,
|
|
2774
2892
|
S: void 0,
|
|
2775
2893
|
A: [
|
|
2776
2894
|
"text?.doc && text?.content",
|
|
@@ -2834,8 +2952,8 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2834
2952
|
removed,
|
|
2835
2953
|
origin
|
|
2836
2954
|
}, {
|
|
2837
|
-
F:
|
|
2838
|
-
L:
|
|
2955
|
+
F: __dxlog_file6,
|
|
2956
|
+
L: 101,
|
|
2839
2957
|
S: this,
|
|
2840
2958
|
C: (f, a) => f(...a)
|
|
2841
2959
|
});
|
|
@@ -2847,8 +2965,8 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2847
2965
|
}
|
|
2848
2966
|
_handleSpaceMessage({ payload }) {
|
|
2849
2967
|
log4("space message", payload, {
|
|
2850
|
-
F:
|
|
2851
|
-
L:
|
|
2968
|
+
F: __dxlog_file6,
|
|
2969
|
+
L: 110,
|
|
2852
2970
|
S: this,
|
|
2853
2971
|
C: (f, a) => f(...a)
|
|
2854
2972
|
});
|
|
@@ -2892,14 +3010,12 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2892
3010
|
};
|
|
2893
3011
|
|
|
2894
3012
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
update: (model) => model
|
|
2898
|
-
});
|
|
3013
|
+
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
3014
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2899
3015
|
var useTextModel = (props) => {
|
|
2900
3016
|
const { identity, space, text } = props;
|
|
2901
3017
|
const [model, setModel] = useState2();
|
|
2902
|
-
|
|
3018
|
+
useEffect4(() => setModel(createModel(props)), [
|
|
2903
3019
|
identity,
|
|
2904
3020
|
space,
|
|
2905
3021
|
text
|
|
@@ -2916,44 +3032,6 @@ var createModel = (props) => {
|
|
|
2916
3032
|
return void 0;
|
|
2917
3033
|
}
|
|
2918
3034
|
};
|
|
2919
|
-
|
|
2920
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2921
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2922
|
-
const obj = text;
|
|
2923
|
-
const doc = getRawDoc(obj, [
|
|
2924
|
-
obj.field
|
|
2925
|
-
]);
|
|
2926
|
-
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2927
|
-
space,
|
|
2928
|
-
channel: `automerge.awareness.${obj.id}`,
|
|
2929
|
-
info: {
|
|
2930
|
-
displayName: identity?.profile?.displayName ?? "",
|
|
2931
|
-
color: cursorColor.color,
|
|
2932
|
-
lightColor: cursorColor.light
|
|
2933
|
-
},
|
|
2934
|
-
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2935
|
-
});
|
|
2936
|
-
const model = {
|
|
2937
|
-
id: obj.id,
|
|
2938
|
-
content: doc,
|
|
2939
|
-
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2940
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2941
|
-
extension: [
|
|
2942
|
-
modelState.init(() => model),
|
|
2943
|
-
automerge3({
|
|
2944
|
-
handle: doc.handle,
|
|
2945
|
-
path: doc.path
|
|
2946
|
-
}),
|
|
2947
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2948
|
-
awareness()
|
|
2949
|
-
].filter(isNotNullOrUndefined),
|
|
2950
|
-
peer: identity ? {
|
|
2951
|
-
id: identity.identityKey.toHex(),
|
|
2952
|
-
name: identity.profile?.displayName
|
|
2953
|
-
} : void 0
|
|
2954
|
-
};
|
|
2955
|
-
return model;
|
|
2956
|
-
};
|
|
2957
3035
|
export {
|
|
2958
3036
|
AwarenessProvider,
|
|
2959
3037
|
BaseTextEditor,
|
|
@@ -2979,7 +3057,6 @@ export {
|
|
|
2979
3057
|
comments,
|
|
2980
3058
|
createAutomergeModel,
|
|
2981
3059
|
createYjsModel,
|
|
2982
|
-
cursorConverter,
|
|
2983
3060
|
defaultMarkdownSlots,
|
|
2984
3061
|
defaultOptions,
|
|
2985
3062
|
defaultSlots,
|
|
@@ -2990,6 +3067,7 @@ export {
|
|
|
2990
3067
|
image,
|
|
2991
3068
|
link,
|
|
2992
3069
|
listener,
|
|
3070
|
+
logChanges,
|
|
2993
3071
|
markdownBundle,
|
|
2994
3072
|
markdownHighlightStyle,
|
|
2995
3073
|
markdownTags,
|
|
@@ -2997,7 +3075,8 @@ export {
|
|
|
2997
3075
|
markdownTheme,
|
|
2998
3076
|
mention,
|
|
2999
3077
|
modelState,
|
|
3000
|
-
|
|
3078
|
+
outliner,
|
|
3079
|
+
setComments,
|
|
3001
3080
|
setFocus,
|
|
3002
3081
|
setSelection,
|
|
3003
3082
|
table,
|
|
@@ -3005,6 +3084,8 @@ export {
|
|
|
3005
3084
|
tasklist,
|
|
3006
3085
|
textTheme,
|
|
3007
3086
|
typewriter,
|
|
3087
|
+
useAwareness,
|
|
3088
|
+
useComments,
|
|
3008
3089
|
useTextModel,
|
|
3009
3090
|
yjs
|
|
3010
3091
|
};
|