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