@dxos/react-ui-editor 0.3.11-main.9c729f3 → 0.3.11-main.9d68491
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 +292 -267
- 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 +10 -10
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +2 -2
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- 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/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.map +1 -1
- 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 +0 -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.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/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/package.json +22 -22
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +13 -11
- package/src/components/TextEditor/TextEditor.stories.tsx +3 -4
- package/src/components/TextEditor/TextEditor.tsx +59 -45
- package/src/extensions/autocomplete.ts +18 -17
- package/src/extensions/automerge/index.ts +1 -0
- package/src/extensions/code.ts +4 -5
- package/src/extensions/comments.ts +4 -5
- package/src/extensions/hr.ts +2 -3
- package/src/extensions/image.ts +38 -20
- package/src/extensions/index.ts +0 -1
- package/src/extensions/link.ts +82 -84
- package/src/extensions/markdown/highlight.ts +3 -4
- package/src/extensions/table.ts +9 -3
- package/src/extensions/tasklist.ts +1 -3
- package/src/hooks/useTextModel.ts +1 -1
- package/src/index.ts +3 -0
- package/src/styles/tokens.ts +3 -0
- package/src/themes/default.ts +39 -33
- package/dist/types/src/extensions/mermaid.d.ts +0 -3
- package/dist/types/src/extensions/mermaid.d.ts.map +0 -1
- package/src/extensions/mermaid.ts +0 -11
|
@@ -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
|
};
|
|
@@ -342,8 +343,8 @@ var automerge3 = ({ handle, path }) => {
|
|
|
342
343
|
};
|
|
343
344
|
handle.addListener("change", this._handleChange);
|
|
344
345
|
}
|
|
345
|
-
update(
|
|
346
|
-
if (
|
|
346
|
+
update(update2) {
|
|
347
|
+
if (update2.transactions.length > 0 && update2.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
347
348
|
queueMicrotask(() => {
|
|
348
349
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
349
350
|
});
|
|
@@ -412,13 +413,13 @@ var RemoteSelectionsDecorator = class {
|
|
|
412
413
|
void this._ctx.dispose();
|
|
413
414
|
this._provider.close();
|
|
414
415
|
}
|
|
415
|
-
update(
|
|
416
|
-
this._updateLocalSelection(
|
|
417
|
-
this._updateRemoteSelections(
|
|
416
|
+
update(update2) {
|
|
417
|
+
this._updateLocalSelection(update2);
|
|
418
|
+
this._updateRemoteSelections(update2);
|
|
418
419
|
}
|
|
419
|
-
_updateLocalSelection(
|
|
420
|
-
const hasFocus =
|
|
421
|
-
const { anchor = void 0, head = void 0 } = hasFocus ?
|
|
420
|
+
_updateLocalSelection(update2) {
|
|
421
|
+
const hasFocus = update2.view.hasFocus && update2.view.dom.ownerDocument.hasFocus();
|
|
422
|
+
const { anchor = void 0, head = void 0 } = hasFocus ? update2.state.selection.main : {};
|
|
422
423
|
if (this._lastAnchor === anchor && this._lastHead === head) {
|
|
423
424
|
return;
|
|
424
425
|
}
|
|
@@ -429,7 +430,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
429
430
|
head: this._cursorConverter.toCursor(head)
|
|
430
431
|
} : void 0);
|
|
431
432
|
}
|
|
432
|
-
_updateRemoteSelections(
|
|
433
|
+
_updateRemoteSelections(update2) {
|
|
433
434
|
const decorations = [];
|
|
434
435
|
const awarenessStates = this._provider.getRemoteStates();
|
|
435
436
|
for (const state of awarenessStates) {
|
|
@@ -438,10 +439,10 @@ var RemoteSelectionsDecorator = class {
|
|
|
438
439
|
if (anchor == null || head == null) {
|
|
439
440
|
continue;
|
|
440
441
|
}
|
|
441
|
-
const start = Math.min(Math.min(anchor, head),
|
|
442
|
-
const end = Math.min(Math.max(anchor, head),
|
|
443
|
-
const startLine =
|
|
444
|
-
const endLine =
|
|
442
|
+
const start = Math.min(Math.min(anchor, head), update2.view.state.doc.length);
|
|
443
|
+
const end = Math.min(Math.max(anchor, head), update2.view.state.doc.length);
|
|
444
|
+
const startLine = update2.view.state.doc.lineAt(start);
|
|
445
|
+
const endLine = update2.view.state.doc.lineAt(end);
|
|
445
446
|
const color = state.info.color ?? "#30bced";
|
|
446
447
|
const lightColor = state.info.lightColor ?? color + "33";
|
|
447
448
|
if (startLine.number === endLine.number) {
|
|
@@ -477,7 +478,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
477
478
|
})
|
|
478
479
|
});
|
|
479
480
|
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
480
|
-
const linePos =
|
|
481
|
+
const linePos = update2.view.state.doc.line(i).from;
|
|
481
482
|
decorations.push({
|
|
482
483
|
from: linePos,
|
|
483
484
|
to: linePos,
|
|
@@ -667,12 +668,12 @@ var blast = (options = defaultOptions) => {
|
|
|
667
668
|
};
|
|
668
669
|
return [
|
|
669
670
|
// Cursor moved.
|
|
670
|
-
EditorView3.updateListener.of((
|
|
671
|
-
if (blaster?.node !==
|
|
671
|
+
EditorView3.updateListener.of((update2) => {
|
|
672
|
+
if (blaster?.node !== update2.view.scrollDOM) {
|
|
672
673
|
if (blaster) {
|
|
673
674
|
blaster.destroy();
|
|
674
675
|
}
|
|
675
|
-
blaster = new Blaster(
|
|
676
|
+
blaster = new Blaster(update2.view.scrollDOM, defaultsDeep({
|
|
676
677
|
particleGravity: 0.2,
|
|
677
678
|
particleShrinkRate: 0.995,
|
|
678
679
|
color: () => [
|
|
@@ -686,10 +687,10 @@ var blast = (options = defaultOptions) => {
|
|
|
686
687
|
} else {
|
|
687
688
|
blaster.resize();
|
|
688
689
|
}
|
|
689
|
-
const current =
|
|
690
|
+
const current = update2.state.selection.main.head;
|
|
690
691
|
if (current !== last) {
|
|
691
692
|
last = current;
|
|
692
|
-
const { element, point } = getPoint(
|
|
693
|
+
const { element, point } = getPoint(update2.view, current - 1);
|
|
693
694
|
if (element && point) {
|
|
694
695
|
blaster.spawn({
|
|
695
696
|
element,
|
|
@@ -930,7 +931,6 @@ var random = (min, max) => {
|
|
|
930
931
|
|
|
931
932
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
932
933
|
import { ViewPlugin as ViewPlugin3, EditorView as EditorView4, Decoration as Decoration2 } from "@codemirror/view";
|
|
933
|
-
import get2 from "lodash.get";
|
|
934
934
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
935
935
|
|
|
936
936
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1014,20 +1014,22 @@ var inlineUrl = mx(code, "px-1");
|
|
|
1014
1014
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1015
1015
|
|
|
1016
1016
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1017
|
+
import get2 from "lodash.get";
|
|
1017
1018
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1018
1019
|
var tokens = tailwindConfig({}).theme;
|
|
1020
|
+
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1019
1021
|
|
|
1020
1022
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1021
1023
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1022
1024
|
var styles2 = EditorView4.baseTheme({
|
|
1023
1025
|
"& .cm-codeblock": {
|
|
1024
|
-
fontFamily:
|
|
1026
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1025
1027
|
},
|
|
1026
1028
|
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1027
|
-
background:
|
|
1029
|
+
background: getToken("extend.colors.neutral.50")
|
|
1028
1030
|
},
|
|
1029
1031
|
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1030
|
-
background:
|
|
1032
|
+
background: getToken("extend.colors.neutral.850")
|
|
1031
1033
|
},
|
|
1032
1034
|
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1033
1035
|
display: "block",
|
|
@@ -1076,9 +1078,9 @@ var code2 = () => {
|
|
|
1076
1078
|
constructor(view) {
|
|
1077
1079
|
this.decorations = getDecorations(view);
|
|
1078
1080
|
}
|
|
1079
|
-
update(
|
|
1080
|
-
if (
|
|
1081
|
-
this.decorations = getDecorations(
|
|
1081
|
+
update(update2) {
|
|
1082
|
+
if (update2.docChanged || update2.viewportChanged) {
|
|
1083
|
+
this.decorations = getDecorations(update2.view);
|
|
1082
1084
|
}
|
|
1083
1085
|
}
|
|
1084
1086
|
}, {
|
|
@@ -1091,7 +1093,6 @@ var code2 = () => {
|
|
|
1091
1093
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1092
1094
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1093
1095
|
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1094
|
-
import get3 from "lodash.get";
|
|
1095
1096
|
import sortBy from "lodash.sortby";
|
|
1096
1097
|
import { debounce } from "@dxos/async";
|
|
1097
1098
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
@@ -1109,10 +1110,10 @@ var styles3 = EditorView5.baseTheme({
|
|
|
1109
1110
|
backgroundColor: "orange"
|
|
1110
1111
|
},
|
|
1111
1112
|
"& .cm-comment": {
|
|
1112
|
-
backgroundColor:
|
|
1113
|
+
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1113
1114
|
},
|
|
1114
1115
|
"& .cm-comment-active": {
|
|
1115
|
-
backgroundColor:
|
|
1116
|
+
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1116
1117
|
}
|
|
1117
1118
|
});
|
|
1118
1119
|
var marks = {
|
|
@@ -1203,7 +1204,7 @@ var BookmarkWidget = class extends WidgetType2 {
|
|
|
1203
1204
|
this._handleClick = _handleClick;
|
|
1204
1205
|
invariant2(this._id, void 0, {
|
|
1205
1206
|
F: __dxlog_file3,
|
|
1206
|
-
L:
|
|
1207
|
+
L: 168,
|
|
1207
1208
|
S: this,
|
|
1208
1209
|
A: [
|
|
1209
1210
|
"this._id",
|
|
@@ -1230,7 +1231,7 @@ var comments = (options = {}) => {
|
|
|
1230
1231
|
const cursorConverter3 = view.state.facet(CursorConverter);
|
|
1231
1232
|
invariant2(options.onCreate, void 0, {
|
|
1232
1233
|
F: __dxlog_file3,
|
|
1233
|
-
L:
|
|
1234
|
+
L: 224,
|
|
1234
1235
|
S: void 0,
|
|
1235
1236
|
A: [
|
|
1236
1237
|
"options.onCreate",
|
|
@@ -1291,8 +1292,8 @@ var comments = (options = {}) => {
|
|
|
1291
1292
|
constructor(view) {
|
|
1292
1293
|
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
1293
1294
|
}
|
|
1294
|
-
update(
|
|
1295
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(
|
|
1295
|
+
update(update2) {
|
|
1296
|
+
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update2, this.bookmarks);
|
|
1296
1297
|
}
|
|
1297
1298
|
}, {
|
|
1298
1299
|
decorations: (instance) => instance.bookmarks,
|
|
@@ -1361,7 +1362,7 @@ var comments = (options = {}) => {
|
|
|
1361
1362
|
thread: range.id
|
|
1362
1363
|
}, {
|
|
1363
1364
|
F: __dxlog_file3,
|
|
1364
|
-
L:
|
|
1365
|
+
L: 358,
|
|
1365
1366
|
S: void 0,
|
|
1366
1367
|
C: (f, a) => f(...a)
|
|
1367
1368
|
});
|
|
@@ -1429,7 +1430,7 @@ var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
|
1429
1430
|
const parts = cursor.split(":");
|
|
1430
1431
|
const from = cursorConverter3.fromCursor(parts[0]);
|
|
1431
1432
|
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1432
|
-
return from && to ? {
|
|
1433
|
+
return from !== void 0 && to !== void 0 ? {
|
|
1433
1434
|
from,
|
|
1434
1435
|
to
|
|
1435
1436
|
} : void 0;
|
|
@@ -1437,12 +1438,11 @@ var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
|
1437
1438
|
|
|
1438
1439
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
1440
|
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin5, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1440
|
-
import get4 from "lodash.get";
|
|
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
1448
|
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
@@ -1471,8 +1471,8 @@ var hr = () => [
|
|
|
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 {
|
|
1488
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1489
1489
|
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType4 } 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
1541
|
var ImageWidget = class extends WidgetType4 {
|
|
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 WidgetType5, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin6 } 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
|
+
ViewPlugin6.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: {
|
|
@@ -1594,14 +1614,13 @@ var link = (options = {}) => {
|
|
|
1594
1614
|
return extensions;
|
|
1595
1615
|
};
|
|
1596
1616
|
var LinkButton = class extends WidgetType5 {
|
|
1597
|
-
constructor(
|
|
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");
|
|
@@ -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,20 +1709,19 @@ 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(),
|
|
@@ -1882,9 +1905,9 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1882
1905
|
class: "font-mono"
|
|
1883
1906
|
}
|
|
1884
1907
|
], {
|
|
1885
|
-
scope:
|
|
1908
|
+
scope: markdownLanguage2,
|
|
1886
1909
|
all: {
|
|
1887
|
-
fontFamily:
|
|
1910
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1888
1911
|
}
|
|
1889
1912
|
});
|
|
1890
1913
|
};
|
|
@@ -1894,7 +1917,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1894
1917
|
return [
|
|
1895
1918
|
EditorState.allowMultipleSelections.of(true),
|
|
1896
1919
|
EditorState.tabSize.of(2),
|
|
1897
|
-
|
|
1920
|
+
EditorView9.lineWrapping,
|
|
1898
1921
|
customKeymap(),
|
|
1899
1922
|
bracketMatching2(),
|
|
1900
1923
|
closeBrackets2(),
|
|
@@ -1914,7 +1937,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1914
1937
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1915
1938
|
// https://github.github.com/gfm
|
|
1916
1939
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1917
|
-
base:
|
|
1940
|
+
base: markdownLanguage3,
|
|
1918
1941
|
// Languages for syntax highlighting fenced code blocks.
|
|
1919
1942
|
codeLanguages: languages,
|
|
1920
1943
|
// Parser extensions.
|
|
@@ -1965,24 +1988,19 @@ var mention = ({ onSearch }) => {
|
|
|
1965
1988
|
});
|
|
1966
1989
|
};
|
|
1967
1990
|
|
|
1968
|
-
// packages/ui/react-ui-editor/src/extensions/mermaid.ts
|
|
1969
|
-
var mermaid = () => {
|
|
1970
|
-
return [];
|
|
1971
|
-
};
|
|
1972
|
-
|
|
1973
1991
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1974
1992
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1975
|
-
import { RangeSetBuilder as
|
|
1976
|
-
import { Decoration as Decoration7, EditorView as
|
|
1993
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1994
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
1977
1995
|
var table = (options = {}) => {
|
|
1978
|
-
return
|
|
1979
|
-
create: (state) =>
|
|
1980
|
-
update: (_, tr) =>
|
|
1981
|
-
provide: (field) =>
|
|
1996
|
+
return StateField4.define({
|
|
1997
|
+
create: (state) => update(state, options),
|
|
1998
|
+
update: (_, tr) => update(tr.state, options),
|
|
1999
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1982
2000
|
});
|
|
1983
2001
|
};
|
|
1984
|
-
var
|
|
1985
|
-
const builder = new
|
|
2002
|
+
var update = (state, options) => {
|
|
2003
|
+
const builder = new RangeSetBuilder2();
|
|
1986
2004
|
const cursor = state.selection.main.head;
|
|
1987
2005
|
const tables = [];
|
|
1988
2006
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2023,7 +2041,6 @@ var update3 = (state, options) => {
|
|
|
2023
2041
|
tables.forEach((table2) => {
|
|
2024
2042
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2025
2043
|
hide && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
2026
|
-
block: true,
|
|
2027
2044
|
widget: new TableWidget(table2)
|
|
2028
2045
|
}));
|
|
2029
2046
|
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
@@ -2038,7 +2055,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2038
2055
|
this._table = _table;
|
|
2039
2056
|
}
|
|
2040
2057
|
eq(other) {
|
|
2041
|
-
return this._table.
|
|
2058
|
+
return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
|
|
2042
2059
|
}
|
|
2043
2060
|
toDOM(view) {
|
|
2044
2061
|
const table2 = document.createElement("table");
|
|
@@ -2064,26 +2081,28 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2064
2081
|
}
|
|
2065
2082
|
return table2;
|
|
2066
2083
|
}
|
|
2084
|
+
ignoreEvent(e) {
|
|
2085
|
+
return !/^mouse/.test(e.type);
|
|
2086
|
+
}
|
|
2067
2087
|
};
|
|
2068
2088
|
|
|
2069
2089
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2070
|
-
import { EditorView as
|
|
2071
|
-
var styles5 =
|
|
2090
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType7, MatchDecorator as MatchDecorator3, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
2091
|
+
var styles5 = EditorView11.baseTheme({
|
|
2072
2092
|
"& .cm-task-item": {
|
|
2073
2093
|
paddingLeft: "4px",
|
|
2074
2094
|
paddingRight: "8px"
|
|
2075
2095
|
}
|
|
2076
2096
|
});
|
|
2077
2097
|
var CheckboxWidget = class extends WidgetType7 {
|
|
2078
|
-
constructor(
|
|
2098
|
+
constructor(_checked, _indent, _onCheck) {
|
|
2079
2099
|
super();
|
|
2080
|
-
this._pos = _pos;
|
|
2081
2100
|
this._checked = _checked;
|
|
2082
2101
|
this._indent = _indent;
|
|
2083
2102
|
this._onCheck = _onCheck;
|
|
2084
2103
|
}
|
|
2085
2104
|
eq(other) {
|
|
2086
|
-
return this.
|
|
2105
|
+
return this._checked === other._checked && this._indent === other._indent;
|
|
2087
2106
|
}
|
|
2088
2107
|
toDOM(view) {
|
|
2089
2108
|
const wrap = document.createElement("span");
|
|
@@ -2115,7 +2134,7 @@ var tasklist = (options = {}) => {
|
|
|
2115
2134
|
const indent = Math.floor(match[1].length / 2);
|
|
2116
2135
|
const checked = match[2] === "x" || match[2] === "X";
|
|
2117
2136
|
return Decoration8.replace({
|
|
2118
|
-
widget: new CheckboxWidget(
|
|
2137
|
+
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2119
2138
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
2120
2139
|
view.dispatch({
|
|
2121
2140
|
changes: {
|
|
@@ -2132,16 +2151,16 @@ var tasklist = (options = {}) => {
|
|
|
2132
2151
|
});
|
|
2133
2152
|
}
|
|
2134
2153
|
});
|
|
2135
|
-
const tasks =
|
|
2154
|
+
const tasks = ViewPlugin7.fromClass(class {
|
|
2136
2155
|
constructor(view) {
|
|
2137
2156
|
this.tasks = taskMatcher.createDeco(view);
|
|
2138
2157
|
}
|
|
2139
|
-
update(
|
|
2140
|
-
this.tasks = taskMatcher.updateDeco(
|
|
2158
|
+
update(update2) {
|
|
2159
|
+
this.tasks = taskMatcher.updateDeco(update2, this.tasks);
|
|
2141
2160
|
}
|
|
2142
2161
|
}, {
|
|
2143
2162
|
decorations: (value) => value.tasks,
|
|
2144
|
-
provide: (plugin) =>
|
|
2163
|
+
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2145
2164
|
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
2146
2165
|
})
|
|
2147
2166
|
});
|
|
@@ -2230,7 +2249,7 @@ var yjs = (content, awareness2) => [
|
|
|
2230
2249
|
];
|
|
2231
2250
|
|
|
2232
2251
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2233
|
-
import
|
|
2252
|
+
import get3 from "lodash.get";
|
|
2234
2253
|
var defaultTheme = {
|
|
2235
2254
|
//
|
|
2236
2255
|
// Main layout:
|
|
@@ -2259,21 +2278,21 @@ var defaultTheme = {
|
|
|
2259
2278
|
"&.cm-focused": {
|
|
2260
2279
|
outline: "none"
|
|
2261
2280
|
},
|
|
2262
|
-
"
|
|
2281
|
+
".cm-scroller": {
|
|
2263
2282
|
overflow: "visible",
|
|
2264
|
-
fontFamily:
|
|
2283
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2265
2284
|
},
|
|
2266
|
-
"
|
|
2285
|
+
".cm-content": {
|
|
2267
2286
|
padding: 0,
|
|
2268
2287
|
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2269
2288
|
fontSize: "16px"
|
|
2270
2289
|
},
|
|
2271
2290
|
"&light .cm-content": {
|
|
2272
|
-
color:
|
|
2291
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
2273
2292
|
caretColor: "black"
|
|
2274
2293
|
},
|
|
2275
2294
|
"&dark .cm-content": {
|
|
2276
|
-
color:
|
|
2295
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
2277
2296
|
caretColor: "white"
|
|
2278
2297
|
},
|
|
2279
2298
|
//
|
|
@@ -2285,41 +2304,41 @@ var defaultTheme = {
|
|
|
2285
2304
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2286
2305
|
borderLeft: "2px solid white"
|
|
2287
2306
|
},
|
|
2288
|
-
"
|
|
2307
|
+
".cm-placeholder": {
|
|
2289
2308
|
fontWeight: 100
|
|
2290
2309
|
},
|
|
2291
2310
|
//
|
|
2292
2311
|
// line
|
|
2293
2312
|
//
|
|
2294
|
-
"
|
|
2313
|
+
".cm-line": {
|
|
2295
2314
|
paddingInline: 0
|
|
2296
2315
|
},
|
|
2297
|
-
"
|
|
2316
|
+
".cm-activeLine": {
|
|
2298
2317
|
background: "inherit"
|
|
2299
2318
|
},
|
|
2300
2319
|
//
|
|
2301
2320
|
// Selection
|
|
2302
2321
|
//
|
|
2303
2322
|
"&light .cm-selectionBackground": {
|
|
2304
|
-
background:
|
|
2323
|
+
background: get3(tokens, "extend.colors.primary.100")
|
|
2305
2324
|
},
|
|
2306
2325
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2307
|
-
background:
|
|
2326
|
+
background: get3(tokens, "extend.colors.primary.200")
|
|
2308
2327
|
},
|
|
2309
2328
|
"&dark .cm-selectionBackground": {
|
|
2310
|
-
background:
|
|
2329
|
+
background: get3(tokens, "extend.colors.primary.700")
|
|
2311
2330
|
},
|
|
2312
2331
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2313
|
-
background:
|
|
2332
|
+
background: get3(tokens, "extend.colors.primary.600")
|
|
2314
2333
|
},
|
|
2315
2334
|
//
|
|
2316
2335
|
// Search
|
|
2317
2336
|
//
|
|
2318
2337
|
"&light .cm-searchMatch": {
|
|
2319
|
-
backgroundColor:
|
|
2338
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2320
2339
|
},
|
|
2321
2340
|
"&dark .cm-searchMatch": {
|
|
2322
|
-
backgroundColor:
|
|
2341
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2323
2342
|
},
|
|
2324
2343
|
//
|
|
2325
2344
|
// collaboration
|
|
@@ -2331,95 +2350,101 @@ var defaultTheme = {
|
|
|
2331
2350
|
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2332
2351
|
mixBlendMode: "screen"
|
|
2333
2352
|
},
|
|
2334
|
-
"
|
|
2353
|
+
".cm-ySelectionInfo": {
|
|
2335
2354
|
padding: "2px 4px",
|
|
2336
2355
|
marginBlockStart: "-4px"
|
|
2337
2356
|
},
|
|
2338
|
-
"
|
|
2357
|
+
".cm-ySelection, & .cm-selectionMatch": {
|
|
2339
2358
|
paddingBlockStart: ".15em",
|
|
2340
2359
|
paddingBlockEnd: ".15em"
|
|
2341
2360
|
},
|
|
2342
|
-
"
|
|
2361
|
+
".cm-ySelectionCaret": {
|
|
2343
2362
|
display: "inline-block",
|
|
2344
2363
|
insetBlockStart: ".1em",
|
|
2345
2364
|
blockSize: "1.4em",
|
|
2346
2365
|
verticalAlign: "top"
|
|
2347
2366
|
},
|
|
2348
|
-
"
|
|
2367
|
+
".cm-yLineSelection": {
|
|
2349
2368
|
margin: 0
|
|
2350
2369
|
},
|
|
2351
2370
|
//
|
|
2352
2371
|
// link
|
|
2353
2372
|
//
|
|
2354
|
-
"
|
|
2355
|
-
color:
|
|
2373
|
+
".cm-link": {
|
|
2374
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
2356
2375
|
textDecorationLine: "underline",
|
|
2357
2376
|
textDecorationThickness: "1px",
|
|
2358
2377
|
textUnderlineOffset: "2px",
|
|
2359
2378
|
borderRadius: ".125rem",
|
|
2360
|
-
fontFamily:
|
|
2379
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2361
2380
|
},
|
|
2362
2381
|
//
|
|
2363
2382
|
// tooltip
|
|
2364
2383
|
//
|
|
2365
|
-
"
|
|
2384
|
+
".cm-tooltip": {
|
|
2366
2385
|
border: "none"
|
|
2367
2386
|
},
|
|
2368
|
-
"
|
|
2387
|
+
".cm-tooltip-below": {},
|
|
2369
2388
|
//
|
|
2370
2389
|
// autocomplete
|
|
2371
2390
|
//
|
|
2372
|
-
"
|
|
2391
|
+
".cm-tooltip-autocomplete": {
|
|
2373
2392
|
marginTop: "4px",
|
|
2374
2393
|
marginLeft: "-3px"
|
|
2375
2394
|
},
|
|
2376
|
-
"
|
|
2377
|
-
"
|
|
2378
|
-
"
|
|
2395
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
2396
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2397
|
+
".cm-completionIcon": {
|
|
2379
2398
|
display: "none"
|
|
2380
2399
|
},
|
|
2381
|
-
"
|
|
2382
|
-
fontFamily:
|
|
2400
|
+
".cm-completionLabel": {
|
|
2401
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2383
2402
|
},
|
|
2384
|
-
"
|
|
2403
|
+
".cm-completionMatchedText": {
|
|
2385
2404
|
textDecoration: "none"
|
|
2386
2405
|
},
|
|
2387
2406
|
//
|
|
2388
2407
|
// widgets
|
|
2389
2408
|
//
|
|
2390
|
-
"
|
|
2409
|
+
".cm-widgetBuffer": {
|
|
2391
2410
|
display: "none",
|
|
2392
2411
|
height: 0
|
|
2393
2412
|
},
|
|
2394
2413
|
//
|
|
2395
2414
|
// table
|
|
2396
2415
|
//
|
|
2397
|
-
"
|
|
2398
|
-
fontFamily: `${
|
|
2416
|
+
".cm-table *": {
|
|
2417
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2399
2418
|
textDecoration: "none !important"
|
|
2400
2419
|
},
|
|
2401
|
-
"
|
|
2420
|
+
".cm-table-head": {
|
|
2402
2421
|
padding: "2px 16px 2px 0px",
|
|
2403
|
-
borderBottom: `1px solid ${
|
|
2422
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2404
2423
|
fontWeight: 100,
|
|
2405
2424
|
textAlign: "left",
|
|
2406
|
-
color:
|
|
2425
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
2407
2426
|
},
|
|
2408
|
-
"
|
|
2427
|
+
".cm-table-cell": {
|
|
2409
2428
|
padding: "2px 16px 2px 0px"
|
|
2410
2429
|
},
|
|
2411
2430
|
//
|
|
2412
2431
|
// image
|
|
2413
2432
|
//
|
|
2414
|
-
"
|
|
2415
|
-
|
|
2433
|
+
".cm-image": {
|
|
2434
|
+
display: "block",
|
|
2435
|
+
height: "0"
|
|
2436
|
+
},
|
|
2437
|
+
".cm-image.cm-loaded-image": {
|
|
2438
|
+
height: "auto",
|
|
2439
|
+
borderTop: "0.5rem solid transparent",
|
|
2440
|
+
borderBottom: "0.5rem solid transparent"
|
|
2416
2441
|
},
|
|
2417
2442
|
//
|
|
2418
2443
|
// font size
|
|
2419
2444
|
// TODO(thure): This appears to be the best or only way to set selection caret heights, but it's far more verbose than it needs to be.
|
|
2420
2445
|
//
|
|
2421
|
-
...Object.keys(
|
|
2422
|
-
const height =
|
|
2446
|
+
...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
|
|
2447
|
+
const height = get3(tokens, [
|
|
2423
2448
|
"extend",
|
|
2424
2449
|
"fontSize",
|
|
2425
2450
|
fontSize,
|
|
@@ -2453,51 +2478,51 @@ var defaultTheme = {
|
|
|
2453
2478
|
* </div>
|
|
2454
2479
|
* </div
|
|
2455
2480
|
*/
|
|
2456
|
-
"
|
|
2457
|
-
border: `1px solid ${
|
|
2481
|
+
".cm-panels": {
|
|
2482
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2458
2483
|
},
|
|
2459
|
-
"
|
|
2460
|
-
background:
|
|
2461
|
-
fontFamily:
|
|
2484
|
+
".cm-panel": {
|
|
2485
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2486
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2462
2487
|
},
|
|
2463
|
-
"
|
|
2488
|
+
".cm-button": {
|
|
2464
2489
|
margin: "4px",
|
|
2465
|
-
fontFamily:
|
|
2466
|
-
background:
|
|
2490
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2491
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2467
2492
|
backgroundImage: "none",
|
|
2468
2493
|
border: "none",
|
|
2469
2494
|
"&:hover": {
|
|
2470
|
-
background:
|
|
2495
|
+
background: get3(tokens, "extend.colors.neutral.200")
|
|
2471
2496
|
},
|
|
2472
2497
|
"&:active": {
|
|
2473
|
-
background:
|
|
2498
|
+
background: get3(tokens, "extend.colors.neutral.300"),
|
|
2474
2499
|
backgroundImage: "none"
|
|
2475
2500
|
}
|
|
2476
2501
|
},
|
|
2477
|
-
"
|
|
2502
|
+
".cm-panel input[type=checkbox]": {
|
|
2478
2503
|
marginRight: "0.4rem !important"
|
|
2479
2504
|
}
|
|
2480
2505
|
};
|
|
2481
2506
|
var textTheme = {
|
|
2482
|
-
"
|
|
2483
|
-
fontFamily:
|
|
2507
|
+
".cm-scroller": {
|
|
2508
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2484
2509
|
},
|
|
2485
|
-
"
|
|
2486
|
-
fontFamily:
|
|
2510
|
+
".cm-placeholder": {
|
|
2511
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2487
2512
|
}
|
|
2488
2513
|
};
|
|
2489
2514
|
var markdownTheme = {
|
|
2490
2515
|
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
2491
|
-
"
|
|
2492
|
-
fontFamily:
|
|
2516
|
+
".cm-placeholder": {
|
|
2517
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2493
2518
|
}
|
|
2494
2519
|
};
|
|
2495
2520
|
var codeTheme = {
|
|
2496
|
-
"
|
|
2497
|
-
fontFamily:
|
|
2521
|
+
".cm-scroller": {
|
|
2522
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2498
2523
|
},
|
|
2499
|
-
"
|
|
2500
|
-
fontFamily:
|
|
2524
|
+
".cm-placeholder": {
|
|
2525
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2501
2526
|
}
|
|
2502
2527
|
};
|
|
2503
2528
|
|
|
@@ -2506,21 +2531,23 @@ var EditorModes = [
|
|
|
2506
2531
|
"default",
|
|
2507
2532
|
"vim"
|
|
2508
2533
|
];
|
|
2509
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2510
|
-
const { themeMode } = useThemeContext();
|
|
2534
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2511
2535
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2512
2536
|
tabBehavior: "limited"
|
|
2513
2537
|
});
|
|
2514
|
-
const
|
|
2515
|
-
const
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
state,
|
|
2538
|
+
const { themeMode } = useThemeContext();
|
|
2539
|
+
const rootRef = useRef(null);
|
|
2540
|
+
const [view, setView] = useState(null);
|
|
2541
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2519
2542
|
view
|
|
2520
|
-
|
|
2543
|
+
]);
|
|
2544
|
+
useEffect(() => {
|
|
2545
|
+
if (view && focus) {
|
|
2546
|
+
view.focus();
|
|
2547
|
+
}
|
|
2548
|
+
}, [
|
|
2521
2549
|
view,
|
|
2522
|
-
|
|
2523
|
-
root
|
|
2550
|
+
focus
|
|
2524
2551
|
]);
|
|
2525
2552
|
const { awareness: awareness2, peer } = model;
|
|
2526
2553
|
useEffect(() => {
|
|
@@ -2557,20 +2584,21 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2557
2584
|
comments2
|
|
2558
2585
|
]);
|
|
2559
2586
|
useEffect(() => {
|
|
2560
|
-
if (!
|
|
2587
|
+
if (!model || !rootRef.current) {
|
|
2561
2588
|
return;
|
|
2562
2589
|
}
|
|
2563
|
-
const
|
|
2590
|
+
const state = EditorState2.create({
|
|
2564
2591
|
doc: model.text(),
|
|
2592
|
+
selection,
|
|
2565
2593
|
extensions: [
|
|
2566
2594
|
readonly && EditorState2.readOnly.of(readonly),
|
|
2567
2595
|
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
2568
2596
|
editorMode === "vim" && vim(),
|
|
2569
2597
|
// Theme.
|
|
2570
2598
|
// TODO(burdon): Make theme configurable.
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2599
|
+
EditorView12.baseTheme(defaultTheme),
|
|
2600
|
+
EditorView12.theme(slots?.editor?.theme ?? {}),
|
|
2601
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
|
2574
2602
|
// Storage and replication.
|
|
2575
2603
|
model.extension,
|
|
2576
2604
|
// Custom.
|
|
@@ -2578,19 +2606,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2578
2606
|
].filter(Boolean)
|
|
2579
2607
|
});
|
|
2580
2608
|
view?.destroy();
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
state: state2,
|
|
2585
|
-
parent: root
|
|
2586
|
-
})
|
|
2609
|
+
const newView = new EditorView12({
|
|
2610
|
+
parent: rootRef.current,
|
|
2611
|
+
state
|
|
2587
2612
|
});
|
|
2613
|
+
setView(newView);
|
|
2588
2614
|
return () => {
|
|
2589
|
-
|
|
2590
|
-
|
|
2615
|
+
newView?.destroy();
|
|
2616
|
+
setView(null);
|
|
2591
2617
|
};
|
|
2592
2618
|
}, [
|
|
2593
|
-
|
|
2619
|
+
rootRef,
|
|
2594
2620
|
model,
|
|
2595
2621
|
readonly,
|
|
2596
2622
|
editorMode,
|
|
@@ -2599,12 +2625,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2599
2625
|
const handleKeyUp = useCallback((event) => {
|
|
2600
2626
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2601
2627
|
switch (key) {
|
|
2602
|
-
case "Enter": {
|
|
2603
|
-
view?.contentDOM.focus();
|
|
2604
|
-
break;
|
|
2605
|
-
}
|
|
2606
2628
|
case "Escape": {
|
|
2607
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) &&
|
|
2629
|
+
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
|
|
2608
2630
|
break;
|
|
2609
2631
|
}
|
|
2610
2632
|
}
|
|
@@ -2614,16 +2636,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2614
2636
|
]);
|
|
2615
2637
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2616
2638
|
key: model.id,
|
|
2617
|
-
ref:
|
|
2639
|
+
ref: rootRef,
|
|
2618
2640
|
tabIndex: 0,
|
|
2619
2641
|
...slots?.root,
|
|
2620
2642
|
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2621
2643
|
onKeyUp: handleKeyUp
|
|
2622
2644
|
});
|
|
2623
2645
|
});
|
|
2624
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots
|
|
2646
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots, ...props }, forwardedRef) => {
|
|
2625
2647
|
const { themeMode } = useThemeContext();
|
|
2626
|
-
const
|
|
2648
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2627
2649
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2628
2650
|
ref: forwardedRef,
|
|
2629
2651
|
readonly,
|
|
@@ -2631,17 +2653,17 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
|
|
|
2631
2653
|
basicBundle({
|
|
2632
2654
|
readonly,
|
|
2633
2655
|
themeMode,
|
|
2634
|
-
placeholder:
|
|
2656
|
+
placeholder: updatedSlots?.editor?.placeholder
|
|
2635
2657
|
}),
|
|
2636
2658
|
...extensions
|
|
2637
2659
|
],
|
|
2638
|
-
slots,
|
|
2660
|
+
slots: updatedSlots,
|
|
2639
2661
|
...props
|
|
2640
2662
|
});
|
|
2641
2663
|
});
|
|
2642
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots
|
|
2664
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots, ...props }, forwardedRef) => {
|
|
2643
2665
|
const { themeMode } = useThemeContext();
|
|
2644
|
-
const
|
|
2666
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2645
2667
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2646
2668
|
ref: forwardedRef,
|
|
2647
2669
|
readonly,
|
|
@@ -2649,11 +2671,11 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
|
|
|
2649
2671
|
markdownBundle({
|
|
2650
2672
|
readonly,
|
|
2651
2673
|
themeMode,
|
|
2652
|
-
placeholder:
|
|
2674
|
+
placeholder: updatedSlots?.editor?.placeholder
|
|
2653
2675
|
}),
|
|
2654
2676
|
...extensions
|
|
2655
2677
|
],
|
|
2656
|
-
slots,
|
|
2678
|
+
slots: updatedSlots,
|
|
2657
2679
|
...props
|
|
2658
2680
|
});
|
|
2659
2681
|
});
|
|
@@ -2676,7 +2698,7 @@ var defaultMarkdownSlots = {
|
|
|
2676
2698
|
};
|
|
2677
2699
|
|
|
2678
2700
|
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2679
|
-
import
|
|
2701
|
+
import get4 from "lodash.get";
|
|
2680
2702
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
2681
2703
|
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2682
2704
|
|
|
@@ -2786,7 +2808,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2786
2808
|
};
|
|
2787
2809
|
|
|
2788
2810
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2789
|
-
import { StateField as
|
|
2811
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
|
2790
2812
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2791
2813
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2792
2814
|
|
|
@@ -2953,13 +2975,13 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2953
2975
|
};
|
|
2954
2976
|
|
|
2955
2977
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2956
|
-
var modelState =
|
|
2978
|
+
var modelState = StateField5.define({
|
|
2957
2979
|
create: () => void 0,
|
|
2958
2980
|
update: (model) => model
|
|
2959
2981
|
});
|
|
2960
2982
|
var useTextModel = (props) => {
|
|
2961
2983
|
const { identity, space, text } = props;
|
|
2962
|
-
const [model, setModel] = useState2(
|
|
2984
|
+
const [model, setModel] = useState2();
|
|
2963
2985
|
useEffect2(() => setModel(createModel(props)), [
|
|
2964
2986
|
identity,
|
|
2965
2987
|
space,
|
|
@@ -2997,7 +3019,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2997
3019
|
const model = {
|
|
2998
3020
|
id: obj.id,
|
|
2999
3021
|
content: doc,
|
|
3000
|
-
text: () =>
|
|
3022
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3001
3023
|
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3002
3024
|
extension: [
|
|
3003
3025
|
modelState.init(() => model),
|
|
@@ -3018,6 +3040,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3018
3040
|
export {
|
|
3019
3041
|
AwarenessProvider,
|
|
3020
3042
|
BaseTextEditor,
|
|
3043
|
+
CursorConverter,
|
|
3021
3044
|
Doc,
|
|
3022
3045
|
EditorModes,
|
|
3023
3046
|
MarkdownEditor,
|
|
@@ -3033,16 +3056,19 @@ export {
|
|
|
3033
3056
|
awareness,
|
|
3034
3057
|
basicBundle,
|
|
3035
3058
|
blast,
|
|
3059
|
+
callbackWrapper,
|
|
3036
3060
|
code2 as code,
|
|
3037
3061
|
codeTheme,
|
|
3038
3062
|
comments,
|
|
3039
3063
|
createAutomergeModel,
|
|
3040
3064
|
createYjsModel,
|
|
3065
|
+
cursorConverter,
|
|
3041
3066
|
defaultMarkdownSlots,
|
|
3042
3067
|
defaultOptions,
|
|
3043
3068
|
defaultSlots,
|
|
3044
3069
|
defaultTextSlots,
|
|
3045
3070
|
defaultTheme,
|
|
3071
|
+
getToken,
|
|
3046
3072
|
hr,
|
|
3047
3073
|
image,
|
|
3048
3074
|
link,
|
|
@@ -3053,7 +3079,6 @@ export {
|
|
|
3053
3079
|
markdownTagsExtensions,
|
|
3054
3080
|
markdownTheme,
|
|
3055
3081
|
mention,
|
|
3056
|
-
mermaid,
|
|
3057
3082
|
modelState,
|
|
3058
3083
|
setCommentRange,
|
|
3059
3084
|
setFocus,
|