@bl33dz/fa814698dcde12f86a37ac31dd3aedf9 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 (387) hide show
  1. package/dist/perisai-ui.es.js +6402 -0
  2. package/dist/perisai-ui.umd.js +1 -0
  3. package/dist/ui.css +1 -0
  4. package/fix_imports.sh +38 -0
  5. package/generate_index.cjs +52 -0
  6. package/package.json +46 -0
  7. package/package.json.bak +42 -0
  8. package/src/index.css +7704 -0
  9. package/src/index.ts +179 -0
  10. package/src/lib/utils.ts +6 -0
  11. package/src/shadcn/accordion/Accordion.vue +19 -0
  12. package/src/shadcn/accordion/AccordionContent.vue +23 -0
  13. package/src/shadcn/accordion/AccordionItem.vue +23 -0
  14. package/src/shadcn/accordion/AccordionTrigger.vue +38 -0
  15. package/src/shadcn/accordion/index.ts +4 -0
  16. package/src/shadcn/avatar/Avatar.vue +18 -0
  17. package/src/shadcn/avatar/AvatarFallback.vue +21 -0
  18. package/src/shadcn/avatar/AvatarImage.vue +16 -0
  19. package/src/shadcn/avatar/index.ts +3 -0
  20. package/src/shadcn/breadcrumb/Breadcrumb.vue +8 -0
  21. package/src/shadcn/breadcrumb/BreadcrumbEllipsis.vue +9 -0
  22. package/src/shadcn/breadcrumb/BreadcrumbItem.vue +8 -0
  23. package/src/shadcn/breadcrumb/BreadcrumbLink.vue +8 -0
  24. package/src/shadcn/breadcrumb/BreadcrumbList.vue +8 -0
  25. package/src/shadcn/breadcrumb/BreadcrumbPage.vue +8 -0
  26. package/src/shadcn/breadcrumb/BreadcrumbSeparator.vue +8 -0
  27. package/src/shadcn/breadcrumb/index.ts +7 -0
  28. package/src/shadcn/button/Button.vue +29 -0
  29. package/src/shadcn/button/index.ts +38 -0
  30. package/src/shadcn/calendar/Calendar.vue +64 -0
  31. package/src/shadcn/calendar/CalendarCell.vue +23 -0
  32. package/src/shadcn/calendar/CalendarCellTrigger.vue +39 -0
  33. package/src/shadcn/calendar/CalendarGrid.vue +23 -0
  34. package/src/shadcn/calendar/CalendarGridBody.vue +15 -0
  35. package/src/shadcn/calendar/CalendarGridHead.vue +16 -0
  36. package/src/shadcn/calendar/CalendarGridRow.vue +22 -0
  37. package/src/shadcn/calendar/CalendarHeadCell.vue +23 -0
  38. package/src/shadcn/calendar/CalendarHeader.vue +23 -0
  39. package/src/shadcn/calendar/CalendarHeading.vue +30 -0
  40. package/src/shadcn/calendar/CalendarNextButton.vue +32 -0
  41. package/src/shadcn/calendar/CalendarPrevButton.vue +32 -0
  42. package/src/shadcn/calendar/index.ts +12 -0
  43. package/src/shadcn/card/Card.vue +8 -0
  44. package/src/shadcn/card/CardContent.vue +8 -0
  45. package/src/shadcn/card/CardDescription.vue +8 -0
  46. package/src/shadcn/card/CardHeader.vue +8 -0
  47. package/src/shadcn/card/CardTitle.vue +8 -0
  48. package/src/shadcn/card/index.ts +5 -0
  49. package/src/shadcn/checkbox/Checkbox.vue +38 -0
  50. package/src/shadcn/checkbox/index.ts +1 -0
  51. package/src/shadcn/command/Command.vue +87 -0
  52. package/src/shadcn/command/CommandDialog.vue +31 -0
  53. package/src/shadcn/command/CommandEmpty.vue +27 -0
  54. package/src/shadcn/command/CommandGroup.vue +45 -0
  55. package/src/shadcn/command/CommandInput.vue +39 -0
  56. package/src/shadcn/command/CommandItem.vue +76 -0
  57. package/src/shadcn/command/CommandList.vue +25 -0
  58. package/src/shadcn/command/CommandSeparator.vue +21 -0
  59. package/src/shadcn/command/CommandShortcut.vue +17 -0
  60. package/src/shadcn/command/index.ts +25 -0
  61. package/src/shadcn/context-menu/ContextMenu.vue +18 -0
  62. package/src/shadcn/context-menu/ContextMenuCheckboxItem.vue +38 -0
  63. package/src/shadcn/context-menu/ContextMenuContent.vue +34 -0
  64. package/src/shadcn/context-menu/ContextMenuGroup.vue +15 -0
  65. package/src/shadcn/context-menu/ContextMenuItem.vue +39 -0
  66. package/src/shadcn/context-menu/ContextMenuLabel.vue +22 -0
  67. package/src/shadcn/context-menu/ContextMenuPortal.vue +15 -0
  68. package/src/shadcn/context-menu/ContextMenuRadioGroup.vue +22 -0
  69. package/src/shadcn/context-menu/ContextMenuRadioItem.vue +38 -0
  70. package/src/shadcn/context-menu/ContextMenuSeparator.vue +22 -0
  71. package/src/shadcn/context-menu/ContextMenuShortcut.vue +17 -0
  72. package/src/shadcn/context-menu/ContextMenuSub.vue +22 -0
  73. package/src/shadcn/context-menu/ContextMenuSubContent.vue +33 -0
  74. package/src/shadcn/context-menu/ContextMenuSubTrigger.vue +33 -0
  75. package/src/shadcn/context-menu/ContextMenuTrigger.vue +17 -0
  76. package/src/shadcn/context-menu/index.ts +15 -0
  77. package/src/shadcn/dialog/Dialog.vue +18 -0
  78. package/src/shadcn/dialog/DialogClose.vue +15 -0
  79. package/src/shadcn/dialog/DialogContent.vue +46 -0
  80. package/src/shadcn/dialog/DialogDescription.vue +23 -0
  81. package/src/shadcn/dialog/DialogFooter.vue +15 -0
  82. package/src/shadcn/dialog/DialogHeader.vue +17 -0
  83. package/src/shadcn/dialog/DialogOverlay.vue +21 -0
  84. package/src/shadcn/dialog/DialogScrollContent.vue +56 -0
  85. package/src/shadcn/dialog/DialogTitle.vue +23 -0
  86. package/src/shadcn/dialog/DialogTrigger.vue +15 -0
  87. package/src/shadcn/dialog/index.ts +10 -0
  88. package/src/shadcn/dropdown-menu/DropdownMenu.vue +18 -0
  89. package/src/shadcn/dropdown-menu/DropdownMenuCheckboxItem.vue +38 -0
  90. package/src/shadcn/dropdown-menu/DropdownMenuContent.vue +36 -0
  91. package/src/shadcn/dropdown-menu/DropdownMenuGroup.vue +15 -0
  92. package/src/shadcn/dropdown-menu/DropdownMenuItem.vue +31 -0
  93. package/src/shadcn/dropdown-menu/DropdownMenuLabel.vue +23 -0
  94. package/src/shadcn/dropdown-menu/DropdownMenuRadioGroup.vue +22 -0
  95. package/src/shadcn/dropdown-menu/DropdownMenuRadioItem.vue +39 -0
  96. package/src/shadcn/dropdown-menu/DropdownMenuSeparator.vue +24 -0
  97. package/src/shadcn/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  98. package/src/shadcn/dropdown-menu/DropdownMenuSub.vue +19 -0
  99. package/src/shadcn/dropdown-menu/DropdownMenuSubContent.vue +28 -0
  100. package/src/shadcn/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  101. package/src/shadcn/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  102. package/src/shadcn/dropdown-menu/index.ts +16 -0
  103. package/src/shadcn/menubar/Menubar.vue +33 -0
  104. package/src/shadcn/menubar/MenubarCheckboxItem.vue +38 -0
  105. package/src/shadcn/menubar/MenubarContent.vue +42 -0
  106. package/src/shadcn/menubar/MenubarGroup.vue +15 -0
  107. package/src/shadcn/menubar/MenubarItem.vue +37 -0
  108. package/src/shadcn/menubar/MenubarLabel.vue +20 -0
  109. package/src/shadcn/menubar/MenubarMenu.vue +15 -0
  110. package/src/shadcn/menubar/MenubarPortal.vue +5 -0
  111. package/src/shadcn/menubar/MenubarRadioGroup.vue +22 -0
  112. package/src/shadcn/menubar/MenubarRadioItem.vue +38 -0
  113. package/src/shadcn/menubar/MenubarSeparator.vue +21 -0
  114. package/src/shadcn/menubar/MenubarShortcut.vue +17 -0
  115. package/src/shadcn/menubar/MenubarSub.vue +23 -0
  116. package/src/shadcn/menubar/MenubarSubContent.vue +36 -0
  117. package/src/shadcn/menubar/MenubarSubTrigger.vue +28 -0
  118. package/src/shadcn/menubar/MenubarTrigger.vue +28 -0
  119. package/src/shadcn/menubar/index.ts +15 -0
  120. package/src/shadcn/navigation-menu/NavigationMenu.vue +35 -0
  121. package/src/shadcn/navigation-menu/NavigationMenuContent.vue +31 -0
  122. package/src/shadcn/navigation-menu/NavigationMenuIndicator.vue +23 -0
  123. package/src/shadcn/navigation-menu/NavigationMenuItem.vue +21 -0
  124. package/src/shadcn/navigation-menu/NavigationMenuLink.vue +26 -0
  125. package/src/shadcn/navigation-menu/NavigationMenuList.vue +28 -0
  126. package/src/shadcn/navigation-menu/NavigationMenuTrigger.vue +24 -0
  127. package/src/shadcn/navigation-menu/NavigationMenuViewport.vue +31 -0
  128. package/src/shadcn/navigation-menu/index.ts +14 -0
  129. package/src/shadcn/pagination/Pagination.vue +151 -0
  130. package/src/shadcn/pagination/PaginationContent.vue +22 -0
  131. package/src/shadcn/pagination/PaginationEllipsis.vue +25 -0
  132. package/src/shadcn/pagination/PaginationFirst.vue +33 -0
  133. package/src/shadcn/pagination/PaginationItem.vue +31 -0
  134. package/src/shadcn/pagination/PaginationLast.vue +33 -0
  135. package/src/shadcn/pagination/PaginationLink.vue +13 -0
  136. package/src/shadcn/pagination/PaginationNext.vue +22 -0
  137. package/src/shadcn/pagination/PaginationPrevious.vue +33 -0
  138. package/src/shadcn/pagination/index.ts +9 -0
  139. package/src/shadcn/popover/Popover.vue +18 -0
  140. package/src/shadcn/popover/PopoverAnchor.vue +15 -0
  141. package/src/shadcn/popover/PopoverContent.vue +46 -0
  142. package/src/shadcn/popover/PopoverTrigger.vue +15 -0
  143. package/src/shadcn/popover/index.ts +4 -0
  144. package/src/shadcn/radio-group/RadioGroup.vue +24 -0
  145. package/src/shadcn/radio-group/RadioGroupItem.vue +39 -0
  146. package/src/shadcn/radio-group/index.ts +2 -0
  147. package/src/shadcn/range-calendar/RangeCalendar.vue +71 -0
  148. package/src/shadcn/range-calendar/RangeCalendarCell.vue +23 -0
  149. package/src/shadcn/range-calendar/RangeCalendarCellTrigger.vue +41 -0
  150. package/src/shadcn/range-calendar/RangeCalendarGrid.vue +23 -0
  151. package/src/shadcn/range-calendar/RangeCalendarGridBody.vue +15 -0
  152. package/src/shadcn/range-calendar/RangeCalendarGridHead.vue +15 -0
  153. package/src/shadcn/range-calendar/RangeCalendarGridRow.vue +22 -0
  154. package/src/shadcn/range-calendar/RangeCalendarHeadCell.vue +23 -0
  155. package/src/shadcn/range-calendar/RangeCalendarHeader.vue +23 -0
  156. package/src/shadcn/range-calendar/RangeCalendarHeading.vue +30 -0
  157. package/src/shadcn/range-calendar/RangeCalendarNextButton.vue +32 -0
  158. package/src/shadcn/range-calendar/RangeCalendarPrevButton.vue +32 -0
  159. package/src/shadcn/range-calendar/index.ts +12 -0
  160. package/src/shadcn/select/Select.vue +18 -0
  161. package/src/shadcn/select/SelectContent.vue +52 -0
  162. package/src/shadcn/select/SelectGroup.vue +15 -0
  163. package/src/shadcn/select/SelectItem.vue +43 -0
  164. package/src/shadcn/select/SelectItemText.vue +15 -0
  165. package/src/shadcn/select/SelectLabel.vue +17 -0
  166. package/src/shadcn/select/SelectScrollDownButton.vue +26 -0
  167. package/src/shadcn/select/SelectScrollUpButton.vue +26 -0
  168. package/src/shadcn/select/SelectSeparator.vue +19 -0
  169. package/src/shadcn/select/SelectTrigger.vue +33 -0
  170. package/src/shadcn/select/SelectValue.vue +15 -0
  171. package/src/shadcn/select/index.ts +11 -0
  172. package/src/shadcn/separator/Separator.vue +31 -0
  173. package/src/shadcn/separator/index.ts +1 -0
  174. package/src/shadcn/sidebar/MenuGroup.vue +28 -0
  175. package/src/shadcn/sidebar/MenuItemRenderer.vue +23 -0
  176. package/src/shadcn/sidebar/Sidebar.vue +14 -0
  177. package/src/shadcn/sidebar/SidebarDemoContent.vue +26 -0
  178. package/src/shadcn/sidebar/SidebarMenuGroupWithLabel.vue +29 -0
  179. package/src/shadcn/sidebar/SidebarMenuItemWithIcon.vue +103 -0
  180. package/src/shadcn/sidebar/SidebarMenuSub.vue +10 -0
  181. package/src/shadcn/sidebar/SidebarMenuSubItemStyled.vue +38 -0
  182. package/src/shadcn/sidebar/SidebarTrigger.vue +8 -0
  183. package/src/shadcn/sidebar/index.ts +5 -0
  184. package/src/shadcn/slider/Slider.vue +43 -0
  185. package/src/shadcn/slider/index.ts +1 -0
  186. package/src/shadcn/sonner/Sonner.vue +19 -0
  187. package/src/shadcn/sonner/index.ts +1 -0
  188. package/src/shadcn/switch/Switch.vue +38 -0
  189. package/src/shadcn/switch/index.ts +1 -0
  190. package/src/shadcn/tabs/CardTabsContent.vue +16 -0
  191. package/src/shadcn/tabs/CornerCutTabsTrigger.vue +102 -0
  192. package/src/shadcn/tabs/GridTabsList.vue +30 -0
  193. package/src/shadcn/tabs/ScrollableTabsList.vue +8 -0
  194. package/src/shadcn/tabs/Tabs.vue +23 -0
  195. package/src/shadcn/tabs/TabsContent.vue +21 -0
  196. package/src/shadcn/tabs/TabsList.vue +24 -0
  197. package/src/shadcn/tabs/TabsTrigger.vue +30 -0
  198. package/src/shadcn/tabs/VerticalTabsList.vue +28 -0
  199. package/src/shadcn/tabs/VerticalTabsTrigger.vue +16 -0
  200. package/src/shadcn/tabs/index.ts +10 -0
  201. package/src/shadcn/toggle/Toggle.vue +35 -0
  202. package/src/shadcn/toggle/index.ts +28 -0
  203. package/src/shadcn/tooltip/Tooltip.vue +18 -0
  204. package/src/shadcn/tooltip/TooltipContent.vue +34 -0
  205. package/src/shadcn/tooltip/TooltipProvider.vue +14 -0
  206. package/src/shadcn/tooltip/TooltipTrigger.vue +15 -0
  207. package/src/shadcn/tooltip/index.ts +4 -0
  208. package/src/ui/InputOTP.vue +69 -0
  209. package/src/ui/InputOTPContext.ts +10 -0
  210. package/src/ui/InputOTPGroup.vue +7 -0
  211. package/src/ui/InputOTPSeparator.vue +8 -0
  212. package/src/ui/InputOTPSlot.vue +61 -0
  213. package/src/ui/PopoverContent.vue +27 -0
  214. package/src/ui/PopoverTrigger.vue +9 -0
  215. package/src/ui/SelectContent.vue +24 -0
  216. package/src/ui/SelectGroup.vue +22 -0
  217. package/src/ui/SelectItem.vue +25 -0
  218. package/src/ui/SelectLabel.vue +27 -0
  219. package/src/ui/SelectSeparator.vue +23 -0
  220. package/src/ui/SelectTrigger.vue +22 -0
  221. package/src/ui/SelectValue.vue +9 -0
  222. package/src/ui/SheetContent.vue +34 -0
  223. package/src/ui/SheetDescription.vue +9 -0
  224. package/src/ui/SheetHeader.vue +11 -0
  225. package/src/ui/SheetTitle.vue +9 -0
  226. package/src/ui/accordion-content.vue +21 -0
  227. package/src/ui/accordion-item.vue +18 -0
  228. package/src/ui/accordion-trigger.vue +14 -0
  229. package/src/ui/accordion.vue +9 -0
  230. package/src/ui/alert-actions.vue +13 -0
  231. package/src/ui/alert-description.vue +13 -0
  232. package/src/ui/alert-title.vue +13 -0
  233. package/src/ui/alert.vue +63 -0
  234. package/src/ui/avatar-fallback.vue +38 -0
  235. package/src/ui/avatar-group.vue +32 -0
  236. package/src/ui/avatar-image.vue +19 -0
  237. package/src/ui/avatar.vue +32 -0
  238. package/src/ui/badge.vue +90 -0
  239. package/src/ui/breadcrumb-item.vue +11 -0
  240. package/src/ui/breadcrumb-separator.vue +9 -0
  241. package/src/ui/breadcrumb.vue +11 -0
  242. package/src/ui/button.vue +76 -0
  243. package/src/ui/card-content.vue +16 -0
  244. package/src/ui/card-description.vue +16 -0
  245. package/src/ui/card-footer.vue +13 -0
  246. package/src/ui/card-header.vue +19 -0
  247. package/src/ui/card-title.vue +16 -0
  248. package/src/ui/card.vue +73 -0
  249. package/src/ui/category-breakdown-metric.vue +205 -0
  250. package/src/ui/checkbox.vue +84 -0
  251. package/src/ui/cn.ts +6 -0
  252. package/src/ui/dialog-body.vue +13 -0
  253. package/src/ui/dialog-close.vue +9 -0
  254. package/src/ui/dialog-content.vue +36 -0
  255. package/src/ui/dialog-description.vue +13 -0
  256. package/src/ui/dialog-footer.vue +13 -0
  257. package/src/ui/dialog-header.vue +13 -0
  258. package/src/ui/dialog-overlay.vue +14 -0
  259. package/src/ui/dialog-portal.vue +9 -0
  260. package/src/ui/dialog-title.vue +13 -0
  261. package/src/ui/dialog-trigger.vue +9 -0
  262. package/src/ui/dialog.vue +9 -0
  263. package/src/ui/dismissible-badges-demo.vue +94 -0
  264. package/src/ui/drawer-content.vue +53 -0
  265. package/src/ui/drawer-description.vue +23 -0
  266. package/src/ui/drawer-footer.vue +22 -0
  267. package/src/ui/drawer-header.vue +22 -0
  268. package/src/ui/drawer-title.vue +23 -0
  269. package/src/ui/drawer-trigger.vue +23 -0
  270. package/src/ui/drawer.vue +34 -0
  271. package/src/ui/dropdown-menu-checkbox-item.vue +27 -0
  272. package/src/ui/dropdown-menu-content.vue +23 -0
  273. package/src/ui/dropdown-menu-group.vue +7 -0
  274. package/src/ui/dropdown-menu-item.vue +19 -0
  275. package/src/ui/dropdown-menu-label.vue +17 -0
  276. package/src/ui/dropdown-menu-portal.vue +8 -0
  277. package/src/ui/dropdown-menu-radio-group.vue +14 -0
  278. package/src/ui/dropdown-menu-radio-item.vue +30 -0
  279. package/src/ui/dropdown-menu-separator.vue +13 -0
  280. package/src/ui/dropdown-menu-shortcut.vue +15 -0
  281. package/src/ui/dropdown-menu-sub-content.vue +8 -0
  282. package/src/ui/dropdown-menu-sub-trigger.vue +8 -0
  283. package/src/ui/dropdown-menu-sub.vue +8 -0
  284. package/src/ui/dropdown-menu-trigger.vue +8 -0
  285. package/src/ui/dropdown-menu.vue +9 -0
  286. package/src/ui/grouped-avatar.vue +19 -0
  287. package/src/ui/icons/Accessibility.vue +7 -0
  288. package/src/ui/icons/AlignLeft.vue +6 -0
  289. package/src/ui/icons/ArrowDown.vue +7 -0
  290. package/src/ui/icons/ArrowUp.vue +7 -0
  291. package/src/ui/icons/ArrowUpDown.vue +8 -0
  292. package/src/ui/icons/BookOpen.vue +6 -0
  293. package/src/ui/icons/Calendar.vue +9 -0
  294. package/src/ui/icons/Check.vue +6 -0
  295. package/src/ui/icons/ChevronRight.vue +6 -0
  296. package/src/ui/icons/Circle.vue +6 -0
  297. package/src/ui/icons/Copy.vue +7 -0
  298. package/src/ui/icons/Dot.vue +6 -0
  299. package/src/ui/icons/Edit.vue +6 -0
  300. package/src/ui/icons/FileText.vue +9 -0
  301. package/src/ui/icons/Folder.vue +6 -0
  302. package/src/ui/icons/FolderOpen.vue +7 -0
  303. package/src/ui/icons/Hash.vue +6 -0
  304. package/src/ui/icons/Home.vue +6 -0
  305. package/src/ui/icons/Minus.vue +6 -0
  306. package/src/ui/icons/MoreHorizontal.vue +8 -0
  307. package/src/ui/icons/Settings.vue +7 -0
  308. package/src/ui/icons/Slash.vue +6 -0
  309. package/src/ui/icons/Trash2.vue +6 -0
  310. package/src/ui/icons/Type.vue +6 -0
  311. package/src/ui/icons/User.vue +7 -0
  312. package/src/ui/input-otp.vue +52 -0
  313. package/src/ui/input.vue +98 -0
  314. package/src/ui/label.vue +19 -0
  315. package/src/ui/pagination.vue +41 -0
  316. package/src/ui/popover.vue +9 -0
  317. package/src/ui/progress.vue +67 -0
  318. package/src/ui/radio-group-item.vue +53 -0
  319. package/src/ui/radio-group.vue +27 -0
  320. package/src/ui/scrollable-tabs-list.vue +148 -0
  321. package/src/ui/select-multiple.vue +135 -0
  322. package/src/ui/select.vue +77 -0
  323. package/src/ui/separator.vue +60 -0
  324. package/src/ui/sheet.vue +50 -0
  325. package/src/ui/sidebar/BaseSidebar.vue +97 -0
  326. package/src/ui/sidebar/BasicSearch.vue +27 -0
  327. package/src/ui/sidebar/ResponsiveSearch.vue +54 -0
  328. package/src/ui/sidebar/Sidebar.vue +227 -0
  329. package/src/ui/sidebar/SidebarCollapseButton.vue +10 -0
  330. package/src/ui/sidebar/SidebarContent.vue +31 -0
  331. package/src/ui/sidebar/SidebarDescription.vue +10 -0
  332. package/src/ui/sidebar/SidebarExpandButton.vue +10 -0
  333. package/src/ui/sidebar/SidebarFooter.vue +10 -0
  334. package/src/ui/sidebar/SidebarGroup.vue +11 -0
  335. package/src/ui/sidebar/SidebarGroupContent.vue +10 -0
  336. package/src/ui/sidebar/SidebarGroupLabel.vue +7 -0
  337. package/src/ui/sidebar/SidebarHeader.vue +10 -0
  338. package/src/ui/sidebar/SidebarInset.vue +19 -0
  339. package/src/ui/sidebar/SidebarMenu.vue +7 -0
  340. package/src/ui/sidebar/SidebarMenuBadge.vue +7 -0
  341. package/src/ui/sidebar/SidebarMenuButton.vue +17 -0
  342. package/src/ui/sidebar/SidebarMenuItem.vue +10 -0
  343. package/src/ui/sidebar/SidebarMenuSub.vue +18 -0
  344. package/src/ui/sidebar/SidebarMenuSubContent.vue +10 -0
  345. package/src/ui/sidebar/SidebarMenuSubItem.vue +10 -0
  346. package/src/ui/sidebar/SidebarMenuSubTrigger.vue +10 -0
  347. package/src/ui/sidebar/SidebarProvider.vue +108 -0
  348. package/src/ui/sidebar/SidebarScrollArea.vue +10 -0
  349. package/src/ui/sidebar/SidebarSection.vue +10 -0
  350. package/src/ui/sidebar/SidebarSeparator.vue +8 -0
  351. package/src/ui/sidebar/SidebarShortcut.vue +10 -0
  352. package/src/ui/sidebar/SidebarTitle.vue +10 -0
  353. package/src/ui/sidebar/SidebarTrigger.vue +27 -0
  354. package/src/ui/sidebar/Wrapper.vue +12 -0
  355. package/src/ui/sidebar/context.ts +8 -0
  356. package/src/ui/sidebar/index.ts +27 -0
  357. package/src/ui/sidebar/sidebarStore.ts +40 -0
  358. package/src/ui/sidebar/types.ts +30 -0
  359. package/src/ui/sidebar/useAutoCollapse.ts +81 -0
  360. package/src/ui/sidebar.vue +24 -0
  361. package/src/ui/skeleton.vue +15 -0
  362. package/src/ui/slider.vue +32 -0
  363. package/src/ui/sonner.vue +67 -0
  364. package/src/ui/switch.vue +33 -0
  365. package/src/ui/tab-content.vue +28 -0
  366. package/src/ui/tab-list.vue +31 -0
  367. package/src/ui/tab-panel.vue +19 -0
  368. package/src/ui/tab-trigger.vue +34 -0
  369. package/src/ui/tab.vue +30 -0
  370. package/src/ui/table-body.vue +16 -0
  371. package/src/ui/table-caption.vue +20 -0
  372. package/src/ui/table-cell.vue +16 -0
  373. package/src/ui/table-footer.vue +16 -0
  374. package/src/ui/table-header.vue +132 -0
  375. package/src/ui/table-row.vue +16 -0
  376. package/src/ui/table.vue +55 -0
  377. package/src/ui/tabs.vue +33 -0
  378. package/src/ui/textarea.vue +91 -0
  379. package/src/ui/threat-gauge.vue +137 -0
  380. package/src/ui/toggle.vue +69 -0
  381. package/src/ui/tooltip-content.vue +52 -0
  382. package/src/ui/tooltip-provider.vue +13 -0
  383. package/src/ui/tooltip-root.vue +9 -0
  384. package/src/ui/tooltip-trigger.vue +13 -0
  385. package/src/ui/tooltip.vue +22 -0
  386. package/src/ui/utils.ts +6 -0
  387. package/vite.config.ts +39 -0
@@ -0,0 +1,205 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed } from 'vue'
3
+ import Tooltip from './tooltip.vue'
4
+ import TooltipContent from './tooltip-content.vue'
5
+ import TooltipProvider from './tooltip-provider.vue'
6
+ import TooltipTrigger from './tooltip-trigger.vue'
7
+
8
+ type Category = {
9
+ name: string
10
+ label?: string
11
+ color: string
12
+ }
13
+
14
+
15
+
16
+ const props = defineProps({
17
+ title: String,
18
+ iconName: String,
19
+ categories: {
20
+ type: Array as () => Category[],
21
+ required: true
22
+ },
23
+ data: {
24
+ type: Object as () => Record<string, number>,
25
+ required: true
26
+ },
27
+ isLoading: Boolean
28
+ })
29
+
30
+ const nonZeroCategories = computed(() => props.categories?.filter(c => (props.data[c.name] ?? 0) > 0))
31
+ const total = computed(() => nonZeroCategories.value?.reduce((sum, cat) => sum + (props.data[cat.name] || 0), 0))
32
+
33
+ const categoryPositions = computed(() => {
34
+ let cumulativePercentage = 0
35
+ return nonZeroCategories.value?.map((category, index) => {
36
+ const value = props.data[category.name] || 0
37
+ const proportion = total.value > 0 ? value / total.value : 0
38
+ const percentage = proportion * 100
39
+ const boundaryPosition = cumulativePercentage
40
+ cumulativePercentage += percentage
41
+ return {
42
+ ...category,
43
+ value,
44
+ boundaryPosition,
45
+ percentage,
46
+ index
47
+ }
48
+ })
49
+ })
50
+
51
+ const MIN_LABEL_WIDTH_PCT = 24
52
+ const showLabel = computed(() => {
53
+ const arr = categoryPositions.value?.map(() => true)
54
+ for (let i = 0; i < categoryPositions.value?.length - 1; i++) {
55
+ const cur = categoryPositions.value[i]
56
+ const next = categoryPositions.value[i + 1]
57
+ const segmentWidthPct = next.boundaryPosition - cur.boundaryPosition
58
+ if (segmentWidthPct < MIN_LABEL_WIDTH_PCT) {
59
+ arr[i] = false
60
+ }
61
+ }
62
+ if (categoryPositions.value?.length > 0) {
63
+ const last = categoryPositions.value[categoryPositions.value?.length - 1]
64
+ const lastWidthPct = 100 - last.boundaryPosition
65
+ if (lastWidthPct < MIN_LABEL_WIDTH_PCT) {
66
+ arr[categoryPositions.value?.length - 1] = false
67
+ }
68
+ }
69
+ return arr
70
+ })
71
+
72
+ const visibleCategories = computed(() => {
73
+ return categoryPositions.value?.map((category, index) => {
74
+ if (index === categoryPositions.value?.length - 1) {
75
+ return { ...category, isVisible: true }
76
+ }
77
+ const nextCategory = categoryPositions.value[index + 1]
78
+ const minSpacingNeeded = 15
79
+ const spaceAvailable = nextCategory.boundaryPosition - category.boundaryPosition
80
+ const isVisible = spaceAvailable >= minSpacingNeeded
81
+ return { ...category, isVisible }
82
+ })
83
+ })
84
+
85
+ const BAR_COUNT = 74
86
+ const bars = computed(() => {
87
+ const arr: Array<{ color: string; position: number }> = []
88
+ let currentPosition = 0
89
+ props.categories?.forEach(category => {
90
+ const value = props.data[category.name] || 0
91
+ const isNonZero = nonZeroCategories.value.find(c => c.name === category.name)
92
+ const proportion = total.value > 0 ? (isNonZero ? value / total.value : 0) : 0
93
+ const barCount = Math.round(proportion * BAR_COUNT)
94
+ for (let i = 0; i < barCount; i++) {
95
+ arr.push({ color: category.color, position: currentPosition + i })
96
+ }
97
+ currentPosition += barCount
98
+ })
99
+ while (arr?.length < BAR_COUNT) {
100
+ let lastNonZero
101
+ if (nonZeroCategories.value) lastNonZero = nonZeroCategories.value[nonZeroCategories.value?.length - 1]
102
+ const fallback = lastNonZero?.color || (props.categories && props.categories[props.categories?.length - 1]?.color) || '#9ca3af'
103
+ arr.push({ color: fallback, position: arr?.length })
104
+ }
105
+ return arr
106
+ })
107
+
108
+ const isEmpty = computed(() => total.value === 0)
109
+ </script>
110
+
111
+ <template>
112
+ <div v-if="isEmpty" class="relative w-full h-[75px] flex items-center justify-center bg-gray-800 rounded-md">
113
+ <span class="text-gray-400 text-sm">No data available</span>
114
+ </div>
115
+ <TooltipProvider v-else>
116
+ <Tooltip>
117
+ <TooltipTrigger as-child>
118
+ <div class="relative w-full h-[75px] cursor-help select-none">
119
+ <!-- Labels -->
120
+ <template v-for="(category, index) in categoryPositions" :key="category.name">
121
+ <div v-if="showLabel[index]">
122
+ <div
123
+ v-if="index !== categoryPositions?.length - 1"
124
+ class="absolute box-border content-stretch flex flex-col gap-[4px] py-0 top-[0.33px] items-start"
125
+ :style="{ left: category.boundaryPosition + '%', transform: 'translateX(8px)' }"
126
+ >
127
+ <p class="leading-[16px] text-[12px] text-muted-foreground">{{ category.label || category.name }}</p>
128
+ <p class="leading-[20px] text-[24px]" :style="{ color: category.color }">{{ category.value }}</p>
129
+ </div>
130
+ <div
131
+ v-else
132
+ class="absolute box-border content-stretch flex flex-col gap-[4px] py-0 top-[0.33px]"
133
+ :style="{
134
+ left: category.boundaryPosition + '%',
135
+ transform: (100 - category.boundaryPosition < 6) ? 'translateX(calc(-100% - 8px))' : 'translateX(8px)',
136
+ textAlign: (100 - category.boundaryPosition < 6) ? 'right' : 'left'
137
+ }"
138
+ >
139
+ <p class="leading-[16px] text-[12px] text-muted-foreground">{{ category.label || category.name }}</p>
140
+ <p class="leading-[20px] text-[24px]" :style="{ color: category.color }">{{ category.value }}</p>
141
+ </div>
142
+ </div>
143
+ </template>
144
+
145
+ <!-- Boundary separators -->
146
+ <template v-for="(category, index) in categoryPositions" :key="'line-' + index">
147
+ <div v-if="index !== 0" class="absolute flex h-[75px] items-center justify-center top-0 w-[0px] overflow-visible" :style="{ left: categoryPositions.slice(0, index).reduce((sum, cat) => sum + cat.percentage, 0) + '%' }">
148
+ <div class="flex-none" style="rotate: 90deg">
149
+ <div class="h-0 relative w-[75px]">
150
+ <div class="absolute bottom-0 left-0 right-0 top-[-1px]">
151
+ <svg class="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 75 1">
152
+ <line :stroke="category.color" x2="75" y1="0.5" y2="0.5" />
153
+ </svg>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ </div>
158
+ </template>
159
+
160
+ <!-- Left edge vertical line -->
161
+ <div class="absolute flex h-[75px] items-center justify-center left-0 top-0 w-[0px]">
162
+ <div class="flex-none" style="rotate: 90deg">
163
+ <div class="h-0 relative w-[75px]">
164
+ <div class="absolute bottom-0 left-0 right-0 top-[-1px]">
165
+ <svg class="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 75 1">
166
+ <line :stroke="(visibleCategories && visibleCategories[0]?.color) || (nonZeroCategories && nonZeroCategories[0]?.color) || '#9ca3af'" x2="75" y1="0.5" y2="0.5" />
167
+ </svg>
168
+ </div>
169
+ </div>
170
+ </div>
171
+ </div>
172
+
173
+ <!-- Bars -->
174
+ <div class="absolute box-border content-stretch flex items-center justify-between left-[0.33px] overflow-clip px-[2px] py-0 right-[0.33px] rounded-[2px] top-[51px]">
175
+ <div v-for="(bar, index) in bars" :key="index" class="flex items-center justify-center relative shrink-0">
176
+ <div class="flex-none rotate-[180deg] scale-y-[-100%]">
177
+ <div class="h-[24px] w-px" :style="{ backgroundColor: isEmpty ? '#9ca3af' : bar.color }" />
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </div>
182
+ </TooltipTrigger>
183
+ <TooltipContent variant="outline">
184
+ <div class="space-y-2">
185
+ <p class="font-medium text-sm">Threat Breakdown</p>
186
+ <div class="space-y-1">
187
+ <div v-for="category in props.categories" :key="category.name" class="flex items-center justify-between gap-4">
188
+ <div class="flex items-center gap-2">
189
+ <div class="w-2 h-2 rounded-full flex-shrink-0" :style="{ backgroundColor: category.color }" />
190
+ <span class="text-sm">{{ category.label || category.name }}</span>
191
+ </div>
192
+ <span class="text-sm font-mono" :style="{ color: category.color }">{{ props.data[category.name] || 0 }}</span>
193
+ </div>
194
+ </div>
195
+ <div class="border-t pt-2 mt-2">
196
+ <div class="flex items-center justify-between">
197
+ <span class="text-sm font-medium">Total</span>
198
+ <span class="text-sm font-mono font-medium">{{ props.categories.reduce((sum, c) => sum + (props.data[c.name] || 0), 0).toLocaleString() }}</span>
199
+ </div>
200
+ </div>
201
+ </div>
202
+ </TooltipContent>
203
+ </Tooltip>
204
+ </TooltipProvider>
205
+ </template>
@@ -0,0 +1,84 @@
1
+
2
+
3
+ <template>
4
+ <div v-if="label" class="space-y-2">
5
+ <div class="flex items-center space-x-2">
6
+ <span class="relative flex items-center">
7
+ <input
8
+ id="with-label"
9
+ data-slot="checkbox"
10
+ type="checkbox"
11
+ :checked="modelValue"
12
+ :disabled="disabled"
13
+ :aria-invalid="validationState === 'error' ? 'true' : undefined"
14
+ :class="checkboxClass"
15
+ v-bind="$attrs"
16
+ @change="$emit('update:modelValue', $event.target.checked)"
17
+ />
18
+ <span v-if="modelValue" data-slot="checkbox-indicator" class="absolute left-0 top-0 flex h-full w-full items-center justify-center text-current transition-none pointer-events-none">
19
+ <CheckIcon class="h-3.5 w-3.5" />
20
+ </span>
21
+ </span>
22
+ <Label htmlFor="with-label">{{ label }}</Label>
23
+ </div>
24
+ <p v-if="validationState === 'success' && validationText" class="text-sm text-green-600 flex items-center gap-1">
25
+ <CheckIcon class="h-4 w-4" />
26
+ {{ validationText }}
27
+ </p>
28
+ <p v-if="validationState === 'error' && validationText" class="text-sm text-red-600 flex items-center gap-1">
29
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01" /></svg>
30
+ {{ validationText }}
31
+ </p>
32
+ </div>
33
+ <div v-else class="space-y-2">
34
+ <span class="relative flex items-center">
35
+ <input
36
+ data-slot="checkbox"
37
+ type="checkbox"
38
+ :checked="modelValue"
39
+ :disabled="disabled"
40
+ :aria-invalid="validationState === 'error' ? 'true' : undefined"
41
+ :class="checkboxClass"
42
+ v-bind="$attrs"
43
+ @change="$emit('update:modelValue', $event.target.checked)"
44
+ />
45
+ <span v-if="modelValue" data-slot="checkbox-indicator" class="absolute left-0 top-0 flex h-full w-full items-center justify-center text-current transition-none pointer-events-none">
46
+ <CheckIcon class="h-3.5 w-3.5" />
47
+ </span>
48
+ </span>
49
+ <slot name="label" />
50
+ <p v-if="validationState === 'success' && validationText" class="text-sm text-green-600 flex items-center gap-1">
51
+ <CheckIcon class="h-4 w-4" />
52
+ {{ validationText }}
53
+ </p>
54
+ <p v-if="validationState === 'error' && validationText" class="text-sm text-red-600 flex items-center gap-1">
55
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01" /></svg>
56
+ {{ validationText }}
57
+ </p>
58
+ </div>
59
+ </template>
60
+
61
+ <script setup>
62
+ import { computed } from 'vue';
63
+ import Label from './label.vue';
64
+ import CheckIcon from './icons/Check.vue';
65
+
66
+ const props = defineProps({
67
+ modelValue: { type: Boolean, default: false },
68
+ disabled: { type: Boolean, default: false },
69
+ label: { type: String, default: '' },
70
+ validationState: { type: String, default: undefined }, // 'success' | 'error'
71
+ validationText: { type: String, default: '' },
72
+ id: { type: String, default: undefined },
73
+ class: { type: String, default: '' },
74
+ });
75
+
76
+ const computedId = computed(() => props.id || `checkbox-${Math.random().toString(36).substr(2, 9)}`);
77
+
78
+ const checkboxClass = computed(() => [
79
+ 'peer border bg-input-background dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
80
+ props.validationState === 'error' ? 'border-red-500 data-[state=checked]:bg-red-500' : '',
81
+ props.validationState === 'success' ? 'border-green-500 data-[state=checked]:bg-green-500' : '',
82
+ props.class,
83
+ ]);
84
+ </script>
package/src/ui/cn.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div
3
+ data-slot="dialog-body"
4
+ :class="['p-4 space-y-4', $attrs.class]"
5
+ v-bind="$attrs"
6
+ >
7
+ <slot />
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ // No additional logic needed
13
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <DialogClose v-bind="$attrs">
3
+ <slot />
4
+ </DialogClose>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { DialogClose } from "reka-ui"
9
+ </script>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <DialogContent data-slot="dialog-content" :class="[
3
+ 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200 sm:max-w-lg',
4
+ dialogSizeVariants[size],
5
+ $attrs.class
6
+ ]" v-bind="$attrs">
7
+ <slot />
8
+ <DialogClose
9
+ class="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4">
10
+ <X />
11
+ <span class="sr-only">Close</span>
12
+ </DialogClose>
13
+ </DialogContent>
14
+ </template>
15
+
16
+ <script setup>
17
+ import { DialogContent, DialogClose } from '@/shadcn/dialog';
18
+ import { X } from 'lucide-vue-next';
19
+
20
+ const props = defineProps({
21
+ size: {
22
+ type: String,
23
+ default: 'lg',
24
+ },
25
+ });
26
+
27
+ const dialogSizeVariants = {
28
+ sm: 'sm:max-w-sm max-w-[calc(100%-2rem)]',
29
+ md: 'sm:max-w-md max-w-[calc(100%-2rem)]',
30
+ lg: 'sm:max-w-lg max-w-[calc(100%-2rem)]',
31
+ xl: 'sm:max-w-xl max-w-[calc(100%-2rem)]',
32
+ '2xl': 'sm:max-w-2xl max-w-[calc(100%-2rem)]',
33
+ '4xl': 'sm:max-w-4xl max-w-[calc(100%-2rem)]',
34
+ full: 'sm:max-w-[calc(100vw-2rem)] max-w-[calc(100%-2rem)]',
35
+ };
36
+ </script>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <DialogDescription
3
+ data-slot="dialog-description"
4
+ :class="['text-muted-foreground text-sm', $attrs.class]"
5
+ v-bind="$attrs"
6
+ >
7
+ <slot />
8
+ </DialogDescription>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { DialogDescription } from '@/shadcn/dialog';
13
+ </script>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div
3
+ data-slot="dialog-footer"
4
+ :class="['flex flex-col-reverse gap-2 sm:flex-row sm:justify-end border-t p-2', $attrs.class]"
5
+ v-bind="$attrs"
6
+ >
7
+ <slot />
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ // No additional logic needed
13
+ </script>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div
3
+ data-slot="dialog-header"
4
+ :class="['flex flex-col gap-2 text-center pl-4 py-4 pr-5 sm:text-left border-b', $attrs.class]"
5
+ v-bind="$attrs"
6
+ >
7
+ <slot />
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ // No additional logic needed
13
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <DialogOverlay
3
+ data-slot="dialog-overlay"
4
+ :class="[
5
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
6
+ $attrs.class
7
+ ]"
8
+ v-bind="$attrs"
9
+ />
10
+ </template>
11
+
12
+ <script setup>
13
+ import { DialogOverlay } from 'reka-ui'
14
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <DialogPortal v-bind="$attrs">
3
+ <slot />
4
+ </DialogPortal>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { DialogPortal } from "reka-ui"
9
+ </script>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <DialogTitle
3
+ data-slot="dialog-title"
4
+ :class="['text-lg leading-none font-semibold', $attrs.class]"
5
+ v-bind="$attrs"
6
+ >
7
+ <slot />
8
+ </DialogTitle>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { DialogTitle } from '@/shadcn/dialog';
13
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <DialogTrigger v-bind="$attrs">
3
+ <slot />
4
+ </DialogTrigger>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { DialogTrigger } from '@/shadcn/dialog';
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <Dialog v-bind="$attrs">
3
+ <slot />
4
+ </Dialog>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { Dialog } from '@/shadcn/dialog';
9
+ </script>
@@ -0,0 +1,94 @@
1
+ <script setup>
2
+ import { ref } from 'vue';
3
+ import Badge from './badge.vue';
4
+ import Button from './button.vue';
5
+ import { CheckCircle } from 'lucide-vue-next';
6
+
7
+ const initialTags = [
8
+ { id: 1, label: 'React', variant: 'soft-primary', size: 'md' },
9
+ { id: 2, label: 'TypeScript', variant: 'soft-info', size: 'md' },
10
+ { id: 3, label: 'Design System', variant: 'soft-teal', size: 'md' },
11
+ { id: 4, label: 'UI/UX', variant: 'soft-pink', size: 'md' },
12
+ { id: 5, label: 'Accessibility', variant: 'soft-success', size: 'md' },
13
+ { id: 6, label: 'Performance', variant: 'soft-warning', size: 'md' },
14
+ ];
15
+
16
+ const initialFilters = [
17
+ { id: 1, label: 'Active', variant: 'soft-success', size: 'md' },
18
+ { id: 2, label: 'Pending', variant: 'soft-warning', size: 'md' },
19
+ { id: 3, label: 'Draft', variant: 'soft-neutral', size: 'md' },
20
+ ];
21
+
22
+ const tags = ref([...initialTags]);
23
+ const filters = ref([...initialFilters]);
24
+
25
+ function removeTag(id) {
26
+ tags.value = tags.value.filter(tag => tag.id !== id);
27
+ }
28
+ function removeFilter(id) {
29
+ filters.value = filters.value.filter(filter => filter.id !== id);
30
+ }
31
+ function resetTags() {
32
+ tags.value = [...initialTags];
33
+ }
34
+ function resetFilters() {
35
+ filters.value = [...initialFilters];
36
+ }
37
+ </script>
38
+
39
+ <template>
40
+ <div class="space-y-6 p-6 border rounded-lg">
41
+ <div>
42
+ <div class="flex items-center justify-between mb-3">
43
+ <h4 class="font-medium">Project Tags</h4>
44
+ <Button variant="outline" size="sm" @click="resetTags" :disabled="tags.length === initialTags.length">
45
+ Reset Tags
46
+ </Button>
47
+ </div>
48
+ <div class="flex flex-wrap gap-2 min-h-[2rem]">
49
+ <template v-if="tags.length > 0">
50
+ <Badge
51
+ v-for="tag in tags"
52
+ :key="tag.id"
53
+ :variant="tag.variant"
54
+ :size="tag.size"
55
+ dismissible
56
+ @dismiss="removeTag(tag.id)"
57
+ >
58
+ {{ tag.label }}
59
+ </Badge>
60
+ </template>
61
+ <p v-else class="text-sm text-muted-foreground">No tags selected</p>
62
+ </div>
63
+ </div>
64
+
65
+ <div>
66
+ <div class="flex items-center justify-between mb-3">
67
+ <h4 class="font-medium">Applied Filters</h4>
68
+ <Button variant="outline" size="sm" @click="resetFilters" :disabled="filters.length === initialFilters.length">
69
+ Reset Filters
70
+ </Button>
71
+ </div>
72
+ <div class="flex flex-wrap gap-2 min-h-[2rem]">
73
+ <template v-if="filters.length > 0">
74
+ <Badge
75
+ v-for="filter in filters"
76
+ :key="filter.id"
77
+ :variant="filter.variant"
78
+ :size="filter.size"
79
+ dismissible
80
+ @dismiss="removeFilter(filter.id)"
81
+ >
82
+ <CheckCircle />
83
+ {{ filter.label }}
84
+ </Badge>
85
+ </template>
86
+ <p v-else class="text-sm text-muted-foreground">No filters applied</p>
87
+ </div>
88
+ </div>
89
+
90
+ <div class="text-sm text-muted-foreground">
91
+ <p>Click the × button on any badge to remove it</p>
92
+ </div>
93
+ </div>
94
+ </template>
@@ -0,0 +1,53 @@
1
+ <script setup>
2
+ // DrawerContent.vue - Vue migration of DrawerContent from drawer.tsx
3
+ import { DrawerContent, DrawerOverlay, DrawerPortal, DrawerRoot, DrawerTrigger } from 'vaul-vue';
4
+ import { computed } from 'vue';
5
+
6
+ const props = defineProps({
7
+ size: {
8
+ type: String,
9
+ default: 'md',
10
+ },
11
+ direction: {
12
+ type: String,
13
+ default: 'right',
14
+ },
15
+ class: String,
16
+ });
17
+
18
+ const drawerSizeVariants = {
19
+ sm: 'sm:max-w-sm max-w-[calc(100%-2rem)]',
20
+ md: 'sm:max-w-md max-w-[calc(100%-2rem)]',
21
+ lg: 'sm:max-w-lg max-w-[calc(100%-2rem)]',
22
+ xl: 'sm:max-w-xl max-w-[calc(100%-2rem)]',
23
+ '2xl': 'sm:max-w-2xl max-w-[calc(100%-2rem)]',
24
+ '4xl': 'sm:max-w-4xl max-w-[calc(100%-2rem)]',
25
+ full: 'sm:max-w-[calc(100vw-2rem)] max-w-[calc(100%-2rem)]',
26
+ };
27
+
28
+ const contentClass = computed(() => {
29
+ return [
30
+ 'group/drawer-content bg-background fixed z-50 flex h-auto flex-col',
31
+ drawerSizeVariants[props.size],
32
+ props.class,
33
+ ].join(' ');
34
+ });
35
+ </script>
36
+
37
+ <template>
38
+ <DrawerPortal data-slot="drawer-portal">
39
+ <DrawerOverlay data-slot="drawer-overlay" />
40
+ <DrawerContent
41
+ v-bind="$attrs"
42
+ :class="contentClass"
43
+ data-slot="drawer-content"
44
+ >
45
+ <div class="bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
46
+ <slot />
47
+ </DrawerContent>
48
+ </DrawerPortal>
49
+ </template>
50
+
51
+ <style scoped>
52
+ /* Add any necessary styles for drawer content and variants here */
53
+ </style>
@@ -0,0 +1,23 @@
1
+ <script setup>
2
+ // DrawerDescription.vue - Vue migration of DrawerDescription from drawer.tsx
3
+ import { DrawerContent, DrawerOverlay, DrawerPortal, DrawerRoot, DrawerTrigger } from 'vaul-vue';
4
+ import { computed } from 'vue';
5
+
6
+ defineProps({
7
+ class: String,
8
+ });
9
+
10
+ const descClass = computed(() => {
11
+ return ['text-muted-foreground text-sm', $props.class].join(' ');
12
+ });
13
+ </script>
14
+
15
+ <template>
16
+ <VaulDrawerDescription v-bind="$attrs" :class="descClass" data-slot="drawer-description">
17
+ <slot />
18
+ </VaulDrawerDescription>
19
+ </template>
20
+
21
+ <style scoped>
22
+ /* Add any necessary styles for drawer description here */
23
+ </style>
@@ -0,0 +1,22 @@
1
+ <script setup>
2
+ // DrawerFooter.vue - Vue migration of DrawerFooter from drawer.tsx
3
+ import { computed } from 'vue';
4
+
5
+ defineProps({
6
+ class: String,
7
+ });
8
+
9
+ const footerClass = computed(() => {
10
+ return ['mt-auto flex flex-col gap-2 p-4', $props.class].join(' ');
11
+ });
12
+ </script>
13
+
14
+ <template>
15
+ <div :class="footerClass" data-slot="drawer-footer">
16
+ <slot />
17
+ </div>
18
+ </template>
19
+
20
+ <style scoped>
21
+ /* Add any necessary styles for drawer footer here */
22
+ </style>