@brumaombra/ui-vintage 0.9.0 → 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/AGENTS.md +1 -1
- package/COMPONENTS.md +1 -1
- package/README.md +3 -3
- 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 +20 -20
- package/src/components/blog/BlogHeaderSection.vue +81 -81
- package/src/components/blog/BlogInfoSection.vue +50 -48
- 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 +27 -26
- package/src/components/blog/HeaderCarousel.vue +99 -98
- package/src/components/blog/PostCard.vue +34 -34
- package/src/components/blog/PostsList.vue +15 -15
- package/src/components/blog/SocialShareSidebar.vue +92 -85
- package/src/components/blog/TableOfContents.vue +310 -308
- 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 +35 -35
- package/src/components/chip/Chip.vue +16 -16
- package/src/components/confirm-dialog/ConfirmDialog.vue +51 -51
- package/src/components/confirm-dialog/confirm-dialog-state.ts +131 -131
- package/src/components/content/BlogList.vue +32 -31
- package/src/components/content/BlogTable.vue +36 -36
- package/src/components/content/CodeBlock.vue +139 -137
- package/src/components/content/Flow.vue +60 -60
- package/src/components/content/ProseHr.vue +16 -16
- package/src/components/content/ProsePre.vue +12 -12
- package/src/components/content/Terminal.vue +62 -60
- 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 +41 -41
- package/src/components/error-page/ErrorPage.vue +73 -73
- 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 +129 -129
- 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 +77 -77
- package/src/components/load-more-button/LoadMoreButton.vue +19 -18
- package/src/components/loading-state-card/LoadingStateCard.vue +29 -29
- package/src/components/message-dialog/MessageDialog.vue +62 -60
- package/src/components/message-dialog/message-dialog-state.ts +105 -105
- package/src/components/message-toast/MessageToast.vue +153 -150
- 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 +59 -58
- 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 +65 -62
- package/src/components/theme-selector/theme-transition.ts +63 -63
- package/src/components/ui/accordion/Accordion.vue +39 -39
- 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 +10 -10
- 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 +16 -16
- package/src/components/ui/calendar/CalendarPrevButton.vue +16 -16
- 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 +18 -18
- package/src/components/ui/combobox/ComboboxList.vue +19 -19
- package/src/components/ui/combobox/ComboboxSelect.vue +79 -78
- package/src/components/ui/combobox/ComboboxSeparator.vue +1 -1
- package/src/components/ui/combobox/ComboboxTrigger.vue +11 -11
- 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 +10 -10
- 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 +147 -146
- package/src/components/ui/data-table/index.ts +11 -11
- package/src/components/ui/date-picker/DatePicker.vue +32 -32
- 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 +22 -22
- 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 +33 -33
- 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 +12 -12
- 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 +16 -16
- 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 +163 -154
- 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 +17 -17
- 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 +90 -89
- 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 +10 -10
- package/src/components/ui/pagination/PaginationFirst.vue +9 -9
- package/src/components/ui/pagination/PaginationItem.vue +14 -14
- package/src/components/ui/pagination/PaginationLast.vue +9 -9
- package/src/components/ui/pagination/PaginationNext.vue +9 -9
- package/src/components/ui/pagination/PaginationPrevious.vue +9 -9
- 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 +25 -25
- 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 +10 -10
- package/src/components/ui/select/SelectScrollUpButton.vue +10 -10
- package/src/components/ui/select/SelectSeparator.vue +2 -2
- package/src/components/ui/select/SelectTrigger.vue +15 -15
- 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 +6 -6
- 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 +27 -27
- 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 +18 -18
- 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 +13 -13
- 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
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
2
|
+
import AlertCircleIcon from '@hugeicons/core-free-icons/AlertCircleIcon';
|
|
3
|
+
import Cancel01Icon from '@hugeicons/core-free-icons/Cancel01Icon';
|
|
4
|
+
import CheckmarkCircle02Icon from '@hugeicons/core-free-icons/CheckmarkCircle02Icon';
|
|
5
|
+
import InformationCircleIcon from '@hugeicons/core-free-icons/InformationCircleIcon';
|
|
3
6
|
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
4
7
|
import { computed, onBeforeUnmount, reactive, ref, watch } from 'vue';
|
|
5
8
|
import { getUiVintageRuntimeMessage } from '../../lib/i18n';
|
|
@@ -23,25 +26,25 @@ const regionAriaLabel = computed(() => getUiVintageRuntimeMessage('uiVintage.toa
|
|
|
23
26
|
|
|
24
27
|
// Resolve the icon for each toast type
|
|
25
28
|
const getToastIcon = (toast: MessageToastItem) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if (toast.icon) return toast.icon;
|
|
30
|
+
if (toast.type === 'success') return CheckmarkCircle02Icon;
|
|
31
|
+
return toast.type === 'info' ? InformationCircleIcon : AlertCircleIcon;
|
|
29
32
|
};
|
|
30
33
|
|
|
31
34
|
// Resolve the tinted icon tile classes for each toast type
|
|
32
35
|
const toneClasses: Record<MessageToastType, string> = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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'
|
|
37
40
|
};
|
|
38
41
|
|
|
39
42
|
// Progress bar color for each toast type
|
|
40
43
|
const progressClasses: Record<MessageToastType, string> = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
success: 'bg-success',
|
|
45
|
+
info: 'bg-info',
|
|
46
|
+
warning: 'bg-warning',
|
|
47
|
+
error: 'bg-destructive'
|
|
45
48
|
};
|
|
46
49
|
|
|
47
50
|
const toasts = computed(() => messageToastState.toasts);
|
|
@@ -49,41 +52,41 @@ const frontHeight = computed(() => (toasts.value[0] && heights.get(toasts.value[
|
|
|
49
52
|
|
|
50
53
|
// Height of the stack container so the hover area always matches what is visible
|
|
51
54
|
const containerHeight = computed(() => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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);
|
|
58
61
|
});
|
|
59
62
|
|
|
60
63
|
// Compute the stacked position of a toast from its index (0 = newest)
|
|
61
64
|
const getToastStyle = (toast: MessageToastItem, index: number) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
+
};
|
|
87
90
|
};
|
|
88
91
|
|
|
89
92
|
// Toast content elements currently watched by the observer, by toast id
|
|
@@ -91,172 +94,172 @@ const observedElements = new Map<number, HTMLElement>();
|
|
|
91
94
|
|
|
92
95
|
// Measure toast content heights so the stack can lay itself out
|
|
93
96
|
const resizeObserver = typeof ResizeObserver !== 'undefined'
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
? new ResizeObserver((entries) => {
|
|
98
|
+
for (const entry of entries) {
|
|
99
|
+
const id = Number((entry.target as HTMLElement).dataset.toastId);
|
|
97
100
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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;
|
|
104
107
|
|
|
105
108
|
// Register toast content elements with the observer
|
|
106
109
|
const observeToast = (element: unknown) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
+
}
|
|
114
117
|
};
|
|
115
118
|
|
|
116
119
|
// Expand the stack and pause timers while the user interacts with it
|
|
117
120
|
const handleEnter = () => {
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
expanded.value = true;
|
|
122
|
+
pauseMessageToasts();
|
|
120
123
|
};
|
|
121
124
|
|
|
122
125
|
// Collapse the stack and resume timers
|
|
123
126
|
const handleLeave = () => {
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
expanded.value = false;
|
|
128
|
+
resumeMessageToasts();
|
|
126
129
|
};
|
|
127
130
|
|
|
128
131
|
// Begin a horizontal swipe gesture
|
|
129
132
|
const handlePointerDown = (event: PointerEvent, toast: MessageToastItem) => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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);
|
|
135
138
|
};
|
|
136
139
|
|
|
137
140
|
// Follow the pointer while swiping
|
|
138
141
|
const handlePointerMove = (event: PointerEvent) => {
|
|
139
|
-
|
|
140
|
-
|
|
142
|
+
if (swipe.id === null) return;
|
|
143
|
+
swipe.deltaX = event.clientX - swipe.startX;
|
|
141
144
|
};
|
|
142
145
|
|
|
143
146
|
// Dismiss the toast when swiped far enough, otherwise spring back
|
|
144
147
|
const handlePointerUp = () => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
+
}
|
|
154
157
|
};
|
|
155
158
|
|
|
156
159
|
// Run a toast action and dismiss it
|
|
157
160
|
const handleAction = async (toast: MessageToastItem) => {
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
closeMessageToast(toast.id);
|
|
162
|
+
await toast.action?.onClick();
|
|
160
163
|
};
|
|
161
164
|
|
|
162
165
|
// Forget measurements of removed toasts
|
|
163
166
|
const handleAfterLeave = (element: Element) => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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);
|
|
172
175
|
};
|
|
173
176
|
|
|
174
177
|
// Reset the interaction state once the stack is empty (mouseleave never fires on a collapsed region)
|
|
175
178
|
watch(() => toasts.value.length, (length) => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
if (length === 0 && expanded.value) {
|
|
180
|
+
handleLeave();
|
|
181
|
+
}
|
|
179
182
|
});
|
|
180
183
|
|
|
181
184
|
// Stop observing on unmount
|
|
182
185
|
onBeforeUnmount(() => {
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
resizeObserver?.disconnect();
|
|
187
|
+
observedElements.clear();
|
|
185
188
|
});
|
|
186
189
|
</script>
|
|
187
190
|
|
|
188
191
|
<template>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
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>
|
|
229
232
|
</template>
|
|
230
233
|
|
|
231
234
|
<style>
|
|
232
235
|
.uv-toast {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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;
|
|
240
243
|
}
|
|
241
244
|
|
|
242
245
|
.uv-toast-enter-from {
|
|
243
|
-
|
|
244
|
-
|
|
246
|
+
opacity: 0 !important;
|
|
247
|
+
transform: translateY(110%) scale(0.92);
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
.uv-toast-leave-active {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
+
transition:
|
|
252
|
+
transform 260ms var(--ease-snappy),
|
|
253
|
+
opacity 200ms var(--ease-snappy) !important;
|
|
251
254
|
}
|
|
252
255
|
|
|
253
256
|
.uv-toast-leave-to {
|
|
254
|
-
|
|
255
|
-
|
|
257
|
+
opacity: 0 !important;
|
|
258
|
+
transform: translateX(var(--uv-toast-leave-x, 110%));
|
|
256
259
|
}
|
|
257
260
|
|
|
258
261
|
@keyframes uv-toast-countdown {
|
|
259
|
-
|
|
260
|
-
|
|
262
|
+
from { transform: scaleX(1); }
|
|
263
|
+
to { transform: scaleX(0); }
|
|
261
264
|
}
|
|
262
265
|
</style>
|