@dxos/react-ui-editor 0.3.11-main.264ec26 → 0.3.11-main.27967cf
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 +1406 -934
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +1 -2
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +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 +14 -6
- 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/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 +39 -29
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +16 -20
- 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 -10
- package/src/extensions/automerge/cursor.ts +3 -3
- package/src/extensions/automerge/defs.ts +9 -9
- package/src/extensions/automerge/semaphore.ts +17 -19
- package/src/extensions/automerge/update-automerge.ts +12 -6
- package/src/extensions/automerge/update-codemirror.ts +5 -5
- package/src/extensions/awareness.ts +21 -35
- package/src/extensions/basic.ts +17 -15
- package/src/extensions/blast.ts +4 -1
- package/src/extensions/comments.ts +138 -80
- 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/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 +11 -8
- 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,35 @@ var logChanges = (trs) => {
|
|
|
1156
1073
|
};
|
|
1157
1074
|
|
|
1158
1075
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1159
|
-
var
|
|
1160
|
-
|
|
1161
|
-
|
|
1076
|
+
var styles2 = EditorView5.baseTheme({
|
|
1077
|
+
"&light .cm-comment, &light .cm-comment-current": {
|
|
1078
|
+
mixBlendMode: "darken"
|
|
1079
|
+
},
|
|
1080
|
+
"&dark .cm-comment, &dark .cm-comment-current": {
|
|
1081
|
+
mixBlendMode: "plus-lighter"
|
|
1082
|
+
},
|
|
1083
|
+
"&light .cm-comment": {
|
|
1162
1084
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1163
1085
|
},
|
|
1164
|
-
"& .cm-comment-
|
|
1086
|
+
"&light .cm-comment-current": {
|
|
1165
1087
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1088
|
+
},
|
|
1089
|
+
"&dark .cm-comment": {
|
|
1090
|
+
color: getToken("extend.colors.yellow.50"),
|
|
1091
|
+
backgroundColor: getToken("extend.colors.yellow.900")
|
|
1092
|
+
},
|
|
1093
|
+
"&dark .cm-comment-current": {
|
|
1094
|
+
color: getToken("extend.colors.yellow.100"),
|
|
1095
|
+
backgroundColor: getToken("extend.colors.yellow.950")
|
|
1166
1096
|
}
|
|
1167
1097
|
});
|
|
1168
|
-
var
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
};
|
|
1176
|
-
var setFocus = (view, id, center = true) => {
|
|
1098
|
+
var commentMark = Decoration2.mark({
|
|
1099
|
+
class: "cm-comment"
|
|
1100
|
+
});
|
|
1101
|
+
var commentCurrentMark = Decoration2.mark({
|
|
1102
|
+
class: "cm-comment-current"
|
|
1103
|
+
});
|
|
1104
|
+
var focusComment = (view, id, center = true) => {
|
|
1177
1105
|
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1178
1106
|
if (!comment?.comment.cursor) {
|
|
1179
1107
|
return;
|
|
@@ -1186,11 +1114,11 @@ var setFocus = (view, id, center = true) => {
|
|
|
1186
1114
|
},
|
|
1187
1115
|
effects: [
|
|
1188
1116
|
//
|
|
1189
|
-
|
|
1117
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1190
1118
|
y: "center"
|
|
1191
1119
|
} : void 0),
|
|
1192
1120
|
setSelection.of({
|
|
1193
|
-
|
|
1121
|
+
current: id
|
|
1194
1122
|
})
|
|
1195
1123
|
]
|
|
1196
1124
|
});
|
|
@@ -1235,23 +1163,23 @@ var commentsState = StateField2.define({
|
|
|
1235
1163
|
return value;
|
|
1236
1164
|
}
|
|
1237
1165
|
});
|
|
1238
|
-
var
|
|
1166
|
+
var commentsDecorations = EditorView5.decorations.compute([
|
|
1239
1167
|
commentsState
|
|
1240
1168
|
], (state) => {
|
|
1241
|
-
const { selection: {
|
|
1169
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1242
1170
|
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1243
1171
|
const range = comment.range;
|
|
1244
1172
|
if (!range || range.from === range.to) {
|
|
1245
1173
|
console.warn("Invalid range:", range);
|
|
1246
1174
|
return void 0;
|
|
1247
1175
|
}
|
|
1248
|
-
if (comment.comment.id ===
|
|
1249
|
-
return
|
|
1176
|
+
if (comment.comment.id === current) {
|
|
1177
|
+
return commentCurrentMark.range(range.from, range.to);
|
|
1250
1178
|
} else {
|
|
1251
|
-
return
|
|
1179
|
+
return commentMark.range(range.from, range.to);
|
|
1252
1180
|
}
|
|
1253
1181
|
}).filter(nonNullable);
|
|
1254
|
-
return
|
|
1182
|
+
return Decoration2.set(decorations);
|
|
1255
1183
|
});
|
|
1256
1184
|
var trackPastedComments = (onUpdate) => {
|
|
1257
1185
|
let tracked = null;
|
|
@@ -1273,96 +1201,140 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1273
1201
|
}
|
|
1274
1202
|
};
|
|
1275
1203
|
return [
|
|
1276
|
-
|
|
1204
|
+
EditorView5.domEventHandlers({
|
|
1277
1205
|
cut: handleTrack,
|
|
1278
1206
|
copy: handleTrack
|
|
1279
1207
|
}),
|
|
1280
|
-
//
|
|
1281
|
-
|
|
1208
|
+
// Track deleted comments.
|
|
1209
|
+
invertedEffects2.of((tr) => {
|
|
1210
|
+
const { comments: comments2 } = tr.startState.field(commentsState);
|
|
1211
|
+
const effects = [];
|
|
1212
|
+
tr.changes.iterChangedRanges((fromA, toA) => {
|
|
1213
|
+
for (const { comment: { id }, range: { from, to } } of comments2) {
|
|
1214
|
+
if (from < to && from >= fromA && to <= toA) {
|
|
1215
|
+
effects.push(restoreCommentEffect.of({
|
|
1216
|
+
id,
|
|
1217
|
+
from,
|
|
1218
|
+
to
|
|
1219
|
+
}));
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
return effects;
|
|
1224
|
+
}),
|
|
1225
|
+
// Handle paste or the undo of comment deletion.
|
|
1226
|
+
EditorView5.updateListener.of((update2) => {
|
|
1227
|
+
const restore = [];
|
|
1228
|
+
for (let i = 0; i < update2.transactions.length; i++) {
|
|
1229
|
+
const tr = update2.transactions[i];
|
|
1230
|
+
for (let j = 0; j < restore.length; j++) {
|
|
1231
|
+
restore[j] = mapTrackedComment(restore[j], tr.changes);
|
|
1232
|
+
}
|
|
1233
|
+
for (const effect of tr.effects) {
|
|
1234
|
+
if (effect.is(restoreCommentEffect)) {
|
|
1235
|
+
restore.push(effect.value);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1282
1239
|
if (tracked) {
|
|
1283
|
-
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1240
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1284
1241
|
if (paste) {
|
|
1285
1242
|
let found = -1;
|
|
1286
1243
|
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1287
1244
|
if (text.eq(tracked.text)) {
|
|
1288
|
-
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1289
|
-
fromB = transactions[i].changes.mapPos(fromB);
|
|
1245
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1246
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1290
1247
|
}
|
|
1291
1248
|
found = fromB;
|
|
1292
1249
|
}
|
|
1293
1250
|
});
|
|
1294
1251
|
if (found > -1) {
|
|
1295
1252
|
for (const moved of tracked.comments) {
|
|
1296
|
-
|
|
1253
|
+
restore.push({
|
|
1254
|
+
id: moved.id,
|
|
1297
1255
|
from: found + moved.from,
|
|
1298
1256
|
to: found + moved.to
|
|
1299
|
-
};
|
|
1300
|
-
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1301
|
-
onUpdate(moved.id, cursor);
|
|
1257
|
+
});
|
|
1302
1258
|
}
|
|
1303
1259
|
}
|
|
1304
1260
|
tracked = null;
|
|
1305
1261
|
}
|
|
1306
1262
|
}
|
|
1263
|
+
for (const comment of restore) {
|
|
1264
|
+
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
1265
|
+
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
1266
|
+
if (!exists) {
|
|
1267
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
1268
|
+
onUpdate(comment.id, cursor);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1307
1271
|
})
|
|
1308
1272
|
];
|
|
1309
1273
|
};
|
|
1310
|
-
var
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1274
|
+
var mapTrackedComment = (comment, changes) => ({
|
|
1275
|
+
id: comment.id,
|
|
1276
|
+
from: changes.mapPos(comment.from, 1),
|
|
1277
|
+
to: changes.mapPos(comment.to, 1)
|
|
1278
|
+
});
|
|
1279
|
+
var restoreCommentEffect = StateEffect2.define({
|
|
1280
|
+
map: mapTrackedComment
|
|
1281
|
+
});
|
|
1282
|
+
var optionsFacet = Facet3.define({
|
|
1283
|
+
combine: (providers) => providers[0]
|
|
1284
|
+
});
|
|
1285
|
+
var createComment = (view) => {
|
|
1286
|
+
const options = view.state.facet(optionsFacet);
|
|
1287
|
+
const { from, to } = view.state.selection.main;
|
|
1288
|
+
if (from === to) {
|
|
1289
|
+
return false;
|
|
1290
|
+
}
|
|
1291
|
+
if (to === view.state.doc.length) {
|
|
1292
|
+
view.dispatch({
|
|
1293
|
+
changes: {
|
|
1294
|
+
from: to,
|
|
1295
|
+
insert: "\n"
|
|
1296
|
+
}
|
|
1322
1297
|
});
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1298
|
+
}
|
|
1299
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1300
|
+
from,
|
|
1301
|
+
to
|
|
1302
|
+
});
|
|
1303
|
+
if (cursor) {
|
|
1304
|
+
const id = options.onCreate?.({
|
|
1305
|
+
cursor,
|
|
1306
|
+
from,
|
|
1307
|
+
location: view.coordsAtPos(from)
|
|
1308
|
+
});
|
|
1309
|
+
if (id) {
|
|
1328
1310
|
view.dispatch({
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1311
|
+
effects: setSelection.of({
|
|
1312
|
+
current: id
|
|
1313
|
+
}),
|
|
1314
|
+
selection: {
|
|
1315
|
+
anchor: to
|
|
1332
1316
|
}
|
|
1333
1317
|
});
|
|
1318
|
+
return true;
|
|
1334
1319
|
}
|
|
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
|
-
};
|
|
1320
|
+
}
|
|
1321
|
+
return false;
|
|
1322
|
+
};
|
|
1323
|
+
var comments = (options = {}) => {
|
|
1324
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1325
|
+
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1355
1326
|
return [
|
|
1327
|
+
optionsFacet.of(options),
|
|
1356
1328
|
commentsState,
|
|
1357
|
-
|
|
1358
|
-
|
|
1329
|
+
commentsDecorations,
|
|
1330
|
+
styles2,
|
|
1359
1331
|
//
|
|
1360
1332
|
// Keymap.
|
|
1361
1333
|
//
|
|
1362
1334
|
options.onCreate ? keymap3.of([
|
|
1363
1335
|
{
|
|
1364
1336
|
key: shortcut,
|
|
1365
|
-
run: callbackWrapper(
|
|
1337
|
+
run: callbackWrapper(createComment)
|
|
1366
1338
|
}
|
|
1367
1339
|
]) : [],
|
|
1368
1340
|
//
|
|
@@ -1398,7 +1370,7 @@ var comments = (options = {}) => {
|
|
|
1398
1370
|
//
|
|
1399
1371
|
// Track deleted ranges and update ranges for decorations.
|
|
1400
1372
|
//
|
|
1401
|
-
|
|
1373
|
+
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1402
1374
|
let mod = false;
|
|
1403
1375
|
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1404
1376
|
changes.iterChanges((from, to, from2, to2) => {
|
|
@@ -1428,17 +1400,17 @@ var comments = (options = {}) => {
|
|
|
1428
1400
|
//
|
|
1429
1401
|
// Track selection/proximity.
|
|
1430
1402
|
//
|
|
1431
|
-
|
|
1403
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1432
1404
|
let min = Infinity;
|
|
1433
|
-
const { selection: {
|
|
1405
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1434
1406
|
const { head } = state.selection.main;
|
|
1435
1407
|
const selection = {};
|
|
1436
1408
|
comments2.forEach(({ comment, range }) => {
|
|
1437
1409
|
if (head >= range.from && head <= range.to) {
|
|
1438
|
-
selection.
|
|
1410
|
+
selection.current = comment.id;
|
|
1439
1411
|
selection.closest = void 0;
|
|
1440
1412
|
}
|
|
1441
|
-
if (!selection.
|
|
1413
|
+
if (!selection.current) {
|
|
1442
1414
|
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1443
1415
|
if (d < min) {
|
|
1444
1416
|
selection.closest = comment.id;
|
|
@@ -1446,7 +1418,7 @@ var comments = (options = {}) => {
|
|
|
1446
1418
|
}
|
|
1447
1419
|
}
|
|
1448
1420
|
});
|
|
1449
|
-
if (selection.
|
|
1421
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1450
1422
|
view.dispatch({
|
|
1451
1423
|
effects: setSelection.of(selection)
|
|
1452
1424
|
});
|
|
@@ -1463,9 +1435,9 @@ var comments = (options = {}) => {
|
|
|
1463
1435
|
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1464
1436
|
];
|
|
1465
1437
|
};
|
|
1466
|
-
var useComments = (view, comments2) => {
|
|
1467
|
-
|
|
1468
|
-
if (view
|
|
1438
|
+
var useComments = (view, comments2 = []) => {
|
|
1439
|
+
useEffect(() => {
|
|
1440
|
+
if (view) {
|
|
1469
1441
|
view.dispatch({
|
|
1470
1442
|
effects: setComments.of(comments2)
|
|
1471
1443
|
});
|
|
@@ -1476,314 +1448,51 @@ var useComments = (view, comments2) => {
|
|
|
1476
1448
|
]);
|
|
1477
1449
|
};
|
|
1478
1450
|
|
|
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
|
-
];
|
|
1451
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1452
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1453
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1454
|
+
const extensions = [];
|
|
1455
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1456
|
+
onFocus(focused);
|
|
1457
|
+
return null;
|
|
1458
|
+
}));
|
|
1459
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1460
|
+
onChange(update2.state.doc.toString());
|
|
1461
|
+
}));
|
|
1462
|
+
return extensions;
|
|
1532
1463
|
};
|
|
1533
1464
|
|
|
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()
|
|
1465
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1466
|
+
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1467
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1468
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1469
|
+
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1470
|
+
import { languages } from "@codemirror/language-data";
|
|
1471
|
+
import { searchKeymap } from "@codemirror/search";
|
|
1472
|
+
import { EditorState } from "@codemirror/state";
|
|
1473
|
+
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1474
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1475
|
+
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1476
|
+
|
|
1477
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1478
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
1479
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
1480
|
+
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
1481
|
+
import { Table } from "@lezer/markdown";
|
|
1482
|
+
var markdownTags = {
|
|
1483
|
+
Blockquote: Tag.define(),
|
|
1484
|
+
CodeMark: Tag.define(),
|
|
1485
|
+
CodeText: Tag.define(),
|
|
1486
|
+
EmphasisMark: Tag.define(),
|
|
1487
|
+
HeaderMark: Tag.define(),
|
|
1488
|
+
InlineCode: Tag.define(),
|
|
1489
|
+
LinkLabel: Tag.define(),
|
|
1490
|
+
LinkReference: Tag.define(),
|
|
1491
|
+
ListMark: Tag.define(),
|
|
1492
|
+
QuoteMark: Tag.define(),
|
|
1493
|
+
URL: Tag.define(),
|
|
1494
|
+
// Custom.
|
|
1495
|
+
TableCell: Tag.define()
|
|
1787
1496
|
};
|
|
1788
1497
|
Table.defineNodes?.forEach((node) => {
|
|
1789
1498
|
switch (node?.name) {
|
|
@@ -1860,7 +1569,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1860
1569
|
markdownTags.QuoteMark,
|
|
1861
1570
|
markdownTags.EmphasisMark
|
|
1862
1571
|
],
|
|
1863
|
-
class:
|
|
1572
|
+
class: mark
|
|
1864
1573
|
},
|
|
1865
1574
|
// E.g., code block language (after ```).
|
|
1866
1575
|
{
|
|
@@ -1868,7 +1577,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1868
1577
|
tags.function(tags.variableName),
|
|
1869
1578
|
tags.labelName
|
|
1870
1579
|
],
|
|
1871
|
-
class:
|
|
1580
|
+
class: codeMark
|
|
1872
1581
|
},
|
|
1873
1582
|
{
|
|
1874
1583
|
tag: [
|
|
@@ -1879,27 +1588,27 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1879
1588
|
// Headings.
|
|
1880
1589
|
{
|
|
1881
1590
|
tag: tags.heading1,
|
|
1882
|
-
class: heading(1
|
|
1591
|
+
class: heading(1)
|
|
1883
1592
|
},
|
|
1884
1593
|
{
|
|
1885
1594
|
tag: tags.heading2,
|
|
1886
|
-
class: heading(2
|
|
1595
|
+
class: heading(2)
|
|
1887
1596
|
},
|
|
1888
1597
|
{
|
|
1889
1598
|
tag: tags.heading3,
|
|
1890
|
-
class: heading(3
|
|
1599
|
+
class: heading(3)
|
|
1891
1600
|
},
|
|
1892
1601
|
{
|
|
1893
1602
|
tag: tags.heading4,
|
|
1894
|
-
class: heading(4
|
|
1603
|
+
class: heading(4)
|
|
1895
1604
|
},
|
|
1896
1605
|
{
|
|
1897
1606
|
tag: tags.heading5,
|
|
1898
|
-
class: heading(5
|
|
1607
|
+
class: heading(5)
|
|
1899
1608
|
},
|
|
1900
1609
|
{
|
|
1901
1610
|
tag: tags.heading6,
|
|
1902
|
-
class: heading(6
|
|
1611
|
+
class: heading(6)
|
|
1903
1612
|
},
|
|
1904
1613
|
// Emphasis.
|
|
1905
1614
|
{
|
|
@@ -1925,7 +1634,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1925
1634
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
1926
1635
|
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
1927
1636
|
// the code, but all other CSS properties will be inherited.
|
|
1928
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
1637
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
1929
1638
|
{
|
|
1930
1639
|
tag: [
|
|
1931
1640
|
markdownTags.CodeText,
|
|
@@ -1954,11 +1663,11 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1954
1663
|
};
|
|
1955
1664
|
|
|
1956
1665
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1957
|
-
var
|
|
1666
|
+
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
1958
1667
|
return [
|
|
1668
|
+
lineWrapping && EditorView7.lineWrapping,
|
|
1959
1669
|
EditorState.allowMultipleSelections.of(true),
|
|
1960
1670
|
EditorState.tabSize.of(2),
|
|
1961
|
-
EditorView10.lineWrapping,
|
|
1962
1671
|
// https://github.com/codemirror/basic-setup
|
|
1963
1672
|
bracketMatching2(),
|
|
1964
1673
|
closeBrackets2(),
|
|
@@ -1968,7 +1677,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1968
1677
|
highlightActiveLine2(),
|
|
1969
1678
|
history2(),
|
|
1970
1679
|
indentOnInput(),
|
|
1971
|
-
_placeholder
|
|
1680
|
+
_placeholder && placeholder2(_placeholder),
|
|
1972
1681
|
// Main extension.
|
|
1973
1682
|
// https://github.com/codemirror/lang-markdown
|
|
1974
1683
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1990,7 +1699,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1990
1699
|
// https://github.com/codemirror/theme-one-dark
|
|
1991
1700
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1992
1701
|
// Custom styles.
|
|
1993
|
-
syntaxHighlighting2(markdownHighlightStyle(
|
|
1702
|
+
syntaxHighlighting2(markdownHighlightStyle()),
|
|
1994
1703
|
keymap4.of([
|
|
1995
1704
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1996
1705
|
indentWithTab,
|
|
@@ -2003,47 +1712,580 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
2003
1712
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2004
1713
|
...standardKeymap
|
|
2005
1714
|
])
|
|
2006
|
-
];
|
|
1715
|
+
].filter(isNotFalsy2);
|
|
2007
1716
|
};
|
|
2008
1717
|
|
|
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
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
1718
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1719
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1720
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1721
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1722
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1723
|
+
var styles3 = EditorView8.baseTheme({
|
|
1724
|
+
"& .cm-code": {
|
|
1725
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1726
|
+
},
|
|
1727
|
+
"& .cm-codeblock": {
|
|
1728
|
+
width: "100%",
|
|
1729
|
+
paddingInline: "1rem !important",
|
|
1730
|
+
position: "relative",
|
|
1731
|
+
"&::after": {
|
|
1732
|
+
content: '""',
|
|
1733
|
+
position: "absolute",
|
|
1734
|
+
inset: 0
|
|
1735
|
+
}
|
|
1736
|
+
},
|
|
1737
|
+
"&light .cm-codeblock": {
|
|
1738
|
+
"&::after": {
|
|
1739
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
1740
|
+
mixBlendMode: "darken"
|
|
1741
|
+
}
|
|
1742
|
+
},
|
|
1743
|
+
"&dark .cm-codeblock": {
|
|
1744
|
+
"&::after": {
|
|
1745
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
1746
|
+
mixBlendMode: "lighten"
|
|
1747
|
+
}
|
|
1748
|
+
},
|
|
1749
|
+
"& .cm-codeblock-first": {
|
|
1750
|
+
display: "inline-block",
|
|
1751
|
+
"&::after": {
|
|
1752
|
+
borderTopLeftRadius: ".5rem",
|
|
1753
|
+
borderTopRightRadius: ".5rem"
|
|
1754
|
+
}
|
|
1755
|
+
},
|
|
1756
|
+
"& .cm-codeblock-last": {
|
|
1757
|
+
display: "inline-block",
|
|
1758
|
+
"&::after": {
|
|
1759
|
+
borderBottomLeftRadius: ".5rem",
|
|
1760
|
+
borderBottomRightRadius: ".5rem"
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
var getLineRange = (lines, from, to) => {
|
|
1765
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1766
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1767
|
+
return [
|
|
1768
|
+
start,
|
|
1769
|
+
end
|
|
1770
|
+
];
|
|
2036
1771
|
};
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
1772
|
+
var LineWidget = class extends WidgetType2 {
|
|
1773
|
+
constructor(_className) {
|
|
1774
|
+
super();
|
|
1775
|
+
this._className = _className;
|
|
1776
|
+
}
|
|
1777
|
+
toDOM() {
|
|
1778
|
+
const el = document.createElement("span");
|
|
1779
|
+
el.innerHTML = " ";
|
|
1780
|
+
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1781
|
+
return el;
|
|
1782
|
+
}
|
|
1783
|
+
};
|
|
1784
|
+
var top = new LineWidget("cm-codeblock-first");
|
|
1785
|
+
var bottom = new LineWidget("cm-codeblock-last");
|
|
1786
|
+
var buildDecorations = (view) => {
|
|
1787
|
+
const builder = new RangeSetBuilder();
|
|
1788
|
+
const { state } = view;
|
|
1789
|
+
const blocks = view.viewportLineBlocks;
|
|
1790
|
+
const cursor = state.selection.main.head;
|
|
1791
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1792
|
+
syntaxTree(state).iterate({
|
|
1793
|
+
enter: (node) => {
|
|
1794
|
+
if (node.name === "FencedCode") {
|
|
1795
|
+
const edit = !view.state.readOnly && cursor >= node.from && cursor <= node.to;
|
|
1796
|
+
const range = getLineRange(blocks, node.from, node.to);
|
|
1797
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1798
|
+
const block = blocks[i];
|
|
1799
|
+
if (!edit && (i === range[0] || i === range[1])) {
|
|
1800
|
+
builder.add(block.from, block.to, Decoration3.replace({
|
|
1801
|
+
widget: i === range[0] ? top : bottom
|
|
1802
|
+
}));
|
|
1803
|
+
} else {
|
|
1804
|
+
builder.add(block.from, block.from, Decoration3.line({
|
|
1805
|
+
class: mx2("cm-code cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1806
|
+
}));
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
},
|
|
1811
|
+
from,
|
|
1812
|
+
to
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
return builder.finish();
|
|
1816
|
+
};
|
|
1817
|
+
var code2 = () => {
|
|
1818
|
+
return [
|
|
1819
|
+
ViewPlugin3.fromClass(class {
|
|
1820
|
+
constructor(view) {
|
|
1821
|
+
this.decorations = buildDecorations(view);
|
|
1822
|
+
}
|
|
1823
|
+
update(update2) {
|
|
1824
|
+
this.decorations = buildDecorations(update2.view);
|
|
1825
|
+
}
|
|
1826
|
+
}, {
|
|
1827
|
+
decorations: (value) => value.decorations
|
|
1828
|
+
}),
|
|
1829
|
+
styles3
|
|
1830
|
+
];
|
|
1831
|
+
};
|
|
1832
|
+
|
|
1833
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1834
|
+
import { snippet } from "@codemirror/autocomplete";
|
|
1835
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1836
|
+
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1837
|
+
import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1838
|
+
var setHeading = (level) => (view) => {
|
|
1839
|
+
const { selection: { ranges }, doc } = view.state;
|
|
1840
|
+
const changes = [];
|
|
1841
|
+
for (const range of ranges) {
|
|
1842
|
+
const { number } = doc.lineAt(range.anchor);
|
|
1843
|
+
const { from, to } = doc.line(number);
|
|
1844
|
+
const line = doc.sliceString(from, to);
|
|
1845
|
+
const [_, marks, spaces] = line.match(/(#+)(\s+)/) ?? [];
|
|
1846
|
+
const current = marks?.length ?? 0;
|
|
1847
|
+
if (level !== current) {
|
|
1848
|
+
changes.push({
|
|
1849
|
+
from,
|
|
1850
|
+
to: from + current + (spaces?.length ?? 0),
|
|
1851
|
+
insert: "#".repeat(level) + (level > 0 ? " " : "")
|
|
1852
|
+
});
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
if (changes.length) {
|
|
1856
|
+
view.dispatch({
|
|
1857
|
+
changes
|
|
1858
|
+
});
|
|
1859
|
+
}
|
|
1860
|
+
return true;
|
|
1861
|
+
};
|
|
1862
|
+
var toggleStyle = (mark2) => (view) => {
|
|
1863
|
+
const { ranges } = view.state.selection;
|
|
1864
|
+
for (const range of ranges) {
|
|
1865
|
+
if (range.from === range.to) {
|
|
1866
|
+
return false;
|
|
1867
|
+
}
|
|
1868
|
+
view.dispatch({
|
|
1869
|
+
changes: [
|
|
1870
|
+
{
|
|
1871
|
+
from: range.from,
|
|
1872
|
+
insert: mark2
|
|
1873
|
+
},
|
|
1874
|
+
{
|
|
1875
|
+
from: range.to,
|
|
1876
|
+
insert: mark2
|
|
1877
|
+
}
|
|
1878
|
+
]
|
|
1879
|
+
});
|
|
1880
|
+
}
|
|
1881
|
+
return true;
|
|
1882
|
+
};
|
|
1883
|
+
var snippets = {
|
|
1884
|
+
codeblock: snippet([
|
|
1885
|
+
"```#{lang}",
|
|
1886
|
+
" #{}",
|
|
1887
|
+
"```"
|
|
1888
|
+
].join("\n")),
|
|
1889
|
+
table: snippet([
|
|
1890
|
+
"| #{col1} | #{col2} |",
|
|
1891
|
+
"| ---- | ---- |",
|
|
1892
|
+
"| #{val1} | #{val2} |",
|
|
1893
|
+
"| #{val3} | #{val4} |"
|
|
1894
|
+
].join("\n"))
|
|
1895
|
+
};
|
|
1896
|
+
var insertCodeblock = (view) => {
|
|
1897
|
+
const { selection: { main }, doc } = view.state;
|
|
1898
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1899
|
+
const { from } = doc.line(number);
|
|
1900
|
+
snippets.codeblock(view, null, from, from);
|
|
1901
|
+
};
|
|
1902
|
+
var insertTable = (view) => {
|
|
1903
|
+
const { selection: { main }, doc } = view.state;
|
|
1904
|
+
const { number } = doc.lineAt(main.anchor);
|
|
1905
|
+
const { from } = doc.line(number);
|
|
1906
|
+
snippets.table(view, null, from, from);
|
|
1907
|
+
};
|
|
1908
|
+
var toggleBold = toggleStyle("**");
|
|
1909
|
+
var toggleItalic = toggleStyle("_");
|
|
1910
|
+
var toggleStrikethrough = toggleStyle("~~");
|
|
1911
|
+
var toggleList = (view) => {
|
|
1912
|
+
};
|
|
1913
|
+
var formatting = (options = {}) => {
|
|
1914
|
+
return [
|
|
1915
|
+
keymap5.of([
|
|
1916
|
+
{
|
|
1917
|
+
key: "meta-b",
|
|
1918
|
+
run: toggleBold
|
|
1919
|
+
}
|
|
1920
|
+
]),
|
|
1921
|
+
styling()
|
|
1922
|
+
];
|
|
1923
|
+
};
|
|
1924
|
+
var styling = () => {
|
|
1925
|
+
const buildDecorations7 = (view) => {
|
|
1926
|
+
const builder = new RangeSetBuilder2();
|
|
1927
|
+
const { state } = view;
|
|
1928
|
+
const cursor = state.selection.main.head;
|
|
1929
|
+
const replace = (node, marks) => {
|
|
1930
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1931
|
+
for (const mark2 of marks) {
|
|
1932
|
+
builder.add(mark2.from, mark2.to, Decoration4.replace({}));
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1937
|
+
syntaxTree2(state).iterate({
|
|
1938
|
+
enter: (node) => {
|
|
1939
|
+
switch (node.name) {
|
|
1940
|
+
case "Emphasis":
|
|
1941
|
+
case "StrongEmphasis": {
|
|
1942
|
+
const marks = node.node.getChildren("EmphasisMark");
|
|
1943
|
+
replace(node, marks);
|
|
1944
|
+
break;
|
|
1945
|
+
}
|
|
1946
|
+
case "Strikethrough": {
|
|
1947
|
+
const marks = node.node.getChildren("StrikethroughMark");
|
|
1948
|
+
replace(node, marks);
|
|
1949
|
+
break;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
},
|
|
1953
|
+
from,
|
|
1954
|
+
to
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
return builder.finish();
|
|
1958
|
+
};
|
|
1959
|
+
return [
|
|
1960
|
+
ViewPlugin4.fromClass(class {
|
|
1961
|
+
constructor(view) {
|
|
1962
|
+
this.decorations = buildDecorations7(view);
|
|
1963
|
+
}
|
|
1964
|
+
update(update2) {
|
|
1965
|
+
this.decorations = buildDecorations7(update2.view);
|
|
1966
|
+
}
|
|
1967
|
+
}, {
|
|
1968
|
+
decorations: (value) => value.decorations
|
|
1969
|
+
})
|
|
1970
|
+
];
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1973
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1974
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1975
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1976
|
+
import { Decoration as Decoration5, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1977
|
+
var buildDecorations2 = (view) => {
|
|
1978
|
+
const builder = new RangeSetBuilder3();
|
|
1979
|
+
const { state } = view;
|
|
1980
|
+
const cursor = state.selection.main.head;
|
|
1981
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1982
|
+
syntaxTree3(state).iterate({
|
|
1983
|
+
enter: (node) => {
|
|
1984
|
+
switch (node.name) {
|
|
1985
|
+
case "ATXHeading1":
|
|
1986
|
+
case "ATXHeading2":
|
|
1987
|
+
case "ATXHeading3":
|
|
1988
|
+
case "ATXHeading4":
|
|
1989
|
+
case "ATXHeading5":
|
|
1990
|
+
case "ATXHeading6": {
|
|
1991
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1992
|
+
if (mark2) {
|
|
1993
|
+
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1994
|
+
builder.add(mark2.from, mark2.to + 1, Decoration5.replace({}));
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
},
|
|
2000
|
+
from,
|
|
2001
|
+
to
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
return builder.finish();
|
|
2005
|
+
};
|
|
2006
|
+
var heading2 = () => {
|
|
2007
|
+
return [
|
|
2008
|
+
ViewPlugin5.fromClass(class {
|
|
2009
|
+
constructor(view) {
|
|
2010
|
+
this.decorations = buildDecorations2(view);
|
|
2011
|
+
}
|
|
2012
|
+
update(update2) {
|
|
2013
|
+
this.decorations = buildDecorations2(update2.view);
|
|
2014
|
+
}
|
|
2015
|
+
}, {
|
|
2016
|
+
decorations: (value) => value.decorations
|
|
2017
|
+
})
|
|
2018
|
+
];
|
|
2019
|
+
};
|
|
2020
|
+
|
|
2021
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
2022
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2023
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2024
|
+
import { Decoration as Decoration6, EditorView as EditorView9, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
2025
|
+
var styles4 = EditorView9.baseTheme({
|
|
2026
|
+
"& .cm-hr": {
|
|
2027
|
+
// Note that block-level decorations should not have vertical margins,
|
|
2028
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2029
|
+
}
|
|
2030
|
+
});
|
|
2031
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2032
|
+
toDOM() {
|
|
2033
|
+
const el = document.createElement("div");
|
|
2034
|
+
el.className = "cm-hr";
|
|
2035
|
+
return el;
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
var decoration = Decoration6.replace({
|
|
2039
|
+
widget: new HorizontalRuleWidget()
|
|
2040
|
+
});
|
|
2041
|
+
var buildDecorations3 = (view) => {
|
|
2042
|
+
const builder = new RangeSetBuilder4();
|
|
2043
|
+
const { state } = view;
|
|
2044
|
+
const cursor = state.selection.main.head;
|
|
2045
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2046
|
+
syntaxTree4(state).iterate({
|
|
2047
|
+
enter: (node) => {
|
|
2048
|
+
if (node.name === "HorizontalRule") {
|
|
2049
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
2050
|
+
builder.add(node.from, node.to, decoration);
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
},
|
|
2054
|
+
from,
|
|
2055
|
+
to
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
return builder.finish();
|
|
2059
|
+
};
|
|
2060
|
+
var hr = () => {
|
|
2061
|
+
return [
|
|
2062
|
+
ViewPlugin6.fromClass(class {
|
|
2063
|
+
constructor(view) {
|
|
2064
|
+
this.decorations = buildDecorations3(view);
|
|
2065
|
+
}
|
|
2066
|
+
update(update2) {
|
|
2067
|
+
this.decorations = buildDecorations3(update2.view);
|
|
2068
|
+
}
|
|
2069
|
+
}, {
|
|
2070
|
+
decorations: (value) => value.decorations
|
|
2071
|
+
}),
|
|
2072
|
+
styles4
|
|
2073
|
+
];
|
|
2074
|
+
};
|
|
2075
|
+
|
|
2076
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
2077
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2078
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
2079
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
2080
|
+
var image = (options = {}) => {
|
|
2081
|
+
return StateField3.define({
|
|
2082
|
+
create: (state) => {
|
|
2083
|
+
return Decoration7.set(buildDecorations4(0, state.doc.length, state));
|
|
2084
|
+
},
|
|
2085
|
+
update: (value, tr) => {
|
|
2086
|
+
if (!tr.docChanged && !tr.selection) {
|
|
2087
|
+
return value;
|
|
2088
|
+
}
|
|
2089
|
+
const cursor = tr.state.selection.main.head;
|
|
2090
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
2091
|
+
let from = Math.min(cursor, oldCursor);
|
|
2092
|
+
let to = Math.max(cursor, oldCursor);
|
|
2093
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
2094
|
+
from = Math.min(from, fromB);
|
|
2095
|
+
to = Math.max(to, toB);
|
|
2096
|
+
});
|
|
2097
|
+
from = tr.state.doc.lineAt(from).from;
|
|
2098
|
+
to = tr.state.doc.lineAt(to).to;
|
|
2099
|
+
return value.map(tr.changes).update({
|
|
2100
|
+
filterFrom: from,
|
|
2101
|
+
filterTo: to,
|
|
2102
|
+
filter: () => false,
|
|
2103
|
+
add: buildDecorations4(from, to, tr.state)
|
|
2104
|
+
});
|
|
2105
|
+
},
|
|
2106
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
2107
|
+
});
|
|
2108
|
+
};
|
|
2109
|
+
var buildDecorations4 = (from, to, state) => {
|
|
2110
|
+
const decorations = [];
|
|
2111
|
+
const cursor = state.selection.main.head;
|
|
2112
|
+
syntaxTree5(state).iterate({
|
|
2113
|
+
enter: (node) => {
|
|
2114
|
+
if (node.name === "Image") {
|
|
2115
|
+
const urlNode = node.node.getChild("URL");
|
|
2116
|
+
if (urlNode) {
|
|
2117
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
2118
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
2119
|
+
decorations.push(Decoration7.replace({
|
|
2120
|
+
block: true,
|
|
2121
|
+
widget: new ImageWidget(url)
|
|
2122
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
},
|
|
2126
|
+
from,
|
|
2127
|
+
to
|
|
2128
|
+
});
|
|
2129
|
+
return decorations;
|
|
2130
|
+
};
|
|
2131
|
+
var ImageWidget = class extends WidgetType4 {
|
|
2132
|
+
constructor(_url) {
|
|
2133
|
+
super();
|
|
2134
|
+
this._url = _url;
|
|
2135
|
+
}
|
|
2136
|
+
eq(other) {
|
|
2137
|
+
return this._url === other._url;
|
|
2138
|
+
}
|
|
2139
|
+
toDOM(view) {
|
|
2140
|
+
const img = document.createElement("img");
|
|
2141
|
+
img.setAttribute("src", this._url);
|
|
2142
|
+
img.setAttribute("class", "cm-image");
|
|
2143
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
2144
|
+
return img;
|
|
2145
|
+
}
|
|
2146
|
+
};
|
|
2147
|
+
|
|
2148
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
2149
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2150
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2151
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration8, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
2152
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
2153
|
+
var link = (options = {}) => {
|
|
2154
|
+
const extensions = [
|
|
2155
|
+
ViewPlugin7.fromClass(class {
|
|
2156
|
+
constructor(view) {
|
|
2157
|
+
this.decorations = buildDecorations5(view, options);
|
|
2158
|
+
}
|
|
2159
|
+
update(update2) {
|
|
2160
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2161
|
+
this.decorations = buildDecorations5(update2.view, options);
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
}, {
|
|
2165
|
+
decorations: (value) => value.decorations
|
|
2166
|
+
})
|
|
2167
|
+
];
|
|
2168
|
+
if (options.onHover) {
|
|
2169
|
+
extensions.push(
|
|
2170
|
+
// https://codemirror.net/examples/tooltip
|
|
2171
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
2172
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
2173
|
+
hoverTooltip2((view, pos, side) => {
|
|
2174
|
+
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
2175
|
+
let link2 = null;
|
|
2176
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
2177
|
+
link2 = node.name === "Link" ? node : null;
|
|
2178
|
+
}
|
|
2179
|
+
const url = link2 && link2.getChild("URL");
|
|
2180
|
+
if (!url || !link2) {
|
|
2181
|
+
return null;
|
|
2182
|
+
}
|
|
2183
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
2184
|
+
return {
|
|
2185
|
+
pos: link2.from,
|
|
2186
|
+
end: link2.to,
|
|
2187
|
+
above: true,
|
|
2188
|
+
create: () => {
|
|
2189
|
+
const el = document.createElement("div");
|
|
2190
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
2191
|
+
options.onHover(el, urlText);
|
|
2192
|
+
return {
|
|
2193
|
+
dom: el,
|
|
2194
|
+
offset: {
|
|
2195
|
+
x: 0,
|
|
2196
|
+
y: 4
|
|
2197
|
+
}
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
};
|
|
2201
|
+
})
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
return extensions;
|
|
2205
|
+
};
|
|
2206
|
+
var LinkButton = class extends WidgetType5 {
|
|
2207
|
+
constructor(_url, _onAttach) {
|
|
2208
|
+
super();
|
|
2209
|
+
this._url = _url;
|
|
2210
|
+
this._onAttach = _onAttach;
|
|
2211
|
+
}
|
|
2212
|
+
eq(other) {
|
|
2213
|
+
return this._url === other._url;
|
|
2214
|
+
}
|
|
2215
|
+
toDOM(view) {
|
|
2216
|
+
const el = document.createElement("span");
|
|
2217
|
+
this._onAttach(el, this._url);
|
|
2218
|
+
return el;
|
|
2219
|
+
}
|
|
2220
|
+
};
|
|
2221
|
+
var LinkText = class extends WidgetType5 {
|
|
2222
|
+
constructor(_text, _url) {
|
|
2223
|
+
super();
|
|
2224
|
+
this._text = _text;
|
|
2225
|
+
this._url = _url;
|
|
2226
|
+
}
|
|
2227
|
+
eq(other) {
|
|
2228
|
+
return this._url === other._url;
|
|
2229
|
+
}
|
|
2230
|
+
toDOM(view) {
|
|
2231
|
+
const link2 = document.createElement("a");
|
|
2232
|
+
link2.setAttribute("class", "cm-link");
|
|
2233
|
+
link2.textContent = this._text;
|
|
2234
|
+
if (this._url) {
|
|
2235
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2236
|
+
link2.setAttribute("target", "_blank");
|
|
2237
|
+
link2.href = this._url;
|
|
2238
|
+
} else {
|
|
2239
|
+
link2.onclick = () => {
|
|
2240
|
+
view.dispatch({
|
|
2241
|
+
selection: {
|
|
2242
|
+
anchor: view.posAtDOM(link2)
|
|
2243
|
+
}
|
|
2244
|
+
});
|
|
2245
|
+
};
|
|
2246
|
+
}
|
|
2247
|
+
return link2;
|
|
2248
|
+
}
|
|
2249
|
+
};
|
|
2250
|
+
var buildDecorations5 = (view, options) => {
|
|
2251
|
+
const builder = new RangeSetBuilder5();
|
|
2252
|
+
const { state } = view;
|
|
2253
|
+
const cursor = state.selection.main.head;
|
|
2254
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2255
|
+
syntaxTree6(state).iterate({
|
|
2256
|
+
enter: (node) => {
|
|
2257
|
+
if (node.name === "Link") {
|
|
2258
|
+
const marks = node.node.getChildren("LinkMark");
|
|
2259
|
+
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
2260
|
+
const urlNode = node.node.getChild("URL");
|
|
2261
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2262
|
+
if (!url) {
|
|
2263
|
+
return false;
|
|
2264
|
+
}
|
|
2265
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2266
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
|
2267
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2268
|
+
}));
|
|
2269
|
+
}
|
|
2270
|
+
if (options.onRender) {
|
|
2271
|
+
builder.add(node.to, node.to, Decoration8.replace({
|
|
2272
|
+
widget: new LinkButton(url, options.onRender)
|
|
2273
|
+
}));
|
|
2274
|
+
}
|
|
2275
|
+
return false;
|
|
2276
|
+
}
|
|
2277
|
+
},
|
|
2278
|
+
from,
|
|
2279
|
+
to
|
|
2280
|
+
});
|
|
2281
|
+
}
|
|
2282
|
+
return builder.finish();
|
|
2041
2283
|
};
|
|
2042
2284
|
|
|
2043
|
-
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
2044
|
-
import { syntaxTree as
|
|
2045
|
-
import { RangeSetBuilder as
|
|
2046
|
-
import { Decoration as
|
|
2285
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2286
|
+
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
2287
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
2288
|
+
import { Decoration as Decoration9, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
2047
2289
|
var table = (options = {}) => {
|
|
2048
2290
|
return StateField4.define({
|
|
2049
2291
|
create: (state) => update(state, options),
|
|
@@ -2052,7 +2294,7 @@ var table = (options = {}) => {
|
|
|
2052
2294
|
});
|
|
2053
2295
|
};
|
|
2054
2296
|
var update = (state, options) => {
|
|
2055
|
-
const builder = new
|
|
2297
|
+
const builder = new RangeSetBuilder6();
|
|
2056
2298
|
const cursor = state.selection.main.head;
|
|
2057
2299
|
const tables = [];
|
|
2058
2300
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2060,7 +2302,7 @@ var update = (state, options) => {
|
|
|
2060
2302
|
const table2 = getTable();
|
|
2061
2303
|
return table2.rows?.[table2.rows.length - 1];
|
|
2062
2304
|
};
|
|
2063
|
-
|
|
2305
|
+
syntaxTree7(state).iterate({
|
|
2064
2306
|
enter: (node) => {
|
|
2065
2307
|
switch (node.name) {
|
|
2066
2308
|
case "Table": {
|
|
@@ -2092,16 +2334,16 @@ var update = (state, options) => {
|
|
|
2092
2334
|
});
|
|
2093
2335
|
tables.forEach((table2) => {
|
|
2094
2336
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2095
|
-
hide && builder.add(table2.from, table2.to,
|
|
2337
|
+
hide && builder.add(table2.from, table2.to, Decoration9.replace({
|
|
2096
2338
|
widget: new TableWidget(table2)
|
|
2097
2339
|
}));
|
|
2098
|
-
builder.add(table2.from, table2.to,
|
|
2340
|
+
builder.add(table2.from, table2.to, Decoration9.mark({
|
|
2099
2341
|
class: "cm-table"
|
|
2100
2342
|
}));
|
|
2101
2343
|
});
|
|
2102
2344
|
return builder.finish();
|
|
2103
2345
|
};
|
|
2104
|
-
var TableWidget = class extends
|
|
2346
|
+
var TableWidget = class extends WidgetType6 {
|
|
2105
2347
|
constructor(_table) {
|
|
2106
2348
|
super();
|
|
2107
2349
|
this._table = _table;
|
|
@@ -2138,10 +2380,10 @@ var TableWidget = class extends WidgetType5 {
|
|
|
2138
2380
|
}
|
|
2139
2381
|
};
|
|
2140
2382
|
|
|
2141
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2142
|
-
import { syntaxTree as
|
|
2143
|
-
import { RangeSetBuilder as
|
|
2144
|
-
import { EditorView as EditorView12, Decoration as
|
|
2383
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2384
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
2385
|
+
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
2386
|
+
import { EditorView as EditorView12, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
2145
2387
|
var styles5 = EditorView12.baseTheme({
|
|
2146
2388
|
"& .cm-task": {
|
|
2147
2389
|
color: getToken("extend.colors.blue.500")
|
|
@@ -2151,7 +2393,7 @@ var styles5 = EditorView12.baseTheme({
|
|
|
2151
2393
|
marginRight: "4px"
|
|
2152
2394
|
}
|
|
2153
2395
|
});
|
|
2154
|
-
var CheckboxWidget = class extends
|
|
2396
|
+
var CheckboxWidget = class extends WidgetType7 {
|
|
2155
2397
|
constructor(_checked) {
|
|
2156
2398
|
super();
|
|
2157
2399
|
this._checked = _checked;
|
|
@@ -2188,23 +2430,23 @@ var CheckboxWidget = class extends WidgetType6 {
|
|
|
2188
2430
|
return false;
|
|
2189
2431
|
}
|
|
2190
2432
|
};
|
|
2191
|
-
var checkedDecoration =
|
|
2433
|
+
var checkedDecoration = Decoration10.replace({
|
|
2192
2434
|
widget: new CheckboxWidget(true)
|
|
2193
2435
|
});
|
|
2194
|
-
var uncheckedDecoration =
|
|
2436
|
+
var uncheckedDecoration = Decoration10.replace({
|
|
2195
2437
|
widget: new CheckboxWidget(false)
|
|
2196
2438
|
});
|
|
2197
|
-
var
|
|
2198
|
-
const builder = new
|
|
2439
|
+
var buildDecorations6 = (view) => {
|
|
2440
|
+
const builder = new RangeSetBuilder7();
|
|
2199
2441
|
const { state } = view;
|
|
2200
2442
|
const cursor = state.selection.main.head;
|
|
2201
2443
|
for (const { from, to } of view.visibleRanges) {
|
|
2202
|
-
|
|
2444
|
+
syntaxTree8(state).iterate({
|
|
2203
2445
|
enter: (node) => {
|
|
2204
2446
|
if (node.name === "TaskMarker") {
|
|
2205
2447
|
if (cursor < node.from || cursor > node.to) {
|
|
2206
2448
|
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2207
|
-
builder.add(node.from - 2, node.from - 1,
|
|
2449
|
+
builder.add(node.from - 2, node.from - 1, Decoration10.mark({
|
|
2208
2450
|
class: "cm-task"
|
|
2209
2451
|
}));
|
|
2210
2452
|
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
@@ -2219,24 +2461,58 @@ var buildDecorations4 = (view) => {
|
|
|
2219
2461
|
};
|
|
2220
2462
|
var tasklist = (options = {}) => {
|
|
2221
2463
|
return [
|
|
2222
|
-
|
|
2464
|
+
ViewPlugin8.fromClass(class {
|
|
2223
2465
|
constructor(view) {
|
|
2224
|
-
this.decorations =
|
|
2466
|
+
this.decorations = buildDecorations6(view);
|
|
2225
2467
|
}
|
|
2226
2468
|
update(update2) {
|
|
2227
2469
|
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2228
|
-
this.decorations =
|
|
2470
|
+
this.decorations = buildDecorations6(update2.view);
|
|
2229
2471
|
}
|
|
2230
2472
|
}
|
|
2231
2473
|
}, {
|
|
2232
|
-
decorations: (
|
|
2474
|
+
decorations: (value) => value.decorations
|
|
2233
2475
|
}),
|
|
2234
2476
|
styles5
|
|
2235
2477
|
];
|
|
2236
2478
|
};
|
|
2237
2479
|
|
|
2480
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2481
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2482
|
+
var mention = ({ onSearch }) => {
|
|
2483
|
+
return autocompletion2({
|
|
2484
|
+
// TODO(burdon): Not working.
|
|
2485
|
+
activateOnTyping: true,
|
|
2486
|
+
// activateOnTypingDelay: 100,
|
|
2487
|
+
// selectOnOpen: true,
|
|
2488
|
+
closeOnBlur: false,
|
|
2489
|
+
// defaultKeymap: false,
|
|
2490
|
+
icons: false,
|
|
2491
|
+
override: [
|
|
2492
|
+
(context) => {
|
|
2493
|
+
console.log(context);
|
|
2494
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2495
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2496
|
+
return null;
|
|
2497
|
+
}
|
|
2498
|
+
return {
|
|
2499
|
+
from: match.from,
|
|
2500
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2501
|
+
label: `@${value}`
|
|
2502
|
+
}))
|
|
2503
|
+
};
|
|
2504
|
+
}
|
|
2505
|
+
]
|
|
2506
|
+
});
|
|
2507
|
+
};
|
|
2508
|
+
|
|
2509
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2510
|
+
var outliner = (options = {}) => {
|
|
2511
|
+
return [];
|
|
2512
|
+
};
|
|
2513
|
+
|
|
2238
2514
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2239
|
-
import { keymap as
|
|
2515
|
+
import { keymap as keymap6 } from "@codemirror/view";
|
|
2240
2516
|
var defaultItems = [
|
|
2241
2517
|
"hello world!",
|
|
2242
2518
|
"this is a test.",
|
|
@@ -2246,7 +2522,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2246
2522
|
let t;
|
|
2247
2523
|
let idx = 0;
|
|
2248
2524
|
return [
|
|
2249
|
-
|
|
2525
|
+
keymap6.of([
|
|
2250
2526
|
{
|
|
2251
2527
|
// Reset.
|
|
2252
2528
|
key: "alt-meta-'",
|
|
@@ -2292,27 +2568,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2292
2568
|
];
|
|
2293
2569
|
};
|
|
2294
2570
|
|
|
2295
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2296
|
-
import { yCollab } from "y-codemirror.next";
|
|
2297
|
-
|
|
2298
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2299
|
-
import * as Y from "yjs";
|
|
2300
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2301
|
-
var cursorConverter2 = (text) => ({
|
|
2302
|
-
toCursor: (index, assoc) => {
|
|
2303
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2304
|
-
},
|
|
2305
|
-
fromCursor: (cursor) => {
|
|
2306
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2307
|
-
}
|
|
2308
|
-
});
|
|
2309
|
-
|
|
2310
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2311
|
-
var yjs = (content, awareness2) => [
|
|
2312
|
-
Cursor.converter.of(cursorConverter2(content)),
|
|
2313
|
-
yCollab(content, awareness2)
|
|
2314
|
-
];
|
|
2315
|
-
|
|
2316
2571
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2317
2572
|
import get3 from "lodash.get";
|
|
2318
2573
|
var defaultTheme = {
|
|
@@ -2344,8 +2599,9 @@ var defaultTheme = {
|
|
|
2344
2599
|
outline: "none"
|
|
2345
2600
|
},
|
|
2346
2601
|
".cm-scroller": {
|
|
2347
|
-
overflow:
|
|
2348
|
-
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
2602
|
+
// overflow: 'visible',
|
|
2603
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(","),
|
|
2604
|
+
lineHeight: 1.4
|
|
2349
2605
|
},
|
|
2350
2606
|
".cm-content": {
|
|
2351
2607
|
padding: 0,
|
|
@@ -2353,11 +2609,11 @@ var defaultTheme = {
|
|
|
2353
2609
|
fontSize: "16px"
|
|
2354
2610
|
},
|
|
2355
2611
|
"&light .cm-content": {
|
|
2356
|
-
color: get3(tokens, "extend.
|
|
2612
|
+
color: get3(tokens, "extend.semanticColors.base.fg.light", "black"),
|
|
2357
2613
|
caretColor: "black"
|
|
2358
2614
|
},
|
|
2359
2615
|
"&dark .cm-content": {
|
|
2360
|
-
color: get3(tokens, "extend.
|
|
2616
|
+
color: get3(tokens, "extend.semanticColors.base.fg.dark", "white"),
|
|
2361
2617
|
caretColor: "white"
|
|
2362
2618
|
},
|
|
2363
2619
|
//
|
|
@@ -2369,8 +2625,11 @@ var defaultTheme = {
|
|
|
2369
2625
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2370
2626
|
borderLeft: "2px solid white"
|
|
2371
2627
|
},
|
|
2372
|
-
".cm-placeholder": {
|
|
2373
|
-
|
|
2628
|
+
"&light .cm-placeholder": {
|
|
2629
|
+
color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
2630
|
+
},
|
|
2631
|
+
"&dark .cm-placeholder": {
|
|
2632
|
+
color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
2374
2633
|
},
|
|
2375
2634
|
//
|
|
2376
2635
|
// line
|
|
@@ -2379,7 +2638,7 @@ var defaultTheme = {
|
|
|
2379
2638
|
paddingInline: 0
|
|
2380
2639
|
},
|
|
2381
2640
|
".cm-activeLine": {
|
|
2382
|
-
background: "
|
|
2641
|
+
background: "transparent"
|
|
2383
2642
|
},
|
|
2384
2643
|
//
|
|
2385
2644
|
// Selection
|
|
@@ -2550,31 +2809,35 @@ var codeTheme = {
|
|
|
2550
2809
|
};
|
|
2551
2810
|
|
|
2552
2811
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2553
|
-
var
|
|
2812
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2554
2813
|
var EditorModes = [
|
|
2555
2814
|
"default",
|
|
2556
2815
|
"vim"
|
|
2557
2816
|
];
|
|
2558
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2559
|
-
const
|
|
2560
|
-
tabBehavior: "limited"
|
|
2561
|
-
});
|
|
2562
|
-
const { themeMode } = useThemeContext2();
|
|
2817
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2818
|
+
const { themeMode } = useThemeContext();
|
|
2563
2819
|
const rootRef = useRef(null);
|
|
2564
2820
|
const [view, setView] = useState(null);
|
|
2565
2821
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2566
2822
|
view
|
|
2567
2823
|
]);
|
|
2568
|
-
|
|
2569
|
-
if (
|
|
2824
|
+
useEffect2(() => {
|
|
2825
|
+
if (autoFocus && !view?.hasFocus) {
|
|
2826
|
+
if (view?.state.selection.main?.from === 0) {
|
|
2827
|
+
const { to } = view.state.doc.lineAt(0);
|
|
2828
|
+
view?.dispatch({
|
|
2829
|
+
selection: {
|
|
2830
|
+
anchor: to
|
|
2831
|
+
}
|
|
2832
|
+
});
|
|
2833
|
+
}
|
|
2570
2834
|
view?.focus();
|
|
2571
2835
|
}
|
|
2572
2836
|
}, [
|
|
2573
2837
|
view,
|
|
2574
|
-
|
|
2838
|
+
autoFocus
|
|
2575
2839
|
]);
|
|
2576
|
-
|
|
2577
|
-
useEffect3(() => {
|
|
2840
|
+
useEffect2(() => {
|
|
2578
2841
|
if (!model || !rootRef.current) {
|
|
2579
2842
|
return;
|
|
2580
2843
|
}
|
|
@@ -2585,8 +2848,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2585
2848
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2586
2849
|
EditorView13.exceptionSink.of((err) => {
|
|
2587
2850
|
log2.catch(err, void 0, {
|
|
2588
|
-
F:
|
|
2589
|
-
L:
|
|
2851
|
+
F: __dxlog_file3,
|
|
2852
|
+
L: 134,
|
|
2590
2853
|
S: void 0,
|
|
2591
2854
|
C: (f, a) => f(...a)
|
|
2592
2855
|
});
|
|
@@ -2603,15 +2866,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2603
2866
|
class: slots.content?.className ?? ""
|
|
2604
2867
|
}),
|
|
2605
2868
|
// State.
|
|
2869
|
+
EditorView13.editable.of(!readonly),
|
|
2606
2870
|
EditorState2.readOnly.of(!!readonly),
|
|
2607
2871
|
// Storage and replication.
|
|
2608
2872
|
// NOTE: This must come before user extensions.
|
|
2609
2873
|
model.extension,
|
|
2610
|
-
// TODO(burdon): Factor out (
|
|
2874
|
+
// TODO(burdon): Factor out? (Requires special handling for Escape/Enter below).
|
|
2611
2875
|
editorMode === "vim" && vim(),
|
|
2612
2876
|
// Custom.
|
|
2613
2877
|
...extensions
|
|
2614
|
-
].filter(
|
|
2878
|
+
].filter(isNotFalsy3)
|
|
2615
2879
|
});
|
|
2616
2880
|
const newView = new EditorView13({
|
|
2617
2881
|
state,
|
|
@@ -2620,11 +2884,10 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2620
2884
|
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2621
2885
|
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2622
2886
|
dispatchTransactions: (trs, view2) => {
|
|
2623
|
-
view2.update(trs);
|
|
2624
|
-
const debug = false;
|
|
2625
2887
|
if (debug) {
|
|
2626
2888
|
logChanges(trs);
|
|
2627
2889
|
}
|
|
2890
|
+
view2.update(trs);
|
|
2628
2891
|
}
|
|
2629
2892
|
});
|
|
2630
2893
|
view?.destroy();
|
|
@@ -2649,7 +2912,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2649
2912
|
}
|
|
2650
2913
|
case "Escape": {
|
|
2651
2914
|
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2652
|
-
|
|
2915
|
+
view?.focus();
|
|
2653
2916
|
}
|
|
2654
2917
|
break;
|
|
2655
2918
|
}
|
|
@@ -2662,23 +2925,23 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autofocus, s
|
|
|
2662
2925
|
key: model.id,
|
|
2663
2926
|
role: "none",
|
|
2664
2927
|
tabIndex: 0,
|
|
2665
|
-
onKeyUp: handleKeyUp,
|
|
2666
2928
|
...slots.root,
|
|
2667
|
-
...editorMode !==
|
|
2929
|
+
// {...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
2930
|
+
onKeyUp: handleKeyUp,
|
|
2668
2931
|
ref: rootRef
|
|
2669
2932
|
});
|
|
2670
2933
|
});
|
|
2671
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3,
|
|
2672
|
-
const { themeMode } =
|
|
2934
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2935
|
+
const { themeMode } = useThemeContext();
|
|
2673
2936
|
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2674
2937
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2675
2938
|
ref: forwardedRef,
|
|
2676
2939
|
readonly,
|
|
2677
2940
|
extensions: [
|
|
2678
|
-
|
|
2941
|
+
createBasicBundle({
|
|
2679
2942
|
themeMode,
|
|
2680
2943
|
placeholder: placeholder3,
|
|
2681
|
-
|
|
2944
|
+
lineWrapping
|
|
2682
2945
|
}),
|
|
2683
2946
|
...extensions
|
|
2684
2947
|
],
|
|
@@ -2688,15 +2951,14 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2688
2951
|
});
|
|
2689
2952
|
});
|
|
2690
2953
|
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2691
|
-
const { themeMode } =
|
|
2954
|
+
const { themeMode } = useThemeContext();
|
|
2692
2955
|
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2693
2956
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2694
2957
|
ref: forwardedRef,
|
|
2695
2958
|
readonly,
|
|
2696
2959
|
extensions: [
|
|
2697
|
-
|
|
2960
|
+
createMarkdownExtensions({
|
|
2698
2961
|
themeMode,
|
|
2699
|
-
readonly,
|
|
2700
2962
|
placeholder: placeholder3
|
|
2701
2963
|
}),
|
|
2702
2964
|
...extensions
|
|
@@ -2708,11 +2970,10 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2708
2970
|
});
|
|
2709
2971
|
var defaultSlots = {
|
|
2710
2972
|
root: {
|
|
2711
|
-
|
|
2712
|
-
className: mx3("flex flex-col grow overflow-y-auto", inputSurface)
|
|
2973
|
+
className: mx3("grow", focusRing)
|
|
2713
2974
|
},
|
|
2714
2975
|
editor: {
|
|
2715
|
-
className: "
|
|
2976
|
+
className: "bs-full"
|
|
2716
2977
|
}
|
|
2717
2978
|
};
|
|
2718
2979
|
var defaultTextSlots = {
|
|
@@ -2722,22 +2983,178 @@ var defaultMarkdownSlots = {
|
|
|
2722
2983
|
...defaultSlots
|
|
2723
2984
|
};
|
|
2724
2985
|
|
|
2725
|
-
// packages/ui/react-ui-editor/src/
|
|
2726
|
-
import
|
|
2727
|
-
import {
|
|
2728
|
-
import
|
|
2986
|
+
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
2987
|
+
import { At, CaretRight, ChatText, Code, Image, Link, ListBullets, ListChecks, ListNumbers, TextStrikethrough, Table as Table2, TextB, TextItalic } from "@phosphor-icons/react";
|
|
2988
|
+
import { createContext } from "@radix-ui/react-context";
|
|
2989
|
+
import React2 from "react";
|
|
2990
|
+
import { Button, DensityProvider, Select } from "@dxos/react-ui";
|
|
2991
|
+
import { getSize } from "@dxos/react-ui-theme";
|
|
2992
|
+
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
2993
|
+
var ToolbarRoot = ({ children, onAction }) => {
|
|
2994
|
+
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
2995
|
+
onAction
|
|
2996
|
+
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
2997
|
+
density: "fine"
|
|
2998
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
2999
|
+
role: "toolbar",
|
|
3000
|
+
className: "flex w-full shrink-0 p-2 gap-4 items-center whitespace-nowrap overflow-hidden"
|
|
3001
|
+
}, children)));
|
|
3002
|
+
};
|
|
3003
|
+
var ToolbarButton = ({ Icon, onClick, title }) => {
|
|
3004
|
+
const { onAction } = useToolbarContext("ToolbarButton");
|
|
3005
|
+
const handleClick = () => {
|
|
3006
|
+
const action = onClick();
|
|
3007
|
+
if (action) {
|
|
3008
|
+
onAction?.(action);
|
|
3009
|
+
}
|
|
3010
|
+
};
|
|
3011
|
+
return /* @__PURE__ */ React2.createElement(Button, {
|
|
3012
|
+
variant: "ghost",
|
|
3013
|
+
classNames: "p-2",
|
|
3014
|
+
onClick: handleClick,
|
|
3015
|
+
title
|
|
3016
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
3017
|
+
className: getSize(5)
|
|
3018
|
+
}));
|
|
3019
|
+
};
|
|
3020
|
+
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3021
|
+
className: "grow"
|
|
3022
|
+
});
|
|
3023
|
+
var MarkdownHeading = () => {
|
|
3024
|
+
const { onAction } = useToolbarContext("MarkdownFormatting");
|
|
3025
|
+
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
3026
|
+
defaultValue: "0",
|
|
3027
|
+
onValueChange: (value) => onAction?.({
|
|
3028
|
+
type: "heading",
|
|
3029
|
+
data: parseInt(value)
|
|
3030
|
+
})
|
|
3031
|
+
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
|
|
3032
|
+
classNames: "w-[8rem]"
|
|
3033
|
+
}), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3034
|
+
value: "0"
|
|
3035
|
+
}, "Paragraph"), [
|
|
3036
|
+
1,
|
|
3037
|
+
2,
|
|
3038
|
+
3,
|
|
3039
|
+
4,
|
|
3040
|
+
5,
|
|
3041
|
+
6
|
|
3042
|
+
].map((level) => /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3043
|
+
key: level,
|
|
3044
|
+
value: String(level)
|
|
3045
|
+
}, "Heading ", level))))));
|
|
3046
|
+
};
|
|
3047
|
+
var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3048
|
+
role: "none"
|
|
3049
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3050
|
+
Icon: TextB,
|
|
3051
|
+
title: "Bold",
|
|
3052
|
+
onClick: () => ({
|
|
3053
|
+
type: "bold"
|
|
3054
|
+
})
|
|
3055
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3056
|
+
Icon: TextItalic,
|
|
3057
|
+
title: "Italic",
|
|
3058
|
+
onClick: () => ({
|
|
3059
|
+
type: "italic"
|
|
3060
|
+
})
|
|
3061
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3062
|
+
Icon: TextStrikethrough,
|
|
3063
|
+
title: "Strike-through",
|
|
3064
|
+
onClick: () => ({
|
|
3065
|
+
type: "strikethrough"
|
|
3066
|
+
})
|
|
3067
|
+
}));
|
|
3068
|
+
var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3069
|
+
role: "none"
|
|
3070
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3071
|
+
Icon: ListBullets,
|
|
3072
|
+
title: "Bullet list",
|
|
3073
|
+
onClick: () => ({
|
|
3074
|
+
type: "list"
|
|
3075
|
+
})
|
|
3076
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3077
|
+
Icon: ListNumbers,
|
|
3078
|
+
title: "Numbered list",
|
|
3079
|
+
onClick: () => ({
|
|
3080
|
+
type: "list-ordered"
|
|
3081
|
+
})
|
|
3082
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3083
|
+
Icon: ListChecks,
|
|
3084
|
+
title: "Task list",
|
|
3085
|
+
onClick: () => ({
|
|
3086
|
+
type: "list-tasks"
|
|
3087
|
+
})
|
|
3088
|
+
}));
|
|
3089
|
+
var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3090
|
+
role: "none"
|
|
3091
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3092
|
+
Icon: CaretRight,
|
|
3093
|
+
title: "Block quite",
|
|
3094
|
+
onClick: () => ({
|
|
3095
|
+
type: "blockquote"
|
|
3096
|
+
})
|
|
3097
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3098
|
+
Icon: Code,
|
|
3099
|
+
title: "Code block",
|
|
3100
|
+
onClick: () => ({
|
|
3101
|
+
type: "codeblock"
|
|
3102
|
+
})
|
|
3103
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3104
|
+
Icon: Table2,
|
|
3105
|
+
title: "Table",
|
|
3106
|
+
onClick: () => ({
|
|
3107
|
+
type: "table"
|
|
3108
|
+
})
|
|
3109
|
+
}));
|
|
3110
|
+
var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3111
|
+
role: "none"
|
|
3112
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3113
|
+
Icon: Link,
|
|
3114
|
+
title: "Link",
|
|
3115
|
+
onClick: () => ({
|
|
3116
|
+
type: "link"
|
|
3117
|
+
})
|
|
3118
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3119
|
+
Icon: At,
|
|
3120
|
+
title: "Mention",
|
|
3121
|
+
onClick: () => ({
|
|
3122
|
+
type: "mention"
|
|
3123
|
+
})
|
|
3124
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3125
|
+
Icon: Image,
|
|
3126
|
+
title: "Image",
|
|
3127
|
+
onClick: () => ({
|
|
3128
|
+
type: "image"
|
|
3129
|
+
})
|
|
3130
|
+
}));
|
|
3131
|
+
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));
|
|
3132
|
+
var MarkdownExtended = () => /* @__PURE__ */ React2.createElement(Toolbar.Button, {
|
|
3133
|
+
Icon: ChatText,
|
|
3134
|
+
title: "Create comment",
|
|
3135
|
+
onClick: () => ({
|
|
3136
|
+
type: "comment"
|
|
3137
|
+
})
|
|
3138
|
+
});
|
|
3139
|
+
var Toolbar = {
|
|
3140
|
+
Root: ToolbarRoot,
|
|
3141
|
+
Button: ToolbarButton,
|
|
3142
|
+
Separator: ToolbarSeparator,
|
|
3143
|
+
Markdown: MarkdownStandard,
|
|
3144
|
+
Extended: MarkdownExtended
|
|
3145
|
+
};
|
|
2729
3146
|
|
|
2730
3147
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2731
3148
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2732
3149
|
import { Context as Context2 } from "@dxos/context";
|
|
2733
|
-
import { invariant as
|
|
3150
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
2734
3151
|
import { log as log3 } from "@dxos/log";
|
|
2735
|
-
var
|
|
3152
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2736
3153
|
var DEBOUNCE_INTERVAL = 100;
|
|
2737
3154
|
var SpaceAwarenessProvider = class {
|
|
2738
3155
|
constructor(params) {
|
|
2739
|
-
this.remoteStateChange = new Event2();
|
|
2740
3156
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
3157
|
+
this.remoteStateChange = new Event2();
|
|
2741
3158
|
this._space = params.space;
|
|
2742
3159
|
this._channel = params.channel;
|
|
2743
3160
|
this._peerId = params.peerId;
|
|
@@ -2754,7 +3171,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2754
3171
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2755
3172
|
}
|
|
2756
3173
|
});
|
|
2757
|
-
|
|
3174
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2758
3175
|
switch (message.payload.kind) {
|
|
2759
3176
|
case "query": {
|
|
2760
3177
|
this._handleQueryMessage();
|
|
@@ -2765,16 +3182,15 @@ var SpaceAwarenessProvider = class {
|
|
|
2765
3182
|
break;
|
|
2766
3183
|
}
|
|
2767
3184
|
}
|
|
2768
|
-
});
|
|
2769
|
-
this._ctx.onDispose(unsubscribe);
|
|
3185
|
+
}));
|
|
2770
3186
|
void this._space.postMessage(this._channel, {
|
|
2771
3187
|
kind: "query"
|
|
2772
3188
|
}).catch((err) => {
|
|
2773
3189
|
log3.debug("failed to query awareness", {
|
|
2774
3190
|
err
|
|
2775
3191
|
}, {
|
|
2776
|
-
F:
|
|
2777
|
-
L:
|
|
3192
|
+
F: __dxlog_file4,
|
|
3193
|
+
L: 89,
|
|
2778
3194
|
S: this,
|
|
2779
3195
|
C: (f, a) => f(...a)
|
|
2780
3196
|
});
|
|
@@ -2785,10 +3201,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2785
3201
|
this._ctx = void 0;
|
|
2786
3202
|
this._postTask = void 0;
|
|
2787
3203
|
}
|
|
3204
|
+
getRemoteStates() {
|
|
3205
|
+
return Array.from(this._remoteStates.values());
|
|
3206
|
+
}
|
|
2788
3207
|
update(position) {
|
|
2789
|
-
|
|
2790
|
-
F:
|
|
2791
|
-
L:
|
|
3208
|
+
invariant2(this._postTask, void 0, {
|
|
3209
|
+
F: __dxlog_file4,
|
|
3210
|
+
L: 104,
|
|
2792
3211
|
S: this,
|
|
2793
3212
|
A: [
|
|
2794
3213
|
"this._postTask",
|
|
@@ -2802,13 +3221,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2802
3221
|
};
|
|
2803
3222
|
this._postTask.schedule();
|
|
2804
3223
|
}
|
|
2805
|
-
getRemoteStates() {
|
|
2806
|
-
return Array.from(this._remoteStates.values());
|
|
2807
|
-
}
|
|
2808
3224
|
_handleQueryMessage() {
|
|
2809
|
-
|
|
2810
|
-
F:
|
|
2811
|
-
L:
|
|
3225
|
+
invariant2(this._postTask, void 0, {
|
|
3226
|
+
F: __dxlog_file4,
|
|
3227
|
+
L: 115,
|
|
2812
3228
|
S: this,
|
|
2813
3229
|
A: [
|
|
2814
3230
|
"this._postTask",
|
|
@@ -2818,9 +3234,9 @@ var SpaceAwarenessProvider = class {
|
|
|
2818
3234
|
this._postTask.schedule();
|
|
2819
3235
|
}
|
|
2820
3236
|
_handlePostMessage(message) {
|
|
2821
|
-
|
|
2822
|
-
F:
|
|
2823
|
-
L:
|
|
3237
|
+
invariant2(message.kind === "post", void 0, {
|
|
3238
|
+
F: __dxlog_file4,
|
|
3239
|
+
L: 120,
|
|
2824
3240
|
S: this,
|
|
2825
3241
|
A: [
|
|
2826
3242
|
"message.kind === 'post'",
|
|
@@ -2839,182 +3255,177 @@ var modelState = StateField5.define({
|
|
|
2839
3255
|
update: (model) => model
|
|
2840
3256
|
});
|
|
2841
3257
|
|
|
2842
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2843
|
-
var
|
|
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
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
3258
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
3259
|
+
var useActionHandler = (view) => {
|
|
3260
|
+
return (action) => {
|
|
3261
|
+
if (!view) {
|
|
3262
|
+
return;
|
|
3263
|
+
}
|
|
3264
|
+
switch (action.type) {
|
|
3265
|
+
case "heading":
|
|
3266
|
+
setHeading(parseInt(action.data))(view);
|
|
3267
|
+
break;
|
|
3268
|
+
case "bold":
|
|
3269
|
+
toggleBold(view);
|
|
3270
|
+
break;
|
|
3271
|
+
case "italic":
|
|
3272
|
+
toggleItalic(view);
|
|
3273
|
+
break;
|
|
3274
|
+
case "strikethrough":
|
|
3275
|
+
toggleStrikethrough(view);
|
|
3276
|
+
break;
|
|
3277
|
+
case "list":
|
|
3278
|
+
toggleList(view);
|
|
3279
|
+
break;
|
|
3280
|
+
case "codeblock":
|
|
3281
|
+
insertCodeblock(view);
|
|
3282
|
+
break;
|
|
3283
|
+
case "table":
|
|
3284
|
+
insertTable(view);
|
|
3285
|
+
break;
|
|
3286
|
+
case "comment":
|
|
3287
|
+
createComment(view);
|
|
3288
|
+
break;
|
|
3289
|
+
}
|
|
3290
|
+
setTimeout(() => {
|
|
3291
|
+
view.focus();
|
|
3292
|
+
view.dispatch({
|
|
3293
|
+
selection: view.state.selection
|
|
3294
|
+
});
|
|
3295
|
+
});
|
|
2876
3296
|
};
|
|
2877
|
-
return model;
|
|
2878
3297
|
};
|
|
2879
3298
|
|
|
2880
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2881
|
-
import
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
F: __dxlog_file6,
|
|
2891
|
-
L: 22,
|
|
2892
|
-
S: void 0,
|
|
2893
|
-
A: [
|
|
2894
|
-
"text?.doc && text?.content",
|
|
2895
|
-
""
|
|
2896
|
-
]
|
|
2897
|
-
});
|
|
2898
|
-
const provider = space ? new YAwarenessProvider({
|
|
2899
|
-
space,
|
|
2900
|
-
doc: text.doc,
|
|
2901
|
-
channel: `yjs.awareness.${text.id}`
|
|
2902
|
-
}) : void 0;
|
|
2903
|
-
const model = {
|
|
2904
|
-
id: text.doc.guid,
|
|
2905
|
-
content: text.content,
|
|
2906
|
-
text: () => text.content.toString(),
|
|
2907
|
-
extension: [
|
|
2908
|
-
modelState.init(() => model),
|
|
2909
|
-
yjs(text.content, provider?.awareness)
|
|
2910
|
-
],
|
|
2911
|
-
awareness: provider?.awareness,
|
|
2912
|
-
peer: identity ? {
|
|
2913
|
-
id: identity.identityKey.toHex(),
|
|
2914
|
-
name: identity.profile?.displayName
|
|
2915
|
-
} : void 0
|
|
2916
|
-
};
|
|
2917
|
-
return model;
|
|
3299
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3300
|
+
import { useState as useState2 } from "react";
|
|
3301
|
+
var useEditorView = () => {
|
|
3302
|
+
const [view, setView] = useState2(null);
|
|
3303
|
+
return [
|
|
3304
|
+
(ref) => {
|
|
3305
|
+
setView(ref);
|
|
3306
|
+
},
|
|
3307
|
+
view
|
|
3308
|
+
];
|
|
2918
3309
|
};
|
|
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
|
-
|
|
2965
|
-
|
|
2966
|
-
_handleSpaceMessage({ payload }) {
|
|
2967
|
-
log4("space message", payload, {
|
|
2968
|
-
F: __dxlog_file6,
|
|
2969
|
-
L: 110,
|
|
2970
|
-
S: this,
|
|
2971
|
-
C: (f, a) => f(...a)
|
|
2972
|
-
});
|
|
2973
|
-
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2974
|
-
const encoder = this._readMessage(data);
|
|
2975
|
-
if (encoder) {
|
|
2976
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
3310
|
+
|
|
3311
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
3312
|
+
import { EditorSelection, EditorState as EditorState3 } from "@codemirror/state";
|
|
3313
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
3314
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
3315
|
+
import { log as log4 } from "@dxos/log";
|
|
3316
|
+
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
3317
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
3318
|
+
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
|
|
3319
|
+
const onUpdate = useRef2();
|
|
3320
|
+
const [view, setView] = useState3();
|
|
3321
|
+
const parentRef = useRef2(null);
|
|
3322
|
+
useEffect3(() => {
|
|
3323
|
+
if (parentRef.current) {
|
|
3324
|
+
const state = EditorState3.create({
|
|
3325
|
+
doc,
|
|
3326
|
+
selection,
|
|
3327
|
+
extensions: [
|
|
3328
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
3329
|
+
EditorView14.exceptionSink.of((err) => {
|
|
3330
|
+
log4.catch(err, void 0, {
|
|
3331
|
+
F: __dxlog_file5,
|
|
3332
|
+
L: 57,
|
|
3333
|
+
S: void 0,
|
|
3334
|
+
C: (f, a) => f(...a)
|
|
3335
|
+
});
|
|
3336
|
+
}),
|
|
3337
|
+
extensions,
|
|
3338
|
+
EditorView14.updateListener.of(() => {
|
|
3339
|
+
onUpdate.current?.();
|
|
3340
|
+
})
|
|
3341
|
+
].filter(isNotFalsy4)
|
|
3342
|
+
});
|
|
3343
|
+
const view2 = new EditorView14({
|
|
3344
|
+
parent: parentRef.current,
|
|
3345
|
+
scrollTo,
|
|
3346
|
+
state,
|
|
3347
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
3348
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
3349
|
+
dispatchTransactions: (trs, view3) => {
|
|
3350
|
+
if (debug) {
|
|
3351
|
+
logChanges(trs);
|
|
3352
|
+
}
|
|
3353
|
+
view3.update(trs);
|
|
3354
|
+
}
|
|
3355
|
+
});
|
|
3356
|
+
setView(view2);
|
|
2977
3357
|
}
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
3358
|
+
return () => {
|
|
3359
|
+
view?.destroy();
|
|
3360
|
+
};
|
|
3361
|
+
}, [
|
|
3362
|
+
parentRef
|
|
3363
|
+
]);
|
|
3364
|
+
useEffect3(() => {
|
|
3365
|
+
if (view) {
|
|
3366
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
3367
|
+
selection = EditorSelection.single(view.state.doc.line(1).to);
|
|
2988
3368
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3369
|
+
if (selection || scrollTo) {
|
|
3370
|
+
onUpdate.current = () => {
|
|
3371
|
+
onUpdate.current = void 0;
|
|
3372
|
+
view.dispatch({
|
|
3373
|
+
selection,
|
|
3374
|
+
effects: scrollTo && [
|
|
3375
|
+
scrollTo
|
|
3376
|
+
],
|
|
3377
|
+
scrollIntoView: !scrollTo
|
|
3378
|
+
});
|
|
3379
|
+
};
|
|
2994
3380
|
}
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
return encoder;
|
|
3381
|
+
if (autoFocus) {
|
|
3382
|
+
view.focus();
|
|
2998
3383
|
}
|
|
2999
3384
|
}
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
}
|
|
3385
|
+
}, [
|
|
3386
|
+
view,
|
|
3387
|
+
autoFocus,
|
|
3388
|
+
selection,
|
|
3389
|
+
scrollTo
|
|
3390
|
+
]);
|
|
3391
|
+
return {
|
|
3392
|
+
parentRef,
|
|
3393
|
+
view
|
|
3394
|
+
};
|
|
3395
|
+
};
|
|
3396
|
+
var createDataExtensions = ({ readonly = false } = {}) => {
|
|
3397
|
+
return [
|
|
3398
|
+
//
|
|
3399
|
+
EditorState3.readOnly.of(readonly),
|
|
3400
|
+
EditorView14.editable.of(!readonly)
|
|
3401
|
+
];
|
|
3402
|
+
};
|
|
3403
|
+
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
3404
|
+
return [
|
|
3405
|
+
//
|
|
3406
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3407
|
+
theme && EditorView14.theme(theme),
|
|
3408
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3409
|
+
EditorView14.editorAttributes.of({
|
|
3410
|
+
class: slots?.editor?.className ?? ""
|
|
3411
|
+
}),
|
|
3412
|
+
EditorView14.contentAttributes.of({
|
|
3413
|
+
class: slots?.content?.className ?? ""
|
|
3414
|
+
})
|
|
3415
|
+
].filter(isNotFalsy4);
|
|
3010
3416
|
};
|
|
3011
3417
|
|
|
3012
3418
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
3013
|
-
import
|
|
3419
|
+
import get4 from "lodash.get";
|
|
3420
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
3421
|
+
import { generateName } from "@dxos/display-name";
|
|
3422
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
3423
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
3014
3424
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
3425
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
3015
3426
|
var useTextModel = (props) => {
|
|
3016
3427
|
const { identity, space, text } = props;
|
|
3017
|
-
const [model, setModel] =
|
|
3428
|
+
const [model, setModel] = useState4();
|
|
3018
3429
|
useEffect4(() => setModel(createModel(props)), [
|
|
3019
3430
|
identity,
|
|
3020
3431
|
space,
|
|
@@ -3022,18 +3433,63 @@ var useTextModel = (props) => {
|
|
|
3022
3433
|
]);
|
|
3023
3434
|
return model;
|
|
3024
3435
|
};
|
|
3025
|
-
var
|
|
3026
|
-
const
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3436
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
3437
|
+
const [content, setContent] = useState4(defaultContent ?? "");
|
|
3438
|
+
return {
|
|
3439
|
+
id,
|
|
3440
|
+
content,
|
|
3441
|
+
setContent,
|
|
3442
|
+
text: () => content
|
|
3443
|
+
};
|
|
3444
|
+
};
|
|
3445
|
+
var createModel = ({ space, identity, text }) => {
|
|
3446
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
3447
|
+
F: __dxlog_file6,
|
|
3448
|
+
L: 50,
|
|
3449
|
+
S: void 0,
|
|
3450
|
+
A: [
|
|
3451
|
+
"isAutomergeObject(text)",
|
|
3452
|
+
""
|
|
3453
|
+
]
|
|
3454
|
+
});
|
|
3455
|
+
const obj = text;
|
|
3456
|
+
const doc = getRawDoc(obj, [
|
|
3457
|
+
obj.field
|
|
3458
|
+
]);
|
|
3459
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
3460
|
+
space,
|
|
3461
|
+
channel: `automerge.awareness.${obj.id}`,
|
|
3462
|
+
info: {
|
|
3463
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
3464
|
+
color: cursorColor.color,
|
|
3465
|
+
lightColor: cursorColor.light
|
|
3466
|
+
},
|
|
3467
|
+
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
3468
|
+
});
|
|
3469
|
+
const extensions = [
|
|
3470
|
+
//
|
|
3471
|
+
modelState.init(() => model),
|
|
3472
|
+
automerge({
|
|
3473
|
+
handle: doc.handle,
|
|
3474
|
+
path: doc.path
|
|
3475
|
+
})
|
|
3476
|
+
];
|
|
3477
|
+
if (awarenessProvider2) {
|
|
3478
|
+
extensions.push(awareness(awarenessProvider2));
|
|
3033
3479
|
}
|
|
3480
|
+
const model = {
|
|
3481
|
+
id: obj.id,
|
|
3482
|
+
content: doc,
|
|
3483
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3484
|
+
extension: extensions,
|
|
3485
|
+
peer: identity ? {
|
|
3486
|
+
id: identity.identityKey.toHex(),
|
|
3487
|
+
name: identity.profile?.displayName
|
|
3488
|
+
} : void 0
|
|
3489
|
+
};
|
|
3490
|
+
return model;
|
|
3034
3491
|
};
|
|
3035
3492
|
export {
|
|
3036
|
-
AwarenessProvider,
|
|
3037
3493
|
BaseTextEditor,
|
|
3038
3494
|
Cursor,
|
|
3039
3495
|
Doc,
|
|
@@ -3043,32 +3499,40 @@ export {
|
|
|
3043
3499
|
SpaceAwarenessProvider,
|
|
3044
3500
|
TextEditor,
|
|
3045
3501
|
TextKind,
|
|
3046
|
-
|
|
3502
|
+
Toolbar,
|
|
3047
3503
|
YText,
|
|
3048
3504
|
YXmlFragment,
|
|
3049
3505
|
autocomplete,
|
|
3050
|
-
|
|
3506
|
+
automerge,
|
|
3051
3507
|
awareness,
|
|
3052
|
-
|
|
3508
|
+
awarenessProvider,
|
|
3053
3509
|
blast,
|
|
3054
3510
|
callbackWrapper,
|
|
3055
3511
|
code2 as code,
|
|
3056
3512
|
codeTheme,
|
|
3057
3513
|
comments,
|
|
3058
|
-
|
|
3059
|
-
|
|
3514
|
+
createBasicBundle,
|
|
3515
|
+
createComment,
|
|
3516
|
+
createDataExtensions,
|
|
3517
|
+
createMarkdownExtensions,
|
|
3518
|
+
createThemeExtensions,
|
|
3060
3519
|
defaultMarkdownSlots,
|
|
3061
3520
|
defaultOptions,
|
|
3062
3521
|
defaultSlots,
|
|
3063
3522
|
defaultTextSlots,
|
|
3064
3523
|
defaultTheme,
|
|
3524
|
+
focusComment,
|
|
3525
|
+
formatting,
|
|
3065
3526
|
getToken,
|
|
3527
|
+
heading2 as heading,
|
|
3066
3528
|
hr,
|
|
3067
3529
|
image,
|
|
3530
|
+
insertCodeblock,
|
|
3531
|
+
insertTable,
|
|
3532
|
+
keymap7 as keymap,
|
|
3068
3533
|
link,
|
|
3069
3534
|
listener,
|
|
3070
3535
|
logChanges,
|
|
3071
|
-
markdownBundle,
|
|
3072
3536
|
markdownHighlightStyle,
|
|
3073
3537
|
markdownTags,
|
|
3074
3538
|
markdownTagsExtensions,
|
|
@@ -3077,16 +3541,24 @@ export {
|
|
|
3077
3541
|
modelState,
|
|
3078
3542
|
outliner,
|
|
3079
3543
|
setComments,
|
|
3080
|
-
|
|
3544
|
+
setHeading,
|
|
3081
3545
|
setSelection,
|
|
3082
3546
|
table,
|
|
3083
3547
|
tags2 as tags,
|
|
3084
3548
|
tasklist,
|
|
3085
3549
|
textTheme,
|
|
3550
|
+
toggleBold,
|
|
3551
|
+
toggleItalic,
|
|
3552
|
+
toggleList,
|
|
3553
|
+
toggleStrikethrough,
|
|
3554
|
+
toggleStyle,
|
|
3086
3555
|
typewriter,
|
|
3087
|
-
|
|
3556
|
+
useActionHandler,
|
|
3088
3557
|
useComments,
|
|
3558
|
+
useEditorView,
|
|
3559
|
+
useInMemoryTextModel,
|
|
3560
|
+
useTextEditor,
|
|
3089
3561
|
useTextModel,
|
|
3090
|
-
|
|
3562
|
+
useToolbarContext
|
|
3091
3563
|
};
|
|
3092
3564
|
//# sourceMappingURL=index.mjs.map
|