reflet-sdk 0.7.3 → 0.7.5
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/CHANGELOG.md +28 -0
- package/README.md +54 -17
- package/dist/desktop.d.ts +24 -0
- package/dist/desktop.d.ts.map +1 -0
- package/dist/desktop.js +118 -0
- package/dist/desktop.js.map +1 -0
- package/dist/{devtools-layer-CsIcpepI.js → devtools-layer-o1O55wu1.js} +396 -277
- package/dist/devtools-layer-o1O55wu1.js.map +1 -0
- package/dist/devtools-next.d.ts.map +1 -1
- package/dist/devtools-next.js +1 -1
- package/dist/{sessions-panel-BYM0UUgT.js → devtools-styles-TWR5Ps34.js} +2078 -1686
- package/dist/devtools-styles-TWR5Ps34.js.map +1 -0
- package/dist/devtools-vite.js +2 -1
- package/dist/devtools-vite.js.map +1 -1
- package/dist/feedback.d.ts +7 -3
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +21 -12
- package/dist/feedback.js.map +1 -1
- package/dist/{handler-17FmwoSX.js → handler-ndF3gZBx.js} +11 -416
- package/dist/handler-ndF3gZBx.js.map +1 -0
- package/dist/reflet-proxy-BW6q9xds.js +467 -0
- package/dist/reflet-proxy-BW6q9xds.js.map +1 -0
- package/dist/{submit-Dl0rm6TV.js → submit-DJIKxRUp.js} +2 -2
- package/dist/submit-DJIKxRUp.js.map +1 -0
- package/dist/{team-layer-Dvjkh-_y.js → team-layer-_It1_oSo.js} +159 -95
- package/dist/team-layer-_It1_oSo.js.map +1 -0
- package/dist/team-tools-bridge-C51PpkUI.d.ts +31 -0
- package/dist/team-tools-bridge-C51PpkUI.d.ts.map +1 -0
- package/package.json +5 -1
- package/dist/devtools-layer-CsIcpepI.js.map +0 -1
- package/dist/handler-17FmwoSX.js.map +0 -1
- package/dist/sessions-panel-BYM0UUgT.js.map +0 -1
- package/dist/submit-Dl0rm6TV.js.map +0 -1
- package/dist/team-layer-Dvjkh-_y.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as EDITORS, n as DEVTOOLS_REQUEST_HEADER, r as DEVTOOLS_ROUTE_BASE, t as DEVTOOLS_ENDPOINTS } from "./protocol-cJVVwnPe.js";
|
|
2
|
-
import { B as clip, D as MoreIcon, G as describeElement, K as getElementRect, M as TargetIcon, O as PencilIcon, R as DEFAULT_WIDGET_LABELS, S as CheckIcon, T as GripIcon, W as buildSelector, Y as redactUrl, Z as inspectReactElement, _ as matchesHotkey, a as uploadBlob, c as useFloatingPosition, g as isSubmitEnter, it as releaseCapture, j as Svg, l as onViewportChange, m as startsInWidget, o as ElementPicker, p as listenToKeydown, q as REDACT_ATTRIBUTE, s as isWidgetOwned, tt as captureViewport, u as visibleViewport, w as CloseIcon } from "./submit-
|
|
2
|
+
import { B as clip, D as MoreIcon, G as describeElement, K as getElementRect, M as TargetIcon, O as PencilIcon, R as DEFAULT_WIDGET_LABELS, S as CheckIcon, T as GripIcon, W as buildSelector, Y as redactUrl, Z as inspectReactElement, _ as matchesHotkey, a as uploadBlob, c as useFloatingPosition, g as isSubmitEnter, it as releaseCapture, j as Svg, l as onViewportChange, m as startsInWidget, o as ElementPicker, p as listenToKeydown, q as REDACT_ATTRIBUTE, s as isWidgetOwned, tt as captureViewport, u as visibleViewport, w as CloseIcon } from "./submit-DJIKxRUp.js";
|
|
3
3
|
import { t as REFLET_Z_INDEX } from "./z-index-CwokqVq_.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { createContext, useContext, useEffect, useId, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
@@ -274,6 +274,8 @@ const sessionIdentitySchema = z.object({
|
|
|
274
274
|
user: z.object({
|
|
275
275
|
email: z.string().nullable(),
|
|
276
276
|
id: z.string(),
|
|
277
|
+
/** Absent from older Reflet backends. */
|
|
278
|
+
image: z.string().nullable().optional(),
|
|
277
279
|
name: z.string().nullable()
|
|
278
280
|
})
|
|
279
281
|
});
|
|
@@ -1068,6 +1070,27 @@ function teamTransport(options) {
|
|
|
1068
1070
|
return schema.parse(await response.json().catch(() => null));
|
|
1069
1071
|
} };
|
|
1070
1072
|
}
|
|
1073
|
+
function parseReplyBody(body) {
|
|
1074
|
+
try {
|
|
1075
|
+
return JSON.parse(body);
|
|
1076
|
+
} catch {
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
/** Calls go through the desktop app's privileged process, which holds the credential. Absent keys stay absent: IPC keeps an `undefined` value. */
|
|
1081
|
+
function bridgeTransport(bridge) {
|
|
1082
|
+
return { async request({ body, method, path, query, schema }) {
|
|
1083
|
+
const reply = await bridge.request({
|
|
1084
|
+
method,
|
|
1085
|
+
path,
|
|
1086
|
+
...method === "POST" && { body: JSON.stringify(body ?? {}) },
|
|
1087
|
+
...query && { query }
|
|
1088
|
+
});
|
|
1089
|
+
const payload = parseReplyBody(reply.body);
|
|
1090
|
+
if (!(reply.status >= 200 && reply.status < 300)) throw toSessionApiError(payload, reply.status);
|
|
1091
|
+
return schema.parse(payload);
|
|
1092
|
+
} };
|
|
1093
|
+
}
|
|
1071
1094
|
function uploadSessionBlob(uploadUrl, blob) {
|
|
1072
1095
|
return uploadBlob(uploadUrl, {
|
|
1073
1096
|
blob,
|
|
@@ -3285,11 +3308,25 @@ function preciseSeconds(ms) {
|
|
|
3285
3308
|
function minutesLeft(remainingMs) {
|
|
3286
3309
|
return Math.max(1, Math.ceil(remainingMs / MINUTE_MS));
|
|
3287
3310
|
}
|
|
3288
|
-
function
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3311
|
+
function startOfDay(epochMs, daysBack) {
|
|
3312
|
+
const day = new Date(epochMs);
|
|
3313
|
+
day.setHours(0, 0, 0, 0);
|
|
3314
|
+
day.setDate(day.getDate() - daysBack);
|
|
3315
|
+
return day.getTime();
|
|
3316
|
+
}
|
|
3317
|
+
function dayLabel(epochMs, now) {
|
|
3318
|
+
if (epochMs >= startOfDay(now, 0)) return "Today";
|
|
3319
|
+
if (epochMs >= startOfDay(now, 1)) return "Yesterday";
|
|
3320
|
+
const date = new Date(epochMs);
|
|
3321
|
+
const isThisYear = date.getFullYear() === new Date(now).getFullYear();
|
|
3322
|
+
return date.toLocaleDateString(void 0, isThisYear ? {
|
|
3323
|
+
day: "numeric",
|
|
3324
|
+
month: "short"
|
|
3325
|
+
} : { dateStyle: "medium" });
|
|
3326
|
+
}
|
|
3327
|
+
function formatDate(epochMs, now = Date.now()) {
|
|
3328
|
+
const time = new Date(epochMs).toLocaleTimeString(void 0, { timeStyle: "short" });
|
|
3329
|
+
return `${dayLabel(epochMs, now)}, ${time}`;
|
|
3293
3330
|
}
|
|
3294
3331
|
function isAnalysisBusy(summary) {
|
|
3295
3332
|
return summary.analysis.state === "waiting" || summary.analysis.state === "running";
|
|
@@ -3333,13 +3370,6 @@ function PauseIcon() {
|
|
|
3333
3370
|
function PlayIcon() {
|
|
3334
3371
|
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m8 5 11 7-11 7z" }) });
|
|
3335
3372
|
}
|
|
3336
|
-
function PersonIcon() {
|
|
3337
|
-
return /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("circle", {
|
|
3338
|
-
cx: "12",
|
|
3339
|
-
cy: "8",
|
|
3340
|
-
r: "4"
|
|
3341
|
-
}), /* @__PURE__ */ jsx("path", { d: "M4.5 20a7.5 7.5 0 0 1 15 0" })] });
|
|
3342
|
-
}
|
|
3343
3373
|
function ClockIcon() {
|
|
3344
3374
|
return /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("circle", {
|
|
3345
3375
|
cx: "12",
|
|
@@ -3347,6 +3377,29 @@ function ClockIcon() {
|
|
|
3347
3377
|
r: "8.5"
|
|
3348
3378
|
}), /* @__PURE__ */ jsx("path", { d: "M12 7.5V12l3 2" })] });
|
|
3349
3379
|
}
|
|
3380
|
+
function IntentionIcon() {
|
|
3381
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "M9 18h6M10 21h4M12 3a6 6 0 0 0-3.6 10.8c.6.5 1.1 1.3 1.1 2.2h5c0-.9.5-1.7 1.1-2.2A6 6 0 0 0 12 3z" }) });
|
|
3382
|
+
}
|
|
3383
|
+
function TranscriptIcon() {
|
|
3384
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 11h16M4 16h10" }) });
|
|
3385
|
+
}
|
|
3386
|
+
function ImageIcon() {
|
|
3387
|
+
return /* @__PURE__ */ jsxs(Svg, { children: [
|
|
3388
|
+
/* @__PURE__ */ jsx("rect", {
|
|
3389
|
+
height: "16",
|
|
3390
|
+
rx: "2.5",
|
|
3391
|
+
width: "18",
|
|
3392
|
+
x: "3",
|
|
3393
|
+
y: "4"
|
|
3394
|
+
}),
|
|
3395
|
+
/* @__PURE__ */ jsx("circle", {
|
|
3396
|
+
cx: "9",
|
|
3397
|
+
cy: "10",
|
|
3398
|
+
r: "1.6"
|
|
3399
|
+
}),
|
|
3400
|
+
/* @__PURE__ */ jsx("path", { d: "m21 16-5-5-9 9" })
|
|
3401
|
+
] });
|
|
3402
|
+
}
|
|
3350
3403
|
//#endregion
|
|
3351
3404
|
//#region src/sessions/ui/recording/level-meter.tsx
|
|
3352
3405
|
const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
@@ -3604,179 +3657,6 @@ function RecordingLayer({ onFinished }) {
|
|
|
3604
3657
|
})] });
|
|
3605
3658
|
}
|
|
3606
3659
|
//#endregion
|
|
3607
|
-
//#region src/sessions/ui/intention-styles.ts
|
|
3608
|
-
const INTENTION_STYLES = `
|
|
3609
|
-
.dt-ses-panel { display: contents; }
|
|
3610
|
-
.dt-ses-panel[hidden] { display: none; }
|
|
3611
|
-
.dt-ses-moment, .dt-ses-moment-section, .dt-ses-block, .dt-ses-change, .dt-ses-history { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
3612
|
-
.dt-ses-moment-item { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; border-radius: 10px; background: var(--rf-bg-subtle); }
|
|
3613
|
-
.dt-ses-moment-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; overflow-wrap: anywhere; }
|
|
3614
|
-
.dt-ses-moment-quote { display: flex; flex-direction: column; gap: 2px; margin: 0; padding-left: 10px; border-left: 2px solid var(--rf-border); overflow-wrap: anywhere; }
|
|
3615
|
-
.dt-ses-moment-notices { color: var(--rf-text-muted); font-size: 12px; }
|
|
3616
|
-
.dt-ses-moment-shot { display: flex; flex-direction: column; gap: 4px; margin: 0; max-width: 100%; }
|
|
3617
|
-
.dt-ses-shot-mark[data-match="approximate"] { border-style: dashed; }
|
|
3618
|
-
.dt-ses-shot-pointer {
|
|
3619
|
-
position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
|
|
3620
|
-
background: var(--rf-accent); box-shadow: 0 0 0 2px var(--rf-bg); pointer-events: none;
|
|
3621
|
-
}
|
|
3622
|
-
.dt-ses-source { margin: 0; font-size: 12px; overflow-wrap: anywhere; }
|
|
3623
|
-
.dt-ses-context-line { display: block; }
|
|
3624
|
-
.dt-ses-attached { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px; }
|
|
3625
|
-
.dt-ses-attached p { margin: 0; }
|
|
3626
|
-
.dt-ses-history[data-removed="true"] > .dt-ses-subhead { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
3627
|
-
.dt-ses-change { padding: 8px 10px; border-radius: 10px; background: var(--rf-bg-subtle); list-style: none; }
|
|
3628
|
-
.dt-ses-change[data-decision="rejected"] .dt-ses-diff { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
3629
|
-
.dt-ses-diff { display: grid; grid-template-columns: auto 1fr; gap: 2px 8px; margin: 0; overflow-wrap: anywhere; }
|
|
3630
|
-
p.dt-ses-diff { display: block; }
|
|
3631
|
-
.dt-ses-diff dd { margin: 0; }
|
|
3632
|
-
.dt-card:focus-visible { outline: 2px solid var(--rf-accent); outline-offset: 2px; }
|
|
3633
|
-
`;
|
|
3634
|
-
//#endregion
|
|
3635
|
-
//#region src/sessions/ui/review/screens/report-styles.ts
|
|
3636
|
-
const REPORT_STYLES = `
|
|
3637
|
-
.dt-ses-report { display: flex; flex-direction: column; gap: 4px; width: 100%; min-width: 0; margin: 0; }
|
|
3638
|
-
.dt-ses-report-canvas { position: relative; width: 100%; }
|
|
3639
|
-
.dt-ses-report-canvas img { display: block; width: 100%; max-width: 100%; height: auto; border-radius: 8px; box-shadow: var(--rf-shadow-inset); }
|
|
3640
|
-
.dt-ses-report-canvas[data-measured="false"] .dt-ses-callout { visibility: hidden; }
|
|
3641
|
-
.dt-ses-report-mark { --dt-mark: var(--rf-accent); position: absolute; border: 2px solid var(--dt-mark); border-radius: 4px; pointer-events: none; }
|
|
3642
|
-
.dt-ses-report-lines { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
|
|
3643
|
-
.dt-ses-report-lines g { color: var(--rf-accent); }
|
|
3644
|
-
.dt-ses-report-lines line { stroke: currentColor; stroke-width: 1.5; }
|
|
3645
|
-
.dt-ses-report-lines circle { fill: currentColor; }
|
|
3646
|
-
.dt-ses-report-mark[data-decision="kept"], .dt-ses-report-lines g[data-decision="kept"] { --dt-mark: var(--rf-success); color: var(--rf-success); }
|
|
3647
|
-
.dt-ses-report-mark[data-decision="dismissed"], .dt-ses-report-lines g[data-decision="dismissed"] { opacity: .35; }
|
|
3648
|
-
.dt-ses-callouts { margin: 0; padding: 0; list-style: none; }
|
|
3649
|
-
.dt-ses-callouts[data-flow="list"] { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
|
|
3650
|
-
.dt-ses-callout {
|
|
3651
|
-
display: flex; align-items: center; gap: 4px; max-width: 100%; padding: 3px; border-radius: var(--rf-pill);
|
|
3652
|
-
background: var(--rf-bg); box-shadow: var(--rf-shadow-inset), var(--rf-shadow-low); font-size: 12px; line-height: 1.3;
|
|
3653
|
-
}
|
|
3654
|
-
.dt-ses-report-canvas .dt-ses-callout { position: absolute; top: 0; left: 0; width: max-content; max-width: min(280px, 100%); }
|
|
3655
|
-
.dt-ses-callout-number {
|
|
3656
|
-
display: grid; place-items: center; flex: none; min-width: 20px; height: 20px; padding: 0 5px; border-radius: var(--rf-pill);
|
|
3657
|
-
background: var(--rf-accent); color: var(--rf-accent-text, #fff); font-size: 11px; font-weight: 650; font-variant-numeric: tabular-nums;
|
|
3658
|
-
}
|
|
3659
|
-
.dt-ses-callout[data-decision="kept"] .dt-ses-callout-number { background: var(--rf-success); }
|
|
3660
|
-
.dt-ses-callout[data-decision="dismissed"] .dt-ses-callout-number { background: var(--rf-text-muted); }
|
|
3661
|
-
.dt-ses-callout-label { min-width: 0; padding: 0 4px; font-weight: 550; text-align: left; overflow-wrap: anywhere; }
|
|
3662
|
-
.dt-ses-callout-label:hover { color: var(--rf-accent); }
|
|
3663
|
-
.dt-ses-callout[data-decision="dismissed"] .dt-ses-callout-label { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
3664
|
-
.dt-ses-callout-btn {
|
|
3665
|
-
display: grid; place-items: center; flex: none; width: 22px; height: 22px; border-radius: 50%; color: var(--rf-text-muted);
|
|
3666
|
-
transition: background-color 120ms var(--rf-ease), color 120ms var(--rf-ease);
|
|
3667
|
-
}
|
|
3668
|
-
.dt-ses-callout-btn svg { width: 13px; height: 13px; }
|
|
3669
|
-
.dt-ses-callout-btn:hover { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
3670
|
-
.dt-ses-callout-btn[data-decision="kept"][aria-pressed="true"] { background: var(--rf-success); color: #fff; }
|
|
3671
|
-
.dt-ses-callout-btn[data-decision="dismissed"][aria-pressed="true"] { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
3672
|
-
`;
|
|
3673
|
-
//#endregion
|
|
3674
|
-
//#region src/sessions/ui/sessions-styles.ts
|
|
3675
|
-
const MONO_FONT$1 = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
3676
|
-
const SESSIONS_STYLES = `${`
|
|
3677
|
-
.dt-rec {
|
|
3678
|
-
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; left: 50%; translate: -50% 0;
|
|
3679
|
-
bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + 16px);
|
|
3680
|
-
display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px;
|
|
3681
|
-
max-width: calc(100vw - 24px); padding: 6px 6px 6px 12px; border-radius: 18px;
|
|
3682
|
-
animation: dt-rec-in 240ms var(--rf-ease);
|
|
3683
|
-
}
|
|
3684
|
-
@keyframes dt-rec-in { from { transform: translateY(8px); opacity: 0; } }
|
|
3685
|
-
.dt-rec-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--rf-danger); }
|
|
3686
|
-
.dt-rec[data-phase="recording"] .dt-rec-dot { animation: dt-rec-pulse 1.6s ease-in-out infinite; }
|
|
3687
|
-
.dt-rec[data-phase="paused"] .dt-rec-dot, .dt-rec[data-phase="finishing"] .dt-rec-dot { background: var(--rf-text-muted); }
|
|
3688
|
-
@keyframes dt-rec-pulse { 50% { opacity: .35; } }
|
|
3689
|
-
.dt-rec-meter { display: inline-flex; align-items: center; gap: 2px; height: 16px; }
|
|
3690
|
-
.dt-rec-meter span {
|
|
3691
|
-
width: 3px; height: 100%; border-radius: 2px; background: var(--rf-text-muted);
|
|
3692
|
-
scale: 1 calc(.2 + var(--dt-level, 0) * .8); transition: scale 90ms linear;
|
|
3693
|
-
}
|
|
3694
|
-
.dt-rec-meter span:nth-child(2) { scale: 1 calc(.2 + var(--dt-level, 0)); }
|
|
3695
|
-
.dt-rec-time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 5ch; }
|
|
3696
|
-
.dt-rec-status { color: var(--rf-text-muted); font-size: 12px; overflow-wrap: anywhere; }
|
|
3697
|
-
.dt-rec-status:empty { display: none; }
|
|
3698
|
-
.dt-rec-note { display: flex; align-items: center; gap: 6px; flex: 1 1 100%; font-size: 12px; color: var(--rf-text-muted); }
|
|
3699
|
-
.dt-rec-note .dt-field { flex: 1; min-width: 0; padding: 4px 8px; }
|
|
3700
|
-
`}
|
|
3701
|
-
.dt-ses-subhead, .dt-ses-label { margin: 0 0 4px; font-size: 12px; font-weight: 600; color: var(--rf-text); }
|
|
3702
|
-
.dt-ses-label { font-size: 11px; color: var(--rf-text-muted); }
|
|
3703
|
-
.dt-ses-list { margin: 0; padding-left: 18px; overflow-wrap: anywhere; }
|
|
3704
|
-
.dt-ses-list li + li { margin-top: 3px; }
|
|
3705
|
-
.dt-ses-link { align-self: flex-start; padding: 0; color: var(--rf-accent); font-size: 12px; text-align: left; }
|
|
3706
|
-
.dt-ses-link:hover { text-decoration: underline; }
|
|
3707
|
-
.dt-ses-problem, .dt-ses-banner, .dt-ses-form, .dt-ses-head, .dt-ses-strip, .dt-ses-handoff { display: flex; flex-direction: column; gap: 6px; }
|
|
3708
|
-
.dt-ses-banner { padding: 8px 10px; border-radius: 10px; background: color-mix(in srgb, var(--rf-accent) 10%, transparent); }
|
|
3709
|
-
.dt-ses-banner p { margin: 0; overflow-wrap: anywhere; }
|
|
3710
|
-
.dt-ses-strip:empty { display: none; }
|
|
3711
|
-
.dt-ses-rows { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; list-style: none; }
|
|
3712
|
-
.dt-ses-row {
|
|
3713
|
-
display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
|
|
3714
|
-
padding: 8px 10px; border-radius: 10px; background: var(--rf-bg-subtle); text-align: left;
|
|
3715
|
-
}
|
|
3716
|
-
button.dt-ses-row:hover { background: var(--rf-bg-hover); }
|
|
3717
|
-
.dt-ses-row .dt-card-title { max-width: 100%; }
|
|
3718
|
-
${`
|
|
3719
|
-
.dt-ses-title { flex: 1; min-width: 0; margin: 0; font-size: 15px; font-weight: 650; overflow-wrap: anywhere; }
|
|
3720
|
-
.dt-ses-menu { position: relative; flex: none; }
|
|
3721
|
-
.dt-ses-menu > .icon-btn { width: 30px; height: 30px; }
|
|
3722
|
-
.dt-ses-menu-list {
|
|
3723
|
-
position: absolute; top: calc(100% + 4px); right: 0; z-index: 2; display: flex; flex-direction: column; min-width: 168px; padding: 4px;
|
|
3724
|
-
border: 1px solid var(--rf-border); border-radius: var(--rf-radius-sm); background: var(--rf-bg); box-shadow: var(--rf-shadow);
|
|
3725
|
-
}
|
|
3726
|
-
.dt-ses-menu-item { display: flex; align-items: center; height: 30px; padding: 0 10px; border-radius: 6px; color: var(--rf-text); font-size: 12.5px; text-align: left; }
|
|
3727
|
-
.dt-ses-menu-item:hover, .dt-ses-menu-item:focus-visible { background: var(--rf-bg-hover); }
|
|
3728
|
-
.dt-ses-menu-item[data-variant="danger"] { color: var(--rf-danger); }
|
|
3729
|
-
.dt-btn[data-icon-only] { justify-content: center; width: 28px; padding: 0; }
|
|
3730
|
-
.dt-ses-tabs { flex-wrap: wrap; margin: 0; }
|
|
3731
|
-
.dt-ses-field { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; color: var(--rf-text-muted); }
|
|
3732
|
-
.dt-ses-need {
|
|
3733
|
-
margin: 0; font-weight: 600; overflow-wrap: anywhere;
|
|
3734
|
-
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
|
|
3735
|
-
}
|
|
3736
|
-
.dt-ses-need[data-expanded="true"] { display: block; }
|
|
3737
|
-
.dt-card[data-decision="dismissed"] .dt-ses-need { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
3738
|
-
.dt-ses-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
3739
|
-
.dt-ses-chips:empty { display: none; }
|
|
3740
|
-
.dt-ses-details { display: flex; flex-direction: column; gap: 8px; }
|
|
3741
|
-
.dt-ses-details[hidden] { display: none; }
|
|
3742
|
-
.dt-ses-details section { display: flex; flex-direction: column; gap: 2px; }
|
|
3743
|
-
.dt-ses-quote { padding: 2px 0; font-size: 12px; text-align: left; overflow-wrap: anywhere; }
|
|
3744
|
-
.dt-ses-quote:hover { color: var(--rf-accent); }
|
|
3745
|
-
.dt-ses-time { flex: none; color: var(--rf-text-muted); font: 11.5px ${MONO_FONT$1}; font-variant-numeric: tabular-nums; }
|
|
3746
|
-
.dt-ses-verify { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 8px 0 0; border: 0; border-top: 1px solid var(--rf-border); }
|
|
3747
|
-
.dt-ses-timeline { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
|
|
3748
|
-
.dt-ses-seg { display: flex; gap: 8px; padding: 6px 8px; border-radius: 8px; }
|
|
3749
|
-
.dt-ses-seg:focus { outline: 2px solid var(--rf-accent); outline-offset: -2px; }
|
|
3750
|
-
.dt-ses-seg[data-kind="note"] { padding-block: 2px; }
|
|
3751
|
-
.dt-ses-seg-body { display: flex; flex: 1; flex-direction: column; gap: 4px; min-width: 0; }
|
|
3752
|
-
`}${`
|
|
3753
|
-
.dt-ses-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
3754
|
-
.dt-ses-shot { position: relative; display: inline-block; max-width: 100%; line-height: 0; }
|
|
3755
|
-
.dt-ses-shot img { display: block; max-width: 100%; height: auto; max-height: 132px; border-radius: 8px; box-shadow: var(--rf-shadow-inset); }
|
|
3756
|
-
.dt-ses-shot[data-large="true"] img { max-height: none; }
|
|
3757
|
-
.dt-ses-shot-mark { position: absolute; border: 2px solid var(--rf-accent); border-radius: 4px; pointer-events: none; }
|
|
3758
|
-
.dt-ses-shot-btn { align-self: flex-start; padding: 0; border-radius: 8px; }
|
|
3759
|
-
.dt-ses-check { display: flex; align-items: flex-start; gap: 6px; overflow-wrap: anywhere; }
|
|
3760
|
-
.dt-ses-check input { flex: none; margin-top: 3px; accent-color: var(--rf-accent); }
|
|
3761
|
-
.dt-ses-choices { margin: 0; padding: 0; border: 0; }
|
|
3762
|
-
.dt-ses-choices .dt-ses-list { padding-left: 0; list-style: none; }
|
|
3763
|
-
.dt-ses-brief {
|
|
3764
|
-
max-height: 50vh; overflow: auto; margin: 0; padding: 10px; border-radius: 10px;
|
|
3765
|
-
background: var(--rf-bg-subtle); font: 11.5px/1.55 ${MONO_FONT$1}; white-space: pre-wrap; overflow-wrap: anywhere;
|
|
3766
|
-
}
|
|
3767
|
-
`}${`
|
|
3768
|
-
.dt-team-anchor {
|
|
3769
|
-
--dt-edge-gap: calc(max(var(--rf-offset), 12px) + 48px);
|
|
3770
|
-
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; width: min(300px, calc(100vw - 24px));
|
|
3771
|
-
}
|
|
3772
|
-
.dt-team-anchor[data-side="left"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }
|
|
3773
|
-
.dt-team-anchor[data-side="right"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }
|
|
3774
|
-
.dt-team-anchor[data-edge="bottom"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }
|
|
3775
|
-
.dt-team-anchor[data-edge="top"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }
|
|
3776
|
-
.dt-team-card { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: 14px; animation: dt-popover-in 200ms var(--rf-ease); }
|
|
3777
|
-
.dt-bar > .dt-btn { margin-inline: 2px 4px; }
|
|
3778
|
-
`}${INTENTION_STYLES}${REPORT_STYLES}`;
|
|
3779
|
-
//#endregion
|
|
3780
3660
|
//#region src/devtools/client/clipboard.ts
|
|
3781
3661
|
/**
|
|
3782
3662
|
* Safari only lets a page write the clipboard inside the key press or click
|
|
@@ -3789,1334 +3669,833 @@ async function copyToClipboard(text) {
|
|
|
3789
3669
|
await navigator.clipboard.write([new ClipboardItem({ "text/plain": blob })]);
|
|
3790
3670
|
}
|
|
3791
3671
|
//#endregion
|
|
3792
|
-
//#region src/
|
|
3793
|
-
|
|
3794
|
-
|
|
3672
|
+
//#region src/sessions/ui/handoff/zip-archive.ts
|
|
3673
|
+
const LOCAL_HEADER_SIGNATURE = 67324752;
|
|
3674
|
+
const CENTRAL_HEADER_SIGNATURE = 33639248;
|
|
3675
|
+
const END_SIGNATURE = 101010256;
|
|
3676
|
+
const LOCAL_HEADER_SIZE = 30;
|
|
3677
|
+
const CENTRAL_HEADER_SIZE = 46;
|
|
3678
|
+
const END_RECORD_SIZE = 22;
|
|
3679
|
+
const ZIP_VERSION = 20;
|
|
3680
|
+
const UTF8_NAMES_FLAG = 2048;
|
|
3681
|
+
const DEFLATE_METHOD = 8;
|
|
3682
|
+
const GZIP_HEADER_SIZE = 10;
|
|
3683
|
+
const GZIP_FLAGS_OFFSET = 3;
|
|
3684
|
+
const GZIP_TRAILER_SIZE = 8;
|
|
3685
|
+
const DOS_EPOCH_YEAR = 1980;
|
|
3686
|
+
function dosStamp(date) {
|
|
3687
|
+
return {
|
|
3688
|
+
date: (date.getFullYear() - DOS_EPOCH_YEAR) * 512 + (date.getMonth() + 1) * 32 + date.getDate(),
|
|
3689
|
+
time: date.getHours() * 2048 + date.getMinutes() * 32 + Math.floor(date.getSeconds() / 2)
|
|
3690
|
+
};
|
|
3795
3691
|
}
|
|
3796
|
-
|
|
3797
|
-
|
|
3692
|
+
/** gzip wraps raw deflate data and ends with the CRC-32 zip needs, so the browser computes both natively. */
|
|
3693
|
+
async function deflateEntry(data) {
|
|
3694
|
+
const stream = new Response(data).body?.pipeThrough(new CompressionStream("gzip"));
|
|
3695
|
+
const gzip = new Uint8Array(await new Response(stream).arrayBuffer());
|
|
3696
|
+
if (gzip[GZIP_FLAGS_OFFSET] !== 0) throw new Error("The browser wrote an unexpected gzip header.");
|
|
3697
|
+
return {
|
|
3698
|
+
checksum: new DataView(gzip.buffer, gzip.length - GZIP_TRAILER_SIZE).getUint32(0, true),
|
|
3699
|
+
compressed: gzip.slice(GZIP_HEADER_SIZE, gzip.length - GZIP_TRAILER_SIZE)
|
|
3700
|
+
};
|
|
3798
3701
|
}
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3702
|
+
function writeCommonFields(view, start, options) {
|
|
3703
|
+
const { record, stamp } = options;
|
|
3704
|
+
view.setUint16(start, ZIP_VERSION, true);
|
|
3705
|
+
view.setUint16(start + 2, UTF8_NAMES_FLAG, true);
|
|
3706
|
+
view.setUint16(start + 4, DEFLATE_METHOD, true);
|
|
3707
|
+
view.setUint16(start + 6, stamp.time, true);
|
|
3708
|
+
view.setUint16(start + 8, stamp.date, true);
|
|
3709
|
+
view.setUint32(start + 10, record.checksum, true);
|
|
3710
|
+
view.setUint32(start + 14, record.compressed.length, true);
|
|
3711
|
+
view.setUint32(start + 18, record.size, true);
|
|
3712
|
+
view.setUint16(start + 22, record.name.length, true);
|
|
3713
|
+
view.setUint16(start + 24, 0, true);
|
|
3714
|
+
}
|
|
3715
|
+
function localHeader(record, stamp) {
|
|
3716
|
+
const bytes = new Uint8Array(LOCAL_HEADER_SIZE + record.name.length);
|
|
3717
|
+
const view = new DataView(bytes.buffer);
|
|
3718
|
+
view.setUint32(0, LOCAL_HEADER_SIGNATURE, true);
|
|
3719
|
+
writeCommonFields(view, 4, {
|
|
3720
|
+
record,
|
|
3721
|
+
stamp
|
|
3812
3722
|
});
|
|
3723
|
+
bytes.set(record.name, LOCAL_HEADER_SIZE);
|
|
3724
|
+
return bytes;
|
|
3813
3725
|
}
|
|
3814
|
-
function
|
|
3815
|
-
const
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
"data-edge": edge,
|
|
3823
|
-
"data-moved": floating.position !== null,
|
|
3824
|
-
"data-side": side,
|
|
3825
|
-
ref: floating.rootRef,
|
|
3826
|
-
role: "toolbar",
|
|
3827
|
-
children: [
|
|
3828
|
-
/* @__PURE__ */ jsx("style", { children: floating.styles }),
|
|
3829
|
-
/* @__PURE__ */ jsx("button", {
|
|
3830
|
-
"aria-label": `Move ${label} (double-click to reset)`,
|
|
3831
|
-
className: "icon-btn drag-handle dt-grip",
|
|
3832
|
-
onDoubleClick: floating.resetPosition,
|
|
3833
|
-
title: "Drag to move · double-click to reset",
|
|
3834
|
-
type: "button",
|
|
3835
|
-
...floating.handleProps,
|
|
3836
|
-
children: /* @__PURE__ */ jsx(GripIcon, {})
|
|
3837
|
-
}),
|
|
3838
|
-
children
|
|
3839
|
-
]
|
|
3726
|
+
function centralHeader(record, stamp) {
|
|
3727
|
+
const bytes = new Uint8Array(CENTRAL_HEADER_SIZE + record.name.length);
|
|
3728
|
+
const view = new DataView(bytes.buffer);
|
|
3729
|
+
view.setUint32(0, CENTRAL_HEADER_SIGNATURE, true);
|
|
3730
|
+
view.setUint16(4, ZIP_VERSION, true);
|
|
3731
|
+
writeCommonFields(view, 6, {
|
|
3732
|
+
record,
|
|
3733
|
+
stamp
|
|
3840
3734
|
});
|
|
3735
|
+
view.setUint32(42, record.offset, true);
|
|
3736
|
+
bytes.set(record.name, CENTRAL_HEADER_SIZE);
|
|
3737
|
+
return bytes;
|
|
3841
3738
|
}
|
|
3842
|
-
function
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3739
|
+
function endRecord(options) {
|
|
3740
|
+
const bytes = new Uint8Array(END_RECORD_SIZE);
|
|
3741
|
+
const view = new DataView(bytes.buffer);
|
|
3742
|
+
view.setUint32(0, END_SIGNATURE, true);
|
|
3743
|
+
view.setUint16(8, options.count, true);
|
|
3744
|
+
view.setUint16(10, options.count, true);
|
|
3745
|
+
view.setUint32(12, options.directorySize, true);
|
|
3746
|
+
view.setUint32(16, options.directoryOffset, true);
|
|
3747
|
+
return bytes;
|
|
3748
|
+
}
|
|
3749
|
+
async function createZipArchive(entries, modifiedAt = /* @__PURE__ */ new Date()) {
|
|
3750
|
+
const stamp = dosStamp(modifiedAt);
|
|
3751
|
+
const encoder = new TextEncoder();
|
|
3752
|
+
const deflated = await Promise.all(entries.map(async (entry) => ({
|
|
3753
|
+
...await deflateEntry(entry.data),
|
|
3754
|
+
name: encoder.encode(entry.name),
|
|
3755
|
+
size: entry.data.length
|
|
3756
|
+
})));
|
|
3757
|
+
const records = [];
|
|
3758
|
+
const parts = [];
|
|
3759
|
+
let offset = 0;
|
|
3760
|
+
for (const entry of deflated) {
|
|
3761
|
+
const record = {
|
|
3762
|
+
...entry,
|
|
3763
|
+
offset
|
|
3764
|
+
};
|
|
3765
|
+
const header = localHeader(record, stamp);
|
|
3766
|
+
parts.push(header, record.compressed);
|
|
3767
|
+
records.push(record);
|
|
3768
|
+
offset += header.length + record.compressed.length;
|
|
3769
|
+
}
|
|
3770
|
+
const directory = records.map((record) => centralHeader(record, stamp));
|
|
3771
|
+
const directorySize = directory.reduce((size, part) => size + part.length, 0);
|
|
3772
|
+
const end = endRecord({
|
|
3773
|
+
count: records.length,
|
|
3774
|
+
directoryOffset: offset,
|
|
3775
|
+
directorySize
|
|
3848
3776
|
});
|
|
3777
|
+
return new Blob([
|
|
3778
|
+
...parts,
|
|
3779
|
+
...directory,
|
|
3780
|
+
end
|
|
3781
|
+
], { type: "application/zip" });
|
|
3849
3782
|
}
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3783
|
+
//#endregion
|
|
3784
|
+
//#region src/sessions/ui/handoff/brief-export.ts
|
|
3785
|
+
const BRIEF_FILE_NAME = "brief.md";
|
|
3786
|
+
const UNSAFE_FILE_CHARACTERS = /[^a-z0-9]+/g;
|
|
3787
|
+
const EDGE_DASHES = /^-|-$/g;
|
|
3788
|
+
async function downloadFile(file) {
|
|
3789
|
+
const response = await fetch(file.url);
|
|
3790
|
+
if (!response.ok) throw new Error(`${file.name} could not be downloaded (${response.status}).`);
|
|
3791
|
+
return {
|
|
3792
|
+
data: new Uint8Array(await response.arrayBuffer()),
|
|
3793
|
+
name: file.name
|
|
3794
|
+
};
|
|
3795
|
+
}
|
|
3796
|
+
function zipFileName(sessionTitle) {
|
|
3797
|
+
return `reflet-session-${sessionTitle.toLowerCase().replace(UNSAFE_FILE_CHARACTERS, "-").replace(EDGE_DASHES, "") || "brief"}.zip`;
|
|
3798
|
+
}
|
|
3799
|
+
/** File URLs are short-lived, so they are fetched right when the export is asked for. */
|
|
3800
|
+
async function buildBriefZip(options) {
|
|
3801
|
+
const evidence = await Promise.all(options.files.map(downloadFile));
|
|
3802
|
+
return await createZipArchive([{
|
|
3803
|
+
data: new TextEncoder().encode(options.brief),
|
|
3804
|
+
name: BRIEF_FILE_NAME
|
|
3805
|
+
}, ...evidence]);
|
|
3806
|
+
}
|
|
3807
|
+
function saveBlob(options) {
|
|
3808
|
+
const url = URL.createObjectURL(options.blob);
|
|
3809
|
+
const link = document.createElement("a");
|
|
3810
|
+
link.download = options.fileName;
|
|
3811
|
+
link.href = url;
|
|
3812
|
+
link.click();
|
|
3813
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
3878
3814
|
}
|
|
3879
3815
|
//#endregion
|
|
3880
|
-
//#region src/
|
|
3881
|
-
const
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
dx: 0,
|
|
3889
|
-
dy: KEYBOARD_STEP
|
|
3890
|
-
},
|
|
3891
|
-
ArrowLeft: {
|
|
3892
|
-
dx: -24,
|
|
3893
|
-
dy: 0
|
|
3894
|
-
},
|
|
3895
|
-
ArrowRight: {
|
|
3896
|
-
dx: KEYBOARD_STEP,
|
|
3897
|
-
dy: 0
|
|
3898
|
-
},
|
|
3899
|
-
ArrowUp: {
|
|
3900
|
-
dx: 0,
|
|
3901
|
-
dy: -24
|
|
3902
|
-
}
|
|
3816
|
+
//#region src/sessions/ui/review/transcript/evidence-thumb.tsx
|
|
3817
|
+
const TRIGGER_LABELS = {
|
|
3818
|
+
hover: "Long hover",
|
|
3819
|
+
manual: "Added by hand",
|
|
3820
|
+
mark: "Marked moment",
|
|
3821
|
+
navigation: "Page change",
|
|
3822
|
+
select: "Pointed element",
|
|
3823
|
+
start: "Session start"
|
|
3903
3824
|
};
|
|
3904
|
-
function
|
|
3905
|
-
const
|
|
3906
|
-
|
|
3907
|
-
width: DEFAULT_WIDTH
|
|
3908
|
-
};
|
|
3909
|
-
try {
|
|
3910
|
-
const stored = JSON.parse(localStorage.getItem(SIZE_KEY) ?? "null");
|
|
3911
|
-
if (typeof stored === "object" && stored !== null && "width" in stored && typeof stored.width === "number" && "height" in stored && (stored.height === null || typeof stored.height === "number")) return {
|
|
3912
|
-
height: stored.height,
|
|
3913
|
-
width: stored.width
|
|
3914
|
-
};
|
|
3915
|
-
} catch {
|
|
3916
|
-
return fallback;
|
|
3917
|
-
}
|
|
3918
|
-
return fallback;
|
|
3825
|
+
function evidenceCaption(evidence) {
|
|
3826
|
+
const element = evidence.element ? ` · ${evidence.element.label}` : "";
|
|
3827
|
+
return `${TRIGGER_LABELS[evidence.trigger]}${element}`;
|
|
3919
3828
|
}
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
function fitted(size, viewport) {
|
|
3925
|
-
const maxWidth = viewport.width - 24;
|
|
3926
|
-
const maxHeight = viewport.height - 24;
|
|
3829
|
+
const hasViewport = (frame) => frame.viewportWidth > 0 && frame.viewportHeight > 0;
|
|
3830
|
+
const percent = (value, total) => `${value / total * 100}%`;
|
|
3831
|
+
function percentBox(rect, frame) {
|
|
3832
|
+
if (!hasViewport(frame)) return null;
|
|
3927
3833
|
return {
|
|
3928
|
-
height:
|
|
3929
|
-
|
|
3834
|
+
height: percent(rect.height, frame.viewportHeight),
|
|
3835
|
+
left: percent(rect.x, frame.viewportWidth),
|
|
3836
|
+
top: percent(rect.y, frame.viewportHeight),
|
|
3837
|
+
width: percent(rect.width, frame.viewportWidth)
|
|
3930
3838
|
};
|
|
3931
3839
|
}
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
* a height reaching the bottom of the window snaps back to full height.
|
|
3935
|
-
*/
|
|
3936
|
-
function useSheetSize(side) {
|
|
3937
|
-
const [preference, setPreference] = useState(readStoredSize);
|
|
3938
|
-
const [viewport, setViewport] = useState(visibleViewport);
|
|
3939
|
-
const drag = useRef(null);
|
|
3940
|
-
const widthDirection = side === "right" ? -1 : 1;
|
|
3941
|
-
const size = fitted(preference, viewport);
|
|
3942
|
-
useEffect(() => onViewportChange(() => setViewport(visibleViewport())), []);
|
|
3943
|
-
useEffect(() => {
|
|
3944
|
-
try {
|
|
3945
|
-
localStorage.setItem(SIZE_KEY, JSON.stringify(preference));
|
|
3946
|
-
} catch {}
|
|
3947
|
-
}, [preference]);
|
|
3948
|
-
const resize = (axis, from, dx, dy) => {
|
|
3949
|
-
const fullHeight = viewport.height - 24;
|
|
3950
|
-
setPreference(fitted({
|
|
3951
|
-
height: axis === "width" ? from.height : (from.height ?? fullHeight) + dy,
|
|
3952
|
-
width: axis === "height" ? from.width : from.width + dx * widthDirection
|
|
3953
|
-
}, viewport));
|
|
3954
|
-
};
|
|
3955
|
-
const handleProps = (axis) => ({
|
|
3956
|
-
onDoubleClick: () => setPreference((current) => ({
|
|
3957
|
-
height: axis === "width" ? current.height : null,
|
|
3958
|
-
width: axis === "height" ? current.width : DEFAULT_WIDTH
|
|
3959
|
-
})),
|
|
3960
|
-
onKeyDown: (event) => {
|
|
3961
|
-
const delta = ARROW_DELTAS[event.key];
|
|
3962
|
-
if (!delta) return;
|
|
3963
|
-
event.preventDefault();
|
|
3964
|
-
const sheetHeight = event.currentTarget.parentElement?.getBoundingClientRect().height ?? null;
|
|
3965
|
-
resize(axis, {
|
|
3966
|
-
height: size.height ?? sheetHeight,
|
|
3967
|
-
width: size.width
|
|
3968
|
-
}, delta.dx, delta.dy);
|
|
3969
|
-
},
|
|
3970
|
-
onLostPointerCapture: () => {
|
|
3971
|
-
drag.current = null;
|
|
3972
|
-
},
|
|
3973
|
-
onPointerDown: (event) => {
|
|
3974
|
-
if (event.button !== 0) return;
|
|
3975
|
-
const sheet = event.currentTarget.parentElement?.getBoundingClientRect();
|
|
3976
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
3977
|
-
drag.current = {
|
|
3978
|
-
axis,
|
|
3979
|
-
size: {
|
|
3980
|
-
height: sheet?.height ?? size.height,
|
|
3981
|
-
width: size.width
|
|
3982
|
-
},
|
|
3983
|
-
x: event.clientX,
|
|
3984
|
-
y: event.clientY
|
|
3985
|
-
};
|
|
3986
|
-
},
|
|
3987
|
-
onPointerMove: (event) => {
|
|
3988
|
-
const start = drag.current;
|
|
3989
|
-
if (start && event.currentTarget.hasPointerCapture(event.pointerId)) resize(start.axis, start.size, event.clientX - start.x, event.clientY - start.y);
|
|
3990
|
-
}
|
|
3991
|
-
});
|
|
3840
|
+
function percentPoint(point, frame) {
|
|
3841
|
+
if (!hasViewport(frame)) return null;
|
|
3992
3842
|
return {
|
|
3993
|
-
|
|
3994
|
-
|
|
3843
|
+
left: percent(point.x, frame.viewportWidth),
|
|
3844
|
+
top: percent(point.y, frame.viewportHeight)
|
|
3995
3845
|
};
|
|
3996
3846
|
}
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
const
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
if (opener instanceof HTMLElement && opener.isConnected) opener.focus({ preventScroll: true });
|
|
4015
|
-
};
|
|
4016
|
-
}, [rootRef]);
|
|
4017
|
-
}
|
|
4018
|
-
function DevtoolsSheet({ children, label = "Reflet devtools", onClose, onPick, onSelectTab, side, tab, tabs }) {
|
|
4019
|
-
const { handleProps, size } = useSheetSize(side);
|
|
4020
|
-
const floating = useFloatingPosition(`top-${side}`, false, {
|
|
4021
|
-
anchorSelector: ".dt-sheet",
|
|
4022
|
-
persistKey: SHEET_POSITION_KEY
|
|
3847
|
+
function EvidenceThumb({ evidence, isLarge = false }) {
|
|
3848
|
+
const { element, frame, image } = evidence;
|
|
3849
|
+
if (!image?.url) return null;
|
|
3850
|
+
const highlight = element && frame ? percentBox(element.rect, frame) : null;
|
|
3851
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
3852
|
+
className: "dt-ses-shot",
|
|
3853
|
+
"data-large": isLarge,
|
|
3854
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
3855
|
+
alt: evidenceCaption(evidence),
|
|
3856
|
+
height: image.height,
|
|
3857
|
+
src: image.url,
|
|
3858
|
+
width: image.width
|
|
3859
|
+
}), highlight && /* @__PURE__ */ jsx("span", {
|
|
3860
|
+
"aria-hidden": "true",
|
|
3861
|
+
className: "dt-ses-shot-mark",
|
|
3862
|
+
style: highlight
|
|
3863
|
+
})]
|
|
4023
3864
|
});
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
3865
|
+
}
|
|
3866
|
+
//#endregion
|
|
3867
|
+
//#region src/sessions/ui/review/continuation/intention-history.tsx
|
|
3868
|
+
const FIELD_LABELS = {
|
|
3869
|
+
need: "Need",
|
|
3870
|
+
observed: "Observed",
|
|
3871
|
+
response: "Considered response",
|
|
3872
|
+
setAside: "Set aside",
|
|
3873
|
+
unknowns: "To check"
|
|
3874
|
+
};
|
|
3875
|
+
function fieldValueText(value) {
|
|
3876
|
+
return (Array.isArray(value) ? value.join("; ") : value) || "—";
|
|
3877
|
+
}
|
|
3878
|
+
function AppliedChanges({ applied }) {
|
|
3879
|
+
if (applied.length === 0) return null;
|
|
3880
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
3881
|
+
className: "dt-ses-rows",
|
|
3882
|
+
children: applied.map((change) => /* @__PURE__ */ jsxs("li", {
|
|
3883
|
+
className: "dt-ses-row",
|
|
3884
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
3885
|
+
className: "dt-meta",
|
|
3886
|
+
children: [
|
|
3887
|
+
"Accepted into revision ",
|
|
3888
|
+
change.revision,
|
|
3889
|
+
" by",
|
|
3890
|
+
" ",
|
|
3891
|
+
change.byName ?? "a teammate",
|
|
3892
|
+
" · ",
|
|
3893
|
+
formatDate(change.at)
|
|
3894
|
+
]
|
|
3895
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
3896
|
+
className: "dt-ses-list",
|
|
3897
|
+
children: change.fields.map((field) => /* @__PURE__ */ jsxs("li", { children: [
|
|
3898
|
+
FIELD_LABELS[field.field],
|
|
3899
|
+
": ",
|
|
3900
|
+
fieldValueText(field.before),
|
|
3901
|
+
" →",
|
|
3902
|
+
" ",
|
|
3903
|
+
fieldValueText(field.after)
|
|
3904
|
+
] }, field.field))
|
|
3905
|
+
})]
|
|
3906
|
+
}, change.revision))
|
|
3907
|
+
});
|
|
3908
|
+
}
|
|
3909
|
+
function HistoryExtracts({ evidence, quotes }) {
|
|
3910
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [quotes.map((quote) => /* @__PURE__ */ jsxs("blockquote", {
|
|
3911
|
+
className: "dt-ses-moment-quote",
|
|
4040
3912
|
children: [
|
|
4041
|
-
/* @__PURE__ */
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
className: "dt-resize",
|
|
4045
|
-
"data-axis": "width",
|
|
4046
|
-
type: "button",
|
|
4047
|
-
...handleProps("width")
|
|
4048
|
-
}),
|
|
4049
|
-
/* @__PURE__ */ jsx("button", {
|
|
4050
|
-
"aria-label": "Resize panel height (double-click for full height)",
|
|
4051
|
-
className: "dt-resize",
|
|
4052
|
-
"data-axis": "height",
|
|
4053
|
-
type: "button",
|
|
4054
|
-
...handleProps("height")
|
|
3913
|
+
/* @__PURE__ */ jsx("span", {
|
|
3914
|
+
className: "dt-ses-time",
|
|
3915
|
+
children: formatClock(quote.startMs)
|
|
4055
3916
|
}),
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
className: "dt-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
3917
|
+
` “${quote.text}”`,
|
|
3918
|
+
quote.context.map((line) => /* @__PURE__ */ jsx("span", {
|
|
3919
|
+
className: "dt-meta dt-ses-context-line",
|
|
3920
|
+
children: line
|
|
3921
|
+
}, line))
|
|
3922
|
+
]
|
|
3923
|
+
}, quote.segmentId)), evidence.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
3924
|
+
className: "dt-ses-thumbs",
|
|
3925
|
+
children: evidence.map((item) => /* @__PURE__ */ jsx(EvidenceThumb, { evidence: item }, item.id))
|
|
3926
|
+
})] });
|
|
3927
|
+
}
|
|
3928
|
+
function entryTitle(entry) {
|
|
3929
|
+
const { session } = entry;
|
|
3930
|
+
return entry.origin === "continuation" ? `Continued in “${session.title}” · ${formatDate(session.startedAt)}` : `Added from “${session.title}” · ${formatDate(session.startedAt)}`;
|
|
3931
|
+
}
|
|
3932
|
+
function HistoryEntry({ context, entry }) {
|
|
3933
|
+
const evidenceIds = new Set(entry.evidenceIds);
|
|
3934
|
+
const evidence = context.detail.contributedEvidence.filter((item) => evidenceIds.has(item.id));
|
|
3935
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
3936
|
+
className: "dt-ses-history",
|
|
3937
|
+
"data-removed": entry.detachedAt !== null,
|
|
3938
|
+
children: [
|
|
3939
|
+
/* @__PURE__ */ jsx("p", {
|
|
3940
|
+
className: "dt-ses-subhead",
|
|
3941
|
+
children: entryTitle(entry)
|
|
4062
3942
|
}),
|
|
4063
|
-
/* @__PURE__ */ jsxs("
|
|
4064
|
-
className: "dt-
|
|
3943
|
+
entry.detachedAt !== null && /* @__PURE__ */ jsxs("p", {
|
|
3944
|
+
className: "dt-meta",
|
|
4065
3945
|
children: [
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
onDoubleClick: floating.resetPosition,
|
|
4070
|
-
title: "Drag to move · double-click to dock",
|
|
4071
|
-
type: "button",
|
|
4072
|
-
...floating.handleProps
|
|
4073
|
-
}),
|
|
4074
|
-
onPick && /* @__PURE__ */ jsx("button", {
|
|
4075
|
-
"aria-label": "Pick an element: note it, copy it, or Shift+click to open its code",
|
|
4076
|
-
className: "icon-btn",
|
|
4077
|
-
onClick: onPick,
|
|
4078
|
-
title: "Pick an element",
|
|
4079
|
-
type: "button",
|
|
4080
|
-
children: /* @__PURE__ */ jsx(TargetIcon, {})
|
|
4081
|
-
}),
|
|
4082
|
-
/* @__PURE__ */ jsx("div", {
|
|
4083
|
-
className: "dt-tabs",
|
|
4084
|
-
role: "tablist",
|
|
4085
|
-
children: tabs.map((option) => /* @__PURE__ */ jsx("button", {
|
|
4086
|
-
"aria-selected": option === tab,
|
|
4087
|
-
className: "dt-tab",
|
|
4088
|
-
onClick: () => onSelectTab(option),
|
|
4089
|
-
role: "tab",
|
|
4090
|
-
type: "button",
|
|
4091
|
-
children: TAB_LABELS[option]
|
|
4092
|
-
}, option))
|
|
4093
|
-
}),
|
|
4094
|
-
/* @__PURE__ */ jsx("button", {
|
|
4095
|
-
"aria-label": `Close ${label} panel`,
|
|
4096
|
-
className: "icon-btn",
|
|
4097
|
-
onClick: onClose,
|
|
4098
|
-
title: "Close",
|
|
4099
|
-
type: "button",
|
|
4100
|
-
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
4101
|
-
})
|
|
3946
|
+
"Removed on ",
|
|
3947
|
+
formatDate(entry.detachedAt),
|
|
3948
|
+
": what it added was taken back."
|
|
4102
3949
|
]
|
|
4103
3950
|
}),
|
|
4104
|
-
/* @__PURE__ */ jsx(
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
children
|
|
4108
|
-
},
|
|
3951
|
+
/* @__PURE__ */ jsx(AppliedChanges, { applied: entry.applied }),
|
|
3952
|
+
entry.extractsHidden ? /* @__PURE__ */ jsx("p", {
|
|
3953
|
+
className: "dt-meta",
|
|
3954
|
+
children: "Extracts are private to the author"
|
|
3955
|
+
}) : /* @__PURE__ */ jsx(HistoryExtracts, {
|
|
3956
|
+
evidence,
|
|
3957
|
+
quotes: entry.quotes
|
|
3958
|
+
}),
|
|
3959
|
+
entry.session.canOpen && /* @__PURE__ */ jsx("button", {
|
|
3960
|
+
className: "dt-ses-link",
|
|
3961
|
+
onClick: () => context.navigation.onOpenSession(entry.session.id),
|
|
3962
|
+
type: "button",
|
|
3963
|
+
children: "Open session"
|
|
3964
|
+
})
|
|
4109
3965
|
]
|
|
4110
3966
|
});
|
|
4111
3967
|
}
|
|
3968
|
+
function IntentionHistory({ context, intentionId }) {
|
|
3969
|
+
const entries = context.detail.history.filter((entry) => entry.intentionId === intentionId);
|
|
3970
|
+
if (entries.length === 0) return null;
|
|
3971
|
+
return /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h4", {
|
|
3972
|
+
className: "dt-ses-label",
|
|
3973
|
+
children: "History"
|
|
3974
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
3975
|
+
className: "dt-ses-rows",
|
|
3976
|
+
children: entries.map((entry) => /* @__PURE__ */ jsx(HistoryEntry, {
|
|
3977
|
+
context,
|
|
3978
|
+
entry
|
|
3979
|
+
}, entry.id))
|
|
3980
|
+
})] });
|
|
3981
|
+
}
|
|
4112
3982
|
//#endregion
|
|
4113
|
-
//#region src/
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
3983
|
+
//#region src/sessions/ui/handoff/handoff-changes.tsx
|
|
3984
|
+
function differences(proposal, last) {
|
|
3985
|
+
return [
|
|
3986
|
+
{
|
|
3987
|
+
after: proposal.need,
|
|
3988
|
+
before: last.need,
|
|
3989
|
+
label: "Need"
|
|
3990
|
+
},
|
|
3991
|
+
{
|
|
3992
|
+
after: fieldValueText(proposal.response),
|
|
3993
|
+
before: fieldValueText(last.response),
|
|
3994
|
+
label: "Considered response"
|
|
3995
|
+
},
|
|
3996
|
+
{
|
|
3997
|
+
after: fieldValueText(proposal.unknowns),
|
|
3998
|
+
before: last.unknowns === null ? null : fieldValueText(last.unknowns),
|
|
3999
|
+
label: "To check"
|
|
4000
|
+
}
|
|
4001
|
+
].flatMap(({ after, before, label }) => before === null || before === after ? [] : [{
|
|
4002
|
+
after,
|
|
4003
|
+
before,
|
|
4004
|
+
label
|
|
4005
|
+
}]);
|
|
4127
4006
|
}
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4007
|
+
function ChangeSummary({ last, proposal }) {
|
|
4008
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
4009
|
+
className: "dt-ses-row",
|
|
4010
|
+
children: [
|
|
4011
|
+
/* @__PURE__ */ jsx("p", {
|
|
4012
|
+
className: "dt-ses-subhead",
|
|
4013
|
+
children: proposal.need
|
|
4014
|
+
}),
|
|
4015
|
+
/* @__PURE__ */ jsxs("p", {
|
|
4016
|
+
className: "dt-meta",
|
|
4017
|
+
children: ["Changed since your brief of ", formatDate(last.at)]
|
|
4018
|
+
}),
|
|
4019
|
+
/* @__PURE__ */ jsx("ul", {
|
|
4020
|
+
className: "dt-ses-list",
|
|
4021
|
+
children: differences(proposal, last).map((difference) => /* @__PURE__ */ jsxs("li", { children: [
|
|
4022
|
+
difference.label,
|
|
4023
|
+
": ",
|
|
4024
|
+
difference.before,
|
|
4025
|
+
" → ",
|
|
4026
|
+
difference.after
|
|
4027
|
+
] }, difference.label))
|
|
4028
|
+
})
|
|
4029
|
+
]
|
|
4030
|
+
});
|
|
4139
4031
|
}
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
.
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
}
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
.
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
.
|
|
4156
|
-
|
|
4157
|
-
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar};
|
|
4158
|
-
display: flex; align-items: center; gap: 2px; padding: 3px;
|
|
4159
|
-
border-radius: var(--rf-pill);
|
|
4160
|
-
}
|
|
4161
|
-
.dt-bar[data-moved="false"] { transition: left 260ms var(--rf-ease), right 260ms var(--rf-ease); }
|
|
4162
|
-
.dt-bar[data-side="left"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }
|
|
4163
|
-
.dt-bar[data-side="right"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }
|
|
4164
|
-
.dt-bar[data-edge="bottom"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }
|
|
4165
|
-
.dt-bar[data-edge="top"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }
|
|
4166
|
-
.dt-bar .icon-btn { position: relative; width: 34px; height: 34px; }
|
|
4167
|
-
.dt-bar .icon-btn.dt-grip { width: 22px; color: var(--rf-text-muted); opacity: .6; }
|
|
4168
|
-
.dt-bar .icon-btn.dt-grip:hover { opacity: 1; }
|
|
4169
|
-
.dt-bar .icon-btn[aria-pressed="true"] { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
4170
|
-
.dt-count {
|
|
4171
|
-
position: absolute; top: 1px; right: 1px; display: flex; align-items: center; justify-content: center;
|
|
4172
|
-
min-width: 15px; height: 15px; padding: 0 4px; border-radius: var(--rf-pill);
|
|
4173
|
-
background: var(--rf-accent); color: var(--rf-accent-text); font-size: 9.5px; font-weight: 600;
|
|
4032
|
+
function ChangedSinceBriefs({ detail, proposalIds }) {
|
|
4033
|
+
const selected = new Set(proposalIds);
|
|
4034
|
+
const changed = detail.proposals.flatMap((proposal) => {
|
|
4035
|
+
const last = proposal.lastHandoff;
|
|
4036
|
+
return selected.has(proposal.id) && last && last.revision < proposal.revision ? [{
|
|
4037
|
+
last,
|
|
4038
|
+
proposal
|
|
4039
|
+
}] : [];
|
|
4040
|
+
});
|
|
4041
|
+
if (changed.length === 0) return null;
|
|
4042
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
4043
|
+
className: "dt-ses-rows",
|
|
4044
|
+
children: changed.map(({ last, proposal }) => /* @__PURE__ */ jsx(ChangeSummary, {
|
|
4045
|
+
last,
|
|
4046
|
+
proposal
|
|
4047
|
+
}, proposal.id))
|
|
4048
|
+
});
|
|
4174
4049
|
}
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4050
|
+
const DELIVERY_LABELS = {
|
|
4051
|
+
copied: "Copied",
|
|
4052
|
+
exported: "Downloaded"
|
|
4053
|
+
};
|
|
4054
|
+
function deliveryLine(handoff) {
|
|
4055
|
+
const kinds = new Set(handoff.deliveries.map((delivery) => delivery.kind));
|
|
4056
|
+
if (kinds.size === 0) return "Not copied yet";
|
|
4057
|
+
return [...kinds].map((kind) => DELIVERY_LABELS[kind]).join(", ");
|
|
4181
4058
|
}
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
.
|
|
4186
|
-
@keyframes dt-sheet-slide { from { transform: translateX(var(--dt-enter-x)); box-shadow: none; } }
|
|
4187
|
-
.dt-resize { position: absolute; z-index: 2; padding: 0; touch-action: none; }
|
|
4188
|
-
.dt-resize:active:not(:disabled) { scale: 1; }
|
|
4189
|
-
.dt-resize:focus-visible { outline: none; }
|
|
4190
|
-
.dt-resize[data-axis="width"] { top: 16px; bottom: 16px; width: 10px; cursor: ew-resize; }
|
|
4191
|
-
.dt-sheet[data-side="right"] .dt-resize[data-axis="width"] { left: 0; }
|
|
4192
|
-
.dt-sheet[data-side="left"] .dt-resize[data-axis="width"] { right: 0; }
|
|
4193
|
-
.dt-resize[data-axis="height"] { left: 16px; right: 16px; bottom: 0; height: 10px; cursor: ns-resize; }
|
|
4194
|
-
.dt-resize[data-axis="both"] { bottom: 0; width: 16px; height: 16px; }
|
|
4195
|
-
.dt-sheet[data-side="right"] .dt-resize[data-axis="both"] { left: 0; cursor: nesw-resize; }
|
|
4196
|
-
.dt-sheet[data-side="left"] .dt-resize[data-axis="both"] { right: 0; cursor: nwse-resize; }
|
|
4197
|
-
.dt-resize[data-axis="width"]::after, .dt-resize[data-axis="height"]::after {
|
|
4198
|
-
content: ""; position: absolute; border-radius: var(--rf-pill); background: var(--rf-text-muted);
|
|
4199
|
-
opacity: 0; transition: opacity 160ms var(--rf-ease);
|
|
4059
|
+
function briefTitle(handoff) {
|
|
4060
|
+
const [only, ...others] = handoff.proposals;
|
|
4061
|
+
if (only && others.length === 0) return only.need;
|
|
4062
|
+
return countLabel(handoff.proposals.length, "intention");
|
|
4200
4063
|
}
|
|
4201
|
-
|
|
4202
|
-
.
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4064
|
+
function EarlierBriefs({ handoffs }) {
|
|
4065
|
+
if (handoffs.length === 0) return null;
|
|
4066
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
4067
|
+
className: "dt-ses-form",
|
|
4068
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
4069
|
+
className: "dt-group",
|
|
4070
|
+
children: "Earlier briefs"
|
|
4071
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
4072
|
+
className: "dt-ses-rows",
|
|
4073
|
+
children: handoffs.map((handoff) => {
|
|
4074
|
+
const date = formatDate(handoff.createdAt);
|
|
4075
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("details", {
|
|
4076
|
+
className: "dt-ses-brief-entry",
|
|
4077
|
+
children: [/* @__PURE__ */ jsxs("summary", { children: [/* @__PURE__ */ jsx("span", {
|
|
4078
|
+
className: "dt-card-title",
|
|
4079
|
+
children: briefTitle(handoff)
|
|
4080
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
4081
|
+
className: "dt-meta",
|
|
4082
|
+
children: [
|
|
4083
|
+
date,
|
|
4084
|
+
" · ",
|
|
4085
|
+
deliveryLine(handoff)
|
|
4086
|
+
]
|
|
4087
|
+
})] }), /* @__PURE__ */ jsx("textarea", {
|
|
4088
|
+
"aria-label": `Brief of ${date}`,
|
|
4089
|
+
className: "dt-field dt-ses-brief",
|
|
4090
|
+
readOnly: true,
|
|
4091
|
+
rows: 8,
|
|
4092
|
+
value: handoff.brief
|
|
4093
|
+
})]
|
|
4094
|
+
}) }, handoff.id);
|
|
4095
|
+
})
|
|
4096
|
+
})]
|
|
4097
|
+
});
|
|
4220
4098
|
}
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
.
|
|
4225
|
-
.dt-card[data-sent="true"] { opacity: .7; }
|
|
4226
|
-
.dt-card-head { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
4227
|
-
.dt-card-title { min-width: 0; margin: 0; overflow: hidden; font-size: 13px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
|
|
4228
|
-
.dt-meta { margin: 0; font-size: 11.5px; color: var(--rf-text-muted); overflow-wrap: anywhere; }
|
|
4229
|
-
.dt-note-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
4230
|
-
.dt-chip { flex: none; padding: 1px 7px; border-radius: var(--rf-pill); background: var(--rf-bg-hover); color: var(--rf-text-muted); font-size: 10.5px; font-weight: 600; }
|
|
4231
|
-
.dt-chip[data-tone="accent"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); color: var(--rf-accent); }
|
|
4232
|
-
.dt-source { padding: 0; font: 11.5px/1.4 ${MONO_FONT}; color: var(--rf-accent); text-align: left; overflow-wrap: anywhere; }
|
|
4233
|
-
.dt-source:hover { text-decoration: underline; }
|
|
4234
|
-
.dt-thumb { display: block; align-self: flex-start; max-width: 100%; height: auto; max-height: 132px; object-fit: contain; border-radius: 8px; box-shadow: var(--rf-shadow-inset); }
|
|
4235
|
-
.dt-actions { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
4236
|
-
.dt-btn {
|
|
4237
|
-
display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
|
|
4238
|
-
border-radius: var(--rf-pill); background: var(--rf-bg-hover); color: var(--rf-text);
|
|
4239
|
-
font-size: 12px; font-weight: 500; text-decoration: none;
|
|
4099
|
+
//#endregion
|
|
4100
|
+
//#region src/sessions/ui/handoff/handoff-selection.tsx
|
|
4101
|
+
function keptProposals(detail) {
|
|
4102
|
+
return detail.proposals.filter((proposal) => proposal.decision === "kept" && proposal.mergedIntoId === null);
|
|
4240
4103
|
}
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
.
|
|
4246
|
-
.dt-empty code, .dt-hint code { padding: 1px 4px; border-radius: 4px; background: var(--rf-bg-hover); font: 11.5px ${MONO_FONT}; overflow-wrap: anywhere; }
|
|
4247
|
-
.dt-hint { margin: 0; padding: 8px 10px; border-radius: 10px; background: var(--rf-bg-subtle); color: var(--rf-text-muted); font-size: 12px; }
|
|
4248
|
-
.dt-error { margin: 0; color: var(--rf-danger); font-size: 12px; }
|
|
4249
|
-
.dt-status { margin: 0 auto 0 0; color: var(--rf-text-muted); font-size: 12px; }
|
|
4250
|
-
.dt-field {
|
|
4251
|
-
width: 100%; padding: 7px 9px; border: 1px solid var(--rf-border); border-radius: 8px;
|
|
4252
|
-
background: var(--rf-bg); color: var(--rf-text); font: inherit; resize: vertical;
|
|
4104
|
+
function evidenceOf(detail, proposals) {
|
|
4105
|
+
const intentionIds = new Set(proposals.map((proposal) => proposal.id));
|
|
4106
|
+
const contributed = detail.history.filter((entry) => intentionIds.has(entry.intentionId) && entry.detachedAt === null);
|
|
4107
|
+
const cited = /* @__PURE__ */ new Set([...proposals.flatMap((proposal) => proposal.evidenceIds), ...contributed.flatMap((entry) => entry.evidenceIds)]);
|
|
4108
|
+
return [...detail.evidence, ...detail.contributedEvidence].filter((item) => cited.has(item.id) && item.status === "available");
|
|
4253
4109
|
}
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
.dt-matches { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
|
|
4257
|
-
.dt-match { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 6px 8px; border-radius: 8px; text-align: left; }
|
|
4258
|
-
.dt-match:hover { background: var(--rf-bg-hover); }
|
|
4259
|
-
.dt-match code { font: 11.5px ${MONO_FONT}; color: var(--rf-accent); }
|
|
4260
|
-
.dt-match span { font: 11.5px ${MONO_FONT}; color: var(--rf-text-muted); white-space: pre; overflow: hidden; text-overflow: ellipsis; }
|
|
4261
|
-
.dt-code-head { display: flex; flex-direction: column; gap: 6px; }
|
|
4262
|
-
.dt-code-path { margin: 0; font: 12px/1.4 ${MONO_FONT}; overflow-wrap: anywhere; }
|
|
4263
|
-
.dt-code { flex: 1; min-height: 0; overflow: auto; margin: 0; padding: 8px 0; border-radius: 10px; background: var(--rf-bg-subtle); font: 12px/1.6 ${MONO_FONT}; }
|
|
4264
|
-
.dt-code-lines { display: table; min-width: 100%; }
|
|
4265
|
-
.dt-line { display: table-row; white-space: pre; }
|
|
4266
|
-
.dt-line > span { display: table-cell; padding-right: 14px; }
|
|
4267
|
-
.dt-line > .dt-line-number { width: 1%; padding: 0 12px 0 10px; color: var(--rf-text-muted); text-align: right; user-select: none; }
|
|
4268
|
-
.dt-line[data-marked="true"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); }
|
|
4269
|
-
.dt-line[data-marked="true"] > .dt-line-number { color: var(--rf-accent); }
|
|
4270
|
-
`;
|
|
4271
|
-
//#endregion
|
|
4272
|
-
//#region src/sessions/ui/handoff/zip-archive.ts
|
|
4273
|
-
const LOCAL_HEADER_SIGNATURE = 67324752;
|
|
4274
|
-
const CENTRAL_HEADER_SIGNATURE = 33639248;
|
|
4275
|
-
const END_SIGNATURE = 101010256;
|
|
4276
|
-
const LOCAL_HEADER_SIZE = 30;
|
|
4277
|
-
const CENTRAL_HEADER_SIZE = 46;
|
|
4278
|
-
const END_RECORD_SIZE = 22;
|
|
4279
|
-
const ZIP_VERSION = 20;
|
|
4280
|
-
const UTF8_NAMES_FLAG = 2048;
|
|
4281
|
-
const DEFLATE_METHOD = 8;
|
|
4282
|
-
const GZIP_HEADER_SIZE = 10;
|
|
4283
|
-
const GZIP_FLAGS_OFFSET = 3;
|
|
4284
|
-
const GZIP_TRAILER_SIZE = 8;
|
|
4285
|
-
const DOS_EPOCH_YEAR = 1980;
|
|
4286
|
-
function dosStamp(date) {
|
|
4110
|
+
function initialSelection(detail) {
|
|
4111
|
+
const proposals = keptProposals(detail);
|
|
4287
4112
|
return {
|
|
4288
|
-
|
|
4289
|
-
|
|
4113
|
+
evidenceIds: evidenceOf(detail, proposals).map((item) => item.id),
|
|
4114
|
+
proposalIds: proposals.map((proposal) => proposal.id)
|
|
4290
4115
|
};
|
|
4291
4116
|
}
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
const stream = new Response(data).body?.pipeThrough(new CompressionStream("gzip"));
|
|
4295
|
-
const gzip = new Uint8Array(await new Response(stream).arrayBuffer());
|
|
4296
|
-
if (gzip[GZIP_FLAGS_OFFSET] !== 0) throw new Error("The browser wrote an unexpected gzip header.");
|
|
4297
|
-
return {
|
|
4298
|
-
checksum: new DataView(gzip.buffer, gzip.length - GZIP_TRAILER_SIZE).getUint32(0, true),
|
|
4299
|
-
compressed: gzip.slice(GZIP_HEADER_SIZE, gzip.length - GZIP_TRAILER_SIZE)
|
|
4300
|
-
};
|
|
4117
|
+
function toggled(ids, id) {
|
|
4118
|
+
return ids.includes(id) ? ids.filter((other) => other !== id) : [...ids, id];
|
|
4301
4119
|
}
|
|
4302
|
-
function
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
view.setUint32(start + 18, record.size, true);
|
|
4312
|
-
view.setUint16(start + 22, record.name.length, true);
|
|
4313
|
-
view.setUint16(start + 24, 0, true);
|
|
4120
|
+
function CheckRow({ isChecked, label, onToggle }) {
|
|
4121
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("label", {
|
|
4122
|
+
className: "dt-ses-check",
|
|
4123
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
4124
|
+
checked: isChecked,
|
|
4125
|
+
onChange: onToggle,
|
|
4126
|
+
type: "checkbox"
|
|
4127
|
+
}), /* @__PURE__ */ jsx("span", { children: label })]
|
|
4128
|
+
}) });
|
|
4314
4129
|
}
|
|
4315
|
-
function
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4130
|
+
function ChoiceGroup({ children, legend }) {
|
|
4131
|
+
return /* @__PURE__ */ jsxs("fieldset", {
|
|
4132
|
+
className: "dt-ses-choices",
|
|
4133
|
+
children: [/* @__PURE__ */ jsx("legend", {
|
|
4134
|
+
className: "dt-ses-label",
|
|
4135
|
+
children: legend
|
|
4136
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
4137
|
+
className: "dt-ses-list",
|
|
4138
|
+
children
|
|
4139
|
+
})]
|
|
4322
4140
|
});
|
|
4323
|
-
bytes.set(record.name, LOCAL_HEADER_SIZE);
|
|
4324
|
-
return bytes;
|
|
4325
4141
|
}
|
|
4326
|
-
function
|
|
4327
|
-
const
|
|
4328
|
-
const
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
record,
|
|
4333
|
-
stamp
|
|
4142
|
+
function HandoffChoices({ detail, onChange, selection }) {
|
|
4143
|
+
const proposals = keptProposals(detail);
|
|
4144
|
+
const evidence = evidenceOf(detail, proposals);
|
|
4145
|
+
const toggleProposal = (id) => onChange({
|
|
4146
|
+
...selection,
|
|
4147
|
+
proposalIds: toggled(selection.proposalIds, id)
|
|
4334
4148
|
});
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
}
|
|
4339
|
-
function endRecord(options) {
|
|
4340
|
-
const bytes = new Uint8Array(END_RECORD_SIZE);
|
|
4341
|
-
const view = new DataView(bytes.buffer);
|
|
4342
|
-
view.setUint32(0, END_SIGNATURE, true);
|
|
4343
|
-
view.setUint16(8, options.count, true);
|
|
4344
|
-
view.setUint16(10, options.count, true);
|
|
4345
|
-
view.setUint32(12, options.directorySize, true);
|
|
4346
|
-
view.setUint32(16, options.directoryOffset, true);
|
|
4347
|
-
return bytes;
|
|
4348
|
-
}
|
|
4349
|
-
async function createZipArchive(entries, modifiedAt = /* @__PURE__ */ new Date()) {
|
|
4350
|
-
const stamp = dosStamp(modifiedAt);
|
|
4351
|
-
const encoder = new TextEncoder();
|
|
4352
|
-
const deflated = await Promise.all(entries.map(async (entry) => ({
|
|
4353
|
-
...await deflateEntry(entry.data),
|
|
4354
|
-
name: encoder.encode(entry.name),
|
|
4355
|
-
size: entry.data.length
|
|
4356
|
-
})));
|
|
4357
|
-
const records = [];
|
|
4358
|
-
const parts = [];
|
|
4359
|
-
let offset = 0;
|
|
4360
|
-
for (const entry of deflated) {
|
|
4361
|
-
const record = {
|
|
4362
|
-
...entry,
|
|
4363
|
-
offset
|
|
4364
|
-
};
|
|
4365
|
-
const header = localHeader(record, stamp);
|
|
4366
|
-
parts.push(header, record.compressed);
|
|
4367
|
-
records.push(record);
|
|
4368
|
-
offset += header.length + record.compressed.length;
|
|
4369
|
-
}
|
|
4370
|
-
const directory = records.map((record) => centralHeader(record, stamp));
|
|
4371
|
-
const directorySize = directory.reduce((size, part) => size + part.length, 0);
|
|
4372
|
-
const end = endRecord({
|
|
4373
|
-
count: records.length,
|
|
4374
|
-
directoryOffset: offset,
|
|
4375
|
-
directorySize
|
|
4149
|
+
const toggleEvidence = (id) => onChange({
|
|
4150
|
+
...selection,
|
|
4151
|
+
evidenceIds: toggled(selection.evidenceIds, id)
|
|
4376
4152
|
});
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4153
|
+
const chosenProposalIds = new Set(selection.proposalIds);
|
|
4154
|
+
const chosenEvidenceIds = new Set(selection.evidenceIds);
|
|
4155
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ChoiceGroup, {
|
|
4156
|
+
legend: "Intentions",
|
|
4157
|
+
children: proposals.map((proposal) => /* @__PURE__ */ jsx(CheckRow, {
|
|
4158
|
+
isChecked: chosenProposalIds.has(proposal.id),
|
|
4159
|
+
label: proposal.need,
|
|
4160
|
+
onToggle: () => toggleProposal(proposal.id)
|
|
4161
|
+
}, proposal.id))
|
|
4162
|
+
}), evidence.length > 0 && /* @__PURE__ */ jsx(ChoiceGroup, {
|
|
4163
|
+
legend: "Evidence",
|
|
4164
|
+
children: evidence.map((item) => /* @__PURE__ */ jsx(CheckRow, {
|
|
4165
|
+
isChecked: chosenEvidenceIds.has(item.id),
|
|
4166
|
+
label: `${formatClock(item.atMs)} · ${evidenceCaption(item)}`,
|
|
4167
|
+
onToggle: () => toggleEvidence(item.id)
|
|
4168
|
+
}, item.id))
|
|
4169
|
+
})] });
|
|
4382
4170
|
}
|
|
4383
4171
|
//#endregion
|
|
4384
|
-
//#region src/sessions/ui/handoff/
|
|
4385
|
-
|
|
4386
|
-
const
|
|
4387
|
-
const
|
|
4388
|
-
|
|
4389
|
-
const
|
|
4390
|
-
|
|
4172
|
+
//#region src/sessions/ui/handoff/handoff-view.tsx
|
|
4173
|
+
function useDelivery(options) {
|
|
4174
|
+
const { api } = useSessionWorkspace();
|
|
4175
|
+
const run = useSessionAction();
|
|
4176
|
+
const { files, handoff } = options.prepared;
|
|
4177
|
+
const deliver = async (kind, send) => {
|
|
4178
|
+
try {
|
|
4179
|
+
await send();
|
|
4180
|
+
} catch (error) {
|
|
4181
|
+
reportFailure(`The brief was not ${kind}`, error);
|
|
4182
|
+
return;
|
|
4183
|
+
}
|
|
4184
|
+
announce(kind === "copied" ? "Brief copied" : "Brief downloaded");
|
|
4185
|
+
await run("The delivery was not recorded", () => api.markHandoffDelivered({
|
|
4186
|
+
handoffId: handoff.id,
|
|
4187
|
+
kind
|
|
4188
|
+
}));
|
|
4189
|
+
};
|
|
4391
4190
|
return {
|
|
4392
|
-
|
|
4393
|
-
|
|
4191
|
+
copy: () => deliver("copied", () => copyToClipboard(Promise.resolve(handoff.brief))),
|
|
4192
|
+
exportZip: () => deliver("exported", async () => {
|
|
4193
|
+
saveBlob({
|
|
4194
|
+
blob: await buildBriefZip({
|
|
4195
|
+
brief: handoff.brief,
|
|
4196
|
+
files
|
|
4197
|
+
}),
|
|
4198
|
+
fileName: zipFileName(options.title)
|
|
4199
|
+
});
|
|
4200
|
+
})
|
|
4394
4201
|
};
|
|
4395
4202
|
}
|
|
4396
|
-
function
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4203
|
+
function PreparedBrief({ onChangeSelection, prepared, title }) {
|
|
4204
|
+
const { copy, exportZip } = useDelivery({
|
|
4205
|
+
prepared,
|
|
4206
|
+
title
|
|
4207
|
+
});
|
|
4208
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("textarea", {
|
|
4209
|
+
"aria-label": "Brief",
|
|
4210
|
+
className: "dt-field dt-ses-brief",
|
|
4211
|
+
readOnly: true,
|
|
4212
|
+
rows: 12,
|
|
4213
|
+
value: prepared.handoff.brief
|
|
4214
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4215
|
+
className: "dt-actions",
|
|
4216
|
+
children: [
|
|
4217
|
+
/* @__PURE__ */ jsx("button", {
|
|
4218
|
+
className: "dt-btn",
|
|
4219
|
+
"data-variant": "primary",
|
|
4220
|
+
onClick: copy,
|
|
4221
|
+
type: "button",
|
|
4222
|
+
children: "Copy brief"
|
|
4223
|
+
}),
|
|
4224
|
+
/* @__PURE__ */ jsx("button", {
|
|
4225
|
+
className: "dt-btn",
|
|
4226
|
+
onClick: exportZip,
|
|
4227
|
+
type: "button",
|
|
4228
|
+
children: "Download .zip"
|
|
4229
|
+
}),
|
|
4230
|
+
/* @__PURE__ */ jsx("button", {
|
|
4231
|
+
className: "dt-btn",
|
|
4232
|
+
onClick: onChangeSelection,
|
|
4233
|
+
type: "button",
|
|
4234
|
+
children: "Edit selection"
|
|
4235
|
+
})
|
|
4236
|
+
]
|
|
4237
|
+
})] });
|
|
4428
4238
|
}
|
|
4429
|
-
|
|
4430
|
-
const
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4239
|
+
function usePrepareHandoff(options) {
|
|
4240
|
+
const { api } = useSessionWorkspace();
|
|
4241
|
+
const run = useSessionAction();
|
|
4242
|
+
const [request, setRequest] = useState(() => ({
|
|
4243
|
+
clientKey: crypto.randomUUID(),
|
|
4244
|
+
selection: initialSelection(options.detail)
|
|
4245
|
+
}));
|
|
4246
|
+
const [prepared, setPrepared] = useState(null);
|
|
4247
|
+
const [isPreparing, setIsPreparing] = useState(false);
|
|
4248
|
+
const prepare = async () => {
|
|
4249
|
+
setIsPreparing(true);
|
|
4250
|
+
const result = await run("The brief was not prepared", () => api.createHandoff({
|
|
4251
|
+
clientKey: request.clientKey,
|
|
4252
|
+
sessionId: options.detail.session.id,
|
|
4253
|
+
...request.selection
|
|
4254
|
+
}));
|
|
4255
|
+
setIsPreparing(false);
|
|
4256
|
+
if (result) {
|
|
4257
|
+
setPrepared(result);
|
|
4258
|
+
options.review.reload();
|
|
4259
|
+
}
|
|
4438
4260
|
};
|
|
4439
|
-
}
|
|
4440
|
-
function percentPoint(point, frame) {
|
|
4441
|
-
if (!hasViewport(frame)) return null;
|
|
4442
4261
|
return {
|
|
4443
|
-
|
|
4444
|
-
|
|
4262
|
+
clear: () => setPrepared(null),
|
|
4263
|
+
isPreparing,
|
|
4264
|
+
prepare,
|
|
4265
|
+
prepared,
|
|
4266
|
+
select: (selection) => setRequest({
|
|
4267
|
+
clientKey: crypto.randomUUID(),
|
|
4268
|
+
selection
|
|
4269
|
+
}),
|
|
4270
|
+
selection: request.selection
|
|
4445
4271
|
};
|
|
4446
4272
|
}
|
|
4447
|
-
function
|
|
4448
|
-
const
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4273
|
+
function SelectionStep({ detail, handoff }) {
|
|
4274
|
+
const count = handoff.selection.proposalIds.length;
|
|
4275
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4276
|
+
/* @__PURE__ */ jsx("p", {
|
|
4277
|
+
className: "dt-hint",
|
|
4278
|
+
children: "Tick what your agent should get. Nothing leaves Reflet until you copy or download the brief."
|
|
4279
|
+
}),
|
|
4280
|
+
/* @__PURE__ */ jsx(HandoffChoices, {
|
|
4281
|
+
detail,
|
|
4282
|
+
onChange: handoff.select,
|
|
4283
|
+
selection: handoff.selection
|
|
4284
|
+
}),
|
|
4285
|
+
/* @__PURE__ */ jsx(ChangedSinceBriefs, {
|
|
4286
|
+
detail,
|
|
4287
|
+
proposalIds: handoff.selection.proposalIds
|
|
4288
|
+
}),
|
|
4289
|
+
/* @__PURE__ */ jsx("div", {
|
|
4290
|
+
className: "dt-actions",
|
|
4291
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
4292
|
+
className: "dt-btn",
|
|
4293
|
+
"data-variant": "primary",
|
|
4294
|
+
disabled: count === 0 || handoff.isPreparing,
|
|
4295
|
+
onClick: handoff.prepare,
|
|
4296
|
+
type: "button",
|
|
4297
|
+
children: "Build brief"
|
|
4298
|
+
})
|
|
4299
|
+
})
|
|
4300
|
+
] });
|
|
4301
|
+
}
|
|
4302
|
+
function HandoffView({ detail, review }) {
|
|
4303
|
+
const handoff = usePrepareHandoff({
|
|
4304
|
+
detail,
|
|
4305
|
+
review
|
|
4306
|
+
});
|
|
4307
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
4308
|
+
"aria-labelledby": "rf-handoff-title",
|
|
4309
|
+
className: "dt-ses-handoff",
|
|
4310
|
+
children: [
|
|
4311
|
+
/* @__PURE__ */ jsx("h2", {
|
|
4312
|
+
className: "dt-ses-title",
|
|
4313
|
+
id: "rf-handoff-title",
|
|
4314
|
+
tabIndex: -1,
|
|
4315
|
+
children: "Brief for your agent"
|
|
4316
|
+
}),
|
|
4317
|
+
handoff.prepared ? /* @__PURE__ */ jsx(PreparedBrief, {
|
|
4318
|
+
onChangeSelection: handoff.clear,
|
|
4319
|
+
prepared: handoff.prepared,
|
|
4320
|
+
title: detail.session.title
|
|
4321
|
+
}) : /* @__PURE__ */ jsx(SelectionStep, {
|
|
4322
|
+
detail,
|
|
4323
|
+
handoff
|
|
4324
|
+
}),
|
|
4325
|
+
/* @__PURE__ */ jsx(EarlierBriefs, { handoffs: detail.handoffs })
|
|
4326
|
+
]
|
|
4464
4327
|
});
|
|
4465
4328
|
}
|
|
4466
4329
|
//#endregion
|
|
4467
|
-
//#region src/sessions/ui/review/
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
}
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
children: [/* @__PURE__ */ jsxs("p", {
|
|
4485
|
-
className: "dt-meta",
|
|
4486
|
-
children: [
|
|
4487
|
-
"Accepted into revision ",
|
|
4488
|
-
change.revision,
|
|
4489
|
-
" by",
|
|
4490
|
-
" ",
|
|
4491
|
-
change.byName ?? "a teammate",
|
|
4492
|
-
" · ",
|
|
4493
|
-
formatDate(change.at)
|
|
4494
|
-
]
|
|
4495
|
-
}), /* @__PURE__ */ jsx("ul", {
|
|
4496
|
-
className: "dt-ses-list",
|
|
4497
|
-
children: change.fields.map((field) => /* @__PURE__ */ jsxs("li", { children: [
|
|
4498
|
-
FIELD_LABELS[field.field],
|
|
4499
|
-
": ",
|
|
4500
|
-
fieldValueText(field.before),
|
|
4501
|
-
" →",
|
|
4502
|
-
" ",
|
|
4503
|
-
fieldValueText(field.after)
|
|
4504
|
-
] }, field.field))
|
|
4505
|
-
})]
|
|
4506
|
-
}, change.revision))
|
|
4507
|
-
});
|
|
4508
|
-
}
|
|
4509
|
-
function HistoryExtracts({ evidence, quotes }) {
|
|
4510
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [quotes.map((quote) => /* @__PURE__ */ jsxs("blockquote", {
|
|
4511
|
-
className: "dt-ses-moment-quote",
|
|
4512
|
-
children: [
|
|
4513
|
-
/* @__PURE__ */ jsx("span", {
|
|
4514
|
-
className: "dt-ses-time",
|
|
4515
|
-
children: formatClock(quote.startMs)
|
|
4516
|
-
}),
|
|
4517
|
-
` “${quote.text}”`,
|
|
4518
|
-
quote.context.map((line) => /* @__PURE__ */ jsx("span", {
|
|
4519
|
-
className: "dt-meta dt-ses-context-line",
|
|
4520
|
-
children: line
|
|
4521
|
-
}, line))
|
|
4522
|
-
]
|
|
4523
|
-
}, quote.segmentId)), evidence.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
4524
|
-
className: "dt-ses-thumbs",
|
|
4525
|
-
children: evidence.map((item) => /* @__PURE__ */ jsx(EvidenceThumb, { evidence: item }, item.id))
|
|
4526
|
-
})] });
|
|
4527
|
-
}
|
|
4528
|
-
function entryTitle(entry) {
|
|
4529
|
-
const { session } = entry;
|
|
4530
|
-
return entry.origin === "continuation" ? `Continued in “${session.title}” · ${formatDate(session.startedAt)}` : `Added from “${session.title}” · ${formatDate(session.startedAt)}`;
|
|
4531
|
-
}
|
|
4532
|
-
function HistoryEntry({ context, entry }) {
|
|
4533
|
-
const evidenceIds = new Set(entry.evidenceIds);
|
|
4534
|
-
const evidence = context.detail.contributedEvidence.filter((item) => evidenceIds.has(item.id));
|
|
4535
|
-
return /* @__PURE__ */ jsxs("li", {
|
|
4536
|
-
className: "dt-ses-history",
|
|
4537
|
-
"data-removed": entry.detachedAt !== null,
|
|
4538
|
-
children: [
|
|
4539
|
-
/* @__PURE__ */ jsx("p", {
|
|
4540
|
-
className: "dt-ses-subhead",
|
|
4541
|
-
children: entryTitle(entry)
|
|
4542
|
-
}),
|
|
4543
|
-
entry.detachedAt !== null && /* @__PURE__ */ jsxs("p", {
|
|
4544
|
-
className: "dt-meta",
|
|
4545
|
-
children: [
|
|
4546
|
-
"Removed on ",
|
|
4547
|
-
formatDate(entry.detachedAt),
|
|
4548
|
-
": what it added was taken back."
|
|
4549
|
-
]
|
|
4550
|
-
}),
|
|
4551
|
-
/* @__PURE__ */ jsx(AppliedChanges, { applied: entry.applied }),
|
|
4552
|
-
entry.extractsHidden ? /* @__PURE__ */ jsx("p", {
|
|
4553
|
-
className: "dt-meta",
|
|
4554
|
-
children: "Extracts are private to the author"
|
|
4555
|
-
}) : /* @__PURE__ */ jsx(HistoryExtracts, {
|
|
4556
|
-
evidence,
|
|
4557
|
-
quotes: entry.quotes
|
|
4558
|
-
}),
|
|
4559
|
-
entry.session.canOpen && /* @__PURE__ */ jsx("button", {
|
|
4560
|
-
className: "dt-ses-link",
|
|
4561
|
-
onClick: () => context.navigation.onOpenSession(entry.session.id),
|
|
4562
|
-
type: "button",
|
|
4563
|
-
children: "Open session"
|
|
4564
|
-
})
|
|
4565
|
-
]
|
|
4566
|
-
});
|
|
4567
|
-
}
|
|
4568
|
-
function IntentionHistory({ context, intentionId }) {
|
|
4569
|
-
const entries = context.detail.history.filter((entry) => entry.intentionId === intentionId);
|
|
4570
|
-
if (entries.length === 0) return null;
|
|
4571
|
-
return /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h4", {
|
|
4572
|
-
className: "dt-ses-label",
|
|
4573
|
-
children: "History"
|
|
4574
|
-
}), /* @__PURE__ */ jsx("ul", {
|
|
4575
|
-
className: "dt-ses-rows",
|
|
4576
|
-
children: entries.map((entry) => /* @__PURE__ */ jsx(HistoryEntry, {
|
|
4577
|
-
context,
|
|
4578
|
-
entry
|
|
4579
|
-
}, entry.id))
|
|
4580
|
-
})] });
|
|
4581
|
-
}
|
|
4582
|
-
//#endregion
|
|
4583
|
-
//#region src/sessions/ui/handoff/handoff-changes.tsx
|
|
4584
|
-
function differences(proposal, last) {
|
|
4585
|
-
return [
|
|
4586
|
-
{
|
|
4587
|
-
after: proposal.need,
|
|
4588
|
-
before: last.need,
|
|
4589
|
-
label: "Need"
|
|
4590
|
-
},
|
|
4591
|
-
{
|
|
4592
|
-
after: fieldValueText(proposal.response),
|
|
4593
|
-
before: fieldValueText(last.response),
|
|
4594
|
-
label: "Considered response"
|
|
4595
|
-
},
|
|
4596
|
-
{
|
|
4597
|
-
after: fieldValueText(proposal.unknowns),
|
|
4598
|
-
before: last.unknowns === null ? null : fieldValueText(last.unknowns),
|
|
4599
|
-
label: "To check"
|
|
4330
|
+
//#region src/sessions/ui/review/guarded-save.tsx
|
|
4331
|
+
function useGuardedSave() {
|
|
4332
|
+
const { onUnauthorized } = useSessionWorkspace();
|
|
4333
|
+
const [problem, setProblem] = useState(null);
|
|
4334
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
4335
|
+
const save = async (write) => {
|
|
4336
|
+
setIsSaving(true);
|
|
4337
|
+
setProblem(null);
|
|
4338
|
+
try {
|
|
4339
|
+
await write();
|
|
4340
|
+
} catch (error) {
|
|
4341
|
+
if (isUnauthorized(error)) onUnauthorized();
|
|
4342
|
+
else if (error instanceof SessionApiError && error.status === 409) setProblem({ kind: "stale" });
|
|
4343
|
+
else setProblem({
|
|
4344
|
+
kind: "failed",
|
|
4345
|
+
message: failureMessage(error)
|
|
4346
|
+
});
|
|
4600
4347
|
}
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
return /* @__PURE__ */ jsxs("li", {
|
|
4609
|
-
className: "dt-ses-row",
|
|
4610
|
-
children: [
|
|
4611
|
-
/* @__PURE__ */ jsx("p", {
|
|
4612
|
-
className: "dt-ses-subhead",
|
|
4613
|
-
children: proposal.need
|
|
4614
|
-
}),
|
|
4615
|
-
/* @__PURE__ */ jsxs("p", {
|
|
4616
|
-
className: "dt-meta",
|
|
4617
|
-
children: [
|
|
4618
|
-
"Changed since the brief of ",
|
|
4619
|
-
formatDate(last.at),
|
|
4620
|
-
" (revision",
|
|
4621
|
-
" ",
|
|
4622
|
-
last.revision,
|
|
4623
|
-
" → ",
|
|
4624
|
-
proposal.revision,
|
|
4625
|
-
")"
|
|
4626
|
-
]
|
|
4627
|
-
}),
|
|
4628
|
-
/* @__PURE__ */ jsx("ul", {
|
|
4629
|
-
className: "dt-ses-list",
|
|
4630
|
-
children: differences(proposal, last).map((difference) => /* @__PURE__ */ jsxs("li", { children: [
|
|
4631
|
-
difference.label,
|
|
4632
|
-
": ",
|
|
4633
|
-
difference.before,
|
|
4634
|
-
" → ",
|
|
4635
|
-
difference.after
|
|
4636
|
-
] }, difference.label))
|
|
4637
|
-
})
|
|
4638
|
-
]
|
|
4639
|
-
});
|
|
4640
|
-
}
|
|
4641
|
-
function ChangedSinceBriefs({ detail, proposalIds }) {
|
|
4642
|
-
const selected = new Set(proposalIds);
|
|
4643
|
-
const changed = detail.proposals.flatMap((proposal) => {
|
|
4644
|
-
const last = proposal.lastHandoff;
|
|
4645
|
-
return selected.has(proposal.id) && last && last.revision < proposal.revision ? [{
|
|
4646
|
-
last,
|
|
4647
|
-
proposal
|
|
4648
|
-
}] : [];
|
|
4649
|
-
});
|
|
4650
|
-
if (changed.length === 0) return null;
|
|
4651
|
-
return /* @__PURE__ */ jsx("ul", {
|
|
4652
|
-
className: "dt-ses-rows",
|
|
4653
|
-
children: changed.map(({ last, proposal }) => /* @__PURE__ */ jsx(ChangeSummary, {
|
|
4654
|
-
last,
|
|
4655
|
-
proposal
|
|
4656
|
-
}, proposal.id))
|
|
4657
|
-
});
|
|
4658
|
-
}
|
|
4659
|
-
function deliveryLine(handoff) {
|
|
4660
|
-
const kinds = new Set(handoff.deliveries.map((delivery) => delivery.kind));
|
|
4661
|
-
if (kinds.size === 0) return "not copied or exported";
|
|
4662
|
-
return [...kinds].join(" and ");
|
|
4663
|
-
}
|
|
4664
|
-
function intentionsLine(handoff) {
|
|
4665
|
-
const [only, ...others] = handoff.proposals;
|
|
4666
|
-
if (only && others.length === 0) return `“${only.need}” revision ${only.revision}`;
|
|
4667
|
-
return countLabel(handoff.proposals.length, "intention");
|
|
4348
|
+
setIsSaving(false);
|
|
4349
|
+
};
|
|
4350
|
+
return {
|
|
4351
|
+
isSaving,
|
|
4352
|
+
problem,
|
|
4353
|
+
save
|
|
4354
|
+
};
|
|
4668
4355
|
}
|
|
4669
|
-
function
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
children: [/* @__PURE__ */ jsx("
|
|
4674
|
-
className: "dt-
|
|
4675
|
-
children: "
|
|
4676
|
-
}), /* @__PURE__ */ jsx("
|
|
4677
|
-
className: "dt-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
date,
|
|
4682
|
-
" · ",
|
|
4683
|
-
intentionsLine(handoff),
|
|
4684
|
-
" · ",
|
|
4685
|
-
deliveryLine(handoff)
|
|
4686
|
-
] }), /* @__PURE__ */ jsx("textarea", {
|
|
4687
|
-
"aria-label": `Brief of ${date}`,
|
|
4688
|
-
className: "dt-field dt-ses-brief",
|
|
4689
|
-
readOnly: true,
|
|
4690
|
-
rows: 8,
|
|
4691
|
-
value: handoff.brief
|
|
4692
|
-
})] }) }, handoff.id);
|
|
4693
|
-
})
|
|
4356
|
+
function SaveProblemMessage({ onReload, problem }) {
|
|
4357
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4358
|
+
className: "dt-actions",
|
|
4359
|
+
role: "alert",
|
|
4360
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
4361
|
+
className: "dt-error",
|
|
4362
|
+
children: problem.kind === "stale" ? "Someone changed this since you opened it. Reload it, then edit again." : `Not saved: ${problem.message}`
|
|
4363
|
+
}), problem.kind === "stale" && /* @__PURE__ */ jsx("button", {
|
|
4364
|
+
className: "dt-btn",
|
|
4365
|
+
onClick: onReload,
|
|
4366
|
+
type: "button",
|
|
4367
|
+
children: "Reload"
|
|
4694
4368
|
})]
|
|
4695
4369
|
});
|
|
4696
4370
|
}
|
|
4697
4371
|
//#endregion
|
|
4698
|
-
//#region src/sessions/ui/
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
}
|
|
4702
|
-
function evidenceOf(detail, proposals) {
|
|
4703
|
-
const intentionIds = new Set(proposals.map((proposal) => proposal.id));
|
|
4704
|
-
const contributed = detail.history.filter((entry) => intentionIds.has(entry.intentionId) && entry.detachedAt === null);
|
|
4705
|
-
const cited = /* @__PURE__ */ new Set([...proposals.flatMap((proposal) => proposal.evidenceIds), ...contributed.flatMap((entry) => entry.evidenceIds)]);
|
|
4706
|
-
return [...detail.evidence, ...detail.contributedEvidence].filter((item) => cited.has(item.id) && item.status === "available");
|
|
4707
|
-
}
|
|
4708
|
-
function initialSelection(detail) {
|
|
4709
|
-
const proposals = keptProposals(detail);
|
|
4372
|
+
//#region src/sessions/ui/review/use-session-detail.ts
|
|
4373
|
+
const POLL_INTERVAL_MS = 2e3;
|
|
4374
|
+
function nextRequest(current) {
|
|
4710
4375
|
return {
|
|
4711
|
-
|
|
4712
|
-
|
|
4376
|
+
...current,
|
|
4377
|
+
count: current.count + 1
|
|
4713
4378
|
};
|
|
4714
4379
|
}
|
|
4715
|
-
function
|
|
4716
|
-
|
|
4380
|
+
function withProposal(detail, proposal) {
|
|
4381
|
+
const isKnown = detail.proposals.some((item) => item.id === proposal.id);
|
|
4382
|
+
return {
|
|
4383
|
+
...detail,
|
|
4384
|
+
proposals: isKnown ? detail.proposals.map((item) => item.id === proposal.id ? proposal : item) : [...detail.proposals, proposal]
|
|
4385
|
+
};
|
|
4717
4386
|
}
|
|
4718
|
-
function
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
type: "checkbox"
|
|
4725
|
-
}), /* @__PURE__ */ jsx("span", { children: label })]
|
|
4726
|
-
}) });
|
|
4387
|
+
function withSegment(detail, segment) {
|
|
4388
|
+
const others = detail.segments.filter((item) => item.id !== segment.id);
|
|
4389
|
+
return {
|
|
4390
|
+
...detail,
|
|
4391
|
+
segments: [...others, segment].sort((a, b) => a.startMs - b.startMs)
|
|
4392
|
+
};
|
|
4727
4393
|
}
|
|
4728
|
-
function
|
|
4729
|
-
return
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
children: legend
|
|
4734
|
-
}), /* @__PURE__ */ jsx("ul", {
|
|
4735
|
-
className: "dt-ses-list",
|
|
4736
|
-
children
|
|
4737
|
-
})]
|
|
4738
|
-
});
|
|
4394
|
+
function withEvidence(detail, evidence) {
|
|
4395
|
+
return {
|
|
4396
|
+
...detail,
|
|
4397
|
+
evidence: detail.evidence.map((item) => item.id === evidence.id ? evidence : item)
|
|
4398
|
+
};
|
|
4739
4399
|
}
|
|
4740
|
-
function
|
|
4741
|
-
|
|
4742
|
-
const evidence = evidenceOf(detail, proposals);
|
|
4743
|
-
const toggleProposal = (id) => onChange({
|
|
4744
|
-
...selection,
|
|
4745
|
-
proposalIds: toggled(selection.proposalIds, id)
|
|
4746
|
-
});
|
|
4747
|
-
const toggleEvidence = (id) => onChange({
|
|
4748
|
-
...selection,
|
|
4749
|
-
evidenceIds: toggled(selection.evidenceIds, id)
|
|
4750
|
-
});
|
|
4751
|
-
const chosenProposalIds = new Set(selection.proposalIds);
|
|
4752
|
-
const chosenEvidenceIds = new Set(selection.evidenceIds);
|
|
4753
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ChoiceGroup, {
|
|
4754
|
-
legend: "Intentions",
|
|
4755
|
-
children: proposals.map((proposal) => /* @__PURE__ */ jsx(CheckRow, {
|
|
4756
|
-
isChecked: chosenProposalIds.has(proposal.id),
|
|
4757
|
-
label: proposal.need,
|
|
4758
|
-
onToggle: () => toggleProposal(proposal.id)
|
|
4759
|
-
}, proposal.id))
|
|
4760
|
-
}), evidence.length > 0 && /* @__PURE__ */ jsx(ChoiceGroup, {
|
|
4761
|
-
legend: "Evidence",
|
|
4762
|
-
children: evidence.map((item) => /* @__PURE__ */ jsx(CheckRow, {
|
|
4763
|
-
isChecked: chosenEvidenceIds.has(item.id),
|
|
4764
|
-
label: `${formatClock(item.atMs)} · ${evidenceCaption(item)}`,
|
|
4765
|
-
onToggle: () => toggleEvidence(item.id)
|
|
4766
|
-
}, item.id))
|
|
4767
|
-
})] });
|
|
4400
|
+
function isHidden() {
|
|
4401
|
+
return typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
4768
4402
|
}
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4403
|
+
function usePollTick(lastAnswer) {
|
|
4404
|
+
const [tick, setTick] = useState(0);
|
|
4405
|
+
useEffect(() => {
|
|
4406
|
+
if (lastAnswer.kind !== "ready" || !isDetailProcessing(lastAnswer.detail)) return;
|
|
4407
|
+
let timer = 0;
|
|
4408
|
+
const schedule = () => {
|
|
4409
|
+
window.clearTimeout(timer);
|
|
4410
|
+
if (!isHidden()) timer = window.setTimeout(() => setTick((current) => current + 1), POLL_INTERVAL_MS);
|
|
4411
|
+
};
|
|
4412
|
+
schedule();
|
|
4413
|
+
document.addEventListener("visibilitychange", schedule);
|
|
4414
|
+
return () => {
|
|
4415
|
+
window.clearTimeout(timer);
|
|
4416
|
+
document.removeEventListener("visibilitychange", schedule);
|
|
4417
|
+
};
|
|
4418
|
+
}, [lastAnswer]);
|
|
4419
|
+
return tick;
|
|
4420
|
+
}
|
|
4421
|
+
function failedState(error, current) {
|
|
4422
|
+
if (error instanceof SessionApiError && error.status === 404) return { kind: "missing" };
|
|
4423
|
+
if (current.kind === "ready") return current;
|
|
4788
4424
|
return {
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
saveBlob({
|
|
4792
|
-
blob: await buildBriefZip({
|
|
4793
|
-
brief: handoff.brief,
|
|
4794
|
-
files
|
|
4795
|
-
}),
|
|
4796
|
-
fileName: zipFileName(options.title)
|
|
4797
|
-
});
|
|
4798
|
-
})
|
|
4425
|
+
kind: "failed",
|
|
4426
|
+
message: failureMessage(error)
|
|
4799
4427
|
};
|
|
4800
4428
|
}
|
|
4801
|
-
function
|
|
4802
|
-
const {
|
|
4803
|
-
|
|
4804
|
-
|
|
4429
|
+
function useLandedUploadTick() {
|
|
4430
|
+
const { account } = useSessionWorkspace();
|
|
4431
|
+
const { pendingOperations } = useSyncStatus(account.key);
|
|
4432
|
+
const [seen, setSeen] = useState({
|
|
4433
|
+
pending: pendingOperations,
|
|
4434
|
+
tick: 0
|
|
4805
4435
|
});
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
value: prepared.handoff.brief
|
|
4812
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
4813
|
-
className: "dt-actions",
|
|
4814
|
-
children: [
|
|
4815
|
-
/* @__PURE__ */ jsx("button", {
|
|
4816
|
-
className: "dt-btn",
|
|
4817
|
-
"data-variant": "primary",
|
|
4818
|
-
onClick: copy,
|
|
4819
|
-
type: "button",
|
|
4820
|
-
children: "Copy brief"
|
|
4821
|
-
}),
|
|
4822
|
-
/* @__PURE__ */ jsx("button", {
|
|
4823
|
-
className: "dt-btn",
|
|
4824
|
-
onClick: exportZip,
|
|
4825
|
-
type: "button",
|
|
4826
|
-
children: "Export .zip"
|
|
4827
|
-
}),
|
|
4828
|
-
/* @__PURE__ */ jsx("button", {
|
|
4829
|
-
className: "dt-btn",
|
|
4830
|
-
onClick: onChangeSelection,
|
|
4831
|
-
type: "button",
|
|
4832
|
-
children: "Change selection"
|
|
4833
|
-
})
|
|
4834
|
-
]
|
|
4835
|
-
})] });
|
|
4436
|
+
if (seen.pending !== pendingOperations) setSeen({
|
|
4437
|
+
pending: pendingOperations,
|
|
4438
|
+
tick: pendingOperations < seen.pending ? seen.tick + 1 : seen.tick
|
|
4439
|
+
});
|
|
4440
|
+
return seen.tick;
|
|
4836
4441
|
}
|
|
4837
|
-
function
|
|
4838
|
-
const { api } = useSessionWorkspace();
|
|
4839
|
-
const
|
|
4840
|
-
|
|
4841
|
-
|
|
4442
|
+
function useSessionDetail(sessionId) {
|
|
4443
|
+
const { api, onUnauthorized } = useSessionWorkspace();
|
|
4444
|
+
const [state, setState] = useState({ kind: "loading" });
|
|
4445
|
+
const [request, setRequest] = useState({
|
|
4446
|
+
count: 0,
|
|
4447
|
+
sessionId
|
|
4448
|
+
});
|
|
4449
|
+
const pollTick = usePollTick(state);
|
|
4450
|
+
const uploadTick = useLandedUploadTick();
|
|
4451
|
+
useEffect(() => {
|
|
4452
|
+
let isCurrent = true;
|
|
4453
|
+
api.detail(request.sessionId).then((detail) => isCurrent && setState({
|
|
4454
|
+
detail,
|
|
4455
|
+
kind: "ready"
|
|
4456
|
+
}), (error) => {
|
|
4457
|
+
if (isUnauthorized(error)) {
|
|
4458
|
+
onUnauthorized();
|
|
4459
|
+
return;
|
|
4460
|
+
}
|
|
4461
|
+
if (isCurrent) setState((current) => failedState(error, current));
|
|
4462
|
+
const isRefresh = request.count + pollTick + uploadTick > 0;
|
|
4463
|
+
if (isCurrent && isRefresh) reportFailure("The session did not refresh", error);
|
|
4464
|
+
});
|
|
4465
|
+
return () => {
|
|
4466
|
+
isCurrent = false;
|
|
4467
|
+
};
|
|
4468
|
+
}, [
|
|
4469
|
+
api,
|
|
4470
|
+
onUnauthorized,
|
|
4471
|
+
request,
|
|
4472
|
+
pollTick,
|
|
4473
|
+
uploadTick
|
|
4474
|
+
]);
|
|
4475
|
+
return {
|
|
4476
|
+
patch: (update) => setState((current) => current.kind === "ready" ? {
|
|
4477
|
+
detail: update(current.detail),
|
|
4478
|
+
kind: "ready"
|
|
4479
|
+
} : current),
|
|
4480
|
+
reload: () => setRequest(nextRequest),
|
|
4481
|
+
state
|
|
4842
4482
|
};
|
|
4843
4483
|
}
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
const [prepared, setPrepared] = useState(null);
|
|
4852
|
-
const [isPreparing, setIsPreparing] = useState(false);
|
|
4853
|
-
const prepare = async () => {
|
|
4854
|
-
setIsPreparing(true);
|
|
4855
|
-
const result = await run("The brief was not prepared", () => api.createHandoff({
|
|
4856
|
-
clientKey: request.clientKey,
|
|
4857
|
-
sessionId: options.detail.session.id,
|
|
4858
|
-
...request.selection
|
|
4859
|
-
}));
|
|
4860
|
-
setIsPreparing(false);
|
|
4861
|
-
if (result) {
|
|
4862
|
-
setPrepared(result);
|
|
4863
|
-
options.review.reload();
|
|
4864
|
-
}
|
|
4865
|
-
};
|
|
4484
|
+
//#endregion
|
|
4485
|
+
//#region src/sessions/ui/review/proposals/proposal-editor.tsx
|
|
4486
|
+
const MAX_LIST_ITEMS = 8;
|
|
4487
|
+
function lines(text) {
|
|
4488
|
+
return text.split("\n").map((line) => line.trim()).filter((line) => line !== "").slice(0, MAX_LIST_ITEMS);
|
|
4489
|
+
}
|
|
4490
|
+
function editBody(proposal, draft) {
|
|
4866
4491
|
return {
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
}),
|
|
4875
|
-
selection: request.selection
|
|
4876
|
-
};
|
|
4877
|
-
}
|
|
4878
|
-
function SelectionStep({ detail, handoff }) {
|
|
4879
|
-
const createFeedback = useInternalFeedback(handoff.selection.proposalIds);
|
|
4880
|
-
const hasProposals = handoff.selection.proposalIds.length > 0;
|
|
4881
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4882
|
-
/* @__PURE__ */ jsx("p", {
|
|
4883
|
-
className: "dt-hint",
|
|
4884
|
-
children: "Coding agents get exactly the brief and files you pick here."
|
|
4885
|
-
}),
|
|
4886
|
-
/* @__PURE__ */ jsx(HandoffChoices, {
|
|
4887
|
-
detail,
|
|
4888
|
-
onChange: handoff.select,
|
|
4889
|
-
selection: handoff.selection
|
|
4890
|
-
}),
|
|
4891
|
-
/* @__PURE__ */ jsx(ChangedSinceBriefs, {
|
|
4892
|
-
detail,
|
|
4893
|
-
proposalIds: handoff.selection.proposalIds
|
|
4894
|
-
}),
|
|
4895
|
-
/* @__PURE__ */ jsxs("div", {
|
|
4896
|
-
className: "dt-actions",
|
|
4897
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
4898
|
-
className: "dt-btn",
|
|
4899
|
-
"data-variant": "primary",
|
|
4900
|
-
disabled: !hasProposals || handoff.isPreparing,
|
|
4901
|
-
onClick: handoff.prepare,
|
|
4902
|
-
type: "button",
|
|
4903
|
-
children: "Prepare brief"
|
|
4904
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
4905
|
-
className: "dt-btn",
|
|
4906
|
-
disabled: !hasProposals,
|
|
4907
|
-
onClick: createFeedback,
|
|
4908
|
-
type: "button",
|
|
4909
|
-
children: "Create internal feedback"
|
|
4910
|
-
})]
|
|
4911
|
-
})
|
|
4912
|
-
] });
|
|
4913
|
-
}
|
|
4914
|
-
function HandoffView({ detail, onClose, review }) {
|
|
4915
|
-
const handoff = usePrepareHandoff({
|
|
4916
|
-
detail,
|
|
4917
|
-
review
|
|
4918
|
-
});
|
|
4919
|
-
return /* @__PURE__ */ jsxs("section", {
|
|
4920
|
-
"aria-labelledby": "rf-handoff-title",
|
|
4921
|
-
className: "dt-ses-handoff",
|
|
4922
|
-
children: [
|
|
4923
|
-
/* @__PURE__ */ jsx("button", {
|
|
4924
|
-
className: "dt-ses-link",
|
|
4925
|
-
onClick: onClose,
|
|
4926
|
-
type: "button",
|
|
4927
|
-
children: "← Back to review"
|
|
4928
|
-
}),
|
|
4929
|
-
/* @__PURE__ */ jsx("h2", {
|
|
4930
|
-
className: "dt-ses-title",
|
|
4931
|
-
id: "rf-handoff-title",
|
|
4932
|
-
children: "Hand off"
|
|
4933
|
-
}),
|
|
4934
|
-
handoff.prepared ? /* @__PURE__ */ jsx(PreparedBrief, {
|
|
4935
|
-
onChangeSelection: handoff.clear,
|
|
4936
|
-
prepared: handoff.prepared,
|
|
4937
|
-
title: detail.session.title
|
|
4938
|
-
}) : /* @__PURE__ */ jsx(SelectionStep, {
|
|
4939
|
-
detail,
|
|
4940
|
-
handoff
|
|
4941
|
-
}),
|
|
4942
|
-
/* @__PURE__ */ jsx("p", {
|
|
4943
|
-
className: "dt-meta",
|
|
4944
|
-
children: "Copied or exported briefs can't be recalled."
|
|
4945
|
-
}),
|
|
4946
|
-
/* @__PURE__ */ jsx(PreviousBriefs, { handoffs: detail.handoffs })
|
|
4947
|
-
]
|
|
4948
|
-
});
|
|
4949
|
-
}
|
|
4950
|
-
//#endregion
|
|
4951
|
-
//#region src/sessions/ui/review/guarded-save.tsx
|
|
4952
|
-
function useGuardedSave() {
|
|
4953
|
-
const { onUnauthorized } = useSessionWorkspace();
|
|
4954
|
-
const [problem, setProblem] = useState(null);
|
|
4955
|
-
const [isSaving, setIsSaving] = useState(false);
|
|
4956
|
-
const save = async (write) => {
|
|
4957
|
-
setIsSaving(true);
|
|
4958
|
-
setProblem(null);
|
|
4959
|
-
try {
|
|
4960
|
-
await write();
|
|
4961
|
-
} catch (error) {
|
|
4962
|
-
if (isUnauthorized(error)) onUnauthorized();
|
|
4963
|
-
else if (error instanceof SessionApiError && error.status === 409) setProblem({ kind: "stale" });
|
|
4964
|
-
else setProblem({
|
|
4965
|
-
kind: "failed",
|
|
4966
|
-
message: failureMessage(error)
|
|
4967
|
-
});
|
|
4968
|
-
}
|
|
4969
|
-
setIsSaving(false);
|
|
4970
|
-
};
|
|
4971
|
-
return {
|
|
4972
|
-
isSaving,
|
|
4973
|
-
problem,
|
|
4974
|
-
save
|
|
4975
|
-
};
|
|
4976
|
-
}
|
|
4977
|
-
function SaveProblemMessage({ onReload, problem }) {
|
|
4978
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
4979
|
-
className: "dt-actions",
|
|
4980
|
-
role: "alert",
|
|
4981
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
4982
|
-
className: "dt-error",
|
|
4983
|
-
children: problem.kind === "stale" ? "Someone changed this since you opened it. Reload it, then edit again." : `Not saved: ${problem.message}`
|
|
4984
|
-
}), problem.kind === "stale" && /* @__PURE__ */ jsx("button", {
|
|
4985
|
-
className: "dt-btn",
|
|
4986
|
-
onClick: onReload,
|
|
4987
|
-
type: "button",
|
|
4988
|
-
children: "Reload"
|
|
4989
|
-
})]
|
|
4990
|
-
});
|
|
4991
|
-
}
|
|
4992
|
-
//#endregion
|
|
4993
|
-
//#region src/sessions/ui/review/use-session-detail.ts
|
|
4994
|
-
const POLL_INTERVAL_MS = 2e3;
|
|
4995
|
-
function nextRequest(current) {
|
|
4996
|
-
return {
|
|
4997
|
-
...current,
|
|
4998
|
-
count: current.count + 1
|
|
4999
|
-
};
|
|
5000
|
-
}
|
|
5001
|
-
function withProposal(detail, proposal) {
|
|
5002
|
-
const isKnown = detail.proposals.some((item) => item.id === proposal.id);
|
|
5003
|
-
return {
|
|
5004
|
-
...detail,
|
|
5005
|
-
proposals: isKnown ? detail.proposals.map((item) => item.id === proposal.id ? proposal : item) : [...detail.proposals, proposal]
|
|
5006
|
-
};
|
|
5007
|
-
}
|
|
5008
|
-
function withSegment(detail, segment) {
|
|
5009
|
-
const others = detail.segments.filter((item) => item.id !== segment.id);
|
|
5010
|
-
return {
|
|
5011
|
-
...detail,
|
|
5012
|
-
segments: [...others, segment].sort((a, b) => a.startMs - b.startMs)
|
|
5013
|
-
};
|
|
5014
|
-
}
|
|
5015
|
-
function withEvidence(detail, evidence) {
|
|
5016
|
-
return {
|
|
5017
|
-
...detail,
|
|
5018
|
-
evidence: detail.evidence.map((item) => item.id === evidence.id ? evidence : item)
|
|
5019
|
-
};
|
|
5020
|
-
}
|
|
5021
|
-
function isHidden() {
|
|
5022
|
-
return typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
5023
|
-
}
|
|
5024
|
-
function usePollTick(lastAnswer) {
|
|
5025
|
-
const [tick, setTick] = useState(0);
|
|
5026
|
-
useEffect(() => {
|
|
5027
|
-
if (lastAnswer.kind !== "ready" || !isDetailProcessing(lastAnswer.detail)) return;
|
|
5028
|
-
let timer = 0;
|
|
5029
|
-
const schedule = () => {
|
|
5030
|
-
window.clearTimeout(timer);
|
|
5031
|
-
if (!isHidden()) timer = window.setTimeout(() => setTick((current) => current + 1), POLL_INTERVAL_MS);
|
|
5032
|
-
};
|
|
5033
|
-
schedule();
|
|
5034
|
-
document.addEventListener("visibilitychange", schedule);
|
|
5035
|
-
return () => {
|
|
5036
|
-
window.clearTimeout(timer);
|
|
5037
|
-
document.removeEventListener("visibilitychange", schedule);
|
|
5038
|
-
};
|
|
5039
|
-
}, [lastAnswer]);
|
|
5040
|
-
return tick;
|
|
5041
|
-
}
|
|
5042
|
-
function failedState(error, current) {
|
|
5043
|
-
if (error instanceof SessionApiError && error.status === 404) return { kind: "missing" };
|
|
5044
|
-
if (current.kind === "ready") return current;
|
|
5045
|
-
return {
|
|
5046
|
-
kind: "failed",
|
|
5047
|
-
message: failureMessage(error)
|
|
5048
|
-
};
|
|
5049
|
-
}
|
|
5050
|
-
function useLandedUploadTick() {
|
|
5051
|
-
const { account } = useSessionWorkspace();
|
|
5052
|
-
const { pendingOperations } = useSyncStatus(account.key);
|
|
5053
|
-
const [seen, setSeen] = useState({
|
|
5054
|
-
pending: pendingOperations,
|
|
5055
|
-
tick: 0
|
|
5056
|
-
});
|
|
5057
|
-
if (seen.pending !== pendingOperations) setSeen({
|
|
5058
|
-
pending: pendingOperations,
|
|
5059
|
-
tick: pendingOperations < seen.pending ? seen.tick + 1 : seen.tick
|
|
5060
|
-
});
|
|
5061
|
-
return seen.tick;
|
|
5062
|
-
}
|
|
5063
|
-
function useSessionDetail(sessionId) {
|
|
5064
|
-
const { api, onUnauthorized } = useSessionWorkspace();
|
|
5065
|
-
const [state, setState] = useState({ kind: "loading" });
|
|
5066
|
-
const [request, setRequest] = useState({
|
|
5067
|
-
count: 0,
|
|
5068
|
-
sessionId
|
|
5069
|
-
});
|
|
5070
|
-
const pollTick = usePollTick(state);
|
|
5071
|
-
const uploadTick = useLandedUploadTick();
|
|
5072
|
-
useEffect(() => {
|
|
5073
|
-
let isCurrent = true;
|
|
5074
|
-
api.detail(request.sessionId).then((detail) => isCurrent && setState({
|
|
5075
|
-
detail,
|
|
5076
|
-
kind: "ready"
|
|
5077
|
-
}), (error) => {
|
|
5078
|
-
if (isUnauthorized(error)) {
|
|
5079
|
-
onUnauthorized();
|
|
5080
|
-
return;
|
|
5081
|
-
}
|
|
5082
|
-
if (isCurrent) setState((current) => failedState(error, current));
|
|
5083
|
-
const isRefresh = request.count + pollTick + uploadTick > 0;
|
|
5084
|
-
if (isCurrent && isRefresh) reportFailure("The session did not refresh", error);
|
|
5085
|
-
});
|
|
5086
|
-
return () => {
|
|
5087
|
-
isCurrent = false;
|
|
5088
|
-
};
|
|
5089
|
-
}, [
|
|
5090
|
-
api,
|
|
5091
|
-
onUnauthorized,
|
|
5092
|
-
request,
|
|
5093
|
-
pollTick,
|
|
5094
|
-
uploadTick
|
|
5095
|
-
]);
|
|
5096
|
-
return {
|
|
5097
|
-
patch: (update) => setState((current) => current.kind === "ready" ? {
|
|
5098
|
-
detail: update(current.detail),
|
|
5099
|
-
kind: "ready"
|
|
5100
|
-
} : current),
|
|
5101
|
-
reload: () => setRequest(nextRequest),
|
|
5102
|
-
state
|
|
5103
|
-
};
|
|
5104
|
-
}
|
|
5105
|
-
//#endregion
|
|
5106
|
-
//#region src/sessions/ui/review/proposals/proposal-editor.tsx
|
|
5107
|
-
const MAX_LIST_ITEMS = 8;
|
|
5108
|
-
function lines(text) {
|
|
5109
|
-
return text.split("\n").map((line) => line.trim()).filter((line) => line !== "").slice(0, MAX_LIST_ITEMS);
|
|
5110
|
-
}
|
|
5111
|
-
function editBody(proposal, draft) {
|
|
5112
|
-
return {
|
|
5113
|
-
expectedRevision: proposal.revision,
|
|
5114
|
-
need: draft.need.trim(),
|
|
5115
|
-
observed: draft.observed.trim(),
|
|
5116
|
-
proposalId: proposal.id,
|
|
5117
|
-
response: draft.response.trim() || null,
|
|
5118
|
-
setAside: lines(draft.setAside),
|
|
5119
|
-
unknowns: lines(draft.unknowns)
|
|
4492
|
+
expectedRevision: proposal.revision,
|
|
4493
|
+
need: draft.need.trim(),
|
|
4494
|
+
observed: draft.observed.trim(),
|
|
4495
|
+
proposalId: proposal.id,
|
|
4496
|
+
response: draft.response.trim() || null,
|
|
4497
|
+
setAside: lines(draft.setAside),
|
|
4498
|
+
unknowns: lines(draft.unknowns)
|
|
5120
4499
|
};
|
|
5121
4500
|
}
|
|
5122
4501
|
function TextField({ label, maxLength, onChange, rows, value }) {
|
|
@@ -5880,7 +5259,7 @@ function UpdateCard({ context, continuation }) {
|
|
|
5880
5259
|
}
|
|
5881
5260
|
//#endregion
|
|
5882
5261
|
//#region src/sessions/ui/review/transcript/remove-evidence.tsx
|
|
5883
|
-
const REMOVE_COPY = "Remove this screenshot? The image is deleted for good. Briefs you already
|
|
5262
|
+
const REMOVE_COPY = "Remove this screenshot? The image is deleted for good. Briefs you already downloaded keep their copy.";
|
|
5884
5263
|
function useFocusWhen(shouldFocus) {
|
|
5885
5264
|
const ref = useRef(null);
|
|
5886
5265
|
useEffect(() => {
|
|
@@ -6412,7 +5791,7 @@ function MomentHeading({ onClose, segment }) {
|
|
|
6412
5791
|
})]
|
|
6413
5792
|
});
|
|
6414
5793
|
}
|
|
6415
|
-
function useEscapeToClose(onClose) {
|
|
5794
|
+
function useEscapeToClose$1(onClose) {
|
|
6416
5795
|
const sectionRef = useRef(null);
|
|
6417
5796
|
const onCloseRef = useRef(onClose);
|
|
6418
5797
|
useLayoutEffect(() => {
|
|
@@ -6434,7 +5813,7 @@ function useEscapeToClose(onClose) {
|
|
|
6434
5813
|
function MomentView({ handlers, segmentId, session }) {
|
|
6435
5814
|
const { detail, review } = session;
|
|
6436
5815
|
const segment = detail.segments.find((item) => item.id === segmentId);
|
|
6437
|
-
const sectionRef = useEscapeToClose(handlers.onClose);
|
|
5816
|
+
const sectionRef = useEscapeToClose$1(handlers.onClose);
|
|
6438
5817
|
return /* @__PURE__ */ jsxs("section", {
|
|
6439
5818
|
"aria-label": "Moment",
|
|
6440
5819
|
className: "dt-ses-moment",
|
|
@@ -6873,6 +6252,50 @@ function ScreenReport({ context, report }) {
|
|
|
6873
6252
|
})] });
|
|
6874
6253
|
}
|
|
6875
6254
|
//#endregion
|
|
6255
|
+
//#region src/devtools/client/devtools-icons.tsx
|
|
6256
|
+
function NotesIcon() {
|
|
6257
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "M8 6h13M8 12h13M8 18h13M3.5 6h.01M3.5 12h.01M3.5 18h.01" }) });
|
|
6258
|
+
}
|
|
6259
|
+
function InboxIcon() {
|
|
6260
|
+
return /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("path", { d: "M22 12h-6l-2 3h-4l-2-3H2" }), /* @__PURE__ */ jsx("path", { d: "M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" })] });
|
|
6261
|
+
}
|
|
6262
|
+
function PanelIcon() {
|
|
6263
|
+
return /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("rect", {
|
|
6264
|
+
height: "16",
|
|
6265
|
+
rx: "2.5",
|
|
6266
|
+
width: "18",
|
|
6267
|
+
x: "3",
|
|
6268
|
+
y: "4"
|
|
6269
|
+
}), /* @__PURE__ */ jsx("path", { d: "M14 4v16" })] });
|
|
6270
|
+
}
|
|
6271
|
+
function CodeIcon() {
|
|
6272
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m8 7-5 5 5 5M16 7l5 5-5 5" }) });
|
|
6273
|
+
}
|
|
6274
|
+
function RefreshIcon() {
|
|
6275
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "M20 11a8 8 0 0 0-14.5-4.5L4 8M4 4v4h4M4 13a8 8 0 0 0 14.5 4.5L20 16M20 20v-4h-4" }) });
|
|
6276
|
+
}
|
|
6277
|
+
function ChevronLeftIcon() {
|
|
6278
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m15 6-6 6 6 6" }) });
|
|
6279
|
+
}
|
|
6280
|
+
function ChevronUpDownIcon() {
|
|
6281
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m8 10 4-4 4 4M8 14l4 4 4-4" }) });
|
|
6282
|
+
}
|
|
6283
|
+
function ViewOptionsIcon() {
|
|
6284
|
+
return /* @__PURE__ */ jsxs(Svg, { children: [
|
|
6285
|
+
/* @__PURE__ */ jsx("path", { d: "M4 7h10M18 7h2M4 17h2M10 17h10" }),
|
|
6286
|
+
/* @__PURE__ */ jsx("circle", {
|
|
6287
|
+
cx: "16",
|
|
6288
|
+
cy: "7",
|
|
6289
|
+
r: "2"
|
|
6290
|
+
}),
|
|
6291
|
+
/* @__PURE__ */ jsx("circle", {
|
|
6292
|
+
cx: "8",
|
|
6293
|
+
cy: "17",
|
|
6294
|
+
r: "2"
|
|
6295
|
+
})
|
|
6296
|
+
] });
|
|
6297
|
+
}
|
|
6298
|
+
//#endregion
|
|
6876
6299
|
//#region src/sessions/ui/start/session-disclosure.tsx
|
|
6877
6300
|
const SEEN_KEY_PREFIX = "reflet-sessions-disclosure:";
|
|
6878
6301
|
function hasSeenDisclosure(accountKey) {
|
|
@@ -6960,21 +6383,22 @@ function StartProblem({ failure, onRetry, onWriteNote }) {
|
|
|
6960
6383
|
})]
|
|
6961
6384
|
});
|
|
6962
6385
|
}
|
|
6963
|
-
function StartActions({ isBusy, onStart
|
|
6386
|
+
function StartActions({ isBusy, onStart }) {
|
|
6964
6387
|
return /* @__PURE__ */ jsxs("div", {
|
|
6965
|
-
className: "dt-
|
|
6966
|
-
children: [/* @__PURE__ */ jsx("
|
|
6967
|
-
className: "dt-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6388
|
+
className: "dt-ses-start",
|
|
6389
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
6390
|
+
className: "dt-meta",
|
|
6391
|
+
children: "Talk while you use the app. Reflet turns what you say and show into intentions you can brief an agent with."
|
|
6392
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
6393
|
+
className: "dt-actions",
|
|
6394
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
6395
|
+
className: "dt-btn",
|
|
6396
|
+
"data-variant": "primary",
|
|
6397
|
+
disabled: isBusy,
|
|
6398
|
+
onClick: onStart,
|
|
6399
|
+
type: "button",
|
|
6400
|
+
children: [/* @__PURE__ */ jsx(MicIcon, {}), "Start session"]
|
|
6401
|
+
})
|
|
6978
6402
|
})]
|
|
6979
6403
|
});
|
|
6980
6404
|
}
|
|
@@ -7006,19 +6430,21 @@ function MicrophonePrompt({ isRequesting }) {
|
|
|
7006
6430
|
function StartSession({ onStarted, onWriteNote }) {
|
|
7007
6431
|
const { account } = useSessionWorkspace();
|
|
7008
6432
|
const { failure, isBusy, isRequesting, start } = useRecorderStart(onStarted);
|
|
6433
|
+
const [isFirstVisit] = useState(() => !hasSeenDisclosure(account.key));
|
|
7009
6434
|
const startBlank = () => start({});
|
|
6435
|
+
const disclosure = /* @__PURE__ */ jsx(SessionDisclosure, { accountKey: account.key });
|
|
7010
6436
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7011
|
-
|
|
7012
|
-
/* @__PURE__ */ jsx(MicrophonePrompt, { isRequesting }),
|
|
6437
|
+
isFirstVisit && disclosure,
|
|
7013
6438
|
failure ? /* @__PURE__ */ jsx(StartProblem, {
|
|
7014
6439
|
failure,
|
|
7015
6440
|
onRetry: startBlank,
|
|
7016
6441
|
onWriteNote
|
|
7017
6442
|
}) : /* @__PURE__ */ jsx(StartActions, {
|
|
7018
6443
|
isBusy,
|
|
7019
|
-
onStart: startBlank
|
|
7020
|
-
|
|
7021
|
-
})
|
|
6444
|
+
onStart: startBlank
|
|
6445
|
+
}),
|
|
6446
|
+
/* @__PURE__ */ jsx(MicrophonePrompt, { isRequesting }),
|
|
6447
|
+
!isFirstVisit && disclosure
|
|
7022
6448
|
] });
|
|
7023
6449
|
}
|
|
7024
6450
|
//#endregion
|
|
@@ -7103,15 +6529,44 @@ function useDecide(review) {
|
|
|
7103
6529
|
});
|
|
7104
6530
|
};
|
|
7105
6531
|
}
|
|
7106
|
-
function
|
|
7107
|
-
|
|
6532
|
+
function withFeedbackIds(feedbackIds) {
|
|
6533
|
+
return (detail) => ({
|
|
6534
|
+
...detail,
|
|
6535
|
+
proposals: detail.proposals.map((item) => {
|
|
6536
|
+
const feedbackId = feedbackIds.get(item.id);
|
|
6537
|
+
return feedbackId ? {
|
|
6538
|
+
...item,
|
|
6539
|
+
feedbackId
|
|
6540
|
+
} : item;
|
|
6541
|
+
})
|
|
6542
|
+
});
|
|
6543
|
+
}
|
|
6544
|
+
function useAddToBoard(review) {
|
|
6545
|
+
const { api } = useSessionWorkspace();
|
|
6546
|
+
const run = useSessionAction();
|
|
6547
|
+
return async (proposals) => {
|
|
6548
|
+
const created = await Promise.all(proposals.map(async (proposal) => {
|
|
6549
|
+
const result = await run(`${quotedNeed(proposal.need)} was not added to the board`, () => api.createFeedback(proposal.id));
|
|
6550
|
+
return result ? [proposal.id, result.feedbackId] : null;
|
|
6551
|
+
}));
|
|
6552
|
+
const added = new Map(created.flatMap((entry) => entry ? [entry] : []));
|
|
6553
|
+
if (added.size === 0) return;
|
|
6554
|
+
review.patch(withFeedbackIds(added));
|
|
6555
|
+
const onlyAdded = added.size === 1 ? proposals.find((proposal) => added.has(proposal.id)) : void 0;
|
|
6556
|
+
announce(onlyAdded ? `Added ${quotedNeed(onlyAdded.need)} to the board` : `Added ${countLabel(added.size, "intention")} to the board`);
|
|
6557
|
+
};
|
|
6558
|
+
}
|
|
6559
|
+
function useProposalActions(review) {
|
|
6560
|
+
const save = useProposalSave(review);
|
|
6561
|
+
const decide = useDecide(review);
|
|
7108
6562
|
return {
|
|
6563
|
+
addToBoard: useAddToBoard(review),
|
|
7109
6564
|
clarify: (proposal, text) => save("The precision was not sent", (client) => client.clarifyProposal({
|
|
7110
6565
|
expectedRevision: proposal.revision,
|
|
7111
6566
|
proposalId: proposal.id,
|
|
7112
6567
|
text
|
|
7113
6568
|
})),
|
|
7114
|
-
decide
|
|
6569
|
+
decide,
|
|
7115
6570
|
merge: async (targetId, sourceIds) => {
|
|
7116
6571
|
if (await save("The intentions were not merged", (client) => client.mergeProposals({
|
|
7117
6572
|
sourceIds,
|
|
@@ -7129,7 +6584,7 @@ function useProposalActions(review) {
|
|
|
7129
6584
|
}
|
|
7130
6585
|
//#endregion
|
|
7131
6586
|
//#region src/sessions/ui/review/proposals/delete-intention.tsx
|
|
7132
|
-
const DELETE_INTENTION_COPY = "Delete this intention? What later sessions added to it
|
|
6587
|
+
const DELETE_INTENTION_COPY = "Delete this intention? What later sessions added to it goes too, and so do the briefs Reflet saved that include it. Briefs you already copied or downloaded keep their text.";
|
|
7133
6588
|
function DeleteConfirmation$1({ context, onCancel, proposal }) {
|
|
7134
6589
|
const { api } = useSessionWorkspace();
|
|
7135
6590
|
const run = useSessionAction();
|
|
@@ -7640,8 +7095,8 @@ const ICON_DECISIONS = [{
|
|
|
7640
7095
|
function ProposalChips({ proposal }) {
|
|
7641
7096
|
const decisionChip = DECISION_CHIPS[proposal.decision];
|
|
7642
7097
|
const { handedOffRevision } = proposal;
|
|
7643
|
-
let
|
|
7644
|
-
if (handedOffRevision !== null)
|
|
7098
|
+
let briefChip = null;
|
|
7099
|
+
if (handedOffRevision !== null) briefChip = proposal.revision > handedOffRevision ? "Changed since brief" : "In a brief";
|
|
7645
7100
|
return /* @__PURE__ */ jsxs("div", {
|
|
7646
7101
|
className: "dt-ses-chips",
|
|
7647
7102
|
children: [
|
|
@@ -7662,9 +7117,13 @@ function ProposalChips({ proposal }) {
|
|
|
7662
7117
|
"data-tone": "accent",
|
|
7663
7118
|
children: "To re-examine"
|
|
7664
7119
|
}),
|
|
7665
|
-
|
|
7120
|
+
briefChip && /* @__PURE__ */ jsx("span", {
|
|
7666
7121
|
className: "dt-chip",
|
|
7667
|
-
children:
|
|
7122
|
+
children: briefChip
|
|
7123
|
+
}),
|
|
7124
|
+
proposal.feedbackId !== null && /* @__PURE__ */ jsx("span", {
|
|
7125
|
+
className: "dt-chip",
|
|
7126
|
+
children: "On the board"
|
|
7668
7127
|
})
|
|
7669
7128
|
]
|
|
7670
7129
|
});
|
|
@@ -7741,6 +7200,15 @@ function DecisionButtons({ context, onEdit, proposal }) {
|
|
|
7741
7200
|
title: "Edit",
|
|
7742
7201
|
type: "button",
|
|
7743
7202
|
children: /* @__PURE__ */ jsx(PencilIcon, {})
|
|
7203
|
+
}),
|
|
7204
|
+
proposal.feedbackId === null && proposal.decision !== "dismissed" && /* @__PURE__ */ jsx("button", {
|
|
7205
|
+
"aria-label": "Add to board",
|
|
7206
|
+
className: "dt-btn",
|
|
7207
|
+
"data-icon-only": true,
|
|
7208
|
+
onClick: () => context.actions.addToBoard([proposal]),
|
|
7209
|
+
title: "Add to board",
|
|
7210
|
+
type: "button",
|
|
7211
|
+
children: /* @__PURE__ */ jsx(InboxIcon, {})
|
|
7744
7212
|
})
|
|
7745
7213
|
]
|
|
7746
7214
|
});
|
|
@@ -7896,13 +7364,6 @@ function ProposalCard({ context, proposal }) {
|
|
|
7896
7364
|
}
|
|
7897
7365
|
//#endregion
|
|
7898
7366
|
//#region src/sessions/ui/review/proposals/proposals-tab.tsx
|
|
7899
|
-
const VIEW_OPTIONS = [{
|
|
7900
|
-
label: "On screen",
|
|
7901
|
-
value: "screens"
|
|
7902
|
-
}, {
|
|
7903
|
-
label: "Details",
|
|
7904
|
-
value: "cards"
|
|
7905
|
-
}];
|
|
7906
7367
|
function emptyCopy(detail) {
|
|
7907
7368
|
const { session } = detail;
|
|
7908
7369
|
if (session.collection !== "ended") return "Intentions appear here once the recording has uploaded and Reflet has read it.";
|
|
@@ -7971,25 +7432,12 @@ function AddProposalForm({ context, onDone }) {
|
|
|
7971
7432
|
]
|
|
7972
7433
|
});
|
|
7973
7434
|
}
|
|
7974
|
-
function
|
|
7975
|
-
return /* @__PURE__ */ jsx("div", {
|
|
7976
|
-
className: "dt-tabs",
|
|
7977
|
-
children: VIEW_OPTIONS.map((option) => /* @__PURE__ */ jsx("button", {
|
|
7978
|
-
"aria-pressed": option.value === view,
|
|
7979
|
-
className: "dt-tab",
|
|
7980
|
-
onClick: () => onSelect(option.value),
|
|
7981
|
-
type: "button",
|
|
7982
|
-
children: option.label
|
|
7983
|
-
}, option.value))
|
|
7984
|
-
});
|
|
7985
|
-
}
|
|
7986
|
-
function ProposalsTab({ context, onSelectView, view }) {
|
|
7435
|
+
function ProposalsTab({ context, view }) {
|
|
7987
7436
|
const [isAdding, setIsAdding] = useState(false);
|
|
7988
7437
|
const proposals = context.detail.proposals.filter((proposal) => proposal.mergedIntoId === null);
|
|
7989
7438
|
const { continuation } = context.detail;
|
|
7990
7439
|
const report = calloutReport(context.detail);
|
|
7991
|
-
const
|
|
7992
|
-
const showsScreens = hasScreens && view === "screens";
|
|
7440
|
+
const showsScreens = report.screens.length > 0 && view === "screens";
|
|
7993
7441
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7994
7442
|
continuation && /* @__PURE__ */ jsx(UpdateCard, {
|
|
7995
7443
|
context,
|
|
@@ -7999,10 +7447,6 @@ function ProposalsTab({ context, onSelectView, view }) {
|
|
|
7999
7447
|
className: "dt-empty",
|
|
8000
7448
|
children: emptyCopy(context.detail)
|
|
8001
7449
|
}),
|
|
8002
|
-
hasScreens && /* @__PURE__ */ jsx(ViewSwitch, {
|
|
8003
|
-
onSelect: onSelectView,
|
|
8004
|
-
view
|
|
8005
|
-
}),
|
|
8006
7450
|
showsScreens && /* @__PURE__ */ jsx(ScreenReport, {
|
|
8007
7451
|
context,
|
|
8008
7452
|
report
|
|
@@ -8026,8 +7470,199 @@ function ProposalsTab({ context, onSelectView, view }) {
|
|
|
8026
7470
|
] });
|
|
8027
7471
|
}
|
|
8028
7472
|
//#endregion
|
|
7473
|
+
//#region src/sessions/ui/review/review-footer.tsx
|
|
7474
|
+
function ReviewFooter({ context, onOpenBrief }) {
|
|
7475
|
+
const confirmed = keptProposals(context.detail);
|
|
7476
|
+
const offBoard = confirmed.filter((proposal) => proposal.feedbackId === null);
|
|
7477
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7478
|
+
className: "dt-sheet-foot",
|
|
7479
|
+
children: [
|
|
7480
|
+
/* @__PURE__ */ jsxs("button", {
|
|
7481
|
+
"aria-describedby": confirmed.length === 0 ? "rf-brief-hint" : void 0,
|
|
7482
|
+
className: "dt-btn",
|
|
7483
|
+
"data-variant": "primary",
|
|
7484
|
+
disabled: confirmed.length === 0,
|
|
7485
|
+
onClick: onOpenBrief,
|
|
7486
|
+
type: "button",
|
|
7487
|
+
children: ["Prepare brief", confirmed.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
7488
|
+
className: "dt-btn-count",
|
|
7489
|
+
children: confirmed.length
|
|
7490
|
+
})]
|
|
7491
|
+
}),
|
|
7492
|
+
offBoard.length > 0 && /* @__PURE__ */ jsxs("button", {
|
|
7493
|
+
className: "dt-btn",
|
|
7494
|
+
onClick: () => context.actions.addToBoard(offBoard),
|
|
7495
|
+
type: "button",
|
|
7496
|
+
children: [
|
|
7497
|
+
"Add ",
|
|
7498
|
+
offBoard.length,
|
|
7499
|
+
" to board"
|
|
7500
|
+
]
|
|
7501
|
+
}),
|
|
7502
|
+
confirmed.length === 0 && /* @__PURE__ */ jsx("span", {
|
|
7503
|
+
className: "dt-status",
|
|
7504
|
+
id: "rf-brief-hint",
|
|
7505
|
+
children: "Confirm an intention to brief your agent or add it to the board"
|
|
7506
|
+
})
|
|
7507
|
+
]
|
|
7508
|
+
});
|
|
7509
|
+
}
|
|
7510
|
+
//#endregion
|
|
7511
|
+
//#region src/devtools/client/focused-element.ts
|
|
7512
|
+
function focusedElementAround(node) {
|
|
7513
|
+
const scope = node.getRootNode();
|
|
7514
|
+
return scope instanceof ShadowRoot || scope instanceof Document ? scope.activeElement : null;
|
|
7515
|
+
}
|
|
7516
|
+
//#endregion
|
|
7517
|
+
//#region src/devtools/client/menu.tsx
|
|
7518
|
+
const MENU_ITEM_SELECTOR = "[role^=\"menuitem\"]";
|
|
7519
|
+
function nextIndex(key, current, count) {
|
|
7520
|
+
if (key === "ArrowDown") return (current + 1) % count;
|
|
7521
|
+
if (key === "ArrowUp") return (current - 1 + count) % count;
|
|
7522
|
+
if (key === "Home") return 0;
|
|
7523
|
+
if (key === "End") return count - 1;
|
|
7524
|
+
return null;
|
|
7525
|
+
}
|
|
7526
|
+
function useCloseOnOutsidePointer(containerRef, options) {
|
|
7527
|
+
const closeRef = useRef(options.close);
|
|
7528
|
+
useLayoutEffect(() => {
|
|
7529
|
+
closeRef.current = options.close;
|
|
7530
|
+
});
|
|
7531
|
+
const { isOpen } = options;
|
|
7532
|
+
useEffect(() => {
|
|
7533
|
+
if (!isOpen) return;
|
|
7534
|
+
const closeOnOutsidePointer = (event) => {
|
|
7535
|
+
const container = containerRef.current;
|
|
7536
|
+
if (container && !event.composedPath().includes(container)) closeRef.current();
|
|
7537
|
+
};
|
|
7538
|
+
document.addEventListener("pointerdown", closeOnOutsidePointer, true);
|
|
7539
|
+
return () => document.removeEventListener("pointerdown", closeOnOutsidePointer, true);
|
|
7540
|
+
}, [containerRef, isOpen]);
|
|
7541
|
+
}
|
|
7542
|
+
function useFocusOnOpen(listRef, isOpen) {
|
|
7543
|
+
useLayoutEffect(() => {
|
|
7544
|
+
const list = listRef.current;
|
|
7545
|
+
if (!(isOpen && list)) return;
|
|
7546
|
+
const items = [...list.querySelectorAll(MENU_ITEM_SELECTOR)];
|
|
7547
|
+
(items.find((item) => item.getAttribute("aria-checked") === "true") ?? items[0])?.focus({ preventScroll: true });
|
|
7548
|
+
}, [isOpen, listRef]);
|
|
7549
|
+
}
|
|
7550
|
+
/** Native: the panel's Escape listener shares the shadow root with React's, and runs before React's handler. */
|
|
7551
|
+
function useEscapeToClose(listRef, options) {
|
|
7552
|
+
const { isOpen, onEscape } = options;
|
|
7553
|
+
useEffect(() => {
|
|
7554
|
+
const list = listRef.current;
|
|
7555
|
+
if (!(isOpen && list)) return;
|
|
7556
|
+
const closeOnEscape = (event) => {
|
|
7557
|
+
if (event.key === "Escape" && !event.isComposing) {
|
|
7558
|
+
event.stopPropagation();
|
|
7559
|
+
onEscape();
|
|
7560
|
+
}
|
|
7561
|
+
};
|
|
7562
|
+
list.addEventListener("keydown", closeOnEscape);
|
|
7563
|
+
return () => list.removeEventListener("keydown", closeOnEscape);
|
|
7564
|
+
}, [
|
|
7565
|
+
isOpen,
|
|
7566
|
+
listRef,
|
|
7567
|
+
onEscape
|
|
7568
|
+
]);
|
|
7569
|
+
}
|
|
7570
|
+
function MenuItemButton({ hasChoices, item, onChosen }) {
|
|
7571
|
+
const select = () => {
|
|
7572
|
+
onChosen();
|
|
7573
|
+
item.onSelect();
|
|
7574
|
+
};
|
|
7575
|
+
if (!hasChoices) return /* @__PURE__ */ jsx("button", {
|
|
7576
|
+
className: "dt-menu-item",
|
|
7577
|
+
"data-variant": item.variant,
|
|
7578
|
+
onClick: select,
|
|
7579
|
+
role: "menuitem",
|
|
7580
|
+
tabIndex: -1,
|
|
7581
|
+
type: "button",
|
|
7582
|
+
children: item.label
|
|
7583
|
+
});
|
|
7584
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
7585
|
+
"aria-checked": item.checked === true,
|
|
7586
|
+
className: "dt-menu-item",
|
|
7587
|
+
onClick: select,
|
|
7588
|
+
role: "menuitemradio",
|
|
7589
|
+
tabIndex: -1,
|
|
7590
|
+
type: "button",
|
|
7591
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
7592
|
+
className: "dt-menu-check",
|
|
7593
|
+
children: item.checked && /* @__PURE__ */ jsx(CheckIcon, { size: 14 })
|
|
7594
|
+
}), item.label]
|
|
7595
|
+
});
|
|
7596
|
+
}
|
|
7597
|
+
function Menu({ items, placement = "below", trigger }) {
|
|
7598
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
7599
|
+
const menuId = useId();
|
|
7600
|
+
const containerRef = useRef(null);
|
|
7601
|
+
const triggerRef = useRef(null);
|
|
7602
|
+
const listRef = useRef(null);
|
|
7603
|
+
const close = () => setIsOpen(false);
|
|
7604
|
+
const closeAndRefocus = () => {
|
|
7605
|
+
close();
|
|
7606
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
7607
|
+
};
|
|
7608
|
+
useCloseOnOutsidePointer(containerRef, {
|
|
7609
|
+
close,
|
|
7610
|
+
isOpen
|
|
7611
|
+
});
|
|
7612
|
+
useFocusOnOpen(listRef, isOpen);
|
|
7613
|
+
useEscapeToClose(listRef, {
|
|
7614
|
+
isOpen,
|
|
7615
|
+
onEscape: closeAndRefocus
|
|
7616
|
+
});
|
|
7617
|
+
const hasChoices = items.some((item) => item.checked !== void 0);
|
|
7618
|
+
const moveWithKeys = (event) => {
|
|
7619
|
+
if (event.key === "Tab") {
|
|
7620
|
+
close();
|
|
7621
|
+
return;
|
|
7622
|
+
}
|
|
7623
|
+
const list = event.currentTarget;
|
|
7624
|
+
const options = [...list.querySelectorAll(MENU_ITEM_SELECTOR)];
|
|
7625
|
+
const focused = focusedElementAround(list);
|
|
7626
|
+
const current = focused instanceof HTMLElement ? options.indexOf(focused) : -1;
|
|
7627
|
+
const index = nextIndex(event.key, current, options.length);
|
|
7628
|
+
if (index !== null) {
|
|
7629
|
+
event.preventDefault();
|
|
7630
|
+
options[index]?.focus();
|
|
7631
|
+
}
|
|
7632
|
+
};
|
|
7633
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7634
|
+
className: "dt-menu",
|
|
7635
|
+
ref: containerRef,
|
|
7636
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
7637
|
+
"aria-controls": isOpen ? menuId : void 0,
|
|
7638
|
+
"aria-expanded": isOpen,
|
|
7639
|
+
"aria-haspopup": "menu",
|
|
7640
|
+
"aria-label": trigger.label,
|
|
7641
|
+
className: trigger.className,
|
|
7642
|
+
onClick: () => setIsOpen(!isOpen),
|
|
7643
|
+
ref: triggerRef,
|
|
7644
|
+
title: trigger.label,
|
|
7645
|
+
type: "button",
|
|
7646
|
+
children: trigger.content
|
|
7647
|
+
}), isOpen && /* @__PURE__ */ jsx("div", {
|
|
7648
|
+
"aria-label": trigger.label,
|
|
7649
|
+
className: "dt-menu-list",
|
|
7650
|
+
"data-placement": placement,
|
|
7651
|
+
id: menuId,
|
|
7652
|
+
onKeyDown: moveWithKeys,
|
|
7653
|
+
ref: listRef,
|
|
7654
|
+
role: "menu",
|
|
7655
|
+
children: items.map((item) => /* @__PURE__ */ jsx(MenuItemButton, {
|
|
7656
|
+
hasChoices,
|
|
7657
|
+
item,
|
|
7658
|
+
onChosen: closeAndRefocus
|
|
7659
|
+
}, item.label))
|
|
7660
|
+
})]
|
|
7661
|
+
});
|
|
7662
|
+
}
|
|
7663
|
+
//#endregion
|
|
8029
7664
|
//#region src/sessions/ui/review/review-header.tsx
|
|
8030
|
-
const DELETE_COPY = "Delete this session? Its
|
|
7665
|
+
const DELETE_COPY = "Delete this session? Its recording, transcript, screenshots and intentions go, along with what later sessions added to those intentions.";
|
|
8031
7666
|
function withSessionFields(change) {
|
|
8032
7667
|
return (detail) => ({
|
|
8033
7668
|
...detail,
|
|
@@ -8124,94 +7759,29 @@ function DeleteConfirmation({ onCancel, onDeleted, sessionId }) {
|
|
|
8124
7759
|
})]
|
|
8125
7760
|
});
|
|
8126
7761
|
}
|
|
8127
|
-
function
|
|
8128
|
-
const containerRef = useRef(null);
|
|
8129
|
-
const closeRef = useRef(close);
|
|
8130
|
-
useLayoutEffect(() => {
|
|
8131
|
-
closeRef.current = close;
|
|
8132
|
-
});
|
|
8133
|
-
useEffect(() => {
|
|
8134
|
-
if (!isOpen) return;
|
|
8135
|
-
const container = containerRef.current;
|
|
8136
|
-
const closeOnOutsidePointer = (event) => {
|
|
8137
|
-
if (container && !event.composedPath().includes(container)) closeRef.current();
|
|
8138
|
-
};
|
|
8139
|
-
const closeOnEscape = (event) => {
|
|
8140
|
-
if (event instanceof KeyboardEvent && event.key === "Escape") {
|
|
8141
|
-
event.stopPropagation();
|
|
8142
|
-
closeRef.current();
|
|
8143
|
-
}
|
|
8144
|
-
};
|
|
8145
|
-
document.addEventListener("pointerdown", closeOnOutsidePointer, true);
|
|
8146
|
-
container?.addEventListener("keydown", closeOnEscape);
|
|
8147
|
-
return () => {
|
|
8148
|
-
document.removeEventListener("pointerdown", closeOnOutsidePointer, true);
|
|
8149
|
-
container?.removeEventListener("keydown", closeOnEscape);
|
|
8150
|
-
};
|
|
8151
|
-
}, [isOpen]);
|
|
8152
|
-
return containerRef;
|
|
8153
|
-
}
|
|
8154
|
-
function SessionMenu({ actions, isShared }) {
|
|
8155
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
8156
|
-
const menuId = useId();
|
|
8157
|
-
const close = () => setIsOpen(false);
|
|
8158
|
-
const containerRef = useDismissOnOutside(isOpen, close);
|
|
8159
|
-
const choose = (action) => () => {
|
|
8160
|
-
close();
|
|
8161
|
-
action();
|
|
8162
|
-
};
|
|
8163
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
8164
|
-
className: "dt-ses-menu",
|
|
8165
|
-
ref: containerRef,
|
|
8166
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
8167
|
-
"aria-controls": menuId,
|
|
8168
|
-
"aria-expanded": isOpen,
|
|
8169
|
-
"aria-label": "Session options",
|
|
8170
|
-
className: "icon-btn",
|
|
8171
|
-
onClick: () => setIsOpen(!isOpen),
|
|
8172
|
-
type: "button",
|
|
8173
|
-
children: /* @__PURE__ */ jsx(MoreIcon, {})
|
|
8174
|
-
}), isOpen && /* @__PURE__ */ jsxs("div", {
|
|
8175
|
-
className: "dt-ses-menu-list",
|
|
8176
|
-
id: menuId,
|
|
8177
|
-
children: [
|
|
8178
|
-
/* @__PURE__ */ jsx("button", {
|
|
8179
|
-
className: "dt-ses-menu-item",
|
|
8180
|
-
onClick: choose(actions.onRename),
|
|
8181
|
-
type: "button",
|
|
8182
|
-
children: "Rename"
|
|
8183
|
-
}),
|
|
8184
|
-
/* @__PURE__ */ jsx("button", {
|
|
8185
|
-
className: "dt-ses-menu-item",
|
|
8186
|
-
onClick: choose(actions.onToggleSharing),
|
|
8187
|
-
type: "button",
|
|
8188
|
-
children: isShared ? "Make private" : "Share with team"
|
|
8189
|
-
}),
|
|
8190
|
-
/* @__PURE__ */ jsx("button", {
|
|
8191
|
-
className: "dt-ses-menu-item",
|
|
8192
|
-
"data-variant": "danger",
|
|
8193
|
-
onClick: choose(actions.onDelete),
|
|
8194
|
-
type: "button",
|
|
8195
|
-
children: "Delete session"
|
|
8196
|
-
})
|
|
8197
|
-
]
|
|
8198
|
-
})]
|
|
8199
|
-
});
|
|
8200
|
-
}
|
|
8201
|
-
function ReviewHeader({ onBack, review, session }) {
|
|
7762
|
+
function ReviewHeader({ onDeleted, review, session }) {
|
|
8202
7763
|
const [isRenaming, setIsRenaming] = useState(false);
|
|
8203
7764
|
const [isConfirmingDelete, setIsConfirmingDelete] = useState(false);
|
|
8204
7765
|
const update = useSessionUpdate(review, session);
|
|
8205
7766
|
const isShared = session.visibility === "team";
|
|
7767
|
+
const menuItems = [
|
|
7768
|
+
{
|
|
7769
|
+
label: "Rename",
|
|
7770
|
+
onSelect: () => setIsRenaming(true)
|
|
7771
|
+
},
|
|
7772
|
+
{
|
|
7773
|
+
label: isShared ? "Make private" : "Share with team",
|
|
7774
|
+
onSelect: () => update("The sharing was not changed", { visibility: isShared ? "private" : "team" })
|
|
7775
|
+
},
|
|
7776
|
+
{
|
|
7777
|
+
label: "Delete session",
|
|
7778
|
+
onSelect: () => setIsConfirmingDelete(true),
|
|
7779
|
+
variant: "danger"
|
|
7780
|
+
}
|
|
7781
|
+
];
|
|
8206
7782
|
return /* @__PURE__ */ jsxs("header", {
|
|
8207
7783
|
className: "dt-ses-head",
|
|
8208
7784
|
children: [
|
|
8209
|
-
/* @__PURE__ */ jsx("button", {
|
|
8210
|
-
className: "dt-ses-link",
|
|
8211
|
-
onClick: onBack,
|
|
8212
|
-
type: "button",
|
|
8213
|
-
children: "← All sessions"
|
|
8214
|
-
}),
|
|
8215
7785
|
isRenaming ? /* @__PURE__ */ jsx(TitleEditor, {
|
|
8216
7786
|
onDone: () => setIsRenaming(false),
|
|
8217
7787
|
review,
|
|
@@ -8220,14 +7790,15 @@ function ReviewHeader({ onBack, review, session }) {
|
|
|
8220
7790
|
className: "dt-card-head",
|
|
8221
7791
|
children: [/* @__PURE__ */ jsx("h2", {
|
|
8222
7792
|
className: "dt-ses-title",
|
|
7793
|
+
tabIndex: -1,
|
|
8223
7794
|
children: session.title
|
|
8224
|
-
}), session.canEdit && /* @__PURE__ */ jsx(
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
7795
|
+
}), session.canEdit && /* @__PURE__ */ jsx(Menu, {
|
|
7796
|
+
items: menuItems,
|
|
7797
|
+
trigger: {
|
|
7798
|
+
className: "icon-btn",
|
|
7799
|
+
content: /* @__PURE__ */ jsx(MoreIcon, {}),
|
|
7800
|
+
label: "Session options"
|
|
7801
|
+
}
|
|
8231
7802
|
})]
|
|
8232
7803
|
}),
|
|
8233
7804
|
/* @__PURE__ */ jsxs("p", {
|
|
@@ -8244,13 +7815,83 @@ function ReviewHeader({ onBack, review, session }) {
|
|
|
8244
7815
|
}),
|
|
8245
7816
|
isConfirmingDelete && session.canEdit && /* @__PURE__ */ jsx(DeleteConfirmation, {
|
|
8246
7817
|
onCancel: () => setIsConfirmingDelete(false),
|
|
8247
|
-
onDeleted
|
|
7818
|
+
onDeleted,
|
|
8248
7819
|
sessionId: session.id
|
|
8249
7820
|
})
|
|
8250
7821
|
]
|
|
8251
7822
|
});
|
|
8252
7823
|
}
|
|
8253
7824
|
//#endregion
|
|
7825
|
+
//#region src/sessions/ui/review/review-tabs.tsx
|
|
7826
|
+
const INTENTION_VIEWS = [{
|
|
7827
|
+
label: "On screen",
|
|
7828
|
+
value: "screens"
|
|
7829
|
+
}, {
|
|
7830
|
+
label: "Details",
|
|
7831
|
+
value: "cards"
|
|
7832
|
+
}];
|
|
7833
|
+
function IntentionViewMenu({ place }) {
|
|
7834
|
+
return /* @__PURE__ */ jsx(Menu, {
|
|
7835
|
+
items: INTENTION_VIEWS.map((option) => ({
|
|
7836
|
+
checked: option.value === place.intentionView,
|
|
7837
|
+
label: option.label,
|
|
7838
|
+
onSelect: () => place.selectIntentionView(option.value)
|
|
7839
|
+
})),
|
|
7840
|
+
trigger: {
|
|
7841
|
+
className: "icon-btn",
|
|
7842
|
+
content: /* @__PURE__ */ jsx(ViewOptionsIcon, {}),
|
|
7843
|
+
label: "Show intentions"
|
|
7844
|
+
}
|
|
7845
|
+
});
|
|
7846
|
+
}
|
|
7847
|
+
function tabOptions(detail) {
|
|
7848
|
+
return [
|
|
7849
|
+
{
|
|
7850
|
+
count: detail.proposals.filter((proposal) => proposal.mergedIntoId === null && proposal.attachment === null).length,
|
|
7851
|
+
icon: /* @__PURE__ */ jsx(IntentionIcon, {}),
|
|
7852
|
+
label: "Intentions",
|
|
7853
|
+
value: "proposals"
|
|
7854
|
+
},
|
|
7855
|
+
{
|
|
7856
|
+
count: null,
|
|
7857
|
+
icon: /* @__PURE__ */ jsx(TranscriptIcon, {}),
|
|
7858
|
+
label: "Transcript",
|
|
7859
|
+
value: "transcript"
|
|
7860
|
+
},
|
|
7861
|
+
{
|
|
7862
|
+
count: detail.evidence.length,
|
|
7863
|
+
icon: /* @__PURE__ */ jsx(ImageIcon, {}),
|
|
7864
|
+
label: "Evidence",
|
|
7865
|
+
value: "evidence"
|
|
7866
|
+
}
|
|
7867
|
+
];
|
|
7868
|
+
}
|
|
7869
|
+
function ReviewTabs({ detail, place }) {
|
|
7870
|
+
const canPickView = place.tab === "proposals" && calloutReport(detail).screens.length > 0;
|
|
7871
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7872
|
+
className: "dt-toolbar",
|
|
7873
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
7874
|
+
className: "dt-tabs",
|
|
7875
|
+
role: "tablist",
|
|
7876
|
+
children: tabOptions(detail).map((option) => /* @__PURE__ */ jsxs("button", {
|
|
7877
|
+
"aria-selected": option.value === place.tab,
|
|
7878
|
+
className: "dt-tab",
|
|
7879
|
+
onClick: () => place.selectTab(option.value),
|
|
7880
|
+
role: "tab",
|
|
7881
|
+
type: "button",
|
|
7882
|
+
children: [
|
|
7883
|
+
option.icon,
|
|
7884
|
+
option.label,
|
|
7885
|
+
option.count !== null && /* @__PURE__ */ jsx("span", {
|
|
7886
|
+
className: "dt-tab-count",
|
|
7887
|
+
children: option.count
|
|
7888
|
+
})
|
|
7889
|
+
]
|
|
7890
|
+
}, option.value))
|
|
7891
|
+
}), canPickView && /* @__PURE__ */ jsx(IntentionViewMenu, { place })]
|
|
7892
|
+
});
|
|
7893
|
+
}
|
|
7894
|
+
//#endregion
|
|
8254
7895
|
//#region src/sessions/ui/review/status-strip.tsx
|
|
8255
7896
|
function transcribingLine(detail) {
|
|
8256
7897
|
const voice = detail.segments.filter((segment) => segment.source === "voice");
|
|
@@ -8995,56 +8636,10 @@ function TranscriptTab({ detail, onShowMoment, review }) {
|
|
|
8995
8636
|
}
|
|
8996
8637
|
//#endregion
|
|
8997
8638
|
//#region src/sessions/ui/review/session-review.tsx
|
|
8998
|
-
function HandoffFooter({ detail, onHandOff }) {
|
|
8999
|
-
const confirmed = detail.proposals.filter((proposal) => proposal.decision === "kept" && proposal.mergedIntoId === null).length;
|
|
9000
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
9001
|
-
className: "dt-sheet-foot",
|
|
9002
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
9003
|
-
"aria-describedby": confirmed === 0 ? "rf-handoff-hint" : void 0,
|
|
9004
|
-
className: "dt-btn",
|
|
9005
|
-
"data-variant": "primary",
|
|
9006
|
-
disabled: confirmed === 0,
|
|
9007
|
-
onClick: onHandOff,
|
|
9008
|
-
type: "button",
|
|
9009
|
-
children: confirmed === 0 ? "Hand off" : `Hand off ${confirmed} confirmed`
|
|
9010
|
-
}), confirmed === 0 && /* @__PURE__ */ jsx("span", {
|
|
9011
|
-
className: "dt-status",
|
|
9012
|
-
id: "rf-handoff-hint",
|
|
9013
|
-
children: "Confirm an intention to hand it off"
|
|
9014
|
-
})]
|
|
9015
|
-
});
|
|
9016
|
-
}
|
|
9017
|
-
function ReviewTabs({ detail, onSelect, tab }) {
|
|
9018
|
-
const options = [
|
|
9019
|
-
{
|
|
9020
|
-
label: `Intentions (${detail.proposals.filter((proposal) => proposal.mergedIntoId === null && proposal.attachment === null).length})`,
|
|
9021
|
-
value: "proposals"
|
|
9022
|
-
},
|
|
9023
|
-
{
|
|
9024
|
-
label: "Transcript",
|
|
9025
|
-
value: "transcript"
|
|
9026
|
-
},
|
|
9027
|
-
{
|
|
9028
|
-
label: `Evidence (${detail.evidence.length})`,
|
|
9029
|
-
value: "evidence"
|
|
9030
|
-
}
|
|
9031
|
-
];
|
|
9032
|
-
return /* @__PURE__ */ jsx("div", {
|
|
9033
|
-
className: "dt-tabs dt-ses-tabs",
|
|
9034
|
-
children: options.map((option) => /* @__PURE__ */ jsx("button", {
|
|
9035
|
-
"aria-pressed": option.value === tab,
|
|
9036
|
-
className: "dt-tab",
|
|
9037
|
-
onClick: () => onSelect(option.value),
|
|
9038
|
-
type: "button",
|
|
9039
|
-
children: option.label
|
|
9040
|
-
}, option.value))
|
|
9041
|
-
});
|
|
9042
|
-
}
|
|
9043
8639
|
function ReviewTabPanel({ context, place }) {
|
|
9044
8640
|
const { detail, navigation, review } = context;
|
|
9045
8641
|
if (place.tab === "proposals") return /* @__PURE__ */ jsx(ProposalsTab, {
|
|
9046
8642
|
context,
|
|
9047
|
-
onSelectView: place.selectIntentionView,
|
|
9048
8643
|
view: place.intentionView
|
|
9049
8644
|
});
|
|
9050
8645
|
if (place.tab === "transcript") return /* @__PURE__ */ jsx(TranscriptTab, {
|
|
@@ -9103,8 +8698,7 @@ function ReviewPanels({ context, place }) {
|
|
|
9103
8698
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9104
8699
|
/* @__PURE__ */ jsx(ReviewTabs, {
|
|
9105
8700
|
detail,
|
|
9106
|
-
|
|
9107
|
-
tab: place.tab
|
|
8701
|
+
place
|
|
9108
8702
|
}),
|
|
9109
8703
|
/* @__PURE__ */ jsx("div", {
|
|
9110
8704
|
className: "dt-ses-panel",
|
|
@@ -9132,7 +8726,7 @@ function ReviewTop({ context, links }) {
|
|
|
9132
8726
|
const { detail, review } = context;
|
|
9133
8727
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9134
8728
|
/* @__PURE__ */ jsx(ReviewHeader, {
|
|
9135
|
-
|
|
8729
|
+
onDeleted: links.onDeleted,
|
|
9136
8730
|
review,
|
|
9137
8731
|
session: detail.session
|
|
9138
8732
|
}),
|
|
@@ -9146,9 +8740,8 @@ function ReviewTop({ context, links }) {
|
|
|
9146
8740
|
})
|
|
9147
8741
|
] });
|
|
9148
8742
|
}
|
|
9149
|
-
function ReviewScreen({ detail, links, review }) {
|
|
8743
|
+
function ReviewScreen({ detail, isBriefOpen, links, review }) {
|
|
9150
8744
|
const place = useReviewPlace();
|
|
9151
|
-
const [isHandingOff, setIsHandingOff] = useState(false);
|
|
9152
8745
|
const context = {
|
|
9153
8746
|
actions: useProposalActions(review),
|
|
9154
8747
|
canEdit: detail.session.canEdit,
|
|
@@ -9162,9 +8755,8 @@ function ReviewScreen({ detail, links, review }) {
|
|
|
9162
8755
|
},
|
|
9163
8756
|
review
|
|
9164
8757
|
};
|
|
9165
|
-
if (
|
|
8758
|
+
if (isBriefOpen) return /* @__PURE__ */ jsx(HandoffView, {
|
|
9166
8759
|
detail,
|
|
9167
|
-
onClose: () => setIsHandingOff(false),
|
|
9168
8760
|
review
|
|
9169
8761
|
});
|
|
9170
8762
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -9176,13 +8768,13 @@ function ReviewScreen({ detail, links, review }) {
|
|
|
9176
8768
|
context,
|
|
9177
8769
|
place
|
|
9178
8770
|
}),
|
|
9179
|
-
context.canEdit && /* @__PURE__ */ jsx(
|
|
9180
|
-
|
|
9181
|
-
|
|
8771
|
+
context.canEdit && /* @__PURE__ */ jsx(ReviewFooter, {
|
|
8772
|
+
context,
|
|
8773
|
+
onOpenBrief: links.onOpenBrief
|
|
9182
8774
|
})
|
|
9183
8775
|
] });
|
|
9184
8776
|
}
|
|
9185
|
-
function SessionReview({ links, sessionId }) {
|
|
8777
|
+
function SessionReview({ isBriefOpen, links, sessionId }) {
|
|
9186
8778
|
const handle = useSessionDetail(sessionId);
|
|
9187
8779
|
const { state } = handle;
|
|
9188
8780
|
if (state.kind === "loading") return /* @__PURE__ */ jsx("p", {
|
|
@@ -9191,24 +8783,22 @@ function SessionReview({ links, sessionId }) {
|
|
|
9191
8783
|
});
|
|
9192
8784
|
if (state.kind === "ready") return /* @__PURE__ */ jsx(ReviewScreen, {
|
|
9193
8785
|
detail: state.detail,
|
|
8786
|
+
isBriefOpen,
|
|
9194
8787
|
links,
|
|
9195
8788
|
review: handle
|
|
9196
8789
|
});
|
|
8790
|
+
if (state.kind === "missing") return /* @__PURE__ */ jsx("p", {
|
|
8791
|
+
className: "dt-empty",
|
|
8792
|
+
children: "This session is gone: it was deleted or is no longer shared with you."
|
|
8793
|
+
});
|
|
9197
8794
|
return /* @__PURE__ */ jsxs("div", {
|
|
9198
8795
|
className: "dt-empty",
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
children: "Try again"
|
|
9206
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
9207
|
-
className: "dt-btn",
|
|
9208
|
-
onClick: links.onBack,
|
|
9209
|
-
type: "button",
|
|
9210
|
-
children: "All sessions"
|
|
9211
|
-
})]
|
|
8796
|
+
role: "alert",
|
|
8797
|
+
children: [/* @__PURE__ */ jsxs("p", { children: ["The session did not load: ", state.message] }), /* @__PURE__ */ jsx("button", {
|
|
8798
|
+
className: "dt-btn",
|
|
8799
|
+
onClick: handle.reload,
|
|
8800
|
+
type: "button",
|
|
8801
|
+
children: "Try again"
|
|
9212
8802
|
})]
|
|
9213
8803
|
});
|
|
9214
8804
|
}
|
|
@@ -9335,7 +8925,7 @@ function SessionList({ drafts, onOpen }) {
|
|
|
9335
8925
|
interruptedIds,
|
|
9336
8926
|
onOpen,
|
|
9337
8927
|
sessions: mine,
|
|
9338
|
-
title: "
|
|
8928
|
+
title: "Your sessions"
|
|
9339
8929
|
}),
|
|
9340
8930
|
/* @__PURE__ */ jsx(SessionGroup, {
|
|
9341
8931
|
interruptedIds,
|
|
@@ -9398,17 +8988,7 @@ function SessionsHome({ onOpenSession, onStarted, onWriteNote }) {
|
|
|
9398
8988
|
const { account } = useSessionWorkspace();
|
|
9399
8989
|
const drafts = useLocalDrafts(account.key);
|
|
9400
8990
|
const interrupted = drafts.filter((draft) => draft.state === "interrupted");
|
|
9401
|
-
const name = account.userName ?? account.userEmail ?? "you";
|
|
9402
8991
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9403
|
-
/* @__PURE__ */ jsxs("p", {
|
|
9404
|
-
className: "dt-meta",
|
|
9405
|
-
children: [
|
|
9406
|
-
"Recording as ",
|
|
9407
|
-
name,
|
|
9408
|
-
" · ",
|
|
9409
|
-
account.organizationName
|
|
9410
|
-
]
|
|
9411
|
-
}),
|
|
9412
8992
|
interrupted.map((draft) => /* @__PURE__ */ jsx(InterruptedDraft, {
|
|
9413
8993
|
draft,
|
|
9414
8994
|
onOpenSession,
|
|
@@ -9426,6 +9006,32 @@ function SessionsHome({ onOpenSession, onStarted, onWriteNote }) {
|
|
|
9426
9006
|
}
|
|
9427
9007
|
//#endregion
|
|
9428
9008
|
//#region src/sessions/ui/sessions-panel.tsx
|
|
9009
|
+
const SESSIONS_HOME = { view: "home" };
|
|
9010
|
+
function useSessionNavigation() {
|
|
9011
|
+
const [place, setPlace] = useState(SESSIONS_HOME);
|
|
9012
|
+
return {
|
|
9013
|
+
go: setPlace,
|
|
9014
|
+
place
|
|
9015
|
+
};
|
|
9016
|
+
}
|
|
9017
|
+
/** Where the panel header's back button leads; null on the sessions home. */
|
|
9018
|
+
function sessionSheetPlace({ go, place }) {
|
|
9019
|
+
if (place.view === "home") return null;
|
|
9020
|
+
const sessionRef = place.target.sessionId ?? place.target.sessionKey ?? "";
|
|
9021
|
+
if (place.view === "review") return {
|
|
9022
|
+
backLabel: "Sessions",
|
|
9023
|
+
id: `review:${sessionRef}`,
|
|
9024
|
+
onBack: () => go(SESSIONS_HOME)
|
|
9025
|
+
};
|
|
9026
|
+
return {
|
|
9027
|
+
backLabel: "Session",
|
|
9028
|
+
id: `brief:${sessionRef}`,
|
|
9029
|
+
onBack: () => go({
|
|
9030
|
+
target: place.target,
|
|
9031
|
+
view: "review"
|
|
9032
|
+
})
|
|
9033
|
+
};
|
|
9034
|
+
}
|
|
9429
9035
|
function useResolvedSessionId(target) {
|
|
9430
9036
|
const { account } = useSessionWorkspace();
|
|
9431
9037
|
const drafts = useLocalDrafts(account.key);
|
|
@@ -9434,36 +9040,822 @@ function useResolvedSessionId(target) {
|
|
|
9434
9040
|
}
|
|
9435
9041
|
/** A just-finished session may not have reached Reflet yet: it opens once its id is known. */
|
|
9436
9042
|
function SessionsPanel({ navigation, onStarted, onWriteNote }) {
|
|
9437
|
-
const
|
|
9438
|
-
const
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
}, sessionId);
|
|
9450
|
-
if (navigation.open) return /* @__PURE__ */ jsxs("div", {
|
|
9043
|
+
const { go, place } = navigation;
|
|
9044
|
+
const target = place.view === "home" ? null : place.target;
|
|
9045
|
+
const sessionId = useResolvedSessionId(target);
|
|
9046
|
+
if (!target) return /* @__PURE__ */ jsx(SessionsHome, {
|
|
9047
|
+
onOpenSession: (opened) => go({
|
|
9048
|
+
target: opened,
|
|
9049
|
+
view: "review"
|
|
9050
|
+
}),
|
|
9051
|
+
onStarted,
|
|
9052
|
+
onWriteNote
|
|
9053
|
+
});
|
|
9054
|
+
if (!sessionId) return /* @__PURE__ */ jsx("p", {
|
|
9451
9055
|
className: "dt-empty",
|
|
9452
9056
|
role: "status",
|
|
9453
|
-
children:
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9057
|
+
children: "This session is still uploading. It opens here once it reaches Reflet."
|
|
9058
|
+
});
|
|
9059
|
+
return /* @__PURE__ */ jsx(SessionReview, {
|
|
9060
|
+
isBriefOpen: place.view === "brief",
|
|
9061
|
+
links: {
|
|
9062
|
+
onDeleted: () => go(SESSIONS_HOME),
|
|
9063
|
+
onOpenBrief: () => go({
|
|
9064
|
+
target,
|
|
9065
|
+
view: "brief"
|
|
9066
|
+
}),
|
|
9067
|
+
onOpenSession: (openedId) => go({
|
|
9068
|
+
target: {
|
|
9069
|
+
sessionId: openedId,
|
|
9070
|
+
sessionKey: null
|
|
9071
|
+
},
|
|
9072
|
+
view: "review"
|
|
9073
|
+
}),
|
|
9074
|
+
onStarted
|
|
9075
|
+
},
|
|
9076
|
+
sessionId
|
|
9077
|
+
}, sessionId);
|
|
9078
|
+
}
|
|
9079
|
+
//#endregion
|
|
9080
|
+
//#region src/sessions/ui/intention-styles.ts
|
|
9081
|
+
const INTENTION_STYLES = `
|
|
9082
|
+
.dt-ses-panel { display: contents; }
|
|
9083
|
+
.dt-ses-panel[hidden] { display: none; }
|
|
9084
|
+
.dt-ses-moment, .dt-ses-moment-section, .dt-ses-block, .dt-ses-change, .dt-ses-history { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
9085
|
+
.dt-ses-moment-item { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); }
|
|
9086
|
+
.dt-ses-moment-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; overflow-wrap: anywhere; }
|
|
9087
|
+
.dt-ses-moment-quote { display: flex; flex-direction: column; gap: 2px; margin: 0; padding-left: 10px; border-left: 2px solid var(--rf-border); overflow-wrap: anywhere; }
|
|
9088
|
+
.dt-ses-moment-notices { color: var(--rf-text-muted); font-size: 12px; }
|
|
9089
|
+
.dt-ses-moment-shot { display: flex; flex-direction: column; gap: 4px; margin: 0; max-width: 100%; }
|
|
9090
|
+
.dt-ses-shot-mark[data-match="approximate"] { border-style: dashed; }
|
|
9091
|
+
.dt-ses-shot-pointer {
|
|
9092
|
+
position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
|
|
9093
|
+
background: var(--rf-accent); box-shadow: 0 0 0 2px var(--rf-bg); pointer-events: none;
|
|
9094
|
+
}
|
|
9095
|
+
.dt-ses-source { margin: 0; font-size: 12px; overflow-wrap: anywhere; }
|
|
9096
|
+
.dt-ses-context-line { display: block; }
|
|
9097
|
+
.dt-ses-attached { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px; }
|
|
9098
|
+
.dt-ses-attached p { margin: 0; }
|
|
9099
|
+
.dt-ses-history[data-removed="true"] > .dt-ses-subhead { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9100
|
+
.dt-ses-change { padding: 8px 10px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); list-style: none; }
|
|
9101
|
+
.dt-ses-change[data-decision="rejected"] .dt-ses-diff { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9102
|
+
.dt-ses-diff { display: grid; grid-template-columns: auto 1fr; gap: 2px 8px; margin: 0; overflow-wrap: anywhere; }
|
|
9103
|
+
p.dt-ses-diff { display: block; }
|
|
9104
|
+
.dt-ses-diff dd { margin: 0; }
|
|
9105
|
+
.dt-card:focus-visible { outline: 2px solid var(--rf-accent); outline-offset: 2px; }
|
|
9106
|
+
`;
|
|
9107
|
+
//#endregion
|
|
9108
|
+
//#region src/sessions/ui/review/screens/report-styles.ts
|
|
9109
|
+
const REPORT_STYLES = `
|
|
9110
|
+
.dt-ses-report { display: flex; flex-direction: column; gap: 4px; width: 100%; min-width: 0; margin: 0; }
|
|
9111
|
+
.dt-ses-report-canvas { position: relative; width: 100%; }
|
|
9112
|
+
.dt-ses-report-canvas img { display: block; width: 100%; max-width: 100%; height: auto; border-radius: 8px; box-shadow: var(--rf-shadow-inset); }
|
|
9113
|
+
.dt-ses-report-canvas[data-measured="false"] .dt-ses-callout { visibility: hidden; }
|
|
9114
|
+
.dt-ses-report-mark { --dt-mark: var(--rf-accent); position: absolute; border: 2px solid var(--dt-mark); border-radius: 4px; pointer-events: none; }
|
|
9115
|
+
.dt-ses-report-lines { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
|
|
9116
|
+
.dt-ses-report-lines g { color: var(--rf-accent); }
|
|
9117
|
+
.dt-ses-report-lines line { stroke: currentColor; stroke-width: 1.5; }
|
|
9118
|
+
.dt-ses-report-lines circle { fill: currentColor; }
|
|
9119
|
+
.dt-ses-report-mark[data-decision="kept"], .dt-ses-report-lines g[data-decision="kept"] { --dt-mark: var(--rf-success); color: var(--rf-success); }
|
|
9120
|
+
.dt-ses-report-mark[data-decision="dismissed"], .dt-ses-report-lines g[data-decision="dismissed"] { opacity: .35; }
|
|
9121
|
+
.dt-ses-callouts { margin: 0; padding: 0; list-style: none; }
|
|
9122
|
+
.dt-ses-callouts[data-flow="list"] { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
|
|
9123
|
+
.dt-ses-callout {
|
|
9124
|
+
display: flex; align-items: center; gap: 4px; max-width: 100%; padding: 3px; border-radius: var(--rf-pill);
|
|
9125
|
+
background: var(--rf-bg); box-shadow: var(--rf-shadow-inset), var(--rf-shadow-low); font-size: 12px; line-height: 1.3;
|
|
9126
|
+
}
|
|
9127
|
+
.dt-ses-report-canvas .dt-ses-callout { position: absolute; top: 0; left: 0; width: max-content; max-width: min(280px, 100%); }
|
|
9128
|
+
.dt-ses-callout-number {
|
|
9129
|
+
display: grid; place-items: center; flex: none; min-width: 20px; height: 20px; padding: 0 5px; border-radius: var(--rf-pill);
|
|
9130
|
+
background: var(--rf-accent); color: var(--rf-accent-text, #fff); font-size: 11px; font-weight: 650; font-variant-numeric: tabular-nums;
|
|
9131
|
+
}
|
|
9132
|
+
.dt-ses-callout[data-decision="kept"] .dt-ses-callout-number { background: var(--rf-success); }
|
|
9133
|
+
.dt-ses-callout[data-decision="dismissed"] .dt-ses-callout-number { background: var(--rf-text-muted); }
|
|
9134
|
+
.dt-ses-callout-label { min-width: 0; padding: 0 4px; font-weight: 550; text-align: left; overflow-wrap: anywhere; }
|
|
9135
|
+
.dt-ses-callout-label:hover { color: var(--rf-accent); }
|
|
9136
|
+
.dt-ses-callout[data-decision="dismissed"] .dt-ses-callout-label { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9137
|
+
.dt-ses-callout-btn {
|
|
9138
|
+
display: grid; place-items: center; flex: none; width: 22px; height: 22px; border-radius: 50%; color: var(--rf-text-muted);
|
|
9139
|
+
transition: background-color 120ms var(--rf-ease), color 120ms var(--rf-ease);
|
|
9140
|
+
}
|
|
9141
|
+
.dt-ses-callout-btn svg { width: 13px; height: 13px; }
|
|
9142
|
+
.dt-ses-callout-btn:hover { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
9143
|
+
.dt-ses-callout-btn[data-decision="kept"][aria-pressed="true"] { background: var(--rf-success); color: #fff; }
|
|
9144
|
+
.dt-ses-callout-btn[data-decision="dismissed"][aria-pressed="true"] { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
9145
|
+
`;
|
|
9146
|
+
//#endregion
|
|
9147
|
+
//#region src/sessions/ui/sessions-styles.ts
|
|
9148
|
+
const MONO_FONT$1 = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
9149
|
+
const SESSIONS_STYLES = `${`
|
|
9150
|
+
.dt-rec {
|
|
9151
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; left: 50%; translate: -50% 0;
|
|
9152
|
+
bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + 16px);
|
|
9153
|
+
display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px;
|
|
9154
|
+
max-width: calc(100vw - 24px); padding: 6px 6px 6px 12px; border-radius: var(--dt-radius-surface);
|
|
9155
|
+
animation: dt-rec-in 240ms var(--rf-ease);
|
|
9156
|
+
}
|
|
9157
|
+
@keyframes dt-rec-in { from { transform: translateY(8px); opacity: 0; } }
|
|
9158
|
+
.dt-rec-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--rf-danger); }
|
|
9159
|
+
.dt-rec[data-phase="recording"] .dt-rec-dot { animation: dt-rec-pulse 1.6s ease-in-out infinite; }
|
|
9160
|
+
.dt-rec[data-phase="paused"] .dt-rec-dot, .dt-rec[data-phase="finishing"] .dt-rec-dot { background: var(--rf-text-muted); }
|
|
9161
|
+
@keyframes dt-rec-pulse { 50% { opacity: .35; } }
|
|
9162
|
+
.dt-rec-meter { display: inline-flex; align-items: center; gap: 2px; height: 16px; }
|
|
9163
|
+
.dt-rec-meter span {
|
|
9164
|
+
width: 3px; height: 100%; border-radius: 2px; background: var(--rf-text-muted);
|
|
9165
|
+
scale: 1 calc(.2 + var(--dt-level, 0) * .8); transition: scale 90ms linear;
|
|
9166
|
+
}
|
|
9167
|
+
.dt-rec-meter span:nth-child(2) { scale: 1 calc(.2 + var(--dt-level, 0)); }
|
|
9168
|
+
.dt-rec-time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 5ch; }
|
|
9169
|
+
.dt-rec-status { color: var(--rf-text-muted); font-size: 12px; overflow-wrap: anywhere; }
|
|
9170
|
+
.dt-rec-status:empty { display: none; }
|
|
9171
|
+
.dt-rec-note { display: flex; align-items: center; gap: 6px; flex: 1 1 100%; font-size: 12px; color: var(--rf-text-muted); }
|
|
9172
|
+
.dt-rec-note .dt-field { flex: 1; min-width: 0; padding: 4px 8px; }
|
|
9173
|
+
`}
|
|
9174
|
+
.dt-ses-subhead, .dt-ses-label { margin: 0 0 4px; font-size: 12px; font-weight: 600; color: var(--rf-text); }
|
|
9175
|
+
.dt-ses-label { font-size: 11px; color: var(--rf-text-muted); }
|
|
9176
|
+
.dt-ses-list { margin: 0; padding-left: 18px; overflow-wrap: anywhere; }
|
|
9177
|
+
.dt-ses-list li + li { margin-top: 3px; }
|
|
9178
|
+
.dt-ses-link { align-self: flex-start; padding: 0; color: var(--rf-accent); font-size: 12px; text-align: left; }
|
|
9179
|
+
.dt-ses-link:hover { text-decoration: underline; }
|
|
9180
|
+
.dt-ses-problem, .dt-ses-banner, .dt-ses-form, .dt-ses-head, .dt-ses-strip, .dt-ses-handoff { display: flex; flex-direction: column; gap: 6px; }
|
|
9181
|
+
.dt-ses-banner { padding: 8px 10px; border-radius: var(--dt-radius-card); background: color-mix(in srgb, var(--rf-accent) 10%, transparent); }
|
|
9182
|
+
.dt-ses-banner p { margin: 0; overflow-wrap: anywhere; }
|
|
9183
|
+
.dt-ses-strip:empty { display: none; }
|
|
9184
|
+
.dt-ses-rows { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; list-style: none; }
|
|
9185
|
+
.dt-ses-row {
|
|
9186
|
+
display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
|
|
9187
|
+
padding: 8px 10px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); text-align: left;
|
|
9188
|
+
}
|
|
9189
|
+
button.dt-ses-row:hover { background: var(--rf-bg-hover); }
|
|
9190
|
+
.dt-ses-row .dt-card-title { max-width: 100%; }
|
|
9191
|
+
${`
|
|
9192
|
+
.dt-ses-title { flex: 1; min-width: 0; margin: 0; font-size: 15px; font-weight: 650; overflow-wrap: anywhere; }
|
|
9193
|
+
.dt-ses-head .dt-menu > .icon-btn { width: 30px; height: 30px; }
|
|
9194
|
+
.dt-btn[data-icon-only] { justify-content: center; width: 28px; padding: 0; }
|
|
9195
|
+
.dt-ses-field { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; color: var(--rf-text-muted); }
|
|
9196
|
+
.dt-ses-need {
|
|
9197
|
+
margin: 0; font-weight: 600; overflow-wrap: anywhere;
|
|
9198
|
+
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
|
|
9199
|
+
}
|
|
9200
|
+
.dt-ses-need[data-expanded="true"] { display: block; }
|
|
9201
|
+
.dt-card[data-decision="dismissed"] .dt-ses-need { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9202
|
+
.dt-ses-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
9203
|
+
.dt-ses-chips:empty { display: none; }
|
|
9204
|
+
.dt-ses-details { display: flex; flex-direction: column; gap: 8px; }
|
|
9205
|
+
.dt-ses-details[hidden] { display: none; }
|
|
9206
|
+
.dt-ses-details section { display: flex; flex-direction: column; gap: 2px; }
|
|
9207
|
+
.dt-ses-quote { padding: 2px 0; font-size: 12px; text-align: left; overflow-wrap: anywhere; }
|
|
9208
|
+
.dt-ses-quote:hover { color: var(--rf-accent); }
|
|
9209
|
+
.dt-ses-time { flex: none; color: var(--rf-text-muted); font: 11.5px ${MONO_FONT$1}; font-variant-numeric: tabular-nums; }
|
|
9210
|
+
.dt-ses-verify { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 8px 0 0; border: 0; border-top: 1px solid var(--rf-border); }
|
|
9211
|
+
.dt-ses-timeline { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
|
|
9212
|
+
.dt-ses-seg { display: flex; gap: 8px; padding: 6px 8px; border-radius: var(--dt-radius-field); }
|
|
9213
|
+
.dt-ses-seg:focus { outline: 2px solid var(--rf-accent); outline-offset: -2px; }
|
|
9214
|
+
.dt-ses-seg[data-kind="note"] { padding-block: 2px; }
|
|
9215
|
+
.dt-ses-seg-body { display: flex; flex: 1; flex-direction: column; gap: 4px; min-width: 0; }
|
|
9216
|
+
`}${`
|
|
9217
|
+
.dt-ses-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
9218
|
+
.dt-ses-shot { position: relative; display: inline-block; max-width: 100%; line-height: 0; }
|
|
9219
|
+
.dt-ses-shot img { display: block; max-width: 100%; height: auto; max-height: 132px; border-radius: var(--dt-radius-field); box-shadow: var(--rf-shadow-inset); }
|
|
9220
|
+
.dt-ses-shot[data-large="true"] img { max-height: none; }
|
|
9221
|
+
.dt-ses-shot-mark { position: absolute; border: 2px solid var(--rf-accent); border-radius: var(--dt-radius-tiny); pointer-events: none; }
|
|
9222
|
+
.dt-ses-shot-btn { align-self: flex-start; padding: 0; border-radius: var(--dt-radius-field); }
|
|
9223
|
+
.dt-ses-start { display: flex; flex-direction: column; gap: 8px; }
|
|
9224
|
+
.dt-ses-brief-entry > summary { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); cursor: pointer; list-style: none; }
|
|
9225
|
+
.dt-ses-brief-entry > summary::-webkit-details-marker { display: none; }
|
|
9226
|
+
.dt-ses-brief-entry > summary:hover { background: var(--rf-bg-hover); }
|
|
9227
|
+
.dt-ses-brief-entry[open] > summary { margin-bottom: 6px; }
|
|
9228
|
+
.dt-ses-check { display: flex; align-items: flex-start; gap: 6px; overflow-wrap: anywhere; }
|
|
9229
|
+
.dt-ses-check input { flex: none; margin-top: 3px; accent-color: var(--rf-accent); }
|
|
9230
|
+
.dt-ses-choices { margin: 0; padding: 0; border: 0; }
|
|
9231
|
+
.dt-ses-choices .dt-ses-list { padding-left: 0; list-style: none; }
|
|
9232
|
+
.dt-ses-brief {
|
|
9233
|
+
max-height: 50vh; overflow: auto; margin: 0; padding: 10px; border-radius: var(--dt-radius-card);
|
|
9234
|
+
background: var(--rf-bg-subtle); font: 11.5px/1.55 ${MONO_FONT$1}; white-space: pre-wrap; overflow-wrap: anywhere;
|
|
9235
|
+
}
|
|
9236
|
+
`}${`
|
|
9237
|
+
.dt-team-anchor {
|
|
9238
|
+
--dt-edge-gap: calc(max(var(--rf-offset), 12px) + 48px);
|
|
9239
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; width: min(300px, calc(100vw - 24px));
|
|
9240
|
+
}
|
|
9241
|
+
.dt-team-anchor[data-side="left"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }
|
|
9242
|
+
.dt-team-anchor[data-side="right"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }
|
|
9243
|
+
.dt-team-anchor[data-edge="bottom"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }
|
|
9244
|
+
.dt-team-anchor[data-edge="top"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }
|
|
9245
|
+
.dt-team-card { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: var(--dt-radius-surface); animation: dt-popover-in 200ms var(--rf-ease); }
|
|
9246
|
+
.dt-bar > .dt-btn { margin-inline: 2px 4px; }
|
|
9247
|
+
`}${INTENTION_STYLES}${REPORT_STYLES}`;
|
|
9248
|
+
//#endregion
|
|
9249
|
+
//#region src/devtools/client/account/account-footer.tsx
|
|
9250
|
+
const WHITESPACE = /\s+/;
|
|
9251
|
+
function initials(text) {
|
|
9252
|
+
return text.split(WHITESPACE).filter(Boolean).slice(0, 2).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
9253
|
+
}
|
|
9254
|
+
function Avatar({ image, name }) {
|
|
9255
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
9256
|
+
"aria-hidden": "true",
|
|
9257
|
+
className: "dt-avatar",
|
|
9258
|
+
children: [initials(name), image && /* @__PURE__ */ jsx("img", {
|
|
9259
|
+
alt: "",
|
|
9260
|
+
height: 28,
|
|
9261
|
+
referrerPolicy: "no-referrer",
|
|
9262
|
+
src: image,
|
|
9263
|
+
width: 28
|
|
9458
9264
|
})]
|
|
9459
9265
|
});
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9266
|
+
}
|
|
9267
|
+
function AccountFooter({ actions, organizationName, person }) {
|
|
9268
|
+
const name = person?.name ?? person?.email ?? null;
|
|
9269
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9270
|
+
/* @__PURE__ */ jsx(Avatar, {
|
|
9271
|
+
image: person?.image ?? null,
|
|
9272
|
+
name: name ?? organizationName
|
|
9273
|
+
}),
|
|
9274
|
+
/* @__PURE__ */ jsxs("span", {
|
|
9275
|
+
className: "dt-account-text",
|
|
9276
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
9277
|
+
className: "dt-account-name",
|
|
9278
|
+
children: name ?? organizationName
|
|
9279
|
+
}), name && /* @__PURE__ */ jsx("span", {
|
|
9280
|
+
className: "dt-meta",
|
|
9281
|
+
children: organizationName
|
|
9282
|
+
})]
|
|
9283
|
+
}),
|
|
9284
|
+
/* @__PURE__ */ jsx(ChevronUpDownIcon, {})
|
|
9285
|
+
] });
|
|
9286
|
+
return /* @__PURE__ */ jsx("div", {
|
|
9287
|
+
className: "dt-sheet-account",
|
|
9288
|
+
children: /* @__PURE__ */ jsx(Menu, {
|
|
9289
|
+
items: actions,
|
|
9290
|
+
placement: "above",
|
|
9291
|
+
trigger: {
|
|
9292
|
+
className: "dt-account",
|
|
9293
|
+
content,
|
|
9294
|
+
label: name ? `${name}, ${organizationName}` : organizationName
|
|
9295
|
+
}
|
|
9296
|
+
})
|
|
9297
|
+
});
|
|
9298
|
+
}
|
|
9299
|
+
function AccountNote({ children }) {
|
|
9300
|
+
return /* @__PURE__ */ jsx("div", {
|
|
9301
|
+
className: "dt-sheet-account",
|
|
9302
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
9303
|
+
className: "dt-meta",
|
|
9304
|
+
children
|
|
9305
|
+
})
|
|
9306
|
+
});
|
|
9307
|
+
}
|
|
9308
|
+
//#endregion
|
|
9309
|
+
//#region src/devtools/client/devtools-bar.tsx
|
|
9310
|
+
const BAR_POSITION_KEY = "reflet-devtools-bar-position";
|
|
9311
|
+
const PICK_BUTTON_LABEL = "Pick an element: note it, copy it, or Shift+click to open its code";
|
|
9312
|
+
const SHEET_TABS = [
|
|
9313
|
+
"inbox",
|
|
9314
|
+
"notes",
|
|
9315
|
+
"sessions",
|
|
9316
|
+
"code"
|
|
9317
|
+
];
|
|
9318
|
+
function BarButton({ children, label, onClick }) {
|
|
9319
|
+
return /* @__PURE__ */ jsx("button", {
|
|
9320
|
+
"aria-label": label,
|
|
9321
|
+
className: "icon-btn",
|
|
9322
|
+
onClick,
|
|
9323
|
+
title: label,
|
|
9324
|
+
type: "button",
|
|
9325
|
+
children
|
|
9326
|
+
});
|
|
9327
|
+
}
|
|
9328
|
+
function DevtoolsBar({ children, edge, label = "Reflet devtools", side }) {
|
|
9329
|
+
const floating = useFloatingPosition(`${edge}-${side}`, false, {
|
|
9330
|
+
anchorSelector: ".dt-bar",
|
|
9331
|
+
persistKey: BAR_POSITION_KEY
|
|
9332
|
+
});
|
|
9333
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
9334
|
+
"aria-label": label,
|
|
9335
|
+
className: "dt-bar glass",
|
|
9336
|
+
"data-edge": edge,
|
|
9337
|
+
"data-moved": floating.position !== null,
|
|
9338
|
+
"data-side": side,
|
|
9339
|
+
ref: floating.rootRef,
|
|
9340
|
+
role: "toolbar",
|
|
9341
|
+
children: [
|
|
9342
|
+
/* @__PURE__ */ jsx("style", { children: floating.styles }),
|
|
9343
|
+
/* @__PURE__ */ jsx("button", {
|
|
9344
|
+
"aria-label": `Move ${label} (double-click to reset)`,
|
|
9345
|
+
className: "icon-btn drag-handle dt-grip",
|
|
9346
|
+
onDoubleClick: floating.resetPosition,
|
|
9347
|
+
title: "Drag to move · double-click to reset",
|
|
9348
|
+
type: "button",
|
|
9349
|
+
...floating.handleProps,
|
|
9350
|
+
children: /* @__PURE__ */ jsx(GripIcon, {})
|
|
9351
|
+
}),
|
|
9352
|
+
children
|
|
9353
|
+
]
|
|
9354
|
+
});
|
|
9355
|
+
}
|
|
9356
|
+
function SessionsBarButton({ onOpen }) {
|
|
9357
|
+
return /* @__PURE__ */ jsx(BarButton, {
|
|
9358
|
+
label: "Sessions",
|
|
9359
|
+
onClick: onOpen,
|
|
9360
|
+
children: /* @__PURE__ */ jsx(MicIcon, {})
|
|
9464
9361
|
});
|
|
9465
9362
|
}
|
|
9363
|
+
function panelLabel(unsentNoteCount) {
|
|
9364
|
+
if (unsentNoteCount === 0) return "Open the Reflet panel";
|
|
9365
|
+
return `Open the Reflet panel (${unsentNoteCount} ${unsentNoteCount === 1 ? "note" : "notes"} not on the board)`;
|
|
9366
|
+
}
|
|
9367
|
+
function DevtoolsBarButtons({ onOpen, onPick, unsentNoteCount }) {
|
|
9368
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9369
|
+
/* @__PURE__ */ jsx(BarButton, {
|
|
9370
|
+
label: PICK_BUTTON_LABEL,
|
|
9371
|
+
onClick: onPick,
|
|
9372
|
+
children: /* @__PURE__ */ jsx(TargetIcon, {})
|
|
9373
|
+
}),
|
|
9374
|
+
/* @__PURE__ */ jsx(SessionsBarButton, { onOpen: () => onOpen("sessions") }),
|
|
9375
|
+
/* @__PURE__ */ jsxs(BarButton, {
|
|
9376
|
+
label: panelLabel(unsentNoteCount),
|
|
9377
|
+
onClick: () => onOpen(null),
|
|
9378
|
+
children: [/* @__PURE__ */ jsx(PanelIcon, {}), unsentNoteCount > 0 && /* @__PURE__ */ jsx("span", {
|
|
9379
|
+
className: "dt-count",
|
|
9380
|
+
children: unsentNoteCount
|
|
9381
|
+
})]
|
|
9382
|
+
})
|
|
9383
|
+
] });
|
|
9384
|
+
}
|
|
9385
|
+
//#endregion
|
|
9386
|
+
//#region src/devtools/client/use-sheet-size.ts
|
|
9387
|
+
const SIZE_KEY = "reflet-devtools-sheet-size";
|
|
9388
|
+
const DEFAULT_WIDTH = 480;
|
|
9389
|
+
const MIN_WIDTH = 320;
|
|
9390
|
+
const MIN_HEIGHT = 240;
|
|
9391
|
+
const KEYBOARD_STEP = 24;
|
|
9392
|
+
const ARROW_DELTAS = {
|
|
9393
|
+
ArrowDown: {
|
|
9394
|
+
dx: 0,
|
|
9395
|
+
dy: KEYBOARD_STEP
|
|
9396
|
+
},
|
|
9397
|
+
ArrowLeft: {
|
|
9398
|
+
dx: -24,
|
|
9399
|
+
dy: 0
|
|
9400
|
+
},
|
|
9401
|
+
ArrowRight: {
|
|
9402
|
+
dx: KEYBOARD_STEP,
|
|
9403
|
+
dy: 0
|
|
9404
|
+
},
|
|
9405
|
+
ArrowUp: {
|
|
9406
|
+
dx: 0,
|
|
9407
|
+
dy: -24
|
|
9408
|
+
}
|
|
9409
|
+
};
|
|
9410
|
+
function readStoredSize() {
|
|
9411
|
+
const fallback = {
|
|
9412
|
+
height: null,
|
|
9413
|
+
width: DEFAULT_WIDTH
|
|
9414
|
+
};
|
|
9415
|
+
try {
|
|
9416
|
+
const stored = JSON.parse(localStorage.getItem(SIZE_KEY) ?? "null");
|
|
9417
|
+
if (typeof stored === "object" && stored !== null && "width" in stored && typeof stored.width === "number" && "height" in stored && (stored.height === null || typeof stored.height === "number")) return {
|
|
9418
|
+
height: stored.height,
|
|
9419
|
+
width: stored.width
|
|
9420
|
+
};
|
|
9421
|
+
} catch {
|
|
9422
|
+
return fallback;
|
|
9423
|
+
}
|
|
9424
|
+
return fallback;
|
|
9425
|
+
}
|
|
9426
|
+
/**
|
|
9427
|
+
* The stored size is the preference; what renders is that preference fitted
|
|
9428
|
+
* to today's window, so shrinking the window never loses the chosen size.
|
|
9429
|
+
*/
|
|
9430
|
+
function fitted(size, viewport) {
|
|
9431
|
+
const maxWidth = viewport.width - 24;
|
|
9432
|
+
const maxHeight = viewport.height - 24;
|
|
9433
|
+
return {
|
|
9434
|
+
height: size.height === null || size.height >= maxHeight ? null : Math.max(Math.min(MIN_HEIGHT, maxHeight), size.height),
|
|
9435
|
+
width: Math.min(maxWidth, Math.max(MIN_WIDTH, size.width))
|
|
9436
|
+
};
|
|
9437
|
+
}
|
|
9438
|
+
/**
|
|
9439
|
+
* Width grows away from the docked side, height grows downward from the top;
|
|
9440
|
+
* a height reaching the bottom of the window snaps back to full height.
|
|
9441
|
+
*/
|
|
9442
|
+
function useSheetSize(side) {
|
|
9443
|
+
const [preference, setPreference] = useState(readStoredSize);
|
|
9444
|
+
const [viewport, setViewport] = useState(visibleViewport);
|
|
9445
|
+
const drag = useRef(null);
|
|
9446
|
+
const widthDirection = side === "right" ? -1 : 1;
|
|
9447
|
+
const size = fitted(preference, viewport);
|
|
9448
|
+
useEffect(() => onViewportChange(() => setViewport(visibleViewport())), []);
|
|
9449
|
+
useEffect(() => {
|
|
9450
|
+
try {
|
|
9451
|
+
localStorage.setItem(SIZE_KEY, JSON.stringify(preference));
|
|
9452
|
+
} catch {}
|
|
9453
|
+
}, [preference]);
|
|
9454
|
+
const resize = (axis, from, dx, dy) => {
|
|
9455
|
+
const fullHeight = viewport.height - 24;
|
|
9456
|
+
setPreference(fitted({
|
|
9457
|
+
height: axis === "width" ? from.height : (from.height ?? fullHeight) + dy,
|
|
9458
|
+
width: axis === "height" ? from.width : from.width + dx * widthDirection
|
|
9459
|
+
}, viewport));
|
|
9460
|
+
};
|
|
9461
|
+
const handleProps = (axis) => ({
|
|
9462
|
+
onDoubleClick: () => setPreference((current) => ({
|
|
9463
|
+
height: axis === "width" ? current.height : null,
|
|
9464
|
+
width: axis === "height" ? current.width : DEFAULT_WIDTH
|
|
9465
|
+
})),
|
|
9466
|
+
onKeyDown: (event) => {
|
|
9467
|
+
const delta = ARROW_DELTAS[event.key];
|
|
9468
|
+
if (!delta) return;
|
|
9469
|
+
event.preventDefault();
|
|
9470
|
+
const sheetHeight = event.currentTarget.parentElement?.getBoundingClientRect().height ?? null;
|
|
9471
|
+
resize(axis, {
|
|
9472
|
+
height: size.height ?? sheetHeight,
|
|
9473
|
+
width: size.width
|
|
9474
|
+
}, delta.dx, delta.dy);
|
|
9475
|
+
},
|
|
9476
|
+
onLostPointerCapture: () => {
|
|
9477
|
+
drag.current = null;
|
|
9478
|
+
},
|
|
9479
|
+
onPointerDown: (event) => {
|
|
9480
|
+
if (event.button !== 0) return;
|
|
9481
|
+
const sheet = event.currentTarget.parentElement?.getBoundingClientRect();
|
|
9482
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
9483
|
+
drag.current = {
|
|
9484
|
+
axis,
|
|
9485
|
+
size: {
|
|
9486
|
+
height: sheet?.height ?? size.height,
|
|
9487
|
+
width: size.width
|
|
9488
|
+
},
|
|
9489
|
+
x: event.clientX,
|
|
9490
|
+
y: event.clientY
|
|
9491
|
+
};
|
|
9492
|
+
},
|
|
9493
|
+
onPointerMove: (event) => {
|
|
9494
|
+
const start = drag.current;
|
|
9495
|
+
if (start && event.currentTarget.hasPointerCapture(event.pointerId)) resize(start.axis, start.size, event.clientX - start.x, event.clientY - start.y);
|
|
9496
|
+
}
|
|
9497
|
+
});
|
|
9498
|
+
return {
|
|
9499
|
+
handleProps,
|
|
9500
|
+
size
|
|
9501
|
+
};
|
|
9502
|
+
}
|
|
9503
|
+
//#endregion
|
|
9504
|
+
//#region src/devtools/client/devtools-sheet.tsx
|
|
9505
|
+
const FULL_HEIGHT = "calc(100dvh - 24px)";
|
|
9506
|
+
const TABS = {
|
|
9507
|
+
code: {
|
|
9508
|
+
icon: /* @__PURE__ */ jsx(CodeIcon, {}),
|
|
9509
|
+
label: "Code"
|
|
9510
|
+
},
|
|
9511
|
+
inbox: {
|
|
9512
|
+
icon: /* @__PURE__ */ jsx(InboxIcon, {}),
|
|
9513
|
+
label: "Board"
|
|
9514
|
+
},
|
|
9515
|
+
notes: {
|
|
9516
|
+
icon: /* @__PURE__ */ jsx(NotesIcon, {}),
|
|
9517
|
+
label: "Notes"
|
|
9518
|
+
},
|
|
9519
|
+
sessions: {
|
|
9520
|
+
icon: /* @__PURE__ */ jsx(MicIcon, {}),
|
|
9521
|
+
label: "Sessions"
|
|
9522
|
+
}
|
|
9523
|
+
};
|
|
9524
|
+
const SHEET_POSITION_KEY = "reflet-devtools-sheet-position";
|
|
9525
|
+
function useSheetFocus(rootRef) {
|
|
9526
|
+
useLayoutEffect(() => {
|
|
9527
|
+
const root = rootRef.current;
|
|
9528
|
+
const opener = root ? focusedElementAround(root) : null;
|
|
9529
|
+
if (opener instanceof HTMLElement && typeof opener.checkVisibility === "function" && !opener.checkVisibility({ visibilityProperty: true })) root?.querySelector("[role=\"tab\"][aria-selected=\"true\"], .dt-sheet-back, .dt-sheet-title")?.focus({ preventScroll: true });
|
|
9530
|
+
return () => {
|
|
9531
|
+
queueMicrotask(() => {
|
|
9532
|
+
if (opener instanceof HTMLElement && opener.isConnected) opener.focus({ preventScroll: true });
|
|
9533
|
+
});
|
|
9534
|
+
};
|
|
9535
|
+
}, [rootRef]);
|
|
9536
|
+
}
|
|
9537
|
+
const ROOT_FOCUS_SELECTOR = "[role=\"tab\"][aria-selected=\"true\"], .dt-sheet-title";
|
|
9538
|
+
function nestedViewStart(root) {
|
|
9539
|
+
return root.querySelector(".dt-sheet-body h2") ?? root.querySelector(".dt-sheet-body");
|
|
9540
|
+
}
|
|
9541
|
+
/** Lands keyboard users at the top of the view they moved to, never on a control that changed meaning. */
|
|
9542
|
+
function useFocusOnNavigation(rootRef, placeId) {
|
|
9543
|
+
const shownPlaceId = useRef(placeId);
|
|
9544
|
+
useLayoutEffect(() => {
|
|
9545
|
+
const root = rootRef.current;
|
|
9546
|
+
if (shownPlaceId.current === placeId || !root) return;
|
|
9547
|
+
shownPlaceId.current = placeId;
|
|
9548
|
+
const body = root.querySelector(".dt-sheet-body");
|
|
9549
|
+
if (body) body.scrollTop = 0;
|
|
9550
|
+
(placeId === null ? root.querySelector(ROOT_FOCUS_SELECTOR) : nestedViewStart(root))?.focus({ preventScroll: true });
|
|
9551
|
+
}, [placeId, rootRef]);
|
|
9552
|
+
}
|
|
9553
|
+
function SheetNavigation({ onSelectTab, place, tab, tabs }) {
|
|
9554
|
+
if (place) return /* @__PURE__ */ jsxs("button", {
|
|
9555
|
+
"aria-label": `Back to ${place.backLabel}`,
|
|
9556
|
+
className: "dt-sheet-back",
|
|
9557
|
+
onClick: place.onBack,
|
|
9558
|
+
type: "button",
|
|
9559
|
+
children: [/* @__PURE__ */ jsx(ChevronLeftIcon, {}), place.backLabel]
|
|
9560
|
+
});
|
|
9561
|
+
if (tabs.length === 1) return /* @__PURE__ */ jsxs("h2", {
|
|
9562
|
+
className: "dt-sheet-title",
|
|
9563
|
+
tabIndex: -1,
|
|
9564
|
+
children: [TABS[tab].icon, TABS[tab].label]
|
|
9565
|
+
});
|
|
9566
|
+
return /* @__PURE__ */ jsx("div", {
|
|
9567
|
+
className: "dt-tabs",
|
|
9568
|
+
role: "tablist",
|
|
9569
|
+
children: tabs.map((option) => /* @__PURE__ */ jsxs("button", {
|
|
9570
|
+
"aria-selected": option === tab,
|
|
9571
|
+
className: "dt-tab",
|
|
9572
|
+
onClick: () => onSelectTab(option),
|
|
9573
|
+
role: "tab",
|
|
9574
|
+
type: "button",
|
|
9575
|
+
children: [TABS[option].icon, TABS[option].label]
|
|
9576
|
+
}, option))
|
|
9577
|
+
});
|
|
9578
|
+
}
|
|
9579
|
+
function DevtoolsSheet({ children, footer, label = "Reflet devtools", navigation, onClose, side }) {
|
|
9580
|
+
const { handleProps, size } = useSheetSize(side);
|
|
9581
|
+
const floating = useFloatingPosition(`top-${side}`, false, {
|
|
9582
|
+
anchorSelector: ".dt-sheet",
|
|
9583
|
+
persistKey: SHEET_POSITION_KEY
|
|
9584
|
+
});
|
|
9585
|
+
const isMoved = floating.position !== null;
|
|
9586
|
+
const { rootRef } = floating;
|
|
9587
|
+
useSheetFocus(rootRef);
|
|
9588
|
+
useFocusOnNavigation(rootRef, navigation.place?.id ?? null);
|
|
9589
|
+
useEffect(() => listenToKeydown(rootRef.current, (event) => {
|
|
9590
|
+
if (event.key === "Escape" && !event.isComposing) onClose();
|
|
9591
|
+
}), [onClose, rootRef]);
|
|
9592
|
+
return /* @__PURE__ */ jsxs("aside", {
|
|
9593
|
+
"aria-label": label,
|
|
9594
|
+
className: "dt-sheet glass",
|
|
9595
|
+
"data-moved": isMoved,
|
|
9596
|
+
"data-side": side,
|
|
9597
|
+
ref: rootRef,
|
|
9598
|
+
style: {
|
|
9599
|
+
height: size.height ?? (isMoved ? FULL_HEIGHT : void 0),
|
|
9600
|
+
width: size.width
|
|
9601
|
+
},
|
|
9602
|
+
children: [
|
|
9603
|
+
/* @__PURE__ */ jsx("style", { children: floating.styles }),
|
|
9604
|
+
/* @__PURE__ */ jsx("button", {
|
|
9605
|
+
"aria-label": "Resize panel width (double-click to reset)",
|
|
9606
|
+
className: "dt-resize",
|
|
9607
|
+
"data-axis": "width",
|
|
9608
|
+
type: "button",
|
|
9609
|
+
...handleProps("width")
|
|
9610
|
+
}),
|
|
9611
|
+
/* @__PURE__ */ jsx("button", {
|
|
9612
|
+
"aria-label": "Resize panel height (double-click for full height)",
|
|
9613
|
+
className: "dt-resize",
|
|
9614
|
+
"data-axis": "height",
|
|
9615
|
+
type: "button",
|
|
9616
|
+
...handleProps("height")
|
|
9617
|
+
}),
|
|
9618
|
+
/* @__PURE__ */ jsx("button", {
|
|
9619
|
+
"aria-label": "Resize panel (double-click to reset)",
|
|
9620
|
+
className: "dt-resize",
|
|
9621
|
+
"data-axis": "both",
|
|
9622
|
+
type: "button",
|
|
9623
|
+
...handleProps("both")
|
|
9624
|
+
}),
|
|
9625
|
+
/* @__PURE__ */ jsxs("div", {
|
|
9626
|
+
className: "dt-sheet-head",
|
|
9627
|
+
children: [
|
|
9628
|
+
/* @__PURE__ */ jsx("button", {
|
|
9629
|
+
"aria-label": "Move panel (double-click to dock it back)",
|
|
9630
|
+
className: "dt-sheet-drag",
|
|
9631
|
+
onDoubleClick: floating.resetPosition,
|
|
9632
|
+
title: "Drag to move · double-click to dock",
|
|
9633
|
+
type: "button",
|
|
9634
|
+
...floating.handleProps
|
|
9635
|
+
}),
|
|
9636
|
+
/* @__PURE__ */ jsx(SheetNavigation, { ...navigation }),
|
|
9637
|
+
/* @__PURE__ */ jsx("button", {
|
|
9638
|
+
"aria-label": `Close ${label} panel`,
|
|
9639
|
+
className: "icon-btn dt-sheet-close",
|
|
9640
|
+
onClick: onClose,
|
|
9641
|
+
title: "Close",
|
|
9642
|
+
type: "button",
|
|
9643
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
9644
|
+
})
|
|
9645
|
+
]
|
|
9646
|
+
}),
|
|
9647
|
+
/* @__PURE__ */ jsx("div", {
|
|
9648
|
+
className: "dt-sheet-body",
|
|
9649
|
+
role: navigation.place === null && navigation.tabs.length > 1 ? "tabpanel" : void 0,
|
|
9650
|
+
tabIndex: navigation.place === null ? void 0 : -1,
|
|
9651
|
+
children
|
|
9652
|
+
}, `${navigation.tab}:${navigation.place === null ? "root" : "nested"}`),
|
|
9653
|
+
footer
|
|
9654
|
+
]
|
|
9655
|
+
});
|
|
9656
|
+
}
|
|
9657
|
+
//#endregion
|
|
9658
|
+
//#region src/devtools/client/devtools-styles.ts
|
|
9659
|
+
const MONO_FONT = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
9660
|
+
const DEVTOOLS_STYLES = `
|
|
9661
|
+
.dt {
|
|
9662
|
+
--dt-radius-surface: 16px; --dt-radius-card: 12px; --dt-radius-field: 8px; --dt-radius-tiny: 4px;
|
|
9663
|
+
font: 13px/1.45 var(--rf-font, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif); color: var(--rf-text);
|
|
9664
|
+
}
|
|
9665
|
+
.dt button:active:not(:disabled, .dt-btn, .icon-btn) { scale: 1; }
|
|
9666
|
+
.dt[data-recessed="true"] .dt-bar, .dt[data-recessed="true"] .dt-sheet, .dt-sheet ~ .dt-bar { visibility: hidden; pointer-events: none; }
|
|
9667
|
+
.dt-pin {
|
|
9668
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; top: 0; left: 0;
|
|
9669
|
+
display: flex; align-items: center; justify-content: center;
|
|
9670
|
+
min-width: 24px; height: 24px; padding: 0 7px;
|
|
9671
|
+
border-radius: 12px 12px 12px 3px; background: var(--rf-accent); color: var(--rf-accent-text);
|
|
9672
|
+
font-size: 11.5px; font-weight: 650; box-shadow: 0 0 0 2px var(--rf-bg), var(--rf-shadow-low);
|
|
9673
|
+
animation: dt-pin-in 260ms var(--rf-ease);
|
|
9674
|
+
transition: scale 140ms var(--rf-ease), opacity 160ms var(--rf-ease);
|
|
9675
|
+
}
|
|
9676
|
+
.dt-pin:hover, .dt-pin[aria-expanded="true"] { scale: 1.12; }
|
|
9677
|
+
.dt-pin[data-sent="true"] { background: var(--rf-text-muted); }
|
|
9678
|
+
.dt-pin-badge { display: inline-flex; flex: none; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px 10px 10px 3px; background: var(--rf-accent); color: var(--rf-accent-text); font-size: 10.5px; font-weight: 650; }
|
|
9679
|
+
.dt-card[data-sent="true"] .dt-pin-badge { background: var(--rf-text-muted); }
|
|
9680
|
+
.dt-pin[data-locating="true"] { animation: dt-pin-in 260ms var(--rf-ease), dt-pin-pulse 1.2s ease-in-out infinite; }
|
|
9681
|
+
@keyframes dt-pin-in { from { scale: .4; opacity: 0; } }
|
|
9682
|
+
@keyframes dt-pin-pulse { 50% { box-shadow: 0 0 0 2px var(--rf-bg), 0 0 0 6px color-mix(in srgb, var(--rf-accent) 30%, transparent); } }
|
|
9683
|
+
.dt-popover {
|
|
9684
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; width: 320px; max-height: calc(100dvh - 24px); overflow: auto;
|
|
9685
|
+
inset-inline-end: auto; margin: 0; padding: 6px; border-radius: var(--dt-radius-surface); background: transparent; color: inherit;
|
|
9686
|
+
animation: dt-popover-in 200ms var(--rf-ease);
|
|
9687
|
+
}
|
|
9688
|
+
.dt-popover.glass::before { animation: rf-fade 180ms var(--rf-ease); }
|
|
9689
|
+
.dt-popover .dt-card { background: transparent; }
|
|
9690
|
+
@keyframes dt-popover-in { from { transform: translateY(4px); } }
|
|
9691
|
+
@keyframes dt-notice-in { from { transform: translateY(-6px); } }
|
|
9692
|
+
.dt-notices {
|
|
9693
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.annotatorOverlay}; left: 50%; top: 16px; translate: -50% 0;
|
|
9694
|
+
display: flex; flex-direction: column; gap: 6px; width: min(460px, calc(100vw - 24px));
|
|
9695
|
+
}
|
|
9696
|
+
.dt-notice {
|
|
9697
|
+
display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 14px; border-radius: var(--dt-radius-card);
|
|
9698
|
+
color: var(--rf-danger); font-size: 12.5px; animation: dt-notice-in 220ms var(--rf-ease);
|
|
9699
|
+
}
|
|
9700
|
+
.dt-notice[data-kind="status"] { color: var(--rf-text); }
|
|
9701
|
+
.dt-notice p { flex: 1; margin: 0; overflow-wrap: anywhere; }
|
|
9702
|
+
.dt-notice .icon-btn { width: 30px; height: 30px; }
|
|
9703
|
+
.dt-bar {
|
|
9704
|
+
--dt-edge-gap: calc(max(var(--rf-offset), 12px) + 48px);
|
|
9705
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar};
|
|
9706
|
+
display: flex; align-items: center; gap: 2px; padding: 3px;
|
|
9707
|
+
border-radius: var(--rf-pill);
|
|
9708
|
+
}
|
|
9709
|
+
.dt-bar[data-side="left"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }
|
|
9710
|
+
.dt-bar[data-side="right"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }
|
|
9711
|
+
.dt-bar[data-edge="bottom"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }
|
|
9712
|
+
.dt-bar[data-edge="top"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }
|
|
9713
|
+
.dt-bar .icon-btn { position: relative; width: 34px; height: 34px; }
|
|
9714
|
+
.dt-bar .icon-btn.dt-grip { width: 22px; color: var(--rf-text-muted); opacity: .6; }
|
|
9715
|
+
.dt-bar .icon-btn.dt-grip:hover { opacity: 1; }
|
|
9716
|
+
.dt-count {
|
|
9717
|
+
position: absolute; top: 1px; right: 1px; display: flex; align-items: center; justify-content: center;
|
|
9718
|
+
min-width: 15px; height: 15px; padding: 0 4px; border-radius: var(--rf-pill);
|
|
9719
|
+
background: var(--rf-accent); color: var(--rf-accent-text); font-size: 9.5px; font-weight: 600;
|
|
9720
|
+
}
|
|
9721
|
+
.dt-sheet {
|
|
9722
|
+
--dt-enter-x: 20px;
|
|
9723
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; top: 12px; bottom: 12px;
|
|
9724
|
+
display: flex; flex-direction: column; max-width: calc(100vw - 24px); max-height: calc(100dvh - 24px);
|
|
9725
|
+
border-radius: var(--dt-radius-surface); overflow: hidden;
|
|
9726
|
+
animation: dt-sheet-slide 320ms var(--rf-ease);
|
|
9727
|
+
}
|
|
9728
|
+
.dt-sheet[data-side="left"] { --dt-enter-x: -20px; left: 12px; }
|
|
9729
|
+
.dt-sheet[data-side="right"] { right: 12px; }
|
|
9730
|
+
.dt-sheet.glass::before { animation: rf-fade 220ms var(--rf-ease); }
|
|
9731
|
+
.dt-sheet-head, .dt-sheet-body { animation: rf-fade 260ms 60ms var(--rf-ease) both; }
|
|
9732
|
+
@keyframes dt-sheet-slide { from { transform: translateX(var(--dt-enter-x)); box-shadow: none; } }
|
|
9733
|
+
.dt-resize { position: absolute; z-index: 2; padding: 0; touch-action: none; }
|
|
9734
|
+
.dt-resize:active:not(:disabled) { scale: 1; }
|
|
9735
|
+
.dt-resize:focus-visible { outline: none; }
|
|
9736
|
+
.dt-resize[data-axis="width"] { top: 16px; bottom: 16px; width: 10px; cursor: ew-resize; }
|
|
9737
|
+
.dt-sheet[data-side="right"] .dt-resize[data-axis="width"] { left: 0; }
|
|
9738
|
+
.dt-sheet[data-side="left"] .dt-resize[data-axis="width"] { right: 0; }
|
|
9739
|
+
.dt-resize[data-axis="height"] { left: 16px; right: 16px; bottom: 0; height: 10px; cursor: ns-resize; }
|
|
9740
|
+
.dt-resize[data-axis="both"] { bottom: 0; width: 16px; height: 16px; }
|
|
9741
|
+
.dt-sheet[data-side="right"] .dt-resize[data-axis="both"] { left: 0; cursor: nesw-resize; }
|
|
9742
|
+
.dt-sheet[data-side="left"] .dt-resize[data-axis="both"] { right: 0; cursor: nwse-resize; }
|
|
9743
|
+
.dt-resize[data-axis="width"]::after, .dt-resize[data-axis="height"]::after {
|
|
9744
|
+
content: ""; position: absolute; border-radius: var(--rf-pill); background: var(--rf-text-muted);
|
|
9745
|
+
opacity: 0; transition: opacity 160ms var(--rf-ease);
|
|
9746
|
+
}
|
|
9747
|
+
.dt-resize[data-axis="width"]::after { top: 50%; left: 3px; width: 4px; height: 36px; translate: 0 -50%; }
|
|
9748
|
+
.dt-resize[data-axis="height"]::after { left: 50%; top: 3px; width: 36px; height: 4px; translate: -50% 0; }
|
|
9749
|
+
.dt-resize:hover::after, .dt-resize:focus-visible::after, .dt-resize:active::after { opacity: .5; }
|
|
9750
|
+
.dt-sheet-head { position: relative; display: flex; align-items: center; gap: 4px; padding: 8px 8px 8px 6px; border-bottom: 1px solid var(--rf-border); }
|
|
9751
|
+
.dt-sheet-head > :not(.dt-sheet-drag) { position: relative; z-index: 1; }
|
|
9752
|
+
.dt-sheet-head .icon-btn { width: 32px; height: 32px; }
|
|
9753
|
+
.dt-sheet .dt-sheet-drag { position: absolute; inset: 0; z-index: 0; padding: 0; border-radius: 0; cursor: grab; touch-action: none; }
|
|
9754
|
+
.dt-sheet .dt-sheet-drag::before { content: ""; position: absolute; top: 4px; left: 50%; width: 36px; height: 4px; translate: -50% 0; border-radius: var(--rf-pill); background: var(--rf-text-muted); opacity: .3; transition: opacity 160ms var(--rf-ease); }
|
|
9755
|
+
.dt-sheet .dt-sheet-drag:hover::before, .dt-sheet .dt-sheet-drag:active::before { opacity: .7; }
|
|
9756
|
+
.dt-sheet .dt-sheet-drag:active:not(:disabled) { cursor: grabbing; scale: 1; }
|
|
9757
|
+
.dt-sheet .dt-sheet-drag:focus-visible { outline-offset: -2px; }
|
|
9758
|
+
.dt-tabs { display: flex; gap: 2px; min-width: 0; margin-right: auto; overflow-x: auto; scrollbar-width: none; }
|
|
9759
|
+
.dt-tab { display: inline-flex; flex: none; align-items: center; gap: 6px; height: 30px; padding: 0 11px 0 9px; border-radius: var(--rf-pill); color: var(--rf-text-muted); font-weight: 500; }
|
|
9760
|
+
.dt-tab svg { flex: none; width: 15px; height: 15px; }
|
|
9761
|
+
.dt-tab:hover { color: var(--rf-text); }
|
|
9762
|
+
.dt-tab[aria-selected="true"] { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
9763
|
+
.dt-tab-count { min-width: 18px; padding: 0 5px; border-radius: var(--rf-pill); background: var(--rf-bg-hover); font-size: 10.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
9764
|
+
.dt-tab[aria-selected="true"] .dt-tab-count { background: var(--rf-bg); }
|
|
9765
|
+
.dt-sheet-back { display: inline-flex; align-items: center; gap: 4px; height: 32px; margin-right: auto; padding: 0 12px 0 6px; border-radius: var(--rf-pill); font-weight: 500; }
|
|
9766
|
+
.dt-sheet-back:hover { background: var(--rf-bg-hover); }
|
|
9767
|
+
.dt-sheet-back svg, .dt-sheet-title svg { flex: none; width: 16px; height: 16px; }
|
|
9768
|
+
.dt-sheet-title { display: inline-flex; align-items: center; gap: 6px; margin: 0 auto 0 8px; font-size: 13px; font-weight: 600; }
|
|
9769
|
+
.dt-sheet-title:focus { outline: none; }
|
|
9770
|
+
.dt-toolbar { display: flex; align-items: center; gap: 2px; min-height: 30px; }
|
|
9771
|
+
.dt-toolbar .icon-btn, .dt-toolbar .dt-menu > .icon-btn { width: 30px; height: 30px; }
|
|
9772
|
+
.dt-sheet-body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 8px; padding: 10px; }
|
|
9773
|
+
.dt-sheet-foot {
|
|
9774
|
+
position: sticky; bottom: -10px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
|
|
9775
|
+
margin: auto -10px -10px; padding: 10px; border-top: 1px solid var(--rf-border); background: var(--rf-bg);
|
|
9776
|
+
}
|
|
9777
|
+
.dt-archived { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 10px; border: 1px dashed var(--rf-border); border-radius: var(--dt-radius-card); }
|
|
9778
|
+
.dt-archived .dt-meta { flex: 1 1 100%; }
|
|
9779
|
+
.dt-group { margin: 6px 2px 0; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--rf-text-muted); }
|
|
9780
|
+
.dt-card { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); }
|
|
9781
|
+
.dt-card[data-sent="true"] { opacity: .7; }
|
|
9782
|
+
.dt-card-head { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
9783
|
+
.dt-card-title { min-width: 0; margin: 0; overflow: hidden; font-size: 13px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
|
|
9784
|
+
.dt-meta { margin: 0; font-size: 11.5px; color: var(--rf-text-muted); overflow-wrap: anywhere; }
|
|
9785
|
+
.dt-note-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
9786
|
+
.dt-chip { flex: none; padding: 1px 7px; border-radius: var(--rf-pill); background: var(--rf-bg-hover); color: var(--rf-text-muted); font-size: 10.5px; font-weight: 600; }
|
|
9787
|
+
.dt-chip[data-tone="accent"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); color: var(--rf-accent); }
|
|
9788
|
+
.dt-source { padding: 0; font: 11.5px/1.4 ${MONO_FONT}; color: var(--rf-accent); text-align: left; overflow-wrap: anywhere; }
|
|
9789
|
+
.dt-source:hover { text-decoration: underline; }
|
|
9790
|
+
.dt-thumb { display: block; align-self: flex-start; max-width: 100%; height: auto; max-height: 132px; object-fit: contain; border-radius: var(--dt-radius-field); box-shadow: var(--rf-shadow-inset); }
|
|
9791
|
+
.dt-actions { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
9792
|
+
.dt-btn {
|
|
9793
|
+
display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
|
|
9794
|
+
border-radius: var(--rf-pill); background: var(--rf-bg-hover); color: var(--rf-text);
|
|
9795
|
+
font-size: 12px; font-weight: 500; text-decoration: none;
|
|
9796
|
+
}
|
|
9797
|
+
.dt-btn:hover { background: color-mix(in srgb, var(--rf-text) 12%, transparent); }
|
|
9798
|
+
.dt-btn[data-variant="primary"] { background: var(--rf-primary); color: var(--rf-primary-text); }
|
|
9799
|
+
.dt-btn[data-variant="danger"] { color: var(--rf-danger); }
|
|
9800
|
+
.dt-btn svg { flex: none; width: 14px; height: 14px; }
|
|
9801
|
+
.dt-btn-count { padding: 0 6px; border-radius: var(--rf-pill); background: color-mix(in srgb, currentColor 18%, transparent); font-size: 10.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
9802
|
+
.dt-empty { margin: auto; padding: 24px 16px; color: var(--rf-text-muted); font-size: 12.5px; text-align: center; text-wrap: pretty; }
|
|
9803
|
+
.dt-empty p { margin: 0 0 8px; }
|
|
9804
|
+
.dt-empty-title { margin: 0 0 4px; color: var(--rf-text); font-size: 13.5px; font-weight: 600; text-wrap: balance; }
|
|
9805
|
+
.dt-empty .dt-btn { margin-top: 4px; }
|
|
9806
|
+
.dt-empty code, .dt-hint code { padding: 1px 4px; border-radius: var(--dt-radius-tiny); background: var(--rf-bg-hover); font: 11.5px ${MONO_FONT}; overflow-wrap: anywhere; }
|
|
9807
|
+
.dt-hint { margin: 0; padding: 8px 10px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); color: var(--rf-text-muted); font-size: 12px; }
|
|
9808
|
+
.dt-error { margin: 0; color: var(--rf-danger); font-size: 12px; }
|
|
9809
|
+
.dt-status { margin: 0 auto 0 0; color: var(--rf-text-muted); font-size: 12px; }
|
|
9810
|
+
.dt-field {
|
|
9811
|
+
width: 100%; padding: 7px 9px; border: 1px solid var(--rf-border); border-radius: var(--dt-radius-field);
|
|
9812
|
+
background: var(--rf-bg); color: var(--rf-text); font: inherit; resize: vertical;
|
|
9813
|
+
}
|
|
9814
|
+
.dt-field:focus { outline: 2px solid var(--rf-accent); outline-offset: 0; }
|
|
9815
|
+
.dt-search { display: flex; gap: 6px; }
|
|
9816
|
+
.dt-matches { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
|
|
9817
|
+
.dt-match { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 6px 8px; border-radius: var(--dt-radius-field); text-align: left; }
|
|
9818
|
+
.dt-match:hover { background: var(--rf-bg-hover); }
|
|
9819
|
+
.dt-match code { font: 11.5px ${MONO_FONT}; color: var(--rf-accent); }
|
|
9820
|
+
.dt-match span { font: 11.5px ${MONO_FONT}; color: var(--rf-text-muted); white-space: pre; overflow: hidden; text-overflow: ellipsis; }
|
|
9821
|
+
.dt-code-head { display: flex; flex-direction: column; gap: 6px; }
|
|
9822
|
+
.dt-code-path { margin: 0; font: 12px/1.4 ${MONO_FONT}; overflow-wrap: anywhere; }
|
|
9823
|
+
.dt-code { flex: 1; min-height: 0; overflow: auto; margin: 0; padding: 8px 0; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); font: 12px/1.6 ${MONO_FONT}; }
|
|
9824
|
+
.dt-code-lines { display: table; min-width: 100%; }
|
|
9825
|
+
.dt-line { display: table-row; white-space: pre; }
|
|
9826
|
+
.dt-line > span { display: table-cell; padding-right: 14px; }
|
|
9827
|
+
.dt-line > .dt-line-number { width: 1%; padding: 0 12px 0 10px; color: var(--rf-text-muted); text-align: right; user-select: none; }
|
|
9828
|
+
.dt-line[data-marked="true"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); }
|
|
9829
|
+
.dt-line[data-marked="true"] > .dt-line-number { color: var(--rf-accent); }
|
|
9830
|
+
.dt-menu { position: relative; flex: none; }
|
|
9831
|
+
.dt-menu-list {
|
|
9832
|
+
position: absolute; right: 0; z-index: 3; display: flex; flex-direction: column; min-width: 176px; padding: 4px;
|
|
9833
|
+
border: 1px solid var(--rf-border); border-radius: var(--dt-radius-card); background: var(--rf-bg); box-shadow: var(--rf-shadow);
|
|
9834
|
+
animation: rf-fade 120ms var(--rf-ease);
|
|
9835
|
+
}
|
|
9836
|
+
.dt-menu-list[data-placement="below"] { top: calc(100% + 4px); }
|
|
9837
|
+
.dt-menu-list[data-placement="above"] { bottom: calc(100% + 4px); }
|
|
9838
|
+
.dt-menu-item { display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; border-radius: var(--dt-radius-field); color: var(--rf-text); font-size: 12.5px; text-align: left; white-space: nowrap; }
|
|
9839
|
+
.dt-menu-item:hover, .dt-menu-item:focus-visible { background: var(--rf-bg-hover); outline: none; }
|
|
9840
|
+
.dt-menu-item[data-variant="danger"] { color: var(--rf-danger); }
|
|
9841
|
+
.dt-menu-check { display: inline-flex; width: 14px; color: var(--rf-accent); }
|
|
9842
|
+
.dt-sheet-account { display: flex; flex: none; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px; border-top: 1px solid var(--rf-border); }
|
|
9843
|
+
.dt-sheet-account > .dt-meta { flex: 1 1 160px; padding-inline: 4px; }
|
|
9844
|
+
.dt-sheet-account > .dt-menu { flex: 1; min-width: 0; }
|
|
9845
|
+
.dt-sheet-account .dt-menu-list { left: 0; }
|
|
9846
|
+
.dt-account { display: flex; align-items: center; gap: 8px; width: 100%; padding: 4px 8px 4px 4px; border-radius: var(--dt-radius-card); text-align: left; }
|
|
9847
|
+
.dt-account:hover, .dt-account[aria-expanded="true"] { background: var(--rf-bg-hover); }
|
|
9848
|
+
.dt-account > svg { flex: none; width: 14px; height: 14px; color: var(--rf-text-muted); }
|
|
9849
|
+
.dt-account-text { display: flex; flex: 1; flex-direction: column; min-width: 0; line-height: 1.3; }
|
|
9850
|
+
.dt-account-name, .dt-account-text .dt-meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
9851
|
+
.dt-account-name { font-size: 12.5px; font-weight: 600; }
|
|
9852
|
+
.dt-avatar {
|
|
9853
|
+
position: relative; display: flex; flex: none; align-items: center; justify-content: center; width: 28px; height: 28px; overflow: hidden;
|
|
9854
|
+
border-radius: 50%; background: color-mix(in srgb, var(--rf-accent) 18%, transparent); color: var(--rf-accent); font-size: 11px; font-weight: 650;
|
|
9855
|
+
}
|
|
9856
|
+
.dt-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
|
|
9857
|
+
`;
|
|
9466
9858
|
//#endregion
|
|
9467
|
-
export {
|
|
9859
|
+
export { probeDevRoute as A, reportFailure as B, bridgeTransport as C, disconnectBoard as D, callReflet as E, openDatabase as F, settle as I, sessionApiErrorSchema as L, startBoardConnect as M, committed as N, fetchBoardFeedback as O, describeStorageFailure as P, Notices as R, purgeAccount as S, teamTransport as T, RecordingLayer as _, SHEET_TABS as a, failureMessage as b, AccountNote as c, sessionSheetPlace as d, useSessionNavigation as f, copyToClipboard as g, ViewOptionsIcon as h, DevtoolsBarButtons as i, searchCode as j, fetchSourceFile as k, SESSIONS_STYLES as l, RefreshIcon as m, DevtoolsSheet as n, SessionsBarButton as o, Menu as p, DevtoolsBar as r, AccountFooter as s, DEVTOOLS_STYLES as t, SessionsPanel as u, countLabel as v, devtoolsTransport as w, useWorkspaceLoader as x, SessionWorkspaceProvider as y, announce as z };
|
|
9468
9860
|
|
|
9469
|
-
//# sourceMappingURL=
|
|
9861
|
+
//# sourceMappingURL=devtools-styles-TWR5Ps34.js.map
|