@dxos/react-ui-editor 0.3.11-main.c01834e → 0.3.11-main.c8e9429
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 +347 -448
- 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 +6 -2
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +12 -17
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +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/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +4 -4
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +4 -9
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/code.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +14 -5
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/{util → extensions}/cursor.d.ts +9 -1
- package/dist/types/src/extensions/cursor.d.ts.map +1 -0
- 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/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/tasklist.d.ts +5 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +1 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +0 -5
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/hooks/yjs.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +25 -24
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +19 -16
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +71 -67
- package/src/components/TextEditor/comments.stories.tsx +355 -0
- package/src/extensions/autocomplete.ts +18 -17
- package/src/extensions/automerge/automerge.ts +12 -14
- package/src/extensions/automerge/cursor.ts +2 -1
- package/src/extensions/automerge/defs.ts +13 -9
- package/src/extensions/automerge/semaphore.ts +10 -12
- package/src/extensions/awareness.ts +27 -33
- package/src/extensions/code.ts +24 -18
- package/src/extensions/comments.ts +128 -140
- package/src/extensions/cursor.ts +46 -0
- package/src/extensions/hr.ts +8 -9
- package/src/extensions/image.ts +2 -2
- package/src/extensions/index.ts +1 -0
- package/src/extensions/link.ts +7 -7
- package/src/extensions/markdown/highlight.ts +0 -8
- package/src/extensions/table.ts +2 -2
- package/src/extensions/tasklist.ts +54 -77
- package/src/extensions/yjs/cursor.ts +2 -1
- package/src/extensions/yjs/yjs.test.ts +1 -1
- package/src/extensions/yjs/yjs.ts +2 -2
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useTextModel.ts +4 -7
- package/src/hooks/yjs.ts +1 -23
- package/src/index.ts +2 -0
- package/src/styles/markdown.ts +0 -2
- package/src/themes/default.ts +17 -50
- package/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/index.d.ts +0 -3
- package/dist/types/src/util/index.d.ts.map +0 -1
- package/dist/types/src/util/util.d.ts.map +0 -1
- package/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- /package/dist/types/src/{util/util.d.ts → util.d.ts} +0 -0
- /package/src/{util/util.ts → util.ts} +0 -0
|
@@ -11,46 +11,47 @@ import { EditorView as EditorView12 } from "@codemirror/view";
|
|
|
11
11
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState, useRef } from "react";
|
|
15
15
|
import { generateName } from "@dxos/display-name";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
17
|
import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
18
|
|
|
19
19
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
21
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
21
22
|
import { keymap } from "@codemirror/view";
|
|
22
23
|
var autocomplete = ({ onSearch }) => {
|
|
23
24
|
return [
|
|
24
25
|
// https://codemirror.net/docs/ref/#view.keymap
|
|
25
26
|
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
|
27
|
+
// TODO(burdon): Set custom keymap.
|
|
26
28
|
keymap.of(completionKeymap),
|
|
27
29
|
// https://codemirror.net/examples/autocompletion
|
|
28
30
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
29
31
|
autocompletion({
|
|
30
|
-
|
|
31
|
-
// defaultKeymap: false,
|
|
32
|
+
defaultKeymap: false,
|
|
32
33
|
// Don't start unless key press.
|
|
33
|
-
activateOnTyping: false
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
from: match.from,
|
|
44
|
-
options: onSearch(match.text.toLowerCase())
|
|
45
|
-
};
|
|
34
|
+
activateOnTyping: false
|
|
35
|
+
}),
|
|
36
|
+
// TODO(burdon): Option to create new page?
|
|
37
|
+
// TODO(burdon): Optional decoration via addToOptions
|
|
38
|
+
markdownLanguage.data.of({
|
|
39
|
+
autocomplete: (context) => {
|
|
40
|
+
const match = context.matchBefore(/\w*/);
|
|
41
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
42
|
+
return null;
|
|
46
43
|
}
|
|
47
|
-
|
|
44
|
+
return {
|
|
45
|
+
from: match.from,
|
|
46
|
+
options: onSearch(match.text.toLowerCase())
|
|
47
|
+
};
|
|
48
|
+
}
|
|
48
49
|
})
|
|
49
50
|
];
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
53
|
-
import {
|
|
54
|
+
import { StateField } from "@codemirror/state";
|
|
54
55
|
import { ViewPlugin } from "@codemirror/view";
|
|
55
56
|
import { next as A } from "@dxos/automerge/automerge";
|
|
56
57
|
|
|
@@ -91,7 +92,7 @@ var cursorConverter = (handle, path) => ({
|
|
|
91
92
|
});
|
|
92
93
|
|
|
93
94
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
94
|
-
import { Annotation, StateEffect } from "@codemirror/state";
|
|
95
|
+
import { Annotation, StateEffect, Facet } from "@codemirror/state";
|
|
95
96
|
var effectType = StateEffect.define({});
|
|
96
97
|
var updateHeads = (newHeads) => effectType.of({
|
|
97
98
|
newHeads
|
|
@@ -100,6 +101,9 @@ var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
|
100
101
|
var getPath = (state, field) => state.field(field).path;
|
|
101
102
|
var reconcileAnnotationType = Annotation.define();
|
|
102
103
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
104
|
+
var semaphoreFacet = Facet.define({
|
|
105
|
+
combine: (values) => values.at(-1)
|
|
106
|
+
});
|
|
103
107
|
|
|
104
108
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
105
109
|
import { next as automerge2 } from "@dxos/automerge/automerge";
|
|
@@ -236,11 +240,11 @@ var charPath = (textPath, candidatePath) => {
|
|
|
236
240
|
|
|
237
241
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
238
242
|
var PatchSemaphore = class {
|
|
239
|
-
constructor(_field) {
|
|
243
|
+
constructor(_handle, _field) {
|
|
244
|
+
this._handle = _handle;
|
|
240
245
|
this._field = _field;
|
|
241
246
|
this._inReconcile = false;
|
|
242
|
-
this.
|
|
243
|
-
this.reconcile = (handle, view) => {
|
|
247
|
+
this.reconcile = (view) => {
|
|
244
248
|
if (this._inReconcile) {
|
|
245
249
|
return;
|
|
246
250
|
}
|
|
@@ -258,11 +262,11 @@ var PatchSemaphore = class {
|
|
|
258
262
|
annotations: reconcileAnnotationType.of(true)
|
|
259
263
|
});
|
|
260
264
|
}
|
|
261
|
-
let newHeads = updateAutomerge(this._field,
|
|
265
|
+
let newHeads = updateAutomerge(this._field, this._handle, transactions, view.state);
|
|
262
266
|
if (newHeads === null || newHeads === void 0) {
|
|
263
|
-
newHeads = automerge2.getHeads(
|
|
267
|
+
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
264
268
|
}
|
|
265
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(
|
|
269
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
266
270
|
updateCodeMirror(view, selection, path, diff);
|
|
267
271
|
view.dispatch({
|
|
268
272
|
effects: updateHeads(newHeads),
|
|
@@ -273,36 +277,42 @@ var PatchSemaphore = class {
|
|
|
273
277
|
}
|
|
274
278
|
};
|
|
275
279
|
|
|
276
|
-
// packages/ui/react-ui-editor/src/
|
|
277
|
-
import { Facet } from "@codemirror/state";
|
|
278
|
-
var
|
|
280
|
+
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
281
|
+
import { Facet as Facet2 } from "@codemirror/state";
|
|
282
|
+
var defaultCursorConverter = {
|
|
279
283
|
toCursor: (position) => position.toString(),
|
|
280
284
|
fromCursor: (cursor) => parseInt(cursor)
|
|
281
285
|
};
|
|
282
|
-
var
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
// packages/ui/react-ui-editor/src/util/util.ts
|
|
287
|
-
import { log } from "@dxos/log";
|
|
288
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
289
|
-
var callbackWrapper = (fn) => (...args) => {
|
|
290
|
-
try {
|
|
291
|
-
return fn(...args);
|
|
292
|
-
} catch (error) {
|
|
293
|
-
log.catch(error, void 0, {
|
|
294
|
-
F: __dxlog_file,
|
|
295
|
-
L: 16,
|
|
296
|
-
S: void 0,
|
|
297
|
-
C: (f, a) => f(...a)
|
|
286
|
+
var Cursor = class {
|
|
287
|
+
static {
|
|
288
|
+
this.converter = Facet2.define({
|
|
289
|
+
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
298
290
|
});
|
|
299
291
|
}
|
|
292
|
+
static {
|
|
293
|
+
this.getCursorFromRange = (cursorConverter3, range) => {
|
|
294
|
+
const from = cursorConverter3.toCursor(range.from);
|
|
295
|
+
const to = cursorConverter3.toCursor(range.to, -1);
|
|
296
|
+
return [
|
|
297
|
+
from,
|
|
298
|
+
to
|
|
299
|
+
].join(":");
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
static {
|
|
303
|
+
this.getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
304
|
+
const parts = cursor.split(":");
|
|
305
|
+
const from = cursorConverter3.fromCursor(parts[0]);
|
|
306
|
+
const to = cursorConverter3.fromCursor(parts[1]);
|
|
307
|
+
return from !== void 0 && to !== void 0 ? {
|
|
308
|
+
from,
|
|
309
|
+
to
|
|
310
|
+
} : void 0;
|
|
311
|
+
};
|
|
312
|
+
}
|
|
300
313
|
};
|
|
301
314
|
|
|
302
315
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
303
|
-
var semaphoreFacet = Facet2.define({
|
|
304
|
-
combine: (values) => values.at(-1)
|
|
305
|
-
});
|
|
306
316
|
var automerge3 = ({ handle, path }) => {
|
|
307
317
|
const stateField = StateField.define({
|
|
308
318
|
create: () => ({
|
|
@@ -333,19 +343,19 @@ var automerge3 = ({ handle, path }) => {
|
|
|
333
343
|
return result;
|
|
334
344
|
}
|
|
335
345
|
});
|
|
336
|
-
const semaphore = new PatchSemaphore(stateField);
|
|
337
|
-
const viewPlugin = ViewPlugin.fromClass(class
|
|
346
|
+
const semaphore = new PatchSemaphore(handle, stateField);
|
|
347
|
+
const viewPlugin = ViewPlugin.fromClass(class AutomergeViewPlugin {
|
|
338
348
|
constructor(_view) {
|
|
339
349
|
this._view = _view;
|
|
340
350
|
this._handleChange = () => {
|
|
341
|
-
this._view.state.facet(semaphoreFacet).reconcile(
|
|
351
|
+
this._view.state.facet(semaphoreFacet).reconcile(this._view);
|
|
342
352
|
};
|
|
343
353
|
handle.addListener("change", this._handleChange);
|
|
344
354
|
}
|
|
345
355
|
update(update2) {
|
|
346
356
|
if (update2.transactions.length > 0 && update2.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
347
357
|
queueMicrotask(() => {
|
|
348
|
-
this._view.state.facet(semaphoreFacet).reconcile(
|
|
358
|
+
this._view.state.facet(semaphoreFacet).reconcile(this._view);
|
|
349
359
|
});
|
|
350
360
|
}
|
|
351
361
|
}
|
|
@@ -355,7 +365,7 @@ var automerge3 = ({ handle, path }) => {
|
|
|
355
365
|
});
|
|
356
366
|
return {
|
|
357
367
|
extension: [
|
|
358
|
-
|
|
368
|
+
Cursor.converter.of(cursorConverter(handle, path)),
|
|
359
369
|
semaphoreFacet.of(semaphore),
|
|
360
370
|
stateField,
|
|
361
371
|
viewPlugin
|
|
@@ -397,7 +407,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
397
407
|
this._ctx = new Context();
|
|
398
408
|
this._lastAnchor = void 0;
|
|
399
409
|
this._lastHead = void 0;
|
|
400
|
-
this._cursorConverter = view.state.facet(
|
|
410
|
+
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
401
411
|
this._provider = view.state.facet(AwarenessProvider);
|
|
402
412
|
this._provider.open();
|
|
403
413
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
@@ -452,7 +462,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
452
462
|
attributes: {
|
|
453
463
|
style: `background-color: ${lightColor}`
|
|
454
464
|
},
|
|
455
|
-
class: "cm-
|
|
465
|
+
class: "cm-collab-selection"
|
|
456
466
|
})
|
|
457
467
|
});
|
|
458
468
|
} else {
|
|
@@ -463,7 +473,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
463
473
|
attributes: {
|
|
464
474
|
style: `background-color: ${color}`
|
|
465
475
|
},
|
|
466
|
-
class: "cm-
|
|
476
|
+
class: "cm-collab-selection"
|
|
467
477
|
})
|
|
468
478
|
});
|
|
469
479
|
decorations.push({
|
|
@@ -473,7 +483,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
473
483
|
attributes: {
|
|
474
484
|
style: `background-color: ${color}`
|
|
475
485
|
},
|
|
476
|
-
class: "cm-
|
|
486
|
+
class: "cm-collab-selection"
|
|
477
487
|
})
|
|
478
488
|
});
|
|
479
489
|
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
@@ -484,7 +494,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
484
494
|
value: Decoration.line({
|
|
485
495
|
attributes: {
|
|
486
496
|
style: `background-color: ${color}`,
|
|
487
|
-
class: "cm-
|
|
497
|
+
class: "cm-collab-selectionLine"
|
|
488
498
|
}
|
|
489
499
|
})
|
|
490
500
|
});
|
|
@@ -504,23 +514,21 @@ var RemoteSelectionsDecorator = class {
|
|
|
504
514
|
}
|
|
505
515
|
};
|
|
506
516
|
var RemoteCaretWidget = class extends WidgetType {
|
|
507
|
-
constructor(
|
|
517
|
+
constructor(_name, _color) {
|
|
508
518
|
super();
|
|
509
|
-
this.
|
|
510
|
-
this.
|
|
511
|
-
this.name = name;
|
|
512
|
-
this.color = color;
|
|
519
|
+
this._name = _name;
|
|
520
|
+
this._color = _color;
|
|
513
521
|
}
|
|
514
522
|
toDOM() {
|
|
515
523
|
const span = document.createElement("span");
|
|
516
|
-
span.className = "cm-
|
|
517
|
-
span.style.backgroundColor = this.
|
|
518
|
-
span.style.borderColor = this.
|
|
524
|
+
span.className = "cm-collab-selectionCaret";
|
|
525
|
+
span.style.backgroundColor = this._color;
|
|
526
|
+
span.style.borderColor = this._color;
|
|
519
527
|
const dot = document.createElement("div");
|
|
520
|
-
dot.className = "cm-
|
|
528
|
+
dot.className = "cm-collab-selectionCaretDot";
|
|
521
529
|
const info = document.createElement("div");
|
|
522
|
-
info.className = "cm-
|
|
523
|
-
info.innerText = this.
|
|
530
|
+
info.className = "cm-collab-selectionInfo";
|
|
531
|
+
info.innerText = this._name;
|
|
524
532
|
span.appendChild(document.createTextNode("\u2060"));
|
|
525
533
|
span.appendChild(dot);
|
|
526
534
|
span.appendChild(document.createTextNode("\u2060"));
|
|
@@ -528,15 +536,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
528
536
|
span.appendChild(document.createTextNode("\u2060"));
|
|
529
537
|
return span;
|
|
530
538
|
}
|
|
531
|
-
eq(widget) {
|
|
532
|
-
return widget.color === this.color;
|
|
533
|
-
}
|
|
534
|
-
compare(widget) {
|
|
535
|
-
return widget.color === this.color;
|
|
536
|
-
}
|
|
537
539
|
updateDOM() {
|
|
538
540
|
return false;
|
|
539
541
|
}
|
|
542
|
+
eq(widget) {
|
|
543
|
+
return widget._color === this._color;
|
|
544
|
+
}
|
|
540
545
|
get estimatedHeight() {
|
|
541
546
|
return -1;
|
|
542
547
|
}
|
|
@@ -545,12 +550,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
545
550
|
}
|
|
546
551
|
};
|
|
547
552
|
var styles = EditorView.baseTheme({
|
|
548
|
-
".cm-
|
|
549
|
-
".cm-
|
|
553
|
+
".cm-collab-selection": {},
|
|
554
|
+
".cm-collab-selectionLine": {
|
|
550
555
|
padding: 0,
|
|
551
556
|
margin: "0px 2px 0px 4px"
|
|
552
557
|
},
|
|
553
|
-
".cm-
|
|
558
|
+
".cm-collab-selectionCaret": {
|
|
554
559
|
position: "relative",
|
|
555
560
|
borderLeft: "1px solid black",
|
|
556
561
|
borderRight: "1px solid black",
|
|
@@ -559,7 +564,7 @@ var styles = EditorView.baseTheme({
|
|
|
559
564
|
boxSizing: "border-box",
|
|
560
565
|
display: "inline"
|
|
561
566
|
},
|
|
562
|
-
".cm-
|
|
567
|
+
".cm-collab-selectionCaretDot": {
|
|
563
568
|
borderRadius: "50%",
|
|
564
569
|
position: "absolute",
|
|
565
570
|
width: ".4em",
|
|
@@ -570,11 +575,11 @@ var styles = EditorView.baseTheme({
|
|
|
570
575
|
transition: "transform .3s ease-in-out",
|
|
571
576
|
boxSizing: "border-box"
|
|
572
577
|
},
|
|
573
|
-
".cm-
|
|
578
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
574
579
|
transformOrigin: "bottom center",
|
|
575
580
|
transform: "scale(0)"
|
|
576
581
|
},
|
|
577
|
-
".cm-
|
|
582
|
+
".cm-collab-selectionInfo": {
|
|
578
583
|
position: "absolute",
|
|
579
584
|
top: "-1.05em",
|
|
580
585
|
left: "-1px",
|
|
@@ -590,12 +595,12 @@ var styles = EditorView.baseTheme({
|
|
|
590
595
|
zIndex: 101,
|
|
591
596
|
transition: "opacity .3s ease-in-out",
|
|
592
597
|
backgroundColor: "inherit",
|
|
593
|
-
//
|
|
598
|
+
// These should be separate.
|
|
594
599
|
opacity: 0,
|
|
595
600
|
transitionDelay: "0s",
|
|
596
601
|
whiteSpace: "nowrap"
|
|
597
602
|
},
|
|
598
|
-
".cm-
|
|
603
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionInfo": {
|
|
599
604
|
opacity: 1,
|
|
600
605
|
transitionDelay: "0s"
|
|
601
606
|
}
|
|
@@ -622,7 +627,7 @@ var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
|
622
627
|
import { EditorView as EditorView3, keymap as keymap2 } from "@codemirror/view";
|
|
623
628
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
624
629
|
import { invariant } from "@dxos/invariant";
|
|
625
|
-
var
|
|
630
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
626
631
|
var defaultOptions = {
|
|
627
632
|
effect: 2,
|
|
628
633
|
maxParticles: 200,
|
|
@@ -749,7 +754,7 @@ var Blaster = class {
|
|
|
749
754
|
}
|
|
750
755
|
initialize() {
|
|
751
756
|
invariant(!this._canvas && !this._ctx, void 0, {
|
|
752
|
-
F:
|
|
757
|
+
F: __dxlog_file,
|
|
753
758
|
L: 138,
|
|
754
759
|
S: this,
|
|
755
760
|
A: [
|
|
@@ -786,7 +791,7 @@ var Blaster = class {
|
|
|
786
791
|
}
|
|
787
792
|
start() {
|
|
788
793
|
invariant(this._canvas && this._ctx, void 0, {
|
|
789
|
-
F:
|
|
794
|
+
F: __dxlog_file,
|
|
790
795
|
L: 177,
|
|
791
796
|
S: this,
|
|
792
797
|
A: [
|
|
@@ -1054,20 +1059,18 @@ var getLineRange = (lines, from, to) => {
|
|
|
1054
1059
|
];
|
|
1055
1060
|
};
|
|
1056
1061
|
var code2 = () => {
|
|
1057
|
-
const
|
|
1062
|
+
const buildDecorations4 = (view) => {
|
|
1058
1063
|
const decorations = [];
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
}).range(block.from));
|
|
1070
|
-
}
|
|
1064
|
+
const text = view.state.doc.sliceString(0);
|
|
1065
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1066
|
+
const blocks = view.viewportLineBlocks;
|
|
1067
|
+
for (const match of matches) {
|
|
1068
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1069
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1070
|
+
const block = blocks[i];
|
|
1071
|
+
decorations.push(Decoration2.line({
|
|
1072
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1073
|
+
}).range(block.from));
|
|
1071
1074
|
}
|
|
1072
1075
|
}
|
|
1073
1076
|
return Decoration2.set(decorations);
|
|
@@ -1075,11 +1078,16 @@ var code2 = () => {
|
|
|
1075
1078
|
return [
|
|
1076
1079
|
ViewPlugin3.fromClass(class {
|
|
1077
1080
|
constructor(view) {
|
|
1078
|
-
this.
|
|
1081
|
+
this.hasFocus = false;
|
|
1082
|
+
this.decorations = buildDecorations4(view);
|
|
1079
1083
|
}
|
|
1080
1084
|
update(update2) {
|
|
1081
|
-
if (
|
|
1082
|
-
|
|
1085
|
+
if (
|
|
1086
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1087
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1088
|
+
) {
|
|
1089
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1090
|
+
this.decorations = buildDecorations4(update2.view);
|
|
1083
1091
|
}
|
|
1084
1092
|
}
|
|
1085
1093
|
}, {
|
|
@@ -1091,23 +1099,31 @@ var code2 = () => {
|
|
|
1091
1099
|
|
|
1092
1100
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1093
1101
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1094
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5
|
|
1102
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
|
|
1095
1103
|
import sortBy from "lodash.sortby";
|
|
1096
1104
|
import { debounce } from "@dxos/async";
|
|
1097
1105
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1098
|
-
import { log as log2 } from "@dxos/log";
|
|
1099
1106
|
import { nonNullable } from "@dxos/util";
|
|
1107
|
+
|
|
1108
|
+
// packages/ui/react-ui-editor/src/util.ts
|
|
1109
|
+
import { log } from "@dxos/log";
|
|
1110
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1111
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
1112
|
+
try {
|
|
1113
|
+
return fn(...args);
|
|
1114
|
+
} catch (error) {
|
|
1115
|
+
log.catch(error, void 0, {
|
|
1116
|
+
F: __dxlog_file2,
|
|
1117
|
+
L: 16,
|
|
1118
|
+
S: void 0,
|
|
1119
|
+
C: (f, a) => f(...a)
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1124
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1100
1125
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1101
1126
|
var styles3 = EditorView5.baseTheme({
|
|
1102
|
-
"& .cm-bookmark": {
|
|
1103
|
-
cursor: "pointer",
|
|
1104
|
-
margin: "4px",
|
|
1105
|
-
padding: "4px",
|
|
1106
|
-
backgroundColor: "yellow"
|
|
1107
|
-
},
|
|
1108
|
-
"& .cm-bookmark-selected": {
|
|
1109
|
-
backgroundColor: "orange"
|
|
1110
|
-
},
|
|
1111
1127
|
"& .cm-comment": {
|
|
1112
1128
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1113
1129
|
},
|
|
@@ -1146,7 +1162,7 @@ var commentsStateField = StateField2.define({
|
|
|
1146
1162
|
ranges: []
|
|
1147
1163
|
}),
|
|
1148
1164
|
update: (value, tr) => {
|
|
1149
|
-
const cursorConverter3 = tr.state.facet(
|
|
1165
|
+
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1150
1166
|
for (const effect of tr.effects) {
|
|
1151
1167
|
if (effect.is(setSelection)) {
|
|
1152
1168
|
return {
|
|
@@ -1157,7 +1173,7 @@ var commentsStateField = StateField2.define({
|
|
|
1157
1173
|
if (effect.is(setCommentRange)) {
|
|
1158
1174
|
const { comments: comments2 } = effect.value;
|
|
1159
1175
|
const ranges = comments2.map((comment) => {
|
|
1160
|
-
const range = getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1176
|
+
const range = Cursor.getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1161
1177
|
return range && {
|
|
1162
1178
|
...comment,
|
|
1163
1179
|
...range
|
|
@@ -1195,58 +1211,89 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1195
1211
|
}).filter(nonNullable) ?? [];
|
|
1196
1212
|
return Decoration3.set(decorations);
|
|
1197
1213
|
});
|
|
1198
|
-
var
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
return this._anchor === other._anchor && this._id === other._id;
|
|
1216
|
-
}
|
|
1217
|
-
toDOM() {
|
|
1218
|
-
const span = document.createElement("span");
|
|
1219
|
-
span.className = "cm-bookmark";
|
|
1220
|
-
span.textContent = "\u203B";
|
|
1221
|
-
if (this._handleClick) {
|
|
1222
|
-
span.onclick = () => this._handleClick();
|
|
1214
|
+
var trackPastedComments = (onUpdate) => {
|
|
1215
|
+
let tracked = null;
|
|
1216
|
+
const handleTrack = (event, view) => {
|
|
1217
|
+
const comments2 = view.state.field(commentsStateField);
|
|
1218
|
+
const { main } = view.state.selection;
|
|
1219
|
+
const selectedRanges = comments2.ranges.filter((range) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1220
|
+
if (!selectedRanges.length) {
|
|
1221
|
+
tracked = null;
|
|
1222
|
+
} else {
|
|
1223
|
+
tracked = {
|
|
1224
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1225
|
+
comments: selectedRanges.map((range) => ({
|
|
1226
|
+
id: range.id,
|
|
1227
|
+
from: range.from - main.from,
|
|
1228
|
+
to: range.to - main.from
|
|
1229
|
+
}))
|
|
1230
|
+
};
|
|
1223
1231
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1232
|
+
};
|
|
1233
|
+
return [
|
|
1234
|
+
EditorView5.domEventHandlers({
|
|
1235
|
+
cut: handleTrack,
|
|
1236
|
+
copy: handleTrack
|
|
1237
|
+
}),
|
|
1238
|
+
// Handle paste.
|
|
1239
|
+
EditorView5.updateListener.of(({ view, state, transactions }) => {
|
|
1240
|
+
if (tracked) {
|
|
1241
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1242
|
+
if (paste) {
|
|
1243
|
+
let found = -1;
|
|
1244
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1245
|
+
if (text.eq(tracked.text)) {
|
|
1246
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1247
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1248
|
+
}
|
|
1249
|
+
found = fromB;
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
if (found > -1) {
|
|
1253
|
+
const comments2 = tracked.comments;
|
|
1254
|
+
view.state.facet(semaphoreFacet).reconcile(view);
|
|
1255
|
+
const active = state.field(commentsStateField).ranges;
|
|
1256
|
+
for (const moved of comments2) {
|
|
1257
|
+
if (active.some((range) => range.id === moved.id && range.from === range.to)) {
|
|
1258
|
+
const range = {
|
|
1259
|
+
from: found + moved.from,
|
|
1260
|
+
to: found + moved.to
|
|
1261
|
+
};
|
|
1262
|
+
const cursor = Cursor.getCursorFromRange(state.facet(Cursor.converter), range);
|
|
1263
|
+
onUpdate(moved.id, cursor);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
tracked = null;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
})
|
|
1271
|
+
];
|
|
1226
1272
|
};
|
|
1227
1273
|
var comments = (options = {}) => {
|
|
1274
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1228
1275
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
1276
|
const createCommentThread = (view) => {
|
|
1230
|
-
const cursorConverter3 = view.state.facet(
|
|
1277
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1231
1278
|
invariant2(options.onCreate, void 0, {
|
|
1232
1279
|
F: __dxlog_file3,
|
|
1233
|
-
L:
|
|
1280
|
+
L: 264,
|
|
1234
1281
|
S: void 0,
|
|
1235
1282
|
A: [
|
|
1236
1283
|
"options.onCreate",
|
|
1237
1284
|
""
|
|
1238
1285
|
]
|
|
1239
1286
|
});
|
|
1240
|
-
const {
|
|
1287
|
+
const { from, to } = view.state.selection.main;
|
|
1241
1288
|
if (from === to) {
|
|
1242
1289
|
return false;
|
|
1243
1290
|
}
|
|
1244
|
-
const
|
|
1291
|
+
const cursor = Cursor.getCursorFromRange(cursorConverter3, {
|
|
1245
1292
|
from,
|
|
1246
1293
|
to
|
|
1247
1294
|
});
|
|
1248
|
-
if (
|
|
1249
|
-
const id = callbackWrapper(options.onCreate)(
|
|
1295
|
+
if (cursor) {
|
|
1296
|
+
const id = callbackWrapper(options.onCreate)(cursor, view.coordsAtPos(from));
|
|
1250
1297
|
if (id) {
|
|
1251
1298
|
view.dispatch({
|
|
1252
1299
|
effects: setSelection.of({
|
|
@@ -1256,52 +1303,12 @@ var comments = (options = {}) => {
|
|
|
1256
1303
|
anchor: from
|
|
1257
1304
|
}
|
|
1258
1305
|
});
|
|
1259
|
-
if (options.footnote) {
|
|
1260
|
-
const tag = `[^${id}]`;
|
|
1261
|
-
view.dispatch({
|
|
1262
|
-
changes: {
|
|
1263
|
-
from: head,
|
|
1264
|
-
insert: tag
|
|
1265
|
-
},
|
|
1266
|
-
selection: {
|
|
1267
|
-
anchor: head + tag.length
|
|
1268
|
-
}
|
|
1269
|
-
});
|
|
1270
|
-
}
|
|
1271
1306
|
return true;
|
|
1272
1307
|
}
|
|
1273
1308
|
}
|
|
1274
1309
|
return false;
|
|
1275
1310
|
};
|
|
1276
|
-
const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
|
|
1277
|
-
static {
|
|
1278
|
-
// Match markdown footnotes (option).
|
|
1279
|
-
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
1280
|
-
this.bookmarkMatcher = new MatchDecorator({
|
|
1281
|
-
regexp: /\[\^(\w+)\]/g,
|
|
1282
|
-
decoration: (match, view, pos) => {
|
|
1283
|
-
const id = match[1];
|
|
1284
|
-
return Decoration3.replace({
|
|
1285
|
-
id,
|
|
1286
|
-
widget: new BookmarkWidget(pos, id)
|
|
1287
|
-
});
|
|
1288
|
-
}
|
|
1289
|
-
});
|
|
1290
|
-
}
|
|
1291
|
-
constructor(view) {
|
|
1292
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
1293
|
-
}
|
|
1294
|
-
update(update2) {
|
|
1295
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update2, this.bookmarks);
|
|
1296
|
-
}
|
|
1297
|
-
}, {
|
|
1298
|
-
decorations: (instance) => instance.bookmarks,
|
|
1299
|
-
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1300
|
-
return view.plugin(plugin)?.bookmarks || Decoration3.none;
|
|
1301
|
-
})
|
|
1302
|
-
});
|
|
1303
1311
|
return [
|
|
1304
|
-
bookmarksViewPlugin,
|
|
1305
1312
|
commentsStateField,
|
|
1306
1313
|
highlightDecorations,
|
|
1307
1314
|
styles3,
|
|
@@ -1310,7 +1317,7 @@ var comments = (options = {}) => {
|
|
|
1310
1317
|
//
|
|
1311
1318
|
options.onCreate ? keymap3.of([
|
|
1312
1319
|
{
|
|
1313
|
-
key:
|
|
1320
|
+
key: shortcut,
|
|
1314
1321
|
run: callbackWrapper(createCommentThread)
|
|
1315
1322
|
}
|
|
1316
1323
|
]) : [],
|
|
@@ -1327,7 +1334,7 @@ var comments = (options = {}) => {
|
|
|
1327
1334
|
above: true,
|
|
1328
1335
|
create: () => {
|
|
1329
1336
|
const el = document.createElement("div");
|
|
1330
|
-
options.onHover
|
|
1337
|
+
options.onHover(el, shortcut);
|
|
1331
1338
|
return {
|
|
1332
1339
|
dom: el,
|
|
1333
1340
|
offset: {
|
|
@@ -1340,7 +1347,8 @@ var comments = (options = {}) => {
|
|
|
1340
1347
|
}
|
|
1341
1348
|
return null;
|
|
1342
1349
|
}, {
|
|
1343
|
-
|
|
1350
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1351
|
+
// hideOnChange: true,
|
|
1344
1352
|
hoverTime: 1e3
|
|
1345
1353
|
}) : [],
|
|
1346
1354
|
//
|
|
@@ -1348,27 +1356,20 @@ var comments = (options = {}) => {
|
|
|
1348
1356
|
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1349
1357
|
//
|
|
1350
1358
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1351
|
-
const cursorConverter3 = view.state.facet(
|
|
1359
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1352
1360
|
{
|
|
1353
1361
|
let mod = false;
|
|
1354
1362
|
const { active, ranges } = state.field(commentsStateField);
|
|
1355
1363
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1356
1364
|
ranges.forEach((range) => {
|
|
1357
1365
|
if (from2 === to2) {
|
|
1358
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1366
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1359
1367
|
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
|
-
|
|
1361
|
-
thread: range.id
|
|
1362
|
-
}, {
|
|
1363
|
-
F: __dxlog_file3,
|
|
1364
|
-
L: 358,
|
|
1365
|
-
S: void 0,
|
|
1366
|
-
C: (f, a) => f(...a)
|
|
1367
|
-
});
|
|
1368
|
+
options.onDelete?.(range.id);
|
|
1368
1369
|
}
|
|
1369
1370
|
}
|
|
1370
1371
|
if (from <= range.to) {
|
|
1371
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
1373
|
Object.assign(range, newRange);
|
|
1373
1374
|
mod = true;
|
|
1374
1375
|
}
|
|
@@ -1414,29 +1415,13 @@ var comments = (options = {}) => {
|
|
|
1414
1415
|
});
|
|
1415
1416
|
}
|
|
1416
1417
|
}
|
|
1417
|
-
})
|
|
1418
|
+
}),
|
|
1419
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1418
1420
|
];
|
|
1419
1421
|
};
|
|
1420
|
-
var getCursorFromRange = (cursorConverter3, range) => {
|
|
1421
|
-
const from = cursorConverter3.toCursor(range.from);
|
|
1422
|
-
const to = cursorConverter3.toCursor(range.to, -1);
|
|
1423
|
-
return [
|
|
1424
|
-
from,
|
|
1425
|
-
to
|
|
1426
|
-
].join(":");
|
|
1427
|
-
};
|
|
1428
|
-
var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
1429
|
-
const parts = cursor.split(":");
|
|
1430
|
-
const from = cursorConverter3.fromCursor(parts[0]);
|
|
1431
|
-
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1432
|
-
return from !== void 0 && to !== void 0 ? {
|
|
1433
|
-
from,
|
|
1434
|
-
to
|
|
1435
|
-
} : void 0;
|
|
1436
|
-
};
|
|
1437
1422
|
|
|
1438
1423
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
-
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator
|
|
1424
|
+
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1440
1425
|
var styles4 = EditorView6.baseTheme({
|
|
1441
1426
|
"& .cm-hr": {
|
|
1442
1427
|
// TODO(burdon): ???
|
|
@@ -1444,7 +1429,7 @@ var styles4 = EditorView6.baseTheme({
|
|
|
1444
1429
|
borderBottom: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1445
1430
|
}
|
|
1446
1431
|
});
|
|
1447
|
-
var HorizontalRuleWidget = class extends
|
|
1432
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1448
1433
|
constructor(_pos) {
|
|
1449
1434
|
super();
|
|
1450
1435
|
this._pos = _pos;
|
|
@@ -1458,15 +1443,16 @@ var HorizontalRuleWidget = class extends WidgetType3 {
|
|
|
1458
1443
|
return el;
|
|
1459
1444
|
}
|
|
1460
1445
|
};
|
|
1461
|
-
var placeholderMatcher = new
|
|
1462
|
-
regexp:
|
|
1446
|
+
var placeholderMatcher = new MatchDecorator({
|
|
1447
|
+
// regexp: /(?<=\n\n)---/gs,
|
|
1448
|
+
regexp: /^---$/gs,
|
|
1463
1449
|
decoration: (match, view, pos) => Decoration4.replace({
|
|
1464
1450
|
widget: new HorizontalRuleWidget(pos)
|
|
1465
1451
|
})
|
|
1466
1452
|
});
|
|
1467
1453
|
var hr = () => [
|
|
1468
1454
|
styles4,
|
|
1469
|
-
|
|
1455
|
+
ViewPlugin4.fromClass(class {
|
|
1470
1456
|
constructor(view) {
|
|
1471
1457
|
this.rules = placeholderMatcher.createDeco(view);
|
|
1472
1458
|
}
|
|
@@ -1474,18 +1460,14 @@ var hr = () => [
|
|
|
1474
1460
|
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1475
1461
|
}
|
|
1476
1462
|
}, {
|
|
1477
|
-
decorations: (instance) => instance.rules
|
|
1478
|
-
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1479
|
-
provide: (plugin) => EditorView6.atomicRanges.of((view) => {
|
|
1480
|
-
return view.plugin(plugin)?.rules || Decoration4.none;
|
|
1481
|
-
})
|
|
1463
|
+
decorations: (instance) => instance.rules
|
|
1482
1464
|
})
|
|
1483
1465
|
];
|
|
1484
1466
|
|
|
1485
1467
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1486
1468
|
import { syntaxTree } from "@codemirror/language";
|
|
1487
1469
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
1488
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as
|
|
1470
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1489
1471
|
var image = (options = {}) => {
|
|
1490
1472
|
return StateField3.define({
|
|
1491
1473
|
create: (state) => {
|
|
@@ -1537,7 +1519,7 @@ var buildDecorations = (from, to, state) => {
|
|
|
1537
1519
|
});
|
|
1538
1520
|
return decorations;
|
|
1539
1521
|
};
|
|
1540
|
-
var ImageWidget = class extends
|
|
1522
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1541
1523
|
constructor(_url) {
|
|
1542
1524
|
super();
|
|
1543
1525
|
this._url = _url;
|
|
@@ -1557,11 +1539,11 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1557
1539
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1558
1540
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1559
1541
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
1560
|
-
import {
|
|
1542
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1561
1543
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1562
1544
|
var link = (options = {}) => {
|
|
1563
1545
|
const extensions = [
|
|
1564
|
-
|
|
1546
|
+
ViewPlugin5.fromClass(class {
|
|
1565
1547
|
constructor(view) {
|
|
1566
1548
|
this.decorations = buildDecorations2(view, options);
|
|
1567
1549
|
}
|
|
@@ -1612,7 +1594,7 @@ var link = (options = {}) => {
|
|
|
1612
1594
|
}
|
|
1613
1595
|
return extensions;
|
|
1614
1596
|
};
|
|
1615
|
-
var LinkButton = class extends
|
|
1597
|
+
var LinkButton = class extends WidgetType4 {
|
|
1616
1598
|
constructor(_url, _onAttach) {
|
|
1617
1599
|
super();
|
|
1618
1600
|
this._url = _url;
|
|
@@ -1627,7 +1609,7 @@ var LinkButton = class extends WidgetType5 {
|
|
|
1627
1609
|
return el;
|
|
1628
1610
|
}
|
|
1629
1611
|
};
|
|
1630
|
-
var LinkText = class extends
|
|
1612
|
+
var LinkText = class extends WidgetType4 {
|
|
1631
1613
|
constructor(_text, _url) {
|
|
1632
1614
|
super();
|
|
1633
1615
|
this._text = _text;
|
|
@@ -1708,7 +1690,7 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1708
1690
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1709
1691
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1710
1692
|
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1711
|
-
import { markdownLanguage as
|
|
1693
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1712
1694
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1713
1695
|
import { languages } from "@codemirror/language-data";
|
|
1714
1696
|
import { searchKeymap } from "@codemirror/search";
|
|
@@ -1717,7 +1699,7 @@ import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/the
|
|
|
1717
1699
|
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1718
1700
|
|
|
1719
1701
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1720
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
1702
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1721
1703
|
import { HighlightStyle } from "@codemirror/language";
|
|
1722
1704
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1723
1705
|
import { Table } from "@lezer/markdown";
|
|
@@ -1727,7 +1709,6 @@ var markdownTags = {
|
|
|
1727
1709
|
CodeText: Tag.define(),
|
|
1728
1710
|
EmphasisMark: Tag.define(),
|
|
1729
1711
|
HeaderMark: Tag.define(),
|
|
1730
|
-
// HorizontalRule: Tag.define(),
|
|
1731
1712
|
InlineCode: Tag.define(),
|
|
1732
1713
|
LinkLabel: Tag.define(),
|
|
1733
1714
|
LinkReference: Tag.define(),
|
|
@@ -1891,12 +1872,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1891
1872
|
],
|
|
1892
1873
|
class: blockquote
|
|
1893
1874
|
},
|
|
1894
|
-
// TODO(burdon): Replace with extension.
|
|
1895
|
-
// {
|
|
1896
|
-
// tag: [markdownTags.HorizontalRule],
|
|
1897
|
-
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1898
|
-
// },
|
|
1899
|
-
// TODO(burdon): Only if being edited.
|
|
1900
1875
|
{
|
|
1901
1876
|
tag: [
|
|
1902
1877
|
markdownTags.TableCell
|
|
@@ -1904,7 +1879,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1904
1879
|
class: "font-mono"
|
|
1905
1880
|
}
|
|
1906
1881
|
], {
|
|
1907
|
-
scope:
|
|
1882
|
+
scope: markdownLanguage2,
|
|
1908
1883
|
all: {
|
|
1909
1884
|
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1910
1885
|
}
|
|
@@ -1936,7 +1911,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1936
1911
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1937
1912
|
// https://github.github.com/gfm
|
|
1938
1913
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1939
|
-
base:
|
|
1914
|
+
base: markdownLanguage3,
|
|
1940
1915
|
// Languages for syntax highlighting fenced code blocks.
|
|
1941
1916
|
codeLanguages: languages,
|
|
1942
1917
|
// Parser extensions.
|
|
@@ -1990,7 +1965,7 @@ var mention = ({ onSearch }) => {
|
|
|
1990
1965
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1991
1966
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1992
1967
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1993
|
-
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as
|
|
1968
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1994
1969
|
var table = (options = {}) => {
|
|
1995
1970
|
return StateField4.define({
|
|
1996
1971
|
create: (state) => update(state, options),
|
|
@@ -2048,7 +2023,7 @@ var update = (state, options) => {
|
|
|
2048
2023
|
});
|
|
2049
2024
|
return builder.finish();
|
|
2050
2025
|
};
|
|
2051
|
-
var TableWidget = class extends
|
|
2026
|
+
var TableWidget = class extends WidgetType5 {
|
|
2052
2027
|
constructor(_table) {
|
|
2053
2028
|
super();
|
|
2054
2029
|
this._table = _table;
|
|
@@ -2086,87 +2061,86 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2086
2061
|
};
|
|
2087
2062
|
|
|
2088
2063
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2089
|
-
import {
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
}
|
|
2095
|
-
});
|
|
2096
|
-
var CheckboxWidget = class extends WidgetType7 {
|
|
2097
|
-
constructor(_checked, _indent, _onCheck) {
|
|
2064
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2065
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
2066
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2067
|
+
var CheckboxWidget = class extends WidgetType6 {
|
|
2068
|
+
constructor(_checked) {
|
|
2098
2069
|
super();
|
|
2099
2070
|
this._checked = _checked;
|
|
2100
|
-
this._indent = _indent;
|
|
2101
|
-
this._onCheck = _onCheck;
|
|
2102
2071
|
}
|
|
2103
2072
|
eq(other) {
|
|
2104
|
-
return this._checked === other._checked
|
|
2073
|
+
return this._checked === other._checked;
|
|
2105
2074
|
}
|
|
2106
2075
|
toDOM(view) {
|
|
2107
|
-
const
|
|
2108
|
-
wrap.className = "cm-task-item";
|
|
2109
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2110
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2111
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2076
|
+
const input = document.createElement("input");
|
|
2112
2077
|
input.type = "checkbox";
|
|
2113
2078
|
input.checked = this._checked;
|
|
2114
|
-
if (
|
|
2079
|
+
if (view.state.readOnly) {
|
|
2115
2080
|
input.setAttribute("disabled", "true");
|
|
2116
|
-
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2081
|
+
} else {
|
|
2082
|
+
input.onmousedown = (event) => {
|
|
2083
|
+
const pos = view.posAtDOM(input);
|
|
2084
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2085
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2086
|
+
view.dispatch({
|
|
2087
|
+
changes: {
|
|
2088
|
+
from: pos + 1,
|
|
2089
|
+
to: pos + 2,
|
|
2090
|
+
insert: this._checked ? " " : "x"
|
|
2091
|
+
}
|
|
2092
|
+
});
|
|
2093
|
+
event.preventDefault();
|
|
2094
|
+
}
|
|
2121
2095
|
};
|
|
2122
2096
|
}
|
|
2123
|
-
return
|
|
2097
|
+
return input;
|
|
2124
2098
|
}
|
|
2125
2099
|
ignoreEvent() {
|
|
2126
2100
|
return false;
|
|
2127
2101
|
}
|
|
2128
2102
|
};
|
|
2103
|
+
var checkedDeco = Decoration8.replace({
|
|
2104
|
+
widget: new CheckboxWidget(true)
|
|
2105
|
+
});
|
|
2106
|
+
var uncheckedDeco = Decoration8.replace({
|
|
2107
|
+
widget: new CheckboxWidget(false)
|
|
2108
|
+
});
|
|
2129
2109
|
var tasklist = (options = {}) => {
|
|
2130
|
-
|
|
2131
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2132
|
-
decoration: (match, view, pos) => {
|
|
2133
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2134
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2135
|
-
return Decoration8.replace({
|
|
2136
|
-
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2137
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2138
|
-
view.dispatch({
|
|
2139
|
-
changes: {
|
|
2140
|
-
from: idx,
|
|
2141
|
-
to: idx + 1,
|
|
2142
|
-
insert: checked2 ? "x" : " "
|
|
2143
|
-
},
|
|
2144
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2145
|
-
selection: {
|
|
2146
|
-
anchor: idx + 3
|
|
2147
|
-
}
|
|
2148
|
-
});
|
|
2149
|
-
})
|
|
2150
|
-
});
|
|
2151
|
-
}
|
|
2152
|
-
});
|
|
2153
|
-
const tasks = ViewPlugin7.fromClass(class {
|
|
2110
|
+
return ViewPlugin6.fromClass(class {
|
|
2154
2111
|
constructor(view) {
|
|
2155
|
-
this.
|
|
2112
|
+
this.decorations = buildDecorations3(view);
|
|
2156
2113
|
}
|
|
2157
2114
|
update(update2) {
|
|
2158
|
-
|
|
2115
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2116
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2117
|
+
}
|
|
2159
2118
|
}
|
|
2160
2119
|
}, {
|
|
2161
|
-
decorations: (
|
|
2120
|
+
decorations: (v) => v.decorations,
|
|
2121
|
+
// TODO(burdon): Is this still required?
|
|
2162
2122
|
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2163
|
-
return view.plugin(plugin)?.
|
|
2123
|
+
return view.plugin(plugin)?.decorations || Decoration8.none;
|
|
2164
2124
|
})
|
|
2165
2125
|
});
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2126
|
+
};
|
|
2127
|
+
var buildDecorations3 = (view) => {
|
|
2128
|
+
const builder = new RangeSetBuilder3();
|
|
2129
|
+
const { state } = view;
|
|
2130
|
+
const cursor = state.selection.main.head;
|
|
2131
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2132
|
+
syntaxTree4(state).iterate({
|
|
2133
|
+
enter: (node) => {
|
|
2134
|
+
if (node.name === "TaskMarker" && (cursor < node.from || cursor > node.to)) {
|
|
2135
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2136
|
+
builder.add(node.from, node.to, checked ? checkedDeco : uncheckedDeco);
|
|
2137
|
+
}
|
|
2138
|
+
},
|
|
2139
|
+
from,
|
|
2140
|
+
to
|
|
2141
|
+
});
|
|
2142
|
+
}
|
|
2143
|
+
return builder.finish();
|
|
2170
2144
|
};
|
|
2171
2145
|
|
|
2172
2146
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
@@ -2243,7 +2217,7 @@ var cursorConverter2 = (text) => ({
|
|
|
2243
2217
|
|
|
2244
2218
|
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2245
2219
|
var yjs = (content, awareness2) => [
|
|
2246
|
-
|
|
2220
|
+
Cursor.converter.of(cursorConverter2(content)),
|
|
2247
2221
|
yCollab(content, awareness2)
|
|
2248
2222
|
];
|
|
2249
2223
|
|
|
@@ -2340,33 +2314,6 @@ var defaultTheme = {
|
|
|
2340
2314
|
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2341
2315
|
},
|
|
2342
2316
|
//
|
|
2343
|
-
// collaboration
|
|
2344
|
-
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
2345
|
-
//
|
|
2346
|
-
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
2347
|
-
mixBlendMode: "multiply"
|
|
2348
|
-
},
|
|
2349
|
-
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2350
|
-
mixBlendMode: "screen"
|
|
2351
|
-
},
|
|
2352
|
-
".cm-ySelectionInfo": {
|
|
2353
|
-
padding: "2px 4px",
|
|
2354
|
-
marginBlockStart: "-4px"
|
|
2355
|
-
},
|
|
2356
|
-
".cm-ySelection, & .cm-selectionMatch": {
|
|
2357
|
-
paddingBlockStart: ".15em",
|
|
2358
|
-
paddingBlockEnd: ".15em"
|
|
2359
|
-
},
|
|
2360
|
-
".cm-ySelectionCaret": {
|
|
2361
|
-
display: "inline-block",
|
|
2362
|
-
insetBlockStart: ".1em",
|
|
2363
|
-
blockSize: "1.4em",
|
|
2364
|
-
verticalAlign: "top"
|
|
2365
|
-
},
|
|
2366
|
-
".cm-yLineSelection": {
|
|
2367
|
-
margin: 0
|
|
2368
|
-
},
|
|
2369
|
-
//
|
|
2370
2317
|
// link
|
|
2371
2318
|
//
|
|
2372
2319
|
".cm-link": {
|
|
@@ -2403,13 +2350,6 @@ var defaultTheme = {
|
|
|
2403
2350
|
textDecoration: "none"
|
|
2404
2351
|
},
|
|
2405
2352
|
//
|
|
2406
|
-
// widgets
|
|
2407
|
-
//
|
|
2408
|
-
".cm-widgetBuffer": {
|
|
2409
|
-
display: "none",
|
|
2410
|
-
height: 0
|
|
2411
|
-
},
|
|
2412
|
-
//
|
|
2413
2353
|
// table
|
|
2414
2354
|
//
|
|
2415
2355
|
".cm-table *": {
|
|
@@ -2440,27 +2380,17 @@ var defaultTheme = {
|
|
|
2440
2380
|
},
|
|
2441
2381
|
//
|
|
2442
2382
|
// font size
|
|
2443
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2383
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2384
|
+
// but it's far more verbose than it needs to be.
|
|
2444
2385
|
//
|
|
2445
|
-
...Object.keys(
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
|
|
2454
|
-
height
|
|
2455
|
-
};
|
|
2456
|
-
acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
|
|
2457
|
-
height
|
|
2458
|
-
};
|
|
2459
|
-
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
|
|
2460
|
-
height
|
|
2461
|
-
};
|
|
2462
|
-
return acc;
|
|
2463
|
-
}, {}),
|
|
2386
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2387
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2388
|
+
//
|
|
2389
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2390
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2391
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2392
|
+
// return acc;
|
|
2393
|
+
// }, {}),
|
|
2464
2394
|
/**
|
|
2465
2395
|
* Panels
|
|
2466
2396
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2511,7 +2441,9 @@ var textTheme = {
|
|
|
2511
2441
|
}
|
|
2512
2442
|
};
|
|
2513
2443
|
var markdownTheme = {
|
|
2514
|
-
|
|
2444
|
+
".cm-scroller": {
|
|
2445
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2446
|
+
},
|
|
2515
2447
|
".cm-placeholder": {
|
|
2516
2448
|
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2517
2449
|
}
|
|
@@ -2530,21 +2462,23 @@ var EditorModes = [
|
|
|
2530
2462
|
"default",
|
|
2531
2463
|
"vim"
|
|
2532
2464
|
];
|
|
2533
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2534
|
-
const { themeMode } = useThemeContext();
|
|
2465
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, selection, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
|
|
2535
2466
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2536
2467
|
tabBehavior: "limited"
|
|
2537
2468
|
});
|
|
2538
|
-
const
|
|
2539
|
-
const
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2469
|
+
const { themeMode } = useThemeContext();
|
|
2470
|
+
const rootRef = useRef(null);
|
|
2471
|
+
const [view, setView] = useState(null);
|
|
2472
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2473
|
+
view
|
|
2474
|
+
]);
|
|
2475
|
+
useEffect(() => {
|
|
2476
|
+
if (autofocus) {
|
|
2477
|
+
view?.focus();
|
|
2478
|
+
}
|
|
2479
|
+
}, [
|
|
2480
|
+
autofocus,
|
|
2543
2481
|
view
|
|
2544
|
-
}), [
|
|
2545
|
-
view,
|
|
2546
|
-
state,
|
|
2547
|
-
root
|
|
2548
2482
|
]);
|
|
2549
2483
|
const { awareness: awareness2, peer } = model;
|
|
2550
2484
|
useEffect(() => {
|
|
@@ -2568,7 +2502,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2568
2502
|
themeMode
|
|
2569
2503
|
]);
|
|
2570
2504
|
useEffect(() => {
|
|
2571
|
-
if (view && comments2
|
|
2505
|
+
if (view && comments2 !== void 0) {
|
|
2572
2506
|
view.dispatch({
|
|
2573
2507
|
effects: setCommentRange.of({
|
|
2574
2508
|
model,
|
|
@@ -2581,11 +2515,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2581
2515
|
comments2
|
|
2582
2516
|
]);
|
|
2583
2517
|
useEffect(() => {
|
|
2584
|
-
if (!
|
|
2518
|
+
if (!model || !rootRef.current) {
|
|
2585
2519
|
return;
|
|
2586
2520
|
}
|
|
2587
|
-
const
|
|
2521
|
+
const state = EditorState2.create({
|
|
2588
2522
|
doc: model.text(),
|
|
2523
|
+
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2524
|
+
selection,
|
|
2589
2525
|
extensions: [
|
|
2590
2526
|
readonly && EditorState2.readOnly.of(readonly),
|
|
2591
2527
|
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
@@ -2593,7 +2529,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2593
2529
|
// Theme.
|
|
2594
2530
|
// TODO(burdon): Make theme configurable.
|
|
2595
2531
|
EditorView12.baseTheme(defaultTheme),
|
|
2596
|
-
EditorView12.theme(
|
|
2532
|
+
EditorView12.theme(theme ?? {}),
|
|
2597
2533
|
EditorView12.darkTheme.of(themeMode === "dark"),
|
|
2598
2534
|
// Storage and replication.
|
|
2599
2535
|
model.extension,
|
|
@@ -2602,19 +2538,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2602
2538
|
].filter(Boolean)
|
|
2603
2539
|
});
|
|
2604
2540
|
view?.destroy();
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
state: state2,
|
|
2609
|
-
parent: root
|
|
2610
|
-
})
|
|
2541
|
+
const newView = new EditorView12({
|
|
2542
|
+
parent: rootRef.current,
|
|
2543
|
+
state
|
|
2611
2544
|
});
|
|
2545
|
+
setView(newView);
|
|
2612
2546
|
return () => {
|
|
2613
|
-
|
|
2614
|
-
|
|
2547
|
+
newView?.destroy();
|
|
2548
|
+
setView(null);
|
|
2615
2549
|
};
|
|
2616
2550
|
}, [
|
|
2617
|
-
|
|
2551
|
+
rootRef,
|
|
2618
2552
|
model,
|
|
2619
2553
|
readonly,
|
|
2620
2554
|
editorMode,
|
|
@@ -2623,12 +2557,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2623
2557
|
const handleKeyUp = useCallback((event) => {
|
|
2624
2558
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2625
2559
|
switch (key) {
|
|
2626
|
-
case "Enter": {
|
|
2627
|
-
view?.contentDOM.focus();
|
|
2628
|
-
break;
|
|
2629
|
-
}
|
|
2630
2560
|
case "Escape": {
|
|
2631
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) &&
|
|
2561
|
+
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
|
|
2632
2562
|
break;
|
|
2633
2563
|
}
|
|
2634
2564
|
}
|
|
@@ -2638,16 +2568,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2638
2568
|
]);
|
|
2639
2569
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2640
2570
|
key: model.id,
|
|
2641
|
-
|
|
2571
|
+
role: "none",
|
|
2642
2572
|
tabIndex: 0,
|
|
2643
|
-
|
|
2573
|
+
onKeyUp: handleKeyUp,
|
|
2574
|
+
...slots.root,
|
|
2644
2575
|
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2645
|
-
|
|
2576
|
+
ref: rootRef
|
|
2646
2577
|
});
|
|
2647
2578
|
});
|
|
2648
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2579
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = textTheme, slots, ...props }, forwardedRef) => {
|
|
2649
2580
|
const { themeMode } = useThemeContext();
|
|
2650
|
-
const
|
|
2581
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2651
2582
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2652
2583
|
ref: forwardedRef,
|
|
2653
2584
|
readonly,
|
|
@@ -2655,17 +2586,18 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
|
|
|
2655
2586
|
basicBundle({
|
|
2656
2587
|
readonly,
|
|
2657
2588
|
themeMode,
|
|
2658
|
-
placeholder:
|
|
2589
|
+
placeholder: placeholder3
|
|
2659
2590
|
}),
|
|
2660
2591
|
...extensions
|
|
2661
2592
|
],
|
|
2662
|
-
|
|
2593
|
+
theme,
|
|
2594
|
+
slots: updatedSlots,
|
|
2663
2595
|
...props
|
|
2664
2596
|
});
|
|
2665
2597
|
});
|
|
2666
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2598
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = markdownTheme, slots, ...props }, forwardedRef) => {
|
|
2667
2599
|
const { themeMode } = useThemeContext();
|
|
2668
|
-
const
|
|
2600
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2669
2601
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2670
2602
|
ref: forwardedRef,
|
|
2671
2603
|
readonly,
|
|
@@ -2673,30 +2605,25 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
|
|
|
2673
2605
|
markdownBundle({
|
|
2674
2606
|
readonly,
|
|
2675
2607
|
themeMode,
|
|
2676
|
-
placeholder:
|
|
2608
|
+
placeholder: placeholder3
|
|
2677
2609
|
}),
|
|
2678
2610
|
...extensions
|
|
2679
2611
|
],
|
|
2680
|
-
|
|
2612
|
+
theme,
|
|
2613
|
+
slots: updatedSlots,
|
|
2681
2614
|
...props
|
|
2682
2615
|
});
|
|
2683
2616
|
});
|
|
2684
2617
|
var defaultSlots = {
|
|
2685
2618
|
root: {
|
|
2686
|
-
className: mx3("p-2", inputSurface)
|
|
2619
|
+
className: mx3("w-full p-2 overflow-y-auto", inputSurface)
|
|
2687
2620
|
}
|
|
2688
2621
|
};
|
|
2689
2622
|
var defaultTextSlots = {
|
|
2690
|
-
...defaultSlots
|
|
2691
|
-
editor: {
|
|
2692
|
-
theme: textTheme
|
|
2693
|
-
}
|
|
2623
|
+
...defaultSlots
|
|
2694
2624
|
};
|
|
2695
2625
|
var defaultMarkdownSlots = {
|
|
2696
|
-
...defaultSlots
|
|
2697
|
-
editor: {
|
|
2698
|
-
theme: markdownTheme
|
|
2699
|
-
}
|
|
2626
|
+
...defaultSlots
|
|
2700
2627
|
};
|
|
2701
2628
|
|
|
2702
2629
|
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
@@ -2708,7 +2635,7 @@ import { isNotNullOrUndefined } from "@dxos/util";
|
|
|
2708
2635
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2709
2636
|
import { Context as Context2 } from "@dxos/context";
|
|
2710
2637
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2711
|
-
import { log as
|
|
2638
|
+
import { log as log2 } from "@dxos/log";
|
|
2712
2639
|
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2713
2640
|
var DEBOUNCE_INTERVAL = 100;
|
|
2714
2641
|
var SpaceAwarenessProvider = class {
|
|
@@ -2747,7 +2674,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2747
2674
|
void this._space.postMessage(this._channel, {
|
|
2748
2675
|
kind: "query"
|
|
2749
2676
|
}).catch((err) => {
|
|
2750
|
-
|
|
2677
|
+
log2.debug("failed to query awareness", {
|
|
2751
2678
|
err
|
|
2752
2679
|
}, {
|
|
2753
2680
|
F: __dxlog_file4,
|
|
@@ -2819,15 +2746,13 @@ import * as decoding from "lib0/decoding";
|
|
|
2819
2746
|
import * as encoding from "lib0/encoding";
|
|
2820
2747
|
import { Observable } from "lib0/observable";
|
|
2821
2748
|
import * as YP from "y-protocols/awareness";
|
|
2822
|
-
import * as Y2 from "yjs";
|
|
2823
2749
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2824
|
-
import { log as
|
|
2825
|
-
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2750
|
+
import { log as log3 } from "@dxos/log";
|
|
2826
2751
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2827
2752
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2828
2753
|
invariant4(text?.doc && text?.content, void 0, {
|
|
2829
2754
|
F: __dxlog_file5,
|
|
2830
|
-
L:
|
|
2755
|
+
L: 21,
|
|
2831
2756
|
S: void 0,
|
|
2832
2757
|
A: [
|
|
2833
2758
|
"text?.doc && text?.content",
|
|
@@ -2843,34 +2768,6 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
2843
2768
|
id: text.doc.guid,
|
|
2844
2769
|
content: text.content,
|
|
2845
2770
|
text: () => text.content.toString(),
|
|
2846
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2847
|
-
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2848
|
-
getCursorFromRange: (range) => {
|
|
2849
|
-
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2850
|
-
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2851
|
-
return [
|
|
2852
|
-
arrayToString2(from),
|
|
2853
|
-
arrayToString2(to)
|
|
2854
|
-
].join(":");
|
|
2855
|
-
},
|
|
2856
|
-
getRangeFromCursor: (cursor) => {
|
|
2857
|
-
invariant4(text.doc, void 0, {
|
|
2858
|
-
F: __dxlog_file5,
|
|
2859
|
-
L: 40,
|
|
2860
|
-
S: void 0,
|
|
2861
|
-
A: [
|
|
2862
|
-
"text.doc",
|
|
2863
|
-
""
|
|
2864
|
-
]
|
|
2865
|
-
});
|
|
2866
|
-
const parts = cursor.split(":");
|
|
2867
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2868
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2869
|
-
return from && to ? {
|
|
2870
|
-
from: from.index,
|
|
2871
|
-
to: to.index
|
|
2872
|
-
} : void 0;
|
|
2873
|
-
},
|
|
2874
2771
|
extension: [
|
|
2875
2772
|
modelState.init(() => model),
|
|
2876
2773
|
yjs(text.content, provider?.awareness)
|
|
@@ -2913,14 +2810,14 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2913
2810
|
return this._awareness;
|
|
2914
2811
|
}
|
|
2915
2812
|
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2916
|
-
|
|
2813
|
+
log3("awareness update", {
|
|
2917
2814
|
added,
|
|
2918
2815
|
updated,
|
|
2919
2816
|
removed,
|
|
2920
2817
|
origin
|
|
2921
2818
|
}, {
|
|
2922
2819
|
F: __dxlog_file5,
|
|
2923
|
-
L:
|
|
2820
|
+
L: 100,
|
|
2924
2821
|
S: this,
|
|
2925
2822
|
C: (f, a) => f(...a)
|
|
2926
2823
|
});
|
|
@@ -2931,9 +2828,9 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2931
2828
|
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2932
2829
|
}
|
|
2933
2830
|
_handleSpaceMessage({ payload }) {
|
|
2934
|
-
|
|
2831
|
+
log3("space message", payload, {
|
|
2935
2832
|
F: __dxlog_file5,
|
|
2936
|
-
L:
|
|
2833
|
+
L: 109,
|
|
2937
2834
|
S: this,
|
|
2938
2835
|
C: (f, a) => f(...a)
|
|
2939
2836
|
});
|
|
@@ -2983,7 +2880,7 @@ var modelState = StateField5.define({
|
|
|
2983
2880
|
});
|
|
2984
2881
|
var useTextModel = (props) => {
|
|
2985
2882
|
const { identity, space, text } = props;
|
|
2986
|
-
const [model, setModel] = useState2(
|
|
2883
|
+
const [model, setModel] = useState2();
|
|
2987
2884
|
useEffect2(() => setModel(createModel(props)), [
|
|
2988
2885
|
identity,
|
|
2989
2886
|
space,
|
|
@@ -3042,6 +2939,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3042
2939
|
export {
|
|
3043
2940
|
AwarenessProvider,
|
|
3044
2941
|
BaseTextEditor,
|
|
2942
|
+
Cursor,
|
|
3045
2943
|
Doc,
|
|
3046
2944
|
EditorModes,
|
|
3047
2945
|
MarkdownEditor,
|
|
@@ -3057,6 +2955,7 @@ export {
|
|
|
3057
2955
|
awareness,
|
|
3058
2956
|
basicBundle,
|
|
3059
2957
|
blast,
|
|
2958
|
+
callbackWrapper,
|
|
3060
2959
|
code2 as code,
|
|
3061
2960
|
codeTheme,
|
|
3062
2961
|
comments,
|