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