@dxos/react-ui-editor 0.3.10-next.ef70620 → 0.3.10

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 (154) hide show
  1. package/dist/lib/browser/index.mjs +1827 -799
  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 +59 -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 +7 -3
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +12 -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 +10 -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} +3 -2
  13. package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -0
  14. package/dist/types/src/components/TextEditor/extensions/blast.d.ts +25 -0
  15. package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +1 -0
  16. package/dist/types/src/components/TextEditor/extensions/code.d.ts +2 -0
  17. package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +1 -0
  18. package/dist/types/src/components/TextEditor/extensions/comments.d.ts +18 -0
  19. package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -0
  20. package/dist/types/src/components/TextEditor/extensions/demo.d.ts +11 -0
  21. package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +1 -0
  22. package/dist/types/src/components/TextEditor/extensions/{hyperlink/hyperlinkWidget.d.ts → experimental.d.ts} +2 -2
  23. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -0
  24. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts +24 -0
  25. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts.map +1 -0
  26. package/dist/types/src/components/TextEditor/extensions/image.d.ts +4 -0
  27. package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +1 -0
  28. package/dist/types/src/components/TextEditor/extensions/index.d.ts +13 -2
  29. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
  30. package/dist/types/src/components/TextEditor/extensions/link.d.ts +11 -0
  31. package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +1 -0
  32. package/dist/types/src/components/TextEditor/extensions/listener.d.ts +9 -0
  33. package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -0
  34. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +10 -1
  35. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
  36. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts +37 -0
  37. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -0
  38. package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts +1 -1
  39. package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts.map +1 -1
  40. package/dist/types/src/components/TextEditor/extensions/mention.d.ts +6 -0
  41. package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +1 -0
  42. package/dist/types/src/components/TextEditor/extensions/table.d.ts +8 -0
  43. package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +1 -0
  44. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +3 -0
  45. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -0
  46. package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts +12 -0
  47. package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts.map +1 -0
  48. package/dist/types/src/components/TextEditor/index.d.ts +2 -0
  49. package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
  50. package/dist/types/src/components/TextEditor/themes/default.d.ts +25 -0
  51. package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -0
  52. package/dist/types/src/components/TextEditor/themes/index.d.ts +2 -0
  53. package/dist/types/src/components/TextEditor/themes/index.d.ts.map +1 -0
  54. package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/PatchSemaphore.d.ts +3 -0
  55. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +1 -0
  56. package/dist/types/src/hooks/automerge/automerge.stories.d.ts +16 -0
  57. package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -0
  58. package/dist/types/src/hooks/automerge/handle.d.ts.map +1 -0
  59. package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/index.d.ts +1 -1
  60. package/dist/types/src/hooks/automerge/index.d.ts.map +1 -0
  61. package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -0
  62. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts +5 -0
  63. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts.map +1 -0
  64. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts +6 -0
  65. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts.map +1 -0
  66. package/dist/types/src/hooks/automerge/translation/index.d.ts +3 -0
  67. package/dist/types/src/hooks/automerge/translation/index.d.ts.map +1 -0
  68. package/dist/types/src/hooks/index.d.ts +0 -1
  69. package/dist/types/src/hooks/index.d.ts.map +1 -1
  70. package/dist/types/src/hooks/useTextModel.d.ts +9 -3
  71. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  72. package/dist/types/src/{components/TextEditor → hooks/yjs}/yjs.stories.d.ts +2 -1
  73. package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -0
  74. package/dist/types/src/styles/markdown.d.ts +14 -11
  75. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  76. package/dist/types/src/testing/replicator.d.ts.map +1 -1
  77. package/package.json +24 -33
  78. package/src/components/TextEditor/MarkdownEditor.stories.tsx +367 -0
  79. package/src/components/TextEditor/TextEditor.stories.tsx +57 -43
  80. package/src/components/TextEditor/TextEditor.tsx +87 -45
  81. package/src/components/TextEditor/extensions/autocomplete.ts +59 -0
  82. package/src/components/TextEditor/extensions/{basic/bundle.ts → basic.ts} +8 -4
  83. package/src/components/TextEditor/extensions/blast.ts +373 -0
  84. package/src/components/TextEditor/extensions/code.ts +99 -0
  85. package/src/components/TextEditor/extensions/comments.ts +173 -0
  86. package/src/components/TextEditor/extensions/demo.ts +69 -0
  87. package/src/components/TextEditor/extensions/{hyperlink/hyperlinkWidget.tsx → experimental.tsx} +16 -21
  88. package/src/components/TextEditor/extensions/highlight.ts +128 -0
  89. package/src/components/TextEditor/extensions/image.ts +67 -0
  90. package/src/components/TextEditor/extensions/index.ts +13 -2
  91. package/src/components/TextEditor/extensions/{hyperlink/hyperlinkDecoration.ts → link.ts} +75 -38
  92. package/src/components/TextEditor/extensions/{change.ts → listener.ts} +5 -4
  93. package/src/components/TextEditor/extensions/markdown/bundle.ts +56 -49
  94. package/src/components/TextEditor/extensions/markdown/highlight.ts +207 -0
  95. package/src/components/TextEditor/extensions/markdown/index.ts +1 -1
  96. package/src/components/TextEditor/extensions/mention.ts +31 -0
  97. package/src/components/TextEditor/extensions/table.ts +119 -0
  98. package/src/components/TextEditor/extensions/tasklist.ts +121 -0
  99. package/src/components/TextEditor/extensions/{hyperlink/hyperlinkTooltip.tsx → tooltip.tsx} +9 -9
  100. package/src/components/TextEditor/index.ts +3 -0
  101. package/src/components/TextEditor/themes/default.ts +279 -0
  102. package/src/components/TextEditor/themes/index.ts +5 -0
  103. package/src/{automerge/automerge-plugin → hooks/automerge}/PatchSemaphore.ts +12 -9
  104. package/src/{automerge → hooks/automerge}/automerge.stories.tsx +6 -3
  105. package/src/{automerge/automerge-plugin → hooks/automerge}/plugin.ts +1 -0
  106. package/src/{automerge/automerge-plugin/amToCodemirror.ts → hooks/automerge/translation/automerge-to-codemirror.ts} +10 -2
  107. package/src/{automerge/automerge-plugin/codeMirrorToAm.ts → hooks/automerge/translation/codemirror-to-automerge.ts} +7 -4
  108. package/src/hooks/automerge/translation/index.ts +6 -0
  109. package/src/hooks/index.ts +0 -1
  110. package/src/hooks/useTextModel.ts +61 -39
  111. package/src/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +2 -1
  112. package/src/styles/markdown.ts +33 -24
  113. package/src/testing/replicator.ts +7 -6
  114. package/dist/types/src/automerge/automerge-plugin/PatchSemaphore.d.ts.map +0 -1
  115. package/dist/types/src/automerge/automerge-plugin/amToCodemirror.d.ts +0 -6
  116. package/dist/types/src/automerge/automerge-plugin/amToCodemirror.d.ts.map +0 -1
  117. package/dist/types/src/automerge/automerge-plugin/codeMirrorToAm.d.ts +0 -7
  118. package/dist/types/src/automerge/automerge-plugin/codeMirrorToAm.d.ts.map +0 -1
  119. package/dist/types/src/automerge/automerge-plugin/handle.d.ts.map +0 -1
  120. package/dist/types/src/automerge/automerge-plugin/index.d.ts.map +0 -1
  121. package/dist/types/src/automerge/automerge-plugin/plugin.d.ts.map +0 -1
  122. package/dist/types/src/automerge/automerge.stories.d.ts +0 -9
  123. package/dist/types/src/automerge/automerge.stories.d.ts.map +0 -1
  124. package/dist/types/src/components/TextEditor/extensions/basic/bundle.d.ts.map +0 -1
  125. package/dist/types/src/components/TextEditor/extensions/basic/index.d.ts +0 -3
  126. package/dist/types/src/components/TextEditor/extensions/basic/index.d.ts.map +0 -1
  127. package/dist/types/src/components/TextEditor/extensions/basic/theme.d.ts +0 -10
  128. package/dist/types/src/components/TextEditor/extensions/basic/theme.d.ts.map +0 -1
  129. package/dist/types/src/components/TextEditor/extensions/change.d.ts +0 -7
  130. package/dist/types/src/components/TextEditor/extensions/change.d.ts.map +0 -1
  131. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.d.ts +0 -11
  132. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.d.ts.map +0 -1
  133. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.d.ts +0 -8
  134. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.d.ts.map +0 -1
  135. package/dist/types/src/components/TextEditor/extensions/hyperlink/hyperlinkWidget.d.ts.map +0 -1
  136. package/dist/types/src/components/TextEditor/extensions/hyperlink/index.d.ts +0 -4
  137. package/dist/types/src/components/TextEditor/extensions/hyperlink/index.d.ts.map +0 -1
  138. package/dist/types/src/components/TextEditor/extensions/markdown/tags.d.ts +0 -17
  139. package/dist/types/src/components/TextEditor/extensions/markdown/tags.d.ts.map +0 -1
  140. package/dist/types/src/components/TextEditor/extensions/markdown/theme.d.ts +0 -21
  141. package/dist/types/src/components/TextEditor/extensions/markdown/theme.d.ts.map +0 -1
  142. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
  143. package/dist/types/src/hooks/useCollaboration.d.ts +0 -9
  144. package/dist/types/src/hooks/useCollaboration.d.ts.map +0 -1
  145. package/src/components/TextEditor/extensions/basic/index.ts +0 -6
  146. package/src/components/TextEditor/extensions/basic/theme.ts +0 -49
  147. package/src/components/TextEditor/extensions/hyperlink/index.ts +0 -7
  148. package/src/components/TextEditor/extensions/markdown/tags.ts +0 -38
  149. package/src/components/TextEditor/extensions/markdown/theme.ts +0 -265
  150. package/src/hooks/useCollaboration.ts +0 -45
  151. package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/handle.d.ts +0 -0
  152. package/dist/types/src/{automerge/automerge-plugin → hooks/automerge}/plugin.d.ts +0 -0
  153. package/src/{automerge/automerge-plugin → hooks/automerge}/handle.ts +0 -0
  154. package/src/{automerge/automerge-plugin → hooks/automerge}/index.ts +1 -1
@@ -1,162 +1,1410 @@
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 = ({ onSearch }) => {
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 match = context.matchBefore(/\w*/);
28
+ if (!match || match.from === match.to && !context.explicit) {
29
+ return null;
30
+ }
31
+ return {
32
+ from: match.from,
33
+ options: onSearch(match.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
- import { EditorView, placeholder } from "@codemirror/view";
13
- var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
45
+ import { drawSelection, EditorView, placeholder } from "@codemirror/view";
46
+ var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
47
+ EditorView.lineWrapping,
48
+ // TODO(burdon): Compare with minimalSetup.
49
+ // https://codemirror.net/docs/ref/#codemirror.minimalSetup
14
50
  bracketMatching(),
15
51
  closeBrackets(),
52
+ drawSelection(),
16
53
  _placeholder && placeholder(_placeholder),
17
- EditorView.lineWrapping,
18
54
  // TODO(burdon): Is this required?
19
55
  themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
20
56
  ].filter(Boolean);
21
57
 
22
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/basic/theme.ts
58
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts
59
+ import { EditorView as EditorView2, keymap as keymap2 } from "@codemirror/view";
60
+ import defaultsDeep from "lodash.defaultsdeep";
61
+ import { invariant } from "@dxos/invariant";
62
+ var __dxlog_file = "/home/circleci/project/packages/ui/react-ui-editor/src/components/TextEditor/extensions/blast.ts";
63
+ var defaultOptions = {
64
+ effect: 2,
65
+ maxParticles: 200,
66
+ particleGravity: 0.08,
67
+ particleAlphaFadeout: 0.996,
68
+ particleSize: {
69
+ min: 2,
70
+ max: 8
71
+ },
72
+ particleNumRange: {
73
+ min: 5,
74
+ max: 10
75
+ },
76
+ particleVelocityRange: {
77
+ x: [
78
+ -1,
79
+ 1
80
+ ],
81
+ y: [
82
+ -3.5,
83
+ -1.5
84
+ ]
85
+ },
86
+ particleShrinkRate: 0.95,
87
+ shakeIntensity: 5
88
+ };
89
+ var blast = (options = defaultOptions) => {
90
+ let blaster;
91
+ let last = 0;
92
+ const getPoint = (view, pos) => {
93
+ const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
94
+ const element = document.elementFromPoint(x, y);
95
+ const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
96
+ const point = {
97
+ x: x - left,
98
+ y: y - top
99
+ };
100
+ return {
101
+ element,
102
+ point
103
+ };
104
+ };
105
+ return [
106
+ // Cursor moved.
107
+ EditorView2.updateListener.of((update4) => {
108
+ if (blaster?.node !== update4.view.scrollDOM) {
109
+ if (blaster) {
110
+ blaster.destroy();
111
+ }
112
+ blaster = new Blaster(update4.view.scrollDOM, defaultsDeep({
113
+ particleGravity: 0.2,
114
+ particleShrinkRate: 0.995,
115
+ color: () => [
116
+ 100 + Math.random() * 100,
117
+ 0,
118
+ 0
119
+ ]
120
+ }, options, defaultOptions));
121
+ blaster.initialize();
122
+ blaster.start();
123
+ } else {
124
+ blaster.resize();
125
+ }
126
+ const current = update4.state.selection.main.head;
127
+ if (current !== last) {
128
+ last = current;
129
+ const { element, point } = getPoint(update4.view, current - 1);
130
+ if (element && point) {
131
+ blaster.spawn({
132
+ element,
133
+ point
134
+ });
135
+ }
136
+ }
137
+ }),
138
+ keymap2.of([
139
+ {
140
+ any: (_, event) => {
141
+ if (blaster) {
142
+ if (event.key === "Enter" && event.shiftKey) {
143
+ blaster.shake({
144
+ time: 0.8
145
+ });
146
+ return true;
147
+ }
148
+ }
149
+ return false;
150
+ }
151
+ }
152
+ ])
153
+ ];
154
+ };
155
+ var Blaster = class {
156
+ constructor(_node, _options) {
157
+ this._node = _node;
158
+ this._options = _options;
159
+ this._running = false;
160
+ this._shakeTime = 0;
161
+ this._shakeTimeMax = 0;
162
+ this._particles = [];
163
+ this._particlePointer = 0;
164
+ this._lastPoint = {
165
+ x: 0,
166
+ y: 0
167
+ };
168
+ this.shake = throttle(({ time }) => {
169
+ this._shakeTime = this._shakeTimeMax || time;
170
+ this._shakeTimeMax = time;
171
+ }, 100);
172
+ this.spawn = throttle(({ element, point }) => {
173
+ const color = getRGBComponents(element, this._options.color);
174
+ const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
175
+ const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
176
+ this._lastPoint = point;
177
+ for (let i = numParticles; i--; i > 0) {
178
+ this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
179
+ this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
180
+ }
181
+ }, 100);
182
+ this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
183
+ }
184
+ get node() {
185
+ return this._node;
186
+ }
187
+ initialize() {
188
+ invariant(!this._canvas && !this._ctx, void 0, {
189
+ F: __dxlog_file,
190
+ L: 138,
191
+ S: this,
192
+ A: [
193
+ "!this._canvas && !this._ctx",
194
+ ""
195
+ ]
196
+ });
197
+ this._canvas = document.createElement("canvas");
198
+ this._canvas.id = "code-blast-canvas";
199
+ this._canvas.style.position = "absolute";
200
+ this._canvas.style.zIndex = "0";
201
+ this._canvas.style.pointerEvents = "none";
202
+ this._ctx = this._canvas.getContext("2d");
203
+ const parent = this._node.parentElement?.parentElement;
204
+ parent?.appendChild(this._canvas);
205
+ this.resize();
206
+ }
207
+ destroy() {
208
+ this.stop();
209
+ if (this._canvas) {
210
+ this._canvas.remove();
211
+ this._canvas = void 0;
212
+ this._ctx = void 0;
213
+ }
214
+ }
215
+ resize() {
216
+ if (this._node.parentElement && this._canvas) {
217
+ const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
218
+ this._canvas.style.top = `${y}px`;
219
+ this._canvas.style.left = `${x}px`;
220
+ this._canvas.width = width;
221
+ this._canvas.height = height;
222
+ }
223
+ }
224
+ start() {
225
+ invariant(this._canvas && this._ctx, void 0, {
226
+ F: __dxlog_file,
227
+ L: 177,
228
+ S: this,
229
+ A: [
230
+ "this._canvas && this._ctx",
231
+ ""
232
+ ]
233
+ });
234
+ this._running = true;
235
+ this.loop();
236
+ }
237
+ stop() {
238
+ this._running = false;
239
+ this._node.style.transform = "translate(0px, 0px)";
240
+ }
241
+ loop() {
242
+ if (!this._running || !this._canvas || !this._ctx) {
243
+ return;
244
+ }
245
+ this._ctx.clearRect(0, 0, this._canvas.width ?? 0, this._canvas.height ?? 0);
246
+ const now = (/* @__PURE__ */ new Date()).getTime();
247
+ this._lastTime ??= now;
248
+ const dt = (now - this._lastTime) / 1e3;
249
+ this._lastTime = now;
250
+ if (this._shakeTime > 0) {
251
+ this._shakeTime -= dt;
252
+ const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
253
+ const shakeX = random(-magnitude, magnitude);
254
+ const shakeY = random(-magnitude, magnitude);
255
+ this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
256
+ }
257
+ this.drawParticles();
258
+ requestAnimationFrame(this.loop.bind(this));
259
+ }
260
+ drawParticles() {
261
+ for (let i = this._particles.length; i--; i > 0) {
262
+ const particle = this._particles[i];
263
+ if (!particle) {
264
+ continue;
265
+ }
266
+ if (particle.alpha < 0.01 || particle.size <= 0.5) {
267
+ continue;
268
+ }
269
+ this._effect.update(this._ctx, particle);
270
+ }
271
+ }
272
+ };
273
+ var Effect = class {
274
+ constructor(_options) {
275
+ this._options = _options;
276
+ }
277
+ };
278
+ var Effect1 = class extends Effect {
279
+ create(x, y, color) {
280
+ return {
281
+ x,
282
+ y: y + 10,
283
+ vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
284
+ vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
285
+ size: random(this._options.particleSize.min, this._options.particleSize.max),
286
+ color,
287
+ alpha: 1
288
+ };
289
+ }
290
+ update(ctx, particle) {
291
+ particle.vy += this._options.particleGravity;
292
+ particle.x += particle.vx;
293
+ particle.y += particle.vy;
294
+ particle.alpha *= this._options.particleAlphaFadeout;
295
+ ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
296
+ ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
297
+ }
298
+ };
299
+ var Effect2 = class extends Effect {
300
+ create(x, y, color) {
301
+ return {
302
+ x,
303
+ y: y + 10,
304
+ vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
305
+ vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
306
+ size: random(this._options.particleSize.min, this._options.particleSize.max),
307
+ color,
308
+ alpha: 1,
309
+ theta: random(0, 360) * Math.PI / 180,
310
+ drag: 0.92,
311
+ wander: 0.15
312
+ };
313
+ }
314
+ update(ctx, particle) {
315
+ particle.vy += this._options.particleGravity;
316
+ particle.x += particle.vx;
317
+ particle.y += particle.vy;
318
+ particle.vx *= particle.drag;
319
+ particle.vy *= particle.drag;
320
+ particle.theta += random(-0.5, 0.5);
321
+ particle.vx += Math.sin(particle.theta) * 0.1;
322
+ particle.vy += Math.cos(particle.theta) * 0.1;
323
+ particle.size *= this._options.particleShrinkRate;
324
+ particle.alpha *= this._options.particleAlphaFadeout;
325
+ ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
326
+ ctx.beginPath();
327
+ ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
328
+ ctx.fill();
329
+ }
330
+ };
331
+ function throttle(callback, limit) {
332
+ let wait = false;
333
+ return function(...args) {
334
+ if (!wait) {
335
+ callback.apply(this, args);
336
+ wait = true;
337
+ setTimeout(() => {
338
+ wait = false;
339
+ }, limit);
340
+ }
341
+ };
342
+ }
343
+ var getRGBComponents = (node, color) => {
344
+ if (typeof color === "function") {
345
+ return color();
346
+ }
347
+ const bgColor = getComputedStyle(node).color;
348
+ if (bgColor) {
349
+ const x = bgColor.match(/(\d+), (\d+), (\d+)/)?.slice(1);
350
+ if (x) {
351
+ return x;
352
+ }
353
+ }
354
+ return [
355
+ 50,
356
+ 50,
357
+ 50
358
+ ];
359
+ };
360
+ var random = (min, max) => {
361
+ if (!max) {
362
+ max = min;
363
+ min = 0;
364
+ }
365
+ return min + ~~(Math.random() * (max - min + 1));
366
+ };
367
+
368
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/code.ts
369
+ import { ViewPlugin, EditorView as EditorView3, Decoration } from "@codemirror/view";
23
370
  import get from "lodash.get";
371
+ import { mx as mx2 } from "@dxos/react-ui-theme";
24
372
 
25
373
  // packages/ui/react-ui-editor/src/styles/markdown.ts
26
374
  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"
375
+ var headings = {
376
+ 1: [
377
+ "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
378
+ "-ml-[10px]"
379
+ ],
380
+ 2: [
381
+ "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
382
+ "-ml-[8px]"
383
+ ],
384
+ 3: [
385
+ "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
386
+ "-ml-[7px]"
387
+ ],
388
+ 4: [
389
+ "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
390
+ "-ml-[6px]"
391
+ ],
392
+ 5: [
393
+ "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
394
+ "-ml-[5px]"
395
+ ],
396
+ 6: [
397
+ "mbs-4 mbe-2 font-medium text-inherit no-underline",
398
+ "-ml-[4px]"
399
+ ]
400
+ };
401
+ var heading = (level, readonly) => {
402
+ const [style, offset] = headings[level];
403
+ return mx(style, readonly && offset);
404
+ };
405
+ var light = "text-neutral-200 dark:text-neutral-800";
406
+ var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
407
+ var bold = "font-bold";
408
+ var italic = "italic";
409
+ var strikethrough = "line-through";
410
+ var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
411
+ var codeMark = "font-mono text-primary-500";
412
+ var inlineUrl = mx(code, "px-1");
413
+ var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
414
+ var horizontalRule = "flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800";
415
+
416
+ // packages/ui/react-ui-editor/src/styles/tokens.ts
417
+ import { tailwindConfig } from "@dxos/react-ui-theme";
418
+ var tokens = tailwindConfig({}).theme;
419
+
420
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/code.ts
421
+ var CODE_REGEX = /```[\s\S]*?```/gs;
422
+ var styles = EditorView3.baseTheme({
423
+ "& .cm-code-block": {
424
+ display: "block",
425
+ paddingInline: "4px !important"
426
+ },
427
+ "&light .cm-code-block": {
428
+ background: get(tokens, "extend.colors.neutral.50")
429
+ },
430
+ "&dark .cm-code-block": {
431
+ background: get(tokens, "extend.colors.neutral.850")
432
+ },
433
+ "& .cm-code-block-first": {
434
+ paddingTop: "4px !important",
435
+ borderTopLeftRadius: "4px",
436
+ borderTopRightRadius: "4px"
437
+ },
438
+ "& .cm-code-block-last": {
439
+ paddingBottom: "4px !important",
440
+ borderBottomLeftRadius: "4px",
441
+ borderBottomRightRadius: "4px"
442
+ }
443
+ });
444
+ var getLineRange = (lines, from, to) => {
445
+ const start = lines.findIndex((line) => line.from >= from);
446
+ const end = lines.findIndex((line) => line.to >= to);
447
+ return [
448
+ start,
449
+ end
450
+ ];
451
+ };
452
+ var code2 = () => {
453
+ const getDecorations = (view) => {
454
+ const decorations = [];
455
+ if (view.state.readOnly) {
456
+ const text = view.state.doc.sliceString(0);
457
+ const matches = text.matchAll(CODE_REGEX);
458
+ const blocks = view.viewportLineBlocks;
459
+ for (const match of matches) {
460
+ const range = getLineRange(blocks, match.index, match.index + match[0].length);
461
+ for (let i = range[0]; i <= range[1]; i++) {
462
+ const block = blocks[i];
463
+ decorations.push(Decoration.line({
464
+ class: mx2("cm-code-block", i === range[0] && "cm-code-block-first", i === range[1] && "cm-code-block-last")
465
+ }).range(block.from));
466
+ }
467
+ }
468
+ }
469
+ return Decoration.set(decorations);
470
+ };
471
+ return [
472
+ ViewPlugin.fromClass(class {
473
+ constructor(view) {
474
+ this.decorations = getDecorations(view);
475
+ }
476
+ update(update4) {
477
+ if (update4.docChanged || update4.viewportChanged) {
478
+ this.decorations = getDecorations(update4.view);
479
+ }
480
+ }
481
+ }, {
482
+ decorations: (value) => value.decorations
483
+ }),
484
+ styles
485
+ ];
486
+ };
487
+
488
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
489
+ import { keymap as keymap3 } from "@codemirror/view";
490
+ var defaultItems = [
491
+ "hello world!",
492
+ "this is a test.",
493
+ "this is [DXOS](https://dxos.org)"
494
+ ];
495
+ var demo = ({ delay = 75, items = defaultItems } = {}) => {
496
+ let t;
497
+ let idx = 0;
498
+ return [
499
+ keymap3.of([
500
+ {
501
+ // Reset.
502
+ key: "alt-meta-'",
503
+ run: (view) => {
504
+ clearTimeout(t);
505
+ idx = 0;
506
+ return true;
507
+ }
508
+ },
509
+ {
510
+ // Next prompt.
511
+ // TODO(burdon): Press 1-9 to select prompt?
512
+ key: "shift-meta-'",
513
+ run: (view) => {
514
+ clearTimeout(t);
515
+ const text = items[idx++];
516
+ if (idx === items?.length) {
517
+ idx = 0;
518
+ }
519
+ let i = 0;
520
+ const insert = (d = 0) => {
521
+ t = setTimeout(() => {
522
+ const pos = view.state.selection.main.head;
523
+ view.dispatch({
524
+ changes: {
525
+ from: pos,
526
+ insert: text[i++]
527
+ },
528
+ selection: {
529
+ anchor: pos + 1
530
+ }
531
+ });
532
+ if (i < text.length) {
533
+ insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
534
+ }
535
+ }, d);
536
+ };
537
+ insert();
538
+ return true;
539
+ }
540
+ }
541
+ ])
542
+ ];
543
+ };
544
+
545
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
546
+ import { keymap as keymap4, Decoration as Decoration2, EditorView as EditorView4, MatchDecorator, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
547
+ import { debounce } from "@dxos/async";
548
+ import { invariant as invariant2 } from "@dxos/invariant";
549
+ var __dxlog_file2 = "/home/circleci/project/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
550
+ var styles2 = EditorView4.baseTheme({
551
+ "& .cm-bookmark": {
552
+ cursor: "pointer",
553
+ margin: "4px",
554
+ padding: "4px",
555
+ backgroundColor: "yellow"
556
+ },
557
+ "& .cm-bookmark-selected": {
558
+ backgroundColor: "orange"
559
+ }
560
+ });
561
+ var BookmarkWidget = class extends WidgetType {
562
+ constructor(_pos, _id, _handleClick) {
563
+ super();
564
+ this._pos = _pos;
565
+ this._id = _id;
566
+ this._handleClick = _handleClick;
567
+ invariant2(this._id, void 0, {
568
+ F: __dxlog_file2,
569
+ L: 37,
570
+ S: this,
571
+ A: [
572
+ "this._id",
573
+ ""
574
+ ]
575
+ });
576
+ }
577
+ eq(other) {
578
+ return this._id === other._id;
579
+ }
580
+ toDOM() {
581
+ const span = document.createElement("span");
582
+ span.className = "cm-bookmark";
583
+ span.textContent = "\xA7";
584
+ span.onclick = () => this._handleClick();
585
+ return span;
586
+ }
587
+ };
588
+ var comments = (options = {}) => {
589
+ let active;
590
+ const bookmarkMatcher = new MatchDecorator({
591
+ regexp: /\[\^(\w+)\]/g,
592
+ decoration: (match, view, pos) => {
593
+ const id = match[1];
594
+ return Decoration2.replace({
595
+ id,
596
+ widget: new BookmarkWidget(pos, id, () => handleUpdate({
597
+ active: id
598
+ }))
599
+ });
600
+ }
601
+ });
602
+ const bookmarks = ViewPlugin2.fromClass(class {
603
+ constructor(view) {
604
+ this.bookmarks = bookmarkMatcher.createDeco(view);
605
+ }
606
+ update(update4) {
607
+ this.bookmarks = bookmarkMatcher.updateDeco(update4, this.bookmarks);
608
+ }
609
+ }, {
610
+ decorations: (instance) => instance.bookmarks,
611
+ provide: (plugin) => EditorView4.atomicRanges.of((view) => {
612
+ return view.plugin(plugin)?.bookmarks || Decoration2.none;
613
+ })
614
+ });
615
+ const handleUpdate = debounce((data) => {
616
+ options.onUpdate?.(data);
617
+ }, 200);
618
+ return [
619
+ keymap4.of([
620
+ {
621
+ key: options?.key ?? "shift-meta-c",
622
+ run: (view) => {
623
+ const { from, to, head } = view.state.selection.main;
624
+ const id = options.onCreate?.(from, to);
625
+ if (id) {
626
+ const tag = `[^${id}]`;
627
+ view.dispatch({
628
+ changes: {
629
+ from: head,
630
+ insert: tag
631
+ },
632
+ selection: {
633
+ anchor: head + tag.length
634
+ }
635
+ });
636
+ return true;
637
+ }
638
+ return false;
639
+ }
640
+ }
641
+ ]),
642
+ bookmarks,
643
+ // Monitor cursor movement.
644
+ EditorView4.updateListener.of((update4) => {
645
+ active = void 0;
646
+ if (!options.onUpdate) {
647
+ return;
648
+ }
649
+ const { view, state } = update4;
650
+ const pos = state.selection.main.head;
651
+ const decorations = [];
652
+ const rangeSet = view.plugin(bookmarks)?.bookmarks;
653
+ let closest = Infinity;
654
+ const { from, to } = (
655
+ /* view.visibleRanges?.[0] ?? */
656
+ {
657
+ from: 0,
658
+ to: state.doc.length
659
+ }
660
+ );
661
+ rangeSet?.between(from, to, (from2, to2, value) => {
662
+ decorations.push({
663
+ from: from2,
664
+ to: to2,
665
+ value
666
+ });
667
+ const d = Math.min(Math.abs(pos - from2), Math.abs(pos - to2));
668
+ if (d < closest) {
669
+ active = value.spec.id;
670
+ closest = d;
671
+ }
672
+ });
673
+ if (decorations.length) {
674
+ handleUpdate({
675
+ active,
676
+ items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
677
+ id,
678
+ pos: from2,
679
+ location: view.coordsAtPos(from2)
680
+ }))
681
+ });
682
+ }
683
+ }),
684
+ styles2
685
+ ];
686
+ };
687
+
688
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/highlight.ts
689
+ import { StateEffect, StateField } from "@codemirror/state";
690
+ import { Decoration as Decoration3, EditorView as EditorView5 } from "@codemirror/view";
691
+ import sortBy from "lodash.sortby";
692
+ import { useEffect } from "react";
693
+ var styles3 = EditorView5.baseTheme({
694
+ "& .cm-highlight": {
695
+ backgroundColor: "yellow"
696
+ },
697
+ "& .cm-highlight::before": {
698
+ content: "]"
699
+ },
700
+ "& .cm-highlight-active": {
701
+ backgroundColor: "lime"
702
+ }
703
+ });
704
+ var marks = {
705
+ highlight: Decoration3.mark({
706
+ class: "cm-highlight"
707
+ }),
708
+ HighlightActive: Decoration3.mark({
709
+ class: "cm-highlight-active"
710
+ })
711
+ };
712
+ var setHighlights = StateEffect.define();
713
+ var useHighlights = (view, ranges = []) => {
714
+ useEffect(() => {
715
+ view?.dispatch({
716
+ effects: setHighlights.of(ranges)
717
+ });
718
+ }, [
719
+ view,
720
+ ranges
721
+ ]);
722
+ };
723
+ var highlightStateField = StateField.define({
724
+ create: () => [],
725
+ update: (threads, tr) => {
726
+ for (const effect of tr.effects) {
727
+ if (effect.is(setHighlights)) {
728
+ return effect.value;
729
+ }
730
+ }
731
+ return threads;
732
+ }
733
+ });
734
+ var highlightDecorations = EditorView5.decorations.compute([
735
+ highlightStateField
736
+ ], (state) => {
737
+ const selectionRanges = state.field(highlightStateField);
738
+ const decorations = sortBy(selectionRanges ?? [], (selection) => selection.from)?.flatMap((selection) => {
739
+ const range = {
740
+ from: selection.from,
741
+ to: selection.to + 1
742
+ };
743
+ if (selection.to > selection.from) {
744
+ if (selection.active) {
745
+ return marks.HighlightActive.range(range.from, range.to);
746
+ } else {
747
+ return marks.highlight.range(range.from, range.to);
748
+ }
749
+ } else {
750
+ return [];
751
+ }
752
+ }) ?? [];
753
+ return Decoration3.set(decorations);
754
+ });
755
+ var listener = (options) => {
756
+ return EditorView5.updateListener.of((update4) => {
757
+ const { view, state } = update4;
758
+ const { head } = state.selection.main;
759
+ const ranges = state.field(highlightStateField);
760
+ let mod = false;
761
+ const newRanges = ranges.map((range) => {
762
+ const active = head >= range.from && head <= range.to;
763
+ if (active !== range.active) {
764
+ mod = true;
765
+ return {
766
+ ...range,
767
+ active
768
+ };
769
+ } else {
770
+ return range;
771
+ }
772
+ });
773
+ if (mod) {
774
+ view.dispatch({
775
+ effects: setHighlights.of(newRanges)
776
+ });
777
+ options?.onChange?.(newRanges.find((range) => range.active)?.id);
778
+ }
779
+ });
780
+ };
781
+ var highlight = (options = {}) => {
782
+ return [
783
+ highlightStateField,
784
+ highlightDecorations,
785
+ listener(options),
786
+ styles3
787
+ ];
788
+ };
789
+
790
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/image.ts
791
+ import { syntaxTree } from "@codemirror/language";
792
+ import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
793
+ import { Decoration as Decoration4, EditorView as EditorView6, WidgetType as WidgetType2 } from "@codemirror/view";
794
+ var image = (options = {}) => {
795
+ return StateField2.define({
796
+ create: (state) => update(state, options),
797
+ update: (_, tr) => update(tr.state, options),
798
+ provide: (field) => EditorView6.decorations.from(field)
799
+ });
800
+ };
801
+ var update = (state, options) => {
802
+ const builder = new RangeSetBuilder();
803
+ const cursor = state.selection.main.head;
804
+ syntaxTree(state).iterate({
805
+ enter: (node) => {
806
+ if (node.name === "Image") {
807
+ const urlNode = node.node.getChild("URL");
808
+ if (urlNode) {
809
+ const hide = state.readOnly || cursor < node.from || cursor > node.to;
810
+ const url = state.sliceDoc(urlNode.from, urlNode.to);
811
+ builder.add(hide ? node.from : node.to, node.to, Decoration4.replace({
812
+ widget: new ImageWidget(url)
813
+ }));
814
+ }
815
+ }
816
+ }
817
+ });
818
+ return builder.finish();
819
+ };
820
+ var ImageWidget = class extends WidgetType2 {
821
+ constructor(_url) {
822
+ super();
823
+ this._url = _url;
824
+ }
825
+ eq(other) {
826
+ return this._url === other?._url;
827
+ }
828
+ toDOM(view) {
829
+ const img = document.createElement("img");
830
+ img.setAttribute("src", this._url);
831
+ img.setAttribute("class", "cm-image");
832
+ return img;
833
+ }
834
+ };
835
+
836
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/link.ts
837
+ import { syntaxTree as syntaxTree2 } from "@codemirror/language";
838
+ import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField3 } from "@codemirror/state";
839
+ import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType3 } from "@codemirror/view";
840
+ var link = (options = {}) => {
841
+ return StateField3.define({
842
+ create: (state) => update2(state, options),
843
+ update: (_, tr) => update2(tr.state, options),
844
+ provide: (field) => EditorView7.decorations.from(field)
845
+ });
846
+ };
847
+ var LinkButton = class extends WidgetType3 {
848
+ constructor(_pos, _url, _onAttach) {
849
+ super();
850
+ this._pos = _pos;
851
+ this._url = _url;
852
+ this._onAttach = _onAttach;
853
+ }
854
+ eq(other) {
855
+ return this._pos === other._pos && this._url === other._url;
856
+ }
857
+ toDOM(view) {
858
+ const el = document.createElement("span");
859
+ this._onAttach(el, this._url);
860
+ return el;
861
+ }
862
+ };
863
+ var LinkText = class extends WidgetType3 {
864
+ constructor(_pos, _text, _url) {
865
+ super();
866
+ this._pos = _pos;
867
+ this._text = _text;
868
+ this._url = _url;
869
+ }
870
+ eq(other) {
871
+ return this._pos === other._pos && this._url === other._url;
872
+ }
873
+ toDOM(view) {
874
+ const link2 = document.createElement("a");
875
+ link2.setAttribute("class", "cm-link");
876
+ link2.textContent = this._text;
877
+ if (this._url) {
878
+ link2.setAttribute("rel", "noreferrer");
879
+ link2.setAttribute("target", "_blank");
880
+ link2.href = this._url;
881
+ } else {
882
+ link2.onclick = () => {
883
+ view.dispatch({
884
+ selection: {
885
+ anchor: this._pos
886
+ }
887
+ });
888
+ };
889
+ }
890
+ return link2;
891
+ }
892
+ };
893
+ var update2 = (state, options) => {
894
+ const builder = new RangeSetBuilder2();
895
+ const cursor = state.selection.main.head;
896
+ syntaxTree2(state).iterate({
897
+ enter: (node) => {
898
+ if (node.name === "Link") {
899
+ const marks2 = node.node.getChildren("LinkMark");
900
+ const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
901
+ const urlNode = node.node.getChild("URL");
902
+ const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
903
+ if (!url) {
904
+ return false;
905
+ }
906
+ if (state.readOnly || cursor < node.from || cursor > node.to) {
907
+ builder.add(node.from, node.to, Decoration5.replace({
908
+ widget: new LinkText(node.from, text, options.link ? url : void 0)
909
+ }));
910
+ }
911
+ if (options.onRender) {
912
+ builder.add(node.to, node.to, Decoration5.replace({
913
+ widget: new LinkButton(node.from, url, options.onRender)
914
+ }));
915
+ }
916
+ return false;
917
+ }
918
+ }
919
+ });
920
+ return builder.finish();
921
+ };
922
+
923
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
924
+ import { StateField as StateField4 } from "@codemirror/state";
925
+ var listener2 = ({ onChange }) => {
926
+ return StateField4.define({
927
+ create: () => null,
928
+ update: (_value, transaction) => {
929
+ if (transaction.docChanged && onChange) {
930
+ onChange(transaction.newDoc.toString());
931
+ }
932
+ return null;
933
+ }
934
+ });
935
+ };
936
+
937
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
938
+ import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
939
+ import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
940
+ import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
941
+ import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
942
+ import { languages } from "@codemirror/language-data";
943
+ import { searchKeymap } from "@codemirror/search";
944
+ import { EditorState } from "@codemirror/state";
945
+ import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
946
+ import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView8, highlightActiveLine, keymap as keymap5, placeholder as placeholder2 } from "@codemirror/view";
947
+
948
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
949
+ import { markdownLanguage } from "@codemirror/lang-markdown";
950
+ import { HighlightStyle } from "@codemirror/language";
951
+ import { tags, styleTags, Tag } from "@lezer/highlight";
952
+ import { Table } from "@lezer/markdown";
953
+ import get2 from "lodash.get";
954
+ import { mx as mx3 } from "@dxos/react-ui-theme";
955
+ var markdownTags = {
956
+ Blockquote: Tag.define(),
957
+ CodeMark: Tag.define(),
958
+ CodeText: Tag.define(),
959
+ EmphasisMark: Tag.define(),
960
+ HeaderMark: Tag.define(),
961
+ HorizontalRule: Tag.define(),
962
+ InlineCode: Tag.define(),
963
+ LinkLabel: Tag.define(),
964
+ LinkReference: Tag.define(),
965
+ ListMark: Tag.define(),
966
+ QuoteMark: Tag.define(),
967
+ URL: Tag.define(),
968
+ // Custom.
969
+ TableCell: Tag.define()
970
+ };
971
+ Table.defineNodes?.forEach((node) => {
972
+ switch (node?.name) {
973
+ case "TableCell": {
974
+ node.style = markdownTags.TableCell;
975
+ break;
976
+ }
977
+ }
978
+ });
979
+ var markdownTagsExtensions = [
980
+ Table,
981
+ {
982
+ props: [
983
+ styleTags(markdownTags)
984
+ ]
985
+ }
986
+ ];
987
+ var markdownHighlightStyle = (readonly) => {
988
+ return HighlightStyle.define([
989
+ {
990
+ tag: [
991
+ tags.keyword,
992
+ tags.name,
993
+ tags.deleted,
994
+ tags.character,
995
+ tags.propertyName,
996
+ tags.macroName,
997
+ tags.color,
998
+ tags.constant(tags.name),
999
+ tags.standard(tags.name),
1000
+ tags.definition(tags.name),
1001
+ tags.separator,
1002
+ tags.typeName,
1003
+ tags.className,
1004
+ tags.number,
1005
+ tags.changed,
1006
+ tags.annotation,
1007
+ tags.modifier,
1008
+ tags.self,
1009
+ tags.namespace,
1010
+ tags.operator,
1011
+ tags.operatorKeyword,
1012
+ tags.escape,
1013
+ tags.regexp,
1014
+ tags.special(tags.string),
1015
+ tags.meta,
1016
+ tags.comment,
1017
+ tags.atom,
1018
+ tags.bool,
1019
+ tags.special(tags.variableName),
1020
+ tags.processingInstruction,
1021
+ tags.string,
1022
+ tags.inserted,
1023
+ tags.invalid
1024
+ ],
1025
+ color: "inherit !important"
1026
+ },
1027
+ // Markdown marks.
1028
+ {
1029
+ tag: [
1030
+ tags.meta,
1031
+ tags.processingInstruction,
1032
+ markdownTags.LinkLabel,
1033
+ markdownTags.LinkReference,
1034
+ markdownTags.ListMark
1035
+ ],
1036
+ class: mark
1037
+ },
1038
+ // Markdown marks.
1039
+ {
1040
+ tag: [
1041
+ markdownTags.CodeMark,
1042
+ markdownTags.HeaderMark,
1043
+ markdownTags.QuoteMark,
1044
+ markdownTags.EmphasisMark
1045
+ ],
1046
+ class: readonly ? "hidden" : mark
1047
+ },
1048
+ // E.g., code block language (after ```).
1049
+ {
1050
+ tag: [
1051
+ tags.function(tags.variableName),
1052
+ tags.labelName
1053
+ ],
1054
+ class: readonly ? "hidden" : codeMark
1055
+ },
1056
+ {
1057
+ tag: [
1058
+ tags.monospace
1059
+ ],
1060
+ class: "font-mono"
1061
+ },
1062
+ // Headings.
1063
+ {
1064
+ tag: tags.heading1,
1065
+ class: heading(1, readonly)
1066
+ },
1067
+ {
1068
+ tag: tags.heading2,
1069
+ class: heading(2, readonly)
1070
+ },
1071
+ {
1072
+ tag: tags.heading3,
1073
+ class: heading(3, readonly)
1074
+ },
1075
+ {
1076
+ tag: tags.heading4,
1077
+ class: heading(4, readonly)
1078
+ },
1079
+ {
1080
+ tag: tags.heading5,
1081
+ class: heading(5, readonly)
1082
+ },
1083
+ {
1084
+ tag: tags.heading6,
1085
+ class: heading(6, readonly)
1086
+ },
1087
+ // Emphasis.
1088
+ {
1089
+ tag: tags.emphasis,
1090
+ class: italic
1091
+ },
1092
+ {
1093
+ tag: tags.strong,
1094
+ class: bold
1095
+ },
1096
+ {
1097
+ tag: tags.strikethrough,
1098
+ class: strikethrough
1099
+ },
1100
+ // Naked URLs.
1101
+ {
1102
+ tag: [
1103
+ markdownTags.URL
1104
+ ],
1105
+ class: inlineUrl
1106
+ },
1107
+ // NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
1108
+ // However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
1109
+ // when a language is specified. In this case, the syntax highlighting extensions will colorize
1110
+ // the code, but all other CSS properties will be inherited.
1111
+ // IMPORTANT: Therefore, the fenced code block will use the base editor font.
1112
+ {
1113
+ tag: [
1114
+ markdownTags.CodeText,
1115
+ markdownTags.InlineCode
1116
+ ],
1117
+ class: code
1118
+ },
1119
+ {
1120
+ tag: [
1121
+ markdownTags.QuoteMark
1122
+ ],
1123
+ class: blockquote
1124
+ },
1125
+ // TODO(burdon): Replace with extension.
1126
+ {
1127
+ tag: [
1128
+ markdownTags.HorizontalRule
1129
+ ],
1130
+ class: mx3(horizontalRule, readonly && "-indent-[100rem]")
1131
+ },
1132
+ // TODO(burdon): Only if being edited.
1133
+ {
1134
+ tag: [
1135
+ markdownTags.TableCell
1136
+ ],
1137
+ class: "font-mono"
1138
+ }
1139
+ ], {
1140
+ scope: markdownLanguage,
1141
+ all: {
1142
+ fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1143
+ }
1144
+ });
1145
+ };
1146
+
1147
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
1148
+ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
1149
+ return [
1150
+ EditorState.allowMultipleSelections.of(true),
1151
+ EditorState.tabSize.of(2),
1152
+ EditorView8.lineWrapping,
1153
+ customKeymap(),
1154
+ bracketMatching2(),
1155
+ closeBrackets2(),
1156
+ crosshairCursor(),
1157
+ dropCursor(),
1158
+ drawSelection2(),
1159
+ highlightActiveLine(),
1160
+ history(),
1161
+ indentOnInput(),
1162
+ _placeholder && placeholder2(_placeholder),
1163
+ // Main extension.
1164
+ // https://github.com/codemirror/lang-markdown
1165
+ // https://codemirror.net/5/mode/markdown/index.html (demo).
1166
+ markdown({
1167
+ // GRM by default (vs strict CommonMark):
1168
+ // Table, TaskList, Strikethrough, and Autolink.
1169
+ // NOTE: This extends the parser; it doesn't affect rendering.
1170
+ // https://github.github.com/gfm
1171
+ // https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
1172
+ base: markdownLanguage2,
1173
+ // Languages for syntax highlighting fenced code blocks.
1174
+ codeLanguages: languages,
1175
+ // Parser extensions.
1176
+ extensions: [
1177
+ // GFM provided by default.
1178
+ markdownTagsExtensions
1179
+ ]
1180
+ }),
1181
+ // https://github.com/codemirror/theme-one-dark
1182
+ themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
1183
+ // Custom styles.
1184
+ syntaxHighlighting2(markdownHighlightStyle(readonly))
1185
+ ].filter(Boolean);
34
1186
  };
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";
1187
+ var customKeymap = () => keymap5.of([
1188
+ // https://codemirror.net/docs/ref/#commands.indentWithTab
1189
+ indentWithTab,
1190
+ // https://codemirror.net/docs/ref/#commands.standardKeymap
1191
+ ...standardKeymap,
1192
+ // https://codemirror.net/docs/ref/#commands.historyKeymap
1193
+ ...historyKeymap,
1194
+ // https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
1195
+ ...closeBracketsKeymap,
1196
+ // https://codemirror.net/docs/ref/#search.searchKeymap
1197
+ ...searchKeymap
1198
+ ]);
41
1199
 
42
- // packages/ui/react-ui-editor/src/styles/tokens.ts
43
- import { tailwindConfig } from "@dxos/react-ui-theme";
44
- var tokens = tailwindConfig({}).theme;
1200
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/mention.ts
1201
+ import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
1202
+ var mention = ({ onSearch }) => {
1203
+ return autocompletion2({
1204
+ closeOnBlur: false,
1205
+ override: [
1206
+ (context) => {
1207
+ const match = context.matchBefore(/@(\w+)?/);
1208
+ if (!match || match.from === match.to && !context.explicit) {
1209
+ return null;
1210
+ }
1211
+ console.log(match);
1212
+ return {
1213
+ from: match.from,
1214
+ options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
1215
+ label: `@${value}`
1216
+ }))
1217
+ };
1218
+ }
1219
+ ]
1220
+ });
1221
+ };
45
1222
 
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"
1223
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/table.ts
1224
+ import { syntaxTree as syntaxTree3 } from "@codemirror/language";
1225
+ import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField5 } from "@codemirror/state";
1226
+ import { Decoration as Decoration6, EditorView as EditorView9, WidgetType as WidgetType4 } from "@codemirror/view";
1227
+ var table = (options = {}) => {
1228
+ return StateField5.define({
1229
+ create: (state) => update3(state, options),
1230
+ update: (_, tr) => update3(tr.state, options),
1231
+ provide: (field) => EditorView9.decorations.from(field)
1232
+ });
1233
+ };
1234
+ var update3 = (state, options) => {
1235
+ const builder = new RangeSetBuilder3();
1236
+ const cursor = state.selection.main.head;
1237
+ const tables = [];
1238
+ const getTable = () => tables[tables.length - 1];
1239
+ const getRow = () => {
1240
+ const table2 = getTable();
1241
+ return table2.rows?.[table2.rows.length - 1];
1242
+ };
1243
+ syntaxTree3(state).iterate({
1244
+ enter: (node) => {
1245
+ switch (node.name) {
1246
+ case "Table": {
1247
+ tables.push({
1248
+ from: node.from,
1249
+ to: node.to
1250
+ });
1251
+ break;
1252
+ }
1253
+ case "TableHeader": {
1254
+ getTable().header = [];
1255
+ break;
1256
+ }
1257
+ case "TableRow": {
1258
+ (getTable().rows ??= []).push([]);
1259
+ break;
1260
+ }
1261
+ case "TableCell": {
1262
+ const row = getRow();
1263
+ if (row) {
1264
+ row.push(state.sliceDoc(node.from, node.to));
1265
+ } else {
1266
+ getTable().header?.push(state.sliceDoc(node.from, node.to));
1267
+ }
1268
+ break;
1269
+ }
1270
+ }
1271
+ }
1272
+ });
1273
+ tables.forEach((table2) => {
1274
+ const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
1275
+ hide && builder.add(table2.from, table2.to, Decoration6.replace({
1276
+ widget: new TableWidget(table2)
1277
+ }));
1278
+ builder.add(table2.from, table2.to, Decoration6.mark({
1279
+ class: "cm-table"
1280
+ }));
1281
+ });
1282
+ return builder.finish();
1283
+ };
1284
+ var TableWidget = class extends WidgetType4 {
1285
+ constructor(_table) {
1286
+ super();
1287
+ this._table = _table;
1288
+ }
1289
+ eq(other) {
1290
+ return this._table.from === other?._table?.from;
1291
+ }
1292
+ toDOM(view) {
1293
+ const table2 = document.createElement("table");
1294
+ {
1295
+ const header = table2.appendChild(document.createElement("thead"));
1296
+ const tr = header.appendChild(document.createElement("tr"));
1297
+ this._table.header?.forEach((cell) => {
1298
+ const th = document.createElement("th");
1299
+ th.setAttribute("class", "cm-table-head");
1300
+ tr.appendChild(th).textContent = cell;
1301
+ });
1302
+ }
1303
+ {
1304
+ const body = table2.appendChild(document.createElement("tbody"));
1305
+ this._table.rows?.forEach((row) => {
1306
+ const tr = body.appendChild(document.createElement("tr"));
1307
+ row.forEach((cell) => {
1308
+ const td = document.createElement("td");
1309
+ td.setAttribute("class", "cm-table-cell");
1310
+ tr.appendChild(td).textContent = cell;
1311
+ });
1312
+ });
1313
+ }
1314
+ return table2;
77
1315
  }
78
1316
  };
79
1317
 
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;
1318
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tasklist.ts
1319
+ import { EditorView as EditorView10, Decoration as Decoration7, WidgetType as WidgetType5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
1320
+ var styles4 = EditorView10.baseTheme({
1321
+ "& .cm-task-item": {
1322
+ paddingLeft: "4px",
1323
+ paddingRight: "8px"
89
1324
  }
90
1325
  });
91
-
92
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkDecoration.ts
93
- import { syntaxTree } from "@codemirror/language";
94
- import { RangeSetBuilder, StateField as StateField2 } from "@codemirror/state";
95
- import { Decoration, EditorView as EditorView2, WidgetType } from "@codemirror/view";
96
- var Link = class extends WidgetType {
97
- constructor(_anchor, _text, _url) {
1326
+ var CheckboxWidget = class extends WidgetType5 {
1327
+ constructor(_pos, _checked, _indent, _onCheck) {
98
1328
  super();
99
- this._anchor = _anchor;
100
- this._text = _text;
101
- this._url = _url;
1329
+ this._pos = _pos;
1330
+ this._checked = _checked;
1331
+ this._indent = _indent;
1332
+ this._onCheck = _onCheck;
102
1333
  }
103
1334
  eq(other) {
104
- return this._text === other.text && this._url === other.url;
1335
+ return this._pos === other._pos && this._checked === other._checked && this._indent === other._indent;
105
1336
  }
106
1337
  toDOM(view) {
107
- const link = document.createElement("a");
108
- link.setAttribute("class", "cm-link");
109
- link.textContent = this._text;
110
- if (this._url) {
111
- link.setAttribute("target", "_blank");
112
- link.href = this._url;
113
- } else {
114
- link.onclick = () => {
115
- view.dispatch({
116
- selection: {
117
- anchor: this._anchor
118
- }
119
- });
1338
+ const wrap = document.createElement("span");
1339
+ wrap.className = "cm-task-item";
1340
+ wrap.setAttribute("aria-hidden", "true");
1341
+ wrap.style.setProperty("margin-left", this._indent * 24 + "px");
1342
+ const input = wrap.appendChild(document.createElement("input"));
1343
+ input.type = "checkbox";
1344
+ input.checked = this._checked;
1345
+ if (!this._onCheck) {
1346
+ input.setAttribute("disabled", "true");
1347
+ }
1348
+ if (this._onCheck) {
1349
+ input.onchange = (event) => {
1350
+ this._onCheck?.(event.target.checked);
1351
+ return true;
120
1352
  };
121
1353
  }
122
- return link;
1354
+ return wrap;
1355
+ }
1356
+ ignoreEvent() {
1357
+ return false;
123
1358
  }
124
1359
  };
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)
1360
+ var tasklist = (options = {}) => {
1361
+ const taskMatcher = new MatchDecorator2({
1362
+ regexp: /^(\s*)- \[([ xX])\]\s/g,
1363
+ decoration: (match, view, pos) => {
1364
+ const indent = Math.floor(match[1].length / 2);
1365
+ const checked = match[2] === "x" || match[2] === "X";
1366
+ return Decoration7.replace({
1367
+ widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
1368
+ const idx = pos + match[0].indexOf("[") + 1;
1369
+ view.dispatch({
1370
+ changes: {
1371
+ from: idx,
1372
+ to: idx + 1,
1373
+ insert: checked2 ? "x" : " "
1374
+ },
1375
+ // TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
1376
+ selection: {
1377
+ anchor: idx + 3
1378
+ }
1379
+ });
1380
+ })
1381
+ });
1382
+ }
130
1383
  });
131
- };
132
- var update = (state, link) => {
133
- const builder = new RangeSetBuilder();
134
- const cursor = state.selection.main.head;
135
- syntaxTree(state).iterate({
136
- 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) : "";
143
- builder.add(node.from, node.to, Decoration.replace({
144
- widget: new Link(node.from, text, link ? url : void 0)
145
- }));
146
- return false;
147
- }
148
- }
149
- return true;
1384
+ const tasks = ViewPlugin3.fromClass(class {
1385
+ constructor(view) {
1386
+ this.tasks = taskMatcher.createDeco(view);
150
1387
  }
1388
+ update(update4) {
1389
+ this.tasks = taskMatcher.updateDeco(update4, this.tasks);
1390
+ }
1391
+ }, {
1392
+ decorations: (value) => value.tasks,
1393
+ provide: (plugin) => EditorView10.atomicRanges.of((view) => {
1394
+ return view.plugin(plugin)?.tasks || Decoration7.none;
1395
+ })
151
1396
  });
152
- return builder.finish();
1397
+ return [
1398
+ tasks,
1399
+ styles4
1400
+ ];
153
1401
  };
154
1402
 
155
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/hyperlink/hyperlinkTooltip.tsx
1403
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/tooltip.tsx
156
1404
  import { hoverTooltip } from "@codemirror/view";
157
1405
  import { tooltipContent } from "@dxos/react-ui-theme";
158
1406
  var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
159
- var createHyperlinkTooltip = (onHover, regexp = markdownLinkRegexp) => hoverTooltip((view, pos) => {
1407
+ var tooltip = ({ onHover, regexp = markdownLinkRegexp }) => hoverTooltip((view, pos) => {
160
1408
  const { from, text } = view.state.doc.lineAt(pos);
161
1409
  const p = pos - from;
162
1410
  let idx = 0;
@@ -182,288 +1430,102 @@ var createHyperlinkTooltip = (onHover, regexp = markdownLinkRegexp) => hoverTool
182
1430
  end: idx + from + match[0].length,
183
1431
  above: true,
184
1432
  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);
1433
+ const el = document.createElement("div");
1434
+ el.className = tooltipContent({}, "pli-2 plb-1");
190
1435
  onHover(el, url);
191
1436
  return {
192
- dom: el
1437
+ dom: el,
1438
+ offset: {
1439
+ x: 0,
1440
+ y: 12
1441
+ }
193
1442
  };
194
1443
  }
195
1444
  };
196
1445
  });
197
1446
 
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
- });
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
-
291
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
292
- import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
293
- import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
294
- import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
295
- import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, foldKeymap, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
296
- import { languages } from "@codemirror/language-data";
297
- import { lintKeymap } from "@codemirror/lint";
298
- import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
299
- import { EditorState } from "@codemirror/state";
300
- 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";
302
-
303
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/tags.ts
304
- import { styleTags, Tag } from "@lezer/highlight";
305
- 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()
317
- };
318
- var markdownTagsExtension = {
319
- 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
- })
333
- ]
334
- };
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
- // },
1447
+ // packages/ui/react-ui-editor/src/components/TextEditor/themes/default.ts
1448
+ import get3 from "lodash.get";
1449
+ var defaultTheme = {
1450
+ //
1451
+ // Main layout:
1452
+ // <div class=".cm-editor .cm-focused">
1453
+ // <div class=".cm-scroller">
1454
+ // <div class=".cm-content" role="textbox" contenteditable="true">
1455
+ // <div class=".cm-line" />
1456
+ // </div>
1457
+ // </div>
1458
+ // </div>
1459
+ //
1460
+ "&": {},
416
1461
  "&.cm-focused": {
417
1462
  outline: "none"
418
1463
  },
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"
1464
+ "& .cm-scroller": {
1465
+ overflow: "visible",
1466
+ fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
438
1467
  },
439
1468
  "& .cm-content": {
440
1469
  padding: 0,
1470
+ // Base font size (otherwise defined by HTML tag, which might be different for storybook).
1471
+ fontSize: "16px"
1472
+ },
1473
+ "&light .cm-content": {
1474
+ color: get3(tokens, "extend.colors.neutral.900", "black"),
441
1475
  caretColor: "black"
442
1476
  },
443
- ".dark & .cm-content": {
1477
+ "&dark .cm-content": {
1478
+ color: get3(tokens, "extend.colors.neutral.100", "white"),
444
1479
  caretColor: "white"
445
1480
  },
446
- "& .cm-cursor": {
447
- borderLeftColor: "black"
1481
+ //
1482
+ // Cursor
1483
+ //
1484
+ "&light .cm-cursor, &light .cm-dropCursor": {
1485
+ borderLeft: "2px solid black"
448
1486
  },
449
- ".dark & .cm-cursor": {
450
- borderLeftColor: "white"
1487
+ "&dark .cm-cursor, &dark .cm-dropCursor": {
1488
+ borderLeft: "2px solid white"
451
1489
  },
452
- ".cm-placeholder": {
453
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1490
+ "& .cm-placeholder": {
1491
+ fontWeight: 100
454
1492
  },
455
- "& .cm-scroller": {
456
- fontFamily: get2(tokens, "fontFamily.mono", []).join(","),
457
- overflow: "visible"
1493
+ //
1494
+ // line
1495
+ //
1496
+ "& .cm-line": {
1497
+ paddingInline: 0
458
1498
  },
1499
+ "& .cm-line *": {},
459
1500
  "& .cm-activeLine": {
460
1501
  backgroundColor: "transparent"
461
1502
  },
462
- ".dark & .cm-activeLine": {
463
- backgroundColor: "transparent"
1503
+ //
1504
+ // selection
1505
+ //
1506
+ "&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground": {
1507
+ background: get3(tokens, "extend.colors.primary.150", "#00ffff")
1508
+ },
1509
+ "&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground": {
1510
+ background: get3(tokens, "extend.colors.primary.850", "#00ffff")
1511
+ },
1512
+ "&light .cm-selectionMatch": {
1513
+ background: get3(tokens, "extend.colors.primary.250", "#00ffff") + "44"
1514
+ },
1515
+ "&dark .cm-selectionMatch": {
1516
+ background: get3(tokens, "extend.colors.primary.600", "#00ffff") + "44"
1517
+ },
1518
+ //
1519
+ // collaboration
1520
+ // TODO(burdon): Review classnames (YJS dependent?)
1521
+ //
1522
+ "&light .cm-ySelection, &light .cm-yLineSelection": {
1523
+ mixBlendMode: "multiply"
1524
+ },
1525
+ "&dark .cm-ySelection, &dark .cm-yLineSelection": {
1526
+ mixBlendMode: "screen"
464
1527
  },
465
1528
  "& .cm-ySelectionInfo": {
466
- fontFamily: get2(tokens, "fontFamily.body", []).join(","),
467
1529
  padding: "2px 4px",
468
1530
  marginBlockStart: "-4px"
469
1531
  },
@@ -471,12 +1533,6 @@ var markdownTheme = {
471
1533
  paddingBlockStart: ".15em",
472
1534
  paddingBlockEnd: ".15em"
473
1535
  },
474
- "& .cm-ySelection, & .cm-yLineSelection": {
475
- mixBlendMode: "multiply"
476
- },
477
- ".dark & .cm-ySelection, .dark & .cm-yLineSelection": {
478
- mixBlendMode: "screen"
479
- },
480
1536
  "& .cm-ySelectionCaret": {
481
1537
  display: "inline-block",
482
1538
  insetBlockStart: ".1em",
@@ -484,18 +1540,80 @@ var markdownTheme = {
484
1540
  verticalAlign: "top"
485
1541
  },
486
1542
  "& .cm-yLineSelection": {
487
- margin: "0"
1543
+ margin: 0
488
1544
  },
489
- ".cm-link": {
490
- color: "rgb(20 89 208)",
1545
+ //
1546
+ // link
1547
+ //
1548
+ "& .cm-link": {
1549
+ color: get3(tokens, "extend.colors.primary.500"),
491
1550
  textDecorationLine: "underline",
492
1551
  textDecorationThickness: "1px",
493
1552
  textUnderlineOffset: "2px",
494
- borderRadius: ".125rem"
1553
+ borderRadius: ".125rem",
1554
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1555
+ },
1556
+ //
1557
+ // tooltip
1558
+ //
1559
+ "& .cm-tooltip": {
1560
+ border: "none"
1561
+ },
1562
+ "& .cm-tooltip-below": {},
1563
+ //
1564
+ // autocomplete
1565
+ //
1566
+ "& .cm-tooltip-autocomplete": {
1567
+ marginTop: "4px",
1568
+ marginLeft: "-3px"
1569
+ },
1570
+ "& .cm-tooltip-autocomplete ul li": {},
1571
+ "& .cm-tooltip-autocomplete ul li[aria-selected]": {},
1572
+ "& .cm-completionIcon": {
1573
+ display: "none"
1574
+ },
1575
+ "& .cm-completionLabel": {
1576
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1577
+ },
1578
+ "& .cm-completionMatchedText": {
1579
+ textDecoration: "none"
1580
+ },
1581
+ //
1582
+ // widgets
1583
+ //
1584
+ "& .cm-widgetBuffer": {
1585
+ display: "none",
1586
+ height: 0
495
1587
  },
496
- // TODO(burdon): Document.
497
- ...Object.keys(get2(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
498
- const height = get2(tokens, [
1588
+ //
1589
+ // table
1590
+ //
1591
+ "& .cm-table *": {
1592
+ fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
1593
+ textDecoration: "none !important"
1594
+ },
1595
+ "& .cm-table-head": {
1596
+ padding: "2px 16px 2px 0px",
1597
+ borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
1598
+ fontWeight: 100,
1599
+ textAlign: "left",
1600
+ color: get3(tokens, "extend.colors.neutral.500")
1601
+ },
1602
+ "& .cm-table-cell": {
1603
+ padding: "2px 16px 2px 0px"
1604
+ },
1605
+ //
1606
+ // image
1607
+ //
1608
+ "& .cm-image": {
1609
+ margin: "0.5rem 0"
1610
+ },
1611
+ //
1612
+ // font size
1613
+ // 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.
1614
+ //
1615
+ ...Object.keys(get3(tokens, "extend.fontSize", {})).reduce((acc, fontSize) => {
1616
+ const height = get3(tokens, [
499
1617
  "extend",
500
1618
  "fontSize",
501
1619
  fontSize,
@@ -512,208 +1630,255 @@ var markdownTheme = {
512
1630
  height
513
1631
  };
514
1632
  return acc;
515
- }, {})
516
- };
517
- var markdownHighlightStyle = HighlightStyle.define([
518
- {
519
- tag: [
520
- tags.keyword,
521
- tags.name,
522
- tags.deleted,
523
- tags.character,
524
- tags.propertyName,
525
- tags.macroName,
526
- tags.color,
527
- tags.constant(tags.name),
528
- tags.standard(tags.name),
529
- tags.definition(tags.name),
530
- tags.separator,
531
- tags.typeName,
532
- tags.className,
533
- tags.number,
534
- tags.changed,
535
- tags.annotation,
536
- tags.modifier,
537
- tags.self,
538
- tags.namespace,
539
- tags.operator,
540
- tags.operatorKeyword,
541
- tags.escape,
542
- tags.regexp,
543
- tags.special(tags.string),
544
- tags.meta,
545
- tags.comment,
546
- tags.atom,
547
- tags.bool,
548
- tags.special(tags.variableName),
549
- tags.processingInstruction,
550
- tags.string,
551
- tags.inserted,
552
- tags.invalid
553
- ],
554
- color: "inherit !important"
555
- },
556
- {
557
- 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
- tags.meta,
583
- tags.processingInstruction
584
- ],
585
- class: mark
586
- },
587
- {
588
- tag: [
589
- markdownTags.codeText,
590
- markdownTags.inlineCode
591
- ],
592
- class: "font-mono"
593
- },
594
- {
595
- tag: tags.emphasis,
596
- class: italic
597
- },
598
- {
599
- tag: tags.heading1,
600
- class: heading[1]
601
- },
602
- {
603
- tag: tags.heading2,
604
- class: heading[2]
605
- },
606
- {
607
- tag: tags.heading3,
608
- class: heading[3]
1633
+ }, {}),
1634
+ /**
1635
+ * Panels
1636
+ * https://github.com/codemirror/search/blob/main/src/search.ts#L745
1637
+ *
1638
+ * Find/replace panel.
1639
+ * <div class="cm-announced">...</div>
1640
+ * <div class="cm-scroller">...</div>
1641
+ * <div class="cm-panels cm-panels-bottom">
1642
+ * <div class="cm-search cm-panel">
1643
+ * <input class="cm-textfield" />
1644
+ * <button class="cm-button">...</button>
1645
+ * <label><input type="checkbox" />...</label>
1646
+ * </div>
1647
+ * </div
1648
+ */
1649
+ "& .cm-panels": {
1650
+ border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`,
1651
+ borderBottom: "none"
609
1652
  },
610
- {
611
- tag: tags.heading4,
612
- class: heading[4]
1653
+ "& .cm-panel": {
1654
+ background: get3(tokens, "extend.colors.neutral.50"),
1655
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
613
1656
  },
614
- {
615
- tag: tags.heading5,
616
- class: heading[5]
1657
+ "& .cm-button": {
1658
+ margin: "4px",
1659
+ fontFamily: get3(tokens, "fontFamily.body", []).join(","),
1660
+ background: get3(tokens, "extend.colors.neutral.100"),
1661
+ border: "none"
617
1662
  },
618
- {
619
- tag: tags.heading6,
620
- class: heading[6]
1663
+ "& .cm-searchMatch": {
1664
+ backgroundColor: get3(tokens, "extend.colors.yellow.100")
621
1665
  },
622
- {
623
- tag: tags.strikethrough,
624
- class: strikethrough
1666
+ "& .cm-searchMatch.cm-searchMatch-selected": {
1667
+ backgroundColor: get3(tokens, "extend.colors.primary.100")
1668
+ }
1669
+ };
1670
+ var textTheme = {
1671
+ "& .cm-scroller": {
1672
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
625
1673
  },
626
- {
627
- tag: tags.strong,
628
- class: bold
1674
+ "& .cm-placeholder": {
1675
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
629
1676
  }
630
- ], {
631
- scope: markdownLanguage,
632
- all: {
633
- fontFamily: get2(tokens, "fontFamily.body", []).join(",")
1677
+ };
1678
+ var markdownTheme = {
1679
+ // NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
1680
+ "& .cm-placeholder": {
1681
+ fontFamily: get3(tokens, "fontFamily.body", []).join(",")
1682
+ }
1683
+ };
1684
+ var codeTheme = {
1685
+ "& .cm-scroller": {
1686
+ fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
1687
+ },
1688
+ "& .cm-placeholder": {
1689
+ fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
634
1690
  }
635
- });
636
-
637
- // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
638
- var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
639
- return [
640
- bracketMatching2(),
641
- closeBrackets2(),
642
- _placeholder && placeholder2(_placeholder),
643
- EditorState.allowMultipleSelections.of(true),
644
- EditorView4.lineWrapping,
645
- // autocompletion(),
646
- crosshairCursor(),
647
- dropCursor(),
648
- drawSelection(),
649
- highlightActiveLine(),
650
- highlightActiveLineGutter(),
651
- highlightSelectionMatches(),
652
- highlightSpecialChars(),
653
- history(),
654
- indentOnInput(),
655
- rectangularSelection(),
656
- keymap.of([
657
- ...closeBracketsKeymap,
658
- // ...completionKeymap,
659
- ...defaultKeymap,
660
- ...foldKeymap,
661
- ...historyKeymap,
662
- ...lintKeymap,
663
- ...searchKeymap,
664
- indentWithTab
665
- ]),
666
- // Main extension.
667
- // https://github.com/codemirror/lang-markdown
668
- markdown({
669
- base: markdownLanguage2,
670
- codeLanguages: languages,
671
- 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.
678
- markdownTagsExtension
679
- ]
680
- }),
681
- // TODO(thure): All but one rule here apply to both themes; rename or refactor.
682
- syntaxHighlighting2(markdownHighlightStyle),
683
- themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2)
684
- ].filter(Boolean);
685
1691
  };
686
1692
 
687
1693
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
688
1694
  import { EditorState as EditorState2 } from "@codemirror/state";
689
- import { EditorView as EditorView5 } from "@codemirror/view";
1695
+ import { EditorView as EditorView11 } from "@codemirror/view";
690
1696
  import { useFocusableGroup } from "@fluentui/react-tabster";
691
1697
  import { vim } from "@replit/codemirror-vim";
692
- import defaultsDeep from "lodash.defaultsdeep";
693
- import get3 from "lodash.get";
1698
+ import defaultsDeep2 from "lodash.defaultsdeep";
694
1699
  import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState } from "react";
695
- import { isDocAccessor as isDocAccessor2 } from "@dxos/echo-schema";
1700
+ import { generateName } from "@dxos/display-name";
696
1701
  import { useThemeContext } from "@dxos/react-ui";
1702
+ import { getColorForValue, inputSurface, mx as mx4 } from "@dxos/react-ui-theme";
1703
+ var EditorModes = [
1704
+ "default",
1705
+ "vim"
1706
+ ];
1707
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
1708
+ const { themeMode } = useThemeContext();
1709
+ const tabsterDOMAttribute = useFocusableGroup({
1710
+ tabBehavior: "limited"
1711
+ });
1712
+ const [root, setRoot] = useState(null);
1713
+ const [state, setState] = useState();
1714
+ const [view, setView] = useState();
1715
+ useImperativeHandle(forwardedRef, () => ({
1716
+ root,
1717
+ state,
1718
+ view
1719
+ }), [
1720
+ view,
1721
+ state,
1722
+ root
1723
+ ]);
1724
+ const { awareness, peer } = model;
1725
+ useEffect2(() => {
1726
+ if (awareness && peer) {
1727
+ awareness.setLocalStateField("user", {
1728
+ name: peer.name ?? generateName(peer.id),
1729
+ color: getColorForValue({
1730
+ value: peer.id,
1731
+ type: "color"
1732
+ }),
1733
+ colorLight: getColorForValue({
1734
+ value: peer.id,
1735
+ themeMode,
1736
+ type: "highlight"
1737
+ })
1738
+ });
1739
+ }
1740
+ }, [
1741
+ awareness,
1742
+ peer,
1743
+ themeMode
1744
+ ]);
1745
+ useEffect2(() => {
1746
+ if (!root) {
1747
+ return;
1748
+ }
1749
+ const state2 = EditorState2.create({
1750
+ doc: model.text(),
1751
+ extensions: [
1752
+ readonly && EditorState2.readOnly.of(readonly),
1753
+ // TODO(burdon): Factor out VIM mode?
1754
+ editorMode === "vim" && vim(),
1755
+ // Theme.
1756
+ // TODO(burdon): Make optional.
1757
+ EditorView11.baseTheme(defaultTheme),
1758
+ EditorView11.theme(slots?.editor?.theme ?? {}),
1759
+ // TODO(burdon): themeMode doesn't change in storybooks.
1760
+ EditorView11.darkTheme.of(themeMode === "dark"),
1761
+ // Storage and replication.
1762
+ model.extension,
1763
+ // Custom.
1764
+ ...extensions
1765
+ ].filter(Boolean)
1766
+ });
1767
+ view?.destroy();
1768
+ setView(new EditorView11({
1769
+ state: state2,
1770
+ parent: root
1771
+ }));
1772
+ setState(state2);
1773
+ return () => {
1774
+ view?.destroy();
1775
+ setView(void 0);
1776
+ setState(void 0);
1777
+ };
1778
+ }, [
1779
+ root,
1780
+ model,
1781
+ themeMode,
1782
+ readonly,
1783
+ editorMode
1784
+ ]);
1785
+ const handleKeyUp = useCallback((event) => {
1786
+ const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
1787
+ switch (key) {
1788
+ case "Enter": {
1789
+ view?.contentDOM.focus();
1790
+ break;
1791
+ }
1792
+ case "Escape": {
1793
+ editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey) && root?.focus();
1794
+ break;
1795
+ }
1796
+ }
1797
+ }, [
1798
+ view,
1799
+ editorMode
1800
+ ]);
1801
+ return /* @__PURE__ */ React.createElement("div", {
1802
+ key: model.id,
1803
+ ref: setRoot,
1804
+ tabIndex: 0,
1805
+ ...slots?.root,
1806
+ ...editorMode !== "vim" && tabsterDOMAttribute,
1807
+ onKeyUp: handleKeyUp
1808
+ });
1809
+ });
1810
+ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
1811
+ const { themeMode } = useThemeContext();
1812
+ const slots = defaultsDeep2({}, _slots, defaultTextSlots);
1813
+ return /* @__PURE__ */ React.createElement(BaseTextEditor, {
1814
+ ref: forwardedRef,
1815
+ readonly,
1816
+ extensions: [
1817
+ basicBundle({
1818
+ readonly,
1819
+ themeMode,
1820
+ placeholder: slots?.editor?.placeholder
1821
+ }),
1822
+ ...extensions
1823
+ ],
1824
+ slots,
1825
+ ...props
1826
+ });
1827
+ });
1828
+ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
1829
+ const { themeMode } = useThemeContext();
1830
+ const slots = defaultsDeep2({}, _slots, defaultMarkdownSlots);
1831
+ return /* @__PURE__ */ React.createElement(BaseTextEditor, {
1832
+ ref: forwardedRef,
1833
+ readonly,
1834
+ extensions: [
1835
+ markdownBundle({
1836
+ readonly,
1837
+ themeMode,
1838
+ placeholder: slots?.editor?.placeholder
1839
+ }),
1840
+ ...extensions
1841
+ ],
1842
+ slots,
1843
+ ...props
1844
+ });
1845
+ });
1846
+ var defaultSlots = {
1847
+ root: {
1848
+ className: mx4("p-2", inputSurface)
1849
+ }
1850
+ };
1851
+ var defaultTextSlots = {
1852
+ ...defaultSlots,
1853
+ editor: {
1854
+ theme: textTheme
1855
+ }
1856
+ };
1857
+ var defaultMarkdownSlots = {
1858
+ ...defaultSlots,
1859
+ editor: {
1860
+ theme: markdownTheme
1861
+ }
1862
+ };
697
1863
 
698
- // packages/ui/react-ui-editor/src/hooks/useCollaboration.ts
699
- import { useEffect, useMemo } from "react";
1864
+ // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
1865
+ import get4 from "lodash.get";
1866
+ import { useEffect as useEffect3, useState as useState2 } from "react";
700
1867
  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";
1868
+ import { invariant as invariant3 } from "@dxos/invariant";
1869
+ import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
705
1870
 
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";
1871
+ // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
1872
+ import { Annotation, Facet, StateEffect as StateEffect2, StateField as StateField6 } from "@codemirror/state";
1873
+ import { ViewPlugin as ViewPlugin4 } from "@codemirror/view";
709
1874
  import * as automerge2 from "@dxos/automerge/automerge";
710
1875
 
711
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/PatchSemaphore.ts
1876
+ // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
712
1877
  import { next as automerge } from "@dxos/automerge/automerge";
713
1878
 
714
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/amToCodemirror.ts
1879
+ // packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
715
1880
  import { ChangeSet } from "@codemirror/state";
716
- var amToCodemirror_default = (view, selection, target, patches) => {
1881
+ var automergeToCodemirror = (view, selection, target, patches) => {
717
1882
  for (const patch of patches) {
718
1883
  const changeSpec = handlePatch(patch, target, view.state);
719
1884
  if (changeSpec != null) {
@@ -818,9 +1983,9 @@ var charPath = (textPath, candidatePath) => {
818
1983
  return null;
819
1984
  };
820
1985
 
821
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/codeMirrorToAm.ts
1986
+ // packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
822
1987
  import { next as am } from "@dxos/automerge/automerge";
823
- var codeMirrorToAm_default = (field, handle, transactions, state) => {
1988
+ var codemirrorToAutomerge = (field, handle, transactions, state) => {
824
1989
  const { lastHeads, path } = state.field(field);
825
1990
  let hasChanges = false;
826
1991
  for (const tr of transactions) {
@@ -841,7 +2006,7 @@ var codeMirrorToAm_default = (field, handle, transactions, state) => {
841
2006
  return newHeads ?? void 0;
842
2007
  };
843
2008
 
844
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/PatchSemaphore.ts
2009
+ // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
845
2010
  var PatchSemaphore = class {
846
2011
  constructor(field) {
847
2012
  this._inReconcile = false;
@@ -864,12 +2029,12 @@ var PatchSemaphore = class {
864
2029
  annotations: reconcileAnnotationType.of(true)
865
2030
  });
866
2031
  }
867
- let newHeads = codeMirrorToAm_default(this._field, handle, transactions, view.state);
2032
+ let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
868
2033
  if (newHeads === null || newHeads === void 0) {
869
2034
  newHeads = automerge.getHeads(handle.docSync());
870
2035
  }
871
2036
  const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
872
- amToCodemirror_default(view, selection, path, diff);
2037
+ automergeToCodemirror(view, selection, path, diff);
873
2038
  view.dispatch({
874
2039
  effects: updateHeads(newHeads),
875
2040
  annotations: reconcileAnnotationType.of({})
@@ -882,8 +2047,8 @@ var PatchSemaphore = class {
882
2047
  }
883
2048
  };
884
2049
 
885
- // packages/ui/react-ui-editor/src/automerge/automerge-plugin/plugin.ts
886
- var effectType = StateEffect.define({});
2050
+ // packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
2051
+ var effectType = StateEffect2.define({});
887
2052
  var updateHeads = (newHeads) => effectType.of({
888
2053
  newHeads
889
2054
  });
@@ -893,7 +2058,7 @@ var semaphoreFacet = Facet.define({
893
2058
  combine: (values) => values.at(-1)
894
2059
  });
895
2060
  var automergePlugin = (handle, path) => {
896
- const stateField = StateField3.define({
2061
+ const stateField = StateField6.define({
897
2062
  create: () => ({
898
2063
  lastHeads: automerge2.getHeads(handle.docSync()),
899
2064
  unreconciledTransactions: [],
@@ -923,7 +2088,7 @@ var automergePlugin = (handle, path) => {
923
2088
  }
924
2089
  });
925
2090
  const semaphore = new PatchSemaphore(stateField);
926
- const viewPlugin = ViewPlugin2.fromClass(class AutomergeCodemirrorViewPlugin {
2091
+ const viewPlugin = ViewPlugin4.fromClass(class AutomergeCodemirrorViewPlugin {
927
2092
  constructor(view) {
928
2093
  this._handleChange = () => {
929
2094
  this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
@@ -931,8 +2096,8 @@ var automergePlugin = (handle, path) => {
931
2096
  this._view = view;
932
2097
  handle.addListener("change", this._handleChange);
933
2098
  }
934
- update(update2) {
935
- if (update2.transactions.length > 0 && update2.transactions.some((t) => !isReconcileTx(t))) {
2099
+ update(update4) {
2100
+ if (update4.transactions.length > 0 && update4.transactions.some((t) => !isReconcileTx(t))) {
936
2101
  queueMicrotask(() => {
937
2102
  this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
938
2103
  });
@@ -953,47 +2118,8 @@ var automergePlugin = (handle, path) => {
953
2118
  var reconcileAnnotationType = Annotation.define();
954
2119
  var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
955
2120
 
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
2121
  // packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
996
- import * as random from "lib0/random";
2122
+ import * as random2 from "lib0/random";
997
2123
  var cursorColors = [
998
2124
  {
999
2125
  color: "#30bced",
@@ -1028,7 +2154,7 @@ var cursorColors = [
1028
2154
  light: "#1be7ff33"
1029
2155
  }
1030
2156
  ];
1031
- var cursorColor = cursorColors[random.uint32() % cursorColors.length];
2157
+ var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
1032
2158
 
1033
2159
  // packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
1034
2160
  import * as decoding from "lib0/decoding";
@@ -1036,7 +2162,7 @@ import * as encoding from "lib0/encoding";
1036
2162
  import { Observable } from "lib0/observable";
1037
2163
  import * as awarenessProtocol from "y-protocols/awareness";
1038
2164
  import { log } from "@dxos/log";
1039
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
2165
+ var __dxlog_file3 = "/home/circleci/project/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
1040
2166
  var messageAwareness = 1;
1041
2167
  var messageQueryAwareness = 3;
1042
2168
  var SpaceAwarenessProvider = class extends Observable {
@@ -1073,7 +2199,7 @@ var SpaceAwarenessProvider = class extends Observable {
1073
2199
  removed,
1074
2200
  origin
1075
2201
  }, {
1076
- F: __dxlog_file,
2202
+ F: __dxlog_file3,
1077
2203
  L: 67,
1078
2204
  S: this,
1079
2205
  C: (f, a) => f(...a)
@@ -1086,7 +2212,7 @@ var SpaceAwarenessProvider = class extends Observable {
1086
2212
  }
1087
2213
  _handleSpaceMessage({ payload }) {
1088
2214
  log("space message", payload, {
1089
- F: __dxlog_file,
2215
+ F: __dxlog_file3,
1090
2216
  L: 79,
1091
2217
  S: this,
1092
2218
  C: (f, a) => f(...a)
@@ -1131,185 +2257,82 @@ var SpaceAwarenessProvider = class extends Observable {
1131
2257
  };
1132
2258
 
1133
2259
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
2260
+ var __dxlog_file4 = "/home/circleci/project/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
1134
2261
  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({
2262
+ const [model, setModel] = useState2(() => createModel({
2263
+ identity,
2264
+ space,
2265
+ text
2266
+ }));
2267
+ useEffect3(() => {
2268
+ setModel(createModel({
2269
+ identity,
1143
2270
  space,
1144
- doc: text.doc,
1145
- channel: `yjs.awareness.${text.id}`
1146
- });
2271
+ text
2272
+ }));
1147
2273
  }, [
1148
2274
  identity,
1149
2275
  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
2276
  text
1164
2277
  ]);
2278
+ return model;
2279
+ };
2280
+ var createModel = (options) => {
2281
+ const { text } = options;
1165
2282
  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;
2283
+ return createAutomergeModel(options);
2284
+ } else {
2285
+ if (!text?.doc) {
2286
+ return void 0;
2287
+ }
2288
+ return createYjsModel(options);
1179
2289
  }
2290
+ };
2291
+ var createYjsModel = ({ identity, space, text }) => {
2292
+ invariant3(text?.doc && text?.content, void 0, {
2293
+ F: __dxlog_file4,
2294
+ L: 81,
2295
+ S: void 0,
2296
+ A: [
2297
+ "text?.doc && text?.content",
2298
+ ""
2299
+ ]
2300
+ });
2301
+ const provider = space ? new SpaceAwarenessProvider({
2302
+ space,
2303
+ doc: text.doc,
2304
+ channel: `yjs.awareness.${text.id}`
2305
+ }) : void 0;
1180
2306
  return {
1181
2307
  id: text.doc.guid,
1182
2308
  content: text.content,
1183
- provider,
2309
+ text: () => text.content.toString(),
2310
+ ranges: [],
2311
+ extension: yCollab(text.content, provider?.awareness),
2312
+ awareness: provider?.awareness,
1184
2313
  peer: identity ? {
1185
2314
  id: identity.identityKey.toHex(),
1186
2315
  name: identity.profile?.displayName
1187
2316
  } : void 0
1188
2317
  };
1189
2318
  };
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
2319
+ var createAutomergeModel = ({ identity, text }) => {
2320
+ const obj = text;
2321
+ const doc = getRawDoc(obj, [
2322
+ obj.field
1264
2323
  ]);
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
- });
2324
+ return {
2325
+ id: obj.id,
2326
+ content: doc,
2327
+ text: () => get4(doc.handle.docSync(), doc.path),
2328
+ ranges: [],
2329
+ extension: automergePlugin(doc.handle, doc.path),
2330
+ peer: identity ? {
2331
+ id: identity.identityKey.toHex(),
2332
+ name: identity.profile?.displayName
2333
+ } : void 0
2334
+ };
2335
+ };
1313
2336
  export {
1314
2337
  BaseTextEditor,
1315
2338
  Doc,
@@ -1318,34 +2341,39 @@ export {
1318
2341
  SpaceAwarenessProvider,
1319
2342
  TextEditor,
1320
2343
  TextKind,
1321
- YText2 as YText,
2344
+ YText,
1322
2345
  YXmlFragment,
2346
+ autocomplete,
1323
2347
  basicBundle,
1324
- basicTheme,
1325
- chalky,
1326
- coral,
1327
- createHyperlinkTooltip,
2348
+ blast,
2349
+ code2 as code,
2350
+ codeTheme,
2351
+ comments,
1328
2352
  cursorColor,
1329
- cyan,
1330
- highlightBackground,
1331
- hyperLinkExtension,
1332
- hyperlinkDecoration,
1333
- hyperlinkStyle,
1334
- hyperlinkWidget,
1335
- invalid,
1336
- ivory,
1337
- malibu,
2353
+ defaultMarkdownSlots,
2354
+ defaultOptions,
2355
+ defaultSlots,
2356
+ defaultTextSlots,
2357
+ defaultTheme,
2358
+ demo,
2359
+ highlight,
2360
+ highlightDecorations,
2361
+ highlightStateField,
2362
+ image,
2363
+ link,
2364
+ listener2 as listener,
1338
2365
  markdownBundle,
1339
2366
  markdownHighlightStyle,
2367
+ markdownTags,
2368
+ markdownTagsExtensions,
1340
2369
  markdownTheme,
1341
- onChangeExtension,
1342
- sage,
1343
- stone,
2370
+ mention,
2371
+ table,
1344
2372
  tags2 as tags,
1345
- tooltipBackground,
1346
- useCollaboration,
1347
- useTextModel,
1348
- violet,
1349
- whiskey
2373
+ tasklist,
2374
+ textTheme,
2375
+ tooltip,
2376
+ useHighlights,
2377
+ useTextModel
1350
2378
  };
1351
2379
  //# sourceMappingURL=index.mjs.map