@brumaombra/ui-vintage 0.7.8 → 0.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +308 -48
- package/module.mjs +1 -1
- package/package.json +2 -1
- package/src/components/background-grid/BackgroundGrid.vue +11 -2
- package/src/components/background-grid/index.ts +2 -2
- package/src/components/blog/AllPostsSection.vue +25 -9
- package/src/components/blog/BlogContentRenderer.vue +133 -0
- package/src/components/blog/BlogFAQSection.vue +8 -3
- package/src/components/blog/BlogHeaderSection.vue +14 -11
- package/src/components/blog/BlogInfoSection.vue +13 -11
- package/src/components/blog/BlogProgressBar.vue +77 -0
- package/src/components/blog/BlogSectionTitle.vue +5 -5
- package/src/components/blog/CategoriesList.vue +11 -3
- package/src/components/blog/CategoriesSection.vue +11 -3
- package/src/components/blog/CategoryCard.vue +10 -8
- package/src/components/blog/HeaderCarousel.vue +24 -15
- package/src/components/blog/PostCard.vue +16 -11
- package/src/components/blog/PostsList.vue +12 -3
- package/src/components/blog/SocialShareSidebar.vue +43 -41
- package/src/components/blog/TableOfContents.vue +29 -13
- package/src/components/blog/index.ts +1 -0
- package/src/components/busy-indicator/BusyIndicator.vue +2 -2
- package/src/components/busy-indicator/busy-indicator-state.ts +11 -12
- package/src/components/busy-indicator/index.ts +3 -3
- package/src/components/card-grid/CardGrid.vue +25 -11
- package/src/components/chip/Chip.vue +15 -15
- package/src/components/chip/index.ts +2 -2
- package/src/components/confirm-dialog/ConfirmDialog.vue +9 -9
- package/src/components/confirm-dialog/confirm-dialog-state.ts +15 -14
- package/src/components/confirm-dialog/index.ts +3 -12
- package/src/components/content/BlogList.vue +11 -8
- package/src/components/content/BlogTable.vue +18 -14
- package/src/components/content/ProseHr.vue +10 -7
- package/src/components/content/Terminal.vue +70 -0
- package/src/components/content/index.ts +2 -1
- package/src/components/dashboard-shell/DashboardShell.vue +43 -64
- package/src/components/dashboard-shell/index.ts +2 -2
- package/src/components/data-list/DataList.vue +11 -13
- package/src/components/data-list/DataListItem.vue +9 -11
- package/src/components/data-list/DataListLabel.vue +9 -11
- package/src/components/data-list/DataListText.vue +9 -11
- package/src/components/data-list/DataListValue.vue +9 -11
- package/src/components/data-list/index.ts +5 -5
- package/src/components/empty-state-card/EmptyStateCard.vue +21 -11
- package/src/components/error-page/ErrorPage.vue +24 -27
- package/src/components/error-page/index.ts +2 -2
- package/src/components/info-card/InfoCard.vue +17 -11
- package/src/components/landing/index.ts +6 -6
- package/src/components/landing/landing-content/LandingContent.vue +5 -7
- package/src/components/landing/landing-content/index.ts +2 -2
- package/src/components/landing/landing-footer/LandingFooter.vue +26 -29
- package/src/components/landing/landing-footer/index.ts +3 -3
- package/src/components/landing/landing-navbar/LandingNavbar.vue +51 -19
- package/src/components/landing/landing-navbar/index.ts +2 -2
- package/src/components/landing/landing-shell/LandingShell.vue +12 -15
- package/src/components/landing/landing-shell/index.ts +2 -2
- package/src/components/language-flag/LanguageFlag.vue +6 -5
- package/src/components/language-flag/index.ts +1 -0
- package/src/components/language-selector/LanguageSelector.vue +20 -21
- package/src/components/load-more-button/LoadMoreButton.vue +18 -14
- package/src/components/loading-state-card/LoadingStateCard.vue +13 -9
- package/src/components/message-dialog/MessageDialog.vue +19 -19
- package/src/components/message-dialog/index.ts +3 -11
- package/src/components/message-dialog/message-dialog-state.ts +12 -11
- package/src/components/message-toast/MessageToast.vue +16 -16
- package/src/components/message-toast/index.ts +2 -9
- package/src/components/message-toast/message-toast-state.ts +9 -9
- package/src/components/page-header/PageHeader.vue +8 -5
- package/src/components/progress-component/ProgressComponent.vue +13 -10
- package/src/components/single-value-card/SingleValueCard.vue +22 -19
- package/src/components/slider-form-component/SliderFormComponent.vue +11 -20
- package/src/components/slider-form-component/index.ts +2 -2
- package/src/components/switch-form-component/SwitchFormComponent.vue +7 -9
- package/src/components/switch-form-component/index.ts +2 -2
- package/src/components/text-link/TextLink.vue +11 -7
- package/src/components/ui/accordion/Accordion.vue +10 -13
- package/src/components/ui/accordion/index.ts +1 -1
- package/src/components/ui/alert/Alert.vue +11 -10
- package/src/components/ui/alert/AlertDescription.vue +9 -8
- package/src/components/ui/alert/AlertTitle.vue +9 -8
- package/src/components/ui/alert/index.ts +10 -10
- package/src/components/ui/alert-dialog/AlertDialog.vue +13 -9
- package/src/components/ui/alert-dialog/AlertDialogAction.vue +14 -12
- package/src/components/ui/alert-dialog/AlertDialogCancel.vue +14 -16
- package/src/components/ui/alert-dialog/AlertDialogContent.vue +24 -27
- package/src/components/ui/alert-dialog/AlertDialogDescription.vue +13 -13
- package/src/components/ui/alert-dialog/AlertDialogFooter.vue +9 -12
- package/src/components/ui/alert-dialog/AlertDialogHeader.vue +9 -8
- package/src/components/ui/alert-dialog/AlertDialogTitle.vue +13 -11
- package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +8 -7
- package/src/components/ui/alert-dialog/index.ts +9 -9
- package/src/components/ui/badge/Badge.vue +11 -12
- package/src/components/ui/badge/index.ts +1 -1
- package/src/components/ui/breadcrumb/Breadcrumb.vue +9 -12
- package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +15 -19
- package/src/components/ui/breadcrumb/BreadcrumbItem.vue +10 -12
- package/src/components/ui/breadcrumb/BreadcrumbLink.vue +13 -17
- package/src/components/ui/breadcrumb/BreadcrumbList.vue +10 -12
- package/src/components/ui/breadcrumb/BreadcrumbPage.vue +10 -15
- package/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +14 -18
- package/src/components/ui/breadcrumb/index.ts +7 -7
- package/src/components/ui/busy/Busy.vue +36 -29
- package/src/components/ui/busy/index.ts +1 -1
- package/src/components/ui/button/Button.vue +18 -19
- package/src/components/ui/button/index.ts +54 -35
- package/src/components/ui/calendar/Calendar.vue +167 -121
- package/src/components/ui/calendar/CalendarCell.vue +18 -17
- package/src/components/ui/calendar/CalendarCellTrigger.vue +31 -33
- package/src/components/ui/calendar/CalendarGrid.vue +14 -17
- package/src/components/ui/calendar/CalendarGridBody.vue +9 -11
- package/src/components/ui/calendar/CalendarGridHead.vue +10 -12
- package/src/components/ui/calendar/CalendarGridRow.vue +14 -16
- package/src/components/ui/calendar/CalendarHeadCell.vue +18 -17
- package/src/components/ui/calendar/CalendarHeader.vue +18 -17
- package/src/components/ui/calendar/CalendarHeading.vue +18 -22
- package/src/components/ui/calendar/CalendarNextButton.vue +29 -26
- package/src/components/ui/calendar/CalendarPrevButton.vue +29 -26
- package/src/components/ui/calendar/index.ts +17 -13
- package/src/components/ui/card/Card.vue +21 -13
- package/src/components/ui/card/CardAction.vue +12 -7
- package/src/components/ui/card/CardContent.vue +8 -7
- package/src/components/ui/card/CardDescription.vue +16 -7
- package/src/components/ui/card/CardFooter.vue +8 -7
- package/src/components/ui/card/CardHeader.vue +12 -7
- package/src/components/ui/card/CardText.vue +12 -7
- package/src/components/ui/card/CardTitle.vue +9 -7
- package/src/components/ui/card/index.ts +8 -8
- package/src/components/ui/command/Command.vue +71 -61
- package/src/components/ui/command/CommandDialog.vue +33 -23
- package/src/components/ui/command/CommandEmpty.vue +19 -20
- package/src/components/ui/command/CommandGroup.vue +32 -35
- package/src/components/ui/command/CommandInput.vue +25 -21
- package/src/components/ui/command/CommandItem.vue +62 -59
- package/src/components/ui/command/CommandList.vue +21 -18
- package/src/components/ui/command/CommandSeparator.vue +13 -11
- package/src/components/ui/command/CommandShortcut.vue +13 -8
- package/src/components/ui/command/index.ts +24 -20
- package/src/components/ui/date-picker/DatePicker.vue +46 -37
- package/src/components/ui/date-picker/index.ts +2 -2
- package/src/components/ui/date-time-picker/DateTimePicker.vue +99 -95
- package/src/components/ui/date-time-picker/index.ts +2 -2
- package/src/components/ui/dialog/Dialog.vue +12 -9
- package/src/components/ui/dialog/DialogClose.vue +8 -10
- package/src/components/ui/dialog/DialogContent.vue +36 -42
- package/src/components/ui/dialog/DialogDescription.vue +16 -11
- package/src/components/ui/dialog/DialogFooter.vue +13 -12
- package/src/components/ui/dialog/DialogHeader.vue +9 -8
- package/src/components/ui/dialog/DialogOverlay.vue +16 -11
- package/src/components/ui/dialog/DialogScrollContent.vue +47 -45
- package/src/components/ui/dialog/DialogTitle.vue +13 -12
- package/src/components/ui/dialog/DialogTrigger.vue +8 -7
- package/src/components/ui/dialog/index.ts +10 -10
- package/src/components/ui/field/Field.vue +12 -14
- package/src/components/ui/field/FieldContent.vue +13 -11
- package/src/components/ui/field/FieldDescription.vue +15 -13
- package/src/components/ui/field/FieldError.vue +43 -40
- package/src/components/ui/field/FieldGroup.vue +13 -11
- package/src/components/ui/field/FieldLabel.vue +16 -14
- package/src/components/ui/field/FieldLegend.vue +16 -14
- package/src/components/ui/field/FieldSeparator.vue +17 -15
- package/src/components/ui/field/FieldSet.vue +14 -12
- package/src/components/ui/field/FieldTitle.vue +13 -11
- package/src/components/ui/field/index.ts +36 -36
- package/src/components/ui/input/Input.vue +23 -20
- package/src/components/ui/input/index.ts +1 -1
- package/src/components/ui/label/Label.vue +16 -15
- package/src/components/ui/label/index.ts +1 -1
- package/src/components/ui/native-select/NativeSelect.vue +31 -41
- package/src/components/ui/native-select/NativeSelectOptGroup.vue +8 -7
- package/src/components/ui/native-select/NativeSelectOption.vue +8 -7
- package/src/components/ui/native-select/index.ts +3 -3
- package/src/components/ui/popover/Popover.vue +12 -9
- package/src/components/ui/popover/PopoverAnchor.vue +8 -7
- package/src/components/ui/popover/PopoverContent.vue +27 -31
- package/src/components/ui/popover/PopoverTrigger.vue +8 -7
- package/src/components/ui/popover/index.ts +4 -4
- package/src/components/ui/progress/Progress.vue +18 -32
- package/src/components/ui/progress/index.ts +1 -1
- package/src/components/ui/scroll-area/ScrollArea.vue +23 -26
- package/src/components/ui/scroll-area/ScrollBar.vue +22 -26
- package/src/components/ui/scroll-area/index.ts +2 -2
- package/src/components/ui/select/Select.vue +12 -9
- package/src/components/ui/select/SelectContent.vue +39 -40
- package/src/components/ui/select/SelectGroup.vue +8 -7
- package/src/components/ui/select/SelectItem.vue +36 -41
- package/src/components/ui/select/SelectItemContent.vue +22 -15
- package/src/components/ui/select/SelectItemText.vue +8 -7
- package/src/components/ui/select/SelectLabel.vue +10 -9
- package/src/components/ui/select/SelectScrollDownButton.vue +21 -17
- package/src/components/ui/select/SelectScrollUpButton.vue +21 -17
- package/src/components/ui/select/SelectSeparator.vue +11 -9
- package/src/components/ui/select/SelectTrigger.vue +27 -25
- package/src/components/ui/select/SelectValue.vue +8 -7
- package/src/components/ui/select/SelectValueContent.vue +30 -18
- package/src/components/ui/select/index.ts +13 -13
- package/src/components/ui/separator/Separator.vue +17 -18
- package/src/components/ui/separator/index.ts +1 -1
- package/src/components/ui/sheet/Sheet.vue +12 -9
- package/src/components/ui/sheet/SheetClose.vue +8 -7
- package/src/components/ui/sheet/SheetContent.vue +36 -37
- package/src/components/ui/sheet/SheetDescription.vue +12 -11
- package/src/components/ui/sheet/SheetFooter.vue +8 -7
- package/src/components/ui/sheet/SheetHeader.vue +8 -7
- package/src/components/ui/sheet/SheetOverlay.vue +16 -11
- package/src/components/ui/sheet/SheetTitle.vue +12 -11
- package/src/components/ui/sheet/SheetTrigger.vue +8 -7
- package/src/components/ui/sheet/index.ts +8 -8
- package/src/components/ui/sidebar/Sidebar.vue +68 -61
- package/src/components/ui/sidebar/SidebarContent.vue +13 -8
- package/src/components/ui/sidebar/SidebarFooter.vue +13 -8
- package/src/components/ui/sidebar/SidebarGroup.vue +13 -8
- package/src/components/ui/sidebar/SidebarGroupAction.vue +16 -16
- package/src/components/ui/sidebar/SidebarGroupContent.vue +9 -8
- package/src/components/ui/sidebar/SidebarGroupLabel.vue +15 -14
- package/src/components/ui/sidebar/SidebarHeader.vue +13 -8
- package/src/components/ui/sidebar/SidebarInput.vue +14 -12
- package/src/components/ui/sidebar/SidebarInset.vue +14 -12
- package/src/components/ui/sidebar/SidebarMenu.vue +9 -8
- package/src/components/ui/sidebar/SidebarMenuAction.vue +25 -23
- package/src/components/ui/sidebar/SidebarMenuBadge.vue +19 -17
- package/src/components/ui/sidebar/SidebarMenuButton.vue +33 -32
- package/src/components/ui/sidebar/SidebarMenuButtonChild.vue +19 -18
- package/src/components/ui/sidebar/SidebarMenuItem.vue +9 -8
- package/src/components/ui/sidebar/SidebarMenuSkeleton.vue +17 -12
- package/src/components/ui/sidebar/SidebarMenuSub.vue +14 -12
- package/src/components/ui/sidebar/SidebarMenuSubButton.vue +24 -21
- package/src/components/ui/sidebar/SidebarMenuSubItem.vue +9 -8
- package/src/components/ui/sidebar/SidebarProvider.vue +63 -53
- package/src/components/ui/sidebar/SidebarRail.vue +20 -18
- package/src/components/ui/sidebar/SidebarSeparator.vue +10 -9
- package/src/components/ui/sidebar/SidebarTrigger.vue +15 -14
- package/src/components/ui/sidebar/index.ts +62 -58
- package/src/components/ui/sidebar/utils.ts +16 -16
- package/src/components/ui/skeleton/Skeleton.vue +12 -9
- package/src/components/ui/skeleton/index.ts +1 -1
- package/src/components/ui/slider/Slider.vue +24 -19
- package/src/components/ui/slider/index.ts +1 -1
- package/src/components/ui/switch/Switch.vue +26 -23
- package/src/components/ui/switch/index.ts +1 -1
- package/src/components/ui/table/Table.vue +11 -10
- package/src/components/ui/table/TableBody.vue +9 -11
- package/src/components/ui/table/TableCaption.vue +9 -11
- package/src/components/ui/table/TableCell.vue +13 -16
- package/src/components/ui/table/TableEmpty.vue +22 -25
- package/src/components/ui/table/TableFooter.vue +13 -11
- package/src/components/ui/table/TableHead.vue +13 -11
- package/src/components/ui/table/TableHeader.vue +9 -11
- package/src/components/ui/table/TableRow.vue +13 -11
- package/src/components/ui/table/index.ts +9 -9
- package/src/components/ui/tabs/Tabs.vue +18 -18
- package/src/components/ui/tabs/TabsContent.vue +14 -15
- package/src/components/ui/tabs/TabsList.vue +18 -18
- package/src/components/ui/tabs/TabsTrigger.vue +19 -20
- package/src/components/ui/tabs/index.ts +4 -4
- package/src/components/ui/textarea/Textarea.vue +23 -20
- package/src/components/ui/textarea/index.ts +1 -1
- package/src/components/ui/time-picker/TimePicker.vue +33 -38
- package/src/components/ui/time-picker/index.ts +2 -2
- package/src/components/ui/tooltip/Tooltip.vue +12 -9
- package/src/components/ui/tooltip/TooltipContent.vue +28 -20
- package/src/components/ui/tooltip/TooltipProvider.vue +9 -8
- package/src/components/ui/tooltip/TooltipTrigger.vue +8 -7
- package/src/components/ui/tooltip/index.ts +4 -4
- package/src/i18n/de.json +5 -0
- package/src/i18n/en.json +5 -0
- package/src/i18n/es.json +5 -0
- package/src/i18n/fr.json +5 -0
- package/src/i18n/it.json +5 -0
- package/src/i18n/ja.json +5 -0
- package/src/i18n/pt.json +5 -0
- package/src/i18n/ru.json +5 -0
- package/src/i18n/zh.json +5 -0
- package/src/lib/common-types.ts +2 -0
- package/src/lib/i18n.ts +0 -5
- package/src/runtime/{ui-vintage-i18n-plugin.js → ui-vintage-i18n-plugin.ts} +30 -8
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { NuxtImg } from
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { cn } from "../../../lib/utils";
|
|
2
|
+
import { NuxtImg } from '#components';
|
|
3
|
+
import { FavouriteIcon } from '@hugeicons/core-free-icons';
|
|
4
|
+
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
5
|
+
import { computed, type Component, type HTMLAttributes } from 'vue';
|
|
6
|
+
import { useI18n } from 'vue-i18n';
|
|
7
|
+
import { cn } from '../../../lib/utils';
|
|
9
8
|
|
|
10
9
|
export interface LandingFooterLink {
|
|
11
10
|
id: string;
|
|
@@ -21,7 +20,8 @@ export interface LandingFooterSection {
|
|
|
21
20
|
links: LandingFooterLink[];
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
// Props
|
|
24
|
+
const props = withDefaults(defineProps<{
|
|
25
25
|
appName: string;
|
|
26
26
|
appLogo?: string;
|
|
27
27
|
appLinkTo?: string;
|
|
@@ -32,21 +32,18 @@ interface LandingFooterProps {
|
|
|
32
32
|
authorLink?: string;
|
|
33
33
|
year?: number;
|
|
34
34
|
showBottomBar?: boolean;
|
|
35
|
-
class?: HTMLAttributes[
|
|
36
|
-
containerClass?: HTMLAttributes[
|
|
37
|
-
brandClass?: HTMLAttributes[
|
|
38
|
-
sectionsClass?: HTMLAttributes[
|
|
39
|
-
bottomBarClass?: HTMLAttributes[
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const props = withDefaults(defineProps<LandingFooterProps>(), {
|
|
44
|
-
appLinkTo: "/",
|
|
45
|
-
appDescription: "",
|
|
35
|
+
class?: HTMLAttributes['class'];
|
|
36
|
+
containerClass?: HTMLAttributes['class'];
|
|
37
|
+
brandClass?: HTMLAttributes['class'];
|
|
38
|
+
sectionsClass?: HTMLAttributes['class'];
|
|
39
|
+
bottomBarClass?: HTMLAttributes['class'];
|
|
40
|
+
}>(), {
|
|
41
|
+
appLinkTo: '/',
|
|
42
|
+
appDescription: '',
|
|
46
43
|
sections: () => [],
|
|
47
|
-
linkComponent:
|
|
48
|
-
authorName:
|
|
49
|
-
authorLink:
|
|
44
|
+
linkComponent: 'a',
|
|
45
|
+
authorName: '',
|
|
46
|
+
authorLink: '',
|
|
50
47
|
year: () => new Date().getFullYear(),
|
|
51
48
|
showBottomBar: true
|
|
52
49
|
});
|
|
@@ -56,19 +53,19 @@ const hasSingleSection = computed(() => props.sections.length === 1);
|
|
|
56
53
|
|
|
57
54
|
// Get link props based on the type of link component and whether the link should open in a new tab
|
|
58
55
|
const getLinkProps = (link: LandingFooterLink) => {
|
|
59
|
-
const sharedProps = link.newTab ? { target:
|
|
56
|
+
const sharedProps = link.newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {};
|
|
60
57
|
|
|
61
58
|
// If the link component is an anchor, use href. Otherwise, use to for router links.
|
|
62
|
-
if (props.linkComponent ===
|
|
59
|
+
if (props.linkComponent === 'a') {
|
|
63
60
|
return {
|
|
64
|
-
href: link.href ??
|
|
61
|
+
href: link.href ?? '#',
|
|
65
62
|
...sharedProps
|
|
66
63
|
};
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
// For non-anchor link components, assume they use a "to" prop (like Vue Router's <RouterLink>).
|
|
70
67
|
return {
|
|
71
|
-
to: link.to ?? link.href ??
|
|
68
|
+
to: link.to ?? link.href ?? '/',
|
|
72
69
|
...sharedProps
|
|
73
70
|
};
|
|
74
71
|
};
|
|
@@ -135,14 +132,14 @@ const getLinkProps = (link: LandingFooterLink) => {
|
|
|
135
132
|
<div v-if="props.showBottomBar" :class="cn('mt-12 flex flex-col items-center justify-between gap-4 border-t border-border pt-8 text-xs md:text-sm text-muted-foreground md:flex-row', props.bottomBarClass)">
|
|
136
133
|
<!-- Copyright -->
|
|
137
134
|
<div>
|
|
138
|
-
© {{ props.year }} {{ props.appName }}. {{ t(
|
|
135
|
+
© {{ props.year }} {{ props.appName }}. {{ t('uiVintage.footer.allRightsReserved') }}
|
|
139
136
|
</div>
|
|
140
137
|
|
|
141
138
|
<!-- Author -->
|
|
142
139
|
<div v-if="props.authorName && props.authorLink" class="flex flex-wrap items-center justify-center gap-1.5 md:justify-end">
|
|
143
|
-
<span>{{ t(
|
|
140
|
+
<span>{{ t('uiVintage.footer.madeWith') }}</span>
|
|
144
141
|
<HugeiconsIcon :icon="FavouriteIcon" class="size-4 shrink-0 text-red-700 dark:text-red-400" />
|
|
145
|
-
<span>{{ t(
|
|
142
|
+
<span>{{ t('uiVintage.footer.by') }}</span>
|
|
146
143
|
<a :href="props.authorLink" target="_blank" rel="noopener noreferrer" class="font-semibold text-foreground hover:underline">
|
|
147
144
|
{{ props.authorName }}
|
|
148
145
|
</a>
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { default } from
|
|
2
|
-
export { default as LandingFooter } from
|
|
3
|
-
export type { LandingFooterLink, LandingFooterSection } from
|
|
1
|
+
export { default } from './LandingFooter.vue';
|
|
2
|
+
export { default as LandingFooter } from './LandingFooter.vue';
|
|
3
|
+
export type { LandingFooterLink, LandingFooterSection } from './LandingFooter.vue';
|
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { NuxtImg } from
|
|
3
|
-
import type { HTMLAttributes } from
|
|
4
|
-
import
|
|
2
|
+
import { NuxtImg } from '#components';
|
|
3
|
+
import type { HTMLAttributes } from 'vue';
|
|
4
|
+
import BlogProgressBar from '../../blog/BlogProgressBar.vue';
|
|
5
|
+
import { cn } from '../../../lib/utils';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
// Props
|
|
8
|
+
const props = withDefaults(defineProps<{
|
|
7
9
|
appName?: string;
|
|
8
10
|
appLogo?: string;
|
|
9
11
|
appLinkTo?: string;
|
|
10
|
-
logoClass?: HTMLAttributes[
|
|
11
|
-
class?: HTMLAttributes[
|
|
12
|
-
containerClass?: HTMLAttributes[
|
|
13
|
-
leftClass?: HTMLAttributes[
|
|
14
|
-
rightClass?: HTMLAttributes[
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
appLinkTo: "/"
|
|
12
|
+
logoClass?: HTMLAttributes['class'];
|
|
13
|
+
class?: HTMLAttributes['class'];
|
|
14
|
+
containerClass?: HTMLAttributes['class'];
|
|
15
|
+
leftClass?: HTMLAttributes['class'];
|
|
16
|
+
rightClass?: HTMLAttributes['class'];
|
|
17
|
+
showProgress?: boolean;
|
|
18
|
+
}>(), {
|
|
19
|
+
appName: '',
|
|
20
|
+
appLogo: '',
|
|
21
|
+
appLinkTo: '/',
|
|
22
|
+
showProgress: false
|
|
22
23
|
});
|
|
23
24
|
</script>
|
|
24
25
|
|
|
25
26
|
<template>
|
|
26
|
-
<header :class="cn('z-30 flex h-20 w-full flex-wrap sm:flex-nowrap sm:justify-start', props.class)">
|
|
27
|
+
<header :class="cn('sticky top-0 z-30 flex h-20 w-full flex-wrap border-b border-transparent bg-transparent text-card-foreground landing-navbar-sticky sm:flex-nowrap sm:justify-start', props.class)">
|
|
27
28
|
<nav :class="cn('mx-auto flex max-w-6xl basis-full items-center justify-between px-3 sm:px-6 lg:px-8', props.containerClass)">
|
|
28
29
|
<!-- Left-aligned content -->
|
|
29
30
|
<div :class="cn('flex items-center', props.leftClass)">
|
|
@@ -33,7 +34,7 @@ const props = withDefaults(defineProps<LandingNavbarProps>(), {
|
|
|
33
34
|
<NuxtImg v-if="props.appLogo" :src="props.appLogo" :alt="`${props.appName} logo`" width="44" height="44" :sizes="{ 320: '44px', 640: '36px' }" loading="eager" fetchpriority="high" :class="cn('size-11 sm:size-9 shrink-0 object-contain', props.logoClass)" />
|
|
34
35
|
|
|
35
36
|
<!-- App name -->
|
|
36
|
-
<span v-if="props.appName" class="hidden sm
|
|
37
|
+
<span v-if="props.appName" class="hidden sm:inline! text-xl font-bold tracking-tight text-foreground">
|
|
37
38
|
{{ props.appName }}
|
|
38
39
|
</span>
|
|
39
40
|
</a>
|
|
@@ -45,5 +46,36 @@ const props = withDefaults(defineProps<LandingNavbarProps>(), {
|
|
|
45
46
|
<slot name="right" />
|
|
46
47
|
</div>
|
|
47
48
|
</nav>
|
|
49
|
+
|
|
50
|
+
<div v-if="props.showProgress" class="absolute inset-x-0 bottom-0 translate-y-full">
|
|
51
|
+
<BlogProgressBar aria-label="Blog reading progress" />
|
|
52
|
+
</div>
|
|
48
53
|
</header>
|
|
49
|
-
</template>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<style scoped>
|
|
57
|
+
.landing-navbar-sticky {
|
|
58
|
+
animation: landing-navbar-scroll linear both;
|
|
59
|
+
animation-range: 0 160px;
|
|
60
|
+
animation-timeline: scroll(root);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@keyframes landing-navbar-scroll {
|
|
64
|
+
from {
|
|
65
|
+
background-color: transparent;
|
|
66
|
+
border-bottom-color: transparent;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
to {
|
|
70
|
+
background-color: var(--card);
|
|
71
|
+
border-bottom-color: var(--border);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@supports not (animation-timeline: scroll()) {
|
|
76
|
+
.landing-navbar-sticky {
|
|
77
|
+
border-bottom-color: var(--border);
|
|
78
|
+
background-color: var(--card);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { default } from
|
|
2
|
-
export { default as LandingNavbar } from
|
|
1
|
+
export { default } from './LandingNavbar.vue';
|
|
2
|
+
export { default as LandingNavbar } from './LandingNavbar.vue';
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { cn } from "../../../lib/utils";
|
|
6
|
-
|
|
7
|
-
interface LandingShellProps {
|
|
8
|
-
showBackground?: boolean;
|
|
9
|
-
rootClass?: HTMLAttributes["class"];
|
|
10
|
-
navbarClass?: HTMLAttributes["class"];
|
|
11
|
-
mainClass?: HTMLAttributes["class"];
|
|
12
|
-
footerClass?: HTMLAttributes["class"];
|
|
13
|
-
}
|
|
2
|
+
import { computed, useSlots, type HTMLAttributes } from 'vue';
|
|
3
|
+
import BackgroundGrid from '../../background-grid/BackgroundGrid.vue';
|
|
4
|
+
import { cn } from '../../../lib/utils';
|
|
14
5
|
|
|
15
6
|
// Props
|
|
16
|
-
const props = withDefaults(defineProps<
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
showBackground?: boolean;
|
|
9
|
+
rootClass?: HTMLAttributes['class'];
|
|
10
|
+
navbarClass?: HTMLAttributes['class'];
|
|
11
|
+
mainClass?: HTMLAttributes['class'];
|
|
12
|
+
footerClass?: HTMLAttributes['class'];
|
|
13
|
+
}>(), {
|
|
17
14
|
showBackground: true
|
|
18
15
|
});
|
|
19
16
|
|
|
@@ -33,9 +30,9 @@ const hasStructuredSlots = computed(() => {
|
|
|
33
30
|
<!-- If structured slots are provided, render them -->
|
|
34
31
|
<template v-if="hasStructuredSlots">
|
|
35
32
|
<!-- Navbar -->
|
|
36
|
-
<
|
|
33
|
+
<div :class="cn('contents', props.navbarClass)">
|
|
37
34
|
<slot name="navbar" />
|
|
38
|
-
</
|
|
35
|
+
</div>
|
|
39
36
|
|
|
40
37
|
<!-- Main content -->
|
|
41
38
|
<main :class="cn('relative z-10 flex-1', props.mainClass)">
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { default } from
|
|
2
|
-
export { default as LandingShell } from
|
|
1
|
+
export { default } from './LandingShell.vue';
|
|
2
|
+
export { default as LandingShell } from './LandingShell.vue';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type
|
|
3
|
-
import { computed, defineAsyncComponent } from 'vue';
|
|
2
|
+
import { computed, defineAsyncComponent, type Component } from 'vue';
|
|
4
3
|
|
|
5
4
|
// Single source of truth for supported flag component loaders
|
|
6
5
|
const supportedFlagLoaders = {
|
|
@@ -15,7 +14,7 @@ const supportedFlagLoaders = {
|
|
|
15
14
|
ru: () => import('./flags/RussianFlag.vue')
|
|
16
15
|
} as const;
|
|
17
16
|
|
|
18
|
-
type SupportedLanguageCode = keyof typeof supportedFlagLoaders;
|
|
17
|
+
export type SupportedLanguageCode = keyof typeof supportedFlagLoaders;
|
|
19
18
|
const asyncFlagComponentCache = new Map<SupportedLanguageCode, Component>();
|
|
20
19
|
|
|
21
20
|
// Type guard to ensure a code is one of the supported flag codes
|
|
@@ -38,8 +37,10 @@ const getAsyncFlagComponent = (code: SupportedLanguageCode) => {
|
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
// Props
|
|
41
|
-
const props = defineProps
|
|
42
|
-
code
|
|
40
|
+
const props = withDefaults(defineProps<{
|
|
41
|
+
code?: SupportedLanguageCode;
|
|
42
|
+
}>(), {
|
|
43
|
+
code: 'en'
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
// Get the appropriate flag component based on the code prop
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default } from './LanguageFlag.vue';
|
|
2
2
|
export { default as LanguageFlag } from './LanguageFlag.vue';
|
|
3
|
+
export type { SupportedLanguageCode } from './LanguageFlag.vue';
|
|
3
4
|
export { default as EnglishFlag } from './flags/EnglishFlag.vue';
|
|
4
5
|
export { default as FrenchFlag } from './flags/FrenchFlag.vue';
|
|
5
6
|
export { default as GermanFlag } from './flags/GermanFlag.vue';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
3
|
-
import { computed, defineAsyncComponent, ref } from 'vue';
|
|
2
|
+
import { computed, defineAsyncComponent, ref, type Component } from 'vue';
|
|
4
3
|
import { useI18n } from 'vue-i18n';
|
|
5
4
|
import { Tick02Icon } from '@hugeicons/core-free-icons';
|
|
6
5
|
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
@@ -10,6 +9,24 @@ import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
|
|
10
9
|
|
|
11
10
|
export type LanguageSelectorCode = string;
|
|
12
11
|
|
|
12
|
+
// Props
|
|
13
|
+
const props = withDefaults(defineProps<{
|
|
14
|
+
modelValue?: string;
|
|
15
|
+
languages?: LanguageSelectorCode[];
|
|
16
|
+
}>(), {
|
|
17
|
+
modelValue: '',
|
|
18
|
+
languages: () => ['en', 'it']
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Emits
|
|
22
|
+
const emits = defineEmits<{
|
|
23
|
+
'update:modelValue': [value: string];
|
|
24
|
+
select: [value: string];
|
|
25
|
+
}>();
|
|
26
|
+
|
|
27
|
+
const { locale, t } = useI18n();
|
|
28
|
+
const isOpen = ref(false);
|
|
29
|
+
|
|
13
30
|
// Single source of truth for supported language codes, labels, and flag loaders
|
|
14
31
|
const supportedLanguages = [
|
|
15
32
|
{ code: 'en', label: 'English', loadFlag: () => import('../language-flag/flags/EnglishFlag.vue') },
|
|
@@ -51,24 +68,6 @@ const getAsyncFlagComponent = (code: SupportedLanguageCode) => {
|
|
|
51
68
|
return asyncComponent;
|
|
52
69
|
};
|
|
53
70
|
|
|
54
|
-
// Props
|
|
55
|
-
const props = defineProps({
|
|
56
|
-
modelValue: { type: String, default: '' },
|
|
57
|
-
languages: {
|
|
58
|
-
type: Array as PropType<LanguageSelectorCode[]>,
|
|
59
|
-
default: () => ['en', 'it']
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Emits
|
|
64
|
-
const emits = defineEmits<{
|
|
65
|
-
'update:modelValue': [value: string];
|
|
66
|
-
select: [value: string];
|
|
67
|
-
}>();
|
|
68
|
-
|
|
69
|
-
const { locale, t } = useI18n();
|
|
70
|
-
const isOpen = ref(false);
|
|
71
|
-
|
|
72
71
|
// Build localized language labels from the provided language codes
|
|
73
72
|
const languageDisplayNames = computed(() => {
|
|
74
73
|
return typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames([locale.value], { type: 'language' }) : null;
|
|
@@ -137,7 +136,7 @@ const handleSelectLanguage = (language: string) => {
|
|
|
137
136
|
</PopoverTrigger>
|
|
138
137
|
|
|
139
138
|
<!-- Popover content with language options -->
|
|
140
|
-
<PopoverContent side="bottom" align="end" :side-offset="8" class="w-44
|
|
139
|
+
<PopoverContent side="bottom" align="end" :side-offset="8" class="w-44 p-0!">
|
|
141
140
|
<Command :model-value="props.modelValue">
|
|
142
141
|
<CommandList>
|
|
143
142
|
<CommandGroup :heading="t('uiVintage.language.title')">
|
|
@@ -5,19 +5,27 @@ import { ArrowDown01Icon, RefreshIcon } from '@hugeicons/core-free-icons';
|
|
|
5
5
|
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
6
6
|
import { Button } from '../ui/button';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
// Props
|
|
9
|
+
const props = withDefaults(defineProps<{
|
|
10
|
+
busy?: boolean;
|
|
11
|
+
text?: string;
|
|
12
|
+
loadingText?: string;
|
|
13
|
+
}>(), {
|
|
14
|
+
busy: false,
|
|
15
|
+
text: '',
|
|
16
|
+
loadingText: ''
|
|
12
17
|
});
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
// Emits
|
|
20
|
+
const emits = defineEmits<{
|
|
21
|
+
'load-more': [];
|
|
22
|
+
}>();
|
|
15
23
|
|
|
16
24
|
const { t } = useI18n();
|
|
17
|
-
|
|
18
25
|
const resolvedText = computed(() => props.text || t('uiVintage.buttons.loadMore') || 'Load more');
|
|
19
26
|
const resolvedLoadingText = computed(() => props.loadingText || t('uiVintage.buttons.loading') || 'Loading');
|
|
20
27
|
|
|
28
|
+
// Handle click event
|
|
21
29
|
const handleClick = () => {
|
|
22
30
|
emits('load-more');
|
|
23
31
|
};
|
|
@@ -25,18 +33,14 @@ const handleClick = () => {
|
|
|
25
33
|
|
|
26
34
|
<template>
|
|
27
35
|
<div class="flex justify-center">
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class="w-full md:w-auto"
|
|
31
|
-
:disabled="true">
|
|
36
|
+
<!-- Loading button -->
|
|
37
|
+
<Button v-if="props.busy" variant="secondary" class="w-full md:w-auto" :disabled="true">
|
|
32
38
|
<HugeiconsIcon :icon="RefreshIcon" class="size-4 animate-spin" />
|
|
33
39
|
{{ resolvedLoadingText }}
|
|
34
40
|
</Button>
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class="w-full md:w-auto"
|
|
39
|
-
@click="handleClick">
|
|
42
|
+
<!-- Load more button -->
|
|
43
|
+
<Button v-else variant="secondary" class="w-full md:w-auto" @click="handleClick">
|
|
40
44
|
<HugeiconsIcon :icon="ArrowDown01Icon" class="size-4" />
|
|
41
45
|
{{ resolvedText }}
|
|
42
46
|
</Button>
|
|
@@ -4,35 +4,39 @@ import { useI18n } from 'vue-i18n';
|
|
|
4
4
|
import { Loading03Icon } from '@hugeicons/core-free-icons';
|
|
5
5
|
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
6
6
|
import { Card, CardContent } from '../ui/card';
|
|
7
|
+
import type { HugeiconsIconDefinition } from '../../lib/common-types';
|
|
7
8
|
|
|
8
9
|
// Props
|
|
9
|
-
const props = defineProps
|
|
10
|
-
icon
|
|
11
|
-
title
|
|
12
|
-
description
|
|
10
|
+
const props = withDefaults(defineProps<{
|
|
11
|
+
icon?: HugeiconsIconDefinition;
|
|
12
|
+
title?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
}>(), {
|
|
15
|
+
icon: () => Loading03Icon,
|
|
16
|
+
title: '',
|
|
17
|
+
description: ''
|
|
13
18
|
});
|
|
14
19
|
|
|
15
20
|
const { t } = useI18n();
|
|
16
|
-
|
|
17
21
|
const resolvedTitle = computed(() => props.title || t('uiVintage.common.loading.title') || 'Loading...');
|
|
18
22
|
const resolvedDescription = computed(() => props.description || t('uiVintage.common.loading.description') || 'Please wait a moment while we load the content.');
|
|
19
23
|
</script>
|
|
20
24
|
|
|
21
25
|
<template>
|
|
22
26
|
<Card class="flex flex-col items-center justify-center px-4 py-8 text-center md:py-12">
|
|
23
|
-
<CardContent class="flex flex-col items-center justify-center
|
|
27
|
+
<CardContent class="flex flex-col items-center justify-center p-0! text-center">
|
|
24
28
|
<!-- Loading spinner icon -->
|
|
25
|
-
<div class="flex items-center justify-center text-4xl text-
|
|
29
|
+
<div class="flex items-center justify-center text-4xl text-(--text-secondary-light) opacity-60 dark:text-(--text-secondary-dark)">
|
|
26
30
|
<HugeiconsIcon :icon="props.icon" class="size-10 animate-spin" />
|
|
27
31
|
</div>
|
|
28
32
|
|
|
29
33
|
<!-- Title -->
|
|
30
|
-
<h3 v-if="resolvedTitle" class="text-sm font-bold text-
|
|
34
|
+
<h3 v-if="resolvedTitle" class="text-sm font-bold text-(--text-primary-light) dark:text-(--text-primary-dark) md:text-lg">
|
|
31
35
|
{{ resolvedTitle }}
|
|
32
36
|
</h3>
|
|
33
37
|
|
|
34
38
|
<!-- Description -->
|
|
35
|
-
<p v-if="resolvedDescription" class="max-w-md text-xs text-
|
|
39
|
+
<p v-if="resolvedDescription" class="max-w-md text-xs text-(--text-secondary-light) dark:text-(--text-secondary-dark) md:text-sm">
|
|
36
40
|
{{ resolvedDescription }}
|
|
37
41
|
</p>
|
|
38
42
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { HugeiconsIcon } from
|
|
3
|
-
import { computed } from
|
|
4
|
-
import { AlertCircleIcon, InformationCircleIcon, Tick02Icon } from
|
|
5
|
-
import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from
|
|
6
|
-
import { Button } from
|
|
7
|
-
import { getUiVintageRuntimeMessage } from
|
|
8
|
-
import { closeMessageDialog, messageDialogState, resolveActiveMessageDialog } from
|
|
2
|
+
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
3
|
+
import { computed } from 'vue';
|
|
4
|
+
import { AlertCircleIcon, InformationCircleIcon, Tick02Icon } from '@hugeicons/core-free-icons';
|
|
5
|
+
import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '../ui/alert-dialog';
|
|
6
|
+
import { Button } from '../ui/button';
|
|
7
|
+
import { getUiVintageRuntimeMessage } from '../../lib/i18n';
|
|
8
|
+
import { closeMessageDialog, messageDialogState, resolveActiveMessageDialog } from './message-dialog-state';
|
|
9
9
|
|
|
10
10
|
// Active dialog state
|
|
11
11
|
const currentDialog = computed(() => messageDialogState.current);
|
|
@@ -28,29 +28,29 @@ const resolvedCloseText = computed(() => {
|
|
|
28
28
|
const defaultMessageIcon = computed(() => {
|
|
29
29
|
const current = currentDialog.value;
|
|
30
30
|
if (!current) return InformationCircleIcon;
|
|
31
|
-
if (current.options.type ===
|
|
32
|
-
if (current.options.type ===
|
|
31
|
+
if (current.options.type === 'error' || current.options.type === 'warning') return AlertCircleIcon;
|
|
32
|
+
if (current.options.type === 'success') return Tick02Icon;
|
|
33
33
|
return InformationCircleIcon;
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
// Resolved container classes for the message icon
|
|
37
37
|
const messageIconClasses = computed(() => {
|
|
38
38
|
const current = currentDialog.value;
|
|
39
|
-
if (!current) return
|
|
40
|
-
if (current.options.type ===
|
|
41
|
-
if (current.options.type ===
|
|
42
|
-
if (current.options.type ===
|
|
43
|
-
return
|
|
39
|
+
if (!current) return 'border-(--border) bg-(--bg-surface-light) dark:bg-(--bg-surface-dark)';
|
|
40
|
+
if (current.options.type === 'error') return 'border-red-200 bg-red-50 dark:border-red-900/50 dark:bg-red-950/30';
|
|
41
|
+
if (current.options.type === 'warning') return 'border-amber-200 bg-amber-50 dark:border-amber-900/50 dark:bg-amber-950/30';
|
|
42
|
+
if (current.options.type === 'success') return 'border-green-200 bg-green-50 dark:border-green-900/50 dark:bg-green-950/30';
|
|
43
|
+
return 'border-(--border) bg-(--bg-surface-light) dark:bg-(--bg-surface-dark)';
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
// Resolved glyph color classes
|
|
47
47
|
const messageGlyphClasses = computed(() => {
|
|
48
48
|
const current = currentDialog.value;
|
|
49
|
-
if (!current) return
|
|
50
|
-
if (current.options.type ===
|
|
51
|
-
if (current.options.type ===
|
|
52
|
-
if (current.options.type ===
|
|
53
|
-
return
|
|
49
|
+
if (!current) return 'text-blue-600';
|
|
50
|
+
if (current.options.type === 'error') return 'text-red-600';
|
|
51
|
+
if (current.options.type === 'warning') return 'text-amber-600';
|
|
52
|
+
if (current.options.type === 'success') return 'text-green-600';
|
|
53
|
+
return 'text-blue-600';
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
// Close the dialog when the shell requests it
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
export { default as MessageDialog } from
|
|
2
|
-
export {
|
|
3
|
-
|
|
4
|
-
messageDialogState,
|
|
5
|
-
resolveActiveMessageDialog,
|
|
6
|
-
showMessageDialog
|
|
7
|
-
} from "./message-dialog-state";
|
|
8
|
-
export type {
|
|
9
|
-
DialogMessageType,
|
|
10
|
-
ShowMessageDialogOptions
|
|
11
|
-
} from "./message-dialog-state";
|
|
1
|
+
export { default as MessageDialog } from './MessageDialog.vue';
|
|
2
|
+
export { closeMessageDialog, messageDialogState, resolveActiveMessageDialog, showMessageDialog } from './message-dialog-state';
|
|
3
|
+
export type { DialogMessageType, ShowMessageDialogOptions } from './message-dialog-state';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { h, markRaw, reactive, render } from
|
|
1
|
+
import { h, markRaw, reactive, render } from 'vue';
|
|
2
|
+
import type { HugeiconsIconDefinition } from '../../lib/common-types';
|
|
2
3
|
|
|
3
|
-
export type DialogMessageType =
|
|
4
|
-
export type
|
|
4
|
+
export type DialogMessageType = 'error' | 'success' | 'info' | 'warning';
|
|
5
|
+
export type { HugeiconsIconDefinition };
|
|
5
6
|
|
|
6
7
|
export interface ShowMessageDialogOptions {
|
|
7
8
|
type?: DialogMessageType;
|
|
@@ -14,7 +15,7 @@ export interface ShowMessageDialogOptions {
|
|
|
14
15
|
|
|
15
16
|
interface MessageDialogRequest {
|
|
16
17
|
id: number;
|
|
17
|
-
options: Omit<ShowMessageDialogOptions,
|
|
18
|
+
options: Omit<ShowMessageDialogOptions, 'icon' | 'closeButtonIcon'> & {
|
|
18
19
|
icon: HugeiconsIconDefinition | null;
|
|
19
20
|
closeButtonIcon: HugeiconsIconDefinition | null;
|
|
20
21
|
};
|
|
@@ -33,7 +34,7 @@ const DIALOG_CLOSE_DURATION_MS = 300;
|
|
|
33
34
|
let closeTimer: ReturnType<typeof setTimeout> | null = null;
|
|
34
35
|
let messageDialogMountPromise: Promise<void> | null = null;
|
|
35
36
|
|
|
36
|
-
const MESSAGE_DIALOG_ROOT_ID =
|
|
37
|
+
const MESSAGE_DIALOG_ROOT_ID = 'ui-vintage-message-dialog-root';
|
|
37
38
|
|
|
38
39
|
// Shared message dialog state
|
|
39
40
|
export const messageDialogState: MessageDialogState = reactive({
|
|
@@ -48,7 +49,7 @@ const markIcon = (icon: HugeiconsIconDefinition | null | undefined) => icon ? ma
|
|
|
48
49
|
// Mount the dialog once on demand
|
|
49
50
|
const ensureMessageDialogMounted = () => {
|
|
50
51
|
// Skip mounting during SSR
|
|
51
|
-
if (typeof document ===
|
|
52
|
+
if (typeof document === 'undefined') {
|
|
52
53
|
return Promise.resolve();
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -66,7 +67,7 @@ const ensureMessageDialogMounted = () => {
|
|
|
66
67
|
// Start the lazy mount
|
|
67
68
|
messageDialogMountPromise = (async () => {
|
|
68
69
|
// Load the component only when needed
|
|
69
|
-
const { default: MessageDialog } = await import(
|
|
70
|
+
const { default: MessageDialog } = await import('./MessageDialog.vue');
|
|
70
71
|
|
|
71
72
|
// Guard against a concurrent mount
|
|
72
73
|
if (document.getElementById(MESSAGE_DIALOG_ROOT_ID)) {
|
|
@@ -74,7 +75,7 @@ const ensureMessageDialogMounted = () => {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
// Create the host element and render the component
|
|
77
|
-
const container = document.createElement(
|
|
78
|
+
const container = document.createElement('div');
|
|
78
79
|
container.id = MESSAGE_DIALOG_ROOT_ID;
|
|
79
80
|
document.body.appendChild(container);
|
|
80
81
|
render(h(MessageDialog), container);
|
|
@@ -155,10 +156,10 @@ export const showMessageDialog = (options: ShowMessageDialogOptions) => {
|
|
|
155
156
|
enqueueMessageDialog({
|
|
156
157
|
id: nextMessageDialogId += 1,
|
|
157
158
|
options: {
|
|
158
|
-
type: options.type ??
|
|
159
|
-
title: options.title ??
|
|
159
|
+
type: options.type ?? 'info',
|
|
160
|
+
title: options.title ?? '',
|
|
160
161
|
message: options.message,
|
|
161
|
-
closeText: options.closeText ??
|
|
162
|
+
closeText: options.closeText ?? '',
|
|
162
163
|
icon: markIcon(options.icon),
|
|
163
164
|
closeButtonIcon: markIcon(options.closeButtonIcon)
|
|
164
165
|
},
|