@dxos/react-ui-editor 0.3.11-main.121f5a8 → 0.3.11-main.13264f1
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 +618 -748
- 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.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +2 -2
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness.d.ts +1 -3
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +2 -2
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +3 -3
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -7
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +7 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +1 -4
- package/dist/types/src/hooks/defs.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts +17 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/package.json +24 -27
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +3 -1
- package/src/components/TextEditor/TextEditor.tsx +11 -14
- package/src/components/TextEditor/comments.stories.tsx +5 -5
- package/src/extensions/awareness.ts +14 -31
- package/src/extensions/basic.ts +3 -3
- package/src/extensions/comments.ts +15 -15
- package/src/extensions/index.ts +0 -7
- package/src/extensions/{code.ts → markdown/code.ts} +1 -1
- package/src/extensions/markdown/heading.ts +60 -0
- package/src/extensions/{hr.ts → markdown/hr.ts} +1 -1
- package/src/extensions/markdown/index.ts +7 -0
- package/src/extensions/{tasklist.ts → markdown/tasklist.ts} +1 -1
- package/src/hooks/awareness-provider.ts +24 -20
- package/src/hooks/defs.ts +1 -6
- package/src/hooks/index.ts +1 -2
- package/src/hooks/useTextEditor.ts +29 -0
- package/src/hooks/useTextModel.ts +46 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -4
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts +0 -28
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
- package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
- package/dist/types/src/testing/proto/index.d.ts +0 -2
- package/dist/types/src/testing/proto/index.d.ts.map +0 -1
- package/dist/types/src/testing/replicator.d.ts +0 -45
- package/dist/types/src/testing/replicator.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/yjs/cursor.ts +0 -22
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.test.ts +0 -35
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -53
- package/src/hooks/yjs.ts +0 -157
- package/src/testing/index.ts +0 -6
- package/src/testing/proto/gen/schema.ts +0 -49
- package/src/testing/proto/index.ts +0 -5
- package/src/testing/proto/schema.proto +0 -15
- package/src/testing/replicator.ts +0 -184
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
- /package/src/extensions/{image.ts → markdown/image.ts} +0 -0
- /package/src/extensions/{link.ts → markdown/link.ts} +0 -0
- /package/src/extensions/{table.ts → markdown/table.ts} +0 -0
|
@@ -11,10 +11,10 @@ import { EditorView as EditorView13 } from "@codemirror/view";
|
|
|
11
11
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect as
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
15
15
|
import { log as log2 } from "@dxos/log";
|
|
16
|
-
import { useThemeContext
|
|
17
|
-
import {
|
|
16
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
+
import { attentionSurface, 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";
|
|
@@ -293,9 +293,9 @@ var Cursor = class _Cursor {
|
|
|
293
293
|
}
|
|
294
294
|
static {
|
|
295
295
|
this.getCursorFromRange = (state, range) => {
|
|
296
|
-
const
|
|
297
|
-
const from =
|
|
298
|
-
const to =
|
|
296
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
297
|
+
const from = cursorConverter2.toCursor(range.from);
|
|
298
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
|
299
299
|
return [
|
|
300
300
|
from,
|
|
301
301
|
to
|
|
@@ -304,10 +304,10 @@ var Cursor = class _Cursor {
|
|
|
304
304
|
}
|
|
305
305
|
static {
|
|
306
306
|
this.getRangeFromCursor = (state, cursor) => {
|
|
307
|
-
const
|
|
307
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
308
308
|
const parts = cursor.split(":");
|
|
309
|
-
const from =
|
|
310
|
-
const to =
|
|
309
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
|
310
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
|
311
311
|
return from !== void 0 && to !== void 0 ? {
|
|
312
312
|
from,
|
|
313
313
|
to
|
|
@@ -386,21 +386,17 @@ var automerge3 = ({ handle, path }) => {
|
|
|
386
386
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
387
387
|
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
388
388
|
import { Decoration, EditorView as EditorView2, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
389
|
-
import { useEffect } from "react";
|
|
390
389
|
import { Event } from "@dxos/async";
|
|
391
390
|
import { Context } from "@dxos/context";
|
|
392
|
-
import { generateName } from "@dxos/display-name";
|
|
393
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
394
|
-
import { getColorForValue } from "@dxos/react-ui-theme";
|
|
395
391
|
var dummyProvider = {
|
|
396
392
|
remoteStateChange: new Event(),
|
|
397
393
|
open: () => {
|
|
398
394
|
},
|
|
399
395
|
close: () => {
|
|
400
396
|
},
|
|
397
|
+
getRemoteStates: () => [],
|
|
401
398
|
update: () => {
|
|
402
|
-
}
|
|
403
|
-
getRemoteStates: () => []
|
|
399
|
+
}
|
|
404
400
|
};
|
|
405
401
|
var AwarenessProvider = Facet2.define({
|
|
406
402
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
@@ -415,29 +411,6 @@ var awareness = (provider = dummyProvider) => {
|
|
|
415
411
|
styles
|
|
416
412
|
];
|
|
417
413
|
};
|
|
418
|
-
var useAwareness = ({ awareness: awareness2, peer }) => {
|
|
419
|
-
const { themeMode } = useThemeContext();
|
|
420
|
-
useEffect(() => {
|
|
421
|
-
if (awareness2 && peer) {
|
|
422
|
-
awareness2.setLocalStateField("user", {
|
|
423
|
-
name: peer.name ?? generateName(peer.id),
|
|
424
|
-
color: getColorForValue({
|
|
425
|
-
value: peer.id,
|
|
426
|
-
type: "color"
|
|
427
|
-
}),
|
|
428
|
-
colorLight: getColorForValue({
|
|
429
|
-
value: peer.id,
|
|
430
|
-
themeMode,
|
|
431
|
-
type: "highlight"
|
|
432
|
-
})
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
}, [
|
|
436
|
-
awareness2,
|
|
437
|
-
peer,
|
|
438
|
-
themeMode
|
|
439
|
-
]);
|
|
440
|
-
};
|
|
441
414
|
var RemoteSelectionsDecorator = class {
|
|
442
415
|
constructor(view) {
|
|
443
416
|
this.decorations = RangeSet.of([]);
|
|
@@ -599,39 +572,41 @@ var styles = EditorView2.baseTheme({
|
|
|
599
572
|
marginLeft: "-1px",
|
|
600
573
|
marginRight: "-1px",
|
|
601
574
|
boxSizing: "border-box",
|
|
602
|
-
display: "inline"
|
|
575
|
+
display: "inline",
|
|
576
|
+
cursor: "pointer"
|
|
603
577
|
},
|
|
604
578
|
".cm-collab-selectionCaretDot": {
|
|
605
579
|
borderRadius: "50%",
|
|
606
580
|
position: "absolute",
|
|
607
|
-
width: ".
|
|
608
|
-
height: ".
|
|
609
|
-
top: "-.
|
|
610
|
-
left: "-.
|
|
581
|
+
width: ".5em",
|
|
582
|
+
height: ".5em",
|
|
583
|
+
top: "-.25em",
|
|
584
|
+
left: "-.25em",
|
|
611
585
|
backgroundColor: "inherit",
|
|
612
586
|
transition: "transform .3s ease-in-out",
|
|
613
587
|
boxSizing: "border-box"
|
|
614
588
|
},
|
|
615
589
|
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
616
|
-
|
|
617
|
-
|
|
590
|
+
transform: "scale(0)",
|
|
591
|
+
transformOrigin: "center"
|
|
618
592
|
},
|
|
619
593
|
".cm-collab-selectionInfo": {
|
|
620
594
|
position: "absolute",
|
|
621
|
-
|
|
622
|
-
|
|
595
|
+
transform: "translate(-50%, 0)",
|
|
596
|
+
top: "-20px",
|
|
597
|
+
left: 0,
|
|
623
598
|
fontSize: ".75em",
|
|
624
|
-
fontFamily: "serif",
|
|
599
|
+
fontFamily: "sans-serif",
|
|
625
600
|
fontStyle: "normal",
|
|
626
601
|
fontWeight: "normal",
|
|
627
602
|
lineHeight: "normal",
|
|
628
603
|
userSelect: "none",
|
|
629
604
|
color: "white",
|
|
630
|
-
|
|
631
|
-
paddingRight: "2px",
|
|
605
|
+
padding: "2px",
|
|
632
606
|
zIndex: 101,
|
|
633
607
|
transition: "opacity .3s ease-in-out",
|
|
634
608
|
backgroundColor: "inherit",
|
|
609
|
+
borderRadius: "2px",
|
|
635
610
|
// These should be separate.
|
|
636
611
|
opacity: 0,
|
|
637
612
|
transitionDelay: "0s",
|
|
@@ -649,8 +624,8 @@ import { history } from "@codemirror/commands";
|
|
|
649
624
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
650
625
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
651
626
|
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
652
|
-
var basicBundle = ({ themeMode, placeholder: _placeholder,
|
|
653
|
-
|
|
627
|
+
var basicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true }) => [
|
|
628
|
+
lineWrapping ? EditorView3.lineWrapping : [],
|
|
654
629
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
655
630
|
bracketMatching(),
|
|
656
631
|
closeBrackets(),
|
|
@@ -972,9 +947,14 @@ var random = (min, max) => {
|
|
|
972
947
|
return min + ~~(Math.random() * (max - min + 1));
|
|
973
948
|
};
|
|
974
949
|
|
|
975
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
976
|
-
import {
|
|
977
|
-
import {
|
|
950
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
951
|
+
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
952
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
953
|
+
import sortBy from "lodash.sortby";
|
|
954
|
+
import { useEffect } from "react";
|
|
955
|
+
import { debounce } from "@dxos/async";
|
|
956
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
957
|
+
import { nonNullable } from "@dxos/util";
|
|
978
958
|
|
|
979
959
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
980
960
|
import * as random2 from "lib0/random";
|
|
@@ -1062,89 +1042,6 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
|
1062
1042
|
var tokens = tailwindConfig({}).theme;
|
|
1063
1043
|
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1064
1044
|
|
|
1065
|
-
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1066
|
-
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1067
|
-
var styles2 = EditorView5.baseTheme({
|
|
1068
|
-
"& .cm-codeblock": {
|
|
1069
|
-
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1070
|
-
},
|
|
1071
|
-
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1072
|
-
background: getToken("extend.colors.neutral.50")
|
|
1073
|
-
},
|
|
1074
|
-
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1075
|
-
background: getToken("extend.colors.neutral.850")
|
|
1076
|
-
},
|
|
1077
|
-
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1078
|
-
display: "block",
|
|
1079
|
-
paddingInline: "4px !important"
|
|
1080
|
-
},
|
|
1081
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1082
|
-
paddingTop: "4px !important",
|
|
1083
|
-
borderTopLeftRadius: "4px",
|
|
1084
|
-
borderTopRightRadius: "4px"
|
|
1085
|
-
},
|
|
1086
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1087
|
-
paddingBottom: "4px !important",
|
|
1088
|
-
borderBottomLeftRadius: "4px",
|
|
1089
|
-
borderBottomRightRadius: "4px"
|
|
1090
|
-
}
|
|
1091
|
-
});
|
|
1092
|
-
var getLineRange = (lines, from, to) => {
|
|
1093
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1094
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1095
|
-
return [
|
|
1096
|
-
start,
|
|
1097
|
-
end
|
|
1098
|
-
];
|
|
1099
|
-
};
|
|
1100
|
-
var code2 = () => {
|
|
1101
|
-
const buildDecorations5 = (view) => {
|
|
1102
|
-
const decorations = [];
|
|
1103
|
-
const text = view.state.doc.sliceString(0);
|
|
1104
|
-
const matches = text.matchAll(CODE_REGEX);
|
|
1105
|
-
const blocks = view.viewportLineBlocks;
|
|
1106
|
-
for (const match of matches) {
|
|
1107
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1108
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1109
|
-
const block = blocks[i];
|
|
1110
|
-
decorations.push(Decoration2.line({
|
|
1111
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1112
|
-
}).range(block.from));
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
return Decoration2.set(decorations);
|
|
1116
|
-
};
|
|
1117
|
-
return [
|
|
1118
|
-
ViewPlugin3.fromClass(class {
|
|
1119
|
-
constructor(view) {
|
|
1120
|
-
this.hasFocus = false;
|
|
1121
|
-
this.decorations = buildDecorations5(view);
|
|
1122
|
-
}
|
|
1123
|
-
update(update2) {
|
|
1124
|
-
if (
|
|
1125
|
-
// TODO(burdon): Generalize for other extensions.
|
|
1126
|
-
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1127
|
-
) {
|
|
1128
|
-
this.hasFocus = update2.view.hasFocus;
|
|
1129
|
-
this.decorations = buildDecorations5(update2.view);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
}, {
|
|
1133
|
-
decorations: (value) => value.decorations
|
|
1134
|
-
}),
|
|
1135
|
-
styles2
|
|
1136
|
-
];
|
|
1137
|
-
};
|
|
1138
|
-
|
|
1139
|
-
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1140
|
-
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1141
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
|
|
1142
|
-
import sortBy from "lodash.sortby";
|
|
1143
|
-
import { useEffect as useEffect2 } from "react";
|
|
1144
|
-
import { debounce } from "@dxos/async";
|
|
1145
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1146
|
-
import { nonNullable } from "@dxos/util";
|
|
1147
|
-
|
|
1148
1045
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1149
1046
|
import { log } from "@dxos/log";
|
|
1150
1047
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
@@ -1182,20 +1079,20 @@ var logChanges = (trs) => {
|
|
|
1182
1079
|
|
|
1183
1080
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1184
1081
|
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1185
|
-
var
|
|
1082
|
+
var styles2 = EditorView5.baseTheme({
|
|
1186
1083
|
"& .cm-comment": {
|
|
1187
1084
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1188
1085
|
},
|
|
1189
|
-
"& .cm-comment-
|
|
1086
|
+
"& .cm-comment-current": {
|
|
1190
1087
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1191
1088
|
}
|
|
1192
1089
|
});
|
|
1193
1090
|
var marks = {
|
|
1194
|
-
highlight:
|
|
1091
|
+
highlight: Decoration2.mark({
|
|
1195
1092
|
class: "cm-comment"
|
|
1196
1093
|
}),
|
|
1197
|
-
highlightActive:
|
|
1198
|
-
class: "cm-comment-
|
|
1094
|
+
highlightActive: Decoration2.mark({
|
|
1095
|
+
class: "cm-comment-current"
|
|
1199
1096
|
})
|
|
1200
1097
|
};
|
|
1201
1098
|
var setFocus = (view, id, center = true) => {
|
|
@@ -1211,11 +1108,11 @@ var setFocus = (view, id, center = true) => {
|
|
|
1211
1108
|
},
|
|
1212
1109
|
effects: [
|
|
1213
1110
|
//
|
|
1214
|
-
|
|
1111
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1215
1112
|
y: "center"
|
|
1216
1113
|
} : void 0),
|
|
1217
1114
|
setSelection.of({
|
|
1218
|
-
|
|
1115
|
+
current: id
|
|
1219
1116
|
})
|
|
1220
1117
|
]
|
|
1221
1118
|
});
|
|
@@ -1260,23 +1157,23 @@ var commentsState = StateField2.define({
|
|
|
1260
1157
|
return value;
|
|
1261
1158
|
}
|
|
1262
1159
|
});
|
|
1263
|
-
var highlightDecorations =
|
|
1160
|
+
var highlightDecorations = EditorView5.decorations.compute([
|
|
1264
1161
|
commentsState
|
|
1265
1162
|
], (state) => {
|
|
1266
|
-
const { selection: {
|
|
1163
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1267
1164
|
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1268
1165
|
const range = comment.range;
|
|
1269
1166
|
if (!range || range.from === range.to) {
|
|
1270
1167
|
console.warn("Invalid range:", range);
|
|
1271
1168
|
return void 0;
|
|
1272
1169
|
}
|
|
1273
|
-
if (comment.comment.id ===
|
|
1170
|
+
if (comment.comment.id === current) {
|
|
1274
1171
|
return marks.highlightActive.range(range.from, range.to);
|
|
1275
1172
|
} else {
|
|
1276
1173
|
return marks.highlight.range(range.from, range.to);
|
|
1277
1174
|
}
|
|
1278
1175
|
}).filter(nonNullable);
|
|
1279
|
-
return
|
|
1176
|
+
return Decoration2.set(decorations);
|
|
1280
1177
|
});
|
|
1281
1178
|
var trackPastedComments = (onUpdate) => {
|
|
1282
1179
|
let tracked = null;
|
|
@@ -1298,12 +1195,12 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1298
1195
|
}
|
|
1299
1196
|
};
|
|
1300
1197
|
return [
|
|
1301
|
-
|
|
1198
|
+
EditorView5.domEventHandlers({
|
|
1302
1199
|
cut: handleTrack,
|
|
1303
1200
|
copy: handleTrack
|
|
1304
1201
|
}),
|
|
1305
1202
|
// Handle paste.
|
|
1306
|
-
|
|
1203
|
+
EditorView5.updateListener.of(({ view, state, transactions }) => {
|
|
1307
1204
|
if (tracked) {
|
|
1308
1205
|
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1309
1206
|
if (paste) {
|
|
@@ -1366,7 +1263,7 @@ var comments = (options = {}) => {
|
|
|
1366
1263
|
if (id) {
|
|
1367
1264
|
view.dispatch({
|
|
1368
1265
|
effects: setSelection.of({
|
|
1369
|
-
|
|
1266
|
+
current: id
|
|
1370
1267
|
}),
|
|
1371
1268
|
selection: {
|
|
1372
1269
|
anchor: from
|
|
@@ -1380,7 +1277,7 @@ var comments = (options = {}) => {
|
|
|
1380
1277
|
return [
|
|
1381
1278
|
commentsState,
|
|
1382
1279
|
highlightDecorations,
|
|
1383
|
-
|
|
1280
|
+
styles2,
|
|
1384
1281
|
//
|
|
1385
1282
|
// Keymap.
|
|
1386
1283
|
//
|
|
@@ -1423,7 +1320,7 @@ var comments = (options = {}) => {
|
|
|
1423
1320
|
//
|
|
1424
1321
|
// Track deleted ranges and update ranges for decorations.
|
|
1425
1322
|
//
|
|
1426
|
-
|
|
1323
|
+
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1427
1324
|
let mod = false;
|
|
1428
1325
|
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1429
1326
|
changes.iterChanges((from, to, from2, to2) => {
|
|
@@ -1453,17 +1350,17 @@ var comments = (options = {}) => {
|
|
|
1453
1350
|
//
|
|
1454
1351
|
// Track selection/proximity.
|
|
1455
1352
|
//
|
|
1456
|
-
|
|
1353
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1457
1354
|
let min = Infinity;
|
|
1458
|
-
const { selection: {
|
|
1355
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1459
1356
|
const { head } = state.selection.main;
|
|
1460
1357
|
const selection = {};
|
|
1461
1358
|
comments2.forEach(({ comment, range }) => {
|
|
1462
1359
|
if (head >= range.from && head <= range.to) {
|
|
1463
|
-
selection.
|
|
1360
|
+
selection.current = comment.id;
|
|
1464
1361
|
selection.closest = void 0;
|
|
1465
1362
|
}
|
|
1466
|
-
if (!selection.
|
|
1363
|
+
if (!selection.current) {
|
|
1467
1364
|
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1468
1365
|
if (d < min) {
|
|
1469
1366
|
selection.closest = comment.id;
|
|
@@ -1471,7 +1368,7 @@ var comments = (options = {}) => {
|
|
|
1471
1368
|
}
|
|
1472
1369
|
}
|
|
1473
1370
|
});
|
|
1474
|
-
if (selection.
|
|
1371
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1475
1372
|
view.dispatch({
|
|
1476
1373
|
effects: setSelection.of(selection)
|
|
1477
1374
|
});
|
|
@@ -1488,9 +1385,9 @@ var comments = (options = {}) => {
|
|
|
1488
1385
|
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1489
1386
|
];
|
|
1490
1387
|
};
|
|
1491
|
-
var useComments = (view, comments2) => {
|
|
1492
|
-
|
|
1493
|
-
if (view
|
|
1388
|
+
var useComments = (view, comments2 = []) => {
|
|
1389
|
+
useEffect(() => {
|
|
1390
|
+
if (view) {
|
|
1494
1391
|
view.dispatch({
|
|
1495
1392
|
effects: setComments.of(comments2)
|
|
1496
1393
|
});
|
|
@@ -1501,329 +1398,65 @@ var useComments = (view, comments2) => {
|
|
|
1501
1398
|
]);
|
|
1502
1399
|
};
|
|
1503
1400
|
|
|
1504
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1505
|
-
import {
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
const el = document.createElement("div");
|
|
1517
|
-
el.className = "cm-hr";
|
|
1518
|
-
return el;
|
|
1519
|
-
}
|
|
1520
|
-
};
|
|
1521
|
-
var decoration = Decoration4.replace({
|
|
1522
|
-
widget: new HorizontalRuleWidget()
|
|
1523
|
-
});
|
|
1524
|
-
var buildDecorations = (view) => {
|
|
1525
|
-
const builder = new RangeSetBuilder();
|
|
1526
|
-
const { state } = view;
|
|
1527
|
-
const cursor = state.selection.main.head;
|
|
1528
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1529
|
-
syntaxTree(state).iterate({
|
|
1530
|
-
enter: (node) => {
|
|
1531
|
-
if (node.name === "HorizontalRule") {
|
|
1532
|
-
if (cursor <= node.from || cursor >= node.to) {
|
|
1533
|
-
builder.add(node.from, node.to, decoration);
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
},
|
|
1537
|
-
from,
|
|
1538
|
-
to
|
|
1539
|
-
});
|
|
1540
|
-
}
|
|
1541
|
-
return builder.finish();
|
|
1542
|
-
};
|
|
1543
|
-
var hr = () => {
|
|
1544
|
-
return [
|
|
1545
|
-
styles4,
|
|
1546
|
-
ViewPlugin4.fromClass(class {
|
|
1547
|
-
constructor(view) {
|
|
1548
|
-
this.decorations = buildDecorations(view);
|
|
1549
|
-
}
|
|
1550
|
-
update(update2) {
|
|
1551
|
-
this.decorations = buildDecorations(update2.view);
|
|
1552
|
-
}
|
|
1553
|
-
}, {
|
|
1554
|
-
decorations: (v) => v.decorations
|
|
1555
|
-
})
|
|
1556
|
-
];
|
|
1401
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1402
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1403
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1404
|
+
const extensions = [];
|
|
1405
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1406
|
+
onFocus(focused);
|
|
1407
|
+
return null;
|
|
1408
|
+
}));
|
|
1409
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1410
|
+
onChange(update2.state.doc.toString());
|
|
1411
|
+
}));
|
|
1412
|
+
return extensions;
|
|
1557
1413
|
};
|
|
1558
1414
|
|
|
1559
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1560
|
-
import {
|
|
1561
|
-
import {
|
|
1562
|
-
import {
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
provide: (field) => EditorView8.decorations.from(field)
|
|
1590
|
-
});
|
|
1591
|
-
};
|
|
1592
|
-
var buildDecorations2 = (from, to, state) => {
|
|
1593
|
-
const decorations = [];
|
|
1594
|
-
const cursor = state.selection.main.head;
|
|
1595
|
-
syntaxTree2(state).iterate({
|
|
1596
|
-
enter: (node) => {
|
|
1597
|
-
if (node.name === "Image") {
|
|
1598
|
-
const urlNode = node.node.getChild("URL");
|
|
1599
|
-
if (urlNode) {
|
|
1600
|
-
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1601
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1602
|
-
decorations.push(Decoration5.replace({
|
|
1603
|
-
block: true,
|
|
1604
|
-
widget: new ImageWidget(url)
|
|
1605
|
-
}).range(hide ? node.from : node.to, node.to));
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
},
|
|
1609
|
-
from,
|
|
1610
|
-
to
|
|
1611
|
-
});
|
|
1612
|
-
return decorations;
|
|
1415
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1416
|
+
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1417
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1418
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1419
|
+
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1420
|
+
import { languages } from "@codemirror/language-data";
|
|
1421
|
+
import { searchKeymap } from "@codemirror/search";
|
|
1422
|
+
import { EditorState } from "@codemirror/state";
|
|
1423
|
+
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1424
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1425
|
+
|
|
1426
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1427
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1428
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
1429
|
+
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1430
|
+
import { Table } from "@lezer/markdown";
|
|
1431
|
+
var markdownTags = {
|
|
1432
|
+
Blockquote: Tag.define(),
|
|
1433
|
+
CodeMark: Tag.define(),
|
|
1434
|
+
CodeText: Tag.define(),
|
|
1435
|
+
EmphasisMark: Tag.define(),
|
|
1436
|
+
HeaderMark: Tag.define(),
|
|
1437
|
+
InlineCode: Tag.define(),
|
|
1438
|
+
LinkLabel: Tag.define(),
|
|
1439
|
+
LinkReference: Tag.define(),
|
|
1440
|
+
ListMark: Tag.define(),
|
|
1441
|
+
QuoteMark: Tag.define(),
|
|
1442
|
+
URL: Tag.define(),
|
|
1443
|
+
// Custom.
|
|
1444
|
+
TableCell: Tag.define()
|
|
1613
1445
|
};
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1446
|
+
Table.defineNodes?.forEach((node) => {
|
|
1447
|
+
switch (node?.name) {
|
|
1448
|
+
case "TableCell": {
|
|
1449
|
+
node.style = markdownTags.TableCell;
|
|
1450
|
+
break;
|
|
1451
|
+
}
|
|
1618
1452
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1627
|
-
return img;
|
|
1628
|
-
}
|
|
1629
|
-
};
|
|
1630
|
-
|
|
1631
|
-
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1632
|
-
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1633
|
-
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1634
|
-
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1635
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1636
|
-
var link = (options = {}) => {
|
|
1637
|
-
const extensions = [
|
|
1638
|
-
ViewPlugin5.fromClass(class {
|
|
1639
|
-
constructor(view) {
|
|
1640
|
-
this.decorations = buildDecorations3(view, options);
|
|
1641
|
-
}
|
|
1642
|
-
update(update2) {
|
|
1643
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1644
|
-
this.decorations = buildDecorations3(update2.view, options);
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
}, {
|
|
1648
|
-
decorations: (v) => v.decorations
|
|
1649
|
-
})
|
|
1650
|
-
];
|
|
1651
|
-
if (options.onHover) {
|
|
1652
|
-
extensions.push(
|
|
1653
|
-
// https://codemirror.net/examples/tooltip
|
|
1654
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1655
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1656
|
-
hoverTooltip2((view, pos, side) => {
|
|
1657
|
-
const syntax = syntaxTree3(view.state).resolveInner(pos, side);
|
|
1658
|
-
let link2 = null;
|
|
1659
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1660
|
-
link2 = node.name === "Link" ? node : null;
|
|
1661
|
-
}
|
|
1662
|
-
const url = link2 && link2.getChild("URL");
|
|
1663
|
-
if (!url || !link2) {
|
|
1664
|
-
return null;
|
|
1665
|
-
}
|
|
1666
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1667
|
-
return {
|
|
1668
|
-
pos: link2.from,
|
|
1669
|
-
end: link2.to,
|
|
1670
|
-
above: true,
|
|
1671
|
-
create: () => {
|
|
1672
|
-
const el = document.createElement("div");
|
|
1673
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1674
|
-
options.onHover(el, urlText);
|
|
1675
|
-
return {
|
|
1676
|
-
dom: el,
|
|
1677
|
-
offset: {
|
|
1678
|
-
x: 0,
|
|
1679
|
-
y: 4
|
|
1680
|
-
}
|
|
1681
|
-
};
|
|
1682
|
-
}
|
|
1683
|
-
};
|
|
1684
|
-
})
|
|
1685
|
-
);
|
|
1686
|
-
}
|
|
1687
|
-
return extensions;
|
|
1688
|
-
};
|
|
1689
|
-
var LinkButton = class extends WidgetType4 {
|
|
1690
|
-
constructor(_url, _onAttach) {
|
|
1691
|
-
super();
|
|
1692
|
-
this._url = _url;
|
|
1693
|
-
this._onAttach = _onAttach;
|
|
1694
|
-
}
|
|
1695
|
-
eq(other) {
|
|
1696
|
-
return this._url === other._url;
|
|
1697
|
-
}
|
|
1698
|
-
toDOM(view) {
|
|
1699
|
-
const el = document.createElement("span");
|
|
1700
|
-
this._onAttach(el, this._url);
|
|
1701
|
-
return el;
|
|
1702
|
-
}
|
|
1703
|
-
};
|
|
1704
|
-
var LinkText = class extends WidgetType4 {
|
|
1705
|
-
constructor(_text, _url) {
|
|
1706
|
-
super();
|
|
1707
|
-
this._text = _text;
|
|
1708
|
-
this._url = _url;
|
|
1709
|
-
}
|
|
1710
|
-
eq(other) {
|
|
1711
|
-
return this._url === other._url;
|
|
1712
|
-
}
|
|
1713
|
-
toDOM(view) {
|
|
1714
|
-
const link2 = document.createElement("a");
|
|
1715
|
-
link2.setAttribute("class", "cm-link");
|
|
1716
|
-
link2.textContent = this._text;
|
|
1717
|
-
if (this._url) {
|
|
1718
|
-
link2.setAttribute("rel", "noreferrer");
|
|
1719
|
-
link2.setAttribute("target", "_blank");
|
|
1720
|
-
link2.href = this._url;
|
|
1721
|
-
} else {
|
|
1722
|
-
link2.onclick = () => {
|
|
1723
|
-
view.dispatch({
|
|
1724
|
-
selection: {
|
|
1725
|
-
anchor: view.posAtDOM(link2)
|
|
1726
|
-
}
|
|
1727
|
-
});
|
|
1728
|
-
};
|
|
1729
|
-
}
|
|
1730
|
-
return link2;
|
|
1731
|
-
}
|
|
1732
|
-
};
|
|
1733
|
-
var buildDecorations3 = (view, options) => {
|
|
1734
|
-
const builder = new RangeSetBuilder2();
|
|
1735
|
-
const { state } = view;
|
|
1736
|
-
const cursor = state.selection.main.head;
|
|
1737
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1738
|
-
syntaxTree3(state).iterate({
|
|
1739
|
-
enter: (node) => {
|
|
1740
|
-
if (node.name === "Link") {
|
|
1741
|
-
const marks2 = node.node.getChildren("LinkMark");
|
|
1742
|
-
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1743
|
-
const urlNode = node.node.getChild("URL");
|
|
1744
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1745
|
-
if (!url) {
|
|
1746
|
-
return false;
|
|
1747
|
-
}
|
|
1748
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1749
|
-
builder.add(node.from, node.to, Decoration6.replace({
|
|
1750
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
1751
|
-
}));
|
|
1752
|
-
}
|
|
1753
|
-
if (options.onRender) {
|
|
1754
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1755
|
-
widget: new LinkButton(url, options.onRender)
|
|
1756
|
-
}));
|
|
1757
|
-
}
|
|
1758
|
-
return false;
|
|
1759
|
-
}
|
|
1760
|
-
},
|
|
1761
|
-
from,
|
|
1762
|
-
to
|
|
1763
|
-
});
|
|
1764
|
-
}
|
|
1765
|
-
return builder.finish();
|
|
1766
|
-
};
|
|
1767
|
-
|
|
1768
|
-
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1769
|
-
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1770
|
-
var listener = ({ onFocus, onChange }) => {
|
|
1771
|
-
const extensions = [];
|
|
1772
|
-
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1773
|
-
onFocus(focused);
|
|
1774
|
-
return null;
|
|
1775
|
-
}));
|
|
1776
|
-
onChange && extensions.push(EditorView9.updateListener.of((update2) => {
|
|
1777
|
-
onChange(update2.state.doc.toString());
|
|
1778
|
-
}));
|
|
1779
|
-
return extensions;
|
|
1780
|
-
};
|
|
1781
|
-
|
|
1782
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1783
|
-
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1784
|
-
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1785
|
-
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1786
|
-
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1787
|
-
import { languages } from "@codemirror/language-data";
|
|
1788
|
-
import { searchKeymap } from "@codemirror/search";
|
|
1789
|
-
import { EditorState } from "@codemirror/state";
|
|
1790
|
-
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1791
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1792
|
-
|
|
1793
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1794
|
-
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1795
|
-
import { HighlightStyle } from "@codemirror/language";
|
|
1796
|
-
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1797
|
-
import { Table } from "@lezer/markdown";
|
|
1798
|
-
var markdownTags = {
|
|
1799
|
-
Blockquote: Tag.define(),
|
|
1800
|
-
CodeMark: Tag.define(),
|
|
1801
|
-
CodeText: Tag.define(),
|
|
1802
|
-
EmphasisMark: Tag.define(),
|
|
1803
|
-
HeaderMark: Tag.define(),
|
|
1804
|
-
InlineCode: Tag.define(),
|
|
1805
|
-
LinkLabel: Tag.define(),
|
|
1806
|
-
LinkReference: Tag.define(),
|
|
1807
|
-
ListMark: Tag.define(),
|
|
1808
|
-
QuoteMark: Tag.define(),
|
|
1809
|
-
URL: Tag.define(),
|
|
1810
|
-
// Custom.
|
|
1811
|
-
TableCell: Tag.define()
|
|
1812
|
-
};
|
|
1813
|
-
Table.defineNodes?.forEach((node) => {
|
|
1814
|
-
switch (node?.name) {
|
|
1815
|
-
case "TableCell": {
|
|
1816
|
-
node.style = markdownTags.TableCell;
|
|
1817
|
-
break;
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
});
|
|
1821
|
-
var markdownTagsExtensions = [
|
|
1822
|
-
Table,
|
|
1823
|
-
{
|
|
1824
|
-
props: [
|
|
1825
|
-
styleTags(markdownTags)
|
|
1826
|
-
]
|
|
1453
|
+
});
|
|
1454
|
+
var markdownTagsExtensions = [
|
|
1455
|
+
Table,
|
|
1456
|
+
{
|
|
1457
|
+
props: [
|
|
1458
|
+
styleTags(markdownTags)
|
|
1459
|
+
]
|
|
1827
1460
|
}
|
|
1828
1461
|
];
|
|
1829
1462
|
var markdownHighlightStyle = (readonly) => {
|
|
@@ -1983,7 +1616,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1983
1616
|
return [
|
|
1984
1617
|
EditorState.allowMultipleSelections.of(true),
|
|
1985
1618
|
EditorState.tabSize.of(2),
|
|
1986
|
-
|
|
1619
|
+
EditorView7.lineWrapping,
|
|
1987
1620
|
// https://github.com/codemirror/basic-setup
|
|
1988
1621
|
bracketMatching2(),
|
|
1989
1622
|
closeBrackets2(),
|
|
@@ -2031,44 +1664,396 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
2031
1664
|
];
|
|
2032
1665
|
};
|
|
2033
1666
|
|
|
2034
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
2035
|
-
import {
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
1667
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1668
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3 } from "@codemirror/view";
|
|
1669
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1670
|
+
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1671
|
+
var styles3 = EditorView8.baseTheme({
|
|
1672
|
+
"& .cm-codeblock": {
|
|
1673
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1674
|
+
},
|
|
1675
|
+
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1676
|
+
background: getToken("extend.colors.neutral.50")
|
|
1677
|
+
},
|
|
1678
|
+
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1679
|
+
background: getToken("extend.colors.neutral.850")
|
|
1680
|
+
},
|
|
1681
|
+
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1682
|
+
display: "block",
|
|
1683
|
+
paddingInline: "4px !important"
|
|
1684
|
+
},
|
|
1685
|
+
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1686
|
+
paddingTop: "4px !important",
|
|
1687
|
+
borderTopLeftRadius: "4px",
|
|
1688
|
+
borderTopRightRadius: "4px"
|
|
1689
|
+
},
|
|
1690
|
+
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1691
|
+
paddingBottom: "4px !important",
|
|
1692
|
+
borderBottomLeftRadius: "4px",
|
|
1693
|
+
borderBottomRightRadius: "4px"
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1696
|
+
var getLineRange = (lines, from, to) => {
|
|
1697
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1698
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1699
|
+
return [
|
|
1700
|
+
start,
|
|
1701
|
+
end
|
|
1702
|
+
];
|
|
1703
|
+
};
|
|
1704
|
+
var code2 = () => {
|
|
1705
|
+
const buildDecorations6 = (view) => {
|
|
1706
|
+
const decorations = [];
|
|
1707
|
+
const text = view.state.doc.sliceString(0);
|
|
1708
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1709
|
+
const blocks = view.viewportLineBlocks;
|
|
1710
|
+
for (const match of matches) {
|
|
1711
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1712
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1713
|
+
const block = blocks[i];
|
|
1714
|
+
decorations.push(Decoration3.line({
|
|
1715
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1716
|
+
}).range(block.from));
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return Decoration3.set(decorations);
|
|
1720
|
+
};
|
|
1721
|
+
return [
|
|
1722
|
+
ViewPlugin3.fromClass(class {
|
|
1723
|
+
constructor(view) {
|
|
1724
|
+
this.hasFocus = false;
|
|
1725
|
+
this.decorations = buildDecorations6(view);
|
|
1726
|
+
}
|
|
1727
|
+
update(update2) {
|
|
1728
|
+
if (
|
|
1729
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1730
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1731
|
+
) {
|
|
1732
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1733
|
+
this.decorations = buildDecorations6(update2.view);
|
|
2051
1734
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
1735
|
+
}
|
|
1736
|
+
}, {
|
|
1737
|
+
decorations: (value) => value.decorations
|
|
1738
|
+
}),
|
|
1739
|
+
styles3
|
|
1740
|
+
];
|
|
1741
|
+
};
|
|
1742
|
+
|
|
1743
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1744
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1745
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1746
|
+
import { Decoration as Decoration4, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1747
|
+
var buildDecorations = (view) => {
|
|
1748
|
+
const builder = new RangeSetBuilder();
|
|
1749
|
+
const { state } = view;
|
|
1750
|
+
const cursor = state.selection.main.head;
|
|
1751
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1752
|
+
syntaxTree(state).iterate({
|
|
1753
|
+
enter: (node) => {
|
|
1754
|
+
switch (node.name) {
|
|
1755
|
+
case "ATXHeading1":
|
|
1756
|
+
case "ATXHeading2":
|
|
1757
|
+
case "ATXHeading3":
|
|
1758
|
+
case "ATXHeading4":
|
|
1759
|
+
case "ATXHeading5":
|
|
1760
|
+
case "ATXHeading6": {
|
|
1761
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1762
|
+
if (mark2 && (cursor < node.from || cursor > node.to)) {
|
|
1763
|
+
builder.add(mark2.from, mark2.to + 1, Decoration4.replace({}));
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
},
|
|
1768
|
+
from,
|
|
1769
|
+
to
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
return builder.finish();
|
|
1773
|
+
};
|
|
1774
|
+
var heading2 = () => {
|
|
1775
|
+
return [
|
|
1776
|
+
ViewPlugin4.fromClass(class {
|
|
1777
|
+
constructor(view) {
|
|
1778
|
+
this.decorations = buildDecorations(view);
|
|
1779
|
+
}
|
|
1780
|
+
update(update2) {
|
|
1781
|
+
this.decorations = buildDecorations(update2.view);
|
|
1782
|
+
}
|
|
1783
|
+
}, {
|
|
1784
|
+
decorations: (v) => v.decorations
|
|
1785
|
+
})
|
|
1786
|
+
];
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1789
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
1790
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1791
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1792
|
+
import { Decoration as Decoration5, EditorView as EditorView9, ViewPlugin as ViewPlugin5, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1793
|
+
var styles4 = EditorView9.baseTheme({
|
|
1794
|
+
"& .cm-hr": {
|
|
1795
|
+
// Note that block-level decorations should not have vertical margins,
|
|
1796
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1797
|
+
}
|
|
1798
|
+
});
|
|
1799
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1800
|
+
toDOM() {
|
|
1801
|
+
const el = document.createElement("div");
|
|
1802
|
+
el.className = "cm-hr";
|
|
1803
|
+
return el;
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
var decoration = Decoration5.replace({
|
|
1807
|
+
widget: new HorizontalRuleWidget()
|
|
1808
|
+
});
|
|
1809
|
+
var buildDecorations2 = (view) => {
|
|
1810
|
+
const builder = new RangeSetBuilder2();
|
|
1811
|
+
const { state } = view;
|
|
1812
|
+
const cursor = state.selection.main.head;
|
|
1813
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1814
|
+
syntaxTree2(state).iterate({
|
|
1815
|
+
enter: (node) => {
|
|
1816
|
+
if (node.name === "HorizontalRule") {
|
|
1817
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1818
|
+
builder.add(node.from, node.to, decoration);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
},
|
|
1822
|
+
from,
|
|
1823
|
+
to
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
return builder.finish();
|
|
1827
|
+
};
|
|
1828
|
+
var hr = () => {
|
|
1829
|
+
return [
|
|
1830
|
+
styles4,
|
|
1831
|
+
ViewPlugin5.fromClass(class {
|
|
1832
|
+
constructor(view) {
|
|
1833
|
+
this.decorations = buildDecorations2(view);
|
|
1834
|
+
}
|
|
1835
|
+
update(update2) {
|
|
1836
|
+
this.decorations = buildDecorations2(update2.view);
|
|
1837
|
+
}
|
|
1838
|
+
}, {
|
|
1839
|
+
decorations: (v) => v.decorations
|
|
1840
|
+
})
|
|
1841
|
+
];
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1844
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
1845
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1846
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1847
|
+
import { Decoration as Decoration6, EditorView as EditorView10, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1848
|
+
var image = (options = {}) => {
|
|
1849
|
+
return StateField3.define({
|
|
1850
|
+
create: (state) => {
|
|
1851
|
+
return Decoration6.set(buildDecorations3(0, state.doc.length, state));
|
|
1852
|
+
},
|
|
1853
|
+
update: (value, tr) => {
|
|
1854
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1855
|
+
return value;
|
|
1856
|
+
}
|
|
1857
|
+
const cursor = tr.state.selection.main.head;
|
|
1858
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1859
|
+
let from = Math.min(cursor, oldCursor);
|
|
1860
|
+
let to = Math.max(cursor, oldCursor);
|
|
1861
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1862
|
+
from = Math.min(from, fromB);
|
|
1863
|
+
to = Math.max(to, toB);
|
|
1864
|
+
});
|
|
1865
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1866
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1867
|
+
return value.map(tr.changes).update({
|
|
1868
|
+
filterFrom: from,
|
|
1869
|
+
filterTo: to,
|
|
1870
|
+
filter: () => false,
|
|
1871
|
+
add: buildDecorations3(from, to, tr.state)
|
|
1872
|
+
});
|
|
1873
|
+
},
|
|
1874
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1875
|
+
});
|
|
1876
|
+
};
|
|
1877
|
+
var buildDecorations3 = (from, to, state) => {
|
|
1878
|
+
const decorations = [];
|
|
1879
|
+
const cursor = state.selection.main.head;
|
|
1880
|
+
syntaxTree3(state).iterate({
|
|
1881
|
+
enter: (node) => {
|
|
1882
|
+
if (node.name === "Image") {
|
|
1883
|
+
const urlNode = node.node.getChild("URL");
|
|
1884
|
+
if (urlNode) {
|
|
1885
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1886
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1887
|
+
decorations.push(Decoration6.replace({
|
|
1888
|
+
block: true,
|
|
1889
|
+
widget: new ImageWidget(url)
|
|
1890
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
},
|
|
1894
|
+
from,
|
|
1895
|
+
to
|
|
1896
|
+
});
|
|
1897
|
+
return decorations;
|
|
1898
|
+
};
|
|
1899
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1900
|
+
constructor(_url) {
|
|
1901
|
+
super();
|
|
1902
|
+
this._url = _url;
|
|
1903
|
+
}
|
|
1904
|
+
eq(other) {
|
|
1905
|
+
return this._url === other._url;
|
|
1906
|
+
}
|
|
1907
|
+
toDOM(view) {
|
|
1908
|
+
const img = document.createElement("img");
|
|
1909
|
+
img.setAttribute("src", this._url);
|
|
1910
|
+
img.setAttribute("class", "cm-image");
|
|
1911
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1912
|
+
return img;
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
|
|
1916
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
1917
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
1918
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1919
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration7, ViewPlugin as ViewPlugin6, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1920
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1921
|
+
var link = (options = {}) => {
|
|
1922
|
+
const extensions = [
|
|
1923
|
+
ViewPlugin6.fromClass(class {
|
|
1924
|
+
constructor(view) {
|
|
1925
|
+
this.decorations = buildDecorations4(view, options);
|
|
1926
|
+
}
|
|
1927
|
+
update(update2) {
|
|
1928
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1929
|
+
this.decorations = buildDecorations4(update2.view, options);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}, {
|
|
1933
|
+
decorations: (v) => v.decorations
|
|
1934
|
+
})
|
|
1935
|
+
];
|
|
1936
|
+
if (options.onHover) {
|
|
1937
|
+
extensions.push(
|
|
1938
|
+
// https://codemirror.net/examples/tooltip
|
|
1939
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1940
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1941
|
+
hoverTooltip2((view, pos, side) => {
|
|
1942
|
+
const syntax = syntaxTree4(view.state).resolveInner(pos, side);
|
|
1943
|
+
let link2 = null;
|
|
1944
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1945
|
+
link2 = node.name === "Link" ? node : null;
|
|
1946
|
+
}
|
|
1947
|
+
const url = link2 && link2.getChild("URL");
|
|
1948
|
+
if (!url || !link2) {
|
|
1949
|
+
return null;
|
|
1950
|
+
}
|
|
1951
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1952
|
+
return {
|
|
1953
|
+
pos: link2.from,
|
|
1954
|
+
end: link2.to,
|
|
1955
|
+
above: true,
|
|
1956
|
+
create: () => {
|
|
1957
|
+
const el = document.createElement("div");
|
|
1958
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1959
|
+
options.onHover(el, urlText);
|
|
1960
|
+
return {
|
|
1961
|
+
dom: el,
|
|
1962
|
+
offset: {
|
|
1963
|
+
x: 0,
|
|
1964
|
+
y: 4
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
2057
1968
|
};
|
|
2058
|
-
}
|
|
2059
|
-
|
|
2060
|
-
}
|
|
1969
|
+
})
|
|
1970
|
+
);
|
|
1971
|
+
}
|
|
1972
|
+
return extensions;
|
|
2061
1973
|
};
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
1974
|
+
var LinkButton = class extends WidgetType4 {
|
|
1975
|
+
constructor(_url, _onAttach) {
|
|
1976
|
+
super();
|
|
1977
|
+
this._url = _url;
|
|
1978
|
+
this._onAttach = _onAttach;
|
|
1979
|
+
}
|
|
1980
|
+
eq(other) {
|
|
1981
|
+
return this._url === other._url;
|
|
1982
|
+
}
|
|
1983
|
+
toDOM(view) {
|
|
1984
|
+
const el = document.createElement("span");
|
|
1985
|
+
this._onAttach(el, this._url);
|
|
1986
|
+
return el;
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
var LinkText = class extends WidgetType4 {
|
|
1990
|
+
constructor(_text, _url) {
|
|
1991
|
+
super();
|
|
1992
|
+
this._text = _text;
|
|
1993
|
+
this._url = _url;
|
|
1994
|
+
}
|
|
1995
|
+
eq(other) {
|
|
1996
|
+
return this._url === other._url;
|
|
1997
|
+
}
|
|
1998
|
+
toDOM(view) {
|
|
1999
|
+
const link2 = document.createElement("a");
|
|
2000
|
+
link2.setAttribute("class", "cm-link");
|
|
2001
|
+
link2.textContent = this._text;
|
|
2002
|
+
if (this._url) {
|
|
2003
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2004
|
+
link2.setAttribute("target", "_blank");
|
|
2005
|
+
link2.href = this._url;
|
|
2006
|
+
} else {
|
|
2007
|
+
link2.onclick = () => {
|
|
2008
|
+
view.dispatch({
|
|
2009
|
+
selection: {
|
|
2010
|
+
anchor: view.posAtDOM(link2)
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
return link2;
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
var buildDecorations4 = (view, options) => {
|
|
2019
|
+
const builder = new RangeSetBuilder3();
|
|
2020
|
+
const { state } = view;
|
|
2021
|
+
const cursor = state.selection.main.head;
|
|
2022
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2023
|
+
syntaxTree4(state).iterate({
|
|
2024
|
+
enter: (node) => {
|
|
2025
|
+
if (node.name === "Link") {
|
|
2026
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
2027
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
2028
|
+
const urlNode = node.node.getChild("URL");
|
|
2029
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2030
|
+
if (!url) {
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2034
|
+
builder.add(node.from, node.to, Decoration7.replace({
|
|
2035
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2036
|
+
}));
|
|
2037
|
+
}
|
|
2038
|
+
if (options.onRender) {
|
|
2039
|
+
builder.add(node.to, node.to, Decoration7.replace({
|
|
2040
|
+
widget: new LinkButton(url, options.onRender)
|
|
2041
|
+
}));
|
|
2042
|
+
}
|
|
2043
|
+
return false;
|
|
2044
|
+
}
|
|
2045
|
+
},
|
|
2046
|
+
from,
|
|
2047
|
+
to
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
return builder.finish();
|
|
2066
2051
|
};
|
|
2067
2052
|
|
|
2068
|
-
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
2069
|
-
import { syntaxTree as
|
|
2070
|
-
import { RangeSetBuilder as
|
|
2071
|
-
import { Decoration as
|
|
2053
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2054
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2055
|
+
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField4 } from "@codemirror/state";
|
|
2056
|
+
import { Decoration as Decoration8, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
2072
2057
|
var table = (options = {}) => {
|
|
2073
2058
|
return StateField4.define({
|
|
2074
2059
|
create: (state) => update(state, options),
|
|
@@ -2077,7 +2062,7 @@ var table = (options = {}) => {
|
|
|
2077
2062
|
});
|
|
2078
2063
|
};
|
|
2079
2064
|
var update = (state, options) => {
|
|
2080
|
-
const builder = new
|
|
2065
|
+
const builder = new RangeSetBuilder4();
|
|
2081
2066
|
const cursor = state.selection.main.head;
|
|
2082
2067
|
const tables = [];
|
|
2083
2068
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2085,7 +2070,7 @@ var update = (state, options) => {
|
|
|
2085
2070
|
const table2 = getTable();
|
|
2086
2071
|
return table2.rows?.[table2.rows.length - 1];
|
|
2087
2072
|
};
|
|
2088
|
-
|
|
2073
|
+
syntaxTree5(state).iterate({
|
|
2089
2074
|
enter: (node) => {
|
|
2090
2075
|
switch (node.name) {
|
|
2091
2076
|
case "Table": {
|
|
@@ -2117,10 +2102,10 @@ var update = (state, options) => {
|
|
|
2117
2102
|
});
|
|
2118
2103
|
tables.forEach((table2) => {
|
|
2119
2104
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2120
|
-
hide && builder.add(table2.from, table2.to,
|
|
2105
|
+
hide && builder.add(table2.from, table2.to, Decoration8.replace({
|
|
2121
2106
|
widget: new TableWidget(table2)
|
|
2122
2107
|
}));
|
|
2123
|
-
builder.add(table2.from, table2.to,
|
|
2108
|
+
builder.add(table2.from, table2.to, Decoration8.mark({
|
|
2124
2109
|
class: "cm-table"
|
|
2125
2110
|
}));
|
|
2126
2111
|
});
|
|
@@ -2163,10 +2148,10 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2163
2148
|
}
|
|
2164
2149
|
};
|
|
2165
2150
|
|
|
2166
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2167
|
-
import { syntaxTree as
|
|
2168
|
-
import { RangeSetBuilder as
|
|
2169
|
-
import { EditorView as EditorView12, Decoration as
|
|
2151
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2152
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2153
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2154
|
+
import { EditorView as EditorView12, Decoration as Decoration9, WidgetType as WidgetType6, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
2170
2155
|
var styles5 = EditorView12.baseTheme({
|
|
2171
2156
|
"& .cm-task": {
|
|
2172
2157
|
color: getToken("extend.colors.blue.500")
|
|
@@ -2213,23 +2198,23 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2213
2198
|
return false;
|
|
2214
2199
|
}
|
|
2215
2200
|
};
|
|
2216
|
-
var checkedDecoration =
|
|
2201
|
+
var checkedDecoration = Decoration9.replace({
|
|
2217
2202
|
widget: new CheckboxWidget(true)
|
|
2218
2203
|
});
|
|
2219
|
-
var uncheckedDecoration =
|
|
2204
|
+
var uncheckedDecoration = Decoration9.replace({
|
|
2220
2205
|
widget: new CheckboxWidget(false)
|
|
2221
2206
|
});
|
|
2222
|
-
var
|
|
2223
|
-
const builder = new
|
|
2207
|
+
var buildDecorations5 = (view) => {
|
|
2208
|
+
const builder = new RangeSetBuilder5();
|
|
2224
2209
|
const { state } = view;
|
|
2225
2210
|
const cursor = state.selection.main.head;
|
|
2226
2211
|
for (const { from, to } of view.visibleRanges) {
|
|
2227
|
-
|
|
2212
|
+
syntaxTree6(state).iterate({
|
|
2228
2213
|
enter: (node) => {
|
|
2229
2214
|
if (node.name === "TaskMarker") {
|
|
2230
2215
|
if (cursor < node.from || cursor > node.to) {
|
|
2231
2216
|
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2232
|
-
builder.add(node.from - 2, node.from - 1,
|
|
2217
|
+
builder.add(node.from - 2, node.from - 1, Decoration9.mark({
|
|
2233
2218
|
class: "cm-task"
|
|
2234
2219
|
}));
|
|
2235
2220
|
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
@@ -2244,13 +2229,13 @@ var buildDecorations4 = (view) => {
|
|
|
2244
2229
|
};
|
|
2245
2230
|
var tasklist = (options = {}) => {
|
|
2246
2231
|
return [
|
|
2247
|
-
|
|
2232
|
+
ViewPlugin7.fromClass(class {
|
|
2248
2233
|
constructor(view) {
|
|
2249
|
-
this.decorations =
|
|
2234
|
+
this.decorations = buildDecorations5(view);
|
|
2250
2235
|
}
|
|
2251
2236
|
update(update2) {
|
|
2252
2237
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2253
|
-
this.decorations =
|
|
2238
|
+
this.decorations = buildDecorations5(update2.view);
|
|
2254
2239
|
}
|
|
2255
2240
|
}
|
|
2256
2241
|
}, {
|
|
@@ -2260,6 +2245,40 @@ var tasklist = (options = {}) => {
|
|
|
2260
2245
|
];
|
|
2261
2246
|
};
|
|
2262
2247
|
|
|
2248
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2249
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2250
|
+
var mention = ({ onSearch }) => {
|
|
2251
|
+
return autocompletion2({
|
|
2252
|
+
// TODO(burdon): Not working.
|
|
2253
|
+
activateOnTyping: true,
|
|
2254
|
+
// activateOnTypingDelay: 100,
|
|
2255
|
+
// selectOnOpen: true,
|
|
2256
|
+
closeOnBlur: false,
|
|
2257
|
+
// defaultKeymap: false,
|
|
2258
|
+
icons: false,
|
|
2259
|
+
override: [
|
|
2260
|
+
(context) => {
|
|
2261
|
+
console.log(context);
|
|
2262
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2263
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2264
|
+
return null;
|
|
2265
|
+
}
|
|
2266
|
+
return {
|
|
2267
|
+
from: match.from,
|
|
2268
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2269
|
+
label: `@${value}`
|
|
2270
|
+
}))
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
]
|
|
2274
|
+
});
|
|
2275
|
+
};
|
|
2276
|
+
|
|
2277
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2278
|
+
var outliner = (options = {}) => {
|
|
2279
|
+
return [];
|
|
2280
|
+
};
|
|
2281
|
+
|
|
2263
2282
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2264
2283
|
import { keymap as keymap5 } from "@codemirror/view";
|
|
2265
2284
|
var defaultItems = [
|
|
@@ -2317,27 +2336,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2317
2336
|
];
|
|
2318
2337
|
};
|
|
2319
2338
|
|
|
2320
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2321
|
-
import { yCollab } from "y-codemirror.next";
|
|
2322
|
-
|
|
2323
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2324
|
-
import * as Y from "yjs";
|
|
2325
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2326
|
-
var cursorConverter2 = (text) => ({
|
|
2327
|
-
toCursor: (index, assoc) => {
|
|
2328
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2329
|
-
},
|
|
2330
|
-
fromCursor: (cursor) => {
|
|
2331
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2332
|
-
}
|
|
2333
|
-
});
|
|
2334
|
-
|
|
2335
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2336
|
-
var yjs = (content, awareness2) => [
|
|
2337
|
-
Cursor.converter.of(cursorConverter2(content)),
|
|
2338
|
-
yCollab(content, awareness2)
|
|
2339
|
-
];
|
|
2340
|
-
|
|
2341
2339
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2342
2340
|
import get3 from "lodash.get";
|
|
2343
2341
|
var defaultTheme = {
|
|
@@ -2580,26 +2578,25 @@ var EditorModes = [
|
|
|
2580
2578
|
"default",
|
|
2581
2579
|
"vim"
|
|
2582
2580
|
];
|
|
2583
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2581
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2584
2582
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2585
2583
|
tabBehavior: "limited"
|
|
2586
2584
|
});
|
|
2587
|
-
const { themeMode } =
|
|
2585
|
+
const { themeMode } = useThemeContext();
|
|
2588
2586
|
const rootRef = useRef(null);
|
|
2589
2587
|
const [view, setView] = useState(null);
|
|
2590
2588
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2591
2589
|
view
|
|
2592
2590
|
]);
|
|
2593
|
-
|
|
2594
|
-
if (
|
|
2591
|
+
useEffect2(() => {
|
|
2592
|
+
if (autoFocus) {
|
|
2595
2593
|
view?.focus();
|
|
2596
2594
|
}
|
|
2597
2595
|
}, [
|
|
2598
2596
|
view,
|
|
2599
|
-
|
|
2597
|
+
autoFocus
|
|
2600
2598
|
]);
|
|
2601
|
-
|
|
2602
|
-
useEffect3(() => {
|
|
2599
|
+
useEffect2(() => {
|
|
2603
2600
|
if (!model || !rootRef.current) {
|
|
2604
2601
|
return;
|
|
2605
2602
|
}
|
|
@@ -2611,7 +2608,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2611
2608
|
EditorView13.exceptionSink.of((err) => {
|
|
2612
2609
|
log2.catch(err, void 0, {
|
|
2613
2610
|
F: __dxlog_file5,
|
|
2614
|
-
L:
|
|
2611
|
+
L: 123,
|
|
2615
2612
|
S: void 0,
|
|
2616
2613
|
C: (f, a) => f(...a)
|
|
2617
2614
|
});
|
|
@@ -2692,8 +2689,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2692
2689
|
ref: rootRef
|
|
2693
2690
|
});
|
|
2694
2691
|
});
|
|
2695
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2696
|
-
const { themeMode } =
|
|
2692
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2693
|
+
const { themeMode } = useThemeContext();
|
|
2697
2694
|
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2698
2695
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2699
2696
|
ref: forwardedRef,
|
|
@@ -2702,7 +2699,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2702
2699
|
basicBundle({
|
|
2703
2700
|
themeMode,
|
|
2704
2701
|
placeholder: placeholder3,
|
|
2705
|
-
|
|
2702
|
+
lineWrapping
|
|
2706
2703
|
}),
|
|
2707
2704
|
...extensions
|
|
2708
2705
|
],
|
|
@@ -2712,7 +2709,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2712
2709
|
});
|
|
2713
2710
|
});
|
|
2714
2711
|
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2715
|
-
const { themeMode } =
|
|
2712
|
+
const { themeMode } = useThemeContext();
|
|
2716
2713
|
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2717
2714
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2718
2715
|
ref: forwardedRef,
|
|
@@ -2733,7 +2730,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2733
2730
|
var defaultSlots = {
|
|
2734
2731
|
root: {
|
|
2735
2732
|
// TODO(burdon): Add focusRing by default/as property?
|
|
2736
|
-
className: mx3("flex flex-col grow overflow-y-auto",
|
|
2733
|
+
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
2737
2734
|
},
|
|
2738
2735
|
editor: {
|
|
2739
2736
|
className: "h-full p-2"
|
|
@@ -2746,11 +2743,6 @@ var defaultMarkdownSlots = {
|
|
|
2746
2743
|
...defaultSlots
|
|
2747
2744
|
};
|
|
2748
2745
|
|
|
2749
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2750
|
-
import get4 from "lodash.get";
|
|
2751
|
-
import { getRawDoc } from "@dxos/echo-schema";
|
|
2752
|
-
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2753
|
-
|
|
2754
2746
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2755
2747
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2756
2748
|
import { Context as Context2 } from "@dxos/context";
|
|
@@ -2760,8 +2752,8 @@ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src
|
|
|
2760
2752
|
var DEBOUNCE_INTERVAL = 100;
|
|
2761
2753
|
var SpaceAwarenessProvider = class {
|
|
2762
2754
|
constructor(params) {
|
|
2763
|
-
this.remoteStateChange = new Event2();
|
|
2764
2755
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
2756
|
+
this.remoteStateChange = new Event2();
|
|
2765
2757
|
this._space = params.space;
|
|
2766
2758
|
this._channel = params.channel;
|
|
2767
2759
|
this._peerId = params.peerId;
|
|
@@ -2778,7 +2770,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2778
2770
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2779
2771
|
}
|
|
2780
2772
|
});
|
|
2781
|
-
|
|
2773
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2782
2774
|
switch (message.payload.kind) {
|
|
2783
2775
|
case "query": {
|
|
2784
2776
|
this._handleQueryMessage();
|
|
@@ -2789,8 +2781,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2789
2781
|
break;
|
|
2790
2782
|
}
|
|
2791
2783
|
}
|
|
2792
|
-
});
|
|
2793
|
-
this._ctx.onDispose(unsubscribe);
|
|
2784
|
+
}));
|
|
2794
2785
|
void this._space.postMessage(this._channel, {
|
|
2795
2786
|
kind: "query"
|
|
2796
2787
|
}).catch((err) => {
|
|
@@ -2798,7 +2789,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2798
2789
|
err
|
|
2799
2790
|
}, {
|
|
2800
2791
|
F: __dxlog_file6,
|
|
2801
|
-
L:
|
|
2792
|
+
L: 89,
|
|
2802
2793
|
S: this,
|
|
2803
2794
|
C: (f, a) => f(...a)
|
|
2804
2795
|
});
|
|
@@ -2809,10 +2800,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2809
2800
|
this._ctx = void 0;
|
|
2810
2801
|
this._postTask = void 0;
|
|
2811
2802
|
}
|
|
2803
|
+
getRemoteStates() {
|
|
2804
|
+
return Array.from(this._remoteStates.values());
|
|
2805
|
+
}
|
|
2812
2806
|
update(position) {
|
|
2813
2807
|
invariant4(this._postTask, void 0, {
|
|
2814
2808
|
F: __dxlog_file6,
|
|
2815
|
-
L:
|
|
2809
|
+
L: 104,
|
|
2816
2810
|
S: this,
|
|
2817
2811
|
A: [
|
|
2818
2812
|
"this._postTask",
|
|
@@ -2826,13 +2820,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2826
2820
|
};
|
|
2827
2821
|
this._postTask.schedule();
|
|
2828
2822
|
}
|
|
2829
|
-
getRemoteStates() {
|
|
2830
|
-
return Array.from(this._remoteStates.values());
|
|
2831
|
-
}
|
|
2832
2823
|
_handleQueryMessage() {
|
|
2833
2824
|
invariant4(this._postTask, void 0, {
|
|
2834
2825
|
F: __dxlog_file6,
|
|
2835
|
-
L:
|
|
2826
|
+
L: 115,
|
|
2836
2827
|
S: this,
|
|
2837
2828
|
A: [
|
|
2838
2829
|
"this._postTask",
|
|
@@ -2844,7 +2835,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2844
2835
|
_handlePostMessage(message) {
|
|
2845
2836
|
invariant4(message.kind === "post", void 0, {
|
|
2846
2837
|
F: __dxlog_file6,
|
|
2847
|
-
L:
|
|
2838
|
+
L: 120,
|
|
2848
2839
|
S: this,
|
|
2849
2840
|
A: [
|
|
2850
2841
|
"message.kind === 'post'",
|
|
@@ -2863,8 +2854,47 @@ var modelState = StateField5.define({
|
|
|
2863
2854
|
update: (model) => model
|
|
2864
2855
|
});
|
|
2865
2856
|
|
|
2866
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2867
|
-
|
|
2857
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
2858
|
+
import { useState as useState2 } from "react";
|
|
2859
|
+
var useTextEditor = () => {
|
|
2860
|
+
const [view, setView] = useState2(null);
|
|
2861
|
+
return [
|
|
2862
|
+
(ref) => {
|
|
2863
|
+
setView(ref);
|
|
2864
|
+
},
|
|
2865
|
+
view
|
|
2866
|
+
];
|
|
2867
|
+
};
|
|
2868
|
+
|
|
2869
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2870
|
+
import get4 from "lodash.get";
|
|
2871
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
2872
|
+
import { generateName } from "@dxos/display-name";
|
|
2873
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
2874
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
2875
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2876
|
+
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2877
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2878
|
+
var useTextModel = (props) => {
|
|
2879
|
+
const { identity, space, text } = props;
|
|
2880
|
+
const [model, setModel] = useState3();
|
|
2881
|
+
useEffect3(() => setModel(createModel(props)), [
|
|
2882
|
+
identity,
|
|
2883
|
+
space,
|
|
2884
|
+
text
|
|
2885
|
+
]);
|
|
2886
|
+
return model;
|
|
2887
|
+
};
|
|
2888
|
+
var createModel = ({ space, identity, text }) => {
|
|
2889
|
+
invariant5(isAutomergeObject(text), void 0, {
|
|
2890
|
+
F: __dxlog_file7,
|
|
2891
|
+
L: 35,
|
|
2892
|
+
S: void 0,
|
|
2893
|
+
A: [
|
|
2894
|
+
"isAutomergeObject(text)",
|
|
2895
|
+
""
|
|
2896
|
+
]
|
|
2897
|
+
});
|
|
2868
2898
|
const obj = text;
|
|
2869
2899
|
const doc = getRawDoc(obj, [
|
|
2870
2900
|
obj.field
|
|
@@ -2873,7 +2903,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2873
2903
|
space,
|
|
2874
2904
|
channel: `automerge.awareness.${obj.id}`,
|
|
2875
2905
|
info: {
|
|
2876
|
-
displayName: identity
|
|
2906
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
2877
2907
|
color: cursorColor.color,
|
|
2878
2908
|
lightColor: cursorColor.light
|
|
2879
2909
|
},
|
|
@@ -2883,7 +2913,6 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2883
2913
|
id: obj.id,
|
|
2884
2914
|
content: doc,
|
|
2885
2915
|
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2886
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2887
2916
|
extension: [
|
|
2888
2917
|
modelState.init(() => model),
|
|
2889
2918
|
automerge3({
|
|
@@ -2900,162 +2929,6 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2900
2929
|
};
|
|
2901
2930
|
return model;
|
|
2902
2931
|
};
|
|
2903
|
-
|
|
2904
|
-
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2905
|
-
import * as decoding from "lib0/decoding";
|
|
2906
|
-
import * as encoding from "lib0/encoding";
|
|
2907
|
-
import { Observable } from "lib0/observable";
|
|
2908
|
-
import * as YP from "y-protocols/awareness";
|
|
2909
|
-
import { invariant as invariant5 } from "@dxos/invariant";
|
|
2910
|
-
import { log as log4 } from "@dxos/log";
|
|
2911
|
-
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2912
|
-
var createYjsModel = ({ identity, space, text }) => {
|
|
2913
|
-
invariant5(text?.doc && text?.content, void 0, {
|
|
2914
|
-
F: __dxlog_file7,
|
|
2915
|
-
L: 22,
|
|
2916
|
-
S: void 0,
|
|
2917
|
-
A: [
|
|
2918
|
-
"text?.doc && text?.content",
|
|
2919
|
-
""
|
|
2920
|
-
]
|
|
2921
|
-
});
|
|
2922
|
-
const provider = space ? new YAwarenessProvider({
|
|
2923
|
-
space,
|
|
2924
|
-
doc: text.doc,
|
|
2925
|
-
channel: `yjs.awareness.${text.id}`
|
|
2926
|
-
}) : void 0;
|
|
2927
|
-
const model = {
|
|
2928
|
-
id: text.doc.guid,
|
|
2929
|
-
content: text.content,
|
|
2930
|
-
text: () => text.content.toString(),
|
|
2931
|
-
extension: [
|
|
2932
|
-
modelState.init(() => model),
|
|
2933
|
-
yjs(text.content, provider?.awareness)
|
|
2934
|
-
],
|
|
2935
|
-
awareness: provider?.awareness,
|
|
2936
|
-
peer: identity ? {
|
|
2937
|
-
id: identity.identityKey.toHex(),
|
|
2938
|
-
name: identity.profile?.displayName
|
|
2939
|
-
} : void 0
|
|
2940
|
-
};
|
|
2941
|
-
return model;
|
|
2942
|
-
};
|
|
2943
|
-
var messageAwareness = 1;
|
|
2944
|
-
var messageQueryAwareness = 3;
|
|
2945
|
-
var YAwarenessProvider = class extends Observable {
|
|
2946
|
-
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2947
|
-
super();
|
|
2948
|
-
this._space = space;
|
|
2949
|
-
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2950
|
-
this._channel = channel;
|
|
2951
|
-
this._clientId = doc.clientID;
|
|
2952
|
-
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
2953
|
-
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
2954
|
-
if (typeof window !== "undefined") {
|
|
2955
|
-
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
2956
|
-
} else if (typeof process !== "undefined") {
|
|
2957
|
-
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
2958
|
-
}
|
|
2959
|
-
const encoderAwarenessQuery = encoding.createEncoder();
|
|
2960
|
-
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
2961
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
2962
|
-
const encoderAwarenessState = encoding.createEncoder();
|
|
2963
|
-
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
2964
|
-
encoding.writeVarUint8Array(encoderAwarenessState, YP.encodeAwarenessUpdate(this.awareness, [
|
|
2965
|
-
this._clientId
|
|
2966
|
-
]));
|
|
2967
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
2968
|
-
}
|
|
2969
|
-
get awareness() {
|
|
2970
|
-
return this._awareness;
|
|
2971
|
-
}
|
|
2972
|
-
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2973
|
-
log4("awareness update", {
|
|
2974
|
-
added,
|
|
2975
|
-
updated,
|
|
2976
|
-
removed,
|
|
2977
|
-
origin
|
|
2978
|
-
}, {
|
|
2979
|
-
F: __dxlog_file7,
|
|
2980
|
-
L: 101,
|
|
2981
|
-
S: this,
|
|
2982
|
-
C: (f, a) => f(...a)
|
|
2983
|
-
});
|
|
2984
|
-
const changedClients = added.concat(updated).concat(removed);
|
|
2985
|
-
const encoderAwareness = encoding.createEncoder();
|
|
2986
|
-
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
2987
|
-
encoding.writeVarUint8Array(encoderAwareness, YP.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
2988
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2989
|
-
}
|
|
2990
|
-
_handleSpaceMessage({ payload }) {
|
|
2991
|
-
log4("space message", payload, {
|
|
2992
|
-
F: __dxlog_file7,
|
|
2993
|
-
L: 110,
|
|
2994
|
-
S: this,
|
|
2995
|
-
C: (f, a) => f(...a)
|
|
2996
|
-
});
|
|
2997
|
-
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2998
|
-
const encoder = this._readMessage(data);
|
|
2999
|
-
if (encoder) {
|
|
3000
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
3001
|
-
}
|
|
3002
|
-
}
|
|
3003
|
-
_readMessage(message) {
|
|
3004
|
-
const decoder = decoding.createDecoder(message);
|
|
3005
|
-
const encoder = encoding.createEncoder();
|
|
3006
|
-
const messageType = decoding.readVarUint(decoder);
|
|
3007
|
-
let sendReply = false;
|
|
3008
|
-
switch (messageType) {
|
|
3009
|
-
case messageAwareness: {
|
|
3010
|
-
YP.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
3011
|
-
break;
|
|
3012
|
-
}
|
|
3013
|
-
case messageQueryAwareness: {
|
|
3014
|
-
encoding.writeVarUint(encoder, messageAwareness);
|
|
3015
|
-
encoding.writeVarUint8Array(encoder, YP.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
3016
|
-
sendReply = true;
|
|
3017
|
-
break;
|
|
3018
|
-
}
|
|
3019
|
-
default: {
|
|
3020
|
-
console.error("Invalid message:", messageType);
|
|
3021
|
-
return encoder;
|
|
3022
|
-
}
|
|
3023
|
-
}
|
|
3024
|
-
if (!sendReply) {
|
|
3025
|
-
return null;
|
|
3026
|
-
}
|
|
3027
|
-
return encoder;
|
|
3028
|
-
}
|
|
3029
|
-
_handleBeforeUnload() {
|
|
3030
|
-
YP.removeAwarenessStates(this._awareness, [
|
|
3031
|
-
this._clientId
|
|
3032
|
-
], "window unload");
|
|
3033
|
-
}
|
|
3034
|
-
};
|
|
3035
|
-
|
|
3036
|
-
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
3037
|
-
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
3038
|
-
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
3039
|
-
var useTextModel = (props) => {
|
|
3040
|
-
const { identity, space, text } = props;
|
|
3041
|
-
const [model, setModel] = useState2();
|
|
3042
|
-
useEffect4(() => setModel(createModel(props)), [
|
|
3043
|
-
identity,
|
|
3044
|
-
space,
|
|
3045
|
-
text
|
|
3046
|
-
]);
|
|
3047
|
-
return model;
|
|
3048
|
-
};
|
|
3049
|
-
var createModel = (props) => {
|
|
3050
|
-
const { text } = props;
|
|
3051
|
-
if (isAutomergeObject(text)) {
|
|
3052
|
-
return createAutomergeModel(props);
|
|
3053
|
-
} else if (text?.doc) {
|
|
3054
|
-
return createYjsModel(props);
|
|
3055
|
-
} else {
|
|
3056
|
-
return void 0;
|
|
3057
|
-
}
|
|
3058
|
-
};
|
|
3059
2932
|
export {
|
|
3060
2933
|
AwarenessProvider,
|
|
3061
2934
|
BaseTextEditor,
|
|
@@ -3067,7 +2940,6 @@ export {
|
|
|
3067
2940
|
SpaceAwarenessProvider,
|
|
3068
2941
|
TextEditor,
|
|
3069
2942
|
TextKind,
|
|
3070
|
-
YAwarenessProvider,
|
|
3071
2943
|
YText,
|
|
3072
2944
|
YXmlFragment,
|
|
3073
2945
|
autocomplete,
|
|
@@ -3079,14 +2951,13 @@ export {
|
|
|
3079
2951
|
code2 as code,
|
|
3080
2952
|
codeTheme,
|
|
3081
2953
|
comments,
|
|
3082
|
-
createAutomergeModel,
|
|
3083
|
-
createYjsModel,
|
|
3084
2954
|
defaultMarkdownSlots,
|
|
3085
2955
|
defaultOptions,
|
|
3086
2956
|
defaultSlots,
|
|
3087
2957
|
defaultTextSlots,
|
|
3088
2958
|
defaultTheme,
|
|
3089
2959
|
getToken,
|
|
2960
|
+
heading2 as heading,
|
|
3090
2961
|
hr,
|
|
3091
2962
|
image,
|
|
3092
2963
|
link,
|
|
@@ -3108,9 +2979,8 @@ export {
|
|
|
3108
2979
|
tasklist,
|
|
3109
2980
|
textTheme,
|
|
3110
2981
|
typewriter,
|
|
3111
|
-
useAwareness,
|
|
3112
2982
|
useComments,
|
|
3113
|
-
|
|
3114
|
-
|
|
2983
|
+
useTextEditor,
|
|
2984
|
+
useTextModel
|
|
3115
2985
|
};
|
|
3116
2986
|
//# sourceMappingURL=index.mjs.map
|