@dxos/react-ui-editor 0.4.8-main.5f46a83 → 0.4.8-main.97e86fe

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 (47) hide show
  1. package/dist/lib/browser/index.mjs +796 -797
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
  5. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  7. package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
  8. package/dist/types/src/{hooks → extensions/awareness}/awareness-provider.d.ts +1 -1
  9. package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -0
  10. package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -0
  11. package/dist/types/src/extensions/awareness/index.d.ts +3 -0
  12. package/dist/types/src/extensions/awareness/index.d.ts.map +1 -0
  13. package/dist/types/src/extensions/comments.d.ts +1 -1
  14. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  15. package/dist/types/src/extensions/cursor.d.ts +1 -1
  16. package/dist/types/src/extensions/cursor.d.ts.map +1 -1
  17. package/dist/types/src/{hooks/extension-utils.d.ts → extensions/factories.d.ts} +2 -7
  18. package/dist/types/src/extensions/factories.d.ts.map +1 -0
  19. package/dist/types/src/extensions/index.d.ts +2 -0
  20. package/dist/types/src/extensions/index.d.ts.map +1 -1
  21. package/dist/types/src/{hooks/defs.d.ts → extensions/types.d.ts} +1 -1
  22. package/dist/types/src/extensions/types.d.ts.map +1 -0
  23. package/dist/types/src/hooks/index.d.ts +1 -3
  24. package/dist/types/src/hooks/index.d.ts.map +1 -1
  25. package/dist/types/src/hooks/useDocAccessor.d.ts +7 -0
  26. package/dist/types/src/hooks/useDocAccessor.d.ts.map +1 -0
  27. package/package.json +24 -24
  28. package/src/components/TextEditor/TextEditor.stories.tsx +5 -7
  29. package/src/components/Toolbar/Toolbar.stories.tsx +5 -9
  30. package/src/extensions/automerge/automerge.stories.tsx +2 -1
  31. package/src/{hooks → extensions/awareness}/awareness-provider.ts +1 -1
  32. package/src/extensions/{awareness.ts → awareness/awareness.ts} +1 -1
  33. package/src/extensions/awareness/index.ts +6 -0
  34. package/src/extensions/comments.ts +1 -1
  35. package/src/extensions/cursor.ts +1 -1
  36. package/src/{hooks/extension-utils.ts → extensions/factories.ts} +3 -21
  37. package/src/extensions/index.ts +2 -0
  38. package/src/extensions/markdown/decorate.ts +1 -1
  39. package/src/{hooks/defs.ts → extensions/types.ts} +1 -0
  40. package/src/hooks/index.ts +1 -4
  41. package/src/hooks/useDocAccessor.ts +21 -0
  42. package/src/hooks/useTextEditor.stories.tsx +1 -1
  43. package/dist/types/src/extensions/awareness.d.ts.map +0 -1
  44. package/dist/types/src/hooks/awareness-provider.d.ts.map +0 -1
  45. package/dist/types/src/hooks/defs.d.ts.map +0 -1
  46. package/dist/types/src/hooks/extension-utils.d.ts.map +0 -1
  47. /package/dist/types/src/extensions/{awareness.d.ts → awareness/awareness.d.ts} +0 -0
@@ -29,12 +29,12 @@ import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
29
29
  import { Doc, YText, YXmlFragment } from "@dxos/text-model";
30
30
 
31
31
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
32
- import { EditorState } from "@codemirror/state";
33
- import { EditorView as EditorView15 } from "@codemirror/view";
32
+ import { EditorState as EditorState2 } from "@codemirror/state";
33
+ import { EditorView as EditorView16 } from "@codemirror/view";
34
34
  import { useFocusableGroup } from "@fluentui/react-tabster";
35
35
  import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
36
- import { log as log7 } from "@dxos/log";
37
- import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
36
+ import { log as log9 } from "@dxos/log";
37
+ import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
38
38
 
39
39
  // packages/ui/react-ui-editor/src/extensions/annotations.ts
40
40
  import { StateField } from "@codemirror/state";
@@ -492,7 +492,7 @@ var automerge = (accessor) => {
492
492
  ];
493
493
  };
494
494
 
495
- // packages/ui/react-ui-editor/src/extensions/awareness.ts
495
+ // packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
496
496
  import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
497
497
  import { Decoration as Decoration2, EditorView as EditorView3, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
498
498
  import { Event } from "@dxos/async";
@@ -727,11 +727,115 @@ var styles2 = EditorView3.baseTheme({
727
727
  }
728
728
  });
729
729
 
730
+ // packages/ui/react-ui-editor/src/extensions/awareness/awareness-provider.ts
731
+ import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
732
+ import { Context as Context2 } from "@dxos/context";
733
+ import { invariant } from "@dxos/invariant";
734
+ import { log as log2 } from "@dxos/log";
735
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness-provider.ts";
736
+ var DEBOUNCE_INTERVAL = 100;
737
+ var SpaceAwarenessProvider = class {
738
+ constructor(params) {
739
+ this._remoteStates = /* @__PURE__ */ new Map();
740
+ this.remoteStateChange = new Event2();
741
+ this._space = params.space;
742
+ this._channel = params.channel;
743
+ this._peerId = params.peerId;
744
+ this._info = params.info;
745
+ }
746
+ open() {
747
+ this._ctx = new Context2();
748
+ this._postTask = new DeferredTask(this._ctx, async () => {
749
+ if (this._localState) {
750
+ await this._space.postMessage(this._channel, {
751
+ kind: "post",
752
+ state: this._localState
753
+ });
754
+ await sleep(DEBOUNCE_INTERVAL);
755
+ }
756
+ });
757
+ this._ctx.onDispose(this._space.listen(this._channel, (message) => {
758
+ switch (message.payload.kind) {
759
+ case "query": {
760
+ this._handleQueryMessage();
761
+ break;
762
+ }
763
+ case "post": {
764
+ this._handlePostMessage(message.payload);
765
+ break;
766
+ }
767
+ }
768
+ }));
769
+ void this._space.postMessage(this._channel, {
770
+ kind: "query"
771
+ }).catch((err) => {
772
+ log2.debug("failed to query awareness", {
773
+ err
774
+ }, {
775
+ F: __dxlog_file2,
776
+ L: 89,
777
+ S: this,
778
+ C: (f, a) => f(...a)
779
+ });
780
+ });
781
+ }
782
+ close() {
783
+ void this._ctx?.dispose();
784
+ this._ctx = void 0;
785
+ this._postTask = void 0;
786
+ }
787
+ getRemoteStates() {
788
+ return Array.from(this._remoteStates.values());
789
+ }
790
+ update(position) {
791
+ invariant(this._postTask, void 0, {
792
+ F: __dxlog_file2,
793
+ L: 104,
794
+ S: this,
795
+ A: [
796
+ "this._postTask",
797
+ ""
798
+ ]
799
+ });
800
+ this._localState = {
801
+ peerId: this._peerId,
802
+ position,
803
+ info: this._info
804
+ };
805
+ this._postTask.schedule();
806
+ }
807
+ _handleQueryMessage() {
808
+ invariant(this._postTask, void 0, {
809
+ F: __dxlog_file2,
810
+ L: 115,
811
+ S: this,
812
+ A: [
813
+ "this._postTask",
814
+ ""
815
+ ]
816
+ });
817
+ this._postTask.schedule();
818
+ }
819
+ _handlePostMessage(message) {
820
+ invariant(message.kind === "post", void 0, {
821
+ F: __dxlog_file2,
822
+ L: 120,
823
+ S: this,
824
+ A: [
825
+ "message.kind === 'post'",
826
+ ""
827
+ ]
828
+ });
829
+ this._remoteStates.set(message.state.peerId, message.state);
830
+ this.remoteStateChange.emit();
831
+ }
832
+ };
833
+
730
834
  // packages/ui/react-ui-editor/src/extensions/blast.ts
731
835
  import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
732
836
  import defaultsDeep from "lodash.defaultsdeep";
733
- import { invariant } from "@dxos/invariant";
734
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
837
+ import { invariant as invariant2 } from "@dxos/invariant";
838
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
735
839
  var defaultOptions = {
736
840
  effect: 2,
737
841
  maxParticles: 200,
@@ -857,8 +961,8 @@ var Blaster = class {
857
961
  return this._node;
858
962
  }
859
963
  initialize() {
860
- invariant(!this._canvas && !this._ctx, void 0, {
861
- F: __dxlog_file2,
964
+ invariant2(!this._canvas && !this._ctx, void 0, {
965
+ F: __dxlog_file3,
862
966
  L: 141,
863
967
  S: this,
864
968
  A: [
@@ -894,8 +998,8 @@ var Blaster = class {
894
998
  }
895
999
  }
896
1000
  start() {
897
- invariant(this._canvas && this._ctx, void 0, {
898
- F: __dxlog_file2,
1001
+ invariant2(this._canvas && this._ctx, void 0, {
1002
+ F: __dxlog_file3,
899
1003
  L: 180,
900
1004
  S: this,
901
1005
  A: [
@@ -1261,7 +1365,7 @@ import { hoverTooltip, keymap as keymap4, Decoration as Decoration4, EditorView
1261
1365
  import sortBy from "lodash.sortby";
1262
1366
  import { useEffect } from "react";
1263
1367
  import { debounce } from "@dxos/async";
1264
- import { log as log3 } from "@dxos/log";
1368
+ import { log as log4 } from "@dxos/log";
1265
1369
  import { nonNullable } from "@dxos/util";
1266
1370
 
1267
1371
  // packages/ui/react-ui-editor/src/styles/markdown.ts
@@ -1299,14 +1403,14 @@ var editorFillLayoutRoot = "bs-full relative";
1299
1403
  var editorFillLayoutEditor = "!absolute inset-0";
1300
1404
 
1301
1405
  // packages/ui/react-ui-editor/src/util.ts
1302
- import { log as log2 } from "@dxos/log";
1303
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
1406
+ import { log as log3 } from "@dxos/log";
1407
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
1304
1408
  var callbackWrapper = (fn) => (...args) => {
1305
1409
  try {
1306
1410
  return fn(...args);
1307
1411
  } catch (err) {
1308
- log2.catch(err, void 0, {
1309
- F: __dxlog_file3,
1412
+ log3.catch(err, void 0, {
1413
+ F: __dxlog_file4,
1310
1414
  L: 18,
1311
1415
  S: void 0,
1312
1416
  C: (f, a) => f(...a)
@@ -1329,10 +1433,10 @@ var logChanges = (trs) => {
1329
1433
  return changes2;
1330
1434
  }).filter(Boolean);
1331
1435
  if (changes.length) {
1332
- log2.info("changes", {
1436
+ log3.info("changes", {
1333
1437
  changes
1334
1438
  }, {
1335
- F: __dxlog_file3,
1439
+ F: __dxlog_file4,
1336
1440
  L: 39,
1337
1441
  S: void 0,
1338
1442
  C: (f, a) => f(...a)
@@ -1341,7 +1445,7 @@ var logChanges = (trs) => {
1341
1445
  };
1342
1446
 
1343
1447
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1344
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
1448
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
1345
1449
  var documentId = Facet4.define({
1346
1450
  combine: (values) => values[0]
1347
1451
  });
@@ -1427,8 +1531,8 @@ var commentsDecorations = EditorView7.decorations.compute([
1427
1531
  const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
1428
1532
  const range = comment.range;
1429
1533
  if (!range || range.from === range.to) {
1430
- log3.warn("Invalid range:", range, {
1431
- F: __dxlog_file4,
1534
+ log4.warn("Invalid range:", range, {
1535
+ F: __dxlog_file5,
1432
1536
  L: 132,
1433
1537
  S: void 0,
1434
1538
  C: (f, a) => f(...a)
@@ -1749,8 +1853,8 @@ var useComments = (view, id, comments2 = []) => {
1749
1853
  // packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
1750
1854
  import { Transaction } from "@codemirror/state";
1751
1855
  import { EditorView as EditorView8 } from "@codemirror/view";
1752
- import { log as log4 } from "@dxos/log";
1753
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts";
1856
+ import { log as log5 } from "@dxos/log";
1857
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts";
1754
1858
  var annotation = "cursorLineMargin";
1755
1859
  var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
1756
1860
  var cursorLineMargin = (options = {
@@ -1777,8 +1881,8 @@ var cursorLineMargin = (options = {
1777
1881
  const needsScrollTop = false;
1778
1882
  const needsScrollBot = mainLine >= visBotLine - lines;
1779
1883
  if (needsScrollTop && needsScrollBot) {
1780
- log4.warn("is cursorScrollMargin too large for the editor size?", void 0, {
1781
- F: __dxlog_file5,
1884
+ log5.warn("is cursorScrollMargin too large for the editor size?", void 0, {
1885
+ F: __dxlog_file6,
1782
1886
  L: 65,
1783
1887
  S: void 0,
1784
1888
  C: (f, a) => f(...a)
@@ -1810,12 +1914,12 @@ var cursorLineMargin = (options = {
1810
1914
 
1811
1915
  // packages/ui/react-ui-editor/src/extensions/doc.ts
1812
1916
  import { Facet as Facet5 } from "@codemirror/state";
1813
- import { invariant as invariant2 } from "@dxos/invariant";
1814
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/doc.ts";
1917
+ import { invariant as invariant3 } from "@dxos/invariant";
1918
+ var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/doc.ts";
1815
1919
  var documentId2 = Facet5.define({
1816
1920
  combine: (providers) => {
1817
- invariant2(providers.length <= 1, void 0, {
1818
- F: __dxlog_file6,
1921
+ invariant3(providers.length <= 1, void 0, {
1922
+ F: __dxlog_file7,
1819
1923
  L: 11,
1820
1924
  S: void 0,
1821
1925
  A: [
@@ -1829,15 +1933,15 @@ var documentId2 = Facet5.define({
1829
1933
 
1830
1934
  // packages/ui/react-ui-editor/src/extensions/dnd.ts
1831
1935
  import { EditorView as EditorView9 } from "@codemirror/view";
1832
- import { log as log5 } from "@dxos/log";
1833
- var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/dnd.ts";
1936
+ import { log as log6 } from "@dxos/log";
1937
+ var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/dnd.ts";
1834
1938
  var dnd = () => {
1835
1939
  return EditorView9.domEventHandlers({
1836
1940
  drop: (event, view) => {
1837
- log5.info("domEventHandlersDrop", {
1941
+ log6.info("domEventHandlersDrop", {
1838
1942
  event
1839
1943
  }, {
1840
- F: __dxlog_file7,
1944
+ F: __dxlog_file8,
1841
1945
  L: 14,
1842
1946
  S: void 0,
1843
1947
  C: (f, a) => f(...a)
@@ -1846,178 +1950,499 @@ var dnd = () => {
1846
1950
  });
1847
1951
  };
1848
1952
 
1849
- // packages/ui/react-ui-editor/src/extensions/listener.ts
1850
- import { EditorView as EditorView10 } from "@codemirror/view";
1851
- var listener = ({ onFocus, onChange }) => {
1852
- const extensions = [];
1853
- onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
1854
- onFocus(focusing);
1855
- return null;
1856
- }));
1857
- onChange && extensions.push(EditorView10.updateListener.of((update2) => {
1858
- onChange(update2.state.doc.toString());
1859
- }));
1860
- return extensions;
1861
- };
1862
-
1863
- // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
1864
- import { closeBracketsKeymap } from "@codemirror/autocomplete";
1865
- import { historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
1866
- import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
1867
- import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
1868
- import { languages } from "@codemirror/language-data";
1869
- import { searchKeymap } from "@codemirror/search";
1870
- import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
1871
- import { keymap as keymap5 } from "@codemirror/view";
1953
+ // packages/ui/react-ui-editor/src/extensions/factories.ts
1954
+ import { closeBrackets } from "@codemirror/autocomplete";
1955
+ import { history } from "@codemirror/commands";
1956
+ import { bracketMatching } from "@codemirror/language";
1957
+ import { EditorState } from "@codemirror/state";
1958
+ import { EditorView as EditorView10, crosshairCursor, drawSelection, dropCursor, highlightActiveLine, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
1959
+ import defaultsDeep2 from "lodash.defaultsdeep";
1960
+ import { generateName } from "@dxos/display-name";
1961
+ import { log as log7 } from "@dxos/log";
1962
+ import { hueTokens } from "@dxos/react-ui-theme";
1963
+ import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
1872
1964
 
1873
- // packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
1874
- import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
1875
- import { HighlightStyle } from "@codemirror/language";
1876
- import { tags, styleTags, Tag } from "@lezer/highlight";
1877
- import { Table } from "@lezer/markdown";
1878
- var markdownTags = {
1879
- Blockquote: Tag.define(),
1880
- CodeMark: Tag.define(),
1881
- CodeText: Tag.define(),
1882
- EmphasisMark: Tag.define(),
1883
- HeaderMark: Tag.define(),
1884
- InlineCode: Tag.define(),
1885
- LinkLabel: Tag.define(),
1886
- LinkReference: Tag.define(),
1887
- ListMark: Tag.define(),
1888
- QuoteMark: Tag.define(),
1889
- URL: Tag.define(),
1890
- // Custom.
1891
- TableCell: Tag.define()
1892
- };
1893
- Table.defineNodes?.forEach((node) => {
1894
- switch (node?.name) {
1895
- case "TableCell": {
1896
- node.style = markdownTags.TableCell;
1897
- break;
1898
- }
1899
- }
1900
- });
1901
- var markdownTagsExtensions = [
1902
- Table,
1903
- {
1904
- props: [
1905
- styleTags(markdownTags)
1906
- ]
1907
- }
1908
- ];
1909
- var markdownHighlightStyle = (readonly) => {
1910
- return HighlightStyle.define([
1911
- {
1912
- tag: [
1913
- tags.keyword,
1914
- tags.name,
1915
- tags.deleted,
1916
- tags.character,
1917
- tags.propertyName,
1918
- tags.macroName,
1919
- tags.color,
1920
- tags.constant(tags.name),
1921
- tags.standard(tags.name),
1922
- tags.definition(tags.name),
1923
- tags.separator,
1924
- tags.typeName,
1925
- tags.className,
1926
- tags.number,
1927
- tags.changed,
1928
- tags.annotation,
1929
- tags.modifier,
1930
- tags.self,
1931
- tags.namespace,
1932
- tags.operator,
1933
- tags.operatorKeyword,
1934
- tags.escape,
1935
- tags.regexp,
1936
- tags.special(tags.string),
1937
- tags.meta,
1938
- tags.comment,
1939
- tags.atom,
1940
- tags.bool,
1941
- tags.special(tags.variableName),
1942
- tags.processingInstruction,
1943
- tags.string,
1944
- tags.inserted,
1945
- tags.invalid
1946
- ],
1947
- color: "inherit !important"
1948
- },
1949
- // Markdown marks.
1950
- {
1951
- tag: [
1952
- tags.meta,
1953
- tags.processingInstruction,
1954
- markdownTags.LinkLabel,
1955
- markdownTags.LinkReference,
1956
- markdownTags.ListMark
1957
- ],
1958
- class: mark
1959
- },
1960
- // Markdown marks.
1961
- {
1962
- tag: [
1963
- markdownTags.CodeMark,
1964
- markdownTags.HeaderMark,
1965
- markdownTags.QuoteMark,
1966
- markdownTags.EmphasisMark
1967
- ],
1968
- class: mark
1969
- },
1970
- // E.g., code block language (after ```).
1971
- {
1972
- tag: [
1973
- tags.function(tags.variableName),
1974
- tags.labelName
1975
- ],
1976
- class: codeMark
1977
- },
1978
- {
1979
- tag: [
1980
- tags.monospace
1981
- ],
1982
- class: "font-mono"
1983
- },
1984
- // Headings.
1985
- {
1986
- tag: tags.heading1,
1987
- class: heading(1)
1988
- },
1989
- {
1990
- tag: tags.heading2,
1991
- class: heading(2)
1992
- },
1993
- {
1994
- tag: tags.heading3,
1995
- class: heading(3)
1996
- },
1997
- {
1998
- tag: tags.heading4,
1999
- class: heading(4)
2000
- },
2001
- {
2002
- tag: tags.heading5,
2003
- class: heading(5)
2004
- },
2005
- {
2006
- tag: tags.heading6,
2007
- class: heading(6)
2008
- },
2009
- // Emphasis.
2010
- {
2011
- tag: tags.emphasis,
2012
- class: italic
2013
- },
2014
- {
2015
- tag: tags.strong,
2016
- class: bold
1965
+ // packages/ui/react-ui-editor/src/themes/default.ts
1966
+ import get3 from "lodash.get";
1967
+ var defaultTheme = {
1968
+ //
1969
+ // Main layout:
1970
+ // https://codemirror.net/examples/styling
1971
+ //
1972
+ // <div class="cm-editor [cm-focused] [generated classes]">
1973
+ // <div class="cm-scroller">
1974
+ // <div class="cm-gutters">
1975
+ // <div class="cm-gutter [...]">
1976
+ // <div class="cm-gutterElement">...</div>
1977
+ // </div>
1978
+ // </div>
1979
+ // <div class="cm-content" role="textbox" contenteditable="true">
1980
+ // <div class="cm-line"></div>
1981
+ // </div>
1982
+ // <div class="cm-selectionLayer">
1983
+ // <div class="cm-selectionBackground"></div>
1984
+ // </div>
1985
+ // <div class="cm-cursorLayer">
1986
+ // <div class="cm-cursor"></div>
1987
+ // </div>
1988
+ // </div>
1989
+ // </div>
1990
+ //
1991
+ "&": {},
1992
+ "&.cm-focused": {
1993
+ outline: "none"
1994
+ },
1995
+ // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
1996
+ ".cm-scroller": {
1997
+ // TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
1998
+ // 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.
1999
+ overflowY: "auto",
2000
+ fontFamily: get3(tokens, "fontFamily.body", []).join(","),
2001
+ lineHeight: 1.5
2002
+ },
2003
+ ".cm-content": {
2004
+ // TODO(burdon): Is it possible to remove the padding value from CM's default theme?
2005
+ // padding: 'unset',
2006
+ // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
2007
+ fontSize: "16px"
2008
+ },
2009
+ "&light .cm-content": {
2010
+ color: get3(tokens, "extend.semanticColors.base.fg.light", "black"),
2011
+ caretColor: "black"
2012
+ },
2013
+ "&dark .cm-content": {
2014
+ color: get3(tokens, "extend.semanticColors.base.fg.dark", "white"),
2015
+ caretColor: "white"
2016
+ },
2017
+ //
2018
+ // Cursor
2019
+ //
2020
+ "&light .cm-cursor, &light .cm-dropCursor": {
2021
+ borderLeft: "2px solid black"
2022
+ },
2023
+ "&dark .cm-cursor, &dark .cm-dropCursor": {
2024
+ borderLeft: "2px solid white"
2025
+ },
2026
+ "&light .cm-placeholder": {
2027
+ color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
2028
+ },
2029
+ "&dark .cm-placeholder": {
2030
+ color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
2031
+ },
2032
+ //
2033
+ // line
2034
+ //
2035
+ ".cm-line": {
2036
+ paddingInline: 0
2037
+ },
2038
+ ".cm-activeLine": {
2039
+ background: "transparent"
2040
+ },
2041
+ //
2042
+ // gutter
2043
+ //
2044
+ ".cm-gutterElement": {
2045
+ width: "48px"
2046
+ },
2047
+ //
2048
+ // Selection
2049
+ //
2050
+ "&light .cm-selectionBackground": {
2051
+ background: get3(tokens, "extend.colors.primary.100")
2052
+ },
2053
+ "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
2054
+ background: get3(tokens, "extend.colors.primary.200")
2055
+ },
2056
+ "&dark .cm-selectionBackground": {
2057
+ background: get3(tokens, "extend.colors.primary.700")
2058
+ },
2059
+ "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
2060
+ background: get3(tokens, "extend.colors.primary.600")
2061
+ },
2062
+ //
2063
+ // Search
2064
+ //
2065
+ "&light .cm-searchMatch": {
2066
+ backgroundColor: get3(tokens, "extend.colors.yellow.100")
2067
+ },
2068
+ "&dark .cm-searchMatch": {
2069
+ backgroundColor: get3(tokens, "extend.colors.yellow.700")
2070
+ },
2071
+ //
2072
+ // link
2073
+ //
2074
+ ".cm-link": {
2075
+ color: get3(tokens, "extend.colors.primary.500"),
2076
+ textDecorationLine: "underline",
2077
+ textDecorationThickness: "1px",
2078
+ textUnderlineOffset: "2px",
2079
+ borderRadius: ".125rem",
2080
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
2081
+ },
2082
+ //
2083
+ // tooltip
2084
+ //
2085
+ ".cm-tooltip": {
2086
+ border: "none",
2087
+ background: "unset"
2088
+ },
2089
+ ".cm-tooltip-below": {},
2090
+ //
2091
+ // autocomplete
2092
+ //
2093
+ ".cm-tooltip-autocomplete": {
2094
+ marginTop: "4px",
2095
+ marginLeft: "-3px"
2096
+ },
2097
+ ".cm-tooltip-autocomplete ul li": {},
2098
+ ".cm-tooltip-autocomplete ul li[aria-selected]": {},
2099
+ ".cm-completionIcon": {
2100
+ display: "none"
2101
+ },
2102
+ ".cm-completionLabel": {
2103
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
2104
+ },
2105
+ ".cm-completionMatchedText": {
2106
+ textDecoration: "none"
2107
+ },
2108
+ //
2109
+ // table
2110
+ //
2111
+ ".cm-table *": {
2112
+ fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
2113
+ textDecoration: "none !important"
2114
+ },
2115
+ ".cm-table-head": {
2116
+ padding: "2px 16px 2px 0px",
2117
+ borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
2118
+ fontWeight: 100,
2119
+ textAlign: "left",
2120
+ color: get3(tokens, "extend.colors.neutral.500")
2121
+ },
2122
+ ".cm-table-cell": {
2123
+ padding: "2px 16px 2px 0px"
2124
+ },
2125
+ //
2126
+ // image
2127
+ //
2128
+ ".cm-image": {
2129
+ display: "block",
2130
+ height: "0"
2131
+ },
2132
+ ".cm-image.cm-loaded-image": {
2133
+ height: "auto",
2134
+ borderTop: "0.5rem solid transparent",
2135
+ borderBottom: "0.5rem solid transparent"
2136
+ },
2137
+ //
2138
+ // font size
2139
+ // TODO(thure): This appears to be the best or only way to set selection caret heights,
2140
+ // but it's far more verbose than it needs to be.
2141
+ //
2142
+ // ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
2143
+ // const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
2144
+ //
2145
+ // acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
2146
+ // acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
2147
+ // acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
2148
+ // return acc;
2149
+ // }, {}),
2150
+ /**
2151
+ * Panels
2152
+ * TODO(burdon): Needs styling attention (esp. dark mode).
2153
+ * https://github.com/codemirror/search/blob/main/src/search.ts#L745
2154
+ *
2155
+ * Find/replace panel.
2156
+ * <div class="cm-announced">...</div>
2157
+ * <div class="cm-scroller">...</div>
2158
+ * <div class="cm-panels cm-panels-bottom">
2159
+ * <div class="cm-search cm-panel">
2160
+ * <input class="cm-textfield" />
2161
+ * <button class="cm-button">...</button>
2162
+ * <label><input type="checkbox" />...</label>
2163
+ * </div>
2164
+ * </div
2165
+ */
2166
+ ".cm-panels": {
2167
+ border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
2168
+ },
2169
+ ".cm-panel": {
2170
+ background: get3(tokens, "extend.colors.neutral.50"),
2171
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
2172
+ },
2173
+ ".cm-button": {
2174
+ margin: "4px",
2175
+ fontFamily: get3(tokens, "fontFamily.body", []).join(","),
2176
+ background: get3(tokens, "extend.colors.neutral.100"),
2177
+ backgroundImage: "none",
2178
+ border: "none",
2179
+ "&:hover": {
2180
+ background: get3(tokens, "extend.colors.neutral.200")
2017
2181
  },
2018
- {
2019
- tag: tags.strikethrough,
2020
- class: strikethrough
2182
+ "&:active": {
2183
+ background: get3(tokens, "extend.colors.neutral.300"),
2184
+ backgroundImage: "none"
2185
+ }
2186
+ },
2187
+ ".cm-panel input[type=checkbox]": {
2188
+ marginRight: "0.4rem !important"
2189
+ }
2190
+ };
2191
+
2192
+ // packages/ui/react-ui-editor/src/extensions/factories.ts
2193
+ var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
2194
+ var defaults = {
2195
+ bracketMatching: true,
2196
+ closeBrackets: true,
2197
+ drawSelection: true,
2198
+ editable: true,
2199
+ history: true,
2200
+ lineWrapping: true
2201
+ };
2202
+ var createBasicExtensions = (_props) => {
2203
+ const props = defaultsDeep2({}, _props, defaults);
2204
+ return [
2205
+ // TODO(burdon): Doesn't catch errors in keymap functions.
2206
+ EditorView10.exceptionSink.of((err) => {
2207
+ log7.catch(err, void 0, {
2208
+ F: __dxlog_file9,
2209
+ L: 78,
2210
+ S: void 0,
2211
+ C: (f, a) => f(...a)
2212
+ });
2213
+ }),
2214
+ props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
2215
+ props.bracketMatching && bracketMatching(),
2216
+ props.closeBrackets && closeBrackets(),
2217
+ props.crosshairCursor && crosshairCursor(),
2218
+ props.dropCursor && dropCursor(),
2219
+ props.drawSelection && drawSelection(),
2220
+ props.highlightActiveLine && highlightActiveLine(),
2221
+ props.history && history(),
2222
+ props.lineNumbers && lineNumbers(),
2223
+ props.lineWrapping && EditorView10.lineWrapping,
2224
+ props.placeholder && placeholder(props.placeholder),
2225
+ props.readonly && [
2226
+ EditorState.readOnly.of(true),
2227
+ EditorView10.editable.of(false)
2228
+ ],
2229
+ props.scrollPastEnd && scrollPastEnd(),
2230
+ props.tabSize && EditorState.tabSize.of(props.tabSize)
2231
+ ].filter(isNotFalsy2);
2232
+ };
2233
+ var defaultSlots = {
2234
+ editor: {
2235
+ className: "w-full bs-full"
2236
+ }
2237
+ };
2238
+ var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
2239
+ const slots = defaultsDeep2({}, _slots, defaultSlots);
2240
+ return [
2241
+ EditorView10.baseTheme(defaultTheme),
2242
+ EditorView10.darkTheme.of(themeMode === "dark"),
2243
+ theme && EditorView10.theme(theme),
2244
+ slots.editor?.className && EditorView10.editorAttributes.of({
2245
+ class: slots.editor.className
2246
+ }),
2247
+ slots.content?.className && EditorView10.contentAttributes.of({
2248
+ class: slots.content.className
2249
+ })
2250
+ ].filter(isNotFalsy2);
2251
+ };
2252
+ var createDataExtensions = ({ id, text, space, identity }) => {
2253
+ const extensions = [
2254
+ automerge(text)
2255
+ ];
2256
+ if (space && identity) {
2257
+ const peerId = identity?.identityKey.toHex();
2258
+ const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
2259
+ const awarenessProvider2 = new SpaceAwarenessProvider({
2260
+ space,
2261
+ channel: `awareness.${id}`,
2262
+ peerId: identity.identityKey.toHex(),
2263
+ info: {
2264
+ displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
2265
+ color: cursorDarkValue,
2266
+ lightColor: cursorLightValue
2267
+ }
2268
+ });
2269
+ extensions.push(awareness(awarenessProvider2));
2270
+ }
2271
+ return extensions;
2272
+ };
2273
+
2274
+ // packages/ui/react-ui-editor/src/extensions/listener.ts
2275
+ import { EditorView as EditorView11 } from "@codemirror/view";
2276
+ var listener = ({ onFocus, onChange }) => {
2277
+ const extensions = [];
2278
+ onFocus && extensions.push(EditorView11.focusChangeEffect.of((_, focusing) => {
2279
+ onFocus(focusing);
2280
+ return null;
2281
+ }));
2282
+ onChange && extensions.push(EditorView11.updateListener.of((update2) => {
2283
+ onChange(update2.state.doc.toString());
2284
+ }));
2285
+ return extensions;
2286
+ };
2287
+
2288
+ // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
2289
+ import { closeBracketsKeymap } from "@codemirror/autocomplete";
2290
+ import { historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
2291
+ import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
2292
+ import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
2293
+ import { languages } from "@codemirror/language-data";
2294
+ import { searchKeymap } from "@codemirror/search";
2295
+ import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
2296
+ import { keymap as keymap5 } from "@codemirror/view";
2297
+
2298
+ // packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
2299
+ import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
2300
+ import { HighlightStyle } from "@codemirror/language";
2301
+ import { tags, styleTags, Tag } from "@lezer/highlight";
2302
+ import { Table } from "@lezer/markdown";
2303
+ var markdownTags = {
2304
+ Blockquote: Tag.define(),
2305
+ CodeMark: Tag.define(),
2306
+ CodeText: Tag.define(),
2307
+ EmphasisMark: Tag.define(),
2308
+ HeaderMark: Tag.define(),
2309
+ InlineCode: Tag.define(),
2310
+ LinkLabel: Tag.define(),
2311
+ LinkReference: Tag.define(),
2312
+ ListMark: Tag.define(),
2313
+ QuoteMark: Tag.define(),
2314
+ URL: Tag.define(),
2315
+ // Custom.
2316
+ TableCell: Tag.define()
2317
+ };
2318
+ Table.defineNodes?.forEach((node) => {
2319
+ switch (node?.name) {
2320
+ case "TableCell": {
2321
+ node.style = markdownTags.TableCell;
2322
+ break;
2323
+ }
2324
+ }
2325
+ });
2326
+ var markdownTagsExtensions = [
2327
+ Table,
2328
+ {
2329
+ props: [
2330
+ styleTags(markdownTags)
2331
+ ]
2332
+ }
2333
+ ];
2334
+ var markdownHighlightStyle = (readonly) => {
2335
+ return HighlightStyle.define([
2336
+ {
2337
+ tag: [
2338
+ tags.keyword,
2339
+ tags.name,
2340
+ tags.deleted,
2341
+ tags.character,
2342
+ tags.propertyName,
2343
+ tags.macroName,
2344
+ tags.color,
2345
+ tags.constant(tags.name),
2346
+ tags.standard(tags.name),
2347
+ tags.definition(tags.name),
2348
+ tags.separator,
2349
+ tags.typeName,
2350
+ tags.className,
2351
+ tags.number,
2352
+ tags.changed,
2353
+ tags.annotation,
2354
+ tags.modifier,
2355
+ tags.self,
2356
+ tags.namespace,
2357
+ tags.operator,
2358
+ tags.operatorKeyword,
2359
+ tags.escape,
2360
+ tags.regexp,
2361
+ tags.special(tags.string),
2362
+ tags.meta,
2363
+ tags.comment,
2364
+ tags.atom,
2365
+ tags.bool,
2366
+ tags.special(tags.variableName),
2367
+ tags.processingInstruction,
2368
+ tags.string,
2369
+ tags.inserted,
2370
+ tags.invalid
2371
+ ],
2372
+ color: "inherit !important"
2373
+ },
2374
+ // Markdown marks.
2375
+ {
2376
+ tag: [
2377
+ tags.meta,
2378
+ tags.processingInstruction,
2379
+ markdownTags.LinkLabel,
2380
+ markdownTags.LinkReference,
2381
+ markdownTags.ListMark
2382
+ ],
2383
+ class: mark
2384
+ },
2385
+ // Markdown marks.
2386
+ {
2387
+ tag: [
2388
+ markdownTags.CodeMark,
2389
+ markdownTags.HeaderMark,
2390
+ markdownTags.QuoteMark,
2391
+ markdownTags.EmphasisMark
2392
+ ],
2393
+ class: mark
2394
+ },
2395
+ // E.g., code block language (after ```).
2396
+ {
2397
+ tag: [
2398
+ tags.function(tags.variableName),
2399
+ tags.labelName
2400
+ ],
2401
+ class: codeMark
2402
+ },
2403
+ {
2404
+ tag: [
2405
+ tags.monospace
2406
+ ],
2407
+ class: "font-mono"
2408
+ },
2409
+ // Headings.
2410
+ {
2411
+ tag: tags.heading1,
2412
+ class: heading(1)
2413
+ },
2414
+ {
2415
+ tag: tags.heading2,
2416
+ class: heading(2)
2417
+ },
2418
+ {
2419
+ tag: tags.heading3,
2420
+ class: heading(3)
2421
+ },
2422
+ {
2423
+ tag: tags.heading4,
2424
+ class: heading(4)
2425
+ },
2426
+ {
2427
+ tag: tags.heading5,
2428
+ class: heading(5)
2429
+ },
2430
+ {
2431
+ tag: tags.heading6,
2432
+ class: heading(6)
2433
+ },
2434
+ // Emphasis.
2435
+ {
2436
+ tag: tags.emphasis,
2437
+ class: italic
2438
+ },
2439
+ {
2440
+ tag: tags.strong,
2441
+ class: bold
2442
+ },
2443
+ {
2444
+ tag: tags.strikethrough,
2445
+ class: strikethrough
2021
2446
  },
2022
2447
  // Naked URLs.
2023
2448
  {
@@ -2101,7 +2526,7 @@ var createMarkdownExtensions = ({ themeMode } = {}) => {
2101
2526
  // packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
2102
2527
  import { syntaxTree } from "@codemirror/language";
2103
2528
  import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
2104
- import { EditorView as EditorView11, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
2529
+ import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
2105
2530
  import { mx as mx2 } from "@dxos/react-ui-theme";
2106
2531
  var HorizontalRuleWidget = class extends WidgetType3 {
2107
2532
  toDOM() {
@@ -2135,7 +2560,7 @@ var CheckboxWidget = class extends WidgetType3 {
2135
2560
  }
2136
2561
  toDOM(view) {
2137
2562
  const input = document.createElement("input");
2138
- input.className = "cm-task-checkbox";
2563
+ input.className = "cm-task-checkbox ch-checkbox ch-focus-ring -mbs-0.5";
2139
2564
  input.type = "checkbox";
2140
2565
  input.checked = this._checked;
2141
2566
  if (view.state.readOnly) {
@@ -2309,15 +2734,15 @@ var decorateMarkdown = (options = {}) => {
2309
2734
  }
2310
2735
  }, {
2311
2736
  provide: (plugin) => [
2312
- EditorView11.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2313
- EditorView11.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2314
- EditorView11.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
2737
+ EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2738
+ EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2739
+ EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
2315
2740
  ]
2316
2741
  }),
2317
2742
  formattingStyles
2318
2743
  ];
2319
2744
  };
2320
- var formattingStyles = EditorView11.baseTheme({
2745
+ var formattingStyles = EditorView12.baseTheme({
2321
2746
  "& .cm-code": {
2322
2747
  fontFamily: getToken("fontFamily.mono", []).join(",")
2323
2748
  },
@@ -2370,7 +2795,7 @@ var formattingStyles = EditorView11.baseTheme({
2370
2795
  import { snippet } from "@codemirror/autocomplete";
2371
2796
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
2372
2797
  import { EditorSelection } from "@codemirror/state";
2373
- import { EditorView as EditorView12, keymap as keymap6 } from "@codemirror/view";
2798
+ import { EditorView as EditorView13, keymap as keymap6 } from "@codemirror/view";
2374
2799
  import { useState, useMemo } from "react";
2375
2800
  var compareFormatting = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
2376
2801
  var Inline;
@@ -3440,7 +3865,7 @@ var getFormatting = (state) => {
3440
3865
  };
3441
3866
  var useFormattingState = () => {
3442
3867
  const [state, setState] = useState(null);
3443
- const observer = useMemo(() => EditorView12.updateListener.of((update2) => {
3868
+ const observer = useMemo(() => EditorView13.updateListener.of((update2) => {
3444
3869
  if (update2.docChanged || update2.selectionSet) {
3445
3870
  const newState = getFormatting(update2.state);
3446
3871
  if (!state || !compareFormatting(state, newState)) {
@@ -3457,7 +3882,7 @@ var useFormattingState = () => {
3457
3882
  // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
3458
3883
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
3459
3884
  import { StateField as StateField5 } from "@codemirror/state";
3460
- import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
3885
+ import { Decoration as Decoration6, EditorView as EditorView14, WidgetType as WidgetType4 } from "@codemirror/view";
3461
3886
  var image = (options = {}) => {
3462
3887
  return StateField5.define({
3463
3888
  create: (state) => {
@@ -3484,7 +3909,7 @@ var image = (options = {}) => {
3484
3909
  add: buildDecorations2(from, to, tr.state)
3485
3910
  });
3486
3911
  },
3487
- provide: (field) => EditorView13.decorations.from(field)
3912
+ provide: (field) => EditorView14.decorations.from(field)
3488
3913
  });
3489
3914
  };
3490
3915
  var preloaded = /* @__PURE__ */ new Set();
@@ -3572,12 +3997,12 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
3572
3997
  // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
3573
3998
  import { syntaxTree as syntaxTree5 } from "@codemirror/language";
3574
3999
  import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
3575
- import { Decoration as Decoration7, EditorView as EditorView14, WidgetType as WidgetType5 } from "@codemirror/view";
4000
+ import { Decoration as Decoration7, EditorView as EditorView15, WidgetType as WidgetType5 } from "@codemirror/view";
3576
4001
  var table = (options = {}) => {
3577
4002
  return StateField6.define({
3578
4003
  create: (state) => update(state, options),
3579
4004
  update: (_, tr) => update(tr.state, options),
3580
- provide: (field) => EditorView14.decorations.from(field)
4005
+ provide: (field) => EditorView15.decorations.from(field)
3581
4006
  });
3582
4007
  };
3583
4008
  var update = (state, options) => {
@@ -3671,8 +4096,8 @@ var TableWidget = class extends WidgetType5 {
3671
4096
 
3672
4097
  // packages/ui/react-ui-editor/src/extensions/mention.ts
3673
4098
  import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
3674
- import { log as log6 } from "@dxos/log";
3675
- var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
4099
+ import { log as log8 } from "@dxos/log";
4100
+ var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
3676
4101
  var mention = ({ onSearch }) => {
3677
4102
  return autocompletion2({
3678
4103
  // TODO(burdon): Not working.
@@ -3684,10 +4109,10 @@ var mention = ({ onSearch }) => {
3684
4109
  icons: false,
3685
4110
  override: [
3686
4111
  (context) => {
3687
- log6.info("completion context", {
4112
+ log8.info("completion context", {
3688
4113
  context
3689
4114
  }, {
3690
- F: __dxlog_file8,
4115
+ F: __dxlog_file10,
3691
4116
  L: 26,
3692
4117
  S: void 0,
3693
4118
  C: (f, a) => f(...a)
@@ -3794,9 +4219,9 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
3794
4219
  };
3795
4220
 
3796
4221
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
3797
- var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
4222
+ var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
3798
4223
  var instanceCount = 0;
3799
- var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo = EditorView15.scrollIntoView(0), moveToEndOfLine, debug, dataTestId }, forwardedRef) => {
4224
+ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo = EditorView16.scrollIntoView(0), moveToEndOfLine, debug, dataTestId }, forwardedRef) => {
3800
4225
  const [instanceId] = useState2(() => `text-editor-${++instanceCount}`);
3801
4226
  const tabsterDOMAttribute = useFocusableGroup({
3802
4227
  tabBehavior: "limited"
@@ -3815,31 +4240,31 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
3815
4240
  autoFocus
3816
4241
  ]);
3817
4242
  useEffect2(() => {
3818
- log7("updating", {
4243
+ log9("updating", {
3819
4244
  id,
3820
4245
  instanceId
3821
4246
  }, {
3822
- F: __dxlog_file9,
4247
+ F: __dxlog_file11,
3823
4248
  L: 88,
3824
4249
  S: void 0,
3825
4250
  C: (f, a) => f(...a)
3826
4251
  });
3827
- const state = EditorState.create({
4252
+ const state = EditorState2.create({
3828
4253
  doc,
3829
4254
  selection,
3830
4255
  extensions: [
3831
4256
  id && documentId2.of(id),
3832
4257
  // TODO(burdon): NOTE: Doesn't catch errors in keymap functions.
3833
- EditorView15.exceptionSink.of((err) => {
3834
- log7.catch(err, void 0, {
3835
- F: __dxlog_file9,
4258
+ EditorView16.exceptionSink.of((err) => {
4259
+ log9.catch(err, void 0, {
4260
+ F: __dxlog_file11,
3836
4261
  L: 101,
3837
4262
  S: void 0,
3838
4263
  C: (f, a) => f(...a)
3839
4264
  });
3840
4265
  }),
3841
4266
  // Focus.
3842
- EditorView15.updateListener.of((update2) => {
4267
+ EditorView16.updateListener.of((update2) => {
3843
4268
  update2.transactions.forEach((transaction) => {
3844
4269
  if (transaction.isUserEvent("focus.container")) {
3845
4270
  rootRef.current?.focus();
@@ -3847,9 +4272,9 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
3847
4272
  });
3848
4273
  }),
3849
4274
  extensions
3850
- ].filter(isNotFalsy2)
4275
+ ].filter(isNotFalsy3)
3851
4276
  });
3852
- const view2 = new EditorView15({
4277
+ const view2 = new EditorView16({
3853
4278
  state,
3854
4279
  parent: rootRef.current,
3855
4280
  scrollTo,
@@ -4030,585 +4455,146 @@ var MarkdownHeading = () => {
4030
4455
  className: iconStyles
4031
4456
  }), level === 6 && /* @__PURE__ */ React2.createElement(TextHSix, {
4032
4457
  className: iconStyles
4033
- })))), /* @__PURE__ */ React2.createElement(Select.ScrollDownButton, null), /* @__PURE__ */ React2.createElement(Select.Arrow, null)))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
4034
- };
4035
- var markdownStyles = [
4036
- {
4037
- type: "strong",
4038
- Icon: TextB,
4039
- getState: (state) => state.strong
4040
- },
4041
- {
4042
- type: "emphasis",
4043
- Icon: TextItalic,
4044
- getState: (state) => state.emphasis
4045
- },
4046
- {
4047
- type: "strikethrough",
4048
- Icon: TextStrikethrough,
4049
- getState: (state) => state.strikethrough
4050
- },
4051
- {
4052
- type: "code",
4053
- Icon: Code,
4054
- getState: (state) => state.code
4055
- },
4056
- {
4057
- type: "link",
4058
- Icon: Link,
4059
- getState: (state) => state.link
4060
- }
4061
- ];
4062
- var MarkdownStyles = () => {
4063
- const { onAction, state } = useToolbarContext("MarkdownStyles");
4064
- const { t } = useTranslation(translationKey);
4065
- return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4066
- type: "multiple",
4067
- value: markdownStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)
4068
- }, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4069
- key: type,
4070
- value: type,
4071
- Icon,
4072
- disabled: state?.blockType === "codeblock",
4073
- onClick: state ? () => onAction?.({
4074
- type,
4075
- data: !getState(state)
4076
- }) : void 0
4077
- }, t(`${type} label`))));
4078
- };
4079
- var markdownLists = [
4080
- {
4081
- type: "list-bullet",
4082
- Icon: ListBullets,
4083
- getState: (state) => state.listStyle === "bullet"
4084
- },
4085
- {
4086
- type: "list-ordered",
4087
- Icon: ListNumbers,
4088
- getState: (state) => state.listStyle === "ordered"
4089
- },
4090
- {
4091
- type: "list-task",
4092
- Icon: ListChecks,
4093
- getState: (state) => state.listStyle === "task"
4094
- }
4095
- ];
4096
- var MarkdownLists = () => {
4097
- const { onAction, state } = useToolbarContext("MarkdownStyles");
4098
- const { t } = useTranslation(translationKey);
4099
- return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4100
- type: "single",
4101
- value: state?.listStyle ? `list-${state.listStyle}` : ""
4102
- }, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4103
- key: type,
4104
- value: type,
4105
- Icon,
4106
- onClick: state ? () => onAction?.({
4107
- type,
4108
- data: !getState(state)
4109
- }) : void 0
4110
- }, t(`${type} label`))));
4111
- };
4112
- var markdownBlocks = [
4113
- {
4114
- type: "blockquote",
4115
- Icon: Quotes,
4116
- getState: (state) => state.blockQuote
4117
- },
4118
- {
4119
- type: "codeblock",
4120
- Icon: CodeBlock,
4121
- getState: (state) => state.blockType === "codeblock"
4122
- },
4123
- {
4124
- type: "table",
4125
- Icon: Table2,
4126
- getState: (state) => state.blockType === "tablecell",
4127
- disabled: (state) => !state.blankLine
4128
- }
4129
- ];
4130
- var MarkdownBlocks = () => {
4131
- const { onAction, state } = useToolbarContext("MarkdownStyles");
4132
- const { t } = useTranslation(translationKey);
4133
- const value = markdownBlocks.find(({ getState }) => state && getState(state));
4134
- return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4135
- type: "single",
4136
- value: value?.type ?? ""
4137
- }, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4138
- key: type,
4139
- value: type,
4140
- Icon,
4141
- disabled: !state || disabled?.(state),
4142
- onClick: state ? () => onAction?.({
4143
- type,
4144
- data: !getState(state)
4145
- }) : void 0
4146
- }, t(`${type} label`))));
4147
- };
4148
- var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null));
4149
- var MarkdownExtended = () => {
4150
- const { onAction } = useToolbarContext("MarkdownStyles");
4151
- const { t } = useTranslation(translationKey);
4152
- return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
4153
- asChild: true
4154
- }, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
4155
- variant: "ghost",
4156
- "data-testid": "editor.toolbar.comment",
4157
- onClick: () => onAction?.({
4158
- type: "comment"
4159
- }),
4160
- classNames: buttonStyles
4161
- }, /* @__PURE__ */ React2.createElement(ChatText, {
4162
- className: iconStyles
4163
- }), /* @__PURE__ */ React2.createElement("span", {
4164
- className: "sr-only"
4165
- }, t("comment label")))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("comment label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
4166
- };
4167
- var Toolbar = {
4168
- Root: ToolbarRoot,
4169
- Button: ToolbarButton,
4170
- Separator: ToolbarSeparator,
4171
- Markdown: MarkdownStandard,
4172
- Extended: MarkdownExtended
4173
- };
4174
-
4175
- // packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
4176
- import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
4177
- import { Context as Context2 } from "@dxos/context";
4178
- import { invariant as invariant3 } from "@dxos/invariant";
4179
- import { log as log8 } from "@dxos/log";
4180
- var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
4181
- var DEBOUNCE_INTERVAL = 100;
4182
- var SpaceAwarenessProvider = class {
4183
- constructor(params) {
4184
- this._remoteStates = /* @__PURE__ */ new Map();
4185
- this.remoteStateChange = new Event2();
4186
- this._space = params.space;
4187
- this._channel = params.channel;
4188
- this._peerId = params.peerId;
4189
- this._info = params.info;
4190
- }
4191
- open() {
4192
- this._ctx = new Context2();
4193
- this._postTask = new DeferredTask(this._ctx, async () => {
4194
- if (this._localState) {
4195
- await this._space.postMessage(this._channel, {
4196
- kind: "post",
4197
- state: this._localState
4198
- });
4199
- await sleep(DEBOUNCE_INTERVAL);
4200
- }
4201
- });
4202
- this._ctx.onDispose(this._space.listen(this._channel, (message) => {
4203
- switch (message.payload.kind) {
4204
- case "query": {
4205
- this._handleQueryMessage();
4206
- break;
4207
- }
4208
- case "post": {
4209
- this._handlePostMessage(message.payload);
4210
- break;
4211
- }
4212
- }
4213
- }));
4214
- void this._space.postMessage(this._channel, {
4215
- kind: "query"
4216
- }).catch((err) => {
4217
- log8.debug("failed to query awareness", {
4218
- err
4219
- }, {
4220
- F: __dxlog_file10,
4221
- L: 89,
4222
- S: this,
4223
- C: (f, a) => f(...a)
4224
- });
4225
- });
4226
- }
4227
- close() {
4228
- void this._ctx?.dispose();
4229
- this._ctx = void 0;
4230
- this._postTask = void 0;
4231
- }
4232
- getRemoteStates() {
4233
- return Array.from(this._remoteStates.values());
4234
- }
4235
- update(position) {
4236
- invariant3(this._postTask, void 0, {
4237
- F: __dxlog_file10,
4238
- L: 104,
4239
- S: this,
4240
- A: [
4241
- "this._postTask",
4242
- ""
4243
- ]
4244
- });
4245
- this._localState = {
4246
- peerId: this._peerId,
4247
- position,
4248
- info: this._info
4249
- };
4250
- this._postTask.schedule();
4251
- }
4252
- _handleQueryMessage() {
4253
- invariant3(this._postTask, void 0, {
4254
- F: __dxlog_file10,
4255
- L: 115,
4256
- S: this,
4257
- A: [
4258
- "this._postTask",
4259
- ""
4260
- ]
4261
- });
4262
- this._postTask.schedule();
4263
- }
4264
- _handlePostMessage(message) {
4265
- invariant3(message.kind === "post", void 0, {
4266
- F: __dxlog_file10,
4267
- L: 120,
4268
- S: this,
4269
- A: [
4270
- "message.kind === 'post'",
4271
- ""
4272
- ]
4273
- });
4274
- this._remoteStates.set(message.state.peerId, message.state);
4275
- this.remoteStateChange.emit();
4276
- }
4277
- };
4278
-
4279
- // packages/ui/react-ui-editor/src/hooks/extension-utils.ts
4280
- import { closeBrackets } from "@codemirror/autocomplete";
4281
- import { history } from "@codemirror/commands";
4282
- import { bracketMatching } from "@codemirror/language";
4283
- import { EditorState as EditorState2 } from "@codemirror/state";
4284
- import { EditorView as EditorView16, crosshairCursor, drawSelection, dropCursor, highlightActiveLine, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
4285
- import defaultsDeep2 from "lodash.defaultsdeep";
4286
- import { useMemo as useMemo2 } from "react";
4287
- import { generateName } from "@dxos/display-name";
4288
- import { createDocAccessor, getTextContent } from "@dxos/echo-schema";
4289
- import { log as log9 } from "@dxos/log";
4290
- import { hueTokens } from "@dxos/react-ui-theme";
4291
- import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
4292
-
4293
- // packages/ui/react-ui-editor/src/themes/default.ts
4294
- import get3 from "lodash.get";
4295
- var defaultTheme = {
4296
- //
4297
- // Main layout:
4298
- // https://codemirror.net/examples/styling
4299
- //
4300
- // <div class="cm-editor [cm-focused] [generated classes]">
4301
- // <div class="cm-scroller">
4302
- // <div class="cm-gutters">
4303
- // <div class="cm-gutter [...]">
4304
- // <div class="cm-gutterElement">...</div>
4305
- // </div>
4306
- // </div>
4307
- // <div class="cm-content" role="textbox" contenteditable="true">
4308
- // <div class="cm-line"></div>
4309
- // </div>
4310
- // <div class="cm-selectionLayer">
4311
- // <div class="cm-selectionBackground"></div>
4312
- // </div>
4313
- // <div class="cm-cursorLayer">
4314
- // <div class="cm-cursor"></div>
4315
- // </div>
4316
- // </div>
4317
- // </div>
4318
- //
4319
- "&": {},
4320
- "&.cm-focused": {
4321
- outline: "none"
4322
- },
4323
- // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
4324
- ".cm-scroller": {
4325
- // TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
4326
- // 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.
4327
- overflowY: "auto",
4328
- fontFamily: get3(tokens, "fontFamily.body", []).join(","),
4329
- lineHeight: 1.5
4330
- },
4331
- ".cm-content": {
4332
- // TODO(burdon): Is it possible to remove the padding value from CM's default theme?
4333
- // padding: 'unset',
4334
- // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
4335
- fontSize: "16px"
4336
- },
4337
- "&light .cm-content": {
4338
- color: get3(tokens, "extend.semanticColors.base.fg.light", "black"),
4339
- caretColor: "black"
4340
- },
4341
- "&dark .cm-content": {
4342
- color: get3(tokens, "extend.semanticColors.base.fg.dark", "white"),
4343
- caretColor: "white"
4344
- },
4345
- //
4346
- // Cursor
4347
- //
4348
- "&light .cm-cursor, &light .cm-dropCursor": {
4349
- borderLeft: "2px solid black"
4350
- },
4351
- "&dark .cm-cursor, &dark .cm-dropCursor": {
4352
- borderLeft: "2px solid white"
4353
- },
4354
- "&light .cm-placeholder": {
4355
- color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
4356
- },
4357
- "&dark .cm-placeholder": {
4358
- color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
4359
- },
4360
- //
4361
- // line
4362
- //
4363
- ".cm-line": {
4364
- paddingInline: 0
4365
- },
4366
- ".cm-activeLine": {
4367
- background: "transparent"
4368
- },
4369
- //
4370
- // gutter
4371
- //
4372
- ".cm-gutterElement": {
4373
- width: "48px"
4374
- },
4375
- //
4376
- // Selection
4377
- //
4378
- "&light .cm-selectionBackground": {
4379
- background: get3(tokens, "extend.colors.primary.100")
4380
- },
4381
- "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
4382
- background: get3(tokens, "extend.colors.primary.200")
4383
- },
4384
- "&dark .cm-selectionBackground": {
4385
- background: get3(tokens, "extend.colors.primary.700")
4386
- },
4387
- "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
4388
- background: get3(tokens, "extend.colors.primary.600")
4389
- },
4390
- //
4391
- // Search
4392
- //
4393
- "&light .cm-searchMatch": {
4394
- backgroundColor: get3(tokens, "extend.colors.yellow.100")
4395
- },
4396
- "&dark .cm-searchMatch": {
4397
- backgroundColor: get3(tokens, "extend.colors.yellow.700")
4398
- },
4399
- //
4400
- // link
4401
- //
4402
- ".cm-link": {
4403
- color: get3(tokens, "extend.colors.primary.500"),
4404
- textDecorationLine: "underline",
4405
- textDecorationThickness: "1px",
4406
- textUnderlineOffset: "2px",
4407
- borderRadius: ".125rem",
4408
- fontFamily: get3(tokens, "fontFamily.body", []).join(",")
4409
- },
4410
- //
4411
- // tooltip
4412
- //
4413
- ".cm-tooltip": {
4414
- border: "none",
4415
- background: "unset"
4416
- },
4417
- ".cm-tooltip-below": {},
4418
- //
4419
- // autocomplete
4420
- //
4421
- ".cm-tooltip-autocomplete": {
4422
- marginTop: "4px",
4423
- marginLeft: "-3px"
4424
- },
4425
- ".cm-tooltip-autocomplete ul li": {},
4426
- ".cm-tooltip-autocomplete ul li[aria-selected]": {},
4427
- ".cm-completionIcon": {
4428
- display: "none"
4429
- },
4430
- ".cm-completionLabel": {
4431
- fontFamily: get3(tokens, "fontFamily.body", []).join(",")
4432
- },
4433
- ".cm-completionMatchedText": {
4434
- textDecoration: "none"
4435
- },
4436
- //
4437
- // table
4438
- //
4439
- ".cm-table *": {
4440
- fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
4441
- textDecoration: "none !important"
4442
- },
4443
- ".cm-table-head": {
4444
- padding: "2px 16px 2px 0px",
4445
- borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
4446
- fontWeight: 100,
4447
- textAlign: "left",
4448
- color: get3(tokens, "extend.colors.neutral.500")
4449
- },
4450
- ".cm-table-cell": {
4451
- padding: "2px 16px 2px 0px"
4452
- },
4453
- //
4454
- // image
4455
- //
4456
- ".cm-image": {
4457
- display: "block",
4458
- height: "0"
4459
- },
4460
- ".cm-image.cm-loaded-image": {
4461
- height: "auto",
4462
- borderTop: "0.5rem solid transparent",
4463
- borderBottom: "0.5rem solid transparent"
4458
+ })))), /* @__PURE__ */ React2.createElement(Select.ScrollDownButton, null), /* @__PURE__ */ React2.createElement(Select.Arrow, null)))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
4459
+ };
4460
+ var markdownStyles = [
4461
+ {
4462
+ type: "strong",
4463
+ Icon: TextB,
4464
+ getState: (state) => state.strong
4464
4465
  },
4465
- //
4466
- // font size
4467
- // TODO(thure): This appears to be the best or only way to set selection caret heights,
4468
- // but it's far more verbose than it needs to be.
4469
- //
4470
- // ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
4471
- // const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
4472
- //
4473
- // acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
4474
- // acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
4475
- // acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
4476
- // return acc;
4477
- // }, {}),
4478
- /**
4479
- * Panels
4480
- * TODO(burdon): Needs styling attention (esp. dark mode).
4481
- * https://github.com/codemirror/search/blob/main/src/search.ts#L745
4482
- *
4483
- * Find/replace panel.
4484
- * <div class="cm-announced">...</div>
4485
- * <div class="cm-scroller">...</div>
4486
- * <div class="cm-panels cm-panels-bottom">
4487
- * <div class="cm-search cm-panel">
4488
- * <input class="cm-textfield" />
4489
- * <button class="cm-button">...</button>
4490
- * <label><input type="checkbox" />...</label>
4491
- * </div>
4492
- * </div
4493
- */
4494
- ".cm-panels": {
4495
- border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
4466
+ {
4467
+ type: "emphasis",
4468
+ Icon: TextItalic,
4469
+ getState: (state) => state.emphasis
4496
4470
  },
4497
- ".cm-panel": {
4498
- background: get3(tokens, "extend.colors.neutral.50"),
4499
- fontFamily: get3(tokens, "fontFamily.body", []).join(",")
4471
+ {
4472
+ type: "strikethrough",
4473
+ Icon: TextStrikethrough,
4474
+ getState: (state) => state.strikethrough
4500
4475
  },
4501
- ".cm-button": {
4502
- margin: "4px",
4503
- fontFamily: get3(tokens, "fontFamily.body", []).join(","),
4504
- background: get3(tokens, "extend.colors.neutral.100"),
4505
- backgroundImage: "none",
4506
- border: "none",
4507
- "&:hover": {
4508
- background: get3(tokens, "extend.colors.neutral.200")
4509
- },
4510
- "&:active": {
4511
- background: get3(tokens, "extend.colors.neutral.300"),
4512
- backgroundImage: "none"
4513
- }
4476
+ {
4477
+ type: "code",
4478
+ Icon: Code,
4479
+ getState: (state) => state.code
4514
4480
  },
4515
- ".cm-panel input[type=checkbox]": {
4516
- marginRight: "0.4rem !important"
4481
+ {
4482
+ type: "link",
4483
+ Icon: Link,
4484
+ getState: (state) => state.link
4517
4485
  }
4486
+ ];
4487
+ var MarkdownStyles = () => {
4488
+ const { onAction, state } = useToolbarContext("MarkdownStyles");
4489
+ const { t } = useTranslation(translationKey);
4490
+ return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4491
+ type: "multiple",
4492
+ value: markdownStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)
4493
+ }, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4494
+ key: type,
4495
+ value: type,
4496
+ Icon,
4497
+ disabled: state?.blockType === "codeblock",
4498
+ onClick: state ? () => onAction?.({
4499
+ type,
4500
+ data: !getState(state)
4501
+ }) : void 0
4502
+ }, t(`${type} label`))));
4518
4503
  };
4519
-
4520
- // packages/ui/react-ui-editor/src/hooks/extension-utils.ts
4521
- var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/extension-utils.ts";
4522
- var defaults = {
4523
- bracketMatching: true,
4524
- closeBrackets: true,
4525
- drawSelection: true,
4526
- editable: true,
4527
- history: true,
4528
- lineWrapping: true
4529
- };
4530
- var createBasicExtensions = (_props) => {
4531
- const props = defaultsDeep2({}, _props, defaults);
4532
- return [
4533
- // TODO(burdon): Doesn't catch errors in keymap functions.
4534
- EditorView16.exceptionSink.of((err) => {
4535
- log9.catch(err, void 0, {
4536
- F: __dxlog_file11,
4537
- L: 79,
4538
- S: void 0,
4539
- C: (f, a) => f(...a)
4540
- });
4541
- }),
4542
- props.allowMultipleSelections && EditorState2.allowMultipleSelections.of(true),
4543
- props.bracketMatching && bracketMatching(),
4544
- props.closeBrackets && closeBrackets(),
4545
- props.crosshairCursor && crosshairCursor(),
4546
- props.dropCursor && dropCursor(),
4547
- props.drawSelection && drawSelection(),
4548
- props.highlightActiveLine && highlightActiveLine(),
4549
- props.history && history(),
4550
- props.lineNumbers && lineNumbers(),
4551
- props.lineWrapping && EditorView16.lineWrapping,
4552
- props.placeholder && placeholder(props.placeholder),
4553
- props.readonly && [
4554
- EditorState2.readOnly.of(true),
4555
- EditorView16.editable.of(false)
4556
- ],
4557
- props.scrollPastEnd && scrollPastEnd(),
4558
- props.tabSize && EditorState2.tabSize.of(props.tabSize)
4559
- ].filter(isNotFalsy3);
4504
+ var markdownLists = [
4505
+ {
4506
+ type: "list-bullet",
4507
+ Icon: ListBullets,
4508
+ getState: (state) => state.listStyle === "bullet"
4509
+ },
4510
+ {
4511
+ type: "list-ordered",
4512
+ Icon: ListNumbers,
4513
+ getState: (state) => state.listStyle === "ordered"
4514
+ },
4515
+ {
4516
+ type: "list-task",
4517
+ Icon: ListChecks,
4518
+ getState: (state) => state.listStyle === "task"
4519
+ }
4520
+ ];
4521
+ var MarkdownLists = () => {
4522
+ const { onAction, state } = useToolbarContext("MarkdownStyles");
4523
+ const { t } = useTranslation(translationKey);
4524
+ return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4525
+ type: "single",
4526
+ value: state?.listStyle ? `list-${state.listStyle}` : ""
4527
+ }, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4528
+ key: type,
4529
+ value: type,
4530
+ Icon,
4531
+ onClick: state ? () => onAction?.({
4532
+ type,
4533
+ data: !getState(state)
4534
+ }) : void 0
4535
+ }, t(`${type} label`))));
4560
4536
  };
4561
- var defaultSlots = {
4562
- editor: {
4563
- className: "w-full bs-full"
4537
+ var markdownBlocks = [
4538
+ {
4539
+ type: "blockquote",
4540
+ Icon: Quotes,
4541
+ getState: (state) => state.blockQuote
4542
+ },
4543
+ {
4544
+ type: "codeblock",
4545
+ Icon: CodeBlock,
4546
+ getState: (state) => state.blockType === "codeblock"
4564
4547
  },
4565
- content: {
4566
- className: "!p-2"
4548
+ {
4549
+ type: "table",
4550
+ Icon: Table2,
4551
+ getState: (state) => state.blockType === "tablecell",
4552
+ disabled: (state) => !state.blankLine
4567
4553
  }
4554
+ ];
4555
+ var MarkdownBlocks = () => {
4556
+ const { onAction, state } = useToolbarContext("MarkdownStyles");
4557
+ const { t } = useTranslation(translationKey);
4558
+ const value = markdownBlocks.find(({ getState }) => state && getState(state));
4559
+ return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4560
+ type: "single",
4561
+ value: value?.type ?? ""
4562
+ }, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4563
+ key: type,
4564
+ value: type,
4565
+ Icon,
4566
+ disabled: !state || disabled?.(state),
4567
+ onClick: state ? () => onAction?.({
4568
+ type,
4569
+ data: !getState(state)
4570
+ }) : void 0
4571
+ }, t(`${type} label`))));
4568
4572
  };
4569
- var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
4570
- const slots = defaultsDeep2({}, _slots, defaultSlots);
4571
- return [
4572
- EditorView16.baseTheme(defaultTheme),
4573
- EditorView16.darkTheme.of(themeMode === "dark"),
4574
- theme && EditorView16.theme(theme),
4575
- slots.editor?.className && EditorView16.editorAttributes.of({
4576
- class: slots.editor.className
4573
+ var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null));
4574
+ var MarkdownExtended = () => {
4575
+ const { onAction } = useToolbarContext("MarkdownStyles");
4576
+ const { t } = useTranslation(translationKey);
4577
+ return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
4578
+ asChild: true
4579
+ }, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
4580
+ variant: "ghost",
4581
+ "data-testid": "editor.toolbar.comment",
4582
+ onClick: () => onAction?.({
4583
+ type: "comment"
4577
4584
  }),
4578
- slots.content?.className && EditorView16.contentAttributes.of({
4579
- class: slots.content.className
4580
- })
4581
- ].filter(isNotFalsy3);
4582
- };
4583
- var createDataExtensions = ({ id, text, space, identity }) => {
4584
- const extensions = [
4585
- automerge(text)
4586
- ];
4587
- if (space && identity) {
4588
- const peerId = identity?.identityKey.toHex();
4589
- const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
4590
- const awarenessProvider2 = new SpaceAwarenessProvider({
4591
- space,
4592
- channel: `awareness.${id}`,
4593
- peerId: identity.identityKey.toHex(),
4594
- info: {
4595
- displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
4596
- color: cursorDarkValue,
4597
- lightColor: cursorLightValue
4598
- }
4599
- });
4600
- extensions.push(awareness(awarenessProvider2));
4601
- }
4602
- return extensions;
4585
+ classNames: buttonStyles
4586
+ }, /* @__PURE__ */ React2.createElement(ChatText, {
4587
+ className: iconStyles
4588
+ }), /* @__PURE__ */ React2.createElement("span", {
4589
+ className: "sr-only"
4590
+ }, t("comment label")))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("comment label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
4603
4591
  };
4604
- var useDocAccessor = (text) => {
4605
- return useMemo2(() => ({
4606
- id: text.id,
4607
- doc: getTextContent(text),
4608
- accessor: createDocAccessor(text)
4609
- }), [
4610
- text
4611
- ]);
4592
+ var Toolbar = {
4593
+ Root: ToolbarRoot,
4594
+ Button: ToolbarButton,
4595
+ Separator: ToolbarSeparator,
4596
+ Markdown: MarkdownStandard,
4597
+ Extended: MarkdownExtended
4612
4598
  };
4613
4599
 
4614
4600
  // packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
@@ -4659,6 +4645,19 @@ var useActionHandler = (view) => {
4659
4645
  };
4660
4646
  };
4661
4647
 
4648
+ // packages/ui/react-ui-editor/src/hooks/useDocAccessor.ts
4649
+ import { useMemo as useMemo2 } from "react";
4650
+ import { createDocAccessor, getTextContent } from "@dxos/echo-schema";
4651
+ var useDocAccessor = (text) => {
4652
+ return useMemo2(() => ({
4653
+ id: text.id,
4654
+ doc: getTextContent(text),
4655
+ accessor: createDocAccessor(text)
4656
+ }), [
4657
+ text
4658
+ ]);
4659
+ };
4660
+
4662
4661
  // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
4663
4662
  import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
4664
4663
  import { EditorView as EditorView17 } from "@codemirror/view";