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