@dxos/ui-editor 0.8.4-main.69d29f4 → 0.8.4-main.7996785055

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 (71) hide show
  1. package/dist/lib/browser/index.mjs +594 -461
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +594 -461
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/defaults.d.ts +2 -9
  8. package/dist/types/src/defaults.d.ts.map +1 -1
  9. package/dist/types/src/extensions/auto-scroll.d.ts +6 -0
  10. package/dist/types/src/extensions/auto-scroll.d.ts.map +1 -0
  11. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  12. package/dist/types/src/extensions/factories.d.ts.map +1 -1
  13. package/dist/types/src/extensions/folding.d.ts.map +1 -1
  14. package/dist/types/src/extensions/index.d.ts +2 -2
  15. package/dist/types/src/extensions/index.d.ts.map +1 -1
  16. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  17. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  18. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  19. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
  20. package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
  21. package/dist/types/src/extensions/preview/preview.d.ts +3 -1
  22. package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
  23. package/dist/types/src/extensions/scroller.d.ts +66 -0
  24. package/dist/types/src/extensions/scroller.d.ts.map +1 -0
  25. package/dist/types/src/extensions/tags/streamer.d.ts +1 -1
  26. package/dist/types/src/styles/index.d.ts +0 -2
  27. package/dist/types/src/styles/index.d.ts.map +1 -1
  28. package/dist/types/src/styles/theme.d.ts +15 -0
  29. package/dist/types/src/styles/theme.d.ts.map +1 -1
  30. package/dist/types/src/util/cursor.d.ts +1 -1
  31. package/dist/types/src/util/cursor.d.ts.map +1 -1
  32. package/dist/types/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +32 -32
  34. package/src/defaults.ts +15 -17
  35. package/src/extensions/annotations.ts +1 -1
  36. package/src/extensions/auto-scroll.ts +129 -0
  37. package/src/extensions/automerge/automerge.test.tsx +2 -2
  38. package/src/extensions/automerge/automerge.ts +6 -5
  39. package/src/extensions/blocks.ts +5 -5
  40. package/src/extensions/comments.ts +5 -5
  41. package/src/extensions/dnd.ts +2 -2
  42. package/src/extensions/factories.ts +6 -7
  43. package/src/extensions/folding.ts +3 -20
  44. package/src/extensions/index.ts +2 -2
  45. package/src/extensions/markdown/bundle.ts +19 -8
  46. package/src/extensions/markdown/decorate.ts +15 -11
  47. package/src/extensions/markdown/highlight.ts +15 -7
  48. package/src/extensions/markdown/link.ts +27 -33
  49. package/src/extensions/markdown/parser.test.ts +0 -1
  50. package/src/extensions/markdown/styles.ts +27 -9
  51. package/src/extensions/outliner/outliner.ts +3 -3
  52. package/src/extensions/preview/preview.ts +62 -15
  53. package/src/extensions/scroller.ts +233 -0
  54. package/src/extensions/selection.ts +1 -1
  55. package/src/extensions/tags/streamer.ts +2 -2
  56. package/src/extensions/tags/xml-tags.ts +7 -4
  57. package/src/styles/index.ts +0 -2
  58. package/src/styles/theme.ts +116 -34
  59. package/src/util/cursor.ts +1 -1
  60. package/dist/types/src/extensions/autoscroll.d.ts +0 -20
  61. package/dist/types/src/extensions/autoscroll.d.ts.map +0 -1
  62. package/dist/types/src/extensions/scrolling.d.ts +0 -78
  63. package/dist/types/src/extensions/scrolling.d.ts.map +0 -1
  64. package/dist/types/src/styles/markdown.d.ts +0 -8
  65. package/dist/types/src/styles/markdown.d.ts.map +0 -1
  66. package/dist/types/src/styles/tokens.d.ts +0 -3
  67. package/dist/types/src/styles/tokens.d.ts.map +0 -1
  68. package/src/extensions/autoscroll.ts +0 -165
  69. package/src/extensions/scrolling.ts +0 -189
  70. package/src/styles/markdown.ts +0 -26
  71. package/src/styles/tokens.ts +0 -17
@@ -13,17 +13,23 @@ import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
13
13
 
14
14
  // src/defaults.ts
15
15
  import { mx } from "@dxos/ui-theme";
16
- var editorWidth = "!mli-auto is-full max-is-[min(50rem,100%-4rem)]";
17
- var editorSlots = {
18
- scroll: {
19
- className: "pbs-2"
20
- },
16
+ var documentSlots = {
21
17
  content: {
22
- className: editorWidth
18
+ /**
19
+ * CodeMirror content width.
20
+ * 40rem = 640px. Corresponds to initial plank width (Google docs, Stashpad, etc.)
21
+ * 50rem = 800px. Maximum content width for solo mode.
22
+ * NOTE: Max width - 4rem = 2rem left/right margin (or 2rem gutter plus 1rem left/right margin).
23
+ */
24
+ className: "mx-auto! w-full pointer-fine:max-w-[min(50rem,100%-4rem)] pointer-coarse:max-w-[min(50rem,100%-2rem)]"
23
25
  }
24
26
  };
25
- var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
26
- var stackItemContentEditorClassNames = (role) => mx("p-0.5 dx-focus-ring-inset attention-surface data-[toolbar=disabled]:pbs-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24" : "min-bs-0");
27
+ var compactSlots = {
28
+ content: {
29
+ className: "mx-2! w-full"
30
+ }
31
+ };
32
+ var stackItemContentEditorClassNames = (role) => mx("dx-attention-surface p-0.5 dx-focus-ring-inset data-[toolbar=disabled]:pt-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-h-24" : "dx-container overflow-hidden");
27
33
 
28
34
  // src/extensions/annotations.ts
29
35
  import { RangeSetBuilder } from "@codemirror/state";
@@ -58,7 +64,7 @@ var annotations = ({ match } = {}) => {
58
64
  ".cm-annotation": {
59
65
  textDecoration: "underline",
60
66
  textDecorationStyle: "wavy",
61
- textDecorationColor: "var(--dx-errorText)"
67
+ textDecorationColor: "var(--color-error-text)"
62
68
  }
63
69
  })
64
70
  ];
@@ -501,228 +507,245 @@ var typeahead = ({ onComplete } = {}) => {
501
507
  ];
502
508
  };
503
509
 
504
- // src/extensions/autoscroll.ts
505
- import { StateEffect as StateEffect2 } from "@codemirror/state";
510
+ // src/extensions/auto-scroll.ts
506
511
  import { EditorView as EditorView5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
507
- import { debounce } from "@dxos/async";
512
+ import { addEventListener, combine, throttle } from "@dxos/async";
508
513
  import { Domino } from "@dxos/ui";
509
514
 
510
- // src/extensions/scrolling.ts
515
+ // src/extensions/scroller.ts
511
516
  import { StateEffect } from "@codemirror/state";
512
517
  import { EditorView as EditorView4, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
513
- var scrollToLineEffect = StateEffect.define();
514
- var smoothScroll = ({ offset = 0, position = "start" } = {}) => {
515
- const scrollPlugin = ViewPlugin5.fromClass(class SmoothScrollPlugin {
518
+ import { log as log2 } from "@dxos/log";
519
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/scroller.ts";
520
+ var scrollerLineEffect = StateEffect.define();
521
+ var scrollerCrawlEffect = StateEffect.define();
522
+ var scrollToLine = (view, options) => {
523
+ view.dispatch({
524
+ effects: scrollerLineEffect.of(options)
525
+ });
526
+ };
527
+ var scroller = ({ overScroll = 0 } = {}) => {
528
+ const scrollPlugin = ViewPlugin5.fromClass(class ScrollerPlugin {
516
529
  view;
530
+ crawler;
517
531
  constructor(view) {
518
532
  this.view = view;
533
+ this.crawler = createCrawler(this.view);
519
534
  }
520
535
  // No-op.
521
536
  destroy() {
537
+ this.crawler.cancel();
522
538
  }
523
- /**
524
- * Perform smooth scroll to the specified line.
525
- */
526
- scrollToLine(lineNumber, options) {
527
- const { offset: animOffset = 0, position: animPosition, behavior } = options;
528
- const doc = this.view.state.doc;
529
- const scroller = this.view.scrollDOM;
530
- const targetLine = Math.max(0, lineNumber - 1);
531
- if (behavior === "instant") {
532
- requestAnimationFrame(() => {
533
- this.view.dispatch({
534
- selection: {
535
- anchor: doc.line(targetLine + 1).from
536
- },
537
- scrollIntoView: true
538
- });
539
- });
540
- return;
541
- }
542
- if (targetLine >= doc.lines) {
543
- const targetScrollTop2 = scroller.scrollHeight - scroller.clientHeight + (animOffset || 0);
544
- this.animateScroll(scroller, targetScrollTop2);
545
- return;
546
- }
547
- const lineStart = doc.line(targetLine + 1).from;
548
- const coords = this.view.coordsAtPos(lineStart);
549
- if (!coords) {
550
- return;
551
- }
552
- const currentScrollTop = scroller.scrollTop;
553
- const scrollerRect = scroller.getBoundingClientRect();
554
- const maxScrollTop = scroller.scrollHeight - scroller.clientHeight;
555
- let targetScrollTop;
556
- if (animPosition === "end") {
557
- targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + animOffset;
539
+ cancel() {
540
+ this.crawler.cancel();
541
+ }
542
+ crawl(start = false) {
543
+ if (start) {
544
+ this.crawler.scroll();
558
545
  } else {
559
- targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + animOffset;
546
+ this.crawler.cancel();
560
547
  }
561
- const clampedScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
562
- this.animateScroll(scroller, clampedScrollTop);
563
548
  }
564
- /**
565
- * Animate scroll using browser's built-in smooth scrolling.
566
- */
567
- animateScroll(element, targetScrollTop) {
568
- if (Math.abs(targetScrollTop - element.scrollTop) < 1) {
569
- return;
549
+ scroll({ line, offset = 0, position, behavior = "instant" }) {
550
+ const { scrollTop, scrollHeight, clientHeight } = this.view.scrollDOM;
551
+ const scrollerRect = this.view.scrollDOM.getBoundingClientRect();
552
+ const doc = this.view.state.doc;
553
+ let targetScrollTop = scrollHeight - clientHeight + offset;
554
+ if (line >= 0 && line <= doc.lines - 1) {
555
+ const lineStart = doc.line(line + 1).from;
556
+ const coords = this.view.coordsAtPos(lineStart);
557
+ if (coords) {
558
+ const currentScrollTop = scrollTop;
559
+ const maxScrollTop = scrollHeight - clientHeight;
560
+ if (position === "end") {
561
+ targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + offset;
562
+ } else {
563
+ targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + offset;
564
+ }
565
+ targetScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
566
+ }
570
567
  }
571
- element.scrollTo({
572
- top: targetScrollTop,
573
- behavior: "smooth"
568
+ requestAnimationFrame(() => {
569
+ this.view.scrollDOM.scrollTo({
570
+ top: targetScrollTop
571
+ });
574
572
  });
575
573
  }
576
574
  });
577
575
  return [
578
576
  scrollPlugin,
579
- // Update listener to handle scroll effects.
577
+ // Listen for effect.s
580
578
  EditorView4.updateListener.of((update2) => {
581
579
  update2.transactions.forEach((transaction) => {
582
- for (const effect of transaction.effects) {
583
- if (effect.is(scrollToLineEffect)) {
584
- const { line, options = {} } = effect.value;
585
- const plugin = update2.view.plugin(scrollPlugin);
586
- if (plugin) {
587
- plugin.scrollToLine(line, {
588
- offset,
589
- position,
590
- ...options
591
- });
580
+ try {
581
+ const plugin = update2.view.plugin(scrollPlugin);
582
+ if (plugin) {
583
+ for (const effect of transaction.effects) {
584
+ if (effect.is(scrollerCrawlEffect)) {
585
+ plugin.crawl(effect.value);
586
+ } else if (effect.is(scrollerLineEffect)) {
587
+ plugin.scroll(effect.value);
588
+ }
592
589
  }
593
590
  }
591
+ } catch (err) {
592
+ log2.catch(err, void 0, {
593
+ F: __dxlog_file2,
594
+ L: 146,
595
+ S: void 0,
596
+ C: (f, a) => f(...a)
597
+ });
594
598
  }
595
599
  });
600
+ }),
601
+ // Styles.
602
+ EditorView4.theme({
603
+ ".cm-content": {
604
+ paddingBottom: `${overScroll}px`
605
+ },
606
+ ".cm-scroller": {
607
+ overflowAnchor: "none",
608
+ paddingBottom: "0"
609
+ },
610
+ ".cm-scroller.cm-hide-scrollbar::-webkit-scrollbar": {
611
+ display: "none"
612
+ },
613
+ ".cm-scroller::-webkit-scrollbar-thumb": {
614
+ background: "transparent",
615
+ transition: "background 0.15s"
616
+ },
617
+ "&:hover .cm-scroller::-webkit-scrollbar-thumb": {
618
+ background: "var(--color-scrollbar-thumb)"
619
+ },
620
+ ".cm-scroll-button": {
621
+ position: "absolute",
622
+ bottom: "0.5rem",
623
+ right: "1rem"
624
+ }
596
625
  })
597
626
  ];
598
627
  };
599
- var scrollToLine = (view, line, options) => {
600
- view.dispatch({
601
- effects: scrollToLineEffect.of({
602
- line,
603
- options
604
- })
605
- });
606
- };
628
+ function createCrawler(view, k = 0.3, maxStep = 2, targetDelta = 0.5) {
629
+ const el = view.scrollDOM;
630
+ let currentTop = 0;
631
+ let rafId = null;
632
+ function frame() {
633
+ const targetTop = el.scrollHeight - el.clientHeight;
634
+ const delta = targetTop - currentTop;
635
+ const absDelta = Math.abs(delta);
636
+ if (absDelta < targetDelta) {
637
+ el.scrollTop = targetTop;
638
+ currentTop = targetTop;
639
+ rafId = null;
640
+ return;
641
+ }
642
+ const step = Math.sign(delta) * Math.min(absDelta, Math.max(1, Math.min(absDelta * k, maxStep)));
643
+ currentTop += step;
644
+ el.scrollTop = currentTop;
645
+ rafId = requestAnimationFrame(frame);
646
+ }
647
+ return {
648
+ scroll: () => {
649
+ if (rafId === null) {
650
+ currentTop = el.scrollTop;
651
+ rafId = requestAnimationFrame(frame);
652
+ }
653
+ },
654
+ cancel: () => {
655
+ if (rafId !== null) {
656
+ cancelAnimationFrame(rafId);
657
+ rafId = null;
658
+ }
659
+ }
660
+ };
661
+ }
607
662
 
608
- // src/extensions/autoscroll.ts
609
- var scrollToBottomEffect = StateEffect2.define();
610
- var autoScroll = ({ autoScroll: autoScroll2 = true, threshold = 100, throttleDelay = 1e3, onAutoScroll } = {}) => {
663
+ // src/extensions/auto-scroll.ts
664
+ import { getSize } from "@dxos/ui-theme";
665
+ var autoScroll = (_ = {}) => {
611
666
  let buttonContainer;
612
- let hideTimeout;
613
- let lastScrollTop = 0;
614
667
  let isPinned = true;
615
- const setPinned = (pin) => {
616
- isPinned = pin;
617
- buttonContainer?.classList.toggle("opacity-0", pin);
668
+ const setPinned = (pinned) => {
669
+ buttonContainer?.classList.toggle("opacity-0", pinned);
670
+ isPinned = pinned;
618
671
  };
619
- const hideScrollbar = (view) => {
620
- view.scrollDOM.classList.add("cm-hide-scrollbar");
621
- clearTimeout(hideTimeout);
622
- hideTimeout = setTimeout(() => {
623
- view.scrollDOM.classList.remove("cm-hide-scrollbar");
624
- }, 1e3);
625
- };
626
- const scrollToBottom = (view, behavior) => {
627
- setPinned(true);
628
- hideScrollbar(view);
629
- const line = view.state.doc.lineAt(view.state.doc.length);
630
- view.dispatch({
631
- selection: {
632
- anchor: line.to,
633
- head: line.to
634
- },
635
- effects: scrollToLineEffect.of({
636
- line: line.number,
637
- options: {
638
- position: "end",
639
- offset: threshold,
640
- behavior
641
- }
642
- })
643
- });
644
- };
645
- const checkDistance = debounce((view) => {
646
- const scrollerRect = view.scrollDOM.getBoundingClientRect();
647
- const coords = view.coordsAtPos(view.state.doc.length);
648
- const distanceFromBottom = coords ? coords.bottom - scrollerRect.bottom : 0;
649
- setPinned(distanceFromBottom < 0);
650
- }, 1e3);
651
- const triggerUpdate = debounce((view) => scrollToBottom(view), throttleDelay);
652
672
  return [
653
673
  // Update listener for logging when scrolling is needed.
654
- EditorView5.updateListener.of(({ view, transactions, heightChanged }) => {
655
- transactions.forEach((transaction) => {
656
- for (const effect of transaction.effects) {
657
- if (effect.is(scrollToBottomEffect)) {
658
- scrollToBottom(view, effect.value);
674
+ EditorView5.updateListener.of(({ view, heightChanged, state }) => {
675
+ if (heightChanged) {
676
+ if (isPinned) {
677
+ const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
678
+ const delta = scrollHeight - scrollTop - clientHeight;
679
+ if (delta > 0 && scrollTop > 0) {
680
+ setPinned(true);
681
+ view.dispatch({
682
+ effects: scrollerCrawlEffect.of(true)
683
+ });
684
+ } else if (delta < 0) {
685
+ setPinned(false);
659
686
  }
660
- }
661
- });
662
- if (heightChanged && isPinned) {
663
- const coords = view.coordsAtPos(view.state.doc.length);
664
- const scrollerRect = view.scrollDOM.getBoundingClientRect();
665
- const distanceFromBottom = coords ? scrollerRect.bottom - coords.bottom : 0;
666
- if (autoScroll2 && distanceFromBottom < threshold) {
667
- const shouldScroll = onAutoScroll?.({
668
- view,
669
- distanceFromBottom
670
- }) ?? true;
671
- if (shouldScroll) {
672
- triggerUpdate(view);
687
+ } else {
688
+ if (state.doc.length === 0) {
689
+ setPinned(true);
673
690
  }
674
- } else if (distanceFromBottom < 0) {
675
- setPinned(false);
676
691
  }
677
692
  }
678
693
  }),
679
- // Detect user scroll.
680
- EditorView5.domEventHandlers({
681
- scroll: (event, view) => {
682
- const currentScrollTop = view.scrollDOM.scrollTop;
683
- const scrollingUp = currentScrollTop < lastScrollTop;
684
- lastScrollTop = currentScrollTop;
685
- if (scrollingUp) {
686
- setPinned(false);
687
- } else {
688
- checkDistance(view);
689
- }
694
+ // Detect user scroll and unpin (or re-pin if scrolled to the bottom).
695
+ ViewPlugin6.fromClass(class {
696
+ cleanup;
697
+ constructor(view) {
698
+ this.cleanup = createUserScrollDetector(view.scrollDOM, throttle(() => {
699
+ requestAnimationFrame(() => {
700
+ const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
701
+ const delta = scrollHeight - scrollTop - clientHeight;
702
+ const pinned = delta === 0;
703
+ setPinned(pinned);
704
+ if (!pinned) {
705
+ view.dispatch({
706
+ effects: scrollerCrawlEffect.of(false)
707
+ });
708
+ }
709
+ });
710
+ }, 500));
711
+ }
712
+ destroy() {
713
+ this.cleanup();
690
714
  }
691
715
  }),
692
716
  // Scroll button.
693
717
  ViewPlugin6.fromClass(class {
694
718
  constructor(view) {
695
- const icon = Domino.of("dx-icon").attributes({
719
+ const icon = Domino.of("dx-icon").classNames(getSize(4)).attributes({
696
720
  icon: "ph--arrow-down--regular"
697
721
  });
698
- const button = Domino.of("button").classNames("dx-button bg-accentSurface").attributes({
722
+ const button = Domino.of("button").classNames("dx-button bg-accent-surface").attributes({
699
723
  "data-density": "fine"
700
724
  }).children(icon).on("click", () => {
701
- scrollToBottom(view);
725
+ setPinned(true);
726
+ view.dispatch({
727
+ effects: scrollerLineEffect.of({
728
+ line: -1,
729
+ position: "end",
730
+ behavior: "smooth"
731
+ })
732
+ });
702
733
  });
703
734
  buttonContainer = Domino.of("div").classNames("cm-scroll-button transition-opacity duration-300 opacity-0").children(button).root;
704
735
  view.scrollDOM.parentElement.appendChild(buttonContainer);
705
736
  }
706
- }),
707
- // Styles.
708
- EditorView5.theme({
709
- ".cm-scroller": {
710
- scrollbarWidth: "thin"
711
- },
712
- ".cm-scroller.cm-hide-scrollbar": {
713
- scrollbarWidth: "none"
714
- },
715
- ".cm-scroller.cm-hide-scrollbar::-webkit-scrollbar": {
716
- display: "none"
717
- },
718
- ".cm-scroll-button": {
719
- position: "absolute",
720
- bottom: "0.5rem",
721
- right: "1rem"
722
- }
723
737
  })
724
738
  ];
725
739
  };
740
+ function createUserScrollDetector(element, onUserScroll) {
741
+ return combine(addEventListener(element, "wheel", () => onUserScroll(), {
742
+ passive: true
743
+ }), addEventListener(element, "pointerdown", (event) => {
744
+ if (event.clientX > element.getBoundingClientRect().right - (element.offsetWidth - element.clientWidth)) {
745
+ onUserScroll();
746
+ }
747
+ }));
748
+ }
726
749
 
727
750
  // src/extensions/automerge/automerge.ts
728
751
  import { next as A3 } from "@automerge/automerge";
@@ -736,15 +759,15 @@ var initialSync = Transaction.userEvent.of("initial.sync");
736
759
 
737
760
  // src/extensions/automerge/cursor.ts
738
761
  import { fromCursor, toCursor } from "@dxos/echo-db";
739
- import { log as log2 } from "@dxos/log";
740
- var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/automerge/cursor.ts";
762
+ import { log as log3 } from "@dxos/log";
763
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/automerge/cursor.ts";
741
764
  var cursorConverter = (accessor) => ({
742
765
  toCursor: (pos, assoc) => {
743
766
  try {
744
767
  return toCursor(accessor, pos, assoc);
745
768
  } catch (err) {
746
- log2.catch(err, void 0, {
747
- F: __dxlog_file2,
769
+ log3.catch(err, void 0, {
770
+ F: __dxlog_file3,
748
771
  L: 15,
749
772
  S: void 0,
750
773
  C: (f, a) => f(...a)
@@ -756,8 +779,8 @@ var cursorConverter = (accessor) => ({
756
779
  try {
757
780
  return fromCursor(accessor, cursor2);
758
781
  } catch (err) {
759
- log2.catch(err, void 0, {
760
- F: __dxlog_file2,
782
+ log3.catch(err, void 0, {
783
+ F: __dxlog_file3,
761
784
  L: 24,
762
785
  S: void 0,
763
786
  C: (f, a) => f(...a)
@@ -768,10 +791,10 @@ var cursorConverter = (accessor) => ({
768
791
  });
769
792
 
770
793
  // src/extensions/automerge/defs.ts
771
- import { Annotation, StateEffect as StateEffect3 } from "@codemirror/state";
794
+ import { Annotation, StateEffect as StateEffect2 } from "@codemirror/state";
772
795
  var getPath = (state, field) => state.field(field).path;
773
796
  var getLastHeads = (state, field) => state.field(field).lastHeads;
774
- var updateHeadsEffect = StateEffect3.define({});
797
+ var updateHeadsEffect = StateEffect2.define({});
775
798
  var updateHeads = (newHeads) => updateHeadsEffect.of({
776
799
  newHeads
777
800
  });
@@ -782,7 +805,7 @@ var isReconcile = (tr) => {
782
805
 
783
806
  // src/extensions/automerge/sync.ts
784
807
  import { next as A2 } from "@automerge/automerge";
785
- import { log as log3 } from "@dxos/log";
808
+ import { log as log4 } from "@dxos/log";
786
809
 
787
810
  // src/extensions/automerge/update-automerge.ts
788
811
  import { next as A } from "@automerge/automerge";
@@ -923,7 +946,7 @@ var charPath = (textPath, candidatePath) => {
923
946
  };
924
947
 
925
948
  // src/extensions/automerge/sync.ts
926
- var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/automerge/sync.ts";
949
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/automerge/sync.ts";
927
950
  var Syncer = class {
928
951
  _handle;
929
952
  _state;
@@ -946,8 +969,8 @@ var Syncer = class {
946
969
  this._pending = false;
947
970
  }
948
971
  onEditorChange(view) {
949
- log3("onEditorChange", void 0, {
950
- F: __dxlog_file3,
972
+ log4("onEditorChange", void 0, {
973
+ F: __dxlog_file4,
951
974
  L: 45,
952
975
  S: this,
953
976
  C: (f, a) => f(...a)
@@ -962,8 +985,8 @@ var Syncer = class {
962
985
  }
963
986
  }
964
987
  onAutomergeChange(view) {
965
- log3("onAutomergeChange", void 0, {
966
- F: __dxlog_file3,
988
+ log4("onAutomergeChange", void 0, {
989
+ F: __dxlog_file4,
967
990
  L: 60,
968
991
  S: this,
969
992
  C: (f, a) => f(...a)
@@ -1029,6 +1052,15 @@ var automerge = (accessor) => {
1029
1052
  const value = DocAccessor.getValue(accessor);
1030
1053
  const current = this._view.state.doc.toString();
1031
1054
  if (value !== current) {
1055
+ console.warn("ENABLING INITIAL SYNC -- THIS MAY BE A REGRESSION");
1056
+ this._view.dispatch({
1057
+ changes: {
1058
+ from: 0,
1059
+ to: this._view.state.doc.length,
1060
+ insert: value
1061
+ },
1062
+ annotations: initialSync
1063
+ });
1032
1064
  }
1033
1065
  });
1034
1066
  }
@@ -1056,7 +1088,7 @@ import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
1056
1088
  import { Decoration as Decoration5, EditorView as EditorView7, ViewPlugin as ViewPlugin8, WidgetType as WidgetType3 } from "@codemirror/view";
1057
1089
  import { Event } from "@dxos/async";
1058
1090
  import { Context } from "@dxos/context";
1059
- var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/awareness/awareness.ts";
1091
+ var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/awareness/awareness.ts";
1060
1092
  var dummyProvider = {
1061
1093
  remoteStateChange: new Event(),
1062
1094
  open: () => {
@@ -1080,7 +1112,7 @@ var awareness = (provider = dummyProvider) => {
1080
1112
  };
1081
1113
  var RemoteSelectionsDecorator = class {
1082
1114
  _ctx = new Context(void 0, {
1083
- F: __dxlog_file4,
1115
+ F: __dxlog_file5,
1084
1116
  L: 80
1085
1117
  });
1086
1118
  _cursorConverter;
@@ -1293,8 +1325,8 @@ var styles = EditorView7.theme({
1293
1325
  import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
1294
1326
  import { Context as Context2 } from "@dxos/context";
1295
1327
  import { invariant } from "@dxos/invariant";
1296
- import { log as log4 } from "@dxos/log";
1297
- var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/awareness/awareness-provider.ts";
1328
+ import { log as log5 } from "@dxos/log";
1329
+ var __dxlog_file6 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/awareness/awareness-provider.ts";
1298
1330
  var DEBOUNCE_INTERVAL = 100;
1299
1331
  var SpaceAwarenessProvider = class {
1300
1332
  _remoteStates = /* @__PURE__ */ new Map();
@@ -1314,7 +1346,7 @@ var SpaceAwarenessProvider = class {
1314
1346
  }
1315
1347
  open() {
1316
1348
  this._ctx = new Context2(void 0, {
1317
- F: __dxlog_file5,
1349
+ F: __dxlog_file6,
1318
1350
  L: 57
1319
1351
  });
1320
1352
  this._postTask = new DeferredTask(this._ctx, async () => {
@@ -1341,10 +1373,10 @@ var SpaceAwarenessProvider = class {
1341
1373
  void this._messenger.postMessage(this._channel, {
1342
1374
  kind: "query"
1343
1375
  }).catch((err) => {
1344
- log4.debug("failed to query awareness", {
1376
+ log5.debug("failed to query awareness", {
1345
1377
  err
1346
1378
  }, {
1347
- F: __dxlog_file5,
1379
+ F: __dxlog_file6,
1348
1380
  L: 91,
1349
1381
  S: this,
1350
1382
  C: (f, a) => f(...a)
@@ -1361,7 +1393,7 @@ var SpaceAwarenessProvider = class {
1361
1393
  }
1362
1394
  update(position) {
1363
1395
  invariant(this._postTask, void 0, {
1364
- F: __dxlog_file5,
1396
+ F: __dxlog_file6,
1365
1397
  L: 106,
1366
1398
  S: this,
1367
1399
  A: [
@@ -1378,7 +1410,7 @@ var SpaceAwarenessProvider = class {
1378
1410
  }
1379
1411
  _handleQueryMessage() {
1380
1412
  invariant(this._postTask, void 0, {
1381
- F: __dxlog_file5,
1413
+ F: __dxlog_file6,
1382
1414
  L: 117,
1383
1415
  S: this,
1384
1416
  A: [
@@ -1390,7 +1422,7 @@ var SpaceAwarenessProvider = class {
1390
1422
  }
1391
1423
  _handlePostMessage(message) {
1392
1424
  invariant(message.kind === "post", void 0, {
1393
- F: __dxlog_file5,
1425
+ F: __dxlog_file6,
1394
1426
  L: 122,
1395
1427
  S: this,
1396
1428
  A: [
@@ -1406,9 +1438,9 @@ var SpaceAwarenessProvider = class {
1406
1438
  // src/extensions/blast.ts
1407
1439
  import { EditorView as EditorView8, keymap as keymap3 } from "@codemirror/view";
1408
1440
  import defaultsDeep from "lodash.defaultsdeep";
1409
- import { throttle } from "@dxos/async";
1441
+ import { throttle as throttle2 } from "@dxos/async";
1410
1442
  import { invariant as invariant2 } from "@dxos/invariant";
1411
- var __dxlog_file6 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/blast.ts";
1443
+ var __dxlog_file7 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/blast.ts";
1412
1444
  var defaultOptions = {
1413
1445
  effect: 2,
1414
1446
  maxParticles: 200,
@@ -1527,7 +1559,7 @@ var Blaster = class {
1527
1559
  }
1528
1560
  initialize() {
1529
1561
  invariant2(!this._canvas && !this._ctx, void 0, {
1530
- F: __dxlog_file6,
1562
+ F: __dxlog_file7,
1531
1563
  L: 142,
1532
1564
  S: this,
1533
1565
  A: [
@@ -1564,7 +1596,7 @@ var Blaster = class {
1564
1596
  }
1565
1597
  start() {
1566
1598
  invariant2(this._canvas && this._ctx, void 0, {
1567
- F: __dxlog_file6,
1599
+ F: __dxlog_file7,
1568
1600
  L: 181,
1569
1601
  S: this,
1570
1602
  A: [
@@ -1598,11 +1630,11 @@ var Blaster = class {
1598
1630
  this.drawParticles();
1599
1631
  requestAnimationFrame(this.loop.bind(this));
1600
1632
  }
1601
- shake = throttle(({ time }) => {
1633
+ shake = throttle2(({ time }) => {
1602
1634
  this._shakeTime = this._shakeTimeMax || time;
1603
1635
  this._shakeTimeMax = time;
1604
1636
  }, 100);
1605
- spawn = throttle(({ element, point }) => {
1637
+ spawn = throttle2(({ element, point }) => {
1606
1638
  const color = getRGBComponents(element, this._options.color);
1607
1639
  const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
1608
1640
  const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
@@ -1776,11 +1808,11 @@ var blocks = () => [
1776
1808
  ".cm-line.block-line": {
1777
1809
  paddingLeft: "0.75rem",
1778
1810
  paddingRight: "0.75rem",
1779
- borderLeft: "1px solid var(--dx-subduedSeparator)",
1780
- borderRight: "1px solid var(--dx-subduedSeparator)"
1811
+ borderLeft: "1px solid var(--color-subdued-separator)",
1812
+ borderRight: "1px solid var(--color-subdued-separator)"
1781
1813
  },
1782
1814
  ".cm-line.block-single": {
1783
- border: "1px solid var(--dx-subduedSeparator)",
1815
+ border: "1px solid var(--color-subdued-separator)",
1784
1816
  borderRadius: "6px",
1785
1817
  paddingTop: "0.5rem",
1786
1818
  paddingBottom: "0.5rem",
@@ -1788,7 +1820,7 @@ var blocks = () => [
1788
1820
  marginBottom: "0.5rem"
1789
1821
  },
1790
1822
  ".cm-line.block-first": {
1791
- borderTop: "1px solid var(--dx-subduedSeparator)",
1823
+ borderTop: "1px solid var(--color-subdued-separator)",
1792
1824
  borderTopLeftRadius: "6px",
1793
1825
  borderTopRightRadius: "6px",
1794
1826
  paddingTop: "0.5rem",
@@ -1796,7 +1828,7 @@ var blocks = () => [
1796
1828
  },
1797
1829
  ".cm-line.block-middle": {},
1798
1830
  ".cm-line.block-last": {
1799
- borderBottom: "1px solid var(--dx-subduedSeparator)",
1831
+ borderBottom: "1px solid var(--color-subdued-separator)",
1800
1832
  borderBottomLeftRadius: "6px",
1801
1833
  borderBottomRightRadius: "6px",
1802
1834
  paddingBottom: "0.5rem",
@@ -1806,13 +1838,13 @@ var blocks = () => [
1806
1838
  ];
1807
1839
 
1808
1840
  // src/extensions/bookmarks.ts
1809
- import { Prec as Prec3, StateEffect as StateEffect4, StateField as StateField2 } from "@codemirror/state";
1841
+ import { Prec as Prec3, StateEffect as StateEffect3, StateField as StateField2 } from "@codemirror/state";
1810
1842
  import { keymap as keymap4 } from "@codemirror/view";
1811
- import { log as log5 } from "@dxos/log";
1812
- var __dxlog_file7 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/bookmarks.ts";
1813
- var addBookmark = StateEffect4.define();
1814
- var removeBookmark = StateEffect4.define();
1815
- var clearBookmarks = StateEffect4.define();
1843
+ import { log as log6 } from "@dxos/log";
1844
+ var __dxlog_file8 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/bookmarks.ts";
1845
+ var addBookmark = StateEffect3.define();
1846
+ var removeBookmark = StateEffect3.define();
1847
+ var clearBookmarks = StateEffect3.define();
1816
1848
  var bookmarks = () => {
1817
1849
  return [
1818
1850
  bookmarksField,
@@ -1821,8 +1853,8 @@ var bookmarks = () => {
1821
1853
  key: "Mod-ArrowUp",
1822
1854
  run: (view) => {
1823
1855
  const bookmarks2 = view.state.field(bookmarksField);
1824
- log5("up", bookmarks2, {
1825
- F: __dxlog_file7,
1856
+ log6("up", bookmarks2, {
1857
+ F: __dxlog_file8,
1826
1858
  L: 29,
1827
1859
  S: void 0,
1828
1860
  C: (f, a) => f(...a)
@@ -1834,8 +1866,8 @@ var bookmarks = () => {
1834
1866
  key: "Mod-ArrowDown",
1835
1867
  run: (view) => {
1836
1868
  const bookmarks2 = view.state.field(bookmarksField);
1837
- log5("down", bookmarks2, {
1838
- F: __dxlog_file7,
1869
+ log6("down", bookmarks2, {
1870
+ F: __dxlog_file8,
1839
1871
  L: 37,
1840
1872
  S: void 0,
1841
1873
  C: (f, a) => f(...a)
@@ -1876,22 +1908,22 @@ var bookmarksField = StateField2.define({
1876
1908
 
1877
1909
  // src/extensions/comments.ts
1878
1910
  import { invertedEffects } from "@codemirror/commands";
1879
- import { StateEffect as StateEffect5, StateField as StateField3 } from "@codemirror/state";
1911
+ import { StateEffect as StateEffect4, StateField as StateField3 } from "@codemirror/state";
1880
1912
  import { Decoration as Decoration7, EditorView as EditorView11, ViewPlugin as ViewPlugin10, hoverTooltip, keymap as keymap6 } from "@codemirror/view";
1881
1913
  import sortBy from "lodash.sortby";
1882
- import { debounce as debounce3 } from "@dxos/async";
1883
- import { log as log6 } from "@dxos/log";
1914
+ import { debounce as debounce2 } from "@dxos/async";
1915
+ import { log as log7 } from "@dxos/log";
1884
1916
  import { isNonNullable } from "@dxos/util";
1885
1917
 
1886
1918
  // src/extensions/selection.ts
1887
1919
  import { Transaction as Transaction3 } from "@codemirror/state";
1888
1920
  import { EditorView as EditorView10, keymap as keymap5 } from "@codemirror/view";
1889
- import { debounce as debounce2 } from "@dxos/async";
1921
+ import { debounce } from "@dxos/async";
1890
1922
  import { invariant as invariant3 } from "@dxos/invariant";
1891
1923
  import { isTruthy } from "@dxos/util";
1892
- var __dxlog_file8 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/selection.ts";
1924
+ var __dxlog_file9 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/selection.ts";
1893
1925
  var documentId = singleValueFacet();
1894
- var stateRestoreAnnotation = "dxos.org/cm/state-restore";
1926
+ var stateRestoreAnnotation = "org.dxos.cm.state-restore";
1895
1927
  var createEditorStateTransaction = ({ scrollTo, selection }) => {
1896
1928
  return {
1897
1929
  selection,
@@ -1905,7 +1937,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
1905
1937
  var createEditorStateStore = (keyPrefix) => ({
1906
1938
  getState: (id) => {
1907
1939
  invariant3(id, void 0, {
1908
- F: __dxlog_file8,
1940
+ F: __dxlog_file9,
1909
1941
  L: 47,
1910
1942
  S: void 0,
1911
1943
  A: [
@@ -1918,7 +1950,7 @@ var createEditorStateStore = (keyPrefix) => ({
1918
1950
  },
1919
1951
  setState: (id, state) => {
1920
1952
  invariant3(id, void 0, {
1921
- F: __dxlog_file8,
1953
+ F: __dxlog_file9,
1922
1954
  L: 53,
1923
1955
  S: void 0,
1924
1956
  A: [
@@ -1930,7 +1962,7 @@ var createEditorStateStore = (keyPrefix) => ({
1930
1962
  }
1931
1963
  });
1932
1964
  var selectionState = ({ getState, setState } = {}) => {
1933
- const setStateDebounced = debounce2(setState, 1e3);
1965
+ const setStateDebounced = debounce(setState, 1e3);
1934
1966
  return [
1935
1967
  // TODO(burdon): Track scrolling (currently only updates when cursor moves).
1936
1968
  // EditorView.domEventHandlers({
@@ -1977,10 +2009,10 @@ var selectionState = ({ getState, setState } = {}) => {
1977
2009
  };
1978
2010
 
1979
2011
  // src/extensions/comments.ts
1980
- var __dxlog_file9 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/comments.ts";
1981
- var setComments = StateEffect5.define();
1982
- var setSelection = StateEffect5.define();
1983
- var setCommentState = StateEffect5.define();
2012
+ var __dxlog_file10 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/comments.ts";
2013
+ var setComments = StateEffect4.define();
2014
+ var setSelection = StateEffect4.define();
2015
+ var setCommentState = StateEffect4.define();
1984
2016
  var commentsState = StateField3.define({
1985
2017
  create: (state) => ({
1986
2018
  id: state.facet(documentId),
@@ -2022,14 +2054,14 @@ var commentsState = StateField3.define({
2022
2054
  var styles2 = EditorView11.theme({
2023
2055
  ".cm-comment, .cm-comment-current": {
2024
2056
  padding: "3px 0",
2025
- color: "var(--dx-cmCommentText)",
2026
- backgroundColor: "var(--dx-cmCommentSurface)"
2057
+ color: "var(--color-cm-comment-text)",
2058
+ backgroundColor: "var(--color-cm-comment-surface)"
2027
2059
  },
2028
2060
  ".cm-comment > span, .cm-comment-current > span": {
2029
2061
  boxDecorationBreak: "clone",
2030
- boxShadow: "0 0 1px 3px var(--dx-cmCommentSurface)",
2031
- backgroundColor: "var(--dx-cmCommentSurface)",
2032
- color: "var(--dx-cmCommentText)",
2062
+ boxShadow: "0 0 1px 3px var(--color-cm-comment-surface)",
2063
+ backgroundColor: "var(--color-cm-comment-surface)",
2064
+ color: "var(--color-cm-comment-text)",
2033
2065
  cursor: "pointer"
2034
2066
  }
2035
2067
  });
@@ -2047,8 +2079,8 @@ var commentsDecorations = EditorView11.decorations.compute([
2047
2079
  const decorations2 = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
2048
2080
  const range = comment.range;
2049
2081
  if (!range) {
2050
- log6.warn("Invalid range:", range, {
2051
- F: __dxlog_file9,
2082
+ log7.warn("Invalid range:", range, {
2083
+ F: __dxlog_file10,
2052
2084
  L: 140,
2053
2085
  S: void 0,
2054
2086
  C: (f, a) => f(...a)
@@ -2062,7 +2094,7 @@ var commentsDecorations = EditorView11.decorations.compute([
2062
2094
  }).filter(isNonNullable);
2063
2095
  return Decoration7.set(decorations2);
2064
2096
  });
2065
- var commentClickedEffect = StateEffect5.define();
2097
+ var commentClickedEffect = StateEffect4.define();
2066
2098
  var handleCommentClick = EditorView11.domEventHandlers({
2067
2099
  click: (event, view) => {
2068
2100
  let target = event.target;
@@ -2180,7 +2212,7 @@ var mapTrackedComment = (comment, changes) => ({
2180
2212
  from: changes.mapPos(comment.from, 1),
2181
2213
  to: changes.mapPos(comment.to, 1)
2182
2214
  });
2183
- var restoreCommentEffect = StateEffect5.define({
2215
+ var restoreCommentEffect = StateEffect4.define({
2184
2216
  map: mapTrackedComment
2185
2217
  });
2186
2218
  var createComment = (view) => {
@@ -2214,7 +2246,7 @@ var createComment = (view) => {
2214
2246
  var optionsFacet = singleValueFacet();
2215
2247
  var comments = (options = {}) => {
2216
2248
  const { key: shortcut = "meta-'" } = options;
2217
- const handleSelect = debounce3((state) => options.onSelect?.(state), 200);
2249
+ const handleSelect = debounce2((state) => options.onSelect?.(state), 200);
2218
2250
  return [
2219
2251
  optionsFacet.of(options),
2220
2252
  options.id ? documentId.of(options.id) : void 0,
@@ -2392,9 +2424,9 @@ var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin10.fro
2392
2424
  // src/extensions/debug.ts
2393
2425
  import { syntaxTree } from "@codemirror/language";
2394
2426
  import { StateField as StateField4 } from "@codemirror/state";
2395
- var debugNodeLogger = (log11 = console.log) => {
2427
+ var debugNodeLogger = (log12 = console.log) => {
2396
2428
  const logTokens = (state) => syntaxTree(state).iterate({
2397
- enter: (node) => log11(node.type)
2429
+ enter: (node) => log12(node.type)
2398
2430
  });
2399
2431
  return StateField4.define({
2400
2432
  create: (state) => logTokens(state),
@@ -2429,8 +2461,8 @@ var dropFile = (options = {}) => {
2429
2461
  };
2430
2462
  var styles3 = EditorView12.theme({
2431
2463
  ".cm-dropCursor": {
2432
- borderLeft: "2px solid var(--dx-accentText)",
2433
- color: "var(--dx-accentText)",
2464
+ borderLeft: "2px solid var(--color-accent-text)",
2465
+ color: "var(--color-accent-text)",
2434
2466
  padding: "0 4px"
2435
2467
  },
2436
2468
  ".cm-dropCursor:after": {
@@ -2448,43 +2480,62 @@ import { EditorView as EditorView15, ViewPlugin as ViewPlugin11, drawSelection,
2448
2480
  import { vscodeDarkStyle, vscodeLightStyle } from "@uiw/codemirror-theme-vscode";
2449
2481
  import defaultsDeep2 from "lodash.defaultsdeep";
2450
2482
  import { generateName } from "@dxos/display-name";
2451
- import { log as log7 } from "@dxos/log";
2483
+ import { log as log8 } from "@dxos/log";
2452
2484
  import { hexToHue, isTruthy as isTruthy2 } from "@dxos/util";
2453
2485
 
2454
- // src/styles/markdown.ts
2486
+ // src/styles/theme.ts
2487
+ import { EditorView as EditorView13 } from "@codemirror/view";
2455
2488
  import { mx as mx3 } from "@dxos/ui-theme";
2456
2489
  var headings = {
2457
- 1: "text-4xl",
2458
- 2: "text-3xl",
2459
- 3: "text-2xl",
2460
- 4: "text-xl",
2461
- 5: "text-lg",
2462
- 6: ""
2490
+ 1: {
2491
+ className: "text-3xl",
2492
+ fontSize: "var(--text-3xl)",
2493
+ lineHeight: "var(--text-4xl--line-height)"
2494
+ },
2495
+ 2: {
2496
+ className: "text-2xl",
2497
+ fontSize: "var(--text-2xl)",
2498
+ lineHeight: "var(--text-3xl--line-height)"
2499
+ },
2500
+ 3: {
2501
+ className: "text-xl",
2502
+ fontSize: "var(--text-xl)",
2503
+ lineHeight: "var(--text-2xl--line-height)"
2504
+ },
2505
+ 4: {
2506
+ className: "text-lg",
2507
+ fontSize: "var(--text-lg)",
2508
+ lineHeight: "var(--text-xl--line-height)"
2509
+ },
2510
+ 5: {
2511
+ className: "text-base",
2512
+ fontSize: "var(--text-base)",
2513
+ lineHeight: "var(--text-lg--line-height)"
2514
+ },
2515
+ 6: {
2516
+ className: "text-base",
2517
+ fontSize: "var(--text-base)",
2518
+ lineHeight: "var(--text-base--line-height)"
2519
+ }
2463
2520
  };
2521
+ var fontBody = '"Inter Variable", ui-sans-serif, system-ui, sans-serif';
2522
+ var fontMono = '"JetBrains Mono Variable", ui-monospace, "Cascadia Code", "Source Code Pro", monospace';
2464
2523
  var markdownTheme = {
2465
- code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
2466
- codeMark: "font-mono text-primary-500",
2467
- mark: "opacity-50",
2468
- heading: (level) => {
2469
- return mx3(headings[level], "dark:text-neutral-400");
2470
- }
2524
+ code: "font-mono! text-cm-code",
2525
+ codeMark: "font-mono! text-cm-code-mark",
2526
+ mark: "font-mono!",
2527
+ heading: (level) => ({
2528
+ className: mx3(headings[level].className, "font-light text-cm-heading-number"),
2529
+ color: "var(--color-cm-heading) !important",
2530
+ lineHeight: headings[level].lineHeight,
2531
+ fontSize: headings[level].fontSize,
2532
+ fontWeight: "100 !important"
2533
+ })
2471
2534
  };
2472
-
2473
- // src/styles/theme.ts
2474
- import { EditorView as EditorView13 } from "@codemirror/view";
2475
-
2476
- // src/styles/tokens.ts
2477
- import { tokens } from "@dxos/ui-theme";
2478
- import { get } from "@dxos/util";
2479
- var getToken = (path, defaultValue) => {
2480
- const value = get(tokens, path, defaultValue);
2481
- return value?.toString() ?? "";
2482
- };
2483
- var fontBody = getToken("fontFamily.body");
2484
- var fontMono = getToken("fontFamily.mono");
2485
-
2486
- // src/styles/theme.ts
2487
2535
  var baseTheme = EditorView13.baseTheme({
2536
+ /**
2537
+ * Outer frame.
2538
+ */
2488
2539
  "&": {},
2489
2540
  "&.cm-focused": {
2490
2541
  outline: "none"
@@ -2493,7 +2544,18 @@ var baseTheme = EditorView13.baseTheme({
2493
2544
  * Scroller
2494
2545
  */
2495
2546
  ".cm-scroller": {
2496
- overflowY: "auto"
2547
+ overflowAnchor: "none"
2548
+ },
2549
+ ".cm-scroller::-webkit-scrollbar": {
2550
+ width: "8px"
2551
+ },
2552
+ ".cm-scroller::-webkit-scrollbar-track": {},
2553
+ ".cm-scroller::-webkit-scrollbar-thumb": {
2554
+ background: "transparent",
2555
+ transition: "background 0.15s"
2556
+ },
2557
+ "&:hover .cm-scroller::-webkit-scrollbar-thumb": {
2558
+ background: "var(--color-scrollbar-thumb)"
2497
2559
  },
2498
2560
  /**
2499
2561
  * Content
@@ -2501,7 +2563,6 @@ var baseTheme = EditorView13.baseTheme({
2501
2563
  */
2502
2564
  ".cm-content": {
2503
2565
  padding: "unset",
2504
- lineHeight: "24px",
2505
2566
  color: "unset"
2506
2567
  },
2507
2568
  /**
@@ -2515,8 +2576,8 @@ var baseTheme = EditorView13.baseTheme({
2515
2576
  ".cm-gutter": {},
2516
2577
  ".cm-gutter.cm-lineNumbers": {
2517
2578
  paddingRight: "4px",
2518
- borderRight: "1px solid var(--dx-subduedSeparator)",
2519
- color: "var(--dx-subduedText)"
2579
+ borderRight: "1px solid var(--color-subdued-separator)",
2580
+ color: "var(--color-subdued)"
2520
2581
  },
2521
2582
  ".cm-gutter.cm-lineNumbers .cm-gutterElement": {
2522
2583
  minWidth: "40px"
@@ -2525,36 +2586,43 @@ var baseTheme = EditorView13.baseTheme({
2525
2586
  * Height is set to match the corresponding line (which may have wrapped).
2526
2587
  */
2527
2588
  ".cm-gutterElement": {
2528
- lineHeight: "24px",
2589
+ lineHeight: 1.5,
2529
2590
  fontSize: "12px"
2530
2591
  },
2531
2592
  /**
2532
2593
  * Line.
2533
2594
  */
2534
2595
  ".cm-line": {
2535
- lineHeight: "24px",
2596
+ lineHeight: 1.5,
2536
2597
  paddingInline: 0
2537
2598
  },
2599
+ /**
2600
+ * Force all inline children to inherit line-height to prevent monospace font metrics
2601
+ * (JetBrains Mono ascent/descent) from inflating the line box beyond 24px.
2602
+ */
2603
+ ".cm-line *": {
2604
+ lineHeight: "inherit"
2605
+ },
2538
2606
  ".cm-activeLine": {
2539
- background: "var(--dx-cmActiveLine)"
2607
+ background: "var(--color-cm-active-line)"
2540
2608
  },
2541
2609
  /**
2542
2610
  * Cursor (layer).
2543
2611
  */
2544
2612
  ".cm-cursor, .cm-dropCursor": {
2545
- borderLeft: "2px solid var(--dx-cmCursor)"
2613
+ borderLeft: "2px solid var(--color-cm-cursor)"
2546
2614
  },
2547
2615
  ".cm-placeholder": {
2548
- color: "var(--dx-placeholder)"
2616
+ color: "var(--color-placeholder)"
2549
2617
  },
2550
2618
  /**
2551
2619
  * Selection (layer).
2552
2620
  */
2553
2621
  ".cm-selectionBackground": {
2554
- background: "var(--dx-cmSelection)"
2622
+ background: "var(--color-cm-selection)"
2555
2623
  },
2556
2624
  "&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
2557
- background: "var(--dx-cmFocusedSelection)"
2625
+ background: "var(--color-cm-focused-selection)"
2558
2626
  },
2559
2627
  /**
2560
2628
  * Search.
@@ -2564,8 +2632,8 @@ var baseTheme = EditorView13.baseTheme({
2564
2632
  margin: "0 -3px",
2565
2633
  padding: "3px",
2566
2634
  borderRadius: "3px",
2567
- background: "var(--dx-cmHighlightSurface)",
2568
- color: "var(--dx-cmHighlight)"
2635
+ background: "var(--color-cm-highlight-surface)",
2636
+ color: "var(--color-cm-highlight)"
2569
2637
  },
2570
2638
  ".cm-searchMatch-selected": {
2571
2639
  textDecoration: "underline"
@@ -2576,20 +2644,29 @@ var baseTheme = EditorView13.baseTheme({
2576
2644
  ".cm-link": {
2577
2645
  textDecorationLine: "underline",
2578
2646
  textDecorationThickness: "1px",
2579
- textDecorationColor: "var(--dx-separator)",
2647
+ textDecorationColor: "var(--color-separator)",
2580
2648
  textUnderlineOffset: "2px",
2581
2649
  borderRadius: ".125rem"
2582
2650
  },
2583
2651
  ".cm-link > span": {
2584
- color: "var(--dx-accentText)"
2652
+ color: "var(--color-accent-text)"
2653
+ },
2654
+ ".cm-link > span:hover": {
2655
+ color: "var(--color-accent-text-hover)"
2585
2656
  },
2586
2657
  /**
2587
2658
  * Tooltip.
2588
2659
  */
2589
2660
  ".cm-tooltip": {
2590
- background: "var(--dx-baseSurface)"
2661
+ background: "var(--color-modal-surface)"
2591
2662
  },
2592
2663
  ".cm-tooltip-below": {},
2664
+ ".cm-tooltip-hover": {
2665
+ background: "var(--color-modal-surface)",
2666
+ border: "1px solid var(--color-separator)",
2667
+ borderRadius: "4px",
2668
+ overflow: "hidden"
2669
+ },
2593
2670
  /**
2594
2671
  * Autocomplete.
2595
2672
  * https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
@@ -2597,7 +2674,7 @@ var baseTheme = EditorView13.baseTheme({
2597
2674
  ".cm-tooltip.cm-tooltip-autocomplete": {
2598
2675
  marginTop: "6px",
2599
2676
  marginLeft: "-10px",
2600
- border: "2px solid var(--dx-separator)",
2677
+ border: "2px solid var(--color-separator)",
2601
2678
  borderRadius: "4px"
2602
2679
  },
2603
2680
  ".cm-tooltip.cm-tooltip-autocomplete > ul": {
@@ -2607,12 +2684,12 @@ var baseTheme = EditorView13.baseTheme({
2607
2684
  padding: "4px"
2608
2685
  },
2609
2686
  ".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {
2610
- background: "var(--dx-activeSurface)",
2611
- color: "var(--dx-activeSurfaceText)"
2687
+ background: "var(--color-active-surface)",
2688
+ color: "var(--color-base-surface-text)"
2612
2689
  },
2613
2690
  ".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
2614
2691
  paddingLeft: "4px !important",
2615
- color: "var(--dx-hoverSurfaceText)"
2692
+ color: "var(--color-base-surface-text)"
2616
2693
  },
2617
2694
  /**
2618
2695
  * Completion info.
@@ -2621,17 +2698,17 @@ var baseTheme = EditorView13.baseTheme({
2621
2698
  width: "360px !important",
2622
2699
  margin: "-10px 1px 0 1px",
2623
2700
  padding: "8px !important",
2624
- borderColor: "var(--dx-separator)"
2701
+ borderColor: "var(--color-separator)"
2625
2702
  },
2626
2703
  ".cm-completionIcon": {
2627
2704
  display: "none"
2628
2705
  },
2629
2706
  ".cm-completionLabel": {
2630
- color: "var(--dx-description)",
2707
+ color: "var(--color-description)",
2631
2708
  padding: "0 4px"
2632
2709
  },
2633
2710
  ".cm-completionMatchedText": {
2634
- color: "var(--dx-baseText)",
2711
+ color: "var(--color-base-surface-text)",
2635
2712
  textDecoration: "none !important"
2636
2713
  },
2637
2714
  /**
@@ -2655,7 +2732,7 @@ var baseTheme = EditorView13.baseTheme({
2655
2732
  backgroundColor: "var(--surface-bg)"
2656
2733
  },
2657
2734
  ".cm-panel input, .cm-panel button, .cm-panel label": {
2658
- color: "var(--dx-subdued)",
2735
+ color: "var(--color-subdued)",
2659
2736
  fontSize: "14px",
2660
2737
  all: "unset",
2661
2738
  margin: "3px !important",
@@ -2663,10 +2740,10 @@ var baseTheme = EditorView13.baseTheme({
2663
2740
  outline: "1px solid transparent"
2664
2741
  },
2665
2742
  ".cm-panel input, .cm-panel button": {
2666
- backgroundColor: "var(--dx-inputSurface)"
2743
+ backgroundColor: "var(--color-input-surface)"
2667
2744
  },
2668
2745
  ".cm-panel input:focus, .cm-panel button:focus": {
2669
- outline: "1px solid var(--dx-neutralFocusIndicator)"
2746
+ outline: "1px solid var(--color-neutral-focus-indicator)"
2670
2747
  },
2671
2748
  ".cm-panel label": {
2672
2749
  display: "inline-flex",
@@ -2679,33 +2756,33 @@ var baseTheme = EditorView13.baseTheme({
2679
2756
  height: "8px",
2680
2757
  marginRight: "6px !important",
2681
2758
  padding: "2px !important",
2682
- color: "var(--dx-neutralFocusIndicator)"
2759
+ color: "var(--color-neutral-focus-indicator)"
2683
2760
  },
2684
2761
  ".cm-panel button": {
2685
2762
  "&:hover": {
2686
- backgroundColor: "var(--dx-accentSurfaceHover) !important"
2763
+ // TODO(burdon): Replace with layer and @apply bg-accent-surface-hover
2764
+ backgroundColor: "var(--color-accent-surface-hover) !important"
2687
2765
  },
2688
2766
  "&:active": {
2689
- backgroundColor: "var(--dx-accentSurfaceHover)"
2767
+ backgroundColor: "var(--color-accent-surface-hover)"
2690
2768
  }
2691
2769
  },
2692
2770
  ".cm-panel.cm-search": {
2693
2771
  padding: "4px",
2694
- borderTop: "1px solid var(--dx-separator)"
2772
+ borderTop: "1px solid var(--color-separator)"
2695
2773
  }
2696
2774
  });
2697
2775
  var editorGutter = EditorView13.theme({
2698
2776
  ".cm-gutters": {
2699
2777
  // NOTE: Non-transparent background required to cover content if scrolling horizontally.
2700
- background: "var(--dx-baseSurface) !important",
2778
+ background: "var(--color-base-surface) !important",
2701
2779
  paddingRight: "1rem"
2702
2780
  }
2703
2781
  });
2704
2782
  var createFontTheme = ({ monospace } = {}) => EditorView13.theme({
2705
- // Set metrics on the scroller (this is often what CM uses for layout).
2783
+ // Main content.
2706
2784
  ".cm-scroller": {
2707
- fontFamily: monospace ? fontMono : fontBody,
2708
- fontSize: "16px"
2785
+ fontFamily: monospace ? fontMono : fontBody
2709
2786
  },
2710
2787
  // Maintain defaults for UI components.
2711
2788
  ".cm-content, .cm-gutters, .cm-panel": {
@@ -2715,9 +2792,9 @@ var createFontTheme = ({ monospace } = {}) => EditorView13.theme({
2715
2792
  });
2716
2793
 
2717
2794
  // src/extensions/focus.ts
2718
- import { StateEffect as StateEffect6, StateField as StateField5 } from "@codemirror/state";
2795
+ import { StateEffect as StateEffect5, StateField as StateField5 } from "@codemirror/state";
2719
2796
  import { EditorView as EditorView14 } from "@codemirror/view";
2720
- var focusEffect = StateEffect6.define();
2797
+ var focusEffect = StateEffect5.define();
2721
2798
  var focusField = StateField5.define({
2722
2799
  create: () => false,
2723
2800
  update: (value, tr) => {
@@ -2746,7 +2823,7 @@ var focus = [
2746
2823
  ];
2747
2824
 
2748
2825
  // src/extensions/factories.ts
2749
- var __dxlog_file10 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/factories.ts";
2826
+ var __dxlog_file11 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/factories.ts";
2750
2827
  var tabbable = EditorView15.contentAttributes.of({
2751
2828
  tabindex: "0"
2752
2829
  });
@@ -2801,9 +2878,9 @@ var createBasicExtensions = (propsProp) => {
2801
2878
  return [
2802
2879
  // NOTE: Doesn't catch errors in keymap functions.
2803
2880
  EditorView15.exceptionSink.of((err) => {
2804
- log7.catch(err, void 0, {
2805
- F: __dxlog_file10,
2806
- L: 132,
2881
+ log8.catch(err, void 0, {
2882
+ F: __dxlog_file11,
2883
+ L: 131,
2807
2884
  S: void 0,
2808
2885
  C: (f, a) => f(...a)
2809
2886
  });
@@ -2855,12 +2932,12 @@ var createBasicExtensions = (propsProp) => {
2855
2932
  };
2856
2933
  var grow = {
2857
2934
  editor: {
2858
- className: "bs-full is-full"
2935
+ className: "h-full w-full"
2859
2936
  }
2860
2937
  };
2861
2938
  var fullWidth = {
2862
2939
  editor: {
2863
- className: "is-full"
2940
+ className: "w-full"
2864
2941
  }
2865
2942
  };
2866
2943
  var defaultThemeSlots = grow;
@@ -2903,8 +2980,8 @@ var createDataExtensions = ({ id, text, messenger, identity }) => {
2903
2980
  channel: `awareness.${id}`,
2904
2981
  peerId: identity.identityKey.toHex(),
2905
2982
  info: {
2906
- darkColor: `var(--dx-${hue}Cursor)`,
2907
- lightColor: `var(--dx-${hue}Cursor)`,
2983
+ darkColor: `var(--color-${hue}-border)`,
2984
+ lightColor: `var(--color-${hue}-border)`,
2908
2985
  displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex())
2909
2986
  }
2910
2987
  })));
@@ -2922,8 +2999,9 @@ var folding = () => {
2922
2999
  placeholderDOM: () => Domino2.of("span").root
2923
3000
  }),
2924
3001
  foldGutter({
3002
+ // NOTE: We can't animate since the element is remounted on state change.
2925
3003
  markerDOM: (open) => {
2926
- return Domino2.of("div").classNames("flex bs-full justify-center items-center").children(Domino2.of("svg", Domino2.SVG).classNames(mx4("is-4 bs-4 cursor-pointer", open && "rotate-90")).children(Domino2.of("use", Domino2.SVG).attributes({
3004
+ return Domino2.of("div").classNames("flex h-full justify-center items-center").children(Domino2.of("svg", Domino2.SVG).classNames(mx4("w-4 h-4 cursor-pointer", open && "rotate-90")).children(Domino2.of("use", Domino2.SVG).attributes({
2927
3005
  href: Domino2.icon("ph--caret-right--regular")
2928
3006
  }))).root;
2929
3007
  }
@@ -4208,8 +4286,7 @@ import { completionKeymap } from "@codemirror/autocomplete";
4208
4286
  import { defaultKeymap as defaultKeymap2, indentWithTab as indentWithTab2 } from "@codemirror/commands";
4209
4287
  import { jsonLanguage } from "@codemirror/lang-json";
4210
4288
  import { markdown, markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
4211
- import { xml } from "@codemirror/lang-xml";
4212
- import { LanguageDescription, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
4289
+ import { foldNodeProp, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
4213
4290
  import { languages } from "@codemirror/language-data";
4214
4291
  import { keymap as keymap9 } from "@codemirror/view";
4215
4292
  import { isTruthy as isTruthy3 } from "@dxos/util";
@@ -4330,30 +4407,38 @@ var markdownHighlightStyle = (_options = {}) => {
4330
4407
  ],
4331
4408
  class: "font-mono"
4332
4409
  },
4333
- // Headings.
4410
+ // Headings — use CSS properties only (no class:) so CodeMirror generates scoped CSS via
4411
+ // StyleModule that overrides vscodeDarkStyle's t.heading rule. When class: is present,
4412
+ // HighlightStyle silently ignores all other CSS properties (they're mutually exclusive).
4413
+ // Font sizes use Tailwind v4 CSS variables so nothing is hardcoded.
4414
+ {
4415
+ tag: tags.heading,
4416
+ color: "var(--color-cm-heading) !important",
4417
+ fontWeight: "300"
4418
+ },
4334
4419
  {
4335
4420
  tag: tags.heading1,
4336
- class: markdownTheme.heading(1)
4421
+ ...markdownTheme.heading(1)
4337
4422
  },
4338
4423
  {
4339
4424
  tag: tags.heading2,
4340
- class: markdownTheme.heading(2)
4425
+ ...markdownTheme.heading(2)
4341
4426
  },
4342
4427
  {
4343
4428
  tag: tags.heading3,
4344
- class: markdownTheme.heading(3)
4429
+ ...markdownTheme.heading(3)
4345
4430
  },
4346
4431
  {
4347
4432
  tag: tags.heading4,
4348
- class: markdownTheme.heading(4)
4433
+ ...markdownTheme.heading(4)
4349
4434
  },
4350
4435
  {
4351
4436
  tag: tags.heading5,
4352
- class: markdownTheme.heading(5)
4437
+ ...markdownTheme.heading(5)
4353
4438
  },
4354
4439
  {
4355
4440
  tag: tags.heading6,
4356
- class: markdownTheme.heading(6)
4441
+ ...markdownTheme.heading(6)
4357
4442
  },
4358
4443
  // Emphasis.
4359
4444
  {
@@ -4416,7 +4501,11 @@ var createMarkdownExtensions = (options = {}) => {
4416
4501
  extensions: [
4417
4502
  // GFM provided by default.
4418
4503
  markdownTagsExtensions,
4419
- ...options.extensions ?? defaultExtensions()
4504
+ ...options.extensions ?? defaultExtensions(),
4505
+ // Disable folding for fenced code blocks by overriding foldNodeProp.
4506
+ // Note: returning null from foldService does not prevent syntaxFolding fallback,
4507
+ // so we must override the node prop directly on the FencedCode node type.
4508
+ noFencedCodeFolding
4420
4509
  ]
4421
4510
  }),
4422
4511
  // Custom styles.
@@ -4431,18 +4520,13 @@ var createMarkdownExtensions = (options = {}) => {
4431
4520
  ].filter(isTruthy3))
4432
4521
  ];
4433
4522
  };
4434
- var xmlLanguageDesc = LanguageDescription.of({
4435
- name: "xml",
4436
- alias: [
4437
- "html",
4438
- "xhtml"
4439
- ],
4440
- extensions: [
4441
- "xml",
4442
- "xhtml"
4443
- ],
4444
- load: async () => xml()
4445
- });
4523
+ var noFencedCodeFolding = {
4524
+ props: [
4525
+ foldNodeProp.add({
4526
+ FencedCode: () => null
4527
+ })
4528
+ ]
4529
+ };
4446
4530
  var defaultExtensions = () => [
4447
4531
  noSetExtHeading,
4448
4532
  noHtml
@@ -4483,10 +4567,9 @@ var convertTreeToJson = (state) => {
4483
4567
 
4484
4568
  // src/extensions/markdown/decorate.ts
4485
4569
  import { syntaxTree as syntaxTree7 } from "@codemirror/language";
4486
- import { Prec as Prec4, RangeSetBuilder as RangeSetBuilder5, StateEffect as StateEffect7 } from "@codemirror/state";
4570
+ import { Prec as Prec4, RangeSetBuilder as RangeSetBuilder5, StateEffect as StateEffect6 } from "@codemirror/state";
4487
4571
  import { Decoration as Decoration11, EditorView as EditorView23, ViewPlugin as ViewPlugin14, WidgetType as WidgetType7 } from "@codemirror/view";
4488
4572
  import { invariant as invariant4 } from "@dxos/invariant";
4489
- import { mx as mx6 } from "@dxos/ui-theme";
4490
4573
 
4491
4574
  // src/extensions/markdown/changes.ts
4492
4575
  import { syntaxTree as syntaxTree4 } from "@codemirror/language";
@@ -4735,7 +4818,7 @@ var formattingStyles = EditorView21.theme({
4735
4818
  width: "100%",
4736
4819
  height: "0",
4737
4820
  verticalAlign: "middle",
4738
- borderTop: "1px solid var(--dx-cmSeparator)",
4821
+ borderTop: "1px solid var(--color-cm-separator)",
4739
4822
  opacity: 0.5
4740
4823
  },
4741
4824
  /**
@@ -4758,10 +4841,10 @@ var formattingStyles = EditorView21.theme({
4758
4841
  * Blockquote.
4759
4842
  */
4760
4843
  "& .cm-blockquote": {
4761
- background: "var(--dx-cmCodeblock)",
4762
- borderLeft: "2px solid var(--dx-cmSeparator)",
4844
+ background: "var(--color-cm-codeblock)",
4845
+ borderLeft: "2px solid var(--color-cm-separator)",
4763
4846
  paddingLeft: "1rem",
4764
- margin: "0"
4847
+ margin: 0
4765
4848
  },
4766
4849
  /**
4767
4850
  * Code and codeblocks.
@@ -4769,8 +4852,25 @@ var formattingStyles = EditorView21.theme({
4769
4852
  "& .cm-code": {
4770
4853
  fontFamily: fontMono
4771
4854
  },
4855
+ // Inline code spans (triggered by backticks) use `text-cm-code` + `font-mono`.
4856
+ // Different monospace font metrics can slightly overflow the fixed CodeMirror line box,
4857
+ // so constrain them to the target 24px height.
4858
+ "& .text-cm-code": {
4859
+ fontFamily: fontMono,
4860
+ height: "24px",
4861
+ display: "inline-flex",
4862
+ alignItems: "center",
4863
+ overflow: "hidden"
4864
+ },
4865
+ "& .text-cm-code-mark": {
4866
+ fontFamily: fontMono,
4867
+ height: "24px",
4868
+ display: "inline-flex",
4869
+ alignItems: "center",
4870
+ overflow: "hidden"
4871
+ },
4772
4872
  "& .cm-codeblock-line": {
4773
- background: "var(--dx-cmCodeblock)",
4873
+ background: "var(--color-cm-codeblock)",
4774
4874
  paddingInline: "1rem !important"
4775
4875
  },
4776
4876
  "& .cm-codeblock-start": {
@@ -4799,13 +4899,14 @@ var formattingStyles = EditorView21.theme({
4799
4899
  */
4800
4900
  ".cm-table *": {
4801
4901
  fontFamily: fontMono,
4902
+ lineHeight: 1.5,
4802
4903
  textDecoration: "none !important"
4803
4904
  },
4804
4905
  ".cm-table-head": {
4805
4906
  padding: "2px 16px 2px 0px",
4806
4907
  textAlign: "left",
4807
- borderBottom: "1px solid var(--dx-cmSeparator)",
4808
- color: "var(--dx-subdued)"
4908
+ borderBottom: "1px solid var(--color-cm-separator)",
4909
+ color: "var(--color-subdued)"
4809
4910
  },
4810
4911
  ".cm-table-cell": {
4811
4912
  padding: "2px 16px 2px 0px"
@@ -4824,12 +4925,12 @@ var formattingStyles = EditorView21.theme({
4824
4925
  },
4825
4926
  ".cm-image-with-loader": {
4826
4927
  display: "block",
4827
- opacity: "0",
4928
+ opacity: 0,
4828
4929
  transitionDuration: "350ms",
4829
4930
  transitionProperty: "opacity"
4830
4931
  },
4831
4932
  ".cm-image-with-loader.cm-loaded-image": {
4832
- opacity: "1"
4933
+ opacity: 1
4833
4934
  },
4834
4935
  ".cm-image-wrapper": {
4835
4936
  "grid-template-columns": "1fr",
@@ -4945,7 +5046,7 @@ var TableWidget = class extends WidgetType6 {
4945
5046
  };
4946
5047
 
4947
5048
  // src/extensions/markdown/decorate.ts
4948
- var __dxlog_file11 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/markdown/decorate.ts";
5049
+ var __dxlog_file12 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/markdown/decorate.ts";
4949
5050
  var Unicode = {
4950
5051
  emDash: "\u2014",
4951
5052
  bullet: "\u2022",
@@ -4968,7 +5069,6 @@ var LinkButton = class extends WidgetType7 {
4968
5069
  eq(other) {
4969
5070
  return this.url === other.url;
4970
5071
  }
4971
- // TODO(burdon): Create icon and link directly without react?
4972
5072
  toDOM(view) {
4973
5073
  const el = document.createElement("span");
4974
5074
  this.render(el, {
@@ -5045,10 +5145,10 @@ var fencedCodeLine = Decoration11.line({
5045
5145
  class: "cm-code cm-codeblock-line"
5046
5146
  });
5047
5147
  var fencedCodeLineFirst = Decoration11.line({
5048
- class: mx6("cm-code cm-codeblock-line", "cm-codeblock-start")
5148
+ class: "cm-code cm-codeblock-line cm-codeblock-start"
5049
5149
  });
5050
5150
  var fencedCodeLineLast = Decoration11.line({
5051
- class: mx6("cm-code cm-codeblock-line", "cm-codeblock-end")
5151
+ class: "cm-code cm-codeblock-line cm-codeblock-end"
5052
5152
  });
5053
5153
  var commentBlockLine = fencedCodeLine;
5054
5154
  var commentBlockLineFirst = fencedCodeLineFirst;
@@ -5081,8 +5181,8 @@ var buildDecorations2 = (view, options, focus2) => {
5081
5181
  const headerLevels = [];
5082
5182
  const getHeaderLevels = (node, level) => {
5083
5183
  invariant4(level > 0, void 0, {
5084
- F: __dxlog_file11,
5085
- L: 180,
5184
+ F: __dxlog_file12,
5185
+ L: 178,
5086
5186
  S: void 0,
5087
5187
  A: [
5088
5188
  "level > 0",
@@ -5120,8 +5220,8 @@ var buildDecorations2 = (view, options, focus2) => {
5120
5220
  };
5121
5221
  const getCurrentListLevel = () => {
5122
5222
  invariant4(listLevels.length, void 0, {
5123
- F: __dxlog_file11,
5124
- L: 202,
5223
+ F: __dxlog_file12,
5224
+ L: 200,
5125
5225
  S: void 0,
5126
5226
  A: [
5127
5227
  "listLevels.length",
@@ -5165,13 +5265,13 @@ var buildDecorations2 = (view, options, focus2) => {
5165
5265
  deco: hide
5166
5266
  });
5167
5267
  } else {
5168
- const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + " ";
5268
+ const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + "). ";
5169
5269
  if (num.length) {
5170
5270
  atomicDecoRanges.push({
5171
5271
  from: mark.from,
5172
5272
  to: mark.from + len,
5173
5273
  deco: Decoration11.replace({
5174
- widget: new TextWidget(num, markdownTheme.heading(level))
5274
+ widget: new TextWidget(num, markdownTheme.heading(level).className)
5175
5275
  })
5176
5276
  });
5177
5277
  }
@@ -5348,11 +5448,11 @@ var buildDecorations2 = (view, options, focus2) => {
5348
5448
  }
5349
5449
  decoRanges.push({
5350
5450
  from: marks[0].to,
5351
- to: marks[1].from,
5451
+ to: !editing && options.renderLinkButton ? node.to : marks[1].from,
5352
5452
  deco: Decoration11.mark({
5353
5453
  tagName: "a",
5354
5454
  attributes: {
5355
- class: "cm-link",
5455
+ class: options.renderLinkButton ? "cm-link cm-link-with-button" : "cm-link",
5356
5456
  href: url,
5357
5457
  rel: "noreferrer",
5358
5458
  target: "_blank"
@@ -5430,15 +5530,18 @@ var buildDecorations2 = (view, options, focus2) => {
5430
5530
  deco.add(from, to, d);
5431
5531
  }
5432
5532
  const atomicDeco = new RangeSetBuilder5();
5433
- for (const { from, to, deco: d } of atomicDecoRanges) {
5434
- atomicDeco.add(from, to, d);
5533
+ for (const { from, to, deco: deco2 } of atomicDecoRanges) {
5534
+ if (from < to && state.doc.lineAt(from).number !== state.doc.lineAt(to).number) {
5535
+ continue;
5536
+ }
5537
+ atomicDeco.add(from, to, deco2);
5435
5538
  }
5436
5539
  return {
5437
5540
  deco: deco.finish(),
5438
5541
  atomicDeco: atomicDeco.finish()
5439
5542
  };
5440
5543
  };
5441
- var forceUpdate = StateEffect7.define();
5544
+ var forceUpdate = StateEffect6.define();
5442
5545
  var decorateMarkdown = (options = {}) => {
5443
5546
  return [
5444
5547
  ViewPlugin14.fromClass(class {
@@ -5510,8 +5613,7 @@ var linkTooltip = (renderTooltip) => {
5510
5613
  return {
5511
5614
  pos: link.from,
5512
5615
  end: link.to,
5513
- // NOTE: Forcing above causes the tooltip to flicker.
5514
- // above: true,
5616
+ above: true,
5515
5617
  create: () => {
5516
5618
  const el = document.createElement("div");
5517
5619
  el.className = tooltipContent({});
@@ -5527,16 +5629,13 @@ var linkTooltip = (renderTooltip) => {
5527
5629
  };
5528
5630
  }
5529
5631
  };
5530
- }, {
5531
- // NOTE: 0 = default of 300ms.
5532
- hoverTime: 1
5533
5632
  });
5534
5633
  };
5535
5634
 
5536
5635
  // src/extensions/mention.ts
5537
5636
  import { autocompletion } from "@codemirror/autocomplete";
5538
- import { log as log8 } from "@dxos/log";
5539
- var __dxlog_file12 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/mention.ts";
5637
+ import { log as log9 } from "@dxos/log";
5638
+ var __dxlog_file13 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/mention.ts";
5540
5639
  var mention = ({ debug, onSearch }) => {
5541
5640
  return autocompletion({
5542
5641
  // TODO(burdon): Not working.
@@ -5548,10 +5647,10 @@ var mention = ({ debug, onSearch }) => {
5548
5647
  icons: false,
5549
5648
  override: [
5550
5649
  (context) => {
5551
- log8.info("completion context", {
5650
+ log9.info("completion context", {
5552
5651
  context
5553
5652
  }, {
5554
- F: __dxlog_file12,
5653
+ F: __dxlog_file13,
5555
5654
  L: 27,
5556
5655
  S: void 0,
5557
5656
  C: (f, a) => f(...a)
@@ -5572,8 +5671,8 @@ var mention = ({ debug, onSearch }) => {
5572
5671
  };
5573
5672
 
5574
5673
  // src/extensions/modal.ts
5575
- import { StateEffect as StateEffect8, StateField as StateField9 } from "@codemirror/state";
5576
- var modalStateEffect = StateEffect8.define();
5674
+ import { StateEffect as StateEffect7, StateField as StateField9 } from "@codemirror/state";
5675
+ var modalStateEffect = StateEffect7.define();
5577
5676
  var modalStateField = StateField9.define({
5578
5677
  create: () => false,
5579
5678
  update: (value, tr) => {
@@ -5634,7 +5733,7 @@ import { syntaxTree as syntaxTree9 } from "@codemirror/language";
5634
5733
  import { StateField as StateField10 } from "@codemirror/state";
5635
5734
  import { Facet as Facet2 } from "@codemirror/state";
5636
5735
  import { invariant as invariant5 } from "@dxos/invariant";
5637
- var __dxlog_file13 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/outliner/tree.ts";
5736
+ var __dxlog_file14 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/outliner/tree.ts";
5638
5737
  var itemToJSON = ({ type, index, level, lineRange, contentRange, children }) => {
5639
5738
  return {
5640
5739
  type,
@@ -5789,7 +5888,7 @@ var outlinerTree = (_options = {}) => {
5789
5888
  }
5790
5889
  case "BulletList": {
5791
5890
  invariant5(current, void 0, {
5792
- F: __dxlog_file13,
5891
+ F: __dxlog_file14,
5793
5892
  L: 219,
5794
5893
  S: void 0,
5795
5894
  A: [
@@ -5806,7 +5905,7 @@ var outlinerTree = (_options = {}) => {
5806
5905
  }
5807
5906
  case "ListItem": {
5808
5907
  invariant5(parent, void 0, {
5809
- F: __dxlog_file13,
5908
+ F: __dxlog_file14,
5810
5909
  L: 228,
5811
5910
  S: void 0,
5812
5911
  A: [
@@ -5848,7 +5947,7 @@ var outlinerTree = (_options = {}) => {
5848
5947
  }
5849
5948
  case "ListMark": {
5850
5949
  invariant5(current, void 0, {
5851
- F: __dxlog_file13,
5950
+ F: __dxlog_file14,
5852
5951
  L: 272,
5853
5952
  S: void 0,
5854
5953
  A: [
@@ -5862,7 +5961,7 @@ var outlinerTree = (_options = {}) => {
5862
5961
  }
5863
5962
  case "Task": {
5864
5963
  invariant5(current, void 0, {
5865
- F: __dxlog_file13,
5964
+ F: __dxlog_file14,
5866
5965
  L: 278,
5867
5966
  S: void 0,
5868
5967
  A: [
@@ -5875,7 +5974,7 @@ var outlinerTree = (_options = {}) => {
5875
5974
  }
5876
5975
  case "TaskMarker": {
5877
5976
  invariant5(current, void 0, {
5878
- F: __dxlog_file13,
5977
+ F: __dxlog_file14,
5879
5978
  L: 283,
5880
5979
  S: void 0,
5881
5980
  A: [
@@ -5891,7 +5990,7 @@ var outlinerTree = (_options = {}) => {
5891
5990
  leave: (node) => {
5892
5991
  if (node.name === "BulletList") {
5893
5992
  invariant5(parent, void 0, {
5894
- F: __dxlog_file13,
5993
+ F: __dxlog_file14,
5895
5994
  L: 291,
5896
5995
  S: void 0,
5897
5996
  A: [
@@ -5905,7 +6004,7 @@ var outlinerTree = (_options = {}) => {
5905
6004
  }
5906
6005
  });
5907
6006
  invariant5(tree, void 0, {
5908
- F: __dxlog_file13,
6007
+ F: __dxlog_file14,
5909
6008
  L: 298,
5910
6009
  S: void 0,
5911
6010
  A: [
@@ -6198,13 +6297,13 @@ var commands = () => keymap11.of([
6198
6297
  // src/extensions/outliner/outliner.ts
6199
6298
  import { Prec as Prec5 } from "@codemirror/state";
6200
6299
  import { Decoration as Decoration12, EditorView as EditorView25, ViewPlugin as ViewPlugin17 } from "@codemirror/view";
6201
- import { mx as mx7 } from "@dxos/ui-theme";
6300
+ import { mx as mx6 } from "@dxos/ui-theme";
6202
6301
 
6203
6302
  // src/extensions/outliner/editor.ts
6204
6303
  import { EditorSelection as EditorSelection4, EditorState as EditorState2 } from "@codemirror/state";
6205
6304
  import { ViewPlugin as ViewPlugin15 } from "@codemirror/view";
6206
- import { log as log9 } from "@dxos/log";
6207
- var __dxlog_file14 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/outliner/editor.ts";
6305
+ import { log as log10 } from "@dxos/log";
6306
+ var __dxlog_file15 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/outliner/editor.ts";
6208
6307
  var LIST_ITEM_REGEX = /^\s*- (\[ \]|\[x\])? /;
6209
6308
  var initialize = () => {
6210
6309
  return ViewPlugin15.fromClass(class {
@@ -6336,7 +6435,7 @@ var editor = () => [
6336
6435
  cancel = true;
6337
6436
  return;
6338
6437
  }
6339
- log9("change", {
6438
+ log10("change", {
6340
6439
  item,
6341
6440
  line: {
6342
6441
  from: line.from,
@@ -6355,7 +6454,7 @@ var editor = () => [
6355
6454
  length: insert.length
6356
6455
  }
6357
6456
  }, {
6358
- F: __dxlog_file14,
6457
+ F: __dxlog_file15,
6359
6458
  L: 164,
6360
6459
  S: void 0,
6361
6460
  C: (f, a) => f(...a)
@@ -6363,10 +6462,10 @@ var editor = () => [
6363
6462
  }
6364
6463
  });
6365
6464
  if (changes.length > 0) {
6366
- log9("modified,", {
6465
+ log10("modified,", {
6367
6466
  changes
6368
6467
  }, {
6369
- F: __dxlog_file14,
6468
+ F: __dxlog_file15,
6370
6469
  L: 175,
6371
6470
  S: void 0,
6372
6471
  C: (f, a) => f(...a)
@@ -6377,8 +6476,8 @@ var editor = () => [
6377
6476
  }
6378
6477
  ];
6379
6478
  } else if (cancel) {
6380
- log9("cancel", void 0, {
6381
- F: __dxlog_file14,
6479
+ log10("cancel", void 0, {
6480
+ F: __dxlog_file15,
6382
6481
  L: 178,
6383
6482
  S: void 0,
6384
6483
  C: (f, a) => f(...a)
@@ -6391,7 +6490,7 @@ var editor = () => [
6391
6490
 
6392
6491
  // src/extensions/outliner/menu.ts
6393
6492
  import { EditorView as EditorView24, ViewPlugin as ViewPlugin16 } from "@codemirror/view";
6394
- import { addEventListener } from "@dxos/async";
6493
+ import { addEventListener as addEventListener2 } from "@dxos/async";
6395
6494
  var menu = (options = {}) => [
6396
6495
  ViewPlugin16.fromClass(class {
6397
6496
  view;
@@ -6413,7 +6512,7 @@ var menu = (options = {}) => [
6413
6512
  }
6414
6513
  container.appendChild(this.tag);
6415
6514
  const handler = () => this.scheduleUpdate();
6416
- this.cleanup = addEventListener(container, "scroll", handler);
6515
+ this.cleanup = addEventListener2(container, "scroll", handler);
6417
6516
  this.scheduleUpdate();
6418
6517
  }
6419
6518
  destroy() {
@@ -6492,7 +6591,7 @@ var outliner = (_options = {}) => [
6492
6591
  }),
6493
6592
  // Researve space for menu.
6494
6593
  EditorView25.contentAttributes.of({
6495
- class: "is-full !mr-[3rem]"
6594
+ class: "w-full !mr-[3rem]"
6496
6595
  })
6497
6596
  ];
6498
6597
  var decorations = () => [
@@ -6521,7 +6620,7 @@ var decorations = () => [
6521
6620
  const lineTo = doc.lineAt(item.contentRange.to);
6522
6621
  const isSelected = selection.includes(item.index) || item === current;
6523
6622
  decorations2.push(Decoration12.line({
6524
- class: mx7("cm-list-item", lineFrom.number === line.number && "cm-list-item-start", lineTo.number === line.number && "cm-list-item-end", isSelected && (hasFocus ? "cm-list-item-focused" : "cm-list-item-selected"))
6623
+ class: mx6("cm-list-item", lineFrom.number === line.number && "cm-list-item-start", lineTo.number === line.number && "cm-list-item-end", isSelected && (hasFocus ? "cm-list-item-focused" : "cm-list-item-selected"))
6525
6624
  }).range(line.from, line.from));
6526
6625
  }
6527
6626
  }
@@ -6556,27 +6655,32 @@ var decorations = () => [
6556
6655
  marginBottom: "2px"
6557
6656
  },
6558
6657
  ".cm-list-item-focused": {
6559
- borderColor: "var(--dx-neutralFocusIndicator)"
6658
+ borderColor: "var(--color-neutral-focus-indicator)"
6560
6659
  },
6561
6660
  "&:focus-within .cm-list-item-selected": {
6562
- borderColor: "var(--dx-separator)"
6661
+ borderColor: "var(--color-separator)"
6563
6662
  }
6564
6663
  }))
6565
6664
  ];
6566
6665
 
6567
6666
  // src/extensions/preview/preview.ts
6568
6667
  import { syntaxTree as syntaxTree10 } from "@codemirror/language";
6569
- import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField11 } from "@codemirror/state";
6570
- import { Decoration as Decoration13, EditorView as EditorView26, WidgetType as WidgetType8 } from "@codemirror/view";
6668
+ import { RangeSetBuilder as RangeSetBuilder6, StateEffect as StateEffect8, StateField as StateField11 } from "@codemirror/state";
6669
+ import { Decoration as Decoration13, EditorView as EditorView26, ViewPlugin as ViewPlugin18, WidgetType as WidgetType8 } from "@codemirror/view";
6670
+ import { DXN, Entity } from "@dxos/echo";
6671
+ var labelResolvedEffect = StateEffect8.define();
6571
6672
  var preview = (options = {}) => {
6673
+ const viewRef = {
6674
+ current: void 0
6675
+ };
6572
6676
  return [
6573
6677
  // NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
6574
6678
  // "Block decorations may not be specified via plugins".
6575
6679
  StateField11.define({
6576
- create: (state) => buildDecorations3(state, options),
6680
+ create: (state) => buildDecorations3(state, options, viewRef),
6577
6681
  update: (decorations2, tr) => {
6578
- if (tr.docChanged) {
6579
- return buildDecorations3(tr.state, options);
6682
+ if (tr.docChanged || tr.effects.some((effect) => effect.is(labelResolvedEffect))) {
6683
+ return buildDecorations3(tr.state, options, viewRef);
6580
6684
  }
6581
6685
  return decorations2.map(tr.changes);
6582
6686
  },
@@ -6584,10 +6688,34 @@ var preview = (options = {}) => {
6584
6688
  EditorView26.decorations.from(field),
6585
6689
  EditorView26.atomicRanges.of((view) => view.state.field(field))
6586
6690
  ]
6691
+ }),
6692
+ ViewPlugin18.define((view) => {
6693
+ viewRef.current = view;
6694
+ return {
6695
+ destroy() {
6696
+ viewRef.current = void 0;
6697
+ }
6698
+ };
6587
6699
  })
6588
6700
  ];
6589
6701
  };
6590
- var buildDecorations3 = (state, options) => {
6702
+ var resolveLabel = (db, dxnStr, viewRef) => {
6703
+ const dxn = DXN.tryParse(dxnStr);
6704
+ if (!dxn) {
6705
+ return;
6706
+ }
6707
+ const ref = db.makeRef(dxn);
6708
+ const target = ref.target;
6709
+ if (target) {
6710
+ return Entity.getLabel(target);
6711
+ }
6712
+ void ref.tryLoad().then(() => {
6713
+ viewRef.current?.dispatch({
6714
+ effects: labelResolvedEffect.of(void 0)
6715
+ });
6716
+ });
6717
+ };
6718
+ var buildDecorations3 = (state, options, viewRef) => {
6591
6719
  const builder = new RangeSetBuilder6();
6592
6720
  syntaxTree10(state).iterate({
6593
6721
  enter: (node) => {
@@ -6599,8 +6727,13 @@ var buildDecorations3 = (state, options) => {
6599
6727
  case "Link": {
6600
6728
  const link = getLinkRef(state, node.node);
6601
6729
  if (link) {
6730
+ const resolved = options.db ? resolveLabel(options.db, link.dxn, viewRef) : void 0;
6731
+ const displayLink = resolved ? {
6732
+ ...link,
6733
+ label: resolved
6734
+ } : link;
6602
6735
  builder.add(node.from, node.to, Decoration13.replace({
6603
- widget: new PreviewInlineWidget(options, link),
6736
+ widget: new PreviewInlineWidget(options, displayLink),
6604
6737
  side: 1
6605
6738
  }));
6606
6739
  }
@@ -6631,13 +6764,13 @@ var getLinkRef = (state, node) => {
6631
6764
  const mark = node.getChildren("LinkMark");
6632
6765
  const urlNode = node.getChild("URL");
6633
6766
  if (mark && urlNode) {
6634
- const url = state.sliceDoc(urlNode.from, urlNode.to);
6635
- if (url.startsWith("dxn:")) {
6767
+ const dxn = state.sliceDoc(urlNode.from, urlNode.to);
6768
+ if (dxn.startsWith("dxn:")) {
6636
6769
  const label = state.sliceDoc(mark[0].to, mark[1].from);
6637
6770
  return {
6638
6771
  block: state.sliceDoc(mark[0].from, mark[0].from + 1) === "!",
6639
6772
  label,
6640
- ref: url
6773
+ dxn
6641
6774
  };
6642
6775
  }
6643
6776
  }
@@ -6652,13 +6785,13 @@ var PreviewInlineWidget = class extends WidgetType8 {
6652
6785
  // return false;
6653
6786
  // }
6654
6787
  eq(other) {
6655
- return this._link.ref === other._link.ref && this._link.label === other._link.label;
6788
+ return this._link.dxn === other._link.dxn && this._link.label === other._link.label;
6656
6789
  }
6657
6790
  toDOM(_view) {
6658
6791
  const root = document.createElement("dx-anchor");
6659
6792
  root.classList.add("dx-tag--anchor");
6660
6793
  root.textContent = this._link.label;
6661
- root.setAttribute("refId", this._link.ref);
6794
+ root.setAttribute("dxn", this._link.dxn);
6662
6795
  return root;
6663
6796
  }
6664
6797
  };
@@ -6672,11 +6805,11 @@ var PreviewBlockWidget = class extends WidgetType8 {
6672
6805
  // return true;
6673
6806
  // }
6674
6807
  eq(other) {
6675
- return this._link.ref === other._link.ref;
6808
+ return this._link.dxn === other._link.dxn;
6676
6809
  }
6677
6810
  toDOM(_view) {
6678
6811
  const root = document.createElement("div");
6679
- root.classList.add("cm-preview-block", "density-fine");
6812
+ root.classList.add("cm-preview-block", "dx-density-fine");
6680
6813
  this._options.addBlockContainer?.({
6681
6814
  link: this._link,
6682
6815
  el: root
@@ -6892,7 +7025,7 @@ var mixedParser = (registry) => {
6892
7025
 
6893
7026
  // src/extensions/tags/streamer.ts
6894
7027
  import { StateEffect as StateEffect9, StateField as StateField12 } from "@codemirror/state";
6895
- import { Decoration as Decoration14, EditorView as EditorView28, ViewPlugin as ViewPlugin18, WidgetType as WidgetType9 } from "@codemirror/view";
7028
+ import { Decoration as Decoration14, EditorView as EditorView28, ViewPlugin as ViewPlugin19, WidgetType as WidgetType9 } from "@codemirror/view";
6896
7029
  import { Domino as Domino3 } from "@dxos/ui";
6897
7030
  import { isTruthy as isTruthy4 } from "@dxos/util";
6898
7031
  var BLINK_RATE = 2e3;
@@ -6918,7 +7051,7 @@ var cursor = () => {
6918
7051
  return value;
6919
7052
  }
6920
7053
  });
6921
- const timerPlugin = ViewPlugin18.fromClass(class {
7054
+ const timerPlugin = ViewPlugin19.fromClass(class {
6922
7055
  view;
6923
7056
  timer;
6924
7057
  constructor(view) {
@@ -6973,7 +7106,7 @@ var CursorWidget = class extends WidgetType9 {
6973
7106
  };
6974
7107
  var fadeIn = (options = {}) => {
6975
7108
  const FADE_IN_DURATION = 1e3;
6976
- const DEFAULT_REMOVAL_DELAY = 5e3;
7109
+ const DEFAULT_REMOVAL_DELAY = 3e3;
6977
7110
  const removalDelay = options.removalDelay ?? DEFAULT_REMOVAL_DELAY;
6978
7111
  const removeDecoration = StateEffect9.define();
6979
7112
  const fadeField = StateField12.define({
@@ -7019,7 +7152,7 @@ var fadeIn = (options = {}) => {
7019
7152
  },
7020
7153
  provide: (f) => EditorView28.decorations.from(f)
7021
7154
  });
7022
- const timerPlugin = ViewPlugin18.fromClass(class {
7155
+ const timerPlugin = ViewPlugin19.fromClass(class {
7023
7156
  view;
7024
7157
  // Map a simple key "from-to" to timer id.
7025
7158
  _timers = /* @__PURE__ */ new Map();
@@ -7086,16 +7219,16 @@ var fadeIn = (options = {}) => {
7086
7219
  // src/extensions/tags/xml-tags.ts
7087
7220
  import { syntaxTree as syntaxTree11 } from "@codemirror/language";
7088
7221
  import { Prec as Prec7, RangeSetBuilder as RangeSetBuilder7, StateEffect as StateEffect10, StateField as StateField13 } from "@codemirror/state";
7089
- import { Decoration as Decoration15, EditorView as EditorView29, ViewPlugin as ViewPlugin19, WidgetType as WidgetType10, keymap as keymap13 } from "@codemirror/view";
7222
+ import { Decoration as Decoration15, EditorView as EditorView29, ViewPlugin as ViewPlugin20, WidgetType as WidgetType10, keymap as keymap13 } from "@codemirror/view";
7090
7223
  import { invariant as invariant7 } from "@dxos/invariant";
7091
- import { log as log10 } from "@dxos/log";
7224
+ import { log as log11 } from "@dxos/log";
7092
7225
 
7093
7226
  // src/extensions/tags/xml-util.ts
7094
7227
  import { invariant as invariant6 } from "@dxos/invariant";
7095
- var __dxlog_file15 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-util.ts";
7228
+ var __dxlog_file16 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-util.ts";
7096
7229
  var nodeToJson = (state, node) => {
7097
7230
  invariant6(node.type.name === "Element", "Node is not an Element", {
7098
- F: __dxlog_file15,
7231
+ F: __dxlog_file16,
7099
7232
  L: 18,
7100
7233
  S: void 0,
7101
7234
  A: [
@@ -7159,7 +7292,7 @@ var nodeToJson = (state, node) => {
7159
7292
  };
7160
7293
 
7161
7294
  // src/extensions/tags/xml-tags.ts
7162
- var __dxlog_file16 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-tags.ts";
7295
+ var __dxlog_file17 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-tags.ts";
7163
7296
  var navigatePreviousEffect = StateEffect10.define();
7164
7297
  var navigateNextEffect = StateEffect10.define();
7165
7298
  var getXmlTextChild = (children) => {
@@ -7189,11 +7322,11 @@ var widgetStateMapStateField = StateField13.define({
7189
7322
  }
7190
7323
  if (effect.is(xmlTagUpdateEffect)) {
7191
7324
  const { id, value } = effect.value;
7192
- log10("widget updated", {
7325
+ log11("widget updated", {
7193
7326
  id,
7194
7327
  value
7195
7328
  }, {
7196
- F: __dxlog_file16,
7329
+ F: __dxlog_file17,
7197
7330
  L: 153,
7198
7331
  S: void 0,
7199
7332
  C: (f, a) => f(...a)
@@ -7224,11 +7357,11 @@ var createWidgetMap = (setWidgets) => {
7224
7357
  const widgets = /* @__PURE__ */ new Map();
7225
7358
  const notifier = {
7226
7359
  mounted: (state) => {
7227
- log10("widget mounted", {
7360
+ log11("widget mounted", {
7228
7361
  id: state.id,
7229
7362
  tag: state.props._tag
7230
7363
  }, {
7231
- F: __dxlog_file16,
7364
+ F: __dxlog_file17,
7232
7365
  L: 206,
7233
7366
  S: void 0,
7234
7367
  C: (f, a) => f(...a)
@@ -7240,11 +7373,11 @@ var createWidgetMap = (setWidgets) => {
7240
7373
  },
7241
7374
  unmounted: (id) => {
7242
7375
  const state = widgets.get(id);
7243
- log10("widget unmounted", {
7376
+ log11("widget unmounted", {
7244
7377
  id,
7245
7378
  tag: state?.props._tag
7246
7379
  }, {
7247
- F: __dxlog_file16,
7380
+ F: __dxlog_file17,
7248
7381
  L: 212,
7249
7382
  S: void 0,
7250
7383
  C: (f, a) => f(...a)
@@ -7306,11 +7439,9 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
7306
7439
  anchor: line.from,
7307
7440
  head: line.from
7308
7441
  },
7309
- effects: scrollToLineEffect.of({
7310
- line: line.number,
7311
- options: {
7312
- offset: -16
7313
- }
7442
+ effects: scrollerLineEffect.of({
7443
+ line: line.number - 1,
7444
+ offset: -16
7314
7445
  })
7315
7446
  });
7316
7447
  continue;
@@ -7341,11 +7472,9 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
7341
7472
  anchor: line.to,
7342
7473
  head: line.to
7343
7474
  },
7344
- effects: scrollToLineEffect.of({
7345
- line: line.number,
7346
- options: {
7347
- offset: -16
7348
- }
7475
+ effects: scrollerLineEffect.of({
7476
+ line: line.number - 1,
7477
+ offset: -16
7349
7478
  })
7350
7479
  });
7351
7480
  } else {
@@ -7355,11 +7484,9 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
7355
7484
  anchor: line.to,
7356
7485
  head: line.to
7357
7486
  },
7358
- effects: scrollToLineEffect.of({
7359
- line: line.number,
7360
- options: {
7361
- position: "end"
7362
- }
7487
+ effects: scrollerLineEffect.of({
7488
+ line: line.number - 1,
7489
+ position: "end"
7363
7490
  })
7364
7491
  });
7365
7492
  }
@@ -7369,7 +7496,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
7369
7496
  });
7370
7497
  });
7371
7498
  };
7372
- var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin19.fromClass(class {
7499
+ var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin20.fromClass(class {
7373
7500
  update(update2) {
7374
7501
  const widgetStateMap = update2.state.field(widgetStateMapStateField);
7375
7502
  const { decorations: decorations2 } = update2.state.field(widgetDecorationsField);
@@ -7406,6 +7533,12 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
7406
7533
  update: ({ from, decorations: decorations2 }, tr) => {
7407
7534
  for (const effect of tr.effects) {
7408
7535
  if (effect.is(xmlTagResetEffect)) {
7536
+ if (tr.docChanged) {
7537
+ return buildDecorations4(tr.state, {
7538
+ from: 0,
7539
+ to: tr.state.doc.length
7540
+ }, registry, notifier);
7541
+ }
7409
7542
  return {
7410
7543
  from: 0,
7411
7544
  decorations: Decoration15.none
@@ -7416,12 +7549,12 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
7416
7549
  const { state } = tr;
7417
7550
  const reset = tr.changes.touchesRange(0, from);
7418
7551
  if (reset) {
7419
- log10("document reset", {
7552
+ log11("document reset", {
7420
7553
  from,
7421
7554
  to: state.doc.length
7422
7555
  }, {
7423
- F: __dxlog_file16,
7424
- L: 371,
7556
+ F: __dxlog_file17,
7557
+ L: 374,
7425
7558
  S: void 0,
7426
7559
  C: (f, a) => f(...a)
7427
7560
  });
@@ -7502,9 +7635,9 @@ var buildDecorations4 = (state, range, registry, notifier) => {
7502
7635
  }
7503
7636
  }
7504
7637
  } catch (err) {
7505
- log10.catch(err, void 0, {
7506
- F: __dxlog_file16,
7507
- L: 456,
7638
+ log11.catch(err, void 0, {
7639
+ F: __dxlog_file17,
7640
+ L: 459,
7508
7641
  S: void 0,
7509
7642
  C: (f, a) => f(...a)
7510
7643
  });
@@ -7528,8 +7661,8 @@ var PlaceholderWidget2 = class extends WidgetType10 {
7528
7661
  constructor(id, Component, props, notifier) {
7529
7662
  super(), this.id = id, this.Component = Component, this.props = props, this.notifier = notifier;
7530
7663
  invariant7(id, void 0, {
7531
- F: __dxlog_file16,
7532
- L: 482,
7664
+ F: __dxlog_file17,
7665
+ L: 485,
7533
7666
  S: this,
7534
7667
  A: [
7535
7668
  "id",
@@ -7655,9 +7788,11 @@ export {
7655
7788
  commentClickedEffect,
7656
7789
  comments,
7657
7790
  commentsState,
7791
+ compactSlots,
7658
7792
  convertTreeToJson,
7659
7793
  createBasicExtensions,
7660
7794
  createComment,
7795
+ createCrawler,
7661
7796
  createDataExtensions,
7662
7797
  createEditorStateStore,
7663
7798
  createEditorStateTransaction,
@@ -7677,11 +7812,9 @@ export {
7677
7812
  defaultThemeSlots,
7678
7813
  deleteItem,
7679
7814
  documentId,
7815
+ documentSlots,
7680
7816
  dropFile,
7681
7817
  editorInputMode,
7682
- editorSlots,
7683
- editorWidth,
7684
- editorWithToolbarLayout,
7685
7818
  extendedMarkdown,
7686
7819
  filterChars,
7687
7820
  flattenRect,
@@ -7738,9 +7871,10 @@ export {
7738
7871
  removeStyle,
7739
7872
  replacer,
7740
7873
  scrollThreadIntoView,
7741
- scrollToBottomEffect,
7742
7874
  scrollToLine,
7743
- scrollToLineEffect,
7875
+ scroller,
7876
+ scrollerCrawlEffect,
7877
+ scrollerLineEffect,
7744
7878
  selectionState,
7745
7879
  setBlockquote,
7746
7880
  setComments,
@@ -7748,7 +7882,6 @@ export {
7748
7882
  setSelection,
7749
7883
  setStyle,
7750
7884
  singleValueFacet,
7751
- smoothScroll,
7752
7885
  stackItemContentEditorClassNames,
7753
7886
  staticCompletion,
7754
7887
  streamer,