@dxos/react-ui-editor 0.3.11-main.6d5715f → 0.3.11-main.870164f
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 +961 -1406
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -3
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/util.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor → hooks/automerge}/automerge.stories.d.ts +1 -6
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/handle.d.ts +9 -0
- package/dist/types/src/hooks/automerge/handle.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/index.d.ts +3 -0
- package/dist/types/src/hooks/automerge/index.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/plugin.d.ts +26 -0
- package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -0
- package/dist/types/src/{extensions → hooks}/automerge/semaphore.d.ts +4 -4
- package/dist/types/src/hooks/automerge/semaphore.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/update-automerge.d.ts +6 -0
- package/dist/types/src/hooks/automerge/update-automerge.d.ts.map +1 -0
- package/dist/types/src/hooks/automerge/update-codemirror.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +0 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +7 -8
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/hooks/yjs/cursors.d.ts.map +1 -0
- package/dist/types/src/hooks/yjs/index.d.ts +3 -0
- package/dist/types/src/hooks/yjs/index.d.ts.map +1 -0
- package/dist/types/src/hooks/{yjs.d.ts → yjs/space-provider.d.ts} +8 -8
- package/dist/types/src/hooks/yjs/space-provider.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor → hooks/yjs}/yjs.stories.d.ts +1 -1
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/yjs/yjs.test.d.ts.map +1 -0
- package/dist/types/src/styles/index.d.ts +0 -1
- package/dist/types/src/styles/index.d.ts.map +1 -1
- package/dist/types/src/testing/replicator.d.ts +2 -2
- package/dist/types/src/testing/replicator.d.ts.map +1 -1
- package/package.json +21 -22
- package/src/components/TextEditor/TextEditor.tsx +1 -1
- package/src/components/TextEditor/codemirror.stories.ts +2 -3
- package/src/extensions/comments.ts +11 -27
- package/src/extensions/index.ts +0 -3
- package/src/{components/TextEditor → hooks/automerge}/automerge.stories.tsx +6 -66
- package/src/hooks/automerge/handle.ts +14 -0
- package/src/hooks/automerge/index.ts +6 -0
- package/src/{extensions/automerge/automerge.ts → hooks/automerge/plugin.ts} +58 -20
- package/src/{extensions → hooks}/automerge/semaphore.ts +12 -14
- package/src/{extensions → hooks}/automerge/update-automerge.ts +6 -5
- package/src/{extensions → hooks}/automerge/update-codemirror.ts +5 -13
- package/src/hooks/index.ts +0 -2
- package/src/hooks/useTextModel.ts +93 -19
- package/src/hooks/yjs/index.ts +6 -0
- package/src/hooks/{yjs.ts → yjs/space-provider.ts} +19 -71
- package/src/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +1 -1
- package/src/{extensions → hooks}/yjs/yjs.test.ts +25 -1
- package/src/styles/index.ts +0 -1
- package/src/testing/replicator.ts +15 -10
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts +0 -9
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +0 -5
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +0 -26
- package/dist/types/src/extensions/automerge/defs.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/index.d.ts +0 -3
- package/dist/types/src/extensions/automerge/index.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +0 -5
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness.d.ts +0 -46
- package/dist/types/src/extensions/awareness.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -3
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/awareness-provider.d.ts +0 -28
- package/dist/types/src/hooks/awareness-provider.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/styles/cursors.d.ts.map +0 -1
- package/dist/types/src/util/cursor.d.ts +0 -17
- package/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/index.d.ts +0 -3
- package/dist/types/src/util/index.d.ts.map +0 -1
- package/dist/types/src/util/util.d.ts.map +0 -1
- package/src/extensions/automerge/cursor.ts +0 -51
- package/src/extensions/automerge/defs.ts +0 -62
- package/src/extensions/automerge/index.ts +0 -6
- package/src/extensions/awareness.ts +0 -316
- package/src/extensions/yjs/cursor.ts +0 -21
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -52
- package/src/hooks/awareness-provider.ts +0 -120
- package/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- /package/dist/types/src/{util → extensions}/util.d.ts +0 -0
- /package/dist/types/src/{extensions → hooks}/automerge/update-codemirror.d.ts +0 -0
- /package/dist/types/src/{styles → hooks/yjs}/cursors.d.ts +0 -0
- /package/dist/types/src/{extensions → hooks}/yjs/yjs.test.d.ts +0 -0
- /package/src/{util → extensions}/util.ts +0 -0
- /package/src/{styles → hooks/yjs}/cursors.ts +0 -0
|
@@ -7,11 +7,11 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
7
7
|
|
|
8
8
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
9
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
-
import { EditorView as
|
|
10
|
+
import { EditorView as EditorView12 } from "@codemirror/view";
|
|
11
11
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useState as useState2 } from "react";
|
|
15
15
|
import { generateName } from "@dxos/display-name";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
17
|
import { getColorForValue, inputSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
@@ -49,891 +49,742 @@ var autocomplete = ({ onSearch }) => {
|
|
|
49
49
|
];
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
53
|
-
import {
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
52
|
+
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
53
|
+
import { closeBrackets } from "@codemirror/autocomplete";
|
|
54
|
+
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
55
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
56
|
+
import { drawSelection, EditorView, placeholder } from "@codemirror/view";
|
|
57
|
+
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
58
|
+
EditorView.lineWrapping,
|
|
59
|
+
// TODO(burdon): Compare with minimalSetup.
|
|
60
|
+
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
61
|
+
bracketMatching(),
|
|
62
|
+
closeBrackets(),
|
|
63
|
+
drawSelection(),
|
|
64
|
+
_placeholder && placeholder(_placeholder),
|
|
65
|
+
// TODO(burdon): Is this required?
|
|
66
|
+
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
67
|
+
].filter(Boolean);
|
|
56
68
|
|
|
57
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
58
|
-
import
|
|
59
|
-
import
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
return automerge.getCursor(doc, path.slice(), pos);
|
|
69
|
+
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
70
|
+
import { EditorView as EditorView2, keymap as keymap2 } from "@codemirror/view";
|
|
71
|
+
import defaultsDeep from "lodash.defaultsdeep";
|
|
72
|
+
import { invariant } from "@dxos/invariant";
|
|
73
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
74
|
+
var defaultOptions = {
|
|
75
|
+
effect: 2,
|
|
76
|
+
maxParticles: 200,
|
|
77
|
+
particleGravity: 0.08,
|
|
78
|
+
particleAlphaFadeout: 0.996,
|
|
79
|
+
particleSize: {
|
|
80
|
+
min: 2,
|
|
81
|
+
max: 8
|
|
72
82
|
},
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return automerge.getCursorPosition(doc, path.slice(), cursor);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
94
|
-
import { Annotation, StateEffect } from "@codemirror/state";
|
|
95
|
-
var effectType = StateEffect.define({});
|
|
96
|
-
var updateHeads = (newHeads) => effectType.of({
|
|
97
|
-
newHeads
|
|
98
|
-
});
|
|
99
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
100
|
-
var getPath = (state, field) => state.field(field).path;
|
|
101
|
-
var reconcileAnnotationType = Annotation.define();
|
|
102
|
-
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
103
|
-
|
|
104
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
105
|
-
import { next as automerge2 } from "@dxos/automerge/automerge";
|
|
106
|
-
|
|
107
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
108
|
-
import { next as am } from "@dxos/automerge/automerge";
|
|
109
|
-
var updateAutomerge = (field, handle, transactions, state) => {
|
|
110
|
-
const { lastHeads, path } = state.field(field);
|
|
111
|
-
let hasChanges = false;
|
|
112
|
-
for (const tr of transactions) {
|
|
113
|
-
tr.changes.iterChanges(() => {
|
|
114
|
-
hasChanges = true;
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
if (!hasChanges) {
|
|
118
|
-
return void 0;
|
|
119
|
-
}
|
|
120
|
-
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
121
|
-
for (const tr of transactions) {
|
|
122
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
123
|
-
am.splice(doc, path, fromA, toA - fromA, inserted.toString());
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
return newHeads ?? void 0;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/update-codemirror.ts
|
|
131
|
-
import { ChangeSet } from "@codemirror/state";
|
|
132
|
-
var updateCodeMirror = (view, selection, target, patches) => {
|
|
133
|
-
for (const patch of patches) {
|
|
134
|
-
const changeSpec = handlePatch(patch, target, view.state);
|
|
135
|
-
if (changeSpec != null) {
|
|
136
|
-
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
|
137
|
-
selection = selection.map(changeSet, 1);
|
|
138
|
-
view.dispatch({
|
|
139
|
-
changes: changeSet,
|
|
140
|
-
annotations: reconcileAnnotationType.of({})
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
view.dispatch({
|
|
145
|
-
selection,
|
|
146
|
-
annotations: reconcileAnnotationType.of({})
|
|
147
|
-
});
|
|
148
|
-
};
|
|
149
|
-
var handlePatch = (patch, target, state) => {
|
|
150
|
-
if (patch.action === "insert") {
|
|
151
|
-
return handleInsert(target, patch);
|
|
152
|
-
} else if (patch.action === "splice") {
|
|
153
|
-
return handleSplice(target, patch);
|
|
154
|
-
} else if (patch.action === "del") {
|
|
155
|
-
return handleDel(target, patch);
|
|
156
|
-
} else if (patch.action === "put") {
|
|
157
|
-
return handlePut(target, patch, state);
|
|
158
|
-
} else {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
var handleInsert = (target, patch) => {
|
|
163
|
-
const index = charPath(target, patch.path);
|
|
164
|
-
if (index == null) {
|
|
165
|
-
return [];
|
|
166
|
-
}
|
|
167
|
-
const text = patch.values.map((v) => v ? v.toString() : "").join("");
|
|
168
|
-
return [
|
|
169
|
-
{
|
|
170
|
-
from: index,
|
|
171
|
-
to: index,
|
|
172
|
-
insert: text
|
|
173
|
-
}
|
|
174
|
-
];
|
|
175
|
-
};
|
|
176
|
-
var handleSplice = (target, patch) => {
|
|
177
|
-
const index = charPath(target, patch.path);
|
|
178
|
-
if (index == null) {
|
|
179
|
-
return [];
|
|
180
|
-
}
|
|
181
|
-
return [
|
|
182
|
-
{
|
|
183
|
-
from: index,
|
|
184
|
-
insert: patch.value
|
|
185
|
-
}
|
|
186
|
-
];
|
|
187
|
-
};
|
|
188
|
-
var handleDel = (target, patch) => {
|
|
189
|
-
const index = charPath(target, patch.path);
|
|
190
|
-
if (index == null) {
|
|
191
|
-
return [];
|
|
192
|
-
}
|
|
193
|
-
const length = patch.length || 1;
|
|
194
|
-
return [
|
|
195
|
-
{
|
|
196
|
-
from: index,
|
|
197
|
-
to: index + length
|
|
198
|
-
}
|
|
199
|
-
];
|
|
83
|
+
particleNumRange: {
|
|
84
|
+
min: 5,
|
|
85
|
+
max: 10
|
|
86
|
+
},
|
|
87
|
+
particleVelocityRange: {
|
|
88
|
+
x: [
|
|
89
|
+
-1,
|
|
90
|
+
1
|
|
91
|
+
],
|
|
92
|
+
y: [
|
|
93
|
+
-3.5,
|
|
94
|
+
-1.5
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
particleShrinkRate: 0.95,
|
|
98
|
+
shakeIntensity: 5
|
|
200
99
|
};
|
|
201
|
-
var
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
100
|
+
var blast = (options = defaultOptions) => {
|
|
101
|
+
let blaster;
|
|
102
|
+
let last = 0;
|
|
103
|
+
const getPoint = (view, pos) => {
|
|
104
|
+
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
105
|
+
const element = document.elementFromPoint(x, y);
|
|
106
|
+
const { offsetLeft: left = 0, offsetTop: top = 0 } = view.scrollDOM.parentElement ?? {};
|
|
107
|
+
const point = {
|
|
108
|
+
x: x - left,
|
|
109
|
+
y: y - top
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
element,
|
|
113
|
+
point
|
|
114
|
+
};
|
|
115
|
+
};
|
|
213
116
|
return [
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
return null;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
238
|
-
var PatchSemaphore = class {
|
|
239
|
-
constructor(_field) {
|
|
240
|
-
this._field = _field;
|
|
241
|
-
this._inReconcile = false;
|
|
242
|
-
this._queue = [];
|
|
243
|
-
this.reconcile = (handle, view) => {
|
|
244
|
-
if (this._inReconcile) {
|
|
245
|
-
return;
|
|
117
|
+
// Cursor moved.
|
|
118
|
+
EditorView2.updateListener.of((update4) => {
|
|
119
|
+
if (blaster?.node !== update4.view.scrollDOM) {
|
|
120
|
+
if (blaster) {
|
|
121
|
+
blaster.destroy();
|
|
122
|
+
}
|
|
123
|
+
blaster = new Blaster(update4.view.scrollDOM, defaultsDeep({
|
|
124
|
+
particleGravity: 0.2,
|
|
125
|
+
particleShrinkRate: 0.995,
|
|
126
|
+
color: () => [
|
|
127
|
+
100 + Math.random() * 100,
|
|
128
|
+
0,
|
|
129
|
+
0
|
|
130
|
+
]
|
|
131
|
+
}, options, defaultOptions));
|
|
132
|
+
blaster.initialize();
|
|
133
|
+
blaster.start();
|
|
134
|
+
} else {
|
|
135
|
+
blaster.resize();
|
|
246
136
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
changes: inverted,
|
|
258
|
-
annotations: reconcileAnnotationType.of(true)
|
|
259
|
-
});
|
|
137
|
+
const current = update4.state.selection.main.head;
|
|
138
|
+
if (current !== last) {
|
|
139
|
+
last = current;
|
|
140
|
+
const { element, point } = getPoint(update4.view, current - 1);
|
|
141
|
+
if (element && point) {
|
|
142
|
+
blaster.spawn({
|
|
143
|
+
element,
|
|
144
|
+
point
|
|
145
|
+
});
|
|
146
|
+
}
|
|
260
147
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
148
|
+
}),
|
|
149
|
+
keymap2.of([
|
|
150
|
+
{
|
|
151
|
+
any: (_, event) => {
|
|
152
|
+
if (blaster) {
|
|
153
|
+
if (event.key === "Enter" && event.shiftKey) {
|
|
154
|
+
blaster.shake({
|
|
155
|
+
time: 0.8
|
|
156
|
+
});
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
264
162
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
163
|
+
])
|
|
164
|
+
];
|
|
165
|
+
};
|
|
166
|
+
var Blaster = class {
|
|
167
|
+
constructor(_node, _options) {
|
|
168
|
+
this._node = _node;
|
|
169
|
+
this._options = _options;
|
|
170
|
+
this._running = false;
|
|
171
|
+
this._shakeTime = 0;
|
|
172
|
+
this._shakeTimeMax = 0;
|
|
173
|
+
this._particles = [];
|
|
174
|
+
this._particlePointer = 0;
|
|
175
|
+
this._lastPoint = {
|
|
176
|
+
x: 0,
|
|
177
|
+
y: 0
|
|
272
178
|
};
|
|
179
|
+
this.shake = throttle(({ time }) => {
|
|
180
|
+
this._shakeTime = this._shakeTimeMax || time;
|
|
181
|
+
this._shakeTimeMax = time;
|
|
182
|
+
}, 100);
|
|
183
|
+
this.spawn = throttle(({ element, point }) => {
|
|
184
|
+
const color = getRGBComponents(element, this._options.color);
|
|
185
|
+
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
186
|
+
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
187
|
+
this._lastPoint = point;
|
|
188
|
+
for (let i = numParticles; i--; i > 0) {
|
|
189
|
+
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
190
|
+
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
191
|
+
}
|
|
192
|
+
}, 100);
|
|
193
|
+
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
273
194
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
toCursor: (position) => position.toString(),
|
|
280
|
-
fromCursor: (cursor) => parseInt(cursor)
|
|
281
|
-
};
|
|
282
|
-
var CursorConverter = Facet.define({
|
|
283
|
-
combine: (providers) => providers[0] ?? DEFAULT_CURSOR_CONVERTER
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// packages/ui/react-ui-editor/src/util/util.ts
|
|
287
|
-
import { log } from "@dxos/log";
|
|
288
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
289
|
-
var callbackWrapper = (fn) => (...args) => {
|
|
290
|
-
try {
|
|
291
|
-
return fn(...args);
|
|
292
|
-
} catch (error) {
|
|
293
|
-
log.catch(error, void 0, {
|
|
195
|
+
get node() {
|
|
196
|
+
return this._node;
|
|
197
|
+
}
|
|
198
|
+
initialize() {
|
|
199
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
294
200
|
F: __dxlog_file,
|
|
295
|
-
L:
|
|
296
|
-
S:
|
|
297
|
-
|
|
201
|
+
L: 138,
|
|
202
|
+
S: this,
|
|
203
|
+
A: [
|
|
204
|
+
"!this._canvas && !this._ctx",
|
|
205
|
+
""
|
|
206
|
+
]
|
|
298
207
|
});
|
|
208
|
+
this._canvas = document.createElement("canvas");
|
|
209
|
+
this._canvas.id = "code-blast-canvas";
|
|
210
|
+
this._canvas.style.position = "absolute";
|
|
211
|
+
this._canvas.style.zIndex = "0";
|
|
212
|
+
this._canvas.style.pointerEvents = "none";
|
|
213
|
+
this._ctx = this._canvas.getContext("2d");
|
|
214
|
+
const parent = this._node.parentElement?.parentElement;
|
|
215
|
+
parent?.appendChild(this._canvas);
|
|
216
|
+
this.resize();
|
|
299
217
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
lastHeads: value.lastHeads,
|
|
316
|
-
unreconciledTransactions: value.unreconciledTransactions.slice(),
|
|
317
|
-
path: path.slice()
|
|
318
|
-
};
|
|
319
|
-
let clearUnreconciled = false;
|
|
320
|
-
for (const effect of tr.effects) {
|
|
321
|
-
if (effect.is(effectType)) {
|
|
322
|
-
result.lastHeads = effect.value.newHeads;
|
|
323
|
-
clearUnreconciled = true;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
if (clearUnreconciled) {
|
|
327
|
-
result.unreconciledTransactions = [];
|
|
328
|
-
} else {
|
|
329
|
-
if (!isReconcileTx(tr)) {
|
|
330
|
-
result.unreconciledTransactions.push(tr);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
return result;
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
const semaphore = new PatchSemaphore(stateField);
|
|
337
|
-
const viewPlugin = ViewPlugin.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
338
|
-
constructor(_view) {
|
|
339
|
-
this._view = _view;
|
|
340
|
-
this._handleChange = () => {
|
|
341
|
-
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
342
|
-
};
|
|
343
|
-
handle.addListener("change", this._handleChange);
|
|
344
|
-
}
|
|
345
|
-
update(update4) {
|
|
346
|
-
if (update4.transactions.length > 0 && update4.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
347
|
-
queueMicrotask(() => {
|
|
348
|
-
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
destroy() {
|
|
353
|
-
handle.addListener("change", this._handleChange);
|
|
218
|
+
destroy() {
|
|
219
|
+
this.stop();
|
|
220
|
+
if (this._canvas) {
|
|
221
|
+
this._canvas.remove();
|
|
222
|
+
this._canvas = void 0;
|
|
223
|
+
this._ctx = void 0;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
resize() {
|
|
227
|
+
if (this._node.parentElement && this._canvas) {
|
|
228
|
+
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
229
|
+
this._canvas.style.top = `${y}px`;
|
|
230
|
+
this._canvas.style.left = `${x}px`;
|
|
231
|
+
this._canvas.width = width;
|
|
232
|
+
this._canvas.height = height;
|
|
354
233
|
}
|
|
355
|
-
});
|
|
356
|
-
return {
|
|
357
|
-
extension: [
|
|
358
|
-
CursorConverter.of(cursorConverter(handle, path)),
|
|
359
|
-
semaphoreFacet.of(semaphore),
|
|
360
|
-
stateField,
|
|
361
|
-
viewPlugin
|
|
362
|
-
]
|
|
363
|
-
};
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
367
|
-
import { Annotation as Annotation2, Facet as Facet3, RangeSet } from "@codemirror/state";
|
|
368
|
-
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
369
|
-
import { Event } from "@dxos/async";
|
|
370
|
-
import { Context } from "@dxos/context";
|
|
371
|
-
var dummyProvider = {
|
|
372
|
-
remoteStateChange: new Event(),
|
|
373
|
-
open: () => {
|
|
374
|
-
},
|
|
375
|
-
close: () => {
|
|
376
|
-
},
|
|
377
|
-
update: () => {
|
|
378
|
-
},
|
|
379
|
-
getRemoteStates: () => []
|
|
380
|
-
};
|
|
381
|
-
var AwarenessProvider = Facet3.define({
|
|
382
|
-
combine: (providers) => providers[0] ?? dummyProvider
|
|
383
|
-
});
|
|
384
|
-
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
385
|
-
var awareness = (provider = dummyProvider) => {
|
|
386
|
-
return [
|
|
387
|
-
AwarenessProvider.of(provider),
|
|
388
|
-
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
389
|
-
decorations: (value) => value.decorations
|
|
390
|
-
}),
|
|
391
|
-
styles
|
|
392
|
-
];
|
|
393
|
-
};
|
|
394
|
-
var RemoteSelectionsDecorator = class {
|
|
395
|
-
constructor(view) {
|
|
396
|
-
this.decorations = RangeSet.of([]);
|
|
397
|
-
this._ctx = new Context();
|
|
398
|
-
this._lastAnchor = void 0;
|
|
399
|
-
this._lastHead = void 0;
|
|
400
|
-
this._cursorConverter = view.state.facet(CursorConverter);
|
|
401
|
-
this._provider = view.state.facet(AwarenessProvider);
|
|
402
|
-
this._provider.open();
|
|
403
|
-
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
404
|
-
view.dispatch({
|
|
405
|
-
annotations: [
|
|
406
|
-
RemoteSelectionChangedAnnotation.of([])
|
|
407
|
-
]
|
|
408
|
-
});
|
|
409
|
-
});
|
|
410
234
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
235
|
+
start() {
|
|
236
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
237
|
+
F: __dxlog_file,
|
|
238
|
+
L: 177,
|
|
239
|
+
S: this,
|
|
240
|
+
A: [
|
|
241
|
+
"this._canvas && this._ctx",
|
|
242
|
+
""
|
|
243
|
+
]
|
|
244
|
+
});
|
|
245
|
+
this._running = true;
|
|
246
|
+
this.loop();
|
|
414
247
|
}
|
|
415
|
-
|
|
416
|
-
this.
|
|
417
|
-
this.
|
|
248
|
+
stop() {
|
|
249
|
+
this._running = false;
|
|
250
|
+
this._node.style.transform = "translate(0px, 0px)";
|
|
418
251
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const { anchor = void 0, head = void 0 } = hasFocus ? update4.state.selection.main : {};
|
|
422
|
-
if (this._lastAnchor === anchor && this._lastHead === head) {
|
|
252
|
+
loop() {
|
|
253
|
+
if (!this._running || !this._canvas || !this._ctx) {
|
|
423
254
|
return;
|
|
424
255
|
}
|
|
425
|
-
this.
|
|
426
|
-
|
|
427
|
-
this.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
256
|
+
this._ctx.clearRect(0, 0, this._canvas.width ?? 0, this._canvas.height ?? 0);
|
|
257
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
258
|
+
this._lastTime ??= now;
|
|
259
|
+
const dt = (now - this._lastTime) / 1e3;
|
|
260
|
+
this._lastTime = now;
|
|
261
|
+
if (this._shakeTime > 0) {
|
|
262
|
+
this._shakeTime -= dt;
|
|
263
|
+
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
264
|
+
const shakeX = random(-magnitude, magnitude);
|
|
265
|
+
const shakeY = random(-magnitude, magnitude);
|
|
266
|
+
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
267
|
+
}
|
|
268
|
+
this.drawParticles();
|
|
269
|
+
requestAnimationFrame(this.loop.bind(this));
|
|
270
|
+
}
|
|
271
|
+
drawParticles() {
|
|
272
|
+
for (let i = this._particles.length; i--; i > 0) {
|
|
273
|
+
const particle = this._particles[i];
|
|
274
|
+
if (!particle) {
|
|
439
275
|
continue;
|
|
440
276
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
const startLine = update4.view.state.doc.lineAt(start);
|
|
444
|
-
const endLine = update4.view.state.doc.lineAt(end);
|
|
445
|
-
const color = state.info.color ?? "#30bced";
|
|
446
|
-
const lightColor = state.info.lightColor ?? color + "33";
|
|
447
|
-
if (startLine.number === endLine.number) {
|
|
448
|
-
decorations.push({
|
|
449
|
-
from: start,
|
|
450
|
-
to: end,
|
|
451
|
-
value: Decoration.mark({
|
|
452
|
-
attributes: {
|
|
453
|
-
style: `background-color: ${lightColor}`
|
|
454
|
-
},
|
|
455
|
-
class: "cm-ySelection"
|
|
456
|
-
})
|
|
457
|
-
});
|
|
458
|
-
} else {
|
|
459
|
-
decorations.push({
|
|
460
|
-
from: start,
|
|
461
|
-
to: startLine.from + startLine.length,
|
|
462
|
-
value: Decoration.mark({
|
|
463
|
-
attributes: {
|
|
464
|
-
style: `background-color: ${color}`
|
|
465
|
-
},
|
|
466
|
-
class: "cm-ySelection"
|
|
467
|
-
})
|
|
468
|
-
});
|
|
469
|
-
decorations.push({
|
|
470
|
-
from: endLine.from,
|
|
471
|
-
to: end,
|
|
472
|
-
value: Decoration.mark({
|
|
473
|
-
attributes: {
|
|
474
|
-
style: `background-color: ${color}`
|
|
475
|
-
},
|
|
476
|
-
class: "cm-ySelection"
|
|
477
|
-
})
|
|
478
|
-
});
|
|
479
|
-
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
480
|
-
const linePos = update4.view.state.doc.line(i).from;
|
|
481
|
-
decorations.push({
|
|
482
|
-
from: linePos,
|
|
483
|
-
to: linePos,
|
|
484
|
-
value: Decoration.line({
|
|
485
|
-
attributes: {
|
|
486
|
-
style: `background-color: ${color}`,
|
|
487
|
-
class: "cm-yLineSelection"
|
|
488
|
-
}
|
|
489
|
-
})
|
|
490
|
-
});
|
|
491
|
-
}
|
|
277
|
+
if (particle.alpha < 0.01 || particle.size <= 0.5) {
|
|
278
|
+
continue;
|
|
492
279
|
}
|
|
493
|
-
|
|
494
|
-
from: head,
|
|
495
|
-
to: head,
|
|
496
|
-
value: Decoration.widget({
|
|
497
|
-
side: head - anchor > 0 ? -1 : 1,
|
|
498
|
-
block: false,
|
|
499
|
-
widget: new RemoteCaretWidget(state.info.displayName ?? "Anonymous", color)
|
|
500
|
-
})
|
|
501
|
-
});
|
|
280
|
+
this._effect.update(this._ctx, particle);
|
|
502
281
|
}
|
|
503
|
-
this.decorations = Decoration.set(decorations, true);
|
|
504
282
|
}
|
|
505
283
|
};
|
|
506
|
-
var
|
|
507
|
-
constructor(
|
|
508
|
-
|
|
509
|
-
this.name = name;
|
|
510
|
-
this.color = color;
|
|
511
|
-
this.name = name;
|
|
512
|
-
this.color = color;
|
|
284
|
+
var Effect = class {
|
|
285
|
+
constructor(_options) {
|
|
286
|
+
this._options = _options;
|
|
513
287
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
span.appendChild(document.createTextNode("\u2060"));
|
|
527
|
-
span.appendChild(info);
|
|
528
|
-
span.appendChild(document.createTextNode("\u2060"));
|
|
529
|
-
return span;
|
|
288
|
+
};
|
|
289
|
+
var Effect1 = class extends Effect {
|
|
290
|
+
create(x, y, color) {
|
|
291
|
+
return {
|
|
292
|
+
x,
|
|
293
|
+
y: y + 10,
|
|
294
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
295
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
296
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
297
|
+
color,
|
|
298
|
+
alpha: 1
|
|
299
|
+
};
|
|
530
300
|
}
|
|
531
|
-
|
|
532
|
-
|
|
301
|
+
update(ctx, particle) {
|
|
302
|
+
particle.vy += this._options.particleGravity;
|
|
303
|
+
particle.x += particle.vx;
|
|
304
|
+
particle.y += particle.vy;
|
|
305
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
306
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
307
|
+
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
533
308
|
}
|
|
534
|
-
|
|
535
|
-
|
|
309
|
+
};
|
|
310
|
+
var Effect2 = class extends Effect {
|
|
311
|
+
create(x, y, color) {
|
|
312
|
+
return {
|
|
313
|
+
x,
|
|
314
|
+
y: y + 10,
|
|
315
|
+
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
316
|
+
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
317
|
+
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
318
|
+
color,
|
|
319
|
+
alpha: 1,
|
|
320
|
+
theta: random(0, 360) * Math.PI / 180,
|
|
321
|
+
drag: 0.92,
|
|
322
|
+
wander: 0.15
|
|
323
|
+
};
|
|
536
324
|
}
|
|
537
|
-
|
|
538
|
-
|
|
325
|
+
update(ctx, particle) {
|
|
326
|
+
particle.vy += this._options.particleGravity;
|
|
327
|
+
particle.x += particle.vx;
|
|
328
|
+
particle.y += particle.vy;
|
|
329
|
+
particle.vx *= particle.drag;
|
|
330
|
+
particle.vy *= particle.drag;
|
|
331
|
+
particle.theta += random(-0.5, 0.5);
|
|
332
|
+
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
333
|
+
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
334
|
+
particle.size *= this._options.particleShrinkRate;
|
|
335
|
+
particle.alpha *= this._options.particleAlphaFadeout;
|
|
336
|
+
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
337
|
+
ctx.beginPath();
|
|
338
|
+
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
339
|
+
ctx.fill();
|
|
539
340
|
}
|
|
540
|
-
|
|
541
|
-
|
|
341
|
+
};
|
|
342
|
+
function throttle(callback, limit) {
|
|
343
|
+
let wait = false;
|
|
344
|
+
return function(...args) {
|
|
345
|
+
if (!wait) {
|
|
346
|
+
callback.apply(this, args);
|
|
347
|
+
wait = true;
|
|
348
|
+
setTimeout(() => {
|
|
349
|
+
wait = false;
|
|
350
|
+
}, limit);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
var getRGBComponents = (node, color) => {
|
|
355
|
+
if (typeof color === "function") {
|
|
356
|
+
return color();
|
|
542
357
|
}
|
|
543
|
-
|
|
544
|
-
|
|
358
|
+
const bgColor = getComputedStyle(node).color;
|
|
359
|
+
if (bgColor) {
|
|
360
|
+
const x = bgColor.match(/(\d+), (\d+), (\d+)/)?.slice(1);
|
|
361
|
+
if (x) {
|
|
362
|
+
return x;
|
|
363
|
+
}
|
|
545
364
|
}
|
|
365
|
+
return [
|
|
366
|
+
50,
|
|
367
|
+
50,
|
|
368
|
+
50
|
|
369
|
+
];
|
|
546
370
|
};
|
|
547
|
-
var
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
margin: "0px 2px 0px 4px"
|
|
552
|
-
},
|
|
553
|
-
".cm-ySelectionCaret": {
|
|
554
|
-
position: "relative",
|
|
555
|
-
borderLeft: "1px solid black",
|
|
556
|
-
borderRight: "1px solid black",
|
|
557
|
-
marginLeft: "-1px",
|
|
558
|
-
marginRight: "-1px",
|
|
559
|
-
boxSizing: "border-box",
|
|
560
|
-
display: "inline"
|
|
561
|
-
},
|
|
562
|
-
".cm-ySelectionCaretDot": {
|
|
563
|
-
borderRadius: "50%",
|
|
564
|
-
position: "absolute",
|
|
565
|
-
width: ".4em",
|
|
566
|
-
height: ".4em",
|
|
567
|
-
top: "-.2em",
|
|
568
|
-
left: "-.2em",
|
|
569
|
-
backgroundColor: "inherit",
|
|
570
|
-
transition: "transform .3s ease-in-out",
|
|
571
|
-
boxSizing: "border-box"
|
|
572
|
-
},
|
|
573
|
-
".cm-ySelectionCaret:hover > .cm-ySelectionCaretDot": {
|
|
574
|
-
transformOrigin: "bottom center",
|
|
575
|
-
transform: "scale(0)"
|
|
576
|
-
},
|
|
577
|
-
".cm-ySelectionInfo": {
|
|
578
|
-
position: "absolute",
|
|
579
|
-
top: "-1.05em",
|
|
580
|
-
left: "-1px",
|
|
581
|
-
fontSize: ".75em",
|
|
582
|
-
fontFamily: "serif",
|
|
583
|
-
fontStyle: "normal",
|
|
584
|
-
fontWeight: "normal",
|
|
585
|
-
lineHeight: "normal",
|
|
586
|
-
userSelect: "none",
|
|
587
|
-
color: "white",
|
|
588
|
-
paddingLeft: "2px",
|
|
589
|
-
paddingRight: "2px",
|
|
590
|
-
zIndex: 101,
|
|
591
|
-
transition: "opacity .3s ease-in-out",
|
|
592
|
-
backgroundColor: "inherit",
|
|
593
|
-
// these should be separate
|
|
594
|
-
opacity: 0,
|
|
595
|
-
transitionDelay: "0s",
|
|
596
|
-
whiteSpace: "nowrap"
|
|
597
|
-
},
|
|
598
|
-
".cm-ySelectionCaret:hover > .cm-ySelectionInfo": {
|
|
599
|
-
opacity: 1,
|
|
600
|
-
transitionDelay: "0s"
|
|
371
|
+
var random = (min, max) => {
|
|
372
|
+
if (!max) {
|
|
373
|
+
max = min;
|
|
374
|
+
min = 0;
|
|
601
375
|
}
|
|
602
|
-
|
|
376
|
+
return min + ~~(Math.random() * (max - min + 1));
|
|
377
|
+
};
|
|
603
378
|
|
|
604
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
605
|
-
import {
|
|
606
|
-
import
|
|
607
|
-
import {
|
|
608
|
-
import { drawSelection, EditorView as EditorView2, placeholder } from "@codemirror/view";
|
|
609
|
-
var basicBundle = ({ readonly, themeMode, placeholder: _placeholder }) => [
|
|
610
|
-
EditorView2.lineWrapping,
|
|
611
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
612
|
-
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
613
|
-
bracketMatching(),
|
|
614
|
-
closeBrackets(),
|
|
615
|
-
drawSelection(),
|
|
616
|
-
_placeholder && placeholder(_placeholder),
|
|
617
|
-
// TODO(burdon): Is this required?
|
|
618
|
-
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
619
|
-
].filter(Boolean);
|
|
379
|
+
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
380
|
+
import { ViewPlugin, EditorView as EditorView3, Decoration } from "@codemirror/view";
|
|
381
|
+
import get from "lodash.get";
|
|
382
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
620
383
|
|
|
621
|
-
// packages/ui/react-ui-editor/src/
|
|
622
|
-
import {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
384
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
385
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
386
|
+
var headings = {
|
|
387
|
+
1: [
|
|
388
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
389
|
+
"-ml-[10px]"
|
|
390
|
+
],
|
|
391
|
+
2: [
|
|
392
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
393
|
+
"-ml-[8px]"
|
|
394
|
+
],
|
|
395
|
+
3: [
|
|
396
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
397
|
+
"-ml-[7px]"
|
|
398
|
+
],
|
|
399
|
+
4: [
|
|
400
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
401
|
+
"-ml-[6px]"
|
|
402
|
+
],
|
|
403
|
+
5: [
|
|
404
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
405
|
+
"-ml-[5px]"
|
|
406
|
+
],
|
|
407
|
+
6: [
|
|
408
|
+
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
409
|
+
"-ml-[4px]"
|
|
410
|
+
]
|
|
411
|
+
};
|
|
412
|
+
var heading = (level, readonly) => {
|
|
413
|
+
const [style, offset] = headings[level];
|
|
414
|
+
return mx(style, readonly && offset);
|
|
415
|
+
};
|
|
416
|
+
var light = "text-neutral-200 dark:text-neutral-800";
|
|
417
|
+
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
418
|
+
var bold = "font-bold";
|
|
419
|
+
var italic = "italic";
|
|
420
|
+
var strikethrough = "line-through";
|
|
421
|
+
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
422
|
+
var codeMark = "font-mono text-primary-500";
|
|
423
|
+
var inlineUrl = mx(code, "px-1");
|
|
424
|
+
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
425
|
+
|
|
426
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
427
|
+
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
428
|
+
var tokens = tailwindConfig({}).theme;
|
|
429
|
+
|
|
430
|
+
// packages/ui/react-ui-editor/src/extensions/code.ts
|
|
431
|
+
var CODE_REGEX = /```[\s\S]*?```/gs;
|
|
432
|
+
var styles = EditorView3.baseTheme({
|
|
433
|
+
"& .cm-codeblock": {
|
|
434
|
+
fontFamily: get(tokens, "fontFamily.mono", []).join(",")
|
|
634
435
|
},
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
max: 10
|
|
436
|
+
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
437
|
+
background: get(tokens, "extend.colors.neutral.50")
|
|
638
438
|
},
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
-1,
|
|
642
|
-
1
|
|
643
|
-
],
|
|
644
|
-
y: [
|
|
645
|
-
-3.5,
|
|
646
|
-
-1.5
|
|
647
|
-
]
|
|
439
|
+
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
440
|
+
background: get(tokens, "extend.colors.neutral.850")
|
|
648
441
|
},
|
|
649
|
-
|
|
650
|
-
|
|
442
|
+
'& [aria-readonly="true"] .cm-codeblock': {
|
|
443
|
+
display: "block",
|
|
444
|
+
paddingInline: "4px !important"
|
|
445
|
+
},
|
|
446
|
+
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
447
|
+
paddingTop: "4px !important",
|
|
448
|
+
borderTopLeftRadius: "4px",
|
|
449
|
+
borderTopRightRadius: "4px"
|
|
450
|
+
},
|
|
451
|
+
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
452
|
+
paddingBottom: "4px !important",
|
|
453
|
+
borderBottomLeftRadius: "4px",
|
|
454
|
+
borderBottomRightRadius: "4px"
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
var getLineRange = (lines, from, to) => {
|
|
458
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
459
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
460
|
+
return [
|
|
461
|
+
start,
|
|
462
|
+
end
|
|
463
|
+
];
|
|
651
464
|
};
|
|
652
|
-
var
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
465
|
+
var code2 = () => {
|
|
466
|
+
const getDecorations = (view) => {
|
|
467
|
+
const decorations = [];
|
|
468
|
+
if (view.state.readOnly) {
|
|
469
|
+
const text = view.state.doc.sliceString(0);
|
|
470
|
+
const matches = text.matchAll(CODE_REGEX);
|
|
471
|
+
const blocks = view.viewportLineBlocks;
|
|
472
|
+
for (const match of matches) {
|
|
473
|
+
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
474
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
475
|
+
const block = blocks[i];
|
|
476
|
+
decorations.push(Decoration.line({
|
|
477
|
+
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
478
|
+
}).range(block.from));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return Decoration.set(decorations);
|
|
667
483
|
};
|
|
668
484
|
return [
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
if (blaster) {
|
|
673
|
-
blaster.destroy();
|
|
674
|
-
}
|
|
675
|
-
blaster = new Blaster(update4.view.scrollDOM, defaultsDeep({
|
|
676
|
-
particleGravity: 0.2,
|
|
677
|
-
particleShrinkRate: 0.995,
|
|
678
|
-
color: () => [
|
|
679
|
-
100 + Math.random() * 100,
|
|
680
|
-
0,
|
|
681
|
-
0
|
|
682
|
-
]
|
|
683
|
-
}, options, defaultOptions));
|
|
684
|
-
blaster.initialize();
|
|
685
|
-
blaster.start();
|
|
686
|
-
} else {
|
|
687
|
-
blaster.resize();
|
|
485
|
+
ViewPlugin.fromClass(class {
|
|
486
|
+
constructor(view) {
|
|
487
|
+
this.decorations = getDecorations(view);
|
|
688
488
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
const { element, point } = getPoint(update4.view, current - 1);
|
|
693
|
-
if (element && point) {
|
|
694
|
-
blaster.spawn({
|
|
695
|
-
element,
|
|
696
|
-
point
|
|
697
|
-
});
|
|
489
|
+
update(update4) {
|
|
490
|
+
if (update4.docChanged || update4.viewportChanged) {
|
|
491
|
+
this.decorations = getDecorations(update4.view);
|
|
698
492
|
}
|
|
699
493
|
}
|
|
494
|
+
}, {
|
|
495
|
+
decorations: (value) => value.decorations
|
|
700
496
|
}),
|
|
701
|
-
|
|
702
|
-
{
|
|
703
|
-
any: (_, event) => {
|
|
704
|
-
if (blaster) {
|
|
705
|
-
if (event.key === "Enter" && event.shiftKey) {
|
|
706
|
-
blaster.shake({
|
|
707
|
-
time: 0.8
|
|
708
|
-
});
|
|
709
|
-
return true;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
return false;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
])
|
|
497
|
+
styles
|
|
716
498
|
];
|
|
717
499
|
};
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
738
|
-
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
739
|
-
this._lastPoint = point;
|
|
740
|
-
for (let i = numParticles; i--; i > 0) {
|
|
741
|
-
this._particles[this._particlePointer] = this._effect.create(point.x - dir * 16, point.y, color);
|
|
742
|
-
this._particlePointer = (this._particlePointer + 1) % this._options.maxParticles;
|
|
743
|
-
}
|
|
744
|
-
}, 100);
|
|
745
|
-
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
746
|
-
}
|
|
747
|
-
get node() {
|
|
748
|
-
return this._node;
|
|
749
|
-
}
|
|
750
|
-
initialize() {
|
|
751
|
-
invariant(!this._canvas && !this._ctx, void 0, {
|
|
500
|
+
|
|
501
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
502
|
+
import { StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
|
|
503
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView4, MatchDecorator, ViewPlugin as ViewPlugin3, WidgetType } from "@codemirror/view";
|
|
504
|
+
import get3 from "lodash.get";
|
|
505
|
+
import sortBy from "lodash.sortby";
|
|
506
|
+
import { debounce } from "@dxos/async";
|
|
507
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
508
|
+
import { log as log3 } from "@dxos/log";
|
|
509
|
+
import { nonNullable } from "@dxos/util";
|
|
510
|
+
|
|
511
|
+
// packages/ui/react-ui-editor/src/extensions/util.ts
|
|
512
|
+
import { log } from "@dxos/log";
|
|
513
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/util.ts";
|
|
514
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
515
|
+
try {
|
|
516
|
+
return fn(...args);
|
|
517
|
+
} catch (error) {
|
|
518
|
+
log.catch(error, void 0, {
|
|
752
519
|
F: __dxlog_file2,
|
|
753
|
-
L:
|
|
754
|
-
S:
|
|
755
|
-
|
|
756
|
-
"!this._canvas && !this._ctx",
|
|
757
|
-
""
|
|
758
|
-
]
|
|
520
|
+
L: 16,
|
|
521
|
+
S: void 0,
|
|
522
|
+
C: (f, a) => f(...a)
|
|
759
523
|
});
|
|
760
|
-
this._canvas = document.createElement("canvas");
|
|
761
|
-
this._canvas.id = "code-blast-canvas";
|
|
762
|
-
this._canvas.style.position = "absolute";
|
|
763
|
-
this._canvas.style.zIndex = "0";
|
|
764
|
-
this._canvas.style.pointerEvents = "none";
|
|
765
|
-
this._ctx = this._canvas.getContext("2d");
|
|
766
|
-
const parent = this._node.parentElement?.parentElement;
|
|
767
|
-
parent?.appendChild(this._canvas);
|
|
768
|
-
this.resize();
|
|
769
|
-
}
|
|
770
|
-
destroy() {
|
|
771
|
-
this.stop();
|
|
772
|
-
if (this._canvas) {
|
|
773
|
-
this._canvas.remove();
|
|
774
|
-
this._canvas = void 0;
|
|
775
|
-
this._ctx = void 0;
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
resize() {
|
|
779
|
-
if (this._node.parentElement && this._canvas) {
|
|
780
|
-
const { offsetLeft: x, offsetTop: y, offsetWidth: width, offsetHeight: height } = this._node.parentElement;
|
|
781
|
-
this._canvas.style.top = `${y}px`;
|
|
782
|
-
this._canvas.style.left = `${x}px`;
|
|
783
|
-
this._canvas.width = width;
|
|
784
|
-
this._canvas.height = height;
|
|
785
|
-
}
|
|
786
524
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
528
|
+
import { StateField as StateField2 } from "@codemirror/state";
|
|
529
|
+
import get2 from "lodash.get";
|
|
530
|
+
import { useEffect, useState } from "react";
|
|
531
|
+
import { yCollab } from "y-codemirror.next";
|
|
532
|
+
import * as Y from "yjs";
|
|
533
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
534
|
+
import { getRawDoc, isActualAutomergeObject } from "@dxos/react-client/echo";
|
|
535
|
+
import { arrayToString, stringToArray } from "@dxos/util";
|
|
536
|
+
|
|
537
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
538
|
+
import { Annotation, Facet, StateEffect, StateField } from "@codemirror/state";
|
|
539
|
+
import { ViewPlugin as ViewPlugin2 } from "@codemirror/view";
|
|
540
|
+
import * as automerge2 from "@dxos/automerge/automerge";
|
|
541
|
+
|
|
542
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/semaphore.ts
|
|
543
|
+
import { next as automerge } from "@dxos/automerge/automerge";
|
|
544
|
+
|
|
545
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/update-automerge.ts
|
|
546
|
+
import { next as am } from "@dxos/automerge/automerge";
|
|
547
|
+
var updateAutomerge = (field, handle, transactions, state) => {
|
|
548
|
+
const { lastHeads, path } = state.field(field);
|
|
549
|
+
let hasChanges = false;
|
|
550
|
+
for (const tr of transactions) {
|
|
551
|
+
tr.changes.iterChanges(() => {
|
|
552
|
+
hasChanges = true;
|
|
796
553
|
});
|
|
797
|
-
this._running = true;
|
|
798
|
-
this.loop();
|
|
799
554
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
this._node.style.transform = "translate(0px, 0px)";
|
|
555
|
+
if (!hasChanges) {
|
|
556
|
+
return void 0;
|
|
803
557
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
810
|
-
this._lastTime ??= now;
|
|
811
|
-
const dt = (now - this._lastTime) / 1e3;
|
|
812
|
-
this._lastTime = now;
|
|
813
|
-
if (this._shakeTime > 0) {
|
|
814
|
-
this._shakeTime -= dt;
|
|
815
|
-
const magnitude = this._shakeTime / this._shakeTimeMax * this._options.shakeIntensity;
|
|
816
|
-
const shakeX = random(-magnitude, magnitude);
|
|
817
|
-
const shakeY = random(-magnitude, magnitude);
|
|
818
|
-
this._node.style.transform = `translate(${shakeX}px,${shakeY}px)`;
|
|
558
|
+
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
559
|
+
for (const tr of transactions) {
|
|
560
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
561
|
+
am.splice(doc, path, fromA, toA - fromA, inserted.toString());
|
|
562
|
+
});
|
|
819
563
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
564
|
+
});
|
|
565
|
+
return newHeads ?? void 0;
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/update-codemirror.ts
|
|
569
|
+
import { ChangeSet } from "@codemirror/state";
|
|
570
|
+
var updateCodeMirror = (view, selection, target, patches) => {
|
|
571
|
+
for (const patch of patches) {
|
|
572
|
+
const changeSpec = handlePatch(patch, target, view.state);
|
|
573
|
+
if (changeSpec != null) {
|
|
574
|
+
const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
|
|
575
|
+
selection = selection.map(changeSet, 1);
|
|
576
|
+
view.dispatch({
|
|
577
|
+
changes: changeSet,
|
|
578
|
+
annotations: reconcileAnnotationType.of({})
|
|
579
|
+
});
|
|
833
580
|
}
|
|
834
581
|
}
|
|
582
|
+
view.dispatch({
|
|
583
|
+
selection,
|
|
584
|
+
annotations: reconcileAnnotationType.of({})
|
|
585
|
+
});
|
|
835
586
|
};
|
|
836
|
-
var
|
|
837
|
-
|
|
838
|
-
|
|
587
|
+
var handlePatch = (patch, target, state) => {
|
|
588
|
+
if (patch.action === "insert") {
|
|
589
|
+
return handleInsert(target, patch);
|
|
590
|
+
} else if (patch.action === "splice") {
|
|
591
|
+
return handleSplice(target, patch);
|
|
592
|
+
} else if (patch.action === "del") {
|
|
593
|
+
return handleDel(target, patch);
|
|
594
|
+
} else if (patch.action === "put") {
|
|
595
|
+
return handlePut(target, patch, state);
|
|
596
|
+
} else {
|
|
597
|
+
return null;
|
|
839
598
|
}
|
|
840
599
|
};
|
|
841
|
-
var
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
y: y + 10,
|
|
846
|
-
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
847
|
-
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
848
|
-
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
849
|
-
color,
|
|
850
|
-
alpha: 1
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
update(ctx, particle) {
|
|
854
|
-
particle.vy += this._options.particleGravity;
|
|
855
|
-
particle.x += particle.vx;
|
|
856
|
-
particle.y += particle.vy;
|
|
857
|
-
particle.alpha *= this._options.particleAlphaFadeout;
|
|
858
|
-
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
859
|
-
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
|
600
|
+
var handleInsert = (target, patch) => {
|
|
601
|
+
const index = charPath(target, patch.path);
|
|
602
|
+
if (index == null) {
|
|
603
|
+
return [];
|
|
860
604
|
}
|
|
605
|
+
const text = patch.values.map((v) => v ? v.toString() : "").join("");
|
|
606
|
+
return [
|
|
607
|
+
{
|
|
608
|
+
from: index,
|
|
609
|
+
to: index,
|
|
610
|
+
insert: text
|
|
611
|
+
}
|
|
612
|
+
];
|
|
861
613
|
};
|
|
862
|
-
var
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
y: y + 10,
|
|
867
|
-
vx: random(this._options.particleVelocityRange.x[0], this._options.particleVelocityRange.x[1]),
|
|
868
|
-
vy: random(this._options.particleVelocityRange.y[0], this._options.particleVelocityRange.y[1]),
|
|
869
|
-
size: random(this._options.particleSize.min, this._options.particleSize.max),
|
|
870
|
-
color,
|
|
871
|
-
alpha: 1,
|
|
872
|
-
theta: random(0, 360) * Math.PI / 180,
|
|
873
|
-
drag: 0.92,
|
|
874
|
-
wander: 0.15
|
|
875
|
-
};
|
|
876
|
-
}
|
|
877
|
-
update(ctx, particle) {
|
|
878
|
-
particle.vy += this._options.particleGravity;
|
|
879
|
-
particle.x += particle.vx;
|
|
880
|
-
particle.y += particle.vy;
|
|
881
|
-
particle.vx *= particle.drag;
|
|
882
|
-
particle.vy *= particle.drag;
|
|
883
|
-
particle.theta += random(-0.5, 0.5);
|
|
884
|
-
particle.vx += Math.sin(particle.theta) * 0.1;
|
|
885
|
-
particle.vy += Math.cos(particle.theta) * 0.1;
|
|
886
|
-
particle.size *= this._options.particleShrinkRate;
|
|
887
|
-
particle.alpha *= this._options.particleAlphaFadeout;
|
|
888
|
-
ctx.fillStyle = `rgba(${particle.color[0]},${particle.color[1]},${particle.color[2]},${particle.alpha})`;
|
|
889
|
-
ctx.beginPath();
|
|
890
|
-
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
|
891
|
-
ctx.fill();
|
|
614
|
+
var handleSplice = (target, patch) => {
|
|
615
|
+
const index = charPath(target, patch.path);
|
|
616
|
+
if (index == null) {
|
|
617
|
+
return [];
|
|
892
618
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
if (!wait) {
|
|
898
|
-
callback.apply(this, args);
|
|
899
|
-
wait = true;
|
|
900
|
-
setTimeout(() => {
|
|
901
|
-
wait = false;
|
|
902
|
-
}, limit);
|
|
619
|
+
return [
|
|
620
|
+
{
|
|
621
|
+
from: index,
|
|
622
|
+
insert: patch.value
|
|
903
623
|
}
|
|
904
|
-
|
|
905
|
-
}
|
|
906
|
-
var
|
|
907
|
-
|
|
908
|
-
|
|
624
|
+
];
|
|
625
|
+
};
|
|
626
|
+
var handleDel = (target, patch) => {
|
|
627
|
+
const index = charPath(target, patch.path);
|
|
628
|
+
if (index == null) {
|
|
629
|
+
return [];
|
|
909
630
|
}
|
|
910
|
-
const
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
631
|
+
const length = patch.length || 1;
|
|
632
|
+
return [
|
|
633
|
+
{
|
|
634
|
+
from: index,
|
|
635
|
+
to: index + length
|
|
915
636
|
}
|
|
637
|
+
];
|
|
638
|
+
};
|
|
639
|
+
var handlePut = (target, patch, state) => {
|
|
640
|
+
const index = charPath(target, [
|
|
641
|
+
...patch.path,
|
|
642
|
+
0
|
|
643
|
+
]);
|
|
644
|
+
if (index == null) {
|
|
645
|
+
return [];
|
|
646
|
+
}
|
|
647
|
+
const length = state.doc.length;
|
|
648
|
+
if (typeof patch.value !== "string") {
|
|
649
|
+
return [];
|
|
916
650
|
}
|
|
917
651
|
return [
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
652
|
+
{
|
|
653
|
+
from: 0,
|
|
654
|
+
to: length,
|
|
655
|
+
insert: patch.value
|
|
656
|
+
}
|
|
921
657
|
];
|
|
922
658
|
};
|
|
923
|
-
var
|
|
924
|
-
if (
|
|
925
|
-
|
|
926
|
-
min = 0;
|
|
659
|
+
var charPath = (textPath, candidatePath) => {
|
|
660
|
+
if (candidatePath.length !== textPath.length + 1) {
|
|
661
|
+
return null;
|
|
927
662
|
}
|
|
928
|
-
|
|
663
|
+
for (let i = 0; i < textPath.length; i++) {
|
|
664
|
+
if (textPath[i] !== candidatePath[i]) {
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
const index = candidatePath[candidatePath.length - 1];
|
|
669
|
+
if (typeof index === "number") {
|
|
670
|
+
return index;
|
|
671
|
+
}
|
|
672
|
+
return null;
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/semaphore.ts
|
|
676
|
+
var PatchSemaphore = class {
|
|
677
|
+
constructor(field) {
|
|
678
|
+
this._inReconcile = false;
|
|
679
|
+
this._queue = [];
|
|
680
|
+
this.reconcile = (handle, view) => {
|
|
681
|
+
if (this._inReconcile) {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
this._inReconcile = true;
|
|
685
|
+
const path = getPath(view.state, this._field);
|
|
686
|
+
const oldHeads = getLastHeads(view.state, this._field);
|
|
687
|
+
let selection = view.state.selection;
|
|
688
|
+
const transactions = view.state.field(this._field).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
689
|
+
const toInvert = transactions.slice().reverse();
|
|
690
|
+
for (const tx of toInvert) {
|
|
691
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
692
|
+
selection = selection.map(inverted);
|
|
693
|
+
view.dispatch({
|
|
694
|
+
changes: inverted,
|
|
695
|
+
annotations: reconcileAnnotationType.of(true)
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
699
|
+
if (newHeads === null || newHeads === void 0) {
|
|
700
|
+
newHeads = automerge.getHeads(handle.docSync());
|
|
701
|
+
}
|
|
702
|
+
const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
|
|
703
|
+
updateCodeMirror(view, selection, path, diff);
|
|
704
|
+
view.dispatch({
|
|
705
|
+
effects: updateHeads(newHeads),
|
|
706
|
+
annotations: reconcileAnnotationType.of({})
|
|
707
|
+
});
|
|
708
|
+
this._inReconcile = false;
|
|
709
|
+
};
|
|
710
|
+
if (field !== void 0) {
|
|
711
|
+
this._field = field;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
// packages/ui/react-ui-editor/src/hooks/automerge/plugin.ts
|
|
717
|
+
var effectType = StateEffect.define({});
|
|
718
|
+
var updateHeads = (newHeads) => effectType.of({
|
|
719
|
+
newHeads
|
|
720
|
+
});
|
|
721
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
722
|
+
var getPath = (state, field) => state.field(field).path;
|
|
723
|
+
var semaphoreFacet = Facet.define({
|
|
724
|
+
combine: (values) => values.at(-1)
|
|
725
|
+
});
|
|
726
|
+
var automergePlugin = (handle, path) => {
|
|
727
|
+
const stateField = StateField.define({
|
|
728
|
+
create: () => ({
|
|
729
|
+
lastHeads: automerge2.getHeads(handle.docSync()),
|
|
730
|
+
unreconciledTransactions: [],
|
|
731
|
+
path: path.slice()
|
|
732
|
+
}),
|
|
733
|
+
update: (value, tr) => {
|
|
734
|
+
const result = {
|
|
735
|
+
lastHeads: value.lastHeads,
|
|
736
|
+
unreconciledTransactions: value.unreconciledTransactions.slice(),
|
|
737
|
+
path: path.slice()
|
|
738
|
+
};
|
|
739
|
+
let clearUnreconciled = false;
|
|
740
|
+
for (const effect of tr.effects) {
|
|
741
|
+
if (effect.is(effectType)) {
|
|
742
|
+
result.lastHeads = effect.value.newHeads;
|
|
743
|
+
clearUnreconciled = true;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (clearUnreconciled) {
|
|
747
|
+
result.unreconciledTransactions = [];
|
|
748
|
+
} else {
|
|
749
|
+
if (!isReconcileTx(tr)) {
|
|
750
|
+
result.unreconciledTransactions.push(tr);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return result;
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
const semaphore = new PatchSemaphore(stateField);
|
|
757
|
+
const viewPlugin = ViewPlugin2.fromClass(class AutomergeCodemirrorViewPlugin {
|
|
758
|
+
constructor(_view) {
|
|
759
|
+
this._view = _view;
|
|
760
|
+
this._handleChange = () => {
|
|
761
|
+
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
762
|
+
};
|
|
763
|
+
handle.addListener("change", this._handleChange);
|
|
764
|
+
}
|
|
765
|
+
update(update4) {
|
|
766
|
+
if (update4.transactions.length > 0 && update4.transactions.some((tr) => !isReconcileTx(tr))) {
|
|
767
|
+
queueMicrotask(() => {
|
|
768
|
+
this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
destroy() {
|
|
773
|
+
handle.addListener("change", this._handleChange);
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
return {
|
|
777
|
+
extension: [
|
|
778
|
+
stateField,
|
|
779
|
+
semaphoreFacet.of(semaphore),
|
|
780
|
+
viewPlugin
|
|
781
|
+
]
|
|
782
|
+
};
|
|
929
783
|
};
|
|
784
|
+
var reconcileAnnotationType = Annotation.define();
|
|
785
|
+
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
930
786
|
|
|
931
|
-
// packages/ui/react-ui-editor/src/
|
|
932
|
-
import { ViewPlugin as ViewPlugin3, EditorView as EditorView4, Decoration as Decoration2 } from "@codemirror/view";
|
|
933
|
-
import get2 from "lodash.get";
|
|
934
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
935
|
-
|
|
936
|
-
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
787
|
+
// packages/ui/react-ui-editor/src/hooks/yjs/cursors.ts
|
|
937
788
|
import * as random2 from "lib0/random";
|
|
938
789
|
var cursorColors = [
|
|
939
790
|
{
|
|
@@ -971,134 +822,216 @@ var cursorColors = [
|
|
|
971
822
|
];
|
|
972
823
|
var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
973
824
|
|
|
974
|
-
// packages/ui/react-ui-editor/src/
|
|
975
|
-
import
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
"
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
825
|
+
// packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts
|
|
826
|
+
import * as decoding from "lib0/decoding";
|
|
827
|
+
import * as encoding from "lib0/encoding";
|
|
828
|
+
import { Observable } from "lib0/observable";
|
|
829
|
+
import * as awarenessProtocol from "y-protocols/awareness";
|
|
830
|
+
import { log as log2 } from "@dxos/log";
|
|
831
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs/space-provider.ts";
|
|
832
|
+
var messageAwareness = 1;
|
|
833
|
+
var messageQueryAwareness = 3;
|
|
834
|
+
var SpaceAwarenessProvider = class extends Observable {
|
|
835
|
+
constructor({ space, doc, channel, awareness }) {
|
|
836
|
+
super();
|
|
837
|
+
this._space = space;
|
|
838
|
+
this._awareness = awareness ?? new awarenessProtocol.Awareness(doc);
|
|
839
|
+
this._channel = channel;
|
|
840
|
+
this._clientId = doc.clientID;
|
|
841
|
+
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
842
|
+
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
843
|
+
if (typeof window !== "undefined") {
|
|
844
|
+
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
845
|
+
} else if (typeof process !== "undefined") {
|
|
846
|
+
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
847
|
+
}
|
|
848
|
+
const encoderAwarenessQuery = encoding.createEncoder();
|
|
849
|
+
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
850
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
851
|
+
const encoderAwarenessState = encoding.createEncoder();
|
|
852
|
+
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
853
|
+
encoding.writeVarUint8Array(encoderAwarenessState, awarenessProtocol.encodeAwarenessUpdate(this.awareness, [
|
|
854
|
+
this._clientId
|
|
855
|
+
]));
|
|
856
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
857
|
+
}
|
|
858
|
+
get awareness() {
|
|
859
|
+
return this._awareness;
|
|
860
|
+
}
|
|
861
|
+
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
862
|
+
log2("awareness update", {
|
|
863
|
+
added,
|
|
864
|
+
updated,
|
|
865
|
+
removed,
|
|
866
|
+
origin
|
|
867
|
+
}, {
|
|
868
|
+
F: __dxlog_file3,
|
|
869
|
+
L: 67,
|
|
870
|
+
S: this,
|
|
871
|
+
C: (f, a) => f(...a)
|
|
872
|
+
});
|
|
873
|
+
const changedClients = added.concat(updated).concat(removed);
|
|
874
|
+
const encoderAwareness = encoding.createEncoder();
|
|
875
|
+
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
876
|
+
encoding.writeVarUint8Array(encoderAwareness, awarenessProtocol.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
877
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
878
|
+
}
|
|
879
|
+
_handleSpaceMessage({ payload }) {
|
|
880
|
+
log2("space message", payload, {
|
|
881
|
+
F: __dxlog_file3,
|
|
882
|
+
L: 79,
|
|
883
|
+
S: this,
|
|
884
|
+
C: (f, a) => f(...a)
|
|
885
|
+
});
|
|
886
|
+
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
887
|
+
const encoder = this._readMessage(data);
|
|
888
|
+
if (encoder) {
|
|
889
|
+
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
_readMessage(message) {
|
|
893
|
+
const decoder = decoding.createDecoder(message);
|
|
894
|
+
const encoder = encoding.createEncoder();
|
|
895
|
+
const messageType = decoding.readVarUint(decoder);
|
|
896
|
+
let sendReply = false;
|
|
897
|
+
switch (messageType) {
|
|
898
|
+
case messageAwareness: {
|
|
899
|
+
awarenessProtocol.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
case messageQueryAwareness: {
|
|
903
|
+
encoding.writeVarUint(encoder, messageAwareness);
|
|
904
|
+
encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
905
|
+
sendReply = true;
|
|
906
|
+
break;
|
|
907
|
+
}
|
|
908
|
+
default: {
|
|
909
|
+
console.error("Invalid message:", messageType);
|
|
910
|
+
return encoder;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
if (!sendReply) {
|
|
914
|
+
return null;
|
|
915
|
+
}
|
|
916
|
+
return encoder;
|
|
917
|
+
}
|
|
918
|
+
_handleBeforeUnload() {
|
|
919
|
+
awarenessProtocol.removeAwarenessStates(this._awareness, [
|
|
920
|
+
this._clientId
|
|
921
|
+
], "window unload");
|
|
922
|
+
}
|
|
1005
923
|
};
|
|
1006
|
-
var light = "text-neutral-200 dark:text-neutral-800";
|
|
1007
|
-
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
1008
|
-
var bold = "font-bold";
|
|
1009
|
-
var italic = "italic";
|
|
1010
|
-
var strikethrough = "line-through";
|
|
1011
|
-
var code = "font-mono !no-underline text-neutral-700 dark:text-neutral-300";
|
|
1012
|
-
var codeMark = "font-mono text-primary-500";
|
|
1013
|
-
var inlineUrl = mx(code, "px-1");
|
|
1014
|
-
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1015
|
-
|
|
1016
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1017
|
-
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1018
|
-
var tokens = tailwindConfig({}).theme;
|
|
1019
924
|
|
|
1020
|
-
// packages/ui/react-ui-editor/src/
|
|
1021
|
-
var
|
|
1022
|
-
var
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
},
|
|
1026
|
-
'&light [aria-readonly="true"] .cm-codeblock': {
|
|
1027
|
-
background: get2(tokens, "extend.colors.neutral.50")
|
|
1028
|
-
},
|
|
1029
|
-
'&dark [aria-readonly="true"] .cm-codeblock': {
|
|
1030
|
-
background: get2(tokens, "extend.colors.neutral.850")
|
|
1031
|
-
},
|
|
1032
|
-
'& [aria-readonly="true"] .cm-codeblock': {
|
|
1033
|
-
display: "block",
|
|
1034
|
-
paddingInline: "4px !important"
|
|
1035
|
-
},
|
|
1036
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1037
|
-
paddingTop: "4px !important",
|
|
1038
|
-
borderTopLeftRadius: "4px",
|
|
1039
|
-
borderTopRightRadius: "4px"
|
|
1040
|
-
},
|
|
1041
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1042
|
-
paddingBottom: "4px !important",
|
|
1043
|
-
borderBottomLeftRadius: "4px",
|
|
1044
|
-
borderBottomRightRadius: "4px"
|
|
1045
|
-
}
|
|
925
|
+
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
926
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
927
|
+
var modelState = StateField2.define({
|
|
928
|
+
create: () => void 0,
|
|
929
|
+
update: (model) => model
|
|
1046
930
|
});
|
|
1047
|
-
var
|
|
1048
|
-
const
|
|
1049
|
-
const
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
931
|
+
var useTextModel = (props) => {
|
|
932
|
+
const { identity, space, text } = props;
|
|
933
|
+
const [model, setModel] = useState(() => createModel(props));
|
|
934
|
+
useEffect(() => setModel(createModel(props)), [
|
|
935
|
+
identity,
|
|
936
|
+
space,
|
|
937
|
+
text
|
|
938
|
+
]);
|
|
939
|
+
return model;
|
|
1054
940
|
};
|
|
1055
|
-
var
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
for (const match of matches) {
|
|
1063
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1064
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1065
|
-
const block = blocks[i];
|
|
1066
|
-
decorations.push(Decoration2.line({
|
|
1067
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1068
|
-
}).range(block.from));
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
941
|
+
var createModel = (props) => {
|
|
942
|
+
const { text } = props;
|
|
943
|
+
if (isActualAutomergeObject(text)) {
|
|
944
|
+
return createAutomergeModel(props);
|
|
945
|
+
} else {
|
|
946
|
+
if (!text?.doc) {
|
|
947
|
+
return void 0;
|
|
1071
948
|
}
|
|
1072
|
-
return
|
|
949
|
+
return createYjsModel(props);
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
var createYjsModel = ({ identity, space, text }) => {
|
|
953
|
+
invariant2(text?.doc && text?.content, void 0, {
|
|
954
|
+
F: __dxlog_file4,
|
|
955
|
+
L: 97,
|
|
956
|
+
S: void 0,
|
|
957
|
+
A: [
|
|
958
|
+
"text?.doc && text?.content",
|
|
959
|
+
""
|
|
960
|
+
]
|
|
961
|
+
});
|
|
962
|
+
const provider = space ? new SpaceAwarenessProvider({
|
|
963
|
+
space,
|
|
964
|
+
doc: text.doc,
|
|
965
|
+
channel: `yjs.awareness.${text.id}`
|
|
966
|
+
}) : void 0;
|
|
967
|
+
const model = {
|
|
968
|
+
id: text.doc.guid,
|
|
969
|
+
content: text.content,
|
|
970
|
+
text: () => text.content.toString(),
|
|
971
|
+
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
972
|
+
getCursorFromRange: (range) => {
|
|
973
|
+
const from = Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
974
|
+
const to = Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
975
|
+
return [
|
|
976
|
+
arrayToString(from),
|
|
977
|
+
arrayToString(to)
|
|
978
|
+
].join(":");
|
|
979
|
+
},
|
|
980
|
+
getRangeFromCursor: (cursor) => {
|
|
981
|
+
invariant2(text.doc, void 0, {
|
|
982
|
+
F: __dxlog_file4,
|
|
983
|
+
L: 113,
|
|
984
|
+
S: void 0,
|
|
985
|
+
A: [
|
|
986
|
+
"text.doc",
|
|
987
|
+
""
|
|
988
|
+
]
|
|
989
|
+
});
|
|
990
|
+
const parts = cursor.split(":");
|
|
991
|
+
const from = Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(parts[0])), text.doc);
|
|
992
|
+
const to = Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(parts[1])), text.doc);
|
|
993
|
+
return from && to ? {
|
|
994
|
+
from: from.index,
|
|
995
|
+
to: to.index
|
|
996
|
+
} : void 0;
|
|
997
|
+
},
|
|
998
|
+
extension: [
|
|
999
|
+
yCollab(text.content, provider?.awareness),
|
|
1000
|
+
modelState.init(() => model)
|
|
1001
|
+
],
|
|
1002
|
+
awareness: provider?.awareness,
|
|
1003
|
+
peer: identity ? {
|
|
1004
|
+
id: identity.identityKey.toHex(),
|
|
1005
|
+
name: identity.profile?.displayName
|
|
1006
|
+
} : void 0
|
|
1007
|
+
};
|
|
1008
|
+
return model;
|
|
1009
|
+
};
|
|
1010
|
+
var createAutomergeModel = ({ identity, text }) => {
|
|
1011
|
+
const obj = text;
|
|
1012
|
+
const doc = getRawDoc(obj, [
|
|
1013
|
+
obj.field
|
|
1014
|
+
]);
|
|
1015
|
+
const model = {
|
|
1016
|
+
id: obj.id,
|
|
1017
|
+
content: doc,
|
|
1018
|
+
text: () => get2(doc.handle.docSync(), doc.path),
|
|
1019
|
+
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
1020
|
+
extension: [
|
|
1021
|
+
automergePlugin(doc.handle, doc.path),
|
|
1022
|
+
modelState.init(() => model)
|
|
1023
|
+
],
|
|
1024
|
+
peer: identity ? {
|
|
1025
|
+
id: identity.identityKey.toHex(),
|
|
1026
|
+
name: identity.profile?.displayName
|
|
1027
|
+
} : void 0
|
|
1073
1028
|
};
|
|
1074
|
-
return
|
|
1075
|
-
ViewPlugin3.fromClass(class {
|
|
1076
|
-
constructor(view) {
|
|
1077
|
-
this.decorations = getDecorations(view);
|
|
1078
|
-
}
|
|
1079
|
-
update(update4) {
|
|
1080
|
-
if (update4.docChanged || update4.viewportChanged) {
|
|
1081
|
-
this.decorations = getDecorations(update4.view);
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
}, {
|
|
1085
|
-
decorations: (value) => value.decorations
|
|
1086
|
-
}),
|
|
1087
|
-
styles2
|
|
1088
|
-
];
|
|
1029
|
+
return model;
|
|
1089
1030
|
};
|
|
1090
1031
|
|
|
1091
1032
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
import get3 from "lodash.get";
|
|
1095
|
-
import sortBy from "lodash.sortby";
|
|
1096
|
-
import { debounce } from "@dxos/async";
|
|
1097
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1098
|
-
import { log as log2 } from "@dxos/log";
|
|
1099
|
-
import { nonNullable } from "@dxos/util";
|
|
1100
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1101
|
-
var styles3 = EditorView5.baseTheme({
|
|
1033
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1034
|
+
var styles2 = EditorView4.baseTheme({
|
|
1102
1035
|
"& .cm-bookmark": {
|
|
1103
1036
|
cursor: "pointer",
|
|
1104
1037
|
margin: "4px",
|
|
@@ -1116,10 +1049,10 @@ var styles3 = EditorView5.baseTheme({
|
|
|
1116
1049
|
}
|
|
1117
1050
|
});
|
|
1118
1051
|
var marks = {
|
|
1119
|
-
highlight:
|
|
1052
|
+
highlight: Decoration2.mark({
|
|
1120
1053
|
class: "cm-comment"
|
|
1121
1054
|
}),
|
|
1122
|
-
highlightActive:
|
|
1055
|
+
highlightActive: Decoration2.mark({
|
|
1123
1056
|
class: "cm-comment-active"
|
|
1124
1057
|
})
|
|
1125
1058
|
};
|
|
@@ -1141,12 +1074,11 @@ var setFocus = (view, thread) => {
|
|
|
1141
1074
|
var setCommentRange = StateEffect2.define();
|
|
1142
1075
|
var setSelection = StateEffect2.define();
|
|
1143
1076
|
var setCommentState = StateEffect2.define();
|
|
1144
|
-
var commentsStateField =
|
|
1077
|
+
var commentsStateField = StateField3.define({
|
|
1145
1078
|
create: () => ({
|
|
1146
1079
|
ranges: []
|
|
1147
1080
|
}),
|
|
1148
1081
|
update: (value, tr) => {
|
|
1149
|
-
const cursorConverter3 = tr.state.facet(CursorConverter);
|
|
1150
1082
|
for (const effect of tr.effects) {
|
|
1151
1083
|
if (effect.is(setSelection)) {
|
|
1152
1084
|
return {
|
|
@@ -1155,9 +1087,9 @@ var commentsStateField = StateField2.define({
|
|
|
1155
1087
|
};
|
|
1156
1088
|
}
|
|
1157
1089
|
if (effect.is(setCommentRange)) {
|
|
1158
|
-
const { comments: comments2 } = effect.value;
|
|
1090
|
+
const { model, comments: comments2 } = effect.value;
|
|
1159
1091
|
const ranges = comments2.map((comment) => {
|
|
1160
|
-
const range = getRangeFromCursor(
|
|
1092
|
+
const range = model.getRangeFromCursor(comment.cursor);
|
|
1161
1093
|
return range && {
|
|
1162
1094
|
...comment,
|
|
1163
1095
|
...range
|
|
@@ -1175,7 +1107,7 @@ var commentsStateField = StateField2.define({
|
|
|
1175
1107
|
return value;
|
|
1176
1108
|
}
|
|
1177
1109
|
});
|
|
1178
|
-
var highlightDecorations =
|
|
1110
|
+
var highlightDecorations = EditorView4.decorations.compute([
|
|
1179
1111
|
commentsStateField
|
|
1180
1112
|
], (state) => {
|
|
1181
1113
|
const { active, ranges } = state.field(commentsStateField);
|
|
@@ -1193,17 +1125,17 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1193
1125
|
return marks.highlight.range(range.from, range.to);
|
|
1194
1126
|
}
|
|
1195
1127
|
}).filter(nonNullable) ?? [];
|
|
1196
|
-
return
|
|
1128
|
+
return Decoration2.set(decorations);
|
|
1197
1129
|
});
|
|
1198
|
-
var BookmarkWidget = class extends
|
|
1130
|
+
var BookmarkWidget = class extends WidgetType {
|
|
1199
1131
|
constructor(_anchor, _id, _handleClick) {
|
|
1200
1132
|
super();
|
|
1201
1133
|
this._anchor = _anchor;
|
|
1202
1134
|
this._id = _id;
|
|
1203
1135
|
this._handleClick = _handleClick;
|
|
1204
|
-
|
|
1205
|
-
F:
|
|
1206
|
-
L:
|
|
1136
|
+
invariant3(this._id, void 0, {
|
|
1137
|
+
F: __dxlog_file5,
|
|
1138
|
+
L: 167,
|
|
1207
1139
|
S: this,
|
|
1208
1140
|
A: [
|
|
1209
1141
|
"this._id",
|
|
@@ -1227,10 +1159,9 @@ var BookmarkWidget = class extends WidgetType2 {
|
|
|
1227
1159
|
var comments = (options = {}) => {
|
|
1228
1160
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1229
1161
|
const createCommentThread = (view) => {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
L: 225,
|
|
1162
|
+
invariant3(options.onCreate, void 0, {
|
|
1163
|
+
F: __dxlog_file5,
|
|
1164
|
+
L: 221,
|
|
1234
1165
|
S: void 0,
|
|
1235
1166
|
A: [
|
|
1236
1167
|
"options.onCreate",
|
|
@@ -1241,7 +1172,8 @@ var comments = (options = {}) => {
|
|
|
1241
1172
|
if (from === to) {
|
|
1242
1173
|
return false;
|
|
1243
1174
|
}
|
|
1244
|
-
const
|
|
1175
|
+
const model = view.state.field(modelState);
|
|
1176
|
+
const relPos = model?.getCursorFromRange?.({
|
|
1245
1177
|
from,
|
|
1246
1178
|
to
|
|
1247
1179
|
});
|
|
@@ -1273,7 +1205,7 @@ var comments = (options = {}) => {
|
|
|
1273
1205
|
}
|
|
1274
1206
|
return false;
|
|
1275
1207
|
};
|
|
1276
|
-
const bookmarksViewPlugin =
|
|
1208
|
+
const bookmarksViewPlugin = ViewPlugin3.fromClass(class BookmarkViewPlugin {
|
|
1277
1209
|
static {
|
|
1278
1210
|
// Match markdown footnotes (option).
|
|
1279
1211
|
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
@@ -1281,7 +1213,7 @@ var comments = (options = {}) => {
|
|
|
1281
1213
|
regexp: /\[\^(\w+)\]/g,
|
|
1282
1214
|
decoration: (match, view, pos) => {
|
|
1283
1215
|
const id = match[1];
|
|
1284
|
-
return
|
|
1216
|
+
return Decoration2.replace({
|
|
1285
1217
|
id,
|
|
1286
1218
|
widget: new BookmarkWidget(pos, id)
|
|
1287
1219
|
});
|
|
@@ -1296,15 +1228,15 @@ var comments = (options = {}) => {
|
|
|
1296
1228
|
}
|
|
1297
1229
|
}, {
|
|
1298
1230
|
decorations: (instance) => instance.bookmarks,
|
|
1299
|
-
provide: (plugin) =>
|
|
1300
|
-
return view.plugin(plugin)?.bookmarks ||
|
|
1231
|
+
provide: (plugin) => EditorView4.atomicRanges.of((view) => {
|
|
1232
|
+
return view.plugin(plugin)?.bookmarks || Decoration2.none;
|
|
1301
1233
|
})
|
|
1302
1234
|
});
|
|
1303
1235
|
return [
|
|
1304
1236
|
bookmarksViewPlugin,
|
|
1305
1237
|
commentsStateField,
|
|
1306
1238
|
highlightDecorations,
|
|
1307
|
-
|
|
1239
|
+
styles2,
|
|
1308
1240
|
//
|
|
1309
1241
|
// Keymap.
|
|
1310
1242
|
//
|
|
@@ -1347,28 +1279,37 @@ var comments = (options = {}) => {
|
|
|
1347
1279
|
// Monitor cursor movement and text updates.
|
|
1348
1280
|
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1349
1281
|
//
|
|
1350
|
-
|
|
1351
|
-
const cursorConverter3 = view.state.facet(CursorConverter);
|
|
1282
|
+
EditorView4.updateListener.of(({ view, state, startState, changes }) => {
|
|
1352
1283
|
{
|
|
1353
1284
|
let mod = false;
|
|
1285
|
+
const model = state.field(modelState);
|
|
1354
1286
|
const { active, ranges } = state.field(commentsStateField);
|
|
1355
1287
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1288
|
+
invariant3(model, void 0, {
|
|
1289
|
+
F: __dxlog_file5,
|
|
1290
|
+
L: 350,
|
|
1291
|
+
S: void 0,
|
|
1292
|
+
A: [
|
|
1293
|
+
"model",
|
|
1294
|
+
""
|
|
1295
|
+
]
|
|
1296
|
+
});
|
|
1356
1297
|
ranges.forEach((range) => {
|
|
1357
1298
|
if (from2 === to2) {
|
|
1358
|
-
const newRange = getRangeFromCursor(
|
|
1299
|
+
const newRange = model.getRangeFromCursor(range.cursor);
|
|
1359
1300
|
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1360
|
-
|
|
1301
|
+
log3.info("deleted comment", {
|
|
1361
1302
|
thread: range.id
|
|
1362
1303
|
}, {
|
|
1363
|
-
F:
|
|
1364
|
-
L:
|
|
1304
|
+
F: __dxlog_file5,
|
|
1305
|
+
L: 356,
|
|
1365
1306
|
S: void 0,
|
|
1366
1307
|
C: (f, a) => f(...a)
|
|
1367
1308
|
});
|
|
1368
1309
|
}
|
|
1369
1310
|
}
|
|
1370
1311
|
if (from <= range.to) {
|
|
1371
|
-
const newRange = getRangeFromCursor(
|
|
1312
|
+
const newRange = model.getRangeFromCursor(range.cursor);
|
|
1372
1313
|
Object.assign(range, newRange);
|
|
1373
1314
|
mod = true;
|
|
1374
1315
|
}
|
|
@@ -1417,35 +1358,18 @@ var comments = (options = {}) => {
|
|
|
1417
1358
|
})
|
|
1418
1359
|
];
|
|
1419
1360
|
};
|
|
1420
|
-
var getCursorFromRange = (cursorConverter3, range) => {
|
|
1421
|
-
const from = cursorConverter3.toCursor(range.from);
|
|
1422
|
-
const to = cursorConverter3.toCursor(range.to, -1);
|
|
1423
|
-
return [
|
|
1424
|
-
from,
|
|
1425
|
-
to
|
|
1426
|
-
].join(":");
|
|
1427
|
-
};
|
|
1428
|
-
var getRangeFromCursor = (cursorConverter3, cursor) => {
|
|
1429
|
-
const parts = cursor.split(":");
|
|
1430
|
-
const from = cursorConverter3.fromCursor(parts[0]);
|
|
1431
|
-
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1432
|
-
return from && to ? {
|
|
1433
|
-
from,
|
|
1434
|
-
to
|
|
1435
|
-
} : void 0;
|
|
1436
|
-
};
|
|
1437
1361
|
|
|
1438
1362
|
// packages/ui/react-ui-editor/src/extensions/hr.ts
|
|
1439
|
-
import { Decoration as
|
|
1363
|
+
import { Decoration as Decoration3, EditorView as EditorView5, MatchDecorator as MatchDecorator2, ViewPlugin as ViewPlugin4, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1440
1364
|
import get4 from "lodash.get";
|
|
1441
|
-
var
|
|
1365
|
+
var styles3 = EditorView5.baseTheme({
|
|
1442
1366
|
"& .cm-hr": {
|
|
1443
1367
|
// TODO(burdon): ???
|
|
1444
1368
|
// Note that block-level decorations should not have vertical margins,
|
|
1445
1369
|
borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.200")}`
|
|
1446
1370
|
}
|
|
1447
1371
|
});
|
|
1448
|
-
var HorizontalRuleWidget = class extends
|
|
1372
|
+
var HorizontalRuleWidget = class extends WidgetType2 {
|
|
1449
1373
|
constructor(_pos) {
|
|
1450
1374
|
super();
|
|
1451
1375
|
this._pos = _pos;
|
|
@@ -1461,13 +1385,13 @@ var HorizontalRuleWidget = class extends WidgetType3 {
|
|
|
1461
1385
|
};
|
|
1462
1386
|
var placeholderMatcher = new MatchDecorator2({
|
|
1463
1387
|
regexp: /^---$/g,
|
|
1464
|
-
decoration: (match, view, pos) =>
|
|
1388
|
+
decoration: (match, view, pos) => Decoration3.replace({
|
|
1465
1389
|
widget: new HorizontalRuleWidget(pos)
|
|
1466
1390
|
})
|
|
1467
1391
|
});
|
|
1468
1392
|
var hr = () => [
|
|
1469
|
-
|
|
1470
|
-
|
|
1393
|
+
styles3,
|
|
1394
|
+
ViewPlugin4.fromClass(class {
|
|
1471
1395
|
constructor(view) {
|
|
1472
1396
|
this.rules = placeholderMatcher.createDeco(view);
|
|
1473
1397
|
}
|
|
@@ -1477,21 +1401,21 @@ var hr = () => [
|
|
|
1477
1401
|
}, {
|
|
1478
1402
|
decorations: (instance) => instance.rules,
|
|
1479
1403
|
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1480
|
-
provide: (plugin) =>
|
|
1481
|
-
return view.plugin(plugin)?.rules ||
|
|
1404
|
+
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1405
|
+
return view.plugin(plugin)?.rules || Decoration3.none;
|
|
1482
1406
|
})
|
|
1483
1407
|
})
|
|
1484
1408
|
];
|
|
1485
1409
|
|
|
1486
1410
|
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
1411
|
import { syntaxTree } from "@codemirror/language";
|
|
1488
|
-
import { RangeSetBuilder, StateField as
|
|
1489
|
-
import { Decoration as
|
|
1412
|
+
import { RangeSetBuilder, StateField as StateField4 } from "@codemirror/state";
|
|
1413
|
+
import { Decoration as Decoration4, EditorView as EditorView6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1490
1414
|
var image = (options = {}) => {
|
|
1491
|
-
return
|
|
1415
|
+
return StateField4.define({
|
|
1492
1416
|
create: (state) => update(state, options),
|
|
1493
1417
|
update: (_, tr) => update(tr.state, options),
|
|
1494
|
-
provide: (field) =>
|
|
1418
|
+
provide: (field) => EditorView6.decorations.from(field)
|
|
1495
1419
|
});
|
|
1496
1420
|
};
|
|
1497
1421
|
var update = (state, options) => {
|
|
@@ -1504,7 +1428,7 @@ var update = (state, options) => {
|
|
|
1504
1428
|
if (urlNode) {
|
|
1505
1429
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1506
1430
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1507
|
-
builder.add(hide ? node.from : node.to, node.to,
|
|
1431
|
+
builder.add(hide ? node.from : node.to, node.to, Decoration4.replace({
|
|
1508
1432
|
block: true,
|
|
1509
1433
|
widget: new ImageWidget(url)
|
|
1510
1434
|
}));
|
|
@@ -1514,7 +1438,7 @@ var update = (state, options) => {
|
|
|
1514
1438
|
});
|
|
1515
1439
|
return builder.finish();
|
|
1516
1440
|
};
|
|
1517
|
-
var ImageWidget = class extends
|
|
1441
|
+
var ImageWidget = class extends WidgetType3 {
|
|
1518
1442
|
constructor(_url) {
|
|
1519
1443
|
super();
|
|
1520
1444
|
this._url = _url;
|
|
@@ -1533,16 +1457,16 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1533
1457
|
|
|
1534
1458
|
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1535
1459
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1536
|
-
import { RangeSetBuilder as RangeSetBuilder2, StateField as
|
|
1537
|
-
import { Decoration as
|
|
1460
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField5 } from "@codemirror/state";
|
|
1461
|
+
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType4, hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
|
1538
1462
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1539
1463
|
var markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
|
|
1540
1464
|
var link = (options = {}) => {
|
|
1541
1465
|
const extensions = [
|
|
1542
|
-
|
|
1466
|
+
StateField5.define({
|
|
1543
1467
|
create: (state) => update2(state, options),
|
|
1544
1468
|
update: (_, tr) => update2(tr.state, options),
|
|
1545
|
-
provide: (field) =>
|
|
1469
|
+
provide: (field) => EditorView7.decorations.from(field)
|
|
1546
1470
|
})
|
|
1547
1471
|
];
|
|
1548
1472
|
if (options.onHover) {
|
|
@@ -1593,7 +1517,7 @@ var link = (options = {}) => {
|
|
|
1593
1517
|
}
|
|
1594
1518
|
return extensions;
|
|
1595
1519
|
};
|
|
1596
|
-
var LinkButton = class extends
|
|
1520
|
+
var LinkButton = class extends WidgetType4 {
|
|
1597
1521
|
constructor(_pos, _url, _onAttach) {
|
|
1598
1522
|
super();
|
|
1599
1523
|
this._pos = _pos;
|
|
@@ -1609,7 +1533,7 @@ var LinkButton = class extends WidgetType5 {
|
|
|
1609
1533
|
return el;
|
|
1610
1534
|
}
|
|
1611
1535
|
};
|
|
1612
|
-
var LinkText = class extends
|
|
1536
|
+
var LinkText = class extends WidgetType4 {
|
|
1613
1537
|
constructor(_text, _url) {
|
|
1614
1538
|
super();
|
|
1615
1539
|
this._text = _text;
|
|
@@ -1652,12 +1576,12 @@ var update2 = (state, options) => {
|
|
|
1652
1576
|
return false;
|
|
1653
1577
|
}
|
|
1654
1578
|
if (state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1655
|
-
builder.add(node.from, node.to,
|
|
1579
|
+
builder.add(node.from, node.to, Decoration5.replace({
|
|
1656
1580
|
widget: new LinkText(text, options.link ? url : void 0)
|
|
1657
1581
|
}));
|
|
1658
1582
|
}
|
|
1659
1583
|
if (options.onRender) {
|
|
1660
|
-
builder.add(node.to, node.to,
|
|
1584
|
+
builder.add(node.to, node.to, Decoration5.replace({
|
|
1661
1585
|
widget: new LinkButton(node.from, url, options.onRender)
|
|
1662
1586
|
}));
|
|
1663
1587
|
}
|
|
@@ -1669,14 +1593,14 @@ var update2 = (state, options) => {
|
|
|
1669
1593
|
};
|
|
1670
1594
|
|
|
1671
1595
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1672
|
-
import { EditorView as
|
|
1596
|
+
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1673
1597
|
var listener = ({ onFocus, onChange }) => {
|
|
1674
1598
|
const extensions = [];
|
|
1675
|
-
onFocus && extensions.push(
|
|
1599
|
+
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1676
1600
|
onFocus(focused);
|
|
1677
1601
|
return null;
|
|
1678
1602
|
}));
|
|
1679
|
-
onChange && extensions.push(
|
|
1603
|
+
onChange && extensions.push(EditorView8.updateListener.of((update4) => {
|
|
1680
1604
|
onChange(update4.state.doc.toString());
|
|
1681
1605
|
}));
|
|
1682
1606
|
return extensions;
|
|
@@ -1691,7 +1615,7 @@ import { languages } from "@codemirror/language-data";
|
|
|
1691
1615
|
import { searchKeymap } from "@codemirror/search";
|
|
1692
1616
|
import { EditorState } from "@codemirror/state";
|
|
1693
1617
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1694
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1618
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1695
1619
|
|
|
1696
1620
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1697
1621
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
@@ -1894,7 +1818,7 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1894
1818
|
return [
|
|
1895
1819
|
EditorState.allowMultipleSelections.of(true),
|
|
1896
1820
|
EditorState.tabSize.of(2),
|
|
1897
|
-
|
|
1821
|
+
EditorView9.lineWrapping,
|
|
1898
1822
|
customKeymap(),
|
|
1899
1823
|
bracketMatching2(),
|
|
1900
1824
|
closeBrackets2(),
|
|
@@ -1972,13 +1896,13 @@ var mermaid = () => {
|
|
|
1972
1896
|
|
|
1973
1897
|
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1974
1898
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1975
|
-
import { RangeSetBuilder as RangeSetBuilder3, StateField as
|
|
1976
|
-
import { Decoration as
|
|
1899
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
|
|
1900
|
+
import { Decoration as Decoration6, EditorView as EditorView10, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1977
1901
|
var table = (options = {}) => {
|
|
1978
|
-
return
|
|
1902
|
+
return StateField6.define({
|
|
1979
1903
|
create: (state) => update3(state, options),
|
|
1980
1904
|
update: (_, tr) => update3(tr.state, options),
|
|
1981
|
-
provide: (field) =>
|
|
1905
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1982
1906
|
});
|
|
1983
1907
|
};
|
|
1984
1908
|
var update3 = (state, options) => {
|
|
@@ -2022,17 +1946,17 @@ var update3 = (state, options) => {
|
|
|
2022
1946
|
});
|
|
2023
1947
|
tables.forEach((table2) => {
|
|
2024
1948
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2025
|
-
hide && builder.add(table2.from, table2.to,
|
|
1949
|
+
hide && builder.add(table2.from, table2.to, Decoration6.replace({
|
|
2026
1950
|
block: true,
|
|
2027
1951
|
widget: new TableWidget(table2)
|
|
2028
1952
|
}));
|
|
2029
|
-
builder.add(table2.from, table2.to,
|
|
1953
|
+
builder.add(table2.from, table2.to, Decoration6.mark({
|
|
2030
1954
|
class: "cm-table"
|
|
2031
1955
|
}));
|
|
2032
1956
|
});
|
|
2033
1957
|
return builder.finish();
|
|
2034
1958
|
};
|
|
2035
|
-
var TableWidget = class extends
|
|
1959
|
+
var TableWidget = class extends WidgetType5 {
|
|
2036
1960
|
constructor(_table) {
|
|
2037
1961
|
super();
|
|
2038
1962
|
this._table = _table;
|
|
@@ -2067,14 +1991,14 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2067
1991
|
};
|
|
2068
1992
|
|
|
2069
1993
|
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2070
|
-
import { EditorView as
|
|
2071
|
-
var
|
|
1994
|
+
import { EditorView as EditorView11, Decoration as Decoration7, WidgetType as WidgetType6, MatchDecorator as MatchDecorator3, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1995
|
+
var styles4 = EditorView11.baseTheme({
|
|
2072
1996
|
"& .cm-task-item": {
|
|
2073
1997
|
paddingLeft: "4px",
|
|
2074
1998
|
paddingRight: "8px"
|
|
2075
1999
|
}
|
|
2076
2000
|
});
|
|
2077
|
-
var CheckboxWidget = class extends
|
|
2001
|
+
var CheckboxWidget = class extends WidgetType6 {
|
|
2078
2002
|
constructor(_pos, _checked, _indent, _onCheck) {
|
|
2079
2003
|
super();
|
|
2080
2004
|
this._pos = _pos;
|
|
@@ -2114,7 +2038,7 @@ var tasklist = (options = {}) => {
|
|
|
2114
2038
|
decoration: (match, view, pos) => {
|
|
2115
2039
|
const indent = Math.floor(match[1].length / 2);
|
|
2116
2040
|
const checked = match[2] === "x" || match[2] === "X";
|
|
2117
|
-
return
|
|
2041
|
+
return Decoration7.replace({
|
|
2118
2042
|
widget: new CheckboxWidget(pos, checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2119
2043
|
const idx = pos + match[0].indexOf("[") + 1;
|
|
2120
2044
|
view.dispatch({
|
|
@@ -2132,7 +2056,7 @@ var tasklist = (options = {}) => {
|
|
|
2132
2056
|
});
|
|
2133
2057
|
}
|
|
2134
2058
|
});
|
|
2135
|
-
const tasks =
|
|
2059
|
+
const tasks = ViewPlugin5.fromClass(class {
|
|
2136
2060
|
constructor(view) {
|
|
2137
2061
|
this.tasks = taskMatcher.createDeco(view);
|
|
2138
2062
|
}
|
|
@@ -2141,13 +2065,13 @@ var tasklist = (options = {}) => {
|
|
|
2141
2065
|
}
|
|
2142
2066
|
}, {
|
|
2143
2067
|
decorations: (value) => value.tasks,
|
|
2144
|
-
provide: (plugin) =>
|
|
2145
|
-
return view.plugin(plugin)?.tasks ||
|
|
2068
|
+
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2069
|
+
return view.plugin(plugin)?.tasks || Decoration7.none;
|
|
2146
2070
|
})
|
|
2147
2071
|
});
|
|
2148
2072
|
return [
|
|
2149
2073
|
tasks,
|
|
2150
|
-
|
|
2074
|
+
styles4
|
|
2151
2075
|
];
|
|
2152
2076
|
};
|
|
2153
2077
|
|
|
@@ -2208,27 +2132,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2208
2132
|
];
|
|
2209
2133
|
};
|
|
2210
2134
|
|
|
2211
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2212
|
-
import { yCollab } from "y-codemirror.next";
|
|
2213
|
-
|
|
2214
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2215
|
-
import * as Y from "yjs";
|
|
2216
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2217
|
-
var cursorConverter2 = (text) => ({
|
|
2218
|
-
toCursor: (index, assoc) => {
|
|
2219
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2220
|
-
},
|
|
2221
|
-
fromCursor: (cursor) => {
|
|
2222
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2223
|
-
}
|
|
2224
|
-
});
|
|
2225
|
-
|
|
2226
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2227
|
-
var yjs = (content, awareness2) => [
|
|
2228
|
-
CursorConverter.of(cursorConverter2(content)),
|
|
2229
|
-
yCollab(content, awareness2)
|
|
2230
|
-
];
|
|
2231
|
-
|
|
2232
2135
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2233
2136
|
import get6 from "lodash.get";
|
|
2234
2137
|
var defaultTheme = {
|
|
@@ -2511,8 +2414,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2511
2414
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2512
2415
|
tabBehavior: "limited"
|
|
2513
2416
|
});
|
|
2514
|
-
const [root, setRoot] =
|
|
2515
|
-
const [{ state = void 0, view = void 0 } = {}, setEditor] =
|
|
2417
|
+
const [root, setRoot] = useState2(null);
|
|
2418
|
+
const [{ state = void 0, view = void 0 } = {}, setEditor] = useState2();
|
|
2516
2419
|
useImperativeHandle(forwardedRef, () => ({
|
|
2517
2420
|
root,
|
|
2518
2421
|
state,
|
|
@@ -2522,10 +2425,10 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2522
2425
|
state,
|
|
2523
2426
|
root
|
|
2524
2427
|
]);
|
|
2525
|
-
const { awareness
|
|
2526
|
-
|
|
2527
|
-
if (
|
|
2528
|
-
|
|
2428
|
+
const { awareness, peer } = model;
|
|
2429
|
+
useEffect2(() => {
|
|
2430
|
+
if (awareness && peer) {
|
|
2431
|
+
awareness.setLocalStateField("user", {
|
|
2529
2432
|
name: peer.name ?? generateName(peer.id),
|
|
2530
2433
|
color: getColorForValue({
|
|
2531
2434
|
value: peer.id,
|
|
@@ -2539,11 +2442,11 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2539
2442
|
});
|
|
2540
2443
|
}
|
|
2541
2444
|
}, [
|
|
2542
|
-
|
|
2445
|
+
awareness,
|
|
2543
2446
|
peer,
|
|
2544
2447
|
themeMode
|
|
2545
2448
|
]);
|
|
2546
|
-
|
|
2449
|
+
useEffect2(() => {
|
|
2547
2450
|
if (view && comments2?.length) {
|
|
2548
2451
|
view.dispatch({
|
|
2549
2452
|
effects: setCommentRange.of({
|
|
@@ -2556,7 +2459,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2556
2459
|
view,
|
|
2557
2460
|
comments2
|
|
2558
2461
|
]);
|
|
2559
|
-
|
|
2462
|
+
useEffect2(() => {
|
|
2560
2463
|
if (!root) {
|
|
2561
2464
|
return;
|
|
2562
2465
|
}
|
|
@@ -2568,9 +2471,9 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2568
2471
|
editorMode === "vim" && vim(),
|
|
2569
2472
|
// Theme.
|
|
2570
2473
|
// TODO(burdon): Make theme configurable.
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2474
|
+
EditorView12.baseTheme(defaultTheme),
|
|
2475
|
+
EditorView12.theme(slots?.editor?.theme ?? {}),
|
|
2476
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
|
2574
2477
|
// Storage and replication.
|
|
2575
2478
|
model.extension,
|
|
2576
2479
|
// Custom.
|
|
@@ -2580,7 +2483,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2580
2483
|
view?.destroy();
|
|
2581
2484
|
setEditor({
|
|
2582
2485
|
state: state2,
|
|
2583
|
-
view: new
|
|
2486
|
+
view: new EditorView12({
|
|
2584
2487
|
state: state2,
|
|
2585
2488
|
parent: root
|
|
2586
2489
|
})
|
|
@@ -2674,370 +2577,23 @@ var defaultMarkdownSlots = {
|
|
|
2674
2577
|
theme: markdownTheme
|
|
2675
2578
|
}
|
|
2676
2579
|
};
|
|
2677
|
-
|
|
2678
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2679
|
-
import get7 from "lodash.get";
|
|
2680
|
-
import { getRawDoc } from "@dxos/echo-schema";
|
|
2681
|
-
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2682
|
-
|
|
2683
|
-
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2684
|
-
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2685
|
-
import { Context as Context2 } from "@dxos/context";
|
|
2686
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2687
|
-
import { log as log3 } from "@dxos/log";
|
|
2688
|
-
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2689
|
-
var DEBOUNCE_INTERVAL = 100;
|
|
2690
|
-
var SpaceAwarenessProvider = class {
|
|
2691
|
-
constructor(params) {
|
|
2692
|
-
this.remoteStateChange = new Event2();
|
|
2693
|
-
this._remoteStates = /* @__PURE__ */ new Map();
|
|
2694
|
-
this._space = params.space;
|
|
2695
|
-
this._channel = params.channel;
|
|
2696
|
-
this._peerId = params.peerId;
|
|
2697
|
-
this._info = params.info;
|
|
2698
|
-
}
|
|
2699
|
-
open() {
|
|
2700
|
-
this._ctx = new Context2();
|
|
2701
|
-
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
2702
|
-
if (this._localState) {
|
|
2703
|
-
await this._space.postMessage(this._channel, {
|
|
2704
|
-
kind: "post",
|
|
2705
|
-
state: this._localState
|
|
2706
|
-
});
|
|
2707
|
-
await sleep(DEBOUNCE_INTERVAL);
|
|
2708
|
-
}
|
|
2709
|
-
});
|
|
2710
|
-
const unsubscribe = this._space.listen(this._channel, (message) => {
|
|
2711
|
-
switch (message.payload.kind) {
|
|
2712
|
-
case "query": {
|
|
2713
|
-
this._handleQueryMessage();
|
|
2714
|
-
break;
|
|
2715
|
-
}
|
|
2716
|
-
case "post": {
|
|
2717
|
-
this._handlePostMessage(message.payload);
|
|
2718
|
-
break;
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
});
|
|
2722
|
-
this._ctx.onDispose(unsubscribe);
|
|
2723
|
-
void this._space.postMessage(this._channel, {
|
|
2724
|
-
kind: "query"
|
|
2725
|
-
}).catch((err) => {
|
|
2726
|
-
log3.debug("failed to query awareness", {
|
|
2727
|
-
err
|
|
2728
|
-
}, {
|
|
2729
|
-
F: __dxlog_file4,
|
|
2730
|
-
L: 85,
|
|
2731
|
-
S: this,
|
|
2732
|
-
C: (f, a) => f(...a)
|
|
2733
|
-
});
|
|
2734
|
-
});
|
|
2735
|
-
}
|
|
2736
|
-
close() {
|
|
2737
|
-
void this._ctx?.dispose();
|
|
2738
|
-
this._ctx = void 0;
|
|
2739
|
-
this._postTask = void 0;
|
|
2740
|
-
}
|
|
2741
|
-
update(position) {
|
|
2742
|
-
invariant3(this._postTask, void 0, {
|
|
2743
|
-
F: __dxlog_file4,
|
|
2744
|
-
L: 96,
|
|
2745
|
-
S: this,
|
|
2746
|
-
A: [
|
|
2747
|
-
"this._postTask",
|
|
2748
|
-
""
|
|
2749
|
-
]
|
|
2750
|
-
});
|
|
2751
|
-
this._localState = {
|
|
2752
|
-
peerId: this._peerId,
|
|
2753
|
-
position,
|
|
2754
|
-
info: this._info
|
|
2755
|
-
};
|
|
2756
|
-
this._postTask.schedule();
|
|
2757
|
-
}
|
|
2758
|
-
getRemoteStates() {
|
|
2759
|
-
return Array.from(this._remoteStates.values());
|
|
2760
|
-
}
|
|
2761
|
-
_handleQueryMessage() {
|
|
2762
|
-
invariant3(this._postTask, void 0, {
|
|
2763
|
-
F: __dxlog_file4,
|
|
2764
|
-
L: 111,
|
|
2765
|
-
S: this,
|
|
2766
|
-
A: [
|
|
2767
|
-
"this._postTask",
|
|
2768
|
-
""
|
|
2769
|
-
]
|
|
2770
|
-
});
|
|
2771
|
-
this._postTask.schedule();
|
|
2772
|
-
}
|
|
2773
|
-
_handlePostMessage(message) {
|
|
2774
|
-
invariant3(message.kind === "post", void 0, {
|
|
2775
|
-
F: __dxlog_file4,
|
|
2776
|
-
L: 116,
|
|
2777
|
-
S: this,
|
|
2778
|
-
A: [
|
|
2779
|
-
"message.kind === 'post'",
|
|
2780
|
-
""
|
|
2781
|
-
]
|
|
2782
|
-
});
|
|
2783
|
-
this._remoteStates.set(message.state.peerId, message.state);
|
|
2784
|
-
this.remoteStateChange.emit();
|
|
2785
|
-
}
|
|
2786
|
-
};
|
|
2787
|
-
|
|
2788
|
-
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2789
|
-
import { StateField as StateField6 } from "@codemirror/state";
|
|
2790
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2791
|
-
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2792
|
-
|
|
2793
|
-
// packages/ui/react-ui-editor/src/hooks/yjs.ts
|
|
2794
|
-
import * as decoding from "lib0/decoding";
|
|
2795
|
-
import * as encoding from "lib0/encoding";
|
|
2796
|
-
import { Observable } from "lib0/observable";
|
|
2797
|
-
import * as YP from "y-protocols/awareness";
|
|
2798
|
-
import * as Y2 from "yjs";
|
|
2799
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2800
|
-
import { log as log4 } from "@dxos/log";
|
|
2801
|
-
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2802
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2803
|
-
var createYjsModel = ({ identity, space, text }) => {
|
|
2804
|
-
invariant4(text?.doc && text?.content, void 0, {
|
|
2805
|
-
F: __dxlog_file5,
|
|
2806
|
-
L: 23,
|
|
2807
|
-
S: void 0,
|
|
2808
|
-
A: [
|
|
2809
|
-
"text?.doc && text?.content",
|
|
2810
|
-
""
|
|
2811
|
-
]
|
|
2812
|
-
});
|
|
2813
|
-
const provider = space ? new YAwarenessProvider({
|
|
2814
|
-
space,
|
|
2815
|
-
doc: text.doc,
|
|
2816
|
-
channel: `yjs.awareness.${text.id}`
|
|
2817
|
-
}) : void 0;
|
|
2818
|
-
const model = {
|
|
2819
|
-
id: text.doc.guid,
|
|
2820
|
-
content: text.content,
|
|
2821
|
-
text: () => text.content.toString(),
|
|
2822
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2823
|
-
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2824
|
-
getCursorFromRange: (range) => {
|
|
2825
|
-
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2826
|
-
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2827
|
-
return [
|
|
2828
|
-
arrayToString2(from),
|
|
2829
|
-
arrayToString2(to)
|
|
2830
|
-
].join(":");
|
|
2831
|
-
},
|
|
2832
|
-
getRangeFromCursor: (cursor) => {
|
|
2833
|
-
invariant4(text.doc, void 0, {
|
|
2834
|
-
F: __dxlog_file5,
|
|
2835
|
-
L: 40,
|
|
2836
|
-
S: void 0,
|
|
2837
|
-
A: [
|
|
2838
|
-
"text.doc",
|
|
2839
|
-
""
|
|
2840
|
-
]
|
|
2841
|
-
});
|
|
2842
|
-
const parts = cursor.split(":");
|
|
2843
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2844
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2845
|
-
return from && to ? {
|
|
2846
|
-
from: from.index,
|
|
2847
|
-
to: to.index
|
|
2848
|
-
} : void 0;
|
|
2849
|
-
},
|
|
2850
|
-
extension: [
|
|
2851
|
-
modelState.init(() => model),
|
|
2852
|
-
yjs(text.content, provider?.awareness)
|
|
2853
|
-
],
|
|
2854
|
-
awareness: provider?.awareness,
|
|
2855
|
-
peer: identity ? {
|
|
2856
|
-
id: identity.identityKey.toHex(),
|
|
2857
|
-
name: identity.profile?.displayName
|
|
2858
|
-
} : void 0
|
|
2859
|
-
};
|
|
2860
|
-
return model;
|
|
2861
|
-
};
|
|
2862
|
-
var messageAwareness = 1;
|
|
2863
|
-
var messageQueryAwareness = 3;
|
|
2864
|
-
var YAwarenessProvider = class extends Observable {
|
|
2865
|
-
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2866
|
-
super();
|
|
2867
|
-
this._space = space;
|
|
2868
|
-
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2869
|
-
this._channel = channel;
|
|
2870
|
-
this._clientId = doc.clientID;
|
|
2871
|
-
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
2872
|
-
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
2873
|
-
if (typeof window !== "undefined") {
|
|
2874
|
-
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
2875
|
-
} else if (typeof process !== "undefined") {
|
|
2876
|
-
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
2877
|
-
}
|
|
2878
|
-
const encoderAwarenessQuery = encoding.createEncoder();
|
|
2879
|
-
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
2880
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
2881
|
-
const encoderAwarenessState = encoding.createEncoder();
|
|
2882
|
-
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
2883
|
-
encoding.writeVarUint8Array(encoderAwarenessState, YP.encodeAwarenessUpdate(this.awareness, [
|
|
2884
|
-
this._clientId
|
|
2885
|
-
]));
|
|
2886
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
2887
|
-
}
|
|
2888
|
-
get awareness() {
|
|
2889
|
-
return this._awareness;
|
|
2890
|
-
}
|
|
2891
|
-
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2892
|
-
log4("awareness update", {
|
|
2893
|
-
added,
|
|
2894
|
-
updated,
|
|
2895
|
-
removed,
|
|
2896
|
-
origin
|
|
2897
|
-
}, {
|
|
2898
|
-
F: __dxlog_file5,
|
|
2899
|
-
L: 122,
|
|
2900
|
-
S: this,
|
|
2901
|
-
C: (f, a) => f(...a)
|
|
2902
|
-
});
|
|
2903
|
-
const changedClients = added.concat(updated).concat(removed);
|
|
2904
|
-
const encoderAwareness = encoding.createEncoder();
|
|
2905
|
-
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
2906
|
-
encoding.writeVarUint8Array(encoderAwareness, YP.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
2907
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2908
|
-
}
|
|
2909
|
-
_handleSpaceMessage({ payload }) {
|
|
2910
|
-
log4("space message", payload, {
|
|
2911
|
-
F: __dxlog_file5,
|
|
2912
|
-
L: 131,
|
|
2913
|
-
S: this,
|
|
2914
|
-
C: (f, a) => f(...a)
|
|
2915
|
-
});
|
|
2916
|
-
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2917
|
-
const encoder = this._readMessage(data);
|
|
2918
|
-
if (encoder) {
|
|
2919
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
2920
|
-
}
|
|
2921
|
-
}
|
|
2922
|
-
_readMessage(message) {
|
|
2923
|
-
const decoder = decoding.createDecoder(message);
|
|
2924
|
-
const encoder = encoding.createEncoder();
|
|
2925
|
-
const messageType = decoding.readVarUint(decoder);
|
|
2926
|
-
let sendReply = false;
|
|
2927
|
-
switch (messageType) {
|
|
2928
|
-
case messageAwareness: {
|
|
2929
|
-
YP.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
2930
|
-
break;
|
|
2931
|
-
}
|
|
2932
|
-
case messageQueryAwareness: {
|
|
2933
|
-
encoding.writeVarUint(encoder, messageAwareness);
|
|
2934
|
-
encoding.writeVarUint8Array(encoder, YP.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
2935
|
-
sendReply = true;
|
|
2936
|
-
break;
|
|
2937
|
-
}
|
|
2938
|
-
default: {
|
|
2939
|
-
console.error("Invalid message:", messageType);
|
|
2940
|
-
return encoder;
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
if (!sendReply) {
|
|
2944
|
-
return null;
|
|
2945
|
-
}
|
|
2946
|
-
return encoder;
|
|
2947
|
-
}
|
|
2948
|
-
_handleBeforeUnload() {
|
|
2949
|
-
YP.removeAwarenessStates(this._awareness, [
|
|
2950
|
-
this._clientId
|
|
2951
|
-
], "window unload");
|
|
2952
|
-
}
|
|
2953
|
-
};
|
|
2954
|
-
|
|
2955
|
-
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2956
|
-
var modelState = StateField6.define({
|
|
2957
|
-
create: () => void 0,
|
|
2958
|
-
update: (model) => model
|
|
2959
|
-
});
|
|
2960
|
-
var useTextModel = (props) => {
|
|
2961
|
-
const { identity, space, text } = props;
|
|
2962
|
-
const [model, setModel] = useState2(() => createModel(props));
|
|
2963
|
-
useEffect2(() => setModel(createModel(props)), [
|
|
2964
|
-
identity,
|
|
2965
|
-
space,
|
|
2966
|
-
text
|
|
2967
|
-
]);
|
|
2968
|
-
return model;
|
|
2969
|
-
};
|
|
2970
|
-
var createModel = (props) => {
|
|
2971
|
-
const { text } = props;
|
|
2972
|
-
if (isAutomergeObject(text)) {
|
|
2973
|
-
return createAutomergeModel(props);
|
|
2974
|
-
} else if (text?.doc) {
|
|
2975
|
-
return createYjsModel(props);
|
|
2976
|
-
} else {
|
|
2977
|
-
return void 0;
|
|
2978
|
-
}
|
|
2979
|
-
};
|
|
2980
|
-
|
|
2981
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2982
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2983
|
-
const obj = text;
|
|
2984
|
-
const doc = getRawDoc(obj, [
|
|
2985
|
-
obj.field
|
|
2986
|
-
]);
|
|
2987
|
-
const awarenessProvider = space && new SpaceAwarenessProvider({
|
|
2988
|
-
space,
|
|
2989
|
-
channel: `automerge.awareness.${obj.id}`,
|
|
2990
|
-
info: {
|
|
2991
|
-
displayName: identity?.profile?.displayName ?? "",
|
|
2992
|
-
color: cursorColor.color,
|
|
2993
|
-
lightColor: cursorColor.light
|
|
2994
|
-
},
|
|
2995
|
-
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2996
|
-
});
|
|
2997
|
-
const model = {
|
|
2998
|
-
id: obj.id,
|
|
2999
|
-
content: doc,
|
|
3000
|
-
text: () => get7(doc.handle.docSync(), doc.path),
|
|
3001
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3002
|
-
extension: [
|
|
3003
|
-
modelState.init(() => model),
|
|
3004
|
-
automerge3({
|
|
3005
|
-
handle: doc.handle,
|
|
3006
|
-
path: doc.path
|
|
3007
|
-
}),
|
|
3008
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
3009
|
-
awareness()
|
|
3010
|
-
].filter(isNotNullOrUndefined),
|
|
3011
|
-
peer: identity ? {
|
|
3012
|
-
id: identity.identityKey.toHex(),
|
|
3013
|
-
name: identity.profile?.displayName
|
|
3014
|
-
} : void 0
|
|
3015
|
-
};
|
|
3016
|
-
return model;
|
|
3017
|
-
};
|
|
3018
2580
|
export {
|
|
3019
|
-
AwarenessProvider,
|
|
3020
2581
|
BaseTextEditor,
|
|
3021
2582
|
Doc,
|
|
3022
2583
|
EditorModes,
|
|
3023
2584
|
MarkdownEditor,
|
|
3024
|
-
RemoteSelectionsDecorator,
|
|
3025
2585
|
SpaceAwarenessProvider,
|
|
3026
2586
|
TextEditor,
|
|
3027
2587
|
TextKind,
|
|
3028
|
-
YAwarenessProvider,
|
|
3029
2588
|
YText,
|
|
3030
2589
|
YXmlFragment,
|
|
3031
2590
|
autocomplete,
|
|
3032
|
-
automerge3 as automerge,
|
|
3033
|
-
awareness,
|
|
3034
2591
|
basicBundle,
|
|
3035
2592
|
blast,
|
|
3036
2593
|
code2 as code,
|
|
3037
2594
|
codeTheme,
|
|
3038
2595
|
comments,
|
|
3039
|
-
|
|
3040
|
-
createYjsModel,
|
|
2596
|
+
cursorColor,
|
|
3041
2597
|
defaultMarkdownSlots,
|
|
3042
2598
|
defaultOptions,
|
|
3043
2599
|
defaultSlots,
|
|
@@ -3063,7 +2619,6 @@ export {
|
|
|
3063
2619
|
tasklist,
|
|
3064
2620
|
textTheme,
|
|
3065
2621
|
typewriter,
|
|
3066
|
-
useTextModel
|
|
3067
|
-
yjs
|
|
2622
|
+
useTextModel
|
|
3068
2623
|
};
|
|
3069
2624
|
//# sourceMappingURL=index.mjs.map
|