@dxos/react-ui-editor 0.3.10-main.16895f7 → 0.3.10-main.375af01

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 (121) hide show
  1. package/dist/lib/browser/index.mjs +728 -732
  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/MarkdownEditor.stories.d.ts +35 -0
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -0
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +4 -2
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +9 -4
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts +9 -0
  11. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +1 -0
  12. package/dist/types/src/components/TextEditor/extensions/{basic/bundle.d.ts → basic.d.ts} +1 -1
  13. package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -0
  14. package/dist/types/src/components/TextEditor/extensions/{hyperlink/hyperlinkWidget.d.ts → experimental.d.ts} +2 -2
  15. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -0
  16. package/dist/types/src/components/TextEditor/extensions/index.d.ts +5 -2
  17. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
  18. package/dist/types/src/components/TextEditor/extensions/link.d.ts +11 -0
  19. package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +1 -0
  20. package/dist/types/src/components/TextEditor/extensions/listener.d.ts +7 -0
  21. package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -0
  22. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
  23. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts +31 -0
  24. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -0
  25. package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts +1 -1
  26. package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts.map +1 -1
  27. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +5 -0
  28. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -0
  29. package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts +12 -0
  30. package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts.map +1 -0
  31. package/dist/types/src/components/TextEditor/index.d.ts +2 -0
  32. package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
  33. package/dist/types/src/components/TextEditor/themes/default.d.ts +17 -0
  34. package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -0
  35. package/dist/types/src/components/TextEditor/themes/index.d.ts +2 -0
  36. package/dist/types/src/components/TextEditor/themes/index.d.ts.map +1 -0
  37. package/dist/types/src/components/TextEditor/yjs.stories.d.ts +1 -0
  38. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +1 -1
  39. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +1 -0
  40. package/dist/types/src/hooks/automerge/amToCodemirror.d.ts.map +1 -0
  41. package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -0
  42. package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts.map +1 -0
  43. package/dist/types/src/hooks/automerge/handle.d.ts.map +1 -0
  44. package/dist/types/src/hooks/automerge/index.d.ts.map +1 -0
  45. package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -0
  46. package/dist/types/src/hooks/index.d.ts +0 -1
  47. package/dist/types/src/hooks/index.d.ts.map +1 -1
  48. package/dist/types/src/hooks/useTextModel.d.ts +4 -4
  49. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  50. package/dist/types/src/styles/markdown.d.ts +12 -10
  51. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  52. package/package.json +20 -32
  53. package/src/components/TextEditor/MarkdownEditor.stories.tsx +242 -0
  54. package/src/components/TextEditor/TextEditor.stories.tsx +46 -43
  55. package/src/components/TextEditor/TextEditor.tsx +59 -45
  56. package/src/components/TextEditor/extensions/autocomplete.ts +72 -0
  57. package/src/components/TextEditor/extensions/{basic/bundle.ts → basic.ts} +4 -2
  58. package/src/components/TextEditor/extensions/{hyperlink/hyperlinkWidget.tsx → experimental.tsx} +17 -2
  59. package/src/components/TextEditor/extensions/index.ts +5 -2
  60. package/src/components/TextEditor/extensions/{hyperlink/hyperlinkDecoration.ts → link.ts} +68 -31
  61. package/src/components/TextEditor/extensions/{change.ts → listener.ts} +3 -3
  62. package/src/components/TextEditor/extensions/markdown/bundle.ts +15 -11
  63. package/src/components/TextEditor/extensions/markdown/highlight.ts +166 -0
  64. package/src/components/TextEditor/extensions/markdown/index.ts +1 -1
  65. package/src/components/TextEditor/extensions/tasklist.ts +113 -0
  66. package/src/components/TextEditor/extensions/{hyperlink/hyperlinkTooltip.tsx → tooltip.tsx} +9 -9
  67. package/src/components/TextEditor/index.ts +3 -0
  68. package/src/components/TextEditor/themes/default.ts +170 -0
  69. package/src/components/TextEditor/themes/index.ts +5 -0
  70. package/src/components/TextEditor/yjs.stories.tsx +1 -0
  71. package/src/{automerge → hooks/automerge}/automerge.stories.tsx +2 -1
  72. package/src/hooks/index.ts +0 -1
  73. package/src/hooks/useTextModel.ts +50 -40
  74. package/src/styles/markdown.ts +26 -24
  75. package/src/testing/replicator.ts +2 -2
  76. package/dist/types/src/automerge/automerge-plugin/PatchSemaphore.d.ts.map +0 -1
  77. package/dist/types/src/automerge/automerge-plugin/amToCodemirror.d.ts.map +0 -1
  78. package/dist/types/src/automerge/automerge-plugin/codeMirrorToAm.d.ts.map +0 -1
  79. package/dist/types/src/automerge/automerge-plugin/handle.d.ts.map +0 -1
  80. package/dist/types/src/automerge/automerge-plugin/index.d.ts.map +0 -1
  81. package/dist/types/src/automerge/automerge-plugin/plugin.d.ts.map +0 -1
  82. package/dist/types/src/automerge/automerge.stories.d.ts.map +0 -1
  83. package/dist/types/src/components/TextEditor/extensions/basic/bundle.d.ts.map +0 -1
  84. package/dist/types/src/components/TextEditor/extensions/basic/index.d.ts +0 -3
  85. package/dist/types/src/components/TextEditor/extensions/basic/index.d.ts.map +0 -1
  86. package/dist/types/src/components/TextEditor/extensions/basic/theme.d.ts +0 -10
  87. package/dist/types/src/components/TextEditor/extensions/basic/theme.d.ts.map +0 -1
  88. package/dist/types/src/components/TextEditor/extensions/change.d.ts +0 -7
  89. package/dist/types/src/components/TextEditor/extensions/change.d.ts.map +0 -1
  90. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.d.ts +0 -11
  91. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.d.ts.map +0 -1
  92. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.d.ts +0 -8
  93. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.d.ts.map +0 -1
  94. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkWidget.d.ts.map +0 -1
  95. package/dist/types/src/components/TextEditor/extensions/hyperlink/index.d.ts +0 -4
  96. package/dist/types/src/components/TextEditor/extensions/hyperlink/index.d.ts.map +0 -1
  97. package/dist/types/src/components/TextEditor/extensions/markdown/tags.d.ts +0 -17
  98. package/dist/types/src/components/TextEditor/extensions/markdown/tags.d.ts.map +0 -1
  99. package/dist/types/src/components/TextEditor/extensions/markdown/theme.d.ts +0 -21
  100. package/dist/types/src/components/TextEditor/extensions/markdown/theme.d.ts.map +0 -1
  101. package/dist/types/src/hooks/useCollaboration.d.ts +0 -9
  102. package/dist/types/src/hooks/useCollaboration.d.ts.map +0 -1
  103. package/src/components/TextEditor/extensions/basic/index.ts +0 -6
  104. package/src/components/TextEditor/extensions/basic/theme.ts +0 -49
  105. package/src/components/TextEditor/extensions/hyperlink/index.ts +0 -7
  106. package/src/components/TextEditor/extensions/markdown/tags.ts +0 -38
  107. package/src/components/TextEditor/extensions/markdown/theme.ts +0 -265
  108. package/src/hooks/useCollaboration.ts +0 -45
  109. /package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/PatchSemaphore.d.ts +0 -0
  110. /package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/amToCodemirror.d.ts +0 -0
  111. /package/dist/types/src/{automerge → hooks/automerge}/automerge.stories.d.ts +0 -0
  112. /package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/codeMirrorToAm.d.ts +0 -0
  113. /package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/handle.d.ts +0 -0
  114. /package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/index.d.ts +0 -0
  115. /package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/plugin.d.ts +0 -0
  116. /package/src/{automerge/automerge-plugin → hooks/automerge}/PatchSemaphore.ts +0 -0
  117. /package/src/{automerge/automerge-plugin → hooks/automerge}/amToCodemirror.ts +0 -0
  118. /package/src/{automerge/automerge-plugin → hooks/automerge}/codeMirrorToAm.ts +0 -0
  119. /package/src/{automerge/automerge-plugin → hooks/automerge}/handle.ts +0 -0
  120. /package/src/{automerge/automerge-plugin → hooks/automerge}/index.ts +0 -0
  121. /package/src/{automerge/automerge-plugin → hooks/automerge}/plugin.ts +0 -0
@@ -1,149 +1,128 @@
1
1
  // packages/ui/react-ui-editor/src/index.ts
2
2
  import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
3
- import { Doc, YText as YText2, YXmlFragment } from "@dxos/text-model";
3
+ import { Doc, YText, YXmlFragment } from "@dxos/text-model";
4
4
 
5
5
  // packages/ui/react-ui-editor/src/components/TextEditor/index.ts
6
6
  import { tags as tags2 } from "@lezer/highlight";
7
7
 
8
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic/bundle.ts
8
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/autocomplete.ts
9
+ import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
10
+ import { keymap } from "@codemirror/view";
11
+ var autocomplete = ({ getOptions }) => {
12
+ return [
13
+ // https://codemirror.net/docs/ref/#view.keymap
14
+ // https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
15
+ keymap.of(completionKeymap),
16
+ // https://codemirror.net/examples/autocompletion
17
+ // https://codemirror.net/docs/ref/#autocomplete.autocompletion
18
+ autocompletion({
19
+ // TODO(burdon): Set custom keymap.
20
+ // defaultKeymap: false,
21
+ // Don't start unless key press.
22
+ activateOnTyping: false,
23
+ // TODO(burdon): Option to create new page?
24
+ // TODO(burdon): Optional decoration via addToOptions
25
+ override: [
26
+ (context) => {
27
+ const word = context.matchBefore(/\w*/);
28
+ if (!word || word.from === word.to && !context.explicit) {
29
+ return null;
30
+ }
31
+ return {
32
+ from: word.from,
33
+ options: getOptions(word.text.toLowerCase())
34
+ };
35
+ }
36
+ ]
37
+ })
38
+ ];
39
+ };
40
+
41
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic.ts
9
42
  import { closeBrackets } from "@codemirror/autocomplete";
10
43
  import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
11
44
  import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
12
45
  import { EditorView, placeholder } from "@codemirror/view";
13
46
  var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
47
+ // TODO(burdon): Compare with minimalSetup.
48
+ // https://codemirror.net/docs/ref/#codemirror.minimalSetup
14
49
  bracketMatching(),
15
50
  closeBrackets(),
16
- _placeholder && placeholder(_placeholder),
17
51
  EditorView.lineWrapping,
52
+ _placeholder && placeholder(_placeholder),
18
53
  // TODO(burdon): Is this required?
19
54
  themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
20
55
  ].filter(Boolean);
21
56
 
22
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic/theme.ts
23
- import get from "lodash.get";
24
-
25
- // packages/ui/react-ui-editor/src/styles/markdown.ts
26
- import { mx } from "@dxos/react-ui-theme";
27
- var heading = {
28
- 1: "mbs-4 mbe-2 text-4xl font-semibold text-inherit no-underline",
29
- 2: "mbs-4 mbe-2 text-3xl font-bold text-inherit no-underline",
30
- 3: "mbs-4 mbe-2 text-2xl font-bold text-inherit no-underline",
31
- 4: "mbs-4 mbe-2 text-xl font-extrabold text-inherit no-underline",
32
- 5: "mbs-4 mbe-2 text-lg font-extrabold text-inherit no-underline",
33
- 6: "mbs-4 mbe-2 font-black text-inherit no-underline"
34
- };
35
- var bold = "font-bold";
36
- var code = "font-mono bg-neutral-500/10 rounded pli-0.5 plb-0.5 -mlb-0.5";
37
- var codeWithoutMarks = mx(code, "pli-1.5 mli-0.5");
38
- var italic = "italic";
39
- var strikethrough = "line-through";
40
- var mark = "!font-normal !no-underline !text-inherit opacity-40";
41
-
42
- // packages/ui/react-ui-editor/src/styles/tokens.ts
43
- import { tailwindConfig } from "@dxos/react-ui-theme";
44
- var tokens = tailwindConfig({}).theme;
45
-
46
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic/theme.ts
47
- var basicTheme = {
48
- "&.cm-focused": {
49
- outline: "none"
50
- },
51
- "& .cm-line": {
52
- paddingInline: 0,
53
- lineHeight: 1.6,
54
- minBlockSize: "1.6em"
55
- },
56
- "& .cm-line *": {
57
- lineHeight: 1.6
58
- },
59
- "& .cm-scroller": {
60
- fontFamily: get(tokens, "fontFamily.body", []).join(","),
61
- overflow: "visible"
62
- },
63
- "& .cm-content": {
64
- padding: 0,
65
- caretColor: "black"
66
- },
67
- ".dark & .cm-content": {
68
- caretColor: "white"
69
- },
70
- "& .cm-tooltip": {
71
- backgroundColor: "transparent",
72
- border: "none"
73
- },
74
- "& .cm-link": {
75
- color: get(tokens, "extend.colors.primary.500"),
76
- textDecoration: "underline"
77
- }
78
- };
79
-
80
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/change.ts
81
- import { StateField } from "@codemirror/state";
82
- var onChangeExtension = (onChange) => StateField.define({
83
- create: () => null,
84
- update: (_value, transaction) => {
85
- if (transaction.docChanged && onChange) {
86
- onChange(transaction.newDoc.toString());
87
- }
88
- return null;
89
- }
90
- });
91
-
92
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.ts
57
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
93
58
  import { syntaxTree } from "@codemirror/language";
94
- import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
59
+ import { RangeSetBuilder, StateField } from "@codemirror/state";
95
60
  import { Decoration, EditorView as EditorView2, WidgetType } from "@codemirror/view";
96
- var Link = class extends WidgetType {
97
- constructor(_anchor, _text, _url) {
61
+ var LinkButton = class extends WidgetType {
62
+ constructor(_pos, _url, _onAttach) {
63
+ super();
64
+ this._pos = _pos;
65
+ this._url = _url;
66
+ this._onAttach = _onAttach;
67
+ }
68
+ eq(other) {
69
+ return this._pos === other._pos && this._url === other._url;
70
+ }
71
+ toDOM(view) {
72
+ const el = document.createElement("span");
73
+ this._onAttach(el, this._url);
74
+ return el;
75
+ }
76
+ };
77
+ var LinkText = class extends WidgetType {
78
+ constructor(_pos, _text, _url) {
98
79
  super();
99
- this._anchor = _anchor;
80
+ this._pos = _pos;
100
81
  this._text = _text;
101
82
  this._url = _url;
102
83
  }
103
84
  eq(other) {
104
- return this._text === other.text && this._url === other.url;
85
+ return this._pos === other._pos && this._url === other._url;
105
86
  }
106
87
  toDOM(view) {
107
- const link = document.createElement("a");
108
- link.setAttribute("class", "cm-link");
109
- link.textContent = this._text;
88
+ const link2 = document.createElement("a");
89
+ link2.setAttribute("class", "cm-link");
90
+ link2.textContent = this._text;
110
91
  if (this._url) {
111
- link.setAttribute("target", "_blank");
112
- link.href = this._url;
92
+ link2.setAttribute("rel", "noreferrer");
93
+ link2.setAttribute("target", "_blank");
94
+ link2.href = this._url;
113
95
  } else {
114
- link.onclick = () => {
96
+ link2.onclick = () => {
115
97
  view.dispatch({
116
98
  selection: {
117
- anchor: this._anchor
99
+ anchor: this._pos
118
100
  }
119
101
  });
120
102
  };
121
103
  }
122
- return link;
104
+ return link2;
123
105
  }
124
106
  };
125
- var hyperlinkDecoration = ({ link } = {}) => {
126
- return StateField2.define({
127
- create: (state) => update(state, link),
128
- update: (_, tr) => update(tr.state, link),
129
- provide: (field) => EditorView2.decorations.from(field)
130
- });
131
- };
132
- var update = (state, link) => {
107
+ var update = (state, options) => {
133
108
  const builder = new RangeSetBuilder();
134
109
  const cursor = state.selection.main.head;
135
110
  syntaxTree(state).iterate({
136
111
  enter: (node) => {
137
- if (cursor < node.from || cursor > node.to) {
138
- if (node.name === "Link") {
139
- const marks = node.node.getChildren("LinkMark");
140
- const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
141
- const urlNode = node.node.getChild("URL");
142
- const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
112
+ if (node.name === "Link") {
113
+ const marks = node.node.getChildren("LinkMark");
114
+ const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
115
+ const urlNode = node.node.getChild("URL");
116
+ const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
117
+ if (cursor < node.from || cursor > node.to) {
143
118
  builder.add(node.from, node.to, Decoration.replace({
144
- widget: new Link(node.from, text, link ? url : void 0)
119
+ widget: new LinkText(node.from, text, options.link ? url : void 0)
120
+ }));
121
+ }
122
+ if (options.onRender) {
123
+ builder.add(node.to, node.to, Decoration.replace({
124
+ widget: new LinkButton(node.from, url, options.onRender)
145
125
  }));
146
- return false;
147
126
  }
148
127
  }
149
128
  return true;
@@ -151,142 +130,25 @@ var update = (state, link) => {
151
130
  });
152
131
  return builder.finish();
153
132
  };
133
+ var link = (options = {}) => {
134
+ return StateField.define({
135
+ create: (state) => update(state, options),
136
+ update: (_, tr) => update(tr.state, options),
137
+ provide: (field) => EditorView2.decorations.from(field)
138
+ });
139
+ };
154
140
 
155
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.tsx
156
- import { hoverTooltip } from "@codemirror/view";
157
- import { tooltipContent } from "@dxos/react-ui-theme";
158
- var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
159
- var createHyperlinkTooltip = (onHover, regexp = markdownLinkRegexp) => hoverTooltip((view, pos) => {
160
- const { from, text } = view.state.doc.lineAt(pos);
161
- const p = pos - from;
162
- let idx = 0;
163
- let match;
164
- do {
165
- match = text.substring(idx).match(regexp);
166
- if (!match) {
167
- match = void 0;
168
- break;
169
- }
170
- idx = text.indexOf(match[0]);
171
- if (p >= idx && p < idx + match[0].length) {
172
- break;
141
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
142
+ import { StateField as StateField2 } from "@codemirror/state";
143
+ var listener = (onChange) => StateField2.define({
144
+ create: () => null,
145
+ update: (_value, transaction) => {
146
+ if (transaction.docChanged && onChange) {
147
+ onChange(transaction.newDoc.toString());
173
148
  }
174
- idx += match[0].length;
175
- } while (true);
176
- if (!match) {
177
149
  return null;
178
150
  }
179
- const [, , url] = match ?? [];
180
- return {
181
- pos: idx + from,
182
- end: idx + from + match[0].length,
183
- above: true,
184
- create: () => {
185
- const el = document.createElement("a");
186
- el.innerText = "_";
187
- el.className = tooltipContent({}, "mb-2 p-1");
188
- el.setAttribute("target", "_blank");
189
- el.setAttribute("href", url);
190
- onHover(el, url);
191
- return {
192
- dom: el
193
- };
194
- }
195
- };
196
- });
197
-
198
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkWidget.tsx
199
- import { Decoration as Decoration2, EditorView as EditorView3, MatchDecorator, ViewPlugin } from "@codemirror/view";
200
- var markdownLinkRegexp2 = /\[([^\]]+)]\(([^)]+)\)(!?)/gi;
201
- var linkDecorator = () => new MatchDecorator({
202
- regexp: markdownLinkRegexp2,
203
- decorate: (add, from, to, match, view) => {
204
- const [_, label, url] = match;
205
- const p0 = {
206
- start: from,
207
- end: from + 1
208
- };
209
- const p1 = {
210
- start: from + 1,
211
- end: from + 1 + label.length
212
- };
213
- const p2 = {
214
- start: p1.end,
215
- end: p1.end + 1
216
- };
217
- const p3 = {
218
- start: p1.end + 1,
219
- end: p1.end + 1 + url.length + 2
220
- };
221
- add(p0.start, p0.end, Decoration2.mark({
222
- class: "cm-hyperlink-bracket",
223
- _attributes: {
224
- style: "display: none"
225
- }
226
- }));
227
- add(p1.start, p1.end, Decoration2.mark({
228
- class: "cm-hyperlink-label"
229
- }));
230
- add(p2.start, p2.end, Decoration2.mark({
231
- class: "cm-hyperlink-bracket",
232
- _attributes: {
233
- style: "display: none"
234
- }
235
- }));
236
- add(p3.start, p3.end, Decoration2.mark({
237
- class: "cm-hyperlink-url",
238
- _attributes: {
239
- style: "display: none"
240
- }
241
- }));
242
- }
243
151
  });
244
- function hyperLinkExtension() {
245
- return ViewPlugin.fromClass(class HyperLinkView {
246
- constructor(view) {
247
- this.decorator = linkDecorator();
248
- this.decorations = this.decorator.createDeco(view);
249
- }
250
- update(update2) {
251
- if (update2.docChanged || update2.viewportChanged) {
252
- this.decorations = this.decorator.updateDeco(update2, this.decorations);
253
- }
254
- }
255
- }, {
256
- decorations: (view) => view.decorations,
257
- eventHandlers: {
258
- // TODO(burdon): CLick to expand link.
259
- // https://discuss.codemirror.net/t/decorator-iteration-on-click-event/4226/2
260
- mousedown: function(event, view) {
261
- const pos = view.posAtDOM(event.target);
262
- if (pos !== 0) {
263
- console.log(this);
264
- }
265
- },
266
- // TODO(burdon): Hide when cursor moves away.
267
- keydown: (event, view) => {
268
- view.update([]);
269
- }
270
- }
271
- });
272
- }
273
- var hyperlinkStyle = EditorView3.baseTheme({
274
- ".cm-hyperlink-label": {
275
- cursor: "pointer",
276
- textDecoration: "underline"
277
- },
278
- ".cm-hyperlink-bracket": {
279
- opacity: 0.2
280
- },
281
- ".cm-hyperlink-url": {
282
- opacity: 0.5,
283
- fontFamily: "monospace"
284
- }
285
- });
286
- var hyperlinkWidget = [
287
- hyperLinkExtension(),
288
- hyperlinkStyle
289
- ];
290
152
 
291
153
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
292
154
  import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
@@ -298,222 +160,59 @@ import { lintKeymap } from "@codemirror/lint";
298
160
  import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
299
161
  import { EditorState } from "@codemirror/state";
300
162
  import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
301
- import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView4, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
163
+ import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView3, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap2, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
164
+
165
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
166
+ import { markdownLanguage } from "@codemirror/lang-markdown";
167
+ import { HighlightStyle } from "@codemirror/language";
168
+ import { tags, styleTags, Tag } from "@lezer/highlight";
169
+ import get from "lodash.get";
170
+
171
+ // packages/ui/react-ui-editor/src/styles/markdown.ts
172
+ import { mx } from "@dxos/react-ui-theme";
173
+ var heading = {
174
+ 1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
175
+ 2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
176
+ 3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
177
+ 4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
178
+ 5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
179
+ 6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
180
+ };
181
+ var light = "text-neutral-200 dark:text-neutral-800";
182
+ var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
183
+ var bold = "font-bold";
184
+ var italic = "italic";
185
+ var strikethrough = "line-through";
186
+ var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
187
+ var codeMark = "font-mono text-primary-500";
188
+ var inlineUrl = mx(code, "px-1");
189
+ var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
190
+ var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-500/50";
191
+
192
+ // packages/ui/react-ui-editor/src/styles/tokens.ts
193
+ import { tailwindConfig } from "@dxos/react-ui-theme";
194
+ var tokens = tailwindConfig({}).theme;
302
195
 
303
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/tags.ts
304
- import { styleTags, Tag } from "@lezer/highlight";
196
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
305
197
  var markdownTags = {
306
- headingMark: Tag.define(),
307
- quoteMark: Tag.define(),
308
- listMark: Tag.define(),
309
- linkMark: Tag.define(),
310
- emphasisMark: Tag.define(),
311
- codeMark: Tag.define(),
312
- codeText: Tag.define(),
313
- inlineCode: Tag.define(),
314
- url: Tag.define(),
315
- linkReference: Tag.define(),
316
- linkLabel: Tag.define()
198
+ Blockquote: Tag.define(),
199
+ CodeMark: Tag.define(),
200
+ CodeText: Tag.define(),
201
+ EmphasisMark: Tag.define(),
202
+ HeaderMark: Tag.define(),
203
+ HorizontalRule: Tag.define(),
204
+ InlineCode: Tag.define(),
205
+ LinkLabel: Tag.define(),
206
+ LinkReference: Tag.define(),
207
+ ListMark: Tag.define(),
208
+ QuoteMark: Tag.define(),
209
+ URL: Tag.define()
317
210
  };
318
211
  var markdownTagsExtension = {
319
212
  props: [
320
- styleTags({
321
- HeaderMark: markdownTags.headingMark,
322
- QuoteMark: markdownTags.quoteMark,
323
- ListMark: markdownTags.listMark,
324
- LinkMark: markdownTags.linkMark,
325
- EmphasisMark: markdownTags.emphasisMark,
326
- CodeMark: markdownTags.codeMark,
327
- CodeText: markdownTags.codeText,
328
- InlineCode: markdownTags.inlineCode,
329
- URL: markdownTags.url,
330
- LinkReference: markdownTags.linkReference,
331
- LinkLabel: markdownTags.linkLabel
332
- })
213
+ styleTags(markdownTags)
333
214
  ]
334
215
  };
335
-
336
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/theme.ts
337
- import { markdownLanguage } from "@codemirror/lang-markdown";
338
- import { HighlightStyle } from "@codemirror/language";
339
- import { tags } from "@lezer/highlight";
340
- import get2 from "lodash.get";
341
- var chalky = "#e5c07b";
342
- var coral = "#e06c75";
343
- var cyan = "#56b6c2";
344
- var invalid = "#ffffff";
345
- var ivory = "#abb2bf";
346
- var stone = "#7d8799";
347
- var malibu = "#61afef";
348
- var sage = "#98c379";
349
- var whiskey = "#d19a66";
350
- var violet = "#c678dd";
351
- var highlightBackground = "#2c313a";
352
- var tooltipBackground = "#353a42";
353
- var monospace = get2(tokens, "fontFamily.mono", [
354
- "monospace"
355
- ]).join(",");
356
- var markdownTheme = {
357
- // TODO(thure): Consider whether these commented-out rules from one-dark-theme should be integrated.
358
- // '&': {
359
- // color: ivory,
360
- // backgroundColor: background
361
- // },
362
- // '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor },
363
- // '&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {
364
- // backgroundColor: selection
365
- // },
366
- // '.cm-panels': { backgroundColor: darkBackground, color: ivory },
367
- // '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' },
368
- // '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' },
369
- // '.cm-searchMatch': {
370
- // backgroundColor: '#72a1ff59',
371
- // outline: '1px solid #457dff'
372
- // },
373
- // '.cm-searchMatch.cm-searchMatch-selected': {
374
- // backgroundColor: '#6199ff2f'
375
- // },
376
- // '.cm-activeLine': { backgroundColor: '#6699ff0b' },
377
- // '.cm-selectionMatch': { backgroundColor: '#aafe661a' },
378
- // '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
379
- // backgroundColor: '#bad0f847'
380
- // },
381
- // '.cm-gutters': {
382
- // backgroundColor: background,
383
- // color: stone,
384
- // border: 'none'
385
- // },
386
- // '.cm-activeLineGutter': {
387
- // backgroundColor: highlightBackground
388
- // },
389
- // '.cm-foldPlaceholder': {
390
- // backgroundColor: 'transparent',
391
- // border: 'none',
392
- // color: '#ddd'
393
- // },
394
- "& .cm-tooltip": {
395
- backgroundColor: "transparent",
396
- border: "none"
397
- },
398
- // '.dark & .cm-tooltip': {
399
- // border: 'none',
400
- // backgroundColor: tooltipBackground,
401
- // },
402
- // '.dark & .cm-tooltip .cm-tooltip-arrow:before': {
403
- // borderTopColor: 'transparent',
404
- // borderBottomColor: 'transparent',
405
- // },
406
- // '.dark & .cm-tooltip .cm-tooltip-arrow:after': {
407
- // borderTopColor: tooltipBackground,
408
- // borderBottomColor: tooltipBackground,
409
- // },
410
- // '.dark & .cm-tooltip-autocomplete': {
411
- // '& > ul > li[aria-selected]': {
412
- // backgroundColor: highlightBackground,
413
- // color: ivory,
414
- // },
415
- // },
416
- "&.cm-focused": {
417
- outline: "none"
418
- },
419
- "& .cm-line": {
420
- paddingInline: 0,
421
- lineHeight: 1.6,
422
- minBlockSize: "1.6em"
423
- },
424
- "& .cm-line *": {
425
- lineHeight: 1.6
426
- },
427
- "&.cm-focused .cm-selectionBackground, & .cm-selectionBackground": {
428
- background: get2(tokens, "extend.colors.primary.150", "#00ffff")
429
- },
430
- ".dark & .cm-selectionBackground, .dark &.cm-focused .cm-selectionBackground": {
431
- background: get2(tokens, "extend.colors.primary.850", "#00ffff")
432
- },
433
- "& .cm-selectionMatch": {
434
- background: get2(tokens, "extend.colors.primary.250", "#00ffff") + "44"
435
- },
436
- ".dark & .cm-selectionMatch": {
437
- background: get2(tokens, "extend.colors.primary.600", "#00ffff") + "44"
438
- },
439
- "& .cm-content": {
440
- padding: 0,
441
- caretColor: "black"
442
- },
443
- ".dark & .cm-content": {
444
- caretColor: "white"
445
- },
446
- "& .cm-cursor": {
447
- borderLeftColor: "black"
448
- },
449
- ".dark & .cm-cursor": {
450
- borderLeftColor: "white"
451
- },
452
- ".cm-placeholder": {
453
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
454
- },
455
- "& .cm-scroller": {
456
- fontFamily: get2(tokens, "fontFamily.mono", []).join(","),
457
- overflow: "visible"
458
- },
459
- "& .cm-activeLine": {
460
- backgroundColor: "transparent"
461
- },
462
- ".dark & .cm-activeLine": {
463
- backgroundColor: "transparent"
464
- },
465
- "& .cm-ySelectionInfo": {
466
- fontFamily: get2(tokens, "fontFamily.body", []).join(","),
467
- padding: "2px 4px",
468
- marginBlockStart: "-4px"
469
- },
470
- "& .cm-ySelection, & .cm-selectionMatch": {
471
- paddingBlockStart: ".15em",
472
- paddingBlockEnd: ".15em"
473
- },
474
- "& .cm-ySelection, & .cm-yLineSelection": {
475
- mixBlendMode: "multiply"
476
- },
477
- ".dark & .cm-ySelection, .dark & .cm-yLineSelection": {
478
- mixBlendMode: "screen"
479
- },
480
- "& .cm-ySelectionCaret": {
481
- display: "inline-block",
482
- insetBlockStart: ".1em",
483
- blockSize: "1.4em",
484
- verticalAlign: "top"
485
- },
486
- "& .cm-yLineSelection": {
487
- margin: "0"
488
- },
489
- ".cm-link": {
490
- color: "rgb(20 89 208)",
491
- textDecorationLine: "underline",
492
- textDecorationThickness: "1px",
493
- textUnderlineOffset: "2px",
494
- borderRadius: ".125rem"
495
- },
496
- // TODO(burdon): Document.
497
- ...Object.keys(get2(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
498
- const height = get2(tokens, [
499
- "extend",
500
- "fontSize",
501
- fontSize,
502
- 1,
503
- "lineHeight"
504
- ]);
505
- acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
506
- height
507
- };
508
- acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
509
- height
510
- };
511
- acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
512
- height
513
- };
514
- return acc;
515
- }, {})
516
- };
517
216
  var markdownHighlightStyle = HighlightStyle.define([
518
217
  {
519
218
  tag: [
@@ -553,48 +252,22 @@ var markdownHighlightStyle = HighlightStyle.define([
553
252
  ],
554
253
  color: "inherit !important"
555
254
  },
255
+ // Markdown marks.
556
256
  {
557
257
  tag: [
558
- tags.link,
559
- tags.url
560
- ],
561
- color: "inherit !important",
562
- textDecoration: "none !important"
563
- },
564
- {
565
- tag: [
566
- tags.function(tags.variableName),
567
- tags.labelName
568
- ],
569
- color: malibu,
570
- fontFamily: monospace
571
- },
572
- {
573
- tag: [
574
- markdownTags.codeMark,
575
- markdownTags.emphasisMark,
576
- markdownTags.headingMark,
577
- markdownTags.linkLabel,
578
- markdownTags.linkReference,
579
- markdownTags.listMark,
580
- markdownTags.quoteMark,
581
- markdownTags.url,
582
258
  tags.meta,
583
- tags.processingInstruction
259
+ tags.processingInstruction,
260
+ markdownTags.CodeMark,
261
+ markdownTags.EmphasisMark,
262
+ markdownTags.HeaderMark,
263
+ markdownTags.LinkLabel,
264
+ markdownTags.LinkReference,
265
+ markdownTags.ListMark,
266
+ markdownTags.QuoteMark
584
267
  ],
585
268
  class: mark
586
269
  },
587
- {
588
- tag: [
589
- markdownTags.codeText,
590
- markdownTags.inlineCode
591
- ],
592
- class: "font-mono"
593
- },
594
- {
595
- tag: tags.emphasis,
596
- class: italic
597
- },
270
+ // Headings.
598
271
  {
599
272
  tag: tags.heading1,
600
273
  class: heading[1]
@@ -619,18 +292,61 @@ var markdownHighlightStyle = HighlightStyle.define([
619
292
  tag: tags.heading6,
620
293
  class: heading[6]
621
294
  },
295
+ // Emphasis.
622
296
  {
623
- tag: tags.strikethrough,
624
- class: strikethrough
297
+ tag: tags.emphasis,
298
+ class: italic
625
299
  },
626
300
  {
627
301
  tag: tags.strong,
628
302
  class: bold
303
+ },
304
+ {
305
+ tag: tags.strikethrough,
306
+ class: strikethrough
307
+ },
308
+ // Naked URLs.
309
+ {
310
+ tag: [
311
+ markdownTags.URL
312
+ ],
313
+ class: inlineUrl
314
+ },
315
+ // E.g., code block language (after ```).
316
+ {
317
+ tag: [
318
+ tags.function(tags.variableName),
319
+ tags.labelName
320
+ ],
321
+ class: codeMark
322
+ },
323
+ // The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
324
+ // However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
325
+ // when a language is specified. In this case, the syntax highlighting extensions will colorize
326
+ // the code, but all other CSS properties will be inherited.
327
+ {
328
+ tag: [
329
+ markdownTags.CodeText,
330
+ markdownTags.InlineCode
331
+ ],
332
+ class: code
333
+ },
334
+ {
335
+ tag: [
336
+ markdownTags.QuoteMark
337
+ ],
338
+ class: blockquote
339
+ },
340
+ {
341
+ tag: [
342
+ markdownTags.HorizontalRule
343
+ ],
344
+ class: horizontalRule
629
345
  }
630
346
  ], {
631
347
  scope: markdownLanguage,
632
348
  all: {
633
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
349
+ fontFamily: get(tokens, "fontFamily.body", []).join(",")
634
350
  }
635
351
  });
636
352
 
@@ -641,7 +357,7 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
641
357
  closeBrackets2(),
642
358
  _placeholder && placeholder2(_placeholder),
643
359
  EditorState.allowMultipleSelections.of(true),
644
- EditorView4.lineWrapping,
360
+ EditorView3.lineWrapping,
645
361
  // autocompletion(),
646
362
  crosshairCursor(),
647
363
  dropCursor(),
@@ -653,7 +369,7 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
653
369
  history(),
654
370
  indentOnInput(),
655
371
  rectangularSelection(),
656
- keymap.of([
372
+ keymap2.of([
657
373
  ...closeBracketsKeymap,
658
374
  // ...completionKeymap,
659
375
  ...defaultKeymap,
@@ -665,53 +381,484 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
665
381
  ]),
666
382
  // Main extension.
667
383
  // https://github.com/codemirror/lang-markdown
384
+ // https://codemirror.net/5/mode/markdown/index.html (demo).
668
385
  markdown({
386
+ // GRM by default (vs strict CommonMark):
387
+ // Table, TaskList, Strikethrough, and Autolink.
388
+ // NOTE: This extends the parser; it doesn't affect rendering.
389
+ // https://github.github.com/gfm
390
+ // https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
669
391
  base: markdownLanguage2,
392
+ // Languages for syntax highlighting fenced code blocks.
670
393
  codeLanguages: languages,
394
+ // Parser extensions.
671
395
  extensions: [
672
- // TODO(burdon): This seems to upgrade the parser.
673
- // GitHub flavored markdown bundle: Table, TaskList, Strikethrough, and Autolink.
674
- // https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
675
- // https://github.github.com/gfm
676
- // GFM,
677
- // Custom styling.
396
+ // GFM, // TODO(burdon): Provided by default?
678
397
  markdownTagsExtension
679
398
  ]
680
399
  }),
681
- // TODO(thure): All but one rule here apply to both themes; rename or refactor.
400
+ // Custom styles.
682
401
  syntaxHighlighting2(markdownHighlightStyle),
402
+ // TODO(thure): All but one rule here apply to both themes; rename or refactor.
683
403
  themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
684
404
  ].filter(Boolean);
685
405
  };
686
406
 
407
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
408
+ import { syntaxTree as syntaxTree2 } from "@codemirror/language";
409
+ import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
410
+ import { EditorView as EditorView4, Decoration as Decoration2, WidgetType as WidgetType2 } from "@codemirror/view";
411
+ var CheckboxWidget = class extends WidgetType2 {
412
+ constructor(_pos, _getCursor, _checked) {
413
+ super();
414
+ this._pos = _pos;
415
+ this._getCursor = _getCursor;
416
+ this._checked = _checked;
417
+ }
418
+ eq(other) {
419
+ return this._pos === other._pos && this._checked === other._checked;
420
+ }
421
+ toDOM(view) {
422
+ const wrap = document.createElement("span");
423
+ wrap.setAttribute("aria-hidden", "true");
424
+ wrap.className = "cm-task-item";
425
+ const box = wrap.appendChild(document.createElement("input"));
426
+ box.type = "checkbox";
427
+ box.checked = this._checked;
428
+ box.onclick = (event) => {
429
+ this._checked = !isChecked(view.state, this._pos);
430
+ view.dispatch({
431
+ changes: {
432
+ from: this._pos + 1,
433
+ to: this._pos + 2,
434
+ insert: this._checked ? "x" : " "
435
+ },
436
+ // TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
437
+ selection: {
438
+ anchor: this._pos + 4
439
+ }
440
+ });
441
+ return true;
442
+ };
443
+ return wrap;
444
+ }
445
+ // TODO(burdon): Remove listener?
446
+ // override destroy() {
447
+ // console.log('destroy', this._pos);
448
+ // }
449
+ ignoreEvent() {
450
+ return false;
451
+ }
452
+ };
453
+ var isChecked = (state, pos) => {
454
+ return state.sliceDoc(pos, pos + 3).toLowerCase() === "[x]";
455
+ };
456
+ var statefield = () => {
457
+ let lastPosition = 0;
458
+ const listener2 = EditorView4.updateListener.of((update2) => {
459
+ lastPosition = update2.startState.selection.main.head;
460
+ });
461
+ const checkbox = (state) => {
462
+ const builder = new RangeSetBuilder2();
463
+ syntaxTree2(state).iterate({
464
+ enter: (node) => {
465
+ if (node.name === "TaskMarker") {
466
+ builder.add(node.from, node.to, Decoration2.replace({
467
+ widget: new CheckboxWidget(node.from, () => lastPosition, isChecked(state, node.from))
468
+ }));
469
+ }
470
+ }
471
+ });
472
+ return builder.finish();
473
+ };
474
+ return [
475
+ listener2,
476
+ StateField3.define({
477
+ create: (state) => checkbox(state),
478
+ update: (_, tr) => checkbox(tr.state),
479
+ provide: (field) => EditorView4.decorations.from(field)
480
+ })
481
+ ];
482
+ };
483
+ var styles = EditorView4.baseTheme({
484
+ "& .cm-task-item": {
485
+ padding: "0 4px"
486
+ }
487
+ });
488
+ var tasklist = () => [
489
+ statefield(),
490
+ styles
491
+ ];
492
+
493
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tooltip.tsx
494
+ import { hoverTooltip } from "@codemirror/view";
495
+ import { tooltipContent } from "@dxos/react-ui-theme";
496
+ var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
497
+ var tooltip = ({ onHover, regexp = markdownLinkRegexp }) => hoverTooltip((view, pos) => {
498
+ const { from, text } = view.state.doc.lineAt(pos);
499
+ const p = pos - from;
500
+ let idx = 0;
501
+ let match;
502
+ do {
503
+ match = text.substring(idx).match(regexp);
504
+ if (!match) {
505
+ match = void 0;
506
+ break;
507
+ }
508
+ idx = text.indexOf(match[0]);
509
+ if (p >= idx && p < idx + match[0].length) {
510
+ break;
511
+ }
512
+ idx += match[0].length;
513
+ } while (true);
514
+ if (!match) {
515
+ return null;
516
+ }
517
+ const [, , url] = match ?? [];
518
+ return {
519
+ pos: idx + from,
520
+ end: idx + from + match[0].length,
521
+ above: true,
522
+ create: () => {
523
+ const el = document.createElement("div");
524
+ el.className = tooltipContent({}, "pli-2 plb-1");
525
+ onHover(el, url);
526
+ return {
527
+ dom: el,
528
+ offset: {
529
+ x: 0,
530
+ y: 12
531
+ }
532
+ };
533
+ }
534
+ };
535
+ });
536
+
537
+ // packages/ui/react-ui-editor/src/components/TextEditor/themes/default.ts
538
+ import get2 from "lodash.get";
539
+ var defaultTheme = {
540
+ //
541
+ // Main layout:
542
+ // <div class=".cm-editor .cm-focused">
543
+ // <div class=".cm-scroller">
544
+ // <div class=".cm-content" role="textbox" contenteditable="true">
545
+ // <div class=".cm-line" />
546
+ // </div>
547
+ // </div>
548
+ // </div>
549
+ //
550
+ "&": {},
551
+ "&.cm-focused": {
552
+ outline: "none"
553
+ },
554
+ "& .cm-scroller": {
555
+ overflow: "visible"
556
+ },
557
+ "& .cm-content": {
558
+ padding: 0,
559
+ // Base font size (otherwise defined by HTML tag, which might be different for storybook).
560
+ fontSize: "16px"
561
+ },
562
+ "&light .cm-content": {
563
+ color: get2(tokens, "extend.colors.neutral.900", "black"),
564
+ caretColor: "black"
565
+ },
566
+ "&dark .cm-content": {
567
+ color: get2(tokens, "extend.colors.neutral.100", "white"),
568
+ caretColor: "white"
569
+ },
570
+ //
571
+ // Cursor
572
+ //
573
+ "&light .cm-cursor": {
574
+ borderLeft: "2px solid black"
575
+ },
576
+ "&dark .cm-cursor": {
577
+ borderLeft: "2px solid white"
578
+ },
579
+ "& .cm-placeholder": {
580
+ fontWeight: 100
581
+ },
582
+ //
583
+ // line
584
+ //
585
+ "& .cm-line": {
586
+ paddingInline: 0
587
+ },
588
+ "& .cm-line *": {},
589
+ "& .cm-activeLine": {
590
+ backgroundColor: "transparent"
591
+ },
592
+ //
593
+ // selection
594
+ //
595
+ "&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground": {
596
+ background: get2(tokens, "extend.colors.primary.150", "#00ffff")
597
+ },
598
+ "&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground": {
599
+ background: get2(tokens, "extend.colors.primary.850", "#00ffff")
600
+ },
601
+ "&light .cm-selectionMatch": {
602
+ background: get2(tokens, "extend.colors.primary.250", "#00ffff") + "44"
603
+ },
604
+ "&dark .cm-selectionMatch": {
605
+ background: get2(tokens, "extend.colors.primary.600", "#00ffff") + "44"
606
+ },
607
+ //
608
+ // collaboration
609
+ // TODO(burdon): Review classnames (YJS dependent?)
610
+ //
611
+ "&light .cm-ySelection, &light .cm-yLineSelection": {
612
+ mixBlendMode: "multiply"
613
+ },
614
+ "&dark .cm-ySelection, &dark .cm-yLineSelection": {
615
+ mixBlendMode: "screen"
616
+ },
617
+ "& .cm-ySelectionInfo": {
618
+ padding: "2px 4px",
619
+ marginBlockStart: "-4px"
620
+ },
621
+ "& .cm-ySelection, & .cm-selectionMatch": {
622
+ paddingBlockStart: ".15em",
623
+ paddingBlockEnd: ".15em"
624
+ },
625
+ "& .cm-ySelectionCaret": {
626
+ display: "inline-block",
627
+ insetBlockStart: ".1em",
628
+ blockSize: "1.4em",
629
+ verticalAlign: "top"
630
+ },
631
+ "& .cm-yLineSelection": {
632
+ margin: 0
633
+ },
634
+ //
635
+ // link
636
+ //
637
+ "& .cm-link": {
638
+ color: get2(tokens, "extend.colors.primary.500"),
639
+ textDecorationLine: "underline",
640
+ textDecorationThickness: "1px",
641
+ textUnderlineOffset: "2px",
642
+ borderRadius: ".125rem",
643
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
644
+ },
645
+ //
646
+ // tooltip
647
+ //
648
+ "& .cm-tooltip": {
649
+ border: "none"
650
+ },
651
+ // '& .cm-tooltip-below': {},
652
+ // '& .cm-tooltip-autocomplete': {},
653
+ //
654
+ // font size
655
+ // TODO(thure): This appears to be the best or only way to set selection caret heights, but it's far more verbose than it needs to be.
656
+ //
657
+ ...Object.keys(get2(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
658
+ const height = get2(tokens, [
659
+ "extend",
660
+ "fontSize",
661
+ fontSize,
662
+ 1,
663
+ "lineHeight"
664
+ ]);
665
+ acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
666
+ height
667
+ };
668
+ acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
669
+ height
670
+ };
671
+ acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
672
+ height
673
+ };
674
+ return acc;
675
+ }, {})
676
+ };
677
+ var textTheme = {
678
+ "& .cm-scroller": {
679
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
680
+ }
681
+ };
682
+ var codeTheme = {
683
+ "& .cm-scroller": {
684
+ fontFamily: get2(tokens, "fontFamily.mono", []).join(",")
685
+ }
686
+ };
687
+
687
688
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
688
689
  import { EditorState as EditorState2 } from "@codemirror/state";
689
690
  import { EditorView as EditorView5 } from "@codemirror/view";
690
691
  import { useFocusableGroup } from "@fluentui/react-tabster";
691
692
  import { vim } from "@replit/codemirror-vim";
692
693
  import defaultsDeep from "lodash.defaultsdeep";
693
- import get3 from "lodash.get";
694
- import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
695
- import { isDocAccessor as isDocAccessor2 } from "@dxos/echo-schema";
694
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
695
+ import { generateName } from "@dxos/display-name";
696
696
  import { useThemeContext } from "@dxos/react-ui";
697
+ import { getColorForValue, inputSurface, mx as mx2 } from "@dxos/react-ui-theme";
698
+ var EditorModes = [
699
+ "default",
700
+ "vim"
701
+ ];
702
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots = defaultSlots, editorMode }, forwardedRef) => {
703
+ const { themeMode } = useThemeContext();
704
+ const tabsterDOMAttribute = useFocusableGroup({
705
+ tabBehavior: "limited"
706
+ });
707
+ const { awareness, peer } = model;
708
+ useEffect(() => {
709
+ if (awareness && peer) {
710
+ awareness.setLocalStateField("user", {
711
+ name: peer.name ?? generateName(peer.id),
712
+ color: getColorForValue({
713
+ value: peer.id,
714
+ type: "color"
715
+ }),
716
+ colorLight: getColorForValue({
717
+ value: peer.id,
718
+ themeMode,
719
+ type: "highlight"
720
+ })
721
+ });
722
+ }
723
+ }, [
724
+ awareness,
725
+ peer,
726
+ themeMode
727
+ ]);
728
+ const [root, setRoot] = useState(null);
729
+ const [state, setState] = useState();
730
+ const [view, setView] = useState();
731
+ useImperativeHandle(forwardedRef, () => ({
732
+ root,
733
+ state,
734
+ view
735
+ }), [
736
+ view,
737
+ state,
738
+ root
739
+ ]);
740
+ useEffect(() => {
741
+ if (!root) {
742
+ return;
743
+ }
744
+ const state2 = EditorState2.create({
745
+ doc: model.text(),
746
+ extensions: [
747
+ // TODO(burdon): Factor out VIM mode?
748
+ editorMode === "vim" && vim(),
749
+ // Theme.
750
+ EditorView5.baseTheme(defaultTheme),
751
+ EditorView5.theme(slots?.editor?.theme ?? {}),
752
+ // TODO(burdon): themeMode doesn't change in storybooks.
753
+ EditorView5.darkTheme.of(themeMode === "dark"),
754
+ // Storage and replication.
755
+ model.extension,
756
+ // Custom.
757
+ ...extensions
758
+ ].filter(Boolean)
759
+ });
760
+ view?.destroy();
761
+ setView(new EditorView5({
762
+ state: state2,
763
+ parent: root
764
+ }));
765
+ setState(state2);
766
+ return () => {
767
+ view?.destroy();
768
+ setView(void 0);
769
+ setState(void 0);
770
+ };
771
+ }, [
772
+ root,
773
+ model,
774
+ themeMode,
775
+ editorMode
776
+ ]);
777
+ const handleKeyUp = useCallback((event) => {
778
+ const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
779
+ switch (key) {
780
+ case "Enter": {
781
+ view?.contentDOM.focus();
782
+ break;
783
+ }
784
+ case "Escape": {
785
+ editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && root?.focus();
786
+ break;
787
+ }
788
+ }
789
+ }, [
790
+ view,
791
+ editorMode
792
+ ]);
793
+ return /* @__PURE__ */ React.createElement("div", {
794
+ key: model.id,
795
+ ref: setRoot,
796
+ tabIndex: 0,
797
+ ...slots?.root,
798
+ ...editorMode !== "vim" && tabsterDOMAttribute,
799
+ onKeyUp: handleKeyUp
800
+ });
801
+ });
802
+ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
803
+ const { themeMode } = useThemeContext();
804
+ const slots = defaultsDeep({}, _slots, defaultTextSlots);
805
+ return /* @__PURE__ */ React.createElement(BaseTextEditor, {
806
+ ref: forwardedRef,
807
+ extensions: [
808
+ basicBundle({
809
+ themeMode,
810
+ placeholder: slots?.editor?.placeholder
811
+ }),
812
+ ...extensions
813
+ ],
814
+ slots,
815
+ ...props
816
+ });
817
+ });
818
+ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
819
+ const { themeMode } = useThemeContext();
820
+ const slots = defaultsDeep({}, _slots, defaultSlots);
821
+ return /* @__PURE__ */ React.createElement(BaseTextEditor, {
822
+ ref: forwardedRef,
823
+ extensions: [
824
+ markdownBundle({
825
+ themeMode,
826
+ placeholder: slots?.editor?.placeholder
827
+ }),
828
+ ...extensions
829
+ ],
830
+ slots,
831
+ ...props
832
+ });
833
+ });
834
+ var defaultSlots = {
835
+ root: {
836
+ className: mx2("p-2", inputSurface)
837
+ }
838
+ };
839
+ var defaultTextSlots = {
840
+ ...defaultSlots,
841
+ editor: {
842
+ theme: textTheme
843
+ }
844
+ };
697
845
 
698
- // packages/ui/react-ui-editor/src/hooks/useCollaboration.ts
699
- import { useEffect, useMemo } from "react";
846
+ // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
847
+ import get3 from "lodash.get";
848
+ import { useEffect as useEffect2, useState as useState2 } from "react";
700
849
  import { yCollab } from "y-codemirror.next";
701
- import { generateName } from "@dxos/display-name";
702
- import { isDocAccessor } from "@dxos/echo-schema";
703
- import { getColorForValue } from "@dxos/react-ui-theme";
704
- import { YText } from "@dxos/text-model";
850
+ import { invariant } from "@dxos/invariant";
851
+ import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
705
852
 
706
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/plugin.ts
707
- import { Annotation, Facet, StateEffect, StateField as StateField3 } from "@codemirror/state";
708
- import { ViewPlugin as ViewPlugin2 } from "@codemirror/view";
853
+ // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
854
+ import { Annotation, Facet, StateEffect, StateField as StateField4 } from "@codemirror/state";
855
+ import { ViewPlugin } from "@codemirror/view";
709
856
  import * as automerge2 from "@dxos/automerge/automerge";
710
857
 
711
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/PatchSemaphore.ts
858
+ // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
712
859
  import { next as automerge } from "@dxos/automerge/automerge";
713
860
 
714
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/amToCodemirror.ts
861
+ // packages/ui/react-ui-editor/src/hooks/automerge/amToCodemirror.ts
715
862
  import { ChangeSet } from "@codemirror/state";
716
863
  var amToCodemirror_default = (view, selection, target, patches) => {
717
864
  for (const patch of patches) {
@@ -818,7 +965,7 @@ var charPath = (textPath, candidatePath) => {
818
965
  return null;
819
966
  };
820
967
 
821
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/codeMirrorToAm.ts
968
+ // packages/ui/react-ui-editor/src/hooks/automerge/codeMirrorToAm.ts
822
969
  import { next as am } from "@dxos/automerge/automerge";
823
970
  var codeMirrorToAm_default = (field, handle, transactions, state) => {
824
971
  const { lastHeads, path } = state.field(field);
@@ -841,7 +988,7 @@ var codeMirrorToAm_default = (field, handle, transactions, state) => {
841
988
  return newHeads ?? void 0;
842
989
  };
843
990
 
844
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/PatchSemaphore.ts
991
+ // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
845
992
  var PatchSemaphore = class {
846
993
  constructor(field) {
847
994
  this._inReconcile = false;
@@ -882,7 +1029,7 @@ var PatchSemaphore = class {
882
1029
  }
883
1030
  };
884
1031
 
885
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/plugin.ts
1032
+ // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
886
1033
  var effectType = StateEffect.define({});
887
1034
  var updateHeads = (newHeads) => effectType.of({
888
1035
  newHeads
@@ -893,7 +1040,7 @@ var semaphoreFacet = Facet.define({
893
1040
  combine: (values) => values.at(-1)
894
1041
  });
895
1042
  var automergePlugin = (handle, path) => {
896
- const stateField = StateField3.define({
1043
+ const stateField = StateField4.define({
897
1044
  create: () => ({
898
1045
  lastHeads: automerge2.getHeads(handle.docSync()),
899
1046
  unreconciledTransactions: [],
@@ -923,7 +1070,7 @@ var automergePlugin = (handle, path) => {
923
1070
  }
924
1071
  });
925
1072
  const semaphore = new PatchSemaphore(stateField);
926
- const viewPlugin = ViewPlugin2.fromClass(class AutomergeCodemirrorViewPlugin {
1073
+ const viewPlugin = ViewPlugin.fromClass(class AutomergeCodemirrorViewPlugin {
927
1074
  constructor(view) {
928
1075
  this._handleChange = () => {
929
1076
  this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
@@ -953,45 +1100,6 @@ var automergePlugin = (handle, path) => {
953
1100
  var reconcileAnnotationType = Annotation.define();
954
1101
  var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
955
1102
 
956
- // packages/ui/react-ui-editor/src/hooks/useCollaboration.ts
957
- var useCollaboration = (model, themeMode) => {
958
- const { provider, peer, content } = model;
959
- const extension = useMemo(() => {
960
- if (content instanceof YText) {
961
- return yCollab(content, provider?.awareness);
962
- } else if (isDocAccessor(content)) {
963
- return automergePlugin(content.handle, content.path);
964
- } else {
965
- return void 0;
966
- }
967
- }, []);
968
- useEffect(() => {
969
- if (provider && peer) {
970
- provider.awareness.setLocalStateField("user", {
971
- name: peer.name ?? generateName(peer.id),
972
- color: getColorForValue({
973
- value: peer.id,
974
- type: "color"
975
- }),
976
- colorLight: getColorForValue({
977
- value: peer.id,
978
- themeMode,
979
- type: "highlight"
980
- })
981
- });
982
- }
983
- }, [
984
- provider,
985
- peer,
986
- themeMode
987
- ]);
988
- return extension;
989
- };
990
-
991
- // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
992
- import { useMemo as useMemo2 } from "react";
993
- import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
994
-
995
1103
  // packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
996
1104
  import * as random from "lib0/random";
997
1105
  var cursorColors = [
@@ -1131,185 +1239,80 @@ var SpaceAwarenessProvider = class extends Observable {
1131
1239
  };
1132
1240
 
1133
1241
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
1242
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
1134
1243
  var useTextModel = ({ identity, space, text }) => {
1135
- const provider = useMemo2(() => {
1136
- if (isActualAutomergeObject(text)) {
1137
- return void 0;
1138
- }
1139
- if (!space || !text?.doc) {
1140
- return void 0;
1141
- }
1142
- return new SpaceAwarenessProvider({
1244
+ const [model, setModel] = useState2(() => createModel({
1245
+ identity,
1246
+ space,
1247
+ text
1248
+ }));
1249
+ useEffect2(() => {
1250
+ setModel(createModel({
1251
+ identity,
1143
1252
  space,
1144
- doc: text.doc,
1145
- channel: `yjs.awareness.${text.id}`
1146
- });
1253
+ text
1254
+ }));
1147
1255
  }, [
1148
1256
  identity,
1149
1257
  space,
1150
- text,
1151
- text?.doc
1152
- ]);
1153
- const content = useMemo2(() => {
1154
- if (isActualAutomergeObject(text)) {
1155
- const obj = text;
1156
- return getRawDoc(obj, [
1157
- obj.field
1158
- ]);
1159
- } else {
1160
- return text?.content;
1161
- }
1162
- }, [
1163
1258
  text
1164
1259
  ]);
1260
+ return model;
1261
+ };
1262
+ var createModel = (options) => {
1263
+ const { space, text } = options;
1165
1264
  if (isActualAutomergeObject(text)) {
1166
- const obj = text;
1167
- return {
1168
- id: obj.id,
1169
- content,
1170
- provider: void 0,
1171
- peer: identity ? {
1172
- id: identity.identityKey.toHex(),
1173
- name: identity.profile?.displayName
1174
- } : void 0
1175
- };
1176
- }
1177
- if (!text?.doc || !text?.content) {
1178
- return void 0;
1265
+ return createAutomergeModel(options);
1266
+ } else {
1267
+ if (!space || !text?.doc || !text?.content) {
1268
+ return void 0;
1269
+ }
1270
+ return createYjsModel(options);
1179
1271
  }
1272
+ };
1273
+ var createYjsModel = ({ identity, space, text }) => {
1274
+ invariant(space && text?.doc && text?.content, void 0, {
1275
+ F: __dxlog_file2,
1276
+ L: 73,
1277
+ S: void 0,
1278
+ A: [
1279
+ "space && text?.doc && text?.content",
1280
+ ""
1281
+ ]
1282
+ });
1283
+ const provider = new SpaceAwarenessProvider({
1284
+ space,
1285
+ doc: text.doc,
1286
+ channel: `yjs.awareness.${text.id}`
1287
+ });
1180
1288
  return {
1181
1289
  id: text.doc.guid,
1182
1290
  content: text.content,
1183
- provider,
1291
+ text: () => text.content.toString(),
1292
+ extension: yCollab(text.content, provider.awareness),
1293
+ awareness: provider.awareness,
1184
1294
  peer: identity ? {
1185
1295
  id: identity.identityKey.toHex(),
1186
1296
  name: identity.profile?.displayName
1187
1297
  } : void 0
1188
1298
  };
1189
1299
  };
1190
-
1191
- // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
1192
- var EditorModes = [
1193
- "default",
1194
- "vim"
1195
- ];
1196
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots, editorMode }, forwardedRef) => {
1197
- const { themeMode } = useThemeContext();
1198
- const tabsterDOMAttribute = useFocusableGroup({
1199
- tabBehavior: "limited"
1200
- });
1201
- const [parent, setParent] = useState(null);
1202
- const [state, setState] = useState();
1203
- const [view, setView] = useState();
1204
- useImperativeHandle(forwardedRef, () => ({
1205
- editor: parent,
1206
- state,
1207
- view
1208
- }), [
1209
- view,
1210
- state,
1211
- parent
1212
- ]);
1213
- const collaboration = useCollaboration(model, themeMode);
1214
- useEffect2(() => {
1215
- if (!parent) {
1216
- return;
1217
- }
1218
- const initialText = isDocAccessor2(model.content) ? get3(model.content.handle.docSync(), model.content.path) : model.content?.toString();
1219
- const state2 = EditorState2.create({
1220
- doc: initialText,
1221
- extensions: [
1222
- // TODO(burdon): Factor out VIM mode?
1223
- editorMode === "vim" && vim(),
1224
- // Replication.
1225
- collaboration,
1226
- // Theme.
1227
- slots?.editor?.theme && EditorView5.theme(slots?.editor?.theme),
1228
- // Custom.
1229
- ...extensions
1230
- ].filter(Boolean)
1231
- });
1232
- setState(state2);
1233
- view?.destroy();
1234
- setView(new EditorView5({
1235
- state: state2,
1236
- parent
1237
- }));
1238
- return () => {
1239
- view?.destroy();
1240
- setView(void 0);
1241
- setState(void 0);
1242
- };
1243
- }, [
1244
- parent,
1245
- model.content,
1246
- themeMode,
1247
- editorMode
1248
- ]);
1249
- const handleKeyUp = useCallback((event) => {
1250
- const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
1251
- switch (key) {
1252
- case "Enter": {
1253
- view?.contentDOM.focus();
1254
- break;
1255
- }
1256
- case "Escape": {
1257
- editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && parent?.focus();
1258
- break;
1259
- }
1260
- }
1261
- }, [
1262
- view,
1263
- editorMode
1300
+ var createAutomergeModel = ({ identity, space, text }) => {
1301
+ const obj = text;
1302
+ const doc = getRawDoc(obj, [
1303
+ obj.field
1264
1304
  ]);
1265
- return /* @__PURE__ */ React.createElement("div", {
1266
- key: model.id,
1267
- ref: setParent,
1268
- tabIndex: 0,
1269
- ...slots?.root,
1270
- ...editorMode !== "vim" && tabsterDOMAttribute,
1271
- onKeyUp: handleKeyUp
1272
- });
1273
- });
1274
- var TextEditor = /* @__PURE__ */ forwardRef(({ extensions: _extensions, slots, ...props }, forwardedRef) => {
1275
- const { themeMode } = useThemeContext();
1276
- const extensions = [
1277
- ..._extensions ?? [],
1278
- basicBundle({
1279
- themeMode,
1280
- placeholder: slots?.editor?.placeholder
1281
- })
1282
- ];
1283
- return /* @__PURE__ */ React.createElement(BaseTextEditor, {
1284
- ref: forwardedRef,
1285
- extensions,
1286
- slots: defaultsDeep({}, slots, {
1287
- editor: {
1288
- theme: basicTheme
1289
- }
1290
- }),
1291
- ...props
1292
- });
1293
- });
1294
- var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions: _extensions, slots, ...props }, forwardedRef) => {
1295
- const { themeMode } = useThemeContext();
1296
- const extensions = [
1297
- ..._extensions ?? [],
1298
- markdownBundle({
1299
- themeMode
1300
- })
1301
- ];
1302
- return /* @__PURE__ */ React.createElement(BaseTextEditor, {
1303
- ref: forwardedRef,
1304
- extensions,
1305
- slots: defaultsDeep({}, slots, {
1306
- editor: {
1307
- theme: markdownTheme
1308
- }
1309
- }),
1310
- ...props
1311
- });
1312
- });
1305
+ return {
1306
+ id: obj.id,
1307
+ content: doc,
1308
+ text: () => get3(doc.handle.docSync(), doc.path),
1309
+ extension: automergePlugin(doc.handle, doc.path),
1310
+ peer: identity ? {
1311
+ id: identity.identityKey.toHex(),
1312
+ name: identity.profile?.displayName
1313
+ } : void 0
1314
+ };
1315
+ };
1313
1316
  export {
1314
1317
  BaseTextEditor,
1315
1318
  Doc,
@@ -1318,34 +1321,27 @@ export {
1318
1321
  SpaceAwarenessProvider,
1319
1322
  TextEditor,
1320
1323
  TextKind,
1321
- YText2 as YText,
1324
+ YText,
1322
1325
  YXmlFragment,
1326
+ autocomplete,
1323
1327
  basicBundle,
1324
- basicTheme,
1325
- chalky,
1326
- coral,
1327
- createHyperlinkTooltip,
1328
+ codeTheme,
1328
1329
  cursorColor,
1329
- cyan,
1330
- highlightBackground,
1331
- hyperLinkExtension,
1332
- hyperlinkDecoration,
1333
- hyperlinkStyle,
1334
- hyperlinkWidget,
1335
- invalid,
1336
- ivory,
1337
- malibu,
1330
+ defaultSlots,
1331
+ defaultTextSlots,
1332
+ defaultTheme,
1333
+ link,
1334
+ listener,
1338
1335
  markdownBundle,
1339
1336
  markdownHighlightStyle,
1340
- markdownTheme,
1341
- onChangeExtension,
1342
- sage,
1343
- stone,
1337
+ markdownTags,
1338
+ markdownTagsExtension,
1339
+ statefield,
1340
+ styles,
1344
1341
  tags2 as tags,
1345
- tooltipBackground,
1346
- useCollaboration,
1347
- useTextModel,
1348
- violet,
1349
- whiskey
1342
+ tasklist,
1343
+ textTheme,
1344
+ tooltip,
1345
+ useTextModel
1350
1346
  };
1351
1347
  //# sourceMappingURL=index.mjs.map