@dxos/react-ui-editor 0.3.11-main.8d54a30 → 0.3.11-main.8feb6a5
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 +511 -569
- 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 +6 -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 +329 -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 +89 -120
- 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.test.ts +1 -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,68 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1195
1214
|
}).filter(nonNullable) ?? [];
|
|
1196
1215
|
return Decoration3.set(decorations);
|
|
1197
1216
|
});
|
|
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();
|
|
1217
|
+
var trackPastedComments = (onMove) => {
|
|
1218
|
+
let tracked = null;
|
|
1219
|
+
const registerCopy = (event, view) => {
|
|
1220
|
+
const comments2 = view.state.field(commentsStateField);
|
|
1221
|
+
const { main } = view.state.selection;
|
|
1222
|
+
const inSel = comments2.ranges.filter((range) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1223
|
+
if (!inSel.length) {
|
|
1224
|
+
tracked = null;
|
|
1225
|
+
} else {
|
|
1226
|
+
tracked = {
|
|
1227
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1228
|
+
comments: inSel.map((range) => ({
|
|
1229
|
+
from: range.from - main.from,
|
|
1230
|
+
to: range.to - main.from,
|
|
1231
|
+
id: range.id
|
|
1232
|
+
}))
|
|
1233
|
+
};
|
|
1223
1234
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1235
|
+
};
|
|
1236
|
+
return [
|
|
1237
|
+
EditorView5.domEventHandlers({
|
|
1238
|
+
cut: registerCopy,
|
|
1239
|
+
copy: registerCopy
|
|
1240
|
+
}),
|
|
1241
|
+
EditorView5.updateListener.of((update2) => {
|
|
1242
|
+
if (tracked) {
|
|
1243
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1244
|
+
if (paste) {
|
|
1245
|
+
let found = -1;
|
|
1246
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1247
|
+
if (text.eq(tracked.text)) {
|
|
1248
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1249
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1250
|
+
}
|
|
1251
|
+
found = fromB;
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
if (found > -1) {
|
|
1255
|
+
const active = update2.view.state.field(commentsStateField).ranges;
|
|
1256
|
+
for (const moved of tracked.comments) {
|
|
1257
|
+
if (active.some((range) => range.id === moved.id && range.from === range.to)) {
|
|
1258
|
+
onMove(moved.id, Cursor.getCursorFromRange(update2.view.state.facet(Cursor.converter), {
|
|
1259
|
+
from: found + moved.from,
|
|
1260
|
+
to: found + moved.to
|
|
1261
|
+
}));
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
tracked = null;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
})
|
|
1269
|
+
];
|
|
1226
1270
|
};
|
|
1227
1271
|
var comments = (options = {}) => {
|
|
1272
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1228
1273
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
1274
|
const createCommentThread = (view) => {
|
|
1230
|
-
const cursorConverter3 = view.state.facet(
|
|
1275
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1231
1276
|
invariant2(options.onCreate, void 0, {
|
|
1232
1277
|
F: __dxlog_file3,
|
|
1233
|
-
L:
|
|
1278
|
+
L: 240,
|
|
1234
1279
|
S: void 0,
|
|
1235
1280
|
A: [
|
|
1236
1281
|
"options.onCreate",
|
|
@@ -1241,12 +1286,12 @@ var comments = (options = {}) => {
|
|
|
1241
1286
|
if (from === to) {
|
|
1242
1287
|
return false;
|
|
1243
1288
|
}
|
|
1244
|
-
const
|
|
1289
|
+
const cursor = Cursor.getCursorFromRange(cursorConverter3, {
|
|
1245
1290
|
from,
|
|
1246
1291
|
to
|
|
1247
1292
|
});
|
|
1248
|
-
if (
|
|
1249
|
-
const id = callbackWrapper(options.onCreate)(
|
|
1293
|
+
if (cursor) {
|
|
1294
|
+
const id = callbackWrapper(options.onCreate)(cursor, view.coordsAtPos(from));
|
|
1250
1295
|
if (id) {
|
|
1251
1296
|
view.dispatch({
|
|
1252
1297
|
effects: setSelection.of({
|
|
@@ -1273,35 +1318,7 @@ var comments = (options = {}) => {
|
|
|
1273
1318
|
}
|
|
1274
1319
|
return false;
|
|
1275
1320
|
};
|
|
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
1321
|
return [
|
|
1304
|
-
bookmarksViewPlugin,
|
|
1305
1322
|
commentsStateField,
|
|
1306
1323
|
highlightDecorations,
|
|
1307
1324
|
styles3,
|
|
@@ -1310,7 +1327,7 @@ var comments = (options = {}) => {
|
|
|
1310
1327
|
//
|
|
1311
1328
|
options.onCreate ? keymap3.of([
|
|
1312
1329
|
{
|
|
1313
|
-
key:
|
|
1330
|
+
key: shortcut,
|
|
1314
1331
|
run: callbackWrapper(createCommentThread)
|
|
1315
1332
|
}
|
|
1316
1333
|
]) : [],
|
|
@@ -1327,7 +1344,7 @@ var comments = (options = {}) => {
|
|
|
1327
1344
|
above: true,
|
|
1328
1345
|
create: () => {
|
|
1329
1346
|
const el = document.createElement("div");
|
|
1330
|
-
options.onHover?.(el);
|
|
1347
|
+
options.onHover?.(el, shortcut);
|
|
1331
1348
|
return {
|
|
1332
1349
|
dom: el,
|
|
1333
1350
|
offset: {
|
|
@@ -1348,27 +1365,27 @@ var comments = (options = {}) => {
|
|
|
1348
1365
|
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1349
1366
|
//
|
|
1350
1367
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1351
|
-
const cursorConverter3 = view.state.facet(
|
|
1368
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1352
1369
|
{
|
|
1353
1370
|
let mod = false;
|
|
1354
1371
|
const { active, ranges } = state.field(commentsStateField);
|
|
1355
1372
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1356
1373
|
ranges.forEach((range) => {
|
|
1357
1374
|
if (from2 === to2) {
|
|
1358
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1375
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1359
1376
|
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
1377
|
log2.info("deleted comment", {
|
|
1361
1378
|
thread: range.id
|
|
1362
1379
|
}, {
|
|
1363
1380
|
F: __dxlog_file3,
|
|
1364
|
-
L:
|
|
1381
|
+
L: 337,
|
|
1365
1382
|
S: void 0,
|
|
1366
1383
|
C: (f, a) => f(...a)
|
|
1367
1384
|
});
|
|
1368
1385
|
}
|
|
1369
1386
|
}
|
|
1370
1387
|
if (from <= range.to) {
|
|
1371
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1388
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
1389
|
Object.assign(range, newRange);
|
|
1373
1390
|
mod = true;
|
|
1374
1391
|
}
|
|
@@ -1414,38 +1431,21 @@ var comments = (options = {}) => {
|
|
|
1414
1431
|
});
|
|
1415
1432
|
}
|
|
1416
1433
|
}
|
|
1417
|
-
})
|
|
1434
|
+
}),
|
|
1435
|
+
options.onMove ? trackPastedComments(options.onMove) : []
|
|
1418
1436
|
];
|
|
1419
1437
|
};
|
|
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
1438
|
|
|
1438
1439
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
-
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator
|
|
1440
|
-
import get4 from "lodash.get";
|
|
1440
|
+
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1441
1441
|
var styles4 = EditorView6.baseTheme({
|
|
1442
1442
|
"& .cm-hr": {
|
|
1443
1443
|
// TODO(burdon): ???
|
|
1444
1444
|
// Note that block-level decorations should not have vertical margins,
|
|
1445
|
-
borderBottom: `1px solid ${
|
|
1445
|
+
borderBottom: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1446
1446
|
}
|
|
1447
1447
|
});
|
|
1448
|
-
var HorizontalRuleWidget = class extends
|
|
1448
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1449
1449
|
constructor(_pos) {
|
|
1450
1450
|
super();
|
|
1451
1451
|
this._pos = _pos;
|
|
@@ -1459,7 +1459,7 @@ var HorizontalRuleWidget = class extends WidgetType3 {
|
|
|
1459
1459
|
return el;
|
|
1460
1460
|
}
|
|
1461
1461
|
};
|
|
1462
|
-
var placeholderMatcher = new
|
|
1462
|
+
var placeholderMatcher = new MatchDecorator({
|
|
1463
1463
|
regexp: /^---$/g,
|
|
1464
1464
|
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
1465
|
widget: new HorizontalRuleWidget(pos)
|
|
@@ -1467,12 +1467,12 @@ var placeholderMatcher = new MatchDecorator2({
|
|
|
1467
1467
|
});
|
|
1468
1468
|
var hr = () => [
|
|
1469
1469
|
styles4,
|
|
1470
|
-
|
|
1470
|
+
ViewPlugin4.fromClass(class {
|
|
1471
1471
|
constructor(view) {
|
|
1472
1472
|
this.rules = placeholderMatcher.createDeco(view);
|
|
1473
1473
|
}
|
|
1474
|
-
update(
|
|
1475
|
-
this.rules = placeholderMatcher.updateDeco(
|
|
1474
|
+
update(update2) {
|
|
1475
|
+
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1476
1476
|
}
|
|
1477
1477
|
}, {
|
|
1478
1478
|
decorations: (instance) => instance.rules,
|
|
@@ -1485,17 +1485,39 @@ var hr = () => [
|
|
|
1485
1485
|
|
|
1486
1486
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
1487
|
import { syntaxTree } from "@codemirror/language";
|
|
1488
|
-
import {
|
|
1489
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as
|
|
1488
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1489
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1490
1490
|
var image = (options = {}) => {
|
|
1491
1491
|
return StateField3.define({
|
|
1492
|
-
create: (state) =>
|
|
1493
|
-
|
|
1492
|
+
create: (state) => {
|
|
1493
|
+
return Decoration5.set(buildDecorations(0, state.doc.length, state));
|
|
1494
|
+
},
|
|
1495
|
+
update: (value, tr) => {
|
|
1496
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1497
|
+
return value;
|
|
1498
|
+
}
|
|
1499
|
+
const cursor = tr.state.selection.main.head;
|
|
1500
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1501
|
+
let from = Math.min(cursor, oldCursor);
|
|
1502
|
+
let to = Math.max(cursor, oldCursor);
|
|
1503
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1504
|
+
from = Math.min(from, fromB);
|
|
1505
|
+
to = Math.max(to, toB);
|
|
1506
|
+
});
|
|
1507
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1508
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1509
|
+
return value.map(tr.changes).update({
|
|
1510
|
+
filterFrom: from,
|
|
1511
|
+
filterTo: to,
|
|
1512
|
+
filter: () => false,
|
|
1513
|
+
add: buildDecorations(from, to, tr.state)
|
|
1514
|
+
});
|
|
1515
|
+
},
|
|
1494
1516
|
provide: (field) => EditorView7.decorations.from(field)
|
|
1495
1517
|
});
|
|
1496
1518
|
};
|
|
1497
|
-
var
|
|
1498
|
-
const
|
|
1519
|
+
var buildDecorations = (from, to, state) => {
|
|
1520
|
+
const decorations = [];
|
|
1499
1521
|
const cursor = state.selection.main.head;
|
|
1500
1522
|
syntaxTree(state).iterate({
|
|
1501
1523
|
enter: (node) => {
|
|
@@ -1504,22 +1526,23 @@ var update = (state, options) => {
|
|
|
1504
1526
|
if (urlNode) {
|
|
1505
1527
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1506
1528
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1507
|
-
|
|
1529
|
+
decorations.push(Decoration5.replace({
|
|
1508
1530
|
block: true,
|
|
1509
1531
|
widget: new ImageWidget(url)
|
|
1510
|
-
}));
|
|
1532
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1511
1533
|
}
|
|
1512
1534
|
}
|
|
1513
|
-
}
|
|
1535
|
+
},
|
|
1536
|
+
from,
|
|
1537
|
+
to
|
|
1514
1538
|
});
|
|
1515
|
-
return
|
|
1539
|
+
return decorations;
|
|
1516
1540
|
};
|
|
1517
|
-
var ImageWidget = class extends
|
|
1541
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1518
1542
|
constructor(_url) {
|
|
1519
1543
|
super();
|
|
1520
1544
|
this._url = _url;
|
|
1521
1545
|
}
|
|
1522
|
-
// TODO(burdon): Does this need to be unique for each position?
|
|
1523
1546
|
eq(other) {
|
|
1524
1547
|
return this._url === other._url;
|
|
1525
1548
|
}
|
|
@@ -1527,22 +1550,29 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1527
1550
|
const img = document.createElement("img");
|
|
1528
1551
|
img.setAttribute("src", this._url);
|
|
1529
1552
|
img.setAttribute("class", "cm-image");
|
|
1553
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1530
1554
|
return img;
|
|
1531
1555
|
}
|
|
1532
1556
|
};
|
|
1533
1557
|
|
|
1534
1558
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1535
1559
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1536
|
-
import { RangeSetBuilder
|
|
1537
|
-
import { Decoration as Decoration6,
|
|
1560
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1561
|
+
import { Decoration as Decoration6, WidgetType as WidgetType4, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1538
1562
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1539
|
-
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
1540
1563
|
var link = (options = {}) => {
|
|
1541
1564
|
const extensions = [
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1565
|
+
ViewPlugin5.fromClass(class {
|
|
1566
|
+
constructor(view) {
|
|
1567
|
+
this.decorations = buildDecorations2(view, options);
|
|
1568
|
+
}
|
|
1569
|
+
update(update2) {
|
|
1570
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1571
|
+
this.decorations = buildDecorations2(update2.view, options);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
}, {
|
|
1575
|
+
decorations: (v) => v.decorations
|
|
1546
1576
|
})
|
|
1547
1577
|
];
|
|
1548
1578
|
if (options.onHover) {
|
|
@@ -1550,35 +1580,25 @@ var link = (options = {}) => {
|
|
|
1550
1580
|
// https://codemirror.net/examples/tooltip
|
|
1551
1581
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1552
1582
|
// 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) {
|
|
1583
|
+
hoverTooltip2((view, pos, side) => {
|
|
1584
|
+
const syntax = syntaxTree2(view.state).resolveInner(pos, side);
|
|
1585
|
+
let link2 = null;
|
|
1586
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1587
|
+
link2 = node.name === "Link" ? node : null;
|
|
1588
|
+
}
|
|
1589
|
+
const url = link2 && link2.getChild("URL");
|
|
1590
|
+
if (!url || !link2) {
|
|
1571
1591
|
return null;
|
|
1572
1592
|
}
|
|
1573
|
-
const
|
|
1593
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1574
1594
|
return {
|
|
1575
|
-
pos:
|
|
1576
|
-
end:
|
|
1595
|
+
pos: link2.from,
|
|
1596
|
+
end: link2.to,
|
|
1577
1597
|
above: true,
|
|
1578
1598
|
create: () => {
|
|
1579
1599
|
const el = document.createElement("div");
|
|
1580
1600
|
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1581
|
-
options.onHover(el,
|
|
1601
|
+
options.onHover(el, urlText);
|
|
1582
1602
|
return {
|
|
1583
1603
|
dom: el,
|
|
1584
1604
|
offset: {
|
|
@@ -1593,15 +1613,14 @@ var link = (options = {}) => {
|
|
|
1593
1613
|
}
|
|
1594
1614
|
return extensions;
|
|
1595
1615
|
};
|
|
1596
|
-
var LinkButton = class extends
|
|
1597
|
-
constructor(
|
|
1616
|
+
var LinkButton = class extends WidgetType4 {
|
|
1617
|
+
constructor(_url, _onAttach) {
|
|
1598
1618
|
super();
|
|
1599
|
-
this._pos = _pos;
|
|
1600
1619
|
this._url = _url;
|
|
1601
1620
|
this._onAttach = _onAttach;
|
|
1602
1621
|
}
|
|
1603
1622
|
eq(other) {
|
|
1604
|
-
return this.
|
|
1623
|
+
return this._url === other._url;
|
|
1605
1624
|
}
|
|
1606
1625
|
toDOM(view) {
|
|
1607
1626
|
const el = document.createElement("span");
|
|
@@ -1609,7 +1628,7 @@ var LinkButton = class extends WidgetType5 {
|
|
|
1609
1628
|
return el;
|
|
1610
1629
|
}
|
|
1611
1630
|
};
|
|
1612
|
-
var LinkText = class extends
|
|
1631
|
+
var LinkText = class extends WidgetType4 {
|
|
1613
1632
|
constructor(_text, _url) {
|
|
1614
1633
|
super();
|
|
1615
1634
|
this._text = _text;
|
|
@@ -1638,46 +1657,51 @@ var LinkText = class extends WidgetType5 {
|
|
|
1638
1657
|
return link2;
|
|
1639
1658
|
}
|
|
1640
1659
|
};
|
|
1641
|
-
var
|
|
1642
|
-
const builder = new
|
|
1660
|
+
var buildDecorations2 = (view, options) => {
|
|
1661
|
+
const builder = new RangeSetBuilder();
|
|
1662
|
+
const { state } = view;
|
|
1643
1663
|
const cursor = state.selection.main.head;
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1664
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1665
|
+
syntaxTree2(state).iterate({
|
|
1666
|
+
enter: (node) => {
|
|
1667
|
+
if (node.name === "Link") {
|
|
1668
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
1669
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1670
|
+
const urlNode = node.node.getChild("URL");
|
|
1671
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1672
|
+
if (!url) {
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1676
|
+
builder.add(node.from, node.to, Decoration6.replace({
|
|
1677
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
1678
|
+
}));
|
|
1679
|
+
}
|
|
1680
|
+
if (options.onRender) {
|
|
1681
|
+
builder.add(node.to, node.to, Decoration6.replace({
|
|
1682
|
+
widget: new LinkButton(url, options.onRender)
|
|
1683
|
+
}));
|
|
1684
|
+
}
|
|
1652
1685
|
return false;
|
|
1653
1686
|
}
|
|
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
|
-
});
|
|
1687
|
+
},
|
|
1688
|
+
from,
|
|
1689
|
+
to
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1668
1692
|
return builder.finish();
|
|
1669
1693
|
};
|
|
1670
1694
|
|
|
1671
1695
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1672
|
-
import { EditorView as
|
|
1696
|
+
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1673
1697
|
var listener = ({ onFocus, onChange }) => {
|
|
1674
1698
|
const extensions = [];
|
|
1675
|
-
onFocus && extensions.push(
|
|
1699
|
+
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1676
1700
|
onFocus(focused);
|
|
1677
1701
|
return null;
|
|
1678
1702
|
}));
|
|
1679
|
-
onChange && extensions.push(
|
|
1680
|
-
onChange(
|
|
1703
|
+
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1704
|
+
onChange(update2.state.doc.toString());
|
|
1681
1705
|
}));
|
|
1682
1706
|
return extensions;
|
|
1683
1707
|
};
|
|
@@ -1685,27 +1709,25 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1685
1709
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1686
1710
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1687
1711
|
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1688
|
-
import { markdownLanguage as
|
|
1712
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1689
1713
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1690
1714
|
import { languages } from "@codemirror/language-data";
|
|
1691
1715
|
import { searchKeymap } from "@codemirror/search";
|
|
1692
1716
|
import { EditorState } from "@codemirror/state";
|
|
1693
1717
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1694
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1718
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1695
1719
|
|
|
1696
1720
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1697
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
1721
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1698
1722
|
import { HighlightStyle } from "@codemirror/language";
|
|
1699
1723
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1700
1724
|
import { Table } from "@lezer/markdown";
|
|
1701
|
-
import get5 from "lodash.get";
|
|
1702
1725
|
var markdownTags = {
|
|
1703
1726
|
Blockquote: Tag.define(),
|
|
1704
1727
|
CodeMark: Tag.define(),
|
|
1705
1728
|
CodeText: Tag.define(),
|
|
1706
1729
|
EmphasisMark: Tag.define(),
|
|
1707
1730
|
HeaderMark: Tag.define(),
|
|
1708
|
-
// HorizontalRule: Tag.define(),
|
|
1709
1731
|
InlineCode: Tag.define(),
|
|
1710
1732
|
LinkLabel: Tag.define(),
|
|
1711
1733
|
LinkReference: Tag.define(),
|
|
@@ -1869,12 +1891,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1869
1891
|
],
|
|
1870
1892
|
class: blockquote
|
|
1871
1893
|
},
|
|
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
1894
|
{
|
|
1879
1895
|
tag: [
|
|
1880
1896
|
markdownTags.TableCell
|
|
@@ -1882,9 +1898,9 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1882
1898
|
class: "font-mono"
|
|
1883
1899
|
}
|
|
1884
1900
|
], {
|
|
1885
|
-
scope:
|
|
1901
|
+
scope: markdownLanguage2,
|
|
1886
1902
|
all: {
|
|
1887
|
-
fontFamily:
|
|
1903
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1888
1904
|
}
|
|
1889
1905
|
});
|
|
1890
1906
|
};
|
|
@@ -1894,7 +1910,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1894
1910
|
return [
|
|
1895
1911
|
EditorState.allowMultipleSelections.of(true),
|
|
1896
1912
|
EditorState.tabSize.of(2),
|
|
1897
|
-
|
|
1913
|
+
EditorView9.lineWrapping,
|
|
1898
1914
|
customKeymap(),
|
|
1899
1915
|
bracketMatching2(),
|
|
1900
1916
|
closeBrackets2(),
|
|
@@ -1914,7 +1930,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1914
1930
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1915
1931
|
// https://github.github.com/gfm
|
|
1916
1932
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1917
|
-
base:
|
|
1933
|
+
base: markdownLanguage3,
|
|
1918
1934
|
// Languages for syntax highlighting fenced code blocks.
|
|
1919
1935
|
codeLanguages: languages,
|
|
1920
1936
|
// Parser extensions.
|
|
@@ -1965,24 +1981,19 @@ var mention = ({ onSearch }) => {
|
|
|
1965
1981
|
});
|
|
1966
1982
|
};
|
|
1967
1983
|
|
|
1968
|
-
// packages/ui/react-ui-editor/src/extensions/mermaid.ts
|
|
1969
|
-
var mermaid = () => {
|
|
1970
|
-
return [];
|
|
1971
|
-
};
|
|
1972
|
-
|
|
1973
1984
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1974
1985
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1975
|
-
import { RangeSetBuilder as
|
|
1976
|
-
import { Decoration as Decoration7, EditorView as
|
|
1986
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1987
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1977
1988
|
var table = (options = {}) => {
|
|
1978
|
-
return
|
|
1979
|
-
create: (state) =>
|
|
1980
|
-
update: (_, tr) =>
|
|
1981
|
-
provide: (field) =>
|
|
1989
|
+
return StateField4.define({
|
|
1990
|
+
create: (state) => update(state, options),
|
|
1991
|
+
update: (_, tr) => update(tr.state, options),
|
|
1992
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1982
1993
|
});
|
|
1983
1994
|
};
|
|
1984
|
-
var
|
|
1985
|
-
const builder = new
|
|
1995
|
+
var update = (state, options) => {
|
|
1996
|
+
const builder = new RangeSetBuilder2();
|
|
1986
1997
|
const cursor = state.selection.main.head;
|
|
1987
1998
|
const tables = [];
|
|
1988
1999
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2023,7 +2034,6 @@ var update3 = (state, options) => {
|
|
|
2023
2034
|
tables.forEach((table2) => {
|
|
2024
2035
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2025
2036
|
hide && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
2026
|
-
block: true,
|
|
2027
2037
|
widget: new TableWidget(table2)
|
|
2028
2038
|
}));
|
|
2029
2039
|
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
@@ -2032,13 +2042,13 @@ var update3 = (state, options) => {
|
|
|
2032
2042
|
});
|
|
2033
2043
|
return builder.finish();
|
|
2034
2044
|
};
|
|
2035
|
-
var TableWidget = class extends
|
|
2045
|
+
var TableWidget = class extends WidgetType5 {
|
|
2036
2046
|
constructor(_table) {
|
|
2037
2047
|
super();
|
|
2038
2048
|
this._table = _table;
|
|
2039
2049
|
}
|
|
2040
2050
|
eq(other) {
|
|
2041
|
-
return this._table.
|
|
2051
|
+
return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
|
|
2042
2052
|
}
|
|
2043
2053
|
toDOM(view) {
|
|
2044
2054
|
const table2 = document.createElement("table");
|
|
@@ -2064,91 +2074,91 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2064
2074
|
}
|
|
2065
2075
|
return table2;
|
|
2066
2076
|
}
|
|
2077
|
+
ignoreEvent(e) {
|
|
2078
|
+
return !/^mouse/.test(e.type);
|
|
2079
|
+
}
|
|
2067
2080
|
};
|
|
2068
2081
|
|
|
2069
2082
|
// 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) {
|
|
2083
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2084
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
2085
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2086
|
+
var CheckboxWidget = class extends WidgetType6 {
|
|
2087
|
+
constructor(_checked) {
|
|
2079
2088
|
super();
|
|
2080
|
-
this._pos = _pos;
|
|
2081
2089
|
this._checked = _checked;
|
|
2082
|
-
this._indent = _indent;
|
|
2083
|
-
this._onCheck = _onCheck;
|
|
2084
2090
|
}
|
|
2085
2091
|
eq(other) {
|
|
2086
|
-
return this.
|
|
2092
|
+
return this._checked === other._checked;
|
|
2087
2093
|
}
|
|
2088
2094
|
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"));
|
|
2095
|
+
const input = document.createElement("input");
|
|
2094
2096
|
input.type = "checkbox";
|
|
2095
2097
|
input.checked = this._checked;
|
|
2096
|
-
if (
|
|
2098
|
+
if (view.state.readOnly) {
|
|
2097
2099
|
input.setAttribute("disabled", "true");
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2100
|
+
} else {
|
|
2101
|
+
input.onmousedown = (event) => {
|
|
2102
|
+
const pos = view.posAtDOM(input);
|
|
2103
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2104
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2105
|
+
view.dispatch({
|
|
2106
|
+
changes: {
|
|
2107
|
+
from: pos + 1,
|
|
2108
|
+
to: pos + 2,
|
|
2109
|
+
insert: this._checked ? " " : "x"
|
|
2110
|
+
}
|
|
2111
|
+
});
|
|
2112
|
+
event.preventDefault();
|
|
2113
|
+
}
|
|
2103
2114
|
};
|
|
2104
2115
|
}
|
|
2105
|
-
return
|
|
2116
|
+
return input;
|
|
2106
2117
|
}
|
|
2107
2118
|
ignoreEvent() {
|
|
2108
2119
|
return false;
|
|
2109
2120
|
}
|
|
2110
2121
|
};
|
|
2122
|
+
var checkedDeco = Decoration8.replace({
|
|
2123
|
+
widget: new CheckboxWidget(true)
|
|
2124
|
+
});
|
|
2125
|
+
var uncheckedDeco = Decoration8.replace({
|
|
2126
|
+
widget: new CheckboxWidget(false)
|
|
2127
|
+
});
|
|
2111
2128
|
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 {
|
|
2129
|
+
return ViewPlugin6.fromClass(class {
|
|
2136
2130
|
constructor(view) {
|
|
2137
|
-
this.
|
|
2131
|
+
this.decorations = buildDecorations3(view);
|
|
2138
2132
|
}
|
|
2139
|
-
update(
|
|
2140
|
-
|
|
2133
|
+
update(update2) {
|
|
2134
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2135
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2136
|
+
}
|
|
2141
2137
|
}
|
|
2142
2138
|
}, {
|
|
2143
|
-
decorations: (
|
|
2144
|
-
provide: (plugin) =>
|
|
2145
|
-
return view.plugin(plugin)?.
|
|
2139
|
+
decorations: (v) => v.decorations,
|
|
2140
|
+
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2141
|
+
return view.plugin(plugin)?.decorations || Decoration8.none;
|
|
2146
2142
|
})
|
|
2147
2143
|
});
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2144
|
+
};
|
|
2145
|
+
var buildDecorations3 = (view) => {
|
|
2146
|
+
const builder = new RangeSetBuilder3();
|
|
2147
|
+
const { state } = view;
|
|
2148
|
+
const cursor = state.selection.main.head;
|
|
2149
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2150
|
+
syntaxTree4(state).iterate({
|
|
2151
|
+
enter: (node) => {
|
|
2152
|
+
if (node.name === "TaskMarker" && (cursor < node.from || cursor > node.to)) {
|
|
2153
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2154
|
+
builder.add(node.from, node.to, checked ? checkedDeco : uncheckedDeco);
|
|
2155
|
+
}
|
|
2156
|
+
},
|
|
2157
|
+
from,
|
|
2158
|
+
to
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
return builder.finish();
|
|
2152
2162
|
};
|
|
2153
2163
|
|
|
2154
2164
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
@@ -2225,12 +2235,12 @@ var cursorConverter2 = (text) => ({
|
|
|
2225
2235
|
|
|
2226
2236
|
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2227
2237
|
var yjs = (content, awareness2) => [
|
|
2228
|
-
|
|
2238
|
+
Cursor.converter.of(cursorConverter2(content)),
|
|
2229
2239
|
yCollab(content, awareness2)
|
|
2230
2240
|
];
|
|
2231
2241
|
|
|
2232
2242
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2233
|
-
import
|
|
2243
|
+
import get3 from "lodash.get";
|
|
2234
2244
|
var defaultTheme = {
|
|
2235
2245
|
//
|
|
2236
2246
|
// Main layout:
|
|
@@ -2259,21 +2269,21 @@ var defaultTheme = {
|
|
|
2259
2269
|
"&.cm-focused": {
|
|
2260
2270
|
outline: "none"
|
|
2261
2271
|
},
|
|
2262
|
-
"
|
|
2272
|
+
".cm-scroller": {
|
|
2263
2273
|
overflow: "visible",
|
|
2264
|
-
fontFamily:
|
|
2274
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2265
2275
|
},
|
|
2266
|
-
"
|
|
2276
|
+
".cm-content": {
|
|
2267
2277
|
padding: 0,
|
|
2268
2278
|
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2269
2279
|
fontSize: "16px"
|
|
2270
2280
|
},
|
|
2271
2281
|
"&light .cm-content": {
|
|
2272
|
-
color:
|
|
2282
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
2273
2283
|
caretColor: "black"
|
|
2274
2284
|
},
|
|
2275
2285
|
"&dark .cm-content": {
|
|
2276
|
-
color:
|
|
2286
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
2277
2287
|
caretColor: "white"
|
|
2278
2288
|
},
|
|
2279
2289
|
//
|
|
@@ -2285,158 +2295,120 @@ var defaultTheme = {
|
|
|
2285
2295
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2286
2296
|
borderLeft: "2px solid white"
|
|
2287
2297
|
},
|
|
2288
|
-
"
|
|
2298
|
+
".cm-placeholder": {
|
|
2289
2299
|
fontWeight: 100
|
|
2290
2300
|
},
|
|
2291
2301
|
//
|
|
2292
2302
|
// line
|
|
2293
2303
|
//
|
|
2294
|
-
"
|
|
2304
|
+
".cm-line": {
|
|
2295
2305
|
paddingInline: 0
|
|
2296
2306
|
},
|
|
2297
|
-
"
|
|
2307
|
+
".cm-activeLine": {
|
|
2298
2308
|
background: "inherit"
|
|
2299
2309
|
},
|
|
2300
2310
|
//
|
|
2301
2311
|
// Selection
|
|
2302
2312
|
//
|
|
2303
2313
|
"&light .cm-selectionBackground": {
|
|
2304
|
-
background:
|
|
2314
|
+
background: get3(tokens, "extend.colors.primary.100")
|
|
2305
2315
|
},
|
|
2306
2316
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2307
|
-
background:
|
|
2317
|
+
background: get3(tokens, "extend.colors.primary.200")
|
|
2308
2318
|
},
|
|
2309
2319
|
"&dark .cm-selectionBackground": {
|
|
2310
|
-
background:
|
|
2320
|
+
background: get3(tokens, "extend.colors.primary.700")
|
|
2311
2321
|
},
|
|
2312
2322
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2313
|
-
background:
|
|
2323
|
+
background: get3(tokens, "extend.colors.primary.600")
|
|
2314
2324
|
},
|
|
2315
2325
|
//
|
|
2316
2326
|
// Search
|
|
2317
2327
|
//
|
|
2318
2328
|
"&light .cm-searchMatch": {
|
|
2319
|
-
backgroundColor:
|
|
2329
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2320
2330
|
},
|
|
2321
2331
|
"&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
|
|
2332
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2350
2333
|
},
|
|
2351
2334
|
//
|
|
2352
2335
|
// link
|
|
2353
2336
|
//
|
|
2354
|
-
"
|
|
2355
|
-
color:
|
|
2337
|
+
".cm-link": {
|
|
2338
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
2356
2339
|
textDecorationLine: "underline",
|
|
2357
2340
|
textDecorationThickness: "1px",
|
|
2358
2341
|
textUnderlineOffset: "2px",
|
|
2359
2342
|
borderRadius: ".125rem",
|
|
2360
|
-
fontFamily:
|
|
2343
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2361
2344
|
},
|
|
2362
2345
|
//
|
|
2363
2346
|
// tooltip
|
|
2364
2347
|
//
|
|
2365
|
-
"
|
|
2348
|
+
".cm-tooltip": {
|
|
2366
2349
|
border: "none"
|
|
2367
2350
|
},
|
|
2368
|
-
"
|
|
2351
|
+
".cm-tooltip-below": {},
|
|
2369
2352
|
//
|
|
2370
2353
|
// autocomplete
|
|
2371
2354
|
//
|
|
2372
|
-
"
|
|
2355
|
+
".cm-tooltip-autocomplete": {
|
|
2373
2356
|
marginTop: "4px",
|
|
2374
2357
|
marginLeft: "-3px"
|
|
2375
2358
|
},
|
|
2376
|
-
"
|
|
2377
|
-
"
|
|
2378
|
-
"
|
|
2359
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
2360
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2361
|
+
".cm-completionIcon": {
|
|
2379
2362
|
display: "none"
|
|
2380
2363
|
},
|
|
2381
|
-
"
|
|
2382
|
-
fontFamily:
|
|
2364
|
+
".cm-completionLabel": {
|
|
2365
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2383
2366
|
},
|
|
2384
|
-
"
|
|
2367
|
+
".cm-completionMatchedText": {
|
|
2385
2368
|
textDecoration: "none"
|
|
2386
2369
|
},
|
|
2387
2370
|
//
|
|
2388
|
-
// widgets
|
|
2389
|
-
//
|
|
2390
|
-
"& .cm-widgetBuffer": {
|
|
2391
|
-
display: "none",
|
|
2392
|
-
height: 0
|
|
2393
|
-
},
|
|
2394
|
-
//
|
|
2395
2371
|
// table
|
|
2396
2372
|
//
|
|
2397
|
-
"
|
|
2398
|
-
fontFamily: `${
|
|
2373
|
+
".cm-table *": {
|
|
2374
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2399
2375
|
textDecoration: "none !important"
|
|
2400
2376
|
},
|
|
2401
|
-
"
|
|
2377
|
+
".cm-table-head": {
|
|
2402
2378
|
padding: "2px 16px 2px 0px",
|
|
2403
|
-
borderBottom: `1px solid ${
|
|
2379
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2404
2380
|
fontWeight: 100,
|
|
2405
2381
|
textAlign: "left",
|
|
2406
|
-
color:
|
|
2382
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
2407
2383
|
},
|
|
2408
|
-
"
|
|
2384
|
+
".cm-table-cell": {
|
|
2409
2385
|
padding: "2px 16px 2px 0px"
|
|
2410
2386
|
},
|
|
2411
2387
|
//
|
|
2412
2388
|
// image
|
|
2413
2389
|
//
|
|
2414
|
-
"
|
|
2415
|
-
|
|
2390
|
+
".cm-image": {
|
|
2391
|
+
display: "block",
|
|
2392
|
+
height: "0"
|
|
2393
|
+
},
|
|
2394
|
+
".cm-image.cm-loaded-image": {
|
|
2395
|
+
height: "auto",
|
|
2396
|
+
borderTop: "0.5rem solid transparent",
|
|
2397
|
+
borderBottom: "0.5rem solid transparent"
|
|
2416
2398
|
},
|
|
2417
2399
|
//
|
|
2418
2400
|
// font size
|
|
2419
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2401
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2402
|
+
// but it's far more verbose than it needs to be.
|
|
2420
2403
|
//
|
|
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
|
-
}, {}),
|
|
2404
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2405
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2406
|
+
//
|
|
2407
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2408
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2409
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2410
|
+
// return acc;
|
|
2411
|
+
// }, {}),
|
|
2440
2412
|
/**
|
|
2441
2413
|
* Panels
|
|
2442
2414
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2453,51 +2425,53 @@ var defaultTheme = {
|
|
|
2453
2425
|
* </div>
|
|
2454
2426
|
* </div
|
|
2455
2427
|
*/
|
|
2456
|
-
"
|
|
2457
|
-
border: `1px solid ${
|
|
2428
|
+
".cm-panels": {
|
|
2429
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2458
2430
|
},
|
|
2459
|
-
"
|
|
2460
|
-
background:
|
|
2461
|
-
fontFamily:
|
|
2431
|
+
".cm-panel": {
|
|
2432
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2433
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2462
2434
|
},
|
|
2463
|
-
"
|
|
2435
|
+
".cm-button": {
|
|
2464
2436
|
margin: "4px",
|
|
2465
|
-
fontFamily:
|
|
2466
|
-
background:
|
|
2437
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2438
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2467
2439
|
backgroundImage: "none",
|
|
2468
2440
|
border: "none",
|
|
2469
2441
|
"&:hover": {
|
|
2470
|
-
background:
|
|
2442
|
+
background: get3(tokens, "extend.colors.neutral.200")
|
|
2471
2443
|
},
|
|
2472
2444
|
"&:active": {
|
|
2473
|
-
background:
|
|
2445
|
+
background: get3(tokens, "extend.colors.neutral.300"),
|
|
2474
2446
|
backgroundImage: "none"
|
|
2475
2447
|
}
|
|
2476
2448
|
},
|
|
2477
|
-
"
|
|
2449
|
+
".cm-panel input[type=checkbox]": {
|
|
2478
2450
|
marginRight: "0.4rem !important"
|
|
2479
2451
|
}
|
|
2480
2452
|
};
|
|
2481
2453
|
var textTheme = {
|
|
2482
|
-
"
|
|
2483
|
-
fontFamily:
|
|
2454
|
+
".cm-scroller": {
|
|
2455
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2484
2456
|
},
|
|
2485
|
-
"
|
|
2486
|
-
fontFamily:
|
|
2457
|
+
".cm-placeholder": {
|
|
2458
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2487
2459
|
}
|
|
2488
2460
|
};
|
|
2489
2461
|
var markdownTheme = {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2462
|
+
".cm-scroller": {
|
|
2463
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2464
|
+
},
|
|
2465
|
+
".cm-placeholder": {
|
|
2466
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2493
2467
|
}
|
|
2494
2468
|
};
|
|
2495
2469
|
var codeTheme = {
|
|
2496
|
-
"
|
|
2497
|
-
fontFamily:
|
|
2470
|
+
".cm-scroller": {
|
|
2471
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2498
2472
|
},
|
|
2499
|
-
"
|
|
2500
|
-
fontFamily:
|
|
2473
|
+
".cm-placeholder": {
|
|
2474
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2501
2475
|
}
|
|
2502
2476
|
};
|
|
2503
2477
|
|
|
@@ -2506,21 +2480,23 @@ var EditorModes = [
|
|
|
2506
2480
|
"default",
|
|
2507
2481
|
"vim"
|
|
2508
2482
|
];
|
|
2509
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2510
|
-
const { themeMode } = useThemeContext();
|
|
2483
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, readonly, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
|
|
2511
2484
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2512
2485
|
tabBehavior: "limited"
|
|
2513
2486
|
});
|
|
2514
|
-
const
|
|
2515
|
-
const
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
state,
|
|
2487
|
+
const { themeMode } = useThemeContext();
|
|
2488
|
+
const rootRef = useRef(null);
|
|
2489
|
+
const [view, setView] = useState(null);
|
|
2490
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2519
2491
|
view
|
|
2520
|
-
|
|
2492
|
+
]);
|
|
2493
|
+
useEffect(() => {
|
|
2494
|
+
if (view && focus) {
|
|
2495
|
+
view.focus();
|
|
2496
|
+
}
|
|
2497
|
+
}, [
|
|
2521
2498
|
view,
|
|
2522
|
-
|
|
2523
|
-
root
|
|
2499
|
+
focus
|
|
2524
2500
|
]);
|
|
2525
2501
|
const { awareness: awareness2, peer } = model;
|
|
2526
2502
|
useEffect(() => {
|
|
@@ -2544,7 +2520,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2544
2520
|
themeMode
|
|
2545
2521
|
]);
|
|
2546
2522
|
useEffect(() => {
|
|
2547
|
-
if (view && comments2
|
|
2523
|
+
if (view && comments2 !== void 0) {
|
|
2548
2524
|
view.dispatch({
|
|
2549
2525
|
effects: setCommentRange.of({
|
|
2550
2526
|
model,
|
|
@@ -2557,20 +2533,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2557
2533
|
comments2
|
|
2558
2534
|
]);
|
|
2559
2535
|
useEffect(() => {
|
|
2560
|
-
if (!
|
|
2536
|
+
if (!model || !rootRef.current) {
|
|
2561
2537
|
return;
|
|
2562
2538
|
}
|
|
2563
|
-
const
|
|
2539
|
+
const state = EditorState2.create({
|
|
2564
2540
|
doc: model.text(),
|
|
2541
|
+
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2542
|
+
selection,
|
|
2565
2543
|
extensions: [
|
|
2566
2544
|
readonly && EditorState2.readOnly.of(readonly),
|
|
2567
2545
|
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
2568
2546
|
editorMode === "vim" && vim(),
|
|
2569
2547
|
// Theme.
|
|
2570
2548
|
// TODO(burdon): Make theme configurable.
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2549
|
+
EditorView12.baseTheme(defaultTheme),
|
|
2550
|
+
EditorView12.theme(theme ?? {}),
|
|
2551
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
|
2574
2552
|
// Storage and replication.
|
|
2575
2553
|
model.extension,
|
|
2576
2554
|
// Custom.
|
|
@@ -2578,19 +2556,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2578
2556
|
].filter(Boolean)
|
|
2579
2557
|
});
|
|
2580
2558
|
view?.destroy();
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
state: state2,
|
|
2585
|
-
parent: root
|
|
2586
|
-
})
|
|
2559
|
+
const newView = new EditorView12({
|
|
2560
|
+
parent: rootRef.current,
|
|
2561
|
+
state
|
|
2587
2562
|
});
|
|
2563
|
+
setView(newView);
|
|
2588
2564
|
return () => {
|
|
2589
|
-
|
|
2590
|
-
|
|
2565
|
+
newView?.destroy();
|
|
2566
|
+
setView(null);
|
|
2591
2567
|
};
|
|
2592
2568
|
}, [
|
|
2593
|
-
|
|
2569
|
+
rootRef,
|
|
2594
2570
|
model,
|
|
2595
2571
|
readonly,
|
|
2596
2572
|
editorMode,
|
|
@@ -2599,12 +2575,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2599
2575
|
const handleKeyUp = useCallback((event) => {
|
|
2600
2576
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2601
2577
|
switch (key) {
|
|
2602
|
-
case "Enter": {
|
|
2603
|
-
view?.contentDOM.focus();
|
|
2604
|
-
break;
|
|
2605
|
-
}
|
|
2606
2578
|
case "Escape": {
|
|
2607
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) &&
|
|
2579
|
+
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
|
|
2608
2580
|
break;
|
|
2609
2581
|
}
|
|
2610
2582
|
}
|
|
@@ -2614,16 +2586,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2614
2586
|
]);
|
|
2615
2587
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2616
2588
|
key: model.id,
|
|
2617
|
-
|
|
2589
|
+
role: "none",
|
|
2590
|
+
ref: rootRef,
|
|
2618
2591
|
tabIndex: 0,
|
|
2619
|
-
|
|
2620
|
-
...
|
|
2621
|
-
|
|
2592
|
+
onKeyUp: handleKeyUp,
|
|
2593
|
+
...slots.root,
|
|
2594
|
+
...editorMode !== "vim" && tabsterDOMAttribute
|
|
2622
2595
|
});
|
|
2623
2596
|
});
|
|
2624
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2597
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = textTheme, slots, ...props }, forwardedRef) => {
|
|
2625
2598
|
const { themeMode } = useThemeContext();
|
|
2626
|
-
const
|
|
2599
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2627
2600
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2628
2601
|
ref: forwardedRef,
|
|
2629
2602
|
readonly,
|
|
@@ -2631,17 +2604,18 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
|
|
|
2631
2604
|
basicBundle({
|
|
2632
2605
|
readonly,
|
|
2633
2606
|
themeMode,
|
|
2634
|
-
placeholder:
|
|
2607
|
+
placeholder: placeholder3
|
|
2635
2608
|
}),
|
|
2636
2609
|
...extensions
|
|
2637
2610
|
],
|
|
2638
|
-
|
|
2611
|
+
theme,
|
|
2612
|
+
slots: updatedSlots,
|
|
2639
2613
|
...props
|
|
2640
2614
|
});
|
|
2641
2615
|
});
|
|
2642
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2616
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = markdownTheme, slots, ...props }, forwardedRef) => {
|
|
2643
2617
|
const { themeMode } = useThemeContext();
|
|
2644
|
-
const
|
|
2618
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2645
2619
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2646
2620
|
ref: forwardedRef,
|
|
2647
2621
|
readonly,
|
|
@@ -2649,34 +2623,29 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
|
|
|
2649
2623
|
markdownBundle({
|
|
2650
2624
|
readonly,
|
|
2651
2625
|
themeMode,
|
|
2652
|
-
placeholder:
|
|
2626
|
+
placeholder: placeholder3
|
|
2653
2627
|
}),
|
|
2654
2628
|
...extensions
|
|
2655
2629
|
],
|
|
2656
|
-
|
|
2630
|
+
theme,
|
|
2631
|
+
slots: updatedSlots,
|
|
2657
2632
|
...props
|
|
2658
2633
|
});
|
|
2659
2634
|
});
|
|
2660
2635
|
var defaultSlots = {
|
|
2661
2636
|
root: {
|
|
2662
|
-
className: mx3("p-2", inputSurface)
|
|
2637
|
+
className: mx3("p-2 overflow-y-auto", inputSurface)
|
|
2663
2638
|
}
|
|
2664
2639
|
};
|
|
2665
2640
|
var defaultTextSlots = {
|
|
2666
|
-
...defaultSlots
|
|
2667
|
-
editor: {
|
|
2668
|
-
theme: textTheme
|
|
2669
|
-
}
|
|
2641
|
+
...defaultSlots
|
|
2670
2642
|
};
|
|
2671
2643
|
var defaultMarkdownSlots = {
|
|
2672
|
-
...defaultSlots
|
|
2673
|
-
editor: {
|
|
2674
|
-
theme: markdownTheme
|
|
2675
|
-
}
|
|
2644
|
+
...defaultSlots
|
|
2676
2645
|
};
|
|
2677
2646
|
|
|
2678
2647
|
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2679
|
-
import
|
|
2648
|
+
import get4 from "lodash.get";
|
|
2680
2649
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
2681
2650
|
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2682
2651
|
|
|
@@ -2786,7 +2755,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2786
2755
|
};
|
|
2787
2756
|
|
|
2788
2757
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2789
|
-
import { StateField as
|
|
2758
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
|
2790
2759
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2791
2760
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2792
2761
|
|
|
@@ -2795,15 +2764,13 @@ import * as decoding from "lib0/decoding";
|
|
|
2795
2764
|
import * as encoding from "lib0/encoding";
|
|
2796
2765
|
import { Observable } from "lib0/observable";
|
|
2797
2766
|
import * as YP from "y-protocols/awareness";
|
|
2798
|
-
import * as Y2 from "yjs";
|
|
2799
2767
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2800
2768
|
import { log as log4 } from "@dxos/log";
|
|
2801
|
-
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2802
2769
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2803
2770
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2804
2771
|
invariant4(text?.doc && text?.content, void 0, {
|
|
2805
2772
|
F: __dxlog_file5,
|
|
2806
|
-
L:
|
|
2773
|
+
L: 21,
|
|
2807
2774
|
S: void 0,
|
|
2808
2775
|
A: [
|
|
2809
2776
|
"text?.doc && text?.content",
|
|
@@ -2819,34 +2786,6 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
2819
2786
|
id: text.doc.guid,
|
|
2820
2787
|
content: text.content,
|
|
2821
2788
|
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
2789
|
extension: [
|
|
2851
2790
|
modelState.init(() => model),
|
|
2852
2791
|
yjs(text.content, provider?.awareness)
|
|
@@ -2896,7 +2835,7 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2896
2835
|
origin
|
|
2897
2836
|
}, {
|
|
2898
2837
|
F: __dxlog_file5,
|
|
2899
|
-
L:
|
|
2838
|
+
L: 100,
|
|
2900
2839
|
S: this,
|
|
2901
2840
|
C: (f, a) => f(...a)
|
|
2902
2841
|
});
|
|
@@ -2909,7 +2848,7 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2909
2848
|
_handleSpaceMessage({ payload }) {
|
|
2910
2849
|
log4("space message", payload, {
|
|
2911
2850
|
F: __dxlog_file5,
|
|
2912
|
-
L:
|
|
2851
|
+
L: 109,
|
|
2913
2852
|
S: this,
|
|
2914
2853
|
C: (f, a) => f(...a)
|
|
2915
2854
|
});
|
|
@@ -2953,13 +2892,13 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2953
2892
|
};
|
|
2954
2893
|
|
|
2955
2894
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2956
|
-
var modelState =
|
|
2895
|
+
var modelState = StateField5.define({
|
|
2957
2896
|
create: () => void 0,
|
|
2958
2897
|
update: (model) => model
|
|
2959
2898
|
});
|
|
2960
2899
|
var useTextModel = (props) => {
|
|
2961
2900
|
const { identity, space, text } = props;
|
|
2962
|
-
const [model, setModel] = useState2(
|
|
2901
|
+
const [model, setModel] = useState2();
|
|
2963
2902
|
useEffect2(() => setModel(createModel(props)), [
|
|
2964
2903
|
identity,
|
|
2965
2904
|
space,
|
|
@@ -2997,7 +2936,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2997
2936
|
const model = {
|
|
2998
2937
|
id: obj.id,
|
|
2999
2938
|
content: doc,
|
|
3000
|
-
text: () =>
|
|
2939
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3001
2940
|
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3002
2941
|
extension: [
|
|
3003
2942
|
modelState.init(() => model),
|
|
@@ -3018,6 +2957,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3018
2957
|
export {
|
|
3019
2958
|
AwarenessProvider,
|
|
3020
2959
|
BaseTextEditor,
|
|
2960
|
+
Cursor,
|
|
3021
2961
|
Doc,
|
|
3022
2962
|
EditorModes,
|
|
3023
2963
|
MarkdownEditor,
|
|
@@ -3033,16 +2973,19 @@ export {
|
|
|
3033
2973
|
awareness,
|
|
3034
2974
|
basicBundle,
|
|
3035
2975
|
blast,
|
|
2976
|
+
callbackWrapper,
|
|
3036
2977
|
code2 as code,
|
|
3037
2978
|
codeTheme,
|
|
3038
2979
|
comments,
|
|
3039
2980
|
createAutomergeModel,
|
|
3040
2981
|
createYjsModel,
|
|
2982
|
+
cursorConverter,
|
|
3041
2983
|
defaultMarkdownSlots,
|
|
3042
2984
|
defaultOptions,
|
|
3043
2985
|
defaultSlots,
|
|
3044
2986
|
defaultTextSlots,
|
|
3045
2987
|
defaultTheme,
|
|
2988
|
+
getToken,
|
|
3046
2989
|
hr,
|
|
3047
2990
|
image,
|
|
3048
2991
|
link,
|
|
@@ -3053,7 +2996,6 @@ export {
|
|
|
3053
2996
|
markdownTagsExtensions,
|
|
3054
2997
|
markdownTheme,
|
|
3055
2998
|
mention,
|
|
3056
|
-
mermaid,
|
|
3057
2999
|
modelState,
|
|
3058
3000
|
setCommentRange,
|
|
3059
3001
|
setFocus,
|