@dxos/react-ui-editor 0.8.2 → 0.8.3-main.7f5a14c

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 (83) hide show
  1. package/dist/lib/browser/index.mjs +936 -274
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +981 -314
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +936 -274
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/EditorToolbar/util.d.ts +2 -2
  11. package/dist/types/src/components/Popover/CommandMenu.d.ts +34 -0
  12. package/dist/types/src/components/Popover/CommandMenu.d.ts.map +1 -0
  13. package/dist/types/src/components/Popover/RefPopover.d.ts +19 -6
  14. package/dist/types/src/components/Popover/RefPopover.d.ts.map +1 -1
  15. package/dist/types/src/components/Popover/index.d.ts +1 -0
  16. package/dist/types/src/components/Popover/index.d.ts.map +1 -1
  17. package/dist/types/src/defaults.d.ts.map +1 -1
  18. package/dist/types/src/extensions/command/menu.d.ts +40 -0
  19. package/dist/types/src/extensions/command/menu.d.ts.map +1 -1
  20. package/dist/types/src/extensions/factories.d.ts +1 -0
  21. package/dist/types/src/extensions/factories.d.ts.map +1 -1
  22. package/dist/types/src/extensions/hashtag.d.ts +3 -0
  23. package/dist/types/src/extensions/hashtag.d.ts.map +1 -0
  24. package/dist/types/src/extensions/index.d.ts +2 -0
  25. package/dist/types/src/extensions/index.d.ts.map +1 -1
  26. package/dist/types/src/extensions/json.d.ts.map +1 -1
  27. package/dist/types/src/extensions/markdown/debug.d.ts +2 -2
  28. package/dist/types/src/extensions/markdown/debug.d.ts.map +1 -1
  29. package/dist/types/src/extensions/outliner/outliner.d.ts +1 -3
  30. package/dist/types/src/extensions/outliner/outliner.d.ts.map +1 -1
  31. package/dist/types/src/extensions/placeholder.d.ts +4 -0
  32. package/dist/types/src/extensions/placeholder.d.ts.map +1 -0
  33. package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
  34. package/dist/types/src/hooks/useTextEditor.d.ts +8 -9
  35. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  36. package/dist/types/src/stories/Command.stories.d.ts +1 -1
  37. package/dist/types/src/stories/Command.stories.d.ts.map +1 -1
  38. package/dist/types/src/stories/CommandMenu.stories.d.ts +12 -0
  39. package/dist/types/src/stories/CommandMenu.stories.d.ts.map +1 -0
  40. package/dist/types/src/stories/Comments.stories.d.ts +1 -1
  41. package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
  42. package/dist/types/src/stories/Experimental.stories.d.ts +1 -1
  43. package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
  44. package/dist/types/src/stories/Markdown.stories.d.ts +1 -1
  45. package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
  46. package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
  47. package/dist/types/src/stories/Preview.stories.d.ts +1 -1
  48. package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
  49. package/dist/types/src/stories/TextEditor.stories.d.ts +1 -1
  50. package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
  51. package/dist/types/src/stories/components/EditorStory.d.ts +43 -0
  52. package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -0
  53. package/dist/types/src/stories/components/index.d.ts +3 -0
  54. package/dist/types/src/stories/components/index.d.ts.map +1 -0
  55. package/dist/types/src/stories/{util.d.ts → components/util.d.ts} +3 -18
  56. package/dist/types/src/stories/components/util.d.ts.map +1 -0
  57. package/package.json +31 -27
  58. package/src/components/Popover/CommandMenu.tsx +279 -0
  59. package/src/components/Popover/RefPopover.tsx +44 -22
  60. package/src/components/Popover/index.ts +1 -0
  61. package/src/defaults.ts +1 -0
  62. package/src/extensions/command/menu.ts +334 -23
  63. package/src/extensions/factories.ts +4 -1
  64. package/src/extensions/hashtag.tsx +68 -0
  65. package/src/extensions/index.ts +2 -0
  66. package/src/extensions/json.ts +2 -1
  67. package/src/extensions/markdown/debug.ts +2 -2
  68. package/src/extensions/outliner/outliner.ts +6 -8
  69. package/src/extensions/placeholder.ts +82 -0
  70. package/src/extensions/preview/preview.ts +3 -6
  71. package/src/hooks/useTextEditor.ts +11 -12
  72. package/src/stories/Command.stories.tsx +1 -1
  73. package/src/stories/CommandMenu.stories.tsx +143 -0
  74. package/src/stories/Comments.stories.tsx +2 -2
  75. package/src/stories/Experimental.stories.tsx +2 -2
  76. package/src/stories/Markdown.stories.tsx +2 -2
  77. package/src/stories/Outliner.stories.tsx +19 -7
  78. package/src/stories/Preview.stories.tsx +34 -32
  79. package/src/stories/TextEditor.stories.tsx +3 -3
  80. package/src/stories/components/EditorStory.tsx +135 -0
  81. package/src/stories/components/index.ts +6 -0
  82. package/src/stories/{util.tsx → components/util.tsx} +5 -100
  83. package/dist/types/src/stories/util.d.ts.map +0 -1
@@ -35,14 +35,14 @@ var translations_default = [
35
35
 
36
36
  // packages/ui/react-ui-editor/src/index.ts
37
37
  import { EditorState as EditorState4 } from "@codemirror/state";
38
- import { EditorView as EditorView24, keymap as keymap13 } from "@codemirror/view";
38
+ import { EditorView as EditorView26, keymap as keymap14 } from "@codemirror/view";
39
39
  import { tags as tags2 } from "@lezer/highlight";
40
40
  import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
41
41
 
42
42
  // packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
43
43
  import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
44
44
  import { Rx } from "@effect-rx/rx-react";
45
- import React3, { memo, useMemo as useMemo3 } from "react";
45
+ import React3, { memo, useMemo as useMemo4 } from "react";
46
46
  import { rxFromSignal } from "@dxos/app-graph";
47
47
  import { ElevationProvider } from "@dxos/react-ui";
48
48
  import { MenuProvider, ToolbarMenu, createGapSeparator, useMenuActions } from "@dxos/react-ui-menu";
@@ -1458,27 +1458,107 @@ var command = (options = {}) => {
1458
1458
  };
1459
1459
 
1460
1460
  // packages/ui/react-ui-editor/src/extensions/command/menu.ts
1461
- import { EditorView as EditorView7, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
1461
+ import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField3, StateEffect as StateEffect3, Prec } from "@codemirror/state";
1462
+ import { EditorView as EditorView8, ViewPlugin as ViewPlugin6, Decoration as Decoration5, keymap as keymap4 } from "@codemirror/view";
1463
+ import { useCallback, useMemo as useMemo2, useRef, useState } from "react";
1464
+ import { addEventListener } from "@dxos/async";
1465
+
1466
+ // packages/ui/react-ui-editor/src/extensions/placeholder.ts
1467
+ import { Decoration as Decoration4, EditorView as EditorView7, WidgetType as WidgetType3, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
1468
+ var Placeholder = class extends WidgetType3 {
1469
+ constructor(content) {
1470
+ super(), this.content = content;
1471
+ }
1472
+ toDOM(view) {
1473
+ const wrap = document.createElement("span");
1474
+ wrap.className = "cm-placeholder";
1475
+ wrap.style.pointerEvents = "none";
1476
+ wrap.appendChild(typeof this.content === "string" ? document.createTextNode(this.content) : typeof this.content === "function" ? this.content(view) : this.content.cloneNode(true));
1477
+ wrap.setAttribute("aria-hidden", "true");
1478
+ return wrap;
1479
+ }
1480
+ coordsAt(dom) {
1481
+ const rects = dom.firstChild ? clientRectsFor(dom.firstChild) : [];
1482
+ if (!rects.length) {
1483
+ return null;
1484
+ }
1485
+ const style = window.getComputedStyle(dom.parentNode);
1486
+ const rect = flattenRect(rects[0], style.direction !== "rtl");
1487
+ const lineHeight = parseInt(style.lineHeight);
1488
+ if (rect.bottom - rect.top > lineHeight * 1.5) {
1489
+ return {
1490
+ left: rect.left,
1491
+ right: rect.right,
1492
+ top: rect.top,
1493
+ bottom: rect.top + lineHeight
1494
+ };
1495
+ }
1496
+ return rect;
1497
+ }
1498
+ ignoreEvent() {
1499
+ return false;
1500
+ }
1501
+ };
1502
+ function multilinePlaceholder(content) {
1503
+ const plugin = ViewPlugin5.fromClass(class {
1504
+ constructor(view) {
1505
+ this.view = view;
1506
+ }
1507
+ get decorations() {
1508
+ const activeLine = this.view.state.doc.lineAt(this.view.state.selection.main.head);
1509
+ const isEmpty = activeLine.text.trim() === "";
1510
+ if (!isEmpty || !content) {
1511
+ return Decoration4.none;
1512
+ }
1513
+ const lineStart = activeLine.from;
1514
+ return Decoration4.set([
1515
+ Decoration4.widget({
1516
+ widget: new Placeholder(content),
1517
+ side: 1
1518
+ }).range(lineStart)
1519
+ ]);
1520
+ }
1521
+ }, {
1522
+ decorations: (v) => v.decorations
1523
+ });
1524
+ return typeof content === "string" ? [
1525
+ plugin,
1526
+ EditorView7.contentAttributes.of({
1527
+ "aria-placeholder": content
1528
+ })
1529
+ ] : plugin;
1530
+ }
1531
+
1532
+ // packages/ui/react-ui-editor/src/extensions/command/menu.ts
1462
1533
  var floatingMenu = (options = {}) => [
1463
- ViewPlugin5.fromClass(class {
1534
+ ViewPlugin6.fromClass(class {
1464
1535
  constructor(view) {
1465
- this.rafId = null;
1466
1536
  this.view = view;
1467
1537
  const container = view.scrollDOM;
1468
1538
  if (getComputedStyle(container).position === "static") {
1469
1539
  container.style.position = "relative";
1470
1540
  }
1471
- const icon = document.createElement("dx-icon");
1472
- icon.setAttribute("icon", options.icon ?? "ph--dots-three-outline--regular");
1473
- const button = document.createElement("button");
1474
- button.appendChild(icon);
1475
- this.tag = document.createElement("dx-ref-tag");
1476
- this.tag.classList.add("cm-ref-tag");
1477
- this.tag.appendChild(button);
1541
+ {
1542
+ const icon = document.createElement("dx-icon");
1543
+ icon.setAttribute("icon", options.icon ?? "ph--dots-three-vertical--regular");
1544
+ const button = document.createElement("button");
1545
+ button.appendChild(icon);
1546
+ this.tag = document.createElement("dx-ref-tag");
1547
+ this.tag.classList.add("cm-ref-tag");
1548
+ this.tag.appendChild(button);
1549
+ }
1478
1550
  container.appendChild(this.tag);
1479
- container.addEventListener("scroll", this.scheduleUpdate.bind(this));
1551
+ const handler = () => this.scheduleUpdate();
1552
+ this.cleanup = addEventListener(container, "scroll", handler);
1480
1553
  this.scheduleUpdate();
1481
1554
  }
1555
+ destroy() {
1556
+ this.cleanup?.();
1557
+ this.tag.remove();
1558
+ if (this.rafId != null) {
1559
+ cancelAnimationFrame(this.rafId);
1560
+ }
1561
+ }
1482
1562
  update(update2) {
1483
1563
  this.tag.dataset.focused = update2.view.hasFocus ? "true" : "false";
1484
1564
  if (!update2.view.hasFocus) {
@@ -1515,20 +1595,16 @@ var floatingMenu = (options = {}) => [
1515
1595
  }
1516
1596
  this.rafId = requestAnimationFrame(this.updateButtonPosition.bind(this));
1517
1597
  }
1518
- destroy() {
1519
- this.tag.remove();
1520
- if (this.rafId != null) {
1521
- cancelAnimationFrame(this.rafId);
1522
- }
1523
- }
1524
1598
  }),
1525
- EditorView7.theme({
1599
+ EditorView8.theme({
1526
1600
  ".cm-ref-tag": {
1527
1601
  position: "fixed",
1528
1602
  padding: "0",
1529
1603
  border: "none",
1530
- transition: "opacity 0.3s ease-in-out",
1531
- opacity: 0.1
1604
+ opacity: "0"
1605
+ },
1606
+ "[data-has-focus] & .cm-ref-tag": {
1607
+ opacity: "1"
1532
1608
  },
1533
1609
  ".cm-ref-tag button": {
1534
1610
  display: "grid",
@@ -1536,16 +1612,262 @@ var floatingMenu = (options = {}) => [
1536
1612
  justifyContent: "center",
1537
1613
  width: "2rem",
1538
1614
  height: "2rem"
1539
- },
1540
- '.cm-ref-tag[data-focused="true"]': {
1541
- opacity: 1
1542
1615
  }
1543
1616
  })
1544
1617
  ];
1618
+ var commandRangeEffect = StateEffect3.define();
1619
+ var commandMenuState = StateField3.define({
1620
+ create: () => null,
1621
+ update: (value, tr) => {
1622
+ let newValue = value;
1623
+ for (const effect of tr.effects) {
1624
+ if (effect.is(commandRangeEffect)) {
1625
+ newValue = effect.value;
1626
+ }
1627
+ }
1628
+ return newValue;
1629
+ }
1630
+ });
1631
+ var commandMenu = (options) => {
1632
+ const commandMenuPlugin = ViewPlugin6.fromClass(class {
1633
+ constructor(view) {
1634
+ this.view = view;
1635
+ this.decorations = Decoration5.none;
1636
+ }
1637
+ // TODO(wittjosiah): The decorations are repainted on every update, this occasionally causes menu to flicker.
1638
+ update(update2) {
1639
+ const builder = new RangeSetBuilder3();
1640
+ const selection = update2.view.state.selection.main;
1641
+ const { range: activeRange, trigger } = update2.view.state.field(commandMenuState) ?? {};
1642
+ const shouldShowWidget = activeRange && selection.head >= activeRange.from && selection.head <= activeRange.to;
1643
+ if (shouldShowWidget) {
1644
+ builder.add(activeRange.from, activeRange.to, Decoration5.mark({
1645
+ tagName: "dx-ref-tag",
1646
+ class: "cm-ref-tag",
1647
+ attributes: {
1648
+ "data-auto-trigger": "true",
1649
+ "data-trigger": trigger
1650
+ }
1651
+ }));
1652
+ }
1653
+ const activeRangeChanged = update2.transactions.some((tr) => tr.effects.some((effect) => effect.is(commandRangeEffect)));
1654
+ if (activeRange && activeRangeChanged && trigger) {
1655
+ const content = update2.view.state.sliceDoc(activeRange.from + 1, activeRange.to);
1656
+ options.onTextChange?.(trigger, content);
1657
+ }
1658
+ this.decorations = builder.finish();
1659
+ }
1660
+ }, {
1661
+ decorations: (v) => v.decorations
1662
+ });
1663
+ const triggers = Array.isArray(options.trigger) ? options.trigger : [
1664
+ options.trigger
1665
+ ];
1666
+ const commandKeymap = keymap4.of([
1667
+ ...triggers.map((trigger) => ({
1668
+ key: trigger,
1669
+ run: (view) => {
1670
+ const selection = view.state.selection.main;
1671
+ const line = view.state.doc.lineAt(selection.head);
1672
+ const shouldTrigger = line.text.trim() === "" || selection.head === line.from || selection.head > line.from && line.text[selection.head - line.from - 1] === " ";
1673
+ if (shouldTrigger) {
1674
+ view.dispatch({
1675
+ changes: {
1676
+ from: selection.head,
1677
+ insert: trigger
1678
+ },
1679
+ selection: {
1680
+ anchor: selection.head + 1,
1681
+ head: selection.head + 1
1682
+ },
1683
+ effects: commandRangeEffect.of({
1684
+ trigger,
1685
+ range: {
1686
+ from: selection.head,
1687
+ to: selection.head + 1
1688
+ }
1689
+ })
1690
+ });
1691
+ return true;
1692
+ }
1693
+ return false;
1694
+ }
1695
+ })),
1696
+ {
1697
+ key: "Enter",
1698
+ run: (view) => {
1699
+ const activeRange = view.state.field(commandMenuState)?.range;
1700
+ if (activeRange) {
1701
+ view.dispatch({
1702
+ changes: {
1703
+ from: activeRange.from,
1704
+ to: activeRange.to,
1705
+ insert: ""
1706
+ }
1707
+ });
1708
+ options.onEnter?.();
1709
+ return true;
1710
+ }
1711
+ return false;
1712
+ }
1713
+ },
1714
+ {
1715
+ key: "ArrowDown",
1716
+ run: (view) => {
1717
+ const activeRange = view.state.field(commandMenuState)?.range;
1718
+ if (activeRange) {
1719
+ options.onArrowDown?.();
1720
+ return true;
1721
+ }
1722
+ return false;
1723
+ }
1724
+ },
1725
+ {
1726
+ key: "ArrowUp",
1727
+ run: (view) => {
1728
+ const activeRange = view.state.field(commandMenuState)?.range;
1729
+ if (activeRange) {
1730
+ options.onArrowUp?.();
1731
+ return true;
1732
+ }
1733
+ return false;
1734
+ }
1735
+ }
1736
+ ]);
1737
+ const updateListener = EditorView8.updateListener.of((update2) => {
1738
+ const { trigger, range: activeRange } = update2.view.state.field(commandMenuState) ?? {};
1739
+ if (!activeRange || !trigger) {
1740
+ return;
1741
+ }
1742
+ const selection = update2.view.state.selection.main;
1743
+ const firstChar = update2.view.state.doc.sliceString(activeRange.from, activeRange.from + 1);
1744
+ const shouldRemove = firstChar !== trigger || // Trigger deleted.
1745
+ selection.head < activeRange.from || // Cursor moved before the range.
1746
+ selection.head > activeRange.to + 1;
1747
+ const nextRange = shouldRemove ? null : update2.docChanged ? {
1748
+ from: activeRange.from,
1749
+ to: selection.head
1750
+ } : activeRange;
1751
+ if (nextRange !== activeRange) {
1752
+ update2.view.dispatch({
1753
+ effects: commandRangeEffect.of(nextRange ? {
1754
+ trigger,
1755
+ range: nextRange
1756
+ } : null)
1757
+ });
1758
+ }
1759
+ if (shouldRemove) {
1760
+ options.onDeactivate?.();
1761
+ }
1762
+ });
1763
+ return [
1764
+ multilinePlaceholder(options.placeholder ?? `Press '${Array.isArray(options.trigger) ? options.trigger[0] : options.trigger}' for commands`),
1765
+ Prec.highest(commandKeymap),
1766
+ updateListener,
1767
+ commandMenuState,
1768
+ commandMenuPlugin
1769
+ ];
1770
+ };
1771
+ var useCommandMenu = ({ viewRef, trigger, placeholder: placeholder2, getGroups }) => {
1772
+ const triggerRef = useRef(null);
1773
+ const currentRef = useRef(null);
1774
+ const groupsRef = useRef([]);
1775
+ const [currentItem, setCurrentItem] = useState();
1776
+ const [open, setOpen] = useState(false);
1777
+ const [_, update2] = useState({});
1778
+ const handleOpenChange = useCallback(async (open2, trigger2) => {
1779
+ if (open2 && trigger2) {
1780
+ groupsRef.current = await getGroups(trigger2);
1781
+ }
1782
+ setOpen(open2);
1783
+ if (!open2) {
1784
+ triggerRef.current = null;
1785
+ setCurrentItem(void 0);
1786
+ viewRef.current?.dispatch({
1787
+ effects: [
1788
+ commandRangeEffect.of(null)
1789
+ ]
1790
+ });
1791
+ }
1792
+ }, [
1793
+ getGroups
1794
+ ]);
1795
+ const handleActivate = useCallback(async (event) => {
1796
+ const item = getItem(groupsRef.current, currentItem);
1797
+ if (item) {
1798
+ currentRef.current = item;
1799
+ }
1800
+ triggerRef.current = event.trigger;
1801
+ const triggerKey = event.trigger.getAttribute("data-trigger");
1802
+ if (!open && triggerKey) {
1803
+ await handleOpenChange(true, triggerKey);
1804
+ }
1805
+ }, [
1806
+ open,
1807
+ handleOpenChange
1808
+ ]);
1809
+ const handleSelect = useCallback((item) => {
1810
+ const view = viewRef.current;
1811
+ if (!view) {
1812
+ return;
1813
+ }
1814
+ const selection = view.state.selection.main;
1815
+ void item.onSelect?.(view, selection.head);
1816
+ }, []);
1817
+ const serializedTrigger = Array.isArray(trigger) ? trigger.join(",") : trigger;
1818
+ const _commandMenu = useMemo2(() => commandMenu({
1819
+ trigger,
1820
+ placeholder: placeholder2,
1821
+ onArrowDown: () => {
1822
+ setCurrentItem((currentItem2) => {
1823
+ const next = getNextItem(groupsRef.current, currentItem2);
1824
+ currentRef.current = next;
1825
+ return next.id;
1826
+ });
1827
+ },
1828
+ onArrowUp: () => {
1829
+ setCurrentItem((currentItem2) => {
1830
+ const previous = getPreviousItem(groupsRef.current, currentItem2);
1831
+ currentRef.current = previous;
1832
+ return previous.id;
1833
+ });
1834
+ },
1835
+ onDeactivate: () => handleOpenChange(false),
1836
+ onEnter: () => {
1837
+ if (currentRef.current) {
1838
+ handleSelect(currentRef.current);
1839
+ }
1840
+ },
1841
+ onTextChange: async (trigger2, text) => {
1842
+ groupsRef.current = await getGroups(trigger2, text);
1843
+ const firstItem = groupsRef.current.filter((group) => group.items.length > 0)[0]?.items[0];
1844
+ if (firstItem) {
1845
+ setCurrentItem(firstItem.id);
1846
+ currentRef.current = firstItem;
1847
+ }
1848
+ update2({});
1849
+ }
1850
+ }), [
1851
+ handleOpenChange,
1852
+ getGroups,
1853
+ serializedTrigger,
1854
+ placeholder2
1855
+ ]);
1856
+ return {
1857
+ commandMenu: _commandMenu,
1858
+ currentItem,
1859
+ groupsRef,
1860
+ ref: triggerRef,
1861
+ open,
1862
+ onActivate: handleActivate,
1863
+ onOpenChange: setOpen,
1864
+ onSelect: handleSelect
1865
+ };
1866
+ };
1545
1867
 
1546
1868
  // packages/ui/react-ui-editor/src/extensions/command/typeahead.ts
1547
- import { EditorSelection, Prec, RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
1548
- import { Decoration as Decoration4, keymap as keymap4, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
1869
+ import { EditorSelection, Prec as Prec2, RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
1870
+ import { Decoration as Decoration6, keymap as keymap5, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
1549
1871
  var typeahead = ({ onComplete } = {}) => {
1550
1872
  let hint;
1551
1873
  const complete = (view) => {
@@ -1566,12 +1888,12 @@ var typeahead = ({ onComplete } = {}) => {
1566
1888
  return true;
1567
1889
  };
1568
1890
  return [
1569
- ViewPlugin6.fromClass(class {
1891
+ ViewPlugin7.fromClass(class {
1570
1892
  constructor() {
1571
- this.decorations = Decoration4.none;
1893
+ this.decorations = Decoration6.none;
1572
1894
  }
1573
1895
  update(update2) {
1574
- const builder = new RangeSetBuilder3();
1896
+ const builder = new RangeSetBuilder4();
1575
1897
  const selection = update2.view.state.selection.main;
1576
1898
  const line = update2.view.state.doc.lineAt(selection.from);
1577
1899
  if (selection.from === selection.to && selection.from === line.to) {
@@ -1580,7 +1902,7 @@ var typeahead = ({ onComplete } = {}) => {
1580
1902
  line: str
1581
1903
  });
1582
1904
  if (hint) {
1583
- builder.add(selection.from, selection.to, Decoration4.widget({
1905
+ builder.add(selection.from, selection.to, Decoration6.widget({
1584
1906
  widget: new Hint(hint)
1585
1907
  }));
1586
1908
  }
@@ -1591,7 +1913,7 @@ var typeahead = ({ onComplete } = {}) => {
1591
1913
  decorations: (v) => v.decorations
1592
1914
  }),
1593
1915
  // Keys.
1594
- Prec.highest(keymap4.of([
1916
+ Prec2.highest(keymap5.of([
1595
1917
  {
1596
1918
  key: "Tab",
1597
1919
  preventDefault: true,
@@ -1628,8 +1950,8 @@ var matchCompletion = (completion, word) => {
1628
1950
 
1629
1951
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1630
1952
  import { invertedEffects } from "@codemirror/commands";
1631
- import { StateEffect as StateEffect3, StateField as StateField3 } from "@codemirror/state";
1632
- import { hoverTooltip, keymap as keymap6, Decoration as Decoration5, EditorView as EditorView9, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
1953
+ import { StateEffect as StateEffect4, StateField as StateField4 } from "@codemirror/state";
1954
+ import { hoverTooltip, keymap as keymap7, Decoration as Decoration7, EditorView as EditorView10, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
1633
1955
  import sortBy from "lodash.sortby";
1634
1956
  import { useEffect } from "react";
1635
1957
  import { debounce as debounce2 } from "@dxos/async";
@@ -1638,7 +1960,7 @@ import { isNonNullable } from "@dxos/util";
1638
1960
 
1639
1961
  // packages/ui/react-ui-editor/src/extensions/selection.ts
1640
1962
  import { Transaction } from "@codemirror/state";
1641
- import { EditorView as EditorView8, keymap as keymap5 } from "@codemirror/view";
1963
+ import { EditorView as EditorView9, keymap as keymap6 } from "@codemirror/view";
1642
1964
  import { debounce } from "@dxos/async";
1643
1965
  import { invariant as invariant3 } from "@dxos/invariant";
1644
1966
  import { isNotFalsy } from "@dxos/util";
@@ -1649,7 +1971,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
1649
1971
  return {
1650
1972
  selection,
1651
1973
  scrollIntoView: !scrollTo,
1652
- effects: scrollTo ? EditorView8.scrollIntoView(scrollTo, {
1974
+ effects: scrollTo ? EditorView9.scrollIntoView(scrollTo, {
1653
1975
  yMargin: 96
1654
1976
  }) : void 0,
1655
1977
  annotations: Transaction.userEvent.of(stateRestoreAnnotation)
@@ -1691,7 +2013,7 @@ var selectionState = ({ getState, setState } = {}) => {
1691
2013
  // setStateDebounced(id, {});
1692
2014
  // },
1693
2015
  // }),
1694
- EditorView8.updateListener.of(({ view, transactions }) => {
2016
+ EditorView9.updateListener.of(({ view, transactions }) => {
1695
2017
  const id = view.state.facet(documentId);
1696
2018
  if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
1697
2019
  return;
@@ -1714,7 +2036,7 @@ var selectionState = ({ getState, setState } = {}) => {
1714
2036
  }
1715
2037
  }
1716
2038
  }),
1717
- getState && keymap5.of([
2039
+ getState && keymap6.of([
1718
2040
  {
1719
2041
  key: "ctrl-r",
1720
2042
  run: (view) => {
@@ -1731,10 +2053,10 @@ var selectionState = ({ getState, setState } = {}) => {
1731
2053
 
1732
2054
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1733
2055
  var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
1734
- var setComments = StateEffect3.define();
1735
- var setSelection = StateEffect3.define();
1736
- var setCommentState = StateEffect3.define();
1737
- var commentsState = StateField3.define({
2056
+ var setComments = StateEffect4.define();
2057
+ var setSelection = StateEffect4.define();
2058
+ var setCommentState = StateEffect4.define();
2059
+ var commentsState = StateField4.define({
1738
2060
  create: (state) => ({
1739
2061
  id: state.facet(documentId),
1740
2062
  comments: [],
@@ -1772,7 +2094,7 @@ var commentsState = StateField3.define({
1772
2094
  return value;
1773
2095
  }
1774
2096
  });
1775
- var styles2 = EditorView9.theme({
2097
+ var styles2 = EditorView10.theme({
1776
2098
  ".cm-comment, .cm-comment-current": {
1777
2099
  margin: "0 -3px",
1778
2100
  padding: "3px",
@@ -1785,14 +2107,14 @@ var styles2 = EditorView9.theme({
1785
2107
  textDecoration: "underline"
1786
2108
  }
1787
2109
  });
1788
- var createCommentMark = (id, isCurrent) => Decoration5.mark({
2110
+ var createCommentMark = (id, isCurrent) => Decoration7.mark({
1789
2111
  class: isCurrent ? "cm-comment-current" : "cm-comment",
1790
2112
  attributes: {
1791
2113
  "data-testid": "cm-comment",
1792
2114
  "data-comment-id": id
1793
2115
  }
1794
2116
  });
1795
- var commentsDecorations = EditorView9.decorations.compute([
2117
+ var commentsDecorations = EditorView10.decorations.compute([
1796
2118
  commentsState
1797
2119
  ], (state) => {
1798
2120
  const { selection: { current }, comments: comments2 } = state.field(commentsState);
@@ -1812,10 +2134,10 @@ var commentsDecorations = EditorView9.decorations.compute([
1812
2134
  const mark = createCommentMark(comment.comment.id, comment.comment.id === current);
1813
2135
  return mark.range(range.from, range.to);
1814
2136
  }).filter(isNonNullable);
1815
- return Decoration5.set(decorations2);
2137
+ return Decoration7.set(decorations2);
1816
2138
  });
1817
- var commentClickedEffect = StateEffect3.define();
1818
- var handleCommentClick = EditorView9.domEventHandlers({
2139
+ var commentClickedEffect = StateEffect4.define();
2140
+ var handleCommentClick = EditorView10.domEventHandlers({
1819
2141
  click: (event, view) => {
1820
2142
  let target = event.target;
1821
2143
  const editorRoot = view.dom;
@@ -1854,7 +2176,7 @@ var trackPastedComments = (onUpdate) => {
1854
2176
  }
1855
2177
  };
1856
2178
  return [
1857
- EditorView9.domEventHandlers({
2179
+ EditorView10.domEventHandlers({
1858
2180
  cut: handleTrack,
1859
2181
  copy: handleTrack
1860
2182
  }),
@@ -1876,7 +2198,7 @@ var trackPastedComments = (onUpdate) => {
1876
2198
  return effects;
1877
2199
  }),
1878
2200
  // Handle paste or the undo of comment deletion.
1879
- EditorView9.updateListener.of((update2) => {
2201
+ EditorView10.updateListener.of((update2) => {
1880
2202
  const restore = [];
1881
2203
  for (let i = 0; i < update2.transactions.length; i++) {
1882
2204
  const tr = update2.transactions[i];
@@ -1932,7 +2254,7 @@ var mapTrackedComment = (comment, changes) => ({
1932
2254
  from: changes.mapPos(comment.from, 1),
1933
2255
  to: changes.mapPos(comment.to, 1)
1934
2256
  });
1935
- var restoreCommentEffect = StateEffect3.define({
2257
+ var restoreCommentEffect = StateEffect4.define({
1936
2258
  map: mapTrackedComment
1937
2259
  });
1938
2260
  var createComment = (view) => {
@@ -1977,7 +2299,7 @@ var comments = (options = {}) => {
1977
2299
  //
1978
2300
  // Keymap.
1979
2301
  //
1980
- options.onCreate && keymap6.of([
2302
+ options.onCreate && keymap7.of([
1981
2303
  {
1982
2304
  key: shortcut,
1983
2305
  run: callbackWrapper(createComment)
@@ -2018,7 +2340,7 @@ var comments = (options = {}) => {
2018
2340
  //
2019
2341
  // Track deleted ranges and update ranges for decorations.
2020
2342
  //
2021
- EditorView9.updateListener.of(({ view, state, changes }) => {
2343
+ EditorView10.updateListener.of(({ view, state, changes }) => {
2022
2344
  let mod = false;
2023
2345
  const { comments: comments2, ...value } = state.field(commentsState);
2024
2346
  changes.iterChanges((from, to, from2, to2) => {
@@ -2050,7 +2372,7 @@ var comments = (options = {}) => {
2050
2372
  //
2051
2373
  // Track selection/proximity.
2052
2374
  //
2053
- EditorView9.updateListener.of(({ view, state }) => {
2375
+ EditorView10.updateListener.of(({ view, state }) => {
2054
2376
  let min = Infinity;
2055
2377
  const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
2056
2378
  const { head } = state.selection.main;
@@ -2104,7 +2426,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
2104
2426
  anchor: range.from
2105
2427
  } : void 0,
2106
2428
  effects: [
2107
- needsScroll ? EditorView9.scrollIntoView(range.from, center ? {
2429
+ needsScroll ? EditorView10.scrollIntoView(range.from, center ? {
2108
2430
  y: "center"
2109
2431
  } : void 0) : [],
2110
2432
  needsSelectionUpdate ? setSelection.of({
@@ -2134,7 +2456,7 @@ var ExternalCommentSync = class {
2134
2456
  this.unsubscribe = subscribe(updateComments);
2135
2457
  }
2136
2458
  };
2137
- var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin7.fromClass(class {
2459
+ var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin8.fromClass(class {
2138
2460
  constructor(view) {
2139
2461
  return new ExternalCommentSync(view, id, subscribe, getComments);
2140
2462
  }
@@ -2156,20 +2478,20 @@ var useComments = (view, id, comments2) => {
2156
2478
 
2157
2479
  // packages/ui/react-ui-editor/src/extensions/debug.ts
2158
2480
  import { syntaxTree } from "@codemirror/language";
2159
- import { StateField as StateField4 } from "@codemirror/state";
2481
+ import { StateField as StateField5 } from "@codemirror/state";
2160
2482
  var debugNodeLogger = (log9 = console.log) => {
2161
2483
  const logTokens = (state) => syntaxTree(state).iterate({
2162
2484
  enter: (node) => log9(node.type)
2163
2485
  });
2164
- return StateField4.define({
2486
+ return StateField5.define({
2165
2487
  create: (state) => logTokens(state),
2166
2488
  update: (_, tr) => logTokens(tr.state)
2167
2489
  });
2168
2490
  };
2169
2491
 
2170
2492
  // packages/ui/react-ui-editor/src/extensions/dnd.ts
2171
- import { dropCursor, EditorView as EditorView10 } from "@codemirror/view";
2172
- var styles3 = EditorView10.theme({
2493
+ import { dropCursor, EditorView as EditorView11 } from "@codemirror/view";
2494
+ var styles3 = EditorView11.theme({
2173
2495
  ".cm-dropCursor": {
2174
2496
  borderLeft: "2px solid var(--dx-accentText)",
2175
2497
  color: "var(--dx-accentText)",
@@ -2183,7 +2505,7 @@ var dropFile = (options = {}) => {
2183
2505
  return [
2184
2506
  styles3,
2185
2507
  dropCursor(),
2186
- EditorView10.domEventHandlers({
2508
+ EditorView11.domEventHandlers({
2187
2509
  drop: (event, view) => {
2188
2510
  event.preventDefault();
2189
2511
  const files = event.dataTransfer?.files;
@@ -2210,7 +2532,7 @@ import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@cod
2210
2532
  import { searchKeymap } from "@codemirror/search";
2211
2533
  import { EditorState } from "@codemirror/state";
2212
2534
  import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
2213
- import { EditorView as EditorView12, ViewPlugin as ViewPlugin8, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap7, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
2535
+ import { EditorView as EditorView14, ViewPlugin as ViewPlugin9, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap8, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
2214
2536
  import defaultsDeep2 from "lodash.defaultsdeep";
2215
2537
  import merge from "lodash.merge";
2216
2538
  import { generateName } from "@dxos/display-name";
@@ -2218,10 +2540,10 @@ import { log as log5 } from "@dxos/log";
2218
2540
  import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
2219
2541
 
2220
2542
  // packages/ui/react-ui-editor/src/extensions/focus.ts
2221
- import { StateEffect as StateEffect4, StateField as StateField5 } from "@codemirror/state";
2222
- import { EditorView as EditorView11 } from "@codemirror/view";
2223
- var focusEffect = StateEffect4.define();
2224
- var focusField = StateField5.define({
2543
+ import { StateEffect as StateEffect5, StateField as StateField6 } from "@codemirror/state";
2544
+ import { EditorView as EditorView12 } from "@codemirror/view";
2545
+ var focusEffect = StateEffect5.define();
2546
+ var focusField = StateField6.define({
2225
2547
  create: () => false,
2226
2548
  update: (value, tr) => {
2227
2549
  for (const effect of tr.effects) {
@@ -2234,7 +2556,7 @@ var focusField = StateField5.define({
2234
2556
  });
2235
2557
  var focus = [
2236
2558
  focusField,
2237
- EditorView11.domEventHandlers({
2559
+ EditorView12.domEventHandlers({
2238
2560
  focus: (event, view) => {
2239
2561
  setTimeout(() => view.dispatch({
2240
2562
  effects: focusEffect.of(true)
@@ -2248,6 +2570,10 @@ var focus = [
2248
2570
  })
2249
2571
  ];
2250
2572
 
2573
+ // packages/ui/react-ui-editor/src/defaults.ts
2574
+ import { EditorView as EditorView13 } from "@codemirror/view";
2575
+ import { mx as mx2 } from "@dxos/react-ui-theme";
2576
+
2251
2577
  // packages/ui/react-ui-editor/src/styles/markdown.ts
2252
2578
  import { mx } from "@dxos/react-ui-theme";
2253
2579
  var headings = {
@@ -2489,6 +2815,31 @@ var defaultTheme = {
2489
2815
  }
2490
2816
  };
2491
2817
 
2818
+ // packages/ui/react-ui-editor/src/defaults.ts
2819
+ var editorWidth = "!mli-auto is-full max-is-[min(50rem,100%-4rem)]";
2820
+ var editorSlots = {
2821
+ scroll: {
2822
+ className: "pbs-2"
2823
+ },
2824
+ content: {
2825
+ className: editorWidth
2826
+ }
2827
+ };
2828
+ var editorGutter = EditorView13.theme({
2829
+ ".cm-gutters": {
2830
+ background: "var(--dx-baseSurface)",
2831
+ paddingRight: "1rem"
2832
+ }
2833
+ });
2834
+ var editorMonospace = EditorView13.theme({
2835
+ ".cm-content": {
2836
+ fontFamily: fontMono
2837
+ }
2838
+ });
2839
+ var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
2840
+ var stackItemContentEditorClassNames = (role) => mx2("attention-surface dx-focus-ring-inset data-[toolbar=disabled]:pbs-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24" : "min-bs-0");
2841
+ var stackItemContentToolbarClassNames = (role) => mx2("relative z-[1] flex is-full bg-toolbarSurface border-be border-subduedSeparator", role === "section" && "sticky block-start-0 -mbe-px min-is-0");
2842
+
2492
2843
  // packages/ui/react-ui-editor/src/extensions/factories.ts
2493
2844
  var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
2494
2845
  var preventNewline = EditorState.transactionFilter.of((tr) => tr.newDoc.lines > 1 ? [] : tr);
@@ -2513,10 +2864,10 @@ var createBasicExtensions = (_props) => {
2513
2864
  const props = defaultsDeep2({}, _props, defaultBasicOptions);
2514
2865
  return [
2515
2866
  // NOTE: Doesn't catch errors in keymap functions.
2516
- EditorView12.exceptionSink.of((err) => {
2867
+ EditorView14.exceptionSink.of((err) => {
2517
2868
  log5.catch(err, void 0, {
2518
2869
  F: __dxlog_file8,
2519
- L: 98,
2870
+ L: 100,
2520
2871
  S: void 0,
2521
2872
  C: (f, a) => f(...a)
2522
2873
  });
@@ -2528,18 +2879,22 @@ var createBasicExtensions = (_props) => {
2528
2879
  props.drawSelection && drawSelection({
2529
2880
  cursorBlinkRate: 1200
2530
2881
  }),
2531
- props.editable !== void 0 && EditorView12.editable.of(props.editable),
2882
+ props.editable !== void 0 && EditorView14.editable.of(props.editable),
2532
2883
  props.focus && focus,
2533
2884
  props.highlightActiveLine && highlightActiveLine(),
2534
2885
  props.history && history(),
2535
- props.lineNumbers && lineNumbers(),
2536
- props.lineWrapping && EditorView12.lineWrapping,
2886
+ props.lineNumbers && [
2887
+ lineNumbers(),
2888
+ editorGutter
2889
+ ],
2890
+ props.lineWrapping && EditorView14.lineWrapping,
2891
+ props.monospace && editorMonospace,
2537
2892
  props.placeholder && placeholder(props.placeholder),
2538
2893
  props.readOnly !== void 0 && EditorState.readOnly.of(props.readOnly),
2539
2894
  props.scrollPastEnd && scrollPastEnd(),
2540
2895
  props.tabSize && EditorState.tabSize.of(props.tabSize),
2541
2896
  // https://codemirror.net/docs/ref/#view.KeyBinding
2542
- keymap7.of([
2897
+ keymap8.of([
2543
2898
  ...(props.keymap && keymaps[props.keymap]) ?? [],
2544
2899
  // NOTE: Tabs are also configured by markdown extension.
2545
2900
  // https://codemirror.net/docs/ref/#commands.indentWithTab
@@ -2570,17 +2925,17 @@ var defaultThemeSlots = {
2570
2925
  var createThemeExtensions = ({ themeMode, styles: styles4, syntaxHighlighting: _syntaxHighlighting, slots: _slots } = {}) => {
2571
2926
  const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
2572
2927
  return [
2573
- EditorView12.darkTheme.of(themeMode === "dark"),
2574
- EditorView12.baseTheme(styles4 ? merge({}, defaultTheme, styles4) : defaultTheme),
2928
+ EditorView14.darkTheme.of(themeMode === "dark"),
2929
+ EditorView14.baseTheme(styles4 ? merge({}, defaultTheme, styles4) : defaultTheme),
2575
2930
  // https://github.com/codemirror/theme-one-dark
2576
2931
  _syntaxHighlighting && (themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)),
2577
- slots.editor?.className && EditorView12.editorAttributes.of({
2932
+ slots.editor?.className && EditorView14.editorAttributes.of({
2578
2933
  class: slots.editor.className
2579
2934
  }),
2580
- slots.content?.className && EditorView12.contentAttributes.of({
2935
+ slots.content?.className && EditorView14.contentAttributes.of({
2581
2936
  class: slots.content.className
2582
2937
  }),
2583
- slots.scroll?.className && ViewPlugin8.fromClass(class {
2938
+ slots.scroll?.className && ViewPlugin9.fromClass(class {
2584
2939
  constructor(view) {
2585
2940
  view.scrollDOM.classList.add(slots.scroll.className);
2586
2941
  }
@@ -2611,7 +2966,7 @@ var createDataExtensions = ({ id, text, space, identity }) => {
2611
2966
 
2612
2967
  // packages/ui/react-ui-editor/src/extensions/folding.tsx
2613
2968
  import { codeFolding, foldGutter } from "@codemirror/language";
2614
- import { EditorView as EditorView13 } from "@codemirror/view";
2969
+ import { EditorView as EditorView15 } from "@codemirror/view";
2615
2970
  import React2 from "react";
2616
2971
  import { Icon } from "@dxos/react-ui";
2617
2972
  var folding = (_props = {}) => [
@@ -2635,7 +2990,7 @@ var folding = (_props = {}) => [
2635
2990
  }));
2636
2991
  }
2637
2992
  }),
2638
- EditorView13.theme({
2993
+ EditorView15.theme({
2639
2994
  ".cm-foldGutter": {
2640
2995
  opacity: 0.3,
2641
2996
  transition: "opacity 0.3s",
@@ -2647,6 +3002,49 @@ var folding = (_props = {}) => [
2647
3002
  })
2648
3003
  ];
2649
3004
 
3005
+ // packages/ui/react-ui-editor/src/extensions/hashtag.tsx
3006
+ import { Decoration as Decoration8, EditorView as EditorView16, MatchDecorator, ViewPlugin as ViewPlugin10, WidgetType as WidgetType4 } from "@codemirror/view";
3007
+ import { getHashColor, mx as mx3 } from "@dxos/react-ui-theme";
3008
+ var TagWidget = class extends WidgetType4 {
3009
+ constructor(_text) {
3010
+ super(), this._text = _text;
3011
+ }
3012
+ toDOM() {
3013
+ const span = document.createElement("span");
3014
+ span.className = mx3("cm-tag", getHashColor(this._text).tag);
3015
+ span.textContent = this._text;
3016
+ return span;
3017
+ }
3018
+ };
3019
+ var tagMatcher = new MatchDecorator({
3020
+ regexp: /#(\w+)\W/g,
3021
+ decoration: (match) => Decoration8.replace({
3022
+ widget: new TagWidget(match[1])
3023
+ })
3024
+ });
3025
+ var hashtag = () => [
3026
+ ViewPlugin10.fromClass(class {
3027
+ constructor(view) {
3028
+ this.tags = tagMatcher.createDeco(view);
3029
+ }
3030
+ update(update2) {
3031
+ this.tags = tagMatcher.updateDeco(update2, this.tags);
3032
+ }
3033
+ }, {
3034
+ decorations: (instance) => instance.tags,
3035
+ provide: (plugin) => EditorView16.atomicRanges.of((view) => {
3036
+ return view.plugin(plugin)?.tags || Decoration8.none;
3037
+ })
3038
+ }),
3039
+ EditorView16.theme({
3040
+ ".cm-tag": {
3041
+ borderRadius: "4px",
3042
+ marginRight: "6px",
3043
+ padding: "2px 6px"
3044
+ }
3045
+ })
3046
+ ];
3047
+
2650
3048
  // packages/ui/react-ui-editor/src/extensions/json.ts
2651
3049
  import { json, jsonParseLinter } from "@codemirror/lang-json";
2652
3050
  import { linter } from "@codemirror/lint";
@@ -2655,7 +3053,8 @@ var createJsonExtensions = ({ schema } = {}) => {
2655
3053
  let lintSource = jsonParseLinter();
2656
3054
  if (schema) {
2657
3055
  const ajv = new Ajv({
2658
- allErrors: false
3056
+ allErrors: false,
3057
+ strict: false
2659
3058
  });
2660
3059
  const validate = ajv.compile(schema);
2661
3060
  lintSource = schemaLinter(validate);
@@ -2692,14 +3091,14 @@ var schemaLinter = (validate) => (view) => {
2692
3091
  };
2693
3092
 
2694
3093
  // packages/ui/react-ui-editor/src/extensions/listener.ts
2695
- import { EditorView as EditorView14 } from "@codemirror/view";
3094
+ import { EditorView as EditorView17 } from "@codemirror/view";
2696
3095
  var listener = ({ onFocus, onChange }) => {
2697
3096
  const extensions = [];
2698
- onFocus && extensions.push(EditorView14.focusChangeEffect.of((_, focusing) => {
3097
+ onFocus && extensions.push(EditorView17.focusChangeEffect.of((_, focusing) => {
2699
3098
  onFocus(focusing);
2700
3099
  return null;
2701
3100
  }));
2702
- onChange && extensions.push(EditorView14.updateListener.of((update2) => {
3101
+ onChange && extensions.push(EditorView17.updateListener.of((update2) => {
2703
3102
  onChange(update2.state.doc.toString(), update2.state.facet(documentId));
2704
3103
  }));
2705
3104
  return extensions;
@@ -2709,8 +3108,8 @@ var listener = ({ onFocus, onChange }) => {
2709
3108
  import { snippet } from "@codemirror/autocomplete";
2710
3109
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
2711
3110
  import { EditorSelection as EditorSelection2 } from "@codemirror/state";
2712
- import { EditorView as EditorView15, keymap as keymap8 } from "@codemirror/view";
2713
- import { useMemo as useMemo2 } from "react";
3111
+ import { EditorView as EditorView18, keymap as keymap9 } from "@codemirror/view";
3112
+ import { useMemo as useMemo3 } from "react";
2714
3113
  var formattingEquals = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
2715
3114
  var Inline = /* @__PURE__ */ function(Inline2) {
2716
3115
  Inline2[Inline2["Strong"] = 0] = "Strong";
@@ -3597,7 +3996,7 @@ var toggleCodeblock = (target) => {
3597
3996
  };
3598
3997
  var formattingKeymap = (_options = {}) => {
3599
3998
  return [
3600
- keymap8.of([
3999
+ keymap9.of([
3601
4000
  {
3602
4001
  key: "meta-b",
3603
4002
  run: toggleStrong
@@ -3798,7 +4197,7 @@ var getFormatting = (state) => {
3798
4197
  };
3799
4198
  };
3800
4199
  var useFormattingState = (state) => {
3801
- return useMemo2(() => EditorView15.updateListener.of((update2) => {
4200
+ return useMemo3(() => EditorView18.updateListener.of((update2) => {
3802
4201
  if (update2.docChanged || update2.selectionSet) {
3803
4202
  Object.entries(getFormatting(update2.state)).forEach(([key, active]) => {
3804
4203
  state[key] = active;
@@ -3863,7 +4262,7 @@ import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lan
3863
4262
  import { syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
3864
4263
  import { languages } from "@codemirror/language-data";
3865
4264
  import { lintKeymap } from "@codemirror/lint";
3866
- import { keymap as keymap9 } from "@codemirror/view";
4265
+ import { keymap as keymap10 } from "@codemirror/view";
3867
4266
  import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
3868
4267
 
3869
4268
  // packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
@@ -4070,7 +4469,7 @@ var createMarkdownExtensions = (options = {}) => {
4070
4469
  }),
4071
4470
  // Custom styles.
4072
4471
  syntaxHighlighting2(markdownHighlightStyle()),
4073
- keymap9.of([
4472
+ keymap10.of([
4074
4473
  // https://codemirror.net/docs/ref/#commands.indentWithTab
4075
4474
  options.indentWithTab !== false && indentWithTab2,
4076
4475
  // https://codemirror.net/docs/ref/#commands.defaultKeymap
@@ -4083,8 +4482,8 @@ var createMarkdownExtensions = (options = {}) => {
4083
4482
 
4084
4483
  // packages/ui/react-ui-editor/src/extensions/markdown/debug.ts
4085
4484
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
4086
- import { StateField as StateField6 } from "@codemirror/state";
4087
- var debugTree = (cb) => StateField6.define({
4485
+ import { StateField as StateField7 } from "@codemirror/state";
4486
+ var debugTree = (cb) => StateField7.define({
4088
4487
  create: (state) => cb(convertTreeToJson(state)),
4089
4488
  update: (value, tr) => cb(convertTreeToJson(tr.state))
4090
4489
  });
@@ -4110,17 +4509,17 @@ var convertTreeToJson = (state) => {
4110
4509
 
4111
4510
  // packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
4112
4511
  import { syntaxTree as syntaxTree7 } from "@codemirror/language";
4113
- import { RangeSetBuilder as RangeSetBuilder5, StateEffect as StateEffect5 } from "@codemirror/state";
4114
- import { EditorView as EditorView19, Decoration as Decoration8, WidgetType as WidgetType5, ViewPlugin as ViewPlugin10 } from "@codemirror/view";
4512
+ import { RangeSetBuilder as RangeSetBuilder6, StateEffect as StateEffect6 } from "@codemirror/state";
4513
+ import { EditorView as EditorView22, Decoration as Decoration11, WidgetType as WidgetType7, ViewPlugin as ViewPlugin12 } from "@codemirror/view";
4115
4514
  import { invariant as invariant4 } from "@dxos/invariant";
4116
- import { mx as mx2 } from "@dxos/react-ui-theme";
4515
+ import { mx as mx4 } from "@dxos/react-ui-theme";
4117
4516
 
4118
4517
  // packages/ui/react-ui-editor/src/extensions/markdown/changes.ts
4119
4518
  import { syntaxTree as syntaxTree4 } from "@codemirror/language";
4120
4519
  import { Transaction as Transaction2 } from "@codemirror/state";
4121
- import { ViewPlugin as ViewPlugin9 } from "@codemirror/view";
4520
+ import { ViewPlugin as ViewPlugin11 } from "@codemirror/view";
4122
4521
  var adjustChanges = () => {
4123
- return ViewPlugin9.fromClass(class {
4522
+ return ViewPlugin11.fromClass(class {
4124
4523
  update(update2) {
4125
4524
  const tree = syntaxTree4(update2.state);
4126
4525
  const adjustments = [];
@@ -4261,13 +4660,13 @@ var getValidUrl = (str) => {
4261
4660
 
4262
4661
  // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
4263
4662
  import { syntaxTree as syntaxTree5 } from "@codemirror/language";
4264
- import { StateField as StateField7 } from "@codemirror/state";
4265
- import { Decoration as Decoration6, EditorView as EditorView16, WidgetType as WidgetType3 } from "@codemirror/view";
4663
+ import { StateField as StateField8 } from "@codemirror/state";
4664
+ import { Decoration as Decoration9, EditorView as EditorView19, WidgetType as WidgetType5 } from "@codemirror/view";
4266
4665
  var image = (_options = {}) => {
4267
4666
  return [
4268
- StateField7.define({
4667
+ StateField8.define({
4269
4668
  create: (state) => {
4270
- return Decoration6.set(buildDecorations(0, state.doc.length, state));
4669
+ return Decoration9.set(buildDecorations(0, state.doc.length, state));
4271
4670
  },
4272
4671
  update: (value, tr) => {
4273
4672
  if (!tr.docChanged && !tr.selection) {
@@ -4290,7 +4689,7 @@ var image = (_options = {}) => {
4290
4689
  add: buildDecorations(from, to, tr.state)
4291
4690
  });
4292
4691
  },
4293
- provide: (field) => EditorView16.decorations.from(field)
4692
+ provide: (field) => EditorView19.decorations.from(field)
4294
4693
  })
4295
4694
  ];
4296
4695
  };
@@ -4308,7 +4707,7 @@ var buildDecorations = (from, to, state) => {
4308
4707
  return;
4309
4708
  }
4310
4709
  preloadImage(url);
4311
- decorations2.push(Decoration6.replace({
4710
+ decorations2.push(Decoration9.replace({
4312
4711
  block: true,
4313
4712
  widget: new ImageWidget(url)
4314
4713
  }).range(hide2 ? node.from : node.to, node.to));
@@ -4328,7 +4727,7 @@ var preloadImage = (url) => {
4328
4727
  preloaded.add(url);
4329
4728
  }
4330
4729
  };
4331
- var ImageWidget = class extends WidgetType3 {
4730
+ var ImageWidget = class extends WidgetType5 {
4332
4731
  constructor(_url) {
4333
4732
  super(), this._url = _url;
4334
4733
  }
@@ -4349,10 +4748,10 @@ var ImageWidget = class extends WidgetType3 {
4349
4748
  };
4350
4749
 
4351
4750
  // packages/ui/react-ui-editor/src/extensions/markdown/styles.ts
4352
- import { EditorView as EditorView17 } from "@codemirror/view";
4751
+ import { EditorView as EditorView20 } from "@codemirror/view";
4353
4752
  var bulletListIndentationWidth = 24;
4354
4753
  var orderedListIndentationWidth = 36;
4355
- var formattingStyles = EditorView17.theme({
4754
+ var formattingStyles = EditorView20.theme({
4356
4755
  /**
4357
4756
  * Horizontal rule.
4358
4757
  */
@@ -4473,17 +4872,17 @@ var formattingStyles = EditorView17.theme({
4473
4872
 
4474
4873
  // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
4475
4874
  import { syntaxTree as syntaxTree6 } from "@codemirror/language";
4476
- import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField8 } from "@codemirror/state";
4477
- import { Decoration as Decoration7, EditorView as EditorView18, WidgetType as WidgetType4 } from "@codemirror/view";
4875
+ import { RangeSetBuilder as RangeSetBuilder5, StateField as StateField9 } from "@codemirror/state";
4876
+ import { Decoration as Decoration10, EditorView as EditorView21, WidgetType as WidgetType6 } from "@codemirror/view";
4478
4877
  var table = (options = {}) => {
4479
- return StateField8.define({
4878
+ return StateField9.define({
4480
4879
  create: (state) => update(state, options),
4481
4880
  update: (_, tr) => update(tr.state, options),
4482
- provide: (field) => EditorView18.decorations.from(field)
4881
+ provide: (field) => EditorView21.decorations.from(field)
4483
4882
  });
4484
4883
  };
4485
4884
  var update = (state, _options) => {
4486
- const builder = new RangeSetBuilder4();
4885
+ const builder = new RangeSetBuilder5();
4487
4886
  const cursor = state.selection.main.head;
4488
4887
  const tables = [];
4489
4888
  const getTable = () => tables[tables.length - 1];
@@ -4524,19 +4923,19 @@ var update = (state, _options) => {
4524
4923
  tables.forEach((table2) => {
4525
4924
  const replace = state.readOnly || cursor < table2.from || cursor > table2.to;
4526
4925
  if (replace) {
4527
- builder.add(table2.from, table2.to, Decoration7.replace({
4926
+ builder.add(table2.from, table2.to, Decoration10.replace({
4528
4927
  block: true,
4529
4928
  widget: new TableWidget(table2)
4530
4929
  }));
4531
4930
  } else {
4532
- builder.add(table2.from, table2.to, Decoration7.mark({
4931
+ builder.add(table2.from, table2.to, Decoration10.mark({
4533
4932
  class: "cm-table"
4534
4933
  }));
4535
4934
  }
4536
4935
  });
4537
4936
  return builder.finish();
4538
4937
  };
4539
- var TableWidget = class extends WidgetType4 {
4938
+ var TableWidget = class extends WidgetType6 {
4540
4939
  constructor(_table) {
4541
4940
  super(), this._table = _table;
4542
4941
  }
@@ -4577,14 +4976,14 @@ var Unicode = {
4577
4976
  bulletSmall: "\u2219",
4578
4977
  bulletSquare: "\u2B1D"
4579
4978
  };
4580
- var HorizontalRuleWidget = class extends WidgetType5 {
4979
+ var HorizontalRuleWidget = class extends WidgetType7 {
4581
4980
  toDOM() {
4582
4981
  const el = document.createElement("span");
4583
4982
  el.className = "cm-hr";
4584
4983
  return el;
4585
4984
  }
4586
4985
  };
4587
- var LinkButton = class extends WidgetType5 {
4986
+ var LinkButton = class extends WidgetType7 {
4588
4987
  constructor(url, render) {
4589
4988
  super(), this.url = url, this.render = render;
4590
4989
  }
@@ -4600,7 +4999,7 @@ var LinkButton = class extends WidgetType5 {
4600
4999
  return el;
4601
5000
  }
4602
5001
  };
4603
- var CheckboxWidget = class extends WidgetType5 {
5002
+ var CheckboxWidget = class extends WidgetType7 {
4604
5003
  constructor(_checked) {
4605
5004
  super(), this._checked = _checked;
4606
5005
  }
@@ -4644,7 +5043,7 @@ var CheckboxWidget = class extends WidgetType5 {
4644
5043
  return false;
4645
5044
  }
4646
5045
  };
4647
- var TextWidget = class extends WidgetType5 {
5046
+ var TextWidget = class extends WidgetType7 {
4648
5047
  constructor(text, className) {
4649
5048
  super(), this.text = text, this.className = className;
4650
5049
  }
@@ -4657,29 +5056,29 @@ var TextWidget = class extends WidgetType5 {
4657
5056
  return el;
4658
5057
  }
4659
5058
  };
4660
- var hide = Decoration8.replace({});
4661
- var blockQuote = Decoration8.line({
5059
+ var hide = Decoration11.replace({});
5060
+ var blockQuote = Decoration11.line({
4662
5061
  class: "cm-blockquote"
4663
5062
  });
4664
- var fencedCodeLine = Decoration8.line({
5063
+ var fencedCodeLine = Decoration11.line({
4665
5064
  class: "cm-code cm-codeblock-line"
4666
5065
  });
4667
- var fencedCodeLineFirst = Decoration8.line({
4668
- class: mx2("cm-code cm-codeblock-line", "cm-codeblock-start")
5066
+ var fencedCodeLineFirst = Decoration11.line({
5067
+ class: mx4("cm-code cm-codeblock-line", "cm-codeblock-start")
4669
5068
  });
4670
- var fencedCodeLineLast = Decoration8.line({
4671
- class: mx2("cm-code cm-codeblock-line", "cm-codeblock-end")
5069
+ var fencedCodeLineLast = Decoration11.line({
5070
+ class: mx4("cm-code cm-codeblock-line", "cm-codeblock-end")
4672
5071
  });
4673
5072
  var commentBlockLine = fencedCodeLine;
4674
5073
  var commentBlockLineFirst = fencedCodeLineFirst;
4675
5074
  var commentBlockLineLast = fencedCodeLineLast;
4676
- var horizontalRule = Decoration8.replace({
5075
+ var horizontalRule = Decoration11.replace({
4677
5076
  widget: new HorizontalRuleWidget()
4678
5077
  });
4679
- var checkedTask = Decoration8.replace({
5078
+ var checkedTask = Decoration11.replace({
4680
5079
  widget: new CheckboxWidget(true)
4681
5080
  });
4682
- var uncheckedTask = Decoration8.replace({
5081
+ var uncheckedTask = Decoration11.replace({
4683
5082
  widget: new CheckboxWidget(false)
4684
5083
  });
4685
5084
  var editingRange = (state, range, focus2) => {
@@ -4695,8 +5094,8 @@ var autoHideTags = /* @__PURE__ */ new Set([
4695
5094
  "SuperscriptMark"
4696
5095
  ]);
4697
5096
  var buildDecorations2 = (view, options, focus2) => {
4698
- const deco = new RangeSetBuilder5();
4699
- const atomicDeco = new RangeSetBuilder5();
5097
+ const deco = new RangeSetBuilder6();
5098
+ const atomicDeco = new RangeSetBuilder6();
4700
5099
  const { state } = view;
4701
5100
  const headerLevels = [];
4702
5101
  const getHeaderLevels = (node, level) => {
@@ -4783,7 +5182,7 @@ var buildDecorations2 = (view, options, focus2) => {
4783
5182
  } else {
4784
5183
  const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + " ";
4785
5184
  if (num.length) {
4786
- atomicDeco.add(mark.from, mark.from + len, Decoration8.replace({
5185
+ atomicDeco.add(mark.from, mark.from + len, Decoration11.replace({
4787
5186
  widget: new TextWidget(num, theme.heading(level))
4788
5187
  }));
4789
5188
  }
@@ -4808,7 +5207,7 @@ var buildDecorations2 = (view, options, focus2) => {
4808
5207
  if (node.from === line.to - 1) {
4809
5208
  return false;
4810
5209
  }
4811
- deco.add(line.from, line.from, Decoration8.line({
5210
+ deco.add(line.from, line.from, Decoration11.line({
4812
5211
  class: "cm-list-item",
4813
5212
  attributes: {
4814
5213
  style: `padding-left: ${offset}px; text-indent: -${width}px;`
@@ -4825,7 +5224,7 @@ var buildDecorations2 = (view, options, focus2) => {
4825
5224
  const label = list.type === "OrderedList" ? `${++list.number}.` : Unicode.bulletSmall;
4826
5225
  const line = state.doc.lineAt(node.from);
4827
5226
  const to = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
4828
- atomicDeco.add(line.from, to, Decoration8.replace({
5227
+ atomicDeco.add(line.from, to, Decoration11.replace({
4829
5228
  widget: new TextWidget(label, list.type === "OrderedList" ? "cm-list-mark cm-list-mark-ordered" : "cm-list-mark cm-list-mark-bullet")
4830
5229
  }));
4831
5230
  break;
@@ -4912,7 +5311,7 @@ var buildDecorations2 = (view, options, focus2) => {
4912
5311
  if (!editing) {
4913
5312
  atomicDeco.add(node.from, marks[0].to, hide);
4914
5313
  }
4915
- deco.add(marks[0].to, marks[1].from, Decoration8.mark({
5314
+ deco.add(marks[0].to, marks[1].from, Decoration11.mark({
4916
5315
  tagName: "a",
4917
5316
  attributes: {
4918
5317
  class: "cm-link",
@@ -4922,7 +5321,7 @@ var buildDecorations2 = (view, options, focus2) => {
4922
5321
  }
4923
5322
  }));
4924
5323
  if (!editing) {
4925
- atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration8.replace({
5324
+ atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration11.replace({
4926
5325
  widget: new LinkButton(url, options.renderLinkButton)
4927
5326
  }) : hide);
4928
5327
  }
@@ -4977,10 +5376,10 @@ var buildDecorations2 = (view, options, focus2) => {
4977
5376
  atomicDeco: atomicDeco.finish()
4978
5377
  };
4979
5378
  };
4980
- var forceUpdate = StateEffect5.define();
5379
+ var forceUpdate = StateEffect6.define();
4981
5380
  var decorateMarkdown = (options = {}) => {
4982
5381
  return [
4983
- ViewPlugin10.fromClass(class {
5382
+ ViewPlugin12.fromClass(class {
4984
5383
  constructor(view) {
4985
5384
  ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(view, options, view.hasFocus));
4986
5385
  }
@@ -5012,9 +5411,9 @@ var decorateMarkdown = (options = {}) => {
5012
5411
  }
5013
5412
  }, {
5014
5413
  provide: (plugin) => [
5015
- EditorView19.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration8.none),
5016
- EditorView19.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration8.none),
5017
- EditorView19.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration8.none)
5414
+ EditorView22.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration11.none),
5415
+ EditorView22.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration11.none),
5416
+ EditorView22.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration11.none)
5018
5417
  ]
5019
5418
  }),
5020
5419
  image(),
@@ -5105,7 +5504,7 @@ var mention = ({ debug, onSearch }) => {
5105
5504
  };
5106
5505
 
5107
5506
  // packages/ui/react-ui-editor/src/extensions/modes.ts
5108
- import { keymap as keymap10 } from "@codemirror/view";
5507
+ import { keymap as keymap11 } from "@codemirror/view";
5109
5508
  import { vim } from "@replit/codemirror-vim";
5110
5509
  import { vscodeKeymap } from "@replit/codemirror-vscode-keymap";
5111
5510
  import { Schema } from "effect";
@@ -5129,7 +5528,7 @@ var InputModeExtensions = {
5129
5528
  editorInputMode.of({
5130
5529
  type: "vscode"
5131
5530
  }),
5132
- keymap10.of(vscodeKeymap)
5531
+ keymap11.of(vscodeKeymap)
5133
5532
  ],
5134
5533
  vim: [
5135
5534
  // https://github.com/replit/codemirror-vim
@@ -5138,7 +5537,7 @@ var InputModeExtensions = {
5138
5537
  type: "vim",
5139
5538
  noTabster: true
5140
5539
  }),
5141
- keymap10.of([
5540
+ keymap11.of([
5142
5541
  {
5143
5542
  key: "Alt-Escape",
5144
5543
  run: (view) => {
@@ -5154,14 +5553,14 @@ var InputModeExtensions = {
5154
5553
  import { indentMore } from "@codemirror/commands";
5155
5554
  import { getIndentUnit } from "@codemirror/language";
5156
5555
  import { EditorSelection as EditorSelection3 } from "@codemirror/state";
5157
- import { keymap as keymap11 } from "@codemirror/view";
5556
+ import { keymap as keymap12 } from "@codemirror/view";
5158
5557
 
5159
5558
  // packages/ui/react-ui-editor/src/extensions/outliner/selection.ts
5160
5559
  import { Compartment, Facet as Facet3 } from "@codemirror/state";
5161
5560
 
5162
5561
  // packages/ui/react-ui-editor/src/extensions/outliner/tree.ts
5163
5562
  import { syntaxTree as syntaxTree9 } from "@codemirror/language";
5164
- import { StateField as StateField9 } from "@codemirror/state";
5563
+ import { StateField as StateField10 } from "@codemirror/state";
5165
5564
  import { Facet as Facet2 } from "@codemirror/state";
5166
5565
  import { invariant as invariant5 } from "@dxos/invariant";
5167
5566
  var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/outliner/tree.ts";
@@ -5442,7 +5841,7 @@ var outlinerTree = (options = {}) => {
5442
5841
  return tree;
5443
5842
  };
5444
5843
  return [
5445
- StateField9.define({
5844
+ StateField10.define({
5446
5845
  create: (state) => {
5447
5846
  return buildTree(state);
5448
5847
  },
@@ -5616,7 +6015,7 @@ var toggleTask = (view) => {
5616
6015
  }
5617
6016
  return true;
5618
6017
  };
5619
- var commands = () => keymap11.of([
6018
+ var commands = () => keymap12.of([
5620
6019
  //
5621
6020
  // Indentation.
5622
6021
  //
@@ -5722,18 +6121,18 @@ var commands = () => keymap11.of([
5722
6121
  ]);
5723
6122
 
5724
6123
  // packages/ui/react-ui-editor/src/extensions/outliner/outliner.ts
5725
- import { Prec as Prec2 } from "@codemirror/state";
5726
- import { Decoration as Decoration9, EditorView as EditorView20, ViewPlugin as ViewPlugin12 } from "@codemirror/view";
5727
- import { mx as mx3 } from "@dxos/react-ui-theme";
6124
+ import { Prec as Prec3 } from "@codemirror/state";
6125
+ import { Decoration as Decoration12, EditorView as EditorView23, ViewPlugin as ViewPlugin14 } from "@codemirror/view";
6126
+ import { mx as mx5 } from "@dxos/react-ui-theme";
5728
6127
 
5729
6128
  // packages/ui/react-ui-editor/src/extensions/outliner/editor.ts
5730
6129
  import { EditorSelection as EditorSelection4, EditorState as EditorState2 } from "@codemirror/state";
5731
- import { ViewPlugin as ViewPlugin11 } from "@codemirror/view";
6130
+ import { ViewPlugin as ViewPlugin13 } from "@codemirror/view";
5732
6131
  import { log as log7 } from "@dxos/log";
5733
6132
  var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/outliner/editor.ts";
5734
6133
  var LIST_ITEM_REGEX = /^\s*- (\[ \]|\[x\])? /;
5735
6134
  var initialize = () => {
5736
- return ViewPlugin11.fromClass(class {
6135
+ return ViewPlugin13.fromClass(class {
5737
6136
  constructor(view) {
5738
6137
  const first = view.state.doc.lineAt(0);
5739
6138
  const text = view.state.sliceDoc(first.from, first.to);
@@ -5918,7 +6317,7 @@ var editor = () => [
5918
6317
  // packages/ui/react-ui-editor/src/extensions/outliner/outliner.ts
5919
6318
  var outliner = (options = {}) => [
5920
6319
  // Commands.
5921
- Prec2.highest(commands()),
6320
+ Prec3.highest(commands()),
5922
6321
  // Selection.
5923
6322
  selectionCompartment.of(selectionFacet.of([])),
5924
6323
  // State.
@@ -5928,20 +6327,20 @@ var outliner = (options = {}) => [
5928
6327
  // Floating menu.
5929
6328
  floatingMenu(),
5930
6329
  // Line decorations.
5931
- decorations(options),
6330
+ decorations(),
5932
6331
  // Default markdown decorations.
5933
6332
  decorateMarkdown({
5934
6333
  listPaddingLeft: 8
5935
6334
  }),
5936
6335
  // Researve space for menu.
5937
- EditorView20.contentAttributes.of({
6336
+ EditorView23.contentAttributes.of({
5938
6337
  class: "is-full !mr-[3rem]"
5939
6338
  })
5940
6339
  ];
5941
- var decorations = (options) => [
5942
- ViewPlugin12.fromClass(class {
6340
+ var decorations = () => [
6341
+ ViewPlugin14.fromClass(class {
5943
6342
  constructor(view) {
5944
- this.decorations = Decoration9.none;
6343
+ this.decorations = Decoration12.none;
5945
6344
  this.updateDecorations(view.state, view);
5946
6345
  }
5947
6346
  update(update2) {
@@ -5963,18 +6362,18 @@ var decorations = (options) => [
5963
6362
  const lineFrom = doc.lineAt(item.contentRange.from);
5964
6363
  const lineTo = doc.lineAt(item.contentRange.to);
5965
6364
  const isSelected = selection.includes(item.index) || item === current;
5966
- decorations2.push(Decoration9.line({
5967
- class: mx3("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"))
6365
+ decorations2.push(Decoration12.line({
6366
+ class: mx5("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"))
5968
6367
  }).range(line.from, line.from));
5969
6368
  }
5970
6369
  }
5971
- this.decorations = Decoration9.set(decorations2);
6370
+ this.decorations = Decoration12.set(decorations2);
5972
6371
  }
5973
6372
  }, {
5974
6373
  decorations: (v) => v.decorations
5975
6374
  }),
5976
6375
  // Theme.
5977
- EditorView20.theme(Object.assign({
6376
+ EditorView23.theme(Object.assign({
5978
6377
  ".cm-list-item": {
5979
6378
  borderLeftWidth: "1px",
5980
6379
  borderRightWidth: "1px",
@@ -5998,11 +6397,11 @@ var decorations = (options) => [
5998
6397
  paddingBottom: "4px",
5999
6398
  marginBottom: "2px"
6000
6399
  },
6001
- ".cm-list-item-selected": {
6002
- borderColor: options.showSelected ? "var(--dx-separator)" : void 0
6003
- },
6004
6400
  ".cm-list-item-focused": {
6005
6401
  borderColor: "var(--dx-accentFocusIndicator)"
6402
+ },
6403
+ "[data-has-focus] & .cm-list-item-selected": {
6404
+ borderColor: "var(--dx-separator)"
6006
6405
  }
6007
6406
  }))
6008
6407
  ];
@@ -6010,28 +6409,25 @@ var decorations = (options) => [
6010
6409
  // packages/ui/react-ui-editor/src/extensions/preview/preview.ts
6011
6410
  import "@dxos/lit-ui/dx-ref-tag.pcss";
6012
6411
  import { syntaxTree as syntaxTree10 } from "@codemirror/language";
6013
- import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField10 } from "@codemirror/state";
6014
- import { Decoration as Decoration10, EditorView as EditorView21, WidgetType as WidgetType6 } from "@codemirror/view";
6412
+ import { RangeSetBuilder as RangeSetBuilder7, StateField as StateField11 } from "@codemirror/state";
6413
+ import { Decoration as Decoration13, EditorView as EditorView24, WidgetType as WidgetType8 } from "@codemirror/view";
6015
6414
  var preview = (options = {}) => {
6016
6415
  return [
6017
6416
  // NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
6018
6417
  // "Block decorations may not be specified via plugins"
6019
- StateField10.define({
6418
+ StateField11.define({
6020
6419
  create: (state) => buildDecorations3(state, options),
6021
6420
  update: (_, tr) => buildDecorations3(tr.state, options),
6022
6421
  provide: (field) => [
6023
- EditorView21.decorations.from(field),
6024
- EditorView21.atomicRanges.of((view) => view.state.field(field))
6422
+ EditorView24.decorations.from(field),
6423
+ EditorView24.atomicRanges.of((view) => view.state.field(field))
6025
6424
  ]
6026
6425
  }),
6027
- EditorView21.theme({
6426
+ EditorView24.theme({
6028
6427
  ".cm-preview-block": {
6029
- marginLeft: "-1rem",
6030
- marginRight: "-1rem",
6031
- padding: "1rem",
6032
- borderRadius: "0.5rem",
6033
- background: "var(--dx-modalSurface)",
6034
- border: "1px solid var(--dx-separator)"
6428
+ "--dx-card-spacing-inline": "var(--dx-trimMd)",
6429
+ "--dx-card-spacing-block": "var(--dx-trimMd)",
6430
+ marginInline: "calc(-1*var(--dx-trimMd))"
6035
6431
  }
6036
6432
  })
6037
6433
  ];
@@ -6050,7 +6446,7 @@ var getLinkRef = (state, node) => {
6050
6446
  }
6051
6447
  };
6052
6448
  var buildDecorations3 = (state, options) => {
6053
- const builder = new RangeSetBuilder6();
6449
+ const builder = new RangeSetBuilder7();
6054
6450
  syntaxTree10(state).iterate({
6055
6451
  enter: (node) => {
6056
6452
  switch (node.name) {
@@ -6061,7 +6457,7 @@ var buildDecorations3 = (state, options) => {
6061
6457
  case "Link": {
6062
6458
  const link = getLinkRef(state, node.node);
6063
6459
  if (link) {
6064
- builder.add(node.from, node.to, Decoration10.replace({
6460
+ builder.add(node.from, node.to, Decoration13.replace({
6065
6461
  widget: new PreviewInlineWidget(options, link)
6066
6462
  }));
6067
6463
  }
@@ -6074,7 +6470,7 @@ var buildDecorations3 = (state, options) => {
6074
6470
  case "Image": {
6075
6471
  const link = getLinkRef(state, node.node);
6076
6472
  if (options.renderBlock && link) {
6077
- builder.add(node.from, node.to, Decoration10.replace({
6473
+ builder.add(node.from, node.to, Decoration13.replace({
6078
6474
  block: true,
6079
6475
  // atomic: true,
6080
6476
  widget: new PreviewBlockWidget(options, link)
@@ -6087,7 +6483,7 @@ var buildDecorations3 = (state, options) => {
6087
6483
  });
6088
6484
  return builder.finish();
6089
6485
  };
6090
- var PreviewInlineWidget = class extends WidgetType6 {
6486
+ var PreviewInlineWidget = class extends WidgetType8 {
6091
6487
  constructor(_options, _link) {
6092
6488
  super(), this._options = _options, this._link = _link;
6093
6489
  }
@@ -6104,7 +6500,7 @@ var PreviewInlineWidget = class extends WidgetType6 {
6104
6500
  return root;
6105
6501
  }
6106
6502
  };
6107
- var PreviewBlockWidget = class extends WidgetType6 {
6503
+ var PreviewBlockWidget = class extends WidgetType8 {
6108
6504
  constructor(_options, _link) {
6109
6505
  super(), this._options = _options, this._link = _link;
6110
6506
  }
@@ -6163,7 +6559,7 @@ var PreviewBlockWidget = class extends WidgetType6 {
6163
6559
  };
6164
6560
 
6165
6561
  // packages/ui/react-ui-editor/src/extensions/typewriter.ts
6166
- import { keymap as keymap12 } from "@codemirror/view";
6562
+ import { keymap as keymap13 } from "@codemirror/view";
6167
6563
  var defaultItems = [
6168
6564
  "hello world!",
6169
6565
  "this is a test.",
@@ -6173,7 +6569,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
6173
6569
  let t;
6174
6570
  let idx = 0;
6175
6571
  return [
6176
- keymap12.of([
6572
+ keymap13.of([
6177
6573
  {
6178
6574
  // Reset.
6179
6575
  key: "alt-meta-'",
@@ -6516,32 +6912,6 @@ var createViewMode = (state, onViewModeChange) => {
6516
6912
  };
6517
6913
  };
6518
6914
 
6519
- // packages/ui/react-ui-editor/src/defaults.ts
6520
- import { EditorView as EditorView22 } from "@codemirror/view";
6521
- import { mx as mx4 } from "@dxos/react-ui-theme";
6522
- var editorWidth = "!mli-auto is-full max-is-[min(50rem,100%-4rem)]";
6523
- var editorSlots = {
6524
- scroll: {
6525
- className: "pbs-2"
6526
- },
6527
- content: {
6528
- className: editorWidth
6529
- }
6530
- };
6531
- var editorGutter = EditorView22.theme({
6532
- ".cm-gutters": {
6533
- paddingRight: "1rem"
6534
- }
6535
- });
6536
- var editorMonospace = EditorView22.theme({
6537
- ".cm-content": {
6538
- fontFamily: fontMono
6539
- }
6540
- });
6541
- var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
6542
- var stackItemContentEditorClassNames = (role) => mx4("attention-surface dx-focus-ring-inset data-[toolbar=disabled]:pbs-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24" : "min-bs-0");
6543
- var stackItemContentToolbarClassNames = (role) => mx4("relative z-[1] flex is-full bg-toolbarSurface border-be border-subduedSeparator", role === "section" && "sticky block-start-0 -mbe-px min-is-0");
6544
-
6545
6915
  // packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
6546
6916
  var createToolbar = ({ getView, state, customActions, ...features }) => {
6547
6917
  return Rx.make((get2) => {
@@ -6597,7 +6967,7 @@ var createToolbar = ({ getView, state, customActions, ...features }) => {
6597
6967
  });
6598
6968
  };
6599
6969
  var useEditorToolbarActionGraph = (props) => {
6600
- const menuCreator = useMemo3(() => createToolbar({
6970
+ const menuCreator = useMemo4(() => createToolbar({
6601
6971
  getView: props.getView,
6602
6972
  state: props.state,
6603
6973
  customActions: props.customActions,
@@ -6645,26 +7015,315 @@ var EditorToolbar = /* @__PURE__ */ memo(({ classNames, attendableId, role, ...p
6645
7015
  }
6646
7016
  });
6647
7017
 
6648
- // packages/ui/react-ui-editor/src/components/Popover/RefPopover.tsx
7018
+ // packages/ui/react-ui-editor/src/components/Popover/CommandMenu.tsx
6649
7019
  import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
7020
+ import React4, { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2 } from "react";
7021
+ import { Icon as Icon2, Popover, toLocalizedString, useThemeContext, useTranslation } from "@dxos/react-ui";
7022
+ var CommandMenu = ({ groups, currentItem, onSelect }) => {
7023
+ var _effect = _useSignals2();
7024
+ try {
7025
+ const { tx } = useThemeContext();
7026
+ const groupsWithItems = groups.filter((group) => group.items.length > 0);
7027
+ return /* @__PURE__ */ React4.createElement(Popover.Portal, null, /* @__PURE__ */ React4.createElement(Popover.Content, {
7028
+ align: "start",
7029
+ onOpenAutoFocus: (event) => event.preventDefault(),
7030
+ classNames: tx("menu.content", "menu--exotic-unfocusable", {
7031
+ elevation: "positioned"
7032
+ }, [
7033
+ "max-h-[300px] overflow-y-auto"
7034
+ ])
7035
+ }, /* @__PURE__ */ React4.createElement(Popover.Viewport, {
7036
+ classNames: tx("menu.viewport", "menu__viewport--exotic-unfocusable", {})
7037
+ }, /* @__PURE__ */ React4.createElement("ul", null, groupsWithItems.map((group, index) => /* @__PURE__ */ React4.createElement(React4.Fragment, {
7038
+ key: group.id
7039
+ }, /* @__PURE__ */ React4.createElement(CommandGroup, {
7040
+ group,
7041
+ currentItem,
7042
+ onSelect
7043
+ }), index < groupsWithItems.length - 1 && /* @__PURE__ */ React4.createElement("div", {
7044
+ className: tx("menu.separator", "menu__item", {})
7045
+ })))))));
7046
+ } finally {
7047
+ _effect.f();
7048
+ }
7049
+ };
7050
+ var CommandGroup = ({ group, currentItem, onSelect }) => {
7051
+ var _effect = _useSignals2();
7052
+ try {
7053
+ const { tx } = useThemeContext();
7054
+ const { t } = useTranslation();
7055
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, group.label && /* @__PURE__ */ React4.createElement("div", {
7056
+ className: tx("menu.groupLabel", "menu__group__label", {})
7057
+ }, /* @__PURE__ */ React4.createElement("span", null, toLocalizedString(group.label, t))), group.items.map((item) => /* @__PURE__ */ React4.createElement(CommandItem, {
7058
+ key: item.id,
7059
+ item,
7060
+ current: currentItem === item.id,
7061
+ onSelect
7062
+ })));
7063
+ } finally {
7064
+ _effect.f();
7065
+ }
7066
+ };
7067
+ var CommandItem = ({ item, current, onSelect }) => {
7068
+ var _effect = _useSignals2();
7069
+ try {
7070
+ const ref = useRef2(null);
7071
+ const { tx } = useThemeContext();
7072
+ const { t } = useTranslation();
7073
+ const handleSelect = useCallback2(() => onSelect(item), [
7074
+ item,
7075
+ onSelect
7076
+ ]);
7077
+ useEffect2(() => {
7078
+ if (current && ref.current) {
7079
+ ref.current.scrollIntoView({
7080
+ behavior: "smooth",
7081
+ block: "nearest"
7082
+ });
7083
+ }
7084
+ }, [
7085
+ current
7086
+ ]);
7087
+ return /* @__PURE__ */ React4.createElement("li", {
7088
+ ref,
7089
+ className: tx("menu.item", "menu__item--exotic-unfocusable", {}, [
7090
+ current && "bg-hoverSurface"
7091
+ ]),
7092
+ onClick: handleSelect
7093
+ }, item.icon && /* @__PURE__ */ React4.createElement(Icon2, {
7094
+ icon: item.icon,
7095
+ size: 5
7096
+ }), /* @__PURE__ */ React4.createElement("span", {
7097
+ className: "grow truncate"
7098
+ }, toLocalizedString(item.label, t)));
7099
+ } finally {
7100
+ _effect.f();
7101
+ }
7102
+ };
7103
+ var getItem = (groups, id) => {
7104
+ return groups.flatMap((group) => group.items).find((item) => item.id === id);
7105
+ };
7106
+ var getNextItem = (groups, id) => {
7107
+ const items = groups.flatMap((group) => group.items);
7108
+ const index = items.findIndex((item) => item.id === id);
7109
+ return items[(index + 1) % items.length];
7110
+ };
7111
+ var getPreviousItem = (groups, id) => {
7112
+ const items = groups.flatMap((group) => group.items);
7113
+ const index = items.findIndex((item) => item.id === id);
7114
+ return items[(index - 1 + items.length) % items.length];
7115
+ };
7116
+ var filterItems = (groups, filter) => {
7117
+ return groups.map((group) => ({
7118
+ ...group,
7119
+ items: group.items.filter(filter)
7120
+ }));
7121
+ };
7122
+ var insertAtCursor = (view, head, insert) => {
7123
+ view.dispatch({
7124
+ changes: {
7125
+ from: head,
7126
+ to: head,
7127
+ insert
7128
+ },
7129
+ selection: {
7130
+ anchor: head + insert.length,
7131
+ head: head + insert.length
7132
+ }
7133
+ });
7134
+ };
7135
+ var insertAtLineStart = (view, head, insert) => {
7136
+ const line = view.state.doc.lineAt(head);
7137
+ if (line.from === head) {
7138
+ insertAtCursor(view, head, insert);
7139
+ } else {
7140
+ insert = "\n" + insert;
7141
+ view.dispatch({
7142
+ changes: {
7143
+ from: line.to,
7144
+ to: line.to,
7145
+ insert
7146
+ },
7147
+ selection: {
7148
+ anchor: line.to + insert.length,
7149
+ head: line.to + insert.length
7150
+ }
7151
+ });
7152
+ }
7153
+ };
7154
+ var coreSlashCommands = {
7155
+ id: "markdown",
7156
+ label: "Markdown",
7157
+ items: [
7158
+ {
7159
+ id: "heading-1",
7160
+ label: "Heading 1",
7161
+ icon: "ph--text-h-one--regular",
7162
+ onSelect: (view, head) => insertAtLineStart(view, head, "# ")
7163
+ },
7164
+ {
7165
+ id: "heading-2",
7166
+ label: "Heading 2",
7167
+ icon: "ph--text-h-two--regular",
7168
+ onSelect: (view, head) => insertAtLineStart(view, head, "## ")
7169
+ },
7170
+ {
7171
+ id: "heading-3",
7172
+ label: "Heading 3",
7173
+ icon: "ph--text-h-three--regular",
7174
+ onSelect: (view, head) => insertAtLineStart(view, head, "### ")
7175
+ },
7176
+ {
7177
+ id: "heading-4",
7178
+ label: "Heading 4",
7179
+ icon: "ph--text-h-four--regular",
7180
+ onSelect: (view, head) => insertAtLineStart(view, head, "#### ")
7181
+ },
7182
+ {
7183
+ id: "heading-5",
7184
+ label: "Heading 5",
7185
+ icon: "ph--text-h-five--regular",
7186
+ onSelect: (view, head) => insertAtLineStart(view, head, "##### ")
7187
+ },
7188
+ {
7189
+ id: "heading-6",
7190
+ label: "Heading 6",
7191
+ icon: "ph--text-h-six--regular",
7192
+ onSelect: (view, head) => insertAtLineStart(view, head, "###### ")
7193
+ },
7194
+ {
7195
+ id: "bullet-list",
7196
+ label: "Bullet List",
7197
+ icon: "ph--list-bullets--regular",
7198
+ onSelect: (view, head) => insertAtLineStart(view, head, "- ")
7199
+ },
7200
+ {
7201
+ id: "numbered-list",
7202
+ label: "Numbered List",
7203
+ icon: "ph--list-numbers--regular",
7204
+ onSelect: (view, head) => insertAtLineStart(view, head, "1. ")
7205
+ },
7206
+ {
7207
+ id: "task-list",
7208
+ label: "Task List",
7209
+ icon: "ph--list-checks--regular",
7210
+ onSelect: (view, head) => insertAtLineStart(view, head, "- [ ] ")
7211
+ },
7212
+ {
7213
+ id: "quote",
7214
+ label: "Quote",
7215
+ icon: "ph--quotes--regular",
7216
+ onSelect: (view, head) => insertAtLineStart(view, head, "> ")
7217
+ },
7218
+ {
7219
+ id: "code-block",
7220
+ label: "Code Block",
7221
+ icon: "ph--code-block--regular",
7222
+ onSelect: (view, head) => insertAtLineStart(view, head, "```\n\n```")
7223
+ },
7224
+ {
7225
+ id: "table",
7226
+ label: "Table",
7227
+ icon: "ph--table--regular",
7228
+ onSelect: (view, head) => insertAtLineStart(view, head, "| | | |\n|---|---|---|\n| | | |")
7229
+ }
7230
+ ]
7231
+ };
7232
+ var linkSlashCommands = {
7233
+ id: "link",
7234
+ label: "Link",
7235
+ items: [
7236
+ {
7237
+ id: "inline-link",
7238
+ label: "Inline link",
7239
+ icon: "ph--link--regular",
7240
+ onSelect: (view, head) => view.dispatch({
7241
+ changes: {
7242
+ from: head,
7243
+ insert: "@"
7244
+ },
7245
+ selection: {
7246
+ anchor: head + 1,
7247
+ head: head + 1
7248
+ },
7249
+ effects: commandRangeEffect.of({
7250
+ trigger: "@",
7251
+ range: {
7252
+ from: head,
7253
+ to: head + 1
7254
+ }
7255
+ })
7256
+ })
7257
+ },
7258
+ {
7259
+ id: "block-embed",
7260
+ label: "Block embed",
7261
+ icon: "ph--lego--regular",
7262
+ onSelect: (view, head) => view.dispatch({
7263
+ changes: {
7264
+ from: head,
7265
+ insert: "@@"
7266
+ },
7267
+ selection: {
7268
+ anchor: head + 2,
7269
+ head: head + 2
7270
+ },
7271
+ effects: commandRangeEffect.of({
7272
+ trigger: "@",
7273
+ range: {
7274
+ from: head,
7275
+ to: head + 2
7276
+ }
7277
+ })
7278
+ })
7279
+ }
7280
+ ]
7281
+ };
7282
+
7283
+ // packages/ui/react-ui-editor/src/components/Popover/RefPopover.tsx
7284
+ import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
6650
7285
  import { createContext } from "@radix-ui/react-context";
6651
- import React4, { useRef, useState, useEffect as useEffect2, useCallback } from "react";
6652
- import { addEventListener } from "@dxos/async";
6653
- import { Popover } from "@dxos/react-ui";
7286
+ import React5, { useRef as useRef3, useState as useState2, useEffect as useEffect3, useCallback as useCallback3, forwardRef } from "react";
7287
+ import { addEventListener as addEventListener2 } from "@dxos/async";
7288
+ import { Popover as Popover2 } from "@dxos/react-ui";
6654
7289
  var customEventOptions = {
6655
7290
  capture: true,
6656
7291
  passive: false
6657
7292
  };
7293
+ var RefPopover = /* @__PURE__ */ forwardRef(({ children, open, onOpenChange, modal, onActivate }, ref) => {
7294
+ var _effect = _useSignals3();
7295
+ try {
7296
+ const [rootRef, setRootRef] = useState2(null);
7297
+ useEffect3(() => {
7298
+ return rootRef && onActivate ? addEventListener2(rootRef, "dx-ref-tag-activate", onActivate, customEventOptions) : void 0;
7299
+ }, [
7300
+ rootRef,
7301
+ onActivate
7302
+ ]);
7303
+ return /* @__PURE__ */ React5.createElement(Popover2.Root, {
7304
+ open,
7305
+ onOpenChange,
7306
+ modal
7307
+ }, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
7308
+ virtualRef: ref
7309
+ }), /* @__PURE__ */ React5.createElement("div", {
7310
+ role: "none",
7311
+ className: "contents",
7312
+ ref: setRootRef
7313
+ }, children));
7314
+ } finally {
7315
+ _effect.f();
7316
+ }
7317
+ });
6658
7318
  var REF_POPOVER = "RefPopover";
6659
7319
  var [RefPopoverContextProvider, useRefPopover] = createContext(REF_POPOVER, {});
6660
- var RefPopoverProvider = ({ children, onLookup }) => {
6661
- var _effect = _useSignals2();
7320
+ var PreviewProvider = ({ children, onLookup }) => {
7321
+ var _effect = _useSignals3();
6662
7322
  try {
6663
- const trigger = useRef(null);
6664
- const [value, setValue] = useState({});
6665
- const [rootRef, setRootRef] = useState(null);
6666
- const [open, setOpen] = useState(false);
6667
- const handleDxRefTagActivate = useCallback((event) => {
7323
+ const trigger = useRef3(null);
7324
+ const [value, setValue] = useState2({});
7325
+ const [open, setOpen] = useState2(false);
7326
+ const handleDxRefTagActivate = useCallback3((event) => {
6668
7327
  const { refId, label, trigger: dxTrigger } = event;
6669
7328
  setValue((value2) => ({
6670
7329
  ...value2,
@@ -6687,38 +7346,26 @@ var RefPopoverProvider = ({ children, onLookup }) => {
6687
7346
  }, [
6688
7347
  onLookup
6689
7348
  ]);
6690
- useEffect2(() => {
6691
- return rootRef ? addEventListener(rootRef, "dx-ref-tag-activate", handleDxRefTagActivate, customEventOptions) : void 0;
6692
- }, [
6693
- rootRef
6694
- ]);
6695
- return /* @__PURE__ */ React4.createElement(RefPopoverContextProvider, {
7349
+ return /* @__PURE__ */ React5.createElement(RefPopoverContextProvider, {
6696
7350
  pending: value.pending,
6697
7351
  link: value.link,
6698
7352
  target: value.target
6699
- }, /* @__PURE__ */ React4.createElement(Popover.Root, {
7353
+ }, /* @__PURE__ */ React5.createElement(RefPopover, {
7354
+ ref: trigger,
6700
7355
  open,
6701
- onOpenChange: setOpen
6702
- }, /* @__PURE__ */ React4.createElement(Popover.VirtualTrigger, {
6703
- virtualRef: trigger
6704
- }), /* @__PURE__ */ React4.createElement("div", {
6705
- role: "none",
6706
- className: "contents",
6707
- ref: setRootRef
6708
- }, children)));
7356
+ onOpenChange: setOpen,
7357
+ onActivate: handleDxRefTagActivate
7358
+ }, children));
6709
7359
  } finally {
6710
7360
  _effect.f();
6711
7361
  }
6712
7362
  };
6713
- var RefPopover = {
6714
- Provider: RefPopoverProvider
6715
- };
6716
7363
 
6717
7364
  // packages/ui/react-ui-editor/src/components/Popover/RefDropdownMenu.tsx
6718
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
7365
+ import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
6719
7366
  import { createContext as createContext2 } from "@radix-ui/react-context";
6720
- import React5, { useRef as useRef2, useState as useState2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
6721
- import { addEventListener as addEventListener2 } from "@dxos/async";
7367
+ import React6, { useRef as useRef4, useState as useState3, useEffect as useEffect4, useCallback as useCallback4 } from "react";
7368
+ import { addEventListener as addEventListener3 } from "@dxos/async";
6722
7369
  import { DropdownMenu } from "@dxos/react-ui";
6723
7370
  var customEventOptions2 = {
6724
7371
  capture: true,
@@ -6727,13 +7374,13 @@ var customEventOptions2 = {
6727
7374
  var REF_DROPDOWN_MENU = "RefDropdownMenu";
6728
7375
  var [RefDropdownMenuContextProvider, useRefDropdownMenu] = createContext2(REF_DROPDOWN_MENU, {});
6729
7376
  var RefDropdownMenuProvider = ({ children, onLookup }) => {
6730
- var _effect = _useSignals3();
7377
+ var _effect = _useSignals4();
6731
7378
  try {
6732
- const trigger = useRef2(null);
6733
- const [value, setValue] = useState2({});
6734
- const [rootRef, setRootRef] = useState2(null);
6735
- const [open, setOpen] = useState2(false);
6736
- const handleDxRefTagActivate = useCallback2((event) => {
7379
+ const trigger = useRef4(null);
7380
+ const [value, setValue] = useState3({});
7381
+ const [rootRef, setRootRef] = useState3(null);
7382
+ const [open, setOpen] = useState3(false);
7383
+ const handleDxRefTagActivate = useCallback4((event) => {
6737
7384
  const { refId, label, trigger: dxTrigger } = event;
6738
7385
  setValue((value2) => ({
6739
7386
  ...value2,
@@ -6756,21 +7403,21 @@ var RefDropdownMenuProvider = ({ children, onLookup }) => {
6756
7403
  }, [
6757
7404
  onLookup
6758
7405
  ]);
6759
- useEffect3(() => {
6760
- return rootRef ? addEventListener2(rootRef, "dx-ref-tag-activate", handleDxRefTagActivate, customEventOptions2) : void 0;
7406
+ useEffect4(() => {
7407
+ return rootRef ? addEventListener3(rootRef, "dx-ref-tag-activate", handleDxRefTagActivate, customEventOptions2) : void 0;
6761
7408
  }, [
6762
7409
  rootRef
6763
7410
  ]);
6764
- return /* @__PURE__ */ React5.createElement(RefDropdownMenuContextProvider, {
7411
+ return /* @__PURE__ */ React6.createElement(RefDropdownMenuContextProvider, {
6765
7412
  pending: value.pending,
6766
7413
  link: value.link,
6767
7414
  target: value.target
6768
- }, /* @__PURE__ */ React5.createElement(DropdownMenu.Root, {
7415
+ }, /* @__PURE__ */ React6.createElement(DropdownMenu.Root, {
6769
7416
  open,
6770
7417
  onOpenChange: setOpen
6771
- }, /* @__PURE__ */ React5.createElement(DropdownMenu.VirtualTrigger, {
7418
+ }, /* @__PURE__ */ React6.createElement(DropdownMenu.VirtualTrigger, {
6772
7419
  virtualRef: trigger
6773
- }), /* @__PURE__ */ React5.createElement("div", {
7420
+ }), /* @__PURE__ */ React6.createElement("div", {
6774
7421
  role: "none",
6775
7422
  className: "contents",
6776
7423
  ref: setRootRef
@@ -6785,19 +7432,19 @@ var RefDropdownMenu = {
6785
7432
 
6786
7433
  // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
6787
7434
  import { EditorState as EditorState3 } from "@codemirror/state";
6788
- import { EditorView as EditorView23 } from "@codemirror/view";
7435
+ import { EditorView as EditorView25 } from "@codemirror/view";
6789
7436
  import { useFocusableGroup } from "@fluentui/react-tabster";
6790
- import { useCallback as useCallback3, useEffect as useEffect4, useMemo as useMemo4, useRef as useRef3, useState as useState3 } from "react";
7437
+ import { useCallback as useCallback5, useEffect as useEffect5, useMemo as useMemo5, useRef as useRef5, useState as useState4 } from "react";
6791
7438
  import { log as log8 } from "@dxos/log";
6792
7439
  import { getProviderValue, isNotFalsy as isNotFalsy4 } from "@dxos/util";
6793
7440
  var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
6794
7441
  var instanceCount = 0;
6795
7442
  var useTextEditor = (props = {}, deps = []) => {
6796
- const { id, doc, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } = useMemo4(() => getProviderValue(props), deps ?? []);
6797
- const [instanceId] = useState3(() => `text-editor-${++instanceCount}`);
6798
- const [view, setView] = useState3();
6799
- const parentRef = useRef3(null);
6800
- useEffect4(() => {
7443
+ const { id, doc, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } = useMemo5(() => getProviderValue(props), deps ?? []);
7444
+ const [instanceId] = useState4(() => `text-editor-${++instanceCount}`);
7445
+ const [view, setView] = useState4();
7446
+ const parentRef = useRef5(null);
7447
+ useEffect5(() => {
6801
7448
  let view2;
6802
7449
  if (parentRef.current) {
6803
7450
  log8("create", {
@@ -6806,7 +7453,7 @@ var useTextEditor = (props = {}, deps = []) => {
6806
7453
  doc: initialValue?.length ?? 0
6807
7454
  }, {
6808
7455
  F: __dxlog_file13,
6809
- L: 76,
7456
+ L: 75,
6810
7457
  S: void 0,
6811
7458
  C: (f, a) => f(...a)
6812
7459
  });
@@ -6829,20 +7476,20 @@ var useTextEditor = (props = {}, deps = []) => {
6829
7476
  id && documentId.of(id),
6830
7477
  extensions,
6831
7478
  // NOTE: This doesn't catch errors in keymap functions.
6832
- EditorView23.exceptionSink.of((err) => {
7479
+ EditorView25.exceptionSink.of((err) => {
6833
7480
  log8.catch(err, void 0, {
6834
7481
  F: __dxlog_file13,
6835
- L: 98,
7482
+ L: 97,
6836
7483
  S: void 0,
6837
7484
  C: (f, a) => f(...a)
6838
7485
  });
6839
7486
  })
6840
7487
  ].filter(isNotFalsy4)
6841
7488
  });
6842
- view2 = new EditorView23({
7489
+ view2 = new EditorView25({
6843
7490
  parent: parentRef.current,
6844
7491
  state,
6845
- scrollTo: scrollTo ? EditorView23.scrollIntoView(scrollTo, {
7492
+ scrollTo: scrollTo ? EditorView25.scrollIntoView(scrollTo, {
6846
7493
  yMargin: 96
6847
7494
  }) : void 0,
6848
7495
  dispatchTransactions: debug ? debugDispatcher : void 0
@@ -6864,14 +7511,14 @@ var useTextEditor = (props = {}, deps = []) => {
6864
7511
  id
6865
7512
  }, {
6866
7513
  F: __dxlog_file13,
6867
- L: 135,
7514
+ L: 134,
6868
7515
  S: void 0,
6869
7516
  C: (f, a) => f(...a)
6870
7517
  });
6871
7518
  view2?.destroy();
6872
7519
  };
6873
7520
  }, deps);
6874
- useEffect4(() => {
7521
+ useEffect5(() => {
6875
7522
  if (view) {
6876
7523
  if (scrollTo || selection) {
6877
7524
  if (selection && selection.anchor > view.state.doc.length) {
@@ -6881,7 +7528,7 @@ var useTextEditor = (props = {}, deps = []) => {
6881
7528
  selection
6882
7529
  }, {
6883
7530
  F: __dxlog_file13,
6884
- L: 144,
7531
+ L: 143,
6885
7532
  S: void 0,
6886
7533
  C: (f, a) => f(...a)
6887
7534
  });
@@ -6898,7 +7545,7 @@ var useTextEditor = (props = {}, deps = []) => {
6898
7545
  scrollTo,
6899
7546
  selection
6900
7547
  ]);
6901
- useEffect4(() => {
7548
+ useEffect5(() => {
6902
7549
  if (view && autoFocus) {
6903
7550
  view.focus();
6904
7551
  }
@@ -6912,7 +7559,7 @@ var useTextEditor = (props = {}, deps = []) => {
6912
7559
  Escape: view?.state.facet(editorInputMode).noTabster
6913
7560
  }
6914
7561
  });
6915
- const handleKeyUp = useCallback3((event) => {
7562
+ const handleKeyUp = useCallback5((event) => {
6916
7563
  const { key, target, currentTarget } = event;
6917
7564
  if (target === currentTarget) {
6918
7565
  switch (key) {
@@ -6936,17 +7583,19 @@ var useTextEditor = (props = {}, deps = []) => {
6936
7583
  };
6937
7584
  };
6938
7585
  export {
7586
+ CommandMenu,
6939
7587
  Cursor,
6940
7588
  EditorInputMode,
6941
7589
  EditorInputModes,
6942
7590
  EditorState4 as EditorState,
6943
7591
  EditorToolbar,
6944
- EditorView24 as EditorView,
7592
+ EditorView26 as EditorView,
6945
7593
  EditorViewMode,
6946
7594
  EditorViewModes,
6947
7595
  Inline,
6948
7596
  InputModeExtensions,
6949
7597
  List,
7598
+ PreviewProvider,
6950
7599
  RefDropdownMenu,
6951
7600
  RefPopover,
6952
7601
  RemoteSelectionsDecorator,
@@ -6970,11 +7619,14 @@ export {
6970
7619
  closeEffect,
6971
7620
  command,
6972
7621
  commandKeyBindings,
7622
+ commandMenu,
7623
+ commandRangeEffect,
6973
7624
  commands,
6974
7625
  commentClickedEffect,
6975
7626
  comments,
6976
7627
  commentsState,
6977
7628
  convertTreeToJson,
7629
+ coreSlashCommands,
6978
7630
  createBasicExtensions,
6979
7631
  createComment,
6980
7632
  createDataExtensions,
@@ -7002,6 +7654,7 @@ export {
7002
7654
  editorSlots,
7003
7655
  editorWidth,
7004
7656
  editorWithToolbarLayout,
7657
+ filterItems,
7005
7658
  flattenRect,
7006
7659
  floatingMenu,
7007
7660
  focus,
@@ -7010,14 +7663,21 @@ export {
7010
7663
  formattingEquals,
7011
7664
  formattingKeymap,
7012
7665
  getFormatting,
7666
+ getItem,
7013
7667
  getListItemContent,
7668
+ getNextItem,
7669
+ getPreviousItem,
7014
7670
  getRange,
7671
+ hashtag,
7015
7672
  image,
7016
7673
  indentItemLess,
7017
7674
  indentItemMore,
7675
+ insertAtCursor,
7676
+ insertAtLineStart,
7018
7677
  insertTable,
7019
7678
  itemToJSON,
7020
- keymap13 as keymap,
7679
+ keymap14 as keymap,
7680
+ linkSlashCommands,
7021
7681
  linkTooltip,
7022
7682
  listItemToString,
7023
7683
  listener,
@@ -7029,6 +7689,7 @@ export {
7029
7689
  mention,
7030
7690
  moveItemDown,
7031
7691
  moveItemUp,
7692
+ multilinePlaceholder,
7032
7693
  openCommand,
7033
7694
  openEffect,
7034
7695
  outliner,
@@ -7071,6 +7732,7 @@ export {
7071
7732
  treeFacet,
7072
7733
  typeahead,
7073
7734
  typewriter,
7735
+ useCommandMenu,
7074
7736
  useComments,
7075
7737
  useEditorToolbarState,
7076
7738
  useFormattingState,