@hanzo/ui 5.0.2 → 5.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 (371) hide show
  1. package/dist/accordion.js +1 -0
  2. package/dist/accordion.mjs +1 -0
  3. package/dist/alert-dialog.js +1 -0
  4. package/dist/alert-dialog.mjs +1 -0
  5. package/dist/alert.js +1 -0
  6. package/dist/alert.mjs +1 -0
  7. package/dist/avatar.js +1 -0
  8. package/dist/avatar.mjs +1 -0
  9. package/dist/badge.js +1 -0
  10. package/dist/badge.mjs +1 -0
  11. package/dist/breadcrumb.js +1 -0
  12. package/dist/breadcrumb.mjs +1 -0
  13. package/dist/calendar.js +1 -0
  14. package/dist/calendar.mjs +1 -0
  15. package/dist/carousel.js +1 -0
  16. package/dist/carousel.mjs +1 -0
  17. package/dist/checkbox.js +1 -0
  18. package/dist/checkbox.mjs +1 -0
  19. package/dist/chunk-3H5S2OQ3.mjs +1 -0
  20. package/dist/chunk-5GRJ7UQX.js +1 -0
  21. package/dist/chunk-63HNMH7C.js +1 -0
  22. package/dist/chunk-72TOQ4DM.mjs +1 -0
  23. package/dist/chunk-7AEFTV5R.mjs +1 -0
  24. package/dist/chunk-7M4AVV2R.js +1 -0
  25. package/dist/chunk-DKPVJSBC.js +1 -0
  26. package/dist/chunk-EI7MMDWY.js +1 -0
  27. package/dist/chunk-GANGDIZG.mjs +1 -0
  28. package/dist/chunk-GRGT2Z4K.js +1 -0
  29. package/dist/chunk-JCUUC6NY.mjs +1 -0
  30. package/dist/chunk-JUQMWLIN.js +1 -0
  31. package/dist/chunk-PRVEIITE.js +1 -0
  32. package/dist/chunk-SH52AKNZ.js +1 -0
  33. package/dist/chunk-TU67EJEW.mjs +1 -0
  34. package/dist/chunk-WN5KN73U.mjs +1 -0
  35. package/dist/chunk-YSXGDEY5.mjs +1 -0
  36. package/dist/chunk-Z76OOVUE.mjs +1 -0
  37. package/dist/collapsible.js +1 -0
  38. package/dist/collapsible.mjs +1 -0
  39. package/dist/command.js +1 -0
  40. package/dist/command.mjs +1 -0
  41. package/dist/context-menu.js +1 -0
  42. package/dist/context-menu.mjs +1 -0
  43. package/dist/dialog.js +1 -0
  44. package/dist/dialog.mjs +1 -0
  45. package/dist/drawer.js +1 -0
  46. package/dist/drawer.mjs +1 -0
  47. package/dist/dropdown-menu.js +1 -0
  48. package/dist/dropdown-menu.mjs +1 -0
  49. package/dist/form.js +1 -0
  50. package/dist/form.mjs +1 -0
  51. package/dist/hover-card.js +1 -0
  52. package/dist/hover-card.mjs +1 -0
  53. package/dist/index.js +1 -9079
  54. package/dist/index.mjs +1 -8700
  55. package/dist/input-otp.js +1 -0
  56. package/dist/input-otp.mjs +1 -0
  57. package/dist/lib/utils.js +1 -0
  58. package/dist/lib/utils.mjs +1 -0
  59. package/dist/navigation-menu.js +1 -0
  60. package/dist/navigation-menu.mjs +1 -0
  61. package/dist/popover.js +1 -0
  62. package/dist/popover.mjs +1 -0
  63. package/dist/progress.js +1 -0
  64. package/dist/progress.mjs +1 -0
  65. package/dist/radio-group.js +1 -0
  66. package/dist/radio-group.mjs +1 -0
  67. package/dist/resizable.js +1 -0
  68. package/dist/resizable.mjs +1 -0
  69. package/dist/scroll-area.js +1 -0
  70. package/dist/scroll-area.mjs +1 -0
  71. package/dist/select.js +1 -0
  72. package/dist/select.mjs +1 -0
  73. package/dist/separator.js +1 -0
  74. package/dist/separator.mjs +1 -0
  75. package/dist/sheet.js +1 -0
  76. package/dist/sheet.mjs +1 -0
  77. package/dist/skeleton.js +1 -0
  78. package/dist/skeleton.mjs +1 -0
  79. package/dist/slider.js +1 -0
  80. package/dist/slider.mjs +1 -0
  81. package/dist/sonner.js +1 -0
  82. package/dist/sonner.mjs +1 -0
  83. package/dist/src/utils.js +1 -0
  84. package/dist/src/utils.mjs +1 -0
  85. package/dist/switch.js +1 -0
  86. package/dist/switch.mjs +1 -0
  87. package/dist/table.js +1 -0
  88. package/dist/table.mjs +1 -0
  89. package/dist/tabs.js +1 -0
  90. package/dist/tabs.mjs +1 -0
  91. package/dist/tailwind/index.js +1 -0
  92. package/dist/tailwind/index.mjs +1 -0
  93. package/dist/textarea.js +1 -0
  94. package/dist/textarea.mjs +1 -0
  95. package/dist/toggle-group.js +1 -0
  96. package/dist/toggle-group.mjs +1 -0
  97. package/dist/toggle.js +1 -0
  98. package/dist/toggle.mjs +1 -0
  99. package/dist/tooltip.js +1 -0
  100. package/dist/tooltip.mjs +1 -0
  101. package/dist/types/index.js +1 -0
  102. package/dist/types/index.mjs +1 -0
  103. package/package.json +110 -81
  104. package/assets/ai-icons.tsx +0 -207
  105. package/assets/crypto.tsx +0 -33
  106. package/assets/file-type-icon.tsx +0 -66
  107. package/assets/file.tsx +0 -45
  108. package/assets/general.tsx +0 -2318
  109. package/assets/hanzo-logo.svg +0 -9
  110. package/assets/hanzo-logo.tsx +0 -17
  111. package/assets/index.ts +0 -122
  112. package/assets/index.tsx +0 -4
  113. package/assets/llm-provider.tsx +0 -1094
  114. package/blocks/auth/index.ts +0 -6
  115. package/blocks/auth/login-2fa.tsx +0 -165
  116. package/blocks/auth/login-basic.tsx +0 -94
  117. package/blocks/auth/login-social.tsx +0 -148
  118. package/blocks/auth/magic-link.tsx +0 -129
  119. package/blocks/auth/password-reset.tsx +0 -97
  120. package/blocks/auth/signup.tsx +0 -157
  121. package/blocks/components/accordian-block.tsx +0 -48
  122. package/blocks/components/block-component-props.ts +0 -11
  123. package/blocks/components/bullet-cards-block.tsx +0 -46
  124. package/blocks/components/card-block/index.tsx +0 -171
  125. package/blocks/components/card-block/link-out-button.tsx +0 -20
  126. package/blocks/components/card-block/util.ts +0 -28
  127. package/blocks/components/carte-blanche-block/index.tsx +0 -127
  128. package/blocks/components/carte-blanche-block/variant-content-left.tsx +0 -49
  129. package/blocks/components/content.tsx +0 -70
  130. package/blocks/components/cta-block.tsx +0 -115
  131. package/blocks/components/enh-heading-block.tsx +0 -204
  132. package/blocks/components/grid-block/grid-block-mutator.ts +0 -12
  133. package/blocks/components/grid-block/index.tsx +0 -83
  134. package/blocks/components/grid-block/mutator-registry.ts +0 -10
  135. package/blocks/components/grid-block/table-borders.mutator.ts +0 -47
  136. package/blocks/components/group-block.tsx +0 -83
  137. package/blocks/components/heading-block.tsx +0 -88
  138. package/blocks/components/image-block.tsx +0 -111
  139. package/blocks/components/index.ts +0 -30
  140. package/blocks/components/screenful-block/content.tsx +0 -123
  141. package/blocks/components/screenful-block/index.tsx +0 -107
  142. package/blocks/components/screenful-block/poster-background.tsx +0 -34
  143. package/blocks/components/screenful-block/video-background.tsx +0 -45
  144. package/blocks/components/space-block.tsx +0 -66
  145. package/blocks/components/video-block.tsx +0 -138
  146. package/blocks/data-display/activity-feed.tsx +0 -242
  147. package/blocks/data-display/data-table.tsx +0 -235
  148. package/blocks/data-display/stats-grid.tsx +0 -194
  149. package/blocks/def/accordian-block.ts +0 -14
  150. package/blocks/def/block.ts +0 -7
  151. package/blocks/def/bullet-cards-block.ts +0 -22
  152. package/blocks/def/card-block.ts +0 -22
  153. package/blocks/def/carte-blanche-block.ts +0 -21
  154. package/blocks/def/cta-block.ts +0 -19
  155. package/blocks/def/element-block.ts +0 -11
  156. package/blocks/def/enh-heading-block.ts +0 -44
  157. package/blocks/def/grid-block.ts +0 -16
  158. package/blocks/def/group-block.ts +0 -11
  159. package/blocks/def/heading-block.ts +0 -15
  160. package/blocks/def/image-block.ts +0 -31
  161. package/blocks/def/index.ts +0 -35
  162. package/blocks/def/screenful-block.ts +0 -54
  163. package/blocks/def/space-block.ts +0 -64
  164. package/blocks/def/video-block.ts +0 -9
  165. package/blocks/ecommerce/checkout.tsx +0 -242
  166. package/blocks/ecommerce/index.ts +0 -7
  167. package/blocks/ecommerce/product-detail.tsx +0 -257
  168. package/blocks/ecommerce/product-grid.tsx +0 -148
  169. package/blocks/ecommerce/shopping-cart.tsx +0 -181
  170. package/blocks/index.ts +0 -2
  171. package/blocks/marketing/cta-section.tsx +0 -207
  172. package/blocks/marketing/faq.tsx +0 -159
  173. package/blocks/marketing/features-grid.tsx +0 -156
  174. package/blocks/marketing/hero-section.tsx +0 -192
  175. package/blocks/marketing/index.ts +0 -6
  176. package/blocks/marketing/pricing-table.tsx +0 -121
  177. package/blocks/marketing/testimonials.tsx +0 -196
  178. package/components/index.ts +0 -9
  179. package/dist/index.js.map +0 -1
  180. package/dist/index.mjs.map +0 -1
  181. package/dist/tailwind.js +0 -2025
  182. package/dist/tailwind.js.map +0 -1
  183. package/dist/tailwind.mjs +0 -2013
  184. package/dist/tailwind.mjs.map +0 -1
  185. package/dist/types.js +0 -59
  186. package/dist/types.js.map +0 -1
  187. package/dist/types.mjs +0 -53
  188. package/dist/types.mjs.map +0 -1
  189. package/dist/utils.js +0 -30
  190. package/dist/utils.js.map +0 -1
  191. package/dist/utils.mjs +0 -26
  192. package/dist/utils.mjs.map +0 -1
  193. package/frameworks/core/index.ts +0 -6
  194. package/frameworks/core/utils/index.ts +0 -64
  195. package/frameworks/react/components/button.tsx +0 -26
  196. package/frameworks/react/components/index.ts +0 -5
  197. package/frameworks/react/hooks/index.ts +0 -5
  198. package/frameworks/react/index.ts +0 -9
  199. package/frameworks/react/package.json +0 -8
  200. package/frameworks/react/utils/index.ts +0 -2
  201. package/frameworks/react-native/index.ts +0 -9
  202. package/frameworks/react-native/package.json +0 -8
  203. package/frameworks/registry.json +0 -371
  204. package/frameworks/setup.sh +0 -69
  205. package/frameworks/svelte/index.ts +0 -9
  206. package/frameworks/svelte/package.json +0 -8
  207. package/frameworks/tracker.json +0 -1854
  208. package/frameworks/vue/index.ts +0 -9
  209. package/frameworks/vue/package.json +0 -8
  210. package/helpers/file.ts +0 -33
  211. package/helpers/memoization.ts +0 -40
  212. package/primitives/accordion.tsx +0 -74
  213. package/primitives/action-button.tsx +0 -42
  214. package/primitives/alert-dialog.tsx +0 -185
  215. package/primitives/alert.tsx +0 -74
  216. package/primitives/apply-typography.tsx +0 -55
  217. package/primitives/aspect-ratio.tsx +0 -5
  218. package/primitives/avatar.tsx +0 -57
  219. package/primitives/background-beams.tsx +0 -142
  220. package/primitives/badge.tsx +0 -45
  221. package/primitives/breadcrumb.tsx +0 -130
  222. package/primitives/breakpoint-indicator.tsx +0 -19
  223. package/primitives/button.tsx +0 -72
  224. package/primitives/calendar.tsx +0 -72
  225. package/primitives/card.tsx +0 -97
  226. package/primitives/carousel.tsx +0 -238
  227. package/primitives/chat/chat-input-area.tsx +0 -88
  228. package/primitives/chat/chat-input.tsx +0 -71
  229. package/primitives/chat/files-preview.tsx +0 -331
  230. package/primitives/chat/index.ts +0 -6
  231. package/primitives/chat/json-form.tsx +0 -8
  232. package/primitives/chat/message-list.tsx +0 -308
  233. package/primitives/chat/message.tsx +0 -569
  234. package/primitives/chat/sqlite-preview.tsx +0 -215
  235. package/primitives/checkbox.tsx +0 -32
  236. package/primitives/collapsible.tsx +0 -9
  237. package/primitives/combobox.tsx +0 -239
  238. package/primitives/command.tsx +0 -151
  239. package/primitives/context-menu.tsx +0 -206
  240. package/primitives/copy-to-clipboard-icon.tsx +0 -60
  241. package/primitives/dialog-video-controller.tsx +0 -38
  242. package/primitives/dialog.tsx +0 -128
  243. package/primitives/dot-pattern.tsx +0 -57
  244. package/primitives/dots-loader.tsx +0 -13
  245. package/primitives/drawer.tsx +0 -113
  246. package/primitives/dropdown-menu.tsx +0 -199
  247. package/primitives/error-message.tsx +0 -19
  248. package/primitives/file-uploader.tsx +0 -203
  249. package/primitives/form.tsx +0 -185
  250. package/primitives/hover-card.tsx +0 -28
  251. package/primitives/icons/github.tsx +0 -14
  252. package/primitives/icons/index.ts +0 -18
  253. package/primitives/icons/youtube-logo.tsx +0 -59
  254. package/primitives/index-client.ts +0 -4
  255. package/primitives/index-common.ts +0 -304
  256. package/primitives/index-next.ts +0 -4
  257. package/primitives/input-otp.tsx +0 -65
  258. package/primitives/input.tsx +0 -128
  259. package/primitives/label.tsx +0 -21
  260. package/primitives/list-adaptor.ts +0 -12
  261. package/primitives/list-box.tsx +0 -74
  262. package/primitives/loading-spinner.tsx +0 -33
  263. package/primitives/markdown-preview.tsx +0 -612
  264. package/primitives/mermaid.tsx +0 -196
  265. package/primitives/navigation-menu.tsx +0 -147
  266. package/primitives/next/image.tsx +0 -91
  267. package/primitives/next/index.ts +0 -7
  268. package/primitives/next/inline-icon.tsx +0 -36
  269. package/primitives/next/link-element.tsx +0 -109
  270. package/primitives/next/mdx-link.tsx +0 -22
  271. package/primitives/next/media-stack.tsx +0 -52
  272. package/primitives/next/nav-items.tsx +0 -45
  273. package/primitives/next/youtube-embed.tsx +0 -83
  274. package/primitives/pagination.tsx +0 -117
  275. package/primitives/popover.tsx +0 -34
  276. package/primitives/pretty-json-print.tsx +0 -28
  277. package/primitives/progress.tsx +0 -27
  278. package/primitives/prompt-textarea.tsx +0 -72
  279. package/primitives/qr-code.tsx +0 -112
  280. package/primitives/radio-group.tsx +0 -42
  281. package/primitives/resizable.tsx +0 -47
  282. package/primitives/scroll-area.tsx +0 -57
  283. package/primitives/search-input.tsx +0 -66
  284. package/primitives/select.tsx +0 -122
  285. package/primitives/separator.tsx +0 -26
  286. package/primitives/sheet.tsx +0 -139
  287. package/primitives/skeleton.tsx +0 -18
  288. package/primitives/slider.tsx +0 -63
  289. package/primitives/sonner.tsx +0 -35
  290. package/primitives/step-indicator.tsx +0 -69
  291. package/primitives/stepper.tsx +0 -272
  292. package/primitives/switch.tsx +0 -27
  293. package/primitives/table.tsx +0 -105
  294. package/primitives/tabs.tsx +0 -50
  295. package/primitives/text-area.tsx +0 -26
  296. package/primitives/text-link.tsx +0 -27
  297. package/primitives/textarea.tsx +0 -64
  298. package/primitives/textfield.tsx +0 -78
  299. package/primitives/toast.tsx +0 -30
  300. package/primitives/toggle-group.tsx +0 -63
  301. package/primitives/toggle.tsx +0 -44
  302. package/primitives/tooltip.tsx +0 -47
  303. package/primitives/video-player.tsx +0 -23
  304. package/src/button.ts +0 -1
  305. package/src/hooks/index.ts +0 -7
  306. package/src/hooks/use-click-away.ts +0 -31
  307. package/src/hooks/use-combined-refs.ts +0 -22
  308. package/src/hooks/use-copy-clipboard.ts +0 -30
  309. package/src/hooks/use-debounce.ts +0 -17
  310. package/src/hooks/use-fill-ids.ts +0 -25
  311. package/src/hooks/use-map.ts +0 -26
  312. package/src/hooks/use-measure.ts +0 -42
  313. package/src/hooks/use-reverse-video-playback.ts +0 -43
  314. package/src/hooks/use-scroll-restoration.ts +0 -50
  315. package/src/index-lean.ts +0 -87
  316. package/src/index.ts +0 -54
  317. package/src/mcp/README.md +0 -141
  318. package/src/mcp/enhanced-server.ts +0 -1208
  319. package/src/mcp/index.ts +0 -518
  320. package/src/mcp/package.json +0 -10
  321. package/src/registry/api.ts +0 -164
  322. package/src/registry/index.ts +0 -60
  323. package/src/registry/package.json +0 -10
  324. package/src/utils.ts +0 -19
  325. package/tailwind/colors.tailwind.js +0 -53
  326. package/tailwind/fontFamily.tailwind.ts +0 -7
  327. package/tailwind/fontSize.tailwind.ts +0 -13
  328. package/tailwind/index.ts +0 -7
  329. package/tailwind/safelist.tailwind.js +0 -26
  330. package/tailwind/screens.tailwind.js +0 -8
  331. package/tailwind/spacing.tailwind.js +0 -65
  332. package/tailwind/tailwind.config.hanzo-preset.d.ts +0 -5
  333. package/tailwind/tailwind.config.hanzo-preset.js +0 -915
  334. package/tailwind/tw-font-desc.ts +0 -15
  335. package/tailwind/typo-plugin/get-plugin-styles.js +0 -679
  336. package/tailwind/typo-plugin/index.d.ts +0 -9
  337. package/tailwind/typo-plugin/index.js +0 -141
  338. package/tailwind/typo-plugin/utils.js +0 -60
  339. package/tailwind/typography-test.mdx +0 -35
  340. package/tailwind/z-index.tailwind.js +0 -71
  341. package/types/animation-def.ts +0 -3
  342. package/types/breakpoints.ts +0 -11
  343. package/types/bullet-item.ts +0 -10
  344. package/types/button-def.ts +0 -39
  345. package/types/dimensions.ts +0 -8
  346. package/types/grid-def.ts +0 -56
  347. package/types/image-def.ts +0 -32
  348. package/types/index.ts +0 -30
  349. package/types/link-def.ts +0 -56
  350. package/types/media-stack-def.ts +0 -31
  351. package/types/t-shirt-size.ts +0 -5
  352. package/types/tshirt-dimensions.ts +0 -20
  353. package/types/video-def.ts +0 -25
  354. package/util/blob.ts +0 -33
  355. package/util/copy-to-clipboard.ts +0 -17
  356. package/util/create-shadow-root.ts +0 -22
  357. package/util/date.ts +0 -84
  358. package/util/debounce.ts +0 -11
  359. package/util/file.ts +0 -15
  360. package/util/format-and-abbreviate-as-currency.ts +0 -125
  361. package/util/format-text.ts +0 -34
  362. package/util/format-to-max-char.ts +0 -68
  363. package/util/index-client.ts +0 -3
  364. package/util/index.ts +0 -112
  365. package/util/number-abbreviate.ts +0 -49
  366. package/util/specifier.ts +0 -43
  367. package/util/spread-to-transform.ts +0 -25
  368. package/util/step-animation.ts +0 -90
  369. package/util/timing.ts +0 -3
  370. package/util/toasts.tsx +0 -17
  371. package/util/two-way-map.ts +0 -19
@@ -1,242 +0,0 @@
1
- 'use client'
2
-
3
- import { cn } from '@hanzo/ui/util'
4
- import { Button } from '@hanzo/ui/primitives'
5
- import { Input } from '@hanzo/ui/primitives'
6
- import { Label } from '@hanzo/ui/primitives'
7
- import { RadioGroup, RadioGroupItem } from '@hanzo/ui/primitives'
8
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@hanzo/ui/primitives'
9
- import { Separator } from '@hanzo/ui/primitives'
10
- import { Checkbox } from '@hanzo/ui/primitives'
11
-
12
- interface CheckoutProps extends React.ComponentPropsWithoutRef<'div'> {
13
- orderSummary: {
14
- items: Array<{
15
- name: string
16
- quantity: number
17
- price: number
18
- }>
19
- subtotal: number
20
- shipping: number
21
- tax: number
22
- total: number
23
- currency?: string
24
- }
25
- onSubmit?: (data: any) => void
26
- onBack?: () => void
27
- }
28
-
29
- export function Checkout({
30
- className,
31
- orderSummary,
32
- onSubmit,
33
- onBack,
34
- ...props
35
- }: CheckoutProps) {
36
- const formatPrice = (price: number, currency = '$') => {
37
- return `${currency}${price.toFixed(2)}`
38
- }
39
-
40
- const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
41
- e.preventDefault()
42
- const formData = new FormData(e.currentTarget)
43
- const data = Object.fromEntries(formData.entries())
44
- onSubmit?.(data)
45
- }
46
-
47
- return (
48
- <div className={cn('container py-8', className)} {...props}>
49
- <form onSubmit={handleSubmit} className="grid gap-8 lg:grid-cols-3">
50
- <div className="lg:col-span-2 space-y-6">
51
- {/* Shipping Information */}
52
- <Card>
53
- <CardHeader>
54
- <CardTitle>Shipping Information</CardTitle>
55
- <CardDescription>
56
- Enter your shipping address details
57
- </CardDescription>
58
- </CardHeader>
59
- <CardContent className="grid gap-4">
60
- <div className="grid gap-4 sm:grid-cols-2">
61
- <div className="grid gap-2">
62
- <Label htmlFor="firstName">First Name</Label>
63
- <Input id="firstName" name="firstName" required />
64
- </div>
65
- <div className="grid gap-2">
66
- <Label htmlFor="lastName">Last Name</Label>
67
- <Input id="lastName" name="lastName" required />
68
- </div>
69
- </div>
70
- <div className="grid gap-2">
71
- <Label htmlFor="email">Email</Label>
72
- <Input id="email" name="email" type="email" required />
73
- </div>
74
- <div className="grid gap-2">
75
- <Label htmlFor="address">Street Address</Label>
76
- <Input id="address" name="address" required />
77
- </div>
78
- <div className="grid gap-2">
79
- <Label htmlFor="address2">Apartment, suite, etc. (optional)</Label>
80
- <Input id="address2" name="address2" />
81
- </div>
82
- <div className="grid gap-4 sm:grid-cols-3">
83
- <div className="grid gap-2">
84
- <Label htmlFor="city">City</Label>
85
- <Input id="city" name="city" required />
86
- </div>
87
- <div className="grid gap-2">
88
- <Label htmlFor="state">State / Province</Label>
89
- <Input id="state" name="state" required />
90
- </div>
91
- <div className="grid gap-2">
92
- <Label htmlFor="zip">ZIP / Postal Code</Label>
93
- <Input id="zip" name="zip" required />
94
- </div>
95
- </div>
96
- <div className="grid gap-2">
97
- <Label htmlFor="phone">Phone Number</Label>
98
- <Input id="phone" name="phone" type="tel" />
99
- </div>
100
- </CardContent>
101
- </Card>
102
-
103
- {/* Payment Method */}
104
- <Card>
105
- <CardHeader>
106
- <CardTitle>Payment Method</CardTitle>
107
- <CardDescription>
108
- Select your payment method
109
- </CardDescription>
110
- </CardHeader>
111
- <CardContent className="grid gap-6">
112
- <RadioGroup defaultValue="card" name="paymentMethod">
113
- <div className="flex items-center space-x-2">
114
- <RadioGroupItem value="card" id="card" />
115
- <Label htmlFor="card">Credit Card</Label>
116
- </div>
117
- <div className="flex items-center space-x-2">
118
- <RadioGroupItem value="paypal" id="paypal" />
119
- <Label htmlFor="paypal">PayPal</Label>
120
- </div>
121
- <div className="flex items-center space-x-2">
122
- <RadioGroupItem value="crypto" id="crypto" />
123
- <Label htmlFor="crypto">Cryptocurrency</Label>
124
- </div>
125
- </RadioGroup>
126
-
127
- <div className="grid gap-4">
128
- <div className="grid gap-2">
129
- <Label htmlFor="cardNumber">Card Number</Label>
130
- <Input
131
- id="cardNumber"
132
- name="cardNumber"
133
- placeholder="1234 5678 9012 3456"
134
- />
135
- </div>
136
- <div className="grid gap-4 sm:grid-cols-3">
137
- <div className="grid gap-2 sm:col-span-2">
138
- <Label htmlFor="expiry">Expiry Date</Label>
139
- <Input
140
- id="expiry"
141
- name="expiry"
142
- placeholder="MM/YY"
143
- />
144
- </div>
145
- <div className="grid gap-2">
146
- <Label htmlFor="cvc">CVC</Label>
147
- <Input
148
- id="cvc"
149
- name="cvc"
150
- placeholder="123"
151
- />
152
- </div>
153
- </div>
154
- </div>
155
- </CardContent>
156
- </Card>
157
-
158
- {/* Billing Address */}
159
- <Card>
160
- <CardHeader>
161
- <CardTitle>Billing Address</CardTitle>
162
- </CardHeader>
163
- <CardContent>
164
- <div className="flex items-center space-x-2">
165
- <Checkbox id="sameAsShipping" name="sameAsShipping" defaultChecked />
166
- <label
167
- htmlFor="sameAsShipping"
168
- className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
169
- >
170
- Same as shipping address
171
- </label>
172
- </div>
173
- </CardContent>
174
- </Card>
175
- </div>
176
-
177
- {/* Order Summary */}
178
- <div>
179
- <Card>
180
- <CardHeader>
181
- <CardTitle>Order Summary</CardTitle>
182
- </CardHeader>
183
- <CardContent className="space-y-4">
184
- <div className="space-y-2">
185
- {orderSummary.items.map((item, i) => (
186
- <div key={i} className="flex justify-between text-sm">
187
- <span className="text-muted-foreground">
188
- {item.name} x {item.quantity}
189
- </span>
190
- <span>
191
- {formatPrice(item.price * item.quantity, orderSummary.currency)}
192
- </span>
193
- </div>
194
- ))}
195
- </div>
196
- <Separator />
197
- <div className="space-y-2">
198
- <div className="flex justify-between">
199
- <span>Subtotal</span>
200
- <span>{formatPrice(orderSummary.subtotal, orderSummary.currency)}</span>
201
- </div>
202
- <div className="flex justify-between">
203
- <span>Shipping</span>
204
- <span>{formatPrice(orderSummary.shipping, orderSummary.currency)}</span>
205
- </div>
206
- <div className="flex justify-between">
207
- <span>Tax</span>
208
- <span>{formatPrice(orderSummary.tax, orderSummary.currency)}</span>
209
- </div>
210
- </div>
211
- <Separator />
212
- <div className="flex justify-between text-lg font-semibold">
213
- <span>Total</span>
214
- <span>{formatPrice(orderSummary.total, orderSummary.currency)}</span>
215
- </div>
216
- </CardContent>
217
- <CardFooter className="flex-col gap-2">
218
- <Button type="submit" className="w-full" size="lg">
219
- Complete Order
220
- </Button>
221
- {onBack && (
222
- <Button
223
- type="button"
224
- variant="outline"
225
- className="w-full"
226
- onClick={onBack}
227
- >
228
- Back to Cart
229
- </Button>
230
- )}
231
- </CardFooter>
232
- </Card>
233
-
234
- <div className="mt-4 text-xs text-center text-muted-foreground">
235
- Your payment information is encrypted and secure.
236
- We never store your credit card details.
237
- </div>
238
- </div>
239
- </form>
240
- </div>
241
- )
242
- }
@@ -1,7 +0,0 @@
1
- export { ProductGrid } from './product-grid'
2
- export { ProductDetail } from './product-detail'
3
- export { ShoppingCart } from './shopping-cart'
4
- export { Checkout } from './checkout'
5
-
6
- export type { Product } from './product-grid'
7
- export type { CartItem } from './shopping-cart'
@@ -1,257 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import { cn } from '@hanzo/ui/util'
5
- import { Button } from '@hanzo/ui/primitives'
6
- import { Badge } from '@hanzo/ui/primitives'
7
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '@hanzo/ui/primitives'
8
- import { Star, ShoppingCart, Heart, Share2 } from 'lucide-react'
9
-
10
- interface ProductDetailProps extends React.ComponentPropsWithoutRef<'div'> {
11
- product: {
12
- id: string | number
13
- name: string
14
- description: string
15
- price: number
16
- originalPrice?: number
17
- currency?: string
18
- images: string[]
19
- rating?: number
20
- reviewCount?: number
21
- badge?: string
22
- inStock?: boolean
23
- variants?: Array<{
24
- id: string
25
- name: string
26
- value: string
27
- }>
28
- features?: string[]
29
- specifications?: Record<string, string>
30
- }
31
- onAddToCart?: (quantity: number, variant?: string) => void
32
- onAddToWishlist?: () => void
33
- onShare?: () => void
34
- }
35
-
36
- export function ProductDetail({
37
- className,
38
- product,
39
- onAddToCart,
40
- onAddToWishlist,
41
- onShare,
42
- ...props
43
- }: ProductDetailProps) {
44
- const [selectedImage, setSelectedImage] = useState(0)
45
- const [quantity, setQuantity] = useState(1)
46
- const [selectedVariant, setSelectedVariant] = useState(
47
- product.variants?.[0]?.id || ''
48
- )
49
-
50
- const formatPrice = (price: number, currency = '$') => {
51
- return `${currency}${price.toFixed(2)}`
52
- }
53
-
54
- const calculateDiscount = (price: number, originalPrice: number) => {
55
- return Math.round(((originalPrice - price) / originalPrice) * 100)
56
- }
57
-
58
- return (
59
- <div className={cn('container py-8', className)} {...props}>
60
- <div className="grid gap-8 lg:grid-cols-2">
61
- {/* Images */}
62
- <div className="space-y-4">
63
- <div className="aspect-square overflow-hidden rounded-lg">
64
- <img
65
- src={product.images[selectedImage]}
66
- alt={product.name}
67
- className="h-full w-full object-cover"
68
- />
69
- </div>
70
- {product.images.length > 1 && (
71
- <div className="grid grid-cols-4 gap-4">
72
- {product.images.map((image, i) => (
73
- <button
74
- key={i}
75
- onClick={() => setSelectedImage(i)}
76
- className={cn(
77
- 'aspect-square overflow-hidden rounded-lg border-2',
78
- selectedImage === i ? 'border-primary' : 'border-transparent'
79
- )}
80
- >
81
- <img
82
- src={image}
83
- alt=""
84
- className="h-full w-full object-cover"
85
- />
86
- </button>
87
- ))}
88
- </div>
89
- )}
90
- </div>
91
-
92
- {/* Product Info */}
93
- <div className="space-y-6">
94
- <div>
95
- {product.badge && (
96
- <Badge className="mb-2">{product.badge}</Badge>
97
- )}
98
- <h1 className="text-3xl font-bold">{product.name}</h1>
99
- {product.rating !== undefined && (
100
- <div className="mt-4 flex items-center gap-2">
101
- <div className="flex items-center gap-1">
102
- {Array.from({ length: 5 }).map((_, i) => (
103
- <Star
104
- key={i}
105
- className={cn(
106
- 'h-5 w-5',
107
- i < Math.floor(product.rating!)
108
- ? 'fill-primary text-primary'
109
- : 'text-muted-foreground'
110
- )}
111
- />
112
- ))}
113
- </div>
114
- <span className="font-medium">{product.rating.toFixed(1)}</span>
115
- {product.reviewCount !== undefined && (
116
- <span className="text-muted-foreground">
117
- ({product.reviewCount} reviews)
118
- </span>
119
- )}
120
- </div>
121
- )}
122
- </div>
123
-
124
- <div className="space-y-2">
125
- <div className="flex items-center gap-2">
126
- <span className="text-3xl font-bold">
127
- {formatPrice(product.price, product.currency)}
128
- </span>
129
- {product.originalPrice && product.originalPrice > product.price && (
130
- <>
131
- <span className="text-xl text-muted-foreground line-through">
132
- {formatPrice(product.originalPrice, product.currency)}
133
- </span>
134
- <Badge variant="destructive">
135
- -{calculateDiscount(product.price, product.originalPrice)}%
136
- </Badge>
137
- </>
138
- )}
139
- </div>
140
- {product.inStock === false && (
141
- <p className="text-sm text-destructive">Out of stock</p>
142
- )}
143
- </div>
144
-
145
- <p className="text-muted-foreground">{product.description}</p>
146
-
147
- {/* Variants */}
148
- {product.variants && product.variants.length > 0 && (
149
- <div className="space-y-2">
150
- <label className="text-sm font-medium">
151
- {product.variants[0].name}
152
- </label>
153
- <div className="flex flex-wrap gap-2">
154
- {product.variants.map((variant) => (
155
- <Button
156
- key={variant.id}
157
- variant={selectedVariant === variant.id ? 'default' : 'outline'}
158
- size="sm"
159
- onClick={() => setSelectedVariant(variant.id)}
160
- >
161
- {variant.value}
162
- </Button>
163
- ))}
164
- </div>
165
- </div>
166
- )}
167
-
168
- {/* Quantity and Actions */}
169
- <div className="space-y-4">
170
- <div className="flex items-center gap-4">
171
- <label className="text-sm font-medium">Quantity:</label>
172
- <div className="flex items-center gap-2">
173
- <Button
174
- size="icon"
175
- variant="outline"
176
- onClick={() => setQuantity(Math.max(1, quantity - 1))}
177
- disabled={quantity <= 1}
178
- >
179
- -
180
- </Button>
181
- <span className="w-12 text-center">{quantity}</span>
182
- <Button
183
- size="icon"
184
- variant="outline"
185
- onClick={() => setQuantity(quantity + 1)}
186
- >
187
- +
188
- </Button>
189
- </div>
190
- </div>
191
-
192
- <div className="flex gap-4">
193
- <Button
194
- className="flex-1"
195
- size="lg"
196
- disabled={product.inStock === false}
197
- onClick={() => onAddToCart?.(quantity, selectedVariant)}
198
- >
199
- <ShoppingCart className="mr-2 h-5 w-5" />
200
- Add to Cart
201
- </Button>
202
- <Button
203
- size="lg"
204
- variant="outline"
205
- onClick={onAddToWishlist}
206
- >
207
- <Heart className="h-5 w-5" />
208
- </Button>
209
- <Button
210
- size="lg"
211
- variant="outline"
212
- onClick={onShare}
213
- >
214
- <Share2 className="h-5 w-5" />
215
- </Button>
216
- </div>
217
- </div>
218
-
219
- {/* Tabs */}
220
- {(product.features || product.specifications) && (
221
- <Tabs defaultValue="features" className="w-full">
222
- <TabsList className="grid w-full grid-cols-2">
223
- {product.features && <TabsTrigger value="features">Features</TabsTrigger>}
224
- {product.specifications && (
225
- <TabsTrigger value="specifications">Specifications</TabsTrigger>
226
- )}
227
- </TabsList>
228
- {product.features && (
229
- <TabsContent value="features" className="space-y-2">
230
- <ul className="list-inside list-disc space-y-1">
231
- {product.features.map((feature, i) => (
232
- <li key={i} className="text-sm">
233
- {feature}
234
- </li>
235
- ))}
236
- </ul>
237
- </TabsContent>
238
- )}
239
- {product.specifications && (
240
- <TabsContent value="specifications">
241
- <dl className="space-y-2">
242
- {Object.entries(product.specifications).map(([key, value]) => (
243
- <div key={key} className="flex gap-4 text-sm">
244
- <dt className="min-w-[120px] font-medium">{key}:</dt>
245
- <dd className="text-muted-foreground">{value}</dd>
246
- </div>
247
- ))}
248
- </dl>
249
- </TabsContent>
250
- )}
251
- </Tabs>
252
- )}
253
- </div>
254
- </div>
255
- </div>
256
- )
257
- }
@@ -1,148 +0,0 @@
1
- 'use client'
2
-
3
- import { cn } from '@hanzo/ui/util'
4
- import { Button } from '@hanzo/ui/primitives'
5
- import { Card, CardContent, CardFooter } from '@hanzo/ui/primitives'
6
- import { Badge } from '@hanzo/ui/primitives'
7
- import { Star, ShoppingCart } from 'lucide-react'
8
-
9
- export interface Product {
10
- id: string | number
11
- name: string
12
- description?: string
13
- price: number
14
- originalPrice?: number
15
- currency?: string
16
- image: string
17
- rating?: number
18
- reviewCount?: number
19
- badge?: string
20
- inStock?: boolean
21
- }
22
-
23
- interface ProductGridProps extends React.ComponentPropsWithoutRef<'section'> {
24
- products: Product[]
25
- columns?: 2 | 3 | 4
26
- onAddToCart?: (product: Product) => void
27
- onProductClick?: (product: Product) => void
28
- }
29
-
30
- export function ProductGrid({
31
- className,
32
- products,
33
- columns = 4,
34
- onAddToCart,
35
- onProductClick,
36
- ...props
37
- }: ProductGridProps) {
38
- const gridCols = {
39
- 2: 'sm:grid-cols-2',
40
- 3: 'sm:grid-cols-2 lg:grid-cols-3',
41
- 4: 'sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
42
- }[columns]
43
-
44
- const formatPrice = (price: number, currency = '$') => {
45
- return `${currency}${price.toFixed(2)}`
46
- }
47
-
48
- const calculateDiscount = (price: number, originalPrice: number) => {
49
- return Math.round(((originalPrice - price) / originalPrice) * 100)
50
- }
51
-
52
- return (
53
- <section className={cn('py-8', className)} {...props}>
54
- <div className="container">
55
- <div className={cn('grid gap-6', gridCols)}>
56
- {products.map((product) => (
57
- <Card
58
- key={product.id}
59
- className="group relative overflow-hidden"
60
- >
61
- {product.badge && (
62
- <Badge className="absolute left-2 top-2 z-10">
63
- {product.badge}
64
- </Badge>
65
- )}
66
- {product.originalPrice && product.originalPrice > product.price && (
67
- <Badge
68
- variant="destructive"
69
- className="absolute right-2 top-2 z-10"
70
- >
71
- -{calculateDiscount(product.price, product.originalPrice)}%
72
- </Badge>
73
- )}
74
-
75
- <div
76
- className="aspect-square cursor-pointer overflow-hidden"
77
- onClick={() => onProductClick?.(product)}
78
- >
79
- <img
80
- src={product.image}
81
- alt={product.name}
82
- className="h-full w-full object-cover transition-transform group-hover:scale-105"
83
- />
84
- </div>
85
-
86
- <CardContent className="p-4">
87
- <h3
88
- className="cursor-pointer font-semibold hover:underline"
89
- onClick={() => onProductClick?.(product)}
90
- >
91
- {product.name}
92
- </h3>
93
-
94
- {product.description && (
95
- <p className="mt-1 line-clamp-2 text-sm text-muted-foreground">
96
- {product.description}
97
- </p>
98
- )}
99
-
100
- {product.rating !== undefined && (
101
- <div className="mt-2 flex items-center gap-2">
102
- <div className="flex items-center gap-1">
103
- <Star className="h-4 w-4 fill-primary text-primary" />
104
- <span className="text-sm font-medium">
105
- {product.rating.toFixed(1)}
106
- </span>
107
- </div>
108
- {product.reviewCount !== undefined && (
109
- <span className="text-sm text-muted-foreground">
110
- ({product.reviewCount})
111
- </span>
112
- )}
113
- </div>
114
- )}
115
-
116
- <div className="mt-3 flex items-center gap-2">
117
- <span className="text-lg font-bold">
118
- {formatPrice(product.price, product.currency)}
119
- </span>
120
- {product.originalPrice && product.originalPrice > product.price && (
121
- <span className="text-sm text-muted-foreground line-through">
122
- {formatPrice(product.originalPrice, product.currency)}
123
- </span>
124
- )}
125
- </div>
126
-
127
- {product.inStock === false && (
128
- <p className="mt-2 text-sm text-destructive">Out of stock</p>
129
- )}
130
- </CardContent>
131
-
132
- <CardFooter className="p-4 pt-0">
133
- <Button
134
- className="w-full"
135
- disabled={product.inStock === false}
136
- onClick={() => onAddToCart?.(product)}
137
- >
138
- <ShoppingCart className="mr-2 h-4 w-4" />
139
- Add to cart
140
- </Button>
141
- </CardFooter>
142
- </Card>
143
- ))}
144
- </div>
145
- </div>
146
- </section>
147
- )
148
- }