@n3wth/ui 0.8.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.
Files changed (229) hide show
  1. package/dist/atoms/AnimatedText/AnimatedText.js +65 -0
  2. package/dist/atoms/AnimatedText/AnimatedText.js.map +1 -0
  3. package/dist/atoms/Avatar/Avatar.js +55 -0
  4. package/dist/atoms/Avatar/Avatar.js.map +1 -0
  5. package/dist/atoms/Badge/Badge.js +57 -0
  6. package/dist/atoms/Badge/Badge.js.map +1 -0
  7. package/dist/atoms/Button/Button.js +92 -0
  8. package/dist/atoms/Button/Button.js.map +1 -0
  9. package/dist/atoms/Character/Character.js +155 -0
  10. package/dist/atoms/Character/Character.js.map +1 -0
  11. package/dist/atoms/CodeBlock/CodeBlock.js +75 -0
  12. package/dist/atoms/CodeBlock/CodeBlock.js.map +1 -0
  13. package/dist/atoms/HamburgerIcon/HamburgerIcon.js +50 -0
  14. package/dist/atoms/HamburgerIcon/HamburgerIcon.js.map +1 -0
  15. package/dist/atoms/Icon/Icon.js +199 -0
  16. package/dist/atoms/Icon/Icon.js.map +1 -0
  17. package/dist/atoms/Input/Input.js +80 -0
  18. package/dist/atoms/Input/Input.js.map +1 -0
  19. package/dist/atoms/Label/Label.js +32 -0
  20. package/dist/atoms/Label/Label.js.map +1 -0
  21. package/dist/atoms/NoiseOverlay/NoiseOverlay.js +32 -0
  22. package/dist/atoms/NoiseOverlay/NoiseOverlay.js.map +1 -0
  23. package/dist/atoms/Progress/Progress.js +63 -0
  24. package/dist/atoms/Progress/Progress.js.map +1 -0
  25. package/dist/atoms/ScrollIndicator/ScrollIndicator.js +51 -0
  26. package/dist/atoms/ScrollIndicator/ScrollIndicator.js.map +1 -0
  27. package/dist/atoms/Separator/Separator.js +28 -0
  28. package/dist/atoms/Separator/Separator.js.map +1 -0
  29. package/dist/atoms/Shape/Shape.js +110 -0
  30. package/dist/atoms/Shape/Shape.js.map +1 -0
  31. package/dist/atoms/Shape/patterns.js +66 -0
  32. package/dist/atoms/Shape/patterns.js.map +1 -0
  33. package/dist/atoms/Skeleton/Skeleton.js +77 -0
  34. package/dist/atoms/Skeleton/Skeleton.js.map +1 -0
  35. package/dist/atoms/SpeechBubble/SpeechBubble.js +98 -0
  36. package/dist/atoms/SpeechBubble/SpeechBubble.js.map +1 -0
  37. package/dist/atoms/Switch/Switch.js +78 -0
  38. package/dist/atoms/Switch/Switch.js.map +1 -0
  39. package/dist/atoms/Textarea/Textarea.js +40 -0
  40. package/dist/atoms/Textarea/Textarea.js.map +1 -0
  41. package/dist/atoms/Tooltip/Tooltip.js +153 -0
  42. package/dist/atoms/Tooltip/Tooltip.js.map +1 -0
  43. package/dist/hooks/useButtonPulse.js +43 -0
  44. package/dist/hooks/useButtonPulse.js.map +1 -0
  45. package/dist/hooks/useCountUp.js +52 -0
  46. package/dist/hooks/useCountUp.js.map +1 -0
  47. package/dist/hooks/useKeyboardShortcuts.js +37 -0
  48. package/dist/hooks/useKeyboardShortcuts.js.map +1 -0
  49. package/dist/hooks/useMediaQuery.js +59 -0
  50. package/dist/hooks/useMediaQuery.js.map +1 -0
  51. package/dist/hooks/usePageTransition.js +39 -0
  52. package/dist/hooks/usePageTransition.js.map +1 -0
  53. package/dist/hooks/useReducedMotion.js +57 -0
  54. package/dist/hooks/useReducedMotion.js.map +1 -0
  55. package/dist/hooks/useScrollReveal.js +61 -0
  56. package/dist/hooks/useScrollReveal.js.map +1 -0
  57. package/dist/hooks/useStaggerList.js +54 -0
  58. package/dist/hooks/useStaggerList.js.map +1 -0
  59. package/dist/hooks/useTextReveal.js +59 -0
  60. package/dist/hooks/useTextReveal.js.map +1 -0
  61. package/dist/hooks/useTheme.js +37 -0
  62. package/dist/hooks/useTheme.js.map +1 -0
  63. package/dist/hooks/useToast.js +84 -0
  64. package/dist/hooks/useToast.js.map +1 -0
  65. package/dist/index.js +147 -7925
  66. package/dist/index.js.map +1 -1
  67. package/dist/molecules/Accordion/Accordion.js +178 -0
  68. package/dist/molecules/Accordion/Accordion.js.map +1 -0
  69. package/dist/molecules/Card/Card.js +104 -0
  70. package/dist/molecules/Card/Card.js.map +1 -0
  71. package/dist/molecules/CommandBox/CommandBox.js +65 -0
  72. package/dist/molecules/CommandBox/CommandBox.js.map +1 -0
  73. package/dist/molecules/CompositeShape/CompositeShape.js +69 -0
  74. package/dist/molecules/CompositeShape/CompositeShape.js.map +1 -0
  75. package/dist/molecules/CompositeShape/presets.js +71 -0
  76. package/dist/molecules/CompositeShape/presets.js.map +1 -0
  77. package/dist/molecules/Dropdown/Dropdown.d.ts.map +1 -1
  78. package/dist/molecules/Dropdown/Dropdown.js +530 -0
  79. package/dist/molecules/Dropdown/Dropdown.js.map +1 -0
  80. package/dist/molecules/ErrorBoundary/ErrorBoundary.js +128 -0
  81. package/dist/molecules/ErrorBoundary/ErrorBoundary.js.map +1 -0
  82. package/dist/molecules/MobileDrawer/MobileDrawer.js +78 -0
  83. package/dist/molecules/MobileDrawer/MobileDrawer.js.map +1 -0
  84. package/dist/molecules/Modal/Modal.js +262 -0
  85. package/dist/molecules/Modal/Modal.js.map +1 -0
  86. package/dist/molecules/NavLink/NavLink.js +38 -0
  87. package/dist/molecules/NavLink/NavLink.js.map +1 -0
  88. package/dist/molecules/Tabs/Tabs.js +188 -0
  89. package/dist/molecules/Tabs/Tabs.js.map +1 -0
  90. package/dist/molecules/ThemeToggle/ThemeToggle.js +48 -0
  91. package/dist/molecules/ThemeToggle/ThemeToggle.js.map +1 -0
  92. package/dist/molecules/Toast/Toast.js +156 -0
  93. package/dist/molecules/Toast/Toast.js.map +1 -0
  94. package/dist/node_modules/clsx/dist/clsx.js +17 -0
  95. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  96. package/dist/node_modules/iconoir-react/dist/esm/IconoirContext.js +6 -0
  97. package/dist/node_modules/iconoir-react/dist/esm/IconoirContext.js.map +1 -0
  98. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowDown.js +17 -0
  99. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowDown.js.map +1 -0
  100. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowLeft.js +17 -0
  101. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowLeft.js.map +1 -0
  102. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowRight.js +17 -0
  103. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowRight.js.map +1 -0
  104. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUp.js +17 -0
  105. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUp.js.map +1 -0
  106. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUpRight.js +17 -0
  107. package/dist/node_modules/iconoir-react/dist/esm/regular/ArrowUpRight.js.map +1 -0
  108. package/dist/node_modules/iconoir-react/dist/esm/regular/Bell.js +17 -0
  109. package/dist/node_modules/iconoir-react/dist/esm/regular/Bell.js.map +1 -0
  110. package/dist/node_modules/iconoir-react/dist/esm/regular/Calendar.js +17 -0
  111. package/dist/node_modules/iconoir-react/dist/esm/regular/Calendar.js.map +1 -0
  112. package/dist/node_modules/iconoir-react/dist/esm/regular/Check.js +17 -0
  113. package/dist/node_modules/iconoir-react/dist/esm/regular/Check.js.map +1 -0
  114. package/dist/node_modules/iconoir-react/dist/esm/regular/CheckCircle.js +17 -0
  115. package/dist/node_modules/iconoir-react/dist/esm/regular/CheckCircle.js.map +1 -0
  116. package/dist/node_modules/iconoir-react/dist/esm/regular/Clock.js +17 -0
  117. package/dist/node_modules/iconoir-react/dist/esm/regular/Clock.js.map +1 -0
  118. package/dist/node_modules/iconoir-react/dist/esm/regular/Code.js +17 -0
  119. package/dist/node_modules/iconoir-react/dist/esm/regular/Code.js.map +1 -0
  120. package/dist/node_modules/iconoir-react/dist/esm/regular/Copy.js +17 -0
  121. package/dist/node_modules/iconoir-react/dist/esm/regular/Copy.js.map +1 -0
  122. package/dist/node_modules/iconoir-react/dist/esm/regular/Download.js +17 -0
  123. package/dist/node_modules/iconoir-react/dist/esm/regular/Download.js.map +1 -0
  124. package/dist/node_modules/iconoir-react/dist/esm/regular/EditPencil.js +17 -0
  125. package/dist/node_modules/iconoir-react/dist/esm/regular/EditPencil.js.map +1 -0
  126. package/dist/node_modules/iconoir-react/dist/esm/regular/Eye.js +17 -0
  127. package/dist/node_modules/iconoir-react/dist/esm/regular/Eye.js.map +1 -0
  128. package/dist/node_modules/iconoir-react/dist/esm/regular/EyeClosed.js +17 -0
  129. package/dist/node_modules/iconoir-react/dist/esm/regular/EyeClosed.js.map +1 -0
  130. package/dist/node_modules/iconoir-react/dist/esm/regular/Filter.js +17 -0
  131. package/dist/node_modules/iconoir-react/dist/esm/regular/Filter.js.map +1 -0
  132. package/dist/node_modules/iconoir-react/dist/esm/regular/Folder.js +17 -0
  133. package/dist/node_modules/iconoir-react/dist/esm/regular/Folder.js.map +1 -0
  134. package/dist/node_modules/iconoir-react/dist/esm/regular/Github.js +17 -0
  135. package/dist/node_modules/iconoir-react/dist/esm/regular/Github.js.map +1 -0
  136. package/dist/node_modules/iconoir-react/dist/esm/regular/HalfMoon.js +17 -0
  137. package/dist/node_modules/iconoir-react/dist/esm/regular/HalfMoon.js.map +1 -0
  138. package/dist/node_modules/iconoir-react/dist/esm/regular/Heart.js +17 -0
  139. package/dist/node_modules/iconoir-react/dist/esm/regular/Heart.js.map +1 -0
  140. package/dist/node_modules/iconoir-react/dist/esm/regular/Home.js +17 -0
  141. package/dist/node_modules/iconoir-react/dist/esm/regular/Home.js.map +1 -0
  142. package/dist/node_modules/iconoir-react/dist/esm/regular/InfoCircle.js +17 -0
  143. package/dist/node_modules/iconoir-react/dist/esm/regular/InfoCircle.js.map +1 -0
  144. package/dist/node_modules/iconoir-react/dist/esm/regular/Link.js +17 -0
  145. package/dist/node_modules/iconoir-react/dist/esm/regular/Link.js.map +1 -0
  146. package/dist/node_modules/iconoir-react/dist/esm/regular/List.js +17 -0
  147. package/dist/node_modules/iconoir-react/dist/esm/regular/List.js.map +1 -0
  148. package/dist/node_modules/iconoir-react/dist/esm/regular/Lock.js +17 -0
  149. package/dist/node_modules/iconoir-react/dist/esm/regular/Lock.js.map +1 -0
  150. package/dist/node_modules/iconoir-react/dist/esm/regular/LockSlash.js +17 -0
  151. package/dist/node_modules/iconoir-react/dist/esm/regular/LockSlash.js.map +1 -0
  152. package/dist/node_modules/iconoir-react/dist/esm/regular/Mail.js +17 -0
  153. package/dist/node_modules/iconoir-react/dist/esm/regular/Mail.js.map +1 -0
  154. package/dist/node_modules/iconoir-react/dist/esm/regular/Menu.js +17 -0
  155. package/dist/node_modules/iconoir-react/dist/esm/regular/Menu.js.map +1 -0
  156. package/dist/node_modules/iconoir-react/dist/esm/regular/Minus.js +17 -0
  157. package/dist/node_modules/iconoir-react/dist/esm/regular/Minus.js.map +1 -0
  158. package/dist/node_modules/iconoir-react/dist/esm/regular/MoreHoriz.js +17 -0
  159. package/dist/node_modules/iconoir-react/dist/esm/regular/MoreHoriz.js.map +1 -0
  160. package/dist/node_modules/iconoir-react/dist/esm/regular/MoreVert.js +17 -0
  161. package/dist/node_modules/iconoir-react/dist/esm/regular/MoreVert.js.map +1 -0
  162. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowDown.js +17 -0
  163. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowDown.js.map +1 -0
  164. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowLeft.js +17 -0
  165. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowLeft.js.map +1 -0
  166. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowRight.js +17 -0
  167. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowRight.js.map +1 -0
  168. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowUp.js +17 -0
  169. package/dist/node_modules/iconoir-react/dist/esm/regular/NavArrowUp.js.map +1 -0
  170. package/dist/node_modules/iconoir-react/dist/esm/regular/OpenInWindow.js +17 -0
  171. package/dist/node_modules/iconoir-react/dist/esm/regular/OpenInWindow.js.map +1 -0
  172. package/dist/node_modules/iconoir-react/dist/esm/regular/Page.js +17 -0
  173. package/dist/node_modules/iconoir-react/dist/esm/regular/Page.js.map +1 -0
  174. package/dist/node_modules/iconoir-react/dist/esm/regular/Plus.js +17 -0
  175. package/dist/node_modules/iconoir-react/dist/esm/regular/Plus.js.map +1 -0
  176. package/dist/node_modules/iconoir-react/dist/esm/regular/RefreshDouble.js +17 -0
  177. package/dist/node_modules/iconoir-react/dist/esm/regular/RefreshDouble.js.map +1 -0
  178. package/dist/node_modules/iconoir-react/dist/esm/regular/Search.js +17 -0
  179. package/dist/node_modules/iconoir-react/dist/esm/regular/Search.js.map +1 -0
  180. package/dist/node_modules/iconoir-react/dist/esm/regular/Settings.js +17 -0
  181. package/dist/node_modules/iconoir-react/dist/esm/regular/Settings.js.map +1 -0
  182. package/dist/node_modules/iconoir-react/dist/esm/regular/SortDown.js +17 -0
  183. package/dist/node_modules/iconoir-react/dist/esm/regular/SortDown.js.map +1 -0
  184. package/dist/node_modules/iconoir-react/dist/esm/regular/Sparks.js +17 -0
  185. package/dist/node_modules/iconoir-react/dist/esm/regular/Sparks.js.map +1 -0
  186. package/dist/node_modules/iconoir-react/dist/esm/regular/Star.js +17 -0
  187. package/dist/node_modules/iconoir-react/dist/esm/regular/Star.js.map +1 -0
  188. package/dist/node_modules/iconoir-react/dist/esm/regular/SunLight.js +17 -0
  189. package/dist/node_modules/iconoir-react/dist/esm/regular/SunLight.js.map +1 -0
  190. package/dist/node_modules/iconoir-react/dist/esm/regular/Terminal.js +17 -0
  191. package/dist/node_modules/iconoir-react/dist/esm/regular/Terminal.js.map +1 -0
  192. package/dist/node_modules/iconoir-react/dist/esm/regular/Trash.js +17 -0
  193. package/dist/node_modules/iconoir-react/dist/esm/regular/Trash.js.map +1 -0
  194. package/dist/node_modules/iconoir-react/dist/esm/regular/Upload.js +17 -0
  195. package/dist/node_modules/iconoir-react/dist/esm/regular/Upload.js.map +1 -0
  196. package/dist/node_modules/iconoir-react/dist/esm/regular/User.js +17 -0
  197. package/dist/node_modules/iconoir-react/dist/esm/regular/User.js.map +1 -0
  198. package/dist/node_modules/iconoir-react/dist/esm/regular/ViewGrid.js +17 -0
  199. package/dist/node_modules/iconoir-react/dist/esm/regular/ViewGrid.js.map +1 -0
  200. package/dist/node_modules/iconoir-react/dist/esm/regular/WarningTriangle.js +17 -0
  201. package/dist/node_modules/iconoir-react/dist/esm/regular/WarningTriangle.js.map +1 -0
  202. package/dist/node_modules/iconoir-react/dist/esm/regular/Xmark.js +17 -0
  203. package/dist/node_modules/iconoir-react/dist/esm/regular/Xmark.js.map +1 -0
  204. package/dist/node_modules/iconoir-react/dist/esm/regular/XmarkCircle.js +17 -0
  205. package/dist/node_modules/iconoir-react/dist/esm/regular/XmarkCircle.js.map +1 -0
  206. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +2996 -0
  207. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  208. package/dist/organisms/Footer/Footer.js +108 -0
  209. package/dist/organisms/Footer/Footer.js.map +1 -0
  210. package/dist/organisms/Hero/Hero.d.ts.map +1 -1
  211. package/dist/organisms/Hero/Hero.js +101 -0
  212. package/dist/organisms/Hero/Hero.js.map +1 -0
  213. package/dist/organisms/Nav/Nav.js +177 -0
  214. package/dist/organisms/Nav/Nav.js.map +1 -0
  215. package/dist/organisms/Section/Section.js +57 -0
  216. package/dist/organisms/Section/Section.js.map +1 -0
  217. package/dist/tokens/colors.js +105 -0
  218. package/dist/tokens/colors.js.map +1 -0
  219. package/dist/tokens/effects.js +26 -0
  220. package/dist/tokens/effects.js.map +1 -0
  221. package/dist/tokens/motion.js +25 -0
  222. package/dist/tokens/motion.js.map +1 -0
  223. package/dist/tokens/spacing.js +31 -0
  224. package/dist/tokens/spacing.js.map +1 -0
  225. package/dist/tokens/typography.js +63 -0
  226. package/dist/tokens/typography.js.map +1 -0
  227. package/dist/utils/cn.js +9 -0
  228. package/dist/utils/cn.js.map +1 -0
  229. package/package.json +5 -3
@@ -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;"}