@reinvented/design 0.3.0 → 1.0.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 (348) hide show
  1. package/package.json +55 -21
  2. package/src/components/blocks/auth/auth-card/AuthCard.tsx +62 -0
  3. package/src/components/blocks/auth/auth-card/index.ts +1 -0
  4. package/src/components/blocks/auth/index.ts +3 -0
  5. package/src/components/blocks/auth/social-login/SocialLoginGroup.tsx +75 -0
  6. package/src/components/blocks/auth/social-login/index.ts +1 -0
  7. package/src/components/blocks/auth/two-factor/TwoFactorForm.tsx +59 -0
  8. package/src/components/blocks/auth/two-factor/index.ts +1 -0
  9. package/src/components/blocks/communication/activity-item/ActivityItem.tsx +17 -0
  10. package/src/components/blocks/communication/activity-item/ActivityItemAvatar.tsx +21 -0
  11. package/src/components/blocks/communication/activity-item/ActivityItemContent.tsx +16 -0
  12. package/src/components/blocks/communication/activity-item/index.ts +3 -0
  13. package/src/components/blocks/communication/chat-bubble/ChatBubble.tsx +21 -0
  14. package/src/components/blocks/communication/chat-bubble/ChatBubbleAvatar.tsx +19 -0
  15. package/src/components/blocks/communication/chat-bubble/ChatBubbleMessage.tsx +35 -0
  16. package/src/components/blocks/communication/chat-bubble/ChatBubbleTimestamp.tsx +15 -0
  17. package/src/components/blocks/communication/chat-bubble/index.ts +4 -0
  18. package/src/components/blocks/communication/index.ts +2 -0
  19. package/src/components/blocks/content/article-header/ArticleHeader.tsx +73 -0
  20. package/src/components/blocks/content/article-header/index.ts +1 -0
  21. package/src/components/blocks/content/author-card/AuthorCard.tsx +46 -0
  22. package/src/components/blocks/content/author-card/index.ts +1 -0
  23. package/src/components/blocks/content/index.ts +3 -0
  24. package/src/components/blocks/content/rich-text/RichTextContent.tsx +27 -0
  25. package/src/components/blocks/content/rich-text/index.ts +1 -0
  26. package/src/components/blocks/data-management/index.ts +2 -0
  27. package/src/components/blocks/data-management/kanban/KanbanBoard.tsx +10 -0
  28. package/src/components/blocks/data-management/kanban/KanbanCard.tsx +102 -0
  29. package/src/components/blocks/data-management/kanban/KanbanColumn.tsx +41 -0
  30. package/src/components/blocks/data-management/kanban/index.ts +3 -0
  31. package/src/components/blocks/data-management/tree-view/TreeItem.tsx +68 -0
  32. package/src/components/blocks/data-management/tree-view/TreeView.tsx +10 -0
  33. package/src/components/blocks/data-management/tree-view/index.ts +2 -0
  34. package/src/components/blocks/data-viz/financial-ticker/FinancialTicker.tsx +35 -0
  35. package/src/components/blocks/data-viz/financial-ticker/index.ts +1 -0
  36. package/src/components/blocks/data-viz/index.ts +3 -0
  37. package/src/components/blocks/data-viz/kpi-card/KpiCard.tsx +61 -0
  38. package/src/components/blocks/data-viz/kpi-card/index.ts +1 -0
  39. package/src/components/blocks/data-viz/stat-grid/StatGrid.tsx +28 -0
  40. package/src/components/blocks/data-viz/stat-grid/index.ts +1 -0
  41. package/src/components/blocks/ecommerce/index.ts +3 -0
  42. package/src/components/blocks/ecommerce/pricing-tier/PricingFeatureList.tsx +27 -0
  43. package/src/components/blocks/ecommerce/pricing-tier/PricingHeader.tsx +25 -0
  44. package/src/components/blocks/ecommerce/pricing-tier/PricingTier.tsx +31 -0
  45. package/src/components/blocks/ecommerce/pricing-tier/index.ts +3 -0
  46. package/src/components/blocks/ecommerce/product-card/ProductCard.tsx +17 -0
  47. package/src/components/blocks/ecommerce/product-card/ProductCardContent.tsx +15 -0
  48. package/src/components/blocks/ecommerce/product-card/ProductCardImage.tsx +20 -0
  49. package/src/components/blocks/ecommerce/product-card/ProductCardPrice.tsx +20 -0
  50. package/src/components/blocks/ecommerce/product-card/index.ts +4 -0
  51. package/src/components/blocks/ecommerce/rating-summary/RatingStars.tsx +32 -0
  52. package/src/components/blocks/ecommerce/rating-summary/index.ts +1 -0
  53. package/src/components/blocks/feedback/empty-state/EmptyState.tsx +53 -0
  54. package/src/components/blocks/feedback/empty-state/index.ts +1 -0
  55. package/src/components/blocks/feedback/error-state/ErrorState.tsx +50 -0
  56. package/src/components/blocks/feedback/error-state/index.ts +1 -0
  57. package/src/components/blocks/feedback/index.ts +3 -0
  58. package/src/components/blocks/feedback/not-found/NotFoundState.tsx +47 -0
  59. package/src/components/blocks/feedback/not-found/index.ts +1 -0
  60. package/src/components/blocks/filtering/faceted-sidebar/FacetedGroup.tsx +32 -0
  61. package/src/components/blocks/filtering/faceted-sidebar/FacetedSidebar.tsx +26 -0
  62. package/src/components/blocks/filtering/faceted-sidebar/index.ts +2 -0
  63. package/src/components/blocks/filtering/filter-bar/FilterBar.tsx +85 -0
  64. package/src/components/blocks/filtering/filter-bar/index.ts +1 -0
  65. package/src/components/blocks/filtering/index.ts +3 -0
  66. package/src/components/blocks/filtering/search-result/SearchResultItem.tsx +70 -0
  67. package/src/components/blocks/filtering/search-result/index.ts +1 -0
  68. package/src/components/blocks/index.ts +21 -0
  69. package/src/components/blocks/marketing/cta-block/CtaBlock.tsx +80 -0
  70. package/src/components/blocks/marketing/cta-block/index.ts +1 -0
  71. package/src/components/blocks/marketing/feature-grid/FeatureGrid.tsx +47 -0
  72. package/src/components/blocks/marketing/feature-grid/index.ts +1 -0
  73. package/src/components/blocks/marketing/hero-section/HeroSection.tsx +89 -0
  74. package/src/components/blocks/marketing/hero-section/index.ts +1 -0
  75. package/src/components/blocks/marketing/index.ts +4 -0
  76. package/src/components/blocks/marketing/testimonial-card/TestimonialCard.tsx +71 -0
  77. package/src/components/blocks/marketing/testimonial-card/index.ts +1 -0
  78. package/src/components/blocks/media/call-controls/CallControlButton.tsx +52 -0
  79. package/src/components/blocks/media/call-controls/CallControls.tsx +10 -0
  80. package/src/components/blocks/media/call-controls/index.ts +2 -0
  81. package/src/components/blocks/media/index.ts +2 -0
  82. package/src/components/blocks/media/media-player/MediaPlayer.tsx +20 -0
  83. package/src/components/blocks/media/media-player/MediaPlayerControls.tsx +16 -0
  84. package/src/components/blocks/media/media-player/MediaPlayerScrubber.tsx +29 -0
  85. package/src/components/blocks/media/media-player/MediaPlayerVideo.tsx +25 -0
  86. package/src/components/blocks/media/media-player/index.ts +4 -0
  87. package/src/components/blocks/navigation/app-sidebar/AppSidebar.tsx +32 -0
  88. package/src/components/blocks/navigation/app-sidebar/NavItem.tsx +43 -0
  89. package/src/components/blocks/navigation/app-sidebar/index.ts +2 -0
  90. package/src/components/blocks/navigation/context-switcher/ContextSwitcher.tsx +77 -0
  91. package/src/components/blocks/navigation/context-switcher/index.ts +1 -0
  92. package/src/components/blocks/navigation/index.ts +3 -0
  93. package/src/components/blocks/navigation/top-navbar/TopNavbar.tsx +47 -0
  94. package/src/components/blocks/navigation/top-navbar/index.ts +1 -0
  95. package/src/components/blocks/onboarding/index.ts +2 -0
  96. package/src/components/blocks/onboarding/onboarding-welcome/OnboardingWelcome.tsx +74 -0
  97. package/src/components/blocks/onboarding/onboarding-welcome/index.ts +1 -0
  98. package/src/components/blocks/onboarding/step-wizard/StepWizard.tsx +72 -0
  99. package/src/components/blocks/onboarding/step-wizard/index.ts +1 -0
  100. package/src/components/blocks/profiles/connection-list/ConnectionItem.tsx +35 -0
  101. package/src/components/blocks/profiles/connection-list/ConnectionList.tsx +16 -0
  102. package/src/components/blocks/profiles/connection-list/index.ts +2 -0
  103. package/src/components/blocks/profiles/index.ts +3 -0
  104. package/src/components/blocks/profiles/profile-header/ProfileHeader.tsx +88 -0
  105. package/src/components/blocks/profiles/profile-header/index.ts +1 -0
  106. package/src/components/blocks/profiles/profile-stats/ProfileStats.tsx +20 -0
  107. package/src/components/blocks/profiles/profile-stats/index.ts +1 -0
  108. package/src/components/blocks/scheduling/booking-slot/BookingSlot.tsx +44 -0
  109. package/src/components/blocks/scheduling/booking-slot/index.ts +1 -0
  110. package/src/components/blocks/scheduling/event-card/EventCard.tsx +85 -0
  111. package/src/components/blocks/scheduling/event-card/index.ts +1 -0
  112. package/src/components/blocks/scheduling/index.ts +3 -0
  113. package/src/components/blocks/scheduling/timeline-row/TimelineRow.tsx +82 -0
  114. package/src/components/blocks/scheduling/timeline-row/index.ts +1 -0
  115. package/src/components/blocks/settings/billing-usage/BillingUsage.tsx +49 -0
  116. package/src/components/blocks/settings/billing-usage/index.ts +1 -0
  117. package/src/components/blocks/settings/index.ts +3 -0
  118. package/src/components/blocks/settings/integration-card/IntegrationCard.tsx +62 -0
  119. package/src/components/blocks/settings/integration-card/index.ts +1 -0
  120. package/src/components/blocks/settings/settings-section/SettingsSection.tsx +23 -0
  121. package/src/components/blocks/settings/settings-section/index.ts +1 -0
  122. package/src/components/ui/accordion.tsx +56 -0
  123. package/src/components/ui/alert-dialog.tsx +141 -0
  124. package/src/components/ui/alert.tsx +59 -0
  125. package/src/components/ui/aspect-ratio.tsx +5 -0
  126. package/src/components/ui/avatar.tsx +50 -0
  127. package/src/components/ui/badge.tsx +36 -0
  128. package/src/components/ui/breadcrumb.tsx +115 -0
  129. package/src/components/ui/button.tsx +56 -0
  130. package/src/components/ui/calendar.tsx +211 -0
  131. package/src/components/ui/card.tsx +79 -0
  132. package/src/components/ui/carousel.tsx +262 -0
  133. package/src/components/ui/chart.tsx +367 -0
  134. package/src/components/ui/checkbox.tsx +28 -0
  135. package/src/components/ui/collapsible.tsx +11 -0
  136. package/src/components/ui/command.tsx +153 -0
  137. package/src/components/ui/component-placeholder.tsx +38 -0
  138. package/src/components/ui/context-menu.tsx +198 -0
  139. package/src/components/ui/dialog.tsx +122 -0
  140. package/src/components/ui/drawer.tsx +116 -0
  141. package/src/components/ui/dropdown-menu.tsx +200 -0
  142. package/src/components/ui/form.tsx +176 -0
  143. package/src/components/ui/hover-card.tsx +27 -0
  144. package/src/components/ui/input-otp.tsx +69 -0
  145. package/src/components/ui/input.tsx +22 -0
  146. package/src/components/ui/label.tsx +24 -0
  147. package/src/components/ui/menubar.tsx +256 -0
  148. package/src/components/ui/navigation-menu.tsx +128 -0
  149. package/src/components/ui/pagination.tsx +117 -0
  150. package/src/components/ui/popover.tsx +29 -0
  151. package/src/components/ui/progress.tsx +28 -0
  152. package/src/components/ui/radio-group.tsx +42 -0
  153. package/src/components/ui/resizable.tsx +45 -0
  154. package/src/components/ui/scroll-area.tsx +46 -0
  155. package/src/components/ui/select.tsx +160 -0
  156. package/src/components/ui/separator.tsx +29 -0
  157. package/src/components/ui/sheet.tsx +140 -0
  158. package/src/components/ui/skeleton.tsx +15 -0
  159. package/src/components/ui/slider.tsx +26 -0
  160. package/src/components/ui/sonner.tsx +45 -0
  161. package/src/components/ui/switch.tsx +27 -0
  162. package/src/components/ui/table.tsx +117 -0
  163. package/src/components/ui/tabs.tsx +53 -0
  164. package/src/components/ui/textarea.tsx +22 -0
  165. package/src/components/ui/toast.tsx +127 -0
  166. package/src/components/ui/toaster.tsx +33 -0
  167. package/src/components/ui/toggle-group.tsx +61 -0
  168. package/src/components/ui/toggle.tsx +45 -0
  169. package/src/components/ui/tooltip.tsx +28 -0
  170. package/src/hooks/use-toast.ts +194 -0
  171. package/src/index.ts +53 -56
  172. package/src/styles/index.css +6 -0
  173. package/src/styles/tokens.css +30 -18
  174. package/tailwind.config.js +120 -98
  175. package/tsconfig.json +2 -2
  176. package/src/components/ui/accordion/Accordion.vue +0 -13
  177. package/src/components/ui/accordion/AccordionContent.vue +0 -20
  178. package/src/components/ui/accordion/AccordionItem.vue +0 -15
  179. package/src/components/ui/accordion/AccordionTrigger.vue +0 -25
  180. package/src/components/ui/accordion/index.ts +0 -4
  181. package/src/components/ui/alert/Alert.vue +0 -38
  182. package/src/components/ui/alert/AlertDescription.vue +0 -12
  183. package/src/components/ui/alert/AlertTitle.vue +0 -12
  184. package/src/components/ui/alert/index.ts +0 -3
  185. package/src/components/ui/alert-dialog/AlertDialog.vue +0 -13
  186. package/src/components/ui/alert-dialog/AlertDialogAction.vue +0 -21
  187. package/src/components/ui/alert-dialog/AlertDialogCancel.vue +0 -21
  188. package/src/components/ui/alert-dialog/AlertDialogContent.vue +0 -39
  189. package/src/components/ui/alert-dialog/AlertDialogDescription.vue +0 -15
  190. package/src/components/ui/alert-dialog/AlertDialogFooter.vue +0 -12
  191. package/src/components/ui/alert-dialog/AlertDialogHeader.vue +0 -12
  192. package/src/components/ui/alert-dialog/AlertDialogTitle.vue +0 -15
  193. package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +0 -11
  194. package/src/components/ui/alert-dialog/index.ts +0 -9
  195. package/src/components/ui/avatar/Avatar.vue +0 -14
  196. package/src/components/ui/avatar/index.ts +0 -1
  197. package/src/components/ui/badge/Badge.vue +0 -27
  198. package/src/components/ui/badge/index.ts +0 -1
  199. package/src/components/ui/breadcrumb/Breadcrumb.vue +0 -6
  200. package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +0 -12
  201. package/src/components/ui/breadcrumb/BreadcrumbItem.vue +0 -6
  202. package/src/components/ui/breadcrumb/BreadcrumbLink.vue +0 -20
  203. package/src/components/ui/breadcrumb/BreadcrumbList.vue +0 -6
  204. package/src/components/ui/breadcrumb/BreadcrumbPage.vue +0 -6
  205. package/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +0 -11
  206. package/src/components/ui/breadcrumb/index.ts +0 -7
  207. package/src/components/ui/button/Button.vue +0 -65
  208. package/src/components/ui/button/index.ts +0 -1
  209. package/src/components/ui/card/Card.vue +0 -13
  210. package/src/components/ui/card/CardContent.vue +0 -7
  211. package/src/components/ui/card/CardDescription.vue +0 -7
  212. package/src/components/ui/card/CardFooter.vue +0 -7
  213. package/src/components/ui/card/CardHeader.vue +0 -9
  214. package/src/components/ui/card/CardTitle.vue +0 -7
  215. package/src/components/ui/card/index.ts +0 -6
  216. package/src/components/ui/checkbox/Checkbox.vue +0 -25
  217. package/src/components/ui/checkbox/index.ts +0 -1
  218. package/src/components/ui/collapsible/Collapsible.vue +0 -13
  219. package/src/components/ui/collapsible/index.ts +0 -2
  220. package/src/components/ui/command/Command.vue +0 -16
  221. package/src/components/ui/command/CommandEmpty.vue +0 -5
  222. package/src/components/ui/command/CommandGroup.vue +0 -22
  223. package/src/components/ui/command/CommandInput.vue +0 -21
  224. package/src/components/ui/command/CommandItem.vue +0 -22
  225. package/src/components/ui/command/CommandList.vue +0 -17
  226. package/src/components/ui/command/CommandSeparator.vue +0 -5
  227. package/src/components/ui/command/index.ts +0 -7
  228. package/src/components/ui/context-menu/ContextMenuContent.vue +0 -24
  229. package/src/components/ui/context-menu/ContextMenuItem.vue +0 -16
  230. package/src/components/ui/context-menu/ContextMenuLabel.vue +0 -9
  231. package/src/components/ui/context-menu/ContextMenuSeparator.vue +0 -9
  232. package/src/components/ui/context-menu/ContextMenuSubContent.vue +0 -14
  233. package/src/components/ui/context-menu/index.ts +0 -9
  234. package/src/components/ui/dialog/Dialog.vue +0 -14
  235. package/src/components/ui/dialog/DialogClose.vue +0 -12
  236. package/src/components/ui/dialog/DialogContent.vue +0 -48
  237. package/src/components/ui/dialog/DialogDescription.vue +0 -23
  238. package/src/components/ui/dialog/DialogFooter.vue +0 -12
  239. package/src/components/ui/dialog/DialogHeader.vue +0 -12
  240. package/src/components/ui/dialog/DialogScrollContent.vue +0 -47
  241. package/src/components/ui/dialog/DialogTitle.vue +0 -23
  242. package/src/components/ui/dialog/DialogTrigger.vue +0 -12
  243. package/src/components/ui/dialog/index.ts +0 -9
  244. package/src/components/ui/dropdown-menu/DropdownMenu.vue +0 -13
  245. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +0 -28
  246. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +0 -33
  247. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +0 -11
  248. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +0 -27
  249. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +0 -23
  250. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +0 -13
  251. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +0 -27
  252. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +0 -13
  253. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +0 -12
  254. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +0 -13
  255. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +0 -27
  256. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +0 -23
  257. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +0 -11
  258. package/src/components/ui/dropdown-menu/index.ts +0 -14
  259. package/src/components/ui/form/FormControl.vue +0 -3
  260. package/src/components/ui/form/FormDescription.vue +0 -6
  261. package/src/components/ui/form/FormItem.vue +0 -6
  262. package/src/components/ui/form/FormLabel.vue +0 -10
  263. package/src/components/ui/form/FormMessage.vue +0 -10
  264. package/src/components/ui/form/index.ts +0 -9
  265. package/src/components/ui/hover-card/HoverCard.vue +0 -13
  266. package/src/components/ui/hover-card/HoverCardContent.vue +0 -26
  267. package/src/components/ui/hover-card/HoverCardTrigger.vue +0 -11
  268. package/src/components/ui/hover-card/index.ts +0 -3
  269. package/src/components/ui/input/Input.vue +0 -23
  270. package/src/components/ui/input/index.ts +0 -1
  271. package/src/components/ui/label/Label.vue +0 -18
  272. package/src/components/ui/label/index.ts +0 -1
  273. package/src/components/ui/lib/utils.ts +0 -2
  274. package/src/components/ui/menubar/MenubarContent.vue +0 -15
  275. package/src/components/ui/menubar/MenubarItem.vue +0 -13
  276. package/src/components/ui/menubar/MenubarTrigger.vue +0 -13
  277. package/src/components/ui/menubar/index.ts +0 -5
  278. package/src/components/ui/navigation-menu/NavigationMenuContent.vue +0 -14
  279. package/src/components/ui/navigation-menu/NavigationMenuTrigger.vue +0 -15
  280. package/src/components/ui/navigation-menu/index.ts +0 -4
  281. package/src/components/ui/pagination/PaginationContent.vue +0 -13
  282. package/src/components/ui/pagination/PaginationEllipsis.vue +0 -12
  283. package/src/components/ui/pagination/PaginationNext.vue +0 -14
  284. package/src/components/ui/pagination/PaginationPrev.vue +0 -14
  285. package/src/components/ui/pagination/index.ts +0 -6
  286. package/src/components/ui/popover/Popover.vue +0 -13
  287. package/src/components/ui/popover/PopoverContent.vue +0 -27
  288. package/src/components/ui/popover/PopoverTrigger.vue +0 -11
  289. package/src/components/ui/popover/index.ts +0 -3
  290. package/src/components/ui/progress/Progress.vue +0 -21
  291. package/src/components/ui/progress/index.ts +0 -1
  292. package/src/components/ui/radio-group/RadioGroup.vue +0 -16
  293. package/src/components/ui/radio-group/RadioGroupItem.vue +0 -24
  294. package/src/components/ui/radio-group/index.ts +0 -2
  295. package/src/components/ui/scroll-area/ScrollArea.vue +0 -13
  296. package/src/components/ui/scroll-area/index.ts +0 -1
  297. package/src/components/ui/select/Select.vue +0 -13
  298. package/src/components/ui/select/SelectContent.vue +0 -40
  299. package/src/components/ui/select/SelectGroup.vue +0 -15
  300. package/src/components/ui/select/SelectItem.vue +0 -30
  301. package/src/components/ui/select/SelectLabel.vue +0 -15
  302. package/src/components/ui/select/SelectSeparator.vue +0 -13
  303. package/src/components/ui/select/SelectTrigger.vue +0 -23
  304. package/src/components/ui/select/SelectValue.vue +0 -11
  305. package/src/components/ui/select/index.ts +0 -8
  306. package/src/components/ui/separator/Separator.vue +0 -16
  307. package/src/components/ui/separator/index.ts +0 -1
  308. package/src/components/ui/sheet/Sheet.vue +0 -13
  309. package/src/components/ui/sheet/SheetClose.vue +0 -11
  310. package/src/components/ui/sheet/SheetContent.vue +0 -65
  311. package/src/components/ui/sheet/SheetDescription.vue +0 -15
  312. package/src/components/ui/sheet/SheetFooter.vue +0 -12
  313. package/src/components/ui/sheet/SheetHeader.vue +0 -12
  314. package/src/components/ui/sheet/SheetTitle.vue +0 -15
  315. package/src/components/ui/sheet/SheetTrigger.vue +0 -11
  316. package/src/components/ui/sheet/index.ts +0 -8
  317. package/src/components/ui/skeleton/Skeleton.vue +0 -9
  318. package/src/components/ui/skeleton/index.ts +0 -1
  319. package/src/components/ui/slider/Slider.vue +0 -26
  320. package/src/components/ui/slider/index.ts +0 -1
  321. package/src/components/ui/switch/Switch.vue +0 -24
  322. package/src/components/ui/switch/index.ts +0 -1
  323. package/src/components/ui/table/Table.vue +0 -13
  324. package/src/components/ui/table/TableBody.vue +0 -6
  325. package/src/components/ui/table/TableCaption.vue +0 -6
  326. package/src/components/ui/table/TableCell.vue +0 -6
  327. package/src/components/ui/table/TableFooter.vue +0 -6
  328. package/src/components/ui/table/TableHead.vue +0 -6
  329. package/src/components/ui/table/TableHeader.vue +0 -6
  330. package/src/components/ui/table/TableRow.vue +0 -6
  331. package/src/components/ui/table/index.ts +0 -8
  332. package/src/components/ui/tabs/Tabs.vue +0 -13
  333. package/src/components/ui/tabs/TabsContent.vue +0 -21
  334. package/src/components/ui/tabs/TabsList.vue +0 -21
  335. package/src/components/ui/tabs/TabsTrigger.vue +0 -21
  336. package/src/components/ui/tabs/index.ts +0 -4
  337. package/src/components/ui/textarea/Textarea.vue +0 -29
  338. package/src/components/ui/textarea/index.ts +0 -1
  339. package/src/components/ui/toggle/Toggle.vue +0 -40
  340. package/src/components/ui/toggle/index.ts +0 -1
  341. package/src/components/ui/toggle-group/ToggleGroup.vue +0 -16
  342. package/src/components/ui/toggle-group/ToggleGroupItem.vue +0 -21
  343. package/src/components/ui/toggle-group/index.ts +0 -2
  344. package/src/components/ui/tooltip/Tooltip.vue +0 -13
  345. package/src/components/ui/tooltip/TooltipContent.vue +0 -27
  346. package/src/components/ui/tooltip/TooltipProvider.vue +0 -12
  347. package/src/components/ui/tooltip/TooltipTrigger.vue +0 -11
  348. package/src/components/ui/tooltip/index.ts +0 -4
@@ -0,0 +1,50 @@
1
+ import React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+ import { Button } from '@/components/ui/button'
4
+ import { AlertTriangle, RefreshCcw } from 'lucide-react'
5
+
6
+ interface ErrorStateProps {
7
+ title?: string
8
+ description?: string
9
+ retryLabel?: string
10
+ className?: string
11
+ onRetry?: () => void
12
+ }
13
+
14
+ export function ErrorState({
15
+ title,
16
+ description,
17
+ retryLabel,
18
+ className,
19
+ onRetry,
20
+ }: ErrorStateProps) {
21
+ return (
22
+ <div
23
+ className={cn(
24
+ 'flex flex-col items-center justify-center py-12 px-6 text-center bg-rose-500/5 border border-rose-500/20 rounded-xl',
25
+ className,
26
+ )}
27
+ >
28
+ <div className="h-12 w-12 rounded-full bg-rose-500/10 flex items-center justify-center mb-4 text-rose-500">
29
+ <AlertTriangle className="h-6 w-6" />
30
+ </div>
31
+
32
+ <h3 className="text-lg font-semibold text-foreground mb-1">
33
+ {title || 'Something went wrong'}
34
+ </h3>
35
+ <p className="text-sm text-muted-foreground max-w-md mx-auto mb-6">
36
+ {description ||
37
+ 'An unexpected error occurred while trying to load this content. Please try again later.'}
38
+ </p>
39
+
40
+ <Button
41
+ variant="outline"
42
+ onClick={onRetry}
43
+ className="border-rose-500/20 hover:bg-rose-500/10 hover:text-rose-600 text-rose-600"
44
+ >
45
+ <RefreshCcw className="mr-2 h-4 w-4" />
46
+ {retryLabel || 'Try again'}
47
+ </Button>
48
+ </div>
49
+ )
50
+ }
@@ -0,0 +1 @@
1
+ export * from './ErrorState'
@@ -0,0 +1,3 @@
1
+ export * from './empty-state'
2
+ export * from './error-state'
3
+ export * from './not-found'
@@ -0,0 +1,47 @@
1
+ import React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+ import { Button } from '@/components/ui/button'
4
+ import { Search, Home, ArrowLeft } from 'lucide-react'
5
+
6
+ interface NotFoundStateProps {
7
+ title?: string
8
+ description?: string
9
+ className?: string
10
+ onBack?: () => void
11
+ onHome?: () => void
12
+ }
13
+
14
+ export function NotFoundState({
15
+ title,
16
+ description,
17
+ className,
18
+ onBack,
19
+ onHome,
20
+ }: NotFoundStateProps) {
21
+ return (
22
+ <div className={cn('flex flex-col items-center justify-center py-20 px-6 text-center', className)}>
23
+ <div className="relative mb-6">
24
+ <h1 className="text-7xl sm:text-9xl font-extrabold tracking-tighter text-muted select-none">404</h1>
25
+ <div className="absolute inset-0 flex items-center justify-center">
26
+ <Search className="h-10 w-10 sm:h-12 sm:w-12 text-muted-foreground/50" />
27
+ </div>
28
+ </div>
29
+
30
+ <h3 className="text-2xl font-bold text-foreground mb-2">{title || 'Page not found'}</h3>
31
+ <p className="text-base text-muted-foreground max-w-md mx-auto mb-8">
32
+ {description || "Sorry, we couldn't find the page you're looking for. It might have been moved or deleted."}
33
+ </p>
34
+
35
+ <div className="flex items-center gap-3">
36
+ <Button variant="outline" onClick={onBack}>
37
+ <ArrowLeft className="mr-2 h-4 w-4" />
38
+ Go back
39
+ </Button>
40
+ <Button onClick={onHome}>
41
+ <Home className="mr-2 h-4 w-4" />
42
+ Back to home
43
+ </Button>
44
+ </div>
45
+ </div>
46
+ )
47
+ }
@@ -0,0 +1 @@
1
+ export * from './NotFoundState'
@@ -0,0 +1,32 @@
1
+ import React, { useState } from 'react'
2
+ import { cn } from '@/lib/utils'
3
+ import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@/components/ui/collapsible'
4
+ import { ChevronDown } from 'lucide-react'
5
+
6
+ interface FacetedGroupProps {
7
+ title: string
8
+ defaultExpanded?: boolean
9
+ className?: string
10
+ children?: React.ReactNode
11
+ }
12
+
13
+ export function FacetedGroup({ title, defaultExpanded = true, className, children }: FacetedGroupProps) {
14
+ const [isOpen, setIsOpen] = useState(defaultExpanded)
15
+
16
+ return (
17
+ <Collapsible open={isOpen} onOpenChange={setIsOpen} className={cn('w-full', className)}>
18
+ <CollapsibleTrigger className="flex items-center justify-between w-full py-2 hover:bg-muted/50 rounded-md transition-colors group">
19
+ <h4 className="text-sm font-semibold tracking-tight">{title}</h4>
20
+ <ChevronDown
21
+ className={cn(
22
+ 'h-4 w-4 text-muted-foreground transition-transform duration-200',
23
+ isOpen ? 'rotate-180' : 'rotate-0'
24
+ )}
25
+ />
26
+ </CollapsibleTrigger>
27
+ <CollapsibleContent className="pt-3 pb-1 space-y-3">
28
+ {children}
29
+ </CollapsibleContent>
30
+ </Collapsible>
31
+ )
32
+ }
@@ -0,0 +1,26 @@
1
+ import React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+ import { ScrollArea } from '@/components/ui/scroll-area'
4
+
5
+ interface FacetedSidebarProps {
6
+ title?: string
7
+ className?: string
8
+ children?: React.ReactNode
9
+ }
10
+
11
+ export function FacetedSidebar({ title, className, children }: FacetedSidebarProps) {
12
+ return (
13
+ <div className={cn('w-full md:w-64 shrink-0 flex flex-col pt-1', className)}>
14
+ {title && (
15
+ <div className="mb-4">
16
+ <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">{title}</h3>
17
+ </div>
18
+ )}
19
+ <ScrollArea className="h-[calc(100vh-12rem)] pr-4">
20
+ <div className="flex flex-col gap-6 pb-6 w-full">
21
+ {children}
22
+ </div>
23
+ </ScrollArea>
24
+ </div>
25
+ )
26
+ }
@@ -0,0 +1,2 @@
1
+ export * from './FacetedSidebar'
2
+ export * from './FacetedGroup'
@@ -0,0 +1,85 @@
1
+ import React from 'react'
2
+ import { Input } from '@/components/ui/input'
3
+ import { Button } from '@/components/ui/button'
4
+ import { Badge } from '@/components/ui/badge'
5
+ import { Search, Filter, X } from 'lucide-react'
6
+ import { cn } from '@/lib/utils'
7
+
8
+ interface FilterBarProps {
9
+ placeholder?: string
10
+ activeFilters?: { key: string; label: string }[]
11
+ resultsCount?: number
12
+ className?: string
13
+ controls?: React.ReactNode
14
+ onRemoveFilter?: (filter: { key: string; label: string }) => void
15
+ onClearFilters?: () => void
16
+ }
17
+
18
+ export function FilterBar({
19
+ placeholder,
20
+ activeFilters,
21
+ resultsCount,
22
+ className,
23
+ controls,
24
+ onRemoveFilter,
25
+ onClearFilters,
26
+ }: FilterBarProps) {
27
+ return (
28
+ <div className={cn('flex flex-col gap-4 w-full', className)}>
29
+ <div className="flex flex-col sm:flex-row items-center gap-3">
30
+ <div className="relative w-full flex-1">
31
+ <Search className="absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
32
+ <Input
33
+ placeholder={placeholder || 'Search...'}
34
+ className="w-full pl-9 bg-background border-muted-foreground/20 shadow-sm"
35
+ />
36
+ </div>
37
+ <div className="flex items-center gap-2 w-full sm:w-auto">
38
+ {controls !== undefined ? (
39
+ controls
40
+ ) : (
41
+ <Button variant="outline" className="w-full sm:w-auto shadow-sm">
42
+ <Filter className="mr-2 h-4 w-4" />
43
+ Filters
44
+ </Button>
45
+ )}
46
+ </div>
47
+ </div>
48
+
49
+ {activeFilters && activeFilters.length > 0 && (
50
+ <div className="flex items-center flex-wrap gap-2 text-sm">
51
+ <span className="text-muted-foreground mr-1 text-xs font-medium">Active filters:</span>
52
+ {activeFilters.map((filter) => (
53
+ <Badge
54
+ key={filter.key}
55
+ variant="secondary"
56
+ className="gap-1 pr-1 font-normal bg-primary/10 text-primary hover:bg-primary/20 border-transparent"
57
+ >
58
+ {filter.label}
59
+ <div
60
+ className="h-3.5 w-3.5 rounded-full hover:bg-primary/30 flex items-center justify-center cursor-pointer transition-colors"
61
+ onClick={() => onRemoveFilter?.(filter)}
62
+ >
63
+ <X className="h-2.5 w-2.5" />
64
+ </div>
65
+ </Badge>
66
+ ))}
67
+ <Button
68
+ variant="ghost"
69
+ size="sm"
70
+ className="h-6 px-2 text-xs text-muted-foreground hover:text-foreground hover:bg-muted/50"
71
+ onClick={() => onClearFilters?.()}
72
+ >
73
+ Clear all
74
+ </Button>
75
+ </div>
76
+ )}
77
+
78
+ {resultsCount !== undefined && (
79
+ <div className="text-xs text-muted-foreground">
80
+ Showing <span className="font-medium text-foreground">{resultsCount}</span> results
81
+ </div>
82
+ )}
83
+ </div>
84
+ )
85
+ }
@@ -0,0 +1 @@
1
+ export * from './FilterBar'
@@ -0,0 +1,3 @@
1
+ export * from './filter-bar'
2
+ export * from './faceted-sidebar'
3
+ export * from './search-result'
@@ -0,0 +1,70 @@
1
+ import React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+ import { Badge } from '@/components/ui/badge'
4
+
5
+ interface SearchResultItemProps {
6
+ title: string
7
+ subtitle?: string
8
+ description?: string
9
+ tag?: string
10
+ url?: string
11
+ image?: string
12
+ className?: string
13
+ meta?: React.ReactNode
14
+ }
15
+
16
+ export function SearchResultItem({
17
+ title,
18
+ subtitle,
19
+ description,
20
+ tag,
21
+ url,
22
+ image,
23
+ className,
24
+ meta,
25
+ }: SearchResultItemProps) {
26
+ return (
27
+ <div className={cn('flex py-4 md:py-5 border-b last:border-0 group', className)}>
28
+ {image && (
29
+ <div className="shrink-0 mr-4 md:mr-6 h-20 w-20 sm:h-24 sm:w-24 border rounded-md overflow-hidden bg-muted">
30
+ <img
31
+ src={image}
32
+ className="h-full w-full object-cover group-hover:scale-105 transition-transform duration-300"
33
+ />
34
+ </div>
35
+ )}
36
+
37
+ <div className="flex flex-col flex-1 min-w-0">
38
+ <div className="flex items-start justify-between gap-4 mb-1">
39
+ <a
40
+ href={url || '#'}
41
+ className="text-lg font-medium text-primary hover:underline underline-offset-4 truncate"
42
+ >
43
+ {title}
44
+ </a>
45
+ {tag && (
46
+ <Badge variant="outline" className="shrink-0 text-[10px] uppercase font-mono">
47
+ {tag}
48
+ </Badge>
49
+ )}
50
+ </div>
51
+
52
+ {(subtitle || url) && (
53
+ <div className="text-xs font-mono text-muted-foreground mb-2 flex items-center gap-1.5 align-middle truncate">
54
+ <span>{url ? url : subtitle}</span>
55
+ </div>
56
+ )}
57
+
58
+ {description && (
59
+ <p className="text-sm text-foreground/80 line-clamp-2 md:line-clamp-3 leading-relaxed">
60
+ {description}
61
+ </p>
62
+ )}
63
+
64
+ <div className="mt-3 flex items-center gap-4 text-xs text-muted-foreground">
65
+ {meta}
66
+ </div>
67
+ </div>
68
+ </div>
69
+ )
70
+ }
@@ -0,0 +1 @@
1
+ export * from './SearchResultItem'
@@ -0,0 +1,21 @@
1
+ // ── @reinvented/design/blocks — Blocks Barrel Export ──────────────
2
+ // This file re-exports all composite Block components from the design system.
3
+
4
+ // As blocks are generated via the `/build-block` workflow, they should be exported here.
5
+ // e.g., export * from './communication'
6
+
7
+ export * from './communication'
8
+ export * from './media'
9
+ export * from './ecommerce'
10
+ export * from './content'
11
+ export * from './data-viz'
12
+ export * from './data-management'
13
+ export * from './auth'
14
+ export * from './profiles'
15
+ export * from './settings'
16
+ export * from './onboarding'
17
+ export * from './feedback'
18
+ export * from './filtering'
19
+ export * from './scheduling'
20
+ export * from './navigation'
21
+ export * from './marketing'
@@ -0,0 +1,80 @@
1
+ import React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+ import { Button } from '@/components/ui/button'
4
+ import { ArrowRight } from 'lucide-react'
5
+
6
+ interface CtaBlockProps {
7
+ title: string
8
+ description?: string
9
+ primaryAction?: string
10
+ secondaryAction?: string
11
+ className?: string
12
+ onPrimary?: () => void
13
+ onSecondary?: () => void
14
+ }
15
+
16
+ export function CtaBlock({
17
+ title,
18
+ description,
19
+ primaryAction,
20
+ secondaryAction,
21
+ className,
22
+ onPrimary,
23
+ onSecondary,
24
+ }: CtaBlockProps) {
25
+ return (
26
+ <section
27
+ className={cn(
28
+ 'w-full py-20 lg:py-24 px-4 md:px-6 relative overflow-hidden rounded-3xl bg-primary text-primary-foreground shadow-xl',
29
+ className
30
+ )}
31
+ >
32
+ {/* Ambient background patterns */}
33
+ <div className="absolute right-0 top-0 -translate-y-12 translate-x-1/3 opacity-10 pointer-events-none">
34
+ <svg width="400" height="400" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
35
+ <path
36
+ fill="currentColor"
37
+ d="M44.7,-76.4C58.8,-69.2,71.8,-59.1,79.6,-45.8C87.4,-32.6,90,-16.3,89.1,-0.5C88.1,15.3,83.5,30.6,74.2,42.5C64.9,54.4,50.9,62.9,36.5,69.5C22.1,76.1,7.3,80.8,-7.4,81.3C-22,81.8,-36.5,78,-50.7,71.4C-64.8,64.9,-78.6,55.5,-86.3,42.1C-93.9,28.6,-95.4,11.3,-91.9,-4.5C-88.5,-20.3,-80.2,-34.5,-69.3,-45C-58.4,-55.5,-44.9,-62.3,-31.6,-69.8C-18.3,-77.3,-5.1,-85.5,5.1,-85C15.3,-84.4,30.6,-83.5,44.7,-76.4Z"
38
+ transform="translate(100 100)"
39
+ />
40
+ </svg>
41
+ </div>
42
+
43
+ <div className="relative z-10 flex flex-col items-center text-center max-w-3xl mx-auto">
44
+ <h2 className="text-3xl md:text-5xl font-bold tracking-tight mb-6">
45
+ {title}
46
+ </h2>
47
+
48
+ {description && (
49
+ <p className="text-lg md:text-xl text-primary-foreground/80 mb-10 leading-relaxed">
50
+ {description}
51
+ </p>
52
+ )}
53
+
54
+ <div className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto">
55
+ {primaryAction && (
56
+ <Button
57
+ size="lg"
58
+ variant="secondary"
59
+ className="h-12 px-8 text-base font-semibold w-full sm:w-auto shadow-sm"
60
+ onClick={onPrimary}
61
+ >
62
+ {primaryAction}
63
+ <ArrowRight className="ml-2 h-4 w-4" />
64
+ </Button>
65
+ )}
66
+ {secondaryAction && (
67
+ <Button
68
+ size="lg"
69
+ variant="outline"
70
+ className="h-12 px-8 text-base font-semibold w-full sm:w-auto border-primary-foreground/30 bg-primary-foreground/5 text-primary-foreground hover:bg-primary-foreground/20 hover:text-primary-foreground backdrop-blur"
71
+ onClick={onSecondary}
72
+ >
73
+ {secondaryAction}
74
+ </Button>
75
+ )}
76
+ </div>
77
+ </div>
78
+ </section>
79
+ )
80
+ }
@@ -0,0 +1 @@
1
+ export * from './CtaBlock'
@@ -0,0 +1,47 @@
1
+ import React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+
4
+ interface Feature {
5
+ title: string
6
+ description: string
7
+ icon?: React.ComponentType<{ className?: string }>
8
+ }
9
+
10
+ interface FeatureGridProps {
11
+ features: Feature[]
12
+ columns?: 2 | 3 | 4
13
+ className?: string
14
+ }
15
+
16
+ export function FeatureGrid({ features, columns, className }: FeatureGridProps) {
17
+ return (
18
+ <div
19
+ className={cn(
20
+ 'grid gap-8 sm:gap-12 w-full',
21
+ columns === 2
22
+ ? 'grid-cols-1 md:grid-cols-2'
23
+ : columns === 4
24
+ ? 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4'
25
+ : 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
26
+ className
27
+ )}
28
+ >
29
+ {features.map((feature) => {
30
+ const Icon = feature.icon
31
+ return (
32
+ <div key={feature.title} className="flex flex-col">
33
+ <div className="h-12 w-12 rounded-lg bg-primary/10 flex items-center justify-center mb-6 text-primary">
34
+ {Icon ? (
35
+ <Icon className="h-6 w-6" />
36
+ ) : (
37
+ <div className="h-6 w-6 bg-primary/40 rounded-sm rotate-3 transform transition-transform group-hover:rotate-12" />
38
+ )}
39
+ </div>
40
+ <h3 className="text-xl font-bold mb-3 tracking-tight">{feature.title}</h3>
41
+ <p className="text-muted-foreground leading-relaxed">{feature.description}</p>
42
+ </div>
43
+ )
44
+ })}
45
+ </div>
46
+ )
47
+ }
@@ -0,0 +1 @@
1
+ export * from './FeatureGrid'
@@ -0,0 +1,89 @@
1
+ import React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+ import { Button } from '@/components/ui/button'
4
+ import { Badge } from '@/components/ui/badge'
5
+ import { ArrowRight } from 'lucide-react'
6
+
7
+ interface HeroSectionProps {
8
+ badge?: string
9
+ title: string
10
+ description?: string
11
+ primaryAction?: string
12
+ secondaryAction?: string
13
+ image?: string
14
+ className?: string
15
+ onPrimary?: () => void
16
+ onSecondary?: () => void
17
+ }
18
+
19
+ export function HeroSection({
20
+ badge,
21
+ title,
22
+ description,
23
+ primaryAction,
24
+ secondaryAction,
25
+ image,
26
+ className,
27
+ onPrimary,
28
+ onSecondary,
29
+ }: HeroSectionProps) {
30
+ return (
31
+ <section className={cn('relative overflow-hidden py-24 lg:py-32', className)}>
32
+ <div className="container mx-auto px-4 md:px-6 relative z-10 flex flex-col items-center text-center">
33
+ {badge && (
34
+ <Badge
35
+ variant="secondary"
36
+ className="mb-6 rounded-full px-4 py-1.5 text-sm font-medium border-primary/20 bg-primary/10 text-primary"
37
+ >
38
+ {badge}
39
+ </Badge>
40
+ )}
41
+
42
+ <h1 className="max-w-4xl text-4xl font-extrabold tracking-tight sm:text-5xl md:text-6xl lg:text-7xl mb-6 leading-[1.1]">
43
+ {title}
44
+ </h1>
45
+
46
+ {description && (
47
+ <p className="max-w-2xl text-lg sm:text-xl text-muted-foreground mb-10 leading-relaxed">
48
+ {description}
49
+ </p>
50
+ )}
51
+
52
+ <div className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto mt-2">
53
+ {primaryAction && (
54
+ <Button
55
+ size="lg"
56
+ className="h-12 px-8 text-base font-semibold w-full sm:w-auto"
57
+ onClick={onPrimary}
58
+ >
59
+ {primaryAction}
60
+ <ArrowRight className="ml-2 h-4 w-4" />
61
+ </Button>
62
+ )}
63
+ {secondaryAction && (
64
+ <Button
65
+ size="lg"
66
+ variant="outline"
67
+ className="h-12 px-8 text-base font-semibold w-full sm:w-auto bg-background/50 backdrop-blur"
68
+ onClick={onSecondary}
69
+ >
70
+ {secondaryAction}
71
+ </Button>
72
+ )}
73
+ </div>
74
+ </div>
75
+
76
+ {image && (
77
+ <div className="w-full max-w-6xl mx-auto mt-16 px-4 md:px-6 relative z-10 hidden sm:block">
78
+ <div className="rounded-xl border shadow-2xl overflow-hidden bg-muted">
79
+ <img src={image} className="w-full h-auto object-cover" />
80
+ </div>
81
+ </div>
82
+ )}
83
+
84
+ {/* Abstract Background Elements */}
85
+ <div className="absolute inset-0 -z-10 h-full w-full bg-background bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]"></div>
86
+ <div className="absolute left-0 right-0 top-0 -z-10 m-auto h-[310px] w-[310px] rounded-full bg-primary opacity-20 blur-[100px]"></div>
87
+ </section>
88
+ )
89
+ }
@@ -0,0 +1 @@
1
+ export * from './HeroSection'
@@ -0,0 +1,4 @@
1
+ export * from './hero-section'
2
+ export * from './feature-grid'
3
+ export * from './testimonial-card'
4
+ export * from './cta-block'
@@ -0,0 +1,71 @@
1
+ import React from 'react'
2
+ import { Card, CardContent } from '@/components/ui/card'
3
+ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
4
+ import { Star } from 'lucide-react'
5
+ import { cn } from '@/lib/utils'
6
+
7
+ interface TestimonialCardProps {
8
+ quote: string
9
+ name: string
10
+ role?: string
11
+ company?: string
12
+ avatar?: string
13
+ rating?: number
14
+ className?: string
15
+ }
16
+
17
+ export function TestimonialCard({
18
+ quote,
19
+ name,
20
+ role,
21
+ company,
22
+ avatar,
23
+ rating,
24
+ className,
25
+ }: TestimonialCardProps) {
26
+ return (
27
+ <Card
28
+ className={cn(
29
+ 'overflow-hidden h-full border-none shadow-md bg-muted/30 hover:bg-muted/50 transition-colors duration-300',
30
+ className,
31
+ )}
32
+ >
33
+ <CardContent className="p-8 flex flex-col h-full">
34
+ {rating != null && (
35
+ <div className="flex items-center gap-1 mb-6 text-yellow-500">
36
+ {[1, 2, 3, 4, 5].map((i) => (
37
+ <Star
38
+ key={i}
39
+ className="h-4 w-4"
40
+ fill={i <= rating ? 'currentColor' : 'transparent'}
41
+ />
42
+ ))}
43
+ </div>
44
+ )}
45
+
46
+ <blockquote className="text-lg md:text-xl text-foreground font-medium mb-8 flex-1 leading-snug">
47
+ &ldquo;{quote}&rdquo;
48
+ </blockquote>
49
+
50
+ <div className="flex items-center gap-4 mt-auto">
51
+ <Avatar className="h-12 w-12 border-2 border-background shadow-sm">
52
+ {avatar && <AvatarImage src={avatar} />}
53
+ <AvatarFallback className="bg-primary/5 text-primary font-bold">
54
+ {name.substring(0, 2).toUpperCase()}
55
+ </AvatarFallback>
56
+ </Avatar>
57
+ <div className="flex flex-col">
58
+ <span className="font-bold text-base leading-none">{name}</span>
59
+ {(role || company) && (
60
+ <span className="text-sm text-muted-foreground mt-1.5 leading-none">
61
+ {role}
62
+ {role && company && ', '}
63
+ {company}
64
+ </span>
65
+ )}
66
+ </div>
67
+ </div>
68
+ </CardContent>
69
+ </Card>
70
+ )
71
+ }
@@ -0,0 +1 @@
1
+ export * from './TestimonialCard'