@dxos/react-ui-editor 0.3.10-main.ee543cf → 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.
Files changed (102) hide show
  1. package/dist/lib/browser/index.mjs +1417 -387
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +26 -2
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +3 -1
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +3 -0
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts +3 -2
  11. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +1 -1
  12. package/dist/types/src/components/TextEditor/extensions/basic.d.ts +2 -1
  13. package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -1
  14. package/dist/types/src/components/TextEditor/extensions/blast.d.ts +25 -0
  15. package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +1 -0
  16. package/dist/types/src/components/TextEditor/extensions/code.d.ts +2 -0
  17. package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +1 -0
  18. package/dist/types/src/components/TextEditor/extensions/comments.d.ts +18 -0
  19. package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -0
  20. package/dist/types/src/components/TextEditor/extensions/demo.d.ts +11 -0
  21. package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +1 -0
  22. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts +1 -1
  23. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -1
  24. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts +24 -0
  25. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts.map +1 -0
  26. package/dist/types/src/components/TextEditor/extensions/image.d.ts +4 -0
  27. package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +1 -0
  28. package/dist/types/src/components/TextEditor/extensions/index.d.ts +8 -0
  29. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
  30. package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +1 -1
  31. package/dist/types/src/components/TextEditor/extensions/listener.d.ts +4 -2
  32. package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -1
  33. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +10 -1
  34. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
  35. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts +9 -3
  36. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
  37. package/dist/types/src/components/TextEditor/extensions/mention.d.ts +6 -0
  38. package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +1 -0
  39. package/dist/types/src/components/TextEditor/extensions/table.d.ts +8 -0
  40. package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +1 -0
  41. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +2 -4
  42. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -1
  43. package/dist/types/src/components/TextEditor/themes/default.d.ts +8 -0
  44. package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
  45. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts +3 -0
  46. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +1 -1
  47. package/dist/types/src/hooks/automerge/automerge.stories.d.ts +8 -1
  48. package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -1
  49. package/dist/types/src/hooks/automerge/index.d.ts +1 -1
  50. package/dist/types/src/hooks/automerge/index.d.ts.map +1 -1
  51. package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -1
  52. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts +5 -0
  53. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts.map +1 -0
  54. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts +6 -0
  55. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts.map +1 -0
  56. package/dist/types/src/hooks/automerge/translation/index.d.ts +3 -0
  57. package/dist/types/src/hooks/automerge/translation/index.d.ts.map +1 -0
  58. package/dist/types/src/hooks/useTextModel.d.ts +6 -0
  59. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  60. package/dist/types/src/{components/TextEditor → hooks/yjs}/yjs.stories.d.ts +2 -2
  61. package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -0
  62. package/dist/types/src/styles/markdown.d.ts +3 -2
  63. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  64. package/dist/types/src/testing/replicator.d.ts.map +1 -1
  65. package/package.json +22 -19
  66. package/src/components/TextEditor/MarkdownEditor.stories.tsx +161 -36
  67. package/src/components/TextEditor/TextEditor.stories.tsx +12 -1
  68. package/src/components/TextEditor/TextEditor.tsx +43 -15
  69. package/src/components/TextEditor/extensions/autocomplete.ts +9 -22
  70. package/src/components/TextEditor/extensions/basic.ts +6 -4
  71. package/src/components/TextEditor/extensions/blast.ts +373 -0
  72. package/src/components/TextEditor/extensions/code.ts +99 -0
  73. package/src/components/TextEditor/extensions/comments.ts +173 -0
  74. package/src/components/TextEditor/extensions/demo.ts +69 -0
  75. package/src/components/TextEditor/extensions/experimental.tsx +15 -35
  76. package/src/components/TextEditor/extensions/highlight.ts +128 -0
  77. package/src/components/TextEditor/extensions/image.ts +67 -0
  78. package/src/components/TextEditor/extensions/index.ts +8 -0
  79. package/src/components/TextEditor/extensions/link.ts +27 -27
  80. package/src/components/TextEditor/extensions/listener.ts +4 -3
  81. package/src/components/TextEditor/extensions/markdown/bundle.ts +47 -53
  82. package/src/components/TextEditor/extensions/markdown/highlight.ts +148 -107
  83. package/src/components/TextEditor/extensions/mention.ts +31 -0
  84. package/src/components/TextEditor/extensions/table.ts +119 -0
  85. package/src/components/TextEditor/extensions/tasklist.ts +89 -81
  86. package/src/components/TextEditor/themes/default.ts +112 -4
  87. package/src/hooks/automerge/PatchSemaphore.ts +12 -9
  88. package/src/hooks/automerge/automerge.stories.tsx +4 -2
  89. package/src/hooks/automerge/index.ts +1 -1
  90. package/src/hooks/automerge/plugin.ts +1 -0
  91. package/src/hooks/automerge/{amToCodemirror.ts → translation/automerge-to-codemirror.ts} +10 -2
  92. package/src/hooks/automerge/{codeMirrorToAm.ts → translation/codemirror-to-automerge.ts} +7 -4
  93. package/src/hooks/automerge/translation/index.ts +6 -0
  94. package/src/hooks/useTextModel.ts +20 -8
  95. package/src/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +2 -2
  96. package/src/styles/markdown.ts +15 -8
  97. package/src/testing/replicator.ts +6 -5
  98. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
  99. package/dist/types/src/hooks/automerge/amToCodemirror.d.ts +0 -6
  100. package/dist/types/src/hooks/automerge/amToCodemirror.d.ts.map +0 -1
  101. package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts +0 -7
  102. package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts.map +0 -1
@@ -8,7 +8,7 @@ import { tags as tags2 } from "@lezer/highlight";
8
8
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/autocomplete.ts
9
9
  import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
10
10
  import { keymap } from "@codemirror/view";
11
- var autocomplete = ({ getOptions }) => {
11
+ var autocomplete = ({ onSearch }) => {
12
12
  return [
13
13
  // https://codemirror.net/docs/ref/#view.keymap
14
14
  // https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
@@ -24,13 +24,13 @@ var autocomplete = ({ getOptions }) => {
24
24
  // TODO(burdon): Optional decoration via addToOptions
25
25
  override: [
26
26
  (context) => {
27
- const word = context.matchBefore(/\w*/);
28
- if (!word || word.from === word.to && !context.explicit) {
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: word.from,
33
- options: getOptions(word.text.toLowerCase())
32
+ from: match.from,
33
+ options: onSearch(match.text.toLowerCase())
34
34
  };
35
35
  }
36
36
  ]
@@ -42,23 +42,809 @@ var autocomplete = ({ getOptions }) => {
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
- EditorView.lineWrapping,
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
 
57
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
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
+
488
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
489
+ import { keymap as keymap3 } from "@codemirror/view";
490
+ var defaultItems = [
491
+ "hello world!",
492
+ "this is a test.",
493
+ "this is [DXOS](https://dxos.org)"
494
+ ];
495
+ var demo = ({ delay = 75, items = defaultItems } = {}) => {
496
+ let t;
497
+ let idx = 0;
498
+ return [
499
+ keymap3.of([
500
+ {
501
+ // Reset.
502
+ key: "alt-meta-'",
503
+ run: (view) => {
504
+ clearTimeout(t);
505
+ idx = 0;
506
+ return true;
507
+ }
508
+ },
509
+ {
510
+ // Next prompt.
511
+ // TODO(burdon): Press 1-9 to select prompt?
512
+ key: "shift-meta-'",
513
+ run: (view) => {
514
+ clearTimeout(t);
515
+ const text = items[idx++];
516
+ if (idx === items?.length) {
517
+ idx = 0;
518
+ }
519
+ let i = 0;
520
+ const insert = (d = 0) => {
521
+ t = setTimeout(() => {
522
+ const pos = view.state.selection.main.head;
523
+ view.dispatch({
524
+ changes: {
525
+ from: pos,
526
+ insert: text[i++]
527
+ },
528
+ selection: {
529
+ anchor: pos + 1
530
+ }
531
+ });
532
+ if (i < text.length) {
533
+ insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
534
+ }
535
+ }, d);
536
+ };
537
+ insert();
538
+ return true;
539
+ }
540
+ }
541
+ ])
542
+ ];
543
+ };
544
+
545
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
546
+ import { keymap as keymap4, Decoration as Decoration2, EditorView as EditorView4, MatchDecorator, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
547
+ import { debounce } from "@dxos/async";
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
+ });
561
+ var BookmarkWidget = class extends WidgetType {
562
+ constructor(_pos, _id, _handleClick) {
563
+ super();
564
+ this._pos = _pos;
565
+ this._id = _id;
566
+ this._handleClick = _handleClick;
567
+ invariant2(this._id, void 0, {
568
+ F: __dxlog_file2,
569
+ L: 37,
570
+ S: this,
571
+ A: [
572
+ "this._id",
573
+ ""
574
+ ]
575
+ });
576
+ }
577
+ eq(other) {
578
+ return this._id === other._id;
579
+ }
580
+ toDOM() {
581
+ const span = document.createElement("span");
582
+ span.className = "cm-bookmark";
583
+ span.textContent = "\xA7";
584
+ span.onclick = () => this._handleClick();
585
+ return span;
586
+ }
587
+ };
588
+ var comments = (options = {}) => {
589
+ let active;
590
+ const bookmarkMatcher = new MatchDecorator({
591
+ regexp: /\[\^(\w+)\]/g,
592
+ decoration: (match, view, pos) => {
593
+ const id = match[1];
594
+ return Decoration2.replace({
595
+ id,
596
+ widget: new BookmarkWidget(pos, id, () => handleUpdate({
597
+ active: id
598
+ }))
599
+ });
600
+ }
601
+ });
602
+ const bookmarks = ViewPlugin2.fromClass(class {
603
+ constructor(view) {
604
+ this.bookmarks = bookmarkMatcher.createDeco(view);
605
+ }
606
+ update(update4) {
607
+ this.bookmarks = bookmarkMatcher.updateDeco(update4, this.bookmarks);
608
+ }
609
+ }, {
610
+ decorations: (instance) => instance.bookmarks,
611
+ provide: (plugin) => EditorView4.atomicRanges.of((view) => {
612
+ return view.plugin(plugin)?.bookmarks || Decoration2.none;
613
+ })
614
+ });
615
+ const handleUpdate = debounce((data) => {
616
+ options.onUpdate?.(data);
617
+ }, 200);
618
+ return [
619
+ keymap4.of([
620
+ {
621
+ key: options?.key ?? "shift-meta-c",
622
+ run: (view) => {
623
+ const { from, to, head } = view.state.selection.main;
624
+ const id = options.onCreate?.(from, to);
625
+ if (id) {
626
+ const tag = `[^${id}]`;
627
+ view.dispatch({
628
+ changes: {
629
+ from: head,
630
+ insert: tag
631
+ },
632
+ selection: {
633
+ anchor: head + tag.length
634
+ }
635
+ });
636
+ return true;
637
+ }
638
+ return false;
639
+ }
640
+ }
641
+ ]),
642
+ bookmarks,
643
+ // Monitor cursor movement.
644
+ EditorView4.updateListener.of((update4) => {
645
+ active = void 0;
646
+ if (!options.onUpdate) {
647
+ return;
648
+ }
649
+ const { view, state } = update4;
650
+ const pos = state.selection.main.head;
651
+ const decorations = [];
652
+ const rangeSet = view.plugin(bookmarks)?.bookmarks;
653
+ let closest = Infinity;
654
+ const { from, to } = (
655
+ /* view.visibleRanges?.[0] ?? */
656
+ {
657
+ from: 0,
658
+ to: state.doc.length
659
+ }
660
+ );
661
+ rangeSet?.between(from, to, (from2, to2, value) => {
662
+ decorations.push({
663
+ from: from2,
664
+ to: to2,
665
+ value
666
+ });
667
+ const d = Math.min(Math.abs(pos - from2), Math.abs(pos - to2));
668
+ if (d < closest) {
669
+ active = value.spec.id;
670
+ closest = d;
671
+ }
672
+ });
673
+ if (decorations.length) {
674
+ handleUpdate({
675
+ active,
676
+ items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
677
+ id,
678
+ pos: from2,
679
+ location: view.coordsAtPos(from2)
680
+ }))
681
+ });
682
+ }
683
+ }),
684
+ styles2
685
+ ];
686
+ };
687
+
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
58
791
  import { syntaxTree } from "@codemirror/language";
59
- import { RangeSetBuilder, StateField } from "@codemirror/state";
60
- import { Decoration, EditorView as EditorView2, WidgetType } from "@codemirror/view";
61
- var LinkButton = class extends WidgetType {
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 {
62
848
  constructor(_pos, _url, _onAttach) {
63
849
  super();
64
850
  this._pos = _pos;
@@ -74,7 +860,7 @@ var LinkButton = class extends WidgetType {
74
860
  return el;
75
861
  }
76
862
  };
77
- var LinkText = class extends WidgetType {
863
+ var LinkText = class extends WidgetType3 {
78
864
  constructor(_pos, _text, _url) {
79
865
  super();
80
866
  this._pos = _pos;
@@ -104,96 +890,68 @@ var LinkText = class extends WidgetType {
104
890
  return link2;
105
891
  }
106
892
  };
107
- var update = (state, options) => {
108
- const builder = new RangeSetBuilder();
893
+ var update2 = (state, options) => {
894
+ const builder = new RangeSetBuilder2();
109
895
  const cursor = state.selection.main.head;
110
- syntaxTree(state).iterate({
896
+ syntaxTree2(state).iterate({
111
897
  enter: (node) => {
112
898
  if (node.name === "Link") {
113
- const marks = node.node.getChildren("LinkMark");
114
- const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
899
+ const marks2 = node.node.getChildren("LinkMark");
900
+ const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
115
901
  const urlNode = node.node.getChild("URL");
116
902
  const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
117
- if (cursor < node.from || cursor > node.to) {
118
- builder.add(node.from, node.to, Decoration.replace({
903
+ if (!url) {
904
+ return false;
905
+ }
906
+ if (state.readOnly || cursor < node.from || cursor > node.to) {
907
+ builder.add(node.from, node.to, Decoration5.replace({
119
908
  widget: new LinkText(node.from, text, options.link ? url : void 0)
120
909
  }));
121
910
  }
122
911
  if (options.onRender) {
123
- builder.add(node.to, node.to, Decoration.replace({
912
+ builder.add(node.to, node.to, Decoration5.replace({
124
913
  widget: new LinkButton(node.from, url, options.onRender)
125
914
  }));
126
915
  }
916
+ return false;
127
917
  }
128
- return true;
129
918
  }
130
919
  });
131
920
  return builder.finish();
132
921
  };
133
- var link = (options = {}) => {
134
- return StateField.define({
135
- create: (state) => update(state, options),
136
- update: (_, tr) => update(tr.state, options),
137
- provide: (field) => EditorView2.decorations.from(field)
138
- });
139
- };
140
922
 
141
923
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
142
- import { StateField as StateField2 } from "@codemirror/state";
143
- var listener = (onChange) => StateField2.define({
144
- create: () => null,
145
- update: (_value, transaction) => {
146
- if (transaction.docChanged && onChange) {
147
- onChange(transaction.newDoc.toString());
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;
148
933
  }
149
- return null;
150
- }
151
- });
934
+ });
935
+ };
152
936
 
153
937
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
154
938
  import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
155
- import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
939
+ import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
156
940
  import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
157
- import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, foldKeymap, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
941
+ import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
158
942
  import { languages } from "@codemirror/language-data";
159
- import { lintKeymap } from "@codemirror/lint";
160
- import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
943
+ import { searchKeymap } from "@codemirror/search";
161
944
  import { EditorState } from "@codemirror/state";
162
945
  import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
163
- import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView3, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap2, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
946
+ import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView8, keymap as keymap5, placeholder as placeholder2 } from "@codemirror/view";
164
947
 
165
948
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
166
949
  import { markdownLanguage } from "@codemirror/lang-markdown";
167
950
  import { HighlightStyle } from "@codemirror/language";
168
951
  import { tags, styleTags, Tag } from "@lezer/highlight";
169
- import get from "lodash.get";
170
-
171
- // packages/ui/react-ui-editor/src/styles/markdown.ts
172
- import { mx } from "@dxos/react-ui-theme";
173
- var heading = {
174
- 1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
175
- 2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
176
- 3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
177
- 4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
178
- 5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
179
- 6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
180
- };
181
- var light = "text-neutral-200 dark:text-neutral-800";
182
- var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
183
- var bold = "font-bold";
184
- var italic = "italic";
185
- var strikethrough = "line-through";
186
- var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
187
- var codeMark = "font-mono text-primary-500";
188
- var inlineUrl = mx(code, "px-1");
189
- var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
190
- var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-500/50";
191
-
192
- // packages/ui/react-ui-editor/src/styles/tokens.ts
193
- import { tailwindConfig } from "@dxos/react-ui-theme";
194
- var tokens = tailwindConfig({}).theme;
195
-
196
- // 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";
197
955
  var markdownTags = {
198
956
  Blockquote: Tag.define(),
199
957
  CodeMark: Tag.define(),
@@ -206,179 +964,201 @@ var markdownTags = {
206
964
  LinkReference: Tag.define(),
207
965
  ListMark: Tag.define(),
208
966
  QuoteMark: Tag.define(),
209
- URL: Tag.define()
210
- };
211
- var markdownTagsExtension = {
212
- props: [
213
- styleTags(markdownTags)
214
- ]
967
+ URL: Tag.define(),
968
+ // Custom.
969
+ TableCell: Tag.define()
215
970
  };
216
- var markdownHighlightStyle = HighlightStyle.define([
217
- {
218
- tag: [
219
- tags.keyword,
220
- tags.name,
221
- tags.deleted,
222
- tags.character,
223
- tags.propertyName,
224
- tags.macroName,
225
- tags.color,
226
- tags.constant(tags.name),
227
- tags.standard(tags.name),
228
- tags.definition(tags.name),
229
- tags.separator,
230
- tags.typeName,
231
- tags.className,
232
- tags.number,
233
- tags.changed,
234
- tags.annotation,
235
- tags.modifier,
236
- tags.self,
237
- tags.namespace,
238
- tags.operator,
239
- tags.operatorKeyword,
240
- tags.escape,
241
- tags.regexp,
242
- tags.special(tags.string),
243
- tags.meta,
244
- tags.comment,
245
- tags.atom,
246
- tags.bool,
247
- tags.special(tags.variableName),
248
- tags.processingInstruction,
249
- tags.string,
250
- tags.inserted,
251
- tags.invalid
252
- ],
253
- color: "inherit !important"
254
- },
255
- // Markdown marks.
256
- {
257
- tag: [
258
- tags.meta,
259
- tags.processingInstruction,
260
- markdownTags.CodeMark,
261
- markdownTags.EmphasisMark,
262
- markdownTags.HeaderMark,
263
- markdownTags.LinkLabel,
264
- markdownTags.LinkReference,
265
- markdownTags.ListMark,
266
- markdownTags.QuoteMark
267
- ],
268
- class: mark
269
- },
270
- // Headings.
271
- {
272
- tag: tags.heading1,
273
- class: heading[1]
274
- },
275
- {
276
- tag: tags.heading2,
277
- class: heading[2]
278
- },
279
- {
280
- tag: tags.heading3,
281
- class: heading[3]
282
- },
283
- {
284
- tag: tags.heading4,
285
- class: heading[4]
286
- },
287
- {
288
- tag: tags.heading5,
289
- class: heading[5]
290
- },
291
- {
292
- tag: tags.heading6,
293
- class: heading[6]
294
- },
295
- // Emphasis.
296
- {
297
- tag: tags.emphasis,
298
- class: italic
299
- },
300
- {
301
- tag: tags.strong,
302
- class: bold
303
- },
304
- {
305
- tag: tags.strikethrough,
306
- class: strikethrough
307
- },
308
- // Naked URLs.
309
- {
310
- tag: [
311
- markdownTags.URL
312
- ],
313
- class: inlineUrl
314
- },
315
- // E.g., code block language (after ```).
316
- {
317
- tag: [
318
- tags.function(tags.variableName),
319
- tags.labelName
320
- ],
321
- class: codeMark
322
- },
323
- // The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
324
- // However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
325
- // when a language is specified. In this case, the syntax highlighting extensions will colorize
326
- // the code, but all other CSS properties will be inherited.
327
- {
328
- tag: [
329
- markdownTags.CodeText,
330
- markdownTags.InlineCode
331
- ],
332
- class: code
333
- },
334
- {
335
- tag: [
336
- markdownTags.QuoteMark
337
- ],
338
- class: blockquote
339
- },
340
- {
341
- tag: [
342
- markdownTags.HorizontalRule
343
- ],
344
- class: horizontalRule
345
- }
346
- ], {
347
- scope: markdownLanguage,
348
- all: {
349
- 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
+ }
350
977
  }
351
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
+ };
352
1146
 
353
1147
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
354
- var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
1148
+ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
355
1149
  return [
1150
+ EditorState.allowMultipleSelections.of(true),
1151
+ EditorState.tabSize.of(2),
1152
+ EditorView8.lineWrapping,
1153
+ customKeymap(),
356
1154
  bracketMatching2(),
357
1155
  closeBrackets2(),
358
- _placeholder && placeholder2(_placeholder),
359
- EditorState.allowMultipleSelections.of(true),
360
- EditorView3.lineWrapping,
361
- // autocompletion(),
362
1156
  crosshairCursor(),
363
1157
  dropCursor(),
364
- drawSelection(),
365
- highlightActiveLine(),
366
- highlightActiveLineGutter(),
367
- highlightSelectionMatches(),
368
- highlightSpecialChars(),
1158
+ drawSelection2(),
369
1159
  history(),
370
1160
  indentOnInput(),
371
- rectangularSelection(),
372
- keymap2.of([
373
- ...closeBracketsKeymap,
374
- // ...completionKeymap,
375
- ...defaultKeymap,
376
- ...foldKeymap,
377
- ...historyKeymap,
378
- ...lintKeymap,
379
- ...searchKeymap,
380
- indentWithTab
381
- ]),
1161
+ _placeholder && placeholder2(_placeholder),
382
1162
  // Main extension.
383
1163
  // https://github.com/codemirror/lang-markdown
384
1164
  // https://codemirror.net/5/mode/markdown/index.html (demo).
@@ -393,102 +1173,231 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
393
1173
  codeLanguages: languages,
394
1174
  // Parser extensions.
395
1175
  extensions: [
396
- // GFM, // TODO(burdon): Provided by default?
397
- markdownTagsExtension
1176
+ // GFM provided by default.
1177
+ markdownTagsExtensions
398
1178
  ]
399
1179
  }),
1180
+ // https://github.com/codemirror/theme-one-dark
1181
+ themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
400
1182
  // Custom styles.
401
- syntaxHighlighting2(markdownHighlightStyle),
402
- // TODO(thure): All but one rule here apply to both themes; rename or refactor.
403
- themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
1183
+ syntaxHighlighting2(markdownHighlightStyle(readonly))
404
1184
  ].filter(Boolean);
405
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
+ };
406
1316
 
407
1317
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
408
- import { syntaxTree as syntaxTree2 } from "@codemirror/language";
409
- import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
410
- import { EditorView as EditorView4, Decoration as Decoration2, WidgetType as WidgetType2 } from "@codemirror/view";
411
- var CheckboxWidget = class extends WidgetType2 {
412
- constructor(_pos, _getCursor, _checked) {
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 {
1326
+ constructor(_pos, _checked, _indent, _onCheck) {
413
1327
  super();
414
1328
  this._pos = _pos;
415
- this._getCursor = _getCursor;
416
1329
  this._checked = _checked;
1330
+ this._indent = _indent;
1331
+ this._onCheck = _onCheck;
417
1332
  }
418
1333
  eq(other) {
419
- return this._pos === other._pos && this._checked === other._checked;
1334
+ return this._pos === other._pos && this._checked === other._checked && this._indent === other._indent;
420
1335
  }
421
1336
  toDOM(view) {
422
1337
  const wrap = document.createElement("span");
423
- wrap.setAttribute("aria-hidden", "true");
424
1338
  wrap.className = "cm-task-item";
425
- const box = wrap.appendChild(document.createElement("input"));
426
- box.type = "checkbox";
427
- box.checked = this._checked;
428
- box.onclick = (event) => {
429
- this._checked = !isChecked(view.state, this._pos);
430
- view.dispatch({
431
- changes: {
432
- from: this._pos + 1,
433
- to: this._pos + 2,
434
- insert: this._checked ? "x" : " "
435
- },
436
- // TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
437
- selection: {
438
- anchor: this._pos + 4
439
- }
440
- });
441
- return true;
442
- };
1339
+ wrap.setAttribute("aria-hidden", "true");
1340
+ wrap.style.setProperty("margin-left", this._indent * 24 + "px");
1341
+ const input = wrap.appendChild(document.createElement("input"));
1342
+ input.type = "checkbox";
1343
+ input.checked = this._checked;
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
+ }
443
1353
  return wrap;
444
1354
  }
445
- // TODO(burdon): Remove listener?
446
- // override destroy() {
447
- // console.log('destroy', this._pos);
448
- // }
449
1355
  ignoreEvent() {
450
1356
  return false;
451
1357
  }
452
1358
  };
453
- var isChecked = (state, pos) => {
454
- return state.sliceDoc(pos, pos + 3).toLowerCase() === "[x]";
455
- };
456
- var statefield = () => {
457
- let lastPosition = 0;
458
- const listener2 = EditorView4.updateListener.of((update2) => {
459
- lastPosition = update2.startState.selection.main.head;
1359
+ var tasklist = (options = {}) => {
1360
+ const taskMatcher = new MatchDecorator2({
1361
+ regexp: /^(\s*)- \[([ xX])\]\s/g,
1362
+ decoration: (match, view, pos) => {
1363
+ const indent = Math.floor(match[1].length / 2);
1364
+ const checked = match[2] === "x" || match[2] === "X";
1365
+ return Decoration7.replace({
1366
+ widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
1367
+ const idx = pos + match[0].indexOf("[") + 1;
1368
+ view.dispatch({
1369
+ changes: {
1370
+ from: idx,
1371
+ to: idx + 1,
1372
+ insert: checked2 ? "x" : " "
1373
+ },
1374
+ // TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
1375
+ selection: {
1376
+ anchor: idx + 3
1377
+ }
1378
+ });
1379
+ })
1380
+ });
1381
+ }
460
1382
  });
461
- const checkbox = (state) => {
462
- const builder = new RangeSetBuilder2();
463
- syntaxTree2(state).iterate({
464
- enter: (node) => {
465
- if (node.name === "TaskMarker") {
466
- builder.add(node.from, node.to, Decoration2.replace({
467
- widget: new CheckboxWidget(node.from, () => lastPosition, isChecked(state, node.from))
468
- }));
469
- }
470
- }
471
- });
472
- return builder.finish();
473
- };
474
- return [
475
- listener2,
476
- StateField3.define({
477
- create: (state) => checkbox(state),
478
- update: (_, tr) => checkbox(tr.state),
479
- provide: (field) => EditorView4.decorations.from(field)
1383
+ const tasks = ViewPlugin3.fromClass(class {
1384
+ constructor(view) {
1385
+ this.tasks = taskMatcher.createDeco(view);
1386
+ }
1387
+ update(update4) {
1388
+ this.tasks = taskMatcher.updateDeco(update4, this.tasks);
1389
+ }
1390
+ }, {
1391
+ decorations: (value) => value.tasks,
1392
+ provide: (plugin) => EditorView10.atomicRanges.of((view) => {
1393
+ return view.plugin(plugin)?.tasks || Decoration7.none;
480
1394
  })
1395
+ });
1396
+ return [
1397
+ tasks,
1398
+ styles4
481
1399
  ];
482
1400
  };
483
- var styles = EditorView4.baseTheme({
484
- "& .cm-task-item": {
485
- padding: "0 4px"
486
- }
487
- });
488
- var tasklist = () => [
489
- statefield(),
490
- styles
491
- ];
492
1401
 
493
1402
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tooltip.tsx
494
1403
  import { hoverTooltip } from "@codemirror/view";
@@ -535,7 +1444,7 @@ var tooltip = ({ onHover, regexp = markdownLinkRegexp }) => hoverTooltip((view,
535
1444
  });
536
1445
 
537
1446
  // packages/ui/react-ui-editor/src/components/TextEditor/themes/default.ts
538
- import get2 from "lodash.get";
1447
+ import get3 from "lodash.get";
539
1448
  var defaultTheme = {
540
1449
  //
541
1450
  // Main layout:
@@ -560,20 +1469,20 @@ var defaultTheme = {
560
1469
  fontSize: "16px"
561
1470
  },
562
1471
  "&light .cm-content": {
563
- color: get2(tokens, "extend.colors.neutral.900", "black"),
1472
+ color: get3(tokens, "extend.colors.neutral.900", "black"),
564
1473
  caretColor: "black"
565
1474
  },
566
1475
  "&dark .cm-content": {
567
- color: get2(tokens, "extend.colors.neutral.100", "white"),
1476
+ color: get3(tokens, "extend.colors.neutral.100", "white"),
568
1477
  caretColor: "white"
569
1478
  },
570
1479
  //
571
1480
  // Cursor
572
1481
  //
573
- "&light .cm-cursor": {
1482
+ "&light .cm-cursor, &light .cm-dropCursor": {
574
1483
  borderLeft: "2px solid black"
575
1484
  },
576
- "&dark .cm-cursor": {
1485
+ "&dark .cm-cursor, &dark .cm-dropCursor": {
577
1486
  borderLeft: "2px solid white"
578
1487
  },
579
1488
  "& .cm-placeholder": {
@@ -593,16 +1502,16 @@ var defaultTheme = {
593
1502
  // selection
594
1503
  //
595
1504
  "&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground": {
596
- background: get2(tokens, "extend.colors.primary.150", "#00ffff")
1505
+ background: get3(tokens, "extend.colors.primary.150", "#00ffff")
597
1506
  },
598
1507
  "&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground": {
599
- background: get2(tokens, "extend.colors.primary.850", "#00ffff")
1508
+ background: get3(tokens, "extend.colors.primary.850", "#00ffff")
600
1509
  },
601
1510
  "&light .cm-selectionMatch": {
602
- background: get2(tokens, "extend.colors.primary.250", "#00ffff") + "44"
1511
+ background: get3(tokens, "extend.colors.primary.250", "#00ffff") + "44"
603
1512
  },
604
1513
  "&dark .cm-selectionMatch": {
605
- background: get2(tokens, "extend.colors.primary.600", "#00ffff") + "44"
1514
+ background: get3(tokens, "extend.colors.primary.600", "#00ffff") + "44"
606
1515
  },
607
1516
  //
608
1517
  // collaboration
@@ -635,12 +1544,12 @@ var defaultTheme = {
635
1544
  // link
636
1545
  //
637
1546
  "& .cm-link": {
638
- color: get2(tokens, "extend.colors.primary.500"),
1547
+ color: get3(tokens, "extend.colors.primary.500"),
639
1548
  textDecorationLine: "underline",
640
1549
  textDecorationThickness: "1px",
641
1550
  textUnderlineOffset: "2px",
642
1551
  borderRadius: ".125rem",
643
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1552
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
644
1553
  },
645
1554
  //
646
1555
  // tooltip
@@ -648,14 +1557,61 @@ var defaultTheme = {
648
1557
  "& .cm-tooltip": {
649
1558
  border: "none"
650
1559
  },
651
- // '& .cm-tooltip-below': {},
652
- // '& .cm-tooltip-autocomplete': {},
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
+ },
653
1609
  //
654
1610
  // font size
655
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.
656
1612
  //
657
- ...Object.keys(get2(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
658
- const height = get2(tokens, [
1613
+ ...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
1614
+ const height = get3(tokens, [
659
1615
  "extend",
660
1616
  "fontSize",
661
1617
  fontSize,
@@ -672,40 +1628,99 @@ var defaultTheme = {
672
1628
  height
673
1629
  };
674
1630
  return acc;
675
- }, {})
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
+ }
676
1667
  };
677
1668
  var textTheme = {
678
1669
  "& .cm-scroller": {
679
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1670
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1671
+ },
1672
+ "& .cm-placeholder": {
1673
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1674
+ }
1675
+ };
1676
+ var markdownTheme = {
1677
+ // NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
1678
+ "& .cm-placeholder": {
1679
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
680
1680
  }
681
1681
  };
682
1682
  var codeTheme = {
683
1683
  "& .cm-scroller": {
684
- fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
1684
+ fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
1685
+ },
1686
+ "& .cm-placeholder": {
1687
+ fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
685
1688
  }
686
1689
  };
687
1690
 
688
1691
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
689
1692
  import { EditorState as EditorState2 } from "@codemirror/state";
690
- import { EditorView as EditorView5 } from "@codemirror/view";
1693
+ import { EditorView as EditorView11 } from "@codemirror/view";
691
1694
  import { useFocusableGroup } from "@fluentui/react-tabster";
692
1695
  import { vim } from "@replit/codemirror-vim";
693
- import defaultsDeep from "lodash.defaultsdeep";
694
- 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";
695
1698
  import { generateName } from "@dxos/display-name";
696
1699
  import { useThemeContext } from "@dxos/react-ui";
697
- import { getColorForValue, inputSurface, mx as mx2 } from "@dxos/react-ui-theme";
1700
+ import { getColorForValue, inputSurface, mx as mx4 } from "@dxos/react-ui-theme";
698
1701
  var EditorModes = [
699
1702
  "default",
700
1703
  "vim"
701
1704
  ];
702
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots = defaultSlots, editorMode }, forwardedRef) => {
1705
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
703
1706
  const { themeMode } = useThemeContext();
704
1707
  const tabsterDOMAttribute = useFocusableGroup({
705
1708
  tabBehavior: "limited"
706
1709
  });
1710
+ const [root, setRoot] = useState(null);
1711
+ const [state, setState] = useState();
1712
+ const [view, setView] = useState();
1713
+ useImperativeHandle(forwardedRef, () => ({
1714
+ root,
1715
+ state,
1716
+ view
1717
+ }), [
1718
+ view,
1719
+ state,
1720
+ root
1721
+ ]);
707
1722
  const { awareness, peer } = model;
708
- useEffect(() => {
1723
+ useEffect2(() => {
709
1724
  if (awareness && peer) {
710
1725
  awareness.setLocalStateField("user", {
711
1726
  name: peer.name ?? generateName(peer.id),
@@ -725,32 +1740,22 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
725
1740
  peer,
726
1741
  themeMode
727
1742
  ]);
728
- const [root, setRoot] = useState(null);
729
- const [state, setState] = useState();
730
- const [view, setView] = useState();
731
- useImperativeHandle(forwardedRef, () => ({
732
- root,
733
- state,
734
- view
735
- }), [
736
- view,
737
- state,
738
- root
739
- ]);
740
- useEffect(() => {
1743
+ useEffect2(() => {
741
1744
  if (!root) {
742
1745
  return;
743
1746
  }
744
1747
  const state2 = EditorState2.create({
745
1748
  doc: model.text(),
746
1749
  extensions: [
1750
+ readonly && EditorState2.readOnly.of(readonly),
747
1751
  // TODO(burdon): Factor out VIM mode?
748
1752
  editorMode === "vim" && vim(),
749
1753
  // Theme.
750
- EditorView5.baseTheme(defaultTheme),
751
- EditorView5.theme(slots?.editor?.theme ?? {}),
1754
+ // TODO(burdon): Make optional.
1755
+ EditorView11.baseTheme(defaultTheme),
1756
+ EditorView11.theme(slots?.editor?.theme ?? {}),
752
1757
  // TODO(burdon): themeMode doesn't change in storybooks.
753
- EditorView5.darkTheme.of(themeMode === "dark"),
1758
+ EditorView11.darkTheme.of(themeMode === "dark"),
754
1759
  // Storage and replication.
755
1760
  model.extension,
756
1761
  // Custom.
@@ -758,7 +1763,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
758
1763
  ].filter(Boolean)
759
1764
  });
760
1765
  view?.destroy();
761
- setView(new EditorView5({
1766
+ setView(new EditorView11({
762
1767
  state: state2,
763
1768
  parent: root
764
1769
  }));
@@ -772,6 +1777,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
772
1777
  root,
773
1778
  model,
774
1779
  themeMode,
1780
+ readonly,
775
1781
  editorMode
776
1782
  ]);
777
1783
  const handleKeyUp = useCallback((event) => {
@@ -799,13 +1805,15 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
799
1805
  onKeyUp: handleKeyUp
800
1806
  });
801
1807
  });
802
- var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
1808
+ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
803
1809
  const { themeMode } = useThemeContext();
804
- const slots = defaultsDeep({}, _slots, defaultTextSlots);
1810
+ const slots = defaultsDeep2({}, _slots, defaultTextSlots);
805
1811
  return /* @__PURE__ */ React.createElement(BaseTextEditor, {
806
1812
  ref: forwardedRef,
1813
+ readonly,
807
1814
  extensions: [
808
1815
  basicBundle({
1816
+ readonly,
809
1817
  themeMode,
810
1818
  placeholder: slots?.editor?.placeholder
811
1819
  }),
@@ -815,13 +1823,15 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, .
815
1823
  ...props
816
1824
  });
817
1825
  });
818
- var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
1826
+ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
819
1827
  const { themeMode } = useThemeContext();
820
- const slots = defaultsDeep({}, _slots, defaultSlots);
1828
+ const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
821
1829
  return /* @__PURE__ */ React.createElement(BaseTextEditor, {
822
1830
  ref: forwardedRef,
1831
+ readonly,
823
1832
  extensions: [
824
1833
  markdownBundle({
1834
+ readonly,
825
1835
  themeMode,
826
1836
  placeholder: slots?.editor?.placeholder
827
1837
  }),
@@ -833,7 +1843,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
833
1843
  });
834
1844
  var defaultSlots = {
835
1845
  root: {
836
- className: mx2("p-2", inputSurface)
1846
+ className: mx4("p-2", inputSurface)
837
1847
  }
838
1848
  };
839
1849
  var defaultTextSlots = {
@@ -842,25 +1852,31 @@ var defaultTextSlots = {
842
1852
  theme: textTheme
843
1853
  }
844
1854
  };
1855
+ var defaultMarkdownSlots = {
1856
+ ...defaultSlots,
1857
+ editor: {
1858
+ theme: markdownTheme
1859
+ }
1860
+ };
845
1861
 
846
1862
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
847
- import get3 from "lodash.get";
848
- import { useEffect as useEffect2, useState as useState2 } from "react";
1863
+ import get4 from "lodash.get";
1864
+ import { useEffect as useEffect3, useState as useState2 } from "react";
849
1865
  import { yCollab } from "y-codemirror.next";
850
- import { invariant } from "@dxos/invariant";
1866
+ import { invariant as invariant3 } from "@dxos/invariant";
851
1867
  import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
852
1868
 
853
1869
  // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
854
- import { Annotation, Facet, StateEffect, StateField as StateField4 } from "@codemirror/state";
855
- import { ViewPlugin } from "@codemirror/view";
1870
+ import { Annotation, Facet, StateEffect as StateEffect2, StateField as StateField6 } from "@codemirror/state";
1871
+ import { ViewPlugin as ViewPlugin4 } from "@codemirror/view";
856
1872
  import * as automerge2 from "@dxos/automerge/automerge";
857
1873
 
858
1874
  // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
859
1875
  import { next as automerge } from "@dxos/automerge/automerge";
860
1876
 
861
- // packages/ui/react-ui-editor/src/hooks/automerge/amToCodemirror.ts
1877
+ // packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
862
1878
  import { ChangeSet } from "@codemirror/state";
863
- var amToCodemirror_default = (view, selection, target, patches) => {
1879
+ var automergeToCodemirror = (view, selection, target, patches) => {
864
1880
  for (const patch of patches) {
865
1881
  const changeSpec = handlePatch(patch, target, view.state);
866
1882
  if (changeSpec != null) {
@@ -965,9 +1981,9 @@ var charPath = (textPath, candidatePath) => {
965
1981
  return null;
966
1982
  };
967
1983
 
968
- // packages/ui/react-ui-editor/src/hooks/automerge/codeMirrorToAm.ts
1984
+ // packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
969
1985
  import { next as am } from "@dxos/automerge/automerge";
970
- var codeMirrorToAm_default = (field, handle, transactions, state) => {
1986
+ var codemirrorToAutomerge = (field, handle, transactions, state) => {
971
1987
  const { lastHeads, path } = state.field(field);
972
1988
  let hasChanges = false;
973
1989
  for (const tr of transactions) {
@@ -1011,12 +2027,12 @@ var PatchSemaphore = class {
1011
2027
  annotations: reconcileAnnotationType.of(true)
1012
2028
  });
1013
2029
  }
1014
- let newHeads = codeMirrorToAm_default(this._field, handle, transactions, view.state);
2030
+ let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
1015
2031
  if (newHeads === null || newHeads === void 0) {
1016
2032
  newHeads = automerge.getHeads(handle.docSync());
1017
2033
  }
1018
2034
  const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
1019
- amToCodemirror_default(view, selection, path, diff);
2035
+ automergeToCodemirror(view, selection, path, diff);
1020
2036
  view.dispatch({
1021
2037
  effects: updateHeads(newHeads),
1022
2038
  annotations: reconcileAnnotationType.of({})
@@ -1030,7 +2046,7 @@ var PatchSemaphore = class {
1030
2046
  };
1031
2047
 
1032
2048
  // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
1033
- var effectType = StateEffect.define({});
2049
+ var effectType = StateEffect2.define({});
1034
2050
  var updateHeads = (newHeads) => effectType.of({
1035
2051
  newHeads
1036
2052
  });
@@ -1040,7 +2056,7 @@ var semaphoreFacet = Facet.define({
1040
2056
  combine: (values) => values.at(-1)
1041
2057
  });
1042
2058
  var automergePlugin = (handle, path) => {
1043
- const stateField = StateField4.define({
2059
+ const stateField = StateField6.define({
1044
2060
  create: () => ({
1045
2061
  lastHeads: automerge2.getHeads(handle.docSync()),
1046
2062
  unreconciledTransactions: [],
@@ -1070,7 +2086,7 @@ var automergePlugin = (handle, path) => {
1070
2086
  }
1071
2087
  });
1072
2088
  const semaphore = new PatchSemaphore(stateField);
1073
- const viewPlugin = ViewPlugin.fromClass(class AutomergeCodemirrorViewPlugin {
2089
+ const viewPlugin = ViewPlugin4.fromClass(class AutomergeCodemirrorViewPlugin {
1074
2090
  constructor(view) {
1075
2091
  this._handleChange = () => {
1076
2092
  this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
@@ -1078,8 +2094,8 @@ var automergePlugin = (handle, path) => {
1078
2094
  this._view = view;
1079
2095
  handle.addListener("change", this._handleChange);
1080
2096
  }
1081
- update(update2) {
1082
- if (update2.transactions.length > 0 && update2.transactions.some((t) => !isReconcileTx(t))) {
2097
+ update(update4) {
2098
+ if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
1083
2099
  queueMicrotask(() => {
1084
2100
  this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
1085
2101
  });
@@ -1101,7 +2117,7 @@ var reconcileAnnotationType = Annotation.define();
1101
2117
  var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
1102
2118
 
1103
2119
  // packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
1104
- import * as random from "lib0/random";
2120
+ import * as random2 from "lib0/random";
1105
2121
  var cursorColors = [
1106
2122
  {
1107
2123
  color: "#30bced",
@@ -1136,7 +2152,7 @@ var cursorColors = [
1136
2152
  light: "#1be7ff33"
1137
2153
  }
1138
2154
  ];
1139
- var cursorColor = cursorColors[random.uint32() % cursorColors.length];
2155
+ var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
1140
2156
 
1141
2157
  // packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
1142
2158
  import * as decoding from "lib0/decoding";
@@ -1144,7 +2160,7 @@ import * as encoding from "lib0/encoding";
1144
2160
  import { Observable } from "lib0/observable";
1145
2161
  import * as awarenessProtocol from "y-protocols/awareness";
1146
2162
  import { log } from "@dxos/log";
1147
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
2163
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
1148
2164
  var messageAwareness = 1;
1149
2165
  var messageQueryAwareness = 3;
1150
2166
  var SpaceAwarenessProvider = class extends Observable {
@@ -1181,7 +2197,7 @@ var SpaceAwarenessProvider = class extends Observable {
1181
2197
  removed,
1182
2198
  origin
1183
2199
  }, {
1184
- F: __dxlog_file,
2200
+ F: __dxlog_file3,
1185
2201
  L: 67,
1186
2202
  S: this,
1187
2203
  C: (f, a) => f(...a)
@@ -1194,7 +2210,7 @@ var SpaceAwarenessProvider = class extends Observable {
1194
2210
  }
1195
2211
  _handleSpaceMessage({ payload }) {
1196
2212
  log("space message", payload, {
1197
- F: __dxlog_file,
2213
+ F: __dxlog_file3,
1198
2214
  L: 79,
1199
2215
  S: this,
1200
2216
  C: (f, a) => f(...a)
@@ -1239,14 +2255,14 @@ var SpaceAwarenessProvider = class extends Observable {
1239
2255
  };
1240
2256
 
1241
2257
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
1242
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
2258
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
1243
2259
  var useTextModel = ({ identity, space, text }) => {
1244
2260
  const [model, setModel] = useState2(() => createModel({
1245
2261
  identity,
1246
2262
  space,
1247
2263
  text
1248
2264
  }));
1249
- useEffect2(() => {
2265
+ useEffect3(() => {
1250
2266
  setModel(createModel({
1251
2267
  identity,
1252
2268
  space,
@@ -1260,44 +2276,45 @@ var useTextModel = ({ identity, space, text }) => {
1260
2276
  return model;
1261
2277
  };
1262
2278
  var createModel = (options) => {
1263
- const { space, text } = options;
2279
+ const { text } = options;
1264
2280
  if (isActualAutomergeObject(text)) {
1265
2281
  return createAutomergeModel(options);
1266
2282
  } else {
1267
- if (!space || !text?.doc || !text?.content) {
2283
+ if (!text?.doc) {
1268
2284
  return void 0;
1269
2285
  }
1270
2286
  return createYjsModel(options);
1271
2287
  }
1272
2288
  };
1273
2289
  var createYjsModel = ({ identity, space, text }) => {
1274
- invariant(space && text?.doc && text?.content, void 0, {
1275
- F: __dxlog_file2,
1276
- L: 73,
2290
+ invariant3(text?.doc && text?.content, void 0, {
2291
+ F: __dxlog_file4,
2292
+ L: 81,
1277
2293
  S: void 0,
1278
2294
  A: [
1279
- "space && text?.doc && text?.content",
2295
+ "text?.doc && text?.content",
1280
2296
  ""
1281
2297
  ]
1282
2298
  });
1283
- const provider = new SpaceAwarenessProvider({
2299
+ const provider = space ? new SpaceAwarenessProvider({
1284
2300
  space,
1285
2301
  doc: text.doc,
1286
2302
  channel: `yjs.awareness.${text.id}`
1287
- });
2303
+ }) : void 0;
1288
2304
  return {
1289
2305
  id: text.doc.guid,
1290
2306
  content: text.content,
1291
2307
  text: () => text.content.toString(),
1292
- extension: yCollab(text.content, provider.awareness),
1293
- awareness: provider.awareness,
2308
+ ranges: [],
2309
+ extension: yCollab(text.content, provider?.awareness),
2310
+ awareness: provider?.awareness,
1294
2311
  peer: identity ? {
1295
2312
  id: identity.identityKey.toHex(),
1296
2313
  name: identity.profile?.displayName
1297
2314
  } : void 0
1298
2315
  };
1299
2316
  };
1300
- var createAutomergeModel = ({ identity, space, text }) => {
2317
+ var createAutomergeModel = ({ identity, text }) => {
1301
2318
  const obj = text;
1302
2319
  const doc = getRawDoc(obj, [
1303
2320
  obj.field
@@ -1305,7 +2322,8 @@ var createAutomergeModel = ({ identity, space, text }) => {
1305
2322
  return {
1306
2323
  id: obj.id,
1307
2324
  content: doc,
1308
- text: () => get3(doc.handle.docSync(), doc.path),
2325
+ text: () => get4(doc.handle.docSync(), doc.path),
2326
+ ranges: [],
1309
2327
  extension: automergePlugin(doc.handle, doc.path),
1310
2328
  peer: identity ? {
1311
2329
  id: identity.identityKey.toHex(),
@@ -1325,23 +2343,35 @@ export {
1325
2343
  YXmlFragment,
1326
2344
  autocomplete,
1327
2345
  basicBundle,
2346
+ blast,
2347
+ code2 as code,
1328
2348
  codeTheme,
2349
+ comments,
1329
2350
  cursorColor,
2351
+ defaultMarkdownSlots,
2352
+ defaultOptions,
1330
2353
  defaultSlots,
1331
2354
  defaultTextSlots,
1332
2355
  defaultTheme,
2356
+ demo,
2357
+ highlight,
2358
+ highlightDecorations,
2359
+ highlightStateField,
2360
+ image,
1333
2361
  link,
1334
- listener,
2362
+ listener2 as listener,
1335
2363
  markdownBundle,
1336
2364
  markdownHighlightStyle,
1337
2365
  markdownTags,
1338
- markdownTagsExtension,
1339
- statefield,
1340
- styles,
2366
+ markdownTagsExtensions,
2367
+ markdownTheme,
2368
+ mention,
2369
+ table,
1341
2370
  tags2 as tags,
1342
2371
  tasklist,
1343
2372
  textTheme,
1344
2373
  tooltip,
2374
+ useHighlights,
1345
2375
  useTextModel
1346
2376
  };
1347
2377
  //# sourceMappingURL=index.mjs.map