@dxos/react-ui-editor 0.3.10-main.c5193cc → 0.3.10-main.c9b5e9b

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 (55) hide show
  1. package/dist/lib/browser/index.mjs +615 -380
  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 +6 -3
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  7. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +3 -0
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/extensions/blast.d.ts +1 -1
  11. package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +1 -1
  12. package/dist/types/src/components/TextEditor/extensions/code.d.ts +2 -0
  13. package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +1 -0
  14. package/dist/types/src/components/TextEditor/extensions/comments.d.ts +1 -1
  15. package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -1
  16. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts +1 -1
  17. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -1
  18. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts +24 -0
  19. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts.map +1 -0
  20. package/dist/types/src/components/TextEditor/extensions/index.d.ts +2 -0
  21. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
  22. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +8 -0
  23. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
  24. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts +3 -1
  25. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
  26. package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
  27. package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -1
  28. package/dist/types/src/hooks/useTextModel.d.ts +6 -0
  29. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  30. package/dist/types/src/hooks/yjs/yjs.stories.d.ts +1 -1
  31. package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -1
  32. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  33. package/dist/types/src/testing/replicator.d.ts.map +1 -1
  34. package/package.json +22 -20
  35. package/src/components/TextEditor/MarkdownEditor.stories.tsx +48 -32
  36. package/src/components/TextEditor/TextEditor.stories.tsx +12 -1
  37. package/src/components/TextEditor/TextEditor.tsx +18 -1
  38. package/src/components/TextEditor/extensions/basic.ts +4 -3
  39. package/src/components/TextEditor/extensions/blast.ts +14 -28
  40. package/src/components/TextEditor/extensions/code.ts +99 -0
  41. package/src/components/TextEditor/extensions/comments.ts +22 -40
  42. package/src/components/TextEditor/extensions/experimental.tsx +15 -36
  43. package/src/components/TextEditor/extensions/highlight.ts +128 -0
  44. package/src/components/TextEditor/extensions/index.ts +2 -0
  45. package/src/components/TextEditor/extensions/link.ts +1 -2
  46. package/src/components/TextEditor/extensions/markdown/bundle.ts +19 -19
  47. package/src/components/TextEditor/extensions/markdown/highlight.ts +37 -11
  48. package/src/components/TextEditor/extensions/table.ts +44 -48
  49. package/src/components/TextEditor/extensions/tasklist.ts +9 -9
  50. package/src/components/TextEditor/themes/default.ts +43 -2
  51. package/src/hooks/automerge/automerge.stories.tsx +1 -0
  52. package/src/hooks/useTextModel.ts +9 -0
  53. package/src/hooks/yjs/yjs.stories.tsx +1 -1
  54. package/src/styles/markdown.ts +5 -4
  55. package/src/testing/replicator.ts +1 -0
@@ -42,20 +42,20 @@ 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";
45
+ import { drawSelection, EditorView, placeholder } from "@codemirror/view";
46
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
58
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts
58
- import { StateField } from "@codemirror/state";
59
59
  import { EditorView as EditorView2, keymap as keymap2 } from "@codemirror/view";
60
60
  import defaultsDeep from "lodash.defaultsdeep";
61
61
  import { invariant } from "@dxos/invariant";
@@ -86,7 +86,7 @@ var defaultOptions = {
86
86
  particleShrinkRate: 0.95,
87
87
  shakeIntensity: 5
88
88
  };
89
- var blast = (options) => {
89
+ var blast = (options = defaultOptions) => {
90
90
  let blaster;
91
91
  let last = 0;
92
92
  const getPoint = (view, pos) => {
@@ -123,10 +123,10 @@ var blast = (options) => {
123
123
  } else {
124
124
  blaster.resize();
125
125
  }
126
- const current = update4.view.state.selection.main.head;
126
+ const current = update4.state.selection.main.head;
127
127
  if (current !== last) {
128
128
  last = current;
129
- const { element, point } = getPoint(update4.view, current);
129
+ const { element, point } = getPoint(update4.view, current - 1);
130
130
  if (element && point) {
131
131
  blaster.spawn({
132
132
  element,
@@ -135,30 +135,16 @@ var blast = (options) => {
135
135
  }
136
136
  }
137
137
  }),
138
- // Document changed.
139
- StateField.define({
140
- create: () => null,
141
- update: (_value, transaction) => {
142
- if (blaster && transaction.docChanged) {
143
- const view = EditorView2.findFromDOM(blaster.node);
144
- const { element, point } = getPoint(view, transaction.selection.main.head);
145
- if (element && point) {
146
- blaster.spawn({
147
- element,
148
- point
149
- });
150
- }
151
- }
152
- return null;
153
- }
154
- }),
155
138
  keymap2.of([
156
139
  {
157
- any: (view, event) => {
158
- if (blaster && event.key === "Enter" && event.shiftKey) {
159
- blaster.shake({
160
- time: 0.4
161
- });
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
+ }
162
148
  }
163
149
  return false;
164
150
  }
@@ -180,7 +166,7 @@ var Blaster = class {
180
166
  y: 0
181
167
  };
182
168
  this.shake = throttle(({ time }) => {
183
- this._shakeTime = this._shakeTimeMax;
169
+ this._shakeTime = this._shakeTimeMax || time;
184
170
  this._shakeTimeMax = time;
185
171
  }, 100);
186
172
  this.spawn = throttle(({ element, point }) => {
@@ -201,7 +187,7 @@ var Blaster = class {
201
187
  initialize() {
202
188
  invariant(!this._canvas && !this._ctx, void 0, {
203
189
  F: __dxlog_file,
204
- L: 152,
190
+ L: 138,
205
191
  S: this,
206
192
  A: [
207
193
  "!this._canvas && !this._ctx",
@@ -238,7 +224,7 @@ var Blaster = class {
238
224
  start() {
239
225
  invariant(this._canvas && this._ctx, void 0, {
240
226
  F: __dxlog_file,
241
- L: 191,
227
+ L: 177,
242
228
  S: this,
243
229
  A: [
244
230
  "this._canvas && this._ctx",
@@ -379,6 +365,126 @@ var random = (min, max) => {
379
365
  return min + ~~(Math.random() * (max - min + 1));
380
366
  };
381
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
+
382
488
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
383
489
  import { keymap as keymap3 } from "@codemirror/view";
384
490
  var defaultItems = [
@@ -437,10 +543,21 @@ var demo = ({ delay = 75, items = defaultItems } = {}) => {
437
543
  };
438
544
 
439
545
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
440
- import { keymap as keymap4, Decoration, EditorView as EditorView3, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
546
+ import { keymap as keymap4, Decoration as Decoration2, EditorView as EditorView4, MatchDecorator, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
441
547
  import { debounce } from "@dxos/async";
442
548
  import { invariant as invariant2 } from "@dxos/invariant";
443
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
+ });
444
561
  var BookmarkWidget = class extends WidgetType {
445
562
  constructor(_pos, _id, _handleClick) {
446
563
  super();
@@ -449,7 +566,7 @@ var BookmarkWidget = class extends WidgetType {
449
566
  this._handleClick = _handleClick;
450
567
  invariant2(this._id, void 0, {
451
568
  F: __dxlog_file2,
452
- L: 41,
569
+ L: 37,
453
570
  S: this,
454
571
  A: [
455
572
  "this._id",
@@ -463,29 +580,18 @@ var BookmarkWidget = class extends WidgetType {
463
580
  toDOM() {
464
581
  const span = document.createElement("span");
465
582
  span.className = "cm-bookmark";
466
- span.textContent = "\u{1F4AC}";
583
+ span.textContent = "\xA7";
467
584
  span.onclick = () => this._handleClick();
468
585
  return span;
469
586
  }
470
587
  };
471
- var styles = EditorView3.baseTheme({
472
- "& .cm-bookmark": {
473
- cursor: "pointer",
474
- margin: "4px",
475
- padding: "4px",
476
- backgroundColor: "yellow"
477
- },
478
- "& .cm-bookmark-selected": {
479
- backgroundColor: "orange"
480
- }
481
- });
482
588
  var comments = (options = {}) => {
483
589
  let active;
484
590
  const bookmarkMatcher = new MatchDecorator({
485
591
  regexp: /\[\^(\w+)\]/g,
486
592
  decoration: (match, view, pos) => {
487
593
  const id = match[1];
488
- return Decoration.replace({
594
+ return Decoration2.replace({
489
595
  id,
490
596
  widget: new BookmarkWidget(pos, id, () => handleUpdate({
491
597
  active: id
@@ -493,7 +599,7 @@ var comments = (options = {}) => {
493
599
  });
494
600
  }
495
601
  });
496
- const bookmarks = ViewPlugin.fromClass(class {
602
+ const bookmarks = ViewPlugin2.fromClass(class {
497
603
  constructor(view) {
498
604
  this.bookmarks = bookmarkMatcher.createDeco(view);
499
605
  }
@@ -502,8 +608,8 @@ var comments = (options = {}) => {
502
608
  }
503
609
  }, {
504
610
  decorations: (instance) => instance.bookmarks,
505
- provide: (plugin) => EditorView3.atomicRanges.of((view) => {
506
- return view.plugin(plugin)?.bookmarks || Decoration.none;
611
+ provide: (plugin) => EditorView4.atomicRanges.of((view) => {
612
+ return view.plugin(plugin)?.bookmarks || Decoration2.none;
507
613
  })
508
614
  });
509
615
  const handleUpdate = debounce((data) => {
@@ -514,17 +620,17 @@ var comments = (options = {}) => {
514
620
  {
515
621
  key: options?.key ?? "shift-meta-c",
516
622
  run: (view) => {
517
- const id = options.onCreate?.();
623
+ const { from, to, head } = view.state.selection.main;
624
+ const id = options.onCreate?.(from, to);
518
625
  if (id) {
519
- const pos = view.state.selection.main.head;
520
626
  const tag = `[^${id}]`;
521
627
  view.dispatch({
522
628
  changes: {
523
- from: pos,
629
+ from: head,
524
630
  insert: tag
525
631
  },
526
632
  selection: {
527
- anchor: pos + tag.length
633
+ anchor: head + tag.length
528
634
  }
529
635
  });
530
636
  return true;
@@ -535,13 +641,13 @@ var comments = (options = {}) => {
535
641
  ]),
536
642
  bookmarks,
537
643
  // Monitor cursor movement.
538
- EditorView3.updateListener.of((update4) => {
644
+ EditorView4.updateListener.of((update4) => {
539
645
  active = void 0;
540
646
  if (!options.onUpdate) {
541
647
  return;
542
648
  }
543
- const view = update4.view;
544
- const pos = view.state.selection.main.head;
649
+ const { view, state } = update4;
650
+ const pos = state.selection.main.head;
545
651
  const decorations = [];
546
652
  const rangeSet = view.plugin(bookmarks)?.bookmarks;
547
653
  let closest = Infinity;
@@ -549,7 +655,7 @@ var comments = (options = {}) => {
549
655
  /* view.visibleRanges?.[0] ?? */
550
656
  {
551
657
  from: 0,
552
- to: view.state.doc.length
658
+ to: state.doc.length
553
659
  }
554
660
  );
555
661
  rangeSet?.between(from, to, (from2, to2, value) => {
@@ -575,19 +681,121 @@ var comments = (options = {}) => {
575
681
  });
576
682
  }
577
683
  }),
578
- styles
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
579
787
  ];
580
788
  };
581
789
 
582
790
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/image.ts
583
791
  import { syntaxTree } from "@codemirror/language";
584
792
  import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
585
- import { Decoration as Decoration2, EditorView as EditorView4, WidgetType as WidgetType2 } from "@codemirror/view";
793
+ import { Decoration as Decoration4, EditorView as EditorView6, WidgetType as WidgetType2 } from "@codemirror/view";
586
794
  var image = (options = {}) => {
587
795
  return StateField2.define({
588
796
  create: (state) => update(state, options),
589
797
  update: (_, tr) => update(tr.state, options),
590
- provide: (field) => EditorView4.decorations.from(field)
798
+ provide: (field) => EditorView6.decorations.from(field)
591
799
  });
592
800
  };
593
801
  var update = (state, options) => {
@@ -600,7 +808,7 @@ var update = (state, options) => {
600
808
  if (urlNode) {
601
809
  const hide = state.readOnly || cursor < node.from || cursor > node.to;
602
810
  const url = state.sliceDoc(urlNode.from, urlNode.to);
603
- builder.add(hide ? node.from : node.to, node.to, Decoration2.replace({
811
+ builder.add(hide ? node.from : node.to, node.to, Decoration4.replace({
604
812
  widget: new ImageWidget(url)
605
813
  }));
606
814
  }
@@ -628,12 +836,12 @@ var ImageWidget = class extends WidgetType2 {
628
836
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
629
837
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
630
838
  import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
631
- import { Decoration as Decoration3, EditorView as EditorView5, WidgetType as WidgetType3 } from "@codemirror/view";
839
+ import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
632
840
  var link = (options = {}) => {
633
841
  return StateField3.define({
634
842
  create: (state) => update2(state, options),
635
843
  update: (_, tr) => update2(tr.state, options),
636
- provide: (field) => EditorView5.decorations.from(field)
844
+ provide: (field) => EditorView7.decorations.from(field)
637
845
  });
638
846
  };
639
847
  var LinkButton = class extends WidgetType3 {
@@ -688,20 +896,20 @@ var update2 = (state, options) => {
688
896
  syntaxTree2(state).iterate({
689
897
  enter: (node) => {
690
898
  if (node.name === "Link") {
691
- const marks = node.node.getChildren("LinkMark");
692
- 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) : "";
693
901
  const urlNode = node.node.getChild("URL");
694
902
  const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
695
903
  if (!url) {
696
904
  return false;
697
905
  }
698
- if (cursor < node.from || cursor > node.to) {
699
- builder.add(node.from, node.to, Decoration3.replace({
906
+ if (state.readOnly || cursor < node.from || cursor > node.to) {
907
+ builder.add(node.from, node.to, Decoration5.replace({
700
908
  widget: new LinkText(node.from, text, options.link ? url : void 0)
701
909
  }));
702
910
  }
703
911
  if (options.onRender) {
704
- builder.add(node.to, node.to, Decoration3.replace({
912
+ builder.add(node.to, node.to, Decoration5.replace({
705
913
  widget: new LinkButton(node.from, url, options.onRender)
706
914
  }));
707
915
  }
@@ -714,7 +922,7 @@ var update2 = (state, options) => {
714
922
 
715
923
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
716
924
  import { StateField as StateField4 } from "@codemirror/state";
717
- var listener = ({ onChange }) => {
925
+ var listener2 = ({ onChange }) => {
718
926
  return StateField4.define({
719
927
  create: () => null,
720
928
  update: (_value, transaction) => {
@@ -732,66 +940,18 @@ import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirr
732
940
  import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
733
941
  import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
734
942
  import { languages } from "@codemirror/language-data";
735
- import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
943
+ import { searchKeymap } from "@codemirror/search";
736
944
  import { EditorState } from "@codemirror/state";
737
945
  import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
738
- import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView6, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap5, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
946
+ import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView8, highlightActiveLine, keymap as keymap5, placeholder as placeholder2 } from "@codemirror/view";
739
947
 
740
948
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
741
949
  import { markdownLanguage } from "@codemirror/lang-markdown";
742
950
  import { HighlightStyle } from "@codemirror/language";
743
951
  import { tags, styleTags, Tag } from "@lezer/highlight";
744
- import get from "lodash.get";
745
- import { mx as mx2 } from "@dxos/react-ui-theme";
746
-
747
- // packages/ui/react-ui-editor/src/styles/markdown.ts
748
- import { mx } from "@dxos/react-ui-theme";
749
- var headings = {
750
- 1: [
751
- "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
752
- "-ml-1.5"
753
- ],
754
- 2: [
755
- "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
756
- "-ml-1.5"
757
- ],
758
- 3: [
759
- "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
760
- "-ml-1.5"
761
- ],
762
- 4: [
763
- "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
764
- "-ml-[5px]"
765
- ],
766
- 5: [
767
- "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
768
- "-ml-[5px]"
769
- ],
770
- 6: [
771
- "mbs-4 mbe-2 font-medium text-inherit no-underline",
772
- "-ml-[4px]"
773
- ]
774
- };
775
- var heading = (level, readonly) => {
776
- const [style, offset] = headings[level];
777
- return mx(style, readonly && offset);
778
- };
779
- var light = "text-neutral-200 dark:text-neutral-800";
780
- var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
781
- var bold = "font-bold";
782
- var italic = "italic";
783
- var strikethrough = "line-through";
784
- var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
785
- var codeMark = "font-mono text-primary-500";
786
- var inlineUrl = mx(code, "px-1");
787
- var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
788
- var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800";
789
-
790
- // packages/ui/react-ui-editor/src/styles/tokens.ts
791
- import { tailwindConfig } from "@dxos/react-ui-theme";
792
- var tokens = tailwindConfig({}).theme;
793
-
794
- // 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";
795
955
  var markdownTags = {
796
956
  Blockquote: Tag.define(),
797
957
  CodeMark: Tag.define(),
@@ -804,176 +964,202 @@ var markdownTags = {
804
964
  LinkReference: Tag.define(),
805
965
  ListMark: Tag.define(),
806
966
  QuoteMark: Tag.define(),
807
- URL: Tag.define()
808
- };
809
- var markdownTagsExtension = {
810
- props: [
811
- styleTags(markdownTags)
812
- ]
967
+ URL: Tag.define(),
968
+ // Custom.
969
+ TableCell: Tag.define()
813
970
  };
814
- var markdownHighlightStyle = (readonly) => HighlightStyle.define([
815
- {
816
- tag: [
817
- tags.keyword,
818
- tags.name,
819
- tags.deleted,
820
- tags.character,
821
- tags.propertyName,
822
- tags.macroName,
823
- tags.color,
824
- tags.constant(tags.name),
825
- tags.standard(tags.name),
826
- tags.definition(tags.name),
827
- tags.separator,
828
- tags.typeName,
829
- tags.className,
830
- tags.number,
831
- tags.changed,
832
- tags.annotation,
833
- tags.modifier,
834
- tags.self,
835
- tags.namespace,
836
- tags.operator,
837
- tags.operatorKeyword,
838
- tags.escape,
839
- tags.regexp,
840
- tags.special(tags.string),
841
- tags.meta,
842
- tags.comment,
843
- tags.atom,
844
- tags.bool,
845
- tags.special(tags.variableName),
846
- tags.processingInstruction,
847
- tags.string,
848
- tags.inserted,
849
- tags.invalid
850
- ],
851
- color: "inherit !important"
852
- },
853
- // Markdown marks.
854
- {
855
- tag: [
856
- tags.meta,
857
- tags.processingInstruction,
858
- markdownTags.LinkLabel,
859
- markdownTags.LinkReference,
860
- markdownTags.ListMark
861
- ],
862
- class: mark
863
- },
864
- // Markdown marks.
865
- {
866
- tag: [
867
- markdownTags.CodeMark,
868
- markdownTags.HeaderMark,
869
- markdownTags.QuoteMark,
870
- markdownTags.EmphasisMark
871
- ],
872
- class: readonly ? "hidden" : mark
873
- },
874
- // E.g., code block language (after ```).
875
- {
876
- tag: [
877
- tags.function(tags.variableName),
878
- tags.labelName
879
- ],
880
- class: readonly ? "hidden" : codeMark
881
- },
882
- // Headings.
883
- {
884
- tag: tags.heading1,
885
- class: heading(1, readonly)
886
- },
887
- {
888
- tag: tags.heading2,
889
- class: heading(2, readonly)
890
- },
891
- {
892
- tag: tags.heading3,
893
- class: heading(3, readonly)
894
- },
895
- {
896
- tag: tags.heading4,
897
- class: heading(4, readonly)
898
- },
899
- {
900
- tag: tags.heading5,
901
- class: heading(5, readonly)
902
- },
903
- {
904
- tag: tags.heading6,
905
- class: heading(6, readonly)
906
- },
907
- // Emphasis.
908
- {
909
- tag: tags.emphasis,
910
- class: italic
911
- },
912
- {
913
- tag: tags.strong,
914
- class: bold
915
- },
916
- {
917
- tag: tags.strikethrough,
918
- class: strikethrough
919
- },
920
- // Naked URLs.
921
- {
922
- tag: [
923
- markdownTags.URL
924
- ],
925
- class: inlineUrl
926
- },
927
- // NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
928
- // However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
929
- // when a language is specified. In this case, the syntax highlighting extensions will colorize
930
- // the code, but all other CSS properties will be inherited.
931
- // IMPORTANT: Therefore, the fenced code block will use the base editor font.
932
- {
933
- tag: [
934
- markdownTags.CodeText,
935
- markdownTags.InlineCode
936
- ],
937
- class: code
938
- },
939
- {
940
- tag: [
941
- markdownTags.QuoteMark
942
- ],
943
- class: blockquote
944
- },
945
- {
946
- tag: [
947
- markdownTags.HorizontalRule
948
- ],
949
- class: mx2(horizontalRule, readonly && "-indent-[100rem]")
950
- }
951
- ], {
952
- scope: markdownLanguage,
953
- all: {
954
- 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
+ }
955
977
  }
956
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
+ };
957
1146
 
958
1147
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
959
1148
  var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
960
1149
  return [
1150
+ EditorState.allowMultipleSelections.of(true),
1151
+ EditorState.tabSize.of(2),
1152
+ EditorView8.lineWrapping,
1153
+ customKeymap(),
961
1154
  bracketMatching2(),
962
1155
  closeBrackets2(),
963
- _placeholder && placeholder2(_placeholder),
964
- EditorState.allowMultipleSelections.of(true),
965
- EditorView6.lineWrapping,
966
1156
  crosshairCursor(),
967
1157
  dropCursor(),
968
- drawSelection(),
1158
+ drawSelection2(),
969
1159
  highlightActiveLine(),
970
- highlightActiveLineGutter(),
971
- highlightSelectionMatches(),
972
- highlightSpecialChars(),
973
1160
  history(),
974
1161
  indentOnInput(),
975
- rectangularSelection(),
976
- customkeymap(),
1162
+ _placeholder && placeholder2(_placeholder),
977
1163
  // Main extension.
978
1164
  // https://github.com/codemirror/lang-markdown
979
1165
  // https://codemirror.net/5/mode/markdown/index.html (demo).
@@ -989,7 +1175,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
989
1175
  // Parser extensions.
990
1176
  extensions: [
991
1177
  // GFM provided by default.
992
- markdownTagsExtension
1178
+ markdownTagsExtensions
993
1179
  ]
994
1180
  }),
995
1181
  // https://github.com/codemirror/theme-one-dark
@@ -998,7 +1184,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
998
1184
  syntaxHighlighting2(markdownHighlightStyle(readonly))
999
1185
  ].filter(Boolean);
1000
1186
  };
1001
- var customkeymap = () => keymap5.of([
1187
+ var customKeymap = () => keymap5.of([
1002
1188
  // https://codemirror.net/docs/ref/#commands.indentWithTab
1003
1189
  indentWithTab,
1004
1190
  // https://codemirror.net/docs/ref/#commands.standardKeymap
@@ -1037,60 +1223,62 @@ var mention = ({ onSearch }) => {
1037
1223
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
1038
1224
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
1039
1225
  import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
1040
- import { Decoration as Decoration4, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
1226
+ import { Decoration as Decoration6, EditorView as EditorView9, WidgetType as WidgetType4 } from "@codemirror/view";
1041
1227
  var table = (options = {}) => {
1042
1228
  return StateField5.define({
1043
1229
  create: (state) => update3(state, options),
1044
1230
  update: (_, tr) => update3(tr.state, options),
1045
- provide: (field) => EditorView7.decorations.from(field)
1231
+ provide: (field) => EditorView9.decorations.from(field)
1046
1232
  });
1047
1233
  };
1048
1234
  var update3 = (state, options) => {
1049
1235
  const builder = new RangeSetBuilder3();
1050
- if (state.readOnly) {
1051
- const tables = [];
1052
- const getTable = () => tables[tables.length - 1];
1053
- const getRow = () => {
1054
- const table2 = getTable();
1055
- return table2.rows?.[table2.rows.length - 1];
1056
- };
1057
- syntaxTree3(state).iterate({
1058
- enter: (node) => {
1059
- switch (node.name) {
1060
- case "Table": {
1061
- tables.push({
1062
- from: node.from
1063
- });
1064
- break;
1065
- }
1066
- case "TableHeader": {
1067
- getTable().header = [];
1068
- break;
1069
- }
1070
- case "TableRow": {
1071
- (getTable().rows ??= []).push([]);
1072
- break;
1073
- }
1074
- case "TableCell": {
1075
- const row = getRow();
1076
- if (row) {
1077
- row.push(state.sliceDoc(node.from, node.to));
1078
- } else {
1079
- getTable().header?.push(state.sliceDoc(node.from, node.to));
1080
- }
1081
- break;
1082
- }
1083
- case "TableDelimiter": {
1084
- getTable().to = node.to;
1085
- break;
1236
+ const cursor = state.selection.main.head;
1237
+ const tables = [];
1238
+ const getTable = () => tables[tables.length - 1];
1239
+ const getRow = () => {
1240
+ const table2 = getTable();
1241
+ return table2.rows?.[table2.rows.length - 1];
1242
+ };
1243
+ syntaxTree3(state).iterate({
1244
+ enter: (node) => {
1245
+ switch (node.name) {
1246
+ case "Table": {
1247
+ tables.push({
1248
+ from: node.from,
1249
+ to: node.to
1250
+ });
1251
+ break;
1252
+ }
1253
+ case "TableHeader": {
1254
+ getTable().header = [];
1255
+ break;
1256
+ }
1257
+ case "TableRow": {
1258
+ (getTable().rows ??= []).push([]);
1259
+ break;
1260
+ }
1261
+ case "TableCell": {
1262
+ const row = getRow();
1263
+ if (row) {
1264
+ row.push(state.sliceDoc(node.from, node.to));
1265
+ } else {
1266
+ getTable().header?.push(state.sliceDoc(node.from, node.to));
1086
1267
  }
1268
+ break;
1087
1269
  }
1088
1270
  }
1089
- });
1090
- tables.forEach((table2) => builder.add(table2.from, table2.to, Decoration4.replace({
1271
+ }
1272
+ });
1273
+ tables.forEach((table2) => {
1274
+ const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
1275
+ hide && builder.add(table2.from, table2.to, Decoration6.replace({
1091
1276
  widget: new TableWidget(table2)
1092
- })));
1093
- }
1277
+ }));
1278
+ builder.add(table2.from, table2.to, Decoration6.mark({
1279
+ class: "cm-table"
1280
+ }));
1281
+ });
1094
1282
  return builder.finish();
1095
1283
  };
1096
1284
  var TableWidget = class extends WidgetType4 {
@@ -1105,11 +1293,11 @@ var TableWidget = class extends WidgetType4 {
1105
1293
  const table2 = document.createElement("table");
1106
1294
  {
1107
1295
  const header = table2.appendChild(document.createElement("thead"));
1108
- const row = header.appendChild(document.createElement("tr"));
1296
+ const tr = header.appendChild(document.createElement("tr"));
1109
1297
  this._table.header?.forEach((cell) => {
1110
1298
  const th = document.createElement("th");
1111
1299
  th.setAttribute("class", "cm-table-head");
1112
- row.appendChild(th).textContent = cell;
1300
+ tr.appendChild(th).textContent = cell;
1113
1301
  });
1114
1302
  }
1115
1303
  {
@@ -1128,7 +1316,13 @@ var TableWidget = class extends WidgetType4 {
1128
1316
  };
1129
1317
 
1130
1318
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
1131
- import { EditorView as EditorView8, Decoration as Decoration5, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin2 } from "@codemirror/view";
1319
+ import { EditorView as EditorView10, Decoration as Decoration7, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
1320
+ var styles4 = EditorView10.baseTheme({
1321
+ "& .cm-task-item": {
1322
+ paddingLeft: "4px",
1323
+ paddingRight: "8px"
1324
+ }
1325
+ });
1132
1326
  var CheckboxWidget = class extends WidgetType5 {
1133
1327
  constructor(_pos, _checked, _indent, _onCheck) {
1134
1328
  super();
@@ -1163,19 +1357,13 @@ var CheckboxWidget = class extends WidgetType5 {
1163
1357
  return false;
1164
1358
  }
1165
1359
  };
1166
- var styles2 = EditorView8.baseTheme({
1167
- "& .cm-task-item": {
1168
- paddingLeft: "4px",
1169
- paddingRight: "8px"
1170
- }
1171
- });
1172
1360
  var tasklist = (options = {}) => {
1173
1361
  const taskMatcher = new MatchDecorator2({
1174
1362
  regexp: /^(\s*)- \[([ xX])\]\s/g,
1175
1363
  decoration: (match, view, pos) => {
1176
1364
  const indent = Math.floor(match[1].length / 2);
1177
1365
  const checked = match[2] === "x" || match[2] === "X";
1178
- return Decoration5.replace({
1366
+ return Decoration7.replace({
1179
1367
  widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
1180
1368
  const idx = pos + match[0].indexOf("[") + 1;
1181
1369
  view.dispatch({
@@ -1193,7 +1381,7 @@ var tasklist = (options = {}) => {
1193
1381
  });
1194
1382
  }
1195
1383
  });
1196
- const tasks = ViewPlugin2.fromClass(class {
1384
+ const tasks = ViewPlugin3.fromClass(class {
1197
1385
  constructor(view) {
1198
1386
  this.tasks = taskMatcher.createDeco(view);
1199
1387
  }
@@ -1201,14 +1389,14 @@ var tasklist = (options = {}) => {
1201
1389
  this.tasks = taskMatcher.updateDeco(update4, this.tasks);
1202
1390
  }
1203
1391
  }, {
1204
- decorations: (instance) => instance.tasks,
1205
- provide: (plugin) => EditorView8.atomicRanges.of((view) => {
1206
- return view.plugin(plugin)?.tasks || Decoration5.none;
1392
+ decorations: (value) => value.tasks,
1393
+ provide: (plugin) => EditorView10.atomicRanges.of((view) => {
1394
+ return view.plugin(plugin)?.tasks || Decoration7.none;
1207
1395
  })
1208
1396
  });
1209
1397
  return [
1210
1398
  tasks,
1211
- styles2
1399
+ styles4
1212
1400
  ];
1213
1401
  };
1214
1402
 
@@ -1257,7 +1445,7 @@ var tooltip = ({ onHover, regexp = markdownLinkRegexp }) => hoverTooltip((view,
1257
1445
  });
1258
1446
 
1259
1447
  // packages/ui/react-ui-editor/src/components/TextEditor/themes/default.ts
1260
- import get2 from "lodash.get";
1448
+ import get3 from "lodash.get";
1261
1449
  var defaultTheme = {
1262
1450
  //
1263
1451
  // Main layout:
@@ -1282,20 +1470,20 @@ var defaultTheme = {
1282
1470
  fontSize: "16px"
1283
1471
  },
1284
1472
  "&light .cm-content": {
1285
- color: get2(tokens, "extend.colors.neutral.900", "black"),
1473
+ color: get3(tokens, "extend.colors.neutral.900", "black"),
1286
1474
  caretColor: "black"
1287
1475
  },
1288
1476
  "&dark .cm-content": {
1289
- color: get2(tokens, "extend.colors.neutral.100", "white"),
1477
+ color: get3(tokens, "extend.colors.neutral.100", "white"),
1290
1478
  caretColor: "white"
1291
1479
  },
1292
1480
  //
1293
1481
  // Cursor
1294
1482
  //
1295
- "&light .cm-cursor": {
1483
+ "&light .cm-cursor, &light .cm-dropCursor": {
1296
1484
  borderLeft: "2px solid black"
1297
1485
  },
1298
- "&dark .cm-cursor": {
1486
+ "&dark .cm-cursor, &dark .cm-dropCursor": {
1299
1487
  borderLeft: "2px solid white"
1300
1488
  },
1301
1489
  "& .cm-placeholder": {
@@ -1315,16 +1503,16 @@ var defaultTheme = {
1315
1503
  // selection
1316
1504
  //
1317
1505
  "&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground": {
1318
- background: get2(tokens, "extend.colors.primary.150", "#00ffff")
1506
+ background: get3(tokens, "extend.colors.primary.150", "#00ffff")
1319
1507
  },
1320
1508
  "&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground": {
1321
- background: get2(tokens, "extend.colors.primary.850", "#00ffff")
1509
+ background: get3(tokens, "extend.colors.primary.850", "#00ffff")
1322
1510
  },
1323
1511
  "&light .cm-selectionMatch": {
1324
- background: get2(tokens, "extend.colors.primary.250", "#00ffff") + "44"
1512
+ background: get3(tokens, "extend.colors.primary.250", "#00ffff") + "44"
1325
1513
  },
1326
1514
  "&dark .cm-selectionMatch": {
1327
- background: get2(tokens, "extend.colors.primary.600", "#00ffff") + "44"
1515
+ background: get3(tokens, "extend.colors.primary.600", "#00ffff") + "44"
1328
1516
  },
1329
1517
  //
1330
1518
  // collaboration
@@ -1357,12 +1545,12 @@ var defaultTheme = {
1357
1545
  // link
1358
1546
  //
1359
1547
  "& .cm-link": {
1360
- color: get2(tokens, "extend.colors.primary.500"),
1548
+ color: get3(tokens, "extend.colors.primary.500"),
1361
1549
  textDecorationLine: "underline",
1362
1550
  textDecorationThickness: "1px",
1363
1551
  textUnderlineOffset: "2px",
1364
1552
  borderRadius: ".125rem",
1365
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1553
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1366
1554
  },
1367
1555
  //
1368
1556
  // tooltip
@@ -1384,7 +1572,7 @@ var defaultTheme = {
1384
1572
  display: "none"
1385
1573
  },
1386
1574
  "& .cm-completionLabel": {
1387
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1575
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1388
1576
  },
1389
1577
  "& .cm-completionMatchedText": {
1390
1578
  textDecoration: "none"
@@ -1399,12 +1587,16 @@ var defaultTheme = {
1399
1587
  //
1400
1588
  // table
1401
1589
  //
1590
+ "& .cm-table *": {
1591
+ fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
1592
+ textDecoration: "none !important"
1593
+ },
1402
1594
  "& .cm-table-head": {
1403
1595
  padding: "2px 16px 2px 0px",
1404
- borderBottom: `1px solid ${get2(tokens, "extend.colors.neutral.500")}`,
1596
+ borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
1405
1597
  fontWeight: 100,
1406
1598
  textAlign: "left",
1407
- color: get2(tokens, "extend.colors.neutral.500")
1599
+ color: get3(tokens, "extend.colors.neutral.500")
1408
1600
  },
1409
1601
  "& .cm-table-cell": {
1410
1602
  padding: "2px 16px 2px 0px"
@@ -1419,8 +1611,8 @@ var defaultTheme = {
1419
1611
  // font size
1420
1612
  // 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.
1421
1613
  //
1422
- ...Object.keys(get2(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
1423
- const height = get2(tokens, [
1614
+ ...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
1615
+ const height = get3(tokens, [
1424
1616
  "extend",
1425
1617
  "fontSize",
1426
1618
  fontSize,
@@ -1437,41 +1629,76 @@ var defaultTheme = {
1437
1629
  height
1438
1630
  };
1439
1631
  return acc;
1440
- }, {})
1632
+ }, {}),
1633
+ /**
1634
+ * Panels
1635
+ * https://github.com/codemirror/search/blob/main/src/search.ts#L745
1636
+ *
1637
+ * Find/replace panel.
1638
+ * <div class="cm-announced">...</div>
1639
+ * <div class="cm-scroller">...</div>
1640
+ * <div class="cm-panels cm-panels-bottom">
1641
+ * <div class="cm-search cm-panel">
1642
+ * <input class="cm-textfield" />
1643
+ * <button class="cm-button">...</button>
1644
+ * <label><input type="checkbox" />...</label>
1645
+ * </div>
1646
+ * </div
1647
+ */
1648
+ "& .cm-panels": {
1649
+ border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`,
1650
+ borderBottom: "none"
1651
+ },
1652
+ "& .cm-panel": {
1653
+ background: get3(tokens, "extend.colors.neutral.50"),
1654
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1655
+ },
1656
+ "& .cm-button": {
1657
+ margin: "4px",
1658
+ fontFamily: get3(tokens, "fontFamily.body", []).join(","),
1659
+ background: get3(tokens, "extend.colors.neutral.100"),
1660
+ border: "none"
1661
+ },
1662
+ "& .cm-searchMatch": {
1663
+ backgroundColor: get3(tokens, "extend.colors.yellow.100")
1664
+ },
1665
+ "& .cm-searchMatch.cm-searchMatch-selected": {
1666
+ backgroundColor: get3(tokens, "extend.colors.primary.100")
1667
+ }
1441
1668
  };
1442
1669
  var textTheme = {
1443
1670
  "& .cm-scroller": {
1444
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1671
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1445
1672
  },
1446
1673
  "& .cm-placeholder": {
1447
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1674
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1448
1675
  }
1449
1676
  };
1450
1677
  var markdownTheme = {
1451
1678
  // NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
1452
1679
  "& .cm-placeholder": {
1453
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1680
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1454
1681
  }
1455
1682
  };
1456
1683
  var codeTheme = {
1457
1684
  "& .cm-scroller": {
1458
- fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
1685
+ fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
1459
1686
  },
1460
1687
  "& .cm-placeholder": {
1461
- fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
1688
+ fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
1462
1689
  }
1463
1690
  };
1464
1691
 
1465
1692
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
1466
1693
  import { EditorState as EditorState2 } from "@codemirror/state";
1467
- import { EditorView as EditorView9 } from "@codemirror/view";
1694
+ import { EditorView as EditorView11 } from "@codemirror/view";
1468
1695
  import { useFocusableGroup } from "@fluentui/react-tabster";
1469
1696
  import { vim } from "@replit/codemirror-vim";
1470
1697
  import defaultsDeep2 from "lodash.defaultsdeep";
1471
- import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
1698
+ import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
1472
1699
  import { generateName } from "@dxos/display-name";
1473
1700
  import { useThemeContext } from "@dxos/react-ui";
1474
- import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
1701
+ import { getColorForValue, inputSurface, mx as mx4 } from "@dxos/react-ui-theme";
1475
1702
  var EditorModes = [
1476
1703
  "default",
1477
1704
  "vim"
@@ -1494,7 +1721,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
1494
1721
  root
1495
1722
  ]);
1496
1723
  const { awareness, peer } = model;
1497
- useEffect(() => {
1724
+ useEffect2(() => {
1498
1725
  if (awareness && peer) {
1499
1726
  awareness.setLocalStateField("user", {
1500
1727
  name: peer.name ?? generateName(peer.id),
@@ -1514,7 +1741,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
1514
1741
  peer,
1515
1742
  themeMode
1516
1743
  ]);
1517
- useEffect(() => {
1744
+ useEffect2(() => {
1518
1745
  if (!root) {
1519
1746
  return;
1520
1747
  }
@@ -1525,10 +1752,11 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
1525
1752
  // TODO(burdon): Factor out VIM mode?
1526
1753
  editorMode === "vim" && vim(),
1527
1754
  // Theme.
1528
- EditorView9.baseTheme(defaultTheme),
1529
- EditorView9.theme(slots?.editor?.theme ?? {}),
1755
+ // TODO(burdon): Make optional.
1756
+ EditorView11.baseTheme(defaultTheme),
1757
+ EditorView11.theme(slots?.editor?.theme ?? {}),
1530
1758
  // TODO(burdon): themeMode doesn't change in storybooks.
1531
- EditorView9.darkTheme.of(themeMode === "dark"),
1759
+ EditorView11.darkTheme.of(themeMode === "dark"),
1532
1760
  // Storage and replication.
1533
1761
  model.extension,
1534
1762
  // Custom.
@@ -1536,7 +1764,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode,
1536
1764
  ].filter(Boolean)
1537
1765
  });
1538
1766
  view?.destroy();
1539
- setView(new EditorView9({
1767
+ setView(new EditorView11({
1540
1768
  state: state2,
1541
1769
  parent: root
1542
1770
  }));
@@ -1616,7 +1844,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], sl
1616
1844
  });
1617
1845
  var defaultSlots = {
1618
1846
  root: {
1619
- className: mx3("p-2", inputSurface)
1847
+ className: mx4("p-2", inputSurface)
1620
1848
  }
1621
1849
  };
1622
1850
  var defaultTextSlots = {
@@ -1633,15 +1861,15 @@ var defaultMarkdownSlots = {
1633
1861
  };
1634
1862
 
1635
1863
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
1636
- import get3 from "lodash.get";
1637
- import { useEffect as useEffect2, useState as useState2 } from "react";
1864
+ import get4 from "lodash.get";
1865
+ import { useEffect as useEffect3, useState as useState2 } from "react";
1638
1866
  import { yCollab } from "y-codemirror.next";
1639
1867
  import { invariant as invariant3 } from "@dxos/invariant";
1640
1868
  import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
1641
1869
 
1642
1870
  // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
1643
- import { Annotation, Facet, StateEffect, StateField as StateField6 } from "@codemirror/state";
1644
- import { ViewPlugin as ViewPlugin3 } from "@codemirror/view";
1871
+ import { Annotation, Facet, StateEffect as StateEffect2, StateField as StateField6 } from "@codemirror/state";
1872
+ import { ViewPlugin as ViewPlugin4 } from "@codemirror/view";
1645
1873
  import * as automerge2 from "@dxos/automerge/automerge";
1646
1874
 
1647
1875
  // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
@@ -1819,7 +2047,7 @@ var PatchSemaphore = class {
1819
2047
  };
1820
2048
 
1821
2049
  // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
1822
- var effectType = StateEffect.define({});
2050
+ var effectType = StateEffect2.define({});
1823
2051
  var updateHeads = (newHeads) => effectType.of({
1824
2052
  newHeads
1825
2053
  });
@@ -1859,7 +2087,7 @@ var automergePlugin = (handle, path) => {
1859
2087
  }
1860
2088
  });
1861
2089
  const semaphore = new PatchSemaphore(stateField);
1862
- const viewPlugin = ViewPlugin3.fromClass(class AutomergeCodemirrorViewPlugin {
2090
+ const viewPlugin = ViewPlugin4.fromClass(class AutomergeCodemirrorViewPlugin {
1863
2091
  constructor(view) {
1864
2092
  this._handleChange = () => {
1865
2093
  this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
@@ -2035,7 +2263,7 @@ var useTextModel = ({ identity, space, text }) => {
2035
2263
  space,
2036
2264
  text
2037
2265
  }));
2038
- useEffect2(() => {
2266
+ useEffect3(() => {
2039
2267
  setModel(createModel({
2040
2268
  identity,
2041
2269
  space,
@@ -2062,7 +2290,7 @@ var createModel = (options) => {
2062
2290
  var createYjsModel = ({ identity, space, text }) => {
2063
2291
  invariant3(text?.doc && text?.content, void 0, {
2064
2292
  F: __dxlog_file4,
2065
- L: 74,
2293
+ L: 81,
2066
2294
  S: void 0,
2067
2295
  A: [
2068
2296
  "text?.doc && text?.content",
@@ -2078,6 +2306,7 @@ var createYjsModel = ({ identity, space, text }) => {
2078
2306
  id: text.doc.guid,
2079
2307
  content: text.content,
2080
2308
  text: () => text.content.toString(),
2309
+ ranges: [],
2081
2310
  extension: yCollab(text.content, provider?.awareness),
2082
2311
  awareness: provider?.awareness,
2083
2312
  peer: identity ? {
@@ -2094,7 +2323,8 @@ var createAutomergeModel = ({ identity, text }) => {
2094
2323
  return {
2095
2324
  id: obj.id,
2096
2325
  content: doc,
2097
- text: () => get3(doc.handle.docSync(), doc.path),
2326
+ text: () => get4(doc.handle.docSync(), doc.path),
2327
+ ranges: [],
2098
2328
  extension: automergePlugin(doc.handle, doc.path),
2099
2329
  peer: identity ? {
2100
2330
  id: identity.identityKey.toHex(),
@@ -2115,6 +2345,7 @@ export {
2115
2345
  autocomplete,
2116
2346
  basicBundle,
2117
2347
  blast,
2348
+ code2 as code,
2118
2349
  codeTheme,
2119
2350
  comments,
2120
2351
  cursorColor,
@@ -2124,13 +2355,16 @@ export {
2124
2355
  defaultTextSlots,
2125
2356
  defaultTheme,
2126
2357
  demo,
2358
+ highlight,
2359
+ highlightDecorations,
2360
+ highlightStateField,
2127
2361
  image,
2128
2362
  link,
2129
- listener,
2363
+ listener2 as listener,
2130
2364
  markdownBundle,
2131
2365
  markdownHighlightStyle,
2132
2366
  markdownTags,
2133
- markdownTagsExtension,
2367
+ markdownTagsExtensions,
2134
2368
  markdownTheme,
2135
2369
  mention,
2136
2370
  table,
@@ -2138,6 +2372,7 @@ export {
2138
2372
  tasklist,
2139
2373
  textTheme,
2140
2374
  tooltip,
2375
+ useHighlights,
2141
2376
  useTextModel
2142
2377
  };
2143
2378
  //# sourceMappingURL=index.mjs.map