@brumaombra/ui-vintage 0.9.1 → 0.9.3
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/COMPONENTS.md +102 -2
- 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/BlogCategoriesPage.vue +46 -0
- 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/BlogIndexPage.vue +118 -0
- package/src/components/blog/BlogInfoSection.vue +47 -47
- package/src/components/blog/BlogPageBreadcrumbs.vue +43 -0
- package/src/components/blog/BlogPostHeader.vue +135 -135
- package/src/components/blog/BlogPostPage.vue +116 -0
- package/src/components/blog/BlogPostsPage.vue +74 -0
- package/src/components/blog/BlogProgressBar.vue +33 -33
- package/src/components/blog/BlogSectionTitle.vue +22 -22
- package/src/components/blog/BlogTagsPage.vue +46 -0
- package/src/components/blog/BlogTagsSection.vue +25 -25
- package/src/components/blog/BlogViewAllLink.vue +18 -0
- 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/blog/blogPageUtils.ts +98 -0
- package/src/components/blog/index.ts +12 -1
- 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 +206 -185
- package/src/i18n/en.json +206 -185
- package/src/i18n/es.json +206 -185
- package/src/i18n/fr.json +206 -185
- package/src/i18n/it.json +206 -185
- package/src/i18n/ja.json +206 -185
- package/src/i18n/pt.json +206 -185
- package/src/i18n/ru.json +206 -185
- package/src/i18n/zh.json +206 -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
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Post fields read by the blog page helpers (a Nuxt Content blog collection entry)
|
|
2
|
+
export interface BlogPostData {
|
|
3
|
+
path?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
image?: string;
|
|
7
|
+
categoryText?: string;
|
|
8
|
+
categorySlug?: string;
|
|
9
|
+
tags?: string[];
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Category card data built from the posts
|
|
14
|
+
export interface BlogCategoryData {
|
|
15
|
+
name: string;
|
|
16
|
+
slug: string;
|
|
17
|
+
path: string;
|
|
18
|
+
count: number;
|
|
19
|
+
image?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Tag badge data built from the posts
|
|
23
|
+
export interface BlogTagData {
|
|
24
|
+
name: string;
|
|
25
|
+
slug: string;
|
|
26
|
+
count: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Turn a label into a URL slug (e.g. "Dark Mode" -> "dark-mode")
|
|
30
|
+
export const slugify = (value: unknown) => {
|
|
31
|
+
return String(value || '')
|
|
32
|
+
.trim()
|
|
33
|
+
.toLowerCase()
|
|
34
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
35
|
+
.replace(/^-+|-+$/g, '');
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Remove the trailing slashes of a route path, since content paths never have one ("/blog/post/" -> "/blog/post")
|
|
39
|
+
export const normalizeContentPath = (path: string) => path.replace(/(.)\/+$/, '$1');
|
|
40
|
+
|
|
41
|
+
// Build the unique categories of the posts, with their post count and the image of their first post
|
|
42
|
+
export const buildCategoriesFromPosts = (posts: BlogPostData[], getPath: (slug: string) => string): BlogCategoryData[] => {
|
|
43
|
+
const categoriesList = posts.map(post => post.categorySlug);
|
|
44
|
+
const uniqueCategories = categoriesList.filter((category, index, self): category is string => !!category && self.indexOf(category) === index);
|
|
45
|
+
|
|
46
|
+
// Map unique categories to category data
|
|
47
|
+
return uniqueCategories.map(category => {
|
|
48
|
+
const firstPost = posts.find(post => post.categorySlug === category);
|
|
49
|
+
|
|
50
|
+
// Return category data
|
|
51
|
+
return {
|
|
52
|
+
name: firstPost?.categoryText || category,
|
|
53
|
+
slug: category,
|
|
54
|
+
path: getPath(category),
|
|
55
|
+
count: categoriesList.filter(item => item === category).length,
|
|
56
|
+
image: firstPost?.image
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Build the unique tags of the posts, with their number of uses (the first label wins for tags that share a slug)
|
|
62
|
+
export const buildTagsFromPosts = (posts: BlogPostData[]): BlogTagData[] => {
|
|
63
|
+
const tagsBySlug = new Map<string, BlogTagData>();
|
|
64
|
+
|
|
65
|
+
// Loop through each post and tag
|
|
66
|
+
for (const post of posts) {
|
|
67
|
+
for (const tag of post.tags || []) {
|
|
68
|
+
const slug = slugify(tag);
|
|
69
|
+
if (!slug) continue; // Skip tags that cannot produce a URL slug
|
|
70
|
+
|
|
71
|
+
// Preserve the first label while counting the duplicates
|
|
72
|
+
const existingTag = tagsBySlug.get(slug);
|
|
73
|
+
tagsBySlug.set(slug, {
|
|
74
|
+
name: existingTag?.name || tag,
|
|
75
|
+
slug,
|
|
76
|
+
count: (existingTag?.count || 0) + 1
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Return unique tags with their post counts
|
|
82
|
+
return [...tagsBySlug.values()];
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Create a deterministic hash for stable related content ordering (FNV-1a: a linear hash would give every seed the same order)
|
|
86
|
+
const hashString = (value: string) => {
|
|
87
|
+
let hash = 2166136261;
|
|
88
|
+
for (let index = 0; index < value.length; index++) {
|
|
89
|
+
hash ^= value.charCodeAt(index);
|
|
90
|
+
hash = Math.imul(hash, 16777619);
|
|
91
|
+
}
|
|
92
|
+
return hash >>> 0;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Sort a list by a deterministic score derived from a seed (the same post always shows the same related items, on the server and in the browser)
|
|
96
|
+
export const sortByStableSeed = <T>(items: T[], seed: string, getKey: (item: T) => string) => {
|
|
97
|
+
return [...items].sort((itemA, itemB) => hashString(`${seed}-${getKey(itemA)}`) - hashString(`${seed}-${getKey(itemB)}`));
|
|
98
|
+
};
|
|
@@ -13,4 +13,15 @@ export { default as HeaderCarousel } from './HeaderCarousel.vue';
|
|
|
13
13
|
export { default as PostCard } from './PostCard.vue';
|
|
14
14
|
export { default as PostsList } from './PostsList.vue';
|
|
15
15
|
export { default as SocialShareSidebar } from './SocialShareSidebar.vue';
|
|
16
|
-
export { default as TableOfContents } from './TableOfContents.vue';
|
|
16
|
+
export { default as TableOfContents } from './TableOfContents.vue';
|
|
17
|
+
// Complete blog pages (the app fetches the content and sets the SEO, these render the page)
|
|
18
|
+
export { default as BlogIndexPage } from './BlogIndexPage.vue';
|
|
19
|
+
export { default as BlogPostPage } from './BlogPostPage.vue';
|
|
20
|
+
export { default as BlogCategoriesPage } from './BlogCategoriesPage.vue';
|
|
21
|
+
export { default as BlogTagsPage } from './BlogTagsPage.vue';
|
|
22
|
+
export { default as BlogPostsPage } from './BlogPostsPage.vue';
|
|
23
|
+
export { default as BlogViewAllLink } from './BlogViewAllLink.vue';
|
|
24
|
+
|
|
25
|
+
// Helpers for the data of the blog pages
|
|
26
|
+
export { slugify, normalizeContentPath, buildCategoriesFromPosts, buildTagsFromPosts, sortByStableSeed } from './blogPageUtils';
|
|
27
|
+
export type { BlogPostData, BlogCategoryData, BlogTagData } from './blogPageUtils';
|
|
@@ -4,11 +4,11 @@ import { busyIndicatorState } from './busy-indicator-state';
|
|
|
4
4
|
</script>
|
|
5
5
|
|
|
6
6
|
<template>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
<!-- Busy overlay -->
|
|
8
|
+
<Busy
|
|
9
|
+
:show="busyIndicatorState.show"
|
|
10
|
+
:label="busyIndicatorState.label"
|
|
11
|
+
:class="busyIndicatorState.class"
|
|
12
|
+
:overlay-class="busyIndicatorState.overlayClass"
|
|
13
|
+
/>
|
|
14
14
|
</template>
|
|
@@ -2,16 +2,16 @@ import { h, reactive, render, type HTMLAttributes } from 'vue';
|
|
|
2
2
|
import { getUiVintageRuntimeMessage } from '../../lib/i18n';
|
|
3
3
|
|
|
4
4
|
export interface SetBusyOptions {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
label?: string;
|
|
6
|
+
class?: HTMLAttributes['class'];
|
|
7
|
+
overlayClass?: HTMLAttributes['class'];
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
interface BusyIndicatorState {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
show: boolean;
|
|
12
|
+
label: string;
|
|
13
|
+
class: HTMLAttributes['class'];
|
|
14
|
+
overlayClass: HTMLAttributes['class'];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const BUSY_INDICATOR_ROOT_ID = 'ui-vintage-busy-indicator-root';
|
|
@@ -20,69 +20,69 @@ let busyIndicatorMountPromise: Promise<void> | null = null;
|
|
|
20
20
|
|
|
21
21
|
// Shared busy state
|
|
22
22
|
export const busyIndicatorState: BusyIndicatorState = reactive({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
show: false,
|
|
24
|
+
label: getUiVintageRuntimeMessage('uiVintage.common.loading.title', 'Loading...'),
|
|
25
|
+
class: undefined,
|
|
26
|
+
overlayClass: undefined
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
// Mount the busy indicator once on demand
|
|
30
30
|
const ensureBusyIndicatorMounted = () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
// Skip mounting during SSR
|
|
32
|
+
if (typeof document === 'undefined') {
|
|
33
|
+
return Promise.resolve();
|
|
34
|
+
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
// Reuse the existing mount root
|
|
37
|
+
const existingRoot = document.getElementById(BUSY_INDICATOR_ROOT_ID);
|
|
38
|
+
if (existingRoot) {
|
|
39
|
+
return Promise.resolve();
|
|
40
|
+
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
// Reuse the in-flight mount
|
|
43
|
+
if (busyIndicatorMountPromise) {
|
|
44
|
+
return busyIndicatorMountPromise;
|
|
45
|
+
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
// Start the lazy mount
|
|
48
|
+
busyIndicatorMountPromise = (async () => {
|
|
49
|
+
// Load the component only when needed
|
|
50
|
+
const { default: BusyIndicator } = await import('./BusyIndicator.vue');
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
// Guard against a concurrent mount
|
|
53
|
+
if (document.getElementById(BUSY_INDICATOR_ROOT_ID)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
// Create the host element and render the component
|
|
58
|
+
const container = document.createElement('div');
|
|
59
|
+
container.id = BUSY_INDICATOR_ROOT_ID;
|
|
60
|
+
document.body.appendChild(container);
|
|
61
|
+
render(h(BusyIndicator), container);
|
|
62
|
+
})().finally(() => {
|
|
63
|
+
busyIndicatorMountPromise = null;
|
|
64
|
+
});
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
// Let callers await the mount
|
|
67
|
+
return busyIndicatorMountPromise;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
// Toggle the global busy overlay
|
|
71
71
|
export const setBusy = (show: boolean, options: SetBusyOptions = {}) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
// Prepare the overlay before showing it
|
|
73
|
+
if (show) {
|
|
74
|
+
busyIndicatorState.label = options.label ?? getUiVintageRuntimeMessage('uiVintage.common.loading.title', 'Loading...');
|
|
75
|
+
busyIndicatorState.class = options.class;
|
|
76
|
+
busyIndicatorState.overlayClass = options.overlayClass;
|
|
77
|
+
void ensureBusyIndicatorMounted();
|
|
78
|
+
}
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
// Toggle the overlay visibility
|
|
81
|
+
busyIndicatorState.show = show;
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
// Reset transient styling after hiding
|
|
84
|
+
if (!show) {
|
|
85
|
+
busyIndicatorState.class = undefined;
|
|
86
|
+
busyIndicatorState.overlayClass = undefined;
|
|
87
|
+
}
|
|
88
88
|
};
|
|
@@ -7,55 +7,55 @@ import type { HugeiconsIconDefinition } from '../../lib/common-types';
|
|
|
7
7
|
|
|
8
8
|
// Props
|
|
9
9
|
const props = withDefaults(defineProps<{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
items?: T[];
|
|
11
|
+
busy?: boolean;
|
|
12
|
+
loadMoreBusy?: boolean;
|
|
13
|
+
hasMore?: boolean;
|
|
14
|
+
emptyMessage: string;
|
|
15
|
+
emptyIcon?: HugeiconsIconDefinition;
|
|
16
16
|
}>(), {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
items: () => [],
|
|
18
|
+
busy: false,
|
|
19
|
+
loadMoreBusy: false,
|
|
20
|
+
hasMore: false,
|
|
21
|
+
emptyIcon: () => PackageIcon
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
// Emits
|
|
25
25
|
const emits = defineEmits<{
|
|
26
|
-
|
|
26
|
+
'load-more': [];
|
|
27
27
|
}>();
|
|
28
28
|
|
|
29
29
|
// Slots
|
|
30
30
|
defineSlots<{
|
|
31
|
-
|
|
31
|
+
card(props: { item: T; key?: PropertyKey }): unknown;
|
|
32
32
|
}>();
|
|
33
33
|
|
|
34
34
|
// Handle load more
|
|
35
35
|
const handleLoadMore = () => {
|
|
36
|
-
|
|
36
|
+
emits('load-more');
|
|
37
37
|
};
|
|
38
38
|
</script>
|
|
39
39
|
|
|
40
40
|
<template>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
41
|
+
<div>
|
|
42
|
+
<!-- Busy state for initial loading -->
|
|
43
|
+
<LoadingStateCard v-if="props.busy" />
|
|
44
|
+
|
|
45
|
+
<!-- Empty state -->
|
|
46
|
+
<EmptyStateCard v-else-if="props.items.length === 0"
|
|
47
|
+
:description="props.emptyMessage"
|
|
48
|
+
:icon="props.emptyIcon" />
|
|
49
|
+
|
|
50
|
+
<!-- Cards grid -->
|
|
51
|
+
<div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 md:gap-6 xl:gap-4">
|
|
52
|
+
<slot name="card" v-for="item in props.items" :item="item" :key="item.id" />
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<!-- Load more button (only under a grid, never under the loading or empty state) -->
|
|
56
|
+
<div v-if="!props.busy && props.items.length > 0 && (props.hasMore || props.loadMoreBusy)" class="flex justify-center mt-6">
|
|
57
|
+
<LoadMoreButton :busy="props.loadMoreBusy"
|
|
58
|
+
@load-more="handleLoadMore" />
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
61
|
</template>
|
|
@@ -9,12 +9,12 @@ import { cn } from '../../lib/utils';
|
|
|
9
9
|
|
|
10
10
|
// Props
|
|
11
11
|
const props = withDefaults(defineProps<{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
text: string;
|
|
13
|
+
color?: ToneColor;
|
|
14
|
+
removeLabel?: string;
|
|
15
|
+
class?: HTMLAttributes['class'];
|
|
16
16
|
}>(), {
|
|
17
|
-
|
|
17
|
+
color: 'gray'
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const { t } = useI18n();
|
|
@@ -22,23 +22,23 @@ const resolvedRemoveLabel = computed(() => props.removeLabel || t('uiVintage.but
|
|
|
22
22
|
|
|
23
23
|
// Emits
|
|
24
24
|
const emits = defineEmits<{
|
|
25
|
-
|
|
25
|
+
remove: []
|
|
26
26
|
}>();
|
|
27
27
|
|
|
28
28
|
// Handle remove button click
|
|
29
29
|
const handleRemove = () => {
|
|
30
|
-
|
|
30
|
+
emits('remove');
|
|
31
31
|
};
|
|
32
32
|
</script>
|
|
33
33
|
|
|
34
34
|
<template>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
<div data-slot="chip" :class="cn('inline-flex items-center gap-2 rounded border px-3 py-2 text-sm font-semibold transition-colors duration-150', getSurfaceToneClasses(props.color), props.class)">
|
|
36
|
+
<!-- Text content -->
|
|
37
|
+
<span class="leading-none">{{ props.text }}</span>
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
<!-- Remove button -->
|
|
40
|
+
<button type="button" :aria-label="resolvedRemoveLabel" class="group/remove inline-flex size-4 cursor-pointer items-center justify-center rounded-sm opacity-70 [transition:opacity_150ms,background-color_150ms,scale_300ms_var(--ease-spring)] hover:bg-black/5 hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-current/20 active:scale-75 dark:hover:bg-white/10" @click="handleRemove">
|
|
41
|
+
<HugeiconsIcon :icon="Cancel01Icon" class="size-3 transition-transform duration-300 ease-spring group-hover/remove:rotate-90" />
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
44
|
</template>
|
|
@@ -11,66 +11,66 @@ const pendingAction = ref<'confirm' | 'cancel' | null>(null);
|
|
|
11
11
|
|
|
12
12
|
// Run an action while showing a spinner on the button that triggered it
|
|
13
13
|
const runAction = async (action: 'confirm' | 'cancel') => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
// Ignore clicks while another action is still running
|
|
15
|
+
if (pendingAction.value) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
pendingAction.value = action;
|
|
20
|
+
try {
|
|
21
|
+
await (action === 'confirm' ? confirmActiveDialog() : cancelActiveConfirmDialog());
|
|
22
|
+
} finally {
|
|
23
|
+
pendingAction.value = null;
|
|
24
|
+
}
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
// Close the dialog when the shell requests it
|
|
28
28
|
const handleOpenChange = (open: boolean) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
if (!open) {
|
|
30
|
+
closeConfirmDialog();
|
|
31
|
+
}
|
|
32
32
|
};
|
|
33
33
|
</script>
|
|
34
34
|
|
|
35
35
|
<template>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
<!-- Dialog shell -->
|
|
37
|
+
<AlertDialog :open="confirmDialogState.isOpen" @update:open="handleOpenChange">
|
|
38
|
+
<!-- Dialog content -->
|
|
39
|
+
<AlertDialogContent v-if="currentDialog">
|
|
40
|
+
<div class="px-5 pb-5 pt-5 sm:px-6 sm:pb-4 sm:pt-6">
|
|
41
|
+
<div class="flex flex-col gap-4 sm:flex-row sm:items-start">
|
|
42
|
+
<!-- Dialog icon -->
|
|
43
|
+
<div class="flex size-12 shrink-0 self-center items-center justify-center rounded border border-primary/30 bg-primary/10 sm:size-10 sm:self-start">
|
|
44
|
+
<HugeiconsIcon v-if="currentDialog.options.icon" :icon="currentDialog.options.icon" :stroke-width="1.8" class="size-6 animate-uv-pop text-primary [animation-delay:140ms]" />
|
|
45
|
+
<HugeiconsIcon v-else :icon="InformationCircleIcon" :stroke-width="1.8" class="size-6 animate-uv-pop text-primary [animation-delay:140ms]" />
|
|
46
|
+
</div>
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
<!-- Dialog header -->
|
|
49
|
+
<AlertDialogHeader class="sm:pt-0">
|
|
50
|
+
<AlertDialogTitle>
|
|
51
|
+
{{ currentDialog.options.title }}
|
|
52
|
+
</AlertDialogTitle>
|
|
53
|
+
<AlertDialogDescription>
|
|
54
|
+
{{ currentDialog.options.message }}
|
|
55
|
+
</AlertDialogDescription>
|
|
56
|
+
</AlertDialogHeader>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
<!-- Dialog actions -->
|
|
61
|
+
<AlertDialogFooter>
|
|
62
|
+
<!-- Cancel button -->
|
|
63
|
+
<Button :variant="currentDialog.options.cancelButtonType" :disabled="confirmDialogState.busy && pendingAction !== 'cancel'" :loading="pendingAction === 'cancel'" @click="runAction('cancel')">
|
|
64
|
+
<HugeiconsIcon v-if="currentDialog.options.cancelButtonIcon" :icon="currentDialog.options.cancelButtonIcon" class="size-4" />
|
|
65
|
+
{{ currentDialog.options.cancelText }}
|
|
66
|
+
</Button>
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
<!-- Confirm button -->
|
|
69
|
+
<Button :variant="currentDialog.options.confirmButtonType" :disabled="confirmDialogState.busy && pendingAction !== 'confirm'" :loading="pendingAction === 'confirm'" @click="runAction('confirm')">
|
|
70
|
+
<HugeiconsIcon v-if="currentDialog.options.confirmButtonIcon" :icon="currentDialog.options.confirmButtonIcon" class="size-4" />
|
|
71
|
+
{{ currentDialog.options.confirmText }}
|
|
72
|
+
</Button>
|
|
73
|
+
</AlertDialogFooter>
|
|
74
|
+
</AlertDialogContent>
|
|
75
|
+
</AlertDialog>
|
|
76
76
|
</template>
|