@inkandswitch/patchwork-pkg-base 0.0.40 → 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/package.json +1 -1
  2. package/packages/account/dist/{InlineContactAvatar-TVDLE2AV.js → InlineContactAvatar-6UAAJ73R.js} +2 -1
  3. package/packages/account/dist/InlineContactAvatar-6UAAJ73R.js.map +7 -0
  4. package/packages/account/dist/index.js +1 -1
  5. package/packages/chat/dist/{ChatRoot-DQkQQvPO.js → ChatRoot-WdCS4aLg.js} +3001 -2807
  6. package/packages/chat/dist/{context-tool-BuY29sJF.js → context-tool-KkwLFr2k.js} +2 -2
  7. package/packages/chat/dist/{index-NiYOPQzY.js → index-P8UuZ1jj.js} +3 -3
  8. package/packages/chat/dist/index.js +1 -1
  9. package/packages/chat/dist/{tool-He3mRTzT.js → tool-DWqQOW59.js} +2 -2
  10. package/packages/chat/package.json +1 -1
  11. package/packages/codemirror-base/dist/chunk-H5POLO74.js +2658 -0
  12. package/packages/codemirror-base/dist/chunk-H5POLO74.js.map +7 -0
  13. package/packages/codemirror-base/dist/lib/codemirror.js +1 -1
  14. package/packages/codemirror-base/dist/tool.js +9 -5
  15. package/packages/codemirror-base/dist/tool.js.map +2 -2
  16. package/packages/codemirror-base/package.json +1 -1
  17. package/packages/codemirror-markdown/dist/extensions/markdown.js +0 -94
  18. package/packages/codemirror-markdown/dist/extensions/markdown.js.map +3 -3
  19. package/packages/drafts/dist/assets/{DraftOverlayProvider-B0Mtq1UF.js → DraftOverlayProvider-VYKlzOy1.js} +85 -25
  20. package/packages/drafts/dist/assets/DraftOverlayProvider-VYKlzOy1.js.map +1 -0
  21. package/packages/drafts/dist/assets/{DraftListProvider-D41q9O5B.js → DraftStateProvider-DX8b_RgQ.js} +270 -39
  22. package/packages/drafts/dist/assets/DraftStateProvider-DX8b_RgQ.js.map +1 -0
  23. package/packages/drafts/dist/assets/{clone-policy-C4pVv5sr.js → clone-policy-CIdEhg7W.js} +5 -2
  24. package/packages/drafts/dist/assets/{clone-policy-C4pVv5sr.js.map → clone-policy-CIdEhg7W.js.map} +1 -1
  25. package/packages/drafts/dist/assets/draft-docs-Bi8K1y3a.js +554 -0
  26. package/packages/drafts/dist/assets/draft-docs-Bi8K1y3a.js.map +1 -0
  27. package/packages/drafts/dist/assets/main-BR_tW0sp.js +3105 -0
  28. package/packages/drafts/dist/assets/main-BR_tW0sp.js.map +1 -0
  29. package/packages/drafts/dist/index.js +14 -14
  30. package/packages/drafts/dist/index.js.map +1 -1
  31. package/packages/drafts/package.json +1 -1
  32. package/packages/threepane/dist/IsolatedDocumentArea-2JIBFDOX.js +2 -0
  33. package/packages/threepane/dist/{PatchworkFrame-4AEBOBRE.js → PatchworkFrame-P5P6JTJE.js} +2 -2
  34. package/packages/threepane/dist/chunk-CGHYPNSB.js +972 -0
  35. package/packages/threepane/dist/chunk-CGHYPNSB.js.map +7 -0
  36. package/packages/threepane/dist/index.js +1 -1
  37. package/packages/tldraw4/dist/tool.js +61 -10
  38. package/packages/tldraw4/dist/tool.js.map +2 -2
  39. package/packages/tldraw4/package.json +2 -2
  40. package/packages/account/dist/InlineContactAvatar-TVDLE2AV.js.map +0 -7
  41. package/packages/codemirror-base/dist/chunk-5IG5TKXV.js +0 -795
  42. package/packages/codemirror-base/dist/chunk-5IG5TKXV.js.map +0 -7
  43. package/packages/drafts/dist/assets/DraftListProvider-D41q9O5B.js.map +0 -1
  44. package/packages/drafts/dist/assets/DraftOverlayProvider-B0Mtq1UF.js.map +0 -1
  45. package/packages/drafts/dist/assets/main-Cp8VsNHh.js +0 -2331
  46. package/packages/drafts/dist/assets/main-Cp8VsNHh.js.map +0 -1
  47. package/packages/threepane/dist/IsolatedDocumentArea-MZBBRFMY.js +0 -2
  48. package/packages/threepane/dist/chunk-HNLVJAZZ.js +0 -972
  49. package/packages/threepane/dist/chunk-HNLVJAZZ.js.map +0 -7
  50. /package/packages/threepane/dist/{IsolatedDocumentArea-MZBBRFMY.js.map → IsolatedDocumentArea-2JIBFDOX.js.map} +0 -0
  51. /package/packages/threepane/dist/{PatchworkFrame-4AEBOBRE.js.map → PatchworkFrame-P5P6JTJE.js.map} +0 -0
@@ -1,795 +0,0 @@
1
- // src/lib/codemirror.tsx
2
- import { onCleanup, createEffect as createEffect7 } from "solid-js";
3
- import { EditorView as EditorView6 } from "@codemirror/view";
4
- import { EditorState as EditorState2, Compartment as Compartment4 } from "@codemirror/state";
5
-
6
- // src/lib/extensions/decorations.ts
7
- import { createEffect } from "solid-js";
8
- import { Decoration, EditorView } from "@codemirror/view";
9
- import { StateEffect, StateField } from "@codemirror/state";
10
- function createDecorationsExtension(decorations) {
11
- const setDecorations = StateEffect.define();
12
- const decorationsField = StateField.define({
13
- create() {
14
- return Decoration.none;
15
- },
16
- update(value, tr) {
17
- for (const e of tr.effects) {
18
- if (e.is(setDecorations)) return e.value;
19
- }
20
- if (tr.docChanged) return value.map(tr.changes);
21
- return value;
22
- },
23
- provide: (f) => EditorView.decorations.from(f)
24
- });
25
- const createDecorationsEffect = (view) => createEffect(() => {
26
- decorations() && view.dispatch({
27
- effects: setDecorations.of(decorations())
28
- });
29
- });
30
- return [decorationsField, createDecorationsEffect];
31
- }
32
-
33
- // src/lib/extensions/readOnly.ts
34
- import { createEffect as createEffect2 } from "solid-js";
35
- import { EditorView as EditorView2 } from "@codemirror/view";
36
- import { Compartment, EditorState } from "@codemirror/state";
37
- function createReadOnlyExtension(readOnly) {
38
- const readOnlyCompartment = new Compartment();
39
- const readOnlyExtensions = () => readOnly() ? [EditorState.readOnly.of(true), EditorView2.editable.of(false)] : [];
40
- const createReconfigureEffect = (view) => createEffect2(() => {
41
- view.dispatch({
42
- effects: readOnlyCompartment.reconfigure(readOnlyExtensions())
43
- });
44
- });
45
- return [
46
- readOnlyCompartment.of(readOnlyExtensions()),
47
- createReconfigureEffect
48
- ];
49
- }
50
-
51
- // src/lib/extensions/automergeSync.ts
52
- import { createEffect as createEffect3 } from "solid-js";
53
- import { Compartment as Compartment2 } from "@codemirror/state";
54
-
55
- // node_modules/.pnpm/@automerge+automerge-codemirror@0.2.0/node_modules/@automerge/automerge-codemirror/dist/plugin.js
56
- import * as A2 from "@automerge/automerge";
57
- import { ViewPlugin } from "@codemirror/view";
58
- import { Annotation } from "@codemirror/state";
59
-
60
- // node_modules/.pnpm/@automerge+automerge-codemirror@0.2.0/node_modules/@automerge/automerge-codemirror/dist/codeMirrorToAm.js
61
- import * as A from "@automerge/automerge";
62
- var applyCmTransactionsToAmHandle = (handle, path, transactions) => {
63
- const transactionsWithChanges = transactions.filter((tr) => !isReconcileTx(tr) && !tr.changes.empty);
64
- if (transactionsWithChanges.length === 0) {
65
- return;
66
- }
67
- handle.change((doc) => {
68
- transactionsWithChanges.forEach((tr) => {
69
- tr.changes.iterChanges((fromA, toA, fromB, _toB, inserted) => {
70
- A.splice(doc, path.slice(), fromB, toA - fromA, inserted.toString());
71
- });
72
- });
73
- });
74
- return A.getHeads(handle.doc());
75
- };
76
-
77
- // node_modules/.pnpm/@automerge+automerge-codemirror@0.2.0/node_modules/@automerge/automerge-codemirror/dist/amToCodemirror.js
78
- import { ChangeSet } from "@codemirror/state";
79
- var applyAmPatchesToCm = (view, target, patches) => {
80
- let selection = view.state.selection;
81
- for (const patch of patches) {
82
- const changeSpec = handlePatch(patch, target, view.state);
83
- if (changeSpec != null) {
84
- const changeSet = ChangeSet.of(changeSpec, view.state.doc.length, "\n");
85
- selection = selection.map(changeSet, 1);
86
- view.dispatch({
87
- changes: changeSet,
88
- annotations: reconcileAnnotationType.of({})
89
- });
90
- }
91
- }
92
- view.dispatch({
93
- selection,
94
- annotations: reconcileAnnotationType.of({})
95
- });
96
- };
97
- function handlePatch(patch, target, state) {
98
- if (patch.action === "insert") {
99
- return handleInsert(target, patch);
100
- } else if (patch.action === "splice") {
101
- return handleSplice(target, patch);
102
- } else if (patch.action === "del") {
103
- return handleDel(target, patch);
104
- } else if (patch.action === "put") {
105
- return handlePut(target, patch, state);
106
- } else {
107
- return null;
108
- }
109
- }
110
- function handleInsert(target, patch) {
111
- const index = charPath(target, patch.path);
112
- if (index == null) {
113
- return [];
114
- }
115
- const text = patch.values.map((v) => v ? v.toString() : "").join("");
116
- return [{ from: index, to: index, insert: text }];
117
- }
118
- function handleSplice(target, patch) {
119
- const index = charPath(target, patch.path);
120
- if (index == null) {
121
- return [];
122
- }
123
- return [{ from: index, insert: patch.value }];
124
- }
125
- function handleDel(target, patch) {
126
- const index = charPath(target, patch.path);
127
- if (index == null) {
128
- return [];
129
- }
130
- const length = patch.length || 1;
131
- return [{ from: index, to: index + length }];
132
- }
133
- function handlePut(target, patch, state) {
134
- const index = charPath(target, [...patch.path, 0]);
135
- if (index == null) {
136
- return [];
137
- }
138
- const length = state.doc.length;
139
- if (typeof patch.value !== "string") {
140
- return [];
141
- }
142
- return [{ from: 0, to: length, insert: patch.value }];
143
- }
144
- function charPath(textPath, candidatePath) {
145
- if (candidatePath.length !== textPath.length + 1)
146
- return null;
147
- for (let i = 0; i < textPath.length; i++) {
148
- if (textPath[i] !== candidatePath[i])
149
- return null;
150
- }
151
- const index = candidatePath[candidatePath.length - 1];
152
- if (typeof index === "number")
153
- return index;
154
- return null;
155
- }
156
-
157
- // node_modules/.pnpm/@automerge+automerge-codemirror@0.2.0/node_modules/@automerge/automerge-codemirror/dist/plugin.js
158
- var reconcileAnnotationType = Annotation.define();
159
- var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
160
- var automergeSyncPlugin = ({ handle, path }) => {
161
- if (!handle.isReady()) {
162
- throw new Error("ensure the handle is ready before initializing the automergeSyncPlugin");
163
- }
164
- return ViewPlugin.fromClass(class {
165
- view;
166
- reconciledHeads = A2.getHeads(handle.doc());
167
- isProcessingCmTransaction = false;
168
- constructor(view) {
169
- this.view = view;
170
- this.onChange = this.onChange.bind(this);
171
- handle.on("change", this.onChange);
172
- }
173
- update(update) {
174
- this.isProcessingCmTransaction = true;
175
- const newHeads = applyCmTransactionsToAmHandle(handle, path, update.transactions);
176
- if (newHeads) {
177
- this.reconciledHeads = newHeads;
178
- }
179
- this.isProcessingCmTransaction = false;
180
- }
181
- onChange = () => {
182
- if (this.isProcessingCmTransaction) {
183
- return;
184
- }
185
- const currentHeads = A2.getHeads(handle.doc());
186
- if (A2.equals(currentHeads, this.reconciledHeads)) {
187
- return;
188
- }
189
- const patches = A2.diff(handle.doc(), this.reconciledHeads, currentHeads);
190
- applyAmPatchesToCm(this.view, path, patches);
191
- this.reconciledHeads = currentHeads;
192
- };
193
- destroy() {
194
- handle.off("change", this.onChange);
195
- }
196
- });
197
- };
198
-
199
- // src/lib/extensions/automergeSync.ts
200
- function createSyncExtension(handle, path, initialDoc) {
201
- const sync = new Compartment2();
202
- const syncExtension = () => handle() && path() ? automergeSyncPlugin({
203
- handle: handle(),
204
- // typescript is confused by different version of doc handle
205
- path: path()
206
- }) : [];
207
- const createReconfigureEffect = (view) => createEffect3(() => {
208
- view.dispatch({
209
- effects: sync.reconfigure(syncExtension()),
210
- changes: {
211
- from: 0,
212
- to: view.state.doc.length,
213
- insert: initialDoc()
214
- }
215
- });
216
- });
217
- return [sync.of(syncExtension()), createReconfigureEffect];
218
- }
219
-
220
- // src/lib/extensions/diff.ts
221
- import { createEffect as createEffect4 } from "solid-js";
222
- import {
223
- Decoration as Decoration2,
224
- ViewPlugin as ViewPlugin2,
225
- WidgetType
226
- } from "@codemirror/view";
227
- import { RangeSet, StateEffect as StateEffect2 } from "@codemirror/state";
228
- import { next as Automerge } from "@automerge/automerge/slim";
229
- import {
230
- decodeHeads
231
- } from "@automerge/automerge-repo/slim";
232
- var setBaseline = StateEffect2.define();
233
- function createDiffExtension(handle, path, baseline) {
234
- const plugin = ViewPlugin2.fromClass(
235
- class {
236
- baseline = null;
237
- decorations = Decoration2.none;
238
- update(update) {
239
- let baselineChanged = false;
240
- for (const tr of update.transactions) {
241
- for (const effect of tr.effects) {
242
- if (effect.is(setBaseline)) {
243
- this.baseline = effect.value;
244
- baselineChanged = true;
245
- }
246
- }
247
- }
248
- if (update.docChanged || baselineChanged) {
249
- this.decorations = this.build();
250
- }
251
- }
252
- build() {
253
- const heads = this.baseline;
254
- const doc = handle()?.doc();
255
- if (!heads || !doc) return Decoration2.none;
256
- return RangeSet.of(
257
- buildDiffDecorations(
258
- diffContent(doc, heads, path()),
259
- prefersDarkMode()
260
- ),
261
- true
262
- // sort ranges
263
- );
264
- }
265
- },
266
- { decorations: (v) => v.decorations }
267
- );
268
- const createReconfigureEffect = (view) => createEffect4(() => {
269
- view.dispatch({ effects: setBaseline.of(baseline()) });
270
- });
271
- return [plugin, createReconfigureEffect];
272
- }
273
- function diffContent(doc, baselineHeads, path) {
274
- const before = decodeHeads(baselineHeads);
275
- const beforeContent = lookupString(Automerge.view(doc, before), path);
276
- const patches = Automerge.diff(doc, before, Automerge.getHeads(doc));
277
- const out = [];
278
- let offset = 0;
279
- for (const patch of patches) {
280
- if (!isIndexedChildOf(patch.path, path)) continue;
281
- const pos = patch.path[path.length];
282
- if (patch.action === "splice") {
283
- const len = patch.value.length;
284
- out.push({ type: "added", from: pos, to: pos + len });
285
- offset -= len;
286
- } else if (patch.action === "del") {
287
- const len = patch.length ?? 1;
288
- const original = pos + offset;
289
- out.push({
290
- type: "deleted",
291
- at: pos,
292
- text: beforeContent.substring(original, original + len)
293
- });
294
- offset += len;
295
- }
296
- }
297
- return out;
298
- }
299
- function buildDiffDecorations(diffs, dark) {
300
- const out = [];
301
- for (const diff2 of diffs) {
302
- if (diff2.type === "deleted") {
303
- out.push(
304
- Decoration2.widget({
305
- widget: new DeletionMarker(diff2.text, false),
306
- side: 1
307
- }).range(diff2.at)
308
- );
309
- continue;
310
- }
311
- if (diff2.from === diff2.to) continue;
312
- out.push(
313
- Decoration2.mark({
314
- attributes: { style: addedDiffStyle(dark) }
315
- }).range(diff2.from, diff2.to)
316
- );
317
- }
318
- return out;
319
- }
320
- function isIndexedChildOf(patchPath, path) {
321
- if (patchPath.length !== path.length + 1) return false;
322
- for (let i = 0; i < path.length; i++) {
323
- if (patchPath[i] !== path[i]) return false;
324
- }
325
- return typeof patchPath[path.length] === "number";
326
- }
327
- function lookupString(doc, path) {
328
- let current = doc;
329
- for (const key of path) {
330
- if (current == null) return "";
331
- current = current[key];
332
- }
333
- return typeof current === "string" ? current : "";
334
- }
335
- function addedDiffStyle(dark) {
336
- return `
337
- border-bottom: 2px solid ${dark ? "#4ade80" : "#22c55e"};
338
- background-color: ${dark ? "#14532d" : "#dcfce7"};
339
- `;
340
- }
341
- function prefersDarkMode() {
342
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
343
- }
344
- var DeletionMarker = class extends WidgetType {
345
- deletedText;
346
- isActive;
347
- constructor(deletedText, isActive) {
348
- super();
349
- this.deletedText = deletedText;
350
- this.isActive = isActive;
351
- }
352
- toDOM() {
353
- const box = document.createElement("div");
354
- box.style.display = "inline-block";
355
- box.style.position = "relative";
356
- box.style.lineHeight = "1";
357
- box.style.verticalAlign = "middle";
358
- box.style.boxSizing = "border-box";
359
- box.style.padding = "2px 3px";
360
- box.style.color = "rgb(239 68 68)";
361
- box.style.margin = "0 4px";
362
- box.style.fontSize = "1.2em";
363
- box.style.whiteSpace = "nowrap";
364
- box.style.backgroundColor = this.isActive ? "rgb(239 68 68 / 20%)" : "rgb(239 68 68 / 10%)";
365
- box.style.borderRadius = "3px";
366
- box.style.cursor = "default";
367
- box.innerText = "\u232B";
368
- const hoverText = document.createElement("div");
369
- hoverText.style.position = "absolute";
370
- hoverText.style.top = "100%";
371
- hoverText.style.left = "0";
372
- hoverText.style.zIndex = "1";
373
- hoverText.style.padding = "5px";
374
- hoverText.style.backgroundColor = "rgb(254 242 242)";
375
- hoverText.style.fontSize = "15px";
376
- hoverText.style.color = "rgb(17 24 39)";
377
- hoverText.style.border = "1px solid rgb(185 28 28)";
378
- hoverText.style.boxShadow = "0px 0px 6px rgba(0, 0, 0, 0.1)";
379
- hoverText.style.borderRadius = "3px";
380
- hoverText.style.visibility = "hidden";
381
- hoverText.innerText = this.deletedText;
382
- const isDarkMode = document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
383
- if (isDarkMode) {
384
- box.style.color = "rgb(248 113 113)";
385
- box.style.backgroundColor = this.isActive ? "rgb(248 113 113 / 20%)" : "rgb(248 113 113 / 10%)";
386
- hoverText.style.backgroundColor = "rgb(69 10 10)";
387
- hoverText.style.color = "rgb(254 226 226)";
388
- hoverText.style.border = "1px solid rgb(153 27 27)";
389
- }
390
- box.appendChild(hoverText);
391
- box.onmouseover = function() {
392
- hoverText.style.visibility = "visible";
393
- };
394
- box.onmouseout = function() {
395
- hoverText.style.visibility = "hidden";
396
- };
397
- return box;
398
- }
399
- eq(other) {
400
- return other.deletedText === this.deletedText && other.isActive === this.isActive;
401
- }
402
- ignoreEvent() {
403
- return true;
404
- }
405
- };
406
-
407
- // src/lib/extensions/scrollHighlightIntoView.ts
408
- import { createEffect as createEffect5 } from "solid-js";
409
- import { EditorView as EditorView4 } from "@codemirror/view";
410
- import { EditorSelection } from "@codemirror/state";
411
- function createScrollHighlightIntoViewExtension(target) {
412
- const extension = [];
413
- const createScrollHighlightIntoViewEffect = (view) => createEffect5(() => {
414
- const range = target();
415
- if (!range) return;
416
- const docLength = view.state.doc.length;
417
- const from = Math.min(range[0], docLength);
418
- const to = Math.min(range[1], docLength);
419
- view.dispatch({
420
- effects: EditorView4.scrollIntoView(EditorSelection.range(from, to), {
421
- x: "nearest",
422
- y: "nearest"
423
- })
424
- });
425
- });
426
- return [extension, createScrollHighlightIntoViewEffect];
427
- }
428
-
429
- // src/lib/extensions/presence.ts
430
- import { createEffect as createEffect6 } from "solid-js";
431
- import {
432
- Decoration as Decoration3,
433
- EditorView as EditorView5,
434
- RectangleMarker,
435
- ViewPlugin as ViewPlugin3,
436
- layer
437
- } from "@codemirror/view";
438
- import {
439
- Compartment as Compartment3,
440
- EditorSelection as EditorSelection2,
441
- StateEffect as StateEffect3,
442
- StateField as StateField2,
443
- Transaction
444
- } from "@codemirror/state";
445
- import {
446
- next as A3
447
- } from "@automerge/automerge/slim";
448
- import {
449
- Presence
450
- } from "@automerge/automerge-repo/slim";
451
- function createPresenceExtension(handle, path, contactUrl) {
452
- const compartment = new Compartment3();
453
- const extension = () => {
454
- const url = contactUrl();
455
- return url ? presence(handle(), path(), url) : [];
456
- };
457
- const createReconfigureEffect = (view) => createEffect6(() => {
458
- view.dispatch({ effects: compartment.reconfigure(extension()) });
459
- });
460
- return [compartment.of(extension()), createReconfigureEffect];
461
- }
462
- function presence(handle, path, contactUrl) {
463
- const setRemoteSelections = StateEffect3.define();
464
- const remoteSelectionField = StateField2.define({
465
- create() {
466
- return [];
467
- },
468
- update(value, tr) {
469
- if (tr.docChanged) {
470
- value = value.map((sel) => ({
471
- ...sel,
472
- from: tr.changes.mapPos(sel.from),
473
- to: tr.changes.mapPos(sel.to),
474
- head: tr.changes.mapPos(sel.head)
475
- }));
476
- }
477
- for (const e of tr.effects) {
478
- if (e.is(setRemoteSelections)) value = e.value;
479
- }
480
- return value;
481
- },
482
- // Selection tints are plain mark decorations: they carry no stateful
483
- // DOM, so redrawing them is invisible.
484
- provide: (f) => EditorView5.decorations.from(f, buildSelectionTints)
485
- });
486
- const caretLayer = layer({
487
- above: true,
488
- class: "cm-presence-layer",
489
- update: (update) => update.docChanged || update.transactions.some(
490
- (tr) => tr.effects.some((e) => e.is(setRemoteSelections))
491
- ),
492
- markers(view) {
493
- const selections = [...view.state.field(remoteSelectionField)].sort(
494
- (a, b) => a.peerId < b.peerId ? -1 : a.peerId > b.peerId ? 1 : 0
495
- );
496
- const markers = [];
497
- for (const sel of selections) {
498
- const [rect] = RectangleMarker.forRange(
499
- view,
500
- "cm-presence-caret",
501
- EditorSelection2.cursor(sel.head)
502
- );
503
- if (!rect) continue;
504
- markers.push(
505
- new PresenceCaretMarker(sel, rect.left, rect.top, rect.height)
506
- );
507
- }
508
- return markers;
509
- }
510
- });
511
- const plugin = ViewPlugin3.fromClass(
512
- class {
513
- view;
514
- presence;
515
- destroyed = false;
516
- broadcastQueued = false;
517
- constructor(view) {
518
- this.view = view;
519
- this.presence = new Presence({
520
- handle,
521
- userId: contactUrl
522
- });
523
- this.presence.start({ initialState: { selection: null } });
524
- this.presence.on("update", this.refresh);
525
- this.presence.on("snapshot", this.refresh);
526
- this.presence.on("goodbye", this.refresh);
527
- this.presence.on("pruned", this.refresh);
528
- window.addEventListener("pagehide", this.stopPresence);
529
- }
530
- update(update) {
531
- const typed = update.docChanged && update.transactions.some(
532
- (tr) => tr.annotation(Transaction.userEvent) !== void 0
533
- );
534
- if (update.focusChanged && !update.view.hasFocus) {
535
- if (this.presence.running) {
536
- this.presence.broadcast("selection", null);
537
- }
538
- } else if (update.selectionSet || typed || update.focusChanged && update.view.hasFocus) {
539
- this.scheduleBroadcast();
540
- }
541
- if (update.docChanged) {
542
- queueMicrotask(this.refresh);
543
- }
544
- }
545
- destroy() {
546
- this.destroyed = true;
547
- this.stopPresence();
548
- window.removeEventListener("pagehide", this.stopPresence);
549
- }
550
- stopPresence = () => {
551
- if (this.presence.running) this.presence.stop();
552
- };
553
- // rAF-throttled (matching tldraw4) so drag-selections don't flood the
554
- // channel. The selection is read fresh at flush time.
555
- scheduleBroadcast() {
556
- if (this.broadcastQueued) return;
557
- this.broadcastQueued = true;
558
- requestAnimationFrame(() => {
559
- this.broadcastQueued = false;
560
- if (this.destroyed || !this.presence.running) return;
561
- if (!this.view.hasFocus) return;
562
- const doc = handle.doc();
563
- const sel = this.view.state.selection.main;
564
- this.presence.broadcast("selection", {
565
- start: A3.getCursor(doc, path, sel.from),
566
- end: A3.getCursor(doc, path, sel.to),
567
- headAtStart: sel.to > sel.from && sel.head === sel.from,
568
- lastMoved: Date.now()
569
- });
570
- });
571
- }
572
- // Re-resolve every peer's cursors against the current doc. A cursor can
573
- // briefly fail to resolve when a presence message races ahead of doc
574
- // sync -- the peer is skipped and picked up again on the next change.
575
- refresh = () => {
576
- if (this.destroyed) return;
577
- const doc = handle.doc();
578
- const resolved = [];
579
- for (const peer of this.presence.getPeerStates().peers) {
580
- const peerId = String(peer.peerId);
581
- const selection = peer.value?.selection ?? null;
582
- if (!selection) continue;
583
- try {
584
- const from = A3.getCursorPosition(doc, path, selection.start);
585
- const to = A3.getCursorPosition(doc, path, selection.end);
586
- const peerContactUrl = peer.userId ?? null;
587
- resolved.push({
588
- peerId,
589
- contactUrl: peerContactUrl,
590
- // Same rule as the contact-cursor token (palette hash of the
591
- // contact url), so the tint and the token can't drift apart.
592
- color: generateColorFromString(peerContactUrl ?? peerId),
593
- from,
594
- to,
595
- head: selection.headAtStart ? from : to,
596
- lastMoved: selection.lastMoved
597
- });
598
- } catch {
599
- continue;
600
- }
601
- }
602
- this.view.dispatch({ effects: setRemoteSelections.of(resolved) });
603
- };
604
- }
605
- );
606
- return [remoteSelectionField, caretLayer, plugin, presenceTheme];
607
- }
608
- function buildSelectionTints(selections) {
609
- const ranges = [];
610
- for (const sel of selections) {
611
- if (sel.from < sel.to) {
612
- ranges.push(
613
- Decoration3.mark({
614
- class: "cm-presence-range",
615
- attributes: {
616
- style: `background-color: color-mix(in srgb, ${sel.color} 25%, transparent);`
617
- }
618
- }).range(sel.from, sel.to)
619
- );
620
- }
621
- }
622
- return Decoration3.set(ranges, true);
623
- }
624
- var LABEL_TIMEOUT_MS = 2e3;
625
- var PresenceCaretMarker = class {
626
- sel;
627
- left;
628
- top;
629
- height;
630
- constructor(sel, left, top, height) {
631
- this.sel = sel;
632
- this.left = left;
633
- this.top = top;
634
- this.height = height;
635
- }
636
- eq(other) {
637
- return other.sel.peerId === this.sel.peerId && other.sel.contactUrl === this.sel.contactUrl && other.sel.color === this.sel.color && other.sel.lastMoved === this.sel.lastMoved && other.left === this.left && other.top === this.top && other.height === this.height;
638
- }
639
- draw() {
640
- const caret = document.createElement("div");
641
- caret.className = "cm-presence-caret";
642
- caret.dataset.peerId = this.sel.peerId;
643
- if (this.sel.contactUrl) {
644
- const label = document.createElement("span");
645
- label.className = "cm-presence-caret-label";
646
- const token = document.createElement("patchwork-view");
647
- token.setAttribute("doc-url", this.sel.contactUrl);
648
- token.setAttribute("tool-id", "contact-cursor");
649
- token.style.display = "block";
650
- label.appendChild(token);
651
- caret.appendChild(label);
652
- }
653
- this.adjust(caret);
654
- restartIdleCountdown(caret);
655
- return caret;
656
- }
657
- // Reposition the peer's existing element instead of redrawing it, keeping
658
- // the mounted contact token alive (a remount re-renders asynchronously and
659
- // flickers -- see the layer comment in `presence`).
660
- update(dom, prev) {
661
- if (prev.sel.peerId !== this.sel.peerId || prev.sel.contactUrl !== this.sel.contactUrl) {
662
- return false;
663
- }
664
- this.adjust(dom);
665
- if (prev.sel.lastMoved !== this.sel.lastMoved) restartIdleCountdown(dom);
666
- return true;
667
- }
668
- adjust(dom) {
669
- dom.style.left = `${this.left}px`;
670
- dom.style.top = `${this.top}px`;
671
- dom.style.height = `${this.height}px`;
672
- dom.style.setProperty("--cm-presence-color", this.sel.color);
673
- }
674
- };
675
- var idleTimers = /* @__PURE__ */ new WeakMap();
676
- function restartIdleCountdown(caret) {
677
- clearTimeout(idleTimers.get(caret));
678
- caret.classList.remove("cm-presence-caret--idle");
679
- idleTimers.set(
680
- caret,
681
- setTimeout(
682
- () => caret.classList.add("cm-presence-caret--idle"),
683
- LABEL_TIMEOUT_MS
684
- )
685
- );
686
- }
687
- var presenceTheme = EditorView5.baseTheme({
688
- // Positioned absolutely by the layer (document-relative); -1px centers
689
- // the 2px bar on the caret position.
690
- ".cm-presence-caret": {
691
- borderLeft: "2px solid var(--cm-presence-color)",
692
- marginLeft: "-1px",
693
- pointerEvents: "none"
694
- },
695
- ".cm-presence-caret-label": {
696
- position: "absolute",
697
- top: "-1.4em",
698
- left: "-2px",
699
- zIndex: "150",
700
- whiteSpace: "nowrap",
701
- pointerEvents: "none",
702
- userSelect: "none",
703
- opacity: "1",
704
- transition: "opacity 200ms ease-in-out"
705
- },
706
- ".cm-presence-caret--idle .cm-presence-caret-label": {
707
- opacity: "0"
708
- }
709
- });
710
- var USER_COLOR_PALETTE = [
711
- "hsl(200, 70%, 50%)",
712
- "hsl(10, 75%, 58%)",
713
- "hsl(145, 70%, 45%)",
714
- "hsl(270, 70%, 55%)",
715
- "hsl(38, 85%, 50%)",
716
- "hsl(350, 70%, 55%)",
717
- "hsl(178, 70%, 45%)",
718
- "hsl(235, 70%, 58%)",
719
- "hsl(85, 70%, 45%)",
720
- "hsl(310, 70%, 55%)",
721
- "hsl(25, 80%, 52%)",
722
- "hsl(188, 75%, 48%)"
723
- ];
724
- function generateColorFromString(str) {
725
- const hash = Math.abs(
726
- str.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0)
727
- );
728
- return USER_COLOR_PALETTE[hash % USER_COLOR_PALETTE.length];
729
- }
730
-
731
- // src/lib/codemirror.tsx
732
- var lookup = (doc, path) => {
733
- let current = doc;
734
- for (const key of path) {
735
- current = current[key];
736
- if (current === void 0) {
737
- return void 0;
738
- }
739
- }
740
- return current;
741
- };
742
- function CodeMirror(props) {
743
- const initialDoc = () => props.handle && lookup(props.handle.doc(), props.path) || "";
744
- const [syncExtension, createEffectReconfigureSync] = createSyncExtension(() => props.handle, () => props.path, initialDoc);
745
- const [readOnlyExtension, createEffectReconfigureReadOnly] = createReadOnlyExtension(() => !!props.readOnly);
746
- const [decorationsExtension, createEffectReconfigureDecorations] = createDecorationsExtension(() => props.decorations?.());
747
- const [diffExtension, createEffectReconfigureDiff] = createDiffExtension(() => props.handle, () => props.path, () => props.baseline?.() ?? null);
748
- const [scrollHighlightIntoViewExtension, createEffectScrollHighlightIntoView] = createScrollHighlightIntoViewExtension(() => props.scrollTarget?.() ?? null);
749
- const [presenceExtension, createEffectReconfigurePresence] = createPresenceExtension(() => props.handle, () => props.path, () => props.readOnly ? null : props.contactUrl?.() ?? null);
750
- const userExtensionsCompartment = new Compartment4();
751
- const selectionExtension = EditorView6.updateListener.of((update) => {
752
- if (!props.onChangeSelection) return;
753
- if (update.selectionSet) {
754
- const sel = update.state.selection.main;
755
- props.onChangeSelection(sel.from, sel.to);
756
- }
757
- });
758
- const extensions = [
759
- selectionExtension,
760
- decorationsExtension,
761
- // syncExtension must come before diffExtension so diff stays in sync with edits.
762
- syncExtension,
763
- diffExtension,
764
- scrollHighlightIntoViewExtension,
765
- presenceExtension,
766
- userExtensionsCompartment.of(props.extensions || []),
767
- readOnlyExtension
768
- ].filter(Boolean);
769
- const state = EditorState2.create({
770
- doc: initialDoc(),
771
- extensions
772
- });
773
- const view = new EditorView6({
774
- state
775
- });
776
- props.withView?.(view);
777
- createEffectReconfigureSync(view);
778
- createEffectReconfigureReadOnly(view);
779
- createEffectReconfigureDecorations?.(view);
780
- createEffectReconfigureDiff(view);
781
- createEffectScrollHighlightIntoView(view);
782
- createEffectReconfigurePresence(view);
783
- createEffect7(() => {
784
- view.dispatch({
785
- effects: userExtensionsCompartment.reconfigure(props.extensions || [])
786
- });
787
- });
788
- onCleanup(() => view.destroy());
789
- return view.dom;
790
- }
791
-
792
- export {
793
- CodeMirror
794
- };
795
- //# sourceMappingURL=chunk-5IG5TKXV.js.map