@codefast/ui 0.3.16-canary.3 → 0.4.0-canary.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 (281) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +27 -16
  3. package/dist/components/accordion.d.mts +7 -22
  4. package/dist/components/accordion.mjs +26 -29
  5. package/dist/components/alert-dialog.d.mts +27 -26
  6. package/dist/components/alert-dialog.mjs +53 -45
  7. package/dist/components/alert.d.mts +12 -2
  8. package/dist/components/alert.mjs +15 -6
  9. package/dist/components/aspect-ratio.d.mts +2 -2
  10. package/dist/components/aspect-ratio.mjs +2 -3
  11. package/dist/components/avatar.d.mts +41 -5
  12. package/dist/components/avatar.mjs +40 -10
  13. package/dist/components/badge.mjs +4 -4
  14. package/dist/components/breadcrumb.d.mts +1 -0
  15. package/dist/components/breadcrumb.mjs +11 -10
  16. package/dist/components/button-group.d.mts +1 -1
  17. package/dist/components/button-group.mjs +6 -7
  18. package/dist/components/button.d.mts +0 -1
  19. package/dist/components/button.mjs +7 -7
  20. package/dist/components/calendar.d.mts +6 -2
  21. package/dist/components/calendar.mjs +39 -43
  22. package/dist/components/card.d.mts +4 -2
  23. package/dist/components/card.mjs +9 -9
  24. package/dist/components/carousel.d.mts +16 -4
  25. package/dist/components/carousel.mjs +24 -11
  26. package/dist/components/chart.d.mts +8 -3
  27. package/dist/components/chart.mjs +21 -15
  28. package/dist/components/checkbox-cards.mjs +4 -4
  29. package/dist/components/checkbox-group.mjs +3 -4
  30. package/dist/components/checkbox.d.mts +2 -2
  31. package/dist/components/checkbox.mjs +6 -7
  32. package/dist/components/collapsible.d.mts +4 -4
  33. package/dist/components/collapsible.mjs +4 -5
  34. package/dist/components/command.d.mts +11 -1
  35. package/dist/components/command.mjs +35 -32
  36. package/dist/components/context-menu.d.mts +22 -15
  37. package/dist/components/context-menu.mjs +44 -39
  38. package/dist/components/dialog.d.mts +19 -23
  39. package/dist/components/dialog.mjs +48 -47
  40. package/dist/components/direction.d.mts +24 -0
  41. package/dist/components/direction.mjs +18 -0
  42. package/dist/components/drawer.d.mts +2 -20
  43. package/dist/components/drawer.mjs +17 -25
  44. package/dist/components/dropdown-menu.d.mts +22 -15
  45. package/dist/components/dropdown-menu.mjs +41 -37
  46. package/dist/components/empty.mjs +5 -5
  47. package/dist/components/field.d.mts +1 -1
  48. package/dist/components/field.mjs +11 -12
  49. package/dist/components/form.d.mts +6 -7
  50. package/dist/components/form.mjs +6 -7
  51. package/dist/components/hover-card.d.mts +5 -5
  52. package/dist/components/hover-card.mjs +14 -12
  53. package/dist/components/input-group.d.mts +1 -1
  54. package/dist/components/input-group.mjs +12 -7
  55. package/dist/components/input-number.d.mts +3 -1
  56. package/dist/components/input-number.mjs +49 -27
  57. package/dist/components/input-otp.mjs +9 -7
  58. package/dist/components/input-password.mjs +1 -4
  59. package/dist/components/input-search.mjs +3 -5
  60. package/dist/components/input.mjs +1 -2
  61. package/dist/components/item.mjs +9 -9
  62. package/dist/components/kbd.mjs +1 -1
  63. package/dist/components/label.d.mts +2 -2
  64. package/dist/components/label.mjs +3 -4
  65. package/dist/components/menubar.d.mts +22 -16
  66. package/dist/components/menubar.mjs +54 -47
  67. package/dist/components/native-select.d.mts +5 -1
  68. package/dist/components/native-select.mjs +9 -6
  69. package/dist/components/navigation-menu.d.mts +30 -8
  70. package/dist/components/navigation-menu.mjs +33 -23
  71. package/dist/components/pagination.d.mts +6 -0
  72. package/dist/components/pagination.mjs +26 -11
  73. package/dist/components/popover.d.mts +40 -7
  74. package/dist/components/popover.mjs +46 -14
  75. package/dist/components/progress-circle.d.mts +1 -1
  76. package/dist/components/progress-circle.mjs +1 -2
  77. package/dist/components/progress.d.mts +2 -2
  78. package/dist/components/progress.mjs +5 -6
  79. package/dist/components/radio-cards.d.mts +3 -3
  80. package/dist/components/radio-cards.mjs +11 -11
  81. package/dist/components/radio-group.d.mts +3 -3
  82. package/dist/components/radio-group.mjs +9 -9
  83. package/dist/components/radio.mjs +2 -3
  84. package/dist/components/resizable.mjs +3 -8
  85. package/dist/components/scroll-area.d.mts +5 -5
  86. package/dist/components/scroll-area.mjs +13 -10
  87. package/dist/components/select.d.mts +14 -14
  88. package/dist/components/select.mjs +47 -47
  89. package/dist/components/separator.d.mts +2 -2
  90. package/dist/components/separator.mjs +3 -4
  91. package/dist/components/sheet.d.mts +13 -14
  92. package/dist/components/sheet.mjs +41 -39
  93. package/dist/components/sidebar.d.mts +2 -3
  94. package/dist/components/sidebar.mjs +46 -46
  95. package/dist/components/skeleton.mjs +1 -1
  96. package/dist/components/slider.d.mts +2 -2
  97. package/dist/components/slider.mjs +9 -11
  98. package/dist/components/sonner.mjs +11 -3
  99. package/dist/components/spinner.mjs +6 -7
  100. package/dist/components/switch.d.mts +5 -2
  101. package/dist/components/switch.mjs +7 -7
  102. package/dist/components/table.mjs +10 -10
  103. package/dist/components/tabs.d.mts +8 -5
  104. package/dist/components/tabs.mjs +18 -12
  105. package/dist/components/textarea.mjs +1 -1
  106. package/dist/components/toggle-group.d.mts +9 -6
  107. package/dist/components/toggle-group.mjs +19 -20
  108. package/dist/components/toggle.d.mts +2 -3
  109. package/dist/components/toggle.mjs +4 -6
  110. package/dist/components/tooltip.d.mts +7 -6
  111. package/dist/components/tooltip.mjs +19 -17
  112. package/dist/hooks/use-animated-value.mjs +0 -1
  113. package/dist/hooks/use-copy-to-clipboard.mjs +0 -1
  114. package/dist/hooks/use-is-mobile.mjs +0 -1
  115. package/dist/hooks/use-media-query.mjs +0 -1
  116. package/dist/hooks/use-mutation-observer.mjs +0 -1
  117. package/dist/hooks/use-pagination.mjs +0 -1
  118. package/dist/index.d.mts +15 -13
  119. package/dist/index.mjs +18 -16
  120. package/dist/primitives/checkbox-group.d.mts +9 -10
  121. package/dist/primitives/checkbox-group.mjs +14 -19
  122. package/dist/primitives/input-number.d.mts +3 -3
  123. package/dist/primitives/input-number.mjs +3 -5
  124. package/dist/primitives/input.d.mts +4 -4
  125. package/dist/primitives/input.mjs +2 -3
  126. package/dist/primitives/progress-circle.d.mts +3 -3
  127. package/dist/primitives/progress-circle.mjs +2 -3
  128. package/dist/variants/alert.d.mts +1 -1
  129. package/dist/variants/alert.mjs +3 -13
  130. package/dist/variants/badge.d.mts +6 -4
  131. package/dist/variants/badge.mjs +7 -34
  132. package/dist/variants/button-group.d.mts +2 -2
  133. package/dist/variants/button-group.mjs +3 -14
  134. package/dist/variants/button.d.mts +12 -10
  135. package/dist/variants/button.mjs +15 -57
  136. package/dist/variants/empty.d.mts +1 -1
  137. package/dist/variants/empty.mjs +2 -7
  138. package/dist/variants/field.d.mts +3 -3
  139. package/dist/variants/field.mjs +4 -22
  140. package/dist/variants/input-group.d.mts +9 -9
  141. package/dist/variants/input-group.mjs +11 -70
  142. package/dist/variants/input-number.d.mts +45 -0
  143. package/dist/variants/input-number.mjs +40 -0
  144. package/dist/variants/item.d.mts +5 -4
  145. package/dist/variants/item.mjs +9 -31
  146. package/dist/variants/navigation-menu.d.mts +1 -1
  147. package/dist/variants/navigation-menu.mjs +1 -5
  148. package/dist/variants/progress-circle.d.mts +1 -1
  149. package/dist/variants/progress-circle.mjs +1 -5
  150. package/dist/variants/scroll-area.d.mts +2 -2
  151. package/dist/variants/scroll-area.mjs +3 -8
  152. package/dist/variants/separator.mjs +6 -6
  153. package/dist/variants/sheet.d.mts +4 -4
  154. package/dist/variants/sheet.mjs +5 -38
  155. package/dist/variants/sidebar.d.mts +4 -4
  156. package/dist/variants/sidebar.mjs +6 -23
  157. package/dist/variants/tabs.d.mts +18 -0
  158. package/dist/variants/tabs.mjs +15 -0
  159. package/dist/variants/toggle.d.mts +4 -4
  160. package/dist/variants/toggle.mjs +9 -27
  161. package/package.json +27 -44
  162. package/src/components/accordion.tsx +26 -68
  163. package/src/components/alert-dialog.tsx +70 -86
  164. package/src/components/alert.tsx +27 -19
  165. package/src/components/aspect-ratio.tsx +1 -4
  166. package/src/components/avatar.tsx +99 -12
  167. package/src/components/badge.tsx +5 -8
  168. package/src/components/breadcrumb.tsx +18 -24
  169. package/src/components/button-group.tsx +10 -20
  170. package/src/components/button.tsx +8 -19
  171. package/src/components/calendar.tsx +77 -132
  172. package/src/components/card.tsx +16 -22
  173. package/src/components/carousel.tsx +38 -56
  174. package/src/components/chart.tsx +41 -92
  175. package/src/components/checkbox-cards.tsx +10 -30
  176. package/src/components/checkbox-group.tsx +5 -28
  177. package/src/components/checkbox.tsx +5 -26
  178. package/src/components/collapsible.tsx +1 -4
  179. package/src/components/command.tsx +52 -65
  180. package/src/components/context-menu.tsx +46 -125
  181. package/src/components/dialog.tsx +49 -101
  182. package/src/components/direction.tsx +32 -0
  183. package/src/components/drawer.tsx +17 -79
  184. package/src/components/dropdown-menu.tsx +39 -118
  185. package/src/components/empty.tsx +6 -20
  186. package/src/components/field.tsx +19 -52
  187. package/src/components/form.tsx +19 -61
  188. package/src/components/hover-card.tsx +4 -27
  189. package/src/components/input-group.tsx +13 -52
  190. package/src/components/input-number.tsx +55 -75
  191. package/src/components/input-otp.tsx +19 -38
  192. package/src/components/input-password.tsx +5 -29
  193. package/src/components/input-search.tsx +6 -23
  194. package/src/components/input.tsx +1 -17
  195. package/src/components/item.tsx +17 -31
  196. package/src/components/kbd.tsx +2 -14
  197. package/src/components/label.tsx +2 -10
  198. package/src/components/menubar.tsx +34 -125
  199. package/src/components/native-select.tsx +21 -30
  200. package/src/components/navigation-menu.tsx +34 -94
  201. package/src/components/pagination.tsx +28 -34
  202. package/src/components/popover.tsx +66 -35
  203. package/src/components/progress-circle.tsx +7 -25
  204. package/src/components/progress.tsx +3 -16
  205. package/src/components/radio-cards.tsx +8 -27
  206. package/src/components/radio-group.tsx +7 -27
  207. package/src/components/radio.tsx +3 -24
  208. package/src/components/resizable.tsx +5 -26
  209. package/src/components/scroll-area.tsx +12 -32
  210. package/src/components/select.tsx +36 -59
  211. package/src/components/separator.tsx +4 -18
  212. package/src/components/sheet.tsx +37 -74
  213. package/src/components/sidebar.tsx +47 -177
  214. package/src/components/skeleton.tsx +1 -3
  215. package/src/components/slider.tsx +7 -36
  216. package/src/components/sonner.tsx +16 -6
  217. package/src/components/spinner.tsx +6 -15
  218. package/src/components/switch.tsx +8 -30
  219. package/src/components/table.tsx +18 -35
  220. package/src/components/tabs.tsx +16 -34
  221. package/src/components/textarea.tsx +1 -15
  222. package/src/components/toggle-group.tsx +34 -38
  223. package/src/components/toggle.tsx +4 -13
  224. package/src/components/tooltip.tsx +11 -37
  225. package/src/css/foundation/base.css +50 -0
  226. package/src/css/foundation/motion.css +36 -0
  227. package/src/css/foundation/source.css +3 -0
  228. package/src/css/foundation/tokens.css +71 -0
  229. package/src/css/foundation/variants.css +113 -0
  230. package/src/css/preset.css +5 -214
  231. package/src/css/style.css +1 -1
  232. package/src/hooks/use-animated-value.ts +1 -7
  233. package/src/hooks/use-copy-to-clipboard.ts +1 -6
  234. package/src/hooks/use-is-mobile.ts +0 -2
  235. package/src/hooks/use-media-query.ts +0 -2
  236. package/src/hooks/use-mutation-observer.ts +0 -3
  237. package/src/hooks/use-pagination.ts +0 -2
  238. package/src/index.ts +39 -80
  239. package/src/primitives/checkbox-group.tsx +25 -39
  240. package/src/primitives/input-number.tsx +17 -63
  241. package/src/primitives/input.tsx +8 -24
  242. package/src/primitives/progress-circle.tsx +13 -43
  243. package/src/variants/alert.ts +3 -14
  244. package/src/variants/badge.ts +8 -35
  245. package/src/variants/button-group.ts +5 -18
  246. package/src/variants/button.ts +21 -58
  247. package/src/variants/empty.ts +2 -11
  248. package/src/variants/field.ts +6 -19
  249. package/src/variants/input-group.ts +12 -64
  250. package/src/variants/input-number.ts +65 -0
  251. package/src/variants/item.ts +10 -32
  252. package/src/variants/navigation-menu.ts +1 -8
  253. package/src/variants/progress-circle.ts +1 -2
  254. package/src/variants/scroll-area.ts +3 -9
  255. package/src/variants/separator.ts +6 -7
  256. package/src/variants/sheet.ts +6 -39
  257. package/src/variants/sidebar.ts +7 -27
  258. package/src/variants/tabs.ts +34 -0
  259. package/src/variants/toggle.ts +9 -28
  260. /package/src/css/{amber.css → themes/amber.css} +0 -0
  261. /package/src/css/{blue.css → themes/blue.css} +0 -0
  262. /package/src/css/{cyan.css → themes/cyan.css} +0 -0
  263. /package/src/css/{emerald.css → themes/emerald.css} +0 -0
  264. /package/src/css/{fuchsia.css → themes/fuchsia.css} +0 -0
  265. /package/src/css/{gray.css → themes/gray.css} +0 -0
  266. /package/src/css/{green.css → themes/green.css} +0 -0
  267. /package/src/css/{indigo.css → themes/indigo.css} +0 -0
  268. /package/src/css/{lime.css → themes/lime.css} +0 -0
  269. /package/src/css/{neutral.css → themes/neutral.css} +0 -0
  270. /package/src/css/{orange.css → themes/orange.css} +0 -0
  271. /package/src/css/{pink.css → themes/pink.css} +0 -0
  272. /package/src/css/{purple.css → themes/purple.css} +0 -0
  273. /package/src/css/{red.css → themes/red.css} +0 -0
  274. /package/src/css/{rose.css → themes/rose.css} +0 -0
  275. /package/src/css/{sky.css → themes/sky.css} +0 -0
  276. /package/src/css/{slate.css → themes/slate.css} +0 -0
  277. /package/src/css/{stone.css → themes/stone.css} +0 -0
  278. /package/src/css/{teal.css → themes/teal.css} +0 -0
  279. /package/src/css/{violet.css → themes/violet.css} +0 -0
  280. /package/src/css/{yellow.css → themes/yellow.css} +0 -0
  281. /package/src/css/{zinc.css → themes/zinc.css} +0 -0
@@ -1,17 +1,13 @@
1
- "use client";
2
-
3
- import type { Scope } from "@radix-ui/react-context";
4
- import type * as LabelPrimitive from "@radix-ui/react-label";
1
+ import type { Label as LabelPrimitive } from "radix-ui";
2
+ import { Slot } from "radix-ui";
3
+ import { Context } from "radix-ui/internal";
5
4
  import type { ComponentProps, JSX, ReactNode } from "react";
6
- import type { ControllerProps, FieldError, FieldPath, FieldValues } from "react-hook-form";
7
-
8
- import { cn } from "#/lib/utils";
9
- import { createContextScope } from "@radix-ui/react-context";
10
- import { Slot } from "@radix-ui/react-slot";
11
5
  import { useId } from "react";
6
+ import type { ControllerProps, FieldError, FieldPath, FieldValues } from "react-hook-form";
12
7
  import { Controller, FormProvider, useFormContext, useFormState } from "react-hook-form";
13
8
 
14
9
  import { Label } from "#/components/label";
10
+ import { cn } from "#/lib/utils";
15
11
 
16
12
  /* -----------------------------------------------------------------------------
17
13
  * Component: Form
@@ -33,9 +29,9 @@ const Form: typeof FormProvider = FormProvider;
33
29
 
34
30
  const FORM_FIELD_NAME = "FormField";
35
31
 
36
- type ScopedProps<P> = P & { __scopeFormField?: Scope };
32
+ type ScopedProps<P> = P & { __scopeFormField?: Context.Scope };
37
33
 
38
- const [createFormFieldContext, createFormFieldScope] = createContextScope(FORM_FIELD_NAME);
34
+ const [createFormFieldContext, createFormFieldScope] = Context.createContextScope(FORM_FIELD_NAME);
39
35
 
40
36
  interface FormFieldContextValue<
41
37
  TFieldValues extends FieldValues = FieldValues,
@@ -44,12 +40,11 @@ interface FormFieldContextValue<
44
40
  name: TName;
45
41
  }
46
42
 
47
- const [FormFieldContextProvider, useFormFieldContext] =
48
- createFormFieldContext<FormFieldContextValue>(FORM_FIELD_NAME);
43
+ const [FormFieldContextProvider, useFormFieldContext] = createFormFieldContext<FormFieldContextValue>(FORM_FIELD_NAME);
49
44
 
50
45
  function useFormItem(
51
46
  consumerName: string,
52
- scope: Scope,
47
+ scope: Context.Scope,
53
48
  ): {
54
49
  formDescriptionId: string;
55
50
  formItemId: string;
@@ -116,8 +111,7 @@ interface FormItemContextValue {
116
111
  id: string;
117
112
  }
118
113
 
119
- const [FormItemContextProvider, useFormItemContext] =
120
- createFormFieldContext<FormItemContextValue>(FORM_ITEM_NAME);
114
+ const [FormItemContextProvider, useFormItemContext] = createFormFieldContext<FormItemContextValue>(FORM_ITEM_NAME);
121
115
 
122
116
  /* -----------------------------------------------------------------------------
123
117
  * Component: FormItem
@@ -131,11 +125,7 @@ type FormItemProps = ComponentProps<"div">;
131
125
  /**
132
126
  * @since 0.3.16-canary.0
133
127
  */
134
- function FormItem({
135
- __scopeFormField,
136
- className,
137
- ...props
138
- }: ScopedProps<FormItemProps>): JSX.Element {
128
+ function FormItem({ __scopeFormField, className, ...props }: ScopedProps<FormItemProps>): JSX.Element {
139
129
  const id = useId();
140
130
 
141
131
  return (
@@ -162,14 +152,7 @@ type FormLabelProps = ComponentProps<typeof LabelPrimitive.Root>;
162
152
  function FormLabel({ __scopeFormField, ...props }: ScopedProps<FormLabelProps>): JSX.Element {
163
153
  const { error, formItemId } = useFormItem(FORM_LABEL_NAME, __scopeFormField);
164
154
 
165
- return (
166
- <Label
167
- data-invalid={error ? true : undefined}
168
- data-slot="form-label"
169
- htmlFor={formItemId}
170
- {...props}
171
- />
172
- );
155
+ return <Label data-invalid={error ? true : undefined} data-slot="form-label" htmlFor={formItemId} {...props} />;
173
156
  }
174
157
 
175
158
  /* -----------------------------------------------------------------------------
@@ -181,19 +164,16 @@ const FORM_CONTROL_NAME = "FormControl";
181
164
  /**
182
165
  * @since 0.3.16-canary.0
183
166
  */
184
- type FormControlProps = ComponentProps<typeof Slot>;
167
+ type FormControlProps = ComponentProps<typeof Slot.Root>;
185
168
 
186
169
  /**
187
170
  * @since 0.3.16-canary.0
188
171
  */
189
172
  function FormControl({ __scopeFormField, ...props }: ScopedProps<FormControlProps>): JSX.Element {
190
- const { error, formDescriptionId, formItemId, formMessageId } = useFormItem(
191
- FORM_CONTROL_NAME,
192
- __scopeFormField,
193
- );
173
+ const { error, formDescriptionId, formItemId, formMessageId } = useFormItem(FORM_CONTROL_NAME, __scopeFormField);
194
174
 
195
175
  return (
196
- <Slot
176
+ <Slot.Root
197
177
  aria-describedby={error ? `${formDescriptionId} ${formMessageId}` : formDescriptionId}
198
178
  aria-invalid={Boolean(error)}
199
179
  data-slot="form-control"
@@ -215,11 +195,7 @@ type FormDescriptionProps = ComponentProps<"p">;
215
195
  /**
216
196
  * @since 0.3.16-canary.0
217
197
  */
218
- function FormDescription({
219
- __scopeFormField,
220
- className,
221
- ...props
222
- }: ScopedProps<FormDescriptionProps>): JSX.Element {
198
+ function FormDescription({ __scopeFormField, className, ...props }: ScopedProps<FormDescriptionProps>): JSX.Element {
223
199
  const { formDescriptionId } = useFormItem(FORM_MESSAGE_NAME, __scopeFormField);
224
200
 
225
201
  return (
@@ -246,12 +222,7 @@ type FormMessageProps = ComponentProps<"p">;
246
222
  /**
247
223
  * @since 0.3.16-canary.0
248
224
  */
249
- function FormMessage({
250
- __scopeFormField,
251
- children,
252
- className,
253
- ...props
254
- }: ScopedProps<FormMessageProps>): ReactNode {
225
+ function FormMessage({ __scopeFormField, children, className, ...props }: ScopedProps<FormMessageProps>): ReactNode {
255
226
  const { error, formMessageId } = useFormItem(FORM_MESSAGE_NAME, __scopeFormField);
256
227
  const body = error?.message ?? children;
257
228
 
@@ -261,11 +232,7 @@ function FormMessage({
261
232
 
262
233
  return (
263
234
  <p
264
- className={cn(
265
- "text-xs",
266
- error?.message ? "font-medium text-destructive" : "text-muted-foreground",
267
- className,
268
- )}
235
+ className={cn("text-xs", error?.message ? "font-medium text-destructive" : "text-muted-foreground", className)}
269
236
  data-slot="form-message"
270
237
  id={formMessageId}
271
238
  {...props}
@@ -288,13 +255,4 @@ export type {
288
255
  FormMessageProps,
289
256
  FormProps,
290
257
  };
291
- export {
292
- createFormFieldScope,
293
- Form,
294
- FormControl,
295
- FormDescription,
296
- FormField,
297
- FormItem,
298
- FormLabel,
299
- FormMessage,
300
- };
258
+ export { createFormFieldScope, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage };
@@ -1,9 +1,7 @@
1
- "use client";
2
-
1
+ import { HoverCard as HoverCardPrimitive } from "radix-ui";
3
2
  import type { ComponentProps, JSX } from "react";
4
3
 
5
4
  import { cn } from "#/lib/utils";
6
- import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
7
5
 
8
6
  /* -----------------------------------------------------------------------------
9
7
  * Component: HoverCard
@@ -56,26 +54,11 @@ function HoverCardContent({
56
54
  ...props
57
55
  }: HoverCardContentProps): JSX.Element {
58
56
  return (
59
- <HoverCardPrimitive.Portal>
57
+ <HoverCardPrimitive.Portal data-slot="hover-card-portal">
60
58
  <HoverCardPrimitive.Content
61
59
  align={align}
62
60
  className={cn(
63
- "z-50",
64
- "min-w-32 p-4",
65
- "rounded-lg border",
66
- "bg-popover text-popover-foreground shadow-lg",
67
- "ease-snappy data-open:animate-in data-open:duration-200 data-open:fade-in-0 data-open:zoom-in-95",
68
- "data-open:data-side-top:slide-in-from-bottom-2",
69
- "data-open:data-side-right:slide-in-from-left-2",
70
- "data-open:data-side-bottom:slide-in-from-top-2",
71
- "data-open:data-side-left:slide-in-from-right-2",
72
- "data-closed:animate-out data-closed:duration-150 data-closed:fade-out-0 data-closed:zoom-out-95",
73
- "data-closed:data-side-top:slide-out-to-bottom-2",
74
- "data-closed:data-side-right:slide-out-to-left-2",
75
- "data-closed:data-side-bottom:slide-out-to-top-2",
76
- "data-closed:data-side-left:slide-out-to-right-2",
77
- "motion-reduce:animate-none motion-reduce:transition-none motion-reduce:duration-0",
78
- "origin-(--radix-hover-card-content-transform-origin)",
61
+ "z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-lg bg-popover p-4 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden ease-snappy data-open:animate-in data-open:animation-duration-popup-in data-open:fade-in-0 data-open:zoom-in-95 data-open:data-side-top:slide-in-from-bottom-2 data-open:data-side-right:slide-in-from-left-2 data-open:data-side-bottom:slide-in-from-top-2 data-open:data-side-left:slide-in-from-right-2 data-closed:animate-out data-closed:ease-exit data-closed:animation-duration-popup-out data-closed:fade-out-0 data-closed:zoom-out-95 data-closed:data-side-top:slide-out-to-bottom-2 data-closed:data-side-right:slide-out-to-left-2 data-closed:data-side-bottom:slide-out-to-top-2 data-closed:data-side-left:slide-out-to-right-2",
79
62
  className,
80
63
  )}
81
64
  data-slot="hover-card-content"
@@ -99,13 +82,7 @@ type HoverCardArrowProps = ComponentProps<typeof HoverCardPrimitive.Arrow>;
99
82
  * @since 0.3.16-canary.0
100
83
  */
101
84
  function HoverCardArrow({ className, ...props }: HoverCardArrowProps): JSX.Element {
102
- return (
103
- <HoverCardPrimitive.Arrow
104
- className={cn("fill-popover", className)}
105
- data-slot="hover-card-arrow"
106
- {...props}
107
- />
108
- );
85
+ return <HoverCardPrimitive.Arrow className={cn("fill-popover", className)} data-slot="hover-card-arrow" {...props} />;
109
86
  }
110
87
 
111
88
  /* -----------------------------------------------------------------------------
@@ -1,23 +1,14 @@
1
- "use client";
2
-
3
- import type { InputGroupAddonVariants, InputGroupButtonVariants } from "#/variants/input-group";
4
1
  import type { ComponentProps, JSX } from "react";
5
2
 
6
- import { cn } from "#/lib/utils";
7
-
8
- import {
9
- inputGroupAddonVariants,
10
- inputGroupButtonVariants,
11
- inputGroupVariants,
12
- } from "#/variants/input-group";
13
-
14
3
  import type { ButtonProps } from "#/components/button";
15
- import type { InputProps } from "#/components/input";
16
- import type { TextareaProps } from "#/components/textarea";
17
-
18
4
  import { Button } from "#/components/button";
5
+ import type { InputProps } from "#/components/input";
19
6
  import { Input } from "#/components/input";
7
+ import type { TextareaProps } from "#/components/textarea";
20
8
  import { Textarea } from "#/components/textarea";
9
+ import { cn } from "#/lib/utils";
10
+ import type { InputGroupAddonVariants, InputGroupButtonVariants } from "#/variants/input-group";
11
+ import { inputGroupAddonVariants, inputGroupButtonVariants, inputGroupVariants } from "#/variants/input-group";
21
12
 
22
13
  /* -----------------------------------------------------------------------------
23
14
  * Component: InputGroup
@@ -32,14 +23,7 @@ type InputGroupProps = ComponentProps<"div">;
32
23
  * @since 0.3.16-canary.0
33
24
  */
34
25
  function InputGroup({ className, ...props }: InputGroupProps): JSX.Element {
35
- return (
36
- <div
37
- className={inputGroupVariants({ className })}
38
- data-slot="input-group"
39
- role="group"
40
- {...props}
41
- />
42
- );
26
+ return <div className={inputGroupVariants({ className })} data-slot="input-group" role="group" {...props} />;
43
27
  }
44
28
 
45
29
  /* -----------------------------------------------------------------------------
@@ -54,14 +38,10 @@ type InputGroupAddonProps = ComponentProps<"div"> & InputGroupAddonVariants;
54
38
  /**
55
39
  * @since 0.3.16-canary.0
56
40
  */
57
- function InputGroupAddon({
58
- align = "inline-start",
59
- className,
60
- ...props
61
- }: InputGroupAddonProps): JSX.Element {
41
+ function InputGroupAddon({ align = "inline-start", className, ...props }: InputGroupAddonProps): JSX.Element {
62
42
  return (
63
43
  <div
64
- className={cn(inputGroupAddonVariants({ align }), className)}
44
+ className={inputGroupAddonVariants({ align, className })}
65
45
  data-align={align}
66
46
  data-slot="input-group-addon"
67
47
  role="group"
@@ -104,7 +84,7 @@ function InputGroupButton({
104
84
  }: InputGroupButtonProps): JSX.Element {
105
85
  return (
106
86
  <Button
107
- className={cn(inputGroupButtonVariants({ size }), className)}
87
+ className={inputGroupButtonVariants({ size, className })}
108
88
  data-size={size}
109
89
  data-slot="input-group-button"
110
90
  type={type}
@@ -130,8 +110,7 @@ function InputGroupText({ className, ...props }: InputGroupTextProps): JSX.Eleme
130
110
  return (
131
111
  <span
132
112
  className={cn(
133
- "flex items-center gap-2 text-sm text-muted-foreground",
134
- "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
113
+ "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
135
114
  className,
136
115
  )}
137
116
  data-slot="input-group-text"
@@ -156,12 +135,7 @@ function InputGroupInput({ className, ...props }: InputGroupInputProps): JSX.Ele
156
135
  return (
157
136
  <Input
158
137
  className={cn(
159
- "flex-1",
160
- "px-3 py-1",
161
- "rounded-none border-0",
162
- "bg-transparent shadow-none",
163
- "focus-visible:ring-0",
164
- "dark:bg-transparent",
138
+ "flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
165
139
  className,
166
140
  )}
167
141
  data-slot="input-group-control"
@@ -186,13 +160,7 @@ function InputGroupTextarea({ className, ...props }: InputGroupTextareaProps): J
186
160
  return (
187
161
  <Textarea
188
162
  className={cn(
189
- "flex-1",
190
- "py-3",
191
- "rounded-none border-0",
192
- "bg-transparent shadow-none",
193
- "resize-none",
194
- "focus-visible:ring-0",
195
- "dark:bg-transparent",
163
+ "flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
196
164
  className,
197
165
  )}
198
166
  data-slot="input-group-control"
@@ -205,14 +173,7 @@ function InputGroupTextarea({ className, ...props }: InputGroupTextareaProps): J
205
173
  * Exports
206
174
  * -------------------------------------------------------------------------- */
207
175
 
208
- export {
209
- InputGroup,
210
- InputGroupAddon,
211
- InputGroupButton,
212
- InputGroupInput,
213
- InputGroupText,
214
- InputGroupTextarea,
215
- };
176
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea };
216
177
 
217
178
  export type {
218
179
  InputGroupAddonProps,
@@ -1,13 +1,11 @@
1
- "use client";
2
-
1
+ import { ChevronDownIcon, ChevronUpIcon, MinusIcon, PlusIcon } from "lucide-react";
3
2
  import type { ComponentProps, JSX } from "react";
4
3
 
5
- import { cn } from "#/lib/utils";
6
- import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
7
-
8
- import { buttonVariants } from "#/variants/button";
9
4
  import { Spinner } from "#/components/spinner";
10
5
  import * as InputNumberPrimitive from "#/primitives/input-number";
6
+ import { buttonVariants } from "#/variants/button";
7
+ import type { InputNumberVariants } from "#/variants/input-number";
8
+ import { inputNumberVariants } from "#/variants/input-number";
11
9
 
12
10
  /* -----------------------------------------------------------------------------
13
11
  * Component: InputNumber
@@ -19,7 +17,8 @@ import * as InputNumberPrimitive from "#/primitives/input-number";
19
17
  interface InputNumberProps
20
18
  extends
21
19
  ComponentProps<typeof InputNumberPrimitive.Field>,
22
- ComponentProps<typeof InputNumberPrimitive.Root> {}
20
+ ComponentProps<typeof InputNumberPrimitive.Root>,
21
+ InputNumberVariants {}
23
22
 
24
23
  /**
25
24
  * @since 0.3.16-canary.0
@@ -43,33 +42,19 @@ function InputNumber({
43
42
  step,
44
43
  suffix,
45
44
  value,
45
+ variant = "stepper",
46
46
  ...props
47
47
  }: InputNumberProps): JSX.Element {
48
+ const isSplit = variant === "split";
49
+ const { decrementButton, field, incrementButton, root, stepper, stepperButton } = inputNumberVariants({ variant });
50
+
48
51
  return (
49
52
  <InputNumberPrimitive.Root
50
53
  ariaDecrementLabel={ariaDecrementLabel}
51
54
  ariaIncrementLabel={ariaIncrementLabel}
52
- className={cn(
53
- "group peer flex h-9 w-full grow items-center gap-3 px-3 pr-0",
54
- "rounded-lg border border-input",
55
- "text-base",
56
- "transition",
57
- "motion-reduce:transition-none",
58
- "not-has-disabled:shadow-xs",
59
- "focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50",
60
- "hover:not-has-disabled:not-focus-within:border-ring/60",
61
- "focus-within:has-aria-invalid:ring-destructive/20",
62
- "hover:not-has-disabled:not-focus-within:has-aria-invalid:border-destructive/60",
63
- "md:text-sm",
64
- "dark:bg-input/30",
65
- "dark:focus-within:has-aria-invalid:ring-destructive/40",
66
- "has-disabled:opacity-50",
67
- "has-aria-invalid:border-destructive",
68
- "[&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
69
- "[&>svg]:text-muted-foreground",
70
- className,
71
- )}
55
+ className={root({ className })}
72
56
  data-slot="input-number"
57
+ data-variant={variant}
73
58
  defaultValue={defaultValue}
74
59
  disabled={disabled}
75
60
  formatOptions={formatOptions}
@@ -86,69 +71,64 @@ function InputNumber({
86
71
  value={value}
87
72
  onChange={onChange}
88
73
  >
74
+ {isSplit ? (
75
+ <InputNumberPrimitive.DecrementButton
76
+ aria-label="Decrement"
77
+ className={buttonVariants({
78
+ className: decrementButton(),
79
+ variant: "ghost",
80
+ })}
81
+ data-slot="input-number-decrement-button"
82
+ >
83
+ <MinusIcon />
84
+ </InputNumberPrimitive.DecrementButton>
85
+ ) : null}
86
+
89
87
  <InputNumberPrimitive.Field
90
88
  autoCapitalize="none"
91
89
  autoComplete="off"
92
90
  autoCorrect="off"
93
- className={cn(
94
- "h-9 w-full min-w-0 px-3 py-1",
95
- "rounded-md border border-input",
96
- "bg-transparent shadow-xs outline-none",
97
- "text-base",
98
- "transition-[color,box-shadow]",
99
- "motion-reduce:transition-none",
100
- "selection:bg-primary selection:text-primary-foreground",
101
- "file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground",
102
- "placeholder:text-muted-foreground",
103
- "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
104
- "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
105
- "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
106
- "md:text-sm",
107
- "dark:bg-input/30",
108
- "dark:aria-invalid:ring-destructive/40",
109
- )}
91
+ className={field()}
110
92
  spellCheck="false"
111
93
  {...props}
112
94
  />
113
- <div
114
- className={cn(
115
- "order-last ml-auto grid h-full shrink-0",
116
- "divide-y divide-input border-l border-l-input",
117
- "transition",
118
- "motion-reduce:transition-none",
119
- "group-hover:not-group-focus-within:not-has-disabled:border-l-border-ring/60 group-hover:not-group-focus-within:not-has-disabled:divide-border-ring/60",
120
- "group-focus-within:divide-ring group-focus-within:border-l-ring",
121
- "group-has-aria-invalid:divide-destructive group-has-aria-invalid:border-l-destructive",
122
- "group-hover:group-has-aria-invalid:not-group-focus-within:not-has-disabled:divide-destructive/60 group-hover:group-has-aria-invalid:not-group-focus-within:not-has-disabled:border-l-destructive/60",
123
- "*:[button]:focus-visible:bg-ring/50 *:[button]:focus-visible:ring-0",
124
- "group-has-aria-invalid:*:[button]:focus-visible:bg-destructive/20",
125
- "dark:group-has-aria-invalid:*:[button]:focus-visible:bg-destructive/40",
126
- )}
127
- data-slot="input-number-buttons"
128
- >
95
+
96
+ {isSplit ? (
129
97
  <InputNumberPrimitive.IncrementButton
130
98
  aria-label="Increment"
131
99
  className={buttonVariants({
132
- className:
133
- "text-muted-foreground h-auto rounded-none rounded-tr-[calc(var(--radius-lg)-1px)]",
100
+ className: incrementButton(),
134
101
  variant: "ghost",
135
102
  })}
136
103
  data-slot="input-number-increment-button"
137
104
  >
138
- <ChevronUpIcon />
105
+ <PlusIcon />
139
106
  </InputNumberPrimitive.IncrementButton>
140
- <InputNumberPrimitive.DecrementButton
141
- aria-label="Decrement"
142
- className={buttonVariants({
143
- className:
144
- "text-muted-foreground h-auto rounded-none rounded-br-[calc(var(--radius-lg)-1px)]",
145
- variant: "ghost",
146
- })}
147
- data-slot="input-number-decrement-button"
148
- >
149
- <ChevronDownIcon />
150
- </InputNumberPrimitive.DecrementButton>
151
- </div>
107
+ ) : (
108
+ <div className={stepper()} data-slot="input-number-buttons">
109
+ <InputNumberPrimitive.IncrementButton
110
+ aria-label="Increment"
111
+ className={buttonVariants({
112
+ className: stepperButton(),
113
+ variant: "ghost",
114
+ })}
115
+ data-slot="input-number-increment-button"
116
+ >
117
+ <ChevronUpIcon className="size-3.5" />
118
+ </InputNumberPrimitive.IncrementButton>
119
+
120
+ <InputNumberPrimitive.DecrementButton
121
+ aria-label="Decrement"
122
+ className={buttonVariants({
123
+ className: stepperButton(),
124
+ variant: "ghost",
125
+ })}
126
+ data-slot="input-number-decrement-button"
127
+ >
128
+ <ChevronDownIcon className="size-3.5" />
129
+ </InputNumberPrimitive.DecrementButton>
130
+ </div>
131
+ )}
152
132
  </InputNumberPrimitive.Root>
153
133
  );
154
134
  }
@@ -1,12 +1,10 @@
1
- "use client";
2
-
3
- import type { ComponentProps, JSX } from "react";
4
-
5
- import { cn } from "#/lib/utils";
6
1
  import { OTPInput, OTPInputContext } from "input-otp";
7
2
  import { MinusIcon } from "lucide-react";
3
+ import type { ComponentProps, JSX } from "react";
8
4
  import { use } from "react";
9
5
 
6
+ import { cn } from "#/lib/utils";
7
+
10
8
  /* -----------------------------------------------------------------------------
11
9
  * Component: InputOtp
12
10
  * -------------------------------------------------------------------------- */
@@ -23,13 +21,10 @@ function InputOTP({ className, containerClassName, ...props }: InputOTPProps): J
23
21
  return (
24
22
  <OTPInput
25
23
  aria-label="One-time password"
26
- className={cn(className)}
27
- containerClassName={cn(
28
- "flex items-center gap-2",
29
- "has-disabled:opacity-50",
30
- containerClassName,
31
- )}
24
+ className={cn("disabled:cursor-not-allowed", className)}
25
+ containerClassName={cn("flex items-center gap-2 has-disabled:opacity-50", containerClassName)}
32
26
  data-slot="input-otp"
27
+ spellCheck={false}
33
28
  {...props}
34
29
  />
35
30
  );
@@ -50,7 +45,10 @@ type InputOTPGroupProps = ComponentProps<"div">;
50
45
  function InputOTPGroup({ className, ...props }: InputOTPGroupProps): JSX.Element {
51
46
  return (
52
47
  <div
53
- className={cn("flex items-center -space-x-px", className)}
48
+ className={cn(
49
+ "flex items-center rounded-md has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40",
50
+ className,
51
+ )}
54
52
  data-slot="input-otp-group"
55
53
  role="group"
56
54
  {...props}
@@ -83,19 +81,7 @@ function InputOTPSlot({ className, index, ...props }: InputOTPSlotProps): JSX.El
83
81
  return (
84
82
  <div
85
83
  className={cn(
86
- "relative flex size-9 items-center justify-center",
87
- "border border-input outline-hidden",
88
- "text-sm",
89
- "transition-all",
90
- "motion-reduce:transition-none",
91
- "not-has-disabled:shadow-xs",
92
- "first:rounded-l-lg",
93
- "last:rounded-r-lg",
94
- "aria-invalid:border-destructive",
95
- "dark:bg-input/30",
96
- "data-active:z-10 data-active:border-ring data-active:ring-3 data-active:ring-ring/50",
97
- "data-active:aria-invalid:border-destructive data-active:aria-invalid:ring-destructive/20",
98
- "dark:data-active:aria-invalid:ring-destructive/40",
84
+ "relative flex size-9 items-center justify-center border-y border-r border-input text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-3 data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40",
99
85
  className,
100
86
  )}
101
87
  data-active={isActive}
@@ -104,18 +90,8 @@ function InputOTPSlot({ className, index, ...props }: InputOTPSlotProps): JSX.El
104
90
  >
105
91
  {char}
106
92
  {hasFakeCaret ? (
107
- <div
108
- className={cn("absolute inset-0 flex items-center justify-center", "pointer-events-none")}
109
- >
110
- <div
111
- className={cn(
112
- "h-4 w-px",
113
- "bg-foreground",
114
- "animate-caret-blink",
115
- "animation-duration-1000",
116
- "motion-reduce:animate-none motion-reduce:duration-0",
117
- )}
118
- />
93
+ <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
94
+ <div className="h-4 w-px animate-caret-blink bg-foreground animation-duration-1000" />
119
95
  </div>
120
96
  ) : null}
121
97
  </div>
@@ -136,7 +112,12 @@ type InputOTPSeparatorProps = ComponentProps<"div">;
136
112
  */
137
113
  function InputOTPSeparator({ ...props }: InputOTPSeparatorProps): JSX.Element {
138
114
  return (
139
- <div data-slot="input-otp-separator" {...props}>
115
+ <div
116
+ className="flex items-center [&_svg:not([class*='size-'])]:size-4"
117
+ data-slot="input-otp-separator"
118
+ role="separator"
119
+ {...props}
120
+ >
140
121
  <MinusIcon />
141
122
  </div>
142
123
  );
@@ -1,9 +1,5 @@
1
- "use client";
2
-
3
- import { cn } from "#/lib/utils";
4
- import type { ComponentProps, JSX, MouseEventHandler } from "react";
5
-
6
1
  import { EyeIcon, EyeOffIcon } from "lucide-react";
2
+ import type { ComponentProps, JSX, MouseEventHandler } from "react";
7
3
  import { useCallback, useState } from "react";
8
4
 
9
5
  import { InputGroup, InputGroupButton, InputGroupInput } from "#/components/input-group";
@@ -20,12 +16,7 @@ type InputPasswordProps = Omit<ComponentProps<typeof InputGroupInput>, "type">;
20
16
  /**
21
17
  * @since 0.3.16-canary.0
22
18
  */
23
- function InputPassword({
24
- className,
25
- disabled,
26
- readOnly,
27
- ...props
28
- }: InputPasswordProps): JSX.Element {
19
+ function InputPassword({ className, disabled, readOnly, ...props }: InputPasswordProps): JSX.Element {
29
20
  const [type, setType] = useState<"password" | "text">("password");
30
21
 
31
22
  const togglePasswordVisibility = useCallback<MouseEventHandler<HTMLButtonElement>>(() => {
@@ -33,26 +24,11 @@ function InputPassword({
33
24
  }, []);
34
25
 
35
26
  return (
36
- <InputGroup
37
- className={className}
38
- data-disabled={disabled ? "true" : undefined}
39
- data-slot="input-password"
40
- >
41
- <InputGroupInput
42
- autoCapitalize="none"
43
- data-slot="input-password-item"
44
- disabled={disabled}
45
- readOnly={readOnly}
46
- type={type}
47
- {...props}
48
- />
27
+ <InputGroup className={className} data-disabled={disabled ? "true" : undefined} data-slot="input-password">
28
+ <InputGroupInput autoCapitalize="none" disabled={disabled} readOnly={readOnly} type={type} {...props} />
49
29
  <InputGroupButton
50
30
  aria-label={type === "password" ? "Show password" : "Hide password"}
51
- className={cn(
52
- "rounded-full",
53
- "focus-visible:ring-0",
54
- "focus-visible:not-disabled:bg-input",
55
- )}
31
+ className="rounded-full"
56
32
  data-slot="input-password-toggle"
57
33
  disabled={disabled}
58
34
  size="icon-sm"