@dxos/react-ui-editor 0.3.11-main.927e4ba → 0.3.11-main.9b81c36
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 +1267 -662
- 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 +1 -2
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/{comments.stories.d.ts → hooks.stories.d.ts} +9 -12
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +25 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +23 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/index.d.ts +2 -0
- package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/defs.d.ts +5 -5
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +2 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness.d.ts +1 -1
- package/dist/types/src/extensions/basic.d.ts +1 -1
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +6 -2
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -6
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +2 -2
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +13 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +8 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +4 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -0
- package/dist/types/src/hooks/useEditorView.d.ts +17 -0
- package/dist/types/src/hooks/useEditorView.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +36 -14
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +12 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +2 -2
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/package.json +39 -26
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +14 -18
- package/src/components/TextEditor/TextEditor.tsx +27 -16
- package/src/components/TextEditor/automerge.stories.tsx +1 -2
- package/src/components/TextEditor/hooks.stories.tsx +106 -0
- package/src/components/Toolbar/Toolbar.stories.tsx +90 -0
- package/src/components/Toolbar/Toolbar.tsx +166 -0
- package/src/components/Toolbar/index.ts +5 -0
- package/src/components/index.ts +1 -0
- package/src/extensions/automerge/automerge.spec.tsx +76 -0
- package/src/extensions/automerge/automerge.test.ts +13 -0
- package/src/extensions/automerge/automerge.ts +26 -11
- package/src/extensions/automerge/cursor.ts +3 -3
- package/src/extensions/automerge/defs.ts +9 -9
- package/src/extensions/automerge/semaphore.ts +17 -19
- package/src/extensions/automerge/update-automerge.ts +12 -6
- package/src/extensions/automerge/update-codemirror.ts +5 -5
- package/src/extensions/awareness.ts +7 -4
- package/src/extensions/basic.ts +15 -13
- package/src/extensions/blast.ts +4 -1
- package/src/extensions/comments.ts +113 -65
- package/src/extensions/index.ts +0 -6
- package/src/extensions/markdown/bundle.ts +9 -8
- package/src/extensions/markdown/code.ts +150 -0
- package/src/extensions/markdown/formatting.ts +188 -0
- package/src/extensions/markdown/heading.ts +59 -0
- package/src/extensions/markdown/highlight.ts +9 -15
- package/src/extensions/{hr.ts → markdown/hr.ts} +3 -4
- package/src/extensions/markdown/index.ts +8 -0
- package/src/extensions/{link.ts → markdown/link.ts} +13 -4
- package/src/extensions/{tasklist.ts → markdown/tasklist.ts} +2 -3
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useActionHandler.ts +62 -0
- package/src/hooks/useEditorView.ts +29 -0
- package/src/hooks/useTextEditor.ts +143 -19
- package/src/hooks/useTextModel.ts +28 -9
- package/src/index.ts +1 -1
- package/src/styles/markdown.ts +9 -10
- package/src/themes/default.ts +9 -6
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/src/components/TextEditor/comments.stories.tsx +0 -357
- package/src/extensions/code.ts +0 -104
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
- /package/src/extensions/{image.ts → markdown/image.ts} +0 -0
- /package/src/extensions/{table.ts → markdown/table.ts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// packages/ui/react-ui-editor/src/index.ts
|
|
2
2
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
3
3
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
4
|
+
import { keymap as keymap7 } from "@codemirror/view";
|
|
4
5
|
|
|
5
6
|
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
6
7
|
import { tags as tags2 } from "@lezer/highlight";
|
|
@@ -8,13 +9,13 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
8
9
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
10
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
11
|
import { EditorView as EditorView13 } from "@codemirror/view";
|
|
11
|
-
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
14
|
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
15
15
|
import { log as log2 } from "@dxos/log";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
17
|
+
import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
18
19
|
|
|
19
20
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
21
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
@@ -53,14 +54,14 @@ var autocomplete = ({ onSearch }) => {
|
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
57
|
+
import { invertedEffects } from "@codemirror/commands";
|
|
56
58
|
import { StateField } from "@codemirror/state";
|
|
57
59
|
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
58
|
-
import { next as
|
|
59
|
-
import { invariant } from "@dxos/invariant";
|
|
60
|
+
import { next as A4 } from "@dxos/automerge/automerge";
|
|
60
61
|
|
|
61
62
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
62
63
|
import get from "lodash.get";
|
|
63
|
-
import { next as
|
|
64
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
64
65
|
var cursorConverter = (handle, path) => ({
|
|
65
66
|
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
66
67
|
toCursor: (pos) => {
|
|
@@ -72,7 +73,7 @@ var cursorConverter = (handle, path) => ({
|
|
|
72
73
|
if (typeof value === "string" && value.length <= pos) {
|
|
73
74
|
return "end";
|
|
74
75
|
}
|
|
75
|
-
return
|
|
76
|
+
return A.getCursor(doc, path.slice(), pos);
|
|
76
77
|
},
|
|
77
78
|
fromCursor: (cursor) => {
|
|
78
79
|
if (cursor === "") {
|
|
@@ -90,26 +91,28 @@ var cursorConverter = (handle, path) => ({
|
|
|
90
91
|
return 0;
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
|
-
return
|
|
94
|
+
return A.getCursorPosition(doc, path.slice(), cursor);
|
|
94
95
|
}
|
|
95
96
|
});
|
|
96
97
|
|
|
97
98
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
98
99
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
99
|
-
var effectType = StateEffect.define({});
|
|
100
|
-
var reconcileAnnotationType = Annotation.define();
|
|
101
100
|
var getPath = (state, field) => state.field(field).path;
|
|
102
101
|
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
103
|
-
var
|
|
102
|
+
var updateHeadsEffect = StateEffect.define({});
|
|
103
|
+
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
104
104
|
newHeads
|
|
105
105
|
});
|
|
106
|
-
var
|
|
106
|
+
var reconcileAnnotation = Annotation.define();
|
|
107
|
+
var isReconcile = (tr) => {
|
|
108
|
+
return !!tr.annotation(reconcileAnnotation);
|
|
109
|
+
};
|
|
107
110
|
|
|
108
111
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
109
|
-
import { next as
|
|
112
|
+
import { next as A3 } from "@dxos/automerge/automerge";
|
|
110
113
|
|
|
111
114
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
112
|
-
import { next as
|
|
115
|
+
import { next as A2 } from "@dxos/automerge/automerge";
|
|
113
116
|
var updateAutomerge = (field, handle, transactions, state) => {
|
|
114
117
|
const { lastHeads, path } = state.field(field);
|
|
115
118
|
let hasChanges = false;
|
|
@@ -122,11 +125,19 @@ var updateAutomerge = (field, handle, transactions, state) => {
|
|
|
122
125
|
return void 0;
|
|
123
126
|
}
|
|
124
127
|
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
128
|
+
const invertedTransactions = [];
|
|
125
129
|
for (const tr of transactions) {
|
|
126
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB,
|
|
127
|
-
|
|
130
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
|
|
131
|
+
invertedTransactions.push({
|
|
132
|
+
from: fromA,
|
|
133
|
+
del: toA - fromA,
|
|
134
|
+
insert
|
|
135
|
+
});
|
|
128
136
|
});
|
|
129
137
|
}
|
|
138
|
+
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
|
139
|
+
A2.splice(doc, path.slice(), from, del, insert.toString());
|
|
140
|
+
});
|
|
130
141
|
});
|
|
131
142
|
return newHeads ?? void 0;
|
|
132
143
|
};
|
|
@@ -141,13 +152,13 @@ var updateCodeMirror = (view, selection, target, patches) => {
|
|
|
141
152
|
selection = selection.map(changeSet, 1);
|
|
142
153
|
view.dispatch({
|
|
143
154
|
changes: changeSet,
|
|
144
|
-
annotations:
|
|
155
|
+
annotations: reconcileAnnotation.of(false)
|
|
145
156
|
});
|
|
146
157
|
}
|
|
147
158
|
}
|
|
148
159
|
view.dispatch({
|
|
149
160
|
selection,
|
|
150
|
-
annotations:
|
|
161
|
+
annotations: reconcileAnnotation.of(false)
|
|
151
162
|
});
|
|
152
163
|
};
|
|
153
164
|
var handlePatch = (patch, target, state) => {
|
|
@@ -168,7 +179,7 @@ var handleInsert = (target, patch) => {
|
|
|
168
179
|
if (index == null) {
|
|
169
180
|
return [];
|
|
170
181
|
}
|
|
171
|
-
const text = patch.values.map((
|
|
182
|
+
const text = patch.values.map((value) => value ? value.toString() : "").join("");
|
|
172
183
|
return [
|
|
173
184
|
{
|
|
174
185
|
from: index,
|
|
@@ -246,36 +257,37 @@ var PatchSemaphore = class {
|
|
|
246
257
|
this._state = _state;
|
|
247
258
|
this._inReconcile = false;
|
|
248
259
|
}
|
|
249
|
-
// NOTE: Cannot destruct view.state.
|
|
250
260
|
reconcile(view) {
|
|
251
|
-
if (this._inReconcile) {
|
|
252
|
-
|
|
261
|
+
if (!this._inReconcile) {
|
|
262
|
+
this._inReconcile = true;
|
|
263
|
+
this.doReconcile(view);
|
|
264
|
+
this._inReconcile = false;
|
|
253
265
|
}
|
|
254
|
-
|
|
266
|
+
}
|
|
267
|
+
doReconcile(view) {
|
|
255
268
|
const path = getPath(view.state, this._state);
|
|
256
269
|
const oldHeads = getLastHeads(view.state, this._state);
|
|
257
270
|
let selection = view.state.selection;
|
|
258
|
-
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !
|
|
271
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
259
272
|
const toInvert = transactions.slice().reverse();
|
|
260
|
-
for (const
|
|
261
|
-
const inverted =
|
|
273
|
+
for (const tr of toInvert) {
|
|
274
|
+
const inverted = tr.changes.invert(tr.startState.doc);
|
|
262
275
|
selection = selection.map(inverted);
|
|
263
276
|
view.dispatch({
|
|
264
277
|
changes: inverted,
|
|
265
|
-
annotations:
|
|
278
|
+
annotations: reconcileAnnotation.of(true)
|
|
266
279
|
});
|
|
267
280
|
}
|
|
268
281
|
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
269
282
|
if (newHeads === null || newHeads === void 0) {
|
|
270
|
-
newHeads =
|
|
283
|
+
newHeads = A3.getHeads(this._handle.docSync());
|
|
271
284
|
}
|
|
272
|
-
const diff =
|
|
285
|
+
const diff = A3.equals(oldHeads, newHeads) ? [] : A3.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
273
286
|
updateCodeMirror(view, selection, path, diff);
|
|
274
287
|
view.dispatch({
|
|
275
288
|
effects: updateHeads(newHeads),
|
|
276
|
-
annotations:
|
|
289
|
+
annotations: reconcileAnnotation.of(false)
|
|
277
290
|
});
|
|
278
|
-
this._inReconcile = false;
|
|
279
291
|
}
|
|
280
292
|
};
|
|
281
293
|
|
|
@@ -317,12 +329,11 @@ var Cursor = class _Cursor {
|
|
|
317
329
|
};
|
|
318
330
|
|
|
319
331
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
320
|
-
var
|
|
321
|
-
|
|
322
|
-
const state = StateField.define({
|
|
332
|
+
var automerge = ({ handle, path }) => {
|
|
333
|
+
const syncState = StateField.define({
|
|
323
334
|
create: () => ({
|
|
324
335
|
path: path.slice(),
|
|
325
|
-
lastHeads:
|
|
336
|
+
lastHeads: A4.getHeads(handle.docSync()),
|
|
326
337
|
unreconciledTransactions: []
|
|
327
338
|
}),
|
|
328
339
|
update: (value, tr) => {
|
|
@@ -333,7 +344,7 @@ var automerge3 = ({ handle, path }) => {
|
|
|
333
344
|
};
|
|
334
345
|
let clearUnreconciled = false;
|
|
335
346
|
for (const effect of tr.effects) {
|
|
336
|
-
if (effect.is(
|
|
347
|
+
if (effect.is(updateHeadsEffect)) {
|
|
337
348
|
result.lastHeads = effect.value.newHeads;
|
|
338
349
|
clearUnreconciled = true;
|
|
339
350
|
}
|
|
@@ -341,29 +352,21 @@ var automerge3 = ({ handle, path }) => {
|
|
|
341
352
|
if (clearUnreconciled) {
|
|
342
353
|
result.unreconciledTransactions = [];
|
|
343
354
|
} else {
|
|
344
|
-
if (!
|
|
355
|
+
if (!isReconcile(tr)) {
|
|
345
356
|
result.unreconciledTransactions.push(tr);
|
|
346
357
|
}
|
|
347
358
|
}
|
|
348
359
|
return result;
|
|
349
360
|
}
|
|
350
361
|
});
|
|
351
|
-
const semaphore = new PatchSemaphore(handle,
|
|
362
|
+
const semaphore = new PatchSemaphore(handle, syncState);
|
|
352
363
|
return [
|
|
353
364
|
Cursor.converter.of(cursorConverter(handle, path)),
|
|
365
|
+
syncState,
|
|
354
366
|
// Reconcile external updates.
|
|
355
367
|
ViewPlugin.fromClass(class {
|
|
356
368
|
constructor(_view) {
|
|
357
369
|
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
|
-
]
|
|
366
|
-
});
|
|
367
370
|
handle.addListener("change", this._handleChange.bind(this));
|
|
368
371
|
}
|
|
369
372
|
destroy() {
|
|
@@ -379,7 +382,17 @@ var automerge3 = ({ handle, path }) => {
|
|
|
379
382
|
semaphore.reconcile(view);
|
|
380
383
|
}
|
|
381
384
|
}),
|
|
382
|
-
|
|
385
|
+
// TODO(burdon): Record undo transactions.
|
|
386
|
+
// See https://github.com/yjs/y-codemirror.next/tree/main
|
|
387
|
+
// https://codemirror.net/examples/inverted-effect
|
|
388
|
+
invertedEffects.of((tr) => {
|
|
389
|
+
const effects = [];
|
|
390
|
+
if (!tr.changes.empty) {
|
|
391
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
return effects;
|
|
395
|
+
})
|
|
383
396
|
];
|
|
384
397
|
};
|
|
385
398
|
|
|
@@ -398,13 +411,13 @@ var dummyProvider = {
|
|
|
398
411
|
update: () => {
|
|
399
412
|
}
|
|
400
413
|
};
|
|
401
|
-
var
|
|
414
|
+
var awarenessProvider = Facet2.define({
|
|
402
415
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
403
416
|
});
|
|
404
417
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
405
418
|
var awareness = (provider = dummyProvider) => {
|
|
406
419
|
return [
|
|
407
|
-
|
|
420
|
+
awarenessProvider.of(provider),
|
|
408
421
|
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
409
422
|
decorations: (value) => value.decorations
|
|
410
423
|
}),
|
|
@@ -418,7 +431,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
418
431
|
this._lastAnchor = void 0;
|
|
419
432
|
this._lastHead = void 0;
|
|
420
433
|
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
421
|
-
this._provider = view.state.facet(
|
|
434
|
+
this._provider = view.state.facet(awarenessProvider);
|
|
422
435
|
this._provider.open();
|
|
423
436
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
424
437
|
view.dispatch({
|
|
@@ -624,24 +637,25 @@ import { history } from "@codemirror/commands";
|
|
|
624
637
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
625
638
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
626
639
|
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
627
|
-
|
|
628
|
-
|
|
640
|
+
import { isNotFalsy } from "@dxos/util";
|
|
641
|
+
var createBasicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => [
|
|
642
|
+
lineWrapping && EditorView3.lineWrapping,
|
|
629
643
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
630
644
|
bracketMatching(),
|
|
631
645
|
closeBrackets(),
|
|
632
646
|
drawSelection(),
|
|
633
647
|
highlightActiveLine(),
|
|
634
648
|
history(),
|
|
635
|
-
_placeholder
|
|
649
|
+
_placeholder && placeholder(_placeholder),
|
|
636
650
|
// https://github.com/codemirror/theme-one-dark
|
|
637
651
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
638
|
-
];
|
|
652
|
+
].filter(isNotFalsy);
|
|
639
653
|
|
|
640
654
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
641
655
|
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
642
656
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
643
|
-
import { invariant
|
|
644
|
-
var
|
|
657
|
+
import { invariant } from "@dxos/invariant";
|
|
658
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
645
659
|
var defaultOptions = {
|
|
646
660
|
effect: 2,
|
|
647
661
|
maxParticles: 200,
|
|
@@ -674,10 +688,10 @@ var blast = (options = defaultOptions) => {
|
|
|
674
688
|
const getPoint = (view, pos) => {
|
|
675
689
|
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
676
690
|
const element = document.elementFromPoint(x, y);
|
|
677
|
-
const { offsetLeft: left = 0, offsetTop:
|
|
691
|
+
const { offsetLeft: left = 0, offsetTop: top2 = 0 } = view.scrollDOM.parentElement ?? {};
|
|
678
692
|
const point = {
|
|
679
693
|
x: x - left,
|
|
680
|
-
y: y -
|
|
694
|
+
y: y - top2
|
|
681
695
|
};
|
|
682
696
|
return {
|
|
683
697
|
element,
|
|
@@ -767,9 +781,9 @@ var Blaster = class {
|
|
|
767
781
|
return this._node;
|
|
768
782
|
}
|
|
769
783
|
initialize() {
|
|
770
|
-
|
|
771
|
-
F:
|
|
772
|
-
L:
|
|
784
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
785
|
+
F: __dxlog_file,
|
|
786
|
+
L: 141,
|
|
773
787
|
S: this,
|
|
774
788
|
A: [
|
|
775
789
|
"!this._canvas && !this._ctx",
|
|
@@ -804,9 +818,9 @@ var Blaster = class {
|
|
|
804
818
|
}
|
|
805
819
|
}
|
|
806
820
|
start() {
|
|
807
|
-
|
|
808
|
-
F:
|
|
809
|
-
L:
|
|
821
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
822
|
+
F: __dxlog_file,
|
|
823
|
+
L: 180,
|
|
810
824
|
S: this,
|
|
811
825
|
A: [
|
|
812
826
|
"this._canvas && this._ctx",
|
|
@@ -947,9 +961,14 @@ var random = (min, max) => {
|
|
|
947
961
|
return min + ~~(Math.random() * (max - min + 1));
|
|
948
962
|
};
|
|
949
963
|
|
|
950
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
951
|
-
import {
|
|
952
|
-
import {
|
|
964
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
965
|
+
import { invertedEffects as invertedEffects2 } from "@codemirror/commands";
|
|
966
|
+
import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
967
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
968
|
+
import sortBy from "lodash.sortby";
|
|
969
|
+
import { useEffect } from "react";
|
|
970
|
+
import { debounce } from "@dxos/async";
|
|
971
|
+
import { nonNullable } from "@dxos/util";
|
|
953
972
|
|
|
954
973
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
955
974
|
import * as random2 from "lib0/random";
|
|
@@ -992,34 +1011,15 @@ var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
|
992
1011
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
993
1012
|
import { mx } from "@dxos/react-ui-theme";
|
|
994
1013
|
var headings = {
|
|
995
|
-
1:
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
1005
|
-
"-ml-[7px]"
|
|
1006
|
-
],
|
|
1007
|
-
4: [
|
|
1008
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
1009
|
-
"-ml-[6px]"
|
|
1010
|
-
],
|
|
1011
|
-
5: [
|
|
1012
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
1013
|
-
"-ml-[5px]"
|
|
1014
|
-
],
|
|
1015
|
-
6: [
|
|
1016
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
1017
|
-
"-ml-[4px]"
|
|
1018
|
-
]
|
|
1019
|
-
};
|
|
1020
|
-
var heading = (level, readonly) => {
|
|
1021
|
-
const [style, offset] = headings[level];
|
|
1022
|
-
return mx(style, readonly && offset);
|
|
1014
|
+
1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
1015
|
+
2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
1016
|
+
3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
1017
|
+
4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
1018
|
+
5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
1019
|
+
6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
|
|
1020
|
+
};
|
|
1021
|
+
var heading = (level) => {
|
|
1022
|
+
return headings[level];
|
|
1023
1023
|
};
|
|
1024
1024
|
var light = "text-neutral-200 dark:text-neutral-800";
|
|
1025
1025
|
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
@@ -1037,98 +1037,15 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
|
1037
1037
|
var tokens = tailwindConfig({}).theme;
|
|
1038
1038
|
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1039
1039
|
|
|
1040
|
-
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
1041
|
-
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
1042
|
-
var styles2 = EditorView5.baseTheme({
|
|
1043
|
-
"& .cm-codeblock": {
|
|
1044
|
-
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1045
|
-
},
|
|
1046
|
-
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1047
|
-
background: getToken("extend.colors.neutral.50")
|
|
1048
|
-
},
|
|
1049
|
-
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1050
|
-
background: getToken("extend.colors.neutral.850")
|
|
1051
|
-
},
|
|
1052
|
-
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1053
|
-
display: "block",
|
|
1054
|
-
paddingInline: "4px !important"
|
|
1055
|
-
},
|
|
1056
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1057
|
-
paddingTop: "4px !important",
|
|
1058
|
-
borderTopLeftRadius: "4px",
|
|
1059
|
-
borderTopRightRadius: "4px"
|
|
1060
|
-
},
|
|
1061
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1062
|
-
paddingBottom: "4px !important",
|
|
1063
|
-
borderBottomLeftRadius: "4px",
|
|
1064
|
-
borderBottomRightRadius: "4px"
|
|
1065
|
-
}
|
|
1066
|
-
});
|
|
1067
|
-
var getLineRange = (lines, from, to) => {
|
|
1068
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1069
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1070
|
-
return [
|
|
1071
|
-
start,
|
|
1072
|
-
end
|
|
1073
|
-
];
|
|
1074
|
-
};
|
|
1075
|
-
var code2 = () => {
|
|
1076
|
-
const buildDecorations5 = (view) => {
|
|
1077
|
-
const decorations = [];
|
|
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));
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
return Decoration2.set(decorations);
|
|
1091
|
-
};
|
|
1092
|
-
return [
|
|
1093
|
-
ViewPlugin3.fromClass(class {
|
|
1094
|
-
constructor(view) {
|
|
1095
|
-
this.hasFocus = false;
|
|
1096
|
-
this.decorations = buildDecorations5(view);
|
|
1097
|
-
}
|
|
1098
|
-
update(update2) {
|
|
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);
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
}, {
|
|
1108
|
-
decorations: (value) => value.decorations
|
|
1109
|
-
}),
|
|
1110
|
-
styles2
|
|
1111
|
-
];
|
|
1112
|
-
};
|
|
1113
|
-
|
|
1114
|
-
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1115
|
-
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1116
|
-
import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
|
|
1117
|
-
import sortBy from "lodash.sortby";
|
|
1118
|
-
import { useEffect } from "react";
|
|
1119
|
-
import { debounce } from "@dxos/async";
|
|
1120
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1121
|
-
import { nonNullable } from "@dxos/util";
|
|
1122
|
-
|
|
1123
1040
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1124
1041
|
import { log } from "@dxos/log";
|
|
1125
|
-
var
|
|
1042
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1126
1043
|
var callbackWrapper = (fn) => (...args) => {
|
|
1127
1044
|
try {
|
|
1128
1045
|
return fn(...args);
|
|
1129
1046
|
} catch (err) {
|
|
1130
1047
|
log.catch(err, void 0, {
|
|
1131
|
-
F:
|
|
1048
|
+
F: __dxlog_file2,
|
|
1132
1049
|
L: 18,
|
|
1133
1050
|
S: void 0,
|
|
1134
1051
|
C: (f, a) => f(...a)
|
|
@@ -1156,8 +1073,7 @@ var logChanges = (trs) => {
|
|
|
1156
1073
|
};
|
|
1157
1074
|
|
|
1158
1075
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1159
|
-
var
|
|
1160
|
-
var styles3 = EditorView6.baseTheme({
|
|
1076
|
+
var styles2 = EditorView5.baseTheme({
|
|
1161
1077
|
"& .cm-comment": {
|
|
1162
1078
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1163
1079
|
},
|
|
@@ -1165,15 +1081,13 @@ var styles3 = EditorView6.baseTheme({
|
|
|
1165
1081
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1166
1082
|
}
|
|
1167
1083
|
});
|
|
1168
|
-
var
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
};
|
|
1176
|
-
var setFocus = (view, id, center = true) => {
|
|
1084
|
+
var commentMark = Decoration2.mark({
|
|
1085
|
+
class: "cm-comment"
|
|
1086
|
+
});
|
|
1087
|
+
var commentCurrentMark = Decoration2.mark({
|
|
1088
|
+
class: "cm-comment-current"
|
|
1089
|
+
});
|
|
1090
|
+
var focusComment = (view, id, center = true) => {
|
|
1177
1091
|
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1178
1092
|
if (!comment?.comment.cursor) {
|
|
1179
1093
|
return;
|
|
@@ -1186,7 +1100,7 @@ var setFocus = (view, id, center = true) => {
|
|
|
1186
1100
|
},
|
|
1187
1101
|
effects: [
|
|
1188
1102
|
//
|
|
1189
|
-
|
|
1103
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1190
1104
|
y: "center"
|
|
1191
1105
|
} : void 0),
|
|
1192
1106
|
setSelection.of({
|
|
@@ -1235,7 +1149,7 @@ var commentsState = StateField2.define({
|
|
|
1235
1149
|
return value;
|
|
1236
1150
|
}
|
|
1237
1151
|
});
|
|
1238
|
-
var
|
|
1152
|
+
var commentsDecorations = EditorView5.decorations.compute([
|
|
1239
1153
|
commentsState
|
|
1240
1154
|
], (state) => {
|
|
1241
1155
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
@@ -1246,12 +1160,12 @@ var highlightDecorations = EditorView6.decorations.compute([
|
|
|
1246
1160
|
return void 0;
|
|
1247
1161
|
}
|
|
1248
1162
|
if (comment.comment.id === current) {
|
|
1249
|
-
return
|
|
1163
|
+
return commentCurrentMark.range(range.from, range.to);
|
|
1250
1164
|
} else {
|
|
1251
|
-
return
|
|
1165
|
+
return commentMark.range(range.from, range.to);
|
|
1252
1166
|
}
|
|
1253
1167
|
}).filter(nonNullable);
|
|
1254
|
-
return
|
|
1168
|
+
return Decoration2.set(decorations);
|
|
1255
1169
|
});
|
|
1256
1170
|
var trackPastedComments = (onUpdate) => {
|
|
1257
1171
|
let tracked = null;
|
|
@@ -1273,96 +1187,136 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1273
1187
|
}
|
|
1274
1188
|
};
|
|
1275
1189
|
return [
|
|
1276
|
-
|
|
1190
|
+
EditorView5.domEventHandlers({
|
|
1277
1191
|
cut: handleTrack,
|
|
1278
1192
|
copy: handleTrack
|
|
1279
1193
|
}),
|
|
1280
|
-
//
|
|
1281
|
-
|
|
1194
|
+
// Track deleted comments.
|
|
1195
|
+
invertedEffects2.of((tr) => {
|
|
1196
|
+
const { comments: comments2 } = tr.startState.field(commentsState);
|
|
1197
|
+
const effects = [];
|
|
1198
|
+
tr.changes.iterChangedRanges((fromA, toA) => {
|
|
1199
|
+
for (const { comment: { id }, range: { from, to } } of comments2) {
|
|
1200
|
+
if (from < to && from >= fromA && to <= toA) {
|
|
1201
|
+
effects.push(restoreCommentEffect.of({
|
|
1202
|
+
id,
|
|
1203
|
+
from,
|
|
1204
|
+
to
|
|
1205
|
+
}));
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
});
|
|
1209
|
+
return effects;
|
|
1210
|
+
}),
|
|
1211
|
+
// Handle paste or the undo of comment deletion.
|
|
1212
|
+
EditorView5.updateListener.of((update2) => {
|
|
1213
|
+
const restore = [];
|
|
1214
|
+
for (let i = 0; i < update2.transactions.length; i++) {
|
|
1215
|
+
const tr = update2.transactions[i];
|
|
1216
|
+
for (let j = 0; j < restore.length; j++) {
|
|
1217
|
+
restore[j] = mapTrackedComment(restore[j], tr.changes);
|
|
1218
|
+
}
|
|
1219
|
+
for (const effect of tr.effects) {
|
|
1220
|
+
if (effect.is(restoreCommentEffect)) {
|
|
1221
|
+
restore.push(effect.value);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1282
1225
|
if (tracked) {
|
|
1283
|
-
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1226
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1284
1227
|
if (paste) {
|
|
1285
1228
|
let found = -1;
|
|
1286
1229
|
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1287
1230
|
if (text.eq(tracked.text)) {
|
|
1288
|
-
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1289
|
-
fromB = transactions[i].changes.mapPos(fromB);
|
|
1231
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1232
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1290
1233
|
}
|
|
1291
1234
|
found = fromB;
|
|
1292
1235
|
}
|
|
1293
1236
|
});
|
|
1294
1237
|
if (found > -1) {
|
|
1295
1238
|
for (const moved of tracked.comments) {
|
|
1296
|
-
|
|
1239
|
+
restore.push({
|
|
1240
|
+
id: moved.id,
|
|
1297
1241
|
from: found + moved.from,
|
|
1298
1242
|
to: found + moved.to
|
|
1299
|
-
};
|
|
1300
|
-
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1301
|
-
onUpdate(moved.id, cursor);
|
|
1243
|
+
});
|
|
1302
1244
|
}
|
|
1303
1245
|
}
|
|
1304
1246
|
tracked = null;
|
|
1305
1247
|
}
|
|
1306
1248
|
}
|
|
1249
|
+
for (const comment of restore) {
|
|
1250
|
+
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
1251
|
+
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
1252
|
+
if (!exists) {
|
|
1253
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
1254
|
+
onUpdate(comment.id, cursor);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1307
1257
|
})
|
|
1308
1258
|
];
|
|
1309
1259
|
};
|
|
1310
|
-
var
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1260
|
+
var mapTrackedComment = (comment, changes) => ({
|
|
1261
|
+
id: comment.id,
|
|
1262
|
+
from: changes.mapPos(comment.from, 1),
|
|
1263
|
+
to: changes.mapPos(comment.to, 1)
|
|
1264
|
+
});
|
|
1265
|
+
var restoreCommentEffect = StateEffect2.define({
|
|
1266
|
+
map: mapTrackedComment
|
|
1267
|
+
});
|
|
1268
|
+
var optionsFacet = Facet3.define({
|
|
1269
|
+
combine: (providers) => providers[0]
|
|
1270
|
+
});
|
|
1271
|
+
var createComment = (view) => {
|
|
1272
|
+
const options = view.state.facet(optionsFacet);
|
|
1273
|
+
const { from, to } = view.state.selection.main;
|
|
1274
|
+
if (from === to) {
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
if (to === view.state.doc.length) {
|
|
1278
|
+
view.dispatch({
|
|
1279
|
+
changes: {
|
|
1280
|
+
from: to,
|
|
1281
|
+
insert: "\n"
|
|
1282
|
+
}
|
|
1322
1283
|
});
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1284
|
+
}
|
|
1285
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1286
|
+
from,
|
|
1287
|
+
to
|
|
1288
|
+
});
|
|
1289
|
+
if (cursor) {
|
|
1290
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1291
|
+
if (id) {
|
|
1328
1292
|
view.dispatch({
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1293
|
+
effects: setSelection.of({
|
|
1294
|
+
current: id
|
|
1295
|
+
}),
|
|
1296
|
+
selection: {
|
|
1297
|
+
anchor: to
|
|
1332
1298
|
}
|
|
1333
1299
|
});
|
|
1300
|
+
return true;
|
|
1334
1301
|
}
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
if (id) {
|
|
1342
|
-
view.dispatch({
|
|
1343
|
-
effects: setSelection.of({
|
|
1344
|
-
current: id
|
|
1345
|
-
}),
|
|
1346
|
-
selection: {
|
|
1347
|
-
anchor: from
|
|
1348
|
-
}
|
|
1349
|
-
});
|
|
1350
|
-
return true;
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
return false;
|
|
1354
|
-
};
|
|
1302
|
+
}
|
|
1303
|
+
return false;
|
|
1304
|
+
};
|
|
1305
|
+
var comments = (options = {}) => {
|
|
1306
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1307
|
+
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1355
1308
|
return [
|
|
1309
|
+
optionsFacet.of(options),
|
|
1356
1310
|
commentsState,
|
|
1357
|
-
|
|
1358
|
-
|
|
1311
|
+
commentsDecorations,
|
|
1312
|
+
styles2,
|
|
1359
1313
|
//
|
|
1360
1314
|
// Keymap.
|
|
1361
1315
|
//
|
|
1362
1316
|
options.onCreate ? keymap3.of([
|
|
1363
1317
|
{
|
|
1364
1318
|
key: shortcut,
|
|
1365
|
-
run: callbackWrapper(
|
|
1319
|
+
run: callbackWrapper(createComment)
|
|
1366
1320
|
}
|
|
1367
1321
|
]) : [],
|
|
1368
1322
|
//
|
|
@@ -1398,7 +1352,7 @@ var comments = (options = {}) => {
|
|
|
1398
1352
|
//
|
|
1399
1353
|
// Track deleted ranges and update ranges for decorations.
|
|
1400
1354
|
//
|
|
1401
|
-
|
|
1355
|
+
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1402
1356
|
let mod = false;
|
|
1403
1357
|
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1404
1358
|
changes.iterChanges((from, to, from2, to2) => {
|
|
@@ -1428,7 +1382,7 @@ var comments = (options = {}) => {
|
|
|
1428
1382
|
//
|
|
1429
1383
|
// Track selection/proximity.
|
|
1430
1384
|
//
|
|
1431
|
-
|
|
1385
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1432
1386
|
let min = Infinity;
|
|
1433
1387
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1434
1388
|
const { head } = state.selection.main;
|
|
@@ -1476,294 +1430,31 @@ var useComments = (view, comments2 = []) => {
|
|
|
1476
1430
|
]);
|
|
1477
1431
|
};
|
|
1478
1432
|
|
|
1479
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1480
|
-
import {
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
const el = document.createElement("div");
|
|
1492
|
-
el.className = "cm-hr";
|
|
1493
|
-
return el;
|
|
1494
|
-
}
|
|
1495
|
-
};
|
|
1496
|
-
var decoration = Decoration4.replace({
|
|
1497
|
-
widget: new HorizontalRuleWidget()
|
|
1498
|
-
});
|
|
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
|
|
1530
|
-
})
|
|
1531
|
-
];
|
|
1433
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1434
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1435
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1436
|
+
const extensions = [];
|
|
1437
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1438
|
+
onFocus(focused);
|
|
1439
|
+
return null;
|
|
1440
|
+
}));
|
|
1441
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1442
|
+
onChange(update2.state.doc.toString());
|
|
1443
|
+
}));
|
|
1444
|
+
return extensions;
|
|
1532
1445
|
};
|
|
1533
1446
|
|
|
1534
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1535
|
-
import {
|
|
1536
|
-
import {
|
|
1537
|
-
import {
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
return value;
|
|
1546
|
-
}
|
|
1547
|
-
const cursor = tr.state.selection.main.head;
|
|
1548
|
-
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1549
|
-
let from = Math.min(cursor, oldCursor);
|
|
1550
|
-
let to = Math.max(cursor, oldCursor);
|
|
1551
|
-
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1552
|
-
from = Math.min(from, fromB);
|
|
1553
|
-
to = Math.max(to, toB);
|
|
1554
|
-
});
|
|
1555
|
-
from = tr.state.doc.lineAt(from).from;
|
|
1556
|
-
to = tr.state.doc.lineAt(to).to;
|
|
1557
|
-
return value.map(tr.changes).update({
|
|
1558
|
-
filterFrom: from,
|
|
1559
|
-
filterTo: to,
|
|
1560
|
-
filter: () => false,
|
|
1561
|
-
add: buildDecorations2(from, to, tr.state)
|
|
1562
|
-
});
|
|
1563
|
-
},
|
|
1564
|
-
provide: (field) => EditorView8.decorations.from(field)
|
|
1565
|
-
});
|
|
1566
|
-
};
|
|
1567
|
-
var buildDecorations2 = (from, to, state) => {
|
|
1568
|
-
const decorations = [];
|
|
1569
|
-
const cursor = state.selection.main.head;
|
|
1570
|
-
syntaxTree2(state).iterate({
|
|
1571
|
-
enter: (node) => {
|
|
1572
|
-
if (node.name === "Image") {
|
|
1573
|
-
const urlNode = node.node.getChild("URL");
|
|
1574
|
-
if (urlNode) {
|
|
1575
|
-
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1576
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1577
|
-
decorations.push(Decoration5.replace({
|
|
1578
|
-
block: true,
|
|
1579
|
-
widget: new ImageWidget(url)
|
|
1580
|
-
}).range(hide ? node.from : node.to, node.to));
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
},
|
|
1584
|
-
from,
|
|
1585
|
-
to
|
|
1586
|
-
});
|
|
1587
|
-
return decorations;
|
|
1588
|
-
};
|
|
1589
|
-
var ImageWidget = class extends WidgetType3 {
|
|
1590
|
-
constructor(_url) {
|
|
1591
|
-
super();
|
|
1592
|
-
this._url = _url;
|
|
1593
|
-
}
|
|
1594
|
-
eq(other) {
|
|
1595
|
-
return this._url === other._url;
|
|
1596
|
-
}
|
|
1597
|
-
toDOM(view) {
|
|
1598
|
-
const img = document.createElement("img");
|
|
1599
|
-
img.setAttribute("src", this._url);
|
|
1600
|
-
img.setAttribute("class", "cm-image");
|
|
1601
|
-
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1602
|
-
return img;
|
|
1603
|
-
}
|
|
1604
|
-
};
|
|
1605
|
-
|
|
1606
|
-
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
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";
|
|
1610
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1611
|
-
var link = (options = {}) => {
|
|
1612
|
-
const extensions = [
|
|
1613
|
-
ViewPlugin5.fromClass(class {
|
|
1614
|
-
constructor(view) {
|
|
1615
|
-
this.decorations = buildDecorations3(view, options);
|
|
1616
|
-
}
|
|
1617
|
-
update(update2) {
|
|
1618
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1619
|
-
this.decorations = buildDecorations3(update2.view, options);
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
}, {
|
|
1623
|
-
decorations: (v) => v.decorations
|
|
1624
|
-
})
|
|
1625
|
-
];
|
|
1626
|
-
if (options.onHover) {
|
|
1627
|
-
extensions.push(
|
|
1628
|
-
// https://codemirror.net/examples/tooltip
|
|
1629
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1630
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1631
|
-
hoverTooltip2((view, pos, side) => {
|
|
1632
|
-
const syntax = syntaxTree3(view.state).resolveInner(pos, side);
|
|
1633
|
-
let link2 = null;
|
|
1634
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1635
|
-
link2 = node.name === "Link" ? node : null;
|
|
1636
|
-
}
|
|
1637
|
-
const url = link2 && link2.getChild("URL");
|
|
1638
|
-
if (!url || !link2) {
|
|
1639
|
-
return null;
|
|
1640
|
-
}
|
|
1641
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1642
|
-
return {
|
|
1643
|
-
pos: link2.from,
|
|
1644
|
-
end: link2.to,
|
|
1645
|
-
above: true,
|
|
1646
|
-
create: () => {
|
|
1647
|
-
const el = document.createElement("div");
|
|
1648
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1649
|
-
options.onHover(el, urlText);
|
|
1650
|
-
return {
|
|
1651
|
-
dom: el,
|
|
1652
|
-
offset: {
|
|
1653
|
-
x: 0,
|
|
1654
|
-
y: 4
|
|
1655
|
-
}
|
|
1656
|
-
};
|
|
1657
|
-
}
|
|
1658
|
-
};
|
|
1659
|
-
})
|
|
1660
|
-
);
|
|
1661
|
-
}
|
|
1662
|
-
return extensions;
|
|
1663
|
-
};
|
|
1664
|
-
var LinkButton = class extends WidgetType4 {
|
|
1665
|
-
constructor(_url, _onAttach) {
|
|
1666
|
-
super();
|
|
1667
|
-
this._url = _url;
|
|
1668
|
-
this._onAttach = _onAttach;
|
|
1669
|
-
}
|
|
1670
|
-
eq(other) {
|
|
1671
|
-
return this._url === other._url;
|
|
1672
|
-
}
|
|
1673
|
-
toDOM(view) {
|
|
1674
|
-
const el = document.createElement("span");
|
|
1675
|
-
this._onAttach(el, this._url);
|
|
1676
|
-
return el;
|
|
1677
|
-
}
|
|
1678
|
-
};
|
|
1679
|
-
var LinkText = class extends WidgetType4 {
|
|
1680
|
-
constructor(_text, _url) {
|
|
1681
|
-
super();
|
|
1682
|
-
this._text = _text;
|
|
1683
|
-
this._url = _url;
|
|
1684
|
-
}
|
|
1685
|
-
eq(other) {
|
|
1686
|
-
return this._url === other._url;
|
|
1687
|
-
}
|
|
1688
|
-
toDOM(view) {
|
|
1689
|
-
const link2 = document.createElement("a");
|
|
1690
|
-
link2.setAttribute("class", "cm-link");
|
|
1691
|
-
link2.textContent = this._text;
|
|
1692
|
-
if (this._url) {
|
|
1693
|
-
link2.setAttribute("rel", "noreferrer");
|
|
1694
|
-
link2.setAttribute("target", "_blank");
|
|
1695
|
-
link2.href = this._url;
|
|
1696
|
-
} else {
|
|
1697
|
-
link2.onclick = () => {
|
|
1698
|
-
view.dispatch({
|
|
1699
|
-
selection: {
|
|
1700
|
-
anchor: view.posAtDOM(link2)
|
|
1701
|
-
}
|
|
1702
|
-
});
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
return link2;
|
|
1706
|
-
}
|
|
1707
|
-
};
|
|
1708
|
-
var buildDecorations3 = (view, options) => {
|
|
1709
|
-
const builder = new RangeSetBuilder2();
|
|
1710
|
-
const { state } = view;
|
|
1711
|
-
const cursor = state.selection.main.head;
|
|
1712
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1713
|
-
syntaxTree3(state).iterate({
|
|
1714
|
-
enter: (node) => {
|
|
1715
|
-
if (node.name === "Link") {
|
|
1716
|
-
const marks2 = node.node.getChildren("LinkMark");
|
|
1717
|
-
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1718
|
-
const urlNode = node.node.getChild("URL");
|
|
1719
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1720
|
-
if (!url) {
|
|
1721
|
-
return false;
|
|
1722
|
-
}
|
|
1723
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1724
|
-
builder.add(node.from, node.to, Decoration6.replace({
|
|
1725
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
1726
|
-
}));
|
|
1727
|
-
}
|
|
1728
|
-
if (options.onRender) {
|
|
1729
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1730
|
-
widget: new LinkButton(url, options.onRender)
|
|
1731
|
-
}));
|
|
1732
|
-
}
|
|
1733
|
-
return false;
|
|
1734
|
-
}
|
|
1735
|
-
},
|
|
1736
|
-
from,
|
|
1737
|
-
to
|
|
1738
|
-
});
|
|
1739
|
-
}
|
|
1740
|
-
return builder.finish();
|
|
1741
|
-
};
|
|
1742
|
-
|
|
1743
|
-
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1744
|
-
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
1745
|
-
var listener = ({ onFocus, onChange }) => {
|
|
1746
|
-
const extensions = [];
|
|
1747
|
-
onFocus && extensions.push(EditorView9.focusChangeEffect.of((_, focused) => {
|
|
1748
|
-
onFocus(focused);
|
|
1749
|
-
return null;
|
|
1750
|
-
}));
|
|
1751
|
-
onChange && extensions.push(EditorView9.updateListener.of((update2) => {
|
|
1752
|
-
onChange(update2.state.doc.toString());
|
|
1753
|
-
}));
|
|
1754
|
-
return extensions;
|
|
1755
|
-
};
|
|
1756
|
-
|
|
1757
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1758
|
-
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1759
|
-
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1760
|
-
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1761
|
-
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1762
|
-
import { languages } from "@codemirror/language-data";
|
|
1763
|
-
import { searchKeymap } from "@codemirror/search";
|
|
1764
|
-
import { EditorState } from "@codemirror/state";
|
|
1765
|
-
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1766
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView10, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1447
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1448
|
+
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1449
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1450
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1451
|
+
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1452
|
+
import { languages } from "@codemirror/language-data";
|
|
1453
|
+
import { searchKeymap } from "@codemirror/search";
|
|
1454
|
+
import { EditorState } from "@codemirror/state";
|
|
1455
|
+
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1456
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1457
|
+
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1767
1458
|
|
|
1768
1459
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1769
1460
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1860,7 +1551,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1860
1551
|
markdownTags.QuoteMark,
|
|
1861
1552
|
markdownTags.EmphasisMark
|
|
1862
1553
|
],
|
|
1863
|
-
class:
|
|
1554
|
+
class: mark
|
|
1864
1555
|
},
|
|
1865
1556
|
// E.g., code block language (after ```).
|
|
1866
1557
|
{
|
|
@@ -1868,7 +1559,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1868
1559
|
tags.function(tags.variableName),
|
|
1869
1560
|
tags.labelName
|
|
1870
1561
|
],
|
|
1871
|
-
class:
|
|
1562
|
+
class: codeMark
|
|
1872
1563
|
},
|
|
1873
1564
|
{
|
|
1874
1565
|
tag: [
|
|
@@ -1879,27 +1570,27 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1879
1570
|
// Headings.
|
|
1880
1571
|
{
|
|
1881
1572
|
tag: tags.heading1,
|
|
1882
|
-
class: heading(1
|
|
1573
|
+
class: heading(1)
|
|
1883
1574
|
},
|
|
1884
1575
|
{
|
|
1885
1576
|
tag: tags.heading2,
|
|
1886
|
-
class: heading(2
|
|
1577
|
+
class: heading(2)
|
|
1887
1578
|
},
|
|
1888
1579
|
{
|
|
1889
1580
|
tag: tags.heading3,
|
|
1890
|
-
class: heading(3
|
|
1581
|
+
class: heading(3)
|
|
1891
1582
|
},
|
|
1892
1583
|
{
|
|
1893
1584
|
tag: tags.heading4,
|
|
1894
|
-
class: heading(4
|
|
1585
|
+
class: heading(4)
|
|
1895
1586
|
},
|
|
1896
1587
|
{
|
|
1897
1588
|
tag: tags.heading5,
|
|
1898
|
-
class: heading(5
|
|
1589
|
+
class: heading(5)
|
|
1899
1590
|
},
|
|
1900
1591
|
{
|
|
1901
1592
|
tag: tags.heading6,
|
|
1902
|
-
class: heading(6
|
|
1593
|
+
class: heading(6)
|
|
1903
1594
|
},
|
|
1904
1595
|
// Emphasis.
|
|
1905
1596
|
{
|
|
@@ -1925,7 +1616,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1925
1616
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
1926
1617
|
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
1927
1618
|
// the code, but all other CSS properties will be inherited.
|
|
1928
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
1619
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
1929
1620
|
{
|
|
1930
1621
|
tag: [
|
|
1931
1622
|
markdownTags.CodeText,
|
|
@@ -1954,11 +1645,11 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1954
1645
|
};
|
|
1955
1646
|
|
|
1956
1647
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1957
|
-
var
|
|
1648
|
+
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
1958
1649
|
return [
|
|
1650
|
+
lineWrapping && EditorView7.lineWrapping,
|
|
1959
1651
|
EditorState.allowMultipleSelections.of(true),
|
|
1960
1652
|
EditorState.tabSize.of(2),
|
|
1961
|
-
EditorView10.lineWrapping,
|
|
1962
1653
|
// https://github.com/codemirror/basic-setup
|
|
1963
1654
|
bracketMatching2(),
|
|
1964
1655
|
closeBrackets2(),
|
|
@@ -1968,7 +1659,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1968
1659
|
highlightActiveLine2(),
|
|
1969
1660
|
history2(),
|
|
1970
1661
|
indentOnInput(),
|
|
1971
|
-
_placeholder
|
|
1662
|
+
_placeholder && placeholder2(_placeholder),
|
|
1972
1663
|
// Main extension.
|
|
1973
1664
|
// https://github.com/codemirror/lang-markdown
|
|
1974
1665
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1990,7 +1681,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1990
1681
|
// https://github.com/codemirror/theme-one-dark
|
|
1991
1682
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1992
1683
|
// Custom styles.
|
|
1993
|
-
syntaxHighlighting2(markdownHighlightStyle(
|
|
1684
|
+
syntaxHighlighting2(markdownHighlightStyle()),
|
|
1994
1685
|
keymap4.of([
|
|
1995
1686
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1996
1687
|
indentWithTab,
|
|
@@ -2003,47 +1694,580 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
2003
1694
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2004
1695
|
...standardKeymap
|
|
2005
1696
|
])
|
|
1697
|
+
].filter(isNotFalsy2);
|
|
1698
|
+
};
|
|
1699
|
+
|
|
1700
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1701
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1702
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1703
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1704
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1705
|
+
var styles3 = EditorView8.baseTheme({
|
|
1706
|
+
"& .cm-code": {
|
|
1707
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1708
|
+
},
|
|
1709
|
+
"& .cm-codeblock": {
|
|
1710
|
+
width: "100%",
|
|
1711
|
+
paddingInline: "1rem !important",
|
|
1712
|
+
position: "relative",
|
|
1713
|
+
"&::after": {
|
|
1714
|
+
content: '""',
|
|
1715
|
+
position: "absolute",
|
|
1716
|
+
inset: 0
|
|
1717
|
+
}
|
|
1718
|
+
},
|
|
1719
|
+
"&light .cm-codeblock": {
|
|
1720
|
+
"&::after": {
|
|
1721
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
1722
|
+
mixBlendMode: "darken"
|
|
1723
|
+
}
|
|
1724
|
+
},
|
|
1725
|
+
"&dark .cm-codeblock": {
|
|
1726
|
+
"&::after": {
|
|
1727
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
1728
|
+
mixBlendMode: "lighten"
|
|
1729
|
+
}
|
|
1730
|
+
},
|
|
1731
|
+
"& .cm-codeblock-first": {
|
|
1732
|
+
display: "inline-block",
|
|
1733
|
+
"&::after": {
|
|
1734
|
+
borderTopLeftRadius: ".5rem",
|
|
1735
|
+
borderTopRightRadius: ".5rem"
|
|
1736
|
+
}
|
|
1737
|
+
},
|
|
1738
|
+
"& .cm-codeblock-last": {
|
|
1739
|
+
display: "inline-block",
|
|
1740
|
+
"&::after": {
|
|
1741
|
+
borderBottomLeftRadius: ".5rem",
|
|
1742
|
+
borderBottomRightRadius: ".5rem"
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
var getLineRange = (lines, from, to) => {
|
|
1747
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1748
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1749
|
+
return [
|
|
1750
|
+
start,
|
|
1751
|
+
end
|
|
1752
|
+
];
|
|
1753
|
+
};
|
|
1754
|
+
var LineWidget = class extends WidgetType2 {
|
|
1755
|
+
constructor(_className) {
|
|
1756
|
+
super();
|
|
1757
|
+
this._className = _className;
|
|
1758
|
+
}
|
|
1759
|
+
toDOM() {
|
|
1760
|
+
const el = document.createElement("span");
|
|
1761
|
+
el.innerHTML = " ";
|
|
1762
|
+
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1763
|
+
return el;
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
var top = new LineWidget("cm-codeblock-first");
|
|
1767
|
+
var bottom = new LineWidget("cm-codeblock-last");
|
|
1768
|
+
var buildDecorations = (view) => {
|
|
1769
|
+
const builder = new RangeSetBuilder();
|
|
1770
|
+
const { state } = view;
|
|
1771
|
+
const blocks = view.viewportLineBlocks;
|
|
1772
|
+
const cursor = state.selection.main.head;
|
|
1773
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1774
|
+
syntaxTree(state).iterate({
|
|
1775
|
+
enter: (node) => {
|
|
1776
|
+
if (node.name === "FencedCode") {
|
|
1777
|
+
const edit = !view.state.readOnly && cursor >= node.from && cursor <= node.to;
|
|
1778
|
+
const range = getLineRange(blocks, node.from, node.to);
|
|
1779
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1780
|
+
const block = blocks[i];
|
|
1781
|
+
if (!edit && (i === range[0] || i === range[1])) {
|
|
1782
|
+
builder.add(block.from, block.to, Decoration3.replace({
|
|
1783
|
+
widget: i === range[0] ? top : bottom
|
|
1784
|
+
}));
|
|
1785
|
+
} else {
|
|
1786
|
+
builder.add(block.from, block.from, Decoration3.line({
|
|
1787
|
+
class: mx2("cm-code cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1788
|
+
}));
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
},
|
|
1793
|
+
from,
|
|
1794
|
+
to
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
return builder.finish();
|
|
1798
|
+
};
|
|
1799
|
+
var code2 = () => {
|
|
1800
|
+
return [
|
|
1801
|
+
ViewPlugin3.fromClass(class {
|
|
1802
|
+
constructor(view) {
|
|
1803
|
+
this.decorations = buildDecorations(view);
|
|
1804
|
+
}
|
|
1805
|
+
update(update2) {
|
|
1806
|
+
this.decorations = buildDecorations(update2.view);
|
|
1807
|
+
}
|
|
1808
|
+
}, {
|
|
1809
|
+
decorations: (value) => value.decorations
|
|
1810
|
+
}),
|
|
1811
|
+
styles3
|
|
2006
1812
|
];
|
|
2007
1813
|
};
|
|
2008
1814
|
|
|
2009
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
2010
|
-
import {
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
1815
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1816
|
+
import { snippet } from "@codemirror/autocomplete";
|
|
1817
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1818
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1819
|
+
import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1820
|
+
var setHeading = (level) => (view) => {
|
|
1821
|
+
const { selection: { ranges }, doc } = view.state;
|
|
1822
|
+
const changes = [];
|
|
1823
|
+
for (const range of ranges) {
|
|
1824
|
+
const { number } = doc.lineAt(range.anchor);
|
|
1825
|
+
const { from, to } = doc.line(number);
|
|
1826
|
+
const line = doc.sliceString(from, to);
|
|
1827
|
+
const [_, marks, spaces] = line.match(/(#+)(\s+)/) ?? [];
|
|
1828
|
+
const current = marks?.length ?? 0;
|
|
1829
|
+
if (level !== current) {
|
|
1830
|
+
changes.push({
|
|
1831
|
+
from,
|
|
1832
|
+
to: from + current + (spaces?.length ?? 0),
|
|
1833
|
+
insert: "#".repeat(level) + (level > 0 ? " " : "")
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
if (changes.length) {
|
|
1838
|
+
view.dispatch({
|
|
1839
|
+
changes
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
return true;
|
|
1843
|
+
};
|
|
1844
|
+
var toggleStyle = (mark2) => (view) => {
|
|
1845
|
+
const { ranges } = view.state.selection;
|
|
1846
|
+
for (const range of ranges) {
|
|
1847
|
+
if (range.from === range.to) {
|
|
1848
|
+
return false;
|
|
1849
|
+
}
|
|
1850
|
+
view.dispatch({
|
|
1851
|
+
changes: [
|
|
1852
|
+
{
|
|
1853
|
+
from: range.from,
|
|
1854
|
+
insert: mark2
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
from: range.to,
|
|
1858
|
+
insert: mark2
|
|
1859
|
+
}
|
|
1860
|
+
]
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
return true;
|
|
1864
|
+
};
|
|
1865
|
+
var snippets = {
|
|
1866
|
+
codeblock: snippet([
|
|
1867
|
+
"```#{lang}",
|
|
1868
|
+
" #{}",
|
|
1869
|
+
"```"
|
|
1870
|
+
].join("\n")),
|
|
1871
|
+
table: snippet([
|
|
1872
|
+
"| #{col1} | #{col2} |",
|
|
1873
|
+
"| ---- | ---- |",
|
|
1874
|
+
"| #{val1} | #{val2} |",
|
|
1875
|
+
"| #{val3} | #{val4} |"
|
|
1876
|
+
].join("\n"))
|
|
1877
|
+
};
|
|
1878
|
+
var insertCodeblock = (view) => {
|
|
1879
|
+
const { selection: { main }, doc } = view.state;
|
|
1880
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1881
|
+
const { from } = doc.line(number);
|
|
1882
|
+
snippets.codeblock(view, null, from, from);
|
|
1883
|
+
};
|
|
1884
|
+
var insertTable = (view) => {
|
|
1885
|
+
const { selection: { main }, doc } = view.state;
|
|
1886
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1887
|
+
const { from } = doc.line(number);
|
|
1888
|
+
snippets.table(view, null, from, from);
|
|
1889
|
+
};
|
|
1890
|
+
var toggleBold = toggleStyle("**");
|
|
1891
|
+
var toggleItalic = toggleStyle("_");
|
|
1892
|
+
var toggleStrikethrough = toggleStyle("~~");
|
|
1893
|
+
var toggleList = (view) => {
|
|
1894
|
+
};
|
|
1895
|
+
var formatting = (options = {}) => {
|
|
1896
|
+
return [
|
|
1897
|
+
keymap5.of([
|
|
1898
|
+
{
|
|
1899
|
+
key: "meta-b",
|
|
1900
|
+
run: toggleBold
|
|
1901
|
+
}
|
|
1902
|
+
]),
|
|
1903
|
+
styling()
|
|
1904
|
+
];
|
|
1905
|
+
};
|
|
1906
|
+
var styling = () => {
|
|
1907
|
+
const buildDecorations7 = (view) => {
|
|
1908
|
+
const builder = new RangeSetBuilder2();
|
|
1909
|
+
const { state } = view;
|
|
1910
|
+
const cursor = state.selection.main.head;
|
|
1911
|
+
const replace = (node, marks) => {
|
|
1912
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1913
|
+
for (const mark2 of marks) {
|
|
1914
|
+
builder.add(mark2.from, mark2.to, Decoration4.replace({}));
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
};
|
|
1918
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1919
|
+
syntaxTree2(state).iterate({
|
|
1920
|
+
enter: (node) => {
|
|
1921
|
+
switch (node.name) {
|
|
1922
|
+
case "Emphasis":
|
|
1923
|
+
case "StrongEmphasis": {
|
|
1924
|
+
const marks = node.node.getChildren("EmphasisMark");
|
|
1925
|
+
replace(node, marks);
|
|
1926
|
+
break;
|
|
1927
|
+
}
|
|
1928
|
+
case "Strikethrough": {
|
|
1929
|
+
const marks = node.node.getChildren("StrikethroughMark");
|
|
1930
|
+
replace(node, marks);
|
|
1931
|
+
break;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
},
|
|
1935
|
+
from,
|
|
1936
|
+
to
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
return builder.finish();
|
|
1940
|
+
};
|
|
1941
|
+
return [
|
|
1942
|
+
ViewPlugin4.fromClass(class {
|
|
1943
|
+
constructor(view) {
|
|
1944
|
+
this.decorations = buildDecorations7(view);
|
|
1945
|
+
}
|
|
1946
|
+
update(update2) {
|
|
1947
|
+
this.decorations = buildDecorations7(update2.view);
|
|
1948
|
+
}
|
|
1949
|
+
}, {
|
|
1950
|
+
decorations: (value) => value.decorations
|
|
1951
|
+
})
|
|
1952
|
+
];
|
|
1953
|
+
};
|
|
1954
|
+
|
|
1955
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1956
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1957
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1958
|
+
import { Decoration as Decoration5, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1959
|
+
var buildDecorations2 = (view) => {
|
|
1960
|
+
const builder = new RangeSetBuilder3();
|
|
1961
|
+
const { state } = view;
|
|
1962
|
+
const cursor = state.selection.main.head;
|
|
1963
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1964
|
+
syntaxTree3(state).iterate({
|
|
1965
|
+
enter: (node) => {
|
|
1966
|
+
switch (node.name) {
|
|
1967
|
+
case "ATXHeading1":
|
|
1968
|
+
case "ATXHeading2":
|
|
1969
|
+
case "ATXHeading3":
|
|
1970
|
+
case "ATXHeading4":
|
|
1971
|
+
case "ATXHeading5":
|
|
1972
|
+
case "ATXHeading6": {
|
|
1973
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1974
|
+
if (mark2) {
|
|
1975
|
+
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1976
|
+
builder.add(mark2.from, mark2.to + 1, Decoration5.replace({}));
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
},
|
|
1982
|
+
from,
|
|
1983
|
+
to
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
return builder.finish();
|
|
1987
|
+
};
|
|
1988
|
+
var heading2 = () => {
|
|
1989
|
+
return [
|
|
1990
|
+
ViewPlugin5.fromClass(class {
|
|
1991
|
+
constructor(view) {
|
|
1992
|
+
this.decorations = buildDecorations2(view);
|
|
1993
|
+
}
|
|
1994
|
+
update(update2) {
|
|
1995
|
+
this.decorations = buildDecorations2(update2.view);
|
|
1996
|
+
}
|
|
1997
|
+
}, {
|
|
1998
|
+
decorations: (value) => value.decorations
|
|
1999
|
+
})
|
|
2000
|
+
];
|
|
2001
|
+
};
|
|
2002
|
+
|
|
2003
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
2004
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2005
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2006
|
+
import { Decoration as Decoration6, EditorView as EditorView9, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
2007
|
+
var styles4 = EditorView9.baseTheme({
|
|
2008
|
+
"& .cm-hr": {
|
|
2009
|
+
// Note that block-level decorations should not have vertical margins,
|
|
2010
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2014
|
+
toDOM() {
|
|
2015
|
+
const el = document.createElement("div");
|
|
2016
|
+
el.className = "cm-hr";
|
|
2017
|
+
return el;
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
var decoration = Decoration6.replace({
|
|
2021
|
+
widget: new HorizontalRuleWidget()
|
|
2022
|
+
});
|
|
2023
|
+
var buildDecorations3 = (view) => {
|
|
2024
|
+
const builder = new RangeSetBuilder4();
|
|
2025
|
+
const { state } = view;
|
|
2026
|
+
const cursor = state.selection.main.head;
|
|
2027
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2028
|
+
syntaxTree4(state).iterate({
|
|
2029
|
+
enter: (node) => {
|
|
2030
|
+
if (node.name === "HorizontalRule") {
|
|
2031
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
2032
|
+
builder.add(node.from, node.to, decoration);
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
},
|
|
2036
|
+
from,
|
|
2037
|
+
to
|
|
2038
|
+
});
|
|
2039
|
+
}
|
|
2040
|
+
return builder.finish();
|
|
2041
|
+
};
|
|
2042
|
+
var hr = () => {
|
|
2043
|
+
return [
|
|
2044
|
+
ViewPlugin6.fromClass(class {
|
|
2045
|
+
constructor(view) {
|
|
2046
|
+
this.decorations = buildDecorations3(view);
|
|
2047
|
+
}
|
|
2048
|
+
update(update2) {
|
|
2049
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2050
|
+
}
|
|
2051
|
+
}, {
|
|
2052
|
+
decorations: (value) => value.decorations
|
|
2053
|
+
}),
|
|
2054
|
+
styles4
|
|
2055
|
+
];
|
|
2056
|
+
};
|
|
2057
|
+
|
|
2058
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
2059
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2060
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
2061
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
2062
|
+
var image = (options = {}) => {
|
|
2063
|
+
return StateField3.define({
|
|
2064
|
+
create: (state) => {
|
|
2065
|
+
return Decoration7.set(buildDecorations4(0, state.doc.length, state));
|
|
2066
|
+
},
|
|
2067
|
+
update: (value, tr) => {
|
|
2068
|
+
if (!tr.docChanged && !tr.selection) {
|
|
2069
|
+
return value;
|
|
2070
|
+
}
|
|
2071
|
+
const cursor = tr.state.selection.main.head;
|
|
2072
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
2073
|
+
let from = Math.min(cursor, oldCursor);
|
|
2074
|
+
let to = Math.max(cursor, oldCursor);
|
|
2075
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
2076
|
+
from = Math.min(from, fromB);
|
|
2077
|
+
to = Math.max(to, toB);
|
|
2078
|
+
});
|
|
2079
|
+
from = tr.state.doc.lineAt(from).from;
|
|
2080
|
+
to = tr.state.doc.lineAt(to).to;
|
|
2081
|
+
return value.map(tr.changes).update({
|
|
2082
|
+
filterFrom: from,
|
|
2083
|
+
filterTo: to,
|
|
2084
|
+
filter: () => false,
|
|
2085
|
+
add: buildDecorations4(from, to, tr.state)
|
|
2086
|
+
});
|
|
2087
|
+
},
|
|
2088
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
2089
|
+
});
|
|
2090
|
+
};
|
|
2091
|
+
var buildDecorations4 = (from, to, state) => {
|
|
2092
|
+
const decorations = [];
|
|
2093
|
+
const cursor = state.selection.main.head;
|
|
2094
|
+
syntaxTree5(state).iterate({
|
|
2095
|
+
enter: (node) => {
|
|
2096
|
+
if (node.name === "Image") {
|
|
2097
|
+
const urlNode = node.node.getChild("URL");
|
|
2098
|
+
if (urlNode) {
|
|
2099
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
2100
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
2101
|
+
decorations.push(Decoration7.replace({
|
|
2102
|
+
block: true,
|
|
2103
|
+
widget: new ImageWidget(url)
|
|
2104
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
},
|
|
2108
|
+
from,
|
|
2109
|
+
to
|
|
2110
|
+
});
|
|
2111
|
+
return decorations;
|
|
2112
|
+
};
|
|
2113
|
+
var ImageWidget = class extends WidgetType4 {
|
|
2114
|
+
constructor(_url) {
|
|
2115
|
+
super();
|
|
2116
|
+
this._url = _url;
|
|
2117
|
+
}
|
|
2118
|
+
eq(other) {
|
|
2119
|
+
return this._url === other._url;
|
|
2120
|
+
}
|
|
2121
|
+
toDOM(view) {
|
|
2122
|
+
const img = document.createElement("img");
|
|
2123
|
+
img.setAttribute("src", this._url);
|
|
2124
|
+
img.setAttribute("class", "cm-image");
|
|
2125
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
2126
|
+
return img;
|
|
2127
|
+
}
|
|
2128
|
+
};
|
|
2129
|
+
|
|
2130
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
2131
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2132
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2133
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration8, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
2134
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
2135
|
+
var link = (options = {}) => {
|
|
2136
|
+
const extensions = [
|
|
2137
|
+
ViewPlugin7.fromClass(class {
|
|
2138
|
+
constructor(view) {
|
|
2139
|
+
this.decorations = buildDecorations5(view, options);
|
|
2140
|
+
}
|
|
2141
|
+
update(update2) {
|
|
2142
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2143
|
+
this.decorations = buildDecorations5(update2.view, options);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
}, {
|
|
2147
|
+
decorations: (value) => value.decorations
|
|
2148
|
+
})
|
|
2149
|
+
];
|
|
2150
|
+
if (options.onHover) {
|
|
2151
|
+
extensions.push(
|
|
2152
|
+
// https://codemirror.net/examples/tooltip
|
|
2153
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
2154
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
2155
|
+
hoverTooltip2((view, pos, side) => {
|
|
2156
|
+
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
2157
|
+
let link2 = null;
|
|
2158
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
2159
|
+
link2 = node.name === "Link" ? node : null;
|
|
2160
|
+
}
|
|
2161
|
+
const url = link2 && link2.getChild("URL");
|
|
2162
|
+
if (!url || !link2) {
|
|
2025
2163
|
return null;
|
|
2026
2164
|
}
|
|
2165
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
2027
2166
|
return {
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2167
|
+
pos: link2.from,
|
|
2168
|
+
end: link2.to,
|
|
2169
|
+
above: true,
|
|
2170
|
+
create: () => {
|
|
2171
|
+
const el = document.createElement("div");
|
|
2172
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
2173
|
+
options.onHover(el, urlText);
|
|
2174
|
+
return {
|
|
2175
|
+
dom: el,
|
|
2176
|
+
offset: {
|
|
2177
|
+
x: 0,
|
|
2178
|
+
y: 4
|
|
2179
|
+
}
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2032
2182
|
};
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
}
|
|
2183
|
+
})
|
|
2184
|
+
);
|
|
2185
|
+
}
|
|
2186
|
+
return extensions;
|
|
2036
2187
|
};
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2188
|
+
var LinkButton = class extends WidgetType5 {
|
|
2189
|
+
constructor(_url, _onAttach) {
|
|
2190
|
+
super();
|
|
2191
|
+
this._url = _url;
|
|
2192
|
+
this._onAttach = _onAttach;
|
|
2193
|
+
}
|
|
2194
|
+
eq(other) {
|
|
2195
|
+
return this._url === other._url;
|
|
2196
|
+
}
|
|
2197
|
+
toDOM(view) {
|
|
2198
|
+
const el = document.createElement("span");
|
|
2199
|
+
this._onAttach(el, this._url);
|
|
2200
|
+
return el;
|
|
2201
|
+
}
|
|
2202
|
+
};
|
|
2203
|
+
var LinkText = class extends WidgetType5 {
|
|
2204
|
+
constructor(_text, _url) {
|
|
2205
|
+
super();
|
|
2206
|
+
this._text = _text;
|
|
2207
|
+
this._url = _url;
|
|
2208
|
+
}
|
|
2209
|
+
eq(other) {
|
|
2210
|
+
return this._url === other._url;
|
|
2211
|
+
}
|
|
2212
|
+
toDOM(view) {
|
|
2213
|
+
const link2 = document.createElement("a");
|
|
2214
|
+
link2.setAttribute("class", "cm-link");
|
|
2215
|
+
link2.textContent = this._text;
|
|
2216
|
+
if (this._url) {
|
|
2217
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2218
|
+
link2.setAttribute("target", "_blank");
|
|
2219
|
+
link2.href = this._url;
|
|
2220
|
+
} else {
|
|
2221
|
+
link2.onclick = () => {
|
|
2222
|
+
view.dispatch({
|
|
2223
|
+
selection: {
|
|
2224
|
+
anchor: view.posAtDOM(link2)
|
|
2225
|
+
}
|
|
2226
|
+
});
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
return link2;
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
var buildDecorations5 = (view, options) => {
|
|
2233
|
+
const builder = new RangeSetBuilder5();
|
|
2234
|
+
const { state } = view;
|
|
2235
|
+
const cursor = state.selection.main.head;
|
|
2236
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2237
|
+
syntaxTree6(state).iterate({
|
|
2238
|
+
enter: (node) => {
|
|
2239
|
+
if (node.name === "Link") {
|
|
2240
|
+
const marks = node.node.getChildren("LinkMark");
|
|
2241
|
+
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
2242
|
+
const urlNode = node.node.getChild("URL");
|
|
2243
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2244
|
+
if (!url) {
|
|
2245
|
+
return false;
|
|
2246
|
+
}
|
|
2247
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2248
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
|
2249
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2250
|
+
}));
|
|
2251
|
+
}
|
|
2252
|
+
if (options.onRender) {
|
|
2253
|
+
builder.add(node.to, node.to, Decoration8.replace({
|
|
2254
|
+
widget: new LinkButton(url, options.onRender)
|
|
2255
|
+
}));
|
|
2256
|
+
}
|
|
2257
|
+
return false;
|
|
2258
|
+
}
|
|
2259
|
+
},
|
|
2260
|
+
from,
|
|
2261
|
+
to
|
|
2262
|
+
});
|
|
2263
|
+
}
|
|
2264
|
+
return builder.finish();
|
|
2041
2265
|
};
|
|
2042
2266
|
|
|
2043
|
-
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
2044
|
-
import { syntaxTree as
|
|
2045
|
-
import { RangeSetBuilder as
|
|
2046
|
-
import { Decoration as
|
|
2267
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2268
|
+
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
2269
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
2270
|
+
import { Decoration as Decoration9, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
2047
2271
|
var table = (options = {}) => {
|
|
2048
2272
|
return StateField4.define({
|
|
2049
2273
|
create: (state) => update(state, options),
|
|
@@ -2052,7 +2276,7 @@ var table = (options = {}) => {
|
|
|
2052
2276
|
});
|
|
2053
2277
|
};
|
|
2054
2278
|
var update = (state, options) => {
|
|
2055
|
-
const builder = new
|
|
2279
|
+
const builder = new RangeSetBuilder6();
|
|
2056
2280
|
const cursor = state.selection.main.head;
|
|
2057
2281
|
const tables = [];
|
|
2058
2282
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2060,7 +2284,7 @@ var update = (state, options) => {
|
|
|
2060
2284
|
const table2 = getTable();
|
|
2061
2285
|
return table2.rows?.[table2.rows.length - 1];
|
|
2062
2286
|
};
|
|
2063
|
-
|
|
2287
|
+
syntaxTree7(state).iterate({
|
|
2064
2288
|
enter: (node) => {
|
|
2065
2289
|
switch (node.name) {
|
|
2066
2290
|
case "Table": {
|
|
@@ -2092,16 +2316,16 @@ var update = (state, options) => {
|
|
|
2092
2316
|
});
|
|
2093
2317
|
tables.forEach((table2) => {
|
|
2094
2318
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2095
|
-
hide && builder.add(table2.from, table2.to,
|
|
2319
|
+
hide && builder.add(table2.from, table2.to, Decoration9.replace({
|
|
2096
2320
|
widget: new TableWidget(table2)
|
|
2097
2321
|
}));
|
|
2098
|
-
builder.add(table2.from, table2.to,
|
|
2322
|
+
builder.add(table2.from, table2.to, Decoration9.mark({
|
|
2099
2323
|
class: "cm-table"
|
|
2100
2324
|
}));
|
|
2101
2325
|
});
|
|
2102
2326
|
return builder.finish();
|
|
2103
2327
|
};
|
|
2104
|
-
var TableWidget = class extends
|
|
2328
|
+
var TableWidget = class extends WidgetType6 {
|
|
2105
2329
|
constructor(_table) {
|
|
2106
2330
|
super();
|
|
2107
2331
|
this._table = _table;
|
|
@@ -2138,10 +2362,10 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2138
2362
|
}
|
|
2139
2363
|
};
|
|
2140
2364
|
|
|
2141
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2142
|
-
import { syntaxTree as
|
|
2143
|
-
import { RangeSetBuilder as
|
|
2144
|
-
import { EditorView as EditorView12, Decoration as
|
|
2365
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2366
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
2367
|
+
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
2368
|
+
import { EditorView as EditorView12, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
2145
2369
|
var styles5 = EditorView12.baseTheme({
|
|
2146
2370
|
"& .cm-task": {
|
|
2147
2371
|
color: getToken("extend.colors.blue.500")
|
|
@@ -2151,7 +2375,7 @@ var styles5 = EditorView12.baseTheme({
|
|
|
2151
2375
|
marginRight: "4px"
|
|
2152
2376
|
}
|
|
2153
2377
|
});
|
|
2154
|
-
var CheckboxWidget = class extends
|
|
2378
|
+
var CheckboxWidget = class extends WidgetType7 {
|
|
2155
2379
|
constructor(_checked) {
|
|
2156
2380
|
super();
|
|
2157
2381
|
this._checked = _checked;
|
|
@@ -2188,23 +2412,23 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2188
2412
|
return false;
|
|
2189
2413
|
}
|
|
2190
2414
|
};
|
|
2191
|
-
var checkedDecoration =
|
|
2415
|
+
var checkedDecoration = Decoration10.replace({
|
|
2192
2416
|
widget: new CheckboxWidget(true)
|
|
2193
2417
|
});
|
|
2194
|
-
var uncheckedDecoration =
|
|
2418
|
+
var uncheckedDecoration = Decoration10.replace({
|
|
2195
2419
|
widget: new CheckboxWidget(false)
|
|
2196
2420
|
});
|
|
2197
|
-
var
|
|
2198
|
-
const builder = new
|
|
2421
|
+
var buildDecorations6 = (view) => {
|
|
2422
|
+
const builder = new RangeSetBuilder7();
|
|
2199
2423
|
const { state } = view;
|
|
2200
2424
|
const cursor = state.selection.main.head;
|
|
2201
2425
|
for (const { from, to } of view.visibleRanges) {
|
|
2202
|
-
|
|
2426
|
+
syntaxTree8(state).iterate({
|
|
2203
2427
|
enter: (node) => {
|
|
2204
2428
|
if (node.name === "TaskMarker") {
|
|
2205
2429
|
if (cursor < node.from || cursor > node.to) {
|
|
2206
2430
|
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2207
|
-
builder.add(node.from - 2, node.from - 1,
|
|
2431
|
+
builder.add(node.from - 2, node.from - 1, Decoration10.mark({
|
|
2208
2432
|
class: "cm-task"
|
|
2209
2433
|
}));
|
|
2210
2434
|
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
@@ -2219,24 +2443,58 @@ var buildDecorations4 = (view) => {
|
|
|
2219
2443
|
};
|
|
2220
2444
|
var tasklist = (options = {}) => {
|
|
2221
2445
|
return [
|
|
2222
|
-
|
|
2446
|
+
ViewPlugin8.fromClass(class {
|
|
2223
2447
|
constructor(view) {
|
|
2224
|
-
this.decorations =
|
|
2448
|
+
this.decorations = buildDecorations6(view);
|
|
2225
2449
|
}
|
|
2226
2450
|
update(update2) {
|
|
2227
2451
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2228
|
-
this.decorations =
|
|
2452
|
+
this.decorations = buildDecorations6(update2.view);
|
|
2229
2453
|
}
|
|
2230
2454
|
}
|
|
2231
2455
|
}, {
|
|
2232
|
-
decorations: (
|
|
2456
|
+
decorations: (value) => value.decorations
|
|
2233
2457
|
}),
|
|
2234
2458
|
styles5
|
|
2235
2459
|
];
|
|
2236
2460
|
};
|
|
2237
2461
|
|
|
2462
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2463
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2464
|
+
var mention = ({ onSearch }) => {
|
|
2465
|
+
return autocompletion2({
|
|
2466
|
+
// TODO(burdon): Not working.
|
|
2467
|
+
activateOnTyping: true,
|
|
2468
|
+
// activateOnTypingDelay: 100,
|
|
2469
|
+
// selectOnOpen: true,
|
|
2470
|
+
closeOnBlur: false,
|
|
2471
|
+
// defaultKeymap: false,
|
|
2472
|
+
icons: false,
|
|
2473
|
+
override: [
|
|
2474
|
+
(context) => {
|
|
2475
|
+
console.log(context);
|
|
2476
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2477
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2478
|
+
return null;
|
|
2479
|
+
}
|
|
2480
|
+
return {
|
|
2481
|
+
from: match.from,
|
|
2482
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2483
|
+
label: `@${value}`
|
|
2484
|
+
}))
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
]
|
|
2488
|
+
});
|
|
2489
|
+
};
|
|
2490
|
+
|
|
2491
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2492
|
+
var outliner = (options = {}) => {
|
|
2493
|
+
return [];
|
|
2494
|
+
};
|
|
2495
|
+
|
|
2238
2496
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2239
|
-
import { keymap as
|
|
2497
|
+
import { keymap as keymap6 } from "@codemirror/view";
|
|
2240
2498
|
var defaultItems = [
|
|
2241
2499
|
"hello world!",
|
|
2242
2500
|
"this is a test.",
|
|
@@ -2246,7 +2504,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2246
2504
|
let t;
|
|
2247
2505
|
let idx = 0;
|
|
2248
2506
|
return [
|
|
2249
|
-
|
|
2507
|
+
keymap6.of([
|
|
2250
2508
|
{
|
|
2251
2509
|
// Reset.
|
|
2252
2510
|
key: "alt-meta-'",
|
|
@@ -2323,8 +2581,9 @@ var defaultTheme = {
|
|
|
2323
2581
|
outline: "none"
|
|
2324
2582
|
},
|
|
2325
2583
|
".cm-scroller": {
|
|
2326
|
-
overflow:
|
|
2327
|
-
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2584
|
+
// overflow: 'visible',
|
|
2585
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(","),
|
|
2586
|
+
lineHeight: 1.4
|
|
2328
2587
|
},
|
|
2329
2588
|
".cm-content": {
|
|
2330
2589
|
padding: 0,
|
|
@@ -2348,8 +2607,11 @@ var defaultTheme = {
|
|
|
2348
2607
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2349
2608
|
borderLeft: "2px solid white"
|
|
2350
2609
|
},
|
|
2351
|
-
".cm-placeholder": {
|
|
2352
|
-
|
|
2610
|
+
"&light .cm-placeholder": {
|
|
2611
|
+
color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
2612
|
+
},
|
|
2613
|
+
"&dark .cm-placeholder": {
|
|
2614
|
+
color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
2353
2615
|
},
|
|
2354
2616
|
//
|
|
2355
2617
|
// line
|
|
@@ -2358,7 +2620,7 @@ var defaultTheme = {
|
|
|
2358
2620
|
paddingInline: 0
|
|
2359
2621
|
},
|
|
2360
2622
|
".cm-activeLine": {
|
|
2361
|
-
background: "
|
|
2623
|
+
background: "transparent"
|
|
2362
2624
|
},
|
|
2363
2625
|
//
|
|
2364
2626
|
// Selection
|
|
@@ -2529,15 +2791,12 @@ var codeTheme = {
|
|
|
2529
2791
|
};
|
|
2530
2792
|
|
|
2531
2793
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2532
|
-
var
|
|
2794
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2533
2795
|
var EditorModes = [
|
|
2534
2796
|
"default",
|
|
2535
2797
|
"vim"
|
|
2536
2798
|
];
|
|
2537
2799
|
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2538
|
-
const tabsterDOMAttribute = useFocusableGroup({
|
|
2539
|
-
tabBehavior: "limited"
|
|
2540
|
-
});
|
|
2541
2800
|
const { themeMode } = useThemeContext();
|
|
2542
2801
|
const rootRef = useRef(null);
|
|
2543
2802
|
const [view, setView] = useState(null);
|
|
@@ -2545,7 +2804,15 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2545
2804
|
view
|
|
2546
2805
|
]);
|
|
2547
2806
|
useEffect2(() => {
|
|
2548
|
-
if (autoFocus) {
|
|
2807
|
+
if (autoFocus && !view?.hasFocus) {
|
|
2808
|
+
if (view?.state.selection.main?.from === 0) {
|
|
2809
|
+
const { to } = view.state.doc.lineAt(0);
|
|
2810
|
+
view?.dispatch({
|
|
2811
|
+
selection: {
|
|
2812
|
+
anchor: to
|
|
2813
|
+
}
|
|
2814
|
+
});
|
|
2815
|
+
}
|
|
2549
2816
|
view?.focus();
|
|
2550
2817
|
}
|
|
2551
2818
|
}, [
|
|
@@ -2563,8 +2830,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2563
2830
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2564
2831
|
EditorView13.exceptionSink.of((err) => {
|
|
2565
2832
|
log2.catch(err, void 0, {
|
|
2566
|
-
F:
|
|
2567
|
-
L:
|
|
2833
|
+
F: __dxlog_file3,
|
|
2834
|
+
L: 134,
|
|
2568
2835
|
S: void 0,
|
|
2569
2836
|
C: (f, a) => f(...a)
|
|
2570
2837
|
});
|
|
@@ -2581,15 +2848,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2581
2848
|
class: slots.content?.className ?? ""
|
|
2582
2849
|
}),
|
|
2583
2850
|
// State.
|
|
2851
|
+
EditorView13.editable.of(!readonly),
|
|
2584
2852
|
EditorState2.readOnly.of(!!readonly),
|
|
2585
2853
|
// Storage and replication.
|
|
2586
2854
|
// NOTE: This must come before user extensions.
|
|
2587
2855
|
model.extension,
|
|
2588
|
-
// TODO(burdon): Factor out (
|
|
2856
|
+
// TODO(burdon): Factor out? (Requires special handling for Escape/Enter below).
|
|
2589
2857
|
editorMode === "vim" && vim(),
|
|
2590
2858
|
// Custom.
|
|
2591
2859
|
...extensions
|
|
2592
|
-
].filter(
|
|
2860
|
+
].filter(isNotFalsy3)
|
|
2593
2861
|
});
|
|
2594
2862
|
const newView = new EditorView13({
|
|
2595
2863
|
state,
|
|
@@ -2626,7 +2894,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2626
2894
|
}
|
|
2627
2895
|
case "Escape": {
|
|
2628
2896
|
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2629
|
-
|
|
2897
|
+
view?.focus();
|
|
2630
2898
|
}
|
|
2631
2899
|
break;
|
|
2632
2900
|
}
|
|
@@ -2639,9 +2907,9 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2639
2907
|
key: model.id,
|
|
2640
2908
|
role: "none",
|
|
2641
2909
|
tabIndex: 0,
|
|
2642
|
-
onKeyUp: handleKeyUp,
|
|
2643
2910
|
...slots.root,
|
|
2644
|
-
...editorMode !==
|
|
2911
|
+
// {...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
2912
|
+
onKeyUp: handleKeyUp,
|
|
2645
2913
|
ref: rootRef
|
|
2646
2914
|
});
|
|
2647
2915
|
});
|
|
@@ -2652,7 +2920,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2652
2920
|
ref: forwardedRef,
|
|
2653
2921
|
readonly,
|
|
2654
2922
|
extensions: [
|
|
2655
|
-
|
|
2923
|
+
createBasicBundle({
|
|
2656
2924
|
themeMode,
|
|
2657
2925
|
placeholder: placeholder3,
|
|
2658
2926
|
lineWrapping
|
|
@@ -2671,9 +2939,8 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2671
2939
|
ref: forwardedRef,
|
|
2672
2940
|
readonly,
|
|
2673
2941
|
extensions: [
|
|
2674
|
-
|
|
2942
|
+
createMarkdownExtensions({
|
|
2675
2943
|
themeMode,
|
|
2676
|
-
readonly,
|
|
2677
2944
|
placeholder: placeholder3
|
|
2678
2945
|
}),
|
|
2679
2946
|
...extensions
|
|
@@ -2685,11 +2952,10 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2685
2952
|
});
|
|
2686
2953
|
var defaultSlots = {
|
|
2687
2954
|
root: {
|
|
2688
|
-
|
|
2689
|
-
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
2955
|
+
className: mx3("grow", focusRing)
|
|
2690
2956
|
},
|
|
2691
2957
|
editor: {
|
|
2692
|
-
className: "
|
|
2958
|
+
className: "bs-full"
|
|
2693
2959
|
}
|
|
2694
2960
|
};
|
|
2695
2961
|
var defaultTextSlots = {
|
|
@@ -2699,12 +2965,173 @@ var defaultMarkdownSlots = {
|
|
|
2699
2965
|
...defaultSlots
|
|
2700
2966
|
};
|
|
2701
2967
|
|
|
2968
|
+
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
2969
|
+
import { At, CaretRight, ChatText, Code, Image, Link, ListBullets, ListChecks, ListNumbers, TextStrikethrough, Table as Table2, TextB, TextItalic } from "@phosphor-icons/react";
|
|
2970
|
+
import { createContext } from "@radix-ui/react-context";
|
|
2971
|
+
import React2 from "react";
|
|
2972
|
+
import { Button, DensityProvider, Select } from "@dxos/react-ui";
|
|
2973
|
+
import { getSize } from "@dxos/react-ui-theme";
|
|
2974
|
+
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
2975
|
+
var ToolbarRoot = ({ children, onAction }) => {
|
|
2976
|
+
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
2977
|
+
onAction
|
|
2978
|
+
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
2979
|
+
density: "fine"
|
|
2980
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
2981
|
+
role: "toolbar",
|
|
2982
|
+
className: "flex w-full shrink-0 p-2 gap-4 items-center whitespace-nowrap overflow-hidden"
|
|
2983
|
+
}, children)));
|
|
2984
|
+
};
|
|
2985
|
+
var ToolbarButton = ({ Icon, onClick, title }) => {
|
|
2986
|
+
const { onAction } = useToolbarContext("ToolbarButton");
|
|
2987
|
+
const handleClick = () => {
|
|
2988
|
+
const action = onClick();
|
|
2989
|
+
if (action) {
|
|
2990
|
+
onAction?.(action);
|
|
2991
|
+
}
|
|
2992
|
+
};
|
|
2993
|
+
return /* @__PURE__ */ React2.createElement(Button, {
|
|
2994
|
+
variant: "ghost",
|
|
2995
|
+
classNames: "p-2",
|
|
2996
|
+
onClick: handleClick,
|
|
2997
|
+
title
|
|
2998
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
2999
|
+
className: getSize(5)
|
|
3000
|
+
}));
|
|
3001
|
+
};
|
|
3002
|
+
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3003
|
+
className: "grow"
|
|
3004
|
+
});
|
|
3005
|
+
var MarkdownHeading = () => {
|
|
3006
|
+
const { onAction } = useToolbarContext("MarkdownFormatting");
|
|
3007
|
+
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
3008
|
+
defaultValue: "0",
|
|
3009
|
+
onValueChange: (value) => onAction?.({
|
|
3010
|
+
type: "heading",
|
|
3011
|
+
data: parseInt(value)
|
|
3012
|
+
})
|
|
3013
|
+
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
|
|
3014
|
+
classNames: "w-[8rem]"
|
|
3015
|
+
}), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3016
|
+
value: "0"
|
|
3017
|
+
}, "Paragraph"), [
|
|
3018
|
+
1,
|
|
3019
|
+
2,
|
|
3020
|
+
3,
|
|
3021
|
+
4,
|
|
3022
|
+
5,
|
|
3023
|
+
6
|
|
3024
|
+
].map((level) => /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3025
|
+
key: level,
|
|
3026
|
+
value: String(level)
|
|
3027
|
+
}, "Heading ", level))))));
|
|
3028
|
+
};
|
|
3029
|
+
var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3030
|
+
role: "none"
|
|
3031
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3032
|
+
Icon: TextB,
|
|
3033
|
+
title: "Bold",
|
|
3034
|
+
onClick: () => ({
|
|
3035
|
+
type: "bold"
|
|
3036
|
+
})
|
|
3037
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3038
|
+
Icon: TextItalic,
|
|
3039
|
+
title: "Italic",
|
|
3040
|
+
onClick: () => ({
|
|
3041
|
+
type: "italic"
|
|
3042
|
+
})
|
|
3043
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3044
|
+
Icon: TextStrikethrough,
|
|
3045
|
+
title: "Strike-through",
|
|
3046
|
+
onClick: () => ({
|
|
3047
|
+
type: "strikethrough"
|
|
3048
|
+
})
|
|
3049
|
+
}));
|
|
3050
|
+
var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3051
|
+
role: "none"
|
|
3052
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3053
|
+
Icon: ListBullets,
|
|
3054
|
+
title: "Bullet list",
|
|
3055
|
+
onClick: () => ({
|
|
3056
|
+
type: "list"
|
|
3057
|
+
})
|
|
3058
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3059
|
+
Icon: ListNumbers,
|
|
3060
|
+
title: "Numbered list",
|
|
3061
|
+
onClick: () => ({
|
|
3062
|
+
type: "list-ordered"
|
|
3063
|
+
})
|
|
3064
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3065
|
+
Icon: ListChecks,
|
|
3066
|
+
title: "Task list",
|
|
3067
|
+
onClick: () => ({
|
|
3068
|
+
type: "list-tasks"
|
|
3069
|
+
})
|
|
3070
|
+
}));
|
|
3071
|
+
var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3072
|
+
role: "none"
|
|
3073
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3074
|
+
Icon: CaretRight,
|
|
3075
|
+
title: "Block quite",
|
|
3076
|
+
onClick: () => ({
|
|
3077
|
+
type: "blockquote"
|
|
3078
|
+
})
|
|
3079
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3080
|
+
Icon: Code,
|
|
3081
|
+
title: "Code block",
|
|
3082
|
+
onClick: () => ({
|
|
3083
|
+
type: "codeblock"
|
|
3084
|
+
})
|
|
3085
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3086
|
+
Icon: Table2,
|
|
3087
|
+
title: "Table",
|
|
3088
|
+
onClick: () => ({
|
|
3089
|
+
type: "table"
|
|
3090
|
+
})
|
|
3091
|
+
}));
|
|
3092
|
+
var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3093
|
+
role: "none"
|
|
3094
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3095
|
+
Icon: Link,
|
|
3096
|
+
title: "Link",
|
|
3097
|
+
onClick: () => ({
|
|
3098
|
+
type: "link"
|
|
3099
|
+
})
|
|
3100
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3101
|
+
Icon: At,
|
|
3102
|
+
title: "Mention",
|
|
3103
|
+
onClick: () => ({
|
|
3104
|
+
type: "mention"
|
|
3105
|
+
})
|
|
3106
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3107
|
+
Icon: Image,
|
|
3108
|
+
title: "Image",
|
|
3109
|
+
onClick: () => ({
|
|
3110
|
+
type: "image"
|
|
3111
|
+
})
|
|
3112
|
+
}));
|
|
3113
|
+
var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null), /* @__PURE__ */ React2.createElement(MarkdownLinks, null));
|
|
3114
|
+
var MarkdownExtended = () => /* @__PURE__ */ React2.createElement(Toolbar.Button, {
|
|
3115
|
+
Icon: ChatText,
|
|
3116
|
+
title: "Create comment",
|
|
3117
|
+
onClick: () => ({
|
|
3118
|
+
type: "comment"
|
|
3119
|
+
})
|
|
3120
|
+
});
|
|
3121
|
+
var Toolbar = {
|
|
3122
|
+
Root: ToolbarRoot,
|
|
3123
|
+
Button: ToolbarButton,
|
|
3124
|
+
Separator: ToolbarSeparator,
|
|
3125
|
+
Markdown: MarkdownStandard,
|
|
3126
|
+
Extended: MarkdownExtended
|
|
3127
|
+
};
|
|
3128
|
+
|
|
2702
3129
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2703
3130
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2704
3131
|
import { Context as Context2 } from "@dxos/context";
|
|
2705
|
-
import { invariant as
|
|
3132
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
2706
3133
|
import { log as log3 } from "@dxos/log";
|
|
2707
|
-
var
|
|
3134
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2708
3135
|
var DEBOUNCE_INTERVAL = 100;
|
|
2709
3136
|
var SpaceAwarenessProvider = class {
|
|
2710
3137
|
constructor(params) {
|
|
@@ -2744,7 +3171,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2744
3171
|
log3.debug("failed to query awareness", {
|
|
2745
3172
|
err
|
|
2746
3173
|
}, {
|
|
2747
|
-
F:
|
|
3174
|
+
F: __dxlog_file4,
|
|
2748
3175
|
L: 89,
|
|
2749
3176
|
S: this,
|
|
2750
3177
|
C: (f, a) => f(...a)
|
|
@@ -2760,8 +3187,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2760
3187
|
return Array.from(this._remoteStates.values());
|
|
2761
3188
|
}
|
|
2762
3189
|
update(position) {
|
|
2763
|
-
|
|
2764
|
-
F:
|
|
3190
|
+
invariant2(this._postTask, void 0, {
|
|
3191
|
+
F: __dxlog_file4,
|
|
2765
3192
|
L: 104,
|
|
2766
3193
|
S: this,
|
|
2767
3194
|
A: [
|
|
@@ -2777,8 +3204,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2777
3204
|
this._postTask.schedule();
|
|
2778
3205
|
}
|
|
2779
3206
|
_handleQueryMessage() {
|
|
2780
|
-
|
|
2781
|
-
F:
|
|
3207
|
+
invariant2(this._postTask, void 0, {
|
|
3208
|
+
F: __dxlog_file4,
|
|
2782
3209
|
L: 115,
|
|
2783
3210
|
S: this,
|
|
2784
3211
|
A: [
|
|
@@ -2789,8 +3216,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2789
3216
|
this._postTask.schedule();
|
|
2790
3217
|
}
|
|
2791
3218
|
_handlePostMessage(message) {
|
|
2792
|
-
|
|
2793
|
-
F:
|
|
3219
|
+
invariant2(message.kind === "post", void 0, {
|
|
3220
|
+
F: __dxlog_file4,
|
|
2794
3221
|
L: 120,
|
|
2795
3222
|
S: this,
|
|
2796
3223
|
A: [
|
|
@@ -2810,9 +3237,50 @@ var modelState = StateField5.define({
|
|
|
2810
3237
|
update: (model) => model
|
|
2811
3238
|
});
|
|
2812
3239
|
|
|
2813
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
3240
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
3241
|
+
var useActionHandler = (view) => {
|
|
3242
|
+
return (action) => {
|
|
3243
|
+
if (!view) {
|
|
3244
|
+
return;
|
|
3245
|
+
}
|
|
3246
|
+
switch (action.type) {
|
|
3247
|
+
case "heading":
|
|
3248
|
+
setHeading(parseInt(action.data))(view);
|
|
3249
|
+
break;
|
|
3250
|
+
case "bold":
|
|
3251
|
+
toggleBold(view);
|
|
3252
|
+
break;
|
|
3253
|
+
case "italic":
|
|
3254
|
+
toggleItalic(view);
|
|
3255
|
+
break;
|
|
3256
|
+
case "strikethrough":
|
|
3257
|
+
toggleStrikethrough(view);
|
|
3258
|
+
break;
|
|
3259
|
+
case "list":
|
|
3260
|
+
toggleList(view);
|
|
3261
|
+
break;
|
|
3262
|
+
case "codeblock":
|
|
3263
|
+
insertCodeblock(view);
|
|
3264
|
+
break;
|
|
3265
|
+
case "table":
|
|
3266
|
+
insertTable(view);
|
|
3267
|
+
break;
|
|
3268
|
+
case "comment":
|
|
3269
|
+
createComment(view);
|
|
3270
|
+
break;
|
|
3271
|
+
}
|
|
3272
|
+
setTimeout(() => {
|
|
3273
|
+
view.focus();
|
|
3274
|
+
view.dispatch({
|
|
3275
|
+
selection: view.state.selection
|
|
3276
|
+
});
|
|
3277
|
+
});
|
|
3278
|
+
};
|
|
3279
|
+
};
|
|
3280
|
+
|
|
3281
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
2814
3282
|
import { useState as useState2 } from "react";
|
|
2815
|
-
var
|
|
3283
|
+
var useEditorView = () => {
|
|
2816
3284
|
const [view, setView] = useState2(null);
|
|
2817
3285
|
return [
|
|
2818
3286
|
(ref) => {
|
|
@@ -2822,29 +3290,144 @@ var useTextEditor = () => {
|
|
|
2822
3290
|
];
|
|
2823
3291
|
};
|
|
2824
3292
|
|
|
3293
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3294
|
+
import { EditorSelection, EditorState as EditorState3 } from "@codemirror/state";
|
|
3295
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
3296
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
3297
|
+
import { log as log4 } from "@dxos/log";
|
|
3298
|
+
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
3299
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
3300
|
+
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
|
|
3301
|
+
const onUpdate = useRef2();
|
|
3302
|
+
const [view, setView] = useState3();
|
|
3303
|
+
const parentRef = useRef2(null);
|
|
3304
|
+
useEffect3(() => {
|
|
3305
|
+
if (parentRef.current) {
|
|
3306
|
+
const state = EditorState3.create({
|
|
3307
|
+
doc,
|
|
3308
|
+
selection,
|
|
3309
|
+
extensions: [
|
|
3310
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3311
|
+
EditorView14.exceptionSink.of((err) => {
|
|
3312
|
+
log4.catch(err, void 0, {
|
|
3313
|
+
F: __dxlog_file5,
|
|
3314
|
+
L: 57,
|
|
3315
|
+
S: void 0,
|
|
3316
|
+
C: (f, a) => f(...a)
|
|
3317
|
+
});
|
|
3318
|
+
}),
|
|
3319
|
+
extensions,
|
|
3320
|
+
EditorView14.updateListener.of(() => {
|
|
3321
|
+
onUpdate.current?.();
|
|
3322
|
+
})
|
|
3323
|
+
].filter(isNotFalsy4)
|
|
3324
|
+
});
|
|
3325
|
+
const view2 = new EditorView14({
|
|
3326
|
+
parent: parentRef.current,
|
|
3327
|
+
scrollTo,
|
|
3328
|
+
state,
|
|
3329
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
3330
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
3331
|
+
dispatchTransactions: (trs, view3) => {
|
|
3332
|
+
if (debug) {
|
|
3333
|
+
logChanges(trs);
|
|
3334
|
+
}
|
|
3335
|
+
view3.update(trs);
|
|
3336
|
+
}
|
|
3337
|
+
});
|
|
3338
|
+
setView(view2);
|
|
3339
|
+
}
|
|
3340
|
+
return () => {
|
|
3341
|
+
view?.destroy();
|
|
3342
|
+
};
|
|
3343
|
+
}, [
|
|
3344
|
+
parentRef
|
|
3345
|
+
]);
|
|
3346
|
+
useEffect3(() => {
|
|
3347
|
+
if (view) {
|
|
3348
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
3349
|
+
selection = EditorSelection.single(view.state.doc.line(1).to);
|
|
3350
|
+
}
|
|
3351
|
+
if (selection || scrollTo) {
|
|
3352
|
+
onUpdate.current = () => {
|
|
3353
|
+
onUpdate.current = void 0;
|
|
3354
|
+
view.dispatch({
|
|
3355
|
+
selection,
|
|
3356
|
+
effects: scrollTo && [
|
|
3357
|
+
scrollTo
|
|
3358
|
+
],
|
|
3359
|
+
scrollIntoView: !scrollTo
|
|
3360
|
+
});
|
|
3361
|
+
};
|
|
3362
|
+
}
|
|
3363
|
+
if (autoFocus) {
|
|
3364
|
+
view.focus();
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
}, [
|
|
3368
|
+
view,
|
|
3369
|
+
autoFocus,
|
|
3370
|
+
selection,
|
|
3371
|
+
scrollTo
|
|
3372
|
+
]);
|
|
3373
|
+
return {
|
|
3374
|
+
parentRef,
|
|
3375
|
+
view
|
|
3376
|
+
};
|
|
3377
|
+
};
|
|
3378
|
+
var createDataExtensions = ({ readonly = false } = {}) => {
|
|
3379
|
+
return [
|
|
3380
|
+
//
|
|
3381
|
+
EditorState3.readOnly.of(readonly),
|
|
3382
|
+
EditorView14.editable.of(!readonly)
|
|
3383
|
+
];
|
|
3384
|
+
};
|
|
3385
|
+
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
3386
|
+
return [
|
|
3387
|
+
//
|
|
3388
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3389
|
+
theme && EditorView14.theme(theme),
|
|
3390
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3391
|
+
EditorView14.editorAttributes.of({
|
|
3392
|
+
class: slots?.editor?.className ?? ""
|
|
3393
|
+
}),
|
|
3394
|
+
EditorView14.contentAttributes.of({
|
|
3395
|
+
class: slots?.content?.className ?? ""
|
|
3396
|
+
})
|
|
3397
|
+
].filter(isNotFalsy4);
|
|
3398
|
+
};
|
|
3399
|
+
|
|
2825
3400
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2826
3401
|
import get4 from "lodash.get";
|
|
2827
|
-
import { useEffect as
|
|
3402
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
2828
3403
|
import { generateName } from "@dxos/display-name";
|
|
2829
3404
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
2830
|
-
import { invariant as
|
|
3405
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2831
3406
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2832
|
-
|
|
2833
|
-
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
3407
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2834
3408
|
var useTextModel = (props) => {
|
|
2835
3409
|
const { identity, space, text } = props;
|
|
2836
|
-
const [model, setModel] =
|
|
2837
|
-
|
|
3410
|
+
const [model, setModel] = useState4();
|
|
3411
|
+
useEffect4(() => setModel(createModel(props)), [
|
|
2838
3412
|
identity,
|
|
2839
3413
|
space,
|
|
2840
3414
|
text
|
|
2841
3415
|
]);
|
|
2842
3416
|
return model;
|
|
2843
3417
|
};
|
|
3418
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
3419
|
+
const [content, setContent] = useState4(defaultContent ?? "");
|
|
3420
|
+
return {
|
|
3421
|
+
id,
|
|
3422
|
+
content,
|
|
3423
|
+
setContent,
|
|
3424
|
+
text: () => content
|
|
3425
|
+
};
|
|
3426
|
+
};
|
|
2844
3427
|
var createModel = ({ space, identity, text }) => {
|
|
2845
|
-
|
|
2846
|
-
F:
|
|
2847
|
-
L:
|
|
3428
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
3429
|
+
F: __dxlog_file6,
|
|
3430
|
+
L: 50,
|
|
2848
3431
|
S: void 0,
|
|
2849
3432
|
A: [
|
|
2850
3433
|
"isAutomergeObject(text)",
|
|
@@ -2855,7 +3438,7 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2855
3438
|
const doc = getRawDoc(obj, [
|
|
2856
3439
|
obj.field
|
|
2857
3440
|
]);
|
|
2858
|
-
const
|
|
3441
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
2859
3442
|
space,
|
|
2860
3443
|
channel: `automerge.awareness.${obj.id}`,
|
|
2861
3444
|
info: {
|
|
@@ -2865,19 +3448,22 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2865
3448
|
},
|
|
2866
3449
|
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2867
3450
|
});
|
|
3451
|
+
const extensions = [
|
|
3452
|
+
//
|
|
3453
|
+
modelState.init(() => model),
|
|
3454
|
+
automerge({
|
|
3455
|
+
handle: doc.handle,
|
|
3456
|
+
path: doc.path
|
|
3457
|
+
})
|
|
3458
|
+
];
|
|
3459
|
+
if (awarenessProvider2) {
|
|
3460
|
+
extensions.push(awareness(awarenessProvider2));
|
|
3461
|
+
}
|
|
2868
3462
|
const model = {
|
|
2869
3463
|
id: obj.id,
|
|
2870
3464
|
content: doc,
|
|
2871
3465
|
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2872
|
-
extension:
|
|
2873
|
-
modelState.init(() => model),
|
|
2874
|
-
automerge3({
|
|
2875
|
-
handle: doc.handle,
|
|
2876
|
-
path: doc.path
|
|
2877
|
-
}),
|
|
2878
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2879
|
-
awareness()
|
|
2880
|
-
].filter(isNotNullOrUndefined),
|
|
3466
|
+
extension: extensions,
|
|
2881
3467
|
peer: identity ? {
|
|
2882
3468
|
id: identity.identityKey.toHex(),
|
|
2883
3469
|
name: identity.profile?.displayName
|
|
@@ -2886,7 +3472,6 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2886
3472
|
return model;
|
|
2887
3473
|
};
|
|
2888
3474
|
export {
|
|
2889
|
-
AwarenessProvider,
|
|
2890
3475
|
BaseTextEditor,
|
|
2891
3476
|
Cursor,
|
|
2892
3477
|
Doc,
|
|
@@ -2896,29 +3481,40 @@ export {
|
|
|
2896
3481
|
SpaceAwarenessProvider,
|
|
2897
3482
|
TextEditor,
|
|
2898
3483
|
TextKind,
|
|
3484
|
+
Toolbar,
|
|
2899
3485
|
YText,
|
|
2900
3486
|
YXmlFragment,
|
|
2901
3487
|
autocomplete,
|
|
2902
|
-
|
|
3488
|
+
automerge,
|
|
2903
3489
|
awareness,
|
|
2904
|
-
|
|
3490
|
+
awarenessProvider,
|
|
2905
3491
|
blast,
|
|
2906
3492
|
callbackWrapper,
|
|
2907
3493
|
code2 as code,
|
|
2908
3494
|
codeTheme,
|
|
2909
3495
|
comments,
|
|
3496
|
+
createBasicBundle,
|
|
3497
|
+
createComment,
|
|
3498
|
+
createDataExtensions,
|
|
3499
|
+
createMarkdownExtensions,
|
|
3500
|
+
createThemeExtensions,
|
|
2910
3501
|
defaultMarkdownSlots,
|
|
2911
3502
|
defaultOptions,
|
|
2912
3503
|
defaultSlots,
|
|
2913
3504
|
defaultTextSlots,
|
|
2914
3505
|
defaultTheme,
|
|
3506
|
+
focusComment,
|
|
3507
|
+
formatting,
|
|
2915
3508
|
getToken,
|
|
3509
|
+
heading2 as heading,
|
|
2916
3510
|
hr,
|
|
2917
3511
|
image,
|
|
3512
|
+
insertCodeblock,
|
|
3513
|
+
insertTable,
|
|
3514
|
+
keymap7 as keymap,
|
|
2918
3515
|
link,
|
|
2919
3516
|
listener,
|
|
2920
3517
|
logChanges,
|
|
2921
|
-
markdownBundle,
|
|
2922
3518
|
markdownHighlightStyle,
|
|
2923
3519
|
markdownTags,
|
|
2924
3520
|
markdownTagsExtensions,
|
|
@@ -2927,15 +3523,24 @@ export {
|
|
|
2927
3523
|
modelState,
|
|
2928
3524
|
outliner,
|
|
2929
3525
|
setComments,
|
|
2930
|
-
|
|
3526
|
+
setHeading,
|
|
2931
3527
|
setSelection,
|
|
2932
3528
|
table,
|
|
2933
3529
|
tags2 as tags,
|
|
2934
3530
|
tasklist,
|
|
2935
3531
|
textTheme,
|
|
3532
|
+
toggleBold,
|
|
3533
|
+
toggleItalic,
|
|
3534
|
+
toggleList,
|
|
3535
|
+
toggleStrikethrough,
|
|
3536
|
+
toggleStyle,
|
|
2936
3537
|
typewriter,
|
|
3538
|
+
useActionHandler,
|
|
2937
3539
|
useComments,
|
|
3540
|
+
useEditorView,
|
|
3541
|
+
useInMemoryTextModel,
|
|
2938
3542
|
useTextEditor,
|
|
2939
|
-
useTextModel
|
|
3543
|
+
useTextModel,
|
|
3544
|
+
useToolbarContext
|
|
2940
3545
|
};
|
|
2941
3546
|
//# sourceMappingURL=index.mjs.map
|