@n3wth/ui 0.7.0 → 0.9.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/dist/atoms/AnimatedText/AnimatedText.js +65 -0
- package/dist/atoms/AnimatedText/AnimatedText.js.map +1 -0
- package/dist/atoms/Avatar/Avatar.js +55 -0
- package/dist/atoms/Avatar/Avatar.js.map +1 -0
- package/dist/atoms/Badge/Badge.js +57 -0
- package/dist/atoms/Badge/Badge.js.map +1 -0
- package/dist/atoms/Button/Button.js +92 -0
- package/dist/atoms/Button/Button.js.map +1 -0
- package/dist/atoms/Character/Character.js +155 -0
- package/dist/atoms/Character/Character.js.map +1 -0
- package/dist/atoms/CodeBlock/CodeBlock.js +75 -0
- package/dist/atoms/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/atoms/HamburgerIcon/HamburgerIcon.js +50 -0
- package/dist/atoms/HamburgerIcon/HamburgerIcon.js.map +1 -0
- package/dist/atoms/Icon/Icon.js +199 -0
- package/dist/atoms/Icon/Icon.js.map +1 -0
- package/dist/atoms/Input/Input.js +80 -0
- package/dist/atoms/Input/Input.js.map +1 -0
- package/dist/atoms/Label/Label.js +32 -0
- package/dist/atoms/Label/Label.js.map +1 -0
- package/dist/atoms/NoiseOverlay/NoiseOverlay.js +32 -0
- package/dist/atoms/NoiseOverlay/NoiseOverlay.js.map +1 -0
- package/dist/atoms/Progress/Progress.js +63 -0
- package/dist/atoms/Progress/Progress.js.map +1 -0
- package/dist/atoms/ScrollIndicator/ScrollIndicator.js +51 -0
- package/dist/atoms/ScrollIndicator/ScrollIndicator.js.map +1 -0
- package/dist/atoms/Separator/Separator.js +28 -0
- package/dist/atoms/Separator/Separator.js.map +1 -0
- package/dist/atoms/Shape/Shape.js +110 -0
- package/dist/atoms/Shape/Shape.js.map +1 -0
- package/dist/atoms/Shape/patterns.js +66 -0
- package/dist/atoms/Shape/patterns.js.map +1 -0
- package/dist/atoms/Skeleton/Skeleton.js +77 -0
- package/dist/atoms/Skeleton/Skeleton.js.map +1 -0
- package/dist/atoms/SpeechBubble/SpeechBubble.js +98 -0
- package/dist/atoms/SpeechBubble/SpeechBubble.js.map +1 -0
- package/dist/atoms/Switch/Switch.js +78 -0
- package/dist/atoms/Switch/Switch.js.map +1 -0
- package/dist/atoms/Textarea/Textarea.js +40 -0
- package/dist/atoms/Textarea/Textarea.js.map +1 -0
- package/dist/atoms/Tooltip/Tooltip.js +153 -0
- package/dist/atoms/Tooltip/Tooltip.js.map +1 -0
- package/dist/hooks/useButtonPulse.js +43 -0
- package/dist/hooks/useButtonPulse.js.map +1 -0
- package/dist/hooks/useCountUp.js +52 -0
- package/dist/hooks/useCountUp.js.map +1 -0
- package/dist/hooks/useKeyboardShortcuts.js +37 -0
- package/dist/hooks/useKeyboardShortcuts.js.map +1 -0
- package/dist/hooks/useMediaQuery.js +59 -0
- package/dist/hooks/useMediaQuery.js.map +1 -0
- package/dist/hooks/usePageTransition.js +39 -0
- package/dist/hooks/usePageTransition.js.map +1 -0
- package/dist/hooks/useReducedMotion.js +57 -0
- package/dist/hooks/useReducedMotion.js.map +1 -0
- package/dist/hooks/useScrollReveal.js +61 -0
- package/dist/hooks/useScrollReveal.js.map +1 -0
- package/dist/hooks/useStaggerList.js +54 -0
- package/dist/hooks/useStaggerList.js.map +1 -0
- package/dist/hooks/useTextReveal.js +59 -0
- package/dist/hooks/useTextReveal.js.map +1 -0
- package/dist/hooks/useTheme.js +37 -0
- package/dist/hooks/useTheme.js.map +1 -0
- package/dist/hooks/useToast.js +84 -0
- package/dist/hooks/useToast.js.map +1 -0
- package/dist/index.js +147 -7925
- package/dist/index.js.map +1 -1
- package/dist/molecules/Accordion/Accordion.js +178 -0
- package/dist/molecules/Accordion/Accordion.js.map +1 -0
- package/dist/molecules/Card/Card.js +104 -0
- package/dist/molecules/Card/Card.js.map +1 -0
- package/dist/molecules/CommandBox/CommandBox.js +65 -0
- package/dist/molecules/CommandBox/CommandBox.js.map +1 -0
- package/dist/molecules/CompositeShape/CompositeShape.js +69 -0
- package/dist/molecules/CompositeShape/CompositeShape.js.map +1 -0
- package/dist/molecules/CompositeShape/presets.js +71 -0
- package/dist/molecules/CompositeShape/presets.js.map +1 -0
- package/dist/molecules/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/molecules/Dropdown/Dropdown.js +530 -0
- package/dist/molecules/Dropdown/Dropdown.js.map +1 -0
- package/dist/molecules/ErrorBoundary/ErrorBoundary.js +128 -0
- package/dist/molecules/ErrorBoundary/ErrorBoundary.js.map +1 -0
- package/dist/molecules/MobileDrawer/MobileDrawer.js +78 -0
- package/dist/molecules/MobileDrawer/MobileDrawer.js.map +1 -0
- package/dist/molecules/Modal/Modal.js +262 -0
- package/dist/molecules/Modal/Modal.js.map +1 -0
- package/dist/molecules/NavLink/NavLink.js +38 -0
- package/dist/molecules/NavLink/NavLink.js.map +1 -0
- package/dist/molecules/Tabs/Tabs.js +188 -0
- package/dist/molecules/Tabs/Tabs.js.map +1 -0
- package/dist/molecules/ThemeToggle/ThemeToggle.js +48 -0
- package/dist/molecules/ThemeToggle/ThemeToggle.js.map +1 -0
- package/dist/molecules/Toast/Toast.js +156 -0
- package/dist/molecules/Toast/Toast.js.map +1 -0
- package/dist/node_modules/clsx/dist/clsx.js +17 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/IconoirContext.js +6 -0
- package/dist/node_modules/iconoir-react/dist/esm/IconoirContext.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowDown.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowDown.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowLeft.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowLeft.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowRight.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowRight.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUp.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUp.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUpRight.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUpRight.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Bell.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Bell.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Calendar.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Calendar.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Check.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Check.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/CheckCircle.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/CheckCircle.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Clock.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Clock.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Code.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Code.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Copy.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Copy.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Download.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Download.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/EditPencil.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/EditPencil.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Eye.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Eye.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/EyeClosed.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/EyeClosed.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Filter.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Filter.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Folder.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Folder.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Github.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Github.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/HalfMoon.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/HalfMoon.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Heart.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Heart.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Home.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Home.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/InfoCircle.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/InfoCircle.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Link.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Link.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/List.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/List.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Lock.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Lock.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/LockSlash.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/LockSlash.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Mail.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Mail.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Menu.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Menu.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Minus.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Minus.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/MoreHoriz.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/MoreHoriz.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/MoreVert.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/MoreVert.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowDown.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowDown.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowLeft.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowLeft.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowRight.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowRight.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowUp.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowUp.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/OpenInWindow.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/OpenInWindow.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Page.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Page.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Plus.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Plus.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/RefreshDouble.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/RefreshDouble.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Search.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Search.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Settings.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Settings.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/SortDown.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/SortDown.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Sparks.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Sparks.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Star.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Star.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/SunLight.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/SunLight.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Terminal.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Terminal.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Trash.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Trash.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Upload.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Upload.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/User.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/User.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ViewGrid.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/ViewGrid.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/WarningTriangle.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/WarningTriangle.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Xmark.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/Xmark.js.map +1 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/XmarkCircle.js +17 -0
- package/dist/node_modules/iconoir-react/dist/esm/regular/XmarkCircle.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +2996 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/dist/organisms/Footer/Footer.js +108 -0
- package/dist/organisms/Footer/Footer.js.map +1 -0
- package/dist/organisms/Hero/Hero.d.ts.map +1 -1
- package/dist/organisms/Hero/Hero.js +101 -0
- package/dist/organisms/Hero/Hero.js.map +1 -0
- package/dist/organisms/Nav/Nav.js +177 -0
- package/dist/organisms/Nav/Nav.js.map +1 -0
- package/dist/organisms/Section/Section.js +57 -0
- package/dist/organisms/Section/Section.js.map +1 -0
- package/dist/theme.css +86 -0
- package/dist/tokens/colors.js +105 -0
- package/dist/tokens/colors.js.map +1 -0
- package/dist/tokens/effects.js +26 -0
- package/dist/tokens/effects.js.map +1 -0
- package/dist/tokens/motion.js +25 -0
- package/dist/tokens/motion.js.map +1 -0
- package/dist/tokens/spacing.js +31 -0
- package/dist/tokens/spacing.js.map +1 -0
- package/dist/tokens/typography.js +63 -0
- package/dist/tokens/typography.js.map +1 -0
- package/dist/utils/cn.js +9 -0
- package/dist/utils/cn.js.map +1 -0
- package/package.json +8 -5
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
var d = Object.defineProperty;
|
|
2
|
+
var h = (t, o, e) => o in t ? d(t, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[o] = e;
|
|
3
|
+
var n = (t, o, e) => h(t, typeof o != "symbol" ? o + "" : o, e);
|
|
4
|
+
import { jsx as r, jsxs as l } from "react/jsx-runtime";
|
|
5
|
+
import { Component as m } from "react";
|
|
6
|
+
import { cn as a } from "../../utils/cn.js";
|
|
7
|
+
class v extends m {
|
|
8
|
+
constructor(e) {
|
|
9
|
+
super(e);
|
|
10
|
+
n(this, "handleRetry", () => {
|
|
11
|
+
this.setState({ hasError: !1, error: null });
|
|
12
|
+
});
|
|
13
|
+
this.state = { hasError: !1, error: null };
|
|
14
|
+
}
|
|
15
|
+
static getDerivedStateFromError(e) {
|
|
16
|
+
return { hasError: !0, error: e };
|
|
17
|
+
}
|
|
18
|
+
componentDidCatch(e, s) {
|
|
19
|
+
this.props.onError?.(e, s);
|
|
20
|
+
}
|
|
21
|
+
render() {
|
|
22
|
+
return this.state.hasError ? this.props.fallback ? this.props.fallback : /* @__PURE__ */ r("div", { className: "min-h-[400px] flex items-center justify-center p-8", children: /* @__PURE__ */ l("div", { className: "text-center max-w-md", children: [
|
|
23
|
+
/* @__PURE__ */ r("div", { className: "w-16 h-16 mx-auto mb-6 rounded-full bg-[var(--color-coral)]/10 flex items-center justify-center", children: /* @__PURE__ */ r(
|
|
24
|
+
"svg",
|
|
25
|
+
{
|
|
26
|
+
className: "w-8 h-8 text-[var(--color-coral)]",
|
|
27
|
+
fill: "none",
|
|
28
|
+
viewBox: "0 0 24 24",
|
|
29
|
+
stroke: "currentColor",
|
|
30
|
+
children: /* @__PURE__ */ r(
|
|
31
|
+
"path",
|
|
32
|
+
{
|
|
33
|
+
strokeLinecap: "round",
|
|
34
|
+
strokeLinejoin: "round",
|
|
35
|
+
strokeWidth: 2,
|
|
36
|
+
d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
) }),
|
|
41
|
+
/* @__PURE__ */ r("h2", { className: "text-xl font-semibold text-[var(--color-white)] mb-2", children: "Something went wrong" }),
|
|
42
|
+
/* @__PURE__ */ r("p", { className: "text-[var(--color-grey-400)] mb-6", children: "We encountered an unexpected error. Please try again." }),
|
|
43
|
+
/* @__PURE__ */ r(
|
|
44
|
+
"button",
|
|
45
|
+
{
|
|
46
|
+
onClick: this.handleRetry,
|
|
47
|
+
className: a(
|
|
48
|
+
"px-6 py-3 rounded-full font-medium",
|
|
49
|
+
"bg-[var(--glass-bg)] border border-[var(--glass-border)]",
|
|
50
|
+
"hover:bg-[var(--glass-highlight)] transition-colors"
|
|
51
|
+
),
|
|
52
|
+
children: "Try Again"
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
] }) }) : this.props.children;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function f({
|
|
59
|
+
title: t = "Page Error",
|
|
60
|
+
message: o = "This page encountered an error and could not be displayed.",
|
|
61
|
+
showReload: e = !0,
|
|
62
|
+
showHomeLink: s = !0,
|
|
63
|
+
homeUrl: i = "/",
|
|
64
|
+
className: c
|
|
65
|
+
}) {
|
|
66
|
+
return /* @__PURE__ */ r(
|
|
67
|
+
"div",
|
|
68
|
+
{
|
|
69
|
+
className: a(
|
|
70
|
+
"min-h-screen flex items-center justify-center p-8",
|
|
71
|
+
c
|
|
72
|
+
),
|
|
73
|
+
children: /* @__PURE__ */ l("div", { className: "text-center max-w-md", children: [
|
|
74
|
+
/* @__PURE__ */ r("div", { className: "w-20 h-20 mx-auto mb-8 rounded-full bg-[var(--color-coral)]/10 flex items-center justify-center", children: /* @__PURE__ */ r(
|
|
75
|
+
"svg",
|
|
76
|
+
{
|
|
77
|
+
className: "w-10 h-10 text-[var(--color-coral)]",
|
|
78
|
+
fill: "none",
|
|
79
|
+
viewBox: "0 0 24 24",
|
|
80
|
+
stroke: "currentColor",
|
|
81
|
+
children: /* @__PURE__ */ r(
|
|
82
|
+
"path",
|
|
83
|
+
{
|
|
84
|
+
strokeLinecap: "round",
|
|
85
|
+
strokeLinejoin: "round",
|
|
86
|
+
strokeWidth: 2,
|
|
87
|
+
d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
) }),
|
|
92
|
+
/* @__PURE__ */ r("h1", { className: "text-2xl font-semibold text-[var(--color-white)] mb-3", children: t }),
|
|
93
|
+
/* @__PURE__ */ r("p", { className: "text-[var(--color-grey-400)] mb-8", children: o }),
|
|
94
|
+
/* @__PURE__ */ l("div", { className: "flex gap-4 justify-center", children: [
|
|
95
|
+
e && /* @__PURE__ */ r(
|
|
96
|
+
"button",
|
|
97
|
+
{
|
|
98
|
+
onClick: () => window.location.reload(),
|
|
99
|
+
className: a(
|
|
100
|
+
"px-6 py-3 rounded-full font-medium",
|
|
101
|
+
"bg-[var(--glass-bg)] border border-[var(--glass-border)]",
|
|
102
|
+
"hover:bg-[var(--glass-highlight)] transition-colors"
|
|
103
|
+
),
|
|
104
|
+
children: "Reload Page"
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
s && /* @__PURE__ */ r(
|
|
108
|
+
"a",
|
|
109
|
+
{
|
|
110
|
+
href: i,
|
|
111
|
+
className: a(
|
|
112
|
+
"px-6 py-3 rounded-full font-medium",
|
|
113
|
+
"bg-[var(--glass-bg)] border border-[var(--glass-border)]",
|
|
114
|
+
"hover:bg-[var(--glass-highlight)] transition-colors"
|
|
115
|
+
),
|
|
116
|
+
children: "Go Home"
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
] })
|
|
120
|
+
] })
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
v as ErrorBoundary,
|
|
126
|
+
f as ErrorFallback
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=ErrorBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.js","sources":["../../../src/molecules/ErrorBoundary/ErrorBoundary.tsx"],"sourcesContent":["import { Component, type ReactNode } from 'react'\nimport { cn } from '../../utils/cn'\n\nexport interface ErrorBoundaryProps {\n /** Child components to wrap */\n children: ReactNode\n /** Custom fallback UI */\n fallback?: ReactNode\n /** Callback when error is caught */\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\n/**\n * Error boundary component that catches JavaScript errors in child components\n * Displays fallback UI and optionally reports errors via callback\n */\nexport class ErrorBoundary extends Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props)\n this.state = { hasError: false, error: null }\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.props.onError?.(error, errorInfo)\n }\n\n handleRetry = (): void => {\n this.setState({ hasError: false, error: null })\n }\n\n render(): ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback\n }\n\n return (\n <div className=\"min-h-[400px] flex items-center justify-center p-8\">\n <div className=\"text-center max-w-md\">\n <div className=\"w-16 h-16 mx-auto mb-6 rounded-full bg-[var(--color-coral)]/10 flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-[var(--color-coral)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <h2 className=\"text-xl font-semibold text-[var(--color-white)] mb-2\">\n Something went wrong\n </h2>\n <p className=\"text-[var(--color-grey-400)] mb-6\">\n We encountered an unexpected error. Please try again.\n </p>\n <button\n onClick={this.handleRetry}\n className={cn(\n 'px-6 py-3 rounded-full font-medium',\n 'bg-[var(--glass-bg)] border border-[var(--glass-border)]',\n 'hover:bg-[var(--glass-highlight)] transition-colors'\n )}\n >\n Try Again\n </button>\n </div>\n </div>\n )\n }\n\n return this.props.children\n }\n}\n\nexport interface ErrorFallbackProps {\n /** Error title */\n title?: string\n /** Error message */\n message?: string\n /** Show reload button */\n showReload?: boolean\n /** Show home link */\n showHomeLink?: boolean\n /** Home URL (default: /) */\n homeUrl?: string\n /** Additional class names */\n className?: string\n}\n\n/**\n * Standalone error fallback component for full-page errors\n */\nexport function ErrorFallback({\n title = 'Page Error',\n message = 'This page encountered an error and could not be displayed.',\n showReload = true,\n showHomeLink = true,\n homeUrl = '/',\n className,\n}: ErrorFallbackProps) {\n return (\n <div\n className={cn(\n 'min-h-screen flex items-center justify-center p-8',\n className\n )}\n >\n <div className=\"text-center max-w-md\">\n <div className=\"w-20 h-20 mx-auto mb-8 rounded-full bg-[var(--color-coral)]/10 flex items-center justify-center\">\n <svg\n className=\"w-10 h-10 text-[var(--color-coral)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-semibold text-[var(--color-white)] mb-3\">\n {title}\n </h1>\n <p className=\"text-[var(--color-grey-400)] mb-8\">{message}</p>\n <div className=\"flex gap-4 justify-center\">\n {showReload && (\n <button\n onClick={() => window.location.reload()}\n className={cn(\n 'px-6 py-3 rounded-full font-medium',\n 'bg-[var(--glass-bg)] border border-[var(--glass-border)]',\n 'hover:bg-[var(--glass-highlight)] transition-colors'\n )}\n >\n Reload Page\n </button>\n )}\n {showHomeLink && (\n <a\n href={homeUrl}\n className={cn(\n 'px-6 py-3 rounded-full font-medium',\n 'bg-[var(--glass-bg)] border border-[var(--glass-border)]',\n 'hover:bg-[var(--glass-highlight)] transition-colors'\n )}\n >\n Go Home\n </a>\n )}\n </div>\n </div>\n </div>\n )\n}\n"],"names":["ErrorBoundary","Component","props","__publicField","error","errorInfo","jsxs","jsx","cn","ErrorFallback","title","message","showReload","showHomeLink","homeUrl","className"],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsxs as k, jsx as u } from "react/jsx-runtime";
|
|
2
|
+
import { useRef as f, useEffect as l, useCallback as p } from "react";
|
|
3
|
+
import { cn as m } from "../../utils/cn.js";
|
|
4
|
+
function j({
|
|
5
|
+
isOpen: e,
|
|
6
|
+
onClose: o,
|
|
7
|
+
children: b,
|
|
8
|
+
width: y = "280px",
|
|
9
|
+
position: i = "right",
|
|
10
|
+
zIndex: s = 50,
|
|
11
|
+
ariaLabel: v = "Navigation menu",
|
|
12
|
+
className: h,
|
|
13
|
+
...x
|
|
14
|
+
}) {
|
|
15
|
+
const r = f(null), a = f(null);
|
|
16
|
+
l(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "", () => {
|
|
17
|
+
document.body.style.overflow = "";
|
|
18
|
+
}), [e]), l(() => {
|
|
19
|
+
const t = (n) => {
|
|
20
|
+
n.key === "Escape" && e && o();
|
|
21
|
+
};
|
|
22
|
+
return document.addEventListener("keydown", t), () => document.removeEventListener("keydown", t);
|
|
23
|
+
}, [e, o]), l(() => {
|
|
24
|
+
e ? (a.current = document.activeElement, r.current?.querySelector(
|
|
25
|
+
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
26
|
+
)?.focus()) : a.current && (a.current.focus(), a.current = null);
|
|
27
|
+
}, [e]);
|
|
28
|
+
const E = p((t) => {
|
|
29
|
+
if (t.key !== "Tab" || !r.current) return;
|
|
30
|
+
const n = r.current.querySelectorAll(
|
|
31
|
+
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
32
|
+
), d = n[0], c = n[n.length - 1];
|
|
33
|
+
t.shiftKey && document.activeElement === d ? (t.preventDefault(), c?.focus()) : !t.shiftKey && document.activeElement === c && (t.preventDefault(), d?.focus());
|
|
34
|
+
}, []), w = i === "right" ? e ? "translate-x-0" : "translate-x-full" : e ? "translate-x-0" : "-translate-x-full", g = i === "right" ? "right-0" : "left-0";
|
|
35
|
+
return /* @__PURE__ */ k("div", { className: h, children: [
|
|
36
|
+
/* @__PURE__ */ u(
|
|
37
|
+
"div",
|
|
38
|
+
{
|
|
39
|
+
className: m(
|
|
40
|
+
"fixed inset-0 bg-black/50 transition-opacity duration-300",
|
|
41
|
+
e ? "opacity-100" : "opacity-0 pointer-events-none"
|
|
42
|
+
),
|
|
43
|
+
style: { zIndex: s },
|
|
44
|
+
onClick: o,
|
|
45
|
+
"aria-hidden": "true"
|
|
46
|
+
}
|
|
47
|
+
),
|
|
48
|
+
/* @__PURE__ */ u(
|
|
49
|
+
"div",
|
|
50
|
+
{
|
|
51
|
+
ref: r,
|
|
52
|
+
role: "dialog",
|
|
53
|
+
"aria-modal": e,
|
|
54
|
+
"aria-label": v,
|
|
55
|
+
"aria-hidden": !e,
|
|
56
|
+
className: m(
|
|
57
|
+
"mobile-menu-drawer",
|
|
58
|
+
"fixed top-0 h-full",
|
|
59
|
+
"transition-transform duration-300 ease-out",
|
|
60
|
+
w,
|
|
61
|
+
g
|
|
62
|
+
),
|
|
63
|
+
style: {
|
|
64
|
+
width: y,
|
|
65
|
+
maxWidth: "80vw",
|
|
66
|
+
zIndex: s + 1
|
|
67
|
+
},
|
|
68
|
+
onKeyDown: E,
|
|
69
|
+
...x,
|
|
70
|
+
children: b
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
] });
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
j as MobileDrawer
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=MobileDrawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MobileDrawer.js","sources":["../../../src/molecules/MobileDrawer/MobileDrawer.tsx"],"sourcesContent":["import { type HTMLAttributes, type ReactNode, useEffect, useRef, useCallback } from 'react'\nimport { cn } from '../../utils/cn'\n\nexport interface MobileDrawerProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether the drawer is open */\n isOpen: boolean\n /** Callback when drawer should close */\n onClose: () => void\n /** Drawer content */\n children: ReactNode\n /** Width of the drawer */\n width?: string\n /** Position of the drawer */\n position?: 'left' | 'right'\n /** Z-index for the drawer */\n zIndex?: number\n /** Accessible label for the drawer */\n ariaLabel?: string\n}\n\nexport function MobileDrawer({\n isOpen,\n onClose,\n children,\n width = '280px',\n position = 'right',\n zIndex = 50,\n ariaLabel = 'Navigation menu',\n className,\n ...props\n}: MobileDrawerProps) {\n const drawerRef = useRef<HTMLDivElement>(null)\n const previousActiveElement = useRef<HTMLElement | null>(null)\n\n // Lock body scroll when open\n useEffect(() => {\n if (isOpen) {\n document.body.style.overflow = 'hidden'\n } else {\n document.body.style.overflow = ''\n }\n return () => {\n document.body.style.overflow = ''\n }\n }, [isOpen])\n\n // Handle escape key\n useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isOpen) {\n onClose()\n }\n }\n document.addEventListener('keydown', handleEscape)\n return () => document.removeEventListener('keydown', handleEscape)\n }, [isOpen, onClose])\n\n // Focus management\n useEffect(() => {\n if (isOpen) {\n previousActiveElement.current = document.activeElement as HTMLElement\n // Focus first focusable element in drawer\n const firstFocusable = drawerRef.current?.querySelector<HTMLElement>(\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n )\n firstFocusable?.focus()\n } else if (previousActiveElement.current) {\n previousActiveElement.current.focus()\n previousActiveElement.current = null\n }\n }, [isOpen])\n\n // Focus trap\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key !== 'Tab' || !drawerRef.current) return\n\n const focusableElements = drawerRef.current.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n )\n const firstElement = focusableElements[0]\n const lastElement = focusableElements[focusableElements.length - 1]\n\n if (e.shiftKey && document.activeElement === firstElement) {\n e.preventDefault()\n lastElement?.focus()\n } else if (!e.shiftKey && document.activeElement === lastElement) {\n e.preventDefault()\n firstElement?.focus()\n }\n }, [])\n\n const translateClass =\n position === 'right'\n ? isOpen\n ? 'translate-x-0'\n : 'translate-x-full'\n : isOpen\n ? 'translate-x-0'\n : '-translate-x-full'\n\n const positionClass = position === 'right' ? 'right-0' : 'left-0'\n\n return (\n <div className={className}>\n {/* Backdrop overlay */}\n <div\n className={cn(\n 'fixed inset-0 bg-black/50 transition-opacity duration-300',\n isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'\n )}\n style={{ zIndex }}\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n {/* Drawer panel */}\n <div\n ref={drawerRef}\n role=\"dialog\"\n aria-modal={isOpen}\n aria-label={ariaLabel}\n aria-hidden={!isOpen}\n className={cn(\n 'mobile-menu-drawer',\n 'fixed top-0 h-full',\n 'transition-transform duration-300 ease-out',\n translateClass,\n positionClass\n )}\n style={{\n width,\n maxWidth: '80vw',\n zIndex: zIndex + 1,\n }}\n onKeyDown={handleKeyDown}\n {...props}\n >\n {children}\n </div>\n </div>\n )\n}\n"],"names":["MobileDrawer","isOpen","onClose","children","width","position","zIndex","ariaLabel","className","props","drawerRef","useRef","previousActiveElement","useEffect","handleEscape","e","handleKeyDown","useCallback","focusableElements","firstElement","lastElement","translateClass","positionClass","jsxs","jsx","cn"],"mappings":";;;AAoBO,SAASA,EAAa;AAAA,EAC3B,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AAAA,EACX,QAAAC,IAAS;AAAA,EACT,WAAAC,IAAY;AAAA,EACZ,WAAAC;AAAA,EACA,GAAGC;AACL,GAAsB;AACpB,QAAMC,IAAYC,EAAuB,IAAI,GACvCC,IAAwBD,EAA2B,IAAI;AAG7D,EAAAE,EAAU,OACJZ,IACF,SAAS,KAAK,MAAM,WAAW,WAE/B,SAAS,KAAK,MAAM,WAAW,IAE1B,MAAM;AACX,aAAS,KAAK,MAAM,WAAW;AAAA,EACjC,IACC,CAACA,CAAM,CAAC,GAGXY,EAAU,MAAM;AACd,UAAMC,IAAe,CAACC,MAAqB;AACzC,MAAIA,EAAE,QAAQ,YAAYd,KACxBC,EAAA;AAAA,IAEJ;AACA,oBAAS,iBAAiB,WAAWY,CAAY,GAC1C,MAAM,SAAS,oBAAoB,WAAWA,CAAY;AAAA,EACnE,GAAG,CAACb,GAAQC,CAAO,CAAC,GAGpBW,EAAU,MAAM;AACd,IAAIZ,KACFW,EAAsB,UAAU,SAAS,eAElBF,EAAU,SAAS;AAAA,MACxC;AAAA,IAAA,GAEc,MAAA,KACPE,EAAsB,YAC/BA,EAAsB,QAAQ,MAAA,GAC9BA,EAAsB,UAAU;AAAA,EAEpC,GAAG,CAACX,CAAM,CAAC;AAGX,QAAMe,IAAgBC,EAAY,CAACF,MAA2B;AAC5D,QAAIA,EAAE,QAAQ,SAAS,CAACL,EAAU,QAAS;AAE3C,UAAMQ,IAAoBR,EAAU,QAAQ;AAAA,MAC1C;AAAA,IAAA,GAEIS,IAAeD,EAAkB,CAAC,GAClCE,IAAcF,EAAkBA,EAAkB,SAAS,CAAC;AAElE,IAAIH,EAAE,YAAY,SAAS,kBAAkBI,KAC3CJ,EAAE,eAAA,GACFK,GAAa,MAAA,KACJ,CAACL,EAAE,YAAY,SAAS,kBAAkBK,MACnDL,EAAE,eAAA,GACFI,GAAc,MAAA;AAAA,EAElB,GAAG,CAAA,CAAE,GAECE,IACJhB,MAAa,UACTJ,IACE,kBACA,qBACFA,IACE,kBACA,qBAEFqB,IAAgBjB,MAAa,UAAU,YAAY;AAEzD,SACE,gBAAAkB,EAAC,SAAI,WAAAf,GAEH,UAAA;AAAA,IAAA,gBAAAgB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWC;AAAA,UACT;AAAA,UACAxB,IAAS,gBAAgB;AAAA,QAAA;AAAA,QAE3B,OAAO,EAAE,QAAAK,EAAA;AAAA,QACT,SAASJ;AAAA,QACT,eAAY;AAAA,MAAA;AAAA,IAAA;AAAA,IAId,gBAAAsB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKd;AAAA,QACL,MAAK;AAAA,QACL,cAAYT;AAAA,QACZ,cAAYM;AAAA,QACZ,eAAa,CAACN;AAAA,QACd,WAAWwB;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACAJ;AAAA,UACAC;AAAA,QAAA;AAAA,QAEF,OAAO;AAAA,UACL,OAAAlB;AAAA,UACA,UAAU;AAAA,UACV,QAAQE,IAAS;AAAA,QAAA;AAAA,QAEnB,WAAWU;AAAA,QACV,GAAGP;AAAA,QAEH,UAAAN;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as I, useRef as w, useId as k, useState as M, useEffect as u, useCallback as N } from "react";
|
|
3
|
+
import { createPortal as R } from "react-dom";
|
|
4
|
+
import { cn as s } from "../../utils/cn.js";
|
|
5
|
+
const E = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])', S = {
|
|
6
|
+
sm: "max-w-[400px]",
|
|
7
|
+
md: "max-w-[560px]",
|
|
8
|
+
lg: "max-w-[720px]",
|
|
9
|
+
full: "max-w-none w-screen h-[100dvh] !rounded-none"
|
|
10
|
+
}, q = I(
|
|
11
|
+
({
|
|
12
|
+
isOpen: t,
|
|
13
|
+
onClose: o,
|
|
14
|
+
children: r,
|
|
15
|
+
size: l = "md",
|
|
16
|
+
closeOnBackdropClick: i = !0,
|
|
17
|
+
closeOnEscape: m = !0,
|
|
18
|
+
ariaLabel: f,
|
|
19
|
+
className: T,
|
|
20
|
+
...D
|
|
21
|
+
}, B) => {
|
|
22
|
+
const C = w(null), d = B || C, c = w(null), y = k(), b = k(), [F, p] = M(!1), [v, x] = M(!1);
|
|
23
|
+
u(() => {
|
|
24
|
+
if (t)
|
|
25
|
+
p(!0), requestAnimationFrame(() => {
|
|
26
|
+
requestAnimationFrame(() => {
|
|
27
|
+
x(!0);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
else {
|
|
31
|
+
x(!1);
|
|
32
|
+
const e = setTimeout(() => p(!1), 200);
|
|
33
|
+
return () => clearTimeout(e);
|
|
34
|
+
}
|
|
35
|
+
}, [t]), u(() => {
|
|
36
|
+
if (t) {
|
|
37
|
+
const e = window.scrollY;
|
|
38
|
+
document.body.style.overflow = "hidden", document.body.style.position = "fixed", document.body.style.top = `-${e}px`, document.body.style.width = "100%";
|
|
39
|
+
} else {
|
|
40
|
+
const e = document.body.style.top;
|
|
41
|
+
document.body.style.overflow = "", document.body.style.position = "", document.body.style.top = "", document.body.style.width = "", e && window.scrollTo(0, parseInt(e, 10) * -1);
|
|
42
|
+
}
|
|
43
|
+
return () => {
|
|
44
|
+
document.body.style.overflow = "", document.body.style.position = "", document.body.style.top = "", document.body.style.width = "";
|
|
45
|
+
};
|
|
46
|
+
}, [t]), u(() => {
|
|
47
|
+
if (!m || !t) return;
|
|
48
|
+
const e = (n) => {
|
|
49
|
+
n.key === "Escape" && (n.stopPropagation(), o());
|
|
50
|
+
};
|
|
51
|
+
return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
|
|
52
|
+
}, [t, o, m]), u(() => {
|
|
53
|
+
if (t) {
|
|
54
|
+
c.current = document.activeElement;
|
|
55
|
+
const e = d.current;
|
|
56
|
+
if (e) {
|
|
57
|
+
const n = e.querySelector(E);
|
|
58
|
+
n ? n.focus() : e.focus();
|
|
59
|
+
}
|
|
60
|
+
} else c.current && (c.current.focus(), c.current = null);
|
|
61
|
+
}, [t, d]);
|
|
62
|
+
const j = N(
|
|
63
|
+
(e) => {
|
|
64
|
+
if (e.key !== "Tab" || !d.current) return;
|
|
65
|
+
const n = d.current.querySelectorAll(E);
|
|
66
|
+
if (n.length === 0) {
|
|
67
|
+
e.preventDefault();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const g = n[0], h = n[n.length - 1];
|
|
71
|
+
e.shiftKey && document.activeElement === g ? (e.preventDefault(), h?.focus()) : !e.shiftKey && document.activeElement === h && (e.preventDefault(), g?.focus());
|
|
72
|
+
},
|
|
73
|
+
[d]
|
|
74
|
+
), A = N(
|
|
75
|
+
(e) => {
|
|
76
|
+
i && e.target === e.currentTarget && o();
|
|
77
|
+
},
|
|
78
|
+
[i, o]
|
|
79
|
+
);
|
|
80
|
+
return F ? R(
|
|
81
|
+
/* @__PURE__ */ a(
|
|
82
|
+
"div",
|
|
83
|
+
{
|
|
84
|
+
className: s(
|
|
85
|
+
"fixed inset-0 z-50 flex items-center justify-center",
|
|
86
|
+
// Backdrop
|
|
87
|
+
"transition-[background-color,backdrop-filter] duration-200 ease-out",
|
|
88
|
+
v ? "bg-black/60 backdrop-blur-sm" : "bg-black/0 backdrop-blur-none",
|
|
89
|
+
// Reduced motion: instant transitions
|
|
90
|
+
"motion-reduce:transition-none"
|
|
91
|
+
),
|
|
92
|
+
onClick: A,
|
|
93
|
+
"aria-hidden": "true",
|
|
94
|
+
children: /* @__PURE__ */ a(
|
|
95
|
+
"div",
|
|
96
|
+
{
|
|
97
|
+
ref: d,
|
|
98
|
+
role: "dialog",
|
|
99
|
+
"aria-modal": "true",
|
|
100
|
+
"aria-labelledby": f ? void 0 : y,
|
|
101
|
+
"aria-label": f,
|
|
102
|
+
"aria-describedby": b,
|
|
103
|
+
tabIndex: -1,
|
|
104
|
+
className: s(
|
|
105
|
+
"relative w-full mx-4",
|
|
106
|
+
S[l],
|
|
107
|
+
// Glass panel styling
|
|
108
|
+
"bg-[var(--color-bg-secondary)] border border-[var(--glass-border)]",
|
|
109
|
+
"backdrop-blur-lg",
|
|
110
|
+
l !== "full" && "rounded-2xl",
|
|
111
|
+
// Focus ring
|
|
112
|
+
"focus-ring",
|
|
113
|
+
// Animation
|
|
114
|
+
"transition-[opacity,transform] duration-200 ease-out",
|
|
115
|
+
v ? "opacity-100 scale-100 translate-y-0" : "opacity-0 scale-95 translate-y-2",
|
|
116
|
+
// Reduced motion: no scale/translate, instant
|
|
117
|
+
"motion-reduce:transition-none motion-reduce:transform-none",
|
|
118
|
+
T
|
|
119
|
+
),
|
|
120
|
+
onKeyDown: j,
|
|
121
|
+
"data-modal-label-id": y,
|
|
122
|
+
"data-modal-description-id": b,
|
|
123
|
+
...D,
|
|
124
|
+
children: r
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
document.body
|
|
130
|
+
) : null;
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
q.displayName = "Modal";
|
|
134
|
+
function K({ children: t, className: o, ...r }) {
|
|
135
|
+
return /* @__PURE__ */ a(
|
|
136
|
+
"div",
|
|
137
|
+
{
|
|
138
|
+
className: s(
|
|
139
|
+
"px-6 pt-6 pb-0",
|
|
140
|
+
"flex items-start justify-between gap-4",
|
|
141
|
+
o
|
|
142
|
+
),
|
|
143
|
+
...r,
|
|
144
|
+
children: t
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
K.displayName = "ModalHeader";
|
|
149
|
+
function L({ children: t, as: o = "h2", className: r, id: l, ...i }) {
|
|
150
|
+
return /* @__PURE__ */ a(
|
|
151
|
+
o,
|
|
152
|
+
{
|
|
153
|
+
id: l,
|
|
154
|
+
className: s(
|
|
155
|
+
"font-display text-lg font-semibold text-[var(--color-white)]",
|
|
156
|
+
"tracking-tight",
|
|
157
|
+
r
|
|
158
|
+
),
|
|
159
|
+
...i,
|
|
160
|
+
children: t
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
L.displayName = "ModalTitle";
|
|
165
|
+
function H({ children: t, className: o, id: r, ...l }) {
|
|
166
|
+
return /* @__PURE__ */ a(
|
|
167
|
+
"p",
|
|
168
|
+
{
|
|
169
|
+
id: r,
|
|
170
|
+
className: s(
|
|
171
|
+
"text-sm text-[var(--color-grey-400)]",
|
|
172
|
+
"mt-1",
|
|
173
|
+
o
|
|
174
|
+
),
|
|
175
|
+
...l,
|
|
176
|
+
children: t
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
H.displayName = "ModalDescription";
|
|
181
|
+
function P({ children: t, className: o, ...r }) {
|
|
182
|
+
return /* @__PURE__ */ a(
|
|
183
|
+
"div",
|
|
184
|
+
{
|
|
185
|
+
className: s(
|
|
186
|
+
"px-6 py-4",
|
|
187
|
+
"overflow-y-auto",
|
|
188
|
+
o
|
|
189
|
+
),
|
|
190
|
+
...r,
|
|
191
|
+
children: t
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
P.displayName = "ModalBody";
|
|
196
|
+
function Y({ children: t, className: o, ...r }) {
|
|
197
|
+
return /* @__PURE__ */ a(
|
|
198
|
+
"div",
|
|
199
|
+
{
|
|
200
|
+
className: s(
|
|
201
|
+
"px-6 pb-6 pt-0",
|
|
202
|
+
"border-t border-[var(--glass-border)]",
|
|
203
|
+
"mt-2 pt-4",
|
|
204
|
+
"flex items-center justify-end gap-3",
|
|
205
|
+
o
|
|
206
|
+
),
|
|
207
|
+
...r,
|
|
208
|
+
children: t
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
Y.displayName = "ModalFooter";
|
|
213
|
+
function z({
|
|
214
|
+
ariaLabel: t = "Close",
|
|
215
|
+
className: o,
|
|
216
|
+
onClick: r,
|
|
217
|
+
...l
|
|
218
|
+
}) {
|
|
219
|
+
return /* @__PURE__ */ a(
|
|
220
|
+
"button",
|
|
221
|
+
{
|
|
222
|
+
type: "button",
|
|
223
|
+
"aria-label": t,
|
|
224
|
+
className: s(
|
|
225
|
+
"inline-flex items-center justify-center",
|
|
226
|
+
"w-8 h-8 rounded-lg",
|
|
227
|
+
"text-[var(--color-grey-400)]",
|
|
228
|
+
"hover:text-[var(--color-white)] hover:bg-[var(--glass-bg)]",
|
|
229
|
+
"transition-colors duration-200",
|
|
230
|
+
"focus-ring",
|
|
231
|
+
"motion-reduce:transition-none",
|
|
232
|
+
o
|
|
233
|
+
),
|
|
234
|
+
onClick: r,
|
|
235
|
+
...l,
|
|
236
|
+
children: /* @__PURE__ */ a(
|
|
237
|
+
"svg",
|
|
238
|
+
{
|
|
239
|
+
width: "16",
|
|
240
|
+
height: "16",
|
|
241
|
+
viewBox: "0 0 16 16",
|
|
242
|
+
fill: "none",
|
|
243
|
+
stroke: "currentColor",
|
|
244
|
+
strokeWidth: "2",
|
|
245
|
+
strokeLinecap: "round",
|
|
246
|
+
children: /* @__PURE__ */ a("path", { d: "M4 4l8 8M12 4l-8 8" })
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
z.displayName = "ModalCloseButton";
|
|
253
|
+
export {
|
|
254
|
+
q as Modal,
|
|
255
|
+
P as ModalBody,
|
|
256
|
+
z as ModalCloseButton,
|
|
257
|
+
H as ModalDescription,
|
|
258
|
+
Y as ModalFooter,
|
|
259
|
+
K as ModalHeader,
|
|
260
|
+
L as ModalTitle
|
|
261
|
+
};
|
|
262
|
+
//# sourceMappingURL=Modal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.js","sources":["../../../src/molecules/Modal/Modal.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useRef,\n useCallback,\n useId,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cn } from '../../utils/cn'\n\nexport type ModalSize = 'sm' | 'md' | 'lg' | 'full'\n\nexport interface ModalProps extends Omit<HTMLAttributes<HTMLDivElement>, 'role'> {\n /** Whether the modal is open */\n isOpen: boolean\n /** Callback when modal should close */\n onClose: () => void\n /** Modal content */\n children: ReactNode\n /** Size of the modal panel */\n size?: ModalSize\n /** Whether clicking the backdrop closes the modal */\n closeOnBackdropClick?: boolean\n /** Whether pressing Escape closes the modal */\n closeOnEscape?: boolean\n /** Accessible label for the modal (used if no Modal.Header is provided) */\n ariaLabel?: string\n}\n\nconst FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nconst sizeClasses: Record<ModalSize, string> = {\n sm: 'max-w-[400px]',\n md: 'max-w-[560px]',\n lg: 'max-w-[720px]',\n full: 'max-w-none w-screen h-[100dvh] !rounded-none',\n}\n\nexport const Modal = forwardRef<HTMLDivElement, ModalProps>(\n (\n {\n isOpen,\n onClose,\n children,\n size = 'md',\n closeOnBackdropClick = true,\n closeOnEscape = true,\n ariaLabel,\n className,\n ...props\n },\n ref\n ) => {\n const internalRef = useRef<HTMLDivElement>(null)\n const panelRef = (ref as React.RefObject<HTMLDivElement>) || internalRef\n const previousActiveElement = useRef<HTMLElement | null>(null)\n const labelId = useId()\n const descriptionId = useId()\n const [mounted, setMounted] = useState(false)\n const [visible, setVisible] = useState(false)\n\n // Mount/unmount with animation\n useEffect(() => {\n if (isOpen) {\n setMounted(true)\n // Trigger enter animation on next frame\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setVisible(true)\n })\n })\n } else {\n setVisible(false)\n const timer = setTimeout(() => setMounted(false), 200)\n return () => clearTimeout(timer)\n }\n }, [isOpen])\n\n // Lock body scroll when open\n useEffect(() => {\n if (isOpen) {\n const scrollY = window.scrollY\n document.body.style.overflow = 'hidden'\n document.body.style.position = 'fixed'\n document.body.style.top = `-${scrollY}px`\n document.body.style.width = '100%'\n } else {\n const top = document.body.style.top\n document.body.style.overflow = ''\n document.body.style.position = ''\n document.body.style.top = ''\n document.body.style.width = ''\n if (top) {\n window.scrollTo(0, parseInt(top, 10) * -1)\n }\n }\n return () => {\n document.body.style.overflow = ''\n document.body.style.position = ''\n document.body.style.top = ''\n document.body.style.width = ''\n }\n }, [isOpen])\n\n // Escape key handler\n useEffect(() => {\n if (!closeOnEscape || !isOpen) return\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n onClose()\n }\n }\n document.addEventListener('keydown', handleEscape)\n return () => document.removeEventListener('keydown', handleEscape)\n }, [isOpen, onClose, closeOnEscape])\n\n // Focus management\n useEffect(() => {\n if (isOpen) {\n previousActiveElement.current = document.activeElement as HTMLElement\n // Focus first focusable element in panel\n const panel = panelRef.current\n if (panel) {\n const firstFocusable = panel.querySelector<HTMLElement>(FOCUSABLE_SELECTOR)\n if (firstFocusable) {\n firstFocusable.focus()\n } else {\n panel.focus()\n }\n }\n } else if (previousActiveElement.current) {\n previousActiveElement.current.focus()\n previousActiveElement.current = null\n }\n }, [isOpen, panelRef])\n\n // Focus trap\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key !== 'Tab' || !panelRef.current) return\n\n const focusableElements =\n panelRef.current.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)\n if (focusableElements.length === 0) {\n e.preventDefault()\n return\n }\n\n const firstElement = focusableElements[0]\n const lastElement = focusableElements[focusableElements.length - 1]\n\n if (e.shiftKey && document.activeElement === firstElement) {\n e.preventDefault()\n lastElement?.focus()\n } else if (!e.shiftKey && document.activeElement === lastElement) {\n e.preventDefault()\n firstElement?.focus()\n }\n },\n [panelRef]\n )\n\n // Backdrop click handler\n const handleBackdropClick = useCallback(\n (e: React.MouseEvent) => {\n if (closeOnBackdropClick && e.target === e.currentTarget) {\n onClose()\n }\n },\n [closeOnBackdropClick, onClose]\n )\n\n if (!mounted) return null\n\n return createPortal(\n <div\n className={cn(\n 'fixed inset-0 z-50 flex items-center justify-center',\n // Backdrop\n 'transition-[background-color,backdrop-filter] duration-200 ease-out',\n visible\n ? 'bg-black/60 backdrop-blur-sm'\n : 'bg-black/0 backdrop-blur-none',\n // Reduced motion: instant transitions\n 'motion-reduce:transition-none'\n )}\n onClick={handleBackdropClick}\n aria-hidden=\"true\"\n >\n {/* Panel */}\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={ariaLabel ? undefined : labelId}\n aria-label={ariaLabel}\n aria-describedby={descriptionId}\n tabIndex={-1}\n className={cn(\n 'relative w-full mx-4',\n sizeClasses[size],\n // Glass panel styling\n 'bg-[var(--color-bg-secondary)] border border-[var(--glass-border)]',\n 'backdrop-blur-lg',\n size !== 'full' && 'rounded-2xl',\n // Focus ring\n 'focus-ring',\n // Animation\n 'transition-[opacity,transform] duration-200 ease-out',\n visible\n ? 'opacity-100 scale-100 translate-y-0'\n : 'opacity-0 scale-95 translate-y-2',\n // Reduced motion: no scale/translate, instant\n 'motion-reduce:transition-none motion-reduce:transform-none',\n className\n )}\n onKeyDown={handleKeyDown}\n // Pass through the label/description IDs via data attributes for sub-components\n data-modal-label-id={labelId}\n data-modal-description-id={descriptionId}\n {...props}\n >\n {children}\n </div>\n </div>,\n document.body\n )\n }\n)\n\nModal.displayName = 'Modal'\n\n// --- Compound sub-components ---\n\nexport interface ModalHeaderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function ModalHeader({ children, className, ...props }: ModalHeaderProps) {\n return (\n <div\n className={cn(\n 'px-6 pt-6 pb-0',\n 'flex items-start justify-between gap-4',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nModalHeader.displayName = 'ModalHeader'\n\nexport interface ModalTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n children: ReactNode\n as?: 'h1' | 'h2' | 'h3' | 'h4'\n}\n\nexport function ModalTitle({ children, as: Tag = 'h2', className, id, ...props }: ModalTitleProps) {\n return (\n <Tag\n id={id}\n className={cn(\n 'font-display text-lg font-semibold text-[var(--color-white)]',\n 'tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </Tag>\n )\n}\n\nModalTitle.displayName = 'ModalTitle'\n\nexport interface ModalDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {\n children: ReactNode\n}\n\nexport function ModalDescription({ children, className, id, ...props }: ModalDescriptionProps) {\n return (\n <p\n id={id}\n className={cn(\n 'text-sm text-[var(--color-grey-400)]',\n 'mt-1',\n className\n )}\n {...props}\n >\n {children}\n </p>\n )\n}\n\nModalDescription.displayName = 'ModalDescription'\n\nexport interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function ModalBody({ children, className, ...props }: ModalBodyProps) {\n return (\n <div\n className={cn(\n 'px-6 py-4',\n 'overflow-y-auto',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nModalBody.displayName = 'ModalBody'\n\nexport interface ModalFooterProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function ModalFooter({ children, className, ...props }: ModalFooterProps) {\n return (\n <div\n className={cn(\n 'px-6 pb-6 pt-0',\n 'border-t border-[var(--glass-border)]',\n 'mt-2 pt-4',\n 'flex items-center justify-end gap-3',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nModalFooter.displayName = 'ModalFooter'\n\nexport interface ModalCloseButtonProps extends HTMLAttributes<HTMLButtonElement> {\n /** Accessible label for the close button */\n ariaLabel?: string\n}\n\nexport function ModalCloseButton({\n ariaLabel = 'Close',\n className,\n onClick,\n ...props\n}: ModalCloseButtonProps) {\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={cn(\n 'inline-flex items-center justify-center',\n 'w-8 h-8 rounded-lg',\n 'text-[var(--color-grey-400)]',\n 'hover:text-[var(--color-white)] hover:bg-[var(--glass-bg)]',\n 'transition-colors duration-200',\n 'focus-ring',\n 'motion-reduce:transition-none',\n className\n )}\n onClick={onClick}\n {...props}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n >\n <path d=\"M4 4l8 8M12 4l-8 8\" />\n </svg>\n </button>\n )\n}\n\nModalCloseButton.displayName = 'ModalCloseButton'\n"],"names":["FOCUSABLE_SELECTOR","sizeClasses","Modal","forwardRef","isOpen","onClose","children","size","closeOnBackdropClick","closeOnEscape","ariaLabel","className","props","ref","internalRef","useRef","panelRef","previousActiveElement","labelId","useId","descriptionId","mounted","setMounted","useState","visible","setVisible","useEffect","timer","scrollY","top","handleEscape","e","panel","firstFocusable","handleKeyDown","useCallback","focusableElements","firstElement","lastElement","handleBackdropClick","createPortal","jsx","cn","ModalHeader","ModalTitle","Tag","id","ModalDescription","ModalBody","ModalFooter","ModalCloseButton","onClick"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as d } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as f } from "react";
|
|
3
|
+
import { cn as b } from "../../utils/cn.js";
|
|
4
|
+
const m = f(
|
|
5
|
+
({ variant: r = "default", isActive: o = !1, children: e, className: t, style: l, ...n }, a) => {
|
|
6
|
+
const s = [
|
|
7
|
+
"inline-flex items-center",
|
|
8
|
+
"text-sm font-normal",
|
|
9
|
+
"transition-[color,background-color,border-color,transform] duration-200 ease-out",
|
|
10
|
+
"focus-ring",
|
|
11
|
+
"hover:text-[--color-white]"
|
|
12
|
+
], i = {
|
|
13
|
+
default: [],
|
|
14
|
+
underline: ["relative", "link-hover"],
|
|
15
|
+
pill: [
|
|
16
|
+
"px-3 py-1.5",
|
|
17
|
+
"rounded-full",
|
|
18
|
+
"border",
|
|
19
|
+
o ? "bg-[--color-white] border-[--color-white]" : "bg-transparent border-transparent hover:bg-[--glass-bg] hover:border-[--glass-border]"
|
|
20
|
+
]
|
|
21
|
+
}, c = () => r === "pill" && o ? "var(--color-bg)" : "var(--color-white)";
|
|
22
|
+
return /* @__PURE__ */ d(
|
|
23
|
+
"a",
|
|
24
|
+
{
|
|
25
|
+
ref: a,
|
|
26
|
+
className: b(s, i[r], t),
|
|
27
|
+
style: { color: c(), ...l },
|
|
28
|
+
...n,
|
|
29
|
+
children: e
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
m.displayName = "NavLink";
|
|
35
|
+
export {
|
|
36
|
+
m as NavLink
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=NavLink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavLink.js","sources":["../../../src/molecules/NavLink/NavLink.tsx"],"sourcesContent":["import { type AnchorHTMLAttributes, type ReactNode, forwardRef } from 'react'\nimport { cn } from '../../utils/cn'\n\nexport interface NavLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n variant?: 'default' | 'underline' | 'pill'\n isActive?: boolean\n children: ReactNode\n}\n\nexport const NavLink = forwardRef<HTMLAnchorElement, NavLinkProps>(\n ({ variant = 'default', isActive = false, children, className, style, ...props }, ref) => {\n const baseStyles = [\n 'inline-flex items-center',\n 'text-sm font-normal',\n 'transition-[color,background-color,border-color,transform] duration-200 ease-out',\n 'focus-ring',\n 'hover:text-[--color-white]',\n ]\n\n const variants = {\n default: [],\n underline: ['relative', 'link-hover'],\n pill: [\n 'px-3 py-1.5',\n 'rounded-full',\n 'border',\n isActive\n ? 'bg-[--color-white] border-[--color-white]'\n : 'bg-transparent border-transparent hover:bg-[--glass-bg] hover:border-[--glass-border]',\n ],\n }\n\n const getColor = () => {\n if (variant === 'pill' && isActive) return 'var(--color-bg)'\n return 'var(--color-white)'\n }\n\n return (\n <a\n ref={ref}\n className={cn(baseStyles, variants[variant], className)}\n style={{ color: getColor(), ...style }}\n {...props}\n >\n {children}\n </a>\n )\n }\n)\n\nNavLink.displayName = 'NavLink'\n"],"names":["NavLink","forwardRef","variant","isActive","children","className","style","props","ref","baseStyles","variants","getColor","jsx","cn"],"mappings":";;;AASO,MAAMA,IAAUC;AAAA,EACrB,CAAC,EAAE,SAAAC,IAAU,WAAW,UAAAC,IAAW,IAAO,UAAAC,GAAU,WAAAC,GAAW,OAAAC,GAAO,GAAGC,EAAA,GAASC,MAAQ;AACxF,UAAMC,IAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,GAGIC,IAAW;AAAA,MACf,SAAS,CAAA;AAAA,MACT,WAAW,CAAC,YAAY,YAAY;AAAA,MACpC,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACAP,IACI,8CACA;AAAA,MAAA;AAAA,IACN,GAGIQ,IAAW,MACXT,MAAY,UAAUC,IAAiB,oBACpC;AAGT,WACE,gBAAAS;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAJ;AAAA,QACA,WAAWK,EAAGJ,GAAYC,EAASR,CAAO,GAAGG,CAAS;AAAA,QACtD,OAAO,EAAE,OAAOM,EAAA,GAAY,GAAGL,EAAA;AAAA,QAC9B,GAAGC;AAAA,QAEH,UAAAH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEAJ,EAAQ,cAAc;"}
|