@vestow/vue 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +233 -0
- package/index.ts +8 -0
- package/package.json +68 -0
- package/src/components/accordion/Accordion.vue +45 -0
- package/src/components/accordion/AccordionContent.vue +31 -0
- package/src/components/accordion/AccordionItem.vue +26 -0
- package/src/components/accordion/AccordionTrigger.vue +39 -0
- package/src/components/accordion/index.ts +18 -0
- package/src/components/alert/Alert.vue +17 -0
- package/src/components/alert/AlertDescription.vue +12 -0
- package/src/components/alert/AlertTitle.vue +12 -0
- package/src/components/alert/index.ts +5 -0
- package/src/components/avatar/Avatar.vue +32 -0
- package/src/components/avatar/AvatarFallback.vue +23 -0
- package/src/components/avatar/AvatarImage.vue +18 -0
- package/src/components/avatar/index.ts +3 -0
- package/src/components/badge/Badge.vue +25 -0
- package/src/components/badge/index.ts +3 -0
- package/src/components/breadcrumb/Breadcrumb.vue +14 -0
- package/src/components/breadcrumb/BreadcrumbItem.vue +12 -0
- package/src/components/breadcrumb/BreadcrumbLink.vue +19 -0
- package/src/components/breadcrumb/BreadcrumbPage.vue +12 -0
- package/src/components/breadcrumb/BreadcrumbSeparator.vue +15 -0
- package/src/components/breadcrumb/index.ts +5 -0
- package/src/components/button/Button.vue +55 -0
- package/src/components/button/index.ts +3 -0
- package/src/components/button-group/ButtonGroup.vue +29 -0
- package/src/components/button-group/ButtonGroupSeparator.vue +30 -0
- package/src/components/button-group/ButtonGroupText.vue +29 -0
- package/src/components/button-group/SplitButton.vue +103 -0
- package/src/components/button-group/SplitButtonItems.vue +50 -0
- package/src/components/button-group/index.ts +34 -0
- package/src/components/calendar/Calendar.vue +120 -0
- package/src/components/calendar/RangeCalendar.vue +127 -0
- package/src/components/calendar/index.ts +2 -0
- package/src/components/card/Card.vue +12 -0
- package/src/components/card/CardAction.vue +12 -0
- package/src/components/card/CardContent.vue +12 -0
- package/src/components/card/CardDescription.vue +12 -0
- package/src/components/card/CardFooter.vue +12 -0
- package/src/components/card/CardHeader.vue +15 -0
- package/src/components/card/CardTitle.vue +12 -0
- package/src/components/card/index.ts +7 -0
- package/src/components/carousel/Carousel.vue +164 -0
- package/src/components/carousel/CarouselContent.vue +43 -0
- package/src/components/carousel/CarouselDots.vue +42 -0
- package/src/components/carousel/CarouselItem.vue +58 -0
- package/src/components/carousel/CarouselNext.vue +45 -0
- package/src/components/carousel/CarouselPrevious.vue +45 -0
- package/src/components/carousel/index.ts +44 -0
- package/src/components/cascade-select/CascadeSelect.vue +314 -0
- package/src/components/cascade-select/index.ts +11 -0
- package/src/components/chart/AreaChart.vue +201 -0
- package/src/components/chart/BarChart.vue +389 -0
- package/src/components/chart/ChartContainer.vue +127 -0
- package/src/components/chart/ChartCrosshair.vue +92 -0
- package/src/components/chart/ChartLegend.vue +63 -0
- package/src/components/chart/ChartTooltipCard.vue +49 -0
- package/src/components/chart/LineChart.vue +214 -0
- package/src/components/chart/PieChart.vue +280 -0
- package/src/components/chart/RadarChart.vue +291 -0
- package/src/components/chart/RadialChart.vue +354 -0
- package/src/components/chart/index.ts +30 -0
- package/src/components/chart/polar.ts +5 -0
- package/src/components/chart/tooltip.ts +5 -0
- package/src/components/chart/types.ts +52 -0
- package/src/components/chart/useChartSeries.ts +138 -0
- package/src/components/chart/xy-label.ts +5 -0
- package/src/components/checkbox/Checkbox.vue +81 -0
- package/src/components/checkbox/CheckboxField.vue +129 -0
- package/src/components/checkbox/CheckboxGroup.vue +62 -0
- package/src/components/checkbox/index.ts +21 -0
- package/src/components/chip/Chip.vue +73 -0
- package/src/components/chip/index.ts +3 -0
- package/src/components/code-block/CodeBlock.vue +100 -0
- package/src/components/code-block/index.ts +4 -0
- package/src/components/collapsible/Collapsible.vue +15 -0
- package/src/components/collapsible/CollapsibleContent.vue +26 -0
- package/src/components/collapsible/CollapsibleTrigger.vue +12 -0
- package/src/components/collapsible/index.ts +3 -0
- package/src/components/combobox/Combobox.vue +23 -0
- package/src/components/combobox/ComboboxAnchor.vue +20 -0
- package/src/components/combobox/ComboboxEmpty.vue +21 -0
- package/src/components/combobox/ComboboxGroup.vue +23 -0
- package/src/components/combobox/ComboboxInput.vue +32 -0
- package/src/components/combobox/ComboboxItem.vue +38 -0
- package/src/components/combobox/ComboboxList.vue +43 -0
- package/src/components/combobox/ComboboxSeparator.vue +18 -0
- package/src/components/combobox/ComboboxTrigger.vue +12 -0
- package/src/components/combobox/index.ts +9 -0
- package/src/components/command/Command.vue +54 -0
- package/src/components/command/CommandDialog.vue +41 -0
- package/src/components/command/CommandEmpty.vue +19 -0
- package/src/components/command/CommandGroup.vue +28 -0
- package/src/components/command/CommandInput.vue +25 -0
- package/src/components/command/CommandItem.vue +40 -0
- package/src/components/command/CommandList.vue +13 -0
- package/src/components/command/CommandSeparator.vue +11 -0
- package/src/components/command/CommandShortcut.vue +13 -0
- package/src/components/command/index.ts +34 -0
- package/src/components/command-block/CommandBlock.vue +90 -0
- package/src/components/command-block/index.ts +2 -0
- package/src/components/confirm-dialog/ConfirmDialog.vue +37 -0
- package/src/components/confirm-dialog/index.ts +1 -0
- package/src/components/confirm-popup/ConfirmPopup.vue +123 -0
- package/src/components/confirm-popup/index.ts +1 -0
- package/src/components/context-menu/ContextMenu.vue +15 -0
- package/src/components/context-menu/ContextMenuCheckboxItem.vue +30 -0
- package/src/components/context-menu/ContextMenuContent.vue +36 -0
- package/src/components/context-menu/ContextMenuGroup.vue +12 -0
- package/src/components/context-menu/ContextMenuItem.vue +32 -0
- package/src/components/context-menu/ContextMenuLabel.vue +21 -0
- package/src/components/context-menu/ContextMenuRadioGroup.vue +15 -0
- package/src/components/context-menu/ContextMenuRadioItem.vue +30 -0
- package/src/components/context-menu/ContextMenuSeparator.vue +19 -0
- package/src/components/context-menu/ContextMenuShortcut.vue +13 -0
- package/src/components/context-menu/ContextMenuSub.vue +15 -0
- package/src/components/context-menu/ContextMenuSubContent.vue +26 -0
- package/src/components/context-menu/ContextMenuSubTrigger.vue +26 -0
- package/src/components/context-menu/ContextMenuTrigger.vue +12 -0
- package/src/components/context-menu/index.ts +14 -0
- package/src/components/data-table/DataTable.vue +458 -0
- package/src/components/data-table/DataTableFacetedFilter.vue +97 -0
- package/src/components/data-table/DataTablePagination.vue +103 -0
- package/src/components/data-table/DataTableViewOptions.vue +69 -0
- package/src/components/data-table/features.ts +87 -0
- package/src/components/data-table/index.ts +27 -0
- package/src/components/data-table/pagination-adapter.ts +67 -0
- package/src/components/data-table/selection-column.ts +48 -0
- package/src/components/data-table/types.ts +36 -0
- package/src/components/data-view/DataView.vue +136 -0
- package/src/components/data-view/index.ts +1 -0
- package/src/components/date-picker/DatePicker.vue +117 -0
- package/src/components/date-picker/DateRangePicker.vue +122 -0
- package/src/components/date-picker/index.ts +2 -0
- package/src/components/deferred/Deferred.vue +80 -0
- package/src/components/deferred/index.ts +1 -0
- package/src/components/dialog/Dialog.vue +15 -0
- package/src/components/dialog/DialogClose.vue +12 -0
- package/src/components/dialog/DialogContent.vue +46 -0
- package/src/components/dialog/DialogDescription.vue +19 -0
- package/src/components/dialog/DialogFooter.vue +12 -0
- package/src/components/dialog/DialogHeader.vue +12 -0
- package/src/components/dialog/DialogTitle.vue +19 -0
- package/src/components/dialog/DialogTrigger.vue +12 -0
- package/src/components/dialog/index.ts +10 -0
- package/src/components/doc-example/DocExample.vue +41 -0
- package/src/components/doc-example/index.ts +1 -0
- package/src/components/doc-text/DocText.vue +64 -0
- package/src/components/doc-text/index.ts +1 -0
- package/src/components/dropdown-menu/DropdownMenu.vue +15 -0
- package/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue +33 -0
- package/src/components/dropdown-menu/DropdownMenuContent.vue +36 -0
- package/src/components/dropdown-menu/DropdownMenuGroup.vue +12 -0
- package/src/components/dropdown-menu/DropdownMenuItem.vue +32 -0
- package/src/components/dropdown-menu/DropdownMenuLabel.vue +24 -0
- package/src/components/dropdown-menu/DropdownMenuRadioGroup.vue +15 -0
- package/src/components/dropdown-menu/DropdownMenuRadioItem.vue +33 -0
- package/src/components/dropdown-menu/DropdownMenuSeparator.vue +19 -0
- package/src/components/dropdown-menu/DropdownMenuShortcut.vue +13 -0
- package/src/components/dropdown-menu/DropdownMenuSub.vue +15 -0
- package/src/components/dropdown-menu/DropdownMenuSubContent.vue +29 -0
- package/src/components/dropdown-menu/DropdownMenuSubTrigger.vue +26 -0
- package/src/components/dropdown-menu/DropdownMenuTrigger.vue +12 -0
- package/src/components/dropdown-menu/index.ts +14 -0
- package/src/components/editable/Editable.vue +41 -0
- package/src/components/editable/EditableArea.vue +22 -0
- package/src/components/editable/EditableCancelTrigger.vue +40 -0
- package/src/components/editable/EditableEditTrigger.vue +40 -0
- package/src/components/editable/EditableInput.vue +28 -0
- package/src/components/editable/EditablePreview.vue +34 -0
- package/src/components/editable/EditableSubmitTrigger.vue +40 -0
- package/src/components/editable/index.ts +17 -0
- package/src/components/empty/Empty.vue +17 -0
- package/src/components/empty/EmptyActions.vue +14 -0
- package/src/components/empty/EmptyDescription.vue +12 -0
- package/src/components/empty/EmptyMedia.vue +16 -0
- package/src/components/empty/EmptyTitle.vue +17 -0
- package/src/components/empty/index.ts +7 -0
- package/src/components/field/Field.vue +22 -0
- package/src/components/field/FieldDescription.vue +20 -0
- package/src/components/field/FieldGroup.vue +22 -0
- package/src/components/field/FieldLabel.vue +27 -0
- package/src/components/field/FieldSeparator.vue +28 -0
- package/src/components/field/index.ts +7 -0
- package/src/components/fieldset/Fieldset.vue +126 -0
- package/src/components/fieldset/index.ts +1 -0
- package/src/components/file-upload/FileUpload.vue +149 -0
- package/src/components/file-upload/index.ts +8 -0
- package/src/components/float-label/FloatLabel.vue +26 -0
- package/src/components/float-label/index.ts +3 -0
- package/src/components/form/Form.vue +126 -0
- package/src/components/form/FormDescription.vue +12 -0
- package/src/components/form/FormField.vue +127 -0
- package/src/components/form/FormItem.vue +12 -0
- package/src/components/form/FormLabel.vue +14 -0
- package/src/components/form/FormMessage.vue +31 -0
- package/src/components/form/context.ts +54 -0
- package/src/components/form/errors.ts +6 -0
- package/src/components/form/index.ts +7 -0
- package/src/components/form/types.ts +55 -0
- package/src/components/hover-card/HoverCard.vue +27 -0
- package/src/components/hover-card/HoverCardContent.vue +36 -0
- package/src/components/hover-card/HoverCardTrigger.vue +12 -0
- package/src/components/hover-card/index.ts +3 -0
- package/src/components/ifta-label/IftaLabel.vue +26 -0
- package/src/components/ifta-label/index.ts +1 -0
- package/src/components/index.ts +89 -0
- package/src/components/input/Input.vue +87 -0
- package/src/components/input/index.ts +1 -0
- package/src/components/input-color/ColorArea.vue +36 -0
- package/src/components/input-color/ColorField.vue +32 -0
- package/src/components/input-color/ColorSlider.vue +31 -0
- package/src/components/input-color/InputColor.vue +65 -0
- package/src/components/input-color/index.ts +16 -0
- package/src/components/input-group/InputGroup.vue +26 -0
- package/src/components/input-group/InputGroupAddon.vue +32 -0
- package/src/components/input-group/InputGroupInput.vue +33 -0
- package/src/components/input-group/index.ts +17 -0
- package/src/components/input-number/InputNumber.vue +82 -0
- package/src/components/input-number/index.ts +1 -0
- package/src/components/input-otp/InputOtp.vue +186 -0
- package/src/components/input-otp/index.ts +1 -0
- package/src/components/input-password/InputPassword.vue +116 -0
- package/src/components/input-password/index.ts +5 -0
- package/src/components/input-tags/InputTags.vue +38 -0
- package/src/components/input-tags/InputTagsClear.vue +39 -0
- package/src/components/input-tags/InputTagsInput.vue +27 -0
- package/src/components/input-tags/InputTagsItem.vue +40 -0
- package/src/components/input-tags/InputTagsItemDelete.vue +32 -0
- package/src/components/input-tags/InputTagsItemText.vue +18 -0
- package/src/components/input-tags/index.ts +16 -0
- package/src/components/kbd/Kbd.vue +17 -0
- package/src/components/kbd/KbdGroup.vue +15 -0
- package/src/components/kbd/index.ts +4 -0
- package/src/components/label/Label.vue +23 -0
- package/src/components/label/index.ts +1 -0
- package/src/components/listbox/Listbox.vue +42 -0
- package/src/components/listbox/ListboxContent.vue +22 -0
- package/src/components/listbox/ListboxFilter.vue +34 -0
- package/src/components/listbox/ListboxGroup.vue +31 -0
- package/src/components/listbox/ListboxItem.vue +46 -0
- package/src/components/listbox/index.ts +19 -0
- package/src/components/mask/Mask.vue +205 -0
- package/src/components/mask/index.ts +15 -0
- package/src/components/menubar/Menubar.vue +26 -0
- package/src/components/menubar/MenubarCheckboxItem.vue +30 -0
- package/src/components/menubar/MenubarContent.vue +52 -0
- package/src/components/menubar/MenubarGroup.vue +12 -0
- package/src/components/menubar/MenubarItem.vue +32 -0
- package/src/components/menubar/MenubarLabel.vue +21 -0
- package/src/components/menubar/MenubarMenu.vue +12 -0
- package/src/components/menubar/MenubarRadioGroup.vue +15 -0
- package/src/components/menubar/MenubarRadioItem.vue +30 -0
- package/src/components/menubar/MenubarSeparator.vue +12 -0
- package/src/components/menubar/MenubarShortcut.vue +13 -0
- package/src/components/menubar/MenubarSub.vue +15 -0
- package/src/components/menubar/MenubarSubContent.vue +26 -0
- package/src/components/menubar/MenubarSubTrigger.vue +26 -0
- package/src/components/menubar/MenubarTrigger.vue +30 -0
- package/src/components/menubar/index.ts +29 -0
- package/src/components/navigation-menu/NavigationMenu.vue +43 -0
- package/src/components/navigation-menu/NavigationMenuContent.vue +63 -0
- package/src/components/navigation-menu/NavigationMenuIndicator.vue +31 -0
- package/src/components/navigation-menu/NavigationMenuItem.vue +20 -0
- package/src/components/navigation-menu/NavigationMenuLink.vue +34 -0
- package/src/components/navigation-menu/NavigationMenuList.vue +23 -0
- package/src/components/navigation-menu/NavigationMenuTrigger.vue +38 -0
- package/src/components/navigation-menu/NavigationMenuViewport.vue +34 -0
- package/src/components/navigation-menu/index.ts +18 -0
- package/src/components/order-list/OrderList.vue +168 -0
- package/src/components/order-list/SelectableList.vue +200 -0
- package/src/components/order-list/index.ts +1 -0
- package/src/components/pagination/Pagination.vue +133 -0
- package/src/components/pagination/index.ts +1 -0
- package/src/components/panel/Panel.vue +69 -0
- package/src/components/panel/index.ts +1 -0
- package/src/components/pick-list/PickList.vue +211 -0
- package/src/components/pick-list/index.ts +1 -0
- package/src/components/popover/Popover.vue +15 -0
- package/src/components/popover/PopoverAnchor.vue +12 -0
- package/src/components/popover/PopoverContent.vue +39 -0
- package/src/components/popover/PopoverTrigger.vue +12 -0
- package/src/components/popover/index.ts +4 -0
- package/src/components/progress/Progress.vue +39 -0
- package/src/components/progress/index.ts +1 -0
- package/src/components/props-table/PropsTable.vue +62 -0
- package/src/components/props-table/index.ts +2 -0
- package/src/components/radio-group/RadioGroup.vue +52 -0
- package/src/components/radio-group/RadioGroupItem.vue +80 -0
- package/src/components/radio-group/RadioGroupItemField.vue +128 -0
- package/src/components/radio-group/index.ts +21 -0
- package/src/components/rating/Rating.vue +70 -0
- package/src/components/rating/RatingItem.vue +26 -0
- package/src/components/rating/RatingItemIndicator.vue +28 -0
- package/src/components/rating/RatingStar.vue +16 -0
- package/src/components/rating/index.ts +13 -0
- package/src/components/scroll-area/ScrollArea.vue +52 -0
- package/src/components/scroll-area/index.ts +1 -0
- package/src/components/search-input/SearchInput.vue +46 -0
- package/src/components/search-input/index.ts +1 -0
- package/src/components/select/Select.vue +15 -0
- package/src/components/select/SelectContent.vue +67 -0
- package/src/components/select/SelectGroup.vue +20 -0
- package/src/components/select/SelectItem.vue +59 -0
- package/src/components/select/SelectLabel.vue +20 -0
- package/src/components/select/SelectSeparator.vue +18 -0
- package/src/components/select/SelectTrigger.vue +101 -0
- package/src/components/select/SelectValue.vue +46 -0
- package/src/components/select/index.ts +8 -0
- package/src/components/separator/Separator.vue +25 -0
- package/src/components/separator/index.ts +1 -0
- package/src/components/sheet/Sheet.vue +15 -0
- package/src/components/sheet/SheetClose.vue +12 -0
- package/src/components/sheet/SheetContent.vue +45 -0
- package/src/components/sheet/SheetDescription.vue +19 -0
- package/src/components/sheet/SheetFooter.vue +12 -0
- package/src/components/sheet/SheetHeader.vue +12 -0
- package/src/components/sheet/SheetTitle.vue +19 -0
- package/src/components/sheet/SheetTrigger.vue +12 -0
- package/src/components/sheet/index.ts +10 -0
- package/src/components/sidebar/Sidebar.vue +108 -0
- package/src/components/sidebar/SidebarContent.vue +19 -0
- package/src/components/sidebar/SidebarFooter.vue +19 -0
- package/src/components/sidebar/SidebarGroup.vue +19 -0
- package/src/components/sidebar/SidebarGroupAction.vue +28 -0
- package/src/components/sidebar/SidebarGroupContent.vue +19 -0
- package/src/components/sidebar/SidebarGroupLabel.vue +25 -0
- package/src/components/sidebar/SidebarHeader.vue +19 -0
- package/src/components/sidebar/SidebarInput.vue +15 -0
- package/src/components/sidebar/SidebarInset.vue +22 -0
- package/src/components/sidebar/SidebarMenu.vue +19 -0
- package/src/components/sidebar/SidebarMenuAction.vue +41 -0
- package/src/components/sidebar/SidebarMenuBadge.vue +24 -0
- package/src/components/sidebar/SidebarMenuButton.vue +94 -0
- package/src/components/sidebar/SidebarMenuItem.vue +19 -0
- package/src/components/sidebar/SidebarMenuSkeleton.vue +36 -0
- package/src/components/sidebar/SidebarMenuSub.vue +22 -0
- package/src/components/sidebar/SidebarMenuSubButton.vue +39 -0
- package/src/components/sidebar/SidebarMenuSubItem.vue +19 -0
- package/src/components/sidebar/SidebarProvider.vue +114 -0
- package/src/components/sidebar/SidebarRail.vue +37 -0
- package/src/components/sidebar/SidebarSeparator.vue +15 -0
- package/src/components/sidebar/SidebarTrigger.vue +27 -0
- package/src/components/sidebar/context.ts +39 -0
- package/src/components/sidebar/index.ts +34 -0
- package/src/components/skeleton/Skeleton.vue +10 -0
- package/src/components/skeleton/index.ts +1 -0
- package/src/components/skip-link/SkipLink.vue +45 -0
- package/src/components/skip-link/index.ts +1 -0
- package/src/components/slider/Slider.vue +57 -0
- package/src/components/slider/index.ts +3 -0
- package/src/components/speed-dial/SpeedDial.vue +362 -0
- package/src/components/speed-dial/index.ts +28 -0
- package/src/components/spinner/Spinner.vue +20 -0
- package/src/components/spinner/index.ts +1 -0
- package/src/components/splitter/Splitter.vue +24 -0
- package/src/components/splitter/SplitterHandle.vue +51 -0
- package/src/components/splitter/SplitterPanel.vue +30 -0
- package/src/components/splitter/index.ts +14 -0
- package/src/components/stepper/Stepper.vue +34 -0
- package/src/components/stepper/StepperItem.vue +113 -0
- package/src/components/stepper/index.ts +2 -0
- package/src/components/switch/Switch.vue +35 -0
- package/src/components/switch/index.ts +1 -0
- package/src/components/table/Table.vue +24 -0
- package/src/components/table/TableBody.vue +12 -0
- package/src/components/table/TableCell.vue +12 -0
- package/src/components/table/TableEmpty.vue +20 -0
- package/src/components/table/TableHead.vue +17 -0
- package/src/components/table/TableHeader.vue +12 -0
- package/src/components/table/TableRow.vue +19 -0
- package/src/components/table/index.ts +7 -0
- package/src/components/tabs/Tabs.vue +23 -0
- package/src/components/tabs/TabsContent.vue +23 -0
- package/src/components/tabs/TabsList.vue +26 -0
- package/src/components/tabs/TabsTrigger.vue +30 -0
- package/src/components/tabs/index.ts +4 -0
- package/src/components/textarea/Textarea.vue +25 -0
- package/src/components/textarea/index.ts +1 -0
- package/src/components/theme-controls/LocaleMenu.vue +95 -0
- package/src/components/theme-controls/PaletteMenu.vue +155 -0
- package/src/components/theme-controls/ThemeToggle.vue +21 -0
- package/src/components/theme-controls/index.ts +15 -0
- package/src/components/timeline/Timeline.vue +20 -0
- package/src/components/timeline/TimelineItem.vue +68 -0
- package/src/components/timeline/index.ts +15 -0
- package/src/components/toast/Toaster.vue +62 -0
- package/src/components/toast/index.ts +4 -0
- package/src/components/toast/toast.ts +57 -0
- package/src/components/toggle/Toggle.vue +32 -0
- package/src/components/toggle/ToggleGroup.vue +56 -0
- package/src/components/toggle/ToggleGroupItem.vue +33 -0
- package/src/components/toggle/index.ts +18 -0
- package/src/components/token-table/TokenTable.vue +67 -0
- package/src/components/token-table/index.ts +2 -0
- package/src/components/toolbar/Toolbar.vue +34 -0
- package/src/components/toolbar/ToolbarButton.vue +33 -0
- package/src/components/toolbar/ToolbarSeparator.vue +21 -0
- package/src/components/toolbar/index.ts +3 -0
- package/src/components/tooltip/Tooltip.vue +15 -0
- package/src/components/tooltip/TooltipContent.vue +38 -0
- package/src/components/tooltip/TooltipProvider.vue +16 -0
- package/src/components/tooltip/TooltipTrigger.vue +12 -0
- package/src/components/tooltip/index.ts +4 -0
- package/src/components/tree/Tree.vue +53 -0
- package/src/components/tree/TreeItem.vue +59 -0
- package/src/components/tree/index.ts +21 -0
- package/src/components/tree-select/TreeSelect.vue +141 -0
- package/src/components/tree-select/index.ts +1 -0
- package/src/components/tree-table/TreeTable.vue +302 -0
- package/src/components/tree-table/features.ts +49 -0
- package/src/components/tree-table/index.ts +3 -0
- package/src/components/video-player/VideoPlayer.vue +472 -0
- package/src/components/video-player/index.ts +20 -0
- package/src/composables/index.ts +15 -0
- package/src/composables/useBase.ts +32 -0
- package/src/composables/useChartPalette.ts +33 -0
- package/src/composables/useColorMode.ts +29 -0
- package/src/composables/useConfirm.ts +81 -0
- package/src/composables/useDelayedFlag.ts +62 -0
- package/src/composables/useI18n.ts +107 -0
- package/src/composables/useIsMobile.ts +34 -0
- package/src/composables/useMenuAccent.ts +32 -0
- package/src/composables/useMenuAppearance.ts +31 -0
- package/src/composables/useMenuColor.ts +31 -0
- package/src/composables/usePalette.ts +30 -0
- package/src/composables/useStyle.ts +35 -0
- package/src/composables/useSurface.ts +30 -0
- package/src/composables/useTableQuery.ts +73 -0
- package/src/composables/useThemeController.ts +48 -0
- package/src/i18n/README.md +68 -0
- package/src/i18n/controller.ts +233 -0
- package/src/i18n/dictionary.ts +43 -0
- package/src/i18n/index.ts +34 -0
- package/src/i18n/registry.ts +64 -0
- package/src/i18n/ui/en/ui.json +114 -0
- package/src/i18n/ui/en/zod.json +16 -0
- package/src/i18n/ui/index.ts +48 -0
- package/src/i18n/ui/vi/ui.json +114 -0
- package/src/i18n/ui/vi/zod.json +16 -0
- package/src/lib/date.ts +24 -0
- package/src/lib/focus.ts +12 -0
- package/src/lib/icons.ts +345 -0
- package/src/lib/menu-styles.ts +16 -0
- package/src/lib/menu.ts +20 -0
- package/src/lib/platform.ts +5 -0
- package/src/lib/types.ts +6 -0
- package/src/lib/utils.ts +9 -0
- package/src/lib/zod-messages.ts +127 -0
- package/src/styles/chart.css +30 -0
- package/src/styles/index.css +18 -0
- package/src/variants/README.md +55 -0
- package/src/variants/components/accordion.ts +71 -0
- package/src/variants/components/alert.ts +20 -0
- package/src/variants/components/badge.ts +76 -0
- package/src/variants/components/button-group.ts +136 -0
- package/src/variants/components/button.ts +160 -0
- package/src/variants/components/checkbox.ts +67 -0
- package/src/variants/components/chip.ts +51 -0
- package/src/variants/components/code-block.ts +22 -0
- package/src/variants/components/dialog.ts +28 -0
- package/src/variants/components/empty.ts +60 -0
- package/src/variants/components/field.ts +35 -0
- package/src/variants/components/float-label.ts +95 -0
- package/src/variants/components/input-group.ts +73 -0
- package/src/variants/components/input-password.ts +68 -0
- package/src/variants/components/kbd.ts +47 -0
- package/src/variants/components/picker-trigger.ts +30 -0
- package/src/variants/components/radio-group.ts +63 -0
- package/src/variants/components/sheet.ts +23 -0
- package/src/variants/components/sidebar.ts +33 -0
- package/src/variants/components/slider.ts +49 -0
- package/src/variants/components/timeline.ts +45 -0
- package/src/variants/components/toggle.ts +58 -0
- package/src/variants/index.ts +35 -0
- package/src/variants/lib/chart/polar.ts +139 -0
- package/src/variants/lib/chart/tooltip.ts +101 -0
- package/src/variants/lib/chart/types.ts +172 -0
- package/src/variants/lib/chart/xy-label.ts +42 -0
- package/src/variants/lib/focus.ts +66 -0
- package/src/variants/lib/form-errors.ts +59 -0
- package/src/variants/lib/highlight.ts +548 -0
- package/src/variants/lib/list-move.ts +63 -0
- package/src/variants/lib/mask.ts +106 -0
- package/src/variants/lib/media.ts +56 -0
- package/src/variants/lib/menu-styles.ts +71 -0
- package/src/variants/lib/platform.ts +68 -0
- package/src/variants/lib/tree.ts +119 -0
- package/src/variants/lib/upload.ts +58 -0
- package/src/variants/lib/utils.ts +11 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PrimitiveProps } from 'reka-ui'
|
|
3
|
+
import type { ClassProps } from '../../lib/types'
|
|
4
|
+
import { Primitive } from 'reka-ui'
|
|
5
|
+
import { cn } from '../../lib/utils'
|
|
6
|
+
|
|
7
|
+
// as-child để dùng chung với RouterLink mà không lồng thẻ <a> trong <a>.
|
|
8
|
+
const props = withDefaults(defineProps<PrimitiveProps & ClassProps>(), { as: 'a' })
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<Primitive
|
|
13
|
+
:as="props.as"
|
|
14
|
+
:as-child="props.asChild"
|
|
15
|
+
:class="cn('rounded transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', props.class)"
|
|
16
|
+
>
|
|
17
|
+
<slot />
|
|
18
|
+
</Primitive>
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ClassProps } from '../../lib/types'
|
|
3
|
+
import { cn } from '../../lib/utils'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<ClassProps>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<span role="link" aria-disabled="true" aria-current="page" :class="cn('font-medium text-foreground', props.class)">
|
|
10
|
+
<slot />
|
|
11
|
+
</span>
|
|
12
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ClassProps } from '../../lib/types'
|
|
3
|
+
import { ChevronRight } from '../../lib/icons'
|
|
4
|
+
import { cn } from '../../lib/utils'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<ClassProps>()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<li role="presentation" aria-hidden="true" :class="cn('[&>svg]:size-3.5', props.class)">
|
|
11
|
+
<slot>
|
|
12
|
+
<ChevronRight />
|
|
13
|
+
</slot>
|
|
14
|
+
</li>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as Breadcrumb } from './Breadcrumb.vue'
|
|
2
|
+
export { default as BreadcrumbItem } from './BreadcrumbItem.vue'
|
|
3
|
+
export { default as BreadcrumbLink } from './BreadcrumbLink.vue'
|
|
4
|
+
export { default as BreadcrumbPage } from './BreadcrumbPage.vue'
|
|
5
|
+
export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PrimitiveProps } from 'reka-ui'
|
|
3
|
+
import type { ClassProps } from '../../lib/types'
|
|
4
|
+
import type { ButtonVariants } from './index'
|
|
5
|
+
import { Primitive } from 'reka-ui'
|
|
6
|
+
import { computed } from 'vue'
|
|
7
|
+
import { LoaderCircle } from '../../lib/icons'
|
|
8
|
+
import { cn } from '../../lib/utils'
|
|
9
|
+
import { buttonVariants } from './index'
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(
|
|
12
|
+
defineProps<PrimitiveProps & ClassProps & {
|
|
13
|
+
variant?: ButtonVariants['variant']
|
|
14
|
+
size?: ButtonVariants['size']
|
|
15
|
+
/** Kiểu tô: `solid` đặc, `soft` nền pha loãng, `glass` kính. */
|
|
16
|
+
tone?: ButtonVariants['tone']
|
|
17
|
+
/**
|
|
18
|
+
* KIỂU TÔ — `solid` · `soft` · `surface` · `outline` · `ghost`.
|
|
19
|
+
*
|
|
20
|
+
* Trục tách khỏi `variant` theo mô hình Radix Themes. `surface` là nền pha
|
|
21
|
+
* loãng KÈM viền, ô mà `variant="outline" tone="soft"` từng không có nghĩa.
|
|
22
|
+
* Xem `CLAUDE.md`, mục "Trục `fill`".
|
|
23
|
+
*/
|
|
24
|
+
fill?: ButtonVariants['fill']
|
|
25
|
+
/** Hiện spinner và chặn tương tác. Không tự set disabled để giữ được focus. */
|
|
26
|
+
loading?: boolean
|
|
27
|
+
disabled?: boolean
|
|
28
|
+
}>(),
|
|
29
|
+
{ as: 'button', loading: false, disabled: false },
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
// Khi `as` là <button> thì phải có type, nếu không trình duyệt mặc định "submit"
|
|
33
|
+
// và bấm nút trong form sẽ submit ngoài ý muốn.
|
|
34
|
+
//
|
|
35
|
+
// `asChild` phải loại trừ: lúc đó element thật do slot quyết định, mà `as` vẫn
|
|
36
|
+
// còn giá trị mặc định `'button'` — nên `<Button as-child><a/></Button>` từng ra
|
|
37
|
+
// `<a type="button">`, một thuộc tính vô nghĩa trên thẻ neo.
|
|
38
|
+
const nativeType = computed(() => (props.as === 'button' && !props.asChild ? 'button' : undefined))
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<Primitive
|
|
43
|
+
:as="as"
|
|
44
|
+
:as-child="asChild"
|
|
45
|
+
:type="nativeType"
|
|
46
|
+
:disabled="disabled || undefined"
|
|
47
|
+
:aria-disabled="loading || disabled || undefined"
|
|
48
|
+
:aria-busy="loading || undefined"
|
|
49
|
+
:data-loading="loading || undefined"
|
|
50
|
+
:class="cn(buttonVariants({ variant, size, tone, fill }), props.class)"
|
|
51
|
+
>
|
|
52
|
+
<LoaderCircle v-if="loading" class="animate-spin" aria-hidden="true" />
|
|
53
|
+
<slot />
|
|
54
|
+
</Primitive>
|
|
55
|
+
</template>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PrimitiveProps } from 'reka-ui'
|
|
3
|
+
import type { ClassProps } from '../../lib/types'
|
|
4
|
+
import type { ButtonGroupVariants } from './index'
|
|
5
|
+
import { Primitive } from 'reka-ui'
|
|
6
|
+
import { cn } from '../../lib/utils'
|
|
7
|
+
import { buttonGroupVariants } from './index'
|
|
8
|
+
|
|
9
|
+
const props = withDefaults(
|
|
10
|
+
defineProps<PrimitiveProps & ClassProps & {
|
|
11
|
+
/** `horizontal` xếp ngang, `vertical` xếp dọc và gộp viền theo chiều dọc. */
|
|
12
|
+
orientation?: ButtonGroupVariants['orientation']
|
|
13
|
+
}>(),
|
|
14
|
+
{ as: 'div', orientation: 'horizontal' },
|
|
15
|
+
)
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<Primitive
|
|
20
|
+
:as="as"
|
|
21
|
+
:as-child="asChild"
|
|
22
|
+
role="group"
|
|
23
|
+
data-slot="button-group"
|
|
24
|
+
:data-orientation="props.orientation"
|
|
25
|
+
:class="cn(buttonGroupVariants({ orientation: props.orientation }), props.class)"
|
|
26
|
+
>
|
|
27
|
+
<slot />
|
|
28
|
+
</Primitive>
|
|
29
|
+
</template>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ClassProps } from '../../lib/types'
|
|
3
|
+
import { Separator } from 'reka-ui'
|
|
4
|
+
import { cn } from '../../lib/utils'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(
|
|
7
|
+
defineProps<ClassProps & {
|
|
8
|
+
/**
|
|
9
|
+
* Hướng của chính đường kẻ, không phải hướng của nhóm: nhóm nằm ngang thì
|
|
10
|
+
* cần đường kẻ **dọc** — nên mặc định là `vertical`.
|
|
11
|
+
*/
|
|
12
|
+
orientation?: 'horizontal' | 'vertical'
|
|
13
|
+
}>(),
|
|
14
|
+
{ orientation: 'vertical' },
|
|
15
|
+
)
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<Separator
|
|
20
|
+
:orientation="props.orientation"
|
|
21
|
+
decorative
|
|
22
|
+
data-slot="button-group-separator"
|
|
23
|
+
:class="cn(
|
|
24
|
+
// `relative` để đường kẻ nằm trên viền của hai nút hai bên, không bị đè.
|
|
25
|
+
'relative shrink-0 self-stretch bg-input',
|
|
26
|
+
props.orientation === 'vertical' ? 'my-px h-auto w-px' : 'mx-px h-px w-auto',
|
|
27
|
+
props.class,
|
|
28
|
+
)"
|
|
29
|
+
/>
|
|
30
|
+
</template>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PrimitiveProps } from 'reka-ui'
|
|
3
|
+
import type { ClassProps } from '../../lib/types'
|
|
4
|
+
import { Primitive } from 'reka-ui'
|
|
5
|
+
import { cn } from '../../lib/utils'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(
|
|
8
|
+
defineProps<PrimitiveProps & ClassProps>(),
|
|
9
|
+
{ as: 'div' },
|
|
10
|
+
)
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<Primitive
|
|
15
|
+
:as="as"
|
|
16
|
+
:as-child="asChild"
|
|
17
|
+
data-slot="button-group-text"
|
|
18
|
+
:class="cn(
|
|
19
|
+
// Cùng chiều cao và bán kính với Button cỡ mặc định để ghép vào nhóm là
|
|
20
|
+
// vừa khít; không có hover vì đây là nhãn, không phải nút.
|
|
21
|
+
'inline-flex h-8 items-center gap-1.5 rounded-lg border border-input bg-muted px-2.5',
|
|
22
|
+
'text-sm font-medium text-muted-foreground',
|
|
23
|
+
'[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
|
24
|
+
props.class,
|
|
25
|
+
)"
|
|
26
|
+
>
|
|
27
|
+
<slot />
|
|
28
|
+
</Primitive>
|
|
29
|
+
</template>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ClassProps } from '../../lib/types'
|
|
3
|
+
import type { ButtonVariants } from '../button'
|
|
4
|
+
import type { SplitButtonItem } from './index'
|
|
5
|
+
import { computed, ref } from 'vue'
|
|
6
|
+
import { useI18n } from '../../composables/useI18n'
|
|
7
|
+
import { ChevronDown } from '../../lib/icons'
|
|
8
|
+
import { cn } from '../../lib/utils'
|
|
9
|
+
import { Button } from '../button'
|
|
10
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '../dropdown-menu'
|
|
11
|
+
import ButtonGroup from './ButtonGroup.vue'
|
|
12
|
+
import SplitButtonItems from './SplitButtonItems.vue'
|
|
13
|
+
|
|
14
|
+
const props = withDefaults(
|
|
15
|
+
defineProps<ClassProps & {
|
|
16
|
+
/** Nhãn của nút hành động chính. Slot mặc định ghi đè được. */
|
|
17
|
+
label?: string
|
|
18
|
+
/** Các mục trong menu xổ xuống. */
|
|
19
|
+
model?: SplitButtonItem[]
|
|
20
|
+
variant?: ButtonVariants['variant']
|
|
21
|
+
size?: Extract<ButtonVariants['size'], 'xs' | 'sm' | 'default' | 'lg'>
|
|
22
|
+
tone?: ButtonVariants['tone']
|
|
23
|
+
disabled?: boolean
|
|
24
|
+
/** Chỉ áp cho nút hành động chính; nút xổ menu vẫn bấm được. */
|
|
25
|
+
loading?: boolean
|
|
26
|
+
/** Tên cho nút xổ menu — nó chỉ có icon nên bắt buộc phải có. */
|
|
27
|
+
menuLabel?: string
|
|
28
|
+
}>(),
|
|
29
|
+
{
|
|
30
|
+
model: () => [],
|
|
31
|
+
size: 'default',
|
|
32
|
+
disabled: false,
|
|
33
|
+
loading: false,
|
|
34
|
+
},
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
const emit = defineEmits<{ click: [event: MouseEvent] }>()
|
|
38
|
+
|
|
39
|
+
const { t } = useI18n()
|
|
40
|
+
|
|
41
|
+
// Xem ghi chú ở SpeedDial về lý do không đặt trong `withDefaults`.
|
|
42
|
+
const menuLabel = computed(() => props.menuLabel ?? t('ui.splitButton.more'))
|
|
43
|
+
|
|
44
|
+
const open = ref(false)
|
|
45
|
+
|
|
46
|
+
/** Nút xổ menu là ô vuông cùng chiều cao với nút chính. */
|
|
47
|
+
const TRIGGER_SIZE = {
|
|
48
|
+
xs: 'icon-xs',
|
|
49
|
+
sm: 'icon-sm',
|
|
50
|
+
default: 'icon',
|
|
51
|
+
lg: 'icon-lg',
|
|
52
|
+
} as const
|
|
53
|
+
|
|
54
|
+
const triggerSize = computed(() => TRIGGER_SIZE[props.size])
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<template>
|
|
58
|
+
<ButtonGroup
|
|
59
|
+
:class="cn(
|
|
60
|
+
// Trả lại viền trái cho nút xổ menu — ButtonGroup vốn bỏ nó đi để gộp
|
|
61
|
+
// viền chung. Màu lấy từ `currentColor` của chính nút nên tự hợp với mọi
|
|
62
|
+
// variant: nền đặc thì kẻ sáng, nền nhạt thì kẻ tối. `bg-input` của
|
|
63
|
+
// ButtonGroupSeparator không làm được vậy vì nó thừa kế màu chữ của NHÓM.
|
|
64
|
+
'[&>*:not(:first-child)]:border-l [&>*:not(:first-child)]:border-l-current/20',
|
|
65
|
+
props.class,
|
|
66
|
+
)"
|
|
67
|
+
>
|
|
68
|
+
<Button
|
|
69
|
+
:variant="variant"
|
|
70
|
+
:size="size"
|
|
71
|
+
:tone="tone"
|
|
72
|
+
:disabled="disabled"
|
|
73
|
+
:loading="loading"
|
|
74
|
+
@click="emit('click', $event)"
|
|
75
|
+
>
|
|
76
|
+
<slot name="icon" />
|
|
77
|
+
<slot>{{ label }}</slot>
|
|
78
|
+
</Button>
|
|
79
|
+
|
|
80
|
+
<DropdownMenu v-model:open="open">
|
|
81
|
+
<DropdownMenuTrigger as-child>
|
|
82
|
+
<Button
|
|
83
|
+
:variant="variant"
|
|
84
|
+
:size="triggerSize"
|
|
85
|
+
:tone="tone"
|
|
86
|
+
:disabled="disabled"
|
|
87
|
+
:aria-label="menuLabel"
|
|
88
|
+
>
|
|
89
|
+
<slot name="dropdownicon">
|
|
90
|
+
<ChevronDown
|
|
91
|
+
class="transition-transform duration-(--duration-base) motion-reduce:transition-none"
|
|
92
|
+
:class="open && '-rotate-180'"
|
|
93
|
+
/>
|
|
94
|
+
</slot>
|
|
95
|
+
</Button>
|
|
96
|
+
</DropdownMenuTrigger>
|
|
97
|
+
|
|
98
|
+
<DropdownMenuContent align="end">
|
|
99
|
+
<SplitButtonItems :items="model" />
|
|
100
|
+
</DropdownMenuContent>
|
|
101
|
+
</DropdownMenu>
|
|
102
|
+
</ButtonGroup>
|
|
103
|
+
</template>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { SplitButtonItem } from './index'
|
|
3
|
+
import {
|
|
4
|
+
DropdownMenuItem,
|
|
5
|
+
DropdownMenuSeparator,
|
|
6
|
+
DropdownMenuShortcut,
|
|
7
|
+
DropdownMenuSub,
|
|
8
|
+
DropdownMenuSubContent,
|
|
9
|
+
DropdownMenuSubTrigger,
|
|
10
|
+
} from '../dropdown-menu'
|
|
11
|
+
|
|
12
|
+
defineProps<{ items: SplitButtonItem[] }>()
|
|
13
|
+
|
|
14
|
+
function run(item: SplitButtonItem): void {
|
|
15
|
+
item.command?.(item)
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<!-- Component tự gọi chính nó để dựng submenu lồng nhau, không giới hạn cấp. -->
|
|
21
|
+
<template v-for="(item, index) in items" :key="index">
|
|
22
|
+
<DropdownMenuSeparator v-if="item.separator" />
|
|
23
|
+
|
|
24
|
+
<DropdownMenuSub v-else-if="item.items?.length">
|
|
25
|
+
<DropdownMenuSubTrigger :disabled="item.disabled">
|
|
26
|
+
<component :is="item.icon" v-if="item.icon" />
|
|
27
|
+
{{ item.label }}
|
|
28
|
+
</DropdownMenuSubTrigger>
|
|
29
|
+
<DropdownMenuSubContent>
|
|
30
|
+
<SplitButtonItems :items="item.items" />
|
|
31
|
+
</DropdownMenuSubContent>
|
|
32
|
+
</DropdownMenuSub>
|
|
33
|
+
|
|
34
|
+
<DropdownMenuItem
|
|
35
|
+
v-else
|
|
36
|
+
:as="item.url ? 'a' : undefined"
|
|
37
|
+
:href="item.url"
|
|
38
|
+
:target="item.target"
|
|
39
|
+
:disabled="item.disabled"
|
|
40
|
+
:variant="item.variant"
|
|
41
|
+
@select="run(item)"
|
|
42
|
+
>
|
|
43
|
+
<component :is="item.icon" v-if="item.icon" />
|
|
44
|
+
{{ item.label }}
|
|
45
|
+
<DropdownMenuShortcut v-if="item.shortcut">
|
|
46
|
+
{{ item.shortcut }}
|
|
47
|
+
</DropdownMenuShortcut>
|
|
48
|
+
</DropdownMenuItem>
|
|
49
|
+
</template>
|
|
50
|
+
</template>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { MenuActionItem } from '../../lib/menu'
|
|
2
|
+
|
|
3
|
+
export { buttonGroupVariants, type ButtonGroupVariants } from '../../variants/components/button-group'
|
|
4
|
+
export { default as ButtonGroup } from './ButtonGroup.vue'
|
|
5
|
+
export { default as ButtonGroupSeparator } from './ButtonGroupSeparator.vue'
|
|
6
|
+
|
|
7
|
+
export { default as ButtonGroupText } from './ButtonGroupText.vue'
|
|
8
|
+
// SplitButton KHÔNG phải một component riêng: nó chính là một ButtonGroup gồm
|
|
9
|
+
// hai nút — nút hành động và nút xổ menu — nên nằm cùng thư mục. Tách ra sẽ
|
|
10
|
+
// thành hai component nói cùng một chuyện. shadcn cũng không có SplitButton, ở
|
|
11
|
+
// đó nó chỉ là một ví dụ của ButtonGroup; PrimeVue phải làm component riêng vì
|
|
12
|
+
// không có ButtonGroup để dựng lên.
|
|
13
|
+
export { default as SplitButton } from './SplitButton.vue'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Một mục trong menu của `SplitButton`.
|
|
17
|
+
*
|
|
18
|
+
* Sáu trường chung (label, icon, command, url, target, disabled) nằm ở
|
|
19
|
+
* `MenuActionItem` — dùng chung với `SpeedDialItem` để hai component không trôi
|
|
20
|
+
* khỏi nhau. Phần thêm dưới đây là ba dạng loại trừ nhau, xét theo thứ tự:
|
|
21
|
+
* `separator` là đường kẻ, có `items` là submenu, còn lại là mục thường.
|
|
22
|
+
*/
|
|
23
|
+
export interface SplitButtonItem extends MenuActionItem {
|
|
24
|
+
/** Đường kẻ ngăn nhóm; mọi trường khác bị bỏ qua. */
|
|
25
|
+
separator?: boolean
|
|
26
|
+
/** Có `items` thì mục thành submenu, `command` và `url` không còn tác dụng. */
|
|
27
|
+
items?: SplitButtonItem[]
|
|
28
|
+
/** Hành động nguy hiểm (xoá, thu hồi quyền) — hiện màu destructive. */
|
|
29
|
+
variant?: 'default' | 'destructive'
|
|
30
|
+
/** Phím tắt hiện mờ ở mép phải. */
|
|
31
|
+
shortcut?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { default as SplitButtonItems } from './SplitButtonItems.vue'
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DateValue } from '@internationalized/date'
|
|
3
|
+
import type { CalendarRootEmits, CalendarRootProps } from 'reka-ui'
|
|
4
|
+
import type { ClassProps } from '../../lib/types'
|
|
5
|
+
import { DateFormatter, getLocalTimeZone } from '@internationalized/date'
|
|
6
|
+
import {
|
|
7
|
+
CalendarCell,
|
|
8
|
+
CalendarCellTrigger,
|
|
9
|
+
CalendarGrid,
|
|
10
|
+
CalendarGridBody,
|
|
11
|
+
CalendarGridHead,
|
|
12
|
+
CalendarGridRow,
|
|
13
|
+
CalendarHeadCell,
|
|
14
|
+
CalendarHeader,
|
|
15
|
+
CalendarHeading,
|
|
16
|
+
CalendarNext,
|
|
17
|
+
CalendarPrev,
|
|
18
|
+
CalendarRoot,
|
|
19
|
+
useForwardPropsEmits,
|
|
20
|
+
} from 'reka-ui'
|
|
21
|
+
import { computed } from 'vue'
|
|
22
|
+
import { ChevronLeft, ChevronRight } from '../../lib/icons'
|
|
23
|
+
import { cn } from '../../lib/utils'
|
|
24
|
+
|
|
25
|
+
const props = withDefaults(
|
|
26
|
+
defineProps<CalendarRootProps & ClassProps>(),
|
|
27
|
+
{ locale: 'vi-VN', weekStartsOn: 1, fixedWeeks: true },
|
|
28
|
+
)
|
|
29
|
+
const emits = defineEmits<CalendarRootEmits>()
|
|
30
|
+
|
|
31
|
+
const delegated = computed(() => {
|
|
32
|
+
const { class: _class, ...rest } = props
|
|
33
|
+
return rest
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const forwarded = useForwardPropsEmits(delegated, emits)
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Tên cho từng lưới tháng.
|
|
40
|
+
*
|
|
41
|
+
* reka render lưới là `<table role="application">`. Role đó **xoá sạch** ngữ
|
|
42
|
+
* nghĩa bảng và bắt trình đọc màn hình chuyển sang chế độ ứng dụng — nhờ vậy
|
|
43
|
+
* phím mũi tên đi thẳng vào lịch thay vì bị chế độ đọc nuốt mất. Cái giá: một
|
|
44
|
+
* vùng `application` không tên chỉ được đọc là "application". reka không tự
|
|
45
|
+
* đặt tên, nên phải tự khai `aria-label`.
|
|
46
|
+
*/
|
|
47
|
+
function monthLabel(month: DateValue): string {
|
|
48
|
+
return new DateFormatter(props.locale, { month: 'long', year: 'numeric' })
|
|
49
|
+
.format(month.toDate(getLocalTimeZone()))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const navButton = cn(
|
|
53
|
+
'inline-flex size-7 items-center justify-center rounded-md border border-input bg-background',
|
|
54
|
+
'text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground',
|
|
55
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
56
|
+
'disabled:pointer-events-none disabled:opacity-40',
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
const cellTrigger = cn(
|
|
60
|
+
'relative inline-flex size-8 items-center justify-center rounded-md text-sm font-normal transition-colors',
|
|
61
|
+
'hover:bg-accent hover:text-accent-foreground',
|
|
62
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
63
|
+
'data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[selected]:hover:bg-primary',
|
|
64
|
+
'data-[today]:font-semibold data-[today]:text-primary data-[selected]:data-[today]:text-primary-foreground',
|
|
65
|
+
'data-[outside-view]:text-muted-foreground/50',
|
|
66
|
+
'data-[unavailable]:text-muted-foreground/50 data-[unavailable]:line-through',
|
|
67
|
+
'data-[disabled]:pointer-events-none data-[disabled]:opacity-40',
|
|
68
|
+
)
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<CalendarRoot
|
|
73
|
+
v-slot="{ grid, weekDays }"
|
|
74
|
+
v-bind="forwarded"
|
|
75
|
+
:class="cn('rounded-md p-3', props.class)"
|
|
76
|
+
>
|
|
77
|
+
<CalendarHeader class="flex items-center justify-between pb-3">
|
|
78
|
+
<CalendarPrev :class="navButton">
|
|
79
|
+
<ChevronLeft class="size-4" />
|
|
80
|
+
</CalendarPrev>
|
|
81
|
+
<CalendarHeading class="text-sm font-medium capitalize" />
|
|
82
|
+
<CalendarNext :class="navButton">
|
|
83
|
+
<ChevronRight class="size-4" />
|
|
84
|
+
</CalendarNext>
|
|
85
|
+
</CalendarHeader>
|
|
86
|
+
|
|
87
|
+
<div class="flex flex-col gap-4 sm:flex-row">
|
|
88
|
+
<CalendarGrid
|
|
89
|
+
v-for="month in grid"
|
|
90
|
+
:key="month.value.toString()"
|
|
91
|
+
:aria-label="monthLabel(month.value)"
|
|
92
|
+
class="w-full border-collapse"
|
|
93
|
+
>
|
|
94
|
+
<CalendarGridHead>
|
|
95
|
+
<CalendarGridRow class="flex w-full justify-between">
|
|
96
|
+
<CalendarHeadCell
|
|
97
|
+
v-for="day in weekDays"
|
|
98
|
+
:key="day"
|
|
99
|
+
class="w-8 text-[0.7rem] font-normal capitalize text-muted-foreground"
|
|
100
|
+
>
|
|
101
|
+
{{ day }}
|
|
102
|
+
</CalendarHeadCell>
|
|
103
|
+
</CalendarGridRow>
|
|
104
|
+
</CalendarGridHead>
|
|
105
|
+
|
|
106
|
+
<CalendarGridBody class="grid">
|
|
107
|
+
<CalendarGridRow
|
|
108
|
+
v-for="(weekDates, index) in month.rows"
|
|
109
|
+
:key="`week-${index}`"
|
|
110
|
+
class="mt-1 flex w-full justify-between"
|
|
111
|
+
>
|
|
112
|
+
<CalendarCell v-for="weekDate in weekDates" :key="weekDate.toString()" :date="weekDate" class="p-0">
|
|
113
|
+
<CalendarCellTrigger :day="weekDate" :month="month.value" :class="cellTrigger" />
|
|
114
|
+
</CalendarCell>
|
|
115
|
+
</CalendarGridRow>
|
|
116
|
+
</CalendarGridBody>
|
|
117
|
+
</CalendarGrid>
|
|
118
|
+
</div>
|
|
119
|
+
</CalendarRoot>
|
|
120
|
+
</template>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DateValue } from '@internationalized/date'
|
|
3
|
+
import type { RangeCalendarRootEmits, RangeCalendarRootProps } from 'reka-ui'
|
|
4
|
+
import type { ClassProps } from '../../lib/types'
|
|
5
|
+
import { DateFormatter, getLocalTimeZone } from '@internationalized/date'
|
|
6
|
+
import {
|
|
7
|
+
RangeCalendarCell,
|
|
8
|
+
RangeCalendarCellTrigger,
|
|
9
|
+
RangeCalendarGrid,
|
|
10
|
+
RangeCalendarGridBody,
|
|
11
|
+
RangeCalendarGridHead,
|
|
12
|
+
RangeCalendarGridRow,
|
|
13
|
+
RangeCalendarHeadCell,
|
|
14
|
+
RangeCalendarHeader,
|
|
15
|
+
RangeCalendarHeading,
|
|
16
|
+
RangeCalendarNext,
|
|
17
|
+
RangeCalendarPrev,
|
|
18
|
+
RangeCalendarRoot,
|
|
19
|
+
useForwardPropsEmits,
|
|
20
|
+
} from 'reka-ui'
|
|
21
|
+
import { computed } from 'vue'
|
|
22
|
+
import { ChevronLeft, ChevronRight } from '../../lib/icons'
|
|
23
|
+
import { cn } from '../../lib/utils'
|
|
24
|
+
|
|
25
|
+
const props = withDefaults(
|
|
26
|
+
defineProps<RangeCalendarRootProps & ClassProps>(),
|
|
27
|
+
{ locale: 'vi-VN', weekStartsOn: 1, fixedWeeks: true, numberOfMonths: 2 },
|
|
28
|
+
)
|
|
29
|
+
const emits = defineEmits<RangeCalendarRootEmits>()
|
|
30
|
+
|
|
31
|
+
const delegated = computed(() => {
|
|
32
|
+
const { class: _class, ...rest } = props
|
|
33
|
+
return rest
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const forwarded = useForwardPropsEmits(delegated, emits)
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Tên cho từng lưới tháng. Xem chú thích cùng tên trong `Calendar.vue` —
|
|
40
|
+
* `role="application"` của reka không có tên, phải tự khai `aria-label`.
|
|
41
|
+
* Ở đây quan trọng hơn: lưới phạm vi mặc định hiện **hai** tháng, không có tên
|
|
42
|
+
* thì trình đọc màn hình gặp hai vùng giống hệt nhau.
|
|
43
|
+
*/
|
|
44
|
+
function monthLabel(month: DateValue): string {
|
|
45
|
+
return new DateFormatter(props.locale, { month: 'long', year: 'numeric' })
|
|
46
|
+
.format(month.toDate(getLocalTimeZone()))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const navButton = cn(
|
|
50
|
+
'inline-flex size-7 items-center justify-center rounded-md border border-input bg-background',
|
|
51
|
+
'text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground',
|
|
52
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
53
|
+
'disabled:pointer-events-none disabled:opacity-40',
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Giống `Calendar` cộng ba trạng thái chỉ khoảng ngày mới có.
|
|
58
|
+
*
|
|
59
|
+
* Ô ở GIỮA khoảng bo vuông và tô nền nhạt, chỉ hai đầu mới bo tròn và tô đặc —
|
|
60
|
+
* nếu ô nào cũng bo tròn thì dải chọn đứt quãng, không đọc ra là một khoảng
|
|
61
|
+
* liền. `data-selection-start` / `data-selection-end` là của reka.
|
|
62
|
+
*/
|
|
63
|
+
const cellTrigger = cn(
|
|
64
|
+
'relative inline-flex size-8 items-center justify-center rounded-md text-sm font-normal transition-colors',
|
|
65
|
+
'hover:bg-accent hover:text-accent-foreground',
|
|
66
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
67
|
+
'data-[selected]:bg-accent data-[selected]:rounded-none',
|
|
68
|
+
'data-[selection-start]:rounded-l-md data-[selection-start]:bg-primary data-[selection-start]:text-primary-foreground',
|
|
69
|
+
'data-[selection-end]:rounded-r-md data-[selection-end]:bg-primary data-[selection-end]:text-primary-foreground',
|
|
70
|
+
'data-[today]:font-semibold data-[today]:text-primary',
|
|
71
|
+
'data-[selection-start]:data-[today]:text-primary-foreground data-[selection-end]:data-[today]:text-primary-foreground',
|
|
72
|
+
'data-[outside-view]:text-muted-foreground/50',
|
|
73
|
+
'data-[unavailable]:text-muted-foreground/50 data-[unavailable]:line-through',
|
|
74
|
+
'data-[disabled]:pointer-events-none data-[disabled]:opacity-40',
|
|
75
|
+
)
|
|
76
|
+
</script>
|
|
77
|
+
|
|
78
|
+
<template>
|
|
79
|
+
<RangeCalendarRoot
|
|
80
|
+
v-slot="{ grid, weekDays }"
|
|
81
|
+
v-bind="forwarded"
|
|
82
|
+
:class="cn('rounded-md p-3', props.class)"
|
|
83
|
+
>
|
|
84
|
+
<RangeCalendarHeader class="flex items-center justify-between pb-3">
|
|
85
|
+
<RangeCalendarPrev :class="navButton">
|
|
86
|
+
<ChevronLeft class="size-4" />
|
|
87
|
+
</RangeCalendarPrev>
|
|
88
|
+
<RangeCalendarHeading class="text-sm font-medium capitalize" />
|
|
89
|
+
<RangeCalendarNext :class="navButton">
|
|
90
|
+
<ChevronRight class="size-4" />
|
|
91
|
+
</RangeCalendarNext>
|
|
92
|
+
</RangeCalendarHeader>
|
|
93
|
+
|
|
94
|
+
<div class="flex flex-col gap-4 sm:flex-row">
|
|
95
|
+
<RangeCalendarGrid
|
|
96
|
+
v-for="month in grid"
|
|
97
|
+
:key="month.value.toString()"
|
|
98
|
+
:aria-label="monthLabel(month.value)"
|
|
99
|
+
class="w-full border-collapse"
|
|
100
|
+
>
|
|
101
|
+
<RangeCalendarGridHead>
|
|
102
|
+
<RangeCalendarGridRow class="flex w-full justify-between">
|
|
103
|
+
<RangeCalendarHeadCell
|
|
104
|
+
v-for="day in weekDays"
|
|
105
|
+
:key="day"
|
|
106
|
+
class="w-8 text-[0.7rem] font-normal capitalize text-muted-foreground"
|
|
107
|
+
>
|
|
108
|
+
{{ day }}
|
|
109
|
+
</RangeCalendarHeadCell>
|
|
110
|
+
</RangeCalendarGridRow>
|
|
111
|
+
</RangeCalendarGridHead>
|
|
112
|
+
|
|
113
|
+
<RangeCalendarGridBody class="grid">
|
|
114
|
+
<RangeCalendarGridRow
|
|
115
|
+
v-for="(weekDates, index) in month.rows"
|
|
116
|
+
:key="`week-${index}`"
|
|
117
|
+
class="mt-1 flex w-full justify-between"
|
|
118
|
+
>
|
|
119
|
+
<RangeCalendarCell v-for="weekDate in weekDates" :key="weekDate.toString()" :date="weekDate" class="p-0">
|
|
120
|
+
<RangeCalendarCellTrigger :day="weekDate" :month="month.value" :class="cellTrigger" />
|
|
121
|
+
</RangeCalendarCell>
|
|
122
|
+
</RangeCalendarGridRow>
|
|
123
|
+
</RangeCalendarGridBody>
|
|
124
|
+
</RangeCalendarGrid>
|
|
125
|
+
</div>
|
|
126
|
+
</RangeCalendarRoot>
|
|
127
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ClassProps } from '../../lib/types'
|
|
3
|
+
import { cn } from '../../lib/utils'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<ClassProps>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<div :class="cn('surface rounded-lg border border-border bg-card text-card-foreground shadow-sm', props.class)">
|
|
10
|
+
<slot />
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|