create-nala 3.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 (316) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/index.js +227 -0
  4. package/package.json +48 -0
  5. package/template/.env.example +45 -0
  6. package/template/_gitignore +33 -0
  7. package/template/components.json +24 -0
  8. package/template/index.html +30 -0
  9. package/template/package.json +51 -0
  10. package/template/public/favicon.svg +15 -0
  11. package/template/public/icons.svg +24 -0
  12. package/template/public/img/avatar.webp +0 -0
  13. package/template/public/screenshot.png +0 -0
  14. package/template/src/App.vue +15 -0
  15. package/template/src/auto-imports.d.ts +691 -0
  16. package/template/src/components/AppLogo.vue +159 -0
  17. package/template/src/components/EmptyState.vue +60 -0
  18. package/template/src/components/PageHeader.vue +60 -0
  19. package/template/src/components/layout/AppNavbar.vue +159 -0
  20. package/template/src/components/layout/AppSidebar.vue +74 -0
  21. package/template/src/components/layout/CommandSearchDialog.vue +120 -0
  22. package/template/src/components/ui/accordion/Accordion.vue +15 -0
  23. package/template/src/components/ui/accordion/AccordionContent.vue +20 -0
  24. package/template/src/components/ui/accordion/AccordionItem.vue +20 -0
  25. package/template/src/components/ui/accordion/AccordionTrigger.vue +34 -0
  26. package/template/src/components/ui/accordion/index.ts +4 -0
  27. package/template/src/components/ui/alert/Alert.vue +21 -0
  28. package/template/src/components/ui/alert/AlertDescription.vue +17 -0
  29. package/template/src/components/ui/alert/AlertTitle.vue +17 -0
  30. package/template/src/components/ui/alert/index.ts +30 -0
  31. package/template/src/components/ui/alert-dialog/AlertDialog.vue +15 -0
  32. package/template/src/components/ui/alert-dialog/AlertDialogAction.vue +18 -0
  33. package/template/src/components/ui/alert-dialog/AlertDialogCancel.vue +25 -0
  34. package/template/src/components/ui/alert-dialog/AlertDialogContent.vue +44 -0
  35. package/template/src/components/ui/alert-dialog/AlertDialogDescription.vue +23 -0
  36. package/template/src/components/ui/alert-dialog/AlertDialogFooter.vue +22 -0
  37. package/template/src/components/ui/alert-dialog/AlertDialogHeader.vue +17 -0
  38. package/template/src/components/ui/alert-dialog/AlertDialogTitle.vue +21 -0
  39. package/template/src/components/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  40. package/template/src/components/ui/alert-dialog/index.ts +9 -0
  41. package/template/src/components/ui/avatar/Avatar.vue +50 -0
  42. package/template/src/components/ui/avatar/AvatarFallback.vue +21 -0
  43. package/template/src/components/ui/avatar/AvatarGroup.vue +69 -0
  44. package/template/src/components/ui/avatar/AvatarImage.vue +16 -0
  45. package/template/src/components/ui/avatar/index.ts +4 -0
  46. package/template/src/components/ui/badge/Badge.vue +40 -0
  47. package/template/src/components/ui/badge/index.ts +45 -0
  48. package/template/src/components/ui/breadcrumb/Breadcrumb.vue +17 -0
  49. package/template/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +23 -0
  50. package/template/src/components/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  51. package/template/src/components/ui/breadcrumb/BreadcrumbLink.vue +21 -0
  52. package/template/src/components/ui/breadcrumb/BreadcrumbList.vue +17 -0
  53. package/template/src/components/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  54. package/template/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +22 -0
  55. package/template/src/components/ui/breadcrumb/index.ts +7 -0
  56. package/template/src/components/ui/button/Button.spec.ts +46 -0
  57. package/template/src/components/ui/button/Button.vue +31 -0
  58. package/template/src/components/ui/button/index.ts +41 -0
  59. package/template/src/components/ui/calendar/Calendar.vue +106 -0
  60. package/template/src/components/ui/calendar/index.ts +1 -0
  61. package/template/src/components/ui/card/Card.vue +29 -0
  62. package/template/src/components/ui/card/CardAction.vue +17 -0
  63. package/template/src/components/ui/card/CardContent.vue +17 -0
  64. package/template/src/components/ui/card/CardDescription.vue +17 -0
  65. package/template/src/components/ui/card/CardFooter.vue +17 -0
  66. package/template/src/components/ui/card/CardHeader.vue +29 -0
  67. package/template/src/components/ui/card/CardTitle.vue +17 -0
  68. package/template/src/components/ui/card/index.ts +7 -0
  69. package/template/src/components/ui/chart/AreaChart.vue +143 -0
  70. package/template/src/components/ui/chart/BarChart.vue +142 -0
  71. package/template/src/components/ui/chart/DonutChart.vue +75 -0
  72. package/template/src/components/ui/chart/LineChart.vue +132 -0
  73. package/template/src/components/ui/chart/index.ts +4 -0
  74. package/template/src/components/ui/checkbox/Checkbox.vue +57 -0
  75. package/template/src/components/ui/checkbox/index.ts +1 -0
  76. package/template/src/components/ui/collapsible/Collapsible.vue +15 -0
  77. package/template/src/components/ui/collapsible/CollapsibleContent.vue +18 -0
  78. package/template/src/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
  79. package/template/src/components/ui/collapsible/index.ts +3 -0
  80. package/template/src/components/ui/command/Command.vue +88 -0
  81. package/template/src/components/ui/command/CommandDialog.vue +31 -0
  82. package/template/src/components/ui/command/CommandEmpty.vue +27 -0
  83. package/template/src/components/ui/command/CommandGroup.vue +45 -0
  84. package/template/src/components/ui/command/CommandInput.vue +39 -0
  85. package/template/src/components/ui/command/CommandItem.vue +76 -0
  86. package/template/src/components/ui/command/CommandList.vue +25 -0
  87. package/template/src/components/ui/command/CommandSeparator.vue +21 -0
  88. package/template/src/components/ui/command/CommandShortcut.vue +17 -0
  89. package/template/src/components/ui/command/index.ts +25 -0
  90. package/template/src/components/ui/context-menu/ContextMenu.vue +15 -0
  91. package/template/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +36 -0
  92. package/template/src/components/ui/context-menu/ContextMenuContent.vue +33 -0
  93. package/template/src/components/ui/context-menu/ContextMenuGroup.vue +12 -0
  94. package/template/src/components/ui/context-menu/ContextMenuItem.vue +36 -0
  95. package/template/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
  96. package/template/src/components/ui/context-menu/ContextMenuRadioGroup.vue +18 -0
  97. package/template/src/components/ui/context-menu/ContextMenuRadioItem.vue +36 -0
  98. package/template/src/components/ui/context-menu/ContextMenuSeparator.vue +18 -0
  99. package/template/src/components/ui/context-menu/ContextMenuShortcut.vue +17 -0
  100. package/template/src/components/ui/context-menu/ContextMenuSub.vue +15 -0
  101. package/template/src/components/ui/context-menu/ContextMenuSubContent.vue +36 -0
  102. package/template/src/components/ui/context-menu/ContextMenuSubTrigger.vue +32 -0
  103. package/template/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
  104. package/template/src/components/ui/context-menu/index.ts +14 -0
  105. package/template/src/components/ui/date-picker/DatePicker.vue +233 -0
  106. package/template/src/components/ui/date-picker/index.ts +1 -0
  107. package/template/src/components/ui/dialog/Dialog.vue +19 -0
  108. package/template/src/components/ui/dialog/DialogClose.vue +15 -0
  109. package/template/src/components/ui/dialog/DialogContent.vue +53 -0
  110. package/template/src/components/ui/dialog/DialogDescription.vue +23 -0
  111. package/template/src/components/ui/dialog/DialogFooter.vue +27 -0
  112. package/template/src/components/ui/dialog/DialogHeader.vue +17 -0
  113. package/template/src/components/ui/dialog/DialogOverlay.vue +21 -0
  114. package/template/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  115. package/template/src/components/ui/dialog/DialogTitle.vue +23 -0
  116. package/template/src/components/ui/dialog/DialogTrigger.vue +15 -0
  117. package/template/src/components/ui/dialog/index.ts +10 -0
  118. package/template/src/components/ui/dropdown-menu/DropdownMenu.vue +19 -0
  119. package/template/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  120. package/template/src/components/ui/dropdown-menu/DropdownMenuContent.vue +41 -0
  121. package/template/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
  122. package/template/src/components/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
  123. package/template/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
  124. package/template/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  125. package/template/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  126. package/template/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  127. package/template/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  128. package/template/src/components/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  129. package/template/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  130. package/template/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  131. package/template/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  132. package/template/src/components/ui/dropdown-menu/index.ts +16 -0
  133. package/template/src/components/ui/form/FormControl.vue +17 -0
  134. package/template/src/components/ui/form/FormDescription.vue +21 -0
  135. package/template/src/components/ui/form/FormItem.vue +23 -0
  136. package/template/src/components/ui/form/FormLabel.vue +25 -0
  137. package/template/src/components/ui/form/FormMessage.vue +23 -0
  138. package/template/src/components/ui/form/index.ts +7 -0
  139. package/template/src/components/ui/form/injectionKeys.ts +4 -0
  140. package/template/src/components/ui/form/useFormField.ts +30 -0
  141. package/template/src/components/ui/hover-card/HoverCard.vue +19 -0
  142. package/template/src/components/ui/hover-card/HoverCardContent.vue +43 -0
  143. package/template/src/components/ui/hover-card/HoverCardTrigger.vue +15 -0
  144. package/template/src/components/ui/hover-card/index.ts +3 -0
  145. package/template/src/components/ui/index.ts +47 -0
  146. package/template/src/components/ui/input/Input.vue +33 -0
  147. package/template/src/components/ui/input/InputAddon.vue +29 -0
  148. package/template/src/components/ui/input/InputGroup.vue +17 -0
  149. package/template/src/components/ui/input/InputIcon.vue +29 -0
  150. package/template/src/components/ui/input/index.ts +4 -0
  151. package/template/src/components/ui/kbd/Kbd.vue +30 -0
  152. package/template/src/components/ui/kbd/index.ts +1 -0
  153. package/template/src/components/ui/label/Label.vue +26 -0
  154. package/template/src/components/ui/label/index.ts +1 -0
  155. package/template/src/components/ui/loading-bar/LoadingBar.vue +41 -0
  156. package/template/src/components/ui/loading-bar/index.ts +2 -0
  157. package/template/src/components/ui/pagination/Pagination.vue +26 -0
  158. package/template/src/components/ui/pagination/PaginationContent.vue +22 -0
  159. package/template/src/components/ui/pagination/PaginationEllipsis.vue +25 -0
  160. package/template/src/components/ui/pagination/PaginationFirst.vue +33 -0
  161. package/template/src/components/ui/pagination/PaginationItem.vue +34 -0
  162. package/template/src/components/ui/pagination/PaginationLast.vue +33 -0
  163. package/template/src/components/ui/pagination/PaginationNext.vue +33 -0
  164. package/template/src/components/ui/pagination/PaginationPrevious.vue +33 -0
  165. package/template/src/components/ui/pagination/index.ts +8 -0
  166. package/template/src/components/ui/pin-input/PinInput.vue +28 -0
  167. package/template/src/components/ui/pin-input/PinInputGroup.vue +18 -0
  168. package/template/src/components/ui/pin-input/PinInputInput.vue +24 -0
  169. package/template/src/components/ui/pin-input/PinInputSeparator.vue +21 -0
  170. package/template/src/components/ui/pin-input/index.ts +4 -0
  171. package/template/src/components/ui/popover/Popover.vue +19 -0
  172. package/template/src/components/ui/popover/PopoverAnchor.vue +15 -0
  173. package/template/src/components/ui/popover/PopoverContent.vue +45 -0
  174. package/template/src/components/ui/popover/PopoverTrigger.vue +15 -0
  175. package/template/src/components/ui/popover/index.ts +4 -0
  176. package/template/src/components/ui/progress/Progress.vue +35 -0
  177. package/template/src/components/ui/progress/index.ts +1 -0
  178. package/template/src/components/ui/radio-group/RadioGroup.vue +23 -0
  179. package/template/src/components/ui/radio-group/RadioGroupItem.vue +30 -0
  180. package/template/src/components/ui/radio-group/index.ts +2 -0
  181. package/template/src/components/ui/scroll-area/ScrollArea.vue +40 -0
  182. package/template/src/components/ui/scroll-area/ScrollBar.vue +44 -0
  183. package/template/src/components/ui/scroll-area/index.ts +2 -0
  184. package/template/src/components/ui/select/Select.vue +19 -0
  185. package/template/src/components/ui/select/SelectContent.vue +51 -0
  186. package/template/src/components/ui/select/SelectGroup.vue +15 -0
  187. package/template/src/components/ui/select/SelectItem.vue +44 -0
  188. package/template/src/components/ui/select/SelectItemText.vue +15 -0
  189. package/template/src/components/ui/select/SelectLabel.vue +17 -0
  190. package/template/src/components/ui/select/SelectScrollDownButton.vue +26 -0
  191. package/template/src/components/ui/select/SelectScrollUpButton.vue +26 -0
  192. package/template/src/components/ui/select/SelectSeparator.vue +19 -0
  193. package/template/src/components/ui/select/SelectTrigger.vue +33 -0
  194. package/template/src/components/ui/select/SelectValue.vue +15 -0
  195. package/template/src/components/ui/select/index.ts +11 -0
  196. package/template/src/components/ui/separator/Separator.vue +29 -0
  197. package/template/src/components/ui/separator/index.ts +1 -0
  198. package/template/src/components/ui/sheet/Sheet.vue +19 -0
  199. package/template/src/components/ui/sheet/SheetClose.vue +15 -0
  200. package/template/src/components/ui/sheet/SheetContent.vue +62 -0
  201. package/template/src/components/ui/sheet/SheetDescription.vue +21 -0
  202. package/template/src/components/ui/sheet/SheetFooter.vue +16 -0
  203. package/template/src/components/ui/sheet/SheetHeader.vue +15 -0
  204. package/template/src/components/ui/sheet/SheetOverlay.vue +21 -0
  205. package/template/src/components/ui/sheet/SheetTitle.vue +21 -0
  206. package/template/src/components/ui/sheet/SheetTrigger.vue +15 -0
  207. package/template/src/components/ui/sheet/index.ts +8 -0
  208. package/template/src/components/ui/sidebar/Sidebar.vue +113 -0
  209. package/template/src/components/ui/sidebar/SidebarContent.vue +18 -0
  210. package/template/src/components/ui/sidebar/SidebarControl.vue +53 -0
  211. package/template/src/components/ui/sidebar/SidebarFooter.vue +18 -0
  212. package/template/src/components/ui/sidebar/SidebarGroup.vue +18 -0
  213. package/template/src/components/ui/sidebar/SidebarGroupAction.vue +27 -0
  214. package/template/src/components/ui/sidebar/SidebarGroupContent.vue +18 -0
  215. package/template/src/components/ui/sidebar/SidebarGroupLabel.vue +25 -0
  216. package/template/src/components/ui/sidebar/SidebarHeader.vue +18 -0
  217. package/template/src/components/ui/sidebar/SidebarInput.vue +22 -0
  218. package/template/src/components/ui/sidebar/SidebarInset.vue +21 -0
  219. package/template/src/components/ui/sidebar/SidebarMenu.vue +18 -0
  220. package/template/src/components/ui/sidebar/SidebarMenuAction.vue +35 -0
  221. package/template/src/components/ui/sidebar/SidebarMenuBadge.vue +26 -0
  222. package/template/src/components/ui/sidebar/SidebarMenuButton.vue +48 -0
  223. package/template/src/components/ui/sidebar/SidebarMenuButtonChild.vue +36 -0
  224. package/template/src/components/ui/sidebar/SidebarMenuItem.vue +18 -0
  225. package/template/src/components/ui/sidebar/SidebarMenuSkeleton.vue +35 -0
  226. package/template/src/components/ui/sidebar/SidebarMenuSub.vue +22 -0
  227. package/template/src/components/ui/sidebar/SidebarMenuSubButton.vue +36 -0
  228. package/template/src/components/ui/sidebar/SidebarMenuSubItem.vue +18 -0
  229. package/template/src/components/ui/sidebar/SidebarProvider.vue +136 -0
  230. package/template/src/components/ui/sidebar/SidebarRail.vue +33 -0
  231. package/template/src/components/ui/sidebar/SidebarSeparator.vue +19 -0
  232. package/template/src/components/ui/sidebar/SidebarTrigger.vue +27 -0
  233. package/template/src/components/ui/sidebar/index.ts +61 -0
  234. package/template/src/components/ui/sidebar/utils.ts +27 -0
  235. package/template/src/components/ui/skeleton/Skeleton.vue +17 -0
  236. package/template/src/components/ui/skeleton/index.ts +1 -0
  237. package/template/src/components/ui/slider/Slider.vue +42 -0
  238. package/template/src/components/ui/slider/index.ts +1 -0
  239. package/template/src/components/ui/sonner/Sonner.vue +42 -0
  240. package/template/src/components/ui/sonner/index.ts +2 -0
  241. package/template/src/components/ui/stepper/Stepper.vue +102 -0
  242. package/template/src/components/ui/stepper/index.ts +1 -0
  243. package/template/src/components/ui/switch/Switch.vue +38 -0
  244. package/template/src/components/ui/switch/index.ts +1 -0
  245. package/template/src/components/ui/table/Table.vue +16 -0
  246. package/template/src/components/ui/table/TableBody.vue +17 -0
  247. package/template/src/components/ui/table/TableCaption.vue +17 -0
  248. package/template/src/components/ui/table/TableCell.vue +22 -0
  249. package/template/src/components/ui/table/TableEmpty.vue +34 -0
  250. package/template/src/components/ui/table/TableFooter.vue +17 -0
  251. package/template/src/components/ui/table/TableHead.vue +17 -0
  252. package/template/src/components/ui/table/TableHeader.vue +17 -0
  253. package/template/src/components/ui/table/TableRow.vue +17 -0
  254. package/template/src/components/ui/table/index.ts +9 -0
  255. package/template/src/components/ui/table/utils.ts +10 -0
  256. package/template/src/components/ui/tabs/Tabs.vue +24 -0
  257. package/template/src/components/ui/tabs/TabsContent.vue +21 -0
  258. package/template/src/components/ui/tabs/TabsList.vue +24 -0
  259. package/template/src/components/ui/tabs/TabsTrigger.vue +26 -0
  260. package/template/src/components/ui/tabs/index.ts +4 -0
  261. package/template/src/components/ui/textarea/Textarea.vue +28 -0
  262. package/template/src/components/ui/textarea/index.ts +1 -0
  263. package/template/src/components/ui/timeline/Timeline.vue +73 -0
  264. package/template/src/components/ui/timeline/index.ts +1 -0
  265. package/template/src/components/ui/toggle/Toggle.vue +35 -0
  266. package/template/src/components/ui/toggle/index.ts +28 -0
  267. package/template/src/components/ui/toggle-group/ToggleGroup.vue +41 -0
  268. package/template/src/components/ui/toggle-group/ToggleGroupItem.vue +43 -0
  269. package/template/src/components/ui/toggle-group/index.ts +12 -0
  270. package/template/src/components/ui/tooltip/Tooltip.vue +19 -0
  271. package/template/src/components/ui/tooltip/TooltipContent.vue +34 -0
  272. package/template/src/components/ui/tooltip/TooltipProvider.vue +14 -0
  273. package/template/src/components/ui/tooltip/TooltipTrigger.vue +15 -0
  274. package/template/src/components/ui/tooltip/index.ts +4 -0
  275. package/template/src/components.d.ts +228 -0
  276. package/template/src/composables/useFormatter.ts +105 -0
  277. package/template/src/composables/useThemeConfig.ts +252 -0
  278. package/template/src/layouts/AdminLayout.vue +55 -0
  279. package/template/src/layouts/AuthLayout.vue +42 -0
  280. package/template/src/lib/axios.spec.ts +46 -0
  281. package/template/src/lib/axios.ts +243 -0
  282. package/template/src/lib/formatters.spec.ts +137 -0
  283. package/template/src/lib/formatters.ts +332 -0
  284. package/template/src/lib/loading-bar.ts +103 -0
  285. package/template/src/lib/utils.spec.ts +26 -0
  286. package/template/src/lib/utils.ts +7 -0
  287. package/template/src/lib/validation.spec.ts +78 -0
  288. package/template/src/main.ts +13 -0
  289. package/template/src/router/index.ts +147 -0
  290. package/template/src/services/auth.service.spec.ts +93 -0
  291. package/template/src/services/auth.service.ts +243 -0
  292. package/template/src/services/index.ts +3 -0
  293. package/template/src/services/types.ts +28 -0
  294. package/template/src/services/user.service.spec.ts +91 -0
  295. package/template/src/services/user.service.ts +283 -0
  296. package/template/src/stores/auth.spec.ts +52 -0
  297. package/template/src/stores/auth.ts +130 -0
  298. package/template/src/style.css +587 -0
  299. package/template/src/views/_starter/BlankView.vue +47 -0
  300. package/template/src/views/auth/ConfirmEmailView.vue +209 -0
  301. package/template/src/views/auth/ForgotPasswordView.vue +151 -0
  302. package/template/src/views/auth/LockScreenView.vue +175 -0
  303. package/template/src/views/auth/LoginView.vue +54 -0
  304. package/template/src/views/auth/RegisterView.vue +265 -0
  305. package/template/src/views/auth/ResetPasswordView.vue +260 -0
  306. package/template/src/views/auth/VerifyOtpView.vue +261 -0
  307. package/template/src/views/dashboard/IndexView.vue +159 -0
  308. package/template/src/views/errors/ComingSoonView.vue +241 -0
  309. package/template/src/views/errors/MaintenanceView.vue +252 -0
  310. package/template/src/views/errors/NotFoundView.vue +81 -0
  311. package/template/src/views/errors/ServerErrorView.vue +101 -0
  312. package/template/src/views/errors/UnauthorizedView.vue +64 -0
  313. package/template/tsconfig.app.json +27 -0
  314. package/template/tsconfig.json +19 -0
  315. package/template/tsconfig.node.json +23 -0
  316. package/template/vite.config.ts +46 -0
@@ -0,0 +1,142 @@
1
+ <script setup lang="ts">
2
+ import { VisXYContainer, VisGroupedBar, VisStackedBar, VisAxis, VisTooltip } from '@unovis/vue'
3
+ import { GroupedBar, StackedBar } from '@unovis/ts'
4
+
5
+ interface Props {
6
+ data: Record<string, any>[]
7
+ index: string
8
+ categories: string[]
9
+ type?: 'grouped' | 'stacked'
10
+ colors?: string[]
11
+ showGridLine?: boolean
12
+ showXAxis?: boolean
13
+ showYAxis?: boolean
14
+ showTooltip?: boolean
15
+ showLegend?: boolean
16
+ roundedCorners?: number
17
+ yFormatter?: (tick: number) => string
18
+ xFormatter?: (tick: number, i?: number) => string
19
+ }
20
+
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ type: 'grouped',
23
+ colors: () => ['var(--primary)', '#3b82f6', '#10b981', '#f59e0b', '#8b5cf6'],
24
+ showGridLine: false,
25
+ showXAxis: true,
26
+ showYAxis: true,
27
+ showTooltip: true,
28
+ showLegend: false,
29
+ roundedCorners: 4,
30
+ })
31
+
32
+ const x = (_: any, i: number) => i
33
+ const y = props.categories.map((c) => (d: any) => d[c])
34
+
35
+ function getColor(_: any, i: number): string {
36
+ return props.colors[i % props.colors.length]
37
+ }
38
+
39
+ const defaultYFormatter = (tick: number) => {
40
+ if (tick >= 1_000_000) return `${(tick / 1_000_000).toFixed(1)}M`
41
+ if (tick >= 1_000) return `${(tick / 1_000).toFixed(0)}k`
42
+ return `${tick}`
43
+ }
44
+
45
+ const defaultXFormatter = (i: number) => {
46
+ const d = props.data[i]
47
+ return d ? String(d[props.index]) : ''
48
+ }
49
+
50
+ const tooltipTemplate = (d: Record<string, any>) => {
51
+ if (!d) return ''
52
+ const title = d[props.index] ?? ''
53
+ const rows = props.categories
54
+ .map((cat, idx) => {
55
+ const val = d[cat]
56
+ const color = props.colors[idx % props.colors.length]
57
+ const formattedVal = typeof val === 'number' ? val.toLocaleString() : val
58
+ return `
59
+ <div class="flex items-center justify-between gap-4 text-xs py-0.5">
60
+ <span class="flex items-center gap-1.5 text-muted-foreground capitalize">
61
+ <span class="h-2 w-2 rounded-full" style="background-color: ${color}"></span>
62
+ ${cat}
63
+ </span>
64
+ <span class="font-mono font-bold text-foreground">${formattedVal}</span>
65
+ </div>
66
+ `
67
+ })
68
+ .join('')
69
+
70
+ return `
71
+ <div class="rounded-lg border border-border bg-popover/95 backdrop-blur-md px-3 py-2 text-xs shadow-md">
72
+ <div class="font-bold text-foreground mb-1.5 pb-1 border-b border-border/40">${title}</div>
73
+ <div class="space-y-0.5">${rows}</div>
74
+ </div>
75
+ `
76
+ }
77
+ </script>
78
+
79
+ <template>
80
+ <div class="w-full h-full flex flex-col">
81
+ <!-- Optional Legend -->
82
+ <div v-if="showLegend" class="flex flex-wrap items-center gap-4 mb-3 text-xs">
83
+ <div
84
+ v-for="(cat, idx) in categories"
85
+ :key="cat"
86
+ class="flex items-center gap-1.5 text-muted-foreground font-medium capitalize"
87
+ >
88
+ <span class="h-2.5 w-2.5 rounded-full" :style="{ backgroundColor: colors[idx % colors.length] }" />
89
+ <span>{{ cat }}</span>
90
+ </div>
91
+ </div>
92
+
93
+ <!-- Chart Container -->
94
+ <div class="flex-1 w-full min-h-45 relative">
95
+ <VisXYContainer :data="data" class="w-full h-full">
96
+ <VisGroupedBar
97
+ v-if="type === 'grouped'"
98
+ :x="x"
99
+ :y="y"
100
+ :color="getColor"
101
+ :roundedCorners="roundedCorners"
102
+ />
103
+ <VisStackedBar
104
+ v-else
105
+ :x="x"
106
+ :y="y"
107
+ :color="getColor"
108
+ :roundedCorners="roundedCorners"
109
+ />
110
+
111
+ <VisAxis
112
+ v-if="showXAxis"
113
+ type="x"
114
+ :tickFormat="xFormatter || defaultXFormatter"
115
+ :numTicks="data.length"
116
+ :gridLine="false"
117
+ :domainLine="false"
118
+ :tickLine="false"
119
+ tickTextColor="var(--muted-foreground)"
120
+ />
121
+ <VisAxis
122
+ v-if="showYAxis"
123
+ type="y"
124
+ :tickFormat="yFormatter || defaultYFormatter"
125
+ :numTicks="4"
126
+ :gridLine="showGridLine"
127
+ :domainLine="false"
128
+ :tickLine="false"
129
+ tickTextColor="var(--muted-foreground)"
130
+ />
131
+
132
+ <VisTooltip
133
+ v-if="showTooltip"
134
+ :attributes="{ 'data-unovis-tooltip': '' }"
135
+ :triggers="{
136
+ [type === 'grouped' ? GroupedBar.selectors.bar : StackedBar.selectors.bar]: tooltipTemplate,
137
+ }"
138
+ />
139
+ </VisXYContainer>
140
+ </div>
141
+ </div>
142
+ </template>
@@ -0,0 +1,75 @@
1
+ <script setup lang="ts">
2
+ import { VisSingleContainer, VisDonut, VisTooltip } from '@unovis/vue'
3
+ import { Donut } from '@unovis/ts'
4
+
5
+ interface Props {
6
+ data: Record<string, any>[]
7
+ category: string
8
+ index: string
9
+ colors?: string[]
10
+ valueFormatter?: (val: number) => string
11
+ showTooltip?: boolean
12
+ showLegend?: boolean
13
+ arcWidth?: number
14
+ padAngle?: number
15
+ }
16
+
17
+ const props = withDefaults(defineProps<Props>(), {
18
+ colors: () => ['var(--primary)', '#3b82f6', '#8b5cf6', '#f59e0b', '#10b981'],
19
+ valueFormatter: (val: number) => val.toLocaleString(),
20
+ showTooltip: true,
21
+ showLegend: false,
22
+ arcWidth: 28,
23
+ padAngle: 0.02,
24
+ })
25
+
26
+ const value = (d: any) => d[props.category]
27
+
28
+ function getColor(_: any, i: number): string {
29
+ return props.colors[i % props.colors.length]
30
+ }
31
+
32
+ const tooltipTemplate = (d: Record<string, any>) => {
33
+ if (!d) return ''
34
+ const name = d[props.index]
35
+ const val = props.valueFormatter(d[props.category])
36
+ return `
37
+ <div class="rounded-lg border border-border bg-popover/95 backdrop-blur-md px-3 py-1.5 text-xs shadow-md">
38
+ <span class="font-medium text-muted-foreground">${name}:</span>
39
+ <span class="font-mono font-bold text-foreground ml-1.5">${val}</span>
40
+ </div>
41
+ `
42
+ }
43
+ </script>
44
+
45
+ <template>
46
+ <div class="w-full h-full flex flex-col items-center justify-center">
47
+ <div class="w-full h-full min-h-40 relative flex items-center justify-center">
48
+ <VisSingleContainer :data="data" class="w-full h-full">
49
+ <VisDonut
50
+ :value="value"
51
+ :color="getColor"
52
+ :arcWidth="arcWidth"
53
+ :padAngle="padAngle"
54
+ />
55
+ <VisTooltip
56
+ v-if="showTooltip"
57
+ :attributes="{ 'data-unovis-tooltip': '' }"
58
+ :triggers="{ [Donut.selectors.segment]: tooltipTemplate }"
59
+ />
60
+ </VisSingleContainer>
61
+ </div>
62
+
63
+ <!-- Optional Legend -->
64
+ <div v-if="showLegend" class="flex flex-wrap items-center justify-center gap-3 mt-3 text-xs">
65
+ <div
66
+ v-for="(item, idx) in data"
67
+ :key="item[index]"
68
+ class="flex items-center gap-1.5 text-muted-foreground font-medium"
69
+ >
70
+ <span class="h-2 w-2 rounded-full" :style="{ backgroundColor: colors[idx % colors.length] }" />
71
+ <span>{{ item[index] }}</span>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </template>
@@ -0,0 +1,132 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { VisXYContainer, VisLine, VisAxis, VisTooltip, VisCrosshair } from '@unovis/vue'
4
+ import { CurveType } from '@unovis/ts'
5
+
6
+ interface Props {
7
+ data: Record<string, any>[]
8
+ index: string
9
+ categories: string[]
10
+ colors?: string[]
11
+ curveType?: CurveType
12
+ showGridLine?: boolean
13
+ showXAxis?: boolean
14
+ showYAxis?: boolean
15
+ showTooltip?: boolean
16
+ showLegend?: boolean
17
+ yFormatter?: (tick: number) => string
18
+ xFormatter?: (tick: number, i?: number) => string
19
+ }
20
+
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ colors: () => ['var(--primary)', '#3b82f6', '#10b981', '#f59e0b', '#8b5cf6'],
23
+ curveType: CurveType.MonotoneX,
24
+ showGridLine: false,
25
+ showXAxis: true,
26
+ showYAxis: true,
27
+ showTooltip: true,
28
+ showLegend: false,
29
+ })
30
+
31
+ const x = (_: any, i: number) => i
32
+
33
+ function getColor(i: number): string {
34
+ return props.colors[i % props.colors.length]
35
+ }
36
+
37
+ const defaultYFormatter = (tick: number) => {
38
+ if (tick >= 1_000_000) return `${(tick / 1_000_000).toFixed(1)}M`
39
+ if (tick >= 1_000) return `${(tick / 1_000).toFixed(0)}k`
40
+ return `${tick}`
41
+ }
42
+
43
+ const defaultXFormatter = (i: number) => {
44
+ const d = props.data[i]
45
+ return d ? String(d[props.index]) : ''
46
+ }
47
+
48
+ const tooltipTemplate = computed(() => {
49
+ return (d: Record<string, any>) => {
50
+ if (!d) return ''
51
+ const title = d[props.index] ?? ''
52
+ const rows = props.categories
53
+ .map((cat, idx) => {
54
+ const val = d[cat]
55
+ const color = getColor(idx)
56
+ const formattedVal = typeof val === 'number' ? val.toLocaleString() : val
57
+ return `
58
+ <div class="flex items-center justify-between gap-4 text-xs py-0.5">
59
+ <span class="flex items-center gap-1.5 text-muted-foreground capitalize">
60
+ <span class="h-2 w-2 rounded-full shrink-0" style="background-color: ${color}"></span>
61
+ ${cat}
62
+ </span>
63
+ <span class="font-mono font-bold text-foreground">${formattedVal}</span>
64
+ </div>
65
+ `
66
+ })
67
+ .join('')
68
+
69
+ return `
70
+ <div class="rounded-lg border border-border bg-popover/95 backdrop-blur-md px-3 py-2 text-xs shadow-md min-w-36">
71
+ <div class="font-bold text-foreground mb-1.5 pb-1 border-b border-border/40">${title}</div>
72
+ <div class="space-y-0.5">${rows}</div>
73
+ </div>
74
+ `
75
+ }
76
+ })
77
+ </script>
78
+
79
+ <template>
80
+ <div class="w-full h-full flex flex-col">
81
+ <!-- Optional Legend -->
82
+ <div v-if="showLegend" class="flex flex-wrap items-center gap-4 mb-3 text-xs">
83
+ <div
84
+ v-for="(cat, idx) in categories"
85
+ :key="cat"
86
+ class="flex items-center gap-1.5 text-muted-foreground font-medium capitalize"
87
+ >
88
+ <span class="h-2.5 w-2.5 rounded-full" :style="{ backgroundColor: getColor(idx) }" />
89
+ <span>{{ cat }}</span>
90
+ </div>
91
+ </div>
92
+
93
+ <!-- Chart Container -->
94
+ <div class="flex-1 w-full min-h-45 relative">
95
+ <VisXYContainer :data="data" class="w-full h-full">
96
+ <template v-for="(category, idx) in categories" :key="category">
97
+ <VisLine
98
+ :x="x"
99
+ :y="(d: any) => d[category]"
100
+ :color="getColor(idx)"
101
+ :lineWidth="2.5"
102
+ :curveType="curveType"
103
+ />
104
+ </template>
105
+
106
+ <VisAxis
107
+ v-if="showXAxis"
108
+ type="x"
109
+ :tickFormat="xFormatter || defaultXFormatter"
110
+ :numTicks="data.length"
111
+ :gridLine="false"
112
+ :domainLine="false"
113
+ :tickLine="false"
114
+ tickTextColor="var(--muted-foreground)"
115
+ />
116
+ <VisAxis
117
+ v-if="showYAxis"
118
+ type="y"
119
+ :tickFormat="yFormatter || defaultYFormatter"
120
+ :numTicks="4"
121
+ :gridLine="showGridLine"
122
+ :domainLine="false"
123
+ :tickLine="false"
124
+ tickTextColor="var(--muted-foreground)"
125
+ />
126
+
127
+ <VisTooltip v-if="showTooltip" :attributes="{ 'data-unovis-tooltip': '' }" />
128
+ <VisCrosshair v-if="showTooltip" :template="tooltipTemplate" />
129
+ </VisXYContainer>
130
+ </div>
131
+ </div>
132
+ </template>
@@ -0,0 +1,4 @@
1
+ export { default as AreaChart } from './AreaChart.vue'
2
+ export { default as LineChart } from './LineChart.vue'
3
+ export { default as BarChart } from './BarChart.vue'
4
+ export { default as DonutChart } from './DonutChart.vue'
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import type { CheckboxRootProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { computed } from "vue"
5
+ import { Check } from "@lucide/vue"
6
+ import { reactiveOmit } from "@vueuse/core"
7
+ import { CheckboxIndicator, CheckboxRoot, useForwardPropsEmits } from "reka-ui"
8
+ import { cn } from "@/lib/utils"
9
+
10
+ interface Props extends /* @vue-ignore */ CheckboxRootProps {
11
+ class?: HTMLAttributes["class"]
12
+ checked?: boolean | 'indeterminate'
13
+ }
14
+
15
+ const props = defineProps<Props>()
16
+ const emits = defineEmits<{
17
+ (e: 'update:modelValue', value: boolean | 'indeterminate'): void
18
+ (e: 'update:checked', value: boolean | 'indeterminate'): void
19
+ }>()
20
+
21
+ const delegatedProps = reactiveOmit(props, "class", "checked", "modelValue")
22
+ const forwarded = useForwardPropsEmits(delegatedProps, emits)
23
+
24
+ const internalValue = computed({
25
+ get: () => {
26
+ if (props.checked !== undefined) {
27
+ return props.checked
28
+ }
29
+ return props.modelValue
30
+ },
31
+ set: (val) => {
32
+ emits('update:modelValue', val as boolean | 'indeterminate')
33
+ emits('update:checked', val as boolean | 'indeterminate')
34
+ },
35
+ })
36
+ </script>
37
+
38
+ <template>
39
+ <CheckboxRoot
40
+ v-slot="slotProps"
41
+ data-slot="checkbox"
42
+ v-bind="forwarded"
43
+ v-model="internalValue"
44
+ :class="
45
+ cn('peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground 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-md border shadow-xs transition-shadow outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 cursor-pointer',
46
+ props.class)"
47
+ >
48
+ <CheckboxIndicator
49
+ data-slot="checkbox-indicator"
50
+ class="grid place-content-center text-current transition-none"
51
+ >
52
+ <slot v-bind="slotProps">
53
+ <Check class="size-3.5" />
54
+ </slot>
55
+ </CheckboxIndicator>
56
+ </CheckboxRoot>
57
+ </template>
@@ -0,0 +1 @@
1
+ export { default as Checkbox } from "./Checkbox.vue"
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import type { CollapsibleRootEmits, CollapsibleRootProps } from "reka-ui"
3
+ import { CollapsibleRoot, useForwardPropsEmits } from "reka-ui"
4
+
5
+ const props = defineProps<CollapsibleRootProps>()
6
+ const emits = defineEmits<CollapsibleRootEmits>()
7
+
8
+ const forwarded = useForwardPropsEmits(props, emits)
9
+ </script>
10
+
11
+ <template>
12
+ <CollapsibleRoot v-bind="forwarded" data-slot="collapsible">
13
+ <slot />
14
+ </CollapsibleRoot>
15
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import type { CollapsibleContentProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { cn } from "@/lib/utils"
5
+ import { CollapsibleContent } from "reka-ui"
6
+
7
+ const props = defineProps<CollapsibleContentProps & { class?: HTMLAttributes["class"] }>()
8
+ </script>
9
+
10
+ <template>
11
+ <CollapsibleContent
12
+ v-bind="props"
13
+ data-slot="collapsible-content"
14
+ :class="cn('overflow-hidden transition-all data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down', props.class)"
15
+ >
16
+ <slot />
17
+ </CollapsibleContent>
18
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import type { CollapsibleTriggerProps } from "reka-ui"
3
+ import { CollapsibleTrigger } from "reka-ui"
4
+
5
+ const props = defineProps<CollapsibleTriggerProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <CollapsibleTrigger v-bind="props" data-slot="collapsible-trigger">
10
+ <slot />
11
+ </CollapsibleTrigger>
12
+ </template>
@@ -0,0 +1,3 @@
1
+ export { default as Collapsible } from "./Collapsible.vue"
2
+ export { default as CollapsibleTrigger } from "./CollapsibleTrigger.vue"
3
+ export { default as CollapsibleContent } from "./CollapsibleContent.vue"
@@ -0,0 +1,88 @@
1
+ <script setup lang="ts">
2
+ import type { ListboxRootEmits, ListboxRootProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { ListboxRoot, useFilter, useForwardPropsEmits } from "reka-ui"
6
+ import { reactive, ref, watch } from "vue"
7
+ import { cn } from "@/lib/utils"
8
+ import { provideCommandContext } from "."
9
+
10
+ const props = withDefaults(defineProps<ListboxRootProps & { class?: HTMLAttributes["class"] }>(), {
11
+ modelValue: "",
12
+ highlightOnHover: true,
13
+ })
14
+
15
+ const emits = defineEmits<ListboxRootEmits>()
16
+
17
+ const delegatedProps = reactiveOmit(props, "class")
18
+
19
+ const forwarded = useForwardPropsEmits(delegatedProps, emits)
20
+
21
+ const allItems = ref<Map<string, string>>(new Map())
22
+ const allGroups = ref<Map<string, Set<string>>>(new Map())
23
+
24
+ const { contains } = useFilter({ sensitivity: "base" })
25
+ const filterState = reactive({
26
+ search: "",
27
+ filtered: {
28
+ /** The count of all visible items. */
29
+ count: 0,
30
+ /** Map from visible item id to its search score. */
31
+ items: new Map() as Map<string, number>,
32
+ /** Set of groups with at least one visible item. */
33
+ groups: new Set() as Set<string>,
34
+ },
35
+ })
36
+
37
+ function filterItems() {
38
+ if (!filterState.search) {
39
+ filterState.filtered.count = allItems.value.size
40
+ // Do nothing, each item will know to show itself because search is empty
41
+ return
42
+ }
43
+
44
+ // Reset the groups
45
+ filterState.filtered.groups = new Set()
46
+ let itemCount = 0
47
+
48
+ // Check which items should be included
49
+ for (const [id, value] of allItems.value) {
50
+ const score = contains(value, filterState.search)
51
+ filterState.filtered.items.set(id, score ? 1 : 0)
52
+ if (score)
53
+ itemCount++
54
+ }
55
+
56
+ // Check which groups have at least 1 item shown
57
+ for (const [groupId, group] of allGroups.value) {
58
+ for (const itemId of group) {
59
+ if (filterState.filtered.items.get(itemId)! > 0) {
60
+ filterState.filtered.groups.add(groupId)
61
+ break
62
+ }
63
+ }
64
+ }
65
+
66
+ filterState.filtered.count = itemCount
67
+ }
68
+
69
+ watch(() => filterState.search, () => {
70
+ filterItems()
71
+ })
72
+
73
+ provideCommandContext({
74
+ allItems,
75
+ allGroups,
76
+ filterState,
77
+ })
78
+ </script>
79
+
80
+ <template>
81
+ <ListboxRoot
82
+ data-slot="command"
83
+ v-bind="forwarded"
84
+ :class="cn('bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md', props.class)"
85
+ >
86
+ <slot />
87
+ </ListboxRoot>
88
+ </template>
@@ -0,0 +1,31 @@
1
+ <script setup lang="ts">
2
+ import type { DialogRootEmits, DialogRootProps } from "reka-ui"
3
+ import { useForwardPropsEmits } from "reka-ui"
4
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'
5
+ import Command from "./Command.vue"
6
+
7
+ const props = withDefaults(defineProps<DialogRootProps & {
8
+ title?: string
9
+ description?: string
10
+ }>(), {
11
+ title: "Command Palette",
12
+ description: "Search for a command to run...",
13
+ })
14
+ const emits = defineEmits<DialogRootEmits>()
15
+
16
+ const forwarded = useForwardPropsEmits(props, emits)
17
+ </script>
18
+
19
+ <template>
20
+ <Dialog v-slot="slotProps" v-bind="forwarded">
21
+ <DialogContent class="overflow-hidden p-0 ">
22
+ <DialogHeader class="sr-only">
23
+ <DialogTitle>{{ title }}</DialogTitle>
24
+ <DialogDescription>{{ description }}</DialogDescription>
25
+ </DialogHeader>
26
+ <Command>
27
+ <slot v-bind="slotProps" />
28
+ </Command>
29
+ </DialogContent>
30
+ </Dialog>
31
+ </template>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import type { PrimitiveProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { Primitive } from "reka-ui"
6
+ import { computed } from "vue"
7
+ import { cn } from "@/lib/utils"
8
+ import { useCommand } from "."
9
+
10
+ const props = defineProps<PrimitiveProps & { class?: HTMLAttributes["class"] }>()
11
+
12
+ const delegatedProps = reactiveOmit(props, "class")
13
+
14
+ const { filterState } = useCommand()
15
+ const isRender = computed(() => !!filterState.search && filterState.filtered.count === 0,
16
+ )
17
+ </script>
18
+
19
+ <template>
20
+ <Primitive
21
+ v-if="isRender"
22
+ data-slot="command-empty"
23
+ v-bind="delegatedProps" :class="cn('py-6 text-center text-sm', props.class)"
24
+ >
25
+ <slot />
26
+ </Primitive>
27
+ </template>
@@ -0,0 +1,45 @@
1
+ <script setup lang="ts">
2
+ import type { ListboxGroupProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { ListboxGroup, ListboxGroupLabel, useId } from "reka-ui"
6
+ import { computed, onMounted, onUnmounted } from "vue"
7
+ import { cn } from "@/lib/utils"
8
+ import { provideCommandGroupContext, useCommand } from "."
9
+
10
+ const props = defineProps<ListboxGroupProps & {
11
+ class?: HTMLAttributes["class"]
12
+ heading?: string
13
+ }>()
14
+
15
+ const delegatedProps = reactiveOmit(props, "class")
16
+
17
+ const { allGroups, filterState } = useCommand()
18
+ const id = useId()
19
+
20
+ const isRender = computed(() => !filterState.search ? true : filterState.filtered.groups.has(id))
21
+
22
+ provideCommandGroupContext({ id })
23
+ onMounted(() => {
24
+ if (!allGroups.value.has(id))
25
+ allGroups.value.set(id, new Set())
26
+ })
27
+ onUnmounted(() => {
28
+ allGroups.value.delete(id)
29
+ })
30
+ </script>
31
+
32
+ <template>
33
+ <ListboxGroup
34
+ v-bind="delegatedProps"
35
+ :id="id"
36
+ data-slot="command-group"
37
+ :class="cn('text-foreground overflow-hidden p-1', props.class)"
38
+ :hidden="isRender ? undefined : true"
39
+ >
40
+ <ListboxGroupLabel v-if="heading" data-slot="command-group-heading" class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
41
+ {{ heading }}
42
+ </ListboxGroupLabel>
43
+ <slot />
44
+ </ListboxGroup>
45
+ </template>