@dxos/react-ui-editor 0.3.11-main.c244d7e → 0.3.11-main.c865ffb
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 +1385 -929
- 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 +7 -11
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +3 -2
- 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/{yjs.stories.d.ts → hooks.stories.d.ts} +13 -2
- 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 +2 -4
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +2 -2
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +9 -5
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -7
- 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/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +1 -4
- package/dist/types/src/hooks/defs.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +3 -2
- 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 +39 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
- 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 +46 -36
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +41 -46
- package/src/components/TextEditor/TextEditor.tsx +46 -27
- 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 +44 -11
- package/src/extensions/automerge/cursor.ts +3 -3
- package/src/extensions/automerge/defs.ts +9 -9
- package/src/extensions/automerge/semaphore.ts +18 -24
- package/src/extensions/automerge/update-automerge.ts +12 -6
- package/src/extensions/automerge/update-codemirror.ts +5 -5
- package/src/extensions/awareness.ts +21 -35
- package/src/extensions/basic.ts +17 -15
- package/src/extensions/blast.ts +4 -1
- package/src/extensions/comments.ts +126 -78
- package/src/extensions/index.ts +0 -7
- 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/extensions/mention.ts +6 -4
- package/src/hooks/awareness-provider.ts +24 -20
- package/src/hooks/defs.ts +1 -6
- package/src/hooks/index.ts +3 -2
- package/src/hooks/useActionHandler.ts +62 -0
- package/src/hooks/useEditorView.ts +29 -0
- package/src/hooks/useTextEditor.ts +153 -0
- package/src/hooks/useTextModel.ts +65 -12
- 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/codemirror.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +0 -26
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -4
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts +0 -28
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
- package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
- package/dist/types/src/testing/proto/index.d.ts +0 -2
- package/dist/types/src/testing/proto/index.d.ts.map +0 -1
- package/dist/types/src/testing/replicator.d.ts +0 -45
- package/dist/types/src/testing/replicator.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/comments.stories.tsx +0 -357
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/code.ts +0 -104
- package/src/extensions/yjs/cursor.ts +0 -22
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.test.ts +0 -35
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -53
- package/src/hooks/yjs.ts +0 -157
- package/src/testing/index.ts +0 -6
- package/src/testing/proto/gen/schema.ts +0 -49
- package/src/testing/proto/index.ts +0 -5
- package/src/testing/proto/schema.proto +0 -15
- package/src/testing/replicator.ts +0 -184
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
- /package/src/extensions/{image.ts → markdown/image.ts} +0 -0
- /package/src/extensions/{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
|
-
import React, { forwardRef, useCallback, useEffect as
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
15
15
|
import { log as log2 } from "@dxos/log";
|
|
16
|
-
import { useThemeContext
|
|
17
|
-
import {
|
|
16
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
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,13 +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
|
-
import { EditorView } from "@codemirror/view";
|
|
58
|
-
import { next as
|
|
59
|
+
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
60
|
+
import { next as A4 } from "@dxos/automerge/automerge";
|
|
59
61
|
|
|
60
62
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
61
63
|
import get from "lodash.get";
|
|
62
|
-
import { next as
|
|
64
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
63
65
|
var cursorConverter = (handle, path) => ({
|
|
64
66
|
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
65
67
|
toCursor: (pos) => {
|
|
@@ -71,7 +73,7 @@ var cursorConverter = (handle, path) => ({
|
|
|
71
73
|
if (typeof value === "string" && value.length <= pos) {
|
|
72
74
|
return "end";
|
|
73
75
|
}
|
|
74
|
-
return
|
|
76
|
+
return A.getCursor(doc, path.slice(), pos);
|
|
75
77
|
},
|
|
76
78
|
fromCursor: (cursor) => {
|
|
77
79
|
if (cursor === "") {
|
|
@@ -89,26 +91,28 @@ var cursorConverter = (handle, path) => ({
|
|
|
89
91
|
return 0;
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
|
-
return
|
|
94
|
+
return A.getCursorPosition(doc, path.slice(), cursor);
|
|
93
95
|
}
|
|
94
96
|
});
|
|
95
97
|
|
|
96
98
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
97
99
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
98
|
-
var effectType = StateEffect.define({});
|
|
99
|
-
var reconcileAnnotationType = Annotation.define();
|
|
100
100
|
var getPath = (state, field) => state.field(field).path;
|
|
101
101
|
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
102
|
-
var
|
|
102
|
+
var updateHeadsEffect = StateEffect.define({});
|
|
103
|
+
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
103
104
|
newHeads
|
|
104
105
|
});
|
|
105
|
-
var
|
|
106
|
+
var reconcileAnnotation = Annotation.define();
|
|
107
|
+
var isReconcile = (tr) => {
|
|
108
|
+
return !!tr.annotation(reconcileAnnotation);
|
|
109
|
+
};
|
|
106
110
|
|
|
107
111
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
108
|
-
import { next as
|
|
112
|
+
import { next as A3 } from "@dxos/automerge/automerge";
|
|
109
113
|
|
|
110
114
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
111
|
-
import { next as
|
|
115
|
+
import { next as A2 } from "@dxos/automerge/automerge";
|
|
112
116
|
var updateAutomerge = (field, handle, transactions, state) => {
|
|
113
117
|
const { lastHeads, path } = state.field(field);
|
|
114
118
|
let hasChanges = false;
|
|
@@ -121,11 +125,19 @@ var updateAutomerge = (field, handle, transactions, state) => {
|
|
|
121
125
|
return void 0;
|
|
122
126
|
}
|
|
123
127
|
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
128
|
+
const invertedTransactions = [];
|
|
124
129
|
for (const tr of transactions) {
|
|
125
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB,
|
|
126
|
-
|
|
130
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
|
|
131
|
+
invertedTransactions.push({
|
|
132
|
+
from: fromA,
|
|
133
|
+
del: toA - fromA,
|
|
134
|
+
insert
|
|
135
|
+
});
|
|
127
136
|
});
|
|
128
137
|
}
|
|
138
|
+
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
|
139
|
+
A2.splice(doc, path.slice(), from, del, insert.toString());
|
|
140
|
+
});
|
|
129
141
|
});
|
|
130
142
|
return newHeads ?? void 0;
|
|
131
143
|
};
|
|
@@ -140,13 +152,13 @@ var updateCodeMirror = (view, selection, target, patches) => {
|
|
|
140
152
|
selection = selection.map(changeSet, 1);
|
|
141
153
|
view.dispatch({
|
|
142
154
|
changes: changeSet,
|
|
143
|
-
annotations:
|
|
155
|
+
annotations: reconcileAnnotation.of(false)
|
|
144
156
|
});
|
|
145
157
|
}
|
|
146
158
|
}
|
|
147
159
|
view.dispatch({
|
|
148
160
|
selection,
|
|
149
|
-
annotations:
|
|
161
|
+
annotations: reconcileAnnotation.of(false)
|
|
150
162
|
});
|
|
151
163
|
};
|
|
152
164
|
var handlePatch = (patch, target, state) => {
|
|
@@ -167,7 +179,7 @@ var handleInsert = (target, patch) => {
|
|
|
167
179
|
if (index == null) {
|
|
168
180
|
return [];
|
|
169
181
|
}
|
|
170
|
-
const text = patch.values.map((
|
|
182
|
+
const text = patch.values.map((value) => value ? value.toString() : "").join("");
|
|
171
183
|
return [
|
|
172
184
|
{
|
|
173
185
|
from: index,
|
|
@@ -245,36 +257,37 @@ var PatchSemaphore = class {
|
|
|
245
257
|
this._state = _state;
|
|
246
258
|
this._inReconcile = false;
|
|
247
259
|
}
|
|
248
|
-
// NOTE: Cannot destruct view.state.
|
|
249
260
|
reconcile(view) {
|
|
250
|
-
if (this._inReconcile) {
|
|
251
|
-
|
|
261
|
+
if (!this._inReconcile) {
|
|
262
|
+
this._inReconcile = true;
|
|
263
|
+
this.doReconcile(view);
|
|
264
|
+
this._inReconcile = false;
|
|
252
265
|
}
|
|
253
|
-
|
|
266
|
+
}
|
|
267
|
+
doReconcile(view) {
|
|
254
268
|
const path = getPath(view.state, this._state);
|
|
255
269
|
const oldHeads = getLastHeads(view.state, this._state);
|
|
256
270
|
let selection = view.state.selection;
|
|
257
|
-
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !
|
|
271
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
258
272
|
const toInvert = transactions.slice().reverse();
|
|
259
|
-
for (const
|
|
260
|
-
const inverted =
|
|
273
|
+
for (const tr of toInvert) {
|
|
274
|
+
const inverted = tr.changes.invert(tr.startState.doc);
|
|
261
275
|
selection = selection.map(inverted);
|
|
262
276
|
view.dispatch({
|
|
263
277
|
changes: inverted,
|
|
264
|
-
annotations:
|
|
278
|
+
annotations: reconcileAnnotation.of(true)
|
|
265
279
|
});
|
|
266
280
|
}
|
|
267
281
|
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
268
282
|
if (newHeads === null || newHeads === void 0) {
|
|
269
|
-
newHeads =
|
|
283
|
+
newHeads = A3.getHeads(this._handle.docSync());
|
|
270
284
|
}
|
|
271
|
-
const diff =
|
|
285
|
+
const diff = A3.equals(oldHeads, newHeads) ? [] : A3.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
272
286
|
updateCodeMirror(view, selection, path, diff);
|
|
273
287
|
view.dispatch({
|
|
274
288
|
effects: updateHeads(newHeads),
|
|
275
|
-
annotations:
|
|
289
|
+
annotations: reconcileAnnotation.of(false)
|
|
276
290
|
});
|
|
277
|
-
this._inReconcile = false;
|
|
278
291
|
}
|
|
279
292
|
};
|
|
280
293
|
|
|
@@ -292,9 +305,9 @@ var Cursor = class _Cursor {
|
|
|
292
305
|
}
|
|
293
306
|
static {
|
|
294
307
|
this.getCursorFromRange = (state, range) => {
|
|
295
|
-
const
|
|
296
|
-
const from =
|
|
297
|
-
const to =
|
|
308
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
309
|
+
const from = cursorConverter2.toCursor(range.from);
|
|
310
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
|
298
311
|
return [
|
|
299
312
|
from,
|
|
300
313
|
to
|
|
@@ -303,10 +316,10 @@ var Cursor = class _Cursor {
|
|
|
303
316
|
}
|
|
304
317
|
static {
|
|
305
318
|
this.getRangeFromCursor = (state, cursor) => {
|
|
306
|
-
const
|
|
319
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
307
320
|
const parts = cursor.split(":");
|
|
308
|
-
const from =
|
|
309
|
-
const to =
|
|
321
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
|
322
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
|
310
323
|
return from !== void 0 && to !== void 0 ? {
|
|
311
324
|
from,
|
|
312
325
|
to
|
|
@@ -316,11 +329,11 @@ var Cursor = class _Cursor {
|
|
|
316
329
|
};
|
|
317
330
|
|
|
318
331
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
319
|
-
var
|
|
320
|
-
const
|
|
332
|
+
var automerge = ({ handle, path }) => {
|
|
333
|
+
const syncState = StateField.define({
|
|
321
334
|
create: () => ({
|
|
322
335
|
path: path.slice(),
|
|
323
|
-
lastHeads:
|
|
336
|
+
lastHeads: A4.getHeads(handle.docSync()),
|
|
324
337
|
unreconciledTransactions: []
|
|
325
338
|
}),
|
|
326
339
|
update: (value, tr) => {
|
|
@@ -331,7 +344,7 @@ var automerge3 = ({ handle, path }) => {
|
|
|
331
344
|
};
|
|
332
345
|
let clearUnreconciled = false;
|
|
333
346
|
for (const effect of tr.effects) {
|
|
334
|
-
if (effect.is(
|
|
347
|
+
if (effect.is(updateHeadsEffect)) {
|
|
335
348
|
result.lastHeads = effect.value.newHeads;
|
|
336
349
|
clearUnreconciled = true;
|
|
337
350
|
}
|
|
@@ -339,80 +352,78 @@ var automerge3 = ({ handle, path }) => {
|
|
|
339
352
|
if (clearUnreconciled) {
|
|
340
353
|
result.unreconciledTransactions = [];
|
|
341
354
|
} else {
|
|
342
|
-
if (!
|
|
355
|
+
if (!isReconcile(tr)) {
|
|
343
356
|
result.unreconciledTransactions.push(tr);
|
|
344
357
|
}
|
|
345
358
|
}
|
|
346
359
|
return result;
|
|
347
360
|
}
|
|
348
361
|
});
|
|
349
|
-
const semaphore = new PatchSemaphore(handle,
|
|
362
|
+
const semaphore = new PatchSemaphore(handle, syncState);
|
|
350
363
|
return [
|
|
351
364
|
Cursor.converter.of(cursorConverter(handle, path)),
|
|
365
|
+
syncState,
|
|
366
|
+
// Reconcile external updates.
|
|
367
|
+
ViewPlugin.fromClass(class {
|
|
368
|
+
constructor(_view) {
|
|
369
|
+
this._view = _view;
|
|
370
|
+
handle.addListener("change", this._handleChange.bind(this));
|
|
371
|
+
}
|
|
372
|
+
destroy() {
|
|
373
|
+
handle.removeListener("change", this._handleChange.bind(this));
|
|
374
|
+
}
|
|
375
|
+
_handleChange() {
|
|
376
|
+
semaphore.reconcile(this._view);
|
|
377
|
+
}
|
|
378
|
+
}),
|
|
379
|
+
// Reconcile local updates.
|
|
352
380
|
EditorView.updateListener.of(({ view, changes }) => {
|
|
353
381
|
if (!changes.empty) {
|
|
354
382
|
semaphore.reconcile(view);
|
|
355
383
|
}
|
|
356
384
|
}),
|
|
357
|
-
|
|
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
|
+
})
|
|
358
396
|
];
|
|
359
397
|
};
|
|
360
398
|
|
|
361
399
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
362
400
|
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
363
|
-
import { Decoration, EditorView as EditorView2, ViewPlugin, WidgetType } from "@codemirror/view";
|
|
364
|
-
import { useEffect } from "react";
|
|
401
|
+
import { Decoration, EditorView as EditorView2, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
365
402
|
import { Event } from "@dxos/async";
|
|
366
403
|
import { Context } from "@dxos/context";
|
|
367
|
-
import { generateName } from "@dxos/display-name";
|
|
368
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
369
|
-
import { getColorForValue } from "@dxos/react-ui-theme";
|
|
370
404
|
var dummyProvider = {
|
|
371
405
|
remoteStateChange: new Event(),
|
|
372
406
|
open: () => {
|
|
373
407
|
},
|
|
374
408
|
close: () => {
|
|
375
409
|
},
|
|
410
|
+
getRemoteStates: () => [],
|
|
376
411
|
update: () => {
|
|
377
|
-
}
|
|
378
|
-
getRemoteStates: () => []
|
|
412
|
+
}
|
|
379
413
|
};
|
|
380
|
-
var
|
|
414
|
+
var awarenessProvider = Facet2.define({
|
|
381
415
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
382
416
|
});
|
|
383
417
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
384
418
|
var awareness = (provider = dummyProvider) => {
|
|
385
419
|
return [
|
|
386
|
-
|
|
387
|
-
|
|
420
|
+
awarenessProvider.of(provider),
|
|
421
|
+
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
388
422
|
decorations: (value) => value.decorations
|
|
389
423
|
}),
|
|
390
424
|
styles
|
|
391
425
|
];
|
|
392
426
|
};
|
|
393
|
-
var useAwareness = ({ awareness: awareness2, peer }) => {
|
|
394
|
-
const { themeMode } = useThemeContext();
|
|
395
|
-
useEffect(() => {
|
|
396
|
-
if (awareness2 && peer) {
|
|
397
|
-
awareness2.setLocalStateField("user", {
|
|
398
|
-
name: peer.name ?? generateName(peer.id),
|
|
399
|
-
color: getColorForValue({
|
|
400
|
-
value: peer.id,
|
|
401
|
-
type: "color"
|
|
402
|
-
}),
|
|
403
|
-
colorLight: getColorForValue({
|
|
404
|
-
value: peer.id,
|
|
405
|
-
themeMode,
|
|
406
|
-
type: "highlight"
|
|
407
|
-
})
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
}, [
|
|
411
|
-
awareness2,
|
|
412
|
-
peer,
|
|
413
|
-
themeMode
|
|
414
|
-
]);
|
|
415
|
-
};
|
|
416
427
|
var RemoteSelectionsDecorator = class {
|
|
417
428
|
constructor(view) {
|
|
418
429
|
this.decorations = RangeSet.of([]);
|
|
@@ -420,7 +431,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
420
431
|
this._lastAnchor = void 0;
|
|
421
432
|
this._lastHead = void 0;
|
|
422
433
|
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
423
|
-
this._provider = view.state.facet(
|
|
434
|
+
this._provider = view.state.facet(awarenessProvider);
|
|
424
435
|
this._provider.open();
|
|
425
436
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
426
437
|
view.dispatch({
|
|
@@ -574,39 +585,41 @@ var styles = EditorView2.baseTheme({
|
|
|
574
585
|
marginLeft: "-1px",
|
|
575
586
|
marginRight: "-1px",
|
|
576
587
|
boxSizing: "border-box",
|
|
577
|
-
display: "inline"
|
|
588
|
+
display: "inline",
|
|
589
|
+
cursor: "pointer"
|
|
578
590
|
},
|
|
579
591
|
".cm-collab-selectionCaretDot": {
|
|
580
592
|
borderRadius: "50%",
|
|
581
593
|
position: "absolute",
|
|
582
|
-
width: ".
|
|
583
|
-
height: ".
|
|
584
|
-
top: "-.
|
|
585
|
-
left: "-.
|
|
594
|
+
width: ".5em",
|
|
595
|
+
height: ".5em",
|
|
596
|
+
top: "-.25em",
|
|
597
|
+
left: "-.25em",
|
|
586
598
|
backgroundColor: "inherit",
|
|
587
599
|
transition: "transform .3s ease-in-out",
|
|
588
600
|
boxSizing: "border-box"
|
|
589
601
|
},
|
|
590
602
|
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
591
|
-
|
|
592
|
-
|
|
603
|
+
transform: "scale(0)",
|
|
604
|
+
transformOrigin: "center"
|
|
593
605
|
},
|
|
594
606
|
".cm-collab-selectionInfo": {
|
|
595
607
|
position: "absolute",
|
|
596
|
-
|
|
597
|
-
|
|
608
|
+
transform: "translate(-50%, 0)",
|
|
609
|
+
top: "-20px",
|
|
610
|
+
left: 0,
|
|
598
611
|
fontSize: ".75em",
|
|
599
|
-
fontFamily: "serif",
|
|
612
|
+
fontFamily: "sans-serif",
|
|
600
613
|
fontStyle: "normal",
|
|
601
614
|
fontWeight: "normal",
|
|
602
615
|
lineHeight: "normal",
|
|
603
616
|
userSelect: "none",
|
|
604
617
|
color: "white",
|
|
605
|
-
|
|
606
|
-
paddingRight: "2px",
|
|
618
|
+
padding: "2px",
|
|
607
619
|
zIndex: 101,
|
|
608
620
|
transition: "opacity .3s ease-in-out",
|
|
609
621
|
backgroundColor: "inherit",
|
|
622
|
+
borderRadius: "2px",
|
|
610
623
|
// These should be separate.
|
|
611
624
|
opacity: 0,
|
|
612
625
|
transitionDelay: "0s",
|
|
@@ -624,18 +637,19 @@ 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";
|
|
@@ -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,
|
|
@@ -769,7 +783,7 @@ var Blaster = class {
|
|
|
769
783
|
initialize() {
|
|
770
784
|
invariant(!this._canvas && !this._ctx, void 0, {
|
|
771
785
|
F: __dxlog_file,
|
|
772
|
-
L:
|
|
786
|
+
L: 141,
|
|
773
787
|
S: this,
|
|
774
788
|
A: [
|
|
775
789
|
"!this._canvas && !this._ctx",
|
|
@@ -806,7 +820,7 @@ var Blaster = class {
|
|
|
806
820
|
start() {
|
|
807
821
|
invariant(this._canvas && this._ctx, void 0, {
|
|
808
822
|
F: __dxlog_file,
|
|
809
|
-
L:
|
|
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,89 +1037,6 @@ 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
|
-
ViewPlugin2.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 as useEffect2 } from "react";
|
|
1119
|
-
import { debounce } from "@dxos/async";
|
|
1120
|
-
import { invariant as invariant2 } 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
1042
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
@@ -1156,24 +1073,21 @@ 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
|
},
|
|
1164
|
-
"& .cm-comment-
|
|
1080
|
+
"& .cm-comment-current": {
|
|
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,11 +1100,11 @@ 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({
|
|
1193
|
-
|
|
1107
|
+
current: id
|
|
1194
1108
|
})
|
|
1195
1109
|
]
|
|
1196
1110
|
});
|
|
@@ -1235,23 +1149,23 @@ 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
|
-
const { selection: {
|
|
1155
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1242
1156
|
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1243
1157
|
const range = comment.range;
|
|
1244
1158
|
if (!range || range.from === range.to) {
|
|
1245
1159
|
console.warn("Invalid range:", range);
|
|
1246
1160
|
return void 0;
|
|
1247
1161
|
}
|
|
1248
|
-
if (comment.comment.id ===
|
|
1249
|
-
return
|
|
1162
|
+
if (comment.comment.id === current) {
|
|
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
|
-
active: 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,17 +1382,17 @@ 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
|
-
const { selection: {
|
|
1387
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1434
1388
|
const { head } = state.selection.main;
|
|
1435
1389
|
const selection = {};
|
|
1436
1390
|
comments2.forEach(({ comment, range }) => {
|
|
1437
1391
|
if (head >= range.from && head <= range.to) {
|
|
1438
|
-
selection.
|
|
1392
|
+
selection.current = comment.id;
|
|
1439
1393
|
selection.closest = void 0;
|
|
1440
1394
|
}
|
|
1441
|
-
if (!selection.
|
|
1395
|
+
if (!selection.current) {
|
|
1442
1396
|
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1443
1397
|
if (d < min) {
|
|
1444
1398
|
selection.closest = comment.id;
|
|
@@ -1446,7 +1400,7 @@ var comments = (options = {}) => {
|
|
|
1446
1400
|
}
|
|
1447
1401
|
}
|
|
1448
1402
|
});
|
|
1449
|
-
if (selection.
|
|
1403
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1450
1404
|
view.dispatch({
|
|
1451
1405
|
effects: setSelection.of(selection)
|
|
1452
1406
|
});
|
|
@@ -1463,9 +1417,9 @@ var comments = (options = {}) => {
|
|
|
1463
1417
|
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1464
1418
|
];
|
|
1465
1419
|
};
|
|
1466
|
-
var useComments = (view, comments2) => {
|
|
1467
|
-
|
|
1468
|
-
if (view
|
|
1420
|
+
var useComments = (view, comments2 = []) => {
|
|
1421
|
+
useEffect(() => {
|
|
1422
|
+
if (view) {
|
|
1469
1423
|
view.dispatch({
|
|
1470
1424
|
effects: setComments.of(comments2)
|
|
1471
1425
|
});
|
|
@@ -1476,314 +1430,51 @@ 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
|
-
ViewPlugin3.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
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
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 ViewPlugin4, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1610
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1611
|
-
var link = (options = {}) => {
|
|
1612
|
-
const extensions = [
|
|
1613
|
-
ViewPlugin4.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";
|
|
1767
|
-
|
|
1768
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1769
|
-
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1770
|
-
import { HighlightStyle } from "@codemirror/language";
|
|
1771
|
-
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1772
|
-
import { Table } from "@lezer/markdown";
|
|
1773
|
-
var markdownTags = {
|
|
1774
|
-
Blockquote: Tag.define(),
|
|
1775
|
-
CodeMark: Tag.define(),
|
|
1776
|
-
CodeText: Tag.define(),
|
|
1777
|
-
EmphasisMark: Tag.define(),
|
|
1778
|
-
HeaderMark: Tag.define(),
|
|
1779
|
-
InlineCode: Tag.define(),
|
|
1780
|
-
LinkLabel: Tag.define(),
|
|
1781
|
-
LinkReference: Tag.define(),
|
|
1782
|
-
ListMark: Tag.define(),
|
|
1783
|
-
QuoteMark: Tag.define(),
|
|
1784
|
-
URL: Tag.define(),
|
|
1785
|
-
// Custom.
|
|
1786
|
-
TableCell: Tag.define()
|
|
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";
|
|
1458
|
+
|
|
1459
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1460
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1461
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
1462
|
+
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1463
|
+
import { Table } from "@lezer/markdown";
|
|
1464
|
+
var markdownTags = {
|
|
1465
|
+
Blockquote: Tag.define(),
|
|
1466
|
+
CodeMark: Tag.define(),
|
|
1467
|
+
CodeText: Tag.define(),
|
|
1468
|
+
EmphasisMark: Tag.define(),
|
|
1469
|
+
HeaderMark: Tag.define(),
|
|
1470
|
+
InlineCode: Tag.define(),
|
|
1471
|
+
LinkLabel: Tag.define(),
|
|
1472
|
+
LinkReference: Tag.define(),
|
|
1473
|
+
ListMark: Tag.define(),
|
|
1474
|
+
QuoteMark: Tag.define(),
|
|
1475
|
+
URL: Tag.define(),
|
|
1476
|
+
// Custom.
|
|
1477
|
+
TableCell: Tag.define()
|
|
1787
1478
|
};
|
|
1788
1479
|
Table.defineNodes?.forEach((node) => {
|
|
1789
1480
|
switch (node?.name) {
|
|
@@ -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,45 +1694,580 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
2003
1694
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2004
1695
|
...standardKeymap
|
|
2005
1696
|
])
|
|
2006
|
-
];
|
|
1697
|
+
].filter(isNotFalsy2);
|
|
2007
1698
|
};
|
|
2008
1699
|
|
|
2009
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
2010
|
-
import {
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
}
|
|
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
|
+
];
|
|
2034
1753
|
};
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
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
|
|
1812
|
+
];
|
|
1813
|
+
};
|
|
1814
|
+
|
|
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) {
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
2166
|
+
return {
|
|
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
|
+
}
|
|
2182
|
+
};
|
|
2183
|
+
})
|
|
2184
|
+
);
|
|
2185
|
+
}
|
|
2186
|
+
return extensions;
|
|
2187
|
+
};
|
|
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();
|
|
2039
2265
|
};
|
|
2040
2266
|
|
|
2041
|
-
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
2042
|
-
import { syntaxTree as
|
|
2043
|
-
import { RangeSetBuilder as
|
|
2044
|
-
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";
|
|
2045
2271
|
var table = (options = {}) => {
|
|
2046
2272
|
return StateField4.define({
|
|
2047
2273
|
create: (state) => update(state, options),
|
|
@@ -2050,7 +2276,7 @@ var table = (options = {}) => {
|
|
|
2050
2276
|
});
|
|
2051
2277
|
};
|
|
2052
2278
|
var update = (state, options) => {
|
|
2053
|
-
const builder = new
|
|
2279
|
+
const builder = new RangeSetBuilder6();
|
|
2054
2280
|
const cursor = state.selection.main.head;
|
|
2055
2281
|
const tables = [];
|
|
2056
2282
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2058,7 +2284,7 @@ var update = (state, options) => {
|
|
|
2058
2284
|
const table2 = getTable();
|
|
2059
2285
|
return table2.rows?.[table2.rows.length - 1];
|
|
2060
2286
|
};
|
|
2061
|
-
|
|
2287
|
+
syntaxTree7(state).iterate({
|
|
2062
2288
|
enter: (node) => {
|
|
2063
2289
|
switch (node.name) {
|
|
2064
2290
|
case "Table": {
|
|
@@ -2090,16 +2316,16 @@ var update = (state, options) => {
|
|
|
2090
2316
|
});
|
|
2091
2317
|
tables.forEach((table2) => {
|
|
2092
2318
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2093
|
-
hide && builder.add(table2.from, table2.to,
|
|
2319
|
+
hide && builder.add(table2.from, table2.to, Decoration9.replace({
|
|
2094
2320
|
widget: new TableWidget(table2)
|
|
2095
2321
|
}));
|
|
2096
|
-
builder.add(table2.from, table2.to,
|
|
2322
|
+
builder.add(table2.from, table2.to, Decoration9.mark({
|
|
2097
2323
|
class: "cm-table"
|
|
2098
2324
|
}));
|
|
2099
2325
|
});
|
|
2100
2326
|
return builder.finish();
|
|
2101
2327
|
};
|
|
2102
|
-
var TableWidget = class extends
|
|
2328
|
+
var TableWidget = class extends WidgetType6 {
|
|
2103
2329
|
constructor(_table) {
|
|
2104
2330
|
super();
|
|
2105
2331
|
this._table = _table;
|
|
@@ -2136,10 +2362,10 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2136
2362
|
}
|
|
2137
2363
|
};
|
|
2138
2364
|
|
|
2139
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2140
|
-
import { syntaxTree as
|
|
2141
|
-
import { RangeSetBuilder as
|
|
2142
|
-
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";
|
|
2143
2369
|
var styles5 = EditorView12.baseTheme({
|
|
2144
2370
|
"& .cm-task": {
|
|
2145
2371
|
color: getToken("extend.colors.blue.500")
|
|
@@ -2149,7 +2375,7 @@ var styles5 = EditorView12.baseTheme({
|
|
|
2149
2375
|
marginRight: "4px"
|
|
2150
2376
|
}
|
|
2151
2377
|
});
|
|
2152
|
-
var CheckboxWidget = class extends
|
|
2378
|
+
var CheckboxWidget = class extends WidgetType7 {
|
|
2153
2379
|
constructor(_checked) {
|
|
2154
2380
|
super();
|
|
2155
2381
|
this._checked = _checked;
|
|
@@ -2186,23 +2412,23 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2186
2412
|
return false;
|
|
2187
2413
|
}
|
|
2188
2414
|
};
|
|
2189
|
-
var checkedDecoration =
|
|
2415
|
+
var checkedDecoration = Decoration10.replace({
|
|
2190
2416
|
widget: new CheckboxWidget(true)
|
|
2191
2417
|
});
|
|
2192
|
-
var uncheckedDecoration =
|
|
2418
|
+
var uncheckedDecoration = Decoration10.replace({
|
|
2193
2419
|
widget: new CheckboxWidget(false)
|
|
2194
2420
|
});
|
|
2195
|
-
var
|
|
2196
|
-
const builder = new
|
|
2421
|
+
var buildDecorations6 = (view) => {
|
|
2422
|
+
const builder = new RangeSetBuilder7();
|
|
2197
2423
|
const { state } = view;
|
|
2198
2424
|
const cursor = state.selection.main.head;
|
|
2199
2425
|
for (const { from, to } of view.visibleRanges) {
|
|
2200
|
-
|
|
2426
|
+
syntaxTree8(state).iterate({
|
|
2201
2427
|
enter: (node) => {
|
|
2202
2428
|
if (node.name === "TaskMarker") {
|
|
2203
2429
|
if (cursor < node.from || cursor > node.to) {
|
|
2204
2430
|
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2205
|
-
builder.add(node.from - 2, node.from - 1,
|
|
2431
|
+
builder.add(node.from - 2, node.from - 1, Decoration10.mark({
|
|
2206
2432
|
class: "cm-task"
|
|
2207
2433
|
}));
|
|
2208
2434
|
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
@@ -2217,24 +2443,58 @@ var buildDecorations4 = (view) => {
|
|
|
2217
2443
|
};
|
|
2218
2444
|
var tasklist = (options = {}) => {
|
|
2219
2445
|
return [
|
|
2220
|
-
|
|
2446
|
+
ViewPlugin8.fromClass(class {
|
|
2221
2447
|
constructor(view) {
|
|
2222
|
-
this.decorations =
|
|
2448
|
+
this.decorations = buildDecorations6(view);
|
|
2223
2449
|
}
|
|
2224
2450
|
update(update2) {
|
|
2225
2451
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2226
|
-
this.decorations =
|
|
2452
|
+
this.decorations = buildDecorations6(update2.view);
|
|
2227
2453
|
}
|
|
2228
2454
|
}
|
|
2229
2455
|
}, {
|
|
2230
|
-
decorations: (
|
|
2456
|
+
decorations: (value) => value.decorations
|
|
2231
2457
|
}),
|
|
2232
2458
|
styles5
|
|
2233
2459
|
];
|
|
2234
2460
|
};
|
|
2235
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
|
+
|
|
2236
2496
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2237
|
-
import { keymap as
|
|
2497
|
+
import { keymap as keymap6 } from "@codemirror/view";
|
|
2238
2498
|
var defaultItems = [
|
|
2239
2499
|
"hello world!",
|
|
2240
2500
|
"this is a test.",
|
|
@@ -2244,7 +2504,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2244
2504
|
let t;
|
|
2245
2505
|
let idx = 0;
|
|
2246
2506
|
return [
|
|
2247
|
-
|
|
2507
|
+
keymap6.of([
|
|
2248
2508
|
{
|
|
2249
2509
|
// Reset.
|
|
2250
2510
|
key: "alt-meta-'",
|
|
@@ -2290,27 +2550,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2290
2550
|
];
|
|
2291
2551
|
};
|
|
2292
2552
|
|
|
2293
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2294
|
-
import { yCollab } from "y-codemirror.next";
|
|
2295
|
-
|
|
2296
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2297
|
-
import * as Y from "yjs";
|
|
2298
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2299
|
-
var cursorConverter2 = (text) => ({
|
|
2300
|
-
toCursor: (index, assoc) => {
|
|
2301
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2302
|
-
},
|
|
2303
|
-
fromCursor: (cursor) => {
|
|
2304
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2305
|
-
}
|
|
2306
|
-
});
|
|
2307
|
-
|
|
2308
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2309
|
-
var yjs = (content, awareness2) => [
|
|
2310
|
-
Cursor.converter.of(cursorConverter2(content)),
|
|
2311
|
-
yCollab(content, awareness2)
|
|
2312
|
-
];
|
|
2313
|
-
|
|
2314
2553
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2315
2554
|
import get3 from "lodash.get";
|
|
2316
2555
|
var defaultTheme = {
|
|
@@ -2342,8 +2581,9 @@ var defaultTheme = {
|
|
|
2342
2581
|
outline: "none"
|
|
2343
2582
|
},
|
|
2344
2583
|
".cm-scroller": {
|
|
2345
|
-
overflow:
|
|
2346
|
-
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2584
|
+
// overflow: 'visible',
|
|
2585
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(","),
|
|
2586
|
+
lineHeight: 1.4
|
|
2347
2587
|
},
|
|
2348
2588
|
".cm-content": {
|
|
2349
2589
|
padding: 0,
|
|
@@ -2367,8 +2607,11 @@ var defaultTheme = {
|
|
|
2367
2607
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2368
2608
|
borderLeft: "2px solid white"
|
|
2369
2609
|
},
|
|
2370
|
-
".cm-placeholder": {
|
|
2371
|
-
|
|
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)")
|
|
2372
2615
|
},
|
|
2373
2616
|
//
|
|
2374
2617
|
// line
|
|
@@ -2377,7 +2620,7 @@ var defaultTheme = {
|
|
|
2377
2620
|
paddingInline: 0
|
|
2378
2621
|
},
|
|
2379
2622
|
".cm-activeLine": {
|
|
2380
|
-
background: "
|
|
2623
|
+
background: "transparent"
|
|
2381
2624
|
},
|
|
2382
2625
|
//
|
|
2383
2626
|
// Selection
|
|
@@ -2548,31 +2791,35 @@ var codeTheme = {
|
|
|
2548
2791
|
};
|
|
2549
2792
|
|
|
2550
2793
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2551
|
-
var
|
|
2794
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2552
2795
|
var EditorModes = [
|
|
2553
2796
|
"default",
|
|
2554
2797
|
"vim"
|
|
2555
2798
|
];
|
|
2556
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2557
|
-
const
|
|
2558
|
-
tabBehavior: "limited"
|
|
2559
|
-
});
|
|
2560
|
-
const { themeMode } = useThemeContext2();
|
|
2799
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2800
|
+
const { themeMode } = useThemeContext();
|
|
2561
2801
|
const rootRef = useRef(null);
|
|
2562
2802
|
const [view, setView] = useState(null);
|
|
2563
2803
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2564
2804
|
view
|
|
2565
2805
|
]);
|
|
2566
|
-
|
|
2567
|
-
if (
|
|
2806
|
+
useEffect2(() => {
|
|
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
|
+
}
|
|
2568
2816
|
view?.focus();
|
|
2569
2817
|
}
|
|
2570
2818
|
}, [
|
|
2571
2819
|
view,
|
|
2572
|
-
|
|
2820
|
+
autoFocus
|
|
2573
2821
|
]);
|
|
2574
|
-
|
|
2575
|
-
useEffect3(() => {
|
|
2822
|
+
useEffect2(() => {
|
|
2576
2823
|
if (!model || !rootRef.current) {
|
|
2577
2824
|
return;
|
|
2578
2825
|
}
|
|
@@ -2583,8 +2830,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2583
2830
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2584
2831
|
EditorView13.exceptionSink.of((err) => {
|
|
2585
2832
|
log2.catch(err, void 0, {
|
|
2586
|
-
F:
|
|
2587
|
-
L:
|
|
2833
|
+
F: __dxlog_file3,
|
|
2834
|
+
L: 134,
|
|
2588
2835
|
S: void 0,
|
|
2589
2836
|
C: (f, a) => f(...a)
|
|
2590
2837
|
});
|
|
@@ -2601,15 +2848,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2601
2848
|
class: slots.content?.className ?? ""
|
|
2602
2849
|
}),
|
|
2603
2850
|
// State.
|
|
2851
|
+
EditorView13.editable.of(!readonly),
|
|
2604
2852
|
EditorState2.readOnly.of(!!readonly),
|
|
2605
2853
|
// Storage and replication.
|
|
2606
2854
|
// NOTE: This must come before user extensions.
|
|
2607
2855
|
model.extension,
|
|
2608
|
-
// TODO(burdon): Factor out (
|
|
2856
|
+
// TODO(burdon): Factor out? (Requires special handling for Escape/Enter below).
|
|
2609
2857
|
editorMode === "vim" && vim(),
|
|
2610
2858
|
// Custom.
|
|
2611
2859
|
...extensions
|
|
2612
|
-
].filter(
|
|
2860
|
+
].filter(isNotFalsy3)
|
|
2613
2861
|
});
|
|
2614
2862
|
const newView = new EditorView13({
|
|
2615
2863
|
state,
|
|
@@ -2618,11 +2866,10 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2618
2866
|
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2619
2867
|
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2620
2868
|
dispatchTransactions: (trs, view2) => {
|
|
2621
|
-
view2.update(trs);
|
|
2622
|
-
const debug = false;
|
|
2623
2869
|
if (debug) {
|
|
2624
2870
|
logChanges(trs);
|
|
2625
2871
|
}
|
|
2872
|
+
view2.update(trs);
|
|
2626
2873
|
}
|
|
2627
2874
|
});
|
|
2628
2875
|
view?.destroy();
|
|
@@ -2647,7 +2894,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2647
2894
|
}
|
|
2648
2895
|
case "Escape": {
|
|
2649
2896
|
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2650
|
-
|
|
2897
|
+
view?.focus();
|
|
2651
2898
|
}
|
|
2652
2899
|
break;
|
|
2653
2900
|
}
|
|
@@ -2660,23 +2907,23 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2660
2907
|
key: model.id,
|
|
2661
2908
|
role: "none",
|
|
2662
2909
|
tabIndex: 0,
|
|
2663
|
-
onKeyUp: handleKeyUp,
|
|
2664
2910
|
...slots.root,
|
|
2665
|
-
...editorMode !==
|
|
2911
|
+
// {...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
2912
|
+
onKeyUp: handleKeyUp,
|
|
2666
2913
|
ref: rootRef
|
|
2667
2914
|
});
|
|
2668
2915
|
});
|
|
2669
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2670
|
-
const { themeMode } =
|
|
2916
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2917
|
+
const { themeMode } = useThemeContext();
|
|
2671
2918
|
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2672
2919
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2673
2920
|
ref: forwardedRef,
|
|
2674
2921
|
readonly,
|
|
2675
2922
|
extensions: [
|
|
2676
|
-
|
|
2923
|
+
createBasicBundle({
|
|
2677
2924
|
themeMode,
|
|
2678
2925
|
placeholder: placeholder3,
|
|
2679
|
-
|
|
2926
|
+
lineWrapping
|
|
2680
2927
|
}),
|
|
2681
2928
|
...extensions
|
|
2682
2929
|
],
|
|
@@ -2686,15 +2933,14 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2686
2933
|
});
|
|
2687
2934
|
});
|
|
2688
2935
|
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2689
|
-
const { themeMode } =
|
|
2936
|
+
const { themeMode } = useThemeContext();
|
|
2690
2937
|
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2691
2938
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2692
2939
|
ref: forwardedRef,
|
|
2693
2940
|
readonly,
|
|
2694
2941
|
extensions: [
|
|
2695
|
-
|
|
2942
|
+
createMarkdownExtensions({
|
|
2696
2943
|
themeMode,
|
|
2697
|
-
readonly,
|
|
2698
2944
|
placeholder: placeholder3
|
|
2699
2945
|
}),
|
|
2700
2946
|
...extensions
|
|
@@ -2706,11 +2952,10 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2706
2952
|
});
|
|
2707
2953
|
var defaultSlots = {
|
|
2708
2954
|
root: {
|
|
2709
|
-
|
|
2710
|
-
className: mx3("flex flex-col grow overflow-y-auto", inputSurface)
|
|
2955
|
+
className: mx3("grow", focusRing)
|
|
2711
2956
|
},
|
|
2712
2957
|
editor: {
|
|
2713
|
-
className: "
|
|
2958
|
+
className: "bs-full"
|
|
2714
2959
|
}
|
|
2715
2960
|
};
|
|
2716
2961
|
var defaultTextSlots = {
|
|
@@ -2720,22 +2965,178 @@ var defaultMarkdownSlots = {
|
|
|
2720
2965
|
...defaultSlots
|
|
2721
2966
|
};
|
|
2722
2967
|
|
|
2723
|
-
// packages/ui/react-ui-editor/src/
|
|
2724
|
-
import
|
|
2725
|
-
import {
|
|
2726
|
-
import
|
|
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
|
+
};
|
|
2727
3128
|
|
|
2728
3129
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2729
3130
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2730
3131
|
import { Context as Context2 } from "@dxos/context";
|
|
2731
|
-
import { invariant as
|
|
3132
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
2732
3133
|
import { log as log3 } from "@dxos/log";
|
|
2733
|
-
var
|
|
3134
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2734
3135
|
var DEBOUNCE_INTERVAL = 100;
|
|
2735
3136
|
var SpaceAwarenessProvider = class {
|
|
2736
3137
|
constructor(params) {
|
|
2737
|
-
this.remoteStateChange = new Event2();
|
|
2738
3138
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
3139
|
+
this.remoteStateChange = new Event2();
|
|
2739
3140
|
this._space = params.space;
|
|
2740
3141
|
this._channel = params.channel;
|
|
2741
3142
|
this._peerId = params.peerId;
|
|
@@ -2752,7 +3153,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2752
3153
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2753
3154
|
}
|
|
2754
3155
|
});
|
|
2755
|
-
|
|
3156
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2756
3157
|
switch (message.payload.kind) {
|
|
2757
3158
|
case "query": {
|
|
2758
3159
|
this._handleQueryMessage();
|
|
@@ -2763,16 +3164,15 @@ var SpaceAwarenessProvider = class {
|
|
|
2763
3164
|
break;
|
|
2764
3165
|
}
|
|
2765
3166
|
}
|
|
2766
|
-
});
|
|
2767
|
-
this._ctx.onDispose(unsubscribe);
|
|
3167
|
+
}));
|
|
2768
3168
|
void this._space.postMessage(this._channel, {
|
|
2769
3169
|
kind: "query"
|
|
2770
3170
|
}).catch((err) => {
|
|
2771
3171
|
log3.debug("failed to query awareness", {
|
|
2772
3172
|
err
|
|
2773
3173
|
}, {
|
|
2774
|
-
F:
|
|
2775
|
-
L:
|
|
3174
|
+
F: __dxlog_file4,
|
|
3175
|
+
L: 89,
|
|
2776
3176
|
S: this,
|
|
2777
3177
|
C: (f, a) => f(...a)
|
|
2778
3178
|
});
|
|
@@ -2783,10 +3183,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2783
3183
|
this._ctx = void 0;
|
|
2784
3184
|
this._postTask = void 0;
|
|
2785
3185
|
}
|
|
3186
|
+
getRemoteStates() {
|
|
3187
|
+
return Array.from(this._remoteStates.values());
|
|
3188
|
+
}
|
|
2786
3189
|
update(position) {
|
|
2787
|
-
|
|
2788
|
-
F:
|
|
2789
|
-
L:
|
|
3190
|
+
invariant2(this._postTask, void 0, {
|
|
3191
|
+
F: __dxlog_file4,
|
|
3192
|
+
L: 104,
|
|
2790
3193
|
S: this,
|
|
2791
3194
|
A: [
|
|
2792
3195
|
"this._postTask",
|
|
@@ -2800,13 +3203,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2800
3203
|
};
|
|
2801
3204
|
this._postTask.schedule();
|
|
2802
3205
|
}
|
|
2803
|
-
getRemoteStates() {
|
|
2804
|
-
return Array.from(this._remoteStates.values());
|
|
2805
|
-
}
|
|
2806
3206
|
_handleQueryMessage() {
|
|
2807
|
-
|
|
2808
|
-
F:
|
|
2809
|
-
L:
|
|
3207
|
+
invariant2(this._postTask, void 0, {
|
|
3208
|
+
F: __dxlog_file4,
|
|
3209
|
+
L: 115,
|
|
2810
3210
|
S: this,
|
|
2811
3211
|
A: [
|
|
2812
3212
|
"this._postTask",
|
|
@@ -2816,9 +3216,9 @@ var SpaceAwarenessProvider = class {
|
|
|
2816
3216
|
this._postTask.schedule();
|
|
2817
3217
|
}
|
|
2818
3218
|
_handlePostMessage(message) {
|
|
2819
|
-
|
|
2820
|
-
F:
|
|
2821
|
-
L:
|
|
3219
|
+
invariant2(message.kind === "post", void 0, {
|
|
3220
|
+
F: __dxlog_file4,
|
|
3221
|
+
L: 120,
|
|
2822
3222
|
S: this,
|
|
2823
3223
|
A: [
|
|
2824
3224
|
"message.kind === 'post'",
|
|
@@ -2837,182 +3237,177 @@ var modelState = StateField5.define({
|
|
|
2837
3237
|
update: (model) => model
|
|
2838
3238
|
});
|
|
2839
3239
|
|
|
2840
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2841
|
-
var
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
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
|
+
});
|
|
2874
3278
|
};
|
|
2875
|
-
return model;
|
|
2876
3279
|
};
|
|
2877
3280
|
|
|
2878
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2879
|
-
import
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
F: __dxlog_file6,
|
|
2889
|
-
L: 22,
|
|
2890
|
-
S: void 0,
|
|
2891
|
-
A: [
|
|
2892
|
-
"text?.doc && text?.content",
|
|
2893
|
-
""
|
|
2894
|
-
]
|
|
2895
|
-
});
|
|
2896
|
-
const provider = space ? new YAwarenessProvider({
|
|
2897
|
-
space,
|
|
2898
|
-
doc: text.doc,
|
|
2899
|
-
channel: `yjs.awareness.${text.id}`
|
|
2900
|
-
}) : void 0;
|
|
2901
|
-
const model = {
|
|
2902
|
-
id: text.doc.guid,
|
|
2903
|
-
content: text.content,
|
|
2904
|
-
text: () => text.content.toString(),
|
|
2905
|
-
extension: [
|
|
2906
|
-
modelState.init(() => model),
|
|
2907
|
-
yjs(text.content, provider?.awareness)
|
|
2908
|
-
],
|
|
2909
|
-
awareness: provider?.awareness,
|
|
2910
|
-
peer: identity ? {
|
|
2911
|
-
id: identity.identityKey.toHex(),
|
|
2912
|
-
name: identity.profile?.displayName
|
|
2913
|
-
} : void 0
|
|
2914
|
-
};
|
|
2915
|
-
return model;
|
|
3281
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3282
|
+
import { useState as useState2 } from "react";
|
|
3283
|
+
var useEditorView = () => {
|
|
3284
|
+
const [view, setView] = useState2(null);
|
|
3285
|
+
return [
|
|
3286
|
+
(ref) => {
|
|
3287
|
+
setView(ref);
|
|
3288
|
+
},
|
|
3289
|
+
view
|
|
3290
|
+
];
|
|
2916
3291
|
};
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
_handleSpaceMessage({ payload }) {
|
|
2965
|
-
log4("space message", payload, {
|
|
2966
|
-
F: __dxlog_file6,
|
|
2967
|
-
L: 110,
|
|
2968
|
-
S: this,
|
|
2969
|
-
C: (f, a) => f(...a)
|
|
2970
|
-
});
|
|
2971
|
-
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2972
|
-
const encoder = this._readMessage(data);
|
|
2973
|
-
if (encoder) {
|
|
2974
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
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);
|
|
2975
3339
|
}
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
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);
|
|
2986
3350
|
}
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
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
|
+
};
|
|
2992
3362
|
}
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
return encoder;
|
|
3363
|
+
if (autoFocus) {
|
|
3364
|
+
view.focus();
|
|
2996
3365
|
}
|
|
2997
3366
|
}
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
}
|
|
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);
|
|
3008
3398
|
};
|
|
3009
3399
|
|
|
3010
3400
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
3011
|
-
import
|
|
3401
|
+
import get4 from "lodash.get";
|
|
3402
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
3403
|
+
import { generateName } from "@dxos/display-name";
|
|
3404
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
3405
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
3012
3406
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
3407
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
3013
3408
|
var useTextModel = (props) => {
|
|
3014
3409
|
const { identity, space, text } = props;
|
|
3015
|
-
const [model, setModel] =
|
|
3410
|
+
const [model, setModel] = useState4();
|
|
3016
3411
|
useEffect4(() => setModel(createModel(props)), [
|
|
3017
3412
|
identity,
|
|
3018
3413
|
space,
|
|
@@ -3020,18 +3415,63 @@ var useTextModel = (props) => {
|
|
|
3020
3415
|
]);
|
|
3021
3416
|
return model;
|
|
3022
3417
|
};
|
|
3023
|
-
var
|
|
3024
|
-
const
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3418
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
3419
|
+
const [content, setContent] = useState4(defaultContent ?? "");
|
|
3420
|
+
return {
|
|
3421
|
+
id,
|
|
3422
|
+
content,
|
|
3423
|
+
setContent,
|
|
3424
|
+
text: () => content
|
|
3425
|
+
};
|
|
3426
|
+
};
|
|
3427
|
+
var createModel = ({ space, identity, text }) => {
|
|
3428
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
3429
|
+
F: __dxlog_file6,
|
|
3430
|
+
L: 50,
|
|
3431
|
+
S: void 0,
|
|
3432
|
+
A: [
|
|
3433
|
+
"isAutomergeObject(text)",
|
|
3434
|
+
""
|
|
3435
|
+
]
|
|
3436
|
+
});
|
|
3437
|
+
const obj = text;
|
|
3438
|
+
const doc = getRawDoc(obj, [
|
|
3439
|
+
obj.field
|
|
3440
|
+
]);
|
|
3441
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
3442
|
+
space,
|
|
3443
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
3444
|
+
info: {
|
|
3445
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
3446
|
+
color: cursorColor.color,
|
|
3447
|
+
lightColor: cursorColor.light
|
|
3448
|
+
},
|
|
3449
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
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));
|
|
3031
3461
|
}
|
|
3462
|
+
const model = {
|
|
3463
|
+
id: obj.id,
|
|
3464
|
+
content: doc,
|
|
3465
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3466
|
+
extension: extensions,
|
|
3467
|
+
peer: identity ? {
|
|
3468
|
+
id: identity.identityKey.toHex(),
|
|
3469
|
+
name: identity.profile?.displayName
|
|
3470
|
+
} : void 0
|
|
3471
|
+
};
|
|
3472
|
+
return model;
|
|
3032
3473
|
};
|
|
3033
3474
|
export {
|
|
3034
|
-
AwarenessProvider,
|
|
3035
3475
|
BaseTextEditor,
|
|
3036
3476
|
Cursor,
|
|
3037
3477
|
Doc,
|
|
@@ -3041,32 +3481,40 @@ export {
|
|
|
3041
3481
|
SpaceAwarenessProvider,
|
|
3042
3482
|
TextEditor,
|
|
3043
3483
|
TextKind,
|
|
3044
|
-
|
|
3484
|
+
Toolbar,
|
|
3045
3485
|
YText,
|
|
3046
3486
|
YXmlFragment,
|
|
3047
3487
|
autocomplete,
|
|
3048
|
-
|
|
3488
|
+
automerge,
|
|
3049
3489
|
awareness,
|
|
3050
|
-
|
|
3490
|
+
awarenessProvider,
|
|
3051
3491
|
blast,
|
|
3052
3492
|
callbackWrapper,
|
|
3053
3493
|
code2 as code,
|
|
3054
3494
|
codeTheme,
|
|
3055
3495
|
comments,
|
|
3056
|
-
|
|
3057
|
-
|
|
3496
|
+
createBasicBundle,
|
|
3497
|
+
createComment,
|
|
3498
|
+
createDataExtensions,
|
|
3499
|
+
createMarkdownExtensions,
|
|
3500
|
+
createThemeExtensions,
|
|
3058
3501
|
defaultMarkdownSlots,
|
|
3059
3502
|
defaultOptions,
|
|
3060
3503
|
defaultSlots,
|
|
3061
3504
|
defaultTextSlots,
|
|
3062
3505
|
defaultTheme,
|
|
3506
|
+
focusComment,
|
|
3507
|
+
formatting,
|
|
3063
3508
|
getToken,
|
|
3509
|
+
heading2 as heading,
|
|
3064
3510
|
hr,
|
|
3065
3511
|
image,
|
|
3512
|
+
insertCodeblock,
|
|
3513
|
+
insertTable,
|
|
3514
|
+
keymap7 as keymap,
|
|
3066
3515
|
link,
|
|
3067
3516
|
listener,
|
|
3068
3517
|
logChanges,
|
|
3069
|
-
markdownBundle,
|
|
3070
3518
|
markdownHighlightStyle,
|
|
3071
3519
|
markdownTags,
|
|
3072
3520
|
markdownTagsExtensions,
|
|
@@ -3075,16 +3523,24 @@ export {
|
|
|
3075
3523
|
modelState,
|
|
3076
3524
|
outliner,
|
|
3077
3525
|
setComments,
|
|
3078
|
-
|
|
3526
|
+
setHeading,
|
|
3079
3527
|
setSelection,
|
|
3080
3528
|
table,
|
|
3081
3529
|
tags2 as tags,
|
|
3082
3530
|
tasklist,
|
|
3083
3531
|
textTheme,
|
|
3532
|
+
toggleBold,
|
|
3533
|
+
toggleItalic,
|
|
3534
|
+
toggleList,
|
|
3535
|
+
toggleStrikethrough,
|
|
3536
|
+
toggleStyle,
|
|
3084
3537
|
typewriter,
|
|
3085
|
-
|
|
3538
|
+
useActionHandler,
|
|
3086
3539
|
useComments,
|
|
3540
|
+
useEditorView,
|
|
3541
|
+
useInMemoryTextModel,
|
|
3542
|
+
useTextEditor,
|
|
3087
3543
|
useTextModel,
|
|
3088
|
-
|
|
3544
|
+
useToolbarContext
|
|
3089
3545
|
};
|
|
3090
3546
|
//# sourceMappingURL=index.mjs.map
|