@handled-ai/design-system 0.18.53 → 0.18.55
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/badge.d.ts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/email-preview-card.js +24 -17
- package/dist/components/email-preview-card.js.map +1 -1
- package/dist/components/pill.d.ts +1 -1
- package/dist/components/tabs.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/__tests__/email-preview-card.test.tsx +13 -7
- package/src/components/email-preview-card.tsx +19 -13
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const badgeVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "secondary" | "destructive" | "outline" | "ghost" |
|
|
6
|
+
variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "ghost" | null | undefined;
|
|
7
7
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
8
8
|
declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
|
|
9
9
|
asChild?: boolean;
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "secondary" | "destructive" | "outline" | "ghost" |
|
|
6
|
+
variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "ghost" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
@@ -19,15 +19,15 @@ function EmailPreviewCard({
|
|
|
19
19
|
signatureHtml,
|
|
20
20
|
className
|
|
21
21
|
}) {
|
|
22
|
-
const recipientLabel = to
|
|
22
|
+
const recipientLabel = to || "the recipient";
|
|
23
23
|
const bodyHtml = htmlBody != null ? htmlBody : textBody ? escapeHtml(textBody) : "";
|
|
24
24
|
return /* @__PURE__ */ jsxs("div", { className: cn("p-4 bg-muted/30 min-h-full", className), children: [
|
|
25
25
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 mb-3 py-2.5 px-3 border rounded-lg bg-background text-[11.5px] text-muted-foreground", children: [
|
|
26
26
|
/* @__PURE__ */ jsx(Eye, { className: "size-4 shrink-0 mt-0.5" }),
|
|
27
27
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
28
|
-
"This is
|
|
28
|
+
"This is a preview for ",
|
|
29
29
|
recipientLabel,
|
|
30
|
-
"
|
|
30
|
+
". Nothing has been sent yet."
|
|
31
31
|
] })
|
|
32
32
|
] }),
|
|
33
33
|
/* @__PURE__ */ jsxs("div", { className: "bg-background border rounded-xl shadow-sm overflow-hidden", children: [
|
|
@@ -48,20 +48,27 @@ function EmailPreviewCard({
|
|
|
48
48
|
] }),
|
|
49
49
|
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground shrink-0", children: "just now" })
|
|
50
50
|
] }),
|
|
51
|
-
/* @__PURE__ */
|
|
52
|
-
"div",
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 px-[18px] pt-3 pb-4", children: [
|
|
52
|
+
/* @__PURE__ */ jsx("div", { className: "size-9 shrink-0", "aria-hidden": "true" }),
|
|
53
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-3", children: [
|
|
54
|
+
/* @__PURE__ */ jsx(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: "text-[13.5px] leading-relaxed whitespace-pre-wrap",
|
|
58
|
+
"data-testid": "email-preview-body",
|
|
59
|
+
dangerouslySetInnerHTML: { __html: bodyHtml }
|
|
60
|
+
}
|
|
61
|
+
),
|
|
62
|
+
signatureHtml ? /* @__PURE__ */ jsx(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
className: "border-t border-border/50 pt-3 text-xs leading-relaxed text-muted-foreground",
|
|
66
|
+
"data-testid": "email-preview-signature",
|
|
67
|
+
dangerouslySetInnerHTML: { __html: signatureHtml }
|
|
68
|
+
}
|
|
69
|
+
) : null
|
|
70
|
+
] })
|
|
71
|
+
] })
|
|
65
72
|
] })
|
|
66
73
|
] });
|
|
67
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/email-preview-card.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { Eye } from \"lucide-react\"\n\nimport { cn } from \"../lib/utils\"\n\nexport interface EmailPreviewCardProps {\n from: { name: string; email: string }\n to?: string\n subject?: string\n htmlBody?: string\n textBody?: string\n signatureHtml?: string | null\n className?: string\n}\n\nfunction getInitials(name: string): string {\n return name\n .split(\" \")\n .map((part) => part[0])\n .filter(Boolean)\n .slice(0, 2)\n .join(\"\")\n .toUpperCase()\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\")\n}\n\nexport function EmailPreviewCard({\n from,\n to,\n subject,\n htmlBody,\n textBody,\n signatureHtml,\n className,\n}: EmailPreviewCardProps) {\n const recipientLabel = to
|
|
1
|
+
{"version":3,"sources":["../../src/components/email-preview-card.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { Eye } from \"lucide-react\"\n\nimport { cn } from \"../lib/utils\"\n\nexport interface EmailPreviewCardProps {\n from: { name: string; email: string }\n to?: string\n subject?: string\n htmlBody?: string\n textBody?: string\n signatureHtml?: string | null\n className?: string\n}\n\nfunction getInitials(name: string): string {\n return name\n .split(\" \")\n .map((part) => part[0])\n .filter(Boolean)\n .slice(0, 2)\n .join(\"\")\n .toUpperCase()\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\")\n}\n\nexport function EmailPreviewCard({\n from,\n to,\n subject,\n htmlBody,\n textBody,\n signatureHtml,\n className,\n}: EmailPreviewCardProps) {\n const recipientLabel = to || \"the recipient\"\n const bodyHtml = htmlBody ?? (textBody ? escapeHtml(textBody) : \"\")\n\n return (\n <div className={cn(\"p-4 bg-muted/30 min-h-full\", className)}>\n <div className=\"flex items-start gap-2 mb-3 py-2.5 px-3 border rounded-lg bg-background text-[11.5px] text-muted-foreground\">\n <Eye className=\"size-4 shrink-0 mt-0.5\" />\n <span>\n This is a preview for {recipientLabel}. Nothing has been sent yet.\n </span>\n </div>\n\n <div className=\"bg-background border rounded-xl shadow-sm overflow-hidden\">\n <div className=\"px-[18px] pt-4 pb-3 text-base font-semibold border-b border-border/50\">\n {subject || \"(no subject)\"}\n </div>\n\n <div className=\"flex items-center gap-3 px-[18px] pt-3\">\n <div className=\"flex size-9 shrink-0 items-center justify-center rounded-full bg-foreground text-background text-xs font-semibold\">\n {getInitials(from.name)}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm\">\n <span className=\"font-semibold text-foreground\">{from.name}</span>{\" \"}\n <span className=\"text-muted-foreground\"><{from.email}></span>\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {to ? `to ${to}` : \"to no recipient yet\"}\n </div>\n </div>\n <div className=\"text-xs text-muted-foreground shrink-0\">just now</div>\n </div>\n\n <div className=\"flex gap-3 px-[18px] pt-3 pb-4\">\n <div className=\"size-9 shrink-0\" aria-hidden=\"true\" />\n <div className=\"min-w-0 flex-1 space-y-3\">\n <div\n className=\"text-[13.5px] leading-relaxed whitespace-pre-wrap\"\n data-testid=\"email-preview-body\"\n dangerouslySetInnerHTML={{ __html: bodyHtml }}\n />\n\n {signatureHtml ? (\n <div\n className=\"border-t border-border/50 pt-3 text-xs leading-relaxed text-muted-foreground\"\n data-testid=\"email-preview-signature\"\n dangerouslySetInnerHTML={{ __html: signatureHtml }}\n />\n ) : null}\n </div>\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":";AAmDQ,cACA,YADA;AAhDR,SAAS,WAAW;AAEpB,SAAS,UAAU;AAYnB,SAAS,YAAY,MAAsB;AACzC,SAAO,KACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,CAAC,CAAC,EACrB,OAAO,OAAO,EACd,MAAM,GAAG,CAAC,EACV,KAAK,EAAE,EACP,YAAY;AACjB;AAEA,SAAS,WAAW,MAAsB;AACxC,SAAO,KACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,OAAO;AAC1B;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,iBAAiB,MAAM;AAC7B,QAAM,WAAW,8BAAa,WAAW,WAAW,QAAQ,IAAI;AAEhE,SACE,qBAAC,SAAI,WAAW,GAAG,8BAA8B,SAAS,GACxD;AAAA,yBAAC,SAAI,WAAU,+GACb;AAAA,0BAAC,OAAI,WAAU,0BAAyB;AAAA,MACxC,qBAAC,UAAK;AAAA;AAAA,QACmB;AAAA,QAAe;AAAA,SACxC;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,6DACb;AAAA,0BAAC,SAAI,WAAU,yEACZ,qBAAW,gBACd;AAAA,MAEA,qBAAC,SAAI,WAAU,0CACb;AAAA,4BAAC,SAAI,WAAU,qHACZ,sBAAY,KAAK,IAAI,GACxB;AAAA,QACA,qBAAC,SAAI,WAAU,kBACb;AAAA,+BAAC,SAAI,WAAU,WACb;AAAA,gCAAC,UAAK,WAAU,iCAAiC,eAAK,MAAK;AAAA,YAAQ;AAAA,YACnE,qBAAC,UAAK,WAAU,yBAAwB;AAAA;AAAA,cAAK,KAAK;AAAA,cAAM;AAAA,eAAI;AAAA,aAC9D;AAAA,UACA,oBAAC,SAAI,WAAU,iCACZ,eAAK,MAAM,EAAE,KAAK,uBACrB;AAAA,WACF;AAAA,QACA,oBAAC,SAAI,WAAU,0CAAyC,sBAAQ;AAAA,SAClE;AAAA,MAEA,qBAAC,SAAI,WAAU,kCACb;AAAA,4BAAC,SAAI,WAAU,mBAAkB,eAAY,QAAO;AAAA,QACpD,qBAAC,SAAI,WAAU,4BACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,eAAY;AAAA,cACZ,yBAAyB,EAAE,QAAQ,SAAS;AAAA;AAAA,UAC9C;AAAA,UAEC,gBACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,eAAY;AAAA,cACZ,yBAAyB,EAAE,QAAQ,cAAc;AAAA;AAAA,UACnD,IACE;AAAA,WACN;AAAA,SACF;AAAA,OACF;AAAA,KACF;AAEJ;","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" | "
|
|
15
|
+
variant?: "error" | "default" | "secondary" | "destructive" | "outline" | "ghost" | "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
|
}
|
|
@@ -5,7 +5,7 @@ import { Tabs as Tabs$1 } from 'radix-ui';
|
|
|
5
5
|
|
|
6
6
|
declare function Tabs({ className, orientation, ...props }: React.ComponentProps<typeof Tabs$1.Root>): React.JSX.Element;
|
|
7
7
|
declare const tabsListVariants: (props?: ({
|
|
8
|
-
variant?: "
|
|
8
|
+
variant?: "line" | "default" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
declare function TabsList({ className, variant, ...props }: React.ComponentProps<typeof Tabs$1.List> & VariantProps<typeof tabsListVariants>): React.JSX.Element;
|
|
11
11
|
declare function TabsTrigger({ className, ...props }: React.ComponentProps<typeof Tabs$1.Trigger>): React.JSX.Element;
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ describe("EmailPreviewCard", () => {
|
|
|
31
31
|
render(<EmailPreviewCard from={from} to="jane@acme.com" />)
|
|
32
32
|
expect(screen.getByText("to jane@acme.com")).toBeTruthy()
|
|
33
33
|
expect(
|
|
34
|
-
screen.getByText(/This is
|
|
34
|
+
screen.getByText(/This is a preview for jane@acme.com\. Nothing has been sent yet\./),
|
|
35
35
|
).toBeTruthy()
|
|
36
36
|
})
|
|
37
37
|
|
|
@@ -39,24 +39,30 @@ describe("EmailPreviewCard", () => {
|
|
|
39
39
|
render(<EmailPreviewCard from={from} />)
|
|
40
40
|
expect(screen.getByText("to no recipient yet")).toBeTruthy()
|
|
41
41
|
expect(
|
|
42
|
-
screen.getByText(/This is
|
|
42
|
+
screen.getByText(/This is a preview for the recipient\. Nothing has been sent yet\./),
|
|
43
43
|
).toBeTruthy()
|
|
44
44
|
})
|
|
45
45
|
|
|
46
|
-
it("renders html body markup", () => {
|
|
46
|
+
it("renders html body markup in the message body area", () => {
|
|
47
47
|
const { container } = render(
|
|
48
48
|
<EmailPreviewCard from={from} htmlBody="<strong>Hello world</strong>" />,
|
|
49
49
|
)
|
|
50
|
-
expect(
|
|
50
|
+
expect(screen.getByTestId("email-preview-body").querySelector("strong")?.textContent).toBe("Hello world")
|
|
51
|
+
expect(container.querySelector("[data-testid='email-preview-body']")?.className).not.toContain("ml-")
|
|
51
52
|
})
|
|
52
53
|
|
|
53
|
-
it("renders the signature
|
|
54
|
-
|
|
54
|
+
it("renders the signature as part of the aligned message content", () => {
|
|
55
|
+
render(
|
|
55
56
|
<EmailPreviewCard
|
|
56
57
|
from={from}
|
|
58
|
+
htmlBody="<p>Hello</p>"
|
|
57
59
|
signatureHtml="<em>Best, Cory</em>"
|
|
58
60
|
/>,
|
|
59
61
|
)
|
|
60
|
-
|
|
62
|
+
|
|
63
|
+
expect(screen.getByTestId("email-preview-signature").querySelector("em")?.textContent).toBe("Best, Cory")
|
|
64
|
+
expect(screen.getByTestId("email-preview-body").parentElement).toBe(
|
|
65
|
+
screen.getByTestId("email-preview-signature").parentElement,
|
|
66
|
+
)
|
|
61
67
|
})
|
|
62
68
|
})
|
|
@@ -43,7 +43,7 @@ export function EmailPreviewCard({
|
|
|
43
43
|
signatureHtml,
|
|
44
44
|
className,
|
|
45
45
|
}: EmailPreviewCardProps) {
|
|
46
|
-
const recipientLabel = to
|
|
46
|
+
const recipientLabel = to || "the recipient"
|
|
47
47
|
const bodyHtml = htmlBody ?? (textBody ? escapeHtml(textBody) : "")
|
|
48
48
|
|
|
49
49
|
return (
|
|
@@ -51,8 +51,7 @@ export function EmailPreviewCard({
|
|
|
51
51
|
<div className="flex items-start gap-2 mb-3 py-2.5 px-3 border rounded-lg bg-background text-[11.5px] text-muted-foreground">
|
|
52
52
|
<Eye className="size-4 shrink-0 mt-0.5" />
|
|
53
53
|
<span>
|
|
54
|
-
This is
|
|
55
|
-
been sent yet.
|
|
54
|
+
This is a preview for {recipientLabel}. Nothing has been sent yet.
|
|
56
55
|
</span>
|
|
57
56
|
</div>
|
|
58
57
|
|
|
@@ -77,17 +76,24 @@ export function EmailPreviewCard({
|
|
|
77
76
|
<div className="text-xs text-muted-foreground shrink-0">just now</div>
|
|
78
77
|
</div>
|
|
79
78
|
|
|
80
|
-
<div
|
|
81
|
-
className="
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
<div className="flex gap-3 px-[18px] pt-3 pb-4">
|
|
80
|
+
<div className="size-9 shrink-0" aria-hidden="true" />
|
|
81
|
+
<div className="min-w-0 flex-1 space-y-3">
|
|
82
|
+
<div
|
|
83
|
+
className="text-[13.5px] leading-relaxed whitespace-pre-wrap"
|
|
84
|
+
data-testid="email-preview-body"
|
|
85
|
+
dangerouslySetInnerHTML={{ __html: bodyHtml }}
|
|
86
|
+
/>
|
|
84
87
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
{signatureHtml ? (
|
|
89
|
+
<div
|
|
90
|
+
className="border-t border-border/50 pt-3 text-xs leading-relaxed text-muted-foreground"
|
|
91
|
+
data-testid="email-preview-signature"
|
|
92
|
+
dangerouslySetInnerHTML={{ __html: signatureHtml }}
|
|
93
|
+
/>
|
|
94
|
+
) : null}
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
91
97
|
</div>
|
|
92
98
|
</div>
|
|
93
99
|
)
|