@brumaombra/ui-vintage 0.9.1 → 0.9.2
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/module.mjs +43 -43
- package/package.json +175 -175
- package/src/components/background-grid/BackgroundGrid.vue +4 -4
- package/src/components/blog/AllPostsSection.vue +33 -33
- package/src/components/blog/BlogContentRenderer.vue +111 -111
- package/src/components/blog/BlogFAQSection.vue +19 -19
- package/src/components/blog/BlogHeaderSection.vue +80 -80
- package/src/components/blog/BlogInfoSection.vue +47 -47
- package/src/components/blog/BlogPostHeader.vue +135 -135
- package/src/components/blog/BlogProgressBar.vue +33 -33
- package/src/components/blog/BlogSectionTitle.vue +22 -22
- package/src/components/blog/BlogTagsSection.vue +25 -25
- package/src/components/blog/CategoriesList.vue +14 -14
- package/src/components/blog/CategoriesSection.vue +11 -11
- package/src/components/blog/CategoryCard.vue +25 -25
- package/src/components/blog/HeaderCarousel.vue +97 -97
- package/src/components/blog/PostCard.vue +33 -33
- package/src/components/blog/PostsList.vue +15 -15
- package/src/components/blog/SocialShareSidebar.vue +84 -84
- package/src/components/blog/TableOfContents.vue +307 -307
- package/src/components/busy-indicator/BusyIndicator.vue +7 -7
- package/src/components/busy-indicator/busy-indicator-state.ts +56 -56
- package/src/components/card-grid/CardGrid.vue +34 -34
- package/src/components/chip/Chip.vue +15 -15
- package/src/components/confirm-dialog/ConfirmDialog.vue +50 -50
- package/src/components/confirm-dialog/confirm-dialog-state.ts +131 -131
- package/src/components/content/BlogList.vue +30 -30
- package/src/components/content/BlogTable.vue +36 -36
- package/src/components/content/CodeBlock.vue +136 -136
- package/src/components/content/Flow.vue +60 -60
- package/src/components/content/ProseHr.vue +15 -15
- package/src/components/content/ProsePre.vue +12 -12
- package/src/components/content/Terminal.vue +59 -59
- package/src/components/cookie-consent/CookieConsent.vue +36 -36
- package/src/components/cookie-consent/useCookieConsent.ts +37 -37
- package/src/components/dashboard-shell/DashboardShell.vue +171 -171
- package/src/components/data-list/DataList.vue +6 -6
- package/src/components/data-list/DataListItem.vue +4 -4
- package/src/components/data-list/DataListLabel.vue +4 -4
- package/src/components/data-list/DataListText.vue +4 -4
- package/src/components/data-list/DataListValue.vue +4 -4
- package/src/components/empty-state-card/EmptyStateCard.vue +40 -40
- package/src/components/error-page/ErrorPage.vue +72 -72
- package/src/components/info-card/InfoCard.vue +31 -31
- package/src/components/landing/landing-content/LandingContent.vue +4 -4
- package/src/components/landing/landing-footer/LandingFooter.vue +128 -128
- package/src/components/landing/landing-navbar/LandingNavbar.vue +50 -50
- package/src/components/landing/landing-shell/LandingShell.vue +36 -36
- package/src/components/language-flag/LanguageFlag.vue +25 -25
- package/src/components/language-flag/flags/ChineseFlag.vue +8 -8
- package/src/components/language-flag/flags/EnglishFlag.vue +7 -7
- package/src/components/language-flag/flags/FrenchFlag.vue +5 -5
- package/src/components/language-flag/flags/GermanFlag.vue +5 -5
- package/src/components/language-flag/flags/ItalianFlag.vue +7 -7
- package/src/components/language-flag/flags/JapaneseFlag.vue +4 -4
- package/src/components/language-flag/flags/PortugueseFlag.vue +57 -57
- package/src/components/language-flag/flags/RussianFlag.vue +5 -5
- package/src/components/language-flag/flags/SpanishFlag.vue +4 -4
- package/src/components/language-selector/LanguageSelector.vue +76 -76
- package/src/components/load-more-button/LoadMoreButton.vue +17 -17
- package/src/components/loading-state-card/LoadingStateCard.vue +28 -28
- package/src/components/message-dialog/MessageDialog.vue +59 -59
- package/src/components/message-dialog/message-dialog-state.ts +105 -105
- package/src/components/message-toast/MessageToast.vue +149 -149
- package/src/components/message-toast/message-toast-state.ts +146 -146
- package/src/components/page-header/PageHeader.vue +34 -34
- package/src/components/progress-component/ProgressComponent.vue +33 -33
- package/src/components/single-value-card/SingleValueCard.vue +57 -57
- package/src/components/slider-form-component/SliderFormComponent.vue +36 -36
- package/src/components/stat-strip/StatStrip.vue +22 -22
- package/src/components/switch-form-component/SwitchFormComponent.vue +20 -20
- package/src/components/text-link/TextLink.vue +14 -14
- package/src/components/theme-selector/ThemeSelector.vue +61 -61
- package/src/components/theme-selector/theme-transition.ts +63 -63
- package/src/components/ui/accordion/Accordion.vue +38 -38
- package/src/components/ui/alert/Alert.vue +5 -5
- package/src/components/ui/alert/AlertDescription.vue +4 -4
- package/src/components/ui/alert/AlertTitle.vue +4 -4
- package/src/components/ui/alert/index.ts +2 -2
- package/src/components/ui/alert-dialog/AlertDialog.vue +3 -3
- package/src/components/ui/alert-dialog/AlertDialogAction.vue +3 -3
- package/src/components/ui/alert-dialog/AlertDialogCancel.vue +3 -3
- package/src/components/ui/alert-dialog/AlertDialogContent.vue +7 -7
- package/src/components/ui/alert-dialog/AlertDialogDescription.vue +3 -3
- package/src/components/ui/alert-dialog/AlertDialogFooter.vue +4 -4
- package/src/components/ui/alert-dialog/AlertDialogHeader.vue +4 -4
- package/src/components/ui/alert-dialog/AlertDialogTitle.vue +3 -3
- package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +3 -3
- package/src/components/ui/animated-number/AnimatedNumber.vue +49 -48
- package/src/components/ui/avatar/Avatar.vue +28 -28
- package/src/components/ui/avatar/AvatarFallback.vue +6 -6
- package/src/components/ui/avatar/AvatarGroup.vue +40 -40
- package/src/components/ui/avatar/AvatarImage.vue +3 -3
- package/src/components/ui/avatar/index.ts +17 -17
- package/src/components/ui/badge/Badge.vue +20 -20
- package/src/components/ui/breadcrumb/Breadcrumb.vue +4 -4
- package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +9 -9
- package/src/components/ui/breadcrumb/BreadcrumbItem.vue +4 -4
- package/src/components/ui/breadcrumb/BreadcrumbLink.vue +4 -4
- package/src/components/ui/breadcrumb/BreadcrumbList.vue +4 -4
- package/src/components/ui/breadcrumb/BreadcrumbPage.vue +4 -4
- package/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +4 -4
- package/src/components/ui/busy/Busy.vue +33 -33
- package/src/components/ui/button/Button.vue +23 -23
- package/src/components/ui/button/index.ts +56 -56
- package/src/components/ui/calendar/Calendar.vue +138 -138
- package/src/components/ui/calendar/CalendarCell.vue +7 -7
- package/src/components/ui/calendar/CalendarCellTrigger.vue +18 -18
- package/src/components/ui/calendar/CalendarGrid.vue +3 -3
- package/src/components/ui/calendar/CalendarGridBody.vue +3 -3
- package/src/components/ui/calendar/CalendarGridHead.vue +3 -3
- package/src/components/ui/calendar/CalendarGridRow.vue +3 -3
- package/src/components/ui/calendar/CalendarHeadCell.vue +7 -7
- package/src/components/ui/calendar/CalendarHeader.vue +7 -7
- package/src/components/ui/calendar/CalendarHeading.vue +6 -6
- package/src/components/ui/calendar/CalendarNextButton.vue +15 -15
- package/src/components/ui/calendar/CalendarPrevButton.vue +15 -15
- package/src/components/ui/calendar/index.ts +4 -4
- package/src/components/ui/card/Card.vue +20 -20
- package/src/components/ui/card/CardAction.vue +8 -8
- package/src/components/ui/card/CardContent.vue +4 -4
- package/src/components/ui/card/CardDescription.vue +12 -12
- package/src/components/ui/card/CardFooter.vue +4 -4
- package/src/components/ui/card/CardHeader.vue +8 -8
- package/src/components/ui/card/CardText.vue +8 -8
- package/src/components/ui/card/CardTitle.vue +8 -8
- package/src/components/ui/checkbox/Checkbox.vue +27 -27
- package/src/components/ui/collapsible/Collapsible.vue +3 -3
- package/src/components/ui/collapsible/CollapsibleContent.vue +3 -3
- package/src/components/ui/collapsible/CollapsibleTrigger.vue +3 -3
- package/src/components/ui/combobox/Combobox.vue +4 -4
- package/src/components/ui/combobox/ComboboxAnchor.vue +16 -16
- package/src/components/ui/combobox/ComboboxEmpty.vue +3 -3
- package/src/components/ui/combobox/ComboboxGroup.vue +9 -9
- package/src/components/ui/combobox/ComboboxInput.vue +6 -6
- package/src/components/ui/combobox/ComboboxItem.vue +17 -17
- package/src/components/ui/combobox/ComboboxList.vue +19 -19
- package/src/components/ui/combobox/ComboboxSelect.vue +77 -77
- package/src/components/ui/combobox/ComboboxSeparator.vue +1 -1
- package/src/components/ui/combobox/ComboboxTrigger.vue +10 -10
- package/src/components/ui/combobox/types.ts +5 -5
- package/src/components/ui/command/Command.vue +48 -48
- package/src/components/ui/command/CommandDialog.vue +14 -14
- package/src/components/ui/command/CommandEmpty.vue +4 -4
- package/src/components/ui/command/CommandGroup.vue +23 -23
- package/src/components/ui/command/CommandInput.vue +9 -9
- package/src/components/ui/command/CommandItem.vue +40 -40
- package/src/components/ui/command/CommandList.vue +9 -9
- package/src/components/ui/command/CommandSeparator.vue +3 -3
- package/src/components/ui/command/CommandShortcut.vue +8 -8
- package/src/components/ui/command/index.ts +11 -11
- package/src/components/ui/data-table/DataTable.vue +145 -145
- package/src/components/ui/data-table/index.ts +11 -11
- package/src/components/ui/date-picker/DatePicker.vue +31 -31
- package/src/components/ui/date-time-picker/DateTimePicker.vue +97 -97
- package/src/components/ui/dialog/Dialog.vue +3 -3
- package/src/components/ui/dialog/DialogClose.vue +3 -3
- package/src/components/ui/dialog/DialogContent.vue +21 -21
- package/src/components/ui/dialog/DialogDescription.vue +7 -7
- package/src/components/ui/dialog/DialogFooter.vue +8 -8
- package/src/components/ui/dialog/DialogHeader.vue +4 -4
- package/src/components/ui/dialog/DialogOverlay.vue +7 -7
- package/src/components/ui/dialog/DialogScrollContent.vue +32 -32
- package/src/components/ui/dialog/DialogTitle.vue +3 -3
- package/src/components/ui/dialog/DialogTrigger.vue +3 -3
- package/src/components/ui/dropdown-menu/DropdownMenu.vue +3 -3
- package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +11 -11
- package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +15 -15
- package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +3 -3
- package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +12 -12
- package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +9 -9
- package/src/components/ui/dropdown-menu/DropdownMenuPortal.vue +3 -3
- package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +3 -3
- package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +11 -11
- package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +1 -1
- package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +4 -4
- package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +3 -3
- package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +15 -15
- package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +15 -15
- package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +3 -3
- package/src/components/ui/dropdown-menu/classes.ts +16 -16
- package/src/components/ui/field/Field.vue +5 -5
- package/src/components/ui/field/FieldContent.vue +8 -8
- package/src/components/ui/field/FieldDescription.vue +10 -10
- package/src/components/ui/field/FieldError.vue +39 -39
- package/src/components/ui/field/FieldGroup.vue +8 -8
- package/src/components/ui/field/FieldLabel.vue +10 -10
- package/src/components/ui/field/FieldLegend.vue +11 -11
- package/src/components/ui/field/FieldSeparator.vue +11 -11
- package/src/components/ui/field/FieldSet.vue +9 -9
- package/src/components/ui/field/FieldTitle.vue +8 -8
- package/src/components/ui/field/field-context.ts +36 -36
- package/src/components/ui/field/index.ts +22 -22
- package/src/components/ui/file-dropzone/FileDropzone.vue +144 -144
- package/src/components/ui/file-dropzone/index.ts +19 -19
- package/src/components/ui/hover-card/HoverCard.vue +5 -5
- package/src/components/ui/hover-card/HoverCardContent.vue +13 -13
- package/src/components/ui/hover-card/HoverCardTrigger.vue +3 -3
- package/src/components/ui/input/Input.vue +13 -13
- package/src/components/ui/kbd/Kbd.vue +10 -10
- package/src/components/ui/kbd/KbdGroup.vue +49 -49
- package/src/components/ui/label/Label.vue +7 -7
- package/src/components/ui/native-select/NativeSelect.vue +16 -16
- package/src/components/ui/native-select/NativeSelectOptGroup.vue +3 -3
- package/src/components/ui/native-select/NativeSelectOption.vue +3 -3
- package/src/components/ui/number-field/NumberField.vue +88 -88
- package/src/components/ui/pagination/Pagination.vue +4 -4
- package/src/components/ui/pagination/PaginationContent.vue +4 -4
- package/src/components/ui/pagination/PaginationEllipsis.vue +9 -9
- package/src/components/ui/pagination/PaginationFirst.vue +8 -8
- package/src/components/ui/pagination/PaginationItem.vue +14 -14
- package/src/components/ui/pagination/PaginationLast.vue +8 -8
- package/src/components/ui/pagination/PaginationNext.vue +8 -8
- package/src/components/ui/pagination/PaginationPrevious.vue +8 -8
- package/src/components/ui/pagination/SimplePagination.vue +25 -25
- package/src/components/ui/pin-input/PinInput.vue +20 -20
- package/src/components/ui/pin-input/PinInputInput.vue +17 -17
- package/src/components/ui/pin-input/context.ts +1 -1
- package/src/components/ui/popover/Popover.vue +3 -3
- package/src/components/ui/popover/PopoverAnchor.vue +3 -3
- package/src/components/ui/popover/PopoverContent.vue +12 -12
- package/src/components/ui/popover/PopoverTrigger.vue +3 -3
- package/src/components/ui/progress/Progress.vue +16 -16
- package/src/components/ui/radio-group/RadioGroup.vue +7 -7
- package/src/components/ui/radio-group/RadioGroupCard.vue +39 -39
- package/src/components/ui/radio-group/RadioGroupItem.vue +20 -20
- package/src/components/ui/scroll-area/ScrollArea.vue +14 -14
- package/src/components/ui/scroll-area/ScrollBar.vue +12 -12
- package/src/components/ui/select/Select.vue +3 -3
- package/src/components/ui/select/SelectContent.vue +25 -25
- package/src/components/ui/select/SelectGroup.vue +3 -3
- package/src/components/ui/select/SelectItem.vue +24 -24
- package/src/components/ui/select/SelectItemContent.vue +32 -32
- package/src/components/ui/select/SelectItemText.vue +3 -3
- package/src/components/ui/select/SelectLabel.vue +3 -3
- package/src/components/ui/select/SelectScrollDownButton.vue +9 -9
- package/src/components/ui/select/SelectScrollUpButton.vue +9 -9
- package/src/components/ui/select/SelectSeparator.vue +2 -2
- package/src/components/ui/select/SelectTrigger.vue +14 -14
- package/src/components/ui/select/SelectValue.vue +3 -3
- package/src/components/ui/select/SelectValueContent.vue +39 -39
- package/src/components/ui/separator/Separator.vue +7 -7
- package/src/components/ui/sheet/Sheet.vue +3 -3
- package/src/components/ui/sheet/SheetClose.vue +3 -3
- package/src/components/ui/sheet/SheetContent.vue +22 -22
- package/src/components/ui/sheet/SheetDescription.vue +3 -3
- package/src/components/ui/sheet/SheetFooter.vue +3 -3
- package/src/components/ui/sheet/SheetHeader.vue +3 -3
- package/src/components/ui/sheet/SheetOverlay.vue +7 -7
- package/src/components/ui/sheet/SheetTitle.vue +3 -3
- package/src/components/ui/sheet/SheetTrigger.vue +3 -3
- package/src/components/ui/sidebar/Sidebar.vue +57 -57
- package/src/components/ui/sidebar/SidebarContent.vue +8 -8
- package/src/components/ui/sidebar/SidebarFooter.vue +8 -8
- package/src/components/ui/sidebar/SidebarGroup.vue +8 -8
- package/src/components/ui/sidebar/SidebarGroupAction.vue +9 -9
- package/src/components/ui/sidebar/SidebarGroupContent.vue +4 -4
- package/src/components/ui/sidebar/SidebarGroupLabel.vue +8 -8
- package/src/components/ui/sidebar/SidebarHeader.vue +8 -8
- package/src/components/ui/sidebar/SidebarInput.vue +8 -8
- package/src/components/ui/sidebar/SidebarInset.vue +9 -9
- package/src/components/ui/sidebar/SidebarMenu.vue +4 -4
- package/src/components/ui/sidebar/SidebarMenuAction.vue +18 -18
- package/src/components/ui/sidebar/SidebarMenuBadge.vue +14 -14
- package/src/components/ui/sidebar/SidebarMenuButton.vue +21 -21
- package/src/components/ui/sidebar/SidebarMenuButtonChild.vue +10 -10
- package/src/components/ui/sidebar/SidebarMenuItem.vue +4 -4
- package/src/components/ui/sidebar/SidebarMenuSkeleton.vue +10 -10
- package/src/components/ui/sidebar/SidebarMenuSub.vue +9 -9
- package/src/components/ui/sidebar/SidebarMenuSubButton.vue +17 -17
- package/src/components/ui/sidebar/SidebarMenuSubItem.vue +4 -4
- package/src/components/ui/sidebar/SidebarProvider.vue +46 -46
- package/src/components/ui/sidebar/SidebarRail.vue +13 -13
- package/src/components/ui/sidebar/SidebarSeparator.vue +4 -4
- package/src/components/ui/sidebar/SidebarTrigger.vue +5 -5
- package/src/components/ui/sidebar/index.ts +29 -29
- package/src/components/ui/sidebar/utils.ts +7 -7
- package/src/components/ui/skeleton/Skeleton.vue +6 -6
- package/src/components/ui/slider/Slider.vue +14 -14
- package/src/components/ui/spinner/Spinner.vue +21 -21
- package/src/components/ui/stepper/SimpleStepper.vue +26 -26
- package/src/components/ui/stepper/Stepper.vue +6 -6
- package/src/components/ui/stepper/StepperDescription.vue +5 -5
- package/src/components/ui/stepper/StepperIndicator.vue +17 -17
- package/src/components/ui/stepper/StepperItem.vue +4 -4
- package/src/components/ui/stepper/StepperSeparator.vue +7 -7
- package/src/components/ui/stepper/StepperTitle.vue +5 -5
- package/src/components/ui/stepper/StepperTrigger.vue +4 -4
- package/src/components/ui/stepper/index.ts +3 -3
- package/src/components/ui/switch/Switch.vue +15 -15
- package/src/components/ui/table/Table.vue +6 -6
- package/src/components/ui/table/TableBody.vue +4 -4
- package/src/components/ui/table/TableCaption.vue +4 -4
- package/src/components/ui/table/TableCell.vue +8 -8
- package/src/components/ui/table/TableEmpty.vue +14 -14
- package/src/components/ui/table/TableFooter.vue +8 -8
- package/src/components/ui/table/TableHead.vue +8 -8
- package/src/components/ui/table/TableHeader.vue +4 -4
- package/src/components/ui/table/TableRow.vue +8 -8
- package/src/components/ui/tabs/Tabs.vue +4 -4
- package/src/components/ui/tabs/TabsContent.vue +4 -4
- package/src/components/ui/tabs/TabsList.vue +15 -15
- package/src/components/ui/tabs/TabsTrigger.vue +10 -10
- package/src/components/ui/tags-input/TagsInput.vue +17 -17
- package/src/components/ui/tags-input/TagsInputInput.vue +6 -6
- package/src/components/ui/tags-input/TagsInputItem.vue +15 -15
- package/src/components/ui/tags-input/TagsInputItemDelete.vue +12 -12
- package/src/components/ui/tags-input/TagsInputItemText.vue +4 -4
- package/src/components/ui/textarea/Textarea.vue +12 -12
- package/src/components/ui/time-picker/TimePicker.vue +25 -25
- package/src/components/ui/toggle-group/Toggle.vue +10 -10
- package/src/components/ui/toggle-group/ToggleGroup.vue +38 -38
- package/src/components/ui/toggle-group/ToggleGroupItem.vue +9 -9
- package/src/components/ui/toggle-group/index.ts +46 -46
- package/src/components/ui/tooltip/Tooltip.vue +3 -3
- package/src/components/ui/tooltip/TooltipContent.vue +13 -13
- package/src/components/ui/tooltip/TooltipProvider.vue +4 -4
- package/src/components/ui/tooltip/TooltipTrigger.vue +3 -3
- package/src/i18n/de.json +185 -185
- package/src/i18n/en.json +185 -185
- package/src/i18n/es.json +185 -185
- package/src/i18n/fr.json +185 -185
- package/src/i18n/it.json +185 -185
- package/src/i18n/ja.json +185 -185
- package/src/i18n/pt.json +185 -185
- package/src/i18n/ru.json +185 -185
- package/src/i18n/zh.json +185 -185
- package/src/lib/color-tokens.ts +24 -24
- package/src/lib/i18n.ts +65 -65
- package/src/lib/utils.ts +33 -33
- package/src/nuxt-components.d.ts +2 -2
- package/src/runtime/ui-vintage-i18n-plugin.ts +49 -49
- package/src/shims-vue.d.ts +3 -3
- package/src/styles.css +377 -377
|
@@ -5,26 +5,26 @@ export type DialogMessageType = 'error' | 'success' | 'info' | 'warning';
|
|
|
5
5
|
export type { HugeiconsIconDefinition };
|
|
6
6
|
|
|
7
7
|
export interface ShowMessageDialogOptions {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
type?: DialogMessageType;
|
|
9
|
+
title?: string;
|
|
10
|
+
message: string;
|
|
11
|
+
closeText?: string;
|
|
12
|
+
icon?: HugeiconsIconDefinition | null;
|
|
13
|
+
closeButtonIcon?: HugeiconsIconDefinition | null;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
interface MessageDialogRequest {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
id: number;
|
|
18
|
+
options: Omit<ShowMessageDialogOptions, 'icon' | 'closeButtonIcon'> & {
|
|
19
|
+
icon: HugeiconsIconDefinition | null;
|
|
20
|
+
closeButtonIcon: HugeiconsIconDefinition | null;
|
|
21
|
+
};
|
|
22
|
+
resolve: () => void;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
interface MessageDialogState {
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
current: MessageDialogRequest | null;
|
|
27
|
+
isOpen: boolean;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const messageDialogQueue: MessageDialogRequest[] = [];
|
|
@@ -37,8 +37,8 @@ const MESSAGE_DIALOG_ROOT_ID = 'ui-vintage-message-dialog-root';
|
|
|
37
37
|
|
|
38
38
|
// Shared message dialog state
|
|
39
39
|
export const messageDialogState: MessageDialogState = reactive({
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
current: null,
|
|
41
|
+
isOpen: false
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
// Keep icon definitions non-reactive
|
|
@@ -46,121 +46,121 @@ const markIcon = (icon: HugeiconsIconDefinition | null | undefined) => icon ? ma
|
|
|
46
46
|
|
|
47
47
|
// Mount the dialog once on demand
|
|
48
48
|
const ensureMessageDialogMounted = () => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
49
|
+
// Skip mounting during SSR
|
|
50
|
+
if (typeof document === 'undefined') {
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Reuse the existing mount root
|
|
55
|
+
const existingRoot = document.getElementById(MESSAGE_DIALOG_ROOT_ID);
|
|
56
|
+
if (existingRoot) {
|
|
57
|
+
return Promise.resolve();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Reuse the in-flight mount
|
|
61
|
+
if (messageDialogMountPromise) {
|
|
62
|
+
return messageDialogMountPromise;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Start the lazy mount
|
|
66
|
+
messageDialogMountPromise = (async () => {
|
|
67
|
+
// Load the component only when needed
|
|
68
|
+
const { default: MessageDialog } = await import('./MessageDialog.vue');
|
|
69
|
+
|
|
70
|
+
// Guard against a concurrent mount
|
|
71
|
+
if (document.getElementById(MESSAGE_DIALOG_ROOT_ID)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Create the host element and render the component
|
|
76
|
+
const container = document.createElement('div');
|
|
77
|
+
container.id = MESSAGE_DIALOG_ROOT_ID;
|
|
78
|
+
document.body.appendChild(container);
|
|
79
|
+
render(h(MessageDialog), container);
|
|
80
|
+
})().finally(() => {
|
|
81
|
+
messageDialogMountPromise = null;
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Let callers await the mount
|
|
85
|
+
return messageDialogMountPromise;
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
// Show the next queued dialog
|
|
89
89
|
const openNextMessageDialog = () => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
const nextDialog = messageDialogQueue.shift() ?? null;
|
|
91
|
+
messageDialogState.current = nextDialog;
|
|
92
|
+
messageDialogState.isOpen = Boolean(nextDialog);
|
|
93
93
|
};
|
|
94
94
|
|
|
95
95
|
// Queue a new dialog request
|
|
96
96
|
const enqueueMessageDialog = (request: MessageDialogRequest) => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
messageDialogQueue.push(request);
|
|
98
|
+
if (!messageDialogState.current) {
|
|
99
|
+
openNextMessageDialog();
|
|
100
|
+
}
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
// Clear the active dialog and continue the queue
|
|
104
104
|
const clearCurrentMessageDialog = () => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
messageDialogState.isOpen = false;
|
|
106
|
+
messageDialogState.current = null;
|
|
107
|
+
openNextMessageDialog();
|
|
108
108
|
};
|
|
109
109
|
|
|
110
110
|
// Close the current dialog after the leave transition
|
|
111
111
|
const scheduleCloseCurrentMessageDialog = () => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
112
|
+
// Guard against missing or already closing dialogs
|
|
113
|
+
if (!messageDialogState.current || !messageDialogState.isOpen) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Start the close transition
|
|
118
|
+
messageDialogState.isOpen = false;
|
|
119
|
+
if (closeTimer) {
|
|
120
|
+
clearTimeout(closeTimer);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Schedule the dialog to be cleared after the transition
|
|
124
|
+
closeTimer = setTimeout(() => {
|
|
125
|
+
closeTimer = null;
|
|
126
|
+
clearCurrentMessageDialog();
|
|
127
|
+
}, DIALOG_CLOSE_DURATION_MS);
|
|
128
128
|
};
|
|
129
129
|
|
|
130
130
|
// Resolve the dialog as closed
|
|
131
131
|
export const closeMessageDialog = () => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
const current = messageDialogState.current;
|
|
133
|
+
if (!current || !messageDialogState.isOpen) return;
|
|
134
|
+
current.resolve();
|
|
135
|
+
scheduleCloseCurrentMessageDialog();
|
|
136
136
|
};
|
|
137
137
|
|
|
138
138
|
// Resolve the active message dialog
|
|
139
139
|
export const resolveActiveMessageDialog = () => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
const current = messageDialogState.current;
|
|
141
|
+
if (!current || !messageDialogState.isOpen) return;
|
|
142
|
+
current.resolve();
|
|
143
|
+
scheduleCloseCurrentMessageDialog();
|
|
144
144
|
};
|
|
145
145
|
|
|
146
146
|
// Queue and show a message dialog
|
|
147
147
|
export const showMessageDialog = (options: ShowMessageDialogOptions) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
148
|
+
// Ensure the renderer exists before queuing work
|
|
149
|
+
void ensureMessageDialogMounted();
|
|
150
|
+
|
|
151
|
+
// Return a promise that resolves when the dialog is closed
|
|
152
|
+
return new Promise<void>((resolve) => {
|
|
153
|
+
enqueueMessageDialog({
|
|
154
|
+
id: nextMessageDialogId += 1,
|
|
155
|
+
options: {
|
|
156
|
+
type: options.type ?? 'info',
|
|
157
|
+
title: options.title ?? '',
|
|
158
|
+
message: options.message,
|
|
159
|
+
closeText: options.closeText ?? '',
|
|
160
|
+
icon: markIcon(options.icon),
|
|
161
|
+
closeButtonIcon: markIcon(options.closeButtonIcon)
|
|
162
|
+
},
|
|
163
|
+
resolve
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
166
|
};
|
|
@@ -26,25 +26,25 @@ const regionAriaLabel = computed(() => getUiVintageRuntimeMessage('uiVintage.toa
|
|
|
26
26
|
|
|
27
27
|
// Resolve the icon for each toast type
|
|
28
28
|
const getToastIcon = (toast: MessageToastItem) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
if (toast.icon) return toast.icon;
|
|
30
|
+
if (toast.type === 'success') return CheckmarkCircle02Icon;
|
|
31
|
+
return toast.type === 'info' ? InformationCircleIcon : AlertCircleIcon;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
// Resolve the tinted icon tile classes for each toast type
|
|
35
35
|
const toneClasses: Record<MessageToastType, string> = {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
success: 'border-success/25 bg-success/10 text-success',
|
|
37
|
+
info: 'border-info/25 bg-info/10 text-info',
|
|
38
|
+
warning: 'border-warning/25 bg-warning/10 text-warning',
|
|
39
|
+
error: 'border-destructive/25 bg-destructive/10 text-destructive'
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
// Progress bar color for each toast type
|
|
43
43
|
const progressClasses: Record<MessageToastType, string> = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
success: 'bg-success',
|
|
45
|
+
info: 'bg-info',
|
|
46
|
+
warning: 'bg-warning',
|
|
47
|
+
error: 'bg-destructive'
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
const toasts = computed(() => messageToastState.toasts);
|
|
@@ -52,41 +52,41 @@ const frontHeight = computed(() => (toasts.value[0] && heights.get(toasts.value[
|
|
|
52
52
|
|
|
53
53
|
// Height of the stack container so the hover area always matches what is visible
|
|
54
54
|
const containerHeight = computed(() => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
const visible = toasts.value.slice(0, VISIBLE_TOASTS);
|
|
56
|
+
if (!visible.length) return 0;
|
|
57
|
+
if (expanded.value) {
|
|
58
|
+
return visible.reduce((total, toast) => total + (heights.get(toast.id) || 0), 0) + STACK_GAP_PX * (visible.length - 1);
|
|
59
|
+
}
|
|
60
|
+
return frontHeight.value + STACK_OFFSET_PX * (visible.length - 1);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
// Compute the stacked position of a toast from its index (0 = newest)
|
|
64
64
|
const getToastStyle = (toast: MessageToastItem, index: number) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
65
|
+
const isSwiping = swipe.id === toast.id;
|
|
66
|
+
let offset = 0;
|
|
67
|
+
let scale = 1;
|
|
68
|
+
|
|
69
|
+
// Expanded: toasts sit on top of each other with a gap
|
|
70
|
+
if (expanded.value) {
|
|
71
|
+
for (const previous of toasts.value.slice(0, index)) {
|
|
72
|
+
offset += (heights.get(previous.id) || 0) + STACK_GAP_PX;
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
// Collapsed: toasts peek out behind the front one
|
|
76
|
+
offset = index * STACK_OFFSET_PX;
|
|
77
|
+
scale = 1 - index * 0.05;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
'--uv-toast-leave-x': `${(leaveDirection.get(toast.id) ?? 1) * 110}%`,
|
|
82
|
+
zIndex: String(100 - index),
|
|
83
|
+
translate: `${isSwiping ? swipe.deltaX : 0}px ${-offset}px`,
|
|
84
|
+
scale: String(scale),
|
|
85
|
+
opacity: index >= VISIBLE_TOASTS ? '0' : isSwiping ? String(1 - Math.min(Math.abs(swipe.deltaX) / 240, 0.6)) : '1',
|
|
86
|
+
height: !expanded.value && index > 0 && frontHeight.value ? `${frontHeight.value}px` : undefined,
|
|
87
|
+
pointerEvents: index >= VISIBLE_TOASTS ? 'none' as const : undefined,
|
|
88
|
+
transition: isSwiping ? 'none' : undefined
|
|
89
|
+
};
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
// Toast content elements currently watched by the observer, by toast id
|
|
@@ -94,172 +94,172 @@ const observedElements = new Map<number, HTMLElement>();
|
|
|
94
94
|
|
|
95
95
|
// Measure toast content heights so the stack can lay itself out
|
|
96
96
|
const resizeObserver = typeof ResizeObserver !== 'undefined'
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
? new ResizeObserver((entries) => {
|
|
98
|
+
for (const entry of entries) {
|
|
99
|
+
const id = Number((entry.target as HTMLElement).dataset.toastId);
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
// Skip late notifications for toasts that already left
|
|
102
|
+
if (observedElements.get(id) !== entry.target) continue;
|
|
103
|
+
heights.set(id, (entry.target as HTMLElement).offsetHeight);
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
: null;
|
|
107
107
|
|
|
108
108
|
// Register toast content elements with the observer
|
|
109
109
|
const observeToast = (element: unknown) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
if (element instanceof HTMLElement && resizeObserver) {
|
|
111
|
+
const id = Number(element.dataset.toastId);
|
|
112
|
+
if (observedElements.get(id) === element) return;
|
|
113
|
+
heights.set(id, element.offsetHeight);
|
|
114
|
+
observedElements.set(id, element);
|
|
115
|
+
resizeObserver.observe(element);
|
|
116
|
+
}
|
|
117
117
|
};
|
|
118
118
|
|
|
119
119
|
// Expand the stack and pause timers while the user interacts with it
|
|
120
120
|
const handleEnter = () => {
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
expanded.value = true;
|
|
122
|
+
pauseMessageToasts();
|
|
123
123
|
};
|
|
124
124
|
|
|
125
125
|
// Collapse the stack and resume timers
|
|
126
126
|
const handleLeave = () => {
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
expanded.value = false;
|
|
128
|
+
resumeMessageToasts();
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
// Begin a horizontal swipe gesture
|
|
132
132
|
const handlePointerDown = (event: PointerEvent, toast: MessageToastItem) => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
if (!toast.dismissible || event.button !== 0 || (event.target as HTMLElement).closest('button')) return;
|
|
134
|
+
swipe.id = toast.id;
|
|
135
|
+
swipe.startX = event.clientX;
|
|
136
|
+
swipe.deltaX = 0;
|
|
137
|
+
(event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
|
|
138
138
|
};
|
|
139
139
|
|
|
140
140
|
// Follow the pointer while swiping
|
|
141
141
|
const handlePointerMove = (event: PointerEvent) => {
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
if (swipe.id === null) return;
|
|
143
|
+
swipe.deltaX = event.clientX - swipe.startX;
|
|
144
144
|
};
|
|
145
145
|
|
|
146
146
|
// Dismiss the toast when swiped far enough, otherwise spring back
|
|
147
147
|
const handlePointerUp = () => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
148
|
+
if (swipe.id === null) return;
|
|
149
|
+
const id = swipe.id;
|
|
150
|
+
const deltaX = swipe.deltaX;
|
|
151
|
+
swipe.id = null;
|
|
152
|
+
swipe.deltaX = 0;
|
|
153
|
+
if (Math.abs(deltaX) > SWIPE_THRESHOLD_PX) {
|
|
154
|
+
leaveDirection.set(id, Math.sign(deltaX));
|
|
155
|
+
closeMessageToast(id);
|
|
156
|
+
}
|
|
157
157
|
};
|
|
158
158
|
|
|
159
159
|
// Run a toast action and dismiss it
|
|
160
160
|
const handleAction = async (toast: MessageToastItem) => {
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
closeMessageToast(toast.id);
|
|
162
|
+
await toast.action?.onClick();
|
|
163
163
|
};
|
|
164
164
|
|
|
165
165
|
// Forget measurements of removed toasts
|
|
166
166
|
const handleAfterLeave = (element: Element) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
167
|
+
const id = Number((element as HTMLElement).dataset.toastId);
|
|
168
|
+
const content = observedElements.get(id);
|
|
169
|
+
if (content) {
|
|
170
|
+
resizeObserver?.unobserve(content);
|
|
171
|
+
observedElements.delete(id);
|
|
172
|
+
}
|
|
173
|
+
heights.delete(id);
|
|
174
|
+
leaveDirection.delete(id);
|
|
175
175
|
};
|
|
176
176
|
|
|
177
177
|
// Reset the interaction state once the stack is empty (mouseleave never fires on a collapsed region)
|
|
178
178
|
watch(() => toasts.value.length, (length) => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
if (length === 0 && expanded.value) {
|
|
180
|
+
handleLeave();
|
|
181
|
+
}
|
|
182
182
|
});
|
|
183
183
|
|
|
184
184
|
// Stop observing on unmount
|
|
185
185
|
onBeforeUnmount(() => {
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
resizeObserver?.disconnect();
|
|
187
|
+
observedElements.clear();
|
|
188
188
|
});
|
|
189
189
|
</script>
|
|
190
190
|
|
|
191
191
|
<template>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
192
|
+
<section :aria-label="regionAriaLabel" class="pointer-events-none fixed inset-x-3 bottom-3 z-60 sm:inset-x-auto sm:right-6 sm:bottom-6 sm:w-[380px]">
|
|
193
|
+
<ol class="pointer-events-auto relative transition-[height] duration-300 ease-out-expo" :style="{ height: `${containerHeight}px` }" @mouseenter="handleEnter" @mouseleave="handleLeave" @focusin="handleEnter" @focusout="handleLeave">
|
|
194
|
+
<TransitionGroup name="uv-toast" @after-leave="handleAfterLeave">
|
|
195
|
+
<li v-for="(toast, index) in toasts" :key="toast.id" :data-toast-id="toast.id" :data-front="index === 0 ? '' : undefined" role="status" :aria-live="toast.type === 'error' || toast.type === 'warning' ? 'assertive' : 'polite'" aria-atomic="true" class="uv-toast absolute inset-x-0 bottom-0 origin-bottom touch-pan-y select-none overflow-hidden rounded border border-border bg-card text-card-foreground shadow-elevated-lg" :style="getToastStyle(toast, index)" @pointerdown="handlePointerDown($event, toast)" @pointermove="handlePointerMove" @pointerup="handlePointerUp" @pointercancel="handlePointerUp">
|
|
196
|
+
<!-- Measured content -->
|
|
197
|
+
<div :ref="observeToast" :data-toast-id="toast.id" :class="cn('flex items-start gap-3 p-4 transition-opacity duration-200', !expanded && index > 0 && 'opacity-0')">
|
|
198
|
+
<!-- Leading type icon -->
|
|
199
|
+
<div :class="cn('flex size-8 shrink-0 items-center justify-center rounded border', toneClasses[toast.type])">
|
|
200
|
+
<HugeiconsIcon :icon="getToastIcon(toast)" :stroke-width="1.8" class="size-4.5 animate-uv-pop [animation-delay:120ms]" />
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<!-- Title and message -->
|
|
204
|
+
<div class="min-w-0 flex-1 self-center">
|
|
205
|
+
<p v-if="toast.title" class="m-0 text-sm font-semibold leading-5">
|
|
206
|
+
{{ toast.title }}
|
|
207
|
+
</p>
|
|
208
|
+
<p :class="cn('m-0 text-sm leading-5 wrap-break-word', toast.title && 'text-xs text-muted-foreground sm:text-[13px]')">
|
|
209
|
+
{{ toast.message }}
|
|
210
|
+
</p>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
<!-- Action button -->
|
|
214
|
+
<button v-if="toast.action" type="button" class="shrink-0 self-center rounded border border-border bg-secondary px-2.5 py-1.5 text-xs font-semibold shadow-elevated-sm outline-none transition-[background-color,border-color,transform] duration-150 hover:border-border-strong hover:bg-accent focus-visible:ring-[3px] focus-visible:ring-ring/45 active:scale-95" @click="handleAction(toast)">
|
|
215
|
+
{{ toast.action.label }}
|
|
216
|
+
</button>
|
|
217
|
+
|
|
218
|
+
<!-- Dismiss button -->
|
|
219
|
+
<button v-if="toast.dismissible" type="button" :aria-label="closeAriaLabel" class="group/close -me-1 -mt-1 flex size-7 shrink-0 cursor-pointer items-center justify-center rounded text-muted-foreground outline-none transition-colors duration-150 hover:bg-accent hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/45" @click="closeMessageToast(toast.id)">
|
|
220
|
+
<HugeiconsIcon :icon="Cancel01Icon" class="size-4 transition-transform duration-300 ease-spring group-hover/close:rotate-90" />
|
|
221
|
+
</button>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<!-- Countdown bar -->
|
|
225
|
+
<div v-if="toast.duration > 0" class="absolute inset-x-0 bottom-0 h-0.5 bg-transparent">
|
|
226
|
+
<div :class="cn('h-full origin-left opacity-60', progressClasses[toast.type])" :style="{ animation: `uv-toast-countdown ${toast.duration}ms linear forwards`, animationPlayState: messageToastState.paused ? 'paused' : 'running' }" />
|
|
227
|
+
</div>
|
|
228
|
+
</li>
|
|
229
|
+
</TransitionGroup>
|
|
230
|
+
</ol>
|
|
231
|
+
</section>
|
|
232
232
|
</template>
|
|
233
233
|
|
|
234
234
|
<style>
|
|
235
235
|
.uv-toast {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
236
|
+
transition:
|
|
237
|
+
translate 480ms var(--ease-spring),
|
|
238
|
+
scale 480ms var(--ease-spring),
|
|
239
|
+
opacity 250ms var(--ease-out-expo),
|
|
240
|
+
height 300ms var(--ease-out-expo),
|
|
241
|
+
transform 480ms var(--ease-spring);
|
|
242
|
+
will-change: translate, scale;
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
.uv-toast-enter-from {
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
opacity: 0 !important;
|
|
247
|
+
transform: translateY(110%) scale(0.92);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
.uv-toast-leave-active {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
transition:
|
|
252
|
+
transform 260ms var(--ease-snappy),
|
|
253
|
+
opacity 200ms var(--ease-snappy) !important;
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
.uv-toast-leave-to {
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
opacity: 0 !important;
|
|
258
|
+
transform: translateX(var(--uv-toast-leave-x, 110%));
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
@keyframes uv-toast-countdown {
|
|
262
|
-
|
|
263
|
-
|
|
262
|
+
from { transform: scaleX(1); }
|
|
263
|
+
to { transform: scaleX(0); }
|
|
264
264
|
}
|
|
265
265
|
</style>
|