@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.
- package/dist/components/case-panel-activity-timeline.d.ts +100 -0
- package/dist/components/case-panel-activity-timeline.js +270 -0
- package/dist/components/case-panel-activity-timeline.js.map +1 -0
- package/dist/components/case-panel-detail.d.ts +60 -0
- package/dist/components/case-panel-detail.js +129 -0
- package/dist/components/case-panel-detail.js.map +1 -0
- package/dist/components/case-panel-email-composer.d.ts +61 -0
- package/dist/components/case-panel-email-composer.js +304 -0
- package/dist/components/case-panel-email-composer.js.map +1 -0
- package/dist/components/case-panel-why.d.ts +35 -0
- package/dist/components/case-panel-why.js +149 -0
- package/dist/components/case-panel-why.js.map +1 -0
- package/dist/components/contextual-quick-action-launcher.d.ts +7 -3
- package/dist/components/contextual-quick-action-launcher.js +99 -27
- package/dist/components/contextual-quick-action-launcher.js.map +1 -1
- package/dist/components/pill.d.ts +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/__tests__/case-panel-activity-timeline.test.tsx +152 -0
- package/src/components/__tests__/case-panel-detail.test.tsx +138 -0
- package/src/components/__tests__/case-panel-email-composer.test.tsx +171 -0
- package/src/components/__tests__/case-panel-why.test.tsx +152 -0
- package/src/components/__tests__/contextual-quick-action-launcher.test.tsx +90 -0
- package/src/components/case-panel-activity-timeline.tsx +414 -0
- package/src/components/case-panel-detail.tsx +228 -0
- package/src/components/case-panel-email-composer.tsx +341 -0
- package/src/components/case-panel-why.tsx +214 -0
- package/src/components/contextual-quick-action-launcher.tsx +92 -15
- package/src/index.ts +4 -0
|
@@ -7,10 +7,13 @@ interface ContextualQuickActionItem {
|
|
|
7
7
|
icon?: React.ReactNode;
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
disabledReason?: string;
|
|
10
|
+
meta?: React.ReactNode;
|
|
10
11
|
}
|
|
12
|
+
type ContextualQuickActionLauncherVariant = "default" | "case-panel";
|
|
11
13
|
interface ContextualQuickActionContextLabelProps {
|
|
12
14
|
contextLabel: string;
|
|
13
15
|
contextSecondary?: string;
|
|
16
|
+
variant?: ContextualQuickActionLauncherVariant;
|
|
14
17
|
className?: string;
|
|
15
18
|
}
|
|
16
19
|
interface ContextualQuickActionLauncherProps {
|
|
@@ -21,12 +24,13 @@ interface ContextualQuickActionLauncherProps {
|
|
|
21
24
|
onBrowseAll?: () => void;
|
|
22
25
|
showHint?: boolean;
|
|
23
26
|
align?: "start" | "end";
|
|
27
|
+
variant?: ContextualQuickActionLauncherVariant;
|
|
24
28
|
className?: string;
|
|
25
29
|
open?: boolean;
|
|
26
30
|
defaultOpen?: boolean;
|
|
27
31
|
onOpenChange?: (open: boolean) => void;
|
|
28
32
|
}
|
|
29
|
-
declare function ContextualQuickActionContextLabel({ contextLabel, contextSecondary, className, }: ContextualQuickActionContextLabelProps): React.JSX.Element;
|
|
30
|
-
declare function ContextualQuickActionLauncher({ contextLabel, contextSecondary, items, onSelect, onBrowseAll, showHint, align, className, open, defaultOpen, onOpenChange, }: ContextualQuickActionLauncherProps): React.JSX.Element;
|
|
33
|
+
declare function ContextualQuickActionContextLabel({ contextLabel, contextSecondary, variant, className, }: ContextualQuickActionContextLabelProps): React.JSX.Element;
|
|
34
|
+
declare function ContextualQuickActionLauncher({ contextLabel, contextSecondary, items, onSelect, onBrowseAll, showHint, align, variant, className, open, defaultOpen, onOpenChange, }: ContextualQuickActionLauncherProps): React.JSX.Element;
|
|
31
35
|
|
|
32
|
-
export { ContextualQuickActionContextLabel, type ContextualQuickActionContextLabelProps, type ContextualQuickActionItem, ContextualQuickActionLauncher, type ContextualQuickActionLauncherProps };
|
|
36
|
+
export { ContextualQuickActionContextLabel, type ContextualQuickActionContextLabelProps, type ContextualQuickActionItem, ContextualQuickActionLauncher, type ContextualQuickActionLauncherProps, type ContextualQuickActionLauncherVariant };
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import * as React from "react";
|
|
6
|
-
import {
|
|
6
|
+
import { ChevronDown, Zap } from "lucide-react";
|
|
7
7
|
import { cn } from "../lib/utils.js";
|
|
8
8
|
import {
|
|
9
9
|
DropdownMenu,
|
|
@@ -15,20 +15,38 @@ import {
|
|
|
15
15
|
function ContextualQuickActionContextLabel({
|
|
16
16
|
contextLabel,
|
|
17
17
|
contextSecondary,
|
|
18
|
+
variant = "default",
|
|
18
19
|
className
|
|
19
20
|
}) {
|
|
21
|
+
const isCasePanel = variant === "case-panel";
|
|
20
22
|
return /* @__PURE__ */ jsxs(
|
|
21
23
|
"div",
|
|
22
24
|
{
|
|
23
25
|
"data-slot": "contextual-quick-action-context-label",
|
|
26
|
+
"data-variant": variant,
|
|
24
27
|
className: cn(
|
|
25
|
-
"-mx-1 -mt-1 mb-1 flex items-center gap-1.5 border-b px-3 py-2 text-[11px] text-muted-foreground",
|
|
28
|
+
isCasePanel ? "-mx-2 -mt-2 mb-1 flex items-center gap-1.5 whitespace-nowrap border-b px-3 py-2.5 text-[13px] text-muted-foreground" : "-mx-1 -mt-1 mb-1 flex items-center gap-1.5 border-b px-3 py-2 text-[11px] text-muted-foreground",
|
|
26
29
|
className
|
|
27
30
|
),
|
|
28
31
|
children: [
|
|
29
|
-
/* @__PURE__ */ jsx(
|
|
32
|
+
/* @__PURE__ */ jsx(
|
|
33
|
+
Zap,
|
|
34
|
+
{
|
|
35
|
+
className: cn(isCasePanel ? "h-3.5 w-3.5 shrink-0" : "h-3 w-3 shrink-0"),
|
|
36
|
+
strokeWidth: 2.25,
|
|
37
|
+
"aria-hidden": "true"
|
|
38
|
+
}
|
|
39
|
+
),
|
|
30
40
|
/* @__PURE__ */ jsx("span", { children: "Acting on" }),
|
|
31
|
-
/* @__PURE__ */ jsx(
|
|
41
|
+
/* @__PURE__ */ jsx(
|
|
42
|
+
"strong",
|
|
43
|
+
{
|
|
44
|
+
className: cn(
|
|
45
|
+
isCasePanel ? "max-w-[260px] truncate font-semibold text-foreground" : "max-w-[180px] truncate font-semibold text-foreground"
|
|
46
|
+
),
|
|
47
|
+
children: contextLabel
|
|
48
|
+
}
|
|
49
|
+
),
|
|
32
50
|
contextSecondary ? /* @__PURE__ */ jsxs("span", { className: "min-w-0 truncate text-muted-foreground", children: [
|
|
33
51
|
"\xB7 ",
|
|
34
52
|
contextSecondary
|
|
@@ -48,12 +66,14 @@ function ContextualQuickActionLauncher({
|
|
|
48
66
|
onBrowseAll,
|
|
49
67
|
showHint = false,
|
|
50
68
|
align = "start",
|
|
69
|
+
variant = "default",
|
|
51
70
|
className,
|
|
52
71
|
open,
|
|
53
72
|
defaultOpen,
|
|
54
73
|
onOpenChange
|
|
55
74
|
}) {
|
|
56
75
|
const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen != null ? defaultOpen : false);
|
|
76
|
+
const isCasePanel = variant === "case-panel";
|
|
57
77
|
const isControlled = open !== void 0;
|
|
58
78
|
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
59
79
|
const handleOpenChange = React.useCallback(
|
|
@@ -122,13 +142,16 @@ function ContextualQuickActionLauncher({
|
|
|
122
142
|
align,
|
|
123
143
|
side: "bottom",
|
|
124
144
|
sideOffset: 6,
|
|
125
|
-
className:
|
|
145
|
+
className: cn(
|
|
146
|
+
isCasePanel ? "pointer-events-auto w-[432px] rounded-[13px] border border-border bg-popover p-2 text-[13px] shadow-[0_18px_44px_rgba(0,0,0,0.14),0_2px_10px_rgba(0,0,0,0.06)]" : "pointer-events-auto w-[308px] rounded-[10px] p-1.5 text-[12.5px] shadow-[0_12px_28px_rgba(0,0,0,0.12),0_2px_6px_rgba(0,0,0,0.04)]"
|
|
147
|
+
),
|
|
126
148
|
children: [
|
|
127
149
|
/* @__PURE__ */ jsx(
|
|
128
150
|
ContextualQuickActionContextLabel,
|
|
129
151
|
{
|
|
130
152
|
contextLabel,
|
|
131
|
-
contextSecondary
|
|
153
|
+
contextSecondary,
|
|
154
|
+
variant
|
|
132
155
|
}
|
|
133
156
|
),
|
|
134
157
|
items.map((item) => {
|
|
@@ -139,7 +162,7 @@ function ContextualQuickActionLauncher({
|
|
|
139
162
|
disabled: item.disabled,
|
|
140
163
|
onSelect: (event) => handleSelect(item, event),
|
|
141
164
|
className: cn(
|
|
142
|
-
"flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-left outline-none focus:bg-accent data-[disabled]:cursor-not-allowed data-[disabled]:opacity-100",
|
|
165
|
+
isCasePanel ? "grid cursor-pointer grid-cols-[34px_minmax(0,1fr)_auto] items-center gap-3 rounded-[9px] px-2.5 py-[9px] text-left outline-none focus:bg-muted/60 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-100" : "flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-left outline-none focus:bg-accent data-[disabled]:cursor-not-allowed data-[disabled]:opacity-100",
|
|
143
166
|
item.disabled && "text-muted-foreground"
|
|
144
167
|
),
|
|
145
168
|
children: [
|
|
@@ -148,38 +171,87 @@ function ContextualQuickActionLauncher({
|
|
|
148
171
|
{
|
|
149
172
|
"data-slot": "contextual-quick-action-item-icon",
|
|
150
173
|
className: cn(
|
|
151
|
-
"flex h-[26px] w-[26px] shrink-0 items-center justify-center rounded-md bg-secondary text-foreground",
|
|
174
|
+
isCasePanel ? "flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-[9px] border border-border/70 bg-muted/60 text-foreground [&_svg]:h-[18px] [&_svg]:w-[18px]" : "flex h-[26px] w-[26px] shrink-0 items-center justify-center rounded-md bg-secondary text-foreground",
|
|
152
175
|
item.disabled && "opacity-60"
|
|
153
176
|
),
|
|
154
177
|
children: (_a = item.icon) != null ? _a : /* @__PURE__ */ jsx(DefaultActionIcon, {})
|
|
155
178
|
}
|
|
156
179
|
),
|
|
157
180
|
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
158
|
-
/* @__PURE__ */ jsx(
|
|
159
|
-
|
|
181
|
+
/* @__PURE__ */ jsx(
|
|
182
|
+
"span",
|
|
183
|
+
{
|
|
184
|
+
className: cn(
|
|
185
|
+
isCasePanel ? "block truncate text-[13.5px] font-semibold leading-tight text-current" : "block truncate text-[12.5px] font-medium leading-tight text-current"
|
|
186
|
+
),
|
|
187
|
+
children: item.label
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
item.description ? /* @__PURE__ */ jsx(
|
|
191
|
+
"span",
|
|
192
|
+
{
|
|
193
|
+
className: cn(
|
|
194
|
+
isCasePanel ? "mt-1 block truncate text-[12px] leading-tight text-muted-foreground" : "mt-0.5 block truncate text-[11px] leading-tight text-muted-foreground"
|
|
195
|
+
),
|
|
196
|
+
children: item.description
|
|
197
|
+
}
|
|
198
|
+
) : null
|
|
160
199
|
] }),
|
|
161
|
-
item.disabled && item.disabledReason ? /* @__PURE__ */ jsx(
|
|
200
|
+
item.disabled && item.disabledReason ? /* @__PURE__ */ jsx(
|
|
201
|
+
"span",
|
|
202
|
+
{
|
|
203
|
+
"data-slot": "contextual-quick-action-item-disabled-meta",
|
|
204
|
+
className: cn(
|
|
205
|
+
isCasePanel ? "ml-auto shrink-0 whitespace-nowrap text-[12px] italic text-muted-foreground/70" : "ml-auto shrink-0 text-[10.5px] italic text-muted-foreground/80"
|
|
206
|
+
),
|
|
207
|
+
children: item.disabledReason
|
|
208
|
+
}
|
|
209
|
+
) : item.meta ? /* @__PURE__ */ jsx(
|
|
210
|
+
"span",
|
|
211
|
+
{
|
|
212
|
+
"data-slot": "contextual-quick-action-item-meta",
|
|
213
|
+
className: cn(
|
|
214
|
+
isCasePanel ? "ml-auto shrink-0 whitespace-nowrap text-[12px] italic text-muted-foreground/70" : "ml-auto shrink-0 text-[10.5px] text-muted-foreground/80"
|
|
215
|
+
),
|
|
216
|
+
children: item.meta
|
|
217
|
+
}
|
|
218
|
+
) : null
|
|
162
219
|
]
|
|
163
220
|
},
|
|
164
221
|
item.id
|
|
165
222
|
);
|
|
166
223
|
}),
|
|
167
|
-
/* @__PURE__ */ jsx(DropdownMenuSeparator, { className: "-mx-1.5 my-1" }),
|
|
168
|
-
/* @__PURE__ */ jsxs(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
224
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, { className: cn(isCasePanel ? "-mx-2 mt-1 mb-1" : "-mx-1.5 my-1") }),
|
|
225
|
+
/* @__PURE__ */ jsxs(
|
|
226
|
+
"div",
|
|
227
|
+
{
|
|
228
|
+
className: cn(
|
|
229
|
+
isCasePanel ? "flex items-center justify-between whitespace-nowrap px-2.5 py-2 text-[13px] text-muted-foreground" : "flex items-center justify-between px-2 py-1.5 text-[11px] text-muted-foreground"
|
|
230
|
+
),
|
|
231
|
+
children: [
|
|
232
|
+
/* @__PURE__ */ jsx(
|
|
233
|
+
"button",
|
|
234
|
+
{
|
|
235
|
+
type: "button",
|
|
236
|
+
className: cn(
|
|
237
|
+
isCasePanel ? "inline-flex items-center gap-1 font-semibold text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2" : "inline-flex items-center gap-1 font-medium text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
238
|
+
),
|
|
239
|
+
onClick: handleBrowseAll,
|
|
240
|
+
children: "Browse all actions"
|
|
241
|
+
}
|
|
242
|
+
),
|
|
243
|
+
/* @__PURE__ */ jsx(
|
|
244
|
+
"span",
|
|
245
|
+
{
|
|
246
|
+
className: cn(
|
|
247
|
+
isCasePanel ? "inline-flex items-center rounded-[5px] border border-border bg-muted/50 px-1.5 py-0.5 font-mono text-[11px] font-medium leading-none text-muted-foreground" : "inline-flex items-center rounded border border-border px-1 py-0.5 text-[10px] font-medium leading-none text-muted-foreground"
|
|
248
|
+
),
|
|
249
|
+
children: "\u2318K"
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
)
|
|
183
255
|
]
|
|
184
256
|
}
|
|
185
257
|
)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/contextual-quick-action-launcher.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ArrowRight, ChevronDown, Zap } from \"lucide-react\"\n\nimport { cn } from \"../lib/utils\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"./dropdown-menu\"\n\nexport interface ContextualQuickActionItem {\n id: string\n label: string\n description?: string\n icon?: React.ReactNode\n disabled?: boolean\n disabledReason?: string\n}\n\nexport interface ContextualQuickActionContextLabelProps {\n contextLabel: string\n contextSecondary?: string\n className?: string\n}\n\nexport interface ContextualQuickActionLauncherProps {\n contextLabel: string\n contextSecondary?: string\n items: ContextualQuickActionItem[]\n onSelect: (item: ContextualQuickActionItem) => void\n onBrowseAll?: () => void\n showHint?: boolean\n align?: \"start\" | \"end\"\n className?: string\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nfunction ContextualQuickActionContextLabel({\n contextLabel,\n contextSecondary,\n className,\n}: ContextualQuickActionContextLabelProps) {\n return (\n <div\n data-slot=\"contextual-quick-action-context-label\"\n className={cn(\n \"-mx-1 -mt-1 mb-1 flex items-center gap-1.5 border-b px-3 py-2 text-[11px] text-muted-foreground\",\n className\n )}\n >\n <Zap className=\"h-3 w-3 shrink-0\" strokeWidth={2.25} aria-hidden=\"true\" />\n <span>Acting on</span>\n <strong className=\"max-w-[180px] truncate font-semibold text-foreground\">\n {contextLabel}\n </strong>\n {contextSecondary ? (\n <span className=\"min-w-0 truncate text-muted-foreground\">\n · {contextSecondary}\n </span>\n ) : null}\n </div>\n )\n}\n\nfunction DefaultActionIcon() {\n return <Zap className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n}\n\nfunction ContextualQuickActionLauncher({\n contextLabel,\n contextSecondary,\n items,\n onSelect,\n onBrowseAll,\n showHint = false,\n align = \"start\",\n className,\n open,\n defaultOpen,\n onOpenChange,\n}: ContextualQuickActionLauncherProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen ?? false)\n const isControlled = open !== undefined\n const isOpen = isControlled ? open : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(nextOpen)\n }\n onOpenChange?.(nextOpen)\n },\n [isControlled, onOpenChange]\n )\n\n const closeMenu = React.useCallback(() => {\n handleOpenChange(false)\n }, [handleOpenChange])\n\n const handleSelect = React.useCallback(\n (item: ContextualQuickActionItem, event?: Event) => {\n if (item.disabled) {\n event?.preventDefault()\n return\n }\n\n onSelect(item)\n closeMenu()\n },\n [closeMenu, onSelect]\n )\n\n const handleBrowseAll = React.useCallback(() => {\n onBrowseAll?.()\n closeMenu()\n }, [closeMenu, onBrowseAll])\n\n return (\n <div\n data-slot=\"contextual-quick-action-launcher\"\n className={cn(\"inline-flex items-center gap-2\", className)}\n >\n <DropdownMenu open={isOpen} onOpenChange={handleOpenChange}>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n data-slot=\"contextual-quick-action-trigger\"\n data-state={isOpen ? \"open\" : \"closed\"}\n className={cn(\n \"inline-flex h-8 items-center gap-2 rounded-lg border border-border bg-background py-1.5 pr-2.5 pl-2 text-xs font-medium text-foreground shadow-sm transition-colors hover:border-muted-foreground/40 hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n \"data-[state=open]:border-foreground data-[state=open]:bg-foreground data-[state=open]:text-background data-[state=open]:hover:bg-foreground\"\n )}\n >\n <span\n className={cn(\n \"inline-flex h-[18px] w-[18px] items-center justify-center rounded bg-foreground/[0.04]\",\n isOpen && \"bg-background/15\"\n )}\n >\n <Zap className=\"h-3 w-3\" strokeWidth={2} aria-hidden=\"true\" />\n </span>\n <span className=\"tracking-[-0.005em]\">Quick action</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" strokeWidth={2} aria-hidden=\"true\" />\n </button>\n </DropdownMenuTrigger>\n\n <DropdownMenuContent\n align={align}\n side=\"bottom\"\n sideOffset={6}\n className=\"pointer-events-auto w-[308px] rounded-[10px] p-1.5 text-[12.5px] shadow-[0_12px_28px_rgba(0,0,0,0.12),0_2px_6px_rgba(0,0,0,0.04)]\"\n >\n <ContextualQuickActionContextLabel\n contextLabel={contextLabel}\n contextSecondary={contextSecondary}\n />\n\n {items.map((item) => (\n <DropdownMenuItem\n key={item.id}\n disabled={item.disabled}\n onSelect={(event) => handleSelect(item, event)}\n className={cn(\n \"flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-left outline-none focus:bg-accent data-[disabled]:cursor-not-allowed data-[disabled]:opacity-100\",\n item.disabled && \"text-muted-foreground\"\n )}\n >\n <span\n data-slot=\"contextual-quick-action-item-icon\"\n className={cn(\n \"flex h-[26px] w-[26px] shrink-0 items-center justify-center rounded-md bg-secondary text-foreground\",\n item.disabled && \"opacity-60\"\n )}\n >\n {item.icon ?? <DefaultActionIcon />}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-[12.5px] font-medium leading-tight text-current\">\n {item.label}\n </span>\n {item.description ? (\n <span className=\"mt-0.5 block truncate text-[11px] leading-tight text-muted-foreground\">\n {item.description}\n </span>\n ) : null}\n </span>\n {item.disabled && item.disabledReason ? (\n <span className=\"ml-auto shrink-0 text-[10.5px] italic text-muted-foreground/80\">\n {item.disabledReason}\n </span>\n ) : null}\n </DropdownMenuItem>\n ))}\n\n <DropdownMenuSeparator className=\"-mx-1.5 my-1\" />\n <div className=\"flex items-center justify-between px-2 py-1.5 text-[11px] text-muted-foreground\">\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1 font-medium text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n onClick={handleBrowseAll}\n >\n Browse all actions\n <ArrowRight className=\"h-3 w-3\" strokeWidth={2} aria-hidden=\"true\" />\n </button>\n <span className=\"inline-flex items-center rounded border border-border px-1 py-0.5 text-[10px] font-medium leading-none text-muted-foreground\">\n ⌘K\n </span>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {showHint ? (\n <span className=\"text-[11px] text-muted-foreground\">\n Or press{\" \"}\n <span className=\"inline-flex items-center rounded border border-border bg-muted/40 px-1 py-0.5 text-[10px] font-medium leading-none\">\n ⌘K\n </span>{\" \"}\n for all actions\n </span>\n ) : null}\n </div>\n )\n}\n\nexport { ContextualQuickActionContextLabel, ContextualQuickActionLauncher }\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/contextual-quick-action-launcher.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronDown, Zap } from \"lucide-react\"\n\nimport { cn } from \"../lib/utils\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"./dropdown-menu\"\n\nexport interface ContextualQuickActionItem {\n id: string\n label: string\n description?: string\n icon?: React.ReactNode\n disabled?: boolean\n disabledReason?: string\n meta?: React.ReactNode\n}\n\nexport type ContextualQuickActionLauncherVariant = \"default\" | \"case-panel\"\n\nexport interface ContextualQuickActionContextLabelProps {\n contextLabel: string\n contextSecondary?: string\n variant?: ContextualQuickActionLauncherVariant\n className?: string\n}\n\nexport interface ContextualQuickActionLauncherProps {\n contextLabel: string\n contextSecondary?: string\n items: ContextualQuickActionItem[]\n onSelect: (item: ContextualQuickActionItem) => void\n onBrowseAll?: () => void\n showHint?: boolean\n align?: \"start\" | \"end\"\n variant?: ContextualQuickActionLauncherVariant\n className?: string\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nfunction ContextualQuickActionContextLabel({\n contextLabel,\n contextSecondary,\n variant = \"default\",\n className,\n}: ContextualQuickActionContextLabelProps) {\n const isCasePanel = variant === \"case-panel\"\n\n return (\n <div\n data-slot=\"contextual-quick-action-context-label\"\n data-variant={variant}\n className={cn(\n isCasePanel\n ? \"-mx-2 -mt-2 mb-1 flex items-center gap-1.5 whitespace-nowrap border-b px-3 py-2.5 text-[13px] text-muted-foreground\"\n : \"-mx-1 -mt-1 mb-1 flex items-center gap-1.5 border-b px-3 py-2 text-[11px] text-muted-foreground\",\n className\n )}\n >\n <Zap\n className={cn(isCasePanel ? \"h-3.5 w-3.5 shrink-0\" : \"h-3 w-3 shrink-0\")}\n strokeWidth={2.25}\n aria-hidden=\"true\"\n />\n <span>Acting on</span>\n <strong\n className={cn(\n isCasePanel\n ? \"max-w-[260px] truncate font-semibold text-foreground\"\n : \"max-w-[180px] truncate font-semibold text-foreground\"\n )}\n >\n {contextLabel}\n </strong>\n {contextSecondary ? (\n <span className=\"min-w-0 truncate text-muted-foreground\">\n · {contextSecondary}\n </span>\n ) : null}\n </div>\n )\n}\n\nfunction DefaultActionIcon() {\n return <Zap className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n}\n\nfunction ContextualQuickActionLauncher({\n contextLabel,\n contextSecondary,\n items,\n onSelect,\n onBrowseAll,\n showHint = false,\n align = \"start\",\n variant = \"default\",\n className,\n open,\n defaultOpen,\n onOpenChange,\n}: ContextualQuickActionLauncherProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen ?? false)\n const isCasePanel = variant === \"case-panel\"\n const isControlled = open !== undefined\n const isOpen = isControlled ? open : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(nextOpen)\n }\n onOpenChange?.(nextOpen)\n },\n [isControlled, onOpenChange]\n )\n\n const closeMenu = React.useCallback(() => {\n handleOpenChange(false)\n }, [handleOpenChange])\n\n const handleSelect = React.useCallback(\n (item: ContextualQuickActionItem, event?: Event) => {\n if (item.disabled) {\n event?.preventDefault()\n return\n }\n\n onSelect(item)\n closeMenu()\n },\n [closeMenu, onSelect]\n )\n\n const handleBrowseAll = React.useCallback(() => {\n onBrowseAll?.()\n closeMenu()\n }, [closeMenu, onBrowseAll])\n\n return (\n <div\n data-slot=\"contextual-quick-action-launcher\"\n className={cn(\"inline-flex items-center gap-2\", className)}\n >\n <DropdownMenu open={isOpen} onOpenChange={handleOpenChange}>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n data-slot=\"contextual-quick-action-trigger\"\n data-state={isOpen ? \"open\" : \"closed\"}\n className={cn(\n \"inline-flex h-8 items-center gap-2 rounded-lg border border-border bg-background py-1.5 pr-2.5 pl-2 text-xs font-medium text-foreground shadow-sm transition-colors hover:border-muted-foreground/40 hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n \"data-[state=open]:border-foreground data-[state=open]:bg-foreground data-[state=open]:text-background data-[state=open]:hover:bg-foreground\"\n )}\n >\n <span\n className={cn(\n \"inline-flex h-[18px] w-[18px] items-center justify-center rounded bg-foreground/[0.04]\",\n isOpen && \"bg-background/15\"\n )}\n >\n <Zap className=\"h-3 w-3\" strokeWidth={2} aria-hidden=\"true\" />\n </span>\n <span className=\"tracking-[-0.005em]\">Quick action</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" strokeWidth={2} aria-hidden=\"true\" />\n </button>\n </DropdownMenuTrigger>\n\n <DropdownMenuContent\n align={align}\n side=\"bottom\"\n sideOffset={6}\n className={cn(\n isCasePanel\n ? \"pointer-events-auto w-[432px] rounded-[13px] border border-border bg-popover p-2 text-[13px] shadow-[0_18px_44px_rgba(0,0,0,0.14),0_2px_10px_rgba(0,0,0,0.06)]\"\n : \"pointer-events-auto w-[308px] rounded-[10px] p-1.5 text-[12.5px] shadow-[0_12px_28px_rgba(0,0,0,0.12),0_2px_6px_rgba(0,0,0,0.04)]\"\n )}\n >\n <ContextualQuickActionContextLabel\n contextLabel={contextLabel}\n contextSecondary={contextSecondary}\n variant={variant}\n />\n\n {items.map((item) => (\n <DropdownMenuItem\n key={item.id}\n disabled={item.disabled}\n onSelect={(event) => handleSelect(item, event)}\n className={cn(\n isCasePanel\n ? \"grid cursor-pointer grid-cols-[34px_minmax(0,1fr)_auto] items-center gap-3 rounded-[9px] px-2.5 py-[9px] text-left outline-none focus:bg-muted/60 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-100\"\n : \"flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-left outline-none focus:bg-accent data-[disabled]:cursor-not-allowed data-[disabled]:opacity-100\",\n item.disabled && \"text-muted-foreground\"\n )}\n >\n <span\n data-slot=\"contextual-quick-action-item-icon\"\n className={cn(\n isCasePanel\n ? \"flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-[9px] border border-border/70 bg-muted/60 text-foreground [&_svg]:h-[18px] [&_svg]:w-[18px]\"\n : \"flex h-[26px] w-[26px] shrink-0 items-center justify-center rounded-md bg-secondary text-foreground\",\n item.disabled && \"opacity-60\"\n )}\n >\n {item.icon ?? <DefaultActionIcon />}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span\n className={cn(\n isCasePanel\n ? \"block truncate text-[13.5px] font-semibold leading-tight text-current\"\n : \"block truncate text-[12.5px] font-medium leading-tight text-current\"\n )}\n >\n {item.label}\n </span>\n {item.description ? (\n <span\n className={cn(\n isCasePanel\n ? \"mt-1 block truncate text-[12px] leading-tight text-muted-foreground\"\n : \"mt-0.5 block truncate text-[11px] leading-tight text-muted-foreground\"\n )}\n >\n {item.description}\n </span>\n ) : null}\n </span>\n {item.disabled && item.disabledReason ? (\n <span\n data-slot=\"contextual-quick-action-item-disabled-meta\"\n className={cn(\n isCasePanel\n ? \"ml-auto shrink-0 whitespace-nowrap text-[12px] italic text-muted-foreground/70\"\n : \"ml-auto shrink-0 text-[10.5px] italic text-muted-foreground/80\"\n )}\n >\n {item.disabledReason}\n </span>\n ) : item.meta ? (\n <span\n data-slot=\"contextual-quick-action-item-meta\"\n className={cn(\n isCasePanel\n ? \"ml-auto shrink-0 whitespace-nowrap text-[12px] italic text-muted-foreground/70\"\n : \"ml-auto shrink-0 text-[10.5px] text-muted-foreground/80\"\n )}\n >\n {item.meta}\n </span>\n ) : null}\n </DropdownMenuItem>\n ))}\n\n <DropdownMenuSeparator className={cn(isCasePanel ? \"-mx-2 mt-1 mb-1\" : \"-mx-1.5 my-1\")} />\n <div\n className={cn(\n isCasePanel\n ? \"flex items-center justify-between whitespace-nowrap px-2.5 py-2 text-[13px] text-muted-foreground\"\n : \"flex items-center justify-between px-2 py-1.5 text-[11px] text-muted-foreground\"\n )}\n >\n <button\n type=\"button\"\n className={cn(\n isCasePanel\n ? \"inline-flex items-center gap-1 font-semibold text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n : \"inline-flex items-center gap-1 font-medium text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n )}\n onClick={handleBrowseAll}\n >\n Browse all actions\n </button>\n <span\n className={cn(\n isCasePanel\n ? \"inline-flex items-center rounded-[5px] border border-border bg-muted/50 px-1.5 py-0.5 font-mono text-[11px] font-medium leading-none text-muted-foreground\"\n : \"inline-flex items-center rounded border border-border px-1 py-0.5 text-[10px] font-medium leading-none text-muted-foreground\"\n )}\n >\n ⌘K\n </span>\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n\n {showHint ? (\n <span className=\"text-[11px] text-muted-foreground\">\n Or press{\" \"}\n <span className=\"inline-flex items-center rounded border border-border bg-muted/40 px-1 py-0.5 text-[10px] font-medium leading-none\">\n ⌘K\n </span>{\" \"}\n for all actions\n </span>\n ) : null}\n </div>\n )\n}\n\nexport { ContextualQuickActionContextLabel, ContextualQuickActionLauncher }\n"],"mappings":"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","names":[]}
|
|
@@ -12,7 +12,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
12
12
|
*/
|
|
13
13
|
type PillStatus = "success" | "warning" | "error" | "neutral" | "info";
|
|
14
14
|
declare const pillVariants: (props?: ({
|
|
15
|
-
variant?: "default" | "secondary" | "destructive" | "outline" | "ghost" | "error" | "
|
|
15
|
+
variant?: "default" | "secondary" | "destructive" | "outline" | "ghost" | "error" | "neutral" | "info" | "success" | "warning" | null | undefined;
|
|
16
16
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
17
17
|
interface PillProps extends React.ComponentProps<"span">, VariantProps<typeof pillVariants> {
|
|
18
18
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,11 +10,15 @@ export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, Ava
|
|
|
10
10
|
export { Badge, badgeVariants } from './components/badge.js';
|
|
11
11
|
export { Button, buttonVariants } from './components/button.js';
|
|
12
12
|
export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './components/card.js';
|
|
13
|
+
export { CasePanelEmailComposer, CasePanelEmailComposerChip, CasePanelEmailComposerChipProps, CasePanelEmailComposerProps, CasePanelEmailComposerRow, CasePanelEmailComposerRowProps, CasePanelEmailComposerRowState, CasePanelEmailComposerSignatureRow, CasePanelEmailComposerSignatureRowProps, CasePanelEmailComposerSlotHelpers } from './components/case-panel-email-composer.js';
|
|
14
|
+
export { CasePanelActivityActor, CasePanelActivityEvent, CasePanelActivityPayload, CasePanelActivityTimeline, CasePanelActivityTimelineProps, CasePanelActivityTone, CasePanelPayloadAction } from './components/case-panel-activity-timeline.js';
|
|
15
|
+
export { CasePanelDetail, CasePanelDetailProps, CasePanelDetailSlots, CasePanelDetailSlotsProps, CasePanelDetailWidth, CasePanelHeader, CasePanelHeaderProps, CasePanelIdentityLink, CasePanelIdentitySubline, CasePanelIdentitySublineProps, CasePanelMetadataRow, CasePanelMetadataRowProps, CasePanelSignalBrief, CasePanelSignalBriefProps } from './components/case-panel-detail.js';
|
|
16
|
+
export { CasePanelSignalApprovalActions, CasePanelSignalApprovalActionsProps, CasePanelWhy, CasePanelWhyItem, CasePanelWhyProps, CasePanelWhyRow, CasePanelWhyTone } from './components/case-panel-why.js';
|
|
13
17
|
export { CollapsibleSection, CollapsibleSectionProps } from './components/collapsible-section.js';
|
|
14
18
|
export { ComplianceBadge, ComplianceBadgeProps, ComplianceStatus } from './components/compliance-badge.js';
|
|
15
19
|
export { ContactChip, ContactChipProps } from './components/contact-chip.js';
|
|
16
20
|
export { ContactChannel, ContactItem, ContactList, ContactListProps } from './components/contact-list.js';
|
|
17
|
-
export { ContextualQuickActionContextLabel, ContextualQuickActionContextLabelProps, ContextualQuickActionItem, ContextualQuickActionLauncher, ContextualQuickActionLauncherProps } from './components/contextual-quick-action-launcher.js';
|
|
21
|
+
export { ContextualQuickActionContextLabel, ContextualQuickActionContextLabelProps, ContextualQuickActionItem, ContextualQuickActionLauncher, ContextualQuickActionLauncherProps, ContextualQuickActionLauncherVariant } from './components/contextual-quick-action-launcher.js';
|
|
18
22
|
export { CheckInsCard, RecentlyCompletedCard, TopTasksCard, UpcomingMeetingsCard } from './components/dashboard-cards.js';
|
|
19
23
|
export { DataRow, DataTable, DataTableProps } from './components/data-table.js';
|
|
20
24
|
export { ConditionFieldDef, ConditionFieldOption, ConditionFilterValue, ConditionOperator, ConditionOptionObject, DEFAULT_OPERATORS, DataTableConditionFilter, DataTableConditionFilterProps, OPERATOR_LABELS, generateConditionId, getOperators, shouldShowOptionSearch } from './components/data-table-condition-filter.js';
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,10 @@ export * from "./components/avatar.js";
|
|
|
10
10
|
export * from "./components/badge.js";
|
|
11
11
|
export * from "./components/button.js";
|
|
12
12
|
export * from "./components/card.js";
|
|
13
|
+
export * from "./components/case-panel-email-composer.js";
|
|
14
|
+
export * from "./components/case-panel-activity-timeline.js";
|
|
15
|
+
export * from "./components/case-panel-detail.js";
|
|
16
|
+
export * from "./components/case-panel-why.js";
|
|
13
17
|
import { CollapsibleSection } from "./components/collapsible-section.js";
|
|
14
18
|
export * from "./components/compliance-badge.js";
|
|
15
19
|
export * from "./components/contact-chip.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @handled-ai/design-system\n * UI components and utilities (shadcn-style, New York)\n */\n\n// Utilities\nexport { cn } from \"./lib/utils\"\nexport { BRAND_ICONS, BRAND_GRAPHICS } from \"./lib/icons\"\nexport { displayName, getInitials, shortName, type ProfileLike } from \"./lib/user-display\"\n\n// Hooks\nexport { useIsMobile } from \"./hooks/use-mobile\"\n\n// Components (light — no recharts/nivo/three transitive deps)\nexport * from \"./components/activity-detail\"\nexport * from \"./components/activity-log\"\nexport * from \"./components/agent-popover\"\nexport * from \"./components/agent-widget\"\nexport * from \"./components/avatar\"\nexport * from \"./components/badge\"\nexport * from \"./components/button\"\nexport * from \"./components/card\"\nexport { CollapsibleSection, type CollapsibleSectionProps } from \"./components/collapsible-section\"\nexport * from \"./components/compliance-badge\"\nexport * from \"./components/contact-chip\"\nexport * from \"./components/contact-list\"\nexport * from \"./components/contextual-quick-action-launcher\"\nexport * from \"./components/dashboard-cards\"\nexport * from \"./components/data-table\"\nexport * from \"./components/data-table-condition-filter\"\nexport * from \"./components/data-table-display\"\nexport * from \"./components/data-table-filter\"\nexport * from \"./components/data-table-quick-views\"\nexport * from \"./components/data-table-toolbar\"\nexport * from \"./components/detail-view\"\nexport * from \"./components/detail-drawer\"\nexport * from \"./components/dialog\"\nexport * from \"./components/dropdown-menu\"\nexport * from \"./components/empty-state\"\nexport * from \"./components/entity-panel\"\nexport { FeedbackFooter, FeedbackChipGroup, FeedbackInput, FeedbackActions, InlineFeedbackControl } from \"./components/feedback-primitives\"\nexport type { FeedbackFooterProps, FeedbackChipTree, FeedbackChipGroupProps, FeedbackInputProps, FeedbackActionsProps, FeedbackSubmitData, PersistedFeedbackData, InlineFeedbackControlProps } from \"./components/feedback-primitives\"\nexport { SignalPriorityPopover } from \"./components/signal-priority-popover\"\nexport type { SignalPriorityPopoverProps, PriorityFactor } from \"./components/signal-priority-popover\"\nexport * from \"./components/filter-chip\"\nexport * from \"./components/inbox-row\"\nexport * from \"./components/inbox-toolbar\"\nexport * from \"./components/inline-banner\"\nexport * from \"./components/input\"\nexport * from \"./components/insights-filter-bar\"\nexport * from \"./components/days-open-cell\"\nexport * from \"./components/linked-entity-cell\"\nexport * from \"./components/item-list\"\nexport * from \"./components/item-list-display\"\nexport * from \"./components/item-list-filter\"\nexport * from \"./components/item-list-toolbar\"\nexport * from \"./components/kbd-hint\"\nexport * from \"./components/label\"\nexport * from \"./components/message\"\nexport * from \"./components/metric-card\"\nexport * from \"./components/performance-metrics-table\"\nexport * from \"./components/pill\"\nexport * from \"./components/preview-list\"\nexport * from \"./components/progress\"\nexport * from \"./components/quick-action-chat-area\"\nexport * from \"./components/quick-segment\"\nexport {\n QuickActionModal,\n type QuickActionPriority,\n type QuickActionTaskDraft,\n type QuickActionTemplate,\n} from \"./components/quick-action-modal\"\nexport * from \"./components/quick-action-sidebar-nav\"\nexport * from \"./components/recommended-actions-section\"\nexport * from \"./components/report-card\"\nexport * from \"./components/rich-text-toolbar\"\nexport * from \"./components/score-analysis-modal\"\nexport * from \"./components/score-breakdown\"\nexport * from \"./components/score-feedback\"\nexport * from \"./components/score-semantics\"\nexport * from \"./components/score-why-chips\"\nexport * from \"./components/score-ring\"\nexport * from \"./components/scroll-area\"\nexport * from \"./components/select\"\nexport * from \"./components/separator\"\nexport * from \"./components/sheet\"\nexport * from \"./components/sidebar\"\nexport * from \"./components/signal-feedback-inline\"\nexport * from \"./components/simple-data-table\"\nexport * from \"./components/skeleton\"\nexport * from \"./components/status-badge\"\nexport * from \"./components/step-timeline\"\nexport * from \"./components/sticky-action-bar\"\nexport * from \"./components/styled-bar-list\"\nexport { DraftFeedbackInline } from \"./components/draft-feedback-inline\"\nexport type { DraftFeedbackInlineProps } from \"./components/draft-feedback-inline\"\nexport { AccountContactsPopover, BrandIcon } from \"./components/account-contacts-popover\"\nexport type { AccountContactsPopoverProps } from \"./components/account-contacts-popover\"\nexport * from \"./components/suggested-actions\"\nexport * from \"./components/switch\"\nexport * from \"./components/table\"\nexport * from \"./components/tabs\"\nexport * from \"./components/textarea\"\nexport * from \"./components/timeline-activity\"\nexport * from \"./components/tooltip\"\nexport * from \"./components/user-display\"\nexport * from \"./components/variable-autocomplete\"\nexport * from \"./components/view-mode-toggle\"\nexport * from \"./components/virtualized-data-table\"\nexport type { ColumnSizingState } from \"@tanstack/react-table\"\n\n// Charts (re-exported for backward compatibility with root imports)\nexport * from \"./charts/index\"\n\n// Prototype template system (re-exported for backward compatibility)\nexport * from \"./prototype/prototype-config\"\nexport * from \"./prototype/prototype-shell\"\nexport * from \"./prototype/prototype-inbox-view\"\nexport * from \"./prototype/prototype-insights-view\"\nexport * from \"./prototype/prototype-accounts-view\"\nexport * from \"./prototype/prototype-admin-view\"\nexport * from \"./prototype/prototype-work-queue-view\"\n"],"mappings":"AAMA,SAAS,UAAU;AACnB,SAAS,aAAa,sBAAsB;AAC5C,SAAS,aAAa,aAAa,iBAAmC;AAGtE,SAAS,mBAAmB;AAG5B,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,0BAAwD;AACjE,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,gBAAgB,mBAAmB,eAAe,iBAAiB,6BAA6B;AAEzG,SAAS,6BAA6B;AAEtC,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd;AAAA,EACE;AAAA,OAIK;AACP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,2BAA2B;AAEpC,SAAS,wBAAwB,iBAAiB;AAElD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAId,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @handled-ai/design-system\n * UI components and utilities (shadcn-style, New York)\n */\n\n// Utilities\nexport { cn } from \"./lib/utils\"\nexport { BRAND_ICONS, BRAND_GRAPHICS } from \"./lib/icons\"\nexport { displayName, getInitials, shortName, type ProfileLike } from \"./lib/user-display\"\n\n// Hooks\nexport { useIsMobile } from \"./hooks/use-mobile\"\n\n// Components (light — no recharts/nivo/three transitive deps)\nexport * from \"./components/activity-detail\"\nexport * from \"./components/activity-log\"\nexport * from \"./components/agent-popover\"\nexport * from \"./components/agent-widget\"\nexport * from \"./components/avatar\"\nexport * from \"./components/badge\"\nexport * from \"./components/button\"\nexport * from \"./components/card\"\nexport * from \"./components/case-panel-email-composer\"\nexport * from \"./components/case-panel-activity-timeline\"\nexport * from \"./components/case-panel-detail\"\nexport * from \"./components/case-panel-why\"\nexport { CollapsibleSection, type CollapsibleSectionProps } from \"./components/collapsible-section\"\nexport * from \"./components/compliance-badge\"\nexport * from \"./components/contact-chip\"\nexport * from \"./components/contact-list\"\nexport * from \"./components/contextual-quick-action-launcher\"\nexport * from \"./components/dashboard-cards\"\nexport * from \"./components/data-table\"\nexport * from \"./components/data-table-condition-filter\"\nexport * from \"./components/data-table-display\"\nexport * from \"./components/data-table-filter\"\nexport * from \"./components/data-table-quick-views\"\nexport * from \"./components/data-table-toolbar\"\nexport * from \"./components/detail-view\"\nexport * from \"./components/detail-drawer\"\nexport * from \"./components/dialog\"\nexport * from \"./components/dropdown-menu\"\nexport * from \"./components/empty-state\"\nexport * from \"./components/entity-panel\"\nexport { FeedbackFooter, FeedbackChipGroup, FeedbackInput, FeedbackActions, InlineFeedbackControl } from \"./components/feedback-primitives\"\nexport type { FeedbackFooterProps, FeedbackChipTree, FeedbackChipGroupProps, FeedbackInputProps, FeedbackActionsProps, FeedbackSubmitData, PersistedFeedbackData, InlineFeedbackControlProps } from \"./components/feedback-primitives\"\nexport { SignalPriorityPopover } from \"./components/signal-priority-popover\"\nexport type { SignalPriorityPopoverProps, PriorityFactor } from \"./components/signal-priority-popover\"\nexport * from \"./components/filter-chip\"\nexport * from \"./components/inbox-row\"\nexport * from \"./components/inbox-toolbar\"\nexport * from \"./components/inline-banner\"\nexport * from \"./components/input\"\nexport * from \"./components/insights-filter-bar\"\nexport * from \"./components/days-open-cell\"\nexport * from \"./components/linked-entity-cell\"\nexport * from \"./components/item-list\"\nexport * from \"./components/item-list-display\"\nexport * from \"./components/item-list-filter\"\nexport * from \"./components/item-list-toolbar\"\nexport * from \"./components/kbd-hint\"\nexport * from \"./components/label\"\nexport * from \"./components/message\"\nexport * from \"./components/metric-card\"\nexport * from \"./components/performance-metrics-table\"\nexport * from \"./components/pill\"\nexport * from \"./components/preview-list\"\nexport * from \"./components/progress\"\nexport * from \"./components/quick-action-chat-area\"\nexport * from \"./components/quick-segment\"\nexport {\n QuickActionModal,\n type QuickActionPriority,\n type QuickActionTaskDraft,\n type QuickActionTemplate,\n} from \"./components/quick-action-modal\"\nexport * from \"./components/quick-action-sidebar-nav\"\nexport * from \"./components/recommended-actions-section\"\nexport * from \"./components/report-card\"\nexport * from \"./components/rich-text-toolbar\"\nexport * from \"./components/score-analysis-modal\"\nexport * from \"./components/score-breakdown\"\nexport * from \"./components/score-feedback\"\nexport * from \"./components/score-semantics\"\nexport * from \"./components/score-why-chips\"\nexport * from \"./components/score-ring\"\nexport * from \"./components/scroll-area\"\nexport * from \"./components/select\"\nexport * from \"./components/separator\"\nexport * from \"./components/sheet\"\nexport * from \"./components/sidebar\"\nexport * from \"./components/signal-feedback-inline\"\nexport * from \"./components/simple-data-table\"\nexport * from \"./components/skeleton\"\nexport * from \"./components/status-badge\"\nexport * from \"./components/step-timeline\"\nexport * from \"./components/sticky-action-bar\"\nexport * from \"./components/styled-bar-list\"\nexport { DraftFeedbackInline } from \"./components/draft-feedback-inline\"\nexport type { DraftFeedbackInlineProps } from \"./components/draft-feedback-inline\"\nexport { AccountContactsPopover, BrandIcon } from \"./components/account-contacts-popover\"\nexport type { AccountContactsPopoverProps } from \"./components/account-contacts-popover\"\nexport * from \"./components/suggested-actions\"\nexport * from \"./components/switch\"\nexport * from \"./components/table\"\nexport * from \"./components/tabs\"\nexport * from \"./components/textarea\"\nexport * from \"./components/timeline-activity\"\nexport * from \"./components/tooltip\"\nexport * from \"./components/user-display\"\nexport * from \"./components/variable-autocomplete\"\nexport * from \"./components/view-mode-toggle\"\nexport * from \"./components/virtualized-data-table\"\nexport type { ColumnSizingState } from \"@tanstack/react-table\"\n\n// Charts (re-exported for backward compatibility with root imports)\nexport * from \"./charts/index\"\n\n// Prototype template system (re-exported for backward compatibility)\nexport * from \"./prototype/prototype-config\"\nexport * from \"./prototype/prototype-shell\"\nexport * from \"./prototype/prototype-inbox-view\"\nexport * from \"./prototype/prototype-insights-view\"\nexport * from \"./prototype/prototype-accounts-view\"\nexport * from \"./prototype/prototype-admin-view\"\nexport * from \"./prototype/prototype-work-queue-view\"\n"],"mappings":"AAMA,SAAS,UAAU;AACnB,SAAS,aAAa,sBAAsB;AAC5C,SAAS,aAAa,aAAa,iBAAmC;AAGtE,SAAS,mBAAmB;AAG5B,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,0BAAwD;AACjE,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,gBAAgB,mBAAmB,eAAe,iBAAiB,6BAA6B;AAEzG,SAAS,6BAA6B;AAEtC,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd;AAAA,EACE;AAAA,OAIK;AACP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,2BAA2B;AAEpC,SAAS,wBAAwB,iBAAiB;AAElD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAId,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
package/package.json
CHANGED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { describe, expect, it, vi } from "vitest"
|
|
3
|
+
import { fireEvent, render, screen, within } from "@testing-library/react"
|
|
4
|
+
import {
|
|
5
|
+
CasePanelActivityTimeline,
|
|
6
|
+
type CasePanelActivityEvent,
|
|
7
|
+
} from "../case-panel-activity-timeline"
|
|
8
|
+
|
|
9
|
+
function event(overrides: Partial<CasePanelActivityEvent> = {}): CasePanelActivityEvent {
|
|
10
|
+
return {
|
|
11
|
+
id: "event-1",
|
|
12
|
+
title: "Signal detected",
|
|
13
|
+
timeLabel: "2h ago",
|
|
14
|
+
tone: "blue",
|
|
15
|
+
payload: { kind: "generic", description: "A case update happened" },
|
|
16
|
+
...overrides,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const visibleEvent = event()
|
|
21
|
+
const systemNoiseEvent = event({
|
|
22
|
+
id: "system-1",
|
|
23
|
+
title: "System recalculated routing state",
|
|
24
|
+
timeLabel: "1h ago",
|
|
25
|
+
tone: "slate",
|
|
26
|
+
actor: { kind: "system" },
|
|
27
|
+
isSystemNoise: true,
|
|
28
|
+
payload: { kind: "generic", description: "Internal routing snapshot refreshed" },
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe("CasePanelActivityTimeline", () => {
|
|
32
|
+
it("renders collapsed by default with non-system count and last activity text", () => {
|
|
33
|
+
render(<CasePanelActivityTimeline events={[visibleEvent, systemNoiseEvent]} />)
|
|
34
|
+
|
|
35
|
+
expect(screen.getByRole("button", { name: /activity/i }).getAttribute("aria-expanded")).toBe("false")
|
|
36
|
+
expect(screen.getByText("1 event")).not.toBeNull()
|
|
37
|
+
expect(screen.getByText("Last activity 2h ago")).not.toBeNull()
|
|
38
|
+
expect(screen.queryByText("Signal detected")).toBeNull()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it("expands and renders visible timeline events", () => {
|
|
42
|
+
render(<CasePanelActivityTimeline events={[visibleEvent]} />)
|
|
43
|
+
|
|
44
|
+
fireEvent.click(screen.getByRole("button", { name: /activity/i }))
|
|
45
|
+
|
|
46
|
+
expect(screen.getByText("Signal detected")).not.toBeNull()
|
|
47
|
+
expect(screen.getByText("A case update happened")).not.toBeNull()
|
|
48
|
+
expect(screen.getByTestId("case-panel-activity-dot").className).toContain("bg-blue-50")
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it("hides system noise until the Show system events toggle is enabled", () => {
|
|
52
|
+
render(<CasePanelActivityTimeline events={[visibleEvent, systemNoiseEvent]} defaultExpanded />)
|
|
53
|
+
|
|
54
|
+
expect((screen.getByLabelText("Show system events") as HTMLInputElement).checked).toBe(false)
|
|
55
|
+
expect(screen.getByText("Signal detected")).not.toBeNull()
|
|
56
|
+
expect(screen.queryByText("System recalculated routing state")).toBeNull()
|
|
57
|
+
|
|
58
|
+
fireEvent.click(screen.getByLabelText("Show system events"))
|
|
59
|
+
|
|
60
|
+
expect(screen.getByText("System recalculated routing state")).not.toBeNull()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it("applies actor byline rules without implying system when actor is missing", () => {
|
|
64
|
+
render(
|
|
65
|
+
<CasePanelActivityTimeline
|
|
66
|
+
defaultExpanded
|
|
67
|
+
events={[
|
|
68
|
+
event({ id: "missing-actor", title: "No actor event" }),
|
|
69
|
+
event({ id: "system-actor", title: "System actor event", actor: { kind: "system" } }),
|
|
70
|
+
event({ id: "integration-actor", title: "Integration actor event", actor: { kind: "integration", name: "Salesforce" } }),
|
|
71
|
+
event({ id: "user-actor", title: "User actor event", actor: { kind: "user", name: "Maya", verb: "approved this" } }),
|
|
72
|
+
]}
|
|
73
|
+
/>
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const bylines = screen.getAllByTestId("case-panel-activity-byline")
|
|
77
|
+
expect(bylines).toHaveLength(2)
|
|
78
|
+
expect(bylines[0].textContent).toContain("Salesforce")
|
|
79
|
+
expect(bylines[0].textContent).toContain("synced this update")
|
|
80
|
+
expect(bylines[0].textContent).toContain("2h ago")
|
|
81
|
+
expect(bylines[1].textContent).toContain("Maya")
|
|
82
|
+
expect(bylines[1].textContent).toContain("approved this")
|
|
83
|
+
expect(bylines[1].textContent).toContain("2h ago")
|
|
84
|
+
expect(screen.queryByText("System")).toBeNull()
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it("renders typed payload variants and dispatches typed signal actions", () => {
|
|
88
|
+
const onPayloadAction = vi.fn()
|
|
89
|
+
render(
|
|
90
|
+
<CasePanelActivityTimeline
|
|
91
|
+
defaultExpanded
|
|
92
|
+
onPayloadAction={onPayloadAction}
|
|
93
|
+
events={[
|
|
94
|
+
event({ id: "signal", title: "Signal", payload: { kind: "signal", key: "sig-1", summary: "Churn risk rose", detail: "Usage fell 30%." } }),
|
|
95
|
+
event({ id: "score", title: "Score", payload: { kind: "scoreUpdate", previousScore: 62, nextScore: 81, reason: "Executive engagement improved." } }),
|
|
96
|
+
event({ id: "rec", title: "Recommendation", payload: { kind: "recommendation", recommendation: "Send renewal brief", rationale: "Close date is within 14 days." } }),
|
|
97
|
+
event({ id: "email", title: "Email", payload: { kind: "email", from: "rep@example.com", to: "buyer@example.com", subject: "Renewal plan", preview: "Can we meet tomorrow?" } }),
|
|
98
|
+
event({ id: "deadline", title: "Deadline", payload: { kind: "deadline", dueLabel: "Due tomorrow", status: "due", description: "SLA response window." } }),
|
|
99
|
+
event({ id: "note", title: "Note", payload: { kind: "operatorNote", note: "Customer asked for legal review." } }),
|
|
100
|
+
event({ id: "assignment", title: "Assignment", payload: { kind: "assignment", assignee: "Jordan", from: "Maya", role: "Owner" } }),
|
|
101
|
+
event({ id: "opened", title: "Opened", payload: { kind: "caseOpened", source: "Gmail", openedBy: "Ari", description: "Inbound renewal request." } }),
|
|
102
|
+
]}
|
|
103
|
+
/>
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
expect(screen.getByTestId("case-panel-payload-signal").textContent).toContain("Churn risk rose")
|
|
107
|
+
expect(screen.getByTestId("case-panel-payload-scoreUpdate").textContent).toContain("62 → 81")
|
|
108
|
+
expect(screen.getByTestId("case-panel-payload-recommendation").textContent).toContain("Send renewal brief")
|
|
109
|
+
expect(screen.getByTestId("case-panel-payload-email").textContent).toContain("Renewal plan")
|
|
110
|
+
expect(screen.getByTestId("case-panel-payload-deadline").textContent).toContain("Due tomorrow")
|
|
111
|
+
expect(screen.getByTestId("case-panel-payload-operatorNote").textContent).toContain("Customer asked for legal review.")
|
|
112
|
+
expect(screen.getByTestId("case-panel-payload-assignment").textContent).toContain("Assigned to Jordan as Owner from Maya")
|
|
113
|
+
expect(screen.getByTestId("case-panel-payload-caseOpened").textContent).toContain("Case opened by Ari from Gmail")
|
|
114
|
+
|
|
115
|
+
fireEvent.click(screen.getByRole("button", { name: "Open signal" }))
|
|
116
|
+
expect(onPayloadAction).toHaveBeenCalledWith({ kind: "openSignal", key: "sig-1", eventId: "signal" })
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it("renders the Salesforce deep-link slot", () => {
|
|
120
|
+
render(
|
|
121
|
+
<CasePanelActivityTimeline
|
|
122
|
+
defaultExpanded
|
|
123
|
+
events={[
|
|
124
|
+
event({
|
|
125
|
+
tone: "salesforce",
|
|
126
|
+
title: "Salesforce opportunity updated",
|
|
127
|
+
payload: {
|
|
128
|
+
kind: "salesforce",
|
|
129
|
+
objectLabel: "Opportunity",
|
|
130
|
+
recordLabel: "ACME Renewal",
|
|
131
|
+
changeSummary: "Stage moved to Negotiation.",
|
|
132
|
+
deepLink: { href: "https://salesforce.example.com/opp/123", label: "View opportunity" },
|
|
133
|
+
},
|
|
134
|
+
}),
|
|
135
|
+
]}
|
|
136
|
+
/>
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
const card = screen.getByTestId("case-panel-payload-salesforce")
|
|
140
|
+
expect(card.textContent).toContain("Opportunity")
|
|
141
|
+
expect(card.textContent).toContain("ACME Renewal")
|
|
142
|
+
const link = within(card).getByRole("link", { name: /view opportunity/i })
|
|
143
|
+
expect(link.getAttribute("href")).toBe("https://salesforce.example.com/opp/123")
|
|
144
|
+
expect(screen.getByTestId("case-panel-activity-dot").className).toContain("border-[#00A1E0]/25")
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it("does not render a Detailed system log section", () => {
|
|
148
|
+
render(<CasePanelActivityTimeline events={[visibleEvent, systemNoiseEvent]} defaultExpanded defaultShowSystemEvents />)
|
|
149
|
+
|
|
150
|
+
expect(screen.queryByText(/detailed system log/i)).toBeNull()
|
|
151
|
+
})
|
|
152
|
+
})
|