@dxos/react-ui-editor 0.3.11-main.008b7c6 → 0.3.11-main.0b0bfb1
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 +457 -570
- 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 +9 -5
- 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/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/index.d.ts +1 -0
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
- package/dist/types/src/extensions/code.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +2 -2
- 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/image.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +1 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/link.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/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 +3 -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/styles/tokens.d.ts +1 -0
- package/dist/types/src/styles/tokens.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 +24 -23
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +25 -23
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +68 -64
- package/src/components/TextEditor/comments.stories.tsx +315 -0
- package/src/extensions/autocomplete.ts +18 -17
- package/src/extensions/automerge/automerge.ts +2 -2
- package/src/extensions/automerge/cursor.ts +2 -1
- package/src/extensions/automerge/index.ts +1 -0
- package/src/extensions/awareness.ts +25 -32
- package/src/extensions/code.ts +14 -7
- package/src/extensions/comments.ts +23 -119
- package/src/extensions/cursor.ts +46 -0
- package/src/extensions/hr.ts +4 -5
- package/src/extensions/image.ts +40 -22
- package/src/extensions/index.ts +1 -1
- package/src/extensions/link.ts +86 -88
- package/src/extensions/markdown/highlight.ts +3 -12
- package/src/extensions/table.ts +10 -4
- package/src/extensions/tasklist.ts +53 -79
- package/src/extensions/yjs/cursor.ts +2 -1
- package/src/extensions/yjs/yjs.ts +2 -2
- package/src/hooks/useTextModel.ts +4 -7
- package/src/hooks/yjs.ts +1 -23
- package/src/index.ts +3 -0
- package/src/styles/markdown.ts +0 -2
- package/src/styles/tokens.ts +3 -0
- package/src/themes/default.ts +51 -78
- package/dist/types/src/extensions/mermaid.d.ts +0 -3
- package/dist/types/src/extensions/mermaid.d.ts.map +0 -1
- 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/extensions/mermaid.ts +0 -11
- 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
|
@@ -7,44 +7,45 @@ 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 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
|
};
|
|
@@ -273,30 +274,39 @@ var PatchSemaphore = class {
|
|
|
273
274
|
}
|
|
274
275
|
};
|
|
275
276
|
|
|
276
|
-
// packages/ui/react-ui-editor/src/
|
|
277
|
+
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
277
278
|
import { Facet } from "@codemirror/state";
|
|
278
|
-
var
|
|
279
|
+
var defaultCursorConverter = {
|
|
279
280
|
toCursor: (position) => position.toString(),
|
|
280
281
|
fromCursor: (cursor) => parseInt(cursor)
|
|
281
282
|
};
|
|
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)
|
|
283
|
+
var Cursor = class {
|
|
284
|
+
static {
|
|
285
|
+
this.converter = Facet.define({
|
|
286
|
+
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
298
287
|
});
|
|
299
288
|
}
|
|
289
|
+
static {
|
|
290
|
+
this.getCursorFromRange = (cursorConverter3, range) => {
|
|
291
|
+
const from = cursorConverter3.toCursor(range.from);
|
|
292
|
+
const to = cursorConverter3.toCursor(range.to, -1);
|
|
293
|
+
return [
|
|
294
|
+
from,
|
|
295
|
+
to
|
|
296
|
+
].join(":");
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
static {
|
|
300
|
+
this.getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
301
|
+
const parts = cursor.split(":");
|
|
302
|
+
const from = cursorConverter3.fromCursor(parts[0]);
|
|
303
|
+
const to = cursorConverter3.fromCursor(parts[1]);
|
|
304
|
+
return from !== void 0 && to !== void 0 ? {
|
|
305
|
+
from,
|
|
306
|
+
to
|
|
307
|
+
} : void 0;
|
|
308
|
+
};
|
|
309
|
+
}
|
|
300
310
|
};
|
|
301
311
|
|
|
302
312
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
@@ -342,8 +352,8 @@ var automerge3 = ({ handle, path }) => {
|
|
|
342
352
|
};
|
|
343
353
|
handle.addListener("change", this._handleChange);
|
|
344
354
|
}
|
|
345
|
-
update(
|
|
346
|
-
if (
|
|
355
|
+
update(update2) {
|
|
356
|
+
if (update2.transactions.length > 0 && update2.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
347
357
|
queueMicrotask(() => {
|
|
348
358
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
349
359
|
});
|
|
@@ -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, () => {
|
|
@@ -412,13 +422,13 @@ var RemoteSelectionsDecorator = class {
|
|
|
412
422
|
void this._ctx.dispose();
|
|
413
423
|
this._provider.close();
|
|
414
424
|
}
|
|
415
|
-
update(
|
|
416
|
-
this._updateLocalSelection(
|
|
417
|
-
this._updateRemoteSelections(
|
|
425
|
+
update(update2) {
|
|
426
|
+
this._updateLocalSelection(update2);
|
|
427
|
+
this._updateRemoteSelections(update2);
|
|
418
428
|
}
|
|
419
|
-
_updateLocalSelection(
|
|
420
|
-
const hasFocus =
|
|
421
|
-
const { anchor = void 0, head = void 0 } = hasFocus ?
|
|
429
|
+
_updateLocalSelection(update2) {
|
|
430
|
+
const hasFocus = update2.view.hasFocus && update2.view.dom.ownerDocument.hasFocus();
|
|
431
|
+
const { anchor = void 0, head = void 0 } = hasFocus ? update2.state.selection.main : {};
|
|
422
432
|
if (this._lastAnchor === anchor && this._lastHead === head) {
|
|
423
433
|
return;
|
|
424
434
|
}
|
|
@@ -429,7 +439,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
429
439
|
head: this._cursorConverter.toCursor(head)
|
|
430
440
|
} : void 0);
|
|
431
441
|
}
|
|
432
|
-
_updateRemoteSelections(
|
|
442
|
+
_updateRemoteSelections(update2) {
|
|
433
443
|
const decorations = [];
|
|
434
444
|
const awarenessStates = this._provider.getRemoteStates();
|
|
435
445
|
for (const state of awarenessStates) {
|
|
@@ -438,10 +448,10 @@ var RemoteSelectionsDecorator = class {
|
|
|
438
448
|
if (anchor == null || head == null) {
|
|
439
449
|
continue;
|
|
440
450
|
}
|
|
441
|
-
const start = Math.min(Math.min(anchor, head),
|
|
442
|
-
const end = Math.min(Math.max(anchor, head),
|
|
443
|
-
const startLine =
|
|
444
|
-
const endLine =
|
|
451
|
+
const start = Math.min(Math.min(anchor, head), update2.view.state.doc.length);
|
|
452
|
+
const end = Math.min(Math.max(anchor, head), update2.view.state.doc.length);
|
|
453
|
+
const startLine = update2.view.state.doc.lineAt(start);
|
|
454
|
+
const endLine = update2.view.state.doc.lineAt(end);
|
|
445
455
|
const color = state.info.color ?? "#30bced";
|
|
446
456
|
const lightColor = state.info.lightColor ?? color + "33";
|
|
447
457
|
if (startLine.number === endLine.number) {
|
|
@@ -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,18 +483,18 @@ 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++) {
|
|
480
|
-
const linePos =
|
|
490
|
+
const linePos = update2.view.state.doc.line(i).from;
|
|
481
491
|
decorations.push({
|
|
482
492
|
from: linePos,
|
|
483
493
|
to: linePos,
|
|
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",
|
|
@@ -595,7 +600,7 @@ var styles = EditorView.baseTheme({
|
|
|
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,
|
|
@@ -667,12 +672,12 @@ var blast = (options = defaultOptions) => {
|
|
|
667
672
|
};
|
|
668
673
|
return [
|
|
669
674
|
// Cursor moved.
|
|
670
|
-
EditorView3.updateListener.of((
|
|
671
|
-
if (blaster?.node !==
|
|
675
|
+
EditorView3.updateListener.of((update2) => {
|
|
676
|
+
if (blaster?.node !== update2.view.scrollDOM) {
|
|
672
677
|
if (blaster) {
|
|
673
678
|
blaster.destroy();
|
|
674
679
|
}
|
|
675
|
-
blaster = new Blaster(
|
|
680
|
+
blaster = new Blaster(update2.view.scrollDOM, defaultsDeep({
|
|
676
681
|
particleGravity: 0.2,
|
|
677
682
|
particleShrinkRate: 0.995,
|
|
678
683
|
color: () => [
|
|
@@ -686,10 +691,10 @@ var blast = (options = defaultOptions) => {
|
|
|
686
691
|
} else {
|
|
687
692
|
blaster.resize();
|
|
688
693
|
}
|
|
689
|
-
const current =
|
|
694
|
+
const current = update2.state.selection.main.head;
|
|
690
695
|
if (current !== last) {
|
|
691
696
|
last = current;
|
|
692
|
-
const { element, point } = getPoint(
|
|
697
|
+
const { element, point } = getPoint(update2.view, current - 1);
|
|
693
698
|
if (element && point) {
|
|
694
699
|
blaster.spawn({
|
|
695
700
|
element,
|
|
@@ -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: [
|
|
@@ -930,7 +935,6 @@ var random = (min, max) => {
|
|
|
930
935
|
|
|
931
936
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
932
937
|
import { ViewPlugin as ViewPlugin3, EditorView as EditorView4, Decoration as Decoration2 } from "@codemirror/view";
|
|
933
|
-
import get2 from "lodash.get";
|
|
934
938
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
935
939
|
|
|
936
940
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1014,20 +1018,22 @@ var inlineUrl = mx(code, "px-1");
|
|
|
1014
1018
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1015
1019
|
|
|
1016
1020
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1021
|
+
import get2 from "lodash.get";
|
|
1017
1022
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1018
1023
|
var tokens = tailwindConfig({}).theme;
|
|
1024
|
+
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1019
1025
|
|
|
1020
1026
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1021
1027
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1022
1028
|
var styles2 = EditorView4.baseTheme({
|
|
1023
1029
|
"& .cm-codeblock": {
|
|
1024
|
-
fontFamily:
|
|
1030
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1025
1031
|
},
|
|
1026
1032
|
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1027
|
-
background:
|
|
1033
|
+
background: getToken("extend.colors.neutral.50")
|
|
1028
1034
|
},
|
|
1029
1035
|
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1030
|
-
background:
|
|
1036
|
+
background: getToken("extend.colors.neutral.850")
|
|
1031
1037
|
},
|
|
1032
1038
|
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1033
1039
|
display: "block",
|
|
@@ -1055,7 +1061,7 @@ var getLineRange = (lines, from, to) => {
|
|
|
1055
1061
|
var code2 = () => {
|
|
1056
1062
|
const getDecorations = (view) => {
|
|
1057
1063
|
const decorations = [];
|
|
1058
|
-
if (view.state.readOnly) {
|
|
1064
|
+
if (!view.hasFocus || view.state.readOnly) {
|
|
1059
1065
|
const text = view.state.doc.sliceString(0);
|
|
1060
1066
|
const matches = text.matchAll(CODE_REGEX);
|
|
1061
1067
|
const blocks = view.viewportLineBlocks;
|
|
@@ -1074,11 +1080,16 @@ var code2 = () => {
|
|
|
1074
1080
|
return [
|
|
1075
1081
|
ViewPlugin3.fromClass(class {
|
|
1076
1082
|
constructor(view) {
|
|
1083
|
+
this.hasFocus = false;
|
|
1077
1084
|
this.decorations = getDecorations(view);
|
|
1078
1085
|
}
|
|
1079
|
-
update(
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
1086
|
+
update(update2) {
|
|
1087
|
+
if (
|
|
1088
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1089
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1090
|
+
) {
|
|
1091
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1092
|
+
this.decorations = getDecorations(update2.view);
|
|
1082
1093
|
}
|
|
1083
1094
|
}
|
|
1084
1095
|
}, {
|
|
@@ -1090,29 +1101,37 @@ var code2 = () => {
|
|
|
1090
1101
|
|
|
1091
1102
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1092
1103
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1093
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5
|
|
1094
|
-
import get3 from "lodash.get";
|
|
1104
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
|
|
1095
1105
|
import sortBy from "lodash.sortby";
|
|
1096
1106
|
import { debounce } from "@dxos/async";
|
|
1097
1107
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1098
1108
|
import { log as log2 } from "@dxos/log";
|
|
1099
1109
|
import { nonNullable } from "@dxos/util";
|
|
1110
|
+
|
|
1111
|
+
// packages/ui/react-ui-editor/src/util.ts
|
|
1112
|
+
import { log } from "@dxos/log";
|
|
1113
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1114
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
1115
|
+
try {
|
|
1116
|
+
return fn(...args);
|
|
1117
|
+
} catch (error) {
|
|
1118
|
+
log.catch(error, void 0, {
|
|
1119
|
+
F: __dxlog_file2,
|
|
1120
|
+
L: 16,
|
|
1121
|
+
S: void 0,
|
|
1122
|
+
C: (f, a) => f(...a)
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1100
1128
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1101
1129
|
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
1130
|
"& .cm-comment": {
|
|
1112
|
-
backgroundColor:
|
|
1131
|
+
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1113
1132
|
},
|
|
1114
1133
|
"& .cm-comment-active": {
|
|
1115
|
-
backgroundColor:
|
|
1134
|
+
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1116
1135
|
}
|
|
1117
1136
|
});
|
|
1118
1137
|
var marks = {
|
|
@@ -1146,7 +1165,7 @@ var commentsStateField = StateField2.define({
|
|
|
1146
1165
|
ranges: []
|
|
1147
1166
|
}),
|
|
1148
1167
|
update: (value, tr) => {
|
|
1149
|
-
const cursorConverter3 = tr.state.facet(
|
|
1168
|
+
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1150
1169
|
for (const effect of tr.effects) {
|
|
1151
1170
|
if (effect.is(setSelection)) {
|
|
1152
1171
|
return {
|
|
@@ -1157,7 +1176,7 @@ var commentsStateField = StateField2.define({
|
|
|
1157
1176
|
if (effect.is(setCommentRange)) {
|
|
1158
1177
|
const { comments: comments2 } = effect.value;
|
|
1159
1178
|
const ranges = comments2.map((comment) => {
|
|
1160
|
-
const range = getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1179
|
+
const range = Cursor.getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1161
1180
|
return range && {
|
|
1162
1181
|
...comment,
|
|
1163
1182
|
...range
|
|
@@ -1195,42 +1214,14 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1195
1214
|
}).filter(nonNullable) ?? [];
|
|
1196
1215
|
return Decoration3.set(decorations);
|
|
1197
1216
|
});
|
|
1198
|
-
var BookmarkWidget = class extends WidgetType2 {
|
|
1199
|
-
constructor(_anchor, _id, _handleClick) {
|
|
1200
|
-
super();
|
|
1201
|
-
this._anchor = _anchor;
|
|
1202
|
-
this._id = _id;
|
|
1203
|
-
this._handleClick = _handleClick;
|
|
1204
|
-
invariant2(this._id, void 0, {
|
|
1205
|
-
F: __dxlog_file3,
|
|
1206
|
-
L: 169,
|
|
1207
|
-
S: this,
|
|
1208
|
-
A: [
|
|
1209
|
-
"this._id",
|
|
1210
|
-
""
|
|
1211
|
-
]
|
|
1212
|
-
});
|
|
1213
|
-
}
|
|
1214
|
-
eq(other) {
|
|
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();
|
|
1223
|
-
}
|
|
1224
|
-
return span;
|
|
1225
|
-
}
|
|
1226
|
-
};
|
|
1227
1217
|
var comments = (options = {}) => {
|
|
1218
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1228
1219
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
1220
|
const createCommentThread = (view) => {
|
|
1230
|
-
const cursorConverter3 = view.state.facet(
|
|
1221
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1231
1222
|
invariant2(options.onCreate, void 0, {
|
|
1232
1223
|
F: __dxlog_file3,
|
|
1233
|
-
L:
|
|
1224
|
+
L: 177,
|
|
1234
1225
|
S: void 0,
|
|
1235
1226
|
A: [
|
|
1236
1227
|
"options.onCreate",
|
|
@@ -1241,12 +1232,12 @@ var comments = (options = {}) => {
|
|
|
1241
1232
|
if (from === to) {
|
|
1242
1233
|
return false;
|
|
1243
1234
|
}
|
|
1244
|
-
const
|
|
1235
|
+
const cursor = Cursor.getCursorFromRange(cursorConverter3, {
|
|
1245
1236
|
from,
|
|
1246
1237
|
to
|
|
1247
1238
|
});
|
|
1248
|
-
if (
|
|
1249
|
-
const id = callbackWrapper(options.onCreate)(
|
|
1239
|
+
if (cursor) {
|
|
1240
|
+
const id = callbackWrapper(options.onCreate)(cursor, view.coordsAtPos(from));
|
|
1250
1241
|
if (id) {
|
|
1251
1242
|
view.dispatch({
|
|
1252
1243
|
effects: setSelection.of({
|
|
@@ -1273,35 +1264,7 @@ var comments = (options = {}) => {
|
|
|
1273
1264
|
}
|
|
1274
1265
|
return false;
|
|
1275
1266
|
};
|
|
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(update4) {
|
|
1295
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update4, 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
1267
|
return [
|
|
1304
|
-
bookmarksViewPlugin,
|
|
1305
1268
|
commentsStateField,
|
|
1306
1269
|
highlightDecorations,
|
|
1307
1270
|
styles3,
|
|
@@ -1310,7 +1273,7 @@ var comments = (options = {}) => {
|
|
|
1310
1273
|
//
|
|
1311
1274
|
options.onCreate ? keymap3.of([
|
|
1312
1275
|
{
|
|
1313
|
-
key:
|
|
1276
|
+
key: shortcut,
|
|
1314
1277
|
run: callbackWrapper(createCommentThread)
|
|
1315
1278
|
}
|
|
1316
1279
|
]) : [],
|
|
@@ -1327,7 +1290,7 @@ var comments = (options = {}) => {
|
|
|
1327
1290
|
above: true,
|
|
1328
1291
|
create: () => {
|
|
1329
1292
|
const el = document.createElement("div");
|
|
1330
|
-
options.onHover?.(el);
|
|
1293
|
+
options.onHover?.(el, shortcut);
|
|
1331
1294
|
return {
|
|
1332
1295
|
dom: el,
|
|
1333
1296
|
offset: {
|
|
@@ -1348,27 +1311,27 @@ var comments = (options = {}) => {
|
|
|
1348
1311
|
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1349
1312
|
//
|
|
1350
1313
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1351
|
-
const cursorConverter3 = view.state.facet(
|
|
1314
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1352
1315
|
{
|
|
1353
1316
|
let mod = false;
|
|
1354
1317
|
const { active, ranges } = state.field(commentsStateField);
|
|
1355
1318
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1356
1319
|
ranges.forEach((range) => {
|
|
1357
1320
|
if (from2 === to2) {
|
|
1358
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1321
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1359
1322
|
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
1323
|
log2.info("deleted comment", {
|
|
1361
1324
|
thread: range.id
|
|
1362
1325
|
}, {
|
|
1363
1326
|
F: __dxlog_file3,
|
|
1364
|
-
L:
|
|
1327
|
+
L: 274,
|
|
1365
1328
|
S: void 0,
|
|
1366
1329
|
C: (f, a) => f(...a)
|
|
1367
1330
|
});
|
|
1368
1331
|
}
|
|
1369
1332
|
}
|
|
1370
1333
|
if (from <= range.to) {
|
|
1371
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1334
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
1335
|
Object.assign(range, newRange);
|
|
1373
1336
|
mod = true;
|
|
1374
1337
|
}
|
|
@@ -1417,35 +1380,17 @@ var comments = (options = {}) => {
|
|
|
1417
1380
|
})
|
|
1418
1381
|
];
|
|
1419
1382
|
};
|
|
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 && to ? {
|
|
1433
|
-
from,
|
|
1434
|
-
to
|
|
1435
|
-
} : void 0;
|
|
1436
|
-
};
|
|
1437
1383
|
|
|
1438
1384
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
-
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator
|
|
1440
|
-
import get4 from "lodash.get";
|
|
1385
|
+
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1441
1386
|
var styles4 = EditorView6.baseTheme({
|
|
1442
1387
|
"& .cm-hr": {
|
|
1443
1388
|
// TODO(burdon): ???
|
|
1444
1389
|
// Note that block-level decorations should not have vertical margins,
|
|
1445
|
-
borderBottom: `1px solid ${
|
|
1390
|
+
borderBottom: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1446
1391
|
}
|
|
1447
1392
|
});
|
|
1448
|
-
var HorizontalRuleWidget = class extends
|
|
1393
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1449
1394
|
constructor(_pos) {
|
|
1450
1395
|
super();
|
|
1451
1396
|
this._pos = _pos;
|
|
@@ -1459,7 +1404,7 @@ var HorizontalRuleWidget = class extends WidgetType3 {
|
|
|
1459
1404
|
return el;
|
|
1460
1405
|
}
|
|
1461
1406
|
};
|
|
1462
|
-
var placeholderMatcher = new
|
|
1407
|
+
var placeholderMatcher = new MatchDecorator({
|
|
1463
1408
|
regexp: /^---$/g,
|
|
1464
1409
|
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
1410
|
widget: new HorizontalRuleWidget(pos)
|
|
@@ -1467,12 +1412,12 @@ var placeholderMatcher = new MatchDecorator2({
|
|
|
1467
1412
|
});
|
|
1468
1413
|
var hr = () => [
|
|
1469
1414
|
styles4,
|
|
1470
|
-
|
|
1415
|
+
ViewPlugin4.fromClass(class {
|
|
1471
1416
|
constructor(view) {
|
|
1472
1417
|
this.rules = placeholderMatcher.createDeco(view);
|
|
1473
1418
|
}
|
|
1474
|
-
update(
|
|
1475
|
-
this.rules = placeholderMatcher.updateDeco(
|
|
1419
|
+
update(update2) {
|
|
1420
|
+
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1476
1421
|
}
|
|
1477
1422
|
}, {
|
|
1478
1423
|
decorations: (instance) => instance.rules,
|
|
@@ -1485,17 +1430,39 @@ var hr = () => [
|
|
|
1485
1430
|
|
|
1486
1431
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
1432
|
import { syntaxTree } from "@codemirror/language";
|
|
1488
|
-
import {
|
|
1489
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as
|
|
1433
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1434
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1490
1435
|
var image = (options = {}) => {
|
|
1491
1436
|
return StateField3.define({
|
|
1492
|
-
create: (state) =>
|
|
1493
|
-
|
|
1437
|
+
create: (state) => {
|
|
1438
|
+
return Decoration5.set(buildDecorations(0, state.doc.length, state));
|
|
1439
|
+
},
|
|
1440
|
+
update: (value, tr) => {
|
|
1441
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1442
|
+
return value;
|
|
1443
|
+
}
|
|
1444
|
+
const cursor = tr.state.selection.main.head;
|
|
1445
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1446
|
+
let from = Math.min(cursor, oldCursor);
|
|
1447
|
+
let to = Math.max(cursor, oldCursor);
|
|
1448
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1449
|
+
from = Math.min(from, fromB);
|
|
1450
|
+
to = Math.max(to, toB);
|
|
1451
|
+
});
|
|
1452
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1453
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1454
|
+
return value.map(tr.changes).update({
|
|
1455
|
+
filterFrom: from,
|
|
1456
|
+
filterTo: to,
|
|
1457
|
+
filter: () => false,
|
|
1458
|
+
add: buildDecorations(from, to, tr.state)
|
|
1459
|
+
});
|
|
1460
|
+
},
|
|
1494
1461
|
provide: (field) => EditorView7.decorations.from(field)
|
|
1495
1462
|
});
|
|
1496
1463
|
};
|
|
1497
|
-
var
|
|
1498
|
-
const
|
|
1464
|
+
var buildDecorations = (from, to, state) => {
|
|
1465
|
+
const decorations = [];
|
|
1499
1466
|
const cursor = state.selection.main.head;
|
|
1500
1467
|
syntaxTree(state).iterate({
|
|
1501
1468
|
enter: (node) => {
|
|
@@ -1504,22 +1471,23 @@ var update = (state, options) => {
|
|
|
1504
1471
|
if (urlNode) {
|
|
1505
1472
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1506
1473
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1507
|
-
|
|
1474
|
+
decorations.push(Decoration5.replace({
|
|
1508
1475
|
block: true,
|
|
1509
1476
|
widget: new ImageWidget(url)
|
|
1510
|
-
}));
|
|
1477
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1511
1478
|
}
|
|
1512
1479
|
}
|
|
1513
|
-
}
|
|
1480
|
+
},
|
|
1481
|
+
from,
|
|
1482
|
+
to
|
|
1514
1483
|
});
|
|
1515
|
-
return
|
|
1484
|
+
return decorations;
|
|
1516
1485
|
};
|
|
1517
|
-
var ImageWidget = class extends
|
|
1486
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1518
1487
|
constructor(_url) {
|
|
1519
1488
|
super();
|
|
1520
1489
|
this._url = _url;
|
|
1521
1490
|
}
|
|
1522
|
-
// TODO(burdon): Does this need to be unique for each position?
|
|
1523
1491
|
eq(other) {
|
|
1524
1492
|
return this._url === other._url;
|
|
1525
1493
|
}
|
|
@@ -1527,22 +1495,29 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1527
1495
|
const img = document.createElement("img");
|
|
1528
1496
|
img.setAttribute("src", this._url);
|
|
1529
1497
|
img.setAttribute("class", "cm-image");
|
|
1498
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1530
1499
|
return img;
|
|
1531
1500
|
}
|
|
1532
1501
|
};
|
|
1533
1502
|
|
|
1534
1503
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1535
1504
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1536
|
-
import { RangeSetBuilder
|
|
1537
|
-
import { Decoration as Decoration6,
|
|
1505
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1506
|
+
import { Decoration as Decoration6, WidgetType as WidgetType4, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1538
1507
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1539
|
-
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
1540
1508
|
var link = (options = {}) => {
|
|
1541
1509
|
const extensions = [
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1510
|
+
ViewPlugin5.fromClass(class {
|
|
1511
|
+
constructor(view) {
|
|
1512
|
+
this.decorations = buildDecorations2(view, options);
|
|
1513
|
+
}
|
|
1514
|
+
update(update2) {
|
|
1515
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1516
|
+
this.decorations = buildDecorations2(update2.view, options);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
}, {
|
|
1520
|
+
decorations: (v) => v.decorations
|
|
1546
1521
|
})
|
|
1547
1522
|
];
|
|
1548
1523
|
if (options.onHover) {
|
|
@@ -1550,35 +1525,25 @@ var link = (options = {}) => {
|
|
|
1550
1525
|
// https://codemirror.net/examples/tooltip
|
|
1551
1526
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1552
1527
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1553
|
-
hoverTooltip2((view, pos) => {
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1556
|
-
let
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
match = void 0;
|
|
1562
|
-
break;
|
|
1563
|
-
}
|
|
1564
|
-
idx = text.indexOf(match[0]);
|
|
1565
|
-
if (p >= idx && p < idx + match[0].length) {
|
|
1566
|
-
break;
|
|
1567
|
-
}
|
|
1568
|
-
idx += match[0].length;
|
|
1569
|
-
} while (true);
|
|
1570
|
-
if (!match) {
|
|
1528
|
+
hoverTooltip2((view, pos, side) => {
|
|
1529
|
+
const syntax = syntaxTree2(view.state).resolveInner(pos, side);
|
|
1530
|
+
let link2 = null;
|
|
1531
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1532
|
+
link2 = node.name === "Link" ? node : null;
|
|
1533
|
+
}
|
|
1534
|
+
const url = link2 && link2.getChild("URL");
|
|
1535
|
+
if (!url || !link2) {
|
|
1571
1536
|
return null;
|
|
1572
1537
|
}
|
|
1573
|
-
const
|
|
1538
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1574
1539
|
return {
|
|
1575
|
-
pos:
|
|
1576
|
-
end:
|
|
1540
|
+
pos: link2.from,
|
|
1541
|
+
end: link2.to,
|
|
1577
1542
|
above: true,
|
|
1578
1543
|
create: () => {
|
|
1579
1544
|
const el = document.createElement("div");
|
|
1580
1545
|
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1581
|
-
options.onHover(el,
|
|
1546
|
+
options.onHover(el, urlText);
|
|
1582
1547
|
return {
|
|
1583
1548
|
dom: el,
|
|
1584
1549
|
offset: {
|
|
@@ -1593,15 +1558,14 @@ var link = (options = {}) => {
|
|
|
1593
1558
|
}
|
|
1594
1559
|
return extensions;
|
|
1595
1560
|
};
|
|
1596
|
-
var LinkButton = class extends
|
|
1597
|
-
constructor(
|
|
1561
|
+
var LinkButton = class extends WidgetType4 {
|
|
1562
|
+
constructor(_url, _onAttach) {
|
|
1598
1563
|
super();
|
|
1599
|
-
this._pos = _pos;
|
|
1600
1564
|
this._url = _url;
|
|
1601
1565
|
this._onAttach = _onAttach;
|
|
1602
1566
|
}
|
|
1603
1567
|
eq(other) {
|
|
1604
|
-
return this.
|
|
1568
|
+
return this._url === other._url;
|
|
1605
1569
|
}
|
|
1606
1570
|
toDOM(view) {
|
|
1607
1571
|
const el = document.createElement("span");
|
|
@@ -1609,7 +1573,7 @@ var LinkButton = class extends WidgetType5 {
|
|
|
1609
1573
|
return el;
|
|
1610
1574
|
}
|
|
1611
1575
|
};
|
|
1612
|
-
var LinkText = class extends
|
|
1576
|
+
var LinkText = class extends WidgetType4 {
|
|
1613
1577
|
constructor(_text, _url) {
|
|
1614
1578
|
super();
|
|
1615
1579
|
this._text = _text;
|
|
@@ -1638,46 +1602,51 @@ var LinkText = class extends WidgetType5 {
|
|
|
1638
1602
|
return link2;
|
|
1639
1603
|
}
|
|
1640
1604
|
};
|
|
1641
|
-
var
|
|
1642
|
-
const builder = new
|
|
1605
|
+
var buildDecorations2 = (view, options) => {
|
|
1606
|
+
const builder = new RangeSetBuilder();
|
|
1607
|
+
const { state } = view;
|
|
1643
1608
|
const cursor = state.selection.main.head;
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1609
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1610
|
+
syntaxTree2(state).iterate({
|
|
1611
|
+
enter: (node) => {
|
|
1612
|
+
if (node.name === "Link") {
|
|
1613
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
1614
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1615
|
+
const urlNode = node.node.getChild("URL");
|
|
1616
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1617
|
+
if (!url) {
|
|
1618
|
+
return false;
|
|
1619
|
+
}
|
|
1620
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1621
|
+
builder.add(node.from, node.to, Decoration6.replace({
|
|
1622
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
1623
|
+
}));
|
|
1624
|
+
}
|
|
1625
|
+
if (options.onRender) {
|
|
1626
|
+
builder.add(node.to, node.to, Decoration6.replace({
|
|
1627
|
+
widget: new LinkButton(url, options.onRender)
|
|
1628
|
+
}));
|
|
1629
|
+
}
|
|
1652
1630
|
return false;
|
|
1653
1631
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
if (options.onRender) {
|
|
1660
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1661
|
-
widget: new LinkButton(node.from, url, options.onRender)
|
|
1662
|
-
}));
|
|
1663
|
-
}
|
|
1664
|
-
return false;
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
});
|
|
1632
|
+
},
|
|
1633
|
+
from,
|
|
1634
|
+
to
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1668
1637
|
return builder.finish();
|
|
1669
1638
|
};
|
|
1670
1639
|
|
|
1671
1640
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1672
|
-
import { EditorView as
|
|
1641
|
+
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1673
1642
|
var listener = ({ onFocus, onChange }) => {
|
|
1674
1643
|
const extensions = [];
|
|
1675
|
-
onFocus && extensions.push(
|
|
1644
|
+
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1676
1645
|
onFocus(focused);
|
|
1677
1646
|
return null;
|
|
1678
1647
|
}));
|
|
1679
|
-
onChange && extensions.push(
|
|
1680
|
-
onChange(
|
|
1648
|
+
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1649
|
+
onChange(update2.state.doc.toString());
|
|
1681
1650
|
}));
|
|
1682
1651
|
return extensions;
|
|
1683
1652
|
};
|
|
@@ -1685,27 +1654,25 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1685
1654
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1686
1655
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1687
1656
|
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1688
|
-
import { markdownLanguage as
|
|
1657
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1689
1658
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1690
1659
|
import { languages } from "@codemirror/language-data";
|
|
1691
1660
|
import { searchKeymap } from "@codemirror/search";
|
|
1692
1661
|
import { EditorState } from "@codemirror/state";
|
|
1693
1662
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1694
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1663
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1695
1664
|
|
|
1696
1665
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1697
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
1666
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1698
1667
|
import { HighlightStyle } from "@codemirror/language";
|
|
1699
1668
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1700
1669
|
import { Table } from "@lezer/markdown";
|
|
1701
|
-
import get5 from "lodash.get";
|
|
1702
1670
|
var markdownTags = {
|
|
1703
1671
|
Blockquote: Tag.define(),
|
|
1704
1672
|
CodeMark: Tag.define(),
|
|
1705
1673
|
CodeText: Tag.define(),
|
|
1706
1674
|
EmphasisMark: Tag.define(),
|
|
1707
1675
|
HeaderMark: Tag.define(),
|
|
1708
|
-
// HorizontalRule: Tag.define(),
|
|
1709
1676
|
InlineCode: Tag.define(),
|
|
1710
1677
|
LinkLabel: Tag.define(),
|
|
1711
1678
|
LinkReference: Tag.define(),
|
|
@@ -1869,12 +1836,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1869
1836
|
],
|
|
1870
1837
|
class: blockquote
|
|
1871
1838
|
},
|
|
1872
|
-
// TODO(burdon): Replace with extension.
|
|
1873
|
-
// {
|
|
1874
|
-
// tag: [markdownTags.HorizontalRule],
|
|
1875
|
-
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1876
|
-
// },
|
|
1877
|
-
// TODO(burdon): Only if being edited.
|
|
1878
1839
|
{
|
|
1879
1840
|
tag: [
|
|
1880
1841
|
markdownTags.TableCell
|
|
@@ -1882,9 +1843,9 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1882
1843
|
class: "font-mono"
|
|
1883
1844
|
}
|
|
1884
1845
|
], {
|
|
1885
|
-
scope:
|
|
1846
|
+
scope: markdownLanguage2,
|
|
1886
1847
|
all: {
|
|
1887
|
-
fontFamily:
|
|
1848
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1888
1849
|
}
|
|
1889
1850
|
});
|
|
1890
1851
|
};
|
|
@@ -1894,7 +1855,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1894
1855
|
return [
|
|
1895
1856
|
EditorState.allowMultipleSelections.of(true),
|
|
1896
1857
|
EditorState.tabSize.of(2),
|
|
1897
|
-
|
|
1858
|
+
EditorView9.lineWrapping,
|
|
1898
1859
|
customKeymap(),
|
|
1899
1860
|
bracketMatching2(),
|
|
1900
1861
|
closeBrackets2(),
|
|
@@ -1914,7 +1875,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1914
1875
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1915
1876
|
// https://github.github.com/gfm
|
|
1916
1877
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1917
|
-
base:
|
|
1878
|
+
base: markdownLanguage3,
|
|
1918
1879
|
// Languages for syntax highlighting fenced code blocks.
|
|
1919
1880
|
codeLanguages: languages,
|
|
1920
1881
|
// Parser extensions.
|
|
@@ -1965,24 +1926,19 @@ var mention = ({ onSearch }) => {
|
|
|
1965
1926
|
});
|
|
1966
1927
|
};
|
|
1967
1928
|
|
|
1968
|
-
// packages/ui/react-ui-editor/src/extensions/mermaid.ts
|
|
1969
|
-
var mermaid = () => {
|
|
1970
|
-
return [];
|
|
1971
|
-
};
|
|
1972
|
-
|
|
1973
1929
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1974
1930
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1975
|
-
import { RangeSetBuilder as
|
|
1976
|
-
import { Decoration as Decoration7, EditorView as
|
|
1931
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1932
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1977
1933
|
var table = (options = {}) => {
|
|
1978
|
-
return
|
|
1979
|
-
create: (state) =>
|
|
1980
|
-
update: (_, tr) =>
|
|
1981
|
-
provide: (field) =>
|
|
1934
|
+
return StateField4.define({
|
|
1935
|
+
create: (state) => update(state, options),
|
|
1936
|
+
update: (_, tr) => update(tr.state, options),
|
|
1937
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1982
1938
|
});
|
|
1983
1939
|
};
|
|
1984
|
-
var
|
|
1985
|
-
const builder = new
|
|
1940
|
+
var update = (state, options) => {
|
|
1941
|
+
const builder = new RangeSetBuilder2();
|
|
1986
1942
|
const cursor = state.selection.main.head;
|
|
1987
1943
|
const tables = [];
|
|
1988
1944
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2023,7 +1979,6 @@ var update3 = (state, options) => {
|
|
|
2023
1979
|
tables.forEach((table2) => {
|
|
2024
1980
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2025
1981
|
hide && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
2026
|
-
block: true,
|
|
2027
1982
|
widget: new TableWidget(table2)
|
|
2028
1983
|
}));
|
|
2029
1984
|
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
@@ -2032,13 +1987,13 @@ var update3 = (state, options) => {
|
|
|
2032
1987
|
});
|
|
2033
1988
|
return builder.finish();
|
|
2034
1989
|
};
|
|
2035
|
-
var TableWidget = class extends
|
|
1990
|
+
var TableWidget = class extends WidgetType5 {
|
|
2036
1991
|
constructor(_table) {
|
|
2037
1992
|
super();
|
|
2038
1993
|
this._table = _table;
|
|
2039
1994
|
}
|
|
2040
1995
|
eq(other) {
|
|
2041
|
-
return this._table.
|
|
1996
|
+
return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
|
|
2042
1997
|
}
|
|
2043
1998
|
toDOM(view) {
|
|
2044
1999
|
const table2 = document.createElement("table");
|
|
@@ -2064,91 +2019,91 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2064
2019
|
}
|
|
2065
2020
|
return table2;
|
|
2066
2021
|
}
|
|
2022
|
+
ignoreEvent(e) {
|
|
2023
|
+
return !/^mouse/.test(e.type);
|
|
2024
|
+
}
|
|
2067
2025
|
};
|
|
2068
2026
|
|
|
2069
2027
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2070
|
-
import {
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
}
|
|
2076
|
-
});
|
|
2077
|
-
var CheckboxWidget = class extends WidgetType7 {
|
|
2078
|
-
constructor(_pos, _checked, _indent, _onCheck) {
|
|
2028
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2029
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
2030
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2031
|
+
var CheckboxWidget = class extends WidgetType6 {
|
|
2032
|
+
constructor(_checked) {
|
|
2079
2033
|
super();
|
|
2080
|
-
this._pos = _pos;
|
|
2081
2034
|
this._checked = _checked;
|
|
2082
|
-
this._indent = _indent;
|
|
2083
|
-
this._onCheck = _onCheck;
|
|
2084
2035
|
}
|
|
2085
2036
|
eq(other) {
|
|
2086
|
-
return this.
|
|
2037
|
+
return this._checked === other._checked;
|
|
2087
2038
|
}
|
|
2088
2039
|
toDOM(view) {
|
|
2089
|
-
const
|
|
2090
|
-
wrap.className = "cm-task-item";
|
|
2091
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2092
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2093
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2040
|
+
const input = document.createElement("input");
|
|
2094
2041
|
input.type = "checkbox";
|
|
2095
2042
|
input.checked = this._checked;
|
|
2096
|
-
if (
|
|
2043
|
+
if (view.state.readOnly) {
|
|
2097
2044
|
input.setAttribute("disabled", "true");
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2045
|
+
} else {
|
|
2046
|
+
input.onmousedown = (event) => {
|
|
2047
|
+
const pos = view.posAtDOM(input);
|
|
2048
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2049
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2050
|
+
view.dispatch({
|
|
2051
|
+
changes: {
|
|
2052
|
+
from: pos + 1,
|
|
2053
|
+
to: pos + 2,
|
|
2054
|
+
insert: this._checked ? " " : "x"
|
|
2055
|
+
}
|
|
2056
|
+
});
|
|
2057
|
+
event.preventDefault();
|
|
2058
|
+
}
|
|
2103
2059
|
};
|
|
2104
2060
|
}
|
|
2105
|
-
return
|
|
2061
|
+
return input;
|
|
2106
2062
|
}
|
|
2107
2063
|
ignoreEvent() {
|
|
2108
2064
|
return false;
|
|
2109
2065
|
}
|
|
2110
2066
|
};
|
|
2067
|
+
var checkedDeco = Decoration8.replace({
|
|
2068
|
+
widget: new CheckboxWidget(true)
|
|
2069
|
+
});
|
|
2070
|
+
var uncheckedDeco = Decoration8.replace({
|
|
2071
|
+
widget: new CheckboxWidget(false)
|
|
2072
|
+
});
|
|
2111
2073
|
var tasklist = (options = {}) => {
|
|
2112
|
-
|
|
2113
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2114
|
-
decoration: (match, view, pos) => {
|
|
2115
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2116
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2117
|
-
return Decoration8.replace({
|
|
2118
|
-
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2119
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2120
|
-
view.dispatch({
|
|
2121
|
-
changes: {
|
|
2122
|
-
from: idx,
|
|
2123
|
-
to: idx + 1,
|
|
2124
|
-
insert: checked2 ? "x" : " "
|
|
2125
|
-
},
|
|
2126
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2127
|
-
selection: {
|
|
2128
|
-
anchor: idx + 3
|
|
2129
|
-
}
|
|
2130
|
-
});
|
|
2131
|
-
})
|
|
2132
|
-
});
|
|
2133
|
-
}
|
|
2134
|
-
});
|
|
2135
|
-
const tasks = ViewPlugin6.fromClass(class {
|
|
2074
|
+
return ViewPlugin6.fromClass(class {
|
|
2136
2075
|
constructor(view) {
|
|
2137
|
-
this.
|
|
2076
|
+
this.decorations = buildDecorations3(view);
|
|
2138
2077
|
}
|
|
2139
|
-
update(
|
|
2140
|
-
|
|
2078
|
+
update(update2) {
|
|
2079
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2080
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2081
|
+
}
|
|
2141
2082
|
}
|
|
2142
2083
|
}, {
|
|
2143
|
-
decorations: (
|
|
2144
|
-
provide: (plugin) =>
|
|
2145
|
-
return view.plugin(plugin)?.
|
|
2084
|
+
decorations: (v) => v.decorations,
|
|
2085
|
+
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2086
|
+
return view.plugin(plugin)?.decorations || Decoration8.none;
|
|
2146
2087
|
})
|
|
2147
2088
|
});
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2089
|
+
};
|
|
2090
|
+
var buildDecorations3 = (view) => {
|
|
2091
|
+
const builder = new RangeSetBuilder3();
|
|
2092
|
+
const { state } = view;
|
|
2093
|
+
const cursor = state.selection.main.head;
|
|
2094
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2095
|
+
syntaxTree4(state).iterate({
|
|
2096
|
+
enter: (node) => {
|
|
2097
|
+
if (node.name === "TaskMarker" && (cursor < node.from || cursor > node.to)) {
|
|
2098
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2099
|
+
builder.add(node.from, node.to, checked ? checkedDeco : uncheckedDeco);
|
|
2100
|
+
}
|
|
2101
|
+
},
|
|
2102
|
+
from,
|
|
2103
|
+
to
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
return builder.finish();
|
|
2152
2107
|
};
|
|
2153
2108
|
|
|
2154
2109
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
@@ -2225,12 +2180,12 @@ var cursorConverter2 = (text) => ({
|
|
|
2225
2180
|
|
|
2226
2181
|
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2227
2182
|
var yjs = (content, awareness2) => [
|
|
2228
|
-
|
|
2183
|
+
Cursor.converter.of(cursorConverter2(content)),
|
|
2229
2184
|
yCollab(content, awareness2)
|
|
2230
2185
|
];
|
|
2231
2186
|
|
|
2232
2187
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2233
|
-
import
|
|
2188
|
+
import get3 from "lodash.get";
|
|
2234
2189
|
var defaultTheme = {
|
|
2235
2190
|
//
|
|
2236
2191
|
// Main layout:
|
|
@@ -2259,21 +2214,21 @@ var defaultTheme = {
|
|
|
2259
2214
|
"&.cm-focused": {
|
|
2260
2215
|
outline: "none"
|
|
2261
2216
|
},
|
|
2262
|
-
"
|
|
2217
|
+
".cm-scroller": {
|
|
2263
2218
|
overflow: "visible",
|
|
2264
|
-
fontFamily:
|
|
2219
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2265
2220
|
},
|
|
2266
|
-
"
|
|
2221
|
+
".cm-content": {
|
|
2267
2222
|
padding: 0,
|
|
2268
2223
|
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2269
2224
|
fontSize: "16px"
|
|
2270
2225
|
},
|
|
2271
2226
|
"&light .cm-content": {
|
|
2272
|
-
color:
|
|
2227
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
2273
2228
|
caretColor: "black"
|
|
2274
2229
|
},
|
|
2275
2230
|
"&dark .cm-content": {
|
|
2276
|
-
color:
|
|
2231
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
2277
2232
|
caretColor: "white"
|
|
2278
2233
|
},
|
|
2279
2234
|
//
|
|
@@ -2285,158 +2240,120 @@ var defaultTheme = {
|
|
|
2285
2240
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2286
2241
|
borderLeft: "2px solid white"
|
|
2287
2242
|
},
|
|
2288
|
-
"
|
|
2243
|
+
".cm-placeholder": {
|
|
2289
2244
|
fontWeight: 100
|
|
2290
2245
|
},
|
|
2291
2246
|
//
|
|
2292
2247
|
// line
|
|
2293
2248
|
//
|
|
2294
|
-
"
|
|
2249
|
+
".cm-line": {
|
|
2295
2250
|
paddingInline: 0
|
|
2296
2251
|
},
|
|
2297
|
-
"
|
|
2252
|
+
".cm-activeLine": {
|
|
2298
2253
|
background: "inherit"
|
|
2299
2254
|
},
|
|
2300
2255
|
//
|
|
2301
2256
|
// Selection
|
|
2302
2257
|
//
|
|
2303
2258
|
"&light .cm-selectionBackground": {
|
|
2304
|
-
background:
|
|
2259
|
+
background: get3(tokens, "extend.colors.primary.100")
|
|
2305
2260
|
},
|
|
2306
2261
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2307
|
-
background:
|
|
2262
|
+
background: get3(tokens, "extend.colors.primary.200")
|
|
2308
2263
|
},
|
|
2309
2264
|
"&dark .cm-selectionBackground": {
|
|
2310
|
-
background:
|
|
2265
|
+
background: get3(tokens, "extend.colors.primary.700")
|
|
2311
2266
|
},
|
|
2312
2267
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2313
|
-
background:
|
|
2268
|
+
background: get3(tokens, "extend.colors.primary.600")
|
|
2314
2269
|
},
|
|
2315
2270
|
//
|
|
2316
2271
|
// Search
|
|
2317
2272
|
//
|
|
2318
2273
|
"&light .cm-searchMatch": {
|
|
2319
|
-
backgroundColor:
|
|
2274
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2320
2275
|
},
|
|
2321
2276
|
"&dark .cm-searchMatch": {
|
|
2322
|
-
backgroundColor:
|
|
2323
|
-
},
|
|
2324
|
-
//
|
|
2325
|
-
// collaboration
|
|
2326
|
-
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
2327
|
-
//
|
|
2328
|
-
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
2329
|
-
mixBlendMode: "multiply"
|
|
2330
|
-
},
|
|
2331
|
-
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2332
|
-
mixBlendMode: "screen"
|
|
2333
|
-
},
|
|
2334
|
-
"& .cm-ySelectionInfo": {
|
|
2335
|
-
padding: "2px 4px",
|
|
2336
|
-
marginBlockStart: "-4px"
|
|
2337
|
-
},
|
|
2338
|
-
"& .cm-ySelection, & .cm-selectionMatch": {
|
|
2339
|
-
paddingBlockStart: ".15em",
|
|
2340
|
-
paddingBlockEnd: ".15em"
|
|
2341
|
-
},
|
|
2342
|
-
"& .cm-ySelectionCaret": {
|
|
2343
|
-
display: "inline-block",
|
|
2344
|
-
insetBlockStart: ".1em",
|
|
2345
|
-
blockSize: "1.4em",
|
|
2346
|
-
verticalAlign: "top"
|
|
2347
|
-
},
|
|
2348
|
-
"& .cm-yLineSelection": {
|
|
2349
|
-
margin: 0
|
|
2277
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2350
2278
|
},
|
|
2351
2279
|
//
|
|
2352
2280
|
// link
|
|
2353
2281
|
//
|
|
2354
|
-
"
|
|
2355
|
-
color:
|
|
2282
|
+
".cm-link": {
|
|
2283
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
2356
2284
|
textDecorationLine: "underline",
|
|
2357
2285
|
textDecorationThickness: "1px",
|
|
2358
2286
|
textUnderlineOffset: "2px",
|
|
2359
2287
|
borderRadius: ".125rem",
|
|
2360
|
-
fontFamily:
|
|
2288
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2361
2289
|
},
|
|
2362
2290
|
//
|
|
2363
2291
|
// tooltip
|
|
2364
2292
|
//
|
|
2365
|
-
"
|
|
2293
|
+
".cm-tooltip": {
|
|
2366
2294
|
border: "none"
|
|
2367
2295
|
},
|
|
2368
|
-
"
|
|
2296
|
+
".cm-tooltip-below": {},
|
|
2369
2297
|
//
|
|
2370
2298
|
// autocomplete
|
|
2371
2299
|
//
|
|
2372
|
-
"
|
|
2300
|
+
".cm-tooltip-autocomplete": {
|
|
2373
2301
|
marginTop: "4px",
|
|
2374
2302
|
marginLeft: "-3px"
|
|
2375
2303
|
},
|
|
2376
|
-
"
|
|
2377
|
-
"
|
|
2378
|
-
"
|
|
2304
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
2305
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2306
|
+
".cm-completionIcon": {
|
|
2379
2307
|
display: "none"
|
|
2380
2308
|
},
|
|
2381
|
-
"
|
|
2382
|
-
fontFamily:
|
|
2309
|
+
".cm-completionLabel": {
|
|
2310
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2383
2311
|
},
|
|
2384
|
-
"
|
|
2312
|
+
".cm-completionMatchedText": {
|
|
2385
2313
|
textDecoration: "none"
|
|
2386
2314
|
},
|
|
2387
2315
|
//
|
|
2388
|
-
// widgets
|
|
2389
|
-
//
|
|
2390
|
-
"& .cm-widgetBuffer": {
|
|
2391
|
-
display: "none",
|
|
2392
|
-
height: 0
|
|
2393
|
-
},
|
|
2394
|
-
//
|
|
2395
2316
|
// table
|
|
2396
2317
|
//
|
|
2397
|
-
"
|
|
2398
|
-
fontFamily: `${
|
|
2318
|
+
".cm-table *": {
|
|
2319
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2399
2320
|
textDecoration: "none !important"
|
|
2400
2321
|
},
|
|
2401
|
-
"
|
|
2322
|
+
".cm-table-head": {
|
|
2402
2323
|
padding: "2px 16px 2px 0px",
|
|
2403
|
-
borderBottom: `1px solid ${
|
|
2324
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2404
2325
|
fontWeight: 100,
|
|
2405
2326
|
textAlign: "left",
|
|
2406
|
-
color:
|
|
2327
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
2407
2328
|
},
|
|
2408
|
-
"
|
|
2329
|
+
".cm-table-cell": {
|
|
2409
2330
|
padding: "2px 16px 2px 0px"
|
|
2410
2331
|
},
|
|
2411
2332
|
//
|
|
2412
2333
|
// image
|
|
2413
2334
|
//
|
|
2414
|
-
"
|
|
2415
|
-
|
|
2335
|
+
".cm-image": {
|
|
2336
|
+
display: "block",
|
|
2337
|
+
height: "0"
|
|
2338
|
+
},
|
|
2339
|
+
".cm-image.cm-loaded-image": {
|
|
2340
|
+
height: "auto",
|
|
2341
|
+
borderTop: "0.5rem solid transparent",
|
|
2342
|
+
borderBottom: "0.5rem solid transparent"
|
|
2416
2343
|
},
|
|
2417
2344
|
//
|
|
2418
2345
|
// font size
|
|
2419
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2346
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2347
|
+
// but it's far more verbose than it needs to be.
|
|
2420
2348
|
//
|
|
2421
|
-
...Object.keys(
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
|
|
2430
|
-
height
|
|
2431
|
-
};
|
|
2432
|
-
acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
|
|
2433
|
-
height
|
|
2434
|
-
};
|
|
2435
|
-
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
|
|
2436
|
-
height
|
|
2437
|
-
};
|
|
2438
|
-
return acc;
|
|
2439
|
-
}, {}),
|
|
2349
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2350
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2351
|
+
//
|
|
2352
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2353
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2354
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2355
|
+
// return acc;
|
|
2356
|
+
// }, {}),
|
|
2440
2357
|
/**
|
|
2441
2358
|
* Panels
|
|
2442
2359
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2453,51 +2370,53 @@ var defaultTheme = {
|
|
|
2453
2370
|
* </div>
|
|
2454
2371
|
* </div
|
|
2455
2372
|
*/
|
|
2456
|
-
"
|
|
2457
|
-
border: `1px solid ${
|
|
2373
|
+
".cm-panels": {
|
|
2374
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2458
2375
|
},
|
|
2459
|
-
"
|
|
2460
|
-
background:
|
|
2461
|
-
fontFamily:
|
|
2376
|
+
".cm-panel": {
|
|
2377
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2378
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2462
2379
|
},
|
|
2463
|
-
"
|
|
2380
|
+
".cm-button": {
|
|
2464
2381
|
margin: "4px",
|
|
2465
|
-
fontFamily:
|
|
2466
|
-
background:
|
|
2382
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2383
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2467
2384
|
backgroundImage: "none",
|
|
2468
2385
|
border: "none",
|
|
2469
2386
|
"&:hover": {
|
|
2470
|
-
background:
|
|
2387
|
+
background: get3(tokens, "extend.colors.neutral.200")
|
|
2471
2388
|
},
|
|
2472
2389
|
"&:active": {
|
|
2473
|
-
background:
|
|
2390
|
+
background: get3(tokens, "extend.colors.neutral.300"),
|
|
2474
2391
|
backgroundImage: "none"
|
|
2475
2392
|
}
|
|
2476
2393
|
},
|
|
2477
|
-
"
|
|
2394
|
+
".cm-panel input[type=checkbox]": {
|
|
2478
2395
|
marginRight: "0.4rem !important"
|
|
2479
2396
|
}
|
|
2480
2397
|
};
|
|
2481
2398
|
var textTheme = {
|
|
2482
|
-
"
|
|
2483
|
-
fontFamily:
|
|
2399
|
+
".cm-scroller": {
|
|
2400
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2484
2401
|
},
|
|
2485
|
-
"
|
|
2486
|
-
fontFamily:
|
|
2402
|
+
".cm-placeholder": {
|
|
2403
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2487
2404
|
}
|
|
2488
2405
|
};
|
|
2489
2406
|
var markdownTheme = {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2407
|
+
".cm-scroller": {
|
|
2408
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2409
|
+
},
|
|
2410
|
+
".cm-placeholder": {
|
|
2411
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2493
2412
|
}
|
|
2494
2413
|
};
|
|
2495
2414
|
var codeTheme = {
|
|
2496
|
-
"
|
|
2497
|
-
fontFamily:
|
|
2415
|
+
".cm-scroller": {
|
|
2416
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2498
2417
|
},
|
|
2499
|
-
"
|
|
2500
|
-
fontFamily:
|
|
2418
|
+
".cm-placeholder": {
|
|
2419
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2501
2420
|
}
|
|
2502
2421
|
};
|
|
2503
2422
|
|
|
@@ -2506,21 +2425,23 @@ var EditorModes = [
|
|
|
2506
2425
|
"default",
|
|
2507
2426
|
"vim"
|
|
2508
2427
|
];
|
|
2509
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2510
|
-
const { themeMode } = useThemeContext();
|
|
2428
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, readonly, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
|
|
2511
2429
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2512
2430
|
tabBehavior: "limited"
|
|
2513
2431
|
});
|
|
2514
|
-
const
|
|
2515
|
-
const
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
state,
|
|
2432
|
+
const { themeMode } = useThemeContext();
|
|
2433
|
+
const rootRef = useRef(null);
|
|
2434
|
+
const [view, setView] = useState(null);
|
|
2435
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2519
2436
|
view
|
|
2520
|
-
|
|
2437
|
+
]);
|
|
2438
|
+
useEffect(() => {
|
|
2439
|
+
if (view && focus) {
|
|
2440
|
+
view.focus();
|
|
2441
|
+
}
|
|
2442
|
+
}, [
|
|
2521
2443
|
view,
|
|
2522
|
-
|
|
2523
|
-
root
|
|
2444
|
+
focus
|
|
2524
2445
|
]);
|
|
2525
2446
|
const { awareness: awareness2, peer } = model;
|
|
2526
2447
|
useEffect(() => {
|
|
@@ -2544,7 +2465,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2544
2465
|
themeMode
|
|
2545
2466
|
]);
|
|
2546
2467
|
useEffect(() => {
|
|
2547
|
-
if (view && comments2
|
|
2468
|
+
if (view && comments2 !== void 0) {
|
|
2548
2469
|
view.dispatch({
|
|
2549
2470
|
effects: setCommentRange.of({
|
|
2550
2471
|
model,
|
|
@@ -2557,20 +2478,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2557
2478
|
comments2
|
|
2558
2479
|
]);
|
|
2559
2480
|
useEffect(() => {
|
|
2560
|
-
if (!
|
|
2481
|
+
if (!model || !rootRef.current) {
|
|
2561
2482
|
return;
|
|
2562
2483
|
}
|
|
2563
|
-
const
|
|
2484
|
+
const state = EditorState2.create({
|
|
2564
2485
|
doc: model.text(),
|
|
2486
|
+
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2487
|
+
selection,
|
|
2565
2488
|
extensions: [
|
|
2566
2489
|
readonly && EditorState2.readOnly.of(readonly),
|
|
2567
2490
|
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
2568
2491
|
editorMode === "vim" && vim(),
|
|
2569
2492
|
// Theme.
|
|
2570
2493
|
// TODO(burdon): Make theme configurable.
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2494
|
+
EditorView12.baseTheme(defaultTheme),
|
|
2495
|
+
EditorView12.theme(theme ?? {}),
|
|
2496
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
|
2574
2497
|
// Storage and replication.
|
|
2575
2498
|
model.extension,
|
|
2576
2499
|
// Custom.
|
|
@@ -2578,19 +2501,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2578
2501
|
].filter(Boolean)
|
|
2579
2502
|
});
|
|
2580
2503
|
view?.destroy();
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
state: state2,
|
|
2585
|
-
parent: root
|
|
2586
|
-
})
|
|
2504
|
+
const newView = new EditorView12({
|
|
2505
|
+
parent: rootRef.current,
|
|
2506
|
+
state
|
|
2587
2507
|
});
|
|
2508
|
+
setView(newView);
|
|
2588
2509
|
return () => {
|
|
2589
|
-
|
|
2590
|
-
|
|
2510
|
+
newView?.destroy();
|
|
2511
|
+
setView(null);
|
|
2591
2512
|
};
|
|
2592
2513
|
}, [
|
|
2593
|
-
|
|
2514
|
+
rootRef,
|
|
2594
2515
|
model,
|
|
2595
2516
|
readonly,
|
|
2596
2517
|
editorMode,
|
|
@@ -2599,12 +2520,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2599
2520
|
const handleKeyUp = useCallback((event) => {
|
|
2600
2521
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2601
2522
|
switch (key) {
|
|
2602
|
-
case "Enter": {
|
|
2603
|
-
view?.contentDOM.focus();
|
|
2604
|
-
break;
|
|
2605
|
-
}
|
|
2606
2523
|
case "Escape": {
|
|
2607
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) &&
|
|
2524
|
+
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
|
|
2608
2525
|
break;
|
|
2609
2526
|
}
|
|
2610
2527
|
}
|
|
@@ -2614,16 +2531,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2614
2531
|
]);
|
|
2615
2532
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2616
2533
|
key: model.id,
|
|
2617
|
-
|
|
2534
|
+
role: "none",
|
|
2535
|
+
ref: rootRef,
|
|
2618
2536
|
tabIndex: 0,
|
|
2619
|
-
|
|
2620
|
-
...
|
|
2621
|
-
|
|
2537
|
+
onKeyUp: handleKeyUp,
|
|
2538
|
+
...slots.root,
|
|
2539
|
+
...editorMode !== "vim" && tabsterDOMAttribute
|
|
2622
2540
|
});
|
|
2623
2541
|
});
|
|
2624
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2542
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = textTheme, slots, ...props }, forwardedRef) => {
|
|
2625
2543
|
const { themeMode } = useThemeContext();
|
|
2626
|
-
const
|
|
2544
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2627
2545
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2628
2546
|
ref: forwardedRef,
|
|
2629
2547
|
readonly,
|
|
@@ -2631,17 +2549,18 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
|
|
|
2631
2549
|
basicBundle({
|
|
2632
2550
|
readonly,
|
|
2633
2551
|
themeMode,
|
|
2634
|
-
placeholder:
|
|
2552
|
+
placeholder: placeholder3
|
|
2635
2553
|
}),
|
|
2636
2554
|
...extensions
|
|
2637
2555
|
],
|
|
2638
|
-
|
|
2556
|
+
theme,
|
|
2557
|
+
slots: updatedSlots,
|
|
2639
2558
|
...props
|
|
2640
2559
|
});
|
|
2641
2560
|
});
|
|
2642
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2561
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = markdownTheme, slots, ...props }, forwardedRef) => {
|
|
2643
2562
|
const { themeMode } = useThemeContext();
|
|
2644
|
-
const
|
|
2563
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2645
2564
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2646
2565
|
ref: forwardedRef,
|
|
2647
2566
|
readonly,
|
|
@@ -2649,34 +2568,29 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
|
|
|
2649
2568
|
markdownBundle({
|
|
2650
2569
|
readonly,
|
|
2651
2570
|
themeMode,
|
|
2652
|
-
placeholder:
|
|
2571
|
+
placeholder: placeholder3
|
|
2653
2572
|
}),
|
|
2654
2573
|
...extensions
|
|
2655
2574
|
],
|
|
2656
|
-
|
|
2575
|
+
theme,
|
|
2576
|
+
slots: updatedSlots,
|
|
2657
2577
|
...props
|
|
2658
2578
|
});
|
|
2659
2579
|
});
|
|
2660
2580
|
var defaultSlots = {
|
|
2661
2581
|
root: {
|
|
2662
|
-
className: mx3("p-2", inputSurface)
|
|
2582
|
+
className: mx3("p-2 overflow-y-auto", inputSurface)
|
|
2663
2583
|
}
|
|
2664
2584
|
};
|
|
2665
2585
|
var defaultTextSlots = {
|
|
2666
|
-
...defaultSlots
|
|
2667
|
-
editor: {
|
|
2668
|
-
theme: textTheme
|
|
2669
|
-
}
|
|
2586
|
+
...defaultSlots
|
|
2670
2587
|
};
|
|
2671
2588
|
var defaultMarkdownSlots = {
|
|
2672
|
-
...defaultSlots
|
|
2673
|
-
editor: {
|
|
2674
|
-
theme: markdownTheme
|
|
2675
|
-
}
|
|
2589
|
+
...defaultSlots
|
|
2676
2590
|
};
|
|
2677
2591
|
|
|
2678
2592
|
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2679
|
-
import
|
|
2593
|
+
import get4 from "lodash.get";
|
|
2680
2594
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
2681
2595
|
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2682
2596
|
|
|
@@ -2786,7 +2700,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2786
2700
|
};
|
|
2787
2701
|
|
|
2788
2702
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2789
|
-
import { StateField as
|
|
2703
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
|
2790
2704
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2791
2705
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2792
2706
|
|
|
@@ -2795,15 +2709,13 @@ import * as decoding from "lib0/decoding";
|
|
|
2795
2709
|
import * as encoding from "lib0/encoding";
|
|
2796
2710
|
import { Observable } from "lib0/observable";
|
|
2797
2711
|
import * as YP from "y-protocols/awareness";
|
|
2798
|
-
import * as Y2 from "yjs";
|
|
2799
2712
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2800
2713
|
import { log as log4 } from "@dxos/log";
|
|
2801
|
-
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2802
2714
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2803
2715
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2804
2716
|
invariant4(text?.doc && text?.content, void 0, {
|
|
2805
2717
|
F: __dxlog_file5,
|
|
2806
|
-
L:
|
|
2718
|
+
L: 21,
|
|
2807
2719
|
S: void 0,
|
|
2808
2720
|
A: [
|
|
2809
2721
|
"text?.doc && text?.content",
|
|
@@ -2819,34 +2731,6 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
2819
2731
|
id: text.doc.guid,
|
|
2820
2732
|
content: text.content,
|
|
2821
2733
|
text: () => text.content.toString(),
|
|
2822
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2823
|
-
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2824
|
-
getCursorFromRange: (range) => {
|
|
2825
|
-
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2826
|
-
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2827
|
-
return [
|
|
2828
|
-
arrayToString2(from),
|
|
2829
|
-
arrayToString2(to)
|
|
2830
|
-
].join(":");
|
|
2831
|
-
},
|
|
2832
|
-
getRangeFromCursor: (cursor) => {
|
|
2833
|
-
invariant4(text.doc, void 0, {
|
|
2834
|
-
F: __dxlog_file5,
|
|
2835
|
-
L: 40,
|
|
2836
|
-
S: void 0,
|
|
2837
|
-
A: [
|
|
2838
|
-
"text.doc",
|
|
2839
|
-
""
|
|
2840
|
-
]
|
|
2841
|
-
});
|
|
2842
|
-
const parts = cursor.split(":");
|
|
2843
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2844
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2845
|
-
return from && to ? {
|
|
2846
|
-
from: from.index,
|
|
2847
|
-
to: to.index
|
|
2848
|
-
} : void 0;
|
|
2849
|
-
},
|
|
2850
2734
|
extension: [
|
|
2851
2735
|
modelState.init(() => model),
|
|
2852
2736
|
yjs(text.content, provider?.awareness)
|
|
@@ -2896,7 +2780,7 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2896
2780
|
origin
|
|
2897
2781
|
}, {
|
|
2898
2782
|
F: __dxlog_file5,
|
|
2899
|
-
L:
|
|
2783
|
+
L: 100,
|
|
2900
2784
|
S: this,
|
|
2901
2785
|
C: (f, a) => f(...a)
|
|
2902
2786
|
});
|
|
@@ -2909,7 +2793,7 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2909
2793
|
_handleSpaceMessage({ payload }) {
|
|
2910
2794
|
log4("space message", payload, {
|
|
2911
2795
|
F: __dxlog_file5,
|
|
2912
|
-
L:
|
|
2796
|
+
L: 109,
|
|
2913
2797
|
S: this,
|
|
2914
2798
|
C: (f, a) => f(...a)
|
|
2915
2799
|
});
|
|
@@ -2953,13 +2837,13 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2953
2837
|
};
|
|
2954
2838
|
|
|
2955
2839
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2956
|
-
var modelState =
|
|
2840
|
+
var modelState = StateField5.define({
|
|
2957
2841
|
create: () => void 0,
|
|
2958
2842
|
update: (model) => model
|
|
2959
2843
|
});
|
|
2960
2844
|
var useTextModel = (props) => {
|
|
2961
2845
|
const { identity, space, text } = props;
|
|
2962
|
-
const [model, setModel] = useState2(
|
|
2846
|
+
const [model, setModel] = useState2();
|
|
2963
2847
|
useEffect2(() => setModel(createModel(props)), [
|
|
2964
2848
|
identity,
|
|
2965
2849
|
space,
|
|
@@ -2997,7 +2881,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2997
2881
|
const model = {
|
|
2998
2882
|
id: obj.id,
|
|
2999
2883
|
content: doc,
|
|
3000
|
-
text: () =>
|
|
2884
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3001
2885
|
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3002
2886
|
extension: [
|
|
3003
2887
|
modelState.init(() => model),
|
|
@@ -3018,6 +2902,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3018
2902
|
export {
|
|
3019
2903
|
AwarenessProvider,
|
|
3020
2904
|
BaseTextEditor,
|
|
2905
|
+
Cursor,
|
|
3021
2906
|
Doc,
|
|
3022
2907
|
EditorModes,
|
|
3023
2908
|
MarkdownEditor,
|
|
@@ -3033,16 +2918,19 @@ export {
|
|
|
3033
2918
|
awareness,
|
|
3034
2919
|
basicBundle,
|
|
3035
2920
|
blast,
|
|
2921
|
+
callbackWrapper,
|
|
3036
2922
|
code2 as code,
|
|
3037
2923
|
codeTheme,
|
|
3038
2924
|
comments,
|
|
3039
2925
|
createAutomergeModel,
|
|
3040
2926
|
createYjsModel,
|
|
2927
|
+
cursorConverter,
|
|
3041
2928
|
defaultMarkdownSlots,
|
|
3042
2929
|
defaultOptions,
|
|
3043
2930
|
defaultSlots,
|
|
3044
2931
|
defaultTextSlots,
|
|
3045
2932
|
defaultTheme,
|
|
2933
|
+
getToken,
|
|
3046
2934
|
hr,
|
|
3047
2935
|
image,
|
|
3048
2936
|
link,
|
|
@@ -3053,7 +2941,6 @@ export {
|
|
|
3053
2941
|
markdownTagsExtensions,
|
|
3054
2942
|
markdownTheme,
|
|
3055
2943
|
mention,
|
|
3056
|
-
mermaid,
|
|
3057
2944
|
modelState,
|
|
3058
2945
|
setCommentRange,
|
|
3059
2946
|
setFocus,
|