@dxos/react-ui-editor 0.3.10-main.5515dfe → 0.3.10-main.560f82b
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 +1049 -285
- 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 +22 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +3 -1
- 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/basic.d.ts +2 -1
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts +25 -0
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +1 -0
- 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 +11 -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/image.d.ts +4 -0
- package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts +6 -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 +2 -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 +6 -2
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/mention.d.ts +6 -0
- package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/table.d.ts +8 -0
- package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +2 -4
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts +8 -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 +16 -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/{components/TextEditor → hooks/yjs}/yjs.stories.d.ts +1 -1
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -0
- package/dist/types/src/styles/markdown.d.ts +3 -2
- package/dist/types/src/styles/markdown.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 +137 -31
- package/src/components/TextEditor/TextEditor.tsx +52 -25
- package/src/components/TextEditor/extensions/autocomplete.ts +9 -22
- package/src/components/TextEditor/extensions/basic.ts +2 -1
- package/src/components/TextEditor/extensions/blast.ts +375 -0
- package/src/components/TextEditor/extensions/comments.ts +190 -0
- package/src/components/TextEditor/extensions/demo.ts +69 -0
- package/src/components/TextEditor/extensions/experimental.tsx +1 -0
- package/src/components/TextEditor/extensions/image.ts +68 -0
- package/src/components/TextEditor/extensions/index.ts +6 -0
- package/src/components/TextEditor/extensions/link.ts +25 -25
- package/src/components/TextEditor/extensions/listener.ts +4 -3
- package/src/components/TextEditor/extensions/markdown/bundle.ts +18 -18
- package/src/components/TextEditor/extensions/markdown/highlight.ts +118 -103
- package/src/components/TextEditor/extensions/mention.ts +31 -0
- package/src/components/TextEditor/extensions/table.ts +123 -0
- package/src/components/TextEditor/extensions/tasklist.ts +89 -81
- package/src/components/TextEditor/themes/default.ts +69 -2
- package/src/{automerge/automerge-plugin → hooks/automerge}/PatchSemaphore.ts +12 -9
- package/src/{automerge → hooks/automerge}/automerge.stories.tsx +5 -3
- 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/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +1 -1
- package/src/styles/markdown.ts +14 -8
- 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 +0 -9
- package/dist/types/src/automerge/automerge.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.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/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
|
|
@@ -24,13 +24,13 @@ var autocomplete = ({ getOptions }) => {
|
|
|
24
24
|
// TODO(burdon): Optional decoration via addToOptions
|
|
25
25
|
override: [
|
|
26
26
|
(context) => {
|
|
27
|
-
const
|
|
28
|
-
if (!
|
|
27
|
+
const match = context.matchBefore(/\w*/);
|
|
28
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
31
31
|
return {
|
|
32
|
-
from:
|
|
33
|
-
options:
|
|
32
|
+
from: match.from,
|
|
33
|
+
options: onSearch(match.text.toLowerCase())
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
]
|
|
@@ -43,7 +43,7 @@ import { closeBrackets } from "@codemirror/autocomplete";
|
|
|
43
43
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
44
44
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
45
45
|
import { EditorView, placeholder } from "@codemirror/view";
|
|
46
|
-
var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
|
|
46
|
+
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
47
47
|
// TODO(burdon): Compare with minimalSetup.
|
|
48
48
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
49
49
|
bracketMatching(),
|
|
@@ -54,11 +54,571 @@ 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/
|
|
57
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts
|
|
58
|
+
import { StateField } from "@codemirror/state";
|
|
59
|
+
import { EditorView as EditorView2, keymap as keymap2 } from "@codemirror/view";
|
|
60
|
+
import defaultsDeep from "lodash.defaultsdeep";
|
|
61
|
+
import { invariant } from "@dxos/invariant";
|
|
62
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts";
|
|
63
|
+
var defaultOptions = {
|
|
64
|
+
maxParticles: 200,
|
|
65
|
+
particleGravity: 0.08,
|
|
66
|
+
particleAlphaFadeout: 0.996,
|
|
67
|
+
particleSize: {
|
|
68
|
+
min: 2,
|
|
69
|
+
max: 8
|
|
70
|
+
},
|
|
71
|
+
particleNumRange: {
|
|
72
|
+
min: 5,
|
|
73
|
+
max: 10
|
|
74
|
+
},
|
|
75
|
+
particleVelocityRange: {
|
|
76
|
+
x: [
|
|
77
|
+
-1,
|
|
78
|
+
1
|
|
79
|
+
],
|
|
80
|
+
y: [
|
|
81
|
+
-3.5,
|
|
82
|
+
-1.5
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
particleShrinkRate: 0.95,
|
|
86
|
+
shakeIntensity: 5
|
|
87
|
+
};
|
|
88
|
+
var blast = (options) => {
|
|
89
|
+
let blaster;
|
|
90
|
+
let last = 0;
|
|
91
|
+
const getPoint = (view, pos) => {
|
|
92
|
+
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
93
|
+
const element = document.elementFromPoint(x, y);
|
|
94
|
+
const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
|
|
95
|
+
const point = {
|
|
96
|
+
x: x - left,
|
|
97
|
+
y: y - top
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
element,
|
|
101
|
+
point
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
return [
|
|
105
|
+
// Cursor moved.
|
|
106
|
+
EditorView2.updateListener.of((update4) => {
|
|
107
|
+
if (blaster?.node !== update4.view.scrollDOM) {
|
|
108
|
+
if (blaster) {
|
|
109
|
+
blaster.destroy();
|
|
110
|
+
}
|
|
111
|
+
blaster = new Blaster(update4.view.scrollDOM, defaultsDeep({}, options, defaultOptions));
|
|
112
|
+
blaster.initialize();
|
|
113
|
+
blaster.start();
|
|
114
|
+
} else {
|
|
115
|
+
blaster.resize();
|
|
116
|
+
}
|
|
117
|
+
const current = update4.view.state.selection.main.head;
|
|
118
|
+
if (current !== last) {
|
|
119
|
+
last = current;
|
|
120
|
+
const { element, point } = getPoint(update4.view, current);
|
|
121
|
+
if (element && point) {
|
|
122
|
+
blaster.spawn({
|
|
123
|
+
element,
|
|
124
|
+
point
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}),
|
|
129
|
+
// Document changed.
|
|
130
|
+
StateField.define({
|
|
131
|
+
create: () => null,
|
|
132
|
+
update: (_value, transaction) => {
|
|
133
|
+
if (blaster && transaction.docChanged) {
|
|
134
|
+
const view = EditorView2.findFromDOM(blaster.node);
|
|
135
|
+
const { element, point } = getPoint(view, transaction.selection.main.head);
|
|
136
|
+
if (element && point) {
|
|
137
|
+
blaster.spawn({
|
|
138
|
+
element,
|
|
139
|
+
point
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}),
|
|
146
|
+
keymap2.of([
|
|
147
|
+
{
|
|
148
|
+
any: (view, event) => {
|
|
149
|
+
if (blaster && event.key === "Enter" && event.shiftKey) {
|
|
150
|
+
blaster.shake({
|
|
151
|
+
time: 0.4
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
])
|
|
158
|
+
];
|
|
159
|
+
};
|
|
160
|
+
var Blaster = class {
|
|
161
|
+
constructor(_node, _options) {
|
|
162
|
+
this._node = _node;
|
|
163
|
+
this._options = _options;
|
|
164
|
+
this._running = false;
|
|
165
|
+
this._shakeTime = 0;
|
|
166
|
+
this._shakeTimeMax = 0;
|
|
167
|
+
this._particles = [];
|
|
168
|
+
this._particlePointer = 0;
|
|
169
|
+
this._lastPoint = {
|
|
170
|
+
x: 0,
|
|
171
|
+
y: 0
|
|
172
|
+
};
|
|
173
|
+
this.shake = throttle(({ time }) => {
|
|
174
|
+
this._shakeTime = this._shakeTimeMax;
|
|
175
|
+
this._shakeTimeMax = time;
|
|
176
|
+
}, 100);
|
|
177
|
+
this.spawn = throttle(({ element, point }) => {
|
|
178
|
+
const color = getRGBComponents(element, this._options.color);
|
|
179
|
+
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
180
|
+
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
181
|
+
this._lastPoint = point;
|
|
182
|
+
for (let i = numParticles; i--; i > 0) {
|
|
183
|
+
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
184
|
+
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
185
|
+
}
|
|
186
|
+
}, 100);
|
|
187
|
+
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
188
|
+
}
|
|
189
|
+
get node() {
|
|
190
|
+
return this._node;
|
|
191
|
+
}
|
|
192
|
+
initialize() {
|
|
193
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
194
|
+
F: __dxlog_file,
|
|
195
|
+
L: 140,
|
|
196
|
+
S: this,
|
|
197
|
+
A: [
|
|
198
|
+
"!this._canvas && !this._ctx",
|
|
199
|
+
""
|
|
200
|
+
]
|
|
201
|
+
});
|
|
202
|
+
this._canvas = document.createElement("canvas");
|
|
203
|
+
this._canvas.id = "code-blast-canvas";
|
|
204
|
+
this._canvas.style.position = "absolute";
|
|
205
|
+
this._canvas.style.zIndex = "0";
|
|
206
|
+
this._canvas.style.pointerEvents = "none";
|
|
207
|
+
this._ctx = this._canvas.getContext("2d");
|
|
208
|
+
const parent = this._node.parentElement?.parentElement;
|
|
209
|
+
parent?.appendChild(this._canvas);
|
|
210
|
+
this.resize();
|
|
211
|
+
}
|
|
212
|
+
destroy() {
|
|
213
|
+
this.stop();
|
|
214
|
+
if (this._canvas) {
|
|
215
|
+
this._canvas.remove();
|
|
216
|
+
this._canvas = void 0;
|
|
217
|
+
this._ctx = void 0;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
resize() {
|
|
221
|
+
if (this._node.parentElement && this._canvas) {
|
|
222
|
+
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
223
|
+
this._canvas.style.top = `${y}px`;
|
|
224
|
+
this._canvas.style.left = `${x}px`;
|
|
225
|
+
this._canvas.width = width;
|
|
226
|
+
this._canvas.height = height;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
start() {
|
|
230
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
231
|
+
F: __dxlog_file,
|
|
232
|
+
L: 179,
|
|
233
|
+
S: this,
|
|
234
|
+
A: [
|
|
235
|
+
"this._canvas && this._ctx",
|
|
236
|
+
""
|
|
237
|
+
]
|
|
238
|
+
});
|
|
239
|
+
this._running = true;
|
|
240
|
+
this.loop();
|
|
241
|
+
}
|
|
242
|
+
stop() {
|
|
243
|
+
this._running = false;
|
|
244
|
+
this._node.style.transform = "translate(0px, 0px)";
|
|
245
|
+
}
|
|
246
|
+
loop() {
|
|
247
|
+
if (!this._running || !this._canvas || !this._ctx) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this._ctx.clearRect(0, 0, this._canvas.width ?? 0, this._canvas.height ?? 0);
|
|
251
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
252
|
+
this._lastTime ??= now;
|
|
253
|
+
const dt = (now - this._lastTime) / 1e3;
|
|
254
|
+
this._lastTime = now;
|
|
255
|
+
if (this._shakeTime > 0) {
|
|
256
|
+
this._shakeTime -= dt;
|
|
257
|
+
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
258
|
+
const shakeX = random(-magnitude, magnitude);
|
|
259
|
+
const shakeY = random(-magnitude, magnitude);
|
|
260
|
+
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
261
|
+
}
|
|
262
|
+
this.drawParticles();
|
|
263
|
+
requestAnimationFrame(this.loop.bind(this));
|
|
264
|
+
}
|
|
265
|
+
drawParticles() {
|
|
266
|
+
for (let i = this._particles.length; i--; i > 0) {
|
|
267
|
+
const particle = this._particles[i];
|
|
268
|
+
if (!particle) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (particle.alpha < 0.01 || particle.size <= 0.5) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
this._effect.update(this._ctx, particle);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var Effect = class {
|
|
279
|
+
constructor(_options) {
|
|
280
|
+
this._options = _options;
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
var Effect1 = class extends Effect {
|
|
284
|
+
create(x, y, color) {
|
|
285
|
+
return {
|
|
286
|
+
x,
|
|
287
|
+
y: y + 10,
|
|
288
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
289
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
290
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
291
|
+
color,
|
|
292
|
+
alpha: 1
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
update(ctx, particle) {
|
|
296
|
+
particle.vy += this._options.particleGravity;
|
|
297
|
+
particle.x += particle.vx;
|
|
298
|
+
particle.y += particle.vy;
|
|
299
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
300
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
301
|
+
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
var Effect2 = class extends Effect {
|
|
305
|
+
create(x, y, color) {
|
|
306
|
+
return {
|
|
307
|
+
x,
|
|
308
|
+
y: y + 10,
|
|
309
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
310
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
311
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
312
|
+
color,
|
|
313
|
+
alpha: 1,
|
|
314
|
+
theta: random(0, 360) * Math.PI / 180,
|
|
315
|
+
drag: 0.92,
|
|
316
|
+
wander: 0.15
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
update(ctx, particle) {
|
|
320
|
+
particle.vy += this._options.particleGravity;
|
|
321
|
+
particle.x += particle.vx;
|
|
322
|
+
particle.y += particle.vy;
|
|
323
|
+
particle.vx *= particle.drag;
|
|
324
|
+
particle.vy *= particle.drag;
|
|
325
|
+
particle.theta += random(-0.5, 0.5);
|
|
326
|
+
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
327
|
+
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
328
|
+
particle.size *= this._options.particleShrinkRate;
|
|
329
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
330
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
331
|
+
ctx.beginPath();
|
|
332
|
+
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
333
|
+
ctx.fill();
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
function throttle(callback, limit) {
|
|
337
|
+
let wait = false;
|
|
338
|
+
return function(...args) {
|
|
339
|
+
if (!wait) {
|
|
340
|
+
callback.apply(this, args);
|
|
341
|
+
wait = true;
|
|
342
|
+
setTimeout(() => {
|
|
343
|
+
wait = false;
|
|
344
|
+
}, limit);
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
var getRGBComponents = (node, color) => {
|
|
349
|
+
if (typeof color === "function") {
|
|
350
|
+
return color();
|
|
351
|
+
}
|
|
352
|
+
const bgColor = getComputedStyle(node).color;
|
|
353
|
+
if (bgColor) {
|
|
354
|
+
const x = bgColor.match(/(\d+), (\d+), (\d+)/)?.slice(1);
|
|
355
|
+
if (x) {
|
|
356
|
+
return x;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return [
|
|
360
|
+
50,
|
|
361
|
+
50,
|
|
362
|
+
50
|
|
363
|
+
];
|
|
364
|
+
};
|
|
365
|
+
var random = (min, max) => {
|
|
366
|
+
if (!max) {
|
|
367
|
+
max = min;
|
|
368
|
+
min = 0;
|
|
369
|
+
}
|
|
370
|
+
return min + ~~(Math.random() * (max - min + 1));
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
|
|
374
|
+
import { keymap as keymap3 } from "@codemirror/view";
|
|
375
|
+
var defaultItems = [
|
|
376
|
+
"hello world!",
|
|
377
|
+
"this is a test.",
|
|
378
|
+
"this is [DXOS](https://dxos.org)"
|
|
379
|
+
];
|
|
380
|
+
var demo = ({ delay = 75, items = defaultItems } = {}) => {
|
|
381
|
+
let t;
|
|
382
|
+
let idx = 0;
|
|
383
|
+
return [
|
|
384
|
+
keymap3.of([
|
|
385
|
+
{
|
|
386
|
+
// Reset.
|
|
387
|
+
key: "alt-meta-'",
|
|
388
|
+
run: (view) => {
|
|
389
|
+
clearTimeout(t);
|
|
390
|
+
idx = 0;
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
// Next prompt.
|
|
396
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
|
397
|
+
key: "shift-meta-'",
|
|
398
|
+
run: (view) => {
|
|
399
|
+
clearTimeout(t);
|
|
400
|
+
const text = items[idx++];
|
|
401
|
+
if (idx === items?.length) {
|
|
402
|
+
idx = 0;
|
|
403
|
+
}
|
|
404
|
+
let i = 0;
|
|
405
|
+
const insert = (d = 0) => {
|
|
406
|
+
t = setTimeout(() => {
|
|
407
|
+
const pos = view.state.selection.main.head;
|
|
408
|
+
view.dispatch({
|
|
409
|
+
changes: {
|
|
410
|
+
from: pos,
|
|
411
|
+
insert: text[i++]
|
|
412
|
+
},
|
|
413
|
+
selection: {
|
|
414
|
+
anchor: pos + 1
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
if (i < text.length) {
|
|
418
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
419
|
+
}
|
|
420
|
+
}, d);
|
|
421
|
+
};
|
|
422
|
+
insert();
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
])
|
|
427
|
+
];
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
|
|
431
|
+
import { keymap as keymap4, Decoration, EditorView as EditorView3, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
|
|
432
|
+
import { debounce } from "@dxos/async";
|
|
433
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
434
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
|
|
435
|
+
var BookmarkWidget = class extends WidgetType {
|
|
436
|
+
constructor(_pos, _id) {
|
|
437
|
+
super();
|
|
438
|
+
this._pos = _pos;
|
|
439
|
+
this._id = _id;
|
|
440
|
+
invariant2(this._id, void 0, {
|
|
441
|
+
F: __dxlog_file2,
|
|
442
|
+
L: 41,
|
|
443
|
+
S: this,
|
|
444
|
+
A: [
|
|
445
|
+
"this._id",
|
|
446
|
+
""
|
|
447
|
+
]
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
eq(other) {
|
|
451
|
+
return this._id === other._id;
|
|
452
|
+
}
|
|
453
|
+
toDOM() {
|
|
454
|
+
const span = document.createElement("span");
|
|
455
|
+
span.className = "cm-bookmark";
|
|
456
|
+
span.textContent = "\u{1F4AC}";
|
|
457
|
+
return span;
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
var styles = EditorView3.baseTheme({
|
|
461
|
+
"& .cm-bookmark": {
|
|
462
|
+
cursor: "pointer",
|
|
463
|
+
margin: "4px",
|
|
464
|
+
padding: "4px",
|
|
465
|
+
backgroundColor: "yellow"
|
|
466
|
+
},
|
|
467
|
+
"& .cm-bookmark-selected": {
|
|
468
|
+
backgroundColor: "orange"
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
var comments = (options = {}) => {
|
|
472
|
+
let active;
|
|
473
|
+
const bookmarkMatcher = new MatchDecorator({
|
|
474
|
+
regexp: /\[\^(\w+)\]/g,
|
|
475
|
+
decoration: (match, view, pos) => {
|
|
476
|
+
const id = match[1];
|
|
477
|
+
return Decoration.replace({
|
|
478
|
+
id,
|
|
479
|
+
widget: new BookmarkWidget(pos, id)
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
const bookmarks = ViewPlugin.fromClass(class {
|
|
484
|
+
constructor(view) {
|
|
485
|
+
this.bookmarks = bookmarkMatcher.createDeco(view);
|
|
486
|
+
}
|
|
487
|
+
update(update4) {
|
|
488
|
+
this.bookmarks = bookmarkMatcher.updateDeco(update4, this.bookmarks);
|
|
489
|
+
}
|
|
490
|
+
}, {
|
|
491
|
+
decorations: (instance) => instance.bookmarks,
|
|
492
|
+
provide: (plugin) => EditorView3.atomicRanges.of((view) => {
|
|
493
|
+
return view.plugin(plugin)?.bookmarks || Decoration.none;
|
|
494
|
+
})
|
|
495
|
+
});
|
|
496
|
+
const doUpdate = debounce((data) => {
|
|
497
|
+
options.onUpdate?.(data);
|
|
498
|
+
}, 200);
|
|
499
|
+
return [
|
|
500
|
+
keymap4.of([
|
|
501
|
+
{
|
|
502
|
+
key: options?.key ?? "shift-meta-c",
|
|
503
|
+
run: (view) => {
|
|
504
|
+
const id = options.onCreate?.();
|
|
505
|
+
if (id) {
|
|
506
|
+
const pos = view.state.selection.main.head;
|
|
507
|
+
const tag = `[^${id}]`;
|
|
508
|
+
view.dispatch({
|
|
509
|
+
changes: {
|
|
510
|
+
from: pos,
|
|
511
|
+
insert: tag
|
|
512
|
+
},
|
|
513
|
+
selection: {
|
|
514
|
+
anchor: pos + tag.length
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
]),
|
|
523
|
+
bookmarks,
|
|
524
|
+
// Monitor cursor movement.
|
|
525
|
+
EditorView3.updateListener.of((update4) => {
|
|
526
|
+
active = void 0;
|
|
527
|
+
if (!options.onUpdate) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const view = update4.view;
|
|
531
|
+
const pos = view.state.selection.main.head;
|
|
532
|
+
const decorations = [];
|
|
533
|
+
const rangeSet = view.plugin(bookmarks)?.bookmarks;
|
|
534
|
+
let closest = Infinity;
|
|
535
|
+
const { from, to } = view.visibleRanges?.[0] ?? {
|
|
536
|
+
from: 0,
|
|
537
|
+
to: view.state.doc.length
|
|
538
|
+
};
|
|
539
|
+
rangeSet?.between(from, to, (from2, to2, value) => {
|
|
540
|
+
decorations.push({
|
|
541
|
+
from: from2,
|
|
542
|
+
to: to2,
|
|
543
|
+
value
|
|
544
|
+
});
|
|
545
|
+
const d = Math.min(Math.abs(pos - from2), Math.abs(pos - to2));
|
|
546
|
+
if (d < closest) {
|
|
547
|
+
active = value.spec.id;
|
|
548
|
+
closest = d;
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
if (decorations.length) {
|
|
552
|
+
doUpdate({
|
|
553
|
+
active,
|
|
554
|
+
items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
|
|
555
|
+
id,
|
|
556
|
+
pos: from2,
|
|
557
|
+
location: view.coordsAtPos(from2)
|
|
558
|
+
}))
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
}),
|
|
562
|
+
styles
|
|
563
|
+
];
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/image.ts
|
|
58
567
|
import { syntaxTree } from "@codemirror/language";
|
|
59
|
-
import { RangeSetBuilder, StateField } from "@codemirror/state";
|
|
60
|
-
import { Decoration, EditorView as
|
|
61
|
-
var
|
|
568
|
+
import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
|
|
569
|
+
import { Decoration as Decoration2, EditorView as EditorView4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
570
|
+
var image = (options = {}) => {
|
|
571
|
+
return StateField2.define({
|
|
572
|
+
create: (state) => update(state, options),
|
|
573
|
+
update: (_, tr) => update(tr.state, options),
|
|
574
|
+
provide: (field) => EditorView4.decorations.from(field)
|
|
575
|
+
});
|
|
576
|
+
};
|
|
577
|
+
var update = (state, options) => {
|
|
578
|
+
const builder = new RangeSetBuilder();
|
|
579
|
+
syntaxTree(state).iterate({
|
|
580
|
+
enter: (node) => {
|
|
581
|
+
if (node.name === "Image") {
|
|
582
|
+
const urlNode = node.node.getChild("URL");
|
|
583
|
+
if (urlNode) {
|
|
584
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
585
|
+
builder.add(state.readOnly ? node.from : node.to, node.to, Decoration2.widget({
|
|
586
|
+
widget: new ImageWidget(url)
|
|
587
|
+
}));
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
return builder.finish();
|
|
593
|
+
};
|
|
594
|
+
var ImageWidget = class extends WidgetType2 {
|
|
595
|
+
constructor(_url) {
|
|
596
|
+
super();
|
|
597
|
+
this._url = _url;
|
|
598
|
+
}
|
|
599
|
+
eq(other) {
|
|
600
|
+
return this._url === other?._url;
|
|
601
|
+
}
|
|
602
|
+
toDOM(view) {
|
|
603
|
+
const img = document.createElement("img");
|
|
604
|
+
img.setAttribute("src", this._url);
|
|
605
|
+
img.setAttribute("class", "cm-image");
|
|
606
|
+
return img;
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
|
|
611
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
612
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
|
|
613
|
+
import { Decoration as Decoration3, EditorView as EditorView5, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
614
|
+
var link = (options = {}) => {
|
|
615
|
+
return StateField3.define({
|
|
616
|
+
create: (state) => update2(state, options),
|
|
617
|
+
update: (_, tr) => update2(tr.state, options),
|
|
618
|
+
provide: (field) => EditorView5.decorations.from(field)
|
|
619
|
+
});
|
|
620
|
+
};
|
|
621
|
+
var LinkButton = class extends WidgetType3 {
|
|
62
622
|
constructor(_pos, _url, _onAttach) {
|
|
63
623
|
super();
|
|
64
624
|
this._pos = _pos;
|
|
@@ -74,7 +634,7 @@ var LinkButton = class extends WidgetType {
|
|
|
74
634
|
return el;
|
|
75
635
|
}
|
|
76
636
|
};
|
|
77
|
-
var LinkText = class extends
|
|
637
|
+
var LinkText = class extends WidgetType3 {
|
|
78
638
|
constructor(_pos, _text, _url) {
|
|
79
639
|
super();
|
|
80
640
|
this._pos = _pos;
|
|
@@ -104,79 +664,99 @@ var LinkText = class extends WidgetType {
|
|
|
104
664
|
return link2;
|
|
105
665
|
}
|
|
106
666
|
};
|
|
107
|
-
var
|
|
108
|
-
const builder = new
|
|
667
|
+
var update2 = (state, options) => {
|
|
668
|
+
const builder = new RangeSetBuilder2();
|
|
109
669
|
const cursor = state.selection.main.head;
|
|
110
|
-
|
|
670
|
+
syntaxTree2(state).iterate({
|
|
111
671
|
enter: (node) => {
|
|
112
672
|
if (node.name === "Link") {
|
|
113
673
|
const marks = node.node.getChildren("LinkMark");
|
|
114
674
|
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
115
675
|
const urlNode = node.node.getChild("URL");
|
|
116
676
|
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
677
|
+
if (!url) {
|
|
678
|
+
return false;
|
|
679
|
+
}
|
|
117
680
|
if (cursor < node.from || cursor > node.to) {
|
|
118
|
-
builder.add(node.from, node.to,
|
|
681
|
+
builder.add(node.from, node.to, Decoration3.replace({
|
|
119
682
|
widget: new LinkText(node.from, text, options.link ? url : void 0)
|
|
120
683
|
}));
|
|
121
684
|
}
|
|
122
685
|
if (options.onRender) {
|
|
123
|
-
builder.add(node.to, node.to,
|
|
686
|
+
builder.add(node.to, node.to, Decoration3.replace({
|
|
124
687
|
widget: new LinkButton(node.from, url, options.onRender)
|
|
125
688
|
}));
|
|
126
689
|
}
|
|
690
|
+
return false;
|
|
127
691
|
}
|
|
128
|
-
return true;
|
|
129
692
|
}
|
|
130
693
|
});
|
|
131
694
|
return builder.finish();
|
|
132
695
|
};
|
|
133
|
-
var link = (options = {}) => {
|
|
134
|
-
return StateField.define({
|
|
135
|
-
create: (state) => update(state, options),
|
|
136
|
-
update: (_, tr) => update(tr.state, options),
|
|
137
|
-
provide: (field) => EditorView2.decorations.from(field)
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
696
|
|
|
141
697
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
|
|
142
|
-
import { StateField as
|
|
143
|
-
var listener = (onChange) =>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
698
|
+
import { StateField as StateField4 } from "@codemirror/state";
|
|
699
|
+
var listener = ({ onChange }) => {
|
|
700
|
+
return StateField4.define({
|
|
701
|
+
create: () => null,
|
|
702
|
+
update: (_value, transaction) => {
|
|
703
|
+
if (transaction.docChanged && onChange) {
|
|
704
|
+
onChange(transaction.newDoc.toString());
|
|
705
|
+
}
|
|
706
|
+
return null;
|
|
148
707
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
708
|
+
});
|
|
709
|
+
};
|
|
152
710
|
|
|
153
711
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
154
712
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
155
713
|
import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
|
|
156
714
|
import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
|
|
157
|
-
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2,
|
|
715
|
+
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
158
716
|
import { languages } from "@codemirror/language-data";
|
|
159
|
-
import { lintKeymap } from "@codemirror/lint";
|
|
160
717
|
import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
|
|
161
718
|
import { EditorState } from "@codemirror/state";
|
|
162
719
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
163
|
-
import { crosshairCursor, drawSelection, dropCursor, EditorView as
|
|
720
|
+
import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView6, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap5, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
|
|
164
721
|
|
|
165
722
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
|
|
166
723
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
167
724
|
import { HighlightStyle } from "@codemirror/language";
|
|
168
725
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
169
726
|
import get from "lodash.get";
|
|
727
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
170
728
|
|
|
171
729
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
172
730
|
import { mx } from "@dxos/react-ui-theme";
|
|
173
|
-
var
|
|
174
|
-
1:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
731
|
+
var headings = {
|
|
732
|
+
1: [
|
|
733
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
734
|
+
"-ml-1.5"
|
|
735
|
+
],
|
|
736
|
+
2: [
|
|
737
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
738
|
+
"-ml-1.5"
|
|
739
|
+
],
|
|
740
|
+
3: [
|
|
741
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
742
|
+
"-ml-1.5"
|
|
743
|
+
],
|
|
744
|
+
4: [
|
|
745
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
746
|
+
"-ml-[5px]"
|
|
747
|
+
],
|
|
748
|
+
5: [
|
|
749
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
750
|
+
"-ml-[5px]"
|
|
751
|
+
],
|
|
752
|
+
6: [
|
|
753
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
754
|
+
"-ml-[4px]"
|
|
755
|
+
]
|
|
756
|
+
};
|
|
757
|
+
var heading = (level, readonly) => {
|
|
758
|
+
const [style, offset] = headings[level];
|
|
759
|
+
return mx(style, readonly && offset);
|
|
180
760
|
};
|
|
181
761
|
var light = "text-neutral-200 dark:text-neutral-800";
|
|
182
762
|
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
@@ -187,7 +767,7 @@ var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
|
187
767
|
var codeMark = "font-mono text-primary-500";
|
|
188
768
|
var inlineUrl = mx(code, "px-1");
|
|
189
769
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
190
|
-
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-
|
|
770
|
+
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800";
|
|
191
771
|
|
|
192
772
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
193
773
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
@@ -213,7 +793,7 @@ var markdownTagsExtension = {
|
|
|
213
793
|
styleTags(markdownTags)
|
|
214
794
|
]
|
|
215
795
|
};
|
|
216
|
-
var markdownHighlightStyle = HighlightStyle.define([
|
|
796
|
+
var markdownHighlightStyle = (readonly) => HighlightStyle.define([
|
|
217
797
|
{
|
|
218
798
|
tag: [
|
|
219
799
|
tags.keyword,
|
|
@@ -257,40 +837,54 @@ var markdownHighlightStyle = HighlightStyle.define([
|
|
|
257
837
|
tag: [
|
|
258
838
|
tags.meta,
|
|
259
839
|
tags.processingInstruction,
|
|
260
|
-
markdownTags.CodeMark,
|
|
261
|
-
markdownTags.EmphasisMark,
|
|
262
|
-
markdownTags.HeaderMark,
|
|
263
840
|
markdownTags.LinkLabel,
|
|
264
841
|
markdownTags.LinkReference,
|
|
265
|
-
markdownTags.ListMark
|
|
266
|
-
markdownTags.QuoteMark
|
|
842
|
+
markdownTags.ListMark
|
|
267
843
|
],
|
|
268
844
|
class: mark
|
|
269
845
|
},
|
|
846
|
+
// Markdown marks.
|
|
847
|
+
{
|
|
848
|
+
tag: [
|
|
849
|
+
markdownTags.CodeMark,
|
|
850
|
+
markdownTags.HeaderMark,
|
|
851
|
+
markdownTags.QuoteMark,
|
|
852
|
+
markdownTags.EmphasisMark
|
|
853
|
+
],
|
|
854
|
+
class: readonly ? "hidden" : mark
|
|
855
|
+
},
|
|
856
|
+
// E.g., code block language (after ```).
|
|
857
|
+
{
|
|
858
|
+
tag: [
|
|
859
|
+
tags.function(tags.variableName),
|
|
860
|
+
tags.labelName
|
|
861
|
+
],
|
|
862
|
+
class: readonly ? "hidden" : codeMark
|
|
863
|
+
},
|
|
270
864
|
// Headings.
|
|
271
865
|
{
|
|
272
866
|
tag: tags.heading1,
|
|
273
|
-
class: heading
|
|
867
|
+
class: heading(1, readonly)
|
|
274
868
|
},
|
|
275
869
|
{
|
|
276
870
|
tag: tags.heading2,
|
|
277
|
-
class: heading
|
|
871
|
+
class: heading(2, readonly)
|
|
278
872
|
},
|
|
279
873
|
{
|
|
280
874
|
tag: tags.heading3,
|
|
281
|
-
class: heading
|
|
875
|
+
class: heading(3, readonly)
|
|
282
876
|
},
|
|
283
877
|
{
|
|
284
878
|
tag: tags.heading4,
|
|
285
|
-
class: heading
|
|
879
|
+
class: heading(4, readonly)
|
|
286
880
|
},
|
|
287
881
|
{
|
|
288
882
|
tag: tags.heading5,
|
|
289
|
-
class: heading
|
|
883
|
+
class: heading(5, readonly)
|
|
290
884
|
},
|
|
291
885
|
{
|
|
292
886
|
tag: tags.heading6,
|
|
293
|
-
class: heading
|
|
887
|
+
class: heading(6, readonly)
|
|
294
888
|
},
|
|
295
889
|
// Emphasis.
|
|
296
890
|
{
|
|
@@ -312,18 +906,11 @@ var markdownHighlightStyle = HighlightStyle.define([
|
|
|
312
906
|
],
|
|
313
907
|
class: inlineUrl
|
|
314
908
|
},
|
|
315
|
-
//
|
|
316
|
-
{
|
|
317
|
-
tag: [
|
|
318
|
-
tags.function(tags.variableName),
|
|
319
|
-
tags.labelName
|
|
320
|
-
],
|
|
321
|
-
class: codeMark
|
|
322
|
-
},
|
|
323
|
-
// The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
909
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
324
910
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
325
911
|
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
326
912
|
// the code, but all other CSS properties will be inherited.
|
|
913
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
327
914
|
{
|
|
328
915
|
tag: [
|
|
329
916
|
markdownTags.CodeText,
|
|
@@ -341,7 +928,7 @@ var markdownHighlightStyle = HighlightStyle.define([
|
|
|
341
928
|
tag: [
|
|
342
929
|
markdownTags.HorizontalRule
|
|
343
930
|
],
|
|
344
|
-
class: horizontalRule
|
|
931
|
+
class: mx2(horizontalRule, readonly && "-indent-[100rem]")
|
|
345
932
|
}
|
|
346
933
|
], {
|
|
347
934
|
scope: markdownLanguage,
|
|
@@ -351,14 +938,13 @@ var markdownHighlightStyle = HighlightStyle.define([
|
|
|
351
938
|
});
|
|
352
939
|
|
|
353
940
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
354
|
-
var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
941
|
+
var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
355
942
|
return [
|
|
356
943
|
bracketMatching2(),
|
|
357
944
|
closeBrackets2(),
|
|
358
945
|
_placeholder && placeholder2(_placeholder),
|
|
359
946
|
EditorState.allowMultipleSelections.of(true),
|
|
360
|
-
|
|
361
|
-
// autocompletion(),
|
|
947
|
+
EditorView6.lineWrapping,
|
|
362
948
|
crosshairCursor(),
|
|
363
949
|
dropCursor(),
|
|
364
950
|
drawSelection(),
|
|
@@ -369,14 +955,17 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
369
955
|
history(),
|
|
370
956
|
indentOnInput(),
|
|
371
957
|
rectangularSelection(),
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
//
|
|
958
|
+
// https://codemirror.net/docs/ref/#view.keymap
|
|
959
|
+
keymap5.of([
|
|
960
|
+
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
375
961
|
...defaultKeymap,
|
|
376
|
-
|
|
962
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
377
963
|
...historyKeymap,
|
|
378
|
-
|
|
964
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
965
|
+
...closeBracketsKeymap,
|
|
966
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
379
967
|
...searchKeymap,
|
|
968
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
380
969
|
indentWithTab
|
|
381
970
|
]),
|
|
382
971
|
// Main extension.
|
|
@@ -397,98 +986,213 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
397
986
|
markdownTagsExtension
|
|
398
987
|
]
|
|
399
988
|
}),
|
|
989
|
+
// https://github.com/codemirror/theme-one-dark
|
|
990
|
+
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
400
991
|
// Custom styles.
|
|
401
|
-
syntaxHighlighting2(markdownHighlightStyle)
|
|
402
|
-
// TODO(thure): All but one rule here apply to both themes; rename or refactor.
|
|
403
|
-
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
|
|
992
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
404
993
|
].filter(Boolean);
|
|
405
994
|
};
|
|
406
995
|
|
|
996
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/mention.ts
|
|
997
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
998
|
+
var mention = ({ onSearch }) => {
|
|
999
|
+
return autocompletion2({
|
|
1000
|
+
closeOnBlur: false,
|
|
1001
|
+
override: [
|
|
1002
|
+
(context) => {
|
|
1003
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
1004
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
console.log(match);
|
|
1008
|
+
return {
|
|
1009
|
+
from: match.from,
|
|
1010
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
1011
|
+
label: `@${value}`
|
|
1012
|
+
}))
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
]
|
|
1016
|
+
});
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
|
|
1020
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1021
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
|
|
1022
|
+
import { Decoration as Decoration4, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1023
|
+
var table = (options = {}) => {
|
|
1024
|
+
return StateField5.define({
|
|
1025
|
+
create: (state) => update3(state, options),
|
|
1026
|
+
update: (_, tr) => update3(tr.state, options),
|
|
1027
|
+
provide: (field) => EditorView7.decorations.from(field)
|
|
1028
|
+
});
|
|
1029
|
+
};
|
|
1030
|
+
var update3 = (state, options) => {
|
|
1031
|
+
const builder = new RangeSetBuilder3();
|
|
1032
|
+
if (state.readOnly) {
|
|
1033
|
+
const tables = [];
|
|
1034
|
+
const getTable = () => tables[tables.length - 1];
|
|
1035
|
+
const getRow = () => {
|
|
1036
|
+
const table2 = getTable();
|
|
1037
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
1038
|
+
};
|
|
1039
|
+
syntaxTree3(state).iterate({
|
|
1040
|
+
enter: (node) => {
|
|
1041
|
+
switch (node.name) {
|
|
1042
|
+
case "Table": {
|
|
1043
|
+
tables.push({
|
|
1044
|
+
from: node.from
|
|
1045
|
+
});
|
|
1046
|
+
break;
|
|
1047
|
+
}
|
|
1048
|
+
case "TableHeader": {
|
|
1049
|
+
getTable().header = [];
|
|
1050
|
+
break;
|
|
1051
|
+
}
|
|
1052
|
+
case "TableRow": {
|
|
1053
|
+
(getTable().rows ??= []).push([]);
|
|
1054
|
+
break;
|
|
1055
|
+
}
|
|
1056
|
+
case "TableCell": {
|
|
1057
|
+
const row = getRow();
|
|
1058
|
+
if (row) {
|
|
1059
|
+
row.push(state.sliceDoc(node.from, node.to));
|
|
1060
|
+
} else {
|
|
1061
|
+
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
1062
|
+
}
|
|
1063
|
+
break;
|
|
1064
|
+
}
|
|
1065
|
+
case "TableDelimiter": {
|
|
1066
|
+
getTable().to = node.to;
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
tables.forEach((table2) => builder.add(table2.from, table2.to, Decoration4.replace({
|
|
1073
|
+
widget: new TableWidget(table2)
|
|
1074
|
+
})));
|
|
1075
|
+
}
|
|
1076
|
+
return builder.finish();
|
|
1077
|
+
};
|
|
1078
|
+
var TableWidget = class extends WidgetType4 {
|
|
1079
|
+
constructor(_table) {
|
|
1080
|
+
super();
|
|
1081
|
+
this._table = _table;
|
|
1082
|
+
}
|
|
1083
|
+
eq(other) {
|
|
1084
|
+
return this._table.from === other?._table?.from;
|
|
1085
|
+
}
|
|
1086
|
+
toDOM(view) {
|
|
1087
|
+
const table2 = document.createElement("table");
|
|
1088
|
+
{
|
|
1089
|
+
const header = table2.appendChild(document.createElement("thead"));
|
|
1090
|
+
const row = header.appendChild(document.createElement("tr"));
|
|
1091
|
+
this._table.header?.forEach((cell) => {
|
|
1092
|
+
const th = document.createElement("th");
|
|
1093
|
+
th.setAttribute("class", "cm-table-head");
|
|
1094
|
+
row.appendChild(th).textContent = cell;
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
{
|
|
1098
|
+
const body = table2.appendChild(document.createElement("tbody"));
|
|
1099
|
+
this._table.rows?.forEach((row) => {
|
|
1100
|
+
const tr = body.appendChild(document.createElement("tr"));
|
|
1101
|
+
row.forEach((cell) => {
|
|
1102
|
+
const td = document.createElement("td");
|
|
1103
|
+
td.setAttribute("class", "cm-table-cell");
|
|
1104
|
+
tr.appendChild(td).textContent = cell;
|
|
1105
|
+
});
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
return table2;
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
1111
|
+
|
|
407
1112
|
// 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) {
|
|
1113
|
+
import { EditorView as EditorView8, Decoration as Decoration5, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin2 } from "@codemirror/view";
|
|
1114
|
+
var CheckboxWidget = class extends WidgetType5 {
|
|
1115
|
+
constructor(_pos, _checked, _indent, _onCheck) {
|
|
413
1116
|
super();
|
|
414
1117
|
this._pos = _pos;
|
|
415
|
-
this._getCursor = _getCursor;
|
|
416
1118
|
this._checked = _checked;
|
|
1119
|
+
this._indent = _indent;
|
|
1120
|
+
this._onCheck = _onCheck;
|
|
417
1121
|
}
|
|
418
1122
|
eq(other) {
|
|
419
|
-
return this._pos === other._pos && this._checked === other._checked;
|
|
1123
|
+
return this._pos === other._pos && this._checked === other._checked && this._indent === other._indent;
|
|
420
1124
|
}
|
|
421
1125
|
toDOM(view) {
|
|
422
1126
|
const wrap = document.createElement("span");
|
|
423
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
424
1127
|
wrap.className = "cm-task-item";
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
return true;
|
|
442
|
-
};
|
|
1128
|
+
wrap.setAttribute("aria-hidden", "true");
|
|
1129
|
+
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
1130
|
+
const input = wrap.appendChild(document.createElement("input"));
|
|
1131
|
+
input.type = "checkbox";
|
|
1132
|
+
input.checked = this._checked;
|
|
1133
|
+
if (!this._onCheck) {
|
|
1134
|
+
input.setAttribute("disabled", "true");
|
|
1135
|
+
}
|
|
1136
|
+
if (this._onCheck) {
|
|
1137
|
+
input.onchange = (event) => {
|
|
1138
|
+
this._onCheck?.(event.target.checked);
|
|
1139
|
+
return true;
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
443
1142
|
return wrap;
|
|
444
1143
|
}
|
|
445
|
-
// TODO(burdon): Remove listener?
|
|
446
|
-
// override destroy() {
|
|
447
|
-
// console.log('destroy', this._pos);
|
|
448
|
-
// }
|
|
449
1144
|
ignoreEvent() {
|
|
450
1145
|
return false;
|
|
451
1146
|
}
|
|
452
1147
|
};
|
|
453
|
-
var
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
1148
|
+
var styles2 = EditorView8.baseTheme({
|
|
1149
|
+
"& .cm-task-item": {
|
|
1150
|
+
paddingLeft: "4px",
|
|
1151
|
+
paddingRight: "8px"
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
var tasklist = (options = {}) => {
|
|
1155
|
+
const taskMatcher = new MatchDecorator2({
|
|
1156
|
+
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
1157
|
+
decoration: (match, view, pos) => {
|
|
1158
|
+
const indent = Math.floor(match[1].length / 2);
|
|
1159
|
+
const checked = match[2] === "x" || match[2] === "X";
|
|
1160
|
+
return Decoration5.replace({
|
|
1161
|
+
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
1162
|
+
const idx = pos + match[0].indexOf("[") + 1;
|
|
1163
|
+
view.dispatch({
|
|
1164
|
+
changes: {
|
|
1165
|
+
from: idx,
|
|
1166
|
+
to: idx + 1,
|
|
1167
|
+
insert: checked2 ? "x" : " "
|
|
1168
|
+
},
|
|
1169
|
+
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
1170
|
+
selection: {
|
|
1171
|
+
anchor: idx + 3
|
|
1172
|
+
}
|
|
1173
|
+
});
|
|
1174
|
+
})
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
460
1177
|
});
|
|
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)
|
|
1178
|
+
const tasks = ViewPlugin2.fromClass(class {
|
|
1179
|
+
constructor(view) {
|
|
1180
|
+
this.tasks = taskMatcher.createDeco(view);
|
|
1181
|
+
}
|
|
1182
|
+
update(update4) {
|
|
1183
|
+
this.tasks = taskMatcher.updateDeco(update4, this.tasks);
|
|
1184
|
+
}
|
|
1185
|
+
}, {
|
|
1186
|
+
decorations: (instance) => instance.tasks,
|
|
1187
|
+
provide: (plugin) => EditorView8.atomicRanges.of((view) => {
|
|
1188
|
+
return view.plugin(plugin)?.tasks || Decoration5.none;
|
|
480
1189
|
})
|
|
1190
|
+
});
|
|
1191
|
+
return [
|
|
1192
|
+
tasks,
|
|
1193
|
+
styles2
|
|
481
1194
|
];
|
|
482
1195
|
};
|
|
483
|
-
var styles = EditorView4.baseTheme({
|
|
484
|
-
"& .cm-task-item": {
|
|
485
|
-
padding: "0 4px"
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
var tasklist = () => [
|
|
489
|
-
statefield(),
|
|
490
|
-
styles
|
|
491
|
-
];
|
|
492
1196
|
|
|
493
1197
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/tooltip.tsx
|
|
494
1198
|
import { hoverTooltip } from "@codemirror/view";
|
|
@@ -648,8 +1352,51 @@ var defaultTheme = {
|
|
|
648
1352
|
"& .cm-tooltip": {
|
|
649
1353
|
border: "none"
|
|
650
1354
|
},
|
|
651
|
-
|
|
652
|
-
//
|
|
1355
|
+
"& .cm-tooltip-below": {},
|
|
1356
|
+
//
|
|
1357
|
+
// autocomplete
|
|
1358
|
+
//
|
|
1359
|
+
"& .cm-tooltip-autocomplete": {
|
|
1360
|
+
marginTop: "4px",
|
|
1361
|
+
marginLeft: "-3px"
|
|
1362
|
+
},
|
|
1363
|
+
"& .cm-tooltip-autocomplete ul li": {},
|
|
1364
|
+
"& .cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
1365
|
+
"& .cm-completionIcon": {
|
|
1366
|
+
display: "none"
|
|
1367
|
+
},
|
|
1368
|
+
"& .cm-completionLabel": {
|
|
1369
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
1370
|
+
},
|
|
1371
|
+
"& .cm-completionMatchedText": {
|
|
1372
|
+
textDecoration: "none"
|
|
1373
|
+
},
|
|
1374
|
+
//
|
|
1375
|
+
// widgets
|
|
1376
|
+
//
|
|
1377
|
+
"& .cm-widgetBuffer": {
|
|
1378
|
+
display: "none",
|
|
1379
|
+
height: 0
|
|
1380
|
+
},
|
|
1381
|
+
//
|
|
1382
|
+
// table
|
|
1383
|
+
//
|
|
1384
|
+
"& .cm-table-head": {
|
|
1385
|
+
padding: "2px 16px 2px 0px",
|
|
1386
|
+
borderBottom: `1px solid ${get2(tokens, "extend.colors.neutral.500")}`,
|
|
1387
|
+
fontWeight: 100,
|
|
1388
|
+
textAlign: "left",
|
|
1389
|
+
color: get2(tokens, "extend.colors.neutral.500")
|
|
1390
|
+
},
|
|
1391
|
+
"& .cm-table-cell": {
|
|
1392
|
+
padding: "2px 16px 2px 0px"
|
|
1393
|
+
},
|
|
1394
|
+
//
|
|
1395
|
+
// image
|
|
1396
|
+
//
|
|
1397
|
+
"& .cm-image": {
|
|
1398
|
+
margin: "0.5rem 0"
|
|
1399
|
+
},
|
|
653
1400
|
//
|
|
654
1401
|
// font size
|
|
655
1402
|
// TODO(thure): This appears to be the best or only way to set selection caret heights, but it's far more verbose than it needs to be.
|
|
@@ -677,38 +1424,61 @@ var defaultTheme = {
|
|
|
677
1424
|
var textTheme = {
|
|
678
1425
|
"& .cm-scroller": {
|
|
679
1426
|
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
1427
|
+
},
|
|
1428
|
+
"& .cm-placeholder": {
|
|
1429
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
var markdownTheme = {
|
|
1433
|
+
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
1434
|
+
"& .cm-placeholder": {
|
|
1435
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
680
1436
|
}
|
|
681
1437
|
};
|
|
682
1438
|
var codeTheme = {
|
|
683
1439
|
"& .cm-scroller": {
|
|
684
1440
|
fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
|
|
1441
|
+
},
|
|
1442
|
+
"& .cm-placeholder": {
|
|
1443
|
+
fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
|
|
685
1444
|
}
|
|
686
1445
|
};
|
|
687
1446
|
|
|
688
1447
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
689
1448
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
690
|
-
import { EditorView as
|
|
1449
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
691
1450
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
692
1451
|
import { vim } from "@replit/codemirror-vim";
|
|
693
|
-
import
|
|
1452
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
694
1453
|
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
695
|
-
import { yCollab } from "y-codemirror.next";
|
|
696
1454
|
import { generateName } from "@dxos/display-name";
|
|
697
1455
|
import { useThemeContext } from "@dxos/react-ui";
|
|
698
|
-
import { getColorForValue, inputSurface, mx as
|
|
1456
|
+
import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
699
1457
|
var EditorModes = [
|
|
700
1458
|
"default",
|
|
701
1459
|
"vim"
|
|
702
1460
|
];
|
|
703
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots = defaultSlots
|
|
1461
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
|
|
704
1462
|
const { themeMode } = useThemeContext();
|
|
705
1463
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
706
1464
|
tabBehavior: "limited"
|
|
707
1465
|
});
|
|
708
|
-
const
|
|
1466
|
+
const [root, setRoot] = useState(null);
|
|
1467
|
+
const [state, setState] = useState();
|
|
1468
|
+
const [view, setView] = useState();
|
|
1469
|
+
useImperativeHandle(forwardedRef, () => ({
|
|
1470
|
+
root,
|
|
1471
|
+
state,
|
|
1472
|
+
view
|
|
1473
|
+
}), [
|
|
1474
|
+
view,
|
|
1475
|
+
state,
|
|
1476
|
+
root
|
|
1477
|
+
]);
|
|
1478
|
+
const { awareness, peer } = model;
|
|
709
1479
|
useEffect(() => {
|
|
710
|
-
if (
|
|
711
|
-
|
|
1480
|
+
if (awareness && peer) {
|
|
1481
|
+
awareness.setLocalStateField("user", {
|
|
712
1482
|
name: peer.name ?? generateName(peer.id),
|
|
713
1483
|
color: getColorForValue({
|
|
714
1484
|
value: peer.id,
|
|
@@ -722,22 +1492,10 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
722
1492
|
});
|
|
723
1493
|
}
|
|
724
1494
|
}, [
|
|
725
|
-
|
|
1495
|
+
awareness,
|
|
726
1496
|
peer,
|
|
727
1497
|
themeMode
|
|
728
1498
|
]);
|
|
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
1499
|
useEffect(() => {
|
|
742
1500
|
if (!root) {
|
|
743
1501
|
return;
|
|
@@ -745,21 +1503,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
745
1503
|
const state2 = EditorState2.create({
|
|
746
1504
|
doc: model.text(),
|
|
747
1505
|
extensions: [
|
|
1506
|
+
readonly && EditorState2.readOnly.of(readonly),
|
|
748
1507
|
// TODO(burdon): Factor out VIM mode?
|
|
749
1508
|
editorMode === "vim" && vim(),
|
|
750
1509
|
// Theme.
|
|
751
|
-
|
|
752
|
-
|
|
1510
|
+
EditorView9.baseTheme(defaultTheme),
|
|
1511
|
+
EditorView9.theme(slots?.editor?.theme ?? {}),
|
|
753
1512
|
// TODO(burdon): themeMode doesn't change in storybooks.
|
|
754
|
-
|
|
1513
|
+
EditorView9.darkTheme.of(themeMode === "dark"),
|
|
755
1514
|
// Storage and replication.
|
|
756
|
-
|
|
1515
|
+
model.extension,
|
|
757
1516
|
// Custom.
|
|
758
1517
|
...extensions
|
|
759
1518
|
].filter(Boolean)
|
|
760
1519
|
});
|
|
761
1520
|
view?.destroy();
|
|
762
|
-
setView(new
|
|
1521
|
+
setView(new EditorView9({
|
|
763
1522
|
state: state2,
|
|
764
1523
|
parent: root
|
|
765
1524
|
}));
|
|
@@ -771,8 +1530,9 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
771
1530
|
};
|
|
772
1531
|
}, [
|
|
773
1532
|
root,
|
|
774
|
-
model
|
|
1533
|
+
model,
|
|
775
1534
|
themeMode,
|
|
1535
|
+
readonly,
|
|
776
1536
|
editorMode
|
|
777
1537
|
]);
|
|
778
1538
|
const handleKeyUp = useCallback((event) => {
|
|
@@ -800,32 +1560,47 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
800
1560
|
onKeyUp: handleKeyUp
|
|
801
1561
|
});
|
|
802
1562
|
});
|
|
803
|
-
var
|
|
1563
|
+
var maybeDebug = () => {
|
|
1564
|
+
const items = localStorage.getItem("dxos.composer.demo");
|
|
1565
|
+
if (items) {
|
|
1566
|
+
return demo({
|
|
1567
|
+
items: items.split(",")
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1570
|
+
return [];
|
|
1571
|
+
};
|
|
1572
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
804
1573
|
const { themeMode } = useThemeContext();
|
|
805
|
-
const slots =
|
|
1574
|
+
const slots = defaultsDeep2({}, _slots, defaultTextSlots);
|
|
806
1575
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
807
1576
|
ref: forwardedRef,
|
|
1577
|
+
readonly,
|
|
808
1578
|
extensions: [
|
|
809
1579
|
basicBundle({
|
|
1580
|
+
readonly,
|
|
810
1581
|
themeMode,
|
|
811
1582
|
placeholder: slots?.editor?.placeholder
|
|
812
1583
|
}),
|
|
1584
|
+
maybeDebug(),
|
|
813
1585
|
...extensions
|
|
814
1586
|
],
|
|
815
1587
|
slots,
|
|
816
1588
|
...props
|
|
817
1589
|
});
|
|
818
1590
|
});
|
|
819
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1591
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
820
1592
|
const { themeMode } = useThemeContext();
|
|
821
|
-
const slots =
|
|
1593
|
+
const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
|
|
822
1594
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
823
1595
|
ref: forwardedRef,
|
|
1596
|
+
readonly,
|
|
824
1597
|
extensions: [
|
|
825
1598
|
markdownBundle({
|
|
1599
|
+
readonly,
|
|
826
1600
|
themeMode,
|
|
827
1601
|
placeholder: slots?.editor?.placeholder
|
|
828
1602
|
}),
|
|
1603
|
+
maybeDebug(),
|
|
829
1604
|
...extensions
|
|
830
1605
|
],
|
|
831
1606
|
slots,
|
|
@@ -834,7 +1609,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
|
|
|
834
1609
|
});
|
|
835
1610
|
var defaultSlots = {
|
|
836
1611
|
root: {
|
|
837
|
-
className:
|
|
1612
|
+
className: mx3("p-2", inputSurface)
|
|
838
1613
|
}
|
|
839
1614
|
};
|
|
840
1615
|
var defaultTextSlots = {
|
|
@@ -843,26 +1618,31 @@ var defaultTextSlots = {
|
|
|
843
1618
|
theme: textTheme
|
|
844
1619
|
}
|
|
845
1620
|
};
|
|
1621
|
+
var defaultMarkdownSlots = {
|
|
1622
|
+
...defaultSlots,
|
|
1623
|
+
editor: {
|
|
1624
|
+
theme: markdownTheme
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
846
1627
|
|
|
847
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
1628
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1629
|
+
import get3 from "lodash.get";
|
|
848
1630
|
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";
|
|
1631
|
+
import { yCollab } from "y-codemirror.next";
|
|
1632
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1633
|
+
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
854
1634
|
|
|
855
|
-
// packages/ui/react-ui-editor/src/
|
|
856
|
-
import { Annotation, Facet, StateEffect, StateField as
|
|
857
|
-
import { ViewPlugin } from "@codemirror/view";
|
|
1635
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1636
|
+
import { Annotation, Facet, StateEffect, StateField as StateField6 } from "@codemirror/state";
|
|
1637
|
+
import { ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
858
1638
|
import * as automerge2 from "@dxos/automerge/automerge";
|
|
859
1639
|
|
|
860
|
-
// packages/ui/react-ui-editor/src/
|
|
1640
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
861
1641
|
import { next as automerge } from "@dxos/automerge/automerge";
|
|
862
1642
|
|
|
863
|
-
// packages/ui/react-ui-editor/src/automerge/automerge-
|
|
1643
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
|
|
864
1644
|
import { ChangeSet } from "@codemirror/state";
|
|
865
|
-
var
|
|
1645
|
+
var automergeToCodemirror = (view, selection, target, patches) => {
|
|
866
1646
|
for (const patch of patches) {
|
|
867
1647
|
const changeSpec = handlePatch(patch, target, view.state);
|
|
868
1648
|
if (changeSpec != null) {
|
|
@@ -967,9 +1747,9 @@ var charPath = (textPath, candidatePath) => {
|
|
|
967
1747
|
return null;
|
|
968
1748
|
};
|
|
969
1749
|
|
|
970
|
-
// packages/ui/react-ui-editor/src/automerge/automerge
|
|
1750
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
|
|
971
1751
|
import { next as am } from "@dxos/automerge/automerge";
|
|
972
|
-
var
|
|
1752
|
+
var codemirrorToAutomerge = (field, handle, transactions, state) => {
|
|
973
1753
|
const { lastHeads, path } = state.field(field);
|
|
974
1754
|
let hasChanges = false;
|
|
975
1755
|
for (const tr of transactions) {
|
|
@@ -990,7 +1770,7 @@ var codeMirrorToAm_default = (field, handle, transactions, state) => {
|
|
|
990
1770
|
return newHeads ?? void 0;
|
|
991
1771
|
};
|
|
992
1772
|
|
|
993
|
-
// packages/ui/react-ui-editor/src/
|
|
1773
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
994
1774
|
var PatchSemaphore = class {
|
|
995
1775
|
constructor(field) {
|
|
996
1776
|
this._inReconcile = false;
|
|
@@ -1013,12 +1793,12 @@ var PatchSemaphore = class {
|
|
|
1013
1793
|
annotations: reconcileAnnotationType.of(true)
|
|
1014
1794
|
});
|
|
1015
1795
|
}
|
|
1016
|
-
let newHeads =
|
|
1796
|
+
let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
|
|
1017
1797
|
if (newHeads === null || newHeads === void 0) {
|
|
1018
1798
|
newHeads = automerge.getHeads(handle.docSync());
|
|
1019
1799
|
}
|
|
1020
1800
|
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
1021
|
-
|
|
1801
|
+
automergeToCodemirror(view, selection, path, diff);
|
|
1022
1802
|
view.dispatch({
|
|
1023
1803
|
effects: updateHeads(newHeads),
|
|
1024
1804
|
annotations: reconcileAnnotationType.of({})
|
|
@@ -1031,7 +1811,7 @@ var PatchSemaphore = class {
|
|
|
1031
1811
|
}
|
|
1032
1812
|
};
|
|
1033
1813
|
|
|
1034
|
-
// packages/ui/react-ui-editor/src/
|
|
1814
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1035
1815
|
var effectType = StateEffect.define({});
|
|
1036
1816
|
var updateHeads = (newHeads) => effectType.of({
|
|
1037
1817
|
newHeads
|
|
@@ -1042,7 +1822,7 @@ var semaphoreFacet = Facet.define({
|
|
|
1042
1822
|
combine: (values) => values.at(-1)
|
|
1043
1823
|
});
|
|
1044
1824
|
var automergePlugin = (handle, path) => {
|
|
1045
|
-
const stateField =
|
|
1825
|
+
const stateField = StateField6.define({
|
|
1046
1826
|
create: () => ({
|
|
1047
1827
|
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
1048
1828
|
unreconciledTransactions: [],
|
|
@@ -1072,7 +1852,7 @@ var automergePlugin = (handle, path) => {
|
|
|
1072
1852
|
}
|
|
1073
1853
|
});
|
|
1074
1854
|
const semaphore = new PatchSemaphore(stateField);
|
|
1075
|
-
const viewPlugin =
|
|
1855
|
+
const viewPlugin = ViewPlugin3.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
1076
1856
|
constructor(view) {
|
|
1077
1857
|
this._handleChange = () => {
|
|
1078
1858
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
@@ -1080,8 +1860,8 @@ var automergePlugin = (handle, path) => {
|
|
|
1080
1860
|
this._view = view;
|
|
1081
1861
|
handle.addListener("change", this._handleChange);
|
|
1082
1862
|
}
|
|
1083
|
-
update(
|
|
1084
|
-
if (
|
|
1863
|
+
update(update4) {
|
|
1864
|
+
if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
|
|
1085
1865
|
queueMicrotask(() => {
|
|
1086
1866
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
1087
1867
|
});
|
|
@@ -1102,47 +1882,8 @@ var automergePlugin = (handle, path) => {
|
|
|
1102
1882
|
var reconcileAnnotationType = Annotation.define();
|
|
1103
1883
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
1104
1884
|
|
|
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
1885
|
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
1145
|
-
import * as
|
|
1886
|
+
import * as random2 from "lib0/random";
|
|
1146
1887
|
var cursorColors = [
|
|
1147
1888
|
{
|
|
1148
1889
|
color: "#30bced",
|
|
@@ -1177,7 +1918,7 @@ var cursorColors = [
|
|
|
1177
1918
|
light: "#1be7ff33"
|
|
1178
1919
|
}
|
|
1179
1920
|
];
|
|
1180
|
-
var cursorColor = cursorColors[
|
|
1921
|
+
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
1181
1922
|
|
|
1182
1923
|
// packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
|
|
1183
1924
|
import * as decoding from "lib0/decoding";
|
|
@@ -1185,7 +1926,7 @@ import * as encoding from "lib0/encoding";
|
|
|
1185
1926
|
import { Observable } from "lib0/observable";
|
|
1186
1927
|
import * as awarenessProtocol from "y-protocols/awareness";
|
|
1187
1928
|
import { log } from "@dxos/log";
|
|
1188
|
-
var
|
|
1929
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
1189
1930
|
var messageAwareness = 1;
|
|
1190
1931
|
var messageQueryAwareness = 3;
|
|
1191
1932
|
var SpaceAwarenessProvider = class extends Observable {
|
|
@@ -1222,7 +1963,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1222
1963
|
removed,
|
|
1223
1964
|
origin
|
|
1224
1965
|
}, {
|
|
1225
|
-
F:
|
|
1966
|
+
F: __dxlog_file3,
|
|
1226
1967
|
L: 67,
|
|
1227
1968
|
S: this,
|
|
1228
1969
|
C: (f, a) => f(...a)
|
|
@@ -1235,7 +1976,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1235
1976
|
}
|
|
1236
1977
|
_handleSpaceMessage({ payload }) {
|
|
1237
1978
|
log("space message", payload, {
|
|
1238
|
-
F:
|
|
1979
|
+
F: __dxlog_file3,
|
|
1239
1980
|
L: 79,
|
|
1240
1981
|
S: this,
|
|
1241
1982
|
C: (f, a) => f(...a)
|
|
@@ -1280,57 +2021,74 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1280
2021
|
};
|
|
1281
2022
|
|
|
1282
2023
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2024
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
1283
2025
|
var useTextModel = ({ identity, space, text }) => {
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
2026
|
+
const [model, setModel] = useState2(() => createModel({
|
|
2027
|
+
identity,
|
|
2028
|
+
space,
|
|
2029
|
+
text
|
|
2030
|
+
}));
|
|
2031
|
+
useEffect2(() => {
|
|
2032
|
+
setModel(createModel({
|
|
2033
|
+
identity,
|
|
1292
2034
|
space,
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
});
|
|
2035
|
+
text
|
|
2036
|
+
}));
|
|
1296
2037
|
}, [
|
|
1297
2038
|
identity,
|
|
1298
2039
|
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
2040
|
text
|
|
1313
2041
|
]);
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
2042
|
+
return model;
|
|
2043
|
+
};
|
|
2044
|
+
var createModel = (options) => {
|
|
2045
|
+
const { text } = options;
|
|
1317
2046
|
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
|
-
};
|
|
2047
|
+
return createAutomergeModel(options);
|
|
2048
|
+
} else {
|
|
2049
|
+
if (!text?.doc) {
|
|
2050
|
+
return void 0;
|
|
2051
|
+
}
|
|
2052
|
+
return createYjsModel(options);
|
|
1329
2053
|
}
|
|
2054
|
+
};
|
|
2055
|
+
var createYjsModel = ({ identity, space, text }) => {
|
|
2056
|
+
invariant3(text?.doc && text?.content, void 0, {
|
|
2057
|
+
F: __dxlog_file4,
|
|
2058
|
+
L: 74,
|
|
2059
|
+
S: void 0,
|
|
2060
|
+
A: [
|
|
2061
|
+
"text?.doc && text?.content",
|
|
2062
|
+
""
|
|
2063
|
+
]
|
|
2064
|
+
});
|
|
2065
|
+
const provider = space ? new SpaceAwarenessProvider({
|
|
2066
|
+
space,
|
|
2067
|
+
doc: text.doc,
|
|
2068
|
+
channel: `yjs.awareness.${text.id}`
|
|
2069
|
+
}) : void 0;
|
|
1330
2070
|
return {
|
|
1331
2071
|
id: text.doc.guid,
|
|
1332
2072
|
content: text.content,
|
|
1333
2073
|
text: () => text.content.toString(),
|
|
2074
|
+
extension: yCollab(text.content, provider?.awareness),
|
|
2075
|
+
awareness: provider?.awareness,
|
|
2076
|
+
peer: identity ? {
|
|
2077
|
+
id: identity.identityKey.toHex(),
|
|
2078
|
+
name: identity.profile?.displayName
|
|
2079
|
+
} : void 0
|
|
2080
|
+
};
|
|
2081
|
+
};
|
|
2082
|
+
var createAutomergeModel = ({ identity, text }) => {
|
|
2083
|
+
const obj = text;
|
|
2084
|
+
const doc = getRawDoc(obj, [
|
|
2085
|
+
obj.field
|
|
2086
|
+
]);
|
|
2087
|
+
return {
|
|
2088
|
+
id: obj.id,
|
|
2089
|
+
content: doc,
|
|
2090
|
+
text: () => get3(doc.handle.docSync(), doc.path),
|
|
2091
|
+
extension: automergePlugin(doc.handle, doc.path),
|
|
1334
2092
|
peer: identity ? {
|
|
1335
2093
|
id: identity.identityKey.toHex(),
|
|
1336
2094
|
name: identity.profile?.displayName
|
|
@@ -1345,28 +2103,34 @@ export {
|
|
|
1345
2103
|
SpaceAwarenessProvider,
|
|
1346
2104
|
TextEditor,
|
|
1347
2105
|
TextKind,
|
|
1348
|
-
|
|
2106
|
+
YText,
|
|
1349
2107
|
YXmlFragment,
|
|
1350
2108
|
autocomplete,
|
|
1351
2109
|
basicBundle,
|
|
2110
|
+
blast,
|
|
1352
2111
|
codeTheme,
|
|
2112
|
+
comments,
|
|
1353
2113
|
cursorColor,
|
|
2114
|
+
defaultMarkdownSlots,
|
|
2115
|
+
defaultOptions,
|
|
1354
2116
|
defaultSlots,
|
|
1355
2117
|
defaultTextSlots,
|
|
1356
2118
|
defaultTheme,
|
|
2119
|
+
demo,
|
|
2120
|
+
image,
|
|
1357
2121
|
link,
|
|
1358
2122
|
listener,
|
|
1359
2123
|
markdownBundle,
|
|
1360
2124
|
markdownHighlightStyle,
|
|
1361
2125
|
markdownTags,
|
|
1362
2126
|
markdownTagsExtension,
|
|
1363
|
-
|
|
1364
|
-
|
|
2127
|
+
markdownTheme,
|
|
2128
|
+
mention,
|
|
2129
|
+
table,
|
|
1365
2130
|
tags2 as tags,
|
|
1366
2131
|
tasklist,
|
|
1367
2132
|
textTheme,
|
|
1368
2133
|
tooltip,
|
|
1369
|
-
useCollaboration,
|
|
1370
2134
|
useTextModel
|
|
1371
2135
|
};
|
|
1372
2136
|
//# sourceMappingURL=index.mjs.map
|