@thangnqdev/ui 0.1.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 (253) hide show
  1. package/README.md +196 -0
  2. package/dist/Label-DWOlgSNW.d.cts +14 -0
  3. package/dist/Label-DWOlgSNW.d.ts +14 -0
  4. package/dist/bento/index.cjs +140 -0
  5. package/dist/bento/index.cjs.map +1 -0
  6. package/dist/bento/index.d.cts +4 -0
  7. package/dist/bento/index.d.ts +4 -0
  8. package/dist/bento/index.js +4 -0
  9. package/dist/bento/index.js.map +1 -0
  10. package/dist/bento/styles.css +46 -0
  11. package/dist/buttons/index.cjs +365 -0
  12. package/dist/buttons/index.cjs.map +1 -0
  13. package/dist/buttons/index.d.cts +4 -0
  14. package/dist/buttons/index.d.ts +4 -0
  15. package/dist/buttons/index.js +5 -0
  16. package/dist/buttons/index.js.map +1 -0
  17. package/dist/buttons/styles.css +6 -0
  18. package/dist/chunk-2OXZK6IP.js +514 -0
  19. package/dist/chunk-2OXZK6IP.js.map +1 -0
  20. package/dist/chunk-4S6L5V7X.js +15 -0
  21. package/dist/chunk-4S6L5V7X.js.map +1 -0
  22. package/dist/chunk-5FZ6ZFII.js +728 -0
  23. package/dist/chunk-5FZ6ZFII.js.map +1 -0
  24. package/dist/chunk-66VWUJEI.js +86 -0
  25. package/dist/chunk-66VWUJEI.js.map +1 -0
  26. package/dist/chunk-A7P3O5Z5.js +163 -0
  27. package/dist/chunk-A7P3O5Z5.js.map +1 -0
  28. package/dist/chunk-ATYGDTMK.js +257 -0
  29. package/dist/chunk-ATYGDTMK.js.map +1 -0
  30. package/dist/chunk-C4SUXMI3.js +138 -0
  31. package/dist/chunk-C4SUXMI3.js.map +1 -0
  32. package/dist/chunk-EU2LPUYP.js +25 -0
  33. package/dist/chunk-EU2LPUYP.js.map +1 -0
  34. package/dist/chunk-F5Q7BTMH.js +1991 -0
  35. package/dist/chunk-F5Q7BTMH.js.map +1 -0
  36. package/dist/chunk-GXI2H5XA.js +46 -0
  37. package/dist/chunk-GXI2H5XA.js.map +1 -0
  38. package/dist/chunk-H3LCNPMC.js +101 -0
  39. package/dist/chunk-H3LCNPMC.js.map +1 -0
  40. package/dist/chunk-IABPUCAQ.js +19 -0
  41. package/dist/chunk-IABPUCAQ.js.map +1 -0
  42. package/dist/chunk-KJRBRTQE.js +101 -0
  43. package/dist/chunk-KJRBRTQE.js.map +1 -0
  44. package/dist/chunk-LBUBXUYQ.js +40 -0
  45. package/dist/chunk-LBUBXUYQ.js.map +1 -0
  46. package/dist/chunk-LWFRUJRU.js +537 -0
  47. package/dist/chunk-LWFRUJRU.js.map +1 -0
  48. package/dist/chunk-NFVONJUK.js +882 -0
  49. package/dist/chunk-NFVONJUK.js.map +1 -0
  50. package/dist/chunk-PF4ZHGVW.js +284 -0
  51. package/dist/chunk-PF4ZHGVW.js.map +1 -0
  52. package/dist/chunk-WAFHC4DQ.js +366 -0
  53. package/dist/chunk-WAFHC4DQ.js.map +1 -0
  54. package/dist/chunk-X76KBH4Y.js +71 -0
  55. package/dist/chunk-X76KBH4Y.js.map +1 -0
  56. package/dist/core/index.cjs +103 -0
  57. package/dist/core/index.cjs.map +1 -0
  58. package/dist/core/index.d.cts +3 -0
  59. package/dist/core/index.d.ts +3 -0
  60. package/dist/core/index.js +4 -0
  61. package/dist/core/index.js.map +1 -0
  62. package/dist/core/styles.css +128 -0
  63. package/dist/data-display/index.cjs +1023 -0
  64. package/dist/data-display/index.cjs.map +1 -0
  65. package/dist/data-display/index.d.cts +4 -0
  66. package/dist/data-display/index.d.ts +4 -0
  67. package/dist/data-display/index.js +6 -0
  68. package/dist/data-display/index.js.map +1 -0
  69. package/dist/data-display/styles.css +4 -0
  70. package/dist/feedback/index.cjs +368 -0
  71. package/dist/feedback/index.cjs.map +1 -0
  72. package/dist/feedback/index.d.cts +4 -0
  73. package/dist/feedback/index.d.ts +4 -0
  74. package/dist/feedback/index.js +4 -0
  75. package/dist/feedback/index.js.map +1 -0
  76. package/dist/feedback/styles.css +4 -0
  77. package/dist/forms/index.cjs +2287 -0
  78. package/dist/forms/index.cjs.map +1 -0
  79. package/dist/forms/index.d.cts +5 -0
  80. package/dist/forms/index.d.ts +5 -0
  81. package/dist/forms/index.js +10 -0
  82. package/dist/forms/index.js.map +1 -0
  83. package/dist/forms/styles.css +6 -0
  84. package/dist/glass/index.cjs +165 -0
  85. package/dist/glass/index.cjs.map +1 -0
  86. package/dist/glass/index.d.cts +4 -0
  87. package/dist/glass/index.d.ts +4 -0
  88. package/dist/glass/index.js +4 -0
  89. package/dist/glass/index.js.map +1 -0
  90. package/dist/glass/styles.css +81 -0
  91. package/dist/index-BTvkbCIj.d.cts +146 -0
  92. package/dist/index-BTvkbCIj.d.ts +146 -0
  93. package/dist/index-BkRqGNG1.d.cts +201 -0
  94. package/dist/index-BkRqGNG1.d.ts +201 -0
  95. package/dist/index-BlPcGeW-.d.cts +45 -0
  96. package/dist/index-BlPcGeW-.d.ts +45 -0
  97. package/dist/index-BzOCqvC6.d.cts +32 -0
  98. package/dist/index-BzOCqvC6.d.ts +32 -0
  99. package/dist/index-CCeWYAvn.d.cts +83 -0
  100. package/dist/index-COQ7uwt9.d.cts +44 -0
  101. package/dist/index-COQ7uwt9.d.ts +44 -0
  102. package/dist/index-CenuF_P2.d.cts +221 -0
  103. package/dist/index-CenuF_P2.d.ts +221 -0
  104. package/dist/index-Cle6QzQl.d.ts +371 -0
  105. package/dist/index-D6fE7w-b.d.cts +90 -0
  106. package/dist/index-D6fE7w-b.d.ts +90 -0
  107. package/dist/index-DR8cfJUG.d.ts +83 -0
  108. package/dist/index-DzcWh1Hs.d.cts +131 -0
  109. package/dist/index-DzcWh1Hs.d.ts +131 -0
  110. package/dist/index-TyK-Ldpy.d.cts +371 -0
  111. package/dist/index-ugj5s6a3.d.cts +95 -0
  112. package/dist/index-ugj5s6a3.d.ts +95 -0
  113. package/dist/index.cjs +6400 -0
  114. package/dist/index.cjs.map +1 -0
  115. package/dist/index.d.cts +16 -0
  116. package/dist/index.d.ts +16 -0
  117. package/dist/index.js +21 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/layout/index.cjs +516 -0
  120. package/dist/layout/index.cjs.map +1 -0
  121. package/dist/layout/index.d.cts +4 -0
  122. package/dist/layout/index.d.ts +4 -0
  123. package/dist/layout/index.js +4 -0
  124. package/dist/layout/index.js.map +1 -0
  125. package/dist/layout/styles.css +8 -0
  126. package/dist/navigation/index.cjs +673 -0
  127. package/dist/navigation/index.cjs.map +1 -0
  128. package/dist/navigation/index.d.cts +2 -0
  129. package/dist/navigation/index.d.ts +2 -0
  130. package/dist/navigation/index.js +8 -0
  131. package/dist/navigation/index.js.map +1 -0
  132. package/dist/navigation/styles.css +4 -0
  133. package/dist/overlays/index.cjs +954 -0
  134. package/dist/overlays/index.cjs.map +1 -0
  135. package/dist/overlays/index.d.cts +4 -0
  136. package/dist/overlays/index.d.ts +4 -0
  137. package/dist/overlays/index.js +9 -0
  138. package/dist/overlays/index.js.map +1 -0
  139. package/dist/overlays/styles.css +8 -0
  140. package/dist/styles.css +333 -0
  141. package/dist/typography/index.cjs +311 -0
  142. package/dist/typography/index.cjs.map +1 -0
  143. package/dist/typography/index.d.cts +5 -0
  144. package/dist/typography/index.d.ts +5 -0
  145. package/dist/typography/index.js +6 -0
  146. package/dist/typography/index.js.map +1 -0
  147. package/dist/typography/styles.css +5 -0
  148. package/llms.txt +113 -0
  149. package/package.json +116 -0
  150. package/src/bento/BentoCard.tsx +140 -0
  151. package/src/bento/BentoGrid.tsx +50 -0
  152. package/src/bento/index.ts +2 -0
  153. package/src/bento/tokens.css +46 -0
  154. package/src/buttons/Button.tsx +104 -0
  155. package/src/buttons/ButtonGroup.tsx +43 -0
  156. package/src/buttons/IconButton.tsx +79 -0
  157. package/src/buttons/SplitButton.tsx +86 -0
  158. package/src/buttons/ToggleButton.tsx +157 -0
  159. package/src/buttons/index.ts +5 -0
  160. package/src/buttons/tokens.css +6 -0
  161. package/src/core/ThemeProvider.tsx +123 -0
  162. package/src/core/index.ts +2 -0
  163. package/src/core/tokens.css +128 -0
  164. package/src/data-display/Accordion.tsx +147 -0
  165. package/src/data-display/Avatar.tsx +134 -0
  166. package/src/data-display/Card.tsx +112 -0
  167. package/src/data-display/Carousel.tsx +130 -0
  168. package/src/data-display/Chip.tsx +74 -0
  169. package/src/data-display/DataTablePro.tsx +356 -0
  170. package/src/data-display/StatCard.tsx +60 -0
  171. package/src/data-display/Table.tsx +74 -0
  172. package/src/data-display/Timeline.tsx +62 -0
  173. package/src/data-display/TreeView.tsx +140 -0
  174. package/src/data-display/index.ts +10 -0
  175. package/src/data-display/tokens.css +4 -0
  176. package/src/feedback/Alert.tsx +80 -0
  177. package/src/feedback/EmptyState.tsx +45 -0
  178. package/src/feedback/ProgressBar.tsx +174 -0
  179. package/src/feedback/Skeleton.tsx +66 -0
  180. package/src/feedback/Spinner.tsx +65 -0
  181. package/src/feedback/index.ts +5 -0
  182. package/src/feedback/tokens.css +4 -0
  183. package/src/forms/Checkbox.tsx +69 -0
  184. package/src/forms/CheckboxGroup.tsx +29 -0
  185. package/src/forms/Combobox.tsx +368 -0
  186. package/src/forms/DatePicker.tsx +480 -0
  187. package/src/forms/FileUpload.tsx +222 -0
  188. package/src/forms/FormField.tsx +115 -0
  189. package/src/forms/Input.tsx +151 -0
  190. package/src/forms/MaskedInput.tsx +97 -0
  191. package/src/forms/NumberInput.tsx +248 -0
  192. package/src/forms/PasswordInput.tsx +35 -0
  193. package/src/forms/PinInput.tsx +125 -0
  194. package/src/forms/Radio.tsx +142 -0
  195. package/src/forms/RangeSlider.tsx +111 -0
  196. package/src/forms/SearchInput.tsx +34 -0
  197. package/src/forms/Select.tsx +103 -0
  198. package/src/forms/Slider.tsx +85 -0
  199. package/src/forms/Switch.tsx +95 -0
  200. package/src/forms/Textarea.tsx +114 -0
  201. package/src/forms/index.ts +18 -0
  202. package/src/forms/tokens.css +6 -0
  203. package/src/glass/GlassBadge.tsx +61 -0
  204. package/src/glass/GlassButton.tsx +59 -0
  205. package/src/glass/GlassCard.tsx +71 -0
  206. package/src/glass/index.ts +3 -0
  207. package/src/glass/tokens.css +81 -0
  208. package/src/index.ts +26 -0
  209. package/src/layout/AspectRatio.tsx +39 -0
  210. package/src/layout/Container.tsx +53 -0
  211. package/src/layout/Divider.tsx +61 -0
  212. package/src/layout/Flex.tsx +79 -0
  213. package/src/layout/Grid.tsx +124 -0
  214. package/src/layout/PageLayout.tsx +59 -0
  215. package/src/layout/ScrollArea.tsx +43 -0
  216. package/src/layout/Section.tsx +47 -0
  217. package/src/layout/Spacer.tsx +30 -0
  218. package/src/layout/Stack.tsx +88 -0
  219. package/src/layout/index.ts +10 -0
  220. package/src/layout/tokens.css +8 -0
  221. package/src/navigation/Breadcrumb.tsx +73 -0
  222. package/src/navigation/CommandPalette.tsx +142 -0
  223. package/src/navigation/DropdownMenu.tsx +160 -0
  224. package/src/navigation/Pagination.tsx +114 -0
  225. package/src/navigation/Stepper.tsx +93 -0
  226. package/src/navigation/Tabs.tsx +133 -0
  227. package/src/navigation/index.ts +6 -0
  228. package/src/navigation/tokens.css +4 -0
  229. package/src/overlays/AlertDialog.tsx +54 -0
  230. package/src/overlays/BottomSheet.tsx +123 -0
  231. package/src/overlays/ContextMenu.tsx +119 -0
  232. package/src/overlays/Drawer.tsx +145 -0
  233. package/src/overlays/FocusTrap.tsx +49 -0
  234. package/src/overlays/HoverCard.tsx +72 -0
  235. package/src/overlays/Modal.tsx +219 -0
  236. package/src/overlays/Popover.tsx +126 -0
  237. package/src/overlays/Portal.tsx +23 -0
  238. package/src/overlays/Toast.tsx +137 -0
  239. package/src/overlays/Tooltip.tsx +100 -0
  240. package/src/overlays/index.ts +11 -0
  241. package/src/overlays/tokens.css +8 -0
  242. package/src/styles/tokens.css +2 -0
  243. package/src/typography/Blockquote.tsx +32 -0
  244. package/src/typography/Code.tsx +89 -0
  245. package/src/typography/Heading.tsx +56 -0
  246. package/src/typography/Kbd.tsx +25 -0
  247. package/src/typography/Label.tsx +47 -0
  248. package/src/typography/Link.tsx +56 -0
  249. package/src/typography/Text.tsx +62 -0
  250. package/src/typography/index.ts +7 -0
  251. package/src/typography/tokens.css +5 -0
  252. package/src/utils/cn.ts +6 -0
  253. package/ui-contract.json +62 -0
@@ -0,0 +1,954 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var reactDom = require('react-dom');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var classVarianceAuthority = require('class-variance-authority');
7
+ var lucideReact = require('lucide-react');
8
+ var clsx = require('clsx');
9
+ var tailwindMerge = require('tailwind-merge');
10
+
11
+ // src/overlays/Portal.tsx
12
+ function Portal({ children, container }) {
13
+ const [mounted, setMounted] = react.useState(false);
14
+ react.useEffect(() => {
15
+ setMounted(true);
16
+ return () => setMounted(false);
17
+ }, []);
18
+ if (!mounted) return null;
19
+ const target = container || (typeof document !== "undefined" ? document.body : null);
20
+ if (!target) return null;
21
+ return reactDom.createPortal(children, target);
22
+ }
23
+ var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
24
+ function FocusTrap({ children, active = true }) {
25
+ const rootRef = react.useRef(null);
26
+ react.useEffect(() => {
27
+ if (!active) return;
28
+ const root = rootRef.current;
29
+ if (!root) return;
30
+ const focusable = root.querySelectorAll(FOCUSABLE_SELECTOR);
31
+ const first = focusable[0];
32
+ const last = focusable[focusable.length - 1];
33
+ if (first) {
34
+ first.focus();
35
+ }
36
+ const handleKeyDown = (e) => {
37
+ if (e.key !== "Tab") return;
38
+ if (e.shiftKey) {
39
+ if (document.activeElement === first) {
40
+ e.preventDefault();
41
+ last?.focus();
42
+ }
43
+ } else {
44
+ if (document.activeElement === last) {
45
+ e.preventDefault();
46
+ first?.focus();
47
+ }
48
+ }
49
+ };
50
+ window.addEventListener("keydown", handleKeyDown);
51
+ return () => window.removeEventListener("keydown", handleKeyDown);
52
+ }, [active]);
53
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: rootRef, className: "contents", children });
54
+ }
55
+ function cn(...inputs) {
56
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
57
+ }
58
+ var ModalContext = react.createContext(null);
59
+ function useModal() {
60
+ const context = react.useContext(ModalContext);
61
+ if (!context) {
62
+ throw new Error("Modal compound components must be used within a <Modal />");
63
+ }
64
+ return context;
65
+ }
66
+ function Modal({
67
+ isOpen,
68
+ onClose,
69
+ children,
70
+ closeOnEsc = true,
71
+ closeOnOverlayClick = true
72
+ }) {
73
+ react.useEffect(() => {
74
+ if (!isOpen) return;
75
+ const handleKeyDown = (e) => {
76
+ if (closeOnEsc && e.key === "Escape") {
77
+ onClose();
78
+ }
79
+ };
80
+ const originalOverflow = document.body.style.overflow;
81
+ document.body.style.overflow = "hidden";
82
+ window.addEventListener("keydown", handleKeyDown);
83
+ return () => {
84
+ window.removeEventListener("keydown", handleKeyDown);
85
+ document.body.style.overflow = originalOverflow;
86
+ };
87
+ }, [isOpen, closeOnEsc, onClose]);
88
+ if (!isOpen) return null;
89
+ return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(ModalContext.Provider, { value: { isOpen, onClose, closeOnOverlayClick }, children: /* @__PURE__ */ jsxRuntime.jsx(FocusTrap, { active: isOpen, children: /* @__PURE__ */ jsxRuntime.jsx(
90
+ "div",
91
+ {
92
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6",
93
+ role: "dialog",
94
+ "aria-modal": "true",
95
+ children
96
+ }
97
+ ) }) }) });
98
+ }
99
+ var ModalOverlay = react.forwardRef(
100
+ ({ className, onClick, ...props }, ref) => {
101
+ const { onClose, closeOnOverlayClick } = useModal();
102
+ return /* @__PURE__ */ jsxRuntime.jsx(
103
+ "div",
104
+ {
105
+ ref,
106
+ "aria-hidden": "true",
107
+ onClick: (e) => {
108
+ onClick?.(e);
109
+ if (closeOnOverlayClick) onClose();
110
+ },
111
+ className: cn(
112
+ "fixed inset-0 bg-[var(--ui-bg-overlay)] backdrop-blur-sm transition-opacity animate-in fade-in duration-200",
113
+ className
114
+ ),
115
+ ...props
116
+ }
117
+ );
118
+ }
119
+ );
120
+ ModalOverlay.displayName = "ModalOverlay";
121
+ var modalContentVariants = classVarianceAuthority.cva(
122
+ "relative w-full max-w-lg rounded-[var(--ui-radius-xl)] bg-[var(--ui-bg-surface)] border border-[var(--ui-border-default)] p-6 text-[var(--ui-text-primary)] shadow-2xl transition-all animate-in zoom-in-95 duration-200 z-10",
123
+ {
124
+ variants: {
125
+ size: {
126
+ sm: "max-w-sm",
127
+ md: "max-w-md",
128
+ lg: "max-w-lg",
129
+ xl: "max-w-xl",
130
+ "2xl": "max-w-2xl",
131
+ full: "max-w-[calc(100vw-2rem)] h-[calc(100vh-2rem)]"
132
+ }
133
+ },
134
+ defaultVariants: {
135
+ size: "md"
136
+ }
137
+ }
138
+ );
139
+ var ModalContent = react.forwardRef(
140
+ ({ className, size, children, ...props }, ref) => {
141
+ return /* @__PURE__ */ jsxRuntime.jsx(
142
+ "div",
143
+ {
144
+ ref,
145
+ className: cn(modalContentVariants({ size }), className),
146
+ ...props,
147
+ children
148
+ }
149
+ );
150
+ }
151
+ );
152
+ ModalContent.displayName = "ModalContent";
153
+ var ModalHeader = react.forwardRef(
154
+ ({ className, children, ...props }, ref) => {
155
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col space-y-1.5 mb-4", className), ...props, children });
156
+ }
157
+ );
158
+ ModalHeader.displayName = "ModalHeader";
159
+ var ModalTitle = react.forwardRef(
160
+ ({ className, children, ...props }, ref) => {
161
+ return /* @__PURE__ */ jsxRuntime.jsx("h2", { ref, className: cn("text-lg sm:text-xl font-bold tracking-tight text-[var(--ui-text-primary)]", className), ...props, children });
162
+ }
163
+ );
164
+ ModalTitle.displayName = "ModalTitle";
165
+ var ModalDescription = react.forwardRef(
166
+ ({ className, children, ...props }, ref) => {
167
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-[var(--ui-text-muted)]", className), ...props, children });
168
+ }
169
+ );
170
+ ModalDescription.displayName = "ModalDescription";
171
+ var ModalBody = react.forwardRef(
172
+ ({ className, children, ...props }, ref) => {
173
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("py-2", className), ...props, children });
174
+ }
175
+ );
176
+ ModalBody.displayName = "ModalBody";
177
+ var ModalFooter = react.forwardRef(
178
+ ({ className, children, ...props }, ref) => {
179
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex items-center justify-end gap-3 mt-6 pt-4 border-t border-[var(--ui-border-subtle)]", className), ...props, children });
180
+ }
181
+ );
182
+ ModalFooter.displayName = "ModalFooter";
183
+ var ModalCloseButton = react.forwardRef(
184
+ ({ className, onClick, ...props }, ref) => {
185
+ const { onClose } = useModal();
186
+ return /* @__PURE__ */ jsxRuntime.jsx(
187
+ "button",
188
+ {
189
+ ref,
190
+ type: "button",
191
+ onClick: (e) => {
192
+ onClick?.(e);
193
+ onClose();
194
+ },
195
+ "aria-label": "Close dialog",
196
+ className: cn(
197
+ "absolute top-4 right-4 p-1.5 rounded-full text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)] transition-colors",
198
+ className
199
+ ),
200
+ ...props,
201
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
202
+ }
203
+ );
204
+ }
205
+ );
206
+ ModalCloseButton.displayName = "ModalCloseButton";
207
+ var buttonVariants = classVarianceAuthority.cva(
208
+ "relative inline-flex items-center justify-center font-medium transition-all duration-200 select-none cursor-pointer disabled:pointer-events-none disabled:opacity-40 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[var(--ui-primary)]/30 active:scale-[0.97] overflow-hidden",
209
+ {
210
+ variants: {
211
+ variant: {
212
+ primary: "bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] text-white shadow-sm hover:shadow-[0_4px_16px_rgba(0,113,227,0.35)] border border-white/20",
213
+ secondary: "bg-[var(--ui-bg-tertiary)] hover:bg-[var(--ui-bg-surface)] text-[var(--ui-text-primary)] border border-[var(--ui-border-subtle)] shadow-sm",
214
+ outline: "border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)]/60 backdrop-blur-xl text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)] hover:border-[var(--ui-border-strong)] shadow-sm",
215
+ ghost: "bg-transparent text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)]/70",
216
+ danger: "bg-[var(--ui-error)] hover:bg-[var(--ui-error)]/90 text-white shadow-sm hover:shadow-[0_4px_16px_rgba(255,59,48,0.35)] border border-white/15",
217
+ link: "bg-transparent text-[var(--ui-primary)] underline-offset-4 hover:underline p-0 h-auto active:scale-100 font-normal",
218
+ glass: "bg-white/10 dark:bg-white/10 backdrop-blur-2xl border border-white/20 dark:border-white/15 text-[var(--ui-text-primary)] hover:bg-white/20 dark:hover:bg-white/15 shadow-[0_8px_32px_rgba(0,0,0,0.12)] hover:shadow-[0_8px_32px_rgba(0,113,227,0.25)]"
219
+ },
220
+ size: {
221
+ xs: "h-7 px-2.5 text-xs rounded-[var(--ui-radius-sm)] gap-1",
222
+ sm: "h-8.5 px-3.5 text-xs rounded-[var(--ui-radius-md)] gap-1.5",
223
+ md: "h-10 px-4.5 text-sm rounded-[var(--ui-radius-md)] gap-2 font-semibold",
224
+ lg: "h-12 px-6 text-base rounded-[var(--ui-radius-lg)] gap-2.5 font-semibold",
225
+ xl: "h-14 px-8 text-lg rounded-[var(--ui-radius-xl)] gap-3 font-bold"
226
+ },
227
+ fullWidth: {
228
+ true: "w-full",
229
+ false: ""
230
+ }
231
+ },
232
+ defaultVariants: {
233
+ variant: "primary",
234
+ size: "md",
235
+ fullWidth: false
236
+ }
237
+ }
238
+ );
239
+ var Button = react.forwardRef(
240
+ ({
241
+ className,
242
+ variant,
243
+ size,
244
+ fullWidth,
245
+ loading = false,
246
+ loadingText,
247
+ leftIcon,
248
+ rightIcon,
249
+ disabled,
250
+ children,
251
+ ...props
252
+ }, ref) => {
253
+ const isDisabled = disabled || loading;
254
+ return /* @__PURE__ */ jsxRuntime.jsxs(
255
+ "button",
256
+ {
257
+ ref,
258
+ disabled: isDisabled,
259
+ className: cn(buttonVariants({ variant, size, fullWidth }), className),
260
+ ...props,
261
+ children: [
262
+ /* @__PURE__ */ jsxRuntime.jsx(
263
+ "span",
264
+ {
265
+ "aria-hidden": "true",
266
+ className: "absolute inset-x-0 top-0 h-[1px] bg-gradient-to-r from-transparent via-white/35 to-transparent pointer-events-none"
267
+ }
268
+ ),
269
+ loading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
270
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "w-4 h-4 animate-spin" }),
271
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: loadingText || children })
272
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
273
+ leftIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 inline-flex items-center", children: leftIcon }),
274
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children }),
275
+ rightIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 inline-flex items-center", children: rightIcon })
276
+ ] })
277
+ ]
278
+ }
279
+ );
280
+ }
281
+ );
282
+ Button.displayName = "Button";
283
+ function AlertDialog({
284
+ isOpen,
285
+ onClose,
286
+ onConfirm,
287
+ title,
288
+ description,
289
+ confirmText = "Confirm",
290
+ cancelText = "Cancel",
291
+ variant = "danger",
292
+ isLoading = false
293
+ }) {
294
+ return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { isOpen, onClose, children: [
295
+ /* @__PURE__ */ jsxRuntime.jsx(ModalOverlay, {}),
296
+ /* @__PURE__ */ jsxRuntime.jsxs(ModalContent, { size: "sm", children: [
297
+ /* @__PURE__ */ jsxRuntime.jsx(ModalCloseButton, {}),
298
+ /* @__PURE__ */ jsxRuntime.jsxs(ModalHeader, { children: [
299
+ /* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { children: title }),
300
+ /* @__PURE__ */ jsxRuntime.jsx(ModalDescription, { children: description })
301
+ ] }),
302
+ /* @__PURE__ */ jsxRuntime.jsxs(ModalFooter, { children: [
303
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", size: "sm", onClick: onClose, disabled: isLoading, children: cancelText }),
304
+ /* @__PURE__ */ jsxRuntime.jsx(
305
+ Button,
306
+ {
307
+ variant: variant === "danger" ? "danger" : "primary",
308
+ size: "sm",
309
+ loading: isLoading,
310
+ onClick: onConfirm,
311
+ children: confirmText
312
+ }
313
+ )
314
+ ] })
315
+ ] })
316
+ ] });
317
+ }
318
+ var DrawerContext = react.createContext(null);
319
+ function useDrawer() {
320
+ const context = react.useContext(DrawerContext);
321
+ if (!context) {
322
+ throw new Error("Drawer compound components must be used within a <Drawer />");
323
+ }
324
+ return context;
325
+ }
326
+ var drawerVariants = classVarianceAuthority.cva(
327
+ "fixed z-50 bg-[var(--ui-bg-surface)] text-[var(--ui-text-primary)] border-[var(--ui-border-default)] shadow-2xl transition-transform duration-300 ease-in-out flex flex-col",
328
+ {
329
+ variants: {
330
+ placement: {
331
+ right: "inset-y-0 right-0 h-full w-full sm:max-w-md border-l animate-in slide-in-from-right",
332
+ left: "inset-y-0 left-0 h-full w-full sm:max-w-md border-r animate-in slide-in-from-left",
333
+ top: "inset-x-0 top-0 w-full max-h-[80vh] border-b animate-in slide-in-from-top",
334
+ bottom: "inset-x-0 bottom-0 w-full max-h-[80vh] border-t rounded-t-[var(--ui-radius-xl)] animate-in slide-in-from-bottom"
335
+ }
336
+ },
337
+ defaultVariants: {
338
+ placement: "right"
339
+ }
340
+ }
341
+ );
342
+ function Drawer({
343
+ isOpen,
344
+ onClose,
345
+ placement = "right",
346
+ children,
347
+ closeOnEsc = true
348
+ }) {
349
+ react.useEffect(() => {
350
+ if (!isOpen) return;
351
+ const handleKeyDown = (e) => {
352
+ if (closeOnEsc && e.key === "Escape") {
353
+ onClose();
354
+ }
355
+ };
356
+ const originalOverflow = document.body.style.overflow;
357
+ document.body.style.overflow = "hidden";
358
+ window.addEventListener("keydown", handleKeyDown);
359
+ return () => {
360
+ window.removeEventListener("keydown", handleKeyDown);
361
+ document.body.style.overflow = originalOverflow;
362
+ };
363
+ }, [isOpen, closeOnEsc, onClose]);
364
+ if (!isOpen) return null;
365
+ return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(DrawerContext.Provider, { value: { isOpen, onClose }, children: /* @__PURE__ */ jsxRuntime.jsx(FocusTrap, { active: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 overflow-hidden", children: [
366
+ /* @__PURE__ */ jsxRuntime.jsx(
367
+ "div",
368
+ {
369
+ "aria-hidden": "true",
370
+ onClick: onClose,
371
+ className: "fixed inset-0 bg-[var(--ui-bg-overlay)] backdrop-blur-sm transition-opacity animate-in fade-in duration-200"
372
+ }
373
+ ),
374
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(drawerVariants({ placement })), children })
375
+ ] }) }) }) });
376
+ }
377
+ var DrawerHeader = react.forwardRef(
378
+ ({ className, children, ...props }, ref) => {
379
+ const { onClose } = useDrawer();
380
+ return /* @__PURE__ */ jsxRuntime.jsxs(
381
+ "div",
382
+ {
383
+ ref,
384
+ className: cn("flex items-center justify-between p-5 border-b border-[var(--ui-border-subtle)]", className),
385
+ ...props,
386
+ children: [
387
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children }),
388
+ /* @__PURE__ */ jsxRuntime.jsx(
389
+ "button",
390
+ {
391
+ type: "button",
392
+ onClick: onClose,
393
+ "aria-label": "Close drawer",
394
+ className: "p-1.5 rounded-full text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)] transition-colors ml-4",
395
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
396
+ }
397
+ )
398
+ ]
399
+ }
400
+ );
401
+ }
402
+ );
403
+ DrawerHeader.displayName = "DrawerHeader";
404
+ var DrawerBody = react.forwardRef(
405
+ ({ className, children, ...props }, ref) => {
406
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex-1 p-5 overflow-y-auto", className), ...props, children });
407
+ }
408
+ );
409
+ DrawerBody.displayName = "DrawerBody";
410
+ var DrawerFooter = react.forwardRef(
411
+ ({ className, children, ...props }, ref) => {
412
+ return /* @__PURE__ */ jsxRuntime.jsx(
413
+ "div",
414
+ {
415
+ ref,
416
+ className: cn("p-4 border-t border-[var(--ui-border-subtle)] bg-[var(--ui-bg-secondary)] flex items-center justify-end gap-3", className),
417
+ ...props,
418
+ children
419
+ }
420
+ );
421
+ }
422
+ );
423
+ DrawerFooter.displayName = "DrawerFooter";
424
+ var tooltipVariants = classVarianceAuthority.cva(
425
+ "z-50 overflow-hidden rounded-[var(--ui-radius-sm)] bg-[var(--ui-bg-primary)] border border-[var(--ui-border-default)] px-2.5 py-1 text-xs font-medium text-[var(--ui-text-primary)] shadow-md animate-in fade-in zoom-in-95 pointer-events-none select-none",
426
+ {
427
+ variants: {
428
+ placement: {
429
+ top: "-translate-x-1/2 -translate-y-full mb-1.5",
430
+ bottom: "-translate-x-1/2 mt-1.5",
431
+ left: "-translate-x-full -translate-y-1/2 mr-1.5",
432
+ right: "translate-y-[-50%] ml-1.5"
433
+ }
434
+ },
435
+ defaultVariants: {
436
+ placement: "top"
437
+ }
438
+ }
439
+ );
440
+ function Tooltip({
441
+ content,
442
+ children,
443
+ placement = "top",
444
+ delayDuration = 200,
445
+ className
446
+ }) {
447
+ const [isVisible, setIsVisible] = react.useState(false);
448
+ const [coords, setCoords] = react.useState({ top: 0, left: 0 });
449
+ const timeoutRef = react.useRef(null);
450
+ const triggerRef = react.useRef(null);
451
+ const handleMouseEnter = () => {
452
+ timeoutRef.current = setTimeout(() => {
453
+ if (triggerRef.current) {
454
+ const rect = triggerRef.current.getBoundingClientRect();
455
+ let top = 0;
456
+ let left = 0;
457
+ if (placement === "top") {
458
+ top = rect.top + window.scrollY;
459
+ left = rect.left + rect.width / 2 + window.scrollX;
460
+ } else if (placement === "bottom") {
461
+ top = rect.bottom + window.scrollY;
462
+ left = rect.left + rect.width / 2 + window.scrollX;
463
+ } else if (placement === "left") {
464
+ top = rect.top + rect.height / 2 + window.scrollY;
465
+ left = rect.left + window.scrollX;
466
+ } else if (placement === "right") {
467
+ top = rect.top + rect.height / 2 + window.scrollY;
468
+ left = rect.right + window.scrollX;
469
+ }
470
+ setCoords({ top, left });
471
+ setIsVisible(true);
472
+ }
473
+ }, delayDuration);
474
+ };
475
+ const handleMouseLeave = () => {
476
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
477
+ setIsVisible(false);
478
+ };
479
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
480
+ /* @__PURE__ */ jsxRuntime.jsx(
481
+ "div",
482
+ {
483
+ ref: triggerRef,
484
+ onMouseEnter: handleMouseEnter,
485
+ onMouseLeave: handleMouseLeave,
486
+ onFocus: handleMouseEnter,
487
+ onBlur: handleMouseLeave,
488
+ className: "inline-flex cursor-pointer",
489
+ children
490
+ }
491
+ ),
492
+ isVisible && /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
493
+ "div",
494
+ {
495
+ style: { top: `${coords.top}px`, left: `${coords.left}px`, position: "absolute" },
496
+ role: "tooltip",
497
+ className: cn(tooltipVariants({ placement }), className),
498
+ children: content
499
+ }
500
+ ) })
501
+ ] });
502
+ }
503
+ var Popover = ({
504
+ trigger,
505
+ children,
506
+ isOpen: controlledIsOpen,
507
+ onClose,
508
+ placement = "bottom",
509
+ className
510
+ }) => {
511
+ const [internalIsOpen, setInternalIsOpen] = react.useState(false);
512
+ const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
513
+ const [coords, setCoords] = react.useState({ top: 0, left: 0 });
514
+ const triggerRef = react.useRef(null);
515
+ const popoverRef = react.useRef(null);
516
+ const calculatePosition = () => {
517
+ if (triggerRef.current) {
518
+ const rect = triggerRef.current.getBoundingClientRect();
519
+ let top = 0;
520
+ let left = 0;
521
+ if (placement === "bottom") {
522
+ top = rect.bottom + window.scrollY + 8;
523
+ left = rect.left + window.scrollX;
524
+ } else if (placement === "top") {
525
+ top = rect.top + window.scrollY - 8;
526
+ left = rect.left + window.scrollX;
527
+ } else if (placement === "right") {
528
+ top = rect.top + window.scrollY;
529
+ left = rect.right + window.scrollX + 8;
530
+ } else if (placement === "left") {
531
+ top = rect.top + window.scrollY;
532
+ left = rect.left + window.scrollX - 8;
533
+ }
534
+ setCoords({ top, left });
535
+ }
536
+ };
537
+ const handleToggle = () => {
538
+ if (!isOpen) {
539
+ calculatePosition();
540
+ }
541
+ if (controlledIsOpen !== void 0) {
542
+ if (isOpen) onClose?.();
543
+ } else {
544
+ setInternalIsOpen(!internalIsOpen);
545
+ }
546
+ };
547
+ react.useEffect(() => {
548
+ if (isOpen) {
549
+ calculatePosition();
550
+ }
551
+ }, [isOpen]);
552
+ react.useEffect(() => {
553
+ const handleOutside = (e) => {
554
+ if (popoverRef.current && !popoverRef.current.contains(e.target) && triggerRef.current && !triggerRef.current.contains(e.target)) {
555
+ if (controlledIsOpen !== void 0) {
556
+ onClose?.();
557
+ } else {
558
+ setInternalIsOpen(false);
559
+ }
560
+ }
561
+ };
562
+ if (isOpen) {
563
+ document.addEventListener("mousedown", handleOutside);
564
+ window.addEventListener("resize", calculatePosition);
565
+ window.addEventListener("scroll", calculatePosition);
566
+ }
567
+ return () => {
568
+ document.removeEventListener("mousedown", handleOutside);
569
+ window.removeEventListener("resize", calculatePosition);
570
+ window.removeEventListener("scroll", calculatePosition);
571
+ };
572
+ }, [isOpen, controlledIsOpen, onClose]);
573
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
574
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: triggerRef, onClick: handleToggle, className: "w-full inline-block cursor-pointer", children: trigger }),
575
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
576
+ "div",
577
+ {
578
+ ref: popoverRef,
579
+ style: {
580
+ top: `${coords.top}px`,
581
+ left: `${coords.left}px`,
582
+ position: "absolute"
583
+ },
584
+ className: cn(
585
+ "z-50 min-w-[12rem] rounded-[var(--ui-radius-lg)] bg-[var(--ui-bg-surface)] border border-[var(--ui-border-default)] p-4 text-[var(--ui-text-primary)] shadow-xl animate-in fade-in zoom-in-95",
586
+ placement === "top" && "-translate-y-full",
587
+ placement === "left" && "-translate-x-full",
588
+ className
589
+ ),
590
+ children
591
+ }
592
+ ) })
593
+ ] });
594
+ };
595
+ var ToastContext = react.createContext(null);
596
+ function useToast() {
597
+ const context = react.useContext(ToastContext);
598
+ if (!context) {
599
+ throw new Error("useToast must be used within a ToasterProvider");
600
+ }
601
+ return context;
602
+ }
603
+ var toastVariants = classVarianceAuthority.cva(
604
+ "pointer-events-auto flex w-full max-w-md items-start gap-3 rounded-[var(--ui-radius-lg)] border p-4 shadow-lg transition-all animate-in slide-in-from-bottom-5 duration-300",
605
+ {
606
+ variants: {
607
+ type: {
608
+ info: "bg-[var(--ui-bg-surface)] border-[var(--ui-info)]/30 text-[var(--ui-text-primary)]",
609
+ success: "bg-[var(--ui-bg-surface)] border-[var(--ui-success)]/30 text-[var(--ui-text-primary)]",
610
+ warning: "bg-[var(--ui-bg-surface)] border-[var(--ui-warning)]/30 text-[var(--ui-text-primary)]",
611
+ error: "bg-[var(--ui-bg-surface)] border-[var(--ui-error)]/30 text-[var(--ui-text-primary)]"
612
+ }
613
+ },
614
+ defaultVariants: {
615
+ type: "info"
616
+ }
617
+ }
618
+ );
619
+ var toastIcons = {
620
+ info: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "w-5 h-5 text-[var(--ui-info)] flex-shrink-0" }),
621
+ success: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "w-5 h-5 text-[var(--ui-success)] flex-shrink-0" }),
622
+ warning: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "w-5 h-5 text-[var(--ui-warning)] flex-shrink-0" }),
623
+ error: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "w-5 h-5 text-[var(--ui-error)] flex-shrink-0" })
624
+ };
625
+ function ToasterProvider({ children, position = "bottom-right" }) {
626
+ const [toasts, setToasts] = react.useState([]);
627
+ const dismiss = react.useCallback((id) => {
628
+ setToasts((prev) => prev.filter((t) => t.id !== id));
629
+ }, []);
630
+ const toast = react.useCallback(
631
+ ({ id = Math.random().toString(36).slice(2, 9), title, description, type = "info", duration = 4e3 }) => {
632
+ const item = { id, title, description, type, duration };
633
+ setToasts((prev) => [...prev, item]);
634
+ if (duration > 0) {
635
+ setTimeout(() => {
636
+ dismiss(id);
637
+ }, duration);
638
+ }
639
+ return id;
640
+ },
641
+ [dismiss]
642
+ );
643
+ const getPositionClasses = () => {
644
+ switch (position) {
645
+ case "top-left":
646
+ return "top-4 left-4 items-start";
647
+ case "top-center":
648
+ return "top-4 left-1/2 -translate-x-1/2 items-center";
649
+ case "top-right":
650
+ return "top-4 right-4 items-end";
651
+ case "bottom-left":
652
+ return "bottom-4 left-4 items-start";
653
+ case "bottom-center":
654
+ return "bottom-4 left-1/2 -translate-x-1/2 items-center";
655
+ case "bottom-right":
656
+ default:
657
+ return "bottom-4 right-4 items-end";
658
+ }
659
+ };
660
+ return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast, dismiss, toasts }, children: [
661
+ children,
662
+ /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
663
+ "div",
664
+ {
665
+ "aria-live": "polite",
666
+ className: cn("fixed z-[100] flex flex-col gap-2 pointer-events-none p-4 w-full max-w-sm sm:max-w-md", getPositionClasses()),
667
+ children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(toastVariants({ type: t.type })), children: [
668
+ toastIcons[t.type || "info"],
669
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-1", children: [
670
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold text-[var(--ui-text-primary)]", children: t.title }),
671
+ t.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-[var(--ui-text-muted)]", children: t.description })
672
+ ] }),
673
+ /* @__PURE__ */ jsxRuntime.jsx(
674
+ "button",
675
+ {
676
+ type: "button",
677
+ onClick: () => dismiss(t.id),
678
+ "aria-label": "Dismiss toast",
679
+ className: "p-1 rounded text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)] transition-colors",
680
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3.5 h-3.5" })
681
+ }
682
+ )
683
+ ] }, t.id))
684
+ }
685
+ ) })
686
+ ] });
687
+ }
688
+ var BottomSheet = react.forwardRef(
689
+ ({
690
+ isOpen,
691
+ onClose,
692
+ children,
693
+ title,
694
+ description,
695
+ className,
696
+ showHandle = true,
697
+ maxHeight = "max-h-[85vh]"
698
+ }, ref) => {
699
+ react.useRef(null);
700
+ react.useEffect(() => {
701
+ const handleKeyDown = (e) => {
702
+ if (e.key === "Escape" && isOpen) {
703
+ onClose();
704
+ }
705
+ };
706
+ window.addEventListener("keydown", handleKeyDown);
707
+ return () => window.removeEventListener("keydown", handleKeyDown);
708
+ }, [isOpen, onClose]);
709
+ if (!isOpen) return null;
710
+ return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(FocusTrap, { active: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex flex-col justify-end", children: [
711
+ /* @__PURE__ */ jsxRuntime.jsx(
712
+ "div",
713
+ {
714
+ onClick: onClose,
715
+ className: "fixed inset-0 bg-black/60 backdrop-blur-md transition-opacity animate-in fade-in duration-300",
716
+ "aria-hidden": "true"
717
+ }
718
+ ),
719
+ /* @__PURE__ */ jsxRuntime.jsxs(
720
+ "div",
721
+ {
722
+ ref,
723
+ className: cn(
724
+ "relative z-50 w-full max-w-2xl mx-auto rounded-t-[2rem] border-t border-x border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)] backdrop-blur-3xl shadow-2xl overflow-hidden flex flex-col transition-transform animate-in slide-in-from-bottom duration-300",
725
+ maxHeight,
726
+ className
727
+ ),
728
+ children: [
729
+ showHandle && /* @__PURE__ */ jsxRuntime.jsx(
730
+ "div",
731
+ {
732
+ onClick: onClose,
733
+ className: "w-full py-3 flex items-center justify-center cursor-grab active:cursor-grabbing",
734
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-1.5 rounded-full bg-[var(--ui-text-muted)]/40 hover:bg-[var(--ui-text-muted)] transition-colors" })
735
+ }
736
+ ),
737
+ (title || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-3 flex items-center justify-between border-b border-[var(--ui-border-subtle)]", children: [
738
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
739
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold tracking-tight text-[var(--ui-text-primary)]", children: title }),
740
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-[var(--ui-text-muted)]", children: description })
741
+ ] }),
742
+ /* @__PURE__ */ jsxRuntime.jsx(
743
+ "button",
744
+ {
745
+ type: "button",
746
+ onClick: onClose,
747
+ className: "p-1.5 rounded-full hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] transition-colors",
748
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
749
+ }
750
+ )
751
+ ] }),
752
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 overflow-y-auto flex-1 space-y-4", children })
753
+ ]
754
+ }
755
+ )
756
+ ] }) }) });
757
+ }
758
+ );
759
+ BottomSheet.displayName = "BottomSheet";
760
+ var BottomSheetHeader = ({ className, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-6 pb-2", className), ...props, children });
761
+ var BottomSheetBody = ({ className, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-6 py-2 overflow-y-auto", className), ...props, children });
762
+ var BottomSheetFooter = ({ className, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 pt-3 border-t border-[var(--ui-border-subtle)] flex items-center justify-end gap-3", className), ...props, children });
763
+ var Kbd = react.forwardRef(
764
+ ({ className, children, ...props }, ref) => {
765
+ return /* @__PURE__ */ jsxRuntime.jsx(
766
+ "kbd",
767
+ {
768
+ ref,
769
+ className: cn(
770
+ "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-[var(--ui-border-default)] bg-[var(--ui-bg-tertiary)] px-1.5 font-mono text-[10px] font-semibold text-[var(--ui-text-muted)] opacity-100 shadow-sm",
771
+ className
772
+ ),
773
+ ...props,
774
+ children
775
+ }
776
+ );
777
+ }
778
+ );
779
+ Kbd.displayName = "Kbd";
780
+ var ContextMenuItem = ({
781
+ icon,
782
+ shortcut,
783
+ disabled = false,
784
+ destructive = false,
785
+ onSelect,
786
+ children,
787
+ className,
788
+ ...props
789
+ }) => {
790
+ return /* @__PURE__ */ jsxRuntime.jsxs(
791
+ "div",
792
+ {
793
+ role: "menuitem",
794
+ "aria-disabled": disabled,
795
+ onClick: () => {
796
+ if (!disabled) onSelect?.();
797
+ },
798
+ className: cn(
799
+ "flex items-center justify-between px-3 py-1.5 rounded-xl text-xs font-medium cursor-pointer transition-colors select-none",
800
+ disabled && "opacity-40 cursor-not-allowed pointer-events-none",
801
+ destructive ? "text-rose-500 hover:bg-rose-500/10" : "text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)]",
802
+ className
803
+ ),
804
+ ...props,
805
+ children: [
806
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
807
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 h-4 shrink-0", children: icon }),
808
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children })
809
+ ] }),
810
+ shortcut && /* @__PURE__ */ jsxRuntime.jsx(Kbd, { className: "text-[10px] py-0 px-1", children: shortcut })
811
+ ]
812
+ }
813
+ );
814
+ };
815
+ var ContextMenuSeparator = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px my-1 bg-[var(--ui-border-subtle)]", role: "separator" });
816
+ var ContextMenu = react.forwardRef(
817
+ ({ children, menuContent, className }, ref) => {
818
+ const [isOpen, setIsOpen] = react.useState(false);
819
+ const [position, setPosition] = react.useState({ x: 0, y: 0 });
820
+ const menuRef = react.useRef(null);
821
+ const handleContextMenu = (e) => {
822
+ e.preventDefault();
823
+ const x = Math.min(window.innerWidth - 220, e.clientX);
824
+ const y = Math.min(window.innerHeight - 260, e.clientY);
825
+ setPosition({ x, y });
826
+ setIsOpen(true);
827
+ };
828
+ react.useEffect(() => {
829
+ const handleClickOutside = (e) => {
830
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
831
+ setIsOpen(false);
832
+ }
833
+ };
834
+ const handleKeyDown = (e) => {
835
+ if (e.key === "Escape") setIsOpen(false);
836
+ };
837
+ if (isOpen) {
838
+ window.addEventListener("click", handleClickOutside);
839
+ window.addEventListener("contextmenu", handleClickOutside);
840
+ window.addEventListener("keydown", handleKeyDown);
841
+ }
842
+ return () => {
843
+ window.removeEventListener("click", handleClickOutside);
844
+ window.removeEventListener("contextmenu", handleClickOutside);
845
+ window.removeEventListener("keydown", handleKeyDown);
846
+ };
847
+ }, [isOpen]);
848
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
849
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref, onContextMenu: handleContextMenu, className, children }),
850
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
851
+ "div",
852
+ {
853
+ ref: menuRef,
854
+ style: { top: `${position.y}px`, left: `${position.x}px` },
855
+ onClick: () => setIsOpen(false),
856
+ className: "fixed z-50 min-w-48 p-1.5 rounded-2xl bg-[var(--ui-bg-surface)]/90 backdrop-blur-3xl border border-[var(--ui-border-default)] shadow-2xl space-y-0.5 animate-in fade-in zoom-in-95 duration-150",
857
+ children: menuContent
858
+ }
859
+ ) })
860
+ ] });
861
+ }
862
+ );
863
+ ContextMenu.displayName = "ContextMenu";
864
+ var HoverCard = react.forwardRef(
865
+ ({ trigger, content, openDelay = 200, closeDelay = 250, className }, ref) => {
866
+ const [isOpen, setIsOpen] = react.useState(false);
867
+ const [coords, setCoords] = react.useState({ top: 0, left: 0 });
868
+ const triggerRef = react.useRef(null);
869
+ const openTimerRef = react.useRef(null);
870
+ const closeTimerRef = react.useRef(null);
871
+ const handleMouseEnter = () => {
872
+ clearTimeout(closeTimerRef.current);
873
+ openTimerRef.current = setTimeout(() => {
874
+ if (triggerRef.current) {
875
+ const rect = triggerRef.current.getBoundingClientRect();
876
+ setCoords({
877
+ top: rect.bottom + window.scrollY + 8,
878
+ left: Math.max(16, Math.min(window.innerWidth - 320, rect.left + window.scrollX))
879
+ });
880
+ setIsOpen(true);
881
+ }
882
+ }, openDelay);
883
+ };
884
+ const handleMouseLeave = () => {
885
+ clearTimeout(openTimerRef.current);
886
+ closeTimerRef.current = setTimeout(() => {
887
+ setIsOpen(false);
888
+ }, closeDelay);
889
+ };
890
+ return /* @__PURE__ */ jsxRuntime.jsxs(
891
+ "div",
892
+ {
893
+ ref,
894
+ className: "inline-block relative",
895
+ onMouseEnter: handleMouseEnter,
896
+ onMouseLeave: handleMouseLeave,
897
+ children: [
898
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: triggerRef, className: "inline-block", children: trigger }),
899
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
900
+ "div",
901
+ {
902
+ style: { top: `${coords.top}px`, left: `${coords.left}px` },
903
+ onMouseEnter: () => clearTimeout(closeTimerRef.current),
904
+ onMouseLeave: handleMouseLeave,
905
+ className: cn(
906
+ "fixed z-50 w-72 p-4 rounded-2xl bg-[var(--ui-bg-surface)] backdrop-blur-3xl border border-[var(--ui-border-default)] shadow-2xl animate-in fade-in zoom-in-95 duration-200",
907
+ className
908
+ ),
909
+ children: content
910
+ }
911
+ ) })
912
+ ]
913
+ }
914
+ );
915
+ }
916
+ );
917
+ HoverCard.displayName = "HoverCard";
918
+
919
+ exports.AlertDialog = AlertDialog;
920
+ exports.BottomSheet = BottomSheet;
921
+ exports.BottomSheetBody = BottomSheetBody;
922
+ exports.BottomSheetFooter = BottomSheetFooter;
923
+ exports.BottomSheetHeader = BottomSheetHeader;
924
+ exports.ContextMenu = ContextMenu;
925
+ exports.ContextMenuItem = ContextMenuItem;
926
+ exports.ContextMenuSeparator = ContextMenuSeparator;
927
+ exports.Drawer = Drawer;
928
+ exports.DrawerBody = DrawerBody;
929
+ exports.DrawerFooter = DrawerFooter;
930
+ exports.DrawerHeader = DrawerHeader;
931
+ exports.FocusTrap = FocusTrap;
932
+ exports.HoverCard = HoverCard;
933
+ exports.Modal = Modal;
934
+ exports.ModalBody = ModalBody;
935
+ exports.ModalCloseButton = ModalCloseButton;
936
+ exports.ModalContent = ModalContent;
937
+ exports.ModalDescription = ModalDescription;
938
+ exports.ModalFooter = ModalFooter;
939
+ exports.ModalHeader = ModalHeader;
940
+ exports.ModalOverlay = ModalOverlay;
941
+ exports.ModalTitle = ModalTitle;
942
+ exports.Popover = Popover;
943
+ exports.Portal = Portal;
944
+ exports.ToasterProvider = ToasterProvider;
945
+ exports.Tooltip = Tooltip;
946
+ exports.drawerVariants = drawerVariants;
947
+ exports.modalContentVariants = modalContentVariants;
948
+ exports.toastVariants = toastVariants;
949
+ exports.tooltipVariants = tooltipVariants;
950
+ exports.useDrawer = useDrawer;
951
+ exports.useModal = useModal;
952
+ exports.useToast = useToast;
953
+ //# sourceMappingURL=index.cjs.map
954
+ //# sourceMappingURL=index.cjs.map