@handled-ai/design-system 0.18.22 → 0.18.24

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.
Files changed (31) hide show
  1. package/dist/components/case-panel-activity-timeline.d.ts +100 -0
  2. package/dist/components/case-panel-activity-timeline.js +270 -0
  3. package/dist/components/case-panel-activity-timeline.js.map +1 -0
  4. package/dist/components/case-panel-detail.d.ts +60 -0
  5. package/dist/components/case-panel-detail.js +129 -0
  6. package/dist/components/case-panel-detail.js.map +1 -0
  7. package/dist/components/case-panel-email-composer.d.ts +61 -0
  8. package/dist/components/case-panel-email-composer.js +304 -0
  9. package/dist/components/case-panel-email-composer.js.map +1 -0
  10. package/dist/components/case-panel-why.d.ts +35 -0
  11. package/dist/components/case-panel-why.js +149 -0
  12. package/dist/components/case-panel-why.js.map +1 -0
  13. package/dist/components/contextual-quick-action-launcher.d.ts +7 -3
  14. package/dist/components/contextual-quick-action-launcher.js +99 -27
  15. package/dist/components/contextual-quick-action-launcher.js.map +1 -1
  16. package/dist/components/pill.d.ts +1 -1
  17. package/dist/index.d.ts +5 -1
  18. package/dist/index.js +4 -0
  19. package/dist/index.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/__tests__/case-panel-activity-timeline.test.tsx +152 -0
  22. package/src/components/__tests__/case-panel-detail.test.tsx +138 -0
  23. package/src/components/__tests__/case-panel-email-composer.test.tsx +171 -0
  24. package/src/components/__tests__/case-panel-why.test.tsx +152 -0
  25. package/src/components/__tests__/contextual-quick-action-launcher.test.tsx +90 -0
  26. package/src/components/case-panel-activity-timeline.tsx +414 -0
  27. package/src/components/case-panel-detail.tsx +228 -0
  28. package/src/components/case-panel-email-composer.tsx +341 -0
  29. package/src/components/case-panel-why.tsx +214 -0
  30. package/src/components/contextual-quick-action-launcher.tsx +92 -15
  31. package/src/index.ts +4 -0
@@ -0,0 +1,100 @@
1
+ import * as React from 'react';
2
+ import { TimelineEventTone } from './timeline-activity.js';
3
+
4
+ type CasePanelActivityTone = TimelineEventTone;
5
+ type CasePanelActivityActor = {
6
+ kind: "system";
7
+ } | {
8
+ kind: "integration";
9
+ name: string;
10
+ iconUrl?: string;
11
+ } | {
12
+ kind: "user";
13
+ name: string;
14
+ avatarUrl?: string;
15
+ verb?: string;
16
+ };
17
+ type CasePanelPayloadAction = {
18
+ kind: "openSignal";
19
+ key: string;
20
+ eventId: string;
21
+ };
22
+ type CasePanelActivityPayload = {
23
+ kind: "signal";
24
+ key: string;
25
+ summary: string;
26
+ detail?: string;
27
+ actionLabel?: string;
28
+ } | {
29
+ kind: "scoreUpdate";
30
+ label?: string;
31
+ previousScore?: number;
32
+ nextScore: number;
33
+ reason?: string;
34
+ } | {
35
+ kind: "recommendation";
36
+ recommendation: string;
37
+ rationale?: string;
38
+ actionLabel?: string;
39
+ } | {
40
+ kind: "email";
41
+ from: string;
42
+ to?: string;
43
+ subject: string;
44
+ preview?: string;
45
+ body?: string;
46
+ } | {
47
+ kind: "salesforce";
48
+ objectLabel: string;
49
+ recordLabel?: string;
50
+ changeSummary: string;
51
+ deepLink?: {
52
+ href: string;
53
+ label?: string;
54
+ };
55
+ } | {
56
+ kind: "deadline";
57
+ dueLabel: string;
58
+ status?: "upcoming" | "due" | "overdue" | "met";
59
+ description?: string;
60
+ } | {
61
+ kind: "operatorNote";
62
+ note: string;
63
+ } | {
64
+ kind: "assignment";
65
+ assignee: string;
66
+ from?: string;
67
+ role?: string;
68
+ } | {
69
+ kind: "caseOpened";
70
+ source?: string;
71
+ openedBy?: string;
72
+ description?: string;
73
+ } | {
74
+ kind: "generic";
75
+ description: string;
76
+ metadata?: Array<{
77
+ label: string;
78
+ value: string;
79
+ }>;
80
+ };
81
+ interface CasePanelActivityEvent {
82
+ id: string;
83
+ title: string;
84
+ timeLabel: string;
85
+ tone: CasePanelActivityTone;
86
+ actor?: CasePanelActivityActor;
87
+ isSystemNoise?: boolean;
88
+ payload: CasePanelActivityPayload;
89
+ }
90
+ interface CasePanelActivityTimelineProps {
91
+ events: CasePanelActivityEvent[];
92
+ className?: string;
93
+ title?: string;
94
+ defaultExpanded?: boolean;
95
+ defaultShowSystemEvents?: boolean;
96
+ onPayloadAction?: (action: CasePanelPayloadAction) => void;
97
+ }
98
+ declare function CasePanelActivityTimeline({ events, className, title, defaultExpanded, defaultShowSystemEvents, onPayloadAction, }: CasePanelActivityTimelineProps): React.JSX.Element;
99
+
100
+ export { type CasePanelActivityActor, type CasePanelActivityEvent, type CasePanelActivityPayload, CasePanelActivityTimeline, type CasePanelActivityTimelineProps, type CasePanelActivityTone, type CasePanelPayloadAction };
@@ -0,0 +1,270 @@
1
+ "use client"
2
+
3
+ "use client";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import * as React from "react";
6
+ import { ChevronDown, ExternalLink } from "lucide-react";
7
+ import { cn } from "../lib/utils.js";
8
+ import { TONE_CLASSES } from "./timeline-activity.js";
9
+ const NEUTRAL_DOT_CLASSES = "bg-background border-border/60";
10
+ const NEUTRAL_ICON_CLASSES = "text-muted-foreground";
11
+ const PAYLOAD_LABELS = {
12
+ signal: "Signal",
13
+ scoreUpdate: "Score update",
14
+ recommendation: "Recommendation",
15
+ email: "Email",
16
+ salesforce: "Salesforce",
17
+ deadline: "Deadline",
18
+ operatorNote: "Operator note",
19
+ assignment: "Assignment",
20
+ caseOpened: "Case opened",
21
+ generic: "Update"
22
+ };
23
+ const STATUS_CLASSES = {
24
+ upcoming: "border-blue-200 bg-blue-50 text-blue-700 dark:border-blue-900/40 dark:bg-blue-950/30 dark:text-blue-300",
25
+ due: "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/40 dark:bg-amber-950/30 dark:text-amber-300",
26
+ overdue: "border-red-200 bg-red-50 text-red-700 dark:border-red-900/40 dark:bg-red-950/30 dark:text-red-300",
27
+ met: "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/40 dark:bg-emerald-950/30 dark:text-emerald-300"
28
+ };
29
+ function CasePanelActivityTimeline({
30
+ events,
31
+ className,
32
+ title = "Activity",
33
+ defaultExpanded = false,
34
+ defaultShowSystemEvents = false,
35
+ onPayloadAction
36
+ }) {
37
+ var _a, _b, _c, _d;
38
+ const [expanded, setExpanded] = React.useState(defaultExpanded);
39
+ const [showSystemEvents, setShowSystemEvents] = React.useState(defaultShowSystemEvents);
40
+ const nonSystemEvents = events.filter((event) => !event.isSystemNoise);
41
+ const visibleEvents = showSystemEvents ? events : nonSystemEvents;
42
+ const systemNoiseCount = events.length - nonSystemEvents.length;
43
+ const lastActivityText = (_d = (_c = (_a = nonSystemEvents[0]) == null ? void 0 : _a.timeLabel) != null ? _c : (_b = events[0]) == null ? void 0 : _b.timeLabel) != null ? _d : "No activity yet";
44
+ return /* @__PURE__ */ jsxs("section", { className: cn("rounded-xl border border-border bg-card text-card-foreground shadow-sm", className), children: [
45
+ /* @__PURE__ */ jsxs(
46
+ "button",
47
+ {
48
+ type: "button",
49
+ className: "flex w-full items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/30",
50
+ "aria-expanded": expanded,
51
+ onClick: () => setExpanded((current) => !current),
52
+ children: [
53
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
54
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
55
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground", children: title }),
56
+ /* @__PURE__ */ jsxs("span", { className: "rounded-full border border-border bg-muted/40 px-2 py-0.5 text-[11px] font-medium text-muted-foreground", children: [
57
+ nonSystemEvents.length,
58
+ " ",
59
+ nonSystemEvents.length === 1 ? "event" : "events"
60
+ ] })
61
+ ] }),
62
+ /* @__PURE__ */ jsxs("span", { className: "mt-1 block truncate text-xs text-muted-foreground", children: [
63
+ "Last activity ",
64
+ lastActivityText
65
+ ] })
66
+ ] }),
67
+ /* @__PURE__ */ jsx(ChevronDown, { className: cn("h-4 w-4 shrink-0 text-muted-foreground transition-transform", expanded && "rotate-180") })
68
+ ]
69
+ }
70
+ ),
71
+ expanded ? /* @__PURE__ */ jsxs("div", { className: "border-t border-border px-4 py-4", children: [
72
+ systemNoiseCount > 0 ? /* @__PURE__ */ jsxs("label", { className: "mb-4 flex items-center justify-between gap-3 rounded-lg border border-border/70 bg-muted/20 px-3 py-2 text-xs text-muted-foreground", children: [
73
+ /* @__PURE__ */ jsx("span", { children: "Show system events" }),
74
+ /* @__PURE__ */ jsx(
75
+ "input",
76
+ {
77
+ type: "checkbox",
78
+ className: "h-4 w-4 rounded border-border text-primary accent-current",
79
+ checked: showSystemEvents,
80
+ onChange: (event) => setShowSystemEvents(event.target.checked)
81
+ }
82
+ )
83
+ ] }) : null,
84
+ visibleEvents.length > 0 ? /* @__PURE__ */ jsx("div", { className: "space-y-0", children: visibleEvents.map((event, index) => /* @__PURE__ */ jsx(
85
+ CasePanelActivityTimelineItem,
86
+ {
87
+ event,
88
+ isLast: index === visibleEvents.length - 1,
89
+ onPayloadAction
90
+ },
91
+ event.id
92
+ )) }) : /* @__PURE__ */ jsx("p", { className: "rounded-lg border border-dashed border-border px-3 py-6 text-center text-sm text-muted-foreground", children: "No activity to show." })
93
+ ] }) : null
94
+ ] });
95
+ }
96
+ function CasePanelActivityTimelineItem({
97
+ event,
98
+ isLast,
99
+ onPayloadAction
100
+ }) {
101
+ const toneStyle = TONE_CLASSES[event.tone];
102
+ const dotClasses = toneStyle ? toneStyle.dot : NEUTRAL_DOT_CLASSES;
103
+ const iconClasses = toneStyle ? toneStyle.icon : NEUTRAL_ICON_CLASSES;
104
+ return /* @__PURE__ */ jsxs("article", { className: "group relative flex gap-3.5", "data-testid": "case-panel-activity-event", children: [
105
+ !isLast ? /* @__PURE__ */ jsx("div", { className: "absolute bottom-[-6px] left-[9px] top-5 w-px bg-border/60" }) : null,
106
+ /* @__PURE__ */ jsx("div", { className: "relative z-10 mt-1 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-card", children: /* @__PURE__ */ jsx(
107
+ "span",
108
+ {
109
+ "aria-hidden": "true",
110
+ className: cn("flex h-4.5 w-4.5 items-center justify-center rounded-full border ring-4 ring-card", dotClasses, iconClasses),
111
+ "data-testid": "case-panel-activity-dot",
112
+ children: /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current" })
113
+ }
114
+ ) }),
115
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 pb-5 pt-0.5", children: [
116
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1 sm:flex-row sm:items-start sm:justify-between", children: [
117
+ /* @__PURE__ */ jsx("h3", { className: "pr-4 text-[13px] font-medium leading-relaxed text-foreground", children: event.title }),
118
+ /* @__PURE__ */ jsx("time", { className: "mt-0.5 shrink-0 whitespace-nowrap text-[11px] text-muted-foreground/70", children: event.timeLabel })
119
+ ] }),
120
+ /* @__PURE__ */ jsx(ActorByline, { actor: event.actor, timeLabel: event.timeLabel }),
121
+ /* @__PURE__ */ jsx(PayloadCard, { event, onPayloadAction })
122
+ ] })
123
+ ] });
124
+ }
125
+ function ActorByline({ actor, timeLabel }) {
126
+ var _a;
127
+ if (!actor || actor.kind === "system") return null;
128
+ if (actor.kind === "integration") {
129
+ return /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-xs text-muted-foreground", "data-testid": "case-panel-activity-byline", children: [
130
+ actor.iconUrl ? /* @__PURE__ */ jsx("img", { src: actor.iconUrl, alt: "", className: "h-4 w-4 rounded-sm object-cover" }) : null,
131
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: actor.name }),
132
+ /* @__PURE__ */ jsx("span", { children: "synced this update" }),
133
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
134
+ /* @__PURE__ */ jsx("span", { children: timeLabel })
135
+ ] });
136
+ }
137
+ const verb = (_a = actor.verb) != null ? _a : "updated this case";
138
+ const initial = actor.name.charAt(0).toUpperCase();
139
+ return /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-xs text-muted-foreground", "data-testid": "case-panel-activity-byline", children: [
140
+ actor.avatarUrl ? /* @__PURE__ */ jsx("img", { src: actor.avatarUrl, alt: actor.name, className: "h-4 w-4 rounded-full object-cover" }) : /* @__PURE__ */ jsx("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-muted-foreground/10 text-[8px] font-semibold text-muted-foreground", children: initial }),
141
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: actor.name }),
142
+ /* @__PURE__ */ jsx("span", { children: verb }),
143
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
144
+ /* @__PURE__ */ jsx("span", { children: timeLabel })
145
+ ] });
146
+ }
147
+ function PayloadCard({
148
+ event,
149
+ onPayloadAction
150
+ }) {
151
+ const payload = event.payload;
152
+ return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded-lg border border-border/80 bg-muted/20 px-3 py-2.5 text-sm", "data-testid": `case-panel-payload-${payload.kind}`, children: [
153
+ /* @__PURE__ */ jsx("div", { className: "mb-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground", children: PAYLOAD_LABELS[payload.kind] }),
154
+ renderPayloadContent(payload, event.id, onPayloadAction)
155
+ ] });
156
+ }
157
+ function renderPayloadContent(payload, eventId, onPayloadAction) {
158
+ var _a, _b, _c;
159
+ switch (payload.kind) {
160
+ case "signal":
161
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
162
+ /* @__PURE__ */ jsx("p", { className: "text-foreground", children: payload.summary }),
163
+ payload.detail ? /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: payload.detail }) : null,
164
+ onPayloadAction ? /* @__PURE__ */ jsx(
165
+ "button",
166
+ {
167
+ type: "button",
168
+ className: "inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground transition-colors hover:text-foreground",
169
+ onClick: () => onPayloadAction({ kind: "openSignal", key: payload.key, eventId }),
170
+ children: (_a = payload.actionLabel) != null ? _a : "Open signal"
171
+ }
172
+ ) : null
173
+ ] });
174
+ case "scoreUpdate":
175
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
176
+ /* @__PURE__ */ jsxs("p", { className: "text-foreground", children: [
177
+ (_b = payload.label) != null ? _b : "Score",
178
+ ": ",
179
+ payload.previousScore !== void 0 ? `${payload.previousScore} \u2192 ` : "",
180
+ payload.nextScore
181
+ ] }),
182
+ payload.reason ? /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: payload.reason }) : null
183
+ ] });
184
+ case "recommendation":
185
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
186
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-foreground", children: payload.recommendation }),
187
+ payload.rationale ? /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: payload.rationale }) : null,
188
+ payload.actionLabel ? /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground", children: payload.actionLabel }) : null
189
+ ] });
190
+ case "email":
191
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
192
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-foreground", children: payload.subject }),
193
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
194
+ "From ",
195
+ payload.from,
196
+ payload.to ? ` to ${payload.to}` : ""
197
+ ] }),
198
+ payload.preview ? /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground/90", children: payload.preview }) : null,
199
+ payload.body ? /* @__PURE__ */ jsx("p", { className: "whitespace-pre-line text-xs leading-relaxed text-muted-foreground", children: payload.body }) : null
200
+ ] });
201
+ case "salesforce":
202
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
203
+ /* @__PURE__ */ jsxs("p", { className: "text-foreground", children: [
204
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: payload.objectLabel }),
205
+ payload.recordLabel ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
206
+ " \xB7 ",
207
+ payload.recordLabel
208
+ ] }) : null
209
+ ] }),
210
+ /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: payload.changeSummary }),
211
+ payload.deepLink ? /* @__PURE__ */ jsxs(
212
+ "a",
213
+ {
214
+ href: payload.deepLink.href,
215
+ target: "_blank",
216
+ rel: "noreferrer noopener",
217
+ className: "inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground transition-colors hover:text-foreground",
218
+ children: [
219
+ (_c = payload.deepLink.label) != null ? _c : "Open in Salesforce",
220
+ /* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" })
221
+ ]
222
+ }
223
+ ) : null
224
+ ] });
225
+ case "deadline":
226
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
227
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
228
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: payload.dueLabel }),
229
+ payload.status ? /* @__PURE__ */ jsx("span", { className: cn("rounded-full border px-2 py-0.5 text-[11px] font-medium", STATUS_CLASSES[payload.status]), children: payload.status }) : null
230
+ ] }),
231
+ payload.description ? /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: payload.description }) : null
232
+ ] });
233
+ case "operatorNote":
234
+ return /* @__PURE__ */ jsx("p", { className: "whitespace-pre-line text-sm leading-relaxed text-foreground", children: payload.note });
235
+ case "assignment":
236
+ return /* @__PURE__ */ jsxs("p", { className: "text-foreground", children: [
237
+ "Assigned to ",
238
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: payload.assignee }),
239
+ payload.role ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
240
+ " as ",
241
+ payload.role
242
+ ] }) : null,
243
+ payload.from ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
244
+ " from ",
245
+ payload.from
246
+ ] }) : null
247
+ ] });
248
+ case "caseOpened":
249
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
250
+ /* @__PURE__ */ jsxs("p", { className: "text-foreground", children: [
251
+ "Case opened",
252
+ payload.openedBy ? ` by ${payload.openedBy}` : "",
253
+ payload.source ? ` from ${payload.source}` : ""
254
+ ] }),
255
+ payload.description ? /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: payload.description }) : null
256
+ ] });
257
+ case "generic":
258
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
259
+ /* @__PURE__ */ jsx("p", { className: "text-foreground", children: payload.description }),
260
+ payload.metadata && payload.metadata.length > 0 ? /* @__PURE__ */ jsx("dl", { className: "grid gap-1 text-xs text-muted-foreground", children: payload.metadata.map((item) => /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
261
+ /* @__PURE__ */ jsx("dt", { className: "font-medium text-foreground", children: item.label }),
262
+ /* @__PURE__ */ jsx("dd", { children: item.value })
263
+ ] }, `${item.label}-${item.value}`)) }) : null
264
+ ] });
265
+ }
266
+ }
267
+ export {
268
+ CasePanelActivityTimeline
269
+ };
270
+ //# sourceMappingURL=case-panel-activity-timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/case-panel-activity-timeline.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronDown, ExternalLink } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\nimport { TONE_CLASSES, type TimelineEventTone } from \"./timeline-activity\"\n\nexport type CasePanelActivityTone = TimelineEventTone\n\nexport type CasePanelActivityActor =\n | { kind: \"system\" }\n | { kind: \"integration\"; name: string; iconUrl?: string }\n | { kind: \"user\"; name: string; avatarUrl?: string; verb?: string }\n\nexport type CasePanelPayloadAction = {\n kind: \"openSignal\"\n key: string\n eventId: string\n}\n\nexport type CasePanelActivityPayload =\n | {\n kind: \"signal\"\n key: string\n summary: string\n detail?: string\n actionLabel?: string\n }\n | {\n kind: \"scoreUpdate\"\n label?: string\n previousScore?: number\n nextScore: number\n reason?: string\n }\n | {\n kind: \"recommendation\"\n recommendation: string\n rationale?: string\n actionLabel?: string\n }\n | {\n kind: \"email\"\n from: string\n to?: string\n subject: string\n preview?: string\n body?: string\n }\n | {\n kind: \"salesforce\"\n objectLabel: string\n recordLabel?: string\n changeSummary: string\n deepLink?: {\n href: string\n label?: string\n }\n }\n | {\n kind: \"deadline\"\n dueLabel: string\n status?: \"upcoming\" | \"due\" | \"overdue\" | \"met\"\n description?: string\n }\n | {\n kind: \"operatorNote\"\n note: string\n }\n | {\n kind: \"assignment\"\n assignee: string\n from?: string\n role?: string\n }\n | {\n kind: \"caseOpened\"\n source?: string\n openedBy?: string\n description?: string\n }\n | {\n kind: \"generic\"\n description: string\n metadata?: Array<{ label: string; value: string }>\n }\n\nexport interface CasePanelActivityEvent {\n id: string\n title: string\n timeLabel: string\n tone: CasePanelActivityTone\n actor?: CasePanelActivityActor\n isSystemNoise?: boolean\n payload: CasePanelActivityPayload\n}\n\nexport interface CasePanelActivityTimelineProps {\n events: CasePanelActivityEvent[]\n className?: string\n title?: string\n defaultExpanded?: boolean\n defaultShowSystemEvents?: boolean\n onPayloadAction?: (action: CasePanelPayloadAction) => void\n}\n\nconst NEUTRAL_DOT_CLASSES = \"bg-background border-border/60\"\nconst NEUTRAL_ICON_CLASSES = \"text-muted-foreground\"\n\nconst PAYLOAD_LABELS: Record<CasePanelActivityPayload[\"kind\"], string> = {\n signal: \"Signal\",\n scoreUpdate: \"Score update\",\n recommendation: \"Recommendation\",\n email: \"Email\",\n salesforce: \"Salesforce\",\n deadline: \"Deadline\",\n operatorNote: \"Operator note\",\n assignment: \"Assignment\",\n caseOpened: \"Case opened\",\n generic: \"Update\",\n}\n\nconst STATUS_CLASSES: Record<NonNullable<Extract<CasePanelActivityPayload, { kind: \"deadline\" }>[\"status\"]>, string> = {\n upcoming: \"border-blue-200 bg-blue-50 text-blue-700 dark:border-blue-900/40 dark:bg-blue-950/30 dark:text-blue-300\",\n due: \"border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/40 dark:bg-amber-950/30 dark:text-amber-300\",\n overdue: \"border-red-200 bg-red-50 text-red-700 dark:border-red-900/40 dark:bg-red-950/30 dark:text-red-300\",\n met: \"border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/40 dark:bg-emerald-950/30 dark:text-emerald-300\",\n}\n\nexport function CasePanelActivityTimeline({\n events,\n className,\n title = \"Activity\",\n defaultExpanded = false,\n defaultShowSystemEvents = false,\n onPayloadAction,\n}: CasePanelActivityTimelineProps) {\n const [expanded, setExpanded] = React.useState(defaultExpanded)\n const [showSystemEvents, setShowSystemEvents] = React.useState(defaultShowSystemEvents)\n\n const nonSystemEvents = events.filter((event) => !event.isSystemNoise)\n const visibleEvents = showSystemEvents ? events : nonSystemEvents\n const systemNoiseCount = events.length - nonSystemEvents.length\n const lastActivityText = nonSystemEvents[0]?.timeLabel ?? events[0]?.timeLabel ?? \"No activity yet\"\n\n return (\n <section className={cn(\"rounded-xl border border-border bg-card text-card-foreground shadow-sm\", className)}>\n <button\n type=\"button\"\n className=\"flex w-full items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/30\"\n aria-expanded={expanded}\n onClick={() => setExpanded((current) => !current)}\n >\n <span className=\"min-w-0\">\n <span className=\"flex items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n <span className=\"rounded-full border border-border bg-muted/40 px-2 py-0.5 text-[11px] font-medium text-muted-foreground\">\n {nonSystemEvents.length} {nonSystemEvents.length === 1 ? \"event\" : \"events\"}\n </span>\n </span>\n <span className=\"mt-1 block truncate text-xs text-muted-foreground\">Last activity {lastActivityText}</span>\n </span>\n <ChevronDown className={cn(\"h-4 w-4 shrink-0 text-muted-foreground transition-transform\", expanded && \"rotate-180\")} />\n </button>\n\n {expanded ? (\n <div className=\"border-t border-border px-4 py-4\">\n {systemNoiseCount > 0 ? (\n <label className=\"mb-4 flex items-center justify-between gap-3 rounded-lg border border-border/70 bg-muted/20 px-3 py-2 text-xs text-muted-foreground\">\n <span>Show system events</span>\n <input\n type=\"checkbox\"\n className=\"h-4 w-4 rounded border-border text-primary accent-current\"\n checked={showSystemEvents}\n onChange={(event) => setShowSystemEvents(event.target.checked)}\n />\n </label>\n ) : null}\n\n {visibleEvents.length > 0 ? (\n <div className=\"space-y-0\">\n {visibleEvents.map((event, index) => (\n <CasePanelActivityTimelineItem\n key={event.id}\n event={event}\n isLast={index === visibleEvents.length - 1}\n onPayloadAction={onPayloadAction}\n />\n ))}\n </div>\n ) : (\n <p className=\"rounded-lg border border-dashed border-border px-3 py-6 text-center text-sm text-muted-foreground\">\n No activity to show.\n </p>\n )}\n </div>\n ) : null}\n </section>\n )\n}\n\nfunction CasePanelActivityTimelineItem({\n event,\n isLast,\n onPayloadAction,\n}: {\n event: CasePanelActivityEvent\n isLast: boolean\n onPayloadAction?: (action: CasePanelPayloadAction) => void\n}) {\n const toneStyle = TONE_CLASSES[event.tone]\n const dotClasses = toneStyle ? toneStyle.dot : NEUTRAL_DOT_CLASSES\n const iconClasses = toneStyle ? toneStyle.icon : NEUTRAL_ICON_CLASSES\n\n return (\n <article className=\"group relative flex gap-3.5\" data-testid=\"case-panel-activity-event\">\n {!isLast ? <div className=\"absolute bottom-[-6px] left-[9px] top-5 w-px bg-border/60\" /> : null}\n <div className=\"relative z-10 mt-1 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-card\">\n <span\n aria-hidden=\"true\"\n className={cn(\"flex h-4.5 w-4.5 items-center justify-center rounded-full border ring-4 ring-card\", dotClasses, iconClasses)}\n data-testid=\"case-panel-activity-dot\"\n >\n <span className=\"h-1.5 w-1.5 rounded-full bg-current\" />\n </span>\n </div>\n <div className=\"min-w-0 flex-1 pb-5 pt-0.5\">\n <div className=\"flex min-w-0 flex-col gap-1 sm:flex-row sm:items-start sm:justify-between\">\n <h3 className=\"pr-4 text-[13px] font-medium leading-relaxed text-foreground\">{event.title}</h3>\n <time className=\"mt-0.5 shrink-0 whitespace-nowrap text-[11px] text-muted-foreground/70\">{event.timeLabel}</time>\n </div>\n <ActorByline actor={event.actor} timeLabel={event.timeLabel} />\n <PayloadCard event={event} onPayloadAction={onPayloadAction} />\n </div>\n </article>\n )\n}\n\nfunction ActorByline({ actor, timeLabel }: { actor?: CasePanelActivityActor; timeLabel: string }) {\n if (!actor || actor.kind === \"system\") return null\n\n if (actor.kind === \"integration\") {\n return (\n <div className=\"mt-1 flex items-center gap-1.5 text-xs text-muted-foreground\" data-testid=\"case-panel-activity-byline\">\n {actor.iconUrl ? <img src={actor.iconUrl} alt=\"\" className=\"h-4 w-4 rounded-sm object-cover\" /> : null}\n <span className=\"font-medium text-foreground\">{actor.name}</span>\n <span>synced this update</span>\n <span className=\"text-muted-foreground/40\">&middot;</span>\n <span>{timeLabel}</span>\n </div>\n )\n }\n\n const verb = actor.verb ?? \"updated this case\"\n const initial = actor.name.charAt(0).toUpperCase()\n\n return (\n <div className=\"mt-1 flex items-center gap-1.5 text-xs text-muted-foreground\" data-testid=\"case-panel-activity-byline\">\n {actor.avatarUrl ? (\n <img src={actor.avatarUrl} alt={actor.name} className=\"h-4 w-4 rounded-full object-cover\" />\n ) : (\n <span className=\"flex h-4 w-4 items-center justify-center rounded-full bg-muted-foreground/10 text-[8px] font-semibold text-muted-foreground\">\n {initial}\n </span>\n )}\n <span className=\"font-medium text-foreground\">{actor.name}</span>\n <span>{verb}</span>\n <span className=\"text-muted-foreground/40\">&middot;</span>\n <span>{timeLabel}</span>\n </div>\n )\n}\n\nfunction PayloadCard({\n event,\n onPayloadAction,\n}: {\n event: CasePanelActivityEvent\n onPayloadAction?: (action: CasePanelPayloadAction) => void\n}) {\n const payload = event.payload\n\n return (\n <div className=\"mt-2 rounded-lg border border-border/80 bg-muted/20 px-3 py-2.5 text-sm\" data-testid={`case-panel-payload-${payload.kind}`}>\n <div className=\"mb-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground\">\n {PAYLOAD_LABELS[payload.kind]}\n </div>\n {renderPayloadContent(payload, event.id, onPayloadAction)}\n </div>\n )\n}\n\nfunction renderPayloadContent(\n payload: CasePanelActivityPayload,\n eventId: string,\n onPayloadAction?: (action: CasePanelPayloadAction) => void\n) {\n switch (payload.kind) {\n case \"signal\":\n return (\n <div className=\"space-y-2\">\n <p className=\"text-foreground\">{payload.summary}</p>\n {payload.detail ? <p className=\"text-xs leading-relaxed text-muted-foreground\">{payload.detail}</p> : null}\n {onPayloadAction ? (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground transition-colors hover:text-foreground\"\n onClick={() => onPayloadAction({ kind: \"openSignal\", key: payload.key, eventId })}\n >\n {payload.actionLabel ?? \"Open signal\"}\n </button>\n ) : null}\n </div>\n )\n case \"scoreUpdate\":\n return (\n <div className=\"space-y-1\">\n <p className=\"text-foreground\">\n {payload.label ?? \"Score\"}: {payload.previousScore !== undefined ? `${payload.previousScore} → ` : \"\"}{payload.nextScore}\n </p>\n {payload.reason ? <p className=\"text-xs leading-relaxed text-muted-foreground\">{payload.reason}</p> : null}\n </div>\n )\n case \"recommendation\":\n return (\n <div className=\"space-y-1\">\n <p className=\"font-medium text-foreground\">{payload.recommendation}</p>\n {payload.rationale ? <p className=\"text-xs leading-relaxed text-muted-foreground\">{payload.rationale}</p> : null}\n {payload.actionLabel ? <p className=\"text-xs font-medium text-muted-foreground\">{payload.actionLabel}</p> : null}\n </div>\n )\n case \"email\":\n return (\n <div className=\"space-y-1\">\n <p className=\"font-medium text-foreground\">{payload.subject}</p>\n <p className=\"text-xs text-muted-foreground\">\n From {payload.from}{payload.to ? ` to ${payload.to}` : \"\"}\n </p>\n {payload.preview ? <p className=\"text-sm text-foreground/90\">{payload.preview}</p> : null}\n {payload.body ? <p className=\"whitespace-pre-line text-xs leading-relaxed text-muted-foreground\">{payload.body}</p> : null}\n </div>\n )\n case \"salesforce\":\n return (\n <div className=\"space-y-2\">\n <p className=\"text-foreground\">\n <span className=\"font-medium\">{payload.objectLabel}</span>\n {payload.recordLabel ? <span className=\"text-muted-foreground\"> · {payload.recordLabel}</span> : null}\n </p>\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{payload.changeSummary}</p>\n {payload.deepLink ? (\n <a\n href={payload.deepLink.href}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"inline-flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground transition-colors hover:text-foreground\"\n >\n {payload.deepLink.label ?? \"Open in Salesforce\"}\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n ) : null}\n </div>\n )\n case \"deadline\":\n return (\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium text-foreground\">{payload.dueLabel}</span>\n {payload.status ? (\n <span className={cn(\"rounded-full border px-2 py-0.5 text-[11px] font-medium\", STATUS_CLASSES[payload.status])}>\n {payload.status}\n </span>\n ) : null}\n </div>\n {payload.description ? <p className=\"text-xs leading-relaxed text-muted-foreground\">{payload.description}</p> : null}\n </div>\n )\n case \"operatorNote\":\n return <p className=\"whitespace-pre-line text-sm leading-relaxed text-foreground\">{payload.note}</p>\n case \"assignment\":\n return (\n <p className=\"text-foreground\">\n Assigned to <span className=\"font-medium\">{payload.assignee}</span>\n {payload.role ? <span className=\"text-muted-foreground\"> as {payload.role}</span> : null}\n {payload.from ? <span className=\"text-muted-foreground\"> from {payload.from}</span> : null}\n </p>\n )\n case \"caseOpened\":\n return (\n <div className=\"space-y-1\">\n <p className=\"text-foreground\">\n Case opened{payload.openedBy ? ` by ${payload.openedBy}` : \"\"}{payload.source ? ` from ${payload.source}` : \"\"}\n </p>\n {payload.description ? <p className=\"text-xs leading-relaxed text-muted-foreground\">{payload.description}</p> : null}\n </div>\n )\n case \"generic\":\n return (\n <div className=\"space-y-2\">\n <p className=\"text-foreground\">{payload.description}</p>\n {payload.metadata && payload.metadata.length > 0 ? (\n <dl className=\"grid gap-1 text-xs text-muted-foreground\">\n {payload.metadata.map((item) => (\n <div key={`${item.label}-${item.value}`} className=\"flex gap-2\">\n <dt className=\"font-medium text-foreground\">{item.label}</dt>\n <dd>{item.value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n </div>\n )\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+
3
+ type CasePanelDetailWidth = "comfortable" | "modest" | "full";
4
+ interface CasePanelDetailProps {
5
+ children: React.ReactNode;
6
+ /** Reading measure for the detail content column. Defaults to the handoff's comfortable 880px measure. */
7
+ width?: CasePanelDetailWidth;
8
+ /** Accessible label for the detail region. */
9
+ "aria-label"?: string;
10
+ className?: string;
11
+ }
12
+ declare function CasePanelDetail({ children, width, "aria-label": ariaLabel, className, }: CasePanelDetailProps): React.JSX.Element;
13
+ interface CasePanelHeaderProps {
14
+ title: React.ReactNode;
15
+ /** Optional action, usually a Quick action trigger. */
16
+ action?: React.ReactNode;
17
+ children?: React.ReactNode;
18
+ className?: string;
19
+ }
20
+ declare function CasePanelHeader({ title, action, children, className, }: CasePanelHeaderProps): React.JSX.Element;
21
+ interface CasePanelIdentityLink {
22
+ id: string;
23
+ label: string;
24
+ href?: string;
25
+ icon?: React.ReactNode;
26
+ kind?: "icon" | "text";
27
+ disabled?: boolean;
28
+ }
29
+ interface CasePanelIdentitySublineProps {
30
+ callsign: string;
31
+ links?: CasePanelIdentityLink[];
32
+ onCopyCallsign?: (callsign: string) => void;
33
+ copyLabel?: string;
34
+ copiedLabel?: string;
35
+ className?: string;
36
+ }
37
+ declare function CasePanelIdentitySubline({ callsign, links, onCopyCallsign, copyLabel, copiedLabel, className, }: CasePanelIdentitySublineProps): React.JSX.Element;
38
+ interface CasePanelSignalBriefProps {
39
+ children: React.ReactNode;
40
+ label?: string;
41
+ className?: string;
42
+ }
43
+ declare function CasePanelSignalBrief({ children, label, className, }: CasePanelSignalBriefProps): React.JSX.Element;
44
+ interface CasePanelMetadataRowProps {
45
+ children: React.ReactNode;
46
+ label?: string;
47
+ className?: string;
48
+ }
49
+ declare function CasePanelMetadataRow({ children, label, className, }: CasePanelMetadataRowProps): React.JSX.Element;
50
+ interface CasePanelDetailSlotsProps {
51
+ why?: React.ReactNode;
52
+ actions?: React.ReactNode;
53
+ opportunity?: React.ReactNode;
54
+ timeline?: React.ReactNode;
55
+ playPanel?: React.ReactNode;
56
+ className?: string;
57
+ }
58
+ declare function CasePanelDetailSlots({ why, actions, opportunity, timeline, playPanel, className, }: CasePanelDetailSlotsProps): React.JSX.Element;
59
+
60
+ export { CasePanelDetail, type CasePanelDetailProps, CasePanelDetailSlots, type CasePanelDetailSlotsProps, type CasePanelDetailWidth, CasePanelHeader, type CasePanelHeaderProps, type CasePanelIdentityLink, CasePanelIdentitySubline, type CasePanelIdentitySublineProps, CasePanelMetadataRow, type CasePanelMetadataRowProps, CasePanelSignalBrief, type CasePanelSignalBriefProps };
@@ -0,0 +1,129 @@
1
+ "use client"
2
+
3
+ "use client";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import * as React from "react";
6
+ import {
7
+ ArrowUpRight,
8
+ Check,
9
+ Copy,
10
+ ExternalLink
11
+ } from "lucide-react";
12
+ import { cn } from "../lib/utils.js";
13
+ const detailWidthClasses = {
14
+ comfortable: "mx-auto w-full max-w-[880px] px-10 pb-[120px] pt-8",
15
+ modest: "mx-auto w-full max-w-[720px] px-8 pb-[112px] pt-7",
16
+ full: "w-full px-8 pb-[120px] pt-8"
17
+ };
18
+ function CasePanelDetail({
19
+ children,
20
+ width = "comfortable",
21
+ "aria-label": ariaLabel = "Case detail",
22
+ className
23
+ }) {
24
+ return /* @__PURE__ */ jsx("section", { "aria-label": ariaLabel, className: cn("min-w-0 bg-background", className), children: /* @__PURE__ */ jsx("div", { className: detailWidthClasses[width], children }) });
25
+ }
26
+ function CasePanelHeader({
27
+ title,
28
+ action,
29
+ children,
30
+ className
31
+ }) {
32
+ return /* @__PURE__ */ jsx("header", { className: cn("mb-7", className), children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-5", children: [
33
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
34
+ /* @__PURE__ */ jsx("h1", { className: "m-0 text-[27px] font-bold leading-[1.18] tracking-[-0.02em] text-foreground [text-wrap:balance]", children: title }),
35
+ children
36
+ ] }),
37
+ action ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: action }) : null
38
+ ] }) });
39
+ }
40
+ function CasePanelIdentitySubline({
41
+ callsign,
42
+ links = [],
43
+ onCopyCallsign,
44
+ copyLabel = "Copy call sign",
45
+ copiedLabel = "Call sign copied",
46
+ className
47
+ }) {
48
+ const [copied, setCopied] = React.useState(false);
49
+ const normalizedCallsign = callsign.startsWith("@") ? callsign : `@${callsign}`;
50
+ const handleCopy = React.useCallback(() => {
51
+ onCopyCallsign == null ? void 0 : onCopyCallsign(normalizedCallsign);
52
+ setCopied(true);
53
+ window.setTimeout(() => setCopied(false), 1400);
54
+ }, [normalizedCallsign, onCopyCallsign]);
55
+ return /* @__PURE__ */ jsxs("div", { className: cn("mt-[9px] inline-flex flex-wrap items-center gap-[7px] text-[13px] text-muted-foreground", className), children: [
56
+ /* @__PURE__ */ jsx("span", { className: "font-mono font-medium tracking-[0.01em] text-gray-700", children: normalizedCallsign }),
57
+ /* @__PURE__ */ jsx(
58
+ "button",
59
+ {
60
+ type: "button",
61
+ onClick: handleCopy,
62
+ "aria-label": copied ? copiedLabel : copyLabel,
63
+ className: "inline-flex h-[22px] w-[22px] items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-accent hover:text-foreground",
64
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "h-[13px] w-[13px] text-emerald-700", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Copy, { className: "h-[13px] w-[13px]", "aria-hidden": "true" })
65
+ }
66
+ ),
67
+ links.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
68
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "mx-[3px] h-3.5 w-px bg-gray-200" }),
69
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1.5", children: links.map((link) => /* @__PURE__ */ jsx(CasePanelIdentityLinkButton, { link }, link.id)) })
70
+ ] }) : null
71
+ ] });
72
+ }
73
+ function CasePanelIdentityLinkButton({ link }) {
74
+ var _a;
75
+ const disabled = link.disabled || !link.href;
76
+ const iconOnly = link.kind === "icon";
77
+ const content = iconOnly ? /* @__PURE__ */ jsx(Fragment, { children: (_a = link.icon) != null ? _a : /* @__PURE__ */ jsx(ExternalLink, { className: "h-[13px] w-[13px]", "aria-hidden": "true" }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
78
+ link.icon ? /* @__PURE__ */ jsx("span", { className: "inline-flex h-3.5 w-3.5 items-center justify-center", children: link.icon }) : null,
79
+ /* @__PURE__ */ jsx("span", { children: link.label }),
80
+ /* @__PURE__ */ jsx(ArrowUpRight, { className: "h-[11px] w-[11px] text-gray-400", "aria-hidden": "true" })
81
+ ] });
82
+ const className = iconOnly ? "inline-flex h-[26px] w-[26px] items-center justify-center rounded-[7px] border border-border bg-background text-foreground shadow-[0_1px_1.5px_rgba(0,0,0,0.03)] transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-45" : "inline-flex h-[26px] items-center gap-1.5 rounded-[7px] border border-border bg-background px-2 text-xs font-medium text-foreground shadow-[0_1px_1.5px_rgba(0,0,0,0.03)] transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-45";
83
+ if (disabled) {
84
+ return /* @__PURE__ */ jsx("button", { type: "button", disabled: true, "aria-label": link.label, className, children: content });
85
+ }
86
+ return /* @__PURE__ */ jsx("a", { href: link.href, "aria-label": link.label, className, children: content });
87
+ }
88
+ function CasePanelSignalBrief({
89
+ children,
90
+ label = "Signal brief",
91
+ className
92
+ }) {
93
+ return /* @__PURE__ */ jsxs("section", { className: cn("mt-7", className), "aria-labelledby": "case-panel-signal-brief-heading", children: [
94
+ /* @__PURE__ */ jsx("div", { id: "case-panel-signal-brief-heading", className: "mb-2.5 text-[11px] font-semibold uppercase tracking-[0.07em] text-muted-foreground", children: label }),
95
+ /* @__PURE__ */ jsx("div", { className: "text-base leading-[1.6] text-foreground [text-wrap:pretty]", children })
96
+ ] });
97
+ }
98
+ function CasePanelMetadataRow({
99
+ children,
100
+ label = "Case metadata",
101
+ className
102
+ }) {
103
+ return /* @__PURE__ */ jsx("div", { "aria-label": label, className: cn("mt-[18px] flex flex-wrap items-center gap-2", className), children });
104
+ }
105
+ function CasePanelDetailSlots({
106
+ why,
107
+ actions,
108
+ opportunity,
109
+ timeline,
110
+ playPanel,
111
+ className
112
+ }) {
113
+ return /* @__PURE__ */ jsxs("div", { className: cn("mt-7 space-y-6", className), children: [
114
+ why ? /* @__PURE__ */ jsx("div", { "data-slot": "why", children: why }) : null,
115
+ actions ? /* @__PURE__ */ jsx("div", { "data-slot": "actions", children: actions }) : null,
116
+ opportunity ? /* @__PURE__ */ jsx("div", { "data-slot": "opportunity", children: opportunity }) : null,
117
+ timeline ? /* @__PURE__ */ jsx("div", { "data-slot": "timeline", children: timeline }) : null,
118
+ playPanel ? /* @__PURE__ */ jsx("div", { "data-slot": "play-panel", children: playPanel }) : null
119
+ ] });
120
+ }
121
+ export {
122
+ CasePanelDetail,
123
+ CasePanelDetailSlots,
124
+ CasePanelHeader,
125
+ CasePanelIdentitySubline,
126
+ CasePanelMetadataRow,
127
+ CasePanelSignalBrief
128
+ };
129
+ //# sourceMappingURL=case-panel-detail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/case-panel-detail.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport {\n ArrowUpRight,\n Check,\n Copy,\n ExternalLink,\n} from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nexport type CasePanelDetailWidth = \"comfortable\" | \"modest\" | \"full\"\n\nexport interface CasePanelDetailProps {\n children: React.ReactNode\n /** Reading measure for the detail content column. Defaults to the handoff's comfortable 880px measure. */\n width?: CasePanelDetailWidth\n /** Accessible label for the detail region. */\n \"aria-label\"?: string\n className?: string\n}\n\nconst detailWidthClasses: Record<CasePanelDetailWidth, string> = {\n comfortable: \"mx-auto w-full max-w-[880px] px-10 pb-[120px] pt-8\",\n modest: \"mx-auto w-full max-w-[720px] px-8 pb-[112px] pt-7\",\n full: \"w-full px-8 pb-[120px] pt-8\",\n}\n\nexport function CasePanelDetail({\n children,\n width = \"comfortable\",\n \"aria-label\": ariaLabel = \"Case detail\",\n className,\n}: CasePanelDetailProps) {\n return (\n <section aria-label={ariaLabel} className={cn(\"min-w-0 bg-background\", className)}>\n <div className={detailWidthClasses[width]}>{children}</div>\n </section>\n )\n}\n\nexport interface CasePanelHeaderProps {\n title: React.ReactNode\n /** Optional action, usually a Quick action trigger. */\n action?: React.ReactNode\n children?: React.ReactNode\n className?: string\n}\n\nexport function CasePanelHeader({\n title,\n action,\n children,\n className,\n}: CasePanelHeaderProps) {\n return (\n <header className={cn(\"mb-7\", className)}>\n <div className=\"flex items-start justify-between gap-5\">\n <div className=\"min-w-0 flex-1\">\n <h1 className=\"m-0 text-[27px] font-bold leading-[1.18] tracking-[-0.02em] text-foreground [text-wrap:balance]\">\n {title}\n </h1>\n {children}\n </div>\n {action ? <div className=\"flex shrink-0 items-center gap-2\">{action}</div> : null}\n </div>\n </header>\n )\n}\n\nexport interface CasePanelIdentityLink {\n id: string\n label: string\n href?: string\n icon?: React.ReactNode\n kind?: \"icon\" | \"text\"\n disabled?: boolean\n}\n\nexport interface CasePanelIdentitySublineProps {\n callsign: string\n links?: CasePanelIdentityLink[]\n onCopyCallsign?: (callsign: string) => void\n copyLabel?: string\n copiedLabel?: string\n className?: string\n}\n\nexport function CasePanelIdentitySubline({\n callsign,\n links = [],\n onCopyCallsign,\n copyLabel = \"Copy call sign\",\n copiedLabel = \"Call sign copied\",\n className,\n}: CasePanelIdentitySublineProps) {\n const [copied, setCopied] = React.useState(false)\n const normalizedCallsign = callsign.startsWith(\"@\") ? callsign : `@${callsign}`\n\n const handleCopy = React.useCallback(() => {\n onCopyCallsign?.(normalizedCallsign)\n setCopied(true)\n window.setTimeout(() => setCopied(false), 1400)\n }, [normalizedCallsign, onCopyCallsign])\n\n return (\n <div className={cn(\"mt-[9px] inline-flex flex-wrap items-center gap-[7px] text-[13px] text-muted-foreground\", className)}>\n <span className=\"font-mono font-medium tracking-[0.01em] text-gray-700\">{normalizedCallsign}</span>\n <button\n type=\"button\"\n onClick={handleCopy}\n aria-label={copied ? copiedLabel : copyLabel}\n className=\"inline-flex h-[22px] w-[22px] items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-accent hover:text-foreground\"\n >\n {copied ? <Check className=\"h-[13px] w-[13px] text-emerald-700\" aria-hidden=\"true\" /> : <Copy className=\"h-[13px] w-[13px]\" aria-hidden=\"true\" />}\n </button>\n {links.length > 0 ? (\n <>\n <span aria-hidden=\"true\" className=\"mx-[3px] h-3.5 w-px bg-gray-200\" />\n <span className=\"inline-flex items-center gap-1.5\">\n {links.map((link) => (\n <CasePanelIdentityLinkButton key={link.id} link={link} />\n ))}\n </span>\n </>\n ) : null}\n </div>\n )\n}\n\nfunction CasePanelIdentityLinkButton({ link }: { link: CasePanelIdentityLink }) {\n const disabled = link.disabled || !link.href\n const iconOnly = link.kind === \"icon\"\n const content = iconOnly ? (\n <>{link.icon ?? <ExternalLink className=\"h-[13px] w-[13px]\" aria-hidden=\"true\" />}</>\n ) : (\n <>\n {link.icon ? <span className=\"inline-flex h-3.5 w-3.5 items-center justify-center\">{link.icon}</span> : null}\n <span>{link.label}</span>\n <ArrowUpRight className=\"h-[11px] w-[11px] text-gray-400\" aria-hidden=\"true\" />\n </>\n )\n\n const className = iconOnly\n ? \"inline-flex h-[26px] w-[26px] items-center justify-center rounded-[7px] border border-border bg-background text-foreground shadow-[0_1px_1.5px_rgba(0,0,0,0.03)] transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-45\"\n : \"inline-flex h-[26px] items-center gap-1.5 rounded-[7px] border border-border bg-background px-2 text-xs font-medium text-foreground shadow-[0_1px_1.5px_rgba(0,0,0,0.03)] transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-45\"\n\n if (disabled) {\n return (\n <button type=\"button\" disabled aria-label={link.label} className={className}>\n {content}\n </button>\n )\n }\n\n return (\n <a href={link.href} aria-label={link.label} className={className}>\n {content}\n </a>\n )\n}\n\nexport interface CasePanelSignalBriefProps {\n children: React.ReactNode\n label?: string\n className?: string\n}\n\nexport function CasePanelSignalBrief({\n children,\n label = \"Signal brief\",\n className,\n}: CasePanelSignalBriefProps) {\n return (\n <section className={cn(\"mt-7\", className)} aria-labelledby=\"case-panel-signal-brief-heading\">\n <div id=\"case-panel-signal-brief-heading\" className=\"mb-2.5 text-[11px] font-semibold uppercase tracking-[0.07em] text-muted-foreground\">\n {label}\n </div>\n <div className=\"text-base leading-[1.6] text-foreground [text-wrap:pretty]\">{children}</div>\n </section>\n )\n}\n\nexport interface CasePanelMetadataRowProps {\n children: React.ReactNode\n label?: string\n className?: string\n}\n\nexport function CasePanelMetadataRow({\n children,\n label = \"Case metadata\",\n className,\n}: CasePanelMetadataRowProps) {\n return (\n <div aria-label={label} className={cn(\"mt-[18px] flex flex-wrap items-center gap-2\", className)}>\n {children}\n </div>\n )\n}\n\nexport interface CasePanelDetailSlotsProps {\n why?: React.ReactNode\n actions?: React.ReactNode\n opportunity?: React.ReactNode\n timeline?: React.ReactNode\n playPanel?: React.ReactNode\n className?: string\n}\n\nexport function CasePanelDetailSlots({\n why,\n actions,\n opportunity,\n timeline,\n playPanel,\n className,\n}: CasePanelDetailSlotsProps) {\n return (\n <div className={cn(\"mt-7 space-y-6\", className)}>\n {why ? <div data-slot=\"why\">{why}</div> : null}\n {actions ? <div data-slot=\"actions\">{actions}</div> : null}\n {opportunity ? <div data-slot=\"opportunity\">{opportunity}</div> : null}\n {timeline ? <div data-slot=\"timeline\">{timeline}</div> : null}\n {playPanel ? <div data-slot=\"play-panel\">{playPanel}</div> : null}\n </div>\n )\n}\n"],"mappings":"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","names":[]}