@thorprovider/blocks 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/.turbo/turbo-build.log +24 -0
  2. package/.turbo/turbo-test.log +10 -0
  3. package/.turbo/turbo-type-check.log +0 -0
  4. package/AGENTS.md +1 -0
  5. package/README.md +161 -0
  6. package/components.json +33 -0
  7. package/dist/.tsbuildinfo +1 -0
  8. package/dist/contracts.d.mts +563 -0
  9. package/dist/contracts.d.ts +563 -0
  10. package/dist/contracts.js +207 -0
  11. package/dist/contracts.js.map +1 -0
  12. package/dist/contracts.mjs +168 -0
  13. package/dist/contracts.mjs.map +1 -0
  14. package/dist/index.d.mts +2408 -0
  15. package/dist/index.d.ts +2408 -0
  16. package/dist/index.js +16422 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/index.mjs +16352 -0
  19. package/dist/index.mjs.map +1 -0
  20. package/docs/standards/data-contracts.md +70 -0
  21. package/docs/standards/theming.md +85 -0
  22. package/package.json +62 -0
  23. package/src/blocks/application/app-shells/app-shell-1-sidebar.tsx +198 -0
  24. package/src/blocks/application/app-shells/app-shell-1.tsx +196 -0
  25. package/src/blocks/application/login-forms/login-page-1.tsx +246 -0
  26. package/src/blocks/application/login-forms/login-page-2.tsx +207 -0
  27. package/src/blocks/application/password-recovery/forgot-password-page-1-brand-mark.tsx +38 -0
  28. package/src/blocks/application/password-recovery/forgot-password-page-1.tsx +320 -0
  29. package/src/blocks/application/signup-forms/signup-page-1.tsx +231 -0
  30. package/src/blocks/application/verification/verify-1.tsx +307 -0
  31. package/src/blocks/application/verification/verify-confetti.tsx +192 -0
  32. package/src/blocks/e-commerce/category-filters/category-filter-1.tsx +260 -0
  33. package/src/blocks/e-commerce/category-filters/category-filter-2-filter-panel.tsx +179 -0
  34. package/src/blocks/e-commerce/category-filters/category-filter-2.tsx +341 -0
  35. package/src/blocks/e-commerce/category-filters/category-filter-4-chip-rail.tsx +57 -0
  36. package/src/blocks/e-commerce/category-filters/category-filter-4-drawer.tsx +124 -0
  37. package/src/blocks/e-commerce/category-filters/category-filter-4-fields.tsx +170 -0
  38. package/src/blocks/e-commerce/category-filters/category-filter-4-sidebar.tsx +52 -0
  39. package/src/blocks/e-commerce/category-filters/category-filter-4-sort-sheet.tsx +57 -0
  40. package/src/blocks/e-commerce/category-filters/category-filter-4-state.ts +68 -0
  41. package/src/blocks/e-commerce/category-filters/category-filter-4.tsx +298 -0
  42. package/src/blocks/e-commerce/checkout-forms/card-formatting.test.ts +47 -0
  43. package/src/blocks/e-commerce/checkout-forms/card-formatting.ts +9 -0
  44. package/src/blocks/e-commerce/checkout-forms/checkbox-check.tsx +74 -0
  45. package/src/blocks/e-commerce/checkout-forms/checkout-confirmation-fulfilment-progress.tsx +189 -0
  46. package/src/blocks/e-commerce/checkout-forms/checkout-confirmation.tsx +283 -0
  47. package/src/blocks/e-commerce/checkout-forms/checkout-field-feedback.tsx +29 -0
  48. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-contact-step.tsx +96 -0
  49. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-country-field.tsx +51 -0
  50. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-order-summary.tsx +139 -0
  51. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-payment-step.tsx +184 -0
  52. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-progress.tsx +36 -0
  53. package/src/blocks/e-commerce/checkout-forms/checkout-form-1-shipping-step.tsx +107 -0
  54. package/src/blocks/e-commerce/checkout-forms/checkout-form-1.tsx +235 -0
  55. package/src/blocks/e-commerce/checkout-forms/checkout-form-2-order-summary.tsx +130 -0
  56. package/src/blocks/e-commerce/checkout-forms/checkout-form-2-payment-card.tsx +175 -0
  57. package/src/blocks/e-commerce/checkout-forms/checkout-form-2-shipping-card.tsx +190 -0
  58. package/src/blocks/e-commerce/checkout-forms/checkout-form-2.tsx +312 -0
  59. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-information-step.tsx +91 -0
  60. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-order-summary.tsx +110 -0
  61. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-payment-step.tsx +137 -0
  62. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-progress.tsx +68 -0
  63. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-review-step.tsx +79 -0
  64. package/src/blocks/e-commerce/checkout-forms/checkout-form-3-shipping-step.tsx +172 -0
  65. package/src/blocks/e-commerce/checkout-forms/checkout-form-3.tsx +392 -0
  66. package/src/blocks/e-commerce/checkout-forms/checkout-form-types.ts +7 -0
  67. package/src/blocks/e-commerce/navigation/category-icon.test.tsx +54 -0
  68. package/src/blocks/e-commerce/navigation/category-icon.tsx +94 -0
  69. package/src/blocks/e-commerce/navigation/mega-menu.test.tsx +139 -0
  70. package/src/blocks/e-commerce/navigation/mega-menu.tsx +271 -0
  71. package/src/blocks/e-commerce/navigation/mobile-category-drawer.test.tsx +152 -0
  72. package/src/blocks/e-commerce/navigation/mobile-category-drawer.tsx +276 -0
  73. package/src/blocks/e-commerce/order-history/order-history-1.tsx +159 -0
  74. package/src/blocks/e-commerce/order-history/order-history-2.tsx +222 -0
  75. package/src/blocks/e-commerce/product-categories/avatar-group.tsx +86 -0
  76. package/src/blocks/e-commerce/product-categories/product-category-1.tsx +126 -0
  77. package/src/blocks/e-commerce/product-categories/product-category-2.tsx +100 -0
  78. package/src/blocks/e-commerce/product-categories/product-category-4.tsx +129 -0
  79. package/src/blocks/e-commerce/product-categories/product-category-5.tsx +218 -0
  80. package/src/blocks/e-commerce/product-list/product-card-1.tsx +131 -0
  81. package/src/blocks/e-commerce/product-list/product-card-2.tsx +71 -0
  82. package/src/blocks/e-commerce/product-list/product-card-3-reaction-toggle.tsx +166 -0
  83. package/src/blocks/e-commerce/product-list/product-card-3.tsx +215 -0
  84. package/src/blocks/e-commerce/product-list/product-card-5-checkbox-check.tsx +98 -0
  85. package/src/blocks/e-commerce/product-list/product-card-5-reaction-toggle.tsx +171 -0
  86. package/src/blocks/e-commerce/product-list/product-card-5.tsx +367 -0
  87. package/src/blocks/e-commerce/product-overview/product-overview-1.tsx +201 -0
  88. package/src/blocks/e-commerce/product-overview/product-overview-2.tsx +272 -0
  89. package/src/blocks/e-commerce/product-overview/product-overview-5-gallery.tsx +59 -0
  90. package/src/blocks/e-commerce/product-overview/product-overview-5-lightbox-tab.tsx +104 -0
  91. package/src/blocks/e-commerce/product-overview/product-overview-5-reviews-tab.tsx +82 -0
  92. package/src/blocks/e-commerce/product-overview/product-overview-5-tabs.tsx +69 -0
  93. package/src/blocks/e-commerce/product-overview/product-overview-5.tsx +274 -0
  94. package/src/blocks/e-commerce/product-overview/product-quick-view-card.tsx +135 -0
  95. package/src/blocks/e-commerce/product-overview/product-quick-view-dialog.tsx +393 -0
  96. package/src/blocks/e-commerce/product-overview/product-quick-view.tsx +136 -0
  97. package/src/blocks/e-commerce/reviews/review-rating-1-review-form.tsx +133 -0
  98. package/src/blocks/e-commerce/reviews/review-rating-1.tsx +178 -0
  99. package/src/blocks/e-commerce/reviews/review-rating-2.tsx +246 -0
  100. package/src/blocks/e-commerce/shopping-carts/shopping-cart-1-spinning-counter.tsx +142 -0
  101. package/src/blocks/e-commerce/shopping-carts/shopping-cart-1.tsx +291 -0
  102. package/src/blocks/e-commerce/shopping-carts/shopping-cart-2-item-row.tsx +110 -0
  103. package/src/blocks/e-commerce/shopping-carts/shopping-cart-2-recommendations.tsx +51 -0
  104. package/src/blocks/e-commerce/shopping-carts/shopping-cart-2-spinning-counter.tsx +146 -0
  105. package/src/blocks/e-commerce/shopping-carts/shopping-cart-2.tsx +295 -0
  106. package/src/blocks/e-commerce/shopping-carts/shopping-cart-3-spinning-counter.tsx +142 -0
  107. package/src/blocks/e-commerce/shopping-carts/shopping-cart-3.tsx +342 -0
  108. package/src/blocks/e-commerce/shopping-carts/shopping-cart-4-spinning-counter.tsx +146 -0
  109. package/src/blocks/e-commerce/shopping-carts/shopping-cart-4.tsx +391 -0
  110. package/src/blocks/e-commerce/store-containers/store-container-1.tsx +29 -0
  111. package/src/blocks/e-commerce/storefront-hero/storefront-hero-1.tsx +244 -0
  112. package/src/blocks/e-commerce/storefront-hero/storefront-hero-2.tsx +283 -0
  113. package/src/blocks/e-commerce/storefront-hero/storefront-hero-5.tsx +318 -0
  114. package/src/blocks/e-commerce/storefront-hero/storefront-hero-6.tsx +205 -0
  115. package/src/blocks/marketing/banners/avatar-group.tsx +69 -0
  116. package/src/blocks/marketing/banners/banner-1.tsx +188 -0
  117. package/src/blocks/marketing/cta/cta-section-1.tsx +112 -0
  118. package/src/blocks/marketing/faq/faq-block-1.tsx +45 -0
  119. package/src/blocks/marketing/features/feature-1.tsx +97 -0
  120. package/src/blocks/marketing/features/feature-2.tsx +82 -0
  121. package/src/blocks/marketing/footers/footer-section-1.tsx +141 -0
  122. package/src/blocks/marketing/footers/footer-section-3.tsx +192 -0
  123. package/src/blocks/marketing/footers/footer-section-4.tsx +355 -0
  124. package/src/blocks/marketing/hero-sections/avatar-group.tsx +86 -0
  125. package/src/blocks/marketing/hero-sections/hero-section-1.tsx +135 -0
  126. package/src/blocks/marketing/logo-clouds/logo-cloud-1-logo-icon.tsx +52 -0
  127. package/src/blocks/marketing/logo-clouds/logo-cloud-1.tsx +56 -0
  128. package/src/blocks/marketing/navbars/navbar-1.tsx +267 -0
  129. package/src/blocks/marketing/navbars/navbar-2.tsx +351 -0
  130. package/src/blocks/marketing/navbars/navbar-3.tsx +303 -0
  131. package/src/blocks/marketing/navbars/navbar-4-account-menu.tsx +118 -0
  132. package/src/blocks/marketing/navbars/navbar-4-cart-sheet.tsx +248 -0
  133. package/src/blocks/marketing/navbars/navbar-4-like-button.tsx +177 -0
  134. package/src/blocks/marketing/navbars/navbar-4-mobile-nav.tsx +104 -0
  135. package/src/blocks/marketing/navbars/navbar-4-product-grid.tsx +219 -0
  136. package/src/blocks/marketing/navbars/navbar-4-search-bar.tsx +52 -0
  137. package/src/blocks/marketing/navbars/navbar-4.tsx +411 -0
  138. package/src/blocks/marketing/pricing/pricing-section-1.tsx +94 -0
  139. package/src/blocks/marketing/statistics/statistic-1.tsx +93 -0
  140. package/src/blocks/marketing/testimonials/testimonial-1.tsx +141 -0
  141. package/src/blocks/marketing/testimonials/testimonial-2.tsx +108 -0
  142. package/src/blocks/shared/reaction-toggle.tsx +145 -0
  143. package/src/hooks/use-mobile.ts +19 -0
  144. package/src/index.ts +200 -0
  145. package/src/lib/contracts.test.ts +32 -0
  146. package/src/lib/contracts.ts +235 -0
  147. package/src/lib/types/menu.ts +43 -0
  148. package/src/lib/types.ts +4 -0
  149. package/src/lib/utils.ts +10 -0
  150. package/src/ui/accordion.tsx +65 -0
  151. package/src/ui/avatar.tsx +108 -0
  152. package/src/ui/badge.tsx +47 -0
  153. package/src/ui/breadcrumb.tsx +108 -0
  154. package/src/ui/button-group.tsx +83 -0
  155. package/src/ui/button.tsx +63 -0
  156. package/src/ui/card.tsx +91 -0
  157. package/src/ui/carousel.tsx +241 -0
  158. package/src/ui/dialog.tsx +158 -0
  159. package/src/ui/drawer.tsx +134 -0
  160. package/src/ui/dropdown-menu.tsx +256 -0
  161. package/src/ui/empty.tsx +103 -0
  162. package/src/ui/field.tsx +248 -0
  163. package/src/ui/input-group.tsx +170 -0
  164. package/src/ui/input-otp.tsx +76 -0
  165. package/src/ui/input.tsx +20 -0
  166. package/src/ui/label.tsx +23 -0
  167. package/src/ui/navigation-menu.tsx +167 -0
  168. package/src/ui/pagination.tsx +127 -0
  169. package/src/ui/progress.tsx +30 -0
  170. package/src/ui/radio-group.tsx +44 -0
  171. package/src/ui/select.tsx +189 -0
  172. package/src/ui/separator.tsx +27 -0
  173. package/src/ui/sheet.tsx +142 -0
  174. package/src/ui/sidebar.tsx +726 -0
  175. package/src/ui/skeleton.tsx +13 -0
  176. package/src/ui/table.tsx +115 -0
  177. package/src/ui/tabs.tsx +90 -0
  178. package/src/ui/textarea.tsx +17 -0
  179. package/src/ui/toggle-group.tsx +83 -0
  180. package/src/ui/toggle.tsx +46 -0
  181. package/src/ui/tooltip.tsx +56 -0
  182. package/tsconfig.json +20 -0
  183. package/tsup.config.ts +16 -0
  184. package/vitest.config.ts +9 -0
@@ -0,0 +1,127 @@
1
+ import * as React from "react"
2
+ import { cn } from "cn"
3
+ import {
4
+ ChevronLeftIcon,
5
+ ChevronRightIcon,
6
+ MoreHorizontalIcon,
7
+ } from "lucide-react"
8
+
9
+ import { buttonVariants, type Button } from "@/ui/button"
10
+
11
+ function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
12
+ return (
13
+ <nav
14
+ role="navigation"
15
+ aria-label="pagination"
16
+ data-slot="pagination"
17
+ className={cn("mx-auto flex w-full justify-center", className)}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function PaginationContent({
24
+ className,
25
+ ...props
26
+ }: React.ComponentProps<"ul">) {
27
+ return (
28
+ <ul
29
+ data-slot="pagination-content"
30
+ className={cn("flex flex-row items-center gap-1", className)}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ function PaginationItem({ ...props }: React.ComponentProps<"li">) {
37
+ return <li data-slot="pagination-item" {...props} />
38
+ }
39
+
40
+ type PaginationLinkProps = {
41
+ isActive?: boolean
42
+ } & Pick<React.ComponentProps<typeof Button>, "size"> &
43
+ React.ComponentProps<"a">
44
+
45
+ function PaginationLink({
46
+ className,
47
+ isActive,
48
+ size = "icon",
49
+ ...props
50
+ }: PaginationLinkProps) {
51
+ return (
52
+ <a
53
+ aria-current={isActive ? "page" : undefined}
54
+ data-slot="pagination-link"
55
+ data-active={isActive}
56
+ className={cn(
57
+ buttonVariants({
58
+ variant: isActive ? "outline" : "ghost",
59
+ size,
60
+ }),
61
+ className
62
+ )}
63
+ {...props}
64
+ />
65
+ )
66
+ }
67
+
68
+ function PaginationPrevious({
69
+ className,
70
+ ...props
71
+ }: React.ComponentProps<typeof PaginationLink>) {
72
+ return (
73
+ <PaginationLink
74
+ aria-label="Go to previous page"
75
+ size="default"
76
+ className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
77
+ {...props}
78
+ >
79
+ <ChevronLeftIcon />
80
+ <span className="hidden sm:block">Previous</span>
81
+ </PaginationLink>
82
+ )
83
+ }
84
+
85
+ function PaginationNext({
86
+ className,
87
+ ...props
88
+ }: React.ComponentProps<typeof PaginationLink>) {
89
+ return (
90
+ <PaginationLink
91
+ aria-label="Go to next page"
92
+ size="default"
93
+ className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
94
+ {...props}
95
+ >
96
+ <span className="hidden sm:block">Next</span>
97
+ <ChevronRightIcon />
98
+ </PaginationLink>
99
+ )
100
+ }
101
+
102
+ function PaginationEllipsis({
103
+ className,
104
+ ...props
105
+ }: React.ComponentProps<"span">) {
106
+ return (
107
+ <span
108
+ aria-hidden
109
+ data-slot="pagination-ellipsis"
110
+ className={cn("flex size-9 items-center justify-center", className)}
111
+ {...props}
112
+ >
113
+ <MoreHorizontalIcon className="size-4" />
114
+ <span className="sr-only">More pages</span>
115
+ </span>
116
+ )
117
+ }
118
+
119
+ export {
120
+ Pagination,
121
+ PaginationContent,
122
+ PaginationLink,
123
+ PaginationItem,
124
+ PaginationPrevious,
125
+ PaginationNext,
126
+ PaginationEllipsis,
127
+ }
@@ -0,0 +1,30 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "cn"
5
+ import { Progress as ProgressPrimitive } from "radix-ui"
6
+
7
+ function Progress({
8
+ className,
9
+ value,
10
+ ...props
11
+ }: React.ComponentProps<typeof ProgressPrimitive.Root>) {
12
+ return (
13
+ <ProgressPrimitive.Root
14
+ data-slot="progress"
15
+ className={cn(
16
+ "relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ <ProgressPrimitive.Indicator
22
+ data-slot="progress-indicator"
23
+ className="h-full w-full flex-1 bg-primary transition-all"
24
+ style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
25
+ />
26
+ </ProgressPrimitive.Root>
27
+ )
28
+ }
29
+
30
+ export { Progress }
@@ -0,0 +1,44 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "cn"
5
+ import { CircleIcon } from "lucide-react"
6
+ import { RadioGroup as RadioGroupPrimitive } from "radix-ui"
7
+
8
+ function RadioGroup({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
12
+ return (
13
+ <RadioGroupPrimitive.Root
14
+ data-slot="radio-group"
15
+ className={cn("grid gap-3", className)}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ function RadioGroupItem({
22
+ className,
23
+ ...props
24
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
25
+ return (
26
+ <RadioGroupPrimitive.Item
27
+ data-slot="radio-group-item"
28
+ className={cn(
29
+ "aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
30
+ className
31
+ )}
32
+ {...props}
33
+ >
34
+ <RadioGroupPrimitive.Indicator
35
+ data-slot="radio-group-indicator"
36
+ className="relative flex items-center justify-center"
37
+ >
38
+ <CircleIcon className="absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-primary" />
39
+ </RadioGroupPrimitive.Indicator>
40
+ </RadioGroupPrimitive.Item>
41
+ )
42
+ }
43
+
44
+ export { RadioGroup, RadioGroupItem }
@@ -0,0 +1,189 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "cn"
5
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
6
+ import { Select as SelectPrimitive } from "radix-ui"
7
+
8
+ function Select({
9
+ ...props
10
+ }: React.ComponentProps<typeof SelectPrimitive.Root>) {
11
+ return <SelectPrimitive.Root data-slot="select" {...props} />
12
+ }
13
+
14
+ function SelectGroup({
15
+ ...props
16
+ }: React.ComponentProps<typeof SelectPrimitive.Group>) {
17
+ return <SelectPrimitive.Group data-slot="select-group" {...props} />
18
+ }
19
+
20
+ function SelectValue({
21
+ ...props
22
+ }: React.ComponentProps<typeof SelectPrimitive.Value>) {
23
+ return <SelectPrimitive.Value data-slot="select-value" {...props} />
24
+ }
25
+
26
+ function SelectTrigger({
27
+ className,
28
+ size = "default",
29
+ children,
30
+ ...props
31
+ }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
32
+ size?: "sm" | "default"
33
+ }) {
34
+ return (
35
+ <SelectPrimitive.Trigger
36
+ data-slot="select-trigger"
37
+ data-size={size}
38
+ className={cn(
39
+ "flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
40
+ className
41
+ )}
42
+ {...props}
43
+ >
44
+ {children}
45
+ <SelectPrimitive.Icon asChild>
46
+ <ChevronDownIcon className="size-4 opacity-50" />
47
+ </SelectPrimitive.Icon>
48
+ </SelectPrimitive.Trigger>
49
+ )
50
+ }
51
+
52
+ function SelectContent({
53
+ className,
54
+ children,
55
+ position = "item-aligned",
56
+ align = "center",
57
+ ...props
58
+ }: React.ComponentProps<typeof SelectPrimitive.Content>) {
59
+ return (
60
+ <SelectPrimitive.Portal>
61
+ <SelectPrimitive.Content
62
+ data-slot="select-content"
63
+ className={cn(
64
+ "relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
65
+ position === "popper" &&
66
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
67
+ className
68
+ )}
69
+ position={position}
70
+ align={align}
71
+ {...props}
72
+ >
73
+ <SelectScrollUpButton />
74
+ <SelectPrimitive.Viewport
75
+ className={cn(
76
+ "p-1",
77
+ position === "popper" &&
78
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
79
+ )}
80
+ >
81
+ {children}
82
+ </SelectPrimitive.Viewport>
83
+ <SelectScrollDownButton />
84
+ </SelectPrimitive.Content>
85
+ </SelectPrimitive.Portal>
86
+ )
87
+ }
88
+
89
+ function SelectLabel({
90
+ className,
91
+ ...props
92
+ }: React.ComponentProps<typeof SelectPrimitive.Label>) {
93
+ return (
94
+ <SelectPrimitive.Label
95
+ data-slot="select-label"
96
+ className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
97
+ {...props}
98
+ />
99
+ )
100
+ }
101
+
102
+ function SelectItem({
103
+ className,
104
+ children,
105
+ ...props
106
+ }: React.ComponentProps<typeof SelectPrimitive.Item>) {
107
+ return (
108
+ <SelectPrimitive.Item
109
+ data-slot="select-item"
110
+ className={cn(
111
+ "relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
112
+ className
113
+ )}
114
+ {...props}
115
+ >
116
+ <span
117
+ data-slot="select-item-indicator"
118
+ className="absolute right-2 flex size-3.5 items-center justify-center"
119
+ >
120
+ <SelectPrimitive.ItemIndicator>
121
+ <CheckIcon className="size-4" />
122
+ </SelectPrimitive.ItemIndicator>
123
+ </span>
124
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
125
+ </SelectPrimitive.Item>
126
+ )
127
+ }
128
+
129
+ function SelectSeparator({
130
+ className,
131
+ ...props
132
+ }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
133
+ return (
134
+ <SelectPrimitive.Separator
135
+ data-slot="select-separator"
136
+ className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
137
+ {...props}
138
+ />
139
+ )
140
+ }
141
+
142
+ function SelectScrollUpButton({
143
+ className,
144
+ ...props
145
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
146
+ return (
147
+ <SelectPrimitive.ScrollUpButton
148
+ data-slot="select-scroll-up-button"
149
+ className={cn(
150
+ "flex cursor-default items-center justify-center py-1",
151
+ className
152
+ )}
153
+ {...props}
154
+ >
155
+ <ChevronUpIcon className="size-4" />
156
+ </SelectPrimitive.ScrollUpButton>
157
+ )
158
+ }
159
+
160
+ function SelectScrollDownButton({
161
+ className,
162
+ ...props
163
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
164
+ return (
165
+ <SelectPrimitive.ScrollDownButton
166
+ data-slot="select-scroll-down-button"
167
+ className={cn(
168
+ "flex cursor-default items-center justify-center py-1",
169
+ className
170
+ )}
171
+ {...props}
172
+ >
173
+ <ChevronDownIcon className="size-4" />
174
+ </SelectPrimitive.ScrollDownButton>
175
+ )
176
+ }
177
+
178
+ export {
179
+ Select,
180
+ SelectContent,
181
+ SelectGroup,
182
+ SelectItem,
183
+ SelectLabel,
184
+ SelectScrollDownButton,
185
+ SelectScrollUpButton,
186
+ SelectSeparator,
187
+ SelectTrigger,
188
+ SelectValue,
189
+ }
@@ -0,0 +1,27 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "cn"
5
+ import { Separator as SeparatorPrimitive } from "radix-ui"
6
+
7
+ function Separator({
8
+ className,
9
+ orientation = "horizontal",
10
+ decorative = true,
11
+ ...props
12
+ }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
13
+ return (
14
+ <SeparatorPrimitive.Root
15
+ data-slot="separator"
16
+ decorative={decorative}
17
+ orientation={orientation}
18
+ className={cn(
19
+ "shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
20
+ className
21
+ )}
22
+ {...props}
23
+ />
24
+ )
25
+ }
26
+
27
+ export { Separator }
@@ -0,0 +1,142 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "cn"
5
+ import { XIcon } from "lucide-react"
6
+ import { Dialog as SheetPrimitive } from "radix-ui"
7
+
8
+ function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
9
+ return <SheetPrimitive.Root data-slot="sheet" {...props} />
10
+ }
11
+
12
+ function SheetTrigger({
13
+ ...props
14
+ }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
15
+ return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
16
+ }
17
+
18
+ function SheetClose({
19
+ ...props
20
+ }: React.ComponentProps<typeof SheetPrimitive.Close>) {
21
+ return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
22
+ }
23
+
24
+ function SheetPortal({
25
+ ...props
26
+ }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
27
+ return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
28
+ }
29
+
30
+ function SheetOverlay({
31
+ className,
32
+ ...props
33
+ }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
34
+ return (
35
+ <SheetPrimitive.Overlay
36
+ data-slot="sheet-overlay"
37
+ className={cn(
38
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
39
+ className
40
+ )}
41
+ {...props}
42
+ />
43
+ )
44
+ }
45
+
46
+ function SheetContent({
47
+ className,
48
+ children,
49
+ side = "right",
50
+ showCloseButton = true,
51
+ ...props
52
+ }: React.ComponentProps<typeof SheetPrimitive.Content> & {
53
+ side?: "top" | "right" | "bottom" | "left"
54
+ showCloseButton?: boolean
55
+ }) {
56
+ return (
57
+ <SheetPortal>
58
+ <SheetOverlay />
59
+ <SheetPrimitive.Content
60
+ data-slot="sheet-content"
61
+ className={cn(
62
+ "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:animate-in data-[state=open]:duration-500",
63
+ side === "right" &&
64
+ "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
65
+ side === "left" &&
66
+ "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
67
+ side === "top" &&
68
+ "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
69
+ side === "bottom" &&
70
+ "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
71
+ className
72
+ )}
73
+ {...props}
74
+ >
75
+ {children}
76
+ {showCloseButton && (
77
+ <SheetPrimitive.Close className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-secondary">
78
+ <XIcon className="size-4" />
79
+ <span className="sr-only">Close</span>
80
+ </SheetPrimitive.Close>
81
+ )}
82
+ </SheetPrimitive.Content>
83
+ </SheetPortal>
84
+ )
85
+ }
86
+
87
+ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
88
+ return (
89
+ <div
90
+ data-slot="sheet-header"
91
+ className={cn("flex flex-col gap-1.5 p-4", className)}
92
+ {...props}
93
+ />
94
+ )
95
+ }
96
+
97
+ function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
98
+ return (
99
+ <div
100
+ data-slot="sheet-footer"
101
+ className={cn("mt-auto flex flex-col gap-2 p-4", className)}
102
+ {...props}
103
+ />
104
+ )
105
+ }
106
+
107
+ function SheetTitle({
108
+ className,
109
+ ...props
110
+ }: React.ComponentProps<typeof SheetPrimitive.Title>) {
111
+ return (
112
+ <SheetPrimitive.Title
113
+ data-slot="sheet-title"
114
+ className={cn("font-semibold text-foreground", className)}
115
+ {...props}
116
+ />
117
+ )
118
+ }
119
+
120
+ function SheetDescription({
121
+ className,
122
+ ...props
123
+ }: React.ComponentProps<typeof SheetPrimitive.Description>) {
124
+ return (
125
+ <SheetPrimitive.Description
126
+ data-slot="sheet-description"
127
+ className={cn("text-sm text-muted-foreground", className)}
128
+ {...props}
129
+ />
130
+ )
131
+ }
132
+
133
+ export {
134
+ Sheet,
135
+ SheetTrigger,
136
+ SheetClose,
137
+ SheetContent,
138
+ SheetHeader,
139
+ SheetFooter,
140
+ SheetTitle,
141
+ SheetDescription,
142
+ }