@devaccel-labs/comment-service 0.6.0 → 0.7.0
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/react.js +317 -128
- package/dist/types/react/handoff.d.ts +15 -0
- package/dist/types/react/icons.d.ts +2 -0
- package/dist/types/react/styles.d.ts +1 -1
- package/dist/types/react/table.d.ts +16 -0
- package/package.json +4 -4
package/dist/react.js
CHANGED
|
@@ -206,11 +206,11 @@ function overlayFor(element) {
|
|
|
206
206
|
return { role, name: labelFor(node) || "dialog" };
|
|
207
207
|
}
|
|
208
208
|
function fiberNames(element) {
|
|
209
|
-
const
|
|
210
|
-
if (!
|
|
209
|
+
const key2 = Object.keys(element).find((name) => name.startsWith("__reactFiber$") || name.startsWith("__reactInternalInstance$"));
|
|
210
|
+
if (!key2)
|
|
211
211
|
return [];
|
|
212
212
|
const names2 = [];
|
|
213
|
-
let fiber = element[
|
|
213
|
+
let fiber = element[key2];
|
|
214
214
|
for (let guard = 0; fiber && guard < 40; guard++) {
|
|
215
215
|
const type = fiber.type;
|
|
216
216
|
if (typeof type === "function") {
|
|
@@ -267,7 +267,7 @@ function ownership(element) {
|
|
|
267
267
|
owner: null
|
|
268
268
|
};
|
|
269
269
|
}
|
|
270
|
-
function candidateFromElement(element, route,
|
|
270
|
+
function candidateFromElement(element, route, key2) {
|
|
271
271
|
const owned = ownership(element);
|
|
272
272
|
const label = labelFor(element);
|
|
273
273
|
const explicit = EXPLICIT.flatMap((attr) => {
|
|
@@ -275,7 +275,7 @@ function candidateFromElement(element, route, key) {
|
|
|
275
275
|
return value && usableExplicit(attr, value) ? [{ attr, value }] : [];
|
|
276
276
|
});
|
|
277
277
|
return {
|
|
278
|
-
key,
|
|
278
|
+
key: key2,
|
|
279
279
|
route,
|
|
280
280
|
visible: !obviouslyHidden(element),
|
|
281
281
|
path: domPath(element),
|
|
@@ -354,8 +354,8 @@ function describeElement(element) {
|
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
// ../react/dist/toolbar.js
|
|
357
|
-
import { jsx as
|
|
358
|
-
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as
|
|
357
|
+
import { jsx as _jsx6, jsxs as _jsxs6, Fragment as _Fragment3 } from "react/jsx-runtime";
|
|
358
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo3, useRef as useRef3, useState as useState5 } from "react";
|
|
359
359
|
import { createPortal as createPortal2 } from "react-dom";
|
|
360
360
|
|
|
361
361
|
// ../react/dist/client.js
|
|
@@ -499,6 +499,8 @@ var Paperclip = () => _jsx(Icon, { size: 15, children: _jsx("path", { d: "m21.44
|
|
|
499
499
|
var Camera = () => _jsxs(Icon, { size: 15, children: [_jsx("path", { d: "M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z" }), _jsx("circle", { cx: "12", cy: "13", r: "3" })] });
|
|
500
500
|
var FileIcon = () => _jsxs(Icon, { size: 15, children: [_jsx("path", { d: "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" }), _jsx("polyline", { points: "14 2 14 8 20 8" })] });
|
|
501
501
|
var Back = () => _jsx(Icon, { children: _jsx("path", { d: "m15 18-6-6 6-6" }) });
|
|
502
|
+
var Table = () => _jsxs(Icon, { children: [_jsx("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2" }), _jsx("path", { d: "M3 10h18M3 15h18M9 10v10" })] });
|
|
503
|
+
var List = () => _jsx(Icon, { children: _jsx("path", { d: "M8 6h13M8 12h13M8 18h13M3.5 6h.01M3.5 12h.01M3.5 18h.01" }) });
|
|
502
504
|
|
|
503
505
|
// ../react/dist/details.js
|
|
504
506
|
var noDetails = { role: null, fields: {} };
|
|
@@ -673,7 +675,7 @@ function useAttachments(session, memberToken, onError) {
|
|
|
673
675
|
const [items, setItems] = useState2([]);
|
|
674
676
|
const itemsRef = useRef(items);
|
|
675
677
|
itemsRef.current = items;
|
|
676
|
-
const patch = (
|
|
678
|
+
const patch = (key2, next) => setItems((current) => current.map((item) => item.key === key2 ? { ...item, ...next } : item));
|
|
677
679
|
const add = useCallback((files) => {
|
|
678
680
|
if (!session || !memberToken)
|
|
679
681
|
return;
|
|
@@ -689,22 +691,22 @@ function useAttachments(session, memberToken, onError) {
|
|
|
689
691
|
onError(`${name} is over 10 MB.`);
|
|
690
692
|
continue;
|
|
691
693
|
}
|
|
692
|
-
const
|
|
694
|
+
const key2 = crypto.randomUUID();
|
|
693
695
|
const preview = blob.type.startsWith("image/") ? URL.createObjectURL(blob) : null;
|
|
694
|
-
setItems((current) => [...current, { key, name, size: blob.size, contentType: blob.type, preview, status: "uploading" }]);
|
|
695
|
-
uploadAttachment(session, memberToken, blob, name).then((attachment) => patch(
|
|
696
|
+
setItems((current) => [...current, { key: key2, name, size: blob.size, contentType: blob.type, preview, status: "uploading" }]);
|
|
697
|
+
uploadAttachment(session, memberToken, blob, name).then((attachment) => patch(key2, { status: "ready", id: attachment.id })).catch((caught) => {
|
|
696
698
|
const message = caught instanceof Error ? caught.message : "Upload failed.";
|
|
697
|
-
patch(
|
|
699
|
+
patch(key2, { status: "failed", error: message });
|
|
698
700
|
onError(`${name}: ${message}`);
|
|
699
701
|
});
|
|
700
702
|
}
|
|
701
703
|
}, [memberToken, onError, session]);
|
|
702
|
-
const remove = useCallback((
|
|
704
|
+
const remove = useCallback((key2) => {
|
|
703
705
|
setItems((current) => {
|
|
704
|
-
const item = current.find((candidate) => candidate.key ===
|
|
706
|
+
const item = current.find((candidate) => candidate.key === key2);
|
|
705
707
|
if (item?.preview)
|
|
706
708
|
URL.revokeObjectURL(item.preview);
|
|
707
|
-
return current.filter((candidate) => candidate.key !==
|
|
709
|
+
return current.filter((candidate) => candidate.key !== key2);
|
|
708
710
|
});
|
|
709
711
|
}, []);
|
|
710
712
|
const reset = useCallback(() => {
|
|
@@ -1146,14 +1148,14 @@ async function createContext(node, options) {
|
|
|
1146
1148
|
drawImageCount: 0,
|
|
1147
1149
|
tasks: [],
|
|
1148
1150
|
features,
|
|
1149
|
-
isEnable: (
|
|
1150
|
-
if (
|
|
1151
|
-
return typeof features === "boolean" ? false : features[
|
|
1151
|
+
isEnable: (key2) => {
|
|
1152
|
+
if (key2 === "restoreScrollPosition") {
|
|
1153
|
+
return typeof features === "boolean" ? false : features[key2] ?? false;
|
|
1152
1154
|
}
|
|
1153
1155
|
if (typeof features === "boolean") {
|
|
1154
1156
|
return features;
|
|
1155
1157
|
}
|
|
1156
|
-
return features[
|
|
1158
|
+
return features[key2] ?? true;
|
|
1157
1159
|
},
|
|
1158
1160
|
shadowRoots: []
|
|
1159
1161
|
};
|
|
@@ -1394,14 +1396,14 @@ function getDefaultStyle(node, pseudoElement, context) {
|
|
|
1394
1396
|
const nodeName = node.nodeName.toLowerCase();
|
|
1395
1397
|
const isSvgNode = isSVGElementNode(node) && nodeName !== "svg";
|
|
1396
1398
|
const attributes = isSvgNode ? includedAttributes.map((name) => [name, node.getAttribute(name)]).filter(([, value]) => value !== null) : [];
|
|
1397
|
-
const
|
|
1399
|
+
const key2 = [
|
|
1398
1400
|
isSvgNode && "svg",
|
|
1399
1401
|
nodeName,
|
|
1400
1402
|
attributes.map((name, value) => `${name}=${value}`).join(","),
|
|
1401
1403
|
pseudoElement
|
|
1402
1404
|
].filter(Boolean).join(":");
|
|
1403
|
-
if (defaultComputedStyles.has(
|
|
1404
|
-
return defaultComputedStyles.get(
|
|
1405
|
+
if (defaultComputedStyles.has(key2))
|
|
1406
|
+
return defaultComputedStyles.get(key2);
|
|
1405
1407
|
const sandbox = getSandBox(context);
|
|
1406
1408
|
const sandboxWindow = sandbox?.contentWindow;
|
|
1407
1409
|
if (!sandboxWindow)
|
|
@@ -1430,7 +1432,7 @@ function getDefaultStyle(node, pseudoElement, context) {
|
|
|
1430
1432
|
styles.set(name, computedStyle.getPropertyValue(name));
|
|
1431
1433
|
}
|
|
1432
1434
|
sandboxDocument.body.removeChild(root);
|
|
1433
|
-
defaultComputedStyles.set(
|
|
1435
|
+
defaultComputedStyles.set(key2, styles);
|
|
1434
1436
|
return styles;
|
|
1435
1437
|
}
|
|
1436
1438
|
function getDiffStyle(style, defaultStyle, includeStyleProperties) {
|
|
@@ -1478,8 +1480,8 @@ function copyCssStyles(node, cloned, isRoot, context) {
|
|
|
1478
1480
|
const clonedStyle = cloned.style;
|
|
1479
1481
|
const computedStyle = ownerWindow.getComputedStyle(node);
|
|
1480
1482
|
const defaultStyle = getDefaultStyle(node, null, context);
|
|
1481
|
-
currentParentNodeStyle?.forEach((_,
|
|
1482
|
-
defaultStyle.delete(
|
|
1483
|
+
currentParentNodeStyle?.forEach((_, key2) => {
|
|
1484
|
+
defaultStyle.delete(key2);
|
|
1483
1485
|
});
|
|
1484
1486
|
const style = getDiffStyle(computedStyle, defaultStyle, includeStyleProperties);
|
|
1485
1487
|
style.delete("transition-property");
|
|
@@ -1550,8 +1552,8 @@ function copyPseudoClass(node, cloned, copyScrollbar, context, addWordToFontFami
|
|
|
1550
1552
|
content = content.replace(/(')|(")|(counter\(.+\))/g, "");
|
|
1551
1553
|
const klasses = [uuid()];
|
|
1552
1554
|
const defaultStyle = getDefaultStyle(node, pseudoClass, context);
|
|
1553
|
-
currentNodeStyle?.forEach((_,
|
|
1554
|
-
defaultStyle.delete(
|
|
1555
|
+
currentNodeStyle?.forEach((_, key2) => {
|
|
1556
|
+
defaultStyle.delete(key2);
|
|
1555
1557
|
});
|
|
1556
1558
|
const style = getDiffStyle(computedStyle, defaultStyle, context.includeStyleProperties);
|
|
1557
1559
|
style.delete("content");
|
|
@@ -2340,6 +2342,145 @@ async function captureAround(element) {
|
|
|
2340
2342
|
return out.toDataURL("image/jpeg", 0.82);
|
|
2341
2343
|
}
|
|
2342
2344
|
|
|
2345
|
+
// ../react/dist/table.js
|
|
2346
|
+
import { jsx as _jsx5, jsxs as _jsxs5 } from "react/jsx-runtime";
|
|
2347
|
+
import { useMemo as useMemo2, useState as useState4 } from "react";
|
|
2348
|
+
var columns = [
|
|
2349
|
+
{ key: "comment", label: "Comment" },
|
|
2350
|
+
{ key: "role", label: "Role" },
|
|
2351
|
+
{ key: "page", label: "Page" },
|
|
2352
|
+
{ key: "author", label: "Author" },
|
|
2353
|
+
{ key: "replies", label: "Replies" },
|
|
2354
|
+
{ key: "status", label: "Status" },
|
|
2355
|
+
{ key: "updated", label: "Updated" }
|
|
2356
|
+
];
|
|
2357
|
+
function sortValue(thread, key2) {
|
|
2358
|
+
if (key2 === "comment")
|
|
2359
|
+
return thread.messages[0]?.body ?? "";
|
|
2360
|
+
if (key2 === "role")
|
|
2361
|
+
return thread.role ?? "";
|
|
2362
|
+
if (key2 === "page")
|
|
2363
|
+
return thread.url || thread.route;
|
|
2364
|
+
if (key2 === "author")
|
|
2365
|
+
return thread.createdBy;
|
|
2366
|
+
if (key2 === "replies")
|
|
2367
|
+
return thread.messages.length;
|
|
2368
|
+
if (key2 === "status")
|
|
2369
|
+
return thread.status;
|
|
2370
|
+
return thread.updatedAt;
|
|
2371
|
+
}
|
|
2372
|
+
function searchText(thread) {
|
|
2373
|
+
return [
|
|
2374
|
+
thread.createdBy,
|
|
2375
|
+
thread.role ?? "",
|
|
2376
|
+
thread.url || thread.route,
|
|
2377
|
+
targetName(thread.anchor),
|
|
2378
|
+
...thread.messages.map((message) => message.body),
|
|
2379
|
+
...thread.fields.map((field) => `${field.label} ${field.value}`)
|
|
2380
|
+
].join("\n").toLowerCase();
|
|
2381
|
+
}
|
|
2382
|
+
function CommentTable({ rows, route, activeId, tabs, onSelect, onList, onClose }) {
|
|
2383
|
+
const [query, setQuery] = useState4("");
|
|
2384
|
+
const [sort, setSort] = useState4({ key: "updated", desc: true });
|
|
2385
|
+
const showRole = rows.some((row) => row.thread.role);
|
|
2386
|
+
const fieldLabels = useMemo2(() => {
|
|
2387
|
+
const labels = [];
|
|
2388
|
+
for (const { thread } of rows)
|
|
2389
|
+
for (const field of thread.fields)
|
|
2390
|
+
if (!labels.includes(field.label))
|
|
2391
|
+
labels.push(field.label);
|
|
2392
|
+
return labels;
|
|
2393
|
+
}, [rows]);
|
|
2394
|
+
const shown = useMemo2(() => {
|
|
2395
|
+
const needle = query.trim().toLowerCase();
|
|
2396
|
+
const matched = needle ? rows.filter((row) => searchText(row.thread).includes(needle)) : rows;
|
|
2397
|
+
return [...matched].sort((a, b) => {
|
|
2398
|
+
const left = sortValue(a.thread, sort.key);
|
|
2399
|
+
const right = sortValue(b.thread, sort.key);
|
|
2400
|
+
const order = typeof left === "number" && typeof right === "number" ? left - right : String(left).localeCompare(String(right));
|
|
2401
|
+
return sort.desc ? -order : order;
|
|
2402
|
+
});
|
|
2403
|
+
}, [query, rows, sort]);
|
|
2404
|
+
const visible = columns.filter((column) => column.key !== "role" || showRole);
|
|
2405
|
+
const header = (column) => _jsx5("th", { "aria-sort": sort.key === column.key ? sort.desc ? "descending" : "ascending" : "none", children: _jsxs5("button", { type: "button", onClick: () => setSort((current) => ({ key: column.key, desc: current.key === column.key ? !current.desc : column.key === "updated" })), children: [column.label, sort.key === column.key ? _jsx5("span", { className: "cs-sort", children: sort.desc ? "\u2193" : "\u2191" }) : null] }) }, column.key);
|
|
2406
|
+
return _jsxs5("section", { className: "cs-card cs-table-sheet cs-hit", "data-cs-ui": "panel", "aria-label": "Comments table", children: [_jsxs5("header", { className: "cs-sheet-head", children: [_jsx5("h2", { children: "Comments" }), _jsx5("input", { className: "cs-table-search", "data-cs-ui": "table-search", type: "search", "aria-label": "Search comments", placeholder: "Search", value: query, onChange: (event) => setQuery(event.target.value) }), _jsx5("button", { className: "cs-icon-button", "data-cs-ui": "list-view", type: "button", "aria-label": "List view", onClick: onList, children: _jsx5(List, {}) }), _jsx5("button", { className: "cs-icon-button", type: "button", "aria-label": "Close comments", onClick: onClose, children: _jsx5(Close, {}) })] }), tabs, _jsx5("div", { className: "cs-table-wrap", children: shown.length === 0 ? _jsx5("p", { className: "cs-empty", children: query ? "No comments match." : "No comments here." }) : _jsxs5("table", { className: "cs-table", "data-cs-ui": "table", children: [_jsx5("thead", { children: _jsxs5("tr", { children: [visible.slice(0, showRole ? 2 : 1).map(header), fieldLabels.map((label) => _jsx5("th", { children: _jsx5("span", { children: label }) }, `field:${label}`)), visible.slice(showRole ? 2 : 1).map(header)] }) }), _jsx5("tbody", { children: shown.map((row) => {
|
|
2407
|
+
const { thread } = row;
|
|
2408
|
+
const first = thread.messages[0];
|
|
2409
|
+
const note = statusNote(row.status, thread.anchor, thread.route === route);
|
|
2410
|
+
return _jsxs5("tr", { className: activeId === thread.id ? "is-active" : void 0, "data-cs-ui": "table-row", "data-thread-id": thread.id, tabIndex: 0, onClick: () => onSelect(row), onKeyDown: (event) => {
|
|
2411
|
+
if (event.key === "Enter") {
|
|
2412
|
+
event.preventDefault();
|
|
2413
|
+
onSelect(row);
|
|
2414
|
+
}
|
|
2415
|
+
}, children: [_jsxs5("td", { className: "cs-cell-comment", children: [_jsx5("span", { className: "cs-cell-clamp", children: first?.body || "\u2014" }), _jsx5("small", { children: targetName(thread.anchor) })] }), showRole ? _jsx5("td", { children: thread.role ? _jsx5("span", { className: "cs-role", children: thread.role }) : null }) : null, fieldLabels.map((label) => _jsx5("td", { children: _jsx5("span", { className: "cs-cell-clamp", children: thread.fields.find((field) => field.label === label)?.value ?? "" }) }, `field:${label}`)), _jsx5("td", { className: "cs-cell-page", title: thread.url || thread.route, children: thread.url || thread.route }), _jsx5("td", { className: "cs-cell-nowrap", children: thread.createdBy }), _jsx5("td", { className: "cs-cell-num", children: thread.messages.length - 1 || "" }), _jsxs5("td", { className: "cs-cell-nowrap", children: [_jsx5("span", { className: thread.status === "resolved" ? "cs-state is-done" : "cs-state", children: thread.status === "resolved" ? "Resolved" : "Open" }), note && thread.status === "open" ? _jsx5("small", { className: `cs-note is-${note.tone}`, children: note.text }) : null] }), _jsx5("td", { className: "cs-cell-nowrap", children: _jsx5("time", { dateTime: thread.updatedAt, children: ago(thread.updatedAt) }) })] }, thread.id);
|
|
2416
|
+
}) })] }) })] });
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
// ../react/dist/handoff.js
|
|
2420
|
+
var key = "devaccel.comment.handoff";
|
|
2421
|
+
var ttl = 30 * 60 * 1e3;
|
|
2422
|
+
function readHandoff() {
|
|
2423
|
+
try {
|
|
2424
|
+
const value = JSON.parse(sessionStorage.getItem(key) ?? "null");
|
|
2425
|
+
return value && Date.now() - value.at < ttl ? value : null;
|
|
2426
|
+
} catch {
|
|
2427
|
+
return null;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
function write(value) {
|
|
2431
|
+
try {
|
|
2432
|
+
if (value.invite || value.thread)
|
|
2433
|
+
sessionStorage.setItem(key, JSON.stringify(value));
|
|
2434
|
+
else
|
|
2435
|
+
sessionStorage.removeItem(key);
|
|
2436
|
+
} catch {
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
function linkParams() {
|
|
2440
|
+
const url = new URL(window.location.href);
|
|
2441
|
+
const hash = new URLSearchParams(url.hash.slice(1));
|
|
2442
|
+
return {
|
|
2443
|
+
url,
|
|
2444
|
+
hash,
|
|
2445
|
+
invite: url.searchParams.get("cs-invite") ?? hash.get("cs-invite"),
|
|
2446
|
+
thread: url.searchParams.get("cs-thread") ?? hash.get("cs-thread")
|
|
2447
|
+
};
|
|
2448
|
+
}
|
|
2449
|
+
function captureHandoff() {
|
|
2450
|
+
if (typeof window === "undefined")
|
|
2451
|
+
return;
|
|
2452
|
+
const { invite, thread } = linkParams();
|
|
2453
|
+
if (!invite && !thread)
|
|
2454
|
+
return;
|
|
2455
|
+
write({ ...readHandoff(), ...invite ? { invite } : {}, ...thread ? { thread } : {}, at: Date.now() });
|
|
2456
|
+
}
|
|
2457
|
+
function dropHandoff(part) {
|
|
2458
|
+
const current = readHandoff();
|
|
2459
|
+
if (!current)
|
|
2460
|
+
return;
|
|
2461
|
+
const { [part]: _dropped, ...rest } = current;
|
|
2462
|
+
write(rest);
|
|
2463
|
+
}
|
|
2464
|
+
function stripHandoffFromUrl() {
|
|
2465
|
+
const { url, hash } = linkParams();
|
|
2466
|
+
const inQuery = url.searchParams.has("cs-invite") || url.searchParams.has("cs-thread");
|
|
2467
|
+
const inHash = hash.has("cs-invite") || hash.has("cs-thread");
|
|
2468
|
+
if (!inQuery && !inHash)
|
|
2469
|
+
return;
|
|
2470
|
+
url.searchParams.delete("cs-invite");
|
|
2471
|
+
url.searchParams.delete("cs-thread");
|
|
2472
|
+
if (inHash)
|
|
2473
|
+
url.hash = "";
|
|
2474
|
+
history.replaceState(history.state, "", url);
|
|
2475
|
+
}
|
|
2476
|
+
function linkWith(href, name, value) {
|
|
2477
|
+
const url = new URL(href, window.location.origin);
|
|
2478
|
+
url.searchParams.delete("cs-invite");
|
|
2479
|
+
url.searchParams.delete("cs-thread");
|
|
2480
|
+
url.hash = `${name}=${encodeURIComponent(value)}`;
|
|
2481
|
+
return url.toString();
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2343
2484
|
// ../react/dist/styles.js
|
|
2344
2485
|
var toolbarCss = `
|
|
2345
2486
|
#cs-root {
|
|
@@ -2593,6 +2734,7 @@ var toolbarCss = `
|
|
|
2593
2734
|
display: flex; flex-direction: column; overflow: hidden;
|
|
2594
2735
|
}
|
|
2595
2736
|
#cs-root .cs-sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 10px 4px 16px; }
|
|
2737
|
+
#cs-root .cs-sheet-head .cs-push { margin-left: auto; }
|
|
2596
2738
|
#cs-root .cs-sheet-head h2 { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
|
|
2597
2739
|
#cs-root .cs-tabs { display: flex; gap: 2px; margin: 4px 12px 6px; padding: 2px; border-radius: 9px; background: var(--cs-fill); }
|
|
2598
2740
|
#cs-root .cs-tabs button {
|
|
@@ -2708,6 +2850,44 @@ var toolbarCss = `
|
|
|
2708
2850
|
#cs-root .cs-add-row input { padding: 5px 8px; }
|
|
2709
2851
|
#cs-root .cs-settings .cs-hint { padding: 6px 8px 4px; }
|
|
2710
2852
|
|
|
2853
|
+
/* Table */
|
|
2854
|
+
#cs-root .cs-table-sheet {
|
|
2855
|
+
top: 12px; right: 12px; width: min(1100px, calc(100vw - 24px)); max-height: calc(100% - 88px);
|
|
2856
|
+
display: flex; flex-direction: column; overflow: hidden;
|
|
2857
|
+
}
|
|
2858
|
+
#cs-root .cs-table-sheet .cs-sheet-head { gap: 6px; }
|
|
2859
|
+
#cs-root .cs-table-sheet .cs-sheet-head h2 { margin-right: auto; }
|
|
2860
|
+
#cs-root .cs-table-search { width: 220px; padding: 5px 10px; }
|
|
2861
|
+
#cs-root .cs-table-sheet .cs-tabs { max-width: 420px; }
|
|
2862
|
+
#cs-root .cs-table-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; border-top: 1px solid var(--cs-line); overscroll-behavior: contain; }
|
|
2863
|
+
#cs-root .cs-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
|
|
2864
|
+
#cs-root .cs-table th {
|
|
2865
|
+
position: sticky; top: 0; z-index: 1; background: var(--cs-card); text-align: left; font-weight: 600;
|
|
2866
|
+
font-size: 11px; color: var(--cs-text-3); text-transform: uppercase; letter-spacing: 0.03em;
|
|
2867
|
+
padding: 0; border-bottom: 1px solid var(--cs-line); white-space: nowrap;
|
|
2868
|
+
}
|
|
2869
|
+
#cs-root .cs-table th > button, #cs-root .cs-table th > span {
|
|
2870
|
+
display: inline-flex; align-items: center; gap: 4px; padding: 8px 10px; font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
|
|
2871
|
+
}
|
|
2872
|
+
#cs-root .cs-table th > button:hover { color: var(--cs-text); }
|
|
2873
|
+
#cs-root .cs-sort { color: var(--cs-accent); }
|
|
2874
|
+
#cs-root .cs-table td { padding: 8px 10px; vertical-align: top; border-bottom: 1px solid var(--cs-line); max-width: 260px; }
|
|
2875
|
+
#cs-root .cs-table tbody tr { cursor: pointer; }
|
|
2876
|
+
#cs-root .cs-table tbody tr:hover { background: var(--cs-fill); }
|
|
2877
|
+
#cs-root .cs-table tbody tr.is-active { background: var(--cs-accent-soft); }
|
|
2878
|
+
#cs-root .cs-table tbody tr:focus-visible { outline: 2px solid var(--cs-accent); outline-offset: -2px; }
|
|
2879
|
+
#cs-root .cs-cell-comment { min-width: 220px; }
|
|
2880
|
+
#cs-root .cs-cell-comment small, #cs-root .cs-table td small { display: block; margin-top: 2px; font-size: 11.5px; color: var(--cs-text-3); }
|
|
2881
|
+
#cs-root .cs-cell-clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
2882
|
+
#cs-root .cs-cell-page { font: 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--cs-text-2); max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2883
|
+
#cs-root .cs-cell-nowrap { white-space: nowrap; }
|
|
2884
|
+
#cs-root .cs-cell-num { text-align: right; font-variant-numeric: tabular-nums; color: var(--cs-text-2); }
|
|
2885
|
+
#cs-root .cs-state { display: inline-flex; align-items: center; gap: 5px; font-weight: 500; }
|
|
2886
|
+
#cs-root .cs-state::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: #34c759; }
|
|
2887
|
+
#cs-root .cs-state.is-done { color: var(--cs-text-3); }
|
|
2888
|
+
#cs-root .cs-state.is-done::before { background: var(--cs-text-3); }
|
|
2889
|
+
#cs-root .cs-table .cs-note { display: flex; margin-top: 2px; font-size: 11px; }
|
|
2890
|
+
|
|
2711
2891
|
/* Attachments */
|
|
2712
2892
|
#cs-root .cs-attach { display: inline-flex; gap: 0; flex: none; }
|
|
2713
2893
|
#cs-root .cs-tray { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 12px 2px 46px; }
|
|
@@ -2798,6 +2978,7 @@ var toolbarCss = `
|
|
|
2798
2978
|
`;
|
|
2799
2979
|
|
|
2800
2980
|
// ../react/dist/toolbar.js
|
|
2981
|
+
captureHandoff();
|
|
2801
2982
|
var historyFlag = "__devaccelCommentHistory";
|
|
2802
2983
|
var prefsKey = "devaccel.comment.prefs";
|
|
2803
2984
|
var positions = [
|
|
@@ -2834,7 +3015,8 @@ function pageHref() {
|
|
|
2834
3015
|
const url = new URL(window.location.href);
|
|
2835
3016
|
url.searchParams.delete("cs-thread");
|
|
2836
3017
|
url.searchParams.delete("cs-invite");
|
|
2837
|
-
|
|
3018
|
+
const hash = url.hash.includes("cs-thread=") || url.hash.includes("cs-invite=") ? "" : url.hash;
|
|
3019
|
+
return `${url.pathname}${url.search}${hash}`;
|
|
2838
3020
|
}
|
|
2839
3021
|
function isTyping(target) {
|
|
2840
3022
|
if (!(target instanceof HTMLElement))
|
|
@@ -2858,47 +3040,48 @@ async function loadSession(sessionPath) {
|
|
|
2858
3040
|
return { apiUrl: payload.apiUrl, project: payload.project, environment: payload.environment, hostToken: payload.hostToken };
|
|
2859
3041
|
}
|
|
2860
3042
|
function Avatar({ name, size = 24 }) {
|
|
2861
|
-
return
|
|
3043
|
+
return _jsx6("span", { className: "cs-avatar", style: { width: size, height: size, fontSize: size * 0.4, background: colorFor(name) }, children: initials(name) });
|
|
2862
3044
|
}
|
|
2863
3045
|
function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs = 4e3, position = "bottom-center", theme = "light", navigate }) {
|
|
2864
|
-
const [phase, setPhase] =
|
|
2865
|
-
const [session, setSession] =
|
|
2866
|
-
const [member, setMember] =
|
|
2867
|
-
const [threads, setThreads] =
|
|
2868
|
-
const [route, setRoute] =
|
|
2869
|
-
const [surface, setSurface] =
|
|
2870
|
-
const [tab, setTab] =
|
|
2871
|
-
const [mode, setMode] =
|
|
2872
|
-
const [reattachId, setReattachId] =
|
|
2873
|
-
const [activeId, setActiveId] =
|
|
2874
|
-
const [peekId, setPeekId] =
|
|
2875
|
-
const [draft, setDraft] =
|
|
2876
|
-
const [body, setBody] =
|
|
2877
|
-
const [reply, setReply] =
|
|
2878
|
-
const [name, setName] =
|
|
2879
|
-
const [passphrase, setPassphrase] =
|
|
2880
|
-
const [email, setEmail] =
|
|
2881
|
-
const [members, setMembers] =
|
|
2882
|
-
const [profile, setProfile] =
|
|
2883
|
-
const [deliveries, setDeliveries] =
|
|
2884
|
-
const [invite, setInvite] =
|
|
2885
|
-
const [capturing, setCapturing] =
|
|
2886
|
-
const [inviteLink, setInviteLink] =
|
|
2887
|
-
const [renaming, setRenaming] =
|
|
2888
|
-
const [confirmReset, setConfirmReset] =
|
|
2889
|
-
const [error, setError] =
|
|
2890
|
-
const [toast, setToast] =
|
|
2891
|
-
const [busy, setBusy] =
|
|
2892
|
-
const [prefs, setPrefs] =
|
|
2893
|
-
const [portal, setPortal] =
|
|
2894
|
-
const [mounted, setMounted] =
|
|
2895
|
-
const [highlight, setHighlight] =
|
|
2896
|
-
const [flash, setFlash] =
|
|
2897
|
-
const [placed, setPlaced] =
|
|
2898
|
-
const [systemDark, setSystemDark] =
|
|
2899
|
-
const [settings, setSettings] =
|
|
2900
|
-
const [draftDetails, setDraftDetails] =
|
|
2901
|
-
const [editingId, setEditingId] =
|
|
3046
|
+
const [phase, setPhase] = useState5("boot");
|
|
3047
|
+
const [session, setSession] = useState5(null);
|
|
3048
|
+
const [member, setMember] = useState5(null);
|
|
3049
|
+
const [threads, setThreads] = useState5([]);
|
|
3050
|
+
const [route, setRoute] = useState5("/");
|
|
3051
|
+
const [surface, setSurface] = useState5("none");
|
|
3052
|
+
const [tab, setTab] = useState5("page");
|
|
3053
|
+
const [mode, setMode] = useState5("browse");
|
|
3054
|
+
const [reattachId, setReattachId] = useState5(null);
|
|
3055
|
+
const [activeId, setActiveId] = useState5(null);
|
|
3056
|
+
const [peekId, setPeekId] = useState5(null);
|
|
3057
|
+
const [draft, setDraft] = useState5(null);
|
|
3058
|
+
const [body, setBody] = useState5("");
|
|
3059
|
+
const [reply, setReply] = useState5("");
|
|
3060
|
+
const [name, setName] = useState5("");
|
|
3061
|
+
const [passphrase, setPassphrase] = useState5("");
|
|
3062
|
+
const [email, setEmail] = useState5("");
|
|
3063
|
+
const [members, setMembers] = useState5([]);
|
|
3064
|
+
const [profile, setProfile] = useState5(null);
|
|
3065
|
+
const [deliveries, setDeliveries] = useState5({});
|
|
3066
|
+
const [invite, setInvite] = useState5(null);
|
|
3067
|
+
const [capturing, setCapturing] = useState5(false);
|
|
3068
|
+
const [inviteLink, setInviteLink] = useState5(null);
|
|
3069
|
+
const [renaming, setRenaming] = useState5(null);
|
|
3070
|
+
const [confirmReset, setConfirmReset] = useState5(false);
|
|
3071
|
+
const [error, setError] = useState5("");
|
|
3072
|
+
const [toast, setToast] = useState5("");
|
|
3073
|
+
const [busy, setBusy] = useState5(false);
|
|
3074
|
+
const [prefs, setPrefs] = useState5({});
|
|
3075
|
+
const [portal, setPortal] = useState5(null);
|
|
3076
|
+
const [mounted, setMounted] = useState5(false);
|
|
3077
|
+
const [highlight, setHighlight] = useState5(null);
|
|
3078
|
+
const [flash, setFlash] = useState5(null);
|
|
3079
|
+
const [placed, setPlaced] = useState5([]);
|
|
3080
|
+
const [systemDark, setSystemDark] = useState5(false);
|
|
3081
|
+
const [settings, setSettings] = useState5(null);
|
|
3082
|
+
const [draftDetails, setDraftDetails] = useState5(noDetails);
|
|
3083
|
+
const [editingId, setEditingId] = useState5(null);
|
|
3084
|
+
const [view, setView] = useState5("list");
|
|
2902
3085
|
const threadsRef = useRef3(threads);
|
|
2903
3086
|
threadsRef.current = threads;
|
|
2904
3087
|
const modeRef = useRef3(mode);
|
|
@@ -3054,22 +3237,23 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3054
3237
|
};
|
|
3055
3238
|
}, [member, session]);
|
|
3056
3239
|
useEffect2(() => {
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
if (
|
|
3061
|
-
setInvite(
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3240
|
+
captureHandoff();
|
|
3241
|
+
const handoff = readHandoff();
|
|
3242
|
+
pendingThread.current = handoff?.thread ?? null;
|
|
3243
|
+
if (handoff?.invite)
|
|
3244
|
+
setInvite(handoff.invite);
|
|
3245
|
+
stripHandoffFromUrl();
|
|
3246
|
+
}, []);
|
|
3247
|
+
const dropInvite = useCallback2(() => {
|
|
3248
|
+
setInvite(null);
|
|
3249
|
+
dropHandoff("invite");
|
|
3066
3250
|
}, []);
|
|
3067
3251
|
useEffect2(() => {
|
|
3068
3252
|
if (phase === "ready" && !member && (pendingThread.current || invite))
|
|
3069
3253
|
setSurface("unlock");
|
|
3070
3254
|
if (member && invite)
|
|
3071
|
-
|
|
3072
|
-
}, [invite, member, phase]);
|
|
3255
|
+
dropInvite();
|
|
3256
|
+
}, [dropInvite, invite, member, phase]);
|
|
3073
3257
|
useEffect2(() => {
|
|
3074
3258
|
if (!mounted)
|
|
3075
3259
|
return;
|
|
@@ -3157,12 +3341,13 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3157
3341
|
}
|
|
3158
3342
|
if (!member || event.metaKey || event.ctrlKey || event.altKey || isTyping(event.target))
|
|
3159
3343
|
return;
|
|
3160
|
-
const
|
|
3161
|
-
if (
|
|
3344
|
+
const key2 = event.key.toLowerCase();
|
|
3345
|
+
if (key2 === "c")
|
|
3162
3346
|
startComment();
|
|
3163
|
-
else if (
|
|
3347
|
+
else if (key2 === "i") {
|
|
3348
|
+
setView(prefs.view ?? "list");
|
|
3164
3349
|
setSurface((current) => current === "inbox" ? "none" : "inbox");
|
|
3165
|
-
else if (
|
|
3350
|
+
} else if (key2 === "h")
|
|
3166
3351
|
togglePins();
|
|
3167
3352
|
else
|
|
3168
3353
|
return;
|
|
@@ -3170,7 +3355,7 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3170
3355
|
};
|
|
3171
3356
|
document.addEventListener("keydown", onKey);
|
|
3172
3357
|
return () => document.removeEventListener("keydown", onKey);
|
|
3173
|
-
}, [draft, member, mode, startComment, surface, togglePins]);
|
|
3358
|
+
}, [draft, member, mode, prefs.view, startComment, surface, togglePins]);
|
|
3174
3359
|
useEffect2(() => {
|
|
3175
3360
|
if (mode === "browse") {
|
|
3176
3361
|
setHighlight(null);
|
|
@@ -3255,19 +3440,19 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3255
3440
|
all: open.length,
|
|
3256
3441
|
resolved: placed.length - open.length
|
|
3257
3442
|
};
|
|
3258
|
-
const listed =
|
|
3443
|
+
const listed = useMemo3(() => {
|
|
3259
3444
|
if (tab === "resolved")
|
|
3260
3445
|
return placed.filter((item) => item.thread.status === "resolved");
|
|
3261
3446
|
const openOnly = placed.filter((item) => item.thread.status === "open");
|
|
3262
3447
|
return tab === "page" ? openOnly.filter((item) => item.thread.route === route) : openOnly;
|
|
3263
3448
|
}, [placed, route, tab]);
|
|
3264
|
-
const groups =
|
|
3449
|
+
const groups = useMemo3(() => {
|
|
3265
3450
|
if (tab !== "all")
|
|
3266
3451
|
return [{ route: null, items: listed }];
|
|
3267
3452
|
const byRoute = /* @__PURE__ */ new Map();
|
|
3268
3453
|
for (const item of listed)
|
|
3269
3454
|
byRoute.set(item.thread.route, [...byRoute.get(item.thread.route) ?? [], item]);
|
|
3270
|
-
return [...byRoute.entries()].sort(([a], [b]) => a === route ? -1 : b === route ? 1 : a.localeCompare(b)).map(([
|
|
3455
|
+
return [...byRoute.entries()].sort(([a], [b]) => a === route ? -1 : b === route ? 1 : a.localeCompare(b)).map(([key2, items]) => ({ route: key2, items }));
|
|
3271
3456
|
}, [listed, route, tab]);
|
|
3272
3457
|
const showOnPage = useCallback2((thread) => {
|
|
3273
3458
|
const { element } = resolveInDocument(thread.anchor, window.location.pathname);
|
|
@@ -3288,9 +3473,7 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3288
3473
|
if (!item)
|
|
3289
3474
|
return;
|
|
3290
3475
|
pendingThread.current = null;
|
|
3291
|
-
|
|
3292
|
-
url.searchParams.delete("cs-thread");
|
|
3293
|
-
history.replaceState(history.state, "", url);
|
|
3476
|
+
dropHandoff("thread");
|
|
3294
3477
|
setTab(item.thread.status === "resolved" ? "resolved" : item.thread.route === route ? "page" : "all");
|
|
3295
3478
|
setActiveId(id);
|
|
3296
3479
|
setSurface("inbox");
|
|
@@ -3313,9 +3496,9 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3313
3496
|
arrival.current = null;
|
|
3314
3497
|
showOnPage(item.thread);
|
|
3315
3498
|
}, [placed, showOnPage]);
|
|
3316
|
-
const select = useCallback2((item) => {
|
|
3499
|
+
const select = useCallback2((item, keepOpen = false) => {
|
|
3317
3500
|
const { thread } = item;
|
|
3318
|
-
if (activeId === thread.id) {
|
|
3501
|
+
if (!keepOpen && activeId === thread.id) {
|
|
3319
3502
|
setActiveId(null);
|
|
3320
3503
|
return;
|
|
3321
3504
|
}
|
|
@@ -3331,9 +3514,7 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3331
3514
|
navigate(target);
|
|
3332
3515
|
return;
|
|
3333
3516
|
}
|
|
3334
|
-
|
|
3335
|
-
url.searchParams.set("cs-thread", thread.id);
|
|
3336
|
-
window.location.assign(url.toString());
|
|
3517
|
+
window.location.assign(linkWith(target, "cs-thread", thread.id));
|
|
3337
3518
|
}, [activeId, navigate, route]);
|
|
3338
3519
|
if (!mounted || phase !== "ready" || !session)
|
|
3339
3520
|
return null;
|
|
@@ -3378,22 +3559,23 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3378
3559
|
setDraft(null);
|
|
3379
3560
|
setSurface("unlock");
|
|
3380
3561
|
};
|
|
3381
|
-
const bar =
|
|
3562
|
+
const bar = _jsx6("div", { className: "cs-bar cs-hit", "data-cs-ui": "bar", role: "toolbar", "aria-label": "Comments toolbar", children: !member ? _jsxs6("button", { className: "cs-bar-lock", "data-cs-ui": "launcher", type: "button", "aria-label": "Comments", onClick: () => {
|
|
3382
3563
|
setError("");
|
|
3383
3564
|
setSurface(surface === "unlock" ? "none" : "unlock");
|
|
3384
|
-
}, children: [
|
|
3565
|
+
}, children: [_jsx6(Lock, {}), _jsx6("span", { children: "Comments" })] }) : _jsxs6(_Fragment3, { children: [_jsx6("button", { className: mode === "select" ? "cs-tool is-on is-accent" : "cs-tool", "data-cs-ui": "comment-mode", "data-tip": "Comment C", type: "button", "aria-label": "Add comment", "aria-pressed": mode === "select", onClick: startComment, children: _jsx6(AddComment, {}) }), _jsxs6("button", { className: surface === "inbox" ? "cs-tool is-on" : "cs-tool", "data-cs-ui": "launcher", "data-tip": "Comments I", type: "button", "aria-label": "Comments", "aria-expanded": surface === "inbox", onClick: () => {
|
|
3385
3566
|
setError("");
|
|
3386
3567
|
setMode("browse");
|
|
3568
|
+
setView(prefs.view ?? "list");
|
|
3387
3569
|
setSurface(surface === "inbox" ? "none" : "inbox");
|
|
3388
|
-
}, children: [
|
|
3570
|
+
}, children: [_jsx6(Inbox, {}), counts.page > 0 ? _jsx6("span", { className: "cs-badge", children: counts.page }) : null] }), _jsx6("button", { className: pinsHidden ? "cs-tool is-on" : "cs-tool", "data-cs-ui": "pins-toggle", "data-tip": pinsHidden ? "Show pins H" : "Hide pins H", type: "button", "aria-label": pinsHidden ? "Show pins" : "Hide pins", "aria-pressed": pinsHidden, onClick: togglePins, children: pinsHidden ? _jsx6(EyeOff, {}) : _jsx6(Eye, {}) }), _jsx6("span", { className: "cs-divider" }), _jsx6("button", { className: surface === "menu" ? "cs-tool cs-me is-on" : "cs-tool cs-me", "data-cs-ui": "menu-button", "data-tip": memberName, type: "button", "aria-label": "You", "aria-expanded": surface === "menu", onClick: () => {
|
|
3389
3571
|
setConfirmReset(false);
|
|
3390
3572
|
setRenaming(null);
|
|
3391
3573
|
if (surface !== "menu" && member) {
|
|
3392
3574
|
getProfile(session, member).then(setProfile).catch(() => void 0);
|
|
3393
3575
|
}
|
|
3394
3576
|
setSurface(surface === "menu" ? "none" : "menu");
|
|
3395
|
-
}, children:
|
|
3396
|
-
const unlockCard =
|
|
3577
|
+
}, children: _jsx6(Avatar, { name: memberName, size: 24 }) })] }) });
|
|
3578
|
+
const unlockCard = _jsxs6("section", { className: "cs-card cs-unlock cs-hit", "data-cs-ui": "panel", "aria-label": "Unlock comments", children: [_jsx6("div", { className: "cs-unlock-icon", children: _jsx6(Lock, { size: 18 }) }), _jsx6("h2", { children: "Comments" }), _jsx6("p", { className: "cs-sub", children: invite ? `${readJwt(invite)?.name ?? "A teammate"} invited you to comment. Add your name and email to join.` : "Enter the team passphrase to see and add comments." }), _jsxs6("form", { onSubmit: (event) => {
|
|
3397
3579
|
event.preventDefault();
|
|
3398
3580
|
setBusy(true);
|
|
3399
3581
|
setError("");
|
|
@@ -3406,16 +3588,16 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3406
3588
|
localStorage.setItem(storageKey(fresh), token);
|
|
3407
3589
|
setMember(token);
|
|
3408
3590
|
setPassphrase("");
|
|
3409
|
-
|
|
3591
|
+
dropInvite();
|
|
3410
3592
|
setTab("page");
|
|
3411
3593
|
setSurface("inbox");
|
|
3412
3594
|
}).catch((caught) => {
|
|
3413
3595
|
if (caught instanceof ApiError && caught.code === "invalid_invite")
|
|
3414
|
-
|
|
3596
|
+
dropInvite();
|
|
3415
3597
|
setError(caught instanceof Error ? caught.message : "Couldn\u2019t unlock.");
|
|
3416
3598
|
}).finally(() => setBusy(false));
|
|
3417
|
-
}, children: [
|
|
3418
|
-
const menuCard =
|
|
3599
|
+
}, children: [_jsxs6("label", { className: "cs-field", children: [_jsx6("span", { children: "Your name" }), _jsx6("input", { "data-cs-ui": "unlock-name", value: name, onChange: (event) => setName(event.target.value), autoComplete: "name", required: true })] }), invite ? null : _jsxs6("label", { className: "cs-field", children: [_jsx6("span", { children: "Passphrase" }), _jsx6("input", { "data-cs-ui": "unlock-passphrase", type: "password", value: passphrase, onChange: (event) => setPassphrase(event.target.value), autoComplete: "current-password", required: true })] }), _jsxs6("label", { className: "cs-field", children: [_jsx6("span", { children: "Email" }), _jsx6("input", { "data-cs-ui": "unlock-email", type: "email", value: email, onChange: (event) => setEmail(event.target.value), autoComplete: "email", required: true }), _jsx6("small", { children: "So teammates can @mention you." })] }), error ? _jsx6("p", { className: "cs-error", "data-cs-ui": "error", children: error }) : null, _jsx6("button", { className: "cs-button is-primary is-wide", "data-cs-ui": "unlock-submit", type: "submit", disabled: busy, children: busy ? "Unlocking\u2026" : invite ? "Join" : "Unlock" })] })] });
|
|
3600
|
+
const menuCard = _jsx6("section", { className: "cs-card cs-menu cs-hit", "data-cs-ui": "menu", "aria-label": "Your comment settings", children: confirmReset ? _jsxs6("div", { className: "cs-confirm", "data-cs-ui": "reset-confirm", children: [_jsx6("h2", { children: "Reset on this device?" }), _jsx6("p", { className: "cs-sub", children: "You\u2019ll be signed out and your name and preferences are cleared. Comments aren\u2019t affected." }), _jsxs6("div", { className: "cs-row-end", children: [_jsx6("button", { className: "cs-button", type: "button", onClick: () => setConfirmReset(false), children: "Cancel" }), _jsx6("button", { className: "cs-button is-danger", "data-cs-ui": "reset-submit", type: "button", onClick: reset, children: "Reset" })] })] }) : _jsxs6(_Fragment3, { children: [_jsxs6("div", { className: "cs-me-row", children: [_jsx6(Avatar, { name: renaming ?? memberName, size: 36 }), renaming != null ? _jsxs6("form", { className: "cs-rename", onSubmit: (event) => {
|
|
3419
3601
|
event.preventDefault();
|
|
3420
3602
|
const next = renaming.trim();
|
|
3421
3603
|
if (!next || next === memberName || !member) {
|
|
@@ -3431,15 +3613,15 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3431
3613
|
setRenaming(null);
|
|
3432
3614
|
say("Name updated");
|
|
3433
3615
|
}).catch((caught) => setError(caught instanceof Error ? caught.message : "Couldn\u2019t rename.")).finally(() => setBusy(false));
|
|
3434
|
-
}, children: [
|
|
3616
|
+
}, children: [_jsx6("input", { "data-cs-ui": "rename-input", "aria-label": "Your name", value: renaming, maxLength: 40, autoFocus: true, onChange: (event) => setRenaming(event.target.value), onKeyDown: (event) => {
|
|
3435
3617
|
if (event.key === "Escape") {
|
|
3436
3618
|
event.preventDefault();
|
|
3437
3619
|
setRenaming(null);
|
|
3438
3620
|
}
|
|
3439
|
-
} }),
|
|
3621
|
+
} }), _jsx6("button", { className: "cs-icon-button", type: "submit", "aria-label": "Save name", disabled: busy, children: _jsx6(Check, {}) })] }) : _jsxs6("div", { className: "cs-me-name", children: [_jsxs6("span", { className: "cs-me-lines", children: [_jsx6("strong", { children: memberName }), _jsx6("small", { children: profile?.email ?? readJwt(member ?? "")?.email ?? "" })] }), _jsx6("button", { className: "cs-icon-button", "data-cs-ui": "rename", type: "button", "aria-label": "Change name", onClick: () => {
|
|
3440
3622
|
setError("");
|
|
3441
3623
|
setRenaming(memberName);
|
|
3442
|
-
}, children:
|
|
3624
|
+
}, children: _jsx6(Pencil, {}) })] })] }), error ? _jsx6("p", { className: "cs-error", children: error }) : null, _jsx6("div", { className: "cs-sep" }), _jsxs6("button", { className: "cs-item", type: "button", role: "switch", "aria-checked": !pinsHidden, onClick: togglePins, children: [_jsx6("span", { children: "Show pins" }), _jsx6("span", { className: pinsHidden ? "cs-switch" : "cs-switch is-on" })] }), _jsxs6("button", { className: "cs-item", "data-cs-ui": "mention-emails", type: "button", role: "switch", "aria-checked": profile?.mentionEmails ?? true, disabled: !profile, onClick: () => {
|
|
3443
3625
|
if (!member || !profile)
|
|
3444
3626
|
return;
|
|
3445
3627
|
updateProfile(session, member, { mentionEmails: !profile.mentionEmails }).then((updated) => {
|
|
@@ -3448,39 +3630,46 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3448
3630
|
setProfile(updated);
|
|
3449
3631
|
say(updated.mentionEmails ? "Mention emails on" : "Mention emails off");
|
|
3450
3632
|
}).catch((caught) => setError(caught instanceof Error ? caught.message : "Couldn\u2019t update."));
|
|
3451
|
-
}, children: [
|
|
3633
|
+
}, children: [_jsx6("span", { children: "Email me when mentioned" }), _jsx6("span", { className: profile?.mentionEmails ?? true ? "cs-switch is-on" : "cs-switch" })] }), _jsxs6("div", { className: "cs-item is-static", children: [_jsx6("span", { children: "Position" }), _jsx6("span", { className: "cs-segment", role: "radiogroup", "aria-label": "Toolbar position", children: positions.map((option) => _jsx6("button", { type: "button", role: "radio", "aria-checked": barPosition === option.value, className: barPosition === option.value ? "is-on" : "", onClick: () => savePrefs({ ...prefs, position: option.value }), children: option.label }, option.value)) })] }), _jsxs6("button", { className: "cs-item", "data-cs-ui": "settings-open", type: "button", onClick: () => {
|
|
3452
3634
|
setError("");
|
|
3453
3635
|
setSurface("settings");
|
|
3454
|
-
}, children: [
|
|
3636
|
+
}, children: [_jsx6("span", { children: "Comment fields" }), _jsx6("span", { className: "cs-hint", children: detailsEnabled(settings) ? "On" : "Off" })] }), _jsx6("div", { className: "cs-sep" }), _jsx6("button", { className: "cs-item", "data-cs-ui": "invite", type: "button", disabled: busy, onClick: () => {
|
|
3455
3637
|
if (!member)
|
|
3456
3638
|
return;
|
|
3457
3639
|
setBusy(true);
|
|
3458
3640
|
createInvite(session, member).then(({ invite: code }) => {
|
|
3459
|
-
const
|
|
3460
|
-
url.search = "";
|
|
3461
|
-
url.hash = "";
|
|
3462
|
-
url.searchParams.set("cs-invite", code);
|
|
3463
|
-
const link = url.toString();
|
|
3641
|
+
const link = linkWith(pageHref(), "cs-invite", code);
|
|
3464
3642
|
setInviteLink(link);
|
|
3465
3643
|
return navigator.clipboard.writeText(link).then(() => say("Invite link copied")).catch(() => say("Invite link ready"));
|
|
3466
3644
|
}).catch((caught) => setError(caught instanceof Error ? caught.message : "Couldn\u2019t create an invite.")).finally(() => setBusy(false));
|
|
3467
|
-
}, children:
|
|
3468
|
-
const
|
|
3645
|
+
}, children: _jsx6("span", { children: "Invite someone" }) }), inviteLink ? _jsxs6("div", { className: "cs-invite", children: [_jsx6("input", { "data-cs-ui": "invite-link", "aria-label": "Invite link", readOnly: true, value: inviteLink, onFocus: (event) => event.currentTarget.select() }), _jsx6("p", { className: "cs-hint", children: "Anyone with this link can join for 7 days. Changing the passphrase cancels it." })] }) : null, _jsx6("button", { className: "cs-item", "data-cs-ui": "lock", type: "button", onClick: lock, children: _jsx6("span", { children: "Lock" }) }), _jsx6("button", { className: "cs-item is-danger", "data-cs-ui": "reset", type: "button", onClick: () => setConfirmReset(true), children: _jsx6("span", { children: "Reset on this device\u2026" }) }), _jsx6("p", { className: "cs-hint", children: "C comment \xB7 I list \xB7 H pins" })] }) });
|
|
3646
|
+
const tabsBar = _jsx6("div", { className: "cs-tabs", role: "tablist", children: [
|
|
3469
3647
|
["page", "This page", counts.page, "scope-page"],
|
|
3470
3648
|
["all", "All pages", counts.all, "scope-all"],
|
|
3471
3649
|
["resolved", "Resolved", counts.resolved, "scope-resolved"]
|
|
3472
|
-
].map(([value, label, count, hook]) =>
|
|
3650
|
+
].map(([value, label, count, hook]) => _jsxs6("button", { type: "button", role: "tab", "aria-selected": tab === value, "data-cs-ui": hook, className: tab === value ? "is-on" : "", onClick: () => setTab(value), children: [label, count > 0 ? _jsx6("span", { className: "cs-count", children: count }) : null] }, value)) });
|
|
3651
|
+
const setViewPref = (next) => {
|
|
3652
|
+
setView(next);
|
|
3653
|
+
savePrefs({ ...prefs, view: next });
|
|
3654
|
+
};
|
|
3655
|
+
const table = _jsx6(CommentTable, { rows: listed, route, activeId, tabs: tabsBar, onList: () => setViewPref("list"), onClose: () => setSurface("none"), onSelect: (row) => {
|
|
3656
|
+
setView("list");
|
|
3657
|
+
const item = placed.find((candidate) => candidate.thread.id === row.thread.id);
|
|
3658
|
+
if (item)
|
|
3659
|
+
select(item, true);
|
|
3660
|
+
} });
|
|
3661
|
+
const inbox = _jsxs6("section", { className: "cs-card cs-sheet cs-hit", "data-cs-ui": "panel", "aria-label": "Comments", children: [_jsxs6("header", { className: "cs-sheet-head", children: [_jsx6("h2", { children: "Comments" }), _jsx6("button", { className: "cs-icon-button cs-push", "data-cs-ui": "table-view", type: "button", "aria-label": "Table view", onClick: () => setViewPref("table"), children: _jsx6(Table, {}) }), _jsx6("button", { className: "cs-icon-button", type: "button", "aria-label": "Close comments", onClick: () => setSurface("none"), children: _jsx6(Close, {}) })] }), tabsBar, error ? _jsx6("p", { className: "cs-error cs-pad", "data-cs-ui": "error", children: error }) : null, _jsxs6("div", { className: "cs-list", children: [listed.length === 0 ? _jsxs6("div", { className: "cs-empty", children: [_jsx6("p", { children: tab === "resolved" ? "Nothing resolved yet." : tab === "page" ? "No comments on this page." : "No open comments." }), tab !== "resolved" ? _jsxs6("button", { className: "cs-button", type: "button", onClick: startComment, children: [_jsx6(AddComment, {}), " Add a comment"] }) : null] }) : null, groups.map((group) => _jsxs6("div", { children: [group.route ? _jsx6("div", { className: "cs-group", children: group.route === route ? "This page" : group.route }) : null, group.items.map((item) => {
|
|
3473
3662
|
const { thread } = item;
|
|
3474
3663
|
const expanded = activeId === thread.id;
|
|
3475
3664
|
const first = thread.messages[0];
|
|
3476
3665
|
const note = statusNote(item.status, thread.anchor, thread.route === route);
|
|
3477
3666
|
const onPage = item.status === "pinned" || item.status === "drifted";
|
|
3478
|
-
return
|
|
3667
|
+
return _jsxs6("article", { className: expanded ? "cs-thread is-open" : "cs-thread", "data-cs-ui": "thread", "data-thread-id": thread.id, "data-cs-status": item.status, children: [_jsxs6("div", { className: "cs-thread-main", role: "button", tabIndex: 0, "aria-expanded": expanded, "aria-label": `${thread.createdBy}: ${first?.body ?? ""}`, onClick: () => select(item), onKeyDown: (event) => {
|
|
3479
3668
|
if (event.key === "Enter" || event.key === " ") {
|
|
3480
3669
|
event.preventDefault();
|
|
3481
3670
|
select(item);
|
|
3482
3671
|
}
|
|
3483
|
-
}, onMouseEnter: () => setPeekId(null), children: [
|
|
3672
|
+
}, onMouseEnter: () => setPeekId(null), children: [_jsx6(Avatar, { name: thread.createdBy }), _jsxs6("div", { className: "cs-thread-body", children: [_jsxs6("div", { className: "cs-meta", children: [_jsx6("strong", { children: thread.createdBy }), _jsx6("time", { dateTime: thread.createdAt, children: ago(thread.createdAt) }), _jsx6(RoleBadge, { role: thread.role })] }), first?.body ? _jsx6("p", { className: "cs-text", children: _jsx6(MessageText, { body: first.body, mentions: first.mentions }) }) : null, _jsx6(FieldValues, { fields: thread.fields, clamp: !expanded }), _jsx6(MessageAttachments, { attachments: first?.attachments }), first && deliveryText(deliveries[first.id]) ? _jsx6("div", { className: "cs-delivery", "data-cs-ui": "delivery", children: deliveryText(deliveries[first.id]) }) : null, _jsxs6("div", { className: "cs-target", children: [_jsx6("span", { title: thread.anchor.component?.file ?? void 0, children: targetName(thread.anchor) }), note ? _jsx6("span", { className: `cs-note is-${note.tone}`, children: note.text }) : null] }), !expanded && thread.messages.length > 1 ? _jsxs6("div", { className: "cs-replies", children: [thread.messages.length - 1, " ", thread.messages.length === 2 ? "reply" : "replies"] }) : null] })] }), expanded ? _jsxs6("div", { className: "cs-thread-more", children: [editingId === thread.id && settings ? _jsx6(DetailsEditor, { settings, thread, onClose: () => setEditingId(null), onSave: (patch) => updateThread(session, member, thread.id, patch).then(() => refresh()).then(() => say("Details saved")).catch((caught) => setError(caught instanceof Error ? caught.message : "Couldn\u2019t save.")) }) : null, thread.messages.slice(1).map((message) => _jsxs6("div", { className: "cs-message", children: [_jsx6(Avatar, { name: message.author, size: 20 }), _jsxs6("div", { children: [_jsxs6("div", { className: "cs-meta", children: [_jsx6("strong", { children: message.author }), _jsx6("time", { dateTime: message.createdAt, children: ago(message.createdAt) })] }), _jsx6("p", { className: "cs-text", children: _jsx6(MessageText, { body: message.body, mentions: message.mentions }) }), _jsx6(MessageAttachments, { attachments: message.attachments }), deliveryText(deliveries[message.id]) ? _jsx6("div", { className: "cs-delivery", "data-cs-ui": "delivery", children: deliveryText(deliveries[message.id]) }) : null] })] }, message.id)), _jsxs6("form", { className: "cs-reply", onSubmit: async (event) => {
|
|
3484
3673
|
event.preventDefault();
|
|
3485
3674
|
if (!member || !reply.trim() && !replyFiles.ids.length || replyFiles.uploading)
|
|
3486
3675
|
return;
|
|
@@ -3506,7 +3695,7 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3506
3695
|
}
|
|
3507
3696
|
await refresh();
|
|
3508
3697
|
}).catch((caught) => setError(caught instanceof Error ? caught.message : "Couldn\u2019t reply.")).finally(() => setBusy(false));
|
|
3509
|
-
}, children: [
|
|
3698
|
+
}, children: [_jsx6(MentionTextarea, { "data-cs-ui": "reply-body", "aria-label": "Reply", placeholder: "Reply\u2026 (@ to mention)", rows: 1, value: reply, onValueChange: setReply, members, selfEmail: readJwt(member ?? "")?.email, onMention: (person) => {
|
|
3510
3699
|
replyPicked.current.set(person.id, person);
|
|
3511
3700
|
const element = thread.route === route ? resolveInDocument(thread.anchor, route).element : null;
|
|
3512
3701
|
if (element && !replyShot.current)
|
|
@@ -3517,25 +3706,25 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3517
3706
|
event.preventDefault();
|
|
3518
3707
|
replyFiles.add(files);
|
|
3519
3708
|
}
|
|
3520
|
-
} }),
|
|
3709
|
+
} }), _jsx6(AttachButtons, { onFiles: replyFiles.add, capturing, onSnapshot: () => snapshot(thread.route === route ? resolveInDocument(thread.anchor, route).element : null, replyFiles.add) }), _jsx6("button", { className: "cs-send", "data-cs-ui": "reply-submit", type: "submit", "aria-label": "Post reply", disabled: busy || replyFiles.uploading || !reply.trim() && !replyFiles.ids.length, children: _jsx6(Send, {}) })] }), _jsx6(AttachmentTray, { items: replyFiles.items, onRemove: replyFiles.remove }), _jsxs6("div", { className: "cs-actions", children: [_jsxs6("button", { className: "cs-button", "data-cs-ui": "resolve", type: "button", onClick: () => {
|
|
3521
3710
|
if (!member)
|
|
3522
3711
|
return;
|
|
3523
3712
|
const next = thread.status === "resolved" ? "open" : "resolved";
|
|
3524
3713
|
updateThread(session, member, thread.id, { status: next }).then(() => refresh()).then(() => say(next === "resolved" ? "Resolved" : "Reopened")).catch((caught) => setError(caught instanceof Error ? caught.message : "Couldn\u2019t update."));
|
|
3525
|
-
}, children: [thread.status === "resolved" ?
|
|
3714
|
+
}, children: [thread.status === "resolved" ? _jsx6(Undo, {}) : _jsx6(Check, {}), thread.status === "resolved" ? "Reopen" : "Resolve"] }), onPage && thread.status === "open" ? _jsxs6("button", { className: "cs-button", type: "button", onClick: () => showOnPage(thread), children: [_jsx6(Target, {}), " Show"] }) : null, detailsEnabled(settings) && editingId !== thread.id ? _jsxs6("button", { className: "cs-button", "data-cs-ui": "details-edit", type: "button", onClick: () => setEditingId(thread.id), children: [_jsx6(Pencil, {}), " Details"] }) : null, !onPage && thread.status === "open" && thread.route === route ? _jsxs6("button", { className: "cs-button", "data-cs-ui": "reattach", type: "button", onClick: () => {
|
|
3526
3715
|
setReattachId(thread.id);
|
|
3527
3716
|
setMode("reattach");
|
|
3528
3717
|
setSurface("none");
|
|
3529
|
-
}, children: [
|
|
3718
|
+
}, children: [_jsx6(Relink, {}), " Reattach"] }) : null] })] }) : null] }, thread.id);
|
|
3530
3719
|
})] }, group.route ?? "all"))] })] });
|
|
3531
|
-
const ui =
|
|
3720
|
+
const ui = _jsxs6("div", { id: "cs-root", className: [
|
|
3532
3721
|
inside ? "cs-inside" : "cs-fixed",
|
|
3533
3722
|
`cs-at-${barPosition.replace("bottom-", "")}`,
|
|
3534
3723
|
theme === "dark" || theme === "system" && systemDark ? "cs-dark" : ""
|
|
3535
|
-
].join(" "), children: [highlight ?
|
|
3724
|
+
].join(" "), children: [highlight ? _jsxs6(_Fragment3, { children: [_jsx6("div", { className: "cs-outline", style: { top: highlight.top, left: highlight.left, width: highlight.width, height: highlight.height } }), _jsx6("div", { className: "cs-outline-label", style: { top: Math.max(4, highlight.top - 26), left: highlight.left }, children: highlight.label })] }) : null, flash ? _jsx6("div", { className: "cs-outline is-flash", style: { top: flash.top, left: flash.left, width: flash.width, height: flash.height } }) : null, mode !== "browse" ? _jsxs6("div", { className: "cs-banner cs-hit", "data-cs-ui": "mode", children: [_jsx6(Cursor, {}), _jsx6("span", { children: mode === "reattach" ? "Click the element this comment belongs to" : "Click anything to comment" }), _jsx6("button", { type: "button", onClick: () => {
|
|
3536
3725
|
setMode("browse");
|
|
3537
3726
|
setReattachId(null);
|
|
3538
|
-
}, children: "Cancel" })] }) : null, pinsHidden ? null : placed.map((item) => item.top == null || item.left == null || item.status !== "pinned" && item.status !== "drifted" ? null :
|
|
3727
|
+
}, children: "Cancel" })] }) : null, pinsHidden ? null : placed.map((item) => item.top == null || item.left == null || item.status !== "pinned" && item.status !== "drifted" ? null : _jsxs6("button", { type: "button", className: [
|
|
3539
3728
|
"cs-pin",
|
|
3540
3729
|
item.status === "drifted" ? "is-drifted" : "",
|
|
3541
3730
|
activeId === item.thread.id && surface === "inbox" ? "is-active" : ""
|
|
@@ -3544,7 +3733,7 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3544
3733
|
setTab("page");
|
|
3545
3734
|
setActiveId(item.thread.id);
|
|
3546
3735
|
setSurface("inbox");
|
|
3547
|
-
}, children: [
|
|
3736
|
+
}, children: [_jsx6(Avatar, { name: item.thread.createdBy, size: 22 }), item.thread.messages.length > 1 ? _jsx6("span", { className: "cs-pin-count", children: item.thread.messages.length }) : null] }, item.thread.id)), peek && !pinsHidden && peek.top != null && peek.left != null ? _jsxs6("div", { className: "cs-peek", style: { top: peek.top + 18, left: Math.max(8, peek.left - 12) }, children: [_jsxs6("div", { className: "cs-meta", children: [_jsx6(Avatar, { name: peek.thread.createdBy, size: 18 }), _jsx6("strong", { children: peek.thread.createdBy }), _jsx6("time", { children: ago(peek.thread.createdAt) })] }), _jsx6("p", { className: "cs-text", children: _jsx6(MessageText, { body: peek.thread.messages[0]?.body ?? "", mentions: peek.thread.messages[0]?.mentions }) }), peek.thread.messages.length > 1 ? _jsxs6("div", { className: "cs-replies", children: [peek.thread.messages.length - 1, " ", peek.thread.messages.length === 2 ? "reply" : "replies"] }) : null] }) : null, draft ? _jsxs6("form", { className: "cs-card cs-composer cs-hit", "data-cs-ui": "composer", style: { top: draft.top, left: draft.left }, onSubmit: async (event) => {
|
|
3548
3737
|
event.preventDefault();
|
|
3549
3738
|
if (!member || !canPost || draftFiles.uploading)
|
|
3550
3739
|
return;
|
|
@@ -3578,7 +3767,7 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3578
3767
|
setSurface("inbox");
|
|
3579
3768
|
await refresh();
|
|
3580
3769
|
}).catch((caught) => setError(caught instanceof Error ? caught.message : "Couldn\u2019t post.")).finally(() => setBusy(false));
|
|
3581
|
-
}, children: [
|
|
3770
|
+
}, children: [_jsxs6("div", { className: "cs-composer-target", children: [_jsx6(Target, {}), _jsx6("span", { className: "cs-composer-name", children: targetName(draft.anchor) }), draft.anchor.component?.file ? _jsx6("code", { children: draft.anchor.component.file }) : null, _jsx6("button", { className: "cs-icon-button", type: "button", "aria-label": "Discard", onClick: () => setDraft(null), children: _jsx6(Close, {}) })] }), _jsxs6("div", { className: "cs-composer-body", children: [_jsx6(Avatar, { name: memberName, size: 24 }), _jsx6(MentionTextarea, { "data-cs-ui": "composer-body", "aria-label": "Comment", placeholder: "Add a comment\u2026 (@ to mention)", value: body, autoFocus: true, onValueChange: setBody, members, selfEmail: readJwt(member ?? "")?.email, onMention: (person) => {
|
|
3582
3771
|
draftPicked.current.set(person.id, person);
|
|
3583
3772
|
if (!draftShot.current)
|
|
3584
3773
|
draftShot.current = captureAround(draft.element);
|
|
@@ -3588,7 +3777,7 @@ function CommentToolbar({ sessionPath = "/api/comment-service/session", pollMs =
|
|
|
3588
3777
|
event.preventDefault();
|
|
3589
3778
|
draftFiles.add(files);
|
|
3590
3779
|
}
|
|
3591
|
-
} })] }),
|
|
3780
|
+
} })] }), _jsx6(DetailsInput, { settings, value: draftDetails, onChange: setDraftDetails, onKeyDown: submitOnCmdEnter }), _jsx6(AttachmentTray, { items: draftFiles.items, onRemove: draftFiles.remove }), error ? _jsx6("p", { className: "cs-error cs-pad", children: error }) : null, _jsxs6("div", { className: "cs-composer-foot", children: [_jsx6(AttachButtons, { onFiles: draftFiles.add, capturing, onSnapshot: () => snapshot(draft.element, draftFiles.add) }), _jsx6("span", { className: "cs-hint", children: capturing ? "Capturing\u2026" : draftFiles.uploading ? "Uploading\u2026" : busy ? "Posting\u2026" : "\u2318\u21B5 to post" }), _jsx6("button", { className: "cs-send", "data-cs-ui": "composer-submit", type: "submit", "aria-label": "Post comment", disabled: busy || draftFiles.uploading || !canPost, children: _jsx6(Send, {}) })] })] }) : null, surface === "unlock" && !member ? unlockCard : null, surface === "menu" && member ? menuCard : null, surface === "settings" && member ? _jsx6(SettingsPanel, { settings, onChange: changeSettings, onBack: () => setSurface("menu"), error }) : null, surface === "inbox" && member ? view === "table" ? table : inbox : null, toast ? _jsx6("div", { className: "cs-toast", role: "status", children: toast }) : null, bar] });
|
|
3592
3781
|
return createPortal2(ui, host);
|
|
3593
3782
|
}
|
|
3594
3783
|
export {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Handoff = {
|
|
2
|
+
invite?: string;
|
|
3
|
+
thread?: string;
|
|
4
|
+
at: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function readHandoff(): Handoff | null;
|
|
7
|
+
/**
|
|
8
|
+
* Saves invite and thread links for this tab before the app's router or sign-in flow rewrites the URL.
|
|
9
|
+
* Runs when the module loads, which is before hydration, and again when the toolbar mounts.
|
|
10
|
+
*/
|
|
11
|
+
export declare function captureHandoff(): void;
|
|
12
|
+
export declare function dropHandoff(part: "invite" | "thread"): void;
|
|
13
|
+
/** Removes the link params from the address bar once they're saved. */
|
|
14
|
+
export declare function stripHandoffFromUrl(): void;
|
|
15
|
+
export declare function linkWith(href: string, name: "cs-invite" | "cs-thread", value: string): string;
|
|
@@ -17,3 +17,5 @@ export declare const Paperclip: () => import("react").JSX.Element;
|
|
|
17
17
|
export declare const Camera: () => import("react").JSX.Element;
|
|
18
18
|
export declare const FileIcon: () => import("react").JSX.Element;
|
|
19
19
|
export declare const Back: () => import("react").JSX.Element;
|
|
20
|
+
export declare const Table: () => import("react").JSX.Element;
|
|
21
|
+
export declare const List: () => import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const toolbarCss = "\n#cs-root {\n --cs-text: #1d1d1f;\n --cs-text-2: #6e6e73;\n --cs-text-3: #a1a1a6;\n --cs-glass: rgba(251, 251, 253, 0.8);\n --cs-card: rgba(255, 255, 255, 0.94);\n --cs-fill: rgba(0, 0, 0, 0.05);\n --cs-fill-2: rgba(0, 0, 0, 0.08);\n --cs-line: rgba(0, 0, 0, 0.08);\n --cs-edge: rgba(0, 0, 0, 0.1);\n --cs-accent: #007aff;\n --cs-accent-soft: rgba(0, 122, 255, 0.12);\n --cs-danger: #ff3b30;\n --cs-warn: #ff9500;\n --cs-shadow: 0 0 0 0.5px var(--cs-edge), 0 10px 30px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.06);\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n pointer-events: none;\n margin: 0;\n padding: 0;\n border: 0;\n background: transparent;\n color: var(--cs-text);\n font: 13px/1.4 -apple-system, BlinkMacSystemFont, \"SF Pro Text\", \"Helvetica Neue\", Inter, system-ui, sans-serif;\n letter-spacing: -0.005em;\n -webkit-font-smoothing: antialiased;\n text-align: left;\n}\n#cs-root.cs-dark {\n --cs-text: #f5f5f7;\n --cs-text-2: #a1a1a6;\n --cs-text-3: #6e6e73;\n --cs-glass: rgba(40, 40, 44, 0.78);\n --cs-card: rgba(36, 36, 40, 0.96);\n --cs-fill: rgba(255, 255, 255, 0.07);\n --cs-fill-2: rgba(255, 255, 255, 0.12);\n --cs-line: rgba(255, 255, 255, 0.08);\n --cs-edge: rgba(255, 255, 255, 0.12);\n --cs-accent: #0a84ff;\n --cs-accent-soft: rgba(10, 132, 255, 0.2);\n --cs-shadow: 0 0 0 0.5px var(--cs-edge), 0 10px 30px rgba(0, 0, 0, 0.45);\n}\n#cs-root.cs-inside { position: absolute; }\n#cs-root, #cs-root * { box-sizing: border-box; }\n#cs-root h2, #cs-root p { margin: 0; }\n#cs-root button, #cs-root input, #cs-root textarea {\n font: inherit; color: inherit; letter-spacing: inherit; margin: 0;\n}\n#cs-root button { background: none; border: 0; padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n#cs-root button:disabled { cursor: default; opacity: 0.45; }\n#cs-root button:focus-visible, #cs-root [role=button]:focus-visible { outline: 2px solid var(--cs-accent); outline-offset: 2px; }\n#cs-root .cs-hit { pointer-events: auto; }\n#cs-root .cs-icon { display: block; flex: none; }\n\n/* Bar */\n#cs-root .cs-bar {\n position: absolute;\n bottom: 16px;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px;\n border-radius: 999px;\n background: var(--cs-glass);\n -webkit-backdrop-filter: saturate(180%) blur(20px);\n backdrop-filter: saturate(180%) blur(20px);\n box-shadow: var(--cs-shadow);\n}\n#cs-root.cs-at-center .cs-bar { left: 50%; transform: translateX(-50%); }\n#cs-root.cs-at-left .cs-bar { left: 16px; }\n#cs-root.cs-at-right .cs-bar { right: 16px; }\n#cs-root .cs-tool {\n position: relative;\n width: 34px;\n height: 34px;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--cs-text);\n transition: background-color 0.15s ease, color 0.15s ease;\n}\n#cs-root .cs-tool:hover { background: var(--cs-fill); }\n#cs-root .cs-tool.is-on { background: var(--cs-fill-2); }\n#cs-root .cs-tool.is-accent { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-tool[data-tip]::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translate(-50%, 2px);\n white-space: pre;\n padding: 4px 8px;\n border-radius: 7px;\n background: rgba(29, 29, 31, 0.92);\n color: #fff;\n font-size: 11.5px;\n font-weight: 500;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.12s ease, transform 0.12s ease;\n}\n#cs-root .cs-tool[data-tip]:hover::after { opacity: 1; transform: translate(-50%, 0); transition-delay: 0.35s; }\n#cs-root .cs-me { width: 34px; }\n#cs-root .cs-divider { width: 1px; height: 18px; background: var(--cs-line); margin: 0 3px; }\n#cs-root .cs-badge {\n position: absolute;\n top: 3px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--cs-accent);\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n box-shadow: 0 0 0 2px var(--cs-glass);\n}\n#cs-root .cs-bar-lock {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n height: 34px;\n padding: 0 14px 0 12px;\n border-radius: 999px;\n font-weight: 500;\n}\n#cs-root .cs-bar-lock:hover { background: var(--cs-fill); }\n#cs-root .cs-avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n border-radius: 999px;\n color: #fff;\n font-weight: 600;\n letter-spacing: 0;\n line-height: 1;\n user-select: none;\n}\n\n/* Cards */\n#cs-root .cs-card {\n position: absolute;\n background: var(--cs-card);\n -webkit-backdrop-filter: saturate(180%) blur(24px);\n backdrop-filter: saturate(180%) blur(24px);\n border-radius: 14px;\n box-shadow: var(--cs-shadow);\n}\n#cs-root .cs-unlock, #cs-root .cs-menu { bottom: 64px; }\n#cs-root.cs-at-center .cs-unlock, #cs-root.cs-at-center .cs-menu { left: 50%; transform: translateX(-50%); }\n#cs-root.cs-at-left .cs-unlock, #cs-root.cs-at-left .cs-menu { left: 16px; }\n#cs-root.cs-at-right .cs-unlock, #cs-root.cs-at-right .cs-menu { right: 16px; }\n#cs-root .cs-unlock { width: 280px; padding: 20px; text-align: center; }\n#cs-root .cs-unlock-icon {\n width: 40px; height: 40px; margin: 0 auto 10px; border-radius: 12px;\n display: flex; align-items: center; justify-content: center; background: var(--cs-fill); color: var(--cs-text-2);\n}\n#cs-root .cs-unlock h2 { font-size: 15px; font-weight: 600; }\n#cs-root .cs-sub { color: var(--cs-text-2); margin-top: 4px; }\n#cs-root .cs-unlock form { margin-top: 14px; display: grid; gap: 8px; text-align: left; }\n#cs-root .cs-field { display: grid; gap: 4px; }\n#cs-root .cs-field span { font-size: 12px; color: var(--cs-text-2); padding-left: 2px; }\n#cs-root input, #cs-root textarea {\n width: 100%;\n border: 0;\n border-radius: 9px;\n background: var(--cs-fill);\n padding: 8px 10px;\n outline: none;\n transition: box-shadow 0.15s ease, background-color 0.15s ease;\n}\n#cs-root input:focus, #cs-root textarea:focus { background: transparent; box-shadow: 0 0 0 1px var(--cs-accent), 0 0 0 4px var(--cs-accent-soft); }\n#cs-root textarea { resize: none; }\n#cs-root .cs-error { color: var(--cs-danger); font-size: 12px; }\n#cs-root .cs-pad { padding: 6px 14px 0; }\n#cs-root .cs-hint { color: var(--cs-text-3); font-size: 11.5px; }\n\n/* Buttons */\n#cs-root .cs-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n height: 28px;\n padding: 0 11px;\n border-radius: 8px;\n background: var(--cs-fill);\n font-size: 12.5px;\n font-weight: 500;\n transition: background-color 0.15s ease;\n}\n#cs-root .cs-button:hover { background: var(--cs-fill-2); }\n#cs-root .cs-button.is-primary { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-button.is-primary:hover { filter: brightness(1.06); }\n#cs-root .cs-button.is-danger { background: var(--cs-danger); color: #fff; }\n#cs-root .cs-button.is-wide { width: 100%; height: 32px; margin-top: 4px; }\n#cs-root .cs-icon-button {\n width: 26px; height: 26px; border-radius: 999px; flex: none;\n display: inline-flex; align-items: center; justify-content: center; color: var(--cs-text-2);\n}\n#cs-root .cs-icon-button:hover { background: var(--cs-fill); color: var(--cs-text); }\n#cs-root .cs-send {\n width: 26px; height: 26px; border-radius: 999px; flex: none;\n display: inline-flex; align-items: center; justify-content: center; background: var(--cs-accent); color: #fff;\n}\n#cs-root .cs-send:disabled { background: var(--cs-fill-2); color: var(--cs-text-3); opacity: 1; }\n\n/* Menu */\n#cs-root .cs-menu { width: 264px; padding: 6px; }\n#cs-root .cs-me-row { display: flex; align-items: center; gap: 10px; padding: 8px 8px 10px; }\n#cs-root .cs-me-name { display: flex; align-items: center; gap: 4px; min-width: 0; }\n#cs-root .cs-me-name strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-rename { display: flex; align-items: center; gap: 4px; flex: 1; }\n#cs-root .cs-rename input { padding: 5px 8px; }\n#cs-root .cs-sep { height: 1px; background: var(--cs-line); margin: 4px 8px; }\n#cs-root .cs-item {\n display: flex; align-items: center; justify-content: space-between; gap: 10px;\n width: 100%; min-height: 32px; padding: 0 8px; border-radius: 8px; text-align: left;\n}\n#cs-root button.cs-item:hover { background: var(--cs-fill); }\n#cs-root .cs-item.is-danger { color: var(--cs-danger); }\n#cs-root .cs-switch { position: relative; width: 32px; height: 20px; border-radius: 999px; background: var(--cs-fill-2); transition: background-color 0.2s ease; flex: none; }\n#cs-root .cs-switch::after {\n content: \"\"; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 999px;\n background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); transition: transform 0.2s ease;\n}\n#cs-root .cs-switch.is-on { background: #34c759; }\n#cs-root .cs-switch.is-on::after { transform: translateX(12px); }\n#cs-root .cs-segment { display: inline-flex; padding: 2px; border-radius: 8px; background: var(--cs-fill); }\n#cs-root .cs-segment button { padding: 2px 8px; border-radius: 6px; font-size: 12px; color: var(--cs-text-2); }\n#cs-root .cs-segment button.is-on { background: var(--cs-card); color: var(--cs-text); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12); font-weight: 500; }\n#cs-root .cs-menu .cs-hint { padding: 6px 8px 4px; }\n#cs-root .cs-invite { padding: 2px 8px 6px; }\n#cs-root .cs-invite input { font: 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; padding: 6px 8px; }\n#cs-root .cs-invite .cs-hint { padding: 4px 0 0; }\n#cs-root .cs-confirm { padding: 10px; }\n#cs-root .cs-confirm h2 { font-size: 14px; font-weight: 600; }\n#cs-root .cs-row-end { display: flex; justify-content: flex-end; gap: 6px; margin-top: 12px; }\n\n/* Sheet */\n#cs-root .cs-sheet {\n top: 12px; right: 12px; max-height: calc(100% - 88px); width: min(360px, calc(100vw - 24px));\n display: flex; flex-direction: column; overflow: hidden;\n}\n#cs-root .cs-sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 10px 4px 16px; }\n#cs-root .cs-sheet-head h2 { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }\n#cs-root .cs-tabs { display: flex; gap: 2px; margin: 4px 12px 6px; padding: 2px; border-radius: 9px; background: var(--cs-fill); }\n#cs-root .cs-tabs button {\n flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px;\n height: 26px; border-radius: 7px; font-size: 12px; font-weight: 500; color: var(--cs-text-2);\n}\n#cs-root .cs-tabs button.is-on { background: var(--cs-card); color: var(--cs-text); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12); }\n#cs-root .cs-count { font-size: 11px; color: var(--cs-text-3); font-variant-numeric: tabular-nums; }\n#cs-root .cs-list { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 2px 6px 8px; overscroll-behavior: contain; }\n#cs-root .cs-group { padding: 10px 10px 4px; font-size: 11px; font-weight: 600; color: var(--cs-text-3); text-transform: uppercase; letter-spacing: 0.04em; }\n#cs-root .cs-empty { padding: 36px 16px; text-align: center; color: var(--cs-text-2); display: grid; gap: 12px; justify-items: center; }\n#cs-root .cs-thread { border-radius: 10px; }\n#cs-root .cs-thread + .cs-thread { margin-top: 1px; }\n#cs-root .cs-thread.is-open { background: var(--cs-fill); }\n#cs-root .cs-thread-main { display: flex; gap: 10px; padding: 10px; border-radius: 10px; cursor: pointer; }\n#cs-root .cs-thread:not(.is-open) .cs-thread-main:hover { background: var(--cs-fill); }\n#cs-root .cs-thread-body { min-width: 0; flex: 1; }\n#cs-root .cs-meta { display: flex; align-items: center; gap: 6px; font-size: 12.5px; }\n#cs-root .cs-meta strong { font-weight: 600; }\n#cs-root .cs-meta time { color: var(--cs-text-3); font-size: 12px; }\n#cs-root .cs-text { margin-top: 2px; white-space: pre-wrap; overflow-wrap: anywhere; }\n#cs-root .cs-target { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 4px; font-size: 11.5px; color: var(--cs-text-3); }\n#cs-root .cs-note { display: inline-flex; align-items: center; gap: 5px; font-weight: 500; }\n#cs-root .cs-note::before { content: \"\"; width: 6px; height: 6px; border-radius: 999px; background: currentColor; }\n#cs-root .cs-note.is-quiet { color: var(--cs-text-2); }\n#cs-root .cs-note.is-warn { color: var(--cs-warn); }\n#cs-root .cs-note.is-bad { color: var(--cs-danger); }\n#cs-root .cs-replies { margin-top: 4px; font-size: 12px; color: var(--cs-accent); font-weight: 500; }\n#cs-root .cs-thread-more { padding: 0 10px 10px 44px; display: grid; gap: 10px; }\n#cs-root .cs-message { display: flex; gap: 8px; }\n#cs-root .cs-reply { display: flex; align-items: flex-end; gap: 6px; padding: 4px 4px 4px 0; border-radius: 10px; }\n#cs-root .cs-reply textarea { min-height: 32px; max-height: 120px; field-sizing: content; }\n#cs-root .cs-thread.is-open .cs-reply textarea { background: var(--cs-card); }\n#cs-root .cs-actions { display: flex; flex-wrap: wrap; gap: 6px; }\n#cs-root .cs-thread.is-open .cs-button { background: var(--cs-card); box-shadow: 0 0 0 0.5px var(--cs-edge); }\n#cs-root .cs-thread.is-open .cs-button:hover { background: var(--cs-fill-2); }\n\n/* Mentions */\n#cs-root .cs-mention { color: var(--cs-accent); background: var(--cs-accent-soft); border-radius: 4px; padding: 0 3px; font-weight: 500; }\n#cs-root .cs-delivery { margin-top: 4px; font-size: 11.5px; color: var(--cs-text-3); display: flex; align-items: center; gap: 5px; }\n#cs-root .cs-delivery::before { content: \"\"; width: 6px; height: 6px; border-radius: 999px; background: #34c759; }\n#cs-root .cs-people {\n position: fixed; z-index: 1; width: 264px; padding: 5px; border-radius: 12px;\n background: var(--cs-card); box-shadow: var(--cs-shadow); pointer-events: auto;\n}\n#cs-root .cs-person { display: flex; align-items: center; gap: 9px; padding: 6px 8px; border-radius: 8px; cursor: pointer; }\n#cs-root .cs-person.is-on { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-person-text { display: grid; line-height: 1.25; min-width: 0; }\n#cs-root .cs-person-text strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-person-text small { font-size: 11.5px; color: var(--cs-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-person.is-on small { color: rgba(255, 255, 255, 0.8); }\n#cs-root .cs-field small { font-size: 11.5px; color: var(--cs-text-3); padding-left: 2px; }\n#cs-root .cs-me-lines { display: grid; line-height: 1.25; min-width: 0; }\n#cs-root .cs-me-lines small { font-size: 11.5px; color: var(--cs-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n/* Composer */\n#cs-root .cs-composer { width: min(320px, calc(100% - 16px)); }\n#cs-root .cs-composer-target {\n display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 12px;\n border-bottom: 1px solid var(--cs-line); font-size: 12px; color: var(--cs-text-2);\n}\n#cs-root .cs-composer-name { font-weight: 500; color: var(--cs-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n#cs-root .cs-composer-target code {\n margin-left: auto; font: 11px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--cs-text-3);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; min-width: 0; max-width: 45%;\n}\n#cs-root .cs-composer-body { display: flex; gap: 10px; padding: 12px 12px 4px; }\n#cs-root .cs-composer-body textarea { background: transparent; padding: 3px 0; min-height: 56px; box-shadow: none; border-radius: 0; }\n#cs-root .cs-composer-foot { display: flex; align-items: center; gap: 6px; padding: 6px 8px 8px 40px; }\n#cs-root .cs-composer-foot .cs-hint { margin-left: auto; }\n\n/* Roles and fields */\n#cs-root .cs-details-input { display: grid; gap: 8px; padding: 2px 12px 6px 46px; }\n#cs-root .cs-details-edit .cs-details-input { padding: 0; }\n#cs-root .cs-detail-field { display: grid; gap: 3px; }\n#cs-root .cs-detail-field span, #cs-root .cs-roles-label, #cs-root .cs-detail-list dt {\n font-size: 11px; font-weight: 600; color: var(--cs-text-3); text-transform: uppercase; letter-spacing: 0.03em;\n}\n#cs-root .cs-detail-field textarea { padding: 6px 8px; min-height: 30px; max-height: 120px; field-sizing: content; }\n#cs-root .cs-thread.is-open .cs-detail-field textarea { background: var(--cs-card); }\n#cs-root .cs-roles { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }\n#cs-root .cs-roles-label { margin-right: 4px; }\n#cs-root .cs-chip {\n display: inline-flex; align-items: center; gap: 2px; height: 24px; padding: 0 9px; border-radius: 999px;\n background: var(--cs-fill); font-size: 12px; font-weight: 500; color: var(--cs-text-2);\n}\n#cs-root button.cs-chip:hover { background: var(--cs-fill-2); }\n#cs-root .cs-chip.is-on, #cs-root button.cs-chip.is-on:hover { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-chip.is-static { padding-right: 3px; color: var(--cs-text); }\n#cs-root .cs-chip.is-static button {\n width: 18px; height: 18px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; color: var(--cs-text-3);\n}\n#cs-root .cs-chip.is-static button:hover { background: var(--cs-fill-2); color: var(--cs-text); }\n#cs-root .cs-chip.is-static .cs-icon { width: 11px; height: 11px; }\n#cs-root .cs-chips { display: flex; flex-wrap: wrap; gap: 4px; }\n#cs-root .cs-role {\n display: inline-flex; align-items: center; height: 18px; padding: 0 7px; border-radius: 999px;\n background: var(--cs-accent-soft); color: var(--cs-accent); font-size: 11px; font-weight: 600;\n}\n#cs-root .cs-detail-list { display: grid; gap: 6px; margin: 6px 0 0; }\n#cs-root .cs-detail-list > div { padding: 6px 8px; border-radius: 8px; background: var(--cs-fill); }\n#cs-root .cs-thread.is-open .cs-detail-list > div { background: var(--cs-card); }\n#cs-root .cs-detail-list dd { margin: 1px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }\n#cs-root .cs-detail-list.is-clamped dd { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n#cs-root .cs-details-edit { display: grid; gap: 8px; }\n#cs-root .cs-details-edit .cs-row-end { margin-top: 0; }\n#cs-root .cs-settings { width: 280px; }\n#cs-root .cs-settings-head { display: flex; align-items: center; gap: 4px; padding: 4px 4px 6px; }\n#cs-root .cs-settings-head h2 { font-size: 14px; font-weight: 600; }\n#cs-root .cs-settings-body { display: grid; gap: 6px; padding: 2px 8px 8px; }\n#cs-root .cs-field-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; min-height: 28px; padding-left: 2px; }\n#cs-root .cs-add-row { display: flex; align-items: center; gap: 4px; }\n#cs-root .cs-add-row input { padding: 5px 8px; }\n#cs-root .cs-settings .cs-hint { padding: 6px 8px 4px; }\n\n/* Attachments */\n#cs-root .cs-attach { display: inline-flex; gap: 0; flex: none; }\n#cs-root .cs-tray { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 12px 2px 46px; }\n#cs-root .cs-thread-more .cs-tray { padding: 0; }\n#cs-root .cs-pending {\n position: relative; display: inline-flex; align-items: center; gap: 6px; max-width: 170px; height: 34px;\n padding: 0 24px 0 4px; border-radius: 8px; background: var(--cs-fill); font-size: 11.5px; color: var(--cs-text-2);\n}\n#cs-root .cs-pending img { width: 26px; height: 26px; border-radius: 5px; object-fit: cover; flex: none; }\n#cs-root .cs-pending .cs-icon { margin-left: 4px; }\n#cs-root .cs-pending-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-pending.is-uploading { opacity: 0.6; }\n#cs-root .cs-pending.is-failed { box-shadow: inset 0 0 0 1px var(--cs-danger); }\n#cs-root .cs-pending-remove {\n position: absolute; right: 3px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; border-radius: 999px;\n display: inline-flex; align-items: center; justify-content: center; color: var(--cs-text-3);\n}\n#cs-root .cs-pending-remove:hover { background: var(--cs-fill-2); color: var(--cs-text); }\n#cs-root .cs-pending-remove .cs-icon { width: 11px; height: 11px; margin: 0; }\n#cs-root .cs-files { display: grid; gap: 6px; margin-top: 6px; }\n#cs-root .cs-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }\n#cs-root .cs-thumb { display: block; width: 112px; height: 72px; border-radius: 8px; overflow: hidden; box-shadow: 0 0 0 0.5px var(--cs-edge); background: var(--cs-fill); }\n#cs-root .cs-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }\n#cs-root .cs-file {\n display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 6px 10px; border-radius: 8px;\n background: var(--cs-fill); color: var(--cs-text); text-decoration: none; font-size: 12px; justify-self: start;\n}\n#cs-root .cs-file:hover { background: var(--cs-fill-2); }\n#cs-root .cs-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-file-size { color: var(--cs-text-3); flex: none; }\n\n/* Page overlays */\n#cs-root .cs-pin {\n position: absolute;\n transform: translate(-50%, -50%);\n padding: 2px;\n border-radius: 999px;\n background: var(--cs-card);\n box-shadow: 0 0 0 0.5px var(--cs-edge), 0 3px 10px rgba(0, 0, 0, 0.18);\n pointer-events: auto;\n transition: transform 0.15s ease;\n}\n#cs-root .cs-pin:hover { transform: translate(-50%, -50%) scale(1.08); }\n#cs-root .cs-pin.is-active { box-shadow: 0 0 0 2px var(--cs-accent), 0 3px 10px rgba(0, 0, 0, 0.18); }\n#cs-root .cs-pin.is-drifted { box-shadow: 0 0 0 1.5px var(--cs-warn), 0 3px 10px rgba(0, 0, 0, 0.18); }\n#cs-root .cs-pin-count {\n position: absolute; top: -5px; right: -6px; min-width: 15px; height: 15px; padding: 0 4px;\n border-radius: 999px; background: var(--cs-text); color: var(--cs-card);\n font-size: 9.5px; font-weight: 700; line-height: 15px; text-align: center;\n}\n#cs-root .cs-peek {\n position: absolute; width: 240px; padding: 10px 12px; border-radius: 12px;\n background: var(--cs-card); box-shadow: var(--cs-shadow); pointer-events: none;\n}\n#cs-root .cs-peek .cs-text { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }\n#cs-root .cs-outline {\n position: absolute; border-radius: 8px; pointer-events: none;\n box-shadow: 0 0 0 2px var(--cs-accent); background: var(--cs-accent-soft);\n}\n#cs-root .cs-outline.is-flash { animation: cs-flash 1.4s ease forwards; }\n@keyframes cs-flash { 0%, 60% { opacity: 1; } 100% { opacity: 0; } }\n#cs-root .cs-outline-label {\n position: absolute; max-width: 360px; padding: 3px 8px; border-radius: 6px; pointer-events: none;\n background: var(--cs-accent); color: #fff; font-size: 11.5px; font-weight: 500;\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n}\n#cs-root .cs-banner {\n position: absolute; top: 14px; left: 50%; transform: translateX(-50%);\n display: flex; align-items: center; gap: 8px; padding: 5px 5px 5px 12px; border-radius: 999px;\n background: var(--cs-glass); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);\n box-shadow: var(--cs-shadow); font-weight: 500; white-space: nowrap;\n}\n#cs-root .cs-banner button { padding: 3px 10px; border-radius: 999px; background: var(--cs-fill); font-size: 12px; }\n#cs-root .cs-banner button:hover { background: var(--cs-fill-2); }\n#cs-root .cs-toast {\n position: absolute; top: 14px; left: 50%; transform: translateX(-50%); padding: 6px 12px; border-radius: 999px;\n background: rgba(29, 29, 31, 0.9); color: #fff; font-size: 12px; font-weight: 500;\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); pointer-events: none; white-space: nowrap;\n}\n\n/* Docked inside an open <dialog> */\n#cs-root.cs-inside .cs-bar { bottom: 8px; }\n#cs-root.cs-inside.cs-at-left .cs-bar { left: 8px; }\n#cs-root.cs-inside.cs-at-right .cs-bar { right: 8px; }\n#cs-root.cs-inside .cs-sheet { top: 8px; right: 8px; bottom: auto; max-height: 46%; width: min(300px, calc(100% - 16px)); }\n#cs-root.cs-inside .cs-unlock, #cs-root.cs-inside .cs-menu { bottom: 52px; }\n#cs-root.cs-inside .cs-toast { top: 8px; }\n";
|
|
1
|
+
export declare const toolbarCss = "\n#cs-root {\n --cs-text: #1d1d1f;\n --cs-text-2: #6e6e73;\n --cs-text-3: #a1a1a6;\n --cs-glass: rgba(251, 251, 253, 0.8);\n --cs-card: rgba(255, 255, 255, 0.94);\n --cs-fill: rgba(0, 0, 0, 0.05);\n --cs-fill-2: rgba(0, 0, 0, 0.08);\n --cs-line: rgba(0, 0, 0, 0.08);\n --cs-edge: rgba(0, 0, 0, 0.1);\n --cs-accent: #007aff;\n --cs-accent-soft: rgba(0, 122, 255, 0.12);\n --cs-danger: #ff3b30;\n --cs-warn: #ff9500;\n --cs-shadow: 0 0 0 0.5px var(--cs-edge), 0 10px 30px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.06);\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n pointer-events: none;\n margin: 0;\n padding: 0;\n border: 0;\n background: transparent;\n color: var(--cs-text);\n font: 13px/1.4 -apple-system, BlinkMacSystemFont, \"SF Pro Text\", \"Helvetica Neue\", Inter, system-ui, sans-serif;\n letter-spacing: -0.005em;\n -webkit-font-smoothing: antialiased;\n text-align: left;\n}\n#cs-root.cs-dark {\n --cs-text: #f5f5f7;\n --cs-text-2: #a1a1a6;\n --cs-text-3: #6e6e73;\n --cs-glass: rgba(40, 40, 44, 0.78);\n --cs-card: rgba(36, 36, 40, 0.96);\n --cs-fill: rgba(255, 255, 255, 0.07);\n --cs-fill-2: rgba(255, 255, 255, 0.12);\n --cs-line: rgba(255, 255, 255, 0.08);\n --cs-edge: rgba(255, 255, 255, 0.12);\n --cs-accent: #0a84ff;\n --cs-accent-soft: rgba(10, 132, 255, 0.2);\n --cs-shadow: 0 0 0 0.5px var(--cs-edge), 0 10px 30px rgba(0, 0, 0, 0.45);\n}\n#cs-root.cs-inside { position: absolute; }\n#cs-root, #cs-root * { box-sizing: border-box; }\n#cs-root h2, #cs-root p { margin: 0; }\n#cs-root button, #cs-root input, #cs-root textarea {\n font: inherit; color: inherit; letter-spacing: inherit; margin: 0;\n}\n#cs-root button { background: none; border: 0; padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n#cs-root button:disabled { cursor: default; opacity: 0.45; }\n#cs-root button:focus-visible, #cs-root [role=button]:focus-visible { outline: 2px solid var(--cs-accent); outline-offset: 2px; }\n#cs-root .cs-hit { pointer-events: auto; }\n#cs-root .cs-icon { display: block; flex: none; }\n\n/* Bar */\n#cs-root .cs-bar {\n position: absolute;\n bottom: 16px;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px;\n border-radius: 999px;\n background: var(--cs-glass);\n -webkit-backdrop-filter: saturate(180%) blur(20px);\n backdrop-filter: saturate(180%) blur(20px);\n box-shadow: var(--cs-shadow);\n}\n#cs-root.cs-at-center .cs-bar { left: 50%; transform: translateX(-50%); }\n#cs-root.cs-at-left .cs-bar { left: 16px; }\n#cs-root.cs-at-right .cs-bar { right: 16px; }\n#cs-root .cs-tool {\n position: relative;\n width: 34px;\n height: 34px;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--cs-text);\n transition: background-color 0.15s ease, color 0.15s ease;\n}\n#cs-root .cs-tool:hover { background: var(--cs-fill); }\n#cs-root .cs-tool.is-on { background: var(--cs-fill-2); }\n#cs-root .cs-tool.is-accent { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-tool[data-tip]::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translate(-50%, 2px);\n white-space: pre;\n padding: 4px 8px;\n border-radius: 7px;\n background: rgba(29, 29, 31, 0.92);\n color: #fff;\n font-size: 11.5px;\n font-weight: 500;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.12s ease, transform 0.12s ease;\n}\n#cs-root .cs-tool[data-tip]:hover::after { opacity: 1; transform: translate(-50%, 0); transition-delay: 0.35s; }\n#cs-root .cs-me { width: 34px; }\n#cs-root .cs-divider { width: 1px; height: 18px; background: var(--cs-line); margin: 0 3px; }\n#cs-root .cs-badge {\n position: absolute;\n top: 3px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--cs-accent);\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n box-shadow: 0 0 0 2px var(--cs-glass);\n}\n#cs-root .cs-bar-lock {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n height: 34px;\n padding: 0 14px 0 12px;\n border-radius: 999px;\n font-weight: 500;\n}\n#cs-root .cs-bar-lock:hover { background: var(--cs-fill); }\n#cs-root .cs-avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n border-radius: 999px;\n color: #fff;\n font-weight: 600;\n letter-spacing: 0;\n line-height: 1;\n user-select: none;\n}\n\n/* Cards */\n#cs-root .cs-card {\n position: absolute;\n background: var(--cs-card);\n -webkit-backdrop-filter: saturate(180%) blur(24px);\n backdrop-filter: saturate(180%) blur(24px);\n border-radius: 14px;\n box-shadow: var(--cs-shadow);\n}\n#cs-root .cs-unlock, #cs-root .cs-menu { bottom: 64px; }\n#cs-root.cs-at-center .cs-unlock, #cs-root.cs-at-center .cs-menu { left: 50%; transform: translateX(-50%); }\n#cs-root.cs-at-left .cs-unlock, #cs-root.cs-at-left .cs-menu { left: 16px; }\n#cs-root.cs-at-right .cs-unlock, #cs-root.cs-at-right .cs-menu { right: 16px; }\n#cs-root .cs-unlock { width: 280px; padding: 20px; text-align: center; }\n#cs-root .cs-unlock-icon {\n width: 40px; height: 40px; margin: 0 auto 10px; border-radius: 12px;\n display: flex; align-items: center; justify-content: center; background: var(--cs-fill); color: var(--cs-text-2);\n}\n#cs-root .cs-unlock h2 { font-size: 15px; font-weight: 600; }\n#cs-root .cs-sub { color: var(--cs-text-2); margin-top: 4px; }\n#cs-root .cs-unlock form { margin-top: 14px; display: grid; gap: 8px; text-align: left; }\n#cs-root .cs-field { display: grid; gap: 4px; }\n#cs-root .cs-field span { font-size: 12px; color: var(--cs-text-2); padding-left: 2px; }\n#cs-root input, #cs-root textarea {\n width: 100%;\n border: 0;\n border-radius: 9px;\n background: var(--cs-fill);\n padding: 8px 10px;\n outline: none;\n transition: box-shadow 0.15s ease, background-color 0.15s ease;\n}\n#cs-root input:focus, #cs-root textarea:focus { background: transparent; box-shadow: 0 0 0 1px var(--cs-accent), 0 0 0 4px var(--cs-accent-soft); }\n#cs-root textarea { resize: none; }\n#cs-root .cs-error { color: var(--cs-danger); font-size: 12px; }\n#cs-root .cs-pad { padding: 6px 14px 0; }\n#cs-root .cs-hint { color: var(--cs-text-3); font-size: 11.5px; }\n\n/* Buttons */\n#cs-root .cs-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n height: 28px;\n padding: 0 11px;\n border-radius: 8px;\n background: var(--cs-fill);\n font-size: 12.5px;\n font-weight: 500;\n transition: background-color 0.15s ease;\n}\n#cs-root .cs-button:hover { background: var(--cs-fill-2); }\n#cs-root .cs-button.is-primary { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-button.is-primary:hover { filter: brightness(1.06); }\n#cs-root .cs-button.is-danger { background: var(--cs-danger); color: #fff; }\n#cs-root .cs-button.is-wide { width: 100%; height: 32px; margin-top: 4px; }\n#cs-root .cs-icon-button {\n width: 26px; height: 26px; border-radius: 999px; flex: none;\n display: inline-flex; align-items: center; justify-content: center; color: var(--cs-text-2);\n}\n#cs-root .cs-icon-button:hover { background: var(--cs-fill); color: var(--cs-text); }\n#cs-root .cs-send {\n width: 26px; height: 26px; border-radius: 999px; flex: none;\n display: inline-flex; align-items: center; justify-content: center; background: var(--cs-accent); color: #fff;\n}\n#cs-root .cs-send:disabled { background: var(--cs-fill-2); color: var(--cs-text-3); opacity: 1; }\n\n/* Menu */\n#cs-root .cs-menu { width: 264px; padding: 6px; }\n#cs-root .cs-me-row { display: flex; align-items: center; gap: 10px; padding: 8px 8px 10px; }\n#cs-root .cs-me-name { display: flex; align-items: center; gap: 4px; min-width: 0; }\n#cs-root .cs-me-name strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-rename { display: flex; align-items: center; gap: 4px; flex: 1; }\n#cs-root .cs-rename input { padding: 5px 8px; }\n#cs-root .cs-sep { height: 1px; background: var(--cs-line); margin: 4px 8px; }\n#cs-root .cs-item {\n display: flex; align-items: center; justify-content: space-between; gap: 10px;\n width: 100%; min-height: 32px; padding: 0 8px; border-radius: 8px; text-align: left;\n}\n#cs-root button.cs-item:hover { background: var(--cs-fill); }\n#cs-root .cs-item.is-danger { color: var(--cs-danger); }\n#cs-root .cs-switch { position: relative; width: 32px; height: 20px; border-radius: 999px; background: var(--cs-fill-2); transition: background-color 0.2s ease; flex: none; }\n#cs-root .cs-switch::after {\n content: \"\"; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 999px;\n background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); transition: transform 0.2s ease;\n}\n#cs-root .cs-switch.is-on { background: #34c759; }\n#cs-root .cs-switch.is-on::after { transform: translateX(12px); }\n#cs-root .cs-segment { display: inline-flex; padding: 2px; border-radius: 8px; background: var(--cs-fill); }\n#cs-root .cs-segment button { padding: 2px 8px; border-radius: 6px; font-size: 12px; color: var(--cs-text-2); }\n#cs-root .cs-segment button.is-on { background: var(--cs-card); color: var(--cs-text); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12); font-weight: 500; }\n#cs-root .cs-menu .cs-hint { padding: 6px 8px 4px; }\n#cs-root .cs-invite { padding: 2px 8px 6px; }\n#cs-root .cs-invite input { font: 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; padding: 6px 8px; }\n#cs-root .cs-invite .cs-hint { padding: 4px 0 0; }\n#cs-root .cs-confirm { padding: 10px; }\n#cs-root .cs-confirm h2 { font-size: 14px; font-weight: 600; }\n#cs-root .cs-row-end { display: flex; justify-content: flex-end; gap: 6px; margin-top: 12px; }\n\n/* Sheet */\n#cs-root .cs-sheet {\n top: 12px; right: 12px; max-height: calc(100% - 88px); width: min(360px, calc(100vw - 24px));\n display: flex; flex-direction: column; overflow: hidden;\n}\n#cs-root .cs-sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 10px 4px 16px; }\n#cs-root .cs-sheet-head .cs-push { margin-left: auto; }\n#cs-root .cs-sheet-head h2 { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }\n#cs-root .cs-tabs { display: flex; gap: 2px; margin: 4px 12px 6px; padding: 2px; border-radius: 9px; background: var(--cs-fill); }\n#cs-root .cs-tabs button {\n flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px;\n height: 26px; border-radius: 7px; font-size: 12px; font-weight: 500; color: var(--cs-text-2);\n}\n#cs-root .cs-tabs button.is-on { background: var(--cs-card); color: var(--cs-text); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12); }\n#cs-root .cs-count { font-size: 11px; color: var(--cs-text-3); font-variant-numeric: tabular-nums; }\n#cs-root .cs-list { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 2px 6px 8px; overscroll-behavior: contain; }\n#cs-root .cs-group { padding: 10px 10px 4px; font-size: 11px; font-weight: 600; color: var(--cs-text-3); text-transform: uppercase; letter-spacing: 0.04em; }\n#cs-root .cs-empty { padding: 36px 16px; text-align: center; color: var(--cs-text-2); display: grid; gap: 12px; justify-items: center; }\n#cs-root .cs-thread { border-radius: 10px; }\n#cs-root .cs-thread + .cs-thread { margin-top: 1px; }\n#cs-root .cs-thread.is-open { background: var(--cs-fill); }\n#cs-root .cs-thread-main { display: flex; gap: 10px; padding: 10px; border-radius: 10px; cursor: pointer; }\n#cs-root .cs-thread:not(.is-open) .cs-thread-main:hover { background: var(--cs-fill); }\n#cs-root .cs-thread-body { min-width: 0; flex: 1; }\n#cs-root .cs-meta { display: flex; align-items: center; gap: 6px; font-size: 12.5px; }\n#cs-root .cs-meta strong { font-weight: 600; }\n#cs-root .cs-meta time { color: var(--cs-text-3); font-size: 12px; }\n#cs-root .cs-text { margin-top: 2px; white-space: pre-wrap; overflow-wrap: anywhere; }\n#cs-root .cs-target { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 4px; font-size: 11.5px; color: var(--cs-text-3); }\n#cs-root .cs-note { display: inline-flex; align-items: center; gap: 5px; font-weight: 500; }\n#cs-root .cs-note::before { content: \"\"; width: 6px; height: 6px; border-radius: 999px; background: currentColor; }\n#cs-root .cs-note.is-quiet { color: var(--cs-text-2); }\n#cs-root .cs-note.is-warn { color: var(--cs-warn); }\n#cs-root .cs-note.is-bad { color: var(--cs-danger); }\n#cs-root .cs-replies { margin-top: 4px; font-size: 12px; color: var(--cs-accent); font-weight: 500; }\n#cs-root .cs-thread-more { padding: 0 10px 10px 44px; display: grid; gap: 10px; }\n#cs-root .cs-message { display: flex; gap: 8px; }\n#cs-root .cs-reply { display: flex; align-items: flex-end; gap: 6px; padding: 4px 4px 4px 0; border-radius: 10px; }\n#cs-root .cs-reply textarea { min-height: 32px; max-height: 120px; field-sizing: content; }\n#cs-root .cs-thread.is-open .cs-reply textarea { background: var(--cs-card); }\n#cs-root .cs-actions { display: flex; flex-wrap: wrap; gap: 6px; }\n#cs-root .cs-thread.is-open .cs-button { background: var(--cs-card); box-shadow: 0 0 0 0.5px var(--cs-edge); }\n#cs-root .cs-thread.is-open .cs-button:hover { background: var(--cs-fill-2); }\n\n/* Mentions */\n#cs-root .cs-mention { color: var(--cs-accent); background: var(--cs-accent-soft); border-radius: 4px; padding: 0 3px; font-weight: 500; }\n#cs-root .cs-delivery { margin-top: 4px; font-size: 11.5px; color: var(--cs-text-3); display: flex; align-items: center; gap: 5px; }\n#cs-root .cs-delivery::before { content: \"\"; width: 6px; height: 6px; border-radius: 999px; background: #34c759; }\n#cs-root .cs-people {\n position: fixed; z-index: 1; width: 264px; padding: 5px; border-radius: 12px;\n background: var(--cs-card); box-shadow: var(--cs-shadow); pointer-events: auto;\n}\n#cs-root .cs-person { display: flex; align-items: center; gap: 9px; padding: 6px 8px; border-radius: 8px; cursor: pointer; }\n#cs-root .cs-person.is-on { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-person-text { display: grid; line-height: 1.25; min-width: 0; }\n#cs-root .cs-person-text strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-person-text small { font-size: 11.5px; color: var(--cs-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-person.is-on small { color: rgba(255, 255, 255, 0.8); }\n#cs-root .cs-field small { font-size: 11.5px; color: var(--cs-text-3); padding-left: 2px; }\n#cs-root .cs-me-lines { display: grid; line-height: 1.25; min-width: 0; }\n#cs-root .cs-me-lines small { font-size: 11.5px; color: var(--cs-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n/* Composer */\n#cs-root .cs-composer { width: min(320px, calc(100% - 16px)); }\n#cs-root .cs-composer-target {\n display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 12px;\n border-bottom: 1px solid var(--cs-line); font-size: 12px; color: var(--cs-text-2);\n}\n#cs-root .cs-composer-name { font-weight: 500; color: var(--cs-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n#cs-root .cs-composer-target code {\n margin-left: auto; font: 11px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--cs-text-3);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; min-width: 0; max-width: 45%;\n}\n#cs-root .cs-composer-body { display: flex; gap: 10px; padding: 12px 12px 4px; }\n#cs-root .cs-composer-body textarea { background: transparent; padding: 3px 0; min-height: 56px; box-shadow: none; border-radius: 0; }\n#cs-root .cs-composer-foot { display: flex; align-items: center; gap: 6px; padding: 6px 8px 8px 40px; }\n#cs-root .cs-composer-foot .cs-hint { margin-left: auto; }\n\n/* Roles and fields */\n#cs-root .cs-details-input { display: grid; gap: 8px; padding: 2px 12px 6px 46px; }\n#cs-root .cs-details-edit .cs-details-input { padding: 0; }\n#cs-root .cs-detail-field { display: grid; gap: 3px; }\n#cs-root .cs-detail-field span, #cs-root .cs-roles-label, #cs-root .cs-detail-list dt {\n font-size: 11px; font-weight: 600; color: var(--cs-text-3); text-transform: uppercase; letter-spacing: 0.03em;\n}\n#cs-root .cs-detail-field textarea { padding: 6px 8px; min-height: 30px; max-height: 120px; field-sizing: content; }\n#cs-root .cs-thread.is-open .cs-detail-field textarea { background: var(--cs-card); }\n#cs-root .cs-roles { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }\n#cs-root .cs-roles-label { margin-right: 4px; }\n#cs-root .cs-chip {\n display: inline-flex; align-items: center; gap: 2px; height: 24px; padding: 0 9px; border-radius: 999px;\n background: var(--cs-fill); font-size: 12px; font-weight: 500; color: var(--cs-text-2);\n}\n#cs-root button.cs-chip:hover { background: var(--cs-fill-2); }\n#cs-root .cs-chip.is-on, #cs-root button.cs-chip.is-on:hover { background: var(--cs-accent); color: #fff; }\n#cs-root .cs-chip.is-static { padding-right: 3px; color: var(--cs-text); }\n#cs-root .cs-chip.is-static button {\n width: 18px; height: 18px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; color: var(--cs-text-3);\n}\n#cs-root .cs-chip.is-static button:hover { background: var(--cs-fill-2); color: var(--cs-text); }\n#cs-root .cs-chip.is-static .cs-icon { width: 11px; height: 11px; }\n#cs-root .cs-chips { display: flex; flex-wrap: wrap; gap: 4px; }\n#cs-root .cs-role {\n display: inline-flex; align-items: center; height: 18px; padding: 0 7px; border-radius: 999px;\n background: var(--cs-accent-soft); color: var(--cs-accent); font-size: 11px; font-weight: 600;\n}\n#cs-root .cs-detail-list { display: grid; gap: 6px; margin: 6px 0 0; }\n#cs-root .cs-detail-list > div { padding: 6px 8px; border-radius: 8px; background: var(--cs-fill); }\n#cs-root .cs-thread.is-open .cs-detail-list > div { background: var(--cs-card); }\n#cs-root .cs-detail-list dd { margin: 1px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }\n#cs-root .cs-detail-list.is-clamped dd { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n#cs-root .cs-details-edit { display: grid; gap: 8px; }\n#cs-root .cs-details-edit .cs-row-end { margin-top: 0; }\n#cs-root .cs-settings { width: 280px; }\n#cs-root .cs-settings-head { display: flex; align-items: center; gap: 4px; padding: 4px 4px 6px; }\n#cs-root .cs-settings-head h2 { font-size: 14px; font-weight: 600; }\n#cs-root .cs-settings-body { display: grid; gap: 6px; padding: 2px 8px 8px; }\n#cs-root .cs-field-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; min-height: 28px; padding-left: 2px; }\n#cs-root .cs-add-row { display: flex; align-items: center; gap: 4px; }\n#cs-root .cs-add-row input { padding: 5px 8px; }\n#cs-root .cs-settings .cs-hint { padding: 6px 8px 4px; }\n\n/* Table */\n#cs-root .cs-table-sheet {\n top: 12px; right: 12px; width: min(1100px, calc(100vw - 24px)); max-height: calc(100% - 88px);\n display: flex; flex-direction: column; overflow: hidden;\n}\n#cs-root .cs-table-sheet .cs-sheet-head { gap: 6px; }\n#cs-root .cs-table-sheet .cs-sheet-head h2 { margin-right: auto; }\n#cs-root .cs-table-search { width: 220px; padding: 5px 10px; }\n#cs-root .cs-table-sheet .cs-tabs { max-width: 420px; }\n#cs-root .cs-table-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; border-top: 1px solid var(--cs-line); overscroll-behavior: contain; }\n#cs-root .cs-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }\n#cs-root .cs-table th {\n position: sticky; top: 0; z-index: 1; background: var(--cs-card); text-align: left; font-weight: 600;\n font-size: 11px; color: var(--cs-text-3); text-transform: uppercase; letter-spacing: 0.03em;\n padding: 0; border-bottom: 1px solid var(--cs-line); white-space: nowrap;\n}\n#cs-root .cs-table th > button, #cs-root .cs-table th > span {\n display: inline-flex; align-items: center; gap: 4px; padding: 8px 10px; font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;\n}\n#cs-root .cs-table th > button:hover { color: var(--cs-text); }\n#cs-root .cs-sort { color: var(--cs-accent); }\n#cs-root .cs-table td { padding: 8px 10px; vertical-align: top; border-bottom: 1px solid var(--cs-line); max-width: 260px; }\n#cs-root .cs-table tbody tr { cursor: pointer; }\n#cs-root .cs-table tbody tr:hover { background: var(--cs-fill); }\n#cs-root .cs-table tbody tr.is-active { background: var(--cs-accent-soft); }\n#cs-root .cs-table tbody tr:focus-visible { outline: 2px solid var(--cs-accent); outline-offset: -2px; }\n#cs-root .cs-cell-comment { min-width: 220px; }\n#cs-root .cs-cell-comment small, #cs-root .cs-table td small { display: block; margin-top: 2px; font-size: 11.5px; color: var(--cs-text-3); }\n#cs-root .cs-cell-clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; white-space: pre-wrap; overflow-wrap: anywhere; }\n#cs-root .cs-cell-page { font: 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--cs-text-2); max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-cell-nowrap { white-space: nowrap; }\n#cs-root .cs-cell-num { text-align: right; font-variant-numeric: tabular-nums; color: var(--cs-text-2); }\n#cs-root .cs-state { display: inline-flex; align-items: center; gap: 5px; font-weight: 500; }\n#cs-root .cs-state::before { content: \"\"; width: 6px; height: 6px; border-radius: 999px; background: #34c759; }\n#cs-root .cs-state.is-done { color: var(--cs-text-3); }\n#cs-root .cs-state.is-done::before { background: var(--cs-text-3); }\n#cs-root .cs-table .cs-note { display: flex; margin-top: 2px; font-size: 11px; }\n\n/* Attachments */\n#cs-root .cs-attach { display: inline-flex; gap: 0; flex: none; }\n#cs-root .cs-tray { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 12px 2px 46px; }\n#cs-root .cs-thread-more .cs-tray { padding: 0; }\n#cs-root .cs-pending {\n position: relative; display: inline-flex; align-items: center; gap: 6px; max-width: 170px; height: 34px;\n padding: 0 24px 0 4px; border-radius: 8px; background: var(--cs-fill); font-size: 11.5px; color: var(--cs-text-2);\n}\n#cs-root .cs-pending img { width: 26px; height: 26px; border-radius: 5px; object-fit: cover; flex: none; }\n#cs-root .cs-pending .cs-icon { margin-left: 4px; }\n#cs-root .cs-pending-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-pending.is-uploading { opacity: 0.6; }\n#cs-root .cs-pending.is-failed { box-shadow: inset 0 0 0 1px var(--cs-danger); }\n#cs-root .cs-pending-remove {\n position: absolute; right: 3px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; border-radius: 999px;\n display: inline-flex; align-items: center; justify-content: center; color: var(--cs-text-3);\n}\n#cs-root .cs-pending-remove:hover { background: var(--cs-fill-2); color: var(--cs-text); }\n#cs-root .cs-pending-remove .cs-icon { width: 11px; height: 11px; margin: 0; }\n#cs-root .cs-files { display: grid; gap: 6px; margin-top: 6px; }\n#cs-root .cs-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }\n#cs-root .cs-thumb { display: block; width: 112px; height: 72px; border-radius: 8px; overflow: hidden; box-shadow: 0 0 0 0.5px var(--cs-edge); background: var(--cs-fill); }\n#cs-root .cs-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }\n#cs-root .cs-file {\n display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 6px 10px; border-radius: 8px;\n background: var(--cs-fill); color: var(--cs-text); text-decoration: none; font-size: 12px; justify-self: start;\n}\n#cs-root .cs-file:hover { background: var(--cs-fill-2); }\n#cs-root .cs-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n#cs-root .cs-file-size { color: var(--cs-text-3); flex: none; }\n\n/* Page overlays */\n#cs-root .cs-pin {\n position: absolute;\n transform: translate(-50%, -50%);\n padding: 2px;\n border-radius: 999px;\n background: var(--cs-card);\n box-shadow: 0 0 0 0.5px var(--cs-edge), 0 3px 10px rgba(0, 0, 0, 0.18);\n pointer-events: auto;\n transition: transform 0.15s ease;\n}\n#cs-root .cs-pin:hover { transform: translate(-50%, -50%) scale(1.08); }\n#cs-root .cs-pin.is-active { box-shadow: 0 0 0 2px var(--cs-accent), 0 3px 10px rgba(0, 0, 0, 0.18); }\n#cs-root .cs-pin.is-drifted { box-shadow: 0 0 0 1.5px var(--cs-warn), 0 3px 10px rgba(0, 0, 0, 0.18); }\n#cs-root .cs-pin-count {\n position: absolute; top: -5px; right: -6px; min-width: 15px; height: 15px; padding: 0 4px;\n border-radius: 999px; background: var(--cs-text); color: var(--cs-card);\n font-size: 9.5px; font-weight: 700; line-height: 15px; text-align: center;\n}\n#cs-root .cs-peek {\n position: absolute; width: 240px; padding: 10px 12px; border-radius: 12px;\n background: var(--cs-card); box-shadow: var(--cs-shadow); pointer-events: none;\n}\n#cs-root .cs-peek .cs-text { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }\n#cs-root .cs-outline {\n position: absolute; border-radius: 8px; pointer-events: none;\n box-shadow: 0 0 0 2px var(--cs-accent); background: var(--cs-accent-soft);\n}\n#cs-root .cs-outline.is-flash { animation: cs-flash 1.4s ease forwards; }\n@keyframes cs-flash { 0%, 60% { opacity: 1; } 100% { opacity: 0; } }\n#cs-root .cs-outline-label {\n position: absolute; max-width: 360px; padding: 3px 8px; border-radius: 6px; pointer-events: none;\n background: var(--cs-accent); color: #fff; font-size: 11.5px; font-weight: 500;\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n}\n#cs-root .cs-banner {\n position: absolute; top: 14px; left: 50%; transform: translateX(-50%);\n display: flex; align-items: center; gap: 8px; padding: 5px 5px 5px 12px; border-radius: 999px;\n background: var(--cs-glass); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);\n box-shadow: var(--cs-shadow); font-weight: 500; white-space: nowrap;\n}\n#cs-root .cs-banner button { padding: 3px 10px; border-radius: 999px; background: var(--cs-fill); font-size: 12px; }\n#cs-root .cs-banner button:hover { background: var(--cs-fill-2); }\n#cs-root .cs-toast {\n position: absolute; top: 14px; left: 50%; transform: translateX(-50%); padding: 6px 12px; border-radius: 999px;\n background: rgba(29, 29, 31, 0.9); color: #fff; font-size: 12px; font-weight: 500;\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); pointer-events: none; white-space: nowrap;\n}\n\n/* Docked inside an open <dialog> */\n#cs-root.cs-inside .cs-bar { bottom: 8px; }\n#cs-root.cs-inside.cs-at-left .cs-bar { left: 8px; }\n#cs-root.cs-inside.cs-at-right .cs-bar { right: 8px; }\n#cs-root.cs-inside .cs-sheet { top: 8px; right: 8px; bottom: auto; max-height: 46%; width: min(300px, calc(100% - 16px)); }\n#cs-root.cs-inside .cs-unlock, #cs-root.cs-inside .cs-menu { bottom: 52px; }\n#cs-root.cs-inside .cs-toast { top: 8px; }\n";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Thread } from "./client.js";
|
|
3
|
+
import { type PlacedStatus } from "./format.js";
|
|
4
|
+
export type TableRow = {
|
|
5
|
+
thread: Thread;
|
|
6
|
+
status: PlacedStatus;
|
|
7
|
+
};
|
|
8
|
+
export declare function CommentTable({ rows, route, activeId, tabs, onSelect, onList, onClose, }: {
|
|
9
|
+
rows: TableRow[];
|
|
10
|
+
route: string;
|
|
11
|
+
activeId: string | null;
|
|
12
|
+
tabs: ReactNode;
|
|
13
|
+
onSelect: (row: TableRow) => void;
|
|
14
|
+
onList: () => void;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
}): import("react").JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devaccel-labs/comment-service",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "In-UI component comments for TanStack Start on Cloudflare. Anchors survive redeploys.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"esbuild": "^0.28.1",
|
|
46
46
|
"@devaccel/comment-core": "0.1.0",
|
|
47
|
-
"@devaccel/comment-react": "0.1.0",
|
|
48
47
|
"@devaccel/comment-compiler": "0.1.0",
|
|
49
|
-
"@devaccel/comment-
|
|
50
|
-
"@devaccel/comment-server": "0.1.0"
|
|
48
|
+
"@devaccel/comment-react": "0.1.0",
|
|
49
|
+
"@devaccel/comment-server": "0.1.0",
|
|
50
|
+
"@devaccel/comment-start": "0.1.0"
|
|
51
51
|
},
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"registry": "https://registry.npmjs.org/",
|