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