@dxos/react-ui-editor 0.3.11-main.0f453da → 0.3.11-main.108b22e
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 +756 -912
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +16 -13
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/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/code.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +32 -19
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
- package/dist/types/src/extensions/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/hr.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +2 -5
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/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 -32
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +7 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +33 -35
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +77 -79
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +122 -93
- package/src/components/TextEditor/comments.stories.tsx +357 -0
- package/src/extensions/autocomplete.ts +6 -3
- package/src/extensions/automerge/automerge.ts +40 -46
- package/src/extensions/automerge/cursor.ts +2 -1
- package/src/extensions/automerge/defs.ts +10 -31
- package/src/extensions/automerge/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 +40 -46
- package/src/extensions/basic.ts +22 -17
- package/src/extensions/code.ts +24 -18
- package/src/extensions/comments.ts +246 -238
- package/src/extensions/cursor.ts +50 -0
- package/src/extensions/hr.ts +49 -50
- package/src/extensions/image.ts +2 -2
- package/src/extensions/index.ts +2 -1
- package/src/extensions/link.ts +7 -7
- package/src/extensions/markdown/bundle.ts +18 -24
- package/src/extensions/markdown/highlight.ts +0 -8
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/extensions/table.ts +2 -2
- package/src/extensions/tasklist.ts +78 -86
- 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 +48 -60
- package/src/index.ts +1 -0
- package/src/styles/markdown.ts +0 -2
- package/src/themes/default.ts +17 -50
- package/src/util.ts +41 -0
- package/dist/types/src/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/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/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/index.d.ts +0 -3
- package/dist/types/src/util/index.d.ts.map +0 -1
- package/dist/types/src/util/util.d.ts +0 -5
- package/dist/types/src/util/util.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/yjs/cursor.ts +0 -21
- 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 -178
- 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/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- package/src/util/util.ts +0 -18
|
@@ -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, useState } from "react";
|
|
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,85 +240,96 @@ 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
|
|
|
277
|
-
// packages/ui/react-ui-editor/src/
|
|
282
|
+
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
278
283
|
import { Facet } from "@codemirror/state";
|
|
279
|
-
var
|
|
284
|
+
var defaultCursorConverter = {
|
|
280
285
|
toCursor: (position) => position.toString(),
|
|
281
286
|
fromCursor: (cursor) => parseInt(cursor)
|
|
282
287
|
};
|
|
283
|
-
var
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
// packages/ui/react-ui-editor/src/util/util.ts
|
|
288
|
-
import { log } from "@dxos/log";
|
|
289
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
290
|
-
var callbackWrapper = (fn) => (...args) => {
|
|
291
|
-
try {
|
|
292
|
-
return fn(...args);
|
|
293
|
-
} catch (error) {
|
|
294
|
-
log.catch(error, void 0, {
|
|
295
|
-
F: __dxlog_file,
|
|
296
|
-
L: 16,
|
|
297
|
-
S: void 0,
|
|
298
|
-
C: (f, a) => f(...a)
|
|
288
|
+
var Cursor = class _Cursor {
|
|
289
|
+
static {
|
|
290
|
+
this.converter = Facet.define({
|
|
291
|
+
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
299
292
|
});
|
|
300
293
|
}
|
|
294
|
+
static {
|
|
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);
|
|
299
|
+
return [
|
|
300
|
+
from,
|
|
301
|
+
to
|
|
302
|
+
].join(":");
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
static {
|
|
306
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
307
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
308
|
+
const parts = cursor.split(":");
|
|
309
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
|
310
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
|
311
|
+
return from !== void 0 && to !== void 0 ? {
|
|
312
|
+
from,
|
|
313
|
+
to
|
|
314
|
+
} : void 0;
|
|
315
|
+
};
|
|
316
|
+
}
|
|
301
317
|
};
|
|
302
318
|
|
|
303
319
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
304
|
-
var
|
|
305
|
-
combine: (values) => values.at(-1)
|
|
306
|
-
});
|
|
320
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts";
|
|
307
321
|
var automerge3 = ({ handle, path }) => {
|
|
308
|
-
const
|
|
322
|
+
const state = StateField.define({
|
|
309
323
|
create: () => ({
|
|
324
|
+
path: path.slice(),
|
|
310
325
|
lastHeads: A.getHeads(handle.docSync()),
|
|
311
|
-
unreconciledTransactions: []
|
|
312
|
-
path: path.slice()
|
|
326
|
+
unreconciledTransactions: []
|
|
313
327
|
}),
|
|
314
328
|
update: (value, tr) => {
|
|
315
329
|
const result = {
|
|
330
|
+
path: path.slice(),
|
|
316
331
|
lastHeads: value.lastHeads,
|
|
317
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
318
|
-
path: path.slice()
|
|
332
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
319
333
|
};
|
|
320
334
|
let clearUnreconciled = false;
|
|
321
335
|
for (const effect of tr.effects) {
|
|
@@ -334,39 +348,44 @@ var automerge3 = ({ handle, path }) => {
|
|
|
334
348
|
return result;
|
|
335
349
|
}
|
|
336
350
|
});
|
|
337
|
-
const semaphore = new PatchSemaphore(
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
+
]
|
|
350
366
|
});
|
|
367
|
+
handle.addListener("change", this._handleChange.bind(this));
|
|
351
368
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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
|
+
];
|
|
365
384
|
};
|
|
366
385
|
|
|
367
386
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
368
|
-
import { Annotation as Annotation2, Facet as
|
|
369
|
-
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";
|
|
370
389
|
import { Event } from "@dxos/async";
|
|
371
390
|
import { Context } from "@dxos/context";
|
|
372
391
|
var dummyProvider = {
|
|
@@ -375,11 +394,11 @@ var dummyProvider = {
|
|
|
375
394
|
},
|
|
376
395
|
close: () => {
|
|
377
396
|
},
|
|
397
|
+
getRemoteStates: () => [],
|
|
378
398
|
update: () => {
|
|
379
|
-
}
|
|
380
|
-
getRemoteStates: () => []
|
|
399
|
+
}
|
|
381
400
|
};
|
|
382
|
-
var AwarenessProvider =
|
|
401
|
+
var AwarenessProvider = Facet2.define({
|
|
383
402
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
384
403
|
});
|
|
385
404
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
@@ -398,7 +417,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
398
417
|
this._ctx = new Context();
|
|
399
418
|
this._lastAnchor = void 0;
|
|
400
419
|
this._lastHead = void 0;
|
|
401
|
-
this._cursorConverter = view.state.facet(
|
|
420
|
+
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
402
421
|
this._provider = view.state.facet(AwarenessProvider);
|
|
403
422
|
this._provider.open();
|
|
404
423
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
@@ -453,7 +472,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
453
472
|
attributes: {
|
|
454
473
|
style: `background-color: ${lightColor}`
|
|
455
474
|
},
|
|
456
|
-
class: "cm-
|
|
475
|
+
class: "cm-collab-selection"
|
|
457
476
|
})
|
|
458
477
|
});
|
|
459
478
|
} else {
|
|
@@ -464,7 +483,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
464
483
|
attributes: {
|
|
465
484
|
style: `background-color: ${color}`
|
|
466
485
|
},
|
|
467
|
-
class: "cm-
|
|
486
|
+
class: "cm-collab-selection"
|
|
468
487
|
})
|
|
469
488
|
});
|
|
470
489
|
decorations.push({
|
|
@@ -474,7 +493,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
474
493
|
attributes: {
|
|
475
494
|
style: `background-color: ${color}`
|
|
476
495
|
},
|
|
477
|
-
class: "cm-
|
|
496
|
+
class: "cm-collab-selection"
|
|
478
497
|
})
|
|
479
498
|
});
|
|
480
499
|
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
@@ -485,7 +504,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
485
504
|
value: Decoration.line({
|
|
486
505
|
attributes: {
|
|
487
506
|
style: `background-color: ${color}`,
|
|
488
|
-
class: "cm-
|
|
507
|
+
class: "cm-collab-selectionLine"
|
|
489
508
|
}
|
|
490
509
|
})
|
|
491
510
|
});
|
|
@@ -505,23 +524,21 @@ var RemoteSelectionsDecorator = class {
|
|
|
505
524
|
}
|
|
506
525
|
};
|
|
507
526
|
var RemoteCaretWidget = class extends WidgetType {
|
|
508
|
-
constructor(
|
|
527
|
+
constructor(_name, _color) {
|
|
509
528
|
super();
|
|
510
|
-
this.
|
|
511
|
-
this.
|
|
512
|
-
this.name = name;
|
|
513
|
-
this.color = color;
|
|
529
|
+
this._name = _name;
|
|
530
|
+
this._color = _color;
|
|
514
531
|
}
|
|
515
532
|
toDOM() {
|
|
516
533
|
const span = document.createElement("span");
|
|
517
|
-
span.className = "cm-
|
|
518
|
-
span.style.backgroundColor = this.
|
|
519
|
-
span.style.borderColor = this.
|
|
534
|
+
span.className = "cm-collab-selectionCaret";
|
|
535
|
+
span.style.backgroundColor = this._color;
|
|
536
|
+
span.style.borderColor = this._color;
|
|
520
537
|
const dot = document.createElement("div");
|
|
521
|
-
dot.className = "cm-
|
|
538
|
+
dot.className = "cm-collab-selectionCaretDot";
|
|
522
539
|
const info = document.createElement("div");
|
|
523
|
-
info.className = "cm-
|
|
524
|
-
info.innerText = this.
|
|
540
|
+
info.className = "cm-collab-selectionInfo";
|
|
541
|
+
info.innerText = this._name;
|
|
525
542
|
span.appendChild(document.createTextNode("\u2060"));
|
|
526
543
|
span.appendChild(dot);
|
|
527
544
|
span.appendChild(document.createTextNode("\u2060"));
|
|
@@ -529,15 +546,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
529
546
|
span.appendChild(document.createTextNode("\u2060"));
|
|
530
547
|
return span;
|
|
531
548
|
}
|
|
532
|
-
eq(widget) {
|
|
533
|
-
return widget.color === this.color;
|
|
534
|
-
}
|
|
535
|
-
compare(widget) {
|
|
536
|
-
return widget.color === this.color;
|
|
537
|
-
}
|
|
538
549
|
updateDOM() {
|
|
539
550
|
return false;
|
|
540
551
|
}
|
|
552
|
+
eq(widget) {
|
|
553
|
+
return widget._color === this._color;
|
|
554
|
+
}
|
|
541
555
|
get estimatedHeight() {
|
|
542
556
|
return -1;
|
|
543
557
|
}
|
|
@@ -545,58 +559,60 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
545
559
|
return true;
|
|
546
560
|
}
|
|
547
561
|
};
|
|
548
|
-
var styles =
|
|
549
|
-
".cm-
|
|
550
|
-
".cm-
|
|
562
|
+
var styles = EditorView2.baseTheme({
|
|
563
|
+
".cm-collab-selection": {},
|
|
564
|
+
".cm-collab-selectionLine": {
|
|
551
565
|
padding: 0,
|
|
552
566
|
margin: "0px 2px 0px 4px"
|
|
553
567
|
},
|
|
554
|
-
".cm-
|
|
568
|
+
".cm-collab-selectionCaret": {
|
|
555
569
|
position: "relative",
|
|
556
570
|
borderLeft: "1px solid black",
|
|
557
571
|
borderRight: "1px solid black",
|
|
558
572
|
marginLeft: "-1px",
|
|
559
573
|
marginRight: "-1px",
|
|
560
574
|
boxSizing: "border-box",
|
|
561
|
-
display: "inline"
|
|
575
|
+
display: "inline",
|
|
576
|
+
cursor: "pointer"
|
|
562
577
|
},
|
|
563
|
-
".cm-
|
|
578
|
+
".cm-collab-selectionCaretDot": {
|
|
564
579
|
borderRadius: "50%",
|
|
565
580
|
position: "absolute",
|
|
566
|
-
width: ".
|
|
567
|
-
height: ".
|
|
568
|
-
top: "-.
|
|
569
|
-
left: "-.
|
|
581
|
+
width: ".5em",
|
|
582
|
+
height: ".5em",
|
|
583
|
+
top: "-.25em",
|
|
584
|
+
left: "-.25em",
|
|
570
585
|
backgroundColor: "inherit",
|
|
571
586
|
transition: "transform .3s ease-in-out",
|
|
572
587
|
boxSizing: "border-box"
|
|
573
588
|
},
|
|
574
|
-
".cm-
|
|
575
|
-
|
|
576
|
-
|
|
589
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
590
|
+
transform: "scale(0)",
|
|
591
|
+
transformOrigin: "center"
|
|
577
592
|
},
|
|
578
|
-
".cm-
|
|
593
|
+
".cm-collab-selectionInfo": {
|
|
579
594
|
position: "absolute",
|
|
580
|
-
|
|
581
|
-
|
|
595
|
+
transform: "translate(-50%, 0)",
|
|
596
|
+
top: "-20px",
|
|
597
|
+
left: 0,
|
|
582
598
|
fontSize: ".75em",
|
|
583
|
-
fontFamily: "serif",
|
|
599
|
+
fontFamily: "sans-serif",
|
|
584
600
|
fontStyle: "normal",
|
|
585
601
|
fontWeight: "normal",
|
|
586
602
|
lineHeight: "normal",
|
|
587
603
|
userSelect: "none",
|
|
588
604
|
color: "white",
|
|
589
|
-
|
|
590
|
-
paddingRight: "2px",
|
|
605
|
+
padding: "2px",
|
|
591
606
|
zIndex: 101,
|
|
592
607
|
transition: "opacity .3s ease-in-out",
|
|
593
608
|
backgroundColor: "inherit",
|
|
594
|
-
|
|
609
|
+
borderRadius: "2px",
|
|
610
|
+
// These should be separate.
|
|
595
611
|
opacity: 0,
|
|
596
612
|
transitionDelay: "0s",
|
|
597
613
|
whiteSpace: "nowrap"
|
|
598
614
|
},
|
|
599
|
-
".cm-
|
|
615
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionInfo": {
|
|
600
616
|
opacity: 1,
|
|
601
617
|
transitionDelay: "0s"
|
|
602
618
|
}
|
|
@@ -604,25 +620,27 @@ var styles = EditorView.baseTheme({
|
|
|
604
620
|
|
|
605
621
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
606
622
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
623
|
+
import { history } from "@codemirror/commands";
|
|
607
624
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
608
625
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
609
|
-
import { drawSelection, EditorView as
|
|
610
|
-
var basicBundle = ({
|
|
611
|
-
|
|
612
|
-
// 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 : [],
|
|
613
629
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
614
630
|
bracketMatching(),
|
|
615
631
|
closeBrackets(),
|
|
616
632
|
drawSelection(),
|
|
617
|
-
|
|
618
|
-
|
|
633
|
+
highlightActiveLine(),
|
|
634
|
+
history(),
|
|
635
|
+
_placeholder ? placeholder(_placeholder) : [],
|
|
636
|
+
// https://github.com/codemirror/theme-one-dark
|
|
619
637
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
620
|
-
]
|
|
638
|
+
];
|
|
621
639
|
|
|
622
640
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
623
|
-
import { EditorView as
|
|
641
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
624
642
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
625
|
-
import { invariant } from "@dxos/invariant";
|
|
643
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
626
644
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
627
645
|
var defaultOptions = {
|
|
628
646
|
effect: 2,
|
|
@@ -668,7 +686,7 @@ var blast = (options = defaultOptions) => {
|
|
|
668
686
|
};
|
|
669
687
|
return [
|
|
670
688
|
// Cursor moved.
|
|
671
|
-
|
|
689
|
+
EditorView4.updateListener.of((update2) => {
|
|
672
690
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
673
691
|
if (blaster) {
|
|
674
692
|
blaster.destroy();
|
|
@@ -749,7 +767,7 @@ var Blaster = class {
|
|
|
749
767
|
return this._node;
|
|
750
768
|
}
|
|
751
769
|
initialize() {
|
|
752
|
-
|
|
770
|
+
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
753
771
|
F: __dxlog_file2,
|
|
754
772
|
L: 138,
|
|
755
773
|
S: this,
|
|
@@ -786,7 +804,7 @@ var Blaster = class {
|
|
|
786
804
|
}
|
|
787
805
|
}
|
|
788
806
|
start() {
|
|
789
|
-
|
|
807
|
+
invariant2(this._canvas && this._ctx, void 0, {
|
|
790
808
|
F: __dxlog_file2,
|
|
791
809
|
L: 177,
|
|
792
810
|
S: this,
|
|
@@ -930,7 +948,7 @@ var random = (min, max) => {
|
|
|
930
948
|
};
|
|
931
949
|
|
|
932
950
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
933
|
-
import { ViewPlugin as ViewPlugin3, EditorView as
|
|
951
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView5, Decoration as Decoration2 } from "@codemirror/view";
|
|
934
952
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
935
953
|
|
|
936
954
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1021,7 +1039,7 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
|
|
|
1021
1039
|
|
|
1022
1040
|
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1023
1041
|
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1024
|
-
var styles2 =
|
|
1042
|
+
var styles2 = EditorView5.baseTheme({
|
|
1025
1043
|
"& .cm-codeblock": {
|
|
1026
1044
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1027
1045
|
},
|
|
@@ -1055,20 +1073,18 @@ var getLineRange = (lines, from, to) => {
|
|
|
1055
1073
|
];
|
|
1056
1074
|
};
|
|
1057
1075
|
var code2 = () => {
|
|
1058
|
-
const
|
|
1076
|
+
const buildDecorations5 = (view) => {
|
|
1059
1077
|
const decorations = [];
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
}).range(block.from));
|
|
1071
|
-
}
|
|
1078
|
+
const text = view.state.doc.sliceString(0);
|
|
1079
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
1080
|
+
const blocks = view.viewportLineBlocks;
|
|
1081
|
+
for (const match of matches) {
|
|
1082
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1083
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1084
|
+
const block = blocks[i];
|
|
1085
|
+
decorations.push(Decoration2.line({
|
|
1086
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1087
|
+
}).range(block.from));
|
|
1072
1088
|
}
|
|
1073
1089
|
}
|
|
1074
1090
|
return Decoration2.set(decorations);
|
|
@@ -1076,11 +1092,16 @@ var code2 = () => {
|
|
|
1076
1092
|
return [
|
|
1077
1093
|
ViewPlugin3.fromClass(class {
|
|
1078
1094
|
constructor(view) {
|
|
1079
|
-
this.
|
|
1095
|
+
this.hasFocus = false;
|
|
1096
|
+
this.decorations = buildDecorations5(view);
|
|
1080
1097
|
}
|
|
1081
1098
|
update(update2) {
|
|
1082
|
-
if (
|
|
1083
|
-
|
|
1099
|
+
if (
|
|
1100
|
+
// TODO(burdon): Generalize for other extensions.
|
|
1101
|
+
this.hasFocus !== update2.view.hasFocus || update2.startState.readOnly !== update2.view.state.readOnly || update2.docChanged || update2.viewportChanged
|
|
1102
|
+
) {
|
|
1103
|
+
this.hasFocus = update2.view.hasFocus;
|
|
1104
|
+
this.decorations = buildDecorations5(update2.view);
|
|
1084
1105
|
}
|
|
1085
1106
|
}
|
|
1086
1107
|
}, {
|
|
@@ -1092,27 +1113,55 @@ var code2 = () => {
|
|
|
1092
1113
|
|
|
1093
1114
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1094
1115
|
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1095
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as
|
|
1116
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
|
|
1096
1117
|
import sortBy from "lodash.sortby";
|
|
1118
|
+
import { useEffect } from "react";
|
|
1097
1119
|
import { debounce } from "@dxos/async";
|
|
1098
|
-
import { invariant as
|
|
1099
|
-
import { log as log2 } from "@dxos/log";
|
|
1120
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1100
1121
|
import { nonNullable } from "@dxos/util";
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1122
|
+
|
|
1123
|
+
// packages/ui/react-ui-editor/src/util.ts
|
|
1124
|
+
import { log } from "@dxos/log";
|
|
1125
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1126
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
1127
|
+
try {
|
|
1128
|
+
return fn(...args);
|
|
1129
|
+
} catch (err) {
|
|
1130
|
+
log.catch(err, void 0, {
|
|
1131
|
+
F: __dxlog_file3,
|
|
1132
|
+
L: 18,
|
|
1133
|
+
S: void 0,
|
|
1134
|
+
C: (f, a) => f(...a)
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
};
|
|
1138
|
+
var logChanges = (trs) => {
|
|
1139
|
+
const changes = trs.flatMap((tr) => {
|
|
1140
|
+
if (tr.changes.empty) {
|
|
1141
|
+
return void 0;
|
|
1142
|
+
}
|
|
1143
|
+
const changes2 = [];
|
|
1144
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1145
|
+
fromA,
|
|
1146
|
+
toA,
|
|
1147
|
+
fromB,
|
|
1148
|
+
toB,
|
|
1149
|
+
inserted: inserted.toString()
|
|
1150
|
+
})));
|
|
1151
|
+
return changes2;
|
|
1152
|
+
}).filter(Boolean);
|
|
1153
|
+
if (changes.length) {
|
|
1154
|
+
console.log("changes", changes);
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
|
|
1158
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1159
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1160
|
+
var styles3 = EditorView6.baseTheme({
|
|
1112
1161
|
"& .cm-comment": {
|
|
1113
1162
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1114
1163
|
},
|
|
1115
|
-
"& .cm-comment-
|
|
1164
|
+
"& .cm-comment-current": {
|
|
1116
1165
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1117
1166
|
}
|
|
1118
1167
|
});
|
|
@@ -1121,52 +1170,62 @@ var marks = {
|
|
|
1121
1170
|
class: "cm-comment"
|
|
1122
1171
|
}),
|
|
1123
1172
|
highlightActive: Decoration3.mark({
|
|
1124
|
-
class: "cm-comment-
|
|
1173
|
+
class: "cm-comment-current"
|
|
1125
1174
|
})
|
|
1126
1175
|
};
|
|
1127
|
-
var setFocus = (view,
|
|
1128
|
-
const
|
|
1129
|
-
if (!
|
|
1176
|
+
var setFocus = (view, id, center = true) => {
|
|
1177
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1178
|
+
if (!comment?.comment.cursor) {
|
|
1130
1179
|
return;
|
|
1131
1180
|
}
|
|
1132
|
-
view.
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1181
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1182
|
+
if (range) {
|
|
1183
|
+
view.dispatch({
|
|
1184
|
+
selection: {
|
|
1185
|
+
anchor: range.from
|
|
1186
|
+
},
|
|
1187
|
+
effects: [
|
|
1188
|
+
//
|
|
1189
|
+
EditorView6.scrollIntoView(range.from, center ? {
|
|
1190
|
+
y: "center"
|
|
1191
|
+
} : void 0),
|
|
1192
|
+
setSelection.of({
|
|
1193
|
+
current: id
|
|
1194
|
+
})
|
|
1195
|
+
]
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1141
1198
|
};
|
|
1142
|
-
var
|
|
1199
|
+
var setComments = StateEffect2.define();
|
|
1143
1200
|
var setSelection = StateEffect2.define();
|
|
1144
1201
|
var setCommentState = StateEffect2.define();
|
|
1145
|
-
var
|
|
1202
|
+
var commentsState = StateField2.define({
|
|
1146
1203
|
create: () => ({
|
|
1147
|
-
|
|
1204
|
+
comments: [],
|
|
1205
|
+
selection: {}
|
|
1148
1206
|
}),
|
|
1149
1207
|
update: (value, tr) => {
|
|
1150
|
-
const cursorConverter3 = tr.state.facet(CursorConverter);
|
|
1151
1208
|
for (const effect of tr.effects) {
|
|
1152
1209
|
if (effect.is(setSelection)) {
|
|
1153
1210
|
return {
|
|
1154
1211
|
...value,
|
|
1155
|
-
|
|
1212
|
+
selection: effect.value
|
|
1156
1213
|
};
|
|
1157
1214
|
}
|
|
1158
|
-
if (effect.is(
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
|
|
1215
|
+
if (effect.is(setComments)) {
|
|
1216
|
+
const comments2 = effect.value.map((comment) => {
|
|
1217
|
+
if (!comment.cursor) {
|
|
1218
|
+
return void 0;
|
|
1219
|
+
}
|
|
1220
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1162
1221
|
return range && {
|
|
1163
|
-
|
|
1164
|
-
|
|
1222
|
+
comment,
|
|
1223
|
+
range
|
|
1165
1224
|
};
|
|
1166
1225
|
}).filter(nonNullable);
|
|
1167
1226
|
return {
|
|
1168
1227
|
...value,
|
|
1169
|
-
|
|
1228
|
+
comments: comments2
|
|
1170
1229
|
};
|
|
1171
1230
|
}
|
|
1172
1231
|
if (effect.is(setCommentState)) {
|
|
@@ -1176,134 +1235,125 @@ var commentsStateField = StateField2.define({
|
|
|
1176
1235
|
return value;
|
|
1177
1236
|
}
|
|
1178
1237
|
});
|
|
1179
|
-
var highlightDecorations =
|
|
1180
|
-
|
|
1238
|
+
var highlightDecorations = EditorView6.decorations.compute([
|
|
1239
|
+
commentsState
|
|
1181
1240
|
], (state) => {
|
|
1182
|
-
const {
|
|
1183
|
-
const decorations = sortBy(
|
|
1184
|
-
|
|
1241
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1242
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1243
|
+
const range = comment.range;
|
|
1244
|
+
if (!range || range.from === range.to) {
|
|
1245
|
+
console.warn("Invalid range:", range);
|
|
1185
1246
|
return void 0;
|
|
1186
1247
|
}
|
|
1187
|
-
|
|
1188
|
-
from: selection.from,
|
|
1189
|
-
to: selection.to
|
|
1190
|
-
};
|
|
1191
|
-
if (selection.id === active) {
|
|
1248
|
+
if (comment.comment.id === current) {
|
|
1192
1249
|
return marks.highlightActive.range(range.from, range.to);
|
|
1193
1250
|
} else {
|
|
1194
1251
|
return marks.highlight.range(range.from, range.to);
|
|
1195
1252
|
}
|
|
1196
|
-
}).filter(nonNullable)
|
|
1253
|
+
}).filter(nonNullable);
|
|
1197
1254
|
return Decoration3.set(decorations);
|
|
1198
1255
|
});
|
|
1199
|
-
var
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
return this._anchor === other._anchor && this._id === other._id;
|
|
1217
|
-
}
|
|
1218
|
-
toDOM() {
|
|
1219
|
-
const span = document.createElement("span");
|
|
1220
|
-
span.className = "cm-bookmark";
|
|
1221
|
-
span.textContent = "\u203B";
|
|
1222
|
-
if (this._handleClick) {
|
|
1223
|
-
span.onclick = () => this._handleClick();
|
|
1256
|
+
var trackPastedComments = (onUpdate) => {
|
|
1257
|
+
let tracked = null;
|
|
1258
|
+
const handleTrack = (event, view) => {
|
|
1259
|
+
const comments2 = view.state.field(commentsState);
|
|
1260
|
+
const { main } = view.state.selection;
|
|
1261
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1262
|
+
if (!selectedRanges.length) {
|
|
1263
|
+
tracked = null;
|
|
1264
|
+
} else {
|
|
1265
|
+
tracked = {
|
|
1266
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1267
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1268
|
+
id: comment.id,
|
|
1269
|
+
from: range.from - main.from,
|
|
1270
|
+
to: range.to - main.from
|
|
1271
|
+
}))
|
|
1272
|
+
};
|
|
1224
1273
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1274
|
+
};
|
|
1275
|
+
return [
|
|
1276
|
+
EditorView6.domEventHandlers({
|
|
1277
|
+
cut: handleTrack,
|
|
1278
|
+
copy: handleTrack
|
|
1279
|
+
}),
|
|
1280
|
+
// Handle paste.
|
|
1281
|
+
EditorView6.updateListener.of(({ view, state, transactions }) => {
|
|
1282
|
+
if (tracked) {
|
|
1283
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1284
|
+
if (paste) {
|
|
1285
|
+
let found = -1;
|
|
1286
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1287
|
+
if (text.eq(tracked.text)) {
|
|
1288
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1289
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1290
|
+
}
|
|
1291
|
+
found = fromB;
|
|
1292
|
+
}
|
|
1293
|
+
});
|
|
1294
|
+
if (found > -1) {
|
|
1295
|
+
for (const moved of tracked.comments) {
|
|
1296
|
+
const range = {
|
|
1297
|
+
from: found + moved.from,
|
|
1298
|
+
to: found + moved.to
|
|
1299
|
+
};
|
|
1300
|
+
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1301
|
+
onUpdate(moved.id, cursor);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
tracked = null;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
})
|
|
1308
|
+
];
|
|
1227
1309
|
};
|
|
1228
1310
|
var comments = (options = {}) => {
|
|
1311
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1229
1312
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1230
1313
|
const createCommentThread = (view) => {
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
L: 224,
|
|
1314
|
+
invariant3(options.onCreate, void 0, {
|
|
1315
|
+
F: __dxlog_file4,
|
|
1316
|
+
L: 259,
|
|
1235
1317
|
S: void 0,
|
|
1236
1318
|
A: [
|
|
1237
1319
|
"options.onCreate",
|
|
1238
1320
|
""
|
|
1239
1321
|
]
|
|
1240
1322
|
});
|
|
1241
|
-
const {
|
|
1323
|
+
const { from, to } = view.state.selection.main;
|
|
1242
1324
|
if (from === to) {
|
|
1243
1325
|
return false;
|
|
1244
1326
|
}
|
|
1245
|
-
|
|
1327
|
+
if (to === view.state.doc.length) {
|
|
1328
|
+
view.dispatch({
|
|
1329
|
+
changes: {
|
|
1330
|
+
from: to,
|
|
1331
|
+
insert: "\n"
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1246
1336
|
from,
|
|
1247
1337
|
to
|
|
1248
1338
|
});
|
|
1249
|
-
if (
|
|
1250
|
-
const id =
|
|
1339
|
+
if (cursor) {
|
|
1340
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1251
1341
|
if (id) {
|
|
1252
1342
|
view.dispatch({
|
|
1253
1343
|
effects: setSelection.of({
|
|
1254
|
-
|
|
1344
|
+
current: id
|
|
1255
1345
|
}),
|
|
1256
1346
|
selection: {
|
|
1257
1347
|
anchor: from
|
|
1258
1348
|
}
|
|
1259
1349
|
});
|
|
1260
|
-
if (options.footnote) {
|
|
1261
|
-
const tag = `[^${id}]`;
|
|
1262
|
-
view.dispatch({
|
|
1263
|
-
changes: {
|
|
1264
|
-
from: head,
|
|
1265
|
-
insert: tag
|
|
1266
|
-
},
|
|
1267
|
-
selection: {
|
|
1268
|
-
anchor: head + tag.length
|
|
1269
|
-
}
|
|
1270
|
-
});
|
|
1271
|
-
}
|
|
1272
1350
|
return true;
|
|
1273
1351
|
}
|
|
1274
1352
|
}
|
|
1275
1353
|
return false;
|
|
1276
1354
|
};
|
|
1277
|
-
const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
|
|
1278
|
-
static {
|
|
1279
|
-
// Match markdown footnotes (option).
|
|
1280
|
-
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
1281
|
-
this.bookmarkMatcher = new MatchDecorator({
|
|
1282
|
-
regexp: /\[\^(\w+)\]/g,
|
|
1283
|
-
decoration: (match, view, pos) => {
|
|
1284
|
-
const id = match[1];
|
|
1285
|
-
return Decoration3.replace({
|
|
1286
|
-
id,
|
|
1287
|
-
widget: new BookmarkWidget(pos, id)
|
|
1288
|
-
});
|
|
1289
|
-
}
|
|
1290
|
-
});
|
|
1291
|
-
}
|
|
1292
|
-
constructor(view) {
|
|
1293
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
1294
|
-
}
|
|
1295
|
-
update(update2) {
|
|
1296
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update2, this.bookmarks);
|
|
1297
|
-
}
|
|
1298
|
-
}, {
|
|
1299
|
-
decorations: (instance) => instance.bookmarks,
|
|
1300
|
-
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1301
|
-
return view.plugin(plugin)?.bookmarks || Decoration3.none;
|
|
1302
|
-
})
|
|
1303
|
-
});
|
|
1304
1355
|
return [
|
|
1305
|
-
|
|
1306
|
-
commentsStateField,
|
|
1356
|
+
commentsState,
|
|
1307
1357
|
highlightDecorations,
|
|
1308
1358
|
styles3,
|
|
1309
1359
|
//
|
|
@@ -1311,7 +1361,7 @@ var comments = (options = {}) => {
|
|
|
1311
1361
|
//
|
|
1312
1362
|
options.onCreate ? keymap3.of([
|
|
1313
1363
|
{
|
|
1314
|
-
key:
|
|
1364
|
+
key: shortcut,
|
|
1315
1365
|
run: callbackWrapper(createCommentThread)
|
|
1316
1366
|
}
|
|
1317
1367
|
]) : [],
|
|
@@ -1328,7 +1378,7 @@ var comments = (options = {}) => {
|
|
|
1328
1378
|
above: true,
|
|
1329
1379
|
create: () => {
|
|
1330
1380
|
const el = document.createElement("div");
|
|
1331
|
-
options.onHover
|
|
1381
|
+
options.onHover(el, shortcut);
|
|
1332
1382
|
return {
|
|
1333
1383
|
dom: el,
|
|
1334
1384
|
offset: {
|
|
@@ -1341,156 +1391,154 @@ var comments = (options = {}) => {
|
|
|
1341
1391
|
}
|
|
1342
1392
|
return null;
|
|
1343
1393
|
}, {
|
|
1344
|
-
|
|
1394
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1395
|
+
// hideOnChange: true,
|
|
1345
1396
|
hoverTime: 1e3
|
|
1346
1397
|
}) : [],
|
|
1347
1398
|
//
|
|
1348
|
-
//
|
|
1349
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1399
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1350
1400
|
//
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
{
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
if (
|
|
1359
|
-
|
|
1360
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1361
|
-
log2.info("deleted comment", {
|
|
1362
|
-
thread: range.id
|
|
1363
|
-
}, {
|
|
1364
|
-
F: __dxlog_file3,
|
|
1365
|
-
L: 358,
|
|
1366
|
-
S: void 0,
|
|
1367
|
-
C: (f, a) => f(...a)
|
|
1368
|
-
});
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
if (from <= range.to) {
|
|
1372
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1373
|
-
Object.assign(range, newRange);
|
|
1374
|
-
mod = true;
|
|
1401
|
+
EditorView6.updateListener.of(({ view, state, changes }) => {
|
|
1402
|
+
let mod = false;
|
|
1403
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1404
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1405
|
+
comments2.forEach(({ comment, range }) => {
|
|
1406
|
+
if (from2 === to2) {
|
|
1407
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1408
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1409
|
+
options.onDelete?.(comment.id);
|
|
1375
1410
|
}
|
|
1376
|
-
}
|
|
1411
|
+
}
|
|
1412
|
+
if (from <= range.to) {
|
|
1413
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1414
|
+
Object.assign(range, newRange);
|
|
1415
|
+
mod = true;
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
});
|
|
1419
|
+
if (mod) {
|
|
1420
|
+
view.dispatch({
|
|
1421
|
+
effects: setCommentState.of({
|
|
1422
|
+
comments: comments2,
|
|
1423
|
+
...value
|
|
1424
|
+
})
|
|
1377
1425
|
});
|
|
1378
|
-
if (mod) {
|
|
1379
|
-
view.dispatch({
|
|
1380
|
-
effects: setCommentState.of({
|
|
1381
|
-
active,
|
|
1382
|
-
ranges
|
|
1383
|
-
})
|
|
1384
|
-
});
|
|
1385
|
-
}
|
|
1386
1426
|
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1427
|
+
}),
|
|
1428
|
+
//
|
|
1429
|
+
// Track selection/proximity.
|
|
1430
|
+
//
|
|
1431
|
+
EditorView6.updateListener.of(({ view, state }) => {
|
|
1432
|
+
let min = Infinity;
|
|
1433
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1434
|
+
const { head } = state.selection.main;
|
|
1435
|
+
const selection = {};
|
|
1436
|
+
comments2.forEach(({ comment, range }) => {
|
|
1437
|
+
if (head >= range.from && head <= range.to) {
|
|
1438
|
+
selection.current = comment.id;
|
|
1439
|
+
selection.closest = void 0;
|
|
1440
|
+
}
|
|
1441
|
+
if (!selection.current) {
|
|
1442
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1400
1443
|
if (d < min) {
|
|
1401
|
-
|
|
1444
|
+
selection.closest = comment.id;
|
|
1402
1445
|
min = d;
|
|
1403
1446
|
}
|
|
1404
|
-
});
|
|
1405
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1406
|
-
view.dispatch({
|
|
1407
|
-
effects: setSelection.of(selected)
|
|
1408
|
-
});
|
|
1409
|
-
handleSelect({
|
|
1410
|
-
...selected,
|
|
1411
|
-
ranges: ranges.map((range) => ({
|
|
1412
|
-
...range,
|
|
1413
|
-
location: view.coordsAtPos(range.from)
|
|
1414
|
-
}))
|
|
1415
|
-
});
|
|
1416
1447
|
}
|
|
1448
|
+
});
|
|
1449
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1450
|
+
view.dispatch({
|
|
1451
|
+
effects: setSelection.of(selection)
|
|
1452
|
+
});
|
|
1453
|
+
handleSelect({
|
|
1454
|
+
selection,
|
|
1455
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1456
|
+
comment,
|
|
1457
|
+
range,
|
|
1458
|
+
location: view.coordsAtPos(range.from)
|
|
1459
|
+
}))
|
|
1460
|
+
});
|
|
1417
1461
|
}
|
|
1418
|
-
})
|
|
1462
|
+
}),
|
|
1463
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1419
1464
|
];
|
|
1420
1465
|
};
|
|
1421
|
-
var
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1433
|
-
return from !== void 0 && to !== void 0 ? {
|
|
1434
|
-
from,
|
|
1435
|
-
to
|
|
1436
|
-
} : void 0;
|
|
1466
|
+
var useComments = (view, comments2 = []) => {
|
|
1467
|
+
useEffect(() => {
|
|
1468
|
+
if (view) {
|
|
1469
|
+
view.dispatch({
|
|
1470
|
+
effects: setComments.of(comments2)
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
}, [
|
|
1474
|
+
view,
|
|
1475
|
+
comments2
|
|
1476
|
+
]);
|
|
1437
1477
|
};
|
|
1438
1478
|
|
|
1439
1479
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1440
|
-
import {
|
|
1441
|
-
|
|
1480
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1481
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1482
|
+
import { Decoration as Decoration4, EditorView as EditorView7, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1483
|
+
var styles4 = EditorView7.baseTheme({
|
|
1442
1484
|
"& .cm-hr": {
|
|
1443
|
-
// TODO(burdon): ???
|
|
1444
1485
|
// Note that block-level decorations should not have vertical margins,
|
|
1445
|
-
|
|
1486
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
1446
1487
|
}
|
|
1447
1488
|
});
|
|
1448
|
-
var HorizontalRuleWidget = class extends
|
|
1449
|
-
|
|
1450
|
-
super();
|
|
1451
|
-
this._pos = _pos;
|
|
1452
|
-
}
|
|
1453
|
-
eq(other) {
|
|
1454
|
-
return this._pos === other._pos;
|
|
1455
|
-
}
|
|
1456
|
-
toDOM(view) {
|
|
1489
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1490
|
+
toDOM() {
|
|
1457
1491
|
const el = document.createElement("div");
|
|
1458
1492
|
el.className = "cm-hr";
|
|
1459
1493
|
return el;
|
|
1460
1494
|
}
|
|
1461
1495
|
};
|
|
1462
|
-
var
|
|
1463
|
-
|
|
1464
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1466
|
-
})
|
|
1496
|
+
var decoration = Decoration4.replace({
|
|
1497
|
+
widget: new HorizontalRuleWidget()
|
|
1467
1498
|
});
|
|
1468
|
-
var
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1499
|
+
var buildDecorations = (view) => {
|
|
1500
|
+
const builder = new RangeSetBuilder();
|
|
1501
|
+
const { state } = view;
|
|
1502
|
+
const cursor = state.selection.main.head;
|
|
1503
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1504
|
+
syntaxTree(state).iterate({
|
|
1505
|
+
enter: (node) => {
|
|
1506
|
+
if (node.name === "HorizontalRule") {
|
|
1507
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1508
|
+
builder.add(node.from, node.to, decoration);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
},
|
|
1512
|
+
from,
|
|
1513
|
+
to
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
return builder.finish();
|
|
1517
|
+
};
|
|
1518
|
+
var hr = () => {
|
|
1519
|
+
return [
|
|
1520
|
+
styles4,
|
|
1521
|
+
ViewPlugin4.fromClass(class {
|
|
1522
|
+
constructor(view) {
|
|
1523
|
+
this.decorations = buildDecorations(view);
|
|
1524
|
+
}
|
|
1525
|
+
update(update2) {
|
|
1526
|
+
this.decorations = buildDecorations(update2.view);
|
|
1527
|
+
}
|
|
1528
|
+
}, {
|
|
1529
|
+
decorations: (v) => v.decorations
|
|
1482
1530
|
})
|
|
1483
|
-
|
|
1484
|
-
|
|
1531
|
+
];
|
|
1532
|
+
};
|
|
1485
1533
|
|
|
1486
1534
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1535
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1488
1536
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
1489
|
-
import { Decoration as Decoration5, EditorView as
|
|
1537
|
+
import { Decoration as Decoration5, EditorView as EditorView8, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1490
1538
|
var image = (options = {}) => {
|
|
1491
1539
|
return StateField3.define({
|
|
1492
1540
|
create: (state) => {
|
|
1493
|
-
return Decoration5.set(
|
|
1541
|
+
return Decoration5.set(buildDecorations2(0, state.doc.length, state));
|
|
1494
1542
|
},
|
|
1495
1543
|
update: (value, tr) => {
|
|
1496
1544
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -1510,16 +1558,16 @@ var image = (options = {}) => {
|
|
|
1510
1558
|
filterFrom: from,
|
|
1511
1559
|
filterTo: to,
|
|
1512
1560
|
filter: () => false,
|
|
1513
|
-
add:
|
|
1561
|
+
add: buildDecorations2(from, to, tr.state)
|
|
1514
1562
|
});
|
|
1515
1563
|
},
|
|
1516
|
-
provide: (field) =>
|
|
1564
|
+
provide: (field) => EditorView8.decorations.from(field)
|
|
1517
1565
|
});
|
|
1518
1566
|
};
|
|
1519
|
-
var
|
|
1567
|
+
var buildDecorations2 = (from, to, state) => {
|
|
1520
1568
|
const decorations = [];
|
|
1521
1569
|
const cursor = state.selection.main.head;
|
|
1522
|
-
|
|
1570
|
+
syntaxTree2(state).iterate({
|
|
1523
1571
|
enter: (node) => {
|
|
1524
1572
|
if (node.name === "Image") {
|
|
1525
1573
|
const urlNode = node.node.getChild("URL");
|
|
@@ -1538,7 +1586,7 @@ var buildDecorations = (from, to, state) => {
|
|
|
1538
1586
|
});
|
|
1539
1587
|
return decorations;
|
|
1540
1588
|
};
|
|
1541
|
-
var ImageWidget = class extends
|
|
1589
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1542
1590
|
constructor(_url) {
|
|
1543
1591
|
super();
|
|
1544
1592
|
this._url = _url;
|
|
@@ -1556,19 +1604,19 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1556
1604
|
};
|
|
1557
1605
|
|
|
1558
1606
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1559
|
-
import { syntaxTree as
|
|
1560
|
-
import { RangeSetBuilder } from "@codemirror/state";
|
|
1561
|
-
import {
|
|
1607
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1608
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1609
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration6, ViewPlugin as ViewPlugin5, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1562
1610
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1563
1611
|
var link = (options = {}) => {
|
|
1564
1612
|
const extensions = [
|
|
1565
|
-
|
|
1613
|
+
ViewPlugin5.fromClass(class {
|
|
1566
1614
|
constructor(view) {
|
|
1567
|
-
this.decorations =
|
|
1615
|
+
this.decorations = buildDecorations3(view, options);
|
|
1568
1616
|
}
|
|
1569
1617
|
update(update2) {
|
|
1570
1618
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1571
|
-
this.decorations =
|
|
1619
|
+
this.decorations = buildDecorations3(update2.view, options);
|
|
1572
1620
|
}
|
|
1573
1621
|
}
|
|
1574
1622
|
}, {
|
|
@@ -1581,7 +1629,7 @@ var link = (options = {}) => {
|
|
|
1581
1629
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1582
1630
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1583
1631
|
hoverTooltip2((view, pos, side) => {
|
|
1584
|
-
const syntax =
|
|
1632
|
+
const syntax = syntaxTree3(view.state).resolveInner(pos, side);
|
|
1585
1633
|
let link2 = null;
|
|
1586
1634
|
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1587
1635
|
link2 = node.name === "Link" ? node : null;
|
|
@@ -1613,7 +1661,7 @@ var link = (options = {}) => {
|
|
|
1613
1661
|
}
|
|
1614
1662
|
return extensions;
|
|
1615
1663
|
};
|
|
1616
|
-
var LinkButton = class extends
|
|
1664
|
+
var LinkButton = class extends WidgetType4 {
|
|
1617
1665
|
constructor(_url, _onAttach) {
|
|
1618
1666
|
super();
|
|
1619
1667
|
this._url = _url;
|
|
@@ -1628,7 +1676,7 @@ var LinkButton = class extends WidgetType5 {
|
|
|
1628
1676
|
return el;
|
|
1629
1677
|
}
|
|
1630
1678
|
};
|
|
1631
|
-
var LinkText = class extends
|
|
1679
|
+
var LinkText = class extends WidgetType4 {
|
|
1632
1680
|
constructor(_text, _url) {
|
|
1633
1681
|
super();
|
|
1634
1682
|
this._text = _text;
|
|
@@ -1657,12 +1705,12 @@ var LinkText = class extends WidgetType5 {
|
|
|
1657
1705
|
return link2;
|
|
1658
1706
|
}
|
|
1659
1707
|
};
|
|
1660
|
-
var
|
|
1661
|
-
const builder = new
|
|
1708
|
+
var buildDecorations3 = (view, options) => {
|
|
1709
|
+
const builder = new RangeSetBuilder2();
|
|
1662
1710
|
const { state } = view;
|
|
1663
1711
|
const cursor = state.selection.main.head;
|
|
1664
1712
|
for (const { from, to } of view.visibleRanges) {
|
|
1665
|
-
|
|
1713
|
+
syntaxTree3(state).iterate({
|
|
1666
1714
|
enter: (node) => {
|
|
1667
1715
|
if (node.name === "Link") {
|
|
1668
1716
|
const marks2 = node.node.getChildren("LinkMark");
|
|
@@ -1693,14 +1741,14 @@ var buildDecorations2 = (view, options) => {
|
|
|
1693
1741
|
};
|
|
1694
1742
|
|
|
1695
1743
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1696
|
-
import { EditorView as
|
|
1744
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1697
1745
|
var listener = ({ onFocus, onChange }) => {
|
|
1698
1746
|
const extensions = [];
|
|
1699
|
-
onFocus && extensions.push(
|
|
1747
|
+
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1700
1748
|
onFocus(focused);
|
|
1701
1749
|
return null;
|
|
1702
1750
|
}));
|
|
1703
|
-
onChange && extensions.push(
|
|
1751
|
+
onChange && extensions.push(EditorView9.updateListener.of((update2) => {
|
|
1704
1752
|
onChange(update2.state.doc.toString());
|
|
1705
1753
|
}));
|
|
1706
1754
|
return extensions;
|
|
@@ -1708,14 +1756,14 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
1708
1756
|
|
|
1709
1757
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1710
1758
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1711
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1759
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1712
1760
|
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1713
1761
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1714
1762
|
import { languages } from "@codemirror/language-data";
|
|
1715
1763
|
import { searchKeymap } from "@codemirror/search";
|
|
1716
1764
|
import { EditorState } from "@codemirror/state";
|
|
1717
1765
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1718
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1766
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1719
1767
|
|
|
1720
1768
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1721
1769
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1728,7 +1776,6 @@ var markdownTags = {
|
|
|
1728
1776
|
CodeText: Tag.define(),
|
|
1729
1777
|
EmphasisMark: Tag.define(),
|
|
1730
1778
|
HeaderMark: Tag.define(),
|
|
1731
|
-
// HorizontalRule: Tag.define(),
|
|
1732
1779
|
InlineCode: Tag.define(),
|
|
1733
1780
|
LinkLabel: Tag.define(),
|
|
1734
1781
|
LinkReference: Tag.define(),
|
|
@@ -1892,12 +1939,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1892
1939
|
],
|
|
1893
1940
|
class: blockquote
|
|
1894
1941
|
},
|
|
1895
|
-
// TODO(burdon): Replace with extension.
|
|
1896
|
-
// {
|
|
1897
|
-
// tag: [markdownTags.HorizontalRule],
|
|
1898
|
-
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1899
|
-
// },
|
|
1900
|
-
// TODO(burdon): Only if being edited.
|
|
1901
1942
|
{
|
|
1902
1943
|
tag: [
|
|
1903
1944
|
markdownTags.TableCell
|
|
@@ -1917,17 +1958,17 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1917
1958
|
return [
|
|
1918
1959
|
EditorState.allowMultipleSelections.of(true),
|
|
1919
1960
|
EditorState.tabSize.of(2),
|
|
1920
|
-
|
|
1921
|
-
|
|
1961
|
+
EditorView10.lineWrapping,
|
|
1962
|
+
// https://github.com/codemirror/basic-setup
|
|
1922
1963
|
bracketMatching2(),
|
|
1923
1964
|
closeBrackets2(),
|
|
1924
1965
|
crosshairCursor(),
|
|
1925
1966
|
dropCursor(),
|
|
1926
1967
|
drawSelection2(),
|
|
1927
|
-
|
|
1928
|
-
|
|
1968
|
+
highlightActiveLine2(),
|
|
1969
|
+
history2(),
|
|
1929
1970
|
indentOnInput(),
|
|
1930
|
-
_placeholder
|
|
1971
|
+
_placeholder ? placeholder2(_placeholder) : [],
|
|
1931
1972
|
// Main extension.
|
|
1932
1973
|
// https://github.com/codemirror/lang-markdown
|
|
1933
1974
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1949,34 +1990,40 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1949
1990
|
// https://github.com/codemirror/theme-one-dark
|
|
1950
1991
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1951
1992
|
// Custom styles.
|
|
1952
|
-
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1993
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly)),
|
|
1994
|
+
keymap4.of([
|
|
1995
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1996
|
+
indentWithTab,
|
|
1997
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1998
|
+
...closeBracketsKeymap,
|
|
1999
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2000
|
+
...historyKeymap,
|
|
2001
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2002
|
+
...searchKeymap,
|
|
2003
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2004
|
+
...standardKeymap
|
|
2005
|
+
])
|
|
2006
|
+
];
|
|
2007
|
+
};
|
|
1967
2008
|
|
|
1968
2009
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
1969
2010
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1970
2011
|
var mention = ({ onSearch }) => {
|
|
1971
2012
|
return autocompletion2({
|
|
2013
|
+
// TODO(burdon): Not working.
|
|
2014
|
+
activateOnTyping: true,
|
|
2015
|
+
// activateOnTypingDelay: 100,
|
|
2016
|
+
// selectOnOpen: true,
|
|
1972
2017
|
closeOnBlur: false,
|
|
2018
|
+
// defaultKeymap: false,
|
|
2019
|
+
icons: false,
|
|
1973
2020
|
override: [
|
|
1974
2021
|
(context) => {
|
|
2022
|
+
console.log(context);
|
|
1975
2023
|
const match = context.matchBefore(/@(\w+)?/);
|
|
1976
2024
|
if (!match || match.from === match.to && !context.explicit) {
|
|
1977
2025
|
return null;
|
|
1978
2026
|
}
|
|
1979
|
-
console.log(match);
|
|
1980
2027
|
return {
|
|
1981
2028
|
from: match.from,
|
|
1982
2029
|
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
@@ -1988,19 +2035,24 @@ var mention = ({ onSearch }) => {
|
|
|
1988
2035
|
});
|
|
1989
2036
|
};
|
|
1990
2037
|
|
|
2038
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2039
|
+
var outliner = (options = {}) => {
|
|
2040
|
+
return [];
|
|
2041
|
+
};
|
|
2042
|
+
|
|
1991
2043
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1992
|
-
import { syntaxTree as
|
|
1993
|
-
import { RangeSetBuilder as
|
|
1994
|
-
import { Decoration as Decoration7, EditorView as
|
|
2044
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2045
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField4 } from "@codemirror/state";
|
|
2046
|
+
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1995
2047
|
var table = (options = {}) => {
|
|
1996
2048
|
return StateField4.define({
|
|
1997
2049
|
create: (state) => update(state, options),
|
|
1998
2050
|
update: (_, tr) => update(tr.state, options),
|
|
1999
|
-
provide: (field) =>
|
|
2051
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
2000
2052
|
});
|
|
2001
2053
|
};
|
|
2002
2054
|
var update = (state, options) => {
|
|
2003
|
-
const builder = new
|
|
2055
|
+
const builder = new RangeSetBuilder3();
|
|
2004
2056
|
const cursor = state.selection.main.head;
|
|
2005
2057
|
const tables = [];
|
|
2006
2058
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2008,7 +2060,7 @@ var update = (state, options) => {
|
|
|
2008
2060
|
const table2 = getTable();
|
|
2009
2061
|
return table2.rows?.[table2.rows.length - 1];
|
|
2010
2062
|
};
|
|
2011
|
-
|
|
2063
|
+
syntaxTree4(state).iterate({
|
|
2012
2064
|
enter: (node) => {
|
|
2013
2065
|
switch (node.name) {
|
|
2014
2066
|
case "Table": {
|
|
@@ -2049,7 +2101,7 @@ var update = (state, options) => {
|
|
|
2049
2101
|
});
|
|
2050
2102
|
return builder.finish();
|
|
2051
2103
|
};
|
|
2052
|
-
var TableWidget = class extends
|
|
2104
|
+
var TableWidget = class extends WidgetType5 {
|
|
2053
2105
|
constructor(_table) {
|
|
2054
2106
|
super();
|
|
2055
2107
|
this._table = _table;
|
|
@@ -2087,85 +2139,98 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2087
2139
|
};
|
|
2088
2140
|
|
|
2089
2141
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2090
|
-
import {
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2142
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2143
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2144
|
+
import { EditorView as EditorView12, Decoration as Decoration8, WidgetType as WidgetType6, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
2145
|
+
var styles5 = EditorView12.baseTheme({
|
|
2146
|
+
"& .cm-task": {
|
|
2147
|
+
color: getToken("extend.colors.blue.500")
|
|
2148
|
+
},
|
|
2149
|
+
"& .cm-task-checkbox": {
|
|
2150
|
+
marginLeft: "4px",
|
|
2151
|
+
marginRight: "4px"
|
|
2095
2152
|
}
|
|
2096
2153
|
});
|
|
2097
|
-
var CheckboxWidget = class extends
|
|
2098
|
-
constructor(_checked
|
|
2154
|
+
var CheckboxWidget = class extends WidgetType6 {
|
|
2155
|
+
constructor(_checked) {
|
|
2099
2156
|
super();
|
|
2100
2157
|
this._checked = _checked;
|
|
2101
|
-
this._indent = _indent;
|
|
2102
|
-
this._onCheck = _onCheck;
|
|
2103
2158
|
}
|
|
2104
2159
|
eq(other) {
|
|
2105
|
-
return this._checked === other._checked
|
|
2160
|
+
return this._checked === other._checked;
|
|
2106
2161
|
}
|
|
2107
2162
|
toDOM(view) {
|
|
2108
|
-
const
|
|
2109
|
-
|
|
2110
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2111
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2112
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2163
|
+
const input = document.createElement("input");
|
|
2164
|
+
input.className = "cm-task-checkbox";
|
|
2113
2165
|
input.type = "checkbox";
|
|
2114
2166
|
input.checked = this._checked;
|
|
2115
|
-
if (
|
|
2167
|
+
if (view.state.readOnly) {
|
|
2116
2168
|
input.setAttribute("disabled", "true");
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2169
|
+
} else {
|
|
2170
|
+
input.onmousedown = (event) => {
|
|
2171
|
+
const pos = view.posAtDOM(input);
|
|
2172
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2173
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2174
|
+
view.dispatch({
|
|
2175
|
+
changes: {
|
|
2176
|
+
from: pos + 1,
|
|
2177
|
+
to: pos + 2,
|
|
2178
|
+
insert: this._checked ? " " : "x"
|
|
2179
|
+
}
|
|
2180
|
+
});
|
|
2181
|
+
event.preventDefault();
|
|
2182
|
+
}
|
|
2122
2183
|
};
|
|
2123
2184
|
}
|
|
2124
|
-
return
|
|
2185
|
+
return input;
|
|
2125
2186
|
}
|
|
2126
2187
|
ignoreEvent() {
|
|
2127
2188
|
return false;
|
|
2128
2189
|
}
|
|
2129
2190
|
};
|
|
2191
|
+
var checkedDecoration = Decoration8.replace({
|
|
2192
|
+
widget: new CheckboxWidget(true)
|
|
2193
|
+
});
|
|
2194
|
+
var uncheckedDecoration = Decoration8.replace({
|
|
2195
|
+
widget: new CheckboxWidget(false)
|
|
2196
|
+
});
|
|
2197
|
+
var buildDecorations4 = (view) => {
|
|
2198
|
+
const builder = new RangeSetBuilder4();
|
|
2199
|
+
const { state } = view;
|
|
2200
|
+
const cursor = state.selection.main.head;
|
|
2201
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2202
|
+
syntaxTree5(state).iterate({
|
|
2203
|
+
enter: (node) => {
|
|
2204
|
+
if (node.name === "TaskMarker") {
|
|
2205
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2206
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2207
|
+
builder.add(node.from - 2, node.from - 1, Decoration8.mark({
|
|
2208
|
+
class: "cm-task"
|
|
2209
|
+
}));
|
|
2210
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
},
|
|
2214
|
+
from,
|
|
2215
|
+
to
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
return builder.finish();
|
|
2219
|
+
};
|
|
2130
2220
|
var tasklist = (options = {}) => {
|
|
2131
|
-
const taskMatcher = new MatchDecorator3({
|
|
2132
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2133
|
-
decoration: (match, view, pos) => {
|
|
2134
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2135
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2136
|
-
return Decoration8.replace({
|
|
2137
|
-
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2138
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2139
|
-
view.dispatch({
|
|
2140
|
-
changes: {
|
|
2141
|
-
from: idx,
|
|
2142
|
-
to: idx + 1,
|
|
2143
|
-
insert: checked2 ? "x" : " "
|
|
2144
|
-
},
|
|
2145
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2146
|
-
selection: {
|
|
2147
|
-
anchor: idx + 3
|
|
2148
|
-
}
|
|
2149
|
-
});
|
|
2150
|
-
})
|
|
2151
|
-
});
|
|
2152
|
-
}
|
|
2153
|
-
});
|
|
2154
|
-
const tasks = ViewPlugin7.fromClass(class {
|
|
2155
|
-
constructor(view) {
|
|
2156
|
-
this.tasks = taskMatcher.createDeco(view);
|
|
2157
|
-
}
|
|
2158
|
-
update(update2) {
|
|
2159
|
-
this.tasks = taskMatcher.updateDeco(update2, this.tasks);
|
|
2160
|
-
}
|
|
2161
|
-
}, {
|
|
2162
|
-
decorations: (value) => value.tasks,
|
|
2163
|
-
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2164
|
-
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
2165
|
-
})
|
|
2166
|
-
});
|
|
2167
2221
|
return [
|
|
2168
|
-
|
|
2222
|
+
ViewPlugin6.fromClass(class {
|
|
2223
|
+
constructor(view) {
|
|
2224
|
+
this.decorations = buildDecorations4(view);
|
|
2225
|
+
}
|
|
2226
|
+
update(update2) {
|
|
2227
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2228
|
+
this.decorations = buildDecorations4(update2.view);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
}, {
|
|
2232
|
+
decorations: (v) => v.decorations
|
|
2233
|
+
}),
|
|
2169
2234
|
styles5
|
|
2170
2235
|
];
|
|
2171
2236
|
};
|
|
@@ -2227,27 +2292,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2227
2292
|
];
|
|
2228
2293
|
};
|
|
2229
2294
|
|
|
2230
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2231
|
-
import { yCollab } from "y-codemirror.next";
|
|
2232
|
-
|
|
2233
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2234
|
-
import * as Y from "yjs";
|
|
2235
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2236
|
-
var cursorConverter2 = (text) => ({
|
|
2237
|
-
toCursor: (index, assoc) => {
|
|
2238
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2239
|
-
},
|
|
2240
|
-
fromCursor: (cursor) => {
|
|
2241
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2242
|
-
}
|
|
2243
|
-
});
|
|
2244
|
-
|
|
2245
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2246
|
-
var yjs = (content, awareness2) => [
|
|
2247
|
-
CursorConverter.of(cursorConverter2(content)),
|
|
2248
|
-
yCollab(content, awareness2)
|
|
2249
|
-
];
|
|
2250
|
-
|
|
2251
2295
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2252
2296
|
import get3 from "lodash.get";
|
|
2253
2297
|
var defaultTheme = {
|
|
@@ -2341,33 +2385,6 @@ var defaultTheme = {
|
|
|
2341
2385
|
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2342
2386
|
},
|
|
2343
2387
|
//
|
|
2344
|
-
// collaboration
|
|
2345
|
-
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
2346
|
-
//
|
|
2347
|
-
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
2348
|
-
mixBlendMode: "multiply"
|
|
2349
|
-
},
|
|
2350
|
-
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2351
|
-
mixBlendMode: "screen"
|
|
2352
|
-
},
|
|
2353
|
-
".cm-ySelectionInfo": {
|
|
2354
|
-
padding: "2px 4px",
|
|
2355
|
-
marginBlockStart: "-4px"
|
|
2356
|
-
},
|
|
2357
|
-
".cm-ySelection, & .cm-selectionMatch": {
|
|
2358
|
-
paddingBlockStart: ".15em",
|
|
2359
|
-
paddingBlockEnd: ".15em"
|
|
2360
|
-
},
|
|
2361
|
-
".cm-ySelectionCaret": {
|
|
2362
|
-
display: "inline-block",
|
|
2363
|
-
insetBlockStart: ".1em",
|
|
2364
|
-
blockSize: "1.4em",
|
|
2365
|
-
verticalAlign: "top"
|
|
2366
|
-
},
|
|
2367
|
-
".cm-yLineSelection": {
|
|
2368
|
-
margin: 0
|
|
2369
|
-
},
|
|
2370
|
-
//
|
|
2371
2388
|
// link
|
|
2372
2389
|
//
|
|
2373
2390
|
".cm-link": {
|
|
@@ -2404,13 +2421,6 @@ var defaultTheme = {
|
|
|
2404
2421
|
textDecoration: "none"
|
|
2405
2422
|
},
|
|
2406
2423
|
//
|
|
2407
|
-
// widgets
|
|
2408
|
-
//
|
|
2409
|
-
".cm-widgetBuffer": {
|
|
2410
|
-
display: "none",
|
|
2411
|
-
height: 0
|
|
2412
|
-
},
|
|
2413
|
-
//
|
|
2414
2424
|
// table
|
|
2415
2425
|
//
|
|
2416
2426
|
".cm-table *": {
|
|
@@ -2441,27 +2451,17 @@ var defaultTheme = {
|
|
|
2441
2451
|
},
|
|
2442
2452
|
//
|
|
2443
2453
|
// font size
|
|
2444
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2454
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2455
|
+
// but it's far more verbose than it needs to be.
|
|
2445
2456
|
//
|
|
2446
|
-
...Object.keys(
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
|
|
2455
|
-
height
|
|
2456
|
-
};
|
|
2457
|
-
acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
|
|
2458
|
-
height
|
|
2459
|
-
};
|
|
2460
|
-
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
|
|
2461
|
-
height
|
|
2462
|
-
};
|
|
2463
|
-
return acc;
|
|
2464
|
-
}, {}),
|
|
2457
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2458
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2459
|
+
//
|
|
2460
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2461
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2462
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2463
|
+
// return acc;
|
|
2464
|
+
// }, {}),
|
|
2465
2465
|
/**
|
|
2466
2466
|
* Panels
|
|
2467
2467
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2512,7 +2512,9 @@ var textTheme = {
|
|
|
2512
2512
|
}
|
|
2513
2513
|
};
|
|
2514
2514
|
var markdownTheme = {
|
|
2515
|
-
|
|
2515
|
+
".cm-scroller": {
|
|
2516
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2517
|
+
},
|
|
2516
2518
|
".cm-placeholder": {
|
|
2517
2519
|
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2518
2520
|
}
|
|
@@ -2527,95 +2529,89 @@ var codeTheme = {
|
|
|
2527
2529
|
};
|
|
2528
2530
|
|
|
2529
2531
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2532
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2530
2533
|
var EditorModes = [
|
|
2531
2534
|
"default",
|
|
2532
2535
|
"vim"
|
|
2533
2536
|
];
|
|
2534
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2535
|
-
const { themeMode } = useThemeContext();
|
|
2537
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2536
2538
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2537
2539
|
tabBehavior: "limited"
|
|
2538
2540
|
});
|
|
2539
|
-
const
|
|
2540
|
-
const
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
state,
|
|
2541
|
+
const { themeMode } = useThemeContext();
|
|
2542
|
+
const rootRef = useRef(null);
|
|
2543
|
+
const [view, setView] = useState(null);
|
|
2544
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2544
2545
|
view
|
|
2545
|
-
}), [
|
|
2546
|
-
view,
|
|
2547
|
-
state,
|
|
2548
|
-
root
|
|
2549
|
-
]);
|
|
2550
|
-
const { awareness: awareness2, peer } = model;
|
|
2551
|
-
useEffect(() => {
|
|
2552
|
-
if (awareness2 && peer) {
|
|
2553
|
-
awareness2.setLocalStateField("user", {
|
|
2554
|
-
name: peer.name ?? generateName(peer.id),
|
|
2555
|
-
color: getColorForValue({
|
|
2556
|
-
value: peer.id,
|
|
2557
|
-
type: "color"
|
|
2558
|
-
}),
|
|
2559
|
-
colorLight: getColorForValue({
|
|
2560
|
-
value: peer.id,
|
|
2561
|
-
themeMode,
|
|
2562
|
-
type: "highlight"
|
|
2563
|
-
})
|
|
2564
|
-
});
|
|
2565
|
-
}
|
|
2566
|
-
}, [
|
|
2567
|
-
awareness2,
|
|
2568
|
-
peer,
|
|
2569
|
-
themeMode
|
|
2570
2546
|
]);
|
|
2571
|
-
|
|
2572
|
-
if (
|
|
2573
|
-
view
|
|
2574
|
-
effects: setCommentRange.of({
|
|
2575
|
-
model,
|
|
2576
|
-
comments: comments2
|
|
2577
|
-
})
|
|
2578
|
-
});
|
|
2547
|
+
useEffect2(() => {
|
|
2548
|
+
if (autoFocus) {
|
|
2549
|
+
view?.focus();
|
|
2579
2550
|
}
|
|
2580
2551
|
}, [
|
|
2581
2552
|
view,
|
|
2582
|
-
|
|
2553
|
+
autoFocus
|
|
2583
2554
|
]);
|
|
2584
|
-
|
|
2585
|
-
if (!
|
|
2555
|
+
useEffect2(() => {
|
|
2556
|
+
if (!model || !rootRef.current) {
|
|
2586
2557
|
return;
|
|
2587
2558
|
}
|
|
2588
|
-
const
|
|
2559
|
+
const state = EditorState2.create({
|
|
2589
2560
|
doc: model.text(),
|
|
2561
|
+
selection,
|
|
2590
2562
|
extensions: [
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2563
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2564
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2565
|
+
log2.catch(err, void 0, {
|
|
2566
|
+
F: __dxlog_file5,
|
|
2567
|
+
L: 123,
|
|
2568
|
+
S: void 0,
|
|
2569
|
+
C: (f, a) => f(...a)
|
|
2570
|
+
});
|
|
2571
|
+
}),
|
|
2594
2572
|
// Theme.
|
|
2595
|
-
// TODO(burdon): Make
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2573
|
+
// TODO(burdon): Make configurable.
|
|
2574
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2575
|
+
EditorView13.theme(theme ?? {}),
|
|
2576
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2577
|
+
EditorView13.editorAttributes.of({
|
|
2578
|
+
class: slots.editor?.className ?? ""
|
|
2579
|
+
}),
|
|
2580
|
+
EditorView13.contentAttributes.of({
|
|
2581
|
+
class: slots.content?.className ?? ""
|
|
2582
|
+
}),
|
|
2583
|
+
// State.
|
|
2584
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2599
2585
|
// Storage and replication.
|
|
2586
|
+
// NOTE: This must come before user extensions.
|
|
2600
2587
|
model.extension,
|
|
2588
|
+
// TODO(burdon): Factor out (requires special handling for Escape/focus).
|
|
2589
|
+
editorMode === "vim" && vim(),
|
|
2601
2590
|
// Custom.
|
|
2602
2591
|
...extensions
|
|
2603
2592
|
].filter(Boolean)
|
|
2604
2593
|
});
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2594
|
+
const newView = new EditorView13({
|
|
2595
|
+
state,
|
|
2596
|
+
parent: rootRef.current,
|
|
2597
|
+
scrollTo,
|
|
2598
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2599
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2600
|
+
dispatchTransactions: (trs, view2) => {
|
|
2601
|
+
if (debug) {
|
|
2602
|
+
logChanges(trs);
|
|
2603
|
+
}
|
|
2604
|
+
view2.update(trs);
|
|
2605
|
+
}
|
|
2612
2606
|
});
|
|
2607
|
+
view?.destroy();
|
|
2608
|
+
setView(newView);
|
|
2613
2609
|
return () => {
|
|
2614
|
-
|
|
2615
|
-
|
|
2610
|
+
newView?.destroy();
|
|
2611
|
+
setView(null);
|
|
2616
2612
|
};
|
|
2617
2613
|
}, [
|
|
2618
|
-
|
|
2614
|
+
rootRef,
|
|
2619
2615
|
model,
|
|
2620
2616
|
readonly,
|
|
2621
2617
|
editorMode,
|
|
@@ -2625,11 +2621,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2625
2621
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2626
2622
|
switch (key) {
|
|
2627
2623
|
case "Enter": {
|
|
2628
|
-
view?.
|
|
2624
|
+
view?.focus();
|
|
2629
2625
|
break;
|
|
2630
2626
|
}
|
|
2631
2627
|
case "Escape": {
|
|
2632
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2628
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2629
|
+
rootRef.current?.focus();
|
|
2630
|
+
}
|
|
2633
2631
|
break;
|
|
2634
2632
|
}
|
|
2635
2633
|
}
|
|
@@ -2639,83 +2637,79 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2639
2637
|
]);
|
|
2640
2638
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2641
2639
|
key: model.id,
|
|
2642
|
-
|
|
2640
|
+
role: "none",
|
|
2643
2641
|
tabIndex: 0,
|
|
2644
|
-
|
|
2642
|
+
onKeyUp: handleKeyUp,
|
|
2643
|
+
...slots.root,
|
|
2645
2644
|
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2646
|
-
|
|
2645
|
+
ref: rootRef
|
|
2647
2646
|
});
|
|
2648
2647
|
});
|
|
2649
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2648
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2650
2649
|
const { themeMode } = useThemeContext();
|
|
2651
|
-
const
|
|
2650
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2652
2651
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2653
2652
|
ref: forwardedRef,
|
|
2654
2653
|
readonly,
|
|
2655
2654
|
extensions: [
|
|
2656
2655
|
basicBundle({
|
|
2657
|
-
readonly,
|
|
2658
2656
|
themeMode,
|
|
2659
|
-
placeholder:
|
|
2657
|
+
placeholder: placeholder3,
|
|
2658
|
+
lineWrapping
|
|
2660
2659
|
}),
|
|
2661
2660
|
...extensions
|
|
2662
2661
|
],
|
|
2663
|
-
|
|
2662
|
+
theme,
|
|
2663
|
+
slots: updatedSlots,
|
|
2664
2664
|
...props
|
|
2665
2665
|
});
|
|
2666
2666
|
});
|
|
2667
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2667
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2668
2668
|
const { themeMode } = useThemeContext();
|
|
2669
|
-
const
|
|
2669
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2670
2670
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2671
2671
|
ref: forwardedRef,
|
|
2672
2672
|
readonly,
|
|
2673
2673
|
extensions: [
|
|
2674
2674
|
markdownBundle({
|
|
2675
|
-
readonly,
|
|
2676
2675
|
themeMode,
|
|
2677
|
-
|
|
2676
|
+
readonly,
|
|
2677
|
+
placeholder: placeholder3
|
|
2678
2678
|
}),
|
|
2679
2679
|
...extensions
|
|
2680
2680
|
],
|
|
2681
|
-
|
|
2681
|
+
theme,
|
|
2682
|
+
slots: updatedSlots,
|
|
2682
2683
|
...props
|
|
2683
2684
|
});
|
|
2684
2685
|
});
|
|
2685
2686
|
var defaultSlots = {
|
|
2686
2687
|
root: {
|
|
2687
|
-
|
|
2688
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
2689
|
+
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
2690
|
+
},
|
|
2691
|
+
editor: {
|
|
2692
|
+
className: "h-full p-2"
|
|
2688
2693
|
}
|
|
2689
2694
|
};
|
|
2690
2695
|
var defaultTextSlots = {
|
|
2691
|
-
...defaultSlots
|
|
2692
|
-
editor: {
|
|
2693
|
-
theme: textTheme
|
|
2694
|
-
}
|
|
2696
|
+
...defaultSlots
|
|
2695
2697
|
};
|
|
2696
2698
|
var defaultMarkdownSlots = {
|
|
2697
|
-
...defaultSlots
|
|
2698
|
-
editor: {
|
|
2699
|
-
theme: markdownTheme
|
|
2700
|
-
}
|
|
2699
|
+
...defaultSlots
|
|
2701
2700
|
};
|
|
2702
2701
|
|
|
2703
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2704
|
-
import get4 from "lodash.get";
|
|
2705
|
-
import { getRawDoc } from "@dxos/echo-schema";
|
|
2706
|
-
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2707
|
-
|
|
2708
2702
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2709
2703
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2710
2704
|
import { Context as Context2 } from "@dxos/context";
|
|
2711
|
-
import { invariant as
|
|
2705
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2712
2706
|
import { log as log3 } from "@dxos/log";
|
|
2713
|
-
var
|
|
2707
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2714
2708
|
var DEBOUNCE_INTERVAL = 100;
|
|
2715
2709
|
var SpaceAwarenessProvider = class {
|
|
2716
2710
|
constructor(params) {
|
|
2717
|
-
this.remoteStateChange = new Event2();
|
|
2718
2711
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
2712
|
+
this.remoteStateChange = new Event2();
|
|
2719
2713
|
this._space = params.space;
|
|
2720
2714
|
this._channel = params.channel;
|
|
2721
2715
|
this._peerId = params.peerId;
|
|
@@ -2732,7 +2726,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2732
2726
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2733
2727
|
}
|
|
2734
2728
|
});
|
|
2735
|
-
|
|
2729
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2736
2730
|
switch (message.payload.kind) {
|
|
2737
2731
|
case "query": {
|
|
2738
2732
|
this._handleQueryMessage();
|
|
@@ -2743,16 +2737,15 @@ var SpaceAwarenessProvider = class {
|
|
|
2743
2737
|
break;
|
|
2744
2738
|
}
|
|
2745
2739
|
}
|
|
2746
|
-
});
|
|
2747
|
-
this._ctx.onDispose(unsubscribe);
|
|
2740
|
+
}));
|
|
2748
2741
|
void this._space.postMessage(this._channel, {
|
|
2749
2742
|
kind: "query"
|
|
2750
2743
|
}).catch((err) => {
|
|
2751
2744
|
log3.debug("failed to query awareness", {
|
|
2752
2745
|
err
|
|
2753
2746
|
}, {
|
|
2754
|
-
F:
|
|
2755
|
-
L:
|
|
2747
|
+
F: __dxlog_file6,
|
|
2748
|
+
L: 89,
|
|
2756
2749
|
S: this,
|
|
2757
2750
|
C: (f, a) => f(...a)
|
|
2758
2751
|
});
|
|
@@ -2763,10 +2756,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2763
2756
|
this._ctx = void 0;
|
|
2764
2757
|
this._postTask = void 0;
|
|
2765
2758
|
}
|
|
2759
|
+
getRemoteStates() {
|
|
2760
|
+
return Array.from(this._remoteStates.values());
|
|
2761
|
+
}
|
|
2766
2762
|
update(position) {
|
|
2767
|
-
|
|
2768
|
-
F:
|
|
2769
|
-
L:
|
|
2763
|
+
invariant4(this._postTask, void 0, {
|
|
2764
|
+
F: __dxlog_file6,
|
|
2765
|
+
L: 104,
|
|
2770
2766
|
S: this,
|
|
2771
2767
|
A: [
|
|
2772
2768
|
"this._postTask",
|
|
@@ -2780,13 +2776,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2780
2776
|
};
|
|
2781
2777
|
this._postTask.schedule();
|
|
2782
2778
|
}
|
|
2783
|
-
getRemoteStates() {
|
|
2784
|
-
return Array.from(this._remoteStates.values());
|
|
2785
|
-
}
|
|
2786
2779
|
_handleQueryMessage() {
|
|
2787
|
-
|
|
2788
|
-
F:
|
|
2789
|
-
L:
|
|
2780
|
+
invariant4(this._postTask, void 0, {
|
|
2781
|
+
F: __dxlog_file6,
|
|
2782
|
+
L: 115,
|
|
2790
2783
|
S: this,
|
|
2791
2784
|
A: [
|
|
2792
2785
|
"this._postTask",
|
|
@@ -2796,9 +2789,9 @@ var SpaceAwarenessProvider = class {
|
|
|
2796
2789
|
this._postTask.schedule();
|
|
2797
2790
|
}
|
|
2798
2791
|
_handlePostMessage(message) {
|
|
2799
|
-
|
|
2800
|
-
F:
|
|
2801
|
-
L:
|
|
2792
|
+
invariant4(message.kind === "post", void 0, {
|
|
2793
|
+
F: __dxlog_file6,
|
|
2794
|
+
L: 120,
|
|
2802
2795
|
S: this,
|
|
2803
2796
|
A: [
|
|
2804
2797
|
"message.kind === 'post'",
|
|
@@ -2810,201 +2803,54 @@ var SpaceAwarenessProvider = class {
|
|
|
2810
2803
|
}
|
|
2811
2804
|
};
|
|
2812
2805
|
|
|
2813
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2806
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2814
2807
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2815
|
-
|
|
2816
|
-
|
|
2808
|
+
var modelState = StateField5.define({
|
|
2809
|
+
create: () => void 0,
|
|
2810
|
+
update: (model) => model
|
|
2811
|
+
});
|
|
2817
2812
|
|
|
2818
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2819
|
-
import
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
import { log as log4 } from "@dxos/log";
|
|
2826
|
-
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2827
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2828
|
-
var createYjsModel = ({ identity, space, text }) => {
|
|
2829
|
-
invariant4(text?.doc && text?.content, void 0, {
|
|
2830
|
-
F: __dxlog_file5,
|
|
2831
|
-
L: 23,
|
|
2832
|
-
S: void 0,
|
|
2833
|
-
A: [
|
|
2834
|
-
"text?.doc && text?.content",
|
|
2835
|
-
""
|
|
2836
|
-
]
|
|
2837
|
-
});
|
|
2838
|
-
const provider = space ? new YAwarenessProvider({
|
|
2839
|
-
space,
|
|
2840
|
-
doc: text.doc,
|
|
2841
|
-
channel: `yjs.awareness.${text.id}`
|
|
2842
|
-
}) : void 0;
|
|
2843
|
-
const model = {
|
|
2844
|
-
id: text.doc.guid,
|
|
2845
|
-
content: text.content,
|
|
2846
|
-
text: () => text.content.toString(),
|
|
2847
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2848
|
-
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2849
|
-
getCursorFromRange: (range) => {
|
|
2850
|
-
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2851
|
-
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2852
|
-
return [
|
|
2853
|
-
arrayToString2(from),
|
|
2854
|
-
arrayToString2(to)
|
|
2855
|
-
].join(":");
|
|
2856
|
-
},
|
|
2857
|
-
getRangeFromCursor: (cursor) => {
|
|
2858
|
-
invariant4(text.doc, void 0, {
|
|
2859
|
-
F: __dxlog_file5,
|
|
2860
|
-
L: 40,
|
|
2861
|
-
S: void 0,
|
|
2862
|
-
A: [
|
|
2863
|
-
"text.doc",
|
|
2864
|
-
""
|
|
2865
|
-
]
|
|
2866
|
-
});
|
|
2867
|
-
const parts = cursor.split(":");
|
|
2868
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2869
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2870
|
-
return from && to ? {
|
|
2871
|
-
from: from.index,
|
|
2872
|
-
to: to.index
|
|
2873
|
-
} : void 0;
|
|
2813
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
2814
|
+
import { useState as useState2 } from "react";
|
|
2815
|
+
var useTextEditor = () => {
|
|
2816
|
+
const [view, setView] = useState2(null);
|
|
2817
|
+
return [
|
|
2818
|
+
(ref) => {
|
|
2819
|
+
setView(ref);
|
|
2874
2820
|
},
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
yjs(text.content, provider?.awareness)
|
|
2878
|
-
],
|
|
2879
|
-
awareness: provider?.awareness,
|
|
2880
|
-
peer: identity ? {
|
|
2881
|
-
id: identity.identityKey.toHex(),
|
|
2882
|
-
name: identity.profile?.displayName
|
|
2883
|
-
} : void 0
|
|
2884
|
-
};
|
|
2885
|
-
return model;
|
|
2886
|
-
};
|
|
2887
|
-
var messageAwareness = 1;
|
|
2888
|
-
var messageQueryAwareness = 3;
|
|
2889
|
-
var YAwarenessProvider = class extends Observable {
|
|
2890
|
-
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2891
|
-
super();
|
|
2892
|
-
this._space = space;
|
|
2893
|
-
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2894
|
-
this._channel = channel;
|
|
2895
|
-
this._clientId = doc.clientID;
|
|
2896
|
-
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
2897
|
-
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
2898
|
-
if (typeof window !== "undefined") {
|
|
2899
|
-
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
2900
|
-
} else if (typeof process !== "undefined") {
|
|
2901
|
-
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
2902
|
-
}
|
|
2903
|
-
const encoderAwarenessQuery = encoding.createEncoder();
|
|
2904
|
-
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
2905
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
2906
|
-
const encoderAwarenessState = encoding.createEncoder();
|
|
2907
|
-
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
2908
|
-
encoding.writeVarUint8Array(encoderAwarenessState, YP.encodeAwarenessUpdate(this.awareness, [
|
|
2909
|
-
this._clientId
|
|
2910
|
-
]));
|
|
2911
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
2912
|
-
}
|
|
2913
|
-
get awareness() {
|
|
2914
|
-
return this._awareness;
|
|
2915
|
-
}
|
|
2916
|
-
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2917
|
-
log4("awareness update", {
|
|
2918
|
-
added,
|
|
2919
|
-
updated,
|
|
2920
|
-
removed,
|
|
2921
|
-
origin
|
|
2922
|
-
}, {
|
|
2923
|
-
F: __dxlog_file5,
|
|
2924
|
-
L: 122,
|
|
2925
|
-
S: this,
|
|
2926
|
-
C: (f, a) => f(...a)
|
|
2927
|
-
});
|
|
2928
|
-
const changedClients = added.concat(updated).concat(removed);
|
|
2929
|
-
const encoderAwareness = encoding.createEncoder();
|
|
2930
|
-
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
2931
|
-
encoding.writeVarUint8Array(encoderAwareness, YP.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
2932
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2933
|
-
}
|
|
2934
|
-
_handleSpaceMessage({ payload }) {
|
|
2935
|
-
log4("space message", payload, {
|
|
2936
|
-
F: __dxlog_file5,
|
|
2937
|
-
L: 131,
|
|
2938
|
-
S: this,
|
|
2939
|
-
C: (f, a) => f(...a)
|
|
2940
|
-
});
|
|
2941
|
-
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2942
|
-
const encoder = this._readMessage(data);
|
|
2943
|
-
if (encoder) {
|
|
2944
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
2945
|
-
}
|
|
2946
|
-
}
|
|
2947
|
-
_readMessage(message) {
|
|
2948
|
-
const decoder = decoding.createDecoder(message);
|
|
2949
|
-
const encoder = encoding.createEncoder();
|
|
2950
|
-
const messageType = decoding.readVarUint(decoder);
|
|
2951
|
-
let sendReply = false;
|
|
2952
|
-
switch (messageType) {
|
|
2953
|
-
case messageAwareness: {
|
|
2954
|
-
YP.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
2955
|
-
break;
|
|
2956
|
-
}
|
|
2957
|
-
case messageQueryAwareness: {
|
|
2958
|
-
encoding.writeVarUint(encoder, messageAwareness);
|
|
2959
|
-
encoding.writeVarUint8Array(encoder, YP.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
2960
|
-
sendReply = true;
|
|
2961
|
-
break;
|
|
2962
|
-
}
|
|
2963
|
-
default: {
|
|
2964
|
-
console.error("Invalid message:", messageType);
|
|
2965
|
-
return encoder;
|
|
2966
|
-
}
|
|
2967
|
-
}
|
|
2968
|
-
if (!sendReply) {
|
|
2969
|
-
return null;
|
|
2970
|
-
}
|
|
2971
|
-
return encoder;
|
|
2972
|
-
}
|
|
2973
|
-
_handleBeforeUnload() {
|
|
2974
|
-
YP.removeAwarenessStates(this._awareness, [
|
|
2975
|
-
this._clientId
|
|
2976
|
-
], "window unload");
|
|
2977
|
-
}
|
|
2821
|
+
view
|
|
2822
|
+
];
|
|
2978
2823
|
};
|
|
2979
2824
|
|
|
2980
2825
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
}
|
|
2826
|
+
import get4 from "lodash.get";
|
|
2827
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
2828
|
+
import { generateName } from "@dxos/display-name";
|
|
2829
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
2830
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
2831
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2832
|
+
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2833
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2985
2834
|
var useTextModel = (props) => {
|
|
2986
2835
|
const { identity, space, text } = props;
|
|
2987
|
-
const [model, setModel] =
|
|
2988
|
-
|
|
2836
|
+
const [model, setModel] = useState3();
|
|
2837
|
+
useEffect3(() => setModel(createModel(props)), [
|
|
2989
2838
|
identity,
|
|
2990
2839
|
space,
|
|
2991
2840
|
text
|
|
2992
2841
|
]);
|
|
2993
2842
|
return model;
|
|
2994
2843
|
};
|
|
2995
|
-
var createModel = (
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
};
|
|
3005
|
-
|
|
3006
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
3007
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2844
|
+
var createModel = ({ space, identity, text }) => {
|
|
2845
|
+
invariant5(isAutomergeObject(text), void 0, {
|
|
2846
|
+
F: __dxlog_file7,
|
|
2847
|
+
L: 35,
|
|
2848
|
+
S: void 0,
|
|
2849
|
+
A: [
|
|
2850
|
+
"isAutomergeObject(text)",
|
|
2851
|
+
""
|
|
2852
|
+
]
|
|
2853
|
+
});
|
|
3008
2854
|
const obj = text;
|
|
3009
2855
|
const doc = getRawDoc(obj, [
|
|
3010
2856
|
obj.field
|
|
@@ -3013,7 +2859,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3013
2859
|
space,
|
|
3014
2860
|
channel: `automerge.awareness.${obj.id}`,
|
|
3015
2861
|
info: {
|
|
3016
|
-
displayName: identity
|
|
2862
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
3017
2863
|
color: cursorColor.color,
|
|
3018
2864
|
lightColor: cursorColor.light
|
|
3019
2865
|
},
|
|
@@ -3023,7 +2869,6 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3023
2869
|
id: obj.id,
|
|
3024
2870
|
content: doc,
|
|
3025
2871
|
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3026
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3027
2872
|
extension: [
|
|
3028
2873
|
modelState.init(() => model),
|
|
3029
2874
|
automerge3({
|
|
@@ -3043,7 +2888,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3043
2888
|
export {
|
|
3044
2889
|
AwarenessProvider,
|
|
3045
2890
|
BaseTextEditor,
|
|
3046
|
-
|
|
2891
|
+
Cursor,
|
|
3047
2892
|
Doc,
|
|
3048
2893
|
EditorModes,
|
|
3049
2894
|
MarkdownEditor,
|
|
@@ -3051,7 +2896,6 @@ export {
|
|
|
3051
2896
|
SpaceAwarenessProvider,
|
|
3052
2897
|
TextEditor,
|
|
3053
2898
|
TextKind,
|
|
3054
|
-
YAwarenessProvider,
|
|
3055
2899
|
YText,
|
|
3056
2900
|
YXmlFragment,
|
|
3057
2901
|
autocomplete,
|
|
@@ -3063,9 +2907,6 @@ export {
|
|
|
3063
2907
|
code2 as code,
|
|
3064
2908
|
codeTheme,
|
|
3065
2909
|
comments,
|
|
3066
|
-
createAutomergeModel,
|
|
3067
|
-
createYjsModel,
|
|
3068
|
-
cursorConverter,
|
|
3069
2910
|
defaultMarkdownSlots,
|
|
3070
2911
|
defaultOptions,
|
|
3071
2912
|
defaultSlots,
|
|
@@ -3076,6 +2917,7 @@ export {
|
|
|
3076
2917
|
image,
|
|
3077
2918
|
link,
|
|
3078
2919
|
listener,
|
|
2920
|
+
logChanges,
|
|
3079
2921
|
markdownBundle,
|
|
3080
2922
|
markdownHighlightStyle,
|
|
3081
2923
|
markdownTags,
|
|
@@ -3083,7 +2925,8 @@ export {
|
|
|
3083
2925
|
markdownTheme,
|
|
3084
2926
|
mention,
|
|
3085
2927
|
modelState,
|
|
3086
|
-
|
|
2928
|
+
outliner,
|
|
2929
|
+
setComments,
|
|
3087
2930
|
setFocus,
|
|
3088
2931
|
setSelection,
|
|
3089
2932
|
table,
|
|
@@ -3091,7 +2934,8 @@ export {
|
|
|
3091
2934
|
tasklist,
|
|
3092
2935
|
textTheme,
|
|
3093
2936
|
typewriter,
|
|
3094
|
-
|
|
3095
|
-
|
|
2937
|
+
useComments,
|
|
2938
|
+
useTextEditor,
|
|
2939
|
+
useTextModel
|
|
3096
2940
|
};
|
|
3097
2941
|
//# sourceMappingURL=index.mjs.map
|