@dxos/react-ui-editor 0.3.10-main.8fd45da → 0.3.10-main.92d1f2c
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 +986 -296
- 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 +19 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +2 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- 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 +10 -6
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -1
- 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 +1 -1
- 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 +5 -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 +9 -3
- 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 -1
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts +5 -0
- package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts +3 -0
- package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts +8 -1
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/index.d.ts +1 -1
- package/dist/types/src/hooks/automerge/index.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -1
- 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/{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/package.json +20 -19
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +106 -29
- package/src/components/TextEditor/TextEditor.tsx +12 -8
- package/src/components/TextEditor/extensions/autocomplete.ts +5 -20
- package/src/components/TextEditor/extensions/basic.ts +2 -1
- package/src/components/TextEditor/extensions/blast.ts +387 -0
- package/src/components/TextEditor/extensions/comments.ts +59 -60
- package/src/components/TextEditor/extensions/demo.ts +69 -0
- package/src/components/TextEditor/extensions/experimental.tsx +14 -35
- package/src/components/TextEditor/extensions/image.ts +67 -0
- package/src/components/TextEditor/extensions/index.ts +5 -0
- package/src/components/TextEditor/extensions/link.ts +17 -25
- package/src/components/TextEditor/extensions/listener.ts +4 -4
- package/src/components/TextEditor/extensions/markdown/bundle.ts +30 -19
- package/src/components/TextEditor/extensions/markdown/highlight.ts +147 -108
- package/src/components/TextEditor/extensions/mention.ts +31 -0
- package/src/components/TextEditor/extensions/table.ts +122 -0
- package/src/components/TextEditor/extensions/tasklist.ts +41 -27
- package/src/components/TextEditor/themes/default.ts +54 -2
- package/src/hooks/automerge/PatchSemaphore.ts +12 -9
- package/src/hooks/automerge/automerge.stories.tsx +3 -2
- package/src/hooks/automerge/index.ts +1 -1
- package/src/hooks/automerge/plugin.ts +1 -0
- package/src/hooks/automerge/{amToCodemirror.ts → translation/automerge-to-codemirror.ts} +10 -2
- package/src/hooks/automerge/{codeMirrorToAm.ts → translation/codemirror-to-automerge.ts} +7 -4
- package/src/hooks/automerge/translation/index.ts +6 -0
- package/src/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +1 -1
- package/src/styles/markdown.ts +14 -8
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/amToCodemirror.d.ts +0 -6
- package/dist/types/src/hooks/automerge/amToCodemirror.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts +0 -7
- package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts.map +0 -1
|
@@ -24,13 +24,13 @@ var autocomplete = ({ onSearch }) => {
|
|
|
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: onSearch(
|
|
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,18 +54,413 @@ 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/
|
|
58
|
-
import {
|
|
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";
|
|
59
61
|
import { invariant } from "@dxos/invariant";
|
|
60
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/
|
|
62
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts";
|
|
63
|
+
var defaultOptions = {
|
|
64
|
+
effect: 2,
|
|
65
|
+
maxParticles: 200,
|
|
66
|
+
particleGravity: 0.08,
|
|
67
|
+
particleAlphaFadeout: 0.996,
|
|
68
|
+
particleSize: {
|
|
69
|
+
min: 2,
|
|
70
|
+
max: 8
|
|
71
|
+
},
|
|
72
|
+
particleNumRange: {
|
|
73
|
+
min: 5,
|
|
74
|
+
max: 10
|
|
75
|
+
},
|
|
76
|
+
particleVelocityRange: {
|
|
77
|
+
x: [
|
|
78
|
+
-1,
|
|
79
|
+
1
|
|
80
|
+
],
|
|
81
|
+
y: [
|
|
82
|
+
-3.5,
|
|
83
|
+
-1.5
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
particleShrinkRate: 0.95,
|
|
87
|
+
shakeIntensity: 5
|
|
88
|
+
};
|
|
89
|
+
var blast = (options) => {
|
|
90
|
+
let blaster;
|
|
91
|
+
let last = 0;
|
|
92
|
+
const getPoint = (view, pos) => {
|
|
93
|
+
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
94
|
+
const element = document.elementFromPoint(x, y);
|
|
95
|
+
const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
|
|
96
|
+
const point = {
|
|
97
|
+
x: x - left,
|
|
98
|
+
y: y - top
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
element,
|
|
102
|
+
point
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
return [
|
|
106
|
+
// Cursor moved.
|
|
107
|
+
EditorView2.updateListener.of((update4) => {
|
|
108
|
+
if (blaster?.node !== update4.view.scrollDOM) {
|
|
109
|
+
if (blaster) {
|
|
110
|
+
blaster.destroy();
|
|
111
|
+
}
|
|
112
|
+
blaster = new Blaster(update4.view.scrollDOM, defaultsDeep({
|
|
113
|
+
particleGravity: 0.2,
|
|
114
|
+
particleShrinkRate: 0.995,
|
|
115
|
+
color: () => [
|
|
116
|
+
100 + Math.random() * 100,
|
|
117
|
+
0,
|
|
118
|
+
0
|
|
119
|
+
]
|
|
120
|
+
}, options, defaultOptions));
|
|
121
|
+
blaster.initialize();
|
|
122
|
+
blaster.start();
|
|
123
|
+
} else {
|
|
124
|
+
blaster.resize();
|
|
125
|
+
}
|
|
126
|
+
const current = update4.view.state.selection.main.head;
|
|
127
|
+
if (current !== last) {
|
|
128
|
+
last = current;
|
|
129
|
+
const { element, point } = getPoint(update4.view, current);
|
|
130
|
+
if (element && point) {
|
|
131
|
+
blaster.spawn({
|
|
132
|
+
element,
|
|
133
|
+
point
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
// Document changed.
|
|
139
|
+
StateField.define({
|
|
140
|
+
create: () => null,
|
|
141
|
+
update: (_value, transaction) => {
|
|
142
|
+
if (blaster && transaction.docChanged) {
|
|
143
|
+
const view = EditorView2.findFromDOM(blaster.node);
|
|
144
|
+
const { element, point } = getPoint(view, transaction.selection.main.head);
|
|
145
|
+
if (element && point) {
|
|
146
|
+
blaster.spawn({
|
|
147
|
+
element,
|
|
148
|
+
point
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}),
|
|
155
|
+
keymap2.of([
|
|
156
|
+
{
|
|
157
|
+
any: (view, event) => {
|
|
158
|
+
if (blaster && event.key === "Enter" && event.shiftKey) {
|
|
159
|
+
blaster.shake({
|
|
160
|
+
time: 0.4
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
])
|
|
167
|
+
];
|
|
168
|
+
};
|
|
169
|
+
var Blaster = class {
|
|
170
|
+
constructor(_node, _options) {
|
|
171
|
+
this._node = _node;
|
|
172
|
+
this._options = _options;
|
|
173
|
+
this._running = false;
|
|
174
|
+
this._shakeTime = 0;
|
|
175
|
+
this._shakeTimeMax = 0;
|
|
176
|
+
this._particles = [];
|
|
177
|
+
this._particlePointer = 0;
|
|
178
|
+
this._lastPoint = {
|
|
179
|
+
x: 0,
|
|
180
|
+
y: 0
|
|
181
|
+
};
|
|
182
|
+
this.shake = throttle(({ time }) => {
|
|
183
|
+
this._shakeTime = this._shakeTimeMax;
|
|
184
|
+
this._shakeTimeMax = time;
|
|
185
|
+
}, 100);
|
|
186
|
+
this.spawn = throttle(({ element, point }) => {
|
|
187
|
+
const color = getRGBComponents(element, this._options.color);
|
|
188
|
+
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
189
|
+
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
190
|
+
this._lastPoint = point;
|
|
191
|
+
for (let i = numParticles; i--; i > 0) {
|
|
192
|
+
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
193
|
+
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
194
|
+
}
|
|
195
|
+
}, 100);
|
|
196
|
+
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
197
|
+
}
|
|
198
|
+
get node() {
|
|
199
|
+
return this._node;
|
|
200
|
+
}
|
|
201
|
+
initialize() {
|
|
202
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
203
|
+
F: __dxlog_file,
|
|
204
|
+
L: 152,
|
|
205
|
+
S: this,
|
|
206
|
+
A: [
|
|
207
|
+
"!this._canvas && !this._ctx",
|
|
208
|
+
""
|
|
209
|
+
]
|
|
210
|
+
});
|
|
211
|
+
this._canvas = document.createElement("canvas");
|
|
212
|
+
this._canvas.id = "code-blast-canvas";
|
|
213
|
+
this._canvas.style.position = "absolute";
|
|
214
|
+
this._canvas.style.zIndex = "0";
|
|
215
|
+
this._canvas.style.pointerEvents = "none";
|
|
216
|
+
this._ctx = this._canvas.getContext("2d");
|
|
217
|
+
const parent = this._node.parentElement?.parentElement;
|
|
218
|
+
parent?.appendChild(this._canvas);
|
|
219
|
+
this.resize();
|
|
220
|
+
}
|
|
221
|
+
destroy() {
|
|
222
|
+
this.stop();
|
|
223
|
+
if (this._canvas) {
|
|
224
|
+
this._canvas.remove();
|
|
225
|
+
this._canvas = void 0;
|
|
226
|
+
this._ctx = void 0;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
resize() {
|
|
230
|
+
if (this._node.parentElement && this._canvas) {
|
|
231
|
+
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
232
|
+
this._canvas.style.top = `${y}px`;
|
|
233
|
+
this._canvas.style.left = `${x}px`;
|
|
234
|
+
this._canvas.width = width;
|
|
235
|
+
this._canvas.height = height;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
start() {
|
|
239
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
240
|
+
F: __dxlog_file,
|
|
241
|
+
L: 191,
|
|
242
|
+
S: this,
|
|
243
|
+
A: [
|
|
244
|
+
"this._canvas && this._ctx",
|
|
245
|
+
""
|
|
246
|
+
]
|
|
247
|
+
});
|
|
248
|
+
this._running = true;
|
|
249
|
+
this.loop();
|
|
250
|
+
}
|
|
251
|
+
stop() {
|
|
252
|
+
this._running = false;
|
|
253
|
+
this._node.style.transform = "translate(0px, 0px)";
|
|
254
|
+
}
|
|
255
|
+
loop() {
|
|
256
|
+
if (!this._running || !this._canvas || !this._ctx) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
this._ctx.clearRect(0, 0, this._canvas.width ?? 0, this._canvas.height ?? 0);
|
|
260
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
261
|
+
this._lastTime ??= now;
|
|
262
|
+
const dt = (now - this._lastTime) / 1e3;
|
|
263
|
+
this._lastTime = now;
|
|
264
|
+
if (this._shakeTime > 0) {
|
|
265
|
+
this._shakeTime -= dt;
|
|
266
|
+
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
267
|
+
const shakeX = random(-magnitude, magnitude);
|
|
268
|
+
const shakeY = random(-magnitude, magnitude);
|
|
269
|
+
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
270
|
+
}
|
|
271
|
+
this.drawParticles();
|
|
272
|
+
requestAnimationFrame(this.loop.bind(this));
|
|
273
|
+
}
|
|
274
|
+
drawParticles() {
|
|
275
|
+
for (let i = this._particles.length; i--; i > 0) {
|
|
276
|
+
const particle = this._particles[i];
|
|
277
|
+
if (!particle) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (particle.alpha < 0.01 || particle.size <= 0.5) {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
this._effect.update(this._ctx, particle);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var Effect = class {
|
|
288
|
+
constructor(_options) {
|
|
289
|
+
this._options = _options;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
var Effect1 = class extends Effect {
|
|
293
|
+
create(x, y, color) {
|
|
294
|
+
return {
|
|
295
|
+
x,
|
|
296
|
+
y: y + 10,
|
|
297
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
298
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
299
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
300
|
+
color,
|
|
301
|
+
alpha: 1
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
update(ctx, particle) {
|
|
305
|
+
particle.vy += this._options.particleGravity;
|
|
306
|
+
particle.x += particle.vx;
|
|
307
|
+
particle.y += particle.vy;
|
|
308
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
309
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
310
|
+
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
var Effect2 = class extends Effect {
|
|
314
|
+
create(x, y, color) {
|
|
315
|
+
return {
|
|
316
|
+
x,
|
|
317
|
+
y: y + 10,
|
|
318
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
319
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
320
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
321
|
+
color,
|
|
322
|
+
alpha: 1,
|
|
323
|
+
theta: random(0, 360) * Math.PI / 180,
|
|
324
|
+
drag: 0.92,
|
|
325
|
+
wander: 0.15
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
update(ctx, particle) {
|
|
329
|
+
particle.vy += this._options.particleGravity;
|
|
330
|
+
particle.x += particle.vx;
|
|
331
|
+
particle.y += particle.vy;
|
|
332
|
+
particle.vx *= particle.drag;
|
|
333
|
+
particle.vy *= particle.drag;
|
|
334
|
+
particle.theta += random(-0.5, 0.5);
|
|
335
|
+
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
336
|
+
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
337
|
+
particle.size *= this._options.particleShrinkRate;
|
|
338
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
339
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
340
|
+
ctx.beginPath();
|
|
341
|
+
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
342
|
+
ctx.fill();
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
function throttle(callback, limit) {
|
|
346
|
+
let wait = false;
|
|
347
|
+
return function(...args) {
|
|
348
|
+
if (!wait) {
|
|
349
|
+
callback.apply(this, args);
|
|
350
|
+
wait = true;
|
|
351
|
+
setTimeout(() => {
|
|
352
|
+
wait = false;
|
|
353
|
+
}, limit);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
var getRGBComponents = (node, color) => {
|
|
358
|
+
if (typeof color === "function") {
|
|
359
|
+
return color();
|
|
360
|
+
}
|
|
361
|
+
const bgColor = getComputedStyle(node).color;
|
|
362
|
+
if (bgColor) {
|
|
363
|
+
const x = bgColor.match(/(\d+), (\d+), (\d+)/)?.slice(1);
|
|
364
|
+
if (x) {
|
|
365
|
+
return x;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return [
|
|
369
|
+
50,
|
|
370
|
+
50,
|
|
371
|
+
50
|
|
372
|
+
];
|
|
373
|
+
};
|
|
374
|
+
var random = (min, max) => {
|
|
375
|
+
if (!max) {
|
|
376
|
+
max = min;
|
|
377
|
+
min = 0;
|
|
378
|
+
}
|
|
379
|
+
return min + ~~(Math.random() * (max - min + 1));
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
|
|
383
|
+
import { keymap as keymap3 } from "@codemirror/view";
|
|
384
|
+
var defaultItems = [
|
|
385
|
+
"hello world!",
|
|
386
|
+
"this is a test.",
|
|
387
|
+
"this is [DXOS](https://dxos.org)"
|
|
388
|
+
];
|
|
389
|
+
var demo = ({ delay = 75, items = defaultItems } = {}) => {
|
|
390
|
+
let t;
|
|
391
|
+
let idx = 0;
|
|
392
|
+
return [
|
|
393
|
+
keymap3.of([
|
|
394
|
+
{
|
|
395
|
+
// Reset.
|
|
396
|
+
key: "alt-meta-'",
|
|
397
|
+
run: (view) => {
|
|
398
|
+
clearTimeout(t);
|
|
399
|
+
idx = 0;
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
// Next prompt.
|
|
405
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
|
406
|
+
key: "shift-meta-'",
|
|
407
|
+
run: (view) => {
|
|
408
|
+
clearTimeout(t);
|
|
409
|
+
const text = items[idx++];
|
|
410
|
+
if (idx === items?.length) {
|
|
411
|
+
idx = 0;
|
|
412
|
+
}
|
|
413
|
+
let i = 0;
|
|
414
|
+
const insert = (d = 0) => {
|
|
415
|
+
t = setTimeout(() => {
|
|
416
|
+
const pos = view.state.selection.main.head;
|
|
417
|
+
view.dispatch({
|
|
418
|
+
changes: {
|
|
419
|
+
from: pos,
|
|
420
|
+
insert: text[i++]
|
|
421
|
+
},
|
|
422
|
+
selection: {
|
|
423
|
+
anchor: pos + 1
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
if (i < text.length) {
|
|
427
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
428
|
+
}
|
|
429
|
+
}, d);
|
|
430
|
+
};
|
|
431
|
+
insert();
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
])
|
|
436
|
+
];
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
|
|
440
|
+
import { keymap as keymap4, Decoration, EditorView as EditorView3, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
|
|
441
|
+
import { debounce } from "@dxos/async";
|
|
442
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
443
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
|
|
444
|
+
var styles = EditorView3.baseTheme({
|
|
445
|
+
"& .cm-bookmark": {
|
|
446
|
+
cursor: "pointer",
|
|
447
|
+
margin: "4px",
|
|
448
|
+
padding: "4px",
|
|
449
|
+
backgroundColor: "yellow"
|
|
450
|
+
},
|
|
451
|
+
"& .cm-bookmark-selected": {
|
|
452
|
+
backgroundColor: "orange"
|
|
453
|
+
}
|
|
454
|
+
});
|
|
61
455
|
var BookmarkWidget = class extends WidgetType {
|
|
62
|
-
constructor(_pos, _id) {
|
|
456
|
+
constructor(_pos, _id, _handleClick) {
|
|
63
457
|
super();
|
|
64
458
|
this._pos = _pos;
|
|
65
459
|
this._id = _id;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
460
|
+
this._handleClick = _handleClick;
|
|
461
|
+
invariant2(this._id, void 0, {
|
|
462
|
+
F: __dxlog_file2,
|
|
463
|
+
L: 37,
|
|
69
464
|
S: this,
|
|
70
465
|
A: [
|
|
71
466
|
"this._id",
|
|
@@ -76,30 +471,25 @@ var BookmarkWidget = class extends WidgetType {
|
|
|
76
471
|
eq(other) {
|
|
77
472
|
return this._id === other._id;
|
|
78
473
|
}
|
|
79
|
-
// TODO(burdon): Click to select.
|
|
80
474
|
toDOM() {
|
|
81
475
|
const span = document.createElement("span");
|
|
82
476
|
span.className = "cm-bookmark";
|
|
83
|
-
span.textContent = "\
|
|
477
|
+
span.textContent = "\xA7";
|
|
478
|
+
span.onclick = () => this._handleClick();
|
|
84
479
|
return span;
|
|
85
480
|
}
|
|
86
481
|
};
|
|
87
|
-
var styles = EditorView2.baseTheme({
|
|
88
|
-
"& .cm-bookmark": {
|
|
89
|
-
cursor: "pointer",
|
|
90
|
-
margin: "4px",
|
|
91
|
-
padding: "4px",
|
|
92
|
-
backgroundColor: "yellow"
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
482
|
var comments = (options = {}) => {
|
|
483
|
+
let active;
|
|
96
484
|
const bookmarkMatcher = new MatchDecorator({
|
|
97
485
|
regexp: /\[\^(\w+)\]/g,
|
|
98
486
|
decoration: (match, view, pos) => {
|
|
99
487
|
const id = match[1];
|
|
100
488
|
return Decoration.replace({
|
|
101
489
|
id,
|
|
102
|
-
widget: new BookmarkWidget(pos, id)
|
|
490
|
+
widget: new BookmarkWidget(pos, id, () => handleUpdate({
|
|
491
|
+
active: id
|
|
492
|
+
}))
|
|
103
493
|
});
|
|
104
494
|
}
|
|
105
495
|
});
|
|
@@ -107,19 +497,22 @@ var comments = (options = {}) => {
|
|
|
107
497
|
constructor(view) {
|
|
108
498
|
this.bookmarks = bookmarkMatcher.createDeco(view);
|
|
109
499
|
}
|
|
110
|
-
update(
|
|
111
|
-
this.bookmarks = bookmarkMatcher.updateDeco(
|
|
500
|
+
update(update4) {
|
|
501
|
+
this.bookmarks = bookmarkMatcher.updateDeco(update4, this.bookmarks);
|
|
112
502
|
}
|
|
113
503
|
}, {
|
|
114
504
|
decorations: (instance) => instance.bookmarks,
|
|
115
|
-
provide: (plugin) =>
|
|
505
|
+
provide: (plugin) => EditorView3.atomicRanges.of((view) => {
|
|
116
506
|
return view.plugin(plugin)?.bookmarks || Decoration.none;
|
|
117
507
|
})
|
|
118
508
|
});
|
|
509
|
+
const handleUpdate = debounce((data) => {
|
|
510
|
+
options.onUpdate?.(data);
|
|
511
|
+
}, 200);
|
|
119
512
|
return [
|
|
120
|
-
|
|
513
|
+
keymap4.of([
|
|
121
514
|
{
|
|
122
|
-
key: options?.key ?? "
|
|
515
|
+
key: options?.key ?? "shift-meta-c",
|
|
123
516
|
run: (view) => {
|
|
124
517
|
const id = options.onCreate?.();
|
|
125
518
|
if (id) {
|
|
@@ -142,42 +535,108 @@ var comments = (options = {}) => {
|
|
|
142
535
|
]),
|
|
143
536
|
bookmarks,
|
|
144
537
|
// Monitor cursor movement.
|
|
145
|
-
|
|
146
|
-
|
|
538
|
+
EditorView3.updateListener.of((update4) => {
|
|
539
|
+
active = void 0;
|
|
540
|
+
if (!options.onUpdate) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const view = update4.view;
|
|
147
544
|
const pos = view.state.selection.main.head;
|
|
148
545
|
const decorations = [];
|
|
149
546
|
const rangeSet = view.plugin(bookmarks)?.bookmarks;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
547
|
+
let closest = Infinity;
|
|
548
|
+
const { from, to } = (
|
|
549
|
+
/* view.visibleRanges?.[0] ?? */
|
|
550
|
+
{
|
|
551
|
+
from: 0,
|
|
552
|
+
to: view.state.doc.length
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
rangeSet?.between(from, to, (from2, to2, value) => {
|
|
556
|
+
decorations.push({
|
|
557
|
+
from: from2,
|
|
558
|
+
to: to2,
|
|
559
|
+
value
|
|
560
|
+
});
|
|
561
|
+
const d = Math.min(Math.abs(pos - from2), Math.abs(pos - to2));
|
|
562
|
+
if (d < closest) {
|
|
563
|
+
active = value.spec.id;
|
|
564
|
+
closest = d;
|
|
157
565
|
}
|
|
158
566
|
});
|
|
159
567
|
if (decorations.length) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
});
|
|
169
|
-
}
|
|
568
|
+
handleUpdate({
|
|
569
|
+
active,
|
|
570
|
+
items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
|
|
571
|
+
id,
|
|
572
|
+
pos: from2,
|
|
573
|
+
location: view.coordsAtPos(from2)
|
|
574
|
+
}))
|
|
575
|
+
});
|
|
170
576
|
}
|
|
171
577
|
}),
|
|
172
578
|
styles
|
|
173
579
|
];
|
|
174
580
|
};
|
|
175
581
|
|
|
176
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/
|
|
582
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/image.ts
|
|
177
583
|
import { syntaxTree } from "@codemirror/language";
|
|
178
|
-
import { RangeSetBuilder, StateField } from "@codemirror/state";
|
|
179
|
-
import { Decoration as Decoration2, EditorView as
|
|
180
|
-
var
|
|
584
|
+
import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
|
|
585
|
+
import { Decoration as Decoration2, EditorView as EditorView4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
586
|
+
var image = (options = {}) => {
|
|
587
|
+
return StateField2.define({
|
|
588
|
+
create: (state) => update(state, options),
|
|
589
|
+
update: (_, tr) => update(tr.state, options),
|
|
590
|
+
provide: (field) => EditorView4.decorations.from(field)
|
|
591
|
+
});
|
|
592
|
+
};
|
|
593
|
+
var update = (state, options) => {
|
|
594
|
+
const builder = new RangeSetBuilder();
|
|
595
|
+
const cursor = state.selection.main.head;
|
|
596
|
+
syntaxTree(state).iterate({
|
|
597
|
+
enter: (node) => {
|
|
598
|
+
if (node.name === "Image") {
|
|
599
|
+
const urlNode = node.node.getChild("URL");
|
|
600
|
+
if (urlNode) {
|
|
601
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
602
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
603
|
+
builder.add(hide ? node.from : node.to, node.to, Decoration2.replace({
|
|
604
|
+
widget: new ImageWidget(url)
|
|
605
|
+
}));
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
return builder.finish();
|
|
611
|
+
};
|
|
612
|
+
var ImageWidget = class extends WidgetType2 {
|
|
613
|
+
constructor(_url) {
|
|
614
|
+
super();
|
|
615
|
+
this._url = _url;
|
|
616
|
+
}
|
|
617
|
+
eq(other) {
|
|
618
|
+
return this._url === other?._url;
|
|
619
|
+
}
|
|
620
|
+
toDOM(view) {
|
|
621
|
+
const img = document.createElement("img");
|
|
622
|
+
img.setAttribute("src", this._url);
|
|
623
|
+
img.setAttribute("class", "cm-image");
|
|
624
|
+
return img;
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
|
|
629
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
630
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
|
|
631
|
+
import { Decoration as Decoration3, EditorView as EditorView5, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
632
|
+
var link = (options = {}) => {
|
|
633
|
+
return StateField3.define({
|
|
634
|
+
create: (state) => update2(state, options),
|
|
635
|
+
update: (_, tr) => update2(tr.state, options),
|
|
636
|
+
provide: (field) => EditorView5.decorations.from(field)
|
|
637
|
+
});
|
|
638
|
+
};
|
|
639
|
+
var LinkButton = class extends WidgetType3 {
|
|
181
640
|
constructor(_pos, _url, _onAttach) {
|
|
182
641
|
super();
|
|
183
642
|
this._pos = _pos;
|
|
@@ -193,7 +652,7 @@ var LinkButton = class extends WidgetType2 {
|
|
|
193
652
|
return el;
|
|
194
653
|
}
|
|
195
654
|
};
|
|
196
|
-
var LinkText = class extends
|
|
655
|
+
var LinkText = class extends WidgetType3 {
|
|
197
656
|
constructor(_pos, _text, _url) {
|
|
198
657
|
super();
|
|
199
658
|
this._pos = _pos;
|
|
@@ -223,10 +682,10 @@ var LinkText = class extends WidgetType2 {
|
|
|
223
682
|
return link2;
|
|
224
683
|
}
|
|
225
684
|
};
|
|
226
|
-
var
|
|
227
|
-
const builder = new
|
|
685
|
+
var update2 = (state, options) => {
|
|
686
|
+
const builder = new RangeSetBuilder2();
|
|
228
687
|
const cursor = state.selection.main.head;
|
|
229
|
-
|
|
688
|
+
syntaxTree2(state).iterate({
|
|
230
689
|
enter: (node) => {
|
|
231
690
|
if (node.name === "Link") {
|
|
232
691
|
const marks = node.node.getChildren("LinkMark");
|
|
@@ -236,13 +695,13 @@ var update = (state, options) => {
|
|
|
236
695
|
if (!url) {
|
|
237
696
|
return false;
|
|
238
697
|
}
|
|
239
|
-
if (cursor < node.from || cursor > node.to) {
|
|
240
|
-
builder.add(node.from, node.to,
|
|
698
|
+
if (state.readOnly || cursor < node.from || cursor > node.to) {
|
|
699
|
+
builder.add(node.from, node.to, Decoration3.replace({
|
|
241
700
|
widget: new LinkText(node.from, text, options.link ? url : void 0)
|
|
242
701
|
}));
|
|
243
702
|
}
|
|
244
703
|
if (options.onRender) {
|
|
245
|
-
builder.add(node.to, node.to,
|
|
704
|
+
builder.add(node.to, node.to, Decoration3.replace({
|
|
246
705
|
widget: new LinkButton(node.from, url, options.onRender)
|
|
247
706
|
}));
|
|
248
707
|
}
|
|
@@ -252,52 +711,71 @@ var update = (state, options) => {
|
|
|
252
711
|
});
|
|
253
712
|
return builder.finish();
|
|
254
713
|
};
|
|
255
|
-
var link = (options = {}) => {
|
|
256
|
-
return StateField.define({
|
|
257
|
-
create: (state) => update(state, options),
|
|
258
|
-
update: (_, tr) => update(tr.state, options),
|
|
259
|
-
provide: (field) => EditorView3.decorations.from(field)
|
|
260
|
-
});
|
|
261
|
-
};
|
|
262
714
|
|
|
263
715
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
|
|
264
|
-
import { StateField as
|
|
265
|
-
var listener = (onChange) =>
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
716
|
+
import { StateField as StateField4 } from "@codemirror/state";
|
|
717
|
+
var listener = ({ onChange }) => {
|
|
718
|
+
return StateField4.define({
|
|
719
|
+
create: () => null,
|
|
720
|
+
update: (_value, transaction) => {
|
|
721
|
+
if (transaction.docChanged && onChange) {
|
|
722
|
+
onChange(transaction.newDoc.toString());
|
|
723
|
+
}
|
|
724
|
+
return null;
|
|
270
725
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
});
|
|
726
|
+
});
|
|
727
|
+
};
|
|
274
728
|
|
|
275
729
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
276
730
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
277
|
-
import {
|
|
731
|
+
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
278
732
|
import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
|
|
279
733
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
280
734
|
import { languages } from "@codemirror/language-data";
|
|
281
735
|
import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
|
|
282
736
|
import { EditorState } from "@codemirror/state";
|
|
283
737
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
284
|
-
import { crosshairCursor, drawSelection, dropCursor, EditorView as
|
|
738
|
+
import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView6, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap5, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
|
|
285
739
|
|
|
286
740
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
|
|
287
741
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
288
742
|
import { HighlightStyle } from "@codemirror/language";
|
|
289
743
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
744
|
+
import { Table } from "@lezer/markdown";
|
|
290
745
|
import get from "lodash.get";
|
|
746
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
291
747
|
|
|
292
748
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
293
749
|
import { mx } from "@dxos/react-ui-theme";
|
|
294
|
-
var
|
|
295
|
-
1:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
750
|
+
var headings = {
|
|
751
|
+
1: [
|
|
752
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
753
|
+
"-ml-1.5"
|
|
754
|
+
],
|
|
755
|
+
2: [
|
|
756
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
757
|
+
"-ml-1.5"
|
|
758
|
+
],
|
|
759
|
+
3: [
|
|
760
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
761
|
+
"-ml-1.5"
|
|
762
|
+
],
|
|
763
|
+
4: [
|
|
764
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
765
|
+
"-ml-[5px]"
|
|
766
|
+
],
|
|
767
|
+
5: [
|
|
768
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
769
|
+
"-ml-[5px]"
|
|
770
|
+
],
|
|
771
|
+
6: [
|
|
772
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
773
|
+
"-ml-[4px]"
|
|
774
|
+
]
|
|
775
|
+
};
|
|
776
|
+
var heading = (level, readonly) => {
|
|
777
|
+
const [style, offset] = headings[level];
|
|
778
|
+
return mx(style, readonly && offset);
|
|
301
779
|
};
|
|
302
780
|
var light = "text-neutral-200 dark:text-neutral-800";
|
|
303
781
|
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
@@ -308,7 +786,7 @@ var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
|
308
786
|
var codeMark = "font-mono text-primary-500";
|
|
309
787
|
var inlineUrl = mx(code, "px-1");
|
|
310
788
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
311
|
-
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-
|
|
789
|
+
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800";
|
|
312
790
|
|
|
313
791
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
314
792
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
@@ -327,159 +805,193 @@ var markdownTags = {
|
|
|
327
805
|
LinkReference: Tag.define(),
|
|
328
806
|
ListMark: Tag.define(),
|
|
329
807
|
QuoteMark: Tag.define(),
|
|
330
|
-
URL: Tag.define()
|
|
808
|
+
URL: Tag.define(),
|
|
809
|
+
// Custom.
|
|
810
|
+
TableCell: Tag.define()
|
|
331
811
|
};
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
{
|
|
339
|
-
tag: [
|
|
340
|
-
tags.keyword,
|
|
341
|
-
tags.name,
|
|
342
|
-
tags.deleted,
|
|
343
|
-
tags.character,
|
|
344
|
-
tags.propertyName,
|
|
345
|
-
tags.macroName,
|
|
346
|
-
tags.color,
|
|
347
|
-
tags.constant(tags.name),
|
|
348
|
-
tags.standard(tags.name),
|
|
349
|
-
tags.definition(tags.name),
|
|
350
|
-
tags.separator,
|
|
351
|
-
tags.typeName,
|
|
352
|
-
tags.className,
|
|
353
|
-
tags.number,
|
|
354
|
-
tags.changed,
|
|
355
|
-
tags.annotation,
|
|
356
|
-
tags.modifier,
|
|
357
|
-
tags.self,
|
|
358
|
-
tags.namespace,
|
|
359
|
-
tags.operator,
|
|
360
|
-
tags.operatorKeyword,
|
|
361
|
-
tags.escape,
|
|
362
|
-
tags.regexp,
|
|
363
|
-
tags.special(tags.string),
|
|
364
|
-
tags.meta,
|
|
365
|
-
tags.comment,
|
|
366
|
-
tags.atom,
|
|
367
|
-
tags.bool,
|
|
368
|
-
tags.special(tags.variableName),
|
|
369
|
-
tags.processingInstruction,
|
|
370
|
-
tags.string,
|
|
371
|
-
tags.inserted,
|
|
372
|
-
tags.invalid
|
|
373
|
-
],
|
|
374
|
-
color: "inherit !important"
|
|
375
|
-
},
|
|
376
|
-
// Markdown marks.
|
|
377
|
-
{
|
|
378
|
-
tag: [
|
|
379
|
-
tags.meta,
|
|
380
|
-
tags.processingInstruction,
|
|
381
|
-
markdownTags.CodeMark,
|
|
382
|
-
markdownTags.EmphasisMark,
|
|
383
|
-
markdownTags.HeaderMark,
|
|
384
|
-
markdownTags.LinkLabel,
|
|
385
|
-
markdownTags.LinkReference,
|
|
386
|
-
markdownTags.ListMark,
|
|
387
|
-
markdownTags.QuoteMark
|
|
388
|
-
],
|
|
389
|
-
class: mark
|
|
390
|
-
},
|
|
391
|
-
// Headings.
|
|
392
|
-
{
|
|
393
|
-
tag: tags.heading1,
|
|
394
|
-
class: heading[1]
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
tag: tags.heading2,
|
|
398
|
-
class: heading[2]
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
tag: tags.heading3,
|
|
402
|
-
class: heading[3]
|
|
403
|
-
},
|
|
404
|
-
{
|
|
405
|
-
tag: tags.heading4,
|
|
406
|
-
class: heading[4]
|
|
407
|
-
},
|
|
408
|
-
{
|
|
409
|
-
tag: tags.heading5,
|
|
410
|
-
class: heading[5]
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
tag: tags.heading6,
|
|
414
|
-
class: heading[6]
|
|
415
|
-
},
|
|
416
|
-
// Emphasis.
|
|
417
|
-
{
|
|
418
|
-
tag: tags.emphasis,
|
|
419
|
-
class: italic
|
|
420
|
-
},
|
|
421
|
-
{
|
|
422
|
-
tag: tags.strong,
|
|
423
|
-
class: bold
|
|
424
|
-
},
|
|
425
|
-
{
|
|
426
|
-
tag: tags.strikethrough,
|
|
427
|
-
class: strikethrough
|
|
428
|
-
},
|
|
429
|
-
// Naked URLs.
|
|
430
|
-
{
|
|
431
|
-
tag: [
|
|
432
|
-
markdownTags.URL
|
|
433
|
-
],
|
|
434
|
-
class: inlineUrl
|
|
435
|
-
},
|
|
436
|
-
// E.g., code block language (after ```).
|
|
437
|
-
{
|
|
438
|
-
tag: [
|
|
439
|
-
tags.function(tags.variableName),
|
|
440
|
-
tags.labelName
|
|
441
|
-
],
|
|
442
|
-
class: codeMark
|
|
443
|
-
},
|
|
444
|
-
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
445
|
-
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
446
|
-
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
447
|
-
// the code, but all other CSS properties will be inherited.
|
|
448
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
449
|
-
{
|
|
450
|
-
tag: [
|
|
451
|
-
markdownTags.CodeText,
|
|
452
|
-
markdownTags.InlineCode
|
|
453
|
-
],
|
|
454
|
-
class: code
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
tag: [
|
|
458
|
-
markdownTags.QuoteMark
|
|
459
|
-
],
|
|
460
|
-
class: blockquote
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
tag: [
|
|
464
|
-
markdownTags.HorizontalRule
|
|
465
|
-
],
|
|
466
|
-
class: horizontalRule
|
|
467
|
-
}
|
|
468
|
-
], {
|
|
469
|
-
scope: markdownLanguage,
|
|
470
|
-
all: {
|
|
471
|
-
fontFamily: get(tokens, "fontFamily.body", []).join(",")
|
|
812
|
+
Table.defineNodes?.forEach((node) => {
|
|
813
|
+
switch (node?.name) {
|
|
814
|
+
case "TableCell": {
|
|
815
|
+
node.style = markdownTags.TableCell;
|
|
816
|
+
break;
|
|
817
|
+
}
|
|
472
818
|
}
|
|
473
819
|
});
|
|
820
|
+
var markdownTagsExtensions = [
|
|
821
|
+
Table,
|
|
822
|
+
{
|
|
823
|
+
props: [
|
|
824
|
+
styleTags(markdownTags)
|
|
825
|
+
]
|
|
826
|
+
}
|
|
827
|
+
];
|
|
828
|
+
var markdownHighlightStyle = (readonly) => {
|
|
829
|
+
return HighlightStyle.define([
|
|
830
|
+
{
|
|
831
|
+
tag: [
|
|
832
|
+
tags.keyword,
|
|
833
|
+
tags.name,
|
|
834
|
+
tags.deleted,
|
|
835
|
+
tags.character,
|
|
836
|
+
tags.propertyName,
|
|
837
|
+
tags.macroName,
|
|
838
|
+
tags.color,
|
|
839
|
+
tags.constant(tags.name),
|
|
840
|
+
tags.standard(tags.name),
|
|
841
|
+
tags.definition(tags.name),
|
|
842
|
+
tags.separator,
|
|
843
|
+
tags.typeName,
|
|
844
|
+
tags.className,
|
|
845
|
+
tags.number,
|
|
846
|
+
tags.changed,
|
|
847
|
+
tags.annotation,
|
|
848
|
+
tags.modifier,
|
|
849
|
+
tags.self,
|
|
850
|
+
tags.namespace,
|
|
851
|
+
tags.operator,
|
|
852
|
+
tags.operatorKeyword,
|
|
853
|
+
tags.escape,
|
|
854
|
+
tags.regexp,
|
|
855
|
+
tags.special(tags.string),
|
|
856
|
+
tags.meta,
|
|
857
|
+
tags.comment,
|
|
858
|
+
tags.atom,
|
|
859
|
+
tags.bool,
|
|
860
|
+
tags.special(tags.variableName),
|
|
861
|
+
tags.processingInstruction,
|
|
862
|
+
tags.string,
|
|
863
|
+
tags.inserted,
|
|
864
|
+
tags.invalid
|
|
865
|
+
],
|
|
866
|
+
color: "inherit !important"
|
|
867
|
+
},
|
|
868
|
+
// Markdown marks.
|
|
869
|
+
{
|
|
870
|
+
tag: [
|
|
871
|
+
tags.meta,
|
|
872
|
+
tags.processingInstruction,
|
|
873
|
+
markdownTags.LinkLabel,
|
|
874
|
+
markdownTags.LinkReference,
|
|
875
|
+
markdownTags.ListMark
|
|
876
|
+
],
|
|
877
|
+
class: mark
|
|
878
|
+
},
|
|
879
|
+
// Markdown marks.
|
|
880
|
+
{
|
|
881
|
+
tag: [
|
|
882
|
+
markdownTags.CodeMark,
|
|
883
|
+
markdownTags.HeaderMark,
|
|
884
|
+
markdownTags.QuoteMark,
|
|
885
|
+
markdownTags.EmphasisMark
|
|
886
|
+
],
|
|
887
|
+
class: readonly ? "hidden" : mark
|
|
888
|
+
},
|
|
889
|
+
// E.g., code block language (after ```).
|
|
890
|
+
{
|
|
891
|
+
tag: [
|
|
892
|
+
tags.function(tags.variableName),
|
|
893
|
+
tags.labelName
|
|
894
|
+
],
|
|
895
|
+
class: readonly ? "hidden" : codeMark
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
tag: [
|
|
899
|
+
tags.monospace
|
|
900
|
+
],
|
|
901
|
+
class: "font-mono"
|
|
902
|
+
},
|
|
903
|
+
// Headings.
|
|
904
|
+
{
|
|
905
|
+
tag: tags.heading1,
|
|
906
|
+
class: heading(1, readonly)
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
tag: tags.heading2,
|
|
910
|
+
class: heading(2, readonly)
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
tag: tags.heading3,
|
|
914
|
+
class: heading(3, readonly)
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
tag: tags.heading4,
|
|
918
|
+
class: heading(4, readonly)
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
tag: tags.heading5,
|
|
922
|
+
class: heading(5, readonly)
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
tag: tags.heading6,
|
|
926
|
+
class: heading(6, readonly)
|
|
927
|
+
},
|
|
928
|
+
// Emphasis.
|
|
929
|
+
{
|
|
930
|
+
tag: tags.emphasis,
|
|
931
|
+
class: italic
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
tag: tags.strong,
|
|
935
|
+
class: bold
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
tag: tags.strikethrough,
|
|
939
|
+
class: strikethrough
|
|
940
|
+
},
|
|
941
|
+
// Naked URLs.
|
|
942
|
+
{
|
|
943
|
+
tag: [
|
|
944
|
+
markdownTags.URL
|
|
945
|
+
],
|
|
946
|
+
class: inlineUrl
|
|
947
|
+
},
|
|
948
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
949
|
+
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
950
|
+
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
951
|
+
// the code, but all other CSS properties will be inherited.
|
|
952
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
953
|
+
{
|
|
954
|
+
tag: [
|
|
955
|
+
markdownTags.CodeText,
|
|
956
|
+
markdownTags.InlineCode
|
|
957
|
+
],
|
|
958
|
+
class: code
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
tag: [
|
|
962
|
+
markdownTags.QuoteMark
|
|
963
|
+
],
|
|
964
|
+
class: blockquote
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
tag: [
|
|
968
|
+
markdownTags.HorizontalRule
|
|
969
|
+
],
|
|
970
|
+
class: mx2(horizontalRule, readonly && "-indent-[100rem]")
|
|
971
|
+
},
|
|
972
|
+
// TODO(burdon): Only if being edited.
|
|
973
|
+
{
|
|
974
|
+
tag: [
|
|
975
|
+
markdownTags.TableCell
|
|
976
|
+
],
|
|
977
|
+
class: "font-mono"
|
|
978
|
+
}
|
|
979
|
+
], {
|
|
980
|
+
scope: markdownLanguage,
|
|
981
|
+
all: {
|
|
982
|
+
fontFamily: get(tokens, "fontFamily.body", []).join(",")
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
};
|
|
474
986
|
|
|
475
987
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
476
|
-
var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
988
|
+
var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
477
989
|
return [
|
|
478
990
|
bracketMatching2(),
|
|
479
991
|
closeBrackets2(),
|
|
480
992
|
_placeholder && placeholder2(_placeholder),
|
|
481
993
|
EditorState.allowMultipleSelections.of(true),
|
|
482
|
-
|
|
994
|
+
EditorView6.lineWrapping,
|
|
483
995
|
crosshairCursor(),
|
|
484
996
|
dropCursor(),
|
|
485
997
|
drawSelection(),
|
|
@@ -490,16 +1002,7 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
490
1002
|
history(),
|
|
491
1003
|
indentOnInput(),
|
|
492
1004
|
rectangularSelection(),
|
|
493
|
-
|
|
494
|
-
keymap3.of([
|
|
495
|
-
...closeBracketsKeymap,
|
|
496
|
-
...defaultKeymap,
|
|
497
|
-
// ...foldKeymap,
|
|
498
|
-
// ...historyKeymap,
|
|
499
|
-
// ...lintKeymap,
|
|
500
|
-
...searchKeymap,
|
|
501
|
-
indentWithTab
|
|
502
|
-
]),
|
|
1005
|
+
customkeymap(),
|
|
503
1006
|
// Main extension.
|
|
504
1007
|
// https://github.com/codemirror/lang-markdown
|
|
505
1008
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -514,20 +1017,153 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
514
1017
|
codeLanguages: languages,
|
|
515
1018
|
// Parser extensions.
|
|
516
1019
|
extensions: [
|
|
517
|
-
// GFM
|
|
518
|
-
|
|
1020
|
+
// GFM provided by default.
|
|
1021
|
+
markdownTagsExtensions
|
|
519
1022
|
]
|
|
520
1023
|
}),
|
|
1024
|
+
// https://github.com/codemirror/theme-one-dark
|
|
1025
|
+
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
521
1026
|
// Custom styles.
|
|
522
|
-
syntaxHighlighting2(markdownHighlightStyle)
|
|
523
|
-
// TODO(thure): All but one rule here apply to both themes; rename or refactor.
|
|
524
|
-
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
|
|
1027
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
525
1028
|
].filter(Boolean);
|
|
526
1029
|
};
|
|
1030
|
+
var customkeymap = () => keymap5.of([
|
|
1031
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1032
|
+
indentWithTab,
|
|
1033
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1034
|
+
...standardKeymap,
|
|
1035
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1036
|
+
...historyKeymap,
|
|
1037
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1038
|
+
...closeBracketsKeymap,
|
|
1039
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1040
|
+
...searchKeymap
|
|
1041
|
+
]);
|
|
1042
|
+
|
|
1043
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/mention.ts
|
|
1044
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1045
|
+
var mention = ({ onSearch }) => {
|
|
1046
|
+
return autocompletion2({
|
|
1047
|
+
closeOnBlur: false,
|
|
1048
|
+
override: [
|
|
1049
|
+
(context) => {
|
|
1050
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
1051
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
1052
|
+
return null;
|
|
1053
|
+
}
|
|
1054
|
+
console.log(match);
|
|
1055
|
+
return {
|
|
1056
|
+
from: match.from,
|
|
1057
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
1058
|
+
label: `@${value}`
|
|
1059
|
+
}))
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
]
|
|
1063
|
+
});
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
|
|
1067
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1068
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
|
|
1069
|
+
import { Decoration as Decoration4, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1070
|
+
var table = (options = {}) => {
|
|
1071
|
+
return StateField5.define({
|
|
1072
|
+
create: (state) => update3(state, options),
|
|
1073
|
+
update: (_, tr) => update3(tr.state, options),
|
|
1074
|
+
provide: (field) => EditorView7.decorations.from(field)
|
|
1075
|
+
});
|
|
1076
|
+
};
|
|
1077
|
+
var update3 = (state, options) => {
|
|
1078
|
+
const builder = new RangeSetBuilder3();
|
|
1079
|
+
const cursor = state.selection.main.head;
|
|
1080
|
+
const tables = [];
|
|
1081
|
+
const getTable = () => tables[tables.length - 1];
|
|
1082
|
+
const getRow = () => {
|
|
1083
|
+
const table2 = getTable();
|
|
1084
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
1085
|
+
};
|
|
1086
|
+
syntaxTree3(state).iterate({
|
|
1087
|
+
enter: (node) => {
|
|
1088
|
+
switch (node.name) {
|
|
1089
|
+
case "Table": {
|
|
1090
|
+
tables.push({
|
|
1091
|
+
from: node.from,
|
|
1092
|
+
to: node.to
|
|
1093
|
+
});
|
|
1094
|
+
break;
|
|
1095
|
+
}
|
|
1096
|
+
case "TableHeader": {
|
|
1097
|
+
getTable().header = [];
|
|
1098
|
+
break;
|
|
1099
|
+
}
|
|
1100
|
+
case "TableRow": {
|
|
1101
|
+
(getTable().rows ??= []).push([]);
|
|
1102
|
+
break;
|
|
1103
|
+
}
|
|
1104
|
+
case "TableCell": {
|
|
1105
|
+
const row = getRow();
|
|
1106
|
+
if (row) {
|
|
1107
|
+
row.push(state.sliceDoc(node.from, node.to));
|
|
1108
|
+
} else {
|
|
1109
|
+
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
1110
|
+
}
|
|
1111
|
+
break;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
tables.forEach((table2) => {
|
|
1117
|
+
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
1118
|
+
hide && builder.add(table2.from, table2.to, Decoration4.replace({
|
|
1119
|
+
widget: new TableWidget(table2)
|
|
1120
|
+
}));
|
|
1121
|
+
});
|
|
1122
|
+
return builder.finish();
|
|
1123
|
+
};
|
|
1124
|
+
var TableWidget = class extends WidgetType4 {
|
|
1125
|
+
constructor(_table) {
|
|
1126
|
+
super();
|
|
1127
|
+
this._table = _table;
|
|
1128
|
+
}
|
|
1129
|
+
eq(other) {
|
|
1130
|
+
return this._table.from === other?._table?.from;
|
|
1131
|
+
}
|
|
1132
|
+
toDOM(view) {
|
|
1133
|
+
const table2 = document.createElement("table");
|
|
1134
|
+
{
|
|
1135
|
+
const header = table2.appendChild(document.createElement("thead"));
|
|
1136
|
+
const tr = header.appendChild(document.createElement("tr"));
|
|
1137
|
+
this._table.header?.forEach((cell) => {
|
|
1138
|
+
const th = document.createElement("th");
|
|
1139
|
+
th.setAttribute("class", "cm-table-head");
|
|
1140
|
+
tr.appendChild(th).textContent = cell;
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
{
|
|
1144
|
+
const body = table2.appendChild(document.createElement("tbody"));
|
|
1145
|
+
this._table.rows?.forEach((row) => {
|
|
1146
|
+
const tr = body.appendChild(document.createElement("tr"));
|
|
1147
|
+
row.forEach((cell) => {
|
|
1148
|
+
const td = document.createElement("td");
|
|
1149
|
+
td.setAttribute("class", "cm-table-cell");
|
|
1150
|
+
tr.appendChild(td).textContent = cell;
|
|
1151
|
+
});
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
return table2;
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
527
1157
|
|
|
528
1158
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
|
|
529
|
-
import { EditorView as
|
|
530
|
-
var
|
|
1159
|
+
import { EditorView as EditorView8, Decoration as Decoration5, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin2 } from "@codemirror/view";
|
|
1160
|
+
var styles2 = EditorView8.baseTheme({
|
|
1161
|
+
"& .cm-task-item": {
|
|
1162
|
+
paddingLeft: "4px",
|
|
1163
|
+
paddingRight: "8px"
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
var CheckboxWidget = class extends WidgetType5 {
|
|
531
1167
|
constructor(_pos, _checked, _indent, _onCheck) {
|
|
532
1168
|
super();
|
|
533
1169
|
this._pos = _pos;
|
|
@@ -546,30 +1182,29 @@ var CheckboxWidget = class extends WidgetType3 {
|
|
|
546
1182
|
const input = wrap.appendChild(document.createElement("input"));
|
|
547
1183
|
input.type = "checkbox";
|
|
548
1184
|
input.checked = this._checked;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
1185
|
+
if (!this._onCheck) {
|
|
1186
|
+
input.setAttribute("disabled", "true");
|
|
1187
|
+
}
|
|
1188
|
+
if (this._onCheck) {
|
|
1189
|
+
input.onchange = (event) => {
|
|
1190
|
+
this._onCheck?.(event.target.checked);
|
|
1191
|
+
return true;
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
553
1194
|
return wrap;
|
|
554
1195
|
}
|
|
555
1196
|
ignoreEvent() {
|
|
556
1197
|
return false;
|
|
557
1198
|
}
|
|
558
1199
|
};
|
|
559
|
-
var
|
|
560
|
-
"& .cm-task-item": {
|
|
561
|
-
paddingLeft: "4px",
|
|
562
|
-
paddingRight: "8px"
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
var tasklist = () => {
|
|
1200
|
+
var tasklist = (options = {}) => {
|
|
566
1201
|
const taskMatcher = new MatchDecorator2({
|
|
567
1202
|
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
568
1203
|
decoration: (match, view, pos) => {
|
|
569
1204
|
const indent = Math.floor(match[1].length / 2);
|
|
570
1205
|
const checked = match[2] === "x" || match[2] === "X";
|
|
571
|
-
return
|
|
572
|
-
widget: new CheckboxWidget(pos, checked, indent, (checked2) => {
|
|
1206
|
+
return Decoration5.replace({
|
|
1207
|
+
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
573
1208
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
574
1209
|
view.dispatch({
|
|
575
1210
|
changes: {
|
|
@@ -590,13 +1225,13 @@ var tasklist = () => {
|
|
|
590
1225
|
constructor(view) {
|
|
591
1226
|
this.tasks = taskMatcher.createDeco(view);
|
|
592
1227
|
}
|
|
593
|
-
update(
|
|
594
|
-
this.tasks = taskMatcher.updateDeco(
|
|
1228
|
+
update(update4) {
|
|
1229
|
+
this.tasks = taskMatcher.updateDeco(update4, this.tasks);
|
|
595
1230
|
}
|
|
596
1231
|
}, {
|
|
597
1232
|
decorations: (instance) => instance.tasks,
|
|
598
|
-
provide: (plugin) =>
|
|
599
|
-
return view.plugin(plugin)?.tasks ||
|
|
1233
|
+
provide: (plugin) => EditorView8.atomicRanges.of((view) => {
|
|
1234
|
+
return view.plugin(plugin)?.tasks || Decoration5.none;
|
|
600
1235
|
})
|
|
601
1236
|
});
|
|
602
1237
|
return [
|
|
@@ -763,8 +1398,51 @@ var defaultTheme = {
|
|
|
763
1398
|
"& .cm-tooltip": {
|
|
764
1399
|
border: "none"
|
|
765
1400
|
},
|
|
766
|
-
|
|
767
|
-
//
|
|
1401
|
+
"& .cm-tooltip-below": {},
|
|
1402
|
+
//
|
|
1403
|
+
// autocomplete
|
|
1404
|
+
//
|
|
1405
|
+
"& .cm-tooltip-autocomplete": {
|
|
1406
|
+
marginTop: "4px",
|
|
1407
|
+
marginLeft: "-3px"
|
|
1408
|
+
},
|
|
1409
|
+
"& .cm-tooltip-autocomplete ul li": {},
|
|
1410
|
+
"& .cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
1411
|
+
"& .cm-completionIcon": {
|
|
1412
|
+
display: "none"
|
|
1413
|
+
},
|
|
1414
|
+
"& .cm-completionLabel": {
|
|
1415
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
1416
|
+
},
|
|
1417
|
+
"& .cm-completionMatchedText": {
|
|
1418
|
+
textDecoration: "none"
|
|
1419
|
+
},
|
|
1420
|
+
//
|
|
1421
|
+
// widgets
|
|
1422
|
+
//
|
|
1423
|
+
"& .cm-widgetBuffer": {
|
|
1424
|
+
display: "none",
|
|
1425
|
+
height: 0
|
|
1426
|
+
},
|
|
1427
|
+
//
|
|
1428
|
+
// table
|
|
1429
|
+
//
|
|
1430
|
+
"& .cm-table-head": {
|
|
1431
|
+
padding: "2px 16px 2px 0px",
|
|
1432
|
+
borderBottom: `1px solid ${get2(tokens, "extend.colors.neutral.500")}`,
|
|
1433
|
+
fontWeight: 100,
|
|
1434
|
+
textAlign: "left",
|
|
1435
|
+
color: get2(tokens, "extend.colors.neutral.500")
|
|
1436
|
+
},
|
|
1437
|
+
"& .cm-table-cell": {
|
|
1438
|
+
padding: "2px 16px 2px 0px"
|
|
1439
|
+
},
|
|
1440
|
+
//
|
|
1441
|
+
// image
|
|
1442
|
+
//
|
|
1443
|
+
"& .cm-image": {
|
|
1444
|
+
margin: "0.5rem 0"
|
|
1445
|
+
},
|
|
768
1446
|
//
|
|
769
1447
|
// font size
|
|
770
1448
|
// 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.
|
|
@@ -814,19 +1492,19 @@ var codeTheme = {
|
|
|
814
1492
|
|
|
815
1493
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
816
1494
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
817
|
-
import { EditorView as
|
|
1495
|
+
import { EditorView as EditorView9 } from "@codemirror/view";
|
|
818
1496
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
819
1497
|
import { vim } from "@replit/codemirror-vim";
|
|
820
|
-
import
|
|
1498
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
821
1499
|
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
822
1500
|
import { generateName } from "@dxos/display-name";
|
|
823
1501
|
import { useThemeContext } from "@dxos/react-ui";
|
|
824
|
-
import { getColorForValue, inputSurface, mx as
|
|
1502
|
+
import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
825
1503
|
var EditorModes = [
|
|
826
1504
|
"default",
|
|
827
1505
|
"vim"
|
|
828
1506
|
];
|
|
829
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots = defaultSlots
|
|
1507
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
|
|
830
1508
|
const { themeMode } = useThemeContext();
|
|
831
1509
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
832
1510
|
tabBehavior: "limited"
|
|
@@ -871,13 +1549,14 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
871
1549
|
const state2 = EditorState2.create({
|
|
872
1550
|
doc: model.text(),
|
|
873
1551
|
extensions: [
|
|
1552
|
+
readonly && EditorState2.readOnly.of(readonly),
|
|
874
1553
|
// TODO(burdon): Factor out VIM mode?
|
|
875
1554
|
editorMode === "vim" && vim(),
|
|
876
1555
|
// Theme.
|
|
877
|
-
|
|
878
|
-
|
|
1556
|
+
EditorView9.baseTheme(defaultTheme),
|
|
1557
|
+
EditorView9.theme(slots?.editor?.theme ?? {}),
|
|
879
1558
|
// TODO(burdon): themeMode doesn't change in storybooks.
|
|
880
|
-
|
|
1559
|
+
EditorView9.darkTheme.of(themeMode === "dark"),
|
|
881
1560
|
// Storage and replication.
|
|
882
1561
|
model.extension,
|
|
883
1562
|
// Custom.
|
|
@@ -885,7 +1564,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
885
1564
|
].filter(Boolean)
|
|
886
1565
|
});
|
|
887
1566
|
view?.destroy();
|
|
888
|
-
setView(new
|
|
1567
|
+
setView(new EditorView9({
|
|
889
1568
|
state: state2,
|
|
890
1569
|
parent: root
|
|
891
1570
|
}));
|
|
@@ -899,6 +1578,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
899
1578
|
root,
|
|
900
1579
|
model,
|
|
901
1580
|
themeMode,
|
|
1581
|
+
readonly,
|
|
902
1582
|
editorMode
|
|
903
1583
|
]);
|
|
904
1584
|
const handleKeyUp = useCallback((event) => {
|
|
@@ -926,13 +1606,15 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
926
1606
|
onKeyUp: handleKeyUp
|
|
927
1607
|
});
|
|
928
1608
|
});
|
|
929
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1609
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
930
1610
|
const { themeMode } = useThemeContext();
|
|
931
|
-
const slots =
|
|
1611
|
+
const slots = defaultsDeep2({}, _slots, defaultTextSlots);
|
|
932
1612
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
933
1613
|
ref: forwardedRef,
|
|
1614
|
+
readonly,
|
|
934
1615
|
extensions: [
|
|
935
1616
|
basicBundle({
|
|
1617
|
+
readonly,
|
|
936
1618
|
themeMode,
|
|
937
1619
|
placeholder: slots?.editor?.placeholder
|
|
938
1620
|
}),
|
|
@@ -942,13 +1624,15 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, .
|
|
|
942
1624
|
...props
|
|
943
1625
|
});
|
|
944
1626
|
});
|
|
945
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1627
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
946
1628
|
const { themeMode } = useThemeContext();
|
|
947
|
-
const slots =
|
|
1629
|
+
const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
|
|
948
1630
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
949
1631
|
ref: forwardedRef,
|
|
1632
|
+
readonly,
|
|
950
1633
|
extensions: [
|
|
951
1634
|
markdownBundle({
|
|
1635
|
+
readonly,
|
|
952
1636
|
themeMode,
|
|
953
1637
|
placeholder: slots?.editor?.placeholder
|
|
954
1638
|
}),
|
|
@@ -960,7 +1644,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
|
|
|
960
1644
|
});
|
|
961
1645
|
var defaultSlots = {
|
|
962
1646
|
root: {
|
|
963
|
-
className:
|
|
1647
|
+
className: mx3("p-2", inputSurface)
|
|
964
1648
|
}
|
|
965
1649
|
};
|
|
966
1650
|
var defaultTextSlots = {
|
|
@@ -980,20 +1664,20 @@ var defaultMarkdownSlots = {
|
|
|
980
1664
|
import get3 from "lodash.get";
|
|
981
1665
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
982
1666
|
import { yCollab } from "y-codemirror.next";
|
|
983
|
-
import { invariant as
|
|
1667
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
984
1668
|
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
985
1669
|
|
|
986
1670
|
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
987
|
-
import { Annotation, Facet, StateEffect, StateField as
|
|
1671
|
+
import { Annotation, Facet, StateEffect, StateField as StateField6 } from "@codemirror/state";
|
|
988
1672
|
import { ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
989
1673
|
import * as automerge2 from "@dxos/automerge/automerge";
|
|
990
1674
|
|
|
991
1675
|
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
992
1676
|
import { next as automerge } from "@dxos/automerge/automerge";
|
|
993
1677
|
|
|
994
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1678
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
|
|
995
1679
|
import { ChangeSet } from "@codemirror/state";
|
|
996
|
-
var
|
|
1680
|
+
var automergeToCodemirror = (view, selection, target, patches) => {
|
|
997
1681
|
for (const patch of patches) {
|
|
998
1682
|
const changeSpec = handlePatch(patch, target, view.state);
|
|
999
1683
|
if (changeSpec != null) {
|
|
@@ -1098,9 +1782,9 @@ var charPath = (textPath, candidatePath) => {
|
|
|
1098
1782
|
return null;
|
|
1099
1783
|
};
|
|
1100
1784
|
|
|
1101
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1785
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
|
|
1102
1786
|
import { next as am } from "@dxos/automerge/automerge";
|
|
1103
|
-
var
|
|
1787
|
+
var codemirrorToAutomerge = (field, handle, transactions, state) => {
|
|
1104
1788
|
const { lastHeads, path } = state.field(field);
|
|
1105
1789
|
let hasChanges = false;
|
|
1106
1790
|
for (const tr of transactions) {
|
|
@@ -1144,12 +1828,12 @@ var PatchSemaphore = class {
|
|
|
1144
1828
|
annotations: reconcileAnnotationType.of(true)
|
|
1145
1829
|
});
|
|
1146
1830
|
}
|
|
1147
|
-
let newHeads =
|
|
1831
|
+
let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
|
|
1148
1832
|
if (newHeads === null || newHeads === void 0) {
|
|
1149
1833
|
newHeads = automerge.getHeads(handle.docSync());
|
|
1150
1834
|
}
|
|
1151
1835
|
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
1152
|
-
|
|
1836
|
+
automergeToCodemirror(view, selection, path, diff);
|
|
1153
1837
|
view.dispatch({
|
|
1154
1838
|
effects: updateHeads(newHeads),
|
|
1155
1839
|
annotations: reconcileAnnotationType.of({})
|
|
@@ -1173,7 +1857,7 @@ var semaphoreFacet = Facet.define({
|
|
|
1173
1857
|
combine: (values) => values.at(-1)
|
|
1174
1858
|
});
|
|
1175
1859
|
var automergePlugin = (handle, path) => {
|
|
1176
|
-
const stateField =
|
|
1860
|
+
const stateField = StateField6.define({
|
|
1177
1861
|
create: () => ({
|
|
1178
1862
|
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
1179
1863
|
unreconciledTransactions: [],
|
|
@@ -1211,8 +1895,8 @@ var automergePlugin = (handle, path) => {
|
|
|
1211
1895
|
this._view = view;
|
|
1212
1896
|
handle.addListener("change", this._handleChange);
|
|
1213
1897
|
}
|
|
1214
|
-
update(
|
|
1215
|
-
if (
|
|
1898
|
+
update(update4) {
|
|
1899
|
+
if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
|
|
1216
1900
|
queueMicrotask(() => {
|
|
1217
1901
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
1218
1902
|
});
|
|
@@ -1234,7 +1918,7 @@ var reconcileAnnotationType = Annotation.define();
|
|
|
1234
1918
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
1235
1919
|
|
|
1236
1920
|
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
1237
|
-
import * as
|
|
1921
|
+
import * as random2 from "lib0/random";
|
|
1238
1922
|
var cursorColors = [
|
|
1239
1923
|
{
|
|
1240
1924
|
color: "#30bced",
|
|
@@ -1269,7 +1953,7 @@ var cursorColors = [
|
|
|
1269
1953
|
light: "#1be7ff33"
|
|
1270
1954
|
}
|
|
1271
1955
|
];
|
|
1272
|
-
var cursorColor = cursorColors[
|
|
1956
|
+
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
1273
1957
|
|
|
1274
1958
|
// packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
|
|
1275
1959
|
import * as decoding from "lib0/decoding";
|
|
@@ -1277,7 +1961,7 @@ import * as encoding from "lib0/encoding";
|
|
|
1277
1961
|
import { Observable } from "lib0/observable";
|
|
1278
1962
|
import * as awarenessProtocol from "y-protocols/awareness";
|
|
1279
1963
|
import { log } from "@dxos/log";
|
|
1280
|
-
var
|
|
1964
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
1281
1965
|
var messageAwareness = 1;
|
|
1282
1966
|
var messageQueryAwareness = 3;
|
|
1283
1967
|
var SpaceAwarenessProvider = class extends Observable {
|
|
@@ -1314,7 +1998,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1314
1998
|
removed,
|
|
1315
1999
|
origin
|
|
1316
2000
|
}, {
|
|
1317
|
-
F:
|
|
2001
|
+
F: __dxlog_file3,
|
|
1318
2002
|
L: 67,
|
|
1319
2003
|
S: this,
|
|
1320
2004
|
C: (f, a) => f(...a)
|
|
@@ -1327,7 +2011,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1327
2011
|
}
|
|
1328
2012
|
_handleSpaceMessage({ payload }) {
|
|
1329
2013
|
log("space message", payload, {
|
|
1330
|
-
F:
|
|
2014
|
+
F: __dxlog_file3,
|
|
1331
2015
|
L: 79,
|
|
1332
2016
|
S: this,
|
|
1333
2017
|
C: (f, a) => f(...a)
|
|
@@ -1372,7 +2056,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1372
2056
|
};
|
|
1373
2057
|
|
|
1374
2058
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1375
|
-
var
|
|
2059
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
1376
2060
|
var useTextModel = ({ identity, space, text }) => {
|
|
1377
2061
|
const [model, setModel] = useState2(() => createModel({
|
|
1378
2062
|
identity,
|
|
@@ -1404,8 +2088,8 @@ var createModel = (options) => {
|
|
|
1404
2088
|
}
|
|
1405
2089
|
};
|
|
1406
2090
|
var createYjsModel = ({ identity, space, text }) => {
|
|
1407
|
-
|
|
1408
|
-
F:
|
|
2091
|
+
invariant3(text?.doc && text?.content, void 0, {
|
|
2092
|
+
F: __dxlog_file4,
|
|
1409
2093
|
L: 74,
|
|
1410
2094
|
S: void 0,
|
|
1411
2095
|
A: [
|
|
@@ -1458,20 +2142,26 @@ export {
|
|
|
1458
2142
|
YXmlFragment,
|
|
1459
2143
|
autocomplete,
|
|
1460
2144
|
basicBundle,
|
|
2145
|
+
blast,
|
|
1461
2146
|
codeTheme,
|
|
1462
2147
|
comments,
|
|
1463
2148
|
cursorColor,
|
|
1464
2149
|
defaultMarkdownSlots,
|
|
2150
|
+
defaultOptions,
|
|
1465
2151
|
defaultSlots,
|
|
1466
2152
|
defaultTextSlots,
|
|
1467
2153
|
defaultTheme,
|
|
2154
|
+
demo,
|
|
2155
|
+
image,
|
|
1468
2156
|
link,
|
|
1469
2157
|
listener,
|
|
1470
2158
|
markdownBundle,
|
|
1471
2159
|
markdownHighlightStyle,
|
|
1472
2160
|
markdownTags,
|
|
1473
|
-
|
|
2161
|
+
markdownTagsExtensions,
|
|
1474
2162
|
markdownTheme,
|
|
2163
|
+
mention,
|
|
2164
|
+
table,
|
|
1475
2165
|
tags2 as tags,
|
|
1476
2166
|
tasklist,
|
|
1477
2167
|
textTheme,
|