@dxos/react-ui-editor 0.3.11-main.a8d7a97 → 0.3.11-main.b00882f
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 +690 -519
- 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 +2 -0
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +4 -5
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/code.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +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/hr.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +1 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +2 -5
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge.d.ts +2 -1
- package/dist/types/src/hooks/automerge.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +28 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +3 -1
- 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/hooks/yjs.d.ts +2 -1
- package/dist/types/src/hooks/yjs.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 +32 -32
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +64 -69
- package/src/components/TextEditor/TextEditor.tsx +97 -69
- 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 +20 -2
- package/src/extensions/basic.ts +22 -17
- package/src/extensions/code.ts +15 -17
- package/src/extensions/comments.ts +239 -136
- package/src/extensions/cursor.ts +7 -3
- package/src/extensions/hr.ts +49 -50
- package/src/extensions/index.ts +1 -0
- package/src/extensions/link.ts +3 -3
- package/src/extensions/markdown/bundle.ts +18 -24
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/extensions/tasklist.ts +76 -84
- package/src/extensions/yjs/yjs.test.ts +1 -1
- package/src/hooks/automerge.ts +2 -1
- package/src/hooks/defs.ts +47 -0
- package/src/hooks/index.ts +4 -1
- package/src/hooks/useTextEditor.ts +29 -0
- package/src/hooks/useTextModel.ts +2 -45
- package/src/hooks/yjs.ts +2 -1
- package/src/util.ts +26 -3
|
@@ -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 {
|
|
16
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useRef, useState } from "react";
|
|
15
|
+
import { log as log2 } from "@dxos/log";
|
|
16
|
+
import { useThemeContext as useThemeContext2 } from "@dxos/react-ui";
|
|
17
|
+
import { inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
18
|
|
|
19
19
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
@@ -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,14 +285,15 @@ 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 = (
|
|
295
|
+
this.getCursorFromRange = (state, range) => {
|
|
296
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
291
297
|
const from = cursorConverter3.toCursor(range.from);
|
|
292
298
|
const to = cursorConverter3.toCursor(range.to, -1);
|
|
293
299
|
return [
|
|
@@ -297,7 +303,8 @@ var Cursor = class {
|
|
|
297
303
|
};
|
|
298
304
|
}
|
|
299
305
|
static {
|
|
300
|
-
this.getRangeFromCursor = (
|
|
306
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
307
|
+
const cursorConverter3 = state.facet(_Cursor.converter);
|
|
301
308
|
const parts = cursor.split(":");
|
|
302
309
|
const from = cursorConverter3.fromCursor(parts[0]);
|
|
303
310
|
const to = cursorConverter3.fromCursor(parts[1]);
|
|
@@ -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,41 +348,50 @@ 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";
|
|
389
|
+
import { useEffect } from "react";
|
|
379
390
|
import { Event } from "@dxos/async";
|
|
380
391
|
import { Context } from "@dxos/context";
|
|
392
|
+
import { generateName } from "@dxos/display-name";
|
|
393
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
394
|
+
import { getColorForValue } from "@dxos/react-ui-theme";
|
|
381
395
|
var dummyProvider = {
|
|
382
396
|
remoteStateChange: new Event(),
|
|
383
397
|
open: () => {
|
|
@@ -388,7 +402,7 @@ var dummyProvider = {
|
|
|
388
402
|
},
|
|
389
403
|
getRemoteStates: () => []
|
|
390
404
|
};
|
|
391
|
-
var AwarenessProvider =
|
|
405
|
+
var AwarenessProvider = Facet2.define({
|
|
392
406
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
393
407
|
});
|
|
394
408
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
@@ -401,6 +415,29 @@ var awareness = (provider = dummyProvider) => {
|
|
|
401
415
|
styles
|
|
402
416
|
];
|
|
403
417
|
};
|
|
418
|
+
var useAwareness = ({ awareness: awareness2, peer }) => {
|
|
419
|
+
const { themeMode } = useThemeContext();
|
|
420
|
+
useEffect(() => {
|
|
421
|
+
if (awareness2 && peer) {
|
|
422
|
+
awareness2.setLocalStateField("user", {
|
|
423
|
+
name: peer.name ?? generateName(peer.id),
|
|
424
|
+
color: getColorForValue({
|
|
425
|
+
value: peer.id,
|
|
426
|
+
type: "color"
|
|
427
|
+
}),
|
|
428
|
+
colorLight: getColorForValue({
|
|
429
|
+
value: peer.id,
|
|
430
|
+
themeMode,
|
|
431
|
+
type: "highlight"
|
|
432
|
+
})
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}, [
|
|
436
|
+
awareness2,
|
|
437
|
+
peer,
|
|
438
|
+
themeMode
|
|
439
|
+
]);
|
|
440
|
+
};
|
|
404
441
|
var RemoteSelectionsDecorator = class {
|
|
405
442
|
constructor(view) {
|
|
406
443
|
this.decorations = RangeSet.of([]);
|
|
@@ -549,7 +586,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
549
586
|
return true;
|
|
550
587
|
}
|
|
551
588
|
};
|
|
552
|
-
var styles =
|
|
589
|
+
var styles = EditorView2.baseTheme({
|
|
553
590
|
".cm-collab-selection": {},
|
|
554
591
|
".cm-collab-selectionLine": {
|
|
555
592
|
padding: 0,
|
|
@@ -595,7 +632,7 @@ var styles = EditorView.baseTheme({
|
|
|
595
632
|
zIndex: 101,
|
|
596
633
|
transition: "opacity .3s ease-in-out",
|
|
597
634
|
backgroundColor: "inherit",
|
|
598
|
-
//
|
|
635
|
+
// These should be separate.
|
|
599
636
|
opacity: 0,
|
|
600
637
|
transitionDelay: "0s",
|
|
601
638
|
whiteSpace: "nowrap"
|
|
@@ -608,26 +645,28 @@ var styles = EditorView.baseTheme({
|
|
|
608
645
|
|
|
609
646
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
610
647
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
648
|
+
import { history } from "@codemirror/commands";
|
|
611
649
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
612
650
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
613
|
-
import { drawSelection, EditorView as
|
|
614
|
-
var basicBundle = ({
|
|
615
|
-
|
|
616
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
651
|
+
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
652
|
+
var basicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true }) => [
|
|
653
|
+
lineWrapping ? EditorView3.lineWrapping : [],
|
|
617
654
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
618
655
|
bracketMatching(),
|
|
619
656
|
closeBrackets(),
|
|
620
657
|
drawSelection(),
|
|
621
|
-
|
|
622
|
-
|
|
658
|
+
highlightActiveLine(),
|
|
659
|
+
history(),
|
|
660
|
+
_placeholder ? placeholder(_placeholder) : [],
|
|
661
|
+
// https://github.com/codemirror/theme-one-dark
|
|
623
662
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
624
|
-
]
|
|
663
|
+
];
|
|
625
664
|
|
|
626
665
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
627
|
-
import { EditorView as
|
|
666
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
628
667
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
629
|
-
import { invariant } from "@dxos/invariant";
|
|
630
|
-
var
|
|
668
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
669
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
631
670
|
var defaultOptions = {
|
|
632
671
|
effect: 2,
|
|
633
672
|
maxParticles: 200,
|
|
@@ -672,7 +711,7 @@ var blast = (options = defaultOptions) => {
|
|
|
672
711
|
};
|
|
673
712
|
return [
|
|
674
713
|
// Cursor moved.
|
|
675
|
-
|
|
714
|
+
EditorView4.updateListener.of((update2) => {
|
|
676
715
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
677
716
|
if (blaster) {
|
|
678
717
|
blaster.destroy();
|
|
@@ -753,8 +792,8 @@ var Blaster = class {
|
|
|
753
792
|
return this._node;
|
|
754
793
|
}
|
|
755
794
|
initialize() {
|
|
756
|
-
|
|
757
|
-
F:
|
|
795
|
+
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
796
|
+
F: __dxlog_file2,
|
|
758
797
|
L: 138,
|
|
759
798
|
S: this,
|
|
760
799
|
A: [
|
|
@@ -790,8 +829,8 @@ var Blaster = class {
|
|
|
790
829
|
}
|
|
791
830
|
}
|
|
792
831
|
start() {
|
|
793
|
-
|
|
794
|
-
F:
|
|
832
|
+
invariant2(this._canvas && this._ctx, void 0, {
|
|
833
|
+
F: __dxlog_file2,
|
|
795
834
|
L: 177,
|
|
796
835
|
S: this,
|
|
797
836
|
A: [
|
|
@@ -934,7 +973,7 @@ var random = (min, max) => {
|
|
|
934
973
|
};
|
|
935
974
|
|
|
936
975
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
937
|
-
import { ViewPlugin as ViewPlugin3, EditorView as
|
|
976
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView5, Decoration as Decoration2 } from "@codemirror/view";
|
|
938
977
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
939
978
|
|
|
940
979
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1025,7 +1064,7 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
|
|
|
1025
1064
|
|
|
1026
1065
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1027
1066
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1028
|
-
var styles2 =
|
|
1067
|
+
var styles2 = EditorView5.baseTheme({
|
|
1029
1068
|
"& .cm-codeblock": {
|
|
1030
1069
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1031
1070
|
},
|
|
@@ -1059,20 +1098,18 @@ var getLineRange = (lines, from, to) => {
|
|
|
1059
1098
|
];
|
|
1060
1099
|
};
|
|
1061
1100
|
var code2 = () => {
|
|
1062
|
-
const
|
|
1101
|
+
const buildDecorations5 = (view) => {
|
|
1063
1102
|
const decorations = [];
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}).range(block.from));
|
|
1075
|
-
}
|
|
1103
|
+
const text = view.state.doc.sliceString(0);
|
|
1104
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1105
|
+
const blocks = view.viewportLineBlocks;
|
|
1106
|
+
for (const match of matches) {
|
|
1107
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1108
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1109
|
+
const block = blocks[i];
|
|
1110
|
+
decorations.push(Decoration2.line({
|
|
1111
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1112
|
+
}).range(block.from));
|
|
1076
1113
|
}
|
|
1077
1114
|
}
|
|
1078
1115
|
return Decoration2.set(decorations);
|
|
@@ -1081,7 +1118,7 @@ var code2 = () => {
|
|
|
1081
1118
|
ViewPlugin3.fromClass(class {
|
|
1082
1119
|
constructor(view) {
|
|
1083
1120
|
this.hasFocus = false;
|
|
1084
|
-
this.decorations =
|
|
1121
|
+
this.decorations = buildDecorations5(view);
|
|
1085
1122
|
}
|
|
1086
1123
|
update(update2) {
|
|
1087
1124
|
if (
|
|
@@ -1089,7 +1126,7 @@ var code2 = () => {
|
|
|
1089
1126
|
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1090
1127
|
) {
|
|
1091
1128
|
this.hasFocus = update2.view.hasFocus;
|
|
1092
|
-
this.decorations =
|
|
1129
|
+
this.decorations = buildDecorations5(update2.view);
|
|
1093
1130
|
}
|
|
1094
1131
|
}
|
|
1095
1132
|
}, {
|
|
@@ -1101,36 +1138,55 @@ var code2 = () => {
|
|
|
1101
1138
|
|
|
1102
1139
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1103
1140
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1104
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as
|
|
1141
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
|
|
1105
1142
|
import sortBy from "lodash.sortby";
|
|
1143
|
+
import { useEffect as useEffect2 } from "react";
|
|
1106
1144
|
import { debounce } from "@dxos/async";
|
|
1107
|
-
import { invariant as
|
|
1108
|
-
import { log as log2 } from "@dxos/log";
|
|
1145
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1109
1146
|
import { nonNullable } from "@dxos/util";
|
|
1110
1147
|
|
|
1111
1148
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1112
1149
|
import { log } from "@dxos/log";
|
|
1113
|
-
var
|
|
1150
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1114
1151
|
var callbackWrapper = (fn) => (...args) => {
|
|
1115
1152
|
try {
|
|
1116
1153
|
return fn(...args);
|
|
1117
|
-
} catch (
|
|
1118
|
-
log.catch(
|
|
1119
|
-
F:
|
|
1120
|
-
L:
|
|
1154
|
+
} catch (err) {
|
|
1155
|
+
log.catch(err, void 0, {
|
|
1156
|
+
F: __dxlog_file3,
|
|
1157
|
+
L: 18,
|
|
1121
1158
|
S: void 0,
|
|
1122
1159
|
C: (f, a) => f(...a)
|
|
1123
1160
|
});
|
|
1124
1161
|
}
|
|
1125
1162
|
};
|
|
1163
|
+
var logChanges = (trs) => {
|
|
1164
|
+
const changes = trs.flatMap((tr) => {
|
|
1165
|
+
if (tr.changes.empty) {
|
|
1166
|
+
return void 0;
|
|
1167
|
+
}
|
|
1168
|
+
const changes2 = [];
|
|
1169
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1170
|
+
fromA,
|
|
1171
|
+
toA,
|
|
1172
|
+
fromB,
|
|
1173
|
+
toB,
|
|
1174
|
+
inserted: inserted.toString()
|
|
1175
|
+
})));
|
|
1176
|
+
return changes2;
|
|
1177
|
+
}).filter(Boolean);
|
|
1178
|
+
if (changes.length) {
|
|
1179
|
+
console.log("changes", changes);
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1126
1182
|
|
|
1127
1183
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1128
|
-
var
|
|
1129
|
-
var styles3 =
|
|
1184
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1185
|
+
var styles3 = EditorView6.baseTheme({
|
|
1130
1186
|
"& .cm-comment": {
|
|
1131
1187
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1132
1188
|
},
|
|
1133
|
-
"& .cm-comment-
|
|
1189
|
+
"& .cm-comment-current": {
|
|
1134
1190
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1135
1191
|
}
|
|
1136
1192
|
});
|
|
@@ -1139,52 +1195,62 @@ var marks = {
|
|
|
1139
1195
|
class: "cm-comment"
|
|
1140
1196
|
}),
|
|
1141
1197
|
highlightActive: Decoration3.mark({
|
|
1142
|
-
class: "cm-comment-
|
|
1198
|
+
class: "cm-comment-current"
|
|
1143
1199
|
})
|
|
1144
1200
|
};
|
|
1145
|
-
var setFocus = (view,
|
|
1146
|
-
const
|
|
1147
|
-
if (!
|
|
1201
|
+
var setFocus = (view, id, center = true) => {
|
|
1202
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1203
|
+
if (!comment?.comment.cursor) {
|
|
1148
1204
|
return;
|
|
1149
1205
|
}
|
|
1150
|
-
view.
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1206
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1207
|
+
if (range) {
|
|
1208
|
+
view.dispatch({
|
|
1209
|
+
selection: {
|
|
1210
|
+
anchor: range.from
|
|
1211
|
+
},
|
|
1212
|
+
effects: [
|
|
1213
|
+
//
|
|
1214
|
+
EditorView6.scrollIntoView(range.from, center ? {
|
|
1215
|
+
y: "center"
|
|
1216
|
+
} : void 0),
|
|
1217
|
+
setSelection.of({
|
|
1218
|
+
current: id
|
|
1219
|
+
})
|
|
1220
|
+
]
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1159
1223
|
};
|
|
1160
|
-
var
|
|
1224
|
+
var setComments = StateEffect2.define();
|
|
1161
1225
|
var setSelection = StateEffect2.define();
|
|
1162
1226
|
var setCommentState = StateEffect2.define();
|
|
1163
|
-
var
|
|
1227
|
+
var commentsState = StateField2.define({
|
|
1164
1228
|
create: () => ({
|
|
1165
|
-
|
|
1229
|
+
comments: [],
|
|
1230
|
+
selection: {}
|
|
1166
1231
|
}),
|
|
1167
1232
|
update: (value, tr) => {
|
|
1168
|
-
const cursorConverter3 = tr.state.facet(Cursor.converter);
|
|
1169
1233
|
for (const effect of tr.effects) {
|
|
1170
1234
|
if (effect.is(setSelection)) {
|
|
1171
1235
|
return {
|
|
1172
1236
|
...value,
|
|
1173
|
-
|
|
1237
|
+
selection: effect.value
|
|
1174
1238
|
};
|
|
1175
1239
|
}
|
|
1176
|
-
if (effect.is(
|
|
1177
|
-
const
|
|
1178
|
-
|
|
1179
|
-
|
|
1240
|
+
if (effect.is(setComments)) {
|
|
1241
|
+
const comments2 = effect.value.map((comment) => {
|
|
1242
|
+
if (!comment.cursor) {
|
|
1243
|
+
return void 0;
|
|
1244
|
+
}
|
|
1245
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1180
1246
|
return range && {
|
|
1181
|
-
|
|
1182
|
-
|
|
1247
|
+
comment,
|
|
1248
|
+
range
|
|
1183
1249
|
};
|
|
1184
1250
|
}).filter(nonNullable);
|
|
1185
1251
|
return {
|
|
1186
1252
|
...value,
|
|
1187
|
-
|
|
1253
|
+
comments: comments2
|
|
1188
1254
|
};
|
|
1189
1255
|
}
|
|
1190
1256
|
if (effect.is(setCommentState)) {
|
|
@@ -1194,78 +1260,125 @@ var commentsStateField = StateField2.define({
|
|
|
1194
1260
|
return value;
|
|
1195
1261
|
}
|
|
1196
1262
|
});
|
|
1197
|
-
var highlightDecorations =
|
|
1198
|
-
|
|
1263
|
+
var highlightDecorations = EditorView6.decorations.compute([
|
|
1264
|
+
commentsState
|
|
1199
1265
|
], (state) => {
|
|
1200
|
-
const {
|
|
1201
|
-
const decorations = sortBy(
|
|
1202
|
-
|
|
1266
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1267
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1268
|
+
const range = comment.range;
|
|
1269
|
+
if (!range || range.from === range.to) {
|
|
1270
|
+
console.warn("Invalid range:", range);
|
|
1203
1271
|
return void 0;
|
|
1204
1272
|
}
|
|
1205
|
-
|
|
1206
|
-
from: selection.from,
|
|
1207
|
-
to: selection.to
|
|
1208
|
-
};
|
|
1209
|
-
if (selection.id === active) {
|
|
1273
|
+
if (comment.comment.id === current) {
|
|
1210
1274
|
return marks.highlightActive.range(range.from, range.to);
|
|
1211
1275
|
} else {
|
|
1212
1276
|
return marks.highlight.range(range.from, range.to);
|
|
1213
1277
|
}
|
|
1214
|
-
}).filter(nonNullable)
|
|
1278
|
+
}).filter(nonNullable);
|
|
1215
1279
|
return Decoration3.set(decorations);
|
|
1216
1280
|
});
|
|
1281
|
+
var trackPastedComments = (onUpdate) => {
|
|
1282
|
+
let tracked = null;
|
|
1283
|
+
const handleTrack = (event, view) => {
|
|
1284
|
+
const comments2 = view.state.field(commentsState);
|
|
1285
|
+
const { main } = view.state.selection;
|
|
1286
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1287
|
+
if (!selectedRanges.length) {
|
|
1288
|
+
tracked = null;
|
|
1289
|
+
} else {
|
|
1290
|
+
tracked = {
|
|
1291
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1292
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1293
|
+
id: comment.id,
|
|
1294
|
+
from: range.from - main.from,
|
|
1295
|
+
to: range.to - main.from
|
|
1296
|
+
}))
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
return [
|
|
1301
|
+
EditorView6.domEventHandlers({
|
|
1302
|
+
cut: handleTrack,
|
|
1303
|
+
copy: handleTrack
|
|
1304
|
+
}),
|
|
1305
|
+
// Handle paste.
|
|
1306
|
+
EditorView6.updateListener.of(({ view, state, transactions }) => {
|
|
1307
|
+
if (tracked) {
|
|
1308
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1309
|
+
if (paste) {
|
|
1310
|
+
let found = -1;
|
|
1311
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1312
|
+
if (text.eq(tracked.text)) {
|
|
1313
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1314
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1315
|
+
}
|
|
1316
|
+
found = fromB;
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
if (found > -1) {
|
|
1320
|
+
for (const moved of tracked.comments) {
|
|
1321
|
+
const range = {
|
|
1322
|
+
from: found + moved.from,
|
|
1323
|
+
to: found + moved.to
|
|
1324
|
+
};
|
|
1325
|
+
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1326
|
+
onUpdate(moved.id, cursor);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
tracked = null;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
})
|
|
1333
|
+
];
|
|
1334
|
+
};
|
|
1217
1335
|
var comments = (options = {}) => {
|
|
1218
1336
|
const { key: shortcut = "meta-'" } = options;
|
|
1219
1337
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1220
1338
|
const createCommentThread = (view) => {
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
L: 177,
|
|
1339
|
+
invariant3(options.onCreate, void 0, {
|
|
1340
|
+
F: __dxlog_file4,
|
|
1341
|
+
L: 259,
|
|
1225
1342
|
S: void 0,
|
|
1226
1343
|
A: [
|
|
1227
1344
|
"options.onCreate",
|
|
1228
1345
|
""
|
|
1229
1346
|
]
|
|
1230
1347
|
});
|
|
1231
|
-
const {
|
|
1348
|
+
const { from, to } = view.state.selection.main;
|
|
1232
1349
|
if (from === to) {
|
|
1233
1350
|
return false;
|
|
1234
1351
|
}
|
|
1235
|
-
|
|
1352
|
+
if (to === view.state.doc.length) {
|
|
1353
|
+
view.dispatch({
|
|
1354
|
+
changes: {
|
|
1355
|
+
from: to,
|
|
1356
|
+
insert: "\n"
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1236
1361
|
from,
|
|
1237
1362
|
to
|
|
1238
1363
|
});
|
|
1239
1364
|
if (cursor) {
|
|
1240
|
-
const id =
|
|
1365
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1241
1366
|
if (id) {
|
|
1242
1367
|
view.dispatch({
|
|
1243
1368
|
effects: setSelection.of({
|
|
1244
|
-
|
|
1369
|
+
current: id
|
|
1245
1370
|
}),
|
|
1246
1371
|
selection: {
|
|
1247
1372
|
anchor: from
|
|
1248
1373
|
}
|
|
1249
1374
|
});
|
|
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
1375
|
return true;
|
|
1263
1376
|
}
|
|
1264
1377
|
}
|
|
1265
1378
|
return false;
|
|
1266
1379
|
};
|
|
1267
1380
|
return [
|
|
1268
|
-
|
|
1381
|
+
commentsState,
|
|
1269
1382
|
highlightDecorations,
|
|
1270
1383
|
styles3,
|
|
1271
1384
|
//
|
|
@@ -1290,7 +1403,7 @@ var comments = (options = {}) => {
|
|
|
1290
1403
|
above: true,
|
|
1291
1404
|
create: () => {
|
|
1292
1405
|
const el = document.createElement("div");
|
|
1293
|
-
options.onHover
|
|
1406
|
+
options.onHover(el, shortcut);
|
|
1294
1407
|
return {
|
|
1295
1408
|
dom: el,
|
|
1296
1409
|
offset: {
|
|
@@ -1303,139 +1416,154 @@ var comments = (options = {}) => {
|
|
|
1303
1416
|
}
|
|
1304
1417
|
return null;
|
|
1305
1418
|
}, {
|
|
1306
|
-
|
|
1419
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1420
|
+
// hideOnChange: true,
|
|
1307
1421
|
hoverTime: 1e3
|
|
1308
1422
|
}) : [],
|
|
1309
1423
|
//
|
|
1310
|
-
//
|
|
1311
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1424
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1312
1425
|
//
|
|
1313
|
-
|
|
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
|
-
}
|
|
1426
|
+
EditorView6.updateListener.of(({ view, state, changes }) => {
|
|
1427
|
+
let mod = false;
|
|
1428
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1429
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1430
|
+
comments2.forEach(({ comment, range }) => {
|
|
1431
|
+
if (from2 === to2) {
|
|
1432
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1433
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1434
|
+
options.onDelete?.(comment.id);
|
|
1332
1435
|
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
}
|
|
1436
|
+
}
|
|
1437
|
+
if (from <= range.to) {
|
|
1438
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1439
|
+
Object.assign(range, newRange);
|
|
1440
|
+
mod = true;
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
});
|
|
1444
|
+
if (mod) {
|
|
1445
|
+
view.dispatch({
|
|
1446
|
+
effects: setCommentState.of({
|
|
1447
|
+
comments: comments2,
|
|
1448
|
+
...value
|
|
1449
|
+
})
|
|
1339
1450
|
});
|
|
1340
|
-
if (mod) {
|
|
1341
|
-
view.dispatch({
|
|
1342
|
-
effects: setCommentState.of({
|
|
1343
|
-
active,
|
|
1344
|
-
ranges
|
|
1345
|
-
})
|
|
1346
|
-
});
|
|
1347
|
-
}
|
|
1348
1451
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1452
|
+
}),
|
|
1453
|
+
//
|
|
1454
|
+
// Track selection/proximity.
|
|
1455
|
+
//
|
|
1456
|
+
EditorView6.updateListener.of(({ view, state }) => {
|
|
1457
|
+
let min = Infinity;
|
|
1458
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1459
|
+
const { head } = state.selection.main;
|
|
1460
|
+
const selection = {};
|
|
1461
|
+
comments2.forEach(({ comment, range }) => {
|
|
1462
|
+
if (head >= range.from && head <= range.to) {
|
|
1463
|
+
selection.current = comment.id;
|
|
1464
|
+
selection.closest = void 0;
|
|
1465
|
+
}
|
|
1466
|
+
if (!selection.current) {
|
|
1467
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1362
1468
|
if (d < min) {
|
|
1363
|
-
|
|
1469
|
+
selection.closest = comment.id;
|
|
1364
1470
|
min = d;
|
|
1365
1471
|
}
|
|
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
1472
|
}
|
|
1473
|
+
});
|
|
1474
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1475
|
+
view.dispatch({
|
|
1476
|
+
effects: setSelection.of(selection)
|
|
1477
|
+
});
|
|
1478
|
+
handleSelect({
|
|
1479
|
+
selection,
|
|
1480
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1481
|
+
comment,
|
|
1482
|
+
range,
|
|
1483
|
+
location: view.coordsAtPos(range.from)
|
|
1484
|
+
}))
|
|
1485
|
+
});
|
|
1379
1486
|
}
|
|
1380
|
-
})
|
|
1487
|
+
}),
|
|
1488
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1381
1489
|
];
|
|
1382
1490
|
};
|
|
1491
|
+
var useComments = (view, comments2 = []) => {
|
|
1492
|
+
useEffect2(() => {
|
|
1493
|
+
if (view) {
|
|
1494
|
+
view.dispatch({
|
|
1495
|
+
effects: setComments.of(comments2)
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
}, [
|
|
1499
|
+
view,
|
|
1500
|
+
comments2
|
|
1501
|
+
]);
|
|
1502
|
+
};
|
|
1383
1503
|
|
|
1384
1504
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1385
|
-
import {
|
|
1386
|
-
|
|
1505
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1506
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1507
|
+
import { Decoration as Decoration4, EditorView as EditorView7, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1508
|
+
var styles4 = EditorView7.baseTheme({
|
|
1387
1509
|
"& .cm-hr": {
|
|
1388
|
-
// TODO(burdon): ???
|
|
1389
1510
|
// Note that block-level decorations should not have vertical margins,
|
|
1390
|
-
|
|
1511
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1391
1512
|
}
|
|
1392
1513
|
});
|
|
1393
1514
|
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1394
|
-
|
|
1395
|
-
super();
|
|
1396
|
-
this._pos = _pos;
|
|
1397
|
-
}
|
|
1398
|
-
eq(other) {
|
|
1399
|
-
return this._pos === other._pos;
|
|
1400
|
-
}
|
|
1401
|
-
toDOM(view) {
|
|
1515
|
+
toDOM() {
|
|
1402
1516
|
const el = document.createElement("div");
|
|
1403
1517
|
el.className = "cm-hr";
|
|
1404
1518
|
return el;
|
|
1405
1519
|
}
|
|
1406
1520
|
};
|
|
1407
|
-
var
|
|
1408
|
-
|
|
1409
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1410
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1411
|
-
})
|
|
1521
|
+
var decoration = Decoration4.replace({
|
|
1522
|
+
widget: new HorizontalRuleWidget()
|
|
1412
1523
|
});
|
|
1413
|
-
var
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1524
|
+
var buildDecorations = (view) => {
|
|
1525
|
+
const builder = new RangeSetBuilder();
|
|
1526
|
+
const { state } = view;
|
|
1527
|
+
const cursor = state.selection.main.head;
|
|
1528
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1529
|
+
syntaxTree(state).iterate({
|
|
1530
|
+
enter: (node) => {
|
|
1531
|
+
if (node.name === "HorizontalRule") {
|
|
1532
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1533
|
+
builder.add(node.from, node.to, decoration);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
},
|
|
1537
|
+
from,
|
|
1538
|
+
to
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
return builder.finish();
|
|
1542
|
+
};
|
|
1543
|
+
var hr = () => {
|
|
1544
|
+
return [
|
|
1545
|
+
styles4,
|
|
1546
|
+
ViewPlugin4.fromClass(class {
|
|
1547
|
+
constructor(view) {
|
|
1548
|
+
this.decorations = buildDecorations(view);
|
|
1549
|
+
}
|
|
1550
|
+
update(update2) {
|
|
1551
|
+
this.decorations = buildDecorations(update2.view);
|
|
1552
|
+
}
|
|
1553
|
+
}, {
|
|
1554
|
+
decorations: (v) => v.decorations
|
|
1427
1555
|
})
|
|
1428
|
-
|
|
1429
|
-
|
|
1556
|
+
];
|
|
1557
|
+
};
|
|
1430
1558
|
|
|
1431
1559
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1432
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1560
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1433
1561
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
1434
|
-
import { Decoration as Decoration5, EditorView as
|
|
1562
|
+
import { Decoration as Decoration5, EditorView as EditorView8, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1435
1563
|
var image = (options = {}) => {
|
|
1436
1564
|
return StateField3.define({
|
|
1437
1565
|
create: (state) => {
|
|
1438
|
-
return Decoration5.set(
|
|
1566
|
+
return Decoration5.set(buildDecorations2(0, state.doc.length, state));
|
|
1439
1567
|
},
|
|
1440
1568
|
update: (value, tr) => {
|
|
1441
1569
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -1455,16 +1583,16 @@ var image = (options = {}) => {
|
|
|
1455
1583
|
filterFrom: from,
|
|
1456
1584
|
filterTo: to,
|
|
1457
1585
|
filter: () => false,
|
|
1458
|
-
add:
|
|
1586
|
+
add: buildDecorations2(from, to, tr.state)
|
|
1459
1587
|
});
|
|
1460
1588
|
},
|
|
1461
|
-
provide: (field) =>
|
|
1589
|
+
provide: (field) => EditorView8.decorations.from(field)
|
|
1462
1590
|
});
|
|
1463
1591
|
};
|
|
1464
|
-
var
|
|
1592
|
+
var buildDecorations2 = (from, to, state) => {
|
|
1465
1593
|
const decorations = [];
|
|
1466
1594
|
const cursor = state.selection.main.head;
|
|
1467
|
-
|
|
1595
|
+
syntaxTree2(state).iterate({
|
|
1468
1596
|
enter: (node) => {
|
|
1469
1597
|
if (node.name === "Image") {
|
|
1470
1598
|
const urlNode = node.node.getChild("URL");
|
|
@@ -1501,19 +1629,19 @@ var ImageWidget = class extends WidgetType3 {
|
|
|
1501
1629
|
};
|
|
1502
1630
|
|
|
1503
1631
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1504
|
-
import { syntaxTree as
|
|
1505
|
-
import { RangeSetBuilder } from "@codemirror/state";
|
|
1506
|
-
import {
|
|
1632
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1633
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1634
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1507
1635
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1508
1636
|
var link = (options = {}) => {
|
|
1509
1637
|
const extensions = [
|
|
1510
1638
|
ViewPlugin5.fromClass(class {
|
|
1511
1639
|
constructor(view) {
|
|
1512
|
-
this.decorations =
|
|
1640
|
+
this.decorations = buildDecorations3(view, options);
|
|
1513
1641
|
}
|
|
1514
1642
|
update(update2) {
|
|
1515
1643
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1516
|
-
this.decorations =
|
|
1644
|
+
this.decorations = buildDecorations3(update2.view, options);
|
|
1517
1645
|
}
|
|
1518
1646
|
}
|
|
1519
1647
|
}, {
|
|
@@ -1526,7 +1654,7 @@ var link = (options = {}) => {
|
|
|
1526
1654
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1527
1655
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1528
1656
|
hoverTooltip2((view, pos, side) => {
|
|
1529
|
-
const syntax =
|
|
1657
|
+
const syntax = syntaxTree3(view.state).resolveInner(pos, side);
|
|
1530
1658
|
let link2 = null;
|
|
1531
1659
|
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1532
1660
|
link2 = node.name === "Link" ? node : null;
|
|
@@ -1602,12 +1730,12 @@ var LinkText = class extends WidgetType4 {
|
|
|
1602
1730
|
return link2;
|
|
1603
1731
|
}
|
|
1604
1732
|
};
|
|
1605
|
-
var
|
|
1606
|
-
const builder = new
|
|
1733
|
+
var buildDecorations3 = (view, options) => {
|
|
1734
|
+
const builder = new RangeSetBuilder2();
|
|
1607
1735
|
const { state } = view;
|
|
1608
1736
|
const cursor = state.selection.main.head;
|
|
1609
1737
|
for (const { from, to } of view.visibleRanges) {
|
|
1610
|
-
|
|
1738
|
+
syntaxTree3(state).iterate({
|
|
1611
1739
|
enter: (node) => {
|
|
1612
1740
|
if (node.name === "Link") {
|
|
1613
1741
|
const marks2 = node.node.getChildren("LinkMark");
|
|
@@ -1638,14 +1766,14 @@ var buildDecorations2 = (view, options) => {
|
|
|
1638
1766
|
};
|
|
1639
1767
|
|
|
1640
1768
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1641
|
-
import { EditorView as
|
|
1769
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1642
1770
|
var listener = ({ onFocus, onChange }) => {
|
|
1643
1771
|
const extensions = [];
|
|
1644
|
-
onFocus && extensions.push(
|
|
1772
|
+
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1645
1773
|
onFocus(focused);
|
|
1646
1774
|
return null;
|
|
1647
1775
|
}));
|
|
1648
|
-
onChange && extensions.push(
|
|
1776
|
+
onChange && extensions.push(EditorView9.updateListener.of((update2) => {
|
|
1649
1777
|
onChange(update2.state.doc.toString());
|
|
1650
1778
|
}));
|
|
1651
1779
|
return extensions;
|
|
@@ -1653,14 +1781,14 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1653
1781
|
|
|
1654
1782
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1655
1783
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1656
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1784
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1657
1785
|
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1658
1786
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1659
1787
|
import { languages } from "@codemirror/language-data";
|
|
1660
1788
|
import { searchKeymap } from "@codemirror/search";
|
|
1661
1789
|
import { EditorState } from "@codemirror/state";
|
|
1662
1790
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1663
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1791
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1664
1792
|
|
|
1665
1793
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1666
1794
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1855,17 +1983,17 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1855
1983
|
return [
|
|
1856
1984
|
EditorState.allowMultipleSelections.of(true),
|
|
1857
1985
|
EditorState.tabSize.of(2),
|
|
1858
|
-
|
|
1859
|
-
|
|
1986
|
+
EditorView10.lineWrapping,
|
|
1987
|
+
// https://github.com/codemirror/basic-setup
|
|
1860
1988
|
bracketMatching2(),
|
|
1861
1989
|
closeBrackets2(),
|
|
1862
1990
|
crosshairCursor(),
|
|
1863
1991
|
dropCursor(),
|
|
1864
1992
|
drawSelection2(),
|
|
1865
|
-
|
|
1866
|
-
|
|
1993
|
+
highlightActiveLine2(),
|
|
1994
|
+
history2(),
|
|
1867
1995
|
indentOnInput(),
|
|
1868
|
-
_placeholder
|
|
1996
|
+
_placeholder ? placeholder2(_placeholder) : [],
|
|
1869
1997
|
// Main extension.
|
|
1870
1998
|
// https://github.com/codemirror/lang-markdown
|
|
1871
1999
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1887,34 +2015,40 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1887
2015
|
// https://github.com/codemirror/theme-one-dark
|
|
1888
2016
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1889
2017
|
// Custom styles.
|
|
1890
|
-
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
2018
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly)),
|
|
2019
|
+
keymap4.of([
|
|
2020
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2021
|
+
indentWithTab,
|
|
2022
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2023
|
+
...closeBracketsKeymap,
|
|
2024
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2025
|
+
...historyKeymap,
|
|
2026
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2027
|
+
...searchKeymap,
|
|
2028
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2029
|
+
...standardKeymap
|
|
2030
|
+
])
|
|
2031
|
+
];
|
|
2032
|
+
};
|
|
1905
2033
|
|
|
1906
2034
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1907
2035
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1908
2036
|
var mention = ({ onSearch }) => {
|
|
1909
2037
|
return autocompletion2({
|
|
2038
|
+
// TODO(burdon): Not working.
|
|
2039
|
+
activateOnTyping: true,
|
|
2040
|
+
// activateOnTypingDelay: 100,
|
|
2041
|
+
// selectOnOpen: true,
|
|
1910
2042
|
closeOnBlur: false,
|
|
2043
|
+
// defaultKeymap: false,
|
|
2044
|
+
icons: false,
|
|
1911
2045
|
override: [
|
|
1912
2046
|
(context) => {
|
|
2047
|
+
console.log(context);
|
|
1913
2048
|
const match = context.matchBefore(/@(\w+)?/);
|
|
1914
2049
|
if (!match || match.from === match.to && !context.explicit) {
|
|
1915
2050
|
return null;
|
|
1916
2051
|
}
|
|
1917
|
-
console.log(match);
|
|
1918
2052
|
return {
|
|
1919
2053
|
from: match.from,
|
|
1920
2054
|
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
@@ -1926,19 +2060,24 @@ var mention = ({ onSearch }) => {
|
|
|
1926
2060
|
});
|
|
1927
2061
|
};
|
|
1928
2062
|
|
|
2063
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2064
|
+
var outliner = (options = {}) => {
|
|
2065
|
+
return [];
|
|
2066
|
+
};
|
|
2067
|
+
|
|
1929
2068
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1930
|
-
import { syntaxTree as
|
|
1931
|
-
import { RangeSetBuilder as
|
|
1932
|
-
import { Decoration as Decoration7, EditorView as
|
|
2069
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2070
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField4 } from "@codemirror/state";
|
|
2071
|
+
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1933
2072
|
var table = (options = {}) => {
|
|
1934
2073
|
return StateField4.define({
|
|
1935
2074
|
create: (state) => update(state, options),
|
|
1936
2075
|
update: (_, tr) => update(tr.state, options),
|
|
1937
|
-
provide: (field) =>
|
|
2076
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
1938
2077
|
});
|
|
1939
2078
|
};
|
|
1940
2079
|
var update = (state, options) => {
|
|
1941
|
-
const builder = new
|
|
2080
|
+
const builder = new RangeSetBuilder3();
|
|
1942
2081
|
const cursor = state.selection.main.head;
|
|
1943
2082
|
const tables = [];
|
|
1944
2083
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -1946,7 +2085,7 @@ var update = (state, options) => {
|
|
|
1946
2085
|
const table2 = getTable();
|
|
1947
2086
|
return table2.rows?.[table2.rows.length - 1];
|
|
1948
2087
|
};
|
|
1949
|
-
|
|
2088
|
+
syntaxTree4(state).iterate({
|
|
1950
2089
|
enter: (node) => {
|
|
1951
2090
|
switch (node.name) {
|
|
1952
2091
|
case "Table": {
|
|
@@ -2025,85 +2164,98 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2025
2164
|
};
|
|
2026
2165
|
|
|
2027
2166
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2028
|
-
import {
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2167
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2168
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2169
|
+
import { EditorView as EditorView12, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2170
|
+
var styles5 = EditorView12.baseTheme({
|
|
2171
|
+
"& .cm-task": {
|
|
2172
|
+
color: getToken("extend.colors.blue.500")
|
|
2173
|
+
},
|
|
2174
|
+
"& .cm-task-checkbox": {
|
|
2175
|
+
marginLeft: "4px",
|
|
2176
|
+
marginRight: "4px"
|
|
2033
2177
|
}
|
|
2034
2178
|
});
|
|
2035
2179
|
var CheckboxWidget = class extends WidgetType6 {
|
|
2036
|
-
constructor(_checked
|
|
2180
|
+
constructor(_checked) {
|
|
2037
2181
|
super();
|
|
2038
2182
|
this._checked = _checked;
|
|
2039
|
-
this._indent = _indent;
|
|
2040
|
-
this._onCheck = _onCheck;
|
|
2041
2183
|
}
|
|
2042
2184
|
eq(other) {
|
|
2043
|
-
return this._checked === other._checked
|
|
2185
|
+
return this._checked === other._checked;
|
|
2044
2186
|
}
|
|
2045
2187
|
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"));
|
|
2188
|
+
const input = document.createElement("input");
|
|
2189
|
+
input.className = "cm-task-checkbox";
|
|
2051
2190
|
input.type = "checkbox";
|
|
2052
2191
|
input.checked = this._checked;
|
|
2053
|
-
if (
|
|
2192
|
+
if (view.state.readOnly) {
|
|
2054
2193
|
input.setAttribute("disabled", "true");
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2194
|
+
} else {
|
|
2195
|
+
input.onmousedown = (event) => {
|
|
2196
|
+
const pos = view.posAtDOM(input);
|
|
2197
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2198
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2199
|
+
view.dispatch({
|
|
2200
|
+
changes: {
|
|
2201
|
+
from: pos + 1,
|
|
2202
|
+
to: pos + 2,
|
|
2203
|
+
insert: this._checked ? " " : "x"
|
|
2204
|
+
}
|
|
2205
|
+
});
|
|
2206
|
+
event.preventDefault();
|
|
2207
|
+
}
|
|
2060
2208
|
};
|
|
2061
2209
|
}
|
|
2062
|
-
return
|
|
2210
|
+
return input;
|
|
2063
2211
|
}
|
|
2064
2212
|
ignoreEvent() {
|
|
2065
2213
|
return false;
|
|
2066
2214
|
}
|
|
2067
2215
|
};
|
|
2216
|
+
var checkedDecoration = Decoration8.replace({
|
|
2217
|
+
widget: new CheckboxWidget(true)
|
|
2218
|
+
});
|
|
2219
|
+
var uncheckedDecoration = Decoration8.replace({
|
|
2220
|
+
widget: new CheckboxWidget(false)
|
|
2221
|
+
});
|
|
2222
|
+
var buildDecorations4 = (view) => {
|
|
2223
|
+
const builder = new RangeSetBuilder4();
|
|
2224
|
+
const { state } = view;
|
|
2225
|
+
const cursor = state.selection.main.head;
|
|
2226
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2227
|
+
syntaxTree5(state).iterate({
|
|
2228
|
+
enter: (node) => {
|
|
2229
|
+
if (node.name === "TaskMarker") {
|
|
2230
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2231
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2232
|
+
builder.add(node.from - 2, node.from - 1, Decoration8.mark({
|
|
2233
|
+
class: "cm-task"
|
|
2234
|
+
}));
|
|
2235
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
},
|
|
2239
|
+
from,
|
|
2240
|
+
to
|
|
2241
|
+
});
|
|
2242
|
+
}
|
|
2243
|
+
return builder.finish();
|
|
2244
|
+
};
|
|
2068
2245
|
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
2246
|
return [
|
|
2106
|
-
|
|
2247
|
+
ViewPlugin6.fromClass(class {
|
|
2248
|
+
constructor(view) {
|
|
2249
|
+
this.decorations = buildDecorations4(view);
|
|
2250
|
+
}
|
|
2251
|
+
update(update2) {
|
|
2252
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2253
|
+
this.decorations = buildDecorations4(update2.view);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
}, {
|
|
2257
|
+
decorations: (v) => v.decorations
|
|
2258
|
+
}),
|
|
2107
2259
|
styles5
|
|
2108
2260
|
];
|
|
2109
2261
|
};
|
|
@@ -2423,90 +2575,83 @@ var codeTheme = {
|
|
|
2423
2575
|
};
|
|
2424
2576
|
|
|
2425
2577
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2578
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2426
2579
|
var EditorModes = [
|
|
2427
2580
|
"default",
|
|
2428
2581
|
"vim"
|
|
2429
2582
|
];
|
|
2430
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model,
|
|
2583
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2431
2584
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2432
2585
|
tabBehavior: "limited"
|
|
2433
2586
|
});
|
|
2434
|
-
const { themeMode } =
|
|
2587
|
+
const { themeMode } = useThemeContext2();
|
|
2435
2588
|
const rootRef = useRef(null);
|
|
2436
2589
|
const [view, setView] = useState(null);
|
|
2437
2590
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2438
2591
|
view
|
|
2439
2592
|
]);
|
|
2440
|
-
|
|
2441
|
-
if (
|
|
2442
|
-
view
|
|
2593
|
+
useEffect3(() => {
|
|
2594
|
+
if (autoFocus) {
|
|
2595
|
+
view?.focus();
|
|
2443
2596
|
}
|
|
2444
2597
|
}, [
|
|
2445
2598
|
view,
|
|
2446
|
-
|
|
2447
|
-
]);
|
|
2448
|
-
const { awareness: awareness2, peer } = model;
|
|
2449
|
-
useEffect(() => {
|
|
2450
|
-
if (awareness2 && peer) {
|
|
2451
|
-
awareness2.setLocalStateField("user", {
|
|
2452
|
-
name: peer.name ?? generateName(peer.id),
|
|
2453
|
-
color: getColorForValue({
|
|
2454
|
-
value: peer.id,
|
|
2455
|
-
type: "color"
|
|
2456
|
-
}),
|
|
2457
|
-
colorLight: getColorForValue({
|
|
2458
|
-
value: peer.id,
|
|
2459
|
-
themeMode,
|
|
2460
|
-
type: "highlight"
|
|
2461
|
-
})
|
|
2462
|
-
});
|
|
2463
|
-
}
|
|
2464
|
-
}, [
|
|
2465
|
-
awareness2,
|
|
2466
|
-
peer,
|
|
2467
|
-
themeMode
|
|
2599
|
+
autoFocus
|
|
2468
2600
|
]);
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
view.dispatch({
|
|
2472
|
-
effects: setCommentRange.of({
|
|
2473
|
-
model,
|
|
2474
|
-
comments: comments2
|
|
2475
|
-
})
|
|
2476
|
-
});
|
|
2477
|
-
}
|
|
2478
|
-
}, [
|
|
2479
|
-
view,
|
|
2480
|
-
comments2
|
|
2481
|
-
]);
|
|
2482
|
-
useEffect(() => {
|
|
2601
|
+
useAwareness(model);
|
|
2602
|
+
useEffect3(() => {
|
|
2483
2603
|
if (!model || !rootRef.current) {
|
|
2484
2604
|
return;
|
|
2485
2605
|
}
|
|
2486
2606
|
const state = EditorState2.create({
|
|
2487
2607
|
doc: model.text(),
|
|
2488
|
-
// TODO(burdon): Composer should store and set selection when switching documents.
|
|
2489
2608
|
selection,
|
|
2490
2609
|
extensions: [
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2610
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2611
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2612
|
+
log2.catch(err, void 0, {
|
|
2613
|
+
F: __dxlog_file5,
|
|
2614
|
+
L: 126,
|
|
2615
|
+
S: void 0,
|
|
2616
|
+
C: (f, a) => f(...a)
|
|
2617
|
+
});
|
|
2618
|
+
}),
|
|
2494
2619
|
// Theme.
|
|
2495
|
-
// TODO(burdon): Make
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2620
|
+
// TODO(burdon): Make configurable.
|
|
2621
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2622
|
+
EditorView13.theme(theme ?? {}),
|
|
2623
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2624
|
+
EditorView13.editorAttributes.of({
|
|
2625
|
+
class: slots.editor?.className ?? ""
|
|
2626
|
+
}),
|
|
2627
|
+
EditorView13.contentAttributes.of({
|
|
2628
|
+
class: slots.content?.className ?? ""
|
|
2629
|
+
}),
|
|
2630
|
+
// State.
|
|
2631
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2499
2632
|
// Storage and replication.
|
|
2633
|
+
// NOTE: This must come before user extensions.
|
|
2500
2634
|
model.extension,
|
|
2635
|
+
// TODO(burdon): Factor out (requires special handling for Escape/focus).
|
|
2636
|
+
editorMode === "vim" && vim(),
|
|
2501
2637
|
// Custom.
|
|
2502
2638
|
...extensions
|
|
2503
2639
|
].filter(Boolean)
|
|
2504
2640
|
});
|
|
2505
|
-
|
|
2506
|
-
|
|
2641
|
+
const newView = new EditorView13({
|
|
2642
|
+
state,
|
|
2507
2643
|
parent: rootRef.current,
|
|
2508
|
-
|
|
2644
|
+
scrollTo,
|
|
2645
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2646
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2647
|
+
dispatchTransactions: (trs, view2) => {
|
|
2648
|
+
if (debug) {
|
|
2649
|
+
logChanges(trs);
|
|
2650
|
+
}
|
|
2651
|
+
view2.update(trs);
|
|
2652
|
+
}
|
|
2509
2653
|
});
|
|
2654
|
+
view?.destroy();
|
|
2510
2655
|
setView(newView);
|
|
2511
2656
|
return () => {
|
|
2512
2657
|
newView?.destroy();
|
|
@@ -2522,8 +2667,14 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, read
|
|
|
2522
2667
|
const handleKeyUp = useCallback((event) => {
|
|
2523
2668
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2524
2669
|
switch (key) {
|
|
2670
|
+
case "Enter": {
|
|
2671
|
+
view?.focus();
|
|
2672
|
+
break;
|
|
2673
|
+
}
|
|
2525
2674
|
case "Escape": {
|
|
2526
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2675
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2676
|
+
rootRef.current?.focus();
|
|
2677
|
+
}
|
|
2527
2678
|
break;
|
|
2528
2679
|
}
|
|
2529
2680
|
}
|
|
@@ -2534,24 +2685,24 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, focus, selection, read
|
|
|
2534
2685
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2535
2686
|
key: model.id,
|
|
2536
2687
|
role: "none",
|
|
2537
|
-
ref: rootRef,
|
|
2538
2688
|
tabIndex: 0,
|
|
2539
2689
|
onKeyUp: handleKeyUp,
|
|
2540
2690
|
...slots.root,
|
|
2541
|
-
...editorMode !== "vim" && tabsterDOMAttribute
|
|
2691
|
+
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2692
|
+
ref: rootRef
|
|
2542
2693
|
});
|
|
2543
2694
|
});
|
|
2544
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2545
|
-
const { themeMode } =
|
|
2695
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2696
|
+
const { themeMode } = useThemeContext2();
|
|
2546
2697
|
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2547
2698
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2548
2699
|
ref: forwardedRef,
|
|
2549
2700
|
readonly,
|
|
2550
2701
|
extensions: [
|
|
2551
2702
|
basicBundle({
|
|
2552
|
-
readonly,
|
|
2553
2703
|
themeMode,
|
|
2554
|
-
placeholder: placeholder3
|
|
2704
|
+
placeholder: placeholder3,
|
|
2705
|
+
lineWrapping
|
|
2555
2706
|
}),
|
|
2556
2707
|
...extensions
|
|
2557
2708
|
],
|
|
@@ -2560,16 +2711,16 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2560
2711
|
...props
|
|
2561
2712
|
});
|
|
2562
2713
|
});
|
|
2563
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2564
|
-
const { themeMode } =
|
|
2714
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2715
|
+
const { themeMode } = useThemeContext2();
|
|
2565
2716
|
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2566
2717
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2567
2718
|
ref: forwardedRef,
|
|
2568
2719
|
readonly,
|
|
2569
2720
|
extensions: [
|
|
2570
2721
|
markdownBundle({
|
|
2571
|
-
readonly,
|
|
2572
2722
|
themeMode,
|
|
2723
|
+
readonly,
|
|
2573
2724
|
placeholder: placeholder3
|
|
2574
2725
|
}),
|
|
2575
2726
|
...extensions
|
|
@@ -2581,7 +2732,11 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2581
2732
|
});
|
|
2582
2733
|
var defaultSlots = {
|
|
2583
2734
|
root: {
|
|
2584
|
-
|
|
2735
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
2736
|
+
className: mx3("flex flex-col grow overflow-y-auto", inputSurface)
|
|
2737
|
+
},
|
|
2738
|
+
editor: {
|
|
2739
|
+
className: "h-full p-2"
|
|
2585
2740
|
}
|
|
2586
2741
|
};
|
|
2587
2742
|
var defaultTextSlots = {
|
|
@@ -2599,9 +2754,9 @@ import { isNotNullOrUndefined } from "@dxos/util";
|
|
|
2599
2754
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2600
2755
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2601
2756
|
import { Context as Context2 } from "@dxos/context";
|
|
2602
|
-
import { invariant as
|
|
2757
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2603
2758
|
import { log as log3 } from "@dxos/log";
|
|
2604
|
-
var
|
|
2759
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2605
2760
|
var DEBOUNCE_INTERVAL = 100;
|
|
2606
2761
|
var SpaceAwarenessProvider = class {
|
|
2607
2762
|
constructor(params) {
|
|
@@ -2642,7 +2797,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2642
2797
|
log3.debug("failed to query awareness", {
|
|
2643
2798
|
err
|
|
2644
2799
|
}, {
|
|
2645
|
-
F:
|
|
2800
|
+
F: __dxlog_file6,
|
|
2646
2801
|
L: 85,
|
|
2647
2802
|
S: this,
|
|
2648
2803
|
C: (f, a) => f(...a)
|
|
@@ -2655,8 +2810,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2655
2810
|
this._postTask = void 0;
|
|
2656
2811
|
}
|
|
2657
2812
|
update(position) {
|
|
2658
|
-
|
|
2659
|
-
F:
|
|
2813
|
+
invariant4(this._postTask, void 0, {
|
|
2814
|
+
F: __dxlog_file6,
|
|
2660
2815
|
L: 96,
|
|
2661
2816
|
S: this,
|
|
2662
2817
|
A: [
|
|
@@ -2675,8 +2830,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2675
2830
|
return Array.from(this._remoteStates.values());
|
|
2676
2831
|
}
|
|
2677
2832
|
_handleQueryMessage() {
|
|
2678
|
-
|
|
2679
|
-
F:
|
|
2833
|
+
invariant4(this._postTask, void 0, {
|
|
2834
|
+
F: __dxlog_file6,
|
|
2680
2835
|
L: 111,
|
|
2681
2836
|
S: this,
|
|
2682
2837
|
A: [
|
|
@@ -2687,8 +2842,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2687
2842
|
this._postTask.schedule();
|
|
2688
2843
|
}
|
|
2689
2844
|
_handlePostMessage(message) {
|
|
2690
|
-
|
|
2691
|
-
F:
|
|
2845
|
+
invariant4(message.kind === "post", void 0, {
|
|
2846
|
+
F: __dxlog_file6,
|
|
2692
2847
|
L: 116,
|
|
2693
2848
|
S: this,
|
|
2694
2849
|
A: [
|
|
@@ -2701,23 +2856,63 @@ var SpaceAwarenessProvider = class {
|
|
|
2701
2856
|
}
|
|
2702
2857
|
};
|
|
2703
2858
|
|
|
2704
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2859
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2705
2860
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2706
|
-
|
|
2707
|
-
|
|
2861
|
+
var modelState = StateField5.define({
|
|
2862
|
+
create: () => void 0,
|
|
2863
|
+
update: (model) => model
|
|
2864
|
+
});
|
|
2865
|
+
|
|
2866
|
+
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2867
|
+
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2868
|
+
const obj = text;
|
|
2869
|
+
const doc = getRawDoc(obj, [
|
|
2870
|
+
obj.field
|
|
2871
|
+
]);
|
|
2872
|
+
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2873
|
+
space,
|
|
2874
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
2875
|
+
info: {
|
|
2876
|
+
displayName: identity?.profile?.displayName ?? "",
|
|
2877
|
+
color: cursorColor.color,
|
|
2878
|
+
lightColor: cursorColor.light
|
|
2879
|
+
},
|
|
2880
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2881
|
+
});
|
|
2882
|
+
const model = {
|
|
2883
|
+
id: obj.id,
|
|
2884
|
+
content: doc,
|
|
2885
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2886
|
+
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2887
|
+
extension: [
|
|
2888
|
+
modelState.init(() => model),
|
|
2889
|
+
automerge3({
|
|
2890
|
+
handle: doc.handle,
|
|
2891
|
+
path: doc.path
|
|
2892
|
+
}),
|
|
2893
|
+
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2894
|
+
awareness()
|
|
2895
|
+
].filter(isNotNullOrUndefined),
|
|
2896
|
+
peer: identity ? {
|
|
2897
|
+
id: identity.identityKey.toHex(),
|
|
2898
|
+
name: identity.profile?.displayName
|
|
2899
|
+
} : void 0
|
|
2900
|
+
};
|
|
2901
|
+
return model;
|
|
2902
|
+
};
|
|
2708
2903
|
|
|
2709
2904
|
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2710
2905
|
import * as decoding from "lib0/decoding";
|
|
2711
2906
|
import * as encoding from "lib0/encoding";
|
|
2712
2907
|
import { Observable } from "lib0/observable";
|
|
2713
2908
|
import * as YP from "y-protocols/awareness";
|
|
2714
|
-
import { invariant as
|
|
2909
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
2715
2910
|
import { log as log4 } from "@dxos/log";
|
|
2716
|
-
var
|
|
2911
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2717
2912
|
var createYjsModel = ({ identity, space, text }) => {
|
|
2718
|
-
|
|
2719
|
-
F:
|
|
2720
|
-
L:
|
|
2913
|
+
invariant5(text?.doc && text?.content, void 0, {
|
|
2914
|
+
F: __dxlog_file7,
|
|
2915
|
+
L: 22,
|
|
2721
2916
|
S: void 0,
|
|
2722
2917
|
A: [
|
|
2723
2918
|
"text?.doc && text?.content",
|
|
@@ -2781,8 +2976,8 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2781
2976
|
removed,
|
|
2782
2977
|
origin
|
|
2783
2978
|
}, {
|
|
2784
|
-
F:
|
|
2785
|
-
L:
|
|
2979
|
+
F: __dxlog_file7,
|
|
2980
|
+
L: 101,
|
|
2786
2981
|
S: this,
|
|
2787
2982
|
C: (f, a) => f(...a)
|
|
2788
2983
|
});
|
|
@@ -2794,8 +2989,8 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2794
2989
|
}
|
|
2795
2990
|
_handleSpaceMessage({ payload }) {
|
|
2796
2991
|
log4("space message", payload, {
|
|
2797
|
-
F:
|
|
2798
|
-
L:
|
|
2992
|
+
F: __dxlog_file7,
|
|
2993
|
+
L: 110,
|
|
2799
2994
|
S: this,
|
|
2800
2995
|
C: (f, a) => f(...a)
|
|
2801
2996
|
});
|
|
@@ -2838,15 +3033,25 @@ var YAwarenessProvider = class extends Observable {
|
|
|
2838
3033
|
}
|
|
2839
3034
|
};
|
|
2840
3035
|
|
|
3036
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3037
|
+
import { useState as useState2 } from "react";
|
|
3038
|
+
var useTextEditor = () => {
|
|
3039
|
+
const [view, setView] = useState2(null);
|
|
3040
|
+
return [
|
|
3041
|
+
(ref) => {
|
|
3042
|
+
setView(ref);
|
|
3043
|
+
},
|
|
3044
|
+
view
|
|
3045
|
+
];
|
|
3046
|
+
};
|
|
3047
|
+
|
|
2841
3048
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
update: (model) => model
|
|
2845
|
-
});
|
|
3049
|
+
import { useEffect as useEffect4, useState as useState3 } from "react";
|
|
3050
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2846
3051
|
var useTextModel = (props) => {
|
|
2847
3052
|
const { identity, space, text } = props;
|
|
2848
|
-
const [model, setModel] =
|
|
2849
|
-
|
|
3053
|
+
const [model, setModel] = useState3();
|
|
3054
|
+
useEffect4(() => setModel(createModel(props)), [
|
|
2850
3055
|
identity,
|
|
2851
3056
|
space,
|
|
2852
3057
|
text
|
|
@@ -2863,44 +3068,6 @@ var createModel = (props) => {
|
|
|
2863
3068
|
return void 0;
|
|
2864
3069
|
}
|
|
2865
3070
|
};
|
|
2866
|
-
|
|
2867
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2868
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2869
|
-
const obj = text;
|
|
2870
|
-
const doc = getRawDoc(obj, [
|
|
2871
|
-
obj.field
|
|
2872
|
-
]);
|
|
2873
|
-
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2874
|
-
space,
|
|
2875
|
-
channel: `automerge.awareness.${obj.id}`,
|
|
2876
|
-
info: {
|
|
2877
|
-
displayName: identity?.profile?.displayName ?? "",
|
|
2878
|
-
color: cursorColor.color,
|
|
2879
|
-
lightColor: cursorColor.light
|
|
2880
|
-
},
|
|
2881
|
-
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2882
|
-
});
|
|
2883
|
-
const model = {
|
|
2884
|
-
id: obj.id,
|
|
2885
|
-
content: doc,
|
|
2886
|
-
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2887
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
2888
|
-
extension: [
|
|
2889
|
-
modelState.init(() => model),
|
|
2890
|
-
automerge3({
|
|
2891
|
-
handle: doc.handle,
|
|
2892
|
-
path: doc.path
|
|
2893
|
-
}),
|
|
2894
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2895
|
-
awareness()
|
|
2896
|
-
].filter(isNotNullOrUndefined),
|
|
2897
|
-
peer: identity ? {
|
|
2898
|
-
id: identity.identityKey.toHex(),
|
|
2899
|
-
name: identity.profile?.displayName
|
|
2900
|
-
} : void 0
|
|
2901
|
-
};
|
|
2902
|
-
return model;
|
|
2903
|
-
};
|
|
2904
3071
|
export {
|
|
2905
3072
|
AwarenessProvider,
|
|
2906
3073
|
BaseTextEditor,
|
|
@@ -2926,7 +3093,6 @@ export {
|
|
|
2926
3093
|
comments,
|
|
2927
3094
|
createAutomergeModel,
|
|
2928
3095
|
createYjsModel,
|
|
2929
|
-
cursorConverter,
|
|
2930
3096
|
defaultMarkdownSlots,
|
|
2931
3097
|
defaultOptions,
|
|
2932
3098
|
defaultSlots,
|
|
@@ -2937,6 +3103,7 @@ export {
|
|
|
2937
3103
|
image,
|
|
2938
3104
|
link,
|
|
2939
3105
|
listener,
|
|
3106
|
+
logChanges,
|
|
2940
3107
|
markdownBundle,
|
|
2941
3108
|
markdownHighlightStyle,
|
|
2942
3109
|
markdownTags,
|
|
@@ -2944,7 +3111,8 @@ export {
|
|
|
2944
3111
|
markdownTheme,
|
|
2945
3112
|
mention,
|
|
2946
3113
|
modelState,
|
|
2947
|
-
|
|
3114
|
+
outliner,
|
|
3115
|
+
setComments,
|
|
2948
3116
|
setFocus,
|
|
2949
3117
|
setSelection,
|
|
2950
3118
|
table,
|
|
@@ -2952,6 +3120,9 @@ export {
|
|
|
2952
3120
|
tasklist,
|
|
2953
3121
|
textTheme,
|
|
2954
3122
|
typewriter,
|
|
3123
|
+
useAwareness,
|
|
3124
|
+
useComments,
|
|
3125
|
+
useTextEditor,
|
|
2955
3126
|
useTextModel,
|
|
2956
3127
|
yjs
|
|
2957
3128
|
};
|