@codefast/ui 0.0.2 → 0.0.4

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 (348) hide show
  1. package/dist/accordion.d.mts +9 -0
  2. package/dist/accordion.d.ts +9 -0
  3. package/dist/accordion.js +2 -0
  4. package/dist/accordion.js.map +1 -0
  5. package/dist/accordion.mjs +2 -0
  6. package/dist/accordion.mjs.map +1 -0
  7. package/dist/alert-dialog.d.mts +16 -0
  8. package/dist/alert-dialog.d.ts +16 -0
  9. package/dist/alert-dialog.js +2 -0
  10. package/dist/alert-dialog.js.map +1 -0
  11. package/dist/alert-dialog.mjs +2 -0
  12. package/dist/alert-dialog.mjs.map +1 -0
  13. package/dist/alert.d.mts +64 -0
  14. package/dist/alert.d.ts +64 -0
  15. package/dist/alert.js +2 -0
  16. package/dist/alert.js.map +1 -0
  17. package/dist/alert.mjs +2 -0
  18. package/dist/alert.mjs.map +1 -0
  19. package/dist/aspect-ratio.d.mts +6 -0
  20. package/dist/aspect-ratio.d.ts +6 -0
  21. package/dist/aspect-ratio.js +2 -0
  22. package/dist/aspect-ratio.js.map +1 -0
  23. package/dist/aspect-ratio.mjs +2 -0
  24. package/dist/aspect-ratio.mjs.map +1 -0
  25. package/dist/avatar.d.mts +8 -0
  26. package/dist/avatar.d.ts +8 -0
  27. package/dist/avatar.js +2 -0
  28. package/dist/avatar.js.map +1 -0
  29. package/dist/avatar.mjs +2 -0
  30. package/dist/avatar.mjs.map +1 -0
  31. package/dist/badge.d.mts +62 -0
  32. package/dist/badge.d.ts +62 -0
  33. package/dist/badge.js +2 -0
  34. package/dist/badge.js.map +1 -0
  35. package/dist/badge.mjs +2 -0
  36. package/dist/badge.mjs.map +1 -0
  37. package/dist/breadcrumb.d.mts +15 -0
  38. package/dist/breadcrumb.d.ts +15 -0
  39. package/dist/breadcrumb.js +2 -0
  40. package/dist/breadcrumb.js.map +1 -0
  41. package/dist/breadcrumb.mjs +2 -0
  42. package/dist/breadcrumb.mjs.map +1 -0
  43. package/dist/button.d.mts +65 -4
  44. package/dist/button.d.ts +65 -4
  45. package/dist/button.js +1 -1
  46. package/dist/button.js.map +1 -1
  47. package/dist/button.mjs +1 -1
  48. package/dist/button.mjs.map +1 -1
  49. package/dist/calendar.d.mts +7 -0
  50. package/dist/calendar.d.ts +7 -0
  51. package/dist/calendar.js +2 -0
  52. package/dist/calendar.js.map +1 -0
  53. package/dist/calendar.mjs +2 -0
  54. package/dist/calendar.mjs.map +1 -0
  55. package/dist/card.d.mts +9 -7
  56. package/dist/card.d.ts +9 -7
  57. package/dist/card.js +1 -1
  58. package/dist/card.js.map +1 -1
  59. package/dist/card.mjs +1 -1
  60. package/dist/card.mjs.map +1 -1
  61. package/dist/carousel.d.mts +22 -0
  62. package/dist/carousel.d.ts +22 -0
  63. package/dist/carousel.js +2 -0
  64. package/dist/carousel.js.map +1 -0
  65. package/dist/carousel.mjs +2 -0
  66. package/dist/carousel.mjs.map +1 -0
  67. package/dist/checkbox.d.mts +6 -0
  68. package/dist/checkbox.d.ts +6 -0
  69. package/dist/checkbox.js +2 -0
  70. package/dist/checkbox.js.map +1 -0
  71. package/dist/checkbox.mjs +2 -0
  72. package/dist/checkbox.mjs.map +1 -0
  73. package/dist/chunk-4ZL55G6C.js +2 -0
  74. package/dist/chunk-4ZL55G6C.js.map +1 -0
  75. package/dist/chunk-76AASLTX.mjs +2 -0
  76. package/dist/chunk-76AASLTX.mjs.map +1 -0
  77. package/dist/chunk-7UVSBFQU.js +2 -0
  78. package/dist/chunk-7UVSBFQU.js.map +1 -0
  79. package/dist/chunk-BP7PEVLB.js +2 -0
  80. package/dist/chunk-BP7PEVLB.js.map +1 -0
  81. package/dist/chunk-BPCLLQ62.mjs +2 -0
  82. package/dist/chunk-BPCLLQ62.mjs.map +1 -0
  83. package/dist/chunk-CAGY2ZSE.js +2 -0
  84. package/dist/chunk-CAGY2ZSE.js.map +1 -0
  85. package/dist/chunk-JTI7KCLO.mjs +2 -0
  86. package/dist/chunk-JTI7KCLO.mjs.map +1 -0
  87. package/dist/chunk-QZCQ42BP.js +2 -0
  88. package/dist/chunk-QZCQ42BP.js.map +1 -0
  89. package/dist/chunk-WZ4XIF6U.mjs +2 -0
  90. package/dist/chunk-WZ4XIF6U.mjs.map +1 -0
  91. package/dist/chunk-YQJHVJVX.mjs +2 -0
  92. package/dist/chunk-YQJHVJVX.mjs.map +1 -0
  93. package/dist/collapsible.d.mts +8 -0
  94. package/dist/collapsible.d.ts +8 -0
  95. package/dist/collapsible.js +2 -0
  96. package/dist/collapsible.js.map +1 -0
  97. package/dist/collapsible.mjs +2 -0
  98. package/dist/collapsible.mjs.map +1 -0
  99. package/dist/command.d.mts +89 -0
  100. package/dist/command.d.ts +89 -0
  101. package/dist/command.js +2 -0
  102. package/dist/command.js.map +1 -0
  103. package/dist/command.mjs +2 -0
  104. package/dist/command.mjs.map +1 -0
  105. package/dist/context-menu.d.mts +26 -0
  106. package/dist/context-menu.d.ts +26 -0
  107. package/dist/context-menu.js +2 -0
  108. package/dist/context-menu.js.map +1 -0
  109. package/dist/context-menu.mjs +2 -0
  110. package/dist/context-menu.mjs.map +1 -0
  111. package/dist/dialog.d.mts +15 -0
  112. package/dist/dialog.d.ts +15 -0
  113. package/dist/dialog.js +2 -0
  114. package/dist/dialog.js.map +1 -0
  115. package/dist/dialog.mjs +2 -0
  116. package/dist/dialog.mjs.map +1 -0
  117. package/dist/drawer.d.mts +18 -0
  118. package/dist/drawer.d.ts +18 -0
  119. package/dist/drawer.js +2 -0
  120. package/dist/drawer.js.map +1 -0
  121. package/dist/drawer.mjs +2 -0
  122. package/dist/drawer.mjs.map +1 -0
  123. package/dist/dropdown-menu.d.mts +26 -0
  124. package/dist/dropdown-menu.d.ts +26 -0
  125. package/dist/dropdown-menu.js +2 -0
  126. package/dist/dropdown-menu.js.map +1 -0
  127. package/dist/dropdown-menu.mjs +2 -0
  128. package/dist/dropdown-menu.mjs.map +1 -0
  129. package/dist/form.d.mts +27 -0
  130. package/dist/form.d.ts +27 -0
  131. package/dist/form.js +2 -0
  132. package/dist/form.js.map +1 -0
  133. package/dist/form.mjs +2 -0
  134. package/dist/form.mjs.map +1 -0
  135. package/dist/hover-card.d.mts +8 -0
  136. package/dist/hover-card.d.ts +8 -0
  137. package/dist/hover-card.js +2 -0
  138. package/dist/hover-card.js.map +1 -0
  139. package/dist/hover-card.mjs +2 -0
  140. package/dist/hover-card.mjs.map +1 -0
  141. package/dist/input-otp.d.mts +36 -0
  142. package/dist/input-otp.d.ts +36 -0
  143. package/dist/input-otp.js +2 -0
  144. package/dist/input-otp.js.map +1 -0
  145. package/dist/input-otp.mjs +2 -0
  146. package/dist/input-otp.mjs.map +1 -0
  147. package/dist/input.d.mts +5 -0
  148. package/dist/input.d.ts +5 -0
  149. package/dist/input.js +2 -0
  150. package/dist/input.js.map +1 -0
  151. package/dist/input.mjs +2 -0
  152. package/dist/input.mjs.map +1 -0
  153. package/dist/label.d.mts +6 -0
  154. package/dist/label.d.ts +6 -0
  155. package/dist/label.js +2 -0
  156. package/dist/label.js.map +1 -0
  157. package/dist/label.mjs +2 -0
  158. package/dist/label.mjs.map +1 -0
  159. package/dist/menubar.d.mts +30 -0
  160. package/dist/menubar.d.ts +30 -0
  161. package/dist/menubar.js +2 -0
  162. package/dist/menubar.js.map +1 -0
  163. package/dist/menubar.mjs +2 -0
  164. package/dist/menubar.mjs.map +1 -0
  165. package/dist/navigation-menu.d.mts +68 -0
  166. package/dist/navigation-menu.d.ts +68 -0
  167. package/dist/navigation-menu.js +2 -0
  168. package/dist/navigation-menu.js.map +1 -0
  169. package/dist/navigation-menu.mjs +2 -0
  170. package/dist/navigation-menu.mjs.map +1 -0
  171. package/dist/pagination.d.mts +16 -0
  172. package/dist/pagination.d.ts +16 -0
  173. package/dist/pagination.js +2 -0
  174. package/dist/pagination.js.map +1 -0
  175. package/dist/pagination.mjs +2 -0
  176. package/dist/pagination.mjs.map +1 -0
  177. package/dist/popover.d.mts +9 -0
  178. package/dist/popover.d.ts +9 -0
  179. package/dist/popover.js +2 -0
  180. package/dist/popover.js.map +1 -0
  181. package/dist/popover.mjs +2 -0
  182. package/dist/popover.mjs.map +1 -0
  183. package/dist/progress.d.mts +6 -0
  184. package/dist/progress.d.ts +6 -0
  185. package/dist/progress.js +2 -0
  186. package/dist/progress.js.map +1 -0
  187. package/dist/progress.mjs +2 -0
  188. package/dist/progress.mjs.map +1 -0
  189. package/dist/radio-group.d.mts +7 -0
  190. package/dist/radio-group.d.ts +7 -0
  191. package/dist/radio-group.js +2 -0
  192. package/dist/radio-group.js.map +1 -0
  193. package/dist/radio-group.mjs +2 -0
  194. package/dist/radio-group.mjs.map +1 -0
  195. package/dist/resizable.d.mts +26 -0
  196. package/dist/resizable.d.ts +26 -0
  197. package/dist/resizable.js +2 -0
  198. package/dist/resizable.js.map +1 -0
  199. package/dist/resizable.mjs +2 -0
  200. package/dist/resizable.mjs.map +1 -0
  201. package/dist/scroll-area.d.mts +7 -0
  202. package/dist/scroll-area.d.ts +7 -0
  203. package/dist/scroll-area.js +2 -0
  204. package/dist/scroll-area.js.map +1 -0
  205. package/dist/scroll-area.mjs +2 -0
  206. package/dist/scroll-area.mjs.map +1 -0
  207. package/dist/select.d.mts +15 -0
  208. package/dist/select.d.ts +15 -0
  209. package/dist/select.js +2 -0
  210. package/dist/select.js.map +1 -0
  211. package/dist/select.mjs +2 -0
  212. package/dist/select.mjs.map +1 -0
  213. package/dist/separator.d.mts +6 -0
  214. package/dist/separator.d.ts +6 -0
  215. package/dist/separator.js +2 -0
  216. package/dist/separator.js.map +1 -0
  217. package/dist/separator.mjs +2 -0
  218. package/dist/separator.mjs.map +1 -0
  219. package/dist/sheet.d.mts +75 -0
  220. package/dist/sheet.d.ts +75 -0
  221. package/dist/sheet.js +2 -0
  222. package/dist/sheet.js.map +1 -0
  223. package/dist/sheet.mjs +2 -0
  224. package/dist/sheet.mjs.map +1 -0
  225. package/dist/skeleton.d.mts +5 -0
  226. package/dist/skeleton.d.ts +5 -0
  227. package/dist/skeleton.js +2 -0
  228. package/dist/skeleton.js.map +1 -0
  229. package/dist/skeleton.mjs +2 -0
  230. package/dist/skeleton.mjs.map +1 -0
  231. package/dist/slider.d.mts +6 -0
  232. package/dist/slider.d.ts +6 -0
  233. package/dist/slider.js +2 -0
  234. package/dist/slider.js.map +1 -0
  235. package/dist/slider.mjs +2 -0
  236. package/dist/slider.mjs.map +1 -0
  237. package/dist/sonner.d.mts +8 -0
  238. package/dist/sonner.d.ts +8 -0
  239. package/dist/sonner.js +2 -0
  240. package/dist/sonner.js.map +1 -0
  241. package/dist/sonner.mjs +2 -0
  242. package/dist/sonner.mjs.map +1 -0
  243. package/dist/styles.css +1 -1
  244. package/dist/styles.css.map +1 -1
  245. package/dist/switch.d.mts +6 -0
  246. package/dist/switch.d.ts +6 -0
  247. package/dist/switch.js +2 -0
  248. package/dist/switch.js.map +1 -0
  249. package/dist/switch.mjs +2 -0
  250. package/dist/switch.mjs.map +1 -0
  251. package/dist/table.d.mts +12 -0
  252. package/dist/table.d.ts +12 -0
  253. package/dist/table.js +2 -0
  254. package/dist/table.js.map +1 -0
  255. package/dist/table.mjs +2 -0
  256. package/dist/table.mjs.map +1 -0
  257. package/dist/tabs.d.mts +9 -0
  258. package/dist/tabs.d.ts +9 -0
  259. package/dist/tabs.js +2 -0
  260. package/dist/tabs.js.map +1 -0
  261. package/dist/tabs.mjs +2 -0
  262. package/dist/tabs.mjs.map +1 -0
  263. package/dist/textarea.d.mts +5 -0
  264. package/dist/textarea.d.ts +5 -0
  265. package/dist/textarea.js +2 -0
  266. package/dist/textarea.js.map +1 -0
  267. package/dist/textarea.mjs +2 -0
  268. package/dist/textarea.mjs.map +1 -0
  269. package/dist/toggle-group.d.mts +10 -0
  270. package/dist/toggle-group.d.ts +10 -0
  271. package/dist/toggle-group.js +2 -0
  272. package/dist/toggle-group.js.map +1 -0
  273. package/dist/toggle-group.mjs +2 -0
  274. package/dist/toggle-group.mjs.map +1 -0
  275. package/dist/toggle.d.mts +66 -0
  276. package/dist/toggle.d.ts +66 -0
  277. package/dist/toggle.js +2 -0
  278. package/dist/toggle.js.map +1 -0
  279. package/dist/toggle.mjs +2 -0
  280. package/dist/toggle.mjs.map +1 -0
  281. package/dist/tooltip.d.mts +11 -0
  282. package/dist/tooltip.d.ts +11 -0
  283. package/dist/tooltip.js +2 -0
  284. package/dist/tooltip.js.map +1 -0
  285. package/dist/tooltip.mjs +2 -0
  286. package/dist/tooltip.mjs.map +1 -0
  287. package/dist/utils.d.mts +5 -3
  288. package/dist/utils.d.ts +5 -3
  289. package/dist/utils.js +1 -1
  290. package/dist/utils.mjs +1 -1
  291. package/package.json +261 -19
  292. package/src/accordion.tsx +80 -0
  293. package/src/alert-dialog.tsx +190 -0
  294. package/src/alert.tsx +78 -0
  295. package/src/aspect-ratio.tsx +15 -0
  296. package/src/avatar.tsx +65 -0
  297. package/src/badge.tsx +43 -0
  298. package/src/breadcrumb.tsx +148 -0
  299. package/src/button.tsx +63 -21
  300. package/src/calendar.tsx +95 -0
  301. package/src/card.tsx +112 -25
  302. package/src/carousel.tsx +281 -0
  303. package/src/checkbox.tsx +36 -0
  304. package/src/collapsible.tsx +27 -0
  305. package/src/command.tsx +214 -0
  306. package/src/context-menu.tsx +290 -0
  307. package/src/dialog.tsx +176 -0
  308. package/src/drawer.tsx +164 -0
  309. package/src/dropdown-menu.tsx +290 -0
  310. package/src/form.tsx +225 -0
  311. package/src/hover-card.tsx +54 -0
  312. package/src/input-otp.tsx +100 -0
  313. package/src/input.tsx +30 -0
  314. package/src/label.tsx +29 -0
  315. package/src/menubar.tsx +326 -0
  316. package/src/navigation-menu.tsx +189 -0
  317. package/src/pagination.tsx +162 -0
  318. package/src/popover.tsx +62 -0
  319. package/src/progress.tsx +35 -0
  320. package/src/radio-group.tsx +54 -0
  321. package/src/resizable.tsx +67 -0
  322. package/src/scroll-area.tsx +60 -0
  323. package/src/select.tsx +216 -0
  324. package/src/separator.tsx +38 -0
  325. package/src/sheet.tsx +209 -0
  326. package/src/skeleton.tsx +24 -0
  327. package/src/slider.tsx +35 -0
  328. package/src/sonner.tsx +41 -0
  329. package/src/switch.tsx +38 -0
  330. package/src/table.tsx +155 -0
  331. package/src/tabs.tsx +75 -0
  332. package/src/textarea.tsx +29 -0
  333. package/src/toggle-group.tsx +70 -0
  334. package/src/toggle.tsx +56 -0
  335. package/src/tooltip.tsx +84 -0
  336. package/src/utils.ts +10 -5
  337. package/tailwind.config.ts +101 -1
  338. package/dist/chunk-LZ5T3FQ5.js +0 -2
  339. package/dist/chunk-LZ5T3FQ5.js.map +0 -1
  340. package/dist/chunk-ULRAQPD3.mjs +0 -2
  341. package/dist/chunk-ULRAQPD3.mjs.map +0 -1
  342. package/dist/code.d.mts +0 -3
  343. package/dist/code.d.ts +0 -3
  344. package/dist/code.js +0 -2
  345. package/dist/code.js.map +0 -1
  346. package/dist/code.mjs +0 -2
  347. package/dist/code.mjs.map +0 -1
  348. package/src/code.tsx +0 -5
package/src/drawer.tsx ADDED
@@ -0,0 +1,164 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Drawer as DrawerPrimitive } from "vaul";
5
+ import { cn } from "./utils";
6
+
7
+ /* -----------------------------------------------------------------------------
8
+ * Component: Drawer
9
+ * -------------------------------------------------------------------------- */
10
+
11
+ function Drawer({
12
+ shouldScaleBackground = true,
13
+ ...props
14
+ }: React.ComponentProps<typeof DrawerPrimitive.Root>): React.JSX.Element {
15
+ return (
16
+ <DrawerPrimitive.Root
17
+ shouldScaleBackground={shouldScaleBackground}
18
+ {...props}
19
+ />
20
+ );
21
+ }
22
+
23
+ /* -----------------------------------------------------------------------------
24
+ * Component: DrawerTrigger
25
+ * -------------------------------------------------------------------------- */
26
+
27
+ const DrawerTrigger = DrawerPrimitive.Trigger;
28
+
29
+ /* -----------------------------------------------------------------------------
30
+ * Component: DrawerPortal
31
+ * -------------------------------------------------------------------------- */
32
+
33
+ const DrawerPortal = DrawerPrimitive.Portal;
34
+
35
+ /* -----------------------------------------------------------------------------
36
+ * Component: DrawerClose
37
+ * -------------------------------------------------------------------------- */
38
+
39
+ const DrawerClose = DrawerPrimitive.Close;
40
+
41
+ /* -----------------------------------------------------------------------------
42
+ * Component: DrawerOverlay
43
+ * -------------------------------------------------------------------------- */
44
+
45
+ const DrawerOverlay = React.forwardRef<
46
+ React.ElementRef<typeof DrawerPrimitive.Overlay>,
47
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
48
+ >(({ className, ...props }, ref) => (
49
+ <DrawerPrimitive.Overlay
50
+ ref={ref}
51
+ className={cn("fixed inset-0 z-50 bg-black/80", className)}
52
+ {...props}
53
+ />
54
+ ));
55
+ DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
56
+
57
+ /* -----------------------------------------------------------------------------
58
+ * Component: DrawerContent
59
+ * -------------------------------------------------------------------------- */
60
+
61
+ const DrawerContent = React.forwardRef<
62
+ React.ElementRef<typeof DrawerPrimitive.Content>,
63
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
64
+ >(({ className, children, ...props }, ref) => (
65
+ <DrawerPortal>
66
+ <DrawerOverlay />
67
+ <DrawerPrimitive.Content
68
+ ref={ref}
69
+ className={cn(
70
+ "bg-background fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border",
71
+ className,
72
+ )}
73
+ {...props}
74
+ >
75
+ <div className="bg-muted mx-auto mt-4 h-2 w-[100px] rounded-full" />
76
+ {children}
77
+ </DrawerPrimitive.Content>
78
+ </DrawerPortal>
79
+ ));
80
+ DrawerContent.displayName = "DrawerContent";
81
+
82
+ /* -----------------------------------------------------------------------------
83
+ * Component: DrawerHeader
84
+ * -------------------------------------------------------------------------- */
85
+
86
+ function DrawerHeader({
87
+ className,
88
+ ...props
89
+ }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element {
90
+ return (
91
+ <div
92
+ className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
93
+ {...props}
94
+ />
95
+ );
96
+ }
97
+
98
+ /* -----------------------------------------------------------------------------
99
+ * Component: DrawerFooter
100
+ * -------------------------------------------------------------------------- */
101
+
102
+ function DrawerFooter({
103
+ className,
104
+ ...props
105
+ }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element {
106
+ return (
107
+ <div
108
+ className={cn("mt-auto flex flex-col gap-2 p-4", className)}
109
+ {...props}
110
+ />
111
+ );
112
+ }
113
+
114
+ /* -----------------------------------------------------------------------------
115
+ * Component: DrawerTitle
116
+ * -------------------------------------------------------------------------- */
117
+
118
+ const DrawerTitle = React.forwardRef<
119
+ React.ElementRef<typeof DrawerPrimitive.Title>,
120
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
121
+ >(({ className, ...props }, ref) => (
122
+ <DrawerPrimitive.Title
123
+ ref={ref}
124
+ className={cn(
125
+ "text-lg font-semibold leading-none tracking-tight",
126
+ className,
127
+ )}
128
+ {...props}
129
+ />
130
+ ));
131
+ DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
132
+
133
+ /* -----------------------------------------------------------------------------
134
+ * Component: DrawerDescription
135
+ * -------------------------------------------------------------------------- */
136
+
137
+ const DrawerDescription = React.forwardRef<
138
+ React.ElementRef<typeof DrawerPrimitive.Description>,
139
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
140
+ >(({ className, ...props }, ref) => (
141
+ <DrawerPrimitive.Description
142
+ ref={ref}
143
+ className={cn("text-muted-foreground text-sm", className)}
144
+ {...props}
145
+ />
146
+ ));
147
+ DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
148
+
149
+ /* -----------------------------------------------------------------------------
150
+ * Exports
151
+ * -------------------------------------------------------------------------- */
152
+
153
+ export {
154
+ Drawer,
155
+ DrawerPortal,
156
+ DrawerOverlay,
157
+ DrawerTrigger,
158
+ DrawerClose,
159
+ DrawerContent,
160
+ DrawerHeader,
161
+ DrawerFooter,
162
+ DrawerTitle,
163
+ DrawerDescription,
164
+ };
@@ -0,0 +1,290 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
+ import {
6
+ CheckIcon,
7
+ ChevronRightIcon,
8
+ DotFilledIcon,
9
+ } from "@radix-ui/react-icons";
10
+ import { cn } from "./utils";
11
+
12
+ /* -----------------------------------------------------------------------------
13
+ * Component: DropdownMenu
14
+ * -------------------------------------------------------------------------- */
15
+
16
+ const DropdownMenu = DropdownMenuPrimitive.Root;
17
+
18
+ /* -----------------------------------------------------------------------------
19
+ * Component: DropdownMenuTrigger
20
+ * -------------------------------------------------------------------------- */
21
+
22
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
23
+
24
+ /* -----------------------------------------------------------------------------
25
+ * Component: DropdownMenuGroup
26
+ * -------------------------------------------------------------------------- */
27
+
28
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group;
29
+
30
+ /* -----------------------------------------------------------------------------
31
+ * Component: DropdownMenuPortal
32
+ * -------------------------------------------------------------------------- */
33
+
34
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
35
+
36
+ /* -----------------------------------------------------------------------------
37
+ * Component: DropdownMenuSub
38
+ * -------------------------------------------------------------------------- */
39
+
40
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
41
+
42
+ /* -----------------------------------------------------------------------------
43
+ * Component: DropdownMenuSubTrigger
44
+ * -------------------------------------------------------------------------- */
45
+
46
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
47
+
48
+ /* -----------------------------------------------------------------------------
49
+ * Component: DropdownMenuSubTrigger
50
+ * -------------------------------------------------------------------------- */
51
+
52
+ const DropdownMenuSubTrigger = React.forwardRef<
53
+ React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
54
+ DropdownMenuPrimitive.DropdownMenuSubTriggerProps & {
55
+ inset?: boolean;
56
+ }
57
+ >(({ className, inset, children, ...props }, ref) => (
58
+ <DropdownMenuPrimitive.SubTrigger
59
+ ref={ref}
60
+ className={cn(
61
+ "focus:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
62
+ "data-[state=open]:bg-accent",
63
+ inset && "pl-8",
64
+ className,
65
+ )}
66
+ {...props}
67
+ >
68
+ {children}
69
+ <ChevronRightIcon className="ml-auto size-4" />
70
+ </DropdownMenuPrimitive.SubTrigger>
71
+ ));
72
+ DropdownMenuSubTrigger.displayName =
73
+ DropdownMenuPrimitive.SubTrigger.displayName;
74
+
75
+ /* -----------------------------------------------------------------------------
76
+ * Component: DropdownMenuSubContent
77
+ * -------------------------------------------------------------------------- */
78
+
79
+ const DropdownMenuSubContent = React.forwardRef<
80
+ React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
81
+ DropdownMenuPrimitive.DropdownMenuSubContentProps
82
+ >(({ className, ...props }, ref) => (
83
+ <DropdownMenuPrimitive.SubContent
84
+ ref={ref}
85
+ className={cn(
86
+ "bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg",
87
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
88
+ "data-[state=open]:data-[side=top]:slide-in-from-bottom-2",
89
+ "data-[state=open]:data-[side=right]:slide-in-from-left-2",
90
+ "data-[state=open]:data-[side=bottom]:slide-in-from-top-2",
91
+ "data-[state=open]:data-[side=left]:slide-in-from-right-2",
92
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
93
+ "data-[state=closed]:data-[side=top]:slide-out-to-bottom-2",
94
+ "data-[state=closed]:data-[side=right]:slide-out-to-left-2",
95
+ "data-[state=closed]:data-[side=bottom]:slide-out-to-top-2",
96
+ "data-[state=closed]:data-[side=left]:slide-out-to-right-2",
97
+ className,
98
+ )}
99
+ {...props}
100
+ />
101
+ ));
102
+ DropdownMenuSubContent.displayName =
103
+ DropdownMenuPrimitive.SubContent.displayName;
104
+
105
+ /* -----------------------------------------------------------------------------
106
+ * Component: DropdownMenuContent
107
+ * -------------------------------------------------------------------------- */
108
+
109
+ const DropdownMenuContent = React.forwardRef<
110
+ React.ElementRef<typeof DropdownMenuPrimitive.Content>,
111
+ DropdownMenuPrimitive.DropdownMenuContentProps
112
+ >(({ className, sideOffset = 4, ...props }, ref) => (
113
+ <DropdownMenuPrimitive.Portal>
114
+ <DropdownMenuPrimitive.Content
115
+ ref={ref}
116
+ sideOffset={sideOffset}
117
+ className={cn(
118
+ "bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md",
119
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
120
+ "data-[state=open]:data-[side=top]:slide-in-from-bottom-2",
121
+ "data-[state=open]:data-[side=right]:slide-in-from-left-2",
122
+ "data-[state=open]:data-[side=bottom]:slide-in-from-top-2",
123
+ "data-[state=open]:data-[side=left]:slide-in-from-right-2",
124
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
125
+ "data-[state=closed]:data-[side=top]:slide-out-to-bottom-2",
126
+ "data-[state=closed]:data-[side=right]:slide-out-to-left-2",
127
+ "data-[state=closed]:data-[side=bottom]:slide-out-to-top-2",
128
+ "data-[state=closed]:data-[side=left]:slide-out-to-right-2",
129
+ className,
130
+ )}
131
+ {...props}
132
+ />
133
+ </DropdownMenuPrimitive.Portal>
134
+ ));
135
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
136
+
137
+ /* -----------------------------------------------------------------------------
138
+ * Component: DropdownMenuItem
139
+ * -------------------------------------------------------------------------- */
140
+
141
+ const DropdownMenuItem = React.forwardRef<
142
+ React.ElementRef<typeof DropdownMenuPrimitive.Item>,
143
+ DropdownMenuPrimitive.DropdownMenuItemProps & {
144
+ inset?: boolean;
145
+ }
146
+ >(({ className, inset, ...props }, ref) => (
147
+ <DropdownMenuPrimitive.Item
148
+ ref={ref}
149
+ className={cn(
150
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors",
151
+ "aria-disabled:pointer-events-none aria-disabled:opacity-50",
152
+ inset && "pl-8",
153
+ className,
154
+ )}
155
+ {...props}
156
+ />
157
+ ));
158
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
159
+
160
+ /* -----------------------------------------------------------------------------
161
+ * Component: DropdownMenuCheckboxItem
162
+ * -------------------------------------------------------------------------- */
163
+
164
+ const DropdownMenuCheckboxItem = React.forwardRef<
165
+ React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
166
+ DropdownMenuPrimitive.DropdownMenuCheckboxItemProps
167
+ >(({ className, children, checked, ...props }, ref) => (
168
+ <DropdownMenuPrimitive.CheckboxItem
169
+ ref={ref}
170
+ className={cn(
171
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors",
172
+ "aria-disabled:pointer-events-none aria-disabled:opacity-50",
173
+ className,
174
+ )}
175
+ checked={checked}
176
+ {...props}
177
+ >
178
+ <span className="absolute left-2 flex size-3.5 items-center justify-center">
179
+ <DropdownMenuPrimitive.ItemIndicator>
180
+ <CheckIcon className="size-4" />
181
+ </DropdownMenuPrimitive.ItemIndicator>
182
+ </span>
183
+ {children}
184
+ </DropdownMenuPrimitive.CheckboxItem>
185
+ ));
186
+ DropdownMenuCheckboxItem.displayName =
187
+ DropdownMenuPrimitive.CheckboxItem.displayName;
188
+
189
+ /* -----------------------------------------------------------------------------
190
+ * Component: DropdownMenuRadioItem
191
+ * -------------------------------------------------------------------------- */
192
+
193
+ const DropdownMenuRadioItem = React.forwardRef<
194
+ React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
195
+ DropdownMenuPrimitive.DropdownMenuRadioItemProps
196
+ >(({ className, children, ...props }, ref) => (
197
+ <DropdownMenuPrimitive.RadioItem
198
+ ref={ref}
199
+ className={cn(
200
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors",
201
+ "aria-disabled:pointer-events-none aria-disabled:opacity-50",
202
+ className,
203
+ )}
204
+ {...props}
205
+ >
206
+ <span className="absolute left-2 flex size-3.5 items-center justify-center">
207
+ <DropdownMenuPrimitive.ItemIndicator>
208
+ <DotFilledIcon className="size-4 fill-current" />
209
+ </DropdownMenuPrimitive.ItemIndicator>
210
+ </span>
211
+ {children}
212
+ </DropdownMenuPrimitive.RadioItem>
213
+ ));
214
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
215
+
216
+ /* -----------------------------------------------------------------------------
217
+ * Component: DropdownMenuLabel
218
+ * -------------------------------------------------------------------------- */
219
+
220
+ const DropdownMenuLabel = React.forwardRef<
221
+ React.ElementRef<typeof DropdownMenuPrimitive.Label>,
222
+ DropdownMenuPrimitive.DropdownMenuLabelProps & {
223
+ inset?: boolean;
224
+ }
225
+ >(({ className, inset, ...props }, ref) => (
226
+ <DropdownMenuPrimitive.Label
227
+ ref={ref}
228
+ className={cn(
229
+ "px-2 py-1.5 text-sm font-semibold",
230
+ inset && "pl-8",
231
+ className,
232
+ )}
233
+ {...props}
234
+ />
235
+ ));
236
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
237
+
238
+ /* -----------------------------------------------------------------------------
239
+ * Component: DropdownMenuSeparator
240
+ * -------------------------------------------------------------------------- */
241
+
242
+ const DropdownMenuSeparator = React.forwardRef<
243
+ React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
244
+ DropdownMenuPrimitive.DropdownMenuSeparatorProps
245
+ >(({ className, ...props }, ref) => (
246
+ <DropdownMenuPrimitive.Separator
247
+ ref={ref}
248
+ className={cn("bg-muted -mx-1 my-1 h-px", className)}
249
+ {...props}
250
+ />
251
+ ));
252
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
253
+
254
+ /* -----------------------------------------------------------------------------
255
+ * Component: DropdownMenuShortcut
256
+ * -------------------------------------------------------------------------- */
257
+
258
+ function DropdownMenuShortcut({
259
+ className,
260
+ ...props
261
+ }: React.HTMLAttributes<HTMLSpanElement>): React.JSX.Element {
262
+ return (
263
+ <span
264
+ className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
265
+ {...props}
266
+ />
267
+ );
268
+ }
269
+
270
+ /* -----------------------------------------------------------------------------
271
+ * Exports
272
+ * -------------------------------------------------------------------------- */
273
+
274
+ export {
275
+ DropdownMenu,
276
+ DropdownMenuTrigger,
277
+ DropdownMenuContent,
278
+ DropdownMenuItem,
279
+ DropdownMenuCheckboxItem,
280
+ DropdownMenuRadioItem,
281
+ DropdownMenuLabel,
282
+ DropdownMenuSeparator,
283
+ DropdownMenuShortcut,
284
+ DropdownMenuGroup,
285
+ DropdownMenuPortal,
286
+ DropdownMenuSub,
287
+ DropdownMenuSubContent,
288
+ DropdownMenuSubTrigger,
289
+ DropdownMenuRadioGroup,
290
+ };
package/src/form.tsx ADDED
@@ -0,0 +1,225 @@
1
+ import * as React from "react";
2
+ import type * as LabelPrimitive from "@radix-ui/react-label";
3
+ import { Slot } from "@radix-ui/react-slot";
4
+ import {
5
+ Controller,
6
+ type ControllerProps,
7
+ type FieldError,
8
+ type FieldPath,
9
+ type FieldValues,
10
+ FormProvider,
11
+ useFormContext,
12
+ type UseFormGetFieldState,
13
+ } from "react-hook-form";
14
+ import { cn } from "./utils";
15
+ import { Label } from "./label";
16
+
17
+ /* -----------------------------------------------------------------------------
18
+ * Context: FormItemContext
19
+ * -------------------------------------------------------------------------- */
20
+
21
+ interface FormItemContextValue {
22
+ id: string;
23
+ }
24
+
25
+ const FormItemContext = React.createContext<FormItemContextValue>(
26
+ {} as FormItemContextValue,
27
+ );
28
+
29
+ /* -----------------------------------------------------------------------------
30
+ * Context: FormFieldContext
31
+ * -------------------------------------------------------------------------- */
32
+
33
+ interface FormFieldContextValue<
34
+ TFieldValues extends FieldValues = FieldValues,
35
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
36
+ > {
37
+ name: TName;
38
+ }
39
+
40
+ const FormFieldContext = React.createContext<FormFieldContextValue>(
41
+ {} as FormFieldContextValue,
42
+ );
43
+
44
+ const useFormField = (): {
45
+ invalid: boolean;
46
+ isDirty: boolean;
47
+ isTouched: boolean;
48
+ isValidating: boolean;
49
+ error?: FieldError | undefined;
50
+ id: string;
51
+ name: string;
52
+ formItemId: string;
53
+ formDescriptionId: string;
54
+ formMessageId: string;
55
+ } => {
56
+ const fieldContext = React.useContext(FormFieldContext);
57
+ const itemContext = React.useContext(FormItemContext);
58
+ const { getFieldState, formState } = useFormContext();
59
+
60
+ const fieldState = getFieldState(fieldContext.name, formState);
61
+
62
+ if (!fieldContext) {
63
+ throw new Error("useFormField should be used within <FormField>");
64
+ }
65
+
66
+ const { id } = itemContext;
67
+
68
+ return {
69
+ id,
70
+ name: fieldContext.name,
71
+ formItemId: `form-item-${id}`,
72
+ formDescriptionId: `form-item-description-${id}`,
73
+ formMessageId: `form-item-message-${id}`,
74
+ ...fieldState,
75
+ };
76
+ };
77
+
78
+ /* -----------------------------------------------------------------------------
79
+ * Component: Form
80
+ * -------------------------------------------------------------------------- */
81
+
82
+ const Form = FormProvider;
83
+
84
+ /* -----------------------------------------------------------------------------
85
+ * Component: FormField
86
+ * -------------------------------------------------------------------------- */
87
+
88
+ function FormField<
89
+ TFieldValues extends FieldValues = FieldValues,
90
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
91
+ >({ ...props }: ControllerProps<TFieldValues, TName>): React.JSX.Element {
92
+ return (
93
+ <FormFieldContext.Provider value={{ name: props.name }}>
94
+ <Controller {...props} />
95
+ </FormFieldContext.Provider>
96
+ );
97
+ }
98
+
99
+ /* -----------------------------------------------------------------------------
100
+ * Component: FormItem
101
+ * -------------------------------------------------------------------------- */
102
+
103
+ const FormItem = React.forwardRef<
104
+ HTMLDivElement,
105
+ React.HTMLAttributes<HTMLDivElement>
106
+ >(({ className, ...props }, ref) => {
107
+ const id = React.useId();
108
+
109
+ return (
110
+ <FormItemContext.Provider value={{ id }}>
111
+ <div ref={ref} className={cn("space-y-2", className)} {...props} />
112
+ </FormItemContext.Provider>
113
+ );
114
+ });
115
+ FormItem.displayName = "FormItem";
116
+
117
+ /* -----------------------------------------------------------------------------
118
+ * Component: FormLabel
119
+ * -------------------------------------------------------------------------- */
120
+
121
+ const FormLabel = React.forwardRef<
122
+ React.ElementRef<typeof LabelPrimitive.Root>,
123
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
124
+ >(({ className, ...props }, ref) => {
125
+ const { error, formItemId } = useFormField();
126
+
127
+ return (
128
+ <Label
129
+ ref={ref}
130
+ className={cn(error && "text-destructive", className)}
131
+ htmlFor={formItemId}
132
+ {...props}
133
+ />
134
+ );
135
+ });
136
+ FormLabel.displayName = "FormLabel";
137
+
138
+ /* -----------------------------------------------------------------------------
139
+ * Component: FormControl
140
+ * -------------------------------------------------------------------------- */
141
+
142
+ const FormControl = React.forwardRef<
143
+ React.ElementRef<typeof Slot>,
144
+ React.ComponentPropsWithoutRef<typeof Slot>
145
+ >(({ ...props }, ref) => {
146
+ const { error, formItemId, formDescriptionId, formMessageId } =
147
+ useFormField();
148
+
149
+ return (
150
+ <Slot
151
+ ref={ref}
152
+ id={formItemId}
153
+ aria-describedby={
154
+ !error ? formDescriptionId : `${formDescriptionId} ${formMessageId}`
155
+ }
156
+ aria-invalid={Boolean(error)}
157
+ {...props}
158
+ />
159
+ );
160
+ });
161
+ FormControl.displayName = "FormControl";
162
+
163
+ /* -----------------------------------------------------------------------------
164
+ * Component: FormDescription
165
+ * -------------------------------------------------------------------------- */
166
+
167
+ const FormDescription = React.forwardRef<
168
+ HTMLParagraphElement,
169
+ React.HTMLAttributes<HTMLParagraphElement>
170
+ >(({ className, ...props }, ref) => {
171
+ const { formDescriptionId } = useFormField();
172
+
173
+ return (
174
+ <p
175
+ ref={ref}
176
+ id={formDescriptionId}
177
+ className={cn("text-muted-foreground text-[0.8rem]", className)}
178
+ {...props}
179
+ />
180
+ );
181
+ });
182
+ FormDescription.displayName = "FormDescription";
183
+
184
+ /* -----------------------------------------------------------------------------
185
+ * Component: FormMessage
186
+ * -------------------------------------------------------------------------- */
187
+
188
+ const FormMessage = React.forwardRef<
189
+ HTMLParagraphElement,
190
+ React.HTMLAttributes<HTMLParagraphElement>
191
+ >(({ className, children, ...props }, ref) => {
192
+ const { error, formMessageId } = useFormField();
193
+ const body = error ? String(error.message) : children;
194
+
195
+ if (!body) {
196
+ return null;
197
+ }
198
+
199
+ return (
200
+ <p
201
+ ref={ref}
202
+ id={formMessageId}
203
+ className={cn("text-destructive text-[0.8rem] font-medium", className)}
204
+ {...props}
205
+ >
206
+ {body}
207
+ </p>
208
+ );
209
+ });
210
+ FormMessage.displayName = "FormMessage";
211
+
212
+ /* -----------------------------------------------------------------------------
213
+ * Exports
214
+ * -------------------------------------------------------------------------- */
215
+
216
+ export {
217
+ useFormField,
218
+ Form,
219
+ FormItem,
220
+ FormLabel,
221
+ FormControl,
222
+ FormDescription,
223
+ FormMessage,
224
+ FormField,
225
+ };