@dxos/react-ui-editor 0.3.10-main.f916973 → 0.3.10-main.fe592a2
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 +1185 -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 +46 -44
- 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 +97 -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, 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,201 @@ 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
|
-
|
|
560
|
-
highlightActiveLine(),
|
|
561
|
-
highlightActiveLineGutter(),
|
|
562
|
-
highlightSelectionMatches(),
|
|
563
|
-
highlightSpecialChars(),
|
|
1158
|
+
drawSelection2(),
|
|
564
1159
|
history(),
|
|
565
1160
|
indentOnInput(),
|
|
566
|
-
|
|
567
|
-
// TODO(burdon): Review.
|
|
568
|
-
keymap4.of([
|
|
569
|
-
...closeBracketsKeymap,
|
|
570
|
-
...defaultKeymap,
|
|
571
|
-
// ...foldKeymap,
|
|
572
|
-
// ...historyKeymap,
|
|
573
|
-
// ...lintKeymap,
|
|
574
|
-
...searchKeymap,
|
|
575
|
-
indentWithTab
|
|
576
|
-
]),
|
|
1161
|
+
_placeholder && placeholder2(_placeholder),
|
|
577
1162
|
// Main extension.
|
|
578
1163
|
// https://github.com/codemirror/lang-markdown
|
|
579
1164
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -588,20 +1173,156 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
588
1173
|
codeLanguages: languages,
|
|
589
1174
|
// Parser extensions.
|
|
590
1175
|
extensions: [
|
|
591
|
-
// GFM
|
|
592
|
-
|
|
1176
|
+
// GFM provided by default.
|
|
1177
|
+
markdownTagsExtensions
|
|
593
1178
|
]
|
|
594
1179
|
}),
|
|
1180
|
+
// https://github.com/codemirror/theme-one-dark
|
|
1181
|
+
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
595
1182
|
// 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)
|
|
1183
|
+
syntaxHighlighting2(markdownHighlightStyle(readonly))
|
|
599
1184
|
].filter(Boolean);
|
|
600
1185
|
};
|
|
1186
|
+
var customKeymap = () => keymap5.of([
|
|
1187
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1188
|
+
indentWithTab,
|
|
1189
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1190
|
+
...standardKeymap,
|
|
1191
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1192
|
+
...historyKeymap,
|
|
1193
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1194
|
+
...closeBracketsKeymap,
|
|
1195
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1196
|
+
...searchKeymap
|
|
1197
|
+
]);
|
|
1198
|
+
|
|
1199
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/mention.ts
|
|
1200
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
1201
|
+
var mention = ({ onSearch }) => {
|
|
1202
|
+
return autocompletion2({
|
|
1203
|
+
closeOnBlur: false,
|
|
1204
|
+
override: [
|
|
1205
|
+
(context) => {
|
|
1206
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
1207
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
1208
|
+
return null;
|
|
1209
|
+
}
|
|
1210
|
+
console.log(match);
|
|
1211
|
+
return {
|
|
1212
|
+
from: match.from,
|
|
1213
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
1214
|
+
label: `@${value}`
|
|
1215
|
+
}))
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
]
|
|
1219
|
+
});
|
|
1220
|
+
};
|
|
1221
|
+
|
|
1222
|
+
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
|
|
1223
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1224
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
|
|
1225
|
+
import { Decoration as Decoration6, EditorView as EditorView9, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1226
|
+
var table = (options = {}) => {
|
|
1227
|
+
return StateField5.define({
|
|
1228
|
+
create: (state) => update3(state, options),
|
|
1229
|
+
update: (_, tr) => update3(tr.state, options),
|
|
1230
|
+
provide: (field) => EditorView9.decorations.from(field)
|
|
1231
|
+
});
|
|
1232
|
+
};
|
|
1233
|
+
var update3 = (state, options) => {
|
|
1234
|
+
const builder = new RangeSetBuilder3();
|
|
1235
|
+
const cursor = state.selection.main.head;
|
|
1236
|
+
const tables = [];
|
|
1237
|
+
const getTable = () => tables[tables.length - 1];
|
|
1238
|
+
const getRow = () => {
|
|
1239
|
+
const table2 = getTable();
|
|
1240
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
1241
|
+
};
|
|
1242
|
+
syntaxTree3(state).iterate({
|
|
1243
|
+
enter: (node) => {
|
|
1244
|
+
switch (node.name) {
|
|
1245
|
+
case "Table": {
|
|
1246
|
+
tables.push({
|
|
1247
|
+
from: node.from,
|
|
1248
|
+
to: node.to
|
|
1249
|
+
});
|
|
1250
|
+
break;
|
|
1251
|
+
}
|
|
1252
|
+
case "TableHeader": {
|
|
1253
|
+
getTable().header = [];
|
|
1254
|
+
break;
|
|
1255
|
+
}
|
|
1256
|
+
case "TableRow": {
|
|
1257
|
+
(getTable().rows ??= []).push([]);
|
|
1258
|
+
break;
|
|
1259
|
+
}
|
|
1260
|
+
case "TableCell": {
|
|
1261
|
+
const row = getRow();
|
|
1262
|
+
if (row) {
|
|
1263
|
+
row.push(state.sliceDoc(node.from, node.to));
|
|
1264
|
+
} else {
|
|
1265
|
+
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
1266
|
+
}
|
|
1267
|
+
break;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
});
|
|
1272
|
+
tables.forEach((table2) => {
|
|
1273
|
+
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
1274
|
+
hide && builder.add(table2.from, table2.to, Decoration6.replace({
|
|
1275
|
+
widget: new TableWidget(table2)
|
|
1276
|
+
}));
|
|
1277
|
+
builder.add(table2.from, table2.to, Decoration6.mark({
|
|
1278
|
+
class: "cm-table"
|
|
1279
|
+
}));
|
|
1280
|
+
});
|
|
1281
|
+
return builder.finish();
|
|
1282
|
+
};
|
|
1283
|
+
var TableWidget = class extends WidgetType4 {
|
|
1284
|
+
constructor(_table) {
|
|
1285
|
+
super();
|
|
1286
|
+
this._table = _table;
|
|
1287
|
+
}
|
|
1288
|
+
eq(other) {
|
|
1289
|
+
return this._table.from === other?._table?.from;
|
|
1290
|
+
}
|
|
1291
|
+
toDOM(view) {
|
|
1292
|
+
const table2 = document.createElement("table");
|
|
1293
|
+
{
|
|
1294
|
+
const header = table2.appendChild(document.createElement("thead"));
|
|
1295
|
+
const tr = header.appendChild(document.createElement("tr"));
|
|
1296
|
+
this._table.header?.forEach((cell) => {
|
|
1297
|
+
const th = document.createElement("th");
|
|
1298
|
+
th.setAttribute("class", "cm-table-head");
|
|
1299
|
+
tr.appendChild(th).textContent = cell;
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
{
|
|
1303
|
+
const body = table2.appendChild(document.createElement("tbody"));
|
|
1304
|
+
this._table.rows?.forEach((row) => {
|
|
1305
|
+
const tr = body.appendChild(document.createElement("tr"));
|
|
1306
|
+
row.forEach((cell) => {
|
|
1307
|
+
const td = document.createElement("td");
|
|
1308
|
+
td.setAttribute("class", "cm-table-cell");
|
|
1309
|
+
tr.appendChild(td).textContent = cell;
|
|
1310
|
+
});
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
return table2;
|
|
1314
|
+
}
|
|
1315
|
+
};
|
|
601
1316
|
|
|
602
1317
|
// packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
|
|
603
|
-
import { EditorView as
|
|
604
|
-
var
|
|
1318
|
+
import { EditorView as EditorView10, Decoration as Decoration7, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
|
|
1319
|
+
var styles4 = EditorView10.baseTheme({
|
|
1320
|
+
"& .cm-task-item": {
|
|
1321
|
+
paddingLeft: "4px",
|
|
1322
|
+
paddingRight: "8px"
|
|
1323
|
+
}
|
|
1324
|
+
});
|
|
1325
|
+
var CheckboxWidget = class extends WidgetType5 {
|
|
605
1326
|
constructor(_pos, _checked, _indent, _onCheck) {
|
|
606
1327
|
super();
|
|
607
1328
|
this._pos = _pos;
|
|
@@ -620,30 +1341,29 @@ var CheckboxWidget = class extends WidgetType3 {
|
|
|
620
1341
|
const input = wrap.appendChild(document.createElement("input"));
|
|
621
1342
|
input.type = "checkbox";
|
|
622
1343
|
input.checked = this._checked;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
1344
|
+
if (!this._onCheck) {
|
|
1345
|
+
input.setAttribute("disabled", "true");
|
|
1346
|
+
}
|
|
1347
|
+
if (this._onCheck) {
|
|
1348
|
+
input.onchange = (event) => {
|
|
1349
|
+
this._onCheck?.(event.target.checked);
|
|
1350
|
+
return true;
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
627
1353
|
return wrap;
|
|
628
1354
|
}
|
|
629
1355
|
ignoreEvent() {
|
|
630
1356
|
return false;
|
|
631
1357
|
}
|
|
632
1358
|
};
|
|
633
|
-
var
|
|
634
|
-
"& .cm-task-item": {
|
|
635
|
-
paddingLeft: "4px",
|
|
636
|
-
paddingRight: "8px"
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
var tasklist = () => {
|
|
1359
|
+
var tasklist = (options = {}) => {
|
|
640
1360
|
const taskMatcher = new MatchDecorator2({
|
|
641
1361
|
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
642
1362
|
decoration: (match, view, pos) => {
|
|
643
1363
|
const indent = Math.floor(match[1].length / 2);
|
|
644
1364
|
const checked = match[2] === "x" || match[2] === "X";
|
|
645
|
-
return
|
|
646
|
-
widget: new CheckboxWidget(pos, checked, indent, (checked2) => {
|
|
1365
|
+
return Decoration7.replace({
|
|
1366
|
+
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
647
1367
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
648
1368
|
view.dispatch({
|
|
649
1369
|
changes: {
|
|
@@ -660,22 +1380,22 @@ var tasklist = () => {
|
|
|
660
1380
|
});
|
|
661
1381
|
}
|
|
662
1382
|
});
|
|
663
|
-
const tasks =
|
|
1383
|
+
const tasks = ViewPlugin3.fromClass(class {
|
|
664
1384
|
constructor(view) {
|
|
665
1385
|
this.tasks = taskMatcher.createDeco(view);
|
|
666
1386
|
}
|
|
667
|
-
update(
|
|
668
|
-
this.tasks = taskMatcher.updateDeco(
|
|
1387
|
+
update(update4) {
|
|
1388
|
+
this.tasks = taskMatcher.updateDeco(update4, this.tasks);
|
|
669
1389
|
}
|
|
670
1390
|
}, {
|
|
671
|
-
decorations: (
|
|
672
|
-
provide: (plugin) =>
|
|
673
|
-
return view.plugin(plugin)?.tasks ||
|
|
1391
|
+
decorations: (value) => value.tasks,
|
|
1392
|
+
provide: (plugin) => EditorView10.atomicRanges.of((view) => {
|
|
1393
|
+
return view.plugin(plugin)?.tasks || Decoration7.none;
|
|
674
1394
|
})
|
|
675
1395
|
});
|
|
676
1396
|
return [
|
|
677
1397
|
tasks,
|
|
678
|
-
|
|
1398
|
+
styles4
|
|
679
1399
|
];
|
|
680
1400
|
};
|
|
681
1401
|
|
|
@@ -724,7 +1444,7 @@ var tooltip = ({ onHover, regexp = markdownLinkRegexp }) => hoverTooltip((view,
|
|
|
724
1444
|
});
|
|
725
1445
|
|
|
726
1446
|
// packages/ui/react-ui-editor/src/components/TextEditor/themes/default.ts
|
|
727
|
-
import
|
|
1447
|
+
import get3 from "lodash.get";
|
|
728
1448
|
var defaultTheme = {
|
|
729
1449
|
//
|
|
730
1450
|
// Main layout:
|
|
@@ -749,20 +1469,20 @@ var defaultTheme = {
|
|
|
749
1469
|
fontSize: "16px"
|
|
750
1470
|
},
|
|
751
1471
|
"&light .cm-content": {
|
|
752
|
-
color:
|
|
1472
|
+
color: get3(tokens, "extend.colors.neutral.900", "black"),
|
|
753
1473
|
caretColor: "black"
|
|
754
1474
|
},
|
|
755
1475
|
"&dark .cm-content": {
|
|
756
|
-
color:
|
|
1476
|
+
color: get3(tokens, "extend.colors.neutral.100", "white"),
|
|
757
1477
|
caretColor: "white"
|
|
758
1478
|
},
|
|
759
1479
|
//
|
|
760
1480
|
// Cursor
|
|
761
1481
|
//
|
|
762
|
-
"&light .cm-cursor": {
|
|
1482
|
+
"&light .cm-cursor, &light .cm-dropCursor": {
|
|
763
1483
|
borderLeft: "2px solid black"
|
|
764
1484
|
},
|
|
765
|
-
"&dark .cm-cursor": {
|
|
1485
|
+
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
766
1486
|
borderLeft: "2px solid white"
|
|
767
1487
|
},
|
|
768
1488
|
"& .cm-placeholder": {
|
|
@@ -782,16 +1502,16 @@ var defaultTheme = {
|
|
|
782
1502
|
// selection
|
|
783
1503
|
//
|
|
784
1504
|
"&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground": {
|
|
785
|
-
background:
|
|
1505
|
+
background: get3(tokens, "extend.colors.primary.150", "#00ffff")
|
|
786
1506
|
},
|
|
787
1507
|
"&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground": {
|
|
788
|
-
background:
|
|
1508
|
+
background: get3(tokens, "extend.colors.primary.850", "#00ffff")
|
|
789
1509
|
},
|
|
790
1510
|
"&light .cm-selectionMatch": {
|
|
791
|
-
background:
|
|
1511
|
+
background: get3(tokens, "extend.colors.primary.250", "#00ffff") + "44"
|
|
792
1512
|
},
|
|
793
1513
|
"&dark .cm-selectionMatch": {
|
|
794
|
-
background:
|
|
1514
|
+
background: get3(tokens, "extend.colors.primary.600", "#00ffff") + "44"
|
|
795
1515
|
},
|
|
796
1516
|
//
|
|
797
1517
|
// collaboration
|
|
@@ -824,12 +1544,12 @@ var defaultTheme = {
|
|
|
824
1544
|
// link
|
|
825
1545
|
//
|
|
826
1546
|
"& .cm-link": {
|
|
827
|
-
color:
|
|
1547
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
828
1548
|
textDecorationLine: "underline",
|
|
829
1549
|
textDecorationThickness: "1px",
|
|
830
1550
|
textUnderlineOffset: "2px",
|
|
831
1551
|
borderRadius: ".125rem",
|
|
832
|
-
fontFamily:
|
|
1552
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
833
1553
|
},
|
|
834
1554
|
//
|
|
835
1555
|
// tooltip
|
|
@@ -837,14 +1557,61 @@ var defaultTheme = {
|
|
|
837
1557
|
"& .cm-tooltip": {
|
|
838
1558
|
border: "none"
|
|
839
1559
|
},
|
|
840
|
-
|
|
841
|
-
//
|
|
1560
|
+
"& .cm-tooltip-below": {},
|
|
1561
|
+
//
|
|
1562
|
+
// autocomplete
|
|
1563
|
+
//
|
|
1564
|
+
"& .cm-tooltip-autocomplete": {
|
|
1565
|
+
marginTop: "4px",
|
|
1566
|
+
marginLeft: "-3px"
|
|
1567
|
+
},
|
|
1568
|
+
"& .cm-tooltip-autocomplete ul li": {},
|
|
1569
|
+
"& .cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
1570
|
+
"& .cm-completionIcon": {
|
|
1571
|
+
display: "none"
|
|
1572
|
+
},
|
|
1573
|
+
"& .cm-completionLabel": {
|
|
1574
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
1575
|
+
},
|
|
1576
|
+
"& .cm-completionMatchedText": {
|
|
1577
|
+
textDecoration: "none"
|
|
1578
|
+
},
|
|
1579
|
+
//
|
|
1580
|
+
// widgets
|
|
1581
|
+
//
|
|
1582
|
+
"& .cm-widgetBuffer": {
|
|
1583
|
+
display: "none",
|
|
1584
|
+
height: 0
|
|
1585
|
+
},
|
|
1586
|
+
//
|
|
1587
|
+
// table
|
|
1588
|
+
//
|
|
1589
|
+
"& .cm-table *": {
|
|
1590
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
1591
|
+
textDecoration: "none !important"
|
|
1592
|
+
},
|
|
1593
|
+
"& .cm-table-head": {
|
|
1594
|
+
padding: "2px 16px 2px 0px",
|
|
1595
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
1596
|
+
fontWeight: 100,
|
|
1597
|
+
textAlign: "left",
|
|
1598
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
1599
|
+
},
|
|
1600
|
+
"& .cm-table-cell": {
|
|
1601
|
+
padding: "2px 16px 2px 0px"
|
|
1602
|
+
},
|
|
1603
|
+
//
|
|
1604
|
+
// image
|
|
1605
|
+
//
|
|
1606
|
+
"& .cm-image": {
|
|
1607
|
+
margin: "0.5rem 0"
|
|
1608
|
+
},
|
|
842
1609
|
//
|
|
843
1610
|
// font size
|
|
844
1611
|
// 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
1612
|
//
|
|
846
|
-
...Object.keys(
|
|
847
|
-
const height =
|
|
1613
|
+
...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
|
|
1614
|
+
const height = get3(tokens, [
|
|
848
1615
|
"extend",
|
|
849
1616
|
"fontSize",
|
|
850
1617
|
fontSize,
|
|
@@ -861,46 +1628,81 @@ var defaultTheme = {
|
|
|
861
1628
|
height
|
|
862
1629
|
};
|
|
863
1630
|
return acc;
|
|
864
|
-
}, {})
|
|
1631
|
+
}, {}),
|
|
1632
|
+
/**
|
|
1633
|
+
* Panels
|
|
1634
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
1635
|
+
*
|
|
1636
|
+
* Find/replace panel.
|
|
1637
|
+
* <div class="cm-announced">...</div>
|
|
1638
|
+
* <div class="cm-scroller">...</div>
|
|
1639
|
+
* <div class="cm-panels cm-panels-bottom">
|
|
1640
|
+
* <div class="cm-search cm-panel">
|
|
1641
|
+
* <input class="cm-textfield" />
|
|
1642
|
+
* <button class="cm-button">...</button>
|
|
1643
|
+
* <label><input type="checkbox" />...</label>
|
|
1644
|
+
* </div>
|
|
1645
|
+
* </div
|
|
1646
|
+
*/
|
|
1647
|
+
"& .cm-panels": {
|
|
1648
|
+
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`,
|
|
1649
|
+
borderBottom: "none"
|
|
1650
|
+
},
|
|
1651
|
+
"& .cm-panel": {
|
|
1652
|
+
background: get3(tokens, "extend.colors.neutral.50"),
|
|
1653
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
1654
|
+
},
|
|
1655
|
+
"& .cm-button": {
|
|
1656
|
+
margin: "4px",
|
|
1657
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
1658
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
1659
|
+
border: "none"
|
|
1660
|
+
},
|
|
1661
|
+
"& .cm-searchMatch": {
|
|
1662
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
1663
|
+
},
|
|
1664
|
+
"& .cm-searchMatch.cm-searchMatch-selected": {
|
|
1665
|
+
backgroundColor: get3(tokens, "extend.colors.primary.100")
|
|
1666
|
+
}
|
|
865
1667
|
};
|
|
866
1668
|
var textTheme = {
|
|
867
1669
|
"& .cm-scroller": {
|
|
868
|
-
fontFamily:
|
|
1670
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
869
1671
|
},
|
|
870
1672
|
"& .cm-placeholder": {
|
|
871
|
-
fontFamily:
|
|
1673
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
872
1674
|
}
|
|
873
1675
|
};
|
|
874
1676
|
var markdownTheme = {
|
|
875
1677
|
// NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
|
|
876
1678
|
"& .cm-placeholder": {
|
|
877
|
-
fontFamily:
|
|
1679
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
878
1680
|
}
|
|
879
1681
|
};
|
|
880
1682
|
var codeTheme = {
|
|
881
1683
|
"& .cm-scroller": {
|
|
882
|
-
fontFamily:
|
|
1684
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
883
1685
|
},
|
|
884
1686
|
"& .cm-placeholder": {
|
|
885
|
-
fontFamily:
|
|
1687
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
886
1688
|
}
|
|
887
1689
|
};
|
|
888
1690
|
|
|
889
1691
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
890
1692
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
891
|
-
import { EditorView as
|
|
1693
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
|
892
1694
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
893
1695
|
import { vim } from "@replit/codemirror-vim";
|
|
894
|
-
import
|
|
895
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
1696
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
1697
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
|
|
896
1698
|
import { generateName } from "@dxos/display-name";
|
|
897
1699
|
import { useThemeContext } from "@dxos/react-ui";
|
|
898
|
-
import { getColorForValue, inputSurface, mx as
|
|
1700
|
+
import { getColorForValue, inputSurface, mx as mx4 } from "@dxos/react-ui-theme";
|
|
899
1701
|
var EditorModes = [
|
|
900
1702
|
"default",
|
|
901
1703
|
"vim"
|
|
902
1704
|
];
|
|
903
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots = defaultSlots
|
|
1705
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
|
|
904
1706
|
const { themeMode } = useThemeContext();
|
|
905
1707
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
906
1708
|
tabBehavior: "limited"
|
|
@@ -918,7 +1720,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
918
1720
|
root
|
|
919
1721
|
]);
|
|
920
1722
|
const { awareness, peer } = model;
|
|
921
|
-
|
|
1723
|
+
useEffect2(() => {
|
|
922
1724
|
if (awareness && peer) {
|
|
923
1725
|
awareness.setLocalStateField("user", {
|
|
924
1726
|
name: peer.name ?? generateName(peer.id),
|
|
@@ -938,20 +1740,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
938
1740
|
peer,
|
|
939
1741
|
themeMode
|
|
940
1742
|
]);
|
|
941
|
-
|
|
1743
|
+
useEffect2(() => {
|
|
942
1744
|
if (!root) {
|
|
943
1745
|
return;
|
|
944
1746
|
}
|
|
945
1747
|
const state2 = EditorState2.create({
|
|
946
1748
|
doc: model.text(),
|
|
947
1749
|
extensions: [
|
|
1750
|
+
readonly && EditorState2.readOnly.of(readonly),
|
|
948
1751
|
// TODO(burdon): Factor out VIM mode?
|
|
949
1752
|
editorMode === "vim" && vim(),
|
|
950
1753
|
// Theme.
|
|
951
|
-
|
|
952
|
-
|
|
1754
|
+
// TODO(burdon): Make optional.
|
|
1755
|
+
EditorView11.baseTheme(defaultTheme),
|
|
1756
|
+
EditorView11.theme(slots?.editor?.theme ?? {}),
|
|
953
1757
|
// TODO(burdon): themeMode doesn't change in storybooks.
|
|
954
|
-
|
|
1758
|
+
EditorView11.darkTheme.of(themeMode === "dark"),
|
|
955
1759
|
// Storage and replication.
|
|
956
1760
|
model.extension,
|
|
957
1761
|
// Custom.
|
|
@@ -959,7 +1763,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
959
1763
|
].filter(Boolean)
|
|
960
1764
|
});
|
|
961
1765
|
view?.destroy();
|
|
962
|
-
setView(new
|
|
1766
|
+
setView(new EditorView11({
|
|
963
1767
|
state: state2,
|
|
964
1768
|
parent: root
|
|
965
1769
|
}));
|
|
@@ -973,6 +1777,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
973
1777
|
root,
|
|
974
1778
|
model,
|
|
975
1779
|
themeMode,
|
|
1780
|
+
readonly,
|
|
976
1781
|
editorMode
|
|
977
1782
|
]);
|
|
978
1783
|
const handleKeyUp = useCallback((event) => {
|
|
@@ -1000,43 +1805,36 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
|
|
|
1000
1805
|
onKeyUp: handleKeyUp
|
|
1001
1806
|
});
|
|
1002
1807
|
});
|
|
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) => {
|
|
1808
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1013
1809
|
const { themeMode } = useThemeContext();
|
|
1014
|
-
const slots =
|
|
1810
|
+
const slots = defaultsDeep2({}, _slots, defaultTextSlots);
|
|
1015
1811
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
1016
1812
|
ref: forwardedRef,
|
|
1813
|
+
readonly,
|
|
1017
1814
|
extensions: [
|
|
1018
1815
|
basicBundle({
|
|
1816
|
+
readonly,
|
|
1019
1817
|
themeMode,
|
|
1020
1818
|
placeholder: slots?.editor?.placeholder
|
|
1021
1819
|
}),
|
|
1022
|
-
maybeDebug(),
|
|
1023
1820
|
...extensions
|
|
1024
1821
|
],
|
|
1025
1822
|
slots,
|
|
1026
1823
|
...props
|
|
1027
1824
|
});
|
|
1028
1825
|
});
|
|
1029
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1826
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
|
|
1030
1827
|
const { themeMode } = useThemeContext();
|
|
1031
|
-
const slots =
|
|
1828
|
+
const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
|
|
1032
1829
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
1033
1830
|
ref: forwardedRef,
|
|
1831
|
+
readonly,
|
|
1034
1832
|
extensions: [
|
|
1035
1833
|
markdownBundle({
|
|
1834
|
+
readonly,
|
|
1036
1835
|
themeMode,
|
|
1037
1836
|
placeholder: slots?.editor?.placeholder
|
|
1038
1837
|
}),
|
|
1039
|
-
maybeDebug(),
|
|
1040
1838
|
...extensions
|
|
1041
1839
|
],
|
|
1042
1840
|
slots,
|
|
@@ -1045,7 +1843,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
|
|
|
1045
1843
|
});
|
|
1046
1844
|
var defaultSlots = {
|
|
1047
1845
|
root: {
|
|
1048
|
-
className:
|
|
1846
|
+
className: mx4("p-2", inputSurface)
|
|
1049
1847
|
}
|
|
1050
1848
|
};
|
|
1051
1849
|
var defaultTextSlots = {
|
|
@@ -1062,23 +1860,23 @@ var defaultMarkdownSlots = {
|
|
|
1062
1860
|
};
|
|
1063
1861
|
|
|
1064
1862
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1065
|
-
import
|
|
1066
|
-
import { useEffect as
|
|
1863
|
+
import get4 from "lodash.get";
|
|
1864
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
1067
1865
|
import { yCollab } from "y-codemirror.next";
|
|
1068
|
-
import { invariant as
|
|
1866
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1069
1867
|
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
1070
1868
|
|
|
1071
1869
|
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1072
|
-
import { Annotation, Facet, StateEffect, StateField as
|
|
1073
|
-
import { ViewPlugin as
|
|
1870
|
+
import { Annotation, Facet, StateEffect as StateEffect2, StateField as StateField6 } from "@codemirror/state";
|
|
1871
|
+
import { ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1074
1872
|
import * as automerge2 from "@dxos/automerge/automerge";
|
|
1075
1873
|
|
|
1076
1874
|
// packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
|
|
1077
1875
|
import { next as automerge } from "@dxos/automerge/automerge";
|
|
1078
1876
|
|
|
1079
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1877
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
|
|
1080
1878
|
import { ChangeSet } from "@codemirror/state";
|
|
1081
|
-
var
|
|
1879
|
+
var automergeToCodemirror = (view, selection, target, patches) => {
|
|
1082
1880
|
for (const patch of patches) {
|
|
1083
1881
|
const changeSpec = handlePatch(patch, target, view.state);
|
|
1084
1882
|
if (changeSpec != null) {
|
|
@@ -1183,9 +1981,9 @@ var charPath = (textPath, candidatePath) => {
|
|
|
1183
1981
|
return null;
|
|
1184
1982
|
};
|
|
1185
1983
|
|
|
1186
|
-
// packages/ui/react-ui-editor/src/hooks/automerge/
|
|
1984
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
|
|
1187
1985
|
import { next as am } from "@dxos/automerge/automerge";
|
|
1188
|
-
var
|
|
1986
|
+
var codemirrorToAutomerge = (field, handle, transactions, state) => {
|
|
1189
1987
|
const { lastHeads, path } = state.field(field);
|
|
1190
1988
|
let hasChanges = false;
|
|
1191
1989
|
for (const tr of transactions) {
|
|
@@ -1229,12 +2027,12 @@ var PatchSemaphore = class {
|
|
|
1229
2027
|
annotations: reconcileAnnotationType.of(true)
|
|
1230
2028
|
});
|
|
1231
2029
|
}
|
|
1232
|
-
let newHeads =
|
|
2030
|
+
let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
|
|
1233
2031
|
if (newHeads === null || newHeads === void 0) {
|
|
1234
2032
|
newHeads = automerge.getHeads(handle.docSync());
|
|
1235
2033
|
}
|
|
1236
2034
|
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
1237
|
-
|
|
2035
|
+
automergeToCodemirror(view, selection, path, diff);
|
|
1238
2036
|
view.dispatch({
|
|
1239
2037
|
effects: updateHeads(newHeads),
|
|
1240
2038
|
annotations: reconcileAnnotationType.of({})
|
|
@@ -1248,7 +2046,7 @@ var PatchSemaphore = class {
|
|
|
1248
2046
|
};
|
|
1249
2047
|
|
|
1250
2048
|
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
1251
|
-
var effectType =
|
|
2049
|
+
var effectType = StateEffect2.define({});
|
|
1252
2050
|
var updateHeads = (newHeads) => effectType.of({
|
|
1253
2051
|
newHeads
|
|
1254
2052
|
});
|
|
@@ -1258,7 +2056,7 @@ var semaphoreFacet = Facet.define({
|
|
|
1258
2056
|
combine: (values) => values.at(-1)
|
|
1259
2057
|
});
|
|
1260
2058
|
var automergePlugin = (handle, path) => {
|
|
1261
|
-
const stateField =
|
|
2059
|
+
const stateField = StateField6.define({
|
|
1262
2060
|
create: () => ({
|
|
1263
2061
|
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
1264
2062
|
unreconciledTransactions: [],
|
|
@@ -1288,7 +2086,7 @@ var automergePlugin = (handle, path) => {
|
|
|
1288
2086
|
}
|
|
1289
2087
|
});
|
|
1290
2088
|
const semaphore = new PatchSemaphore(stateField);
|
|
1291
|
-
const viewPlugin =
|
|
2089
|
+
const viewPlugin = ViewPlugin4.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
1292
2090
|
constructor(view) {
|
|
1293
2091
|
this._handleChange = () => {
|
|
1294
2092
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
@@ -1296,8 +2094,8 @@ var automergePlugin = (handle, path) => {
|
|
|
1296
2094
|
this._view = view;
|
|
1297
2095
|
handle.addListener("change", this._handleChange);
|
|
1298
2096
|
}
|
|
1299
|
-
update(
|
|
1300
|
-
if (
|
|
2097
|
+
update(update4) {
|
|
2098
|
+
if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
|
|
1301
2099
|
queueMicrotask(() => {
|
|
1302
2100
|
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
1303
2101
|
});
|
|
@@ -1319,7 +2117,7 @@ var reconcileAnnotationType = Annotation.define();
|
|
|
1319
2117
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
1320
2118
|
|
|
1321
2119
|
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
1322
|
-
import * as
|
|
2120
|
+
import * as random2 from "lib0/random";
|
|
1323
2121
|
var cursorColors = [
|
|
1324
2122
|
{
|
|
1325
2123
|
color: "#30bced",
|
|
@@ -1354,7 +2152,7 @@ var cursorColors = [
|
|
|
1354
2152
|
light: "#1be7ff33"
|
|
1355
2153
|
}
|
|
1356
2154
|
];
|
|
1357
|
-
var cursorColor = cursorColors[
|
|
2155
|
+
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
1358
2156
|
|
|
1359
2157
|
// packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
|
|
1360
2158
|
import * as decoding from "lib0/decoding";
|
|
@@ -1362,7 +2160,7 @@ import * as encoding from "lib0/encoding";
|
|
|
1362
2160
|
import { Observable } from "lib0/observable";
|
|
1363
2161
|
import * as awarenessProtocol from "y-protocols/awareness";
|
|
1364
2162
|
import { log } from "@dxos/log";
|
|
1365
|
-
var
|
|
2163
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
1366
2164
|
var messageAwareness = 1;
|
|
1367
2165
|
var messageQueryAwareness = 3;
|
|
1368
2166
|
var SpaceAwarenessProvider = class extends Observable {
|
|
@@ -1399,7 +2197,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1399
2197
|
removed,
|
|
1400
2198
|
origin
|
|
1401
2199
|
}, {
|
|
1402
|
-
F:
|
|
2200
|
+
F: __dxlog_file3,
|
|
1403
2201
|
L: 67,
|
|
1404
2202
|
S: this,
|
|
1405
2203
|
C: (f, a) => f(...a)
|
|
@@ -1412,7 +2210,7 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1412
2210
|
}
|
|
1413
2211
|
_handleSpaceMessage({ payload }) {
|
|
1414
2212
|
log("space message", payload, {
|
|
1415
|
-
F:
|
|
2213
|
+
F: __dxlog_file3,
|
|
1416
2214
|
L: 79,
|
|
1417
2215
|
S: this,
|
|
1418
2216
|
C: (f, a) => f(...a)
|
|
@@ -1457,14 +2255,14 @@ var SpaceAwarenessProvider = class extends Observable {
|
|
|
1457
2255
|
};
|
|
1458
2256
|
|
|
1459
2257
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
1460
|
-
var
|
|
2258
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
1461
2259
|
var useTextModel = ({ identity, space, text }) => {
|
|
1462
2260
|
const [model, setModel] = useState2(() => createModel({
|
|
1463
2261
|
identity,
|
|
1464
2262
|
space,
|
|
1465
2263
|
text
|
|
1466
2264
|
}));
|
|
1467
|
-
|
|
2265
|
+
useEffect3(() => {
|
|
1468
2266
|
setModel(createModel({
|
|
1469
2267
|
identity,
|
|
1470
2268
|
space,
|
|
@@ -1489,9 +2287,9 @@ var createModel = (options) => {
|
|
|
1489
2287
|
}
|
|
1490
2288
|
};
|
|
1491
2289
|
var createYjsModel = ({ identity, space, text }) => {
|
|
1492
|
-
|
|
1493
|
-
F:
|
|
1494
|
-
L:
|
|
2290
|
+
invariant3(text?.doc && text?.content, void 0, {
|
|
2291
|
+
F: __dxlog_file4,
|
|
2292
|
+
L: 81,
|
|
1495
2293
|
S: void 0,
|
|
1496
2294
|
A: [
|
|
1497
2295
|
"text?.doc && text?.content",
|
|
@@ -1507,6 +2305,7 @@ var createYjsModel = ({ identity, space, text }) => {
|
|
|
1507
2305
|
id: text.doc.guid,
|
|
1508
2306
|
content: text.content,
|
|
1509
2307
|
text: () => text.content.toString(),
|
|
2308
|
+
ranges: [],
|
|
1510
2309
|
extension: yCollab(text.content, provider?.awareness),
|
|
1511
2310
|
awareness: provider?.awareness,
|
|
1512
2311
|
peer: identity ? {
|
|
@@ -1523,7 +2322,8 @@ var createAutomergeModel = ({ identity, text }) => {
|
|
|
1523
2322
|
return {
|
|
1524
2323
|
id: obj.id,
|
|
1525
2324
|
content: doc,
|
|
1526
|
-
text: () =>
|
|
2325
|
+
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2326
|
+
ranges: [],
|
|
1527
2327
|
extension: automergePlugin(doc.handle, doc.path),
|
|
1528
2328
|
peer: identity ? {
|
|
1529
2329
|
id: identity.identityKey.toHex(),
|
|
@@ -1543,25 +2343,35 @@ export {
|
|
|
1543
2343
|
YXmlFragment,
|
|
1544
2344
|
autocomplete,
|
|
1545
2345
|
basicBundle,
|
|
2346
|
+
blast,
|
|
2347
|
+
code2 as code,
|
|
1546
2348
|
codeTheme,
|
|
1547
2349
|
comments,
|
|
1548
2350
|
cursorColor,
|
|
1549
2351
|
defaultMarkdownSlots,
|
|
2352
|
+
defaultOptions,
|
|
1550
2353
|
defaultSlots,
|
|
1551
2354
|
defaultTextSlots,
|
|
1552
2355
|
defaultTheme,
|
|
1553
2356
|
demo,
|
|
2357
|
+
highlight,
|
|
2358
|
+
highlightDecorations,
|
|
2359
|
+
highlightStateField,
|
|
2360
|
+
image,
|
|
1554
2361
|
link,
|
|
1555
|
-
listener,
|
|
2362
|
+
listener2 as listener,
|
|
1556
2363
|
markdownBundle,
|
|
1557
2364
|
markdownHighlightStyle,
|
|
1558
2365
|
markdownTags,
|
|
1559
|
-
|
|
2366
|
+
markdownTagsExtensions,
|
|
1560
2367
|
markdownTheme,
|
|
2368
|
+
mention,
|
|
2369
|
+
table,
|
|
1561
2370
|
tags2 as tags,
|
|
1562
2371
|
tasklist,
|
|
1563
2372
|
textTheme,
|
|
1564
2373
|
tooltip,
|
|
2374
|
+
useHighlights,
|
|
1565
2375
|
useTextModel
|
|
1566
2376
|
};
|
|
1567
2377
|
//# sourceMappingURL=index.mjs.map
|