reflet-sdk 0.7.3 → 0.7.4
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 +22 -0
- package/README.md +22 -16
- package/dist/{devtools-layer-CsIcpepI.js → devtools-layer-CcTmlikp.js} +396 -277
- package/dist/devtools-layer-CcTmlikp.js.map +1 -0
- package/dist/devtools-next.js +1 -1
- package/dist/{sessions-panel-BYM0UUgT.js → devtools-styles-teRMfSzW.js} +1836 -1465
- package/dist/devtools-styles-teRMfSzW.js.map +1 -0
- package/dist/devtools-vite.js +1 -1
- package/dist/feedback.js +4 -4
- package/dist/{handler-17FmwoSX.js → handler-B3_PQB1q.js} +2 -2
- package/dist/handler-B3_PQB1q.js.map +1 -0
- package/dist/{submit-Dl0rm6TV.js → submit-CG4LXioK.js} +2 -2
- package/dist/{submit-Dl0rm6TV.js.map → submit-CG4LXioK.js.map} +1 -1
- package/dist/{team-layer-Dvjkh-_y.js → team-layer-zLj_QPQX.js} +36 -42
- package/dist/team-layer-zLj_QPQX.js.map +1 -0
- package/package.json +1 -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/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-CG4LXioK.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
|
});
|
|
@@ -3285,11 +3287,25 @@ function preciseSeconds(ms) {
|
|
|
3285
3287
|
function minutesLeft(remainingMs) {
|
|
3286
3288
|
return Math.max(1, Math.ceil(remainingMs / MINUTE_MS));
|
|
3287
3289
|
}
|
|
3288
|
-
function
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3290
|
+
function startOfDay(epochMs, daysBack) {
|
|
3291
|
+
const day = new Date(epochMs);
|
|
3292
|
+
day.setHours(0, 0, 0, 0);
|
|
3293
|
+
day.setDate(day.getDate() - daysBack);
|
|
3294
|
+
return day.getTime();
|
|
3295
|
+
}
|
|
3296
|
+
function dayLabel(epochMs, now) {
|
|
3297
|
+
if (epochMs >= startOfDay(now, 0)) return "Today";
|
|
3298
|
+
if (epochMs >= startOfDay(now, 1)) return "Yesterday";
|
|
3299
|
+
const date = new Date(epochMs);
|
|
3300
|
+
const isThisYear = date.getFullYear() === new Date(now).getFullYear();
|
|
3301
|
+
return date.toLocaleDateString(void 0, isThisYear ? {
|
|
3302
|
+
day: "numeric",
|
|
3303
|
+
month: "short"
|
|
3304
|
+
} : { dateStyle: "medium" });
|
|
3305
|
+
}
|
|
3306
|
+
function formatDate(epochMs, now = Date.now()) {
|
|
3307
|
+
const time = new Date(epochMs).toLocaleTimeString(void 0, { timeStyle: "short" });
|
|
3308
|
+
return `${dayLabel(epochMs, now)}, ${time}`;
|
|
3293
3309
|
}
|
|
3294
3310
|
function isAnalysisBusy(summary) {
|
|
3295
3311
|
return summary.analysis.state === "waiting" || summary.analysis.state === "running";
|
|
@@ -3333,13 +3349,6 @@ function PauseIcon() {
|
|
|
3333
3349
|
function PlayIcon() {
|
|
3334
3350
|
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m8 5 11 7-11 7z" }) });
|
|
3335
3351
|
}
|
|
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
3352
|
function ClockIcon() {
|
|
3344
3353
|
return /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("circle", {
|
|
3345
3354
|
cx: "12",
|
|
@@ -3347,6 +3356,29 @@ function ClockIcon() {
|
|
|
3347
3356
|
r: "8.5"
|
|
3348
3357
|
}), /* @__PURE__ */ jsx("path", { d: "M12 7.5V12l3 2" })] });
|
|
3349
3358
|
}
|
|
3359
|
+
function IntentionIcon() {
|
|
3360
|
+
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" }) });
|
|
3361
|
+
}
|
|
3362
|
+
function TranscriptIcon() {
|
|
3363
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 11h16M4 16h10" }) });
|
|
3364
|
+
}
|
|
3365
|
+
function ImageIcon() {
|
|
3366
|
+
return /* @__PURE__ */ jsxs(Svg, { children: [
|
|
3367
|
+
/* @__PURE__ */ jsx("rect", {
|
|
3368
|
+
height: "16",
|
|
3369
|
+
rx: "2.5",
|
|
3370
|
+
width: "18",
|
|
3371
|
+
x: "3",
|
|
3372
|
+
y: "4"
|
|
3373
|
+
}),
|
|
3374
|
+
/* @__PURE__ */ jsx("circle", {
|
|
3375
|
+
cx: "9",
|
|
3376
|
+
cy: "10",
|
|
3377
|
+
r: "1.6"
|
|
3378
|
+
}),
|
|
3379
|
+
/* @__PURE__ */ jsx("path", { d: "m21 16-5-5-9 9" })
|
|
3380
|
+
] });
|
|
3381
|
+
}
|
|
3350
3382
|
//#endregion
|
|
3351
3383
|
//#region src/sessions/ui/recording/level-meter.tsx
|
|
3352
3384
|
const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
@@ -3604,179 +3636,6 @@ function RecordingLayer({ onFinished }) {
|
|
|
3604
3636
|
})] });
|
|
3605
3637
|
}
|
|
3606
3638
|
//#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
3639
|
//#region src/devtools/client/clipboard.ts
|
|
3781
3640
|
/**
|
|
3782
3641
|
* Safari only lets a page write the clipboard inside the key press or click
|
|
@@ -3789,1057 +3648,572 @@ async function copyToClipboard(text) {
|
|
|
3789
3648
|
await navigator.clipboard.write([new ClipboardItem({ "text/plain": blob })]);
|
|
3790
3649
|
}
|
|
3791
3650
|
//#endregion
|
|
3792
|
-
//#region src/
|
|
3793
|
-
|
|
3794
|
-
|
|
3651
|
+
//#region src/sessions/ui/handoff/zip-archive.ts
|
|
3652
|
+
const LOCAL_HEADER_SIGNATURE = 67324752;
|
|
3653
|
+
const CENTRAL_HEADER_SIGNATURE = 33639248;
|
|
3654
|
+
const END_SIGNATURE = 101010256;
|
|
3655
|
+
const LOCAL_HEADER_SIZE = 30;
|
|
3656
|
+
const CENTRAL_HEADER_SIZE = 46;
|
|
3657
|
+
const END_RECORD_SIZE = 22;
|
|
3658
|
+
const ZIP_VERSION = 20;
|
|
3659
|
+
const UTF8_NAMES_FLAG = 2048;
|
|
3660
|
+
const DEFLATE_METHOD = 8;
|
|
3661
|
+
const GZIP_HEADER_SIZE = 10;
|
|
3662
|
+
const GZIP_FLAGS_OFFSET = 3;
|
|
3663
|
+
const GZIP_TRAILER_SIZE = 8;
|
|
3664
|
+
const DOS_EPOCH_YEAR = 1980;
|
|
3665
|
+
function dosStamp(date) {
|
|
3666
|
+
return {
|
|
3667
|
+
date: (date.getFullYear() - DOS_EPOCH_YEAR) * 512 + (date.getMonth() + 1) * 32 + date.getDate(),
|
|
3668
|
+
time: date.getHours() * 2048 + date.getMinutes() * 32 + Math.floor(date.getSeconds() / 2)
|
|
3669
|
+
};
|
|
3795
3670
|
}
|
|
3796
|
-
|
|
3797
|
-
|
|
3671
|
+
/** gzip wraps raw deflate data and ends with the CRC-32 zip needs, so the browser computes both natively. */
|
|
3672
|
+
async function deflateEntry(data) {
|
|
3673
|
+
const stream = new Response(data).body?.pipeThrough(new CompressionStream("gzip"));
|
|
3674
|
+
const gzip = new Uint8Array(await new Response(stream).arrayBuffer());
|
|
3675
|
+
if (gzip[GZIP_FLAGS_OFFSET] !== 0) throw new Error("The browser wrote an unexpected gzip header.");
|
|
3676
|
+
return {
|
|
3677
|
+
checksum: new DataView(gzip.buffer, gzip.length - GZIP_TRAILER_SIZE).getUint32(0, true),
|
|
3678
|
+
compressed: gzip.slice(GZIP_HEADER_SIZE, gzip.length - GZIP_TRAILER_SIZE)
|
|
3679
|
+
};
|
|
3798
3680
|
}
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
children
|
|
3812
|
-
});
|
|
3681
|
+
function writeCommonFields(view, start, options) {
|
|
3682
|
+
const { record, stamp } = options;
|
|
3683
|
+
view.setUint16(start, ZIP_VERSION, true);
|
|
3684
|
+
view.setUint16(start + 2, UTF8_NAMES_FLAG, true);
|
|
3685
|
+
view.setUint16(start + 4, DEFLATE_METHOD, true);
|
|
3686
|
+
view.setUint16(start + 6, stamp.time, true);
|
|
3687
|
+
view.setUint16(start + 8, stamp.date, true);
|
|
3688
|
+
view.setUint32(start + 10, record.checksum, true);
|
|
3689
|
+
view.setUint32(start + 14, record.compressed.length, true);
|
|
3690
|
+
view.setUint32(start + 18, record.size, true);
|
|
3691
|
+
view.setUint16(start + 22, record.name.length, true);
|
|
3692
|
+
view.setUint16(start + 24, 0, true);
|
|
3813
3693
|
}
|
|
3814
|
-
function
|
|
3815
|
-
const
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
className: "dt-bar glass",
|
|
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
|
-
]
|
|
3694
|
+
function localHeader(record, stamp) {
|
|
3695
|
+
const bytes = new Uint8Array(LOCAL_HEADER_SIZE + record.name.length);
|
|
3696
|
+
const view = new DataView(bytes.buffer);
|
|
3697
|
+
view.setUint32(0, LOCAL_HEADER_SIGNATURE, true);
|
|
3698
|
+
writeCommonFields(view, 4, {
|
|
3699
|
+
record,
|
|
3700
|
+
stamp
|
|
3840
3701
|
});
|
|
3702
|
+
bytes.set(record.name, LOCAL_HEADER_SIZE);
|
|
3703
|
+
return bytes;
|
|
3841
3704
|
}
|
|
3842
|
-
function
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3705
|
+
function centralHeader(record, stamp) {
|
|
3706
|
+
const bytes = new Uint8Array(CENTRAL_HEADER_SIZE + record.name.length);
|
|
3707
|
+
const view = new DataView(bytes.buffer);
|
|
3708
|
+
view.setUint32(0, CENTRAL_HEADER_SIGNATURE, true);
|
|
3709
|
+
view.setUint16(4, ZIP_VERSION, true);
|
|
3710
|
+
writeCommonFields(view, 6, {
|
|
3711
|
+
record,
|
|
3712
|
+
stamp
|
|
3848
3713
|
});
|
|
3714
|
+
view.setUint32(42, record.offset, true);
|
|
3715
|
+
bytes.set(record.name, CENTRAL_HEADER_SIZE);
|
|
3716
|
+
return bytes;
|
|
3849
3717
|
}
|
|
3850
|
-
function
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
label: "Dev notes",
|
|
3860
|
-
onClick: () => onToggleSheet("notes"),
|
|
3861
|
-
pressed: openTab === "notes",
|
|
3862
|
-
children: [/* @__PURE__ */ jsx(NotesIcon, {}), noteCount > 0 && /* @__PURE__ */ jsx("span", {
|
|
3863
|
-
className: "dt-count",
|
|
3864
|
-
children: noteCount
|
|
3865
|
-
})]
|
|
3866
|
-
}),
|
|
3867
|
-
/* @__PURE__ */ jsx(SessionsBarButton, {
|
|
3868
|
-
isOpen: openTab === "sessions",
|
|
3869
|
-
onToggle: () => onToggleSheet("sessions")
|
|
3870
|
-
}),
|
|
3871
|
-
/* @__PURE__ */ jsx(BarButton, {
|
|
3872
|
-
label: "Board feedback",
|
|
3873
|
-
onClick: () => onToggleSheet("inbox"),
|
|
3874
|
-
pressed: openTab === "inbox",
|
|
3875
|
-
children: /* @__PURE__ */ jsx(InboxIcon, {})
|
|
3876
|
-
})
|
|
3877
|
-
] });
|
|
3718
|
+
function endRecord(options) {
|
|
3719
|
+
const bytes = new Uint8Array(END_RECORD_SIZE);
|
|
3720
|
+
const view = new DataView(bytes.buffer);
|
|
3721
|
+
view.setUint32(0, END_SIGNATURE, true);
|
|
3722
|
+
view.setUint16(8, options.count, true);
|
|
3723
|
+
view.setUint16(10, options.count, true);
|
|
3724
|
+
view.setUint32(12, options.directorySize, true);
|
|
3725
|
+
view.setUint32(16, options.directoryOffset, true);
|
|
3726
|
+
return bytes;
|
|
3878
3727
|
}
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
const
|
|
3882
|
-
const
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
},
|
|
3895
|
-
ArrowRight: {
|
|
3896
|
-
dx: KEYBOARD_STEP,
|
|
3897
|
-
dy: 0
|
|
3898
|
-
},
|
|
3899
|
-
ArrowUp: {
|
|
3900
|
-
dx: 0,
|
|
3901
|
-
dy: -24
|
|
3902
|
-
}
|
|
3903
|
-
};
|
|
3904
|
-
function readStoredSize() {
|
|
3905
|
-
const fallback = {
|
|
3906
|
-
height: null,
|
|
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
|
|
3728
|
+
async function createZipArchive(entries, modifiedAt = /* @__PURE__ */ new Date()) {
|
|
3729
|
+
const stamp = dosStamp(modifiedAt);
|
|
3730
|
+
const encoder = new TextEncoder();
|
|
3731
|
+
const deflated = await Promise.all(entries.map(async (entry) => ({
|
|
3732
|
+
...await deflateEntry(entry.data),
|
|
3733
|
+
name: encoder.encode(entry.name),
|
|
3734
|
+
size: entry.data.length
|
|
3735
|
+
})));
|
|
3736
|
+
const records = [];
|
|
3737
|
+
const parts = [];
|
|
3738
|
+
let offset = 0;
|
|
3739
|
+
for (const entry of deflated) {
|
|
3740
|
+
const record = {
|
|
3741
|
+
...entry,
|
|
3742
|
+
offset
|
|
3914
3743
|
};
|
|
3915
|
-
|
|
3916
|
-
|
|
3744
|
+
const header = localHeader(record, stamp);
|
|
3745
|
+
parts.push(header, record.compressed);
|
|
3746
|
+
records.push(record);
|
|
3747
|
+
offset += header.length + record.compressed.length;
|
|
3917
3748
|
}
|
|
3918
|
-
|
|
3749
|
+
const directory = records.map((record) => centralHeader(record, stamp));
|
|
3750
|
+
const directorySize = directory.reduce((size, part) => size + part.length, 0);
|
|
3751
|
+
const end = endRecord({
|
|
3752
|
+
count: records.length,
|
|
3753
|
+
directoryOffset: offset,
|
|
3754
|
+
directorySize
|
|
3755
|
+
});
|
|
3756
|
+
return new Blob([
|
|
3757
|
+
...parts,
|
|
3758
|
+
...directory,
|
|
3759
|
+
end
|
|
3760
|
+
], { type: "application/zip" });
|
|
3919
3761
|
}
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
const
|
|
3762
|
+
//#endregion
|
|
3763
|
+
//#region src/sessions/ui/handoff/brief-export.ts
|
|
3764
|
+
const BRIEF_FILE_NAME = "brief.md";
|
|
3765
|
+
const UNSAFE_FILE_CHARACTERS = /[^a-z0-9]+/g;
|
|
3766
|
+
const EDGE_DASHES = /^-|-$/g;
|
|
3767
|
+
async function downloadFile(file) {
|
|
3768
|
+
const response = await fetch(file.url);
|
|
3769
|
+
if (!response.ok) throw new Error(`${file.name} could not be downloaded (${response.status}).`);
|
|
3927
3770
|
return {
|
|
3928
|
-
|
|
3929
|
-
|
|
3771
|
+
data: new Uint8Array(await response.arrayBuffer()),
|
|
3772
|
+
name: file.name
|
|
3930
3773
|
};
|
|
3931
3774
|
}
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
*/
|
|
3936
|
-
function
|
|
3937
|
-
const
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3775
|
+
function zipFileName(sessionTitle) {
|
|
3776
|
+
return `reflet-session-${sessionTitle.toLowerCase().replace(UNSAFE_FILE_CHARACTERS, "-").replace(EDGE_DASHES, "") || "brief"}.zip`;
|
|
3777
|
+
}
|
|
3778
|
+
/** File URLs are short-lived, so they are fetched right when the export is asked for. */
|
|
3779
|
+
async function buildBriefZip(options) {
|
|
3780
|
+
const evidence = await Promise.all(options.files.map(downloadFile));
|
|
3781
|
+
return await createZipArchive([{
|
|
3782
|
+
data: new TextEncoder().encode(options.brief),
|
|
3783
|
+
name: BRIEF_FILE_NAME
|
|
3784
|
+
}, ...evidence]);
|
|
3785
|
+
}
|
|
3786
|
+
function saveBlob(options) {
|
|
3787
|
+
const url = URL.createObjectURL(options.blob);
|
|
3788
|
+
const link = document.createElement("a");
|
|
3789
|
+
link.download = options.fileName;
|
|
3790
|
+
link.href = url;
|
|
3791
|
+
link.click();
|
|
3792
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
3793
|
+
}
|
|
3794
|
+
//#endregion
|
|
3795
|
+
//#region src/sessions/ui/review/transcript/evidence-thumb.tsx
|
|
3796
|
+
const TRIGGER_LABELS = {
|
|
3797
|
+
hover: "Long hover",
|
|
3798
|
+
manual: "Added by hand",
|
|
3799
|
+
mark: "Marked moment",
|
|
3800
|
+
navigation: "Page change",
|
|
3801
|
+
select: "Pointed element",
|
|
3802
|
+
start: "Session start"
|
|
3803
|
+
};
|
|
3804
|
+
function evidenceCaption(evidence) {
|
|
3805
|
+
const element = evidence.element ? ` · ${evidence.element.label}` : "";
|
|
3806
|
+
return `${TRIGGER_LABELS[evidence.trigger]}${element}`;
|
|
3807
|
+
}
|
|
3808
|
+
const hasViewport = (frame) => frame.viewportWidth > 0 && frame.viewportHeight > 0;
|
|
3809
|
+
const percent = (value, total) => `${value / total * 100}%`;
|
|
3810
|
+
function percentBox(rect, frame) {
|
|
3811
|
+
if (!hasViewport(frame)) return null;
|
|
3812
|
+
return {
|
|
3813
|
+
height: percent(rect.height, frame.viewportHeight),
|
|
3814
|
+
left: percent(rect.x, frame.viewportWidth),
|
|
3815
|
+
top: percent(rect.y, frame.viewportHeight),
|
|
3816
|
+
width: percent(rect.width, frame.viewportWidth)
|
|
3954
3817
|
};
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
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
|
-
});
|
|
3818
|
+
}
|
|
3819
|
+
function percentPoint(point, frame) {
|
|
3820
|
+
if (!hasViewport(frame)) return null;
|
|
3992
3821
|
return {
|
|
3993
|
-
|
|
3994
|
-
|
|
3822
|
+
left: percent(point.x, frame.viewportWidth),
|
|
3823
|
+
top: percent(point.y, frame.viewportHeight)
|
|
3995
3824
|
};
|
|
3996
3825
|
}
|
|
3826
|
+
function EvidenceThumb({ evidence, isLarge = false }) {
|
|
3827
|
+
const { element, frame, image } = evidence;
|
|
3828
|
+
if (!image?.url) return null;
|
|
3829
|
+
const highlight = element && frame ? percentBox(element.rect, frame) : null;
|
|
3830
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
3831
|
+
className: "dt-ses-shot",
|
|
3832
|
+
"data-large": isLarge,
|
|
3833
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
3834
|
+
alt: evidenceCaption(evidence),
|
|
3835
|
+
height: image.height,
|
|
3836
|
+
src: image.url,
|
|
3837
|
+
width: image.width
|
|
3838
|
+
}), highlight && /* @__PURE__ */ jsx("span", {
|
|
3839
|
+
"aria-hidden": "true",
|
|
3840
|
+
className: "dt-ses-shot-mark",
|
|
3841
|
+
style: highlight
|
|
3842
|
+
})]
|
|
3843
|
+
});
|
|
3844
|
+
}
|
|
3997
3845
|
//#endregion
|
|
3998
|
-
//#region src/
|
|
3999
|
-
const
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
};
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
useLayoutEffect(() => {
|
|
4009
|
-
const root = rootRef.current;
|
|
4010
|
-
const scope = root?.getRootNode();
|
|
4011
|
-
const opener = scope instanceof ShadowRoot || scope instanceof Document ? scope.activeElement : null;
|
|
4012
|
-
if (opener instanceof HTMLElement && typeof opener.checkVisibility === "function" && !opener.checkVisibility({ visibilityProperty: true })) root?.querySelector("[role=\"tab\"][aria-selected=\"true\"]")?.focus({ preventScroll: true });
|
|
4013
|
-
return () => {
|
|
4014
|
-
if (opener instanceof HTMLElement && opener.isConnected) opener.focus({ preventScroll: true });
|
|
4015
|
-
};
|
|
4016
|
-
}, [rootRef]);
|
|
3846
|
+
//#region src/sessions/ui/review/continuation/intention-history.tsx
|
|
3847
|
+
const FIELD_LABELS = {
|
|
3848
|
+
need: "Need",
|
|
3849
|
+
observed: "Observed",
|
|
3850
|
+
response: "Considered response",
|
|
3851
|
+
setAside: "Set aside",
|
|
3852
|
+
unknowns: "To check"
|
|
3853
|
+
};
|
|
3854
|
+
function fieldValueText(value) {
|
|
3855
|
+
return (Array.isArray(value) ? value.join("; ") : value) || "—";
|
|
4017
3856
|
}
|
|
4018
|
-
function
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
3857
|
+
function AppliedChanges({ applied }) {
|
|
3858
|
+
if (applied.length === 0) return null;
|
|
3859
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
3860
|
+
className: "dt-ses-rows",
|
|
3861
|
+
children: applied.map((change) => /* @__PURE__ */ jsxs("li", {
|
|
3862
|
+
className: "dt-ses-row",
|
|
3863
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
3864
|
+
className: "dt-meta",
|
|
3865
|
+
children: [
|
|
3866
|
+
"Accepted into revision ",
|
|
3867
|
+
change.revision,
|
|
3868
|
+
" by",
|
|
3869
|
+
" ",
|
|
3870
|
+
change.byName ?? "a teammate",
|
|
3871
|
+
" · ",
|
|
3872
|
+
formatDate(change.at)
|
|
3873
|
+
]
|
|
3874
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
3875
|
+
className: "dt-ses-list",
|
|
3876
|
+
children: change.fields.map((field) => /* @__PURE__ */ jsxs("li", { children: [
|
|
3877
|
+
FIELD_LABELS[field.field],
|
|
3878
|
+
": ",
|
|
3879
|
+
fieldValueText(field.before),
|
|
3880
|
+
" →",
|
|
3881
|
+
" ",
|
|
3882
|
+
fieldValueText(field.after)
|
|
3883
|
+
] }, field.field))
|
|
3884
|
+
})]
|
|
3885
|
+
}, change.revision))
|
|
4023
3886
|
});
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
if (event.key === "Escape" && !event.isComposing) onClose();
|
|
4029
|
-
}), [onClose, rootRef]);
|
|
4030
|
-
return /* @__PURE__ */ jsxs("aside", {
|
|
4031
|
-
"aria-label": label,
|
|
4032
|
-
className: "dt-sheet glass",
|
|
4033
|
-
"data-moved": isMoved,
|
|
4034
|
-
"data-side": side,
|
|
4035
|
-
ref: rootRef,
|
|
4036
|
-
style: {
|
|
4037
|
-
height: size.height ?? (isMoved ? FULL_HEIGHT : void 0),
|
|
4038
|
-
width: size.width
|
|
4039
|
-
},
|
|
3887
|
+
}
|
|
3888
|
+
function HistoryExtracts({ evidence, quotes }) {
|
|
3889
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [quotes.map((quote) => /* @__PURE__ */ jsxs("blockquote", {
|
|
3890
|
+
className: "dt-ses-moment-quote",
|
|
4040
3891
|
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")
|
|
3892
|
+
/* @__PURE__ */ jsx("span", {
|
|
3893
|
+
className: "dt-ses-time",
|
|
3894
|
+
children: formatClock(quote.startMs)
|
|
4055
3895
|
}),
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
className: "dt-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
3896
|
+
` “${quote.text}”`,
|
|
3897
|
+
quote.context.map((line) => /* @__PURE__ */ jsx("span", {
|
|
3898
|
+
className: "dt-meta dt-ses-context-line",
|
|
3899
|
+
children: line
|
|
3900
|
+
}, line))
|
|
3901
|
+
]
|
|
3902
|
+
}, quote.segmentId)), evidence.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
3903
|
+
className: "dt-ses-thumbs",
|
|
3904
|
+
children: evidence.map((item) => /* @__PURE__ */ jsx(EvidenceThumb, { evidence: item }, item.id))
|
|
3905
|
+
})] });
|
|
3906
|
+
}
|
|
3907
|
+
function entryTitle(entry) {
|
|
3908
|
+
const { session } = entry;
|
|
3909
|
+
return entry.origin === "continuation" ? `Continued in “${session.title}” · ${formatDate(session.startedAt)}` : `Added from “${session.title}” · ${formatDate(session.startedAt)}`;
|
|
3910
|
+
}
|
|
3911
|
+
function HistoryEntry({ context, entry }) {
|
|
3912
|
+
const evidenceIds = new Set(entry.evidenceIds);
|
|
3913
|
+
const evidence = context.detail.contributedEvidence.filter((item) => evidenceIds.has(item.id));
|
|
3914
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
3915
|
+
className: "dt-ses-history",
|
|
3916
|
+
"data-removed": entry.detachedAt !== null,
|
|
3917
|
+
children: [
|
|
3918
|
+
/* @__PURE__ */ jsx("p", {
|
|
3919
|
+
className: "dt-ses-subhead",
|
|
3920
|
+
children: entryTitle(entry)
|
|
4062
3921
|
}),
|
|
4063
|
-
/* @__PURE__ */ jsxs("
|
|
4064
|
-
className: "dt-
|
|
3922
|
+
entry.detachedAt !== null && /* @__PURE__ */ jsxs("p", {
|
|
3923
|
+
className: "dt-meta",
|
|
4065
3924
|
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
|
-
})
|
|
3925
|
+
"Removed on ",
|
|
3926
|
+
formatDate(entry.detachedAt),
|
|
3927
|
+
": what it added was taken back."
|
|
4102
3928
|
]
|
|
4103
3929
|
}),
|
|
4104
|
-
/* @__PURE__ */ jsx(
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
children
|
|
4108
|
-
},
|
|
3930
|
+
/* @__PURE__ */ jsx(AppliedChanges, { applied: entry.applied }),
|
|
3931
|
+
entry.extractsHidden ? /* @__PURE__ */ jsx("p", {
|
|
3932
|
+
className: "dt-meta",
|
|
3933
|
+
children: "Extracts are private to the author"
|
|
3934
|
+
}) : /* @__PURE__ */ jsx(HistoryExtracts, {
|
|
3935
|
+
evidence,
|
|
3936
|
+
quotes: entry.quotes
|
|
3937
|
+
}),
|
|
3938
|
+
entry.session.canOpen && /* @__PURE__ */ jsx("button", {
|
|
3939
|
+
className: "dt-ses-link",
|
|
3940
|
+
onClick: () => context.navigation.onOpenSession(entry.session.id),
|
|
3941
|
+
type: "button",
|
|
3942
|
+
children: "Open session"
|
|
3943
|
+
})
|
|
4109
3944
|
]
|
|
4110
3945
|
});
|
|
4111
3946
|
}
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
animation: dt-pin-in 260ms var(--rf-ease);
|
|
4126
|
-
transition: scale 140ms var(--rf-ease), opacity 160ms var(--rf-ease);
|
|
4127
|
-
}
|
|
4128
|
-
.dt-pin:hover, .dt-pin[aria-expanded="true"] { scale: 1.12; }
|
|
4129
|
-
.dt-pin[data-sent="true"] { background: var(--rf-text-muted); }
|
|
4130
|
-
.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; }
|
|
4131
|
-
.dt-card[data-sent="true"] .dt-pin-badge { background: var(--rf-text-muted); }
|
|
4132
|
-
.dt-pin[data-locating="true"] { animation: dt-pin-in 260ms var(--rf-ease), dt-pin-pulse 1.2s ease-in-out infinite; }
|
|
4133
|
-
@keyframes dt-pin-in { from { scale: .4; opacity: 0; } }
|
|
4134
|
-
@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); } }
|
|
4135
|
-
.dt-popover {
|
|
4136
|
-
position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; width: 320px; max-height: calc(100dvh - 24px); overflow: auto;
|
|
4137
|
-
inset-inline-end: auto; margin: 0; padding: 6px; border-radius: 14px; background: transparent; color: inherit;
|
|
4138
|
-
animation: dt-popover-in 200ms var(--rf-ease);
|
|
3947
|
+
function IntentionHistory({ context, intentionId }) {
|
|
3948
|
+
const entries = context.detail.history.filter((entry) => entry.intentionId === intentionId);
|
|
3949
|
+
if (entries.length === 0) return null;
|
|
3950
|
+
return /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h4", {
|
|
3951
|
+
className: "dt-ses-label",
|
|
3952
|
+
children: "History"
|
|
3953
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
3954
|
+
className: "dt-ses-rows",
|
|
3955
|
+
children: entries.map((entry) => /* @__PURE__ */ jsx(HistoryEntry, {
|
|
3956
|
+
context,
|
|
3957
|
+
entry
|
|
3958
|
+
}, entry.id))
|
|
3959
|
+
})] });
|
|
4139
3960
|
}
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
3961
|
+
//#endregion
|
|
3962
|
+
//#region src/sessions/ui/handoff/handoff-changes.tsx
|
|
3963
|
+
function differences(proposal, last) {
|
|
3964
|
+
return [
|
|
3965
|
+
{
|
|
3966
|
+
after: proposal.need,
|
|
3967
|
+
before: last.need,
|
|
3968
|
+
label: "Need"
|
|
3969
|
+
},
|
|
3970
|
+
{
|
|
3971
|
+
after: fieldValueText(proposal.response),
|
|
3972
|
+
before: fieldValueText(last.response),
|
|
3973
|
+
label: "Considered response"
|
|
3974
|
+
},
|
|
3975
|
+
{
|
|
3976
|
+
after: fieldValueText(proposal.unknowns),
|
|
3977
|
+
before: last.unknowns === null ? null : fieldValueText(last.unknowns),
|
|
3978
|
+
label: "To check"
|
|
3979
|
+
}
|
|
3980
|
+
].flatMap(({ after, before, label }) => before === null || before === after ? [] : [{
|
|
3981
|
+
after,
|
|
3982
|
+
before,
|
|
3983
|
+
label
|
|
3984
|
+
}]);
|
|
4147
3985
|
}
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
3986
|
+
function ChangeSummary({ last, proposal }) {
|
|
3987
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
3988
|
+
className: "dt-ses-row",
|
|
3989
|
+
children: [
|
|
3990
|
+
/* @__PURE__ */ jsx("p", {
|
|
3991
|
+
className: "dt-ses-subhead",
|
|
3992
|
+
children: proposal.need
|
|
3993
|
+
}),
|
|
3994
|
+
/* @__PURE__ */ jsxs("p", {
|
|
3995
|
+
className: "dt-meta",
|
|
3996
|
+
children: ["Changed since your brief of ", formatDate(last.at)]
|
|
3997
|
+
}),
|
|
3998
|
+
/* @__PURE__ */ jsx("ul", {
|
|
3999
|
+
className: "dt-ses-list",
|
|
4000
|
+
children: differences(proposal, last).map((difference) => /* @__PURE__ */ jsxs("li", { children: [
|
|
4001
|
+
difference.label,
|
|
4002
|
+
": ",
|
|
4003
|
+
difference.before,
|
|
4004
|
+
" → ",
|
|
4005
|
+
difference.after
|
|
4006
|
+
] }, difference.label))
|
|
4007
|
+
})
|
|
4008
|
+
]
|
|
4009
|
+
});
|
|
4151
4010
|
}
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
.
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
}
|
|
4161
|
-
.
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
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;
|
|
4011
|
+
function ChangedSinceBriefs({ detail, proposalIds }) {
|
|
4012
|
+
const selected = new Set(proposalIds);
|
|
4013
|
+
const changed = detail.proposals.flatMap((proposal) => {
|
|
4014
|
+
const last = proposal.lastHandoff;
|
|
4015
|
+
return selected.has(proposal.id) && last && last.revision < proposal.revision ? [{
|
|
4016
|
+
last,
|
|
4017
|
+
proposal
|
|
4018
|
+
}] : [];
|
|
4019
|
+
});
|
|
4020
|
+
if (changed.length === 0) return null;
|
|
4021
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
4022
|
+
className: "dt-ses-rows",
|
|
4023
|
+
children: changed.map(({ last, proposal }) => /* @__PURE__ */ jsx(ChangeSummary, {
|
|
4024
|
+
last,
|
|
4025
|
+
proposal
|
|
4026
|
+
}, proposal.id))
|
|
4027
|
+
});
|
|
4174
4028
|
}
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4029
|
+
const DELIVERY_LABELS = {
|
|
4030
|
+
copied: "Copied",
|
|
4031
|
+
exported: "Downloaded"
|
|
4032
|
+
};
|
|
4033
|
+
function deliveryLine(handoff) {
|
|
4034
|
+
const kinds = new Set(handoff.deliveries.map((delivery) => delivery.kind));
|
|
4035
|
+
if (kinds.size === 0) return "Not copied yet";
|
|
4036
|
+
return [...kinds].map((kind) => DELIVERY_LABELS[kind]).join(", ");
|
|
4181
4037
|
}
|
|
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);
|
|
4038
|
+
function briefTitle(handoff) {
|
|
4039
|
+
const [only, ...others] = handoff.proposals;
|
|
4040
|
+
if (only && others.length === 0) return only.need;
|
|
4041
|
+
return countLabel(handoff.proposals.length, "intention");
|
|
4200
4042
|
}
|
|
4201
|
-
|
|
4202
|
-
.
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4043
|
+
function EarlierBriefs({ handoffs }) {
|
|
4044
|
+
if (handoffs.length === 0) return null;
|
|
4045
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
4046
|
+
className: "dt-ses-form",
|
|
4047
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
4048
|
+
className: "dt-group",
|
|
4049
|
+
children: "Earlier briefs"
|
|
4050
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
4051
|
+
className: "dt-ses-rows",
|
|
4052
|
+
children: handoffs.map((handoff) => {
|
|
4053
|
+
const date = formatDate(handoff.createdAt);
|
|
4054
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("details", {
|
|
4055
|
+
className: "dt-ses-brief-entry",
|
|
4056
|
+
children: [/* @__PURE__ */ jsxs("summary", { children: [/* @__PURE__ */ jsx("span", {
|
|
4057
|
+
className: "dt-card-title",
|
|
4058
|
+
children: briefTitle(handoff)
|
|
4059
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
4060
|
+
className: "dt-meta",
|
|
4061
|
+
children: [
|
|
4062
|
+
date,
|
|
4063
|
+
" · ",
|
|
4064
|
+
deliveryLine(handoff)
|
|
4065
|
+
]
|
|
4066
|
+
})] }), /* @__PURE__ */ jsx("textarea", {
|
|
4067
|
+
"aria-label": `Brief of ${date}`,
|
|
4068
|
+
className: "dt-field dt-ses-brief",
|
|
4069
|
+
readOnly: true,
|
|
4070
|
+
rows: 8,
|
|
4071
|
+
value: handoff.brief
|
|
4072
|
+
})]
|
|
4073
|
+
}) }, handoff.id);
|
|
4074
|
+
})
|
|
4075
|
+
})]
|
|
4076
|
+
});
|
|
4220
4077
|
}
|
|
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;
|
|
4078
|
+
//#endregion
|
|
4079
|
+
//#region src/sessions/ui/handoff/handoff-selection.tsx
|
|
4080
|
+
function keptProposals(detail) {
|
|
4081
|
+
return detail.proposals.filter((proposal) => proposal.decision === "kept" && proposal.mergedIntoId === null);
|
|
4240
4082
|
}
|
|
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;
|
|
4083
|
+
function evidenceOf(detail, proposals) {
|
|
4084
|
+
const intentionIds = new Set(proposals.map((proposal) => proposal.id));
|
|
4085
|
+
const contributed = detail.history.filter((entry) => intentionIds.has(entry.intentionId) && entry.detachedAt === null);
|
|
4086
|
+
const cited = /* @__PURE__ */ new Set([...proposals.flatMap((proposal) => proposal.evidenceIds), ...contributed.flatMap((entry) => entry.evidenceIds)]);
|
|
4087
|
+
return [...detail.evidence, ...detail.contributedEvidence].filter((item) => cited.has(item.id) && item.status === "available");
|
|
4253
4088
|
}
|
|
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) {
|
|
4089
|
+
function initialSelection(detail) {
|
|
4090
|
+
const proposals = keptProposals(detail);
|
|
4287
4091
|
return {
|
|
4288
|
-
|
|
4289
|
-
|
|
4092
|
+
evidenceIds: evidenceOf(detail, proposals).map((item) => item.id),
|
|
4093
|
+
proposalIds: proposals.map((proposal) => proposal.id)
|
|
4290
4094
|
};
|
|
4291
4095
|
}
|
|
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
|
-
};
|
|
4096
|
+
function toggled(ids, id) {
|
|
4097
|
+
return ids.includes(id) ? ids.filter((other) => other !== id) : [...ids, id];
|
|
4301
4098
|
}
|
|
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);
|
|
4099
|
+
function CheckRow({ isChecked, label, onToggle }) {
|
|
4100
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("label", {
|
|
4101
|
+
className: "dt-ses-check",
|
|
4102
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
4103
|
+
checked: isChecked,
|
|
4104
|
+
onChange: onToggle,
|
|
4105
|
+
type: "checkbox"
|
|
4106
|
+
}), /* @__PURE__ */ jsx("span", { children: label })]
|
|
4107
|
+
}) });
|
|
4314
4108
|
}
|
|
4315
|
-
function
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4109
|
+
function ChoiceGroup({ children, legend }) {
|
|
4110
|
+
return /* @__PURE__ */ jsxs("fieldset", {
|
|
4111
|
+
className: "dt-ses-choices",
|
|
4112
|
+
children: [/* @__PURE__ */ jsx("legend", {
|
|
4113
|
+
className: "dt-ses-label",
|
|
4114
|
+
children: legend
|
|
4115
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
4116
|
+
className: "dt-ses-list",
|
|
4117
|
+
children
|
|
4118
|
+
})]
|
|
4322
4119
|
});
|
|
4323
|
-
bytes.set(record.name, LOCAL_HEADER_SIZE);
|
|
4324
|
-
return bytes;
|
|
4325
4120
|
}
|
|
4326
|
-
function
|
|
4327
|
-
const
|
|
4328
|
-
const
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
record,
|
|
4333
|
-
stamp
|
|
4121
|
+
function HandoffChoices({ detail, onChange, selection }) {
|
|
4122
|
+
const proposals = keptProposals(detail);
|
|
4123
|
+
const evidence = evidenceOf(detail, proposals);
|
|
4124
|
+
const toggleProposal = (id) => onChange({
|
|
4125
|
+
...selection,
|
|
4126
|
+
proposalIds: toggled(selection.proposalIds, id)
|
|
4334
4127
|
});
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
}
|
|
4339
|
-
|
|
4340
|
-
const
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
}
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
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
|
|
4376
|
-
});
|
|
4377
|
-
return new Blob([
|
|
4378
|
-
...parts,
|
|
4379
|
-
...directory,
|
|
4380
|
-
end
|
|
4381
|
-
], { type: "application/zip" });
|
|
4382
|
-
}
|
|
4383
|
-
//#endregion
|
|
4384
|
-
//#region src/sessions/ui/handoff/brief-export.ts
|
|
4385
|
-
const BRIEF_FILE_NAME = "brief.md";
|
|
4386
|
-
const UNSAFE_FILE_CHARACTERS = /[^a-z0-9]+/g;
|
|
4387
|
-
const EDGE_DASHES = /^-|-$/g;
|
|
4388
|
-
async function downloadFile(file) {
|
|
4389
|
-
const response = await fetch(file.url);
|
|
4390
|
-
if (!response.ok) throw new Error(`${file.name} could not be downloaded (${response.status}).`);
|
|
4391
|
-
return {
|
|
4392
|
-
data: new Uint8Array(await response.arrayBuffer()),
|
|
4393
|
-
name: file.name
|
|
4394
|
-
};
|
|
4395
|
-
}
|
|
4396
|
-
function zipFileName(sessionTitle) {
|
|
4397
|
-
return `reflet-session-${sessionTitle.toLowerCase().replace(UNSAFE_FILE_CHARACTERS, "-").replace(EDGE_DASHES, "") || "brief"}.zip`;
|
|
4398
|
-
}
|
|
4399
|
-
/** File URLs are short-lived, so they are fetched right when the export is asked for. */
|
|
4400
|
-
async function buildBriefZip(options) {
|
|
4401
|
-
const evidence = await Promise.all(options.files.map(downloadFile));
|
|
4402
|
-
return await createZipArchive([{
|
|
4403
|
-
data: new TextEncoder().encode(options.brief),
|
|
4404
|
-
name: BRIEF_FILE_NAME
|
|
4405
|
-
}, ...evidence]);
|
|
4406
|
-
}
|
|
4407
|
-
function saveBlob(options) {
|
|
4408
|
-
const url = URL.createObjectURL(options.blob);
|
|
4409
|
-
const link = document.createElement("a");
|
|
4410
|
-
link.download = options.fileName;
|
|
4411
|
-
link.href = url;
|
|
4412
|
-
link.click();
|
|
4413
|
-
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
4128
|
+
const toggleEvidence = (id) => onChange({
|
|
4129
|
+
...selection,
|
|
4130
|
+
evidenceIds: toggled(selection.evidenceIds, id)
|
|
4131
|
+
});
|
|
4132
|
+
const chosenProposalIds = new Set(selection.proposalIds);
|
|
4133
|
+
const chosenEvidenceIds = new Set(selection.evidenceIds);
|
|
4134
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ChoiceGroup, {
|
|
4135
|
+
legend: "Intentions",
|
|
4136
|
+
children: proposals.map((proposal) => /* @__PURE__ */ jsx(CheckRow, {
|
|
4137
|
+
isChecked: chosenProposalIds.has(proposal.id),
|
|
4138
|
+
label: proposal.need,
|
|
4139
|
+
onToggle: () => toggleProposal(proposal.id)
|
|
4140
|
+
}, proposal.id))
|
|
4141
|
+
}), evidence.length > 0 && /* @__PURE__ */ jsx(ChoiceGroup, {
|
|
4142
|
+
legend: "Evidence",
|
|
4143
|
+
children: evidence.map((item) => /* @__PURE__ */ jsx(CheckRow, {
|
|
4144
|
+
isChecked: chosenEvidenceIds.has(item.id),
|
|
4145
|
+
label: `${formatClock(item.atMs)} · ${evidenceCaption(item)}`,
|
|
4146
|
+
onToggle: () => toggleEvidence(item.id)
|
|
4147
|
+
}, item.id))
|
|
4148
|
+
})] });
|
|
4414
4149
|
}
|
|
4415
4150
|
//#endregion
|
|
4416
|
-
//#region src/sessions/ui/
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
}
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
return {
|
|
4434
|
-
height: percent(rect.height, frame.viewportHeight),
|
|
4435
|
-
left: percent(rect.x, frame.viewportWidth),
|
|
4436
|
-
top: percent(rect.y, frame.viewportHeight),
|
|
4437
|
-
width: percent(rect.width, frame.viewportWidth)
|
|
4151
|
+
//#region src/sessions/ui/handoff/handoff-view.tsx
|
|
4152
|
+
function useDelivery(options) {
|
|
4153
|
+
const { api } = useSessionWorkspace();
|
|
4154
|
+
const run = useSessionAction();
|
|
4155
|
+
const { files, handoff } = options.prepared;
|
|
4156
|
+
const deliver = async (kind, send) => {
|
|
4157
|
+
try {
|
|
4158
|
+
await send();
|
|
4159
|
+
} catch (error) {
|
|
4160
|
+
reportFailure(`The brief was not ${kind}`, error);
|
|
4161
|
+
return;
|
|
4162
|
+
}
|
|
4163
|
+
announce(kind === "copied" ? "Brief copied" : "Brief downloaded");
|
|
4164
|
+
await run("The delivery was not recorded", () => api.markHandoffDelivered({
|
|
4165
|
+
handoffId: handoff.id,
|
|
4166
|
+
kind
|
|
4167
|
+
}));
|
|
4438
4168
|
};
|
|
4439
|
-
}
|
|
4440
|
-
function percentPoint(point, frame) {
|
|
4441
|
-
if (!hasViewport(frame)) return null;
|
|
4442
4169
|
return {
|
|
4443
|
-
|
|
4444
|
-
|
|
4170
|
+
copy: () => deliver("copied", () => copyToClipboard(Promise.resolve(handoff.brief))),
|
|
4171
|
+
exportZip: () => deliver("exported", async () => {
|
|
4172
|
+
saveBlob({
|
|
4173
|
+
blob: await buildBriefZip({
|
|
4174
|
+
brief: handoff.brief,
|
|
4175
|
+
files
|
|
4176
|
+
}),
|
|
4177
|
+
fileName: zipFileName(options.title)
|
|
4178
|
+
});
|
|
4179
|
+
})
|
|
4445
4180
|
};
|
|
4446
4181
|
}
|
|
4447
|
-
function
|
|
4448
|
-
const {
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
return /* @__PURE__ */ jsxs("span", {
|
|
4452
|
-
className: "dt-ses-shot",
|
|
4453
|
-
"data-large": isLarge,
|
|
4454
|
-
children: [/* @__PURE__ */ jsx("img", {
|
|
4455
|
-
alt: evidenceCaption(evidence),
|
|
4456
|
-
height: image.height,
|
|
4457
|
-
src: image.url,
|
|
4458
|
-
width: image.width
|
|
4459
|
-
}), highlight && /* @__PURE__ */ jsx("span", {
|
|
4460
|
-
"aria-hidden": "true",
|
|
4461
|
-
className: "dt-ses-shot-mark",
|
|
4462
|
-
style: highlight
|
|
4463
|
-
})]
|
|
4464
|
-
});
|
|
4465
|
-
}
|
|
4466
|
-
//#endregion
|
|
4467
|
-
//#region src/sessions/ui/review/continuation/intention-history.tsx
|
|
4468
|
-
const FIELD_LABELS = {
|
|
4469
|
-
need: "Need",
|
|
4470
|
-
observed: "Observed",
|
|
4471
|
-
response: "Considered response",
|
|
4472
|
-
setAside: "Set aside",
|
|
4473
|
-
unknowns: "To check"
|
|
4474
|
-
};
|
|
4475
|
-
function fieldValueText(value) {
|
|
4476
|
-
return (Array.isArray(value) ? value.join("; ") : value) || "—";
|
|
4477
|
-
}
|
|
4478
|
-
function AppliedChanges({ applied }) {
|
|
4479
|
-
if (applied.length === 0) return null;
|
|
4480
|
-
return /* @__PURE__ */ jsx("ul", {
|
|
4481
|
-
className: "dt-ses-rows",
|
|
4482
|
-
children: applied.map((change) => /* @__PURE__ */ jsxs("li", {
|
|
4483
|
-
className: "dt-ses-row",
|
|
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))
|
|
4182
|
+
function PreparedBrief({ onChangeSelection, prepared, title }) {
|
|
4183
|
+
const { copy, exportZip } = useDelivery({
|
|
4184
|
+
prepared,
|
|
4185
|
+
title
|
|
4507
4186
|
});
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
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,
|
|
4187
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("textarea", {
|
|
4188
|
+
"aria-label": "Brief",
|
|
4189
|
+
className: "dt-field dt-ses-brief",
|
|
4190
|
+
readOnly: true,
|
|
4191
|
+
rows: 12,
|
|
4192
|
+
value: prepared.handoff.brief
|
|
4193
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4194
|
+
className: "dt-actions",
|
|
4538
4195
|
children: [
|
|
4539
|
-
/* @__PURE__ */ jsx("
|
|
4540
|
-
className: "dt-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
children: [
|
|
4546
|
-
"Removed on ",
|
|
4547
|
-
formatDate(entry.detachedAt),
|
|
4548
|
-
": what it added was taken back."
|
|
4549
|
-
]
|
|
4196
|
+
/* @__PURE__ */ jsx("button", {
|
|
4197
|
+
className: "dt-btn",
|
|
4198
|
+
"data-variant": "primary",
|
|
4199
|
+
onClick: copy,
|
|
4200
|
+
type: "button",
|
|
4201
|
+
children: "Copy brief"
|
|
4550
4202
|
}),
|
|
4551
|
-
/* @__PURE__ */ jsx(
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
evidence,
|
|
4557
|
-
quotes: entry.quotes
|
|
4203
|
+
/* @__PURE__ */ jsx("button", {
|
|
4204
|
+
className: "dt-btn",
|
|
4205
|
+
onClick: exportZip,
|
|
4206
|
+
type: "button",
|
|
4207
|
+
children: "Download .zip"
|
|
4558
4208
|
}),
|
|
4559
|
-
|
|
4560
|
-
className: "dt-
|
|
4561
|
-
onClick:
|
|
4209
|
+
/* @__PURE__ */ jsx("button", {
|
|
4210
|
+
className: "dt-btn",
|
|
4211
|
+
onClick: onChangeSelection,
|
|
4562
4212
|
type: "button",
|
|
4563
|
-
children: "
|
|
4213
|
+
children: "Edit selection"
|
|
4564
4214
|
})
|
|
4565
4215
|
]
|
|
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"
|
|
4600
|
-
}
|
|
4601
|
-
].flatMap(({ after, before, label }) => before === null || before === after ? [] : [{
|
|
4602
|
-
after,
|
|
4603
|
-
before,
|
|
4604
|
-
label
|
|
4605
|
-
}]);
|
|
4606
|
-
}
|
|
4607
|
-
function ChangeSummary({ last, proposal }) {
|
|
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");
|
|
4668
|
-
}
|
|
4669
|
-
function PreviousBriefs({ handoffs }) {
|
|
4670
|
-
if (handoffs.length === 0) return null;
|
|
4671
|
-
return /* @__PURE__ */ jsxs("section", {
|
|
4672
|
-
className: "dt-ses-form",
|
|
4673
|
-
children: [/* @__PURE__ */ jsx("h3", {
|
|
4674
|
-
className: "dt-ses-label",
|
|
4675
|
-
children: "Previous briefs"
|
|
4676
|
-
}), /* @__PURE__ */ jsx("ul", {
|
|
4677
|
-
className: "dt-ses-rows",
|
|
4678
|
-
children: handoffs.map((handoff) => {
|
|
4679
|
-
const date = formatDate(handoff.createdAt);
|
|
4680
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsxs("summary", { children: [
|
|
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
|
-
})
|
|
4694
|
-
})]
|
|
4695
|
-
});
|
|
4696
|
-
}
|
|
4697
|
-
//#endregion
|
|
4698
|
-
//#region src/sessions/ui/handoff/handoff-selection.tsx
|
|
4699
|
-
function keptProposals(detail) {
|
|
4700
|
-
return detail.proposals.filter((proposal) => proposal.decision === "kept" && proposal.mergedIntoId === null);
|
|
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);
|
|
4710
|
-
return {
|
|
4711
|
-
evidenceIds: evidenceOf(detail, proposals).map((item) => item.id),
|
|
4712
|
-
proposalIds: proposals.map((proposal) => proposal.id)
|
|
4713
|
-
};
|
|
4714
|
-
}
|
|
4715
|
-
function toggled(ids, id) {
|
|
4716
|
-
return ids.includes(id) ? ids.filter((other) => other !== id) : [...ids, id];
|
|
4717
|
-
}
|
|
4718
|
-
function CheckRow({ isChecked, label, onToggle }) {
|
|
4719
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("label", {
|
|
4720
|
-
className: "dt-ses-check",
|
|
4721
|
-
children: [/* @__PURE__ */ jsx("input", {
|
|
4722
|
-
checked: isChecked,
|
|
4723
|
-
onChange: onToggle,
|
|
4724
|
-
type: "checkbox"
|
|
4725
|
-
}), /* @__PURE__ */ jsx("span", { children: label })]
|
|
4726
|
-
}) });
|
|
4727
|
-
}
|
|
4728
|
-
function ChoiceGroup({ children, legend }) {
|
|
4729
|
-
return /* @__PURE__ */ jsxs("fieldset", {
|
|
4730
|
-
className: "dt-ses-choices",
|
|
4731
|
-
children: [/* @__PURE__ */ jsx("legend", {
|
|
4732
|
-
className: "dt-ses-label",
|
|
4733
|
-
children: legend
|
|
4734
|
-
}), /* @__PURE__ */ jsx("ul", {
|
|
4735
|
-
className: "dt-ses-list",
|
|
4736
|
-
children
|
|
4737
|
-
})]
|
|
4738
|
-
});
|
|
4739
|
-
}
|
|
4740
|
-
function HandoffChoices({ detail, onChange, selection }) {
|
|
4741
|
-
const proposals = keptProposals(detail);
|
|
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
|
-
})] });
|
|
4768
|
-
}
|
|
4769
|
-
//#endregion
|
|
4770
|
-
//#region src/sessions/ui/handoff/handoff-view.tsx
|
|
4771
|
-
function useDelivery(options) {
|
|
4772
|
-
const { api } = useSessionWorkspace();
|
|
4773
|
-
const run = useSessionAction();
|
|
4774
|
-
const { files, handoff } = options.prepared;
|
|
4775
|
-
const deliver = async (kind, send) => {
|
|
4776
|
-
try {
|
|
4777
|
-
await send();
|
|
4778
|
-
} catch (error) {
|
|
4779
|
-
reportFailure(`The brief was not ${kind}`, error);
|
|
4780
|
-
return;
|
|
4781
|
-
}
|
|
4782
|
-
announce(kind === "copied" ? "Brief copied" : "Brief exported");
|
|
4783
|
-
await run("The delivery was not recorded", () => api.markHandoffDelivered({
|
|
4784
|
-
handoffId: handoff.id,
|
|
4785
|
-
kind
|
|
4786
|
-
}));
|
|
4787
|
-
};
|
|
4788
|
-
return {
|
|
4789
|
-
copy: () => deliver("copied", () => copyToClipboard(Promise.resolve(handoff.brief))),
|
|
4790
|
-
exportZip: () => deliver("exported", async () => {
|
|
4791
|
-
saveBlob({
|
|
4792
|
-
blob: await buildBriefZip({
|
|
4793
|
-
brief: handoff.brief,
|
|
4794
|
-
files
|
|
4795
|
-
}),
|
|
4796
|
-
fileName: zipFileName(options.title)
|
|
4797
|
-
});
|
|
4798
|
-
})
|
|
4799
|
-
};
|
|
4800
|
-
}
|
|
4801
|
-
function PreparedBrief({ onChangeSelection, prepared, title }) {
|
|
4802
|
-
const { copy, exportZip } = useDelivery({
|
|
4803
|
-
prepared,
|
|
4804
|
-
title
|
|
4805
|
-
});
|
|
4806
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("textarea", {
|
|
4807
|
-
"aria-label": "Brief",
|
|
4808
|
-
className: "dt-field dt-ses-brief",
|
|
4809
|
-
readOnly: true,
|
|
4810
|
-
rows: 12,
|
|
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
|
-
})] });
|
|
4836
|
-
}
|
|
4837
|
-
function useInternalFeedback(proposalIds) {
|
|
4838
|
-
const { api } = useSessionWorkspace();
|
|
4839
|
-
const run = useSessionAction();
|
|
4840
|
-
return async () => {
|
|
4841
|
-
if ((await Promise.all(proposalIds.map((proposalId) => run("The feedback was not created", () => api.createFeedback(proposalId))))).every((result) => result !== null)) announce("Internal feedback created — agents don't pick it up from the queue; hand off the brief instead.");
|
|
4842
|
-
};
|
|
4216
|
+
})] });
|
|
4843
4217
|
}
|
|
4844
4218
|
function usePrepareHandoff(options) {
|
|
4845
4219
|
const { api } = useSessionWorkspace();
|
|
@@ -4876,12 +4250,11 @@ function usePrepareHandoff(options) {
|
|
|
4876
4250
|
};
|
|
4877
4251
|
}
|
|
4878
4252
|
function SelectionStep({ detail, handoff }) {
|
|
4879
|
-
const
|
|
4880
|
-
const hasProposals = handoff.selection.proposalIds.length > 0;
|
|
4253
|
+
const count = handoff.selection.proposalIds.length;
|
|
4881
4254
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4882
4255
|
/* @__PURE__ */ jsx("p", {
|
|
4883
4256
|
className: "dt-hint",
|
|
4884
|
-
children: "
|
|
4257
|
+
children: "Tick what your agent should get. Nothing leaves Reflet until you copy or download the brief."
|
|
4885
4258
|
}),
|
|
4886
4259
|
/* @__PURE__ */ jsx(HandoffChoices, {
|
|
4887
4260
|
detail,
|
|
@@ -4892,26 +4265,20 @@ function SelectionStep({ detail, handoff }) {
|
|
|
4892
4265
|
detail,
|
|
4893
4266
|
proposalIds: handoff.selection.proposalIds
|
|
4894
4267
|
}),
|
|
4895
|
-
/* @__PURE__ */
|
|
4268
|
+
/* @__PURE__ */ jsx("div", {
|
|
4896
4269
|
className: "dt-actions",
|
|
4897
|
-
children:
|
|
4270
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
4898
4271
|
className: "dt-btn",
|
|
4899
4272
|
"data-variant": "primary",
|
|
4900
|
-
disabled:
|
|
4273
|
+
disabled: count === 0 || handoff.isPreparing,
|
|
4901
4274
|
onClick: handoff.prepare,
|
|
4902
4275
|
type: "button",
|
|
4903
|
-
children: "
|
|
4904
|
-
})
|
|
4905
|
-
className: "dt-btn",
|
|
4906
|
-
disabled: !hasProposals,
|
|
4907
|
-
onClick: createFeedback,
|
|
4908
|
-
type: "button",
|
|
4909
|
-
children: "Create internal feedback"
|
|
4910
|
-
})]
|
|
4276
|
+
children: "Build brief"
|
|
4277
|
+
})
|
|
4911
4278
|
})
|
|
4912
4279
|
] });
|
|
4913
4280
|
}
|
|
4914
|
-
function HandoffView({ detail,
|
|
4281
|
+
function HandoffView({ detail, review }) {
|
|
4915
4282
|
const handoff = usePrepareHandoff({
|
|
4916
4283
|
detail,
|
|
4917
4284
|
review
|
|
@@ -4920,16 +4287,11 @@ function HandoffView({ detail, onClose, review }) {
|
|
|
4920
4287
|
"aria-labelledby": "rf-handoff-title",
|
|
4921
4288
|
className: "dt-ses-handoff",
|
|
4922
4289
|
children: [
|
|
4923
|
-
/* @__PURE__ */ jsx("button", {
|
|
4924
|
-
className: "dt-ses-link",
|
|
4925
|
-
onClick: onClose,
|
|
4926
|
-
type: "button",
|
|
4927
|
-
children: "← Back to review"
|
|
4928
|
-
}),
|
|
4929
4290
|
/* @__PURE__ */ jsx("h2", {
|
|
4930
4291
|
className: "dt-ses-title",
|
|
4931
4292
|
id: "rf-handoff-title",
|
|
4932
|
-
|
|
4293
|
+
tabIndex: -1,
|
|
4294
|
+
children: "Brief for your agent"
|
|
4933
4295
|
}),
|
|
4934
4296
|
handoff.prepared ? /* @__PURE__ */ jsx(PreparedBrief, {
|
|
4935
4297
|
onChangeSelection: handoff.clear,
|
|
@@ -4939,11 +4301,7 @@ function HandoffView({ detail, onClose, review }) {
|
|
|
4939
4301
|
detail,
|
|
4940
4302
|
handoff
|
|
4941
4303
|
}),
|
|
4942
|
-
/* @__PURE__ */ jsx(
|
|
4943
|
-
className: "dt-meta",
|
|
4944
|
-
children: "Copied or exported briefs can't be recalled."
|
|
4945
|
-
}),
|
|
4946
|
-
/* @__PURE__ */ jsx(PreviousBriefs, { handoffs: detail.handoffs })
|
|
4304
|
+
/* @__PURE__ */ jsx(EarlierBriefs, { handoffs: detail.handoffs })
|
|
4947
4305
|
]
|
|
4948
4306
|
});
|
|
4949
4307
|
}
|
|
@@ -5880,7 +5238,7 @@ function UpdateCard({ context, continuation }) {
|
|
|
5880
5238
|
}
|
|
5881
5239
|
//#endregion
|
|
5882
5240
|
//#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
|
|
5241
|
+
const REMOVE_COPY = "Remove this screenshot? The image is deleted for good. Briefs you already downloaded keep their copy.";
|
|
5884
5242
|
function useFocusWhen(shouldFocus) {
|
|
5885
5243
|
const ref = useRef(null);
|
|
5886
5244
|
useEffect(() => {
|
|
@@ -6412,7 +5770,7 @@ function MomentHeading({ onClose, segment }) {
|
|
|
6412
5770
|
})]
|
|
6413
5771
|
});
|
|
6414
5772
|
}
|
|
6415
|
-
function useEscapeToClose(onClose) {
|
|
5773
|
+
function useEscapeToClose$1(onClose) {
|
|
6416
5774
|
const sectionRef = useRef(null);
|
|
6417
5775
|
const onCloseRef = useRef(onClose);
|
|
6418
5776
|
useLayoutEffect(() => {
|
|
@@ -6434,7 +5792,7 @@ function useEscapeToClose(onClose) {
|
|
|
6434
5792
|
function MomentView({ handlers, segmentId, session }) {
|
|
6435
5793
|
const { detail, review } = session;
|
|
6436
5794
|
const segment = detail.segments.find((item) => item.id === segmentId);
|
|
6437
|
-
const sectionRef = useEscapeToClose(handlers.onClose);
|
|
5795
|
+
const sectionRef = useEscapeToClose$1(handlers.onClose);
|
|
6438
5796
|
return /* @__PURE__ */ jsxs("section", {
|
|
6439
5797
|
"aria-label": "Moment",
|
|
6440
5798
|
className: "dt-ses-moment",
|
|
@@ -6873,6 +6231,50 @@ function ScreenReport({ context, report }) {
|
|
|
6873
6231
|
})] });
|
|
6874
6232
|
}
|
|
6875
6233
|
//#endregion
|
|
6234
|
+
//#region src/devtools/client/devtools-icons.tsx
|
|
6235
|
+
function NotesIcon() {
|
|
6236
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "M8 6h13M8 12h13M8 18h13M3.5 6h.01M3.5 12h.01M3.5 18h.01" }) });
|
|
6237
|
+
}
|
|
6238
|
+
function InboxIcon() {
|
|
6239
|
+
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" })] });
|
|
6240
|
+
}
|
|
6241
|
+
function PanelIcon() {
|
|
6242
|
+
return /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("rect", {
|
|
6243
|
+
height: "16",
|
|
6244
|
+
rx: "2.5",
|
|
6245
|
+
width: "18",
|
|
6246
|
+
x: "3",
|
|
6247
|
+
y: "4"
|
|
6248
|
+
}), /* @__PURE__ */ jsx("path", { d: "M14 4v16" })] });
|
|
6249
|
+
}
|
|
6250
|
+
function CodeIcon() {
|
|
6251
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m8 7-5 5 5 5M16 7l5 5-5 5" }) });
|
|
6252
|
+
}
|
|
6253
|
+
function RefreshIcon() {
|
|
6254
|
+
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" }) });
|
|
6255
|
+
}
|
|
6256
|
+
function ChevronLeftIcon() {
|
|
6257
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m15 6-6 6 6 6" }) });
|
|
6258
|
+
}
|
|
6259
|
+
function ChevronUpDownIcon() {
|
|
6260
|
+
return /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "m8 10 4-4 4 4M8 14l4 4 4-4" }) });
|
|
6261
|
+
}
|
|
6262
|
+
function ViewOptionsIcon() {
|
|
6263
|
+
return /* @__PURE__ */ jsxs(Svg, { children: [
|
|
6264
|
+
/* @__PURE__ */ jsx("path", { d: "M4 7h10M18 7h2M4 17h2M10 17h10" }),
|
|
6265
|
+
/* @__PURE__ */ jsx("circle", {
|
|
6266
|
+
cx: "16",
|
|
6267
|
+
cy: "7",
|
|
6268
|
+
r: "2"
|
|
6269
|
+
}),
|
|
6270
|
+
/* @__PURE__ */ jsx("circle", {
|
|
6271
|
+
cx: "8",
|
|
6272
|
+
cy: "17",
|
|
6273
|
+
r: "2"
|
|
6274
|
+
})
|
|
6275
|
+
] });
|
|
6276
|
+
}
|
|
6277
|
+
//#endregion
|
|
6876
6278
|
//#region src/sessions/ui/start/session-disclosure.tsx
|
|
6877
6279
|
const SEEN_KEY_PREFIX = "reflet-sessions-disclosure:";
|
|
6878
6280
|
function hasSeenDisclosure(accountKey) {
|
|
@@ -6960,21 +6362,22 @@ function StartProblem({ failure, onRetry, onWriteNote }) {
|
|
|
6960
6362
|
})]
|
|
6961
6363
|
});
|
|
6962
6364
|
}
|
|
6963
|
-
function StartActions({ isBusy, onStart
|
|
6365
|
+
function StartActions({ isBusy, onStart }) {
|
|
6964
6366
|
return /* @__PURE__ */ jsxs("div", {
|
|
6965
|
-
className: "dt-
|
|
6966
|
-
children: [/* @__PURE__ */ jsx("
|
|
6967
|
-
className: "dt-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6367
|
+
className: "dt-ses-start",
|
|
6368
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
6369
|
+
className: "dt-meta",
|
|
6370
|
+
children: "Talk while you use the app. Reflet turns what you say and show into intentions you can brief an agent with."
|
|
6371
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
6372
|
+
className: "dt-actions",
|
|
6373
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
6374
|
+
className: "dt-btn",
|
|
6375
|
+
"data-variant": "primary",
|
|
6376
|
+
disabled: isBusy,
|
|
6377
|
+
onClick: onStart,
|
|
6378
|
+
type: "button",
|
|
6379
|
+
children: [/* @__PURE__ */ jsx(MicIcon, {}), "Start session"]
|
|
6380
|
+
})
|
|
6978
6381
|
})]
|
|
6979
6382
|
});
|
|
6980
6383
|
}
|
|
@@ -7006,19 +6409,21 @@ function MicrophonePrompt({ isRequesting }) {
|
|
|
7006
6409
|
function StartSession({ onStarted, onWriteNote }) {
|
|
7007
6410
|
const { account } = useSessionWorkspace();
|
|
7008
6411
|
const { failure, isBusy, isRequesting, start } = useRecorderStart(onStarted);
|
|
6412
|
+
const [isFirstVisit] = useState(() => !hasSeenDisclosure(account.key));
|
|
7009
6413
|
const startBlank = () => start({});
|
|
6414
|
+
const disclosure = /* @__PURE__ */ jsx(SessionDisclosure, { accountKey: account.key });
|
|
7010
6415
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7011
|
-
|
|
7012
|
-
/* @__PURE__ */ jsx(MicrophonePrompt, { isRequesting }),
|
|
6416
|
+
isFirstVisit && disclosure,
|
|
7013
6417
|
failure ? /* @__PURE__ */ jsx(StartProblem, {
|
|
7014
6418
|
failure,
|
|
7015
6419
|
onRetry: startBlank,
|
|
7016
6420
|
onWriteNote
|
|
7017
6421
|
}) : /* @__PURE__ */ jsx(StartActions, {
|
|
7018
6422
|
isBusy,
|
|
7019
|
-
onStart: startBlank
|
|
7020
|
-
|
|
7021
|
-
})
|
|
6423
|
+
onStart: startBlank
|
|
6424
|
+
}),
|
|
6425
|
+
/* @__PURE__ */ jsx(MicrophonePrompt, { isRequesting }),
|
|
6426
|
+
!isFirstVisit && disclosure
|
|
7022
6427
|
] });
|
|
7023
6428
|
}
|
|
7024
6429
|
//#endregion
|
|
@@ -7103,15 +6508,44 @@ function useDecide(review) {
|
|
|
7103
6508
|
});
|
|
7104
6509
|
};
|
|
7105
6510
|
}
|
|
6511
|
+
function withFeedbackIds(feedbackIds) {
|
|
6512
|
+
return (detail) => ({
|
|
6513
|
+
...detail,
|
|
6514
|
+
proposals: detail.proposals.map((item) => {
|
|
6515
|
+
const feedbackId = feedbackIds.get(item.id);
|
|
6516
|
+
return feedbackId ? {
|
|
6517
|
+
...item,
|
|
6518
|
+
feedbackId
|
|
6519
|
+
} : item;
|
|
6520
|
+
})
|
|
6521
|
+
});
|
|
6522
|
+
}
|
|
6523
|
+
function useAddToBoard(review) {
|
|
6524
|
+
const { api } = useSessionWorkspace();
|
|
6525
|
+
const run = useSessionAction();
|
|
6526
|
+
return async (proposals) => {
|
|
6527
|
+
const created = await Promise.all(proposals.map(async (proposal) => {
|
|
6528
|
+
const result = await run(`${quotedNeed(proposal.need)} was not added to the board`, () => api.createFeedback(proposal.id));
|
|
6529
|
+
return result ? [proposal.id, result.feedbackId] : null;
|
|
6530
|
+
}));
|
|
6531
|
+
const added = new Map(created.flatMap((entry) => entry ? [entry] : []));
|
|
6532
|
+
if (added.size === 0) return;
|
|
6533
|
+
review.patch(withFeedbackIds(added));
|
|
6534
|
+
const onlyAdded = added.size === 1 ? proposals.find((proposal) => added.has(proposal.id)) : void 0;
|
|
6535
|
+
announce(onlyAdded ? `Added ${quotedNeed(onlyAdded.need)} to the board` : `Added ${countLabel(added.size, "intention")} to the board`);
|
|
6536
|
+
};
|
|
6537
|
+
}
|
|
7106
6538
|
function useProposalActions(review) {
|
|
7107
6539
|
const save = useProposalSave(review);
|
|
6540
|
+
const decide = useDecide(review);
|
|
7108
6541
|
return {
|
|
6542
|
+
addToBoard: useAddToBoard(review),
|
|
7109
6543
|
clarify: (proposal, text) => save("The precision was not sent", (client) => client.clarifyProposal({
|
|
7110
6544
|
expectedRevision: proposal.revision,
|
|
7111
6545
|
proposalId: proposal.id,
|
|
7112
6546
|
text
|
|
7113
6547
|
})),
|
|
7114
|
-
decide
|
|
6548
|
+
decide,
|
|
7115
6549
|
merge: async (targetId, sourceIds) => {
|
|
7116
6550
|
if (await save("The intentions were not merged", (client) => client.mergeProposals({
|
|
7117
6551
|
sourceIds,
|
|
@@ -7129,7 +6563,7 @@ function useProposalActions(review) {
|
|
|
7129
6563
|
}
|
|
7130
6564
|
//#endregion
|
|
7131
6565
|
//#region src/sessions/ui/review/proposals/delete-intention.tsx
|
|
7132
|
-
const DELETE_INTENTION_COPY = "Delete this intention? What later sessions added to it
|
|
6566
|
+
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
6567
|
function DeleteConfirmation$1({ context, onCancel, proposal }) {
|
|
7134
6568
|
const { api } = useSessionWorkspace();
|
|
7135
6569
|
const run = useSessionAction();
|
|
@@ -7640,8 +7074,8 @@ const ICON_DECISIONS = [{
|
|
|
7640
7074
|
function ProposalChips({ proposal }) {
|
|
7641
7075
|
const decisionChip = DECISION_CHIPS[proposal.decision];
|
|
7642
7076
|
const { handedOffRevision } = proposal;
|
|
7643
|
-
let
|
|
7644
|
-
if (handedOffRevision !== null)
|
|
7077
|
+
let briefChip = null;
|
|
7078
|
+
if (handedOffRevision !== null) briefChip = proposal.revision > handedOffRevision ? "Changed since brief" : "In a brief";
|
|
7645
7079
|
return /* @__PURE__ */ jsxs("div", {
|
|
7646
7080
|
className: "dt-ses-chips",
|
|
7647
7081
|
children: [
|
|
@@ -7662,9 +7096,13 @@ function ProposalChips({ proposal }) {
|
|
|
7662
7096
|
"data-tone": "accent",
|
|
7663
7097
|
children: "To re-examine"
|
|
7664
7098
|
}),
|
|
7665
|
-
|
|
7099
|
+
briefChip && /* @__PURE__ */ jsx("span", {
|
|
7100
|
+
className: "dt-chip",
|
|
7101
|
+
children: briefChip
|
|
7102
|
+
}),
|
|
7103
|
+
proposal.feedbackId !== null && /* @__PURE__ */ jsx("span", {
|
|
7666
7104
|
className: "dt-chip",
|
|
7667
|
-
children:
|
|
7105
|
+
children: "On the board"
|
|
7668
7106
|
})
|
|
7669
7107
|
]
|
|
7670
7108
|
});
|
|
@@ -7741,6 +7179,15 @@ function DecisionButtons({ context, onEdit, proposal }) {
|
|
|
7741
7179
|
title: "Edit",
|
|
7742
7180
|
type: "button",
|
|
7743
7181
|
children: /* @__PURE__ */ jsx(PencilIcon, {})
|
|
7182
|
+
}),
|
|
7183
|
+
proposal.feedbackId === null && proposal.decision !== "dismissed" && /* @__PURE__ */ jsx("button", {
|
|
7184
|
+
"aria-label": "Add to board",
|
|
7185
|
+
className: "dt-btn",
|
|
7186
|
+
"data-icon-only": true,
|
|
7187
|
+
onClick: () => context.actions.addToBoard([proposal]),
|
|
7188
|
+
title: "Add to board",
|
|
7189
|
+
type: "button",
|
|
7190
|
+
children: /* @__PURE__ */ jsx(InboxIcon, {})
|
|
7744
7191
|
})
|
|
7745
7192
|
]
|
|
7746
7193
|
});
|
|
@@ -7896,13 +7343,6 @@ function ProposalCard({ context, proposal }) {
|
|
|
7896
7343
|
}
|
|
7897
7344
|
//#endregion
|
|
7898
7345
|
//#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
7346
|
function emptyCopy(detail) {
|
|
7907
7347
|
const { session } = detail;
|
|
7908
7348
|
if (session.collection !== "ended") return "Intentions appear here once the recording has uploaded and Reflet has read it.";
|
|
@@ -7971,25 +7411,12 @@ function AddProposalForm({ context, onDone }) {
|
|
|
7971
7411
|
]
|
|
7972
7412
|
});
|
|
7973
7413
|
}
|
|
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 }) {
|
|
7414
|
+
function ProposalsTab({ context, view }) {
|
|
7987
7415
|
const [isAdding, setIsAdding] = useState(false);
|
|
7988
7416
|
const proposals = context.detail.proposals.filter((proposal) => proposal.mergedIntoId === null);
|
|
7989
7417
|
const { continuation } = context.detail;
|
|
7990
7418
|
const report = calloutReport(context.detail);
|
|
7991
|
-
const
|
|
7992
|
-
const showsScreens = hasScreens && view === "screens";
|
|
7419
|
+
const showsScreens = report.screens.length > 0 && view === "screens";
|
|
7993
7420
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7994
7421
|
continuation && /* @__PURE__ */ jsx(UpdateCard, {
|
|
7995
7422
|
context,
|
|
@@ -7999,10 +7426,6 @@ function ProposalsTab({ context, onSelectView, view }) {
|
|
|
7999
7426
|
className: "dt-empty",
|
|
8000
7427
|
children: emptyCopy(context.detail)
|
|
8001
7428
|
}),
|
|
8002
|
-
hasScreens && /* @__PURE__ */ jsx(ViewSwitch, {
|
|
8003
|
-
onSelect: onSelectView,
|
|
8004
|
-
view
|
|
8005
|
-
}),
|
|
8006
7429
|
showsScreens && /* @__PURE__ */ jsx(ScreenReport, {
|
|
8007
7430
|
context,
|
|
8008
7431
|
report
|
|
@@ -8026,8 +7449,199 @@ function ProposalsTab({ context, onSelectView, view }) {
|
|
|
8026
7449
|
] });
|
|
8027
7450
|
}
|
|
8028
7451
|
//#endregion
|
|
7452
|
+
//#region src/sessions/ui/review/review-footer.tsx
|
|
7453
|
+
function ReviewFooter({ context, onOpenBrief }) {
|
|
7454
|
+
const confirmed = keptProposals(context.detail);
|
|
7455
|
+
const offBoard = confirmed.filter((proposal) => proposal.feedbackId === null);
|
|
7456
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7457
|
+
className: "dt-sheet-foot",
|
|
7458
|
+
children: [
|
|
7459
|
+
/* @__PURE__ */ jsxs("button", {
|
|
7460
|
+
"aria-describedby": confirmed.length === 0 ? "rf-brief-hint" : void 0,
|
|
7461
|
+
className: "dt-btn",
|
|
7462
|
+
"data-variant": "primary",
|
|
7463
|
+
disabled: confirmed.length === 0,
|
|
7464
|
+
onClick: onOpenBrief,
|
|
7465
|
+
type: "button",
|
|
7466
|
+
children: ["Prepare brief", confirmed.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
7467
|
+
className: "dt-btn-count",
|
|
7468
|
+
children: confirmed.length
|
|
7469
|
+
})]
|
|
7470
|
+
}),
|
|
7471
|
+
offBoard.length > 0 && /* @__PURE__ */ jsxs("button", {
|
|
7472
|
+
className: "dt-btn",
|
|
7473
|
+
onClick: () => context.actions.addToBoard(offBoard),
|
|
7474
|
+
type: "button",
|
|
7475
|
+
children: [
|
|
7476
|
+
"Add ",
|
|
7477
|
+
offBoard.length,
|
|
7478
|
+
" to board"
|
|
7479
|
+
]
|
|
7480
|
+
}),
|
|
7481
|
+
confirmed.length === 0 && /* @__PURE__ */ jsx("span", {
|
|
7482
|
+
className: "dt-status",
|
|
7483
|
+
id: "rf-brief-hint",
|
|
7484
|
+
children: "Confirm an intention to brief your agent or add it to the board"
|
|
7485
|
+
})
|
|
7486
|
+
]
|
|
7487
|
+
});
|
|
7488
|
+
}
|
|
7489
|
+
//#endregion
|
|
7490
|
+
//#region src/devtools/client/focused-element.ts
|
|
7491
|
+
function focusedElementAround(node) {
|
|
7492
|
+
const scope = node.getRootNode();
|
|
7493
|
+
return scope instanceof ShadowRoot || scope instanceof Document ? scope.activeElement : null;
|
|
7494
|
+
}
|
|
7495
|
+
//#endregion
|
|
7496
|
+
//#region src/devtools/client/menu.tsx
|
|
7497
|
+
const MENU_ITEM_SELECTOR = "[role^=\"menuitem\"]";
|
|
7498
|
+
function nextIndex(key, current, count) {
|
|
7499
|
+
if (key === "ArrowDown") return (current + 1) % count;
|
|
7500
|
+
if (key === "ArrowUp") return (current - 1 + count) % count;
|
|
7501
|
+
if (key === "Home") return 0;
|
|
7502
|
+
if (key === "End") return count - 1;
|
|
7503
|
+
return null;
|
|
7504
|
+
}
|
|
7505
|
+
function useCloseOnOutsidePointer(containerRef, options) {
|
|
7506
|
+
const closeRef = useRef(options.close);
|
|
7507
|
+
useLayoutEffect(() => {
|
|
7508
|
+
closeRef.current = options.close;
|
|
7509
|
+
});
|
|
7510
|
+
const { isOpen } = options;
|
|
7511
|
+
useEffect(() => {
|
|
7512
|
+
if (!isOpen) return;
|
|
7513
|
+
const closeOnOutsidePointer = (event) => {
|
|
7514
|
+
const container = containerRef.current;
|
|
7515
|
+
if (container && !event.composedPath().includes(container)) closeRef.current();
|
|
7516
|
+
};
|
|
7517
|
+
document.addEventListener("pointerdown", closeOnOutsidePointer, true);
|
|
7518
|
+
return () => document.removeEventListener("pointerdown", closeOnOutsidePointer, true);
|
|
7519
|
+
}, [containerRef, isOpen]);
|
|
7520
|
+
}
|
|
7521
|
+
function useFocusOnOpen(listRef, isOpen) {
|
|
7522
|
+
useLayoutEffect(() => {
|
|
7523
|
+
const list = listRef.current;
|
|
7524
|
+
if (!(isOpen && list)) return;
|
|
7525
|
+
const items = [...list.querySelectorAll(MENU_ITEM_SELECTOR)];
|
|
7526
|
+
(items.find((item) => item.getAttribute("aria-checked") === "true") ?? items[0])?.focus({ preventScroll: true });
|
|
7527
|
+
}, [isOpen, listRef]);
|
|
7528
|
+
}
|
|
7529
|
+
/** Native: the panel's Escape listener shares the shadow root with React's, and runs before React's handler. */
|
|
7530
|
+
function useEscapeToClose(listRef, options) {
|
|
7531
|
+
const { isOpen, onEscape } = options;
|
|
7532
|
+
useEffect(() => {
|
|
7533
|
+
const list = listRef.current;
|
|
7534
|
+
if (!(isOpen && list)) return;
|
|
7535
|
+
const closeOnEscape = (event) => {
|
|
7536
|
+
if (event.key === "Escape" && !event.isComposing) {
|
|
7537
|
+
event.stopPropagation();
|
|
7538
|
+
onEscape();
|
|
7539
|
+
}
|
|
7540
|
+
};
|
|
7541
|
+
list.addEventListener("keydown", closeOnEscape);
|
|
7542
|
+
return () => list.removeEventListener("keydown", closeOnEscape);
|
|
7543
|
+
}, [
|
|
7544
|
+
isOpen,
|
|
7545
|
+
listRef,
|
|
7546
|
+
onEscape
|
|
7547
|
+
]);
|
|
7548
|
+
}
|
|
7549
|
+
function MenuItemButton({ hasChoices, item, onChosen }) {
|
|
7550
|
+
const select = () => {
|
|
7551
|
+
onChosen();
|
|
7552
|
+
item.onSelect();
|
|
7553
|
+
};
|
|
7554
|
+
if (!hasChoices) return /* @__PURE__ */ jsx("button", {
|
|
7555
|
+
className: "dt-menu-item",
|
|
7556
|
+
"data-variant": item.variant,
|
|
7557
|
+
onClick: select,
|
|
7558
|
+
role: "menuitem",
|
|
7559
|
+
tabIndex: -1,
|
|
7560
|
+
type: "button",
|
|
7561
|
+
children: item.label
|
|
7562
|
+
});
|
|
7563
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
7564
|
+
"aria-checked": item.checked === true,
|
|
7565
|
+
className: "dt-menu-item",
|
|
7566
|
+
onClick: select,
|
|
7567
|
+
role: "menuitemradio",
|
|
7568
|
+
tabIndex: -1,
|
|
7569
|
+
type: "button",
|
|
7570
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
7571
|
+
className: "dt-menu-check",
|
|
7572
|
+
children: item.checked && /* @__PURE__ */ jsx(CheckIcon, { size: 14 })
|
|
7573
|
+
}), item.label]
|
|
7574
|
+
});
|
|
7575
|
+
}
|
|
7576
|
+
function Menu({ items, placement = "below", trigger }) {
|
|
7577
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
7578
|
+
const menuId = useId();
|
|
7579
|
+
const containerRef = useRef(null);
|
|
7580
|
+
const triggerRef = useRef(null);
|
|
7581
|
+
const listRef = useRef(null);
|
|
7582
|
+
const close = () => setIsOpen(false);
|
|
7583
|
+
const closeAndRefocus = () => {
|
|
7584
|
+
close();
|
|
7585
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
7586
|
+
};
|
|
7587
|
+
useCloseOnOutsidePointer(containerRef, {
|
|
7588
|
+
close,
|
|
7589
|
+
isOpen
|
|
7590
|
+
});
|
|
7591
|
+
useFocusOnOpen(listRef, isOpen);
|
|
7592
|
+
useEscapeToClose(listRef, {
|
|
7593
|
+
isOpen,
|
|
7594
|
+
onEscape: closeAndRefocus
|
|
7595
|
+
});
|
|
7596
|
+
const hasChoices = items.some((item) => item.checked !== void 0);
|
|
7597
|
+
const moveWithKeys = (event) => {
|
|
7598
|
+
if (event.key === "Tab") {
|
|
7599
|
+
close();
|
|
7600
|
+
return;
|
|
7601
|
+
}
|
|
7602
|
+
const list = event.currentTarget;
|
|
7603
|
+
const options = [...list.querySelectorAll(MENU_ITEM_SELECTOR)];
|
|
7604
|
+
const focused = focusedElementAround(list);
|
|
7605
|
+
const current = focused instanceof HTMLElement ? options.indexOf(focused) : -1;
|
|
7606
|
+
const index = nextIndex(event.key, current, options.length);
|
|
7607
|
+
if (index !== null) {
|
|
7608
|
+
event.preventDefault();
|
|
7609
|
+
options[index]?.focus();
|
|
7610
|
+
}
|
|
7611
|
+
};
|
|
7612
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7613
|
+
className: "dt-menu",
|
|
7614
|
+
ref: containerRef,
|
|
7615
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
7616
|
+
"aria-controls": isOpen ? menuId : void 0,
|
|
7617
|
+
"aria-expanded": isOpen,
|
|
7618
|
+
"aria-haspopup": "menu",
|
|
7619
|
+
"aria-label": trigger.label,
|
|
7620
|
+
className: trigger.className,
|
|
7621
|
+
onClick: () => setIsOpen(!isOpen),
|
|
7622
|
+
ref: triggerRef,
|
|
7623
|
+
title: trigger.label,
|
|
7624
|
+
type: "button",
|
|
7625
|
+
children: trigger.content
|
|
7626
|
+
}), isOpen && /* @__PURE__ */ jsx("div", {
|
|
7627
|
+
"aria-label": trigger.label,
|
|
7628
|
+
className: "dt-menu-list",
|
|
7629
|
+
"data-placement": placement,
|
|
7630
|
+
id: menuId,
|
|
7631
|
+
onKeyDown: moveWithKeys,
|
|
7632
|
+
ref: listRef,
|
|
7633
|
+
role: "menu",
|
|
7634
|
+
children: items.map((item) => /* @__PURE__ */ jsx(MenuItemButton, {
|
|
7635
|
+
hasChoices,
|
|
7636
|
+
item,
|
|
7637
|
+
onChosen: closeAndRefocus
|
|
7638
|
+
}, item.label))
|
|
7639
|
+
})]
|
|
7640
|
+
});
|
|
7641
|
+
}
|
|
7642
|
+
//#endregion
|
|
8029
7643
|
//#region src/sessions/ui/review/review-header.tsx
|
|
8030
|
-
const DELETE_COPY = "Delete this session? Its
|
|
7644
|
+
const DELETE_COPY = "Delete this session? Its recording, transcript, screenshots and intentions go, along with what later sessions added to those intentions.";
|
|
8031
7645
|
function withSessionFields(change) {
|
|
8032
7646
|
return (detail) => ({
|
|
8033
7647
|
...detail,
|
|
@@ -8124,94 +7738,29 @@ function DeleteConfirmation({ onCancel, onDeleted, sessionId }) {
|
|
|
8124
7738
|
})]
|
|
8125
7739
|
});
|
|
8126
7740
|
}
|
|
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 }) {
|
|
7741
|
+
function ReviewHeader({ onDeleted, review, session }) {
|
|
8202
7742
|
const [isRenaming, setIsRenaming] = useState(false);
|
|
8203
7743
|
const [isConfirmingDelete, setIsConfirmingDelete] = useState(false);
|
|
8204
7744
|
const update = useSessionUpdate(review, session);
|
|
8205
7745
|
const isShared = session.visibility === "team";
|
|
7746
|
+
const menuItems = [
|
|
7747
|
+
{
|
|
7748
|
+
label: "Rename",
|
|
7749
|
+
onSelect: () => setIsRenaming(true)
|
|
7750
|
+
},
|
|
7751
|
+
{
|
|
7752
|
+
label: isShared ? "Make private" : "Share with team",
|
|
7753
|
+
onSelect: () => update("The sharing was not changed", { visibility: isShared ? "private" : "team" })
|
|
7754
|
+
},
|
|
7755
|
+
{
|
|
7756
|
+
label: "Delete session",
|
|
7757
|
+
onSelect: () => setIsConfirmingDelete(true),
|
|
7758
|
+
variant: "danger"
|
|
7759
|
+
}
|
|
7760
|
+
];
|
|
8206
7761
|
return /* @__PURE__ */ jsxs("header", {
|
|
8207
7762
|
className: "dt-ses-head",
|
|
8208
7763
|
children: [
|
|
8209
|
-
/* @__PURE__ */ jsx("button", {
|
|
8210
|
-
className: "dt-ses-link",
|
|
8211
|
-
onClick: onBack,
|
|
8212
|
-
type: "button",
|
|
8213
|
-
children: "← All sessions"
|
|
8214
|
-
}),
|
|
8215
7764
|
isRenaming ? /* @__PURE__ */ jsx(TitleEditor, {
|
|
8216
7765
|
onDone: () => setIsRenaming(false),
|
|
8217
7766
|
review,
|
|
@@ -8220,14 +7769,15 @@ function ReviewHeader({ onBack, review, session }) {
|
|
|
8220
7769
|
className: "dt-card-head",
|
|
8221
7770
|
children: [/* @__PURE__ */ jsx("h2", {
|
|
8222
7771
|
className: "dt-ses-title",
|
|
7772
|
+
tabIndex: -1,
|
|
8223
7773
|
children: session.title
|
|
8224
|
-
}), session.canEdit && /* @__PURE__ */ jsx(
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
7774
|
+
}), session.canEdit && /* @__PURE__ */ jsx(Menu, {
|
|
7775
|
+
items: menuItems,
|
|
7776
|
+
trigger: {
|
|
7777
|
+
className: "icon-btn",
|
|
7778
|
+
content: /* @__PURE__ */ jsx(MoreIcon, {}),
|
|
7779
|
+
label: "Session options"
|
|
7780
|
+
}
|
|
8231
7781
|
})]
|
|
8232
7782
|
}),
|
|
8233
7783
|
/* @__PURE__ */ jsxs("p", {
|
|
@@ -8244,13 +7794,83 @@ function ReviewHeader({ onBack, review, session }) {
|
|
|
8244
7794
|
}),
|
|
8245
7795
|
isConfirmingDelete && session.canEdit && /* @__PURE__ */ jsx(DeleteConfirmation, {
|
|
8246
7796
|
onCancel: () => setIsConfirmingDelete(false),
|
|
8247
|
-
onDeleted
|
|
7797
|
+
onDeleted,
|
|
8248
7798
|
sessionId: session.id
|
|
8249
7799
|
})
|
|
8250
7800
|
]
|
|
8251
7801
|
});
|
|
8252
7802
|
}
|
|
8253
7803
|
//#endregion
|
|
7804
|
+
//#region src/sessions/ui/review/review-tabs.tsx
|
|
7805
|
+
const INTENTION_VIEWS = [{
|
|
7806
|
+
label: "On screen",
|
|
7807
|
+
value: "screens"
|
|
7808
|
+
}, {
|
|
7809
|
+
label: "Details",
|
|
7810
|
+
value: "cards"
|
|
7811
|
+
}];
|
|
7812
|
+
function IntentionViewMenu({ place }) {
|
|
7813
|
+
return /* @__PURE__ */ jsx(Menu, {
|
|
7814
|
+
items: INTENTION_VIEWS.map((option) => ({
|
|
7815
|
+
checked: option.value === place.intentionView,
|
|
7816
|
+
label: option.label,
|
|
7817
|
+
onSelect: () => place.selectIntentionView(option.value)
|
|
7818
|
+
})),
|
|
7819
|
+
trigger: {
|
|
7820
|
+
className: "icon-btn",
|
|
7821
|
+
content: /* @__PURE__ */ jsx(ViewOptionsIcon, {}),
|
|
7822
|
+
label: "Show intentions"
|
|
7823
|
+
}
|
|
7824
|
+
});
|
|
7825
|
+
}
|
|
7826
|
+
function tabOptions(detail) {
|
|
7827
|
+
return [
|
|
7828
|
+
{
|
|
7829
|
+
count: detail.proposals.filter((proposal) => proposal.mergedIntoId === null && proposal.attachment === null).length,
|
|
7830
|
+
icon: /* @__PURE__ */ jsx(IntentionIcon, {}),
|
|
7831
|
+
label: "Intentions",
|
|
7832
|
+
value: "proposals"
|
|
7833
|
+
},
|
|
7834
|
+
{
|
|
7835
|
+
count: null,
|
|
7836
|
+
icon: /* @__PURE__ */ jsx(TranscriptIcon, {}),
|
|
7837
|
+
label: "Transcript",
|
|
7838
|
+
value: "transcript"
|
|
7839
|
+
},
|
|
7840
|
+
{
|
|
7841
|
+
count: detail.evidence.length,
|
|
7842
|
+
icon: /* @__PURE__ */ jsx(ImageIcon, {}),
|
|
7843
|
+
label: "Evidence",
|
|
7844
|
+
value: "evidence"
|
|
7845
|
+
}
|
|
7846
|
+
];
|
|
7847
|
+
}
|
|
7848
|
+
function ReviewTabs({ detail, place }) {
|
|
7849
|
+
const canPickView = place.tab === "proposals" && calloutReport(detail).screens.length > 0;
|
|
7850
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7851
|
+
className: "dt-toolbar",
|
|
7852
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
7853
|
+
className: "dt-tabs",
|
|
7854
|
+
role: "tablist",
|
|
7855
|
+
children: tabOptions(detail).map((option) => /* @__PURE__ */ jsxs("button", {
|
|
7856
|
+
"aria-selected": option.value === place.tab,
|
|
7857
|
+
className: "dt-tab",
|
|
7858
|
+
onClick: () => place.selectTab(option.value),
|
|
7859
|
+
role: "tab",
|
|
7860
|
+
type: "button",
|
|
7861
|
+
children: [
|
|
7862
|
+
option.icon,
|
|
7863
|
+
option.label,
|
|
7864
|
+
option.count !== null && /* @__PURE__ */ jsx("span", {
|
|
7865
|
+
className: "dt-tab-count",
|
|
7866
|
+
children: option.count
|
|
7867
|
+
})
|
|
7868
|
+
]
|
|
7869
|
+
}, option.value))
|
|
7870
|
+
}), canPickView && /* @__PURE__ */ jsx(IntentionViewMenu, { place })]
|
|
7871
|
+
});
|
|
7872
|
+
}
|
|
7873
|
+
//#endregion
|
|
8254
7874
|
//#region src/sessions/ui/review/status-strip.tsx
|
|
8255
7875
|
function transcribingLine(detail) {
|
|
8256
7876
|
const voice = detail.segments.filter((segment) => segment.source === "voice");
|
|
@@ -8995,67 +8615,21 @@ function TranscriptTab({ detail, onShowMoment, review }) {
|
|
|
8995
8615
|
}
|
|
8996
8616
|
//#endregion
|
|
8997
8617
|
//#region src/sessions/ui/review/session-review.tsx
|
|
8998
|
-
function
|
|
8999
|
-
const
|
|
9000
|
-
return /* @__PURE__ */
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
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
|
-
function ReviewTabPanel({ context, place }) {
|
|
9044
|
-
const { detail, navigation, review } = context;
|
|
9045
|
-
if (place.tab === "proposals") return /* @__PURE__ */ jsx(ProposalsTab, {
|
|
9046
|
-
context,
|
|
9047
|
-
onSelectView: place.selectIntentionView,
|
|
9048
|
-
view: place.intentionView
|
|
9049
|
-
});
|
|
9050
|
-
if (place.tab === "transcript") return /* @__PURE__ */ jsx(TranscriptTab, {
|
|
9051
|
-
detail,
|
|
9052
|
-
onShowMoment: navigation.onShowMoment,
|
|
9053
|
-
review
|
|
9054
|
-
});
|
|
9055
|
-
return /* @__PURE__ */ jsx(EvidenceTab, {
|
|
9056
|
-
detail,
|
|
9057
|
-
onShowMoment: navigation.onShowMoment,
|
|
9058
|
-
review
|
|
8618
|
+
function ReviewTabPanel({ context, place }) {
|
|
8619
|
+
const { detail, navigation, review } = context;
|
|
8620
|
+
if (place.tab === "proposals") return /* @__PURE__ */ jsx(ProposalsTab, {
|
|
8621
|
+
context,
|
|
8622
|
+
view: place.intentionView
|
|
8623
|
+
});
|
|
8624
|
+
if (place.tab === "transcript") return /* @__PURE__ */ jsx(TranscriptTab, {
|
|
8625
|
+
detail,
|
|
8626
|
+
onShowMoment: navigation.onShowMoment,
|
|
8627
|
+
review
|
|
8628
|
+
});
|
|
8629
|
+
return /* @__PURE__ */ jsx(EvidenceTab, {
|
|
8630
|
+
detail,
|
|
8631
|
+
onShowMoment: navigation.onShowMoment,
|
|
8632
|
+
review
|
|
9059
8633
|
});
|
|
9060
8634
|
}
|
|
9061
8635
|
function useReviewPlace() {
|
|
@@ -9103,8 +8677,7 @@ function ReviewPanels({ context, place }) {
|
|
|
9103
8677
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9104
8678
|
/* @__PURE__ */ jsx(ReviewTabs, {
|
|
9105
8679
|
detail,
|
|
9106
|
-
|
|
9107
|
-
tab: place.tab
|
|
8680
|
+
place
|
|
9108
8681
|
}),
|
|
9109
8682
|
/* @__PURE__ */ jsx("div", {
|
|
9110
8683
|
className: "dt-ses-panel",
|
|
@@ -9132,7 +8705,7 @@ function ReviewTop({ context, links }) {
|
|
|
9132
8705
|
const { detail, review } = context;
|
|
9133
8706
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9134
8707
|
/* @__PURE__ */ jsx(ReviewHeader, {
|
|
9135
|
-
|
|
8708
|
+
onDeleted: links.onDeleted,
|
|
9136
8709
|
review,
|
|
9137
8710
|
session: detail.session
|
|
9138
8711
|
}),
|
|
@@ -9146,9 +8719,8 @@ function ReviewTop({ context, links }) {
|
|
|
9146
8719
|
})
|
|
9147
8720
|
] });
|
|
9148
8721
|
}
|
|
9149
|
-
function ReviewScreen({ detail, links, review }) {
|
|
8722
|
+
function ReviewScreen({ detail, isBriefOpen, links, review }) {
|
|
9150
8723
|
const place = useReviewPlace();
|
|
9151
|
-
const [isHandingOff, setIsHandingOff] = useState(false);
|
|
9152
8724
|
const context = {
|
|
9153
8725
|
actions: useProposalActions(review),
|
|
9154
8726
|
canEdit: detail.session.canEdit,
|
|
@@ -9162,9 +8734,8 @@ function ReviewScreen({ detail, links, review }) {
|
|
|
9162
8734
|
},
|
|
9163
8735
|
review
|
|
9164
8736
|
};
|
|
9165
|
-
if (
|
|
8737
|
+
if (isBriefOpen) return /* @__PURE__ */ jsx(HandoffView, {
|
|
9166
8738
|
detail,
|
|
9167
|
-
onClose: () => setIsHandingOff(false),
|
|
9168
8739
|
review
|
|
9169
8740
|
});
|
|
9170
8741
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -9176,13 +8747,13 @@ function ReviewScreen({ detail, links, review }) {
|
|
|
9176
8747
|
context,
|
|
9177
8748
|
place
|
|
9178
8749
|
}),
|
|
9179
|
-
context.canEdit && /* @__PURE__ */ jsx(
|
|
9180
|
-
|
|
9181
|
-
|
|
8750
|
+
context.canEdit && /* @__PURE__ */ jsx(ReviewFooter, {
|
|
8751
|
+
context,
|
|
8752
|
+
onOpenBrief: links.onOpenBrief
|
|
9182
8753
|
})
|
|
9183
8754
|
] });
|
|
9184
8755
|
}
|
|
9185
|
-
function SessionReview({ links, sessionId }) {
|
|
8756
|
+
function SessionReview({ isBriefOpen, links, sessionId }) {
|
|
9186
8757
|
const handle = useSessionDetail(sessionId);
|
|
9187
8758
|
const { state } = handle;
|
|
9188
8759
|
if (state.kind === "loading") return /* @__PURE__ */ jsx("p", {
|
|
@@ -9191,24 +8762,22 @@ function SessionReview({ links, sessionId }) {
|
|
|
9191
8762
|
});
|
|
9192
8763
|
if (state.kind === "ready") return /* @__PURE__ */ jsx(ReviewScreen, {
|
|
9193
8764
|
detail: state.detail,
|
|
8765
|
+
isBriefOpen,
|
|
9194
8766
|
links,
|
|
9195
8767
|
review: handle
|
|
9196
8768
|
});
|
|
8769
|
+
if (state.kind === "missing") return /* @__PURE__ */ jsx("p", {
|
|
8770
|
+
className: "dt-empty",
|
|
8771
|
+
children: "This session is gone: it was deleted or is no longer shared with you."
|
|
8772
|
+
});
|
|
9197
8773
|
return /* @__PURE__ */ jsxs("div", {
|
|
9198
8774
|
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
|
-
})]
|
|
8775
|
+
role: "alert",
|
|
8776
|
+
children: [/* @__PURE__ */ jsxs("p", { children: ["The session did not load: ", state.message] }), /* @__PURE__ */ jsx("button", {
|
|
8777
|
+
className: "dt-btn",
|
|
8778
|
+
onClick: handle.reload,
|
|
8779
|
+
type: "button",
|
|
8780
|
+
children: "Try again"
|
|
9212
8781
|
})]
|
|
9213
8782
|
});
|
|
9214
8783
|
}
|
|
@@ -9335,7 +8904,7 @@ function SessionList({ drafts, onOpen }) {
|
|
|
9335
8904
|
interruptedIds,
|
|
9336
8905
|
onOpen,
|
|
9337
8906
|
sessions: mine,
|
|
9338
|
-
title: "
|
|
8907
|
+
title: "Your sessions"
|
|
9339
8908
|
}),
|
|
9340
8909
|
/* @__PURE__ */ jsx(SessionGroup, {
|
|
9341
8910
|
interruptedIds,
|
|
@@ -9398,17 +8967,7 @@ function SessionsHome({ onOpenSession, onStarted, onWriteNote }) {
|
|
|
9398
8967
|
const { account } = useSessionWorkspace();
|
|
9399
8968
|
const drafts = useLocalDrafts(account.key);
|
|
9400
8969
|
const interrupted = drafts.filter((draft) => draft.state === "interrupted");
|
|
9401
|
-
const name = account.userName ?? account.userEmail ?? "you";
|
|
9402
8970
|
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
8971
|
interrupted.map((draft) => /* @__PURE__ */ jsx(InterruptedDraft, {
|
|
9413
8972
|
draft,
|
|
9414
8973
|
onOpenSession,
|
|
@@ -9426,6 +8985,32 @@ function SessionsHome({ onOpenSession, onStarted, onWriteNote }) {
|
|
|
9426
8985
|
}
|
|
9427
8986
|
//#endregion
|
|
9428
8987
|
//#region src/sessions/ui/sessions-panel.tsx
|
|
8988
|
+
const SESSIONS_HOME = { view: "home" };
|
|
8989
|
+
function useSessionNavigation() {
|
|
8990
|
+
const [place, setPlace] = useState(SESSIONS_HOME);
|
|
8991
|
+
return {
|
|
8992
|
+
go: setPlace,
|
|
8993
|
+
place
|
|
8994
|
+
};
|
|
8995
|
+
}
|
|
8996
|
+
/** Where the panel header's back button leads; null on the sessions home. */
|
|
8997
|
+
function sessionSheetPlace({ go, place }) {
|
|
8998
|
+
if (place.view === "home") return null;
|
|
8999
|
+
const sessionRef = place.target.sessionId ?? place.target.sessionKey ?? "";
|
|
9000
|
+
if (place.view === "review") return {
|
|
9001
|
+
backLabel: "Sessions",
|
|
9002
|
+
id: `review:${sessionRef}`,
|
|
9003
|
+
onBack: () => go(SESSIONS_HOME)
|
|
9004
|
+
};
|
|
9005
|
+
return {
|
|
9006
|
+
backLabel: "Session",
|
|
9007
|
+
id: `brief:${sessionRef}`,
|
|
9008
|
+
onBack: () => go({
|
|
9009
|
+
target: place.target,
|
|
9010
|
+
view: "review"
|
|
9011
|
+
})
|
|
9012
|
+
};
|
|
9013
|
+
}
|
|
9429
9014
|
function useResolvedSessionId(target) {
|
|
9430
9015
|
const { account } = useSessionWorkspace();
|
|
9431
9016
|
const drafts = useLocalDrafts(account.key);
|
|
@@ -9434,36 +9019,822 @@ function useResolvedSessionId(target) {
|
|
|
9434
9019
|
}
|
|
9435
9020
|
/** A just-finished session may not have reached Reflet yet: it opens once its id is known. */
|
|
9436
9021
|
function SessionsPanel({ navigation, onStarted, onWriteNote }) {
|
|
9437
|
-
const
|
|
9438
|
-
const
|
|
9439
|
-
|
|
9022
|
+
const { go, place } = navigation;
|
|
9023
|
+
const target = place.view === "home" ? null : place.target;
|
|
9024
|
+
const sessionId = useResolvedSessionId(target);
|
|
9025
|
+
if (!target) return /* @__PURE__ */ jsx(SessionsHome, {
|
|
9026
|
+
onOpenSession: (opened) => go({
|
|
9027
|
+
target: opened,
|
|
9028
|
+
view: "review"
|
|
9029
|
+
}),
|
|
9030
|
+
onStarted,
|
|
9031
|
+
onWriteNote
|
|
9032
|
+
});
|
|
9033
|
+
if (!sessionId) return /* @__PURE__ */ jsx("p", {
|
|
9034
|
+
className: "dt-empty",
|
|
9035
|
+
role: "status",
|
|
9036
|
+
children: "This session is still uploading. It opens here once it reaches Reflet."
|
|
9037
|
+
});
|
|
9038
|
+
return /* @__PURE__ */ jsx(SessionReview, {
|
|
9039
|
+
isBriefOpen: place.view === "brief",
|
|
9440
9040
|
links: {
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9041
|
+
onDeleted: () => go(SESSIONS_HOME),
|
|
9042
|
+
onOpenBrief: () => go({
|
|
9043
|
+
target,
|
|
9044
|
+
view: "brief"
|
|
9045
|
+
}),
|
|
9046
|
+
onOpenSession: (openedId) => go({
|
|
9047
|
+
target: {
|
|
9048
|
+
sessionId: openedId,
|
|
9049
|
+
sessionKey: null
|
|
9050
|
+
},
|
|
9051
|
+
view: "review"
|
|
9445
9052
|
}),
|
|
9446
9053
|
onStarted
|
|
9447
9054
|
},
|
|
9448
9055
|
sessionId
|
|
9449
9056
|
}, sessionId);
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9057
|
+
}
|
|
9058
|
+
//#endregion
|
|
9059
|
+
//#region src/sessions/ui/intention-styles.ts
|
|
9060
|
+
const INTENTION_STYLES = `
|
|
9061
|
+
.dt-ses-panel { display: contents; }
|
|
9062
|
+
.dt-ses-panel[hidden] { display: none; }
|
|
9063
|
+
.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; }
|
|
9064
|
+
.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); }
|
|
9065
|
+
.dt-ses-moment-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; overflow-wrap: anywhere; }
|
|
9066
|
+
.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; }
|
|
9067
|
+
.dt-ses-moment-notices { color: var(--rf-text-muted); font-size: 12px; }
|
|
9068
|
+
.dt-ses-moment-shot { display: flex; flex-direction: column; gap: 4px; margin: 0; max-width: 100%; }
|
|
9069
|
+
.dt-ses-shot-mark[data-match="approximate"] { border-style: dashed; }
|
|
9070
|
+
.dt-ses-shot-pointer {
|
|
9071
|
+
position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
|
|
9072
|
+
background: var(--rf-accent); box-shadow: 0 0 0 2px var(--rf-bg); pointer-events: none;
|
|
9073
|
+
}
|
|
9074
|
+
.dt-ses-source { margin: 0; font-size: 12px; overflow-wrap: anywhere; }
|
|
9075
|
+
.dt-ses-context-line { display: block; }
|
|
9076
|
+
.dt-ses-attached { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px; }
|
|
9077
|
+
.dt-ses-attached p { margin: 0; }
|
|
9078
|
+
.dt-ses-history[data-removed="true"] > .dt-ses-subhead { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9079
|
+
.dt-ses-change { padding: 8px 10px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); list-style: none; }
|
|
9080
|
+
.dt-ses-change[data-decision="rejected"] .dt-ses-diff { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9081
|
+
.dt-ses-diff { display: grid; grid-template-columns: auto 1fr; gap: 2px 8px; margin: 0; overflow-wrap: anywhere; }
|
|
9082
|
+
p.dt-ses-diff { display: block; }
|
|
9083
|
+
.dt-ses-diff dd { margin: 0; }
|
|
9084
|
+
.dt-card:focus-visible { outline: 2px solid var(--rf-accent); outline-offset: 2px; }
|
|
9085
|
+
`;
|
|
9086
|
+
//#endregion
|
|
9087
|
+
//#region src/sessions/ui/review/screens/report-styles.ts
|
|
9088
|
+
const REPORT_STYLES = `
|
|
9089
|
+
.dt-ses-report { display: flex; flex-direction: column; gap: 4px; width: 100%; min-width: 0; margin: 0; }
|
|
9090
|
+
.dt-ses-report-canvas { position: relative; width: 100%; }
|
|
9091
|
+
.dt-ses-report-canvas img { display: block; width: 100%; max-width: 100%; height: auto; border-radius: 8px; box-shadow: var(--rf-shadow-inset); }
|
|
9092
|
+
.dt-ses-report-canvas[data-measured="false"] .dt-ses-callout { visibility: hidden; }
|
|
9093
|
+
.dt-ses-report-mark { --dt-mark: var(--rf-accent); position: absolute; border: 2px solid var(--dt-mark); border-radius: 4px; pointer-events: none; }
|
|
9094
|
+
.dt-ses-report-lines { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
|
|
9095
|
+
.dt-ses-report-lines g { color: var(--rf-accent); }
|
|
9096
|
+
.dt-ses-report-lines line { stroke: currentColor; stroke-width: 1.5; }
|
|
9097
|
+
.dt-ses-report-lines circle { fill: currentColor; }
|
|
9098
|
+
.dt-ses-report-mark[data-decision="kept"], .dt-ses-report-lines g[data-decision="kept"] { --dt-mark: var(--rf-success); color: var(--rf-success); }
|
|
9099
|
+
.dt-ses-report-mark[data-decision="dismissed"], .dt-ses-report-lines g[data-decision="dismissed"] { opacity: .35; }
|
|
9100
|
+
.dt-ses-callouts { margin: 0; padding: 0; list-style: none; }
|
|
9101
|
+
.dt-ses-callouts[data-flow="list"] { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
|
|
9102
|
+
.dt-ses-callout {
|
|
9103
|
+
display: flex; align-items: center; gap: 4px; max-width: 100%; padding: 3px; border-radius: var(--rf-pill);
|
|
9104
|
+
background: var(--rf-bg); box-shadow: var(--rf-shadow-inset), var(--rf-shadow-low); font-size: 12px; line-height: 1.3;
|
|
9105
|
+
}
|
|
9106
|
+
.dt-ses-report-canvas .dt-ses-callout { position: absolute; top: 0; left: 0; width: max-content; max-width: min(280px, 100%); }
|
|
9107
|
+
.dt-ses-callout-number {
|
|
9108
|
+
display: grid; place-items: center; flex: none; min-width: 20px; height: 20px; padding: 0 5px; border-radius: var(--rf-pill);
|
|
9109
|
+
background: var(--rf-accent); color: var(--rf-accent-text, #fff); font-size: 11px; font-weight: 650; font-variant-numeric: tabular-nums;
|
|
9110
|
+
}
|
|
9111
|
+
.dt-ses-callout[data-decision="kept"] .dt-ses-callout-number { background: var(--rf-success); }
|
|
9112
|
+
.dt-ses-callout[data-decision="dismissed"] .dt-ses-callout-number { background: var(--rf-text-muted); }
|
|
9113
|
+
.dt-ses-callout-label { min-width: 0; padding: 0 4px; font-weight: 550; text-align: left; overflow-wrap: anywhere; }
|
|
9114
|
+
.dt-ses-callout-label:hover { color: var(--rf-accent); }
|
|
9115
|
+
.dt-ses-callout[data-decision="dismissed"] .dt-ses-callout-label { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9116
|
+
.dt-ses-callout-btn {
|
|
9117
|
+
display: grid; place-items: center; flex: none; width: 22px; height: 22px; border-radius: 50%; color: var(--rf-text-muted);
|
|
9118
|
+
transition: background-color 120ms var(--rf-ease), color 120ms var(--rf-ease);
|
|
9119
|
+
}
|
|
9120
|
+
.dt-ses-callout-btn svg { width: 13px; height: 13px; }
|
|
9121
|
+
.dt-ses-callout-btn:hover { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
9122
|
+
.dt-ses-callout-btn[data-decision="kept"][aria-pressed="true"] { background: var(--rf-success); color: #fff; }
|
|
9123
|
+
.dt-ses-callout-btn[data-decision="dismissed"][aria-pressed="true"] { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
9124
|
+
`;
|
|
9125
|
+
//#endregion
|
|
9126
|
+
//#region src/sessions/ui/sessions-styles.ts
|
|
9127
|
+
const MONO_FONT$1 = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
9128
|
+
const SESSIONS_STYLES = `${`
|
|
9129
|
+
.dt-rec {
|
|
9130
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; left: 50%; translate: -50% 0;
|
|
9131
|
+
bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + 16px);
|
|
9132
|
+
display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px;
|
|
9133
|
+
max-width: calc(100vw - 24px); padding: 6px 6px 6px 12px; border-radius: var(--dt-radius-surface);
|
|
9134
|
+
animation: dt-rec-in 240ms var(--rf-ease);
|
|
9135
|
+
}
|
|
9136
|
+
@keyframes dt-rec-in { from { transform: translateY(8px); opacity: 0; } }
|
|
9137
|
+
.dt-rec-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--rf-danger); }
|
|
9138
|
+
.dt-rec[data-phase="recording"] .dt-rec-dot { animation: dt-rec-pulse 1.6s ease-in-out infinite; }
|
|
9139
|
+
.dt-rec[data-phase="paused"] .dt-rec-dot, .dt-rec[data-phase="finishing"] .dt-rec-dot { background: var(--rf-text-muted); }
|
|
9140
|
+
@keyframes dt-rec-pulse { 50% { opacity: .35; } }
|
|
9141
|
+
.dt-rec-meter { display: inline-flex; align-items: center; gap: 2px; height: 16px; }
|
|
9142
|
+
.dt-rec-meter span {
|
|
9143
|
+
width: 3px; height: 100%; border-radius: 2px; background: var(--rf-text-muted);
|
|
9144
|
+
scale: 1 calc(.2 + var(--dt-level, 0) * .8); transition: scale 90ms linear;
|
|
9145
|
+
}
|
|
9146
|
+
.dt-rec-meter span:nth-child(2) { scale: 1 calc(.2 + var(--dt-level, 0)); }
|
|
9147
|
+
.dt-rec-time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 5ch; }
|
|
9148
|
+
.dt-rec-status { color: var(--rf-text-muted); font-size: 12px; overflow-wrap: anywhere; }
|
|
9149
|
+
.dt-rec-status:empty { display: none; }
|
|
9150
|
+
.dt-rec-note { display: flex; align-items: center; gap: 6px; flex: 1 1 100%; font-size: 12px; color: var(--rf-text-muted); }
|
|
9151
|
+
.dt-rec-note .dt-field { flex: 1; min-width: 0; padding: 4px 8px; }
|
|
9152
|
+
`}
|
|
9153
|
+
.dt-ses-subhead, .dt-ses-label { margin: 0 0 4px; font-size: 12px; font-weight: 600; color: var(--rf-text); }
|
|
9154
|
+
.dt-ses-label { font-size: 11px; color: var(--rf-text-muted); }
|
|
9155
|
+
.dt-ses-list { margin: 0; padding-left: 18px; overflow-wrap: anywhere; }
|
|
9156
|
+
.dt-ses-list li + li { margin-top: 3px; }
|
|
9157
|
+
.dt-ses-link { align-self: flex-start; padding: 0; color: var(--rf-accent); font-size: 12px; text-align: left; }
|
|
9158
|
+
.dt-ses-link:hover { text-decoration: underline; }
|
|
9159
|
+
.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; }
|
|
9160
|
+
.dt-ses-banner { padding: 8px 10px; border-radius: var(--dt-radius-card); background: color-mix(in srgb, var(--rf-accent) 10%, transparent); }
|
|
9161
|
+
.dt-ses-banner p { margin: 0; overflow-wrap: anywhere; }
|
|
9162
|
+
.dt-ses-strip:empty { display: none; }
|
|
9163
|
+
.dt-ses-rows { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; list-style: none; }
|
|
9164
|
+
.dt-ses-row {
|
|
9165
|
+
display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
|
|
9166
|
+
padding: 8px 10px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); text-align: left;
|
|
9167
|
+
}
|
|
9168
|
+
button.dt-ses-row:hover { background: var(--rf-bg-hover); }
|
|
9169
|
+
.dt-ses-row .dt-card-title { max-width: 100%; }
|
|
9170
|
+
${`
|
|
9171
|
+
.dt-ses-title { flex: 1; min-width: 0; margin: 0; font-size: 15px; font-weight: 650; overflow-wrap: anywhere; }
|
|
9172
|
+
.dt-ses-head .dt-menu > .icon-btn { width: 30px; height: 30px; }
|
|
9173
|
+
.dt-btn[data-icon-only] { justify-content: center; width: 28px; padding: 0; }
|
|
9174
|
+
.dt-ses-field { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; color: var(--rf-text-muted); }
|
|
9175
|
+
.dt-ses-need {
|
|
9176
|
+
margin: 0; font-weight: 600; overflow-wrap: anywhere;
|
|
9177
|
+
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
|
|
9178
|
+
}
|
|
9179
|
+
.dt-ses-need[data-expanded="true"] { display: block; }
|
|
9180
|
+
.dt-card[data-decision="dismissed"] .dt-ses-need { color: var(--rf-text-muted); text-decoration: line-through; }
|
|
9181
|
+
.dt-ses-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
9182
|
+
.dt-ses-chips:empty { display: none; }
|
|
9183
|
+
.dt-ses-details { display: flex; flex-direction: column; gap: 8px; }
|
|
9184
|
+
.dt-ses-details[hidden] { display: none; }
|
|
9185
|
+
.dt-ses-details section { display: flex; flex-direction: column; gap: 2px; }
|
|
9186
|
+
.dt-ses-quote { padding: 2px 0; font-size: 12px; text-align: left; overflow-wrap: anywhere; }
|
|
9187
|
+
.dt-ses-quote:hover { color: var(--rf-accent); }
|
|
9188
|
+
.dt-ses-time { flex: none; color: var(--rf-text-muted); font: 11.5px ${MONO_FONT$1}; font-variant-numeric: tabular-nums; }
|
|
9189
|
+
.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); }
|
|
9190
|
+
.dt-ses-timeline { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
|
|
9191
|
+
.dt-ses-seg { display: flex; gap: 8px; padding: 6px 8px; border-radius: var(--dt-radius-field); }
|
|
9192
|
+
.dt-ses-seg:focus { outline: 2px solid var(--rf-accent); outline-offset: -2px; }
|
|
9193
|
+
.dt-ses-seg[data-kind="note"] { padding-block: 2px; }
|
|
9194
|
+
.dt-ses-seg-body { display: flex; flex: 1; flex-direction: column; gap: 4px; min-width: 0; }
|
|
9195
|
+
`}${`
|
|
9196
|
+
.dt-ses-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
9197
|
+
.dt-ses-shot { position: relative; display: inline-block; max-width: 100%; line-height: 0; }
|
|
9198
|
+
.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); }
|
|
9199
|
+
.dt-ses-shot[data-large="true"] img { max-height: none; }
|
|
9200
|
+
.dt-ses-shot-mark { position: absolute; border: 2px solid var(--rf-accent); border-radius: var(--dt-radius-tiny); pointer-events: none; }
|
|
9201
|
+
.dt-ses-shot-btn { align-self: flex-start; padding: 0; border-radius: var(--dt-radius-field); }
|
|
9202
|
+
.dt-ses-start { display: flex; flex-direction: column; gap: 8px; }
|
|
9203
|
+
.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; }
|
|
9204
|
+
.dt-ses-brief-entry > summary::-webkit-details-marker { display: none; }
|
|
9205
|
+
.dt-ses-brief-entry > summary:hover { background: var(--rf-bg-hover); }
|
|
9206
|
+
.dt-ses-brief-entry[open] > summary { margin-bottom: 6px; }
|
|
9207
|
+
.dt-ses-check { display: flex; align-items: flex-start; gap: 6px; overflow-wrap: anywhere; }
|
|
9208
|
+
.dt-ses-check input { flex: none; margin-top: 3px; accent-color: var(--rf-accent); }
|
|
9209
|
+
.dt-ses-choices { margin: 0; padding: 0; border: 0; }
|
|
9210
|
+
.dt-ses-choices .dt-ses-list { padding-left: 0; list-style: none; }
|
|
9211
|
+
.dt-ses-brief {
|
|
9212
|
+
max-height: 50vh; overflow: auto; margin: 0; padding: 10px; border-radius: var(--dt-radius-card);
|
|
9213
|
+
background: var(--rf-bg-subtle); font: 11.5px/1.55 ${MONO_FONT$1}; white-space: pre-wrap; overflow-wrap: anywhere;
|
|
9214
|
+
}
|
|
9215
|
+
`}${`
|
|
9216
|
+
.dt-team-anchor {
|
|
9217
|
+
--dt-edge-gap: calc(max(var(--rf-offset), 12px) + 48px);
|
|
9218
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; width: min(300px, calc(100vw - 24px));
|
|
9219
|
+
}
|
|
9220
|
+
.dt-team-anchor[data-side="left"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }
|
|
9221
|
+
.dt-team-anchor[data-side="right"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }
|
|
9222
|
+
.dt-team-anchor[data-edge="bottom"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }
|
|
9223
|
+
.dt-team-anchor[data-edge="top"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }
|
|
9224
|
+
.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); }
|
|
9225
|
+
.dt-bar > .dt-btn { margin-inline: 2px 4px; }
|
|
9226
|
+
`}${INTENTION_STYLES}${REPORT_STYLES}`;
|
|
9227
|
+
//#endregion
|
|
9228
|
+
//#region src/devtools/client/account/account-footer.tsx
|
|
9229
|
+
const WHITESPACE = /\s+/;
|
|
9230
|
+
function initials(text) {
|
|
9231
|
+
return text.split(WHITESPACE).filter(Boolean).slice(0, 2).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
9232
|
+
}
|
|
9233
|
+
function Avatar({ image, name }) {
|
|
9234
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
9235
|
+
"aria-hidden": "true",
|
|
9236
|
+
className: "dt-avatar",
|
|
9237
|
+
children: [initials(name), image && /* @__PURE__ */ jsx("img", {
|
|
9238
|
+
alt: "",
|
|
9239
|
+
height: 28,
|
|
9240
|
+
referrerPolicy: "no-referrer",
|
|
9241
|
+
src: image,
|
|
9242
|
+
width: 28
|
|
9458
9243
|
})]
|
|
9459
9244
|
});
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9245
|
+
}
|
|
9246
|
+
function AccountFooter({ actions, organizationName, person }) {
|
|
9247
|
+
const name = person?.name ?? person?.email ?? null;
|
|
9248
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9249
|
+
/* @__PURE__ */ jsx(Avatar, {
|
|
9250
|
+
image: person?.image ?? null,
|
|
9251
|
+
name: name ?? organizationName
|
|
9252
|
+
}),
|
|
9253
|
+
/* @__PURE__ */ jsxs("span", {
|
|
9254
|
+
className: "dt-account-text",
|
|
9255
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
9256
|
+
className: "dt-account-name",
|
|
9257
|
+
children: name ?? organizationName
|
|
9258
|
+
}), name && /* @__PURE__ */ jsx("span", {
|
|
9259
|
+
className: "dt-meta",
|
|
9260
|
+
children: organizationName
|
|
9261
|
+
})]
|
|
9262
|
+
}),
|
|
9263
|
+
/* @__PURE__ */ jsx(ChevronUpDownIcon, {})
|
|
9264
|
+
] });
|
|
9265
|
+
return /* @__PURE__ */ jsx("div", {
|
|
9266
|
+
className: "dt-sheet-account",
|
|
9267
|
+
children: /* @__PURE__ */ jsx(Menu, {
|
|
9268
|
+
items: actions,
|
|
9269
|
+
placement: "above",
|
|
9270
|
+
trigger: {
|
|
9271
|
+
className: "dt-account",
|
|
9272
|
+
content,
|
|
9273
|
+
label: name ? `${name}, ${organizationName}` : organizationName
|
|
9274
|
+
}
|
|
9275
|
+
})
|
|
9276
|
+
});
|
|
9277
|
+
}
|
|
9278
|
+
function AccountNote({ children }) {
|
|
9279
|
+
return /* @__PURE__ */ jsx("div", {
|
|
9280
|
+
className: "dt-sheet-account",
|
|
9281
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
9282
|
+
className: "dt-meta",
|
|
9283
|
+
children
|
|
9284
|
+
})
|
|
9464
9285
|
});
|
|
9465
9286
|
}
|
|
9466
9287
|
//#endregion
|
|
9467
|
-
|
|
9288
|
+
//#region src/devtools/client/devtools-bar.tsx
|
|
9289
|
+
const BAR_POSITION_KEY = "reflet-devtools-bar-position";
|
|
9290
|
+
const PICK_BUTTON_LABEL = "Pick an element: note it, copy it, or Shift+click to open its code";
|
|
9291
|
+
const SHEET_TABS = [
|
|
9292
|
+
"inbox",
|
|
9293
|
+
"notes",
|
|
9294
|
+
"sessions",
|
|
9295
|
+
"code"
|
|
9296
|
+
];
|
|
9297
|
+
function BarButton({ children, label, onClick }) {
|
|
9298
|
+
return /* @__PURE__ */ jsx("button", {
|
|
9299
|
+
"aria-label": label,
|
|
9300
|
+
className: "icon-btn",
|
|
9301
|
+
onClick,
|
|
9302
|
+
title: label,
|
|
9303
|
+
type: "button",
|
|
9304
|
+
children
|
|
9305
|
+
});
|
|
9306
|
+
}
|
|
9307
|
+
function DevtoolsBar({ children, edge, label = "Reflet devtools", side }) {
|
|
9308
|
+
const floating = useFloatingPosition(`${edge}-${side}`, false, {
|
|
9309
|
+
anchorSelector: ".dt-bar",
|
|
9310
|
+
persistKey: BAR_POSITION_KEY
|
|
9311
|
+
});
|
|
9312
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
9313
|
+
"aria-label": label,
|
|
9314
|
+
className: "dt-bar glass",
|
|
9315
|
+
"data-edge": edge,
|
|
9316
|
+
"data-moved": floating.position !== null,
|
|
9317
|
+
"data-side": side,
|
|
9318
|
+
ref: floating.rootRef,
|
|
9319
|
+
role: "toolbar",
|
|
9320
|
+
children: [
|
|
9321
|
+
/* @__PURE__ */ jsx("style", { children: floating.styles }),
|
|
9322
|
+
/* @__PURE__ */ jsx("button", {
|
|
9323
|
+
"aria-label": `Move ${label} (double-click to reset)`,
|
|
9324
|
+
className: "icon-btn drag-handle dt-grip",
|
|
9325
|
+
onDoubleClick: floating.resetPosition,
|
|
9326
|
+
title: "Drag to move · double-click to reset",
|
|
9327
|
+
type: "button",
|
|
9328
|
+
...floating.handleProps,
|
|
9329
|
+
children: /* @__PURE__ */ jsx(GripIcon, {})
|
|
9330
|
+
}),
|
|
9331
|
+
children
|
|
9332
|
+
]
|
|
9333
|
+
});
|
|
9334
|
+
}
|
|
9335
|
+
function SessionsBarButton({ onOpen }) {
|
|
9336
|
+
return /* @__PURE__ */ jsx(BarButton, {
|
|
9337
|
+
label: "Sessions",
|
|
9338
|
+
onClick: onOpen,
|
|
9339
|
+
children: /* @__PURE__ */ jsx(MicIcon, {})
|
|
9340
|
+
});
|
|
9341
|
+
}
|
|
9342
|
+
function panelLabel(unsentNoteCount) {
|
|
9343
|
+
if (unsentNoteCount === 0) return "Open the Reflet panel";
|
|
9344
|
+
return `Open the Reflet panel (${unsentNoteCount} ${unsentNoteCount === 1 ? "note" : "notes"} not on the board)`;
|
|
9345
|
+
}
|
|
9346
|
+
function DevtoolsBarButtons({ onOpen, onPick, unsentNoteCount }) {
|
|
9347
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9348
|
+
/* @__PURE__ */ jsx(BarButton, {
|
|
9349
|
+
label: PICK_BUTTON_LABEL,
|
|
9350
|
+
onClick: onPick,
|
|
9351
|
+
children: /* @__PURE__ */ jsx(TargetIcon, {})
|
|
9352
|
+
}),
|
|
9353
|
+
/* @__PURE__ */ jsx(SessionsBarButton, { onOpen: () => onOpen("sessions") }),
|
|
9354
|
+
/* @__PURE__ */ jsxs(BarButton, {
|
|
9355
|
+
label: panelLabel(unsentNoteCount),
|
|
9356
|
+
onClick: () => onOpen(null),
|
|
9357
|
+
children: [/* @__PURE__ */ jsx(PanelIcon, {}), unsentNoteCount > 0 && /* @__PURE__ */ jsx("span", {
|
|
9358
|
+
className: "dt-count",
|
|
9359
|
+
children: unsentNoteCount
|
|
9360
|
+
})]
|
|
9361
|
+
})
|
|
9362
|
+
] });
|
|
9363
|
+
}
|
|
9364
|
+
//#endregion
|
|
9365
|
+
//#region src/devtools/client/use-sheet-size.ts
|
|
9366
|
+
const SIZE_KEY = "reflet-devtools-sheet-size";
|
|
9367
|
+
const DEFAULT_WIDTH = 480;
|
|
9368
|
+
const MIN_WIDTH = 320;
|
|
9369
|
+
const MIN_HEIGHT = 240;
|
|
9370
|
+
const KEYBOARD_STEP = 24;
|
|
9371
|
+
const ARROW_DELTAS = {
|
|
9372
|
+
ArrowDown: {
|
|
9373
|
+
dx: 0,
|
|
9374
|
+
dy: KEYBOARD_STEP
|
|
9375
|
+
},
|
|
9376
|
+
ArrowLeft: {
|
|
9377
|
+
dx: -24,
|
|
9378
|
+
dy: 0
|
|
9379
|
+
},
|
|
9380
|
+
ArrowRight: {
|
|
9381
|
+
dx: KEYBOARD_STEP,
|
|
9382
|
+
dy: 0
|
|
9383
|
+
},
|
|
9384
|
+
ArrowUp: {
|
|
9385
|
+
dx: 0,
|
|
9386
|
+
dy: -24
|
|
9387
|
+
}
|
|
9388
|
+
};
|
|
9389
|
+
function readStoredSize() {
|
|
9390
|
+
const fallback = {
|
|
9391
|
+
height: null,
|
|
9392
|
+
width: DEFAULT_WIDTH
|
|
9393
|
+
};
|
|
9394
|
+
try {
|
|
9395
|
+
const stored = JSON.parse(localStorage.getItem(SIZE_KEY) ?? "null");
|
|
9396
|
+
if (typeof stored === "object" && stored !== null && "width" in stored && typeof stored.width === "number" && "height" in stored && (stored.height === null || typeof stored.height === "number")) return {
|
|
9397
|
+
height: stored.height,
|
|
9398
|
+
width: stored.width
|
|
9399
|
+
};
|
|
9400
|
+
} catch {
|
|
9401
|
+
return fallback;
|
|
9402
|
+
}
|
|
9403
|
+
return fallback;
|
|
9404
|
+
}
|
|
9405
|
+
/**
|
|
9406
|
+
* The stored size is the preference; what renders is that preference fitted
|
|
9407
|
+
* to today's window, so shrinking the window never loses the chosen size.
|
|
9408
|
+
*/
|
|
9409
|
+
function fitted(size, viewport) {
|
|
9410
|
+
const maxWidth = viewport.width - 24;
|
|
9411
|
+
const maxHeight = viewport.height - 24;
|
|
9412
|
+
return {
|
|
9413
|
+
height: size.height === null || size.height >= maxHeight ? null : Math.max(Math.min(MIN_HEIGHT, maxHeight), size.height),
|
|
9414
|
+
width: Math.min(maxWidth, Math.max(MIN_WIDTH, size.width))
|
|
9415
|
+
};
|
|
9416
|
+
}
|
|
9417
|
+
/**
|
|
9418
|
+
* Width grows away from the docked side, height grows downward from the top;
|
|
9419
|
+
* a height reaching the bottom of the window snaps back to full height.
|
|
9420
|
+
*/
|
|
9421
|
+
function useSheetSize(side) {
|
|
9422
|
+
const [preference, setPreference] = useState(readStoredSize);
|
|
9423
|
+
const [viewport, setViewport] = useState(visibleViewport);
|
|
9424
|
+
const drag = useRef(null);
|
|
9425
|
+
const widthDirection = side === "right" ? -1 : 1;
|
|
9426
|
+
const size = fitted(preference, viewport);
|
|
9427
|
+
useEffect(() => onViewportChange(() => setViewport(visibleViewport())), []);
|
|
9428
|
+
useEffect(() => {
|
|
9429
|
+
try {
|
|
9430
|
+
localStorage.setItem(SIZE_KEY, JSON.stringify(preference));
|
|
9431
|
+
} catch {}
|
|
9432
|
+
}, [preference]);
|
|
9433
|
+
const resize = (axis, from, dx, dy) => {
|
|
9434
|
+
const fullHeight = viewport.height - 24;
|
|
9435
|
+
setPreference(fitted({
|
|
9436
|
+
height: axis === "width" ? from.height : (from.height ?? fullHeight) + dy,
|
|
9437
|
+
width: axis === "height" ? from.width : from.width + dx * widthDirection
|
|
9438
|
+
}, viewport));
|
|
9439
|
+
};
|
|
9440
|
+
const handleProps = (axis) => ({
|
|
9441
|
+
onDoubleClick: () => setPreference((current) => ({
|
|
9442
|
+
height: axis === "width" ? current.height : null,
|
|
9443
|
+
width: axis === "height" ? current.width : DEFAULT_WIDTH
|
|
9444
|
+
})),
|
|
9445
|
+
onKeyDown: (event) => {
|
|
9446
|
+
const delta = ARROW_DELTAS[event.key];
|
|
9447
|
+
if (!delta) return;
|
|
9448
|
+
event.preventDefault();
|
|
9449
|
+
const sheetHeight = event.currentTarget.parentElement?.getBoundingClientRect().height ?? null;
|
|
9450
|
+
resize(axis, {
|
|
9451
|
+
height: size.height ?? sheetHeight,
|
|
9452
|
+
width: size.width
|
|
9453
|
+
}, delta.dx, delta.dy);
|
|
9454
|
+
},
|
|
9455
|
+
onLostPointerCapture: () => {
|
|
9456
|
+
drag.current = null;
|
|
9457
|
+
},
|
|
9458
|
+
onPointerDown: (event) => {
|
|
9459
|
+
if (event.button !== 0) return;
|
|
9460
|
+
const sheet = event.currentTarget.parentElement?.getBoundingClientRect();
|
|
9461
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
9462
|
+
drag.current = {
|
|
9463
|
+
axis,
|
|
9464
|
+
size: {
|
|
9465
|
+
height: sheet?.height ?? size.height,
|
|
9466
|
+
width: size.width
|
|
9467
|
+
},
|
|
9468
|
+
x: event.clientX,
|
|
9469
|
+
y: event.clientY
|
|
9470
|
+
};
|
|
9471
|
+
},
|
|
9472
|
+
onPointerMove: (event) => {
|
|
9473
|
+
const start = drag.current;
|
|
9474
|
+
if (start && event.currentTarget.hasPointerCapture(event.pointerId)) resize(start.axis, start.size, event.clientX - start.x, event.clientY - start.y);
|
|
9475
|
+
}
|
|
9476
|
+
});
|
|
9477
|
+
return {
|
|
9478
|
+
handleProps,
|
|
9479
|
+
size
|
|
9480
|
+
};
|
|
9481
|
+
}
|
|
9482
|
+
//#endregion
|
|
9483
|
+
//#region src/devtools/client/devtools-sheet.tsx
|
|
9484
|
+
const FULL_HEIGHT = "calc(100dvh - 24px)";
|
|
9485
|
+
const TABS = {
|
|
9486
|
+
code: {
|
|
9487
|
+
icon: /* @__PURE__ */ jsx(CodeIcon, {}),
|
|
9488
|
+
label: "Code"
|
|
9489
|
+
},
|
|
9490
|
+
inbox: {
|
|
9491
|
+
icon: /* @__PURE__ */ jsx(InboxIcon, {}),
|
|
9492
|
+
label: "Board"
|
|
9493
|
+
},
|
|
9494
|
+
notes: {
|
|
9495
|
+
icon: /* @__PURE__ */ jsx(NotesIcon, {}),
|
|
9496
|
+
label: "Notes"
|
|
9497
|
+
},
|
|
9498
|
+
sessions: {
|
|
9499
|
+
icon: /* @__PURE__ */ jsx(MicIcon, {}),
|
|
9500
|
+
label: "Sessions"
|
|
9501
|
+
}
|
|
9502
|
+
};
|
|
9503
|
+
const SHEET_POSITION_KEY = "reflet-devtools-sheet-position";
|
|
9504
|
+
function useSheetFocus(rootRef) {
|
|
9505
|
+
useLayoutEffect(() => {
|
|
9506
|
+
const root = rootRef.current;
|
|
9507
|
+
const opener = root ? focusedElementAround(root) : null;
|
|
9508
|
+
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 });
|
|
9509
|
+
return () => {
|
|
9510
|
+
queueMicrotask(() => {
|
|
9511
|
+
if (opener instanceof HTMLElement && opener.isConnected) opener.focus({ preventScroll: true });
|
|
9512
|
+
});
|
|
9513
|
+
};
|
|
9514
|
+
}, [rootRef]);
|
|
9515
|
+
}
|
|
9516
|
+
const ROOT_FOCUS_SELECTOR = "[role=\"tab\"][aria-selected=\"true\"], .dt-sheet-title";
|
|
9517
|
+
function nestedViewStart(root) {
|
|
9518
|
+
return root.querySelector(".dt-sheet-body h2") ?? root.querySelector(".dt-sheet-body");
|
|
9519
|
+
}
|
|
9520
|
+
/** Lands keyboard users at the top of the view they moved to, never on a control that changed meaning. */
|
|
9521
|
+
function useFocusOnNavigation(rootRef, placeId) {
|
|
9522
|
+
const shownPlaceId = useRef(placeId);
|
|
9523
|
+
useLayoutEffect(() => {
|
|
9524
|
+
const root = rootRef.current;
|
|
9525
|
+
if (shownPlaceId.current === placeId || !root) return;
|
|
9526
|
+
shownPlaceId.current = placeId;
|
|
9527
|
+
const body = root.querySelector(".dt-sheet-body");
|
|
9528
|
+
if (body) body.scrollTop = 0;
|
|
9529
|
+
(placeId === null ? root.querySelector(ROOT_FOCUS_SELECTOR) : nestedViewStart(root))?.focus({ preventScroll: true });
|
|
9530
|
+
}, [placeId, rootRef]);
|
|
9531
|
+
}
|
|
9532
|
+
function SheetNavigation({ onSelectTab, place, tab, tabs }) {
|
|
9533
|
+
if (place) return /* @__PURE__ */ jsxs("button", {
|
|
9534
|
+
"aria-label": `Back to ${place.backLabel}`,
|
|
9535
|
+
className: "dt-sheet-back",
|
|
9536
|
+
onClick: place.onBack,
|
|
9537
|
+
type: "button",
|
|
9538
|
+
children: [/* @__PURE__ */ jsx(ChevronLeftIcon, {}), place.backLabel]
|
|
9539
|
+
});
|
|
9540
|
+
if (tabs.length === 1) return /* @__PURE__ */ jsxs("h2", {
|
|
9541
|
+
className: "dt-sheet-title",
|
|
9542
|
+
tabIndex: -1,
|
|
9543
|
+
children: [TABS[tab].icon, TABS[tab].label]
|
|
9544
|
+
});
|
|
9545
|
+
return /* @__PURE__ */ jsx("div", {
|
|
9546
|
+
className: "dt-tabs",
|
|
9547
|
+
role: "tablist",
|
|
9548
|
+
children: tabs.map((option) => /* @__PURE__ */ jsxs("button", {
|
|
9549
|
+
"aria-selected": option === tab,
|
|
9550
|
+
className: "dt-tab",
|
|
9551
|
+
onClick: () => onSelectTab(option),
|
|
9552
|
+
role: "tab",
|
|
9553
|
+
type: "button",
|
|
9554
|
+
children: [TABS[option].icon, TABS[option].label]
|
|
9555
|
+
}, option))
|
|
9556
|
+
});
|
|
9557
|
+
}
|
|
9558
|
+
function DevtoolsSheet({ children, footer, label = "Reflet devtools", navigation, onClose, side }) {
|
|
9559
|
+
const { handleProps, size } = useSheetSize(side);
|
|
9560
|
+
const floating = useFloatingPosition(`top-${side}`, false, {
|
|
9561
|
+
anchorSelector: ".dt-sheet",
|
|
9562
|
+
persistKey: SHEET_POSITION_KEY
|
|
9563
|
+
});
|
|
9564
|
+
const isMoved = floating.position !== null;
|
|
9565
|
+
const { rootRef } = floating;
|
|
9566
|
+
useSheetFocus(rootRef);
|
|
9567
|
+
useFocusOnNavigation(rootRef, navigation.place?.id ?? null);
|
|
9568
|
+
useEffect(() => listenToKeydown(rootRef.current, (event) => {
|
|
9569
|
+
if (event.key === "Escape" && !event.isComposing) onClose();
|
|
9570
|
+
}), [onClose, rootRef]);
|
|
9571
|
+
return /* @__PURE__ */ jsxs("aside", {
|
|
9572
|
+
"aria-label": label,
|
|
9573
|
+
className: "dt-sheet glass",
|
|
9574
|
+
"data-moved": isMoved,
|
|
9575
|
+
"data-side": side,
|
|
9576
|
+
ref: rootRef,
|
|
9577
|
+
style: {
|
|
9578
|
+
height: size.height ?? (isMoved ? FULL_HEIGHT : void 0),
|
|
9579
|
+
width: size.width
|
|
9580
|
+
},
|
|
9581
|
+
children: [
|
|
9582
|
+
/* @__PURE__ */ jsx("style", { children: floating.styles }),
|
|
9583
|
+
/* @__PURE__ */ jsx("button", {
|
|
9584
|
+
"aria-label": "Resize panel width (double-click to reset)",
|
|
9585
|
+
className: "dt-resize",
|
|
9586
|
+
"data-axis": "width",
|
|
9587
|
+
type: "button",
|
|
9588
|
+
...handleProps("width")
|
|
9589
|
+
}),
|
|
9590
|
+
/* @__PURE__ */ jsx("button", {
|
|
9591
|
+
"aria-label": "Resize panel height (double-click for full height)",
|
|
9592
|
+
className: "dt-resize",
|
|
9593
|
+
"data-axis": "height",
|
|
9594
|
+
type: "button",
|
|
9595
|
+
...handleProps("height")
|
|
9596
|
+
}),
|
|
9597
|
+
/* @__PURE__ */ jsx("button", {
|
|
9598
|
+
"aria-label": "Resize panel (double-click to reset)",
|
|
9599
|
+
className: "dt-resize",
|
|
9600
|
+
"data-axis": "both",
|
|
9601
|
+
type: "button",
|
|
9602
|
+
...handleProps("both")
|
|
9603
|
+
}),
|
|
9604
|
+
/* @__PURE__ */ jsxs("div", {
|
|
9605
|
+
className: "dt-sheet-head",
|
|
9606
|
+
children: [
|
|
9607
|
+
/* @__PURE__ */ jsx("button", {
|
|
9608
|
+
"aria-label": "Move panel (double-click to dock it back)",
|
|
9609
|
+
className: "dt-sheet-drag",
|
|
9610
|
+
onDoubleClick: floating.resetPosition,
|
|
9611
|
+
title: "Drag to move · double-click to dock",
|
|
9612
|
+
type: "button",
|
|
9613
|
+
...floating.handleProps
|
|
9614
|
+
}),
|
|
9615
|
+
/* @__PURE__ */ jsx(SheetNavigation, { ...navigation }),
|
|
9616
|
+
/* @__PURE__ */ jsx("button", {
|
|
9617
|
+
"aria-label": `Close ${label} panel`,
|
|
9618
|
+
className: "icon-btn dt-sheet-close",
|
|
9619
|
+
onClick: onClose,
|
|
9620
|
+
title: "Close",
|
|
9621
|
+
type: "button",
|
|
9622
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
9623
|
+
})
|
|
9624
|
+
]
|
|
9625
|
+
}),
|
|
9626
|
+
/* @__PURE__ */ jsx("div", {
|
|
9627
|
+
className: "dt-sheet-body",
|
|
9628
|
+
role: navigation.place === null && navigation.tabs.length > 1 ? "tabpanel" : void 0,
|
|
9629
|
+
tabIndex: navigation.place === null ? void 0 : -1,
|
|
9630
|
+
children
|
|
9631
|
+
}, `${navigation.tab}:${navigation.place === null ? "root" : "nested"}`),
|
|
9632
|
+
footer
|
|
9633
|
+
]
|
|
9634
|
+
});
|
|
9635
|
+
}
|
|
9636
|
+
//#endregion
|
|
9637
|
+
//#region src/devtools/client/devtools-styles.ts
|
|
9638
|
+
const MONO_FONT = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
|
|
9639
|
+
const DEVTOOLS_STYLES = `
|
|
9640
|
+
.dt {
|
|
9641
|
+
--dt-radius-surface: 16px; --dt-radius-card: 12px; --dt-radius-field: 8px; --dt-radius-tiny: 4px;
|
|
9642
|
+
font: 13px/1.45 var(--rf-font, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif); color: var(--rf-text);
|
|
9643
|
+
}
|
|
9644
|
+
.dt button:active:not(:disabled, .dt-btn, .icon-btn) { scale: 1; }
|
|
9645
|
+
.dt[data-recessed="true"] .dt-bar, .dt[data-recessed="true"] .dt-sheet, .dt-sheet ~ .dt-bar { visibility: hidden; pointer-events: none; }
|
|
9646
|
+
.dt-pin {
|
|
9647
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; top: 0; left: 0;
|
|
9648
|
+
display: flex; align-items: center; justify-content: center;
|
|
9649
|
+
min-width: 24px; height: 24px; padding: 0 7px;
|
|
9650
|
+
border-radius: 12px 12px 12px 3px; background: var(--rf-accent); color: var(--rf-accent-text);
|
|
9651
|
+
font-size: 11.5px; font-weight: 650; box-shadow: 0 0 0 2px var(--rf-bg), var(--rf-shadow-low);
|
|
9652
|
+
animation: dt-pin-in 260ms var(--rf-ease);
|
|
9653
|
+
transition: scale 140ms var(--rf-ease), opacity 160ms var(--rf-ease);
|
|
9654
|
+
}
|
|
9655
|
+
.dt-pin:hover, .dt-pin[aria-expanded="true"] { scale: 1.12; }
|
|
9656
|
+
.dt-pin[data-sent="true"] { background: var(--rf-text-muted); }
|
|
9657
|
+
.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; }
|
|
9658
|
+
.dt-card[data-sent="true"] .dt-pin-badge { background: var(--rf-text-muted); }
|
|
9659
|
+
.dt-pin[data-locating="true"] { animation: dt-pin-in 260ms var(--rf-ease), dt-pin-pulse 1.2s ease-in-out infinite; }
|
|
9660
|
+
@keyframes dt-pin-in { from { scale: .4; opacity: 0; } }
|
|
9661
|
+
@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); } }
|
|
9662
|
+
.dt-popover {
|
|
9663
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; width: 320px; max-height: calc(100dvh - 24px); overflow: auto;
|
|
9664
|
+
inset-inline-end: auto; margin: 0; padding: 6px; border-radius: var(--dt-radius-surface); background: transparent; color: inherit;
|
|
9665
|
+
animation: dt-popover-in 200ms var(--rf-ease);
|
|
9666
|
+
}
|
|
9667
|
+
.dt-popover.glass::before { animation: rf-fade 180ms var(--rf-ease); }
|
|
9668
|
+
.dt-popover .dt-card { background: transparent; }
|
|
9669
|
+
@keyframes dt-popover-in { from { transform: translateY(4px); } }
|
|
9670
|
+
@keyframes dt-notice-in { from { transform: translateY(-6px); } }
|
|
9671
|
+
.dt-notices {
|
|
9672
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.annotatorOverlay}; left: 50%; top: 16px; translate: -50% 0;
|
|
9673
|
+
display: flex; flex-direction: column; gap: 6px; width: min(460px, calc(100vw - 24px));
|
|
9674
|
+
}
|
|
9675
|
+
.dt-notice {
|
|
9676
|
+
display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 14px; border-radius: var(--dt-radius-card);
|
|
9677
|
+
color: var(--rf-danger); font-size: 12.5px; animation: dt-notice-in 220ms var(--rf-ease);
|
|
9678
|
+
}
|
|
9679
|
+
.dt-notice[data-kind="status"] { color: var(--rf-text); }
|
|
9680
|
+
.dt-notice p { flex: 1; margin: 0; overflow-wrap: anywhere; }
|
|
9681
|
+
.dt-notice .icon-btn { width: 30px; height: 30px; }
|
|
9682
|
+
.dt-bar {
|
|
9683
|
+
--dt-edge-gap: calc(max(var(--rf-offset), 12px) + 48px);
|
|
9684
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar};
|
|
9685
|
+
display: flex; align-items: center; gap: 2px; padding: 3px;
|
|
9686
|
+
border-radius: var(--rf-pill);
|
|
9687
|
+
}
|
|
9688
|
+
.dt-bar[data-side="left"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }
|
|
9689
|
+
.dt-bar[data-side="right"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }
|
|
9690
|
+
.dt-bar[data-edge="bottom"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }
|
|
9691
|
+
.dt-bar[data-edge="top"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }
|
|
9692
|
+
.dt-bar .icon-btn { position: relative; width: 34px; height: 34px; }
|
|
9693
|
+
.dt-bar .icon-btn.dt-grip { width: 22px; color: var(--rf-text-muted); opacity: .6; }
|
|
9694
|
+
.dt-bar .icon-btn.dt-grip:hover { opacity: 1; }
|
|
9695
|
+
.dt-count {
|
|
9696
|
+
position: absolute; top: 1px; right: 1px; display: flex; align-items: center; justify-content: center;
|
|
9697
|
+
min-width: 15px; height: 15px; padding: 0 4px; border-radius: var(--rf-pill);
|
|
9698
|
+
background: var(--rf-accent); color: var(--rf-accent-text); font-size: 9.5px; font-weight: 600;
|
|
9699
|
+
}
|
|
9700
|
+
.dt-sheet {
|
|
9701
|
+
--dt-enter-x: 20px;
|
|
9702
|
+
position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; top: 12px; bottom: 12px;
|
|
9703
|
+
display: flex; flex-direction: column; max-width: calc(100vw - 24px); max-height: calc(100dvh - 24px);
|
|
9704
|
+
border-radius: var(--dt-radius-surface); overflow: hidden;
|
|
9705
|
+
animation: dt-sheet-slide 320ms var(--rf-ease);
|
|
9706
|
+
}
|
|
9707
|
+
.dt-sheet[data-side="left"] { --dt-enter-x: -20px; left: 12px; }
|
|
9708
|
+
.dt-sheet[data-side="right"] { right: 12px; }
|
|
9709
|
+
.dt-sheet.glass::before { animation: rf-fade 220ms var(--rf-ease); }
|
|
9710
|
+
.dt-sheet-head, .dt-sheet-body { animation: rf-fade 260ms 60ms var(--rf-ease) both; }
|
|
9711
|
+
@keyframes dt-sheet-slide { from { transform: translateX(var(--dt-enter-x)); box-shadow: none; } }
|
|
9712
|
+
.dt-resize { position: absolute; z-index: 2; padding: 0; touch-action: none; }
|
|
9713
|
+
.dt-resize:active:not(:disabled) { scale: 1; }
|
|
9714
|
+
.dt-resize:focus-visible { outline: none; }
|
|
9715
|
+
.dt-resize[data-axis="width"] { top: 16px; bottom: 16px; width: 10px; cursor: ew-resize; }
|
|
9716
|
+
.dt-sheet[data-side="right"] .dt-resize[data-axis="width"] { left: 0; }
|
|
9717
|
+
.dt-sheet[data-side="left"] .dt-resize[data-axis="width"] { right: 0; }
|
|
9718
|
+
.dt-resize[data-axis="height"] { left: 16px; right: 16px; bottom: 0; height: 10px; cursor: ns-resize; }
|
|
9719
|
+
.dt-resize[data-axis="both"] { bottom: 0; width: 16px; height: 16px; }
|
|
9720
|
+
.dt-sheet[data-side="right"] .dt-resize[data-axis="both"] { left: 0; cursor: nesw-resize; }
|
|
9721
|
+
.dt-sheet[data-side="left"] .dt-resize[data-axis="both"] { right: 0; cursor: nwse-resize; }
|
|
9722
|
+
.dt-resize[data-axis="width"]::after, .dt-resize[data-axis="height"]::after {
|
|
9723
|
+
content: ""; position: absolute; border-radius: var(--rf-pill); background: var(--rf-text-muted);
|
|
9724
|
+
opacity: 0; transition: opacity 160ms var(--rf-ease);
|
|
9725
|
+
}
|
|
9726
|
+
.dt-resize[data-axis="width"]::after { top: 50%; left: 3px; width: 4px; height: 36px; translate: 0 -50%; }
|
|
9727
|
+
.dt-resize[data-axis="height"]::after { left: 50%; top: 3px; width: 36px; height: 4px; translate: -50% 0; }
|
|
9728
|
+
.dt-resize:hover::after, .dt-resize:focus-visible::after, .dt-resize:active::after { opacity: .5; }
|
|
9729
|
+
.dt-sheet-head { position: relative; display: flex; align-items: center; gap: 4px; padding: 8px 8px 8px 6px; border-bottom: 1px solid var(--rf-border); }
|
|
9730
|
+
.dt-sheet-head > :not(.dt-sheet-drag) { position: relative; z-index: 1; }
|
|
9731
|
+
.dt-sheet-head .icon-btn { width: 32px; height: 32px; }
|
|
9732
|
+
.dt-sheet .dt-sheet-drag { position: absolute; inset: 0; z-index: 0; padding: 0; border-radius: 0; cursor: grab; touch-action: none; }
|
|
9733
|
+
.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); }
|
|
9734
|
+
.dt-sheet .dt-sheet-drag:hover::before, .dt-sheet .dt-sheet-drag:active::before { opacity: .7; }
|
|
9735
|
+
.dt-sheet .dt-sheet-drag:active:not(:disabled) { cursor: grabbing; scale: 1; }
|
|
9736
|
+
.dt-sheet .dt-sheet-drag:focus-visible { outline-offset: -2px; }
|
|
9737
|
+
.dt-tabs { display: flex; gap: 2px; min-width: 0; margin-right: auto; overflow-x: auto; scrollbar-width: none; }
|
|
9738
|
+
.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; }
|
|
9739
|
+
.dt-tab svg { flex: none; width: 15px; height: 15px; }
|
|
9740
|
+
.dt-tab:hover { color: var(--rf-text); }
|
|
9741
|
+
.dt-tab[aria-selected="true"] { background: var(--rf-bg-hover); color: var(--rf-text); }
|
|
9742
|
+
.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; }
|
|
9743
|
+
.dt-tab[aria-selected="true"] .dt-tab-count { background: var(--rf-bg); }
|
|
9744
|
+
.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; }
|
|
9745
|
+
.dt-sheet-back:hover { background: var(--rf-bg-hover); }
|
|
9746
|
+
.dt-sheet-back svg, .dt-sheet-title svg { flex: none; width: 16px; height: 16px; }
|
|
9747
|
+
.dt-sheet-title { display: inline-flex; align-items: center; gap: 6px; margin: 0 auto 0 8px; font-size: 13px; font-weight: 600; }
|
|
9748
|
+
.dt-sheet-title:focus { outline: none; }
|
|
9749
|
+
.dt-toolbar { display: flex; align-items: center; gap: 2px; min-height: 30px; }
|
|
9750
|
+
.dt-toolbar .icon-btn, .dt-toolbar .dt-menu > .icon-btn { width: 30px; height: 30px; }
|
|
9751
|
+
.dt-sheet-body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 8px; padding: 10px; }
|
|
9752
|
+
.dt-sheet-foot {
|
|
9753
|
+
position: sticky; bottom: -10px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
|
|
9754
|
+
margin: auto -10px -10px; padding: 10px; border-top: 1px solid var(--rf-border); background: var(--rf-bg);
|
|
9755
|
+
}
|
|
9756
|
+
.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); }
|
|
9757
|
+
.dt-archived .dt-meta { flex: 1 1 100%; }
|
|
9758
|
+
.dt-group { margin: 6px 2px 0; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--rf-text-muted); }
|
|
9759
|
+
.dt-card { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border-radius: var(--dt-radius-card); background: var(--rf-bg-subtle); }
|
|
9760
|
+
.dt-card[data-sent="true"] { opacity: .7; }
|
|
9761
|
+
.dt-card-head { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
9762
|
+
.dt-card-title { min-width: 0; margin: 0; overflow: hidden; font-size: 13px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
|
|
9763
|
+
.dt-meta { margin: 0; font-size: 11.5px; color: var(--rf-text-muted); overflow-wrap: anywhere; }
|
|
9764
|
+
.dt-note-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
9765
|
+
.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; }
|
|
9766
|
+
.dt-chip[data-tone="accent"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); color: var(--rf-accent); }
|
|
9767
|
+
.dt-source { padding: 0; font: 11.5px/1.4 ${MONO_FONT}; color: var(--rf-accent); text-align: left; overflow-wrap: anywhere; }
|
|
9768
|
+
.dt-source:hover { text-decoration: underline; }
|
|
9769
|
+
.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); }
|
|
9770
|
+
.dt-actions { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
9771
|
+
.dt-btn {
|
|
9772
|
+
display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
|
|
9773
|
+
border-radius: var(--rf-pill); background: var(--rf-bg-hover); color: var(--rf-text);
|
|
9774
|
+
font-size: 12px; font-weight: 500; text-decoration: none;
|
|
9775
|
+
}
|
|
9776
|
+
.dt-btn:hover { background: color-mix(in srgb, var(--rf-text) 12%, transparent); }
|
|
9777
|
+
.dt-btn[data-variant="primary"] { background: var(--rf-primary); color: var(--rf-primary-text); }
|
|
9778
|
+
.dt-btn[data-variant="danger"] { color: var(--rf-danger); }
|
|
9779
|
+
.dt-btn svg { flex: none; width: 14px; height: 14px; }
|
|
9780
|
+
.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; }
|
|
9781
|
+
.dt-empty { margin: auto; padding: 24px 16px; color: var(--rf-text-muted); font-size: 12.5px; text-align: center; text-wrap: pretty; }
|
|
9782
|
+
.dt-empty p { margin: 0 0 8px; }
|
|
9783
|
+
.dt-empty-title { margin: 0 0 4px; color: var(--rf-text); font-size: 13.5px; font-weight: 600; text-wrap: balance; }
|
|
9784
|
+
.dt-empty .dt-btn { margin-top: 4px; }
|
|
9785
|
+
.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; }
|
|
9786
|
+
.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; }
|
|
9787
|
+
.dt-error { margin: 0; color: var(--rf-danger); font-size: 12px; }
|
|
9788
|
+
.dt-status { margin: 0 auto 0 0; color: var(--rf-text-muted); font-size: 12px; }
|
|
9789
|
+
.dt-field {
|
|
9790
|
+
width: 100%; padding: 7px 9px; border: 1px solid var(--rf-border); border-radius: var(--dt-radius-field);
|
|
9791
|
+
background: var(--rf-bg); color: var(--rf-text); font: inherit; resize: vertical;
|
|
9792
|
+
}
|
|
9793
|
+
.dt-field:focus { outline: 2px solid var(--rf-accent); outline-offset: 0; }
|
|
9794
|
+
.dt-search { display: flex; gap: 6px; }
|
|
9795
|
+
.dt-matches { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
|
|
9796
|
+
.dt-match { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 6px 8px; border-radius: var(--dt-radius-field); text-align: left; }
|
|
9797
|
+
.dt-match:hover { background: var(--rf-bg-hover); }
|
|
9798
|
+
.dt-match code { font: 11.5px ${MONO_FONT}; color: var(--rf-accent); }
|
|
9799
|
+
.dt-match span { font: 11.5px ${MONO_FONT}; color: var(--rf-text-muted); white-space: pre; overflow: hidden; text-overflow: ellipsis; }
|
|
9800
|
+
.dt-code-head { display: flex; flex-direction: column; gap: 6px; }
|
|
9801
|
+
.dt-code-path { margin: 0; font: 12px/1.4 ${MONO_FONT}; overflow-wrap: anywhere; }
|
|
9802
|
+
.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}; }
|
|
9803
|
+
.dt-code-lines { display: table; min-width: 100%; }
|
|
9804
|
+
.dt-line { display: table-row; white-space: pre; }
|
|
9805
|
+
.dt-line > span { display: table-cell; padding-right: 14px; }
|
|
9806
|
+
.dt-line > .dt-line-number { width: 1%; padding: 0 12px 0 10px; color: var(--rf-text-muted); text-align: right; user-select: none; }
|
|
9807
|
+
.dt-line[data-marked="true"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); }
|
|
9808
|
+
.dt-line[data-marked="true"] > .dt-line-number { color: var(--rf-accent); }
|
|
9809
|
+
.dt-menu { position: relative; flex: none; }
|
|
9810
|
+
.dt-menu-list {
|
|
9811
|
+
position: absolute; right: 0; z-index: 3; display: flex; flex-direction: column; min-width: 176px; padding: 4px;
|
|
9812
|
+
border: 1px solid var(--rf-border); border-radius: var(--dt-radius-card); background: var(--rf-bg); box-shadow: var(--rf-shadow);
|
|
9813
|
+
animation: rf-fade 120ms var(--rf-ease);
|
|
9814
|
+
}
|
|
9815
|
+
.dt-menu-list[data-placement="below"] { top: calc(100% + 4px); }
|
|
9816
|
+
.dt-menu-list[data-placement="above"] { bottom: calc(100% + 4px); }
|
|
9817
|
+
.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; }
|
|
9818
|
+
.dt-menu-item:hover, .dt-menu-item:focus-visible { background: var(--rf-bg-hover); outline: none; }
|
|
9819
|
+
.dt-menu-item[data-variant="danger"] { color: var(--rf-danger); }
|
|
9820
|
+
.dt-menu-check { display: inline-flex; width: 14px; color: var(--rf-accent); }
|
|
9821
|
+
.dt-sheet-account { display: flex; flex: none; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px; border-top: 1px solid var(--rf-border); }
|
|
9822
|
+
.dt-sheet-account > .dt-meta { flex: 1 1 160px; padding-inline: 4px; }
|
|
9823
|
+
.dt-sheet-account > .dt-menu { flex: 1; min-width: 0; }
|
|
9824
|
+
.dt-sheet-account .dt-menu-list { left: 0; }
|
|
9825
|
+
.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; }
|
|
9826
|
+
.dt-account:hover, .dt-account[aria-expanded="true"] { background: var(--rf-bg-hover); }
|
|
9827
|
+
.dt-account > svg { flex: none; width: 14px; height: 14px; color: var(--rf-text-muted); }
|
|
9828
|
+
.dt-account-text { display: flex; flex: 1; flex-direction: column; min-width: 0; line-height: 1.3; }
|
|
9829
|
+
.dt-account-name, .dt-account-text .dt-meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
9830
|
+
.dt-account-name { font-size: 12.5px; font-weight: 600; }
|
|
9831
|
+
.dt-avatar {
|
|
9832
|
+
position: relative; display: flex; flex: none; align-items: center; justify-content: center; width: 28px; height: 28px; overflow: hidden;
|
|
9833
|
+
border-radius: 50%; background: color-mix(in srgb, var(--rf-accent) 18%, transparent); color: var(--rf-accent); font-size: 11px; font-weight: 650;
|
|
9834
|
+
}
|
|
9835
|
+
.dt-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
|
|
9836
|
+
`;
|
|
9837
|
+
//#endregion
|
|
9838
|
+
export { searchCode as A, devtoolsTransport as C, fetchBoardFeedback as D, disconnectBoard as E, settle as F, sessionApiErrorSchema as I, Notices as L, committed as M, describeStorageFailure as N, fetchSourceFile as O, openDatabase as P, announce as R, purgeAccount as S, callReflet 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, startBoardConnect as j, probeDevRoute 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, teamTransport as w, useWorkspaceLoader as x, SessionWorkspaceProvider as y, reportFailure as z };
|
|
9468
9839
|
|
|
9469
|
-
//# sourceMappingURL=
|
|
9840
|
+
//# sourceMappingURL=devtools-styles-teRMfSzW.js.map
|