@dxos/react-ui-editor 0.3.10 → 0.3.11-main.008b7c6
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 +1537 -847
- 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 +14 -10
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +3 -2
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +3 -0
- 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 -2
- 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 +3 -0
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -0
- package/dist/types/src/{hooks/automerge/PatchSemaphore.d.ts → extensions/automerge/semaphore.d.ts} +5 -5
- 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 +5 -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/extensions/comments.d.ts +50 -0
- package/dist/types/src/extensions/comments.d.ts.map +1 -0
- package/dist/types/src/extensions/hr.d.ts +2 -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 +6 -3
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/link.d.ts +1 -0
- package/dist/types/src/extensions/link.d.ts.map +1 -0
- package/dist/types/src/extensions/listener.d.ts +10 -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/{components/TextEditor/extensions → extensions}/markdown/highlight.d.ts +0 -1
- 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/mermaid.d.ts +3 -0
- package/dist/types/src/extensions/mermaid.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/{components/TextEditor/extensions/demo.d.ts → extensions/typewriter.d.ts} +2 -3
- 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 +2 -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 +20 -11
- 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 +3 -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/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 +5 -13
- 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 +5 -0
- package/dist/types/src/util/util.d.ts.map +1 -0
- package/package.json +25 -20
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +130 -71
- package/src/components/TextEditor/TextEditor.stories.tsx +15 -2
- package/src/components/TextEditor/TextEditor.tsx +30 -26
- package/src/{hooks/automerge → components/TextEditor}/automerge.stories.tsx +67 -8
- 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/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 +6 -0
- package/src/{hooks/automerge/PatchSemaphore.ts → extensions/automerge/semaphore.ts} +18 -15
- package/src/{hooks/automerge/translation/codemirror-to-automerge.ts → extensions/automerge/update-automerge.ts} +6 -7
- package/src/{hooks/automerge/translation/automerge-to-codemirror.ts → extensions/automerge/update-codemirror.ts} +14 -11
- package/src/extensions/awareness.ts +316 -0
- package/src/{components/TextEditor/extensions → extensions}/code.ts +13 -13
- package/src/extensions/comments.ts +421 -0
- package/src/extensions/hr.ts +74 -0
- package/src/{components/TextEditor/extensions → extensions}/image.ts +3 -1
- package/src/{components/TextEditor/extensions → extensions}/index.ts +6 -3
- package/src/{components/TextEditor/extensions → extensions}/link.ts +66 -10
- package/src/extensions/listener.ts +35 -0
- package/src/{components/TextEditor/extensions → extensions}/markdown/highlight.ts +6 -9
- package/src/extensions/mermaid.ts +11 -0
- package/src/{components/TextEditor/extensions → extensions}/table.ts +14 -1
- package/src/{components/TextEditor/extensions/demo.ts → extensions/typewriter.ts} +2 -3
- package/src/extensions/yjs/cursor.ts +21 -0
- package/src/extensions/yjs/index.ts +5 -0
- package/src/extensions/yjs/yjs.test.ts +35 -0
- 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 +43 -79
- package/src/hooks/{yjs/space-provider.ts → yjs.ts} +71 -19
- package/src/index.ts +3 -0
- package/src/styles/index.ts +1 -0
- package/src/testing/replicator.ts +10 -16
- package/src/{components/TextEditor/themes → themes}/default.ts +61 -38
- package/src/util/cursor.ts +29 -0
- package/src/util/index.ts +6 -0
- package/src/util/util.ts +18 -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 +0 -18
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/experimental.d.ts +0 -10
- package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/highlight.d.ts +0 -24
- package/dist/types/src/components/TextEditor/extensions/highlight.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 +0 -9
- 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/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/tooltip.d.ts +0 -12
- package/dist/types/src/components/TextEditor/extensions/tooltip.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/PatchSemaphore.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/translation/automerge-to-codemirror.d.ts +0 -5
- package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts +0 -6
- package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/translation/index.d.ts +0 -3
- package/dist/types/src/hooks/automerge/translation/index.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/src/components/TextEditor/extensions/comments.ts +0 -173
- package/src/components/TextEditor/extensions/experimental.tsx +0 -114
- package/src/components/TextEditor/extensions/highlight.ts +0 -128
- package/src/components/TextEditor/extensions/listener.ts +0 -23
- package/src/components/TextEditor/extensions/tooltip.tsx +0 -61
- 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/automerge/translation/index.ts +0 -6
- 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/{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}/image.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/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/{hooks/yjs → styles}/cursors.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/themes → themes}/index.d.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/autocomplete.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}/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/{components/TextEditor/extensions → extensions}/tasklist.ts +0 -0
- /package/src/{hooks/yjs → styles}/cursors.ts +0 -0
- /package/src/{components/TextEditor/themes → themes}/index.ts +0 -0
|
@@ -5,7 +5,18 @@ 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 EditorView13 } 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 } 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";
|
|
10
21
|
import { keymap } from "@codemirror/view";
|
|
11
22
|
var autocomplete = ({ onSearch }) => {
|
|
@@ -38,13 +49,565 @@ var autocomplete = ({ onSearch }) => {
|
|
|
38
49
|
];
|
|
39
50
|
};
|
|
40
51
|
|
|
41
|
-
// packages/ui/react-ui-editor/src/
|
|
52
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
53
|
+
import { Facet as Facet2, StateField } from "@codemirror/state";
|
|
54
|
+
import { ViewPlugin } from "@codemirror/view";
|
|
55
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
56
|
+
|
|
57
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
58
|
+
import get from "lodash.get";
|
|
59
|
+
import { next as automerge } from "@dxos/automerge/automerge";
|
|
60
|
+
var cursorConverter = (handle, path) => ({
|
|
61
|
+
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
62
|
+
toCursor: (pos) => {
|
|
63
|
+
const doc = handle.docSync();
|
|
64
|
+
if (!doc) {
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
67
|
+
const value = get(doc, path);
|
|
68
|
+
if (typeof value === "string" && value.length <= pos) {
|
|
69
|
+
return "end";
|
|
70
|
+
}
|
|
71
|
+
return automerge.getCursor(doc, path.slice(), pos);
|
|
72
|
+
},
|
|
73
|
+
fromCursor: (cursor) => {
|
|
74
|
+
if (cursor === "") {
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
const doc = handle.docSync();
|
|
78
|
+
if (!doc) {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
if (cursor === "end") {
|
|
82
|
+
const value = get(doc, path);
|
|
83
|
+
if (typeof value === "string") {
|
|
84
|
+
return value.length;
|
|
85
|
+
} else {
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return automerge.getCursorPosition(doc, path.slice(), cursor);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
94
|
+
import { Annotation, StateEffect } from "@codemirror/state";
|
|
95
|
+
var effectType = StateEffect.define({});
|
|
96
|
+
var updateHeads = (newHeads) => effectType.of({
|
|
97
|
+
newHeads
|
|
98
|
+
});
|
|
99
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
100
|
+
var getPath = (state, field) => state.field(field).path;
|
|
101
|
+
var reconcileAnnotationType = Annotation.define();
|
|
102
|
+
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
103
|
+
|
|
104
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
105
|
+
import { next as automerge2 } from "@dxos/automerge/automerge";
|
|
106
|
+
|
|
107
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
108
|
+
import { next as am } from "@dxos/automerge/automerge";
|
|
109
|
+
var updateAutomerge = (field, handle, transactions, state) => {
|
|
110
|
+
const { lastHeads, path } = state.field(field);
|
|
111
|
+
let hasChanges = false;
|
|
112
|
+
for (const tr of transactions) {
|
|
113
|
+
tr.changes.iterChanges(() => {
|
|
114
|
+
hasChanges = true;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (!hasChanges) {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
121
|
+
for (const tr of transactions) {
|
|
122
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
123
|
+
am.splice(doc, path, fromA, toA - fromA, inserted.toString());
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
return newHeads ?? void 0;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/update-codemirror.ts
|
|
131
|
+
import { ChangeSet } from "@codemirror/state";
|
|
132
|
+
var updateCodeMirror = (view, selection, target, patches) => {
|
|
133
|
+
for (const patch of patches) {
|
|
134
|
+
const changeSpec = handlePatch(patch, target, view.state);
|
|
135
|
+
if (changeSpec != null) {
|
|
136
|
+
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
|
137
|
+
selection = selection.map(changeSet, 1);
|
|
138
|
+
view.dispatch({
|
|
139
|
+
changes: changeSet,
|
|
140
|
+
annotations: reconcileAnnotationType.of({})
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
view.dispatch({
|
|
145
|
+
selection,
|
|
146
|
+
annotations: reconcileAnnotationType.of({})
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
var handlePatch = (patch, target, state) => {
|
|
150
|
+
if (patch.action === "insert") {
|
|
151
|
+
return handleInsert(target, patch);
|
|
152
|
+
} else if (patch.action === "splice") {
|
|
153
|
+
return handleSplice(target, patch);
|
|
154
|
+
} else if (patch.action === "del") {
|
|
155
|
+
return handleDel(target, patch);
|
|
156
|
+
} else if (patch.action === "put") {
|
|
157
|
+
return handlePut(target, patch, state);
|
|
158
|
+
} else {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
var handleInsert = (target, patch) => {
|
|
163
|
+
const index = charPath(target, patch.path);
|
|
164
|
+
if (index == null) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
const text = patch.values.map((v) => v ? v.toString() : "").join("");
|
|
168
|
+
return [
|
|
169
|
+
{
|
|
170
|
+
from: index,
|
|
171
|
+
to: index,
|
|
172
|
+
insert: text
|
|
173
|
+
}
|
|
174
|
+
];
|
|
175
|
+
};
|
|
176
|
+
var handleSplice = (target, patch) => {
|
|
177
|
+
const index = charPath(target, patch.path);
|
|
178
|
+
if (index == null) {
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
return [
|
|
182
|
+
{
|
|
183
|
+
from: index,
|
|
184
|
+
insert: patch.value
|
|
185
|
+
}
|
|
186
|
+
];
|
|
187
|
+
};
|
|
188
|
+
var handleDel = (target, patch) => {
|
|
189
|
+
const index = charPath(target, patch.path);
|
|
190
|
+
if (index == null) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
const length = patch.length || 1;
|
|
194
|
+
return [
|
|
195
|
+
{
|
|
196
|
+
from: index,
|
|
197
|
+
to: index + length
|
|
198
|
+
}
|
|
199
|
+
];
|
|
200
|
+
};
|
|
201
|
+
var handlePut = (target, patch, state) => {
|
|
202
|
+
const index = charPath(target, [
|
|
203
|
+
...patch.path,
|
|
204
|
+
0
|
|
205
|
+
]);
|
|
206
|
+
if (index == null) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
const length = state.doc.length;
|
|
210
|
+
if (typeof patch.value !== "string") {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
return [
|
|
214
|
+
{
|
|
215
|
+
from: 0,
|
|
216
|
+
to: length,
|
|
217
|
+
insert: patch.value
|
|
218
|
+
}
|
|
219
|
+
];
|
|
220
|
+
};
|
|
221
|
+
var charPath = (textPath, candidatePath) => {
|
|
222
|
+
if (candidatePath.length !== textPath.length + 1) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
for (let i = 0; i < textPath.length; i++) {
|
|
226
|
+
if (textPath[i] !== candidatePath[i]) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const index = candidatePath[candidatePath.length - 1];
|
|
231
|
+
if (typeof index === "number") {
|
|
232
|
+
return index;
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
238
|
+
var PatchSemaphore = class {
|
|
239
|
+
constructor(_field) {
|
|
240
|
+
this._field = _field;
|
|
241
|
+
this._inReconcile = false;
|
|
242
|
+
this._queue = [];
|
|
243
|
+
this.reconcile = (handle, view) => {
|
|
244
|
+
if (this._inReconcile) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
this._inReconcile = true;
|
|
248
|
+
const path = getPath(view.state, this._field);
|
|
249
|
+
const oldHeads = getLastHeads(view.state, this._field);
|
|
250
|
+
let selection = view.state.selection;
|
|
251
|
+
const transactions = view.state.field(this._field).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
252
|
+
const toInvert = transactions.slice().reverse();
|
|
253
|
+
for (const tx of toInvert) {
|
|
254
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
255
|
+
selection = selection.map(inverted);
|
|
256
|
+
view.dispatch({
|
|
257
|
+
changes: inverted,
|
|
258
|
+
annotations: reconcileAnnotationType.of(true)
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
262
|
+
if (newHeads === null || newHeads === void 0) {
|
|
263
|
+
newHeads = automerge2.getHeads(handle.docSync());
|
|
264
|
+
}
|
|
265
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
|
|
266
|
+
updateCodeMirror(view, selection, path, diff);
|
|
267
|
+
view.dispatch({
|
|
268
|
+
effects: updateHeads(newHeads),
|
|
269
|
+
annotations: reconcileAnnotationType.of({})
|
|
270
|
+
});
|
|
271
|
+
this._inReconcile = false;
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
// packages/ui/react-ui-editor/src/util/cursor.ts
|
|
277
|
+
import { Facet } from "@codemirror/state";
|
|
278
|
+
var DEFAULT_CURSOR_CONVERTER = {
|
|
279
|
+
toCursor: (position) => position.toString(),
|
|
280
|
+
fromCursor: (cursor) => parseInt(cursor)
|
|
281
|
+
};
|
|
282
|
+
var CursorConverter = Facet.define({
|
|
283
|
+
combine: (providers) => providers[0] ?? DEFAULT_CURSOR_CONVERTER
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// packages/ui/react-ui-editor/src/util/util.ts
|
|
287
|
+
import { log } from "@dxos/log";
|
|
288
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
289
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
290
|
+
try {
|
|
291
|
+
return fn(...args);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
log.catch(error, void 0, {
|
|
294
|
+
F: __dxlog_file,
|
|
295
|
+
L: 16,
|
|
296
|
+
S: void 0,
|
|
297
|
+
C: (f, a) => f(...a)
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
303
|
+
var semaphoreFacet = Facet2.define({
|
|
304
|
+
combine: (values) => values.at(-1)
|
|
305
|
+
});
|
|
306
|
+
var automerge3 = ({ handle, path }) => {
|
|
307
|
+
const stateField = StateField.define({
|
|
308
|
+
create: () => ({
|
|
309
|
+
lastHeads: A.getHeads(handle.docSync()),
|
|
310
|
+
unreconciledTransactions: [],
|
|
311
|
+
path: path.slice()
|
|
312
|
+
}),
|
|
313
|
+
update: (value, tr) => {
|
|
314
|
+
const result = {
|
|
315
|
+
lastHeads: value.lastHeads,
|
|
316
|
+
unreconciledTransactions: value.unreconciledTransactions.slice(),
|
|
317
|
+
path: path.slice()
|
|
318
|
+
};
|
|
319
|
+
let clearUnreconciled = false;
|
|
320
|
+
for (const effect of tr.effects) {
|
|
321
|
+
if (effect.is(effectType)) {
|
|
322
|
+
result.lastHeads = effect.value.newHeads;
|
|
323
|
+
clearUnreconciled = true;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (clearUnreconciled) {
|
|
327
|
+
result.unreconciledTransactions = [];
|
|
328
|
+
} else {
|
|
329
|
+
if (!isReconcileTx(tr)) {
|
|
330
|
+
result.unreconciledTransactions.push(tr);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
const semaphore = new PatchSemaphore(stateField);
|
|
337
|
+
const viewPlugin = ViewPlugin.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
338
|
+
constructor(_view) {
|
|
339
|
+
this._view = _view;
|
|
340
|
+
this._handleChange = () => {
|
|
341
|
+
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
342
|
+
};
|
|
343
|
+
handle.addListener("change", this._handleChange);
|
|
344
|
+
}
|
|
345
|
+
update(update4) {
|
|
346
|
+
if (update4.transactions.length > 0 && update4.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
347
|
+
queueMicrotask(() => {
|
|
348
|
+
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
destroy() {
|
|
353
|
+
handle.addListener("change", this._handleChange);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
return {
|
|
357
|
+
extension: [
|
|
358
|
+
CursorConverter.of(cursorConverter(handle, path)),
|
|
359
|
+
semaphoreFacet.of(semaphore),
|
|
360
|
+
stateField,
|
|
361
|
+
viewPlugin
|
|
362
|
+
]
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
367
|
+
import { Annotation as Annotation2, Facet as Facet3, RangeSet } from "@codemirror/state";
|
|
368
|
+
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
369
|
+
import { Event } from "@dxos/async";
|
|
370
|
+
import { Context } from "@dxos/context";
|
|
371
|
+
var dummyProvider = {
|
|
372
|
+
remoteStateChange: new Event(),
|
|
373
|
+
open: () => {
|
|
374
|
+
},
|
|
375
|
+
close: () => {
|
|
376
|
+
},
|
|
377
|
+
update: () => {
|
|
378
|
+
},
|
|
379
|
+
getRemoteStates: () => []
|
|
380
|
+
};
|
|
381
|
+
var AwarenessProvider = Facet3.define({
|
|
382
|
+
combine: (providers) => providers[0] ?? dummyProvider
|
|
383
|
+
});
|
|
384
|
+
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
385
|
+
var awareness = (provider = dummyProvider) => {
|
|
386
|
+
return [
|
|
387
|
+
AwarenessProvider.of(provider),
|
|
388
|
+
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
389
|
+
decorations: (value) => value.decorations
|
|
390
|
+
}),
|
|
391
|
+
styles
|
|
392
|
+
];
|
|
393
|
+
};
|
|
394
|
+
var RemoteSelectionsDecorator = class {
|
|
395
|
+
constructor(view) {
|
|
396
|
+
this.decorations = RangeSet.of([]);
|
|
397
|
+
this._ctx = new Context();
|
|
398
|
+
this._lastAnchor = void 0;
|
|
399
|
+
this._lastHead = void 0;
|
|
400
|
+
this._cursorConverter = view.state.facet(CursorConverter);
|
|
401
|
+
this._provider = view.state.facet(AwarenessProvider);
|
|
402
|
+
this._provider.open();
|
|
403
|
+
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
404
|
+
view.dispatch({
|
|
405
|
+
annotations: [
|
|
406
|
+
RemoteSelectionChangedAnnotation.of([])
|
|
407
|
+
]
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
destroy() {
|
|
412
|
+
void this._ctx.dispose();
|
|
413
|
+
this._provider.close();
|
|
414
|
+
}
|
|
415
|
+
update(update4) {
|
|
416
|
+
this._updateLocalSelection(update4);
|
|
417
|
+
this._updateRemoteSelections(update4);
|
|
418
|
+
}
|
|
419
|
+
_updateLocalSelection(update4) {
|
|
420
|
+
const hasFocus = update4.view.hasFocus && update4.view.dom.ownerDocument.hasFocus();
|
|
421
|
+
const { anchor = void 0, head = void 0 } = hasFocus ? update4.state.selection.main : {};
|
|
422
|
+
if (this._lastAnchor === anchor && this._lastHead === head) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
this._lastAnchor = anchor;
|
|
426
|
+
this._lastHead = head;
|
|
427
|
+
this._provider.update(anchor !== void 0 && head !== void 0 ? {
|
|
428
|
+
anchor: this._cursorConverter.toCursor(anchor),
|
|
429
|
+
head: this._cursorConverter.toCursor(head)
|
|
430
|
+
} : void 0);
|
|
431
|
+
}
|
|
432
|
+
_updateRemoteSelections(update4) {
|
|
433
|
+
const decorations = [];
|
|
434
|
+
const awarenessStates = this._provider.getRemoteStates();
|
|
435
|
+
for (const state of awarenessStates) {
|
|
436
|
+
const anchor = state.position?.anchor ? this._cursorConverter.fromCursor(state.position.anchor) : null;
|
|
437
|
+
const head = state.position?.head ? this._cursorConverter.fromCursor(state.position.head) : null;
|
|
438
|
+
if (anchor == null || head == null) {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
const start = Math.min(Math.min(anchor, head), update4.view.state.doc.length);
|
|
442
|
+
const end = Math.min(Math.max(anchor, head), update4.view.state.doc.length);
|
|
443
|
+
const startLine = update4.view.state.doc.lineAt(start);
|
|
444
|
+
const endLine = update4.view.state.doc.lineAt(end);
|
|
445
|
+
const color = state.info.color ?? "#30bced";
|
|
446
|
+
const lightColor = state.info.lightColor ?? color + "33";
|
|
447
|
+
if (startLine.number === endLine.number) {
|
|
448
|
+
decorations.push({
|
|
449
|
+
from: start,
|
|
450
|
+
to: end,
|
|
451
|
+
value: Decoration.mark({
|
|
452
|
+
attributes: {
|
|
453
|
+
style: `background-color: ${lightColor}`
|
|
454
|
+
},
|
|
455
|
+
class: "cm-ySelection"
|
|
456
|
+
})
|
|
457
|
+
});
|
|
458
|
+
} else {
|
|
459
|
+
decorations.push({
|
|
460
|
+
from: start,
|
|
461
|
+
to: startLine.from + startLine.length,
|
|
462
|
+
value: Decoration.mark({
|
|
463
|
+
attributes: {
|
|
464
|
+
style: `background-color: ${color}`
|
|
465
|
+
},
|
|
466
|
+
class: "cm-ySelection"
|
|
467
|
+
})
|
|
468
|
+
});
|
|
469
|
+
decorations.push({
|
|
470
|
+
from: endLine.from,
|
|
471
|
+
to: end,
|
|
472
|
+
value: Decoration.mark({
|
|
473
|
+
attributes: {
|
|
474
|
+
style: `background-color: ${color}`
|
|
475
|
+
},
|
|
476
|
+
class: "cm-ySelection"
|
|
477
|
+
})
|
|
478
|
+
});
|
|
479
|
+
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
480
|
+
const linePos = update4.view.state.doc.line(i).from;
|
|
481
|
+
decorations.push({
|
|
482
|
+
from: linePos,
|
|
483
|
+
to: linePos,
|
|
484
|
+
value: Decoration.line({
|
|
485
|
+
attributes: {
|
|
486
|
+
style: `background-color: ${color}`,
|
|
487
|
+
class: "cm-yLineSelection"
|
|
488
|
+
}
|
|
489
|
+
})
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
decorations.push({
|
|
494
|
+
from: head,
|
|
495
|
+
to: head,
|
|
496
|
+
value: Decoration.widget({
|
|
497
|
+
side: head - anchor > 0 ? -1 : 1,
|
|
498
|
+
block: false,
|
|
499
|
+
widget: new RemoteCaretWidget(state.info.displayName ?? "Anonymous", color)
|
|
500
|
+
})
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
this.decorations = Decoration.set(decorations, true);
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
var RemoteCaretWidget = class extends WidgetType {
|
|
507
|
+
constructor(name, color) {
|
|
508
|
+
super();
|
|
509
|
+
this.name = name;
|
|
510
|
+
this.color = color;
|
|
511
|
+
this.name = name;
|
|
512
|
+
this.color = color;
|
|
513
|
+
}
|
|
514
|
+
toDOM() {
|
|
515
|
+
const span = document.createElement("span");
|
|
516
|
+
span.className = "cm-ySelectionCaret";
|
|
517
|
+
span.style.backgroundColor = this.color;
|
|
518
|
+
span.style.borderColor = this.color;
|
|
519
|
+
const dot = document.createElement("div");
|
|
520
|
+
dot.className = "cm-ySelectionCaretDot";
|
|
521
|
+
const info = document.createElement("div");
|
|
522
|
+
info.className = "cm-ySelectionInfo";
|
|
523
|
+
info.innerText = this.name;
|
|
524
|
+
span.appendChild(document.createTextNode("\u2060"));
|
|
525
|
+
span.appendChild(dot);
|
|
526
|
+
span.appendChild(document.createTextNode("\u2060"));
|
|
527
|
+
span.appendChild(info);
|
|
528
|
+
span.appendChild(document.createTextNode("\u2060"));
|
|
529
|
+
return span;
|
|
530
|
+
}
|
|
531
|
+
eq(widget) {
|
|
532
|
+
return widget.color === this.color;
|
|
533
|
+
}
|
|
534
|
+
compare(widget) {
|
|
535
|
+
return widget.color === this.color;
|
|
536
|
+
}
|
|
537
|
+
updateDOM() {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
get estimatedHeight() {
|
|
541
|
+
return -1;
|
|
542
|
+
}
|
|
543
|
+
ignoreEvent() {
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
var styles = EditorView.baseTheme({
|
|
548
|
+
".cm-ySelection": {},
|
|
549
|
+
".cm-yLineSelection": {
|
|
550
|
+
padding: 0,
|
|
551
|
+
margin: "0px 2px 0px 4px"
|
|
552
|
+
},
|
|
553
|
+
".cm-ySelectionCaret": {
|
|
554
|
+
position: "relative",
|
|
555
|
+
borderLeft: "1px solid black",
|
|
556
|
+
borderRight: "1px solid black",
|
|
557
|
+
marginLeft: "-1px",
|
|
558
|
+
marginRight: "-1px",
|
|
559
|
+
boxSizing: "border-box",
|
|
560
|
+
display: "inline"
|
|
561
|
+
},
|
|
562
|
+
".cm-ySelectionCaretDot": {
|
|
563
|
+
borderRadius: "50%",
|
|
564
|
+
position: "absolute",
|
|
565
|
+
width: ".4em",
|
|
566
|
+
height: ".4em",
|
|
567
|
+
top: "-.2em",
|
|
568
|
+
left: "-.2em",
|
|
569
|
+
backgroundColor: "inherit",
|
|
570
|
+
transition: "transform .3s ease-in-out",
|
|
571
|
+
boxSizing: "border-box"
|
|
572
|
+
},
|
|
573
|
+
".cm-ySelectionCaret:hover > .cm-ySelectionCaretDot": {
|
|
574
|
+
transformOrigin: "bottom center",
|
|
575
|
+
transform: "scale(0)"
|
|
576
|
+
},
|
|
577
|
+
".cm-ySelectionInfo": {
|
|
578
|
+
position: "absolute",
|
|
579
|
+
top: "-1.05em",
|
|
580
|
+
left: "-1px",
|
|
581
|
+
fontSize: ".75em",
|
|
582
|
+
fontFamily: "serif",
|
|
583
|
+
fontStyle: "normal",
|
|
584
|
+
fontWeight: "normal",
|
|
585
|
+
lineHeight: "normal",
|
|
586
|
+
userSelect: "none",
|
|
587
|
+
color: "white",
|
|
588
|
+
paddingLeft: "2px",
|
|
589
|
+
paddingRight: "2px",
|
|
590
|
+
zIndex: 101,
|
|
591
|
+
transition: "opacity .3s ease-in-out",
|
|
592
|
+
backgroundColor: "inherit",
|
|
593
|
+
// these should be separate
|
|
594
|
+
opacity: 0,
|
|
595
|
+
transitionDelay: "0s",
|
|
596
|
+
whiteSpace: "nowrap"
|
|
597
|
+
},
|
|
598
|
+
".cm-ySelectionCaret:hover > .cm-ySelectionInfo": {
|
|
599
|
+
opacity: 1,
|
|
600
|
+
transitionDelay: "0s"
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
42
605
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
43
606
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
44
607
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
45
|
-
import { drawSelection, EditorView, placeholder } from "@codemirror/view";
|
|
608
|
+
import { drawSelection, EditorView as EditorView2, placeholder } from "@codemirror/view";
|
|
46
609
|
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
47
|
-
|
|
610
|
+
EditorView2.lineWrapping,
|
|
48
611
|
// TODO(burdon): Compare with minimalSetup.
|
|
49
612
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
50
613
|
bracketMatching(),
|
|
@@ -55,11 +618,11 @@ var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
|
55
618
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
56
619
|
].filter(Boolean);
|
|
57
620
|
|
|
58
|
-
// packages/ui/react-ui-editor/src/
|
|
59
|
-
import { EditorView as
|
|
621
|
+
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
622
|
+
import { EditorView as EditorView3, keymap as keymap2 } from "@codemirror/view";
|
|
60
623
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
61
624
|
import { invariant } from "@dxos/invariant";
|
|
62
|
-
var
|
|
625
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
63
626
|
var defaultOptions = {
|
|
64
627
|
effect: 2,
|
|
65
628
|
maxParticles: 200,
|
|
@@ -104,7 +667,7 @@ var blast = (options = defaultOptions) => {
|
|
|
104
667
|
};
|
|
105
668
|
return [
|
|
106
669
|
// Cursor moved.
|
|
107
|
-
|
|
670
|
+
EditorView3.updateListener.of((update4) => {
|
|
108
671
|
if (blaster?.node !== update4.view.scrollDOM) {
|
|
109
672
|
if (blaster) {
|
|
110
673
|
blaster.destroy();
|
|
@@ -186,7 +749,7 @@ var Blaster = class {
|
|
|
186
749
|
}
|
|
187
750
|
initialize() {
|
|
188
751
|
invariant(!this._canvas && !this._ctx, void 0, {
|
|
189
|
-
F:
|
|
752
|
+
F: __dxlog_file2,
|
|
190
753
|
L: 138,
|
|
191
754
|
S: this,
|
|
192
755
|
A: [
|
|
@@ -223,7 +786,7 @@ var Blaster = class {
|
|
|
223
786
|
}
|
|
224
787
|
start() {
|
|
225
788
|
invariant(this._canvas && this._ctx, void 0, {
|
|
226
|
-
F:
|
|
789
|
+
F: __dxlog_file2,
|
|
227
790
|
L: 177,
|
|
228
791
|
S: this,
|
|
229
792
|
A: [
|
|
@@ -365,11 +928,49 @@ var random = (min, max) => {
|
|
|
365
928
|
return min + ~~(Math.random() * (max - min + 1));
|
|
366
929
|
};
|
|
367
930
|
|
|
368
|
-
// packages/ui/react-ui-editor/src/
|
|
369
|
-
import { ViewPlugin, EditorView as
|
|
370
|
-
import
|
|
931
|
+
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
932
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView4, Decoration as Decoration2 } from "@codemirror/view";
|
|
933
|
+
import get2 from "lodash.get";
|
|
371
934
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
372
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"
|
|
970
|
+
}
|
|
971
|
+
];
|
|
972
|
+
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
973
|
+
|
|
373
974
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
374
975
|
import { mx } from "@dxos/react-ui-theme";
|
|
375
976
|
var headings = {
|
|
@@ -411,31 +1012,33 @@ var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
|
411
1012
|
var codeMark = "font-mono text-primary-500";
|
|
412
1013
|
var inlineUrl = mx(code, "px-1");
|
|
413
1014
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
414
|
-
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800";
|
|
415
1015
|
|
|
416
1016
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
417
1017
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
418
1018
|
var tokens = tailwindConfig({}).theme;
|
|
419
1019
|
|
|
420
|
-
// packages/ui/react-ui-editor/src/
|
|
1020
|
+
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
421
1021
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
422
|
-
var
|
|
423
|
-
"& .cm-
|
|
424
|
-
|
|
425
|
-
paddingInline: "4px !important"
|
|
1022
|
+
var styles2 = EditorView4.baseTheme({
|
|
1023
|
+
"& .cm-codeblock": {
|
|
1024
|
+
fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
|
|
426
1025
|
},
|
|
427
|
-
|
|
428
|
-
background:
|
|
1026
|
+
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1027
|
+
background: get2(tokens, "extend.colors.neutral.50")
|
|
429
1028
|
},
|
|
430
|
-
|
|
431
|
-
background:
|
|
1029
|
+
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1030
|
+
background: get2(tokens, "extend.colors.neutral.850")
|
|
432
1031
|
},
|
|
433
|
-
|
|
1032
|
+
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1033
|
+
display: "block",
|
|
1034
|
+
paddingInline: "4px !important"
|
|
1035
|
+
},
|
|
1036
|
+
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
434
1037
|
paddingTop: "4px !important",
|
|
435
1038
|
borderTopLeftRadius: "4px",
|
|
436
1039
|
borderTopRightRadius: "4px"
|
|
437
1040
|
},
|
|
438
|
-
|
|
1041
|
+
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
439
1042
|
paddingBottom: "4px !important",
|
|
440
1043
|
borderBottomLeftRadius: "4px",
|
|
441
1044
|
borderBottomRightRadius: "4px"
|
|
@@ -460,16 +1063,16 @@ var code2 = () => {
|
|
|
460
1063
|
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
461
1064
|
for (let i = range[0]; i <= range[1]; i++) {
|
|
462
1065
|
const block = blocks[i];
|
|
463
|
-
decorations.push(
|
|
464
|
-
class: mx2("cm-
|
|
1066
|
+
decorations.push(Decoration2.line({
|
|
1067
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
465
1068
|
}).range(block.from));
|
|
466
1069
|
}
|
|
467
1070
|
}
|
|
468
1071
|
}
|
|
469
|
-
return
|
|
1072
|
+
return Decoration2.set(decorations);
|
|
470
1073
|
};
|
|
471
1074
|
return [
|
|
472
|
-
|
|
1075
|
+
ViewPlugin3.fromClass(class {
|
|
473
1076
|
constructor(view) {
|
|
474
1077
|
this.decorations = getDecorations(view);
|
|
475
1078
|
}
|
|
@@ -481,73 +1084,21 @@ var code2 = () => {
|
|
|
481
1084
|
}, {
|
|
482
1085
|
decorations: (value) => value.decorations
|
|
483
1086
|
}),
|
|
484
|
-
|
|
485
|
-
];
|
|
486
|
-
};
|
|
487
|
-
|
|
488
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
|
|
489
|
-
import { keymap as keymap3 } from "@codemirror/view";
|
|
490
|
-
var defaultItems = [
|
|
491
|
-
"hello world!",
|
|
492
|
-
"this is a test.",
|
|
493
|
-
"this is [DXOS](https://dxos.org)"
|
|
494
|
-
];
|
|
495
|
-
var demo = ({ delay = 75, items = defaultItems } = {}) => {
|
|
496
|
-
let t;
|
|
497
|
-
let idx = 0;
|
|
498
|
-
return [
|
|
499
|
-
keymap3.of([
|
|
500
|
-
{
|
|
501
|
-
// Reset.
|
|
502
|
-
key: "alt-meta-'",
|
|
503
|
-
run: (view) => {
|
|
504
|
-
clearTimeout(t);
|
|
505
|
-
idx = 0;
|
|
506
|
-
return true;
|
|
507
|
-
}
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
// Next prompt.
|
|
511
|
-
// TODO(burdon): Press 1-9 to select prompt?
|
|
512
|
-
key: "shift-meta-'",
|
|
513
|
-
run: (view) => {
|
|
514
|
-
clearTimeout(t);
|
|
515
|
-
const text = items[idx++];
|
|
516
|
-
if (idx === items?.length) {
|
|
517
|
-
idx = 0;
|
|
518
|
-
}
|
|
519
|
-
let i = 0;
|
|
520
|
-
const insert = (d = 0) => {
|
|
521
|
-
t = setTimeout(() => {
|
|
522
|
-
const pos = view.state.selection.main.head;
|
|
523
|
-
view.dispatch({
|
|
524
|
-
changes: {
|
|
525
|
-
from: pos,
|
|
526
|
-
insert: text[i++]
|
|
527
|
-
},
|
|
528
|
-
selection: {
|
|
529
|
-
anchor: pos + 1
|
|
530
|
-
}
|
|
531
|
-
});
|
|
532
|
-
if (i < text.length) {
|
|
533
|
-
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
534
|
-
}
|
|
535
|
-
}, d);
|
|
536
|
-
};
|
|
537
|
-
insert();
|
|
538
|
-
return true;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
])
|
|
1087
|
+
styles2
|
|
542
1088
|
];
|
|
543
1089
|
};
|
|
544
1090
|
|
|
545
|
-
// packages/ui/react-ui-editor/src/
|
|
546
|
-
import {
|
|
1091
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1092
|
+
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1093
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1094
|
+
import get3 from "lodash.get";
|
|
1095
|
+
import sortBy from "lodash.sortby";
|
|
547
1096
|
import { debounce } from "@dxos/async";
|
|
548
1097
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
549
|
-
|
|
550
|
-
|
|
1098
|
+
import { log as log2 } from "@dxos/log";
|
|
1099
|
+
import { nonNullable } from "@dxos/util";
|
|
1100
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1101
|
+
var styles3 = EditorView5.baseTheme({
|
|
551
1102
|
"& .cm-bookmark": {
|
|
552
1103
|
cursor: "pointer",
|
|
553
1104
|
margin: "4px",
|
|
@@ -556,17 +1107,103 @@ var styles2 = EditorView4.baseTheme({
|
|
|
556
1107
|
},
|
|
557
1108
|
"& .cm-bookmark-selected": {
|
|
558
1109
|
backgroundColor: "orange"
|
|
1110
|
+
},
|
|
1111
|
+
"& .cm-comment": {
|
|
1112
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.50")
|
|
1113
|
+
},
|
|
1114
|
+
"& .cm-comment-active": {
|
|
1115
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
var marks = {
|
|
1119
|
+
highlight: Decoration3.mark({
|
|
1120
|
+
class: "cm-comment"
|
|
1121
|
+
}),
|
|
1122
|
+
highlightActive: Decoration3.mark({
|
|
1123
|
+
class: "cm-comment-active"
|
|
1124
|
+
})
|
|
1125
|
+
};
|
|
1126
|
+
var setFocus = (view, thread) => {
|
|
1127
|
+
const range = view.state.field(commentsStateField).ranges.find((range2) => range2.id === thread);
|
|
1128
|
+
if (!range) {
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
view.dispatch({
|
|
1132
|
+
effects: setSelection.of({
|
|
1133
|
+
active: thread
|
|
1134
|
+
}),
|
|
1135
|
+
selection: {
|
|
1136
|
+
anchor: range.from
|
|
1137
|
+
},
|
|
1138
|
+
scrollIntoView: true
|
|
1139
|
+
});
|
|
1140
|
+
};
|
|
1141
|
+
var setCommentRange = StateEffect2.define();
|
|
1142
|
+
var setSelection = StateEffect2.define();
|
|
1143
|
+
var setCommentState = StateEffect2.define();
|
|
1144
|
+
var commentsStateField = StateField2.define({
|
|
1145
|
+
create: () => ({
|
|
1146
|
+
ranges: []
|
|
1147
|
+
}),
|
|
1148
|
+
update: (value, tr) => {
|
|
1149
|
+
const cursorConverter3 = tr.state.facet(CursorConverter);
|
|
1150
|
+
for (const effect of tr.effects) {
|
|
1151
|
+
if (effect.is(setSelection)) {
|
|
1152
|
+
return {
|
|
1153
|
+
...value,
|
|
1154
|
+
...effect.value
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
if (effect.is(setCommentRange)) {
|
|
1158
|
+
const { comments: comments2 } = effect.value;
|
|
1159
|
+
const ranges = comments2.map((comment) => {
|
|
1160
|
+
const range = getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1161
|
+
return range && {
|
|
1162
|
+
...comment,
|
|
1163
|
+
...range
|
|
1164
|
+
};
|
|
1165
|
+
}).filter(nonNullable);
|
|
1166
|
+
return {
|
|
1167
|
+
...value,
|
|
1168
|
+
ranges
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
if (effect.is(setCommentState)) {
|
|
1172
|
+
return effect.value;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return value;
|
|
559
1176
|
}
|
|
560
1177
|
});
|
|
561
|
-
var
|
|
562
|
-
|
|
1178
|
+
var highlightDecorations = EditorView5.decorations.compute([
|
|
1179
|
+
commentsStateField
|
|
1180
|
+
], (state) => {
|
|
1181
|
+
const { active, ranges } = state.field(commentsStateField);
|
|
1182
|
+
const decorations = sortBy(ranges ?? [], (range) => range.from)?.flatMap((selection) => {
|
|
1183
|
+
if (selection.from === selection.to) {
|
|
1184
|
+
return void 0;
|
|
1185
|
+
}
|
|
1186
|
+
const range = {
|
|
1187
|
+
from: selection.from,
|
|
1188
|
+
to: selection.to
|
|
1189
|
+
};
|
|
1190
|
+
if (selection.id === active) {
|
|
1191
|
+
return marks.highlightActive.range(range.from, range.to);
|
|
1192
|
+
} else {
|
|
1193
|
+
return marks.highlight.range(range.from, range.to);
|
|
1194
|
+
}
|
|
1195
|
+
}).filter(nonNullable) ?? [];
|
|
1196
|
+
return Decoration3.set(decorations);
|
|
1197
|
+
});
|
|
1198
|
+
var BookmarkWidget = class extends WidgetType2 {
|
|
1199
|
+
constructor(_anchor, _id, _handleClick) {
|
|
563
1200
|
super();
|
|
564
|
-
this.
|
|
1201
|
+
this._anchor = _anchor;
|
|
565
1202
|
this._id = _id;
|
|
566
1203
|
this._handleClick = _handleClick;
|
|
567
1204
|
invariant2(this._id, void 0, {
|
|
568
|
-
F:
|
|
569
|
-
L:
|
|
1205
|
+
F: __dxlog_file3,
|
|
1206
|
+
L: 169,
|
|
570
1207
|
S: this,
|
|
571
1208
|
A: [
|
|
572
1209
|
"this._id",
|
|
@@ -575,227 +1212,286 @@ var BookmarkWidget = class extends WidgetType {
|
|
|
575
1212
|
});
|
|
576
1213
|
}
|
|
577
1214
|
eq(other) {
|
|
578
|
-
return this._id === other._id;
|
|
1215
|
+
return this._anchor === other._anchor && this._id === other._id;
|
|
579
1216
|
}
|
|
580
1217
|
toDOM() {
|
|
581
1218
|
const span = document.createElement("span");
|
|
582
1219
|
span.className = "cm-bookmark";
|
|
583
|
-
span.textContent = "\
|
|
584
|
-
|
|
1220
|
+
span.textContent = "\u203B";
|
|
1221
|
+
if (this._handleClick) {
|
|
1222
|
+
span.onclick = () => this._handleClick();
|
|
1223
|
+
}
|
|
585
1224
|
return span;
|
|
586
1225
|
}
|
|
587
1226
|
};
|
|
588
1227
|
var comments = (options = {}) => {
|
|
589
|
-
|
|
590
|
-
const
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
1228
|
+
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
|
+
const createCommentThread = (view) => {
|
|
1230
|
+
const cursorConverter3 = view.state.facet(CursorConverter);
|
|
1231
|
+
invariant2(options.onCreate, void 0, {
|
|
1232
|
+
F: __dxlog_file3,
|
|
1233
|
+
L: 225,
|
|
1234
|
+
S: void 0,
|
|
1235
|
+
A: [
|
|
1236
|
+
"options.onCreate",
|
|
1237
|
+
""
|
|
1238
|
+
]
|
|
1239
|
+
});
|
|
1240
|
+
const { head, from, to } = view.state.selection.main;
|
|
1241
|
+
if (from === to) {
|
|
1242
|
+
return false;
|
|
1243
|
+
}
|
|
1244
|
+
const relPos = getCursorFromRange(cursorConverter3, {
|
|
1245
|
+
from,
|
|
1246
|
+
to
|
|
1247
|
+
});
|
|
1248
|
+
if (relPos) {
|
|
1249
|
+
const id = callbackWrapper(options.onCreate)(relPos);
|
|
1250
|
+
if (id) {
|
|
1251
|
+
view.dispatch({
|
|
1252
|
+
effects: setSelection.of({
|
|
1253
|
+
active: id
|
|
1254
|
+
}),
|
|
1255
|
+
selection: {
|
|
1256
|
+
anchor: from
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
if (options.footnote) {
|
|
1260
|
+
const tag = `[^${id}]`;
|
|
1261
|
+
view.dispatch({
|
|
1262
|
+
changes: {
|
|
1263
|
+
from: head,
|
|
1264
|
+
insert: tag
|
|
1265
|
+
},
|
|
1266
|
+
selection: {
|
|
1267
|
+
anchor: head + tag.length
|
|
1268
|
+
}
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
return true;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
return false;
|
|
1275
|
+
};
|
|
1276
|
+
const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
|
|
1277
|
+
static {
|
|
1278
|
+
// Match markdown footnotes (option).
|
|
1279
|
+
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
1280
|
+
this.bookmarkMatcher = new MatchDecorator({
|
|
1281
|
+
regexp: /\[\^(\w+)\]/g,
|
|
1282
|
+
decoration: (match, view, pos) => {
|
|
1283
|
+
const id = match[1];
|
|
1284
|
+
return Decoration3.replace({
|
|
1285
|
+
id,
|
|
1286
|
+
widget: new BookmarkWidget(pos, id)
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
599
1289
|
});
|
|
600
1290
|
}
|
|
601
|
-
});
|
|
602
|
-
const bookmarks = ViewPlugin2.fromClass(class {
|
|
603
1291
|
constructor(view) {
|
|
604
|
-
this.bookmarks = bookmarkMatcher.createDeco(view);
|
|
1292
|
+
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
605
1293
|
}
|
|
606
1294
|
update(update4) {
|
|
607
|
-
this.bookmarks = bookmarkMatcher.updateDeco(update4, this.bookmarks);
|
|
1295
|
+
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update4, this.bookmarks);
|
|
608
1296
|
}
|
|
609
1297
|
}, {
|
|
610
1298
|
decorations: (instance) => instance.bookmarks,
|
|
611
|
-
provide: (plugin) =>
|
|
612
|
-
return view.plugin(plugin)?.bookmarks ||
|
|
1299
|
+
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1300
|
+
return view.plugin(plugin)?.bookmarks || Decoration3.none;
|
|
613
1301
|
})
|
|
614
1302
|
});
|
|
615
|
-
const handleUpdate = debounce((data) => {
|
|
616
|
-
options.onUpdate?.(data);
|
|
617
|
-
}, 200);
|
|
618
1303
|
return [
|
|
619
|
-
|
|
1304
|
+
bookmarksViewPlugin,
|
|
1305
|
+
commentsStateField,
|
|
1306
|
+
highlightDecorations,
|
|
1307
|
+
styles3,
|
|
1308
|
+
//
|
|
1309
|
+
// Keymap.
|
|
1310
|
+
//
|
|
1311
|
+
options.onCreate ? keymap3.of([
|
|
620
1312
|
{
|
|
621
|
-
key: options?.key ?? "
|
|
622
|
-
run: (
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
1313
|
+
key: options?.key ?? "meta-'",
|
|
1314
|
+
run: callbackWrapper(createCommentThread)
|
|
1315
|
+
}
|
|
1316
|
+
]) : [],
|
|
1317
|
+
//
|
|
1318
|
+
// Hover tooltip (for key shortcut hints, etc.)
|
|
1319
|
+
// TODO(burdon): Factor out to generic hints extension for current selection/line.
|
|
1320
|
+
//
|
|
1321
|
+
options.onHover ? hoverTooltip((view, pos) => {
|
|
1322
|
+
const selection = view.state.selection.main;
|
|
1323
|
+
if (selection && pos >= selection.from && pos <= selection.to) {
|
|
1324
|
+
return {
|
|
1325
|
+
pos: selection.from,
|
|
1326
|
+
end: selection.to,
|
|
1327
|
+
above: true,
|
|
1328
|
+
create: () => {
|
|
1329
|
+
const el = document.createElement("div");
|
|
1330
|
+
options.onHover?.(el);
|
|
1331
|
+
return {
|
|
1332
|
+
dom: el,
|
|
1333
|
+
offset: {
|
|
1334
|
+
x: 0,
|
|
1335
|
+
y: 8
|
|
634
1336
|
}
|
|
635
|
-
}
|
|
636
|
-
return true;
|
|
1337
|
+
};
|
|
637
1338
|
}
|
|
638
|
-
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
]),
|
|
642
|
-
bookmarks,
|
|
643
|
-
// Monitor cursor movement.
|
|
644
|
-
EditorView4.updateListener.of((update4) => {
|
|
645
|
-
active = void 0;
|
|
646
|
-
if (!options.onUpdate) {
|
|
647
|
-
return;
|
|
1339
|
+
};
|
|
648
1340
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
1341
|
+
return null;
|
|
1342
|
+
}, {
|
|
1343
|
+
hideOnChange: true,
|
|
1344
|
+
hoverTime: 1e3
|
|
1345
|
+
}) : [],
|
|
1346
|
+
//
|
|
1347
|
+
// Monitor cursor movement and text updates.
|
|
1348
|
+
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1349
|
+
//
|
|
1350
|
+
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1351
|
+
const cursorConverter3 = view.state.facet(CursorConverter);
|
|
1352
|
+
{
|
|
1353
|
+
let mod = false;
|
|
1354
|
+
const { active, ranges } = state.field(commentsStateField);
|
|
1355
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1356
|
+
ranges.forEach((range) => {
|
|
1357
|
+
if (from2 === to2) {
|
|
1358
|
+
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1359
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
|
+
log2.info("deleted comment", {
|
|
1361
|
+
thread: range.id
|
|
1362
|
+
}, {
|
|
1363
|
+
F: __dxlog_file3,
|
|
1364
|
+
L: 359,
|
|
1365
|
+
S: void 0,
|
|
1366
|
+
C: (f, a) => f(...a)
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
if (from <= range.to) {
|
|
1371
|
+
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
|
+
Object.assign(range, newRange);
|
|
1373
|
+
mod = true;
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
666
1376
|
});
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
1377
|
+
if (mod) {
|
|
1378
|
+
view.dispatch({
|
|
1379
|
+
effects: setCommentState.of({
|
|
1380
|
+
active,
|
|
1381
|
+
ranges
|
|
1382
|
+
})
|
|
1383
|
+
});
|
|
671
1384
|
}
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1385
|
+
}
|
|
1386
|
+
{
|
|
1387
|
+
const { head } = state.selection.main;
|
|
1388
|
+
let min = Infinity;
|
|
1389
|
+
const { active, closest, ranges } = state.field(commentsStateField);
|
|
1390
|
+
const selected = {
|
|
1391
|
+
active: void 0,
|
|
1392
|
+
closest: void 0
|
|
1393
|
+
};
|
|
1394
|
+
ranges.forEach((comment) => {
|
|
1395
|
+
const d = Math.min(Math.abs(head - comment.from), Math.abs(head - comment.to));
|
|
1396
|
+
if (head >= comment.from && head <= comment.to) {
|
|
1397
|
+
selected.active = comment.id;
|
|
1398
|
+
}
|
|
1399
|
+
if (d < min) {
|
|
1400
|
+
selected.closest = comment.id;
|
|
1401
|
+
min = d;
|
|
1402
|
+
}
|
|
681
1403
|
});
|
|
1404
|
+
if (selected.active !== active || selected.closest !== closest) {
|
|
1405
|
+
view.dispatch({
|
|
1406
|
+
effects: setSelection.of(selected)
|
|
1407
|
+
});
|
|
1408
|
+
handleSelect({
|
|
1409
|
+
...selected,
|
|
1410
|
+
ranges: ranges.map((range) => ({
|
|
1411
|
+
...range,
|
|
1412
|
+
location: view.coordsAtPos(range.from)
|
|
1413
|
+
}))
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
682
1416
|
}
|
|
683
|
-
})
|
|
684
|
-
styles2
|
|
1417
|
+
})
|
|
685
1418
|
];
|
|
686
1419
|
};
|
|
1420
|
+
var getCursorFromRange = (cursorConverter3, range) => {
|
|
1421
|
+
const from = cursorConverter3.toCursor(range.from);
|
|
1422
|
+
const to = cursorConverter3.toCursor(range.to, -1);
|
|
1423
|
+
return [
|
|
1424
|
+
from,
|
|
1425
|
+
to
|
|
1426
|
+
].join(":");
|
|
1427
|
+
};
|
|
1428
|
+
var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
1429
|
+
const parts = cursor.split(":");
|
|
1430
|
+
const from = cursorConverter3.fromCursor(parts[0]);
|
|
1431
|
+
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1432
|
+
return from && to ? {
|
|
1433
|
+
from,
|
|
1434
|
+
to
|
|
1435
|
+
} : void 0;
|
|
1436
|
+
};
|
|
687
1437
|
|
|
688
|
-
// packages/ui/react-ui-editor/src/
|
|
689
|
-
import {
|
|
690
|
-
import
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
},
|
|
697
|
-
"& .cm-highlight::before": {
|
|
698
|
-
content: "]"
|
|
699
|
-
},
|
|
700
|
-
"& .cm-highlight-active": {
|
|
701
|
-
backgroundColor: "lime"
|
|
1438
|
+
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
+
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin5, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1440
|
+
import get4 from "lodash.get";
|
|
1441
|
+
var styles4 = EditorView6.baseTheme({
|
|
1442
|
+
"& .cm-hr": {
|
|
1443
|
+
// TODO(burdon): ???
|
|
1444
|
+
// Note that block-level decorations should not have vertical margins,
|
|
1445
|
+
borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.200")}`
|
|
702
1446
|
}
|
|
703
1447
|
});
|
|
704
|
-
var
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
};
|
|
712
|
-
var setHighlights = StateEffect.define();
|
|
713
|
-
var useHighlights = (view, ranges = []) => {
|
|
714
|
-
useEffect(() => {
|
|
715
|
-
view?.dispatch({
|
|
716
|
-
effects: setHighlights.of(ranges)
|
|
717
|
-
});
|
|
718
|
-
}, [
|
|
719
|
-
view,
|
|
720
|
-
ranges
|
|
721
|
-
]);
|
|
722
|
-
};
|
|
723
|
-
var highlightStateField = StateField.define({
|
|
724
|
-
create: () => [],
|
|
725
|
-
update: (threads, tr) => {
|
|
726
|
-
for (const effect of tr.effects) {
|
|
727
|
-
if (effect.is(setHighlights)) {
|
|
728
|
-
return effect.value;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
return threads;
|
|
1448
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
1449
|
+
constructor(_pos) {
|
|
1450
|
+
super();
|
|
1451
|
+
this._pos = _pos;
|
|
1452
|
+
}
|
|
1453
|
+
eq(other) {
|
|
1454
|
+
return this._pos === other._pos;
|
|
732
1455
|
}
|
|
1456
|
+
toDOM(view) {
|
|
1457
|
+
const el = document.createElement("div");
|
|
1458
|
+
el.className = "cm-hr";
|
|
1459
|
+
return el;
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
var placeholderMatcher = new MatchDecorator2({
|
|
1463
|
+
regexp: /^---$/g,
|
|
1464
|
+
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
|
+
widget: new HorizontalRuleWidget(pos)
|
|
1466
|
+
})
|
|
733
1467
|
});
|
|
734
|
-
var
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
const range = {
|
|
740
|
-
from: selection.from,
|
|
741
|
-
to: selection.to + 1
|
|
742
|
-
};
|
|
743
|
-
if (selection.to > selection.from) {
|
|
744
|
-
if (selection.active) {
|
|
745
|
-
return marks.HighlightActive.range(range.from, range.to);
|
|
746
|
-
} else {
|
|
747
|
-
return marks.highlight.range(range.from, range.to);
|
|
748
|
-
}
|
|
749
|
-
} else {
|
|
750
|
-
return [];
|
|
1468
|
+
var hr = () => [
|
|
1469
|
+
styles4,
|
|
1470
|
+
ViewPlugin5.fromClass(class {
|
|
1471
|
+
constructor(view) {
|
|
1472
|
+
this.rules = placeholderMatcher.createDeco(view);
|
|
751
1473
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
});
|
|
755
|
-
var listener = (options) => {
|
|
756
|
-
return EditorView5.updateListener.of((update4) => {
|
|
757
|
-
const { view, state } = update4;
|
|
758
|
-
const { head } = state.selection.main;
|
|
759
|
-
const ranges = state.field(highlightStateField);
|
|
760
|
-
let mod = false;
|
|
761
|
-
const newRanges = ranges.map((range) => {
|
|
762
|
-
const active = head >= range.from && head <= range.to;
|
|
763
|
-
if (active !== range.active) {
|
|
764
|
-
mod = true;
|
|
765
|
-
return {
|
|
766
|
-
...range,
|
|
767
|
-
active
|
|
768
|
-
};
|
|
769
|
-
} else {
|
|
770
|
-
return range;
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
if (mod) {
|
|
774
|
-
view.dispatch({
|
|
775
|
-
effects: setHighlights.of(newRanges)
|
|
776
|
-
});
|
|
777
|
-
options?.onChange?.(newRanges.find((range) => range.active)?.id);
|
|
1474
|
+
update(update4) {
|
|
1475
|
+
this.rules = placeholderMatcher.updateDeco(update4, this.rules);
|
|
778
1476
|
}
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
];
|
|
788
|
-
};
|
|
1477
|
+
}, {
|
|
1478
|
+
decorations: (instance) => instance.rules,
|
|
1479
|
+
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1480
|
+
provide: (plugin) => EditorView6.atomicRanges.of((view) => {
|
|
1481
|
+
return view.plugin(plugin)?.rules || Decoration4.none;
|
|
1482
|
+
})
|
|
1483
|
+
})
|
|
1484
|
+
];
|
|
789
1485
|
|
|
790
|
-
// packages/ui/react-ui-editor/src/
|
|
1486
|
+
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
791
1487
|
import { syntaxTree } from "@codemirror/language";
|
|
792
|
-
import { RangeSetBuilder, StateField as
|
|
793
|
-
import { Decoration as
|
|
1488
|
+
import { RangeSetBuilder, StateField as StateField3 } from "@codemirror/state";
|
|
1489
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
794
1490
|
var image = (options = {}) => {
|
|
795
|
-
return
|
|
1491
|
+
return StateField3.define({
|
|
796
1492
|
create: (state) => update(state, options),
|
|
797
1493
|
update: (_, tr) => update(tr.state, options),
|
|
798
|
-
provide: (field) =>
|
|
1494
|
+
provide: (field) => EditorView7.decorations.from(field)
|
|
799
1495
|
});
|
|
800
1496
|
};
|
|
801
1497
|
var update = (state, options) => {
|
|
@@ -808,7 +1504,8 @@ var update = (state, options) => {
|
|
|
808
1504
|
if (urlNode) {
|
|
809
1505
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
810
1506
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
811
|
-
builder.add(hide ? node.from : node.to, node.to,
|
|
1507
|
+
builder.add(hide ? node.from : node.to, node.to, Decoration5.replace({
|
|
1508
|
+
block: true,
|
|
812
1509
|
widget: new ImageWidget(url)
|
|
813
1510
|
}));
|
|
814
1511
|
}
|
|
@@ -817,13 +1514,14 @@ var update = (state, options) => {
|
|
|
817
1514
|
});
|
|
818
1515
|
return builder.finish();
|
|
819
1516
|
};
|
|
820
|
-
var ImageWidget = class extends
|
|
1517
|
+
var ImageWidget = class extends WidgetType4 {
|
|
821
1518
|
constructor(_url) {
|
|
822
1519
|
super();
|
|
823
1520
|
this._url = _url;
|
|
824
1521
|
}
|
|
1522
|
+
// TODO(burdon): Does this need to be unique for each position?
|
|
825
1523
|
eq(other) {
|
|
826
|
-
return this._url === other
|
|
1524
|
+
return this._url === other._url;
|
|
827
1525
|
}
|
|
828
1526
|
toDOM(view) {
|
|
829
1527
|
const img = document.createElement("img");
|
|
@@ -832,19 +1530,70 @@ var ImageWidget = class extends WidgetType2 {
|
|
|
832
1530
|
return img;
|
|
833
1531
|
}
|
|
834
1532
|
};
|
|
835
|
-
|
|
836
|
-
// packages/ui/react-ui-editor/src/
|
|
837
|
-
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
838
|
-
import { RangeSetBuilder as RangeSetBuilder2, StateField as
|
|
839
|
-
import { Decoration as
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
1533
|
+
|
|
1534
|
+
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1535
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1536
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1537
|
+
import { Decoration as Decoration6, EditorView as EditorView8, WidgetType as WidgetType5, hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
|
1538
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1539
|
+
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
1540
|
+
var link = (options = {}) => {
|
|
1541
|
+
const extensions = [
|
|
1542
|
+
StateField4.define({
|
|
1543
|
+
create: (state) => update2(state, options),
|
|
1544
|
+
update: (_, tr) => update2(tr.state, options),
|
|
1545
|
+
provide: (field) => EditorView8.decorations.from(field)
|
|
1546
|
+
})
|
|
1547
|
+
];
|
|
1548
|
+
if (options.onHover) {
|
|
1549
|
+
extensions.push(
|
|
1550
|
+
// https://codemirror.net/examples/tooltip
|
|
1551
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1552
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1553
|
+
hoverTooltip2((view, pos) => {
|
|
1554
|
+
const { from, text } = view.state.doc.lineAt(pos);
|
|
1555
|
+
const p = pos - from;
|
|
1556
|
+
let idx = 0;
|
|
1557
|
+
let match;
|
|
1558
|
+
do {
|
|
1559
|
+
match = text.substring(idx).match(markdownLinkRegexp);
|
|
1560
|
+
if (!match) {
|
|
1561
|
+
match = void 0;
|
|
1562
|
+
break;
|
|
1563
|
+
}
|
|
1564
|
+
idx = text.indexOf(match[0]);
|
|
1565
|
+
if (p >= idx && p < idx + match[0].length) {
|
|
1566
|
+
break;
|
|
1567
|
+
}
|
|
1568
|
+
idx += match[0].length;
|
|
1569
|
+
} while (true);
|
|
1570
|
+
if (!match) {
|
|
1571
|
+
return null;
|
|
1572
|
+
}
|
|
1573
|
+
const [, , url] = match ?? [];
|
|
1574
|
+
return {
|
|
1575
|
+
pos: idx + from,
|
|
1576
|
+
end: idx + from + match[0].length,
|
|
1577
|
+
above: true,
|
|
1578
|
+
create: () => {
|
|
1579
|
+
const el = document.createElement("div");
|
|
1580
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1581
|
+
options.onHover(el, url);
|
|
1582
|
+
return {
|
|
1583
|
+
dom: el,
|
|
1584
|
+
offset: {
|
|
1585
|
+
x: 0,
|
|
1586
|
+
y: 4
|
|
1587
|
+
}
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
};
|
|
1591
|
+
})
|
|
1592
|
+
);
|
|
1593
|
+
}
|
|
1594
|
+
return extensions;
|
|
1595
|
+
};
|
|
1596
|
+
var LinkButton = class extends WidgetType5 {
|
|
848
1597
|
constructor(_pos, _url, _onAttach) {
|
|
849
1598
|
super();
|
|
850
1599
|
this._pos = _pos;
|
|
@@ -860,15 +1609,14 @@ var LinkButton = class extends WidgetType3 {
|
|
|
860
1609
|
return el;
|
|
861
1610
|
}
|
|
862
1611
|
};
|
|
863
|
-
var LinkText = class extends
|
|
864
|
-
constructor(
|
|
1612
|
+
var LinkText = class extends WidgetType5 {
|
|
1613
|
+
constructor(_text, _url) {
|
|
865
1614
|
super();
|
|
866
|
-
this._pos = _pos;
|
|
867
1615
|
this._text = _text;
|
|
868
1616
|
this._url = _url;
|
|
869
1617
|
}
|
|
870
1618
|
eq(other) {
|
|
871
|
-
return this.
|
|
1619
|
+
return this._url === other._url;
|
|
872
1620
|
}
|
|
873
1621
|
toDOM(view) {
|
|
874
1622
|
const link2 = document.createElement("a");
|
|
@@ -882,7 +1630,7 @@ var LinkText = class extends WidgetType3 {
|
|
|
882
1630
|
link2.onclick = () => {
|
|
883
1631
|
view.dispatch({
|
|
884
1632
|
selection: {
|
|
885
|
-
anchor:
|
|
1633
|
+
anchor: view.posAtDOM(link2)
|
|
886
1634
|
}
|
|
887
1635
|
});
|
|
888
1636
|
};
|
|
@@ -904,12 +1652,12 @@ var update2 = (state, options) => {
|
|
|
904
1652
|
return false;
|
|
905
1653
|
}
|
|
906
1654
|
if (state.readOnly || cursor < node.from || cursor > node.to) {
|
|
907
|
-
builder.add(node.from, node.to,
|
|
908
|
-
widget: new LinkText(
|
|
1655
|
+
builder.add(node.from, node.to, Decoration6.replace({
|
|
1656
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
909
1657
|
}));
|
|
910
1658
|
}
|
|
911
1659
|
if (options.onRender) {
|
|
912
|
-
builder.add(node.to, node.to,
|
|
1660
|
+
builder.add(node.to, node.to, Decoration6.replace({
|
|
913
1661
|
widget: new LinkButton(node.from, url, options.onRender)
|
|
914
1662
|
}));
|
|
915
1663
|
}
|
|
@@ -920,21 +1668,21 @@ var update2 = (state, options) => {
|
|
|
920
1668
|
return builder.finish();
|
|
921
1669
|
};
|
|
922
1670
|
|
|
923
|
-
// packages/ui/react-ui-editor/src/
|
|
924
|
-
import {
|
|
925
|
-
var
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1671
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1672
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1673
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1674
|
+
const extensions = [];
|
|
1675
|
+
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1676
|
+
onFocus(focused);
|
|
1677
|
+
return null;
|
|
1678
|
+
}));
|
|
1679
|
+
onChange && extensions.push(EditorView9.updateListener.of((update4) => {
|
|
1680
|
+
onChange(update4.state.doc.toString());
|
|
1681
|
+
}));
|
|
1682
|
+
return extensions;
|
|
935
1683
|
};
|
|
936
1684
|
|
|
937
|
-
// packages/ui/react-ui-editor/src/
|
|
1685
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
938
1686
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
939
1687
|
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
940
1688
|
import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
|
|
@@ -943,22 +1691,21 @@ import { languages } from "@codemirror/language-data";
|
|
|
943
1691
|
import { searchKeymap } from "@codemirror/search";
|
|
944
1692
|
import { EditorState } from "@codemirror/state";
|
|
945
1693
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
946
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1694
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
947
1695
|
|
|
948
|
-
// packages/ui/react-ui-editor/src/
|
|
1696
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
949
1697
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
950
1698
|
import { HighlightStyle } from "@codemirror/language";
|
|
951
1699
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
952
1700
|
import { Table } from "@lezer/markdown";
|
|
953
|
-
import
|
|
954
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
1701
|
+
import get5 from "lodash.get";
|
|
955
1702
|
var markdownTags = {
|
|
956
1703
|
Blockquote: Tag.define(),
|
|
957
1704
|
CodeMark: Tag.define(),
|
|
958
1705
|
CodeText: Tag.define(),
|
|
959
1706
|
EmphasisMark: Tag.define(),
|
|
960
1707
|
HeaderMark: Tag.define(),
|
|
961
|
-
HorizontalRule: Tag.define(),
|
|
1708
|
+
// HorizontalRule: Tag.define(),
|
|
962
1709
|
InlineCode: Tag.define(),
|
|
963
1710
|
LinkLabel: Tag.define(),
|
|
964
1711
|
LinkReference: Tag.define(),
|
|
@@ -1123,12 +1870,10 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1123
1870
|
class: blockquote
|
|
1124
1871
|
},
|
|
1125
1872
|
// TODO(burdon): Replace with extension.
|
|
1126
|
-
{
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
class: mx3(horizontalRule, readonly && "-indent-[100rem]")
|
|
1131
|
-
},
|
|
1873
|
+
// {
|
|
1874
|
+
// tag: [markdownTags.HorizontalRule],
|
|
1875
|
+
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1876
|
+
// },
|
|
1132
1877
|
// TODO(burdon): Only if being edited.
|
|
1133
1878
|
{
|
|
1134
1879
|
tag: [
|
|
@@ -1139,17 +1884,17 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1139
1884
|
], {
|
|
1140
1885
|
scope: markdownLanguage,
|
|
1141
1886
|
all: {
|
|
1142
|
-
fontFamily:
|
|
1887
|
+
fontFamily: get5(tokens, "fontFamily.body", []).join(",")
|
|
1143
1888
|
}
|
|
1144
1889
|
});
|
|
1145
1890
|
};
|
|
1146
1891
|
|
|
1147
|
-
// packages/ui/react-ui-editor/src/
|
|
1892
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1148
1893
|
var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
1149
1894
|
return [
|
|
1150
1895
|
EditorState.allowMultipleSelections.of(true),
|
|
1151
1896
|
EditorState.tabSize.of(2),
|
|
1152
|
-
|
|
1897
|
+
EditorView10.lineWrapping,
|
|
1153
1898
|
customKeymap(),
|
|
1154
1899
|
bracketMatching2(),
|
|
1155
1900
|
closeBrackets2(),
|
|
@@ -1184,7 +1929,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1184
1929
|
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
1185
1930
|
].filter(Boolean);
|
|
1186
1931
|
};
|
|
1187
|
-
var customKeymap = () =>
|
|
1932
|
+
var customKeymap = () => keymap4.of([
|
|
1188
1933
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1189
1934
|
indentWithTab,
|
|
1190
1935
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
@@ -1197,7 +1942,7 @@ var customKeymap = () => keymap5.of([
|
|
|
1197
1942
|
...searchKeymap
|
|
1198
1943
|
]);
|
|
1199
1944
|
|
|
1200
|
-
// packages/ui/react-ui-editor/src/
|
|
1945
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1201
1946
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1202
1947
|
var mention = ({ onSearch }) => {
|
|
1203
1948
|
return autocompletion2({
|
|
@@ -1220,15 +1965,20 @@ var mention = ({ onSearch }) => {
|
|
|
1220
1965
|
});
|
|
1221
1966
|
};
|
|
1222
1967
|
|
|
1223
|
-
// packages/ui/react-ui-editor/src/
|
|
1968
|
+
// packages/ui/react-ui-editor/src/extensions/mermaid.ts
|
|
1969
|
+
var mermaid = () => {
|
|
1970
|
+
return [];
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1973
|
+
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1224
1974
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1225
1975
|
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
|
|
1226
|
-
import { Decoration as
|
|
1976
|
+
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
1227
1977
|
var table = (options = {}) => {
|
|
1228
1978
|
return StateField5.define({
|
|
1229
1979
|
create: (state) => update3(state, options),
|
|
1230
1980
|
update: (_, tr) => update3(tr.state, options),
|
|
1231
|
-
provide: (field) =>
|
|
1981
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
1232
1982
|
});
|
|
1233
1983
|
};
|
|
1234
1984
|
var update3 = (state, options) => {
|
|
@@ -1272,16 +2022,17 @@ var update3 = (state, options) => {
|
|
|
1272
2022
|
});
|
|
1273
2023
|
tables.forEach((table2) => {
|
|
1274
2024
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
1275
|
-
hide && builder.add(table2.from, table2.to,
|
|
2025
|
+
hide && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
2026
|
+
block: true,
|
|
1276
2027
|
widget: new TableWidget(table2)
|
|
1277
2028
|
}));
|
|
1278
|
-
builder.add(table2.from, table2.to,
|
|
2029
|
+
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
1279
2030
|
class: "cm-table"
|
|
1280
2031
|
}));
|
|
1281
2032
|
});
|
|
1282
2033
|
return builder.finish();
|
|
1283
2034
|
};
|
|
1284
|
-
var TableWidget = class extends
|
|
2035
|
+
var TableWidget = class extends WidgetType6 {
|
|
1285
2036
|
constructor(_table) {
|
|
1286
2037
|
super();
|
|
1287
2038
|
this._table = _table;
|
|
@@ -1315,15 +2066,15 @@ var TableWidget = class extends WidgetType4 {
|
|
|
1315
2066
|
}
|
|
1316
2067
|
};
|
|
1317
2068
|
|
|
1318
|
-
// packages/ui/react-ui-editor/src/
|
|
1319
|
-
import { EditorView as
|
|
1320
|
-
var
|
|
2069
|
+
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2070
|
+
import { EditorView as EditorView12, Decoration as Decoration8, WidgetType as WidgetType7, MatchDecorator as MatchDecorator3, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2071
|
+
var styles5 = EditorView12.baseTheme({
|
|
1321
2072
|
"& .cm-task-item": {
|
|
1322
2073
|
paddingLeft: "4px",
|
|
1323
2074
|
paddingRight: "8px"
|
|
1324
2075
|
}
|
|
1325
2076
|
});
|
|
1326
|
-
var CheckboxWidget = class extends
|
|
2077
|
+
var CheckboxWidget = class extends WidgetType7 {
|
|
1327
2078
|
constructor(_pos, _checked, _indent, _onCheck) {
|
|
1328
2079
|
super();
|
|
1329
2080
|
this._pos = _pos;
|
|
@@ -1358,12 +2109,12 @@ var CheckboxWidget = class extends WidgetType5 {
|
|
|
1358
2109
|
}
|
|
1359
2110
|
};
|
|
1360
2111
|
var tasklist = (options = {}) => {
|
|
1361
|
-
const taskMatcher = new
|
|
2112
|
+
const taskMatcher = new MatchDecorator3({
|
|
1362
2113
|
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
1363
2114
|
decoration: (match, view, pos) => {
|
|
1364
2115
|
const indent = Math.floor(match[1].length / 2);
|
|
1365
2116
|
const checked = match[2] === "x" || match[2] === "X";
|
|
1366
|
-
return
|
|
2117
|
+
return Decoration8.replace({
|
|
1367
2118
|
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
1368
2119
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
1369
2120
|
view.dispatch({
|
|
@@ -1381,7 +2132,7 @@ var tasklist = (options = {}) => {
|
|
|
1381
2132
|
});
|
|
1382
2133
|
}
|
|
1383
2134
|
});
|
|
1384
|
-
const tasks =
|
|
2135
|
+
const tasks = ViewPlugin6.fromClass(class {
|
|
1385
2136
|
constructor(view) {
|
|
1386
2137
|
this.tasks = taskMatcher.createDeco(view);
|
|
1387
2138
|
}
|
|
@@ -1390,69 +2141,116 @@ var tasklist = (options = {}) => {
|
|
|
1390
2141
|
}
|
|
1391
2142
|
}, {
|
|
1392
2143
|
decorations: (value) => value.tasks,
|
|
1393
|
-
provide: (plugin) =>
|
|
1394
|
-
return view.plugin(plugin)?.tasks ||
|
|
2144
|
+
provide: (plugin) => EditorView12.atomicRanges.of((view) => {
|
|
2145
|
+
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
1395
2146
|
})
|
|
1396
2147
|
});
|
|
1397
2148
|
return [
|
|
1398
2149
|
tasks,
|
|
1399
|
-
|
|
2150
|
+
styles5
|
|
1400
2151
|
];
|
|
1401
2152
|
};
|
|
1402
2153
|
|
|
1403
|
-
// packages/ui/react-ui-editor/src/
|
|
1404
|
-
import {
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
2154
|
+
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2155
|
+
import { keymap as keymap5 } from "@codemirror/view";
|
|
2156
|
+
var defaultItems = [
|
|
2157
|
+
"hello world!",
|
|
2158
|
+
"this is a test.",
|
|
2159
|
+
"this is [DXOS](https://dxos.org)"
|
|
2160
|
+
];
|
|
2161
|
+
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
2162
|
+
let t;
|
|
1410
2163
|
let idx = 0;
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
break;
|
|
1421
|
-
}
|
|
1422
|
-
idx += match[0].length;
|
|
1423
|
-
} while (true);
|
|
1424
|
-
if (!match) {
|
|
1425
|
-
return null;
|
|
1426
|
-
}
|
|
1427
|
-
const [, , url] = match ?? [];
|
|
1428
|
-
return {
|
|
1429
|
-
pos: idx + from,
|
|
1430
|
-
end: idx + from + match[0].length,
|
|
1431
|
-
above: true,
|
|
1432
|
-
create: () => {
|
|
1433
|
-
const el = document.createElement("div");
|
|
1434
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1435
|
-
onHover(el, url);
|
|
1436
|
-
return {
|
|
1437
|
-
dom: el,
|
|
1438
|
-
offset: {
|
|
1439
|
-
x: 0,
|
|
1440
|
-
y: 12
|
|
2164
|
+
return [
|
|
2165
|
+
keymap5.of([
|
|
2166
|
+
{
|
|
2167
|
+
// Reset.
|
|
2168
|
+
key: "alt-meta-'",
|
|
2169
|
+
run: (view) => {
|
|
2170
|
+
clearTimeout(t);
|
|
2171
|
+
idx = 0;
|
|
2172
|
+
return true;
|
|
1441
2173
|
}
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
|
|
2174
|
+
},
|
|
2175
|
+
{
|
|
2176
|
+
// Next prompt.
|
|
2177
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
|
2178
|
+
key: "shift-meta-'",
|
|
2179
|
+
run: (view) => {
|
|
2180
|
+
clearTimeout(t);
|
|
2181
|
+
const text = items[idx++];
|
|
2182
|
+
if (idx === items?.length) {
|
|
2183
|
+
idx = 0;
|
|
2184
|
+
}
|
|
2185
|
+
let i = 0;
|
|
2186
|
+
const insert = (d = 0) => {
|
|
2187
|
+
t = setTimeout(() => {
|
|
2188
|
+
const pos = view.state.selection.main.head;
|
|
2189
|
+
view.dispatch({
|
|
2190
|
+
changes: {
|
|
2191
|
+
from: pos,
|
|
2192
|
+
insert: text[i++]
|
|
2193
|
+
},
|
|
2194
|
+
selection: {
|
|
2195
|
+
anchor: pos + 1
|
|
2196
|
+
}
|
|
2197
|
+
});
|
|
2198
|
+
if (i < text.length) {
|
|
2199
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
2200
|
+
}
|
|
2201
|
+
}, d);
|
|
2202
|
+
};
|
|
2203
|
+
insert();
|
|
2204
|
+
return true;
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
])
|
|
2208
|
+
];
|
|
2209
|
+
};
|
|
2210
|
+
|
|
2211
|
+
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2212
|
+
import { yCollab } from "y-codemirror.next";
|
|
2213
|
+
|
|
2214
|
+
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2215
|
+
import * as Y from "yjs";
|
|
2216
|
+
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2217
|
+
var cursorConverter2 = (text) => ({
|
|
2218
|
+
toCursor: (index, assoc) => {
|
|
2219
|
+
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2220
|
+
},
|
|
2221
|
+
fromCursor: (cursor) => {
|
|
2222
|
+
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2223
|
+
}
|
|
1445
2224
|
});
|
|
1446
2225
|
|
|
1447
|
-
// packages/ui/react-ui-editor/src/
|
|
1448
|
-
|
|
2226
|
+
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2227
|
+
var yjs = (content, awareness2) => [
|
|
2228
|
+
CursorConverter.of(cursorConverter2(content)),
|
|
2229
|
+
yCollab(content, awareness2)
|
|
2230
|
+
];
|
|
2231
|
+
|
|
2232
|
+
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2233
|
+
import get6 from "lodash.get";
|
|
1449
2234
|
var defaultTheme = {
|
|
1450
2235
|
//
|
|
1451
2236
|
// Main layout:
|
|
1452
|
-
//
|
|
1453
|
-
//
|
|
1454
|
-
//
|
|
1455
|
-
//
|
|
2237
|
+
// https://codemirror.net/examples/styling
|
|
2238
|
+
//
|
|
2239
|
+
// <div class="cm-editor [cm-focused] [generated classes]">
|
|
2240
|
+
// <div class="cm-scroller">
|
|
2241
|
+
// <div class="cm-gutters">
|
|
2242
|
+
// <div class="cm-gutter [...]">
|
|
2243
|
+
// <div class="cm-gutterElement">...</div>
|
|
2244
|
+
// </div>
|
|
2245
|
+
// </div>
|
|
2246
|
+
// <div class="cm-content" role="textbox" contenteditable="true">
|
|
2247
|
+
// <div class="cm-line"></div>
|
|
2248
|
+
// </div>
|
|
2249
|
+
// <div class="cm-selectionLayer">
|
|
2250
|
+
// <div class="cm-selectionBackground"></div>
|
|
2251
|
+
// </div>
|
|
2252
|
+
// <div class="cm-cursorLayer">
|
|
2253
|
+
// <div class="cm-cursor"></div>
|
|
1456
2254
|
// </div>
|
|
1457
2255
|
// </div>
|
|
1458
2256
|
// </div>
|
|
@@ -1463,19 +2261,19 @@ var defaultTheme = {
|
|
|
1463
2261
|
},
|
|
1464
2262
|
"& .cm-scroller": {
|
|
1465
2263
|
overflow: "visible",
|
|
1466
|
-
fontFamily:
|
|
2264
|
+
fontFamily: get6(tokens, "fontFamily.mono", []).join(",")
|
|
1467
2265
|
},
|
|
1468
2266
|
"& .cm-content": {
|
|
1469
2267
|
padding: 0,
|
|
1470
|
-
// Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2268
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
1471
2269
|
fontSize: "16px"
|
|
1472
2270
|
},
|
|
1473
2271
|
"&light .cm-content": {
|
|
1474
|
-
color:
|
|
2272
|
+
color: get6(tokens, "extend.colors.neutral.900", "black"),
|
|
1475
2273
|
caretColor: "black"
|
|
1476
2274
|
},
|
|
1477
2275
|
"&dark .cm-content": {
|
|
1478
|
-
color:
|
|
2276
|
+
color: get6(tokens, "extend.colors.neutral.100", "white"),
|
|
1479
2277
|
caretColor: "white"
|
|
1480
2278
|
},
|
|
1481
2279
|
//
|
|
@@ -1496,28 +2294,36 @@ var defaultTheme = {
|
|
|
1496
2294
|
"& .cm-line": {
|
|
1497
2295
|
paddingInline: 0
|
|
1498
2296
|
},
|
|
1499
|
-
"& .cm-line *": {},
|
|
1500
2297
|
"& .cm-activeLine": {
|
|
1501
|
-
|
|
2298
|
+
background: "inherit"
|
|
1502
2299
|
},
|
|
1503
2300
|
//
|
|
1504
|
-
//
|
|
2301
|
+
// Selection
|
|
1505
2302
|
//
|
|
1506
|
-
"&light .cm-selectionBackground
|
|
1507
|
-
background:
|
|
2303
|
+
"&light .cm-selectionBackground": {
|
|
2304
|
+
background: get6(tokens, "extend.colors.primary.100")
|
|
2305
|
+
},
|
|
2306
|
+
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2307
|
+
background: get6(tokens, "extend.colors.primary.200")
|
|
2308
|
+
},
|
|
2309
|
+
"&dark .cm-selectionBackground": {
|
|
2310
|
+
background: get6(tokens, "extend.colors.primary.700")
|
|
1508
2311
|
},
|
|
1509
|
-
"&dark .cm-
|
|
1510
|
-
background:
|
|
2312
|
+
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2313
|
+
background: get6(tokens, "extend.colors.primary.600")
|
|
1511
2314
|
},
|
|
1512
|
-
|
|
1513
|
-
|
|
2315
|
+
//
|
|
2316
|
+
// Search
|
|
2317
|
+
//
|
|
2318
|
+
"&light .cm-searchMatch": {
|
|
2319
|
+
backgroundColor: get6(tokens, "extend.colors.yellow.100")
|
|
1514
2320
|
},
|
|
1515
|
-
"&dark .cm-
|
|
1516
|
-
|
|
2321
|
+
"&dark .cm-searchMatch": {
|
|
2322
|
+
backgroundColor: get6(tokens, "extend.colors.yellow.700")
|
|
1517
2323
|
},
|
|
1518
2324
|
//
|
|
1519
2325
|
// collaboration
|
|
1520
|
-
// TODO(burdon): Review classnames (YJS dependent?)
|
|
2326
|
+
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
1521
2327
|
//
|
|
1522
2328
|
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
1523
2329
|
mixBlendMode: "multiply"
|
|
@@ -1546,12 +2352,12 @@ var defaultTheme = {
|
|
|
1546
2352
|
// link
|
|
1547
2353
|
//
|
|
1548
2354
|
"& .cm-link": {
|
|
1549
|
-
color:
|
|
2355
|
+
color: get6(tokens, "extend.colors.primary.500"),
|
|
1550
2356
|
textDecorationLine: "underline",
|
|
1551
2357
|
textDecorationThickness: "1px",
|
|
1552
2358
|
textUnderlineOffset: "2px",
|
|
1553
2359
|
borderRadius: ".125rem",
|
|
1554
|
-
fontFamily:
|
|
2360
|
+
fontFamily: get6(tokens, "fontFamily.body", []).join(",")
|
|
1555
2361
|
},
|
|
1556
2362
|
//
|
|
1557
2363
|
// tooltip
|
|
@@ -1573,7 +2379,7 @@ var defaultTheme = {
|
|
|
1573
2379
|
display: "none"
|
|
1574
2380
|
},
|
|
1575
2381
|
"& .cm-completionLabel": {
|
|
1576
|
-
fontFamily:
|
|
2382
|
+
fontFamily: get6(tokens, "fontFamily.body", []).join(",")
|
|
1577
2383
|
},
|
|
1578
2384
|
"& .cm-completionMatchedText": {
|
|
1579
2385
|
textDecoration: "none"
|
|
@@ -1589,15 +2395,15 @@ var defaultTheme = {
|
|
|
1589
2395
|
// table
|
|
1590
2396
|
//
|
|
1591
2397
|
"& .cm-table *": {
|
|
1592
|
-
fontFamily: `${
|
|
2398
|
+
fontFamily: `${get6(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
1593
2399
|
textDecoration: "none !important"
|
|
1594
2400
|
},
|
|
1595
2401
|
"& .cm-table-head": {
|
|
1596
2402
|
padding: "2px 16px 2px 0px",
|
|
1597
|
-
borderBottom: `1px solid ${
|
|
2403
|
+
borderBottom: `1px solid ${get6(tokens, "extend.colors.neutral.500")}`,
|
|
1598
2404
|
fontWeight: 100,
|
|
1599
2405
|
textAlign: "left",
|
|
1600
|
-
color:
|
|
2406
|
+
color: get6(tokens, "extend.colors.neutral.500")
|
|
1601
2407
|
},
|
|
1602
2408
|
"& .cm-table-cell": {
|
|
1603
2409
|
padding: "2px 16px 2px 0px"
|
|
@@ -1612,8 +2418,8 @@ var defaultTheme = {
|
|
|
1612
2418
|
// font size
|
|
1613
2419
|
// 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.
|
|
1614
2420
|
//
|
|
1615
|
-
...Object.keys(
|
|
1616
|
-
const height =
|
|
2421
|
+
...Object.keys(get6(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
|
|
2422
|
+
const height = get6(tokens, [
|
|
1617
2423
|
"extend",
|
|
1618
2424
|
"fontSize",
|
|
1619
2425
|
fontSize,
|
|
@@ -1633,6 +2439,7 @@ var defaultTheme = {
|
|
|
1633
2439
|
}, {}),
|
|
1634
2440
|
/**
|
|
1635
2441
|
* Panels
|
|
2442
|
+
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
1636
2443
|
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
1637
2444
|
*
|
|
1638
2445
|
* Find/replace panel.
|
|
@@ -1647,71 +2454,65 @@ var defaultTheme = {
|
|
|
1647
2454
|
* </div
|
|
1648
2455
|
*/
|
|
1649
2456
|
"& .cm-panels": {
|
|
1650
|
-
border: `1px solid ${
|
|
1651
|
-
borderBottom: "none"
|
|
2457
|
+
border: `1px solid ${get6(tokens, "extend.colors.neutral.200")}`
|
|
1652
2458
|
},
|
|
1653
2459
|
"& .cm-panel": {
|
|
1654
|
-
background:
|
|
1655
|
-
fontFamily:
|
|
2460
|
+
background: get6(tokens, "extend.colors.neutral.50"),
|
|
2461
|
+
fontFamily: get6(tokens, "fontFamily.body", []).join(",")
|
|
1656
2462
|
},
|
|
1657
2463
|
"& .cm-button": {
|
|
1658
2464
|
margin: "4px",
|
|
1659
|
-
fontFamily:
|
|
1660
|
-
background:
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
2465
|
+
fontFamily: get6(tokens, "fontFamily.body", []).join(","),
|
|
2466
|
+
background: get6(tokens, "extend.colors.neutral.100"),
|
|
2467
|
+
backgroundImage: "none",
|
|
2468
|
+
border: "none",
|
|
2469
|
+
"&:hover": {
|
|
2470
|
+
background: get6(tokens, "extend.colors.neutral.200")
|
|
2471
|
+
},
|
|
2472
|
+
"&:active": {
|
|
2473
|
+
background: get6(tokens, "extend.colors.neutral.300"),
|
|
2474
|
+
backgroundImage: "none"
|
|
2475
|
+
}
|
|
1665
2476
|
},
|
|
1666
|
-
"& .cm-
|
|
1667
|
-
|
|
2477
|
+
"& .cm-panel input[type=checkbox]": {
|
|
2478
|
+
marginRight: "0.4rem !important"
|
|
1668
2479
|
}
|
|
1669
2480
|
};
|
|
1670
2481
|
var textTheme = {
|
|
1671
2482
|
"& .cm-scroller": {
|
|
1672
|
-
fontFamily:
|
|
2483
|
+
fontFamily: get6(tokens, "fontFamily.body", []).join(",")
|
|
1673
2484
|
},
|
|
1674
2485
|
"& .cm-placeholder": {
|
|
1675
|
-
fontFamily:
|
|
2486
|
+
fontFamily: get6(tokens, "fontFamily.body", []).join(",")
|
|
1676
2487
|
}
|
|
1677
2488
|
};
|
|
1678
2489
|
var markdownTheme = {
|
|
1679
2490
|
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
1680
2491
|
"& .cm-placeholder": {
|
|
1681
|
-
fontFamily:
|
|
2492
|
+
fontFamily: get6(tokens, "fontFamily.body", []).join(",")
|
|
1682
2493
|
}
|
|
1683
2494
|
};
|
|
1684
2495
|
var codeTheme = {
|
|
1685
2496
|
"& .cm-scroller": {
|
|
1686
|
-
fontFamily:
|
|
2497
|
+
fontFamily: get6(tokens, "fontFamily.mono", []).join(",")
|
|
1687
2498
|
},
|
|
1688
2499
|
"& .cm-placeholder": {
|
|
1689
|
-
fontFamily:
|
|
2500
|
+
fontFamily: get6(tokens, "fontFamily.mono", []).join(",")
|
|
1690
2501
|
}
|
|
1691
2502
|
};
|
|
1692
2503
|
|
|
1693
2504
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
1694
|
-
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
1695
|
-
import { EditorView as EditorView11 } from "@codemirror/view";
|
|
1696
|
-
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
1697
|
-
import { vim } from "@replit/codemirror-vim";
|
|
1698
|
-
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
1699
|
-
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
|
|
1700
|
-
import { generateName } from "@dxos/display-name";
|
|
1701
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
1702
|
-
import { getColorForValue, inputSurface, mx as mx4 } from "@dxos/react-ui-theme";
|
|
1703
2505
|
var EditorModes = [
|
|
1704
2506
|
"default",
|
|
1705
2507
|
"vim"
|
|
1706
2508
|
];
|
|
1707
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2509
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
1708
2510
|
const { themeMode } = useThemeContext();
|
|
1709
2511
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
1710
2512
|
tabBehavior: "limited"
|
|
1711
2513
|
});
|
|
1712
2514
|
const [root, setRoot] = useState(null);
|
|
1713
|
-
const [state,
|
|
1714
|
-
const [view, setView] = useState();
|
|
2515
|
+
const [{ state = void 0, view = void 0 } = {}, setEditor] = useState();
|
|
1715
2516
|
useImperativeHandle(forwardedRef, () => ({
|
|
1716
2517
|
root,
|
|
1717
2518
|
state,
|
|
@@ -1721,10 +2522,10 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
|
|
|
1721
2522
|
state,
|
|
1722
2523
|
root
|
|
1723
2524
|
]);
|
|
1724
|
-
const { awareness, peer } = model;
|
|
1725
|
-
|
|
1726
|
-
if (
|
|
1727
|
-
|
|
2525
|
+
const { awareness: awareness2, peer } = model;
|
|
2526
|
+
useEffect(() => {
|
|
2527
|
+
if (awareness2 && peer) {
|
|
2528
|
+
awareness2.setLocalStateField("user", {
|
|
1728
2529
|
name: peer.name ?? generateName(peer.id),
|
|
1729
2530
|
color: getColorForValue({
|
|
1730
2531
|
value: peer.id,
|
|
@@ -1738,11 +2539,24 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
|
|
|
1738
2539
|
});
|
|
1739
2540
|
}
|
|
1740
2541
|
}, [
|
|
1741
|
-
|
|
2542
|
+
awareness2,
|
|
1742
2543
|
peer,
|
|
1743
2544
|
themeMode
|
|
1744
2545
|
]);
|
|
1745
|
-
|
|
2546
|
+
useEffect(() => {
|
|
2547
|
+
if (view && comments2?.length) {
|
|
2548
|
+
view.dispatch({
|
|
2549
|
+
effects: setCommentRange.of({
|
|
2550
|
+
model,
|
|
2551
|
+
comments: comments2
|
|
2552
|
+
})
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
}, [
|
|
2556
|
+
view,
|
|
2557
|
+
comments2
|
|
2558
|
+
]);
|
|
2559
|
+
useEffect(() => {
|
|
1746
2560
|
if (!root) {
|
|
1747
2561
|
return;
|
|
1748
2562
|
}
|
|
@@ -1750,14 +2564,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
|
|
|
1750
2564
|
doc: model.text(),
|
|
1751
2565
|
extensions: [
|
|
1752
2566
|
readonly && EditorState2.readOnly.of(readonly),
|
|
1753
|
-
// TODO(burdon): Factor out VIM mode?
|
|
2567
|
+
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
1754
2568
|
editorMode === "vim" && vim(),
|
|
1755
2569
|
// Theme.
|
|
1756
|
-
// TODO(burdon): Make
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
EditorView11.darkTheme.of(themeMode === "dark"),
|
|
2570
|
+
// TODO(burdon): Make theme configurable.
|
|
2571
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2572
|
+
EditorView13.theme(slots?.editor?.theme ?? {}),
|
|
2573
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
1761
2574
|
// Storage and replication.
|
|
1762
2575
|
model.extension,
|
|
1763
2576
|
// Custom.
|
|
@@ -1765,22 +2578,23 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
|
|
|
1765
2578
|
].filter(Boolean)
|
|
1766
2579
|
});
|
|
1767
2580
|
view?.destroy();
|
|
1768
|
-
|
|
2581
|
+
setEditor({
|
|
1769
2582
|
state: state2,
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
2583
|
+
view: new EditorView13({
|
|
2584
|
+
state: state2,
|
|
2585
|
+
parent: root
|
|
2586
|
+
})
|
|
2587
|
+
});
|
|
1773
2588
|
return () => {
|
|
1774
2589
|
view?.destroy();
|
|
1775
|
-
|
|
1776
|
-
setState(void 0);
|
|
2590
|
+
setEditor(void 0);
|
|
1777
2591
|
};
|
|
1778
2592
|
}, [
|
|
1779
2593
|
root,
|
|
1780
2594
|
model,
|
|
1781
|
-
themeMode,
|
|
1782
2595
|
readonly,
|
|
1783
|
-
editorMode
|
|
2596
|
+
editorMode,
|
|
2597
|
+
themeMode
|
|
1784
2598
|
]);
|
|
1785
2599
|
const handleKeyUp = useCallback((event) => {
|
|
1786
2600
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
@@ -1840,336 +2654,218 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
|
|
|
1840
2654
|
...extensions
|
|
1841
2655
|
],
|
|
1842
2656
|
slots,
|
|
1843
|
-
...props
|
|
1844
|
-
});
|
|
1845
|
-
});
|
|
1846
|
-
var defaultSlots = {
|
|
1847
|
-
root: {
|
|
1848
|
-
className:
|
|
1849
|
-
}
|
|
1850
|
-
};
|
|
1851
|
-
var defaultTextSlots = {
|
|
1852
|
-
...defaultSlots,
|
|
1853
|
-
editor: {
|
|
1854
|
-
theme: textTheme
|
|
1855
|
-
}
|
|
1856
|
-
};
|
|
1857
|
-
var defaultMarkdownSlots = {
|
|
1858
|
-
...defaultSlots,
|
|
1859
|
-
editor: {
|
|
1860
|
-
theme: markdownTheme
|
|
1861
|
-
}
|
|
1862
|
-
};
|
|
1863
|
-
|
|
1864
|
-
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1865
|
-
import get4 from "lodash.get";
|
|
1866
|
-
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
1867
|
-
import { yCollab } from "y-codemirror.next";
|
|
1868
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1869
|
-
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
1870
|
-
|
|
1871
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1872
|
-
import { Annotation, Facet, StateEffect as StateEffect2, StateField as StateField6 } from "@codemirror/state";
|
|
1873
|
-
import { ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1874
|
-
import * as automerge2 from "@dxos/automerge/automerge";
|
|
1875
|
-
|
|
1876
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
1877
|
-
import { next as automerge } from "@dxos/automerge/automerge";
|
|
1878
|
-
|
|
1879
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
|
|
1880
|
-
import { ChangeSet } from "@codemirror/state";
|
|
1881
|
-
var automergeToCodemirror = (view, selection, target, patches) => {
|
|
1882
|
-
for (const patch of patches) {
|
|
1883
|
-
const changeSpec = handlePatch(patch, target, view.state);
|
|
1884
|
-
if (changeSpec != null) {
|
|
1885
|
-
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
|
1886
|
-
selection = selection.map(changeSet, 1);
|
|
1887
|
-
view.dispatch({
|
|
1888
|
-
changes: changeSet,
|
|
1889
|
-
annotations: reconcileAnnotationType.of({})
|
|
1890
|
-
});
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
view.dispatch({
|
|
1894
|
-
selection,
|
|
1895
|
-
annotations: reconcileAnnotationType.of({})
|
|
1896
|
-
});
|
|
1897
|
-
};
|
|
1898
|
-
var handlePatch = (patch, target, state) => {
|
|
1899
|
-
if (patch.action === "insert") {
|
|
1900
|
-
return handleInsert(target, patch);
|
|
1901
|
-
} else if (patch.action === "splice") {
|
|
1902
|
-
return handleSplice(target, patch);
|
|
1903
|
-
} else if (patch.action === "del") {
|
|
1904
|
-
return handleDel(target, patch);
|
|
1905
|
-
} else if (patch.action === "put") {
|
|
1906
|
-
return handlePut(target, patch, state);
|
|
1907
|
-
} else {
|
|
1908
|
-
return null;
|
|
1909
|
-
}
|
|
1910
|
-
};
|
|
1911
|
-
var handleInsert = (target, patch) => {
|
|
1912
|
-
const index = charPath(target, patch.path);
|
|
1913
|
-
if (index == null) {
|
|
1914
|
-
return [];
|
|
1915
|
-
}
|
|
1916
|
-
const text = patch.values.map((v) => v ? v.toString() : "").join("");
|
|
1917
|
-
return [
|
|
1918
|
-
{
|
|
1919
|
-
from: index,
|
|
1920
|
-
to: index,
|
|
1921
|
-
insert: text
|
|
1922
|
-
}
|
|
1923
|
-
];
|
|
1924
|
-
};
|
|
1925
|
-
var handleSplice = (target, patch) => {
|
|
1926
|
-
const index = charPath(target, patch.path);
|
|
1927
|
-
if (index == null) {
|
|
1928
|
-
return [];
|
|
1929
|
-
}
|
|
1930
|
-
return [
|
|
1931
|
-
{
|
|
1932
|
-
from: index,
|
|
1933
|
-
insert: patch.value
|
|
1934
|
-
}
|
|
1935
|
-
];
|
|
1936
|
-
};
|
|
1937
|
-
var handleDel = (target, patch) => {
|
|
1938
|
-
const index = charPath(target, patch.path);
|
|
1939
|
-
if (index == null) {
|
|
1940
|
-
return [];
|
|
1941
|
-
}
|
|
1942
|
-
const length = patch.length || 1;
|
|
1943
|
-
return [
|
|
1944
|
-
{
|
|
1945
|
-
from: index,
|
|
1946
|
-
to: index + length
|
|
1947
|
-
}
|
|
1948
|
-
];
|
|
1949
|
-
};
|
|
1950
|
-
var handlePut = (target, patch, state) => {
|
|
1951
|
-
const index = charPath(target, [
|
|
1952
|
-
...patch.path,
|
|
1953
|
-
0
|
|
1954
|
-
]);
|
|
1955
|
-
if (index == null) {
|
|
1956
|
-
return [];
|
|
1957
|
-
}
|
|
1958
|
-
const length = state.doc.length;
|
|
1959
|
-
if (typeof patch.value !== "string") {
|
|
1960
|
-
return [];
|
|
1961
|
-
}
|
|
1962
|
-
return [
|
|
1963
|
-
{
|
|
1964
|
-
from: 0,
|
|
1965
|
-
to: length,
|
|
1966
|
-
insert: patch.value
|
|
1967
|
-
}
|
|
1968
|
-
];
|
|
1969
|
-
};
|
|
1970
|
-
var charPath = (textPath, candidatePath) => {
|
|
1971
|
-
if (candidatePath.length !== textPath.length + 1) {
|
|
1972
|
-
return null;
|
|
1973
|
-
}
|
|
1974
|
-
for (let i = 0; i < textPath.length; i++) {
|
|
1975
|
-
if (textPath[i] !== candidatePath[i]) {
|
|
1976
|
-
return null;
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
const index = candidatePath[candidatePath.length - 1];
|
|
1980
|
-
if (typeof index === "number") {
|
|
1981
|
-
return index;
|
|
2657
|
+
...props
|
|
2658
|
+
});
|
|
2659
|
+
});
|
|
2660
|
+
var defaultSlots = {
|
|
2661
|
+
root: {
|
|
2662
|
+
className: mx3("p-2", inputSurface)
|
|
1982
2663
|
}
|
|
1983
|
-
return null;
|
|
1984
2664
|
};
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
const { lastHeads, path } = state.field(field);
|
|
1990
|
-
let hasChanges = false;
|
|
1991
|
-
for (const tr of transactions) {
|
|
1992
|
-
tr.changes.iterChanges(() => {
|
|
1993
|
-
hasChanges = true;
|
|
1994
|
-
});
|
|
2665
|
+
var defaultTextSlots = {
|
|
2666
|
+
...defaultSlots,
|
|
2667
|
+
editor: {
|
|
2668
|
+
theme: textTheme
|
|
1995
2669
|
}
|
|
1996
|
-
|
|
1997
|
-
|
|
2670
|
+
};
|
|
2671
|
+
var defaultMarkdownSlots = {
|
|
2672
|
+
...defaultSlots,
|
|
2673
|
+
editor: {
|
|
2674
|
+
theme: markdownTheme
|
|
1998
2675
|
}
|
|
1999
|
-
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
2000
|
-
for (const tr of transactions) {
|
|
2001
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
2002
|
-
am.splice(doc, path, fromA, toA - fromA, inserted.toString());
|
|
2003
|
-
});
|
|
2004
|
-
}
|
|
2005
|
-
});
|
|
2006
|
-
return newHeads ?? void 0;
|
|
2007
2676
|
};
|
|
2008
2677
|
|
|
2009
|
-
// packages/ui/react-ui-editor/src/hooks/automerge
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2678
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2679
|
+
import get7 from "lodash.get";
|
|
2680
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
2681
|
+
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2682
|
+
|
|
2683
|
+
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2684
|
+
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2685
|
+
import { Context as Context2 } from "@dxos/context";
|
|
2686
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2687
|
+
import { log as log3 } from "@dxos/log";
|
|
2688
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2689
|
+
var DEBOUNCE_INTERVAL = 100;
|
|
2690
|
+
var SpaceAwarenessProvider = class {
|
|
2691
|
+
constructor(params) {
|
|
2692
|
+
this.remoteStateChange = new Event2();
|
|
2693
|
+
this._remoteStates = /* @__PURE__ */ new Map();
|
|
2694
|
+
this._space = params.space;
|
|
2695
|
+
this._channel = params.channel;
|
|
2696
|
+
this._peerId = params.peerId;
|
|
2697
|
+
this._info = params.info;
|
|
2698
|
+
}
|
|
2699
|
+
open() {
|
|
2700
|
+
this._ctx = new Context2();
|
|
2701
|
+
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
2702
|
+
if (this._localState) {
|
|
2703
|
+
await this._space.postMessage(this._channel, {
|
|
2704
|
+
kind: "post",
|
|
2705
|
+
state: this._localState
|
|
2030
2706
|
});
|
|
2707
|
+
await sleep(DEBOUNCE_INTERVAL);
|
|
2031
2708
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2709
|
+
});
|
|
2710
|
+
const unsubscribe = this._space.listen(this._channel, (message) => {
|
|
2711
|
+
switch (message.payload.kind) {
|
|
2712
|
+
case "query": {
|
|
2713
|
+
this._handleQueryMessage();
|
|
2714
|
+
break;
|
|
2715
|
+
}
|
|
2716
|
+
case "post": {
|
|
2717
|
+
this._handlePostMessage(message.payload);
|
|
2718
|
+
break;
|
|
2719
|
+
}
|
|
2035
2720
|
}
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2721
|
+
});
|
|
2722
|
+
this._ctx.onDispose(unsubscribe);
|
|
2723
|
+
void this._space.postMessage(this._channel, {
|
|
2724
|
+
kind: "query"
|
|
2725
|
+
}).catch((err) => {
|
|
2726
|
+
log3.debug("failed to query awareness", {
|
|
2727
|
+
err
|
|
2728
|
+
}, {
|
|
2729
|
+
F: __dxlog_file4,
|
|
2730
|
+
L: 85,
|
|
2731
|
+
S: this,
|
|
2732
|
+
C: (f, a) => f(...a)
|
|
2041
2733
|
});
|
|
2042
|
-
|
|
2734
|
+
});
|
|
2735
|
+
}
|
|
2736
|
+
close() {
|
|
2737
|
+
void this._ctx?.dispose();
|
|
2738
|
+
this._ctx = void 0;
|
|
2739
|
+
this._postTask = void 0;
|
|
2740
|
+
}
|
|
2741
|
+
update(position) {
|
|
2742
|
+
invariant3(this._postTask, void 0, {
|
|
2743
|
+
F: __dxlog_file4,
|
|
2744
|
+
L: 96,
|
|
2745
|
+
S: this,
|
|
2746
|
+
A: [
|
|
2747
|
+
"this._postTask",
|
|
2748
|
+
""
|
|
2749
|
+
]
|
|
2750
|
+
});
|
|
2751
|
+
this._localState = {
|
|
2752
|
+
peerId: this._peerId,
|
|
2753
|
+
position,
|
|
2754
|
+
info: this._info
|
|
2043
2755
|
};
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2756
|
+
this._postTask.schedule();
|
|
2757
|
+
}
|
|
2758
|
+
getRemoteStates() {
|
|
2759
|
+
return Array.from(this._remoteStates.values());
|
|
2760
|
+
}
|
|
2761
|
+
_handleQueryMessage() {
|
|
2762
|
+
invariant3(this._postTask, void 0, {
|
|
2763
|
+
F: __dxlog_file4,
|
|
2764
|
+
L: 111,
|
|
2765
|
+
S: this,
|
|
2766
|
+
A: [
|
|
2767
|
+
"this._postTask",
|
|
2768
|
+
""
|
|
2769
|
+
]
|
|
2770
|
+
});
|
|
2771
|
+
this._postTask.schedule();
|
|
2772
|
+
}
|
|
2773
|
+
_handlePostMessage(message) {
|
|
2774
|
+
invariant3(message.kind === "post", void 0, {
|
|
2775
|
+
F: __dxlog_file4,
|
|
2776
|
+
L: 116,
|
|
2777
|
+
S: this,
|
|
2778
|
+
A: [
|
|
2779
|
+
"message.kind === 'post'",
|
|
2780
|
+
""
|
|
2781
|
+
]
|
|
2782
|
+
});
|
|
2783
|
+
this._remoteStates.set(message.state.peerId, message.state);
|
|
2784
|
+
this.remoteStateChange.emit();
|
|
2047
2785
|
}
|
|
2048
2786
|
};
|
|
2049
2787
|
|
|
2050
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
});
|
|
2055
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
2056
|
-
var getPath = (state, field) => state.field(field).path;
|
|
2057
|
-
var semaphoreFacet = Facet.define({
|
|
2058
|
-
combine: (values) => values.at(-1)
|
|
2059
|
-
});
|
|
2060
|
-
var automergePlugin = (handle, path) => {
|
|
2061
|
-
const stateField = StateField6.define({
|
|
2062
|
-
create: () => ({
|
|
2063
|
-
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
2064
|
-
unreconciledTransactions: [],
|
|
2065
|
-
path: path.slice()
|
|
2066
|
-
}),
|
|
2067
|
-
update: (value, tr) => {
|
|
2068
|
-
const result = {
|
|
2069
|
-
lastHeads: value.lastHeads,
|
|
2070
|
-
unreconciledTransactions: value.unreconciledTransactions.slice(),
|
|
2071
|
-
path: path.slice()
|
|
2072
|
-
};
|
|
2073
|
-
let clearUnreconciled = false;
|
|
2074
|
-
for (const effect of tr.effects) {
|
|
2075
|
-
if (effect.is(effectType)) {
|
|
2076
|
-
result.lastHeads = effect.value.newHeads;
|
|
2077
|
-
clearUnreconciled = true;
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
if (clearUnreconciled) {
|
|
2081
|
-
result.unreconciledTransactions = [];
|
|
2082
|
-
} else {
|
|
2083
|
-
if (!isReconcileTx(tr)) {
|
|
2084
|
-
result.unreconciledTransactions.push(tr);
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
return result;
|
|
2088
|
-
}
|
|
2089
|
-
});
|
|
2090
|
-
const semaphore = new PatchSemaphore(stateField);
|
|
2091
|
-
const viewPlugin = ViewPlugin4.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
2092
|
-
constructor(view) {
|
|
2093
|
-
this._handleChange = () => {
|
|
2094
|
-
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
2095
|
-
};
|
|
2096
|
-
this._view = view;
|
|
2097
|
-
handle.addListener("change", this._handleChange);
|
|
2098
|
-
}
|
|
2099
|
-
update(update4) {
|
|
2100
|
-
if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
|
|
2101
|
-
queueMicrotask(() => {
|
|
2102
|
-
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
2103
|
-
});
|
|
2104
|
-
}
|
|
2105
|
-
}
|
|
2106
|
-
destroy() {
|
|
2107
|
-
handle.addListener("change", this._handleChange);
|
|
2108
|
-
}
|
|
2109
|
-
});
|
|
2110
|
-
return {
|
|
2111
|
-
extension: [
|
|
2112
|
-
stateField,
|
|
2113
|
-
semaphoreFacet.of(semaphore),
|
|
2114
|
-
viewPlugin
|
|
2115
|
-
]
|
|
2116
|
-
};
|
|
2117
|
-
};
|
|
2118
|
-
var reconcileAnnotationType = Annotation.define();
|
|
2119
|
-
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
2120
|
-
|
|
2121
|
-
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
2122
|
-
import * as random2 from "lib0/random";
|
|
2123
|
-
var cursorColors = [
|
|
2124
|
-
{
|
|
2125
|
-
color: "#30bced",
|
|
2126
|
-
light: "#30bced33"
|
|
2127
|
-
},
|
|
2128
|
-
{
|
|
2129
|
-
color: "#6eeb83",
|
|
2130
|
-
light: "#6eeb8333"
|
|
2131
|
-
},
|
|
2132
|
-
{
|
|
2133
|
-
color: "#ffbc42",
|
|
2134
|
-
light: "#ffbc4233"
|
|
2135
|
-
},
|
|
2136
|
-
{
|
|
2137
|
-
color: "#ecd444",
|
|
2138
|
-
light: "#ecd44433"
|
|
2139
|
-
},
|
|
2140
|
-
{
|
|
2141
|
-
color: "#ee6352",
|
|
2142
|
-
light: "#ee635233"
|
|
2143
|
-
},
|
|
2144
|
-
{
|
|
2145
|
-
color: "#9ac2c9",
|
|
2146
|
-
light: "#9ac2c933"
|
|
2147
|
-
},
|
|
2148
|
-
{
|
|
2149
|
-
color: "#8acb88",
|
|
2150
|
-
light: "#8acb8833"
|
|
2151
|
-
},
|
|
2152
|
-
{
|
|
2153
|
-
color: "#1be7ff",
|
|
2154
|
-
light: "#1be7ff33"
|
|
2155
|
-
}
|
|
2156
|
-
];
|
|
2157
|
-
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
2788
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2789
|
+
import { StateField as StateField6 } from "@codemirror/state";
|
|
2790
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2791
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2158
2792
|
|
|
2159
|
-
// packages/ui/react-ui-editor/src/hooks/yjs
|
|
2793
|
+
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2160
2794
|
import * as decoding from "lib0/decoding";
|
|
2161
2795
|
import * as encoding from "lib0/encoding";
|
|
2162
2796
|
import { Observable } from "lib0/observable";
|
|
2163
|
-
import * as
|
|
2164
|
-
import
|
|
2165
|
-
|
|
2797
|
+
import * as YP from "y-protocols/awareness";
|
|
2798
|
+
import * as Y2 from "yjs";
|
|
2799
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2800
|
+
import { log as log4 } from "@dxos/log";
|
|
2801
|
+
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2802
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2803
|
+
var createYjsModel = ({ identity, space, text }) => {
|
|
2804
|
+
invariant4(text?.doc && text?.content, void 0, {
|
|
2805
|
+
F: __dxlog_file5,
|
|
2806
|
+
L: 23,
|
|
2807
|
+
S: void 0,
|
|
2808
|
+
A: [
|
|
2809
|
+
"text?.doc && text?.content",
|
|
2810
|
+
""
|
|
2811
|
+
]
|
|
2812
|
+
});
|
|
2813
|
+
const provider = space ? new YAwarenessProvider({
|
|
2814
|
+
space,
|
|
2815
|
+
doc: text.doc,
|
|
2816
|
+
channel: `yjs.awareness.${text.id}`
|
|
2817
|
+
}) : void 0;
|
|
2818
|
+
const model = {
|
|
2819
|
+
id: text.doc.guid,
|
|
2820
|
+
content: text.content,
|
|
2821
|
+
text: () => text.content.toString(),
|
|
2822
|
+
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2823
|
+
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2824
|
+
getCursorFromRange: (range) => {
|
|
2825
|
+
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2826
|
+
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2827
|
+
return [
|
|
2828
|
+
arrayToString2(from),
|
|
2829
|
+
arrayToString2(to)
|
|
2830
|
+
].join(":");
|
|
2831
|
+
},
|
|
2832
|
+
getRangeFromCursor: (cursor) => {
|
|
2833
|
+
invariant4(text.doc, void 0, {
|
|
2834
|
+
F: __dxlog_file5,
|
|
2835
|
+
L: 40,
|
|
2836
|
+
S: void 0,
|
|
2837
|
+
A: [
|
|
2838
|
+
"text.doc",
|
|
2839
|
+
""
|
|
2840
|
+
]
|
|
2841
|
+
});
|
|
2842
|
+
const parts = cursor.split(":");
|
|
2843
|
+
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2844
|
+
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2845
|
+
return from && to ? {
|
|
2846
|
+
from: from.index,
|
|
2847
|
+
to: to.index
|
|
2848
|
+
} : void 0;
|
|
2849
|
+
},
|
|
2850
|
+
extension: [
|
|
2851
|
+
modelState.init(() => model),
|
|
2852
|
+
yjs(text.content, provider?.awareness)
|
|
2853
|
+
],
|
|
2854
|
+
awareness: provider?.awareness,
|
|
2855
|
+
peer: identity ? {
|
|
2856
|
+
id: identity.identityKey.toHex(),
|
|
2857
|
+
name: identity.profile?.displayName
|
|
2858
|
+
} : void 0
|
|
2859
|
+
};
|
|
2860
|
+
return model;
|
|
2861
|
+
};
|
|
2166
2862
|
var messageAwareness = 1;
|
|
2167
2863
|
var messageQueryAwareness = 3;
|
|
2168
|
-
var
|
|
2169
|
-
constructor({ space, doc, channel, awareness }) {
|
|
2864
|
+
var YAwarenessProvider = class extends Observable {
|
|
2865
|
+
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2170
2866
|
super();
|
|
2171
2867
|
this._space = space;
|
|
2172
|
-
this._awareness =
|
|
2868
|
+
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2173
2869
|
this._channel = channel;
|
|
2174
2870
|
this._clientId = doc.clientID;
|
|
2175
2871
|
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
@@ -2184,7 +2880,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
2184
2880
|
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
2185
2881
|
const encoderAwarenessState = encoding.createEncoder();
|
|
2186
2882
|
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
2187
|
-
encoding.writeVarUint8Array(encoderAwarenessState,
|
|
2883
|
+
encoding.writeVarUint8Array(encoderAwarenessState, YP.encodeAwarenessUpdate(this.awareness, [
|
|
2188
2884
|
this._clientId
|
|
2189
2885
|
]));
|
|
2190
2886
|
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
@@ -2193,27 +2889,27 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
2193
2889
|
return this._awareness;
|
|
2194
2890
|
}
|
|
2195
2891
|
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2196
|
-
|
|
2892
|
+
log4("awareness update", {
|
|
2197
2893
|
added,
|
|
2198
2894
|
updated,
|
|
2199
2895
|
removed,
|
|
2200
2896
|
origin
|
|
2201
2897
|
}, {
|
|
2202
|
-
F:
|
|
2203
|
-
L:
|
|
2898
|
+
F: __dxlog_file5,
|
|
2899
|
+
L: 122,
|
|
2204
2900
|
S: this,
|
|
2205
2901
|
C: (f, a) => f(...a)
|
|
2206
2902
|
});
|
|
2207
2903
|
const changedClients = added.concat(updated).concat(removed);
|
|
2208
2904
|
const encoderAwareness = encoding.createEncoder();
|
|
2209
2905
|
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
2210
|
-
encoding.writeVarUint8Array(encoderAwareness,
|
|
2906
|
+
encoding.writeVarUint8Array(encoderAwareness, YP.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
2211
2907
|
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2212
2908
|
}
|
|
2213
2909
|
_handleSpaceMessage({ payload }) {
|
|
2214
|
-
|
|
2215
|
-
F:
|
|
2216
|
-
L:
|
|
2910
|
+
log4("space message", payload, {
|
|
2911
|
+
F: __dxlog_file5,
|
|
2912
|
+
L: 131,
|
|
2217
2913
|
S: this,
|
|
2218
2914
|
C: (f, a) => f(...a)
|
|
2219
2915
|
});
|
|
@@ -2230,12 +2926,12 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
2230
2926
|
let sendReply = false;
|
|
2231
2927
|
switch (messageType) {
|
|
2232
2928
|
case messageAwareness: {
|
|
2233
|
-
|
|
2929
|
+
YP.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
2234
2930
|
break;
|
|
2235
2931
|
}
|
|
2236
2932
|
case messageQueryAwareness: {
|
|
2237
2933
|
encoding.writeVarUint(encoder, messageAwareness);
|
|
2238
|
-
encoding.writeVarUint8Array(encoder,
|
|
2934
|
+
encoding.writeVarUint8Array(encoder, YP.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
2239
2935
|
sendReply = true;
|
|
2240
2936
|
break;
|
|
2241
2937
|
}
|
|
@@ -2250,130 +2946,124 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
2250
2946
|
return encoder;
|
|
2251
2947
|
}
|
|
2252
2948
|
_handleBeforeUnload() {
|
|
2253
|
-
|
|
2949
|
+
YP.removeAwarenessStates(this._awareness, [
|
|
2254
2950
|
this._clientId
|
|
2255
2951
|
], "window unload");
|
|
2256
2952
|
}
|
|
2257
2953
|
};
|
|
2258
2954
|
|
|
2259
2955
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2260
|
-
var
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
setModel(createModel({
|
|
2269
|
-
identity,
|
|
2270
|
-
space,
|
|
2271
|
-
text
|
|
2272
|
-
}));
|
|
2273
|
-
}, [
|
|
2956
|
+
var modelState = StateField6.define({
|
|
2957
|
+
create: () => void 0,
|
|
2958
|
+
update: (model) => model
|
|
2959
|
+
});
|
|
2960
|
+
var useTextModel = (props) => {
|
|
2961
|
+
const { identity, space, text } = props;
|
|
2962
|
+
const [model, setModel] = useState2(() => createModel(props));
|
|
2963
|
+
useEffect2(() => setModel(createModel(props)), [
|
|
2274
2964
|
identity,
|
|
2275
2965
|
space,
|
|
2276
2966
|
text
|
|
2277
2967
|
]);
|
|
2278
2968
|
return model;
|
|
2279
2969
|
};
|
|
2280
|
-
var createModel = (
|
|
2281
|
-
const { text } =
|
|
2282
|
-
if (
|
|
2283
|
-
return createAutomergeModel(
|
|
2970
|
+
var createModel = (props) => {
|
|
2971
|
+
const { text } = props;
|
|
2972
|
+
if (isAutomergeObject(text)) {
|
|
2973
|
+
return createAutomergeModel(props);
|
|
2974
|
+
} else if (text?.doc) {
|
|
2975
|
+
return createYjsModel(props);
|
|
2284
2976
|
} else {
|
|
2285
|
-
|
|
2286
|
-
return void 0;
|
|
2287
|
-
}
|
|
2288
|
-
return createYjsModel(options);
|
|
2977
|
+
return void 0;
|
|
2289
2978
|
}
|
|
2290
2979
|
};
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
L: 81,
|
|
2295
|
-
S: void 0,
|
|
2296
|
-
A: [
|
|
2297
|
-
"text?.doc && text?.content",
|
|
2298
|
-
""
|
|
2299
|
-
]
|
|
2300
|
-
});
|
|
2301
|
-
const provider = space ? new SpaceAwarenessProvider({
|
|
2302
|
-
space,
|
|
2303
|
-
doc: text.doc,
|
|
2304
|
-
channel: `yjs.awareness.${text.id}`
|
|
2305
|
-
}) : void 0;
|
|
2306
|
-
return {
|
|
2307
|
-
id: text.doc.guid,
|
|
2308
|
-
content: text.content,
|
|
2309
|
-
text: () => text.content.toString(),
|
|
2310
|
-
ranges: [],
|
|
2311
|
-
extension: yCollab(text.content, provider?.awareness),
|
|
2312
|
-
awareness: provider?.awareness,
|
|
2313
|
-
peer: identity ? {
|
|
2314
|
-
id: identity.identityKey.toHex(),
|
|
2315
|
-
name: identity.profile?.displayName
|
|
2316
|
-
} : void 0
|
|
2317
|
-
};
|
|
2318
|
-
};
|
|
2319
|
-
var createAutomergeModel = ({ identity, text }) => {
|
|
2980
|
+
|
|
2981
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2982
|
+
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2320
2983
|
const obj = text;
|
|
2321
2984
|
const doc = getRawDoc(obj, [
|
|
2322
2985
|
obj.field
|
|
2323
2986
|
]);
|
|
2324
|
-
|
|
2987
|
+
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2988
|
+
space,
|
|
2989
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
2990
|
+
info: {
|
|
2991
|
+
displayName: identity?.profile?.displayName ?? "",
|
|
2992
|
+
color: cursorColor.color,
|
|
2993
|
+
lightColor: cursorColor.light
|
|
2994
|
+
},
|
|
2995
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2996
|
+
});
|
|
2997
|
+
const model = {
|
|
2325
2998
|
id: obj.id,
|
|
2326
2999
|
content: doc,
|
|
2327
|
-
text: () =>
|
|
2328
|
-
|
|
2329
|
-
extension:
|
|
3000
|
+
text: () => get7(doc.handle.docSync(), doc.path),
|
|
3001
|
+
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3002
|
+
extension: [
|
|
3003
|
+
modelState.init(() => model),
|
|
3004
|
+
automerge3({
|
|
3005
|
+
handle: doc.handle,
|
|
3006
|
+
path: doc.path
|
|
3007
|
+
}),
|
|
3008
|
+
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
3009
|
+
awareness()
|
|
3010
|
+
].filter(isNotNullOrUndefined),
|
|
2330
3011
|
peer: identity ? {
|
|
2331
3012
|
id: identity.identityKey.toHex(),
|
|
2332
3013
|
name: identity.profile?.displayName
|
|
2333
3014
|
} : void 0
|
|
2334
3015
|
};
|
|
3016
|
+
return model;
|
|
2335
3017
|
};
|
|
2336
3018
|
export {
|
|
3019
|
+
AwarenessProvider,
|
|
2337
3020
|
BaseTextEditor,
|
|
2338
3021
|
Doc,
|
|
2339
3022
|
EditorModes,
|
|
2340
3023
|
MarkdownEditor,
|
|
3024
|
+
RemoteSelectionsDecorator,
|
|
2341
3025
|
SpaceAwarenessProvider,
|
|
2342
3026
|
TextEditor,
|
|
2343
3027
|
TextKind,
|
|
3028
|
+
YAwarenessProvider,
|
|
2344
3029
|
YText,
|
|
2345
3030
|
YXmlFragment,
|
|
2346
3031
|
autocomplete,
|
|
3032
|
+
automerge3 as automerge,
|
|
3033
|
+
awareness,
|
|
2347
3034
|
basicBundle,
|
|
2348
3035
|
blast,
|
|
2349
3036
|
code2 as code,
|
|
2350
3037
|
codeTheme,
|
|
2351
3038
|
comments,
|
|
2352
|
-
|
|
3039
|
+
createAutomergeModel,
|
|
3040
|
+
createYjsModel,
|
|
2353
3041
|
defaultMarkdownSlots,
|
|
2354
3042
|
defaultOptions,
|
|
2355
3043
|
defaultSlots,
|
|
2356
3044
|
defaultTextSlots,
|
|
2357
3045
|
defaultTheme,
|
|
2358
|
-
|
|
2359
|
-
highlight,
|
|
2360
|
-
highlightDecorations,
|
|
2361
|
-
highlightStateField,
|
|
3046
|
+
hr,
|
|
2362
3047
|
image,
|
|
2363
3048
|
link,
|
|
2364
|
-
|
|
3049
|
+
listener,
|
|
2365
3050
|
markdownBundle,
|
|
2366
3051
|
markdownHighlightStyle,
|
|
2367
3052
|
markdownTags,
|
|
2368
3053
|
markdownTagsExtensions,
|
|
2369
3054
|
markdownTheme,
|
|
2370
3055
|
mention,
|
|
3056
|
+
mermaid,
|
|
3057
|
+
modelState,
|
|
3058
|
+
setCommentRange,
|
|
3059
|
+
setFocus,
|
|
3060
|
+
setSelection,
|
|
2371
3061
|
table,
|
|
2372
3062
|
tags2 as tags,
|
|
2373
3063
|
tasklist,
|
|
2374
3064
|
textTheme,
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
3065
|
+
typewriter,
|
|
3066
|
+
useTextModel,
|
|
3067
|
+
yjs
|
|
2378
3068
|
};
|
|
2379
3069
|
//# sourceMappingURL=index.mjs.map
|