@handled-ai/design-system 0.20.20 → 0.20.22
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/components/timeline-activity.d.ts +45 -0
- package/dist/components/timeline-activity.js +401 -52
- package/dist/components/timeline-activity.js.map +1 -1
- package/package.json +1 -1
- package/src/components/__tests__/timeline-activity.test.tsx +329 -0
- package/src/components/timeline-activity.tsx +516 -39
|
@@ -31,6 +31,51 @@ interface TimelineEvent {
|
|
|
31
31
|
* existing consumers are unaffected.
|
|
32
32
|
*/
|
|
33
33
|
bodyHtml?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Sender signature HTML, split out of the main body by the consuming app's
|
|
36
|
+
* email pipeline. When present, it is hidden behind a subtle "Show
|
|
37
|
+
* signature" toggle (collapsed by default) so signatures don't add noise to
|
|
38
|
+
* the timeline. Sanitized before rendering. Optional — when absent the body
|
|
39
|
+
* renders exactly as before. Mirrors `signatureHtml` on EmailPreviewCard.
|
|
40
|
+
*/
|
|
41
|
+
signatureHtml?: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Quoted / trailing thread content (the "On <date> X wrote:" history) split
|
|
44
|
+
* out of the main body. When present, it is hidden behind a subtle "Show
|
|
45
|
+
* quoted text" toggle (collapsed by default). Sanitized before rendering.
|
|
46
|
+
* Optional — when absent the body renders exactly as before.
|
|
47
|
+
*/
|
|
48
|
+
quotedHtml?: string | null;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Gong call payload. When present, the card renders a dedicated, first-class
|
|
52
|
+
* Gong call card (mirroring the `email` treatment) instead of generic
|
|
53
|
+
* content: a collapsed duration + brief-snippet preview, and an expanded
|
|
54
|
+
* card with the call title, start time, direction/outcome chips, the AI
|
|
55
|
+
* brief, key points, next steps, and a "View in Gong" link. Opt-in: when
|
|
56
|
+
* absent, existing consumers are unaffected. Every field except `title` is
|
|
57
|
+
* optional/nullable and renders nothing when absent (no empty sections,
|
|
58
|
+
* no "null"/"undefined", no "Invalid Date").
|
|
59
|
+
*/
|
|
60
|
+
gongCall?: {
|
|
61
|
+
/** Gong call title. */
|
|
62
|
+
title: string;
|
|
63
|
+
/** ISO datetime of the call start. */
|
|
64
|
+
startTime?: string | null;
|
|
65
|
+
/** Call length in seconds. Formatted to a human duration when present. */
|
|
66
|
+
durationSeconds?: number | null;
|
|
67
|
+
/** Call direction, e.g. "Outbound" / "Inbound". */
|
|
68
|
+
direction?: string | null;
|
|
69
|
+
/** Call outcome, e.g. "Connected". */
|
|
70
|
+
outcome?: string | null;
|
|
71
|
+
/** Gong AI call brief (plain text, may be multi-paragraph). */
|
|
72
|
+
brief?: string | null;
|
|
73
|
+
/** Gong AI key points (plain text, often newline-delimited bullets). */
|
|
74
|
+
keyPoints?: string | null;
|
|
75
|
+
/** Gong AI highlights / next steps (plain text). */
|
|
76
|
+
nextSteps?: string | null;
|
|
77
|
+
/** Deep link to the call in Gong. */
|
|
78
|
+
url?: string | null;
|
|
34
79
|
};
|
|
35
80
|
content?: React.ReactNode;
|
|
36
81
|
source?: {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
import { cn } from "../lib/utils.js";
|
|
7
|
-
import { ChevronDown, ChevronUp, ExternalLink } from "lucide-react";
|
|
7
|
+
import { ChevronDown, ChevronUp, ExternalLink, Phone } from "lucide-react";
|
|
8
8
|
import { EmailBody as SharedEmailBody } from "./email-body.js";
|
|
9
9
|
import {
|
|
10
10
|
decodeEmailDisplayText,
|
|
@@ -78,7 +78,7 @@ const TIMELINE_VARIANT_CLASSES = {
|
|
|
78
78
|
title: "min-w-0 pr-1 text-[13.5px] font-medium leading-tight text-foreground",
|
|
79
79
|
time: "shrink-0 whitespace-nowrap pt-px text-[11px] leading-tight text-muted-foreground/60",
|
|
80
80
|
cardContainer: "overflow-hidden rounded-lg border border-border/70 bg-card",
|
|
81
|
-
cardHeader: "flex items-
|
|
81
|
+
cardHeader: "flex items-start justify-between border-b border-border/60 bg-muted/30 px-3 py-2 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/70",
|
|
82
82
|
cardBody: "px-3 py-2.5 text-[13px] leading-relaxed",
|
|
83
83
|
cardFooter: "border-t border-border/60 bg-muted/10 px-3 py-1.5",
|
|
84
84
|
collapsedPreview: "flex items-center justify-between gap-2 px-3 py-2 text-[13px] text-muted-foreground",
|
|
@@ -135,6 +135,7 @@ function TimelineItem({
|
|
|
135
135
|
const [showAllRecipients, setShowAllRecipients] = React.useState(false);
|
|
136
136
|
const hasContent = !!event.content;
|
|
137
137
|
const hasEmail = !!event.email;
|
|
138
|
+
const hasGongCall = !!event.gongCall;
|
|
138
139
|
const classes = TIMELINE_VARIANT_CLASSES[variant];
|
|
139
140
|
const toneStyle = event.tone ? TONE_CLASSES[event.tone] : null;
|
|
140
141
|
const dotClasses = toneStyle ? toneStyle.dot : NEUTRAL_DOT_CLASSES;
|
|
@@ -148,7 +149,16 @@ function TimelineItem({
|
|
|
148
149
|
/* @__PURE__ */ jsx("span", { className: classes.time, children: event.time })
|
|
149
150
|
] }),
|
|
150
151
|
event.actor && /* @__PURE__ */ jsx(ActorByline, { actor: event.actor, time: event.time }),
|
|
151
|
-
(hasContent || hasEmail) && /* @__PURE__ */ jsx("div", { className: "mt-2", children: event.isInteractive ?
|
|
152
|
+
(hasContent || hasEmail || hasGongCall) && /* @__PURE__ */ jsx("div", { className: "mt-2", children: event.isInteractive ? hasGongCall ? /* @__PURE__ */ jsx(
|
|
153
|
+
GongCallCard,
|
|
154
|
+
{
|
|
155
|
+
event,
|
|
156
|
+
expanded,
|
|
157
|
+
setExpanded,
|
|
158
|
+
variant,
|
|
159
|
+
classes
|
|
160
|
+
}
|
|
161
|
+
) : hasEmail ? /* @__PURE__ */ jsx(
|
|
152
162
|
EmailCard,
|
|
153
163
|
{
|
|
154
164
|
event,
|
|
@@ -176,6 +186,33 @@ function reactNodeToDisplayText(value) {
|
|
|
176
186
|
if (typeof value === "string" || typeof value === "number") return decodeEmailDisplayText(String(value));
|
|
177
187
|
return "";
|
|
178
188
|
}
|
|
189
|
+
function formatCallDuration(durationSeconds) {
|
|
190
|
+
if (durationSeconds == null || !Number.isFinite(durationSeconds) || durationSeconds <= 0) return "";
|
|
191
|
+
const totalMinutes = Math.round(durationSeconds / 60);
|
|
192
|
+
if (totalMinutes < 1) return "< 1 min";
|
|
193
|
+
if (totalMinutes < 60) return `${totalMinutes} min`;
|
|
194
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
195
|
+
const minutes = totalMinutes % 60;
|
|
196
|
+
return minutes === 0 ? `${hours} h` : `${hours} h ${minutes} min`;
|
|
197
|
+
}
|
|
198
|
+
function cleanGongText(value) {
|
|
199
|
+
if (!value) return "";
|
|
200
|
+
return decodeEmailDisplayText(value).trim();
|
|
201
|
+
}
|
|
202
|
+
function getTimelineGongCallDisplay(gongCall) {
|
|
203
|
+
var _a, _b, _c, _d;
|
|
204
|
+
const title = cleanGongText(gongCall.title);
|
|
205
|
+
const startTime = (_a = formatEmailTimestamp(gongCall.startTime)) != null ? _a : "";
|
|
206
|
+
const duration = formatCallDuration(gongCall.durationSeconds);
|
|
207
|
+
const direction = cleanGongText(gongCall.direction);
|
|
208
|
+
const outcome = cleanGongText(gongCall.outcome);
|
|
209
|
+
const brief = cleanGongText(gongCall.brief);
|
|
210
|
+
const keyPoints = cleanGongText(gongCall.keyPoints);
|
|
211
|
+
const nextSteps = cleanGongText(gongCall.nextSteps);
|
|
212
|
+
const url = ((_b = gongCall.url) == null ? void 0 : _b.trim()) || "";
|
|
213
|
+
const snippet = (_d = (_c = brief.split("\n").find((line) => line.trim())) == null ? void 0 : _c.trim()) != null ? _d : "";
|
|
214
|
+
return { title, startTime, duration, direction, outcome, brief, keyPoints, nextSteps, url, snippet };
|
|
215
|
+
}
|
|
179
216
|
function getTimelineEmailDisplay(email) {
|
|
180
217
|
var _a, _b, _c, _d, _e;
|
|
181
218
|
const sender = normalizeEmailSender({ name: email.from, email: email.fromEmail });
|
|
@@ -186,7 +223,8 @@ function getTimelineEmailDisplay(email) {
|
|
|
186
223
|
const subject = email.subject ? decodeEmailDisplayText(email.subject) : "";
|
|
187
224
|
const bodyText = reactNodeToDisplayText(email.body);
|
|
188
225
|
const snippet = emailBodySnippet({ bodyHtml: email.bodyHtml, body: bodyText }, 140);
|
|
189
|
-
|
|
226
|
+
const hasRecipients = Boolean(to || cc || bcc);
|
|
227
|
+
return { sender, to, cc, bcc, date, subject, bodyText, snippet, hasRecipients };
|
|
190
228
|
}
|
|
191
229
|
function EmailMetadata({
|
|
192
230
|
email,
|
|
@@ -194,6 +232,7 @@ function EmailMetadata({
|
|
|
194
232
|
setShowAllRecipients
|
|
195
233
|
}) {
|
|
196
234
|
const display = getTimelineEmailDisplay(email);
|
|
235
|
+
const hasExpandableRecipients = Boolean(display.cc || display.bcc);
|
|
197
236
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
198
237
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
199
238
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-baseline gap-1.5", children: [
|
|
@@ -202,37 +241,78 @@ function EmailMetadata({
|
|
|
202
241
|
] }),
|
|
203
242
|
display.date ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-muted-foreground/50 whitespace-nowrap", children: display.date }) : null
|
|
204
243
|
] }),
|
|
205
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-0.5
|
|
206
|
-
/* @__PURE__ */ jsxs("
|
|
207
|
-
"
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
"
|
|
220
|
-
|
|
221
|
-
|
|
244
|
+
display.hasRecipients ? /* @__PURE__ */ jsxs("div", { className: "mt-0.5 text-xs text-muted-foreground", children: [
|
|
245
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
246
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
247
|
+
display.to ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
248
|
+
"To ",
|
|
249
|
+
display.to
|
|
250
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
251
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "cc" }),
|
|
252
|
+
" ",
|
|
253
|
+
display.cc || display.bcc
|
|
254
|
+
] }),
|
|
255
|
+
display.to && !showAllRecipients && hasExpandableRecipients ? /* @__PURE__ */ jsx(Fragment, { children: ", \u2026" }) : null
|
|
256
|
+
] }),
|
|
257
|
+
hasExpandableRecipients ? /* @__PURE__ */ jsx(
|
|
258
|
+
"button",
|
|
259
|
+
{
|
|
260
|
+
type: "button",
|
|
261
|
+
onClick: (e) => {
|
|
262
|
+
e.stopPropagation();
|
|
263
|
+
setShowAllRecipients((prev) => !prev);
|
|
264
|
+
},
|
|
265
|
+
className: "shrink-0 text-muted-foreground/40 hover:text-muted-foreground transition-colors",
|
|
266
|
+
"aria-label": showAllRecipients ? "Hide cc and bcc" : "Show cc and bcc",
|
|
267
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: cn("h-3 w-3 transition-transform", showAllRecipients && "rotate-180") })
|
|
268
|
+
}
|
|
269
|
+
) : null
|
|
222
270
|
] }),
|
|
223
|
-
display.
|
|
224
|
-
"
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
271
|
+
showAllRecipients && display.to && display.cc ? /* @__PURE__ */ jsxs("div", { className: "truncate", children: [
|
|
272
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "cc" }),
|
|
273
|
+
" ",
|
|
274
|
+
display.cc
|
|
275
|
+
] }) : null,
|
|
276
|
+
showAllRecipients && display.bcc ? /* @__PURE__ */ jsxs("div", { className: "truncate", children: [
|
|
277
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "bcc" }),
|
|
278
|
+
" ",
|
|
279
|
+
display.bcc
|
|
280
|
+
] }) : null
|
|
281
|
+
] }) : null
|
|
282
|
+
] });
|
|
283
|
+
}
|
|
284
|
+
function SuppressedHtmlSection({
|
|
285
|
+
html,
|
|
286
|
+
showLabel,
|
|
287
|
+
hideLabel,
|
|
288
|
+
slot
|
|
289
|
+
}) {
|
|
290
|
+
const [open, setOpen] = React.useState(false);
|
|
291
|
+
return /* @__PURE__ */ jsxs("div", { className: "mt-2", "data-slot": slot, children: [
|
|
292
|
+
/* @__PURE__ */ jsxs(
|
|
293
|
+
"button",
|
|
294
|
+
{
|
|
295
|
+
type: "button",
|
|
296
|
+
onClick: (e) => {
|
|
297
|
+
e.stopPropagation();
|
|
298
|
+
setOpen((value) => !value);
|
|
299
|
+
},
|
|
300
|
+
"aria-expanded": open,
|
|
301
|
+
className: "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-muted-foreground/70 transition-colors hover:bg-muted hover:text-foreground",
|
|
302
|
+
children: [
|
|
303
|
+
open ? hideLabel : showLabel,
|
|
304
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: cn("h-3 w-3 transition-transform", open && "rotate-180") })
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
),
|
|
308
|
+
open ? /* @__PURE__ */ jsx(
|
|
309
|
+
"div",
|
|
310
|
+
{
|
|
311
|
+
"data-slot": `${slot}-content`,
|
|
312
|
+
className: "mt-2 border-l-2 border-border pl-3 text-sm leading-relaxed text-muted-foreground",
|
|
313
|
+
children: /* @__PURE__ */ jsx(SharedEmailBody, { html, variant: "history", collapseDetails: false })
|
|
314
|
+
}
|
|
315
|
+
) : null
|
|
236
316
|
] });
|
|
237
317
|
}
|
|
238
318
|
function TimelineEmailBody({ email }) {
|
|
@@ -251,7 +331,32 @@ function TimelineEmailBody({ email }) {
|
|
|
251
331
|
className: "text-sm leading-relaxed"
|
|
252
332
|
}
|
|
253
333
|
);
|
|
254
|
-
|
|
334
|
+
const hasSignature = Boolean(email.signatureHtml && email.signatureHtml.trim());
|
|
335
|
+
const hasQuoted = Boolean(email.quotedHtml && email.quotedHtml.trim());
|
|
336
|
+
if (!hasSignature && !hasQuoted) {
|
|
337
|
+
return email.bodyHtml ? /* @__PURE__ */ jsx("div", { "data-slot": "timeline-email-html", children: body }) : body;
|
|
338
|
+
}
|
|
339
|
+
return /* @__PURE__ */ jsxs("div", { "data-slot": email.bodyHtml ? "timeline-email-html" : void 0, children: [
|
|
340
|
+
body,
|
|
341
|
+
hasSignature ? /* @__PURE__ */ jsx(
|
|
342
|
+
SuppressedHtmlSection,
|
|
343
|
+
{
|
|
344
|
+
html: email.signatureHtml,
|
|
345
|
+
showLabel: "Show signature",
|
|
346
|
+
hideLabel: "Hide signature",
|
|
347
|
+
slot: "timeline-email-signature"
|
|
348
|
+
}
|
|
349
|
+
) : null,
|
|
350
|
+
hasQuoted ? /* @__PURE__ */ jsx(
|
|
351
|
+
SuppressedHtmlSection,
|
|
352
|
+
{
|
|
353
|
+
html: email.quotedHtml,
|
|
354
|
+
showLabel: "Show quoted text",
|
|
355
|
+
hideLabel: "Hide quoted text",
|
|
356
|
+
slot: "timeline-email-quoted"
|
|
357
|
+
}
|
|
358
|
+
) : null
|
|
359
|
+
] });
|
|
255
360
|
}
|
|
256
361
|
function renderDecodedPreview(preview) {
|
|
257
362
|
if (typeof preview === "string" || typeof preview === "number") return decodeEmailDisplayText(String(preview));
|
|
@@ -267,7 +372,7 @@ function CollapsedEmailPreview({
|
|
|
267
372
|
const display = email ? getTimelineEmailDisplay(email) : null;
|
|
268
373
|
const previewContent = (display == null ? void 0 : display.snippet) || renderDecodedPreview(preview);
|
|
269
374
|
return /* @__PURE__ */ jsxs("div", { className, onClick, children: [
|
|
270
|
-
/* @__PURE__ */ jsxs("span", { className: "line-clamp-1 pr-3 text-[13px]", children: [
|
|
375
|
+
/* @__PURE__ */ jsxs("span", { className: "line-clamp-1 min-w-0 flex-1 pr-3 text-[13px]", children: [
|
|
271
376
|
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: display == null ? void 0 : display.sender.name }),
|
|
272
377
|
/* @__PURE__ */ jsx("span", { className: "mx-1.5 text-muted-foreground/40", children: "\xB7" }),
|
|
273
378
|
(display == null ? void 0 : display.subject) ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -292,6 +397,28 @@ function ShowLessButton({
|
|
|
292
397
|
/* @__PURE__ */ jsx(ChevronUp, { className: "h-3 w-3" })
|
|
293
398
|
] });
|
|
294
399
|
}
|
|
400
|
+
function CollapseTopButton({
|
|
401
|
+
onClick,
|
|
402
|
+
className
|
|
403
|
+
}) {
|
|
404
|
+
return /* @__PURE__ */ jsxs(
|
|
405
|
+
"button",
|
|
406
|
+
{
|
|
407
|
+
type: "button",
|
|
408
|
+
onClick,
|
|
409
|
+
"aria-label": "Show less",
|
|
410
|
+
"data-slot": "timeline-collapse-top",
|
|
411
|
+
className: cn(
|
|
412
|
+
"shrink-0 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground/60 transition-colors hover:text-foreground",
|
|
413
|
+
className
|
|
414
|
+
),
|
|
415
|
+
children: [
|
|
416
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only sm:not-sr-only", children: "Show less" }),
|
|
417
|
+
/* @__PURE__ */ jsx(ChevronUp, { className: "h-3 w-3" })
|
|
418
|
+
]
|
|
419
|
+
}
|
|
420
|
+
);
|
|
421
|
+
}
|
|
295
422
|
function SourceAction({
|
|
296
423
|
source,
|
|
297
424
|
onSourceClick,
|
|
@@ -330,6 +457,204 @@ function SourceAction({
|
|
|
330
457
|
}
|
|
331
458
|
);
|
|
332
459
|
}
|
|
460
|
+
function GongLinkAction({
|
|
461
|
+
url,
|
|
462
|
+
className
|
|
463
|
+
}) {
|
|
464
|
+
return /* @__PURE__ */ jsxs(
|
|
465
|
+
"a",
|
|
466
|
+
{
|
|
467
|
+
href: url,
|
|
468
|
+
target: "_blank",
|
|
469
|
+
rel: "noopener noreferrer",
|
|
470
|
+
onClick: (e) => e.stopPropagation(),
|
|
471
|
+
className,
|
|
472
|
+
"data-slot": "timeline-gong-link",
|
|
473
|
+
children: [
|
|
474
|
+
"View in Gong",
|
|
475
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" })
|
|
476
|
+
]
|
|
477
|
+
}
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
function TimelineGongCallBody({
|
|
481
|
+
display,
|
|
482
|
+
labelClassName
|
|
483
|
+
}) {
|
|
484
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", "data-slot": "timeline-gong-body", children: [
|
|
485
|
+
display.brief ? /* @__PURE__ */ jsx("div", { className: "whitespace-pre-line text-sm leading-relaxed text-foreground/90", children: display.brief }) : null,
|
|
486
|
+
display.keyPoints ? /* @__PURE__ */ jsxs("div", { "data-slot": "timeline-gong-key-points", children: [
|
|
487
|
+
/* @__PURE__ */ jsx("div", { className: labelClassName, children: "Key points" }),
|
|
488
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 whitespace-pre-line text-sm leading-relaxed text-foreground/90", children: display.keyPoints })
|
|
489
|
+
] }) : null,
|
|
490
|
+
display.nextSteps ? /* @__PURE__ */ jsxs("div", { "data-slot": "timeline-gong-next-steps", children: [
|
|
491
|
+
/* @__PURE__ */ jsx("div", { className: labelClassName, children: "Next steps" }),
|
|
492
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 whitespace-pre-line text-sm leading-relaxed text-foreground/90", children: display.nextSteps })
|
|
493
|
+
] }) : null
|
|
494
|
+
] });
|
|
495
|
+
}
|
|
496
|
+
function GongCallHeader({
|
|
497
|
+
display
|
|
498
|
+
}) {
|
|
499
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
500
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
501
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
502
|
+
/* @__PURE__ */ jsx(Phone, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/60" }),
|
|
503
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-semibold text-foreground text-[13px]", children: display.title })
|
|
504
|
+
] }),
|
|
505
|
+
display.startTime ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-muted-foreground/50 whitespace-nowrap", children: display.startTime }) : null
|
|
506
|
+
] }),
|
|
507
|
+
display.duration || display.direction || display.outcome ? /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground", children: [
|
|
508
|
+
display.duration ? /* @__PURE__ */ jsx("span", { "data-slot": "timeline-gong-duration", children: display.duration }) : null,
|
|
509
|
+
display.direction ? /* @__PURE__ */ jsx("span", { className: "rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground", children: display.direction }) : null,
|
|
510
|
+
display.outcome ? /* @__PURE__ */ jsx("span", { className: "rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground", children: display.outcome }) : null
|
|
511
|
+
] }) : null
|
|
512
|
+
] });
|
|
513
|
+
}
|
|
514
|
+
function CollapsedGongCallPreview({
|
|
515
|
+
display,
|
|
516
|
+
className,
|
|
517
|
+
actionClassName,
|
|
518
|
+
onClick
|
|
519
|
+
}) {
|
|
520
|
+
return /* @__PURE__ */ jsxs("div", { className, onClick, children: [
|
|
521
|
+
/* @__PURE__ */ jsxs("span", { className: "line-clamp-1 min-w-0 flex-1 pr-3 text-[13px] text-muted-foreground", children: [
|
|
522
|
+
display.duration ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
523
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
524
|
+
/* @__PURE__ */ jsx(Phone, { className: "h-3 w-3" }),
|
|
525
|
+
display.duration
|
|
526
|
+
] }),
|
|
527
|
+
display.snippet ? /* @__PURE__ */ jsx("span", { className: "mx-1.5 text-muted-foreground/40", children: "\xB7" }) : null
|
|
528
|
+
] }) : null,
|
|
529
|
+
display.snippet ? /* @__PURE__ */ jsx("span", { children: display.snippet }) : null
|
|
530
|
+
] }),
|
|
531
|
+
/* @__PURE__ */ jsxs("button", { type: "button", className: actionClassName, children: [
|
|
532
|
+
"Expand ",
|
|
533
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3" })
|
|
534
|
+
] })
|
|
535
|
+
] });
|
|
536
|
+
}
|
|
537
|
+
function GongCallCard({
|
|
538
|
+
event,
|
|
539
|
+
expanded,
|
|
540
|
+
setExpanded,
|
|
541
|
+
variant,
|
|
542
|
+
classes
|
|
543
|
+
}) {
|
|
544
|
+
const gongCall = event.gongCall;
|
|
545
|
+
const display = getTimelineGongCallDisplay(gongCall);
|
|
546
|
+
if (variant === "default") {
|
|
547
|
+
return /* @__PURE__ */ jsx("div", { className: classes.cardContainer, "data-variant": variant, "data-slot": "timeline-gong-card", children: /* @__PURE__ */ jsx(
|
|
548
|
+
"div",
|
|
549
|
+
{
|
|
550
|
+
className: cn(
|
|
551
|
+
"px-3 py-2.5 text-sm",
|
|
552
|
+
!expanded && "cursor-pointer hover:bg-muted/30 transition-colors"
|
|
553
|
+
),
|
|
554
|
+
onClick: () => !expanded && setExpanded(true),
|
|
555
|
+
children: expanded ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
556
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
557
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(GongCallHeader, { display }) }),
|
|
558
|
+
/* @__PURE__ */ jsx(
|
|
559
|
+
CollapseTopButton,
|
|
560
|
+
{
|
|
561
|
+
onClick: (e) => {
|
|
562
|
+
e.stopPropagation();
|
|
563
|
+
setExpanded(false);
|
|
564
|
+
},
|
|
565
|
+
className: "mt-0.5"
|
|
566
|
+
}
|
|
567
|
+
)
|
|
568
|
+
] }),
|
|
569
|
+
/* @__PURE__ */ jsx(
|
|
570
|
+
TimelineGongCallBody,
|
|
571
|
+
{
|
|
572
|
+
display,
|
|
573
|
+
labelClassName: "text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70"
|
|
574
|
+
}
|
|
575
|
+
),
|
|
576
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-3", children: [
|
|
577
|
+
display.url ? /* @__PURE__ */ jsx(
|
|
578
|
+
GongLinkAction,
|
|
579
|
+
{
|
|
580
|
+
url: display.url,
|
|
581
|
+
className: "mr-auto inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground transition-colors hover:text-foreground"
|
|
582
|
+
}
|
|
583
|
+
) : null,
|
|
584
|
+
/* @__PURE__ */ jsx(
|
|
585
|
+
ShowLessButton,
|
|
586
|
+
{
|
|
587
|
+
onClick: (e) => {
|
|
588
|
+
e.stopPropagation();
|
|
589
|
+
setExpanded(false);
|
|
590
|
+
},
|
|
591
|
+
className: "flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground transition-colors hover:text-foreground"
|
|
592
|
+
}
|
|
593
|
+
)
|
|
594
|
+
] })
|
|
595
|
+
] }) : /* @__PURE__ */ jsx(
|
|
596
|
+
CollapsedGongCallPreview,
|
|
597
|
+
{
|
|
598
|
+
display,
|
|
599
|
+
className: "flex items-center justify-between gap-2 text-muted-foreground",
|
|
600
|
+
actionClassName: "flex shrink-0 items-center gap-1 text-[11px] font-semibold uppercase tracking-wider transition-colors hover:text-foreground"
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
}
|
|
604
|
+
) });
|
|
605
|
+
}
|
|
606
|
+
return /* @__PURE__ */ jsx("div", { className: classes.cardContainer, "data-variant": variant, "data-slot": "timeline-gong-card", children: expanded ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
607
|
+
/* @__PURE__ */ jsxs("div", { className: classes.cardHeader, "data-slot": "timeline-card-header", children: [
|
|
608
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 normal-case tracking-normal", children: /* @__PURE__ */ jsx(GongCallHeader, { display }) }),
|
|
609
|
+
/* @__PURE__ */ jsx(
|
|
610
|
+
CollapseTopButton,
|
|
611
|
+
{
|
|
612
|
+
onClick: (e) => {
|
|
613
|
+
e.stopPropagation();
|
|
614
|
+
setExpanded(false);
|
|
615
|
+
},
|
|
616
|
+
className: "ml-3 normal-case tracking-normal"
|
|
617
|
+
}
|
|
618
|
+
)
|
|
619
|
+
] }),
|
|
620
|
+
/* @__PURE__ */ jsx("div", { className: classes.cardBody, "data-slot": "timeline-card-body", children: /* @__PURE__ */ jsx(
|
|
621
|
+
TimelineGongCallBody,
|
|
622
|
+
{
|
|
623
|
+
display,
|
|
624
|
+
labelClassName: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/70"
|
|
625
|
+
}
|
|
626
|
+
) }),
|
|
627
|
+
/* @__PURE__ */ jsxs(
|
|
628
|
+
"div",
|
|
629
|
+
{
|
|
630
|
+
className: cn(classes.cardFooter, classes.actionLinkRow, display.url ? "justify-between" : "justify-end"),
|
|
631
|
+
"data-slot": "timeline-card-footer",
|
|
632
|
+
children: [
|
|
633
|
+
display.url ? /* @__PURE__ */ jsx(GongLinkAction, { url: display.url, className: classes.actionLink }) : null,
|
|
634
|
+
/* @__PURE__ */ jsx(
|
|
635
|
+
ShowLessButton,
|
|
636
|
+
{
|
|
637
|
+
type: "button",
|
|
638
|
+
onClick: (e) => {
|
|
639
|
+
e.stopPropagation();
|
|
640
|
+
setExpanded(false);
|
|
641
|
+
},
|
|
642
|
+
className: classes.actionLink
|
|
643
|
+
}
|
|
644
|
+
)
|
|
645
|
+
]
|
|
646
|
+
}
|
|
647
|
+
)
|
|
648
|
+
] }) : /* @__PURE__ */ jsx(
|
|
649
|
+
CollapsedGongCallPreview,
|
|
650
|
+
{
|
|
651
|
+
display,
|
|
652
|
+
className: cn(classes.collapsedPreview, "cursor-pointer hover:bg-muted/30 transition-colors"),
|
|
653
|
+
actionClassName: cn(classes.actionLink, "shrink-0"),
|
|
654
|
+
onClick: () => setExpanded(true)
|
|
655
|
+
}
|
|
656
|
+
) });
|
|
657
|
+
}
|
|
333
658
|
function EmailCard({
|
|
334
659
|
event,
|
|
335
660
|
expanded,
|
|
@@ -349,14 +674,26 @@ function EmailCard({
|
|
|
349
674
|
),
|
|
350
675
|
onClick: () => !expanded && setExpanded(true),
|
|
351
676
|
children: expanded && event.email ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
352
|
-
/* @__PURE__ */
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
677
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
678
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
|
|
679
|
+
EmailMetadata,
|
|
680
|
+
{
|
|
681
|
+
email: event.email,
|
|
682
|
+
showAllRecipients,
|
|
683
|
+
setShowAllRecipients
|
|
684
|
+
}
|
|
685
|
+
) }),
|
|
686
|
+
/* @__PURE__ */ jsx(
|
|
687
|
+
CollapseTopButton,
|
|
688
|
+
{
|
|
689
|
+
onClick: (e) => {
|
|
690
|
+
e.stopPropagation();
|
|
691
|
+
setExpanded(false);
|
|
692
|
+
},
|
|
693
|
+
className: "mt-0.5"
|
|
694
|
+
}
|
|
695
|
+
)
|
|
696
|
+
] }),
|
|
360
697
|
/* @__PURE__ */ jsx(TimelineEmailBody, { email: event.email }),
|
|
361
698
|
event.content ? /* @__PURE__ */ jsx("div", { className: "rounded-md bg-muted/30 px-2.5 py-2 text-xs text-muted-foreground", children: event.content }) : null,
|
|
362
699
|
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-3", children: [
|
|
@@ -392,14 +729,26 @@ function EmailCard({
|
|
|
392
729
|
) });
|
|
393
730
|
}
|
|
394
731
|
return /* @__PURE__ */ jsx("div", { className: classes.cardContainer, "data-variant": variant, children: expanded && event.email ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
395
|
-
/* @__PURE__ */
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
732
|
+
/* @__PURE__ */ jsxs("div", { className: classes.cardHeader, "data-slot": "timeline-card-header", children: [
|
|
733
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 normal-case tracking-normal", children: /* @__PURE__ */ jsx(
|
|
734
|
+
EmailMetadata,
|
|
735
|
+
{
|
|
736
|
+
email: event.email,
|
|
737
|
+
showAllRecipients,
|
|
738
|
+
setShowAllRecipients
|
|
739
|
+
}
|
|
740
|
+
) }),
|
|
741
|
+
/* @__PURE__ */ jsx(
|
|
742
|
+
CollapseTopButton,
|
|
743
|
+
{
|
|
744
|
+
onClick: (e) => {
|
|
745
|
+
e.stopPropagation();
|
|
746
|
+
setExpanded(false);
|
|
747
|
+
},
|
|
748
|
+
className: "ml-3 normal-case tracking-normal"
|
|
749
|
+
}
|
|
750
|
+
)
|
|
751
|
+
] }),
|
|
403
752
|
/* @__PURE__ */ jsxs("div", { className: classes.cardBody, "data-slot": "timeline-card-body", children: [
|
|
404
753
|
/* @__PURE__ */ jsx(TimelineEmailBody, { email: event.email }),
|
|
405
754
|
event.content ? /* @__PURE__ */ jsx("div", { className: "mt-3 rounded-md bg-muted/30 px-2.5 py-2 text-xs text-muted-foreground", children: event.content }) : null
|