@dxos/react-ui-editor 0.3.11-main.279d9e6 → 0.3.11-main.2cb95a4
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 +801 -776
- 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 +16 -13
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -12
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
- package/dist/types/src/extensions/awareness.d.ts +2 -0
- 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/code.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +31 -18
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
- package/dist/types/src/extensions/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/hr.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +2 -5
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- 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/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +1 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge.d.ts +2 -1
- package/dist/types/src/hooks/automerge.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +28 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +2 -32
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/hooks/yjs.d.ts +2 -1
- package/dist/types/src/hooks/yjs.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- 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 +7 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +32 -31
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +77 -79
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +124 -92
- package/src/components/TextEditor/comments.stories.tsx +357 -0
- package/src/extensions/autocomplete.ts +23 -19
- package/src/extensions/automerge/automerge.ts +40 -46
- package/src/extensions/automerge/cursor.ts +2 -1
- package/src/extensions/automerge/defs.ts +10 -31
- package/src/extensions/automerge/semaphore.ts +23 -20
- package/src/extensions/automerge/update-automerge.ts +2 -2
- package/src/extensions/awareness.ts +45 -34
- package/src/extensions/basic.ts +22 -17
- package/src/extensions/code.ts +24 -18
- package/src/extensions/comments.ts +242 -234
- package/src/extensions/cursor.ts +50 -0
- package/src/extensions/hr.ts +49 -50
- package/src/extensions/image.ts +2 -2
- package/src/extensions/index.ts +2 -0
- package/src/extensions/link.ts +7 -7
- package/src/extensions/markdown/bundle.ts +18 -24
- package/src/extensions/markdown/highlight.ts +0 -8
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/extensions/table.ts +6 -3
- package/src/extensions/tasklist.ts +78 -86
- package/src/extensions/yjs/cursor.ts +2 -1
- package/src/extensions/yjs/yjs.test.ts +1 -1
- package/src/extensions/yjs/yjs.ts +2 -2
- package/src/hooks/automerge.ts +2 -1
- package/src/hooks/defs.ts +47 -0
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useTextModel.ts +3 -49
- package/src/hooks/yjs.ts +2 -23
- package/src/index.ts +2 -0
- package/src/styles/markdown.ts +0 -2
- package/src/themes/default.ts +17 -50
- package/src/util.ts +41 -0
- package/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/index.d.ts +0 -3
- package/dist/types/src/util/index.d.ts.map +0 -1
- package/dist/types/src/util/util.d.ts +0 -5
- package/dist/types/src/util/util.d.ts.map +0 -1
- package/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- package/src/util/util.ts +0 -18
|
@@ -7,52 +7,56 @@ 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, useState } from "react";
|
|
15
|
-
import {
|
|
16
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useRef, useState } from "react";
|
|
15
|
+
import { log as log2 } from "@dxos/log";
|
|
16
|
+
import { useThemeContext as useThemeContext2 } from "@dxos/react-ui";
|
|
17
|
+
import { inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
18
|
|
|
19
19
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
21
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
21
22
|
import { keymap } from "@codemirror/view";
|
|
22
23
|
var autocomplete = ({ onSearch }) => {
|
|
23
24
|
return [
|
|
24
25
|
// https://codemirror.net/docs/ref/#view.keymap
|
|
25
26
|
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
|
27
|
+
// TODO(burdon): Set custom keymap.
|
|
26
28
|
keymap.of(completionKeymap),
|
|
27
29
|
// https://codemirror.net/examples/autocompletion
|
|
28
30
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
29
31
|
autocompletion({
|
|
30
|
-
|
|
32
|
+
activateOnTyping: true,
|
|
33
|
+
// closeOnBlur: false,
|
|
31
34
|
// defaultKeymap: false,
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
from: match.from,
|
|
44
|
-
options: onSearch(match.text.toLowerCase())
|
|
45
|
-
};
|
|
35
|
+
// TODO(burdon): Styles/fragments.
|
|
36
|
+
tooltipClass: () => "shadow rounded"
|
|
37
|
+
}),
|
|
38
|
+
// TODO(burdon): Option to create new page?
|
|
39
|
+
// TODO(burdon): Optional decoration via addToOptions
|
|
40
|
+
markdownLanguage.data.of({
|
|
41
|
+
autocomplete: (context) => {
|
|
42
|
+
const match = context.matchBefore(/\w*/);
|
|
43
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
44
|
+
return null;
|
|
46
45
|
}
|
|
47
|
-
|
|
46
|
+
return {
|
|
47
|
+
from: match.from,
|
|
48
|
+
options: onSearch(match.text.toLowerCase())
|
|
49
|
+
};
|
|
50
|
+
}
|
|
48
51
|
})
|
|
49
52
|
];
|
|
50
53
|
};
|
|
51
54
|
|
|
52
55
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
53
|
-
import {
|
|
54
|
-
import { ViewPlugin } from "@codemirror/view";
|
|
56
|
+
import { StateField } from "@codemirror/state";
|
|
57
|
+
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
55
58
|
import { next as A } from "@dxos/automerge/automerge";
|
|
59
|
+
import { invariant } from "@dxos/invariant";
|
|
56
60
|
|
|
57
61
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
58
62
|
import get from "lodash.get";
|
|
@@ -93,12 +97,12 @@ var cursorConverter = (handle, path) => ({
|
|
|
93
97
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
94
98
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
95
99
|
var effectType = StateEffect.define({});
|
|
100
|
+
var reconcileAnnotationType = Annotation.define();
|
|
101
|
+
var getPath = (state, field) => state.field(field).path;
|
|
102
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
96
103
|
var updateHeads = (newHeads) => effectType.of({
|
|
97
104
|
newHeads
|
|
98
105
|
});
|
|
99
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
100
|
-
var getPath = (state, field) => state.field(field).path;
|
|
101
|
-
var reconcileAnnotationType = Annotation.define();
|
|
102
106
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
103
107
|
|
|
104
108
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
@@ -236,85 +240,96 @@ var charPath = (textPath, candidatePath) => {
|
|
|
236
240
|
|
|
237
241
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
238
242
|
var PatchSemaphore = class {
|
|
239
|
-
|
|
240
|
-
|
|
243
|
+
// prettier-ignore
|
|
244
|
+
constructor(_handle, _state) {
|
|
245
|
+
this._handle = _handle;
|
|
246
|
+
this._state = _state;
|
|
241
247
|
this._inReconcile = false;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
changes: inverted,
|
|
258
|
-
annotations: reconcileAnnotationType.of(true)
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
262
|
-
if (newHeads === null || newHeads === void 0) {
|
|
263
|
-
newHeads = automerge2.getHeads(handle.docSync());
|
|
264
|
-
}
|
|
265
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
|
|
266
|
-
updateCodeMirror(view, selection, path, diff);
|
|
248
|
+
}
|
|
249
|
+
// NOTE: Cannot destruct view.state.
|
|
250
|
+
reconcile(view) {
|
|
251
|
+
if (this._inReconcile) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
this._inReconcile = true;
|
|
255
|
+
const path = getPath(view.state, this._state);
|
|
256
|
+
const oldHeads = getLastHeads(view.state, this._state);
|
|
257
|
+
let selection = view.state.selection;
|
|
258
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
259
|
+
const toInvert = transactions.slice().reverse();
|
|
260
|
+
for (const tx of toInvert) {
|
|
261
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
262
|
+
selection = selection.map(inverted);
|
|
267
263
|
view.dispatch({
|
|
268
|
-
|
|
269
|
-
annotations: reconcileAnnotationType.of(
|
|
264
|
+
changes: inverted,
|
|
265
|
+
annotations: reconcileAnnotationType.of(true)
|
|
270
266
|
});
|
|
271
|
-
|
|
272
|
-
|
|
267
|
+
}
|
|
268
|
+
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
269
|
+
if (newHeads === null || newHeads === void 0) {
|
|
270
|
+
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
271
|
+
}
|
|
272
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
273
|
+
updateCodeMirror(view, selection, path, diff);
|
|
274
|
+
view.dispatch({
|
|
275
|
+
effects: updateHeads(newHeads),
|
|
276
|
+
annotations: reconcileAnnotationType.of({})
|
|
277
|
+
});
|
|
278
|
+
this._inReconcile = false;
|
|
273
279
|
}
|
|
274
280
|
};
|
|
275
281
|
|
|
276
|
-
// packages/ui/react-ui-editor/src/
|
|
282
|
+
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
277
283
|
import { Facet } from "@codemirror/state";
|
|
278
|
-
var
|
|
284
|
+
var defaultCursorConverter = {
|
|
279
285
|
toCursor: (position) => position.toString(),
|
|
280
286
|
fromCursor: (cursor) => parseInt(cursor)
|
|
281
287
|
};
|
|
282
|
-
var
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
// packages/ui/react-ui-editor/src/util/util.ts
|
|
287
|
-
import { log } from "@dxos/log";
|
|
288
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
289
|
-
var callbackWrapper = (fn) => (...args) => {
|
|
290
|
-
try {
|
|
291
|
-
return fn(...args);
|
|
292
|
-
} catch (error) {
|
|
293
|
-
log.catch(error, void 0, {
|
|
294
|
-
F: __dxlog_file,
|
|
295
|
-
L: 16,
|
|
296
|
-
S: void 0,
|
|
297
|
-
C: (f, a) => f(...a)
|
|
288
|
+
var Cursor = class _Cursor {
|
|
289
|
+
static {
|
|
290
|
+
this.converter = Facet.define({
|
|
291
|
+
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
298
292
|
});
|
|
299
293
|
}
|
|
294
|
+
static {
|
|
295
|
+
this.getCursorFromRange = (state, range) => {
|
|
296
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
297
|
+
const from = cursorConverter3.toCursor(range.from);
|
|
298
|
+
const to = cursorConverter3.toCursor(range.to, -1);
|
|
299
|
+
return [
|
|
300
|
+
from,
|
|
301
|
+
to
|
|
302
|
+
].join(":");
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
static {
|
|
306
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
307
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
308
|
+
const parts = cursor.split(":");
|
|
309
|
+
const from = cursorConverter3.fromCursor(parts[0]);
|
|
310
|
+
const to = cursorConverter3.fromCursor(parts[1]);
|
|
311
|
+
return from !== void 0 && to !== void 0 ? {
|
|
312
|
+
from,
|
|
313
|
+
to
|
|
314
|
+
} : void 0;
|
|
315
|
+
};
|
|
316
|
+
}
|
|
300
317
|
};
|
|
301
318
|
|
|
302
319
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
303
|
-
var
|
|
304
|
-
combine: (values) => values.at(-1)
|
|
305
|
-
});
|
|
320
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts";
|
|
306
321
|
var automerge3 = ({ handle, path }) => {
|
|
307
|
-
const
|
|
322
|
+
const state = StateField.define({
|
|
308
323
|
create: () => ({
|
|
324
|
+
path: path.slice(),
|
|
309
325
|
lastHeads: A.getHeads(handle.docSync()),
|
|
310
|
-
unreconciledTransactions: []
|
|
311
|
-
path: path.slice()
|
|
326
|
+
unreconciledTransactions: []
|
|
312
327
|
}),
|
|
313
328
|
update: (value, tr) => {
|
|
314
329
|
const result = {
|
|
330
|
+
path: path.slice(),
|
|
315
331
|
lastHeads: value.lastHeads,
|
|
316
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
317
|
-
path: path.slice()
|
|
332
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
318
333
|
};
|
|
319
334
|
let clearUnreconciled = false;
|
|
320
335
|
for (const effect of tr.effects) {
|
|
@@ -333,41 +348,50 @@ var automerge3 = ({ handle, path }) => {
|
|
|
333
348
|
return result;
|
|
334
349
|
}
|
|
335
350
|
});
|
|
336
|
-
const semaphore = new PatchSemaphore(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
351
|
+
const semaphore = new PatchSemaphore(handle, state);
|
|
352
|
+
return [
|
|
353
|
+
Cursor.converter.of(cursorConverter(handle, path)),
|
|
354
|
+
// Reconcile external updates.
|
|
355
|
+
ViewPlugin.fromClass(class {
|
|
356
|
+
constructor(_view) {
|
|
357
|
+
this._view = _view;
|
|
358
|
+
invariant(this._view, void 0, {
|
|
359
|
+
F: __dxlog_file,
|
|
360
|
+
L: 66,
|
|
361
|
+
S: this,
|
|
362
|
+
A: [
|
|
363
|
+
"this._view",
|
|
364
|
+
""
|
|
365
|
+
]
|
|
349
366
|
});
|
|
367
|
+
handle.addListener("change", this._handleChange.bind(this));
|
|
350
368
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
369
|
+
destroy() {
|
|
370
|
+
handle.removeListener("change", this._handleChange.bind(this));
|
|
371
|
+
}
|
|
372
|
+
_handleChange() {
|
|
373
|
+
semaphore.reconcile(this._view);
|
|
374
|
+
}
|
|
375
|
+
}),
|
|
376
|
+
// Reconcile local updates.
|
|
377
|
+
EditorView.updateListener.of(({ view, changes }) => {
|
|
378
|
+
if (!changes.empty) {
|
|
379
|
+
semaphore.reconcile(view);
|
|
380
|
+
}
|
|
381
|
+
}),
|
|
382
|
+
state
|
|
383
|
+
];
|
|
364
384
|
};
|
|
365
385
|
|
|
366
386
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
367
|
-
import { Annotation as Annotation2, Facet as
|
|
368
|
-
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
387
|
+
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
388
|
+
import { Decoration, EditorView as EditorView2, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
389
|
+
import { useEffect } from "react";
|
|
369
390
|
import { Event } from "@dxos/async";
|
|
370
391
|
import { Context } from "@dxos/context";
|
|
392
|
+
import { generateName } from "@dxos/display-name";
|
|
393
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
394
|
+
import { getColorForValue } from "@dxos/react-ui-theme";
|
|
371
395
|
var dummyProvider = {
|
|
372
396
|
remoteStateChange: new Event(),
|
|
373
397
|
open: () => {
|
|
@@ -378,7 +402,7 @@ var dummyProvider = {
|
|
|
378
402
|
},
|
|
379
403
|
getRemoteStates: () => []
|
|
380
404
|
};
|
|
381
|
-
var AwarenessProvider =
|
|
405
|
+
var AwarenessProvider = Facet2.define({
|
|
382
406
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
383
407
|
});
|
|
384
408
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
@@ -391,13 +415,36 @@ var awareness = (provider = dummyProvider) => {
|
|
|
391
415
|
styles
|
|
392
416
|
];
|
|
393
417
|
};
|
|
418
|
+
var useAwareness = ({ awareness: awareness2, peer }) => {
|
|
419
|
+
const { themeMode } = useThemeContext();
|
|
420
|
+
useEffect(() => {
|
|
421
|
+
if (awareness2 && peer) {
|
|
422
|
+
awareness2.setLocalStateField("user", {
|
|
423
|
+
name: peer.name ?? generateName(peer.id),
|
|
424
|
+
color: getColorForValue({
|
|
425
|
+
value: peer.id,
|
|
426
|
+
type: "color"
|
|
427
|
+
}),
|
|
428
|
+
colorLight: getColorForValue({
|
|
429
|
+
value: peer.id,
|
|
430
|
+
themeMode,
|
|
431
|
+
type: "highlight"
|
|
432
|
+
})
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}, [
|
|
436
|
+
awareness2,
|
|
437
|
+
peer,
|
|
438
|
+
themeMode
|
|
439
|
+
]);
|
|
440
|
+
};
|
|
394
441
|
var RemoteSelectionsDecorator = class {
|
|
395
442
|
constructor(view) {
|
|
396
443
|
this.decorations = RangeSet.of([]);
|
|
397
444
|
this._ctx = new Context();
|
|
398
445
|
this._lastAnchor = void 0;
|
|
399
446
|
this._lastHead = void 0;
|
|
400
|
-
this._cursorConverter = view.state.facet(
|
|
447
|
+
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
401
448
|
this._provider = view.state.facet(AwarenessProvider);
|
|
402
449
|
this._provider.open();
|
|
403
450
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
@@ -452,7 +499,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
452
499
|
attributes: {
|
|
453
500
|
style: `background-color: ${lightColor}`
|
|
454
501
|
},
|
|
455
|
-
class: "cm-
|
|
502
|
+
class: "cm-collab-selection"
|
|
456
503
|
})
|
|
457
504
|
});
|
|
458
505
|
} else {
|
|
@@ -463,7 +510,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
463
510
|
attributes: {
|
|
464
511
|
style: `background-color: ${color}`
|
|
465
512
|
},
|
|
466
|
-
class: "cm-
|
|
513
|
+
class: "cm-collab-selection"
|
|
467
514
|
})
|
|
468
515
|
});
|
|
469
516
|
decorations.push({
|
|
@@ -473,7 +520,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
473
520
|
attributes: {
|
|
474
521
|
style: `background-color: ${color}`
|
|
475
522
|
},
|
|
476
|
-
class: "cm-
|
|
523
|
+
class: "cm-collab-selection"
|
|
477
524
|
})
|
|
478
525
|
});
|
|
479
526
|
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
@@ -484,7 +531,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
484
531
|
value: Decoration.line({
|
|
485
532
|
attributes: {
|
|
486
533
|
style: `background-color: ${color}`,
|
|
487
|
-
class: "cm-
|
|
534
|
+
class: "cm-collab-selectionLine"
|
|
488
535
|
}
|
|
489
536
|
})
|
|
490
537
|
});
|
|
@@ -504,23 +551,21 @@ var RemoteSelectionsDecorator = class {
|
|
|
504
551
|
}
|
|
505
552
|
};
|
|
506
553
|
var RemoteCaretWidget = class extends WidgetType {
|
|
507
|
-
constructor(
|
|
554
|
+
constructor(_name, _color) {
|
|
508
555
|
super();
|
|
509
|
-
this.
|
|
510
|
-
this.
|
|
511
|
-
this.name = name;
|
|
512
|
-
this.color = color;
|
|
556
|
+
this._name = _name;
|
|
557
|
+
this._color = _color;
|
|
513
558
|
}
|
|
514
559
|
toDOM() {
|
|
515
560
|
const span = document.createElement("span");
|
|
516
|
-
span.className = "cm-
|
|
517
|
-
span.style.backgroundColor = this.
|
|
518
|
-
span.style.borderColor = this.
|
|
561
|
+
span.className = "cm-collab-selectionCaret";
|
|
562
|
+
span.style.backgroundColor = this._color;
|
|
563
|
+
span.style.borderColor = this._color;
|
|
519
564
|
const dot = document.createElement("div");
|
|
520
|
-
dot.className = "cm-
|
|
565
|
+
dot.className = "cm-collab-selectionCaretDot";
|
|
521
566
|
const info = document.createElement("div");
|
|
522
|
-
info.className = "cm-
|
|
523
|
-
info.innerText = this.
|
|
567
|
+
info.className = "cm-collab-selectionInfo";
|
|
568
|
+
info.innerText = this._name;
|
|
524
569
|
span.appendChild(document.createTextNode("\u2060"));
|
|
525
570
|
span.appendChild(dot);
|
|
526
571
|
span.appendChild(document.createTextNode("\u2060"));
|
|
@@ -528,15 +573,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
528
573
|
span.appendChild(document.createTextNode("\u2060"));
|
|
529
574
|
return span;
|
|
530
575
|
}
|
|
531
|
-
eq(widget) {
|
|
532
|
-
return widget.color === this.color;
|
|
533
|
-
}
|
|
534
|
-
compare(widget) {
|
|
535
|
-
return widget.color === this.color;
|
|
536
|
-
}
|
|
537
576
|
updateDOM() {
|
|
538
577
|
return false;
|
|
539
578
|
}
|
|
579
|
+
eq(widget) {
|
|
580
|
+
return widget._color === this._color;
|
|
581
|
+
}
|
|
540
582
|
get estimatedHeight() {
|
|
541
583
|
return -1;
|
|
542
584
|
}
|
|
@@ -544,13 +586,13 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
544
586
|
return true;
|
|
545
587
|
}
|
|
546
588
|
};
|
|
547
|
-
var styles =
|
|
548
|
-
".cm-
|
|
549
|
-
".cm-
|
|
589
|
+
var styles = EditorView2.baseTheme({
|
|
590
|
+
".cm-collab-selection": {},
|
|
591
|
+
".cm-collab-selectionLine": {
|
|
550
592
|
padding: 0,
|
|
551
593
|
margin: "0px 2px 0px 4px"
|
|
552
594
|
},
|
|
553
|
-
".cm-
|
|
595
|
+
".cm-collab-selectionCaret": {
|
|
554
596
|
position: "relative",
|
|
555
597
|
borderLeft: "1px solid black",
|
|
556
598
|
borderRight: "1px solid black",
|
|
@@ -559,7 +601,7 @@ var styles = EditorView.baseTheme({
|
|
|
559
601
|
boxSizing: "border-box",
|
|
560
602
|
display: "inline"
|
|
561
603
|
},
|
|
562
|
-
".cm-
|
|
604
|
+
".cm-collab-selectionCaretDot": {
|
|
563
605
|
borderRadius: "50%",
|
|
564
606
|
position: "absolute",
|
|
565
607
|
width: ".4em",
|
|
@@ -570,11 +612,11 @@ var styles = EditorView.baseTheme({
|
|
|
570
612
|
transition: "transform .3s ease-in-out",
|
|
571
613
|
boxSizing: "border-box"
|
|
572
614
|
},
|
|
573
|
-
".cm-
|
|
615
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
574
616
|
transformOrigin: "bottom center",
|
|
575
617
|
transform: "scale(0)"
|
|
576
618
|
},
|
|
577
|
-
".cm-
|
|
619
|
+
".cm-collab-selectionInfo": {
|
|
578
620
|
position: "absolute",
|
|
579
621
|
top: "-1.05em",
|
|
580
622
|
left: "-1px",
|
|
@@ -590,12 +632,12 @@ var styles = EditorView.baseTheme({
|
|
|
590
632
|
zIndex: 101,
|
|
591
633
|
transition: "opacity .3s ease-in-out",
|
|
592
634
|
backgroundColor: "inherit",
|
|
593
|
-
//
|
|
635
|
+
// These should be separate.
|
|
594
636
|
opacity: 0,
|
|
595
637
|
transitionDelay: "0s",
|
|
596
638
|
whiteSpace: "nowrap"
|
|
597
639
|
},
|
|
598
|
-
".cm-
|
|
640
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionInfo": {
|
|
599
641
|
opacity: 1,
|
|
600
642
|
transitionDelay: "0s"
|
|
601
643
|
}
|
|
@@ -603,25 +645,27 @@ var styles = EditorView.baseTheme({
|
|
|
603
645
|
|
|
604
646
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
605
647
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
648
|
+
import { history } from "@codemirror/commands";
|
|
606
649
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
607
650
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
608
|
-
import { drawSelection, EditorView as
|
|
609
|
-
var basicBundle = ({
|
|
610
|
-
|
|
611
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
651
|
+
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
652
|
+
var basicBundle = ({ themeMode, placeholder: _placeholder, multiline = true }) => [
|
|
653
|
+
multiline ? EditorView3.lineWrapping : [],
|
|
612
654
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
613
655
|
bracketMatching(),
|
|
614
656
|
closeBrackets(),
|
|
615
657
|
drawSelection(),
|
|
616
|
-
|
|
617
|
-
|
|
658
|
+
highlightActiveLine(),
|
|
659
|
+
history(),
|
|
660
|
+
_placeholder ? placeholder(_placeholder) : [],
|
|
661
|
+
// https://github.com/codemirror/theme-one-dark
|
|
618
662
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
619
|
-
]
|
|
663
|
+
];
|
|
620
664
|
|
|
621
665
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
622
|
-
import { EditorView as
|
|
666
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
623
667
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
624
|
-
import { invariant } from "@dxos/invariant";
|
|
668
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
625
669
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
626
670
|
var defaultOptions = {
|
|
627
671
|
effect: 2,
|
|
@@ -667,7 +711,7 @@ var blast = (options = defaultOptions) => {
|
|
|
667
711
|
};
|
|
668
712
|
return [
|
|
669
713
|
// Cursor moved.
|
|
670
|
-
|
|
714
|
+
EditorView4.updateListener.of((update2) => {
|
|
671
715
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
672
716
|
if (blaster) {
|
|
673
717
|
blaster.destroy();
|
|
@@ -748,7 +792,7 @@ var Blaster = class {
|
|
|
748
792
|
return this._node;
|
|
749
793
|
}
|
|
750
794
|
initialize() {
|
|
751
|
-
|
|
795
|
+
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
752
796
|
F: __dxlog_file2,
|
|
753
797
|
L: 138,
|
|
754
798
|
S: this,
|
|
@@ -785,7 +829,7 @@ var Blaster = class {
|
|
|
785
829
|
}
|
|
786
830
|
}
|
|
787
831
|
start() {
|
|
788
|
-
|
|
832
|
+
invariant2(this._canvas && this._ctx, void 0, {
|
|
789
833
|
F: __dxlog_file2,
|
|
790
834
|
L: 177,
|
|
791
835
|
S: this,
|
|
@@ -929,7 +973,7 @@ var random = (min, max) => {
|
|
|
929
973
|
};
|
|
930
974
|
|
|
931
975
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
932
|
-
import { ViewPlugin as ViewPlugin3, EditorView as
|
|
976
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView5, Decoration as Decoration2 } from "@codemirror/view";
|
|
933
977
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
934
978
|
|
|
935
979
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1020,7 +1064,7 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
|
|
|
1020
1064
|
|
|
1021
1065
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1022
1066
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1023
|
-
var styles2 =
|
|
1067
|
+
var styles2 = EditorView5.baseTheme({
|
|
1024
1068
|
"& .cm-codeblock": {
|
|
1025
1069
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1026
1070
|
},
|
|
@@ -1054,20 +1098,18 @@ var getLineRange = (lines, from, to) => {
|
|
|
1054
1098
|
];
|
|
1055
1099
|
};
|
|
1056
1100
|
var code2 = () => {
|
|
1057
|
-
const
|
|
1101
|
+
const buildDecorations5 = (view) => {
|
|
1058
1102
|
const decorations = [];
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
}).range(block.from));
|
|
1070
|
-
}
|
|
1103
|
+
const text = view.state.doc.sliceString(0);
|
|
1104
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1105
|
+
const blocks = view.viewportLineBlocks;
|
|
1106
|
+
for (const match of matches) {
|
|
1107
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1108
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1109
|
+
const block = blocks[i];
|
|
1110
|
+
decorations.push(Decoration2.line({
|
|
1111
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1112
|
+
}).range(block.from));
|
|
1071
1113
|
}
|
|
1072
1114
|
}
|
|
1073
1115
|
return Decoration2.set(decorations);
|
|
@@ -1075,11 +1117,16 @@ var code2 = () => {
|
|
|
1075
1117
|
return [
|
|
1076
1118
|
ViewPlugin3.fromClass(class {
|
|
1077
1119
|
constructor(view) {
|
|
1078
|
-
this.
|
|
1120
|
+
this.hasFocus = false;
|
|
1121
|
+
this.decorations = buildDecorations5(view);
|
|
1079
1122
|
}
|
|
1080
1123
|
update(update2) {
|
|
1081
|
-
if (
|
|
1082
|
-
|
|
1124
|
+
if (
|
|
1125
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1126
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1127
|
+
) {
|
|
1128
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1129
|
+
this.decorations = buildDecorations5(update2.view);
|
|
1083
1130
|
}
|
|
1084
1131
|
}
|
|
1085
1132
|
}, {
|
|
@@ -1091,23 +1138,51 @@ var code2 = () => {
|
|
|
1091
1138
|
|
|
1092
1139
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1093
1140
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1094
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as
|
|
1141
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
|
|
1095
1142
|
import sortBy from "lodash.sortby";
|
|
1143
|
+
import { useEffect as useEffect2 } from "react";
|
|
1096
1144
|
import { debounce } from "@dxos/async";
|
|
1097
|
-
import { invariant as
|
|
1098
|
-
import { log as log2 } from "@dxos/log";
|
|
1145
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1099
1146
|
import { nonNullable } from "@dxos/util";
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1147
|
+
|
|
1148
|
+
// packages/ui/react-ui-editor/src/util.ts
|
|
1149
|
+
import { log } from "@dxos/log";
|
|
1150
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1151
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
1152
|
+
try {
|
|
1153
|
+
return fn(...args);
|
|
1154
|
+
} catch (err) {
|
|
1155
|
+
log.catch(err, void 0, {
|
|
1156
|
+
F: __dxlog_file3,
|
|
1157
|
+
L: 18,
|
|
1158
|
+
S: void 0,
|
|
1159
|
+
C: (f, a) => f(...a)
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
var logChanges = (trs) => {
|
|
1164
|
+
const changes = trs.flatMap((tr) => {
|
|
1165
|
+
if (tr.changes.empty) {
|
|
1166
|
+
return void 0;
|
|
1167
|
+
}
|
|
1168
|
+
const changes2 = [];
|
|
1169
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1170
|
+
fromA,
|
|
1171
|
+
toA,
|
|
1172
|
+
fromB,
|
|
1173
|
+
toB,
|
|
1174
|
+
inserted: inserted.toString()
|
|
1175
|
+
})));
|
|
1176
|
+
return changes2;
|
|
1177
|
+
}).filter(Boolean);
|
|
1178
|
+
if (changes.length) {
|
|
1179
|
+
console.log("changes", changes);
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1184
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1185
|
+
var styles3 = EditorView6.baseTheme({
|
|
1111
1186
|
"& .cm-comment": {
|
|
1112
1187
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1113
1188
|
},
|
|
@@ -1123,49 +1198,59 @@ var marks = {
|
|
|
1123
1198
|
class: "cm-comment-active"
|
|
1124
1199
|
})
|
|
1125
1200
|
};
|
|
1126
|
-
var setFocus = (view,
|
|
1127
|
-
const
|
|
1128
|
-
if (!
|
|
1201
|
+
var setFocus = (view, id, center = true) => {
|
|
1202
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1203
|
+
if (!comment?.comment.cursor) {
|
|
1129
1204
|
return;
|
|
1130
1205
|
}
|
|
1131
|
-
view.
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1206
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1207
|
+
if (range) {
|
|
1208
|
+
view.dispatch({
|
|
1209
|
+
selection: {
|
|
1210
|
+
anchor: range.from
|
|
1211
|
+
},
|
|
1212
|
+
effects: [
|
|
1213
|
+
//
|
|
1214
|
+
EditorView6.scrollIntoView(range.from, center ? {
|
|
1215
|
+
y: "center"
|
|
1216
|
+
} : void 0),
|
|
1217
|
+
setSelection.of({
|
|
1218
|
+
active: id
|
|
1219
|
+
})
|
|
1220
|
+
]
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1140
1223
|
};
|
|
1141
|
-
var
|
|
1224
|
+
var setComments = StateEffect2.define();
|
|
1142
1225
|
var setSelection = StateEffect2.define();
|
|
1143
1226
|
var setCommentState = StateEffect2.define();
|
|
1144
|
-
var
|
|
1227
|
+
var commentsState = StateField2.define({
|
|
1145
1228
|
create: () => ({
|
|
1146
|
-
|
|
1229
|
+
comments: [],
|
|
1230
|
+
selection: {}
|
|
1147
1231
|
}),
|
|
1148
1232
|
update: (value, tr) => {
|
|
1149
|
-
const cursorConverter3 = tr.state.facet(CursorConverter);
|
|
1150
1233
|
for (const effect of tr.effects) {
|
|
1151
1234
|
if (effect.is(setSelection)) {
|
|
1152
1235
|
return {
|
|
1153
1236
|
...value,
|
|
1154
|
-
|
|
1237
|
+
selection: effect.value
|
|
1155
1238
|
};
|
|
1156
1239
|
}
|
|
1157
|
-
if (effect.is(
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
|
|
1240
|
+
if (effect.is(setComments)) {
|
|
1241
|
+
const comments2 = effect.value.map((comment) => {
|
|
1242
|
+
if (!comment.cursor) {
|
|
1243
|
+
return void 0;
|
|
1244
|
+
}
|
|
1245
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1161
1246
|
return range && {
|
|
1162
|
-
|
|
1163
|
-
|
|
1247
|
+
comment,
|
|
1248
|
+
range
|
|
1164
1249
|
};
|
|
1165
1250
|
}).filter(nonNullable);
|
|
1166
1251
|
return {
|
|
1167
1252
|
...value,
|
|
1168
|
-
|
|
1253
|
+
comments: comments2
|
|
1169
1254
|
};
|
|
1170
1255
|
}
|
|
1171
1256
|
if (effect.is(setCommentState)) {
|
|
@@ -1175,78 +1260,109 @@ var commentsStateField = StateField2.define({
|
|
|
1175
1260
|
return value;
|
|
1176
1261
|
}
|
|
1177
1262
|
});
|
|
1178
|
-
var highlightDecorations =
|
|
1179
|
-
|
|
1263
|
+
var highlightDecorations = EditorView6.decorations.compute([
|
|
1264
|
+
commentsState
|
|
1180
1265
|
], (state) => {
|
|
1181
|
-
const { active,
|
|
1182
|
-
const decorations = sortBy(
|
|
1183
|
-
|
|
1266
|
+
const { selection: { active }, comments: comments2 } = state.field(commentsState);
|
|
1267
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1268
|
+
const range = comment.range;
|
|
1269
|
+
if (!range || range.from === range.to) {
|
|
1270
|
+
console.warn("Invalid range:", range);
|
|
1184
1271
|
return void 0;
|
|
1185
1272
|
}
|
|
1186
|
-
|
|
1187
|
-
from: selection.from,
|
|
1188
|
-
to: selection.to
|
|
1189
|
-
};
|
|
1190
|
-
if (selection.id === active) {
|
|
1273
|
+
if (comment.comment.id === active) {
|
|
1191
1274
|
return marks.highlightActive.range(range.from, range.to);
|
|
1192
1275
|
} else {
|
|
1193
1276
|
return marks.highlight.range(range.from, range.to);
|
|
1194
1277
|
}
|
|
1195
|
-
}).filter(nonNullable)
|
|
1278
|
+
}).filter(nonNullable);
|
|
1196
1279
|
return Decoration3.set(decorations);
|
|
1197
1280
|
});
|
|
1198
|
-
var
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
return this._anchor === other._anchor && this._id === other._id;
|
|
1216
|
-
}
|
|
1217
|
-
toDOM() {
|
|
1218
|
-
const span = document.createElement("span");
|
|
1219
|
-
span.className = "cm-bookmark";
|
|
1220
|
-
span.textContent = "\u203B";
|
|
1221
|
-
if (this._handleClick) {
|
|
1222
|
-
span.onclick = () => this._handleClick();
|
|
1281
|
+
var trackPastedComments = (onUpdate) => {
|
|
1282
|
+
let tracked = null;
|
|
1283
|
+
const handleTrack = (event, view) => {
|
|
1284
|
+
const comments2 = view.state.field(commentsState);
|
|
1285
|
+
const { main } = view.state.selection;
|
|
1286
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1287
|
+
if (!selectedRanges.length) {
|
|
1288
|
+
tracked = null;
|
|
1289
|
+
} else {
|
|
1290
|
+
tracked = {
|
|
1291
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1292
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1293
|
+
id: comment.id,
|
|
1294
|
+
from: range.from - main.from,
|
|
1295
|
+
to: range.to - main.from
|
|
1296
|
+
}))
|
|
1297
|
+
};
|
|
1223
1298
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1299
|
+
};
|
|
1300
|
+
return [
|
|
1301
|
+
EditorView6.domEventHandlers({
|
|
1302
|
+
cut: handleTrack,
|
|
1303
|
+
copy: handleTrack
|
|
1304
|
+
}),
|
|
1305
|
+
// Handle paste.
|
|
1306
|
+
EditorView6.updateListener.of(({ view, state, transactions }) => {
|
|
1307
|
+
if (tracked) {
|
|
1308
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1309
|
+
if (paste) {
|
|
1310
|
+
let found = -1;
|
|
1311
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1312
|
+
if (text.eq(tracked.text)) {
|
|
1313
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1314
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1315
|
+
}
|
|
1316
|
+
found = fromB;
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
if (found > -1) {
|
|
1320
|
+
for (const moved of tracked.comments) {
|
|
1321
|
+
const range = {
|
|
1322
|
+
from: found + moved.from,
|
|
1323
|
+
to: found + moved.to
|
|
1324
|
+
};
|
|
1325
|
+
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1326
|
+
onUpdate(moved.id, cursor);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
tracked = null;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
})
|
|
1333
|
+
];
|
|
1226
1334
|
};
|
|
1227
1335
|
var comments = (options = {}) => {
|
|
1336
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1228
1337
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
1338
|
const createCommentThread = (view) => {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
L: 224,
|
|
1339
|
+
invariant3(options.onCreate, void 0, {
|
|
1340
|
+
F: __dxlog_file4,
|
|
1341
|
+
L: 259,
|
|
1234
1342
|
S: void 0,
|
|
1235
1343
|
A: [
|
|
1236
1344
|
"options.onCreate",
|
|
1237
1345
|
""
|
|
1238
1346
|
]
|
|
1239
1347
|
});
|
|
1240
|
-
const {
|
|
1348
|
+
const { from, to } = view.state.selection.main;
|
|
1241
1349
|
if (from === to) {
|
|
1242
1350
|
return false;
|
|
1243
1351
|
}
|
|
1244
|
-
|
|
1352
|
+
if (to === view.state.doc.length) {
|
|
1353
|
+
view.dispatch({
|
|
1354
|
+
changes: {
|
|
1355
|
+
from: to,
|
|
1356
|
+
insert: "\n"
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1245
1361
|
from,
|
|
1246
1362
|
to
|
|
1247
1363
|
});
|
|
1248
|
-
if (
|
|
1249
|
-
const id =
|
|
1364
|
+
if (cursor) {
|
|
1365
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1250
1366
|
if (id) {
|
|
1251
1367
|
view.dispatch({
|
|
1252
1368
|
effects: setSelection.of({
|
|
@@ -1256,53 +1372,13 @@ var comments = (options = {}) => {
|
|
|
1256
1372
|
anchor: from
|
|
1257
1373
|
}
|
|
1258
1374
|
});
|
|
1259
|
-
if (options.footnote) {
|
|
1260
|
-
const tag = `[^${id}]`;
|
|
1261
|
-
view.dispatch({
|
|
1262
|
-
changes: {
|
|
1263
|
-
from: head,
|
|
1264
|
-
insert: tag
|
|
1265
|
-
},
|
|
1266
|
-
selection: {
|
|
1267
|
-
anchor: head + tag.length
|
|
1268
|
-
}
|
|
1269
|
-
});
|
|
1270
|
-
}
|
|
1271
1375
|
return true;
|
|
1272
1376
|
}
|
|
1273
1377
|
}
|
|
1274
1378
|
return false;
|
|
1275
1379
|
};
|
|
1276
|
-
const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
|
|
1277
|
-
static {
|
|
1278
|
-
// Match markdown footnotes (option).
|
|
1279
|
-
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
1280
|
-
this.bookmarkMatcher = new MatchDecorator({
|
|
1281
|
-
regexp: /\[\^(\w+)\]/g,
|
|
1282
|
-
decoration: (match, view, pos) => {
|
|
1283
|
-
const id = match[1];
|
|
1284
|
-
return Decoration3.replace({
|
|
1285
|
-
id,
|
|
1286
|
-
widget: new BookmarkWidget(pos, id)
|
|
1287
|
-
});
|
|
1288
|
-
}
|
|
1289
|
-
});
|
|
1290
|
-
}
|
|
1291
|
-
constructor(view) {
|
|
1292
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
1293
|
-
}
|
|
1294
|
-
update(update2) {
|
|
1295
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update2, this.bookmarks);
|
|
1296
|
-
}
|
|
1297
|
-
}, {
|
|
1298
|
-
decorations: (instance) => instance.bookmarks,
|
|
1299
|
-
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1300
|
-
return view.plugin(plugin)?.bookmarks || Decoration3.none;
|
|
1301
|
-
})
|
|
1302
|
-
});
|
|
1303
1380
|
return [
|
|
1304
|
-
|
|
1305
|
-
commentsStateField,
|
|
1381
|
+
commentsState,
|
|
1306
1382
|
highlightDecorations,
|
|
1307
1383
|
styles3,
|
|
1308
1384
|
//
|
|
@@ -1310,7 +1386,7 @@ var comments = (options = {}) => {
|
|
|
1310
1386
|
//
|
|
1311
1387
|
options.onCreate ? keymap3.of([
|
|
1312
1388
|
{
|
|
1313
|
-
key:
|
|
1389
|
+
key: shortcut,
|
|
1314
1390
|
run: callbackWrapper(createCommentThread)
|
|
1315
1391
|
}
|
|
1316
1392
|
]) : [],
|
|
@@ -1327,7 +1403,7 @@ var comments = (options = {}) => {
|
|
|
1327
1403
|
above: true,
|
|
1328
1404
|
create: () => {
|
|
1329
1405
|
const el = document.createElement("div");
|
|
1330
|
-
options.onHover
|
|
1406
|
+
options.onHover(el, shortcut);
|
|
1331
1407
|
return {
|
|
1332
1408
|
dom: el,
|
|
1333
1409
|
offset: {
|
|
@@ -1340,156 +1416,154 @@ var comments = (options = {}) => {
|
|
|
1340
1416
|
}
|
|
1341
1417
|
return null;
|
|
1342
1418
|
}, {
|
|
1343
|
-
|
|
1419
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1420
|
+
// hideOnChange: true,
|
|
1344
1421
|
hoverTime: 1e3
|
|
1345
1422
|
}) : [],
|
|
1346
1423
|
//
|
|
1347
|
-
//
|
|
1348
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1424
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1349
1425
|
//
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
{
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
1359
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
|
-
log2.info("deleted comment", {
|
|
1361
|
-
thread: range.id
|
|
1362
|
-
}, {
|
|
1363
|
-
F: __dxlog_file3,
|
|
1364
|
-
L: 358,
|
|
1365
|
-
S: void 0,
|
|
1366
|
-
C: (f, a) => f(...a)
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
if (from <= range.to) {
|
|
1371
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
|
-
Object.assign(range, newRange);
|
|
1373
|
-
mod = true;
|
|
1426
|
+
EditorView6.updateListener.of(({ view, state, changes }) => {
|
|
1427
|
+
let mod = false;
|
|
1428
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1429
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1430
|
+
comments2.forEach(({ comment, range }) => {
|
|
1431
|
+
if (from2 === to2) {
|
|
1432
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1433
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1434
|
+
options.onDelete?.(comment.id);
|
|
1374
1435
|
}
|
|
1375
|
-
}
|
|
1436
|
+
}
|
|
1437
|
+
if (from <= range.to) {
|
|
1438
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1439
|
+
Object.assign(range, newRange);
|
|
1440
|
+
mod = true;
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
});
|
|
1444
|
+
if (mod) {
|
|
1445
|
+
view.dispatch({
|
|
1446
|
+
effects: setCommentState.of({
|
|
1447
|
+
comments: comments2,
|
|
1448
|
+
...value
|
|
1449
|
+
})
|
|
1376
1450
|
});
|
|
1377
|
-
if (mod) {
|
|
1378
|
-
view.dispatch({
|
|
1379
|
-
effects: setCommentState.of({
|
|
1380
|
-
active,
|
|
1381
|
-
ranges
|
|
1382
|
-
})
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
1451
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1452
|
+
}),
|
|
1453
|
+
//
|
|
1454
|
+
// Track selection/proximity.
|
|
1455
|
+
//
|
|
1456
|
+
EditorView6.updateListener.of(({ view, state, changes }) => {
|
|
1457
|
+
let min = Infinity;
|
|
1458
|
+
const { selection: { active, closest }, comments: comments2 } = state.field(commentsState);
|
|
1459
|
+
const { head } = state.selection.main;
|
|
1460
|
+
const selection = {};
|
|
1461
|
+
comments2.forEach(({ comment, range }) => {
|
|
1462
|
+
if (head >= range.from && head <= range.to) {
|
|
1463
|
+
selection.active = comment.id;
|
|
1464
|
+
selection.closest = void 0;
|
|
1465
|
+
}
|
|
1466
|
+
if (!selection.active) {
|
|
1467
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1399
1468
|
if (d < min) {
|
|
1400
|
-
|
|
1469
|
+
selection.closest = comment.id;
|
|
1401
1470
|
min = d;
|
|
1402
1471
|
}
|
|
1403
|
-
});
|
|
1404
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1405
|
-
view.dispatch({
|
|
1406
|
-
effects: setSelection.of(selected)
|
|
1407
|
-
});
|
|
1408
|
-
handleSelect({
|
|
1409
|
-
...selected,
|
|
1410
|
-
ranges: ranges.map((range) => ({
|
|
1411
|
-
...range,
|
|
1412
|
-
location: view.coordsAtPos(range.from)
|
|
1413
|
-
}))
|
|
1414
|
-
});
|
|
1415
1472
|
}
|
|
1473
|
+
});
|
|
1474
|
+
if (selection.active !== active || selection.closest !== closest) {
|
|
1475
|
+
view.dispatch({
|
|
1476
|
+
effects: setSelection.of(selection)
|
|
1477
|
+
});
|
|
1478
|
+
handleSelect({
|
|
1479
|
+
selection,
|
|
1480
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1481
|
+
comment,
|
|
1482
|
+
range,
|
|
1483
|
+
location: view.coordsAtPos(range.from)
|
|
1484
|
+
}))
|
|
1485
|
+
});
|
|
1416
1486
|
}
|
|
1417
|
-
})
|
|
1487
|
+
}),
|
|
1488
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1418
1489
|
];
|
|
1419
1490
|
};
|
|
1420
|
-
var
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1432
|
-
return from !== void 0 && to !== void 0 ? {
|
|
1433
|
-
from,
|
|
1434
|
-
to
|
|
1435
|
-
} : void 0;
|
|
1491
|
+
var useComments = (view, comments2) => {
|
|
1492
|
+
useEffect2(() => {
|
|
1493
|
+
if (view && comments2) {
|
|
1494
|
+
view.dispatch({
|
|
1495
|
+
effects: setComments.of(comments2)
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
}, [
|
|
1499
|
+
view,
|
|
1500
|
+
comments2
|
|
1501
|
+
]);
|
|
1436
1502
|
};
|
|
1437
1503
|
|
|
1438
1504
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
-
import {
|
|
1440
|
-
|
|
1505
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1506
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1507
|
+
import { Decoration as Decoration4, EditorView as EditorView7, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1508
|
+
var styles4 = EditorView7.baseTheme({
|
|
1441
1509
|
"& .cm-hr": {
|
|
1442
|
-
// TODO(burdon): ???
|
|
1443
1510
|
// Note that block-level decorations should not have vertical margins,
|
|
1444
|
-
|
|
1511
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1445
1512
|
}
|
|
1446
1513
|
});
|
|
1447
|
-
var HorizontalRuleWidget = class extends
|
|
1448
|
-
|
|
1449
|
-
super();
|
|
1450
|
-
this._pos = _pos;
|
|
1451
|
-
}
|
|
1452
|
-
eq(other) {
|
|
1453
|
-
return this._pos === other._pos;
|
|
1454
|
-
}
|
|
1455
|
-
toDOM(view) {
|
|
1514
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1515
|
+
toDOM() {
|
|
1456
1516
|
const el = document.createElement("div");
|
|
1457
1517
|
el.className = "cm-hr";
|
|
1458
1518
|
return el;
|
|
1459
1519
|
}
|
|
1460
1520
|
};
|
|
1461
|
-
var
|
|
1462
|
-
|
|
1463
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1464
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1465
|
-
})
|
|
1521
|
+
var decoration = Decoration4.replace({
|
|
1522
|
+
widget: new HorizontalRuleWidget()
|
|
1466
1523
|
});
|
|
1467
|
-
var
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1524
|
+
var buildDecorations = (view) => {
|
|
1525
|
+
const builder = new RangeSetBuilder();
|
|
1526
|
+
const { state } = view;
|
|
1527
|
+
const cursor = state.selection.main.head;
|
|
1528
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1529
|
+
syntaxTree(state).iterate({
|
|
1530
|
+
enter: (node) => {
|
|
1531
|
+
if (node.name === "HorizontalRule") {
|
|
1532
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1533
|
+
builder.add(node.from, node.to, decoration);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
},
|
|
1537
|
+
from,
|
|
1538
|
+
to
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
return builder.finish();
|
|
1542
|
+
};
|
|
1543
|
+
var hr = () => {
|
|
1544
|
+
return [
|
|
1545
|
+
styles4,
|
|
1546
|
+
ViewPlugin4.fromClass(class {
|
|
1547
|
+
constructor(view) {
|
|
1548
|
+
this.decorations = buildDecorations(view);
|
|
1549
|
+
}
|
|
1550
|
+
update(update2) {
|
|
1551
|
+
this.decorations = buildDecorations(update2.view);
|
|
1552
|
+
}
|
|
1553
|
+
}, {
|
|
1554
|
+
decorations: (v) => v.decorations
|
|
1481
1555
|
})
|
|
1482
|
-
|
|
1483
|
-
|
|
1556
|
+
];
|
|
1557
|
+
};
|
|
1484
1558
|
|
|
1485
1559
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1486
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1560
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1487
1561
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
1488
|
-
import { Decoration as Decoration5, EditorView as
|
|
1562
|
+
import { Decoration as Decoration5, EditorView as EditorView8, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1489
1563
|
var image = (options = {}) => {
|
|
1490
1564
|
return StateField3.define({
|
|
1491
1565
|
create: (state) => {
|
|
1492
|
-
return Decoration5.set(
|
|
1566
|
+
return Decoration5.set(buildDecorations2(0, state.doc.length, state));
|
|
1493
1567
|
},
|
|
1494
1568
|
update: (value, tr) => {
|
|
1495
1569
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -1509,16 +1583,16 @@ var image = (options = {}) => {
|
|
|
1509
1583
|
filterFrom: from,
|
|
1510
1584
|
filterTo: to,
|
|
1511
1585
|
filter: () => false,
|
|
1512
|
-
add:
|
|
1586
|
+
add: buildDecorations2(from, to, tr.state)
|
|
1513
1587
|
});
|
|
1514
1588
|
},
|
|
1515
|
-
provide: (field) =>
|
|
1589
|
+
provide: (field) => EditorView8.decorations.from(field)
|
|
1516
1590
|
});
|
|
1517
1591
|
};
|
|
1518
|
-
var
|
|
1592
|
+
var buildDecorations2 = (from, to, state) => {
|
|
1519
1593
|
const decorations = [];
|
|
1520
1594
|
const cursor = state.selection.main.head;
|
|
1521
|
-
|
|
1595
|
+
syntaxTree2(state).iterate({
|
|
1522
1596
|
enter: (node) => {
|
|
1523
1597
|
if (node.name === "Image") {
|
|
1524
1598
|
const urlNode = node.node.getChild("URL");
|
|
@@ -1537,7 +1611,7 @@ var buildDecorations = (from, to, state) => {
|
|
|
1537
1611
|
});
|
|
1538
1612
|
return decorations;
|
|
1539
1613
|
};
|
|
1540
|
-
var ImageWidget = class extends
|
|
1614
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1541
1615
|
constructor(_url) {
|
|
1542
1616
|
super();
|
|
1543
1617
|
this._url = _url;
|
|
@@ -1555,19 +1629,19 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1555
1629
|
};
|
|
1556
1630
|
|
|
1557
1631
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1558
|
-
import { syntaxTree as
|
|
1559
|
-
import { RangeSetBuilder } from "@codemirror/state";
|
|
1560
|
-
import {
|
|
1632
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1633
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1634
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1561
1635
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1562
1636
|
var link = (options = {}) => {
|
|
1563
1637
|
const extensions = [
|
|
1564
|
-
|
|
1638
|
+
ViewPlugin5.fromClass(class {
|
|
1565
1639
|
constructor(view) {
|
|
1566
|
-
this.decorations =
|
|
1640
|
+
this.decorations = buildDecorations3(view, options);
|
|
1567
1641
|
}
|
|
1568
1642
|
update(update2) {
|
|
1569
1643
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1570
|
-
this.decorations =
|
|
1644
|
+
this.decorations = buildDecorations3(update2.view, options);
|
|
1571
1645
|
}
|
|
1572
1646
|
}
|
|
1573
1647
|
}, {
|
|
@@ -1580,7 +1654,7 @@ var link = (options = {}) => {
|
|
|
1580
1654
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1581
1655
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1582
1656
|
hoverTooltip2((view, pos, side) => {
|
|
1583
|
-
const syntax =
|
|
1657
|
+
const syntax = syntaxTree3(view.state).resolveInner(pos, side);
|
|
1584
1658
|
let link2 = null;
|
|
1585
1659
|
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1586
1660
|
link2 = node.name === "Link" ? node : null;
|
|
@@ -1612,7 +1686,7 @@ var link = (options = {}) => {
|
|
|
1612
1686
|
}
|
|
1613
1687
|
return extensions;
|
|
1614
1688
|
};
|
|
1615
|
-
var LinkButton = class extends
|
|
1689
|
+
var LinkButton = class extends WidgetType4 {
|
|
1616
1690
|
constructor(_url, _onAttach) {
|
|
1617
1691
|
super();
|
|
1618
1692
|
this._url = _url;
|
|
@@ -1627,7 +1701,7 @@ var LinkButton = class extends WidgetType5 {
|
|
|
1627
1701
|
return el;
|
|
1628
1702
|
}
|
|
1629
1703
|
};
|
|
1630
|
-
var LinkText = class extends
|
|
1704
|
+
var LinkText = class extends WidgetType4 {
|
|
1631
1705
|
constructor(_text, _url) {
|
|
1632
1706
|
super();
|
|
1633
1707
|
this._text = _text;
|
|
@@ -1656,12 +1730,12 @@ var LinkText = class extends WidgetType5 {
|
|
|
1656
1730
|
return link2;
|
|
1657
1731
|
}
|
|
1658
1732
|
};
|
|
1659
|
-
var
|
|
1660
|
-
const builder = new
|
|
1733
|
+
var buildDecorations3 = (view, options) => {
|
|
1734
|
+
const builder = new RangeSetBuilder2();
|
|
1661
1735
|
const { state } = view;
|
|
1662
1736
|
const cursor = state.selection.main.head;
|
|
1663
1737
|
for (const { from, to } of view.visibleRanges) {
|
|
1664
|
-
|
|
1738
|
+
syntaxTree3(state).iterate({
|
|
1665
1739
|
enter: (node) => {
|
|
1666
1740
|
if (node.name === "Link") {
|
|
1667
1741
|
const marks2 = node.node.getChildren("LinkMark");
|
|
@@ -1692,14 +1766,14 @@ var buildDecorations2 = (view, options) => {
|
|
|
1692
1766
|
};
|
|
1693
1767
|
|
|
1694
1768
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1695
|
-
import { EditorView as
|
|
1769
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1696
1770
|
var listener = ({ onFocus, onChange }) => {
|
|
1697
1771
|
const extensions = [];
|
|
1698
|
-
onFocus && extensions.push(
|
|
1772
|
+
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1699
1773
|
onFocus(focused);
|
|
1700
1774
|
return null;
|
|
1701
1775
|
}));
|
|
1702
|
-
onChange && extensions.push(
|
|
1776
|
+
onChange && extensions.push(EditorView9.updateListener.of((update2) => {
|
|
1703
1777
|
onChange(update2.state.doc.toString());
|
|
1704
1778
|
}));
|
|
1705
1779
|
return extensions;
|
|
@@ -1707,17 +1781,17 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1707
1781
|
|
|
1708
1782
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1709
1783
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1710
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1711
|
-
import { markdownLanguage as
|
|
1784
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1785
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1712
1786
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1713
1787
|
import { languages } from "@codemirror/language-data";
|
|
1714
1788
|
import { searchKeymap } from "@codemirror/search";
|
|
1715
1789
|
import { EditorState } from "@codemirror/state";
|
|
1716
1790
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1717
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1791
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1718
1792
|
|
|
1719
1793
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1720
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
1794
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1721
1795
|
import { HighlightStyle } from "@codemirror/language";
|
|
1722
1796
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1723
1797
|
import { Table } from "@lezer/markdown";
|
|
@@ -1727,7 +1801,6 @@ var markdownTags = {
|
|
|
1727
1801
|
CodeText: Tag.define(),
|
|
1728
1802
|
EmphasisMark: Tag.define(),
|
|
1729
1803
|
HeaderMark: Tag.define(),
|
|
1730
|
-
// HorizontalRule: Tag.define(),
|
|
1731
1804
|
InlineCode: Tag.define(),
|
|
1732
1805
|
LinkLabel: Tag.define(),
|
|
1733
1806
|
LinkReference: Tag.define(),
|
|
@@ -1891,12 +1964,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1891
1964
|
],
|
|
1892
1965
|
class: blockquote
|
|
1893
1966
|
},
|
|
1894
|
-
// TODO(burdon): Replace with extension.
|
|
1895
|
-
// {
|
|
1896
|
-
// tag: [markdownTags.HorizontalRule],
|
|
1897
|
-
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1898
|
-
// },
|
|
1899
|
-
// TODO(burdon): Only if being edited.
|
|
1900
1967
|
{
|
|
1901
1968
|
tag: [
|
|
1902
1969
|
markdownTags.TableCell
|
|
@@ -1904,7 +1971,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1904
1971
|
class: "font-mono"
|
|
1905
1972
|
}
|
|
1906
1973
|
], {
|
|
1907
|
-
scope:
|
|
1974
|
+
scope: markdownLanguage2,
|
|
1908
1975
|
all: {
|
|
1909
1976
|
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1910
1977
|
}
|
|
@@ -1916,17 +1983,17 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1916
1983
|
return [
|
|
1917
1984
|
EditorState.allowMultipleSelections.of(true),
|
|
1918
1985
|
EditorState.tabSize.of(2),
|
|
1919
|
-
|
|
1920
|
-
|
|
1986
|
+
EditorView10.lineWrapping,
|
|
1987
|
+
// https://github.com/codemirror/basic-setup
|
|
1921
1988
|
bracketMatching2(),
|
|
1922
1989
|
closeBrackets2(),
|
|
1923
1990
|
crosshairCursor(),
|
|
1924
1991
|
dropCursor(),
|
|
1925
1992
|
drawSelection2(),
|
|
1926
|
-
|
|
1927
|
-
|
|
1993
|
+
highlightActiveLine2(),
|
|
1994
|
+
history2(),
|
|
1928
1995
|
indentOnInput(),
|
|
1929
|
-
_placeholder
|
|
1996
|
+
_placeholder ? placeholder2(_placeholder) : [],
|
|
1930
1997
|
// Main extension.
|
|
1931
1998
|
// https://github.com/codemirror/lang-markdown
|
|
1932
1999
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1936,7 +2003,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1936
2003
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1937
2004
|
// https://github.github.com/gfm
|
|
1938
2005
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1939
|
-
base:
|
|
2006
|
+
base: markdownLanguage3,
|
|
1940
2007
|
// Languages for syntax highlighting fenced code blocks.
|
|
1941
2008
|
codeLanguages: languages,
|
|
1942
2009
|
// Parser extensions.
|
|
@@ -1948,34 +2015,40 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1948
2015
|
// https://github.com/codemirror/theme-one-dark
|
|
1949
2016
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1950
2017
|
// Custom styles.
|
|
1951
|
-
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
2018
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly)),
|
|
2019
|
+
keymap4.of([
|
|
2020
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2021
|
+
indentWithTab,
|
|
2022
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2023
|
+
...closeBracketsKeymap,
|
|
2024
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2025
|
+
...historyKeymap,
|
|
2026
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2027
|
+
...searchKeymap,
|
|
2028
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2029
|
+
...standardKeymap
|
|
2030
|
+
])
|
|
2031
|
+
];
|
|
2032
|
+
};
|
|
1966
2033
|
|
|
1967
2034
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1968
2035
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1969
2036
|
var mention = ({ onSearch }) => {
|
|
1970
2037
|
return autocompletion2({
|
|
2038
|
+
// TODO(burdon): Not working.
|
|
2039
|
+
activateOnTyping: true,
|
|
2040
|
+
// activateOnTypingDelay: 100,
|
|
2041
|
+
// selectOnOpen: true,
|
|
1971
2042
|
closeOnBlur: false,
|
|
2043
|
+
// defaultKeymap: false,
|
|
2044
|
+
icons: false,
|
|
1972
2045
|
override: [
|
|
1973
2046
|
(context) => {
|
|
2047
|
+
console.log(context);
|
|
1974
2048
|
const match = context.matchBefore(/@(\w+)?/);
|
|
1975
2049
|
if (!match || match.from === match.to && !context.explicit) {
|
|
1976
2050
|
return null;
|
|
1977
2051
|
}
|
|
1978
|
-
console.log(match);
|
|
1979
2052
|
return {
|
|
1980
2053
|
from: match.from,
|
|
1981
2054
|
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
@@ -1987,19 +2060,24 @@ var mention = ({ onSearch }) => {
|
|
|
1987
2060
|
});
|
|
1988
2061
|
};
|
|
1989
2062
|
|
|
2063
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2064
|
+
var outliner = (options = {}) => {
|
|
2065
|
+
return [];
|
|
2066
|
+
};
|
|
2067
|
+
|
|
1990
2068
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1991
|
-
import { syntaxTree as
|
|
1992
|
-
import { RangeSetBuilder as
|
|
1993
|
-
import { Decoration as Decoration7, EditorView as
|
|
2069
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2070
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField4 } from "@codemirror/state";
|
|
2071
|
+
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1994
2072
|
var table = (options = {}) => {
|
|
1995
2073
|
return StateField4.define({
|
|
1996
2074
|
create: (state) => update(state, options),
|
|
1997
2075
|
update: (_, tr) => update(tr.state, options),
|
|
1998
|
-
provide: (field) =>
|
|
2076
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
1999
2077
|
});
|
|
2000
2078
|
};
|
|
2001
2079
|
var update = (state, options) => {
|
|
2002
|
-
const builder = new
|
|
2080
|
+
const builder = new RangeSetBuilder3();
|
|
2003
2081
|
const cursor = state.selection.main.head;
|
|
2004
2082
|
const tables = [];
|
|
2005
2083
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2007,7 +2085,7 @@ var update = (state, options) => {
|
|
|
2007
2085
|
const table2 = getTable();
|
|
2008
2086
|
return table2.rows?.[table2.rows.length - 1];
|
|
2009
2087
|
};
|
|
2010
|
-
|
|
2088
|
+
syntaxTree4(state).iterate({
|
|
2011
2089
|
enter: (node) => {
|
|
2012
2090
|
switch (node.name) {
|
|
2013
2091
|
case "Table": {
|
|
@@ -2040,7 +2118,6 @@ var update = (state, options) => {
|
|
|
2040
2118
|
tables.forEach((table2) => {
|
|
2041
2119
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2042
2120
|
hide && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
2043
|
-
block: true,
|
|
2044
2121
|
widget: new TableWidget(table2)
|
|
2045
2122
|
}));
|
|
2046
2123
|
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
@@ -2049,7 +2126,7 @@ var update = (state, options) => {
|
|
|
2049
2126
|
});
|
|
2050
2127
|
return builder.finish();
|
|
2051
2128
|
};
|
|
2052
|
-
var TableWidget = class extends
|
|
2129
|
+
var TableWidget = class extends WidgetType5 {
|
|
2053
2130
|
constructor(_table) {
|
|
2054
2131
|
super();
|
|
2055
2132
|
this._table = _table;
|
|
@@ -2081,88 +2158,104 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2081
2158
|
}
|
|
2082
2159
|
return table2;
|
|
2083
2160
|
}
|
|
2161
|
+
ignoreEvent(e) {
|
|
2162
|
+
return !/^mouse/.test(e.type);
|
|
2163
|
+
}
|
|
2084
2164
|
};
|
|
2085
2165
|
|
|
2086
2166
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2087
|
-
import {
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2167
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2168
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2169
|
+
import { EditorView as EditorView12, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2170
|
+
var styles5 = EditorView12.baseTheme({
|
|
2171
|
+
"& .cm-task": {
|
|
2172
|
+
color: getToken("extend.colors.blue.500")
|
|
2173
|
+
},
|
|
2174
|
+
"& .cm-task-checkbox": {
|
|
2175
|
+
marginLeft: "4px",
|
|
2176
|
+
marginRight: "4px"
|
|
2092
2177
|
}
|
|
2093
2178
|
});
|
|
2094
|
-
var CheckboxWidget = class extends
|
|
2095
|
-
constructor(_checked
|
|
2179
|
+
var CheckboxWidget = class extends WidgetType6 {
|
|
2180
|
+
constructor(_checked) {
|
|
2096
2181
|
super();
|
|
2097
2182
|
this._checked = _checked;
|
|
2098
|
-
this._indent = _indent;
|
|
2099
|
-
this._onCheck = _onCheck;
|
|
2100
2183
|
}
|
|
2101
2184
|
eq(other) {
|
|
2102
|
-
return this._checked === other._checked
|
|
2185
|
+
return this._checked === other._checked;
|
|
2103
2186
|
}
|
|
2104
2187
|
toDOM(view) {
|
|
2105
|
-
const
|
|
2106
|
-
|
|
2107
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2108
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2109
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2188
|
+
const input = document.createElement("input");
|
|
2189
|
+
input.className = "cm-task-checkbox";
|
|
2110
2190
|
input.type = "checkbox";
|
|
2111
2191
|
input.checked = this._checked;
|
|
2112
|
-
if (
|
|
2192
|
+
if (view.state.readOnly) {
|
|
2113
2193
|
input.setAttribute("disabled", "true");
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2194
|
+
} else {
|
|
2195
|
+
input.onmousedown = (event) => {
|
|
2196
|
+
const pos = view.posAtDOM(input);
|
|
2197
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2198
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2199
|
+
view.dispatch({
|
|
2200
|
+
changes: {
|
|
2201
|
+
from: pos + 1,
|
|
2202
|
+
to: pos + 2,
|
|
2203
|
+
insert: this._checked ? " " : "x"
|
|
2204
|
+
}
|
|
2205
|
+
});
|
|
2206
|
+
event.preventDefault();
|
|
2207
|
+
}
|
|
2119
2208
|
};
|
|
2120
2209
|
}
|
|
2121
|
-
return
|
|
2210
|
+
return input;
|
|
2122
2211
|
}
|
|
2123
2212
|
ignoreEvent() {
|
|
2124
2213
|
return false;
|
|
2125
2214
|
}
|
|
2126
2215
|
};
|
|
2216
|
+
var checkedDecoration = Decoration8.replace({
|
|
2217
|
+
widget: new CheckboxWidget(true)
|
|
2218
|
+
});
|
|
2219
|
+
var uncheckedDecoration = Decoration8.replace({
|
|
2220
|
+
widget: new CheckboxWidget(false)
|
|
2221
|
+
});
|
|
2222
|
+
var buildDecorations4 = (view) => {
|
|
2223
|
+
const builder = new RangeSetBuilder4();
|
|
2224
|
+
const { state } = view;
|
|
2225
|
+
const cursor = state.selection.main.head;
|
|
2226
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2227
|
+
syntaxTree5(state).iterate({
|
|
2228
|
+
enter: (node) => {
|
|
2229
|
+
if (node.name === "TaskMarker") {
|
|
2230
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2231
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2232
|
+
builder.add(node.from - 2, node.from - 1, Decoration8.mark({
|
|
2233
|
+
class: "cm-task"
|
|
2234
|
+
}));
|
|
2235
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
},
|
|
2239
|
+
from,
|
|
2240
|
+
to
|
|
2241
|
+
});
|
|
2242
|
+
}
|
|
2243
|
+
return builder.finish();
|
|
2244
|
+
};
|
|
2127
2245
|
var tasklist = (options = {}) => {
|
|
2128
|
-
const taskMatcher = new MatchDecorator3({
|
|
2129
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2130
|
-
decoration: (match, view, pos) => {
|
|
2131
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2132
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2133
|
-
return Decoration8.replace({
|
|
2134
|
-
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2135
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2136
|
-
view.dispatch({
|
|
2137
|
-
changes: {
|
|
2138
|
-
from: idx,
|
|
2139
|
-
to: idx + 1,
|
|
2140
|
-
insert: checked2 ? "x" : " "
|
|
2141
|
-
},
|
|
2142
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2143
|
-
selection: {
|
|
2144
|
-
anchor: idx + 3
|
|
2145
|
-
}
|
|
2146
|
-
});
|
|
2147
|
-
})
|
|
2148
|
-
});
|
|
2149
|
-
}
|
|
2150
|
-
});
|
|
2151
|
-
const tasks = ViewPlugin7.fromClass(class {
|
|
2152
|
-
constructor(view) {
|
|
2153
|
-
this.tasks = taskMatcher.createDeco(view);
|
|
2154
|
-
}
|
|
2155
|
-
update(update2) {
|
|
2156
|
-
this.tasks = taskMatcher.updateDeco(update2, this.tasks);
|
|
2157
|
-
}
|
|
2158
|
-
}, {
|
|
2159
|
-
decorations: (value) => value.tasks,
|
|
2160
|
-
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2161
|
-
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
2162
|
-
})
|
|
2163
|
-
});
|
|
2164
2246
|
return [
|
|
2165
|
-
|
|
2247
|
+
ViewPlugin6.fromClass(class {
|
|
2248
|
+
constructor(view) {
|
|
2249
|
+
this.decorations = buildDecorations4(view);
|
|
2250
|
+
}
|
|
2251
|
+
update(update2) {
|
|
2252
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2253
|
+
this.decorations = buildDecorations4(update2.view);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
}, {
|
|
2257
|
+
decorations: (v) => v.decorations
|
|
2258
|
+
}),
|
|
2166
2259
|
styles5
|
|
2167
2260
|
];
|
|
2168
2261
|
};
|
|
@@ -2241,7 +2334,7 @@ var cursorConverter2 = (text) => ({
|
|
|
2241
2334
|
|
|
2242
2335
|
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2243
2336
|
var yjs = (content, awareness2) => [
|
|
2244
|
-
|
|
2337
|
+
Cursor.converter.of(cursorConverter2(content)),
|
|
2245
2338
|
yCollab(content, awareness2)
|
|
2246
2339
|
];
|
|
2247
2340
|
|
|
@@ -2338,33 +2431,6 @@ var defaultTheme = {
|
|
|
2338
2431
|
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2339
2432
|
},
|
|
2340
2433
|
//
|
|
2341
|
-
// collaboration
|
|
2342
|
-
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
2343
|
-
//
|
|
2344
|
-
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
2345
|
-
mixBlendMode: "multiply"
|
|
2346
|
-
},
|
|
2347
|
-
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2348
|
-
mixBlendMode: "screen"
|
|
2349
|
-
},
|
|
2350
|
-
".cm-ySelectionInfo": {
|
|
2351
|
-
padding: "2px 4px",
|
|
2352
|
-
marginBlockStart: "-4px"
|
|
2353
|
-
},
|
|
2354
|
-
".cm-ySelection, & .cm-selectionMatch": {
|
|
2355
|
-
paddingBlockStart: ".15em",
|
|
2356
|
-
paddingBlockEnd: ".15em"
|
|
2357
|
-
},
|
|
2358
|
-
".cm-ySelectionCaret": {
|
|
2359
|
-
display: "inline-block",
|
|
2360
|
-
insetBlockStart: ".1em",
|
|
2361
|
-
blockSize: "1.4em",
|
|
2362
|
-
verticalAlign: "top"
|
|
2363
|
-
},
|
|
2364
|
-
".cm-yLineSelection": {
|
|
2365
|
-
margin: 0
|
|
2366
|
-
},
|
|
2367
|
-
//
|
|
2368
2434
|
// link
|
|
2369
2435
|
//
|
|
2370
2436
|
".cm-link": {
|
|
@@ -2401,13 +2467,6 @@ var defaultTheme = {
|
|
|
2401
2467
|
textDecoration: "none"
|
|
2402
2468
|
},
|
|
2403
2469
|
//
|
|
2404
|
-
// widgets
|
|
2405
|
-
//
|
|
2406
|
-
".cm-widgetBuffer": {
|
|
2407
|
-
display: "none",
|
|
2408
|
-
height: 0
|
|
2409
|
-
},
|
|
2410
|
-
//
|
|
2411
2470
|
// table
|
|
2412
2471
|
//
|
|
2413
2472
|
".cm-table *": {
|
|
@@ -2438,27 +2497,17 @@ var defaultTheme = {
|
|
|
2438
2497
|
},
|
|
2439
2498
|
//
|
|
2440
2499
|
// font size
|
|
2441
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2500
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2501
|
+
// but it's far more verbose than it needs to be.
|
|
2442
2502
|
//
|
|
2443
|
-
...Object.keys(
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
|
|
2452
|
-
height
|
|
2453
|
-
};
|
|
2454
|
-
acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
|
|
2455
|
-
height
|
|
2456
|
-
};
|
|
2457
|
-
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
|
|
2458
|
-
height
|
|
2459
|
-
};
|
|
2460
|
-
return acc;
|
|
2461
|
-
}, {}),
|
|
2503
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2504
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2505
|
+
//
|
|
2506
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2507
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2508
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2509
|
+
// return acc;
|
|
2510
|
+
// }, {}),
|
|
2462
2511
|
/**
|
|
2463
2512
|
* Panels
|
|
2464
2513
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2509,7 +2558,9 @@ var textTheme = {
|
|
|
2509
2558
|
}
|
|
2510
2559
|
};
|
|
2511
2560
|
var markdownTheme = {
|
|
2512
|
-
|
|
2561
|
+
".cm-scroller": {
|
|
2562
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2563
|
+
},
|
|
2513
2564
|
".cm-placeholder": {
|
|
2514
2565
|
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2515
2566
|
}
|
|
@@ -2524,95 +2575,90 @@ var codeTheme = {
|
|
|
2524
2575
|
};
|
|
2525
2576
|
|
|
2526
2577
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2578
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2527
2579
|
var EditorModes = [
|
|
2528
2580
|
"default",
|
|
2529
2581
|
"vim"
|
|
2530
2582
|
];
|
|
2531
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2532
|
-
const { themeMode } = useThemeContext();
|
|
2583
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2533
2584
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2534
2585
|
tabBehavior: "limited"
|
|
2535
2586
|
});
|
|
2536
|
-
const
|
|
2537
|
-
const
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
state,
|
|
2587
|
+
const { themeMode } = useThemeContext2();
|
|
2588
|
+
const rootRef = useRef(null);
|
|
2589
|
+
const [view, setView] = useState(null);
|
|
2590
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2541
2591
|
view
|
|
2542
|
-
}), [
|
|
2543
|
-
view,
|
|
2544
|
-
state,
|
|
2545
|
-
root
|
|
2546
2592
|
]);
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
awareness2.setLocalStateField("user", {
|
|
2551
|
-
name: peer.name ?? generateName(peer.id),
|
|
2552
|
-
color: getColorForValue({
|
|
2553
|
-
value: peer.id,
|
|
2554
|
-
type: "color"
|
|
2555
|
-
}),
|
|
2556
|
-
colorLight: getColorForValue({
|
|
2557
|
-
value: peer.id,
|
|
2558
|
-
themeMode,
|
|
2559
|
-
type: "highlight"
|
|
2560
|
-
})
|
|
2561
|
-
});
|
|
2562
|
-
}
|
|
2563
|
-
}, [
|
|
2564
|
-
awareness2,
|
|
2565
|
-
peer,
|
|
2566
|
-
themeMode
|
|
2567
|
-
]);
|
|
2568
|
-
useEffect(() => {
|
|
2569
|
-
if (view && comments2?.length) {
|
|
2570
|
-
view.dispatch({
|
|
2571
|
-
effects: setCommentRange.of({
|
|
2572
|
-
model,
|
|
2573
|
-
comments: comments2
|
|
2574
|
-
})
|
|
2575
|
-
});
|
|
2593
|
+
useEffect3(() => {
|
|
2594
|
+
if (autofocus) {
|
|
2595
|
+
view?.focus();
|
|
2576
2596
|
}
|
|
2577
2597
|
}, [
|
|
2578
2598
|
view,
|
|
2579
|
-
|
|
2599
|
+
autofocus
|
|
2580
2600
|
]);
|
|
2581
|
-
|
|
2582
|
-
|
|
2601
|
+
useAwareness(model);
|
|
2602
|
+
useEffect3(() => {
|
|
2603
|
+
if (!model || !rootRef.current) {
|
|
2583
2604
|
return;
|
|
2584
2605
|
}
|
|
2585
|
-
const
|
|
2606
|
+
const state = EditorState2.create({
|
|
2586
2607
|
doc: model.text(),
|
|
2608
|
+
selection,
|
|
2587
2609
|
extensions: [
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2610
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2611
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2612
|
+
log2.catch(err, void 0, {
|
|
2613
|
+
F: __dxlog_file5,
|
|
2614
|
+
L: 126,
|
|
2615
|
+
S: void 0,
|
|
2616
|
+
C: (f, a) => f(...a)
|
|
2617
|
+
});
|
|
2618
|
+
}),
|
|
2591
2619
|
// Theme.
|
|
2592
|
-
// TODO(burdon): Make
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2620
|
+
// TODO(burdon): Make configurable.
|
|
2621
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2622
|
+
EditorView13.theme(theme ?? {}),
|
|
2623
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2624
|
+
EditorView13.editorAttributes.of({
|
|
2625
|
+
class: slots.editor?.className ?? ""
|
|
2626
|
+
}),
|
|
2627
|
+
EditorView13.contentAttributes.of({
|
|
2628
|
+
class: slots.content?.className ?? ""
|
|
2629
|
+
}),
|
|
2630
|
+
// State.
|
|
2631
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2596
2632
|
// Storage and replication.
|
|
2633
|
+
// NOTE: This must come before user extensions.
|
|
2597
2634
|
model.extension,
|
|
2635
|
+
// TODO(burdon): Factor out (requires special handling for Escape/focus).
|
|
2636
|
+
editorMode === "vim" && vim(),
|
|
2598
2637
|
// Custom.
|
|
2599
2638
|
...extensions
|
|
2600
2639
|
].filter(Boolean)
|
|
2601
2640
|
});
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2641
|
+
const newView = new EditorView13({
|
|
2642
|
+
state,
|
|
2643
|
+
parent: rootRef.current,
|
|
2644
|
+
scrollTo,
|
|
2645
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2646
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2647
|
+
dispatchTransactions: (trs, view2) => {
|
|
2648
|
+
if (debug) {
|
|
2649
|
+
logChanges(trs);
|
|
2650
|
+
}
|
|
2651
|
+
view2.update(trs);
|
|
2652
|
+
}
|
|
2609
2653
|
});
|
|
2654
|
+
view?.destroy();
|
|
2655
|
+
setView(newView);
|
|
2610
2656
|
return () => {
|
|
2611
|
-
|
|
2612
|
-
|
|
2657
|
+
newView?.destroy();
|
|
2658
|
+
setView(null);
|
|
2613
2659
|
};
|
|
2614
2660
|
}, [
|
|
2615
|
-
|
|
2661
|
+
rootRef,
|
|
2616
2662
|
model,
|
|
2617
2663
|
readonly,
|
|
2618
2664
|
editorMode,
|
|
@@ -2622,11 +2668,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2622
2668
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2623
2669
|
switch (key) {
|
|
2624
2670
|
case "Enter": {
|
|
2625
|
-
view?.
|
|
2671
|
+
view?.focus();
|
|
2626
2672
|
break;
|
|
2627
2673
|
}
|
|
2628
2674
|
case "Escape": {
|
|
2629
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2675
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2676
|
+
rootRef.current?.focus();
|
|
2677
|
+
}
|
|
2630
2678
|
break;
|
|
2631
2679
|
}
|
|
2632
2680
|
}
|
|
@@ -2636,65 +2684,66 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2636
2684
|
]);
|
|
2637
2685
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2638
2686
|
key: model.id,
|
|
2639
|
-
|
|
2687
|
+
role: "none",
|
|
2640
2688
|
tabIndex: 0,
|
|
2641
|
-
|
|
2689
|
+
onKeyUp: handleKeyUp,
|
|
2690
|
+
...slots.root,
|
|
2642
2691
|
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2643
|
-
|
|
2692
|
+
ref: rootRef
|
|
2644
2693
|
});
|
|
2645
2694
|
});
|
|
2646
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2647
|
-
const { themeMode } =
|
|
2648
|
-
const
|
|
2695
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, multiline, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2696
|
+
const { themeMode } = useThemeContext2();
|
|
2697
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2649
2698
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2650
2699
|
ref: forwardedRef,
|
|
2651
2700
|
readonly,
|
|
2652
2701
|
extensions: [
|
|
2653
2702
|
basicBundle({
|
|
2654
|
-
readonly,
|
|
2655
2703
|
themeMode,
|
|
2656
|
-
placeholder:
|
|
2704
|
+
placeholder: placeholder3,
|
|
2705
|
+
multiline
|
|
2657
2706
|
}),
|
|
2658
2707
|
...extensions
|
|
2659
2708
|
],
|
|
2660
|
-
|
|
2709
|
+
theme,
|
|
2710
|
+
slots: updatedSlots,
|
|
2661
2711
|
...props
|
|
2662
2712
|
});
|
|
2663
2713
|
});
|
|
2664
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2665
|
-
const { themeMode } =
|
|
2666
|
-
const
|
|
2714
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2715
|
+
const { themeMode } = useThemeContext2();
|
|
2716
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2667
2717
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2668
2718
|
ref: forwardedRef,
|
|
2669
2719
|
readonly,
|
|
2670
2720
|
extensions: [
|
|
2671
2721
|
markdownBundle({
|
|
2672
|
-
readonly,
|
|
2673
2722
|
themeMode,
|
|
2674
|
-
|
|
2723
|
+
readonly,
|
|
2724
|
+
placeholder: placeholder3
|
|
2675
2725
|
}),
|
|
2676
2726
|
...extensions
|
|
2677
2727
|
],
|
|
2678
|
-
|
|
2728
|
+
theme,
|
|
2729
|
+
slots: updatedSlots,
|
|
2679
2730
|
...props
|
|
2680
2731
|
});
|
|
2681
2732
|
});
|
|
2682
2733
|
var defaultSlots = {
|
|
2683
2734
|
root: {
|
|
2684
|
-
|
|
2735
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
2736
|
+
className: mx3("flex flex-col grow overflow-y-auto", inputSurface)
|
|
2737
|
+
},
|
|
2738
|
+
editor: {
|
|
2739
|
+
className: "h-full p-2"
|
|
2685
2740
|
}
|
|
2686
2741
|
};
|
|
2687
2742
|
var defaultTextSlots = {
|
|
2688
|
-
...defaultSlots
|
|
2689
|
-
editor: {
|
|
2690
|
-
theme: textTheme
|
|
2691
|
-
}
|
|
2743
|
+
...defaultSlots
|
|
2692
2744
|
};
|
|
2693
2745
|
var defaultMarkdownSlots = {
|
|
2694
|
-
...defaultSlots
|
|
2695
|
-
editor: {
|
|
2696
|
-
theme: markdownTheme
|
|
2697
|
-
}
|
|
2746
|
+
...defaultSlots
|
|
2698
2747
|
};
|
|
2699
2748
|
|
|
2700
2749
|
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
@@ -2705,9 +2754,9 @@ import { isNotNullOrUndefined } from "@dxos/util";
|
|
|
2705
2754
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2706
2755
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2707
2756
|
import { Context as Context2 } from "@dxos/context";
|
|
2708
|
-
import { invariant as
|
|
2757
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2709
2758
|
import { log as log3 } from "@dxos/log";
|
|
2710
|
-
var
|
|
2759
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2711
2760
|
var DEBOUNCE_INTERVAL = 100;
|
|
2712
2761
|
var SpaceAwarenessProvider = class {
|
|
2713
2762
|
constructor(params) {
|
|
@@ -2748,7 +2797,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2748
2797
|
log3.debug("failed to query awareness", {
|
|
2749
2798
|
err
|
|
2750
2799
|
}, {
|
|
2751
|
-
F:
|
|
2800
|
+
F: __dxlog_file6,
|
|
2752
2801
|
L: 85,
|
|
2753
2802
|
S: this,
|
|
2754
2803
|
C: (f, a) => f(...a)
|
|
@@ -2761,8 +2810,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2761
2810
|
this._postTask = void 0;
|
|
2762
2811
|
}
|
|
2763
2812
|
update(position) {
|
|
2764
|
-
|
|
2765
|
-
F:
|
|
2813
|
+
invariant4(this._postTask, void 0, {
|
|
2814
|
+
F: __dxlog_file6,
|
|
2766
2815
|
L: 96,
|
|
2767
2816
|
S: this,
|
|
2768
2817
|
A: [
|
|
@@ -2781,8 +2830,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2781
2830
|
return Array.from(this._remoteStates.values());
|
|
2782
2831
|
}
|
|
2783
2832
|
_handleQueryMessage() {
|
|
2784
|
-
|
|
2785
|
-
F:
|
|
2833
|
+
invariant4(this._postTask, void 0, {
|
|
2834
|
+
F: __dxlog_file6,
|
|
2786
2835
|
L: 111,
|
|
2787
2836
|
S: this,
|
|
2788
2837
|
A: [
|
|
@@ -2793,8 +2842,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2793
2842
|
this._postTask.schedule();
|
|
2794
2843
|
}
|
|
2795
2844
|
_handlePostMessage(message) {
|
|
2796
|
-
|
|
2797
|
-
F:
|
|
2845
|
+
invariant4(message.kind === "post", void 0, {
|
|
2846
|
+
F: __dxlog_file6,
|
|
2798
2847
|
L: 116,
|
|
2799
2848
|
S: this,
|
|
2800
2849
|
A: [
|
|
@@ -2807,25 +2856,63 @@ var SpaceAwarenessProvider = class {
|
|
|
2807
2856
|
}
|
|
2808
2857
|
};
|
|
2809
2858
|
|
|
2810
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2859
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2811
2860
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2812
|
-
|
|
2813
|
-
|
|
2861
|
+
var modelState = StateField5.define({
|
|
2862
|
+
create: () => void 0,
|
|
2863
|
+
update: (model) => model
|
|
2864
|
+
});
|
|
2865
|
+
|
|
2866
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2867
|
+
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2868
|
+
const obj = text;
|
|
2869
|
+
const doc = getRawDoc(obj, [
|
|
2870
|
+
obj.field
|
|
2871
|
+
]);
|
|
2872
|
+
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2873
|
+
space,
|
|
2874
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
2875
|
+
info: {
|
|
2876
|
+
displayName: identity?.profile?.displayName ?? "",
|
|
2877
|
+
color: cursorColor.color,
|
|
2878
|
+
lightColor: cursorColor.light
|
|
2879
|
+
},
|
|
2880
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2881
|
+
});
|
|
2882
|
+
const model = {
|
|
2883
|
+
id: obj.id,
|
|
2884
|
+
content: doc,
|
|
2885
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2886
|
+
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2887
|
+
extension: [
|
|
2888
|
+
modelState.init(() => model),
|
|
2889
|
+
automerge3({
|
|
2890
|
+
handle: doc.handle,
|
|
2891
|
+
path: doc.path
|
|
2892
|
+
}),
|
|
2893
|
+
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2894
|
+
awareness()
|
|
2895
|
+
].filter(isNotNullOrUndefined),
|
|
2896
|
+
peer: identity ? {
|
|
2897
|
+
id: identity.identityKey.toHex(),
|
|
2898
|
+
name: identity.profile?.displayName
|
|
2899
|
+
} : void 0
|
|
2900
|
+
};
|
|
2901
|
+
return model;
|
|
2902
|
+
};
|
|
2814
2903
|
|
|
2815
2904
|
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2816
2905
|
import * as decoding from "lib0/decoding";
|
|
2817
2906
|
import * as encoding from "lib0/encoding";
|
|
2818
2907
|
import { Observable } from "lib0/observable";
|
|
2819
2908
|
import * as YP from "y-protocols/awareness";
|
|
2820
|
-
import
|
|
2821
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2909
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
2822
2910
|
import { log as log4 } from "@dxos/log";
|
|
2823
|
-
|
|
2824
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2911
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2825
2912
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2826
|
-
|
|
2827
|
-
F:
|
|
2828
|
-
L:
|
|
2913
|
+
invariant5(text?.doc && text?.content, void 0, {
|
|
2914
|
+
F: __dxlog_file7,
|
|
2915
|
+
L: 22,
|
|
2829
2916
|
S: void 0,
|
|
2830
2917
|
A: [
|
|
2831
2918
|
"text?.doc && text?.content",
|
|
@@ -2841,34 +2928,6 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
2841
2928
|
id: text.doc.guid,
|
|
2842
2929
|
content: text.content,
|
|
2843
2930
|
text: () => text.content.toString(),
|
|
2844
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2845
|
-
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2846
|
-
getCursorFromRange: (range) => {
|
|
2847
|
-
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2848
|
-
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2849
|
-
return [
|
|
2850
|
-
arrayToString2(from),
|
|
2851
|
-
arrayToString2(to)
|
|
2852
|
-
].join(":");
|
|
2853
|
-
},
|
|
2854
|
-
getRangeFromCursor: (cursor) => {
|
|
2855
|
-
invariant4(text.doc, void 0, {
|
|
2856
|
-
F: __dxlog_file5,
|
|
2857
|
-
L: 40,
|
|
2858
|
-
S: void 0,
|
|
2859
|
-
A: [
|
|
2860
|
-
"text.doc",
|
|
2861
|
-
""
|
|
2862
|
-
]
|
|
2863
|
-
});
|
|
2864
|
-
const parts = cursor.split(":");
|
|
2865
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2866
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2867
|
-
return from && to ? {
|
|
2868
|
-
from: from.index,
|
|
2869
|
-
to: to.index
|
|
2870
|
-
} : void 0;
|
|
2871
|
-
},
|
|
2872
2931
|
extension: [
|
|
2873
2932
|
modelState.init(() => model),
|
|
2874
2933
|
yjs(text.content, provider?.awareness)
|
|
@@ -2917,8 +2976,8 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2917
2976
|
removed,
|
|
2918
2977
|
origin
|
|
2919
2978
|
}, {
|
|
2920
|
-
F:
|
|
2921
|
-
L:
|
|
2979
|
+
F: __dxlog_file7,
|
|
2980
|
+
L: 101,
|
|
2922
2981
|
S: this,
|
|
2923
2982
|
C: (f, a) => f(...a)
|
|
2924
2983
|
});
|
|
@@ -2930,8 +2989,8 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2930
2989
|
}
|
|
2931
2990
|
_handleSpaceMessage({ payload }) {
|
|
2932
2991
|
log4("space message", payload, {
|
|
2933
|
-
F:
|
|
2934
|
-
L:
|
|
2992
|
+
F: __dxlog_file7,
|
|
2993
|
+
L: 110,
|
|
2935
2994
|
S: this,
|
|
2936
2995
|
C: (f, a) => f(...a)
|
|
2937
2996
|
});
|
|
@@ -2975,14 +3034,12 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2975
3034
|
};
|
|
2976
3035
|
|
|
2977
3036
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
update: (model) => model
|
|
2981
|
-
});
|
|
3037
|
+
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
3038
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2982
3039
|
var useTextModel = (props) => {
|
|
2983
3040
|
const { identity, space, text } = props;
|
|
2984
|
-
const [model, setModel] = useState2(
|
|
2985
|
-
|
|
3041
|
+
const [model, setModel] = useState2();
|
|
3042
|
+
useEffect4(() => setModel(createModel(props)), [
|
|
2986
3043
|
identity,
|
|
2987
3044
|
space,
|
|
2988
3045
|
text
|
|
@@ -2999,47 +3056,10 @@ var createModel = (props) => {
|
|
|
2999
3056
|
return void 0;
|
|
3000
3057
|
}
|
|
3001
3058
|
};
|
|
3002
|
-
|
|
3003
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
3004
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
3005
|
-
const obj = text;
|
|
3006
|
-
const doc = getRawDoc(obj, [
|
|
3007
|
-
obj.field
|
|
3008
|
-
]);
|
|
3009
|
-
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
3010
|
-
space,
|
|
3011
|
-
channel: `automerge.awareness.${obj.id}`,
|
|
3012
|
-
info: {
|
|
3013
|
-
displayName: identity?.profile?.displayName ?? "",
|
|
3014
|
-
color: cursorColor.color,
|
|
3015
|
-
lightColor: cursorColor.light
|
|
3016
|
-
},
|
|
3017
|
-
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
3018
|
-
});
|
|
3019
|
-
const model = {
|
|
3020
|
-
id: obj.id,
|
|
3021
|
-
content: doc,
|
|
3022
|
-
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3023
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3024
|
-
extension: [
|
|
3025
|
-
modelState.init(() => model),
|
|
3026
|
-
automerge3({
|
|
3027
|
-
handle: doc.handle,
|
|
3028
|
-
path: doc.path
|
|
3029
|
-
}),
|
|
3030
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
3031
|
-
awareness()
|
|
3032
|
-
].filter(isNotNullOrUndefined),
|
|
3033
|
-
peer: identity ? {
|
|
3034
|
-
id: identity.identityKey.toHex(),
|
|
3035
|
-
name: identity.profile?.displayName
|
|
3036
|
-
} : void 0
|
|
3037
|
-
};
|
|
3038
|
-
return model;
|
|
3039
|
-
};
|
|
3040
3059
|
export {
|
|
3041
3060
|
AwarenessProvider,
|
|
3042
3061
|
BaseTextEditor,
|
|
3062
|
+
Cursor,
|
|
3043
3063
|
Doc,
|
|
3044
3064
|
EditorModes,
|
|
3045
3065
|
MarkdownEditor,
|
|
@@ -3055,6 +3075,7 @@ export {
|
|
|
3055
3075
|
awareness,
|
|
3056
3076
|
basicBundle,
|
|
3057
3077
|
blast,
|
|
3078
|
+
callbackWrapper,
|
|
3058
3079
|
code2 as code,
|
|
3059
3080
|
codeTheme,
|
|
3060
3081
|
comments,
|
|
@@ -3070,6 +3091,7 @@ export {
|
|
|
3070
3091
|
image,
|
|
3071
3092
|
link,
|
|
3072
3093
|
listener,
|
|
3094
|
+
logChanges,
|
|
3073
3095
|
markdownBundle,
|
|
3074
3096
|
markdownHighlightStyle,
|
|
3075
3097
|
markdownTags,
|
|
@@ -3077,7 +3099,8 @@ export {
|
|
|
3077
3099
|
markdownTheme,
|
|
3078
3100
|
mention,
|
|
3079
3101
|
modelState,
|
|
3080
|
-
|
|
3102
|
+
outliner,
|
|
3103
|
+
setComments,
|
|
3081
3104
|
setFocus,
|
|
3082
3105
|
setSelection,
|
|
3083
3106
|
table,
|
|
@@ -3085,6 +3108,8 @@ export {
|
|
|
3085
3108
|
tasklist,
|
|
3086
3109
|
textTheme,
|
|
3087
3110
|
typewriter,
|
|
3111
|
+
useAwareness,
|
|
3112
|
+
useComments,
|
|
3088
3113
|
useTextModel,
|
|
3089
3114
|
yjs
|
|
3090
3115
|
};
|