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