@dxos/react-ui-editor 0.3.11-main.c8e9429 → 0.3.11-main.cb5abf5
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 +1627 -1073
- 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 +13 -15
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +13 -5
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/{yjs.stories.d.ts → hooks.stories.d.ts} +13 -2
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +25 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +23 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/index.d.ts +2 -0
- package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/defs.d.ts +8 -10
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -6
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness.d.ts +2 -2
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +4 -5
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +23 -15
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor.d.ts +3 -3
- package/dist/types/src/extensions/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +1 -7
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +13 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +8 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts +3 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +25 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +4 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -0
- package/dist/types/src/hooks/useEditorView.d.ts +17 -0
- package/dist/types/src/hooks/useEditorView.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +39 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts +14 -27
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +2 -2
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +2 -0
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +46 -36
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +73 -82
- package/src/components/TextEditor/TextEditor.tsx +107 -71
- package/src/components/TextEditor/automerge.stories.tsx +1 -2
- package/src/components/TextEditor/hooks.stories.tsx +106 -0
- package/src/components/Toolbar/Toolbar.stories.tsx +90 -0
- package/src/components/Toolbar/Toolbar.tsx +166 -0
- package/src/components/Toolbar/index.ts +5 -0
- package/src/components/index.ts +1 -0
- package/src/extensions/autocomplete.ts +6 -3
- package/src/extensions/automerge/automerge.spec.tsx +76 -0
- package/src/extensions/automerge/automerge.test.ts +13 -0
- package/src/extensions/automerge/automerge.ts +50 -39
- package/src/extensions/automerge/cursor.ts +3 -3
- package/src/extensions/automerge/defs.ts +11 -36
- package/src/extensions/automerge/semaphore.ts +31 -28
- package/src/extensions/automerge/update-automerge.ts +14 -8
- package/src/extensions/automerge/update-codemirror.ts +5 -5
- package/src/extensions/awareness.ts +21 -18
- package/src/extensions/basic.ts +17 -10
- package/src/extensions/blast.ts +4 -1
- package/src/extensions/comments.ts +247 -179
- package/src/extensions/cursor.ts +7 -3
- package/src/extensions/index.ts +1 -7
- package/src/extensions/markdown/bundle.ts +23 -28
- package/src/extensions/markdown/code.ts +150 -0
- package/src/extensions/markdown/formatting.ts +188 -0
- package/src/extensions/markdown/heading.ts +59 -0
- package/src/extensions/markdown/highlight.ts +9 -15
- package/src/extensions/markdown/hr.ts +71 -0
- package/src/extensions/markdown/index.ts +8 -0
- package/src/extensions/{link.ts → markdown/link.ts} +13 -4
- package/src/extensions/{tasklist.ts → markdown/tasklist.ts} +48 -34
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/hooks/awareness-provider.ts +24 -20
- package/src/hooks/defs.ts +42 -0
- package/src/hooks/index.ts +4 -2
- package/src/hooks/useActionHandler.ts +62 -0
- package/src/hooks/useEditorView.ts +29 -0
- package/src/hooks/useTextEditor.ts +153 -0
- package/src/hooks/useTextModel.ts +66 -56
- package/src/index.ts +1 -1
- package/src/styles/markdown.ts +9 -10
- package/src/themes/default.ts +9 -6
- package/src/util.ts +26 -3
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +0 -26
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts +0 -7
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -3
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts +0 -27
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
- package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
- package/dist/types/src/testing/proto/index.d.ts +0 -2
- package/dist/types/src/testing/proto/index.d.ts.map +0 -1
- package/dist/types/src/testing/replicator.d.ts +0 -45
- package/dist/types/src/testing/replicator.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/comments.stories.tsx +0 -355
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/code.ts +0 -104
- package/src/extensions/hr.ts +0 -72
- package/src/extensions/yjs/cursor.ts +0 -22
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.test.ts +0 -35
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -52
- package/src/hooks/yjs.ts +0 -156
- package/src/testing/index.ts +0 -6
- package/src/testing/proto/gen/schema.ts +0 -49
- package/src/testing/proto/index.ts +0 -5
- package/src/testing/proto/schema.proto +0 -15
- package/src/testing/replicator.ts +0 -184
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /package/src/extensions/{image.ts → markdown/image.ts} +0 -0
- /package/src/extensions/{table.ts → markdown/table.ts} +0 -0
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
// packages/ui/react-ui-editor/src/index.ts
|
|
2
2
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
3
3
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
4
|
+
import { keymap as keymap7 } from "@codemirror/view";
|
|
4
5
|
|
|
5
6
|
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
6
7
|
import { tags as tags2 } from "@lezer/highlight";
|
|
7
8
|
|
|
8
9
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
10
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
-
import { EditorView as
|
|
11
|
-
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
11
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle,
|
|
15
|
-
import {
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
15
|
+
import { log as log2 } from "@dxos/log";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
17
|
+
import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
18
19
|
|
|
19
20
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
21
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
@@ -29,9 +30,11 @@ var autocomplete = ({ onSearch }) => {
|
|
|
29
30
|
// https://codemirror.net/examples/autocompletion
|
|
30
31
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
31
32
|
autocompletion({
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
33
|
+
activateOnTyping: true,
|
|
34
|
+
// closeOnBlur: false,
|
|
35
|
+
// defaultKeymap: false,
|
|
36
|
+
// TODO(burdon): Styles/fragments.
|
|
37
|
+
tooltipClass: () => "shadow rounded"
|
|
35
38
|
}),
|
|
36
39
|
// TODO(burdon): Option to create new page?
|
|
37
40
|
// TODO(burdon): Optional decoration via addToOptions
|
|
@@ -51,13 +54,14 @@ var autocomplete = ({ onSearch }) => {
|
|
|
51
54
|
};
|
|
52
55
|
|
|
53
56
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
57
|
+
import { invertedEffects } from "@codemirror/commands";
|
|
54
58
|
import { StateField } from "@codemirror/state";
|
|
55
|
-
import { ViewPlugin } from "@codemirror/view";
|
|
56
|
-
import { next as
|
|
59
|
+
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
60
|
+
import { next as A4 } from "@dxos/automerge/automerge";
|
|
57
61
|
|
|
58
62
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
59
63
|
import get from "lodash.get";
|
|
60
|
-
import { next as
|
|
64
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
61
65
|
var cursorConverter = (handle, path) => ({
|
|
62
66
|
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
63
67
|
toCursor: (pos) => {
|
|
@@ -69,7 +73,7 @@ var cursorConverter = (handle, path) => ({
|
|
|
69
73
|
if (typeof value === "string" && value.length <= pos) {
|
|
70
74
|
return "end";
|
|
71
75
|
}
|
|
72
|
-
return
|
|
76
|
+
return A.getCursor(doc, path.slice(), pos);
|
|
73
77
|
},
|
|
74
78
|
fromCursor: (cursor) => {
|
|
75
79
|
if (cursor === "") {
|
|
@@ -87,29 +91,28 @@ var cursorConverter = (handle, path) => ({
|
|
|
87
91
|
return 0;
|
|
88
92
|
}
|
|
89
93
|
}
|
|
90
|
-
return
|
|
94
|
+
return A.getCursorPosition(doc, path.slice(), cursor);
|
|
91
95
|
}
|
|
92
96
|
});
|
|
93
97
|
|
|
94
98
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
95
|
-
import { Annotation, StateEffect
|
|
96
|
-
var effectType = StateEffect.define({});
|
|
97
|
-
var updateHeads = (newHeads) => effectType.of({
|
|
98
|
-
newHeads
|
|
99
|
-
});
|
|
100
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
99
|
+
import { Annotation, StateEffect } from "@codemirror/state";
|
|
101
100
|
var getPath = (state, field) => state.field(field).path;
|
|
102
|
-
var
|
|
103
|
-
var
|
|
104
|
-
var
|
|
105
|
-
|
|
101
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
102
|
+
var updateHeadsEffect = StateEffect.define({});
|
|
103
|
+
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
104
|
+
newHeads
|
|
106
105
|
});
|
|
106
|
+
var reconcileAnnotation = Annotation.define();
|
|
107
|
+
var isReconcile = (tr) => {
|
|
108
|
+
return !!tr.annotation(reconcileAnnotation);
|
|
109
|
+
};
|
|
107
110
|
|
|
108
111
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
109
|
-
import { next as
|
|
112
|
+
import { next as A3 } from "@dxos/automerge/automerge";
|
|
110
113
|
|
|
111
114
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
112
|
-
import { next as
|
|
115
|
+
import { next as A2 } from "@dxos/automerge/automerge";
|
|
113
116
|
var updateAutomerge = (field, handle, transactions, state) => {
|
|
114
117
|
const { lastHeads, path } = state.field(field);
|
|
115
118
|
let hasChanges = false;
|
|
@@ -122,11 +125,19 @@ var updateAutomerge = (field, handle, transactions, state) => {
|
|
|
122
125
|
return void 0;
|
|
123
126
|
}
|
|
124
127
|
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
128
|
+
const invertedTransactions = [];
|
|
125
129
|
for (const tr of transactions) {
|
|
126
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB,
|
|
127
|
-
|
|
130
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
|
|
131
|
+
invertedTransactions.push({
|
|
132
|
+
from: fromA,
|
|
133
|
+
del: toA - fromA,
|
|
134
|
+
insert
|
|
135
|
+
});
|
|
128
136
|
});
|
|
129
137
|
}
|
|
138
|
+
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
|
139
|
+
A2.splice(doc, path.slice(), from, del, insert.toString());
|
|
140
|
+
});
|
|
130
141
|
});
|
|
131
142
|
return newHeads ?? void 0;
|
|
132
143
|
};
|
|
@@ -141,13 +152,13 @@ var updateCodeMirror = (view, selection, target, patches) => {
|
|
|
141
152
|
selection = selection.map(changeSet, 1);
|
|
142
153
|
view.dispatch({
|
|
143
154
|
changes: changeSet,
|
|
144
|
-
annotations:
|
|
155
|
+
annotations: reconcileAnnotation.of(false)
|
|
145
156
|
});
|
|
146
157
|
}
|
|
147
158
|
}
|
|
148
159
|
view.dispatch({
|
|
149
160
|
selection,
|
|
150
|
-
annotations:
|
|
161
|
+
annotations: reconcileAnnotation.of(false)
|
|
151
162
|
});
|
|
152
163
|
};
|
|
153
164
|
var handlePatch = (patch, target, state) => {
|
|
@@ -168,7 +179,7 @@ var handleInsert = (target, patch) => {
|
|
|
168
179
|
if (index == null) {
|
|
169
180
|
return [];
|
|
170
181
|
}
|
|
171
|
-
const text = patch.values.map((
|
|
182
|
+
const text = patch.values.map((value) => value ? value.toString() : "").join("");
|
|
172
183
|
return [
|
|
173
184
|
{
|
|
174
185
|
from: index,
|
|
@@ -240,59 +251,63 @@ var charPath = (textPath, candidatePath) => {
|
|
|
240
251
|
|
|
241
252
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
242
253
|
var PatchSemaphore = class {
|
|
243
|
-
|
|
254
|
+
// prettier-ignore
|
|
255
|
+
constructor(_handle, _state) {
|
|
244
256
|
this._handle = _handle;
|
|
245
|
-
this.
|
|
257
|
+
this._state = _state;
|
|
246
258
|
this._inReconcile = false;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
259
|
+
}
|
|
260
|
+
reconcile(view) {
|
|
261
|
+
if (!this._inReconcile) {
|
|
251
262
|
this._inReconcile = true;
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
let newHeads = updateAutomerge(this._field, this._handle, transactions, view.state);
|
|
266
|
-
if (newHeads === null || newHeads === void 0) {
|
|
267
|
-
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
268
|
-
}
|
|
269
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
270
|
-
updateCodeMirror(view, selection, path, diff);
|
|
263
|
+
this.doReconcile(view);
|
|
264
|
+
this._inReconcile = false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
doReconcile(view) {
|
|
268
|
+
const path = getPath(view.state, this._state);
|
|
269
|
+
const oldHeads = getLastHeads(view.state, this._state);
|
|
270
|
+
let selection = view.state.selection;
|
|
271
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
272
|
+
const toInvert = transactions.slice().reverse();
|
|
273
|
+
for (const tr of toInvert) {
|
|
274
|
+
const inverted = tr.changes.invert(tr.startState.doc);
|
|
275
|
+
selection = selection.map(inverted);
|
|
271
276
|
view.dispatch({
|
|
272
|
-
|
|
273
|
-
annotations:
|
|
277
|
+
changes: inverted,
|
|
278
|
+
annotations: reconcileAnnotation.of(true)
|
|
274
279
|
});
|
|
275
|
-
|
|
276
|
-
|
|
280
|
+
}
|
|
281
|
+
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
282
|
+
if (newHeads === null || newHeads === void 0) {
|
|
283
|
+
newHeads = A3.getHeads(this._handle.docSync());
|
|
284
|
+
}
|
|
285
|
+
const diff = A3.equals(oldHeads, newHeads) ? [] : A3.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
286
|
+
updateCodeMirror(view, selection, path, diff);
|
|
287
|
+
view.dispatch({
|
|
288
|
+
effects: updateHeads(newHeads),
|
|
289
|
+
annotations: reconcileAnnotation.of(false)
|
|
290
|
+
});
|
|
277
291
|
}
|
|
278
292
|
};
|
|
279
293
|
|
|
280
294
|
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
281
|
-
import { Facet
|
|
295
|
+
import { Facet } from "@codemirror/state";
|
|
282
296
|
var defaultCursorConverter = {
|
|
283
297
|
toCursor: (position) => position.toString(),
|
|
284
298
|
fromCursor: (cursor) => parseInt(cursor)
|
|
285
299
|
};
|
|
286
|
-
var Cursor = class {
|
|
300
|
+
var Cursor = class _Cursor {
|
|
287
301
|
static {
|
|
288
|
-
this.converter =
|
|
302
|
+
this.converter = Facet.define({
|
|
289
303
|
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
290
304
|
});
|
|
291
305
|
}
|
|
292
306
|
static {
|
|
293
|
-
this.getCursorFromRange = (
|
|
294
|
-
const
|
|
295
|
-
const
|
|
307
|
+
this.getCursorFromRange = (state, range) => {
|
|
308
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
309
|
+
const from = cursorConverter2.toCursor(range.from);
|
|
310
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
|
296
311
|
return [
|
|
297
312
|
from,
|
|
298
313
|
to
|
|
@@ -300,10 +315,11 @@ var Cursor = class {
|
|
|
300
315
|
};
|
|
301
316
|
}
|
|
302
317
|
static {
|
|
303
|
-
this.getRangeFromCursor = (
|
|
318
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
319
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
304
320
|
const parts = cursor.split(":");
|
|
305
|
-
const from =
|
|
306
|
-
const to =
|
|
321
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
|
322
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
|
307
323
|
return from !== void 0 && to !== void 0 ? {
|
|
308
324
|
from,
|
|
309
325
|
to
|
|
@@ -313,22 +329,22 @@ var Cursor = class {
|
|
|
313
329
|
};
|
|
314
330
|
|
|
315
331
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
316
|
-
var
|
|
317
|
-
const
|
|
332
|
+
var automerge = ({ handle, path }) => {
|
|
333
|
+
const syncState = StateField.define({
|
|
318
334
|
create: () => ({
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
335
|
+
path: path.slice(),
|
|
336
|
+
lastHeads: A4.getHeads(handle.docSync()),
|
|
337
|
+
unreconciledTransactions: []
|
|
322
338
|
}),
|
|
323
339
|
update: (value, tr) => {
|
|
324
340
|
const result = {
|
|
341
|
+
path: path.slice(),
|
|
325
342
|
lastHeads: value.lastHeads,
|
|
326
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
327
|
-
path: path.slice()
|
|
343
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
328
344
|
};
|
|
329
345
|
let clearUnreconciled = false;
|
|
330
346
|
for (const effect of tr.effects) {
|
|
331
|
-
if (effect.is(
|
|
347
|
+
if (effect.is(updateHeadsEffect)) {
|
|
332
348
|
result.lastHeads = effect.value.newHeads;
|
|
333
349
|
clearUnreconciled = true;
|
|
334
350
|
}
|
|
@@ -336,46 +352,53 @@ var automerge3 = ({ handle, path }) => {
|
|
|
336
352
|
if (clearUnreconciled) {
|
|
337
353
|
result.unreconciledTransactions = [];
|
|
338
354
|
} else {
|
|
339
|
-
if (!
|
|
355
|
+
if (!isReconcile(tr)) {
|
|
340
356
|
result.unreconciledTransactions.push(tr);
|
|
341
357
|
}
|
|
342
358
|
}
|
|
343
359
|
return result;
|
|
344
360
|
}
|
|
345
361
|
});
|
|
346
|
-
const semaphore = new PatchSemaphore(handle,
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
362
|
+
const semaphore = new PatchSemaphore(handle, syncState);
|
|
363
|
+
return [
|
|
364
|
+
Cursor.converter.of(cursorConverter(handle, path)),
|
|
365
|
+
syncState,
|
|
366
|
+
// Reconcile external updates.
|
|
367
|
+
ViewPlugin.fromClass(class {
|
|
368
|
+
constructor(_view) {
|
|
369
|
+
this._view = _view;
|
|
370
|
+
handle.addListener("change", this._handleChange.bind(this));
|
|
371
|
+
}
|
|
372
|
+
destroy() {
|
|
373
|
+
handle.removeListener("change", this._handleChange.bind(this));
|
|
374
|
+
}
|
|
375
|
+
_handleChange() {
|
|
376
|
+
semaphore.reconcile(this._view);
|
|
377
|
+
}
|
|
378
|
+
}),
|
|
379
|
+
// Reconcile local updates.
|
|
380
|
+
EditorView.updateListener.of(({ view, changes }) => {
|
|
381
|
+
if (!changes.empty) {
|
|
382
|
+
semaphore.reconcile(view);
|
|
383
|
+
}
|
|
384
|
+
}),
|
|
385
|
+
// TODO(burdon): Record undo transactions.
|
|
386
|
+
// See https://github.com/yjs/y-codemirror.next/tree/main
|
|
387
|
+
// https://codemirror.net/examples/inverted-effect
|
|
388
|
+
invertedEffects.of((tr) => {
|
|
389
|
+
const effects = [];
|
|
390
|
+
if (!tr.changes.empty) {
|
|
391
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
|
|
359
392
|
});
|
|
360
393
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
return {
|
|
367
|
-
extension: [
|
|
368
|
-
Cursor.converter.of(cursorConverter(handle, path)),
|
|
369
|
-
semaphoreFacet.of(semaphore),
|
|
370
|
-
stateField,
|
|
371
|
-
viewPlugin
|
|
372
|
-
]
|
|
373
|
-
};
|
|
394
|
+
return effects;
|
|
395
|
+
})
|
|
396
|
+
];
|
|
374
397
|
};
|
|
375
398
|
|
|
376
399
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
377
|
-
import { Annotation as Annotation2, Facet as
|
|
378
|
-
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
400
|
+
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
401
|
+
import { Decoration, EditorView as EditorView2, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
379
402
|
import { Event } from "@dxos/async";
|
|
380
403
|
import { Context } from "@dxos/context";
|
|
381
404
|
var dummyProvider = {
|
|
@@ -384,17 +407,17 @@ var dummyProvider = {
|
|
|
384
407
|
},
|
|
385
408
|
close: () => {
|
|
386
409
|
},
|
|
410
|
+
getRemoteStates: () => [],
|
|
387
411
|
update: () => {
|
|
388
|
-
}
|
|
389
|
-
getRemoteStates: () => []
|
|
412
|
+
}
|
|
390
413
|
};
|
|
391
|
-
var
|
|
414
|
+
var awarenessProvider = Facet2.define({
|
|
392
415
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
393
416
|
});
|
|
394
417
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
395
418
|
var awareness = (provider = dummyProvider) => {
|
|
396
419
|
return [
|
|
397
|
-
|
|
420
|
+
awarenessProvider.of(provider),
|
|
398
421
|
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
399
422
|
decorations: (value) => value.decorations
|
|
400
423
|
}),
|
|
@@ -408,7 +431,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
408
431
|
this._lastAnchor = void 0;
|
|
409
432
|
this._lastHead = void 0;
|
|
410
433
|
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
411
|
-
this._provider = view.state.facet(
|
|
434
|
+
this._provider = view.state.facet(awarenessProvider);
|
|
412
435
|
this._provider.open();
|
|
413
436
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
414
437
|
view.dispatch({
|
|
@@ -549,7 +572,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
549
572
|
return true;
|
|
550
573
|
}
|
|
551
574
|
};
|
|
552
|
-
var styles =
|
|
575
|
+
var styles = EditorView2.baseTheme({
|
|
553
576
|
".cm-collab-selection": {},
|
|
554
577
|
".cm-collab-selectionLine": {
|
|
555
578
|
padding: 0,
|
|
@@ -562,39 +585,41 @@ var styles = EditorView.baseTheme({
|
|
|
562
585
|
marginLeft: "-1px",
|
|
563
586
|
marginRight: "-1px",
|
|
564
587
|
boxSizing: "border-box",
|
|
565
|
-
display: "inline"
|
|
588
|
+
display: "inline",
|
|
589
|
+
cursor: "pointer"
|
|
566
590
|
},
|
|
567
591
|
".cm-collab-selectionCaretDot": {
|
|
568
592
|
borderRadius: "50%",
|
|
569
593
|
position: "absolute",
|
|
570
|
-
width: ".
|
|
571
|
-
height: ".
|
|
572
|
-
top: "-.
|
|
573
|
-
left: "-.
|
|
594
|
+
width: ".5em",
|
|
595
|
+
height: ".5em",
|
|
596
|
+
top: "-.25em",
|
|
597
|
+
left: "-.25em",
|
|
574
598
|
backgroundColor: "inherit",
|
|
575
599
|
transition: "transform .3s ease-in-out",
|
|
576
600
|
boxSizing: "border-box"
|
|
577
601
|
},
|
|
578
602
|
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
579
|
-
|
|
580
|
-
|
|
603
|
+
transform: "scale(0)",
|
|
604
|
+
transformOrigin: "center"
|
|
581
605
|
},
|
|
582
606
|
".cm-collab-selectionInfo": {
|
|
583
607
|
position: "absolute",
|
|
584
|
-
|
|
585
|
-
|
|
608
|
+
transform: "translate(-50%, 0)",
|
|
609
|
+
top: "-20px",
|
|
610
|
+
left: 0,
|
|
586
611
|
fontSize: ".75em",
|
|
587
|
-
fontFamily: "serif",
|
|
612
|
+
fontFamily: "sans-serif",
|
|
588
613
|
fontStyle: "normal",
|
|
589
614
|
fontWeight: "normal",
|
|
590
615
|
lineHeight: "normal",
|
|
591
616
|
userSelect: "none",
|
|
592
617
|
color: "white",
|
|
593
|
-
|
|
594
|
-
paddingRight: "2px",
|
|
618
|
+
padding: "2px",
|
|
595
619
|
zIndex: 101,
|
|
596
620
|
transition: "opacity .3s ease-in-out",
|
|
597
621
|
backgroundColor: "inherit",
|
|
622
|
+
borderRadius: "2px",
|
|
598
623
|
// These should be separate.
|
|
599
624
|
opacity: 0,
|
|
600
625
|
transitionDelay: "0s",
|
|
@@ -608,23 +633,26 @@ var styles = EditorView.baseTheme({
|
|
|
608
633
|
|
|
609
634
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
610
635
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
636
|
+
import { history } from "@codemirror/commands";
|
|
611
637
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
612
638
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
613
|
-
import { drawSelection, EditorView as
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
639
|
+
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
640
|
+
import { isNotFalsy } from "@dxos/util";
|
|
641
|
+
var createBasicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => [
|
|
642
|
+
lineWrapping && EditorView3.lineWrapping,
|
|
617
643
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
618
644
|
bracketMatching(),
|
|
619
645
|
closeBrackets(),
|
|
620
646
|
drawSelection(),
|
|
647
|
+
highlightActiveLine(),
|
|
648
|
+
history(),
|
|
621
649
|
_placeholder && placeholder(_placeholder),
|
|
622
|
-
//
|
|
650
|
+
// https://github.com/codemirror/theme-one-dark
|
|
623
651
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
624
|
-
].filter(
|
|
652
|
+
].filter(isNotFalsy);
|
|
625
653
|
|
|
626
654
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
627
|
-
import { EditorView as
|
|
655
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
628
656
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
629
657
|
import { invariant } from "@dxos/invariant";
|
|
630
658
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
@@ -660,10 +688,10 @@ var blast = (options = defaultOptions) => {
|
|
|
660
688
|
const getPoint = (view, pos) => {
|
|
661
689
|
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
662
690
|
const element = document.elementFromPoint(x, y);
|
|
663
|
-
const { offsetLeft: left = 0, offsetTop:
|
|
691
|
+
const { offsetLeft: left = 0, offsetTop: top2 = 0 } = view.scrollDOM.parentElement ?? {};
|
|
664
692
|
const point = {
|
|
665
693
|
x: x - left,
|
|
666
|
-
y: y -
|
|
694
|
+
y: y - top2
|
|
667
695
|
};
|
|
668
696
|
return {
|
|
669
697
|
element,
|
|
@@ -672,7 +700,7 @@ var blast = (options = defaultOptions) => {
|
|
|
672
700
|
};
|
|
673
701
|
return [
|
|
674
702
|
// Cursor moved.
|
|
675
|
-
|
|
703
|
+
EditorView4.updateListener.of((update2) => {
|
|
676
704
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
677
705
|
if (blaster) {
|
|
678
706
|
blaster.destroy();
|
|
@@ -755,7 +783,7 @@ var Blaster = class {
|
|
|
755
783
|
initialize() {
|
|
756
784
|
invariant(!this._canvas && !this._ctx, void 0, {
|
|
757
785
|
F: __dxlog_file,
|
|
758
|
-
L:
|
|
786
|
+
L: 141,
|
|
759
787
|
S: this,
|
|
760
788
|
A: [
|
|
761
789
|
"!this._canvas && !this._ctx",
|
|
@@ -792,7 +820,7 @@ var Blaster = class {
|
|
|
792
820
|
start() {
|
|
793
821
|
invariant(this._canvas && this._ctx, void 0, {
|
|
794
822
|
F: __dxlog_file,
|
|
795
|
-
L:
|
|
823
|
+
L: 180,
|
|
796
824
|
S: this,
|
|
797
825
|
A: [
|
|
798
826
|
"this._canvas && this._ctx",
|
|
@@ -933,9 +961,14 @@ var random = (min, max) => {
|
|
|
933
961
|
return min + ~~(Math.random() * (max - min + 1));
|
|
934
962
|
};
|
|
935
963
|
|
|
936
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
937
|
-
import {
|
|
938
|
-
import {
|
|
964
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
965
|
+
import { invertedEffects as invertedEffects2 } from "@codemirror/commands";
|
|
966
|
+
import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
967
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
968
|
+
import sortBy from "lodash.sortby";
|
|
969
|
+
import { useEffect } from "react";
|
|
970
|
+
import { debounce } from "@dxos/async";
|
|
971
|
+
import { nonNullable } from "@dxos/util";
|
|
939
972
|
|
|
940
973
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
941
974
|
import * as random2 from "lib0/random";
|
|
@@ -978,34 +1011,15 @@ var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
|
978
1011
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
979
1012
|
import { mx } from "@dxos/react-ui-theme";
|
|
980
1013
|
var headings = {
|
|
981
|
-
1:
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
991
|
-
"-ml-[7px]"
|
|
992
|
-
],
|
|
993
|
-
4: [
|
|
994
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
995
|
-
"-ml-[6px]"
|
|
996
|
-
],
|
|
997
|
-
5: [
|
|
998
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
999
|
-
"-ml-[5px]"
|
|
1000
|
-
],
|
|
1001
|
-
6: [
|
|
1002
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
1003
|
-
"-ml-[4px]"
|
|
1004
|
-
]
|
|
1005
|
-
};
|
|
1006
|
-
var heading = (level, readonly) => {
|
|
1007
|
-
const [style, offset] = headings[level];
|
|
1008
|
-
return mx(style, readonly && offset);
|
|
1014
|
+
1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
1015
|
+
2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
1016
|
+
3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
1017
|
+
4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
1018
|
+
5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
1019
|
+
6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
|
|
1020
|
+
};
|
|
1021
|
+
var heading = (level) => {
|
|
1022
|
+
return headings[level];
|
|
1009
1023
|
};
|
|
1010
1024
|
var light = "text-neutral-200 dark:text-neutral-800";
|
|
1011
1025
|
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
@@ -1023,165 +1037,109 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
|
1023
1037
|
var tokens = tailwindConfig({}).theme;
|
|
1024
1038
|
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1025
1039
|
|
|
1026
|
-
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1027
|
-
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1028
|
-
var styles2 = EditorView4.baseTheme({
|
|
1029
|
-
"& .cm-codeblock": {
|
|
1030
|
-
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1031
|
-
},
|
|
1032
|
-
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1033
|
-
background: getToken("extend.colors.neutral.50")
|
|
1034
|
-
},
|
|
1035
|
-
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1036
|
-
background: getToken("extend.colors.neutral.850")
|
|
1037
|
-
},
|
|
1038
|
-
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1039
|
-
display: "block",
|
|
1040
|
-
paddingInline: "4px !important"
|
|
1041
|
-
},
|
|
1042
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1043
|
-
paddingTop: "4px !important",
|
|
1044
|
-
borderTopLeftRadius: "4px",
|
|
1045
|
-
borderTopRightRadius: "4px"
|
|
1046
|
-
},
|
|
1047
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1048
|
-
paddingBottom: "4px !important",
|
|
1049
|
-
borderBottomLeftRadius: "4px",
|
|
1050
|
-
borderBottomRightRadius: "4px"
|
|
1051
|
-
}
|
|
1052
|
-
});
|
|
1053
|
-
var getLineRange = (lines, from, to) => {
|
|
1054
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1055
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1056
|
-
return [
|
|
1057
|
-
start,
|
|
1058
|
-
end
|
|
1059
|
-
];
|
|
1060
|
-
};
|
|
1061
|
-
var code2 = () => {
|
|
1062
|
-
const buildDecorations4 = (view) => {
|
|
1063
|
-
const decorations = [];
|
|
1064
|
-
const text = view.state.doc.sliceString(0);
|
|
1065
|
-
const matches = text.matchAll(CODE_REGEX);
|
|
1066
|
-
const blocks = view.viewportLineBlocks;
|
|
1067
|
-
for (const match of matches) {
|
|
1068
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1069
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1070
|
-
const block = blocks[i];
|
|
1071
|
-
decorations.push(Decoration2.line({
|
|
1072
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1073
|
-
}).range(block.from));
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
return Decoration2.set(decorations);
|
|
1077
|
-
};
|
|
1078
|
-
return [
|
|
1079
|
-
ViewPlugin3.fromClass(class {
|
|
1080
|
-
constructor(view) {
|
|
1081
|
-
this.hasFocus = false;
|
|
1082
|
-
this.decorations = buildDecorations4(view);
|
|
1083
|
-
}
|
|
1084
|
-
update(update2) {
|
|
1085
|
-
if (
|
|
1086
|
-
// TODO(burdon): Generalize for other extensions.
|
|
1087
|
-
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1088
|
-
) {
|
|
1089
|
-
this.hasFocus = update2.view.hasFocus;
|
|
1090
|
-
this.decorations = buildDecorations4(update2.view);
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
}, {
|
|
1094
|
-
decorations: (value) => value.decorations
|
|
1095
|
-
}),
|
|
1096
|
-
styles2
|
|
1097
|
-
];
|
|
1098
|
-
};
|
|
1099
|
-
|
|
1100
|
-
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1101
|
-
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1102
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
|
|
1103
|
-
import sortBy from "lodash.sortby";
|
|
1104
|
-
import { debounce } from "@dxos/async";
|
|
1105
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1106
|
-
import { nonNullable } from "@dxos/util";
|
|
1107
|
-
|
|
1108
1040
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1109
1041
|
import { log } from "@dxos/log";
|
|
1110
1042
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1111
1043
|
var callbackWrapper = (fn) => (...args) => {
|
|
1112
1044
|
try {
|
|
1113
1045
|
return fn(...args);
|
|
1114
|
-
} catch (
|
|
1115
|
-
log.catch(
|
|
1046
|
+
} catch (err) {
|
|
1047
|
+
log.catch(err, void 0, {
|
|
1116
1048
|
F: __dxlog_file2,
|
|
1117
|
-
L:
|
|
1049
|
+
L: 18,
|
|
1118
1050
|
S: void 0,
|
|
1119
1051
|
C: (f, a) => f(...a)
|
|
1120
1052
|
});
|
|
1121
1053
|
}
|
|
1122
1054
|
};
|
|
1055
|
+
var logChanges = (trs) => {
|
|
1056
|
+
const changes = trs.flatMap((tr) => {
|
|
1057
|
+
if (tr.changes.empty) {
|
|
1058
|
+
return void 0;
|
|
1059
|
+
}
|
|
1060
|
+
const changes2 = [];
|
|
1061
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1062
|
+
fromA,
|
|
1063
|
+
toA,
|
|
1064
|
+
fromB,
|
|
1065
|
+
toB,
|
|
1066
|
+
inserted: inserted.toString()
|
|
1067
|
+
})));
|
|
1068
|
+
return changes2;
|
|
1069
|
+
}).filter(Boolean);
|
|
1070
|
+
if (changes.length) {
|
|
1071
|
+
console.log("changes", changes);
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1123
1074
|
|
|
1124
1075
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1125
|
-
var
|
|
1126
|
-
var styles3 = EditorView5.baseTheme({
|
|
1076
|
+
var styles2 = EditorView5.baseTheme({
|
|
1127
1077
|
"& .cm-comment": {
|
|
1128
1078
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1129
1079
|
},
|
|
1130
|
-
"& .cm-comment-
|
|
1080
|
+
"& .cm-comment-current": {
|
|
1131
1081
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1132
1082
|
}
|
|
1133
1083
|
});
|
|
1134
|
-
var
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
const range = view.state.field(commentsStateField).ranges.find((range2) => range2.id === thread);
|
|
1144
|
-
if (!range) {
|
|
1084
|
+
var commentMark = Decoration2.mark({
|
|
1085
|
+
class: "cm-comment"
|
|
1086
|
+
});
|
|
1087
|
+
var commentCurrentMark = Decoration2.mark({
|
|
1088
|
+
class: "cm-comment-current"
|
|
1089
|
+
});
|
|
1090
|
+
var focusComment = (view, id, center = true) => {
|
|
1091
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1092
|
+
if (!comment?.comment.cursor) {
|
|
1145
1093
|
return;
|
|
1146
1094
|
}
|
|
1147
|
-
view.
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1095
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1096
|
+
if (range) {
|
|
1097
|
+
view.dispatch({
|
|
1098
|
+
selection: {
|
|
1099
|
+
anchor: range.from
|
|
1100
|
+
},
|
|
1101
|
+
effects: [
|
|
1102
|
+
//
|
|
1103
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1104
|
+
y: "center"
|
|
1105
|
+
} : void 0),
|
|
1106
|
+
setSelection.of({
|
|
1107
|
+
current: id
|
|
1108
|
+
})
|
|
1109
|
+
]
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1156
1112
|
};
|
|
1157
|
-
var
|
|
1113
|
+
var setComments = StateEffect2.define();
|
|
1158
1114
|
var setSelection = StateEffect2.define();
|
|
1159
1115
|
var setCommentState = StateEffect2.define();
|
|
1160
|
-
var
|
|
1116
|
+
var commentsState = StateField2.define({
|
|
1161
1117
|
create: () => ({
|
|
1162
|
-
|
|
1118
|
+
comments: [],
|
|
1119
|
+
selection: {}
|
|
1163
1120
|
}),
|
|
1164
1121
|
update: (value, tr) => {
|
|
1165
|
-
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1166
1122
|
for (const effect of tr.effects) {
|
|
1167
1123
|
if (effect.is(setSelection)) {
|
|
1168
1124
|
return {
|
|
1169
1125
|
...value,
|
|
1170
|
-
|
|
1126
|
+
selection: effect.value
|
|
1171
1127
|
};
|
|
1172
1128
|
}
|
|
1173
|
-
if (effect.is(
|
|
1174
|
-
const
|
|
1175
|
-
|
|
1176
|
-
|
|
1129
|
+
if (effect.is(setComments)) {
|
|
1130
|
+
const comments2 = effect.value.map((comment) => {
|
|
1131
|
+
if (!comment.cursor) {
|
|
1132
|
+
return void 0;
|
|
1133
|
+
}
|
|
1134
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1177
1135
|
return range && {
|
|
1178
|
-
|
|
1179
|
-
|
|
1136
|
+
comment,
|
|
1137
|
+
range
|
|
1180
1138
|
};
|
|
1181
1139
|
}).filter(nonNullable);
|
|
1182
1140
|
return {
|
|
1183
1141
|
...value,
|
|
1184
|
-
|
|
1142
|
+
comments: comments2
|
|
1185
1143
|
};
|
|
1186
1144
|
}
|
|
1187
1145
|
if (effect.is(setCommentState)) {
|
|
@@ -1191,39 +1149,37 @@ var commentsStateField = StateField2.define({
|
|
|
1191
1149
|
return value;
|
|
1192
1150
|
}
|
|
1193
1151
|
});
|
|
1194
|
-
var
|
|
1195
|
-
|
|
1152
|
+
var commentsDecorations = EditorView5.decorations.compute([
|
|
1153
|
+
commentsState
|
|
1196
1154
|
], (state) => {
|
|
1197
|
-
const {
|
|
1198
|
-
const decorations = sortBy(
|
|
1199
|
-
|
|
1155
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1156
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1157
|
+
const range = comment.range;
|
|
1158
|
+
if (!range || range.from === range.to) {
|
|
1159
|
+
console.warn("Invalid range:", range);
|
|
1200
1160
|
return void 0;
|
|
1201
1161
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
to: selection.to
|
|
1205
|
-
};
|
|
1206
|
-
if (selection.id === active) {
|
|
1207
|
-
return marks.highlightActive.range(range.from, range.to);
|
|
1162
|
+
if (comment.comment.id === current) {
|
|
1163
|
+
return commentCurrentMark.range(range.from, range.to);
|
|
1208
1164
|
} else {
|
|
1209
|
-
return
|
|
1165
|
+
return commentMark.range(range.from, range.to);
|
|
1210
1166
|
}
|
|
1211
|
-
}).filter(nonNullable)
|
|
1212
|
-
return
|
|
1167
|
+
}).filter(nonNullable);
|
|
1168
|
+
return Decoration2.set(decorations);
|
|
1213
1169
|
});
|
|
1214
1170
|
var trackPastedComments = (onUpdate) => {
|
|
1215
1171
|
let tracked = null;
|
|
1216
1172
|
const handleTrack = (event, view) => {
|
|
1217
|
-
const comments2 = view.state.field(
|
|
1173
|
+
const comments2 = view.state.field(commentsState);
|
|
1218
1174
|
const { main } = view.state.selection;
|
|
1219
|
-
const selectedRanges = comments2.
|
|
1175
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1220
1176
|
if (!selectedRanges.length) {
|
|
1221
1177
|
tracked = null;
|
|
1222
1178
|
} else {
|
|
1223
1179
|
tracked = {
|
|
1224
1180
|
text: view.state.doc.slice(main.from, main.to),
|
|
1225
|
-
comments: selectedRanges.map((range) => ({
|
|
1226
|
-
id:
|
|
1181
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1182
|
+
id: comment.id,
|
|
1227
1183
|
from: range.from - main.from,
|
|
1228
1184
|
to: range.to - main.from
|
|
1229
1185
|
}))
|
|
@@ -1235,90 +1191,132 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1235
1191
|
cut: handleTrack,
|
|
1236
1192
|
copy: handleTrack
|
|
1237
1193
|
}),
|
|
1238
|
-
//
|
|
1239
|
-
|
|
1194
|
+
// Track deleted comments.
|
|
1195
|
+
invertedEffects2.of((tr) => {
|
|
1196
|
+
const { comments: comments2 } = tr.startState.field(commentsState);
|
|
1197
|
+
const effects = [];
|
|
1198
|
+
tr.changes.iterChangedRanges((fromA, toA) => {
|
|
1199
|
+
for (const { comment: { id }, range: { from, to } } of comments2) {
|
|
1200
|
+
if (from < to && from >= fromA && to <= toA) {
|
|
1201
|
+
effects.push(restoreCommentEffect.of({
|
|
1202
|
+
id,
|
|
1203
|
+
from,
|
|
1204
|
+
to
|
|
1205
|
+
}));
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
});
|
|
1209
|
+
return effects;
|
|
1210
|
+
}),
|
|
1211
|
+
// Handle paste or the undo of comment deletion.
|
|
1212
|
+
EditorView5.updateListener.of((update2) => {
|
|
1213
|
+
const restore = [];
|
|
1214
|
+
for (let i = 0; i < update2.transactions.length; i++) {
|
|
1215
|
+
const tr = update2.transactions[i];
|
|
1216
|
+
for (let j = 0; j < restore.length; j++) {
|
|
1217
|
+
restore[j] = mapTrackedComment(restore[j], tr.changes);
|
|
1218
|
+
}
|
|
1219
|
+
for (const effect of tr.effects) {
|
|
1220
|
+
if (effect.is(restoreCommentEffect)) {
|
|
1221
|
+
restore.push(effect.value);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1240
1225
|
if (tracked) {
|
|
1241
|
-
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1226
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1242
1227
|
if (paste) {
|
|
1243
1228
|
let found = -1;
|
|
1244
1229
|
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1245
1230
|
if (text.eq(tracked.text)) {
|
|
1246
|
-
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1247
|
-
fromB = transactions[i].changes.mapPos(fromB);
|
|
1231
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1232
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1248
1233
|
}
|
|
1249
1234
|
found = fromB;
|
|
1250
1235
|
}
|
|
1251
1236
|
});
|
|
1252
1237
|
if (found > -1) {
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
from: found + moved.from,
|
|
1260
|
-
to: found + moved.to
|
|
1261
|
-
};
|
|
1262
|
-
const cursor = Cursor.getCursorFromRange(state.facet(Cursor.converter), range);
|
|
1263
|
-
onUpdate(moved.id, cursor);
|
|
1264
|
-
}
|
|
1238
|
+
for (const moved of tracked.comments) {
|
|
1239
|
+
restore.push({
|
|
1240
|
+
id: moved.id,
|
|
1241
|
+
from: found + moved.from,
|
|
1242
|
+
to: found + moved.to
|
|
1243
|
+
});
|
|
1265
1244
|
}
|
|
1266
1245
|
}
|
|
1267
1246
|
tracked = null;
|
|
1268
1247
|
}
|
|
1269
1248
|
}
|
|
1249
|
+
for (const comment of restore) {
|
|
1250
|
+
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
1251
|
+
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
1252
|
+
if (!exists) {
|
|
1253
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
1254
|
+
onUpdate(comment.id, cursor);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1270
1257
|
})
|
|
1271
1258
|
];
|
|
1272
1259
|
};
|
|
1260
|
+
var mapTrackedComment = (comment, changes) => ({
|
|
1261
|
+
id: comment.id,
|
|
1262
|
+
from: changes.mapPos(comment.from, 1),
|
|
1263
|
+
to: changes.mapPos(comment.to, 1)
|
|
1264
|
+
});
|
|
1265
|
+
var restoreCommentEffect = StateEffect2.define({
|
|
1266
|
+
map: mapTrackedComment
|
|
1267
|
+
});
|
|
1268
|
+
var optionsFacet = Facet3.define({
|
|
1269
|
+
combine: (providers) => providers[0]
|
|
1270
|
+
});
|
|
1271
|
+
var createComment = (view) => {
|
|
1272
|
+
const options = view.state.facet(optionsFacet);
|
|
1273
|
+
const { from, to } = view.state.selection.main;
|
|
1274
|
+
if (from === to) {
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
if (to === view.state.doc.length) {
|
|
1278
|
+
view.dispatch({
|
|
1279
|
+
changes: {
|
|
1280
|
+
from: to,
|
|
1281
|
+
insert: "\n"
|
|
1282
|
+
}
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1286
|
+
from,
|
|
1287
|
+
to
|
|
1288
|
+
});
|
|
1289
|
+
if (cursor) {
|
|
1290
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1291
|
+
if (id) {
|
|
1292
|
+
view.dispatch({
|
|
1293
|
+
effects: setSelection.of({
|
|
1294
|
+
current: id
|
|
1295
|
+
}),
|
|
1296
|
+
selection: {
|
|
1297
|
+
anchor: to
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
return true;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
return false;
|
|
1304
|
+
};
|
|
1273
1305
|
var comments = (options = {}) => {
|
|
1274
1306
|
const { key: shortcut = "meta-'" } = options;
|
|
1275
1307
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1276
|
-
const createCommentThread = (view) => {
|
|
1277
|
-
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1278
|
-
invariant2(options.onCreate, void 0, {
|
|
1279
|
-
F: __dxlog_file3,
|
|
1280
|
-
L: 264,
|
|
1281
|
-
S: void 0,
|
|
1282
|
-
A: [
|
|
1283
|
-
"options.onCreate",
|
|
1284
|
-
""
|
|
1285
|
-
]
|
|
1286
|
-
});
|
|
1287
|
-
const { from, to } = view.state.selection.main;
|
|
1288
|
-
if (from === to) {
|
|
1289
|
-
return false;
|
|
1290
|
-
}
|
|
1291
|
-
const cursor = Cursor.getCursorFromRange(cursorConverter3, {
|
|
1292
|
-
from,
|
|
1293
|
-
to
|
|
1294
|
-
});
|
|
1295
|
-
if (cursor) {
|
|
1296
|
-
const id = callbackWrapper(options.onCreate)(cursor, view.coordsAtPos(from));
|
|
1297
|
-
if (id) {
|
|
1298
|
-
view.dispatch({
|
|
1299
|
-
effects: setSelection.of({
|
|
1300
|
-
active: id
|
|
1301
|
-
}),
|
|
1302
|
-
selection: {
|
|
1303
|
-
anchor: from
|
|
1304
|
-
}
|
|
1305
|
-
});
|
|
1306
|
-
return true;
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
return false;
|
|
1310
|
-
};
|
|
1311
1308
|
return [
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1309
|
+
optionsFacet.of(options),
|
|
1310
|
+
commentsState,
|
|
1311
|
+
commentsDecorations,
|
|
1312
|
+
styles2,
|
|
1315
1313
|
//
|
|
1316
1314
|
// Keymap.
|
|
1317
1315
|
//
|
|
1318
1316
|
options.onCreate ? keymap3.of([
|
|
1319
1317
|
{
|
|
1320
1318
|
key: shortcut,
|
|
1321
|
-
run: callbackWrapper(
|
|
1319
|
+
run: callbackWrapper(createComment)
|
|
1322
1320
|
}
|
|
1323
1321
|
]) : [],
|
|
1324
1322
|
//
|
|
@@ -1352,351 +1350,111 @@ var comments = (options = {}) => {
|
|
|
1352
1350
|
hoverTime: 1e3
|
|
1353
1351
|
}) : [],
|
|
1354
1352
|
//
|
|
1355
|
-
//
|
|
1356
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1353
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1357
1354
|
//
|
|
1358
1355
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1359
|
-
|
|
1360
|
-
{
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
if (
|
|
1366
|
-
|
|
1367
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1368
|
-
options.onDelete?.(range.id);
|
|
1369
|
-
}
|
|
1356
|
+
let mod = false;
|
|
1357
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1358
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1359
|
+
comments2.forEach(({ comment, range }) => {
|
|
1360
|
+
if (from2 === to2) {
|
|
1361
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1362
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1363
|
+
options.onDelete?.(comment.id);
|
|
1370
1364
|
}
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
}
|
|
1365
|
+
}
|
|
1366
|
+
if (from <= range.to) {
|
|
1367
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1368
|
+
Object.assign(range, newRange);
|
|
1369
|
+
mod = true;
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
});
|
|
1373
|
+
if (mod) {
|
|
1374
|
+
view.dispatch({
|
|
1375
|
+
effects: setCommentState.of({
|
|
1376
|
+
comments: comments2,
|
|
1377
|
+
...value
|
|
1378
|
+
})
|
|
1377
1379
|
});
|
|
1378
|
-
if (mod) {
|
|
1379
|
-
view.dispatch({
|
|
1380
|
-
effects: setCommentState.of({
|
|
1381
|
-
active,
|
|
1382
|
-
ranges
|
|
1383
|
-
})
|
|
1384
|
-
});
|
|
1385
|
-
}
|
|
1386
1380
|
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1381
|
+
}),
|
|
1382
|
+
//
|
|
1383
|
+
// Track selection/proximity.
|
|
1384
|
+
//
|
|
1385
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1386
|
+
let min = Infinity;
|
|
1387
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1388
|
+
const { head } = state.selection.main;
|
|
1389
|
+
const selection = {};
|
|
1390
|
+
comments2.forEach(({ comment, range }) => {
|
|
1391
|
+
if (head >= range.from && head <= range.to) {
|
|
1392
|
+
selection.current = comment.id;
|
|
1393
|
+
selection.closest = void 0;
|
|
1394
|
+
}
|
|
1395
|
+
if (!selection.current) {
|
|
1396
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1400
1397
|
if (d < min) {
|
|
1401
|
-
|
|
1398
|
+
selection.closest = comment.id;
|
|
1402
1399
|
min = d;
|
|
1403
1400
|
}
|
|
1404
|
-
});
|
|
1405
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1406
|
-
view.dispatch({
|
|
1407
|
-
effects: setSelection.of(selected)
|
|
1408
|
-
});
|
|
1409
|
-
handleSelect({
|
|
1410
|
-
...selected,
|
|
1411
|
-
ranges: ranges.map((range) => ({
|
|
1412
|
-
...range,
|
|
1413
|
-
location: view.coordsAtPos(range.from)
|
|
1414
|
-
}))
|
|
1415
|
-
});
|
|
1416
1401
|
}
|
|
1402
|
+
});
|
|
1403
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1404
|
+
view.dispatch({
|
|
1405
|
+
effects: setSelection.of(selection)
|
|
1406
|
+
});
|
|
1407
|
+
handleSelect({
|
|
1408
|
+
selection,
|
|
1409
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1410
|
+
comment,
|
|
1411
|
+
range,
|
|
1412
|
+
location: view.coordsAtPos(range.from)
|
|
1413
|
+
}))
|
|
1414
|
+
});
|
|
1417
1415
|
}
|
|
1418
1416
|
}),
|
|
1419
1417
|
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1420
1418
|
];
|
|
1421
1419
|
};
|
|
1420
|
+
var useComments = (view, comments2 = []) => {
|
|
1421
|
+
useEffect(() => {
|
|
1422
|
+
if (view) {
|
|
1423
|
+
view.dispatch({
|
|
1424
|
+
effects: setComments.of(comments2)
|
|
1425
|
+
});
|
|
1426
|
+
}
|
|
1427
|
+
}, [
|
|
1428
|
+
view,
|
|
1429
|
+
comments2
|
|
1430
|
+
]);
|
|
1431
|
+
};
|
|
1422
1432
|
|
|
1423
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1424
|
-
import {
|
|
1425
|
-
var
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
this._pos = _pos;
|
|
1436
|
-
}
|
|
1437
|
-
eq(other) {
|
|
1438
|
-
return this._pos === other._pos;
|
|
1439
|
-
}
|
|
1440
|
-
toDOM(view) {
|
|
1441
|
-
const el = document.createElement("div");
|
|
1442
|
-
el.className = "cm-hr";
|
|
1443
|
-
return el;
|
|
1444
|
-
}
|
|
1445
|
-
};
|
|
1446
|
-
var placeholderMatcher = new MatchDecorator({
|
|
1447
|
-
// regexp: /(?<=\n\n)---/gs,
|
|
1448
|
-
regexp: /^---$/gs,
|
|
1449
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1450
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1451
|
-
})
|
|
1452
|
-
});
|
|
1453
|
-
var hr = () => [
|
|
1454
|
-
styles4,
|
|
1455
|
-
ViewPlugin4.fromClass(class {
|
|
1456
|
-
constructor(view) {
|
|
1457
|
-
this.rules = placeholderMatcher.createDeco(view);
|
|
1458
|
-
}
|
|
1459
|
-
update(update2) {
|
|
1460
|
-
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1461
|
-
}
|
|
1462
|
-
}, {
|
|
1463
|
-
decorations: (instance) => instance.rules
|
|
1464
|
-
})
|
|
1465
|
-
];
|
|
1466
|
-
|
|
1467
|
-
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1468
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1469
|
-
import { StateField as StateField3 } from "@codemirror/state";
|
|
1470
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1471
|
-
var image = (options = {}) => {
|
|
1472
|
-
return StateField3.define({
|
|
1473
|
-
create: (state) => {
|
|
1474
|
-
return Decoration5.set(buildDecorations(0, state.doc.length, state));
|
|
1475
|
-
},
|
|
1476
|
-
update: (value, tr) => {
|
|
1477
|
-
if (!tr.docChanged && !tr.selection) {
|
|
1478
|
-
return value;
|
|
1479
|
-
}
|
|
1480
|
-
const cursor = tr.state.selection.main.head;
|
|
1481
|
-
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1482
|
-
let from = Math.min(cursor, oldCursor);
|
|
1483
|
-
let to = Math.max(cursor, oldCursor);
|
|
1484
|
-
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1485
|
-
from = Math.min(from, fromB);
|
|
1486
|
-
to = Math.max(to, toB);
|
|
1487
|
-
});
|
|
1488
|
-
from = tr.state.doc.lineAt(from).from;
|
|
1489
|
-
to = tr.state.doc.lineAt(to).to;
|
|
1490
|
-
return value.map(tr.changes).update({
|
|
1491
|
-
filterFrom: from,
|
|
1492
|
-
filterTo: to,
|
|
1493
|
-
filter: () => false,
|
|
1494
|
-
add: buildDecorations(from, to, tr.state)
|
|
1495
|
-
});
|
|
1496
|
-
},
|
|
1497
|
-
provide: (field) => EditorView7.decorations.from(field)
|
|
1498
|
-
});
|
|
1499
|
-
};
|
|
1500
|
-
var buildDecorations = (from, to, state) => {
|
|
1501
|
-
const decorations = [];
|
|
1502
|
-
const cursor = state.selection.main.head;
|
|
1503
|
-
syntaxTree(state).iterate({
|
|
1504
|
-
enter: (node) => {
|
|
1505
|
-
if (node.name === "Image") {
|
|
1506
|
-
const urlNode = node.node.getChild("URL");
|
|
1507
|
-
if (urlNode) {
|
|
1508
|
-
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1509
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1510
|
-
decorations.push(Decoration5.replace({
|
|
1511
|
-
block: true,
|
|
1512
|
-
widget: new ImageWidget(url)
|
|
1513
|
-
}).range(hide ? node.from : node.to, node.to));
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
},
|
|
1517
|
-
from,
|
|
1518
|
-
to
|
|
1519
|
-
});
|
|
1520
|
-
return decorations;
|
|
1521
|
-
};
|
|
1522
|
-
var ImageWidget = class extends WidgetType3 {
|
|
1523
|
-
constructor(_url) {
|
|
1524
|
-
super();
|
|
1525
|
-
this._url = _url;
|
|
1526
|
-
}
|
|
1527
|
-
eq(other) {
|
|
1528
|
-
return this._url === other._url;
|
|
1529
|
-
}
|
|
1530
|
-
toDOM(view) {
|
|
1531
|
-
const img = document.createElement("img");
|
|
1532
|
-
img.setAttribute("src", this._url);
|
|
1533
|
-
img.setAttribute("class", "cm-image");
|
|
1534
|
-
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1535
|
-
return img;
|
|
1536
|
-
}
|
|
1537
|
-
};
|
|
1538
|
-
|
|
1539
|
-
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1540
|
-
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1541
|
-
import { RangeSetBuilder } from "@codemirror/state";
|
|
1542
|
-
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1543
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1544
|
-
var link = (options = {}) => {
|
|
1545
|
-
const extensions = [
|
|
1546
|
-
ViewPlugin5.fromClass(class {
|
|
1547
|
-
constructor(view) {
|
|
1548
|
-
this.decorations = buildDecorations2(view, options);
|
|
1549
|
-
}
|
|
1550
|
-
update(update2) {
|
|
1551
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1552
|
-
this.decorations = buildDecorations2(update2.view, options);
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
}, {
|
|
1556
|
-
decorations: (v) => v.decorations
|
|
1557
|
-
})
|
|
1558
|
-
];
|
|
1559
|
-
if (options.onHover) {
|
|
1560
|
-
extensions.push(
|
|
1561
|
-
// https://codemirror.net/examples/tooltip
|
|
1562
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1563
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1564
|
-
hoverTooltip2((view, pos, side) => {
|
|
1565
|
-
const syntax = syntaxTree2(view.state).resolveInner(pos, side);
|
|
1566
|
-
let link2 = null;
|
|
1567
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1568
|
-
link2 = node.name === "Link" ? node : null;
|
|
1569
|
-
}
|
|
1570
|
-
const url = link2 && link2.getChild("URL");
|
|
1571
|
-
if (!url || !link2) {
|
|
1572
|
-
return null;
|
|
1573
|
-
}
|
|
1574
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1575
|
-
return {
|
|
1576
|
-
pos: link2.from,
|
|
1577
|
-
end: link2.to,
|
|
1578
|
-
above: true,
|
|
1579
|
-
create: () => {
|
|
1580
|
-
const el = document.createElement("div");
|
|
1581
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1582
|
-
options.onHover(el, urlText);
|
|
1583
|
-
return {
|
|
1584
|
-
dom: el,
|
|
1585
|
-
offset: {
|
|
1586
|
-
x: 0,
|
|
1587
|
-
y: 4
|
|
1588
|
-
}
|
|
1589
|
-
};
|
|
1590
|
-
}
|
|
1591
|
-
};
|
|
1592
|
-
})
|
|
1593
|
-
);
|
|
1594
|
-
}
|
|
1595
|
-
return extensions;
|
|
1596
|
-
};
|
|
1597
|
-
var LinkButton = class extends WidgetType4 {
|
|
1598
|
-
constructor(_url, _onAttach) {
|
|
1599
|
-
super();
|
|
1600
|
-
this._url = _url;
|
|
1601
|
-
this._onAttach = _onAttach;
|
|
1602
|
-
}
|
|
1603
|
-
eq(other) {
|
|
1604
|
-
return this._url === other._url;
|
|
1605
|
-
}
|
|
1606
|
-
toDOM(view) {
|
|
1607
|
-
const el = document.createElement("span");
|
|
1608
|
-
this._onAttach(el, this._url);
|
|
1609
|
-
return el;
|
|
1610
|
-
}
|
|
1611
|
-
};
|
|
1612
|
-
var LinkText = class extends WidgetType4 {
|
|
1613
|
-
constructor(_text, _url) {
|
|
1614
|
-
super();
|
|
1615
|
-
this._text = _text;
|
|
1616
|
-
this._url = _url;
|
|
1617
|
-
}
|
|
1618
|
-
eq(other) {
|
|
1619
|
-
return this._url === other._url;
|
|
1620
|
-
}
|
|
1621
|
-
toDOM(view) {
|
|
1622
|
-
const link2 = document.createElement("a");
|
|
1623
|
-
link2.setAttribute("class", "cm-link");
|
|
1624
|
-
link2.textContent = this._text;
|
|
1625
|
-
if (this._url) {
|
|
1626
|
-
link2.setAttribute("rel", "noreferrer");
|
|
1627
|
-
link2.setAttribute("target", "_blank");
|
|
1628
|
-
link2.href = this._url;
|
|
1629
|
-
} else {
|
|
1630
|
-
link2.onclick = () => {
|
|
1631
|
-
view.dispatch({
|
|
1632
|
-
selection: {
|
|
1633
|
-
anchor: view.posAtDOM(link2)
|
|
1634
|
-
}
|
|
1635
|
-
});
|
|
1636
|
-
};
|
|
1637
|
-
}
|
|
1638
|
-
return link2;
|
|
1639
|
-
}
|
|
1640
|
-
};
|
|
1641
|
-
var buildDecorations2 = (view, options) => {
|
|
1642
|
-
const builder = new RangeSetBuilder();
|
|
1643
|
-
const { state } = view;
|
|
1644
|
-
const cursor = state.selection.main.head;
|
|
1645
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1646
|
-
syntaxTree2(state).iterate({
|
|
1647
|
-
enter: (node) => {
|
|
1648
|
-
if (node.name === "Link") {
|
|
1649
|
-
const marks2 = node.node.getChildren("LinkMark");
|
|
1650
|
-
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1651
|
-
const urlNode = node.node.getChild("URL");
|
|
1652
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1653
|
-
if (!url) {
|
|
1654
|
-
return false;
|
|
1655
|
-
}
|
|
1656
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1657
|
-
builder.add(node.from, node.to, Decoration6.replace({
|
|
1658
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
1659
|
-
}));
|
|
1660
|
-
}
|
|
1661
|
-
if (options.onRender) {
|
|
1662
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1663
|
-
widget: new LinkButton(url, options.onRender)
|
|
1664
|
-
}));
|
|
1665
|
-
}
|
|
1666
|
-
return false;
|
|
1667
|
-
}
|
|
1668
|
-
},
|
|
1669
|
-
from,
|
|
1670
|
-
to
|
|
1671
|
-
});
|
|
1672
|
-
}
|
|
1673
|
-
return builder.finish();
|
|
1674
|
-
};
|
|
1675
|
-
|
|
1676
|
-
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1677
|
-
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1678
|
-
var listener = ({ onFocus, onChange }) => {
|
|
1679
|
-
const extensions = [];
|
|
1680
|
-
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1681
|
-
onFocus(focused);
|
|
1682
|
-
return null;
|
|
1683
|
-
}));
|
|
1684
|
-
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1685
|
-
onChange(update2.state.doc.toString());
|
|
1686
|
-
}));
|
|
1687
|
-
return extensions;
|
|
1433
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1434
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1435
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1436
|
+
const extensions = [];
|
|
1437
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1438
|
+
onFocus(focused);
|
|
1439
|
+
return null;
|
|
1440
|
+
}));
|
|
1441
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1442
|
+
onChange(update2.state.doc.toString());
|
|
1443
|
+
}));
|
|
1444
|
+
return extensions;
|
|
1688
1445
|
};
|
|
1689
1446
|
|
|
1690
1447
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1691
1448
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1692
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1449
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1693
1450
|
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1694
1451
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1695
1452
|
import { languages } from "@codemirror/language-data";
|
|
1696
1453
|
import { searchKeymap } from "@codemirror/search";
|
|
1697
1454
|
import { EditorState } from "@codemirror/state";
|
|
1698
1455
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1699
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1456
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1457
|
+
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1700
1458
|
|
|
1701
1459
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1702
1460
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1793,7 +1551,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1793
1551
|
markdownTags.QuoteMark,
|
|
1794
1552
|
markdownTags.EmphasisMark
|
|
1795
1553
|
],
|
|
1796
|
-
class:
|
|
1554
|
+
class: mark
|
|
1797
1555
|
},
|
|
1798
1556
|
// E.g., code block language (after ```).
|
|
1799
1557
|
{
|
|
@@ -1801,7 +1559,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1801
1559
|
tags.function(tags.variableName),
|
|
1802
1560
|
tags.labelName
|
|
1803
1561
|
],
|
|
1804
|
-
class:
|
|
1562
|
+
class: codeMark
|
|
1805
1563
|
},
|
|
1806
1564
|
{
|
|
1807
1565
|
tag: [
|
|
@@ -1812,27 +1570,27 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1812
1570
|
// Headings.
|
|
1813
1571
|
{
|
|
1814
1572
|
tag: tags.heading1,
|
|
1815
|
-
class: heading(1
|
|
1573
|
+
class: heading(1)
|
|
1816
1574
|
},
|
|
1817
1575
|
{
|
|
1818
1576
|
tag: tags.heading2,
|
|
1819
|
-
class: heading(2
|
|
1577
|
+
class: heading(2)
|
|
1820
1578
|
},
|
|
1821
1579
|
{
|
|
1822
1580
|
tag: tags.heading3,
|
|
1823
|
-
class: heading(3
|
|
1581
|
+
class: heading(3)
|
|
1824
1582
|
},
|
|
1825
1583
|
{
|
|
1826
1584
|
tag: tags.heading4,
|
|
1827
|
-
class: heading(4
|
|
1585
|
+
class: heading(4)
|
|
1828
1586
|
},
|
|
1829
1587
|
{
|
|
1830
1588
|
tag: tags.heading5,
|
|
1831
|
-
class: heading(5
|
|
1589
|
+
class: heading(5)
|
|
1832
1590
|
},
|
|
1833
1591
|
{
|
|
1834
1592
|
tag: tags.heading6,
|
|
1835
|
-
class: heading(6
|
|
1593
|
+
class: heading(6)
|
|
1836
1594
|
},
|
|
1837
1595
|
// Emphasis.
|
|
1838
1596
|
{
|
|
@@ -1858,7 +1616,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1858
1616
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
1859
1617
|
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
1860
1618
|
// the code, but all other CSS properties will be inherited.
|
|
1861
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
1619
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
1862
1620
|
{
|
|
1863
1621
|
tag: [
|
|
1864
1622
|
markdownTags.CodeText,
|
|
@@ -1887,19 +1645,19 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1887
1645
|
};
|
|
1888
1646
|
|
|
1889
1647
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1890
|
-
var
|
|
1648
|
+
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
1891
1649
|
return [
|
|
1650
|
+
lineWrapping && EditorView7.lineWrapping,
|
|
1892
1651
|
EditorState.allowMultipleSelections.of(true),
|
|
1893
1652
|
EditorState.tabSize.of(2),
|
|
1894
|
-
|
|
1895
|
-
customKeymap(),
|
|
1653
|
+
// https://github.com/codemirror/basic-setup
|
|
1896
1654
|
bracketMatching2(),
|
|
1897
1655
|
closeBrackets2(),
|
|
1898
1656
|
crosshairCursor(),
|
|
1899
1657
|
dropCursor(),
|
|
1900
1658
|
drawSelection2(),
|
|
1901
|
-
|
|
1902
|
-
|
|
1659
|
+
highlightActiveLine2(),
|
|
1660
|
+
history2(),
|
|
1903
1661
|
indentOnInput(),
|
|
1904
1662
|
_placeholder && placeholder2(_placeholder),
|
|
1905
1663
|
// Main extension.
|
|
@@ -1923,76 +1681,620 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1923
1681
|
// https://github.com/codemirror/theme-one-dark
|
|
1924
1682
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1925
1683
|
// Custom styles.
|
|
1926
|
-
syntaxHighlighting2(markdownHighlightStyle(
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
]);
|
|
1941
|
-
|
|
1942
|
-
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1943
|
-
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1944
|
-
var mention = ({ onSearch }) => {
|
|
1945
|
-
return autocompletion2({
|
|
1946
|
-
closeOnBlur: false,
|
|
1947
|
-
override: [
|
|
1948
|
-
(context) => {
|
|
1949
|
-
const match = context.matchBefore(/@(\w+)?/);
|
|
1950
|
-
if (!match || match.from === match.to && !context.explicit) {
|
|
1951
|
-
return null;
|
|
1952
|
-
}
|
|
1953
|
-
console.log(match);
|
|
1954
|
-
return {
|
|
1955
|
-
from: match.from,
|
|
1956
|
-
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
1957
|
-
label: `@${value}`
|
|
1958
|
-
}))
|
|
1959
|
-
};
|
|
1960
|
-
}
|
|
1961
|
-
]
|
|
1962
|
-
});
|
|
1684
|
+
syntaxHighlighting2(markdownHighlightStyle()),
|
|
1685
|
+
keymap4.of([
|
|
1686
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1687
|
+
indentWithTab,
|
|
1688
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1689
|
+
...closeBracketsKeymap,
|
|
1690
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1691
|
+
...historyKeymap,
|
|
1692
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1693
|
+
...searchKeymap,
|
|
1694
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1695
|
+
...standardKeymap
|
|
1696
|
+
])
|
|
1697
|
+
].filter(isNotFalsy2);
|
|
1963
1698
|
};
|
|
1964
1699
|
|
|
1965
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1966
|
-
import { syntaxTree
|
|
1967
|
-
import { RangeSetBuilder
|
|
1968
|
-
import {
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1700
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1701
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1702
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1703
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1704
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1705
|
+
var styles3 = EditorView8.baseTheme({
|
|
1706
|
+
"& .cm-code": {
|
|
1707
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1708
|
+
},
|
|
1709
|
+
"& .cm-codeblock": {
|
|
1710
|
+
width: "100%",
|
|
1711
|
+
paddingInline: "1rem !important",
|
|
1712
|
+
position: "relative",
|
|
1713
|
+
"&::after": {
|
|
1714
|
+
content: '""',
|
|
1715
|
+
position: "absolute",
|
|
1716
|
+
inset: 0
|
|
1717
|
+
}
|
|
1718
|
+
},
|
|
1719
|
+
"&light .cm-codeblock": {
|
|
1720
|
+
"&::after": {
|
|
1721
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
1722
|
+
mixBlendMode: "darken"
|
|
1723
|
+
}
|
|
1724
|
+
},
|
|
1725
|
+
"&dark .cm-codeblock": {
|
|
1726
|
+
"&::after": {
|
|
1727
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
1728
|
+
mixBlendMode: "lighten"
|
|
1729
|
+
}
|
|
1730
|
+
},
|
|
1731
|
+
"& .cm-codeblock-first": {
|
|
1732
|
+
display: "inline-block",
|
|
1733
|
+
"&::after": {
|
|
1734
|
+
borderTopLeftRadius: ".5rem",
|
|
1735
|
+
borderTopRightRadius: ".5rem"
|
|
1736
|
+
}
|
|
1737
|
+
},
|
|
1738
|
+
"& .cm-codeblock-last": {
|
|
1739
|
+
display: "inline-block",
|
|
1740
|
+
"&::after": {
|
|
1741
|
+
borderBottomLeftRadius: ".5rem",
|
|
1742
|
+
borderBottomRightRadius: ".5rem"
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
var getLineRange = (lines, from, to) => {
|
|
1747
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1748
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1749
|
+
return [
|
|
1750
|
+
start,
|
|
1751
|
+
end
|
|
1752
|
+
];
|
|
1975
1753
|
};
|
|
1976
|
-
var
|
|
1977
|
-
|
|
1754
|
+
var LineWidget = class extends WidgetType2 {
|
|
1755
|
+
constructor(_className) {
|
|
1756
|
+
super();
|
|
1757
|
+
this._className = _className;
|
|
1758
|
+
}
|
|
1759
|
+
toDOM() {
|
|
1760
|
+
const el = document.createElement("span");
|
|
1761
|
+
el.innerHTML = " ";
|
|
1762
|
+
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1763
|
+
return el;
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
var top = new LineWidget("cm-codeblock-first");
|
|
1767
|
+
var bottom = new LineWidget("cm-codeblock-last");
|
|
1768
|
+
var buildDecorations = (view) => {
|
|
1769
|
+
const builder = new RangeSetBuilder();
|
|
1770
|
+
const { state } = view;
|
|
1771
|
+
const blocks = view.viewportLineBlocks;
|
|
1978
1772
|
const cursor = state.selection.main.head;
|
|
1979
|
-
const
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1773
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1774
|
+
syntaxTree(state).iterate({
|
|
1775
|
+
enter: (node) => {
|
|
1776
|
+
if (node.name === "FencedCode") {
|
|
1777
|
+
const edit = !view.state.readOnly && cursor >= node.from && cursor <= node.to;
|
|
1778
|
+
const range = getLineRange(blocks, node.from, node.to);
|
|
1779
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1780
|
+
const block = blocks[i];
|
|
1781
|
+
if (!edit && (i === range[0] || i === range[1])) {
|
|
1782
|
+
builder.add(block.from, block.to, Decoration3.replace({
|
|
1783
|
+
widget: i === range[0] ? top : bottom
|
|
1784
|
+
}));
|
|
1785
|
+
} else {
|
|
1786
|
+
builder.add(block.from, block.from, Decoration3.line({
|
|
1787
|
+
class: mx2("cm-code cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1788
|
+
}));
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1994
1791
|
}
|
|
1995
|
-
|
|
1792
|
+
},
|
|
1793
|
+
from,
|
|
1794
|
+
to
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
return builder.finish();
|
|
1798
|
+
};
|
|
1799
|
+
var code2 = () => {
|
|
1800
|
+
return [
|
|
1801
|
+
ViewPlugin3.fromClass(class {
|
|
1802
|
+
constructor(view) {
|
|
1803
|
+
this.decorations = buildDecorations(view);
|
|
1804
|
+
}
|
|
1805
|
+
update(update2) {
|
|
1806
|
+
this.decorations = buildDecorations(update2.view);
|
|
1807
|
+
}
|
|
1808
|
+
}, {
|
|
1809
|
+
decorations: (value) => value.decorations
|
|
1810
|
+
}),
|
|
1811
|
+
styles3
|
|
1812
|
+
];
|
|
1813
|
+
};
|
|
1814
|
+
|
|
1815
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1816
|
+
import { snippet } from "@codemirror/autocomplete";
|
|
1817
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1818
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1819
|
+
import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1820
|
+
var setHeading = (level) => (view) => {
|
|
1821
|
+
const { selection: { ranges }, doc } = view.state;
|
|
1822
|
+
const changes = [];
|
|
1823
|
+
for (const range of ranges) {
|
|
1824
|
+
const { number } = doc.lineAt(range.anchor);
|
|
1825
|
+
const { from, to } = doc.line(number);
|
|
1826
|
+
const line = doc.sliceString(from, to);
|
|
1827
|
+
const [_, marks, spaces] = line.match(/(#+)(\s+)/) ?? [];
|
|
1828
|
+
const current = marks?.length ?? 0;
|
|
1829
|
+
if (level !== current) {
|
|
1830
|
+
changes.push({
|
|
1831
|
+
from,
|
|
1832
|
+
to: from + current + (spaces?.length ?? 0),
|
|
1833
|
+
insert: "#".repeat(level) + (level > 0 ? " " : "")
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
if (changes.length) {
|
|
1838
|
+
view.dispatch({
|
|
1839
|
+
changes
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
return true;
|
|
1843
|
+
};
|
|
1844
|
+
var toggleStyle = (mark2) => (view) => {
|
|
1845
|
+
const { ranges } = view.state.selection;
|
|
1846
|
+
for (const range of ranges) {
|
|
1847
|
+
if (range.from === range.to) {
|
|
1848
|
+
return false;
|
|
1849
|
+
}
|
|
1850
|
+
view.dispatch({
|
|
1851
|
+
changes: [
|
|
1852
|
+
{
|
|
1853
|
+
from: range.from,
|
|
1854
|
+
insert: mark2
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
from: range.to,
|
|
1858
|
+
insert: mark2
|
|
1859
|
+
}
|
|
1860
|
+
]
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
return true;
|
|
1864
|
+
};
|
|
1865
|
+
var snippets = {
|
|
1866
|
+
codeblock: snippet([
|
|
1867
|
+
"```#{lang}",
|
|
1868
|
+
" #{}",
|
|
1869
|
+
"```"
|
|
1870
|
+
].join("\n")),
|
|
1871
|
+
table: snippet([
|
|
1872
|
+
"| #{col1} | #{col2} |",
|
|
1873
|
+
"| ---- | ---- |",
|
|
1874
|
+
"| #{val1} | #{val2} |",
|
|
1875
|
+
"| #{val3} | #{val4} |"
|
|
1876
|
+
].join("\n"))
|
|
1877
|
+
};
|
|
1878
|
+
var insertCodeblock = (view) => {
|
|
1879
|
+
const { selection: { main }, doc } = view.state;
|
|
1880
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1881
|
+
const { from } = doc.line(number);
|
|
1882
|
+
snippets.codeblock(view, null, from, from);
|
|
1883
|
+
};
|
|
1884
|
+
var insertTable = (view) => {
|
|
1885
|
+
const { selection: { main }, doc } = view.state;
|
|
1886
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1887
|
+
const { from } = doc.line(number);
|
|
1888
|
+
snippets.table(view, null, from, from);
|
|
1889
|
+
};
|
|
1890
|
+
var toggleBold = toggleStyle("**");
|
|
1891
|
+
var toggleItalic = toggleStyle("_");
|
|
1892
|
+
var toggleStrikethrough = toggleStyle("~~");
|
|
1893
|
+
var toggleList = (view) => {
|
|
1894
|
+
};
|
|
1895
|
+
var formatting = (options = {}) => {
|
|
1896
|
+
return [
|
|
1897
|
+
keymap5.of([
|
|
1898
|
+
{
|
|
1899
|
+
key: "meta-b",
|
|
1900
|
+
run: toggleBold
|
|
1901
|
+
}
|
|
1902
|
+
]),
|
|
1903
|
+
styling()
|
|
1904
|
+
];
|
|
1905
|
+
};
|
|
1906
|
+
var styling = () => {
|
|
1907
|
+
const buildDecorations7 = (view) => {
|
|
1908
|
+
const builder = new RangeSetBuilder2();
|
|
1909
|
+
const { state } = view;
|
|
1910
|
+
const cursor = state.selection.main.head;
|
|
1911
|
+
const replace = (node, marks) => {
|
|
1912
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1913
|
+
for (const mark2 of marks) {
|
|
1914
|
+
builder.add(mark2.from, mark2.to, Decoration4.replace({}));
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
};
|
|
1918
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1919
|
+
syntaxTree2(state).iterate({
|
|
1920
|
+
enter: (node) => {
|
|
1921
|
+
switch (node.name) {
|
|
1922
|
+
case "Emphasis":
|
|
1923
|
+
case "StrongEmphasis": {
|
|
1924
|
+
const marks = node.node.getChildren("EmphasisMark");
|
|
1925
|
+
replace(node, marks);
|
|
1926
|
+
break;
|
|
1927
|
+
}
|
|
1928
|
+
case "Strikethrough": {
|
|
1929
|
+
const marks = node.node.getChildren("StrikethroughMark");
|
|
1930
|
+
replace(node, marks);
|
|
1931
|
+
break;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
},
|
|
1935
|
+
from,
|
|
1936
|
+
to
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
return builder.finish();
|
|
1940
|
+
};
|
|
1941
|
+
return [
|
|
1942
|
+
ViewPlugin4.fromClass(class {
|
|
1943
|
+
constructor(view) {
|
|
1944
|
+
this.decorations = buildDecorations7(view);
|
|
1945
|
+
}
|
|
1946
|
+
update(update2) {
|
|
1947
|
+
this.decorations = buildDecorations7(update2.view);
|
|
1948
|
+
}
|
|
1949
|
+
}, {
|
|
1950
|
+
decorations: (value) => value.decorations
|
|
1951
|
+
})
|
|
1952
|
+
];
|
|
1953
|
+
};
|
|
1954
|
+
|
|
1955
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1956
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1957
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1958
|
+
import { Decoration as Decoration5, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1959
|
+
var buildDecorations2 = (view) => {
|
|
1960
|
+
const builder = new RangeSetBuilder3();
|
|
1961
|
+
const { state } = view;
|
|
1962
|
+
const cursor = state.selection.main.head;
|
|
1963
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1964
|
+
syntaxTree3(state).iterate({
|
|
1965
|
+
enter: (node) => {
|
|
1966
|
+
switch (node.name) {
|
|
1967
|
+
case "ATXHeading1":
|
|
1968
|
+
case "ATXHeading2":
|
|
1969
|
+
case "ATXHeading3":
|
|
1970
|
+
case "ATXHeading4":
|
|
1971
|
+
case "ATXHeading5":
|
|
1972
|
+
case "ATXHeading6": {
|
|
1973
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1974
|
+
if (mark2) {
|
|
1975
|
+
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1976
|
+
builder.add(mark2.from, mark2.to + 1, Decoration5.replace({}));
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
},
|
|
1982
|
+
from,
|
|
1983
|
+
to
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
return builder.finish();
|
|
1987
|
+
};
|
|
1988
|
+
var heading2 = () => {
|
|
1989
|
+
return [
|
|
1990
|
+
ViewPlugin5.fromClass(class {
|
|
1991
|
+
constructor(view) {
|
|
1992
|
+
this.decorations = buildDecorations2(view);
|
|
1993
|
+
}
|
|
1994
|
+
update(update2) {
|
|
1995
|
+
this.decorations = buildDecorations2(update2.view);
|
|
1996
|
+
}
|
|
1997
|
+
}, {
|
|
1998
|
+
decorations: (value) => value.decorations
|
|
1999
|
+
})
|
|
2000
|
+
];
|
|
2001
|
+
};
|
|
2002
|
+
|
|
2003
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
2004
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2005
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2006
|
+
import { Decoration as Decoration6, EditorView as EditorView9, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
2007
|
+
var styles4 = EditorView9.baseTheme({
|
|
2008
|
+
"& .cm-hr": {
|
|
2009
|
+
// Note that block-level decorations should not have vertical margins,
|
|
2010
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2014
|
+
toDOM() {
|
|
2015
|
+
const el = document.createElement("div");
|
|
2016
|
+
el.className = "cm-hr";
|
|
2017
|
+
return el;
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
var decoration = Decoration6.replace({
|
|
2021
|
+
widget: new HorizontalRuleWidget()
|
|
2022
|
+
});
|
|
2023
|
+
var buildDecorations3 = (view) => {
|
|
2024
|
+
const builder = new RangeSetBuilder4();
|
|
2025
|
+
const { state } = view;
|
|
2026
|
+
const cursor = state.selection.main.head;
|
|
2027
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2028
|
+
syntaxTree4(state).iterate({
|
|
2029
|
+
enter: (node) => {
|
|
2030
|
+
if (node.name === "HorizontalRule") {
|
|
2031
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
2032
|
+
builder.add(node.from, node.to, decoration);
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
},
|
|
2036
|
+
from,
|
|
2037
|
+
to
|
|
2038
|
+
});
|
|
2039
|
+
}
|
|
2040
|
+
return builder.finish();
|
|
2041
|
+
};
|
|
2042
|
+
var hr = () => {
|
|
2043
|
+
return [
|
|
2044
|
+
ViewPlugin6.fromClass(class {
|
|
2045
|
+
constructor(view) {
|
|
2046
|
+
this.decorations = buildDecorations3(view);
|
|
2047
|
+
}
|
|
2048
|
+
update(update2) {
|
|
2049
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2050
|
+
}
|
|
2051
|
+
}, {
|
|
2052
|
+
decorations: (value) => value.decorations
|
|
2053
|
+
}),
|
|
2054
|
+
styles4
|
|
2055
|
+
];
|
|
2056
|
+
};
|
|
2057
|
+
|
|
2058
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
2059
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2060
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
2061
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
2062
|
+
var image = (options = {}) => {
|
|
2063
|
+
return StateField3.define({
|
|
2064
|
+
create: (state) => {
|
|
2065
|
+
return Decoration7.set(buildDecorations4(0, state.doc.length, state));
|
|
2066
|
+
},
|
|
2067
|
+
update: (value, tr) => {
|
|
2068
|
+
if (!tr.docChanged && !tr.selection) {
|
|
2069
|
+
return value;
|
|
2070
|
+
}
|
|
2071
|
+
const cursor = tr.state.selection.main.head;
|
|
2072
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
2073
|
+
let from = Math.min(cursor, oldCursor);
|
|
2074
|
+
let to = Math.max(cursor, oldCursor);
|
|
2075
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
2076
|
+
from = Math.min(from, fromB);
|
|
2077
|
+
to = Math.max(to, toB);
|
|
2078
|
+
});
|
|
2079
|
+
from = tr.state.doc.lineAt(from).from;
|
|
2080
|
+
to = tr.state.doc.lineAt(to).to;
|
|
2081
|
+
return value.map(tr.changes).update({
|
|
2082
|
+
filterFrom: from,
|
|
2083
|
+
filterTo: to,
|
|
2084
|
+
filter: () => false,
|
|
2085
|
+
add: buildDecorations4(from, to, tr.state)
|
|
2086
|
+
});
|
|
2087
|
+
},
|
|
2088
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
2089
|
+
});
|
|
2090
|
+
};
|
|
2091
|
+
var buildDecorations4 = (from, to, state) => {
|
|
2092
|
+
const decorations = [];
|
|
2093
|
+
const cursor = state.selection.main.head;
|
|
2094
|
+
syntaxTree5(state).iterate({
|
|
2095
|
+
enter: (node) => {
|
|
2096
|
+
if (node.name === "Image") {
|
|
2097
|
+
const urlNode = node.node.getChild("URL");
|
|
2098
|
+
if (urlNode) {
|
|
2099
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
2100
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
2101
|
+
decorations.push(Decoration7.replace({
|
|
2102
|
+
block: true,
|
|
2103
|
+
widget: new ImageWidget(url)
|
|
2104
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
},
|
|
2108
|
+
from,
|
|
2109
|
+
to
|
|
2110
|
+
});
|
|
2111
|
+
return decorations;
|
|
2112
|
+
};
|
|
2113
|
+
var ImageWidget = class extends WidgetType4 {
|
|
2114
|
+
constructor(_url) {
|
|
2115
|
+
super();
|
|
2116
|
+
this._url = _url;
|
|
2117
|
+
}
|
|
2118
|
+
eq(other) {
|
|
2119
|
+
return this._url === other._url;
|
|
2120
|
+
}
|
|
2121
|
+
toDOM(view) {
|
|
2122
|
+
const img = document.createElement("img");
|
|
2123
|
+
img.setAttribute("src", this._url);
|
|
2124
|
+
img.setAttribute("class", "cm-image");
|
|
2125
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
2126
|
+
return img;
|
|
2127
|
+
}
|
|
2128
|
+
};
|
|
2129
|
+
|
|
2130
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
2131
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2132
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2133
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration8, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
2134
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
2135
|
+
var link = (options = {}) => {
|
|
2136
|
+
const extensions = [
|
|
2137
|
+
ViewPlugin7.fromClass(class {
|
|
2138
|
+
constructor(view) {
|
|
2139
|
+
this.decorations = buildDecorations5(view, options);
|
|
2140
|
+
}
|
|
2141
|
+
update(update2) {
|
|
2142
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2143
|
+
this.decorations = buildDecorations5(update2.view, options);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
}, {
|
|
2147
|
+
decorations: (value) => value.decorations
|
|
2148
|
+
})
|
|
2149
|
+
];
|
|
2150
|
+
if (options.onHover) {
|
|
2151
|
+
extensions.push(
|
|
2152
|
+
// https://codemirror.net/examples/tooltip
|
|
2153
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
2154
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
2155
|
+
hoverTooltip2((view, pos, side) => {
|
|
2156
|
+
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
2157
|
+
let link2 = null;
|
|
2158
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
2159
|
+
link2 = node.name === "Link" ? node : null;
|
|
2160
|
+
}
|
|
2161
|
+
const url = link2 && link2.getChild("URL");
|
|
2162
|
+
if (!url || !link2) {
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
2166
|
+
return {
|
|
2167
|
+
pos: link2.from,
|
|
2168
|
+
end: link2.to,
|
|
2169
|
+
above: true,
|
|
2170
|
+
create: () => {
|
|
2171
|
+
const el = document.createElement("div");
|
|
2172
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
2173
|
+
options.onHover(el, urlText);
|
|
2174
|
+
return {
|
|
2175
|
+
dom: el,
|
|
2176
|
+
offset: {
|
|
2177
|
+
x: 0,
|
|
2178
|
+
y: 4
|
|
2179
|
+
}
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2182
|
+
};
|
|
2183
|
+
})
|
|
2184
|
+
);
|
|
2185
|
+
}
|
|
2186
|
+
return extensions;
|
|
2187
|
+
};
|
|
2188
|
+
var LinkButton = class extends WidgetType5 {
|
|
2189
|
+
constructor(_url, _onAttach) {
|
|
2190
|
+
super();
|
|
2191
|
+
this._url = _url;
|
|
2192
|
+
this._onAttach = _onAttach;
|
|
2193
|
+
}
|
|
2194
|
+
eq(other) {
|
|
2195
|
+
return this._url === other._url;
|
|
2196
|
+
}
|
|
2197
|
+
toDOM(view) {
|
|
2198
|
+
const el = document.createElement("span");
|
|
2199
|
+
this._onAttach(el, this._url);
|
|
2200
|
+
return el;
|
|
2201
|
+
}
|
|
2202
|
+
};
|
|
2203
|
+
var LinkText = class extends WidgetType5 {
|
|
2204
|
+
constructor(_text, _url) {
|
|
2205
|
+
super();
|
|
2206
|
+
this._text = _text;
|
|
2207
|
+
this._url = _url;
|
|
2208
|
+
}
|
|
2209
|
+
eq(other) {
|
|
2210
|
+
return this._url === other._url;
|
|
2211
|
+
}
|
|
2212
|
+
toDOM(view) {
|
|
2213
|
+
const link2 = document.createElement("a");
|
|
2214
|
+
link2.setAttribute("class", "cm-link");
|
|
2215
|
+
link2.textContent = this._text;
|
|
2216
|
+
if (this._url) {
|
|
2217
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2218
|
+
link2.setAttribute("target", "_blank");
|
|
2219
|
+
link2.href = this._url;
|
|
2220
|
+
} else {
|
|
2221
|
+
link2.onclick = () => {
|
|
2222
|
+
view.dispatch({
|
|
2223
|
+
selection: {
|
|
2224
|
+
anchor: view.posAtDOM(link2)
|
|
2225
|
+
}
|
|
2226
|
+
});
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
return link2;
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
var buildDecorations5 = (view, options) => {
|
|
2233
|
+
const builder = new RangeSetBuilder5();
|
|
2234
|
+
const { state } = view;
|
|
2235
|
+
const cursor = state.selection.main.head;
|
|
2236
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2237
|
+
syntaxTree6(state).iterate({
|
|
2238
|
+
enter: (node) => {
|
|
2239
|
+
if (node.name === "Link") {
|
|
2240
|
+
const marks = node.node.getChildren("LinkMark");
|
|
2241
|
+
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
2242
|
+
const urlNode = node.node.getChild("URL");
|
|
2243
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2244
|
+
if (!url) {
|
|
2245
|
+
return false;
|
|
2246
|
+
}
|
|
2247
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2248
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
|
2249
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2250
|
+
}));
|
|
2251
|
+
}
|
|
2252
|
+
if (options.onRender) {
|
|
2253
|
+
builder.add(node.to, node.to, Decoration8.replace({
|
|
2254
|
+
widget: new LinkButton(url, options.onRender)
|
|
2255
|
+
}));
|
|
2256
|
+
}
|
|
2257
|
+
return false;
|
|
2258
|
+
}
|
|
2259
|
+
},
|
|
2260
|
+
from,
|
|
2261
|
+
to
|
|
2262
|
+
});
|
|
2263
|
+
}
|
|
2264
|
+
return builder.finish();
|
|
2265
|
+
};
|
|
2266
|
+
|
|
2267
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2268
|
+
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
2269
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
2270
|
+
import { Decoration as Decoration9, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
2271
|
+
var table = (options = {}) => {
|
|
2272
|
+
return StateField4.define({
|
|
2273
|
+
create: (state) => update(state, options),
|
|
2274
|
+
update: (_, tr) => update(tr.state, options),
|
|
2275
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
2276
|
+
});
|
|
2277
|
+
};
|
|
2278
|
+
var update = (state, options) => {
|
|
2279
|
+
const builder = new RangeSetBuilder6();
|
|
2280
|
+
const cursor = state.selection.main.head;
|
|
2281
|
+
const tables = [];
|
|
2282
|
+
const getTable = () => tables[tables.length - 1];
|
|
2283
|
+
const getRow = () => {
|
|
2284
|
+
const table2 = getTable();
|
|
2285
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
2286
|
+
};
|
|
2287
|
+
syntaxTree7(state).iterate({
|
|
2288
|
+
enter: (node) => {
|
|
2289
|
+
switch (node.name) {
|
|
2290
|
+
case "Table": {
|
|
2291
|
+
tables.push({
|
|
2292
|
+
from: node.from,
|
|
2293
|
+
to: node.to
|
|
2294
|
+
});
|
|
2295
|
+
break;
|
|
2296
|
+
}
|
|
2297
|
+
case "TableHeader": {
|
|
1996
2298
|
getTable().header = [];
|
|
1997
2299
|
break;
|
|
1998
2300
|
}
|
|
@@ -2014,16 +2316,16 @@ var update = (state, options) => {
|
|
|
2014
2316
|
});
|
|
2015
2317
|
tables.forEach((table2) => {
|
|
2016
2318
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2017
|
-
hide && builder.add(table2.from, table2.to,
|
|
2319
|
+
hide && builder.add(table2.from, table2.to, Decoration9.replace({
|
|
2018
2320
|
widget: new TableWidget(table2)
|
|
2019
2321
|
}));
|
|
2020
|
-
builder.add(table2.from, table2.to,
|
|
2322
|
+
builder.add(table2.from, table2.to, Decoration9.mark({
|
|
2021
2323
|
class: "cm-table"
|
|
2022
2324
|
}));
|
|
2023
2325
|
});
|
|
2024
2326
|
return builder.finish();
|
|
2025
2327
|
};
|
|
2026
|
-
var TableWidget = class extends
|
|
2328
|
+
var TableWidget = class extends WidgetType6 {
|
|
2027
2329
|
constructor(_table) {
|
|
2028
2330
|
super();
|
|
2029
2331
|
this._table = _table;
|
|
@@ -2060,11 +2362,20 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2060
2362
|
}
|
|
2061
2363
|
};
|
|
2062
2364
|
|
|
2063
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2064
|
-
import { syntaxTree as
|
|
2065
|
-
import { RangeSetBuilder as
|
|
2066
|
-
import { EditorView as
|
|
2067
|
-
var
|
|
2365
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2366
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
2367
|
+
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
2368
|
+
import { EditorView as EditorView12, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
2369
|
+
var styles5 = EditorView12.baseTheme({
|
|
2370
|
+
"& .cm-task": {
|
|
2371
|
+
color: getToken("extend.colors.blue.500")
|
|
2372
|
+
},
|
|
2373
|
+
"& .cm-task-checkbox": {
|
|
2374
|
+
marginLeft: "4px",
|
|
2375
|
+
marginRight: "4px"
|
|
2376
|
+
}
|
|
2377
|
+
});
|
|
2378
|
+
var CheckboxWidget = class extends WidgetType7 {
|
|
2068
2379
|
constructor(_checked) {
|
|
2069
2380
|
super();
|
|
2070
2381
|
this._checked = _checked;
|
|
@@ -2074,6 +2385,7 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2074
2385
|
}
|
|
2075
2386
|
toDOM(view) {
|
|
2076
2387
|
const input = document.createElement("input");
|
|
2388
|
+
input.className = "cm-task-checkbox";
|
|
2077
2389
|
input.type = "checkbox";
|
|
2078
2390
|
input.checked = this._checked;
|
|
2079
2391
|
if (view.state.readOnly) {
|
|
@@ -2100,40 +2412,27 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2100
2412
|
return false;
|
|
2101
2413
|
}
|
|
2102
2414
|
};
|
|
2103
|
-
var
|
|
2415
|
+
var checkedDecoration = Decoration10.replace({
|
|
2104
2416
|
widget: new CheckboxWidget(true)
|
|
2105
2417
|
});
|
|
2106
|
-
var
|
|
2418
|
+
var uncheckedDecoration = Decoration10.replace({
|
|
2107
2419
|
widget: new CheckboxWidget(false)
|
|
2108
2420
|
});
|
|
2109
|
-
var
|
|
2110
|
-
|
|
2111
|
-
constructor(view) {
|
|
2112
|
-
this.decorations = buildDecorations3(view);
|
|
2113
|
-
}
|
|
2114
|
-
update(update2) {
|
|
2115
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2116
|
-
this.decorations = buildDecorations3(update2.view);
|
|
2117
|
-
}
|
|
2118
|
-
}
|
|
2119
|
-
}, {
|
|
2120
|
-
decorations: (v) => v.decorations,
|
|
2121
|
-
// TODO(burdon): Is this still required?
|
|
2122
|
-
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2123
|
-
return view.plugin(plugin)?.decorations || Decoration8.none;
|
|
2124
|
-
})
|
|
2125
|
-
});
|
|
2126
|
-
};
|
|
2127
|
-
var buildDecorations3 = (view) => {
|
|
2128
|
-
const builder = new RangeSetBuilder3();
|
|
2421
|
+
var buildDecorations6 = (view) => {
|
|
2422
|
+
const builder = new RangeSetBuilder7();
|
|
2129
2423
|
const { state } = view;
|
|
2130
2424
|
const cursor = state.selection.main.head;
|
|
2131
2425
|
for (const { from, to } of view.visibleRanges) {
|
|
2132
|
-
|
|
2426
|
+
syntaxTree8(state).iterate({
|
|
2133
2427
|
enter: (node) => {
|
|
2134
|
-
if (node.name === "TaskMarker"
|
|
2135
|
-
|
|
2136
|
-
|
|
2428
|
+
if (node.name === "TaskMarker") {
|
|
2429
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2430
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2431
|
+
builder.add(node.from - 2, node.from - 1, Decoration10.mark({
|
|
2432
|
+
class: "cm-task"
|
|
2433
|
+
}));
|
|
2434
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2435
|
+
}
|
|
2137
2436
|
}
|
|
2138
2437
|
},
|
|
2139
2438
|
from,
|
|
@@ -2142,9 +2441,60 @@ var buildDecorations3 = (view) => {
|
|
|
2142
2441
|
}
|
|
2143
2442
|
return builder.finish();
|
|
2144
2443
|
};
|
|
2444
|
+
var tasklist = (options = {}) => {
|
|
2445
|
+
return [
|
|
2446
|
+
ViewPlugin8.fromClass(class {
|
|
2447
|
+
constructor(view) {
|
|
2448
|
+
this.decorations = buildDecorations6(view);
|
|
2449
|
+
}
|
|
2450
|
+
update(update2) {
|
|
2451
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2452
|
+
this.decorations = buildDecorations6(update2.view);
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
}, {
|
|
2456
|
+
decorations: (value) => value.decorations
|
|
2457
|
+
}),
|
|
2458
|
+
styles5
|
|
2459
|
+
];
|
|
2460
|
+
};
|
|
2461
|
+
|
|
2462
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2463
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2464
|
+
var mention = ({ onSearch }) => {
|
|
2465
|
+
return autocompletion2({
|
|
2466
|
+
// TODO(burdon): Not working.
|
|
2467
|
+
activateOnTyping: true,
|
|
2468
|
+
// activateOnTypingDelay: 100,
|
|
2469
|
+
// selectOnOpen: true,
|
|
2470
|
+
closeOnBlur: false,
|
|
2471
|
+
// defaultKeymap: false,
|
|
2472
|
+
icons: false,
|
|
2473
|
+
override: [
|
|
2474
|
+
(context) => {
|
|
2475
|
+
console.log(context);
|
|
2476
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2477
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2478
|
+
return null;
|
|
2479
|
+
}
|
|
2480
|
+
return {
|
|
2481
|
+
from: match.from,
|
|
2482
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2483
|
+
label: `@${value}`
|
|
2484
|
+
}))
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
]
|
|
2488
|
+
});
|
|
2489
|
+
};
|
|
2490
|
+
|
|
2491
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2492
|
+
var outliner = (options = {}) => {
|
|
2493
|
+
return [];
|
|
2494
|
+
};
|
|
2145
2495
|
|
|
2146
2496
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2147
|
-
import { keymap as
|
|
2497
|
+
import { keymap as keymap6 } from "@codemirror/view";
|
|
2148
2498
|
var defaultItems = [
|
|
2149
2499
|
"hello world!",
|
|
2150
2500
|
"this is a test.",
|
|
@@ -2154,7 +2504,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2154
2504
|
let t;
|
|
2155
2505
|
let idx = 0;
|
|
2156
2506
|
return [
|
|
2157
|
-
|
|
2507
|
+
keymap6.of([
|
|
2158
2508
|
{
|
|
2159
2509
|
// Reset.
|
|
2160
2510
|
key: "alt-meta-'",
|
|
@@ -2200,27 +2550,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2200
2550
|
];
|
|
2201
2551
|
};
|
|
2202
2552
|
|
|
2203
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2204
|
-
import { yCollab } from "y-codemirror.next";
|
|
2205
|
-
|
|
2206
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2207
|
-
import * as Y from "yjs";
|
|
2208
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2209
|
-
var cursorConverter2 = (text) => ({
|
|
2210
|
-
toCursor: (index, assoc) => {
|
|
2211
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2212
|
-
},
|
|
2213
|
-
fromCursor: (cursor) => {
|
|
2214
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2215
|
-
}
|
|
2216
|
-
});
|
|
2217
|
-
|
|
2218
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2219
|
-
var yjs = (content, awareness2) => [
|
|
2220
|
-
Cursor.converter.of(cursorConverter2(content)),
|
|
2221
|
-
yCollab(content, awareness2)
|
|
2222
|
-
];
|
|
2223
|
-
|
|
2224
2553
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2225
2554
|
import get3 from "lodash.get";
|
|
2226
2555
|
var defaultTheme = {
|
|
@@ -2252,8 +2581,9 @@ var defaultTheme = {
|
|
|
2252
2581
|
outline: "none"
|
|
2253
2582
|
},
|
|
2254
2583
|
".cm-scroller": {
|
|
2255
|
-
overflow:
|
|
2256
|
-
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2584
|
+
// overflow: 'visible',
|
|
2585
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(","),
|
|
2586
|
+
lineHeight: 1.4
|
|
2257
2587
|
},
|
|
2258
2588
|
".cm-content": {
|
|
2259
2589
|
padding: 0,
|
|
@@ -2277,8 +2607,11 @@ var defaultTheme = {
|
|
|
2277
2607
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2278
2608
|
borderLeft: "2px solid white"
|
|
2279
2609
|
},
|
|
2280
|
-
".cm-placeholder": {
|
|
2281
|
-
|
|
2610
|
+
"&light .cm-placeholder": {
|
|
2611
|
+
color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
2612
|
+
},
|
|
2613
|
+
"&dark .cm-placeholder": {
|
|
2614
|
+
color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
2282
2615
|
},
|
|
2283
2616
|
//
|
|
2284
2617
|
// line
|
|
@@ -2287,7 +2620,7 @@ var defaultTheme = {
|
|
|
2287
2620
|
paddingInline: 0
|
|
2288
2621
|
},
|
|
2289
2622
|
".cm-activeLine": {
|
|
2290
|
-
background: "
|
|
2623
|
+
background: "transparent"
|
|
2291
2624
|
},
|
|
2292
2625
|
//
|
|
2293
2626
|
// Selection
|
|
@@ -2458,90 +2791,88 @@ var codeTheme = {
|
|
|
2458
2791
|
};
|
|
2459
2792
|
|
|
2460
2793
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2794
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2461
2795
|
var EditorModes = [
|
|
2462
2796
|
"default",
|
|
2463
2797
|
"vim"
|
|
2464
2798
|
];
|
|
2465
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model,
|
|
2466
|
-
const tabsterDOMAttribute = useFocusableGroup({
|
|
2467
|
-
tabBehavior: "limited"
|
|
2468
|
-
});
|
|
2799
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2469
2800
|
const { themeMode } = useThemeContext();
|
|
2470
2801
|
const rootRef = useRef(null);
|
|
2471
2802
|
const [view, setView] = useState(null);
|
|
2472
2803
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2473
2804
|
view
|
|
2474
2805
|
]);
|
|
2475
|
-
|
|
2476
|
-
if (
|
|
2806
|
+
useEffect2(() => {
|
|
2807
|
+
if (autoFocus && !view?.hasFocus) {
|
|
2808
|
+
if (view?.state.selection.main?.from === 0) {
|
|
2809
|
+
const { to } = view.state.doc.lineAt(0);
|
|
2810
|
+
view?.dispatch({
|
|
2811
|
+
selection: {
|
|
2812
|
+
anchor: to
|
|
2813
|
+
}
|
|
2814
|
+
});
|
|
2815
|
+
}
|
|
2477
2816
|
view?.focus();
|
|
2478
2817
|
}
|
|
2479
|
-
}, [
|
|
2480
|
-
autofocus,
|
|
2481
|
-
view
|
|
2482
|
-
]);
|
|
2483
|
-
const { awareness: awareness2, peer } = model;
|
|
2484
|
-
useEffect(() => {
|
|
2485
|
-
if (awareness2 && peer) {
|
|
2486
|
-
awareness2.setLocalStateField("user", {
|
|
2487
|
-
name: peer.name ?? generateName(peer.id),
|
|
2488
|
-
color: getColorForValue({
|
|
2489
|
-
value: peer.id,
|
|
2490
|
-
type: "color"
|
|
2491
|
-
}),
|
|
2492
|
-
colorLight: getColorForValue({
|
|
2493
|
-
value: peer.id,
|
|
2494
|
-
themeMode,
|
|
2495
|
-
type: "highlight"
|
|
2496
|
-
})
|
|
2497
|
-
});
|
|
2498
|
-
}
|
|
2499
|
-
}, [
|
|
2500
|
-
awareness2,
|
|
2501
|
-
peer,
|
|
2502
|
-
themeMode
|
|
2503
|
-
]);
|
|
2504
|
-
useEffect(() => {
|
|
2505
|
-
if (view && comments2 !== void 0) {
|
|
2506
|
-
view.dispatch({
|
|
2507
|
-
effects: setCommentRange.of({
|
|
2508
|
-
model,
|
|
2509
|
-
comments: comments2
|
|
2510
|
-
})
|
|
2511
|
-
});
|
|
2512
|
-
}
|
|
2513
2818
|
}, [
|
|
2514
2819
|
view,
|
|
2515
|
-
|
|
2820
|
+
autoFocus
|
|
2516
2821
|
]);
|
|
2517
|
-
|
|
2822
|
+
useEffect2(() => {
|
|
2518
2823
|
if (!model || !rootRef.current) {
|
|
2519
2824
|
return;
|
|
2520
2825
|
}
|
|
2521
2826
|
const state = EditorState2.create({
|
|
2522
2827
|
doc: model.text(),
|
|
2523
|
-
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2524
2828
|
selection,
|
|
2525
2829
|
extensions: [
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2830
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2831
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2832
|
+
log2.catch(err, void 0, {
|
|
2833
|
+
F: __dxlog_file3,
|
|
2834
|
+
L: 134,
|
|
2835
|
+
S: void 0,
|
|
2836
|
+
C: (f, a) => f(...a)
|
|
2837
|
+
});
|
|
2838
|
+
}),
|
|
2529
2839
|
// Theme.
|
|
2530
|
-
// TODO(burdon): Make
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2840
|
+
// TODO(burdon): Make configurable.
|
|
2841
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2842
|
+
EditorView13.theme(theme ?? {}),
|
|
2843
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2844
|
+
EditorView13.editorAttributes.of({
|
|
2845
|
+
class: slots.editor?.className ?? ""
|
|
2846
|
+
}),
|
|
2847
|
+
EditorView13.contentAttributes.of({
|
|
2848
|
+
class: slots.content?.className ?? ""
|
|
2849
|
+
}),
|
|
2850
|
+
// State.
|
|
2851
|
+
EditorView13.editable.of(!readonly),
|
|
2852
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2534
2853
|
// Storage and replication.
|
|
2854
|
+
// NOTE: This must come before user extensions.
|
|
2535
2855
|
model.extension,
|
|
2856
|
+
// TODO(burdon): Factor out? (Requires special handling for Escape/Enter below).
|
|
2857
|
+
editorMode === "vim" && vim(),
|
|
2536
2858
|
// Custom.
|
|
2537
2859
|
...extensions
|
|
2538
|
-
].filter(
|
|
2860
|
+
].filter(isNotFalsy3)
|
|
2539
2861
|
});
|
|
2540
|
-
|
|
2541
|
-
|
|
2862
|
+
const newView = new EditorView13({
|
|
2863
|
+
state,
|
|
2542
2864
|
parent: rootRef.current,
|
|
2543
|
-
|
|
2865
|
+
scrollTo,
|
|
2866
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2867
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2868
|
+
dispatchTransactions: (trs, view2) => {
|
|
2869
|
+
if (debug) {
|
|
2870
|
+
logChanges(trs);
|
|
2871
|
+
}
|
|
2872
|
+
view2.update(trs);
|
|
2873
|
+
}
|
|
2544
2874
|
});
|
|
2875
|
+
view?.destroy();
|
|
2545
2876
|
setView(newView);
|
|
2546
2877
|
return () => {
|
|
2547
2878
|
newView?.destroy();
|
|
@@ -2557,8 +2888,14 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
|
|
|
2557
2888
|
const handleKeyUp = useCallback((event) => {
|
|
2558
2889
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2559
2890
|
switch (key) {
|
|
2891
|
+
case "Enter": {
|
|
2892
|
+
view?.focus();
|
|
2893
|
+
break;
|
|
2894
|
+
}
|
|
2560
2895
|
case "Escape": {
|
|
2561
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2896
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2897
|
+
view?.focus();
|
|
2898
|
+
}
|
|
2562
2899
|
break;
|
|
2563
2900
|
}
|
|
2564
2901
|
}
|
|
@@ -2570,23 +2907,23 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, s
|
|
|
2570
2907
|
key: model.id,
|
|
2571
2908
|
role: "none",
|
|
2572
2909
|
tabIndex: 0,
|
|
2573
|
-
onKeyUp: handleKeyUp,
|
|
2574
2910
|
...slots.root,
|
|
2575
|
-
...editorMode !==
|
|
2911
|
+
// {...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
2912
|
+
onKeyUp: handleKeyUp,
|
|
2576
2913
|
ref: rootRef
|
|
2577
2914
|
});
|
|
2578
2915
|
});
|
|
2579
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2916
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2580
2917
|
const { themeMode } = useThemeContext();
|
|
2581
2918
|
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2582
2919
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2583
2920
|
ref: forwardedRef,
|
|
2584
2921
|
readonly,
|
|
2585
2922
|
extensions: [
|
|
2586
|
-
|
|
2587
|
-
readonly,
|
|
2923
|
+
createBasicBundle({
|
|
2588
2924
|
themeMode,
|
|
2589
|
-
placeholder: placeholder3
|
|
2925
|
+
placeholder: placeholder3,
|
|
2926
|
+
lineWrapping
|
|
2590
2927
|
}),
|
|
2591
2928
|
...extensions
|
|
2592
2929
|
],
|
|
@@ -2595,15 +2932,14 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2595
2932
|
...props
|
|
2596
2933
|
});
|
|
2597
2934
|
});
|
|
2598
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2935
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2599
2936
|
const { themeMode } = useThemeContext();
|
|
2600
2937
|
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2601
2938
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2602
2939
|
ref: forwardedRef,
|
|
2603
2940
|
readonly,
|
|
2604
2941
|
extensions: [
|
|
2605
|
-
|
|
2606
|
-
readonly,
|
|
2942
|
+
createMarkdownExtensions({
|
|
2607
2943
|
themeMode,
|
|
2608
2944
|
placeholder: placeholder3
|
|
2609
2945
|
}),
|
|
@@ -2616,7 +2952,10 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2616
2952
|
});
|
|
2617
2953
|
var defaultSlots = {
|
|
2618
2954
|
root: {
|
|
2619
|
-
className: mx3("
|
|
2955
|
+
className: mx3("grow", focusRing)
|
|
2956
|
+
},
|
|
2957
|
+
editor: {
|
|
2958
|
+
className: "bs-full"
|
|
2620
2959
|
}
|
|
2621
2960
|
};
|
|
2622
2961
|
var defaultTextSlots = {
|
|
@@ -2626,22 +2965,178 @@ var defaultMarkdownSlots = {
|
|
|
2626
2965
|
...defaultSlots
|
|
2627
2966
|
};
|
|
2628
2967
|
|
|
2629
|
-
// packages/ui/react-ui-editor/src/
|
|
2630
|
-
import
|
|
2631
|
-
import {
|
|
2632
|
-
import
|
|
2968
|
+
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
2969
|
+
import { At, CaretRight, ChatText, Code, Image, Link, ListBullets, ListChecks, ListNumbers, TextStrikethrough, Table as Table2, TextB, TextItalic } from "@phosphor-icons/react";
|
|
2970
|
+
import { createContext } from "@radix-ui/react-context";
|
|
2971
|
+
import React2 from "react";
|
|
2972
|
+
import { Button, DensityProvider, Select } from "@dxos/react-ui";
|
|
2973
|
+
import { getSize } from "@dxos/react-ui-theme";
|
|
2974
|
+
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
2975
|
+
var ToolbarRoot = ({ children, onAction }) => {
|
|
2976
|
+
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
2977
|
+
onAction
|
|
2978
|
+
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
2979
|
+
density: "fine"
|
|
2980
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
2981
|
+
role: "toolbar",
|
|
2982
|
+
className: "flex w-full shrink-0 p-2 gap-4 items-center whitespace-nowrap overflow-hidden"
|
|
2983
|
+
}, children)));
|
|
2984
|
+
};
|
|
2985
|
+
var ToolbarButton = ({ Icon, onClick, title }) => {
|
|
2986
|
+
const { onAction } = useToolbarContext("ToolbarButton");
|
|
2987
|
+
const handleClick = () => {
|
|
2988
|
+
const action = onClick();
|
|
2989
|
+
if (action) {
|
|
2990
|
+
onAction?.(action);
|
|
2991
|
+
}
|
|
2992
|
+
};
|
|
2993
|
+
return /* @__PURE__ */ React2.createElement(Button, {
|
|
2994
|
+
variant: "ghost",
|
|
2995
|
+
classNames: "p-2",
|
|
2996
|
+
onClick: handleClick,
|
|
2997
|
+
title
|
|
2998
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
2999
|
+
className: getSize(5)
|
|
3000
|
+
}));
|
|
3001
|
+
};
|
|
3002
|
+
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3003
|
+
className: "grow"
|
|
3004
|
+
});
|
|
3005
|
+
var MarkdownHeading = () => {
|
|
3006
|
+
const { onAction } = useToolbarContext("MarkdownFormatting");
|
|
3007
|
+
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
3008
|
+
defaultValue: "0",
|
|
3009
|
+
onValueChange: (value) => onAction?.({
|
|
3010
|
+
type: "heading",
|
|
3011
|
+
data: parseInt(value)
|
|
3012
|
+
})
|
|
3013
|
+
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
|
|
3014
|
+
classNames: "w-[8rem]"
|
|
3015
|
+
}), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3016
|
+
value: "0"
|
|
3017
|
+
}, "Paragraph"), [
|
|
3018
|
+
1,
|
|
3019
|
+
2,
|
|
3020
|
+
3,
|
|
3021
|
+
4,
|
|
3022
|
+
5,
|
|
3023
|
+
6
|
|
3024
|
+
].map((level) => /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3025
|
+
key: level,
|
|
3026
|
+
value: String(level)
|
|
3027
|
+
}, "Heading ", level))))));
|
|
3028
|
+
};
|
|
3029
|
+
var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3030
|
+
role: "none"
|
|
3031
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3032
|
+
Icon: TextB,
|
|
3033
|
+
title: "Bold",
|
|
3034
|
+
onClick: () => ({
|
|
3035
|
+
type: "bold"
|
|
3036
|
+
})
|
|
3037
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3038
|
+
Icon: TextItalic,
|
|
3039
|
+
title: "Italic",
|
|
3040
|
+
onClick: () => ({
|
|
3041
|
+
type: "italic"
|
|
3042
|
+
})
|
|
3043
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3044
|
+
Icon: TextStrikethrough,
|
|
3045
|
+
title: "Strike-through",
|
|
3046
|
+
onClick: () => ({
|
|
3047
|
+
type: "strikethrough"
|
|
3048
|
+
})
|
|
3049
|
+
}));
|
|
3050
|
+
var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3051
|
+
role: "none"
|
|
3052
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3053
|
+
Icon: ListBullets,
|
|
3054
|
+
title: "Bullet list",
|
|
3055
|
+
onClick: () => ({
|
|
3056
|
+
type: "list"
|
|
3057
|
+
})
|
|
3058
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3059
|
+
Icon: ListNumbers,
|
|
3060
|
+
title: "Numbered list",
|
|
3061
|
+
onClick: () => ({
|
|
3062
|
+
type: "list-ordered"
|
|
3063
|
+
})
|
|
3064
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3065
|
+
Icon: ListChecks,
|
|
3066
|
+
title: "Task list",
|
|
3067
|
+
onClick: () => ({
|
|
3068
|
+
type: "list-tasks"
|
|
3069
|
+
})
|
|
3070
|
+
}));
|
|
3071
|
+
var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3072
|
+
role: "none"
|
|
3073
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3074
|
+
Icon: CaretRight,
|
|
3075
|
+
title: "Block quite",
|
|
3076
|
+
onClick: () => ({
|
|
3077
|
+
type: "blockquote"
|
|
3078
|
+
})
|
|
3079
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3080
|
+
Icon: Code,
|
|
3081
|
+
title: "Code block",
|
|
3082
|
+
onClick: () => ({
|
|
3083
|
+
type: "codeblock"
|
|
3084
|
+
})
|
|
3085
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3086
|
+
Icon: Table2,
|
|
3087
|
+
title: "Table",
|
|
3088
|
+
onClick: () => ({
|
|
3089
|
+
type: "table"
|
|
3090
|
+
})
|
|
3091
|
+
}));
|
|
3092
|
+
var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3093
|
+
role: "none"
|
|
3094
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3095
|
+
Icon: Link,
|
|
3096
|
+
title: "Link",
|
|
3097
|
+
onClick: () => ({
|
|
3098
|
+
type: "link"
|
|
3099
|
+
})
|
|
3100
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3101
|
+
Icon: At,
|
|
3102
|
+
title: "Mention",
|
|
3103
|
+
onClick: () => ({
|
|
3104
|
+
type: "mention"
|
|
3105
|
+
})
|
|
3106
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3107
|
+
Icon: Image,
|
|
3108
|
+
title: "Image",
|
|
3109
|
+
onClick: () => ({
|
|
3110
|
+
type: "image"
|
|
3111
|
+
})
|
|
3112
|
+
}));
|
|
3113
|
+
var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null), /* @__PURE__ */ React2.createElement(MarkdownLinks, null));
|
|
3114
|
+
var MarkdownExtended = () => /* @__PURE__ */ React2.createElement(Toolbar.Button, {
|
|
3115
|
+
Icon: ChatText,
|
|
3116
|
+
title: "Create comment",
|
|
3117
|
+
onClick: () => ({
|
|
3118
|
+
type: "comment"
|
|
3119
|
+
})
|
|
3120
|
+
});
|
|
3121
|
+
var Toolbar = {
|
|
3122
|
+
Root: ToolbarRoot,
|
|
3123
|
+
Button: ToolbarButton,
|
|
3124
|
+
Separator: ToolbarSeparator,
|
|
3125
|
+
Markdown: MarkdownStandard,
|
|
3126
|
+
Extended: MarkdownExtended
|
|
3127
|
+
};
|
|
2633
3128
|
|
|
2634
3129
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2635
3130
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2636
3131
|
import { Context as Context2 } from "@dxos/context";
|
|
2637
|
-
import { invariant as
|
|
2638
|
-
import { log as
|
|
3132
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
3133
|
+
import { log as log3 } from "@dxos/log";
|
|
2639
3134
|
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2640
3135
|
var DEBOUNCE_INTERVAL = 100;
|
|
2641
3136
|
var SpaceAwarenessProvider = class {
|
|
2642
3137
|
constructor(params) {
|
|
2643
|
-
this.remoteStateChange = new Event2();
|
|
2644
3138
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
3139
|
+
this.remoteStateChange = new Event2();
|
|
2645
3140
|
this._space = params.space;
|
|
2646
3141
|
this._channel = params.channel;
|
|
2647
3142
|
this._peerId = params.peerId;
|
|
@@ -2658,7 +3153,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2658
3153
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2659
3154
|
}
|
|
2660
3155
|
});
|
|
2661
|
-
|
|
3156
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2662
3157
|
switch (message.payload.kind) {
|
|
2663
3158
|
case "query": {
|
|
2664
3159
|
this._handleQueryMessage();
|
|
@@ -2669,16 +3164,15 @@ var SpaceAwarenessProvider = class {
|
|
|
2669
3164
|
break;
|
|
2670
3165
|
}
|
|
2671
3166
|
}
|
|
2672
|
-
});
|
|
2673
|
-
this._ctx.onDispose(unsubscribe);
|
|
3167
|
+
}));
|
|
2674
3168
|
void this._space.postMessage(this._channel, {
|
|
2675
3169
|
kind: "query"
|
|
2676
3170
|
}).catch((err) => {
|
|
2677
|
-
|
|
3171
|
+
log3.debug("failed to query awareness", {
|
|
2678
3172
|
err
|
|
2679
3173
|
}, {
|
|
2680
3174
|
F: __dxlog_file4,
|
|
2681
|
-
L:
|
|
3175
|
+
L: 89,
|
|
2682
3176
|
S: this,
|
|
2683
3177
|
C: (f, a) => f(...a)
|
|
2684
3178
|
});
|
|
@@ -2689,10 +3183,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2689
3183
|
this._ctx = void 0;
|
|
2690
3184
|
this._postTask = void 0;
|
|
2691
3185
|
}
|
|
3186
|
+
getRemoteStates() {
|
|
3187
|
+
return Array.from(this._remoteStates.values());
|
|
3188
|
+
}
|
|
2692
3189
|
update(position) {
|
|
2693
|
-
|
|
3190
|
+
invariant2(this._postTask, void 0, {
|
|
2694
3191
|
F: __dxlog_file4,
|
|
2695
|
-
L:
|
|
3192
|
+
L: 104,
|
|
2696
3193
|
S: this,
|
|
2697
3194
|
A: [
|
|
2698
3195
|
"this._postTask",
|
|
@@ -2706,13 +3203,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2706
3203
|
};
|
|
2707
3204
|
this._postTask.schedule();
|
|
2708
3205
|
}
|
|
2709
|
-
getRemoteStates() {
|
|
2710
|
-
return Array.from(this._remoteStates.values());
|
|
2711
|
-
}
|
|
2712
3206
|
_handleQueryMessage() {
|
|
2713
|
-
|
|
3207
|
+
invariant2(this._postTask, void 0, {
|
|
2714
3208
|
F: __dxlog_file4,
|
|
2715
|
-
L:
|
|
3209
|
+
L: 115,
|
|
2716
3210
|
S: this,
|
|
2717
3211
|
A: [
|
|
2718
3212
|
"this._postTask",
|
|
@@ -2722,9 +3216,9 @@ var SpaceAwarenessProvider = class {
|
|
|
2722
3216
|
this._postTask.schedule();
|
|
2723
3217
|
}
|
|
2724
3218
|
_handlePostMessage(message) {
|
|
2725
|
-
|
|
3219
|
+
invariant2(message.kind === "post", void 0, {
|
|
2726
3220
|
F: __dxlog_file4,
|
|
2727
|
-
L:
|
|
3221
|
+
L: 120,
|
|
2728
3222
|
S: this,
|
|
2729
3223
|
A: [
|
|
2730
3224
|
"message.kind === 'post'",
|
|
@@ -2736,199 +3230,240 @@ var SpaceAwarenessProvider = class {
|
|
|
2736
3230
|
}
|
|
2737
3231
|
};
|
|
2738
3232
|
|
|
2739
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
3233
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2740
3234
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2741
|
-
|
|
2742
|
-
|
|
3235
|
+
var modelState = StateField5.define({
|
|
3236
|
+
create: () => void 0,
|
|
3237
|
+
update: (model) => model
|
|
3238
|
+
});
|
|
2743
3239
|
|
|
2744
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2750
|
-
import { log as log3 } from "@dxos/log";
|
|
2751
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2752
|
-
var createYjsModel = ({ identity, space, text }) => {
|
|
2753
|
-
invariant4(text?.doc && text?.content, void 0, {
|
|
2754
|
-
F: __dxlog_file5,
|
|
2755
|
-
L: 21,
|
|
2756
|
-
S: void 0,
|
|
2757
|
-
A: [
|
|
2758
|
-
"text?.doc && text?.content",
|
|
2759
|
-
""
|
|
2760
|
-
]
|
|
2761
|
-
});
|
|
2762
|
-
const provider = space ? new YAwarenessProvider({
|
|
2763
|
-
space,
|
|
2764
|
-
doc: text.doc,
|
|
2765
|
-
channel: `yjs.awareness.${text.id}`
|
|
2766
|
-
}) : void 0;
|
|
2767
|
-
const model = {
|
|
2768
|
-
id: text.doc.guid,
|
|
2769
|
-
content: text.content,
|
|
2770
|
-
text: () => text.content.toString(),
|
|
2771
|
-
extension: [
|
|
2772
|
-
modelState.init(() => model),
|
|
2773
|
-
yjs(text.content, provider?.awareness)
|
|
2774
|
-
],
|
|
2775
|
-
awareness: provider?.awareness,
|
|
2776
|
-
peer: identity ? {
|
|
2777
|
-
id: identity.identityKey.toHex(),
|
|
2778
|
-
name: identity.profile?.displayName
|
|
2779
|
-
} : void 0
|
|
2780
|
-
};
|
|
2781
|
-
return model;
|
|
2782
|
-
};
|
|
2783
|
-
var messageAwareness = 1;
|
|
2784
|
-
var messageQueryAwareness = 3;
|
|
2785
|
-
var YAwarenessProvider = class extends Observable {
|
|
2786
|
-
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2787
|
-
super();
|
|
2788
|
-
this._space = space;
|
|
2789
|
-
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2790
|
-
this._channel = channel;
|
|
2791
|
-
this._clientId = doc.clientID;
|
|
2792
|
-
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
2793
|
-
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
2794
|
-
if (typeof window !== "undefined") {
|
|
2795
|
-
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
2796
|
-
} else if (typeof process !== "undefined") {
|
|
2797
|
-
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
3240
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
3241
|
+
var useActionHandler = (view) => {
|
|
3242
|
+
return (action) => {
|
|
3243
|
+
if (!view) {
|
|
3244
|
+
return;
|
|
2798
3245
|
}
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
_handleSpaceMessage({ payload }) {
|
|
2831
|
-
log3("space message", payload, {
|
|
2832
|
-
F: __dxlog_file5,
|
|
2833
|
-
L: 109,
|
|
2834
|
-
S: this,
|
|
2835
|
-
C: (f, a) => f(...a)
|
|
3246
|
+
switch (action.type) {
|
|
3247
|
+
case "heading":
|
|
3248
|
+
setHeading(parseInt(action.data))(view);
|
|
3249
|
+
break;
|
|
3250
|
+
case "bold":
|
|
3251
|
+
toggleBold(view);
|
|
3252
|
+
break;
|
|
3253
|
+
case "italic":
|
|
3254
|
+
toggleItalic(view);
|
|
3255
|
+
break;
|
|
3256
|
+
case "strikethrough":
|
|
3257
|
+
toggleStrikethrough(view);
|
|
3258
|
+
break;
|
|
3259
|
+
case "list":
|
|
3260
|
+
toggleList(view);
|
|
3261
|
+
break;
|
|
3262
|
+
case "codeblock":
|
|
3263
|
+
insertCodeblock(view);
|
|
3264
|
+
break;
|
|
3265
|
+
case "table":
|
|
3266
|
+
insertTable(view);
|
|
3267
|
+
break;
|
|
3268
|
+
case "comment":
|
|
3269
|
+
createComment(view);
|
|
3270
|
+
break;
|
|
3271
|
+
}
|
|
3272
|
+
setTimeout(() => {
|
|
3273
|
+
view.focus();
|
|
3274
|
+
view.dispatch({
|
|
3275
|
+
selection: view.state.selection
|
|
3276
|
+
});
|
|
2836
3277
|
});
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
3278
|
+
};
|
|
3279
|
+
};
|
|
3280
|
+
|
|
3281
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3282
|
+
import { useState as useState2 } from "react";
|
|
3283
|
+
var useEditorView = () => {
|
|
3284
|
+
const [view, setView] = useState2(null);
|
|
3285
|
+
return [
|
|
3286
|
+
(ref) => {
|
|
3287
|
+
setView(ref);
|
|
3288
|
+
},
|
|
3289
|
+
view
|
|
3290
|
+
];
|
|
3291
|
+
};
|
|
3292
|
+
|
|
3293
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3294
|
+
import { EditorSelection, EditorState as EditorState3 } from "@codemirror/state";
|
|
3295
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
3296
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
3297
|
+
import { log as log4 } from "@dxos/log";
|
|
3298
|
+
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
3299
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
3300
|
+
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
|
|
3301
|
+
const onUpdate = useRef2();
|
|
3302
|
+
const [view, setView] = useState3();
|
|
3303
|
+
const parentRef = useRef2(null);
|
|
3304
|
+
useEffect3(() => {
|
|
3305
|
+
if (parentRef.current) {
|
|
3306
|
+
const state = EditorState3.create({
|
|
3307
|
+
doc,
|
|
3308
|
+
selection,
|
|
3309
|
+
extensions: [
|
|
3310
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3311
|
+
EditorView14.exceptionSink.of((err) => {
|
|
3312
|
+
log4.catch(err, void 0, {
|
|
3313
|
+
F: __dxlog_file5,
|
|
3314
|
+
L: 57,
|
|
3315
|
+
S: void 0,
|
|
3316
|
+
C: (f, a) => f(...a)
|
|
3317
|
+
});
|
|
3318
|
+
}),
|
|
3319
|
+
extensions,
|
|
3320
|
+
EditorView14.updateListener.of(() => {
|
|
3321
|
+
onUpdate.current?.();
|
|
3322
|
+
})
|
|
3323
|
+
].filter(isNotFalsy4)
|
|
3324
|
+
});
|
|
3325
|
+
const view2 = new EditorView14({
|
|
3326
|
+
parent: parentRef.current,
|
|
3327
|
+
scrollTo,
|
|
3328
|
+
state,
|
|
3329
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
3330
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
3331
|
+
dispatchTransactions: (trs, view3) => {
|
|
3332
|
+
if (debug) {
|
|
3333
|
+
logChanges(trs);
|
|
3334
|
+
}
|
|
3335
|
+
view3.update(trs);
|
|
3336
|
+
}
|
|
3337
|
+
});
|
|
3338
|
+
setView(view2);
|
|
2841
3339
|
}
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
3340
|
+
return () => {
|
|
3341
|
+
view?.destroy();
|
|
3342
|
+
};
|
|
3343
|
+
}, [
|
|
3344
|
+
parentRef
|
|
3345
|
+
]);
|
|
3346
|
+
useEffect3(() => {
|
|
3347
|
+
if (view) {
|
|
3348
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
3349
|
+
selection = EditorSelection.single(view.state.doc.line(1).to);
|
|
2852
3350
|
}
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
3351
|
+
if (selection || scrollTo) {
|
|
3352
|
+
onUpdate.current = () => {
|
|
3353
|
+
onUpdate.current = void 0;
|
|
3354
|
+
view.dispatch({
|
|
3355
|
+
selection,
|
|
3356
|
+
effects: scrollTo && [
|
|
3357
|
+
scrollTo
|
|
3358
|
+
],
|
|
3359
|
+
scrollIntoView: !scrollTo
|
|
3360
|
+
});
|
|
3361
|
+
};
|
|
2858
3362
|
}
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
return encoder;
|
|
3363
|
+
if (autoFocus) {
|
|
3364
|
+
view.focus();
|
|
2862
3365
|
}
|
|
2863
3366
|
}
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
}
|
|
3367
|
+
}, [
|
|
3368
|
+
view,
|
|
3369
|
+
autoFocus,
|
|
3370
|
+
selection,
|
|
3371
|
+
scrollTo
|
|
3372
|
+
]);
|
|
3373
|
+
return {
|
|
3374
|
+
parentRef,
|
|
3375
|
+
view
|
|
3376
|
+
};
|
|
3377
|
+
};
|
|
3378
|
+
var createDataExtensions = ({ readonly = false } = {}) => {
|
|
3379
|
+
return [
|
|
3380
|
+
//
|
|
3381
|
+
EditorState3.readOnly.of(readonly),
|
|
3382
|
+
EditorView14.editable.of(!readonly)
|
|
3383
|
+
];
|
|
3384
|
+
};
|
|
3385
|
+
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
3386
|
+
return [
|
|
3387
|
+
//
|
|
3388
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3389
|
+
theme && EditorView14.theme(theme),
|
|
3390
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3391
|
+
EditorView14.editorAttributes.of({
|
|
3392
|
+
class: slots?.editor?.className ?? ""
|
|
3393
|
+
}),
|
|
3394
|
+
EditorView14.contentAttributes.of({
|
|
3395
|
+
class: slots?.content?.className ?? ""
|
|
3396
|
+
})
|
|
3397
|
+
].filter(isNotFalsy4);
|
|
2874
3398
|
};
|
|
2875
3399
|
|
|
2876
3400
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
}
|
|
3401
|
+
import get4 from "lodash.get";
|
|
3402
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
3403
|
+
import { generateName } from "@dxos/display-name";
|
|
3404
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
3405
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
3406
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
3407
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2881
3408
|
var useTextModel = (props) => {
|
|
2882
3409
|
const { identity, space, text } = props;
|
|
2883
|
-
const [model, setModel] =
|
|
2884
|
-
|
|
3410
|
+
const [model, setModel] = useState4();
|
|
3411
|
+
useEffect4(() => setModel(createModel(props)), [
|
|
2885
3412
|
identity,
|
|
2886
3413
|
space,
|
|
2887
3414
|
text
|
|
2888
3415
|
]);
|
|
2889
3416
|
return model;
|
|
2890
3417
|
};
|
|
2891
|
-
var
|
|
2892
|
-
const
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
}
|
|
3418
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
3419
|
+
const [content, setContent] = useState4(defaultContent ?? "");
|
|
3420
|
+
return {
|
|
3421
|
+
id,
|
|
3422
|
+
content,
|
|
3423
|
+
setContent,
|
|
3424
|
+
text: () => content
|
|
3425
|
+
};
|
|
2900
3426
|
};
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3427
|
+
var createModel = ({ space, identity, text }) => {
|
|
3428
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
3429
|
+
F: __dxlog_file6,
|
|
3430
|
+
L: 50,
|
|
3431
|
+
S: void 0,
|
|
3432
|
+
A: [
|
|
3433
|
+
"isAutomergeObject(text)",
|
|
3434
|
+
""
|
|
3435
|
+
]
|
|
3436
|
+
});
|
|
2904
3437
|
const obj = text;
|
|
2905
3438
|
const doc = getRawDoc(obj, [
|
|
2906
3439
|
obj.field
|
|
2907
3440
|
]);
|
|
2908
|
-
const
|
|
3441
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
2909
3442
|
space,
|
|
2910
3443
|
channel: `automerge.awareness.${obj.id}`,
|
|
2911
3444
|
info: {
|
|
2912
|
-
displayName: identity
|
|
3445
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
2913
3446
|
color: cursorColor.color,
|
|
2914
3447
|
lightColor: cursorColor.light
|
|
2915
3448
|
},
|
|
2916
3449
|
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2917
3450
|
});
|
|
3451
|
+
const extensions = [
|
|
3452
|
+
//
|
|
3453
|
+
modelState.init(() => model),
|
|
3454
|
+
automerge({
|
|
3455
|
+
handle: doc.handle,
|
|
3456
|
+
path: doc.path
|
|
3457
|
+
})
|
|
3458
|
+
];
|
|
3459
|
+
if (awarenessProvider2) {
|
|
3460
|
+
extensions.push(awareness(awarenessProvider2));
|
|
3461
|
+
}
|
|
2918
3462
|
const model = {
|
|
2919
3463
|
id: obj.id,
|
|
2920
3464
|
content: doc,
|
|
2921
3465
|
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2922
|
-
|
|
2923
|
-
extension: [
|
|
2924
|
-
modelState.init(() => model),
|
|
2925
|
-
automerge3({
|
|
2926
|
-
handle: doc.handle,
|
|
2927
|
-
path: doc.path
|
|
2928
|
-
}),
|
|
2929
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2930
|
-
awareness()
|
|
2931
|
-
].filter(isNotNullOrUndefined),
|
|
3466
|
+
extension: extensions,
|
|
2932
3467
|
peer: identity ? {
|
|
2933
3468
|
id: identity.identityKey.toHex(),
|
|
2934
3469
|
name: identity.profile?.displayName
|
|
@@ -2937,7 +3472,6 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2937
3472
|
return model;
|
|
2938
3473
|
};
|
|
2939
3474
|
export {
|
|
2940
|
-
AwarenessProvider,
|
|
2941
3475
|
BaseTextEditor,
|
|
2942
3476
|
Cursor,
|
|
2943
3477
|
Doc,
|
|
@@ -2947,46 +3481,66 @@ export {
|
|
|
2947
3481
|
SpaceAwarenessProvider,
|
|
2948
3482
|
TextEditor,
|
|
2949
3483
|
TextKind,
|
|
2950
|
-
|
|
3484
|
+
Toolbar,
|
|
2951
3485
|
YText,
|
|
2952
3486
|
YXmlFragment,
|
|
2953
3487
|
autocomplete,
|
|
2954
|
-
|
|
3488
|
+
automerge,
|
|
2955
3489
|
awareness,
|
|
2956
|
-
|
|
3490
|
+
awarenessProvider,
|
|
2957
3491
|
blast,
|
|
2958
3492
|
callbackWrapper,
|
|
2959
3493
|
code2 as code,
|
|
2960
3494
|
codeTheme,
|
|
2961
3495
|
comments,
|
|
2962
|
-
|
|
2963
|
-
|
|
3496
|
+
createBasicBundle,
|
|
3497
|
+
createComment,
|
|
3498
|
+
createDataExtensions,
|
|
3499
|
+
createMarkdownExtensions,
|
|
3500
|
+
createThemeExtensions,
|
|
2964
3501
|
defaultMarkdownSlots,
|
|
2965
3502
|
defaultOptions,
|
|
2966
3503
|
defaultSlots,
|
|
2967
3504
|
defaultTextSlots,
|
|
2968
3505
|
defaultTheme,
|
|
3506
|
+
focusComment,
|
|
3507
|
+
formatting,
|
|
2969
3508
|
getToken,
|
|
3509
|
+
heading2 as heading,
|
|
2970
3510
|
hr,
|
|
2971
3511
|
image,
|
|
3512
|
+
insertCodeblock,
|
|
3513
|
+
insertTable,
|
|
3514
|
+
keymap7 as keymap,
|
|
2972
3515
|
link,
|
|
2973
3516
|
listener,
|
|
2974
|
-
|
|
3517
|
+
logChanges,
|
|
2975
3518
|
markdownHighlightStyle,
|
|
2976
3519
|
markdownTags,
|
|
2977
3520
|
markdownTagsExtensions,
|
|
2978
3521
|
markdownTheme,
|
|
2979
3522
|
mention,
|
|
2980
3523
|
modelState,
|
|
2981
|
-
|
|
2982
|
-
|
|
3524
|
+
outliner,
|
|
3525
|
+
setComments,
|
|
3526
|
+
setHeading,
|
|
2983
3527
|
setSelection,
|
|
2984
3528
|
table,
|
|
2985
3529
|
tags2 as tags,
|
|
2986
3530
|
tasklist,
|
|
2987
3531
|
textTheme,
|
|
3532
|
+
toggleBold,
|
|
3533
|
+
toggleItalic,
|
|
3534
|
+
toggleList,
|
|
3535
|
+
toggleStrikethrough,
|
|
3536
|
+
toggleStyle,
|
|
2988
3537
|
typewriter,
|
|
3538
|
+
useActionHandler,
|
|
3539
|
+
useComments,
|
|
3540
|
+
useEditorView,
|
|
3541
|
+
useInMemoryTextModel,
|
|
3542
|
+
useTextEditor,
|
|
2989
3543
|
useTextModel,
|
|
2990
|
-
|
|
3544
|
+
useToolbarContext
|
|
2991
3545
|
};
|
|
2992
3546
|
//# sourceMappingURL=index.mjs.map
|