@dxos/react-ui-editor 0.3.11-main.d7d4c52 → 0.3.11-main.d8f9aa0
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 +1009 -988
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +13 -14
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +14 -6
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/index.d.ts +0 -1
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +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 +1 -1
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +4 -5
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +30 -17
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor.d.ts +3 -3
- package/dist/types/src/extensions/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +1 -7
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +2 -5
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +7 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +25 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts +17 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts +2 -27
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +2 -0
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +33 -36
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +66 -69
- package/src/components/TextEditor/TextEditor.tsx +95 -70
- package/src/components/TextEditor/comments.stories.tsx +113 -71
- package/src/extensions/autocomplete.ts +6 -3
- package/src/extensions/automerge/automerge.ts +39 -45
- package/src/extensions/automerge/defs.ts +10 -31
- package/src/extensions/automerge/index.ts +0 -1
- package/src/extensions/automerge/semaphore.ts +23 -20
- package/src/extensions/automerge/update-automerge.ts +2 -2
- package/src/extensions/awareness.ts +15 -14
- package/src/extensions/basic.ts +22 -17
- package/src/extensions/comments.ts +239 -136
- package/src/extensions/cursor.ts +7 -3
- package/src/extensions/index.ts +1 -7
- package/src/extensions/markdown/bundle.ts +18 -24
- package/src/extensions/{code.ts → markdown/code.ts} +16 -18
- package/src/extensions/markdown/heading.ts +60 -0
- package/src/extensions/markdown/hr.ts +72 -0
- package/src/extensions/markdown/index.ts +7 -0
- package/src/extensions/markdown/tasklist.ts +111 -0
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/hooks/awareness-provider.ts +24 -20
- package/src/hooks/defs.ts +42 -0
- package/src/hooks/index.ts +3 -2
- package/src/hooks/useTextEditor.ts +29 -0
- package/src/hooks/useTextModel.ts +47 -56
- package/src/themes/default.ts +0 -8
- package/src/util.ts +26 -3
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -3
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts +0 -27
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
- package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
- package/dist/types/src/testing/proto/index.d.ts +0 -2
- package/dist/types/src/testing/proto/index.d.ts.map +0 -1
- package/dist/types/src/testing/replicator.d.ts +0 -45
- package/dist/types/src/testing/replicator.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/hr.ts +0 -73
- package/src/extensions/tasklist.ts +0 -119
- package/src/extensions/yjs/cursor.ts +0 -22
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.test.ts +0 -35
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -52
- package/src/hooks/yjs.ts +0 -156
- package/src/testing/index.ts +0 -6
- package/src/testing/proto/gen/schema.ts +0 -49
- package/src/testing/proto/index.ts +0 -5
- package/src/testing/proto/schema.proto +0 -15
- package/src/testing/replicator.ts +0 -184
- package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
- package/src/extensions/{image.ts → markdown/image.ts} +0 -0
- package/src/extensions/{link.ts → markdown/link.ts} +3 -3
- /package/src/extensions/{table.ts → markdown/table.ts} +0 -0
|
@@ -7,14 +7,14 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
7
7
|
|
|
8
8
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
9
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
-
import { EditorView as
|
|
10
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
|
11
11
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle,
|
|
15
|
-
import {
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
15
|
+
import { log as log2 } from "@dxos/log";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
17
|
+
import { attentionSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
18
|
|
|
19
19
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
@@ -29,9 +29,11 @@ var autocomplete = ({ onSearch }) => {
|
|
|
29
29
|
// https://codemirror.net/examples/autocompletion
|
|
30
30
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
31
31
|
autocompletion({
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
32
|
+
activateOnTyping: true,
|
|
33
|
+
// closeOnBlur: false,
|
|
34
|
+
// defaultKeymap: false,
|
|
35
|
+
// TODO(burdon): Styles/fragments.
|
|
36
|
+
tooltipClass: () => "shadow rounded"
|
|
35
37
|
}),
|
|
36
38
|
// TODO(burdon): Option to create new page?
|
|
37
39
|
// TODO(burdon): Optional decoration via addToOptions
|
|
@@ -51,9 +53,10 @@ var autocomplete = ({ onSearch }) => {
|
|
|
51
53
|
};
|
|
52
54
|
|
|
53
55
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
54
|
-
import {
|
|
55
|
-
import { ViewPlugin } from "@codemirror/view";
|
|
56
|
+
import { StateField } from "@codemirror/state";
|
|
57
|
+
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
56
58
|
import { next as A } from "@dxos/automerge/automerge";
|
|
59
|
+
import { invariant } from "@dxos/invariant";
|
|
57
60
|
|
|
58
61
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
59
62
|
import get from "lodash.get";
|
|
@@ -94,12 +97,12 @@ var cursorConverter = (handle, path) => ({
|
|
|
94
97
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
95
98
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
96
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;
|
|
97
103
|
var updateHeads = (newHeads) => effectType.of({
|
|
98
104
|
newHeads
|
|
99
105
|
});
|
|
100
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
101
|
-
var getPath = (state, field) => state.field(field).path;
|
|
102
|
-
var reconcileAnnotationType = Annotation.define();
|
|
103
106
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
104
107
|
|
|
105
108
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
@@ -237,40 +240,42 @@ var charPath = (textPath, candidatePath) => {
|
|
|
237
240
|
|
|
238
241
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
239
242
|
var PatchSemaphore = class {
|
|
240
|
-
|
|
241
|
-
|
|
243
|
+
// prettier-ignore
|
|
244
|
+
constructor(_handle, _state) {
|
|
245
|
+
this._handle = _handle;
|
|
246
|
+
this._state = _state;
|
|
242
247
|
this._inReconcile = false;
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
changes: inverted,
|
|
259
|
-
annotations: reconcileAnnotationType.of(true)
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
263
|
-
if (newHeads === null || newHeads === void 0) {
|
|
264
|
-
newHeads = automerge2.getHeads(handle.docSync());
|
|
265
|
-
}
|
|
266
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
|
|
267
|
-
updateCodeMirror(view, selection, path, diff);
|
|
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);
|
|
268
263
|
view.dispatch({
|
|
269
|
-
|
|
270
|
-
annotations: reconcileAnnotationType.of(
|
|
264
|
+
changes: inverted,
|
|
265
|
+
annotations: reconcileAnnotationType.of(true)
|
|
271
266
|
});
|
|
272
|
-
|
|
273
|
-
|
|
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;
|
|
274
279
|
}
|
|
275
280
|
};
|
|
276
281
|
|
|
@@ -280,16 +285,17 @@ var defaultCursorConverter = {
|
|
|
280
285
|
toCursor: (position) => position.toString(),
|
|
281
286
|
fromCursor: (cursor) => parseInt(cursor)
|
|
282
287
|
};
|
|
283
|
-
var Cursor = class {
|
|
288
|
+
var Cursor = class _Cursor {
|
|
284
289
|
static {
|
|
285
290
|
this.converter = Facet.define({
|
|
286
291
|
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
287
292
|
});
|
|
288
293
|
}
|
|
289
294
|
static {
|
|
290
|
-
this.getCursorFromRange = (
|
|
291
|
-
const
|
|
292
|
-
const
|
|
295
|
+
this.getCursorFromRange = (state, range) => {
|
|
296
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
297
|
+
const from = cursorConverter2.toCursor(range.from);
|
|
298
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
|
293
299
|
return [
|
|
294
300
|
from,
|
|
295
301
|
to
|
|
@@ -297,10 +303,11 @@ var Cursor = class {
|
|
|
297
303
|
};
|
|
298
304
|
}
|
|
299
305
|
static {
|
|
300
|
-
this.getRangeFromCursor = (
|
|
306
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
307
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
301
308
|
const parts = cursor.split(":");
|
|
302
|
-
const from =
|
|
303
|
-
const to =
|
|
309
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
|
310
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
|
304
311
|
return from !== void 0 && to !== void 0 ? {
|
|
305
312
|
from,
|
|
306
313
|
to
|
|
@@ -310,21 +317,19 @@ var Cursor = class {
|
|
|
310
317
|
};
|
|
311
318
|
|
|
312
319
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
313
|
-
var
|
|
314
|
-
combine: (values) => values.at(-1)
|
|
315
|
-
});
|
|
320
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts";
|
|
316
321
|
var automerge3 = ({ handle, path }) => {
|
|
317
|
-
const
|
|
322
|
+
const state = StateField.define({
|
|
318
323
|
create: () => ({
|
|
324
|
+
path: path.slice(),
|
|
319
325
|
lastHeads: A.getHeads(handle.docSync()),
|
|
320
|
-
unreconciledTransactions: []
|
|
321
|
-
path: path.slice()
|
|
326
|
+
unreconciledTransactions: []
|
|
322
327
|
}),
|
|
323
328
|
update: (value, tr) => {
|
|
324
329
|
const result = {
|
|
330
|
+
path: path.slice(),
|
|
325
331
|
lastHeads: value.lastHeads,
|
|
326
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
327
|
-
path: path.slice()
|
|
332
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
328
333
|
};
|
|
329
334
|
let clearUnreconciled = false;
|
|
330
335
|
for (const effect of tr.effects) {
|
|
@@ -343,39 +348,44 @@ var automerge3 = ({ handle, path }) => {
|
|
|
343
348
|
return result;
|
|
344
349
|
}
|
|
345
350
|
});
|
|
346
|
-
const semaphore = new PatchSemaphore(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
+
]
|
|
359
366
|
});
|
|
367
|
+
handle.addListener("change", this._handleChange.bind(this));
|
|
360
368
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
+
];
|
|
374
384
|
};
|
|
375
385
|
|
|
376
386
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
377
|
-
import { Annotation as Annotation2, Facet as
|
|
378
|
-
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
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";
|
|
379
389
|
import { Event } from "@dxos/async";
|
|
380
390
|
import { Context } from "@dxos/context";
|
|
381
391
|
var dummyProvider = {
|
|
@@ -384,11 +394,11 @@ var dummyProvider = {
|
|
|
384
394
|
},
|
|
385
395
|
close: () => {
|
|
386
396
|
},
|
|
397
|
+
getRemoteStates: () => [],
|
|
387
398
|
update: () => {
|
|
388
|
-
}
|
|
389
|
-
getRemoteStates: () => []
|
|
399
|
+
}
|
|
390
400
|
};
|
|
391
|
-
var AwarenessProvider =
|
|
401
|
+
var AwarenessProvider = Facet2.define({
|
|
392
402
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
393
403
|
});
|
|
394
404
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
@@ -549,7 +559,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
549
559
|
return true;
|
|
550
560
|
}
|
|
551
561
|
};
|
|
552
|
-
var styles =
|
|
562
|
+
var styles = EditorView2.baseTheme({
|
|
553
563
|
".cm-collab-selection": {},
|
|
554
564
|
".cm-collab-selectionLine": {
|
|
555
565
|
padding: 0,
|
|
@@ -562,40 +572,42 @@ var styles = EditorView.baseTheme({
|
|
|
562
572
|
marginLeft: "-1px",
|
|
563
573
|
marginRight: "-1px",
|
|
564
574
|
boxSizing: "border-box",
|
|
565
|
-
display: "inline"
|
|
575
|
+
display: "inline",
|
|
576
|
+
cursor: "pointer"
|
|
566
577
|
},
|
|
567
578
|
".cm-collab-selectionCaretDot": {
|
|
568
579
|
borderRadius: "50%",
|
|
569
580
|
position: "absolute",
|
|
570
|
-
width: ".
|
|
571
|
-
height: ".
|
|
572
|
-
top: "-.
|
|
573
|
-
left: "-.
|
|
581
|
+
width: ".5em",
|
|
582
|
+
height: ".5em",
|
|
583
|
+
top: "-.25em",
|
|
584
|
+
left: "-.25em",
|
|
574
585
|
backgroundColor: "inherit",
|
|
575
586
|
transition: "transform .3s ease-in-out",
|
|
576
587
|
boxSizing: "border-box"
|
|
577
588
|
},
|
|
578
589
|
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
579
|
-
|
|
580
|
-
|
|
590
|
+
transform: "scale(0)",
|
|
591
|
+
transformOrigin: "center"
|
|
581
592
|
},
|
|
582
593
|
".cm-collab-selectionInfo": {
|
|
583
594
|
position: "absolute",
|
|
584
|
-
|
|
585
|
-
|
|
595
|
+
transform: "translate(-50%, 0)",
|
|
596
|
+
top: "-20px",
|
|
597
|
+
left: 0,
|
|
586
598
|
fontSize: ".75em",
|
|
587
|
-
fontFamily: "serif",
|
|
599
|
+
fontFamily: "sans-serif",
|
|
588
600
|
fontStyle: "normal",
|
|
589
601
|
fontWeight: "normal",
|
|
590
602
|
lineHeight: "normal",
|
|
591
603
|
userSelect: "none",
|
|
592
604
|
color: "white",
|
|
593
|
-
|
|
594
|
-
paddingRight: "2px",
|
|
605
|
+
padding: "2px",
|
|
595
606
|
zIndex: 101,
|
|
596
607
|
transition: "opacity .3s ease-in-out",
|
|
597
608
|
backgroundColor: "inherit",
|
|
598
|
-
|
|
609
|
+
borderRadius: "2px",
|
|
610
|
+
// These should be separate.
|
|
599
611
|
opacity: 0,
|
|
600
612
|
transitionDelay: "0s",
|
|
601
613
|
whiteSpace: "nowrap"
|
|
@@ -608,26 +620,28 @@ var styles = EditorView.baseTheme({
|
|
|
608
620
|
|
|
609
621
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
610
622
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
623
|
+
import { history } from "@codemirror/commands";
|
|
611
624
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
612
625
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
613
|
-
import { drawSelection, EditorView as
|
|
614
|
-
var basicBundle = ({
|
|
615
|
-
|
|
616
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
626
|
+
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
627
|
+
var basicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true }) => [
|
|
628
|
+
lineWrapping ? EditorView3.lineWrapping : [],
|
|
617
629
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
618
630
|
bracketMatching(),
|
|
619
631
|
closeBrackets(),
|
|
620
632
|
drawSelection(),
|
|
621
|
-
|
|
622
|
-
|
|
633
|
+
highlightActiveLine(),
|
|
634
|
+
history(),
|
|
635
|
+
_placeholder ? placeholder(_placeholder) : [],
|
|
636
|
+
// https://github.com/codemirror/theme-one-dark
|
|
623
637
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
624
|
-
]
|
|
638
|
+
];
|
|
625
639
|
|
|
626
640
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
627
|
-
import { EditorView as
|
|
641
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
628
642
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
629
|
-
import { invariant } from "@dxos/invariant";
|
|
630
|
-
var
|
|
643
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
644
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
631
645
|
var defaultOptions = {
|
|
632
646
|
effect: 2,
|
|
633
647
|
maxParticles: 200,
|
|
@@ -672,7 +686,7 @@ var blast = (options = defaultOptions) => {
|
|
|
672
686
|
};
|
|
673
687
|
return [
|
|
674
688
|
// Cursor moved.
|
|
675
|
-
|
|
689
|
+
EditorView4.updateListener.of((update2) => {
|
|
676
690
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
677
691
|
if (blaster) {
|
|
678
692
|
blaster.destroy();
|
|
@@ -753,8 +767,8 @@ var Blaster = class {
|
|
|
753
767
|
return this._node;
|
|
754
768
|
}
|
|
755
769
|
initialize() {
|
|
756
|
-
|
|
757
|
-
F:
|
|
770
|
+
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
771
|
+
F: __dxlog_file2,
|
|
758
772
|
L: 138,
|
|
759
773
|
S: this,
|
|
760
774
|
A: [
|
|
@@ -790,8 +804,8 @@ var Blaster = class {
|
|
|
790
804
|
}
|
|
791
805
|
}
|
|
792
806
|
start() {
|
|
793
|
-
|
|
794
|
-
F:
|
|
807
|
+
invariant2(this._canvas && this._ctx, void 0, {
|
|
808
|
+
F: __dxlog_file2,
|
|
795
809
|
L: 177,
|
|
796
810
|
S: this,
|
|
797
811
|
A: [
|
|
@@ -933,9 +947,14 @@ var random = (min, max) => {
|
|
|
933
947
|
return min + ~~(Math.random() * (max - min + 1));
|
|
934
948
|
};
|
|
935
949
|
|
|
936
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
937
|
-
import {
|
|
938
|
-
import {
|
|
950
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
951
|
+
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
952
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
953
|
+
import sortBy from "lodash.sortby";
|
|
954
|
+
import { useEffect } from "react";
|
|
955
|
+
import { debounce } from "@dxos/async";
|
|
956
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
957
|
+
import { nonNullable } from "@dxos/util";
|
|
939
958
|
|
|
940
959
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
941
960
|
import * as random2 from "lib0/random";
|
|
@@ -1023,168 +1042,112 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
|
1023
1042
|
var tokens = tailwindConfig({}).theme;
|
|
1024
1043
|
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1025
1044
|
|
|
1026
|
-
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1027
|
-
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1028
|
-
var styles2 = EditorView4.baseTheme({
|
|
1029
|
-
"& .cm-codeblock": {
|
|
1030
|
-
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1031
|
-
},
|
|
1032
|
-
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1033
|
-
background: getToken("extend.colors.neutral.50")
|
|
1034
|
-
},
|
|
1035
|
-
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1036
|
-
background: getToken("extend.colors.neutral.850")
|
|
1037
|
-
},
|
|
1038
|
-
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1039
|
-
display: "block",
|
|
1040
|
-
paddingInline: "4px !important"
|
|
1041
|
-
},
|
|
1042
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1043
|
-
paddingTop: "4px !important",
|
|
1044
|
-
borderTopLeftRadius: "4px",
|
|
1045
|
-
borderTopRightRadius: "4px"
|
|
1046
|
-
},
|
|
1047
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1048
|
-
paddingBottom: "4px !important",
|
|
1049
|
-
borderBottomLeftRadius: "4px",
|
|
1050
|
-
borderBottomRightRadius: "4px"
|
|
1051
|
-
}
|
|
1052
|
-
});
|
|
1053
|
-
var getLineRange = (lines, from, to) => {
|
|
1054
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1055
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1056
|
-
return [
|
|
1057
|
-
start,
|
|
1058
|
-
end
|
|
1059
|
-
];
|
|
1060
|
-
};
|
|
1061
|
-
var code2 = () => {
|
|
1062
|
-
const getDecorations = (view) => {
|
|
1063
|
-
const decorations = [];
|
|
1064
|
-
if (!view.hasFocus || view.state.readOnly) {
|
|
1065
|
-
const text = view.state.doc.sliceString(0);
|
|
1066
|
-
const matches = text.matchAll(CODE_REGEX);
|
|
1067
|
-
const blocks = view.viewportLineBlocks;
|
|
1068
|
-
for (const match of matches) {
|
|
1069
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1070
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1071
|
-
const block = blocks[i];
|
|
1072
|
-
decorations.push(Decoration2.line({
|
|
1073
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1074
|
-
}).range(block.from));
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
return Decoration2.set(decorations);
|
|
1079
|
-
};
|
|
1080
|
-
return [
|
|
1081
|
-
ViewPlugin3.fromClass(class {
|
|
1082
|
-
constructor(view) {
|
|
1083
|
-
this.hasFocus = false;
|
|
1084
|
-
this.decorations = getDecorations(view);
|
|
1085
|
-
}
|
|
1086
|
-
update(update2) {
|
|
1087
|
-
if (
|
|
1088
|
-
// TODO(burdon): Generalize for other extensions.
|
|
1089
|
-
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1090
|
-
) {
|
|
1091
|
-
this.hasFocus = update2.view.hasFocus;
|
|
1092
|
-
this.decorations = getDecorations(update2.view);
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
}, {
|
|
1096
|
-
decorations: (value) => value.decorations
|
|
1097
|
-
}),
|
|
1098
|
-
styles2
|
|
1099
|
-
];
|
|
1100
|
-
};
|
|
1101
|
-
|
|
1102
|
-
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1103
|
-
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1104
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
|
|
1105
|
-
import sortBy from "lodash.sortby";
|
|
1106
|
-
import { debounce } from "@dxos/async";
|
|
1107
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1108
|
-
import { log as log2 } from "@dxos/log";
|
|
1109
|
-
import { nonNullable } from "@dxos/util";
|
|
1110
|
-
|
|
1111
1045
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1112
1046
|
import { log } from "@dxos/log";
|
|
1113
|
-
var
|
|
1047
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1114
1048
|
var callbackWrapper = (fn) => (...args) => {
|
|
1115
1049
|
try {
|
|
1116
1050
|
return fn(...args);
|
|
1117
|
-
} catch (
|
|
1118
|
-
log.catch(
|
|
1119
|
-
F:
|
|
1120
|
-
L:
|
|
1051
|
+
} catch (err) {
|
|
1052
|
+
log.catch(err, void 0, {
|
|
1053
|
+
F: __dxlog_file3,
|
|
1054
|
+
L: 18,
|
|
1121
1055
|
S: void 0,
|
|
1122
1056
|
C: (f, a) => f(...a)
|
|
1123
1057
|
});
|
|
1124
1058
|
}
|
|
1125
1059
|
};
|
|
1060
|
+
var logChanges = (trs) => {
|
|
1061
|
+
const changes = trs.flatMap((tr) => {
|
|
1062
|
+
if (tr.changes.empty) {
|
|
1063
|
+
return void 0;
|
|
1064
|
+
}
|
|
1065
|
+
const changes2 = [];
|
|
1066
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1067
|
+
fromA,
|
|
1068
|
+
toA,
|
|
1069
|
+
fromB,
|
|
1070
|
+
toB,
|
|
1071
|
+
inserted: inserted.toString()
|
|
1072
|
+
})));
|
|
1073
|
+
return changes2;
|
|
1074
|
+
}).filter(Boolean);
|
|
1075
|
+
if (changes.length) {
|
|
1076
|
+
console.log("changes", changes);
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1126
1079
|
|
|
1127
1080
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1128
|
-
var
|
|
1129
|
-
var
|
|
1081
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1082
|
+
var styles2 = EditorView5.baseTheme({
|
|
1130
1083
|
"& .cm-comment": {
|
|
1131
1084
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1132
1085
|
},
|
|
1133
|
-
"& .cm-comment-
|
|
1086
|
+
"& .cm-comment-current": {
|
|
1134
1087
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1135
1088
|
}
|
|
1136
1089
|
});
|
|
1137
1090
|
var marks = {
|
|
1138
|
-
highlight:
|
|
1091
|
+
highlight: Decoration2.mark({
|
|
1139
1092
|
class: "cm-comment"
|
|
1140
1093
|
}),
|
|
1141
|
-
highlightActive:
|
|
1142
|
-
class: "cm-comment-
|
|
1094
|
+
highlightActive: Decoration2.mark({
|
|
1095
|
+
class: "cm-comment-current"
|
|
1143
1096
|
})
|
|
1144
1097
|
};
|
|
1145
|
-
var setFocus = (view,
|
|
1146
|
-
const
|
|
1147
|
-
if (!
|
|
1098
|
+
var setFocus = (view, id, center = true) => {
|
|
1099
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1100
|
+
if (!comment?.comment.cursor) {
|
|
1148
1101
|
return;
|
|
1149
1102
|
}
|
|
1150
|
-
view.
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1103
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1104
|
+
if (range) {
|
|
1105
|
+
view.dispatch({
|
|
1106
|
+
selection: {
|
|
1107
|
+
anchor: range.from
|
|
1108
|
+
},
|
|
1109
|
+
effects: [
|
|
1110
|
+
//
|
|
1111
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1112
|
+
y: "center"
|
|
1113
|
+
} : void 0),
|
|
1114
|
+
setSelection.of({
|
|
1115
|
+
current: id
|
|
1116
|
+
})
|
|
1117
|
+
]
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1159
1120
|
};
|
|
1160
|
-
var
|
|
1121
|
+
var setComments = StateEffect2.define();
|
|
1161
1122
|
var setSelection = StateEffect2.define();
|
|
1162
1123
|
var setCommentState = StateEffect2.define();
|
|
1163
|
-
var
|
|
1124
|
+
var commentsState = StateField2.define({
|
|
1164
1125
|
create: () => ({
|
|
1165
|
-
|
|
1126
|
+
comments: [],
|
|
1127
|
+
selection: {}
|
|
1166
1128
|
}),
|
|
1167
1129
|
update: (value, tr) => {
|
|
1168
|
-
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1169
1130
|
for (const effect of tr.effects) {
|
|
1170
1131
|
if (effect.is(setSelection)) {
|
|
1171
1132
|
return {
|
|
1172
1133
|
...value,
|
|
1173
|
-
|
|
1134
|
+
selection: effect.value
|
|
1174
1135
|
};
|
|
1175
1136
|
}
|
|
1176
|
-
if (effect.is(
|
|
1177
|
-
const
|
|
1178
|
-
|
|
1179
|
-
|
|
1137
|
+
if (effect.is(setComments)) {
|
|
1138
|
+
const comments2 = effect.value.map((comment) => {
|
|
1139
|
+
if (!comment.cursor) {
|
|
1140
|
+
return void 0;
|
|
1141
|
+
}
|
|
1142
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1180
1143
|
return range && {
|
|
1181
|
-
|
|
1182
|
-
|
|
1144
|
+
comment,
|
|
1145
|
+
range
|
|
1183
1146
|
};
|
|
1184
1147
|
}).filter(nonNullable);
|
|
1185
1148
|
return {
|
|
1186
1149
|
...value,
|
|
1187
|
-
|
|
1150
|
+
comments: comments2
|
|
1188
1151
|
};
|
|
1189
1152
|
}
|
|
1190
1153
|
if (effect.is(setCommentState)) {
|
|
@@ -1195,79 +1158,126 @@ var commentsStateField = StateField2.define({
|
|
|
1195
1158
|
}
|
|
1196
1159
|
});
|
|
1197
1160
|
var highlightDecorations = EditorView5.decorations.compute([
|
|
1198
|
-
|
|
1161
|
+
commentsState
|
|
1199
1162
|
], (state) => {
|
|
1200
|
-
const {
|
|
1201
|
-
const decorations = sortBy(
|
|
1202
|
-
|
|
1163
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1164
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1165
|
+
const range = comment.range;
|
|
1166
|
+
if (!range || range.from === range.to) {
|
|
1167
|
+
console.warn("Invalid range:", range);
|
|
1203
1168
|
return void 0;
|
|
1204
1169
|
}
|
|
1205
|
-
|
|
1206
|
-
from: selection.from,
|
|
1207
|
-
to: selection.to
|
|
1208
|
-
};
|
|
1209
|
-
if (selection.id === active) {
|
|
1170
|
+
if (comment.comment.id === current) {
|
|
1210
1171
|
return marks.highlightActive.range(range.from, range.to);
|
|
1211
1172
|
} else {
|
|
1212
1173
|
return marks.highlight.range(range.from, range.to);
|
|
1213
1174
|
}
|
|
1214
|
-
}).filter(nonNullable)
|
|
1215
|
-
return
|
|
1175
|
+
}).filter(nonNullable);
|
|
1176
|
+
return Decoration2.set(decorations);
|
|
1216
1177
|
});
|
|
1178
|
+
var trackPastedComments = (onUpdate) => {
|
|
1179
|
+
let tracked = null;
|
|
1180
|
+
const handleTrack = (event, view) => {
|
|
1181
|
+
const comments2 = view.state.field(commentsState);
|
|
1182
|
+
const { main } = view.state.selection;
|
|
1183
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1184
|
+
if (!selectedRanges.length) {
|
|
1185
|
+
tracked = null;
|
|
1186
|
+
} else {
|
|
1187
|
+
tracked = {
|
|
1188
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1189
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1190
|
+
id: comment.id,
|
|
1191
|
+
from: range.from - main.from,
|
|
1192
|
+
to: range.to - main.from
|
|
1193
|
+
}))
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
return [
|
|
1198
|
+
EditorView5.domEventHandlers({
|
|
1199
|
+
cut: handleTrack,
|
|
1200
|
+
copy: handleTrack
|
|
1201
|
+
}),
|
|
1202
|
+
// Handle paste.
|
|
1203
|
+
EditorView5.updateListener.of(({ view, state, transactions }) => {
|
|
1204
|
+
if (tracked) {
|
|
1205
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1206
|
+
if (paste) {
|
|
1207
|
+
let found = -1;
|
|
1208
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1209
|
+
if (text.eq(tracked.text)) {
|
|
1210
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1211
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1212
|
+
}
|
|
1213
|
+
found = fromB;
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
1216
|
+
if (found > -1) {
|
|
1217
|
+
for (const moved of tracked.comments) {
|
|
1218
|
+
const range = {
|
|
1219
|
+
from: found + moved.from,
|
|
1220
|
+
to: found + moved.to
|
|
1221
|
+
};
|
|
1222
|
+
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1223
|
+
onUpdate(moved.id, cursor);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
tracked = null;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
})
|
|
1230
|
+
];
|
|
1231
|
+
};
|
|
1217
1232
|
var comments = (options = {}) => {
|
|
1218
1233
|
const { key: shortcut = "meta-'" } = options;
|
|
1219
1234
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1220
1235
|
const createCommentThread = (view) => {
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
L: 177,
|
|
1236
|
+
invariant3(options.onCreate, void 0, {
|
|
1237
|
+
F: __dxlog_file4,
|
|
1238
|
+
L: 259,
|
|
1225
1239
|
S: void 0,
|
|
1226
1240
|
A: [
|
|
1227
1241
|
"options.onCreate",
|
|
1228
1242
|
""
|
|
1229
1243
|
]
|
|
1230
1244
|
});
|
|
1231
|
-
const {
|
|
1245
|
+
const { from, to } = view.state.selection.main;
|
|
1232
1246
|
if (from === to) {
|
|
1233
1247
|
return false;
|
|
1234
1248
|
}
|
|
1235
|
-
|
|
1249
|
+
if (to === view.state.doc.length) {
|
|
1250
|
+
view.dispatch({
|
|
1251
|
+
changes: {
|
|
1252
|
+
from: to,
|
|
1253
|
+
insert: "\n"
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1236
1258
|
from,
|
|
1237
1259
|
to
|
|
1238
1260
|
});
|
|
1239
1261
|
if (cursor) {
|
|
1240
|
-
const id =
|
|
1262
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1241
1263
|
if (id) {
|
|
1242
1264
|
view.dispatch({
|
|
1243
1265
|
effects: setSelection.of({
|
|
1244
|
-
|
|
1266
|
+
current: id
|
|
1245
1267
|
}),
|
|
1246
1268
|
selection: {
|
|
1247
1269
|
anchor: from
|
|
1248
1270
|
}
|
|
1249
1271
|
});
|
|
1250
|
-
if (options.footnote) {
|
|
1251
|
-
const tag = `[^${id}]`;
|
|
1252
|
-
view.dispatch({
|
|
1253
|
-
changes: {
|
|
1254
|
-
from: head,
|
|
1255
|
-
insert: tag
|
|
1256
|
-
},
|
|
1257
|
-
selection: {
|
|
1258
|
-
anchor: head + tag.length
|
|
1259
|
-
}
|
|
1260
|
-
});
|
|
1261
|
-
}
|
|
1262
1272
|
return true;
|
|
1263
1273
|
}
|
|
1264
1274
|
}
|
|
1265
1275
|
return false;
|
|
1266
1276
|
};
|
|
1267
1277
|
return [
|
|
1268
|
-
|
|
1278
|
+
commentsState,
|
|
1269
1279
|
highlightDecorations,
|
|
1270
|
-
|
|
1280
|
+
styles2,
|
|
1271
1281
|
//
|
|
1272
1282
|
// Keymap.
|
|
1273
1283
|
//
|
|
@@ -1290,7 +1300,7 @@ var comments = (options = {}) => {
|
|
|
1290
1300
|
above: true,
|
|
1291
1301
|
create: () => {
|
|
1292
1302
|
const el = document.createElement("div");
|
|
1293
|
-
options.onHover
|
|
1303
|
+
options.onHover(el, shortcut);
|
|
1294
1304
|
return {
|
|
1295
1305
|
dom: el,
|
|
1296
1306
|
offset: {
|
|
@@ -1303,364 +1313,115 @@ var comments = (options = {}) => {
|
|
|
1303
1313
|
}
|
|
1304
1314
|
return null;
|
|
1305
1315
|
}, {
|
|
1306
|
-
|
|
1316
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1317
|
+
// hideOnChange: true,
|
|
1307
1318
|
hoverTime: 1e3
|
|
1308
1319
|
}) : [],
|
|
1309
1320
|
//
|
|
1310
|
-
//
|
|
1311
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1321
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1312
1322
|
//
|
|
1313
1323
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1314
|
-
|
|
1315
|
-
{
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
if (
|
|
1321
|
-
|
|
1322
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1323
|
-
log2.info("deleted comment", {
|
|
1324
|
-
thread: range.id
|
|
1325
|
-
}, {
|
|
1326
|
-
F: __dxlog_file3,
|
|
1327
|
-
L: 274,
|
|
1328
|
-
S: void 0,
|
|
1329
|
-
C: (f, a) => f(...a)
|
|
1330
|
-
});
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
if (from <= range.to) {
|
|
1334
|
-
const newRange = Cursor.getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1335
|
-
Object.assign(range, newRange);
|
|
1336
|
-
mod = true;
|
|
1324
|
+
let mod = false;
|
|
1325
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1326
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1327
|
+
comments2.forEach(({ comment, range }) => {
|
|
1328
|
+
if (from2 === to2) {
|
|
1329
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1330
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1331
|
+
options.onDelete?.(comment.id);
|
|
1337
1332
|
}
|
|
1338
|
-
}
|
|
1333
|
+
}
|
|
1334
|
+
if (from <= range.to) {
|
|
1335
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1336
|
+
Object.assign(range, newRange);
|
|
1337
|
+
mod = true;
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
});
|
|
1341
|
+
if (mod) {
|
|
1342
|
+
view.dispatch({
|
|
1343
|
+
effects: setCommentState.of({
|
|
1344
|
+
comments: comments2,
|
|
1345
|
+
...value
|
|
1346
|
+
})
|
|
1339
1347
|
});
|
|
1340
|
-
if (mod) {
|
|
1341
|
-
view.dispatch({
|
|
1342
|
-
effects: setCommentState.of({
|
|
1343
|
-
active,
|
|
1344
|
-
ranges
|
|
1345
|
-
})
|
|
1346
|
-
});
|
|
1347
|
-
}
|
|
1348
1348
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1349
|
+
}),
|
|
1350
|
+
//
|
|
1351
|
+
// Track selection/proximity.
|
|
1352
|
+
//
|
|
1353
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1354
|
+
let min = Infinity;
|
|
1355
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1356
|
+
const { head } = state.selection.main;
|
|
1357
|
+
const selection = {};
|
|
1358
|
+
comments2.forEach(({ comment, range }) => {
|
|
1359
|
+
if (head >= range.from && head <= range.to) {
|
|
1360
|
+
selection.current = comment.id;
|
|
1361
|
+
selection.closest = void 0;
|
|
1362
|
+
}
|
|
1363
|
+
if (!selection.current) {
|
|
1364
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1362
1365
|
if (d < min) {
|
|
1363
|
-
|
|
1366
|
+
selection.closest = comment.id;
|
|
1364
1367
|
min = d;
|
|
1365
1368
|
}
|
|
1366
|
-
});
|
|
1367
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1368
|
-
view.dispatch({
|
|
1369
|
-
effects: setSelection.of(selected)
|
|
1370
|
-
});
|
|
1371
|
-
handleSelect({
|
|
1372
|
-
...selected,
|
|
1373
|
-
ranges: ranges.map((range) => ({
|
|
1374
|
-
...range,
|
|
1375
|
-
location: view.coordsAtPos(range.from)
|
|
1376
|
-
}))
|
|
1377
|
-
});
|
|
1378
1369
|
}
|
|
1370
|
+
});
|
|
1371
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1372
|
+
view.dispatch({
|
|
1373
|
+
effects: setSelection.of(selection)
|
|
1374
|
+
});
|
|
1375
|
+
handleSelect({
|
|
1376
|
+
selection,
|
|
1377
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1378
|
+
comment,
|
|
1379
|
+
range,
|
|
1380
|
+
location: view.coordsAtPos(range.from)
|
|
1381
|
+
}))
|
|
1382
|
+
});
|
|
1379
1383
|
}
|
|
1380
|
-
})
|
|
1384
|
+
}),
|
|
1385
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1381
1386
|
];
|
|
1382
1387
|
};
|
|
1388
|
+
var useComments = (view, comments2 = []) => {
|
|
1389
|
+
useEffect(() => {
|
|
1390
|
+
if (view) {
|
|
1391
|
+
view.dispatch({
|
|
1392
|
+
effects: setComments.of(comments2)
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
}, [
|
|
1396
|
+
view,
|
|
1397
|
+
comments2
|
|
1398
|
+
]);
|
|
1399
|
+
};
|
|
1383
1400
|
|
|
1384
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1385
|
-
import {
|
|
1386
|
-
var
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
this._pos = _pos;
|
|
1397
|
-
}
|
|
1398
|
-
eq(other) {
|
|
1399
|
-
return this._pos === other._pos;
|
|
1400
|
-
}
|
|
1401
|
-
toDOM(view) {
|
|
1402
|
-
const el = document.createElement("div");
|
|
1403
|
-
el.className = "cm-hr";
|
|
1404
|
-
return el;
|
|
1405
|
-
}
|
|
1406
|
-
};
|
|
1407
|
-
var placeholderMatcher = new MatchDecorator({
|
|
1408
|
-
regexp: /^---$/g,
|
|
1409
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1410
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1411
|
-
})
|
|
1412
|
-
});
|
|
1413
|
-
var hr = () => [
|
|
1414
|
-
styles4,
|
|
1415
|
-
ViewPlugin4.fromClass(class {
|
|
1416
|
-
constructor(view) {
|
|
1417
|
-
this.rules = placeholderMatcher.createDeco(view);
|
|
1418
|
-
}
|
|
1419
|
-
update(update2) {
|
|
1420
|
-
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1421
|
-
}
|
|
1422
|
-
}, {
|
|
1423
|
-
decorations: (instance) => instance.rules,
|
|
1424
|
-
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1425
|
-
provide: (plugin) => EditorView6.atomicRanges.of((view) => {
|
|
1426
|
-
return view.plugin(plugin)?.rules || Decoration4.none;
|
|
1427
|
-
})
|
|
1428
|
-
})
|
|
1429
|
-
];
|
|
1430
|
-
|
|
1431
|
-
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1432
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1433
|
-
import { StateField as StateField3 } from "@codemirror/state";
|
|
1434
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1435
|
-
var image = (options = {}) => {
|
|
1436
|
-
return StateField3.define({
|
|
1437
|
-
create: (state) => {
|
|
1438
|
-
return Decoration5.set(buildDecorations(0, state.doc.length, state));
|
|
1439
|
-
},
|
|
1440
|
-
update: (value, tr) => {
|
|
1441
|
-
if (!tr.docChanged && !tr.selection) {
|
|
1442
|
-
return value;
|
|
1443
|
-
}
|
|
1444
|
-
const cursor = tr.state.selection.main.head;
|
|
1445
|
-
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1446
|
-
let from = Math.min(cursor, oldCursor);
|
|
1447
|
-
let to = Math.max(cursor, oldCursor);
|
|
1448
|
-
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1449
|
-
from = Math.min(from, fromB);
|
|
1450
|
-
to = Math.max(to, toB);
|
|
1451
|
-
});
|
|
1452
|
-
from = tr.state.doc.lineAt(from).from;
|
|
1453
|
-
to = tr.state.doc.lineAt(to).to;
|
|
1454
|
-
return value.map(tr.changes).update({
|
|
1455
|
-
filterFrom: from,
|
|
1456
|
-
filterTo: to,
|
|
1457
|
-
filter: () => false,
|
|
1458
|
-
add: buildDecorations(from, to, tr.state)
|
|
1459
|
-
});
|
|
1460
|
-
},
|
|
1461
|
-
provide: (field) => EditorView7.decorations.from(field)
|
|
1462
|
-
});
|
|
1463
|
-
};
|
|
1464
|
-
var buildDecorations = (from, to, state) => {
|
|
1465
|
-
const decorations = [];
|
|
1466
|
-
const cursor = state.selection.main.head;
|
|
1467
|
-
syntaxTree(state).iterate({
|
|
1468
|
-
enter: (node) => {
|
|
1469
|
-
if (node.name === "Image") {
|
|
1470
|
-
const urlNode = node.node.getChild("URL");
|
|
1471
|
-
if (urlNode) {
|
|
1472
|
-
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1473
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1474
|
-
decorations.push(Decoration5.replace({
|
|
1475
|
-
block: true,
|
|
1476
|
-
widget: new ImageWidget(url)
|
|
1477
|
-
}).range(hide ? node.from : node.to, node.to));
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
},
|
|
1481
|
-
from,
|
|
1482
|
-
to
|
|
1483
|
-
});
|
|
1484
|
-
return decorations;
|
|
1485
|
-
};
|
|
1486
|
-
var ImageWidget = class extends WidgetType3 {
|
|
1487
|
-
constructor(_url) {
|
|
1488
|
-
super();
|
|
1489
|
-
this._url = _url;
|
|
1490
|
-
}
|
|
1491
|
-
eq(other) {
|
|
1492
|
-
return this._url === other._url;
|
|
1493
|
-
}
|
|
1494
|
-
toDOM(view) {
|
|
1495
|
-
const img = document.createElement("img");
|
|
1496
|
-
img.setAttribute("src", this._url);
|
|
1497
|
-
img.setAttribute("class", "cm-image");
|
|
1498
|
-
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1499
|
-
return img;
|
|
1500
|
-
}
|
|
1501
|
-
};
|
|
1502
|
-
|
|
1503
|
-
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1504
|
-
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1505
|
-
import { RangeSetBuilder } from "@codemirror/state";
|
|
1506
|
-
import { Decoration as Decoration6, WidgetType as WidgetType4, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1507
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1508
|
-
var link = (options = {}) => {
|
|
1509
|
-
const extensions = [
|
|
1510
|
-
ViewPlugin5.fromClass(class {
|
|
1511
|
-
constructor(view) {
|
|
1512
|
-
this.decorations = buildDecorations2(view, options);
|
|
1513
|
-
}
|
|
1514
|
-
update(update2) {
|
|
1515
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1516
|
-
this.decorations = buildDecorations2(update2.view, options);
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
}, {
|
|
1520
|
-
decorations: (v) => v.decorations
|
|
1521
|
-
})
|
|
1522
|
-
];
|
|
1523
|
-
if (options.onHover) {
|
|
1524
|
-
extensions.push(
|
|
1525
|
-
// https://codemirror.net/examples/tooltip
|
|
1526
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1527
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1528
|
-
hoverTooltip2((view, pos, side) => {
|
|
1529
|
-
const syntax = syntaxTree2(view.state).resolveInner(pos, side);
|
|
1530
|
-
let link2 = null;
|
|
1531
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1532
|
-
link2 = node.name === "Link" ? node : null;
|
|
1533
|
-
}
|
|
1534
|
-
const url = link2 && link2.getChild("URL");
|
|
1535
|
-
if (!url || !link2) {
|
|
1536
|
-
return null;
|
|
1537
|
-
}
|
|
1538
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1539
|
-
return {
|
|
1540
|
-
pos: link2.from,
|
|
1541
|
-
end: link2.to,
|
|
1542
|
-
above: true,
|
|
1543
|
-
create: () => {
|
|
1544
|
-
const el = document.createElement("div");
|
|
1545
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1546
|
-
options.onHover(el, urlText);
|
|
1547
|
-
return {
|
|
1548
|
-
dom: el,
|
|
1549
|
-
offset: {
|
|
1550
|
-
x: 0,
|
|
1551
|
-
y: 4
|
|
1552
|
-
}
|
|
1553
|
-
};
|
|
1554
|
-
}
|
|
1555
|
-
};
|
|
1556
|
-
})
|
|
1557
|
-
);
|
|
1558
|
-
}
|
|
1559
|
-
return extensions;
|
|
1560
|
-
};
|
|
1561
|
-
var LinkButton = class extends WidgetType4 {
|
|
1562
|
-
constructor(_url, _onAttach) {
|
|
1563
|
-
super();
|
|
1564
|
-
this._url = _url;
|
|
1565
|
-
this._onAttach = _onAttach;
|
|
1566
|
-
}
|
|
1567
|
-
eq(other) {
|
|
1568
|
-
return this._url === other._url;
|
|
1569
|
-
}
|
|
1570
|
-
toDOM(view) {
|
|
1571
|
-
const el = document.createElement("span");
|
|
1572
|
-
this._onAttach(el, this._url);
|
|
1573
|
-
return el;
|
|
1574
|
-
}
|
|
1575
|
-
};
|
|
1576
|
-
var LinkText = class extends WidgetType4 {
|
|
1577
|
-
constructor(_text, _url) {
|
|
1578
|
-
super();
|
|
1579
|
-
this._text = _text;
|
|
1580
|
-
this._url = _url;
|
|
1581
|
-
}
|
|
1582
|
-
eq(other) {
|
|
1583
|
-
return this._url === other._url;
|
|
1584
|
-
}
|
|
1585
|
-
toDOM(view) {
|
|
1586
|
-
const link2 = document.createElement("a");
|
|
1587
|
-
link2.setAttribute("class", "cm-link");
|
|
1588
|
-
link2.textContent = this._text;
|
|
1589
|
-
if (this._url) {
|
|
1590
|
-
link2.setAttribute("rel", "noreferrer");
|
|
1591
|
-
link2.setAttribute("target", "_blank");
|
|
1592
|
-
link2.href = this._url;
|
|
1593
|
-
} else {
|
|
1594
|
-
link2.onclick = () => {
|
|
1595
|
-
view.dispatch({
|
|
1596
|
-
selection: {
|
|
1597
|
-
anchor: view.posAtDOM(link2)
|
|
1598
|
-
}
|
|
1599
|
-
});
|
|
1600
|
-
};
|
|
1601
|
-
}
|
|
1602
|
-
return link2;
|
|
1603
|
-
}
|
|
1604
|
-
};
|
|
1605
|
-
var buildDecorations2 = (view, options) => {
|
|
1606
|
-
const builder = new RangeSetBuilder();
|
|
1607
|
-
const { state } = view;
|
|
1608
|
-
const cursor = state.selection.main.head;
|
|
1609
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1610
|
-
syntaxTree2(state).iterate({
|
|
1611
|
-
enter: (node) => {
|
|
1612
|
-
if (node.name === "Link") {
|
|
1613
|
-
const marks2 = node.node.getChildren("LinkMark");
|
|
1614
|
-
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1615
|
-
const urlNode = node.node.getChild("URL");
|
|
1616
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1617
|
-
if (!url) {
|
|
1618
|
-
return false;
|
|
1619
|
-
}
|
|
1620
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1621
|
-
builder.add(node.from, node.to, Decoration6.replace({
|
|
1622
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
1623
|
-
}));
|
|
1624
|
-
}
|
|
1625
|
-
if (options.onRender) {
|
|
1626
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1627
|
-
widget: new LinkButton(url, options.onRender)
|
|
1628
|
-
}));
|
|
1629
|
-
}
|
|
1630
|
-
return false;
|
|
1631
|
-
}
|
|
1632
|
-
},
|
|
1633
|
-
from,
|
|
1634
|
-
to
|
|
1635
|
-
});
|
|
1636
|
-
}
|
|
1637
|
-
return builder.finish();
|
|
1638
|
-
};
|
|
1639
|
-
|
|
1640
|
-
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1641
|
-
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1642
|
-
var listener = ({ onFocus, onChange }) => {
|
|
1643
|
-
const extensions = [];
|
|
1644
|
-
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1645
|
-
onFocus(focused);
|
|
1646
|
-
return null;
|
|
1647
|
-
}));
|
|
1648
|
-
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1649
|
-
onChange(update2.state.doc.toString());
|
|
1650
|
-
}));
|
|
1651
|
-
return extensions;
|
|
1401
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1402
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1403
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1404
|
+
const extensions = [];
|
|
1405
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1406
|
+
onFocus(focused);
|
|
1407
|
+
return null;
|
|
1408
|
+
}));
|
|
1409
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1410
|
+
onChange(update2.state.doc.toString());
|
|
1411
|
+
}));
|
|
1412
|
+
return extensions;
|
|
1652
1413
|
};
|
|
1653
1414
|
|
|
1654
1415
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1655
1416
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1656
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1417
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1657
1418
|
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1658
1419
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1659
1420
|
import { languages } from "@codemirror/language-data";
|
|
1660
1421
|
import { searchKeymap } from "@codemirror/search";
|
|
1661
1422
|
import { EditorState } from "@codemirror/state";
|
|
1662
1423
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1663
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1424
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1664
1425
|
|
|
1665
1426
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1666
1427
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1855,17 +1616,17 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1855
1616
|
return [
|
|
1856
1617
|
EditorState.allowMultipleSelections.of(true),
|
|
1857
1618
|
EditorState.tabSize.of(2),
|
|
1858
|
-
|
|
1859
|
-
|
|
1619
|
+
EditorView7.lineWrapping,
|
|
1620
|
+
// https://github.com/codemirror/basic-setup
|
|
1860
1621
|
bracketMatching2(),
|
|
1861
1622
|
closeBrackets2(),
|
|
1862
1623
|
crosshairCursor(),
|
|
1863
1624
|
dropCursor(),
|
|
1864
1625
|
drawSelection2(),
|
|
1865
|
-
|
|
1866
|
-
|
|
1626
|
+
highlightActiveLine2(),
|
|
1627
|
+
history2(),
|
|
1867
1628
|
indentOnInput(),
|
|
1868
|
-
_placeholder
|
|
1629
|
+
_placeholder ? placeholder2(_placeholder) : [],
|
|
1869
1630
|
// Main extension.
|
|
1870
1631
|
// https://github.com/codemirror/lang-markdown
|
|
1871
1632
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1887,58 +1648,421 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1887
1648
|
// https://github.com/codemirror/theme-one-dark
|
|
1888
1649
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1889
1650
|
// Custom styles.
|
|
1890
|
-
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1651
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly)),
|
|
1652
|
+
keymap4.of([
|
|
1653
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1654
|
+
indentWithTab,
|
|
1655
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1656
|
+
...closeBracketsKeymap,
|
|
1657
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1658
|
+
...historyKeymap,
|
|
1659
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1660
|
+
...searchKeymap,
|
|
1661
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1662
|
+
...standardKeymap
|
|
1663
|
+
])
|
|
1664
|
+
];
|
|
1665
|
+
};
|
|
1905
1666
|
|
|
1906
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1907
|
-
import {
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1667
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1668
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3 } from "@codemirror/view";
|
|
1669
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1670
|
+
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1671
|
+
var styles3 = EditorView8.baseTheme({
|
|
1672
|
+
"& .cm-codeblock": {
|
|
1673
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1674
|
+
},
|
|
1675
|
+
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1676
|
+
background: getToken("extend.colors.neutral.50")
|
|
1677
|
+
},
|
|
1678
|
+
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1679
|
+
background: getToken("extend.colors.neutral.850")
|
|
1680
|
+
},
|
|
1681
|
+
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1682
|
+
display: "block",
|
|
1683
|
+
paddingInline: "4px !important"
|
|
1684
|
+
},
|
|
1685
|
+
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1686
|
+
paddingTop: "4px !important",
|
|
1687
|
+
borderTopLeftRadius: "4px",
|
|
1688
|
+
borderTopRightRadius: "4px"
|
|
1689
|
+
},
|
|
1690
|
+
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1691
|
+
paddingBottom: "4px !important",
|
|
1692
|
+
borderBottomLeftRadius: "4px",
|
|
1693
|
+
borderBottomRightRadius: "4px"
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1696
|
+
var getLineRange = (lines, from, to) => {
|
|
1697
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1698
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1699
|
+
return [
|
|
1700
|
+
start,
|
|
1701
|
+
end
|
|
1702
|
+
];
|
|
1703
|
+
};
|
|
1704
|
+
var code2 = () => {
|
|
1705
|
+
const buildDecorations6 = (view) => {
|
|
1706
|
+
const decorations = [];
|
|
1707
|
+
const text = view.state.doc.sliceString(0);
|
|
1708
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1709
|
+
const blocks = view.viewportLineBlocks;
|
|
1710
|
+
for (const match of matches) {
|
|
1711
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1712
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1713
|
+
const block = blocks[i];
|
|
1714
|
+
decorations.push(Decoration3.line({
|
|
1715
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1716
|
+
}).range(block.from));
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return Decoration3.set(decorations);
|
|
1720
|
+
};
|
|
1721
|
+
return [
|
|
1722
|
+
ViewPlugin3.fromClass(class {
|
|
1723
|
+
constructor(view) {
|
|
1724
|
+
this.hasFocus = false;
|
|
1725
|
+
this.decorations = buildDecorations6(view);
|
|
1726
|
+
}
|
|
1727
|
+
update(update2) {
|
|
1728
|
+
if (
|
|
1729
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1730
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1731
|
+
) {
|
|
1732
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1733
|
+
this.decorations = buildDecorations6(update2.view);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}, {
|
|
1737
|
+
decorations: (value) => value.decorations
|
|
1738
|
+
}),
|
|
1739
|
+
styles3
|
|
1740
|
+
];
|
|
1741
|
+
};
|
|
1742
|
+
|
|
1743
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1744
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1745
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1746
|
+
import { Decoration as Decoration4, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1747
|
+
var buildDecorations = (view) => {
|
|
1748
|
+
const builder = new RangeSetBuilder();
|
|
1749
|
+
const { state } = view;
|
|
1750
|
+
const cursor = state.selection.main.head;
|
|
1751
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1752
|
+
syntaxTree(state).iterate({
|
|
1753
|
+
enter: (node) => {
|
|
1754
|
+
switch (node.name) {
|
|
1755
|
+
case "ATXHeading1":
|
|
1756
|
+
case "ATXHeading2":
|
|
1757
|
+
case "ATXHeading3":
|
|
1758
|
+
case "ATXHeading4":
|
|
1759
|
+
case "ATXHeading5":
|
|
1760
|
+
case "ATXHeading6": {
|
|
1761
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1762
|
+
if (mark2 && (cursor < node.from || cursor > node.to)) {
|
|
1763
|
+
builder.add(mark2.from, mark2.to + 1, Decoration4.replace({}));
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
},
|
|
1768
|
+
from,
|
|
1769
|
+
to
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
return builder.finish();
|
|
1773
|
+
};
|
|
1774
|
+
var heading2 = () => {
|
|
1775
|
+
return [
|
|
1776
|
+
ViewPlugin4.fromClass(class {
|
|
1777
|
+
constructor(view) {
|
|
1778
|
+
this.decorations = buildDecorations(view);
|
|
1779
|
+
}
|
|
1780
|
+
update(update2) {
|
|
1781
|
+
this.decorations = buildDecorations(update2.view);
|
|
1782
|
+
}
|
|
1783
|
+
}, {
|
|
1784
|
+
decorations: (v) => v.decorations
|
|
1785
|
+
})
|
|
1786
|
+
];
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1789
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
1790
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1791
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1792
|
+
import { Decoration as Decoration5, EditorView as EditorView9, ViewPlugin as ViewPlugin5, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1793
|
+
var styles4 = EditorView9.baseTheme({
|
|
1794
|
+
"& .cm-hr": {
|
|
1795
|
+
// Note that block-level decorations should not have vertical margins,
|
|
1796
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1797
|
+
}
|
|
1798
|
+
});
|
|
1799
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1800
|
+
toDOM() {
|
|
1801
|
+
const el = document.createElement("div");
|
|
1802
|
+
el.className = "cm-hr";
|
|
1803
|
+
return el;
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
var decoration = Decoration5.replace({
|
|
1807
|
+
widget: new HorizontalRuleWidget()
|
|
1808
|
+
});
|
|
1809
|
+
var buildDecorations2 = (view) => {
|
|
1810
|
+
const builder = new RangeSetBuilder2();
|
|
1811
|
+
const { state } = view;
|
|
1812
|
+
const cursor = state.selection.main.head;
|
|
1813
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1814
|
+
syntaxTree2(state).iterate({
|
|
1815
|
+
enter: (node) => {
|
|
1816
|
+
if (node.name === "HorizontalRule") {
|
|
1817
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1818
|
+
builder.add(node.from, node.to, decoration);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
},
|
|
1822
|
+
from,
|
|
1823
|
+
to
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
return builder.finish();
|
|
1827
|
+
};
|
|
1828
|
+
var hr = () => {
|
|
1829
|
+
return [
|
|
1830
|
+
styles4,
|
|
1831
|
+
ViewPlugin5.fromClass(class {
|
|
1832
|
+
constructor(view) {
|
|
1833
|
+
this.decorations = buildDecorations2(view);
|
|
1834
|
+
}
|
|
1835
|
+
update(update2) {
|
|
1836
|
+
this.decorations = buildDecorations2(update2.view);
|
|
1837
|
+
}
|
|
1838
|
+
}, {
|
|
1839
|
+
decorations: (v) => v.decorations
|
|
1840
|
+
})
|
|
1841
|
+
];
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1844
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
1845
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1846
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1847
|
+
import { Decoration as Decoration6, EditorView as EditorView10, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1848
|
+
var image = (options = {}) => {
|
|
1849
|
+
return StateField3.define({
|
|
1850
|
+
create: (state) => {
|
|
1851
|
+
return Decoration6.set(buildDecorations3(0, state.doc.length, state));
|
|
1852
|
+
},
|
|
1853
|
+
update: (value, tr) => {
|
|
1854
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1855
|
+
return value;
|
|
1856
|
+
}
|
|
1857
|
+
const cursor = tr.state.selection.main.head;
|
|
1858
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1859
|
+
let from = Math.min(cursor, oldCursor);
|
|
1860
|
+
let to = Math.max(cursor, oldCursor);
|
|
1861
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1862
|
+
from = Math.min(from, fromB);
|
|
1863
|
+
to = Math.max(to, toB);
|
|
1864
|
+
});
|
|
1865
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1866
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1867
|
+
return value.map(tr.changes).update({
|
|
1868
|
+
filterFrom: from,
|
|
1869
|
+
filterTo: to,
|
|
1870
|
+
filter: () => false,
|
|
1871
|
+
add: buildDecorations3(from, to, tr.state)
|
|
1872
|
+
});
|
|
1873
|
+
},
|
|
1874
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1875
|
+
});
|
|
1876
|
+
};
|
|
1877
|
+
var buildDecorations3 = (from, to, state) => {
|
|
1878
|
+
const decorations = [];
|
|
1879
|
+
const cursor = state.selection.main.head;
|
|
1880
|
+
syntaxTree3(state).iterate({
|
|
1881
|
+
enter: (node) => {
|
|
1882
|
+
if (node.name === "Image") {
|
|
1883
|
+
const urlNode = node.node.getChild("URL");
|
|
1884
|
+
if (urlNode) {
|
|
1885
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1886
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1887
|
+
decorations.push(Decoration6.replace({
|
|
1888
|
+
block: true,
|
|
1889
|
+
widget: new ImageWidget(url)
|
|
1890
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
},
|
|
1894
|
+
from,
|
|
1895
|
+
to
|
|
1896
|
+
});
|
|
1897
|
+
return decorations;
|
|
1898
|
+
};
|
|
1899
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1900
|
+
constructor(_url) {
|
|
1901
|
+
super();
|
|
1902
|
+
this._url = _url;
|
|
1903
|
+
}
|
|
1904
|
+
eq(other) {
|
|
1905
|
+
return this._url === other._url;
|
|
1906
|
+
}
|
|
1907
|
+
toDOM(view) {
|
|
1908
|
+
const img = document.createElement("img");
|
|
1909
|
+
img.setAttribute("src", this._url);
|
|
1910
|
+
img.setAttribute("class", "cm-image");
|
|
1911
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1912
|
+
return img;
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
|
|
1916
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
1917
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
1918
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1919
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration7, ViewPlugin as ViewPlugin6, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1920
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1921
|
+
var link = (options = {}) => {
|
|
1922
|
+
const extensions = [
|
|
1923
|
+
ViewPlugin6.fromClass(class {
|
|
1924
|
+
constructor(view) {
|
|
1925
|
+
this.decorations = buildDecorations4(view, options);
|
|
1926
|
+
}
|
|
1927
|
+
update(update2) {
|
|
1928
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1929
|
+
this.decorations = buildDecorations4(update2.view, options);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}, {
|
|
1933
|
+
decorations: (v) => v.decorations
|
|
1934
|
+
})
|
|
1935
|
+
];
|
|
1936
|
+
if (options.onHover) {
|
|
1937
|
+
extensions.push(
|
|
1938
|
+
// https://codemirror.net/examples/tooltip
|
|
1939
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1940
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1941
|
+
hoverTooltip2((view, pos, side) => {
|
|
1942
|
+
const syntax = syntaxTree4(view.state).resolveInner(pos, side);
|
|
1943
|
+
let link2 = null;
|
|
1944
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1945
|
+
link2 = node.name === "Link" ? node : null;
|
|
1946
|
+
}
|
|
1947
|
+
const url = link2 && link2.getChild("URL");
|
|
1948
|
+
if (!url || !link2) {
|
|
1915
1949
|
return null;
|
|
1916
1950
|
}
|
|
1917
|
-
|
|
1918
|
-
return {
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1951
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1952
|
+
return {
|
|
1953
|
+
pos: link2.from,
|
|
1954
|
+
end: link2.to,
|
|
1955
|
+
above: true,
|
|
1956
|
+
create: () => {
|
|
1957
|
+
const el = document.createElement("div");
|
|
1958
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1959
|
+
options.onHover(el, urlText);
|
|
1960
|
+
return {
|
|
1961
|
+
dom: el,
|
|
1962
|
+
offset: {
|
|
1963
|
+
x: 0,
|
|
1964
|
+
y: 4
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
};
|
|
1969
|
+
})
|
|
1970
|
+
);
|
|
1971
|
+
}
|
|
1972
|
+
return extensions;
|
|
1973
|
+
};
|
|
1974
|
+
var LinkButton = class extends WidgetType4 {
|
|
1975
|
+
constructor(_url, _onAttach) {
|
|
1976
|
+
super();
|
|
1977
|
+
this._url = _url;
|
|
1978
|
+
this._onAttach = _onAttach;
|
|
1979
|
+
}
|
|
1980
|
+
eq(other) {
|
|
1981
|
+
return this._url === other._url;
|
|
1982
|
+
}
|
|
1983
|
+
toDOM(view) {
|
|
1984
|
+
const el = document.createElement("span");
|
|
1985
|
+
this._onAttach(el, this._url);
|
|
1986
|
+
return el;
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
var LinkText = class extends WidgetType4 {
|
|
1990
|
+
constructor(_text, _url) {
|
|
1991
|
+
super();
|
|
1992
|
+
this._text = _text;
|
|
1993
|
+
this._url = _url;
|
|
1994
|
+
}
|
|
1995
|
+
eq(other) {
|
|
1996
|
+
return this._url === other._url;
|
|
1997
|
+
}
|
|
1998
|
+
toDOM(view) {
|
|
1999
|
+
const link2 = document.createElement("a");
|
|
2000
|
+
link2.setAttribute("class", "cm-link");
|
|
2001
|
+
link2.textContent = this._text;
|
|
2002
|
+
if (this._url) {
|
|
2003
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2004
|
+
link2.setAttribute("target", "_blank");
|
|
2005
|
+
link2.href = this._url;
|
|
2006
|
+
} else {
|
|
2007
|
+
link2.onclick = () => {
|
|
2008
|
+
view.dispatch({
|
|
2009
|
+
selection: {
|
|
2010
|
+
anchor: view.posAtDOM(link2)
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
return link2;
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
var buildDecorations4 = (view, options) => {
|
|
2019
|
+
const builder = new RangeSetBuilder3();
|
|
2020
|
+
const { state } = view;
|
|
2021
|
+
const cursor = state.selection.main.head;
|
|
2022
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2023
|
+
syntaxTree4(state).iterate({
|
|
2024
|
+
enter: (node) => {
|
|
2025
|
+
if (node.name === "Link") {
|
|
2026
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
2027
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
2028
|
+
const urlNode = node.node.getChild("URL");
|
|
2029
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2030
|
+
if (!url) {
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2034
|
+
builder.add(node.from, node.to, Decoration7.replace({
|
|
2035
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2036
|
+
}));
|
|
2037
|
+
}
|
|
2038
|
+
if (options.onRender) {
|
|
2039
|
+
builder.add(node.to, node.to, Decoration7.replace({
|
|
2040
|
+
widget: new LinkButton(url, options.onRender)
|
|
2041
|
+
}));
|
|
2042
|
+
}
|
|
2043
|
+
return false;
|
|
2044
|
+
}
|
|
2045
|
+
},
|
|
2046
|
+
from,
|
|
2047
|
+
to
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
return builder.finish();
|
|
1927
2051
|
};
|
|
1928
2052
|
|
|
1929
|
-
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1930
|
-
import { syntaxTree as
|
|
1931
|
-
import { RangeSetBuilder as
|
|
1932
|
-
import { Decoration as
|
|
2053
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2054
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2055
|
+
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField4 } from "@codemirror/state";
|
|
2056
|
+
import { Decoration as Decoration8, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1933
2057
|
var table = (options = {}) => {
|
|
1934
2058
|
return StateField4.define({
|
|
1935
2059
|
create: (state) => update(state, options),
|
|
1936
2060
|
update: (_, tr) => update(tr.state, options),
|
|
1937
|
-
provide: (field) =>
|
|
2061
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
1938
2062
|
});
|
|
1939
2063
|
};
|
|
1940
2064
|
var update = (state, options) => {
|
|
1941
|
-
const builder = new
|
|
2065
|
+
const builder = new RangeSetBuilder4();
|
|
1942
2066
|
const cursor = state.selection.main.head;
|
|
1943
2067
|
const tables = [];
|
|
1944
2068
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -1946,7 +2070,7 @@ var update = (state, options) => {
|
|
|
1946
2070
|
const table2 = getTable();
|
|
1947
2071
|
return table2.rows?.[table2.rows.length - 1];
|
|
1948
2072
|
};
|
|
1949
|
-
|
|
2073
|
+
syntaxTree5(state).iterate({
|
|
1950
2074
|
enter: (node) => {
|
|
1951
2075
|
switch (node.name) {
|
|
1952
2076
|
case "Table": {
|
|
@@ -1978,10 +2102,10 @@ var update = (state, options) => {
|
|
|
1978
2102
|
});
|
|
1979
2103
|
tables.forEach((table2) => {
|
|
1980
2104
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
1981
|
-
hide && builder.add(table2.from, table2.to,
|
|
2105
|
+
hide && builder.add(table2.from, table2.to, Decoration8.replace({
|
|
1982
2106
|
widget: new TableWidget(table2)
|
|
1983
2107
|
}));
|
|
1984
|
-
builder.add(table2.from, table2.to,
|
|
2108
|
+
builder.add(table2.from, table2.to, Decoration8.mark({
|
|
1985
2109
|
class: "cm-table"
|
|
1986
2110
|
}));
|
|
1987
2111
|
});
|
|
@@ -2024,90 +2148,137 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2024
2148
|
}
|
|
2025
2149
|
};
|
|
2026
2150
|
|
|
2027
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2028
|
-
import {
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2151
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2152
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2153
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2154
|
+
import { EditorView as EditorView12, Decoration as Decoration9, WidgetType as WidgetType6, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
2155
|
+
var styles5 = EditorView12.baseTheme({
|
|
2156
|
+
"& .cm-task": {
|
|
2157
|
+
color: getToken("extend.colors.blue.500")
|
|
2158
|
+
},
|
|
2159
|
+
"& .cm-task-checkbox": {
|
|
2160
|
+
marginLeft: "4px",
|
|
2161
|
+
marginRight: "4px"
|
|
2033
2162
|
}
|
|
2034
2163
|
});
|
|
2035
2164
|
var CheckboxWidget = class extends WidgetType6 {
|
|
2036
|
-
constructor(_checked
|
|
2165
|
+
constructor(_checked) {
|
|
2037
2166
|
super();
|
|
2038
2167
|
this._checked = _checked;
|
|
2039
|
-
this._indent = _indent;
|
|
2040
|
-
this._onCheck = _onCheck;
|
|
2041
2168
|
}
|
|
2042
2169
|
eq(other) {
|
|
2043
|
-
return this._checked === other._checked
|
|
2170
|
+
return this._checked === other._checked;
|
|
2044
2171
|
}
|
|
2045
2172
|
toDOM(view) {
|
|
2046
|
-
const
|
|
2047
|
-
|
|
2048
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2049
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2050
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2173
|
+
const input = document.createElement("input");
|
|
2174
|
+
input.className = "cm-task-checkbox";
|
|
2051
2175
|
input.type = "checkbox";
|
|
2052
2176
|
input.checked = this._checked;
|
|
2053
|
-
if (
|
|
2177
|
+
if (view.state.readOnly) {
|
|
2054
2178
|
input.setAttribute("disabled", "true");
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2179
|
+
} else {
|
|
2180
|
+
input.onmousedown = (event) => {
|
|
2181
|
+
const pos = view.posAtDOM(input);
|
|
2182
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2183
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2184
|
+
view.dispatch({
|
|
2185
|
+
changes: {
|
|
2186
|
+
from: pos + 1,
|
|
2187
|
+
to: pos + 2,
|
|
2188
|
+
insert: this._checked ? " " : "x"
|
|
2189
|
+
}
|
|
2190
|
+
});
|
|
2191
|
+
event.preventDefault();
|
|
2192
|
+
}
|
|
2060
2193
|
};
|
|
2061
2194
|
}
|
|
2062
|
-
return
|
|
2195
|
+
return input;
|
|
2063
2196
|
}
|
|
2064
2197
|
ignoreEvent() {
|
|
2065
2198
|
return false;
|
|
2066
2199
|
}
|
|
2067
2200
|
};
|
|
2201
|
+
var checkedDecoration = Decoration9.replace({
|
|
2202
|
+
widget: new CheckboxWidget(true)
|
|
2203
|
+
});
|
|
2204
|
+
var uncheckedDecoration = Decoration9.replace({
|
|
2205
|
+
widget: new CheckboxWidget(false)
|
|
2206
|
+
});
|
|
2207
|
+
var buildDecorations5 = (view) => {
|
|
2208
|
+
const builder = new RangeSetBuilder5();
|
|
2209
|
+
const { state } = view;
|
|
2210
|
+
const cursor = state.selection.main.head;
|
|
2211
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2212
|
+
syntaxTree6(state).iterate({
|
|
2213
|
+
enter: (node) => {
|
|
2214
|
+
if (node.name === "TaskMarker") {
|
|
2215
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2216
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2217
|
+
builder.add(node.from - 2, node.from - 1, Decoration9.mark({
|
|
2218
|
+
class: "cm-task"
|
|
2219
|
+
}));
|
|
2220
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
},
|
|
2224
|
+
from,
|
|
2225
|
+
to
|
|
2226
|
+
});
|
|
2227
|
+
}
|
|
2228
|
+
return builder.finish();
|
|
2229
|
+
};
|
|
2068
2230
|
var tasklist = (options = {}) => {
|
|
2069
|
-
const taskMatcher = new MatchDecorator2({
|
|
2070
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2071
|
-
decoration: (match, view, pos) => {
|
|
2072
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2073
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2074
|
-
return Decoration8.replace({
|
|
2075
|
-
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2076
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2077
|
-
view.dispatch({
|
|
2078
|
-
changes: {
|
|
2079
|
-
from: idx,
|
|
2080
|
-
to: idx + 1,
|
|
2081
|
-
insert: checked2 ? "x" : " "
|
|
2082
|
-
},
|
|
2083
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2084
|
-
selection: {
|
|
2085
|
-
anchor: idx + 3
|
|
2086
|
-
}
|
|
2087
|
-
});
|
|
2088
|
-
})
|
|
2089
|
-
});
|
|
2090
|
-
}
|
|
2091
|
-
});
|
|
2092
|
-
const tasks = ViewPlugin6.fromClass(class {
|
|
2093
|
-
constructor(view) {
|
|
2094
|
-
this.tasks = taskMatcher.createDeco(view);
|
|
2095
|
-
}
|
|
2096
|
-
update(update2) {
|
|
2097
|
-
this.tasks = taskMatcher.updateDeco(update2, this.tasks);
|
|
2098
|
-
}
|
|
2099
|
-
}, {
|
|
2100
|
-
decorations: (value) => value.tasks,
|
|
2101
|
-
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2102
|
-
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
2103
|
-
})
|
|
2104
|
-
});
|
|
2105
2231
|
return [
|
|
2106
|
-
|
|
2232
|
+
ViewPlugin7.fromClass(class {
|
|
2233
|
+
constructor(view) {
|
|
2234
|
+
this.decorations = buildDecorations5(view);
|
|
2235
|
+
}
|
|
2236
|
+
update(update2) {
|
|
2237
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2238
|
+
this.decorations = buildDecorations5(update2.view);
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
}, {
|
|
2242
|
+
decorations: (v) => v.decorations
|
|
2243
|
+
}),
|
|
2107
2244
|
styles5
|
|
2108
2245
|
];
|
|
2109
2246
|
};
|
|
2110
2247
|
|
|
2248
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2249
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2250
|
+
var mention = ({ onSearch }) => {
|
|
2251
|
+
return autocompletion2({
|
|
2252
|
+
// TODO(burdon): Not working.
|
|
2253
|
+
activateOnTyping: true,
|
|
2254
|
+
// activateOnTypingDelay: 100,
|
|
2255
|
+
// selectOnOpen: true,
|
|
2256
|
+
closeOnBlur: false,
|
|
2257
|
+
// defaultKeymap: false,
|
|
2258
|
+
icons: false,
|
|
2259
|
+
override: [
|
|
2260
|
+
(context) => {
|
|
2261
|
+
console.log(context);
|
|
2262
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2263
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2264
|
+
return null;
|
|
2265
|
+
}
|
|
2266
|
+
return {
|
|
2267
|
+
from: match.from,
|
|
2268
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2269
|
+
label: `@${value}`
|
|
2270
|
+
}))
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
]
|
|
2274
|
+
});
|
|
2275
|
+
};
|
|
2276
|
+
|
|
2277
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2278
|
+
var outliner = (options = {}) => {
|
|
2279
|
+
return [];
|
|
2280
|
+
};
|
|
2281
|
+
|
|
2111
2282
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2112
2283
|
import { keymap as keymap5 } from "@codemirror/view";
|
|
2113
2284
|
var defaultItems = [
|
|
@@ -2165,27 +2336,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2165
2336
|
];
|
|
2166
2337
|
};
|
|
2167
2338
|
|
|
2168
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2169
|
-
import { yCollab } from "y-codemirror.next";
|
|
2170
|
-
|
|
2171
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2172
|
-
import * as Y from "yjs";
|
|
2173
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2174
|
-
var cursorConverter2 = (text) => ({
|
|
2175
|
-
toCursor: (index, assoc) => {
|
|
2176
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2177
|
-
},
|
|
2178
|
-
fromCursor: (cursor) => {
|
|
2179
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2180
|
-
}
|
|
2181
|
-
});
|
|
2182
|
-
|
|
2183
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2184
|
-
var yjs = (content, awareness2) => [
|
|
2185
|
-
Cursor.converter.of(cursorConverter2(content)),
|
|
2186
|
-
yCollab(content, awareness2)
|
|
2187
|
-
];
|
|
2188
|
-
|
|
2189
2339
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2190
2340
|
import get3 from "lodash.get";
|
|
2191
2341
|
var defaultTheme = {
|
|
@@ -2315,13 +2465,6 @@ var defaultTheme = {
|
|
|
2315
2465
|
textDecoration: "none"
|
|
2316
2466
|
},
|
|
2317
2467
|
//
|
|
2318
|
-
// widgets
|
|
2319
|
-
//
|
|
2320
|
-
".cm-widgetBuffer": {
|
|
2321
|
-
display: "none",
|
|
2322
|
-
height: 0
|
|
2323
|
-
},
|
|
2324
|
-
//
|
|
2325
2468
|
// table
|
|
2326
2469
|
//
|
|
2327
2470
|
".cm-table *": {
|
|
@@ -2430,11 +2573,12 @@ var codeTheme = {
|
|
|
2430
2573
|
};
|
|
2431
2574
|
|
|
2432
2575
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2576
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2433
2577
|
var EditorModes = [
|
|
2434
2578
|
"default",
|
|
2435
2579
|
"vim"
|
|
2436
2580
|
];
|
|
2437
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model,
|
|
2581
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2438
2582
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2439
2583
|
tabBehavior: "limited"
|
|
2440
2584
|
});
|
|
@@ -2444,76 +2588,67 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, read
|
|
|
2444
2588
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2445
2589
|
view
|
|
2446
2590
|
]);
|
|
2447
|
-
|
|
2448
|
-
if (
|
|
2449
|
-
view
|
|
2450
|
-
}
|
|
2451
|
-
}, [
|
|
2452
|
-
view,
|
|
2453
|
-
focus
|
|
2454
|
-
]);
|
|
2455
|
-
const { awareness: awareness2, peer } = model;
|
|
2456
|
-
useEffect(() => {
|
|
2457
|
-
if (awareness2 && peer) {
|
|
2458
|
-
awareness2.setLocalStateField("user", {
|
|
2459
|
-
name: peer.name ?? generateName(peer.id),
|
|
2460
|
-
color: getColorForValue({
|
|
2461
|
-
value: peer.id,
|
|
2462
|
-
type: "color"
|
|
2463
|
-
}),
|
|
2464
|
-
colorLight: getColorForValue({
|
|
2465
|
-
value: peer.id,
|
|
2466
|
-
themeMode,
|
|
2467
|
-
type: "highlight"
|
|
2468
|
-
})
|
|
2469
|
-
});
|
|
2470
|
-
}
|
|
2471
|
-
}, [
|
|
2472
|
-
awareness2,
|
|
2473
|
-
peer,
|
|
2474
|
-
themeMode
|
|
2475
|
-
]);
|
|
2476
|
-
useEffect(() => {
|
|
2477
|
-
if (view && comments2 !== void 0) {
|
|
2478
|
-
view.dispatch({
|
|
2479
|
-
effects: setCommentRange.of({
|
|
2480
|
-
model,
|
|
2481
|
-
comments: comments2
|
|
2482
|
-
})
|
|
2483
|
-
});
|
|
2591
|
+
useEffect2(() => {
|
|
2592
|
+
if (autoFocus) {
|
|
2593
|
+
view?.focus();
|
|
2484
2594
|
}
|
|
2485
2595
|
}, [
|
|
2486
2596
|
view,
|
|
2487
|
-
|
|
2597
|
+
autoFocus
|
|
2488
2598
|
]);
|
|
2489
|
-
|
|
2599
|
+
useEffect2(() => {
|
|
2490
2600
|
if (!model || !rootRef.current) {
|
|
2491
2601
|
return;
|
|
2492
2602
|
}
|
|
2493
2603
|
const state = EditorState2.create({
|
|
2494
2604
|
doc: model.text(),
|
|
2495
|
-
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2496
2605
|
selection,
|
|
2497
2606
|
extensions: [
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2607
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2608
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2609
|
+
log2.catch(err, void 0, {
|
|
2610
|
+
F: __dxlog_file5,
|
|
2611
|
+
L: 123,
|
|
2612
|
+
S: void 0,
|
|
2613
|
+
C: (f, a) => f(...a)
|
|
2614
|
+
});
|
|
2615
|
+
}),
|
|
2501
2616
|
// Theme.
|
|
2502
|
-
// TODO(burdon): Make
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2617
|
+
// TODO(burdon): Make configurable.
|
|
2618
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2619
|
+
EditorView13.theme(theme ?? {}),
|
|
2620
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2621
|
+
EditorView13.editorAttributes.of({
|
|
2622
|
+
class: slots.editor?.className ?? ""
|
|
2623
|
+
}),
|
|
2624
|
+
EditorView13.contentAttributes.of({
|
|
2625
|
+
class: slots.content?.className ?? ""
|
|
2626
|
+
}),
|
|
2627
|
+
// State.
|
|
2628
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2506
2629
|
// Storage and replication.
|
|
2630
|
+
// NOTE: This must come before user extensions.
|
|
2507
2631
|
model.extension,
|
|
2632
|
+
// TODO(burdon): Factor out (requires special handling for Escape/focus).
|
|
2633
|
+
editorMode === "vim" && vim(),
|
|
2508
2634
|
// Custom.
|
|
2509
2635
|
...extensions
|
|
2510
2636
|
].filter(Boolean)
|
|
2511
2637
|
});
|
|
2512
|
-
|
|
2513
|
-
|
|
2638
|
+
const newView = new EditorView13({
|
|
2639
|
+
state,
|
|
2514
2640
|
parent: rootRef.current,
|
|
2515
|
-
|
|
2641
|
+
scrollTo,
|
|
2642
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2643
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2644
|
+
dispatchTransactions: (trs, view2) => {
|
|
2645
|
+
if (debug) {
|
|
2646
|
+
logChanges(trs);
|
|
2647
|
+
}
|
|
2648
|
+
view2.update(trs);
|
|
2649
|
+
}
|
|
2516
2650
|
});
|
|
2651
|
+
view?.destroy();
|
|
2517
2652
|
setView(newView);
|
|
2518
2653
|
return () => {
|
|
2519
2654
|
newView?.destroy();
|
|
@@ -2529,8 +2664,14 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, read
|
|
|
2529
2664
|
const handleKeyUp = useCallback((event) => {
|
|
2530
2665
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2531
2666
|
switch (key) {
|
|
2667
|
+
case "Enter": {
|
|
2668
|
+
view?.focus();
|
|
2669
|
+
break;
|
|
2670
|
+
}
|
|
2532
2671
|
case "Escape": {
|
|
2533
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2672
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2673
|
+
rootRef.current?.focus();
|
|
2674
|
+
}
|
|
2534
2675
|
break;
|
|
2535
2676
|
}
|
|
2536
2677
|
}
|
|
@@ -2541,14 +2682,14 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, read
|
|
|
2541
2682
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2542
2683
|
key: model.id,
|
|
2543
2684
|
role: "none",
|
|
2544
|
-
ref: rootRef,
|
|
2545
2685
|
tabIndex: 0,
|
|
2546
2686
|
onKeyUp: handleKeyUp,
|
|
2547
2687
|
...slots.root,
|
|
2548
|
-
...editorMode !== "vim" && tabsterDOMAttribute
|
|
2688
|
+
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2689
|
+
ref: rootRef
|
|
2549
2690
|
});
|
|
2550
2691
|
});
|
|
2551
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2692
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2552
2693
|
const { themeMode } = useThemeContext();
|
|
2553
2694
|
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2554
2695
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
@@ -2556,9 +2697,9 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2556
2697
|
readonly,
|
|
2557
2698
|
extensions: [
|
|
2558
2699
|
basicBundle({
|
|
2559
|
-
readonly,
|
|
2560
2700
|
themeMode,
|
|
2561
|
-
placeholder: placeholder3
|
|
2701
|
+
placeholder: placeholder3,
|
|
2702
|
+
lineWrapping
|
|
2562
2703
|
}),
|
|
2563
2704
|
...extensions
|
|
2564
2705
|
],
|
|
@@ -2567,7 +2708,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2567
2708
|
...props
|
|
2568
2709
|
});
|
|
2569
2710
|
});
|
|
2570
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2711
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2571
2712
|
const { themeMode } = useThemeContext();
|
|
2572
2713
|
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2573
2714
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
@@ -2575,8 +2716,8 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2575
2716
|
readonly,
|
|
2576
2717
|
extensions: [
|
|
2577
2718
|
markdownBundle({
|
|
2578
|
-
readonly,
|
|
2579
2719
|
themeMode,
|
|
2720
|
+
readonly,
|
|
2580
2721
|
placeholder: placeholder3
|
|
2581
2722
|
}),
|
|
2582
2723
|
...extensions
|
|
@@ -2588,7 +2729,11 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2588
2729
|
});
|
|
2589
2730
|
var defaultSlots = {
|
|
2590
2731
|
root: {
|
|
2591
|
-
|
|
2732
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
2733
|
+
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
2734
|
+
},
|
|
2735
|
+
editor: {
|
|
2736
|
+
className: "h-full p-2"
|
|
2592
2737
|
}
|
|
2593
2738
|
};
|
|
2594
2739
|
var defaultTextSlots = {
|
|
@@ -2598,22 +2743,17 @@ var defaultMarkdownSlots = {
|
|
|
2598
2743
|
...defaultSlots
|
|
2599
2744
|
};
|
|
2600
2745
|
|
|
2601
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2602
|
-
import get4 from "lodash.get";
|
|
2603
|
-
import { getRawDoc } from "@dxos/echo-schema";
|
|
2604
|
-
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2605
|
-
|
|
2606
2746
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2607
2747
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2608
2748
|
import { Context as Context2 } from "@dxos/context";
|
|
2609
|
-
import { invariant as
|
|
2749
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2610
2750
|
import { log as log3 } from "@dxos/log";
|
|
2611
|
-
var
|
|
2751
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2612
2752
|
var DEBOUNCE_INTERVAL = 100;
|
|
2613
2753
|
var SpaceAwarenessProvider = class {
|
|
2614
2754
|
constructor(params) {
|
|
2615
|
-
this.remoteStateChange = new Event2();
|
|
2616
2755
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
2756
|
+
this.remoteStateChange = new Event2();
|
|
2617
2757
|
this._space = params.space;
|
|
2618
2758
|
this._channel = params.channel;
|
|
2619
2759
|
this._peerId = params.peerId;
|
|
@@ -2630,7 +2770,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2630
2770
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2631
2771
|
}
|
|
2632
2772
|
});
|
|
2633
|
-
|
|
2773
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2634
2774
|
switch (message.payload.kind) {
|
|
2635
2775
|
case "query": {
|
|
2636
2776
|
this._handleQueryMessage();
|
|
@@ -2641,16 +2781,15 @@ var SpaceAwarenessProvider = class {
|
|
|
2641
2781
|
break;
|
|
2642
2782
|
}
|
|
2643
2783
|
}
|
|
2644
|
-
});
|
|
2645
|
-
this._ctx.onDispose(unsubscribe);
|
|
2784
|
+
}));
|
|
2646
2785
|
void this._space.postMessage(this._channel, {
|
|
2647
2786
|
kind: "query"
|
|
2648
2787
|
}).catch((err) => {
|
|
2649
2788
|
log3.debug("failed to query awareness", {
|
|
2650
2789
|
err
|
|
2651
2790
|
}, {
|
|
2652
|
-
F:
|
|
2653
|
-
L:
|
|
2791
|
+
F: __dxlog_file6,
|
|
2792
|
+
L: 89,
|
|
2654
2793
|
S: this,
|
|
2655
2794
|
C: (f, a) => f(...a)
|
|
2656
2795
|
});
|
|
@@ -2661,10 +2800,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2661
2800
|
this._ctx = void 0;
|
|
2662
2801
|
this._postTask = void 0;
|
|
2663
2802
|
}
|
|
2803
|
+
getRemoteStates() {
|
|
2804
|
+
return Array.from(this._remoteStates.values());
|
|
2805
|
+
}
|
|
2664
2806
|
update(position) {
|
|
2665
|
-
|
|
2666
|
-
F:
|
|
2667
|
-
L:
|
|
2807
|
+
invariant4(this._postTask, void 0, {
|
|
2808
|
+
F: __dxlog_file6,
|
|
2809
|
+
L: 104,
|
|
2668
2810
|
S: this,
|
|
2669
2811
|
A: [
|
|
2670
2812
|
"this._postTask",
|
|
@@ -2678,13 +2820,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2678
2820
|
};
|
|
2679
2821
|
this._postTask.schedule();
|
|
2680
2822
|
}
|
|
2681
|
-
getRemoteStates() {
|
|
2682
|
-
return Array.from(this._remoteStates.values());
|
|
2683
|
-
}
|
|
2684
2823
|
_handleQueryMessage() {
|
|
2685
|
-
|
|
2686
|
-
F:
|
|
2687
|
-
L:
|
|
2824
|
+
invariant4(this._postTask, void 0, {
|
|
2825
|
+
F: __dxlog_file6,
|
|
2826
|
+
L: 115,
|
|
2688
2827
|
S: this,
|
|
2689
2828
|
A: [
|
|
2690
2829
|
"this._postTask",
|
|
@@ -2694,9 +2833,9 @@ var SpaceAwarenessProvider = class {
|
|
|
2694
2833
|
this._postTask.schedule();
|
|
2695
2834
|
}
|
|
2696
2835
|
_handlePostMessage(message) {
|
|
2697
|
-
|
|
2698
|
-
F:
|
|
2699
|
-
L:
|
|
2836
|
+
invariant4(message.kind === "post", void 0, {
|
|
2837
|
+
F: __dxlog_file6,
|
|
2838
|
+
L: 120,
|
|
2700
2839
|
S: this,
|
|
2701
2840
|
A: [
|
|
2702
2841
|
"message.kind === 'post'",
|
|
@@ -2708,171 +2847,54 @@ var SpaceAwarenessProvider = class {
|
|
|
2708
2847
|
}
|
|
2709
2848
|
};
|
|
2710
2849
|
|
|
2711
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2850
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2712
2851
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2713
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2714
|
-
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2715
|
-
|
|
2716
|
-
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2717
|
-
import * as decoding from "lib0/decoding";
|
|
2718
|
-
import * as encoding from "lib0/encoding";
|
|
2719
|
-
import { Observable } from "lib0/observable";
|
|
2720
|
-
import * as YP from "y-protocols/awareness";
|
|
2721
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2722
|
-
import { log as log4 } from "@dxos/log";
|
|
2723
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2724
|
-
var createYjsModel = ({ identity, space, text }) => {
|
|
2725
|
-
invariant4(text?.doc && text?.content, void 0, {
|
|
2726
|
-
F: __dxlog_file5,
|
|
2727
|
-
L: 21,
|
|
2728
|
-
S: void 0,
|
|
2729
|
-
A: [
|
|
2730
|
-
"text?.doc && text?.content",
|
|
2731
|
-
""
|
|
2732
|
-
]
|
|
2733
|
-
});
|
|
2734
|
-
const provider = space ? new YAwarenessProvider({
|
|
2735
|
-
space,
|
|
2736
|
-
doc: text.doc,
|
|
2737
|
-
channel: `yjs.awareness.${text.id}`
|
|
2738
|
-
}) : void 0;
|
|
2739
|
-
const model = {
|
|
2740
|
-
id: text.doc.guid,
|
|
2741
|
-
content: text.content,
|
|
2742
|
-
text: () => text.content.toString(),
|
|
2743
|
-
extension: [
|
|
2744
|
-
modelState.init(() => model),
|
|
2745
|
-
yjs(text.content, provider?.awareness)
|
|
2746
|
-
],
|
|
2747
|
-
awareness: provider?.awareness,
|
|
2748
|
-
peer: identity ? {
|
|
2749
|
-
id: identity.identityKey.toHex(),
|
|
2750
|
-
name: identity.profile?.displayName
|
|
2751
|
-
} : void 0
|
|
2752
|
-
};
|
|
2753
|
-
return model;
|
|
2754
|
-
};
|
|
2755
|
-
var messageAwareness = 1;
|
|
2756
|
-
var messageQueryAwareness = 3;
|
|
2757
|
-
var YAwarenessProvider = class extends Observable {
|
|
2758
|
-
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2759
|
-
super();
|
|
2760
|
-
this._space = space;
|
|
2761
|
-
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2762
|
-
this._channel = channel;
|
|
2763
|
-
this._clientId = doc.clientID;
|
|
2764
|
-
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
2765
|
-
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
2766
|
-
if (typeof window !== "undefined") {
|
|
2767
|
-
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
2768
|
-
} else if (typeof process !== "undefined") {
|
|
2769
|
-
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
2770
|
-
}
|
|
2771
|
-
const encoderAwarenessQuery = encoding.createEncoder();
|
|
2772
|
-
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
2773
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
2774
|
-
const encoderAwarenessState = encoding.createEncoder();
|
|
2775
|
-
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
2776
|
-
encoding.writeVarUint8Array(encoderAwarenessState, YP.encodeAwarenessUpdate(this.awareness, [
|
|
2777
|
-
this._clientId
|
|
2778
|
-
]));
|
|
2779
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
2780
|
-
}
|
|
2781
|
-
get awareness() {
|
|
2782
|
-
return this._awareness;
|
|
2783
|
-
}
|
|
2784
|
-
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2785
|
-
log4("awareness update", {
|
|
2786
|
-
added,
|
|
2787
|
-
updated,
|
|
2788
|
-
removed,
|
|
2789
|
-
origin
|
|
2790
|
-
}, {
|
|
2791
|
-
F: __dxlog_file5,
|
|
2792
|
-
L: 100,
|
|
2793
|
-
S: this,
|
|
2794
|
-
C: (f, a) => f(...a)
|
|
2795
|
-
});
|
|
2796
|
-
const changedClients = added.concat(updated).concat(removed);
|
|
2797
|
-
const encoderAwareness = encoding.createEncoder();
|
|
2798
|
-
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
2799
|
-
encoding.writeVarUint8Array(encoderAwareness, YP.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
2800
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2801
|
-
}
|
|
2802
|
-
_handleSpaceMessage({ payload }) {
|
|
2803
|
-
log4("space message", payload, {
|
|
2804
|
-
F: __dxlog_file5,
|
|
2805
|
-
L: 109,
|
|
2806
|
-
S: this,
|
|
2807
|
-
C: (f, a) => f(...a)
|
|
2808
|
-
});
|
|
2809
|
-
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2810
|
-
const encoder = this._readMessage(data);
|
|
2811
|
-
if (encoder) {
|
|
2812
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
_readMessage(message) {
|
|
2816
|
-
const decoder = decoding.createDecoder(message);
|
|
2817
|
-
const encoder = encoding.createEncoder();
|
|
2818
|
-
const messageType = decoding.readVarUint(decoder);
|
|
2819
|
-
let sendReply = false;
|
|
2820
|
-
switch (messageType) {
|
|
2821
|
-
case messageAwareness: {
|
|
2822
|
-
YP.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
2823
|
-
break;
|
|
2824
|
-
}
|
|
2825
|
-
case messageQueryAwareness: {
|
|
2826
|
-
encoding.writeVarUint(encoder, messageAwareness);
|
|
2827
|
-
encoding.writeVarUint8Array(encoder, YP.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
2828
|
-
sendReply = true;
|
|
2829
|
-
break;
|
|
2830
|
-
}
|
|
2831
|
-
default: {
|
|
2832
|
-
console.error("Invalid message:", messageType);
|
|
2833
|
-
return encoder;
|
|
2834
|
-
}
|
|
2835
|
-
}
|
|
2836
|
-
if (!sendReply) {
|
|
2837
|
-
return null;
|
|
2838
|
-
}
|
|
2839
|
-
return encoder;
|
|
2840
|
-
}
|
|
2841
|
-
_handleBeforeUnload() {
|
|
2842
|
-
YP.removeAwarenessStates(this._awareness, [
|
|
2843
|
-
this._clientId
|
|
2844
|
-
], "window unload");
|
|
2845
|
-
}
|
|
2846
|
-
};
|
|
2847
|
-
|
|
2848
|
-
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2849
2852
|
var modelState = StateField5.define({
|
|
2850
2853
|
create: () => void 0,
|
|
2851
2854
|
update: (model) => model
|
|
2852
2855
|
});
|
|
2856
|
+
|
|
2857
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
2858
|
+
import { useState as useState2 } from "react";
|
|
2859
|
+
var useTextEditor = () => {
|
|
2860
|
+
const [view, setView] = useState2(null);
|
|
2861
|
+
return [
|
|
2862
|
+
(ref) => {
|
|
2863
|
+
setView(ref);
|
|
2864
|
+
},
|
|
2865
|
+
view
|
|
2866
|
+
];
|
|
2867
|
+
};
|
|
2868
|
+
|
|
2869
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2870
|
+
import get4 from "lodash.get";
|
|
2871
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
2872
|
+
import { generateName } from "@dxos/display-name";
|
|
2873
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
2874
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
2875
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2876
|
+
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2877
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2853
2878
|
var useTextModel = (props) => {
|
|
2854
2879
|
const { identity, space, text } = props;
|
|
2855
|
-
const [model, setModel] =
|
|
2856
|
-
|
|
2880
|
+
const [model, setModel] = useState3();
|
|
2881
|
+
useEffect3(() => setModel(createModel(props)), [
|
|
2857
2882
|
identity,
|
|
2858
2883
|
space,
|
|
2859
2884
|
text
|
|
2860
2885
|
]);
|
|
2861
2886
|
return model;
|
|
2862
2887
|
};
|
|
2863
|
-
var createModel = (
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
};
|
|
2873
|
-
|
|
2874
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2875
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2888
|
+
var createModel = ({ space, identity, text }) => {
|
|
2889
|
+
invariant5(isAutomergeObject(text), void 0, {
|
|
2890
|
+
F: __dxlog_file7,
|
|
2891
|
+
L: 35,
|
|
2892
|
+
S: void 0,
|
|
2893
|
+
A: [
|
|
2894
|
+
"isAutomergeObject(text)",
|
|
2895
|
+
""
|
|
2896
|
+
]
|
|
2897
|
+
});
|
|
2876
2898
|
const obj = text;
|
|
2877
2899
|
const doc = getRawDoc(obj, [
|
|
2878
2900
|
obj.field
|
|
@@ -2881,7 +2903,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2881
2903
|
space,
|
|
2882
2904
|
channel: `automerge.awareness.${obj.id}`,
|
|
2883
2905
|
info: {
|
|
2884
|
-
displayName: identity
|
|
2906
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
2885
2907
|
color: cursorColor.color,
|
|
2886
2908
|
lightColor: cursorColor.light
|
|
2887
2909
|
},
|
|
@@ -2891,7 +2913,6 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
2891
2913
|
id: obj.id,
|
|
2892
2914
|
content: doc,
|
|
2893
2915
|
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2894
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2895
2916
|
extension: [
|
|
2896
2917
|
modelState.init(() => model),
|
|
2897
2918
|
automerge3({
|
|
@@ -2919,7 +2940,6 @@ export {
|
|
|
2919
2940
|
SpaceAwarenessProvider,
|
|
2920
2941
|
TextEditor,
|
|
2921
2942
|
TextKind,
|
|
2922
|
-
YAwarenessProvider,
|
|
2923
2943
|
YText,
|
|
2924
2944
|
YXmlFragment,
|
|
2925
2945
|
autocomplete,
|
|
@@ -2931,19 +2951,18 @@ export {
|
|
|
2931
2951
|
code2 as code,
|
|
2932
2952
|
codeTheme,
|
|
2933
2953
|
comments,
|
|
2934
|
-
createAutomergeModel,
|
|
2935
|
-
createYjsModel,
|
|
2936
|
-
cursorConverter,
|
|
2937
2954
|
defaultMarkdownSlots,
|
|
2938
2955
|
defaultOptions,
|
|
2939
2956
|
defaultSlots,
|
|
2940
2957
|
defaultTextSlots,
|
|
2941
2958
|
defaultTheme,
|
|
2942
2959
|
getToken,
|
|
2960
|
+
heading2 as heading,
|
|
2943
2961
|
hr,
|
|
2944
2962
|
image,
|
|
2945
2963
|
link,
|
|
2946
2964
|
listener,
|
|
2965
|
+
logChanges,
|
|
2947
2966
|
markdownBundle,
|
|
2948
2967
|
markdownHighlightStyle,
|
|
2949
2968
|
markdownTags,
|
|
@@ -2951,7 +2970,8 @@ export {
|
|
|
2951
2970
|
markdownTheme,
|
|
2952
2971
|
mention,
|
|
2953
2972
|
modelState,
|
|
2954
|
-
|
|
2973
|
+
outliner,
|
|
2974
|
+
setComments,
|
|
2955
2975
|
setFocus,
|
|
2956
2976
|
setSelection,
|
|
2957
2977
|
table,
|
|
@@ -2959,7 +2979,8 @@ export {
|
|
|
2959
2979
|
tasklist,
|
|
2960
2980
|
textTheme,
|
|
2961
2981
|
typewriter,
|
|
2962
|
-
|
|
2963
|
-
|
|
2982
|
+
useComments,
|
|
2983
|
+
useTextEditor,
|
|
2984
|
+
useTextModel
|
|
2964
2985
|
};
|
|
2965
2986
|
//# sourceMappingURL=index.mjs.map
|