@dxos/react-ui-editor 0.3.11-main.008b7c6 → 0.3.11-main.00a28cb
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 +558 -629
- 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 +12 -5
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +12 -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 +4 -4
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +4 -9
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/code.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +14 -5
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/{util → extensions}/cursor.d.ts +9 -1
- 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/image.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/link.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.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 +5 -1
- 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/index.d.ts +1 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +0 -5
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/hooks/yjs.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -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/styles/tokens.d.ts +1 -0
- package/dist/types/src/styles/tokens.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +25 -24
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +41 -37
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +71 -67
- package/src/components/TextEditor/comments.stories.tsx +355 -0
- package/src/extensions/autocomplete.ts +18 -17
- package/src/extensions/automerge/automerge.ts +12 -14
- package/src/extensions/automerge/cursor.ts +2 -1
- package/src/extensions/automerge/defs.ts +13 -9
- package/src/extensions/automerge/semaphore.ts +10 -12
- package/src/extensions/awareness.ts +27 -33
- package/src/extensions/code.ts +28 -23
- package/src/extensions/comments.ts +131 -144
- package/src/extensions/cursor.ts +46 -0
- package/src/extensions/hr.ts +10 -12
- package/src/extensions/image.ts +40 -22
- package/src/extensions/index.ts +2 -1
- package/src/extensions/link.ts +86 -88
- package/src/extensions/markdown/highlight.ts +3 -12
- package/src/extensions/outliner.ts +12 -0
- package/src/extensions/table.ts +10 -4
- package/src/extensions/tasklist.ts +54 -79
- 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/index.ts +2 -1
- package/src/hooks/useTextModel.ts +4 -7
- package/src/hooks/yjs.ts +1 -23
- package/src/index.ts +3 -0
- package/src/styles/markdown.ts +0 -2
- package/src/styles/tokens.ts +3 -0
- package/src/themes/default.ts +51 -78
- package/dist/types/src/extensions/mermaid.d.ts +0 -3
- package/dist/types/src/extensions/mermaid.d.ts.map +0 -1
- 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.map +0 -1
- package/src/extensions/mermaid.ts +0 -11
- package/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- /package/dist/types/src/{util/util.d.ts → util.d.ts} +0 -0
- /package/src/{util/util.ts → util.ts} +0 -0
|
@@ -7,50 +7,51 @@ 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 EditorView12 } 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";
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState, useRef } from "react";
|
|
15
15
|
import { generateName } from "@dxos/display-name";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
17
|
import { getColorForValue, 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
|
-
|
|
31
|
-
// defaultKeymap: false,
|
|
32
|
+
defaultKeymap: false,
|
|
32
33
|
// Don't start unless key press.
|
|
33
|
-
activateOnTyping: false
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
from: match.from,
|
|
44
|
-
options: onSearch(match.text.toLowerCase())
|
|
45
|
-
};
|
|
34
|
+
activateOnTyping: false
|
|
35
|
+
}),
|
|
36
|
+
// TODO(burdon): Option to create new page?
|
|
37
|
+
// TODO(burdon): Optional decoration via addToOptions
|
|
38
|
+
markdownLanguage.data.of({
|
|
39
|
+
autocomplete: (context) => {
|
|
40
|
+
const match = context.matchBefore(/\w*/);
|
|
41
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
42
|
+
return null;
|
|
46
43
|
}
|
|
47
|
-
|
|
44
|
+
return {
|
|
45
|
+
from: match.from,
|
|
46
|
+
options: onSearch(match.text.toLowerCase())
|
|
47
|
+
};
|
|
48
|
+
}
|
|
48
49
|
})
|
|
49
50
|
];
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
53
|
-
import {
|
|
54
|
+
import { StateField } from "@codemirror/state";
|
|
54
55
|
import { ViewPlugin } from "@codemirror/view";
|
|
55
56
|
import { next as A } from "@dxos/automerge/automerge";
|
|
56
57
|
|
|
@@ -91,7 +92,7 @@ var cursorConverter = (handle, path) => ({
|
|
|
91
92
|
});
|
|
92
93
|
|
|
93
94
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
94
|
-
import { Annotation, StateEffect } from "@codemirror/state";
|
|
95
|
+
import { Annotation, StateEffect, Facet } from "@codemirror/state";
|
|
95
96
|
var effectType = StateEffect.define({});
|
|
96
97
|
var updateHeads = (newHeads) => effectType.of({
|
|
97
98
|
newHeads
|
|
@@ -100,6 +101,9 @@ var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
|
100
101
|
var getPath = (state, field) => state.field(field).path;
|
|
101
102
|
var reconcileAnnotationType = Annotation.define();
|
|
102
103
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
104
|
+
var semaphoreFacet = Facet.define({
|
|
105
|
+
combine: (values) => values.at(-1)
|
|
106
|
+
});
|
|
103
107
|
|
|
104
108
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
105
109
|
import { next as automerge2 } from "@dxos/automerge/automerge";
|
|
@@ -236,11 +240,11 @@ var charPath = (textPath, candidatePath) => {
|
|
|
236
240
|
|
|
237
241
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
238
242
|
var PatchSemaphore = class {
|
|
239
|
-
constructor(_field) {
|
|
243
|
+
constructor(_handle, _field) {
|
|
244
|
+
this._handle = _handle;
|
|
240
245
|
this._field = _field;
|
|
241
246
|
this._inReconcile = false;
|
|
242
|
-
this.
|
|
243
|
-
this.reconcile = (handle, view) => {
|
|
247
|
+
this.reconcile = (view) => {
|
|
244
248
|
if (this._inReconcile) {
|
|
245
249
|
return;
|
|
246
250
|
}
|
|
@@ -258,11 +262,11 @@ var PatchSemaphore = class {
|
|
|
258
262
|
annotations: reconcileAnnotationType.of(true)
|
|
259
263
|
});
|
|
260
264
|
}
|
|
261
|
-
let newHeads = updateAutomerge(this._field,
|
|
265
|
+
let newHeads = updateAutomerge(this._field, this._handle, transactions, view.state);
|
|
262
266
|
if (newHeads === null || newHeads === void 0) {
|
|
263
|
-
newHeads = automerge2.getHeads(
|
|
267
|
+
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
264
268
|
}
|
|
265
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(
|
|
269
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
266
270
|
updateCodeMirror(view, selection, path, diff);
|
|
267
271
|
view.dispatch({
|
|
268
272
|
effects: updateHeads(newHeads),
|
|
@@ -273,36 +277,42 @@ var PatchSemaphore = class {
|
|
|
273
277
|
}
|
|
274
278
|
};
|
|
275
279
|
|
|
276
|
-
// packages/ui/react-ui-editor/src/
|
|
277
|
-
import { Facet } from "@codemirror/state";
|
|
278
|
-
var
|
|
280
|
+
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
281
|
+
import { Facet as Facet2 } from "@codemirror/state";
|
|
282
|
+
var defaultCursorConverter = {
|
|
279
283
|
toCursor: (position) => position.toString(),
|
|
280
284
|
fromCursor: (cursor) => parseInt(cursor)
|
|
281
285
|
};
|
|
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)
|
|
286
|
+
var Cursor = class {
|
|
287
|
+
static {
|
|
288
|
+
this.converter = Facet2.define({
|
|
289
|
+
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
298
290
|
});
|
|
299
291
|
}
|
|
292
|
+
static {
|
|
293
|
+
this.getCursorFromRange = (cursorConverter3, range) => {
|
|
294
|
+
const from = cursorConverter3.toCursor(range.from);
|
|
295
|
+
const to = cursorConverter3.toCursor(range.to, -1);
|
|
296
|
+
return [
|
|
297
|
+
from,
|
|
298
|
+
to
|
|
299
|
+
].join(":");
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
static {
|
|
303
|
+
this.getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
304
|
+
const parts = cursor.split(":");
|
|
305
|
+
const from = cursorConverter3.fromCursor(parts[0]);
|
|
306
|
+
const to = cursorConverter3.fromCursor(parts[1]);
|
|
307
|
+
return from !== void 0 && to !== void 0 ? {
|
|
308
|
+
from,
|
|
309
|
+
to
|
|
310
|
+
} : void 0;
|
|
311
|
+
};
|
|
312
|
+
}
|
|
300
313
|
};
|
|
301
314
|
|
|
302
315
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
303
|
-
var semaphoreFacet = Facet2.define({
|
|
304
|
-
combine: (values) => values.at(-1)
|
|
305
|
-
});
|
|
306
316
|
var automerge3 = ({ handle, path }) => {
|
|
307
317
|
const stateField = StateField.define({
|
|
308
318
|
create: () => ({
|
|
@@ -333,19 +343,19 @@ var automerge3 = ({ handle, path }) => {
|
|
|
333
343
|
return result;
|
|
334
344
|
}
|
|
335
345
|
});
|
|
336
|
-
const semaphore = new PatchSemaphore(stateField);
|
|
337
|
-
const viewPlugin = ViewPlugin.fromClass(class
|
|
346
|
+
const semaphore = new PatchSemaphore(handle, stateField);
|
|
347
|
+
const viewPlugin = ViewPlugin.fromClass(class AutomergeViewPlugin {
|
|
338
348
|
constructor(_view) {
|
|
339
349
|
this._view = _view;
|
|
340
350
|
this._handleChange = () => {
|
|
341
|
-
this._view.state.facet(semaphoreFacet).reconcile(
|
|
351
|
+
this._view.state.facet(semaphoreFacet).reconcile(this._view);
|
|
342
352
|
};
|
|
343
353
|
handle.addListener("change", this._handleChange);
|
|
344
354
|
}
|
|
345
|
-
update(
|
|
346
|
-
if (
|
|
355
|
+
update(update2) {
|
|
356
|
+
if (update2.transactions.length > 0 && update2.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
347
357
|
queueMicrotask(() => {
|
|
348
|
-
this._view.state.facet(semaphoreFacet).reconcile(
|
|
358
|
+
this._view.state.facet(semaphoreFacet).reconcile(this._view);
|
|
349
359
|
});
|
|
350
360
|
}
|
|
351
361
|
}
|
|
@@ -355,7 +365,7 @@ var automerge3 = ({ handle, path }) => {
|
|
|
355
365
|
});
|
|
356
366
|
return {
|
|
357
367
|
extension: [
|
|
358
|
-
|
|
368
|
+
Cursor.converter.of(cursorConverter(handle, path)),
|
|
359
369
|
semaphoreFacet.of(semaphore),
|
|
360
370
|
stateField,
|
|
361
371
|
viewPlugin
|
|
@@ -397,7 +407,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
397
407
|
this._ctx = new Context();
|
|
398
408
|
this._lastAnchor = void 0;
|
|
399
409
|
this._lastHead = void 0;
|
|
400
|
-
this._cursorConverter = view.state.facet(
|
|
410
|
+
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
401
411
|
this._provider = view.state.facet(AwarenessProvider);
|
|
402
412
|
this._provider.open();
|
|
403
413
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
@@ -412,13 +422,13 @@ var RemoteSelectionsDecorator = class {
|
|
|
412
422
|
void this._ctx.dispose();
|
|
413
423
|
this._provider.close();
|
|
414
424
|
}
|
|
415
|
-
update(
|
|
416
|
-
this._updateLocalSelection(
|
|
417
|
-
this._updateRemoteSelections(
|
|
425
|
+
update(update2) {
|
|
426
|
+
this._updateLocalSelection(update2);
|
|
427
|
+
this._updateRemoteSelections(update2);
|
|
418
428
|
}
|
|
419
|
-
_updateLocalSelection(
|
|
420
|
-
const hasFocus =
|
|
421
|
-
const { anchor = void 0, head = void 0 } = hasFocus ?
|
|
429
|
+
_updateLocalSelection(update2) {
|
|
430
|
+
const hasFocus = update2.view.hasFocus && update2.view.dom.ownerDocument.hasFocus();
|
|
431
|
+
const { anchor = void 0, head = void 0 } = hasFocus ? update2.state.selection.main : {};
|
|
422
432
|
if (this._lastAnchor === anchor && this._lastHead === head) {
|
|
423
433
|
return;
|
|
424
434
|
}
|
|
@@ -429,7 +439,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
429
439
|
head: this._cursorConverter.toCursor(head)
|
|
430
440
|
} : void 0);
|
|
431
441
|
}
|
|
432
|
-
_updateRemoteSelections(
|
|
442
|
+
_updateRemoteSelections(update2) {
|
|
433
443
|
const decorations = [];
|
|
434
444
|
const awarenessStates = this._provider.getRemoteStates();
|
|
435
445
|
for (const state of awarenessStates) {
|
|
@@ -438,10 +448,10 @@ var RemoteSelectionsDecorator = class {
|
|
|
438
448
|
if (anchor == null || head == null) {
|
|
439
449
|
continue;
|
|
440
450
|
}
|
|
441
|
-
const start = Math.min(Math.min(anchor, head),
|
|
442
|
-
const end = Math.min(Math.max(anchor, head),
|
|
443
|
-
const startLine =
|
|
444
|
-
const endLine =
|
|
451
|
+
const start = Math.min(Math.min(anchor, head), update2.view.state.doc.length);
|
|
452
|
+
const end = Math.min(Math.max(anchor, head), update2.view.state.doc.length);
|
|
453
|
+
const startLine = update2.view.state.doc.lineAt(start);
|
|
454
|
+
const endLine = update2.view.state.doc.lineAt(end);
|
|
445
455
|
const color = state.info.color ?? "#30bced";
|
|
446
456
|
const lightColor = state.info.lightColor ?? color + "33";
|
|
447
457
|
if (startLine.number === endLine.number) {
|
|
@@ -452,7 +462,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
452
462
|
attributes: {
|
|
453
463
|
style: `background-color: ${lightColor}`
|
|
454
464
|
},
|
|
455
|
-
class: "cm-
|
|
465
|
+
class: "cm-collab-selection"
|
|
456
466
|
})
|
|
457
467
|
});
|
|
458
468
|
} else {
|
|
@@ -463,7 +473,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
463
473
|
attributes: {
|
|
464
474
|
style: `background-color: ${color}`
|
|
465
475
|
},
|
|
466
|
-
class: "cm-
|
|
476
|
+
class: "cm-collab-selection"
|
|
467
477
|
})
|
|
468
478
|
});
|
|
469
479
|
decorations.push({
|
|
@@ -473,18 +483,18 @@ var RemoteSelectionsDecorator = class {
|
|
|
473
483
|
attributes: {
|
|
474
484
|
style: `background-color: ${color}`
|
|
475
485
|
},
|
|
476
|
-
class: "cm-
|
|
486
|
+
class: "cm-collab-selection"
|
|
477
487
|
})
|
|
478
488
|
});
|
|
479
489
|
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
480
|
-
const linePos =
|
|
490
|
+
const linePos = update2.view.state.doc.line(i).from;
|
|
481
491
|
decorations.push({
|
|
482
492
|
from: linePos,
|
|
483
493
|
to: linePos,
|
|
484
494
|
value: Decoration.line({
|
|
485
495
|
attributes: {
|
|
486
496
|
style: `background-color: ${color}`,
|
|
487
|
-
class: "cm-
|
|
497
|
+
class: "cm-collab-selectionLine"
|
|
488
498
|
}
|
|
489
499
|
})
|
|
490
500
|
});
|
|
@@ -504,23 +514,21 @@ var RemoteSelectionsDecorator = class {
|
|
|
504
514
|
}
|
|
505
515
|
};
|
|
506
516
|
var RemoteCaretWidget = class extends WidgetType {
|
|
507
|
-
constructor(
|
|
517
|
+
constructor(_name, _color) {
|
|
508
518
|
super();
|
|
509
|
-
this.
|
|
510
|
-
this.
|
|
511
|
-
this.name = name;
|
|
512
|
-
this.color = color;
|
|
519
|
+
this._name = _name;
|
|
520
|
+
this._color = _color;
|
|
513
521
|
}
|
|
514
522
|
toDOM() {
|
|
515
523
|
const span = document.createElement("span");
|
|
516
|
-
span.className = "cm-
|
|
517
|
-
span.style.backgroundColor = this.
|
|
518
|
-
span.style.borderColor = this.
|
|
524
|
+
span.className = "cm-collab-selectionCaret";
|
|
525
|
+
span.style.backgroundColor = this._color;
|
|
526
|
+
span.style.borderColor = this._color;
|
|
519
527
|
const dot = document.createElement("div");
|
|
520
|
-
dot.className = "cm-
|
|
528
|
+
dot.className = "cm-collab-selectionCaretDot";
|
|
521
529
|
const info = document.createElement("div");
|
|
522
|
-
info.className = "cm-
|
|
523
|
-
info.innerText = this.
|
|
530
|
+
info.className = "cm-collab-selectionInfo";
|
|
531
|
+
info.innerText = this._name;
|
|
524
532
|
span.appendChild(document.createTextNode("\u2060"));
|
|
525
533
|
span.appendChild(dot);
|
|
526
534
|
span.appendChild(document.createTextNode("\u2060"));
|
|
@@ -528,15 +536,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
528
536
|
span.appendChild(document.createTextNode("\u2060"));
|
|
529
537
|
return span;
|
|
530
538
|
}
|
|
531
|
-
eq(widget) {
|
|
532
|
-
return widget.color === this.color;
|
|
533
|
-
}
|
|
534
|
-
compare(widget) {
|
|
535
|
-
return widget.color === this.color;
|
|
536
|
-
}
|
|
537
539
|
updateDOM() {
|
|
538
540
|
return false;
|
|
539
541
|
}
|
|
542
|
+
eq(widget) {
|
|
543
|
+
return widget._color === this._color;
|
|
544
|
+
}
|
|
540
545
|
get estimatedHeight() {
|
|
541
546
|
return -1;
|
|
542
547
|
}
|
|
@@ -545,12 +550,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
545
550
|
}
|
|
546
551
|
};
|
|
547
552
|
var styles = EditorView.baseTheme({
|
|
548
|
-
".cm-
|
|
549
|
-
".cm-
|
|
553
|
+
".cm-collab-selection": {},
|
|
554
|
+
".cm-collab-selectionLine": {
|
|
550
555
|
padding: 0,
|
|
551
556
|
margin: "0px 2px 0px 4px"
|
|
552
557
|
},
|
|
553
|
-
".cm-
|
|
558
|
+
".cm-collab-selectionCaret": {
|
|
554
559
|
position: "relative",
|
|
555
560
|
borderLeft: "1px solid black",
|
|
556
561
|
borderRight: "1px solid black",
|
|
@@ -559,7 +564,7 @@ var styles = EditorView.baseTheme({
|
|
|
559
564
|
boxSizing: "border-box",
|
|
560
565
|
display: "inline"
|
|
561
566
|
},
|
|
562
|
-
".cm-
|
|
567
|
+
".cm-collab-selectionCaretDot": {
|
|
563
568
|
borderRadius: "50%",
|
|
564
569
|
position: "absolute",
|
|
565
570
|
width: ".4em",
|
|
@@ -570,11 +575,11 @@ var styles = EditorView.baseTheme({
|
|
|
570
575
|
transition: "transform .3s ease-in-out",
|
|
571
576
|
boxSizing: "border-box"
|
|
572
577
|
},
|
|
573
|
-
".cm-
|
|
578
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
574
579
|
transformOrigin: "bottom center",
|
|
575
580
|
transform: "scale(0)"
|
|
576
581
|
},
|
|
577
|
-
".cm-
|
|
582
|
+
".cm-collab-selectionInfo": {
|
|
578
583
|
position: "absolute",
|
|
579
584
|
top: "-1.05em",
|
|
580
585
|
left: "-1px",
|
|
@@ -590,12 +595,12 @@ var styles = EditorView.baseTheme({
|
|
|
590
595
|
zIndex: 101,
|
|
591
596
|
transition: "opacity .3s ease-in-out",
|
|
592
597
|
backgroundColor: "inherit",
|
|
593
|
-
//
|
|
598
|
+
// These should be separate.
|
|
594
599
|
opacity: 0,
|
|
595
600
|
transitionDelay: "0s",
|
|
596
601
|
whiteSpace: "nowrap"
|
|
597
602
|
},
|
|
598
|
-
".cm-
|
|
603
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionInfo": {
|
|
599
604
|
opacity: 1,
|
|
600
605
|
transitionDelay: "0s"
|
|
601
606
|
}
|
|
@@ -622,7 +627,7 @@ var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
|
622
627
|
import { EditorView as EditorView3, keymap as keymap2 } from "@codemirror/view";
|
|
623
628
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
624
629
|
import { invariant } from "@dxos/invariant";
|
|
625
|
-
var
|
|
630
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
626
631
|
var defaultOptions = {
|
|
627
632
|
effect: 2,
|
|
628
633
|
maxParticles: 200,
|
|
@@ -667,12 +672,12 @@ var blast = (options = defaultOptions) => {
|
|
|
667
672
|
};
|
|
668
673
|
return [
|
|
669
674
|
// Cursor moved.
|
|
670
|
-
EditorView3.updateListener.of((
|
|
671
|
-
if (blaster?.node !==
|
|
675
|
+
EditorView3.updateListener.of((update2) => {
|
|
676
|
+
if (blaster?.node !== update2.view.scrollDOM) {
|
|
672
677
|
if (blaster) {
|
|
673
678
|
blaster.destroy();
|
|
674
679
|
}
|
|
675
|
-
blaster = new Blaster(
|
|
680
|
+
blaster = new Blaster(update2.view.scrollDOM, defaultsDeep({
|
|
676
681
|
particleGravity: 0.2,
|
|
677
682
|
particleShrinkRate: 0.995,
|
|
678
683
|
color: () => [
|
|
@@ -686,10 +691,10 @@ var blast = (options = defaultOptions) => {
|
|
|
686
691
|
} else {
|
|
687
692
|
blaster.resize();
|
|
688
693
|
}
|
|
689
|
-
const current =
|
|
694
|
+
const current = update2.state.selection.main.head;
|
|
690
695
|
if (current !== last) {
|
|
691
696
|
last = current;
|
|
692
|
-
const { element, point } = getPoint(
|
|
697
|
+
const { element, point } = getPoint(update2.view, current - 1);
|
|
693
698
|
if (element && point) {
|
|
694
699
|
blaster.spawn({
|
|
695
700
|
element,
|
|
@@ -749,7 +754,7 @@ var Blaster = class {
|
|
|
749
754
|
}
|
|
750
755
|
initialize() {
|
|
751
756
|
invariant(!this._canvas && !this._ctx, void 0, {
|
|
752
|
-
F:
|
|
757
|
+
F: __dxlog_file,
|
|
753
758
|
L: 138,
|
|
754
759
|
S: this,
|
|
755
760
|
A: [
|
|
@@ -786,7 +791,7 @@ var Blaster = class {
|
|
|
786
791
|
}
|
|
787
792
|
start() {
|
|
788
793
|
invariant(this._canvas && this._ctx, void 0, {
|
|
789
|
-
F:
|
|
794
|
+
F: __dxlog_file,
|
|
790
795
|
L: 177,
|
|
791
796
|
S: this,
|
|
792
797
|
A: [
|
|
@@ -930,7 +935,6 @@ var random = (min, max) => {
|
|
|
930
935
|
|
|
931
936
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
932
937
|
import { ViewPlugin as ViewPlugin3, EditorView as EditorView4, Decoration as Decoration2 } from "@codemirror/view";
|
|
933
|
-
import get2 from "lodash.get";
|
|
934
938
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
935
939
|
|
|
936
940
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1014,20 +1018,22 @@ var inlineUrl = mx(code, "px-1");
|
|
|
1014
1018
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1015
1019
|
|
|
1016
1020
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1021
|
+
import get2 from "lodash.get";
|
|
1017
1022
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1018
1023
|
var tokens = tailwindConfig({}).theme;
|
|
1024
|
+
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1019
1025
|
|
|
1020
1026
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1021
1027
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1022
1028
|
var styles2 = EditorView4.baseTheme({
|
|
1023
1029
|
"& .cm-codeblock": {
|
|
1024
|
-
fontFamily:
|
|
1030
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1025
1031
|
},
|
|
1026
1032
|
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1027
|
-
background:
|
|
1033
|
+
background: getToken("extend.colors.neutral.50")
|
|
1028
1034
|
},
|
|
1029
1035
|
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1030
|
-
background:
|
|
1036
|
+
background: getToken("extend.colors.neutral.850")
|
|
1031
1037
|
},
|
|
1032
1038
|
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1033
1039
|
display: "block",
|
|
@@ -1053,20 +1059,18 @@ var getLineRange = (lines, from, to) => {
|
|
|
1053
1059
|
];
|
|
1054
1060
|
};
|
|
1055
1061
|
var code2 = () => {
|
|
1056
|
-
const
|
|
1062
|
+
const buildDecorations4 = (view) => {
|
|
1057
1063
|
const decorations = [];
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
}).range(block.from));
|
|
1069
|
-
}
|
|
1064
|
+
const text = view.state.doc.sliceString(0);
|
|
1065
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1066
|
+
const blocks = view.viewportLineBlocks;
|
|
1067
|
+
for (const match of matches) {
|
|
1068
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1069
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1070
|
+
const block = blocks[i];
|
|
1071
|
+
decorations.push(Decoration2.line({
|
|
1072
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1073
|
+
}).range(block.from));
|
|
1070
1074
|
}
|
|
1071
1075
|
}
|
|
1072
1076
|
return Decoration2.set(decorations);
|
|
@@ -1074,11 +1078,16 @@ var code2 = () => {
|
|
|
1074
1078
|
return [
|
|
1075
1079
|
ViewPlugin3.fromClass(class {
|
|
1076
1080
|
constructor(view) {
|
|
1077
|
-
this.
|
|
1081
|
+
this.hasFocus = false;
|
|
1082
|
+
this.decorations = buildDecorations4(view);
|
|
1078
1083
|
}
|
|
1079
|
-
update(
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
1084
|
+
update(update2) {
|
|
1085
|
+
if (
|
|
1086
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1087
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1088
|
+
) {
|
|
1089
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1090
|
+
this.decorations = buildDecorations4(update2.view);
|
|
1082
1091
|
}
|
|
1083
1092
|
}
|
|
1084
1093
|
}, {
|
|
@@ -1090,29 +1099,36 @@ var code2 = () => {
|
|
|
1090
1099
|
|
|
1091
1100
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1092
1101
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1093
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5
|
|
1094
|
-
import get3 from "lodash.get";
|
|
1102
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
|
|
1095
1103
|
import sortBy from "lodash.sortby";
|
|
1096
1104
|
import { debounce } from "@dxos/async";
|
|
1097
1105
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1098
|
-
import { log as log2 } from "@dxos/log";
|
|
1099
1106
|
import { nonNullable } from "@dxos/util";
|
|
1107
|
+
|
|
1108
|
+
// packages/ui/react-ui-editor/src/util.ts
|
|
1109
|
+
import { log } from "@dxos/log";
|
|
1110
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1111
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
1112
|
+
try {
|
|
1113
|
+
return fn(...args);
|
|
1114
|
+
} catch (error) {
|
|
1115
|
+
log.catch(error, void 0, {
|
|
1116
|
+
F: __dxlog_file2,
|
|
1117
|
+
L: 16,
|
|
1118
|
+
S: void 0,
|
|
1119
|
+
C: (f, a) => f(...a)
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1124
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1100
1125
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1101
1126
|
var styles3 = EditorView5.baseTheme({
|
|
1102
|
-
"& .cm-bookmark": {
|
|
1103
|
-
cursor: "pointer",
|
|
1104
|
-
margin: "4px",
|
|
1105
|
-
padding: "4px",
|
|
1106
|
-
backgroundColor: "yellow"
|
|
1107
|
-
},
|
|
1108
|
-
"& .cm-bookmark-selected": {
|
|
1109
|
-
backgroundColor: "orange"
|
|
1110
|
-
},
|
|
1111
1127
|
"& .cm-comment": {
|
|
1112
|
-
backgroundColor:
|
|
1128
|
+
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1113
1129
|
},
|
|
1114
1130
|
"& .cm-comment-active": {
|
|
1115
|
-
backgroundColor:
|
|
1131
|
+
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1116
1132
|
}
|
|
1117
1133
|
});
|
|
1118
1134
|
var marks = {
|
|
@@ -1146,7 +1162,7 @@ var commentsStateField = StateField2.define({
|
|
|
1146
1162
|
ranges: []
|
|
1147
1163
|
}),
|
|
1148
1164
|
update: (value, tr) => {
|
|
1149
|
-
const cursorConverter3 = tr.state.facet(
|
|
1165
|
+
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1150
1166
|
for (const effect of tr.effects) {
|
|
1151
1167
|
if (effect.is(setSelection)) {
|
|
1152
1168
|
return {
|
|
@@ -1157,7 +1173,7 @@ var commentsStateField = StateField2.define({
|
|
|
1157
1173
|
if (effect.is(setCommentRange)) {
|
|
1158
1174
|
const { comments: comments2 } = effect.value;
|
|
1159
1175
|
const ranges = comments2.map((comment) => {
|
|
1160
|
-
const range = getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1176
|
+
const range = Cursor.getRangeFromCursor(cursorConverter3, comment.cursor);
|
|
1161
1177
|
return range && {
|
|
1162
1178
|
...comment,
|
|
1163
1179
|
...range
|
|
@@ -1195,58 +1211,89 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1195
1211
|
}).filter(nonNullable) ?? [];
|
|
1196
1212
|
return Decoration3.set(decorations);
|
|
1197
1213
|
});
|
|
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();
|
|
1214
|
+
var trackPastedComments = (onUpdate) => {
|
|
1215
|
+
let tracked = null;
|
|
1216
|
+
const handleTrack = (event, view) => {
|
|
1217
|
+
const comments2 = view.state.field(commentsStateField);
|
|
1218
|
+
const { main } = view.state.selection;
|
|
1219
|
+
const selectedRanges = comments2.ranges.filter((range) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1220
|
+
if (!selectedRanges.length) {
|
|
1221
|
+
tracked = null;
|
|
1222
|
+
} else {
|
|
1223
|
+
tracked = {
|
|
1224
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1225
|
+
comments: selectedRanges.map((range) => ({
|
|
1226
|
+
id: range.id,
|
|
1227
|
+
from: range.from - main.from,
|
|
1228
|
+
to: range.to - main.from
|
|
1229
|
+
}))
|
|
1230
|
+
};
|
|
1223
1231
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1232
|
+
};
|
|
1233
|
+
return [
|
|
1234
|
+
EditorView5.domEventHandlers({
|
|
1235
|
+
cut: handleTrack,
|
|
1236
|
+
copy: handleTrack
|
|
1237
|
+
}),
|
|
1238
|
+
// Handle paste.
|
|
1239
|
+
EditorView5.updateListener.of(({ view, state, transactions }) => {
|
|
1240
|
+
if (tracked) {
|
|
1241
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1242
|
+
if (paste) {
|
|
1243
|
+
let found = -1;
|
|
1244
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1245
|
+
if (text.eq(tracked.text)) {
|
|
1246
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1247
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1248
|
+
}
|
|
1249
|
+
found = fromB;
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
if (found > -1) {
|
|
1253
|
+
const comments2 = tracked.comments;
|
|
1254
|
+
view.state.facet(semaphoreFacet).reconcile(view);
|
|
1255
|
+
const active = state.field(commentsStateField).ranges;
|
|
1256
|
+
for (const moved of comments2) {
|
|
1257
|
+
if (active.some((range) => range.id === moved.id && range.from === range.to)) {
|
|
1258
|
+
const range = {
|
|
1259
|
+
from: found + moved.from,
|
|
1260
|
+
to: found + moved.to
|
|
1261
|
+
};
|
|
1262
|
+
const cursor = Cursor.getCursorFromRange(state.facet(Cursor.converter), range);
|
|
1263
|
+
onUpdate(moved.id, cursor);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
tracked = null;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
})
|
|
1271
|
+
];
|
|
1226
1272
|
};
|
|
1227
1273
|
var comments = (options = {}) => {
|
|
1274
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1228
1275
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
1276
|
const createCommentThread = (view) => {
|
|
1230
|
-
const cursorConverter3 = view.state.facet(
|
|
1277
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1231
1278
|
invariant2(options.onCreate, void 0, {
|
|
1232
1279
|
F: __dxlog_file3,
|
|
1233
|
-
L:
|
|
1280
|
+
L: 264,
|
|
1234
1281
|
S: void 0,
|
|
1235
1282
|
A: [
|
|
1236
1283
|
"options.onCreate",
|
|
1237
1284
|
""
|
|
1238
1285
|
]
|
|
1239
1286
|
});
|
|
1240
|
-
const {
|
|
1287
|
+
const { from, to } = view.state.selection.main;
|
|
1241
1288
|
if (from === to) {
|
|
1242
1289
|
return false;
|
|
1243
1290
|
}
|
|
1244
|
-
const
|
|
1291
|
+
const cursor = Cursor.getCursorFromRange(cursorConverter3, {
|
|
1245
1292
|
from,
|
|
1246
1293
|
to
|
|
1247
1294
|
});
|
|
1248
|
-
if (
|
|
1249
|
-
const id = callbackWrapper(options.onCreate)(
|
|
1295
|
+
if (cursor) {
|
|
1296
|
+
const id = callbackWrapper(options.onCreate)(cursor, view.coordsAtPos(from));
|
|
1250
1297
|
if (id) {
|
|
1251
1298
|
view.dispatch({
|
|
1252
1299
|
effects: setSelection.of({
|
|
@@ -1256,52 +1303,12 @@ var comments = (options = {}) => {
|
|
|
1256
1303
|
anchor: from
|
|
1257
1304
|
}
|
|
1258
1305
|
});
|
|
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
1306
|
return true;
|
|
1272
1307
|
}
|
|
1273
1308
|
}
|
|
1274
1309
|
return false;
|
|
1275
1310
|
};
|
|
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(update4) {
|
|
1295
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update4, 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
1311
|
return [
|
|
1304
|
-
bookmarksViewPlugin,
|
|
1305
1312
|
commentsStateField,
|
|
1306
1313
|
highlightDecorations,
|
|
1307
1314
|
styles3,
|
|
@@ -1310,7 +1317,7 @@ var comments = (options = {}) => {
|
|
|
1310
1317
|
//
|
|
1311
1318
|
options.onCreate ? keymap3.of([
|
|
1312
1319
|
{
|
|
1313
|
-
key:
|
|
1320
|
+
key: shortcut,
|
|
1314
1321
|
run: callbackWrapper(createCommentThread)
|
|
1315
1322
|
}
|
|
1316
1323
|
]) : [],
|
|
@@ -1327,7 +1334,7 @@ var comments = (options = {}) => {
|
|
|
1327
1334
|
above: true,
|
|
1328
1335
|
create: () => {
|
|
1329
1336
|
const el = document.createElement("div");
|
|
1330
|
-
options.onHover
|
|
1337
|
+
options.onHover(el, shortcut);
|
|
1331
1338
|
return {
|
|
1332
1339
|
dom: el,
|
|
1333
1340
|
offset: {
|
|
@@ -1340,7 +1347,8 @@ var comments = (options = {}) => {
|
|
|
1340
1347
|
}
|
|
1341
1348
|
return null;
|
|
1342
1349
|
}, {
|
|
1343
|
-
|
|
1350
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1351
|
+
// hideOnChange: true,
|
|
1344
1352
|
hoverTime: 1e3
|
|
1345
1353
|
}) : [],
|
|
1346
1354
|
//
|
|
@@ -1348,27 +1356,20 @@ var comments = (options = {}) => {
|
|
|
1348
1356
|
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1349
1357
|
//
|
|
1350
1358
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1351
|
-
const cursorConverter3 = view.state.facet(
|
|
1359
|
+
const cursorConverter3 = view.state.facet(Cursor.converter);
|
|
1352
1360
|
{
|
|
1353
1361
|
let mod = false;
|
|
1354
1362
|
const { active, ranges } = state.field(commentsStateField);
|
|
1355
1363
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1356
1364
|
ranges.forEach((range) => {
|
|
1357
1365
|
if (from2 === to2) {
|
|
1358
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1366
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1359
1367
|
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
|
-
|
|
1361
|
-
thread: range.id
|
|
1362
|
-
}, {
|
|
1363
|
-
F: __dxlog_file3,
|
|
1364
|
-
L: 359,
|
|
1365
|
-
S: void 0,
|
|
1366
|
-
C: (f, a) => f(...a)
|
|
1367
|
-
});
|
|
1368
|
+
options.onDelete?.(range.id);
|
|
1368
1369
|
}
|
|
1369
1370
|
}
|
|
1370
1371
|
if (from <= range.to) {
|
|
1371
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
|
+
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1372
1373
|
Object.assign(range, newRange);
|
|
1373
1374
|
mod = true;
|
|
1374
1375
|
}
|
|
@@ -1414,38 +1415,21 @@ var comments = (options = {}) => {
|
|
|
1414
1415
|
});
|
|
1415
1416
|
}
|
|
1416
1417
|
}
|
|
1417
|
-
})
|
|
1418
|
+
}),
|
|
1419
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1418
1420
|
];
|
|
1419
1421
|
};
|
|
1420
|
-
var getCursorFromRange = (cursorConverter3, range) => {
|
|
1421
|
-
const from = cursorConverter3.toCursor(range.from);
|
|
1422
|
-
const to = cursorConverter3.toCursor(range.to, -1);
|
|
1423
|
-
return [
|
|
1424
|
-
from,
|
|
1425
|
-
to
|
|
1426
|
-
].join(":");
|
|
1427
|
-
};
|
|
1428
|
-
var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
1429
|
-
const parts = cursor.split(":");
|
|
1430
|
-
const from = cursorConverter3.fromCursor(parts[0]);
|
|
1431
|
-
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1432
|
-
return from && to ? {
|
|
1433
|
-
from,
|
|
1434
|
-
to
|
|
1435
|
-
} : void 0;
|
|
1436
|
-
};
|
|
1437
1422
|
|
|
1438
1423
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
-
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator
|
|
1440
|
-
import get4 from "lodash.get";
|
|
1424
|
+
import { Decoration as Decoration4, EditorView as EditorView6, MatchDecorator, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1441
1425
|
var styles4 = EditorView6.baseTheme({
|
|
1442
1426
|
"& .cm-hr": {
|
|
1443
1427
|
// TODO(burdon): ???
|
|
1444
1428
|
// Note that block-level decorations should not have vertical margins,
|
|
1445
|
-
borderBottom: `1px solid ${
|
|
1429
|
+
borderBottom: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1446
1430
|
}
|
|
1447
1431
|
});
|
|
1448
|
-
var HorizontalRuleWidget = class extends
|
|
1432
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1449
1433
|
constructor(_pos) {
|
|
1450
1434
|
super();
|
|
1451
1435
|
this._pos = _pos;
|
|
@@ -1459,43 +1443,62 @@ var HorizontalRuleWidget = class extends WidgetType3 {
|
|
|
1459
1443
|
return el;
|
|
1460
1444
|
}
|
|
1461
1445
|
};
|
|
1462
|
-
var placeholderMatcher = new
|
|
1463
|
-
regexp:
|
|
1446
|
+
var placeholderMatcher = new MatchDecorator({
|
|
1447
|
+
// regexp: /(?<=\n\n)---/gs,
|
|
1448
|
+
regexp: /^---$/gs,
|
|
1464
1449
|
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
1450
|
widget: new HorizontalRuleWidget(pos)
|
|
1466
1451
|
})
|
|
1467
1452
|
});
|
|
1468
1453
|
var hr = () => [
|
|
1469
1454
|
styles4,
|
|
1470
|
-
|
|
1455
|
+
ViewPlugin4.fromClass(class {
|
|
1471
1456
|
constructor(view) {
|
|
1472
1457
|
this.rules = placeholderMatcher.createDeco(view);
|
|
1473
1458
|
}
|
|
1474
|
-
update(
|
|
1475
|
-
this.rules = placeholderMatcher.updateDeco(
|
|
1459
|
+
update(update2) {
|
|
1460
|
+
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1476
1461
|
}
|
|
1477
1462
|
}, {
|
|
1478
|
-
decorations: (instance) => instance.rules
|
|
1479
|
-
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1480
|
-
provide: (plugin) => EditorView6.atomicRanges.of((view) => {
|
|
1481
|
-
return view.plugin(plugin)?.rules || Decoration4.none;
|
|
1482
|
-
})
|
|
1463
|
+
decorations: (instance) => instance.rules
|
|
1483
1464
|
})
|
|
1484
1465
|
];
|
|
1485
1466
|
|
|
1486
1467
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
1468
|
import { syntaxTree } from "@codemirror/language";
|
|
1488
|
-
import {
|
|
1489
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as
|
|
1469
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1470
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1490
1471
|
var image = (options = {}) => {
|
|
1491
1472
|
return StateField3.define({
|
|
1492
|
-
create: (state) =>
|
|
1493
|
-
|
|
1473
|
+
create: (state) => {
|
|
1474
|
+
return Decoration5.set(buildDecorations(0, state.doc.length, state));
|
|
1475
|
+
},
|
|
1476
|
+
update: (value, tr) => {
|
|
1477
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1478
|
+
return value;
|
|
1479
|
+
}
|
|
1480
|
+
const cursor = tr.state.selection.main.head;
|
|
1481
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1482
|
+
let from = Math.min(cursor, oldCursor);
|
|
1483
|
+
let to = Math.max(cursor, oldCursor);
|
|
1484
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1485
|
+
from = Math.min(from, fromB);
|
|
1486
|
+
to = Math.max(to, toB);
|
|
1487
|
+
});
|
|
1488
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1489
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1490
|
+
return value.map(tr.changes).update({
|
|
1491
|
+
filterFrom: from,
|
|
1492
|
+
filterTo: to,
|
|
1493
|
+
filter: () => false,
|
|
1494
|
+
add: buildDecorations(from, to, tr.state)
|
|
1495
|
+
});
|
|
1496
|
+
},
|
|
1494
1497
|
provide: (field) => EditorView7.decorations.from(field)
|
|
1495
1498
|
});
|
|
1496
1499
|
};
|
|
1497
|
-
var
|
|
1498
|
-
const
|
|
1500
|
+
var buildDecorations = (from, to, state) => {
|
|
1501
|
+
const decorations = [];
|
|
1499
1502
|
const cursor = state.selection.main.head;
|
|
1500
1503
|
syntaxTree(state).iterate({
|
|
1501
1504
|
enter: (node) => {
|
|
@@ -1504,22 +1507,23 @@ var update = (state, options) => {
|
|
|
1504
1507
|
if (urlNode) {
|
|
1505
1508
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1506
1509
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1507
|
-
|
|
1510
|
+
decorations.push(Decoration5.replace({
|
|
1508
1511
|
block: true,
|
|
1509
1512
|
widget: new ImageWidget(url)
|
|
1510
|
-
}));
|
|
1513
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1511
1514
|
}
|
|
1512
1515
|
}
|
|
1513
|
-
}
|
|
1516
|
+
},
|
|
1517
|
+
from,
|
|
1518
|
+
to
|
|
1514
1519
|
});
|
|
1515
|
-
return
|
|
1520
|
+
return decorations;
|
|
1516
1521
|
};
|
|
1517
|
-
var ImageWidget = class extends
|
|
1522
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1518
1523
|
constructor(_url) {
|
|
1519
1524
|
super();
|
|
1520
1525
|
this._url = _url;
|
|
1521
1526
|
}
|
|
1522
|
-
// TODO(burdon): Does this need to be unique for each position?
|
|
1523
1527
|
eq(other) {
|
|
1524
1528
|
return this._url === other._url;
|
|
1525
1529
|
}
|
|
@@ -1527,22 +1531,29 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1527
1531
|
const img = document.createElement("img");
|
|
1528
1532
|
img.setAttribute("src", this._url);
|
|
1529
1533
|
img.setAttribute("class", "cm-image");
|
|
1534
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1530
1535
|
return img;
|
|
1531
1536
|
}
|
|
1532
1537
|
};
|
|
1533
1538
|
|
|
1534
1539
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1535
1540
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1536
|
-
import { RangeSetBuilder
|
|
1537
|
-
import {
|
|
1541
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1542
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1538
1543
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1539
|
-
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
1540
1544
|
var link = (options = {}) => {
|
|
1541
1545
|
const extensions = [
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
+
ViewPlugin5.fromClass(class {
|
|
1547
|
+
constructor(view) {
|
|
1548
|
+
this.decorations = buildDecorations2(view, options);
|
|
1549
|
+
}
|
|
1550
|
+
update(update2) {
|
|
1551
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1552
|
+
this.decorations = buildDecorations2(update2.view, options);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
}, {
|
|
1556
|
+
decorations: (v) => v.decorations
|
|
1546
1557
|
})
|
|
1547
1558
|
];
|
|
1548
1559
|
if (options.onHover) {
|
|
@@ -1550,35 +1561,25 @@ var link = (options = {}) => {
|
|
|
1550
1561
|
// https://codemirror.net/examples/tooltip
|
|
1551
1562
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1552
1563
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1553
|
-
hoverTooltip2((view, pos) => {
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1556
|
-
let
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
match = void 0;
|
|
1562
|
-
break;
|
|
1563
|
-
}
|
|
1564
|
-
idx = text.indexOf(match[0]);
|
|
1565
|
-
if (p >= idx && p < idx + match[0].length) {
|
|
1566
|
-
break;
|
|
1567
|
-
}
|
|
1568
|
-
idx += match[0].length;
|
|
1569
|
-
} while (true);
|
|
1570
|
-
if (!match) {
|
|
1564
|
+
hoverTooltip2((view, pos, side) => {
|
|
1565
|
+
const syntax = syntaxTree2(view.state).resolveInner(pos, side);
|
|
1566
|
+
let link2 = null;
|
|
1567
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1568
|
+
link2 = node.name === "Link" ? node : null;
|
|
1569
|
+
}
|
|
1570
|
+
const url = link2 && link2.getChild("URL");
|
|
1571
|
+
if (!url || !link2) {
|
|
1571
1572
|
return null;
|
|
1572
1573
|
}
|
|
1573
|
-
const
|
|
1574
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1574
1575
|
return {
|
|
1575
|
-
pos:
|
|
1576
|
-
end:
|
|
1576
|
+
pos: link2.from,
|
|
1577
|
+
end: link2.to,
|
|
1577
1578
|
above: true,
|
|
1578
1579
|
create: () => {
|
|
1579
1580
|
const el = document.createElement("div");
|
|
1580
1581
|
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1581
|
-
options.onHover(el,
|
|
1582
|
+
options.onHover(el, urlText);
|
|
1582
1583
|
return {
|
|
1583
1584
|
dom: el,
|
|
1584
1585
|
offset: {
|
|
@@ -1593,15 +1594,14 @@ var link = (options = {}) => {
|
|
|
1593
1594
|
}
|
|
1594
1595
|
return extensions;
|
|
1595
1596
|
};
|
|
1596
|
-
var LinkButton = class extends
|
|
1597
|
-
constructor(
|
|
1597
|
+
var LinkButton = class extends WidgetType4 {
|
|
1598
|
+
constructor(_url, _onAttach) {
|
|
1598
1599
|
super();
|
|
1599
|
-
this._pos = _pos;
|
|
1600
1600
|
this._url = _url;
|
|
1601
1601
|
this._onAttach = _onAttach;
|
|
1602
1602
|
}
|
|
1603
1603
|
eq(other) {
|
|
1604
|
-
return this.
|
|
1604
|
+
return this._url === other._url;
|
|
1605
1605
|
}
|
|
1606
1606
|
toDOM(view) {
|
|
1607
1607
|
const el = document.createElement("span");
|
|
@@ -1609,7 +1609,7 @@ var LinkButton = class extends WidgetType5 {
|
|
|
1609
1609
|
return el;
|
|
1610
1610
|
}
|
|
1611
1611
|
};
|
|
1612
|
-
var LinkText = class extends
|
|
1612
|
+
var LinkText = class extends WidgetType4 {
|
|
1613
1613
|
constructor(_text, _url) {
|
|
1614
1614
|
super();
|
|
1615
1615
|
this._text = _text;
|
|
@@ -1638,46 +1638,51 @@ var LinkText = class extends WidgetType5 {
|
|
|
1638
1638
|
return link2;
|
|
1639
1639
|
}
|
|
1640
1640
|
};
|
|
1641
|
-
var
|
|
1642
|
-
const builder = new
|
|
1641
|
+
var buildDecorations2 = (view, options) => {
|
|
1642
|
+
const builder = new RangeSetBuilder();
|
|
1643
|
+
const { state } = view;
|
|
1643
1644
|
const cursor = state.selection.main.head;
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1645
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1646
|
+
syntaxTree2(state).iterate({
|
|
1647
|
+
enter: (node) => {
|
|
1648
|
+
if (node.name === "Link") {
|
|
1649
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
1650
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1651
|
+
const urlNode = node.node.getChild("URL");
|
|
1652
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1653
|
+
if (!url) {
|
|
1654
|
+
return false;
|
|
1655
|
+
}
|
|
1656
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1657
|
+
builder.add(node.from, node.to, Decoration6.replace({
|
|
1658
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
1659
|
+
}));
|
|
1660
|
+
}
|
|
1661
|
+
if (options.onRender) {
|
|
1662
|
+
builder.add(node.to, node.to, Decoration6.replace({
|
|
1663
|
+
widget: new LinkButton(url, options.onRender)
|
|
1664
|
+
}));
|
|
1665
|
+
}
|
|
1652
1666
|
return false;
|
|
1653
1667
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
if (options.onRender) {
|
|
1660
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1661
|
-
widget: new LinkButton(node.from, url, options.onRender)
|
|
1662
|
-
}));
|
|
1663
|
-
}
|
|
1664
|
-
return false;
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
});
|
|
1668
|
+
},
|
|
1669
|
+
from,
|
|
1670
|
+
to
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1668
1673
|
return builder.finish();
|
|
1669
1674
|
};
|
|
1670
1675
|
|
|
1671
1676
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1672
|
-
import { EditorView as
|
|
1677
|
+
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1673
1678
|
var listener = ({ onFocus, onChange }) => {
|
|
1674
1679
|
const extensions = [];
|
|
1675
|
-
onFocus && extensions.push(
|
|
1680
|
+
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1676
1681
|
onFocus(focused);
|
|
1677
1682
|
return null;
|
|
1678
1683
|
}));
|
|
1679
|
-
onChange && extensions.push(
|
|
1680
|
-
onChange(
|
|
1684
|
+
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1685
|
+
onChange(update2.state.doc.toString());
|
|
1681
1686
|
}));
|
|
1682
1687
|
return extensions;
|
|
1683
1688
|
};
|
|
@@ -1685,27 +1690,25 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1685
1690
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1686
1691
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1687
1692
|
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1688
|
-
import { markdownLanguage as
|
|
1693
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1689
1694
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1690
1695
|
import { languages } from "@codemirror/language-data";
|
|
1691
1696
|
import { searchKeymap } from "@codemirror/search";
|
|
1692
1697
|
import { EditorState } from "@codemirror/state";
|
|
1693
1698
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1694
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1699
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1695
1700
|
|
|
1696
1701
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1697
|
-
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
1702
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1698
1703
|
import { HighlightStyle } from "@codemirror/language";
|
|
1699
1704
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1700
1705
|
import { Table } from "@lezer/markdown";
|
|
1701
|
-
import get5 from "lodash.get";
|
|
1702
1706
|
var markdownTags = {
|
|
1703
1707
|
Blockquote: Tag.define(),
|
|
1704
1708
|
CodeMark: Tag.define(),
|
|
1705
1709
|
CodeText: Tag.define(),
|
|
1706
1710
|
EmphasisMark: Tag.define(),
|
|
1707
1711
|
HeaderMark: Tag.define(),
|
|
1708
|
-
// HorizontalRule: Tag.define(),
|
|
1709
1712
|
InlineCode: Tag.define(),
|
|
1710
1713
|
LinkLabel: Tag.define(),
|
|
1711
1714
|
LinkReference: Tag.define(),
|
|
@@ -1869,12 +1872,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1869
1872
|
],
|
|
1870
1873
|
class: blockquote
|
|
1871
1874
|
},
|
|
1872
|
-
// TODO(burdon): Replace with extension.
|
|
1873
|
-
// {
|
|
1874
|
-
// tag: [markdownTags.HorizontalRule],
|
|
1875
|
-
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1876
|
-
// },
|
|
1877
|
-
// TODO(burdon): Only if being edited.
|
|
1878
1875
|
{
|
|
1879
1876
|
tag: [
|
|
1880
1877
|
markdownTags.TableCell
|
|
@@ -1882,9 +1879,9 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1882
1879
|
class: "font-mono"
|
|
1883
1880
|
}
|
|
1884
1881
|
], {
|
|
1885
|
-
scope:
|
|
1882
|
+
scope: markdownLanguage2,
|
|
1886
1883
|
all: {
|
|
1887
|
-
fontFamily:
|
|
1884
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
1888
1885
|
}
|
|
1889
1886
|
});
|
|
1890
1887
|
};
|
|
@@ -1894,7 +1891,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1894
1891
|
return [
|
|
1895
1892
|
EditorState.allowMultipleSelections.of(true),
|
|
1896
1893
|
EditorState.tabSize.of(2),
|
|
1897
|
-
|
|
1894
|
+
EditorView9.lineWrapping,
|
|
1898
1895
|
customKeymap(),
|
|
1899
1896
|
bracketMatching2(),
|
|
1900
1897
|
closeBrackets2(),
|
|
@@ -1914,7 +1911,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1914
1911
|
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
1915
1912
|
// https://github.github.com/gfm
|
|
1916
1913
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
1917
|
-
base:
|
|
1914
|
+
base: markdownLanguage3,
|
|
1918
1915
|
// Languages for syntax highlighting fenced code blocks.
|
|
1919
1916
|
codeLanguages: languages,
|
|
1920
1917
|
// Parser extensions.
|
|
@@ -1965,24 +1962,24 @@ var mention = ({ onSearch }) => {
|
|
|
1965
1962
|
});
|
|
1966
1963
|
};
|
|
1967
1964
|
|
|
1968
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1969
|
-
var
|
|
1965
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
1966
|
+
var outliner = (options = {}) => {
|
|
1970
1967
|
return [];
|
|
1971
1968
|
};
|
|
1972
1969
|
|
|
1973
1970
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1974
1971
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1975
|
-
import { RangeSetBuilder as
|
|
1976
|
-
import { Decoration as Decoration7, EditorView as
|
|
1972
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField4 } from "@codemirror/state";
|
|
1973
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1977
1974
|
var table = (options = {}) => {
|
|
1978
|
-
return
|
|
1979
|
-
create: (state) =>
|
|
1980
|
-
update: (_, tr) =>
|
|
1981
|
-
provide: (field) =>
|
|
1975
|
+
return StateField4.define({
|
|
1976
|
+
create: (state) => update(state, options),
|
|
1977
|
+
update: (_, tr) => update(tr.state, options),
|
|
1978
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1982
1979
|
});
|
|
1983
1980
|
};
|
|
1984
|
-
var
|
|
1985
|
-
const builder = new
|
|
1981
|
+
var update = (state, options) => {
|
|
1982
|
+
const builder = new RangeSetBuilder2();
|
|
1986
1983
|
const cursor = state.selection.main.head;
|
|
1987
1984
|
const tables = [];
|
|
1988
1985
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2023,7 +2020,6 @@ var update3 = (state, options) => {
|
|
|
2023
2020
|
tables.forEach((table2) => {
|
|
2024
2021
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2025
2022
|
hide && builder.add(table2.from, table2.to, Decoration7.replace({
|
|
2026
|
-
block: true,
|
|
2027
2023
|
widget: new TableWidget(table2)
|
|
2028
2024
|
}));
|
|
2029
2025
|
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
@@ -2032,13 +2028,13 @@ var update3 = (state, options) => {
|
|
|
2032
2028
|
});
|
|
2033
2029
|
return builder.finish();
|
|
2034
2030
|
};
|
|
2035
|
-
var TableWidget = class extends
|
|
2031
|
+
var TableWidget = class extends WidgetType5 {
|
|
2036
2032
|
constructor(_table) {
|
|
2037
2033
|
super();
|
|
2038
2034
|
this._table = _table;
|
|
2039
2035
|
}
|
|
2040
2036
|
eq(other) {
|
|
2041
|
-
return this._table.
|
|
2037
|
+
return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
|
|
2042
2038
|
}
|
|
2043
2039
|
toDOM(view) {
|
|
2044
2040
|
const table2 = document.createElement("table");
|
|
@@ -2064,91 +2060,92 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2064
2060
|
}
|
|
2065
2061
|
return table2;
|
|
2066
2062
|
}
|
|
2063
|
+
ignoreEvent(e) {
|
|
2064
|
+
return !/^mouse/.test(e.type);
|
|
2065
|
+
}
|
|
2067
2066
|
};
|
|
2068
2067
|
|
|
2069
2068
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2070
|
-
import {
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
}
|
|
2076
|
-
});
|
|
2077
|
-
var CheckboxWidget = class extends WidgetType7 {
|
|
2078
|
-
constructor(_pos, _checked, _indent, _onCheck) {
|
|
2069
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2070
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
2071
|
+
import { EditorView as EditorView11, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2072
|
+
var CheckboxWidget = class extends WidgetType6 {
|
|
2073
|
+
constructor(_checked) {
|
|
2079
2074
|
super();
|
|
2080
|
-
this._pos = _pos;
|
|
2081
2075
|
this._checked = _checked;
|
|
2082
|
-
this._indent = _indent;
|
|
2083
|
-
this._onCheck = _onCheck;
|
|
2084
2076
|
}
|
|
2085
2077
|
eq(other) {
|
|
2086
|
-
return this.
|
|
2078
|
+
return this._checked === other._checked;
|
|
2087
2079
|
}
|
|
2088
2080
|
toDOM(view) {
|
|
2089
|
-
const
|
|
2090
|
-
wrap.className = "cm-task-item";
|
|
2091
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2092
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2093
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2081
|
+
const input = document.createElement("input");
|
|
2094
2082
|
input.type = "checkbox";
|
|
2095
2083
|
input.checked = this._checked;
|
|
2096
|
-
if (
|
|
2084
|
+
if (view.state.readOnly) {
|
|
2097
2085
|
input.setAttribute("disabled", "true");
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2086
|
+
} else {
|
|
2087
|
+
input.onmousedown = (event) => {
|
|
2088
|
+
const pos = view.posAtDOM(input);
|
|
2089
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2090
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2091
|
+
view.dispatch({
|
|
2092
|
+
changes: {
|
|
2093
|
+
from: pos + 1,
|
|
2094
|
+
to: pos + 2,
|
|
2095
|
+
insert: this._checked ? " " : "x"
|
|
2096
|
+
}
|
|
2097
|
+
});
|
|
2098
|
+
event.preventDefault();
|
|
2099
|
+
}
|
|
2103
2100
|
};
|
|
2104
2101
|
}
|
|
2105
|
-
return
|
|
2102
|
+
return input;
|
|
2106
2103
|
}
|
|
2107
2104
|
ignoreEvent() {
|
|
2108
2105
|
return false;
|
|
2109
2106
|
}
|
|
2110
2107
|
};
|
|
2108
|
+
var checkedDeco = Decoration8.replace({
|
|
2109
|
+
widget: new CheckboxWidget(true)
|
|
2110
|
+
});
|
|
2111
|
+
var uncheckedDeco = Decoration8.replace({
|
|
2112
|
+
widget: new CheckboxWidget(false)
|
|
2113
|
+
});
|
|
2111
2114
|
var tasklist = (options = {}) => {
|
|
2112
|
-
|
|
2113
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2114
|
-
decoration: (match, view, pos) => {
|
|
2115
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2116
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2117
|
-
return Decoration8.replace({
|
|
2118
|
-
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2119
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2120
|
-
view.dispatch({
|
|
2121
|
-
changes: {
|
|
2122
|
-
from: idx,
|
|
2123
|
-
to: idx + 1,
|
|
2124
|
-
insert: checked2 ? "x" : " "
|
|
2125
|
-
},
|
|
2126
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2127
|
-
selection: {
|
|
2128
|
-
anchor: idx + 3
|
|
2129
|
-
}
|
|
2130
|
-
});
|
|
2131
|
-
})
|
|
2132
|
-
});
|
|
2133
|
-
}
|
|
2134
|
-
});
|
|
2135
|
-
const tasks = ViewPlugin6.fromClass(class {
|
|
2115
|
+
return ViewPlugin6.fromClass(class {
|
|
2136
2116
|
constructor(view) {
|
|
2137
|
-
this.
|
|
2117
|
+
this.decorations = buildDecorations3(view);
|
|
2138
2118
|
}
|
|
2139
|
-
update(
|
|
2140
|
-
|
|
2119
|
+
update(update2) {
|
|
2120
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2121
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2122
|
+
}
|
|
2141
2123
|
}
|
|
2142
2124
|
}, {
|
|
2143
|
-
decorations: (
|
|
2144
|
-
|
|
2145
|
-
|
|
2125
|
+
decorations: (v) => v.decorations,
|
|
2126
|
+
// TODO(burdon): Is this still required?
|
|
2127
|
+
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2128
|
+
return view.plugin(plugin)?.decorations || Decoration8.none;
|
|
2146
2129
|
})
|
|
2147
2130
|
});
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2131
|
+
};
|
|
2132
|
+
var buildDecorations3 = (view) => {
|
|
2133
|
+
const builder = new RangeSetBuilder3();
|
|
2134
|
+
const { state } = view;
|
|
2135
|
+
const cursor = state.selection.main.head;
|
|
2136
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2137
|
+
syntaxTree4(state).iterate({
|
|
2138
|
+
enter: (node) => {
|
|
2139
|
+
if (node.name === "TaskMarker" && (cursor < node.from || cursor > node.to)) {
|
|
2140
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2141
|
+
builder.add(node.from, node.to, checked ? checkedDeco : uncheckedDeco);
|
|
2142
|
+
}
|
|
2143
|
+
},
|
|
2144
|
+
from,
|
|
2145
|
+
to
|
|
2146
|
+
});
|
|
2147
|
+
}
|
|
2148
|
+
return builder.finish();
|
|
2152
2149
|
};
|
|
2153
2150
|
|
|
2154
2151
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
@@ -2225,12 +2222,12 @@ var cursorConverter2 = (text) => ({
|
|
|
2225
2222
|
|
|
2226
2223
|
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2227
2224
|
var yjs = (content, awareness2) => [
|
|
2228
|
-
|
|
2225
|
+
Cursor.converter.of(cursorConverter2(content)),
|
|
2229
2226
|
yCollab(content, awareness2)
|
|
2230
2227
|
];
|
|
2231
2228
|
|
|
2232
2229
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2233
|
-
import
|
|
2230
|
+
import get3 from "lodash.get";
|
|
2234
2231
|
var defaultTheme = {
|
|
2235
2232
|
//
|
|
2236
2233
|
// Main layout:
|
|
@@ -2259,21 +2256,21 @@ var defaultTheme = {
|
|
|
2259
2256
|
"&.cm-focused": {
|
|
2260
2257
|
outline: "none"
|
|
2261
2258
|
},
|
|
2262
|
-
"
|
|
2259
|
+
".cm-scroller": {
|
|
2263
2260
|
overflow: "visible",
|
|
2264
|
-
fontFamily:
|
|
2261
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2265
2262
|
},
|
|
2266
|
-
"
|
|
2263
|
+
".cm-content": {
|
|
2267
2264
|
padding: 0,
|
|
2268
2265
|
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
2269
2266
|
fontSize: "16px"
|
|
2270
2267
|
},
|
|
2271
2268
|
"&light .cm-content": {
|
|
2272
|
-
color:
|
|
2269
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
2273
2270
|
caretColor: "black"
|
|
2274
2271
|
},
|
|
2275
2272
|
"&dark .cm-content": {
|
|
2276
|
-
color:
|
|
2273
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
2277
2274
|
caretColor: "white"
|
|
2278
2275
|
},
|
|
2279
2276
|
//
|
|
@@ -2285,158 +2282,120 @@ var defaultTheme = {
|
|
|
2285
2282
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2286
2283
|
borderLeft: "2px solid white"
|
|
2287
2284
|
},
|
|
2288
|
-
"
|
|
2285
|
+
".cm-placeholder": {
|
|
2289
2286
|
fontWeight: 100
|
|
2290
2287
|
},
|
|
2291
2288
|
//
|
|
2292
2289
|
// line
|
|
2293
2290
|
//
|
|
2294
|
-
"
|
|
2291
|
+
".cm-line": {
|
|
2295
2292
|
paddingInline: 0
|
|
2296
2293
|
},
|
|
2297
|
-
"
|
|
2294
|
+
".cm-activeLine": {
|
|
2298
2295
|
background: "inherit"
|
|
2299
2296
|
},
|
|
2300
2297
|
//
|
|
2301
2298
|
// Selection
|
|
2302
2299
|
//
|
|
2303
2300
|
"&light .cm-selectionBackground": {
|
|
2304
|
-
background:
|
|
2301
|
+
background: get3(tokens, "extend.colors.primary.100")
|
|
2305
2302
|
},
|
|
2306
2303
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2307
|
-
background:
|
|
2304
|
+
background: get3(tokens, "extend.colors.primary.200")
|
|
2308
2305
|
},
|
|
2309
2306
|
"&dark .cm-selectionBackground": {
|
|
2310
|
-
background:
|
|
2307
|
+
background: get3(tokens, "extend.colors.primary.700")
|
|
2311
2308
|
},
|
|
2312
2309
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2313
|
-
background:
|
|
2310
|
+
background: get3(tokens, "extend.colors.primary.600")
|
|
2314
2311
|
},
|
|
2315
2312
|
//
|
|
2316
2313
|
// Search
|
|
2317
2314
|
//
|
|
2318
2315
|
"&light .cm-searchMatch": {
|
|
2319
|
-
backgroundColor:
|
|
2316
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2320
2317
|
},
|
|
2321
2318
|
"&dark .cm-searchMatch": {
|
|
2322
|
-
backgroundColor:
|
|
2323
|
-
},
|
|
2324
|
-
//
|
|
2325
|
-
// collaboration
|
|
2326
|
-
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
2327
|
-
//
|
|
2328
|
-
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
2329
|
-
mixBlendMode: "multiply"
|
|
2330
|
-
},
|
|
2331
|
-
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2332
|
-
mixBlendMode: "screen"
|
|
2333
|
-
},
|
|
2334
|
-
"& .cm-ySelectionInfo": {
|
|
2335
|
-
padding: "2px 4px",
|
|
2336
|
-
marginBlockStart: "-4px"
|
|
2337
|
-
},
|
|
2338
|
-
"& .cm-ySelection, & .cm-selectionMatch": {
|
|
2339
|
-
paddingBlockStart: ".15em",
|
|
2340
|
-
paddingBlockEnd: ".15em"
|
|
2341
|
-
},
|
|
2342
|
-
"& .cm-ySelectionCaret": {
|
|
2343
|
-
display: "inline-block",
|
|
2344
|
-
insetBlockStart: ".1em",
|
|
2345
|
-
blockSize: "1.4em",
|
|
2346
|
-
verticalAlign: "top"
|
|
2347
|
-
},
|
|
2348
|
-
"& .cm-yLineSelection": {
|
|
2349
|
-
margin: 0
|
|
2319
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2350
2320
|
},
|
|
2351
2321
|
//
|
|
2352
2322
|
// link
|
|
2353
2323
|
//
|
|
2354
|
-
"
|
|
2355
|
-
color:
|
|
2324
|
+
".cm-link": {
|
|
2325
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
2356
2326
|
textDecorationLine: "underline",
|
|
2357
2327
|
textDecorationThickness: "1px",
|
|
2358
2328
|
textUnderlineOffset: "2px",
|
|
2359
2329
|
borderRadius: ".125rem",
|
|
2360
|
-
fontFamily:
|
|
2330
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2361
2331
|
},
|
|
2362
2332
|
//
|
|
2363
2333
|
// tooltip
|
|
2364
2334
|
//
|
|
2365
|
-
"
|
|
2335
|
+
".cm-tooltip": {
|
|
2366
2336
|
border: "none"
|
|
2367
2337
|
},
|
|
2368
|
-
"
|
|
2338
|
+
".cm-tooltip-below": {},
|
|
2369
2339
|
//
|
|
2370
2340
|
// autocomplete
|
|
2371
2341
|
//
|
|
2372
|
-
"
|
|
2342
|
+
".cm-tooltip-autocomplete": {
|
|
2373
2343
|
marginTop: "4px",
|
|
2374
2344
|
marginLeft: "-3px"
|
|
2375
2345
|
},
|
|
2376
|
-
"
|
|
2377
|
-
"
|
|
2378
|
-
"
|
|
2346
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
2347
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2348
|
+
".cm-completionIcon": {
|
|
2379
2349
|
display: "none"
|
|
2380
2350
|
},
|
|
2381
|
-
"
|
|
2382
|
-
fontFamily:
|
|
2351
|
+
".cm-completionLabel": {
|
|
2352
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2383
2353
|
},
|
|
2384
|
-
"
|
|
2354
|
+
".cm-completionMatchedText": {
|
|
2385
2355
|
textDecoration: "none"
|
|
2386
2356
|
},
|
|
2387
2357
|
//
|
|
2388
|
-
// widgets
|
|
2389
|
-
//
|
|
2390
|
-
"& .cm-widgetBuffer": {
|
|
2391
|
-
display: "none",
|
|
2392
|
-
height: 0
|
|
2393
|
-
},
|
|
2394
|
-
//
|
|
2395
2358
|
// table
|
|
2396
2359
|
//
|
|
2397
|
-
"
|
|
2398
|
-
fontFamily: `${
|
|
2360
|
+
".cm-table *": {
|
|
2361
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2399
2362
|
textDecoration: "none !important"
|
|
2400
2363
|
},
|
|
2401
|
-
"
|
|
2364
|
+
".cm-table-head": {
|
|
2402
2365
|
padding: "2px 16px 2px 0px",
|
|
2403
|
-
borderBottom: `1px solid ${
|
|
2366
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2404
2367
|
fontWeight: 100,
|
|
2405
2368
|
textAlign: "left",
|
|
2406
|
-
color:
|
|
2369
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
2407
2370
|
},
|
|
2408
|
-
"
|
|
2371
|
+
".cm-table-cell": {
|
|
2409
2372
|
padding: "2px 16px 2px 0px"
|
|
2410
2373
|
},
|
|
2411
2374
|
//
|
|
2412
2375
|
// image
|
|
2413
2376
|
//
|
|
2414
|
-
"
|
|
2415
|
-
|
|
2377
|
+
".cm-image": {
|
|
2378
|
+
display: "block",
|
|
2379
|
+
height: "0"
|
|
2380
|
+
},
|
|
2381
|
+
".cm-image.cm-loaded-image": {
|
|
2382
|
+
height: "auto",
|
|
2383
|
+
borderTop: "0.5rem solid transparent",
|
|
2384
|
+
borderBottom: "0.5rem solid transparent"
|
|
2416
2385
|
},
|
|
2417
2386
|
//
|
|
2418
2387
|
// font size
|
|
2419
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2388
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2389
|
+
// but it's far more verbose than it needs to be.
|
|
2420
2390
|
//
|
|
2421
|
-
...Object.keys(
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
|
|
2430
|
-
height
|
|
2431
|
-
};
|
|
2432
|
-
acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
|
|
2433
|
-
height
|
|
2434
|
-
};
|
|
2435
|
-
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
|
|
2436
|
-
height
|
|
2437
|
-
};
|
|
2438
|
-
return acc;
|
|
2439
|
-
}, {}),
|
|
2391
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2392
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2393
|
+
//
|
|
2394
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2395
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2396
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2397
|
+
// return acc;
|
|
2398
|
+
// }, {}),
|
|
2440
2399
|
/**
|
|
2441
2400
|
* Panels
|
|
2442
2401
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2453,51 +2412,53 @@ var defaultTheme = {
|
|
|
2453
2412
|
* </div>
|
|
2454
2413
|
* </div
|
|
2455
2414
|
*/
|
|
2456
|
-
"
|
|
2457
|
-
border: `1px solid ${
|
|
2415
|
+
".cm-panels": {
|
|
2416
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2458
2417
|
},
|
|
2459
|
-
"
|
|
2460
|
-
background:
|
|
2461
|
-
fontFamily:
|
|
2418
|
+
".cm-panel": {
|
|
2419
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2420
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2462
2421
|
},
|
|
2463
|
-
"
|
|
2422
|
+
".cm-button": {
|
|
2464
2423
|
margin: "4px",
|
|
2465
|
-
fontFamily:
|
|
2466
|
-
background:
|
|
2424
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2425
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2467
2426
|
backgroundImage: "none",
|
|
2468
2427
|
border: "none",
|
|
2469
2428
|
"&:hover": {
|
|
2470
|
-
background:
|
|
2429
|
+
background: get3(tokens, "extend.colors.neutral.200")
|
|
2471
2430
|
},
|
|
2472
2431
|
"&:active": {
|
|
2473
|
-
background:
|
|
2432
|
+
background: get3(tokens, "extend.colors.neutral.300"),
|
|
2474
2433
|
backgroundImage: "none"
|
|
2475
2434
|
}
|
|
2476
2435
|
},
|
|
2477
|
-
"
|
|
2436
|
+
".cm-panel input[type=checkbox]": {
|
|
2478
2437
|
marginRight: "0.4rem !important"
|
|
2479
2438
|
}
|
|
2480
2439
|
};
|
|
2481
2440
|
var textTheme = {
|
|
2482
|
-
"
|
|
2483
|
-
fontFamily:
|
|
2441
|
+
".cm-scroller": {
|
|
2442
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2484
2443
|
},
|
|
2485
|
-
"
|
|
2486
|
-
fontFamily:
|
|
2444
|
+
".cm-placeholder": {
|
|
2445
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2487
2446
|
}
|
|
2488
2447
|
};
|
|
2489
2448
|
var markdownTheme = {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2449
|
+
".cm-scroller": {
|
|
2450
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2451
|
+
},
|
|
2452
|
+
".cm-placeholder": {
|
|
2453
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2493
2454
|
}
|
|
2494
2455
|
};
|
|
2495
2456
|
var codeTheme = {
|
|
2496
|
-
"
|
|
2497
|
-
fontFamily:
|
|
2457
|
+
".cm-scroller": {
|
|
2458
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2498
2459
|
},
|
|
2499
|
-
"
|
|
2500
|
-
fontFamily:
|
|
2460
|
+
".cm-placeholder": {
|
|
2461
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2501
2462
|
}
|
|
2502
2463
|
};
|
|
2503
2464
|
|
|
@@ -2506,21 +2467,23 @@ var EditorModes = [
|
|
|
2506
2467
|
"default",
|
|
2507
2468
|
"vim"
|
|
2508
2469
|
];
|
|
2509
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: comments2, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
|
|
2510
|
-
const { themeMode } = useThemeContext();
|
|
2470
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, autofocus, readonly, selection, comments: comments2, extensions = [], editorMode, theme, slots = defaultSlots }, forwardedRef) => {
|
|
2511
2471
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2512
2472
|
tabBehavior: "limited"
|
|
2513
2473
|
});
|
|
2514
|
-
const
|
|
2515
|
-
const
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2474
|
+
const { themeMode } = useThemeContext();
|
|
2475
|
+
const rootRef = useRef(null);
|
|
2476
|
+
const [view, setView] = useState(null);
|
|
2477
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2478
|
+
view
|
|
2479
|
+
]);
|
|
2480
|
+
useEffect(() => {
|
|
2481
|
+
if (autofocus) {
|
|
2482
|
+
view?.focus();
|
|
2483
|
+
}
|
|
2484
|
+
}, [
|
|
2485
|
+
autofocus,
|
|
2519
2486
|
view
|
|
2520
|
-
}), [
|
|
2521
|
-
view,
|
|
2522
|
-
state,
|
|
2523
|
-
root
|
|
2524
2487
|
]);
|
|
2525
2488
|
const { awareness: awareness2, peer } = model;
|
|
2526
2489
|
useEffect(() => {
|
|
@@ -2544,7 +2507,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2544
2507
|
themeMode
|
|
2545
2508
|
]);
|
|
2546
2509
|
useEffect(() => {
|
|
2547
|
-
if (view && comments2
|
|
2510
|
+
if (view && comments2 !== void 0) {
|
|
2548
2511
|
view.dispatch({
|
|
2549
2512
|
effects: setCommentRange.of({
|
|
2550
2513
|
model,
|
|
@@ -2557,20 +2520,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2557
2520
|
comments2
|
|
2558
2521
|
]);
|
|
2559
2522
|
useEffect(() => {
|
|
2560
|
-
if (!
|
|
2523
|
+
if (!model || !rootRef.current) {
|
|
2561
2524
|
return;
|
|
2562
2525
|
}
|
|
2563
|
-
const
|
|
2526
|
+
const state = EditorState2.create({
|
|
2564
2527
|
doc: model.text(),
|
|
2528
|
+
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2529
|
+
selection,
|
|
2565
2530
|
extensions: [
|
|
2566
2531
|
readonly && EditorState2.readOnly.of(readonly),
|
|
2567
2532
|
// TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
|
|
2568
2533
|
editorMode === "vim" && vim(),
|
|
2569
2534
|
// Theme.
|
|
2570
2535
|
// TODO(burdon): Make theme configurable.
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2536
|
+
EditorView12.baseTheme(defaultTheme),
|
|
2537
|
+
EditorView12.theme(theme ?? {}),
|
|
2538
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
|
2574
2539
|
// Storage and replication.
|
|
2575
2540
|
model.extension,
|
|
2576
2541
|
// Custom.
|
|
@@ -2578,19 +2543,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2578
2543
|
].filter(Boolean)
|
|
2579
2544
|
});
|
|
2580
2545
|
view?.destroy();
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
state: state2,
|
|
2585
|
-
parent: root
|
|
2586
|
-
})
|
|
2546
|
+
const newView = new EditorView12({
|
|
2547
|
+
parent: rootRef.current,
|
|
2548
|
+
state
|
|
2587
2549
|
});
|
|
2550
|
+
setView(newView);
|
|
2588
2551
|
return () => {
|
|
2589
|
-
|
|
2590
|
-
|
|
2552
|
+
newView?.destroy();
|
|
2553
|
+
setView(null);
|
|
2591
2554
|
};
|
|
2592
2555
|
}, [
|
|
2593
|
-
|
|
2556
|
+
rootRef,
|
|
2594
2557
|
model,
|
|
2595
2558
|
readonly,
|
|
2596
2559
|
editorMode,
|
|
@@ -2599,12 +2562,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2599
2562
|
const handleKeyUp = useCallback((event) => {
|
|
2600
2563
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2601
2564
|
switch (key) {
|
|
2602
|
-
case "Enter": {
|
|
2603
|
-
view?.contentDOM.focus();
|
|
2604
|
-
break;
|
|
2605
|
-
}
|
|
2606
2565
|
case "Escape": {
|
|
2607
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) &&
|
|
2566
|
+
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && rootRef.current?.focus();
|
|
2608
2567
|
break;
|
|
2609
2568
|
}
|
|
2610
2569
|
}
|
|
@@ -2614,16 +2573,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2614
2573
|
]);
|
|
2615
2574
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2616
2575
|
key: model.id,
|
|
2617
|
-
|
|
2576
|
+
role: "none",
|
|
2618
2577
|
tabIndex: 0,
|
|
2619
|
-
|
|
2578
|
+
onKeyUp: handleKeyUp,
|
|
2579
|
+
...slots.root,
|
|
2620
2580
|
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2621
|
-
|
|
2581
|
+
ref: rootRef
|
|
2622
2582
|
});
|
|
2623
2583
|
});
|
|
2624
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2584
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = textTheme, slots, ...props }, forwardedRef) => {
|
|
2625
2585
|
const { themeMode } = useThemeContext();
|
|
2626
|
-
const
|
|
2586
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2627
2587
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2628
2588
|
ref: forwardedRef,
|
|
2629
2589
|
readonly,
|
|
@@ -2631,17 +2591,18 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots:
|
|
|
2631
2591
|
basicBundle({
|
|
2632
2592
|
readonly,
|
|
2633
2593
|
themeMode,
|
|
2634
|
-
placeholder:
|
|
2594
|
+
placeholder: placeholder3
|
|
2635
2595
|
}),
|
|
2636
2596
|
...extensions
|
|
2637
2597
|
],
|
|
2638
|
-
|
|
2598
|
+
theme,
|
|
2599
|
+
slots: updatedSlots,
|
|
2639
2600
|
...props
|
|
2640
2601
|
});
|
|
2641
2602
|
});
|
|
2642
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [],
|
|
2603
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, extensions = [], theme = markdownTheme, slots, ...props }, forwardedRef) => {
|
|
2643
2604
|
const { themeMode } = useThemeContext();
|
|
2644
|
-
const
|
|
2605
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2645
2606
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2646
2607
|
ref: forwardedRef,
|
|
2647
2608
|
readonly,
|
|
@@ -2649,34 +2610,29 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
|
|
|
2649
2610
|
markdownBundle({
|
|
2650
2611
|
readonly,
|
|
2651
2612
|
themeMode,
|
|
2652
|
-
placeholder:
|
|
2613
|
+
placeholder: placeholder3
|
|
2653
2614
|
}),
|
|
2654
2615
|
...extensions
|
|
2655
2616
|
],
|
|
2656
|
-
|
|
2617
|
+
theme,
|
|
2618
|
+
slots: updatedSlots,
|
|
2657
2619
|
...props
|
|
2658
2620
|
});
|
|
2659
2621
|
});
|
|
2660
2622
|
var defaultSlots = {
|
|
2661
2623
|
root: {
|
|
2662
|
-
className: mx3("p-2", inputSurface)
|
|
2624
|
+
className: mx3("w-full p-2 overflow-y-auto", inputSurface)
|
|
2663
2625
|
}
|
|
2664
2626
|
};
|
|
2665
2627
|
var defaultTextSlots = {
|
|
2666
|
-
...defaultSlots
|
|
2667
|
-
editor: {
|
|
2668
|
-
theme: textTheme
|
|
2669
|
-
}
|
|
2628
|
+
...defaultSlots
|
|
2670
2629
|
};
|
|
2671
2630
|
var defaultMarkdownSlots = {
|
|
2672
|
-
...defaultSlots
|
|
2673
|
-
editor: {
|
|
2674
|
-
theme: markdownTheme
|
|
2675
|
-
}
|
|
2631
|
+
...defaultSlots
|
|
2676
2632
|
};
|
|
2677
2633
|
|
|
2678
2634
|
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2679
|
-
import
|
|
2635
|
+
import get4 from "lodash.get";
|
|
2680
2636
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
2681
2637
|
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2682
2638
|
|
|
@@ -2684,7 +2640,7 @@ import { isNotNullOrUndefined } from "@dxos/util";
|
|
|
2684
2640
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2685
2641
|
import { Context as Context2 } from "@dxos/context";
|
|
2686
2642
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2687
|
-
import { log as
|
|
2643
|
+
import { log as log2 } from "@dxos/log";
|
|
2688
2644
|
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2689
2645
|
var DEBOUNCE_INTERVAL = 100;
|
|
2690
2646
|
var SpaceAwarenessProvider = class {
|
|
@@ -2723,7 +2679,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2723
2679
|
void this._space.postMessage(this._channel, {
|
|
2724
2680
|
kind: "query"
|
|
2725
2681
|
}).catch((err) => {
|
|
2726
|
-
|
|
2682
|
+
log2.debug("failed to query awareness", {
|
|
2727
2683
|
err
|
|
2728
2684
|
}, {
|
|
2729
2685
|
F: __dxlog_file4,
|
|
@@ -2786,7 +2742,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2786
2742
|
};
|
|
2787
2743
|
|
|
2788
2744
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2789
|
-
import { StateField as
|
|
2745
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
|
2790
2746
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2791
2747
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2792
2748
|
|
|
@@ -2795,15 +2751,13 @@ import * as decoding from "lib0/decoding";
|
|
|
2795
2751
|
import * as encoding from "lib0/encoding";
|
|
2796
2752
|
import { Observable } from "lib0/observable";
|
|
2797
2753
|
import * as YP from "y-protocols/awareness";
|
|
2798
|
-
import * as Y2 from "yjs";
|
|
2799
2754
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2800
|
-
import { log as
|
|
2801
|
-
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2755
|
+
import { log as log3 } from "@dxos/log";
|
|
2802
2756
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2803
2757
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2804
2758
|
invariant4(text?.doc && text?.content, void 0, {
|
|
2805
2759
|
F: __dxlog_file5,
|
|
2806
|
-
L:
|
|
2760
|
+
L: 21,
|
|
2807
2761
|
S: void 0,
|
|
2808
2762
|
A: [
|
|
2809
2763
|
"text?.doc && text?.content",
|
|
@@ -2819,34 +2773,6 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
2819
2773
|
id: text.doc.guid,
|
|
2820
2774
|
content: text.content,
|
|
2821
2775
|
text: () => text.content.toString(),
|
|
2822
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2823
|
-
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2824
|
-
getCursorFromRange: (range) => {
|
|
2825
|
-
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2826
|
-
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2827
|
-
return [
|
|
2828
|
-
arrayToString2(from),
|
|
2829
|
-
arrayToString2(to)
|
|
2830
|
-
].join(":");
|
|
2831
|
-
},
|
|
2832
|
-
getRangeFromCursor: (cursor) => {
|
|
2833
|
-
invariant4(text.doc, void 0, {
|
|
2834
|
-
F: __dxlog_file5,
|
|
2835
|
-
L: 40,
|
|
2836
|
-
S: void 0,
|
|
2837
|
-
A: [
|
|
2838
|
-
"text.doc",
|
|
2839
|
-
""
|
|
2840
|
-
]
|
|
2841
|
-
});
|
|
2842
|
-
const parts = cursor.split(":");
|
|
2843
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2844
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2845
|
-
return from && to ? {
|
|
2846
|
-
from: from.index,
|
|
2847
|
-
to: to.index
|
|
2848
|
-
} : void 0;
|
|
2849
|
-
},
|
|
2850
2776
|
extension: [
|
|
2851
2777
|
modelState.init(() => model),
|
|
2852
2778
|
yjs(text.content, provider?.awareness)
|
|
@@ -2889,14 +2815,14 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2889
2815
|
return this._awareness;
|
|
2890
2816
|
}
|
|
2891
2817
|
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2892
|
-
|
|
2818
|
+
log3("awareness update", {
|
|
2893
2819
|
added,
|
|
2894
2820
|
updated,
|
|
2895
2821
|
removed,
|
|
2896
2822
|
origin
|
|
2897
2823
|
}, {
|
|
2898
2824
|
F: __dxlog_file5,
|
|
2899
|
-
L:
|
|
2825
|
+
L: 100,
|
|
2900
2826
|
S: this,
|
|
2901
2827
|
C: (f, a) => f(...a)
|
|
2902
2828
|
});
|
|
@@ -2907,9 +2833,9 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2907
2833
|
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2908
2834
|
}
|
|
2909
2835
|
_handleSpaceMessage({ payload }) {
|
|
2910
|
-
|
|
2836
|
+
log3("space message", payload, {
|
|
2911
2837
|
F: __dxlog_file5,
|
|
2912
|
-
L:
|
|
2838
|
+
L: 109,
|
|
2913
2839
|
S: this,
|
|
2914
2840
|
C: (f, a) => f(...a)
|
|
2915
2841
|
});
|
|
@@ -2953,13 +2879,13 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2953
2879
|
};
|
|
2954
2880
|
|
|
2955
2881
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2956
|
-
var modelState =
|
|
2882
|
+
var modelState = StateField5.define({
|
|
2957
2883
|
create: () => void 0,
|
|
2958
2884
|
update: (model) => model
|
|
2959
2885
|
});
|
|
2960
2886
|
var useTextModel = (props) => {
|
|
2961
2887
|
const { identity, space, text } = props;
|
|
2962
|
-
const [model, setModel] = useState2(
|
|
2888
|
+
const [model, setModel] = useState2();
|
|
2963
2889
|
useEffect2(() => setModel(createModel(props)), [
|
|
2964
2890
|
identity,
|
|
2965
2891
|
space,
|
|
@@ -2997,7 +2923,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2997
2923
|
const model = {
|
|
2998
2924
|
id: obj.id,
|
|
2999
2925
|
content: doc,
|
|
3000
|
-
text: () =>
|
|
2926
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3001
2927
|
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3002
2928
|
extension: [
|
|
3003
2929
|
modelState.init(() => model),
|
|
@@ -3018,6 +2944,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3018
2944
|
export {
|
|
3019
2945
|
AwarenessProvider,
|
|
3020
2946
|
BaseTextEditor,
|
|
2947
|
+
Cursor,
|
|
3021
2948
|
Doc,
|
|
3022
2949
|
EditorModes,
|
|
3023
2950
|
MarkdownEditor,
|
|
@@ -3033,6 +2960,7 @@ export {
|
|
|
3033
2960
|
awareness,
|
|
3034
2961
|
basicBundle,
|
|
3035
2962
|
blast,
|
|
2963
|
+
callbackWrapper,
|
|
3036
2964
|
code2 as code,
|
|
3037
2965
|
codeTheme,
|
|
3038
2966
|
comments,
|
|
@@ -3043,6 +2971,7 @@ export {
|
|
|
3043
2971
|
defaultSlots,
|
|
3044
2972
|
defaultTextSlots,
|
|
3045
2973
|
defaultTheme,
|
|
2974
|
+
getToken,
|
|
3046
2975
|
hr,
|
|
3047
2976
|
image,
|
|
3048
2977
|
link,
|
|
@@ -3053,8 +2982,8 @@ export {
|
|
|
3053
2982
|
markdownTagsExtensions,
|
|
3054
2983
|
markdownTheme,
|
|
3055
2984
|
mention,
|
|
3056
|
-
mermaid,
|
|
3057
2985
|
modelState,
|
|
2986
|
+
outliner,
|
|
3058
2987
|
setCommentRange,
|
|
3059
2988
|
setFocus,
|
|
3060
2989
|
setSelection,
|