@codefast/ui 0.3.16-canary.2 → 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 (289) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +28 -17
  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 +14 -14
  8. package/dist/components/alert.mjs +17 -28
  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.d.mts +3 -15
  14. package/dist/components/badge.mjs +6 -48
  15. package/dist/components/breadcrumb.d.mts +1 -0
  16. package/dist/components/breadcrumb.mjs +11 -10
  17. package/dist/components/button-group.d.mts +3 -13
  18. package/dist/components/button-group.mjs +9 -31
  19. package/dist/components/button.d.mts +3 -26
  20. package/dist/components/button.mjs +9 -79
  21. package/dist/components/calendar.d.mts +6 -2
  22. package/dist/components/calendar.mjs +41 -44
  23. package/dist/components/card.d.mts +4 -2
  24. package/dist/components/card.mjs +9 -9
  25. package/dist/components/carousel.d.mts +16 -5
  26. package/dist/components/carousel.mjs +24 -11
  27. package/dist/components/chart.d.mts +9 -6
  28. package/dist/components/chart.mjs +21 -15
  29. package/dist/components/checkbox-cards.mjs +4 -4
  30. package/dist/components/checkbox-group.mjs +3 -4
  31. package/dist/components/checkbox.d.mts +2 -2
  32. package/dist/components/checkbox.mjs +6 -7
  33. package/dist/components/collapsible.d.mts +4 -4
  34. package/dist/components/collapsible.mjs +4 -5
  35. package/dist/components/command.d.mts +11 -1
  36. package/dist/components/command.mjs +35 -32
  37. package/dist/components/context-menu.d.mts +22 -15
  38. package/dist/components/context-menu.mjs +44 -39
  39. package/dist/components/dialog.d.mts +19 -23
  40. package/dist/components/dialog.mjs +48 -47
  41. package/dist/components/direction.d.mts +24 -0
  42. package/dist/components/direction.mjs +18 -0
  43. package/dist/components/drawer.d.mts +3 -21
  44. package/dist/components/drawer.mjs +19 -27
  45. package/dist/components/dropdown-menu.d.mts +22 -15
  46. package/dist/components/dropdown-menu.mjs +41 -37
  47. package/dist/components/empty.d.mts +3 -13
  48. package/dist/components/empty.mjs +8 -23
  49. package/dist/components/field.d.mts +3 -14
  50. package/dist/components/field.mjs +14 -44
  51. package/dist/components/form.d.mts +7 -10
  52. package/dist/components/form.mjs +6 -7
  53. package/dist/components/hover-card.d.mts +5 -5
  54. package/dist/components/hover-card.mjs +14 -12
  55. package/dist/components/input-group.d.mts +4 -31
  56. package/dist/components/input-group.mjs +14 -96
  57. package/dist/components/input-number.d.mts +3 -1
  58. package/dist/components/input-number.mjs +50 -28
  59. package/dist/components/input-otp.mjs +9 -7
  60. package/dist/components/input-password.mjs +1 -4
  61. package/dist/components/input-search.mjs +3 -5
  62. package/dist/components/input.mjs +1 -2
  63. package/dist/components/item.d.mts +4 -29
  64. package/dist/components/item.mjs +12 -65
  65. package/dist/components/kbd.mjs +1 -1
  66. package/dist/components/label.d.mts +2 -2
  67. package/dist/components/label.mjs +3 -4
  68. package/dist/components/menubar.d.mts +22 -16
  69. package/dist/components/menubar.mjs +54 -47
  70. package/dist/components/native-select.d.mts +5 -1
  71. package/dist/components/native-select.mjs +9 -6
  72. package/dist/components/navigation-menu.d.mts +30 -13
  73. package/dist/components/navigation-menu.mjs +35 -32
  74. package/dist/components/pagination.d.mts +7 -1
  75. package/dist/components/pagination.mjs +27 -12
  76. package/dist/components/popover.d.mts +40 -7
  77. package/dist/components/popover.mjs +46 -14
  78. package/dist/components/progress-circle.d.mts +3 -47
  79. package/dist/components/progress-circle.mjs +2 -48
  80. package/dist/components/progress.d.mts +2 -2
  81. package/dist/components/progress.mjs +5 -6
  82. package/dist/components/radio-cards.d.mts +3 -3
  83. package/dist/components/radio-cards.mjs +11 -11
  84. package/dist/components/radio-group.d.mts +3 -3
  85. package/dist/components/radio-group.mjs +9 -9
  86. package/dist/components/radio.mjs +2 -3
  87. package/dist/components/resizable.mjs +3 -8
  88. package/dist/components/scroll-area.d.mts +8 -24
  89. package/dist/components/scroll-area.mjs +16 -70
  90. package/dist/components/select.d.mts +14 -14
  91. package/dist/components/select.mjs +47 -47
  92. package/dist/components/separator.d.mts +4 -19
  93. package/dist/components/separator.mjs +6 -27
  94. package/dist/components/sheet.d.mts +18 -31
  95. package/dist/components/sheet.mjs +46 -87
  96. package/dist/components/sidebar.d.mts +3 -19
  97. package/dist/components/sidebar.mjs +48 -84
  98. package/dist/components/skeleton.mjs +1 -1
  99. package/dist/components/slider.d.mts +2 -2
  100. package/dist/components/slider.mjs +9 -11
  101. package/dist/components/sonner.mjs +11 -3
  102. package/dist/components/spinner.mjs +6 -7
  103. package/dist/components/switch.d.mts +5 -2
  104. package/dist/components/switch.mjs +7 -7
  105. package/dist/components/table.mjs +10 -10
  106. package/dist/components/tabs.d.mts +8 -5
  107. package/dist/components/tabs.mjs +18 -12
  108. package/dist/components/textarea.mjs +1 -1
  109. package/dist/components/toggle-group.d.mts +11 -7
  110. package/dist/components/toggle-group.mjs +20 -21
  111. package/dist/components/toggle.d.mts +4 -24
  112. package/dist/components/toggle.mjs +6 -45
  113. package/dist/components/tooltip.d.mts +7 -6
  114. package/dist/components/tooltip.mjs +19 -17
  115. package/dist/hooks/use-animated-value.mjs +0 -1
  116. package/dist/hooks/use-copy-to-clipboard.mjs +0 -1
  117. package/dist/hooks/use-is-mobile.mjs +0 -1
  118. package/dist/hooks/use-media-query.mjs +0 -1
  119. package/dist/hooks/use-mutation-observer.mjs +0 -1
  120. package/dist/hooks/use-pagination.mjs +0 -1
  121. package/dist/index.d.mts +38 -21
  122. package/dist/index.mjs +40 -23
  123. package/dist/lib/utils.d.mts +1 -12
  124. package/dist/lib/utils.mjs +1 -9
  125. package/dist/primitives/checkbox-group.d.mts +9 -11
  126. package/dist/primitives/checkbox-group.mjs +14 -19
  127. package/dist/primitives/input-number.d.mts +3 -4
  128. package/dist/primitives/input-number.mjs +3 -5
  129. package/dist/primitives/input.d.mts +4 -5
  130. package/dist/primitives/input.mjs +2 -3
  131. package/dist/primitives/progress-circle.d.mts +3 -4
  132. package/dist/primitives/progress-circle.mjs +2 -3
  133. package/dist/variants/alert.d.mts +18 -0
  134. package/dist/variants/alert.mjs +15 -0
  135. package/dist/variants/badge.d.mts +22 -0
  136. package/dist/variants/badge.mjs +19 -0
  137. package/dist/variants/button-group.d.mts +18 -0
  138. package/dist/variants/button-group.mjs +15 -0
  139. package/dist/variants/button.d.mts +32 -0
  140. package/dist/variants/button.mjs +34 -0
  141. package/dist/variants/empty.d.mts +18 -0
  142. package/dist/variants/empty.mjs +15 -0
  143. package/dist/variants/field.d.mts +19 -0
  144. package/dist/variants/field.mjs +16 -0
  145. package/dist/variants/input-group.d.mts +43 -0
  146. package/dist/variants/input-group.mjs +34 -0
  147. package/dist/variants/input-number.d.mts +45 -0
  148. package/dist/variants/input-number.mjs +40 -0
  149. package/dist/variants/item.d.mts +38 -0
  150. package/dist/variants/item.mjs +38 -0
  151. package/dist/variants/navigation-menu.d.mts +13 -0
  152. package/dist/variants/navigation-menu.mjs +8 -0
  153. package/dist/variants/progress-circle.d.mts +52 -0
  154. package/dist/variants/progress-circle.mjs +45 -0
  155. package/dist/variants/scroll-area.d.mts +24 -0
  156. package/dist/variants/scroll-area.mjs +58 -0
  157. package/dist/variants/separator.d.mts +23 -0
  158. package/dist/variants/separator.mjs +25 -0
  159. package/dist/variants/sheet.d.mts +20 -0
  160. package/dist/variants/sheet.mjs +17 -0
  161. package/dist/variants/sidebar.d.mts +23 -0
  162. package/dist/variants/sidebar.mjs +25 -0
  163. package/dist/variants/tabs.d.mts +18 -0
  164. package/dist/variants/tabs.mjs +15 -0
  165. package/dist/variants/toggle.d.mts +23 -0
  166. package/dist/variants/toggle.mjs +25 -0
  167. package/package.json +186 -55
  168. package/src/components/accordion.tsx +114 -0
  169. package/src/components/alert-dialog.tsx +298 -0
  170. package/src/components/alert.tsx +94 -0
  171. package/src/components/aspect-ratio.tsx +25 -0
  172. package/src/components/avatar.tsx +171 -0
  173. package/src/components/badge.tsx +35 -0
  174. package/src/components/breadcrumb.tsx +191 -0
  175. package/src/components/button-group.tsx +97 -0
  176. package/src/components/button.tsx +55 -0
  177. package/src/components/calendar.tsx +222 -0
  178. package/src/components/card.tsx +169 -0
  179. package/src/components/carousel.tsx +349 -0
  180. package/src/components/chart.tsx +536 -0
  181. package/src/components/checkbox-cards.tsx +72 -0
  182. package/src/components/checkbox-group.tsx +60 -0
  183. package/src/components/checkbox.tsx +44 -0
  184. package/src/components/collapsible.tsx +57 -0
  185. package/src/components/command.tsx +298 -0
  186. package/src/components/context-menu.tsx +410 -0
  187. package/src/components/dialog.tsx +243 -0
  188. package/src/components/direction.tsx +32 -0
  189. package/src/components/drawer.tsx +209 -0
  190. package/src/components/dropdown-menu.tsx +419 -0
  191. package/src/components/empty.tsx +155 -0
  192. package/src/components/field.tsx +329 -0
  193. package/src/components/form.tsx +258 -0
  194. package/src/components/hover-card.tsx +93 -0
  195. package/src/components/input-group.tsx +185 -0
  196. package/src/components/input-number.tsx +141 -0
  197. package/src/components/input-otp.tsx +132 -0
  198. package/src/components/input-password.tsx +50 -0
  199. package/src/components/input-search.tsx +81 -0
  200. package/src/components/input.tsx +36 -0
  201. package/src/components/item.tsx +266 -0
  202. package/src/components/kbd.tsx +47 -0
  203. package/src/components/label.tsx +36 -0
  204. package/src/components/menubar.tsx +440 -0
  205. package/src/components/native-select.tsx +87 -0
  206. package/src/components/navigation-menu.tsx +235 -0
  207. package/src/components/pagination.tsx +198 -0
  208. package/src/components/popover.tsx +170 -0
  209. package/src/components/progress-circle.tsx +185 -0
  210. package/src/components/progress.tsx +41 -0
  211. package/src/components/radio-cards.tsx +66 -0
  212. package/src/components/radio-group.tsx +59 -0
  213. package/src/components/radio.tsx +40 -0
  214. package/src/components/resizable.tsx +78 -0
  215. package/src/components/scroll-area.tsx +95 -0
  216. package/src/components/select.tsx +296 -0
  217. package/src/components/separator.tsx +60 -0
  218. package/src/components/sheet.tsx +241 -0
  219. package/src/components/sidebar.tsx +926 -0
  220. package/src/components/skeleton.tsx +35 -0
  221. package/src/components/slider.tsx +66 -0
  222. package/src/components/sonner.tsx +57 -0
  223. package/src/components/spinner.tsx +66 -0
  224. package/src/components/switch.tsx +44 -0
  225. package/src/components/table.tsx +183 -0
  226. package/src/components/tabs.tsx +110 -0
  227. package/src/components/textarea.tsx +35 -0
  228. package/src/components/toggle-group.tsx +137 -0
  229. package/src/components/toggle.tsx +30 -0
  230. package/src/components/tooltip.tsx +115 -0
  231. package/src/css/foundation/base.css +50 -0
  232. package/src/css/foundation/motion.css +36 -0
  233. package/src/css/foundation/source.css +3 -0
  234. package/src/css/foundation/tokens.css +71 -0
  235. package/src/css/foundation/variants.css +113 -0
  236. package/src/css/preset.css +5 -195
  237. package/src/css/style.css +1 -1
  238. package/src/css/{amber.css → themes/amber.css} +59 -22
  239. package/src/css/{blue.css → themes/blue.css} +59 -22
  240. package/src/css/{cyan.css → themes/cyan.css} +59 -22
  241. package/src/css/{emerald.css → themes/emerald.css} +59 -22
  242. package/src/css/{fuchsia.css → themes/fuchsia.css} +59 -22
  243. package/src/css/{gray.css → themes/gray.css} +59 -22
  244. package/src/css/{green.css → themes/green.css} +59 -22
  245. package/src/css/{indigo.css → themes/indigo.css} +59 -22
  246. package/src/css/{lime.css → themes/lime.css} +59 -22
  247. package/src/css/{neutral.css → themes/neutral.css} +59 -22
  248. package/src/css/{orange.css → themes/orange.css} +59 -22
  249. package/src/css/{pink.css → themes/pink.css} +59 -22
  250. package/src/css/{purple.css → themes/purple.css} +59 -22
  251. package/src/css/{red.css → themes/red.css} +59 -22
  252. package/src/css/{rose.css → themes/rose.css} +59 -22
  253. package/src/css/{sky.css → themes/sky.css} +59 -22
  254. package/src/css/{slate.css → themes/slate.css} +59 -22
  255. package/src/css/{stone.css → themes/stone.css} +59 -22
  256. package/src/css/{teal.css → themes/teal.css} +59 -22
  257. package/src/css/{violet.css → themes/violet.css} +59 -22
  258. package/src/css/{yellow.css → themes/yellow.css} +59 -22
  259. package/src/css/{zinc.css → themes/zinc.css} +59 -22
  260. package/src/hooks/use-animated-value.ts +91 -0
  261. package/src/hooks/use-copy-to-clipboard.ts +58 -0
  262. package/src/hooks/use-is-mobile.ts +25 -0
  263. package/src/hooks/use-media-query.ts +69 -0
  264. package/src/hooks/use-mutation-observer.ts +51 -0
  265. package/src/hooks/use-pagination.ts +164 -0
  266. package/src/index.ts +679 -0
  267. package/src/lib/utils.ts +5 -0
  268. package/src/primitives/checkbox-group.tsx +346 -0
  269. package/src/primitives/input-number.tsx +967 -0
  270. package/src/primitives/input.tsx +227 -0
  271. package/src/primitives/progress-circle.tsx +507 -0
  272. package/src/variants/alert.ts +34 -0
  273. package/src/variants/badge.ts +39 -0
  274. package/src/variants/button-group.ts +36 -0
  275. package/src/variants/button.ts +56 -0
  276. package/src/variants/empty.ts +34 -0
  277. package/src/variants/field.ts +37 -0
  278. package/src/variants/input-group.ts +80 -0
  279. package/src/variants/input-number.ts +65 -0
  280. package/src/variants/item.ts +68 -0
  281. package/src/variants/navigation-menu.ts +25 -0
  282. package/src/variants/progress-circle.ts +46 -0
  283. package/src/variants/scroll-area.ts +73 -0
  284. package/src/variants/separator.ts +40 -0
  285. package/src/variants/sheet.ts +37 -0
  286. package/src/variants/sidebar.ts +41 -0
  287. package/src/variants/tabs.ts +34 -0
  288. package/src/variants/toggle.ts +40 -0
  289. package/dist/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/clsx.d.mts +0 -6
@@ -0,0 +1,169 @@
1
+ import type { ComponentProps, JSX } from "react";
2
+
3
+ import { cn } from "#/lib/utils";
4
+
5
+ /* -----------------------------------------------------------------------------
6
+ * Component: Card
7
+ * -------------------------------------------------------------------------- */
8
+
9
+ /**
10
+ * @since 0.3.16-canary.0
11
+ */
12
+ type CardProps = ComponentProps<"div"> & {
13
+ size?: "default" | "sm";
14
+ };
15
+
16
+ /**
17
+ * @since 0.3.16-canary.0
18
+ */
19
+ function Card({ className, size = "default", ...props }: CardProps): JSX.Element {
20
+ return (
21
+ <div
22
+ className={cn(
23
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground shadow-xs ring-1 ring-foreground/10 [--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
24
+ className,
25
+ )}
26
+ data-size={size}
27
+ data-slot="card"
28
+ {...props}
29
+ />
30
+ );
31
+ }
32
+
33
+ /* -----------------------------------------------------------------------------
34
+ * Component: CardHeader
35
+ * -------------------------------------------------------------------------- */
36
+
37
+ /**
38
+ * @since 0.3.16-canary.0
39
+ */
40
+ type CardHeaderProps = ComponentProps<"div">;
41
+
42
+ /**
43
+ * @since 0.3.16-canary.0
44
+ */
45
+ function CardHeader({ className, ...props }: CardHeaderProps): JSX.Element {
46
+ return (
47
+ <div
48
+ className={cn(
49
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
50
+ className,
51
+ )}
52
+ data-slot="card-header"
53
+ {...props}
54
+ />
55
+ );
56
+ }
57
+
58
+ /* -----------------------------------------------------------------------------
59
+ * Component: CardTitle
60
+ * -------------------------------------------------------------------------- */
61
+
62
+ /**
63
+ * @since 0.3.16-canary.0
64
+ */
65
+ type CardTitleProps = ComponentProps<"div">;
66
+
67
+ /**
68
+ * @since 0.3.16-canary.0
69
+ */
70
+ function CardTitle({ className, ...props }: CardTitleProps): JSX.Element {
71
+ return (
72
+ <div
73
+ className={cn("font-heading text-base leading-normal font-medium group-data-[size=sm]/card:text-sm", className)}
74
+ data-slot="card-title"
75
+ {...props}
76
+ />
77
+ );
78
+ }
79
+
80
+ /* -----------------------------------------------------------------------------
81
+ * Component: CardDescription
82
+ * -------------------------------------------------------------------------- */
83
+
84
+ /**
85
+ * @since 0.3.16-canary.0
86
+ */
87
+ type CardDescriptionProps = ComponentProps<"div">;
88
+
89
+ /**
90
+ * @since 0.3.16-canary.0
91
+ */
92
+ function CardDescription({ className, ...props }: CardDescriptionProps): JSX.Element {
93
+ return <div className={cn("text-sm text-muted-foreground", className)} data-slot="card-description" {...props} />;
94
+ }
95
+
96
+ /* -----------------------------------------------------------------------------
97
+ * Component: CardContent
98
+ * -------------------------------------------------------------------------- */
99
+
100
+ /**
101
+ * @since 0.3.16-canary.0
102
+ */
103
+ type CardContentProps = ComponentProps<"div">;
104
+
105
+ /**
106
+ * @since 0.3.16-canary.0
107
+ */
108
+ function CardContent({ className, ...props }: CardContentProps): JSX.Element {
109
+ return <div className={cn("px-(--card-spacing)", className)} data-slot="card-content" {...props} />;
110
+ }
111
+
112
+ /* -----------------------------------------------------------------------------
113
+ * Component: CardFooter
114
+ * -------------------------------------------------------------------------- */
115
+
116
+ /**
117
+ * @since 0.3.16-canary.0
118
+ */
119
+ type CardFooterProps = ComponentProps<"div">;
120
+
121
+ /**
122
+ * @since 0.3.16-canary.0
123
+ */
124
+ function CardFooter({ className, ...props }: CardFooterProps): JSX.Element {
125
+ return (
126
+ <div
127
+ className={cn("flex items-center rounded-b-xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)", className)}
128
+ data-slot="card-footer"
129
+ {...props}
130
+ />
131
+ );
132
+ }
133
+
134
+ /* -----------------------------------------------------------------------------
135
+ * Component: CardAction
136
+ * -------------------------------------------------------------------------- */
137
+
138
+ /**
139
+ * @since 0.3.16-canary.0
140
+ */
141
+ type CardActionProps = ComponentProps<"div">;
142
+
143
+ /**
144
+ * @since 0.3.16-canary.0
145
+ */
146
+ function CardAction({ className, ...props }: CardActionProps): JSX.Element {
147
+ return (
148
+ <div
149
+ className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
150
+ data-slot="card-action"
151
+ {...props}
152
+ />
153
+ );
154
+ }
155
+
156
+ /* -----------------------------------------------------------------------------
157
+ * Exports
158
+ * -------------------------------------------------------------------------- */
159
+
160
+ export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
161
+ export type {
162
+ CardActionProps,
163
+ CardContentProps,
164
+ CardDescriptionProps,
165
+ CardFooterProps,
166
+ CardHeaderProps,
167
+ CardProps,
168
+ CardTitleProps,
169
+ };
@@ -0,0 +1,349 @@
1
+ import type { UseEmblaCarouselType } from "embla-carousel-react";
2
+ import useEmblaCarousel from "embla-carousel-react";
3
+ import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
4
+ import { Context } from "radix-ui/internal";
5
+ import type { ComponentProps, JSX, KeyboardEvent } from "react";
6
+ import { useCallback, useEffect, useState } from "react";
7
+
8
+ import { Button } from "#/components/button";
9
+ import { cn } from "#/lib/utils";
10
+
11
+ /* -----------------------------------------------------------------------------
12
+ * Context: Carousel
13
+ * -------------------------------------------------------------------------- */
14
+
15
+ const CAROUSEL_NAME = "Carousel";
16
+
17
+ type ScopedProps<P> = P & { __scopeCarousel?: Context.Scope };
18
+
19
+ const [createCarouselContext, createCarouselScope] = Context.createContextScope(CAROUSEL_NAME);
20
+
21
+ /**
22
+ * @since 0.3.16-canary.0
23
+ */
24
+ type CarouselApi = UseEmblaCarouselType[1];
25
+ type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
26
+ type CarouselOptions = UseCarouselParameters[0];
27
+ type CarouselPlugin = UseCarouselParameters[1];
28
+
29
+ interface BaseCarouselProps {
30
+ opts?: CarouselOptions;
31
+ orientation?: "horizontal" | "vertical";
32
+ plugins?: CarouselPlugin;
33
+ setApi?: (api: CarouselApi) => void;
34
+ }
35
+
36
+ type CarouselContextValue = BaseCarouselProps & {
37
+ api: ReturnType<typeof useEmblaCarousel>[1];
38
+ canScrollNext: boolean;
39
+ canScrollPrev: boolean;
40
+ carouselRef: ReturnType<typeof useEmblaCarousel>[0];
41
+ scrollNext: () => void;
42
+ scrollPrev: () => void;
43
+ };
44
+
45
+ const [CarouselContextProvider, useCarouselContext] = createCarouselContext<CarouselContextValue>(CAROUSEL_NAME);
46
+
47
+ /* -----------------------------------------------------------------------------
48
+ * Component: Carousel
49
+ * -------------------------------------------------------------------------- */
50
+
51
+ /**
52
+ * @since 0.3.16-canary.0
53
+ */
54
+ interface CarouselProps extends BaseCarouselProps, ComponentProps<"div"> {}
55
+
56
+ /**
57
+ * @since 0.3.16-canary.0
58
+ */
59
+ function Carousel({
60
+ __scopeCarousel,
61
+ children,
62
+ className,
63
+ opts,
64
+ orientation,
65
+ plugins,
66
+ setApi,
67
+ ...props
68
+ }: ScopedProps<CarouselProps>): JSX.Element {
69
+ const [carouselRef, api] = useEmblaCarousel(
70
+ {
71
+ ...opts,
72
+ axis: orientation === "vertical" ? "y" : "x",
73
+ },
74
+ plugins,
75
+ );
76
+
77
+ const [canScrollPrevious, setCanScrollPrevious] = useState(false);
78
+ const [canScrollNext, setCanScrollNext] = useState(false);
79
+
80
+ const onSelect = useCallback((carouselApi: CarouselApi) => {
81
+ if (!carouselApi) {
82
+ return;
83
+ }
84
+
85
+ setCanScrollPrevious(carouselApi.canScrollPrev());
86
+ setCanScrollNext(carouselApi.canScrollNext());
87
+ }, []);
88
+
89
+ const scrollPrevious = useCallback(() => {
90
+ api?.scrollPrev();
91
+ }, [api]);
92
+
93
+ const scrollNext = useCallback(() => {
94
+ api?.scrollNext();
95
+ }, [api]);
96
+
97
+ const handleKeyDown = useCallback(
98
+ (event: KeyboardEvent<HTMLDivElement>) => {
99
+ if (event.key === "ArrowLeft") {
100
+ event.preventDefault();
101
+ scrollPrevious();
102
+ } else if (event.key === "ArrowRight") {
103
+ event.preventDefault();
104
+ scrollNext();
105
+ }
106
+ },
107
+ [scrollPrevious, scrollNext],
108
+ );
109
+
110
+ useEffect(() => {
111
+ if (!api || !setApi) {
112
+ return;
113
+ }
114
+
115
+ setApi(api);
116
+ }, [api, setApi]);
117
+
118
+ useEffect(() => {
119
+ if (!api) {
120
+ return;
121
+ }
122
+
123
+ // Defer onSelect to avoid synchronous setState in effect
124
+ queueMicrotask(() => {
125
+ onSelect(api);
126
+ });
127
+ api.on("reInit", onSelect);
128
+ api.on("select", onSelect);
129
+
130
+ return (): void => {
131
+ api.off("select", onSelect);
132
+ };
133
+ }, [api, onSelect]);
134
+
135
+ return (
136
+ <CarouselContextProvider
137
+ api={api}
138
+ canScrollNext={canScrollNext}
139
+ canScrollPrev={canScrollPrevious}
140
+ carouselRef={carouselRef}
141
+ opts={opts}
142
+ orientation={orientation ?? (opts?.axis === "y" ? "vertical" : "horizontal")}
143
+ scope={__scopeCarousel}
144
+ scrollNext={scrollNext}
145
+ scrollPrev={scrollPrevious}
146
+ >
147
+ <div
148
+ aria-roledescription="carousel"
149
+ className={cn("relative", className)}
150
+ data-slot="carousel"
151
+ role="region"
152
+ onKeyDownCapture={handleKeyDown}
153
+ {...props}
154
+ >
155
+ {children}
156
+ </div>
157
+ </CarouselContextProvider>
158
+ );
159
+ }
160
+
161
+ /* -----------------------------------------------------------------------------
162
+ * Component: CarouselContent
163
+ * -------------------------------------------------------------------------- */
164
+
165
+ const CAROUSEL_CONTENT_NAME = "CarouselContent";
166
+
167
+ /**
168
+ * @since 0.3.16-canary.0
169
+ */
170
+ interface CarouselContentProps extends ComponentProps<"div"> {
171
+ classNames?: {
172
+ /** Class applied to the flex track that holds the slides. */
173
+ content?: string;
174
+ /** Class applied to the scroll viewport (the `overflow-hidden` element). */
175
+ wrapper?: string;
176
+ };
177
+ }
178
+
179
+ /**
180
+ * The scroll viewport requires `overflow-hidden` (Embla hides off-screen slides
181
+ * with it), so any ring/shadow on slide content that sits OUTSIDE the slide's
182
+ * border-box is clipped where the slide meets the viewport edge. This is
183
+ * inherent to every Embla-based carousel — the active slide is flush with both
184
+ * scroll-axis edges, so left/right rings (horizontal) cannot show without
185
+ * revealing the neighbouring slide.
186
+ *
187
+ * To give content shadows/rings breathing room on the CROSS axis (top/bottom
188
+ * for horizontal carousels), add a negative-margin + matching padding via
189
+ * `classNames.wrapper`, e.g. `classNames={{ wrapper: "-my-2 py-2" }}`. This
190
+ * shifts no layout but lets the clip happen `n`px further out.
191
+ *
192
+ * @since 0.3.16-canary.0
193
+ */
194
+ function CarouselContent({
195
+ __scopeCarousel,
196
+ className,
197
+ classNames,
198
+ ...props
199
+ }: ScopedProps<CarouselContentProps>): JSX.Element {
200
+ const { carouselRef, orientation } = useCarouselContext(CAROUSEL_CONTENT_NAME, __scopeCarousel);
201
+
202
+ return (
203
+ <div ref={carouselRef} className={cn("overflow-hidden", classNames?.wrapper)} data-slot="carousel-content">
204
+ <div
205
+ className={cn(
206
+ "flex",
207
+ orientation === "horizontal" ? "-ml-4" : "-mt-4 h-full flex-col",
208
+ classNames?.content,
209
+ className,
210
+ )}
211
+ {...props}
212
+ />
213
+ </div>
214
+ );
215
+ }
216
+
217
+ /* -----------------------------------------------------------------------------
218
+ * Component: CarouselItem
219
+ * -------------------------------------------------------------------------- */
220
+
221
+ const CAROUSEL_ITEM_NAME = "CarouselItem";
222
+
223
+ /**
224
+ * @since 0.3.16-canary.0
225
+ */
226
+ type CarouselItemProps = ComponentProps<"div">;
227
+
228
+ /**
229
+ * @since 0.3.16-canary.0
230
+ */
231
+ function CarouselItem({ __scopeCarousel, className, ...props }: ScopedProps<CarouselItemProps>): JSX.Element {
232
+ const { orientation } = useCarouselContext(CAROUSEL_ITEM_NAME, __scopeCarousel);
233
+
234
+ return (
235
+ <div
236
+ aria-roledescription="slide"
237
+ className={cn("min-w-0 shrink-0 grow-0 basis-full", orientation === "horizontal" ? "pl-4" : "pt-4", className)}
238
+ data-slot="carousel-item"
239
+ role="group"
240
+ {...props}
241
+ />
242
+ );
243
+ }
244
+
245
+ /* -----------------------------------------------------------------------------
246
+ * Component: CarouselPrevious
247
+ * -------------------------------------------------------------------------- */
248
+
249
+ const CAROUSEL_PREVIOUS_NAME = "CarouselPrevious";
250
+
251
+ /**
252
+ * @since 0.3.16-canary.0
253
+ */
254
+ type CarouselPreviousProps = ComponentProps<typeof Button>;
255
+
256
+ /**
257
+ * @since 0.3.16-canary.0
258
+ */
259
+ function CarouselPrevious({
260
+ __scopeCarousel,
261
+ className,
262
+ size = "icon-sm",
263
+ variant = "outline",
264
+ ...props
265
+ }: ScopedProps<CarouselPreviousProps>): JSX.Element {
266
+ const { canScrollPrev, orientation, scrollPrev } = useCarouselContext(CAROUSEL_PREVIOUS_NAME, __scopeCarousel);
267
+
268
+ return (
269
+ <Button
270
+ aria-label="Previous slide"
271
+ className={cn(
272
+ "absolute touch-manipulation rounded-full",
273
+ orientation === "horizontal"
274
+ ? "top-1/2 -left-12 -translate-y-1/2 active:not-aria-[haspopup]:translate-y-[calc(-50%+1px)]"
275
+ : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
276
+ className,
277
+ )}
278
+ data-slot="carousel-previous"
279
+ disabled={!canScrollPrev}
280
+ size={size}
281
+ variant={variant}
282
+ onClick={scrollPrev}
283
+ {...props}
284
+ >
285
+ <ChevronLeftIcon className="rtl:rotate-180" />
286
+ <span className="sr-only">Previous slide</span>
287
+ </Button>
288
+ );
289
+ }
290
+
291
+ /* -----------------------------------------------------------------------------
292
+ * Component: CarouselNext
293
+ * -------------------------------------------------------------------------- */
294
+
295
+ const CAROUSEL_NEXT_NAME = "CarouselNext";
296
+
297
+ /**
298
+ * @since 0.3.16-canary.0
299
+ */
300
+ type CarouselNextProps = ComponentProps<typeof Button>;
301
+
302
+ /**
303
+ * @since 0.3.16-canary.0
304
+ */
305
+ function CarouselNext({
306
+ __scopeCarousel,
307
+ className,
308
+ size = "icon-sm",
309
+ variant = "outline",
310
+ ...props
311
+ }: ScopedProps<CarouselNextProps>): JSX.Element {
312
+ const { canScrollNext, orientation, scrollNext } = useCarouselContext(CAROUSEL_NEXT_NAME, __scopeCarousel);
313
+
314
+ return (
315
+ <Button
316
+ aria-label="Next slide"
317
+ className={cn(
318
+ "absolute touch-manipulation rounded-full",
319
+ orientation === "horizontal"
320
+ ? "top-1/2 -right-12 -translate-y-1/2 active:not-aria-[haspopup]:translate-y-[calc(-50%+1px)]"
321
+ : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
322
+ className,
323
+ )}
324
+ data-slot="carousel-next"
325
+ disabled={!canScrollNext}
326
+ size={size}
327
+ variant={variant}
328
+ onClick={scrollNext}
329
+ {...props}
330
+ >
331
+ <ChevronRightIcon className="rtl:rotate-180" />
332
+ <span className="sr-only">Next slide</span>
333
+ </Button>
334
+ );
335
+ }
336
+
337
+ /* -----------------------------------------------------------------------------
338
+ * Exports
339
+ * -------------------------------------------------------------------------- */
340
+
341
+ export type {
342
+ CarouselApi,
343
+ CarouselContentProps,
344
+ CarouselItemProps,
345
+ CarouselNextProps,
346
+ CarouselPreviousProps,
347
+ CarouselProps,
348
+ };
349
+ export { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, createCarouselScope };