@dxos/react-ui-editor 0.3.11-main.9bacd9f → 0.3.11-main.9d68491
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +1655 -1156
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +9 -5
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +10 -10
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +5 -2
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/{hooks/automerge → components/TextEditor}/automerge.stories.d.ts +6 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/index.d.ts +0 -2
- package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
- package/dist/types/src/{hooks/yjs → components/TextEditor}/yjs.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts +9 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/cursor.d.ts +5 -0
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/defs.d.ts +26 -0
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/index.d.ts +4 -0
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -0
- package/dist/types/src/{hooks → extensions}/automerge/semaphore.d.ts +4 -4
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +5 -0
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness.d.ts +46 -0
- package/dist/types/src/extensions/awareness.d.ts.map +1 -0
- package/dist/types/src/extensions/basic.d.ts.map +1 -0
- package/dist/types/src/extensions/blast.d.ts.map +1 -0
- package/dist/types/src/extensions/code.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/comments.d.ts +4 -2
- package/dist/types/src/extensions/comments.d.ts.map +1 -0
- package/dist/types/src/extensions/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/image.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/index.d.ts +3 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/extensions/link.d.ts.map +1 -0
- package/dist/types/src/extensions/listener.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -0
- package/dist/types/src/extensions/table.d.ts.map +1 -0
- package/dist/types/src/extensions/tasklist.d.ts.map +1 -0
- package/dist/types/src/extensions/typewriter.d.ts.map +1 -0
- package/dist/types/src/extensions/yjs/cursor.d.ts +4 -0
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/yjs/index.d.ts +2 -0
- package/dist/types/src/extensions/yjs/index.d.ts.map +1 -0
- package/dist/types/src/extensions/yjs/yjs.d.ts +4 -0
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +1 -0
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge.d.ts +3 -0
- package/dist/types/src/hooks/automerge.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +28 -0
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +9 -8
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/hooks/{yjs/space-provider.d.ts → yjs.d.ts} +8 -8
- package/dist/types/src/hooks/yjs.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/cursors.d.ts.map +1 -0
- package/dist/types/src/styles/index.d.ts +1 -0
- package/dist/types/src/styles/index.d.ts.map +1 -1
- package/dist/types/src/styles/tokens.d.ts +1 -0
- package/dist/types/src/styles/tokens.d.ts.map +1 -1
- package/dist/types/src/testing/replicator.d.ts +2 -2
- package/dist/types/src/testing/replicator.d.ts.map +1 -1
- package/dist/types/src/{components/TextEditor/themes → themes}/default.d.ts +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -0
- package/dist/types/src/themes/index.d.ts.map +1 -0
- package/dist/types/src/util/cursor.d.ts +17 -0
- package/dist/types/src/util/cursor.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +3 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/util.d.ts.map +1 -0
- package/package.json +22 -21
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +14 -12
- package/src/components/TextEditor/TextEditor.stories.tsx +17 -5
- package/src/components/TextEditor/TextEditor.tsx +62 -48
- package/src/{hooks/automerge → components/TextEditor}/automerge.stories.tsx +66 -6
- package/src/components/TextEditor/codemirror.stories.ts +3 -2
- package/src/components/TextEditor/index.ts +0 -3
- package/src/{hooks/yjs → components/TextEditor}/yjs.stories.tsx +1 -1
- package/src/{components/TextEditor/extensions → extensions}/autocomplete.ts +18 -17
- package/src/extensions/automerge/automerge.ts +94 -0
- package/src/extensions/automerge/cursor.ts +51 -0
- package/src/extensions/automerge/defs.ts +62 -0
- package/src/extensions/automerge/index.ts +7 -0
- package/src/{hooks → extensions}/automerge/semaphore.ts +14 -12
- package/src/{hooks → extensions}/automerge/update-automerge.ts +5 -6
- package/src/{hooks → extensions}/automerge/update-codemirror.ts +13 -5
- package/src/extensions/awareness.ts +316 -0
- package/src/{components/TextEditor/extensions → extensions}/code.ts +4 -5
- package/src/{components/TextEditor/extensions → extensions}/comments.ts +50 -19
- package/src/{components/TextEditor/extensions → extensions}/hr.ts +2 -3
- package/src/extensions/image.ts +87 -0
- package/src/{components/TextEditor/extensions → extensions}/index.ts +3 -1
- package/src/{components/TextEditor/extensions → extensions}/link.ts +82 -84
- package/src/{components/TextEditor/extensions → extensions}/markdown/highlight.ts +4 -5
- package/src/{components/TextEditor/extensions → extensions}/table.ts +9 -3
- package/src/{components/TextEditor/extensions → extensions}/tasklist.ts +1 -3
- package/src/{components/TextEditor/extensions → extensions}/typewriter.ts +1 -1
- package/src/extensions/yjs/cursor.ts +21 -0
- package/src/extensions/yjs/index.ts +5 -0
- package/src/{hooks → extensions}/yjs/yjs.test.ts +1 -25
- package/src/extensions/yjs/yjs.ts +16 -0
- package/src/hooks/automerge.ts +52 -0
- package/src/hooks/awareness-provider.ts +120 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useTextModel.ts +21 -94
- package/src/hooks/{yjs/space-provider.ts → yjs.ts} +71 -19
- package/src/index.ts +5 -0
- package/src/styles/index.ts +1 -0
- package/src/styles/tokens.ts +3 -0
- package/src/testing/replicator.ts +10 -15
- package/src/{components/TextEditor/themes → themes}/default.ts +40 -34
- package/src/util/cursor.ts +29 -0
- package/src/util/index.ts +6 -0
- package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/mermaid.d.ts +0 -3
- package/dist/types/src/components/TextEditor/extensions/mermaid.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/typewriter.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/util.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/themes/index.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/handle.d.ts +0 -9
- package/dist/types/src/hooks/automerge/handle.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/index.d.ts +0 -3
- package/dist/types/src/hooks/automerge/index.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/plugin.d.ts +0 -26
- package/dist/types/src/hooks/automerge/plugin.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/semaphore.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/update-automerge.d.ts +0 -6
- package/dist/types/src/hooks/automerge/update-automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/update-codemirror.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/cursors.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/index.d.ts +0 -3
- package/dist/types/src/hooks/yjs/index.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/space-provider.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/yjs.test.d.ts.map +0 -1
- package/src/components/TextEditor/extensions/image.ts +0 -69
- package/src/components/TextEditor/extensions/mermaid.ts +0 -11
- package/src/hooks/automerge/handle.ts +0 -14
- package/src/hooks/automerge/index.ts +0 -6
- package/src/hooks/automerge/plugin.ts +0 -134
- package/src/hooks/yjs/index.ts +0 -6
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/autocomplete.d.ts +0 -0
- /package/dist/types/src/{hooks → extensions}/automerge/update-codemirror.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/basic.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/blast.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/code.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/hr.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/image.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/link.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/listener.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/bundle.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/highlight.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/index.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/mention.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/table.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/tasklist.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/typewriter.d.ts +0 -0
- /package/dist/types/src/{hooks → extensions}/yjs/yjs.test.d.ts +0 -0
- /package/dist/types/src/{hooks/yjs → styles}/cursors.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/themes → themes}/index.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → util}/util.d.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/basic.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/blast.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/listener.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/markdown/bundle.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/markdown/index.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/mention.ts +0 -0
- /package/src/{hooks/yjs → styles}/cursors.ts +0 -0
- /package/src/{components/TextEditor/themes → themes}/index.ts +0 -0
- /package/src/{components/TextEditor/extensions → util}/util.ts +0 -0
|
@@ -5,506 +5,294 @@ import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
|
5
5
|
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
6
6
|
import { tags as tags2 } from "@lezer/highlight";
|
|
7
7
|
|
|
8
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/
|
|
8
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
|
+
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
+
import { EditorView as EditorView12 } from "@codemirror/view";
|
|
11
|
+
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
|
+
import { vim } from "@replit/codemirror-vim";
|
|
13
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState, useRef } from "react";
|
|
15
|
+
import { generateName } from "@dxos/display-name";
|
|
16
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
+
import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
|
+
|
|
19
|
+
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
9
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
21
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
10
22
|
import { keymap } from "@codemirror/view";
|
|
11
23
|
var autocomplete = ({ onSearch }) => {
|
|
12
24
|
return [
|
|
13
25
|
// https://codemirror.net/docs/ref/#view.keymap
|
|
14
26
|
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
|
27
|
+
// TODO(burdon): Set custom keymap.
|
|
15
28
|
keymap.of(completionKeymap),
|
|
16
29
|
// https://codemirror.net/examples/autocompletion
|
|
17
30
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
18
31
|
autocompletion({
|
|
19
|
-
|
|
20
|
-
// defaultKeymap: false,
|
|
32
|
+
defaultKeymap: false,
|
|
21
33
|
// Don't start unless key press.
|
|
22
|
-
activateOnTyping: false
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
from: match.from,
|
|
33
|
-
options: onSearch(match.text.toLowerCase())
|
|
34
|
-
};
|
|
34
|
+
activateOnTyping: false
|
|
35
|
+
}),
|
|
36
|
+
// TODO(burdon): Option to create new page?
|
|
37
|
+
// TODO(burdon): Optional decoration via addToOptions
|
|
38
|
+
markdownLanguage.data.of({
|
|
39
|
+
autocomplete: (context) => {
|
|
40
|
+
const match = context.matchBefore(/\w*/);
|
|
41
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
42
|
+
return null;
|
|
35
43
|
}
|
|
36
|
-
|
|
44
|
+
return {
|
|
45
|
+
from: match.from,
|
|
46
|
+
options: onSearch(match.text.toLowerCase())
|
|
47
|
+
};
|
|
48
|
+
}
|
|
37
49
|
})
|
|
38
50
|
];
|
|
39
51
|
};
|
|
40
52
|
|
|
41
|
-
// packages/ui/react-ui-editor/src/
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import { drawSelection, EditorView, placeholder } from "@codemirror/view";
|
|
46
|
-
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
47
|
-
EditorView.lineWrapping,
|
|
48
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
49
|
-
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
50
|
-
bracketMatching(),
|
|
51
|
-
closeBrackets(),
|
|
52
|
-
drawSelection(),
|
|
53
|
-
_placeholder && placeholder(_placeholder),
|
|
54
|
-
// TODO(burdon): Is this required?
|
|
55
|
-
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
56
|
-
].filter(Boolean);
|
|
53
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
54
|
+
import { Facet as Facet2, StateField } from "@codemirror/state";
|
|
55
|
+
import { ViewPlugin } from "@codemirror/view";
|
|
56
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
57
57
|
|
|
58
|
-
// packages/ui/react-ui-editor/src/
|
|
59
|
-
import
|
|
60
|
-
import
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
min: 5,
|
|
74
|
-
max: 10
|
|
75
|
-
},
|
|
76
|
-
particleVelocityRange: {
|
|
77
|
-
x: [
|
|
78
|
-
-1,
|
|
79
|
-
1
|
|
80
|
-
],
|
|
81
|
-
y: [
|
|
82
|
-
-3.5,
|
|
83
|
-
-1.5
|
|
84
|
-
]
|
|
58
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
59
|
+
import get from "lodash.get";
|
|
60
|
+
import { next as automerge } from "@dxos/automerge/automerge";
|
|
61
|
+
var cursorConverter = (handle, path) => ({
|
|
62
|
+
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
63
|
+
toCursor: (pos) => {
|
|
64
|
+
const doc = handle.docSync();
|
|
65
|
+
if (!doc) {
|
|
66
|
+
return "";
|
|
67
|
+
}
|
|
68
|
+
const value = get(doc, path);
|
|
69
|
+
if (typeof value === "string" && value.length <= pos) {
|
|
70
|
+
return "end";
|
|
71
|
+
}
|
|
72
|
+
return automerge.getCursor(doc, path.slice(), pos);
|
|
85
73
|
},
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
y: y - top
|
|
99
|
-
};
|
|
100
|
-
return {
|
|
101
|
-
element,
|
|
102
|
-
point
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
return [
|
|
106
|
-
// Cursor moved.
|
|
107
|
-
EditorView2.updateListener.of((update4) => {
|
|
108
|
-
if (blaster?.node !== update4.view.scrollDOM) {
|
|
109
|
-
if (blaster) {
|
|
110
|
-
blaster.destroy();
|
|
111
|
-
}
|
|
112
|
-
blaster = new Blaster(update4.view.scrollDOM, defaultsDeep({
|
|
113
|
-
particleGravity: 0.2,
|
|
114
|
-
particleShrinkRate: 0.995,
|
|
115
|
-
color: () => [
|
|
116
|
-
100 + Math.random() * 100,
|
|
117
|
-
0,
|
|
118
|
-
0
|
|
119
|
-
]
|
|
120
|
-
}, options, defaultOptions));
|
|
121
|
-
blaster.initialize();
|
|
122
|
-
blaster.start();
|
|
74
|
+
fromCursor: (cursor) => {
|
|
75
|
+
if (cursor === "") {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
const doc = handle.docSync();
|
|
79
|
+
if (!doc) {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
if (cursor === "end") {
|
|
83
|
+
const value = get(doc, path);
|
|
84
|
+
if (typeof value === "string") {
|
|
85
|
+
return value.length;
|
|
123
86
|
} else {
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
const current = update4.state.selection.main.head;
|
|
127
|
-
if (current !== last) {
|
|
128
|
-
last = current;
|
|
129
|
-
const { element, point } = getPoint(update4.view, current - 1);
|
|
130
|
-
if (element && point) {
|
|
131
|
-
blaster.spawn({
|
|
132
|
-
element,
|
|
133
|
-
point
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}),
|
|
138
|
-
keymap2.of([
|
|
139
|
-
{
|
|
140
|
-
any: (_, event) => {
|
|
141
|
-
if (blaster) {
|
|
142
|
-
if (event.key === "Enter" && event.shiftKey) {
|
|
143
|
-
blaster.shake({
|
|
144
|
-
time: 0.8
|
|
145
|
-
});
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
])
|
|
153
|
-
];
|
|
154
|
-
};
|
|
155
|
-
var Blaster = class {
|
|
156
|
-
constructor(_node, _options) {
|
|
157
|
-
this._node = _node;
|
|
158
|
-
this._options = _options;
|
|
159
|
-
this._running = false;
|
|
160
|
-
this._shakeTime = 0;
|
|
161
|
-
this._shakeTimeMax = 0;
|
|
162
|
-
this._particles = [];
|
|
163
|
-
this._particlePointer = 0;
|
|
164
|
-
this._lastPoint = {
|
|
165
|
-
x: 0,
|
|
166
|
-
y: 0
|
|
167
|
-
};
|
|
168
|
-
this.shake = throttle(({ time }) => {
|
|
169
|
-
this._shakeTime = this._shakeTimeMax || time;
|
|
170
|
-
this._shakeTimeMax = time;
|
|
171
|
-
}, 100);
|
|
172
|
-
this.spawn = throttle(({ element, point }) => {
|
|
173
|
-
const color = getRGBComponents(element, this._options.color);
|
|
174
|
-
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
175
|
-
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
176
|
-
this._lastPoint = point;
|
|
177
|
-
for (let i = numParticles; i--; i > 0) {
|
|
178
|
-
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
179
|
-
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
87
|
+
return 0;
|
|
180
88
|
}
|
|
181
|
-
}, 100);
|
|
182
|
-
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
183
|
-
}
|
|
184
|
-
get node() {
|
|
185
|
-
return this._node;
|
|
186
|
-
}
|
|
187
|
-
initialize() {
|
|
188
|
-
invariant(!this._canvas && !this._ctx, void 0, {
|
|
189
|
-
F: __dxlog_file,
|
|
190
|
-
L: 138,
|
|
191
|
-
S: this,
|
|
192
|
-
A: [
|
|
193
|
-
"!this._canvas && !this._ctx",
|
|
194
|
-
""
|
|
195
|
-
]
|
|
196
|
-
});
|
|
197
|
-
this._canvas = document.createElement("canvas");
|
|
198
|
-
this._canvas.id = "code-blast-canvas";
|
|
199
|
-
this._canvas.style.position = "absolute";
|
|
200
|
-
this._canvas.style.zIndex = "0";
|
|
201
|
-
this._canvas.style.pointerEvents = "none";
|
|
202
|
-
this._ctx = this._canvas.getContext("2d");
|
|
203
|
-
const parent = this._node.parentElement?.parentElement;
|
|
204
|
-
parent?.appendChild(this._canvas);
|
|
205
|
-
this.resize();
|
|
206
|
-
}
|
|
207
|
-
destroy() {
|
|
208
|
-
this.stop();
|
|
209
|
-
if (this._canvas) {
|
|
210
|
-
this._canvas.remove();
|
|
211
|
-
this._canvas = void 0;
|
|
212
|
-
this._ctx = void 0;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
resize() {
|
|
216
|
-
if (this._node.parentElement && this._canvas) {
|
|
217
|
-
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
218
|
-
this._canvas.style.top = `${y}px`;
|
|
219
|
-
this._canvas.style.left = `${x}px`;
|
|
220
|
-
this._canvas.width = width;
|
|
221
|
-
this._canvas.height = height;
|
|
222
89
|
}
|
|
90
|
+
return automerge.getCursorPosition(doc, path.slice(), cursor);
|
|
223
91
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
95
|
+
import { Annotation, StateEffect } from "@codemirror/state";
|
|
96
|
+
var effectType = StateEffect.define({});
|
|
97
|
+
var updateHeads = (newHeads) => effectType.of({
|
|
98
|
+
newHeads
|
|
99
|
+
});
|
|
100
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
101
|
+
var getPath = (state, field) => state.field(field).path;
|
|
102
|
+
var reconcileAnnotationType = Annotation.define();
|
|
103
|
+
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
104
|
+
|
|
105
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
106
|
+
import { next as automerge2 } from "@dxos/automerge/automerge";
|
|
107
|
+
|
|
108
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
109
|
+
import { next as am } from "@dxos/automerge/automerge";
|
|
110
|
+
var updateAutomerge = (field, handle, transactions, state) => {
|
|
111
|
+
const { lastHeads, path } = state.field(field);
|
|
112
|
+
let hasChanges = false;
|
|
113
|
+
for (const tr of transactions) {
|
|
114
|
+
tr.changes.iterChanges(() => {
|
|
115
|
+
hasChanges = true;
|
|
233
116
|
});
|
|
234
|
-
this._running = true;
|
|
235
|
-
this.loop();
|
|
236
117
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
this._node.style.transform = "translate(0px, 0px)";
|
|
118
|
+
if (!hasChanges) {
|
|
119
|
+
return void 0;
|
|
240
120
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
247
|
-
this._lastTime ??= now;
|
|
248
|
-
const dt = (now - this._lastTime) / 1e3;
|
|
249
|
-
this._lastTime = now;
|
|
250
|
-
if (this._shakeTime > 0) {
|
|
251
|
-
this._shakeTime -= dt;
|
|
252
|
-
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
253
|
-
const shakeX = random(-magnitude, magnitude);
|
|
254
|
-
const shakeY = random(-magnitude, magnitude);
|
|
255
|
-
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
121
|
+
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
122
|
+
for (const tr of transactions) {
|
|
123
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
124
|
+
am.splice(doc, path, fromA, toA - fromA, inserted.toString());
|
|
125
|
+
});
|
|
256
126
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
127
|
+
});
|
|
128
|
+
return newHeads ?? void 0;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/update-codemirror.ts
|
|
132
|
+
import { ChangeSet } from "@codemirror/state";
|
|
133
|
+
var updateCodeMirror = (view, selection, target, patches) => {
|
|
134
|
+
for (const patch of patches) {
|
|
135
|
+
const changeSpec = handlePatch(patch, target, view.state);
|
|
136
|
+
if (changeSpec != null) {
|
|
137
|
+
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
|
138
|
+
selection = selection.map(changeSet, 1);
|
|
139
|
+
view.dispatch({
|
|
140
|
+
changes: changeSet,
|
|
141
|
+
annotations: reconcileAnnotationType.of({})
|
|
142
|
+
});
|
|
270
143
|
}
|
|
271
144
|
}
|
|
145
|
+
view.dispatch({
|
|
146
|
+
selection,
|
|
147
|
+
annotations: reconcileAnnotationType.of({})
|
|
148
|
+
});
|
|
272
149
|
};
|
|
273
|
-
var
|
|
274
|
-
|
|
275
|
-
|
|
150
|
+
var handlePatch = (patch, target, state) => {
|
|
151
|
+
if (patch.action === "insert") {
|
|
152
|
+
return handleInsert(target, patch);
|
|
153
|
+
} else if (patch.action === "splice") {
|
|
154
|
+
return handleSplice(target, patch);
|
|
155
|
+
} else if (patch.action === "del") {
|
|
156
|
+
return handleDel(target, patch);
|
|
157
|
+
} else if (patch.action === "put") {
|
|
158
|
+
return handlePut(target, patch, state);
|
|
159
|
+
} else {
|
|
160
|
+
return null;
|
|
276
161
|
}
|
|
277
162
|
};
|
|
278
|
-
var
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
y: y + 10,
|
|
283
|
-
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
284
|
-
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
285
|
-
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
286
|
-
color,
|
|
287
|
-
alpha: 1
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
update(ctx, particle) {
|
|
291
|
-
particle.vy += this._options.particleGravity;
|
|
292
|
-
particle.x += particle.vx;
|
|
293
|
-
particle.y += particle.vy;
|
|
294
|
-
particle.alpha *= this._options.particleAlphaFadeout;
|
|
295
|
-
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
296
|
-
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
163
|
+
var handleInsert = (target, patch) => {
|
|
164
|
+
const index = charPath(target, patch.path);
|
|
165
|
+
if (index == null) {
|
|
166
|
+
return [];
|
|
297
167
|
}
|
|
168
|
+
const text = patch.values.map((v) => v ? v.toString() : "").join("");
|
|
169
|
+
return [
|
|
170
|
+
{
|
|
171
|
+
from: index,
|
|
172
|
+
to: index,
|
|
173
|
+
insert: text
|
|
174
|
+
}
|
|
175
|
+
];
|
|
298
176
|
};
|
|
299
|
-
var
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
y: y + 10,
|
|
304
|
-
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
305
|
-
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
306
|
-
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
307
|
-
color,
|
|
308
|
-
alpha: 1,
|
|
309
|
-
theta: random(0, 360) * Math.PI / 180,
|
|
310
|
-
drag: 0.92,
|
|
311
|
-
wander: 0.15
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
update(ctx, particle) {
|
|
315
|
-
particle.vy += this._options.particleGravity;
|
|
316
|
-
particle.x += particle.vx;
|
|
317
|
-
particle.y += particle.vy;
|
|
318
|
-
particle.vx *= particle.drag;
|
|
319
|
-
particle.vy *= particle.drag;
|
|
320
|
-
particle.theta += random(-0.5, 0.5);
|
|
321
|
-
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
322
|
-
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
323
|
-
particle.size *= this._options.particleShrinkRate;
|
|
324
|
-
particle.alpha *= this._options.particleAlphaFadeout;
|
|
325
|
-
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
326
|
-
ctx.beginPath();
|
|
327
|
-
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
328
|
-
ctx.fill();
|
|
177
|
+
var handleSplice = (target, patch) => {
|
|
178
|
+
const index = charPath(target, patch.path);
|
|
179
|
+
if (index == null) {
|
|
180
|
+
return [];
|
|
329
181
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (!wait) {
|
|
335
|
-
callback.apply(this, args);
|
|
336
|
-
wait = true;
|
|
337
|
-
setTimeout(() => {
|
|
338
|
-
wait = false;
|
|
339
|
-
}, limit);
|
|
182
|
+
return [
|
|
183
|
+
{
|
|
184
|
+
from: index,
|
|
185
|
+
insert: patch.value
|
|
340
186
|
}
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
var
|
|
344
|
-
|
|
345
|
-
|
|
187
|
+
];
|
|
188
|
+
};
|
|
189
|
+
var handleDel = (target, patch) => {
|
|
190
|
+
const index = charPath(target, patch.path);
|
|
191
|
+
if (index == null) {
|
|
192
|
+
return [];
|
|
346
193
|
}
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
194
|
+
const length = patch.length || 1;
|
|
195
|
+
return [
|
|
196
|
+
{
|
|
197
|
+
from: index,
|
|
198
|
+
to: index + length
|
|
352
199
|
}
|
|
200
|
+
];
|
|
201
|
+
};
|
|
202
|
+
var handlePut = (target, patch, state) => {
|
|
203
|
+
const index = charPath(target, [
|
|
204
|
+
...patch.path,
|
|
205
|
+
0
|
|
206
|
+
]);
|
|
207
|
+
if (index == null) {
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
const length = state.doc.length;
|
|
211
|
+
if (typeof patch.value !== "string") {
|
|
212
|
+
return [];
|
|
353
213
|
}
|
|
354
214
|
return [
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
215
|
+
{
|
|
216
|
+
from: 0,
|
|
217
|
+
to: length,
|
|
218
|
+
insert: patch.value
|
|
219
|
+
}
|
|
358
220
|
];
|
|
359
221
|
};
|
|
360
|
-
var
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
min = 0;
|
|
222
|
+
var charPath = (textPath, candidatePath) => {
|
|
223
|
+
if (candidatePath.length !== textPath.length + 1) {
|
|
224
|
+
return null;
|
|
364
225
|
}
|
|
365
|
-
|
|
226
|
+
for (let i = 0; i < textPath.length; i++) {
|
|
227
|
+
if (textPath[i] !== candidatePath[i]) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const index = candidatePath[candidatePath.length - 1];
|
|
232
|
+
if (typeof index === "number") {
|
|
233
|
+
return index;
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
366
236
|
};
|
|
367
237
|
|
|
368
|
-
// packages/ui/react-ui-editor/src/
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
238
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
239
|
+
var PatchSemaphore = class {
|
|
240
|
+
constructor(_field) {
|
|
241
|
+
this._field = _field;
|
|
242
|
+
this._inReconcile = false;
|
|
243
|
+
this._queue = [];
|
|
244
|
+
this.reconcile = (handle, view) => {
|
|
245
|
+
if (this._inReconcile) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
this._inReconcile = true;
|
|
249
|
+
const path = getPath(view.state, this._field);
|
|
250
|
+
const oldHeads = getLastHeads(view.state, this._field);
|
|
251
|
+
let selection = view.state.selection;
|
|
252
|
+
const transactions = view.state.field(this._field).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
253
|
+
const toInvert = transactions.slice().reverse();
|
|
254
|
+
for (const tx of toInvert) {
|
|
255
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
256
|
+
selection = selection.map(inverted);
|
|
257
|
+
view.dispatch({
|
|
258
|
+
changes: inverted,
|
|
259
|
+
annotations: reconcileAnnotationType.of(true)
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
263
|
+
if (newHeads === null || newHeads === void 0) {
|
|
264
|
+
newHeads = automerge2.getHeads(handle.docSync());
|
|
265
|
+
}
|
|
266
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
|
|
267
|
+
updateCodeMirror(view, selection, path, diff);
|
|
268
|
+
view.dispatch({
|
|
269
|
+
effects: updateHeads(newHeads),
|
|
270
|
+
annotations: reconcileAnnotationType.of({})
|
|
271
|
+
});
|
|
272
|
+
this._inReconcile = false;
|
|
273
|
+
};
|
|
274
|
+
}
|
|
400
275
|
};
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
276
|
+
|
|
277
|
+
// packages/ui/react-ui-editor/src/util/cursor.ts
|
|
278
|
+
import { Facet } from "@codemirror/state";
|
|
279
|
+
var DEFAULT_CURSOR_CONVERTER = {
|
|
280
|
+
toCursor: (position) => position.toString(),
|
|
281
|
+
fromCursor: (cursor) => parseInt(cursor)
|
|
404
282
|
};
|
|
405
|
-
var
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
var italic = "italic";
|
|
409
|
-
var strikethrough = "line-through";
|
|
410
|
-
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
411
|
-
var codeMark = "font-mono text-primary-500";
|
|
412
|
-
var inlineUrl = mx(code, "px-1");
|
|
413
|
-
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
283
|
+
var CursorConverter = Facet.define({
|
|
284
|
+
combine: (providers) => providers[0] ?? DEFAULT_CURSOR_CONVERTER
|
|
285
|
+
});
|
|
414
286
|
|
|
415
|
-
// packages/ui/react-ui-editor/src/
|
|
416
|
-
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
417
|
-
var tokens = tailwindConfig({}).theme;
|
|
418
|
-
|
|
419
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/code.ts
|
|
420
|
-
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
421
|
-
var styles = EditorView3.baseTheme({
|
|
422
|
-
"& .cm-codeblock": {
|
|
423
|
-
fontFamily: get(tokens, "fontFamily.mono", []).join(",")
|
|
424
|
-
},
|
|
425
|
-
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
426
|
-
background: get(tokens, "extend.colors.neutral.50")
|
|
427
|
-
},
|
|
428
|
-
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
429
|
-
background: get(tokens, "extend.colors.neutral.850")
|
|
430
|
-
},
|
|
431
|
-
'& [aria-readonly="true"] .cm-codeblock': {
|
|
432
|
-
display: "block",
|
|
433
|
-
paddingInline: "4px !important"
|
|
434
|
-
},
|
|
435
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
436
|
-
paddingTop: "4px !important",
|
|
437
|
-
borderTopLeftRadius: "4px",
|
|
438
|
-
borderTopRightRadius: "4px"
|
|
439
|
-
},
|
|
440
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
441
|
-
paddingBottom: "4px !important",
|
|
442
|
-
borderBottomLeftRadius: "4px",
|
|
443
|
-
borderBottomRightRadius: "4px"
|
|
444
|
-
}
|
|
445
|
-
});
|
|
446
|
-
var getLineRange = (lines, from, to) => {
|
|
447
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
448
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
449
|
-
return [
|
|
450
|
-
start,
|
|
451
|
-
end
|
|
452
|
-
];
|
|
453
|
-
};
|
|
454
|
-
var code2 = () => {
|
|
455
|
-
const getDecorations = (view) => {
|
|
456
|
-
const decorations = [];
|
|
457
|
-
if (view.state.readOnly) {
|
|
458
|
-
const text = view.state.doc.sliceString(0);
|
|
459
|
-
const matches = text.matchAll(CODE_REGEX);
|
|
460
|
-
const blocks = view.viewportLineBlocks;
|
|
461
|
-
for (const match of matches) {
|
|
462
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
463
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
464
|
-
const block = blocks[i];
|
|
465
|
-
decorations.push(Decoration.line({
|
|
466
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
467
|
-
}).range(block.from));
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
return Decoration.set(decorations);
|
|
472
|
-
};
|
|
473
|
-
return [
|
|
474
|
-
ViewPlugin.fromClass(class {
|
|
475
|
-
constructor(view) {
|
|
476
|
-
this.decorations = getDecorations(view);
|
|
477
|
-
}
|
|
478
|
-
update(update4) {
|
|
479
|
-
if (update4.docChanged || update4.viewportChanged) {
|
|
480
|
-
this.decorations = getDecorations(update4.view);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}, {
|
|
484
|
-
decorations: (value) => value.decorations
|
|
485
|
-
}),
|
|
486
|
-
styles
|
|
487
|
-
];
|
|
488
|
-
};
|
|
489
|
-
|
|
490
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
|
|
491
|
-
import { StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
|
|
492
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView4, MatchDecorator, ViewPlugin as ViewPlugin3, WidgetType } from "@codemirror/view";
|
|
493
|
-
import sortBy from "lodash.sortby";
|
|
494
|
-
import { debounce } from "@dxos/async";
|
|
495
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
496
|
-
import { log as log3 } from "@dxos/log";
|
|
497
|
-
import { nonNullable } from "@dxos/util";
|
|
498
|
-
|
|
499
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/util.ts
|
|
287
|
+
// packages/ui/react-ui-editor/src/util/util.ts
|
|
500
288
|
import { log } from "@dxos/log";
|
|
501
|
-
var
|
|
289
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
502
290
|
var callbackWrapper = (fn) => (...args) => {
|
|
503
291
|
try {
|
|
504
292
|
return fn(...args);
|
|
505
293
|
} catch (error) {
|
|
506
294
|
log.catch(error, void 0, {
|
|
507
|
-
F:
|
|
295
|
+
F: __dxlog_file,
|
|
508
296
|
L: 16,
|
|
509
297
|
S: void 0,
|
|
510
298
|
C: (f, a) => f(...a)
|
|
@@ -512,209 +300,14 @@ var callbackWrapper = (fn) => (...args) => {
|
|
|
512
300
|
}
|
|
513
301
|
};
|
|
514
302
|
|
|
515
|
-
// packages/ui/react-ui-editor/src/
|
|
516
|
-
|
|
517
|
-
import get2 from "lodash.get";
|
|
518
|
-
import { useEffect, useState } from "react";
|
|
519
|
-
import { yCollab } from "y-codemirror.next";
|
|
520
|
-
import * as Y from "yjs";
|
|
521
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
522
|
-
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
523
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
524
|
-
|
|
525
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
526
|
-
import { Annotation, Facet, StateEffect, StateField } from "@codemirror/state";
|
|
527
|
-
import { ViewPlugin as ViewPlugin2 } from "@codemirror/view";
|
|
528
|
-
import * as automerge2 from "@dxos/automerge/automerge";
|
|
529
|
-
|
|
530
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/semaphore.ts
|
|
531
|
-
import { next as automerge } from "@dxos/automerge/automerge";
|
|
532
|
-
|
|
533
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/update-automerge.ts
|
|
534
|
-
import { next as am } from "@dxos/automerge/automerge";
|
|
535
|
-
var updateAutomerge = (field, handle, transactions, state) => {
|
|
536
|
-
const { lastHeads, path } = state.field(field);
|
|
537
|
-
let hasChanges = false;
|
|
538
|
-
for (const tr of transactions) {
|
|
539
|
-
tr.changes.iterChanges(() => {
|
|
540
|
-
hasChanges = true;
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
if (!hasChanges) {
|
|
544
|
-
return void 0;
|
|
545
|
-
}
|
|
546
|
-
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
547
|
-
for (const tr of transactions) {
|
|
548
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
549
|
-
am.splice(doc, path, fromA, toA - fromA, inserted.toString());
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
});
|
|
553
|
-
return newHeads ?? void 0;
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/update-codemirror.ts
|
|
557
|
-
import { ChangeSet } from "@codemirror/state";
|
|
558
|
-
var updateCodeMirror = (view, selection, target, patches) => {
|
|
559
|
-
for (const patch of patches) {
|
|
560
|
-
const changeSpec = handlePatch(patch, target, view.state);
|
|
561
|
-
if (changeSpec != null) {
|
|
562
|
-
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
|
563
|
-
selection = selection.map(changeSet, 1);
|
|
564
|
-
view.dispatch({
|
|
565
|
-
changes: changeSet,
|
|
566
|
-
annotations: reconcileAnnotationType.of({})
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
view.dispatch({
|
|
571
|
-
selection,
|
|
572
|
-
annotations: reconcileAnnotationType.of({})
|
|
573
|
-
});
|
|
574
|
-
};
|
|
575
|
-
var handlePatch = (patch, target, state) => {
|
|
576
|
-
if (patch.action === "insert") {
|
|
577
|
-
return handleInsert(target, patch);
|
|
578
|
-
} else if (patch.action === "splice") {
|
|
579
|
-
return handleSplice(target, patch);
|
|
580
|
-
} else if (patch.action === "del") {
|
|
581
|
-
return handleDel(target, patch);
|
|
582
|
-
} else if (patch.action === "put") {
|
|
583
|
-
return handlePut(target, patch, state);
|
|
584
|
-
} else {
|
|
585
|
-
return null;
|
|
586
|
-
}
|
|
587
|
-
};
|
|
588
|
-
var handleInsert = (target, patch) => {
|
|
589
|
-
const index = charPath(target, patch.path);
|
|
590
|
-
if (index == null) {
|
|
591
|
-
return [];
|
|
592
|
-
}
|
|
593
|
-
const text = patch.values.map((v) => v ? v.toString() : "").join("");
|
|
594
|
-
return [
|
|
595
|
-
{
|
|
596
|
-
from: index,
|
|
597
|
-
to: index,
|
|
598
|
-
insert: text
|
|
599
|
-
}
|
|
600
|
-
];
|
|
601
|
-
};
|
|
602
|
-
var handleSplice = (target, patch) => {
|
|
603
|
-
const index = charPath(target, patch.path);
|
|
604
|
-
if (index == null) {
|
|
605
|
-
return [];
|
|
606
|
-
}
|
|
607
|
-
return [
|
|
608
|
-
{
|
|
609
|
-
from: index,
|
|
610
|
-
insert: patch.value
|
|
611
|
-
}
|
|
612
|
-
];
|
|
613
|
-
};
|
|
614
|
-
var handleDel = (target, patch) => {
|
|
615
|
-
const index = charPath(target, patch.path);
|
|
616
|
-
if (index == null) {
|
|
617
|
-
return [];
|
|
618
|
-
}
|
|
619
|
-
const length = patch.length || 1;
|
|
620
|
-
return [
|
|
621
|
-
{
|
|
622
|
-
from: index,
|
|
623
|
-
to: index + length
|
|
624
|
-
}
|
|
625
|
-
];
|
|
626
|
-
};
|
|
627
|
-
var handlePut = (target, patch, state) => {
|
|
628
|
-
const index = charPath(target, [
|
|
629
|
-
...patch.path,
|
|
630
|
-
0
|
|
631
|
-
]);
|
|
632
|
-
if (index == null) {
|
|
633
|
-
return [];
|
|
634
|
-
}
|
|
635
|
-
const length = state.doc.length;
|
|
636
|
-
if (typeof patch.value !== "string") {
|
|
637
|
-
return [];
|
|
638
|
-
}
|
|
639
|
-
return [
|
|
640
|
-
{
|
|
641
|
-
from: 0,
|
|
642
|
-
to: length,
|
|
643
|
-
insert: patch.value
|
|
644
|
-
}
|
|
645
|
-
];
|
|
646
|
-
};
|
|
647
|
-
var charPath = (textPath, candidatePath) => {
|
|
648
|
-
if (candidatePath.length !== textPath.length + 1) {
|
|
649
|
-
return null;
|
|
650
|
-
}
|
|
651
|
-
for (let i = 0; i < textPath.length; i++) {
|
|
652
|
-
if (textPath[i] !== candidatePath[i]) {
|
|
653
|
-
return null;
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
const index = candidatePath[candidatePath.length - 1];
|
|
657
|
-
if (typeof index === "number") {
|
|
658
|
-
return index;
|
|
659
|
-
}
|
|
660
|
-
return null;
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/semaphore.ts
|
|
664
|
-
var PatchSemaphore = class {
|
|
665
|
-
constructor(field) {
|
|
666
|
-
this._inReconcile = false;
|
|
667
|
-
this._queue = [];
|
|
668
|
-
this.reconcile = (handle, view) => {
|
|
669
|
-
if (this._inReconcile) {
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
this._inReconcile = true;
|
|
673
|
-
const path = getPath(view.state, this._field);
|
|
674
|
-
const oldHeads = getLastHeads(view.state, this._field);
|
|
675
|
-
let selection = view.state.selection;
|
|
676
|
-
const transactions = view.state.field(this._field).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
677
|
-
const toInvert = transactions.slice().reverse();
|
|
678
|
-
for (const tx of toInvert) {
|
|
679
|
-
const inverted = tx.changes.invert(tx.startState.doc);
|
|
680
|
-
selection = selection.map(inverted);
|
|
681
|
-
view.dispatch({
|
|
682
|
-
changes: inverted,
|
|
683
|
-
annotations: reconcileAnnotationType.of(true)
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
687
|
-
if (newHeads === null || newHeads === void 0) {
|
|
688
|
-
newHeads = automerge.getHeads(handle.docSync());
|
|
689
|
-
}
|
|
690
|
-
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
691
|
-
updateCodeMirror(view, selection, path, diff);
|
|
692
|
-
view.dispatch({
|
|
693
|
-
effects: updateHeads(newHeads),
|
|
694
|
-
annotations: reconcileAnnotationType.of({})
|
|
695
|
-
});
|
|
696
|
-
this._inReconcile = false;
|
|
697
|
-
};
|
|
698
|
-
if (field !== void 0) {
|
|
699
|
-
this._field = field;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
};
|
|
703
|
-
|
|
704
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
705
|
-
var effectType = StateEffect.define({});
|
|
706
|
-
var updateHeads = (newHeads) => effectType.of({
|
|
707
|
-
newHeads
|
|
708
|
-
});
|
|
709
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
710
|
-
var getPath = (state, field) => state.field(field).path;
|
|
711
|
-
var semaphoreFacet = Facet.define({
|
|
303
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
304
|
+
var semaphoreFacet = Facet2.define({
|
|
712
305
|
combine: (values) => values.at(-1)
|
|
713
306
|
});
|
|
714
|
-
var
|
|
307
|
+
var automerge3 = ({ handle, path }) => {
|
|
715
308
|
const stateField = StateField.define({
|
|
716
309
|
create: () => ({
|
|
717
|
-
lastHeads:
|
|
310
|
+
lastHeads: A.getHeads(handle.docSync()),
|
|
718
311
|
unreconciledTransactions: [],
|
|
719
312
|
path: path.slice()
|
|
720
313
|
}),
|
|
@@ -742,16 +335,16 @@ var automergePlugin = (handle, path) => {
|
|
|
742
335
|
}
|
|
743
336
|
});
|
|
744
337
|
const semaphore = new PatchSemaphore(stateField);
|
|
745
|
-
const viewPlugin =
|
|
746
|
-
constructor(
|
|
338
|
+
const viewPlugin = ViewPlugin.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
339
|
+
constructor(_view) {
|
|
340
|
+
this._view = _view;
|
|
747
341
|
this._handleChange = () => {
|
|
748
342
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
749
343
|
};
|
|
750
|
-
this._view = view;
|
|
751
344
|
handle.addListener("change", this._handleChange);
|
|
752
345
|
}
|
|
753
|
-
update(
|
|
754
|
-
if (
|
|
346
|
+
update(update2) {
|
|
347
|
+
if (update2.transactions.length > 0 && update2.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
755
348
|
queueMicrotask(() => {
|
|
756
349
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
757
350
|
});
|
|
@@ -763,254 +356,750 @@ var automergePlugin = (handle, path) => {
|
|
|
763
356
|
});
|
|
764
357
|
return {
|
|
765
358
|
extension: [
|
|
766
|
-
|
|
359
|
+
CursorConverter.of(cursorConverter(handle, path)),
|
|
767
360
|
semaphoreFacet.of(semaphore),
|
|
361
|
+
stateField,
|
|
768
362
|
viewPlugin
|
|
769
363
|
]
|
|
770
364
|
};
|
|
771
365
|
};
|
|
772
|
-
var reconcileAnnotationType = Annotation.define();
|
|
773
|
-
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
774
366
|
|
|
775
|
-
// packages/ui/react-ui-editor/src/
|
|
776
|
-
import
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
367
|
+
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
368
|
+
import { Annotation as Annotation2, Facet as Facet3, RangeSet } from "@codemirror/state";
|
|
369
|
+
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
370
|
+
import { Event } from "@dxos/async";
|
|
371
|
+
import { Context } from "@dxos/context";
|
|
372
|
+
var dummyProvider = {
|
|
373
|
+
remoteStateChange: new Event(),
|
|
374
|
+
open: () => {
|
|
781
375
|
},
|
|
782
|
-
{
|
|
783
|
-
color: "#6eeb83",
|
|
784
|
-
light: "#6eeb8333"
|
|
376
|
+
close: () => {
|
|
785
377
|
},
|
|
786
|
-
{
|
|
787
|
-
color: "#ffbc42",
|
|
788
|
-
light: "#ffbc4233"
|
|
378
|
+
update: () => {
|
|
789
379
|
},
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
380
|
+
getRemoteStates: () => []
|
|
381
|
+
};
|
|
382
|
+
var AwarenessProvider = Facet3.define({
|
|
383
|
+
combine: (providers) => providers[0] ?? dummyProvider
|
|
384
|
+
});
|
|
385
|
+
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
386
|
+
var awareness = (provider = dummyProvider) => {
|
|
387
|
+
return [
|
|
388
|
+
AwarenessProvider.of(provider),
|
|
389
|
+
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
390
|
+
decorations: (value) => value.decorations
|
|
391
|
+
}),
|
|
392
|
+
styles
|
|
393
|
+
];
|
|
394
|
+
};
|
|
395
|
+
var RemoteSelectionsDecorator = class {
|
|
396
|
+
constructor(view) {
|
|
397
|
+
this.decorations = RangeSet.of([]);
|
|
398
|
+
this._ctx = new Context();
|
|
399
|
+
this._lastAnchor = void 0;
|
|
400
|
+
this._lastHead = void 0;
|
|
401
|
+
this._cursorConverter = view.state.facet(CursorConverter);
|
|
402
|
+
this._provider = view.state.facet(AwarenessProvider);
|
|
403
|
+
this._provider.open();
|
|
404
|
+
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
405
|
+
view.dispatch({
|
|
406
|
+
annotations: [
|
|
407
|
+
RemoteSelectionChangedAnnotation.of([])
|
|
408
|
+
]
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
destroy() {
|
|
413
|
+
void this._ctx.dispose();
|
|
414
|
+
this._provider.close();
|
|
415
|
+
}
|
|
416
|
+
update(update2) {
|
|
417
|
+
this._updateLocalSelection(update2);
|
|
418
|
+
this._updateRemoteSelections(update2);
|
|
419
|
+
}
|
|
420
|
+
_updateLocalSelection(update2) {
|
|
421
|
+
const hasFocus = update2.view.hasFocus && update2.view.dom.ownerDocument.hasFocus();
|
|
422
|
+
const { anchor = void 0, head = void 0 } = hasFocus ? update2.state.selection.main : {};
|
|
423
|
+
if (this._lastAnchor === anchor && this._lastHead === head) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
this._lastAnchor = anchor;
|
|
427
|
+
this._lastHead = head;
|
|
428
|
+
this._provider.update(anchor !== void 0 && head !== void 0 ? {
|
|
429
|
+
anchor: this._cursorConverter.toCursor(anchor),
|
|
430
|
+
head: this._cursorConverter.toCursor(head)
|
|
431
|
+
} : void 0);
|
|
432
|
+
}
|
|
433
|
+
_updateRemoteSelections(update2) {
|
|
434
|
+
const decorations = [];
|
|
435
|
+
const awarenessStates = this._provider.getRemoteStates();
|
|
436
|
+
for (const state of awarenessStates) {
|
|
437
|
+
const anchor = state.position?.anchor ? this._cursorConverter.fromCursor(state.position.anchor) : null;
|
|
438
|
+
const head = state.position?.head ? this._cursorConverter.fromCursor(state.position.head) : null;
|
|
439
|
+
if (anchor == null || head == null) {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
const start = Math.min(Math.min(anchor, head), update2.view.state.doc.length);
|
|
443
|
+
const end = Math.min(Math.max(anchor, head), update2.view.state.doc.length);
|
|
444
|
+
const startLine = update2.view.state.doc.lineAt(start);
|
|
445
|
+
const endLine = update2.view.state.doc.lineAt(end);
|
|
446
|
+
const color = state.info.color ?? "#30bced";
|
|
447
|
+
const lightColor = state.info.lightColor ?? color + "33";
|
|
448
|
+
if (startLine.number === endLine.number) {
|
|
449
|
+
decorations.push({
|
|
450
|
+
from: start,
|
|
451
|
+
to: end,
|
|
452
|
+
value: Decoration.mark({
|
|
453
|
+
attributes: {
|
|
454
|
+
style: `background-color: ${lightColor}`
|
|
455
|
+
},
|
|
456
|
+
class: "cm-ySelection"
|
|
457
|
+
})
|
|
458
|
+
});
|
|
459
|
+
} else {
|
|
460
|
+
decorations.push({
|
|
461
|
+
from: start,
|
|
462
|
+
to: startLine.from + startLine.length,
|
|
463
|
+
value: Decoration.mark({
|
|
464
|
+
attributes: {
|
|
465
|
+
style: `background-color: ${color}`
|
|
466
|
+
},
|
|
467
|
+
class: "cm-ySelection"
|
|
468
|
+
})
|
|
469
|
+
});
|
|
470
|
+
decorations.push({
|
|
471
|
+
from: endLine.from,
|
|
472
|
+
to: end,
|
|
473
|
+
value: Decoration.mark({
|
|
474
|
+
attributes: {
|
|
475
|
+
style: `background-color: ${color}`
|
|
476
|
+
},
|
|
477
|
+
class: "cm-ySelection"
|
|
478
|
+
})
|
|
479
|
+
});
|
|
480
|
+
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
481
|
+
const linePos = update2.view.state.doc.line(i).from;
|
|
482
|
+
decorations.push({
|
|
483
|
+
from: linePos,
|
|
484
|
+
to: linePos,
|
|
485
|
+
value: Decoration.line({
|
|
486
|
+
attributes: {
|
|
487
|
+
style: `background-color: ${color}`,
|
|
488
|
+
class: "cm-yLineSelection"
|
|
489
|
+
}
|
|
490
|
+
})
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
decorations.push({
|
|
495
|
+
from: head,
|
|
496
|
+
to: head,
|
|
497
|
+
value: Decoration.widget({
|
|
498
|
+
side: head - anchor > 0 ? -1 : 1,
|
|
499
|
+
block: false,
|
|
500
|
+
widget: new RemoteCaretWidget(state.info.displayName ?? "Anonymous", color)
|
|
501
|
+
})
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
this.decorations = Decoration.set(decorations, true);
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
var RemoteCaretWidget = class extends WidgetType {
|
|
508
|
+
constructor(name, color) {
|
|
509
|
+
super();
|
|
510
|
+
this.name = name;
|
|
511
|
+
this.color = color;
|
|
512
|
+
this.name = name;
|
|
513
|
+
this.color = color;
|
|
514
|
+
}
|
|
515
|
+
toDOM() {
|
|
516
|
+
const span = document.createElement("span");
|
|
517
|
+
span.className = "cm-ySelectionCaret";
|
|
518
|
+
span.style.backgroundColor = this.color;
|
|
519
|
+
span.style.borderColor = this.color;
|
|
520
|
+
const dot = document.createElement("div");
|
|
521
|
+
dot.className = "cm-ySelectionCaretDot";
|
|
522
|
+
const info = document.createElement("div");
|
|
523
|
+
info.className = "cm-ySelectionInfo";
|
|
524
|
+
info.innerText = this.name;
|
|
525
|
+
span.appendChild(document.createTextNode("\u2060"));
|
|
526
|
+
span.appendChild(dot);
|
|
527
|
+
span.appendChild(document.createTextNode("\u2060"));
|
|
528
|
+
span.appendChild(info);
|
|
529
|
+
span.appendChild(document.createTextNode("\u2060"));
|
|
530
|
+
return span;
|
|
531
|
+
}
|
|
532
|
+
eq(widget) {
|
|
533
|
+
return widget.color === this.color;
|
|
534
|
+
}
|
|
535
|
+
compare(widget) {
|
|
536
|
+
return widget.color === this.color;
|
|
537
|
+
}
|
|
538
|
+
updateDOM() {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
get estimatedHeight() {
|
|
542
|
+
return -1;
|
|
543
|
+
}
|
|
544
|
+
ignoreEvent() {
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
var styles = EditorView.baseTheme({
|
|
549
|
+
".cm-ySelection": {},
|
|
550
|
+
".cm-yLineSelection": {
|
|
551
|
+
padding: 0,
|
|
552
|
+
margin: "0px 2px 0px 4px"
|
|
793
553
|
},
|
|
794
|
-
{
|
|
795
|
-
|
|
796
|
-
|
|
554
|
+
".cm-ySelectionCaret": {
|
|
555
|
+
position: "relative",
|
|
556
|
+
borderLeft: "1px solid black",
|
|
557
|
+
borderRight: "1px solid black",
|
|
558
|
+
marginLeft: "-1px",
|
|
559
|
+
marginRight: "-1px",
|
|
560
|
+
boxSizing: "border-box",
|
|
561
|
+
display: "inline"
|
|
797
562
|
},
|
|
798
|
-
{
|
|
799
|
-
|
|
800
|
-
|
|
563
|
+
".cm-ySelectionCaretDot": {
|
|
564
|
+
borderRadius: "50%",
|
|
565
|
+
position: "absolute",
|
|
566
|
+
width: ".4em",
|
|
567
|
+
height: ".4em",
|
|
568
|
+
top: "-.2em",
|
|
569
|
+
left: "-.2em",
|
|
570
|
+
backgroundColor: "inherit",
|
|
571
|
+
transition: "transform .3s ease-in-out",
|
|
572
|
+
boxSizing: "border-box"
|
|
801
573
|
},
|
|
802
|
-
{
|
|
803
|
-
|
|
804
|
-
|
|
574
|
+
".cm-ySelectionCaret:hover > .cm-ySelectionCaretDot": {
|
|
575
|
+
transformOrigin: "bottom center",
|
|
576
|
+
transform: "scale(0)"
|
|
805
577
|
},
|
|
806
|
-
{
|
|
807
|
-
|
|
808
|
-
|
|
578
|
+
".cm-ySelectionInfo": {
|
|
579
|
+
position: "absolute",
|
|
580
|
+
top: "-1.05em",
|
|
581
|
+
left: "-1px",
|
|
582
|
+
fontSize: ".75em",
|
|
583
|
+
fontFamily: "serif",
|
|
584
|
+
fontStyle: "normal",
|
|
585
|
+
fontWeight: "normal",
|
|
586
|
+
lineHeight: "normal",
|
|
587
|
+
userSelect: "none",
|
|
588
|
+
color: "white",
|
|
589
|
+
paddingLeft: "2px",
|
|
590
|
+
paddingRight: "2px",
|
|
591
|
+
zIndex: 101,
|
|
592
|
+
transition: "opacity .3s ease-in-out",
|
|
593
|
+
backgroundColor: "inherit",
|
|
594
|
+
// these should be separate
|
|
595
|
+
opacity: 0,
|
|
596
|
+
transitionDelay: "0s",
|
|
597
|
+
whiteSpace: "nowrap"
|
|
598
|
+
},
|
|
599
|
+
".cm-ySelectionCaret:hover > .cm-ySelectionInfo": {
|
|
600
|
+
opacity: 1,
|
|
601
|
+
transitionDelay: "0s"
|
|
809
602
|
}
|
|
810
|
-
|
|
811
|
-
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
603
|
+
});
|
|
812
604
|
|
|
813
|
-
// packages/ui/react-ui-editor/src/
|
|
814
|
-
import
|
|
815
|
-
import
|
|
816
|
-
import {
|
|
817
|
-
import
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
605
|
+
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
606
|
+
import { closeBrackets } from "@codemirror/autocomplete";
|
|
607
|
+
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
608
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
609
|
+
import { drawSelection, EditorView as EditorView2, placeholder } from "@codemirror/view";
|
|
610
|
+
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
611
|
+
EditorView2.lineWrapping,
|
|
612
|
+
// TODO(burdon): Compare with minimalSetup.
|
|
613
|
+
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
614
|
+
bracketMatching(),
|
|
615
|
+
closeBrackets(),
|
|
616
|
+
drawSelection(),
|
|
617
|
+
_placeholder && placeholder(_placeholder),
|
|
618
|
+
// TODO(burdon): Is this required?
|
|
619
|
+
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
620
|
+
].filter(Boolean);
|
|
621
|
+
|
|
622
|
+
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
623
|
+
import { EditorView as EditorView3, keymap as keymap2 } from "@codemirror/view";
|
|
624
|
+
import defaultsDeep from "lodash.defaultsdeep";
|
|
625
|
+
import { invariant } from "@dxos/invariant";
|
|
626
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
627
|
+
var defaultOptions = {
|
|
628
|
+
effect: 2,
|
|
629
|
+
maxParticles: 200,
|
|
630
|
+
particleGravity: 0.08,
|
|
631
|
+
particleAlphaFadeout: 0.996,
|
|
632
|
+
particleSize: {
|
|
633
|
+
min: 2,
|
|
634
|
+
max: 8
|
|
635
|
+
},
|
|
636
|
+
particleNumRange: {
|
|
637
|
+
min: 5,
|
|
638
|
+
max: 10
|
|
639
|
+
},
|
|
640
|
+
particleVelocityRange: {
|
|
641
|
+
x: [
|
|
642
|
+
-1,
|
|
643
|
+
1
|
|
644
|
+
],
|
|
645
|
+
y: [
|
|
646
|
+
-3.5,
|
|
647
|
+
-1.5
|
|
648
|
+
]
|
|
649
|
+
},
|
|
650
|
+
particleShrinkRate: 0.95,
|
|
651
|
+
shakeIntensity: 5
|
|
652
|
+
};
|
|
653
|
+
var blast = (options = defaultOptions) => {
|
|
654
|
+
let blaster;
|
|
655
|
+
let last = 0;
|
|
656
|
+
const getPoint = (view, pos) => {
|
|
657
|
+
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
658
|
+
const element = document.elementFromPoint(x, y);
|
|
659
|
+
const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
|
|
660
|
+
const point = {
|
|
661
|
+
x: x - left,
|
|
662
|
+
y: y - top
|
|
663
|
+
};
|
|
664
|
+
return {
|
|
665
|
+
element,
|
|
666
|
+
point
|
|
667
|
+
};
|
|
668
|
+
};
|
|
669
|
+
return [
|
|
670
|
+
// Cursor moved.
|
|
671
|
+
EditorView3.updateListener.of((update2) => {
|
|
672
|
+
if (blaster?.node !== update2.view.scrollDOM) {
|
|
673
|
+
if (blaster) {
|
|
674
|
+
blaster.destroy();
|
|
675
|
+
}
|
|
676
|
+
blaster = new Blaster(update2.view.scrollDOM, defaultsDeep({
|
|
677
|
+
particleGravity: 0.2,
|
|
678
|
+
particleShrinkRate: 0.995,
|
|
679
|
+
color: () => [
|
|
680
|
+
100 + Math.random() * 100,
|
|
681
|
+
0,
|
|
682
|
+
0
|
|
683
|
+
]
|
|
684
|
+
}, options, defaultOptions));
|
|
685
|
+
blaster.initialize();
|
|
686
|
+
blaster.start();
|
|
687
|
+
} else {
|
|
688
|
+
blaster.resize();
|
|
689
|
+
}
|
|
690
|
+
const current = update2.state.selection.main.head;
|
|
691
|
+
if (current !== last) {
|
|
692
|
+
last = current;
|
|
693
|
+
const { element, point } = getPoint(update2.view, current - 1);
|
|
694
|
+
if (element && point) {
|
|
695
|
+
blaster.spawn({
|
|
696
|
+
element,
|
|
697
|
+
point
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}),
|
|
702
|
+
keymap2.of([
|
|
703
|
+
{
|
|
704
|
+
any: (_, event) => {
|
|
705
|
+
if (blaster) {
|
|
706
|
+
if (event.key === "Enter" && event.shiftKey) {
|
|
707
|
+
blaster.shake({
|
|
708
|
+
time: 0.8
|
|
709
|
+
});
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
])
|
|
717
|
+
];
|
|
718
|
+
};
|
|
719
|
+
var Blaster = class {
|
|
720
|
+
constructor(_node, _options) {
|
|
721
|
+
this._node = _node;
|
|
722
|
+
this._options = _options;
|
|
723
|
+
this._running = false;
|
|
724
|
+
this._shakeTime = 0;
|
|
725
|
+
this._shakeTimeMax = 0;
|
|
726
|
+
this._particles = [];
|
|
727
|
+
this._particlePointer = 0;
|
|
728
|
+
this._lastPoint = {
|
|
729
|
+
x: 0,
|
|
730
|
+
y: 0
|
|
731
|
+
};
|
|
732
|
+
this.shake = throttle(({ time }) => {
|
|
733
|
+
this._shakeTime = this._shakeTimeMax || time;
|
|
734
|
+
this._shakeTimeMax = time;
|
|
735
|
+
}, 100);
|
|
736
|
+
this.spawn = throttle(({ element, point }) => {
|
|
737
|
+
const color = getRGBComponents(element, this._options.color);
|
|
738
|
+
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
739
|
+
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
740
|
+
this._lastPoint = point;
|
|
741
|
+
for (let i = numParticles; i--; i > 0) {
|
|
742
|
+
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
743
|
+
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
744
|
+
}
|
|
745
|
+
}, 100);
|
|
746
|
+
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
845
747
|
}
|
|
846
|
-
get
|
|
847
|
-
return this.
|
|
748
|
+
get node() {
|
|
749
|
+
return this._node;
|
|
848
750
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
removed,
|
|
854
|
-
origin
|
|
855
|
-
}, {
|
|
856
|
-
F: __dxlog_file3,
|
|
857
|
-
L: 67,
|
|
751
|
+
initialize() {
|
|
752
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
753
|
+
F: __dxlog_file2,
|
|
754
|
+
L: 138,
|
|
858
755
|
S: this,
|
|
859
|
-
|
|
756
|
+
A: [
|
|
757
|
+
"!this._canvas && !this._ctx",
|
|
758
|
+
""
|
|
759
|
+
]
|
|
860
760
|
});
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
761
|
+
this._canvas = document.createElement("canvas");
|
|
762
|
+
this._canvas.id = "code-blast-canvas";
|
|
763
|
+
this._canvas.style.position = "absolute";
|
|
764
|
+
this._canvas.style.zIndex = "0";
|
|
765
|
+
this._canvas.style.pointerEvents = "none";
|
|
766
|
+
this._ctx = this._canvas.getContext("2d");
|
|
767
|
+
const parent = this._node.parentElement?.parentElement;
|
|
768
|
+
parent?.appendChild(this._canvas);
|
|
769
|
+
this.resize();
|
|
866
770
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
771
|
+
destroy() {
|
|
772
|
+
this.stop();
|
|
773
|
+
if (this._canvas) {
|
|
774
|
+
this._canvas.remove();
|
|
775
|
+
this._canvas = void 0;
|
|
776
|
+
this._ctx = void 0;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
resize() {
|
|
780
|
+
if (this._node.parentElement && this._canvas) {
|
|
781
|
+
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
782
|
+
this._canvas.style.top = `${y}px`;
|
|
783
|
+
this._canvas.style.left = `${x}px`;
|
|
784
|
+
this._canvas.width = width;
|
|
785
|
+
this._canvas.height = height;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
start() {
|
|
789
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
790
|
+
F: __dxlog_file2,
|
|
791
|
+
L: 177,
|
|
871
792
|
S: this,
|
|
872
|
-
|
|
793
|
+
A: [
|
|
794
|
+
"this._canvas && this._ctx",
|
|
795
|
+
""
|
|
796
|
+
]
|
|
873
797
|
});
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
798
|
+
this._running = true;
|
|
799
|
+
this.loop();
|
|
800
|
+
}
|
|
801
|
+
stop() {
|
|
802
|
+
this._running = false;
|
|
803
|
+
this._node.style.transform = "translate(0px, 0px)";
|
|
804
|
+
}
|
|
805
|
+
loop() {
|
|
806
|
+
if (!this._running || !this._canvas || !this._ctx) {
|
|
807
|
+
return;
|
|
878
808
|
}
|
|
809
|
+
this._ctx.clearRect(0, 0, this._canvas.width ?? 0, this._canvas.height ?? 0);
|
|
810
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
811
|
+
this._lastTime ??= now;
|
|
812
|
+
const dt = (now - this._lastTime) / 1e3;
|
|
813
|
+
this._lastTime = now;
|
|
814
|
+
if (this._shakeTime > 0) {
|
|
815
|
+
this._shakeTime -= dt;
|
|
816
|
+
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
817
|
+
const shakeX = random(-magnitude, magnitude);
|
|
818
|
+
const shakeY = random(-magnitude, magnitude);
|
|
819
|
+
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
820
|
+
}
|
|
821
|
+
this.drawParticles();
|
|
822
|
+
requestAnimationFrame(this.loop.bind(this));
|
|
879
823
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
switch (messageType) {
|
|
886
|
-
case messageAwareness: {
|
|
887
|
-
awarenessProtocol.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
888
|
-
break;
|
|
889
|
-
}
|
|
890
|
-
case messageQueryAwareness: {
|
|
891
|
-
encoding.writeVarUint(encoder, messageAwareness);
|
|
892
|
-
encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
893
|
-
sendReply = true;
|
|
894
|
-
break;
|
|
824
|
+
drawParticles() {
|
|
825
|
+
for (let i = this._particles.length; i--; i > 0) {
|
|
826
|
+
const particle = this._particles[i];
|
|
827
|
+
if (!particle) {
|
|
828
|
+
continue;
|
|
895
829
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
return encoder;
|
|
830
|
+
if (particle.alpha < 0.01 || particle.size <= 0.5) {
|
|
831
|
+
continue;
|
|
899
832
|
}
|
|
833
|
+
this._effect.update(this._ctx, particle);
|
|
900
834
|
}
|
|
901
|
-
|
|
902
|
-
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
var Effect = class {
|
|
838
|
+
constructor(_options) {
|
|
839
|
+
this._options = _options;
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
var Effect1 = class extends Effect {
|
|
843
|
+
create(x, y, color) {
|
|
844
|
+
return {
|
|
845
|
+
x,
|
|
846
|
+
y: y + 10,
|
|
847
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
848
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
849
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
850
|
+
color,
|
|
851
|
+
alpha: 1
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
update(ctx, particle) {
|
|
855
|
+
particle.vy += this._options.particleGravity;
|
|
856
|
+
particle.x += particle.vx;
|
|
857
|
+
particle.y += particle.vy;
|
|
858
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
859
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
860
|
+
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
var Effect2 = class extends Effect {
|
|
864
|
+
create(x, y, color) {
|
|
865
|
+
return {
|
|
866
|
+
x,
|
|
867
|
+
y: y + 10,
|
|
868
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
869
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
870
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
871
|
+
color,
|
|
872
|
+
alpha: 1,
|
|
873
|
+
theta: random(0, 360) * Math.PI / 180,
|
|
874
|
+
drag: 0.92,
|
|
875
|
+
wander: 0.15
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
update(ctx, particle) {
|
|
879
|
+
particle.vy += this._options.particleGravity;
|
|
880
|
+
particle.x += particle.vx;
|
|
881
|
+
particle.y += particle.vy;
|
|
882
|
+
particle.vx *= particle.drag;
|
|
883
|
+
particle.vy *= particle.drag;
|
|
884
|
+
particle.theta += random(-0.5, 0.5);
|
|
885
|
+
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
886
|
+
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
887
|
+
particle.size *= this._options.particleShrinkRate;
|
|
888
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
889
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
890
|
+
ctx.beginPath();
|
|
891
|
+
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
892
|
+
ctx.fill();
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
function throttle(callback, limit) {
|
|
896
|
+
let wait = false;
|
|
897
|
+
return function(...args) {
|
|
898
|
+
if (!wait) {
|
|
899
|
+
callback.apply(this, args);
|
|
900
|
+
wait = true;
|
|
901
|
+
setTimeout(() => {
|
|
902
|
+
wait = false;
|
|
903
|
+
}, limit);
|
|
903
904
|
}
|
|
904
|
-
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
var getRGBComponents = (node, color) => {
|
|
908
|
+
if (typeof color === "function") {
|
|
909
|
+
return color();
|
|
905
910
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
911
|
+
const bgColor = getComputedStyle(node).color;
|
|
912
|
+
if (bgColor) {
|
|
913
|
+
const x = bgColor.match(/(\d+), (\d+), (\d+)/)?.slice(1);
|
|
914
|
+
if (x) {
|
|
915
|
+
return x;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return [
|
|
919
|
+
50,
|
|
920
|
+
50,
|
|
921
|
+
50
|
|
922
|
+
];
|
|
923
|
+
};
|
|
924
|
+
var random = (min, max) => {
|
|
925
|
+
if (!max) {
|
|
926
|
+
max = min;
|
|
927
|
+
min = 0;
|
|
928
|
+
}
|
|
929
|
+
return min + ~~(Math.random() * (max - min + 1));
|
|
930
|
+
};
|
|
931
|
+
|
|
932
|
+
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
933
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView4, Decoration as Decoration2 } from "@codemirror/view";
|
|
934
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
935
|
+
|
|
936
|
+
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
937
|
+
import * as random2 from "lib0/random";
|
|
938
|
+
var cursorColors = [
|
|
939
|
+
{
|
|
940
|
+
color: "#30bced",
|
|
941
|
+
light: "#30bced33"
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
color: "#6eeb83",
|
|
945
|
+
light: "#6eeb8333"
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
color: "#ffbc42",
|
|
949
|
+
light: "#ffbc4233"
|
|
950
|
+
},
|
|
951
|
+
{
|
|
952
|
+
color: "#ecd444",
|
|
953
|
+
light: "#ecd44433"
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
color: "#ee6352",
|
|
957
|
+
light: "#ee635233"
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
color: "#9ac2c9",
|
|
961
|
+
light: "#9ac2c933"
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
color: "#8acb88",
|
|
965
|
+
light: "#8acb8833"
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
color: "#1be7ff",
|
|
969
|
+
light: "#1be7ff33"
|
|
910
970
|
}
|
|
971
|
+
];
|
|
972
|
+
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
973
|
+
|
|
974
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
975
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
976
|
+
var headings = {
|
|
977
|
+
1: [
|
|
978
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
979
|
+
"-ml-[10px]"
|
|
980
|
+
],
|
|
981
|
+
2: [
|
|
982
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
983
|
+
"-ml-[8px]"
|
|
984
|
+
],
|
|
985
|
+
3: [
|
|
986
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
987
|
+
"-ml-[7px]"
|
|
988
|
+
],
|
|
989
|
+
4: [
|
|
990
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
991
|
+
"-ml-[6px]"
|
|
992
|
+
],
|
|
993
|
+
5: [
|
|
994
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
995
|
+
"-ml-[5px]"
|
|
996
|
+
],
|
|
997
|
+
6: [
|
|
998
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
999
|
+
"-ml-[4px]"
|
|
1000
|
+
]
|
|
1001
|
+
};
|
|
1002
|
+
var heading = (level, readonly) => {
|
|
1003
|
+
const [style, offset] = headings[level];
|
|
1004
|
+
return mx(style, readonly && offset);
|
|
911
1005
|
};
|
|
1006
|
+
var light = "text-neutral-200 dark:text-neutral-800";
|
|
1007
|
+
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
1008
|
+
var bold = "font-bold";
|
|
1009
|
+
var italic = "italic";
|
|
1010
|
+
var strikethrough = "line-through";
|
|
1011
|
+
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
1012
|
+
var codeMark = "font-mono text-primary-500";
|
|
1013
|
+
var inlineUrl = mx(code, "px-1");
|
|
1014
|
+
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
912
1015
|
|
|
913
|
-
// packages/ui/react-ui-editor/src/
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1016
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1017
|
+
import get2 from "lodash.get";
|
|
1018
|
+
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1019
|
+
var tokens = tailwindConfig({}).theme;
|
|
1020
|
+
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1021
|
+
|
|
1022
|
+
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1023
|
+
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1024
|
+
var styles2 = EditorView4.baseTheme({
|
|
1025
|
+
"& .cm-codeblock": {
|
|
1026
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1027
|
+
},
|
|
1028
|
+
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1029
|
+
background: getToken("extend.colors.neutral.50")
|
|
1030
|
+
},
|
|
1031
|
+
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1032
|
+
background: getToken("extend.colors.neutral.850")
|
|
1033
|
+
},
|
|
1034
|
+
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1035
|
+
display: "block",
|
|
1036
|
+
paddingInline: "4px !important"
|
|
1037
|
+
},
|
|
1038
|
+
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1039
|
+
paddingTop: "4px !important",
|
|
1040
|
+
borderTopLeftRadius: "4px",
|
|
1041
|
+
borderTopRightRadius: "4px"
|
|
1042
|
+
},
|
|
1043
|
+
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1044
|
+
paddingBottom: "4px !important",
|
|
1045
|
+
borderBottomLeftRadius: "4px",
|
|
1046
|
+
borderBottomRightRadius: "4px"
|
|
1047
|
+
}
|
|
918
1048
|
});
|
|
919
|
-
var
|
|
920
|
-
const
|
|
921
|
-
const
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
]);
|
|
927
|
-
return model;
|
|
1049
|
+
var getLineRange = (lines, from, to) => {
|
|
1050
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1051
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1052
|
+
return [
|
|
1053
|
+
start,
|
|
1054
|
+
end
|
|
1055
|
+
];
|
|
928
1056
|
};
|
|
929
|
-
var
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1057
|
+
var code2 = () => {
|
|
1058
|
+
const getDecorations = (view) => {
|
|
1059
|
+
const decorations = [];
|
|
1060
|
+
if (view.state.readOnly) {
|
|
1061
|
+
const text = view.state.doc.sliceString(0);
|
|
1062
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1063
|
+
const blocks = view.viewportLineBlocks;
|
|
1064
|
+
for (const match of matches) {
|
|
1065
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1066
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1067
|
+
const block = blocks[i];
|
|
1068
|
+
decorations.push(Decoration2.line({
|
|
1069
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1070
|
+
}).range(block.from));
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
936
1073
|
}
|
|
937
|
-
return
|
|
938
|
-
}
|
|
939
|
-
};
|
|
940
|
-
var createYjsModel = ({ identity, space, text }) => {
|
|
941
|
-
invariant2(text?.doc && text?.content, void 0, {
|
|
942
|
-
F: __dxlog_file4,
|
|
943
|
-
L: 97,
|
|
944
|
-
S: void 0,
|
|
945
|
-
A: [
|
|
946
|
-
"text?.doc && text?.content",
|
|
947
|
-
""
|
|
948
|
-
]
|
|
949
|
-
});
|
|
950
|
-
const provider = space ? new SpaceAwarenessProvider({
|
|
951
|
-
space,
|
|
952
|
-
doc: text.doc,
|
|
953
|
-
channel: `yjs.awareness.${text.id}`
|
|
954
|
-
}) : void 0;
|
|
955
|
-
const model = {
|
|
956
|
-
id: text.doc.guid,
|
|
957
|
-
content: text.content,
|
|
958
|
-
text: () => text.content.toString(),
|
|
959
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
960
|
-
getCursorFromRange: (range) => {
|
|
961
|
-
const from = Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
962
|
-
const to = Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
963
|
-
return [
|
|
964
|
-
arrayToString(from),
|
|
965
|
-
arrayToString(to)
|
|
966
|
-
].join(":");
|
|
967
|
-
},
|
|
968
|
-
getRangeFromCursor: (cursor) => {
|
|
969
|
-
const parts = cursor.split(":");
|
|
970
|
-
const from = Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(parts[0])), text.doc);
|
|
971
|
-
const to = Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(parts[1])), text.doc);
|
|
972
|
-
return {
|
|
973
|
-
from: from.index,
|
|
974
|
-
to: to.index
|
|
975
|
-
};
|
|
976
|
-
},
|
|
977
|
-
extension: [
|
|
978
|
-
yCollab(text.content, provider?.awareness),
|
|
979
|
-
modelState.init(() => model)
|
|
980
|
-
],
|
|
981
|
-
awareness: provider?.awareness,
|
|
982
|
-
peer: identity ? {
|
|
983
|
-
id: identity.identityKey.toHex(),
|
|
984
|
-
name: identity.profile?.displayName
|
|
985
|
-
} : void 0
|
|
986
|
-
};
|
|
987
|
-
return model;
|
|
988
|
-
};
|
|
989
|
-
var createAutomergeModel = ({ identity, text }) => {
|
|
990
|
-
const obj = text;
|
|
991
|
-
const doc = getRawDoc(obj, [
|
|
992
|
-
obj.field
|
|
993
|
-
]);
|
|
994
|
-
const model = {
|
|
995
|
-
id: obj.id,
|
|
996
|
-
content: doc,
|
|
997
|
-
text: () => get2(doc.handle.docSync(), doc.path),
|
|
998
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
999
|
-
extension: [
|
|
1000
|
-
automergePlugin(doc.handle, doc.path),
|
|
1001
|
-
modelState.init(() => model)
|
|
1002
|
-
],
|
|
1003
|
-
peer: identity ? {
|
|
1004
|
-
id: identity.identityKey.toHex(),
|
|
1005
|
-
name: identity.profile?.displayName
|
|
1006
|
-
} : void 0
|
|
1074
|
+
return Decoration2.set(decorations);
|
|
1007
1075
|
};
|
|
1008
|
-
return
|
|
1076
|
+
return [
|
|
1077
|
+
ViewPlugin3.fromClass(class {
|
|
1078
|
+
constructor(view) {
|
|
1079
|
+
this.decorations = getDecorations(view);
|
|
1080
|
+
}
|
|
1081
|
+
update(update2) {
|
|
1082
|
+
if (update2.docChanged || update2.viewportChanged) {
|
|
1083
|
+
this.decorations = getDecorations(update2.view);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}, {
|
|
1087
|
+
decorations: (value) => value.decorations
|
|
1088
|
+
}),
|
|
1089
|
+
styles2
|
|
1090
|
+
];
|
|
1009
1091
|
};
|
|
1010
1092
|
|
|
1011
|
-
// packages/ui/react-ui-editor/src/
|
|
1012
|
-
|
|
1013
|
-
|
|
1093
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1094
|
+
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1095
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1096
|
+
import sortBy from "lodash.sortby";
|
|
1097
|
+
import { debounce } from "@dxos/async";
|
|
1098
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1099
|
+
import { log as log2 } from "@dxos/log";
|
|
1100
|
+
import { nonNullable } from "@dxos/util";
|
|
1101
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1102
|
+
var styles3 = EditorView5.baseTheme({
|
|
1014
1103
|
"& .cm-bookmark": {
|
|
1015
1104
|
cursor: "pointer",
|
|
1016
1105
|
margin: "4px",
|
|
@@ -1021,28 +1110,44 @@ var styles2 = EditorView4.baseTheme({
|
|
|
1021
1110
|
backgroundColor: "orange"
|
|
1022
1111
|
},
|
|
1023
1112
|
"& .cm-comment": {
|
|
1024
|
-
backgroundColor: "yellow"
|
|
1113
|
+
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1025
1114
|
},
|
|
1026
1115
|
"& .cm-comment-active": {
|
|
1027
|
-
backgroundColor: "
|
|
1116
|
+
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1028
1117
|
}
|
|
1029
1118
|
});
|
|
1030
1119
|
var marks = {
|
|
1031
|
-
highlight:
|
|
1120
|
+
highlight: Decoration3.mark({
|
|
1032
1121
|
class: "cm-comment"
|
|
1033
1122
|
}),
|
|
1034
|
-
highlightActive:
|
|
1123
|
+
highlightActive: Decoration3.mark({
|
|
1035
1124
|
class: "cm-comment-active"
|
|
1036
1125
|
})
|
|
1037
1126
|
};
|
|
1127
|
+
var setFocus = (view, thread) => {
|
|
1128
|
+
const range = view.state.field(commentsStateField).ranges.find((range2) => range2.id === thread);
|
|
1129
|
+
if (!range) {
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
view.dispatch({
|
|
1133
|
+
effects: setSelection.of({
|
|
1134
|
+
active: thread
|
|
1135
|
+
}),
|
|
1136
|
+
selection: {
|
|
1137
|
+
anchor: range.from
|
|
1138
|
+
},
|
|
1139
|
+
scrollIntoView: true
|
|
1140
|
+
});
|
|
1141
|
+
};
|
|
1038
1142
|
var setCommentRange = StateEffect2.define();
|
|
1039
1143
|
var setSelection = StateEffect2.define();
|
|
1040
1144
|
var setCommentState = StateEffect2.define();
|
|
1041
|
-
var commentsStateField =
|
|
1145
|
+
var commentsStateField = StateField2.define({
|
|
1042
1146
|
create: () => ({
|
|
1043
1147
|
ranges: []
|
|
1044
1148
|
}),
|
|
1045
1149
|
update: (value, tr) => {
|
|
1150
|
+
const cursorConverter3 = tr.state.facet(CursorConverter);
|
|
1046
1151
|
for (const effect of tr.effects) {
|
|
1047
1152
|
if (effect.is(setSelection)) {
|
|
1048
1153
|
return {
|
|
@@ -1051,14 +1156,14 @@ var commentsStateField = StateField3.define({
|
|
|
1051
1156
|
};
|
|
1052
1157
|
}
|
|
1053
1158
|
if (effect.is(setCommentRange)) {
|
|
1054
|
-
const {
|
|
1159
|
+
const { comments: comments2 } = effect.value;
|
|
1055
1160
|
const ranges = comments2.map((comment) => {
|
|
1056
|
-
const range =
|
|
1057
|
-
return {
|
|
1161
|
+
const range = getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1162
|
+
return range && {
|
|
1058
1163
|
...comment,
|
|
1059
1164
|
...range
|
|
1060
1165
|
};
|
|
1061
|
-
});
|
|
1166
|
+
}).filter(nonNullable);
|
|
1062
1167
|
return {
|
|
1063
1168
|
...value,
|
|
1064
1169
|
ranges
|
|
@@ -1071,7 +1176,7 @@ var commentsStateField = StateField3.define({
|
|
|
1071
1176
|
return value;
|
|
1072
1177
|
}
|
|
1073
1178
|
});
|
|
1074
|
-
var highlightDecorations =
|
|
1179
|
+
var highlightDecorations = EditorView5.decorations.compute([
|
|
1075
1180
|
commentsStateField
|
|
1076
1181
|
], (state) => {
|
|
1077
1182
|
const { active, ranges } = state.field(commentsStateField);
|
|
@@ -1089,17 +1194,17 @@ var highlightDecorations = EditorView4.decorations.compute([
|
|
|
1089
1194
|
return marks.highlight.range(range.from, range.to);
|
|
1090
1195
|
}
|
|
1091
1196
|
}).filter(nonNullable) ?? [];
|
|
1092
|
-
return
|
|
1197
|
+
return Decoration3.set(decorations);
|
|
1093
1198
|
});
|
|
1094
|
-
var BookmarkWidget = class extends
|
|
1199
|
+
var BookmarkWidget = class extends WidgetType2 {
|
|
1095
1200
|
constructor(_anchor, _id, _handleClick) {
|
|
1096
1201
|
super();
|
|
1097
1202
|
this._anchor = _anchor;
|
|
1098
1203
|
this._id = _id;
|
|
1099
1204
|
this._handleClick = _handleClick;
|
|
1100
|
-
|
|
1101
|
-
F:
|
|
1102
|
-
L:
|
|
1205
|
+
invariant2(this._id, void 0, {
|
|
1206
|
+
F: __dxlog_file3,
|
|
1207
|
+
L: 168,
|
|
1103
1208
|
S: this,
|
|
1104
1209
|
A: [
|
|
1105
1210
|
"this._id",
|
|
@@ -1123,9 +1228,10 @@ var BookmarkWidget = class extends WidgetType {
|
|
|
1123
1228
|
var comments = (options = {}) => {
|
|
1124
1229
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1125
1230
|
const createCommentThread = (view) => {
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1231
|
+
const cursorConverter3 = view.state.facet(CursorConverter);
|
|
1232
|
+
invariant2(options.onCreate, void 0, {
|
|
1233
|
+
F: __dxlog_file3,
|
|
1234
|
+
L: 224,
|
|
1129
1235
|
S: void 0,
|
|
1130
1236
|
A: [
|
|
1131
1237
|
"options.onCreate",
|
|
@@ -1136,8 +1242,7 @@ var comments = (options = {}) => {
|
|
|
1136
1242
|
if (from === to) {
|
|
1137
1243
|
return false;
|
|
1138
1244
|
}
|
|
1139
|
-
const
|
|
1140
|
-
const relPos = model?.getCursorFromRange?.({
|
|
1245
|
+
const relPos = getCursorFromRange(cursorConverter3, {
|
|
1141
1246
|
from,
|
|
1142
1247
|
to
|
|
1143
1248
|
});
|
|
@@ -1169,7 +1274,7 @@ var comments = (options = {}) => {
|
|
|
1169
1274
|
}
|
|
1170
1275
|
return false;
|
|
1171
1276
|
};
|
|
1172
|
-
const bookmarksViewPlugin =
|
|
1277
|
+
const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
|
|
1173
1278
|
static {
|
|
1174
1279
|
// Match markdown footnotes (option).
|
|
1175
1280
|
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
@@ -1177,7 +1282,7 @@ var comments = (options = {}) => {
|
|
|
1177
1282
|
regexp: /\[\^(\w+)\]/g,
|
|
1178
1283
|
decoration: (match, view, pos) => {
|
|
1179
1284
|
const id = match[1];
|
|
1180
|
-
return
|
|
1285
|
+
return Decoration3.replace({
|
|
1181
1286
|
id,
|
|
1182
1287
|
widget: new BookmarkWidget(pos, id)
|
|
1183
1288
|
});
|
|
@@ -1187,20 +1292,20 @@ var comments = (options = {}) => {
|
|
|
1187
1292
|
constructor(view) {
|
|
1188
1293
|
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
1189
1294
|
}
|
|
1190
|
-
update(
|
|
1191
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(
|
|
1295
|
+
update(update2) {
|
|
1296
|
+
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update2, this.bookmarks);
|
|
1192
1297
|
}
|
|
1193
1298
|
}, {
|
|
1194
1299
|
decorations: (instance) => instance.bookmarks,
|
|
1195
|
-
provide: (plugin) =>
|
|
1196
|
-
return view.plugin(plugin)?.bookmarks ||
|
|
1300
|
+
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1301
|
+
return view.plugin(plugin)?.bookmarks || Decoration3.none;
|
|
1197
1302
|
})
|
|
1198
1303
|
});
|
|
1199
1304
|
return [
|
|
1200
1305
|
bookmarksViewPlugin,
|
|
1201
1306
|
commentsStateField,
|
|
1202
1307
|
highlightDecorations,
|
|
1203
|
-
|
|
1308
|
+
styles3,
|
|
1204
1309
|
//
|
|
1205
1310
|
// Keymap.
|
|
1206
1311
|
//
|
|
@@ -1243,37 +1348,28 @@ var comments = (options = {}) => {
|
|
|
1243
1348
|
// Monitor cursor movement and text updates.
|
|
1244
1349
|
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1245
1350
|
//
|
|
1246
|
-
|
|
1351
|
+
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1352
|
+
const cursorConverter3 = view.state.facet(CursorConverter);
|
|
1247
1353
|
{
|
|
1248
1354
|
let mod = false;
|
|
1249
|
-
const model = state.field(modelState);
|
|
1250
1355
|
const { active, ranges } = state.field(commentsStateField);
|
|
1251
1356
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1252
|
-
invariant3(model, void 0, {
|
|
1253
|
-
F: __dxlog_file5,
|
|
1254
|
-
L: 334,
|
|
1255
|
-
S: void 0,
|
|
1256
|
-
A: [
|
|
1257
|
-
"model",
|
|
1258
|
-
""
|
|
1259
|
-
]
|
|
1260
|
-
});
|
|
1261
1357
|
ranges.forEach((range) => {
|
|
1262
1358
|
if (from2 === to2) {
|
|
1263
|
-
const newRange =
|
|
1264
|
-
if (newRange.to - newRange.from === 0) {
|
|
1265
|
-
|
|
1359
|
+
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1360
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1361
|
+
log2.info("deleted comment", {
|
|
1266
1362
|
thread: range.id
|
|
1267
1363
|
}, {
|
|
1268
|
-
F:
|
|
1269
|
-
L:
|
|
1364
|
+
F: __dxlog_file3,
|
|
1365
|
+
L: 358,
|
|
1270
1366
|
S: void 0,
|
|
1271
1367
|
C: (f, a) => f(...a)
|
|
1272
1368
|
});
|
|
1273
1369
|
}
|
|
1274
1370
|
}
|
|
1275
1371
|
if (from <= range.to) {
|
|
1276
|
-
const newRange =
|
|
1372
|
+
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1277
1373
|
Object.assign(range, newRange);
|
|
1278
1374
|
mod = true;
|
|
1279
1375
|
}
|
|
@@ -1322,18 +1418,34 @@ var comments = (options = {}) => {
|
|
|
1322
1418
|
})
|
|
1323
1419
|
];
|
|
1324
1420
|
};
|
|
1421
|
+
var getCursorFromRange = (cursorConverter3, range) => {
|
|
1422
|
+
const from = cursorConverter3.toCursor(range.from);
|
|
1423
|
+
const to = cursorConverter3.toCursor(range.to, -1);
|
|
1424
|
+
return [
|
|
1425
|
+
from,
|
|
1426
|
+
to
|
|
1427
|
+
].join(":");
|
|
1428
|
+
};
|
|
1429
|
+
var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
1430
|
+
const parts = cursor.split(":");
|
|
1431
|
+
const from = cursorConverter3.fromCursor(parts[0]);
|
|
1432
|
+
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1433
|
+
return from !== void 0 && to !== void 0 ? {
|
|
1434
|
+
from,
|
|
1435
|
+
to
|
|
1436
|
+
} : void 0;
|
|
1437
|
+
};
|
|
1325
1438
|
|
|
1326
|
-
// packages/ui/react-ui-editor/src/
|
|
1327
|
-
import { Decoration as
|
|
1328
|
-
|
|
1329
|
-
var styles3 = EditorView5.baseTheme({
|
|
1439
|
+
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1440
|
+
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin5, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1441
|
+
var styles4 = EditorView6.baseTheme({
|
|
1330
1442
|
"& .cm-hr": {
|
|
1331
1443
|
// TODO(burdon): ???
|
|
1332
1444
|
// Note that block-level decorations should not have vertical margins,
|
|
1333
|
-
borderBottom: `1px solid ${
|
|
1445
|
+
borderBottom: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1334
1446
|
}
|
|
1335
1447
|
});
|
|
1336
|
-
var HorizontalRuleWidget = class extends
|
|
1448
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
1337
1449
|
constructor(_pos) {
|
|
1338
1450
|
super();
|
|
1339
1451
|
this._pos = _pos;
|
|
@@ -1349,41 +1461,63 @@ var HorizontalRuleWidget = class extends WidgetType2 {
|
|
|
1349
1461
|
};
|
|
1350
1462
|
var placeholderMatcher = new MatchDecorator2({
|
|
1351
1463
|
regexp: /^---$/g,
|
|
1352
|
-
decoration: (match, view, pos) =>
|
|
1464
|
+
decoration: (match, view, pos) => Decoration4.replace({
|
|
1353
1465
|
widget: new HorizontalRuleWidget(pos)
|
|
1354
1466
|
})
|
|
1355
1467
|
});
|
|
1356
1468
|
var hr = () => [
|
|
1357
|
-
|
|
1358
|
-
|
|
1469
|
+
styles4,
|
|
1470
|
+
ViewPlugin5.fromClass(class {
|
|
1359
1471
|
constructor(view) {
|
|
1360
1472
|
this.rules = placeholderMatcher.createDeco(view);
|
|
1361
1473
|
}
|
|
1362
|
-
update(
|
|
1363
|
-
this.rules = placeholderMatcher.updateDeco(
|
|
1474
|
+
update(update2) {
|
|
1475
|
+
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1364
1476
|
}
|
|
1365
1477
|
}, {
|
|
1366
1478
|
decorations: (instance) => instance.rules,
|
|
1367
1479
|
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1368
|
-
provide: (plugin) =>
|
|
1369
|
-
return view.plugin(plugin)?.rules ||
|
|
1480
|
+
provide: (plugin) => EditorView6.atomicRanges.of((view) => {
|
|
1481
|
+
return view.plugin(plugin)?.rules || Decoration4.none;
|
|
1370
1482
|
})
|
|
1371
1483
|
})
|
|
1372
1484
|
];
|
|
1373
1485
|
|
|
1374
|
-
// packages/ui/react-ui-editor/src/
|
|
1486
|
+
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1375
1487
|
import { syntaxTree } from "@codemirror/language";
|
|
1376
|
-
import {
|
|
1377
|
-
import { Decoration as
|
|
1488
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1489
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1378
1490
|
var image = (options = {}) => {
|
|
1379
|
-
return
|
|
1380
|
-
create: (state) =>
|
|
1381
|
-
|
|
1382
|
-
|
|
1491
|
+
return StateField3.define({
|
|
1492
|
+
create: (state) => {
|
|
1493
|
+
return Decoration5.set(buildDecorations(0, state.doc.length, state));
|
|
1494
|
+
},
|
|
1495
|
+
update: (value, tr) => {
|
|
1496
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1497
|
+
return value;
|
|
1498
|
+
}
|
|
1499
|
+
const cursor = tr.state.selection.main.head;
|
|
1500
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1501
|
+
let from = Math.min(cursor, oldCursor);
|
|
1502
|
+
let to = Math.max(cursor, oldCursor);
|
|
1503
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1504
|
+
from = Math.min(from, fromB);
|
|
1505
|
+
to = Math.max(to, toB);
|
|
1506
|
+
});
|
|
1507
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1508
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1509
|
+
return value.map(tr.changes).update({
|
|
1510
|
+
filterFrom: from,
|
|
1511
|
+
filterTo: to,
|
|
1512
|
+
filter: () => false,
|
|
1513
|
+
add: buildDecorations(from, to, tr.state)
|
|
1514
|
+
});
|
|
1515
|
+
},
|
|
1516
|
+
provide: (field) => EditorView7.decorations.from(field)
|
|
1383
1517
|
});
|
|
1384
1518
|
};
|
|
1385
|
-
var
|
|
1386
|
-
const
|
|
1519
|
+
var buildDecorations = (from, to, state) => {
|
|
1520
|
+
const decorations = [];
|
|
1387
1521
|
const cursor = state.selection.main.head;
|
|
1388
1522
|
syntaxTree(state).iterate({
|
|
1389
1523
|
enter: (node) => {
|
|
@@ -1392,22 +1526,23 @@ var update = (state, options) => {
|
|
|
1392
1526
|
if (urlNode) {
|
|
1393
1527
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1394
1528
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1395
|
-
|
|
1529
|
+
decorations.push(Decoration5.replace({
|
|
1396
1530
|
block: true,
|
|
1397
1531
|
widget: new ImageWidget(url)
|
|
1398
|
-
}));
|
|
1532
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1399
1533
|
}
|
|
1400
1534
|
}
|
|
1401
|
-
}
|
|
1535
|
+
},
|
|
1536
|
+
from,
|
|
1537
|
+
to
|
|
1402
1538
|
});
|
|
1403
|
-
return
|
|
1539
|
+
return decorations;
|
|
1404
1540
|
};
|
|
1405
|
-
var ImageWidget = class extends
|
|
1541
|
+
var ImageWidget = class extends WidgetType4 {
|
|
1406
1542
|
constructor(_url) {
|
|
1407
1543
|
super();
|
|
1408
1544
|
this._url = _url;
|
|
1409
1545
|
}
|
|
1410
|
-
// TODO(burdon): Does this need to be unique for each position?
|
|
1411
1546
|
eq(other) {
|
|
1412
1547
|
return this._url === other._url;
|
|
1413
1548
|
}
|
|
@@ -1415,22 +1550,29 @@ var ImageWidget = class extends WidgetType3 {
|
|
|
1415
1550
|
const img = document.createElement("img");
|
|
1416
1551
|
img.setAttribute("src", this._url);
|
|
1417
1552
|
img.setAttribute("class", "cm-image");
|
|
1553
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1418
1554
|
return img;
|
|
1419
1555
|
}
|
|
1420
1556
|
};
|
|
1421
1557
|
|
|
1422
|
-
// packages/ui/react-ui-editor/src/
|
|
1558
|
+
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1423
1559
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1424
|
-
import { RangeSetBuilder
|
|
1425
|
-
import { Decoration as
|
|
1560
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1561
|
+
import { Decoration as Decoration6, WidgetType as WidgetType5, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
1426
1562
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1427
|
-
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
1428
1563
|
var link = (options = {}) => {
|
|
1429
1564
|
const extensions = [
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1565
|
+
ViewPlugin6.fromClass(class {
|
|
1566
|
+
constructor(view) {
|
|
1567
|
+
this.decorations = buildDecorations2(view, options);
|
|
1568
|
+
}
|
|
1569
|
+
update(update2) {
|
|
1570
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1571
|
+
this.decorations = buildDecorations2(update2.view, options);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
}, {
|
|
1575
|
+
decorations: (v) => v.decorations
|
|
1434
1576
|
})
|
|
1435
1577
|
];
|
|
1436
1578
|
if (options.onHover) {
|
|
@@ -1438,35 +1580,25 @@ var link = (options = {}) => {
|
|
|
1438
1580
|
// https://codemirror.net/examples/tooltip
|
|
1439
1581
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1440
1582
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1441
|
-
hoverTooltip2((view, pos) => {
|
|
1442
|
-
const
|
|
1443
|
-
|
|
1444
|
-
let
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
match = void 0;
|
|
1450
|
-
break;
|
|
1451
|
-
}
|
|
1452
|
-
idx = text.indexOf(match[0]);
|
|
1453
|
-
if (p >= idx && p < idx + match[0].length) {
|
|
1454
|
-
break;
|
|
1455
|
-
}
|
|
1456
|
-
idx += match[0].length;
|
|
1457
|
-
} while (true);
|
|
1458
|
-
if (!match) {
|
|
1583
|
+
hoverTooltip2((view, pos, side) => {
|
|
1584
|
+
const syntax = syntaxTree2(view.state).resolveInner(pos, side);
|
|
1585
|
+
let link2 = null;
|
|
1586
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1587
|
+
link2 = node.name === "Link" ? node : null;
|
|
1588
|
+
}
|
|
1589
|
+
const url = link2 && link2.getChild("URL");
|
|
1590
|
+
if (!url || !link2) {
|
|
1459
1591
|
return null;
|
|
1460
1592
|
}
|
|
1461
|
-
const
|
|
1593
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1462
1594
|
return {
|
|
1463
|
-
pos:
|
|
1464
|
-
end:
|
|
1595
|
+
pos: link2.from,
|
|
1596
|
+
end: link2.to,
|
|
1465
1597
|
above: true,
|
|
1466
1598
|
create: () => {
|
|
1467
1599
|
const el = document.createElement("div");
|
|
1468
1600
|
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1469
|
-
options.onHover(el,
|
|
1601
|
+
options.onHover(el, urlText);
|
|
1470
1602
|
return {
|
|
1471
1603
|
dom: el,
|
|
1472
1604
|
offset: {
|
|
@@ -1481,15 +1613,14 @@ var link = (options = {}) => {
|
|
|
1481
1613
|
}
|
|
1482
1614
|
return extensions;
|
|
1483
1615
|
};
|
|
1484
|
-
var LinkButton = class extends
|
|
1485
|
-
constructor(
|
|
1616
|
+
var LinkButton = class extends WidgetType5 {
|
|
1617
|
+
constructor(_url, _onAttach) {
|
|
1486
1618
|
super();
|
|
1487
|
-
this._pos = _pos;
|
|
1488
1619
|
this._url = _url;
|
|
1489
1620
|
this._onAttach = _onAttach;
|
|
1490
1621
|
}
|
|
1491
1622
|
eq(other) {
|
|
1492
|
-
return this.
|
|
1623
|
+
return this._url === other._url;
|
|
1493
1624
|
}
|
|
1494
1625
|
toDOM(view) {
|
|
1495
1626
|
const el = document.createElement("span");
|
|
@@ -1497,7 +1628,7 @@ var LinkButton = class extends WidgetType4 {
|
|
|
1497
1628
|
return el;
|
|
1498
1629
|
}
|
|
1499
1630
|
};
|
|
1500
|
-
var LinkText = class extends
|
|
1631
|
+
var LinkText = class extends WidgetType5 {
|
|
1501
1632
|
constructor(_text, _url) {
|
|
1502
1633
|
super();
|
|
1503
1634
|
this._text = _text;
|
|
@@ -1526,37 +1657,42 @@ var LinkText = class extends WidgetType4 {
|
|
|
1526
1657
|
return link2;
|
|
1527
1658
|
}
|
|
1528
1659
|
};
|
|
1529
|
-
var
|
|
1530
|
-
const builder = new
|
|
1660
|
+
var buildDecorations2 = (view, options) => {
|
|
1661
|
+
const builder = new RangeSetBuilder();
|
|
1662
|
+
const { state } = view;
|
|
1531
1663
|
const cursor = state.selection.main.head;
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1664
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1665
|
+
syntaxTree2(state).iterate({
|
|
1666
|
+
enter: (node) => {
|
|
1667
|
+
if (node.name === "Link") {
|
|
1668
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
1669
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1670
|
+
const urlNode = node.node.getChild("URL");
|
|
1671
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1672
|
+
if (!url) {
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1676
|
+
builder.add(node.from, node.to, Decoration6.replace({
|
|
1677
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
1678
|
+
}));
|
|
1679
|
+
}
|
|
1680
|
+
if (options.onRender) {
|
|
1681
|
+
builder.add(node.to, node.to, Decoration6.replace({
|
|
1682
|
+
widget: new LinkButton(url, options.onRender)
|
|
1683
|
+
}));
|
|
1684
|
+
}
|
|
1540
1685
|
return false;
|
|
1541
1686
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
if (options.onRender) {
|
|
1548
|
-
builder.add(node.to, node.to, Decoration5.replace({
|
|
1549
|
-
widget: new LinkButton(node.from, url, options.onRender)
|
|
1550
|
-
}));
|
|
1551
|
-
}
|
|
1552
|
-
return false;
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
});
|
|
1687
|
+
},
|
|
1688
|
+
from,
|
|
1689
|
+
to
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1556
1692
|
return builder.finish();
|
|
1557
1693
|
};
|
|
1558
1694
|
|
|
1559
|
-
// packages/ui/react-ui-editor/src/
|
|
1695
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1560
1696
|
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1561
1697
|
var listener = ({ onFocus, onChange }) => {
|
|
1562
1698
|
const extensions = [];
|
|
@@ -1564,16 +1700,16 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1564
1700
|
onFocus(focused);
|
|
1565
1701
|
return null;
|
|
1566
1702
|
}));
|
|
1567
|
-
onChange && extensions.push(EditorView8.updateListener.of((
|
|
1568
|
-
onChange(
|
|
1703
|
+
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1704
|
+
onChange(update2.state.doc.toString());
|
|
1569
1705
|
}));
|
|
1570
1706
|
return extensions;
|
|
1571
1707
|
};
|
|
1572
1708
|
|
|
1573
|
-
// packages/ui/react-ui-editor/src/
|
|
1709
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1574
1710
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1575
1711
|
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1576
|
-
import { markdownLanguage as
|
|
1712
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1577
1713
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1578
1714
|
import { languages } from "@codemirror/language-data";
|
|
1579
1715
|
import { searchKeymap } from "@codemirror/search";
|
|
@@ -1581,12 +1717,11 @@ import { EditorState } from "@codemirror/state";
|
|
|
1581
1717
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1582
1718
|
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1583
1719
|
|
|
1584
|
-
// packages/ui/react-ui-editor/src/
|
|
1585
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
1720
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1721
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1586
1722
|
import { HighlightStyle } from "@codemirror/language";
|
|
1587
1723
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1588
1724
|
import { Table } from "@lezer/markdown";
|
|
1589
|
-
import get4 from "lodash.get";
|
|
1590
1725
|
var markdownTags = {
|
|
1591
1726
|
Blockquote: Tag.define(),
|
|
1592
1727
|
CodeMark: Tag.define(),
|
|
@@ -1770,14 +1905,14 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1770
1905
|
class: "font-mono"
|
|
1771
1906
|
}
|
|
1772
1907
|
], {
|
|
1773
|
-
scope:
|
|
1908
|
+
scope: markdownLanguage2,
|
|
1774
1909
|
all: {
|
|
1775
|
-
fontFamily:
|
|
1910
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1776
1911
|
}
|
|
1777
1912
|
});
|
|
1778
1913
|
};
|
|
1779
1914
|
|
|
1780
|
-
// packages/ui/react-ui-editor/src/
|
|
1915
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1781
1916
|
var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
1782
1917
|
return [
|
|
1783
1918
|
EditorState.allowMultipleSelections.of(true),
|
|
@@ -1802,7 +1937,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1802
1937
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1803
1938
|
// https://github.github.com/gfm
|
|
1804
1939
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1805
|
-
base:
|
|
1940
|
+
base: markdownLanguage3,
|
|
1806
1941
|
// Languages for syntax highlighting fenced code blocks.
|
|
1807
1942
|
codeLanguages: languages,
|
|
1808
1943
|
// Parser extensions.
|
|
@@ -1830,7 +1965,7 @@ var customKeymap = () => keymap4.of([
|
|
|
1830
1965
|
...searchKeymap
|
|
1831
1966
|
]);
|
|
1832
1967
|
|
|
1833
|
-
// packages/ui/react-ui-editor/src/
|
|
1968
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1834
1969
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1835
1970
|
var mention = ({ onSearch }) => {
|
|
1836
1971
|
return autocompletion2({
|
|
@@ -1853,24 +1988,19 @@ var mention = ({ onSearch }) => {
|
|
|
1853
1988
|
});
|
|
1854
1989
|
};
|
|
1855
1990
|
|
|
1856
|
-
// packages/ui/react-ui-editor/src/
|
|
1857
|
-
var mermaid = () => {
|
|
1858
|
-
return [];
|
|
1859
|
-
};
|
|
1860
|
-
|
|
1861
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
|
|
1991
|
+
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1862
1992
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1863
|
-
import { RangeSetBuilder as
|
|
1864
|
-
import { Decoration as
|
|
1993
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1994
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
1865
1995
|
var table = (options = {}) => {
|
|
1866
|
-
return
|
|
1867
|
-
create: (state) =>
|
|
1868
|
-
update: (_, tr) =>
|
|
1996
|
+
return StateField4.define({
|
|
1997
|
+
create: (state) => update(state, options),
|
|
1998
|
+
update: (_, tr) => update(tr.state, options),
|
|
1869
1999
|
provide: (field) => EditorView10.decorations.from(field)
|
|
1870
2000
|
});
|
|
1871
2001
|
};
|
|
1872
|
-
var
|
|
1873
|
-
const builder = new
|
|
2002
|
+
var update = (state, options) => {
|
|
2003
|
+
const builder = new RangeSetBuilder2();
|
|
1874
2004
|
const cursor = state.selection.main.head;
|
|
1875
2005
|
const tables = [];
|
|
1876
2006
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -1910,23 +2040,22 @@ var update3 = (state, options) => {
|
|
|
1910
2040
|
});
|
|
1911
2041
|
tables.forEach((table2) => {
|
|
1912
2042
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
1913
|
-
hide && builder.add(table2.from, table2.to,
|
|
1914
|
-
block: true,
|
|
2043
|
+
hide && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
1915
2044
|
widget: new TableWidget(table2)
|
|
1916
2045
|
}));
|
|
1917
|
-
builder.add(table2.from, table2.to,
|
|
2046
|
+
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
1918
2047
|
class: "cm-table"
|
|
1919
2048
|
}));
|
|
1920
2049
|
});
|
|
1921
2050
|
return builder.finish();
|
|
1922
2051
|
};
|
|
1923
|
-
var TableWidget = class extends
|
|
2052
|
+
var TableWidget = class extends WidgetType6 {
|
|
1924
2053
|
constructor(_table) {
|
|
1925
2054
|
super();
|
|
1926
2055
|
this._table = _table;
|
|
1927
2056
|
}
|
|
1928
2057
|
eq(other) {
|
|
1929
|
-
return this._table.
|
|
2058
|
+
return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
|
|
1930
2059
|
}
|
|
1931
2060
|
toDOM(view) {
|
|
1932
2061
|
const table2 = document.createElement("table");
|
|
@@ -1952,26 +2081,28 @@ var TableWidget = class extends WidgetType5 {
|
|
|
1952
2081
|
}
|
|
1953
2082
|
return table2;
|
|
1954
2083
|
}
|
|
2084
|
+
ignoreEvent(e) {
|
|
2085
|
+
return !/^mouse/.test(e.type);
|
|
2086
|
+
}
|
|
1955
2087
|
};
|
|
1956
2088
|
|
|
1957
|
-
// packages/ui/react-ui-editor/src/
|
|
1958
|
-
import { EditorView as EditorView11, Decoration as
|
|
1959
|
-
var
|
|
2089
|
+
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2090
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType7, MatchDecorator as MatchDecorator3, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
2091
|
+
var styles5 = EditorView11.baseTheme({
|
|
1960
2092
|
"& .cm-task-item": {
|
|
1961
2093
|
paddingLeft: "4px",
|
|
1962
2094
|
paddingRight: "8px"
|
|
1963
2095
|
}
|
|
1964
2096
|
});
|
|
1965
|
-
var CheckboxWidget = class extends
|
|
1966
|
-
constructor(
|
|
2097
|
+
var CheckboxWidget = class extends WidgetType7 {
|
|
2098
|
+
constructor(_checked, _indent, _onCheck) {
|
|
1967
2099
|
super();
|
|
1968
|
-
this._pos = _pos;
|
|
1969
2100
|
this._checked = _checked;
|
|
1970
2101
|
this._indent = _indent;
|
|
1971
2102
|
this._onCheck = _onCheck;
|
|
1972
2103
|
}
|
|
1973
2104
|
eq(other) {
|
|
1974
|
-
return this.
|
|
2105
|
+
return this._checked === other._checked && this._indent === other._indent;
|
|
1975
2106
|
}
|
|
1976
2107
|
toDOM(view) {
|
|
1977
2108
|
const wrap = document.createElement("span");
|
|
@@ -2002,8 +2133,8 @@ var tasklist = (options = {}) => {
|
|
|
2002
2133
|
decoration: (match, view, pos) => {
|
|
2003
2134
|
const indent = Math.floor(match[1].length / 2);
|
|
2004
2135
|
const checked = match[2] === "x" || match[2] === "X";
|
|
2005
|
-
return
|
|
2006
|
-
widget: new CheckboxWidget(
|
|
2136
|
+
return Decoration8.replace({
|
|
2137
|
+
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2007
2138
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
2008
2139
|
view.dispatch({
|
|
2009
2140
|
changes: {
|
|
@@ -2020,26 +2151,26 @@ var tasklist = (options = {}) => {
|
|
|
2020
2151
|
});
|
|
2021
2152
|
}
|
|
2022
2153
|
});
|
|
2023
|
-
const tasks =
|
|
2154
|
+
const tasks = ViewPlugin7.fromClass(class {
|
|
2024
2155
|
constructor(view) {
|
|
2025
2156
|
this.tasks = taskMatcher.createDeco(view);
|
|
2026
2157
|
}
|
|
2027
|
-
update(
|
|
2028
|
-
this.tasks = taskMatcher.updateDeco(
|
|
2158
|
+
update(update2) {
|
|
2159
|
+
this.tasks = taskMatcher.updateDeco(update2, this.tasks);
|
|
2029
2160
|
}
|
|
2030
2161
|
}, {
|
|
2031
2162
|
decorations: (value) => value.tasks,
|
|
2032
2163
|
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2033
|
-
return view.plugin(plugin)?.tasks ||
|
|
2164
|
+
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
2034
2165
|
})
|
|
2035
2166
|
});
|
|
2036
2167
|
return [
|
|
2037
2168
|
tasks,
|
|
2038
|
-
|
|
2169
|
+
styles5
|
|
2039
2170
|
];
|
|
2040
2171
|
};
|
|
2041
2172
|
|
|
2042
|
-
// packages/ui/react-ui-editor/src/
|
|
2173
|
+
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2043
2174
|
import { keymap as keymap5 } from "@codemirror/view";
|
|
2044
2175
|
var defaultItems = [
|
|
2045
2176
|
"hello world!",
|
|
@@ -2096,8 +2227,29 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2096
2227
|
];
|
|
2097
2228
|
};
|
|
2098
2229
|
|
|
2099
|
-
// packages/ui/react-ui-editor/src/
|
|
2100
|
-
import
|
|
2230
|
+
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2231
|
+
import { yCollab } from "y-codemirror.next";
|
|
2232
|
+
|
|
2233
|
+
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2234
|
+
import * as Y from "yjs";
|
|
2235
|
+
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2236
|
+
var cursorConverter2 = (text) => ({
|
|
2237
|
+
toCursor: (index, assoc) => {
|
|
2238
|
+
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2239
|
+
},
|
|
2240
|
+
fromCursor: (cursor) => {
|
|
2241
|
+
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2242
|
+
}
|
|
2243
|
+
});
|
|
2244
|
+
|
|
2245
|
+
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2246
|
+
var yjs = (content, awareness2) => [
|
|
2247
|
+
CursorConverter.of(cursorConverter2(content)),
|
|
2248
|
+
yCollab(content, awareness2)
|
|
2249
|
+
];
|
|
2250
|
+
|
|
2251
|
+
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2252
|
+
import get3 from "lodash.get";
|
|
2101
2253
|
var defaultTheme = {
|
|
2102
2254
|
//
|
|
2103
2255
|
// Main layout:
|
|
@@ -2126,21 +2278,21 @@ var defaultTheme = {
|
|
|
2126
2278
|
"&.cm-focused": {
|
|
2127
2279
|
outline: "none"
|
|
2128
2280
|
},
|
|
2129
|
-
"
|
|
2281
|
+
".cm-scroller": {
|
|
2130
2282
|
overflow: "visible",
|
|
2131
|
-
fontFamily:
|
|
2283
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2132
2284
|
},
|
|
2133
|
-
"
|
|
2285
|
+
".cm-content": {
|
|
2134
2286
|
padding: 0,
|
|
2135
2287
|
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2136
2288
|
fontSize: "16px"
|
|
2137
2289
|
},
|
|
2138
2290
|
"&light .cm-content": {
|
|
2139
|
-
color:
|
|
2291
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
2140
2292
|
caretColor: "black"
|
|
2141
2293
|
},
|
|
2142
2294
|
"&dark .cm-content": {
|
|
2143
|
-
color:
|
|
2295
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
2144
2296
|
caretColor: "white"
|
|
2145
2297
|
},
|
|
2146
2298
|
//
|
|
@@ -2152,41 +2304,41 @@ var defaultTheme = {
|
|
|
2152
2304
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2153
2305
|
borderLeft: "2px solid white"
|
|
2154
2306
|
},
|
|
2155
|
-
"
|
|
2307
|
+
".cm-placeholder": {
|
|
2156
2308
|
fontWeight: 100
|
|
2157
2309
|
},
|
|
2158
2310
|
//
|
|
2159
2311
|
// line
|
|
2160
2312
|
//
|
|
2161
|
-
"
|
|
2313
|
+
".cm-line": {
|
|
2162
2314
|
paddingInline: 0
|
|
2163
2315
|
},
|
|
2164
|
-
"
|
|
2316
|
+
".cm-activeLine": {
|
|
2165
2317
|
background: "inherit"
|
|
2166
2318
|
},
|
|
2167
2319
|
//
|
|
2168
2320
|
// Selection
|
|
2169
2321
|
//
|
|
2170
2322
|
"&light .cm-selectionBackground": {
|
|
2171
|
-
background:
|
|
2323
|
+
background: get3(tokens, "extend.colors.primary.100")
|
|
2172
2324
|
},
|
|
2173
2325
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2174
|
-
background:
|
|
2326
|
+
background: get3(tokens, "extend.colors.primary.200")
|
|
2175
2327
|
},
|
|
2176
2328
|
"&dark .cm-selectionBackground": {
|
|
2177
|
-
background:
|
|
2329
|
+
background: get3(tokens, "extend.colors.primary.700")
|
|
2178
2330
|
},
|
|
2179
2331
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2180
|
-
background:
|
|
2332
|
+
background: get3(tokens, "extend.colors.primary.600")
|
|
2181
2333
|
},
|
|
2182
2334
|
//
|
|
2183
2335
|
// Search
|
|
2184
2336
|
//
|
|
2185
2337
|
"&light .cm-searchMatch": {
|
|
2186
|
-
backgroundColor:
|
|
2338
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2187
2339
|
},
|
|
2188
2340
|
"&dark .cm-searchMatch": {
|
|
2189
|
-
backgroundColor:
|
|
2341
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2190
2342
|
},
|
|
2191
2343
|
//
|
|
2192
2344
|
// collaboration
|
|
@@ -2198,95 +2350,101 @@ var defaultTheme = {
|
|
|
2198
2350
|
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2199
2351
|
mixBlendMode: "screen"
|
|
2200
2352
|
},
|
|
2201
|
-
"
|
|
2353
|
+
".cm-ySelectionInfo": {
|
|
2202
2354
|
padding: "2px 4px",
|
|
2203
2355
|
marginBlockStart: "-4px"
|
|
2204
2356
|
},
|
|
2205
|
-
"
|
|
2357
|
+
".cm-ySelection, & .cm-selectionMatch": {
|
|
2206
2358
|
paddingBlockStart: ".15em",
|
|
2207
2359
|
paddingBlockEnd: ".15em"
|
|
2208
2360
|
},
|
|
2209
|
-
"
|
|
2361
|
+
".cm-ySelectionCaret": {
|
|
2210
2362
|
display: "inline-block",
|
|
2211
2363
|
insetBlockStart: ".1em",
|
|
2212
2364
|
blockSize: "1.4em",
|
|
2213
2365
|
verticalAlign: "top"
|
|
2214
2366
|
},
|
|
2215
|
-
"
|
|
2367
|
+
".cm-yLineSelection": {
|
|
2216
2368
|
margin: 0
|
|
2217
2369
|
},
|
|
2218
2370
|
//
|
|
2219
2371
|
// link
|
|
2220
2372
|
//
|
|
2221
|
-
"
|
|
2222
|
-
color:
|
|
2373
|
+
".cm-link": {
|
|
2374
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
2223
2375
|
textDecorationLine: "underline",
|
|
2224
2376
|
textDecorationThickness: "1px",
|
|
2225
2377
|
textUnderlineOffset: "2px",
|
|
2226
2378
|
borderRadius: ".125rem",
|
|
2227
|
-
fontFamily:
|
|
2379
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2228
2380
|
},
|
|
2229
2381
|
//
|
|
2230
2382
|
// tooltip
|
|
2231
2383
|
//
|
|
2232
|
-
"
|
|
2384
|
+
".cm-tooltip": {
|
|
2233
2385
|
border: "none"
|
|
2234
2386
|
},
|
|
2235
|
-
"
|
|
2387
|
+
".cm-tooltip-below": {},
|
|
2236
2388
|
//
|
|
2237
2389
|
// autocomplete
|
|
2238
2390
|
//
|
|
2239
|
-
"
|
|
2391
|
+
".cm-tooltip-autocomplete": {
|
|
2240
2392
|
marginTop: "4px",
|
|
2241
2393
|
marginLeft: "-3px"
|
|
2242
2394
|
},
|
|
2243
|
-
"
|
|
2244
|
-
"
|
|
2245
|
-
"
|
|
2395
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
2396
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2397
|
+
".cm-completionIcon": {
|
|
2246
2398
|
display: "none"
|
|
2247
2399
|
},
|
|
2248
|
-
"
|
|
2249
|
-
fontFamily:
|
|
2400
|
+
".cm-completionLabel": {
|
|
2401
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2250
2402
|
},
|
|
2251
|
-
"
|
|
2403
|
+
".cm-completionMatchedText": {
|
|
2252
2404
|
textDecoration: "none"
|
|
2253
2405
|
},
|
|
2254
2406
|
//
|
|
2255
2407
|
// widgets
|
|
2256
2408
|
//
|
|
2257
|
-
"
|
|
2409
|
+
".cm-widgetBuffer": {
|
|
2258
2410
|
display: "none",
|
|
2259
2411
|
height: 0
|
|
2260
2412
|
},
|
|
2261
2413
|
//
|
|
2262
2414
|
// table
|
|
2263
2415
|
//
|
|
2264
|
-
"
|
|
2265
|
-
fontFamily: `${
|
|
2416
|
+
".cm-table *": {
|
|
2417
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2266
2418
|
textDecoration: "none !important"
|
|
2267
2419
|
},
|
|
2268
|
-
"
|
|
2420
|
+
".cm-table-head": {
|
|
2269
2421
|
padding: "2px 16px 2px 0px",
|
|
2270
|
-
borderBottom: `1px solid ${
|
|
2422
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2271
2423
|
fontWeight: 100,
|
|
2272
2424
|
textAlign: "left",
|
|
2273
|
-
color:
|
|
2425
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
2274
2426
|
},
|
|
2275
|
-
"
|
|
2427
|
+
".cm-table-cell": {
|
|
2276
2428
|
padding: "2px 16px 2px 0px"
|
|
2277
2429
|
},
|
|
2278
2430
|
//
|
|
2279
2431
|
// image
|
|
2280
2432
|
//
|
|
2281
|
-
"
|
|
2282
|
-
|
|
2433
|
+
".cm-image": {
|
|
2434
|
+
display: "block",
|
|
2435
|
+
height: "0"
|
|
2436
|
+
},
|
|
2437
|
+
".cm-image.cm-loaded-image": {
|
|
2438
|
+
height: "auto",
|
|
2439
|
+
borderTop: "0.5rem solid transparent",
|
|
2440
|
+
borderBottom: "0.5rem solid transparent"
|
|
2283
2441
|
},
|
|
2284
2442
|
//
|
|
2285
2443
|
// font size
|
|
2286
2444
|
// TODO(thure): This appears to be the best or only way to set selection caret heights, but it's far more verbose than it needs to be.
|
|
2287
2445
|
//
|
|
2288
|
-
...Object.keys(
|
|
2289
|
-
const height =
|
|
2446
|
+
...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
|
|
2447
|
+
const height = get3(tokens, [
|
|
2290
2448
|
"extend",
|
|
2291
2449
|
"fontSize",
|
|
2292
2450
|
fontSize,
|
|
@@ -2320,88 +2478,81 @@ var defaultTheme = {
|
|
|
2320
2478
|
* </div>
|
|
2321
2479
|
* </div
|
|
2322
2480
|
*/
|
|
2323
|
-
"
|
|
2324
|
-
border: `1px solid ${
|
|
2481
|
+
".cm-panels": {
|
|
2482
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2325
2483
|
},
|
|
2326
|
-
"
|
|
2327
|
-
background:
|
|
2328
|
-
fontFamily:
|
|
2484
|
+
".cm-panel": {
|
|
2485
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2486
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2329
2487
|
},
|
|
2330
|
-
"
|
|
2488
|
+
".cm-button": {
|
|
2331
2489
|
margin: "4px",
|
|
2332
|
-
fontFamily:
|
|
2333
|
-
background:
|
|
2490
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2491
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2334
2492
|
backgroundImage: "none",
|
|
2335
2493
|
border: "none",
|
|
2336
2494
|
"&:hover": {
|
|
2337
|
-
background:
|
|
2495
|
+
background: get3(tokens, "extend.colors.neutral.200")
|
|
2338
2496
|
},
|
|
2339
2497
|
"&:active": {
|
|
2340
|
-
background:
|
|
2498
|
+
background: get3(tokens, "extend.colors.neutral.300"),
|
|
2341
2499
|
backgroundImage: "none"
|
|
2342
2500
|
}
|
|
2343
2501
|
},
|
|
2344
|
-
"
|
|
2502
|
+
".cm-panel input[type=checkbox]": {
|
|
2345
2503
|
marginRight: "0.4rem !important"
|
|
2346
2504
|
}
|
|
2347
2505
|
};
|
|
2348
2506
|
var textTheme = {
|
|
2349
|
-
"
|
|
2350
|
-
fontFamily:
|
|
2507
|
+
".cm-scroller": {
|
|
2508
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2351
2509
|
},
|
|
2352
|
-
"
|
|
2353
|
-
fontFamily:
|
|
2510
|
+
".cm-placeholder": {
|
|
2511
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2354
2512
|
}
|
|
2355
2513
|
};
|
|
2356
2514
|
var markdownTheme = {
|
|
2357
2515
|
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
2358
|
-
"
|
|
2359
|
-
fontFamily:
|
|
2516
|
+
".cm-placeholder": {
|
|
2517
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2360
2518
|
}
|
|
2361
2519
|
};
|
|
2362
2520
|
var codeTheme = {
|
|
2363
|
-
"
|
|
2364
|
-
fontFamily:
|
|
2521
|
+
".cm-scroller": {
|
|
2522
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2365
2523
|
},
|
|
2366
|
-
"
|
|
2367
|
-
fontFamily:
|
|
2524
|
+
".cm-placeholder": {
|
|
2525
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2368
2526
|
}
|
|
2369
2527
|
};
|
|
2370
2528
|
|
|
2371
2529
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2372
|
-
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
2373
|
-
import { EditorView as EditorView12 } from "@codemirror/view";
|
|
2374
|
-
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
2375
|
-
import { vim } from "@replit/codemirror-vim";
|
|
2376
|
-
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
2377
|
-
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState as useState2 } from "react";
|
|
2378
|
-
import { generateName } from "@dxos/display-name";
|
|
2379
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
2380
|
-
import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
2381
2530
|
var EditorModes = [
|
|
2382
2531
|
"default",
|
|
2383
2532
|
"vim"
|
|
2384
2533
|
];
|
|
2385
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2386
|
-
const { themeMode } = useThemeContext();
|
|
2534
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2387
2535
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2388
2536
|
tabBehavior: "limited"
|
|
2389
2537
|
});
|
|
2390
|
-
const
|
|
2391
|
-
const
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
state,
|
|
2538
|
+
const { themeMode } = useThemeContext();
|
|
2539
|
+
const rootRef = useRef(null);
|
|
2540
|
+
const [view, setView] = useState(null);
|
|
2541
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2395
2542
|
view
|
|
2396
|
-
|
|
2543
|
+
]);
|
|
2544
|
+
useEffect(() => {
|
|
2545
|
+
if (view && focus) {
|
|
2546
|
+
view.focus();
|
|
2547
|
+
}
|
|
2548
|
+
}, [
|
|
2397
2549
|
view,
|
|
2398
|
-
|
|
2399
|
-
root
|
|
2550
|
+
focus
|
|
2400
2551
|
]);
|
|
2401
|
-
const { awareness, peer } = model;
|
|
2402
|
-
|
|
2403
|
-
if (
|
|
2404
|
-
|
|
2552
|
+
const { awareness: awareness2, peer } = model;
|
|
2553
|
+
useEffect(() => {
|
|
2554
|
+
if (awareness2 && peer) {
|
|
2555
|
+
awareness2.setLocalStateField("user", {
|
|
2405
2556
|
name: peer.name ?? generateName(peer.id),
|
|
2406
2557
|
color: getColorForValue({
|
|
2407
2558
|
value: peer.id,
|
|
@@ -2415,11 +2566,11 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2415
2566
|
});
|
|
2416
2567
|
}
|
|
2417
2568
|
}, [
|
|
2418
|
-
|
|
2569
|
+
awareness2,
|
|
2419
2570
|
peer,
|
|
2420
2571
|
themeMode
|
|
2421
2572
|
]);
|
|
2422
|
-
|
|
2573
|
+
useEffect(() => {
|
|
2423
2574
|
if (view && comments2?.length) {
|
|
2424
2575
|
view.dispatch({
|
|
2425
2576
|
effects: setCommentRange.of({
|
|
@@ -2432,12 +2583,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2432
2583
|
view,
|
|
2433
2584
|
comments2
|
|
2434
2585
|
]);
|
|
2435
|
-
|
|
2436
|
-
if (!
|
|
2586
|
+
useEffect(() => {
|
|
2587
|
+
if (!model || !rootRef.current) {
|
|
2437
2588
|
return;
|
|
2438
2589
|
}
|
|
2439
|
-
const
|
|
2590
|
+
const state = EditorState2.create({
|
|
2440
2591
|
doc: model.text(),
|
|
2592
|
+
selection,
|
|
2441
2593
|
extensions: [
|
|
2442
2594
|
readonly && EditorState2.readOnly.of(readonly),
|
|
2443
2595
|
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
@@ -2454,19 +2606,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2454
2606
|
].filter(Boolean)
|
|
2455
2607
|
});
|
|
2456
2608
|
view?.destroy();
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
state: state2,
|
|
2461
|
-
parent: root
|
|
2462
|
-
})
|
|
2609
|
+
const newView = new EditorView12({
|
|
2610
|
+
parent: rootRef.current,
|
|
2611
|
+
state
|
|
2463
2612
|
});
|
|
2613
|
+
setView(newView);
|
|
2464
2614
|
return () => {
|
|
2465
|
-
|
|
2466
|
-
|
|
2615
|
+
newView?.destroy();
|
|
2616
|
+
setView(null);
|
|
2467
2617
|
};
|
|
2468
2618
|
}, [
|
|
2469
|
-
|
|
2619
|
+
rootRef,
|
|
2470
2620
|
model,
|
|
2471
2621
|
readonly,
|
|
2472
2622
|
editorMode,
|
|
@@ -2475,12 +2625,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2475
2625
|
const handleKeyUp = useCallback((event) => {
|
|
2476
2626
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2477
2627
|
switch (key) {
|
|
2478
|
-
case "Enter": {
|
|
2479
|
-
view?.contentDOM.focus();
|
|
2480
|
-
break;
|
|
2481
|
-
}
|
|
2482
2628
|
case "Escape": {
|
|
2483
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) &&
|
|
2629
|
+
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
|
|
2484
2630
|
break;
|
|
2485
2631
|
}
|
|
2486
2632
|
}
|
|
@@ -2490,16 +2636,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2490
2636
|
]);
|
|
2491
2637
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2492
2638
|
key: model.id,
|
|
2493
|
-
ref:
|
|
2639
|
+
ref: rootRef,
|
|
2494
2640
|
tabIndex: 0,
|
|
2495
2641
|
...slots?.root,
|
|
2496
2642
|
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2497
2643
|
onKeyUp: handleKeyUp
|
|
2498
2644
|
});
|
|
2499
2645
|
});
|
|
2500
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots
|
|
2646
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots, ...props }, forwardedRef) => {
|
|
2501
2647
|
const { themeMode } = useThemeContext();
|
|
2502
|
-
const
|
|
2648
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2503
2649
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2504
2650
|
ref: forwardedRef,
|
|
2505
2651
|
readonly,
|
|
@@ -2507,17 +2653,17 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
|
|
|
2507
2653
|
basicBundle({
|
|
2508
2654
|
readonly,
|
|
2509
2655
|
themeMode,
|
|
2510
|
-
placeholder:
|
|
2656
|
+
placeholder: updatedSlots?.editor?.placeholder
|
|
2511
2657
|
}),
|
|
2512
2658
|
...extensions
|
|
2513
2659
|
],
|
|
2514
|
-
slots,
|
|
2660
|
+
slots: updatedSlots,
|
|
2515
2661
|
...props
|
|
2516
2662
|
});
|
|
2517
2663
|
});
|
|
2518
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots
|
|
2664
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots, ...props }, forwardedRef) => {
|
|
2519
2665
|
const { themeMode } = useThemeContext();
|
|
2520
|
-
const
|
|
2666
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2521
2667
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2522
2668
|
ref: forwardedRef,
|
|
2523
2669
|
readonly,
|
|
@@ -2525,11 +2671,11 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
|
|
|
2525
2671
|
markdownBundle({
|
|
2526
2672
|
readonly,
|
|
2527
2673
|
themeMode,
|
|
2528
|
-
placeholder:
|
|
2674
|
+
placeholder: updatedSlots?.editor?.placeholder
|
|
2529
2675
|
}),
|
|
2530
2676
|
...extensions
|
|
2531
2677
|
],
|
|
2532
|
-
slots,
|
|
2678
|
+
slots: updatedSlots,
|
|
2533
2679
|
...props
|
|
2534
2680
|
});
|
|
2535
2681
|
});
|
|
@@ -2550,28 +2696,379 @@ var defaultMarkdownSlots = {
|
|
|
2550
2696
|
theme: markdownTheme
|
|
2551
2697
|
}
|
|
2552
2698
|
};
|
|
2699
|
+
|
|
2700
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2701
|
+
import get4 from "lodash.get";
|
|
2702
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
2703
|
+
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2704
|
+
|
|
2705
|
+
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2706
|
+
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2707
|
+
import { Context as Context2 } from "@dxos/context";
|
|
2708
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2709
|
+
import { log as log3 } from "@dxos/log";
|
|
2710
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2711
|
+
var DEBOUNCE_INTERVAL = 100;
|
|
2712
|
+
var SpaceAwarenessProvider = class {
|
|
2713
|
+
constructor(params) {
|
|
2714
|
+
this.remoteStateChange = new Event2();
|
|
2715
|
+
this._remoteStates = /* @__PURE__ */ new Map();
|
|
2716
|
+
this._space = params.space;
|
|
2717
|
+
this._channel = params.channel;
|
|
2718
|
+
this._peerId = params.peerId;
|
|
2719
|
+
this._info = params.info;
|
|
2720
|
+
}
|
|
2721
|
+
open() {
|
|
2722
|
+
this._ctx = new Context2();
|
|
2723
|
+
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
2724
|
+
if (this._localState) {
|
|
2725
|
+
await this._space.postMessage(this._channel, {
|
|
2726
|
+
kind: "post",
|
|
2727
|
+
state: this._localState
|
|
2728
|
+
});
|
|
2729
|
+
await sleep(DEBOUNCE_INTERVAL);
|
|
2730
|
+
}
|
|
2731
|
+
});
|
|
2732
|
+
const unsubscribe = this._space.listen(this._channel, (message) => {
|
|
2733
|
+
switch (message.payload.kind) {
|
|
2734
|
+
case "query": {
|
|
2735
|
+
this._handleQueryMessage();
|
|
2736
|
+
break;
|
|
2737
|
+
}
|
|
2738
|
+
case "post": {
|
|
2739
|
+
this._handlePostMessage(message.payload);
|
|
2740
|
+
break;
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
});
|
|
2744
|
+
this._ctx.onDispose(unsubscribe);
|
|
2745
|
+
void this._space.postMessage(this._channel, {
|
|
2746
|
+
kind: "query"
|
|
2747
|
+
}).catch((err) => {
|
|
2748
|
+
log3.debug("failed to query awareness", {
|
|
2749
|
+
err
|
|
2750
|
+
}, {
|
|
2751
|
+
F: __dxlog_file4,
|
|
2752
|
+
L: 85,
|
|
2753
|
+
S: this,
|
|
2754
|
+
C: (f, a) => f(...a)
|
|
2755
|
+
});
|
|
2756
|
+
});
|
|
2757
|
+
}
|
|
2758
|
+
close() {
|
|
2759
|
+
void this._ctx?.dispose();
|
|
2760
|
+
this._ctx = void 0;
|
|
2761
|
+
this._postTask = void 0;
|
|
2762
|
+
}
|
|
2763
|
+
update(position) {
|
|
2764
|
+
invariant3(this._postTask, void 0, {
|
|
2765
|
+
F: __dxlog_file4,
|
|
2766
|
+
L: 96,
|
|
2767
|
+
S: this,
|
|
2768
|
+
A: [
|
|
2769
|
+
"this._postTask",
|
|
2770
|
+
""
|
|
2771
|
+
]
|
|
2772
|
+
});
|
|
2773
|
+
this._localState = {
|
|
2774
|
+
peerId: this._peerId,
|
|
2775
|
+
position,
|
|
2776
|
+
info: this._info
|
|
2777
|
+
};
|
|
2778
|
+
this._postTask.schedule();
|
|
2779
|
+
}
|
|
2780
|
+
getRemoteStates() {
|
|
2781
|
+
return Array.from(this._remoteStates.values());
|
|
2782
|
+
}
|
|
2783
|
+
_handleQueryMessage() {
|
|
2784
|
+
invariant3(this._postTask, void 0, {
|
|
2785
|
+
F: __dxlog_file4,
|
|
2786
|
+
L: 111,
|
|
2787
|
+
S: this,
|
|
2788
|
+
A: [
|
|
2789
|
+
"this._postTask",
|
|
2790
|
+
""
|
|
2791
|
+
]
|
|
2792
|
+
});
|
|
2793
|
+
this._postTask.schedule();
|
|
2794
|
+
}
|
|
2795
|
+
_handlePostMessage(message) {
|
|
2796
|
+
invariant3(message.kind === "post", void 0, {
|
|
2797
|
+
F: __dxlog_file4,
|
|
2798
|
+
L: 116,
|
|
2799
|
+
S: this,
|
|
2800
|
+
A: [
|
|
2801
|
+
"message.kind === 'post'",
|
|
2802
|
+
""
|
|
2803
|
+
]
|
|
2804
|
+
});
|
|
2805
|
+
this._remoteStates.set(message.state.peerId, message.state);
|
|
2806
|
+
this.remoteStateChange.emit();
|
|
2807
|
+
}
|
|
2808
|
+
};
|
|
2809
|
+
|
|
2810
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2811
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
|
2812
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2813
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2814
|
+
|
|
2815
|
+
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2816
|
+
import * as decoding from "lib0/decoding";
|
|
2817
|
+
import * as encoding from "lib0/encoding";
|
|
2818
|
+
import { Observable } from "lib0/observable";
|
|
2819
|
+
import * as YP from "y-protocols/awareness";
|
|
2820
|
+
import * as Y2 from "yjs";
|
|
2821
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2822
|
+
import { log as log4 } from "@dxos/log";
|
|
2823
|
+
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2824
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2825
|
+
var createYjsModel = ({ identity, space, text }) => {
|
|
2826
|
+
invariant4(text?.doc && text?.content, void 0, {
|
|
2827
|
+
F: __dxlog_file5,
|
|
2828
|
+
L: 23,
|
|
2829
|
+
S: void 0,
|
|
2830
|
+
A: [
|
|
2831
|
+
"text?.doc && text?.content",
|
|
2832
|
+
""
|
|
2833
|
+
]
|
|
2834
|
+
});
|
|
2835
|
+
const provider = space ? new YAwarenessProvider({
|
|
2836
|
+
space,
|
|
2837
|
+
doc: text.doc,
|
|
2838
|
+
channel: `yjs.awareness.${text.id}`
|
|
2839
|
+
}) : void 0;
|
|
2840
|
+
const model = {
|
|
2841
|
+
id: text.doc.guid,
|
|
2842
|
+
content: text.content,
|
|
2843
|
+
text: () => text.content.toString(),
|
|
2844
|
+
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2845
|
+
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2846
|
+
getCursorFromRange: (range) => {
|
|
2847
|
+
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2848
|
+
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2849
|
+
return [
|
|
2850
|
+
arrayToString2(from),
|
|
2851
|
+
arrayToString2(to)
|
|
2852
|
+
].join(":");
|
|
2853
|
+
},
|
|
2854
|
+
getRangeFromCursor: (cursor) => {
|
|
2855
|
+
invariant4(text.doc, void 0, {
|
|
2856
|
+
F: __dxlog_file5,
|
|
2857
|
+
L: 40,
|
|
2858
|
+
S: void 0,
|
|
2859
|
+
A: [
|
|
2860
|
+
"text.doc",
|
|
2861
|
+
""
|
|
2862
|
+
]
|
|
2863
|
+
});
|
|
2864
|
+
const parts = cursor.split(":");
|
|
2865
|
+
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2866
|
+
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2867
|
+
return from && to ? {
|
|
2868
|
+
from: from.index,
|
|
2869
|
+
to: to.index
|
|
2870
|
+
} : void 0;
|
|
2871
|
+
},
|
|
2872
|
+
extension: [
|
|
2873
|
+
modelState.init(() => model),
|
|
2874
|
+
yjs(text.content, provider?.awareness)
|
|
2875
|
+
],
|
|
2876
|
+
awareness: provider?.awareness,
|
|
2877
|
+
peer: identity ? {
|
|
2878
|
+
id: identity.identityKey.toHex(),
|
|
2879
|
+
name: identity.profile?.displayName
|
|
2880
|
+
} : void 0
|
|
2881
|
+
};
|
|
2882
|
+
return model;
|
|
2883
|
+
};
|
|
2884
|
+
var messageAwareness = 1;
|
|
2885
|
+
var messageQueryAwareness = 3;
|
|
2886
|
+
var YAwarenessProvider = class extends Observable {
|
|
2887
|
+
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2888
|
+
super();
|
|
2889
|
+
this._space = space;
|
|
2890
|
+
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2891
|
+
this._channel = channel;
|
|
2892
|
+
this._clientId = doc.clientID;
|
|
2893
|
+
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
2894
|
+
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
2895
|
+
if (typeof window !== "undefined") {
|
|
2896
|
+
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
2897
|
+
} else if (typeof process !== "undefined") {
|
|
2898
|
+
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
2899
|
+
}
|
|
2900
|
+
const encoderAwarenessQuery = encoding.createEncoder();
|
|
2901
|
+
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
2902
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
2903
|
+
const encoderAwarenessState = encoding.createEncoder();
|
|
2904
|
+
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
2905
|
+
encoding.writeVarUint8Array(encoderAwarenessState, YP.encodeAwarenessUpdate(this.awareness, [
|
|
2906
|
+
this._clientId
|
|
2907
|
+
]));
|
|
2908
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
2909
|
+
}
|
|
2910
|
+
get awareness() {
|
|
2911
|
+
return this._awareness;
|
|
2912
|
+
}
|
|
2913
|
+
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2914
|
+
log4("awareness update", {
|
|
2915
|
+
added,
|
|
2916
|
+
updated,
|
|
2917
|
+
removed,
|
|
2918
|
+
origin
|
|
2919
|
+
}, {
|
|
2920
|
+
F: __dxlog_file5,
|
|
2921
|
+
L: 122,
|
|
2922
|
+
S: this,
|
|
2923
|
+
C: (f, a) => f(...a)
|
|
2924
|
+
});
|
|
2925
|
+
const changedClients = added.concat(updated).concat(removed);
|
|
2926
|
+
const encoderAwareness = encoding.createEncoder();
|
|
2927
|
+
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
2928
|
+
encoding.writeVarUint8Array(encoderAwareness, YP.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
2929
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2930
|
+
}
|
|
2931
|
+
_handleSpaceMessage({ payload }) {
|
|
2932
|
+
log4("space message", payload, {
|
|
2933
|
+
F: __dxlog_file5,
|
|
2934
|
+
L: 131,
|
|
2935
|
+
S: this,
|
|
2936
|
+
C: (f, a) => f(...a)
|
|
2937
|
+
});
|
|
2938
|
+
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2939
|
+
const encoder = this._readMessage(data);
|
|
2940
|
+
if (encoder) {
|
|
2941
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
_readMessage(message) {
|
|
2945
|
+
const decoder = decoding.createDecoder(message);
|
|
2946
|
+
const encoder = encoding.createEncoder();
|
|
2947
|
+
const messageType = decoding.readVarUint(decoder);
|
|
2948
|
+
let sendReply = false;
|
|
2949
|
+
switch (messageType) {
|
|
2950
|
+
case messageAwareness: {
|
|
2951
|
+
YP.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
2952
|
+
break;
|
|
2953
|
+
}
|
|
2954
|
+
case messageQueryAwareness: {
|
|
2955
|
+
encoding.writeVarUint(encoder, messageAwareness);
|
|
2956
|
+
encoding.writeVarUint8Array(encoder, YP.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
2957
|
+
sendReply = true;
|
|
2958
|
+
break;
|
|
2959
|
+
}
|
|
2960
|
+
default: {
|
|
2961
|
+
console.error("Invalid message:", messageType);
|
|
2962
|
+
return encoder;
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
if (!sendReply) {
|
|
2966
|
+
return null;
|
|
2967
|
+
}
|
|
2968
|
+
return encoder;
|
|
2969
|
+
}
|
|
2970
|
+
_handleBeforeUnload() {
|
|
2971
|
+
YP.removeAwarenessStates(this._awareness, [
|
|
2972
|
+
this._clientId
|
|
2973
|
+
], "window unload");
|
|
2974
|
+
}
|
|
2975
|
+
};
|
|
2976
|
+
|
|
2977
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2978
|
+
var modelState = StateField5.define({
|
|
2979
|
+
create: () => void 0,
|
|
2980
|
+
update: (model) => model
|
|
2981
|
+
});
|
|
2982
|
+
var useTextModel = (props) => {
|
|
2983
|
+
const { identity, space, text } = props;
|
|
2984
|
+
const [model, setModel] = useState2();
|
|
2985
|
+
useEffect2(() => setModel(createModel(props)), [
|
|
2986
|
+
identity,
|
|
2987
|
+
space,
|
|
2988
|
+
text
|
|
2989
|
+
]);
|
|
2990
|
+
return model;
|
|
2991
|
+
};
|
|
2992
|
+
var createModel = (props) => {
|
|
2993
|
+
const { text } = props;
|
|
2994
|
+
if (isAutomergeObject(text)) {
|
|
2995
|
+
return createAutomergeModel(props);
|
|
2996
|
+
} else if (text?.doc) {
|
|
2997
|
+
return createYjsModel(props);
|
|
2998
|
+
} else {
|
|
2999
|
+
return void 0;
|
|
3000
|
+
}
|
|
3001
|
+
};
|
|
3002
|
+
|
|
3003
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
3004
|
+
var createAutomergeModel = ({ space, identity, text }) => {
|
|
3005
|
+
const obj = text;
|
|
3006
|
+
const doc = getRawDoc(obj, [
|
|
3007
|
+
obj.field
|
|
3008
|
+
]);
|
|
3009
|
+
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
3010
|
+
space,
|
|
3011
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
3012
|
+
info: {
|
|
3013
|
+
displayName: identity?.profile?.displayName ?? "",
|
|
3014
|
+
color: cursorColor.color,
|
|
3015
|
+
lightColor: cursorColor.light
|
|
3016
|
+
},
|
|
3017
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
3018
|
+
});
|
|
3019
|
+
const model = {
|
|
3020
|
+
id: obj.id,
|
|
3021
|
+
content: doc,
|
|
3022
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3023
|
+
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3024
|
+
extension: [
|
|
3025
|
+
modelState.init(() => model),
|
|
3026
|
+
automerge3({
|
|
3027
|
+
handle: doc.handle,
|
|
3028
|
+
path: doc.path
|
|
3029
|
+
}),
|
|
3030
|
+
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
3031
|
+
awareness()
|
|
3032
|
+
].filter(isNotNullOrUndefined),
|
|
3033
|
+
peer: identity ? {
|
|
3034
|
+
id: identity.identityKey.toHex(),
|
|
3035
|
+
name: identity.profile?.displayName
|
|
3036
|
+
} : void 0
|
|
3037
|
+
};
|
|
3038
|
+
return model;
|
|
3039
|
+
};
|
|
2553
3040
|
export {
|
|
3041
|
+
AwarenessProvider,
|
|
2554
3042
|
BaseTextEditor,
|
|
3043
|
+
CursorConverter,
|
|
2555
3044
|
Doc,
|
|
2556
3045
|
EditorModes,
|
|
2557
3046
|
MarkdownEditor,
|
|
3047
|
+
RemoteSelectionsDecorator,
|
|
2558
3048
|
SpaceAwarenessProvider,
|
|
2559
3049
|
TextEditor,
|
|
2560
3050
|
TextKind,
|
|
3051
|
+
YAwarenessProvider,
|
|
2561
3052
|
YText,
|
|
2562
3053
|
YXmlFragment,
|
|
2563
3054
|
autocomplete,
|
|
3055
|
+
automerge3 as automerge,
|
|
3056
|
+
awareness,
|
|
2564
3057
|
basicBundle,
|
|
2565
3058
|
blast,
|
|
3059
|
+
callbackWrapper,
|
|
2566
3060
|
code2 as code,
|
|
2567
3061
|
codeTheme,
|
|
2568
3062
|
comments,
|
|
2569
|
-
|
|
3063
|
+
createAutomergeModel,
|
|
3064
|
+
createYjsModel,
|
|
3065
|
+
cursorConverter,
|
|
2570
3066
|
defaultMarkdownSlots,
|
|
2571
3067
|
defaultOptions,
|
|
2572
3068
|
defaultSlots,
|
|
2573
3069
|
defaultTextSlots,
|
|
2574
3070
|
defaultTheme,
|
|
3071
|
+
getToken,
|
|
2575
3072
|
hr,
|
|
2576
3073
|
image,
|
|
2577
3074
|
link,
|
|
@@ -2582,14 +3079,16 @@ export {
|
|
|
2582
3079
|
markdownTagsExtensions,
|
|
2583
3080
|
markdownTheme,
|
|
2584
3081
|
mention,
|
|
2585
|
-
mermaid,
|
|
2586
3082
|
modelState,
|
|
2587
3083
|
setCommentRange,
|
|
3084
|
+
setFocus,
|
|
3085
|
+
setSelection,
|
|
2588
3086
|
table,
|
|
2589
3087
|
tags2 as tags,
|
|
2590
3088
|
tasklist,
|
|
2591
3089
|
textTheme,
|
|
2592
3090
|
typewriter,
|
|
2593
|
-
useTextModel
|
|
3091
|
+
useTextModel,
|
|
3092
|
+
yjs
|
|
2594
3093
|
};
|
|
2595
3094
|
//# sourceMappingURL=index.mjs.map
|