@dxos/react-ui-editor 0.3.9-main.632a97f → 0.3.9-main.71124bf
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 +962 -608
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/automerge/automerge-plugin/PatchSemaphore.d.ts +2 -2
- package/dist/types/src/automerge/automerge-plugin/PatchSemaphore.d.ts.map +1 -1
- package/dist/types/src/automerge/automerge-plugin/codeMirrorToAm.d.ts +2 -2
- package/dist/types/src/automerge/automerge-plugin/codeMirrorToAm.d.ts.map +1 -1
- package/dist/types/src/automerge/automerge-plugin/handle.d.ts +9 -0
- package/dist/types/src/automerge/automerge-plugin/handle.d.ts.map +1 -0
- package/dist/types/src/automerge/automerge-plugin/index.d.ts +2 -2
- package/dist/types/src/automerge/automerge-plugin/index.d.ts.map +1 -1
- package/dist/types/src/automerge/automerge-plugin/plugin.d.ts +6 -5
- package/dist/types/src/automerge/automerge-plugin/plugin.d.ts.map +1 -1
- package/dist/types/src/automerge/automerge.stories.d.ts +2 -1
- package/dist/types/src/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +24 -20
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +8 -10
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/{stories/html/code-mirror.stories.d.ts → src/components/TextEditor/codemirror.stories.d.ts} +2 -2
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/basic/bundle.d.ts +8 -0
- package/dist/types/src/components/TextEditor/extensions/basic/bundle.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/basic/index.d.ts +3 -0
- package/dist/types/src/components/TextEditor/extensions/basic/index.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/basic/theme.d.ts +10 -0
- package/dist/types/src/components/TextEditor/extensions/basic/theme.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/change.d.ts +7 -0
- package/dist/types/src/components/TextEditor/extensions/change.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.d.ts +11 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.d.ts +8 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkWidget.d.ts +10 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkWidget.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/index.d.ts +4 -0
- package/dist/types/src/components/TextEditor/extensions/hyperlink/index.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts +5 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +8 -0
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts +3 -0
- package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts.map +1 -0
- package/dist/types/src/components/{Markdown/markdownTags.d.ts → TextEditor/extensions/markdown/tags.d.ts} +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/tags.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/markdown/theme.d.ts +21 -0
- package/dist/types/src/components/TextEditor/extensions/markdown/theme.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/index.d.ts +1 -2
- package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +11 -0
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +0 -3
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +4 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useCollaboration.d.ts +9 -0
- package/dist/types/src/hooks/useCollaboration.d.ts.map +1 -0
- package/dist/types/src/{model.d.ts → hooks/useTextModel.d.ts} +3 -15
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -0
- package/dist/types/src/hooks/yjs/cursors.d.ts.map +1 -0
- package/dist/types/src/hooks/yjs/index.d.ts.map +1 -0
- package/dist/types/src/hooks/yjs/space-provider.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/tokens.d.ts +4 -0
- package/dist/types/src/styles/tokens.d.ts.map +1 -1
- package/dist/types/src/testing/replicator.d.ts +1 -1
- package/dist/types/src/testing/replicator.d.ts.map +1 -1
- package/package.json +32 -26
- package/src/automerge/automerge-plugin/PatchSemaphore.ts +5 -5
- package/src/automerge/automerge-plugin/codeMirrorToAm.ts +10 -7
- package/src/automerge/automerge-plugin/handle.ts +14 -0
- package/src/automerge/automerge-plugin/index.ts +2 -2
- package/src/automerge/automerge-plugin/plugin.ts +39 -10
- package/src/automerge/automerge.stories.tsx +32 -47
- package/src/components/TextEditor/TextEditor.stories.tsx +56 -8
- package/src/components/TextEditor/TextEditor.tsx +113 -55
- package/src/components/TextEditor/codemirror.stories.ts +114 -0
- package/src/components/TextEditor/extensions/basic/bundle.ts +26 -0
- package/src/components/TextEditor/extensions/basic/index.ts +6 -0
- package/src/components/TextEditor/extensions/basic/theme.ts +49 -0
- package/src/components/TextEditor/extensions/change.ts +22 -0
- package/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.ts +99 -0
- package/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.tsx +61 -0
- package/src/components/TextEditor/extensions/hyperlink/hyperlinkWidget.tsx +119 -0
- package/src/components/TextEditor/extensions/hyperlink/index.ts +7 -0
- package/src/components/TextEditor/extensions/index.ts +8 -0
- package/src/components/TextEditor/extensions/markdown/bundle.ts +99 -0
- package/src/components/TextEditor/extensions/markdown/index.ts +6 -0
- package/src/components/{Markdown/markdownTheme.ts → TextEditor/extensions/markdown/theme.ts} +42 -27
- package/src/components/TextEditor/index.ts +1 -2
- package/src/components/TextEditor/yjs.stories.tsx +55 -0
- package/src/components/index.ts +0 -3
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useCollaboration.ts +45 -0
- package/src/{model.ts → hooks/useTextModel.ts} +42 -17
- package/src/index.ts +3 -3
- package/src/styles/tokens.ts +6 -0
- package/src/testing/replicator.ts +1 -2
- package/dist/types/src/automerge/demo.d.ts +0 -25
- package/dist/types/src/automerge/demo.d.ts.map +0 -1
- package/dist/types/src/components/Editor/Editor.d.ts +0 -15
- package/dist/types/src/components/Editor/Editor.d.ts.map +0 -1
- package/dist/types/src/components/Editor/Editor.stories.d.ts +0 -28
- package/dist/types/src/components/Editor/Editor.stories.d.ts.map +0 -1
- package/dist/types/src/components/Editor/index.d.ts +0 -2
- package/dist/types/src/components/Editor/index.d.ts.map +0 -1
- package/dist/types/src/components/Markdown/Markdown.d.ts +0 -19
- package/dist/types/src/components/Markdown/Markdown.d.ts.map +0 -1
- package/dist/types/src/components/Markdown/Markdown.stories.d.ts +0 -19
- package/dist/types/src/components/Markdown/Markdown.stories.d.ts.map +0 -1
- package/dist/types/src/components/Markdown/index.d.ts +0 -2
- package/dist/types/src/components/Markdown/index.d.ts.map +0 -1
- package/dist/types/src/components/Markdown/markdownTags.d.ts.map +0 -1
- package/dist/types/src/components/Markdown/markdownTheme.d.ts +0 -107
- package/dist/types/src/components/Markdown/markdownTheme.d.ts.map +0 -1
- package/dist/types/src/components/RichText/RichText.d.ts +0 -20
- package/dist/types/src/components/RichText/RichText.d.ts.map +0 -1
- package/dist/types/src/components/RichText/RichText.stories.d.ts +0 -26
- package/dist/types/src/components/RichText/RichText.stories.d.ts.map +0 -1
- package/dist/types/src/components/RichText/index.d.ts +0 -2
- package/dist/types/src/components/RichText/index.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/theme.d.ts +0 -8
- package/dist/types/src/components/TextEditor/theme.d.ts.map +0 -1
- package/dist/types/src/model.d.ts.map +0 -1
- package/dist/types/src/yjs/cursors.d.ts.map +0 -1
- package/dist/types/src/yjs/index.d.ts.map +0 -1
- package/dist/types/src/yjs/space-provider.d.ts.map +0 -1
- package/dist/types/stories/html/code-mirror.stories.d.ts.map +0 -1
- package/src/automerge/demo.ts +0 -106
- package/src/components/Editor/Editor.stories.tsx +0 -80
- package/src/components/Editor/Editor.tsx +0 -33
- package/src/components/Editor/index.ts +0 -5
- package/src/components/Markdown/Markdown.stories.tsx +0 -57
- package/src/components/Markdown/Markdown.tsx +0 -210
- package/src/components/Markdown/index.ts +0 -5
- package/src/components/RichText/RichText.stories.tsx +0 -68
- package/src/components/RichText/RichText.tsx +0 -181
- package/src/components/RichText/index.ts +0 -5
- package/src/components/TextEditor/theme.ts +0 -29
- /package/dist/types/src/{yjs → hooks/yjs}/cursors.d.ts +0 -0
- /package/dist/types/src/{yjs → hooks/yjs}/index.d.ts +0 -0
- /package/dist/types/src/{yjs → hooks/yjs}/space-provider.d.ts +0 -0
- /package/src/components/{Markdown/markdownTags.ts → TextEditor/extensions/markdown/tags.ts} +0 -0
- /package/src/{yjs → hooks/yjs}/cursors.ts +0 -0
- /package/src/{yjs → hooks/yjs}/index.ts +0 -0
- /package/src/{yjs → hooks/yjs}/space-provider.ts +0 -0
|
@@ -1,199 +1,305 @@
|
|
|
1
|
-
// packages/ui/react-ui-editor/src/
|
|
2
|
-
import
|
|
3
|
-
import { YXmlFragment } from "@dxos/text-model";
|
|
1
|
+
// packages/ui/react-ui-editor/src/index.ts
|
|
2
|
+
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
3
|
+
import { Doc, YText as YText2, YXmlFragment } from "@dxos/text-model";
|
|
4
4
|
|
|
5
|
-
// packages/ui/react-ui-editor/src/
|
|
6
|
-
import {
|
|
5
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
6
|
+
import { tags as tags2 } from "@lezer/highlight";
|
|
7
7
|
|
|
8
|
-
// packages/ui/react-ui-editor/src/
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic/bundle.ts
|
|
9
|
+
import { closeBrackets } from "@codemirror/autocomplete";
|
|
10
|
+
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
11
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
12
|
+
import { placeholder } from "@codemirror/view";
|
|
13
|
+
var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
|
|
14
|
+
bracketMatching(),
|
|
15
|
+
closeBrackets(),
|
|
16
|
+
_placeholder && placeholder(_placeholder),
|
|
17
|
+
// TODO(burdon): Is this required?
|
|
18
|
+
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
19
|
+
].filter(Boolean);
|
|
20
|
+
|
|
21
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic/theme.ts
|
|
22
|
+
import get from "lodash.get";
|
|
23
|
+
|
|
24
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
25
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
26
|
+
var heading = {
|
|
27
|
+
1: "mbs-4 mbe-2 text-4xl font-semibold text-inherit no-underline",
|
|
28
|
+
2: "mbs-4 mbe-2 text-3xl font-bold text-inherit no-underline",
|
|
29
|
+
3: "mbs-4 mbe-2 text-2xl font-bold text-inherit no-underline",
|
|
30
|
+
4: "mbs-4 mbe-2 text-xl font-extrabold text-inherit no-underline",
|
|
31
|
+
5: "mbs-4 mbe-2 text-lg font-extrabold text-inherit no-underline",
|
|
32
|
+
6: "mbs-4 mbe-2 font-black text-inherit no-underline"
|
|
33
|
+
};
|
|
34
|
+
var bold = "font-bold";
|
|
35
|
+
var code = "font-mono bg-neutral-500/10 rounded pli-0.5 plb-0.5 -mlb-0.5";
|
|
36
|
+
var codeWithoutMarks = mx(code, "pli-1.5 mli-0.5");
|
|
37
|
+
var italic = "italic";
|
|
38
|
+
var strikethrough = "line-through";
|
|
39
|
+
var mark = "!font-normal !no-underline !text-inherit opacity-40";
|
|
40
|
+
|
|
41
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
42
|
+
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
43
|
+
var tokens = tailwindConfig({}).theme;
|
|
44
|
+
|
|
45
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic/theme.ts
|
|
46
|
+
var basicTheme = {
|
|
47
|
+
"&.cm-focused": {
|
|
48
|
+
outline: "none"
|
|
14
49
|
},
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
50
|
+
"& .cm-line": {
|
|
51
|
+
paddingInline: 0,
|
|
52
|
+
lineHeight: 1.6,
|
|
53
|
+
minBlockSize: "1.6em"
|
|
18
54
|
},
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
light: "#ffbc4233"
|
|
55
|
+
"& .cm-line *": {
|
|
56
|
+
lineHeight: 1.6
|
|
22
57
|
},
|
|
23
|
-
{
|
|
24
|
-
|
|
25
|
-
|
|
58
|
+
"& .cm-scroller": {
|
|
59
|
+
fontFamily: get(tokens, "fontFamily.body", []).join(","),
|
|
60
|
+
overflow: "visible"
|
|
26
61
|
},
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
62
|
+
"& .cm-content": {
|
|
63
|
+
padding: 0,
|
|
64
|
+
caretColor: "black"
|
|
30
65
|
},
|
|
31
|
-
{
|
|
32
|
-
|
|
33
|
-
light: "#9ac2c933"
|
|
66
|
+
".dark & .cm-content": {
|
|
67
|
+
caretColor: "white"
|
|
34
68
|
},
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
69
|
+
"& .cm-tooltip": {
|
|
70
|
+
backgroundColor: "transparent",
|
|
71
|
+
border: "none"
|
|
38
72
|
},
|
|
39
|
-
{
|
|
40
|
-
color: "
|
|
41
|
-
|
|
73
|
+
"& .cm-link": {
|
|
74
|
+
color: get(tokens, "extend.colors.primary.500"),
|
|
75
|
+
textDecoration: "underline"
|
|
42
76
|
}
|
|
43
|
-
|
|
44
|
-
var cursorColor = cursorColors[random.uint32() % cursorColors.length];
|
|
77
|
+
};
|
|
45
78
|
|
|
46
|
-
// packages/ui/react-ui-editor/src/
|
|
47
|
-
import
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
var messageAwareness = 1;
|
|
54
|
-
var messageQueryAwareness = 3;
|
|
55
|
-
var SpaceAwarenessProvider = class extends Observable {
|
|
56
|
-
constructor({ space, doc, channel, awareness }) {
|
|
57
|
-
super();
|
|
58
|
-
this._space = space;
|
|
59
|
-
this._awareness = awareness ?? new awarenessProtocol.Awareness(doc);
|
|
60
|
-
this._channel = channel;
|
|
61
|
-
this._clientId = doc.clientID;
|
|
62
|
-
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
63
|
-
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
64
|
-
if (typeof window !== "undefined") {
|
|
65
|
-
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
66
|
-
} else if (typeof process !== "undefined") {
|
|
67
|
-
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
79
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/change.ts
|
|
80
|
+
import { StateField } from "@codemirror/state";
|
|
81
|
+
var onChangeExtension = (onChange) => StateField.define({
|
|
82
|
+
create: () => null,
|
|
83
|
+
update: (_value, transaction) => {
|
|
84
|
+
if (transaction.docChanged && onChange) {
|
|
85
|
+
onChange(transaction.newDoc.toString());
|
|
68
86
|
}
|
|
69
|
-
|
|
70
|
-
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
71
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
72
|
-
const encoderAwarenessState = encoding.createEncoder();
|
|
73
|
-
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
74
|
-
encoding.writeVarUint8Array(encoderAwarenessState, awarenessProtocol.encodeAwarenessUpdate(this.awareness, [
|
|
75
|
-
this._clientId
|
|
76
|
-
]));
|
|
77
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
87
|
+
return null;
|
|
78
88
|
}
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.ts
|
|
92
|
+
import { syntaxTree } from "@codemirror/language";
|
|
93
|
+
import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
|
|
94
|
+
import { Decoration, EditorView, WidgetType } from "@codemirror/view";
|
|
95
|
+
var Link = class extends WidgetType {
|
|
96
|
+
constructor(_anchor, _text, _url) {
|
|
97
|
+
super();
|
|
98
|
+
this._anchor = _anchor;
|
|
99
|
+
this._text = _text;
|
|
100
|
+
this._url = _url;
|
|
81
101
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
added,
|
|
85
|
-
updated,
|
|
86
|
-
removed,
|
|
87
|
-
origin
|
|
88
|
-
}, {
|
|
89
|
-
F: __dxlog_file,
|
|
90
|
-
L: 67,
|
|
91
|
-
S: this,
|
|
92
|
-
C: (f, a) => f(...a)
|
|
93
|
-
});
|
|
94
|
-
const changedClients = added.concat(updated).concat(removed);
|
|
95
|
-
const encoderAwareness = encoding.createEncoder();
|
|
96
|
-
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
97
|
-
encoding.writeVarUint8Array(encoderAwareness, awarenessProtocol.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
98
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
102
|
+
eq(other) {
|
|
103
|
+
return this._text === other.text && this._url === other.url;
|
|
99
104
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
toDOM(view) {
|
|
106
|
+
const link = document.createElement("a");
|
|
107
|
+
link.setAttribute("class", "cm-link");
|
|
108
|
+
link.textContent = this._text;
|
|
109
|
+
if (this._url) {
|
|
110
|
+
link.setAttribute("target", "_blank");
|
|
111
|
+
link.href = this._url;
|
|
112
|
+
} else {
|
|
113
|
+
link.onclick = () => {
|
|
114
|
+
view.dispatch({
|
|
115
|
+
selection: {
|
|
116
|
+
anchor: this._anchor
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
};
|
|
111
120
|
}
|
|
121
|
+
return link;
|
|
112
122
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
};
|
|
124
|
+
var hyperlinkDecoration = ({ link } = {}) => {
|
|
125
|
+
return StateField2.define({
|
|
126
|
+
create: (state) => update(state, link),
|
|
127
|
+
update: (_, tr) => update(tr.state, link),
|
|
128
|
+
provide: (field) => EditorView.decorations.from(field)
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
var update = (state, link) => {
|
|
132
|
+
const builder = new RangeSetBuilder();
|
|
133
|
+
const cursor = state.selection.main.head;
|
|
134
|
+
syntaxTree(state).iterate({
|
|
135
|
+
enter: (node) => {
|
|
136
|
+
if (cursor < node.from || cursor > node.to) {
|
|
137
|
+
if (node.name === "Link") {
|
|
138
|
+
const marks = node.node.getChildren("LinkMark");
|
|
139
|
+
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
140
|
+
const urlNode = node.node.getChild("URL");
|
|
141
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
142
|
+
builder.add(node.from, node.to, Decoration.replace({
|
|
143
|
+
widget: new Link(node.from, text, link ? url : void 0)
|
|
144
|
+
}));
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
132
147
|
}
|
|
148
|
+
return true;
|
|
133
149
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
return encoder;
|
|
138
|
-
}
|
|
139
|
-
_handleBeforeUnload() {
|
|
140
|
-
awarenessProtocol.removeAwarenessStates(this._awareness, [
|
|
141
|
-
this._clientId
|
|
142
|
-
], "window unload");
|
|
143
|
-
}
|
|
150
|
+
});
|
|
151
|
+
return builder.finish();
|
|
144
152
|
};
|
|
145
153
|
|
|
146
|
-
// packages/ui/react-ui-editor/src/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.tsx
|
|
155
|
+
import { hoverTooltip } from "@codemirror/view";
|
|
156
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
157
|
+
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
158
|
+
var createHyperlinkTooltip = (onHover, regexp = markdownLinkRegexp) => hoverTooltip((view, pos) => {
|
|
159
|
+
const { from, text } = view.state.doc.lineAt(pos);
|
|
160
|
+
const p = pos - from;
|
|
161
|
+
let idx = 0;
|
|
162
|
+
let match;
|
|
163
|
+
do {
|
|
164
|
+
match = text.substring(idx).match(regexp);
|
|
165
|
+
if (!match) {
|
|
166
|
+
match = void 0;
|
|
167
|
+
break;
|
|
151
168
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
text?.doc
|
|
161
|
-
]);
|
|
162
|
-
if (!text?.doc || !text?.content) {
|
|
163
|
-
return void 0;
|
|
169
|
+
idx = text.indexOf(match[0]);
|
|
170
|
+
if (p >= idx && p < idx + match[0].length) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
idx += match[0].length;
|
|
174
|
+
} while (true);
|
|
175
|
+
if (!match) {
|
|
176
|
+
return null;
|
|
164
177
|
}
|
|
178
|
+
const [, , url] = match ?? [];
|
|
165
179
|
return {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
180
|
+
pos: idx + from,
|
|
181
|
+
end: idx + from + match[0].length,
|
|
182
|
+
above: true,
|
|
183
|
+
create: () => {
|
|
184
|
+
const el = document.createElement("a");
|
|
185
|
+
el.innerText = "_";
|
|
186
|
+
el.className = tooltipContent({}, "mb-2 p-1");
|
|
187
|
+
el.setAttribute("target", "_blank");
|
|
188
|
+
el.setAttribute("href", url);
|
|
189
|
+
onHover(el, url);
|
|
190
|
+
return {
|
|
191
|
+
dom: el
|
|
192
|
+
};
|
|
193
|
+
}
|
|
173
194
|
};
|
|
174
|
-
};
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkWidget.tsx
|
|
198
|
+
import { Decoration as Decoration2, EditorView as EditorView2, MatchDecorator, ViewPlugin } from "@codemirror/view";
|
|
199
|
+
var markdownLinkRegexp2 = /\[([^\]]+)]\(([^)]+)\)(!?)/gi;
|
|
200
|
+
var linkDecorator = () => new MatchDecorator({
|
|
201
|
+
regexp: markdownLinkRegexp2,
|
|
202
|
+
decorate: (add, from, to, match, view) => {
|
|
203
|
+
const [_, label, url] = match;
|
|
204
|
+
const p0 = {
|
|
205
|
+
start: from,
|
|
206
|
+
end: from + 1
|
|
207
|
+
};
|
|
208
|
+
const p1 = {
|
|
209
|
+
start: from + 1,
|
|
210
|
+
end: from + 1 + label.length
|
|
211
|
+
};
|
|
212
|
+
const p2 = {
|
|
213
|
+
start: p1.end,
|
|
214
|
+
end: p1.end + 1
|
|
215
|
+
};
|
|
216
|
+
const p3 = {
|
|
217
|
+
start: p1.end + 1,
|
|
218
|
+
end: p1.end + 1 + url.length + 2
|
|
219
|
+
};
|
|
220
|
+
add(p0.start, p0.end, Decoration2.mark({
|
|
221
|
+
class: "cm-hyperlink-bracket",
|
|
222
|
+
_attributes: {
|
|
223
|
+
style: "display: none"
|
|
224
|
+
}
|
|
225
|
+
}));
|
|
226
|
+
add(p1.start, p1.end, Decoration2.mark({
|
|
227
|
+
class: "cm-hyperlink-label"
|
|
228
|
+
}));
|
|
229
|
+
add(p2.start, p2.end, Decoration2.mark({
|
|
230
|
+
class: "cm-hyperlink-bracket",
|
|
231
|
+
_attributes: {
|
|
232
|
+
style: "display: none"
|
|
233
|
+
}
|
|
234
|
+
}));
|
|
235
|
+
add(p3.start, p3.end, Decoration2.mark({
|
|
236
|
+
class: "cm-hyperlink-url",
|
|
237
|
+
_attributes: {
|
|
238
|
+
style: "display: none"
|
|
239
|
+
}
|
|
240
|
+
}));
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
function hyperLinkExtension() {
|
|
244
|
+
return ViewPlugin.fromClass(class HyperLinkView {
|
|
245
|
+
constructor(view) {
|
|
246
|
+
this.decorator = linkDecorator();
|
|
247
|
+
this.decorations = this.decorator.createDeco(view);
|
|
248
|
+
}
|
|
249
|
+
update(update2) {
|
|
250
|
+
if (update2.docChanged || update2.viewportChanged) {
|
|
251
|
+
this.decorations = this.decorator.updateDeco(update2, this.decorations);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}, {
|
|
255
|
+
decorations: (view) => view.decorations,
|
|
256
|
+
eventHandlers: {
|
|
257
|
+
// TODO(burdon): CLick to expand link.
|
|
258
|
+
// https://discuss.codemirror.net/t/decorator-iteration-on-click-event/4226/2
|
|
259
|
+
mousedown: function(event, view) {
|
|
260
|
+
const pos = view.posAtDOM(event.target);
|
|
261
|
+
if (pos !== 0) {
|
|
262
|
+
console.log(this);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
// TODO(burdon): Hide when cursor moves away.
|
|
266
|
+
keydown: (event, view) => {
|
|
267
|
+
view.update([]);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
var hyperlinkStyle = EditorView2.baseTheme({
|
|
273
|
+
".cm-hyperlink-label": {
|
|
274
|
+
cursor: "pointer",
|
|
275
|
+
textDecoration: "underline"
|
|
276
|
+
},
|
|
277
|
+
".cm-hyperlink-bracket": {
|
|
278
|
+
opacity: 0.2
|
|
279
|
+
},
|
|
280
|
+
".cm-hyperlink-url": {
|
|
281
|
+
opacity: 0.5,
|
|
282
|
+
fontFamily: "monospace"
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
var hyperlinkWidget = [
|
|
286
|
+
hyperLinkExtension(),
|
|
287
|
+
hyperlinkStyle
|
|
288
|
+
];
|
|
175
289
|
|
|
176
|
-
// packages/ui/react-ui-editor/src/components/
|
|
177
|
-
import {
|
|
290
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
291
|
+
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
178
292
|
import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
|
|
179
|
-
import {
|
|
180
|
-
import { bracketMatching, defaultHighlightStyle, foldKeymap, indentOnInput, syntaxHighlighting } from "@codemirror/language";
|
|
293
|
+
import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
|
|
294
|
+
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, foldKeymap, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
181
295
|
import { languages } from "@codemirror/language-data";
|
|
182
296
|
import { lintKeymap } from "@codemirror/lint";
|
|
183
|
-
import {
|
|
184
|
-
import { EditorState
|
|
185
|
-
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
186
|
-
import {
|
|
187
|
-
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
188
|
-
import { vim } from "@replit/codemirror-vim";
|
|
189
|
-
import React, { forwardRef, useEffect, useImperativeHandle, useState, useMemo as useMemo2, useCallback } from "react";
|
|
190
|
-
import { yCollab } from "y-codemirror.next";
|
|
191
|
-
import { generateName } from "@dxos/display-name";
|
|
192
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
193
|
-
import { getColorForValue } from "@dxos/react-ui-theme";
|
|
194
|
-
import { YText } from "@dxos/text-model";
|
|
297
|
+
import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
|
|
298
|
+
import { EditorState } from "@codemirror/state";
|
|
299
|
+
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
300
|
+
import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView3, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
|
|
195
301
|
|
|
196
|
-
// packages/ui/react-ui-editor/src/components/
|
|
302
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/tags.ts
|
|
197
303
|
import { styleTags, Tag } from "@lezer/highlight";
|
|
198
304
|
var markdownTags = {
|
|
199
305
|
headingMark: Tag.define(),
|
|
@@ -226,51 +332,28 @@ var markdownTagsExtension = {
|
|
|
226
332
|
]
|
|
227
333
|
};
|
|
228
334
|
|
|
229
|
-
// packages/ui/react-ui-editor/src/components/
|
|
335
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/theme.ts
|
|
230
336
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
231
337
|
import { HighlightStyle } from "@codemirror/language";
|
|
232
338
|
import { tags } from "@lezer/highlight";
|
|
233
|
-
import
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
var
|
|
238
|
-
1: "mbs-4 mbe-2 text-4xl font-semibold text-inherit no-underline",
|
|
239
|
-
2: "mbs-4 mbe-2 text-3xl font-bold text-inherit no-underline",
|
|
240
|
-
3: "mbs-4 mbe-2 text-2xl font-bold text-inherit no-underline",
|
|
241
|
-
4: "mbs-4 mbe-2 text-xl font-extrabold text-inherit no-underline",
|
|
242
|
-
5: "mbs-4 mbe-2 text-lg font-extrabold text-inherit no-underline",
|
|
243
|
-
6: "mbs-4 mbe-2 font-black text-inherit no-underline"
|
|
244
|
-
};
|
|
245
|
-
var blockquote = "mlb-2 border-is-4 border-neutral-500/50 pis-5";
|
|
246
|
-
var unorderedList = "mlb-2 grid grid-cols-[min-content_1fr] [&>li:before]:content-[attr(marker)] [&>li:before]:mlb-1 [&>li:before]:mie-2";
|
|
247
|
-
var orderedList = 'mlb-2 grid grid-cols-[min-content_1fr] [&>li:before]:content-[counters(section,_".")_"._"] [counter-reset:section] [&>li:before]:mlb-1';
|
|
248
|
-
var listItem = "contents before:[counter-increment:section]";
|
|
249
|
-
var codeBlock = "mlb-2 font-mono bg-neutral-500/10 p-3 rounded";
|
|
250
|
-
var horizontalRule = "mlb-4 border-neutral-500/50";
|
|
251
|
-
var paragraph = "mlb-1";
|
|
252
|
-
var bold = "font-bold";
|
|
253
|
-
var code = "font-mono bg-neutral-500/10 rounded pli-0.5 plb-0.5 -mlb-0.5";
|
|
254
|
-
var codeWithoutMarks = mx(code, "pli-1.5 mli-0.5");
|
|
255
|
-
var italic = "italic";
|
|
256
|
-
var strikethrough = "line-through";
|
|
257
|
-
var mark = "!font-normal !no-underline !text-inherit opacity-40";
|
|
258
|
-
|
|
259
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
260
|
-
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
261
|
-
var tokens = tailwindConfig({}).theme;
|
|
262
|
-
|
|
263
|
-
// packages/ui/react-ui-editor/src/components/Markdown/markdownTheme.ts
|
|
339
|
+
import get2 from "lodash.get";
|
|
340
|
+
var chalky = "#e5c07b";
|
|
341
|
+
var coral = "#e06c75";
|
|
342
|
+
var cyan = "#56b6c2";
|
|
343
|
+
var invalid = "#ffffff";
|
|
264
344
|
var ivory = "#abb2bf";
|
|
345
|
+
var stone = "#7d8799";
|
|
265
346
|
var malibu = "#61afef";
|
|
347
|
+
var sage = "#98c379";
|
|
348
|
+
var whiskey = "#d19a66";
|
|
349
|
+
var violet = "#c678dd";
|
|
266
350
|
var highlightBackground = "#2c313a";
|
|
267
351
|
var tooltipBackground = "#353a42";
|
|
268
|
-
var
|
|
269
|
-
var monospace = get(tokens, "fontFamily.mono", [
|
|
352
|
+
var monospace = get2(tokens, "fontFamily.mono", [
|
|
270
353
|
"monospace"
|
|
271
354
|
]).join(",");
|
|
272
355
|
var markdownTheme = {
|
|
273
|
-
// TODO(thure):
|
|
356
|
+
// TODO(thure): Consider whether these commented-out rules from one-dark-theme should be integrated.
|
|
274
357
|
// '&': {
|
|
275
358
|
// color: ivory,
|
|
276
359
|
// backgroundColor: background
|
|
@@ -307,63 +390,69 @@ var markdownTheme = {
|
|
|
307
390
|
// border: 'none',
|
|
308
391
|
// color: '#ddd'
|
|
309
392
|
// },
|
|
310
|
-
"
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
},
|
|
314
|
-
".dark & .cm-tooltip .cm-tooltip-arrow:before": {
|
|
315
|
-
borderTopColor: "transparent",
|
|
316
|
-
borderBottomColor: "transparent"
|
|
317
|
-
},
|
|
318
|
-
".dark & .cm-tooltip .cm-tooltip-arrow:after": {
|
|
319
|
-
borderTopColor: tooltipBackground,
|
|
320
|
-
borderBottomColor: tooltipBackground
|
|
321
|
-
},
|
|
322
|
-
".dark & .cm-tooltip-autocomplete": {
|
|
323
|
-
"& > ul > li[aria-selected]": {
|
|
324
|
-
backgroundColor: highlightBackground,
|
|
325
|
-
color: ivory
|
|
326
|
-
}
|
|
393
|
+
"& .cm-tooltip": {
|
|
394
|
+
backgroundColor: "transparent",
|
|
395
|
+
border: "none"
|
|
327
396
|
},
|
|
397
|
+
// '.dark & .cm-tooltip': {
|
|
398
|
+
// border: 'none',
|
|
399
|
+
// backgroundColor: tooltipBackground,
|
|
400
|
+
// },
|
|
401
|
+
// '.dark & .cm-tooltip .cm-tooltip-arrow:before': {
|
|
402
|
+
// borderTopColor: 'transparent',
|
|
403
|
+
// borderBottomColor: 'transparent',
|
|
404
|
+
// },
|
|
405
|
+
// '.dark & .cm-tooltip .cm-tooltip-arrow:after': {
|
|
406
|
+
// borderTopColor: tooltipBackground,
|
|
407
|
+
// borderBottomColor: tooltipBackground,
|
|
408
|
+
// },
|
|
409
|
+
// '.dark & .cm-tooltip-autocomplete': {
|
|
410
|
+
// '& > ul > li[aria-selected]': {
|
|
411
|
+
// backgroundColor: highlightBackground,
|
|
412
|
+
// color: ivory,
|
|
413
|
+
// },
|
|
414
|
+
// },
|
|
328
415
|
"&.cm-focused": {
|
|
329
416
|
outline: "none"
|
|
330
417
|
},
|
|
331
418
|
"& .cm-line": {
|
|
332
419
|
paddingInline: 0,
|
|
420
|
+
lineHeight: 1.6,
|
|
333
421
|
minBlockSize: "1.6em"
|
|
334
422
|
},
|
|
335
423
|
"& .cm-line *": {
|
|
336
424
|
lineHeight: 1.6
|
|
337
425
|
},
|
|
338
426
|
"&.cm-focused .cm-selectionBackground, & .cm-selectionBackground": {
|
|
339
|
-
background:
|
|
427
|
+
background: get2(tokens, "extend.colors.primary.150", "#00ffff")
|
|
340
428
|
},
|
|
341
429
|
".dark & .cm-selectionBackground, .dark &.cm-focused .cm-selectionBackground": {
|
|
342
|
-
background:
|
|
430
|
+
background: get2(tokens, "extend.colors.primary.850", "#00ffff")
|
|
343
431
|
},
|
|
344
432
|
"& .cm-selectionMatch": {
|
|
345
|
-
background:
|
|
433
|
+
background: get2(tokens, "extend.colors.primary.250", "#00ffff") + "44"
|
|
346
434
|
},
|
|
347
435
|
".dark & .cm-selectionMatch": {
|
|
348
|
-
background:
|
|
436
|
+
background: get2(tokens, "extend.colors.primary.600", "#00ffff") + "44"
|
|
349
437
|
},
|
|
350
438
|
"& .cm-content": {
|
|
439
|
+
padding: 0,
|
|
351
440
|
caretColor: "black"
|
|
352
441
|
},
|
|
353
442
|
".dark & .cm-content": {
|
|
354
|
-
caretColor:
|
|
443
|
+
caretColor: "white"
|
|
355
444
|
},
|
|
356
445
|
"& .cm-cursor": {
|
|
357
446
|
borderLeftColor: "black"
|
|
358
447
|
},
|
|
359
448
|
".dark & .cm-cursor": {
|
|
360
|
-
borderLeftColor:
|
|
449
|
+
borderLeftColor: "white"
|
|
361
450
|
},
|
|
362
451
|
".cm-placeholder": {
|
|
363
|
-
fontFamily:
|
|
452
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
364
453
|
},
|
|
365
454
|
"& .cm-scroller": {
|
|
366
|
-
fontFamily:
|
|
455
|
+
fontFamily: get2(tokens, "fontFamily.mono", []).join(","),
|
|
367
456
|
overflow: "visible"
|
|
368
457
|
},
|
|
369
458
|
"& .cm-activeLine": {
|
|
@@ -373,7 +462,7 @@ var markdownTheme = {
|
|
|
373
462
|
backgroundColor: "transparent"
|
|
374
463
|
},
|
|
375
464
|
"& .cm-ySelectionInfo": {
|
|
376
|
-
fontFamily:
|
|
465
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(","),
|
|
377
466
|
padding: "2px 4px",
|
|
378
467
|
marginBlockStart: "-4px"
|
|
379
468
|
},
|
|
@@ -396,8 +485,16 @@ var markdownTheme = {
|
|
|
396
485
|
"& .cm-yLineSelection": {
|
|
397
486
|
margin: "0"
|
|
398
487
|
},
|
|
399
|
-
|
|
400
|
-
|
|
488
|
+
".cm-link": {
|
|
489
|
+
color: "rgb(20 89 208)",
|
|
490
|
+
textDecorationLine: "underline",
|
|
491
|
+
textDecorationThickness: "1px",
|
|
492
|
+
textUnderlineOffset: "2px",
|
|
493
|
+
borderRadius: ".125rem"
|
|
494
|
+
},
|
|
495
|
+
// TODO(burdon): Document.
|
|
496
|
+
...Object.keys(get2(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
|
|
497
|
+
const height = get2(tokens, [
|
|
401
498
|
"extend",
|
|
402
499
|
"fontSize",
|
|
403
500
|
fontSize,
|
|
@@ -416,7 +513,7 @@ var markdownTheme = {
|
|
|
416
513
|
return acc;
|
|
417
514
|
}, {})
|
|
418
515
|
};
|
|
419
|
-
var
|
|
516
|
+
var markdownHighlightStyle = HighlightStyle.define([
|
|
420
517
|
{
|
|
421
518
|
tag: [
|
|
422
519
|
tags.keyword,
|
|
@@ -532,40 +629,341 @@ var markdownDarkHighlighting = HighlightStyle.define([
|
|
|
532
629
|
], {
|
|
533
630
|
scope: markdownLanguage,
|
|
534
631
|
all: {
|
|
535
|
-
fontFamily:
|
|
632
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
536
633
|
}
|
|
537
634
|
});
|
|
538
635
|
|
|
539
|
-
// packages/ui/react-ui-editor/src/components/
|
|
540
|
-
var
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
636
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
637
|
+
var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
638
|
+
return [
|
|
639
|
+
bracketMatching2(),
|
|
640
|
+
closeBrackets2(),
|
|
641
|
+
_placeholder && placeholder2(_placeholder),
|
|
642
|
+
EditorState.allowMultipleSelections.of(true),
|
|
643
|
+
EditorView3.lineWrapping,
|
|
644
|
+
// autocompletion(),
|
|
645
|
+
crosshairCursor(),
|
|
646
|
+
dropCursor(),
|
|
647
|
+
drawSelection(),
|
|
648
|
+
highlightActiveLine(),
|
|
649
|
+
highlightActiveLineGutter(),
|
|
650
|
+
highlightSelectionMatches(),
|
|
651
|
+
highlightSpecialChars(),
|
|
652
|
+
history(),
|
|
653
|
+
indentOnInput(),
|
|
654
|
+
rectangularSelection(),
|
|
655
|
+
keymap.of([
|
|
656
|
+
...closeBracketsKeymap,
|
|
657
|
+
// ...completionKeymap,
|
|
658
|
+
...defaultKeymap,
|
|
659
|
+
...foldKeymap,
|
|
660
|
+
...historyKeymap,
|
|
661
|
+
...lintKeymap,
|
|
662
|
+
...searchKeymap,
|
|
663
|
+
indentWithTab
|
|
664
|
+
]),
|
|
665
|
+
// Main extension.
|
|
666
|
+
// https://github.com/codemirror/lang-markdown
|
|
667
|
+
markdown({
|
|
668
|
+
base: markdownLanguage2,
|
|
669
|
+
codeLanguages: languages,
|
|
670
|
+
extensions: [
|
|
671
|
+
// TODO(burdon): This seems to upgrade the parser.
|
|
672
|
+
// GitHub flavored markdown bundle: Table, TaskList, Strikethrough, and Autolink.
|
|
673
|
+
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
674
|
+
// https://github.github.com/gfm
|
|
675
|
+
// GFM,
|
|
676
|
+
// Custom styling.
|
|
677
|
+
markdownTagsExtension
|
|
678
|
+
]
|
|
679
|
+
}),
|
|
680
|
+
// TODO(thure): All but one rule here apply to both themes; rename or refactor.
|
|
681
|
+
syntaxHighlighting2(markdownHighlightStyle),
|
|
682
|
+
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
|
|
683
|
+
].filter(Boolean);
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
687
|
+
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
688
|
+
import { EditorView as EditorView4 } from "@codemirror/view";
|
|
689
|
+
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
690
|
+
import { vim } from "@replit/codemirror-vim";
|
|
691
|
+
import defaultsDeep from "lodash.defaultsdeep";
|
|
692
|
+
import get3 from "lodash.get";
|
|
693
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
|
|
694
|
+
import { isDocAccessor as isDocAccessor2 } from "@dxos/echo-schema";
|
|
695
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
696
|
+
|
|
697
|
+
// packages/ui/react-ui-editor/src/hooks/useCollaboration.ts
|
|
698
|
+
import { useEffect, useMemo } from "react";
|
|
699
|
+
import { yCollab } from "y-codemirror.next";
|
|
700
|
+
import { generateName } from "@dxos/display-name";
|
|
701
|
+
import { isDocAccessor } from "@dxos/echo-schema";
|
|
702
|
+
import { getColorForValue } from "@dxos/react-ui-theme";
|
|
703
|
+
import { YText } from "@dxos/text-model";
|
|
704
|
+
|
|
705
|
+
// packages/ui/react-ui-editor/src/automerge/automerge-plugin/plugin.ts
|
|
706
|
+
import { Annotation, Facet, StateEffect, StateField as StateField3 } from "@codemirror/state";
|
|
707
|
+
import { ViewPlugin as ViewPlugin2 } from "@codemirror/view";
|
|
708
|
+
import * as automerge2 from "@dxos/automerge/automerge";
|
|
709
|
+
|
|
710
|
+
// packages/ui/react-ui-editor/src/automerge/automerge-plugin/PatchSemaphore.ts
|
|
711
|
+
import { next as automerge } from "@dxos/automerge/automerge";
|
|
712
|
+
|
|
713
|
+
// packages/ui/react-ui-editor/src/automerge/automerge-plugin/amToCodemirror.ts
|
|
714
|
+
import { ChangeSet } from "@codemirror/state";
|
|
715
|
+
var amToCodemirror_default = (view, selection, target, patches) => {
|
|
716
|
+
for (const patch of patches) {
|
|
717
|
+
const changeSpec = handlePatch(patch, target, view.state);
|
|
718
|
+
if (changeSpec != null) {
|
|
719
|
+
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
|
720
|
+
selection = selection.map(changeSet, 1);
|
|
721
|
+
view.dispatch({
|
|
722
|
+
changes: changeSet,
|
|
723
|
+
annotations: reconcileAnnotationType.of({})
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
view.dispatch({
|
|
728
|
+
selection,
|
|
729
|
+
annotations: reconcileAnnotationType.of({})
|
|
549
730
|
});
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
731
|
+
};
|
|
732
|
+
var handlePatch = (patch, target, state) => {
|
|
733
|
+
if (patch.action === "insert") {
|
|
734
|
+
return handleInsert(target, patch);
|
|
735
|
+
} else if (patch.action === "splice") {
|
|
736
|
+
return handleSplice(target, patch);
|
|
737
|
+
} else if (patch.action === "del") {
|
|
738
|
+
return handleDel(target, patch);
|
|
739
|
+
} else if (patch.action === "put") {
|
|
740
|
+
return handlePut(target, patch, state);
|
|
741
|
+
} else {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
var handleInsert = (target, patch) => {
|
|
746
|
+
const index = charPath(target, patch.path);
|
|
747
|
+
if (index == null) {
|
|
748
|
+
return [];
|
|
749
|
+
}
|
|
750
|
+
const text = patch.values.map((v) => v ? v.toString() : "").join("");
|
|
751
|
+
return [
|
|
752
|
+
{
|
|
753
|
+
from: index,
|
|
754
|
+
to: index,
|
|
755
|
+
insert: text
|
|
565
756
|
}
|
|
566
|
-
|
|
567
|
-
|
|
757
|
+
];
|
|
758
|
+
};
|
|
759
|
+
var handleSplice = (target, patch) => {
|
|
760
|
+
const index = charPath(target, patch.path);
|
|
761
|
+
if (index == null) {
|
|
762
|
+
return [];
|
|
763
|
+
}
|
|
764
|
+
return [
|
|
765
|
+
{
|
|
766
|
+
from: index,
|
|
767
|
+
insert: patch.value
|
|
768
|
+
}
|
|
769
|
+
];
|
|
770
|
+
};
|
|
771
|
+
var handleDel = (target, patch) => {
|
|
772
|
+
const index = charPath(target, patch.path);
|
|
773
|
+
if (index == null) {
|
|
774
|
+
return [];
|
|
775
|
+
}
|
|
776
|
+
const length = patch.length || 1;
|
|
777
|
+
return [
|
|
778
|
+
{
|
|
779
|
+
from: index,
|
|
780
|
+
to: index + length
|
|
781
|
+
}
|
|
782
|
+
];
|
|
783
|
+
};
|
|
784
|
+
var handlePut = (target, patch, state) => {
|
|
785
|
+
const index = charPath(target, [
|
|
786
|
+
...patch.path,
|
|
787
|
+
0
|
|
568
788
|
]);
|
|
789
|
+
if (index == null) {
|
|
790
|
+
return [];
|
|
791
|
+
}
|
|
792
|
+
const length = state.doc.length;
|
|
793
|
+
if (typeof patch.value !== "string") {
|
|
794
|
+
return [];
|
|
795
|
+
}
|
|
796
|
+
return [
|
|
797
|
+
{
|
|
798
|
+
from: 0,
|
|
799
|
+
to: length,
|
|
800
|
+
insert: patch.value
|
|
801
|
+
}
|
|
802
|
+
];
|
|
803
|
+
};
|
|
804
|
+
var charPath = (textPath, candidatePath) => {
|
|
805
|
+
if (candidatePath.length !== textPath.length + 1) {
|
|
806
|
+
return null;
|
|
807
|
+
}
|
|
808
|
+
for (let i = 0; i < textPath.length; i++) {
|
|
809
|
+
if (textPath[i] !== candidatePath[i]) {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
const index = candidatePath[candidatePath.length - 1];
|
|
814
|
+
if (typeof index === "number") {
|
|
815
|
+
return index;
|
|
816
|
+
}
|
|
817
|
+
return null;
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
// packages/ui/react-ui-editor/src/automerge/automerge-plugin/codeMirrorToAm.ts
|
|
821
|
+
import { next as am } from "@dxos/automerge/automerge";
|
|
822
|
+
var codeMirrorToAm_default = (field, handle, transactions, state) => {
|
|
823
|
+
const { lastHeads, path } = state.field(field);
|
|
824
|
+
let hasChanges = false;
|
|
825
|
+
for (const tr of transactions) {
|
|
826
|
+
tr.changes.iterChanges(() => {
|
|
827
|
+
hasChanges = true;
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
if (!hasChanges) {
|
|
831
|
+
return void 0;
|
|
832
|
+
}
|
|
833
|
+
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
834
|
+
for (const tr of transactions) {
|
|
835
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
836
|
+
am.splice(doc, path, fromA, toA - fromA, inserted.toString());
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
return newHeads ?? void 0;
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
// packages/ui/react-ui-editor/src/automerge/automerge-plugin/PatchSemaphore.ts
|
|
844
|
+
var PatchSemaphore = class {
|
|
845
|
+
constructor(field) {
|
|
846
|
+
this._inReconcile = false;
|
|
847
|
+
this._queue = [];
|
|
848
|
+
this.reconcile = (handle, view) => {
|
|
849
|
+
if (this._inReconcile) {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
this._inReconcile = true;
|
|
853
|
+
const path = getPath(view.state, this._field);
|
|
854
|
+
const oldHeads = getLastHeads(view.state, this._field);
|
|
855
|
+
let selection = view.state.selection;
|
|
856
|
+
const transactions = view.state.field(this._field).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
857
|
+
const toInvert = transactions.slice().reverse();
|
|
858
|
+
for (const tx of toInvert) {
|
|
859
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
860
|
+
selection = selection.map(inverted);
|
|
861
|
+
view.dispatch({
|
|
862
|
+
changes: inverted,
|
|
863
|
+
annotations: reconcileAnnotationType.of(true)
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
let newHeads = codeMirrorToAm_default(this._field, handle, transactions, view.state);
|
|
867
|
+
if (newHeads === null || newHeads === void 0) {
|
|
868
|
+
newHeads = automerge.getHeads(handle.docSync());
|
|
869
|
+
}
|
|
870
|
+
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
871
|
+
amToCodemirror_default(view, selection, path, diff);
|
|
872
|
+
view.dispatch({
|
|
873
|
+
effects: updateHeads(newHeads),
|
|
874
|
+
annotations: reconcileAnnotationType.of({})
|
|
875
|
+
});
|
|
876
|
+
this._inReconcile = false;
|
|
877
|
+
};
|
|
878
|
+
if (field !== void 0) {
|
|
879
|
+
this._field = field;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
// packages/ui/react-ui-editor/src/automerge/automerge-plugin/plugin.ts
|
|
885
|
+
var effectType = StateEffect.define({});
|
|
886
|
+
var updateHeads = (newHeads) => effectType.of({
|
|
887
|
+
newHeads
|
|
888
|
+
});
|
|
889
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
890
|
+
var getPath = (state, field) => state.field(field).path;
|
|
891
|
+
var semaphoreFacet = Facet.define({
|
|
892
|
+
combine: (values) => values.at(-1)
|
|
893
|
+
});
|
|
894
|
+
var automergePlugin = (handle, path) => {
|
|
895
|
+
const stateField = StateField3.define({
|
|
896
|
+
create: () => ({
|
|
897
|
+
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
898
|
+
unreconciledTransactions: [],
|
|
899
|
+
path: path.slice()
|
|
900
|
+
}),
|
|
901
|
+
update: (value, tr) => {
|
|
902
|
+
const result = {
|
|
903
|
+
lastHeads: value.lastHeads,
|
|
904
|
+
unreconciledTransactions: value.unreconciledTransactions.slice(),
|
|
905
|
+
path: path.slice()
|
|
906
|
+
};
|
|
907
|
+
let clearUnreconciled = false;
|
|
908
|
+
for (const effect of tr.effects) {
|
|
909
|
+
if (effect.is(effectType)) {
|
|
910
|
+
result.lastHeads = effect.value.newHeads;
|
|
911
|
+
clearUnreconciled = true;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
if (clearUnreconciled) {
|
|
915
|
+
result.unreconciledTransactions = [];
|
|
916
|
+
} else {
|
|
917
|
+
if (!isReconcileTx(tr)) {
|
|
918
|
+
result.unreconciledTransactions.push(tr);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return result;
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
const semaphore = new PatchSemaphore(stateField);
|
|
925
|
+
const viewPlugin = ViewPlugin2.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
926
|
+
constructor(view) {
|
|
927
|
+
this._handleChange = () => {
|
|
928
|
+
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
929
|
+
};
|
|
930
|
+
this._view = view;
|
|
931
|
+
handle.addListener("change", this._handleChange);
|
|
932
|
+
}
|
|
933
|
+
update(update2) {
|
|
934
|
+
if (update2.transactions.length > 0 && update2.transactions.some((t) => !isReconcileTx(t))) {
|
|
935
|
+
queueMicrotask(() => {
|
|
936
|
+
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
destroy() {
|
|
941
|
+
handle.addListener("change", this._handleChange);
|
|
942
|
+
}
|
|
943
|
+
});
|
|
944
|
+
return {
|
|
945
|
+
extension: [
|
|
946
|
+
stateField,
|
|
947
|
+
semaphoreFacet.of(semaphore),
|
|
948
|
+
viewPlugin
|
|
949
|
+
]
|
|
950
|
+
};
|
|
951
|
+
};
|
|
952
|
+
var reconcileAnnotationType = Annotation.define();
|
|
953
|
+
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
954
|
+
|
|
955
|
+
// packages/ui/react-ui-editor/src/hooks/useCollaboration.ts
|
|
956
|
+
var useCollaboration = (model, themeMode) => {
|
|
957
|
+
const { provider, peer, content } = model;
|
|
958
|
+
const extension = useMemo(() => {
|
|
959
|
+
if (content instanceof YText) {
|
|
960
|
+
return yCollab(content, provider?.awareness);
|
|
961
|
+
} else if (isDocAccessor(content)) {
|
|
962
|
+
return automergePlugin(content.handle, content.path);
|
|
963
|
+
} else {
|
|
964
|
+
return void 0;
|
|
965
|
+
}
|
|
966
|
+
}, []);
|
|
569
967
|
useEffect(() => {
|
|
570
968
|
if (provider && peer) {
|
|
571
969
|
provider.awareness.setLocalStateField("user", {
|
|
@@ -586,76 +984,253 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ model, slots = {}, editorMode
|
|
|
586
984
|
peer,
|
|
587
985
|
themeMode
|
|
588
986
|
]);
|
|
589
|
-
|
|
987
|
+
return extension;
|
|
988
|
+
};
|
|
989
|
+
|
|
990
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
991
|
+
import { useMemo as useMemo2 } from "react";
|
|
992
|
+
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
993
|
+
|
|
994
|
+
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
995
|
+
import * as random from "lib0/random";
|
|
996
|
+
var cursorColors = [
|
|
997
|
+
{
|
|
998
|
+
color: "#30bced",
|
|
999
|
+
light: "#30bced33"
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
color: "#6eeb83",
|
|
1003
|
+
light: "#6eeb8333"
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
color: "#ffbc42",
|
|
1007
|
+
light: "#ffbc4233"
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
color: "#ecd444",
|
|
1011
|
+
light: "#ecd44433"
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
color: "#ee6352",
|
|
1015
|
+
light: "#ee635233"
|
|
1016
|
+
},
|
|
1017
|
+
{
|
|
1018
|
+
color: "#9ac2c9",
|
|
1019
|
+
light: "#9ac2c933"
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
color: "#8acb88",
|
|
1023
|
+
light: "#8acb8833"
|
|
1024
|
+
},
|
|
1025
|
+
{
|
|
1026
|
+
color: "#1be7ff",
|
|
1027
|
+
light: "#1be7ff33"
|
|
1028
|
+
}
|
|
1029
|
+
];
|
|
1030
|
+
var cursorColor = cursorColors[random.uint32() % cursorColors.length];
|
|
1031
|
+
|
|
1032
|
+
// packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
|
|
1033
|
+
import * as decoding from "lib0/decoding";
|
|
1034
|
+
import * as encoding from "lib0/encoding";
|
|
1035
|
+
import { Observable } from "lib0/observable";
|
|
1036
|
+
import * as awarenessProtocol from "y-protocols/awareness";
|
|
1037
|
+
import { log } from "@dxos/log";
|
|
1038
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
1039
|
+
var messageAwareness = 1;
|
|
1040
|
+
var messageQueryAwareness = 3;
|
|
1041
|
+
var SpaceAwarenessProvider = class extends Observable {
|
|
1042
|
+
constructor({ space, doc, channel, awareness }) {
|
|
1043
|
+
super();
|
|
1044
|
+
this._space = space;
|
|
1045
|
+
this._awareness = awareness ?? new awarenessProtocol.Awareness(doc);
|
|
1046
|
+
this._channel = channel;
|
|
1047
|
+
this._clientId = doc.clientID;
|
|
1048
|
+
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
1049
|
+
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
1050
|
+
if (typeof window !== "undefined") {
|
|
1051
|
+
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
1052
|
+
} else if (typeof process !== "undefined") {
|
|
1053
|
+
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
1054
|
+
}
|
|
1055
|
+
const encoderAwarenessQuery = encoding.createEncoder();
|
|
1056
|
+
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
1057
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
1058
|
+
const encoderAwarenessState = encoding.createEncoder();
|
|
1059
|
+
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
1060
|
+
encoding.writeVarUint8Array(encoderAwarenessState, awarenessProtocol.encodeAwarenessUpdate(this.awareness, [
|
|
1061
|
+
this._clientId
|
|
1062
|
+
]));
|
|
1063
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
1064
|
+
}
|
|
1065
|
+
get awareness() {
|
|
1066
|
+
return this._awareness;
|
|
1067
|
+
}
|
|
1068
|
+
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
1069
|
+
log("awareness update", {
|
|
1070
|
+
added,
|
|
1071
|
+
updated,
|
|
1072
|
+
removed,
|
|
1073
|
+
origin
|
|
1074
|
+
}, {
|
|
1075
|
+
F: __dxlog_file,
|
|
1076
|
+
L: 67,
|
|
1077
|
+
S: this,
|
|
1078
|
+
C: (f, a) => f(...a)
|
|
1079
|
+
});
|
|
1080
|
+
const changedClients = added.concat(updated).concat(removed);
|
|
1081
|
+
const encoderAwareness = encoding.createEncoder();
|
|
1082
|
+
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
1083
|
+
encoding.writeVarUint8Array(encoderAwareness, awarenessProtocol.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
1084
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
1085
|
+
}
|
|
1086
|
+
_handleSpaceMessage({ payload }) {
|
|
1087
|
+
log("space message", payload, {
|
|
1088
|
+
F: __dxlog_file,
|
|
1089
|
+
L: 79,
|
|
1090
|
+
S: this,
|
|
1091
|
+
C: (f, a) => f(...a)
|
|
1092
|
+
});
|
|
1093
|
+
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
1094
|
+
const encoder = this._readMessage(data);
|
|
1095
|
+
if (encoder) {
|
|
1096
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
_readMessage(message) {
|
|
1100
|
+
const decoder = decoding.createDecoder(message);
|
|
1101
|
+
const encoder = encoding.createEncoder();
|
|
1102
|
+
const messageType = decoding.readVarUint(decoder);
|
|
1103
|
+
let sendReply = false;
|
|
1104
|
+
switch (messageType) {
|
|
1105
|
+
case messageAwareness: {
|
|
1106
|
+
awarenessProtocol.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1109
|
+
case messageQueryAwareness: {
|
|
1110
|
+
encoding.writeVarUint(encoder, messageAwareness);
|
|
1111
|
+
encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
1112
|
+
sendReply = true;
|
|
1113
|
+
break;
|
|
1114
|
+
}
|
|
1115
|
+
default: {
|
|
1116
|
+
console.error("Invalid message:", messageType);
|
|
1117
|
+
return encoder;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
if (!sendReply) {
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
return encoder;
|
|
1124
|
+
}
|
|
1125
|
+
_handleBeforeUnload() {
|
|
1126
|
+
awarenessProtocol.removeAwarenessStates(this._awareness, [
|
|
1127
|
+
this._clientId
|
|
1128
|
+
], "window unload");
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
|
|
1132
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1133
|
+
var useTextModel = ({ identity, space, text }) => {
|
|
1134
|
+
const provider = useMemo2(() => {
|
|
1135
|
+
if (isActualAutomergeObject(text)) {
|
|
1136
|
+
return void 0;
|
|
1137
|
+
}
|
|
1138
|
+
if (!space || !text?.doc) {
|
|
1139
|
+
return void 0;
|
|
1140
|
+
}
|
|
1141
|
+
return new SpaceAwarenessProvider({
|
|
1142
|
+
space,
|
|
1143
|
+
doc: text.doc,
|
|
1144
|
+
channel: `yjs.awareness.${text.id}`
|
|
1145
|
+
});
|
|
1146
|
+
}, [
|
|
1147
|
+
identity,
|
|
1148
|
+
space,
|
|
1149
|
+
text,
|
|
1150
|
+
text?.doc
|
|
1151
|
+
]);
|
|
1152
|
+
const content = useMemo2(() => {
|
|
1153
|
+
if (isActualAutomergeObject(text)) {
|
|
1154
|
+
const obj = text;
|
|
1155
|
+
return getRawDoc(obj, [
|
|
1156
|
+
obj.field
|
|
1157
|
+
]);
|
|
1158
|
+
} else {
|
|
1159
|
+
return text?.content;
|
|
1160
|
+
}
|
|
1161
|
+
}, [
|
|
1162
|
+
text
|
|
1163
|
+
]);
|
|
1164
|
+
if (isActualAutomergeObject(text)) {
|
|
1165
|
+
const obj = text;
|
|
1166
|
+
return {
|
|
1167
|
+
id: obj.id,
|
|
1168
|
+
content,
|
|
1169
|
+
provider: void 0,
|
|
1170
|
+
peer: identity ? {
|
|
1171
|
+
id: identity.identityKey.toHex(),
|
|
1172
|
+
name: identity.profile?.displayName
|
|
1173
|
+
} : void 0
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
if (!text?.doc || !text?.content) {
|
|
1177
|
+
return void 0;
|
|
1178
|
+
}
|
|
1179
|
+
return {
|
|
1180
|
+
id: text.doc.guid,
|
|
1181
|
+
content: text.content,
|
|
1182
|
+
provider,
|
|
1183
|
+
peer: identity ? {
|
|
1184
|
+
id: identity.identityKey.toHex(),
|
|
1185
|
+
name: identity.profile?.displayName
|
|
1186
|
+
} : void 0
|
|
1187
|
+
};
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
1191
|
+
var EditorModes = [
|
|
1192
|
+
"default",
|
|
1193
|
+
"vim"
|
|
1194
|
+
];
|
|
1195
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots, editorMode }, forwardedRef) => {
|
|
1196
|
+
const { themeMode } = useThemeContext();
|
|
1197
|
+
const tabsterDOMAttribute = useFocusableGroup({
|
|
1198
|
+
tabBehavior: "limited"
|
|
1199
|
+
});
|
|
1200
|
+
const [parent, setParent] = useState(null);
|
|
1201
|
+
const [state, setState] = useState();
|
|
1202
|
+
const [view, setView] = useState();
|
|
1203
|
+
useImperativeHandle(forwardedRef, () => ({
|
|
1204
|
+
editor: parent,
|
|
1205
|
+
state,
|
|
1206
|
+
view
|
|
1207
|
+
}), [
|
|
1208
|
+
view,
|
|
1209
|
+
state,
|
|
1210
|
+
parent
|
|
1211
|
+
]);
|
|
1212
|
+
const collaboration = useCollaboration(model, themeMode);
|
|
1213
|
+
useEffect2(() => {
|
|
590
1214
|
if (!parent) {
|
|
591
1215
|
return;
|
|
592
1216
|
}
|
|
593
|
-
const
|
|
594
|
-
|
|
1217
|
+
const initialText = isDocAccessor2(model.content) ? get3(model.content.handle.docSync(), model.content.path) : model.content?.toString();
|
|
1218
|
+
const state2 = EditorState2.create({
|
|
1219
|
+
doc: initialText,
|
|
595
1220
|
extensions: [
|
|
596
|
-
//
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
drawSelection(),
|
|
606
|
-
dropCursor(),
|
|
607
|
-
EditorState.allowMultipleSelections.of(true),
|
|
608
|
-
indentOnInput(),
|
|
609
|
-
syntaxHighlighting(defaultHighlightStyle, {
|
|
610
|
-
fallback: true
|
|
611
|
-
}),
|
|
612
|
-
bracketMatching(),
|
|
613
|
-
closeBrackets(),
|
|
614
|
-
autocompletion(),
|
|
615
|
-
rectangularSelection(),
|
|
616
|
-
crosshairCursor(),
|
|
617
|
-
highlightActiveLine(),
|
|
618
|
-
highlightSelectionMatches(),
|
|
619
|
-
placeholder(slots.editor?.placeholder ?? ""),
|
|
620
|
-
keymap.of([
|
|
621
|
-
...closeBracketsKeymap,
|
|
622
|
-
...defaultKeymap,
|
|
623
|
-
...searchKeymap,
|
|
624
|
-
...historyKeymap,
|
|
625
|
-
...foldKeymap,
|
|
626
|
-
...completionKeymap,
|
|
627
|
-
...lintKeymap,
|
|
628
|
-
indentWithTab
|
|
629
|
-
]),
|
|
630
|
-
EditorView.lineWrapping,
|
|
631
|
-
// Themes.
|
|
632
|
-
markdown({
|
|
633
|
-
base: markdownLanguage2,
|
|
634
|
-
codeLanguages: languages,
|
|
635
|
-
extensions: [
|
|
636
|
-
markdownTagsExtension
|
|
637
|
-
]
|
|
638
|
-
}),
|
|
639
|
-
EditorView.theme({
|
|
640
|
-
...markdownTheme,
|
|
641
|
-
...slots.editor?.markdownTheme
|
|
642
|
-
}),
|
|
643
|
-
...themeMode === "dark" ? [
|
|
644
|
-
syntaxHighlighting(oneDarkHighlightStyle)
|
|
645
|
-
] : [
|
|
646
|
-
syntaxHighlighting(defaultHighlightStyle)
|
|
647
|
-
],
|
|
648
|
-
// TODO(thure): All but one rule here apply to both themes; rename or refactor.
|
|
649
|
-
syntaxHighlighting(markdownDarkHighlighting),
|
|
650
|
-
// Replication and awareness (incl. remote selection).
|
|
651
|
-
...content instanceof YText ? [
|
|
652
|
-
yCollab(content, provider?.awareness)
|
|
653
|
-
] : []
|
|
654
|
-
]
|
|
1221
|
+
// TODO(burdon): Factor out VIM mode?
|
|
1222
|
+
editorMode === "vim" && vim(),
|
|
1223
|
+
// Replication.
|
|
1224
|
+
collaboration,
|
|
1225
|
+
// Theme.
|
|
1226
|
+
slots?.editor?.theme && EditorView4.theme(slots?.editor?.theme),
|
|
1227
|
+
// Custom.
|
|
1228
|
+
...extensions
|
|
1229
|
+
].filter(Boolean)
|
|
655
1230
|
});
|
|
656
1231
|
setState(state2);
|
|
657
1232
|
view?.destroy();
|
|
658
|
-
setView(new
|
|
1233
|
+
setView(new EditorView4({
|
|
659
1234
|
state: state2,
|
|
660
1235
|
parent
|
|
661
1236
|
}));
|
|
@@ -666,8 +1241,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ model, slots = {}, editorMode
|
|
|
666
1241
|
};
|
|
667
1242
|
}, [
|
|
668
1243
|
parent,
|
|
669
|
-
content,
|
|
670
|
-
provider?.awareness,
|
|
1244
|
+
model.content,
|
|
671
1245
|
themeMode,
|
|
672
1246
|
editorMode
|
|
673
1247
|
]);
|
|
@@ -688,309 +1262,89 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ model, slots = {}, editorMode
|
|
|
688
1262
|
editorMode
|
|
689
1263
|
]);
|
|
690
1264
|
return /* @__PURE__ */ React.createElement("div", {
|
|
691
|
-
|
|
1265
|
+
key: model.id,
|
|
692
1266
|
ref: setParent,
|
|
693
|
-
|
|
694
|
-
...slots
|
|
695
|
-
...editorMode !== "vim"
|
|
1267
|
+
tabIndex: 0,
|
|
1268
|
+
...slots?.root,
|
|
1269
|
+
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
696
1270
|
onKeyUp: handleKeyUp
|
|
697
1271
|
});
|
|
698
1272
|
});
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
import Placeholder from "@tiptap/extension-placeholder";
|
|
707
|
-
import { EditorContent, useEditor as useNaturalEditor } from "@tiptap/react";
|
|
708
|
-
import StarterKit from "@tiptap/starter-kit";
|
|
709
|
-
import React2, { forwardRef as forwardRef2, useImperativeHandle as useImperativeHandle2, useMemo as useMemo3 } from "react";
|
|
710
|
-
import { generateName as generateName2 } from "@dxos/display-name";
|
|
711
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
712
|
-
var useEditor = ({ model, placeholder: placeholder3 = "Enter text\u2026", slots = {} }) => {
|
|
713
|
-
const extensions = useMemo3(() => [
|
|
714
|
-
StarterKit.configure({
|
|
715
|
-
// Extensions
|
|
716
|
-
history: false,
|
|
717
|
-
// Nodes
|
|
718
|
-
blockquote: {
|
|
719
|
-
HTMLAttributes: {
|
|
720
|
-
class: blockquote
|
|
721
|
-
}
|
|
722
|
-
},
|
|
723
|
-
bulletList: {
|
|
724
|
-
HTMLAttributes: {
|
|
725
|
-
class: unorderedList
|
|
726
|
-
}
|
|
727
|
-
},
|
|
728
|
-
codeBlock: {
|
|
729
|
-
HTMLAttributes: {
|
|
730
|
-
class: codeBlock
|
|
731
|
-
}
|
|
732
|
-
},
|
|
733
|
-
heading: false,
|
|
734
|
-
horizontalRule: {
|
|
735
|
-
HTMLAttributes: {
|
|
736
|
-
class: horizontalRule
|
|
737
|
-
}
|
|
738
|
-
},
|
|
739
|
-
listItem: false,
|
|
740
|
-
orderedList: {
|
|
741
|
-
HTMLAttributes: {
|
|
742
|
-
class: orderedList
|
|
743
|
-
}
|
|
744
|
-
},
|
|
745
|
-
paragraph: {
|
|
746
|
-
HTMLAttributes: {
|
|
747
|
-
class: paragraph
|
|
748
|
-
}
|
|
749
|
-
},
|
|
750
|
-
// Marks
|
|
751
|
-
bold: {
|
|
752
|
-
HTMLAttributes: {
|
|
753
|
-
class: bold
|
|
754
|
-
}
|
|
755
|
-
},
|
|
756
|
-
code: {
|
|
757
|
-
HTMLAttributes: {
|
|
758
|
-
class: codeWithoutMarks
|
|
759
|
-
}
|
|
760
|
-
},
|
|
761
|
-
italic: {
|
|
762
|
-
HTMLAttributes: {
|
|
763
|
-
class: italic
|
|
764
|
-
}
|
|
765
|
-
},
|
|
766
|
-
strike: {
|
|
767
|
-
HTMLAttributes: {
|
|
768
|
-
class: strikethrough
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
}),
|
|
772
|
-
Heading.extend({
|
|
773
|
-
renderHTML({ node, HTMLAttributes }) {
|
|
774
|
-
const hasLevel = this.options.levels.includes(node.attrs.level);
|
|
775
|
-
const level = hasLevel ? node.attrs.level : this.options.levels[0];
|
|
776
|
-
return [
|
|
777
|
-
`h${level}`,
|
|
778
|
-
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
|
|
779
|
-
class: heading[level]
|
|
780
|
-
}),
|
|
781
|
-
0
|
|
782
|
-
];
|
|
783
|
-
}
|
|
784
|
-
}),
|
|
785
|
-
ListItem.extend({
|
|
786
|
-
renderHTML: ({ HTMLAttributes }) => [
|
|
787
|
-
"li",
|
|
788
|
-
mergeAttributes(HTMLAttributes, {
|
|
789
|
-
marker: "\u2022 ",
|
|
790
|
-
class: listItem
|
|
791
|
-
}),
|
|
792
|
-
[
|
|
793
|
-
"div",
|
|
794
|
-
{
|
|
795
|
-
role: "none"
|
|
796
|
-
},
|
|
797
|
-
0
|
|
798
|
-
]
|
|
799
|
-
]
|
|
800
|
-
}),
|
|
801
|
-
// https://github.com/ueberdosis/tiptap/tree/main/packages/extension-collaboration
|
|
802
|
-
...model && typeof model.content !== "string" ? [
|
|
803
|
-
Collaboration.configure({
|
|
804
|
-
fragment: model.content
|
|
805
|
-
})
|
|
806
|
-
] : [],
|
|
807
|
-
...model?.provider ? [
|
|
808
|
-
CollaborationCursor.configure({
|
|
809
|
-
provider: model.provider,
|
|
810
|
-
user: model.peer && {
|
|
811
|
-
name: model.peer.name ?? generateName2(model.peer.id),
|
|
812
|
-
color: cursorColor.color
|
|
813
|
-
}
|
|
814
|
-
})
|
|
815
|
-
] : [],
|
|
816
|
-
Placeholder.configure({
|
|
817
|
-
placeholder: placeholder3,
|
|
818
|
-
emptyEditorClass: "before:content-[attr(data-placeholder)] before:absolute opacity-50 cursor-text"
|
|
1273
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ extensions: _extensions, slots, ...props }, forwardedRef) => {
|
|
1274
|
+
const { themeMode } = useThemeContext();
|
|
1275
|
+
const extensions = [
|
|
1276
|
+
..._extensions ?? [],
|
|
1277
|
+
basicBundle({
|
|
1278
|
+
themeMode,
|
|
1279
|
+
placeholder: slots?.editor?.placeholder
|
|
819
1280
|
})
|
|
820
|
-
]
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
return useNaturalEditor({
|
|
1281
|
+
];
|
|
1282
|
+
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
1283
|
+
ref: forwardedRef,
|
|
824
1284
|
extensions,
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
spellcheck: slots.editor?.spellCheck === false ? "false" : "true",
|
|
829
|
-
tabindex: slots.editor?.tabIndex ? String(slots.editor?.tabIndex) : "0"
|
|
1285
|
+
slots: defaultsDeep({}, slots, {
|
|
1286
|
+
editor: {
|
|
1287
|
+
theme: basicTheme
|
|
830
1288
|
}
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
extensions
|
|
834
|
-
]);
|
|
835
|
-
};
|
|
836
|
-
var RichTextEditor = /* @__PURE__ */ forwardRef2((props, ref) => {
|
|
837
|
-
const editor = useEditor(props);
|
|
838
|
-
useImperativeHandle2(ref, () => editor, [
|
|
839
|
-
editor
|
|
840
|
-
]);
|
|
841
|
-
return /* @__PURE__ */ React2.createElement(EditorContent, {
|
|
842
|
-
...props.slots?.root,
|
|
843
|
-
editor
|
|
1289
|
+
}),
|
|
1290
|
+
...props
|
|
844
1291
|
});
|
|
845
1292
|
});
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
})
|
|
862
|
-
}
|
|
863
|
-
}));
|
|
864
|
-
|
|
865
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
866
|
-
import { tags as tags2 } from "@lezer/highlight";
|
|
867
|
-
|
|
868
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
869
|
-
import { closeBrackets as closeBrackets2 } from "@codemirror/autocomplete";
|
|
870
|
-
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
871
|
-
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
872
|
-
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
873
|
-
import { EditorView as EditorView2, placeholder as placeholder2 } from "@codemirror/view";
|
|
874
|
-
import React4, { forwardRef as forwardRef4, useEffect as useEffect2, useImperativeHandle as useImperativeHandle3, useState as useState2, useCallback as useCallback2 } from "react";
|
|
875
|
-
import { yCollab as yCollab2 } from "y-codemirror.next";
|
|
876
|
-
import { useThemeContext as useThemeContext2 } from "@dxos/react-ui";
|
|
877
|
-
import { YText as YText2 } from "@dxos/text-model";
|
|
878
|
-
|
|
879
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/theme.ts
|
|
880
|
-
import get2 from "lodash.get";
|
|
881
|
-
import { tailwindConfig as tailwindConfig2 } from "@dxos/react-ui-theme";
|
|
882
|
-
var tokens2 = tailwindConfig2({}).theme;
|
|
883
|
-
var defaultStyles = {
|
|
884
|
-
"&.cm-focused": {
|
|
885
|
-
outline: "none"
|
|
886
|
-
},
|
|
887
|
-
".cm-placeholder": {
|
|
888
|
-
fontFamily: get2(tokens2, "fontFamily.body", []).join(",")
|
|
889
|
-
},
|
|
890
|
-
"& .cm-scroller": {
|
|
891
|
-
fontFamily: get2(tokens2, "fontFamily.body", []).join(","),
|
|
892
|
-
overflow: "visible"
|
|
893
|
-
}
|
|
894
|
-
};
|
|
895
|
-
|
|
896
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
897
|
-
var TextEditor = /* @__PURE__ */ forwardRef4(({ model, extensions = [], theme = defaultStyles, slots = {}, onKeyDown, ...props }, forwardedRef) => {
|
|
898
|
-
const { id, content } = model ?? {};
|
|
899
|
-
const { themeMode } = useThemeContext2();
|
|
900
|
-
const [parent, setParent] = useState2(null);
|
|
901
|
-
const [state, setState] = useState2();
|
|
902
|
-
const [view, setView] = useState2();
|
|
903
|
-
useImperativeHandle3(forwardedRef, () => {
|
|
904
|
-
return {
|
|
905
|
-
editor: parent,
|
|
906
|
-
state,
|
|
907
|
-
view
|
|
908
|
-
};
|
|
909
|
-
}, [
|
|
910
|
-
view
|
|
911
|
-
]);
|
|
912
|
-
useEffect2(() => {
|
|
913
|
-
if (!parent) {
|
|
914
|
-
return;
|
|
915
|
-
}
|
|
916
|
-
view?.destroy();
|
|
917
|
-
const state2 = EditorState2.create({
|
|
918
|
-
doc: content?.toString(),
|
|
919
|
-
extensions: [
|
|
920
|
-
bracketMatching2(),
|
|
921
|
-
closeBrackets2(),
|
|
922
|
-
placeholder2(slots.editor?.placeholder ?? ""),
|
|
923
|
-
EditorView2.lineWrapping,
|
|
924
|
-
// Themes.
|
|
925
|
-
EditorView2.theme(theme),
|
|
926
|
-
...themeMode === "dark" ? [
|
|
927
|
-
syntaxHighlighting2(oneDarkHighlightStyle2)
|
|
928
|
-
] : [
|
|
929
|
-
syntaxHighlighting2(defaultHighlightStyle2)
|
|
930
|
-
],
|
|
931
|
-
// Replication.
|
|
932
|
-
...content instanceof YText2 ? [
|
|
933
|
-
yCollab2(content, void 0)
|
|
934
|
-
] : [],
|
|
935
|
-
// Custom.
|
|
936
|
-
...extensions
|
|
937
|
-
]
|
|
938
|
-
});
|
|
939
|
-
setState(state2);
|
|
940
|
-
setView(new EditorView2({
|
|
941
|
-
state: state2,
|
|
942
|
-
parent
|
|
943
|
-
}));
|
|
944
|
-
return () => {
|
|
945
|
-
view?.destroy();
|
|
946
|
-
setView(void 0);
|
|
947
|
-
setState(void 0);
|
|
948
|
-
};
|
|
949
|
-
}, [
|
|
950
|
-
parent,
|
|
951
|
-
content,
|
|
952
|
-
themeMode
|
|
953
|
-
]);
|
|
954
|
-
const handleKeyDown = useCallback2((event) => {
|
|
955
|
-
if (view) {
|
|
956
|
-
const { head, from, to } = view.state.selection.ranges[0];
|
|
957
|
-
const { number } = view.state.doc.lineAt(head);
|
|
958
|
-
const after = view.state.sliceDoc(from);
|
|
959
|
-
onKeyDown?.(event, {
|
|
960
|
-
from,
|
|
961
|
-
to,
|
|
962
|
-
line: number,
|
|
963
|
-
lines: view.state.doc.lines,
|
|
964
|
-
after
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
}, [
|
|
968
|
-
view
|
|
969
|
-
]);
|
|
970
|
-
return /* @__PURE__ */ React4.createElement("div", {
|
|
971
|
-
key: id,
|
|
972
|
-
ref: setParent,
|
|
973
|
-
...slots.root,
|
|
974
|
-
onKeyDown: handleKeyDown,
|
|
1293
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions: _extensions, slots, ...props }, forwardedRef) => {
|
|
1294
|
+
const { themeMode } = useThemeContext();
|
|
1295
|
+
const extensions = [
|
|
1296
|
+
..._extensions ?? [],
|
|
1297
|
+
markdownBundle({
|
|
1298
|
+
themeMode
|
|
1299
|
+
})
|
|
1300
|
+
];
|
|
1301
|
+
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
1302
|
+
ref: forwardedRef,
|
|
1303
|
+
extensions,
|
|
1304
|
+
slots: defaultsDeep({}, slots, {
|
|
1305
|
+
editor: {
|
|
1306
|
+
theme: markdownTheme
|
|
1307
|
+
}
|
|
1308
|
+
}),
|
|
975
1309
|
...props
|
|
976
1310
|
});
|
|
977
1311
|
});
|
|
978
|
-
|
|
979
|
-
// packages/ui/react-ui-editor/src/index.ts
|
|
980
|
-
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
981
|
-
import { Doc, YText as YText3, YXmlFragment as YXmlFragment2 } from "@dxos/text-model";
|
|
982
1312
|
export {
|
|
1313
|
+
BaseTextEditor,
|
|
983
1314
|
Doc,
|
|
984
|
-
Editor,
|
|
985
1315
|
EditorModes,
|
|
986
1316
|
MarkdownEditor,
|
|
987
|
-
|
|
1317
|
+
SpaceAwarenessProvider,
|
|
988
1318
|
TextEditor,
|
|
989
1319
|
TextKind,
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1320
|
+
YText2 as YText,
|
|
1321
|
+
YXmlFragment,
|
|
1322
|
+
basicBundle,
|
|
1323
|
+
basicTheme,
|
|
1324
|
+
chalky,
|
|
1325
|
+
coral,
|
|
1326
|
+
createHyperlinkTooltip,
|
|
1327
|
+
cursorColor,
|
|
1328
|
+
cyan,
|
|
1329
|
+
highlightBackground,
|
|
1330
|
+
hyperLinkExtension,
|
|
1331
|
+
hyperlinkDecoration,
|
|
1332
|
+
hyperlinkStyle,
|
|
1333
|
+
hyperlinkWidget,
|
|
1334
|
+
invalid,
|
|
1335
|
+
ivory,
|
|
1336
|
+
malibu,
|
|
1337
|
+
markdownBundle,
|
|
1338
|
+
markdownHighlightStyle,
|
|
1339
|
+
markdownTheme,
|
|
1340
|
+
onChangeExtension,
|
|
1341
|
+
sage,
|
|
1342
|
+
stone,
|
|
993
1343
|
tags2 as tags,
|
|
994
|
-
|
|
1344
|
+
tooltipBackground,
|
|
1345
|
+
useCollaboration,
|
|
1346
|
+
useTextModel,
|
|
1347
|
+
violet,
|
|
1348
|
+
whiskey
|
|
995
1349
|
};
|
|
996
1350
|
//# sourceMappingURL=index.mjs.map
|