@inkandswitch/patchwork-pkg-base 0.0.54 → 0.0.56
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/package.json +1 -1
- package/packages/account/dist/{AccountPicker-HMEN6MEN.js → AccountPicker-HB6MDLKN.js} +390 -123
- package/packages/account/dist/AccountPicker-HB6MDLKN.js.map +7 -0
- package/packages/account/dist/{ContactAvatar-KCZOCABR.js → ContactAvatar-KM4BONY5.js} +7 -7
- package/packages/account/dist/ContactAvatar-KM4BONY5.js.map +7 -0
- package/packages/account/dist/{ContactCursor-RLXRAX65.js → ContactCursor-4FYCATG5.js} +6 -6
- package/packages/account/dist/ContactCursor-4FYCATG5.js.map +7 -0
- package/packages/account/dist/index.css +96 -15
- package/packages/account/dist/index.css.map +2 -2
- package/packages/account/dist/index.js +3 -3
- package/packages/codemirror-base/dist/{chunk-H5POLO74.js → chunk-AKNT5U37.js} +43 -28
- package/packages/codemirror-base/dist/chunk-AKNT5U37.js.map +7 -0
- package/packages/codemirror-base/dist/lib/codemirror.js +1 -1
- package/packages/codemirror-base/dist/tool.js +21 -3
- package/packages/codemirror-base/dist/tool.js.map +2 -2
- package/packages/comments-view/dist/assets/main-BPvgT7fH.js +1 -1
- package/packages/tldraw4/dist/tool.js +3 -23
- package/packages/tldraw4/dist/tool.js.map +2 -2
- package/packages/account/dist/AccountPicker-HMEN6MEN.js.map +0 -7
- package/packages/account/dist/ContactAvatar-KCZOCABR.js.map +0 -7
- package/packages/account/dist/ContactCursor-RLXRAX65.js.map +0 -7
- package/packages/account/dist/chunk-3YUNEZX6.js +0 -38
- package/packages/account/dist/chunk-3YUNEZX6.js.map +0 -7
- package/packages/codemirror-base/dist/chunk-H5POLO74.js.map +0 -7
|
@@ -4,9 +4,6 @@ import {
|
|
|
4
4
|
setAvatarFallback,
|
|
5
5
|
setAvatarImage
|
|
6
6
|
} from "./chunk-PLRZBPU4.js";
|
|
7
|
-
import {
|
|
8
|
-
generateColorFromString
|
|
9
|
-
} from "./chunk-3YUNEZX6.js";
|
|
10
7
|
import "./chunk-5WRI5ZAA.js";
|
|
11
8
|
|
|
12
9
|
// src/contact/ContactAvatar.ts
|
|
@@ -58,16 +55,19 @@ function renderContactAvatar(handle, element) {
|
|
|
58
55
|
updatePresence();
|
|
59
56
|
}
|
|
60
57
|
function updatePresence() {
|
|
61
|
-
const docUrl = handle.url;
|
|
62
58
|
const now = Date.now();
|
|
63
59
|
const timeout = 3e4;
|
|
64
60
|
const isPresent = Object.entries(heartbeats).some(
|
|
65
61
|
([id, ts]) => id !== selfName && now - ts < timeout
|
|
66
62
|
);
|
|
67
|
-
const userColor =
|
|
63
|
+
const userColor = handle.doc()?.color;
|
|
68
64
|
if (isPresent) {
|
|
69
65
|
avatar.classList.add("contact-avatar--present");
|
|
70
|
-
|
|
66
|
+
if (userColor) {
|
|
67
|
+
avatar.style.setProperty("--contact-presence-color", userColor);
|
|
68
|
+
} else {
|
|
69
|
+
avatar.style.removeProperty("--contact-presence-color");
|
|
70
|
+
}
|
|
71
71
|
} else {
|
|
72
72
|
avatar.classList.remove("contact-avatar--present");
|
|
73
73
|
avatar.style.removeProperty("--contact-presence-color");
|
|
@@ -138,4 +138,4 @@ function renderContactAvatar(handle, element) {
|
|
|
138
138
|
export {
|
|
139
139
|
renderContactAvatar
|
|
140
140
|
};
|
|
141
|
-
//# sourceMappingURL=ContactAvatar-
|
|
141
|
+
//# sourceMappingURL=ContactAvatar-KM4BONY5.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/contact/ContactAvatar.ts", "../node_modules/.pnpm/@inkandswitch+patchwork-providers@0.2.2_@automerge+automerge-repo@2.6.0-subduction.12/node_modules/@inkandswitch/patchwork-providers/dist/index.js"],
|
|
4
|
+
"sourcesContent": ["import type { AutomergeUrl, DocHandle } from \"@automerge/automerge-repo/slim\";\nimport type { ToolElement } from \"@inkandswitch/patchwork-plugins\";\nimport type { ContactDoc } from \"../types\";\nimport { createAvatar, setAvatarImage, setAvatarFallback, getInitials } from \"./Avatar\";\nimport { getImportableUrlFromAutomergeUrl } from \"@inkandswitch/patchwork-filesystem\";\nimport { subscribe } from \"@inkandswitch/patchwork-providers\";\n\ndeclare global {\n interface Window {\n accountDocHandle?: { url: AutomergeUrl };\n }\n}\n\ntype TinyPatchworkLayoutDoc = {\n contactUrl: AutomergeUrl;\n};\n\nexport function renderContactAvatar(\n handle: DocHandle<ContactDoc>,\n element: ToolElement\n) {\n const avatar = createAvatar(\"default\");\n element.appendChild(avatar);\n\n let selfName = \"me\";\n const cleanups: (() => void)[] = [];\n\n // Track presence via ephemeral messages\n const heartbeats: Record<string, number> = {};\n let presenceTimer: ReturnType<typeof setInterval>;\n\n function onEphemeralMessage(message: { senderId: string; message: unknown }) {\n // useRemoteAwareness tracks heartbeats from ephemeral messages\n if (message.senderId) {\n heartbeats[message.senderId] = Date.now();\n }\n updatePresence();\n }\n\n function updatePresence() {\n const now = Date.now();\n const timeout = 30000;\n const isPresent = Object.entries(heartbeats).some(\n ([id, ts]) => id !== selfName && now - ts < timeout\n );\n\n // The contact's chosen color; without one, the CSS fallback (neutral\n // gray) applies.\n const userColor = handle.doc()?.color;\n\n if (isPresent) {\n avatar.classList.add(\"contact-avatar--present\");\n if (userColor) {\n avatar.style.setProperty(\"--contact-presence-color\", userColor);\n } else {\n avatar.style.removeProperty(\"--contact-presence-color\");\n }\n } else {\n avatar.classList.remove(\"contact-avatar--present\");\n avatar.style.removeProperty(\"--contact-presence-color\");\n }\n }\n\n handle.on(\"ephemeral-message\", onEphemeralMessage);\n cleanups.push(() => handle.off(\"ephemeral-message\", onEphemeralMessage));\n\n // Periodically clean up stale heartbeats\n presenceTimer = setInterval(updatePresence, 5000);\n cleanups.push(() => clearInterval(presenceTimer));\n\n // Get own contact via provider subscription\n const unsubscribe = subscribe<string>(\n element,\n { type: \"patchwork:contact\" },\n (contactUrl) => {\n element.repo\n .find<ContactDoc>(contactUrl as AutomergeUrl)\n .then((selfHandle) => {\n const selfDoc = selfHandle.doc();\n if (selfDoc?.type === \"registered\") {\n selfName = selfDoc.name;\n }\n });\n }\n );\n cleanups.push(unsubscribe);\n\n // Fallback: use window.accountDocHandle\n if (window.accountDocHandle) {\n element.repo\n .find<TinyPatchworkLayoutDoc>(window.accountDocHandle.url)\n .then((accountHandle) => {\n const accountDoc = accountHandle.doc();\n if (accountDoc?.contactUrl) {\n element.repo\n .find<ContactDoc>(accountDoc.contactUrl)\n .then((selfHandle) => {\n const selfDoc = selfHandle.doc();\n if (selfDoc?.type === \"registered\") {\n selfName = selfDoc.name;\n }\n });\n }\n });\n }\n\n async function update() {\n const contact = handle.doc();\n if (!contact) {\n avatar.style.display = \"none\";\n return;\n }\n avatar.style.display = \"\";\n\n const isRegistered = contact.type === \"registered\";\n const name = isRegistered ? contact.name : \"Anonymous\";\n\n // avatar image\n let avatarImgUrl: string | undefined;\n if (isRegistered && contact.avatarUrl) {\n try {\n const avatarHandle = await element.repo.find(contact.avatarUrl);\n avatarImgUrl = getImportableUrlFromAutomergeUrl(avatarHandle.url);\n } catch {\n // ignore failed avatar lookup\n }\n }\n setAvatarImage(avatar, avatarImgUrl, name);\n\n // fallback\n if (isRegistered && name) {\n setAvatarFallback(avatar, { initials: getInitials(name) });\n } else {\n setAvatarFallback(avatar, { iconSize: 20 });\n }\n\n updatePresence();\n }\n\n handle.on(\"change\", update);\n cleanups.push(() => handle.off(\"change\", update));\n update();\n\n return () => {\n for (const cleanup of cleanups) cleanup();\n };\n}\n", "/**\n * Open a streaming subscription. Dispatches a `patchwork:subscribe` for the\n * given `selector` carrying a fresh `MessageChannel` port; the answering\n * provider pushes values back over that channel for as long as the\n * subscription is live. `listener` is invoked once per emission (the first\n * delivery is always async because `MessagePort.postMessage` queues a task).\n *\n * The event is dispatched from the nearest enclosing `<patchwork-view>` so\n * callers can pass any node inside a provider subtree. An unclaimed\n * subscription is never settled: if no provider answers, `listener` simply\n * never fires.\n *\n * Returns an unsubscribe function. Calling it tells the provider to tear down\n * (via an `unsubscribe` message) and closes the consumer's port; any values\n * the provider emits after that are dropped.\n */\nexport function subscribe(element, selector, listener) {\n const view = element.closest(\"patchwork-view\");\n const dispatchEl = view ?? element;\n const channel = new MessageChannel();\n const port = channel.port2;\n const controller = new AbortController();\n const { signal } = controller;\n port.addEventListener(\"message\", (event) => {\n if (event.data?.type === \"change\")\n listener(event.data.value);\n }, { signal });\n // addEventListener (unlike assigning onmessage) does not implicitly start\n // the port, so message delivery has to be kicked off explicitly.\n port.start();\n const detail = {\n selector,\n port: channel.port1,\n };\n dispatchEl.dispatchEvent(new CustomEvent(\"patchwork:subscribe\", {\n detail,\n bubbles: true,\n composed: true,\n }));\n return () => {\n if (signal.aborted)\n return;\n controller.abort();\n port.postMessage({ type: \"unsubscribe\" });\n port.close();\n };\n}\n/**\n * Answer a `patchwork:subscribe`. The `producer` receives a `respond`\n * callback it can call any number of times to push values to the consumer,\n * and may return a teardown that runs when the consumer unsubscribes. Stops\n * propagation so ancestor providers don't double-answer. Values emitted after\n * the consumer unsubscribes are dropped.\n */\nexport function accept(event, producer) {\n event.stopPropagation();\n const port = event.detail.port;\n let alive = true;\n const respond = (value) => {\n if (!alive)\n return;\n port.postMessage({ type: \"change\", value });\n };\n let teardown;\n try {\n teardown = producer(respond);\n }\n catch (err) {\n console.error(\"[patchwork-providers] subscribe producer threw:\", err);\n }\n const stop = () => {\n if (!alive)\n return;\n alive = false;\n try {\n teardown?.();\n }\n catch (err) {\n console.error(\"[patchwork-providers] subscribe teardown threw:\", err);\n }\n port.close();\n };\n port.onmessage = (event) => {\n if (event.data?.type === \"unsubscribe\")\n stop();\n };\n}\n/**\n * One-shot convenience wrapper over {@link subscribe}: opens a subscription\n * for `selector`, resolves with the first value a provider emits, then\n * immediately unsubscribes. Because there is no fallback provider, an\n * unclaimed selector never resolves \u2014 use `subscribe` directly if you need to\n * handle the \"no provider\" case.\n */\nexport function request(element, selector) {\n return new Promise((resolve) => {\n const unsubscribe = subscribe(element, selector, (value) => {\n // The first emission is always async (postMessage queues a task), so\n // `unsubscribe` is assigned by the time this fires.\n unsubscribe();\n resolve(value);\n });\n });\n}\nexport { registerRepoProviderElement, } from \"./repo-provider.js\";\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
generateColorFromString
|
|
3
|
-
} from "./chunk-3YUNEZX6.js";
|
|
4
1
|
import "./chunk-5WRI5ZAA.js";
|
|
5
2
|
|
|
6
3
|
// src/contact/ContactCursor.ts
|
|
@@ -16,8 +13,11 @@ function renderContactCursor(handle, element) {
|
|
|
16
13
|
}
|
|
17
14
|
token.style.display = "";
|
|
18
15
|
const name = contact.type === "registered" ? contact.name : "Anonymous";
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
if (contact.color) {
|
|
17
|
+
token.style.setProperty("--contact-cursor-color", contact.color);
|
|
18
|
+
} else {
|
|
19
|
+
token.style.removeProperty("--contact-cursor-color");
|
|
20
|
+
}
|
|
21
21
|
token.textContent = name;
|
|
22
22
|
token.title = name;
|
|
23
23
|
}
|
|
@@ -31,4 +31,4 @@ function renderContactCursor(handle, element) {
|
|
|
31
31
|
export {
|
|
32
32
|
renderContactCursor
|
|
33
33
|
};
|
|
34
|
-
//# sourceMappingURL=ContactCursor-
|
|
34
|
+
//# sourceMappingURL=ContactCursor-4FYCATG5.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/contact/ContactCursor.ts"],
|
|
4
|
+
"sourcesContent": ["import type { DocHandle } from \"@automerge/automerge-repo/slim\";\nimport type { ToolElement } from \"@inkandswitch/patchwork-plugins\";\nimport type { ContactDoc } from \"../types\";\n\n/**\n * A compact cursor token: the contact's name on a pill in their presence\n * color. Hosts that render remote cursors (text editors, canvases) mount it\n * next to their own cursor primitive (caret line, pointer arrow) via\n * `<patchwork-view doc-url={contactUrl} tool-id=\"contact-cursor\">`.\n */\nexport function renderContactCursor(\n handle: DocHandle<ContactDoc>,\n element: ToolElement\n) {\n const token = document.createElement(\"div\");\n token.className = \"contact-cursor-token\";\n element.appendChild(token);\n\n function update() {\n const contact = handle.doc();\n if (!contact) {\n token.style.display = \"none\";\n return;\n }\n token.style.display = \"\";\n const name = contact.type === \"registered\" ? contact.name : \"Anonymous\";\n // The contact's chosen color; without one, the CSS fallback (neutral\n // gray) applies.\n if (contact.color) {\n token.style.setProperty(\"--contact-cursor-color\", contact.color);\n } else {\n token.style.removeProperty(\"--contact-cursor-color\");\n }\n token.textContent = name;\n token.title = name;\n }\n\n handle.on(\"change\", update);\n update();\n\n return () => {\n handle.off(\"change\", update);\n token.remove();\n };\n}\n"],
|
|
5
|
+
"mappings": ";;;AAUO,SAAS,oBACd,QACA,SACA;AACA,QAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,QAAM,YAAY;AAClB,UAAQ,YAAY,KAAK;AAEzB,WAAS,SAAS;AAChB,UAAM,UAAU,OAAO,IAAI;AAC3B,QAAI,CAAC,SAAS;AACZ,YAAM,MAAM,UAAU;AACtB;AAAA,IACF;AACA,UAAM,MAAM,UAAU;AACtB,UAAM,OAAO,QAAQ,SAAS,eAAe,QAAQ,OAAO;AAG5D,QAAI,QAAQ,OAAO;AACjB,YAAM,MAAM,YAAY,0BAA0B,QAAQ,KAAK;AAAA,IACjE,OAAO;AACL,YAAM,MAAM,eAAe,wBAAwB;AAAA,IACrD;AACA,UAAM,cAAc;AACpB,UAAM,QAAQ;AAAA,EAChB;AAEA,SAAO,GAAG,UAAU,MAAM;AAC1B,SAAO;AAEP,SAAO,MAAM;AACX,WAAO,IAAI,UAAU,MAAM;AAC3B,UAAM,OAAO;AAAA,EACf;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
height: 64px;
|
|
43
43
|
}
|
|
44
44
|
.contact-avatar--present {
|
|
45
|
-
box-shadow: 0 0 0 2px var(--contact-presence-color);
|
|
45
|
+
box-shadow: 0 0 0 2px var(--contact-presence-color, #888);
|
|
46
46
|
}
|
|
47
47
|
.contact-avatar-image {
|
|
48
48
|
position: absolute;
|
|
@@ -118,26 +118,50 @@
|
|
|
118
118
|
padding: 1.5rem 2rem;
|
|
119
119
|
color: var(--account-picker-fg);
|
|
120
120
|
& .profile-header {
|
|
121
|
+
position: relative;
|
|
121
122
|
display: flex;
|
|
122
|
-
align-items:
|
|
123
|
+
align-items: flex-start;
|
|
123
124
|
gap: 0.75rem;
|
|
124
125
|
margin-bottom: 1.5rem;
|
|
125
126
|
}
|
|
126
|
-
& .
|
|
127
|
+
& .identity {
|
|
127
128
|
position: relative;
|
|
128
129
|
flex-shrink: 0;
|
|
130
|
+
display: flex;
|
|
131
|
+
flex-direction: column;
|
|
132
|
+
align-items: flex-start;
|
|
133
|
+
gap: 0.125rem;
|
|
134
|
+
}
|
|
135
|
+
& .presence-slot {
|
|
136
|
+
width: 0;
|
|
137
|
+
overflow: visible;
|
|
129
138
|
}
|
|
130
139
|
& .avatar-button {
|
|
140
|
+
position: relative;
|
|
131
141
|
background: none;
|
|
132
142
|
border: none;
|
|
133
143
|
padding: 0;
|
|
134
|
-
|
|
144
|
+
margin-inline-start: 5px;
|
|
135
145
|
border-radius: 50%;
|
|
136
146
|
flex-shrink: 0;
|
|
137
147
|
overflow: hidden;
|
|
138
148
|
width: 56px;
|
|
139
149
|
height: 56px;
|
|
140
150
|
display: block;
|
|
151
|
+
cursor: pointer;
|
|
152
|
+
&::after {
|
|
153
|
+
content: "";
|
|
154
|
+
position: absolute;
|
|
155
|
+
inset: 0;
|
|
156
|
+
border-radius: 50%;
|
|
157
|
+
background: rgb(0 0 0 / 30%);
|
|
158
|
+
opacity: 0;
|
|
159
|
+
transition: opacity 100ms;
|
|
160
|
+
}
|
|
161
|
+
&:hover::after,
|
|
162
|
+
&:focus-visible::after {
|
|
163
|
+
opacity: 1;
|
|
164
|
+
}
|
|
141
165
|
& patchwork-view {
|
|
142
166
|
display: block;
|
|
143
167
|
width: 56px;
|
|
@@ -154,6 +178,7 @@
|
|
|
154
178
|
}
|
|
155
179
|
}
|
|
156
180
|
& .input.profile-name-input {
|
|
181
|
+
margin-top: 12px;
|
|
157
182
|
font-size: 1.125rem;
|
|
158
183
|
font-weight: 600;
|
|
159
184
|
border: 1px solid transparent;
|
|
@@ -308,17 +333,36 @@
|
|
|
308
333
|
font-size: 0.75rem;
|
|
309
334
|
color: var(--account-picker-tooltip-fg);
|
|
310
335
|
}
|
|
311
|
-
& .
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
border-radius: 50%;
|
|
318
|
-
border: 2px solid var(--account-picker-bg);
|
|
336
|
+
& .presence-cursor {
|
|
337
|
+
display: inline-flex;
|
|
338
|
+
align-items: flex-start;
|
|
339
|
+
background: none;
|
|
340
|
+
border: none;
|
|
341
|
+
padding: 0;
|
|
319
342
|
cursor: pointer;
|
|
320
|
-
|
|
321
|
-
|
|
343
|
+
&:hover .presence-nametag {
|
|
344
|
+
opacity: 0.85;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
& .presence-cursor-arrow {
|
|
348
|
+
width: 16px;
|
|
349
|
+
height: 24px;
|
|
350
|
+
flex-shrink: 0;
|
|
351
|
+
filter: drop-shadow(0 1px 1px rgb(0 0 0 / 25%));
|
|
352
|
+
}
|
|
353
|
+
& .presence-nametag {
|
|
354
|
+
margin-top: 12px;
|
|
355
|
+
margin-inline-start: -3px;
|
|
356
|
+
padding: 2px 6px;
|
|
357
|
+
border-radius: 4px;
|
|
358
|
+
font-size: 0.75rem;
|
|
359
|
+
font-weight: 500;
|
|
360
|
+
line-height: 1.3;
|
|
361
|
+
color: white;
|
|
362
|
+
max-width: 12rem;
|
|
363
|
+
overflow: hidden;
|
|
364
|
+
text-overflow: ellipsis;
|
|
365
|
+
white-space: nowrap;
|
|
322
366
|
}
|
|
323
367
|
& .color-popup {
|
|
324
368
|
position: absolute;
|
|
@@ -329,7 +373,7 @@
|
|
|
329
373
|
border: 1px solid var(--account-picker-border);
|
|
330
374
|
border-radius: 8px;
|
|
331
375
|
box-shadow: 0 4px 16px rgb(0 0 0 / 12%);
|
|
332
|
-
z-index:
|
|
376
|
+
z-index: 30;
|
|
333
377
|
}
|
|
334
378
|
& .color-grid {
|
|
335
379
|
display: grid;
|
|
@@ -455,6 +499,43 @@
|
|
|
455
499
|
max-width: 90vw;
|
|
456
500
|
box-shadow: 0 8px 30px rgb(0 0 0 / 10%);
|
|
457
501
|
}
|
|
502
|
+
& .cropper-modal {
|
|
503
|
+
width: auto;
|
|
504
|
+
align-items: center;
|
|
505
|
+
}
|
|
506
|
+
& .cropper-viewport {
|
|
507
|
+
position: relative;
|
|
508
|
+
width: 260px;
|
|
509
|
+
height: 260px;
|
|
510
|
+
overflow: hidden;
|
|
511
|
+
border-radius: 6px;
|
|
512
|
+
background: var(--account-picker-border);
|
|
513
|
+
cursor: grab;
|
|
514
|
+
touch-action: none;
|
|
515
|
+
&:active {
|
|
516
|
+
cursor: grabbing;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
& .cropper-image {
|
|
520
|
+
position: absolute;
|
|
521
|
+
top: 0;
|
|
522
|
+
left: 0;
|
|
523
|
+
transform-origin: 0 0;
|
|
524
|
+
max-width: none;
|
|
525
|
+
user-select: none;
|
|
526
|
+
-webkit-user-drag: none;
|
|
527
|
+
}
|
|
528
|
+
& .cropper-mask {
|
|
529
|
+
position: absolute;
|
|
530
|
+
inset: 0;
|
|
531
|
+
border-radius: 50%;
|
|
532
|
+
box-shadow: 0 0 0 9999px rgb(0 0 0 / 45%);
|
|
533
|
+
pointer-events: none;
|
|
534
|
+
}
|
|
535
|
+
& .cropper-zoom {
|
|
536
|
+
width: 260px;
|
|
537
|
+
accent-color: var(--account-picker-fg);
|
|
538
|
+
}
|
|
458
539
|
& .modal-title {
|
|
459
540
|
font-size: 0.875rem;
|
|
460
541
|
font-weight: 600;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/contact/styles.css", "../src/picker/styles.css"],
|
|
4
|
-
"sourcesContent": ["@layer package {\n:root,\n:host,\n[theme] {\n --contact-fg: var(--editor-line, black);\n --contact-muted-fg: var(--editor-line-offset-50, #999);\n --contact-border: var(--editor-fill-offset-10, #e5e5e5);\n --contact-fallback-bg: var(--editor-fill-offset-20, #ccc);\n --contact-fallback-fg: var(--editor-line-offset-30, #4d4d4d);\n --contact-family: var(--editor-family-sans, system-ui, sans-serif);\n}\n}\n\n/* Avatar */\n\n.contact-avatar {\n position: relative;\n display: inline-flex;\n flex-shrink: 0;\n overflow: hidden;\n border-radius: 9999px;\n border: 1px solid var(--contact-border);\n min-width: 2rem;\n min-height: 2rem;\n max-width: 2rem;\n max-height: 2rem;\n height: 100%;\n width: 100%;\n}\n\n.contact-avatar--sm {\n min-width: initial;\n min-height: initial;\n max-width: initial;\n max-height: initial;\n width: 1.5rem;\n height: 1.5rem;\n}\n\n.contact-avatar--lg {\n min-width: initial;\n min-height: initial;\n max-width: initial;\n max-height: initial;\n width: 64px;\n height: 64px;\n}\n\n.contact-avatar--present {\n box-shadow: 0 0 0 2px var(--contact-presence-color);\n}\n\n.contact-avatar-image {\n position: absolute;\n inset: 0;\n z-index: 1;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.contact-avatar-fallback {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 9999px;\n background: var(--contact-fallback-bg);\n color: var(--contact-fallback-fg);\n}\n\n/* Contact Viewer */\n\n.contact-viewer {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5rem;\n color: var(--contact-fg);\n}\n\n.contact-viewer-name {\n margin: 0;\n font-size: 1.25rem;\n font-weight: 600;\n}\n\n.contact-viewer-label {\n margin: 0;\n font-size: 0.875rem;\n color: var(--contact-muted-fg);\n}\n\n/* Cursor token (tool id \"contact-cursor\") \u2014 the contact's name on a pill in\n their presence color. Hosts overlay it next to their own cursor primitive,\n so it must not intercept pointer events. The pill background is the user's\n presence color (not a theme surface), so the label uses white ink, which is\n legible across the whole USER_COLOR_PALETTE. */\n\n.contact-cursor-token {\n display: inline-block;\n max-width: 160px;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--contact-cursor-color, #888);\n color: white;\n font-family: var(--contact-family, system-ui, sans-serif);\n font-size: 11px;\n font-weight: 500;\n line-height: 1.3;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n user-select: none;\n pointer-events: none;\n}\n", "@layer package {\n:root,\n:host,\n[theme] {\n --account-picker-fg: var(--studio-line, black);\n --account-picker-muted: var(--studio-line-offset-50, #999);\n --account-picker-bg: var(--studio-fill, white);\n --account-picker-border: var(--studio-fill-offset-10, #e5e5e5);\n --account-picker-hover: var(--studio-fill-offset-10, #e5e5e5);\n --account-picker-tooltip-bg: var(--studio-line, black);\n --account-picker-tooltip-fg: var(--studio-fill, white);\n}\n}\n\n.account-picker {\n width: 100%;\n height: 100%;\n overflow: auto;\n padding: 1.5rem 2rem;\n color: var(--account-picker-fg);\n\n & .profile-header {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 1.5rem;\n }\n\n & .avatar-area {\n position: relative;\n flex-shrink: 0;\n }\n\n & .avatar-button {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n border-radius: 50%;\n flex-shrink: 0;\n overflow: hidden;\n width: 56px;\n height: 56px;\n display: block;\n\n & patchwork-view {\n display: block;\n width: 56px;\n height: 56px;\n overflow: hidden;\n }\n\n & img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n border: none;\n outline: none;\n }\n }\n\n & .input.profile-name-input {\n font-size: 1.125rem;\n font-weight: 600;\n border: 1px solid transparent;\n background: transparent;\n padding: 0.25rem 0.375rem;\n border-radius: 4px;\n height: auto;\n\n &:focus-visible {\n outline: 2px solid var(--account-picker-fg);\n outline-offset: 1px;\n }\n }\n\n & .actions {\n display: flex;\n flex-wrap: wrap;\n gap: 0.375rem;\n margin-bottom: 1rem;\n }\n\n & .section {\n margin-bottom: 0.25rem;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0.25rem;\n }\n\n & .field-group {\n display: grid;\n width: 100%;\n gap: 0.5rem;\n padding-block: 0.5rem;\n }\n\n & .input-row {\n display: flex;\n gap: 0.25rem;\n }\n\n & .tabs-list {\n display: grid;\n grid-template-columns: 1fr 1fr;\n height: 2rem;\n align-items: center;\n border-radius: 6px;\n background: var(--account-picker-border);\n padding: 2px;\n color: var(--account-picker-muted);\n }\n\n & .tabs-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n padding: 0.25rem 0.5rem;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n border: none;\n background: transparent;\n color: inherit;\n transition: all 100ms;\n\n &[data-selected] {\n background: var(--account-picker-bg);\n color: var(--account-picker-fg);\n box-shadow: 0 1px 2px rgb(0 0 0 / 6%);\n }\n }\n\n & .tabs-content {\n margin-top: 0.5rem;\n }\n\n & .btn {\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n border-radius: 4px;\n font-size: 0.8125rem;\n font-weight: 500;\n border: none;\n height: 2rem;\n padding: 0 0.75rem;\n transition: all 100ms;\n color: var(--account-picker-fg);\n\n &:disabled {\n pointer-events: none;\n opacity: 0.3;\n }\n\n &.default {\n background: var(--account-picker-fg);\n color: var(--account-picker-bg);\n\n &:hover {\n opacity: 0.85;\n }\n }\n\n &.outline,\n &.secondary,\n &.ghost {\n background: var(--account-picker-bg);\n border: 1px solid var(--account-picker-border);\n box-shadow: 0 1px 2px rgb(0 0 0 / 5%);\n\n &:hover {\n background: var(--account-picker-hover);\n box-shadow: none;\n }\n }\n }\n\n & .input {\n display: flex;\n height: 2rem;\n width: 100%;\n border-radius: 4px;\n border: 1px solid var(--account-picker-border);\n background: var(--account-picker-bg);\n padding: 0.375rem 0.5rem;\n font-size: 0.8125rem;\n color: var(--account-picker-fg);\n\n &::placeholder {\n color: var(--account-picker-muted);\n }\n\n &:focus-visible {\n outline: 2px solid var(--account-picker-fg);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.5;\n }\n\n &.valid {\n border-color: hsl(140 40% 60%);\n }\n }\n\n & .label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--account-picker-muted);\n }\n\n & .tooltip-trigger {\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n height: 2rem;\n width: 2rem;\n border: none;\n background: transparent;\n color: inherit;\n\n &:hover {\n background: var(--account-picker-hover);\n }\n }\n\n & .tooltip-content {\n z-index: 50;\n border-radius: 4px;\n background: var(--account-picker-tooltip-bg);\n padding: 0.25rem 0.5rem;\n font-size: 0.75rem;\n color: var(--account-picker-tooltip-fg);\n }\n\n /* ---- Color picker ---- */\n\n & .color-trigger {\n position: absolute;\n bottom: -1px;\n right: -1px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: 2px solid var(--account-picker-bg);\n cursor: pointer;\n z-index: 1;\n box-shadow: 0 1px 3px rgb(0 0 0 / 15%);\n }\n\n & .color-popup {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n padding: 6px;\n background: var(--account-picker-bg);\n border: 1px solid var(--account-picker-border);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgb(0 0 0 / 12%);\n z-index: 10;\n }\n\n & .color-grid {\n display: grid;\n grid-template-columns: repeat(7, 24px);\n gap: 2px;\n }\n\n & .color-swatch {\n width: 24px;\n height: 24px;\n cursor: pointer;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 3px;\n\n &:hover {\n opacity: 0.75;\n }\n\n &.selected {\n box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.5);\n }\n }\n\n & .color-swatch-custom {\n position: relative;\n overflow: hidden;\n cursor: pointer;\n background: conic-gradient(\n hsl(0 70% 55%),\n hsl(60 70% 55%),\n hsl(120 70% 55%),\n hsl(180 70% 55%),\n hsl(240 70% 55%),\n hsl(300 70% 55%),\n hsl(360 70% 55%)\n );\n\n & input {\n position: absolute;\n inset: 0;\n opacity: 0;\n cursor: pointer;\n width: 100%;\n height: 100%;\n border: none;\n padding: 0;\n }\n }\n\n & .icon {\n width: 14px;\n height: 14px;\n }\n\n & .icon-inline {\n width: 14px;\n height: 14px;\n margin-inline-end: 0.25rem;\n }\n\n & .icon-check {\n width: 14px;\n height: 14px;\n margin: auto;\n color: white;\n filter: drop-shadow(0 0.5px 1px rgb(0 0 0 / 25%));\n }\n\n & .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n & .hint {\n font-size: 0.75rem;\n color: var(--account-picker-muted);\n line-height: 1.4;\n }\n\n & .error-text {\n font-size: 0.75rem;\n color: hsl(0 70% 50%);\n min-height: 1rem;\n }\n\n & .loading-text {\n color: var(--account-picker-muted);\n }\n\n & .btn.sign-out {\n color: var(--account-picker-muted);\n\n &:hover {\n color: white;\n background: hsl(0 65% 52%);\n }\n }\n\n & .btn.sign-out-confirm {\n background: hsl(0 65% 52%);\n color: white;\n\n &:hover {\n opacity: 0.9;\n }\n }\n\n & .modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgb(0 0 0 / 20%);\n backdrop-filter: blur(2px);\n z-index: 100;\n }\n\n & .modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 101;\n background: var(--account-picker-bg);\n border: 1px solid var(--account-picker-border);\n border-radius: 8px;\n padding: 1.25rem;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n width: 20rem;\n max-width: 90vw;\n box-shadow: 0 8px 30px rgb(0 0 0 / 10%);\n }\n\n & .modal-title {\n font-size: 0.875rem;\n font-weight: 600;\n margin: 0;\n }\n\n & .modal-actions {\n display: flex;\n gap: 0.375rem;\n justify-content: flex-end;\n margin-top: 0.25rem;\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAAA;AACA;AAAA,EACA;AAAA,EACA,CAAC;AACC,kBAAc,IAAI,aAAa,EAAE;AACjC,wBAAoB,IAAI,uBAAuB,EAAE;AACjD,sBAAkB,IAAI,uBAAuB,EAAE;AAC/C,2BAAuB,IAAI,uBAAuB,EAAE;AACpD,2BAAuB,IAAI,uBAAuB,EAAE;AACpD,sBAAkB,IAAI,oBAAoB,EAAE,SAAS,EAAE;AACzD;AACA;AAIA,CAAC;AACC,YAAU;AACV,WAAS;AACT,eAAa;AACb,YAAU;AACV,iBAAe;AACf,UAAQ,IAAI,MAAM,IAAI;AACtB,aAAW;AACX,cAAY;AACZ,aAAW;AACX,cAAY;AACZ,UAAQ;AACR,SAAO;AACT;AAEA,CAAC;AACC,aAAW;AACX,cAAY;AACZ,aAAW;AACX,cAAY;AACZ,SAAO;AACP,UAAQ;AACV;AAEA,CAAC;AACC,aAAW;AACX,cAAY;AACZ,aAAW;AACX,cAAY;AACZ,SAAO;AACP,UAAQ;AACV;AAEA,CAAC;AACC,cAAY,EAAE,EAAE,EAAE,IAAI,IAAI;
|
|
4
|
+
"sourcesContent": ["@layer package {\n:root,\n:host,\n[theme] {\n --contact-fg: var(--editor-line, black);\n --contact-muted-fg: var(--editor-line-offset-50, #999);\n --contact-border: var(--editor-fill-offset-10, #e5e5e5);\n --contact-fallback-bg: var(--editor-fill-offset-20, #ccc);\n --contact-fallback-fg: var(--editor-line-offset-30, #4d4d4d);\n --contact-family: var(--editor-family-sans, system-ui, sans-serif);\n}\n}\n\n/* Avatar */\n\n.contact-avatar {\n position: relative;\n display: inline-flex;\n flex-shrink: 0;\n overflow: hidden;\n border-radius: 9999px;\n border: 1px solid var(--contact-border);\n min-width: 2rem;\n min-height: 2rem;\n max-width: 2rem;\n max-height: 2rem;\n height: 100%;\n width: 100%;\n}\n\n.contact-avatar--sm {\n min-width: initial;\n min-height: initial;\n max-width: initial;\n max-height: initial;\n width: 1.5rem;\n height: 1.5rem;\n}\n\n.contact-avatar--lg {\n min-width: initial;\n min-height: initial;\n max-width: initial;\n max-height: initial;\n width: 64px;\n height: 64px;\n}\n\n.contact-avatar--present {\n box-shadow: 0 0 0 2px var(--contact-presence-color, #888);\n}\n\n.contact-avatar-image {\n position: absolute;\n inset: 0;\n z-index: 1;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.contact-avatar-fallback {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 9999px;\n background: var(--contact-fallback-bg);\n color: var(--contact-fallback-fg);\n}\n\n/* Contact Viewer */\n\n.contact-viewer {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5rem;\n color: var(--contact-fg);\n}\n\n.contact-viewer-name {\n margin: 0;\n font-size: 1.25rem;\n font-weight: 600;\n}\n\n.contact-viewer-label {\n margin: 0;\n font-size: 0.875rem;\n color: var(--contact-muted-fg);\n}\n\n/* Cursor token (tool id \"contact-cursor\") \u2014 the contact's name on a pill in\n their presence color. Hosts overlay it next to their own cursor primitive,\n so it must not intercept pointer events. The pill background is the user's\n presence color (not a theme surface), so the label uses white ink, which is\n legible across the whole USER_COLOR_PALETTE. */\n\n.contact-cursor-token {\n display: inline-block;\n max-width: 160px;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--contact-cursor-color, #888);\n color: white;\n font-family: var(--contact-family, system-ui, sans-serif);\n font-size: 11px;\n font-weight: 500;\n line-height: 1.3;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n user-select: none;\n pointer-events: none;\n}\n", "@layer package {\n:root,\n:host,\n[theme] {\n --account-picker-fg: var(--studio-line, black);\n --account-picker-muted: var(--studio-line-offset-50, #999);\n --account-picker-bg: var(--studio-fill, white);\n --account-picker-border: var(--studio-fill-offset-10, #e5e5e5);\n --account-picker-hover: var(--studio-fill-offset-10, #e5e5e5);\n --account-picker-tooltip-bg: var(--studio-line, black);\n --account-picker-tooltip-fg: var(--studio-fill, white);\n}\n}\n\n.account-picker {\n width: 100%;\n height: 100%;\n overflow: auto;\n padding: 1.5rem 2rem;\n color: var(--account-picker-fg);\n\n & .profile-header {\n position: relative;\n display: flex;\n align-items: flex-start;\n gap: 0.75rem;\n margin-bottom: 1.5rem;\n }\n\n & .identity {\n position: relative;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0.125rem;\n }\n\n & .presence-slot {\n width: 0;\n overflow: visible;\n }\n\n\n & .avatar-button {\n position: relative;\n background: none;\n border: none;\n padding: 0;\n margin-inline-start: 5px;\n border-radius: 50%;\n flex-shrink: 0;\n overflow: hidden;\n width: 56px;\n height: 56px;\n display: block;\n cursor: pointer;\n\n &::after {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: 50%;\n background: rgb(0 0 0 / 30%);\n opacity: 0;\n transition: opacity 100ms;\n }\n\n &:hover::after,\n &:focus-visible::after {\n opacity: 1;\n }\n\n & patchwork-view {\n display: block;\n width: 56px;\n height: 56px;\n overflow: hidden;\n }\n\n & img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n border: none;\n outline: none;\n }\n }\n\n & .input.profile-name-input {\n margin-top: 12px;\n font-size: 1.125rem;\n font-weight: 600;\n border: 1px solid transparent;\n background: transparent;\n padding: 0.25rem 0.375rem;\n border-radius: 4px;\n height: auto;\n\n &:focus-visible {\n outline: 2px solid var(--account-picker-fg);\n outline-offset: 1px;\n }\n }\n\n & .actions {\n display: flex;\n flex-wrap: wrap;\n gap: 0.375rem;\n margin-bottom: 1rem;\n }\n\n & .section {\n margin-bottom: 0.25rem;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0.25rem;\n }\n\n & .field-group {\n display: grid;\n width: 100%;\n gap: 0.5rem;\n padding-block: 0.5rem;\n }\n\n & .input-row {\n display: flex;\n gap: 0.25rem;\n }\n\n & .tabs-list {\n display: grid;\n grid-template-columns: 1fr 1fr;\n height: 2rem;\n align-items: center;\n border-radius: 6px;\n background: var(--account-picker-border);\n padding: 2px;\n color: var(--account-picker-muted);\n }\n\n & .tabs-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n padding: 0.25rem 0.5rem;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n border: none;\n background: transparent;\n color: inherit;\n transition: all 100ms;\n\n &[data-selected] {\n background: var(--account-picker-bg);\n color: var(--account-picker-fg);\n box-shadow: 0 1px 2px rgb(0 0 0 / 6%);\n }\n }\n\n & .tabs-content {\n margin-top: 0.5rem;\n }\n\n & .btn {\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n border-radius: 4px;\n font-size: 0.8125rem;\n font-weight: 500;\n border: none;\n height: 2rem;\n padding: 0 0.75rem;\n transition: all 100ms;\n color: var(--account-picker-fg);\n\n &:disabled {\n pointer-events: none;\n opacity: 0.3;\n }\n\n &.default {\n background: var(--account-picker-fg);\n color: var(--account-picker-bg);\n\n &:hover {\n opacity: 0.85;\n }\n }\n\n &.outline,\n &.secondary,\n &.ghost {\n background: var(--account-picker-bg);\n border: 1px solid var(--account-picker-border);\n box-shadow: 0 1px 2px rgb(0 0 0 / 5%);\n\n &:hover {\n background: var(--account-picker-hover);\n box-shadow: none;\n }\n }\n }\n\n & .input {\n display: flex;\n height: 2rem;\n width: 100%;\n border-radius: 4px;\n border: 1px solid var(--account-picker-border);\n background: var(--account-picker-bg);\n padding: 0.375rem 0.5rem;\n font-size: 0.8125rem;\n color: var(--account-picker-fg);\n\n &::placeholder {\n color: var(--account-picker-muted);\n }\n\n &:focus-visible {\n outline: 2px solid var(--account-picker-fg);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.5;\n }\n\n &.valid {\n border-color: hsl(140 40% 60%);\n }\n }\n\n & .label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--account-picker-muted);\n }\n\n & .tooltip-trigger {\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n height: 2rem;\n width: 2rem;\n border: none;\n background: transparent;\n color: inherit;\n\n &:hover {\n background: var(--account-picker-hover);\n }\n }\n\n & .tooltip-content {\n z-index: 50;\n border-radius: 4px;\n background: var(--account-picker-tooltip-bg);\n padding: 0.25rem 0.5rem;\n font-size: 0.75rem;\n color: var(--account-picker-tooltip-fg);\n }\n\n /* ---- Color picker ---- */\n\n & .presence-cursor {\n display: inline-flex;\n align-items: flex-start;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n\n &:hover .presence-nametag {\n opacity: 0.85;\n }\n }\n\n & .presence-cursor-arrow {\n width: 16px;\n height: 24px;\n flex-shrink: 0;\n filter: drop-shadow(0 1px 1px rgb(0 0 0 / 25%));\n }\n\n & .presence-nametag {\n margin-top: 12px;\n margin-inline-start: -3px;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.75rem;\n font-weight: 500;\n line-height: 1.3;\n color: white;\n max-width: 12rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n & .color-popup {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n padding: 6px;\n background: var(--account-picker-bg);\n border: 1px solid var(--account-picker-border);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgb(0 0 0 / 12%);\n z-index: 30;\n }\n\n & .color-grid {\n display: grid;\n grid-template-columns: repeat(7, 24px);\n gap: 2px;\n }\n\n & .color-swatch {\n width: 24px;\n height: 24px;\n cursor: pointer;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 3px;\n\n &:hover {\n opacity: 0.75;\n }\n\n &.selected {\n box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.5);\n }\n }\n\n & .color-swatch-custom {\n position: relative;\n overflow: hidden;\n cursor: pointer;\n background: conic-gradient(\n hsl(0 70% 55%),\n hsl(60 70% 55%),\n hsl(120 70% 55%),\n hsl(180 70% 55%),\n hsl(240 70% 55%),\n hsl(300 70% 55%),\n hsl(360 70% 55%)\n );\n\n & input {\n position: absolute;\n inset: 0;\n opacity: 0;\n cursor: pointer;\n width: 100%;\n height: 100%;\n border: none;\n padding: 0;\n }\n }\n\n & .icon {\n width: 14px;\n height: 14px;\n }\n\n & .icon-inline {\n width: 14px;\n height: 14px;\n margin-inline-end: 0.25rem;\n }\n\n & .icon-check {\n width: 14px;\n height: 14px;\n margin: auto;\n color: white;\n filter: drop-shadow(0 0.5px 1px rgb(0 0 0 / 25%));\n }\n\n & .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n & .hint {\n font-size: 0.75rem;\n color: var(--account-picker-muted);\n line-height: 1.4;\n }\n\n & .error-text {\n font-size: 0.75rem;\n color: hsl(0 70% 50%);\n min-height: 1rem;\n }\n\n & .loading-text {\n color: var(--account-picker-muted);\n }\n\n & .btn.sign-out {\n color: var(--account-picker-muted);\n\n &:hover {\n color: white;\n background: hsl(0 65% 52%);\n }\n }\n\n & .btn.sign-out-confirm {\n background: hsl(0 65% 52%);\n color: white;\n\n &:hover {\n opacity: 0.9;\n }\n }\n\n & .modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgb(0 0 0 / 20%);\n backdrop-filter: blur(2px);\n z-index: 100;\n }\n\n & .modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 101;\n background: var(--account-picker-bg);\n border: 1px solid var(--account-picker-border);\n border-radius: 8px;\n padding: 1.25rem;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n width: 20rem;\n max-width: 90vw;\n box-shadow: 0 8px 30px rgb(0 0 0 / 10%);\n }\n\n & .cropper-modal {\n width: auto;\n align-items: center;\n }\n\n & .cropper-viewport {\n position: relative;\n width: 260px;\n height: 260px;\n overflow: hidden;\n border-radius: 6px;\n background: var(--account-picker-border);\n cursor: grab;\n touch-action: none;\n\n &:active {\n cursor: grabbing;\n }\n }\n\n & .cropper-image {\n position: absolute;\n top: 0;\n left: 0;\n transform-origin: 0 0;\n max-width: none;\n user-select: none;\n -webkit-user-drag: none;\n }\n\n & .cropper-mask {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n box-shadow: 0 0 0 9999px rgb(0 0 0 / 45%);\n pointer-events: none;\n }\n\n & .cropper-zoom {\n width: 260px;\n accent-color: var(--account-picker-fg);\n }\n\n & .modal-title {\n font-size: 0.875rem;\n font-weight: 600;\n margin: 0;\n }\n\n & .modal-actions {\n display: flex;\n gap: 0.375rem;\n justify-content: flex-end;\n margin-top: 0.25rem;\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAAA;AACA;AAAA,EACA;AAAA,EACA,CAAC;AACC,kBAAc,IAAI,aAAa,EAAE;AACjC,wBAAoB,IAAI,uBAAuB,EAAE;AACjD,sBAAkB,IAAI,uBAAuB,EAAE;AAC/C,2BAAuB,IAAI,uBAAuB,EAAE;AACpD,2BAAuB,IAAI,uBAAuB,EAAE;AACpD,sBAAkB,IAAI,oBAAoB,EAAE,SAAS,EAAE;AACzD;AACA;AAIA,CAAC;AACC,YAAU;AACV,WAAS;AACT,eAAa;AACb,YAAU;AACV,iBAAe;AACf,UAAQ,IAAI,MAAM,IAAI;AACtB,aAAW;AACX,cAAY;AACZ,aAAW;AACX,cAAY;AACZ,UAAQ;AACR,SAAO;AACT;AAEA,CAAC;AACC,aAAW;AACX,cAAY;AACZ,aAAW;AACX,cAAY;AACZ,SAAO;AACP,UAAQ;AACV;AAEA,CAAC;AACC,aAAW;AACX,cAAY;AACZ,aAAW;AACX,cAAY;AACZ,SAAO;AACP,UAAQ;AACV;AAEA,CAAC;AACC,cAAY,EAAE,EAAE,EAAE,IAAI,IAAI,wBAAwB,EAAE;AACtD;AAEA,CAAC;AACC,YAAU;AACV,SAAO;AACP,WAAS;AACT,SAAO;AACP,UAAQ;AACR,cAAY;AACd;AAEA,CAAC;AACC,YAAU;AACV,SAAO;AACP,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,iBAAe;AACf,cAAY,IAAI;AAChB,SAAO,IAAI;AACb;AAIA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,eAAa;AACb,OAAK;AACL,SAAO,IAAI;AACb;AAEA,CAAC;AACC,UAAQ;AACR,aAAW;AACX,eAAa;AACf;AAEA,CAAC;AACC,UAAQ;AACR,aAAW;AACX,SAAO,IAAI;AACb;AAQA,CAAC;AACC,WAAS;AACT,aAAW;AACX,WAAS,IAAI;AACb,iBAAe;AACf,cAAY,IAAI,sBAAsB,EAAE;AACxC,SAAO;AACP,eAAa,IAAI,gBAAgB,EAAE,SAAS,EAAE;AAC9C,aAAW;AACX,eAAa;AACb,eAAa;AACb,eAAa;AACb,YAAU;AACV,iBAAe;AACf,eAAa;AACb,kBAAgB;AAClB;;;ACpHA;AACA;AAAA,EACA;AAAA,EACA,CAAC;AACC,yBAAqB,IAAI,aAAa,EAAE;AACxC,4BAAwB,IAAI,uBAAuB,EAAE;AACrD,yBAAqB,IAAI,aAAa,EAAE;AACxC,6BAAyB,IAAI,uBAAuB,EAAE;AACtD,4BAAwB,IAAI,uBAAuB,EAAE;AACrD,iCAA6B,IAAI,aAAa,EAAE;AAChD,iCAA6B,IAAI,aAAa,EAAE;AAClD;AACA;AAEA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,YAAU;AACV,WAAS,OAAO;AAChB,SAAO,IAAI;AAEX,IAAE,CAAC;AACD,cAAU;AACV,aAAS;AACT,iBAAa;AACb,SAAK;AACL,mBAAe;AACjB;AAEA,IAAE,CAAC;AACD,cAAU;AACV,iBAAa;AACb,aAAS;AACT,oBAAgB;AAChB,iBAAa;AACb,SAAK;AACP;AAEA,IAAE,CAAC;AACD,WAAO;AACP,cAAU;AACZ;AAGA,IAAE,CAAC;AACD,cAAU;AACV,gBAAY;AACZ,YAAQ;AACR,aAAS;AACT,yBAAqB;AACrB,mBAAe;AACf,iBAAa;AACb,cAAU;AACV,WAAO;AACP,YAAQ;AACR,aAAS;AACT,YAAQ;AAER,KAAC;AACC,eAAS;AACT,gBAAU;AACV,aAAO;AACP,qBAAe;AACf,kBAAY,IAAI,EAAE,EAAE,EAAE,EAAE;AACxB,eAAS;AACT,kBAAY,QAAQ;AACtB;AAEA,KAAC,MAAM;AAAA,IACP,CAAC,cAAc;AACb,eAAS;AACX;AAEA,MAAE;AACA,eAAS;AACT,aAAO;AACP,cAAQ;AACR,gBAAU;AACZ;AAEA,MAAE;AACA,aAAO;AACP,cAAQ;AACR,kBAAY;AACZ,eAAS;AACT,cAAQ;AACR,eAAS;AACX;AACF;AAEA,IAAE,CAAC,KAAK,CAAC;AACP,gBAAY;AACZ,eAAW;AACX,iBAAa;AACb,YAAQ,IAAI,MAAM;AAClB,gBAAY;AACZ,aAAS,QAAQ;AACjB,mBAAe;AACf,YAAQ;AAER,KAAC;AACC,eAAS,IAAI,MAAM,IAAI;AACvB,sBAAgB;AAClB;AACF;AAEA,IAAE,CAAC;AACD,aAAS;AACT,eAAW;AACX,SAAK;AACL,mBAAe;AACjB;AAEA,IAAE,CAAC;AACD,mBAAe;AACf,aAAS;AACT,oBAAgB;AAChB,iBAAa;AACb,SAAK;AACP;AAEA,IAAE,CAAC;AACD,aAAS;AACT,WAAO;AACP,SAAK;AACL,mBAAe;AACjB;AAEA,IAAE,CAAC;AACD,aAAS;AACT,SAAK;AACP;AAEA,IAAE,CAAC;AACD,aAAS;AACT,2BAAuB,IAAI;AAC3B,YAAQ;AACR,iBAAa;AACb,mBAAe;AACf,gBAAY,IAAI;AAChB,aAAS;AACT,WAAO,IAAI;AACb;AAEA,IAAE,CAAC;AACD,aAAS;AACT,iBAAa;AACb,qBAAiB;AACjB,mBAAe;AACf,aAAS,QAAQ;AACjB,eAAW;AACX,iBAAa;AACb,YAAQ;AACR,YAAQ;AACR,gBAAY;AACZ,WAAO;AACP,gBAAY,IAAI;AAEhB,KAAC,CAAC;AACA,kBAAY,IAAI;AAChB,aAAO,IAAI;AACX,kBAAY,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE;AACpC;AACF;AAEA,IAAE,CAAC;AACD,gBAAY;AACd;AAEA,IAAE,CAAC;AACD,YAAQ;AACR,aAAS;AACT,iBAAa;AACb,mBAAe;AACf,eAAW;AACX,iBAAa;AACb,YAAQ;AACR,YAAQ;AACR,aAAS,EAAE;AACX,gBAAY,IAAI;AAChB,WAAO,IAAI;AAEX,KAAC;AACC,sBAAgB;AAChB,eAAS;AACX;AAEA,KAAC,CAAC;AACA,kBAAY,IAAI;AAChB,aAAO,IAAI;AAEX,OAAC;AACC,iBAAS;AACX;AACF;AAEA,KAAC,CAAC;AAAA,IACF,CAAC,CAAC;AAAA,IACF,CAAC,CAAC;AACA,kBAAY,IAAI;AAChB,cAAQ,IAAI,MAAM,IAAI;AACtB,kBAAY,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE;AAElC,OAAC;AACC,oBAAY,IAAI;AAChB,oBAAY;AACd;AACF;AACF;AAEA,IAAE,CAxHC;AAyHD,aAAS;AACT,YAAQ;AACR,WAAO;AACP,mBAAe;AACf,YAAQ,IAAI,MAAM,IAAI;AACtB,gBAAY,IAAI;AAChB,aAAS,SAAS;AAClB,eAAW;AACX,WAAO,IAAI;AAEX,KAAC;AACC,aAAO,IAAI;AACb;AAEA,KAAC;AACC,eAAS,IAAI,MAAM,IAAI;AACvB,sBAAgB;AAClB;AAEA,KAAC;AACC,eAAS;AACX;AAEA,KAAC,CAAC;AACA,oBAAc,IAAI,IAAI,IAAI;AAC5B;AACF;AAEA,IAAE,CAAC;AACD,eAAW;AACX,iBAAa;AACb,WAAO,IAAI;AACb;AAEA,IAAE,CAAC;AACD,YAAQ;AACR,aAAS;AACT,iBAAa;AACb,qBAAiB;AACjB,mBAAe;AACf,YAAQ;AACR,WAAO;AACP,YAAQ;AACR,gBAAY;AACZ,WAAO;AAEP,KAAC;AACC,kBAAY,IAAI;AAClB;AACF;AAEA,IAAE,CAAC;AACD,aAAS;AACT,mBAAe;AACf,gBAAY,IAAI;AAChB,aAAS,QAAQ;AACjB,eAAW;AACX,WAAO,IAAI;AACb;AAIA,IAAE,CAAC;AACD,aAAS;AACT,iBAAa;AACb,gBAAY;AACZ,YAAQ;AACR,aAAS;AACT,YAAQ;AAER,KAAC,OAAO,CAAC;AACP,eAAS;AACX;AACF;AAEA,IAAE,CAAC;AACD,WAAO;AACP,YAAQ;AACR,iBAAa;AACb,YAAQ,YAAY,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE;AAC5C;AAEA,IAAE,CAZS;AAaT,gBAAY;AACZ,yBAAqB;AACrB,aAAS,IAAI;AACb,mBAAe;AACf,eAAW;AACX,iBAAa;AACb,iBAAa;AACb,WAAO;AACP,eAAW;AACX,cAAU;AACV,mBAAe;AACf,iBAAa;AACf;AAEA,IAAE,CAAC;AACD,cAAU;AACV,SAAK,KAAK,KAAK,EAAE;AACjB,UAAM;AACN,aAAS;AACT,gBAAY,IAAI;AAChB,YAAQ,IAAI,MAAM,IAAI;AACtB,mBAAe;AACf,gBAAY,EAAE,IAAI,KAAK,IAAI,EAAE,EAAE,EAAE,EAAE;AACnC,aAAS;AACX;AAEA,IAAE,CAAC;AACD,aAAS;AACT,2BAAuB,OAAO,CAAC,EAAE;AACjC,SAAK;AACP;AAEA,IAAE,CAAC;AACD,WAAO;AACP,YAAQ;AACR,YAAQ;AACR,aAAS;AACT,aAAS;AACT,iBAAa;AACb,qBAAiB;AACjB,YAAQ;AACR,mBAAe;AAEf,KAAC;AACC,eAAS;AACX;AAEA,KAAC,CAAC;AACA,kBAAY,MAAM,EAAE,EAAE,EAAE,IAAI,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAClD;AACF;AAEA,IAAE,CAAC;AACD,cAAU;AACV,cAAU;AACV,YAAQ;AACR;AAAA,MAAY;AAAA,QACV,IAAI,EAAE,IAAI,IADA;AAAA,QAEV,IAAI,GAAG,IAAI,IAFD;AAAA,QAGV,IAAI,IAAI,IAAI,IAHF;AAAA,QAIV,IAAI,IAAI,IAAI,IAJF;AAAA,QAKV,IAAI,IAAI,IAAI,IALF;AAAA,QAMV,IAAI,IAAI,IAAI,IANF;AAAA,QAOV,IAAI,IAAI,IAAI;AAGd,MAAE;AACA,gBAAU;AACV,aAAO;AACP,eAAS;AACT,cAAQ;AACR,aAAO;AACP,cAAQ;AACR,cAAQ;AACR,eAAS;AACX;AACF;AAEA,IAAE,CAAC;AACD,WAAO;AACP,YAAQ;AACV;AAEA,IAAE,CAAC;AACD,WAAO;AACP,YAAQ;AACR,uBAAmB;AACrB;AAEA,IAAE,CAAC;AACD,WAAO;AACP,YAAQ;AACR,YAAQ;AACR,WAAO;AACP,YAAQ,YAAY,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE;AAC9C;AAEA,IAAE,CAAC;AACD,cAAU;AACV,WAAO;AACP,YAAQ;AACR,aAAS;AACT,YAAQ;AACR,cAAU;AACV,UAAM,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACpB,iBAAa;AACb,YAAQ;AACV;AAEA,IAAE,CAAC;AACD,eAAW;AACX,WAAO,IAAI;AACX,iBAAa;AACf;AAEA,IAAE,CAAC;AACD,eAAW;AACX,WAAO,IAAI,EAAE,IAAI;AACjB,gBAAY;AACd;AAEA,IAAE,CAAC;AACD,WAAO,IAAI;AACb;AAEA,IAAE,CA1PC,GA0PG,CAAC;AACL,WAAO,IAAI;AAEX,KAAC;AACC,aAAO;AACP,kBAAY,IAAI,EAAE,IAAI;AACxB;AACF;AAEA,IAAE,CAnQC,GAmQG,CAAC;AACL,gBAAY,IAAI,EAAE,IAAI;AACtB,WAAO;AAEP,KAAC;AACC,eAAS;AACX;AACF;AAEA,IAAE,CAAC;AACD,cAAU;AACV,WAAO;AACP,gBAAY,IAAI,EAAE,EAAE,EAAE,EAAE;AACxB,qBAAiB,KAAK;AACtB,aAAS;AACX;AAEA,IAAE,CAAC;AACD,cAAU;AACV,SAAK;AACL,UAAM;AACN,eAAW,UAAU,IAAI,EAAE;AAC3B,aAAS;AACT,gBAAY,IAAI;AAChB,YAAQ,IAAI,MAAM,IAAI;AACtB,mBAAe;AACf,aAAS;AACT,aAAS;AACT,oBAAgB;AAChB,SAAK;AACL,WAAO;AACP,eAAW;AACX,gBAAY,EAAE,IAAI,KAAK,IAAI,EAAE,EAAE,EAAE,EAAE;AACrC;AAEA,IAAE,CAAC;AACD,WAAO;AACP,iBAAa;AACf;AAEA,IAAE,CAAC;AACD,cAAU;AACV,WAAO;AACP,YAAQ;AACR,cAAU;AACV,mBAAe;AACf,gBAAY,IAAI;AAChB,YAAQ;AACR,kBAAc;AAEd,KAAC;AACC,cAAQ;AACV;AACF;AAEA,IAAE,CAAC;AACD,cAAU;AACV,SAAK;AACL,UAAM;AACN,sBAAkB,EAAE;AACpB,eAAW;AACX,iBAAa;AACb,uBAAmB;AACrB;AAEA,IAAE,CAAC;AACD,cAAU;AACV,WAAO;AACP,mBAAe;AACf,gBAAY,EAAE,EAAE,EAAE,OAAO,IAAI,EAAE,EAAE,EAAE,EAAE;AACrC,oBAAgB;AAClB;AAEA,IAAE,CAAC;AACD,WAAO;AACP,kBAAc,IAAI;AACpB;AAEA,IAAE,CAAC;AACD,eAAW;AACX,iBAAa;AACb,YAAQ;AACV;AAEA,IAAE,CAAC;AACD,aAAS;AACT,SAAK;AACL,qBAAiB;AACjB,gBAAY;AACd;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -30,7 +30,7 @@ var plugins = [
|
|
|
30
30
|
name: "Contact Avatar",
|
|
31
31
|
supportedDatatypes: ["contact"],
|
|
32
32
|
async load() {
|
|
33
|
-
const { renderContactAvatar } = await import("./ContactAvatar-
|
|
33
|
+
const { renderContactAvatar } = await import("./ContactAvatar-KM4BONY5.js");
|
|
34
34
|
const { styled } = await import("./styles-KCFZAQMN.js");
|
|
35
35
|
return styled(renderContactAvatar);
|
|
36
36
|
}
|
|
@@ -52,7 +52,7 @@ var plugins = [
|
|
|
52
52
|
name: "Contact Cursor",
|
|
53
53
|
supportedDatatypes: ["contact"],
|
|
54
54
|
async load() {
|
|
55
|
-
const { renderContactCursor } = await import("./ContactCursor-
|
|
55
|
+
const { renderContactCursor } = await import("./ContactCursor-4FYCATG5.js");
|
|
56
56
|
const { styled } = await import("./styles-KCFZAQMN.js");
|
|
57
57
|
return styled(renderContactCursor);
|
|
58
58
|
}
|
|
@@ -63,7 +63,7 @@ var plugins = [
|
|
|
63
63
|
name: "Account Picker",
|
|
64
64
|
supportedDatatypes: ["account"],
|
|
65
65
|
async load() {
|
|
66
|
-
const { AccountPickerTool } = await import("./AccountPicker-
|
|
66
|
+
const { AccountPickerTool } = await import("./AccountPicker-HB6MDLKN.js");
|
|
67
67
|
const { styled } = await import("./styles-KCFZAQMN.js");
|
|
68
68
|
return styled(AccountPickerTool);
|
|
69
69
|
}
|
|
@@ -2311,18 +2311,18 @@ import {
|
|
|
2311
2311
|
import {
|
|
2312
2312
|
Presence
|
|
2313
2313
|
} from "@automerge/automerge-repo/slim";
|
|
2314
|
-
function createPresenceExtension(handle, path, contactUrl) {
|
|
2314
|
+
function createPresenceExtension(handle, path, contactUrl, repo) {
|
|
2315
2315
|
const compartment = new Compartment5();
|
|
2316
2316
|
const extension = () => {
|
|
2317
2317
|
const url = contactUrl();
|
|
2318
|
-
return url ? presence(handle(), path(), url) : [];
|
|
2318
|
+
return url ? presence(handle(), path(), url, repo) : [];
|
|
2319
2319
|
};
|
|
2320
2320
|
const createReconfigureEffect = (view) => createEffect6(() => {
|
|
2321
2321
|
view.dispatch({ effects: compartment.reconfigure(extension()) });
|
|
2322
2322
|
});
|
|
2323
2323
|
return [compartment.of(extension()), createReconfigureEffect];
|
|
2324
2324
|
}
|
|
2325
|
-
function presence(handle, path, contactUrl) {
|
|
2325
|
+
function presence(handle, path, contactUrl, repo) {
|
|
2326
2326
|
const setRemoteSelections = StateEffect4.define();
|
|
2327
2327
|
const remoteSelectionField = StateField3.define({
|
|
2328
2328
|
create() {
|
|
@@ -2377,6 +2377,11 @@ function presence(handle, path, contactUrl) {
|
|
|
2377
2377
|
presence;
|
|
2378
2378
|
destroyed = false;
|
|
2379
2379
|
broadcastQueued = false;
|
|
2380
|
+
// Peers' contact docs, followed live so a color picked in the account
|
|
2381
|
+
// picker recolors that peer's caret and tint immediately. Keyed by
|
|
2382
|
+
// contact url; the stored function stops the subscription.
|
|
2383
|
+
contactWatchers = /* @__PURE__ */ new Map();
|
|
2384
|
+
contactColors = /* @__PURE__ */ new Map();
|
|
2380
2385
|
constructor(view) {
|
|
2381
2386
|
this.view = view;
|
|
2382
2387
|
this.presence = new Presence({
|
|
@@ -2409,6 +2414,33 @@ function presence(handle, path, contactUrl) {
|
|
|
2409
2414
|
this.destroyed = true;
|
|
2410
2415
|
this.stopPresence();
|
|
2411
2416
|
window.removeEventListener("pagehide", this.stopPresence);
|
|
2417
|
+
for (const stop of this.contactWatchers.values()) stop();
|
|
2418
|
+
this.contactWatchers.clear();
|
|
2419
|
+
}
|
|
2420
|
+
// A peer's color is whatever their account says (contact doc `color`),
|
|
2421
|
+
// never derived locally. The doc is fetched once and followed; until it
|
|
2422
|
+
// loads (or if the contact never picked a color) the caret stays on the
|
|
2423
|
+
// neutral fallback.
|
|
2424
|
+
trackContactColor(url) {
|
|
2425
|
+
if (this.contactWatchers.has(url)) return;
|
|
2426
|
+
this.contactWatchers.set(url, () => {
|
|
2427
|
+
});
|
|
2428
|
+
repo.find(url).then((contactHandle) => {
|
|
2429
|
+
if (this.destroyed) return;
|
|
2430
|
+
const read = () => {
|
|
2431
|
+
const color = contactHandle.doc()?.color;
|
|
2432
|
+
if (!color || this.contactColors.get(url) === color) return;
|
|
2433
|
+
this.contactColors.set(url, color);
|
|
2434
|
+
this.refresh();
|
|
2435
|
+
};
|
|
2436
|
+
contactHandle.on("change", read);
|
|
2437
|
+
this.contactWatchers.set(
|
|
2438
|
+
url,
|
|
2439
|
+
() => contactHandle.off("change", read)
|
|
2440
|
+
);
|
|
2441
|
+
read();
|
|
2442
|
+
}).catch(() => {
|
|
2443
|
+
});
|
|
2412
2444
|
}
|
|
2413
2445
|
stopPresence = () => {
|
|
2414
2446
|
if (this.presence.running) this.presence.stop();
|
|
@@ -2447,12 +2479,14 @@ function presence(handle, path, contactUrl) {
|
|
|
2447
2479
|
const from = A3.getCursorPosition(doc, path, selection.start);
|
|
2448
2480
|
const to = A3.getCursorPosition(doc, path, selection.end);
|
|
2449
2481
|
const peerContactUrl = peer.userId ?? null;
|
|
2482
|
+
if (peerContactUrl) this.trackContactColor(peerContactUrl);
|
|
2450
2483
|
resolved.push({
|
|
2451
2484
|
peerId,
|
|
2452
2485
|
contactUrl: peerContactUrl,
|
|
2453
|
-
//
|
|
2454
|
-
// contact
|
|
2455
|
-
|
|
2486
|
+
// The color the peer chose in their account -- the same contact
|
|
2487
|
+
// doc the contact-cursor token renders from, so the tint and
|
|
2488
|
+
// the token can't drift apart.
|
|
2489
|
+
color: peerContactUrl && this.contactColors.get(peerContactUrl) || FALLBACK_PRESENCE_COLOR,
|
|
2456
2490
|
from,
|
|
2457
2491
|
to,
|
|
2458
2492
|
head: selection.headAtStart ? from : to,
|
|
@@ -2570,26 +2604,7 @@ var presenceTheme = EditorView9.baseTheme({
|
|
|
2570
2604
|
opacity: "0"
|
|
2571
2605
|
}
|
|
2572
2606
|
});
|
|
2573
|
-
var
|
|
2574
|
-
"hsl(200, 70%, 50%)",
|
|
2575
|
-
"hsl(10, 75%, 58%)",
|
|
2576
|
-
"hsl(145, 70%, 45%)",
|
|
2577
|
-
"hsl(270, 70%, 55%)",
|
|
2578
|
-
"hsl(38, 85%, 50%)",
|
|
2579
|
-
"hsl(350, 70%, 55%)",
|
|
2580
|
-
"hsl(178, 70%, 45%)",
|
|
2581
|
-
"hsl(235, 70%, 58%)",
|
|
2582
|
-
"hsl(85, 70%, 45%)",
|
|
2583
|
-
"hsl(310, 70%, 55%)",
|
|
2584
|
-
"hsl(25, 80%, 52%)",
|
|
2585
|
-
"hsl(188, 75%, 48%)"
|
|
2586
|
-
];
|
|
2587
|
-
function generateColorFromString(str) {
|
|
2588
|
-
const hash = Math.abs(
|
|
2589
|
-
str.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0)
|
|
2590
|
-
);
|
|
2591
|
-
return USER_COLOR_PALETTE[hash % USER_COLOR_PALETTE.length];
|
|
2592
|
-
}
|
|
2607
|
+
var FALLBACK_PRESENCE_COLOR = "#888";
|
|
2593
2608
|
|
|
2594
2609
|
// src/lib/codemirror.tsx
|
|
2595
2610
|
var lookup = (doc, path) => {
|
|
@@ -2609,7 +2624,7 @@ function CodeMirror(props) {
|
|
|
2609
2624
|
const [decorationsExtension, createEffectReconfigureDecorations] = createDecorationsExtension(() => props.decorations?.());
|
|
2610
2625
|
const [diffExtension, createEffectReconfigureDiff] = createDiffExtension(() => props.handle, () => props.path, () => props.baseline?.() ?? null);
|
|
2611
2626
|
const [scrollHighlightIntoViewExtension, createEffectScrollHighlightIntoView] = createScrollHighlightIntoViewExtension(() => props.scrollTarget?.() ?? null);
|
|
2612
|
-
const [presenceExtension, createEffectReconfigurePresence] = createPresenceExtension(() => props.handle, () => props.path, () => props.readOnly || props.handle.isReadOnly() ? null : props.contactUrl?.() ?? null);
|
|
2627
|
+
const [presenceExtension, createEffectReconfigurePresence] = createPresenceExtension(() => props.handle, () => props.path, () => props.readOnly || props.handle.isReadOnly() ? null : props.contactUrl?.() ?? null, props.repo);
|
|
2613
2628
|
const userExtensionsCompartment = new Compartment6();
|
|
2614
2629
|
const selectionExtension = EditorView10.updateListener.of((update) => {
|
|
2615
2630
|
if (!props.onChangeSelection) return;
|
|
@@ -2655,4 +2670,4 @@ function CodeMirror(props) {
|
|
|
2655
2670
|
export {
|
|
2656
2671
|
CodeMirror
|
|
2657
2672
|
};
|
|
2658
|
-
//# sourceMappingURL=chunk-
|
|
2673
|
+
//# sourceMappingURL=chunk-AKNT5U37.js.map
|