@polymarbot/nuxt-layer-shadcn-ui 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 (408) hide show
  1. package/app/assets/styles/animate.css +71 -0
  2. package/app/assets/styles/colors.css +116 -0
  3. package/app/assets/styles/globals.css +43 -0
  4. package/app/assets/styles/index.stories.ts +211 -0
  5. package/app/assets/styles/transition.css +34 -0
  6. package/app/assets/styles/utilities.css +26 -0
  7. package/app/components/shadcn/accordion/Accordion.vue +18 -0
  8. package/app/components/shadcn/accordion/AccordionContent.vue +23 -0
  9. package/app/components/shadcn/accordion/AccordionItem.vue +24 -0
  10. package/app/components/shadcn/accordion/AccordionTrigger.vue +37 -0
  11. package/app/components/shadcn/accordion/index.ts +4 -0
  12. package/app/components/shadcn/alert/Alert.vue +21 -0
  13. package/app/components/shadcn/alert/AlertDescription.vue +17 -0
  14. package/app/components/shadcn/alert/AlertTitle.vue +17 -0
  15. package/app/components/shadcn/alert/index.ts +24 -0
  16. package/app/components/shadcn/avatar/Avatar.vue +18 -0
  17. package/app/components/shadcn/avatar/AvatarFallback.vue +21 -0
  18. package/app/components/shadcn/avatar/AvatarImage.vue +16 -0
  19. package/app/components/shadcn/avatar/index.ts +3 -0
  20. package/app/components/shadcn/badge/Badge.vue +26 -0
  21. package/app/components/shadcn/badge/index.ts +26 -0
  22. package/app/components/shadcn/breadcrumb/Breadcrumb.vue +17 -0
  23. package/app/components/shadcn/breadcrumb/BreadcrumbEllipsis.vue +23 -0
  24. package/app/components/shadcn/breadcrumb/BreadcrumbItem.vue +17 -0
  25. package/app/components/shadcn/breadcrumb/BreadcrumbLink.vue +21 -0
  26. package/app/components/shadcn/breadcrumb/BreadcrumbList.vue +17 -0
  27. package/app/components/shadcn/breadcrumb/BreadcrumbPage.vue +20 -0
  28. package/app/components/shadcn/breadcrumb/BreadcrumbSeparator.vue +22 -0
  29. package/app/components/shadcn/breadcrumb/index.ts +7 -0
  30. package/app/components/shadcn/button/Button.vue +31 -0
  31. package/app/components/shadcn/button/index.ts +38 -0
  32. package/app/components/shadcn/card/Card.vue +22 -0
  33. package/app/components/shadcn/card/CardAction.vue +17 -0
  34. package/app/components/shadcn/card/CardContent.vue +17 -0
  35. package/app/components/shadcn/card/CardDescription.vue +17 -0
  36. package/app/components/shadcn/card/CardFooter.vue +17 -0
  37. package/app/components/shadcn/card/CardHeader.vue +17 -0
  38. package/app/components/shadcn/card/CardTitle.vue +17 -0
  39. package/app/components/shadcn/card/index.ts +7 -0
  40. package/app/components/shadcn/checkbox/Checkbox.vue +35 -0
  41. package/app/components/shadcn/checkbox/index.ts +1 -0
  42. package/app/components/shadcn/collapsible/Collapsible.vue +19 -0
  43. package/app/components/shadcn/collapsible/CollapsibleContent.vue +15 -0
  44. package/app/components/shadcn/collapsible/CollapsibleTrigger.vue +15 -0
  45. package/app/components/shadcn/collapsible/index.ts +3 -0
  46. package/app/components/shadcn/command/Command.vue +87 -0
  47. package/app/components/shadcn/command/CommandDialog.vue +31 -0
  48. package/app/components/shadcn/command/CommandEmpty.vue +27 -0
  49. package/app/components/shadcn/command/CommandGroup.vue +45 -0
  50. package/app/components/shadcn/command/CommandInput.vue +39 -0
  51. package/app/components/shadcn/command/CommandItem.vue +76 -0
  52. package/app/components/shadcn/command/CommandList.vue +25 -0
  53. package/app/components/shadcn/command/CommandSeparator.vue +21 -0
  54. package/app/components/shadcn/command/CommandShortcut.vue +17 -0
  55. package/app/components/shadcn/command/index.ts +25 -0
  56. package/app/components/shadcn/dialog/Dialog.vue +19 -0
  57. package/app/components/shadcn/dialog/DialogClose.vue +15 -0
  58. package/app/components/shadcn/dialog/DialogContent.vue +53 -0
  59. package/app/components/shadcn/dialog/DialogDescription.vue +23 -0
  60. package/app/components/shadcn/dialog/DialogFooter.vue +27 -0
  61. package/app/components/shadcn/dialog/DialogHeader.vue +17 -0
  62. package/app/components/shadcn/dialog/DialogOverlay.vue +21 -0
  63. package/app/components/shadcn/dialog/DialogScrollContent.vue +59 -0
  64. package/app/components/shadcn/dialog/DialogTitle.vue +23 -0
  65. package/app/components/shadcn/dialog/DialogTrigger.vue +15 -0
  66. package/app/components/shadcn/dialog/index.ts +10 -0
  67. package/app/components/shadcn/dropdown-menu/DropdownMenu.vue +19 -0
  68. package/app/components/shadcn/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  69. package/app/components/shadcn/dropdown-menu/DropdownMenuContent.vue +39 -0
  70. package/app/components/shadcn/dropdown-menu/DropdownMenuGroup.vue +15 -0
  71. package/app/components/shadcn/dropdown-menu/DropdownMenuItem.vue +31 -0
  72. package/app/components/shadcn/dropdown-menu/DropdownMenuLabel.vue +23 -0
  73. package/app/components/shadcn/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  74. package/app/components/shadcn/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  75. package/app/components/shadcn/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  76. package/app/components/shadcn/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  77. package/app/components/shadcn/dropdown-menu/DropdownMenuSub.vue +18 -0
  78. package/app/components/shadcn/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  79. package/app/components/shadcn/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  80. package/app/components/shadcn/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  81. package/app/components/shadcn/dropdown-menu/index.ts +16 -0
  82. package/app/components/shadcn/field/Field.vue +25 -0
  83. package/app/components/shadcn/field/FieldContent.vue +20 -0
  84. package/app/components/shadcn/field/FieldDescription.vue +22 -0
  85. package/app/components/shadcn/field/FieldError.vue +53 -0
  86. package/app/components/shadcn/field/FieldGroup.vue +20 -0
  87. package/app/components/shadcn/field/FieldLabel.vue +23 -0
  88. package/app/components/shadcn/field/FieldLegend.vue +24 -0
  89. package/app/components/shadcn/field/FieldSeparator.vue +29 -0
  90. package/app/components/shadcn/field/FieldSet.vue +21 -0
  91. package/app/components/shadcn/field/FieldTitle.vue +20 -0
  92. package/app/components/shadcn/field/index.ts +39 -0
  93. package/app/components/shadcn/input/Input.vue +33 -0
  94. package/app/components/shadcn/input/index.ts +1 -0
  95. package/app/components/shadcn/input-group/InputGroup.vue +35 -0
  96. package/app/components/shadcn/input-group/InputGroupAddon.vue +36 -0
  97. package/app/components/shadcn/input-group/InputGroupButton.vue +29 -0
  98. package/app/components/shadcn/input-group/InputGroupInput.vue +19 -0
  99. package/app/components/shadcn/input-group/InputGroupText.vue +19 -0
  100. package/app/components/shadcn/input-group/InputGroupTextarea.vue +19 -0
  101. package/app/components/shadcn/input-group/index.ts +51 -0
  102. package/app/components/shadcn/label/Label.vue +26 -0
  103. package/app/components/shadcn/label/index.ts +1 -0
  104. package/app/components/shadcn/number-field/NumberField.vue +20 -0
  105. package/app/components/shadcn/number-field/NumberFieldContent.vue +14 -0
  106. package/app/components/shadcn/number-field/NumberFieldDecrement.vue +22 -0
  107. package/app/components/shadcn/number-field/NumberFieldIncrement.vue +22 -0
  108. package/app/components/shadcn/number-field/NumberFieldInput.vue +16 -0
  109. package/app/components/shadcn/number-field/index.ts +5 -0
  110. package/app/components/shadcn/pagination/Pagination.vue +26 -0
  111. package/app/components/shadcn/pagination/PaginationContent.vue +22 -0
  112. package/app/components/shadcn/pagination/PaginationEllipsis.vue +25 -0
  113. package/app/components/shadcn/pagination/PaginationFirst.vue +33 -0
  114. package/app/components/shadcn/pagination/PaginationItem.vue +34 -0
  115. package/app/components/shadcn/pagination/PaginationLast.vue +33 -0
  116. package/app/components/shadcn/pagination/PaginationNext.vue +33 -0
  117. package/app/components/shadcn/pagination/PaginationPrevious.vue +33 -0
  118. package/app/components/shadcn/pagination/index.ts +8 -0
  119. package/app/components/shadcn/pin-input/PinInput.vue +26 -0
  120. package/app/components/shadcn/pin-input/PinInputGroup.vue +21 -0
  121. package/app/components/shadcn/pin-input/PinInputSeparator.vue +19 -0
  122. package/app/components/shadcn/pin-input/PinInputSlot.vue +21 -0
  123. package/app/components/shadcn/pin-input/index.ts +4 -0
  124. package/app/components/shadcn/popover/Popover.vue +19 -0
  125. package/app/components/shadcn/popover/PopoverAnchor.vue +15 -0
  126. package/app/components/shadcn/popover/PopoverContent.vue +45 -0
  127. package/app/components/shadcn/popover/PopoverTrigger.vue +15 -0
  128. package/app/components/shadcn/popover/index.ts +4 -0
  129. package/app/components/shadcn/progress/Progress.vue +38 -0
  130. package/app/components/shadcn/progress/index.ts +1 -0
  131. package/app/components/shadcn/radio-group/RadioGroup.vue +25 -0
  132. package/app/components/shadcn/radio-group/RadioGroupItem.vue +40 -0
  133. package/app/components/shadcn/radio-group/index.ts +2 -0
  134. package/app/components/shadcn/scroll-area/ScrollArea.vue +33 -0
  135. package/app/components/shadcn/scroll-area/ScrollBar.vue +32 -0
  136. package/app/components/shadcn/scroll-area/index.ts +2 -0
  137. package/app/components/shadcn/select/Select.vue +19 -0
  138. package/app/components/shadcn/select/SelectContent.vue +51 -0
  139. package/app/components/shadcn/select/SelectGroup.vue +15 -0
  140. package/app/components/shadcn/select/SelectItem.vue +44 -0
  141. package/app/components/shadcn/select/SelectItemText.vue +15 -0
  142. package/app/components/shadcn/select/SelectLabel.vue +17 -0
  143. package/app/components/shadcn/select/SelectScrollDownButton.vue +26 -0
  144. package/app/components/shadcn/select/SelectScrollUpButton.vue +26 -0
  145. package/app/components/shadcn/select/SelectSeparator.vue +19 -0
  146. package/app/components/shadcn/select/SelectTrigger.vue +33 -0
  147. package/app/components/shadcn/select/SelectValue.vue +15 -0
  148. package/app/components/shadcn/select/index.ts +11 -0
  149. package/app/components/shadcn/separator/Separator.vue +29 -0
  150. package/app/components/shadcn/separator/index.ts +1 -0
  151. package/app/components/shadcn/sheet/Sheet.vue +19 -0
  152. package/app/components/shadcn/sheet/SheetClose.vue +15 -0
  153. package/app/components/shadcn/sheet/SheetContent.vue +62 -0
  154. package/app/components/shadcn/sheet/SheetDescription.vue +21 -0
  155. package/app/components/shadcn/sheet/SheetFooter.vue +16 -0
  156. package/app/components/shadcn/sheet/SheetHeader.vue +15 -0
  157. package/app/components/shadcn/sheet/SheetOverlay.vue +21 -0
  158. package/app/components/shadcn/sheet/SheetTitle.vue +21 -0
  159. package/app/components/shadcn/sheet/SheetTrigger.vue +15 -0
  160. package/app/components/shadcn/sheet/index.ts +8 -0
  161. package/app/components/shadcn/sidebar/Sidebar.vue +96 -0
  162. package/app/components/shadcn/sidebar/SidebarContent.vue +18 -0
  163. package/app/components/shadcn/sidebar/SidebarFooter.vue +18 -0
  164. package/app/components/shadcn/sidebar/SidebarGroup.vue +18 -0
  165. package/app/components/shadcn/sidebar/SidebarGroupAction.vue +27 -0
  166. package/app/components/shadcn/sidebar/SidebarGroupContent.vue +18 -0
  167. package/app/components/shadcn/sidebar/SidebarGroupLabel.vue +25 -0
  168. package/app/components/shadcn/sidebar/SidebarHeader.vue +18 -0
  169. package/app/components/shadcn/sidebar/SidebarInput.vue +22 -0
  170. package/app/components/shadcn/sidebar/SidebarInset.vue +21 -0
  171. package/app/components/shadcn/sidebar/SidebarMenu.vue +18 -0
  172. package/app/components/shadcn/sidebar/SidebarMenuAction.vue +35 -0
  173. package/app/components/shadcn/sidebar/SidebarMenuBadge.vue +26 -0
  174. package/app/components/shadcn/sidebar/SidebarMenuButton.vue +48 -0
  175. package/app/components/shadcn/sidebar/SidebarMenuButtonChild.vue +36 -0
  176. package/app/components/shadcn/sidebar/SidebarMenuItem.vue +18 -0
  177. package/app/components/shadcn/sidebar/SidebarMenuSkeleton.vue +35 -0
  178. package/app/components/shadcn/sidebar/SidebarMenuSub.vue +22 -0
  179. package/app/components/shadcn/sidebar/SidebarMenuSubButton.vue +36 -0
  180. package/app/components/shadcn/sidebar/SidebarMenuSubItem.vue +18 -0
  181. package/app/components/shadcn/sidebar/SidebarProvider.vue +82 -0
  182. package/app/components/shadcn/sidebar/SidebarRail.vue +33 -0
  183. package/app/components/shadcn/sidebar/SidebarSeparator.vue +19 -0
  184. package/app/components/shadcn/sidebar/SidebarTrigger.vue +27 -0
  185. package/app/components/shadcn/sidebar/index.ts +60 -0
  186. package/app/components/shadcn/sidebar/utils.ts +19 -0
  187. package/app/components/shadcn/skeleton/Skeleton.vue +17 -0
  188. package/app/components/shadcn/skeleton/index.ts +1 -0
  189. package/app/components/shadcn/slider/Slider.vue +43 -0
  190. package/app/components/shadcn/slider/index.ts +1 -0
  191. package/app/components/shadcn/sonner/Sonner.vue +42 -0
  192. package/app/components/shadcn/sonner/index.ts +1 -0
  193. package/app/components/shadcn/switch/Switch.vue +38 -0
  194. package/app/components/shadcn/switch/index.ts +1 -0
  195. package/app/components/shadcn/table/Table.vue +16 -0
  196. package/app/components/shadcn/table/TableBody.vue +17 -0
  197. package/app/components/shadcn/table/TableCaption.vue +17 -0
  198. package/app/components/shadcn/table/TableCell.vue +22 -0
  199. package/app/components/shadcn/table/TableEmpty.vue +34 -0
  200. package/app/components/shadcn/table/TableFooter.vue +17 -0
  201. package/app/components/shadcn/table/TableHead.vue +17 -0
  202. package/app/components/shadcn/table/TableHeader.vue +17 -0
  203. package/app/components/shadcn/table/TableRow.vue +17 -0
  204. package/app/components/shadcn/table/index.ts +9 -0
  205. package/app/components/shadcn/table/utils.ts +10 -0
  206. package/app/components/shadcn/tabs/Tabs.vue +24 -0
  207. package/app/components/shadcn/tabs/TabsContent.vue +21 -0
  208. package/app/components/shadcn/tabs/TabsList.vue +24 -0
  209. package/app/components/shadcn/tabs/TabsTrigger.vue +26 -0
  210. package/app/components/shadcn/tabs/index.ts +4 -0
  211. package/app/components/shadcn/textarea/Textarea.vue +28 -0
  212. package/app/components/shadcn/textarea/index.ts +1 -0
  213. package/app/components/shadcn/toggle/Toggle.vue +35 -0
  214. package/app/components/shadcn/toggle/index.ts +28 -0
  215. package/app/components/shadcn/toggle-group/ToggleGroup.vue +49 -0
  216. package/app/components/shadcn/toggle-group/ToggleGroupItem.vue +46 -0
  217. package/app/components/shadcn/toggle-group/index.ts +2 -0
  218. package/app/components/shadcn/tooltip/Tooltip.vue +19 -0
  219. package/app/components/shadcn/tooltip/TooltipContent.vue +34 -0
  220. package/app/components/shadcn/tooltip/TooltipProvider.vue +14 -0
  221. package/app/components/shadcn/tooltip/TooltipTrigger.vue +15 -0
  222. package/app/components/shadcn/tooltip/index.ts +4 -0
  223. package/app/components/ui/Accordion/index.stories.ts +108 -0
  224. package/app/components/ui/Accordion/index.vue +80 -0
  225. package/app/components/ui/Accordion/types.ts +27 -0
  226. package/app/components/ui/Alert/index.stories.ts +53 -0
  227. package/app/components/ui/Alert/index.vue +61 -0
  228. package/app/components/ui/Alert/types.ts +9 -0
  229. package/app/components/ui/AlertDialog/index.stories.ts +108 -0
  230. package/app/components/ui/AlertDialog/index.vue +25 -0
  231. package/app/components/ui/AsyncDataTable/en.json +3 -0
  232. package/app/components/ui/AsyncDataTable/index.stories.ts +141 -0
  233. package/app/components/ui/AsyncDataTable/index.vue +312 -0
  234. package/app/components/ui/AsyncDataTable/types.ts +53 -0
  235. package/app/components/ui/Avatar/index.stories.ts +84 -0
  236. package/app/components/ui/Avatar/index.vue +52 -0
  237. package/app/components/ui/Avatar/types.ts +8 -0
  238. package/app/components/ui/Badge/index.stories.ts +67 -0
  239. package/app/components/ui/Badge/index.vue +12 -0
  240. package/app/components/ui/Badge/types.ts +3 -0
  241. package/app/components/ui/Breadcrumb/index.stories.ts +52 -0
  242. package/app/components/ui/Breadcrumb/index.vue +61 -0
  243. package/app/components/ui/Breadcrumb/types.ts +11 -0
  244. package/app/components/ui/Button/index.stories.ts +145 -0
  245. package/app/components/ui/Button/index.vue +63 -0
  246. package/app/components/ui/Button/types.ts +14 -0
  247. package/app/components/ui/ButtonGroup/index.stories.ts +75 -0
  248. package/app/components/ui/ButtonGroup/index.vue +22 -0
  249. package/app/components/ui/ButtonGroup/types.ts +3 -0
  250. package/app/components/ui/Card/index.stories.ts +65 -0
  251. package/app/components/ui/Card/index.vue +28 -0
  252. package/app/components/ui/Card/types.ts +3 -0
  253. package/app/components/ui/Checkbox/index.stories.ts +68 -0
  254. package/app/components/ui/Checkbox/index.vue +23 -0
  255. package/app/components/ui/Checkbox/types.ts +3 -0
  256. package/app/components/ui/CopyButton/en.json +4 -0
  257. package/app/components/ui/CopyButton/index.stories.ts +55 -0
  258. package/app/components/ui/CopyButton/index.vue +98 -0
  259. package/app/components/ui/CopyButton/types.ts +10 -0
  260. package/app/components/ui/DataTable/en.json +3 -0
  261. package/app/components/ui/DataTable/index.stories.ts +231 -0
  262. package/app/components/ui/DataTable/index.vue +505 -0
  263. package/app/components/ui/DataTable/types.ts +42 -0
  264. package/app/components/ui/DatePicker/en.json +9 -0
  265. package/app/components/ui/DatePicker/index.stories.ts +70 -0
  266. package/app/components/ui/DatePicker/index.vue +127 -0
  267. package/app/components/ui/DatePicker/style.css +88 -0
  268. package/app/components/ui/DatePicker/types.ts +41 -0
  269. package/app/components/ui/DateRangePicker/en.json +5 -0
  270. package/app/components/ui/DateRangePicker/index.stories.ts +67 -0
  271. package/app/components/ui/DateRangePicker/index.vue +138 -0
  272. package/app/components/ui/DateRangePicker/types.ts +31 -0
  273. package/app/components/ui/Divider/index.stories.ts +42 -0
  274. package/app/components/ui/Divider/index.vue +16 -0
  275. package/app/components/ui/Divider/types.ts +3 -0
  276. package/app/components/ui/Drawer/index.stories.ts +124 -0
  277. package/app/components/ui/Drawer/index.vue +197 -0
  278. package/app/components/ui/Drawer/types.ts +22 -0
  279. package/app/components/ui/Dropdown/index.stories.ts +145 -0
  280. package/app/components/ui/Dropdown/index.vue +258 -0
  281. package/app/components/ui/Dropdown/types.ts +87 -0
  282. package/app/components/ui/FormItem/index.stories.ts +70 -0
  283. package/app/components/ui/FormItem/index.vue +56 -0
  284. package/app/components/ui/FormItem/types.ts +14 -0
  285. package/app/components/ui/Help/index.stories.ts +54 -0
  286. package/app/components/ui/Help/index.vue +35 -0
  287. package/app/components/ui/Help/types.ts +8 -0
  288. package/app/components/ui/Icon/index.stories.ts +68 -0
  289. package/app/components/ui/Icon/index.vue +30 -0
  290. package/app/components/ui/Icon/types.ts +5 -0
  291. package/app/components/ui/Input/index.stories.ts +73 -0
  292. package/app/components/ui/Input/index.vue +92 -0
  293. package/app/components/ui/Input/types.ts +9 -0
  294. package/app/components/ui/InputCurrency/index.stories.ts +75 -0
  295. package/app/components/ui/InputCurrency/index.vue +31 -0
  296. package/app/components/ui/InputCurrency/types.ts +4 -0
  297. package/app/components/ui/InputNumber/index.stories.ts +56 -0
  298. package/app/components/ui/InputNumber/index.vue +76 -0
  299. package/app/components/ui/InputNumber/types.ts +10 -0
  300. package/app/components/ui/InputOtp/index.stories.ts +39 -0
  301. package/app/components/ui/InputOtp/index.vue +45 -0
  302. package/app/components/ui/InputOtp/types.ts +5 -0
  303. package/app/components/ui/InputPercent/index.stories.ts +32 -0
  304. package/app/components/ui/InputPercent/index.vue +8 -0
  305. package/app/components/ui/InputRange/index.stories.ts +37 -0
  306. package/app/components/ui/InputRange/index.vue +49 -0
  307. package/app/components/ui/InputRange/types.ts +8 -0
  308. package/app/components/ui/Loading/index.stories.ts +36 -0
  309. package/app/components/ui/Loading/index.vue +15 -0
  310. package/app/components/ui/Loading/types.ts +3 -0
  311. package/app/components/ui/Markdown/index.stories.ts +52 -0
  312. package/app/components/ui/Markdown/index.vue +22 -0
  313. package/app/components/ui/Markdown/themes/github.css +1248 -0
  314. package/app/components/ui/Markdown/types.ts +3 -0
  315. package/app/components/ui/Modal/index.stories.ts +124 -0
  316. package/app/components/ui/Modal/index.vue +202 -0
  317. package/app/components/ui/Modal/types.ts +23 -0
  318. package/app/components/ui/ModalContent/index.stories.ts +47 -0
  319. package/app/components/ui/ModalContent/index.vue +79 -0
  320. package/app/components/ui/ModalContent/types.ts +9 -0
  321. package/app/components/ui/PageCard/index.stories.ts +106 -0
  322. package/app/components/ui/PageCard/index.vue +135 -0
  323. package/app/components/ui/PageCard/types.ts +16 -0
  324. package/app/components/ui/Pagination/en.json +3 -0
  325. package/app/components/ui/Pagination/index.stories.ts +82 -0
  326. package/app/components/ui/Pagination/index.vue +173 -0
  327. package/app/components/ui/Pagination/types.ts +18 -0
  328. package/app/components/ui/Popover/index.stories.ts +67 -0
  329. package/app/components/ui/Popover/index.vue +21 -0
  330. package/app/components/ui/Popover/types.ts +5 -0
  331. package/app/components/ui/Qrcode/index.stories.ts +57 -0
  332. package/app/components/ui/Qrcode/index.vue +40 -0
  333. package/app/components/ui/Qrcode/types.ts +3 -0
  334. package/app/components/ui/Radio/index.stories.ts +71 -0
  335. package/app/components/ui/Radio/index.vue +10 -0
  336. package/app/components/ui/Radio/types.ts +3 -0
  337. package/app/components/ui/RadioCardGroup/index.stories.ts +90 -0
  338. package/app/components/ui/RadioCardGroup/index.vue +64 -0
  339. package/app/components/ui/RadioCardGroup/types.ts +13 -0
  340. package/app/components/ui/ScrollArea/index.stories.ts +66 -0
  341. package/app/components/ui/ScrollArea/index.vue +64 -0
  342. package/app/components/ui/ScrollArea/types.ts +5 -0
  343. package/app/components/ui/SearchSelect/en.json +5 -0
  344. package/app/components/ui/SearchSelect/index.stories.ts +126 -0
  345. package/app/components/ui/SearchSelect/index.vue +259 -0
  346. package/app/components/ui/SearchSelect/types.ts +39 -0
  347. package/app/components/ui/Select/en.json +6 -0
  348. package/app/components/ui/Select/index.stories.ts +128 -0
  349. package/app/components/ui/Select/index.vue +267 -0
  350. package/app/components/ui/Select/types.ts +34 -0
  351. package/app/components/ui/Skeleton/index.stories.ts +56 -0
  352. package/app/components/ui/Skeleton/index.vue +12 -0
  353. package/app/components/ui/Skeleton/types.ts +4 -0
  354. package/app/components/ui/Slider/index.stories.ts +60 -0
  355. package/app/components/ui/Slider/index.vue +27 -0
  356. package/app/components/ui/Slider/types.ts +5 -0
  357. package/app/components/ui/Surface/index.stories.ts +50 -0
  358. package/app/components/ui/Surface/index.vue +108 -0
  359. package/app/components/ui/Surface/types.ts +8 -0
  360. package/app/components/ui/Switch/index.stories.ts +32 -0
  361. package/app/components/ui/Switch/index.vue +10 -0
  362. package/app/components/ui/Switch/types.ts +3 -0
  363. package/app/components/ui/Tabs/index.stories.ts +116 -0
  364. package/app/components/ui/Tabs/index.vue +94 -0
  365. package/app/components/ui/Tabs/types.ts +19 -0
  366. package/app/components/ui/Tag/index.stories.ts +51 -0
  367. package/app/components/ui/Tag/index.vue +108 -0
  368. package/app/components/ui/Tag/types.ts +8 -0
  369. package/app/components/ui/Textarea/index.stories.ts +35 -0
  370. package/app/components/ui/Textarea/index.vue +50 -0
  371. package/app/components/ui/Textarea/types.ts +8 -0
  372. package/app/components/ui/Toast/index.stories.ts +48 -0
  373. package/app/components/ui/Toast/index.vue +21 -0
  374. package/app/components/ui/Toast/types.ts +5 -0
  375. package/app/components/ui/Tooltip/index.stories.ts +62 -0
  376. package/app/components/ui/Tooltip/index.vue +72 -0
  377. package/app/components/ui/Tooltip/types.ts +7 -0
  378. package/app/components/ui/WebLink/index.stories.ts +59 -0
  379. package/app/components/ui/WebLink/index.vue +61 -0
  380. package/app/components/ui/WebLink/types.ts +11 -0
  381. package/app/composables/index.ts +9 -0
  382. package/app/composables/useDialog.ts +76 -0
  383. package/app/composables/useToast.ts +49 -0
  384. package/app/en.json +23 -0
  385. package/app/types/index.ts +7 -0
  386. package/app/utils/index.ts +6 -0
  387. package/i18n/messages/ar.json +65 -0
  388. package/i18n/messages/de.json +65 -0
  389. package/i18n/messages/en.json +65 -0
  390. package/i18n/messages/es.json +65 -0
  391. package/i18n/messages/fr.json +65 -0
  392. package/i18n/messages/hi.json +65 -0
  393. package/i18n/messages/id.json +65 -0
  394. package/i18n/messages/it.json +65 -0
  395. package/i18n/messages/ja.json +65 -0
  396. package/i18n/messages/ko.json +65 -0
  397. package/i18n/messages/nl.json +65 -0
  398. package/i18n/messages/pl.json +65 -0
  399. package/i18n/messages/pt.json +65 -0
  400. package/i18n/messages/ru.json +65 -0
  401. package/i18n/messages/th.json +65 -0
  402. package/i18n/messages/tr.json +65 -0
  403. package/i18n/messages/vi.json +65 -0
  404. package/i18n/messages/zh-CN.json +65 -0
  405. package/i18n/messages/zh-TW.json +65 -0
  406. package/i18n.config.ts +19 -0
  407. package/nuxt.config.ts +62 -0
  408. package/package.json +46 -0
@@ -0,0 +1,197 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ Sheet,
4
+ SheetClose,
5
+ SheetContent,
6
+ SheetDescription,
7
+ SheetFooter,
8
+ SheetHeader,
9
+ SheetTitle,
10
+ } from '@polymarbot/nuxt-layer-shadcn-ui/app/components/shadcn/sheet'
11
+ import type { DrawerProps } from './types'
12
+
13
+ const props = withDefaults(defineProps<DrawerProps>(), {
14
+ showClose: true,
15
+ side: 'right',
16
+ title: undefined,
17
+ description: undefined,
18
+ confirmText: undefined,
19
+ cancelText: undefined,
20
+ confirmVariant: 'default',
21
+ cancelVariant: 'outline',
22
+ class: undefined,
23
+ })
24
+
25
+ const emit = defineEmits<{
26
+ 'update:visible': [value: boolean]
27
+ 'open': []
28
+ 'close': []
29
+ 'closed': []
30
+ 'confirm': []
31
+ 'cancel': []
32
+ }>()
33
+
34
+ const { t } = useI18n()
35
+
36
+ const resolvedConfirmText = computed(
37
+ () => props.confirmText ?? t('common.actions.confirm'),
38
+ )
39
+ const resolvedCancelText = computed(
40
+ () => props.cancelText ?? t('common.actions.cancel'),
41
+ )
42
+
43
+ const sheetOpen = computed({
44
+ get: () => props.visible ?? false,
45
+ set: (value: boolean) => {
46
+ if (!value && props.visible && !props.loading) {
47
+ onCancel()
48
+ }
49
+ },
50
+ })
51
+
52
+ watch(() => props.visible, visible => {
53
+ if (visible) emit('open')
54
+ else emit('close')
55
+ })
56
+
57
+ function onConfirm () {
58
+ emit('confirm')
59
+ emit('update:visible', false)
60
+ }
61
+
62
+ function onCancel () {
63
+ emit('cancel')
64
+ emit('update:visible', false)
65
+ }
66
+
67
+ const contentClass = computed(() =>
68
+ cn('flex flex-col gap-0 p-0', props.class),
69
+ )
70
+ </script>
71
+
72
+ <template>
73
+ <Sheet v-model:open="sheetOpen">
74
+ <SheetContent
75
+ :side="side"
76
+ :class="contentClass"
77
+ @pointerDownOutside.prevent
78
+ @closeAutoFocus="emit('closed')"
79
+ >
80
+ <!-- Header -->
81
+ <SheetHeader
82
+ v-if="!hideHeader && (!!title || !!description || !!$slots.header)"
83
+ class="border-b"
84
+ >
85
+ <SheetTitle>
86
+ <slot name="header">
87
+ {{ title }}
88
+ </slot>
89
+ </SheetTitle>
90
+ <SheetDescription v-if="description">
91
+ {{ description }}
92
+ </SheetDescription>
93
+ <SheetDescription
94
+ v-else
95
+ class="sr-only"
96
+ />
97
+ </SheetHeader>
98
+
99
+ <!-- A11y fallback: SheetTitle/SheetDescription required by reka-ui -->
100
+ <template v-else>
101
+ <SheetTitle class="sr-only">
102
+ {{ title }}
103
+ </SheetTitle>
104
+ <SheetDescription class="sr-only" />
105
+ </template>
106
+
107
+ <!-- Content -->
108
+ <ScrollArea
109
+ fadeMask
110
+ class="min-h-0 flex-1"
111
+ >
112
+ <div
113
+ :inert="loading || disabled || undefined"
114
+ :class="[ loading || disabled ? 'opacity-50' : undefined ]"
115
+ class="p-4"
116
+ >
117
+ <slot />
118
+ </div>
119
+ </ScrollArea>
120
+
121
+ <!-- Footer -->
122
+ <SheetFooter
123
+ v-if="!hideFooter"
124
+ class="flex-row items-center border-t"
125
+ >
126
+ <slot name="footer">
127
+ <div class="min-w-0 flex-1">
128
+ <slot name="footerLeft" />
129
+ </div>
130
+
131
+ <div class="flex shrink-0 justify-end gap-4">
132
+ <Button
133
+ v-if="showCancel"
134
+ class="min-w-24"
135
+ :variant="cancelVariant"
136
+ :disabled="loading"
137
+ @click="onCancel"
138
+ >
139
+ {{ resolvedCancelText }}
140
+ </Button>
141
+ <Button
142
+ :class="showCancel ? 'min-w-24' : 'min-w-32'"
143
+ :variant="confirmVariant"
144
+ :loading="loading"
145
+ :disabled="disabled || confirmDisabled"
146
+ @click="onConfirm"
147
+ >
148
+ {{ resolvedConfirmText }}
149
+ </Button>
150
+ </div>
151
+ </slot>
152
+ </SheetFooter>
153
+
154
+ <SheetClose
155
+ v-if="showClose"
156
+ :disabled="loading"
157
+ class="
158
+ absolute top-3 right-3 flex size-8 items-center justify-center
159
+ rounded-full text-muted-foreground ring-offset-background transition
160
+ hover:bg-accent/50 hover:text-foreground
161
+ focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden
162
+ disabled:pointer-events-none disabled:opacity-50
163
+ "
164
+ >
165
+ <Icon name="x" />
166
+ <span class="sr-only">
167
+ {{ t('common.actions.close') }}
168
+ </span>
169
+ </SheetClose>
170
+ </SheetContent>
171
+ </Sheet>
172
+ </template>
173
+
174
+ <style>
175
+ /* Translucent blur backdrop. SheetOverlay is rendered inside DialogPortal
176
+ (outside component scope), so use a non-scoped style. */
177
+ [data-slot='sheet-overlay'] {
178
+ z-index: 200;
179
+ background-color: rgba(252, 252, 252, 0.3);
180
+ backdrop-filter: blur(2px);
181
+ -webkit-backdrop-filter: blur(2px);
182
+ }
183
+ .dark [data-slot='sheet-overlay'] {
184
+ background-color: rgba(25, 25, 25, 0.3);
185
+ }
186
+
187
+ /* Raise above layout header (z-100) so the drawer covers it. */
188
+ [data-slot='sheet-content'] {
189
+ z-index: 200;
190
+ }
191
+
192
+ /* Hide SheetContent's hardcoded built-in close button (no data-slot);
193
+ we render our own SheetClose above with loading-aware disable. */
194
+ [data-slot='sheet-content'] > button:not([data-slot]) {
195
+ display: none;
196
+ }
197
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { ButtonVariants } from '@polymarbot/nuxt-layer-shadcn-ui/app/components/shadcn/button'
2
+
3
+ export type DrawerSide = 'top' | 'right' | 'bottom' | 'left'
4
+
5
+ export interface DrawerProps {
6
+ visible?: boolean
7
+ loading?: boolean
8
+ disabled?: boolean
9
+ confirmDisabled?: boolean
10
+ showCancel?: boolean
11
+ showClose?: boolean
12
+ hideHeader?: boolean
13
+ hideFooter?: boolean
14
+ side?: DrawerSide
15
+ title?: string
16
+ description?: string
17
+ confirmText?: string
18
+ cancelText?: string
19
+ confirmVariant?: ButtonVariants['variant']
20
+ cancelVariant?: ButtonVariants['variant']
21
+ class?: ClassValue
22
+ }
@@ -0,0 +1,145 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import type { DropdownItem } from './types'
3
+ import Button from '../Button/index.vue'
4
+ import Dropdown from './index.vue'
5
+
6
+ const meta = {
7
+ title: 'UI/Dropdown',
8
+ component: Dropdown,
9
+ } satisfies Meta<typeof Dropdown>
10
+
11
+ export default meta
12
+ type Story = StoryObj<typeof meta>
13
+
14
+ const basicMenus: DropdownItem[] = [
15
+ { label: 'Edit', icon: 'pencil' },
16
+ { label: 'Duplicate', icon: 'copy' },
17
+ { type: 'separator' },
18
+ { label: 'Delete', icon: 'trash-2', color: 'danger' },
19
+ ]
20
+
21
+ export const Default: Story = {
22
+ render: () => ({
23
+ components: { Dropdown, Button },
24
+ setup () {
25
+ const menus: DropdownItem[] = [
26
+ { label: 'Profile', icon: 'user' },
27
+ { label: 'Settings', icon: 'settings' },
28
+ { label: 'Admin Panel', icon: 'shield', disabled: true },
29
+ { type: 'separator' },
30
+ { label: 'Logout', icon: 'log-out' },
31
+ ]
32
+
33
+ const linkMenus: DropdownItem[] = [
34
+ { label: 'Documentation', icon: 'book-open', href: 'https://example.com/docs', target: '_blank' },
35
+ { label: 'Support', icon: 'life-buoy', href: 'https://example.com/support', target: '_blank' },
36
+ ]
37
+
38
+ return { basicMenus, menus, linkMenus }
39
+ },
40
+ template: `
41
+ <div class="space-y-10">
42
+ <!-- Hover Trigger -->
43
+ <section>
44
+ <h3 class="mb-4 text-lg font-medium">Hover Trigger</h3>
45
+ <Dropdown :menus="basicMenus" trigger="hover">
46
+ <Button variant="outline">Hover me</Button>
47
+ </Dropdown>
48
+ </section>
49
+
50
+ <!-- Click Trigger -->
51
+ <section>
52
+ <h3 class="mb-4 text-lg font-medium">Click Trigger</h3>
53
+ <Dropdown :menus="basicMenus" trigger="click">
54
+ <Button variant="outline">Click me</Button>
55
+ </Dropdown>
56
+ </section>
57
+
58
+ <!-- With Disabled Items -->
59
+ <section>
60
+ <h3 class="mb-4 text-lg font-medium">With Disabled Items</h3>
61
+ <Dropdown :menus="menus" trigger="click">
62
+ <Button variant="outline">Account</Button>
63
+ </Dropdown>
64
+ </section>
65
+
66
+ <!-- With Links -->
67
+ <section>
68
+ <h3 class="mb-4 text-lg font-medium">With Links</h3>
69
+ <Dropdown :menus="linkMenus" trigger="click">
70
+ <Button variant="outline">Resources</Button>
71
+ </Dropdown>
72
+ </section>
73
+ </div>
74
+ `,
75
+ }),
76
+ }
77
+
78
+ export const WithGroups: Story = {
79
+ render: () => ({
80
+ components: { Dropdown, Button },
81
+ setup () {
82
+ const groupedMenus: DropdownItem[] = [
83
+ { type: 'label', label: 'Organization' },
84
+ { label: 'Switch Org', icon: 'arrow-left-right' },
85
+ { type: 'separator' },
86
+ { type: 'label', label: 'Account' },
87
+ { label: 'Profile', icon: 'user' },
88
+ { label: 'Settings', icon: 'settings' },
89
+ { type: 'separator' },
90
+ { label: 'Logout', icon: 'log-out' },
91
+ ]
92
+
93
+ return { groupedMenus }
94
+ },
95
+ template: `
96
+ <Dropdown :menus="groupedMenus" trigger="click">
97
+ <Button variant="outline">Menu with Groups</Button>
98
+ </Dropdown>
99
+ `,
100
+ }),
101
+ }
102
+
103
+ export const WithCustomSlots: Story = {
104
+ render: () => ({
105
+ components: { Dropdown, Button },
106
+ setup () {
107
+ const customMenus: DropdownItem[] = [
108
+ {
109
+ type: 'custom-label',
110
+ slot: 'profile',
111
+ title: 'Demo User',
112
+ email: 'demo@example.com',
113
+ },
114
+ { type: 'separator' },
115
+ { label: 'Profile', icon: 'user' },
116
+ { label: 'Settings', icon: 'settings' },
117
+ { type: 'separator' },
118
+ {
119
+ type: 'custom-action',
120
+ slot: 'logout',
121
+ command: () => alert('Logged out'),
122
+ },
123
+ ]
124
+
125
+ return { customMenus }
126
+ },
127
+ template: `
128
+ <Dropdown :menus="customMenus" trigger="click">
129
+ <Button variant="outline">Custom Slots</Button>
130
+ <template #profile="{ item }">
131
+ <div class="flex flex-col gap-1 px-2 py-1.5">
132
+ <span class="font-semibold text-sm">{{ item.title }}</span>
133
+ <span class="text-xs text-muted-foreground">{{ item.email }}</span>
134
+ </div>
135
+ </template>
136
+ <template #logout>
137
+ <span class="flex items-center gap-2 text-danger font-semibold">
138
+ <span>🚪</span>
139
+ <span>Custom Logout</span>
140
+ </span>
141
+ </template>
142
+ </Dropdown>
143
+ `,
144
+ }),
145
+ }
@@ -0,0 +1,258 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ DropdownMenu,
4
+ DropdownMenuContent,
5
+ DropdownMenuItem,
6
+ DropdownMenuLabel,
7
+ DropdownMenuSeparator,
8
+ DropdownMenuTrigger,
9
+ } from '@polymarbot/nuxt-layer-shadcn-ui/app/components/shadcn/dropdown-menu'
10
+ import { cva } from 'class-variance-authority'
11
+ import type {
12
+ DropdownActionItem,
13
+ DropdownCustomActionItem,
14
+ DropdownProps,
15
+ } from './types'
16
+
17
+ const actionColorVariants = cva('', {
18
+ variants: {
19
+ color: {
20
+ default: '',
21
+ success: `
22
+ text-success
23
+ focus:bg-success/10 focus:text-success
24
+ `,
25
+ info: `
26
+ text-info
27
+ focus:bg-info/10 focus:text-info
28
+ `,
29
+ help: `
30
+ text-help
31
+ focus:bg-help/10 focus:text-help
32
+ `,
33
+ warn: `
34
+ text-warn
35
+ focus:bg-warn/10 focus:text-warn
36
+ `,
37
+ danger: `
38
+ text-danger
39
+ focus:bg-danger/10 focus:text-danger
40
+ `,
41
+ },
42
+ },
43
+ defaultVariants: { color: 'default' },
44
+ })
45
+
46
+ const props = withDefaults(defineProps<DropdownProps>(), {
47
+ menus: () => [],
48
+ trigger: 'hover',
49
+ side: undefined,
50
+ align: undefined,
51
+ sideOffset: undefined,
52
+ class: undefined,
53
+ })
54
+
55
+ defineSlots<{
56
+ default?: () => unknown
57
+ popup?: (props: { hide: () => void }) => unknown
58
+ [key: string]: ((props?: any) => unknown) | undefined
59
+ }>()
60
+
61
+ const { isMobile } = useDevice()
62
+
63
+ // Force click trigger on mobile devices for better touch experience
64
+ const effectiveTrigger = computed(() => {
65
+ return isMobile.value ? 'click' : props.trigger
66
+ })
67
+
68
+ const isOpen = ref(false)
69
+ let hideTimeout: ReturnType<typeof setTimeout> | null = null
70
+
71
+ const clearHideTimeout = () => {
72
+ if (hideTimeout) {
73
+ clearTimeout(hideTimeout)
74
+ hideTimeout = null
75
+ }
76
+ }
77
+
78
+ const hide = () => {
79
+ isOpen.value = false
80
+ }
81
+
82
+ const handleTriggerEnter = () => {
83
+ if (effectiveTrigger.value === 'hover') {
84
+ clearHideTimeout()
85
+ isOpen.value = true
86
+ }
87
+ }
88
+
89
+ const handleTriggerLeave = () => {
90
+ if (effectiveTrigger.value === 'hover') {
91
+ hideTimeout = setTimeout(hide, 100)
92
+ }
93
+ }
94
+
95
+ const handleMenuEnter = () => {
96
+ if (effectiveTrigger.value === 'hover') {
97
+ clearHideTimeout()
98
+ }
99
+ }
100
+
101
+ const handleMenuLeave = () => {
102
+ if (effectiveTrigger.value === 'hover') {
103
+ hideTimeout = setTimeout(hide, 100)
104
+ }
105
+ }
106
+
107
+ const handleItemAction = (
108
+ item: DropdownActionItem | DropdownCustomActionItem,
109
+ event?: Event,
110
+ ) => {
111
+ if (item.disabled) {
112
+ event?.preventDefault()
113
+ return
114
+ }
115
+ item.command?.()
116
+ hide()
117
+ }
118
+
119
+ onBeforeUnmount(() => {
120
+ clearHideTimeout()
121
+ })
122
+ </script>
123
+
124
+ <template>
125
+ <DropdownMenu
126
+ v-model:open="isOpen"
127
+ :modal="effectiveTrigger !== 'hover'"
128
+ >
129
+ <DropdownMenuTrigger
130
+ asChild
131
+ @mouseenter="handleTriggerEnter"
132
+ @mouseleave="handleTriggerLeave"
133
+ >
134
+ <slot />
135
+ </DropdownMenuTrigger>
136
+ <DropdownMenuContent
137
+ :side="side"
138
+ :align="align"
139
+ :sideOffset="sideOffset"
140
+ :class="props.class"
141
+ @mouseenter="handleMenuEnter"
142
+ @mouseleave="handleMenuLeave"
143
+ >
144
+ <!-- Custom popup content -->
145
+ <template v-if="$slots.popup">
146
+ <slot
147
+ name="popup"
148
+ :hide="hide"
149
+ />
150
+ </template>
151
+
152
+ <!-- Default menu dropdown -->
153
+ <template v-else>
154
+ <template
155
+ v-for="(item, index) in menus"
156
+ :key="index"
157
+ >
158
+ <!-- Built-in: separator -->
159
+ <DropdownMenuSeparator v-if="item.type === 'separator'" />
160
+ <!-- Built-in: group label -->
161
+ <DropdownMenuLabel
162
+ v-else-if="item.type === 'label'"
163
+ class="text-xs font-normal text-muted-foreground"
164
+ >
165
+ {{ item.label }}
166
+ </DropdownMenuLabel>
167
+ <!-- Custom label: content via named slot -->
168
+ <DropdownMenuLabel
169
+ v-else-if="item.type === 'custom-label'"
170
+ :class="cn('p-0 font-normal', item.class)"
171
+ >
172
+ <slot
173
+ :name="item.slot"
174
+ :item="item"
175
+ />
176
+ </DropdownMenuLabel>
177
+ <!-- Custom action: content via named slot -->
178
+ <DropdownMenuItem
179
+ v-else-if="item.type === 'custom-action'"
180
+ :disabled="item.disabled"
181
+ :class="cn(actionColorVariants({ color: item.color }), item.class)"
182
+ @click="handleItemAction(item, $event)"
183
+ >
184
+ <slot
185
+ :name="item.slot"
186
+ :item="item"
187
+ />
188
+ <Icon
189
+ v-if="item.active"
190
+ name="check"
191
+ class="ml-auto size-4"
192
+ />
193
+ </DropdownMenuItem>
194
+ <!-- Built-in: action (default) -->
195
+ <DropdownMenuItem
196
+ v-else
197
+ :disabled="item.disabled"
198
+ :asChild="!!item.href"
199
+ :class="cn(actionColorVariants({ color: item.color }), item.class)"
200
+ @click="!item.href && handleItemAction(item, $event)"
201
+ >
202
+ <template v-if="item.href">
203
+ <WebLink
204
+ unstyled
205
+ :href="item.href"
206
+ :target="item.target"
207
+ class="flex w-full items-center gap-2"
208
+ @click="handleItemAction(item, $event)"
209
+ >
210
+ <Icon
211
+ v-if="typeof item.icon === 'string'"
212
+ :name="item.icon"
213
+ />
214
+ <component
215
+ :is="item.icon"
216
+ v-else-if="item.icon"
217
+ class="size-4"
218
+ />
219
+ <span class="flex-1">
220
+ {{ item.label }}
221
+ </span>
222
+ <Icon
223
+ v-if="isUrl(item.href)"
224
+ name="external-link"
225
+ class="size-3.5 text-muted-foreground"
226
+ />
227
+ <Icon
228
+ v-if="item.active"
229
+ name="check"
230
+ class="size-4"
231
+ />
232
+ </WebLink>
233
+ </template>
234
+ <template v-else>
235
+ <Icon
236
+ v-if="typeof item.icon === 'string'"
237
+ :name="item.icon"
238
+ />
239
+ <component
240
+ :is="item.icon"
241
+ v-else-if="item.icon"
242
+ class="size-4"
243
+ />
244
+ <span class="flex-1">
245
+ {{ item.label }}
246
+ </span>
247
+ <Icon
248
+ v-if="item.active"
249
+ name="check"
250
+ class="size-4"
251
+ />
252
+ </template>
253
+ </DropdownMenuItem>
254
+ </template>
255
+ </template>
256
+ </DropdownMenuContent>
257
+ </DropdownMenu>
258
+ </template>
@@ -0,0 +1,87 @@
1
+ import type { Component } from 'vue'
2
+
3
+ export type DropdownItemColor = 'default' | 'success' | 'info' | 'help' | 'warn' | 'danger'
4
+
5
+ export interface DropdownActionItem {
6
+ /** Defaults to 'action' when omitted. */
7
+ type?: 'action'
8
+ /** Semantic color, matches project-wide color scheme. Defaults to 'default'. */
9
+ color?: DropdownItemColor
10
+ label?: string
11
+ icon?: string | Component
12
+ command?: () => void
13
+ disabled?: boolean
14
+ active?: boolean
15
+ class?: ClassValue
16
+ href?: string
17
+ target?: string
18
+ }
19
+
20
+ export interface DropdownSeparatorItem {
21
+ type: 'separator'
22
+ }
23
+
24
+ export interface DropdownLabelItem {
25
+ type: 'label'
26
+ label: string
27
+ }
28
+
29
+ /**
30
+ * Custom action item: rendered as DropdownMenuItem, content comes from
31
+ * a named slot (`slot` field). Arbitrary extra fields are passed through
32
+ * to the slot as `item` for rendering.
33
+ */
34
+ export interface DropdownCustomActionItem {
35
+ type: 'custom-action'
36
+ /** Semantic color, matches project-wide color scheme. Defaults to 'default'. */
37
+ color?: DropdownItemColor
38
+ slot: string
39
+ command?: () => void
40
+ disabled?: boolean
41
+ active?: boolean
42
+ class?: ClassValue
43
+ [field: string]: unknown
44
+ }
45
+
46
+ /**
47
+ * Custom label item: rendered as DropdownMenuLabel, content comes from
48
+ * a named slot (`slot` field). Arbitrary extra fields are passed through
49
+ * to the slot as `item` for rendering.
50
+ */
51
+ export interface DropdownCustomLabelItem {
52
+ type: 'custom-label'
53
+ slot: string
54
+ class?: ClassValue
55
+ [field: string]: unknown
56
+ }
57
+
58
+ /**
59
+ * Menu item discriminated by `type`.
60
+ *
61
+ * - 'action' (default): built-in action rendering.
62
+ * - 'separator': visual divider.
63
+ * - 'label': built-in group header.
64
+ * - 'custom-action' / 'custom-label': rendered via named `slot`, allowing
65
+ * arbitrary extra fields that the slot consumer can access via `item`.
66
+ */
67
+ export type DropdownItem
68
+ = | DropdownActionItem
69
+ | DropdownSeparatorItem
70
+ | DropdownLabelItem
71
+ | DropdownCustomActionItem
72
+ | DropdownCustomLabelItem
73
+
74
+ export interface DropdownProps {
75
+ /** Menu items to display in the dropdown (not required when using popup slot) */
76
+ menus?: DropdownItem[]
77
+ /** Trigger mode for showing the dropdown */
78
+ trigger?: 'click' | 'hover'
79
+ /** Preferred side of the trigger to render against. */
80
+ side?: 'top' | 'bottom' | 'left' | 'right'
81
+ /** Alignment against the trigger. */
82
+ align?: 'start' | 'center' | 'end'
83
+ /** Distance in pixels from the trigger. */
84
+ sideOffset?: number
85
+ /** Extra class for the dropdown content container. */
86
+ class?: ClassValue
87
+ }