@dxos/react-ui-editor 0.3.10-main.3c0616c → 0.3.10-main.3edbcce
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 +410 -215
- 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 +3 -0
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +1 -0
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts +3 -2
- package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts +18 -0
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/demo.d.ts +10 -0
- package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/index.d.ts +2 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts +4 -2
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +1 -4
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts +3 -0
- package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
- package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/PatchSemaphore.d.ts +3 -0
- package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/handle.d.ts.map +1 -0
- package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/index.d.ts +1 -1
- package/dist/types/src/hooks/automerge/index.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts +5 -0
- package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts +6 -0
- package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/translation/index.d.ts +3 -0
- package/dist/types/src/hooks/automerge/translation/index.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +0 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +3 -4
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/testing/replicator.d.ts.map +1 -1
- package/package.json +20 -19
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +41 -8
- package/src/components/TextEditor/TextEditor.tsx +39 -21
- package/src/components/TextEditor/extensions/autocomplete.ts +5 -3
- package/src/components/TextEditor/extensions/comments.ts +190 -0
- package/src/components/TextEditor/extensions/demo.ts +66 -0
- package/src/components/TextEditor/extensions/experimental.tsx +1 -0
- package/src/components/TextEditor/extensions/index.ts +2 -0
- package/src/components/TextEditor/extensions/link.ts +10 -2
- package/src/components/TextEditor/extensions/listener.ts +3 -2
- package/src/components/TextEditor/extensions/markdown/bundle.ts +6 -14
- package/src/components/TextEditor/extensions/markdown/highlight.ts +2 -1
- package/src/components/TextEditor/extensions/tasklist.ts +73 -79
- package/src/components/TextEditor/themes/default.ts +15 -0
- package/src/{automerge/automerge-plugin → hooks/automerge}/PatchSemaphore.ts +12 -9
- package/src/{automerge → hooks/automerge}/automerge.stories.tsx +2 -1
- package/src/{automerge/automerge-plugin → hooks/automerge}/plugin.ts +1 -0
- package/src/{automerge/automerge-plugin/amToCodemirror.ts → hooks/automerge/translation/automerge-to-codemirror.ts} +10 -2
- package/src/{automerge/automerge-plugin/codeMirrorToAm.ts → hooks/automerge/translation/codemirror-to-automerge.ts} +7 -4
- package/src/hooks/automerge/translation/index.ts +6 -0
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useTextModel.ts +49 -41
- package/src/testing/replicator.ts +6 -7
- package/dist/types/src/automerge/automerge-plugin/PatchSemaphore.d.ts.map +0 -1
- package/dist/types/src/automerge/automerge-plugin/amToCodemirror.d.ts +0 -6
- package/dist/types/src/automerge/automerge-plugin/amToCodemirror.d.ts.map +0 -1
- package/dist/types/src/automerge/automerge-plugin/codeMirrorToAm.d.ts +0 -7
- package/dist/types/src/automerge/automerge-plugin/codeMirrorToAm.d.ts.map +0 -1
- package/dist/types/src/automerge/automerge-plugin/handle.d.ts.map +0 -1
- package/dist/types/src/automerge/automerge-plugin/index.d.ts.map +0 -1
- package/dist/types/src/automerge/automerge-plugin/plugin.d.ts.map +0 -1
- package/dist/types/src/automerge/automerge.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/useCollaboration.d.ts +0 -9
- package/dist/types/src/hooks/useCollaboration.d.ts.map +0 -1
- package/src/hooks/useCollaboration.ts +0 -45
- package/dist/types/src/{automerge → hooks/automerge}/automerge.stories.d.ts +0 -0
- package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/handle.d.ts +0 -0
- package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/plugin.d.ts +0 -0
- package/src/{automerge/automerge-plugin → hooks/automerge}/handle.ts +0 -0
- package/src/{automerge/automerge-plugin → hooks/automerge}/index.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// packages/ui/react-ui-editor/src/index.ts
|
|
2
2
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
3
|
-
import { Doc, YText
|
|
3
|
+
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
4
4
|
|
|
5
5
|
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
6
6
|
import { tags as tags2 } from "@lezer/highlight";
|
|
@@ -8,7 +8,7 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
8
8
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/autocomplete.ts
|
|
9
9
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
10
10
|
import { keymap } from "@codemirror/view";
|
|
11
|
-
var autocomplete = ({
|
|
11
|
+
var autocomplete = ({ onSearch }) => {
|
|
12
12
|
return [
|
|
13
13
|
// https://codemirror.net/docs/ref/#view.keymap
|
|
14
14
|
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
|
@@ -30,7 +30,7 @@ var autocomplete = ({ getOptions }) => {
|
|
|
30
30
|
}
|
|
31
31
|
return {
|
|
32
32
|
from: word.from,
|
|
33
|
-
options:
|
|
33
|
+
options: onSearch(word.text.toLowerCase())
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
]
|
|
@@ -54,11 +54,204 @@ var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
|
|
|
54
54
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
55
55
|
].filter(Boolean);
|
|
56
56
|
|
|
57
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
|
|
58
|
+
import { keymap as keymap2 } from "@codemirror/view";
|
|
59
|
+
var defaultItems = [
|
|
60
|
+
"hello world!",
|
|
61
|
+
"this is a test.",
|
|
62
|
+
"this is [DXOS](https://dxos.org)"
|
|
63
|
+
];
|
|
64
|
+
var demo = ({ delay = 75, items = defaultItems } = {}) => {
|
|
65
|
+
let t;
|
|
66
|
+
let idx = 0;
|
|
67
|
+
return [
|
|
68
|
+
keymap2.of([
|
|
69
|
+
{
|
|
70
|
+
// Reset.
|
|
71
|
+
key: "alt-meta-'",
|
|
72
|
+
run: (view) => {
|
|
73
|
+
clearTimeout(t);
|
|
74
|
+
idx = 0;
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
// Next prompt.
|
|
80
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
|
81
|
+
key: "shift-meta-'",
|
|
82
|
+
run: (view) => {
|
|
83
|
+
clearTimeout(t);
|
|
84
|
+
const text = items[idx++];
|
|
85
|
+
if (idx === items?.length) {
|
|
86
|
+
idx = 0;
|
|
87
|
+
}
|
|
88
|
+
let i = 0;
|
|
89
|
+
const insert = (d = 0) => {
|
|
90
|
+
t = setTimeout(() => {
|
|
91
|
+
const pos = view.state.selection.main.head;
|
|
92
|
+
view.dispatch({
|
|
93
|
+
changes: {
|
|
94
|
+
from: pos,
|
|
95
|
+
insert: text[i++]
|
|
96
|
+
},
|
|
97
|
+
selection: {
|
|
98
|
+
anchor: pos + 1
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
if (i < text.length) {
|
|
102
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
103
|
+
}
|
|
104
|
+
}, d);
|
|
105
|
+
};
|
|
106
|
+
insert();
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
])
|
|
111
|
+
];
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
|
|
115
|
+
import { keymap as keymap3, Decoration, EditorView as EditorView2, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
|
|
116
|
+
import { debounce } from "@dxos/async";
|
|
117
|
+
import { invariant } from "@dxos/invariant";
|
|
118
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
|
|
119
|
+
var BookmarkWidget = class extends WidgetType {
|
|
120
|
+
constructor(_pos, _id) {
|
|
121
|
+
super();
|
|
122
|
+
this._pos = _pos;
|
|
123
|
+
this._id = _id;
|
|
124
|
+
invariant(this._id, void 0, {
|
|
125
|
+
F: __dxlog_file,
|
|
126
|
+
L: 41,
|
|
127
|
+
S: this,
|
|
128
|
+
A: [
|
|
129
|
+
"this._id",
|
|
130
|
+
""
|
|
131
|
+
]
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
eq(other) {
|
|
135
|
+
return this._id === other._id;
|
|
136
|
+
}
|
|
137
|
+
toDOM() {
|
|
138
|
+
const span = document.createElement("span");
|
|
139
|
+
span.className = "cm-bookmark";
|
|
140
|
+
span.textContent = "\u{1F4AC}";
|
|
141
|
+
return span;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
var styles = EditorView2.baseTheme({
|
|
145
|
+
"& .cm-bookmark": {
|
|
146
|
+
cursor: "pointer",
|
|
147
|
+
margin: "4px",
|
|
148
|
+
padding: "4px",
|
|
149
|
+
backgroundColor: "yellow"
|
|
150
|
+
},
|
|
151
|
+
"& .cm-bookmark-selected": {
|
|
152
|
+
backgroundColor: "orange"
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
var comments = (options = {}) => {
|
|
156
|
+
let active;
|
|
157
|
+
const bookmarkMatcher = new MatchDecorator({
|
|
158
|
+
regexp: /\[\^(\w+)\]/g,
|
|
159
|
+
decoration: (match, view, pos) => {
|
|
160
|
+
const id = match[1];
|
|
161
|
+
return Decoration.replace({
|
|
162
|
+
id,
|
|
163
|
+
widget: new BookmarkWidget(pos, id)
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
const bookmarks = ViewPlugin.fromClass(class {
|
|
168
|
+
constructor(view) {
|
|
169
|
+
this.bookmarks = bookmarkMatcher.createDeco(view);
|
|
170
|
+
}
|
|
171
|
+
update(update2) {
|
|
172
|
+
this.bookmarks = bookmarkMatcher.updateDeco(update2, this.bookmarks);
|
|
173
|
+
}
|
|
174
|
+
}, {
|
|
175
|
+
decorations: (instance) => instance.bookmarks,
|
|
176
|
+
provide: (plugin) => EditorView2.atomicRanges.of((view) => {
|
|
177
|
+
return view.plugin(plugin)?.bookmarks || Decoration.none;
|
|
178
|
+
})
|
|
179
|
+
});
|
|
180
|
+
const doUpdate = debounce((data) => {
|
|
181
|
+
options.onUpdate?.(data);
|
|
182
|
+
}, 200);
|
|
183
|
+
return [
|
|
184
|
+
keymap3.of([
|
|
185
|
+
{
|
|
186
|
+
key: options?.key ?? "shift-meta-c",
|
|
187
|
+
run: (view) => {
|
|
188
|
+
const id = options.onCreate?.();
|
|
189
|
+
if (id) {
|
|
190
|
+
const pos = view.state.selection.main.head;
|
|
191
|
+
const tag = `[^${id}]`;
|
|
192
|
+
view.dispatch({
|
|
193
|
+
changes: {
|
|
194
|
+
from: pos,
|
|
195
|
+
insert: tag
|
|
196
|
+
},
|
|
197
|
+
selection: {
|
|
198
|
+
anchor: pos + tag.length
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
]),
|
|
207
|
+
bookmarks,
|
|
208
|
+
// Monitor cursor movement.
|
|
209
|
+
EditorView2.updateListener.of((update2) => {
|
|
210
|
+
active = void 0;
|
|
211
|
+
if (!options.onUpdate) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const view = update2.view;
|
|
215
|
+
const pos = view.state.selection.main.head;
|
|
216
|
+
const decorations = [];
|
|
217
|
+
const rangeSet = view.plugin(bookmarks)?.bookmarks;
|
|
218
|
+
let closest = Infinity;
|
|
219
|
+
const { from, to } = view.visibleRanges?.[0] ?? {
|
|
220
|
+
from: 0,
|
|
221
|
+
to: view.state.doc.length
|
|
222
|
+
};
|
|
223
|
+
rangeSet?.between(from, to, (from2, to2, value) => {
|
|
224
|
+
decorations.push({
|
|
225
|
+
from: from2,
|
|
226
|
+
to: to2,
|
|
227
|
+
value
|
|
228
|
+
});
|
|
229
|
+
const d = Math.min(Math.abs(pos - from2), Math.abs(pos - to2));
|
|
230
|
+
if (d < closest) {
|
|
231
|
+
active = value.spec.id;
|
|
232
|
+
closest = d;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
if (decorations.length) {
|
|
236
|
+
doUpdate({
|
|
237
|
+
active,
|
|
238
|
+
items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
|
|
239
|
+
id,
|
|
240
|
+
pos: from2,
|
|
241
|
+
location: view.coordsAtPos(from2)
|
|
242
|
+
}))
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}),
|
|
246
|
+
styles
|
|
247
|
+
];
|
|
248
|
+
};
|
|
249
|
+
|
|
57
250
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
|
|
58
251
|
import { syntaxTree } from "@codemirror/language";
|
|
59
252
|
import { RangeSetBuilder, StateField } from "@codemirror/state";
|
|
60
|
-
import { Decoration, EditorView as
|
|
61
|
-
var LinkButton = class extends
|
|
253
|
+
import { Decoration as Decoration2, EditorView as EditorView3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
254
|
+
var LinkButton = class extends WidgetType2 {
|
|
62
255
|
constructor(_pos, _url, _onAttach) {
|
|
63
256
|
super();
|
|
64
257
|
this._pos = _pos;
|
|
@@ -74,7 +267,7 @@ var LinkButton = class extends WidgetType {
|
|
|
74
267
|
return el;
|
|
75
268
|
}
|
|
76
269
|
};
|
|
77
|
-
var LinkText = class extends
|
|
270
|
+
var LinkText = class extends WidgetType2 {
|
|
78
271
|
constructor(_pos, _text, _url) {
|
|
79
272
|
super();
|
|
80
273
|
this._pos = _pos;
|
|
@@ -114,18 +307,21 @@ var update = (state, options) => {
|
|
|
114
307
|
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
115
308
|
const urlNode = node.node.getChild("URL");
|
|
116
309
|
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
310
|
+
if (!url) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
117
313
|
if (cursor < node.from || cursor > node.to) {
|
|
118
|
-
builder.add(node.from, node.to,
|
|
314
|
+
builder.add(node.from, node.to, Decoration2.replace({
|
|
119
315
|
widget: new LinkText(node.from, text, options.link ? url : void 0)
|
|
120
316
|
}));
|
|
121
317
|
}
|
|
122
318
|
if (options.onRender) {
|
|
123
|
-
builder.add(node.to, node.to,
|
|
319
|
+
builder.add(node.to, node.to, Decoration2.replace({
|
|
124
320
|
widget: new LinkButton(node.from, url, options.onRender)
|
|
125
321
|
}));
|
|
126
322
|
}
|
|
323
|
+
return false;
|
|
127
324
|
}
|
|
128
|
-
return true;
|
|
129
325
|
}
|
|
130
326
|
});
|
|
131
327
|
return builder.finish();
|
|
@@ -134,13 +330,13 @@ var link = (options = {}) => {
|
|
|
134
330
|
return StateField.define({
|
|
135
331
|
create: (state) => update(state, options),
|
|
136
332
|
update: (_, tr) => update(tr.state, options),
|
|
137
|
-
provide: (field) =>
|
|
333
|
+
provide: (field) => EditorView3.decorations.from(field)
|
|
138
334
|
});
|
|
139
335
|
};
|
|
140
336
|
|
|
141
337
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
|
|
142
338
|
import { StateField as StateField2 } from "@codemirror/state";
|
|
143
|
-
var listener = (onChange) => StateField2.define({
|
|
339
|
+
var listener = ({ onChange }) => StateField2.define({
|
|
144
340
|
create: () => null,
|
|
145
341
|
update: (_value, transaction) => {
|
|
146
342
|
if (transaction.docChanged && onChange) {
|
|
@@ -152,15 +348,14 @@ var listener = (onChange) => StateField2.define({
|
|
|
152
348
|
|
|
153
349
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
154
350
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
155
|
-
import { defaultKeymap, history,
|
|
351
|
+
import { defaultKeymap, history, indentWithTab } from "@codemirror/commands";
|
|
156
352
|
import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
|
|
157
|
-
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2,
|
|
353
|
+
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
158
354
|
import { languages } from "@codemirror/language-data";
|
|
159
|
-
import { lintKeymap } from "@codemirror/lint";
|
|
160
355
|
import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
|
|
161
356
|
import { EditorState } from "@codemirror/state";
|
|
162
357
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
163
|
-
import { crosshairCursor, drawSelection, dropCursor, EditorView as
|
|
358
|
+
import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView4, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap4, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
|
|
164
359
|
|
|
165
360
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
|
|
166
361
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
@@ -320,10 +515,11 @@ var markdownHighlightStyle = HighlightStyle.define([
|
|
|
320
515
|
],
|
|
321
516
|
class: codeMark
|
|
322
517
|
},
|
|
323
|
-
// The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
518
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
324
519
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
325
520
|
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
326
521
|
// the code, but all other CSS properties will be inherited.
|
|
522
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
327
523
|
{
|
|
328
524
|
tag: [
|
|
329
525
|
markdownTags.CodeText,
|
|
@@ -357,8 +553,7 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
357
553
|
closeBrackets2(),
|
|
358
554
|
_placeholder && placeholder2(_placeholder),
|
|
359
555
|
EditorState.allowMultipleSelections.of(true),
|
|
360
|
-
|
|
361
|
-
// autocompletion(),
|
|
556
|
+
EditorView4.lineWrapping,
|
|
362
557
|
crosshairCursor(),
|
|
363
558
|
dropCursor(),
|
|
364
559
|
drawSelection(),
|
|
@@ -369,13 +564,13 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
369
564
|
history(),
|
|
370
565
|
indentOnInput(),
|
|
371
566
|
rectangularSelection(),
|
|
372
|
-
|
|
567
|
+
// TODO(burdon): Review.
|
|
568
|
+
keymap4.of([
|
|
373
569
|
...closeBracketsKeymap,
|
|
374
|
-
// ...completionKeymap,
|
|
375
570
|
...defaultKeymap,
|
|
376
|
-
...foldKeymap,
|
|
377
|
-
...historyKeymap,
|
|
378
|
-
...lintKeymap,
|
|
571
|
+
// ...foldKeymap,
|
|
572
|
+
// ...historyKeymap,
|
|
573
|
+
// ...lintKeymap,
|
|
379
574
|
...searchKeymap,
|
|
380
575
|
indentWithTab
|
|
381
576
|
]),
|
|
@@ -405,90 +600,84 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
405
600
|
};
|
|
406
601
|
|
|
407
602
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
|
|
408
|
-
import {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
var CheckboxWidget = class extends WidgetType2 {
|
|
412
|
-
constructor(_pos, _getCursor, _checked) {
|
|
603
|
+
import { EditorView as EditorView5, Decoration as Decoration3, WidgetType as WidgetType3, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin2 } from "@codemirror/view";
|
|
604
|
+
var CheckboxWidget = class extends WidgetType3 {
|
|
605
|
+
constructor(_pos, _checked, _indent, _onCheck) {
|
|
413
606
|
super();
|
|
414
607
|
this._pos = _pos;
|
|
415
|
-
this._getCursor = _getCursor;
|
|
416
608
|
this._checked = _checked;
|
|
609
|
+
this._indent = _indent;
|
|
610
|
+
this._onCheck = _onCheck;
|
|
417
611
|
}
|
|
418
612
|
eq(other) {
|
|
419
|
-
return this._pos === other._pos && this._checked === other._checked;
|
|
613
|
+
return this._pos === other._pos && this._checked === other._checked && this._indent === other._indent;
|
|
420
614
|
}
|
|
421
615
|
toDOM(view) {
|
|
422
616
|
const wrap = document.createElement("span");
|
|
423
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
424
617
|
wrap.className = "cm-task-item";
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
from: this._pos + 1,
|
|
433
|
-
to: this._pos + 2,
|
|
434
|
-
insert: this._checked ? "x" : " "
|
|
435
|
-
},
|
|
436
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
437
|
-
selection: {
|
|
438
|
-
anchor: this._pos + 4
|
|
439
|
-
}
|
|
440
|
-
});
|
|
618
|
+
wrap.setAttribute("aria-hidden", "true");
|
|
619
|
+
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
620
|
+
const input = wrap.appendChild(document.createElement("input"));
|
|
621
|
+
input.type = "checkbox";
|
|
622
|
+
input.checked = this._checked;
|
|
623
|
+
input.onchange = (event) => {
|
|
624
|
+
this._onCheck(event.target.checked);
|
|
441
625
|
return true;
|
|
442
626
|
};
|
|
443
627
|
return wrap;
|
|
444
628
|
}
|
|
445
|
-
// TODO(burdon): Remove listener?
|
|
446
|
-
// override destroy() {
|
|
447
|
-
// console.log('destroy', this._pos);
|
|
448
|
-
// }
|
|
449
629
|
ignoreEvent() {
|
|
450
630
|
return false;
|
|
451
631
|
}
|
|
452
632
|
};
|
|
453
|
-
var
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
633
|
+
var styles2 = EditorView5.baseTheme({
|
|
634
|
+
"& .cm-task-item": {
|
|
635
|
+
paddingLeft: "4px",
|
|
636
|
+
paddingRight: "8px"
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
var tasklist = () => {
|
|
640
|
+
const taskMatcher = new MatchDecorator2({
|
|
641
|
+
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
642
|
+
decoration: (match, view, pos) => {
|
|
643
|
+
const indent = Math.floor(match[1].length / 2);
|
|
644
|
+
const checked = match[2] === "x" || match[2] === "X";
|
|
645
|
+
return Decoration3.replace({
|
|
646
|
+
widget: new CheckboxWidget(pos, checked, indent, (checked2) => {
|
|
647
|
+
const idx = pos + match[0].indexOf("[") + 1;
|
|
648
|
+
view.dispatch({
|
|
649
|
+
changes: {
|
|
650
|
+
from: idx,
|
|
651
|
+
to: idx + 1,
|
|
652
|
+
insert: checked2 ? "x" : " "
|
|
653
|
+
},
|
|
654
|
+
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
655
|
+
selection: {
|
|
656
|
+
anchor: idx + 3
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
})
|
|
660
|
+
});
|
|
661
|
+
}
|
|
460
662
|
});
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
return builder.finish();
|
|
473
|
-
};
|
|
474
|
-
return [
|
|
475
|
-
listener2,
|
|
476
|
-
StateField3.define({
|
|
477
|
-
create: (state) => checkbox(state),
|
|
478
|
-
update: (_, tr) => checkbox(tr.state),
|
|
479
|
-
provide: (field) => EditorView4.decorations.from(field)
|
|
663
|
+
const tasks = ViewPlugin2.fromClass(class {
|
|
664
|
+
constructor(view) {
|
|
665
|
+
this.tasks = taskMatcher.createDeco(view);
|
|
666
|
+
}
|
|
667
|
+
update(update2) {
|
|
668
|
+
this.tasks = taskMatcher.updateDeco(update2, this.tasks);
|
|
669
|
+
}
|
|
670
|
+
}, {
|
|
671
|
+
decorations: (instance) => instance.tasks,
|
|
672
|
+
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
673
|
+
return view.plugin(plugin)?.tasks || Decoration3.none;
|
|
480
674
|
})
|
|
675
|
+
});
|
|
676
|
+
return [
|
|
677
|
+
tasks,
|
|
678
|
+
styles2
|
|
481
679
|
];
|
|
482
680
|
};
|
|
483
|
-
var styles = EditorView4.baseTheme({
|
|
484
|
-
"& .cm-task-item": {
|
|
485
|
-
padding: "0 4px"
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
var tasklist = () => [
|
|
489
|
-
statefield(),
|
|
490
|
-
styles
|
|
491
|
-
];
|
|
492
681
|
|
|
493
682
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/tooltip.tsx
|
|
494
683
|
import { hoverTooltip } from "@codemirror/view";
|
|
@@ -677,22 +866,33 @@ var defaultTheme = {
|
|
|
677
866
|
var textTheme = {
|
|
678
867
|
"& .cm-scroller": {
|
|
679
868
|
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
869
|
+
},
|
|
870
|
+
"& .cm-placeholder": {
|
|
871
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
var markdownTheme = {
|
|
875
|
+
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
876
|
+
"& .cm-placeholder": {
|
|
877
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
680
878
|
}
|
|
681
879
|
};
|
|
682
880
|
var codeTheme = {
|
|
683
881
|
"& .cm-scroller": {
|
|
684
882
|
fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
|
|
883
|
+
},
|
|
884
|
+
"& .cm-placeholder": {
|
|
885
|
+
fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
|
|
685
886
|
}
|
|
686
887
|
};
|
|
687
888
|
|
|
688
889
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
689
890
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
690
|
-
import { EditorView as
|
|
891
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
691
892
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
692
893
|
import { vim } from "@replit/codemirror-vim";
|
|
693
894
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
694
895
|
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
695
|
-
import { yCollab } from "y-codemirror.next";
|
|
696
896
|
import { generateName } from "@dxos/display-name";
|
|
697
897
|
import { useThemeContext } from "@dxos/react-ui";
|
|
698
898
|
import { getColorForValue, inputSurface, mx as mx2 } from "@dxos/react-ui-theme";
|
|
@@ -705,10 +905,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
705
905
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
706
906
|
tabBehavior: "limited"
|
|
707
907
|
});
|
|
708
|
-
const
|
|
908
|
+
const [root, setRoot] = useState(null);
|
|
909
|
+
const [state, setState] = useState();
|
|
910
|
+
const [view, setView] = useState();
|
|
911
|
+
useImperativeHandle(forwardedRef, () => ({
|
|
912
|
+
root,
|
|
913
|
+
state,
|
|
914
|
+
view
|
|
915
|
+
}), [
|
|
916
|
+
view,
|
|
917
|
+
state,
|
|
918
|
+
root
|
|
919
|
+
]);
|
|
920
|
+
const { awareness, peer } = model;
|
|
709
921
|
useEffect(() => {
|
|
710
|
-
if (
|
|
711
|
-
|
|
922
|
+
if (awareness && peer) {
|
|
923
|
+
awareness.setLocalStateField("user", {
|
|
712
924
|
name: peer.name ?? generateName(peer.id),
|
|
713
925
|
color: getColorForValue({
|
|
714
926
|
value: peer.id,
|
|
@@ -722,22 +934,10 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
722
934
|
});
|
|
723
935
|
}
|
|
724
936
|
}, [
|
|
725
|
-
|
|
937
|
+
awareness,
|
|
726
938
|
peer,
|
|
727
939
|
themeMode
|
|
728
940
|
]);
|
|
729
|
-
const [root, setRoot] = useState(null);
|
|
730
|
-
const [state, setState] = useState();
|
|
731
|
-
const [view, setView] = useState();
|
|
732
|
-
useImperativeHandle(forwardedRef, () => ({
|
|
733
|
-
root,
|
|
734
|
-
state,
|
|
735
|
-
view
|
|
736
|
-
}), [
|
|
737
|
-
view,
|
|
738
|
-
state,
|
|
739
|
-
root
|
|
740
|
-
]);
|
|
741
941
|
useEffect(() => {
|
|
742
942
|
if (!root) {
|
|
743
943
|
return;
|
|
@@ -748,18 +948,18 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
748
948
|
// TODO(burdon): Factor out VIM mode?
|
|
749
949
|
editorMode === "vim" && vim(),
|
|
750
950
|
// Theme.
|
|
751
|
-
|
|
752
|
-
|
|
951
|
+
EditorView6.baseTheme(defaultTheme),
|
|
952
|
+
EditorView6.theme(slots?.editor?.theme ?? {}),
|
|
753
953
|
// TODO(burdon): themeMode doesn't change in storybooks.
|
|
754
|
-
|
|
954
|
+
EditorView6.darkTheme.of(themeMode === "dark"),
|
|
755
955
|
// Storage and replication.
|
|
756
|
-
|
|
956
|
+
model.extension,
|
|
757
957
|
// Custom.
|
|
758
958
|
...extensions
|
|
759
959
|
].filter(Boolean)
|
|
760
960
|
});
|
|
761
961
|
view?.destroy();
|
|
762
|
-
setView(new
|
|
962
|
+
setView(new EditorView6({
|
|
763
963
|
state: state2,
|
|
764
964
|
parent: root
|
|
765
965
|
}));
|
|
@@ -771,7 +971,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
771
971
|
};
|
|
772
972
|
}, [
|
|
773
973
|
root,
|
|
774
|
-
model
|
|
974
|
+
model,
|
|
775
975
|
themeMode,
|
|
776
976
|
editorMode
|
|
777
977
|
]);
|
|
@@ -800,6 +1000,15 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
800
1000
|
onKeyUp: handleKeyUp
|
|
801
1001
|
});
|
|
802
1002
|
});
|
|
1003
|
+
var maybeDebug = () => {
|
|
1004
|
+
const items = localStorage.getItem("dxos.composer.demo");
|
|
1005
|
+
if (items) {
|
|
1006
|
+
return demo({
|
|
1007
|
+
items: items.split(",")
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
return [];
|
|
1011
|
+
};
|
|
803
1012
|
var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
804
1013
|
const { themeMode } = useThemeContext();
|
|
805
1014
|
const slots = defaultsDeep({}, _slots, defaultTextSlots);
|
|
@@ -810,6 +1019,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, .
|
|
|
810
1019
|
themeMode,
|
|
811
1020
|
placeholder: slots?.editor?.placeholder
|
|
812
1021
|
}),
|
|
1022
|
+
maybeDebug(),
|
|
813
1023
|
...extensions
|
|
814
1024
|
],
|
|
815
1025
|
slots,
|
|
@@ -818,7 +1028,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, .
|
|
|
818
1028
|
});
|
|
819
1029
|
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
820
1030
|
const { themeMode } = useThemeContext();
|
|
821
|
-
const slots = defaultsDeep({}, _slots,
|
|
1031
|
+
const slots = defaultsDeep({}, _slots, defaultMarkdownSlots);
|
|
822
1032
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
823
1033
|
ref: forwardedRef,
|
|
824
1034
|
extensions: [
|
|
@@ -826,6 +1036,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
|
|
|
826
1036
|
themeMode,
|
|
827
1037
|
placeholder: slots?.editor?.placeholder
|
|
828
1038
|
}),
|
|
1039
|
+
maybeDebug(),
|
|
829
1040
|
...extensions
|
|
830
1041
|
],
|
|
831
1042
|
slots,
|
|
@@ -843,26 +1054,31 @@ var defaultTextSlots = {
|
|
|
843
1054
|
theme: textTheme
|
|
844
1055
|
}
|
|
845
1056
|
};
|
|
1057
|
+
var defaultMarkdownSlots = {
|
|
1058
|
+
...defaultSlots,
|
|
1059
|
+
editor: {
|
|
1060
|
+
theme: markdownTheme
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
846
1063
|
|
|
847
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
1064
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1065
|
+
import get3 from "lodash.get";
|
|
848
1066
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
849
|
-
import { yCollab
|
|
850
|
-
import {
|
|
851
|
-
import {
|
|
852
|
-
import { getColorForValue as getColorForValue2 } from "@dxos/react-ui-theme";
|
|
853
|
-
import { YText } from "@dxos/text-model";
|
|
1067
|
+
import { yCollab } from "y-codemirror.next";
|
|
1068
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1069
|
+
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
854
1070
|
|
|
855
|
-
// packages/ui/react-ui-editor/src/
|
|
856
|
-
import { Annotation, Facet, StateEffect, StateField as
|
|
857
|
-
import { ViewPlugin } from "@codemirror/view";
|
|
1071
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1072
|
+
import { Annotation, Facet, StateEffect, StateField as StateField3 } from "@codemirror/state";
|
|
1073
|
+
import { ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
858
1074
|
import * as automerge2 from "@dxos/automerge/automerge";
|
|
859
1075
|
|
|
860
|
-
// packages/ui/react-ui-editor/src/
|
|
1076
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
861
1077
|
import { next as automerge } from "@dxos/automerge/automerge";
|
|
862
1078
|
|
|
863
|
-
// packages/ui/react-ui-editor/src/automerge/automerge-
|
|
1079
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
|
|
864
1080
|
import { ChangeSet } from "@codemirror/state";
|
|
865
|
-
var
|
|
1081
|
+
var automergeToCodemirror = (view, selection, target, patches) => {
|
|
866
1082
|
for (const patch of patches) {
|
|
867
1083
|
const changeSpec = handlePatch(patch, target, view.state);
|
|
868
1084
|
if (changeSpec != null) {
|
|
@@ -967,9 +1183,9 @@ var charPath = (textPath, candidatePath) => {
|
|
|
967
1183
|
return null;
|
|
968
1184
|
};
|
|
969
1185
|
|
|
970
|
-
// packages/ui/react-ui-editor/src/automerge/automerge
|
|
1186
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
|
|
971
1187
|
import { next as am } from "@dxos/automerge/automerge";
|
|
972
|
-
var
|
|
1188
|
+
var codemirrorToAutomerge = (field, handle, transactions, state) => {
|
|
973
1189
|
const { lastHeads, path } = state.field(field);
|
|
974
1190
|
let hasChanges = false;
|
|
975
1191
|
for (const tr of transactions) {
|
|
@@ -990,7 +1206,7 @@ var codeMirrorToAm_default = (field, handle, transactions, state) => {
|
|
|
990
1206
|
return newHeads ?? void 0;
|
|
991
1207
|
};
|
|
992
1208
|
|
|
993
|
-
// packages/ui/react-ui-editor/src/
|
|
1209
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
994
1210
|
var PatchSemaphore = class {
|
|
995
1211
|
constructor(field) {
|
|
996
1212
|
this._inReconcile = false;
|
|
@@ -1013,12 +1229,12 @@ var PatchSemaphore = class {
|
|
|
1013
1229
|
annotations: reconcileAnnotationType.of(true)
|
|
1014
1230
|
});
|
|
1015
1231
|
}
|
|
1016
|
-
let newHeads =
|
|
1232
|
+
let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
|
|
1017
1233
|
if (newHeads === null || newHeads === void 0) {
|
|
1018
1234
|
newHeads = automerge.getHeads(handle.docSync());
|
|
1019
1235
|
}
|
|
1020
1236
|
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
1021
|
-
|
|
1237
|
+
automergeToCodemirror(view, selection, path, diff);
|
|
1022
1238
|
view.dispatch({
|
|
1023
1239
|
effects: updateHeads(newHeads),
|
|
1024
1240
|
annotations: reconcileAnnotationType.of({})
|
|
@@ -1031,7 +1247,7 @@ var PatchSemaphore = class {
|
|
|
1031
1247
|
}
|
|
1032
1248
|
};
|
|
1033
1249
|
|
|
1034
|
-
// packages/ui/react-ui-editor/src/
|
|
1250
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1035
1251
|
var effectType = StateEffect.define({});
|
|
1036
1252
|
var updateHeads = (newHeads) => effectType.of({
|
|
1037
1253
|
newHeads
|
|
@@ -1042,7 +1258,7 @@ var semaphoreFacet = Facet.define({
|
|
|
1042
1258
|
combine: (values) => values.at(-1)
|
|
1043
1259
|
});
|
|
1044
1260
|
var automergePlugin = (handle, path) => {
|
|
1045
|
-
const stateField =
|
|
1261
|
+
const stateField = StateField3.define({
|
|
1046
1262
|
create: () => ({
|
|
1047
1263
|
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
1048
1264
|
unreconciledTransactions: [],
|
|
@@ -1072,7 +1288,7 @@ var automergePlugin = (handle, path) => {
|
|
|
1072
1288
|
}
|
|
1073
1289
|
});
|
|
1074
1290
|
const semaphore = new PatchSemaphore(stateField);
|
|
1075
|
-
const viewPlugin =
|
|
1291
|
+
const viewPlugin = ViewPlugin3.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
1076
1292
|
constructor(view) {
|
|
1077
1293
|
this._handleChange = () => {
|
|
1078
1294
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
@@ -1102,45 +1318,6 @@ var automergePlugin = (handle, path) => {
|
|
|
1102
1318
|
var reconcileAnnotationType = Annotation.define();
|
|
1103
1319
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
1104
1320
|
|
|
1105
|
-
// packages/ui/react-ui-editor/src/hooks/useCollaboration.ts
|
|
1106
|
-
var useCollaboration = (model, themeMode) => {
|
|
1107
|
-
const { content, provider, peer } = model;
|
|
1108
|
-
const [extension] = useState2(() => {
|
|
1109
|
-
if (content instanceof YText) {
|
|
1110
|
-
return yCollab2(content, provider?.awareness);
|
|
1111
|
-
} else if (isDocAccessor(content)) {
|
|
1112
|
-
return automergePlugin(content.handle, content.path);
|
|
1113
|
-
} else {
|
|
1114
|
-
return void 0;
|
|
1115
|
-
}
|
|
1116
|
-
});
|
|
1117
|
-
useEffect2(() => {
|
|
1118
|
-
if (provider && peer) {
|
|
1119
|
-
provider.awareness.setLocalStateField("user", {
|
|
1120
|
-
name: peer.name ?? generateName2(peer.id),
|
|
1121
|
-
color: getColorForValue2({
|
|
1122
|
-
value: peer.id,
|
|
1123
|
-
type: "color"
|
|
1124
|
-
}),
|
|
1125
|
-
colorLight: getColorForValue2({
|
|
1126
|
-
value: peer.id,
|
|
1127
|
-
themeMode,
|
|
1128
|
-
type: "highlight"
|
|
1129
|
-
})
|
|
1130
|
-
});
|
|
1131
|
-
}
|
|
1132
|
-
}, [
|
|
1133
|
-
provider,
|
|
1134
|
-
peer,
|
|
1135
|
-
themeMode
|
|
1136
|
-
]);
|
|
1137
|
-
return extension;
|
|
1138
|
-
};
|
|
1139
|
-
|
|
1140
|
-
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1141
|
-
import { useMemo } from "react";
|
|
1142
|
-
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
1143
|
-
|
|
1144
1321
|
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
1145
1322
|
import * as random from "lib0/random";
|
|
1146
1323
|
var cursorColors = [
|
|
@@ -1185,7 +1362,7 @@ import * as encoding from "lib0/encoding";
|
|
|
1185
1362
|
import { Observable } from "lib0/observable";
|
|
1186
1363
|
import * as awarenessProtocol from "y-protocols/awareness";
|
|
1187
1364
|
import { log } from "@dxos/log";
|
|
1188
|
-
var
|
|
1365
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
1189
1366
|
var messageAwareness = 1;
|
|
1190
1367
|
var messageQueryAwareness = 3;
|
|
1191
1368
|
var SpaceAwarenessProvider = class extends Observable {
|
|
@@ -1222,7 +1399,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1222
1399
|
removed,
|
|
1223
1400
|
origin
|
|
1224
1401
|
}, {
|
|
1225
|
-
F:
|
|
1402
|
+
F: __dxlog_file2,
|
|
1226
1403
|
L: 67,
|
|
1227
1404
|
S: this,
|
|
1228
1405
|
C: (f, a) => f(...a)
|
|
@@ -1235,7 +1412,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1235
1412
|
}
|
|
1236
1413
|
_handleSpaceMessage({ payload }) {
|
|
1237
1414
|
log("space message", payload, {
|
|
1238
|
-
F:
|
|
1415
|
+
F: __dxlog_file2,
|
|
1239
1416
|
L: 79,
|
|
1240
1417
|
S: this,
|
|
1241
1418
|
C: (f, a) => f(...a)
|
|
@@ -1280,57 +1457,74 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1280
1457
|
};
|
|
1281
1458
|
|
|
1282
1459
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1460
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
1283
1461
|
var useTextModel = ({ identity, space, text }) => {
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1462
|
+
const [model, setModel] = useState2(() => createModel({
|
|
1463
|
+
identity,
|
|
1464
|
+
space,
|
|
1465
|
+
text
|
|
1466
|
+
}));
|
|
1467
|
+
useEffect2(() => {
|
|
1468
|
+
setModel(createModel({
|
|
1469
|
+
identity,
|
|
1292
1470
|
space,
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
});
|
|
1471
|
+
text
|
|
1472
|
+
}));
|
|
1296
1473
|
}, [
|
|
1297
1474
|
identity,
|
|
1298
1475
|
space,
|
|
1299
|
-
text,
|
|
1300
|
-
text?.doc
|
|
1301
|
-
]);
|
|
1302
|
-
const content = useMemo(() => {
|
|
1303
|
-
if (isActualAutomergeObject(text)) {
|
|
1304
|
-
const obj = text;
|
|
1305
|
-
return getRawDoc(obj, [
|
|
1306
|
-
obj.field
|
|
1307
|
-
]);
|
|
1308
|
-
} else {
|
|
1309
|
-
return text?.content;
|
|
1310
|
-
}
|
|
1311
|
-
}, [
|
|
1312
1476
|
text
|
|
1313
1477
|
]);
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1478
|
+
return model;
|
|
1479
|
+
};
|
|
1480
|
+
var createModel = (options) => {
|
|
1481
|
+
const { text } = options;
|
|
1317
1482
|
if (isActualAutomergeObject(text)) {
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
peer: identity ? {
|
|
1325
|
-
id: identity.identityKey.toHex(),
|
|
1326
|
-
name: identity.profile?.displayName
|
|
1327
|
-
} : void 0
|
|
1328
|
-
};
|
|
1483
|
+
return createAutomergeModel(options);
|
|
1484
|
+
} else {
|
|
1485
|
+
if (!text?.doc) {
|
|
1486
|
+
return void 0;
|
|
1487
|
+
}
|
|
1488
|
+
return createYjsModel(options);
|
|
1329
1489
|
}
|
|
1490
|
+
};
|
|
1491
|
+
var createYjsModel = ({ identity, space, text }) => {
|
|
1492
|
+
invariant2(text?.doc && text?.content, void 0, {
|
|
1493
|
+
F: __dxlog_file3,
|
|
1494
|
+
L: 74,
|
|
1495
|
+
S: void 0,
|
|
1496
|
+
A: [
|
|
1497
|
+
"text?.doc && text?.content",
|
|
1498
|
+
""
|
|
1499
|
+
]
|
|
1500
|
+
});
|
|
1501
|
+
const provider = space ? new SpaceAwarenessProvider({
|
|
1502
|
+
space,
|
|
1503
|
+
doc: text.doc,
|
|
1504
|
+
channel: `yjs.awareness.${text.id}`
|
|
1505
|
+
}) : void 0;
|
|
1330
1506
|
return {
|
|
1331
1507
|
id: text.doc.guid,
|
|
1332
1508
|
content: text.content,
|
|
1333
1509
|
text: () => text.content.toString(),
|
|
1510
|
+
extension: yCollab(text.content, provider?.awareness),
|
|
1511
|
+
awareness: provider?.awareness,
|
|
1512
|
+
peer: identity ? {
|
|
1513
|
+
id: identity.identityKey.toHex(),
|
|
1514
|
+
name: identity.profile?.displayName
|
|
1515
|
+
} : void 0
|
|
1516
|
+
};
|
|
1517
|
+
};
|
|
1518
|
+
var createAutomergeModel = ({ identity, text }) => {
|
|
1519
|
+
const obj = text;
|
|
1520
|
+
const doc = getRawDoc(obj, [
|
|
1521
|
+
obj.field
|
|
1522
|
+
]);
|
|
1523
|
+
return {
|
|
1524
|
+
id: obj.id,
|
|
1525
|
+
content: doc,
|
|
1526
|
+
text: () => get3(doc.handle.docSync(), doc.path),
|
|
1527
|
+
extension: automergePlugin(doc.handle, doc.path),
|
|
1334
1528
|
peer: identity ? {
|
|
1335
1529
|
id: identity.identityKey.toHex(),
|
|
1336
1530
|
name: identity.profile?.displayName
|
|
@@ -1345,28 +1539,29 @@ export {
|
|
|
1345
1539
|
SpaceAwarenessProvider,
|
|
1346
1540
|
TextEditor,
|
|
1347
1541
|
TextKind,
|
|
1348
|
-
|
|
1542
|
+
YText,
|
|
1349
1543
|
YXmlFragment,
|
|
1350
1544
|
autocomplete,
|
|
1351
1545
|
basicBundle,
|
|
1352
1546
|
codeTheme,
|
|
1547
|
+
comments,
|
|
1353
1548
|
cursorColor,
|
|
1549
|
+
defaultMarkdownSlots,
|
|
1354
1550
|
defaultSlots,
|
|
1355
1551
|
defaultTextSlots,
|
|
1356
1552
|
defaultTheme,
|
|
1553
|
+
demo,
|
|
1357
1554
|
link,
|
|
1358
1555
|
listener,
|
|
1359
1556
|
markdownBundle,
|
|
1360
1557
|
markdownHighlightStyle,
|
|
1361
1558
|
markdownTags,
|
|
1362
1559
|
markdownTagsExtension,
|
|
1363
|
-
|
|
1364
|
-
styles,
|
|
1560
|
+
markdownTheme,
|
|
1365
1561
|
tags2 as tags,
|
|
1366
1562
|
tasklist,
|
|
1367
1563
|
textTheme,
|
|
1368
1564
|
tooltip,
|
|
1369
|
-
useCollaboration,
|
|
1370
1565
|
useTextModel
|
|
1371
1566
|
};
|
|
1372
1567
|
//# sourceMappingURL=index.mjs.map
|