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.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/index.js +227 -0
- package/package.json +48 -0
- package/template/.env.example +45 -0
- package/template/_gitignore +33 -0
- package/template/components.json +24 -0
- package/template/index.html +30 -0
- package/template/package.json +51 -0
- package/template/public/favicon.svg +15 -0
- package/template/public/icons.svg +24 -0
- package/template/public/img/avatar.webp +0 -0
- package/template/public/screenshot.png +0 -0
- package/template/src/App.vue +15 -0
- package/template/src/auto-imports.d.ts +691 -0
- package/template/src/components/AppLogo.vue +159 -0
- package/template/src/components/EmptyState.vue +60 -0
- package/template/src/components/PageHeader.vue +60 -0
- package/template/src/components/layout/AppNavbar.vue +159 -0
- package/template/src/components/layout/AppSidebar.vue +74 -0
- package/template/src/components/layout/CommandSearchDialog.vue +120 -0
- package/template/src/components/ui/accordion/Accordion.vue +15 -0
- package/template/src/components/ui/accordion/AccordionContent.vue +20 -0
- package/template/src/components/ui/accordion/AccordionItem.vue +20 -0
- package/template/src/components/ui/accordion/AccordionTrigger.vue +34 -0
- package/template/src/components/ui/accordion/index.ts +4 -0
- package/template/src/components/ui/alert/Alert.vue +21 -0
- package/template/src/components/ui/alert/AlertDescription.vue +17 -0
- package/template/src/components/ui/alert/AlertTitle.vue +17 -0
- package/template/src/components/ui/alert/index.ts +30 -0
- package/template/src/components/ui/alert-dialog/AlertDialog.vue +15 -0
- package/template/src/components/ui/alert-dialog/AlertDialogAction.vue +18 -0
- package/template/src/components/ui/alert-dialog/AlertDialogCancel.vue +25 -0
- package/template/src/components/ui/alert-dialog/AlertDialogContent.vue +44 -0
- package/template/src/components/ui/alert-dialog/AlertDialogDescription.vue +23 -0
- package/template/src/components/ui/alert-dialog/AlertDialogFooter.vue +22 -0
- package/template/src/components/ui/alert-dialog/AlertDialogHeader.vue +17 -0
- package/template/src/components/ui/alert-dialog/AlertDialogTitle.vue +21 -0
- package/template/src/components/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
- package/template/src/components/ui/alert-dialog/index.ts +9 -0
- package/template/src/components/ui/avatar/Avatar.vue +50 -0
- package/template/src/components/ui/avatar/AvatarFallback.vue +21 -0
- package/template/src/components/ui/avatar/AvatarGroup.vue +69 -0
- package/template/src/components/ui/avatar/AvatarImage.vue +16 -0
- package/template/src/components/ui/avatar/index.ts +4 -0
- package/template/src/components/ui/badge/Badge.vue +40 -0
- package/template/src/components/ui/badge/index.ts +45 -0
- package/template/src/components/ui/breadcrumb/Breadcrumb.vue +17 -0
- package/template/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +23 -0
- package/template/src/components/ui/breadcrumb/BreadcrumbItem.vue +17 -0
- package/template/src/components/ui/breadcrumb/BreadcrumbLink.vue +21 -0
- package/template/src/components/ui/breadcrumb/BreadcrumbList.vue +17 -0
- package/template/src/components/ui/breadcrumb/BreadcrumbPage.vue +20 -0
- package/template/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +22 -0
- package/template/src/components/ui/breadcrumb/index.ts +7 -0
- package/template/src/components/ui/button/Button.spec.ts +46 -0
- package/template/src/components/ui/button/Button.vue +31 -0
- package/template/src/components/ui/button/index.ts +41 -0
- package/template/src/components/ui/calendar/Calendar.vue +106 -0
- package/template/src/components/ui/calendar/index.ts +1 -0
- package/template/src/components/ui/card/Card.vue +29 -0
- package/template/src/components/ui/card/CardAction.vue +17 -0
- package/template/src/components/ui/card/CardContent.vue +17 -0
- package/template/src/components/ui/card/CardDescription.vue +17 -0
- package/template/src/components/ui/card/CardFooter.vue +17 -0
- package/template/src/components/ui/card/CardHeader.vue +29 -0
- package/template/src/components/ui/card/CardTitle.vue +17 -0
- package/template/src/components/ui/card/index.ts +7 -0
- package/template/src/components/ui/chart/AreaChart.vue +143 -0
- package/template/src/components/ui/chart/BarChart.vue +142 -0
- package/template/src/components/ui/chart/DonutChart.vue +75 -0
- package/template/src/components/ui/chart/LineChart.vue +132 -0
- package/template/src/components/ui/chart/index.ts +4 -0
- package/template/src/components/ui/checkbox/Checkbox.vue +57 -0
- package/template/src/components/ui/checkbox/index.ts +1 -0
- package/template/src/components/ui/collapsible/Collapsible.vue +15 -0
- package/template/src/components/ui/collapsible/CollapsibleContent.vue +18 -0
- package/template/src/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
- package/template/src/components/ui/collapsible/index.ts +3 -0
- package/template/src/components/ui/command/Command.vue +88 -0
- package/template/src/components/ui/command/CommandDialog.vue +31 -0
- package/template/src/components/ui/command/CommandEmpty.vue +27 -0
- package/template/src/components/ui/command/CommandGroup.vue +45 -0
- package/template/src/components/ui/command/CommandInput.vue +39 -0
- package/template/src/components/ui/command/CommandItem.vue +76 -0
- package/template/src/components/ui/command/CommandList.vue +25 -0
- package/template/src/components/ui/command/CommandSeparator.vue +21 -0
- package/template/src/components/ui/command/CommandShortcut.vue +17 -0
- package/template/src/components/ui/command/index.ts +25 -0
- package/template/src/components/ui/context-menu/ContextMenu.vue +15 -0
- package/template/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +36 -0
- package/template/src/components/ui/context-menu/ContextMenuContent.vue +33 -0
- package/template/src/components/ui/context-menu/ContextMenuGroup.vue +12 -0
- package/template/src/components/ui/context-menu/ContextMenuItem.vue +36 -0
- package/template/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
- package/template/src/components/ui/context-menu/ContextMenuRadioGroup.vue +18 -0
- package/template/src/components/ui/context-menu/ContextMenuRadioItem.vue +36 -0
- package/template/src/components/ui/context-menu/ContextMenuSeparator.vue +18 -0
- package/template/src/components/ui/context-menu/ContextMenuShortcut.vue +17 -0
- package/template/src/components/ui/context-menu/ContextMenuSub.vue +15 -0
- package/template/src/components/ui/context-menu/ContextMenuSubContent.vue +36 -0
- package/template/src/components/ui/context-menu/ContextMenuSubTrigger.vue +32 -0
- package/template/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
- package/template/src/components/ui/context-menu/index.ts +14 -0
- package/template/src/components/ui/date-picker/DatePicker.vue +233 -0
- package/template/src/components/ui/date-picker/index.ts +1 -0
- package/template/src/components/ui/dialog/Dialog.vue +19 -0
- package/template/src/components/ui/dialog/DialogClose.vue +15 -0
- package/template/src/components/ui/dialog/DialogContent.vue +53 -0
- package/template/src/components/ui/dialog/DialogDescription.vue +23 -0
- package/template/src/components/ui/dialog/DialogFooter.vue +27 -0
- package/template/src/components/ui/dialog/DialogHeader.vue +17 -0
- package/template/src/components/ui/dialog/DialogOverlay.vue +21 -0
- package/template/src/components/ui/dialog/DialogScrollContent.vue +59 -0
- package/template/src/components/ui/dialog/DialogTitle.vue +23 -0
- package/template/src/components/ui/dialog/DialogTrigger.vue +15 -0
- package/template/src/components/ui/dialog/index.ts +10 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenu.vue +19 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuContent.vue +41 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
- package/template/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
- package/template/src/components/ui/dropdown-menu/index.ts +16 -0
- package/template/src/components/ui/form/FormControl.vue +17 -0
- package/template/src/components/ui/form/FormDescription.vue +21 -0
- package/template/src/components/ui/form/FormItem.vue +23 -0
- package/template/src/components/ui/form/FormLabel.vue +25 -0
- package/template/src/components/ui/form/FormMessage.vue +23 -0
- package/template/src/components/ui/form/index.ts +7 -0
- package/template/src/components/ui/form/injectionKeys.ts +4 -0
- package/template/src/components/ui/form/useFormField.ts +30 -0
- package/template/src/components/ui/hover-card/HoverCard.vue +19 -0
- package/template/src/components/ui/hover-card/HoverCardContent.vue +43 -0
- package/template/src/components/ui/hover-card/HoverCardTrigger.vue +15 -0
- package/template/src/components/ui/hover-card/index.ts +3 -0
- package/template/src/components/ui/index.ts +47 -0
- package/template/src/components/ui/input/Input.vue +33 -0
- package/template/src/components/ui/input/InputAddon.vue +29 -0
- package/template/src/components/ui/input/InputGroup.vue +17 -0
- package/template/src/components/ui/input/InputIcon.vue +29 -0
- package/template/src/components/ui/input/index.ts +4 -0
- package/template/src/components/ui/kbd/Kbd.vue +30 -0
- package/template/src/components/ui/kbd/index.ts +1 -0
- package/template/src/components/ui/label/Label.vue +26 -0
- package/template/src/components/ui/label/index.ts +1 -0
- package/template/src/components/ui/loading-bar/LoadingBar.vue +41 -0
- package/template/src/components/ui/loading-bar/index.ts +2 -0
- package/template/src/components/ui/pagination/Pagination.vue +26 -0
- package/template/src/components/ui/pagination/PaginationContent.vue +22 -0
- package/template/src/components/ui/pagination/PaginationEllipsis.vue +25 -0
- package/template/src/components/ui/pagination/PaginationFirst.vue +33 -0
- package/template/src/components/ui/pagination/PaginationItem.vue +34 -0
- package/template/src/components/ui/pagination/PaginationLast.vue +33 -0
- package/template/src/components/ui/pagination/PaginationNext.vue +33 -0
- package/template/src/components/ui/pagination/PaginationPrevious.vue +33 -0
- package/template/src/components/ui/pagination/index.ts +8 -0
- package/template/src/components/ui/pin-input/PinInput.vue +28 -0
- package/template/src/components/ui/pin-input/PinInputGroup.vue +18 -0
- package/template/src/components/ui/pin-input/PinInputInput.vue +24 -0
- package/template/src/components/ui/pin-input/PinInputSeparator.vue +21 -0
- package/template/src/components/ui/pin-input/index.ts +4 -0
- package/template/src/components/ui/popover/Popover.vue +19 -0
- package/template/src/components/ui/popover/PopoverAnchor.vue +15 -0
- package/template/src/components/ui/popover/PopoverContent.vue +45 -0
- package/template/src/components/ui/popover/PopoverTrigger.vue +15 -0
- package/template/src/components/ui/popover/index.ts +4 -0
- package/template/src/components/ui/progress/Progress.vue +35 -0
- package/template/src/components/ui/progress/index.ts +1 -0
- package/template/src/components/ui/radio-group/RadioGroup.vue +23 -0
- package/template/src/components/ui/radio-group/RadioGroupItem.vue +30 -0
- package/template/src/components/ui/radio-group/index.ts +2 -0
- package/template/src/components/ui/scroll-area/ScrollArea.vue +40 -0
- package/template/src/components/ui/scroll-area/ScrollBar.vue +44 -0
- package/template/src/components/ui/scroll-area/index.ts +2 -0
- package/template/src/components/ui/select/Select.vue +19 -0
- package/template/src/components/ui/select/SelectContent.vue +51 -0
- package/template/src/components/ui/select/SelectGroup.vue +15 -0
- package/template/src/components/ui/select/SelectItem.vue +44 -0
- package/template/src/components/ui/select/SelectItemText.vue +15 -0
- package/template/src/components/ui/select/SelectLabel.vue +17 -0
- package/template/src/components/ui/select/SelectScrollDownButton.vue +26 -0
- package/template/src/components/ui/select/SelectScrollUpButton.vue +26 -0
- package/template/src/components/ui/select/SelectSeparator.vue +19 -0
- package/template/src/components/ui/select/SelectTrigger.vue +33 -0
- package/template/src/components/ui/select/SelectValue.vue +15 -0
- package/template/src/components/ui/select/index.ts +11 -0
- package/template/src/components/ui/separator/Separator.vue +29 -0
- package/template/src/components/ui/separator/index.ts +1 -0
- package/template/src/components/ui/sheet/Sheet.vue +19 -0
- package/template/src/components/ui/sheet/SheetClose.vue +15 -0
- package/template/src/components/ui/sheet/SheetContent.vue +62 -0
- package/template/src/components/ui/sheet/SheetDescription.vue +21 -0
- package/template/src/components/ui/sheet/SheetFooter.vue +16 -0
- package/template/src/components/ui/sheet/SheetHeader.vue +15 -0
- package/template/src/components/ui/sheet/SheetOverlay.vue +21 -0
- package/template/src/components/ui/sheet/SheetTitle.vue +21 -0
- package/template/src/components/ui/sheet/SheetTrigger.vue +15 -0
- package/template/src/components/ui/sheet/index.ts +8 -0
- package/template/src/components/ui/sidebar/Sidebar.vue +113 -0
- package/template/src/components/ui/sidebar/SidebarContent.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarControl.vue +53 -0
- package/template/src/components/ui/sidebar/SidebarFooter.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarGroup.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarGroupAction.vue +27 -0
- package/template/src/components/ui/sidebar/SidebarGroupContent.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarGroupLabel.vue +25 -0
- package/template/src/components/ui/sidebar/SidebarHeader.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarInput.vue +22 -0
- package/template/src/components/ui/sidebar/SidebarInset.vue +21 -0
- package/template/src/components/ui/sidebar/SidebarMenu.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarMenuAction.vue +35 -0
- package/template/src/components/ui/sidebar/SidebarMenuBadge.vue +26 -0
- package/template/src/components/ui/sidebar/SidebarMenuButton.vue +48 -0
- package/template/src/components/ui/sidebar/SidebarMenuButtonChild.vue +36 -0
- package/template/src/components/ui/sidebar/SidebarMenuItem.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarMenuSkeleton.vue +35 -0
- package/template/src/components/ui/sidebar/SidebarMenuSub.vue +22 -0
- package/template/src/components/ui/sidebar/SidebarMenuSubButton.vue +36 -0
- package/template/src/components/ui/sidebar/SidebarMenuSubItem.vue +18 -0
- package/template/src/components/ui/sidebar/SidebarProvider.vue +136 -0
- package/template/src/components/ui/sidebar/SidebarRail.vue +33 -0
- package/template/src/components/ui/sidebar/SidebarSeparator.vue +19 -0
- package/template/src/components/ui/sidebar/SidebarTrigger.vue +27 -0
- package/template/src/components/ui/sidebar/index.ts +61 -0
- package/template/src/components/ui/sidebar/utils.ts +27 -0
- package/template/src/components/ui/skeleton/Skeleton.vue +17 -0
- package/template/src/components/ui/skeleton/index.ts +1 -0
- package/template/src/components/ui/slider/Slider.vue +42 -0
- package/template/src/components/ui/slider/index.ts +1 -0
- package/template/src/components/ui/sonner/Sonner.vue +42 -0
- package/template/src/components/ui/sonner/index.ts +2 -0
- package/template/src/components/ui/stepper/Stepper.vue +102 -0
- package/template/src/components/ui/stepper/index.ts +1 -0
- package/template/src/components/ui/switch/Switch.vue +38 -0
- package/template/src/components/ui/switch/index.ts +1 -0
- package/template/src/components/ui/table/Table.vue +16 -0
- package/template/src/components/ui/table/TableBody.vue +17 -0
- package/template/src/components/ui/table/TableCaption.vue +17 -0
- package/template/src/components/ui/table/TableCell.vue +22 -0
- package/template/src/components/ui/table/TableEmpty.vue +34 -0
- package/template/src/components/ui/table/TableFooter.vue +17 -0
- package/template/src/components/ui/table/TableHead.vue +17 -0
- package/template/src/components/ui/table/TableHeader.vue +17 -0
- package/template/src/components/ui/table/TableRow.vue +17 -0
- package/template/src/components/ui/table/index.ts +9 -0
- package/template/src/components/ui/table/utils.ts +10 -0
- package/template/src/components/ui/tabs/Tabs.vue +24 -0
- package/template/src/components/ui/tabs/TabsContent.vue +21 -0
- package/template/src/components/ui/tabs/TabsList.vue +24 -0
- package/template/src/components/ui/tabs/TabsTrigger.vue +26 -0
- package/template/src/components/ui/tabs/index.ts +4 -0
- package/template/src/components/ui/textarea/Textarea.vue +28 -0
- package/template/src/components/ui/textarea/index.ts +1 -0
- package/template/src/components/ui/timeline/Timeline.vue +73 -0
- package/template/src/components/ui/timeline/index.ts +1 -0
- package/template/src/components/ui/toggle/Toggle.vue +35 -0
- package/template/src/components/ui/toggle/index.ts +28 -0
- package/template/src/components/ui/toggle-group/ToggleGroup.vue +41 -0
- package/template/src/components/ui/toggle-group/ToggleGroupItem.vue +43 -0
- package/template/src/components/ui/toggle-group/index.ts +12 -0
- package/template/src/components/ui/tooltip/Tooltip.vue +19 -0
- package/template/src/components/ui/tooltip/TooltipContent.vue +34 -0
- package/template/src/components/ui/tooltip/TooltipProvider.vue +14 -0
- package/template/src/components/ui/tooltip/TooltipTrigger.vue +15 -0
- package/template/src/components/ui/tooltip/index.ts +4 -0
- package/template/src/components.d.ts +228 -0
- package/template/src/composables/useFormatter.ts +105 -0
- package/template/src/composables/useThemeConfig.ts +252 -0
- package/template/src/layouts/AdminLayout.vue +55 -0
- package/template/src/layouts/AuthLayout.vue +42 -0
- package/template/src/lib/axios.spec.ts +46 -0
- package/template/src/lib/axios.ts +243 -0
- package/template/src/lib/formatters.spec.ts +137 -0
- package/template/src/lib/formatters.ts +332 -0
- package/template/src/lib/loading-bar.ts +103 -0
- package/template/src/lib/utils.spec.ts +26 -0
- package/template/src/lib/utils.ts +7 -0
- package/template/src/lib/validation.spec.ts +78 -0
- package/template/src/main.ts +13 -0
- package/template/src/router/index.ts +147 -0
- package/template/src/services/auth.service.spec.ts +93 -0
- package/template/src/services/auth.service.ts +243 -0
- package/template/src/services/index.ts +3 -0
- package/template/src/services/types.ts +28 -0
- package/template/src/services/user.service.spec.ts +91 -0
- package/template/src/services/user.service.ts +283 -0
- package/template/src/stores/auth.spec.ts +52 -0
- package/template/src/stores/auth.ts +130 -0
- package/template/src/style.css +587 -0
- package/template/src/views/_starter/BlankView.vue +47 -0
- package/template/src/views/auth/ConfirmEmailView.vue +209 -0
- package/template/src/views/auth/ForgotPasswordView.vue +151 -0
- package/template/src/views/auth/LockScreenView.vue +175 -0
- package/template/src/views/auth/LoginView.vue +54 -0
- package/template/src/views/auth/RegisterView.vue +265 -0
- package/template/src/views/auth/ResetPasswordView.vue +260 -0
- package/template/src/views/auth/VerifyOtpView.vue +261 -0
- package/template/src/views/dashboard/IndexView.vue +159 -0
- package/template/src/views/errors/ComingSoonView.vue +241 -0
- package/template/src/views/errors/MaintenanceView.vue +252 -0
- package/template/src/views/errors/NotFoundView.vue +81 -0
- package/template/src/views/errors/ServerErrorView.vue +101 -0
- package/template/src/views/errors/UnauthorizedView.vue +64 -0
- package/template/tsconfig.app.json +27 -0
- package/template/tsconfig.json +19 -0
- package/template/tsconfig.node.json +23 -0
- package/template/vite.config.ts +46 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
// biome-ignore lint: disable
|
|
4
|
+
// oxlint-disable
|
|
5
|
+
// ------
|
|
6
|
+
// Generated by unplugin-vue-components
|
|
7
|
+
// Read more: https://github.com/vuejs/core/pull/3399
|
|
8
|
+
|
|
9
|
+
export {}
|
|
10
|
+
|
|
11
|
+
/* prettier-ignore */
|
|
12
|
+
declare module 'vue' {
|
|
13
|
+
export interface GlobalComponents {
|
|
14
|
+
Accordion: typeof import('./components/ui/accordion/Accordion.vue')['default']
|
|
15
|
+
AccordionContent: typeof import('./components/ui/accordion/AccordionContent.vue')['default']
|
|
16
|
+
AccordionItem: typeof import('./components/ui/accordion/AccordionItem.vue')['default']
|
|
17
|
+
AccordionTrigger: typeof import('./components/ui/accordion/AccordionTrigger.vue')['default']
|
|
18
|
+
Alert: typeof import('./components/ui/alert/Alert.vue')['default']
|
|
19
|
+
AlertDescription: typeof import('./components/ui/alert/AlertDescription.vue')['default']
|
|
20
|
+
AlertDialog: typeof import('./components/ui/alert-dialog/AlertDialog.vue')['default']
|
|
21
|
+
AlertDialogAction: typeof import('./components/ui/alert-dialog/AlertDialogAction.vue')['default']
|
|
22
|
+
AlertDialogCancel: typeof import('./components/ui/alert-dialog/AlertDialogCancel.vue')['default']
|
|
23
|
+
AlertDialogContent: typeof import('./components/ui/alert-dialog/AlertDialogContent.vue')['default']
|
|
24
|
+
AlertDialogDescription: typeof import('./components/ui/alert-dialog/AlertDialogDescription.vue')['default']
|
|
25
|
+
AlertDialogFooter: typeof import('./components/ui/alert-dialog/AlertDialogFooter.vue')['default']
|
|
26
|
+
AlertDialogHeader: typeof import('./components/ui/alert-dialog/AlertDialogHeader.vue')['default']
|
|
27
|
+
AlertDialogTitle: typeof import('./components/ui/alert-dialog/AlertDialogTitle.vue')['default']
|
|
28
|
+
AlertDialogTrigger: typeof import('./components/ui/alert-dialog/AlertDialogTrigger.vue')['default']
|
|
29
|
+
AlertTitle: typeof import('./components/ui/alert/AlertTitle.vue')['default']
|
|
30
|
+
AppLogo: typeof import('./components/AppLogo.vue')['default']
|
|
31
|
+
AppNavbar: typeof import('./components/layout/AppNavbar.vue')['default']
|
|
32
|
+
AppSidebar: typeof import('./components/layout/AppSidebar.vue')['default']
|
|
33
|
+
AreaChart: typeof import('./components/ui/chart/AreaChart.vue')['default']
|
|
34
|
+
Avatar: typeof import('./components/ui/avatar/Avatar.vue')['default']
|
|
35
|
+
AvatarFallback: typeof import('./components/ui/avatar/AvatarFallback.vue')['default']
|
|
36
|
+
AvatarGroup: typeof import('./components/ui/avatar/AvatarGroup.vue')['default']
|
|
37
|
+
AvatarImage: typeof import('./components/ui/avatar/AvatarImage.vue')['default']
|
|
38
|
+
Badge: typeof import('./components/ui/badge/Badge.vue')['default']
|
|
39
|
+
BarChart: typeof import('./components/ui/chart/BarChart.vue')['default']
|
|
40
|
+
Breadcrumb: typeof import('./components/ui/breadcrumb/Breadcrumb.vue')['default']
|
|
41
|
+
BreadcrumbEllipsis: typeof import('./components/ui/breadcrumb/BreadcrumbEllipsis.vue')['default']
|
|
42
|
+
BreadcrumbItem: typeof import('./components/ui/breadcrumb/BreadcrumbItem.vue')['default']
|
|
43
|
+
BreadcrumbLink: typeof import('./components/ui/breadcrumb/BreadcrumbLink.vue')['default']
|
|
44
|
+
BreadcrumbList: typeof import('./components/ui/breadcrumb/BreadcrumbList.vue')['default']
|
|
45
|
+
BreadcrumbPage: typeof import('./components/ui/breadcrumb/BreadcrumbPage.vue')['default']
|
|
46
|
+
BreadcrumbSeparator: typeof import('./components/ui/breadcrumb/BreadcrumbSeparator.vue')['default']
|
|
47
|
+
Button: typeof import('./components/ui/button/Button.vue')['default']
|
|
48
|
+
Calendar: typeof import('./components/ui/calendar/Calendar.vue')['default']
|
|
49
|
+
Card: typeof import('./components/ui/card/Card.vue')['default']
|
|
50
|
+
CardAction: typeof import('./components/ui/card/CardAction.vue')['default']
|
|
51
|
+
CardContent: typeof import('./components/ui/card/CardContent.vue')['default']
|
|
52
|
+
CardDescription: typeof import('./components/ui/card/CardDescription.vue')['default']
|
|
53
|
+
CardFooter: typeof import('./components/ui/card/CardFooter.vue')['default']
|
|
54
|
+
CardHeader: typeof import('./components/ui/card/CardHeader.vue')['default']
|
|
55
|
+
CardTitle: typeof import('./components/ui/card/CardTitle.vue')['default']
|
|
56
|
+
Checkbox: typeof import('./components/ui/checkbox/Checkbox.vue')['default']
|
|
57
|
+
CodePreview: typeof import('./components/CodePreview.vue')['default']
|
|
58
|
+
Collapsible: typeof import('./components/ui/collapsible/Collapsible.vue')['default']
|
|
59
|
+
CollapsibleContent: typeof import('./components/ui/collapsible/CollapsibleContent.vue')['default']
|
|
60
|
+
CollapsibleTrigger: typeof import('./components/ui/collapsible/CollapsibleTrigger.vue')['default']
|
|
61
|
+
Command: typeof import('./components/ui/command/Command.vue')['default']
|
|
62
|
+
CommandDialog: typeof import('./components/ui/command/CommandDialog.vue')['default']
|
|
63
|
+
CommandEmpty: typeof import('./components/ui/command/CommandEmpty.vue')['default']
|
|
64
|
+
CommandGroup: typeof import('./components/ui/command/CommandGroup.vue')['default']
|
|
65
|
+
CommandInput: typeof import('./components/ui/command/CommandInput.vue')['default']
|
|
66
|
+
CommandItem: typeof import('./components/ui/command/CommandItem.vue')['default']
|
|
67
|
+
CommandList: typeof import('./components/ui/command/CommandList.vue')['default']
|
|
68
|
+
CommandSearchDialog: typeof import('./components/layout/CommandSearchDialog.vue')['default']
|
|
69
|
+
CommandSeparator: typeof import('./components/ui/command/CommandSeparator.vue')['default']
|
|
70
|
+
CommandShortcut: typeof import('./components/ui/command/CommandShortcut.vue')['default']
|
|
71
|
+
ContextMenu: typeof import('./components/ui/context-menu/ContextMenu.vue')['default']
|
|
72
|
+
ContextMenuCheckboxItem: typeof import('./components/ui/context-menu/ContextMenuCheckboxItem.vue')['default']
|
|
73
|
+
ContextMenuContent: typeof import('./components/ui/context-menu/ContextMenuContent.vue')['default']
|
|
74
|
+
ContextMenuGroup: typeof import('./components/ui/context-menu/ContextMenuGroup.vue')['default']
|
|
75
|
+
ContextMenuItem: typeof import('./components/ui/context-menu/ContextMenuItem.vue')['default']
|
|
76
|
+
ContextMenuLabel: typeof import('./components/ui/context-menu/ContextMenuLabel.vue')['default']
|
|
77
|
+
ContextMenuRadioGroup: typeof import('./components/ui/context-menu/ContextMenuRadioGroup.vue')['default']
|
|
78
|
+
ContextMenuRadioItem: typeof import('./components/ui/context-menu/ContextMenuRadioItem.vue')['default']
|
|
79
|
+
ContextMenuSeparator: typeof import('./components/ui/context-menu/ContextMenuSeparator.vue')['default']
|
|
80
|
+
ContextMenuShortcut: typeof import('./components/ui/context-menu/ContextMenuShortcut.vue')['default']
|
|
81
|
+
ContextMenuSub: typeof import('./components/ui/context-menu/ContextMenuSub.vue')['default']
|
|
82
|
+
ContextMenuSubContent: typeof import('./components/ui/context-menu/ContextMenuSubContent.vue')['default']
|
|
83
|
+
ContextMenuSubTrigger: typeof import('./components/ui/context-menu/ContextMenuSubTrigger.vue')['default']
|
|
84
|
+
ContextMenuTrigger: typeof import('./components/ui/context-menu/ContextMenuTrigger.vue')['default']
|
|
85
|
+
DatePicker: typeof import('./components/ui/date-picker/DatePicker.vue')['default']
|
|
86
|
+
Dialog: typeof import('./components/ui/dialog/Dialog.vue')['default']
|
|
87
|
+
DialogClose: typeof import('./components/ui/dialog/DialogClose.vue')['default']
|
|
88
|
+
DialogContent: typeof import('./components/ui/dialog/DialogContent.vue')['default']
|
|
89
|
+
DialogDescription: typeof import('./components/ui/dialog/DialogDescription.vue')['default']
|
|
90
|
+
DialogFooter: typeof import('./components/ui/dialog/DialogFooter.vue')['default']
|
|
91
|
+
DialogHeader: typeof import('./components/ui/dialog/DialogHeader.vue')['default']
|
|
92
|
+
DialogOverlay: typeof import('./components/ui/dialog/DialogOverlay.vue')['default']
|
|
93
|
+
DialogScrollContent: typeof import('./components/ui/dialog/DialogScrollContent.vue')['default']
|
|
94
|
+
DialogTitle: typeof import('./components/ui/dialog/DialogTitle.vue')['default']
|
|
95
|
+
DialogTrigger: typeof import('./components/ui/dialog/DialogTrigger.vue')['default']
|
|
96
|
+
DonutChart: typeof import('./components/ui/chart/DonutChart.vue')['default']
|
|
97
|
+
DropdownMenu: typeof import('./components/ui/dropdown-menu/DropdownMenu.vue')['default']
|
|
98
|
+
DropdownMenuCheckboxItem: typeof import('./components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue')['default']
|
|
99
|
+
DropdownMenuContent: typeof import('./components/ui/dropdown-menu/DropdownMenuContent.vue')['default']
|
|
100
|
+
DropdownMenuGroup: typeof import('./components/ui/dropdown-menu/DropdownMenuGroup.vue')['default']
|
|
101
|
+
DropdownMenuItem: typeof import('./components/ui/dropdown-menu/DropdownMenuItem.vue')['default']
|
|
102
|
+
DropdownMenuLabel: typeof import('./components/ui/dropdown-menu/DropdownMenuLabel.vue')['default']
|
|
103
|
+
DropdownMenuRadioGroup: typeof import('./components/ui/dropdown-menu/DropdownMenuRadioGroup.vue')['default']
|
|
104
|
+
DropdownMenuRadioItem: typeof import('./components/ui/dropdown-menu/DropdownMenuRadioItem.vue')['default']
|
|
105
|
+
DropdownMenuSeparator: typeof import('./components/ui/dropdown-menu/DropdownMenuSeparator.vue')['default']
|
|
106
|
+
DropdownMenuShortcut: typeof import('./components/ui/dropdown-menu/DropdownMenuShortcut.vue')['default']
|
|
107
|
+
DropdownMenuSub: typeof import('./components/ui/dropdown-menu/DropdownMenuSub.vue')['default']
|
|
108
|
+
DropdownMenuSubContent: typeof import('./components/ui/dropdown-menu/DropdownMenuSubContent.vue')['default']
|
|
109
|
+
DropdownMenuSubTrigger: typeof import('./components/ui/dropdown-menu/DropdownMenuSubTrigger.vue')['default']
|
|
110
|
+
DropdownMenuTrigger: typeof import('./components/ui/dropdown-menu/DropdownMenuTrigger.vue')['default']
|
|
111
|
+
EmptyState: typeof import('./components/EmptyState.vue')['default']
|
|
112
|
+
FormControl: typeof import('./components/ui/form/FormControl.vue')['default']
|
|
113
|
+
FormDescription: typeof import('./components/ui/form/FormDescription.vue')['default']
|
|
114
|
+
FormItem: typeof import('./components/ui/form/FormItem.vue')['default']
|
|
115
|
+
FormLabel: typeof import('./components/ui/form/FormLabel.vue')['default']
|
|
116
|
+
FormMessage: typeof import('./components/ui/form/FormMessage.vue')['default']
|
|
117
|
+
HoverCard: typeof import('./components/ui/hover-card/HoverCard.vue')['default']
|
|
118
|
+
HoverCardContent: typeof import('./components/ui/hover-card/HoverCardContent.vue')['default']
|
|
119
|
+
HoverCardTrigger: typeof import('./components/ui/hover-card/HoverCardTrigger.vue')['default']
|
|
120
|
+
Input: typeof import('./components/ui/input/Input.vue')['default']
|
|
121
|
+
InputAddon: typeof import('./components/ui/input/InputAddon.vue')['default']
|
|
122
|
+
InputGroup: typeof import('./components/ui/input/InputGroup.vue')['default']
|
|
123
|
+
InputIcon: typeof import('./components/ui/input/InputIcon.vue')['default']
|
|
124
|
+
Kbd: typeof import('./components/ui/kbd/Kbd.vue')['default']
|
|
125
|
+
Label: typeof import('./components/ui/label/Label.vue')['default']
|
|
126
|
+
LineChart: typeof import('./components/ui/chart/LineChart.vue')['default']
|
|
127
|
+
LoadingBar: typeof import('./components/ui/loading-bar/LoadingBar.vue')['default']
|
|
128
|
+
NotificationDrawer: typeof import('./components/layout/NotificationDrawer.vue')['default']
|
|
129
|
+
PageHeader: typeof import('./components/PageHeader.vue')['default']
|
|
130
|
+
Pagination: typeof import('./components/ui/pagination/Pagination.vue')['default']
|
|
131
|
+
PaginationContent: typeof import('./components/ui/pagination/PaginationContent.vue')['default']
|
|
132
|
+
PaginationEllipsis: typeof import('./components/ui/pagination/PaginationEllipsis.vue')['default']
|
|
133
|
+
PaginationFirst: typeof import('./components/ui/pagination/PaginationFirst.vue')['default']
|
|
134
|
+
PaginationItem: typeof import('./components/ui/pagination/PaginationItem.vue')['default']
|
|
135
|
+
PaginationLast: typeof import('./components/ui/pagination/PaginationLast.vue')['default']
|
|
136
|
+
PaginationNext: typeof import('./components/ui/pagination/PaginationNext.vue')['default']
|
|
137
|
+
PaginationPrevious: typeof import('./components/ui/pagination/PaginationPrevious.vue')['default']
|
|
138
|
+
PinInput: typeof import('./components/ui/pin-input/PinInput.vue')['default']
|
|
139
|
+
PinInputGroup: typeof import('./components/ui/pin-input/PinInputGroup.vue')['default']
|
|
140
|
+
PinInputInput: typeof import('./components/ui/pin-input/PinInputInput.vue')['default']
|
|
141
|
+
PinInputSeparator: typeof import('./components/ui/pin-input/PinInputSeparator.vue')['default']
|
|
142
|
+
Popover: typeof import('./components/ui/popover/Popover.vue')['default']
|
|
143
|
+
PopoverAnchor: typeof import('./components/ui/popover/PopoverAnchor.vue')['default']
|
|
144
|
+
PopoverContent: typeof import('./components/ui/popover/PopoverContent.vue')['default']
|
|
145
|
+
PopoverTrigger: typeof import('./components/ui/popover/PopoverTrigger.vue')['default']
|
|
146
|
+
Progress: typeof import('./components/ui/progress/Progress.vue')['default']
|
|
147
|
+
RadioGroup: typeof import('./components/ui/radio-group/RadioGroup.vue')['default']
|
|
148
|
+
RadioGroupItem: typeof import('./components/ui/radio-group/RadioGroupItem.vue')['default']
|
|
149
|
+
RouterLink: typeof import('vue-router')['RouterLink']
|
|
150
|
+
RouterView: typeof import('vue-router')['RouterView']
|
|
151
|
+
ScrollArea: typeof import('./components/ui/scroll-area/ScrollArea.vue')['default']
|
|
152
|
+
ScrollBar: typeof import('./components/ui/scroll-area/ScrollBar.vue')['default']
|
|
153
|
+
Select: typeof import('./components/ui/select/Select.vue')['default']
|
|
154
|
+
SelectContent: typeof import('./components/ui/select/SelectContent.vue')['default']
|
|
155
|
+
SelectGroup: typeof import('./components/ui/select/SelectGroup.vue')['default']
|
|
156
|
+
SelectItem: typeof import('./components/ui/select/SelectItem.vue')['default']
|
|
157
|
+
SelectItemText: typeof import('./components/ui/select/SelectItemText.vue')['default']
|
|
158
|
+
SelectLabel: typeof import('./components/ui/select/SelectLabel.vue')['default']
|
|
159
|
+
SelectScrollDownButton: typeof import('./components/ui/select/SelectScrollDownButton.vue')['default']
|
|
160
|
+
SelectScrollUpButton: typeof import('./components/ui/select/SelectScrollUpButton.vue')['default']
|
|
161
|
+
SelectSeparator: typeof import('./components/ui/select/SelectSeparator.vue')['default']
|
|
162
|
+
SelectTrigger: typeof import('./components/ui/select/SelectTrigger.vue')['default']
|
|
163
|
+
SelectValue: typeof import('./components/ui/select/SelectValue.vue')['default']
|
|
164
|
+
Separator: typeof import('./components/ui/separator/Separator.vue')['default']
|
|
165
|
+
Sheet: typeof import('./components/ui/sheet/Sheet.vue')['default']
|
|
166
|
+
SheetClose: typeof import('./components/ui/sheet/SheetClose.vue')['default']
|
|
167
|
+
SheetContent: typeof import('./components/ui/sheet/SheetContent.vue')['default']
|
|
168
|
+
SheetDescription: typeof import('./components/ui/sheet/SheetDescription.vue')['default']
|
|
169
|
+
SheetFooter: typeof import('./components/ui/sheet/SheetFooter.vue')['default']
|
|
170
|
+
SheetHeader: typeof import('./components/ui/sheet/SheetHeader.vue')['default']
|
|
171
|
+
SheetOverlay: typeof import('./components/ui/sheet/SheetOverlay.vue')['default']
|
|
172
|
+
SheetTitle: typeof import('./components/ui/sheet/SheetTitle.vue')['default']
|
|
173
|
+
SheetTrigger: typeof import('./components/ui/sheet/SheetTrigger.vue')['default']
|
|
174
|
+
Sidebar: typeof import('./components/ui/sidebar/Sidebar.vue')['default']
|
|
175
|
+
SidebarContent: typeof import('./components/ui/sidebar/SidebarContent.vue')['default']
|
|
176
|
+
SidebarControl: typeof import('./components/ui/sidebar/SidebarControl.vue')['default']
|
|
177
|
+
SidebarFooter: typeof import('./components/ui/sidebar/SidebarFooter.vue')['default']
|
|
178
|
+
SidebarGroup: typeof import('./components/ui/sidebar/SidebarGroup.vue')['default']
|
|
179
|
+
SidebarGroupAction: typeof import('./components/ui/sidebar/SidebarGroupAction.vue')['default']
|
|
180
|
+
SidebarGroupContent: typeof import('./components/ui/sidebar/SidebarGroupContent.vue')['default']
|
|
181
|
+
SidebarGroupLabel: typeof import('./components/ui/sidebar/SidebarGroupLabel.vue')['default']
|
|
182
|
+
SidebarHeader: typeof import('./components/ui/sidebar/SidebarHeader.vue')['default']
|
|
183
|
+
SidebarInput: typeof import('./components/ui/sidebar/SidebarInput.vue')['default']
|
|
184
|
+
SidebarInset: typeof import('./components/ui/sidebar/SidebarInset.vue')['default']
|
|
185
|
+
SidebarMenu: typeof import('./components/ui/sidebar/SidebarMenu.vue')['default']
|
|
186
|
+
SidebarMenuAction: typeof import('./components/ui/sidebar/SidebarMenuAction.vue')['default']
|
|
187
|
+
SidebarMenuBadge: typeof import('./components/ui/sidebar/SidebarMenuBadge.vue')['default']
|
|
188
|
+
SidebarMenuButton: typeof import('./components/ui/sidebar/SidebarMenuButton.vue')['default']
|
|
189
|
+
SidebarMenuButtonChild: typeof import('./components/ui/sidebar/SidebarMenuButtonChild.vue')['default']
|
|
190
|
+
SidebarMenuItem: typeof import('./components/ui/sidebar/SidebarMenuItem.vue')['default']
|
|
191
|
+
SidebarMenuSkeleton: typeof import('./components/ui/sidebar/SidebarMenuSkeleton.vue')['default']
|
|
192
|
+
SidebarMenuSub: typeof import('./components/ui/sidebar/SidebarMenuSub.vue')['default']
|
|
193
|
+
SidebarMenuSubButton: typeof import('./components/ui/sidebar/SidebarMenuSubButton.vue')['default']
|
|
194
|
+
SidebarMenuSubItem: typeof import('./components/ui/sidebar/SidebarMenuSubItem.vue')['default']
|
|
195
|
+
SidebarProvider: typeof import('./components/ui/sidebar/SidebarProvider.vue')['default']
|
|
196
|
+
SidebarRail: typeof import('./components/ui/sidebar/SidebarRail.vue')['default']
|
|
197
|
+
SidebarSeparator: typeof import('./components/ui/sidebar/SidebarSeparator.vue')['default']
|
|
198
|
+
SidebarTrigger: typeof import('./components/ui/sidebar/SidebarTrigger.vue')['default']
|
|
199
|
+
Skeleton: typeof import('./components/ui/skeleton/Skeleton.vue')['default']
|
|
200
|
+
Slider: typeof import('./components/ui/slider/Slider.vue')['default']
|
|
201
|
+
Sonner: typeof import('./components/ui/sonner/Sonner.vue')['default']
|
|
202
|
+
Stepper: typeof import('./components/ui/stepper/Stepper.vue')['default']
|
|
203
|
+
Switch: typeof import('./components/ui/switch/Switch.vue')['default']
|
|
204
|
+
Table: typeof import('./components/ui/table/Table.vue')['default']
|
|
205
|
+
TableBody: typeof import('./components/ui/table/TableBody.vue')['default']
|
|
206
|
+
TableCaption: typeof import('./components/ui/table/TableCaption.vue')['default']
|
|
207
|
+
TableCell: typeof import('./components/ui/table/TableCell.vue')['default']
|
|
208
|
+
TableEmpty: typeof import('./components/ui/table/TableEmpty.vue')['default']
|
|
209
|
+
TableFooter: typeof import('./components/ui/table/TableFooter.vue')['default']
|
|
210
|
+
TableHead: typeof import('./components/ui/table/TableHead.vue')['default']
|
|
211
|
+
TableHeader: typeof import('./components/ui/table/TableHeader.vue')['default']
|
|
212
|
+
TableRow: typeof import('./components/ui/table/TableRow.vue')['default']
|
|
213
|
+
Tabs: typeof import('./components/ui/tabs/Tabs.vue')['default']
|
|
214
|
+
TabsContent: typeof import('./components/ui/tabs/TabsContent.vue')['default']
|
|
215
|
+
TabsList: typeof import('./components/ui/tabs/TabsList.vue')['default']
|
|
216
|
+
TabsTrigger: typeof import('./components/ui/tabs/TabsTrigger.vue')['default']
|
|
217
|
+
Textarea: typeof import('./components/ui/textarea/Textarea.vue')['default']
|
|
218
|
+
ThemeCustomizer: typeof import('./components/layout/ThemeCustomizer.vue')['default']
|
|
219
|
+
Timeline: typeof import('./components/ui/timeline/Timeline.vue')['default']
|
|
220
|
+
Toggle: typeof import('./components/ui/toggle/Toggle.vue')['default']
|
|
221
|
+
ToggleGroup: typeof import('./components/ui/toggle-group/ToggleGroup.vue')['default']
|
|
222
|
+
ToggleGroupItem: typeof import('./components/ui/toggle-group/ToggleGroupItem.vue')['default']
|
|
223
|
+
Tooltip: typeof import('./components/ui/tooltip/Tooltip.vue')['default']
|
|
224
|
+
TooltipContent: typeof import('./components/ui/tooltip/TooltipContent.vue')['default']
|
|
225
|
+
TooltipProvider: typeof import('./components/ui/tooltip/TooltipProvider.vue')['default']
|
|
226
|
+
TooltipTrigger: typeof import('./components/ui/tooltip/TooltipTrigger.vue')['default']
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatCurrency,
|
|
3
|
+
formatNumber,
|
|
4
|
+
formatCompactNumber,
|
|
5
|
+
formatDate,
|
|
6
|
+
formatDateTime,
|
|
7
|
+
formatTime,
|
|
8
|
+
formatDateTimeWithTz,
|
|
9
|
+
formatRelativeTime,
|
|
10
|
+
formatBytes,
|
|
11
|
+
getInitials,
|
|
12
|
+
truncate,
|
|
13
|
+
type CurrencyFormatOptions,
|
|
14
|
+
type DateTimeFormatOptions,
|
|
15
|
+
type TimeOnlyFormatOptions,
|
|
16
|
+
type TimeFormat,
|
|
17
|
+
} from '@/lib/formatters'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Composable that exposes all data formatting utilities under a single object.
|
|
21
|
+
*
|
|
22
|
+
* Auto-imported via unplugin-auto-import — no explicit import needed in <script setup>.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // In any <script setup> — no import required
|
|
26
|
+
* const fmt = useFormatter()
|
|
27
|
+
*
|
|
28
|
+
* fmt.currency(price) // uses VITE_DEFAULT_CURRENCY / VITE_DEFAULT_LOCALE
|
|
29
|
+
* fmt.currency(price, { currency: 'EUR', locale: 'de-DE' }) // per-call override
|
|
30
|
+
* fmt.date(row.createdAt) // "Aug 21, 2026"
|
|
31
|
+
* fmt.date(row.createdAt, 'short') // "8/21/26"
|
|
32
|
+
* fmt.relative(row.lastActive) // "5 minutes ago"
|
|
33
|
+
* fmt.compact(revenue) // "2.4M"
|
|
34
|
+
* fmt.bytes(file.size) // "4.5 MB"
|
|
35
|
+
* fmt.initials(user.name) // "OM"
|
|
36
|
+
* fmt.truncate(description, 60) // "This is a long des..."
|
|
37
|
+
*/
|
|
38
|
+
export function useFormatter() {
|
|
39
|
+
return {
|
|
40
|
+
/** Format value as localized currency. Defaults to VITE_DEFAULT_CURRENCY / VITE_DEFAULT_LOCALE */
|
|
41
|
+
currency: (value: number | string | null | undefined, opts?: CurrencyFormatOptions) =>
|
|
42
|
+
formatCurrency(value, opts),
|
|
43
|
+
|
|
44
|
+
/** Format number with thousand separators */
|
|
45
|
+
number: (value: number | string | null | undefined, locale?: string) =>
|
|
46
|
+
formatNumber(value, locale),
|
|
47
|
+
|
|
48
|
+
/** Format large numbers in compact notation (1.5K, 2.4M, 1.2B) */
|
|
49
|
+
compact: (value: number | string | null | undefined, locale?: string) =>
|
|
50
|
+
formatCompactNumber(value, locale),
|
|
51
|
+
|
|
52
|
+
/** Format date-only: 'short' | 'medium' | 'long' | 'full' */
|
|
53
|
+
date: (
|
|
54
|
+
date: string | number | Date | null | undefined,
|
|
55
|
+
style: 'short' | 'medium' | 'long' | 'full' = 'medium',
|
|
56
|
+
locale?: string,
|
|
57
|
+
) => formatDate(date, style, locale),
|
|
58
|
+
|
|
59
|
+
/** Format date + time together with 24h / 12h clock and timezone support */
|
|
60
|
+
dateTime: (
|
|
61
|
+
date: string | number | Date | null | undefined,
|
|
62
|
+
options?: DateTimeFormatOptions | string,
|
|
63
|
+
) => formatDateTime(date, options),
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Format time only (e.g. "14:30" or "02:30 PM") with 24h / 12h clock support
|
|
67
|
+
* @example fmt.time(order.createdAt) => "14:30" (default 24h)
|
|
68
|
+
* @example fmt.time(order.createdAt, { format: '12h' }) => "02:30 PM"
|
|
69
|
+
* @example fmt.time(order.createdAt, { showSeconds: true }) => "14:30:00"
|
|
70
|
+
*/
|
|
71
|
+
time: (
|
|
72
|
+
date: string | number | Date | null | undefined,
|
|
73
|
+
options?: TimeOnlyFormatOptions,
|
|
74
|
+
) => formatTime(date, options),
|
|
75
|
+
|
|
76
|
+
/** Format as relative time: "5 minutes ago", "yesterday", "in 3 days" */
|
|
77
|
+
relative: (date: string | number | Date | null | undefined, locale?: string) =>
|
|
78
|
+
formatRelativeTime(date, locale),
|
|
79
|
+
|
|
80
|
+
/** Format byte sizes into human-readable units (KB, MB, GB) with locale-aware decimal separator */
|
|
81
|
+
bytes: (bytes: number | null | undefined, decimals?: number, locale?: string) =>
|
|
82
|
+
formatBytes(bytes, decimals, locale),
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Format date + time with explicit timezone and clock format
|
|
86
|
+
* @param timeZone IANA tz: 'Asia/Jakarta' (WIB) | 'Asia/Makassar' (WITA) | 'Asia/Jayapura' (WIT)
|
|
87
|
+
* @param format '24h' | '12h' | 'auto' (defaults to .env: '24h')
|
|
88
|
+
* @example fmt.dateTimeWithTz(date, 'Asia/Jakarta', '24h') => "21 Agt 2026, 14.30"
|
|
89
|
+
*/
|
|
90
|
+
dateTimeWithTz: (
|
|
91
|
+
date: string | number | Date | null | undefined,
|
|
92
|
+
timeZone?: string,
|
|
93
|
+
format?: TimeFormat,
|
|
94
|
+
locale?: string,
|
|
95
|
+
) => formatDateTimeWithTz(date, timeZone, format, locale),
|
|
96
|
+
|
|
97
|
+
/** Extract 2-letter initials from a full name ("Olivia Martin" → "OM") */
|
|
98
|
+
initials: (name: string | null | undefined) =>
|
|
99
|
+
getInitials(name),
|
|
100
|
+
|
|
101
|
+
/** Truncate long strings with ellipsis */
|
|
102
|
+
truncate: (text: string | null | undefined, length?: number) =>
|
|
103
|
+
truncate(text, length),
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { ref, watch } from 'vue'
|
|
2
|
+
import { useStorage } from '@vueuse/core'
|
|
3
|
+
|
|
4
|
+
export type PrimaryColorKey = 'emerald' | 'indigo' | 'violet' | 'rose' | 'amber' | 'cyan' | 'zinc'
|
|
5
|
+
export type RadiusKey = '0' | '0.25' | '0.375' | '0.5' | '0.75' | '1.0'
|
|
6
|
+
export type ContentWidthKey = 'fluid' | 'boxed'
|
|
7
|
+
|
|
8
|
+
export interface PrimaryColorDefinition {
|
|
9
|
+
name: string
|
|
10
|
+
key: PrimaryColorKey
|
|
11
|
+
hex: string
|
|
12
|
+
light: {
|
|
13
|
+
primary: string
|
|
14
|
+
ring: string
|
|
15
|
+
primaryForeground: string
|
|
16
|
+
}
|
|
17
|
+
dark: {
|
|
18
|
+
primary: string
|
|
19
|
+
ring: string
|
|
20
|
+
primaryForeground: string
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RadiusDefinition {
|
|
25
|
+
label: string
|
|
26
|
+
value: RadiusKey
|
|
27
|
+
rem: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const PRIMARY_COLORS: PrimaryColorDefinition[] = [
|
|
31
|
+
{
|
|
32
|
+
name: 'Emerald',
|
|
33
|
+
key: 'emerald',
|
|
34
|
+
hex: '#10b981',
|
|
35
|
+
light: {
|
|
36
|
+
primary: 'oklch(0.55 0.145 163.2)',
|
|
37
|
+
ring: 'oklch(0.55 0.145 163.2 / 35%)',
|
|
38
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
39
|
+
},
|
|
40
|
+
dark: {
|
|
41
|
+
primary: 'oklch(0.48 0.125 163.2)',
|
|
42
|
+
ring: 'oklch(0.48 0.125 163.2 / 35%)',
|
|
43
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Indigo',
|
|
48
|
+
key: 'indigo',
|
|
49
|
+
hex: '#6366f1',
|
|
50
|
+
light: {
|
|
51
|
+
primary: 'oklch(0.51 0.23 277)',
|
|
52
|
+
ring: 'oklch(0.51 0.23 277 / 35%)',
|
|
53
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
54
|
+
},
|
|
55
|
+
dark: {
|
|
56
|
+
primary: 'oklch(0.59 0.21 277)',
|
|
57
|
+
ring: 'oklch(0.59 0.21 277 / 35%)',
|
|
58
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'Violet',
|
|
63
|
+
key: 'violet',
|
|
64
|
+
hex: '#8b5cf6',
|
|
65
|
+
light: {
|
|
66
|
+
primary: 'oklch(0.54 0.24 293)',
|
|
67
|
+
ring: 'oklch(0.54 0.24 293 / 35%)',
|
|
68
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
69
|
+
},
|
|
70
|
+
dark: {
|
|
71
|
+
primary: 'oklch(0.61 0.22 293)',
|
|
72
|
+
ring: 'oklch(0.61 0.22 293 / 35%)',
|
|
73
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'Rose',
|
|
78
|
+
key: 'rose',
|
|
79
|
+
hex: '#f43f5e',
|
|
80
|
+
light: {
|
|
81
|
+
primary: 'oklch(0.59 0.22 17)',
|
|
82
|
+
ring: 'oklch(0.59 0.22 17 / 35%)',
|
|
83
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
84
|
+
},
|
|
85
|
+
dark: {
|
|
86
|
+
primary: 'oklch(0.64 0.20 17)',
|
|
87
|
+
ring: 'oklch(0.64 0.20 17 / 35%)',
|
|
88
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'Amber',
|
|
93
|
+
key: 'amber',
|
|
94
|
+
hex: '#f59e0b',
|
|
95
|
+
light: {
|
|
96
|
+
primary: 'oklch(0.68 0.19 65)',
|
|
97
|
+
ring: 'oklch(0.68 0.19 65 / 35%)',
|
|
98
|
+
primaryForeground: 'oklch(0.15 0 0)',
|
|
99
|
+
},
|
|
100
|
+
dark: {
|
|
101
|
+
primary: 'oklch(0.74 0.17 65)',
|
|
102
|
+
ring: 'oklch(0.74 0.17 65 / 35%)',
|
|
103
|
+
primaryForeground: 'oklch(0.15 0 0)',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'Cyan',
|
|
108
|
+
key: 'cyan',
|
|
109
|
+
hex: '#06b6d4',
|
|
110
|
+
light: {
|
|
111
|
+
primary: 'oklch(0.62 0.15 215)',
|
|
112
|
+
ring: 'oklch(0.62 0.15 215 / 35%)',
|
|
113
|
+
primaryForeground: 'oklch(0.99 0 0)',
|
|
114
|
+
},
|
|
115
|
+
dark: {
|
|
116
|
+
primary: 'oklch(0.68 0.14 215)',
|
|
117
|
+
ring: 'oklch(0.68 0.14 215 / 35%)',
|
|
118
|
+
primaryForeground: 'oklch(0.15 0 0)',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'Zinc',
|
|
123
|
+
key: 'zinc',
|
|
124
|
+
hex: '#71717a',
|
|
125
|
+
light: {
|
|
126
|
+
primary: 'oklch(0.205 0 0)',
|
|
127
|
+
ring: 'oklch(0.205 0 0 / 35%)',
|
|
128
|
+
primaryForeground: 'oklch(0.985 0 0)',
|
|
129
|
+
},
|
|
130
|
+
dark: {
|
|
131
|
+
primary: 'oklch(0.985 0 0)',
|
|
132
|
+
ring: 'oklch(0.985 0 0 / 35%)',
|
|
133
|
+
primaryForeground: 'oklch(0.145 0 0)',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
export const RADIUS_PRESETS: RadiusDefinition[] = [
|
|
139
|
+
{ label: '0', value: '0', rem: '0rem' },
|
|
140
|
+
{ label: '0.25', value: '0.25', rem: '0.25rem' },
|
|
141
|
+
{ label: '0.375', value: '0.375', rem: '0.375rem' },
|
|
142
|
+
{ label: '0.5', value: '0.5', rem: '0.5rem' },
|
|
143
|
+
{ label: '0.75', value: '0.75', rem: '0.75rem' },
|
|
144
|
+
{ label: '1.0', value: '1.0', rem: '1rem' },
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
export interface ThemeConfig {
|
|
148
|
+
primaryColor: PrimaryColorKey
|
|
149
|
+
radius: RadiusKey
|
|
150
|
+
contentWidth: ContentWidthKey
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const DEFAULT_CONFIG: ThemeConfig = {
|
|
154
|
+
primaryColor: 'emerald',
|
|
155
|
+
radius: '0.375',
|
|
156
|
+
contentWidth: 'fluid',
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const isCustomizerOpen = ref(false)
|
|
160
|
+
const themeConfig = useStorage<ThemeConfig>('nala-theme-config', { ...DEFAULT_CONFIG })
|
|
161
|
+
|
|
162
|
+
// Style element injection helper for reliable CSS variable overrides in both light and dark mode
|
|
163
|
+
let customThemeStyleElement: HTMLStyleElement | null = null
|
|
164
|
+
|
|
165
|
+
function ensureThemeStyleElement(): HTMLStyleElement {
|
|
166
|
+
if (!customThemeStyleElement && typeof document !== 'undefined') {
|
|
167
|
+
customThemeStyleElement = document.getElementById('nala-dynamic-theme-vars') as HTMLStyleElement
|
|
168
|
+
if (!customThemeStyleElement) {
|
|
169
|
+
customThemeStyleElement = document.createElement('style')
|
|
170
|
+
customThemeStyleElement.id = 'nala-dynamic-theme-vars'
|
|
171
|
+
document.head.appendChild(customThemeStyleElement)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return customThemeStyleElement!
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function useThemeConfig() {
|
|
178
|
+
const applyTheme = () => {
|
|
179
|
+
if (typeof document === 'undefined') return
|
|
180
|
+
|
|
181
|
+
const colorDef = PRIMARY_COLORS.find(c => c.key === themeConfig.value.primaryColor) || PRIMARY_COLORS[0]
|
|
182
|
+
const radiusDef = RADIUS_PRESETS.find(r => r.value === themeConfig.value.radius) || RADIUS_PRESETS[2]
|
|
183
|
+
|
|
184
|
+
const styleEl = ensureThemeStyleElement()
|
|
185
|
+
if (styleEl) {
|
|
186
|
+
styleEl.innerHTML = `
|
|
187
|
+
:root {
|
|
188
|
+
--radius: ${radiusDef.rem};
|
|
189
|
+
--primary: ${colorDef.light.primary};
|
|
190
|
+
--ring: ${colorDef.light.ring};
|
|
191
|
+
--primary-foreground: ${colorDef.light.primaryForeground};
|
|
192
|
+
}
|
|
193
|
+
.dark {
|
|
194
|
+
--primary: ${colorDef.dark.primary};
|
|
195
|
+
--ring: ${colorDef.dark.ring};
|
|
196
|
+
--primary-foreground: ${colorDef.dark.primaryForeground};
|
|
197
|
+
}
|
|
198
|
+
`
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Set dataset attribute for inspection
|
|
202
|
+
document.documentElement.dataset.themeColor = colorDef.key
|
|
203
|
+
document.documentElement.dataset.themeRadius = radiusDef.value
|
|
204
|
+
document.documentElement.dataset.contentWidth = themeConfig.value.contentWidth
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const setPrimaryColor = (color: PrimaryColorKey) => {
|
|
208
|
+
themeConfig.value.primaryColor = color
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const setRadius = (radius: RadiusKey) => {
|
|
212
|
+
themeConfig.value.radius = radius
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const setContentWidth = (width: ContentWidthKey) => {
|
|
216
|
+
themeConfig.value.contentWidth = width
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const resetThemeConfig = () => {
|
|
220
|
+
themeConfig.value = { ...DEFAULT_CONFIG }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const toggleCustomizer = (open?: boolean) => {
|
|
224
|
+
if (typeof open === 'boolean') {
|
|
225
|
+
isCustomizerOpen.value = open
|
|
226
|
+
} else {
|
|
227
|
+
isCustomizerOpen.value = !isCustomizerOpen.value
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Watch for changes and apply immediately
|
|
232
|
+
watch(
|
|
233
|
+
() => [themeConfig.value.primaryColor, themeConfig.value.radius, themeConfig.value.contentWidth],
|
|
234
|
+
() => {
|
|
235
|
+
applyTheme()
|
|
236
|
+
},
|
|
237
|
+
{ immediate: true },
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
themeConfig,
|
|
242
|
+
isCustomizerOpen,
|
|
243
|
+
primaryColors: PRIMARY_COLORS,
|
|
244
|
+
radiusPresets: RADIUS_PRESETS,
|
|
245
|
+
setPrimaryColor,
|
|
246
|
+
setRadius,
|
|
247
|
+
setContentWidth,
|
|
248
|
+
resetThemeConfig,
|
|
249
|
+
toggleCustomizer,
|
|
250
|
+
applyTheme,
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { SidebarProvider, SidebarInset } from '@/components/ui/sidebar'
|
|
3
|
+
import AppNavbar from '@/components/layout/AppNavbar.vue'
|
|
4
|
+
import AppSidebar from '@/components/layout/AppSidebar.vue'
|
|
5
|
+
import CommandSearchDialog from '@/components/layout/CommandSearchDialog.vue'
|
|
6
|
+
import { useThemeConfig } from '@/composables/useThemeConfig'
|
|
7
|
+
|
|
8
|
+
const isSearchOpen = ref(false)
|
|
9
|
+
const { themeConfig } = useThemeConfig()
|
|
10
|
+
|
|
11
|
+
// Global keyboard shortcut: Ctrl+K or Cmd+K
|
|
12
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
13
|
+
if ((e.ctrlKey || e.metaKey) && (e.key === 'k' || e.key === 'K')) {
|
|
14
|
+
e.preventDefault()
|
|
15
|
+
isSearchOpen.value = !isSearchOpen.value
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
onMounted(() => {
|
|
20
|
+
window.addEventListener('keydown', handleKeyDown)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
onUnmounted(() => {
|
|
24
|
+
window.removeEventListener('keydown', handleKeyDown)
|
|
25
|
+
})
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<template>
|
|
29
|
+
<SidebarProvider class="h-dvh max-h-dvh min-h-0 w-full overflow-hidden flex flex-col pt-14">
|
|
30
|
+
<!-- Top Navigation Header (Fixed at top) -->
|
|
31
|
+
<AppNavbar @open-search="isSearchOpen = true" />
|
|
32
|
+
|
|
33
|
+
<!-- Main Container below Navbar -->
|
|
34
|
+
<div class="flex flex-1 min-h-0 min-w-0 w-full relative overflow-hidden">
|
|
35
|
+
<!-- Left Sidebar Navigation -->
|
|
36
|
+
<AppSidebar />
|
|
37
|
+
|
|
38
|
+
<!-- Main Scrollable Inset Page View -->
|
|
39
|
+
<SidebarInset class="flex flex-col min-h-0 min-w-0 max-w-full overflow-hidden flex-1">
|
|
40
|
+
<main class="flex-1 min-h-0 overflow-y-auto overflow-x-hidden p-4 sm:p-6 bg-background">
|
|
41
|
+
<div :class="themeConfig.contentWidth === 'boxed' ? 'max-w-7xl mx-auto w-full transition-all duration-300' : 'w-full transition-all duration-300'">
|
|
42
|
+
<RouterView v-slot="{ Component }">
|
|
43
|
+
<Transition name="page" mode="out-in">
|
|
44
|
+
<component :is="Component" />
|
|
45
|
+
</Transition>
|
|
46
|
+
</RouterView>
|
|
47
|
+
</div>
|
|
48
|
+
</main>
|
|
49
|
+
</SidebarInset>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- Quick Search Dialog Modal (Ctrl+K) -->
|
|
53
|
+
<CommandSearchDialog v-model:open="isSearchOpen" />
|
|
54
|
+
</SidebarProvider>
|
|
55
|
+
</template>
|