@fanvue/ui 0.1.0-alpha.3 → 1.0.0
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/README.md +1 -1
- package/dist/cjs/components/Alert/Alert.cjs +72 -0
- package/dist/cjs/components/Alert/Alert.cjs.map +1 -0
- package/dist/cjs/components/Avatar/Avatar.cjs +162 -0
- package/dist/cjs/components/Avatar/Avatar.cjs.map +1 -0
- package/dist/cjs/components/Badge/Badge.cjs +99 -0
- package/dist/cjs/components/Badge/Badge.cjs.map +1 -0
- package/dist/cjs/components/Button/Button.cjs +172 -0
- package/dist/cjs/components/Button/Button.cjs.map +1 -0
- package/dist/cjs/components/Checkbox/Checkbox.cjs +157 -0
- package/dist/cjs/components/Checkbox/Checkbox.cjs.map +1 -0
- package/dist/cjs/components/Chip/Chip.cjs +92 -0
- package/dist/cjs/components/Chip/Chip.cjs.map +1 -0
- package/dist/cjs/components/Count/Count.cjs +56 -0
- package/dist/cjs/components/Count/Count.cjs.map +1 -0
- package/dist/cjs/components/DatePicker/DatePicker.cjs +133 -0
- package/dist/cjs/components/DatePicker/DatePicker.cjs.map +1 -0
- package/dist/cjs/components/Divider/Divider.cjs +69 -0
- package/dist/cjs/components/Divider/Divider.cjs.map +1 -0
- package/dist/cjs/components/IconButton/IconButton.cjs +92 -0
- package/dist/cjs/components/IconButton/IconButton.cjs.map +1 -0
- package/dist/cjs/components/Icons/ArrowRightIcon.cjs +47 -0
- package/dist/cjs/components/Icons/ArrowRightIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/ArrowUpRightIcon.cjs +47 -0
- package/dist/cjs/components/Icons/ArrowUpRightIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/CheckCircleIcon.cjs +47 -0
- package/dist/cjs/components/Icons/CheckCircleIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/CheckIcon.cjs +49 -0
- package/dist/cjs/components/Icons/CheckIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/ChevronLeftIcon.cjs +49 -0
- package/dist/cjs/components/Icons/ChevronLeftIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/ChevronRightIcon.cjs +49 -0
- package/dist/cjs/components/Icons/ChevronRightIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/CloseIcon.cjs +46 -0
- package/dist/cjs/components/Icons/CloseIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/CrossIcon.cjs +40 -0
- package/dist/cjs/components/Icons/CrossIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/CrownIcon.cjs +40 -0
- package/dist/cjs/components/Icons/CrownIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/ErrorCircleIcon.cjs +47 -0
- package/dist/cjs/components/Icons/ErrorCircleIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/ErrorIcon.cjs +30 -0
- package/dist/cjs/components/Icons/ErrorIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/FireIcon.cjs +47 -0
- package/dist/cjs/components/Icons/FireIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/HomeIcon.cjs +40 -0
- package/dist/cjs/components/Icons/HomeIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/InfoCircleIcon.cjs +47 -0
- package/dist/cjs/components/Icons/InfoCircleIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/InfoIcon.cjs +30 -0
- package/dist/cjs/components/Icons/InfoIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/MicrophoneIcon.cjs +31 -0
- package/dist/cjs/components/Icons/MicrophoneIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/MinusIcon.cjs +40 -0
- package/dist/cjs/components/Icons/MinusIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/PlusIcon.cjs +40 -0
- package/dist/cjs/components/Icons/PlusIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/SpinnerIcon.cjs +43 -0
- package/dist/cjs/components/Icons/SpinnerIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/StopIcon.cjs +22 -0
- package/dist/cjs/components/Icons/StopIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/SuccessIcon.cjs +30 -0
- package/dist/cjs/components/Icons/SuccessIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/VipBadgeIcon.cjs +97 -0
- package/dist/cjs/components/Icons/VipBadgeIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/WarningIcon.cjs +30 -0
- package/dist/cjs/components/Icons/WarningIcon.cjs.map +1 -0
- package/dist/cjs/components/Icons/WarningTriangleIcon.cjs +47 -0
- package/dist/cjs/components/Icons/WarningTriangleIcon.cjs.map +1 -0
- package/dist/cjs/components/Logo/Logo.cjs +182 -0
- package/dist/cjs/components/Logo/Logo.cjs.map +1 -0
- package/dist/cjs/components/Pagination/Pagination.cjs +144 -0
- package/dist/cjs/components/Pagination/Pagination.cjs.map +1 -0
- package/dist/cjs/components/Pill/Pill.cjs +69 -0
- package/dist/cjs/components/Pill/Pill.cjs.map +1 -0
- package/dist/cjs/components/ProgressBar/ProgressBar.cjs +112 -0
- package/dist/cjs/components/ProgressBar/ProgressBar.cjs.map +1 -0
- package/dist/cjs/components/Radio/Radio.cjs +74 -0
- package/dist/cjs/components/Radio/Radio.cjs.map +1 -0
- package/dist/cjs/components/RadioGroup/RadioGroup.cjs +30 -0
- package/dist/cjs/components/RadioGroup/RadioGroup.cjs.map +1 -0
- package/dist/cjs/components/Slider/Slider.cjs +96 -0
- package/dist/cjs/components/Slider/Slider.cjs.map +1 -0
- package/dist/cjs/components/Slider/SliderLayout.cjs +31 -0
- package/dist/cjs/components/Slider/SliderLayout.cjs.map +1 -0
- package/dist/cjs/components/Slider/SliderThumb.cjs +87 -0
- package/dist/cjs/components/Slider/SliderThumb.cjs.map +1 -0
- package/dist/cjs/components/Snackbar/Snackbar.cjs +215 -0
- package/dist/cjs/components/Snackbar/Snackbar.cjs.map +1 -0
- package/dist/cjs/components/Switch/Switch.cjs +57 -0
- package/dist/cjs/components/Switch/Switch.cjs.map +1 -0
- package/dist/cjs/components/SwitchField/SwitchField.cjs +103 -0
- package/dist/cjs/components/SwitchField/SwitchField.cjs.map +1 -0
- package/dist/cjs/components/SwitchToggle/SwitchToggle.cjs +110 -0
- package/dist/cjs/components/SwitchToggle/SwitchToggle.cjs.map +1 -0
- package/dist/cjs/components/Tabs/Tabs.cjs +24 -0
- package/dist/cjs/components/Tabs/Tabs.cjs.map +1 -0
- package/dist/cjs/components/Tabs/TabsContent.cjs +36 -0
- package/dist/cjs/components/Tabs/TabsContent.cjs.map +1 -0
- package/dist/cjs/components/Tabs/TabsList.cjs +42 -0
- package/dist/cjs/components/Tabs/TabsList.cjs.map +1 -0
- package/dist/cjs/components/Tabs/TabsTrigger.cjs +50 -0
- package/dist/cjs/components/Tabs/TabsTrigger.cjs.map +1 -0
- package/dist/cjs/components/Toast/Toast.cjs +128 -0
- package/dist/cjs/components/Toast/Toast.cjs.map +1 -0
- package/dist/cjs/index.cjs +111 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/utils/cn.cjs +10 -0
- package/dist/cjs/utils/cn.cjs.map +1 -0
- package/dist/components/Alert/Alert.mjs +55 -0
- package/dist/components/Alert/Alert.mjs.map +1 -0
- package/dist/components/Avatar/Avatar.mjs +144 -0
- package/dist/components/Avatar/Avatar.mjs.map +1 -0
- package/dist/components/Badge/Badge.mjs +82 -0
- package/dist/components/Badge/Badge.mjs.map +1 -0
- package/dist/components/Button/Button.mjs +155 -0
- package/dist/components/Button/Button.mjs.map +1 -0
- package/dist/components/Checkbox/Checkbox.mjs +139 -0
- package/dist/components/Checkbox/Checkbox.mjs.map +1 -0
- package/dist/components/Chip/Chip.mjs +75 -0
- package/dist/components/Chip/Chip.mjs.map +1 -0
- package/dist/components/Count/Count.mjs +39 -0
- package/dist/components/Count/Count.mjs.map +1 -0
- package/dist/components/DatePicker/DatePicker.mjs +133 -0
- package/dist/components/DatePicker/DatePicker.mjs.map +1 -0
- package/dist/components/Divider/Divider.mjs +51 -0
- package/dist/components/Divider/Divider.mjs.map +1 -0
- package/dist/components/IconButton/IconButton.mjs +75 -0
- package/dist/components/IconButton/IconButton.mjs.map +1 -0
- package/dist/components/Icons/ArrowRightIcon.mjs +30 -0
- package/dist/components/Icons/ArrowRightIcon.mjs.map +1 -0
- package/dist/components/Icons/ArrowUpRightIcon.mjs +30 -0
- package/dist/components/Icons/ArrowUpRightIcon.mjs.map +1 -0
- package/dist/components/Icons/CheckCircleIcon.mjs +30 -0
- package/dist/components/Icons/CheckCircleIcon.mjs.map +1 -0
- package/dist/components/Icons/CheckIcon.mjs +32 -0
- package/dist/components/Icons/CheckIcon.mjs.map +1 -0
- package/dist/components/Icons/ChevronLeftIcon.mjs +32 -0
- package/dist/components/Icons/ChevronLeftIcon.mjs.map +1 -0
- package/dist/components/Icons/ChevronRightIcon.mjs +32 -0
- package/dist/components/Icons/ChevronRightIcon.mjs.map +1 -0
- package/dist/components/Icons/CloseIcon.mjs +29 -0
- package/dist/components/Icons/CloseIcon.mjs.map +1 -0
- package/dist/components/Icons/CrossIcon.mjs +23 -0
- package/dist/components/Icons/CrossIcon.mjs.map +1 -0
- package/dist/components/Icons/CrownIcon.mjs +23 -0
- package/dist/components/Icons/CrownIcon.mjs.map +1 -0
- package/dist/components/Icons/ErrorCircleIcon.mjs +30 -0
- package/dist/components/Icons/ErrorCircleIcon.mjs.map +1 -0
- package/dist/components/Icons/ErrorIcon.mjs +30 -0
- package/dist/components/Icons/ErrorIcon.mjs.map +1 -0
- package/dist/components/Icons/FireIcon.mjs +30 -0
- package/dist/components/Icons/FireIcon.mjs.map +1 -0
- package/dist/components/Icons/HomeIcon.mjs +23 -0
- package/dist/components/Icons/HomeIcon.mjs.map +1 -0
- package/dist/components/Icons/InfoCircleIcon.mjs +30 -0
- package/dist/components/Icons/InfoCircleIcon.mjs.map +1 -0
- package/dist/components/Icons/InfoIcon.mjs +30 -0
- package/dist/components/Icons/InfoIcon.mjs.map +1 -0
- package/dist/components/Icons/MicrophoneIcon.mjs +31 -0
- package/dist/components/Icons/MicrophoneIcon.mjs.map +1 -0
- package/dist/components/Icons/MinusIcon.mjs +23 -0
- package/dist/components/Icons/MinusIcon.mjs.map +1 -0
- package/dist/components/Icons/PlusIcon.mjs +23 -0
- package/dist/components/Icons/PlusIcon.mjs.map +1 -0
- package/dist/components/Icons/SpinnerIcon.mjs +26 -0
- package/dist/components/Icons/SpinnerIcon.mjs.map +1 -0
- package/dist/components/Icons/StopIcon.mjs +22 -0
- package/dist/components/Icons/StopIcon.mjs.map +1 -0
- package/dist/components/Icons/SuccessIcon.mjs +30 -0
- package/dist/components/Icons/SuccessIcon.mjs.map +1 -0
- package/dist/components/Icons/VipBadgeIcon.mjs +80 -0
- package/dist/components/Icons/VipBadgeIcon.mjs.map +1 -0
- package/dist/components/Icons/WarningIcon.mjs +30 -0
- package/dist/components/Icons/WarningIcon.mjs.map +1 -0
- package/dist/components/Icons/WarningTriangleIcon.mjs +30 -0
- package/dist/components/Icons/WarningTriangleIcon.mjs.map +1 -0
- package/dist/components/Logo/Logo.mjs +165 -0
- package/dist/components/Logo/Logo.mjs.map +1 -0
- package/dist/components/Pagination/Pagination.mjs +127 -0
- package/dist/components/Pagination/Pagination.mjs.map +1 -0
- package/dist/components/Pill/Pill.mjs +52 -0
- package/dist/components/Pill/Pill.mjs.map +1 -0
- package/dist/components/ProgressBar/ProgressBar.mjs +95 -0
- package/dist/components/ProgressBar/ProgressBar.mjs.map +1 -0
- package/dist/components/Radio/Radio.mjs +56 -0
- package/dist/components/Radio/Radio.mjs.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.mjs +12 -0
- package/dist/components/RadioGroup/RadioGroup.mjs.map +1 -0
- package/dist/components/Slider/Slider.mjs +78 -0
- package/dist/components/Slider/Slider.mjs.map +1 -0
- package/dist/components/Slider/SliderLayout.mjs +31 -0
- package/dist/components/Slider/SliderLayout.mjs.map +1 -0
- package/dist/components/Slider/SliderThumb.mjs +69 -0
- package/dist/components/Slider/SliderThumb.mjs.map +1 -0
- package/dist/components/Snackbar/Snackbar.mjs +198 -0
- package/dist/components/Snackbar/Snackbar.mjs.map +1 -0
- package/dist/components/Switch/Switch.mjs +39 -0
- package/dist/components/Switch/Switch.mjs.map +1 -0
- package/dist/components/SwitchField/SwitchField.mjs +86 -0
- package/dist/components/SwitchField/SwitchField.mjs.map +1 -0
- package/dist/components/SwitchToggle/SwitchToggle.mjs +93 -0
- package/dist/components/SwitchToggle/SwitchToggle.mjs.map +1 -0
- package/dist/components/Tabs/Tabs.mjs +7 -0
- package/dist/components/Tabs/Tabs.mjs.map +1 -0
- package/dist/components/Tabs/TabsContent.mjs +18 -0
- package/dist/components/Tabs/TabsContent.mjs.map +1 -0
- package/dist/components/Tabs/TabsList.mjs +24 -0
- package/dist/components/Tabs/TabsList.mjs.map +1 -0
- package/dist/components/Tabs/TabsTrigger.mjs +32 -0
- package/dist/components/Tabs/TabsTrigger.mjs.map +1 -0
- package/dist/components/Toast/Toast.mjs +110 -0
- package/dist/components/Toast/Toast.mjs.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.mjs +107 -10507
- package/dist/index.mjs.map +1 -1
- package/dist/utils/cn.mjs +10 -0
- package/dist/utils/cn.mjs.map +1 -0
- package/package.json +10 -4
- package/dist/index.cjs +0 -2
- package/dist/index.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
+
const React = require("react");
|
|
6
|
+
const cn = require("../../utils/cn.cjs");
|
|
7
|
+
const Button = require("../Button/Button.cjs");
|
|
8
|
+
const CrossIcon = require("../Icons/CrossIcon.cjs");
|
|
9
|
+
function _interopNamespaceDefault(e) {
|
|
10
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
11
|
+
if (e) {
|
|
12
|
+
for (const k in e) {
|
|
13
|
+
if (k !== "default") {
|
|
14
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: () => e[k]
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
26
|
+
const Alert = React__namespace.forwardRef(
|
|
27
|
+
({ className, variant = "info", title, icon, closable = false, onClose, children, ...props }, ref) => {
|
|
28
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29
|
+
"div",
|
|
30
|
+
{
|
|
31
|
+
ref,
|
|
32
|
+
role: "alert",
|
|
33
|
+
"data-testid": "alert",
|
|
34
|
+
className: cn.cn(
|
|
35
|
+
"grid gap-x-3 rounded-lg p-4 text-sm leading-[18px]",
|
|
36
|
+
icon && closable && "grid-cols-[auto_1fr_auto]",
|
|
37
|
+
icon && !closable && "grid-cols-[auto_1fr]",
|
|
38
|
+
!icon && closable && "grid-cols-[1fr_auto]",
|
|
39
|
+
!icon && !closable && "grid-cols-[1fr]",
|
|
40
|
+
title && children ? "items-start" : "items-center",
|
|
41
|
+
variant === "info" && "bg-info-50 text-info-500",
|
|
42
|
+
variant === "success" && "bg-success-50 text-success-500",
|
|
43
|
+
variant === "warning" && "bg-warning-50 text-warning-500",
|
|
44
|
+
variant === "error" && "bg-error-50 text-error-500",
|
|
45
|
+
className
|
|
46
|
+
),
|
|
47
|
+
...props,
|
|
48
|
+
children: [
|
|
49
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-start", "aria-hidden": "true", children: icon }),
|
|
50
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [
|
|
51
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "typography-body-2-semibold text-body-100", children: title }),
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "typography-body-2-regular text-body-200", children })
|
|
53
|
+
] }),
|
|
54
|
+
closable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
55
|
+
Button.Button,
|
|
56
|
+
{
|
|
57
|
+
variant: "tertiary",
|
|
58
|
+
size: "24",
|
|
59
|
+
onClick: onClose,
|
|
60
|
+
className: "self-start",
|
|
61
|
+
"aria-label": "Close alert",
|
|
62
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(CrossIcon.CrossIcon, {})
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
Alert.displayName = "Alert";
|
|
71
|
+
exports.Alert = Alert;
|
|
72
|
+
//# sourceMappingURL=Alert.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.cjs","sources":["../../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\nimport { CrossIcon } from \"../Icons/CrossIcon\";\n\nexport type AlertVariant = \"info\" | \"success\" | \"warning\" | \"error\";\n\nexport interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the alert (matches Figma \"Variant\" property) */\n variant?: AlertVariant;\n /** Optional title text (bold) */\n title?: string;\n /** Left icon element */\n icon?: React.ReactNode;\n /** Show close button */\n closable?: boolean;\n /** Callback when close button is clicked */\n onClose?: () => void;\n}\n\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n (\n { className, variant = \"info\", title, icon, closable = false, onClose, children, ...props },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n role=\"alert\"\n data-testid=\"alert\"\n className={cn(\n \"grid gap-x-3 rounded-lg p-4 text-sm leading-[18px]\",\n icon && closable && \"grid-cols-[auto_1fr_auto]\",\n icon && !closable && \"grid-cols-[auto_1fr]\",\n !icon && closable && \"grid-cols-[1fr_auto]\",\n !icon && !closable && \"grid-cols-[1fr]\",\n title && children ? \"items-start\" : \"items-center\",\n variant === \"info\" && \"bg-info-50 text-info-500\",\n variant === \"success\" && \"bg-success-50 text-success-500\",\n variant === \"warning\" && \"bg-warning-50 text-warning-500\",\n variant === \"error\" && \"bg-error-50 text-error-500\",\n className,\n )}\n {...props}\n >\n {icon && (\n <span className=\"flex shrink-0 items-start\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n\n <div className=\"flex min-w-0 flex-col gap-2\">\n {title && <div className=\"typography-body-2-semibold text-body-100\">{title}</div>}\n <div className=\"typography-body-2-regular text-body-200\">{children}</div>\n </div>\n\n {closable && (\n <Button\n variant=\"tertiary\"\n size=\"24\"\n onClick={onClose}\n className=\"self-start\"\n aria-label=\"Close alert\"\n >\n <CrossIcon />\n </Button>\n )}\n </div>\n );\n },\n);\n\nAlert.displayName = \"Alert\";\n"],"names":["React","jsxs","cn","jsx","Button","CrossIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAoBO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE,EAAE,WAAW,UAAU,QAAQ,OAAO,MAAM,WAAW,OAAO,SAAS,UAAU,GAAG,MAAA,GACpF,QACG;AACH,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,QAAQ,YAAY;AAAA,UACpB,QAAQ,CAAC,YAAY;AAAA,UACrB,CAAC,QAAQ,YAAY;AAAA,UACrB,CAAC,QAAQ,CAAC,YAAY;AAAA,UACtB,SAAS,WAAW,gBAAgB;AAAA,UACpC,YAAY,UAAU;AAAA,UACtB,YAAY,aAAa;AAAA,UACzB,YAAY,aAAa;AAAA,UACzB,YAAY,WAAW;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,uCACE,QAAA,EAAK,WAAU,6BAA4B,eAAY,QACrD,UAAA,MACH;AAAA,UAGFD,2BAAAA,KAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,YAAA,SAASE,2BAAAA,IAAC,OAAA,EAAI,WAAU,4CAA4C,UAAA,OAAM;AAAA,YAC3EA,2BAAAA,IAAC,OAAA,EAAI,WAAU,2CAA2C,SAAA,CAAS;AAAA,UAAA,GACrE;AAAA,UAEC,YACCA,2BAAAA;AAAAA,YAACC,OAAAA;AAAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,yCAACC,UAAAA,WAAA,CAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
+
const AvatarPrimitive = require("@radix-ui/react-avatar");
|
|
6
|
+
const React = require("react");
|
|
7
|
+
const cn = require("../../utils/cn.cjs");
|
|
8
|
+
function _interopNamespaceDefault(e) {
|
|
9
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
|
+
if (e) {
|
|
11
|
+
for (const k in e) {
|
|
12
|
+
if (k !== "default") {
|
|
13
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: () => e[k]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
const AvatarPrimitive__namespace = /* @__PURE__ */ _interopNamespaceDefault(AvatarPrimitive);
|
|
25
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
26
|
+
const AvatarContext = React__namespace.createContext({
|
|
27
|
+
size: 40,
|
|
28
|
+
NSFWShow: false
|
|
29
|
+
});
|
|
30
|
+
const STATUS_POSITIONS = {
|
|
31
|
+
16: { top: -4, right: -4 },
|
|
32
|
+
24: { top: -3, right: -3 },
|
|
33
|
+
32: { top: -2, right: -2 },
|
|
34
|
+
40: { top: -1, right: -1 },
|
|
35
|
+
48: { top: 0, right: 0 },
|
|
36
|
+
64: { top: 2, right: 2 },
|
|
37
|
+
88: { top: 6, right: 6 },
|
|
38
|
+
148: { top: 15, right: 15 }
|
|
39
|
+
};
|
|
40
|
+
const AvatarRoot = React__namespace.forwardRef(
|
|
41
|
+
({
|
|
42
|
+
className,
|
|
43
|
+
size = 40,
|
|
44
|
+
onlineIndicator = false,
|
|
45
|
+
platinumShow = false,
|
|
46
|
+
NSFWShow = false,
|
|
47
|
+
children,
|
|
48
|
+
...props
|
|
49
|
+
}, ref) => {
|
|
50
|
+
const statusPosition = STATUS_POSITIONS[size];
|
|
51
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AvatarContext.Provider, { value: { size, NSFWShow }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative inline-flex", children: [
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
53
|
+
AvatarPrimitive__namespace.Root,
|
|
54
|
+
{
|
|
55
|
+
ref,
|
|
56
|
+
"data-testid": "avatar",
|
|
57
|
+
className: cn.cn(
|
|
58
|
+
"relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-neutral-100",
|
|
59
|
+
size === 16 && "typography-caption-semibold size-4",
|
|
60
|
+
size === 24 && "typography-caption-semibold size-6",
|
|
61
|
+
size === 32 && "typography-body-2-semibold size-8",
|
|
62
|
+
size === 40 && "typography-body-1-semibold size-10",
|
|
63
|
+
size === 48 && "typography-heading-4 size-12",
|
|
64
|
+
size === 64 && "typography-heading-3 size-16",
|
|
65
|
+
size === 88 && "typography-heading-2 size-[88px]",
|
|
66
|
+
size === 148 && "typography-heading-1 size-[148px]",
|
|
67
|
+
className
|
|
68
|
+
),
|
|
69
|
+
...props,
|
|
70
|
+
children
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
platinumShow && /* @__PURE__ */ jsxRuntime.jsx(
|
|
74
|
+
"div",
|
|
75
|
+
{
|
|
76
|
+
className: "pointer-events-none absolute inset-0 rounded-full",
|
|
77
|
+
style: {
|
|
78
|
+
background: `linear-gradient(143deg, #504F54 0%, #B1B1B1 20.3154%, #13181C 37.3727%, #C6C6C8 58.8154%, #FFFFFF 69.3154%, #0C0F14 81.3154%, #696A6E 100%)`,
|
|
79
|
+
WebkitMask: "radial-gradient(circle closest-side, transparent 96%, black 96%)",
|
|
80
|
+
mask: "radial-gradient(circle closest-side, transparent 96%, black 96%)"
|
|
81
|
+
},
|
|
82
|
+
"aria-hidden": "true"
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
onlineIndicator && /* @__PURE__ */ jsxRuntime.jsx(
|
|
86
|
+
"span",
|
|
87
|
+
{
|
|
88
|
+
className: "absolute size-3 rounded-full border-2 border-background-150 bg-brand-green-500",
|
|
89
|
+
style: {
|
|
90
|
+
top: `${statusPosition.top}px`,
|
|
91
|
+
right: `${statusPosition.right}px`
|
|
92
|
+
},
|
|
93
|
+
"aria-hidden": "true"
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
] }) });
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
AvatarRoot.displayName = "AvatarRoot";
|
|
100
|
+
const AvatarImage = React__namespace.forwardRef(({ className, ...props }, ref) => {
|
|
101
|
+
const { NSFWShow } = React__namespace.useContext(AvatarContext);
|
|
102
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
103
|
+
AvatarPrimitive__namespace.Image,
|
|
104
|
+
{
|
|
105
|
+
ref,
|
|
106
|
+
className: cn.cn("size-full bg-neutral-200 object-cover", NSFWShow && "blur-md", className),
|
|
107
|
+
...props
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
AvatarImage.displayName = "AvatarImage";
|
|
112
|
+
const AvatarFallback = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
113
|
+
AvatarPrimitive__namespace.Fallback,
|
|
114
|
+
{
|
|
115
|
+
ref,
|
|
116
|
+
className: cn.cn(
|
|
117
|
+
"flex size-full items-center justify-center bg-neutral-200 text-neutral-400 uppercase leading-none",
|
|
118
|
+
className
|
|
119
|
+
),
|
|
120
|
+
delayMs: 0,
|
|
121
|
+
...props,
|
|
122
|
+
children
|
|
123
|
+
}
|
|
124
|
+
));
|
|
125
|
+
AvatarFallback.displayName = "AvatarFallback";
|
|
126
|
+
const Avatar = React__namespace.forwardRef(
|
|
127
|
+
({
|
|
128
|
+
className,
|
|
129
|
+
size = 40,
|
|
130
|
+
src,
|
|
131
|
+
alt,
|
|
132
|
+
fallback,
|
|
133
|
+
onlineIndicator = false,
|
|
134
|
+
platinumShow = false,
|
|
135
|
+
NSFWShow = false,
|
|
136
|
+
children,
|
|
137
|
+
...props
|
|
138
|
+
}, ref) => {
|
|
139
|
+
const rootProps = {
|
|
140
|
+
ref,
|
|
141
|
+
size,
|
|
142
|
+
onlineIndicator,
|
|
143
|
+
platinumShow,
|
|
144
|
+
NSFWShow,
|
|
145
|
+
className,
|
|
146
|
+
...props
|
|
147
|
+
};
|
|
148
|
+
if (children) {
|
|
149
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AvatarRoot, { ...rootProps, children });
|
|
150
|
+
}
|
|
151
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(AvatarRoot, { ...rootProps, children: [
|
|
152
|
+
src && /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src, alt: alt ?? "Avatar" }),
|
|
153
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: fallback })
|
|
154
|
+
] });
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
Avatar.displayName = "Avatar";
|
|
158
|
+
exports.Avatar = Avatar;
|
|
159
|
+
exports.AvatarFallback = AvatarFallback;
|
|
160
|
+
exports.AvatarImage = AvatarImage;
|
|
161
|
+
exports.AvatarRoot = AvatarRoot;
|
|
162
|
+
//# sourceMappingURL=Avatar.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.cjs","sources":["../../../../src/components/Avatar/Avatar.tsx"],"sourcesContent":["import * as AvatarPrimitive from \"@radix-ui/react-avatar\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type AvatarSize = 16 | 24 | 32 | 40 | 48 | 64 | 88 | 148;\n\nconst AvatarContext = React.createContext<{ size: AvatarSize; NSFWShow: boolean }>({\n size: 40,\n NSFWShow: false,\n});\n\nconst STATUS_POSITIONS: Record<AvatarSize, { top: number; right: number }> = {\n 16: { top: -4, right: -4 },\n 24: { top: -3, right: -3 },\n 32: { top: -2, right: -2 },\n 40: { top: -1, right: -1 },\n 48: { top: 0, right: 0 },\n 64: { top: 2, right: 2 },\n 88: { top: 6, right: 6 },\n 148: { top: 15, right: 15 },\n};\n\n/** Shared avatar styling props */\ninterface AvatarStyleProps {\n /** Size variant of the avatar (matches Figma \"Size\" property) */\n size?: AvatarSize;\n /** Show online status indicator */\n onlineIndicator?: boolean;\n /** Show platinum gradient border (matches Figma \"Platinum show\" property) */\n platinumShow?: boolean;\n /** Show NSFW blur filter (matches Figma \"NSFW show\" property) */\n NSFWShow?: boolean;\n}\n\nexport interface AvatarRootProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n AvatarStyleProps {}\n\nconst AvatarRoot = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Root>,\n AvatarRootProps\n>(\n (\n {\n className,\n size = 40,\n onlineIndicator = false,\n platinumShow = false,\n NSFWShow = false,\n children,\n ...props\n },\n ref,\n ) => {\n const statusPosition = STATUS_POSITIONS[size];\n\n return (\n <AvatarContext.Provider value={{ size, NSFWShow }}>\n <div className=\"relative inline-flex\">\n <AvatarPrimitive.Root\n ref={ref}\n data-testid=\"avatar\"\n className={cn(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-neutral-100\",\n size === 16 && \"typography-caption-semibold size-4\",\n size === 24 && \"typography-caption-semibold size-6\",\n size === 32 && \"typography-body-2-semibold size-8\",\n size === 40 && \"typography-body-1-semibold size-10\",\n size === 48 && \"typography-heading-4 size-12\",\n size === 64 && \"typography-heading-3 size-16\",\n size === 88 && \"typography-heading-2 size-[88px]\",\n size === 148 && \"typography-heading-1 size-[148px]\",\n className,\n )}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n {platinumShow && (\n <div\n className=\"pointer-events-none absolute inset-0 rounded-full\"\n style={{\n background: `linear-gradient(143deg, #504F54 0%, #B1B1B1 20.3154%, #13181C 37.3727%, #C6C6C8 58.8154%, #FFFFFF 69.3154%, #0C0F14 81.3154%, #696A6E 100%)`,\n WebkitMask: \"radial-gradient(circle closest-side, transparent 96%, black 96%)\",\n mask: \"radial-gradient(circle closest-side, transparent 96%, black 96%)\",\n }}\n aria-hidden=\"true\"\n />\n )}\n {onlineIndicator && (\n <span\n className=\"absolute size-3 rounded-full border-2 border-background-150 bg-brand-green-500\"\n style={{\n top: `${statusPosition.top}px`,\n right: `${statusPosition.right}px`,\n }}\n aria-hidden=\"true\"\n />\n )}\n </div>\n </AvatarContext.Provider>\n );\n },\n);\n\nAvatarRoot.displayName = \"AvatarRoot\";\n\nexport interface AvatarImageProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> {}\n\nconst AvatarImage = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Image>,\n AvatarImageProps\n>(({ className, ...props }, ref) => {\n const { NSFWShow } = React.useContext(AvatarContext);\n return (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"size-full bg-neutral-200 object-cover\", NSFWShow && \"blur-md\", className)}\n {...props}\n />\n );\n});\n\nAvatarImage.displayName = \"AvatarImage\";\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {}\n\nconst AvatarFallback = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, children, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n \"flex size-full items-center justify-center bg-neutral-200 text-neutral-400 uppercase leading-none\",\n className,\n )}\n delayMs={0}\n {...props}\n >\n {children}\n </AvatarPrimitive.Fallback>\n));\n\nAvatarFallback.displayName = \"AvatarFallback\";\n\nexport interface AvatarProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n AvatarStyleProps {\n /** URL of the avatar image */\n src?: string;\n /** Alt text for the avatar image */\n alt?: string;\n /** Fallback content (initials, icon, etc.) */\n fallback?: React.ReactNode;\n}\n\nexport const Avatar = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(\n (\n {\n className,\n size = 40,\n src,\n alt,\n fallback,\n onlineIndicator = false,\n platinumShow = false,\n NSFWShow = false,\n children,\n ...props\n },\n ref,\n ) => {\n const rootProps = {\n ref,\n size,\n onlineIndicator,\n platinumShow,\n NSFWShow,\n className,\n ...props,\n };\n\n if (children) {\n return <AvatarRoot {...rootProps}>{children}</AvatarRoot>;\n }\n\n return (\n <AvatarRoot {...rootProps}>\n {src && <AvatarImage src={src} alt={alt ?? \"Avatar\"} />}\n <AvatarFallback>{fallback}</AvatarFallback>\n </AvatarRoot>\n );\n },\n);\n\nAvatar.displayName = \"Avatar\";\n\nexport { AvatarRoot, AvatarImage, AvatarFallback };\n"],"names":["React","jsx","jsxs","AvatarPrimitive","cn"],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
+
const reactSlot = require("@radix-ui/react-slot");
|
|
6
|
+
const React = require("react");
|
|
7
|
+
const cn = require("../../utils/cn.cjs");
|
|
8
|
+
function _interopNamespaceDefault(e) {
|
|
9
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
|
+
if (e) {
|
|
11
|
+
for (const k in e) {
|
|
12
|
+
if (k !== "default") {
|
|
13
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: () => e[k]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
25
|
+
const badgeVariants = {
|
|
26
|
+
variant: {
|
|
27
|
+
default: "bg-neutral-100 text-neutral-400",
|
|
28
|
+
dark: "bg-background-800 text-body-300 dark:text-body-white-solid-constant",
|
|
29
|
+
success: "bg-neutral-100 text-neutral-400",
|
|
30
|
+
warning: "bg-neutral-100 text-neutral-400",
|
|
31
|
+
error: "bg-neutral-100 text-neutral-400",
|
|
32
|
+
special: "bg-neutral-100 text-neutral-400",
|
|
33
|
+
info: "bg-neutral-100 text-neutral-400",
|
|
34
|
+
online: "bg-background-200 text-brand-green-500",
|
|
35
|
+
brand: "bg-brand-green-500 text-body-black-solid-constant",
|
|
36
|
+
pink: "bg-brand-pink-500 text-body-black-solid-constant",
|
|
37
|
+
brandLight: "bg-brand-green-50 text-body-black-solid-constant",
|
|
38
|
+
pinkLight: "bg-brand-pink-50 text-body-black-solid-constant"
|
|
39
|
+
},
|
|
40
|
+
dotColor: {
|
|
41
|
+
default: "bg-body-black-solid-constant",
|
|
42
|
+
dark: "bg-body-300 dark:bg-body-white-solid-constant",
|
|
43
|
+
success: "bg-success-500",
|
|
44
|
+
warning: "bg-warning-500",
|
|
45
|
+
error: "bg-error-500",
|
|
46
|
+
special: "bg-special-500",
|
|
47
|
+
info: "bg-info-500",
|
|
48
|
+
online: "bg-brand-green-500",
|
|
49
|
+
brand: "bg-body-black-solid-constant",
|
|
50
|
+
pink: "bg-body-black-solid-constant",
|
|
51
|
+
brandLight: "bg-body-black-solid-constant",
|
|
52
|
+
pinkLight: "bg-body-black-solid-constant"
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const Badge = React__namespace.forwardRef(
|
|
56
|
+
({
|
|
57
|
+
className,
|
|
58
|
+
variant = "default",
|
|
59
|
+
leftDot = true,
|
|
60
|
+
leftIcon,
|
|
61
|
+
rightIcon,
|
|
62
|
+
asChild = false,
|
|
63
|
+
children,
|
|
64
|
+
...props
|
|
65
|
+
}, ref) => {
|
|
66
|
+
const Comp = asChild ? reactSlot.Slot : "span";
|
|
67
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
68
|
+
Comp,
|
|
69
|
+
{
|
|
70
|
+
ref,
|
|
71
|
+
"data-testid": "badge",
|
|
72
|
+
className: cn.cn(
|
|
73
|
+
// Base styles
|
|
74
|
+
"typography-caption-semibold inline-flex h-5 items-center gap-2 rounded-full px-2",
|
|
75
|
+
// Variant styles
|
|
76
|
+
badgeVariants.variant[variant],
|
|
77
|
+
// Manual CSS overrides
|
|
78
|
+
className
|
|
79
|
+
),
|
|
80
|
+
...props,
|
|
81
|
+
children: [
|
|
82
|
+
leftIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex", "aria-hidden": "true", children: leftIcon }),
|
|
83
|
+
leftDot && /* @__PURE__ */ jsxRuntime.jsx(
|
|
84
|
+
"span",
|
|
85
|
+
{
|
|
86
|
+
className: cn.cn("size-1 shrink-0 rounded-full", badgeVariants.dotColor[variant]),
|
|
87
|
+
"aria-hidden": "true"
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slottable, { children }),
|
|
91
|
+
rightIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex", "aria-hidden": "true", children: rightIcon })
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
Badge.displayName = "Badge";
|
|
98
|
+
exports.Badge = Badge;
|
|
99
|
+
//# sourceMappingURL=Badge.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.cjs","sources":["../../../../src/components/Badge/Badge.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nconst badgeVariants = {\n variant: {\n default: \"bg-neutral-100 text-neutral-400\",\n dark: \"bg-background-800 text-body-300 dark:text-body-white-solid-constant\",\n success: \"bg-neutral-100 text-neutral-400\",\n warning: \"bg-neutral-100 text-neutral-400\",\n error: \"bg-neutral-100 text-neutral-400\",\n special: \"bg-neutral-100 text-neutral-400\",\n info: \"bg-neutral-100 text-neutral-400\",\n online: \"bg-background-200 text-brand-green-500\",\n brand: \"bg-brand-green-500 text-body-black-solid-constant\",\n pink: \"bg-brand-pink-500 text-body-black-solid-constant\",\n brandLight: \"bg-brand-green-50 text-body-black-solid-constant\",\n pinkLight: \"bg-brand-pink-50 text-body-black-solid-constant\",\n },\n dotColor: {\n default: \"bg-body-black-solid-constant\",\n dark: \"bg-body-300 dark:bg-body-white-solid-constant\",\n success: \"bg-success-500\",\n warning: \"bg-warning-500\",\n error: \"bg-error-500\",\n special: \"bg-special-500\",\n info: \"bg-info-500\",\n online: \"bg-brand-green-500\",\n brand: \"bg-body-black-solid-constant\",\n pink: \"bg-body-black-solid-constant\",\n brandLight: \"bg-body-black-solid-constant\",\n pinkLight: \"bg-body-black-solid-constant\",\n },\n} as const;\n\nexport type BadgeVariant = keyof typeof badgeVariants.variant;\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Visual style variant of the badge */\n variant?: BadgeVariant;\n /** Show left status indicator dot */\n leftDot?: boolean;\n /** Left icon element */\n leftIcon?: React.ReactNode;\n /** Right icon element */\n rightIcon?: React.ReactNode;\n /** Render as a different element using Radix Slot */\n asChild?: boolean;\n}\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n (\n {\n className,\n variant = \"default\",\n leftDot = true,\n leftIcon,\n rightIcon,\n asChild = false,\n children,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"span\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"badge\"\n className={cn(\n // Base styles\n \"typography-caption-semibold inline-flex h-5 items-center gap-2 rounded-full px-2\",\n // Variant styles\n badgeVariants.variant[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {leftIcon && (\n <span className=\"flex\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n {leftDot && (\n <span\n className={cn(\"size-1 shrink-0 rounded-full\", badgeVariants.dotColor[variant])}\n aria-hidden=\"true\"\n />\n )}\n <Slottable>{children}</Slottable>\n {rightIcon && (\n <span className=\"flex\" aria-hidden=\"true\">\n {rightIcon}\n </span>\n )}\n </Comp>\n );\n },\n);\n\nBadge.displayName = \"Badge\";\n"],"names":["React","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,gBAAgB;AAAA,EACpB,SAAS;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA;AAAA,EAEb,UAAU;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA;AAEf;AAiBO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,OAAO,UAAUC,UAAAA,OAAO;AAE9B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA;AAAAA,UAET;AAAA;AAAA,UAEA,cAAc,QAAQ,OAAO;AAAA;AAAA,UAE7B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,2CACE,QAAA,EAAK,WAAU,QAAO,eAAY,QAChC,UAAA,UACH;AAAA,UAED,WACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD,GAAAA,GAAG,gCAAgC,cAAc,SAAS,OAAO,CAAC;AAAA,cAC7E,eAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAGhBC,+BAACC,UAAAA,aAAW,UAAS;AAAA,UACpB,aACCD,2BAAAA,IAAC,QAAA,EAAK,WAAU,QAAO,eAAY,QAChC,UAAA,UAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
+
const reactSlot = require("@radix-ui/react-slot");
|
|
6
|
+
const React = require("react");
|
|
7
|
+
const cn = require("../../utils/cn.cjs");
|
|
8
|
+
const SpinnerIcon = require("../Icons/SpinnerIcon.cjs");
|
|
9
|
+
function _interopNamespaceDefault(e) {
|
|
10
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
11
|
+
if (e) {
|
|
12
|
+
for (const k in e) {
|
|
13
|
+
if (k !== "default") {
|
|
14
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: () => e[k]
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
26
|
+
const SIZE_CLASSES = {
|
|
27
|
+
"48": "h-12 px-4 py-3 typography-button-large",
|
|
28
|
+
"40": "h-10 px-4 py-2 typography-button-small",
|
|
29
|
+
"32": "h-8 px-3 py-2 typography-body-2-semibold",
|
|
30
|
+
"24": "h-6 px-0 py-1 typography-body-2-semibold"
|
|
31
|
+
};
|
|
32
|
+
const ICON_SIZE_CLASS = {
|
|
33
|
+
"48": "size-5",
|
|
34
|
+
"40": "size-5",
|
|
35
|
+
"32": "size-4",
|
|
36
|
+
"24": "size-3.5"
|
|
37
|
+
};
|
|
38
|
+
const VARIANT_CLASSES = {
|
|
39
|
+
primary: "bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant",
|
|
40
|
+
secondary: "border-body-100 border border-1 border-body-100 bg-transparent text-body-100 hover:bg-brand-green-50",
|
|
41
|
+
tertiary: "bg-transparent text-body-100 hover:bg-brand-green-50",
|
|
42
|
+
link: "bg-transparent text-body-100 underline decoration-solid hover:bg-brand-green-50",
|
|
43
|
+
brand: "bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-pink-500",
|
|
44
|
+
destructive: "bg-error-500 text-body-white-solid-constant hover:bg-background-solid dark:hover:bg-background-white-solid-constant dark:hover:text-error-500",
|
|
45
|
+
white: "bg-background-white-solid-constant text-body-black-solid-constant hover:bg-brand-green-500",
|
|
46
|
+
tertiaryDestructive: "bg-transparent text-error-500 hover:bg-error-50",
|
|
47
|
+
text: "bg-transparent text-body-100 hover:underline"
|
|
48
|
+
};
|
|
49
|
+
function getTextContent(node) {
|
|
50
|
+
if (typeof node === "string") return node;
|
|
51
|
+
if (typeof node === "number") return String(node);
|
|
52
|
+
if (React__namespace.isValidElement(node)) {
|
|
53
|
+
return getTextContent(node.props.children);
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(node)) {
|
|
56
|
+
const text = node.map(getTextContent).filter(Boolean).join("");
|
|
57
|
+
return text || void 0;
|
|
58
|
+
}
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
const LoadingSpinner = ({ size }) => {
|
|
62
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-spin", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon.SpinnerIcon, { className: ICON_SIZE_CLASS[size], children: /* @__PURE__ */ jsxRuntime.jsx("title", { children: "Loading" }) }) });
|
|
63
|
+
};
|
|
64
|
+
function renderContent({
|
|
65
|
+
loading,
|
|
66
|
+
asChild,
|
|
67
|
+
children,
|
|
68
|
+
size,
|
|
69
|
+
leftIcon,
|
|
70
|
+
rightIcon,
|
|
71
|
+
iconSizeClass,
|
|
72
|
+
discount,
|
|
73
|
+
price
|
|
74
|
+
}) {
|
|
75
|
+
if (loading) {
|
|
76
|
+
if (asChild && React__namespace.isValidElement(children)) {
|
|
77
|
+
return React__namespace.cloneElement(
|
|
78
|
+
children,
|
|
79
|
+
void 0,
|
|
80
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { size })
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
84
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { size }),
|
|
85
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children })
|
|
86
|
+
] });
|
|
87
|
+
}
|
|
88
|
+
if (asChild) return children;
|
|
89
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
90
|
+
leftIcon && /* @__PURE__ */ jsxRuntime.jsx(
|
|
91
|
+
"span",
|
|
92
|
+
{
|
|
93
|
+
className: cn.cn("flex shrink-0 items-center justify-center", iconSizeClass),
|
|
94
|
+
"aria-hidden": "true",
|
|
95
|
+
children: leftIcon
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
children,
|
|
99
|
+
rightIcon && /* @__PURE__ */ jsxRuntime.jsx(
|
|
100
|
+
"span",
|
|
101
|
+
{
|
|
102
|
+
className: cn.cn("flex shrink-0 items-center justify-center", iconSizeClass),
|
|
103
|
+
"aria-hidden": "true",
|
|
104
|
+
children: rightIcon
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
discount != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-body-1-regular line-through", "aria-hidden": "true", children: discount }),
|
|
108
|
+
price != null && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: price })
|
|
109
|
+
] });
|
|
110
|
+
}
|
|
111
|
+
const Button = React__namespace.forwardRef(
|
|
112
|
+
({
|
|
113
|
+
className,
|
|
114
|
+
variant = "primary",
|
|
115
|
+
size = "48",
|
|
116
|
+
leftIcon,
|
|
117
|
+
rightIcon,
|
|
118
|
+
loading = false,
|
|
119
|
+
asChild = false,
|
|
120
|
+
disabled,
|
|
121
|
+
children,
|
|
122
|
+
discount,
|
|
123
|
+
price,
|
|
124
|
+
...props
|
|
125
|
+
}, ref) => {
|
|
126
|
+
const Comp = asChild ? reactSlot.Slot : "button";
|
|
127
|
+
const isDisabled = disabled || loading;
|
|
128
|
+
const iconSizeClass = ICON_SIZE_CLASS[size];
|
|
129
|
+
const buttonSpecificProps = !asChild ? { "data-testid": "button", disabled: isDisabled } : isDisabled ? { "aria-disabled": true } : {};
|
|
130
|
+
const loadingLabelProps = loading && asChild ? { "aria-label": getTextContent(children) } : {};
|
|
131
|
+
const content = renderContent({
|
|
132
|
+
loading,
|
|
133
|
+
asChild,
|
|
134
|
+
children,
|
|
135
|
+
size,
|
|
136
|
+
leftIcon,
|
|
137
|
+
rightIcon,
|
|
138
|
+
iconSizeClass,
|
|
139
|
+
discount,
|
|
140
|
+
price
|
|
141
|
+
});
|
|
142
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
143
|
+
Comp,
|
|
144
|
+
{
|
|
145
|
+
ref,
|
|
146
|
+
...buttonSpecificProps,
|
|
147
|
+
"aria-busy": loading,
|
|
148
|
+
...loadingLabelProps,
|
|
149
|
+
className: cn.cn(
|
|
150
|
+
// Base styles
|
|
151
|
+
"inline-flex cursor-pointer items-center justify-center gap-2 rounded-full transition-colors",
|
|
152
|
+
// Focus ring
|
|
153
|
+
"focus:shadow-focus focus-visible:outline-none",
|
|
154
|
+
// Disabled state
|
|
155
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
156
|
+
"aria-disabled:pointer-events-none aria-disabled:opacity-50",
|
|
157
|
+
// Size styles
|
|
158
|
+
SIZE_CLASSES[size],
|
|
159
|
+
// Variant styles
|
|
160
|
+
VARIANT_CLASSES[variant],
|
|
161
|
+
// Manual CSS overrides
|
|
162
|
+
className
|
|
163
|
+
),
|
|
164
|
+
...props,
|
|
165
|
+
children: content
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
Button.displayName = "Button";
|
|
171
|
+
exports.Button = Button;
|
|
172
|
+
//# sourceMappingURL=Button.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button.cjs","sources":["../../../../src/components/Button/Button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\n\nexport type ButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"link\"\n | \"brand\"\n | \"destructive\"\n | \"white\"\n | \"tertiaryDestructive\"\n | \"text\";\n\nexport type ButtonSize = \"48\" | \"40\" | \"32\" | \"24\";\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant of the button */\n variant?: ButtonVariant;\n /** Size of the button in pixels */\n size?: ButtonSize;\n /** Left icon element */\n leftIcon?: React.ReactNode;\n /** Right icon element */\n rightIcon?: React.ReactNode;\n /** Show loading spinner */\n loading?: boolean;\n /** Render as a different element using Radix Slot */\n asChild?: boolean;\n /** Old price shown with strikethrough before the current price */\n discount?: string;\n /** Current price shown inside the button after the label/icons */\n price?: string;\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, string> = {\n \"48\": \"h-12 px-4 py-3 typography-button-large\",\n \"40\": \"h-10 px-4 py-2 typography-button-small\",\n \"32\": \"h-8 px-3 py-2 typography-body-2-semibold\",\n \"24\": \"h-6 px-0 py-1 typography-body-2-semibold\",\n};\n\nconst ICON_SIZE_CLASS: Record<ButtonSize, string> = {\n \"48\": \"size-5\",\n \"40\": \"size-5\",\n \"32\": \"size-4\",\n \"24\": \"size-3.5\",\n};\n\nconst VARIANT_CLASSES: Record<ButtonVariant, string> = {\n primary:\n \"bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant\",\n secondary:\n \"border-body-100 border border-1 border-body-100 bg-transparent text-body-100 hover:bg-brand-green-50\",\n tertiary: \"bg-transparent text-body-100 hover:bg-brand-green-50\",\n link: \"bg-transparent text-body-100 underline decoration-solid hover:bg-brand-green-50\",\n brand: \"bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-pink-500\",\n destructive:\n \"bg-error-500 text-body-white-solid-constant hover:bg-background-solid dark:hover:bg-background-white-solid-constant dark:hover:text-error-500\",\n white:\n \"bg-background-white-solid-constant text-body-black-solid-constant hover:bg-brand-green-500\",\n tertiaryDestructive: \"bg-transparent text-error-500 hover:bg-error-50\",\n text: \"bg-transparent text-body-100 hover:underline\",\n};\n\n/** Recursively extract text content from React nodes for accessible labels */\nfunction getTextContent(node: React.ReactNode): string | undefined {\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return String(node);\n if (React.isValidElement(node)) {\n return getTextContent((node.props as { children?: React.ReactNode }).children);\n }\n if (Array.isArray(node)) {\n const text = node.map(getTextContent).filter(Boolean).join(\"\");\n return text || undefined;\n }\n return undefined;\n}\n\nconst LoadingSpinner = ({ size }: { size: ButtonSize }) => {\n return (\n <span className=\"animate-spin\" aria-hidden=\"true\">\n <SpinnerIcon className={ICON_SIZE_CLASS[size]}>\n <title>Loading</title>\n </SpinnerIcon>\n </span>\n );\n};\n\nfunction renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n}: {\n loading: boolean;\n asChild: boolean;\n children: React.ReactNode;\n size: ButtonSize;\n leftIcon: React.ReactNode;\n rightIcon: React.ReactNode;\n iconSizeClass: string;\n discount?: string;\n price?: string;\n}) {\n if (loading) {\n // When asChild, clone the child element with spinner content instead of\n // wrapping in sr-only span (which would nest interactive elements)\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<{ children?: React.ReactNode }>,\n undefined,\n <LoadingSpinner size={size} />,\n );\n }\n return (\n <>\n <LoadingSpinner size={size} />\n <span className=\"sr-only\">{children}</span>\n </>\n );\n }\n\n if (asChild) return children;\n\n return (\n <>\n {leftIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {leftIcon}\n </span>\n )}\n {children}\n {rightIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {rightIcon}\n </span>\n )}\n {discount != null && (\n <span className=\"typography-body-1-regular line-through\" aria-hidden=\"true\">\n {discount}\n </span>\n )}\n {price != null && <span aria-hidden=\"true\">{price}</span>}\n </>\n );\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"48\",\n leftIcon,\n rightIcon,\n loading = false,\n asChild = false,\n disabled,\n children,\n discount,\n price,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n const isDisabled = disabled || loading;\n const iconSizeClass = ICON_SIZE_CLASS[size];\n\n const buttonSpecificProps = !asChild\n ? { \"data-testid\": \"button\", disabled: isDisabled }\n : isDisabled\n ? { \"aria-disabled\": true }\n : {};\n\n // When asChild + loading, extract text from children for aria-label since we\n // can't wrap element children in an sr-only span (creates invalid nested markup)\n const loadingLabelProps = loading && asChild ? { \"aria-label\": getTextContent(children) } : {};\n\n const content = renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n });\n\n return (\n <Comp\n ref={ref}\n {...buttonSpecificProps}\n aria-busy={loading}\n {...loadingLabelProps}\n className={cn(\n // Base styles\n \"inline-flex cursor-pointer items-center justify-center gap-2 rounded-full transition-colors\",\n // Focus ring\n \"focus:shadow-focus focus-visible:outline-none\",\n // Disabled state\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n // Size styles\n SIZE_CLASSES[size],\n // Variant styles\n VARIANT_CLASSES[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {content}\n </Comp>\n );\n },\n);\n\nButton.displayName = \"Button\";\n"],"names":["React","jsx","SpinnerIcon","jsxs","Fragment","cn","Slot"],"mappings":"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"}
|