@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,62 @@
|
|
|
1
|
+
import type { MaybeRefOrGetter, Ref } from 'vue'
|
|
2
|
+
import { onScopeDispose, ref, toValue, watch } from 'vue'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hoãn việc BẬT một cờ, nhưng tắt ngay lập tức.
|
|
6
|
+
*
|
|
7
|
+
* Sinh ra cho chỉ báo tải: phản hồi dưới ~300ms mà vẫn nháy spinner thì **đọc
|
|
8
|
+
* ra hỏng hơn** là để nó im. Mắt ghi nhận cái loé đó như một glitch chứ không
|
|
9
|
+
* phải như phản hồi — nhất là với dữ liệu đã cache, nơi `loading` bật rồi tắt
|
|
10
|
+
* trong một khung hình.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const showLoader = useDelayedFlag(() => props.loading)
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* **Bất đối xứng là cố ý.** Bật thì hoãn, tắt thì tức thì:
|
|
17
|
+
*
|
|
18
|
+
* - Hoãn lúc tắt sẽ giữ spinner lại sau khi dữ liệu đã có — người dùng nhìn
|
|
19
|
+
* thấy chỉ báo tải đè lên đúng thứ vừa tải xong.
|
|
20
|
+
* - Không hoãn lúc bật thì mất sạch tác dụng của composable này.
|
|
21
|
+
*
|
|
22
|
+
* Không có "thời gian hiện tối thiểu": một khi đã quá 300ms thì lần chờ đó đủ
|
|
23
|
+
* dài để spinner kịp đọc ra là spinner, thêm ràng buộc nữa chỉ làm chậm thêm.
|
|
24
|
+
*/
|
|
25
|
+
export function useDelayedFlag(
|
|
26
|
+
source: MaybeRefOrGetter<boolean>,
|
|
27
|
+
delayMs = 300,
|
|
28
|
+
): Readonly<Ref<boolean>> {
|
|
29
|
+
const flag = ref(false)
|
|
30
|
+
let timer: ReturnType<typeof setTimeout> | undefined
|
|
31
|
+
|
|
32
|
+
function clear(): void {
|
|
33
|
+
if (timer !== undefined) {
|
|
34
|
+
clearTimeout(timer)
|
|
35
|
+
timer = undefined
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
watch(
|
|
40
|
+
() => toValue(source),
|
|
41
|
+
(active) => {
|
|
42
|
+
clear()
|
|
43
|
+
|
|
44
|
+
if (!active) {
|
|
45
|
+
flag.value = false
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
timer = setTimeout(() => {
|
|
50
|
+
flag.value = true
|
|
51
|
+
timer = undefined
|
|
52
|
+
}, delayMs)
|
|
53
|
+
},
|
|
54
|
+
{ immediate: true },
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
// Component có thể bị gỡ giữa lúc đang chờ — hẹn giờ còn sống sẽ ghi vào một
|
|
58
|
+
// ref không còn ai đọc.
|
|
59
|
+
onScopeDispose(clear)
|
|
60
|
+
|
|
61
|
+
return flag
|
|
62
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue'
|
|
2
|
+
import type { LocaleId, LocaleOption, LocaleState, MessageParams } from '../i18n'
|
|
3
|
+
import { computed, onMounted, shallowRef } from 'vue'
|
|
4
|
+
import { i18nController, locales, uiMessages } from '../i18n'
|
|
5
|
+
|
|
6
|
+
export { locales } from '../i18n'
|
|
7
|
+
export type { LocaleId, LocaleOption } from '../i18n'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Nối locale controller vanilla của `src/i18n` vào hệ reactivity của Vue.
|
|
11
|
+
*
|
|
12
|
+
* Toàn bộ phần code riêng của Vue cho i18n nằm ở đây — logic đọc localStorage,
|
|
13
|
+
* đoán ngôn ngữ trình duyệt, ghi `<html lang>` và đồng bộ giữa các tab thì ở
|
|
14
|
+
* package i18n, dùng chung với woodblock-react / woodblock-angular sau này. Cùng
|
|
15
|
+
* khuôn với `useThemeController`.
|
|
16
|
+
*
|
|
17
|
+
* Từ điển của thư viện nạp NGAY ở tầng module: mọi component cần dịch đều
|
|
18
|
+
* import file này, nên không có đường nào component vẽ ra trước khi chuỗi của
|
|
19
|
+
* nó có mặt. Nạp trong `onMounted` thì lần render đầu sẽ hiện ra khoá.
|
|
20
|
+
*/
|
|
21
|
+
i18nController.addMessages('vi', uiMessages.vi)
|
|
22
|
+
i18nController.addMessages('en', uiMessages.en)
|
|
23
|
+
|
|
24
|
+
const state = shallowRef<LocaleState>(i18nController.getState())
|
|
25
|
+
|
|
26
|
+
// Controller gọi listener ngay khi đăng ký, nên state khớp từ dòng này trở đi.
|
|
27
|
+
i18nController.subscribe((next) => {
|
|
28
|
+
state.value = next
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
let mounted = false
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Trạng thái ngôn ngữ, đã reactive.
|
|
35
|
+
*
|
|
36
|
+
* Gọi trong `setup` của component: phần khởi tạo chạy trong `onMounted` vì nó
|
|
37
|
+
* đụng `document`, `localStorage` và `navigator`.
|
|
38
|
+
*/
|
|
39
|
+
export function useLocaleState(): ComputedRef<LocaleState> {
|
|
40
|
+
onMounted(() => {
|
|
41
|
+
if (mounted)
|
|
42
|
+
return
|
|
43
|
+
mounted = true
|
|
44
|
+
i18nController.init()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return computed(() => state.value)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Dịch từ NGOÀI `setup` — vẫn reactive, nhưng không tự gọi `init()`.
|
|
52
|
+
*
|
|
53
|
+
* Dành cho những chỗ không phải component mà vẫn dựng ra giao diện: hàm sinh
|
|
54
|
+
* column def, hàm render `h()`, factory trả về option… `useI18n()` không dùng
|
|
55
|
+
* được ở đó vì nó đăng ký `onMounted`.
|
|
56
|
+
*
|
|
57
|
+
* Vẫn reactive nhờ đọc `state.value`: hàm render nào gọi tới cũng đăng ký phụ
|
|
58
|
+
* thuộc vào locale, nên đổi ngôn ngữ là bảng vẽ lại nhãn.
|
|
59
|
+
*
|
|
60
|
+
* Không gọi `init()`, nên phải có ít nhất một component đã gọi `useI18n()` —
|
|
61
|
+
* trong app thì `App.vue` lo việc đó.
|
|
62
|
+
*/
|
|
63
|
+
export function translate(key: string, params?: MessageParams): string {
|
|
64
|
+
void state.value
|
|
65
|
+
return i18nController.t(key, params)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface UseI18n {
|
|
69
|
+
/** Ngôn ngữ đang bật. Chỉ đọc — đổi bằng `setLocale`. */
|
|
70
|
+
locale: ComputedRef<LocaleId>
|
|
71
|
+
/** Thẻ BCP 47 (`vi-VN`), truyền thẳng vào `Intl` được. */
|
|
72
|
+
tag: ComputedRef<string>
|
|
73
|
+
/** Danh sách ngôn ngữ. MẢNG TĨNH, không phải ref. */
|
|
74
|
+
locales: readonly LocaleOption[]
|
|
75
|
+
setLocale: (value: LocaleId) => void
|
|
76
|
+
t: (key: string, params?: MessageParams) => string
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Dịch, và đổi ngôn ngữ.
|
|
81
|
+
*
|
|
82
|
+
* `t` là hàm THƯỜNG chứ không phải computed, nhưng vẫn reactive: nó đọc
|
|
83
|
+
* `state.value` trước khi tra từ điển, nên effect nào gọi `t()` cũng đăng ký phụ
|
|
84
|
+
* thuộc vào locale và tự chạy lại khi đổi. Nhờ vậy viết `t('x')` giống nhau ở cả
|
|
85
|
+
* `<script setup>` lẫn template — bọc thành computed thì trong script phải viết
|
|
86
|
+
* `t.value('x')`, còn trong template lại là `t('x')`, hai kiểu cho một thứ.
|
|
87
|
+
*
|
|
88
|
+
* Cũng vì lý do đó mà chuỗi nạp muộn vẫn hiện ra: `addMessages` gọi `notify()`,
|
|
89
|
+
* `state` đổi tham chiếu, mọi chỗ gọi `t()` vẽ lại.
|
|
90
|
+
*/
|
|
91
|
+
export function useI18n(): UseI18n {
|
|
92
|
+
const current = useLocaleState()
|
|
93
|
+
|
|
94
|
+
function t(key: string, params?: MessageParams): string {
|
|
95
|
+
// Đọc để tạo phụ thuộc reactive. Bỏ dòng này thì chữ đứng im khi đổi ngôn ngữ.
|
|
96
|
+
void current.value
|
|
97
|
+
return i18nController.t(key, params)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
locale: computed(() => current.value.locale),
|
|
102
|
+
tag: computed(() => current.value.tag),
|
|
103
|
+
locales,
|
|
104
|
+
setLocale: i18nController.setLocale,
|
|
105
|
+
t,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import { onScopeDispose, readonly, ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
/** Mốc `md` của Tailwind. Sidebar đổi sang ngăn kéo ở dưới mốc này. */
|
|
5
|
+
const MOBILE_BREAKPOINT = 768
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Bề ngang viewport có đang dưới mốc `md` hay không.
|
|
9
|
+
*
|
|
10
|
+
* Dùng `matchMedia` chứ không nghe `resize`: trình duyệt chỉ bắn khi VƯỢT mốc
|
|
11
|
+
* nên không phải lọc lại ở mỗi pixel kéo chuột.
|
|
12
|
+
*
|
|
13
|
+
* Giá trị đầu tiên đọc ngay lúc gọi chứ không chờ `onMounted`: sidebar quyết
|
|
14
|
+
* định render ngăn kéo hay cột cố định dựa vào đây, sai một nhịp là thấy rõ một
|
|
15
|
+
* lần nhảy. Ngoài trình duyệt (SSR) thì trả `false` — không có viewport để đo.
|
|
16
|
+
*/
|
|
17
|
+
export function useIsMobile(): Readonly<Ref<boolean>> {
|
|
18
|
+
const isMobile = ref(false)
|
|
19
|
+
|
|
20
|
+
if (typeof window === 'undefined')
|
|
21
|
+
return readonly(isMobile)
|
|
22
|
+
|
|
23
|
+
const query = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
24
|
+
isMobile.value = query.matches
|
|
25
|
+
|
|
26
|
+
const onChange = (event: MediaQueryListEvent): void => {
|
|
27
|
+
isMobile.value = event.matches
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
query.addEventListener('change', onChange)
|
|
31
|
+
onScopeDispose(() => query.removeEventListener('change', onChange))
|
|
32
|
+
|
|
33
|
+
return readonly(isMobile)
|
|
34
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { MenuAccentId, MenuAccentOption } from '@vestow/theme'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { menuAccents, themeController } from '@vestow/theme'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { useThemeState } from './useThemeController'
|
|
6
|
+
|
|
7
|
+
export type { MenuAccentId, MenuAccentOption }
|
|
8
|
+
export { menuAccents }
|
|
9
|
+
|
|
10
|
+
export interface UseMenuAccentReturn {
|
|
11
|
+
menuAccent: ComputedRef<MenuAccentId>
|
|
12
|
+
menuAccents: readonly MenuAccentOption[]
|
|
13
|
+
setMenuAccent: (value: MenuAccentId) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Cách tô mục menu đang trỏ tới. Vỏ bọc Vue quanh `themeController`, cùng khuôn
|
|
18
|
+
* với `usePalette` / `useStyle` / `useBase`.
|
|
19
|
+
*
|
|
20
|
+
* Trục này chỉ đổi `--menu-accent` và `--menu-accent-foreground` — hai token mà
|
|
21
|
+
* `menu-styles.ts` đọc. Xem đầu `menus.css` để biết vì sao nó không đụng
|
|
22
|
+
* `--accent` chung.
|
|
23
|
+
*/
|
|
24
|
+
export function useMenuAccent(): UseMenuAccentReturn {
|
|
25
|
+
const state = useThemeState()
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
menuAccent: computed(() => state.value.menuAccent),
|
|
29
|
+
menuAccents,
|
|
30
|
+
setMenuAccent: themeController.setMenuAccent,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { MenuAppearanceId, MenuAppearanceOption } from '@vestow/theme'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { menuAppearances, themeController } from '@vestow/theme'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { useThemeState } from './useThemeController'
|
|
6
|
+
|
|
7
|
+
export type { MenuAppearanceId, MenuAppearanceOption }
|
|
8
|
+
export { menuAppearances }
|
|
9
|
+
|
|
10
|
+
export interface UseMenuAppearanceReturn {
|
|
11
|
+
menuAppearance: ComputedRef<MenuAppearanceId>
|
|
12
|
+
menuAppearances: readonly MenuAppearanceOption[]
|
|
13
|
+
setMenuAppearance: (value: MenuAppearanceId) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Mặt menu đục hay trong. Vỏ bọc Vue quanh `themeController`.
|
|
18
|
+
*
|
|
19
|
+
* KHÔNG có tác dụng khi `surface` đang là `glass` — theme kính đã làm mọi tấm
|
|
20
|
+
* menu trong mờ rồi, chồng thêm là chồng kính lên kính. Khối CSS tự loại mình
|
|
21
|
+
* ra chứ không phải composable này; xem `menus.css`.
|
|
22
|
+
*/
|
|
23
|
+
export function useMenuAppearance(): UseMenuAppearanceReturn {
|
|
24
|
+
const state = useThemeState()
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
menuAppearance: computed(() => state.value.menuAppearance),
|
|
28
|
+
menuAppearances,
|
|
29
|
+
setMenuAppearance: themeController.setMenuAppearance,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { MenuColorId, MenuColorOption } from '@vestow/theme'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { menuColors, themeController } from '@vestow/theme'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { useThemeState } from './useThemeController'
|
|
6
|
+
|
|
7
|
+
export type { MenuColorId, MenuColorOption }
|
|
8
|
+
export { menuColors }
|
|
9
|
+
|
|
10
|
+
export interface UseMenuColorReturn {
|
|
11
|
+
menuColor: ComputedRef<MenuColorId>
|
|
12
|
+
menuColors: readonly MenuColorOption[]
|
|
13
|
+
setMenuColor: (value: MenuColorId) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Mặt menu lấy màu ở đâu. Vỏ bọc Vue quanh `themeController`, cùng khuôn với
|
|
18
|
+
* `useMenuAccent` / `usePalette` / `useStyle`.
|
|
19
|
+
*
|
|
20
|
+
* Trục này khai lại token ngay trên phần tử `.ui-menu` chứ không trên `:root`,
|
|
21
|
+
* nên nó không đụng Popover và Tooltip. Xem `menus.css`.
|
|
22
|
+
*/
|
|
23
|
+
export function useMenuColor(): UseMenuColorReturn {
|
|
24
|
+
const state = useThemeState()
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
menuColor: computed(() => state.value.menuColor),
|
|
28
|
+
menuColors,
|
|
29
|
+
setMenuColor: themeController.setMenuColor,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { PaletteId, PaletteOption } from '@vestow/theme'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { palettes, themeController } from '@vestow/theme'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { useThemeState } from './useThemeController'
|
|
6
|
+
|
|
7
|
+
export type { PaletteId, PaletteOption }
|
|
8
|
+
// Danh sách bảng màu là DỮ LIỆU, ở `@vestow/theme`. Re-export để chỗ gọi
|
|
9
|
+
// không phải nhớ nó nằm ở package nào.
|
|
10
|
+
export { palettes }
|
|
11
|
+
|
|
12
|
+
export interface UsePaletteReturn {
|
|
13
|
+
palette: ComputedRef<PaletteId>
|
|
14
|
+
palettes: readonly PaletteOption[]
|
|
15
|
+
setPalette: (value: PaletteId) => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Bảng màu đang chọn. Vỏ bọc Vue quanh `themeController` của
|
|
20
|
+
* `@vestow/theme` — xem `useThemeController.ts`.
|
|
21
|
+
*/
|
|
22
|
+
export function usePalette(): UsePaletteReturn {
|
|
23
|
+
const state = useThemeState()
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
palette: computed(() => state.value.palette),
|
|
27
|
+
palettes,
|
|
28
|
+
setPalette: themeController.setPalette,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { StyleId, StyleOption } from '@vestow/theme'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { styleVariants, themeController } from '@vestow/theme'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { useThemeState } from './useThemeController'
|
|
6
|
+
|
|
7
|
+
export type { StyleId, StyleOption }
|
|
8
|
+
// Danh sách hình khối là DỮ LIỆU, ở `@vestow/theme`. Re-export để chỗ gọi
|
|
9
|
+
// không phải nhớ nó nằm ở package nào.
|
|
10
|
+
export { styleVariants }
|
|
11
|
+
|
|
12
|
+
export interface UseStyleReturn {
|
|
13
|
+
style: ComputedRef<StyleId>
|
|
14
|
+
styleVariants: readonly StyleOption[]
|
|
15
|
+
setStyle: (value: StyleId) => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Hình khối đang chọn — bo góc, độ đậm đường kẻ, độ thoáng của control. Vỏ bọc
|
|
20
|
+
* Vue quanh `themeController` của `@vestow/theme`, cùng khuôn với
|
|
21
|
+
* `usePalette` / `useSurface` — xem `useThemeController.ts`.
|
|
22
|
+
*
|
|
23
|
+
* Trục này ghi `data-style` lên `<html>`. Muốn đổi hình khối cho RIÊNG một vùng
|
|
24
|
+
* thì đừng dùng composable này: đặt thẳng `data-style` lên phần tử bao vùng đó,
|
|
25
|
+
* khai báo trực tiếp luôn thắng giá trị thừa kế.
|
|
26
|
+
*/
|
|
27
|
+
export function useStyle(): UseStyleReturn {
|
|
28
|
+
const state = useThemeState()
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
style: computed(() => state.value.style),
|
|
32
|
+
styleVariants,
|
|
33
|
+
setStyle: themeController.setStyle,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SurfaceId, SurfaceOption } from '@vestow/theme'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { surfaces, themeController } from '@vestow/theme'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { useThemeState } from './useThemeController'
|
|
6
|
+
|
|
7
|
+
export type { SurfaceId, SurfaceOption }
|
|
8
|
+
// Danh sách bề mặt là DỮ LIỆU, ở `@vestow/theme`. Re-export để chỗ gọi
|
|
9
|
+
// không phải nhớ nó nằm ở package nào.
|
|
10
|
+
export { surfaces }
|
|
11
|
+
|
|
12
|
+
export interface UseSurfaceReturn {
|
|
13
|
+
surface: ComputedRef<SurfaceId>
|
|
14
|
+
surfaces: readonly SurfaceOption[]
|
|
15
|
+
setSurface: (value: SurfaceId) => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Bề mặt đang chọn (`solid` / `glass`) — TRỤC RIÊNG, chồng lên bảng màu.
|
|
20
|
+
* Vỏ bọc Vue quanh `themeController` của `@vestow/theme`.
|
|
21
|
+
*/
|
|
22
|
+
export function useSurface(): UseSurfaceReturn {
|
|
23
|
+
const state = useThemeState()
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
surface: computed(() => state.value.surface),
|
|
27
|
+
surfaces,
|
|
28
|
+
setSurface: themeController.setSurface,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ComputedRef, Ref } from 'vue'
|
|
2
|
+
import type { PaginationAdapter, TableQuery } from '../components/data-table/types'
|
|
3
|
+
import { computed, ref } from 'vue'
|
|
4
|
+
|
|
5
|
+
export interface UseTableQueryOptions<TParams> {
|
|
6
|
+
adapter: PaginationAdapter<TParams>
|
|
7
|
+
pageSize?: number
|
|
8
|
+
/**
|
|
9
|
+
* Trạng thái khởi tạo, thường đọc từ URL để refresh và chia sẻ link đều ra
|
|
10
|
+
* đúng trang đang xem.
|
|
11
|
+
*
|
|
12
|
+
* Việc đọc/ghi URL cố ý KHÔNG nằm ở đây: `packages/ui` không được phụ thuộc
|
|
13
|
+
* `vue-router`. App tự nối — xem `useTableQueryUrl` trong `apps/admin`.
|
|
14
|
+
*/
|
|
15
|
+
initialQuery?: Partial<TableQuery>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Giữ trạng thái truy vấn của DataTable ở phía app và dịch sang tham số API.
|
|
20
|
+
*
|
|
21
|
+
* Composable này cố tình không phụ thuộc TanStack Query: app tự ghép.
|
|
22
|
+
*
|
|
23
|
+
* const { query, params, onQueryChange } = useTableQuery({
|
|
24
|
+
* adapter: createPageNumberAdapter(),
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* const { data, isFetching } = useQuery({
|
|
28
|
+
* queryKey: ['users', params],
|
|
29
|
+
* queryFn: () => userApi.list(params.value),
|
|
30
|
+
* })
|
|
31
|
+
*
|
|
32
|
+
* <DataTable
|
|
33
|
+
* server-side
|
|
34
|
+
* :total-records="data?.totalCount ?? 0"
|
|
35
|
+
* @page-change="onQueryChange"
|
|
36
|
+
* @sort-change="onQueryChange"
|
|
37
|
+
* @filter-change="onQueryChange"
|
|
38
|
+
* />
|
|
39
|
+
*/
|
|
40
|
+
export interface UseTableQueryReturn<TParams> {
|
|
41
|
+
query: Ref<TableQuery>
|
|
42
|
+
params: ComputedRef<TParams>
|
|
43
|
+
onQueryChange: (next: TableQuery) => void
|
|
44
|
+
reset: () => void
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function useTableQuery<TParams>(
|
|
48
|
+
options: UseTableQueryOptions<TParams>,
|
|
49
|
+
): UseTableQueryReturn<TParams> {
|
|
50
|
+
function blank(): TableQuery {
|
|
51
|
+
return {
|
|
52
|
+
pageIndex: 0,
|
|
53
|
+
pageSize: options.pageSize ?? 20,
|
|
54
|
+
sorting: [],
|
|
55
|
+
filters: [],
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const query = ref<TableQuery>({ ...blank(), ...options.initialQuery })
|
|
60
|
+
|
|
61
|
+
const params = computed<TParams>(() => options.adapter.toParams(query.value))
|
|
62
|
+
|
|
63
|
+
function onQueryChange(next: TableQuery): void {
|
|
64
|
+
query.value = next
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Về trạng thái rỗng — KHÔNG về `initialQuery`, vì đó là "xoá bộ lọc". */
|
|
68
|
+
function reset(): void {
|
|
69
|
+
query.value = blank()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return { query, params, onQueryChange, reset }
|
|
73
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ThemeState } from '@vestow/theme'
|
|
2
|
+
import type { ComputedRef } from 'vue'
|
|
3
|
+
import { themeController } from '@vestow/theme'
|
|
4
|
+
import { computed, onMounted, shallowRef } from 'vue'
|
|
5
|
+
|
|
6
|
+
// Giá trị mặc định của ba trục là DỮ LIỆU ở `@vestow/theme` (controller cũng
|
|
7
|
+
// đọc chính nó để biết khi nào gỡ `data-palette`). Re-export để app không phải
|
|
8
|
+
// gõ lại `'hyperion'` / `'solid'` ở nút "khôi phục mặc định".
|
|
9
|
+
export { defaults as themeDefaults } from '@vestow/theme'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Nối controller vanilla của `@vestow/theme` vào hệ reactivity của Vue.
|
|
13
|
+
*
|
|
14
|
+
* Đây là TOÀN BỘ phần code riêng của Vue cho ba trục giao diện — logic đọc
|
|
15
|
+
* localStorage, theo dõi `prefers-color-scheme` và ghi lên `<html>` nằm ở
|
|
16
|
+
* package token, dùng chung với woodblock-react / woodblock-angular sau này.
|
|
17
|
+
*
|
|
18
|
+
* State ở module scope, không phải trong hàm: `<html>` chỉ có một, nên mọi
|
|
19
|
+
* component gọi `useColorMode()` / `usePalette()` / `useSurface()` phải đọc
|
|
20
|
+
* chung một giá trị. Đó cũng là lý do component library không cần Pinia (mà
|
|
21
|
+
* cũng không được phép phụ thuộc vào store của app).
|
|
22
|
+
*/
|
|
23
|
+
const state = shallowRef<ThemeState>(themeController.getState())
|
|
24
|
+
|
|
25
|
+
// Controller gọi listener ngay khi đăng ký, nên state khớp từ dòng này trở đi.
|
|
26
|
+
themeController.subscribe((next) => {
|
|
27
|
+
state.value = next
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
let mounted = false
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Trạng thái giao diện, đã reactive.
|
|
34
|
+
*
|
|
35
|
+
* Gọi trong `setup` của component: phần khởi tạo chạy trong `onMounted` vì nó
|
|
36
|
+
* đụng `document` và `localStorage` — gọi ngoài đó thì Vue cảnh báo và theme
|
|
37
|
+
* không được áp lên trang.
|
|
38
|
+
*/
|
|
39
|
+
export function useThemeState(): ComputedRef<ThemeState> {
|
|
40
|
+
onMounted(() => {
|
|
41
|
+
if (mounted)
|
|
42
|
+
return
|
|
43
|
+
mounted = true
|
|
44
|
+
themeController.init()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return computed(() => state.value)
|
|
48
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# `src/i18n`
|
|
2
|
+
|
|
3
|
+
Locale controller của WoodBlock cộng bộ chuỗi của chính thư viện. Không phụ thuộc
|
|
4
|
+
framework nào — `useI18n` mới là phần riêng của Vue, và nó nằm ở `../composables`.
|
|
5
|
+
|
|
6
|
+
Nó TỪNG là package riêng `src/i18n`. Đợt gộp đưa nó về đây vì repo chỉ còn cây
|
|
7
|
+
Vue, và vì 126 khoá trong `ui/` là chuỗi mà chính component phát ra — chúng không dùng
|
|
8
|
+
được nếu không có component.
|
|
9
|
+
|
|
10
|
+
Hai thứ nằm trong đây:
|
|
11
|
+
|
|
12
|
+
| | |
|
|
13
|
+
|---|---|
|
|
14
|
+
| **Registry** | danh sách ngôn ngữ, khoá localStorage, `lang` tag cho `Intl` |
|
|
15
|
+
| **Controller** | đọc lưu trữ, đoán ngôn ngữ trình duyệt, ghi `<html lang>`, đồng bộ giữa tab |
|
|
16
|
+
|
|
17
|
+
Bộ chuỗi thì chia hai: `ui/` là 126 khoá của THƯ VIỆN (nút Đóng của Dialog, `aria-label`
|
|
18
|
+
của Carousel, thông báo Zod), còn từ điển của app nằm ở `vue/apps/<app>/src/i18n`.
|
|
19
|
+
|
|
20
|
+
## Dùng controller
|
|
21
|
+
|
|
22
|
+
Controller là **vanilla TypeScript**: không import framework, không chạm `document` ở tầng
|
|
23
|
+
module (import được trong SSR).
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { i18nController } from '@vestow/vue/i18n'
|
|
27
|
+
|
|
28
|
+
i18nController.init() // đọc localStorage, hoặc đoán theo navigator.languages
|
|
29
|
+
i18nController.setLocale('en')
|
|
30
|
+
i18nController.subscribe(state => console.log(state.locale))
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Vỏ bọc cho từng framework chỉ còn việc nối `subscribe()` vào hệ reactivity của nó. Bản Vue
|
|
34
|
+
ở `vue/packages/ui/src/composables/useI18n.ts` (bản React ở
|
|
35
|
+
`react/packages/ui/src/hooks/useI18n.ts`).
|
|
36
|
+
|
|
37
|
+
## Đoán ngôn ngữ so bằng TIỀN TỐ
|
|
38
|
+
|
|
39
|
+
Không có lựa chọn đã lưu thì controller đọc `navigator.languages` và so bằng **tiền tố**,
|
|
40
|
+
không so bằng nhau: `en-GB`, `vi-VN`, `en-AU` đều phải khớp. Viết `=== 'en'` thì gần như
|
|
41
|
+
không bao giờ trúng, vì trình duyệt hiếm khi trả về đúng hai ký tự.
|
|
42
|
+
|
|
43
|
+
## Đồng bộ giữa tab và iframe
|
|
44
|
+
|
|
45
|
+
Controller lắng nghe sự kiện `storage`, mà sự kiện đó **chỉ phát ở document khác document
|
|
46
|
+
vừa ghi** — đúng quan hệ giữa trang cha và iframe. Không có vòng lặp, vì bên ghi đã tự áp
|
|
47
|
+
trong `setLocale`. Mở app ở hai tab cũng không lệch nhau.
|
|
48
|
+
|
|
49
|
+
## Cố tình KHÔNG dùng `vue-i18n`
|
|
50
|
+
|
|
51
|
+
Thư viện component phải mang theo bộ chuỗi của chính nó — nút Đóng của Dialog, `aria-label`
|
|
52
|
+
của nút phân trang — mà `packages/ui` thì không được kéo một runtime i18n vào mọi app dùng
|
|
53
|
+
nó.
|
|
54
|
+
|
|
55
|
+
Cái giá: không có message compiler, không có bộ luật số nhiều đầy đủ. Chấp nhận được vì
|
|
56
|
+
tiếng Việt không biến đổi theo số lượng, tiếng Anh chỉ cần phân biệt 1 với phần còn lại
|
|
57
|
+
(tách bằng `|`), còn ngày và số thì đã đi qua `Intl`.
|
|
58
|
+
|
|
59
|
+
## Lệnh
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
pnpm -F @vestow/vue typecheck # không có bước build: package ship source
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Publish
|
|
66
|
+
|
|
67
|
+
`exports` trỏ vào `src/` cho tiện phát triển trong workspace; `publishConfig` đổi sang
|
|
68
|
+
`dist/` lúc `pnpm publish`, và `prepack` chạy `build` trước.
|