@dxos/react-ui-editor 0.6.7 → 0.6.8-main.3be982f

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 (109) hide show
  1. package/dist/lib/browser/index.mjs +1019 -796
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/{hooks/InputMode.stories.d.ts → InputMode.stories.d.ts} +6 -4
  5. package/dist/types/src/InputMode.stories.d.ts.map +1 -0
  6. package/dist/types/src/{hooks/TextEditor.stories.d.ts → TextEditor.stories.d.ts} +43 -26
  7. package/dist/types/src/TextEditor.stories.d.ts.map +1 -0
  8. package/dist/types/src/components/Toolbar/Toolbar.d.ts +9 -9
  9. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  10. package/dist/types/src/defaults.d.ts +10 -0
  11. package/dist/types/src/defaults.d.ts.map +1 -0
  12. package/dist/types/src/extensions/autocomplete.d.ts +2 -2
  13. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  14. package/dist/types/src/extensions/automerge/automerge.stories.d.ts +6 -4
  15. package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
  16. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
  17. package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
  18. package/dist/types/src/extensions/blast.d.ts.map +1 -1
  19. package/dist/types/src/extensions/command/state.d.ts +1 -1
  20. package/dist/types/src/extensions/command/state.d.ts.map +1 -1
  21. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  22. package/dist/types/src/extensions/factories.d.ts.map +1 -1
  23. package/dist/types/src/extensions/folding.d.ts +7 -0
  24. package/dist/types/src/extensions/folding.d.ts.map +1 -0
  25. package/dist/types/src/extensions/index.d.ts +1 -0
  26. package/dist/types/src/extensions/index.d.ts.map +1 -1
  27. package/dist/types/src/extensions/markdown/decorate.d.ts +5 -1
  28. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  29. package/dist/types/src/extensions/markdown/formatting.d.ts +9 -9
  30. package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
  31. package/dist/types/src/extensions/markdown/image.d.ts +1 -1
  32. package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
  33. package/dist/types/src/extensions/markdown/link-paste.d.ts +6 -0
  34. package/dist/types/src/extensions/markdown/link-paste.d.ts.map +1 -0
  35. package/dist/types/src/extensions/markdown/link-paste.test.d.ts +2 -0
  36. package/dist/types/src/extensions/markdown/link-paste.test.d.ts.map +1 -0
  37. package/dist/types/src/extensions/markdown/parser.test.d.ts +2 -0
  38. package/dist/types/src/extensions/markdown/parser.test.d.ts.map +1 -0
  39. package/dist/types/src/extensions/state.d.ts.map +1 -1
  40. package/dist/types/src/extensions/util/error.d.ts +2 -0
  41. package/dist/types/src/extensions/util/error.d.ts.map +1 -0
  42. package/dist/types/src/extensions/util/index.d.ts +3 -1
  43. package/dist/types/src/extensions/util/index.d.ts.map +1 -1
  44. package/dist/types/src/extensions/util/overlap.d.ts.map +1 -1
  45. package/dist/types/src/extensions/util/react.d.ts +3 -0
  46. package/dist/types/src/extensions/util/react.d.ts.map +1 -0
  47. package/dist/types/src/hooks/useActionHandler.d.ts +1 -1
  48. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  49. package/dist/types/src/index.d.ts +1 -2
  50. package/dist/types/src/index.d.ts.map +1 -1
  51. package/dist/types/src/styles/index.d.ts +1 -1
  52. package/dist/types/src/styles/index.d.ts.map +1 -1
  53. package/dist/types/src/styles/markdown.d.ts +0 -1
  54. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  55. package/dist/types/src/styles/theme.d.ts +36 -0
  56. package/dist/types/src/styles/theme.d.ts.map +1 -0
  57. package/dist/types/src/styles/tokens.d.ts.map +1 -1
  58. package/dist/types/src/translations.d.ts +2 -0
  59. package/dist/types/src/translations.d.ts.map +1 -1
  60. package/dist/types/src/util.d.ts.map +1 -1
  61. package/package.json +26 -29
  62. package/src/{hooks/InputMode.stories.tsx → InputMode.stories.tsx} +6 -11
  63. package/src/{hooks/TextEditor.stories.tsx → TextEditor.stories.tsx} +139 -92
  64. package/src/components/Toolbar/Toolbar.tsx +17 -9
  65. package/src/defaults.ts +28 -0
  66. package/src/extensions/autocomplete.ts +24 -18
  67. package/src/extensions/automerge/automerge.stories.tsx +4 -6
  68. package/src/extensions/comments.ts +4 -0
  69. package/src/extensions/factories.ts +3 -2
  70. package/src/extensions/folding.tsx +34 -0
  71. package/src/extensions/index.ts +1 -0
  72. package/src/extensions/markdown/bundle.ts +1 -1
  73. package/src/extensions/markdown/decorate.ts +359 -129
  74. package/src/extensions/markdown/formatting.ts +10 -12
  75. package/src/extensions/markdown/image.ts +3 -1
  76. package/src/extensions/markdown/link-paste.test.ts +28 -0
  77. package/src/extensions/markdown/link-paste.ts +104 -0
  78. package/src/extensions/markdown/parser.test.ts +47 -0
  79. package/src/extensions/markdown/table.ts +21 -24
  80. package/src/extensions/util/error.ts +15 -0
  81. package/src/extensions/util/index.ts +3 -1
  82. package/src/extensions/util/overlap.ts +1 -0
  83. package/src/extensions/util/react.tsx +15 -0
  84. package/src/hooks/useTextEditor.ts +1 -1
  85. package/src/index.ts +2 -2
  86. package/src/styles/index.ts +1 -1
  87. package/src/styles/markdown.ts +4 -3
  88. package/src/{themes/default.ts → styles/theme.ts} +51 -43
  89. package/src/styles/tokens.ts +0 -1
  90. package/src/translations.ts +2 -0
  91. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +0 -57
  92. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +0 -1
  93. package/dist/types/src/extensions/markdown/linkPaste.d.ts +0 -16
  94. package/dist/types/src/extensions/markdown/linkPaste.d.ts.map +0 -1
  95. package/dist/types/src/extensions/markdown/linkPaste.test.d.ts +0 -2
  96. package/dist/types/src/extensions/markdown/linkPaste.test.d.ts.map +0 -1
  97. package/dist/types/src/hooks/InputMode.stories.d.ts.map +0 -1
  98. package/dist/types/src/hooks/TextEditor.stories.d.ts.map +0 -1
  99. package/dist/types/src/styles/layout.d.ts +0 -4
  100. package/dist/types/src/styles/layout.d.ts.map +0 -1
  101. package/dist/types/src/themes/default.d.ts +0 -14
  102. package/dist/types/src/themes/default.d.ts.map +0 -1
  103. package/dist/types/src/themes/index.d.ts +0 -2
  104. package/dist/types/src/themes/index.d.ts.map +0 -1
  105. package/src/components/Toolbar/Toolbar.stories.tsx +0 -119
  106. package/src/extensions/markdown/linkPaste.test.ts +0 -45
  107. package/src/extensions/markdown/linkPaste.ts +0 -113
  108. package/src/styles/layout.ts +0 -9
  109. package/src/themes/index.ts +0 -5
@@ -15,6 +15,8 @@ var translations_default = [
15
15
  "blockquote label": "Block quote",
16
16
  "codeblock label": "Code block",
17
17
  "comment label": "Create comment",
18
+ "selection overlaps existing comment label": "Selection overlaps existing comment",
19
+ "select text to comment label": "Select text to comment",
18
20
  "image label": "Insert image",
19
21
  "heading label": "Heading level",
20
22
  "table label": "Create table",
@@ -38,10 +40,10 @@ import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
38
40
  // packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
39
41
  import { ChatText, Code, CodeBlock, Image, Link, ListBullets, ListChecks, ListNumbers, Paragraph, Quotes, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic, CaretDown, Check, PencilSimpleSlash, MarkdownLogo, PencilSimple } from "@phosphor-icons/react";
40
42
  import { createContext } from "@radix-ui/react-context";
41
- import React, { useEffect as useEffect2, useRef, useState as useState3 } from "react";
43
+ import React3, { useEffect as useEffect2, useRef, useState as useState3 } from "react";
42
44
  import { useDropzone } from "react-dropzone";
43
45
  import { Button, DensityProvider, DropdownMenu, ElevationProvider, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
44
- import { getSize } from "@dxos/react-ui-theme";
46
+ import { getSize as getSize2 } from "@dxos/react-ui-theme";
45
47
 
46
48
  // packages/ui/react-ui-editor/src/extensions/annotations.ts
47
49
  import { StateField } from "@codemirror/state";
@@ -149,8 +151,8 @@ var styles = EditorView.baseTheme({
149
151
  import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
150
152
  import { markdownLanguage } from "@codemirror/lang-markdown";
151
153
  import { keymap } from "@codemirror/view";
152
- var autocomplete = ({ activateOnTyping, onSearch }) => {
153
- return [
154
+ var autocomplete = ({ activateOnTyping, onSearch } = {}) => {
155
+ const extentions = [
154
156
  // https://codemirror.net/docs/ref/#view.keymap
155
157
  // https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
156
158
  // TODO(burdon): Set custom keymap.
@@ -163,21 +165,26 @@ var autocomplete = ({ activateOnTyping, onSearch }) => {
163
165
  // defaultKeymap: false,
164
166
  // TODO(burdon): Styles/fragments.
165
167
  tooltipClass: () => "shadow rounded"
166
- }),
167
- // TODO(burdon): Optional decoration via addToOptions
168
- markdownLanguage.data.of({
169
- autocomplete: (context) => {
170
- const match = context.matchBefore(/\w*/);
171
- if (!match || match.from === match.to && !context.explicit) {
172
- return null;
173
- }
174
- return {
175
- from: match.from,
176
- options: onSearch(match.text.toLowerCase())
177
- };
178
- }
179
168
  })
180
169
  ];
170
+ if (onSearch) {
171
+ extentions.push(
172
+ // TODO(burdon): Optional decoration via addToOptions
173
+ markdownLanguage.data.of({
174
+ autocomplete: (context) => {
175
+ const match = context.matchBefore(/\w*/);
176
+ if (!match || match.from === match.to && !context.explicit) {
177
+ return null;
178
+ }
179
+ return {
180
+ from: match.from,
181
+ options: onSearch(match.text.toLowerCase())
182
+ };
183
+ }
184
+ })
185
+ );
186
+ }
187
+ return extentions;
181
188
  };
182
189
 
183
190
  // packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
@@ -1351,12 +1358,43 @@ import { hoverTooltip, keymap as keymap4, Decoration as Decoration4, EditorView
1351
1358
  import sortBy from "lodash.sortby";
1352
1359
  import { useEffect, useMemo, useState } from "react";
1353
1360
  import { debounce } from "@dxos/async";
1354
- import { log as log4 } from "@dxos/log";
1361
+ import { log as log5 } from "@dxos/log";
1355
1362
  import { nonNullable } from "@dxos/util";
1356
1363
 
1364
+ // packages/ui/react-ui-editor/src/extensions/util/error.ts
1365
+ import { log as log3 } from "@dxos/log";
1366
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/util/error.ts";
1367
+ var wrapWithCatch = (fn) => {
1368
+ return (...args) => {
1369
+ try {
1370
+ return fn(...args);
1371
+ } catch (err) {
1372
+ log3.catch(err, void 0, {
1373
+ F: __dxlog_file5,
1374
+ L: 12,
1375
+ S: void 0,
1376
+ C: (f, a) => f(...a)
1377
+ });
1378
+ }
1379
+ };
1380
+ };
1381
+
1357
1382
  // packages/ui/react-ui-editor/src/extensions/util/overlap.ts
1358
1383
  var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
1359
1384
 
1385
+ // packages/ui/react-ui-editor/src/extensions/util/react.tsx
1386
+ import React from "react";
1387
+ import { createRoot } from "react-dom/client";
1388
+ import { ThemeProvider } from "@dxos/react-ui";
1389
+ import { defaultTx } from "@dxos/react-ui-theme";
1390
+ var renderRoot = (node) => {
1391
+ const el = document.createElement("div");
1392
+ createRoot(el).render(/* @__PURE__ */ React.createElement(ThemeProvider, {
1393
+ tx: defaultTx
1394
+ }, node));
1395
+ return el;
1396
+ };
1397
+
1360
1398
  // packages/ui/react-ui-editor/src/styles/markdown.ts
1361
1399
  import { mx } from "@dxos/react-ui-theme";
1362
1400
  var headings = {
@@ -1368,7 +1406,7 @@ var headings = {
1368
1406
  6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
1369
1407
  };
1370
1408
  var heading = (level) => {
1371
- return headings[level];
1409
+ return mx(headings[level], "dark:text-primary-400");
1372
1410
  };
1373
1411
  var light = "text-neutral-200 dark:text-neutral-800";
1374
1412
  var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
@@ -1378,7 +1416,10 @@ var strikethrough = "line-through";
1378
1416
  var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
1379
1417
  var codeMark = "font-mono text-primary-500";
1380
1418
  var inlineUrl = mx(code, "px-1");
1381
- var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
1419
+ var blockquote = mx("pl-1 mr-1 border-is-4 border-orange-500 dark:border-orange-500 text-transparent");
1420
+
1421
+ // packages/ui/react-ui-editor/src/styles/theme.ts
1422
+ import get2 from "lodash.get";
1382
1423
 
1383
1424
  // packages/ui/react-ui-editor/src/styles/tokens.ts
1384
1425
  import get from "lodash.get";
@@ -1386,20 +1427,258 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
1386
1427
  var tokens = tailwindConfig({}).theme;
1387
1428
  var getToken = (path, defaultValue = void 0) => get(tokens, path, defaultValue);
1388
1429
 
1389
- // packages/ui/react-ui-editor/src/styles/layout.ts
1390
- var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
1391
- var editorFillLayoutRoot = "bs-full relative";
1392
- var editorFillLayoutEditor = "!absolute inset-0";
1430
+ // packages/ui/react-ui-editor/src/styles/theme.ts
1431
+ var defaultTheme = {
1432
+ "&": {},
1433
+ "&.cm-focused": {
1434
+ outline: "none"
1435
+ },
1436
+ // Scroller.
1437
+ // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
1438
+ ".cm-scroller": {
1439
+ overflowY: "auto",
1440
+ fontFamily: get2(tokens, "fontFamily.body", []).join(","),
1441
+ lineHeight: 1.5
1442
+ },
1443
+ // Content.
1444
+ ".cm-content": {
1445
+ padding: "unset",
1446
+ // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
1447
+ fontSize: "16px"
1448
+ },
1449
+ "&light .cm-content": {
1450
+ color: get2(tokens, "extend.semanticColors.base.fg.light", "black")
1451
+ },
1452
+ "&dark .cm-content": {
1453
+ color: get2(tokens, "extend.semanticColors.base.fg.dark", "red")
1454
+ },
1455
+ //
1456
+ // Cursor
1457
+ //
1458
+ "&light .cm-cursor, &light .cm-dropCursor": {
1459
+ borderLeft: "2px solid black"
1460
+ },
1461
+ "&dark .cm-cursor, &dark .cm-dropCursor": {
1462
+ borderLeft: "2px solid white"
1463
+ },
1464
+ "&light .cm-placeholder": {
1465
+ color: get2(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
1466
+ },
1467
+ "&dark .cm-placeholder": {
1468
+ color: get2(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
1469
+ },
1470
+ //
1471
+ // line
1472
+ //
1473
+ ".cm-line": {
1474
+ paddingInline: 0
1475
+ },
1476
+ ".cm-activeLine": {
1477
+ background: "transparent"
1478
+ },
1479
+ //
1480
+ // gutter
1481
+ //
1482
+ ".cm-lineNumbers": {
1483
+ minWidth: "36px"
1484
+ },
1485
+ //
1486
+ // Selection
1487
+ //
1488
+ "&light .cm-selectionBackground": {
1489
+ background: get2(tokens, "extend.colors.primary.100")
1490
+ },
1491
+ "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
1492
+ background: get2(tokens, "extend.colors.primary.200")
1493
+ },
1494
+ "&dark .cm-selectionBackground": {
1495
+ background: get2(tokens, "extend.colors.primary.700")
1496
+ },
1497
+ "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
1498
+ background: get2(tokens, "extend.colors.primary.600")
1499
+ },
1500
+ //
1501
+ // Search
1502
+ //
1503
+ "&light .cm-searchMatch": {
1504
+ backgroundColor: get2(tokens, "extend.colors.yellow.100")
1505
+ },
1506
+ "&dark .cm-searchMatch": {
1507
+ backgroundColor: get2(tokens, "extend.colors.yellow.700")
1508
+ },
1509
+ //
1510
+ // link
1511
+ //
1512
+ ".cm-link": {
1513
+ color: get2(tokens, "extend.colors.primary.500"),
1514
+ textDecorationLine: "underline",
1515
+ textDecorationThickness: "1px",
1516
+ textUnderlineOffset: "2px",
1517
+ borderRadius: ".125rem",
1518
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1519
+ },
1520
+ //
1521
+ // tooltip
1522
+ //
1523
+ ".cm-tooltip": {},
1524
+ "&light .cm-tooltip": {
1525
+ background: `${get2(tokens, "extend.colors.neutral.100")} !important`
1526
+ },
1527
+ "&dark .cm-tooltip": {
1528
+ background: `${get2(tokens, "extend.colors.neutral.900")} !important`
1529
+ },
1530
+ ".cm-tooltip-below": {},
1531
+ //
1532
+ // autocomplete
1533
+ // https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
1534
+ //
1535
+ ".cm-tooltip.cm-tooltip-autocomplete": {
1536
+ marginTop: "4px",
1537
+ marginLeft: "-3px"
1538
+ },
1539
+ ".cm-tooltip.cm-tooltip-autocomplete > ul": {
1540
+ maxHeight: "20em !important"
1541
+ },
1542
+ ".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
1543
+ ".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
1544
+ // TODO(burdon): Can we add a class prefix to avoid adding !important?
1545
+ ".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
1546
+ paddingLeft: "4px !important",
1547
+ borderBottom: "none !important",
1548
+ color: get2(tokens, "extend.colors.primary.500")
1549
+ },
1550
+ ".cm-tooltip.cm-completionInfo": {
1551
+ border: get2(tokens, "extend.colors.neutral.500"),
1552
+ width: "360px !important",
1553
+ margin: "-10px 1px 0 1px",
1554
+ padding: "8px !important"
1555
+ },
1556
+ ".cm-completionIcon": {
1557
+ display: "none"
1558
+ },
1559
+ ".cm-completionLabel": {
1560
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1561
+ },
1562
+ ".cm-completionMatchedText": {
1563
+ textDecoration: "none !important",
1564
+ opacity: 0.5
1565
+ },
1566
+ //
1567
+ // table
1568
+ //
1569
+ ".cm-table *": {
1570
+ fontFamily: `${get2(tokens, "fontFamily.mono", []).join(",")} !important`,
1571
+ textDecoration: "none !important"
1572
+ },
1573
+ ".cm-table-head": {
1574
+ padding: "2px 16px 2px 0px",
1575
+ textAlign: "left",
1576
+ borderBottom: `1px solid ${get2(tokens, "extend.colors.primary.500")}`,
1577
+ color: get2(tokens, "extend.colors.neutral.500")
1578
+ },
1579
+ ".cm-table-cell": {
1580
+ padding: "2px 16px 2px 0px"
1581
+ },
1582
+ //
1583
+ // image
1584
+ //
1585
+ ".cm-image": {
1586
+ display: "block",
1587
+ height: "0"
1588
+ },
1589
+ ".cm-image.cm-loaded-image": {
1590
+ height: "auto",
1591
+ borderTop: "0.5rem solid transparent",
1592
+ borderBottom: "0.5rem solid transparent"
1593
+ },
1594
+ //
1595
+ // font size
1596
+ // TODO(thure): This appears to be the best or only way to set selection caret heights,
1597
+ // but it's far more verbose than it needs to be.
1598
+ //
1599
+ // ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
1600
+ // const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
1601
+ //
1602
+ // acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
1603
+ // acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
1604
+ // acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
1605
+ // return acc;
1606
+ // }, {}),
1607
+ // TODO(burdon): Override vars --cm-background.
1608
+ // https://www.npmjs.com/package/codemirror-theme-vars
1609
+ /**
1610
+ * Gutters
1611
+ */
1612
+ ".cm-gutters": {
1613
+ background: "transparent"
1614
+ },
1615
+ /**
1616
+ * Panels
1617
+ * TODO(burdon): Needs styling attention (esp. dark mode).
1618
+ * https://github.com/codemirror/search/blob/main/src/search.ts#L745
1619
+ *
1620
+ * Find/replace panel.
1621
+ * <div class="cm-announced">...</div>
1622
+ * <div class="cm-scroller">...</div>
1623
+ * <div class="cm-panels cm-panels-bottom">
1624
+ * <div class="cm-search cm-panel">
1625
+ * <input class="cm-textfield" />
1626
+ * <button class="cm-button">...</button>
1627
+ * <label><input type="checkbox" />...</label>
1628
+ * </div>
1629
+ * </div
1630
+ */
1631
+ ".cm-panels": {},
1632
+ ".cm-panel": {
1633
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1634
+ },
1635
+ ".cm-panel input[type=checkbox]": {
1636
+ marginRight: "0.4rem !important"
1637
+ },
1638
+ "&light .cm-panel": {
1639
+ background: get2(tokens, "extend.colors.neutral.50")
1640
+ },
1641
+ "&dark .cm-panel": {
1642
+ background: get2(tokens, "extend.colors.neutral.850")
1643
+ },
1644
+ ".cm-button": {
1645
+ margin: "4px",
1646
+ fontFamily: get2(tokens, "fontFamily.body", []).join(","),
1647
+ backgroundImage: "none",
1648
+ border: "none",
1649
+ "&:active": {
1650
+ backgroundImage: "none"
1651
+ }
1652
+ },
1653
+ "&light .cm-button": {
1654
+ background: get2(tokens, "extend.colors.neutral.100"),
1655
+ "&:hover": {
1656
+ background: get2(tokens, "extend.colors.neutral.200")
1657
+ },
1658
+ "&:active": {
1659
+ background: get2(tokens, "extend.colors.neutral.300")
1660
+ }
1661
+ },
1662
+ "&dark .cm-button": {
1663
+ background: get2(tokens, "extend.colors.neutral.800"),
1664
+ "&:hover": {
1665
+ background: get2(tokens, "extend.colors.neutral.700")
1666
+ },
1667
+ "&:active": {
1668
+ background: get2(tokens, "extend.colors.neutral.600")
1669
+ }
1670
+ }
1671
+ };
1393
1672
 
1394
1673
  // packages/ui/react-ui-editor/src/util.ts
1395
- import { log as log3 } from "@dxos/log";
1396
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
1674
+ import { log as log4 } from "@dxos/log";
1675
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
1397
1676
  var callbackWrapper = (fn) => (...args) => {
1398
1677
  try {
1399
1678
  return fn(...args);
1400
1679
  } catch (err) {
1401
- log3.catch(err, void 0, {
1402
- F: __dxlog_file5,
1680
+ log4.catch(err, void 0, {
1681
+ F: __dxlog_file6,
1403
1682
  L: 18,
1404
1683
  S: void 0,
1405
1684
  C: (f, a) => f(...a)
@@ -1422,10 +1701,10 @@ var logChanges = (trs) => {
1422
1701
  return changes2;
1423
1702
  }).filter(Boolean);
1424
1703
  if (changes.length) {
1425
- log3.info("changes", {
1704
+ log4.info("changes", {
1426
1705
  changes
1427
1706
  }, {
1428
- F: __dxlog_file5,
1707
+ F: __dxlog_file6,
1429
1708
  L: 39,
1430
1709
  S: void 0,
1431
1710
  C: (f, a) => f(...a)
@@ -1434,7 +1713,7 @@ var logChanges = (trs) => {
1434
1713
  };
1435
1714
 
1436
1715
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1437
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
1716
+ var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
1438
1717
  var documentId = Facet4.define({
1439
1718
  combine: (values) => values[0]
1440
1719
  });
@@ -1539,8 +1818,8 @@ var commentsDecorations = EditorView7.decorations.compute([
1539
1818
  const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
1540
1819
  const range = comment.range;
1541
1820
  if (!range) {
1542
- log4.warn("Invalid range:", range, {
1543
- F: __dxlog_file6,
1821
+ log5.warn("Invalid range:", range, {
1822
+ F: __dxlog_file7,
1544
1823
  L: 181,
1545
1824
  S: void 0,
1546
1825
  C: (f, a) => f(...a)
@@ -1951,9 +2230,9 @@ var useCommentClickListener = (onCommentClick) => {
1951
2230
  // packages/ui/react-ui-editor/src/extensions/debug.ts
1952
2231
  import { syntaxTree } from "@codemirror/language";
1953
2232
  import { StateField as StateField5 } from "@codemirror/state";
1954
- var debugNodeLogger = (log8 = console.log) => {
2233
+ var debugNodeLogger = (log9 = console.log) => {
1955
2234
  const logTokens = (state2) => syntaxTree(state2).iterate({
1956
- enter: (node) => log8(node.type)
2235
+ enter: (node) => log9(node.type)
1957
2236
  });
1958
2237
  return StateField5.define({
1959
2238
  create: (state2) => logTokens(state2),
@@ -1964,11 +2243,11 @@ var debugNodeLogger = (log8 = console.log) => {
1964
2243
  // packages/ui/react-ui-editor/src/extensions/doc.ts
1965
2244
  import { Facet as Facet5 } from "@codemirror/state";
1966
2245
  import { invariant as invariant3 } from "@dxos/invariant";
1967
- var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/doc.ts";
2246
+ var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/doc.ts";
1968
2247
  var documentId2 = Facet5.define({
1969
2248
  combine: (providers) => {
1970
2249
  invariant3(providers.length <= 1, void 0, {
1971
- F: __dxlog_file7,
2250
+ F: __dxlog_file8,
1972
2251
  L: 11,
1973
2252
  S: void 0,
1974
2253
  A: [
@@ -2025,271 +2304,10 @@ import { EditorState } from "@codemirror/state";
2025
2304
  import { EditorView as EditorView9, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap5, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
2026
2305
  import defaultsDeep2 from "lodash.defaultsdeep";
2027
2306
  import { generateName } from "@dxos/display-name";
2028
- import { log as log5 } from "@dxos/log";
2307
+ import { log as log6 } from "@dxos/log";
2029
2308
  import { hueTokens } from "@dxos/react-ui-theme";
2030
2309
  import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
2031
-
2032
- // packages/ui/react-ui-editor/src/themes/default.ts
2033
- import get2 from "lodash.get";
2034
- var defaultTheme = {
2035
- //
2036
- // Main layout:
2037
- // https://codemirror.net/examples/styling
2038
- //
2039
- // <div class="cm-editor [cm-focused] [generated classes]">
2040
- // <div class="cm-scroller">
2041
- // <div class="cm-gutters">
2042
- // <div class="cm-gutter [...]">
2043
- // <div class="cm-gutterElement">...</div>
2044
- // </div>
2045
- // </div>
2046
- // <div class="cm-content" role="textbox" contenteditable="true">
2047
- // <div class="cm-line"></div>
2048
- // </div>
2049
- // <div class="cm-selectionLayer">
2050
- // <div class="cm-selectionBackground"></div>
2051
- // </div>
2052
- // <div class="cm-cursorLayer">
2053
- // <div class="cm-cursor"></div>
2054
- // </div>
2055
- // </div>
2056
- // </div>
2057
- //
2058
- "&": {},
2059
- "&.cm-focused": {
2060
- outline: "none"
2061
- },
2062
- // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
2063
- ".cm-scroller": {
2064
- // TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
2065
- // Inside of that is the scroller element. If the editor has its own scrollbar, this one should be styled with overflow: auto. But it doesn't have to—the editor also supports growing to accomodate its content, or growing up to a certain max-height and then scrolling.
2066
- overflowY: "auto",
2067
- fontFamily: get2(tokens, "fontFamily.body", []).join(","),
2068
- lineHeight: 1.5
2069
- },
2070
- ".cm-content": {
2071
- // TODO(burdon): Is it possible to remove the padding value from CM's default theme?
2072
- // padding: 'unset',
2073
- // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
2074
- fontSize: "16px"
2075
- },
2076
- "&light .cm-content": {
2077
- color: get2(tokens, "extend.semanticColors.base.fg.light", "black"),
2078
- caretColor: "black"
2079
- },
2080
- "&dark .cm-content": {
2081
- color: get2(tokens, "extend.semanticColors.base.fg.dark", "white"),
2082
- caretColor: "white"
2083
- },
2084
- //
2085
- // Cursor
2086
- //
2087
- "&light .cm-cursor, &light .cm-dropCursor": {
2088
- borderLeft: "2px solid black"
2089
- },
2090
- "&dark .cm-cursor, &dark .cm-dropCursor": {
2091
- borderLeft: "2px solid white"
2092
- },
2093
- "&light .cm-placeholder": {
2094
- color: get2(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
2095
- },
2096
- "&dark .cm-placeholder": {
2097
- color: get2(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
2098
- },
2099
- //
2100
- // line
2101
- //
2102
- ".cm-line": {
2103
- paddingInline: 0
2104
- },
2105
- ".cm-activeLine": {
2106
- background: "transparent"
2107
- },
2108
- //
2109
- // gutter
2110
- //
2111
- ".cm-gutterElement": {
2112
- width: "48px"
2113
- },
2114
- //
2115
- // Selection
2116
- //
2117
- "&light .cm-selectionBackground": {
2118
- background: get2(tokens, "extend.colors.primary.100")
2119
- },
2120
- "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
2121
- background: get2(tokens, "extend.colors.primary.200")
2122
- },
2123
- "&dark .cm-selectionBackground": {
2124
- background: get2(tokens, "extend.colors.primary.700")
2125
- },
2126
- "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
2127
- background: get2(tokens, "extend.colors.primary.600")
2128
- },
2129
- //
2130
- // Search
2131
- //
2132
- "&light .cm-searchMatch": {
2133
- backgroundColor: get2(tokens, "extend.colors.yellow.100")
2134
- },
2135
- "&dark .cm-searchMatch": {
2136
- backgroundColor: get2(tokens, "extend.colors.yellow.700")
2137
- },
2138
- //
2139
- // link
2140
- //
2141
- ".cm-link": {
2142
- color: get2(tokens, "extend.colors.primary.500"),
2143
- textDecorationLine: "underline",
2144
- textDecorationThickness: "1px",
2145
- textUnderlineOffset: "2px",
2146
- borderRadius: ".125rem",
2147
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
2148
- },
2149
- //
2150
- // tooltip
2151
- //
2152
- ".cm-tooltip": {
2153
- border: "none"
2154
- },
2155
- "&light .cm-tooltip": {
2156
- background: `${get2(tokens, "extend.colors.neutral.100")} !important`
2157
- },
2158
- "&dark .cm-tooltip": {
2159
- background: `${get2(tokens, "extend.colors.neutral.900")} !important`
2160
- },
2161
- ".cm-tooltip-below": {},
2162
- //
2163
- // autocomplete
2164
- // https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
2165
- //
2166
- ".cm-tooltip-autocomplete": {
2167
- marginTop: "4px",
2168
- marginLeft: "-3px"
2169
- },
2170
- ".cm-tooltip-autocomplete > ul": {
2171
- maxHeight: "20em !important"
2172
- },
2173
- ".cm-tooltip-autocomplete > ul > li": {},
2174
- ".cm-tooltip-autocomplete > ul > li[aria-selected]": {},
2175
- // TODO(burdon): Can we add a class prefix to avoid adding !important?
2176
- ".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
2177
- paddingLeft: "4px !important",
2178
- borderBottom: "none !important",
2179
- color: get2(tokens, "extend.colors.primary.500")
2180
- },
2181
- ".cm-completionIcon": {
2182
- display: "none"
2183
- },
2184
- ".cm-completionLabel": {
2185
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
2186
- },
2187
- ".cm-completionMatchedText": {
2188
- textDecoration: "none !important",
2189
- opacity: 0.5
2190
- },
2191
- //
2192
- // table
2193
- //
2194
- ".cm-table *": {
2195
- fontFamily: `${get2(tokens, "fontFamily.mono", []).join(",")} !important`,
2196
- textDecoration: "none !important"
2197
- },
2198
- ".cm-table-head": {
2199
- padding: "2px 16px 2px 0px",
2200
- borderBottom: `1px solid ${get2(tokens, "extend.colors.neutral.500")}`,
2201
- fontWeight: 100,
2202
- textAlign: "left",
2203
- color: get2(tokens, "extend.colors.neutral.500")
2204
- },
2205
- ".cm-table-cell": {
2206
- padding: "2px 16px 2px 0px"
2207
- },
2208
- //
2209
- // image
2210
- //
2211
- ".cm-image": {
2212
- display: "block",
2213
- height: "0"
2214
- },
2215
- ".cm-image.cm-loaded-image": {
2216
- height: "auto",
2217
- borderTop: "0.5rem solid transparent",
2218
- borderBottom: "0.5rem solid transparent"
2219
- },
2220
- //
2221
- // font size
2222
- // TODO(thure): This appears to be the best or only way to set selection caret heights,
2223
- // but it's far more verbose than it needs to be.
2224
- //
2225
- // ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
2226
- // const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
2227
- //
2228
- // acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
2229
- // acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
2230
- // acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
2231
- // return acc;
2232
- // }, {}),
2233
- /**
2234
- * Panels
2235
- * TODO(burdon): Needs styling attention (esp. dark mode).
2236
- * https://github.com/codemirror/search/blob/main/src/search.ts#L745
2237
- *
2238
- * Find/replace panel.
2239
- * <div class="cm-announced">...</div>
2240
- * <div class="cm-scroller">...</div>
2241
- * <div class="cm-panels cm-panels-bottom">
2242
- * <div class="cm-search cm-panel">
2243
- * <input class="cm-textfield" />
2244
- * <button class="cm-button">...</button>
2245
- * <label><input type="checkbox" />...</label>
2246
- * </div>
2247
- * </div
2248
- */
2249
- ".cm-panels": {},
2250
- ".cm-panel": {
2251
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
2252
- },
2253
- ".cm-panel input[type=checkbox]": {
2254
- marginRight: "0.4rem !important"
2255
- },
2256
- "&light .cm-panel": {
2257
- background: get2(tokens, "extend.colors.neutral.50")
2258
- },
2259
- "&dark .cm-panel": {
2260
- background: get2(tokens, "extend.colors.neutral.850")
2261
- },
2262
- ".cm-button": {
2263
- margin: "4px",
2264
- fontFamily: get2(tokens, "fontFamily.body", []).join(","),
2265
- backgroundImage: "none",
2266
- border: "none",
2267
- "&:active": {
2268
- backgroundImage: "none"
2269
- }
2270
- },
2271
- "&light .cm-button": {
2272
- background: get2(tokens, "extend.colors.neutral.100"),
2273
- "&:hover": {
2274
- background: get2(tokens, "extend.colors.neutral.200")
2275
- },
2276
- "&:active": {
2277
- background: get2(tokens, "extend.colors.neutral.300")
2278
- }
2279
- },
2280
- "&dark .cm-button": {
2281
- background: get2(tokens, "extend.colors.neutral.800"),
2282
- "&:hover": {
2283
- background: get2(tokens, "extend.colors.neutral.700")
2284
- },
2285
- "&:active": {
2286
- background: get2(tokens, "extend.colors.neutral.600")
2287
- }
2288
- }
2289
- };
2290
-
2291
- // packages/ui/react-ui-editor/src/extensions/factories.ts
2292
- var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
2310
+ var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
2293
2311
  var preventNewline = EditorState.transactionFilter.of((tr) => tr.newDoc.lines > 1 ? [] : tr);
2294
2312
  var defaultBasicOptions = {
2295
2313
  allowMultipleSelections: true,
@@ -2313,9 +2331,9 @@ var createBasicExtensions = (_props) => {
2313
2331
  return [
2314
2332
  // NOTE: Doesn't catch errors in keymap functions.
2315
2333
  EditorView9.exceptionSink.of((err) => {
2316
- log5.catch(err, void 0, {
2317
- F: __dxlog_file8,
2318
- L: 92,
2334
+ log6.catch(err, void 0, {
2335
+ F: __dxlog_file9,
2336
+ L: 91,
2319
2337
  S: void 0,
2320
2338
  C: (f, a) => f(...a)
2321
2339
  });
@@ -2393,6 +2411,28 @@ var createDataExtensions = ({ id, text, space, identity }) => {
2393
2411
  return extensions;
2394
2412
  };
2395
2413
 
2414
+ // packages/ui/react-ui-editor/src/extensions/folding.tsx
2415
+ import { codeFolding, foldGutter } from "@codemirror/language";
2416
+ import React2 from "react";
2417
+ import { ThemeProvider as ThemeProvider2 } from "@dxos/react-ui";
2418
+ import { defaultTx as defaultTx2, getSize, mx as mx2 } from "@dxos/react-ui-theme";
2419
+ var folding = (_props = {}) => [
2420
+ codeFolding({
2421
+ placeholderDOM: () => document.createElement("div")
2422
+ }),
2423
+ foldGutter({
2424
+ markerDOM: (open) => {
2425
+ return renderRoot(/* @__PURE__ */ React2.createElement(ThemeProvider2, {
2426
+ tx: defaultTx2
2427
+ }, /* @__PURE__ */ React2.createElement("svg", {
2428
+ className: mx2(getSize(3), "m-3 cursor-pointer", open && "rotate-90")
2429
+ }, /* @__PURE__ */ React2.createElement("use", {
2430
+ href: "/icons.svg#ph--caret-right--regular"
2431
+ }))));
2432
+ }
2433
+ })
2434
+ ];
2435
+
2396
2436
  // packages/ui/react-ui-editor/src/extensions/listener.ts
2397
2437
  import { EditorView as EditorView10 } from "@codemirror/view";
2398
2438
  var listener = ({ onFocus, onChange }) => {
@@ -3004,7 +3044,6 @@ var addList = (type) => {
3004
3044
  renumberListItems(next.firstChild, last.counter + 1, changes, state2.doc);
3005
3045
  }
3006
3046
  }
3007
- "Oeswe";
3008
3047
  const changeSet = state2.changes(changes);
3009
3048
  dispatch(state2.update({
3010
3049
  changes: changeSet,
@@ -3512,9 +3551,7 @@ var useFormattingState = () => {
3512
3551
  return prevState;
3513
3552
  });
3514
3553
  }
3515
- }), [
3516
- setState
3517
- ]);
3554
+ }), []);
3518
3555
  return [
3519
3556
  state2,
3520
3557
  observer
@@ -3761,102 +3798,102 @@ var markdownHighlightStyle = (readonly) => {
3761
3798
  });
3762
3799
  };
3763
3800
 
3764
- // packages/ui/react-ui-editor/src/extensions/markdown/linkPaste.ts
3801
+ // packages/ui/react-ui-editor/src/extensions/markdown/link-paste.ts
3765
3802
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
3766
3803
  import { Transaction } from "@codemirror/state";
3767
3804
  import { ViewPlugin as ViewPlugin5 } from "@codemirror/view";
3768
- var VALID_PROTOCOLS = [
3769
- "http:",
3770
- "https:",
3771
- "mailto:",
3772
- "tel:"
3773
- ];
3774
- var createTextLink = (text, url) => `[${text}](${url})`;
3775
- var createUrlLink = (url) => {
3776
- const displayUrl = formatUrlForDisplay(url);
3777
- return `[${displayUrl}](${url})`;
3778
- };
3779
- var formatUrlForDisplay = (url) => {
3780
- let formattedUrl = url.replace(/^https?:\/\//, "");
3781
- formattedUrl = formattedUrl.replace(/^www\./, "");
3782
- formattedUrl = formattedUrl.replace(/\.com\/$/, ".com");
3783
- return truncateQueryParams(formattedUrl);
3784
- };
3785
- var truncateQueryParams = (url, maxQueryLength = 15) => {
3786
- const [urlBase, queryString] = url.split("?");
3787
- if (!queryString) {
3788
- return urlBase;
3789
- }
3790
- if (queryString.length > maxQueryLength) {
3791
- const truncatedQuery = queryString.slice(0, maxQueryLength) + "...";
3792
- return `${urlBase}?${truncatedQuery}`;
3793
- } else {
3794
- return `${urlBase}?${queryString}`;
3795
- }
3796
- };
3797
- var isValidUrl = (str) => {
3798
- try {
3799
- const url = new URL(str);
3800
- return VALID_PROTOCOLS.includes(url.protocol);
3801
- } catch (e) {
3802
- return false;
3803
- }
3804
- };
3805
- var onNextUpdate = (callback) => setTimeout(callback, 0);
3806
3805
  var linkPastePlugin = ViewPlugin5.fromClass(class {
3807
- constructor(view) {
3808
- this.view = view;
3809
- }
3810
3806
  update(update2) {
3811
3807
  for (const tr of update2.transactions) {
3812
3808
  const event = tr.annotation(Transaction.userEvent);
3813
3809
  if (event === "input.paste") {
3814
- this.handleInputRead(this.view, tr);
3815
- }
3816
- }
3817
- }
3818
- handleInputRead(view, tr) {
3819
- const changes = tr.changes;
3820
- if (changes.empty) {
3821
- return;
3822
- }
3823
- changes.iterChangedRanges((fromA, toA, fromB, toB) => {
3824
- const insertedText = view.state.sliceDoc(fromB, toB);
3825
- if (isValidUrl(insertedText) && !this.isInCodeBlock(view.state, fromB)) {
3826
- const replacedText = tr.startState.sliceDoc(fromA, toA);
3827
- onNextUpdate(() => {
3828
- view.dispatch(this.createLinkTransaction(view.state, fromA, toB, insertedText, replacedText));
3810
+ const changes = tr.changes;
3811
+ if (changes.empty) {
3812
+ return;
3813
+ }
3814
+ changes.iterChangedRanges((fromA, toA, fromB, toB) => {
3815
+ const insertedUrl = getValidUrl(update2.view.state.sliceDoc(fromB, toB));
3816
+ if (insertedUrl && isValidPosition(update2.view.state, fromB)) {
3817
+ const replacedText = tr.startState.sliceDoc(fromA, toA);
3818
+ setTimeout(() => {
3819
+ update2.view.dispatch(update2.view.state.update({
3820
+ changes: {
3821
+ from: fromA,
3822
+ to: toB,
3823
+ insert: createLink(insertedUrl, replacedText)
3824
+ }
3825
+ }));
3826
+ });
3827
+ }
3829
3828
  });
3830
3829
  }
3831
- });
3832
- }
3833
- /**
3834
- * Determines if a given position is within a code block.
3835
- * Traverses the syntax tree upwards from the position,
3836
- * checking for CodeBlock or FencedCode nodes.
3837
- */
3838
- isInCodeBlock(state2, pos) {
3839
- const tree = syntaxTree3(state2);
3840
- let node = tree.resolveInner(pos, -1);
3841
- while (node) {
3842
- if (node.name.includes("Code") || node.name.includes("FencedCode")) {
3843
- return true;
3844
- }
3845
- node = node.parent;
3846
3830
  }
3847
- return false;
3848
- }
3849
- createLinkTransaction(state2, from, to, url, text) {
3850
- const linkText = text.trim() ? createTextLink(text, url) : createUrlLink(url);
3851
- return state2.update({
3852
- changes: {
3853
- from,
3854
- to,
3855
- insert: linkText
3856
- }
3857
- });
3858
3831
  }
3859
3832
  });
3833
+ var createLink = (url, label) => {
3834
+ const { host, pathname } = url;
3835
+ const [, extension] = pathname.split(".");
3836
+ const imageExtensions = [
3837
+ "jpg",
3838
+ "jpeg",
3839
+ "png",
3840
+ "gif",
3841
+ "svg",
3842
+ "webp"
3843
+ ];
3844
+ if (imageExtensions.includes(extension)) {
3845
+ return `![${label || host}](${url})`;
3846
+ }
3847
+ if (!label) {
3848
+ label = createLinkLabel(url);
3849
+ }
3850
+ return `[${label}](${url})`;
3851
+ };
3852
+ var createLinkLabel = (url) => {
3853
+ let { protocol, host, pathname } = url;
3854
+ if (protocol === "http:" || protocol === "https:") {
3855
+ protocol = "";
3856
+ }
3857
+ host = host.replace(/^www\./, "");
3858
+ return [
3859
+ protocol,
3860
+ host
3861
+ ].filter(Boolean).join("//") + (pathname !== "/" ? pathname : "");
3862
+ };
3863
+ var getValidUrl = (str) => {
3864
+ const validProtocols = [
3865
+ "http:",
3866
+ "https:",
3867
+ "mailto:",
3868
+ "tel:"
3869
+ ];
3870
+ try {
3871
+ const url = new URL(str);
3872
+ if (!validProtocols.includes(url.protocol)) {
3873
+ return void 0;
3874
+ }
3875
+ return url;
3876
+ } catch (_err) {
3877
+ return void 0;
3878
+ }
3879
+ };
3880
+ var isValidPosition = (state2, pos) => {
3881
+ const invalidPositions = /* @__PURE__ */ new Set([
3882
+ "Link",
3883
+ "LinkMark",
3884
+ "Code",
3885
+ "FencedCode"
3886
+ ]);
3887
+ const tree = syntaxTree3(state2);
3888
+ let node = tree.resolveInner(pos, -1);
3889
+ while (node) {
3890
+ if (invalidPositions.has(node.name)) {
3891
+ return false;
3892
+ }
3893
+ node = node.parent;
3894
+ }
3895
+ return true;
3896
+ };
3860
3897
 
3861
3898
  // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
3862
3899
  var createMarkdownExtensions = ({ themeMode } = {}) => {
@@ -3896,18 +3933,204 @@ var createMarkdownExtensions = ({ themeMode } = {}) => {
3896
3933
  };
3897
3934
 
3898
3935
  // packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
3936
+ import { syntaxTree as syntaxTree6 } from "@codemirror/language";
3937
+ import { RangeSetBuilder as RangeSetBuilder3, StateEffect as StateEffect4 } from "@codemirror/state";
3938
+ import { EditorView as EditorView14, Decoration as Decoration7, WidgetType as WidgetType5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
3939
+ import { invariant as invariant4 } from "@dxos/invariant";
3940
+ import { mx as mx3 } from "@dxos/react-ui-theme";
3941
+
3942
+ // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
3899
3943
  import { syntaxTree as syntaxTree4 } from "@codemirror/language";
3900
- import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
3901
- import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
3902
- import { mx as mx2 } from "@dxos/react-ui-theme";
3903
- var HorizontalRuleWidget = class extends WidgetType3 {
3944
+ import { StateField as StateField6 } from "@codemirror/state";
3945
+ import { Decoration as Decoration5, EditorView as EditorView12, WidgetType as WidgetType3 } from "@codemirror/view";
3946
+ var image = (_options = {}) => {
3947
+ return StateField6.define({
3948
+ create: (state2) => {
3949
+ return Decoration5.set(buildDecorations(0, state2.doc.length, state2));
3950
+ },
3951
+ update: (value, tr) => {
3952
+ if (!tr.docChanged && !tr.selection) {
3953
+ return value;
3954
+ }
3955
+ const cursor = tr.state.selection.main.head;
3956
+ const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
3957
+ let from = Math.min(cursor, oldCursor);
3958
+ let to = Math.max(cursor, oldCursor);
3959
+ tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
3960
+ from = Math.min(from, fromB);
3961
+ to = Math.max(to, toB);
3962
+ });
3963
+ from = tr.state.doc.lineAt(from).from;
3964
+ to = tr.state.doc.lineAt(to).to;
3965
+ return value.map(tr.changes).update({
3966
+ filterFrom: from,
3967
+ filterTo: to,
3968
+ filter: () => false,
3969
+ add: buildDecorations(from, to, tr.state)
3970
+ });
3971
+ },
3972
+ provide: (field) => EditorView12.decorations.from(field)
3973
+ });
3974
+ };
3975
+ var preloaded = /* @__PURE__ */ new Set();
3976
+ var preloadImage = (url) => {
3977
+ if (!preloaded.has(url)) {
3978
+ const img = document.createElement("img");
3979
+ img.src = url;
3980
+ preloaded.add(url);
3981
+ }
3982
+ };
3983
+ var buildDecorations = (from, to, state2) => {
3984
+ const decorations = [];
3985
+ const cursor = state2.selection.main.head;
3986
+ syntaxTree4(state2).iterate({
3987
+ enter: (node) => {
3988
+ if (node.name === "Image") {
3989
+ const urlNode = node.node.getChild("URL");
3990
+ if (urlNode) {
3991
+ const hide2 = state2.readOnly || cursor < node.from || cursor > node.to;
3992
+ const url = state2.sliceDoc(urlNode.from, urlNode.to);
3993
+ preloadImage(url);
3994
+ decorations.push(Decoration5.replace({
3995
+ block: true,
3996
+ widget: new ImageWidget(url)
3997
+ }).range(hide2 ? node.from : node.to, node.to));
3998
+ }
3999
+ }
4000
+ },
4001
+ from,
4002
+ to
4003
+ });
4004
+ return decorations;
4005
+ };
4006
+ var ImageWidget = class extends WidgetType3 {
4007
+ constructor(_url) {
4008
+ super();
4009
+ this._url = _url;
4010
+ }
4011
+ eq(other) {
4012
+ return this._url === other._url;
4013
+ }
4014
+ toDOM(view) {
4015
+ const img = document.createElement("img");
4016
+ img.setAttribute("src", this._url);
4017
+ img.setAttribute("class", "cm-image");
4018
+ img.onload = () => img.classList.add("cm-loaded-image");
4019
+ return img;
4020
+ }
4021
+ };
4022
+ var imageUpload = (options = {}) => {
4023
+ };
4024
+
4025
+ // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
4026
+ import { syntaxTree as syntaxTree5 } from "@codemirror/language";
4027
+ import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField7 } from "@codemirror/state";
4028
+ import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
4029
+ var table = (options = {}) => {
4030
+ return StateField7.define({
4031
+ create: (state2) => update(state2, options),
4032
+ update: (_, tr) => update(tr.state, options),
4033
+ provide: (field) => EditorView13.decorations.from(field)
4034
+ });
4035
+ };
4036
+ var update = (state2, _options) => {
4037
+ const builder = new RangeSetBuilder2();
4038
+ const cursor = state2.selection.main.head;
4039
+ const tables = [];
4040
+ const getTable = () => tables[tables.length - 1];
4041
+ const getRow = () => {
4042
+ const table2 = getTable();
4043
+ return table2.rows?.[table2.rows.length - 1];
4044
+ };
4045
+ syntaxTree5(state2).iterate({
4046
+ enter: (node) => {
4047
+ switch (node.name) {
4048
+ case "Table": {
4049
+ tables.push({
4050
+ from: node.from,
4051
+ to: node.to
4052
+ });
4053
+ break;
4054
+ }
4055
+ case "TableHeader": {
4056
+ getTable().header = [];
4057
+ break;
4058
+ }
4059
+ case "TableRow": {
4060
+ (getTable().rows ??= []).push([]);
4061
+ break;
4062
+ }
4063
+ case "TableCell": {
4064
+ const row = getRow();
4065
+ if (row) {
4066
+ row.push(state2.sliceDoc(node.from, node.to));
4067
+ } else {
4068
+ getTable().header?.push(state2.sliceDoc(node.from, node.to));
4069
+ }
4070
+ break;
4071
+ }
4072
+ }
4073
+ }
4074
+ });
4075
+ tables.forEach((table2) => {
4076
+ const replace = state2.readOnly || cursor < table2.from || cursor > table2.to;
4077
+ if (replace) {
4078
+ builder.add(table2.from, table2.to, Decoration6.replace({
4079
+ block: true,
4080
+ widget: new TableWidget(table2)
4081
+ }));
4082
+ } else {
4083
+ builder.add(table2.from, table2.to, Decoration6.mark({
4084
+ class: "cm-table"
4085
+ }));
4086
+ }
4087
+ });
4088
+ return builder.finish();
4089
+ };
4090
+ var TableWidget = class extends WidgetType4 {
4091
+ constructor(_table) {
4092
+ super();
4093
+ this._table = _table;
4094
+ }
4095
+ eq(other) {
4096
+ return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
4097
+ }
4098
+ toDOM(view) {
4099
+ const div = document.createElement("div");
4100
+ const table2 = div.appendChild(document.createElement("table"));
4101
+ const header = table2.appendChild(document.createElement("thead"));
4102
+ const tr = header.appendChild(document.createElement("tr"));
4103
+ this._table.header?.forEach((cell) => {
4104
+ const th = document.createElement("th");
4105
+ th.setAttribute("class", "cm-table-head");
4106
+ tr.appendChild(th).textContent = cell;
4107
+ });
4108
+ const body = table2.appendChild(document.createElement("tbody"));
4109
+ this._table.rows?.forEach((row) => {
4110
+ const tr2 = body.appendChild(document.createElement("tr"));
4111
+ row.forEach((cell) => {
4112
+ const td = document.createElement("td");
4113
+ td.setAttribute("class", "cm-table-cell");
4114
+ tr2.appendChild(td).textContent = cell;
4115
+ });
4116
+ });
4117
+ return div;
4118
+ }
4119
+ ignoreEvent(e) {
4120
+ return !/^mouse/.test(e.type);
4121
+ }
4122
+ };
4123
+
4124
+ // packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
4125
+ var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts";
4126
+ var HorizontalRuleWidget = class extends WidgetType5 {
3904
4127
  toDOM() {
3905
4128
  const el = document.createElement("span");
3906
4129
  el.className = "cm-hr";
3907
4130
  return el;
3908
4131
  }
3909
4132
  };
3910
- var LinkButton = class extends WidgetType3 {
4133
+ var LinkButton = class extends WidgetType5 {
3911
4134
  constructor(url, render) {
3912
4135
  super();
3913
4136
  this.url = url;
@@ -3922,7 +4145,7 @@ var LinkButton = class extends WidgetType3 {
3922
4145
  return el;
3923
4146
  }
3924
4147
  };
3925
- var CheckboxWidget = class extends WidgetType3 {
4148
+ var CheckboxWidget = class extends WidgetType5 {
3926
4149
  constructor(_checked) {
3927
4150
  super();
3928
4151
  this._checked = _checked;
@@ -3932,14 +4155,14 @@ var CheckboxWidget = class extends WidgetType3 {
3932
4155
  }
3933
4156
  toDOM(view) {
3934
4157
  const input = document.createElement("input");
3935
- input.className = "cm-task-checkbox ch-checkbox ch-focus-ring -mbs-0.5";
4158
+ input.className = "cm-task-checkbox ch-checkbox ch-focus-ring";
3936
4159
  input.type = "checkbox";
3937
4160
  input.checked = this._checked;
3938
4161
  if (view.state.readOnly) {
3939
4162
  input.setAttribute("disabled", "true");
3940
4163
  } else {
3941
4164
  input.onmousedown = (event) => {
3942
- const pos = view.posAtDOM(input);
4165
+ const pos = view.posAtDOM(span);
3943
4166
  const text = view.state.sliceDoc(pos, pos + 3);
3944
4167
  if (text === (this._checked ? "[x]" : "[ ]")) {
3945
4168
  view.dispatch({
@@ -3953,157 +4176,302 @@ var CheckboxWidget = class extends WidgetType3 {
3953
4176
  }
3954
4177
  };
3955
4178
  }
3956
- return input;
4179
+ const span = document.createElement("span");
4180
+ span.className = "cm-task";
4181
+ span.appendChild(input);
4182
+ return span;
3957
4183
  }
3958
4184
  ignoreEvent() {
3959
4185
  return false;
3960
4186
  }
3961
4187
  };
3962
- var hide = Decoration5.replace({});
3963
- var fencedCodeLine = Decoration5.line({
3964
- class: mx2("cm-code cm-codeblock-line")
4188
+ var TextWidget = class extends WidgetType5 {
4189
+ constructor(text, className) {
4190
+ super();
4191
+ this.text = text;
4192
+ this.className = className;
4193
+ }
4194
+ toDOM() {
4195
+ const el = document.createElement("span");
4196
+ if (this.className) {
4197
+ el.className = this.className;
4198
+ }
4199
+ el.innerText = this.text;
4200
+ return el;
4201
+ }
4202
+ };
4203
+ var hide = Decoration7.replace({});
4204
+ var fencedCodeLine = Decoration7.line({
4205
+ class: mx3("cm-code cm-codeblock-line")
3965
4206
  });
3966
- var fencedCodeLineFirst = Decoration5.line({
3967
- class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
4207
+ var fencedCodeLineFirst = Decoration7.line({
4208
+ class: mx3("cm-code cm-codeblock-line", "cm-codeblock-first")
3968
4209
  });
3969
- var fencedCodeLineLast = Decoration5.line({
3970
- class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
4210
+ var fencedCodeLineLast = Decoration7.line({
4211
+ class: mx3("cm-code cm-codeblock-line", "cm-codeblock-last")
3971
4212
  });
3972
4213
  var commentBlockLine = fencedCodeLine;
3973
4214
  var commentBlockLineFirst = fencedCodeLineFirst;
3974
4215
  var commentBlockLineLast = fencedCodeLineLast;
3975
- var horizontalRule = Decoration5.replace({
4216
+ var horizontalRule = Decoration7.replace({
3976
4217
  widget: new HorizontalRuleWidget()
3977
4218
  });
3978
- var checkedTask = Decoration5.replace({
4219
+ var checkedTask = Decoration7.replace({
3979
4220
  widget: new CheckboxWidget(true)
3980
4221
  });
3981
- var uncheckedTask = Decoration5.replace({
4222
+ var uncheckedTask = Decoration7.replace({
3982
4223
  widget: new CheckboxWidget(false)
3983
4224
  });
3984
4225
  var editingRange = (state2, range, focus) => {
3985
4226
  const { readOnly, selection: { main: { head } } } = state2;
3986
4227
  return focus && !readOnly && head >= range.from && head <= range.to;
3987
4228
  };
3988
- var MarksByParent = /* @__PURE__ */ new Set([
4229
+ var autoHideTags = /* @__PURE__ */ new Set([
3989
4230
  "CodeMark",
4231
+ "CodeInfo",
3990
4232
  "EmphasisMark",
3991
4233
  "StrikethroughMark",
3992
4234
  "SubscriptMark",
3993
4235
  "SuperscriptMark"
3994
4236
  ]);
3995
- var buildDecorations = (view, options, focus) => {
3996
- const deco = new RangeSetBuilder2();
3997
- const atomicDeco = new RangeSetBuilder2();
4237
+ var bulletListIndentationWidth = 24;
4238
+ var orderedListIndentationWidth = 32;
4239
+ var buildDecorations2 = (view, options, focus) => {
4240
+ const deco = new RangeSetBuilder3();
4241
+ const atomicDeco = new RangeSetBuilder3();
3998
4242
  const { state: state2 } = view;
3999
- for (const { from, to } of view.visibleRanges) {
4000
- syntaxTree4(state2).iterate({
4001
- from,
4002
- to,
4003
- enter: (node) => {
4004
- switch (node.name) {
4005
- case "CommentBlock": {
4006
- const editing = editingRange(state2, node, focus);
4007
- for (const block of view.viewportLineBlocks) {
4008
- if (block.to < node.from) {
4009
- continue;
4010
- }
4011
- if (block.from > node.to) {
4012
- break;
4013
- }
4014
- const first = block.from <= node.from;
4015
- const last = block.to >= node.to && /^(\s>)*-->$/.test(state2.doc.sliceString(block.from, block.to));
4016
- deco.add(block.from, block.from, first ? commentBlockLineFirst : last ? commentBlockLineLast : commentBlockLine);
4017
- if (!editing && (first || last)) {
4018
- atomicDeco.add(block.from, block.to, hide);
4243
+ const headerLevels = [];
4244
+ const getHeaderLevels = (node, level) => {
4245
+ invariant4(level > 0, void 0, {
4246
+ F: __dxlog_file10,
4247
+ L: 157,
4248
+ S: void 0,
4249
+ A: [
4250
+ "level > 0",
4251
+ ""
4252
+ ]
4253
+ });
4254
+ if (level > headerLevels.length) {
4255
+ const len = headerLevels.length;
4256
+ headerLevels.length = level;
4257
+ headerLevels.fill(null, len);
4258
+ headerLevels[level - 1] = {
4259
+ type: node.name,
4260
+ from: node.from,
4261
+ to: node.to,
4262
+ level,
4263
+ number: 0
4264
+ };
4265
+ } else {
4266
+ headerLevels.splice(level);
4267
+ }
4268
+ return headerLevels.slice(0, level);
4269
+ };
4270
+ const listLevels = [];
4271
+ const enterList = (node) => {
4272
+ listLevels.push({
4273
+ type: node.name,
4274
+ from: node.from,
4275
+ to: node.to,
4276
+ level: listLevels.length,
4277
+ number: 0
4278
+ });
4279
+ };
4280
+ const leaveList = () => {
4281
+ listLevels.pop();
4282
+ };
4283
+ const getCurrentList = () => {
4284
+ invariant4(listLevels.length, void 0, {
4285
+ F: __dxlog_file10,
4286
+ L: 179,
4287
+ S: void 0,
4288
+ A: [
4289
+ "listLevels.length",
4290
+ ""
4291
+ ]
4292
+ });
4293
+ return listLevels[listLevels.length - 1];
4294
+ };
4295
+ const enterNode = (node) => {
4296
+ switch (node.name) {
4297
+ case "ATXHeading1":
4298
+ case "ATXHeading2":
4299
+ case "ATXHeading3":
4300
+ case "ATXHeading4":
4301
+ case "ATXHeading5":
4302
+ case "ATXHeading6": {
4303
+ const level = parseInt(node.name["ATXHeading".length]);
4304
+ const headers = getHeaderLevels(node, level);
4305
+ if (options.numberedHeadings?.from !== void 0) {
4306
+ headers[level - 1].number++;
4307
+ }
4308
+ const editing = editingRange(state2, node, focus);
4309
+ if (!editing) {
4310
+ const mark2 = node.node.firstChild;
4311
+ if (mark2?.name === "HeaderMark") {
4312
+ let text = view.state.sliceDoc(mark2.to, node.to).trim();
4313
+ const { from, to } = options.numberedHeadings ?? {};
4314
+ if (from && (!to || level <= to)) {
4315
+ const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".");
4316
+ if (num.length) {
4317
+ text = `${num} ${text}`;
4019
4318
  }
4020
4319
  }
4021
- break;
4320
+ deco.add(node.from, node.to, Decoration7.replace({
4321
+ widget: new TextWidget(text, heading(level))
4322
+ }));
4022
4323
  }
4023
- case "FencedCode": {
4024
- const editing = editingRange(state2, node, focus);
4025
- for (const block of view.viewportLineBlocks) {
4026
- if (block.to < node.from) {
4027
- continue;
4028
- }
4029
- if (block.from > node.to) {
4030
- break;
4031
- }
4032
- const first = block.from <= node.from;
4033
- const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
4034
- deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
4035
- if (!editing && (first || last)) {
4036
- atomicDeco.add(block.from, block.to, hide);
4037
- }
4038
- }
4039
- return false;
4324
+ }
4325
+ return false;
4326
+ }
4327
+ case "BulletList":
4328
+ case "OrderedList": {
4329
+ enterList(node);
4330
+ break;
4331
+ }
4332
+ case "ListItem": {
4333
+ const list = getCurrentList();
4334
+ const width = list.type === "OrderedList" ? orderedListIndentationWidth : bulletListIndentationWidth;
4335
+ const offset = ((list.level ?? 0) + 1) * width;
4336
+ const start = state2.doc.lineAt(node.from);
4337
+ deco.add(start.from, start.from, Decoration7.line({
4338
+ class: "cm-list-item",
4339
+ attributes: {
4340
+ // Subtract 0.25em to account for the space CM adds to Paragraph nodes following the ListItem.
4341
+ // Note: This makes the cursor appear to be left of the margin.
4342
+ style: `padding-left: ${offset}px; text-indent: calc(-${width}px - 0.25em);`
4040
4343
  }
4041
- case "Link": {
4042
- const marks = node.node.getChildren("LinkMark");
4043
- const urlNode = node.node.getChild("URL");
4044
- const editing = editingRange(state2, node, focus);
4045
- if (urlNode && marks.length >= 2) {
4046
- const url = state2.sliceDoc(urlNode.from, urlNode.to);
4047
- if (!editing) {
4048
- atomicDeco.add(node.from, marks[0].to, hide);
4049
- }
4050
- deco.add(marks[0].to, marks[1].from, Decoration5.mark({
4051
- tagName: "a",
4052
- attributes: {
4053
- class: "cm-link",
4054
- href: url,
4055
- rel: "noreferrer",
4056
- target: "_blank"
4057
- }
4058
- }));
4059
- if (!editing) {
4060
- atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
4061
- widget: new LinkButton(url, options.renderLinkButton)
4062
- }) : hide);
4063
- }
4064
- }
4065
- break;
4344
+ }));
4345
+ const line = state2.doc.sliceString(start.from, node.to);
4346
+ const whitespace = line.match(/^ */)?.[0].length ?? 0;
4347
+ if (whitespace) {
4348
+ atomicDeco.add(start.from, start.from + whitespace, hide);
4349
+ }
4350
+ break;
4351
+ }
4352
+ case "ListMark": {
4353
+ const task = tree.resolve(node.to + 1, 1).name === "TaskMarker";
4354
+ if (task) {
4355
+ atomicDeco.add(node.from, node.to, hide);
4356
+ break;
4357
+ }
4358
+ const list = getCurrentList();
4359
+ const label = list.type === "OrderedList" ? `${++list.number}.` : "-";
4360
+ atomicDeco.add(node.from, node.to, Decoration7.replace({
4361
+ widget: new TextWidget(label, list.type === "OrderedList" ? "cm-list-mark cm-list-mark-ordered" : "cm-list-mark cm-list-mark-bullet")
4362
+ }));
4363
+ break;
4364
+ }
4365
+ case "TaskMarker": {
4366
+ if (!editingRange(state2, node, focus)) {
4367
+ const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
4368
+ atomicDeco.add(node.from - 2, node.from - 1, Decoration7.mark({
4369
+ class: "cm-task-checkbox"
4370
+ }));
4371
+ atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
4372
+ }
4373
+ break;
4374
+ }
4375
+ case "CommentBlock": {
4376
+ const editing = editingRange(state2, node, focus);
4377
+ for (const block of view.viewportLineBlocks) {
4378
+ if (block.to < node.from) {
4379
+ continue;
4066
4380
  }
4067
- case "HeaderMark": {
4068
- const parent = node.node.parent;
4069
- if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
4070
- const next = state2.doc.sliceString(node.to, node.to + 1);
4071
- atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
4072
- }
4381
+ if (block.from > node.to) {
4073
4382
  break;
4074
4383
  }
4075
- case "HorizontalRule": {
4076
- if (!editingRange(state2, node, focus)) {
4077
- deco.add(node.from, node.to, horizontalRule);
4078
- }
4079
- break;
4384
+ const first = block.from <= node.from;
4385
+ const last = block.to >= node.to && /^(\s>)*-->$/.test(state2.doc.sliceString(block.from, block.to));
4386
+ deco.add(block.from, block.from, first ? commentBlockLineFirst : last ? commentBlockLineLast : commentBlockLine);
4387
+ if (!editing && (first || last)) {
4388
+ atomicDeco.add(block.from, block.to, hide);
4080
4389
  }
4081
- case "TaskMarker": {
4082
- if (!editingRange(state2, node, focus)) {
4083
- const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
4084
- atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
4085
- class: "cm-task"
4086
- }));
4087
- atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
4088
- }
4089
- break;
4390
+ }
4391
+ break;
4392
+ }
4393
+ case "FencedCode": {
4394
+ for (const block of view.viewportLineBlocks) {
4395
+ if (block.to < node.from) {
4396
+ continue;
4090
4397
  }
4091
- case "ListItem": {
4092
- const start = state2.doc.lineAt(node.from);
4093
- deco.add(start.from, start.from, Decoration5.line({
4094
- class: "cm-list-item"
4095
- }));
4398
+ if (block.from > node.to) {
4096
4399
  break;
4097
4400
  }
4098
- default: {
4099
- if (MarksByParent.has(node.name)) {
4100
- if (!editingRange(state2, node.node.parent, focus)) {
4101
- atomicDeco.add(node.from, node.to, hide);
4102
- }
4401
+ const first = block.from <= node.from;
4402
+ const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
4403
+ deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
4404
+ const editing = editingRange(state2, node, focus);
4405
+ if (!editing && (first || last)) {
4406
+ atomicDeco.add(block.from, block.to, hide);
4407
+ }
4408
+ }
4409
+ return false;
4410
+ }
4411
+ case "Link": {
4412
+ const marks = node.node.getChildren("LinkMark");
4413
+ const urlNode = node.node.getChild("URL");
4414
+ const editing = editingRange(state2, node, focus);
4415
+ if (urlNode && marks.length >= 2) {
4416
+ const url = state2.sliceDoc(urlNode.from, urlNode.to);
4417
+ if (!editing) {
4418
+ atomicDeco.add(node.from, marks[0].to, hide);
4419
+ }
4420
+ deco.add(marks[0].to, marks[1].from, Decoration7.mark({
4421
+ tagName: "a",
4422
+ attributes: {
4423
+ class: "cm-link",
4424
+ href: url,
4425
+ rel: "noreferrer",
4426
+ target: "_blank"
4103
4427
  }
4428
+ }));
4429
+ if (!editing) {
4430
+ atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration7.replace({
4431
+ widget: new LinkButton(url, options.renderLinkButton)
4432
+ }) : hide);
4433
+ }
4434
+ }
4435
+ break;
4436
+ }
4437
+ case "HorizontalRule": {
4438
+ if (!editingRange(state2, node, focus)) {
4439
+ deco.add(node.from, node.to, horizontalRule);
4440
+ }
4441
+ break;
4442
+ }
4443
+ default: {
4444
+ if (autoHideTags.has(node.name)) {
4445
+ if (!editingRange(state2, node.node.parent, focus)) {
4446
+ atomicDeco.add(node.from, node.to, hide);
4104
4447
  }
4105
4448
  }
4106
4449
  }
4450
+ }
4451
+ };
4452
+ const leaveNode = (node) => {
4453
+ switch (node.name) {
4454
+ case "BulletList":
4455
+ case "OrderedList": {
4456
+ leaveList();
4457
+ break;
4458
+ }
4459
+ }
4460
+ };
4461
+ const tree = syntaxTree6(state2);
4462
+ if (options.numberedHeadings?.from === void 0) {
4463
+ for (const { from, to } of view.visibleRanges) {
4464
+ tree.iterate({
4465
+ from,
4466
+ to,
4467
+ enter: wrapWithCatch(enterNode),
4468
+ leave: wrapWithCatch(leaveNode)
4469
+ });
4470
+ }
4471
+ } else {
4472
+ tree.iterate({
4473
+ enter: wrapWithCatch(enterNode),
4474
+ leave: wrapWithCatch(leaveNode)
4107
4475
  });
4108
4476
  }
4109
4477
  return {
@@ -4116,11 +4484,11 @@ var decorateMarkdown = (options = {}) => {
4116
4484
  return [
4117
4485
  ViewPlugin6.fromClass(class {
4118
4486
  constructor(view) {
4119
- ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
4487
+ ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(view, options, view.hasFocus));
4120
4488
  }
4121
4489
  update(update2) {
4122
4490
  if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
4123
- ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
4491
+ ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations2(update2.view, options, update2.view.hasFocus));
4124
4492
  this.clearUpdate();
4125
4493
  } else if (update2.selectionSet) {
4126
4494
  this.scheduleUpdate(update2.view);
@@ -4145,15 +4513,17 @@ var decorateMarkdown = (options = {}) => {
4145
4513
  }
4146
4514
  }, {
4147
4515
  provide: (plugin) => [
4148
- EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
4149
- EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
4150
- EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
4516
+ EditorView14.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
4517
+ EditorView14.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
4518
+ EditorView14.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
4151
4519
  ]
4152
4520
  }),
4153
- formattingStyles
4521
+ formattingStyles,
4522
+ image(),
4523
+ table()
4154
4524
  ];
4155
4525
  };
4156
- var formattingStyles = EditorView12.baseTheme({
4526
+ var formattingStyles = EditorView14.baseTheme({
4157
4527
  "& .cm-code": {
4158
4528
  fontFamily: getToken("fontFamily.mono", []).join(",")
4159
4529
  },
@@ -4171,12 +4541,12 @@ var formattingStyles = EditorView12.baseTheme({
4171
4541
  }
4172
4542
  },
4173
4543
  "& .cm-codeblock-first": {
4174
- borderTopLeftRadius: ".5rem",
4175
- borderTopRightRadius: ".5rem"
4544
+ borderTopLeftRadius: ".25rem",
4545
+ borderTopRightRadius: ".25rem"
4176
4546
  },
4177
4547
  "& .cm-codeblock-last": {
4178
- borderBottomLeftRadius: ".5rem",
4179
- borderBottomRightRadius: ".5rem"
4548
+ borderBottomLeftRadius: ".25rem",
4549
+ borderBottomRightRadius: ".25rem"
4180
4550
  },
4181
4551
  "&light .cm-codeblock-line, &light .cm-activeLine.cm-codeblock-line": {
4182
4552
  background: getToken("extend.semanticColors.input.light"),
@@ -4191,106 +4561,40 @@ var formattingStyles = EditorView12.baseTheme({
4191
4561
  width: "100%",
4192
4562
  height: "0",
4193
4563
  verticalAlign: "middle",
4194
- borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
4564
+ borderTop: `1px solid ${getToken("extend.colors.primary.500")}`,
4565
+ opacity: 0.5
4195
4566
  },
4196
4567
  "& .cm-task": {
4568
+ display: "inline-block",
4569
+ width: `calc(${bulletListIndentationWidth}px - 0.25em)`,
4197
4570
  color: getToken("extend.colors.blue.500")
4198
4571
  },
4199
4572
  "& .cm-task-checkbox": {
4200
- marginLeft: "4px",
4201
- marginRight: "4px"
4573
+ display: "grid",
4574
+ margin: "0",
4575
+ transform: "translateY(2px)"
4576
+ },
4577
+ "& .cm-list-item": {},
4578
+ "& .cm-list-mark": {
4579
+ display: "inline-block",
4580
+ textAlign: "right",
4581
+ color: getToken("extend.colors.neutral.500"),
4582
+ fontVariant: "tabular-nums"
4583
+ },
4584
+ "& .cm-list-mark-bullet": {
4585
+ width: `${bulletListIndentationWidth}px`
4586
+ },
4587
+ "& .cm-list-mark-ordered": {
4588
+ width: `${orderedListIndentationWidth}px`
4202
4589
  }
4203
4590
  });
4204
4591
 
4205
- // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
4206
- import { syntaxTree as syntaxTree5 } from "@codemirror/language";
4207
- import { StateField as StateField6 } from "@codemirror/state";
4208
- import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
4209
- var image = (options = {}) => {
4210
- return StateField6.define({
4211
- create: (state2) => {
4212
- return Decoration6.set(buildDecorations2(0, state2.doc.length, state2));
4213
- },
4214
- update: (value, tr) => {
4215
- if (!tr.docChanged && !tr.selection) {
4216
- return value;
4217
- }
4218
- const cursor = tr.state.selection.main.head;
4219
- const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
4220
- let from = Math.min(cursor, oldCursor);
4221
- let to = Math.max(cursor, oldCursor);
4222
- tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
4223
- from = Math.min(from, fromB);
4224
- to = Math.max(to, toB);
4225
- });
4226
- from = tr.state.doc.lineAt(from).from;
4227
- to = tr.state.doc.lineAt(to).to;
4228
- return value.map(tr.changes).update({
4229
- filterFrom: from,
4230
- filterTo: to,
4231
- filter: () => false,
4232
- add: buildDecorations2(from, to, tr.state)
4233
- });
4234
- },
4235
- provide: (field) => EditorView13.decorations.from(field)
4236
- });
4237
- };
4238
- var preloaded = /* @__PURE__ */ new Set();
4239
- var preloadImage = (url) => {
4240
- if (!preloaded.has(url)) {
4241
- const img = document.createElement("img");
4242
- img.src = url;
4243
- preloaded.add(url);
4244
- }
4245
- };
4246
- var buildDecorations2 = (from, to, state2) => {
4247
- const decorations = [];
4248
- const cursor = state2.selection.main.head;
4249
- syntaxTree5(state2).iterate({
4250
- enter: (node) => {
4251
- if (node.name === "Image") {
4252
- const urlNode = node.node.getChild("URL");
4253
- if (urlNode) {
4254
- const hide2 = state2.readOnly || cursor < node.from || cursor > node.to;
4255
- const url = state2.sliceDoc(urlNode.from, urlNode.to);
4256
- preloadImage(url);
4257
- decorations.push(Decoration6.replace({
4258
- block: true,
4259
- widget: new ImageWidget(url)
4260
- }).range(hide2 ? node.from : node.to, node.to));
4261
- }
4262
- }
4263
- },
4264
- from,
4265
- to
4266
- });
4267
- return decorations;
4268
- };
4269
- var ImageWidget = class extends WidgetType4 {
4270
- constructor(_url) {
4271
- super();
4272
- this._url = _url;
4273
- }
4274
- eq(other) {
4275
- return this._url === other._url;
4276
- }
4277
- toDOM(view) {
4278
- const img = document.createElement("img");
4279
- img.setAttribute("src", this._url);
4280
- img.setAttribute("class", "cm-image");
4281
- img.onload = () => img.classList.add("cm-loaded-image");
4282
- return img;
4283
- }
4284
- };
4285
- var imageUpload = (options = {}) => {
4286
- };
4287
-
4288
4592
  // packages/ui/react-ui-editor/src/extensions/markdown/link.ts
4289
- import { syntaxTree as syntaxTree6 } from "@codemirror/language";
4593
+ import { syntaxTree as syntaxTree7 } from "@codemirror/language";
4290
4594
  import { hoverTooltip as hoverTooltip2 } from "@codemirror/view";
4291
4595
  import { tooltipContent } from "@dxos/react-ui-theme";
4292
4596
  var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
4293
- const syntax = syntaxTree6(view.state).resolveInner(pos, side);
4597
+ const syntax = syntaxTree7(view.state).resolveInner(pos, side);
4294
4598
  let link = null;
4295
4599
  for (let i = 0, node = syntax; !link && node && i < 5; node = node.parent, i++) {
4296
4600
  link = node.name === "Link" ? node : null;
@@ -4319,112 +4623,10 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
4319
4623
  };
4320
4624
  });
4321
4625
 
4322
- // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
4323
- import { syntaxTree as syntaxTree7 } from "@codemirror/language";
4324
- import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField7 } from "@codemirror/state";
4325
- import { Decoration as Decoration7, EditorView as EditorView14, WidgetType as WidgetType5 } from "@codemirror/view";
4326
- var table = (options = {}) => {
4327
- return StateField7.define({
4328
- create: (state2) => update(state2, options),
4329
- update: (_, tr) => update(tr.state, options),
4330
- provide: (field) => EditorView14.decorations.from(field)
4331
- });
4332
- };
4333
- var update = (state2, options) => {
4334
- const builder = new RangeSetBuilder3();
4335
- const cursor = state2.selection.main.head;
4336
- const tables = [];
4337
- const getTable = () => tables[tables.length - 1];
4338
- const getRow = () => {
4339
- const table2 = getTable();
4340
- return table2.rows?.[table2.rows.length - 1];
4341
- };
4342
- syntaxTree7(state2).iterate({
4343
- enter: (node) => {
4344
- switch (node.name) {
4345
- case "Table": {
4346
- tables.push({
4347
- from: node.from,
4348
- to: node.to
4349
- });
4350
- break;
4351
- }
4352
- case "TableHeader": {
4353
- getTable().header = [];
4354
- break;
4355
- }
4356
- case "TableRow": {
4357
- (getTable().rows ??= []).push([]);
4358
- break;
4359
- }
4360
- case "TableCell": {
4361
- const row = getRow();
4362
- if (row) {
4363
- row.push(state2.sliceDoc(node.from, node.to));
4364
- } else {
4365
- getTable().header?.push(state2.sliceDoc(node.from, node.to));
4366
- }
4367
- break;
4368
- }
4369
- }
4370
- }
4371
- });
4372
- tables.forEach((table2) => {
4373
- const replace = state2.readOnly || cursor < table2.from || cursor > table2.to;
4374
- if (replace) {
4375
- builder.add(table2.from, table2.to, Decoration7.replace({
4376
- block: true,
4377
- widget: new TableWidget(table2)
4378
- }));
4379
- } else {
4380
- builder.add(table2.from, table2.to, Decoration7.mark({
4381
- class: "cm-table"
4382
- }));
4383
- }
4384
- });
4385
- return builder.finish();
4386
- };
4387
- var TableWidget = class extends WidgetType5 {
4388
- constructor(_table) {
4389
- super();
4390
- this._table = _table;
4391
- }
4392
- eq(other) {
4393
- return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
4394
- }
4395
- toDOM(view) {
4396
- const table2 = document.createElement("table");
4397
- {
4398
- const header = table2.appendChild(document.createElement("thead"));
4399
- const tr = header.appendChild(document.createElement("tr"));
4400
- this._table.header?.forEach((cell) => {
4401
- const th = document.createElement("th");
4402
- th.setAttribute("class", "cm-table-head");
4403
- tr.appendChild(th).textContent = cell;
4404
- });
4405
- }
4406
- {
4407
- const body = table2.appendChild(document.createElement("tbody"));
4408
- this._table.rows?.forEach((row) => {
4409
- const tr = body.appendChild(document.createElement("tr"));
4410
- row.forEach((cell) => {
4411
- const td = document.createElement("td");
4412
- td.setAttribute("class", "cm-table-cell");
4413
- tr.appendChild(td).textContent = cell;
4414
- });
4415
- });
4416
- }
4417
- return table2;
4418
- }
4419
- ignoreEvent(e) {
4420
- return !/^mouse/.test(e.type);
4421
- }
4422
- };
4423
-
4424
4626
  // packages/ui/react-ui-editor/src/extensions/mention.ts
4425
4627
  import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
4426
- import { log as log6 } from "@dxos/log";
4427
- var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
4628
+ import { log as log7 } from "@dxos/log";
4629
+ var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
4428
4630
  var mention = ({ onSearch }) => {
4429
4631
  return autocompletion2({
4430
4632
  // TODO(burdon): Not working.
@@ -4436,10 +4638,10 @@ var mention = ({ onSearch }) => {
4436
4638
  icons: false,
4437
4639
  override: [
4438
4640
  (context) => {
4439
- log6.info("completion context", {
4641
+ log7.info("completion context", {
4440
4642
  context
4441
4643
  }, {
4442
- F: __dxlog_file9,
4644
+ F: __dxlog_file11,
4443
4645
  L: 26,
4444
4646
  S: void 0,
4445
4647
  C: (f, a) => f(...a)
@@ -4512,15 +4714,15 @@ var InputModeExtensions = {
4512
4714
  import { Transaction as Transaction2 } from "@codemirror/state";
4513
4715
  import { EditorView as EditorView15, keymap as keymap9 } from "@codemirror/view";
4514
4716
  import { debounce as debounce2 } from "@dxos/async";
4515
- import { invariant as invariant4 } from "@dxos/invariant";
4717
+ import { invariant as invariant5 } from "@dxos/invariant";
4516
4718
  import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
4517
- var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
4719
+ var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
4518
4720
  var scrollAnnotation = "dxos.org/cm/scrolling";
4519
4721
  var keyPrefix = "dxos.org/react-ui-editor/state";
4520
4722
  var localStorageStateStoreAdapter = {
4521
4723
  setState: (id, state2) => {
4522
- invariant4(id, void 0, {
4523
- F: __dxlog_file10,
4724
+ invariant5(id, void 0, {
4725
+ F: __dxlog_file12,
4524
4726
  L: 35,
4525
4727
  S: void 0,
4526
4728
  A: [
@@ -4531,8 +4733,8 @@ var localStorageStateStoreAdapter = {
4531
4733
  localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state2));
4532
4734
  },
4533
4735
  getState: (id) => {
4534
- invariant4(id, void 0, {
4535
- F: __dxlog_file10,
4736
+ invariant5(id, void 0, {
4737
+ F: __dxlog_file12,
4536
4738
  L: 39,
4537
4739
  S: void 0,
4538
4740
  A: [
@@ -4653,26 +4855,26 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
4653
4855
  };
4654
4856
 
4655
4857
  // packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
4656
- var iconStyles = getSize(5);
4858
+ var iconStyles = getSize2(5);
4657
4859
  var buttonStyles = "min-bs-0 p-2";
4658
4860
  var tooltipProps = {
4659
4861
  side: "top",
4660
4862
  classNames: "z-10"
4661
4863
  };
4662
- var ToolbarSeparator = () => /* @__PURE__ */ React.createElement("div", {
4864
+ var ToolbarSeparator = () => /* @__PURE__ */ React3.createElement("div", {
4663
4865
  role: "separator",
4664
4866
  className: "grow"
4665
4867
  });
4666
4868
  var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
4667
4869
  var ToolbarRoot = ({ children, onAction, classNames, state: state2 }) => {
4668
- return /* @__PURE__ */ React.createElement(ToolbarContextProvider, {
4870
+ return /* @__PURE__ */ React3.createElement(ToolbarContextProvider, {
4669
4871
  onAction,
4670
4872
  state: state2
4671
- }, /* @__PURE__ */ React.createElement(DensityProvider, {
4873
+ }, /* @__PURE__ */ React3.createElement(DensityProvider, {
4672
4874
  density: "fine"
4673
- }, /* @__PURE__ */ React.createElement(ElevationProvider, {
4875
+ }, /* @__PURE__ */ React3.createElement(ElevationProvider, {
4674
4876
  elevation: "chrome"
4675
- }, /* @__PURE__ */ React.createElement(NaturalToolbar.Root, {
4877
+ }, /* @__PURE__ */ React3.createElement(NaturalToolbar.Root, {
4676
4878
  classNames: [
4677
4879
  "p-1 is-full shrink-0 overflow-x-auto overflow-y-hidden",
4678
4880
  classNames
@@ -4683,30 +4885,30 @@ var ToolbarRoot = ({ children, onAction, classNames, state: state2 }) => {
4683
4885
  }, children))));
4684
4886
  };
4685
4887
  var ToolbarToggleButton = ({ Icon, children, ...props }) => {
4686
- return /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
4888
+ return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
4687
4889
  asChild: true
4688
- }, /* @__PURE__ */ React.createElement(NaturalToolbar.ToggleGroupItem, {
4890
+ }, /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupItem, {
4689
4891
  variant: "ghost",
4690
4892
  ...props,
4691
4893
  classNames: buttonStyles
4692
- }, /* @__PURE__ */ React.createElement(Icon, {
4894
+ }, /* @__PURE__ */ React3.createElement(Icon, {
4693
4895
  className: iconStyles
4694
- }), /* @__PURE__ */ React.createElement("span", {
4896
+ }), /* @__PURE__ */ React3.createElement("span", {
4695
4897
  className: "sr-only"
4696
- }, children))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
4898
+ }, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
4697
4899
  };
4698
4900
  var ToolbarButton = ({ Icon, children, ...props }) => {
4699
- return /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
4901
+ return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
4700
4902
  asChild: true
4701
- }, /* @__PURE__ */ React.createElement(NaturalToolbar.Button, {
4903
+ }, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
4702
4904
  variant: "ghost",
4703
4905
  ...props,
4704
4906
  classNames: buttonStyles
4705
- }, /* @__PURE__ */ React.createElement(Icon, {
4907
+ }, /* @__PURE__ */ React3.createElement(Icon, {
4706
4908
  className: iconStyles
4707
- }), /* @__PURE__ */ React.createElement("span", {
4909
+ }), /* @__PURE__ */ React3.createElement("span", {
4708
4910
  className: "sr-only"
4709
- }, children))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
4911
+ }, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
4710
4912
  };
4711
4913
  var ViewModeIcons = {
4712
4914
  preview: PencilSimple,
@@ -4720,7 +4922,7 @@ var MarkdownView = ({ mode }) => {
4720
4922
  const suppressNextTooltip = useRef(false);
4721
4923
  const [tooltipOpen, setTooltipOpen] = useState3(false);
4722
4924
  const [selectOpen, setSelectOpen] = useState3(false);
4723
- return /* @__PURE__ */ React.createElement(Tooltip.Root, {
4925
+ return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
4724
4926
  open: tooltipOpen,
4725
4927
  onOpenChange: (nextOpen) => {
4726
4928
  if (nextOpen && suppressNextTooltip.current) {
@@ -4730,7 +4932,7 @@ var MarkdownView = ({ mode }) => {
4730
4932
  return setTooltipOpen(nextOpen);
4731
4933
  }
4732
4934
  }
4733
- }, /* @__PURE__ */ React.createElement(DropdownMenu.Root, {
4935
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
4734
4936
  open: selectOpen,
4735
4937
  onOpenChange: (nextOpen) => {
4736
4938
  if (!nextOpen) {
@@ -4738,39 +4940,39 @@ var MarkdownView = ({ mode }) => {
4738
4940
  }
4739
4941
  return setSelectOpen(nextOpen);
4740
4942
  }
4741
- }, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
4943
+ }, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
4742
4944
  asChild: true
4743
- }, /* @__PURE__ */ React.createElement(NaturalToolbar.Button, {
4945
+ }, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
4744
4946
  asChild: true
4745
- }, /* @__PURE__ */ React.createElement(DropdownMenu.Trigger, {
4947
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
4746
4948
  asChild: true
4747
- }, /* @__PURE__ */ React.createElement(Button, {
4949
+ }, /* @__PURE__ */ React3.createElement(Button, {
4748
4950
  variant: "ghost",
4749
4951
  classNames: buttonStyles
4750
- }, /* @__PURE__ */ React.createElement("span", {
4952
+ }, /* @__PURE__ */ React3.createElement("span", {
4751
4953
  className: "sr-only"
4752
- }, t("mode label")), /* @__PURE__ */ React.createElement(ModeIcon, {
4954
+ }, t("mode label")), /* @__PURE__ */ React3.createElement(ModeIcon, {
4753
4955
  className: iconStyles
4754
- }), /* @__PURE__ */ React.createElement(CaretDown, null))))), /* @__PURE__ */ React.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React.createElement(DropdownMenu.Content, {
4956
+ }), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
4755
4957
  classNames: "is-min md:is-min",
4756
4958
  onCloseAutoFocus: (e) => e.preventDefault()
4757
- }, /* @__PURE__ */ React.createElement(DropdownMenu.Viewport, null, EditorViewModes.map((value) => {
4959
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, EditorViewModes.map((value) => {
4758
4960
  const Icon = ViewModeIcons[value];
4759
- return /* @__PURE__ */ React.createElement(DropdownMenu.CheckboxItem, {
4961
+ return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
4760
4962
  key: value,
4761
4963
  checked: value === mode,
4762
4964
  onClick: () => onAction?.({
4763
4965
  type: "view-mode",
4764
4966
  data: value
4765
4967
  })
4766
- }, /* @__PURE__ */ React.createElement(Icon, {
4968
+ }, /* @__PURE__ */ React3.createElement(Icon, {
4767
4969
  className: iconStyles
4768
- }), /* @__PURE__ */ React.createElement("span", {
4970
+ }), /* @__PURE__ */ React3.createElement("span", {
4769
4971
  className: "whitespace-nowrap grow"
4770
- }, t(`${value} mode label`)), /* @__PURE__ */ React.createElement(Check, {
4972
+ }, t(`${value} mode label`)), /* @__PURE__ */ React3.createElement(Check, {
4771
4973
  className: value === mode ? "visible" : "invisible"
4772
4974
  }));
4773
- })), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, tooltipProps, t("view mode label"), /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
4975
+ })), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("view mode label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
4774
4976
  };
4775
4977
  var HeadingIcons = {
4776
4978
  "0": Paragraph,
@@ -4791,7 +4993,7 @@ var MarkdownHeading = () => {
4791
4993
  const suppressNextTooltip = useRef(false);
4792
4994
  const [tooltipOpen, setTooltipOpen] = useState3(false);
4793
4995
  const [selectOpen, setSelectOpen] = useState3(false);
4794
- return /* @__PURE__ */ React.createElement(Tooltip.Root, {
4996
+ return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
4795
4997
  open: tooltipOpen,
4796
4998
  onOpenChange: (nextOpen) => {
4797
4999
  if (nextOpen && suppressNextTooltip.current) {
@@ -4801,7 +5003,7 @@ var MarkdownHeading = () => {
4801
5003
  return setTooltipOpen(nextOpen);
4802
5004
  }
4803
5005
  }
4804
- }, /* @__PURE__ */ React.createElement(DropdownMenu.Root, {
5006
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
4805
5007
  open: selectOpen,
4806
5008
  onOpenChange: (nextOpen) => {
4807
5009
  if (!nextOpen) {
@@ -4809,75 +5011,75 @@ var MarkdownHeading = () => {
4809
5011
  }
4810
5012
  return setSelectOpen(nextOpen);
4811
5013
  }
4812
- }, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
5014
+ }, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
4813
5015
  asChild: true
4814
- }, /* @__PURE__ */ React.createElement(NaturalToolbar.Button, {
5016
+ }, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
4815
5017
  asChild: true
4816
- }, /* @__PURE__ */ React.createElement(DropdownMenu.Trigger, {
5018
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
4817
5019
  asChild: true
4818
- }, /* @__PURE__ */ React.createElement(Button, {
5020
+ }, /* @__PURE__ */ React3.createElement(Button, {
4819
5021
  variant: "ghost",
4820
5022
  classNames: buttonStyles,
4821
5023
  disabled: value === null
4822
- }, /* @__PURE__ */ React.createElement("span", {
5024
+ }, /* @__PURE__ */ React3.createElement("span", {
4823
5025
  className: "sr-only"
4824
- }, t("heading label")), /* @__PURE__ */ React.createElement(HeadingIcon, {
5026
+ }, t("heading label")), /* @__PURE__ */ React3.createElement(HeadingIcon, {
4825
5027
  className: iconStyles
4826
- }), /* @__PURE__ */ React.createElement(CaretDown, null))))), /* @__PURE__ */ React.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React.createElement(DropdownMenu.Content, {
5028
+ }), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
4827
5029
  classNames: "is-min md:is-min",
4828
5030
  onCloseAutoFocus: (e) => e.preventDefault()
4829
- }, /* @__PURE__ */ React.createElement(DropdownMenu.Viewport, null, Object.keys(HeadingIcons).map((level) => {
5031
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, Object.keys(HeadingIcons).map((level) => {
4830
5032
  const Icon = HeadingIcons[level];
4831
- return /* @__PURE__ */ React.createElement(DropdownMenu.CheckboxItem, {
5033
+ return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
4832
5034
  key: level,
4833
5035
  checked: value === level,
4834
5036
  onClick: () => onAction?.({
4835
5037
  type: "heading",
4836
5038
  data: level
4837
5039
  })
4838
- }, /* @__PURE__ */ React.createElement("span", {
5040
+ }, /* @__PURE__ */ React3.createElement("span", {
4839
5041
  className: "sr-only"
4840
5042
  }, t("heading level label", {
4841
5043
  count: parseInt(level)
4842
- })), /* @__PURE__ */ React.createElement(Icon, {
5044
+ })), /* @__PURE__ */ React3.createElement(Icon, {
4843
5045
  className: iconStyles
4844
- }), /* @__PURE__ */ React.createElement(DropdownMenu.ItemIndicator, null, /* @__PURE__ */ React.createElement(Check, null)));
4845
- })), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
5046
+ }), /* @__PURE__ */ React3.createElement(DropdownMenu.ItemIndicator, null, /* @__PURE__ */ React3.createElement(Check, null)));
5047
+ })), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
4846
5048
  };
4847
5049
  var markdownStyles = [
4848
5050
  {
4849
5051
  type: "strong",
4850
5052
  Icon: TextB,
4851
- getState: (state2) => state2.strong
5053
+ getState: (state2) => !!state2?.strong
4852
5054
  },
4853
5055
  {
4854
5056
  type: "emphasis",
4855
5057
  Icon: TextItalic,
4856
- getState: (state2) => state2.emphasis
5058
+ getState: (state2) => !!state2?.emphasis
4857
5059
  },
4858
5060
  {
4859
5061
  type: "strikethrough",
4860
5062
  Icon: TextStrikethrough,
4861
- getState: (state2) => state2.strikethrough
5063
+ getState: (state2) => !!state2?.strikethrough
4862
5064
  },
4863
5065
  {
4864
5066
  type: "code",
4865
5067
  Icon: Code,
4866
- getState: (state2) => state2.code
5068
+ getState: (state2) => !!state2?.code
4867
5069
  },
4868
5070
  {
4869
5071
  type: "link",
4870
5072
  Icon: Link,
4871
- getState: (state2) => state2.link
5073
+ getState: (state2) => !!state2?.link
4872
5074
  }
4873
5075
  ];
4874
5076
  var MarkdownStyles = () => {
4875
5077
  const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
4876
5078
  const { t } = useTranslation(translationKey);
4877
- return /* @__PURE__ */ React.createElement(NaturalToolbar.ToggleGroup, {
5079
+ return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
4878
5080
  type: "multiple",
4879
5081
  value: markdownStyles.filter(({ getState }) => state2 && getState(state2)).map(({ type }) => type)
4880
- }, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React.createElement(ToolbarToggleButton, {
5082
+ }, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
4881
5083
  key: type,
4882
5084
  value: type,
4883
5085
  Icon,
@@ -4908,10 +5110,10 @@ var markdownLists = [
4908
5110
  var MarkdownLists = () => {
4909
5111
  const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
4910
5112
  const { t } = useTranslation(translationKey);
4911
- return /* @__PURE__ */ React.createElement(NaturalToolbar.ToggleGroup, {
5113
+ return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
4912
5114
  type: "single",
4913
5115
  value: state2?.listStyle ? `list-${state2.listStyle}` : ""
4914
- }, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React.createElement(ToolbarToggleButton, {
5116
+ }, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
4915
5117
  key: type,
4916
5118
  value: type,
4917
5119
  Icon,
@@ -4925,7 +5127,7 @@ var markdownBlocks = [
4925
5127
  {
4926
5128
  type: "blockquote",
4927
5129
  Icon: Quotes,
4928
- getState: (state2) => state2.blockQuote
5130
+ getState: (state2) => !!state2?.blockQuote
4929
5131
  },
4930
5132
  {
4931
5133
  type: "codeblock",
@@ -4943,10 +5145,10 @@ var MarkdownBlocks = () => {
4943
5145
  const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
4944
5146
  const { t } = useTranslation(translationKey);
4945
5147
  const value = markdownBlocks.find(({ getState }) => state2 && getState(state2));
4946
- return /* @__PURE__ */ React.createElement(NaturalToolbar.ToggleGroup, {
5148
+ return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
4947
5149
  type: "single",
4948
5150
  value: value?.type ?? ""
4949
- }, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React.createElement(ToolbarToggleButton, {
5151
+ }, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
4950
5152
  key: type,
4951
5153
  value: type,
4952
5154
  Icon,
@@ -4957,7 +5159,7 @@ var MarkdownBlocks = () => {
4957
5159
  }) : void 0
4958
5160
  }, t(`${type} label`))));
4959
5161
  };
4960
- var MarkdownStandard = () => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(MarkdownHeading, null), /* @__PURE__ */ React.createElement(MarkdownStyles, null), /* @__PURE__ */ React.createElement(MarkdownLists, null), /* @__PURE__ */ React.createElement(MarkdownBlocks, null));
5162
+ var MarkdownStandard = () => /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(MarkdownHeading, null), /* @__PURE__ */ React3.createElement(MarkdownStyles, null), /* @__PURE__ */ React3.createElement(MarkdownLists, null), /* @__PURE__ */ React3.createElement(MarkdownBlocks, null));
4961
5163
  var MarkdownCustom = ({ onUpload } = {}) => {
4962
5164
  const { onAction } = useToolbarContext("MarkdownStyles");
4963
5165
  const { t } = useTranslation(translationKey);
@@ -4995,7 +5197,7 @@ var MarkdownCustom = ({ onUpload } = {}) => {
4995
5197
  }, [
4996
5198
  acceptedFiles
4997
5199
  ]);
4998
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("input", getInputProps()), /* @__PURE__ */ React.createElement(ToolbarButton, {
5200
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("input", getInputProps()), /* @__PURE__ */ React3.createElement(ToolbarButton, {
4999
5201
  value: "image",
5000
5202
  Icon: Image,
5001
5203
  onClick: () => open()
@@ -5004,7 +5206,13 @@ var MarkdownCustom = ({ onUpload } = {}) => {
5004
5206
  var MarkdownActions = () => {
5005
5207
  const { onAction, state: state2 } = useToolbarContext("MarkdownActions");
5006
5208
  const { t } = useTranslation(translationKey);
5007
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ToolbarButton, {
5209
+ let toolTipKey = "comment label";
5210
+ if (state2?.comment) {
5211
+ toolTipKey = "selection overlaps existing comment label";
5212
+ } else if (state2?.selection === false) {
5213
+ toolTipKey = "select text to comment label";
5214
+ }
5215
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ToolbarButton, {
5008
5216
  value: "comment",
5009
5217
  Icon: ChatText,
5010
5218
  "data-testid": "editor.toolbar.comment",
@@ -5012,7 +5220,7 @@ var MarkdownActions = () => {
5012
5220
  type: "comment"
5013
5221
  }),
5014
5222
  disabled: !state2 || state2.comment || !state2.selection
5015
- }, t("comment label")));
5223
+ }, t(toolTipKey)));
5016
5224
  };
5017
5225
  var Toolbar = {
5018
5226
  Root: ToolbarRoot,
@@ -5024,6 +5232,21 @@ var Toolbar = {
5024
5232
  Actions: MarkdownActions
5025
5233
  };
5026
5234
 
5235
+ // packages/ui/react-ui-editor/src/defaults.ts
5236
+ import { EditorView as EditorView16 } from "@codemirror/view";
5237
+ var editorContent = "!mt-[16px] !mli-auto w-full max-w-[min(50rem,100%-4rem)]";
5238
+ var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
5239
+ var editorGutter = EditorView16.baseTheme({
5240
+ ".cm-gutters": {
5241
+ // Match margin from content.
5242
+ marginTop: "16px",
5243
+ // Inside within content margin.
5244
+ marginRight: "-32px",
5245
+ width: "32px",
5246
+ backgroundColor: "transparent !important"
5247
+ }
5248
+ });
5249
+
5027
5250
  // packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
5028
5251
  var useActionHandler = (view) => {
5029
5252
  return (action) => view && processAction(view, action);
@@ -5031,20 +5254,20 @@ var useActionHandler = (view) => {
5031
5254
 
5032
5255
  // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
5033
5256
  import { EditorState as EditorState2 } from "@codemirror/state";
5034
- import { EditorView as EditorView16 } from "@codemirror/view";
5257
+ import { EditorView as EditorView17 } from "@codemirror/view";
5035
5258
  import { useFocusableGroup } from "@fluentui/react-tabster";
5036
5259
  import { useCallback, useEffect as useEffect3, useMemo as useMemo3, useRef as useRef2, useState as useState4 } from "react";
5037
- import { log as log7 } from "@dxos/log";
5260
+ import { log as log8 } from "@dxos/log";
5038
5261
  import { useDefaultValue } from "@dxos/react-ui";
5039
5262
  import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
5040
- var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
5263
+ var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
5041
5264
  var instanceCount = 0;
5042
5265
  var useTextEditor = (props = {}, deps = []) => {
5043
5266
  const { id, initialValue, selection, extensions, autoFocus, scrollTo: _scrollTo, moveToEndOfLine, debug } = useMemo3(() => {
5044
5267
  return typeof props === "function" ? props() : props;
5045
5268
  }, deps ?? []);
5046
5269
  const [instanceId] = useState4(() => `text-editor-${++instanceCount}`);
5047
- const scrollTo = useDefaultValue(_scrollTo, EditorView16.scrollIntoView(0, {
5270
+ const scrollTo = useDefaultValue(_scrollTo, EditorView17.scrollIntoView(0, {
5048
5271
  yMargin: 0
5049
5272
  }));
5050
5273
  const onUpdate = useRef2();
@@ -5053,12 +5276,12 @@ var useTextEditor = (props = {}, deps = []) => {
5053
5276
  useEffect3(() => {
5054
5277
  let view2;
5055
5278
  if (parentRef.current) {
5056
- log7("create", {
5279
+ log8("create", {
5057
5280
  id,
5058
5281
  instanceId,
5059
5282
  doc: initialValue?.length ?? 0
5060
5283
  }, {
5061
- F: __dxlog_file11,
5284
+ F: __dxlog_file13,
5062
5285
  L: 86,
5063
5286
  S: void 0,
5064
5287
  C: (f, a) => f(...a)
@@ -5076,22 +5299,22 @@ var useTextEditor = (props = {}, deps = []) => {
5076
5299
  selection: initialSelection,
5077
5300
  extensions: [
5078
5301
  id && documentId2.of(id),
5079
- // TODO(burdon): Doesn't catch errors in keymap functions.
5080
- EditorView16.exceptionSink.of((err) => {
5081
- log7.catch(err, void 0, {
5082
- F: __dxlog_file11,
5302
+ // NOTE: Doesn't catch errors in keymap functions.
5303
+ EditorView17.exceptionSink.of((err) => {
5304
+ log8.catch(err, void 0, {
5305
+ F: __dxlog_file13,
5083
5306
  L: 104,
5084
5307
  S: void 0,
5085
5308
  C: (f, a) => f(...a)
5086
5309
  });
5087
5310
  }),
5088
5311
  extensions,
5089
- EditorView16.updateListener.of(() => {
5312
+ EditorView17.updateListener.of(() => {
5090
5313
  onUpdate.current?.();
5091
5314
  })
5092
5315
  ].filter(isNotFalsy4)
5093
5316
  });
5094
- view2 = new EditorView16({
5317
+ view2 = new EditorView17({
5095
5318
  parent: parentRef.current,
5096
5319
  scrollTo,
5097
5320
  selection: initialSelection,
@@ -5116,10 +5339,10 @@ var useTextEditor = (props = {}, deps = []) => {
5116
5339
  setView(view2);
5117
5340
  }
5118
5341
  return () => {
5119
- log7("destroy", {
5342
+ log8("destroy", {
5120
5343
  id
5121
5344
  }, {
5122
- F: __dxlog_file11,
5345
+ F: __dxlog_file13,
5123
5346
  L: 139,
5124
5347
  S: void 0,
5125
5348
  C: (f, a) => f(...a)
@@ -5219,14 +5442,14 @@ export {
5219
5442
  debugNodeLogger,
5220
5443
  decorateMarkdown,
5221
5444
  defaultOptions,
5222
- defaultTheme,
5223
5445
  documentId2 as documentId,
5224
5446
  dropFile,
5225
- editorFillLayoutEditor,
5226
- editorFillLayoutRoot,
5447
+ editorContent,
5448
+ editorGutter,
5227
5449
  editorInputMode,
5228
5450
  editorWithToolbarLayout,
5229
5451
  focusEvent,
5452
+ folding,
5230
5453
  formattingEquals,
5231
5454
  formattingKeymap,
5232
5455
  getFormatting,