@dxos/react-ui-editor 0.3.10-main.04816d3 → 0.3.10-main.08c6b67
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 +1187 -375
- 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 +23 -2
- 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/TextEditor.stories.d.ts +3 -0
- package/dist/types/src/components/TextEditor/TextEditor.stories.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/code.d.ts +2 -0
- package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts +2 -2
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/demo.d.ts +2 -1
- package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +1 -1
- 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/highlight.d.ts +24 -0
- package/dist/types/src/components/TextEditor/extensions/highlight.d.ts.map +1 -0
- 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.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +10 -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/hooks/useTextModel.d.ts +6 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/{components/TextEditor → hooks/yjs}/yjs.stories.d.ts +2 -2
- 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 +22 -20
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +124 -32
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -1
- package/src/components/TextEditor/TextEditor.tsx +31 -24
- package/src/components/TextEditor/extensions/autocomplete.ts +5 -20
- package/src/components/TextEditor/extensions/basic.ts +6 -4
- package/src/components/TextEditor/extensions/blast.ts +373 -0
- package/src/components/TextEditor/extensions/code.ts +99 -0
- package/src/components/TextEditor/extensions/comments.ts +29 -46
- package/src/components/TextEditor/extensions/demo.ts +4 -1
- package/src/components/TextEditor/extensions/experimental.tsx +15 -36
- package/src/components/TextEditor/extensions/highlight.ts +128 -0
- package/src/components/TextEditor/extensions/image.ts +67 -0
- package/src/components/TextEditor/extensions/index.ts +6 -0
- package/src/components/TextEditor/extensions/link.ts +17 -25
- package/src/components/TextEditor/extensions/listener.ts +3 -3
- package/src/components/TextEditor/extensions/markdown/bundle.ts +45 -34
- package/src/components/TextEditor/extensions/markdown/highlight.ts +148 -108
- package/src/components/TextEditor/extensions/mention.ts +31 -0
- package/src/components/TextEditor/extensions/table.ts +119 -0
- package/src/components/TextEditor/extensions/tasklist.ts +42 -28
- package/src/components/TextEditor/themes/default.ts +98 -4
- package/src/hooks/automerge/PatchSemaphore.ts +12 -9
- package/src/hooks/automerge/automerge.stories.tsx +4 -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/hooks/useTextModel.ts +9 -0
- package/src/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +2 -2
- package/src/styles/markdown.ts +15 -8
- package/src/testing/replicator.ts +1 -0
- 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
|
]
|
|
@@ -42,20 +42,451 @@ var autocomplete = ({ onSearch }) => {
|
|
|
42
42
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
43
43
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
44
44
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
45
|
-
import { EditorView, placeholder } from "@codemirror/view";
|
|
46
|
-
var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
|
|
45
|
+
import { drawSelection, EditorView, placeholder } from "@codemirror/view";
|
|
46
|
+
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
47
|
+
EditorView.lineWrapping,
|
|
47
48
|
// TODO(burdon): Compare with minimalSetup.
|
|
48
49
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
49
50
|
bracketMatching(),
|
|
50
51
|
closeBrackets(),
|
|
51
|
-
|
|
52
|
+
drawSelection(),
|
|
52
53
|
_placeholder && placeholder(_placeholder),
|
|
53
54
|
// TODO(burdon): Is this required?
|
|
54
55
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
55
56
|
].filter(Boolean);
|
|
56
57
|
|
|
58
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts
|
|
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
|
+
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 = defaultOptions) => {
|
|
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.state.selection.main.head;
|
|
127
|
+
if (current !== last) {
|
|
128
|
+
last = current;
|
|
129
|
+
const { element, point } = getPoint(update4.view, current - 1);
|
|
130
|
+
if (element && point) {
|
|
131
|
+
blaster.spawn({
|
|
132
|
+
element,
|
|
133
|
+
point
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
keymap2.of([
|
|
139
|
+
{
|
|
140
|
+
any: (_, event) => {
|
|
141
|
+
if (blaster) {
|
|
142
|
+
if (event.key === "Enter" && event.shiftKey) {
|
|
143
|
+
blaster.shake({
|
|
144
|
+
time: 0.8
|
|
145
|
+
});
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
])
|
|
153
|
+
];
|
|
154
|
+
};
|
|
155
|
+
var Blaster = class {
|
|
156
|
+
constructor(_node, _options) {
|
|
157
|
+
this._node = _node;
|
|
158
|
+
this._options = _options;
|
|
159
|
+
this._running = false;
|
|
160
|
+
this._shakeTime = 0;
|
|
161
|
+
this._shakeTimeMax = 0;
|
|
162
|
+
this._particles = [];
|
|
163
|
+
this._particlePointer = 0;
|
|
164
|
+
this._lastPoint = {
|
|
165
|
+
x: 0,
|
|
166
|
+
y: 0
|
|
167
|
+
};
|
|
168
|
+
this.shake = throttle(({ time }) => {
|
|
169
|
+
this._shakeTime = this._shakeTimeMax || time;
|
|
170
|
+
this._shakeTimeMax = time;
|
|
171
|
+
}, 100);
|
|
172
|
+
this.spawn = throttle(({ element, point }) => {
|
|
173
|
+
const color = getRGBComponents(element, this._options.color);
|
|
174
|
+
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
175
|
+
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
176
|
+
this._lastPoint = point;
|
|
177
|
+
for (let i = numParticles; i--; i > 0) {
|
|
178
|
+
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
179
|
+
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
180
|
+
}
|
|
181
|
+
}, 100);
|
|
182
|
+
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
183
|
+
}
|
|
184
|
+
get node() {
|
|
185
|
+
return this._node;
|
|
186
|
+
}
|
|
187
|
+
initialize() {
|
|
188
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
189
|
+
F: __dxlog_file,
|
|
190
|
+
L: 138,
|
|
191
|
+
S: this,
|
|
192
|
+
A: [
|
|
193
|
+
"!this._canvas && !this._ctx",
|
|
194
|
+
""
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
this._canvas = document.createElement("canvas");
|
|
198
|
+
this._canvas.id = "code-blast-canvas";
|
|
199
|
+
this._canvas.style.position = "absolute";
|
|
200
|
+
this._canvas.style.zIndex = "0";
|
|
201
|
+
this._canvas.style.pointerEvents = "none";
|
|
202
|
+
this._ctx = this._canvas.getContext("2d");
|
|
203
|
+
const parent = this._node.parentElement?.parentElement;
|
|
204
|
+
parent?.appendChild(this._canvas);
|
|
205
|
+
this.resize();
|
|
206
|
+
}
|
|
207
|
+
destroy() {
|
|
208
|
+
this.stop();
|
|
209
|
+
if (this._canvas) {
|
|
210
|
+
this._canvas.remove();
|
|
211
|
+
this._canvas = void 0;
|
|
212
|
+
this._ctx = void 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
resize() {
|
|
216
|
+
if (this._node.parentElement && this._canvas) {
|
|
217
|
+
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
218
|
+
this._canvas.style.top = `${y}px`;
|
|
219
|
+
this._canvas.style.left = `${x}px`;
|
|
220
|
+
this._canvas.width = width;
|
|
221
|
+
this._canvas.height = height;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
start() {
|
|
225
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
226
|
+
F: __dxlog_file,
|
|
227
|
+
L: 177,
|
|
228
|
+
S: this,
|
|
229
|
+
A: [
|
|
230
|
+
"this._canvas && this._ctx",
|
|
231
|
+
""
|
|
232
|
+
]
|
|
233
|
+
});
|
|
234
|
+
this._running = true;
|
|
235
|
+
this.loop();
|
|
236
|
+
}
|
|
237
|
+
stop() {
|
|
238
|
+
this._running = false;
|
|
239
|
+
this._node.style.transform = "translate(0px, 0px)";
|
|
240
|
+
}
|
|
241
|
+
loop() {
|
|
242
|
+
if (!this._running || !this._canvas || !this._ctx) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this._ctx.clearRect(0, 0, this._canvas.width ?? 0, this._canvas.height ?? 0);
|
|
246
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
247
|
+
this._lastTime ??= now;
|
|
248
|
+
const dt = (now - this._lastTime) / 1e3;
|
|
249
|
+
this._lastTime = now;
|
|
250
|
+
if (this._shakeTime > 0) {
|
|
251
|
+
this._shakeTime -= dt;
|
|
252
|
+
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
253
|
+
const shakeX = random(-magnitude, magnitude);
|
|
254
|
+
const shakeY = random(-magnitude, magnitude);
|
|
255
|
+
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
256
|
+
}
|
|
257
|
+
this.drawParticles();
|
|
258
|
+
requestAnimationFrame(this.loop.bind(this));
|
|
259
|
+
}
|
|
260
|
+
drawParticles() {
|
|
261
|
+
for (let i = this._particles.length; i--; i > 0) {
|
|
262
|
+
const particle = this._particles[i];
|
|
263
|
+
if (!particle) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (particle.alpha < 0.01 || particle.size <= 0.5) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
this._effect.update(this._ctx, particle);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
var Effect = class {
|
|
274
|
+
constructor(_options) {
|
|
275
|
+
this._options = _options;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var Effect1 = class extends Effect {
|
|
279
|
+
create(x, y, color) {
|
|
280
|
+
return {
|
|
281
|
+
x,
|
|
282
|
+
y: y + 10,
|
|
283
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
284
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
285
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
286
|
+
color,
|
|
287
|
+
alpha: 1
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
update(ctx, particle) {
|
|
291
|
+
particle.vy += this._options.particleGravity;
|
|
292
|
+
particle.x += particle.vx;
|
|
293
|
+
particle.y += particle.vy;
|
|
294
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
295
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
296
|
+
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
var Effect2 = class extends Effect {
|
|
300
|
+
create(x, y, color) {
|
|
301
|
+
return {
|
|
302
|
+
x,
|
|
303
|
+
y: y + 10,
|
|
304
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
305
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
306
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
307
|
+
color,
|
|
308
|
+
alpha: 1,
|
|
309
|
+
theta: random(0, 360) * Math.PI / 180,
|
|
310
|
+
drag: 0.92,
|
|
311
|
+
wander: 0.15
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
update(ctx, particle) {
|
|
315
|
+
particle.vy += this._options.particleGravity;
|
|
316
|
+
particle.x += particle.vx;
|
|
317
|
+
particle.y += particle.vy;
|
|
318
|
+
particle.vx *= particle.drag;
|
|
319
|
+
particle.vy *= particle.drag;
|
|
320
|
+
particle.theta += random(-0.5, 0.5);
|
|
321
|
+
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
322
|
+
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
323
|
+
particle.size *= this._options.particleShrinkRate;
|
|
324
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
325
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
326
|
+
ctx.beginPath();
|
|
327
|
+
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
328
|
+
ctx.fill();
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
function throttle(callback, limit) {
|
|
332
|
+
let wait = false;
|
|
333
|
+
return function(...args) {
|
|
334
|
+
if (!wait) {
|
|
335
|
+
callback.apply(this, args);
|
|
336
|
+
wait = true;
|
|
337
|
+
setTimeout(() => {
|
|
338
|
+
wait = false;
|
|
339
|
+
}, limit);
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
var getRGBComponents = (node, color) => {
|
|
344
|
+
if (typeof color === "function") {
|
|
345
|
+
return color();
|
|
346
|
+
}
|
|
347
|
+
const bgColor = getComputedStyle(node).color;
|
|
348
|
+
if (bgColor) {
|
|
349
|
+
const x = bgColor.match(/(\d+), (\d+), (\d+)/)?.slice(1);
|
|
350
|
+
if (x) {
|
|
351
|
+
return x;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return [
|
|
355
|
+
50,
|
|
356
|
+
50,
|
|
357
|
+
50
|
|
358
|
+
];
|
|
359
|
+
};
|
|
360
|
+
var random = (min, max) => {
|
|
361
|
+
if (!max) {
|
|
362
|
+
max = min;
|
|
363
|
+
min = 0;
|
|
364
|
+
}
|
|
365
|
+
return min + ~~(Math.random() * (max - min + 1));
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/code.ts
|
|
369
|
+
import { ViewPlugin, EditorView as EditorView3, Decoration } from "@codemirror/view";
|
|
370
|
+
import get from "lodash.get";
|
|
371
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
372
|
+
|
|
373
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
374
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
375
|
+
var headings = {
|
|
376
|
+
1: [
|
|
377
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
378
|
+
"-ml-[10px]"
|
|
379
|
+
],
|
|
380
|
+
2: [
|
|
381
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
382
|
+
"-ml-[8px]"
|
|
383
|
+
],
|
|
384
|
+
3: [
|
|
385
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
386
|
+
"-ml-[7px]"
|
|
387
|
+
],
|
|
388
|
+
4: [
|
|
389
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
390
|
+
"-ml-[6px]"
|
|
391
|
+
],
|
|
392
|
+
5: [
|
|
393
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
394
|
+
"-ml-[5px]"
|
|
395
|
+
],
|
|
396
|
+
6: [
|
|
397
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
398
|
+
"-ml-[4px]"
|
|
399
|
+
]
|
|
400
|
+
};
|
|
401
|
+
var heading = (level, readonly) => {
|
|
402
|
+
const [style, offset] = headings[level];
|
|
403
|
+
return mx(style, readonly && offset);
|
|
404
|
+
};
|
|
405
|
+
var light = "text-neutral-200 dark:text-neutral-800";
|
|
406
|
+
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
407
|
+
var bold = "font-bold";
|
|
408
|
+
var italic = "italic";
|
|
409
|
+
var strikethrough = "line-through";
|
|
410
|
+
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
411
|
+
var codeMark = "font-mono text-primary-500";
|
|
412
|
+
var inlineUrl = mx(code, "px-1");
|
|
413
|
+
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
414
|
+
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800";
|
|
415
|
+
|
|
416
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
417
|
+
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
418
|
+
var tokens = tailwindConfig({}).theme;
|
|
419
|
+
|
|
420
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/code.ts
|
|
421
|
+
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
422
|
+
var styles = EditorView3.baseTheme({
|
|
423
|
+
"& .cm-code-block": {
|
|
424
|
+
display: "block",
|
|
425
|
+
paddingInline: "4px !important"
|
|
426
|
+
},
|
|
427
|
+
"&light .cm-code-block": {
|
|
428
|
+
background: get(tokens, "extend.colors.neutral.50")
|
|
429
|
+
},
|
|
430
|
+
"&dark .cm-code-block": {
|
|
431
|
+
background: get(tokens, "extend.colors.neutral.850")
|
|
432
|
+
},
|
|
433
|
+
"& .cm-code-block-first": {
|
|
434
|
+
paddingTop: "4px !important",
|
|
435
|
+
borderTopLeftRadius: "4px",
|
|
436
|
+
borderTopRightRadius: "4px"
|
|
437
|
+
},
|
|
438
|
+
"& .cm-code-block-last": {
|
|
439
|
+
paddingBottom: "4px !important",
|
|
440
|
+
borderBottomLeftRadius: "4px",
|
|
441
|
+
borderBottomRightRadius: "4px"
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
var getLineRange = (lines, from, to) => {
|
|
445
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
446
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
447
|
+
return [
|
|
448
|
+
start,
|
|
449
|
+
end
|
|
450
|
+
];
|
|
451
|
+
};
|
|
452
|
+
var code2 = () => {
|
|
453
|
+
const getDecorations = (view) => {
|
|
454
|
+
const decorations = [];
|
|
455
|
+
if (view.state.readOnly) {
|
|
456
|
+
const text = view.state.doc.sliceString(0);
|
|
457
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
458
|
+
const blocks = view.viewportLineBlocks;
|
|
459
|
+
for (const match of matches) {
|
|
460
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
461
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
462
|
+
const block = blocks[i];
|
|
463
|
+
decorations.push(Decoration.line({
|
|
464
|
+
class: mx2("cm-code-block", i === range[0] && "cm-code-block-first", i === range[1] && "cm-code-block-last")
|
|
465
|
+
}).range(block.from));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return Decoration.set(decorations);
|
|
470
|
+
};
|
|
471
|
+
return [
|
|
472
|
+
ViewPlugin.fromClass(class {
|
|
473
|
+
constructor(view) {
|
|
474
|
+
this.decorations = getDecorations(view);
|
|
475
|
+
}
|
|
476
|
+
update(update4) {
|
|
477
|
+
if (update4.docChanged || update4.viewportChanged) {
|
|
478
|
+
this.decorations = getDecorations(update4.view);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}, {
|
|
482
|
+
decorations: (value) => value.decorations
|
|
483
|
+
}),
|
|
484
|
+
styles
|
|
485
|
+
];
|
|
486
|
+
};
|
|
487
|
+
|
|
57
488
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
|
|
58
|
-
import { keymap as
|
|
489
|
+
import { keymap as keymap3 } from "@codemirror/view";
|
|
59
490
|
var defaultItems = [
|
|
60
491
|
"hello world!",
|
|
61
492
|
"this is a test.",
|
|
@@ -65,7 +496,7 @@ var demo = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
65
496
|
let t;
|
|
66
497
|
let idx = 0;
|
|
67
498
|
return [
|
|
68
|
-
|
|
499
|
+
keymap3.of([
|
|
69
500
|
{
|
|
70
501
|
// Reset.
|
|
71
502
|
key: "alt-meta-'",
|
|
@@ -112,18 +543,30 @@ var demo = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
112
543
|
};
|
|
113
544
|
|
|
114
545
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
|
|
115
|
-
import { keymap as
|
|
546
|
+
import { keymap as keymap4, Decoration as Decoration2, EditorView as EditorView4, MatchDecorator, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
116
547
|
import { debounce } from "@dxos/async";
|
|
117
|
-
import { invariant } from "@dxos/invariant";
|
|
118
|
-
var
|
|
548
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
549
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
|
|
550
|
+
var styles2 = EditorView4.baseTheme({
|
|
551
|
+
"& .cm-bookmark": {
|
|
552
|
+
cursor: "pointer",
|
|
553
|
+
margin: "4px",
|
|
554
|
+
padding: "4px",
|
|
555
|
+
backgroundColor: "yellow"
|
|
556
|
+
},
|
|
557
|
+
"& .cm-bookmark-selected": {
|
|
558
|
+
backgroundColor: "orange"
|
|
559
|
+
}
|
|
560
|
+
});
|
|
119
561
|
var BookmarkWidget = class extends WidgetType {
|
|
120
|
-
constructor(_pos, _id) {
|
|
562
|
+
constructor(_pos, _id, _handleClick) {
|
|
121
563
|
super();
|
|
122
564
|
this._pos = _pos;
|
|
123
565
|
this._id = _id;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
566
|
+
this._handleClick = _handleClick;
|
|
567
|
+
invariant2(this._id, void 0, {
|
|
568
|
+
F: __dxlog_file2,
|
|
569
|
+
L: 37,
|
|
127
570
|
S: this,
|
|
128
571
|
A: [
|
|
129
572
|
"this._id",
|
|
@@ -137,65 +580,57 @@ var BookmarkWidget = class extends WidgetType {
|
|
|
137
580
|
toDOM() {
|
|
138
581
|
const span = document.createElement("span");
|
|
139
582
|
span.className = "cm-bookmark";
|
|
140
|
-
span.textContent = "\
|
|
583
|
+
span.textContent = "\xA7";
|
|
584
|
+
span.onclick = () => this._handleClick();
|
|
141
585
|
return span;
|
|
142
586
|
}
|
|
143
587
|
};
|
|
144
|
-
var styles = EditorView2.baseTheme({
|
|
145
|
-
"& .cm-bookmark": {
|
|
146
|
-
cursor: "pointer",
|
|
147
|
-
margin: "4px",
|
|
148
|
-
padding: "4px",
|
|
149
|
-
backgroundColor: "yellow"
|
|
150
|
-
},
|
|
151
|
-
"& .cm-bookmark-selected": {
|
|
152
|
-
backgroundColor: "orange"
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
588
|
var comments = (options = {}) => {
|
|
156
589
|
let active;
|
|
157
590
|
const bookmarkMatcher = new MatchDecorator({
|
|
158
591
|
regexp: /\[\^(\w+)\]/g,
|
|
159
592
|
decoration: (match, view, pos) => {
|
|
160
593
|
const id = match[1];
|
|
161
|
-
return
|
|
594
|
+
return Decoration2.replace({
|
|
162
595
|
id,
|
|
163
|
-
widget: new BookmarkWidget(pos, id)
|
|
596
|
+
widget: new BookmarkWidget(pos, id, () => handleUpdate({
|
|
597
|
+
active: id
|
|
598
|
+
}))
|
|
164
599
|
});
|
|
165
600
|
}
|
|
166
601
|
});
|
|
167
|
-
const bookmarks =
|
|
602
|
+
const bookmarks = ViewPlugin2.fromClass(class {
|
|
168
603
|
constructor(view) {
|
|
169
604
|
this.bookmarks = bookmarkMatcher.createDeco(view);
|
|
170
605
|
}
|
|
171
|
-
update(
|
|
172
|
-
this.bookmarks = bookmarkMatcher.updateDeco(
|
|
606
|
+
update(update4) {
|
|
607
|
+
this.bookmarks = bookmarkMatcher.updateDeco(update4, this.bookmarks);
|
|
173
608
|
}
|
|
174
609
|
}, {
|
|
175
610
|
decorations: (instance) => instance.bookmarks,
|
|
176
|
-
provide: (plugin) =>
|
|
177
|
-
return view.plugin(plugin)?.bookmarks ||
|
|
611
|
+
provide: (plugin) => EditorView4.atomicRanges.of((view) => {
|
|
612
|
+
return view.plugin(plugin)?.bookmarks || Decoration2.none;
|
|
178
613
|
})
|
|
179
614
|
});
|
|
180
|
-
const
|
|
615
|
+
const handleUpdate = debounce((data) => {
|
|
181
616
|
options.onUpdate?.(data);
|
|
182
617
|
}, 200);
|
|
183
618
|
return [
|
|
184
|
-
|
|
619
|
+
keymap4.of([
|
|
185
620
|
{
|
|
186
621
|
key: options?.key ?? "shift-meta-c",
|
|
187
622
|
run: (view) => {
|
|
188
|
-
const
|
|
623
|
+
const { from, to, head } = view.state.selection.main;
|
|
624
|
+
const id = options.onCreate?.(from, to);
|
|
189
625
|
if (id) {
|
|
190
|
-
const pos = view.state.selection.main.head;
|
|
191
626
|
const tag = `[^${id}]`;
|
|
192
627
|
view.dispatch({
|
|
193
628
|
changes: {
|
|
194
|
-
from:
|
|
629
|
+
from: head,
|
|
195
630
|
insert: tag
|
|
196
631
|
},
|
|
197
632
|
selection: {
|
|
198
|
-
anchor:
|
|
633
|
+
anchor: head + tag.length
|
|
199
634
|
}
|
|
200
635
|
});
|
|
201
636
|
return true;
|
|
@@ -206,20 +641,23 @@ var comments = (options = {}) => {
|
|
|
206
641
|
]),
|
|
207
642
|
bookmarks,
|
|
208
643
|
// Monitor cursor movement.
|
|
209
|
-
|
|
644
|
+
EditorView4.updateListener.of((update4) => {
|
|
210
645
|
active = void 0;
|
|
211
646
|
if (!options.onUpdate) {
|
|
212
647
|
return;
|
|
213
648
|
}
|
|
214
|
-
const view =
|
|
215
|
-
const pos =
|
|
649
|
+
const { view, state } = update4;
|
|
650
|
+
const pos = state.selection.main.head;
|
|
216
651
|
const decorations = [];
|
|
217
652
|
const rangeSet = view.plugin(bookmarks)?.bookmarks;
|
|
218
653
|
let closest = Infinity;
|
|
219
|
-
const { from, to } =
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
654
|
+
const { from, to } = (
|
|
655
|
+
/* view.visibleRanges?.[0] ?? */
|
|
656
|
+
{
|
|
657
|
+
from: 0,
|
|
658
|
+
to: state.doc.length
|
|
659
|
+
}
|
|
660
|
+
);
|
|
223
661
|
rangeSet?.between(from, to, (from2, to2, value) => {
|
|
224
662
|
decorations.push({
|
|
225
663
|
from: from2,
|
|
@@ -233,7 +671,7 @@ var comments = (options = {}) => {
|
|
|
233
671
|
}
|
|
234
672
|
});
|
|
235
673
|
if (decorations.length) {
|
|
236
|
-
|
|
674
|
+
handleUpdate({
|
|
237
675
|
active,
|
|
238
676
|
items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
|
|
239
677
|
id,
|
|
@@ -243,15 +681,170 @@ var comments = (options = {}) => {
|
|
|
243
681
|
});
|
|
244
682
|
}
|
|
245
683
|
}),
|
|
246
|
-
|
|
684
|
+
styles2
|
|
247
685
|
];
|
|
248
686
|
};
|
|
249
687
|
|
|
250
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/
|
|
688
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/highlight.ts
|
|
689
|
+
import { StateEffect, StateField } from "@codemirror/state";
|
|
690
|
+
import { Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
|
|
691
|
+
import sortBy from "lodash.sortby";
|
|
692
|
+
import { useEffect } from "react";
|
|
693
|
+
var styles3 = EditorView5.baseTheme({
|
|
694
|
+
"& .cm-highlight": {
|
|
695
|
+
backgroundColor: "yellow"
|
|
696
|
+
},
|
|
697
|
+
"& .cm-highlight::before": {
|
|
698
|
+
content: "]"
|
|
699
|
+
},
|
|
700
|
+
"& .cm-highlight-active": {
|
|
701
|
+
backgroundColor: "lime"
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
var marks = {
|
|
705
|
+
highlight: Decoration3.mark({
|
|
706
|
+
class: "cm-highlight"
|
|
707
|
+
}),
|
|
708
|
+
HighlightActive: Decoration3.mark({
|
|
709
|
+
class: "cm-highlight-active"
|
|
710
|
+
})
|
|
711
|
+
};
|
|
712
|
+
var setHighlights = StateEffect.define();
|
|
713
|
+
var useHighlights = (view, ranges = []) => {
|
|
714
|
+
useEffect(() => {
|
|
715
|
+
view?.dispatch({
|
|
716
|
+
effects: setHighlights.of(ranges)
|
|
717
|
+
});
|
|
718
|
+
}, [
|
|
719
|
+
view,
|
|
720
|
+
ranges
|
|
721
|
+
]);
|
|
722
|
+
};
|
|
723
|
+
var highlightStateField = StateField.define({
|
|
724
|
+
create: () => [],
|
|
725
|
+
update: (threads, tr) => {
|
|
726
|
+
for (const effect of tr.effects) {
|
|
727
|
+
if (effect.is(setHighlights)) {
|
|
728
|
+
return effect.value;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return threads;
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
var highlightDecorations = EditorView5.decorations.compute([
|
|
735
|
+
highlightStateField
|
|
736
|
+
], (state) => {
|
|
737
|
+
const selectionRanges = state.field(highlightStateField);
|
|
738
|
+
const decorations = sortBy(selectionRanges ?? [], (selection) => selection.from)?.flatMap((selection) => {
|
|
739
|
+
const range = {
|
|
740
|
+
from: selection.from,
|
|
741
|
+
to: selection.to + 1
|
|
742
|
+
};
|
|
743
|
+
if (selection.to > selection.from) {
|
|
744
|
+
if (selection.active) {
|
|
745
|
+
return marks.HighlightActive.range(range.from, range.to);
|
|
746
|
+
} else {
|
|
747
|
+
return marks.highlight.range(range.from, range.to);
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
return [];
|
|
751
|
+
}
|
|
752
|
+
}) ?? [];
|
|
753
|
+
return Decoration3.set(decorations);
|
|
754
|
+
});
|
|
755
|
+
var listener = (options) => {
|
|
756
|
+
return EditorView5.updateListener.of((update4) => {
|
|
757
|
+
const { view, state } = update4;
|
|
758
|
+
const { head } = state.selection.main;
|
|
759
|
+
const ranges = state.field(highlightStateField);
|
|
760
|
+
let mod = false;
|
|
761
|
+
const newRanges = ranges.map((range) => {
|
|
762
|
+
const active = head >= range.from && head <= range.to;
|
|
763
|
+
if (active !== range.active) {
|
|
764
|
+
mod = true;
|
|
765
|
+
return {
|
|
766
|
+
...range,
|
|
767
|
+
active
|
|
768
|
+
};
|
|
769
|
+
} else {
|
|
770
|
+
return range;
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
if (mod) {
|
|
774
|
+
view.dispatch({
|
|
775
|
+
effects: setHighlights.of(newRanges)
|
|
776
|
+
});
|
|
777
|
+
options?.onChange?.(newRanges.find((range) => range.active)?.id);
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
};
|
|
781
|
+
var highlight = (options = {}) => {
|
|
782
|
+
return [
|
|
783
|
+
highlightStateField,
|
|
784
|
+
highlightDecorations,
|
|
785
|
+
listener(options),
|
|
786
|
+
styles3
|
|
787
|
+
];
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/image.ts
|
|
251
791
|
import { syntaxTree } from "@codemirror/language";
|
|
252
|
-
import { RangeSetBuilder, StateField } from "@codemirror/state";
|
|
253
|
-
import { Decoration as
|
|
254
|
-
var
|
|
792
|
+
import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
|
|
793
|
+
import { Decoration as Decoration4, EditorView as EditorView6, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
794
|
+
var image = (options = {}) => {
|
|
795
|
+
return StateField2.define({
|
|
796
|
+
create: (state) => update(state, options),
|
|
797
|
+
update: (_, tr) => update(tr.state, options),
|
|
798
|
+
provide: (field) => EditorView6.decorations.from(field)
|
|
799
|
+
});
|
|
800
|
+
};
|
|
801
|
+
var update = (state, options) => {
|
|
802
|
+
const builder = new RangeSetBuilder();
|
|
803
|
+
const cursor = state.selection.main.head;
|
|
804
|
+
syntaxTree(state).iterate({
|
|
805
|
+
enter: (node) => {
|
|
806
|
+
if (node.name === "Image") {
|
|
807
|
+
const urlNode = node.node.getChild("URL");
|
|
808
|
+
if (urlNode) {
|
|
809
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
810
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
811
|
+
builder.add(hide ? node.from : node.to, node.to, Decoration4.replace({
|
|
812
|
+
widget: new ImageWidget(url)
|
|
813
|
+
}));
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
return builder.finish();
|
|
819
|
+
};
|
|
820
|
+
var ImageWidget = class extends WidgetType2 {
|
|
821
|
+
constructor(_url) {
|
|
822
|
+
super();
|
|
823
|
+
this._url = _url;
|
|
824
|
+
}
|
|
825
|
+
eq(other) {
|
|
826
|
+
return this._url === other?._url;
|
|
827
|
+
}
|
|
828
|
+
toDOM(view) {
|
|
829
|
+
const img = document.createElement("img");
|
|
830
|
+
img.setAttribute("src", this._url);
|
|
831
|
+
img.setAttribute("class", "cm-image");
|
|
832
|
+
return img;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
|
|
837
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
838
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
|
|
839
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
840
|
+
var link = (options = {}) => {
|
|
841
|
+
return StateField3.define({
|
|
842
|
+
create: (state) => update2(state, options),
|
|
843
|
+
update: (_, tr) => update2(tr.state, options),
|
|
844
|
+
provide: (field) => EditorView7.decorations.from(field)
|
|
845
|
+
});
|
|
846
|
+
};
|
|
847
|
+
var LinkButton = class extends WidgetType3 {
|
|
255
848
|
constructor(_pos, _url, _onAttach) {
|
|
256
849
|
super();
|
|
257
850
|
this._pos = _pos;
|
|
@@ -267,7 +860,7 @@ var LinkButton = class extends WidgetType2 {
|
|
|
267
860
|
return el;
|
|
268
861
|
}
|
|
269
862
|
};
|
|
270
|
-
var LinkText = class extends
|
|
863
|
+
var LinkText = class extends WidgetType3 {
|
|
271
864
|
constructor(_pos, _text, _url) {
|
|
272
865
|
super();
|
|
273
866
|
this._pos = _pos;
|
|
@@ -297,26 +890,26 @@ var LinkText = class extends WidgetType2 {
|
|
|
297
890
|
return link2;
|
|
298
891
|
}
|
|
299
892
|
};
|
|
300
|
-
var
|
|
301
|
-
const builder = new
|
|
893
|
+
var update2 = (state, options) => {
|
|
894
|
+
const builder = new RangeSetBuilder2();
|
|
302
895
|
const cursor = state.selection.main.head;
|
|
303
|
-
|
|
896
|
+
syntaxTree2(state).iterate({
|
|
304
897
|
enter: (node) => {
|
|
305
898
|
if (node.name === "Link") {
|
|
306
|
-
const
|
|
307
|
-
const text =
|
|
899
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
900
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
308
901
|
const urlNode = node.node.getChild("URL");
|
|
309
902
|
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
310
903
|
if (!url) {
|
|
311
904
|
return false;
|
|
312
905
|
}
|
|
313
|
-
if (cursor < node.from || cursor > node.to) {
|
|
314
|
-
builder.add(node.from, node.to,
|
|
906
|
+
if (state.readOnly || cursor < node.from || cursor > node.to) {
|
|
907
|
+
builder.add(node.from, node.to, Decoration5.replace({
|
|
315
908
|
widget: new LinkText(node.from, text, options.link ? url : void 0)
|
|
316
909
|
}));
|
|
317
910
|
}
|
|
318
911
|
if (options.onRender) {
|
|
319
|
-
builder.add(node.to, node.to,
|
|
912
|
+
builder.add(node.to, node.to, Decoration5.replace({
|
|
320
913
|
widget: new LinkButton(node.from, url, options.onRender)
|
|
321
914
|
}));
|
|
322
915
|
}
|
|
@@ -326,69 +919,39 @@ var update = (state, options) => {
|
|
|
326
919
|
});
|
|
327
920
|
return builder.finish();
|
|
328
921
|
};
|
|
329
|
-
var link = (options = {}) => {
|
|
330
|
-
return StateField.define({
|
|
331
|
-
create: (state) => update(state, options),
|
|
332
|
-
update: (_, tr) => update(tr.state, options),
|
|
333
|
-
provide: (field) => EditorView3.decorations.from(field)
|
|
334
|
-
});
|
|
335
|
-
};
|
|
336
922
|
|
|
337
923
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
|
|
338
|
-
import { StateField as
|
|
339
|
-
var
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
924
|
+
import { StateField as StateField4 } from "@codemirror/state";
|
|
925
|
+
var listener2 = ({ onChange }) => {
|
|
926
|
+
return StateField4.define({
|
|
927
|
+
create: () => null,
|
|
928
|
+
update: (_value, transaction) => {
|
|
929
|
+
if (transaction.docChanged && onChange) {
|
|
930
|
+
onChange(transaction.newDoc.toString());
|
|
931
|
+
}
|
|
932
|
+
return null;
|
|
344
933
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
});
|
|
934
|
+
});
|
|
935
|
+
};
|
|
348
936
|
|
|
349
937
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
350
938
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
351
|
-
import {
|
|
939
|
+
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
352
940
|
import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
|
|
353
941
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
354
942
|
import { languages } from "@codemirror/language-data";
|
|
355
|
-
import {
|
|
943
|
+
import { searchKeymap } from "@codemirror/search";
|
|
356
944
|
import { EditorState } from "@codemirror/state";
|
|
357
945
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
358
|
-
import { crosshairCursor, drawSelection, dropCursor, EditorView as
|
|
946
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView8, highlightActiveLine, keymap as keymap5, placeholder as placeholder2 } from "@codemirror/view";
|
|
359
947
|
|
|
360
948
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
|
|
361
949
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
362
950
|
import { HighlightStyle } from "@codemirror/language";
|
|
363
951
|
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
364
|
-
import
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
import { mx } from "@dxos/react-ui-theme";
|
|
368
|
-
var heading = {
|
|
369
|
-
1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
370
|
-
2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
371
|
-
3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
372
|
-
4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
373
|
-
5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
374
|
-
6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
|
|
375
|
-
};
|
|
376
|
-
var light = "text-neutral-200 dark:text-neutral-800";
|
|
377
|
-
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
378
|
-
var bold = "font-bold";
|
|
379
|
-
var italic = "italic";
|
|
380
|
-
var strikethrough = "line-through";
|
|
381
|
-
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
382
|
-
var codeMark = "font-mono text-primary-500";
|
|
383
|
-
var inlineUrl = mx(code, "px-1");
|
|
384
|
-
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
385
|
-
var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-500/50";
|
|
386
|
-
|
|
387
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
388
|
-
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
389
|
-
var tokens = tailwindConfig({}).theme;
|
|
390
|
-
|
|
391
|
-
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
|
|
952
|
+
import { Table } from "@lezer/markdown";
|
|
953
|
+
import get2 from "lodash.get";
|
|
954
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
392
955
|
var markdownTags = {
|
|
393
956
|
Blockquote: Tag.define(),
|
|
394
957
|
CodeMark: Tag.define(),
|
|
@@ -401,179 +964,202 @@ var markdownTags = {
|
|
|
401
964
|
LinkReference: Tag.define(),
|
|
402
965
|
ListMark: Tag.define(),
|
|
403
966
|
QuoteMark: Tag.define(),
|
|
404
|
-
URL: Tag.define()
|
|
967
|
+
URL: Tag.define(),
|
|
968
|
+
// Custom.
|
|
969
|
+
TableCell: Tag.define()
|
|
405
970
|
};
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
{
|
|
413
|
-
tag: [
|
|
414
|
-
tags.keyword,
|
|
415
|
-
tags.name,
|
|
416
|
-
tags.deleted,
|
|
417
|
-
tags.character,
|
|
418
|
-
tags.propertyName,
|
|
419
|
-
tags.macroName,
|
|
420
|
-
tags.color,
|
|
421
|
-
tags.constant(tags.name),
|
|
422
|
-
tags.standard(tags.name),
|
|
423
|
-
tags.definition(tags.name),
|
|
424
|
-
tags.separator,
|
|
425
|
-
tags.typeName,
|
|
426
|
-
tags.className,
|
|
427
|
-
tags.number,
|
|
428
|
-
tags.changed,
|
|
429
|
-
tags.annotation,
|
|
430
|
-
tags.modifier,
|
|
431
|
-
tags.self,
|
|
432
|
-
tags.namespace,
|
|
433
|
-
tags.operator,
|
|
434
|
-
tags.operatorKeyword,
|
|
435
|
-
tags.escape,
|
|
436
|
-
tags.regexp,
|
|
437
|
-
tags.special(tags.string),
|
|
438
|
-
tags.meta,
|
|
439
|
-
tags.comment,
|
|
440
|
-
tags.atom,
|
|
441
|
-
tags.bool,
|
|
442
|
-
tags.special(tags.variableName),
|
|
443
|
-
tags.processingInstruction,
|
|
444
|
-
tags.string,
|
|
445
|
-
tags.inserted,
|
|
446
|
-
tags.invalid
|
|
447
|
-
],
|
|
448
|
-
color: "inherit !important"
|
|
449
|
-
},
|
|
450
|
-
// Markdown marks.
|
|
451
|
-
{
|
|
452
|
-
tag: [
|
|
453
|
-
tags.meta,
|
|
454
|
-
tags.processingInstruction,
|
|
455
|
-
markdownTags.CodeMark,
|
|
456
|
-
markdownTags.EmphasisMark,
|
|
457
|
-
markdownTags.HeaderMark,
|
|
458
|
-
markdownTags.LinkLabel,
|
|
459
|
-
markdownTags.LinkReference,
|
|
460
|
-
markdownTags.ListMark,
|
|
461
|
-
markdownTags.QuoteMark
|
|
462
|
-
],
|
|
463
|
-
class: mark
|
|
464
|
-
},
|
|
465
|
-
// Headings.
|
|
466
|
-
{
|
|
467
|
-
tag: tags.heading1,
|
|
468
|
-
class: heading[1]
|
|
469
|
-
},
|
|
470
|
-
{
|
|
471
|
-
tag: tags.heading2,
|
|
472
|
-
class: heading[2]
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
tag: tags.heading3,
|
|
476
|
-
class: heading[3]
|
|
477
|
-
},
|
|
478
|
-
{
|
|
479
|
-
tag: tags.heading4,
|
|
480
|
-
class: heading[4]
|
|
481
|
-
},
|
|
482
|
-
{
|
|
483
|
-
tag: tags.heading5,
|
|
484
|
-
class: heading[5]
|
|
485
|
-
},
|
|
486
|
-
{
|
|
487
|
-
tag: tags.heading6,
|
|
488
|
-
class: heading[6]
|
|
489
|
-
},
|
|
490
|
-
// Emphasis.
|
|
491
|
-
{
|
|
492
|
-
tag: tags.emphasis,
|
|
493
|
-
class: italic
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
tag: tags.strong,
|
|
497
|
-
class: bold
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
tag: tags.strikethrough,
|
|
501
|
-
class: strikethrough
|
|
502
|
-
},
|
|
503
|
-
// Naked URLs.
|
|
504
|
-
{
|
|
505
|
-
tag: [
|
|
506
|
-
markdownTags.URL
|
|
507
|
-
],
|
|
508
|
-
class: inlineUrl
|
|
509
|
-
},
|
|
510
|
-
// E.g., code block language (after ```).
|
|
511
|
-
{
|
|
512
|
-
tag: [
|
|
513
|
-
tags.function(tags.variableName),
|
|
514
|
-
tags.labelName
|
|
515
|
-
],
|
|
516
|
-
class: codeMark
|
|
517
|
-
},
|
|
518
|
-
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
519
|
-
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
520
|
-
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
521
|
-
// the code, but all other CSS properties will be inherited.
|
|
522
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
523
|
-
{
|
|
524
|
-
tag: [
|
|
525
|
-
markdownTags.CodeText,
|
|
526
|
-
markdownTags.InlineCode
|
|
527
|
-
],
|
|
528
|
-
class: code
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
tag: [
|
|
532
|
-
markdownTags.QuoteMark
|
|
533
|
-
],
|
|
534
|
-
class: blockquote
|
|
535
|
-
},
|
|
536
|
-
{
|
|
537
|
-
tag: [
|
|
538
|
-
markdownTags.HorizontalRule
|
|
539
|
-
],
|
|
540
|
-
class: horizontalRule
|
|
541
|
-
}
|
|
542
|
-
], {
|
|
543
|
-
scope: markdownLanguage,
|
|
544
|
-
all: {
|
|
545
|
-
fontFamily: get(tokens, "fontFamily.body", []).join(",")
|
|
971
|
+
Table.defineNodes?.forEach((node) => {
|
|
972
|
+
switch (node?.name) {
|
|
973
|
+
case "TableCell": {
|
|
974
|
+
node.style = markdownTags.TableCell;
|
|
975
|
+
break;
|
|
976
|
+
}
|
|
546
977
|
}
|
|
547
978
|
});
|
|
979
|
+
var markdownTagsExtensions = [
|
|
980
|
+
Table,
|
|
981
|
+
{
|
|
982
|
+
props: [
|
|
983
|
+
styleTags(markdownTags)
|
|
984
|
+
]
|
|
985
|
+
}
|
|
986
|
+
];
|
|
987
|
+
var markdownHighlightStyle = (readonly) => {
|
|
988
|
+
return HighlightStyle.define([
|
|
989
|
+
{
|
|
990
|
+
tag: [
|
|
991
|
+
tags.keyword,
|
|
992
|
+
tags.name,
|
|
993
|
+
tags.deleted,
|
|
994
|
+
tags.character,
|
|
995
|
+
tags.propertyName,
|
|
996
|
+
tags.macroName,
|
|
997
|
+
tags.color,
|
|
998
|
+
tags.constant(tags.name),
|
|
999
|
+
tags.standard(tags.name),
|
|
1000
|
+
tags.definition(tags.name),
|
|
1001
|
+
tags.separator,
|
|
1002
|
+
tags.typeName,
|
|
1003
|
+
tags.className,
|
|
1004
|
+
tags.number,
|
|
1005
|
+
tags.changed,
|
|
1006
|
+
tags.annotation,
|
|
1007
|
+
tags.modifier,
|
|
1008
|
+
tags.self,
|
|
1009
|
+
tags.namespace,
|
|
1010
|
+
tags.operator,
|
|
1011
|
+
tags.operatorKeyword,
|
|
1012
|
+
tags.escape,
|
|
1013
|
+
tags.regexp,
|
|
1014
|
+
tags.special(tags.string),
|
|
1015
|
+
tags.meta,
|
|
1016
|
+
tags.comment,
|
|
1017
|
+
tags.atom,
|
|
1018
|
+
tags.bool,
|
|
1019
|
+
tags.special(tags.variableName),
|
|
1020
|
+
tags.processingInstruction,
|
|
1021
|
+
tags.string,
|
|
1022
|
+
tags.inserted,
|
|
1023
|
+
tags.invalid
|
|
1024
|
+
],
|
|
1025
|
+
color: "inherit !important"
|
|
1026
|
+
},
|
|
1027
|
+
// Markdown marks.
|
|
1028
|
+
{
|
|
1029
|
+
tag: [
|
|
1030
|
+
tags.meta,
|
|
1031
|
+
tags.processingInstruction,
|
|
1032
|
+
markdownTags.LinkLabel,
|
|
1033
|
+
markdownTags.LinkReference,
|
|
1034
|
+
markdownTags.ListMark
|
|
1035
|
+
],
|
|
1036
|
+
class: mark
|
|
1037
|
+
},
|
|
1038
|
+
// Markdown marks.
|
|
1039
|
+
{
|
|
1040
|
+
tag: [
|
|
1041
|
+
markdownTags.CodeMark,
|
|
1042
|
+
markdownTags.HeaderMark,
|
|
1043
|
+
markdownTags.QuoteMark,
|
|
1044
|
+
markdownTags.EmphasisMark
|
|
1045
|
+
],
|
|
1046
|
+
class: readonly ? "hidden" : mark
|
|
1047
|
+
},
|
|
1048
|
+
// E.g., code block language (after ```).
|
|
1049
|
+
{
|
|
1050
|
+
tag: [
|
|
1051
|
+
tags.function(tags.variableName),
|
|
1052
|
+
tags.labelName
|
|
1053
|
+
],
|
|
1054
|
+
class: readonly ? "hidden" : codeMark
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
tag: [
|
|
1058
|
+
tags.monospace
|
|
1059
|
+
],
|
|
1060
|
+
class: "font-mono"
|
|
1061
|
+
},
|
|
1062
|
+
// Headings.
|
|
1063
|
+
{
|
|
1064
|
+
tag: tags.heading1,
|
|
1065
|
+
class: heading(1, readonly)
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
tag: tags.heading2,
|
|
1069
|
+
class: heading(2, readonly)
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
tag: tags.heading3,
|
|
1073
|
+
class: heading(3, readonly)
|
|
1074
|
+
},
|
|
1075
|
+
{
|
|
1076
|
+
tag: tags.heading4,
|
|
1077
|
+
class: heading(4, readonly)
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
tag: tags.heading5,
|
|
1081
|
+
class: heading(5, readonly)
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
tag: tags.heading6,
|
|
1085
|
+
class: heading(6, readonly)
|
|
1086
|
+
},
|
|
1087
|
+
// Emphasis.
|
|
1088
|
+
{
|
|
1089
|
+
tag: tags.emphasis,
|
|
1090
|
+
class: italic
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
tag: tags.strong,
|
|
1094
|
+
class: bold
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
tag: tags.strikethrough,
|
|
1098
|
+
class: strikethrough
|
|
1099
|
+
},
|
|
1100
|
+
// Naked URLs.
|
|
1101
|
+
{
|
|
1102
|
+
tag: [
|
|
1103
|
+
markdownTags.URL
|
|
1104
|
+
],
|
|
1105
|
+
class: inlineUrl
|
|
1106
|
+
},
|
|
1107
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
1108
|
+
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
1109
|
+
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
1110
|
+
// the code, but all other CSS properties will be inherited.
|
|
1111
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
1112
|
+
{
|
|
1113
|
+
tag: [
|
|
1114
|
+
markdownTags.CodeText,
|
|
1115
|
+
markdownTags.InlineCode
|
|
1116
|
+
],
|
|
1117
|
+
class: code
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
tag: [
|
|
1121
|
+
markdownTags.QuoteMark
|
|
1122
|
+
],
|
|
1123
|
+
class: blockquote
|
|
1124
|
+
},
|
|
1125
|
+
// TODO(burdon): Replace with extension.
|
|
1126
|
+
{
|
|
1127
|
+
tag: [
|
|
1128
|
+
markdownTags.HorizontalRule
|
|
1129
|
+
],
|
|
1130
|
+
class: mx3(horizontalRule, readonly && "-indent-[100rem]")
|
|
1131
|
+
},
|
|
1132
|
+
// TODO(burdon): Only if being edited.
|
|
1133
|
+
{
|
|
1134
|
+
tag: [
|
|
1135
|
+
markdownTags.TableCell
|
|
1136
|
+
],
|
|
1137
|
+
class: "font-mono"
|
|
1138
|
+
}
|
|
1139
|
+
], {
|
|
1140
|
+
scope: markdownLanguage,
|
|
1141
|
+
all: {
|
|
1142
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
};
|
|
548
1146
|
|
|
549
1147
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
|
|
550
|
-
var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
1148
|
+
var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
551
1149
|
return [
|
|
1150
|
+
EditorState.allowMultipleSelections.of(true),
|
|
1151
|
+
EditorState.tabSize.of(2),
|
|
1152
|
+
EditorView8.lineWrapping,
|
|
1153
|
+
customKeymap(),
|
|
552
1154
|
bracketMatching2(),
|
|
553
1155
|
closeBrackets2(),
|
|
554
|
-
_placeholder && placeholder2(_placeholder),
|
|
555
|
-
EditorState.allowMultipleSelections.of(true),
|
|
556
|
-
EditorView4.lineWrapping,
|
|
557
1156
|
crosshairCursor(),
|
|
558
1157
|
dropCursor(),
|
|
559
|
-
|
|
1158
|
+
drawSelection2(),
|
|
560
1159
|
highlightActiveLine(),
|
|
561
|
-
highlightActiveLineGutter(),
|
|
562
|
-
highlightSelectionMatches(),
|
|
563
|
-
highlightSpecialChars(),
|
|
564
1160
|
history(),
|
|
565
1161
|
indentOnInput(),
|
|
566
|
-
|
|
567
|
-
// TODO(burdon): Review.
|
|
568
|
-
keymap4.of([
|
|
569
|
-
...closeBracketsKeymap,
|
|
570
|
-
...defaultKeymap,
|
|
571
|
-
// ...foldKeymap,
|
|
572
|
-
// ...historyKeymap,
|
|
573
|
-
// ...lintKeymap,
|
|
574
|
-
...searchKeymap,
|
|
575
|
-
indentWithTab
|
|
576
|
-
]),
|
|
1162
|
+
_placeholder && placeholder2(_placeholder),
|
|
577
1163
|
// Main extension.
|
|
578
1164
|
// https://github.com/codemirror/lang-markdown
|
|
579
1165
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -588,20 +1174,156 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
588
1174
|
codeLanguages: languages,
|
|
589
1175
|
// Parser extensions.
|
|
590
1176
|
extensions: [
|
|
591
|
-
// GFM
|
|
592
|
-
|
|
1177
|
+
// GFM provided by default.
|
|
1178
|
+
markdownTagsExtensions
|
|
593
1179
|
]
|
|
594
1180
|
}),
|
|
1181
|
+
// https://github.com/codemirror/theme-one-dark
|
|
1182
|
+
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
595
1183
|
// Custom styles.
|
|
596
|
-
syntaxHighlighting2(markdownHighlightStyle)
|
|
597
|
-
// TODO(thure): All but one rule here apply to both themes; rename or refactor.
|
|
598
|
-
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
|
|
1184
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
599
1185
|
].filter(Boolean);
|
|
600
1186
|
};
|
|
1187
|
+
var customKeymap = () => keymap5.of([
|
|
1188
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1189
|
+
indentWithTab,
|
|
1190
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1191
|
+
...standardKeymap,
|
|
1192
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1193
|
+
...historyKeymap,
|
|
1194
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1195
|
+
...closeBracketsKeymap,
|
|
1196
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1197
|
+
...searchKeymap
|
|
1198
|
+
]);
|
|
1199
|
+
|
|
1200
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/mention.ts
|
|
1201
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1202
|
+
var mention = ({ onSearch }) => {
|
|
1203
|
+
return autocompletion2({
|
|
1204
|
+
closeOnBlur: false,
|
|
1205
|
+
override: [
|
|
1206
|
+
(context) => {
|
|
1207
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
1208
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1211
|
+
console.log(match);
|
|
1212
|
+
return {
|
|
1213
|
+
from: match.from,
|
|
1214
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
1215
|
+
label: `@${value}`
|
|
1216
|
+
}))
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
]
|
|
1220
|
+
});
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
|
|
1224
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1225
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
|
|
1226
|
+
import { Decoration as Decoration6, EditorView as EditorView9, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1227
|
+
var table = (options = {}) => {
|
|
1228
|
+
return StateField5.define({
|
|
1229
|
+
create: (state) => update3(state, options),
|
|
1230
|
+
update: (_, tr) => update3(tr.state, options),
|
|
1231
|
+
provide: (field) => EditorView9.decorations.from(field)
|
|
1232
|
+
});
|
|
1233
|
+
};
|
|
1234
|
+
var update3 = (state, options) => {
|
|
1235
|
+
const builder = new RangeSetBuilder3();
|
|
1236
|
+
const cursor = state.selection.main.head;
|
|
1237
|
+
const tables = [];
|
|
1238
|
+
const getTable = () => tables[tables.length - 1];
|
|
1239
|
+
const getRow = () => {
|
|
1240
|
+
const table2 = getTable();
|
|
1241
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
1242
|
+
};
|
|
1243
|
+
syntaxTree3(state).iterate({
|
|
1244
|
+
enter: (node) => {
|
|
1245
|
+
switch (node.name) {
|
|
1246
|
+
case "Table": {
|
|
1247
|
+
tables.push({
|
|
1248
|
+
from: node.from,
|
|
1249
|
+
to: node.to
|
|
1250
|
+
});
|
|
1251
|
+
break;
|
|
1252
|
+
}
|
|
1253
|
+
case "TableHeader": {
|
|
1254
|
+
getTable().header = [];
|
|
1255
|
+
break;
|
|
1256
|
+
}
|
|
1257
|
+
case "TableRow": {
|
|
1258
|
+
(getTable().rows ??= []).push([]);
|
|
1259
|
+
break;
|
|
1260
|
+
}
|
|
1261
|
+
case "TableCell": {
|
|
1262
|
+
const row = getRow();
|
|
1263
|
+
if (row) {
|
|
1264
|
+
row.push(state.sliceDoc(node.from, node.to));
|
|
1265
|
+
} else {
|
|
1266
|
+
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
1267
|
+
}
|
|
1268
|
+
break;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
});
|
|
1273
|
+
tables.forEach((table2) => {
|
|
1274
|
+
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
1275
|
+
hide && builder.add(table2.from, table2.to, Decoration6.replace({
|
|
1276
|
+
widget: new TableWidget(table2)
|
|
1277
|
+
}));
|
|
1278
|
+
builder.add(table2.from, table2.to, Decoration6.mark({
|
|
1279
|
+
class: "cm-table"
|
|
1280
|
+
}));
|
|
1281
|
+
});
|
|
1282
|
+
return builder.finish();
|
|
1283
|
+
};
|
|
1284
|
+
var TableWidget = class extends WidgetType4 {
|
|
1285
|
+
constructor(_table) {
|
|
1286
|
+
super();
|
|
1287
|
+
this._table = _table;
|
|
1288
|
+
}
|
|
1289
|
+
eq(other) {
|
|
1290
|
+
return this._table.from === other?._table?.from;
|
|
1291
|
+
}
|
|
1292
|
+
toDOM(view) {
|
|
1293
|
+
const table2 = document.createElement("table");
|
|
1294
|
+
{
|
|
1295
|
+
const header = table2.appendChild(document.createElement("thead"));
|
|
1296
|
+
const tr = header.appendChild(document.createElement("tr"));
|
|
1297
|
+
this._table.header?.forEach((cell) => {
|
|
1298
|
+
const th = document.createElement("th");
|
|
1299
|
+
th.setAttribute("class", "cm-table-head");
|
|
1300
|
+
tr.appendChild(th).textContent = cell;
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
{
|
|
1304
|
+
const body = table2.appendChild(document.createElement("tbody"));
|
|
1305
|
+
this._table.rows?.forEach((row) => {
|
|
1306
|
+
const tr = body.appendChild(document.createElement("tr"));
|
|
1307
|
+
row.forEach((cell) => {
|
|
1308
|
+
const td = document.createElement("td");
|
|
1309
|
+
td.setAttribute("class", "cm-table-cell");
|
|
1310
|
+
tr.appendChild(td).textContent = cell;
|
|
1311
|
+
});
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
return table2;
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
601
1317
|
|
|
602
1318
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
|
|
603
|
-
import { EditorView as
|
|
604
|
-
var
|
|
1319
|
+
import { EditorView as EditorView10, Decoration as Decoration7, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
1320
|
+
var styles4 = EditorView10.baseTheme({
|
|
1321
|
+
"& .cm-task-item": {
|
|
1322
|
+
paddingLeft: "4px",
|
|
1323
|
+
paddingRight: "8px"
|
|
1324
|
+
}
|
|
1325
|
+
});
|
|
1326
|
+
var CheckboxWidget = class extends WidgetType5 {
|
|
605
1327
|
constructor(_pos, _checked, _indent, _onCheck) {
|
|
606
1328
|
super();
|
|
607
1329
|
this._pos = _pos;
|
|
@@ -620,30 +1342,29 @@ var CheckboxWidget = class extends WidgetType3 {
|
|
|
620
1342
|
const input = wrap.appendChild(document.createElement("input"));
|
|
621
1343
|
input.type = "checkbox";
|
|
622
1344
|
input.checked = this._checked;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
1345
|
+
if (!this._onCheck) {
|
|
1346
|
+
input.setAttribute("disabled", "true");
|
|
1347
|
+
}
|
|
1348
|
+
if (this._onCheck) {
|
|
1349
|
+
input.onchange = (event) => {
|
|
1350
|
+
this._onCheck?.(event.target.checked);
|
|
1351
|
+
return true;
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
627
1354
|
return wrap;
|
|
628
1355
|
}
|
|
629
1356
|
ignoreEvent() {
|
|
630
1357
|
return false;
|
|
631
1358
|
}
|
|
632
1359
|
};
|
|
633
|
-
var
|
|
634
|
-
"& .cm-task-item": {
|
|
635
|
-
paddingLeft: "4px",
|
|
636
|
-
paddingRight: "8px"
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
var tasklist = () => {
|
|
1360
|
+
var tasklist = (options = {}) => {
|
|
640
1361
|
const taskMatcher = new MatchDecorator2({
|
|
641
1362
|
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
642
1363
|
decoration: (match, view, pos) => {
|
|
643
1364
|
const indent = Math.floor(match[1].length / 2);
|
|
644
1365
|
const checked = match[2] === "x" || match[2] === "X";
|
|
645
|
-
return
|
|
646
|
-
widget: new CheckboxWidget(pos, checked, indent, (checked2) => {
|
|
1366
|
+
return Decoration7.replace({
|
|
1367
|
+
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
647
1368
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
648
1369
|
view.dispatch({
|
|
649
1370
|
changes: {
|
|
@@ -660,22 +1381,22 @@ var tasklist = () => {
|
|
|
660
1381
|
});
|
|
661
1382
|
}
|
|
662
1383
|
});
|
|
663
|
-
const tasks =
|
|
1384
|
+
const tasks = ViewPlugin3.fromClass(class {
|
|
664
1385
|
constructor(view) {
|
|
665
1386
|
this.tasks = taskMatcher.createDeco(view);
|
|
666
1387
|
}
|
|
667
|
-
update(
|
|
668
|
-
this.tasks = taskMatcher.updateDeco(
|
|
1388
|
+
update(update4) {
|
|
1389
|
+
this.tasks = taskMatcher.updateDeco(update4, this.tasks);
|
|
669
1390
|
}
|
|
670
1391
|
}, {
|
|
671
|
-
decorations: (
|
|
672
|
-
provide: (plugin) =>
|
|
673
|
-
return view.plugin(plugin)?.tasks ||
|
|
1392
|
+
decorations: (value) => value.tasks,
|
|
1393
|
+
provide: (plugin) => EditorView10.atomicRanges.of((view) => {
|
|
1394
|
+
return view.plugin(plugin)?.tasks || Decoration7.none;
|
|
674
1395
|
})
|
|
675
1396
|
});
|
|
676
1397
|
return [
|
|
677
1398
|
tasks,
|
|
678
|
-
|
|
1399
|
+
styles4
|
|
679
1400
|
];
|
|
680
1401
|
};
|
|
681
1402
|
|
|
@@ -724,7 +1445,7 @@ var tooltip = ({ onHover, regexp = markdownLinkRegexp }) => hoverTooltip((view,
|
|
|
724
1445
|
});
|
|
725
1446
|
|
|
726
1447
|
// packages/ui/react-ui-editor/src/components/TextEditor/themes/default.ts
|
|
727
|
-
import
|
|
1448
|
+
import get3 from "lodash.get";
|
|
728
1449
|
var defaultTheme = {
|
|
729
1450
|
//
|
|
730
1451
|
// Main layout:
|
|
@@ -741,7 +1462,8 @@ var defaultTheme = {
|
|
|
741
1462
|
outline: "none"
|
|
742
1463
|
},
|
|
743
1464
|
"& .cm-scroller": {
|
|
744
|
-
overflow: "visible"
|
|
1465
|
+
overflow: "visible",
|
|
1466
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
745
1467
|
},
|
|
746
1468
|
"& .cm-content": {
|
|
747
1469
|
padding: 0,
|
|
@@ -749,20 +1471,20 @@ var defaultTheme = {
|
|
|
749
1471
|
fontSize: "16px"
|
|
750
1472
|
},
|
|
751
1473
|
"&light .cm-content": {
|
|
752
|
-
color:
|
|
1474
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
753
1475
|
caretColor: "black"
|
|
754
1476
|
},
|
|
755
1477
|
"&dark .cm-content": {
|
|
756
|
-
color:
|
|
1478
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
757
1479
|
caretColor: "white"
|
|
758
1480
|
},
|
|
759
1481
|
//
|
|
760
1482
|
// Cursor
|
|
761
1483
|
//
|
|
762
|
-
"&light .cm-cursor": {
|
|
1484
|
+
"&light .cm-cursor, &light .cm-dropCursor": {
|
|
763
1485
|
borderLeft: "2px solid black"
|
|
764
1486
|
},
|
|
765
|
-
"&dark .cm-cursor": {
|
|
1487
|
+
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
766
1488
|
borderLeft: "2px solid white"
|
|
767
1489
|
},
|
|
768
1490
|
"& .cm-placeholder": {
|
|
@@ -782,16 +1504,16 @@ var defaultTheme = {
|
|
|
782
1504
|
// selection
|
|
783
1505
|
//
|
|
784
1506
|
"&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground": {
|
|
785
|
-
background:
|
|
1507
|
+
background: get3(tokens, "extend.colors.primary.150", "#00ffff")
|
|
786
1508
|
},
|
|
787
1509
|
"&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground": {
|
|
788
|
-
background:
|
|
1510
|
+
background: get3(tokens, "extend.colors.primary.850", "#00ffff")
|
|
789
1511
|
},
|
|
790
1512
|
"&light .cm-selectionMatch": {
|
|
791
|
-
background:
|
|
1513
|
+
background: get3(tokens, "extend.colors.primary.250", "#00ffff") + "44"
|
|
792
1514
|
},
|
|
793
1515
|
"&dark .cm-selectionMatch": {
|
|
794
|
-
background:
|
|
1516
|
+
background: get3(tokens, "extend.colors.primary.600", "#00ffff") + "44"
|
|
795
1517
|
},
|
|
796
1518
|
//
|
|
797
1519
|
// collaboration
|
|
@@ -824,12 +1546,12 @@ var defaultTheme = {
|
|
|
824
1546
|
// link
|
|
825
1547
|
//
|
|
826
1548
|
"& .cm-link": {
|
|
827
|
-
color:
|
|
1549
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
828
1550
|
textDecorationLine: "underline",
|
|
829
1551
|
textDecorationThickness: "1px",
|
|
830
1552
|
textUnderlineOffset: "2px",
|
|
831
1553
|
borderRadius: ".125rem",
|
|
832
|
-
fontFamily:
|
|
1554
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
833
1555
|
},
|
|
834
1556
|
//
|
|
835
1557
|
// tooltip
|
|
@@ -837,14 +1559,61 @@ var defaultTheme = {
|
|
|
837
1559
|
"& .cm-tooltip": {
|
|
838
1560
|
border: "none"
|
|
839
1561
|
},
|
|
840
|
-
|
|
841
|
-
//
|
|
1562
|
+
"& .cm-tooltip-below": {},
|
|
1563
|
+
//
|
|
1564
|
+
// autocomplete
|
|
1565
|
+
//
|
|
1566
|
+
"& .cm-tooltip-autocomplete": {
|
|
1567
|
+
marginTop: "4px",
|
|
1568
|
+
marginLeft: "-3px"
|
|
1569
|
+
},
|
|
1570
|
+
"& .cm-tooltip-autocomplete ul li": {},
|
|
1571
|
+
"& .cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
1572
|
+
"& .cm-completionIcon": {
|
|
1573
|
+
display: "none"
|
|
1574
|
+
},
|
|
1575
|
+
"& .cm-completionLabel": {
|
|
1576
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
1577
|
+
},
|
|
1578
|
+
"& .cm-completionMatchedText": {
|
|
1579
|
+
textDecoration: "none"
|
|
1580
|
+
},
|
|
1581
|
+
//
|
|
1582
|
+
// widgets
|
|
1583
|
+
//
|
|
1584
|
+
"& .cm-widgetBuffer": {
|
|
1585
|
+
display: "none",
|
|
1586
|
+
height: 0
|
|
1587
|
+
},
|
|
1588
|
+
//
|
|
1589
|
+
// table
|
|
1590
|
+
//
|
|
1591
|
+
"& .cm-table *": {
|
|
1592
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
1593
|
+
textDecoration: "none !important"
|
|
1594
|
+
},
|
|
1595
|
+
"& .cm-table-head": {
|
|
1596
|
+
padding: "2px 16px 2px 0px",
|
|
1597
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
1598
|
+
fontWeight: 100,
|
|
1599
|
+
textAlign: "left",
|
|
1600
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
1601
|
+
},
|
|
1602
|
+
"& .cm-table-cell": {
|
|
1603
|
+
padding: "2px 16px 2px 0px"
|
|
1604
|
+
},
|
|
1605
|
+
//
|
|
1606
|
+
// image
|
|
1607
|
+
//
|
|
1608
|
+
"& .cm-image": {
|
|
1609
|
+
margin: "0.5rem 0"
|
|
1610
|
+
},
|
|
842
1611
|
//
|
|
843
1612
|
// font size
|
|
844
1613
|
// 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.
|
|
845
1614
|
//
|
|
846
|
-
...Object.keys(
|
|
847
|
-
const height =
|
|
1615
|
+
...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
|
|
1616
|
+
const height = get3(tokens, [
|
|
848
1617
|
"extend",
|
|
849
1618
|
"fontSize",
|
|
850
1619
|
fontSize,
|
|
@@ -861,46 +1630,81 @@ var defaultTheme = {
|
|
|
861
1630
|
height
|
|
862
1631
|
};
|
|
863
1632
|
return acc;
|
|
864
|
-
}, {})
|
|
1633
|
+
}, {}),
|
|
1634
|
+
/**
|
|
1635
|
+
* Panels
|
|
1636
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
1637
|
+
*
|
|
1638
|
+
* Find/replace panel.
|
|
1639
|
+
* <div class="cm-announced">...</div>
|
|
1640
|
+
* <div class="cm-scroller">...</div>
|
|
1641
|
+
* <div class="cm-panels cm-panels-bottom">
|
|
1642
|
+
* <div class="cm-search cm-panel">
|
|
1643
|
+
* <input class="cm-textfield" />
|
|
1644
|
+
* <button class="cm-button">...</button>
|
|
1645
|
+
* <label><input type="checkbox" />...</label>
|
|
1646
|
+
* </div>
|
|
1647
|
+
* </div
|
|
1648
|
+
*/
|
|
1649
|
+
"& .cm-panels": {
|
|
1650
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`,
|
|
1651
|
+
borderBottom: "none"
|
|
1652
|
+
},
|
|
1653
|
+
"& .cm-panel": {
|
|
1654
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
1655
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
1656
|
+
},
|
|
1657
|
+
"& .cm-button": {
|
|
1658
|
+
margin: "4px",
|
|
1659
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
1660
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
1661
|
+
border: "none"
|
|
1662
|
+
},
|
|
1663
|
+
"& .cm-searchMatch": {
|
|
1664
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
1665
|
+
},
|
|
1666
|
+
"& .cm-searchMatch.cm-searchMatch-selected": {
|
|
1667
|
+
backgroundColor: get3(tokens, "extend.colors.primary.100")
|
|
1668
|
+
}
|
|
865
1669
|
};
|
|
866
1670
|
var textTheme = {
|
|
867
1671
|
"& .cm-scroller": {
|
|
868
|
-
fontFamily:
|
|
1672
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
869
1673
|
},
|
|
870
1674
|
"& .cm-placeholder": {
|
|
871
|
-
fontFamily:
|
|
1675
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
872
1676
|
}
|
|
873
1677
|
};
|
|
874
1678
|
var markdownTheme = {
|
|
875
1679
|
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
876
1680
|
"& .cm-placeholder": {
|
|
877
|
-
fontFamily:
|
|
1681
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
878
1682
|
}
|
|
879
1683
|
};
|
|
880
1684
|
var codeTheme = {
|
|
881
1685
|
"& .cm-scroller": {
|
|
882
|
-
fontFamily:
|
|
1686
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
883
1687
|
},
|
|
884
1688
|
"& .cm-placeholder": {
|
|
885
|
-
fontFamily:
|
|
1689
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
886
1690
|
}
|
|
887
1691
|
};
|
|
888
1692
|
|
|
889
1693
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
890
1694
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
891
|
-
import { EditorView as
|
|
1695
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
|
892
1696
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
893
1697
|
import { vim } from "@replit/codemirror-vim";
|
|
894
|
-
import
|
|
895
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
1698
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
1699
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
|
|
896
1700
|
import { generateName } from "@dxos/display-name";
|
|
897
1701
|
import { useThemeContext } from "@dxos/react-ui";
|
|
898
|
-
import { getColorForValue, inputSurface, mx as
|
|
1702
|
+
import { getColorForValue, inputSurface, mx as mx4 } from "@dxos/react-ui-theme";
|
|
899
1703
|
var EditorModes = [
|
|
900
1704
|
"default",
|
|
901
1705
|
"vim"
|
|
902
1706
|
];
|
|
903
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots = defaultSlots
|
|
1707
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
|
|
904
1708
|
const { themeMode } = useThemeContext();
|
|
905
1709
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
906
1710
|
tabBehavior: "limited"
|
|
@@ -918,7 +1722,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
918
1722
|
root
|
|
919
1723
|
]);
|
|
920
1724
|
const { awareness, peer } = model;
|
|
921
|
-
|
|
1725
|
+
useEffect2(() => {
|
|
922
1726
|
if (awareness && peer) {
|
|
923
1727
|
awareness.setLocalStateField("user", {
|
|
924
1728
|
name: peer.name ?? generateName(peer.id),
|
|
@@ -938,20 +1742,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
938
1742
|
peer,
|
|
939
1743
|
themeMode
|
|
940
1744
|
]);
|
|
941
|
-
|
|
1745
|
+
useEffect2(() => {
|
|
942
1746
|
if (!root) {
|
|
943
1747
|
return;
|
|
944
1748
|
}
|
|
945
1749
|
const state2 = EditorState2.create({
|
|
946
1750
|
doc: model.text(),
|
|
947
1751
|
extensions: [
|
|
1752
|
+
readonly && EditorState2.readOnly.of(readonly),
|
|
948
1753
|
// TODO(burdon): Factor out VIM mode?
|
|
949
1754
|
editorMode === "vim" && vim(),
|
|
950
1755
|
// Theme.
|
|
951
|
-
|
|
952
|
-
|
|
1756
|
+
// TODO(burdon): Make optional.
|
|
1757
|
+
EditorView11.baseTheme(defaultTheme),
|
|
1758
|
+
EditorView11.theme(slots?.editor?.theme ?? {}),
|
|
953
1759
|
// TODO(burdon): themeMode doesn't change in storybooks.
|
|
954
|
-
|
|
1760
|
+
EditorView11.darkTheme.of(themeMode === "dark"),
|
|
955
1761
|
// Storage and replication.
|
|
956
1762
|
model.extension,
|
|
957
1763
|
// Custom.
|
|
@@ -959,7 +1765,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
959
1765
|
].filter(Boolean)
|
|
960
1766
|
});
|
|
961
1767
|
view?.destroy();
|
|
962
|
-
setView(new
|
|
1768
|
+
setView(new EditorView11({
|
|
963
1769
|
state: state2,
|
|
964
1770
|
parent: root
|
|
965
1771
|
}));
|
|
@@ -973,6 +1779,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
973
1779
|
root,
|
|
974
1780
|
model,
|
|
975
1781
|
themeMode,
|
|
1782
|
+
readonly,
|
|
976
1783
|
editorMode
|
|
977
1784
|
]);
|
|
978
1785
|
const handleKeyUp = useCallback((event) => {
|
|
@@ -1000,43 +1807,36 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
1000
1807
|
onKeyUp: handleKeyUp
|
|
1001
1808
|
});
|
|
1002
1809
|
});
|
|
1003
|
-
var
|
|
1004
|
-
const items = localStorage.getItem("dxos.composer.demo");
|
|
1005
|
-
if (items) {
|
|
1006
|
-
return demo({
|
|
1007
|
-
items: items.split(",")
|
|
1008
|
-
});
|
|
1009
|
-
}
|
|
1010
|
-
return [];
|
|
1011
|
-
};
|
|
1012
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1810
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1013
1811
|
const { themeMode } = useThemeContext();
|
|
1014
|
-
const slots =
|
|
1812
|
+
const slots = defaultsDeep2({}, _slots, defaultTextSlots);
|
|
1015
1813
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
1016
1814
|
ref: forwardedRef,
|
|
1815
|
+
readonly,
|
|
1017
1816
|
extensions: [
|
|
1018
1817
|
basicBundle({
|
|
1818
|
+
readonly,
|
|
1019
1819
|
themeMode,
|
|
1020
1820
|
placeholder: slots?.editor?.placeholder
|
|
1021
1821
|
}),
|
|
1022
|
-
maybeDebug(),
|
|
1023
1822
|
...extensions
|
|
1024
1823
|
],
|
|
1025
1824
|
slots,
|
|
1026
1825
|
...props
|
|
1027
1826
|
});
|
|
1028
1827
|
});
|
|
1029
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1828
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1030
1829
|
const { themeMode } = useThemeContext();
|
|
1031
|
-
const slots =
|
|
1830
|
+
const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
|
|
1032
1831
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
1033
1832
|
ref: forwardedRef,
|
|
1833
|
+
readonly,
|
|
1034
1834
|
extensions: [
|
|
1035
1835
|
markdownBundle({
|
|
1836
|
+
readonly,
|
|
1036
1837
|
themeMode,
|
|
1037
1838
|
placeholder: slots?.editor?.placeholder
|
|
1038
1839
|
}),
|
|
1039
|
-
maybeDebug(),
|
|
1040
1840
|
...extensions
|
|
1041
1841
|
],
|
|
1042
1842
|
slots,
|
|
@@ -1045,7 +1845,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
|
|
|
1045
1845
|
});
|
|
1046
1846
|
var defaultSlots = {
|
|
1047
1847
|
root: {
|
|
1048
|
-
className:
|
|
1848
|
+
className: mx4("p-2", inputSurface)
|
|
1049
1849
|
}
|
|
1050
1850
|
};
|
|
1051
1851
|
var defaultTextSlots = {
|
|
@@ -1062,23 +1862,23 @@ var defaultMarkdownSlots = {
|
|
|
1062
1862
|
};
|
|
1063
1863
|
|
|
1064
1864
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1065
|
-
import
|
|
1066
|
-
import { useEffect as
|
|
1865
|
+
import get4 from "lodash.get";
|
|
1866
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
1067
1867
|
import { yCollab } from "y-codemirror.next";
|
|
1068
|
-
import { invariant as
|
|
1868
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1069
1869
|
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
1070
1870
|
|
|
1071
1871
|
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1072
|
-
import { Annotation, Facet, StateEffect, StateField as
|
|
1073
|
-
import { ViewPlugin as
|
|
1872
|
+
import { Annotation, Facet, StateEffect as StateEffect2, StateField as StateField6 } from "@codemirror/state";
|
|
1873
|
+
import { ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1074
1874
|
import * as automerge2 from "@dxos/automerge/automerge";
|
|
1075
1875
|
|
|
1076
1876
|
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
1077
1877
|
import { next as automerge } from "@dxos/automerge/automerge";
|
|
1078
1878
|
|
|
1079
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1879
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
|
|
1080
1880
|
import { ChangeSet } from "@codemirror/state";
|
|
1081
|
-
var
|
|
1881
|
+
var automergeToCodemirror = (view, selection, target, patches) => {
|
|
1082
1882
|
for (const patch of patches) {
|
|
1083
1883
|
const changeSpec = handlePatch(patch, target, view.state);
|
|
1084
1884
|
if (changeSpec != null) {
|
|
@@ -1183,9 +1983,9 @@ var charPath = (textPath, candidatePath) => {
|
|
|
1183
1983
|
return null;
|
|
1184
1984
|
};
|
|
1185
1985
|
|
|
1186
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1986
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
|
|
1187
1987
|
import { next as am } from "@dxos/automerge/automerge";
|
|
1188
|
-
var
|
|
1988
|
+
var codemirrorToAutomerge = (field, handle, transactions, state) => {
|
|
1189
1989
|
const { lastHeads, path } = state.field(field);
|
|
1190
1990
|
let hasChanges = false;
|
|
1191
1991
|
for (const tr of transactions) {
|
|
@@ -1229,12 +2029,12 @@ var PatchSemaphore = class {
|
|
|
1229
2029
|
annotations: reconcileAnnotationType.of(true)
|
|
1230
2030
|
});
|
|
1231
2031
|
}
|
|
1232
|
-
let newHeads =
|
|
2032
|
+
let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
|
|
1233
2033
|
if (newHeads === null || newHeads === void 0) {
|
|
1234
2034
|
newHeads = automerge.getHeads(handle.docSync());
|
|
1235
2035
|
}
|
|
1236
2036
|
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
1237
|
-
|
|
2037
|
+
automergeToCodemirror(view, selection, path, diff);
|
|
1238
2038
|
view.dispatch({
|
|
1239
2039
|
effects: updateHeads(newHeads),
|
|
1240
2040
|
annotations: reconcileAnnotationType.of({})
|
|
@@ -1248,7 +2048,7 @@ var PatchSemaphore = class {
|
|
|
1248
2048
|
};
|
|
1249
2049
|
|
|
1250
2050
|
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1251
|
-
var effectType =
|
|
2051
|
+
var effectType = StateEffect2.define({});
|
|
1252
2052
|
var updateHeads = (newHeads) => effectType.of({
|
|
1253
2053
|
newHeads
|
|
1254
2054
|
});
|
|
@@ -1258,7 +2058,7 @@ var semaphoreFacet = Facet.define({
|
|
|
1258
2058
|
combine: (values) => values.at(-1)
|
|
1259
2059
|
});
|
|
1260
2060
|
var automergePlugin = (handle, path) => {
|
|
1261
|
-
const stateField =
|
|
2061
|
+
const stateField = StateField6.define({
|
|
1262
2062
|
create: () => ({
|
|
1263
2063
|
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
1264
2064
|
unreconciledTransactions: [],
|
|
@@ -1288,7 +2088,7 @@ var automergePlugin = (handle, path) => {
|
|
|
1288
2088
|
}
|
|
1289
2089
|
});
|
|
1290
2090
|
const semaphore = new PatchSemaphore(stateField);
|
|
1291
|
-
const viewPlugin =
|
|
2091
|
+
const viewPlugin = ViewPlugin4.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
1292
2092
|
constructor(view) {
|
|
1293
2093
|
this._handleChange = () => {
|
|
1294
2094
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
@@ -1296,8 +2096,8 @@ var automergePlugin = (handle, path) => {
|
|
|
1296
2096
|
this._view = view;
|
|
1297
2097
|
handle.addListener("change", this._handleChange);
|
|
1298
2098
|
}
|
|
1299
|
-
update(
|
|
1300
|
-
if (
|
|
2099
|
+
update(update4) {
|
|
2100
|
+
if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
|
|
1301
2101
|
queueMicrotask(() => {
|
|
1302
2102
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
1303
2103
|
});
|
|
@@ -1319,7 +2119,7 @@ var reconcileAnnotationType = Annotation.define();
|
|
|
1319
2119
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
1320
2120
|
|
|
1321
2121
|
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
1322
|
-
import * as
|
|
2122
|
+
import * as random2 from "lib0/random";
|
|
1323
2123
|
var cursorColors = [
|
|
1324
2124
|
{
|
|
1325
2125
|
color: "#30bced",
|
|
@@ -1354,7 +2154,7 @@ var cursorColors = [
|
|
|
1354
2154
|
light: "#1be7ff33"
|
|
1355
2155
|
}
|
|
1356
2156
|
];
|
|
1357
|
-
var cursorColor = cursorColors[
|
|
2157
|
+
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
1358
2158
|
|
|
1359
2159
|
// packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
|
|
1360
2160
|
import * as decoding from "lib0/decoding";
|
|
@@ -1362,7 +2162,7 @@ import * as encoding from "lib0/encoding";
|
|
|
1362
2162
|
import { Observable } from "lib0/observable";
|
|
1363
2163
|
import * as awarenessProtocol from "y-protocols/awareness";
|
|
1364
2164
|
import { log } from "@dxos/log";
|
|
1365
|
-
var
|
|
2165
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
1366
2166
|
var messageAwareness = 1;
|
|
1367
2167
|
var messageQueryAwareness = 3;
|
|
1368
2168
|
var SpaceAwarenessProvider = class extends Observable {
|
|
@@ -1399,7 +2199,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1399
2199
|
removed,
|
|
1400
2200
|
origin
|
|
1401
2201
|
}, {
|
|
1402
|
-
F:
|
|
2202
|
+
F: __dxlog_file3,
|
|
1403
2203
|
L: 67,
|
|
1404
2204
|
S: this,
|
|
1405
2205
|
C: (f, a) => f(...a)
|
|
@@ -1412,7 +2212,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1412
2212
|
}
|
|
1413
2213
|
_handleSpaceMessage({ payload }) {
|
|
1414
2214
|
log("space message", payload, {
|
|
1415
|
-
F:
|
|
2215
|
+
F: __dxlog_file3,
|
|
1416
2216
|
L: 79,
|
|
1417
2217
|
S: this,
|
|
1418
2218
|
C: (f, a) => f(...a)
|
|
@@ -1457,14 +2257,14 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1457
2257
|
};
|
|
1458
2258
|
|
|
1459
2259
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1460
|
-
var
|
|
2260
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
1461
2261
|
var useTextModel = ({ identity, space, text }) => {
|
|
1462
2262
|
const [model, setModel] = useState2(() => createModel({
|
|
1463
2263
|
identity,
|
|
1464
2264
|
space,
|
|
1465
2265
|
text
|
|
1466
2266
|
}));
|
|
1467
|
-
|
|
2267
|
+
useEffect3(() => {
|
|
1468
2268
|
setModel(createModel({
|
|
1469
2269
|
identity,
|
|
1470
2270
|
space,
|
|
@@ -1489,9 +2289,9 @@ var createModel = (options) => {
|
|
|
1489
2289
|
}
|
|
1490
2290
|
};
|
|
1491
2291
|
var createYjsModel = ({ identity, space, text }) => {
|
|
1492
|
-
|
|
1493
|
-
F:
|
|
1494
|
-
L:
|
|
2292
|
+
invariant3(text?.doc && text?.content, void 0, {
|
|
2293
|
+
F: __dxlog_file4,
|
|
2294
|
+
L: 81,
|
|
1495
2295
|
S: void 0,
|
|
1496
2296
|
A: [
|
|
1497
2297
|
"text?.doc && text?.content",
|
|
@@ -1507,6 +2307,7 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
1507
2307
|
id: text.doc.guid,
|
|
1508
2308
|
content: text.content,
|
|
1509
2309
|
text: () => text.content.toString(),
|
|
2310
|
+
ranges: [],
|
|
1510
2311
|
extension: yCollab(text.content, provider?.awareness),
|
|
1511
2312
|
awareness: provider?.awareness,
|
|
1512
2313
|
peer: identity ? {
|
|
@@ -1523,7 +2324,8 @@ var createAutomergeModel = ({ identity, text }) => {
|
|
|
1523
2324
|
return {
|
|
1524
2325
|
id: obj.id,
|
|
1525
2326
|
content: doc,
|
|
1526
|
-
text: () =>
|
|
2327
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2328
|
+
ranges: [],
|
|
1527
2329
|
extension: automergePlugin(doc.handle, doc.path),
|
|
1528
2330
|
peer: identity ? {
|
|
1529
2331
|
id: identity.identityKey.toHex(),
|
|
@@ -1543,25 +2345,35 @@ export {
|
|
|
1543
2345
|
YXmlFragment,
|
|
1544
2346
|
autocomplete,
|
|
1545
2347
|
basicBundle,
|
|
2348
|
+
blast,
|
|
2349
|
+
code2 as code,
|
|
1546
2350
|
codeTheme,
|
|
1547
2351
|
comments,
|
|
1548
2352
|
cursorColor,
|
|
1549
2353
|
defaultMarkdownSlots,
|
|
2354
|
+
defaultOptions,
|
|
1550
2355
|
defaultSlots,
|
|
1551
2356
|
defaultTextSlots,
|
|
1552
2357
|
defaultTheme,
|
|
1553
2358
|
demo,
|
|
2359
|
+
highlight,
|
|
2360
|
+
highlightDecorations,
|
|
2361
|
+
highlightStateField,
|
|
2362
|
+
image,
|
|
1554
2363
|
link,
|
|
1555
|
-
listener,
|
|
2364
|
+
listener2 as listener,
|
|
1556
2365
|
markdownBundle,
|
|
1557
2366
|
markdownHighlightStyle,
|
|
1558
2367
|
markdownTags,
|
|
1559
|
-
|
|
2368
|
+
markdownTagsExtensions,
|
|
1560
2369
|
markdownTheme,
|
|
2370
|
+
mention,
|
|
2371
|
+
table,
|
|
1561
2372
|
tags2 as tags,
|
|
1562
2373
|
tasklist,
|
|
1563
2374
|
textTheme,
|
|
1564
2375
|
tooltip,
|
|
2376
|
+
useHighlights,
|
|
1565
2377
|
useTextModel
|
|
1566
2378
|
};
|
|
1567
2379
|
//# sourceMappingURL=index.mjs.map
|