@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,61 @@
1
+ import * as React from 'react';
2
+
3
+ type CasePanelEmailComposerRowState = "default" | "confirmed" | "unconfirmed";
4
+ interface CasePanelEmailComposerRowProps extends React.HTMLAttributes<HTMLDivElement> {
5
+ label: React.ReactNode;
6
+ children?: React.ReactNode;
7
+ value?: React.ReactNode;
8
+ placeholder?: React.ReactNode;
9
+ actions?: React.ReactNode;
10
+ state?: CasePanelEmailComposerRowState;
11
+ }
12
+ declare function CasePanelEmailComposerRow({ label, children, value, placeholder, actions, state, className, ...props }: CasePanelEmailComposerRowProps): React.JSX.Element;
13
+ interface CasePanelEmailComposerChipProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
14
+ children: React.ReactNode;
15
+ }
16
+ declare function CasePanelEmailComposerChip({ children, className, type, ...props }: CasePanelEmailComposerChipProps): React.JSX.Element;
17
+ interface CasePanelEmailComposerSignatureRowProps extends React.HTMLAttributes<HTMLDivElement> {
18
+ children?: React.ReactNode;
19
+ label?: React.ReactNode;
20
+ checked?: boolean;
21
+ disabled?: boolean;
22
+ }
23
+ declare function CasePanelEmailComposerSignatureRow({ children, label, checked, disabled, className, ...props }: CasePanelEmailComposerSignatureRowProps): React.JSX.Element;
24
+ interface CasePanelEmailComposerSlotHelpers {
25
+ Row: typeof CasePanelEmailComposerRow;
26
+ Chip: typeof CasePanelEmailComposerChip;
27
+ SignatureRow: typeof CasePanelEmailComposerSignatureRow;
28
+ }
29
+ interface CasePanelEmailComposerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onKeyDown" | "title"> {
30
+ title?: React.ReactNode;
31
+ providerLabel?: React.ReactNode;
32
+ recipientRows?: React.ReactNode | ((helpers: CasePanelEmailComposerSlotHelpers) => React.ReactNode);
33
+ from?: React.ReactNode;
34
+ to?: React.ReactNode;
35
+ cc?: React.ReactNode;
36
+ bcc?: React.ReactNode;
37
+ subject?: React.ReactNode;
38
+ toState?: CasePanelEmailComposerRowState;
39
+ draftEditor?: React.ReactNode;
40
+ toolbar?: React.ReactNode;
41
+ sendBarActions?: React.ReactNode;
42
+ signatureControl?: React.ReactNode;
43
+ disabledReason?: React.ReactNode;
44
+ disabled?: boolean;
45
+ sendDisabled?: boolean;
46
+ sendLabel?: React.ReactNode;
47
+ onSendIntent?: () => void;
48
+ onContactsIntent?: () => void;
49
+ onAccountDetailsIntent?: () => void;
50
+ onAddCcIntent?: () => void;
51
+ onAddBccIntent?: () => void;
52
+ contactsLabel?: React.ReactNode;
53
+ accountDetailsLabel?: React.ReactNode;
54
+ addCcLabel?: React.ReactNode;
55
+ addBccLabel?: React.ReactNode;
56
+ showRecipientActionChips?: boolean;
57
+ onComposerKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
58
+ }
59
+ declare function CasePanelEmailComposer({ title, providerLabel, recipientRows, from, to, cc, bcc, subject, toState, draftEditor, toolbar, sendBarActions, signatureControl, disabledReason, disabled, sendDisabled, sendLabel, onSendIntent, onContactsIntent, onAccountDetailsIntent, onAddCcIntent, onAddBccIntent, contactsLabel, accountDetailsLabel, addCcLabel, addBccLabel, showRecipientActionChips, onComposerKeyDown, className, ...props }: CasePanelEmailComposerProps): React.JSX.Element;
60
+
61
+ export { CasePanelEmailComposer, CasePanelEmailComposerChip, type CasePanelEmailComposerChipProps, type CasePanelEmailComposerProps, CasePanelEmailComposerRow, type CasePanelEmailComposerRowProps, type CasePanelEmailComposerRowState, CasePanelEmailComposerSignatureRow, type CasePanelEmailComposerSignatureRowProps, type CasePanelEmailComposerSlotHelpers };
@@ -0,0 +1,304 @@
1
+ "use client"
2
+
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __defProps = Object.defineProperties;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols)
16
+ for (var prop of __getOwnPropSymbols(b)) {
17
+ if (__propIsEnum.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
22
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
+ var __objRest = (source, exclude) => {
24
+ var target = {};
25
+ for (var prop in source)
26
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
27
+ target[prop] = source[prop];
28
+ if (source != null && __getOwnPropSymbols)
29
+ for (var prop of __getOwnPropSymbols(source)) {
30
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
31
+ target[prop] = source[prop];
32
+ }
33
+ return target;
34
+ };
35
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
36
+ import * as React from "react";
37
+ import { cn } from "../lib/utils.js";
38
+ import { BRAND_ICONS } from "../lib/icons.js";
39
+ function CasePanelEmailComposerRow(_a) {
40
+ var _b = _a, {
41
+ label,
42
+ children,
43
+ value,
44
+ placeholder,
45
+ actions,
46
+ state = "default",
47
+ className
48
+ } = _b, props = __objRest(_b, [
49
+ "label",
50
+ "children",
51
+ "value",
52
+ "placeholder",
53
+ "actions",
54
+ "state",
55
+ "className"
56
+ ]);
57
+ var _a2;
58
+ const content = (_a2 = children != null ? children : value) != null ? _a2 : placeholder;
59
+ const rowClassName = state === "unconfirmed" ? "flex min-h-11 items-stretch border-b border-amber-200/80 bg-amber-50/75 text-sm dark:border-amber-900/50 dark:bg-amber-950/20" : "flex min-h-11 items-stretch border-b border-border/70 bg-background text-sm";
60
+ const labelClassName = state === "unconfirmed" ? "flex w-[60px] shrink-0 items-center border-r border-amber-200/80 px-3 text-[11px] font-semibold uppercase tracking-wide text-amber-700 dark:border-amber-900/50 dark:text-amber-300" : "flex w-[60px] shrink-0 items-center border-r border-border/70 px-3 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground";
61
+ const contentClassName = state === "unconfirmed" ? "flex min-w-0 flex-1 items-center gap-2 px-3 py-2 text-amber-950 dark:text-amber-100" : "flex min-w-0 flex-1 items-center gap-2 px-3 py-2 text-foreground";
62
+ const placeholderClassName = state === "unconfirmed" ? "min-w-0 truncate text-amber-700/80 dark:text-amber-200/80" : "min-w-0 truncate text-muted-foreground";
63
+ return /* @__PURE__ */ jsxs(
64
+ "div",
65
+ __spreadProps(__spreadValues({
66
+ "data-slot": "case-panel-email-composer-row",
67
+ "data-state": state,
68
+ className: cn(rowClassName, className)
69
+ }, props), {
70
+ children: [
71
+ /* @__PURE__ */ jsx("div", { "data-slot": "case-panel-email-composer-row-label", className: labelClassName, children: label }),
72
+ /* @__PURE__ */ jsxs("div", { "data-slot": "case-panel-email-composer-row-content", className: contentClassName, children: [
73
+ content ? /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 truncate", children: content }) : /* @__PURE__ */ jsxs("div", { className: placeholderClassName, children: [
74
+ "Add ",
75
+ label
76
+ ] }),
77
+ actions ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1.5", children: actions }) : null
78
+ ] })
79
+ ]
80
+ })
81
+ );
82
+ }
83
+ function CasePanelEmailComposerChip(_c) {
84
+ var _d = _c, {
85
+ children,
86
+ className,
87
+ type = "button"
88
+ } = _d, props = __objRest(_d, [
89
+ "children",
90
+ "className",
91
+ "type"
92
+ ]);
93
+ return /* @__PURE__ */ jsx(
94
+ "button",
95
+ __spreadProps(__spreadValues({
96
+ "data-slot": "case-panel-email-composer-chip",
97
+ type,
98
+ className: cn(
99
+ "inline-flex h-6 items-center justify-center rounded-full border border-border bg-background px-2.5 text-[11px] font-medium text-muted-foreground shadow-xs transition-colors hover:bg-muted/60 hover:text-foreground disabled:pointer-events-none disabled:opacity-50",
100
+ className
101
+ )
102
+ }, props), {
103
+ children
104
+ })
105
+ );
106
+ }
107
+ function CasePanelEmailComposerSignatureRow(_e) {
108
+ var _f = _e, {
109
+ children,
110
+ label = "Include signature",
111
+ checked = true,
112
+ disabled,
113
+ className
114
+ } = _f, props = __objRest(_f, [
115
+ "children",
116
+ "label",
117
+ "checked",
118
+ "disabled",
119
+ "className"
120
+ ]);
121
+ return /* @__PURE__ */ jsx(
122
+ "div",
123
+ __spreadProps(__spreadValues({
124
+ "data-slot": "case-panel-email-composer-signature-row",
125
+ className: cn(
126
+ "flex items-center justify-between border-t border-border/70 bg-muted/20 px-4 py-2.5 text-xs text-muted-foreground",
127
+ className
128
+ )
129
+ }, props), {
130
+ children: children != null ? children : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
131
+ /* @__PURE__ */ jsx(
132
+ "span",
133
+ {
134
+ "aria-hidden": "true",
135
+ "data-checked": checked ? "true" : "false",
136
+ className: checked ? "flex size-4 items-center justify-center rounded border border-foreground bg-foreground text-[10px] leading-none text-background" : "flex size-4 items-center justify-center rounded border border-border bg-background text-[10px] leading-none text-background",
137
+ children: checked ? "\u2713" : ""
138
+ }
139
+ ),
140
+ /* @__PURE__ */ jsx("span", { className: disabled ? "text-muted-foreground/60" : "text-muted-foreground", children: label })
141
+ ] })
142
+ })
143
+ );
144
+ }
145
+ const slotHelpers = {
146
+ Row: CasePanelEmailComposerRow,
147
+ Chip: CasePanelEmailComposerChip,
148
+ SignatureRow: CasePanelEmailComposerSignatureRow
149
+ };
150
+ function CasePanelEmailComposer(_g) {
151
+ var _h = _g, {
152
+ title = "Draft",
153
+ providerLabel = "Gmail",
154
+ recipientRows,
155
+ from,
156
+ to,
157
+ cc,
158
+ bcc,
159
+ subject,
160
+ toState = "default",
161
+ draftEditor,
162
+ toolbar,
163
+ sendBarActions,
164
+ signatureControl,
165
+ disabledReason,
166
+ disabled = false,
167
+ sendDisabled = false,
168
+ sendLabel = "Send",
169
+ onSendIntent,
170
+ onContactsIntent,
171
+ onAccountDetailsIntent,
172
+ onAddCcIntent,
173
+ onAddBccIntent,
174
+ contactsLabel = "Contacts",
175
+ accountDetailsLabel = "Account details",
176
+ addCcLabel = "Add Cc",
177
+ addBccLabel = "Add Bcc",
178
+ showRecipientActionChips = true,
179
+ onComposerKeyDown,
180
+ className
181
+ } = _h, props = __objRest(_h, [
182
+ "title",
183
+ "providerLabel",
184
+ "recipientRows",
185
+ "from",
186
+ "to",
187
+ "cc",
188
+ "bcc",
189
+ "subject",
190
+ "toState",
191
+ "draftEditor",
192
+ "toolbar",
193
+ "sendBarActions",
194
+ "signatureControl",
195
+ "disabledReason",
196
+ "disabled",
197
+ "sendDisabled",
198
+ "sendLabel",
199
+ "onSendIntent",
200
+ "onContactsIntent",
201
+ "onAccountDetailsIntent",
202
+ "onAddCcIntent",
203
+ "onAddBccIntent",
204
+ "contactsLabel",
205
+ "accountDetailsLabel",
206
+ "addCcLabel",
207
+ "addBccLabel",
208
+ "showRecipientActionChips",
209
+ "onComposerKeyDown",
210
+ "className"
211
+ ]);
212
+ const disabledReasonId = React.useId();
213
+ const sendIsDisabled = disabled || sendDisabled || Boolean(disabledReason);
214
+ const handleSendIntent = React.useCallback(() => {
215
+ if (sendIsDisabled) return;
216
+ onSendIntent == null ? void 0 : onSendIntent();
217
+ }, [onSendIntent, sendIsDisabled]);
218
+ const handleKeyDown = React.useCallback(
219
+ (event) => {
220
+ onComposerKeyDown == null ? void 0 : onComposerKeyDown(event);
221
+ if (event.defaultPrevented) return;
222
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
223
+ event.preventDefault();
224
+ handleSendIntent();
225
+ }
226
+ },
227
+ [handleSendIntent, onComposerKeyDown]
228
+ );
229
+ const renderedRecipientRows = typeof recipientRows === "function" ? recipientRows(slotHelpers) : recipientRows != null ? recipientRows : /* @__PURE__ */ jsxs(Fragment, { children: [
230
+ /* @__PURE__ */ jsx(CasePanelEmailComposerRow, { label: "From", value: from, placeholder: "Sender" }),
231
+ /* @__PURE__ */ jsx(CasePanelEmailComposerRow, { label: "To", value: to, placeholder: "Recipient", state: toState }),
232
+ cc ? /* @__PURE__ */ jsx(CasePanelEmailComposerRow, { label: "Cc", value: cc }) : null,
233
+ bcc ? /* @__PURE__ */ jsx(CasePanelEmailComposerRow, { label: "Bcc", value: bcc }) : null,
234
+ /* @__PURE__ */ jsx(CasePanelEmailComposerRow, { label: "Subject", value: subject, placeholder: "Subject" })
235
+ ] });
236
+ const showActionChips = showRecipientActionChips && (onContactsIntent || onAccountDetailsIntent || onAddCcIntent || onAddBccIntent);
237
+ return /* @__PURE__ */ jsxs(
238
+ "div",
239
+ __spreadProps(__spreadValues({
240
+ "data-slot": "case-panel-email-composer",
241
+ "aria-disabled": disabled ? "true" : void 0,
242
+ className: cn(
243
+ "overflow-hidden rounded-xl border border-border bg-background shadow-sm",
244
+ className
245
+ ),
246
+ onKeyDown: handleKeyDown
247
+ }, props), {
248
+ children: [
249
+ /* @__PURE__ */ jsxs("div", { "data-slot": "case-panel-email-composer-header", className: "flex items-center justify-between border-b border-border/70 bg-muted/20 px-4 py-3", children: [
250
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
251
+ /* @__PURE__ */ jsx(
252
+ "img",
253
+ {
254
+ src: BRAND_ICONS.gmail.icon,
255
+ alt: "Gmail",
256
+ className: "size-4 shrink-0 object-contain",
257
+ draggable: false
258
+ }
259
+ ),
260
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 truncate text-sm font-semibold text-foreground", children: title })
261
+ ] }),
262
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 text-[11px] font-medium text-muted-foreground", children: providerLabel })
263
+ ] }),
264
+ /* @__PURE__ */ jsxs("div", { "data-slot": "case-panel-email-composer-card", className: "bg-background", children: [
265
+ /* @__PURE__ */ jsx("div", { "data-slot": "case-panel-email-composer-recipient-rows", children: renderedRecipientRows }),
266
+ showActionChips ? /* @__PURE__ */ jsxs("div", { "data-slot": "case-panel-email-composer-chip-row", className: "flex flex-wrap items-center gap-1.5 border-b border-border/70 bg-muted/10 px-3 py-2", children: [
267
+ onContactsIntent ? /* @__PURE__ */ jsx(CasePanelEmailComposerChip, { onClick: onContactsIntent, disabled, children: contactsLabel }) : null,
268
+ onAccountDetailsIntent ? /* @__PURE__ */ jsx(CasePanelEmailComposerChip, { onClick: onAccountDetailsIntent, disabled, children: accountDetailsLabel }) : null,
269
+ onAddCcIntent ? /* @__PURE__ */ jsx(CasePanelEmailComposerChip, { onClick: onAddCcIntent, disabled, children: addCcLabel }) : null,
270
+ onAddBccIntent ? /* @__PURE__ */ jsx(CasePanelEmailComposerChip, { onClick: onAddBccIntent, disabled, children: addBccLabel }) : null
271
+ ] }) : null,
272
+ /* @__PURE__ */ jsx("div", { "data-slot": "case-panel-email-composer-editor", className: "min-h-40 px-4 py-4 text-sm text-foreground", children: draftEditor != null ? draftEditor : /* @__PURE__ */ jsx("div", { className: "text-muted-foreground", children: "Draft editor slot" }) }),
273
+ signatureControl ? /* @__PURE__ */ jsx("div", { "data-slot": "case-panel-email-composer-signature-control", children: signatureControl }) : /* @__PURE__ */ jsx(CasePanelEmailComposerSignatureRow, { disabled }),
274
+ /* @__PURE__ */ jsx("div", { "data-slot": "case-panel-email-composer-toolbar", className: "flex min-h-11 items-center gap-2 border-t border-border/70 bg-muted/10 px-3 py-2", children: toolbar != null ? toolbar : /* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-muted-foreground", children: "Toolbar" }) }),
275
+ /* @__PURE__ */ jsxs("div", { "data-slot": "case-panel-email-composer-send-bar", className: "flex items-center justify-between gap-3 border-t border-border/70 bg-background px-3 py-3", children: [
276
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: disabledReason ? /* @__PURE__ */ jsx("div", { id: disabledReasonId, "data-slot": "case-panel-email-composer-disabled-reason", className: "truncate text-xs text-muted-foreground", children: disabledReason }) : null }),
277
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
278
+ sendBarActions,
279
+ /* @__PURE__ */ jsx(
280
+ "button",
281
+ {
282
+ type: "button",
283
+ "data-slot": "case-panel-email-composer-send-button",
284
+ "aria-describedby": disabledReason ? disabledReasonId : void 0,
285
+ disabled: sendIsDisabled,
286
+ onClick: handleSendIntent,
287
+ className: "inline-flex h-8 items-center justify-center rounded-md bg-foreground px-3 text-xs font-semibold text-background shadow-xs transition-colors hover:bg-foreground/90 disabled:pointer-events-none disabled:bg-muted disabled:text-muted-foreground",
288
+ children: sendLabel
289
+ }
290
+ )
291
+ ] })
292
+ ] })
293
+ ] })
294
+ ]
295
+ })
296
+ );
297
+ }
298
+ export {
299
+ CasePanelEmailComposer,
300
+ CasePanelEmailComposerChip,
301
+ CasePanelEmailComposerRow,
302
+ CasePanelEmailComposerSignatureRow
303
+ };
304
+ //# sourceMappingURL=case-panel-email-composer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/case-panel-email-composer.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"../lib/utils\"\nimport { BRAND_ICONS } from \"../lib/icons\"\n\nexport type CasePanelEmailComposerRowState = \"default\" | \"confirmed\" | \"unconfirmed\"\n\nexport interface CasePanelEmailComposerRowProps extends React.HTMLAttributes<HTMLDivElement> {\n label: React.ReactNode\n children?: React.ReactNode\n value?: React.ReactNode\n placeholder?: React.ReactNode\n actions?: React.ReactNode\n state?: CasePanelEmailComposerRowState\n}\n\nexport function CasePanelEmailComposerRow({\n label,\n children,\n value,\n placeholder,\n actions,\n state = \"default\",\n className,\n ...props\n}: CasePanelEmailComposerRowProps) {\n const content = children ?? value ?? placeholder\n const rowClassName =\n state === \"unconfirmed\"\n ? \"flex min-h-11 items-stretch border-b border-amber-200/80 bg-amber-50/75 text-sm dark:border-amber-900/50 dark:bg-amber-950/20\"\n : \"flex min-h-11 items-stretch border-b border-border/70 bg-background text-sm\"\n const labelClassName =\n state === \"unconfirmed\"\n ? \"flex w-[60px] shrink-0 items-center border-r border-amber-200/80 px-3 text-[11px] font-semibold uppercase tracking-wide text-amber-700 dark:border-amber-900/50 dark:text-amber-300\"\n : \"flex w-[60px] shrink-0 items-center border-r border-border/70 px-3 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\"\n const contentClassName =\n state === \"unconfirmed\"\n ? \"flex min-w-0 flex-1 items-center gap-2 px-3 py-2 text-amber-950 dark:text-amber-100\"\n : \"flex min-w-0 flex-1 items-center gap-2 px-3 py-2 text-foreground\"\n const placeholderClassName =\n state === \"unconfirmed\"\n ? \"min-w-0 truncate text-amber-700/80 dark:text-amber-200/80\"\n : \"min-w-0 truncate text-muted-foreground\"\n\n return (\n <div\n data-slot=\"case-panel-email-composer-row\"\n data-state={state}\n className={cn(rowClassName, className)}\n {...props}\n >\n <div data-slot=\"case-panel-email-composer-row-label\" className={labelClassName}>\n {label}\n </div>\n <div data-slot=\"case-panel-email-composer-row-content\" className={contentClassName}>\n {content ? (\n <div className=\"min-w-0 flex-1 truncate\">{content}</div>\n ) : (\n <div className={placeholderClassName}>Add {label}</div>\n )}\n {actions ? <div className=\"flex shrink-0 items-center gap-1.5\">{actions}</div> : null}\n </div>\n </div>\n )\n}\n\nexport interface CasePanelEmailComposerChipProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode\n}\n\nexport function CasePanelEmailComposerChip({\n children,\n className,\n type = \"button\",\n ...props\n}: CasePanelEmailComposerChipProps) {\n return (\n <button\n data-slot=\"case-panel-email-composer-chip\"\n type={type}\n className={cn(\n \"inline-flex h-6 items-center justify-center rounded-full border border-border bg-background px-2.5 text-[11px] font-medium text-muted-foreground shadow-xs transition-colors hover:bg-muted/60 hover:text-foreground disabled:pointer-events-none disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n {children}\n </button>\n )\n}\n\nexport interface CasePanelEmailComposerSignatureRowProps extends React.HTMLAttributes<HTMLDivElement> {\n children?: React.ReactNode\n label?: React.ReactNode\n checked?: boolean\n disabled?: boolean\n}\n\nexport function CasePanelEmailComposerSignatureRow({\n children,\n label = \"Include signature\",\n checked = true,\n disabled,\n className,\n ...props\n}: CasePanelEmailComposerSignatureRowProps) {\n return (\n <div\n data-slot=\"case-panel-email-composer-signature-row\"\n className={cn(\n \"flex items-center justify-between border-t border-border/70 bg-muted/20 px-4 py-2.5 text-xs text-muted-foreground\",\n className,\n )}\n {...props}\n >\n {children ?? (\n <div className=\"flex items-center gap-2\">\n <span\n aria-hidden=\"true\"\n data-checked={checked ? \"true\" : \"false\"}\n className={\n checked\n ? \"flex size-4 items-center justify-center rounded border border-foreground bg-foreground text-[10px] leading-none text-background\"\n : \"flex size-4 items-center justify-center rounded border border-border bg-background text-[10px] leading-none text-background\"\n }\n >\n {checked ? \"✓\" : \"\"}\n </span>\n <span className={disabled ? \"text-muted-foreground/60\" : \"text-muted-foreground\"}>{label}</span>\n </div>\n )}\n </div>\n )\n}\n\nexport interface CasePanelEmailComposerSlotHelpers {\n Row: typeof CasePanelEmailComposerRow\n Chip: typeof CasePanelEmailComposerChip\n SignatureRow: typeof CasePanelEmailComposerSignatureRow\n}\n\nexport interface CasePanelEmailComposerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onKeyDown\" | \"title\"> {\n title?: React.ReactNode\n providerLabel?: React.ReactNode\n recipientRows?: React.ReactNode | ((helpers: CasePanelEmailComposerSlotHelpers) => React.ReactNode)\n from?: React.ReactNode\n to?: React.ReactNode\n cc?: React.ReactNode\n bcc?: React.ReactNode\n subject?: React.ReactNode\n toState?: CasePanelEmailComposerRowState\n draftEditor?: React.ReactNode\n toolbar?: React.ReactNode\n sendBarActions?: React.ReactNode\n signatureControl?: React.ReactNode\n disabledReason?: React.ReactNode\n disabled?: boolean\n sendDisabled?: boolean\n sendLabel?: React.ReactNode\n onSendIntent?: () => void\n onContactsIntent?: () => void\n onAccountDetailsIntent?: () => void\n onAddCcIntent?: () => void\n onAddBccIntent?: () => void\n contactsLabel?: React.ReactNode\n accountDetailsLabel?: React.ReactNode\n addCcLabel?: React.ReactNode\n addBccLabel?: React.ReactNode\n showRecipientActionChips?: boolean\n onComposerKeyDown?: React.KeyboardEventHandler<HTMLDivElement>\n}\n\nconst slotHelpers: CasePanelEmailComposerSlotHelpers = {\n Row: CasePanelEmailComposerRow,\n Chip: CasePanelEmailComposerChip,\n SignatureRow: CasePanelEmailComposerSignatureRow,\n}\n\nexport function CasePanelEmailComposer({\n title = \"Draft\",\n providerLabel = \"Gmail\",\n recipientRows,\n from,\n to,\n cc,\n bcc,\n subject,\n toState = \"default\",\n draftEditor,\n toolbar,\n sendBarActions,\n signatureControl,\n disabledReason,\n disabled = false,\n sendDisabled = false,\n sendLabel = \"Send\",\n onSendIntent,\n onContactsIntent,\n onAccountDetailsIntent,\n onAddCcIntent,\n onAddBccIntent,\n contactsLabel = \"Contacts\",\n accountDetailsLabel = \"Account details\",\n addCcLabel = \"Add Cc\",\n addBccLabel = \"Add Bcc\",\n showRecipientActionChips = true,\n onComposerKeyDown,\n className,\n ...props\n}: CasePanelEmailComposerProps) {\n const disabledReasonId = React.useId()\n const sendIsDisabled = disabled || sendDisabled || Boolean(disabledReason)\n\n const handleSendIntent = React.useCallback(() => {\n if (sendIsDisabled) return\n onSendIntent?.()\n }, [onSendIntent, sendIsDisabled])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n onComposerKeyDown?.(event)\n if (event.defaultPrevented) return\n if (event.key === \"Enter\" && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n handleSendIntent()\n }\n },\n [handleSendIntent, onComposerKeyDown],\n )\n\n const renderedRecipientRows =\n typeof recipientRows === \"function\"\n ? recipientRows(slotHelpers)\n : recipientRows ?? (\n <>\n <CasePanelEmailComposerRow label=\"From\" value={from} placeholder=\"Sender\" />\n <CasePanelEmailComposerRow label=\"To\" value={to} placeholder=\"Recipient\" state={toState} />\n {cc ? <CasePanelEmailComposerRow label=\"Cc\" value={cc} /> : null}\n {bcc ? <CasePanelEmailComposerRow label=\"Bcc\" value={bcc} /> : null}\n <CasePanelEmailComposerRow label=\"Subject\" value={subject} placeholder=\"Subject\" />\n </>\n )\n\n const showActionChips =\n showRecipientActionChips &&\n (onContactsIntent || onAccountDetailsIntent || onAddCcIntent || onAddBccIntent)\n\n return (\n <div\n data-slot=\"case-panel-email-composer\"\n aria-disabled={disabled ? \"true\" : undefined}\n className={cn(\n \"overflow-hidden rounded-xl border border-border bg-background shadow-sm\",\n className,\n )}\n onKeyDown={handleKeyDown}\n {...props}\n >\n <div data-slot=\"case-panel-email-composer-header\" className=\"flex items-center justify-between border-b border-border/70 bg-muted/20 px-4 py-3\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <img\n src={BRAND_ICONS.gmail.icon}\n alt=\"Gmail\"\n className=\"size-4 shrink-0 object-contain\"\n draggable={false}\n />\n <div className=\"min-w-0 truncate text-sm font-semibold text-foreground\">{title}</div>\n </div>\n <div className=\"shrink-0 text-[11px] font-medium text-muted-foreground\">{providerLabel}</div>\n </div>\n\n <div data-slot=\"case-panel-email-composer-card\" className=\"bg-background\">\n <div data-slot=\"case-panel-email-composer-recipient-rows\">{renderedRecipientRows}</div>\n\n {showActionChips ? (\n <div data-slot=\"case-panel-email-composer-chip-row\" className=\"flex flex-wrap items-center gap-1.5 border-b border-border/70 bg-muted/10 px-3 py-2\">\n {onContactsIntent ? (\n <CasePanelEmailComposerChip onClick={onContactsIntent} disabled={disabled}>\n {contactsLabel}\n </CasePanelEmailComposerChip>\n ) : null}\n {onAccountDetailsIntent ? (\n <CasePanelEmailComposerChip onClick={onAccountDetailsIntent} disabled={disabled}>\n {accountDetailsLabel}\n </CasePanelEmailComposerChip>\n ) : null}\n {onAddCcIntent ? (\n <CasePanelEmailComposerChip onClick={onAddCcIntent} disabled={disabled}>\n {addCcLabel}\n </CasePanelEmailComposerChip>\n ) : null}\n {onAddBccIntent ? (\n <CasePanelEmailComposerChip onClick={onAddBccIntent} disabled={disabled}>\n {addBccLabel}\n </CasePanelEmailComposerChip>\n ) : null}\n </div>\n ) : null}\n\n <div data-slot=\"case-panel-email-composer-editor\" className=\"min-h-40 px-4 py-4 text-sm text-foreground\">\n {draftEditor ?? <div className=\"text-muted-foreground\">Draft editor slot</div>}\n </div>\n\n {signatureControl ? (\n <div data-slot=\"case-panel-email-composer-signature-control\">{signatureControl}</div>\n ) : (\n <CasePanelEmailComposerSignatureRow disabled={disabled} />\n )}\n\n <div data-slot=\"case-panel-email-composer-toolbar\" className=\"flex min-h-11 items-center gap-2 border-t border-border/70 bg-muted/10 px-3 py-2\">\n {toolbar ?? <div className=\"text-xs font-medium text-muted-foreground\">Toolbar</div>}\n </div>\n\n <div data-slot=\"case-panel-email-composer-send-bar\" className=\"flex items-center justify-between gap-3 border-t border-border/70 bg-background px-3 py-3\">\n <div className=\"min-w-0 flex-1\">\n {disabledReason ? (\n <div id={disabledReasonId} data-slot=\"case-panel-email-composer-disabled-reason\" className=\"truncate text-xs text-muted-foreground\">\n {disabledReason}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {sendBarActions}\n <button\n type=\"button\"\n data-slot=\"case-panel-email-composer-send-button\"\n aria-describedby={disabledReason ? disabledReasonId : undefined}\n disabled={sendIsDisabled}\n onClick={handleSendIntent}\n className=\"inline-flex h-8 items-center justify-center rounded-md bg-foreground px-3 text-xs font-semibold text-background shadow-xs transition-colors hover:bg-foreground/90 disabled:pointer-events-none disabled:bg-muted disabled:text-muted-foreground\"\n >\n {sendLabel}\n </button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":["_a"]}
@@ -0,0 +1,35 @@
1
+ import * as React from 'react';
2
+
3
+ type CasePanelWhyTone = "neutral" | "alert" | "warn" | "info" | "success";
4
+ interface CasePanelWhyRow {
5
+ id: string;
6
+ label: React.ReactNode;
7
+ value?: React.ReactNode;
8
+ meta?: React.ReactNode;
9
+ description?: React.ReactNode;
10
+ }
11
+ interface CasePanelWhyItem {
12
+ id: string;
13
+ label: React.ReactNode;
14
+ /** Count rendered in the summary pill as ×N when provided. */
15
+ count?: number;
16
+ summary?: React.ReactNode;
17
+ details?: React.ReactNode;
18
+ rows?: CasePanelWhyRow[];
19
+ icon?: React.ReactNode;
20
+ tone?: CasePanelWhyTone;
21
+ }
22
+ interface CasePanelWhyProps {
23
+ items: CasePanelWhyItem[];
24
+ label?: React.ReactNode;
25
+ defaultExpandedId?: string | null;
26
+ onExpandedChange?: (itemId: string | null) => void;
27
+ className?: string;
28
+ }
29
+ declare function CasePanelWhy({ items, label, defaultExpandedId, onExpandedChange, className, }: CasePanelWhyProps): React.JSX.Element | null;
30
+ interface CasePanelSignalApprovalActionsProps {
31
+ className?: string;
32
+ }
33
+ declare function CasePanelSignalApprovalActions({ className }: CasePanelSignalApprovalActionsProps): React.JSX.Element;
34
+
35
+ export { CasePanelSignalApprovalActions, type CasePanelSignalApprovalActionsProps, CasePanelWhy, type CasePanelWhyItem, type CasePanelWhyProps, type CasePanelWhyRow, type CasePanelWhyTone };
@@ -0,0 +1,149 @@
1
+ "use client"
2
+
3
+ "use client";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import * as React from "react";
6
+ import { CirclePlus, Loader2, ThumbsDown } from "lucide-react";
7
+ import { cn } from "../lib/utils.js";
8
+ import { SignalApprovalActions, useSignalApproval } from "./signal-feedback-inline.js";
9
+ const toneDotClasses = {
10
+ neutral: "bg-muted-foreground/50",
11
+ alert: "bg-red-500",
12
+ warn: "bg-amber-500",
13
+ info: "bg-blue-500",
14
+ success: "bg-emerald-500"
15
+ };
16
+ function makeDomId(...parts) {
17
+ return parts.filter((part) => Boolean(part)).join("-").replace(/[^A-Za-z0-9_-]+/g, "-");
18
+ }
19
+ function DefaultWhyIcon({ tone = "neutral" }) {
20
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("h-1.5 w-1.5 rounded-full", toneDotClasses[tone]) });
21
+ }
22
+ function CasePanelWhy({
23
+ items,
24
+ label = "Why",
25
+ defaultExpandedId = null,
26
+ onExpandedChange,
27
+ className
28
+ }) {
29
+ const [expandedId, setExpandedId] = React.useState(defaultExpandedId);
30
+ const reactId = React.useId();
31
+ const idPrefix = makeDomId("case-panel-why", reactId);
32
+ const toggleExpanded = React.useCallback(
33
+ (itemId) => {
34
+ setExpandedId((current) => {
35
+ const next = current === itemId ? null : itemId;
36
+ onExpandedChange == null ? void 0 : onExpandedChange(next);
37
+ return next;
38
+ });
39
+ },
40
+ [onExpandedChange]
41
+ );
42
+ if (items.length === 0) return null;
43
+ return /* @__PURE__ */ jsxs("section", { className: cn("space-y-2", className), "aria-label": typeof label === "string" ? label : "Case panel why", children: [
44
+ label ? /* @__PURE__ */ jsx("div", { className: "text-[11px] font-semibold uppercase tracking-[0.07em] text-muted-foreground", children: label }) : null,
45
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: items.map((item) => {
46
+ var _a;
47
+ const isExpanded = expandedId === item.id;
48
+ const panelId = `${idPrefix}-panel-${makeDomId(item.id)}`;
49
+ const buttonId = `${idPrefix}-button-${makeDomId(item.id)}`;
50
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
51
+ /* @__PURE__ */ jsxs(
52
+ "button",
53
+ {
54
+ id: buttonId,
55
+ type: "button",
56
+ "aria-expanded": isExpanded,
57
+ "aria-controls": panelId,
58
+ onClick: () => toggleExpanded(item.id),
59
+ onKeyDown: (event) => {
60
+ if (event.key === "Enter" || event.key === " ") {
61
+ event.preventDefault();
62
+ toggleExpanded(item.id);
63
+ }
64
+ },
65
+ className: cn(
66
+ "inline-flex min-h-8 max-w-full items-center gap-2 rounded-full border border-border bg-background px-3 py-1.5 text-left text-xs font-semibold text-foreground shadow-[0_1px_1.5px_rgba(0,0,0,0.03)] transition-colors hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
67
+ isExpanded ? "bg-muted/30" : "bg-background"
68
+ ),
69
+ children: [
70
+ /* @__PURE__ */ jsx("span", { className: "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-muted", children: (_a = item.icon) != null ? _a : /* @__PURE__ */ jsx(DefaultWhyIcon, { tone: item.tone }) }),
71
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: item.label }),
72
+ typeof item.count === "number" ? /* @__PURE__ */ jsxs("span", { className: "shrink-0 rounded-full bg-muted px-1.5 py-0 text-[10px] font-bold tabular-nums text-muted-foreground", children: [
73
+ "\xD7",
74
+ item.count
75
+ ] }) : null
76
+ ]
77
+ }
78
+ ),
79
+ isExpanded ? /* @__PURE__ */ jsxs(
80
+ "div",
81
+ {
82
+ id: panelId,
83
+ role: "region",
84
+ "aria-labelledby": buttonId,
85
+ className: "mt-2 rounded-xl border border-border bg-background p-3 shadow-[0_1px_2px_rgba(0,0,0,0.03)]",
86
+ children: [
87
+ item.summary ? /* @__PURE__ */ jsx("div", { className: "text-sm leading-6 text-foreground", children: item.summary }) : null,
88
+ item.details ? /* @__PURE__ */ jsx("div", { className: "mt-2 text-xs leading-5 text-muted-foreground", children: item.details }) : null,
89
+ item.rows && item.rows.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "mt-3 divide-y divide-border/50", "aria-label": "Why details", children: item.rows.map((row) => /* @__PURE__ */ jsx("li", { className: "py-2 first:pt-0 last:pb-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
90
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
91
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-medium leading-5 text-foreground", children: row.label }),
92
+ row.description ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: row.description }) : null,
93
+ row.meta ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-[11px] leading-4 text-muted-foreground/80", children: row.meta }) : null
94
+ ] }),
95
+ row.value ? /* @__PURE__ */ jsx("div", { className: "shrink-0 text-right text-xs font-semibold tabular-nums text-foreground", children: row.value }) : null
96
+ ] }) }, row.id)) }) : null
97
+ ]
98
+ }
99
+ ) : null
100
+ ] }, item.id);
101
+ }) })
102
+ ] });
103
+ }
104
+ function CasePanelSignalApprovalActions({ className }) {
105
+ const {
106
+ approvalState,
107
+ labels,
108
+ hideApproveButton,
109
+ approveButtonIconUrl,
110
+ requestingApproval,
111
+ requestApproval,
112
+ requestDismiss
113
+ } = useSignalApproval();
114
+ if (approvalState !== "pending") {
115
+ return /* @__PURE__ */ jsx(SignalApprovalActions, {});
116
+ }
117
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-center gap-2", className), children: [
118
+ !hideApproveButton ? /* @__PURE__ */ jsxs(
119
+ "button",
120
+ {
121
+ type: "button",
122
+ onClick: requestApproval,
123
+ disabled: requestingApproval,
124
+ className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-foreground bg-foreground px-3 text-xs font-semibold text-background shadow-none transition-colors hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-50",
125
+ children: [
126
+ requestingApproval ? /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : approveButtonIconUrl ? /* @__PURE__ */ jsx("img", { src: approveButtonIconUrl, alt: "", className: "h-3.5 w-3.5 object-contain", draggable: false }) : /* @__PURE__ */ jsx(CirclePlus, { className: "h-3.5 w-3.5" }),
127
+ labels.approveButton
128
+ ]
129
+ }
130
+ ) : null,
131
+ /* @__PURE__ */ jsxs(
132
+ "button",
133
+ {
134
+ type: "button",
135
+ onClick: requestDismiss,
136
+ className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-muted-foreground shadow-none transition-colors hover:bg-muted hover:text-foreground",
137
+ children: [
138
+ /* @__PURE__ */ jsx(ThumbsDown, { className: "h-3.5 w-3.5" }),
139
+ labels.dismissButton
140
+ ]
141
+ }
142
+ )
143
+ ] });
144
+ }
145
+ export {
146
+ CasePanelSignalApprovalActions,
147
+ CasePanelWhy
148
+ };
149
+ //# sourceMappingURL=case-panel-why.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/case-panel-why.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { CirclePlus, Loader2, ThumbsDown } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\nimport { SignalApprovalActions, useSignalApproval } from \"./signal-feedback-inline\"\n\nexport type CasePanelWhyTone = \"neutral\" | \"alert\" | \"warn\" | \"info\" | \"success\"\n\nexport interface CasePanelWhyRow {\n id: string\n label: React.ReactNode\n value?: React.ReactNode\n meta?: React.ReactNode\n description?: React.ReactNode\n}\n\nexport interface CasePanelWhyItem {\n id: string\n label: React.ReactNode\n /** Count rendered in the summary pill as ×N when provided. */\n count?: number\n summary?: React.ReactNode\n details?: React.ReactNode\n rows?: CasePanelWhyRow[]\n icon?: React.ReactNode\n tone?: CasePanelWhyTone\n}\n\nexport interface CasePanelWhyProps {\n items: CasePanelWhyItem[]\n label?: React.ReactNode\n defaultExpandedId?: string | null\n onExpandedChange?: (itemId: string | null) => void\n className?: string\n}\n\nconst toneDotClasses: Record<CasePanelWhyTone, string> = {\n neutral: \"bg-muted-foreground/50\",\n alert: \"bg-red-500\",\n warn: \"bg-amber-500\",\n info: \"bg-blue-500\",\n success: \"bg-emerald-500\",\n}\n\nfunction makeDomId(...parts: Array<string | undefined>): string {\n return parts\n .filter((part): part is string => Boolean(part))\n .join(\"-\")\n .replace(/[^A-Za-z0-9_-]+/g, \"-\")\n}\n\nfunction DefaultWhyIcon({ tone = \"neutral\" }: { tone?: CasePanelWhyTone }) {\n return <span aria-hidden=\"true\" className={cn(\"h-1.5 w-1.5 rounded-full\", toneDotClasses[tone])} />\n}\n\nexport function CasePanelWhy({\n items,\n label = \"Why\",\n defaultExpandedId = null,\n onExpandedChange,\n className,\n}: CasePanelWhyProps) {\n const [expandedId, setExpandedId] = React.useState<string | null>(defaultExpandedId)\n const reactId = React.useId()\n const idPrefix = makeDomId(\"case-panel-why\", reactId)\n\n const toggleExpanded = React.useCallback(\n (itemId: string) => {\n setExpandedId((current) => {\n const next = current === itemId ? null : itemId\n onExpandedChange?.(next)\n return next\n })\n },\n [onExpandedChange],\n )\n\n if (items.length === 0) return null\n\n return (\n <section className={cn(\"space-y-2\", className)} aria-label={typeof label === \"string\" ? label : \"Case panel why\"}>\n {label ? (\n <div className=\"text-[11px] font-semibold uppercase tracking-[0.07em] text-muted-foreground\">\n {label}\n </div>\n ) : null}\n\n <div className=\"space-y-2\">\n {items.map((item) => {\n const isExpanded = expandedId === item.id\n const panelId = `${idPrefix}-panel-${makeDomId(item.id)}`\n const buttonId = `${idPrefix}-button-${makeDomId(item.id)}`\n\n return (\n <div key={item.id} className=\"space-y-2\">\n <button\n id={buttonId}\n type=\"button\"\n aria-expanded={isExpanded}\n aria-controls={panelId}\n onClick={() => toggleExpanded(item.id)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault()\n toggleExpanded(item.id)\n }\n }}\n className={cn(\n \"inline-flex min-h-8 max-w-full items-center gap-2 rounded-full border border-border bg-background px-3 py-1.5 text-left text-xs font-semibold text-foreground shadow-[0_1px_1.5px_rgba(0,0,0,0.03)] transition-colors hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n isExpanded ? \"bg-muted/30\" : \"bg-background\",\n )}\n >\n <span className=\"inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-muted\">\n {item.icon ?? <DefaultWhyIcon tone={item.tone} />}\n </span>\n <span className=\"min-w-0 truncate\">{item.label}</span>\n {typeof item.count === \"number\" ? (\n <span className=\"shrink-0 rounded-full bg-muted px-1.5 py-0 text-[10px] font-bold tabular-nums text-muted-foreground\">\n ×{item.count}\n </span>\n ) : null}\n </button>\n\n {isExpanded ? (\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={buttonId}\n className=\"mt-2 rounded-xl border border-border bg-background p-3 shadow-[0_1px_2px_rgba(0,0,0,0.03)]\"\n >\n {item.summary ? <div className=\"text-sm leading-6 text-foreground\">{item.summary}</div> : null}\n {item.details ? <div className=\"mt-2 text-xs leading-5 text-muted-foreground\">{item.details}</div> : null}\n {item.rows && item.rows.length > 0 ? (\n <ul className=\"mt-3 divide-y divide-border/50\" aria-label=\"Why details\">\n {item.rows.map((row) => (\n <li key={row.id} className=\"py-2 first:pt-0 last:pb-0\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium leading-5 text-foreground\">{row.label}</div>\n {row.description ? (\n <div className=\"mt-1 text-xs leading-5 text-muted-foreground\">{row.description}</div>\n ) : null}\n {row.meta ? <div className=\"mt-1 text-[11px] leading-4 text-muted-foreground/80\">{row.meta}</div> : null}\n </div>\n {row.value ? (\n <div className=\"shrink-0 text-right text-xs font-semibold tabular-nums text-foreground\">\n {row.value}\n </div>\n ) : null}\n </div>\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n })}\n </div>\n </section>\n )\n}\n\nexport interface CasePanelSignalApprovalActionsProps {\n className?: string\n}\n\nexport function CasePanelSignalApprovalActions({ className }: CasePanelSignalApprovalActionsProps) {\n const {\n approvalState,\n labels,\n hideApproveButton,\n approveButtonIconUrl,\n requestingApproval,\n requestApproval,\n requestDismiss,\n } = useSignalApproval()\n\n if (approvalState !== \"pending\") {\n return <SignalApprovalActions />\n }\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-2\", className)}>\n {!hideApproveButton ? (\n <button\n type=\"button\"\n onClick={requestApproval}\n disabled={requestingApproval}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md border border-foreground bg-foreground px-3 text-xs font-semibold text-background shadow-none transition-colors hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {requestingApproval ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : approveButtonIconUrl ? (\n <img src={approveButtonIconUrl} alt=\"\" className=\"h-3.5 w-3.5 object-contain\" draggable={false} />\n ) : (\n <CirclePlus className=\"h-3.5 w-3.5\" />\n )}\n {labels.approveButton}\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={requestDismiss}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-muted-foreground shadow-none transition-colors hover:bg-muted hover:text-foreground\"\n >\n <ThumbsDown className=\"h-3.5 w-3.5\" />\n {labels.dismissButton}\n </button>\n </div>\n )\n}\n"],"mappings":"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","names":[]}