@flamingo-stack/openframe-frontend-core 0.0.701-snapshot.20261005171139 → 0.0.701
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CXDJUKC6.cjs → chunk-2CSYUMNM.cjs} +2 -2
- package/dist/{chunk-E3DH543A.cjs → chunk-4H5Q6MQG.cjs} +35 -35
- package/dist/{chunk-3WSFIV5G.cjs → chunk-65YVUYWJ.cjs} +32 -32
- package/dist/{chunk-UJJWTJ6S.js → chunk-6JG75WVO.js} +4 -4
- package/dist/{chunk-YGRHITPY.cjs → chunk-7ZDTAABP.cjs} +3 -3
- package/dist/{chunk-Z5HDCZAS.js → chunk-A5ZGKBN2.js} +1 -1
- package/dist/{chunk-CZ34HXDW.js → chunk-B7M6QEEM.js} +275 -661
- package/dist/{chunk-FHM7GD5B.cjs → chunk-BPS7JQCI.cjs} +2 -2
- package/dist/{chunk-LZNJH23A.cjs → chunk-BQ34PIFC.cjs} +3 -3
- package/dist/{chunk-AEQANLBW.cjs → chunk-BRQY2HKD.cjs} +17 -17
- package/dist/{chunk-ETFFEA3J.js → chunk-BZYMGI4L.js} +1 -1
- package/dist/{chunk-IZKOQVXO.js → chunk-CUPJCGLB.js} +1 -1
- package/dist/{chunk-QFW3RUZS.cjs → chunk-DG2I57UM.cjs} +16 -16
- package/dist/{chunk-HYFLTFFB.js → chunk-DJLZXJYB.js} +1 -1
- package/dist/{chunk-MWUBBBWZ.js → chunk-EONNPRAW.js} +1 -1
- package/dist/{chunk-446KS5BG.js → chunk-GD4JALTR.js} +1 -1
- package/dist/{chunk-3G76LRGL.cjs → chunk-GFXZMFDX.cjs} +9 -9
- package/dist/{chunk-BO5ZHDA4.js → chunk-JPVDJB27.js} +3 -3
- package/dist/{chunk-2V4Z44G6.js → chunk-MFORWVGD.js} +4 -4
- package/dist/{chunk-JOY6HVPV.js → chunk-N7DPIH57.js} +1 -1
- package/dist/{chunk-PLK6GHN7.js → chunk-N7HMUQRV.js} +1 -1
- package/dist/{chunk-L7KZA7ZD.cjs → chunk-NIT257DV.cjs} +2 -2
- package/dist/{chunk-SAA7B3DA.js → chunk-PNWIVND4.js} +2 -2
- package/dist/{chunk-FD4DBTFO.cjs → chunk-QDIX2ZRL.cjs} +44 -430
- package/dist/{chunk-CYYTD5ZK.cjs → chunk-QPNR4N7N.cjs} +16 -16
- package/dist/{chunk-HIXGAY2L.cjs → chunk-QZGFJBG5.cjs} +50 -50
- package/dist/{chunk-RS7HWAYX.js → chunk-S4ADN25W.js} +1 -1
- package/dist/{chunk-HPJ4XS2L.js → chunk-V5QNDOEL.js} +3 -3
- package/dist/{chunk-B3LZJ6J3.cjs → chunk-YBC346FY.cjs} +12 -12
- package/dist/{chunk-ASN65P3F.cjs → chunk-ZSPHOHOW.cjs} +2 -2
- package/dist/components/case-studies/index.cjs +11 -11
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/docs/index.cjs +6 -6
- package/dist/components/docs/index.js +5 -5
- package/dist/components/embeds/index.cjs +3 -3
- package/dist/components/embeds/index.js +2 -2
- package/dist/components/faq/index.cjs +3 -3
- package/dist/components/faq/index.js +2 -2
- package/dist/components/features/index.cjs +2 -22
- package/dist/components/features/index.js +1 -21
- package/dist/components/features/remote-session/index.d.ts +1 -9
- package/dist/components/features/remote-session/index.d.ts.map +1 -1
- package/dist/components/features/remote-session/remote-session-block.d.ts +2 -4
- package/dist/components/features/remote-session/remote-session-block.d.ts.map +1 -1
- package/dist/components/features/remote-session/remote-session-chat-panel.d.ts +2 -4
- package/dist/components/features/remote-session/remote-session-chat-panel.d.ts.map +1 -1
- package/dist/components/features/remote-session/remote-session-parts.d.ts +2 -13
- package/dist/components/features/remote-session/remote-session-parts.d.ts.map +1 -1
- package/dist/components/features/remote-session/types.d.ts +0 -22
- package/dist/components/features/remote-session/types.d.ts.map +1 -1
- package/dist/components/help-center-pages/index.cjs +49 -49
- package/dist/components/help-center-pages/index.js +13 -13
- package/dist/components/index.cjs +33 -53
- package/dist/components/index.js +12 -32
- package/dist/components/meeting-scheduler/index.cjs +22 -22
- package/dist/components/meeting-scheduler/index.js +1 -1
- package/dist/components/navigation/index.cjs +5 -5
- package/dist/components/navigation/index.js +4 -4
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/tickets/index.cjs +6 -6
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/index.cjs +6 -26
- package/dist/index.js +5 -25
- package/dist/tailwind.config.cjs +1 -7
- package/dist/tailwind.config.js +1 -7
- package/package.json +1 -1
- package/src/components/features/remote-session/index.ts +0 -28
- package/src/components/features/remote-session/remote-session-block.tsx +3 -6
- package/src/components/features/remote-session/remote-session-chat-panel.tsx +7 -11
- package/src/components/features/remote-session/remote-session-parts.tsx +3 -32
- package/src/components/features/remote-session/types.ts +0 -26
- package/tailwind.config.ts +0 -6
- package/dist/components/features/remote-session/remote-session-events.d.ts +0 -24
- package/dist/components/features/remote-session/remote-session-events.d.ts.map +0 -1
- package/dist/components/features/remote-session/remote-session-keep-modals.d.ts +0 -41
- package/dist/components/features/remote-session/remote-session-keep-modals.d.ts.map +0 -1
- package/dist/components/features/remote-session/remote-session-status.d.ts +0 -34
- package/dist/components/features/remote-session/remote-session-status.d.ts.map +0 -1
- package/dist/components/features/remote-session/remote-session-viewers.d.ts +0 -15
- package/dist/components/features/remote-session/remote-session-viewers.d.ts.map +0 -1
- package/src/components/features/remote-session/remote-session-events.tsx +0 -93
- package/src/components/features/remote-session/remote-session-keep-modals.tsx +0 -208
- package/src/components/features/remote-session/remote-session-status.tsx +0 -102
- package/src/components/features/remote-session/remote-session-viewers.tsx +0 -103
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
SoftwareInfo,
|
|
10
10
|
SoftwareSourceBadge,
|
|
11
11
|
ToolBadge
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-N7HMUQRV.js";
|
|
13
13
|
import {
|
|
14
14
|
AppHeader,
|
|
15
15
|
AppLayout,
|
|
@@ -29,14 +29,14 @@ import {
|
|
|
29
29
|
SlidingSidebar,
|
|
30
30
|
TicketAlertsButton,
|
|
31
31
|
TopNavigation
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-PNWIVND4.js";
|
|
33
33
|
import {
|
|
34
34
|
MobileNavigationDropdown,
|
|
35
35
|
MultiLevelNavigation,
|
|
36
36
|
StickySectionNav,
|
|
37
37
|
useSectionNavigation
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-
|
|
38
|
+
} from "./chunk-DJLZXJYB.js";
|
|
39
|
+
import "./chunk-S4ADN25W.js";
|
|
40
40
|
import {
|
|
41
41
|
AIEnrichButton,
|
|
42
42
|
AIEnrichSection,
|
|
@@ -233,7 +233,6 @@ import {
|
|
|
233
233
|
InputTrigger,
|
|
234
234
|
InviteLinkInvalidModal,
|
|
235
235
|
JsonDetailList,
|
|
236
|
-
KeepRecordingModal,
|
|
237
236
|
KnowledgeBaseLinksManager,
|
|
238
237
|
LabeledDivider,
|
|
239
238
|
LazyMount,
|
|
@@ -335,7 +334,6 @@ import {
|
|
|
335
334
|
QueryReportTableRow,
|
|
336
335
|
QueryReportTableSkeleton,
|
|
337
336
|
REMOTE_SESSION_DRAG_HANDLE_CLASS,
|
|
338
|
-
REMOTE_SESSION_KEEP_REASON_LABELS,
|
|
339
337
|
ROADMAP_STATUS_OPTIONS,
|
|
340
338
|
ROW_HEIGHT_DESKTOP,
|
|
341
339
|
ROW_HEIGHT_MOBILE,
|
|
@@ -344,7 +342,6 @@ import {
|
|
|
344
342
|
RadioGroupBlock,
|
|
345
343
|
RadioGroupItem,
|
|
346
344
|
ReleaseChangelogSection,
|
|
347
|
-
ReleaseKeepingModal,
|
|
348
345
|
RemoteAccessRequestCard,
|
|
349
346
|
RemoteSessionBlockFrame,
|
|
350
347
|
RemoteSessionBorder,
|
|
@@ -352,18 +349,12 @@ import {
|
|
|
352
349
|
RemoteSessionDialog,
|
|
353
350
|
RemoteSessionDragger,
|
|
354
351
|
RemoteSessionEndButton,
|
|
355
|
-
RemoteSessionEventList,
|
|
356
|
-
RemoteSessionExpiry,
|
|
357
352
|
RemoteSessionMinimizedChip,
|
|
358
353
|
RemoteSessionOrgLogo,
|
|
359
354
|
RemoteSessionPill,
|
|
360
355
|
RemoteSessionRecordingTag,
|
|
361
356
|
RemoteSessionScope,
|
|
362
|
-
RemoteSessionStatusTag,
|
|
363
|
-
RemoteSessionStorageAlert,
|
|
364
357
|
RemoteSessionSummary,
|
|
365
|
-
RemoteSessionTimelineMarkers,
|
|
366
|
-
RemoteSessionViewers,
|
|
367
358
|
ReopenTicketModal,
|
|
368
359
|
ReopenTicketRequestModal,
|
|
369
360
|
RichMarkdownRenderer,
|
|
@@ -537,7 +528,6 @@ import {
|
|
|
537
528
|
formatDocName,
|
|
538
529
|
formatPhoneE164,
|
|
539
530
|
formatRemoteSessionElapsed,
|
|
540
|
-
formatRemoteSessionOffset,
|
|
541
531
|
formatTestRunDuration,
|
|
542
532
|
generateBiteId,
|
|
543
533
|
getApprovalMeta,
|
|
@@ -665,7 +655,7 @@ import {
|
|
|
665
655
|
withFirstTouchAttribution,
|
|
666
656
|
withWalkthroughOpenParam,
|
|
667
657
|
writeDismissCookie
|
|
668
|
-
} from "./chunk-
|
|
658
|
+
} from "./chunk-B7M6QEEM.js";
|
|
669
659
|
import "./chunk-LQYXMEYF.js";
|
|
670
660
|
import "./chunk-4JPLYOS6.js";
|
|
671
661
|
import {
|
|
@@ -2400,7 +2390,6 @@ export {
|
|
|
2400
2390
|
InviteLinkInvalidModal,
|
|
2401
2391
|
JsonDetailList,
|
|
2402
2392
|
JumpInIcon,
|
|
2403
|
-
KeepRecordingModal,
|
|
2404
2393
|
KnowledgeBaseLinksManager,
|
|
2405
2394
|
LOG_SEVERITY_COLORS,
|
|
2406
2395
|
LOG_SEVERITY_LABELS,
|
|
@@ -2631,7 +2620,6 @@ export {
|
|
|
2631
2620
|
RATIO_GRID_CLASS,
|
|
2632
2621
|
RATIO_TO_CSS_ASPECT,
|
|
2633
2622
|
REMOTE_SESSION_DRAG_HANDLE_CLASS,
|
|
2634
|
-
REMOTE_SESSION_KEEP_REASON_LABELS,
|
|
2635
2623
|
RESCUE_FORMS,
|
|
2636
2624
|
RESYNC_AFTER_HIDDEN_MS,
|
|
2637
2625
|
ROADMAP_STATUS_OPTIONS,
|
|
@@ -2646,7 +2634,6 @@ export {
|
|
|
2646
2634
|
ReclaimProfitsIcon,
|
|
2647
2635
|
RedditIcon,
|
|
2648
2636
|
ReleaseChangelogSection,
|
|
2649
|
-
ReleaseKeepingModal,
|
|
2650
2637
|
RemoteAccessRequestCard,
|
|
2651
2638
|
RemoteControlIcon,
|
|
2652
2639
|
RemoteSessionBlockFrame,
|
|
@@ -2655,18 +2642,12 @@ export {
|
|
|
2655
2642
|
RemoteSessionDialog,
|
|
2656
2643
|
RemoteSessionDragger,
|
|
2657
2644
|
RemoteSessionEndButton,
|
|
2658
|
-
RemoteSessionEventList,
|
|
2659
|
-
RemoteSessionExpiry,
|
|
2660
2645
|
RemoteSessionMinimizedChip,
|
|
2661
2646
|
RemoteSessionOrgLogo,
|
|
2662
2647
|
RemoteSessionPill,
|
|
2663
2648
|
RemoteSessionRecordingTag,
|
|
2664
2649
|
RemoteSessionScope,
|
|
2665
|
-
RemoteSessionStatusTag,
|
|
2666
|
-
RemoteSessionStorageAlert,
|
|
2667
2650
|
RemoteSessionSummary,
|
|
2668
|
-
RemoteSessionTimelineMarkers,
|
|
2669
|
-
RemoteSessionViewers,
|
|
2670
2651
|
RenameChatModal,
|
|
2671
2652
|
ReopenTicketModal,
|
|
2672
2653
|
ReopenTicketRequestModal,
|
|
@@ -3124,7 +3105,6 @@ export {
|
|
|
3124
3105
|
formatRelativeTime,
|
|
3125
3106
|
formatReleaseDate,
|
|
3126
3107
|
formatRemoteSessionElapsed,
|
|
3127
|
-
formatRemoteSessionOffset,
|
|
3128
3108
|
formatSingularLookupInvocation,
|
|
3129
3109
|
formatTestRunDuration,
|
|
3130
3110
|
formatTicketFullTimestamp,
|
package/dist/tailwind.config.cjs
CHANGED
|
@@ -486,11 +486,6 @@ var config = {
|
|
|
486
486
|
"dot-pulse": {
|
|
487
487
|
"0%, 80%, 100%": { transform: "scale(1)", opacity: "0.7" },
|
|
488
488
|
"40%": { transform: "scale(1.5)", opacity: "1" }
|
|
489
|
-
},
|
|
490
|
-
// The dot on a LIVE tag: opacity only, so it reads as "on air" without moving.
|
|
491
|
-
"live-pulse": {
|
|
492
|
-
"0%, 100%": { opacity: "1" },
|
|
493
|
-
"50%": { opacity: "0.25" }
|
|
494
489
|
}
|
|
495
490
|
},
|
|
496
491
|
animation: {
|
|
@@ -498,8 +493,7 @@ var config = {
|
|
|
498
493
|
"accordion-up": "accordion-up 0.2s ease-out",
|
|
499
494
|
"fade-in": "fade-in 0.3s ease-out",
|
|
500
495
|
"cursor-blink": "cursor-blink 1s steps(1) infinite",
|
|
501
|
-
"dot-pulse": "dot-pulse 1.4s ease-in-out infinite"
|
|
502
|
-
"live-pulse": "live-pulse 1.6s ease-in-out infinite"
|
|
496
|
+
"dot-pulse": "dot-pulse 1.4s ease-in-out infinite"
|
|
503
497
|
}
|
|
504
498
|
}
|
|
505
499
|
},
|
package/dist/tailwind.config.js
CHANGED
|
@@ -479,11 +479,6 @@ var config = {
|
|
|
479
479
|
"dot-pulse": {
|
|
480
480
|
"0%, 80%, 100%": { transform: "scale(1)", opacity: "0.7" },
|
|
481
481
|
"40%": { transform: "scale(1.5)", opacity: "1" }
|
|
482
|
-
},
|
|
483
|
-
// The dot on a LIVE tag: opacity only, so it reads as "on air" without moving.
|
|
484
|
-
"live-pulse": {
|
|
485
|
-
"0%, 100%": { opacity: "1" },
|
|
486
|
-
"50%": { opacity: "0.25" }
|
|
487
482
|
}
|
|
488
483
|
},
|
|
489
484
|
animation: {
|
|
@@ -491,8 +486,7 @@ var config = {
|
|
|
491
486
|
"accordion-up": "accordion-up 0.2s ease-out",
|
|
492
487
|
"fade-in": "fade-in 0.3s ease-out",
|
|
493
488
|
"cursor-blink": "cursor-blink 1s steps(1) infinite",
|
|
494
|
-
"dot-pulse": "dot-pulse 1.4s ease-in-out infinite"
|
|
495
|
-
"live-pulse": "live-pulse 1.6s ease-in-out infinite"
|
|
489
|
+
"dot-pulse": "dot-pulse 1.4s ease-in-out infinite"
|
|
496
490
|
}
|
|
497
491
|
}
|
|
498
492
|
},
|
package/package.json
CHANGED
|
@@ -16,30 +16,6 @@ export type { RemoteSessionChatPanelProps } from './remote-session-chat-panel';
|
|
|
16
16
|
export { RemoteSessionDialog } from './remote-session-dialog';
|
|
17
17
|
export type { RemoteSessionDialogProps } from './remote-session-dialog';
|
|
18
18
|
export { RemoteSessionBorder, RemoteSessionPill } from './remote-session-overlay';
|
|
19
|
-
export {
|
|
20
|
-
REMOTE_SESSION_KEEP_REASON_LABELS,
|
|
21
|
-
KeepRecordingModal,
|
|
22
|
-
ReleaseKeepingModal,
|
|
23
|
-
} from './remote-session-keep-modals';
|
|
24
|
-
export type {
|
|
25
|
-
KeepRecordingModalProps,
|
|
26
|
-
KeepRecordingSelection,
|
|
27
|
-
ReleaseKeepingModalProps,
|
|
28
|
-
} from './remote-session-keep-modals';
|
|
29
|
-
export {
|
|
30
|
-
RemoteSessionEventList,
|
|
31
|
-
RemoteSessionTimelineMarkers,
|
|
32
|
-
formatRemoteSessionOffset,
|
|
33
|
-
} from './remote-session-events';
|
|
34
|
-
export type { RemoteSessionEventListProps, RemoteSessionTimelineMarkersProps } from './remote-session-events';
|
|
35
|
-
export { RemoteSessionExpiry, RemoteSessionStatusTag, RemoteSessionStorageAlert } from './remote-session-status';
|
|
36
|
-
export type {
|
|
37
|
-
RemoteSessionExpiryProps,
|
|
38
|
-
RemoteSessionStatusTagProps,
|
|
39
|
-
RemoteSessionStorageAlertProps,
|
|
40
|
-
} from './remote-session-status';
|
|
41
|
-
export { RemoteSessionViewers } from './remote-session-viewers';
|
|
42
|
-
export type { RemoteSessionViewersProps } from './remote-session-viewers';
|
|
43
19
|
export {
|
|
44
20
|
REMOTE_SESSION_DRAG_HANDLE_CLASS,
|
|
45
21
|
RemoteSessionDragger,
|
|
@@ -56,9 +32,5 @@ export type {
|
|
|
56
32
|
RemoteSessionChatMessage,
|
|
57
33
|
RemoteSessionDialogVariant,
|
|
58
34
|
RemoteSessionDragHandlers,
|
|
59
|
-
RemoteSessionEvent,
|
|
60
|
-
RemoteSessionKeepReason,
|
|
61
35
|
RemoteSessionParty,
|
|
62
|
-
RemoteSessionStatus,
|
|
63
|
-
RemoteSessionViewer,
|
|
64
36
|
} from './types';
|
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
REMOTE_SESSION_DRAG_HANDLE_CLASS,
|
|
11
11
|
RemoteSessionDragger,
|
|
12
12
|
RemoteSessionOrgLogo,
|
|
13
|
-
|
|
13
|
+
RemoteSessionRecordingTag,
|
|
14
14
|
} from './remote-session-parts';
|
|
15
|
-
import type { RemoteSessionDragHandlers, RemoteSessionParty
|
|
15
|
+
import type { RemoteSessionDragHandlers, RemoteSessionParty } from './types';
|
|
16
16
|
|
|
17
17
|
export interface RemoteSessionBlockFrameProps {
|
|
18
18
|
/** The summary or the chat panel. */
|
|
@@ -74,8 +74,6 @@ export interface RemoteSessionSummaryProps {
|
|
|
74
74
|
/** Elapsed session time, e.g. from `useRemoteSessionTimer`. */
|
|
75
75
|
elapsed: string;
|
|
76
76
|
showRecordingTag?: boolean;
|
|
77
|
-
/** Everyone in the session while colleagues watch it, the host included; hidden when empty. */
|
|
78
|
-
viewers?: RemoteSessionViewer[];
|
|
79
77
|
onOpenChat: () => void;
|
|
80
78
|
onEndSession: () => void;
|
|
81
79
|
/** Makes the header row and the dragger move the window. */
|
|
@@ -87,7 +85,6 @@ export function RemoteSessionSummary({
|
|
|
87
85
|
party,
|
|
88
86
|
elapsed,
|
|
89
87
|
showRecordingTag = false,
|
|
90
|
-
viewers,
|
|
91
88
|
onOpenChat,
|
|
92
89
|
onEndSession,
|
|
93
90
|
dragHandlers,
|
|
@@ -121,7 +118,7 @@ export function RemoteSessionSummary({
|
|
|
121
118
|
<p className="w-full truncate text-ods-text-secondary text-h4">{party.organizationName}</p>
|
|
122
119
|
</div>
|
|
123
120
|
</div>
|
|
124
|
-
|
|
121
|
+
{showRecordingTag && <RemoteSessionRecordingTag />}
|
|
125
122
|
<div className="flex w-full items-stretch gap-[var(--spacing-system-m)]">
|
|
126
123
|
<Button
|
|
127
124
|
variant="outline"
|
|
@@ -6,13 +6,12 @@ import { MessageOffIcon, Send03Icon } from '../../icons-v2-generated';
|
|
|
6
6
|
import { Button } from '../../ui/button/button';
|
|
7
7
|
import { SquareAvatar } from '../../ui/square-avatar';
|
|
8
8
|
import { RemoteSessionEndButton } from './remote-session-block';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from './types';
|
|
9
|
+
import {
|
|
10
|
+
REMOTE_SESSION_DRAG_HANDLE_CLASS,
|
|
11
|
+
RemoteSessionDragger,
|
|
12
|
+
RemoteSessionRecordingTag,
|
|
13
|
+
} from './remote-session-parts';
|
|
14
|
+
import type { RemoteSessionChatMessage, RemoteSessionDragHandlers, RemoteSessionParty } from './types';
|
|
16
15
|
|
|
17
16
|
export interface RemoteSessionChatPanelProps {
|
|
18
17
|
party: RemoteSessionParty;
|
|
@@ -20,8 +19,6 @@ export interface RemoteSessionChatPanelProps {
|
|
|
20
19
|
elapsed: string;
|
|
21
20
|
messages: RemoteSessionChatMessage[];
|
|
22
21
|
showRecordingTag?: boolean;
|
|
23
|
-
/** Everyone in the session while colleagues watch it, the host included; hidden when empty. */
|
|
24
|
-
viewers?: RemoteSessionViewer[];
|
|
25
22
|
/** The composer's text; owned by the host so it survives hiding the block. */
|
|
26
23
|
draft: string;
|
|
27
24
|
onDraftChange: (draft: string) => void;
|
|
@@ -46,7 +43,6 @@ export function RemoteSessionChatPanel({
|
|
|
46
43
|
elapsed,
|
|
47
44
|
messages,
|
|
48
45
|
showRecordingTag = false,
|
|
49
|
-
viewers,
|
|
50
46
|
draft,
|
|
51
47
|
onDraftChange,
|
|
52
48
|
onSend,
|
|
@@ -87,7 +83,7 @@ export function RemoteSessionChatPanel({
|
|
|
87
83
|
</p>
|
|
88
84
|
<p className="w-full truncate text-ods-text-secondary text-h4">You can end this session at any time</p>
|
|
89
85
|
</div>
|
|
90
|
-
|
|
86
|
+
{showRecordingTag && <RemoteSessionRecordingTag />}
|
|
91
87
|
<div className="flex w-full items-stretch gap-[var(--spacing-system-m)]">
|
|
92
88
|
<Button
|
|
93
89
|
variant="outline"
|
|
@@ -5,8 +5,7 @@ import { cn } from '../../../utils/cn';
|
|
|
5
5
|
import { DraggerIcon, RecordingIcon } from '../../icons-v2-generated';
|
|
6
6
|
import { OpenFrameLogo } from '../../icons/openframe-logo';
|
|
7
7
|
import { SquareAvatar } from '../../ui/square-avatar';
|
|
8
|
-
import {
|
|
9
|
-
import type { RemoteSessionDragHandlers, RemoteSessionViewer } from './types';
|
|
8
|
+
import type { RemoteSessionDragHandlers } from './types';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* The remote session surfaces are fixed-size desktop windows (440 / 600 px
|
|
@@ -91,43 +90,15 @@ export function RemoteSessionOrgLogo({ name, logoUrl, sizePx, className }: Remot
|
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
/** The green SESSION RECORDING tag. */
|
|
94
|
-
export function RemoteSessionRecordingTag(
|
|
93
|
+
export function RemoteSessionRecordingTag() {
|
|
95
94
|
return (
|
|
96
|
-
<div
|
|
97
|
-
className={cn(
|
|
98
|
-
'flex h-8 items-center gap-[var(--spacing-system-xs)] self-start rounded-md bg-ods-success-secondary p-[var(--spacing-system-xsf)]',
|
|
99
|
-
className,
|
|
100
|
-
)}
|
|
101
|
-
>
|
|
95
|
+
<div className="flex h-8 items-center gap-[var(--spacing-system-xs)] self-start rounded-md bg-ods-success-secondary p-[var(--spacing-system-xsf)]">
|
|
102
96
|
<RecordingIcon size={16} color="currentColor" className="text-ods-success" />
|
|
103
97
|
<span className="text-ods-success text-h5">Session Recording</span>
|
|
104
98
|
</div>
|
|
105
99
|
);
|
|
106
100
|
}
|
|
107
101
|
|
|
108
|
-
/**
|
|
109
|
-
* The row under the block's header: the SESSION RECORDING tag and, while
|
|
110
|
-
* colleagues watch, who is in the session. With viewers the tag stretches to
|
|
111
|
-
* the left and the viewers sit on the right.
|
|
112
|
-
*/
|
|
113
|
-
export function RemoteSessionStatusRow({
|
|
114
|
-
showRecordingTag,
|
|
115
|
-
viewers,
|
|
116
|
-
}: {
|
|
117
|
-
showRecordingTag: boolean;
|
|
118
|
-
viewers?: RemoteSessionViewer[];
|
|
119
|
-
}) {
|
|
120
|
-
const hasViewers = !!viewers && viewers.length > 0;
|
|
121
|
-
if (!showRecordingTag && !hasViewers) return null;
|
|
122
|
-
if (!hasViewers) return <RemoteSessionRecordingTag />;
|
|
123
|
-
return (
|
|
124
|
-
<div className="flex w-full items-center gap-[var(--spacing-system-m)]">
|
|
125
|
-
{showRecordingTag && <RemoteSessionRecordingTag className="flex-1 justify-center self-auto" />}
|
|
126
|
-
<RemoteSessionViewers viewers={viewers} className="ml-auto" />
|
|
127
|
-
</div>
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
102
|
/** Grab cursor on the surfaces the window is moved by. */
|
|
132
103
|
export const REMOTE_SESSION_DRAG_HANDLE_CLASS = 'cursor-grab active:cursor-grabbing';
|
|
133
104
|
|
|
@@ -31,32 +31,6 @@ export interface RemoteSessionChatMessage {
|
|
|
31
31
|
/** The terminal dialogs of a session: the end confirm and the two "it is over" notices. */
|
|
32
32
|
export type RemoteSessionDialogVariant = 'end-confirm' | 'session-ended' | 'connection-lost';
|
|
33
33
|
|
|
34
|
-
/** Someone in a live session: the technician running it (the host) or a colleague watching. */
|
|
35
|
-
export interface RemoteSessionViewer {
|
|
36
|
-
id: string;
|
|
37
|
-
name: string;
|
|
38
|
-
avatarUrl?: string | null;
|
|
39
|
-
/** The technician running the session; listed first and ringed in the accent colour. */
|
|
40
|
-
isHost?: boolean;
|
|
41
|
-
/** The signed-in user, labelled "(you)" in the list. */
|
|
42
|
-
isYou?: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** Where a remote session's recording is in its lifecycle, as the session list tags it. */
|
|
46
|
-
export type RemoteSessionStatus = 'live' | 'processing' | 'failed';
|
|
47
|
-
|
|
48
|
-
/** Why a recording is kept past its expiry date. */
|
|
49
|
-
export type RemoteSessionKeepReason = 'CLIENT_DISPUTE' | 'INTERNAL_REVIEW' | 'LEGAL_OR_COMPLIANCE' | 'OTHER';
|
|
50
|
-
|
|
51
|
-
/** A moment of the session, placed on the recording by its offset from the start. */
|
|
52
|
-
export interface RemoteSessionEvent {
|
|
53
|
-
id: string;
|
|
54
|
-
/** Milliseconds from the start of the recording. */
|
|
55
|
-
offsetMs: number;
|
|
56
|
-
title: string;
|
|
57
|
-
detail?: string | null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
34
|
/**
|
|
61
35
|
* Pointer handlers a host attaches to the surfaces the user moves the window
|
|
62
36
|
* by (the desktop chat starts a native window drag from them).
|
package/tailwind.config.ts
CHANGED
|
@@ -413,11 +413,6 @@ const config: Config = {
|
|
|
413
413
|
'0%, 80%, 100%': { transform: 'scale(1)', opacity: '0.7' },
|
|
414
414
|
'40%': { transform: 'scale(1.5)', opacity: '1' },
|
|
415
415
|
},
|
|
416
|
-
// The dot on a LIVE tag: opacity only, so it reads as "on air" without moving.
|
|
417
|
-
'live-pulse': {
|
|
418
|
-
'0%, 100%': { opacity: '1' },
|
|
419
|
-
'50%': { opacity: '0.25' },
|
|
420
|
-
},
|
|
421
416
|
},
|
|
422
417
|
animation: {
|
|
423
418
|
'accordion-down': 'accordion-down 0.2s ease-out',
|
|
@@ -425,7 +420,6 @@ const config: Config = {
|
|
|
425
420
|
'fade-in': 'fade-in 0.3s ease-out',
|
|
426
421
|
'cursor-blink': 'cursor-blink 1s steps(1) infinite',
|
|
427
422
|
'dot-pulse': 'dot-pulse 1.4s ease-in-out infinite',
|
|
428
|
-
'live-pulse': 'live-pulse 1.6s ease-in-out infinite',
|
|
429
423
|
},
|
|
430
424
|
},
|
|
431
425
|
},
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { RemoteSessionEvent } from './types';
|
|
2
|
-
/** `mm:ss` from the start of a recording; `h:mm:ss` from the first hour on. */
|
|
3
|
-
export declare function formatRemoteSessionOffset(offsetMs: number): string;
|
|
4
|
-
export interface RemoteSessionEventListProps {
|
|
5
|
-
events: RemoteSessionEvent[];
|
|
6
|
-
/** The event the playhead is on; highlighted. */
|
|
7
|
-
activeEventId?: string | null;
|
|
8
|
-
/** Seek the player to the event. */
|
|
9
|
-
onSelect?: (event: RemoteSessionEvent) => void;
|
|
10
|
-
className?: string;
|
|
11
|
-
}
|
|
12
|
-
/** SESSION EVENTS under the recording player: each event with its time, newest last. */
|
|
13
|
-
export declare function RemoteSessionEventList({ events, activeEventId, onSelect, className }: RemoteSessionEventListProps): import("react").JSX.Element;
|
|
14
|
-
export interface RemoteSessionTimelineMarkersProps {
|
|
15
|
-
events: RemoteSessionEvent[];
|
|
16
|
-
/** Length of the recording; events past it are pinned to the end. */
|
|
17
|
-
durationMs: number;
|
|
18
|
-
/** Seek the player to the event. */
|
|
19
|
-
onSelect?: (event: RemoteSessionEvent) => void;
|
|
20
|
-
className?: string;
|
|
21
|
-
}
|
|
22
|
-
/** The event marks above the player's track, one per event, at its share of the recording. */
|
|
23
|
-
export declare function RemoteSessionTimelineMarkers({ events, durationMs, onSelect, className, }: RemoteSessionTimelineMarkersProps): import("react").JSX.Element | null;
|
|
24
|
-
//# sourceMappingURL=remote-session-events.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote-session-events.d.ts","sourceRoot":"","sources":["../../../../src/components/features/remote-session/remote-session-events.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,+EAA+E;AAC/E,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oCAAoC;IACpC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wFAAwF;AACxF,wBAAgB,sBAAsB,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,2BAA2B,+BA8BjH;AAED,MAAM,WAAW,iCAAiC;IAChD,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,8FAA8F;AAC9F,wBAAgB,4BAA4B,CAAC,EAC3C,MAAM,EACN,UAAU,EACV,QAAQ,EACR,SAAS,GACV,EAAE,iCAAiC,sCAqBnC"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { RemoteSessionKeepReason } from './types';
|
|
2
|
-
/** How each Keep reason reads in the dialog, the session list and the release notice. */
|
|
3
|
-
export declare const REMOTE_SESSION_KEEP_REASON_LABELS: Record<RemoteSessionKeepReason, string>;
|
|
4
|
-
export interface KeepRecordingSelection {
|
|
5
|
-
reason: RemoteSessionKeepReason;
|
|
6
|
-
/** Trimmed; set for `OTHER` only. */
|
|
7
|
-
description: string | null;
|
|
8
|
-
}
|
|
9
|
-
export interface KeepRecordingModalProps {
|
|
10
|
-
isOpen: boolean;
|
|
11
|
-
onClose: () => void;
|
|
12
|
-
/** What kept recordings take of the tenant's allowance, e.g. "612 MB of 50 GB". */
|
|
13
|
-
keptUsage: string;
|
|
14
|
-
/** The Keep is in flight: the button spins and the dialog refuses to close. */
|
|
15
|
-
isPending?: boolean;
|
|
16
|
-
onConfirm: (selection: KeepRecordingSelection) => void;
|
|
17
|
-
}
|
|
18
|
-
/** Keep this recording: exempts it from automatic deletion until someone releases it. */
|
|
19
|
-
export declare function KeepRecordingModal({ isOpen, onClose, keptUsage, isPending, onConfirm, }: KeepRecordingModalProps): import("react").JSX.Element;
|
|
20
|
-
export interface ReleaseKeepingModalProps {
|
|
21
|
-
isOpen: boolean;
|
|
22
|
-
onClose: () => void;
|
|
23
|
-
/** Who placed the Keep. */
|
|
24
|
-
keptBy: string;
|
|
25
|
-
/** When the Keep was placed, formatted, e.g. "27 Jul 2026". */
|
|
26
|
-
keptOn: string;
|
|
27
|
-
/** The reason as it reads in the sentence, e.g. "Client dispute". */
|
|
28
|
-
reason: string;
|
|
29
|
-
/** The ticket or reference the Keep was placed for. */
|
|
30
|
-
ticket?: string | null;
|
|
31
|
-
/** When the recording will be deleted once released, formatted. */
|
|
32
|
-
expiresOn: string;
|
|
33
|
-
/** The original expiry date when it has already passed, so the release adds the grace period. */
|
|
34
|
-
dueOn?: string | null;
|
|
35
|
-
/** The release is in flight: the button spins and the dialog refuses to close. */
|
|
36
|
-
isPending?: boolean;
|
|
37
|
-
onConfirm: () => void;
|
|
38
|
-
}
|
|
39
|
-
/** Release Keeping: hands the recording back to the normal expiry, nothing is deleted on the spot. */
|
|
40
|
-
export declare function ReleaseKeepingModal({ isOpen, onClose, keptBy, keptOn, reason, ticket, expiresOn, dueOn, isPending, onConfirm, }: ReleaseKeepingModalProps): import("react").JSX.Element;
|
|
41
|
-
//# sourceMappingURL=remote-session-keep-modals.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote-session-keep-modals.d.ts","sourceRoot":"","sources":["../../../../src/components/features/remote-session/remote-session-keep-modals.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvD,yFAAyF;AACzF,eAAO,MAAM,iCAAiC,EAAE,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAKrF,CAAC;AAmBF,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,uBAAuB,CAAC;IAChC,qCAAqC;IACrC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,CAAC,SAAS,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACxD;AAED,yFAAyF;AACzF,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,OAAO,EACP,SAAS,EACT,SAAiB,EACjB,SAAS,GACV,EAAE,uBAAuB,+BAoFzB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,kFAAkF;IAClF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,OAAO,EACP,MAAM,EACN,MAAM,EACN,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,EACL,SAAiB,EACjB,SAAS,GACV,EAAE,wBAAwB,+BA+B1B"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { RemoteSessionStatus } from './types';
|
|
2
|
-
export interface RemoteSessionStatusTagProps {
|
|
3
|
-
status: RemoteSessionStatus;
|
|
4
|
-
className?: string;
|
|
5
|
-
}
|
|
6
|
-
/** LIVE / PROCESSING / FAILED beside a session's date in the session list and on its page. */
|
|
7
|
-
export declare function RemoteSessionStatusTag({ status, className }: RemoteSessionStatusTagProps): import("react").JSX.Element;
|
|
8
|
-
export type RemoteSessionExpiryProps = {
|
|
9
|
-
className?: string;
|
|
10
|
-
} & ({
|
|
11
|
-
state: 'kept';
|
|
12
|
-
keptBy: string;
|
|
13
|
-
reason: string;
|
|
14
|
-
} | {
|
|
15
|
-
state: 'scheduled';
|
|
16
|
-
date: string;
|
|
17
|
-
remaining?: string | null;
|
|
18
|
-
} | {
|
|
19
|
-
state: 'expired';
|
|
20
|
-
} | {
|
|
21
|
-
state: 'none';
|
|
22
|
-
});
|
|
23
|
-
/** The EXPIRES cell of a recording: its expiry date, the Keep holding it, or that it has expired. */
|
|
24
|
-
export declare function RemoteSessionExpiry(props: RemoteSessionExpiryProps): import("react").JSX.Element;
|
|
25
|
-
export interface RemoteSessionStorageAlertProps {
|
|
26
|
-
/** `device` on the device page (new sessions there aren't recorded); `session` on a running session. */
|
|
27
|
-
scope: 'device' | 'session';
|
|
28
|
-
/** The plan's recording storage, e.g. "100 GB"; named on the device page. */
|
|
29
|
-
capacity?: string | null;
|
|
30
|
-
className?: string;
|
|
31
|
-
}
|
|
32
|
-
/** The banner shown while the tenant's recording storage is full. */
|
|
33
|
-
export declare function RemoteSessionStorageAlert({ scope, capacity, className }: RemoteSessionStorageAlertProps): import("react").JSX.Element;
|
|
34
|
-
//# sourceMappingURL=remote-session-status.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote-session-status.d.ts","sourceRoot":"","sources":["../../../../src/components/features/remote-session/remote-session-status.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAanD,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,8FAA8F;AAC9F,wBAAgB,sBAAsB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,2BAA2B,+BAUxF;AAED,MAAM,MAAM,wBAAwB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,CAC5D;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC/D;IAAE,KAAK,EAAE,SAAS,CAAA;CAAE,GACpB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CACpB,CAAC;AAEF,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,+BA2BlE;AAED,MAAM,WAAW,8BAA8B;IAC7C,wGAAwG;IACxG,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qEAAqE;AACrE,wBAAgB,yBAAyB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,8BAA8B,+BAmBvG"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { RemoteSessionViewer } from './types';
|
|
2
|
-
export interface RemoteSessionViewersProps {
|
|
3
|
-
/** Everyone in the session, the host included. */
|
|
4
|
-
viewers: RemoteSessionViewer[];
|
|
5
|
-
/** Faces shown before the rest collapse into "+N". */
|
|
6
|
-
max?: number;
|
|
7
|
-
className?: string;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Who is in a live session: an avatar stack (the host ringed in the accent
|
|
11
|
-
* colour) that opens the full list. Shown to the host, to the watchers and to
|
|
12
|
-
* the end user.
|
|
13
|
-
*/
|
|
14
|
-
export declare function RemoteSessionViewers({ viewers, max, className }: RemoteSessionViewersProps): import("react").JSX.Element | null;
|
|
15
|
-
//# sourceMappingURL=remote-session-viewers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote-session-viewers.d.ts","sourceRoot":"","sources":["../../../../src/components/features/remote-session/remote-session-viewers.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAanD,MAAM,WAAW,yBAAyB;IACxC,kDAAkD;IAClD,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,GAAO,EAAE,SAAS,EAAE,EAAE,yBAAyB,sCAqE9F"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { cn } from '../../../utils/cn';
|
|
4
|
-
import type { RemoteSessionEvent } from './types';
|
|
5
|
-
|
|
6
|
-
/** `mm:ss` from the start of a recording; `h:mm:ss` from the first hour on. */
|
|
7
|
-
export function formatRemoteSessionOffset(offsetMs: number): string {
|
|
8
|
-
const total = Math.max(0, Math.floor(offsetMs / 1000));
|
|
9
|
-
const hours = Math.floor(total / 3600);
|
|
10
|
-
const minutes = String(Math.floor((total % 3600) / 60)).padStart(2, '0');
|
|
11
|
-
const seconds = String(total % 60).padStart(2, '0');
|
|
12
|
-
return hours > 0 ? `${hours}:${minutes}:${seconds}` : `${minutes}:${seconds}`;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface RemoteSessionEventListProps {
|
|
16
|
-
events: RemoteSessionEvent[];
|
|
17
|
-
/** The event the playhead is on; highlighted. */
|
|
18
|
-
activeEventId?: string | null;
|
|
19
|
-
/** Seek the player to the event. */
|
|
20
|
-
onSelect?: (event: RemoteSessionEvent) => void;
|
|
21
|
-
className?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** SESSION EVENTS under the recording player: each event with its time, newest last. */
|
|
25
|
-
export function RemoteSessionEventList({ events, activeEventId, onSelect, className }: RemoteSessionEventListProps) {
|
|
26
|
-
return (
|
|
27
|
-
<section className={cn('flex w-full flex-col gap-[var(--spacing-system-xxs)]', className)}>
|
|
28
|
-
<h2 className="text-ods-text-secondary text-h5">Session Events</h2>
|
|
29
|
-
<ol className="flex w-full flex-col gap-[var(--spacing-system-xxs)] rounded-md border border-ods-border bg-ods-card p-[var(--spacing-system-m)]">
|
|
30
|
-
{events.map(event => (
|
|
31
|
-
<li key={event.id}>
|
|
32
|
-
<button
|
|
33
|
-
type="button"
|
|
34
|
-
aria-current={event.id === activeEventId || undefined}
|
|
35
|
-
onClick={() => onSelect?.(event)}
|
|
36
|
-
className={cn(
|
|
37
|
-
'flex w-full items-start gap-[var(--spacing-system-xxs)] rounded-md p-[var(--spacing-system-xxs)] text-left outline-none transition-colors',
|
|
38
|
-
'hover:bg-ods-bg-hover focus-visible:ring-2 focus-visible:ring-ods-focus',
|
|
39
|
-
event.id === activeEventId && 'bg-ods-border hover:bg-ods-border',
|
|
40
|
-
)}
|
|
41
|
-
>
|
|
42
|
-
<span className="w-[84px] shrink-0 text-ods-text-secondary text-h4">
|
|
43
|
-
{formatRemoteSessionOffset(event.offsetMs)}
|
|
44
|
-
</span>
|
|
45
|
-
<span className="flex min-w-0 flex-1 flex-col">
|
|
46
|
-
<span className="text-ods-text-primary text-h4">{event.title}</span>
|
|
47
|
-
{event.detail && <span className="text-ods-text-secondary text-h6">{event.detail}</span>}
|
|
48
|
-
</span>
|
|
49
|
-
</button>
|
|
50
|
-
</li>
|
|
51
|
-
))}
|
|
52
|
-
</ol>
|
|
53
|
-
</section>
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface RemoteSessionTimelineMarkersProps {
|
|
58
|
-
events: RemoteSessionEvent[];
|
|
59
|
-
/** Length of the recording; events past it are pinned to the end. */
|
|
60
|
-
durationMs: number;
|
|
61
|
-
/** Seek the player to the event. */
|
|
62
|
-
onSelect?: (event: RemoteSessionEvent) => void;
|
|
63
|
-
className?: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** The event marks above the player's track, one per event, at its share of the recording. */
|
|
67
|
-
export function RemoteSessionTimelineMarkers({
|
|
68
|
-
events,
|
|
69
|
-
durationMs,
|
|
70
|
-
onSelect,
|
|
71
|
-
className,
|
|
72
|
-
}: RemoteSessionTimelineMarkersProps) {
|
|
73
|
-
if (durationMs <= 0) return null;
|
|
74
|
-
return (
|
|
75
|
-
<div className={cn('relative h-4 w-full', className)}>
|
|
76
|
-
{events.map(event => {
|
|
77
|
-
const share = Math.min(1, Math.max(0, event.offsetMs / durationMs));
|
|
78
|
-
const label = `${event.title} at ${formatRemoteSessionOffset(event.offsetMs)}`;
|
|
79
|
-
return (
|
|
80
|
-
<button
|
|
81
|
-
key={event.id}
|
|
82
|
-
type="button"
|
|
83
|
-
aria-label={label}
|
|
84
|
-
title={label}
|
|
85
|
-
onClick={() => onSelect?.(event)}
|
|
86
|
-
style={{ left: `${share * 100}%` }}
|
|
87
|
-
className="absolute top-0 h-4 w-1 -translate-x-1/2 rounded-md bg-ods-text-secondary outline-none transition-colors hover:bg-ods-text-primary focus-visible:ring-2 focus-visible:ring-ods-focus"
|
|
88
|
-
/>
|
|
89
|
-
);
|
|
90
|
-
})}
|
|
91
|
-
</div>
|
|
92
|
-
);
|
|
93
|
-
}
|