@brumaombra/ui-vintage 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/module.mjs +43 -43
  2. package/package.json +175 -175
  3. package/src/components/background-grid/BackgroundGrid.vue +4 -4
  4. package/src/components/blog/AllPostsSection.vue +33 -33
  5. package/src/components/blog/BlogContentRenderer.vue +111 -111
  6. package/src/components/blog/BlogFAQSection.vue +19 -19
  7. package/src/components/blog/BlogHeaderSection.vue +80 -80
  8. package/src/components/blog/BlogInfoSection.vue +47 -47
  9. package/src/components/blog/BlogPostHeader.vue +135 -135
  10. package/src/components/blog/BlogProgressBar.vue +33 -33
  11. package/src/components/blog/BlogSectionTitle.vue +22 -22
  12. package/src/components/blog/BlogTagsSection.vue +25 -25
  13. package/src/components/blog/CategoriesList.vue +14 -14
  14. package/src/components/blog/CategoriesSection.vue +11 -11
  15. package/src/components/blog/CategoryCard.vue +25 -25
  16. package/src/components/blog/HeaderCarousel.vue +97 -97
  17. package/src/components/blog/PostCard.vue +33 -33
  18. package/src/components/blog/PostsList.vue +15 -15
  19. package/src/components/blog/SocialShareSidebar.vue +84 -84
  20. package/src/components/blog/TableOfContents.vue +307 -307
  21. package/src/components/busy-indicator/BusyIndicator.vue +7 -7
  22. package/src/components/busy-indicator/busy-indicator-state.ts +56 -56
  23. package/src/components/card-grid/CardGrid.vue +34 -34
  24. package/src/components/chip/Chip.vue +15 -15
  25. package/src/components/confirm-dialog/ConfirmDialog.vue +50 -50
  26. package/src/components/confirm-dialog/confirm-dialog-state.ts +131 -131
  27. package/src/components/content/BlogList.vue +30 -30
  28. package/src/components/content/BlogTable.vue +36 -36
  29. package/src/components/content/CodeBlock.vue +136 -136
  30. package/src/components/content/Flow.vue +60 -60
  31. package/src/components/content/ProseHr.vue +15 -15
  32. package/src/components/content/ProsePre.vue +12 -12
  33. package/src/components/content/Terminal.vue +59 -59
  34. package/src/components/cookie-consent/CookieConsent.vue +36 -36
  35. package/src/components/cookie-consent/useCookieConsent.ts +37 -37
  36. package/src/components/dashboard-shell/DashboardShell.vue +171 -171
  37. package/src/components/data-list/DataList.vue +6 -6
  38. package/src/components/data-list/DataListItem.vue +4 -4
  39. package/src/components/data-list/DataListLabel.vue +4 -4
  40. package/src/components/data-list/DataListText.vue +4 -4
  41. package/src/components/data-list/DataListValue.vue +4 -4
  42. package/src/components/empty-state-card/EmptyStateCard.vue +40 -40
  43. package/src/components/error-page/ErrorPage.vue +72 -72
  44. package/src/components/info-card/InfoCard.vue +31 -31
  45. package/src/components/landing/landing-content/LandingContent.vue +4 -4
  46. package/src/components/landing/landing-footer/LandingFooter.vue +128 -128
  47. package/src/components/landing/landing-navbar/LandingNavbar.vue +50 -50
  48. package/src/components/landing/landing-shell/LandingShell.vue +36 -36
  49. package/src/components/language-flag/LanguageFlag.vue +25 -25
  50. package/src/components/language-flag/flags/ChineseFlag.vue +8 -8
  51. package/src/components/language-flag/flags/EnglishFlag.vue +7 -7
  52. package/src/components/language-flag/flags/FrenchFlag.vue +5 -5
  53. package/src/components/language-flag/flags/GermanFlag.vue +5 -5
  54. package/src/components/language-flag/flags/ItalianFlag.vue +7 -7
  55. package/src/components/language-flag/flags/JapaneseFlag.vue +4 -4
  56. package/src/components/language-flag/flags/PortugueseFlag.vue +57 -57
  57. package/src/components/language-flag/flags/RussianFlag.vue +5 -5
  58. package/src/components/language-flag/flags/SpanishFlag.vue +4 -4
  59. package/src/components/language-selector/LanguageSelector.vue +76 -76
  60. package/src/components/load-more-button/LoadMoreButton.vue +17 -17
  61. package/src/components/loading-state-card/LoadingStateCard.vue +28 -28
  62. package/src/components/message-dialog/MessageDialog.vue +59 -59
  63. package/src/components/message-dialog/message-dialog-state.ts +105 -105
  64. package/src/components/message-toast/MessageToast.vue +149 -149
  65. package/src/components/message-toast/message-toast-state.ts +146 -146
  66. package/src/components/page-header/PageHeader.vue +34 -34
  67. package/src/components/progress-component/ProgressComponent.vue +33 -33
  68. package/src/components/single-value-card/SingleValueCard.vue +57 -57
  69. package/src/components/slider-form-component/SliderFormComponent.vue +36 -36
  70. package/src/components/stat-strip/StatStrip.vue +22 -22
  71. package/src/components/switch-form-component/SwitchFormComponent.vue +20 -20
  72. package/src/components/text-link/TextLink.vue +14 -14
  73. package/src/components/theme-selector/ThemeSelector.vue +61 -61
  74. package/src/components/theme-selector/theme-transition.ts +63 -63
  75. package/src/components/ui/accordion/Accordion.vue +38 -38
  76. package/src/components/ui/alert/Alert.vue +5 -5
  77. package/src/components/ui/alert/AlertDescription.vue +4 -4
  78. package/src/components/ui/alert/AlertTitle.vue +4 -4
  79. package/src/components/ui/alert/index.ts +2 -2
  80. package/src/components/ui/alert-dialog/AlertDialog.vue +3 -3
  81. package/src/components/ui/alert-dialog/AlertDialogAction.vue +3 -3
  82. package/src/components/ui/alert-dialog/AlertDialogCancel.vue +3 -3
  83. package/src/components/ui/alert-dialog/AlertDialogContent.vue +7 -7
  84. package/src/components/ui/alert-dialog/AlertDialogDescription.vue +3 -3
  85. package/src/components/ui/alert-dialog/AlertDialogFooter.vue +4 -4
  86. package/src/components/ui/alert-dialog/AlertDialogHeader.vue +4 -4
  87. package/src/components/ui/alert-dialog/AlertDialogTitle.vue +3 -3
  88. package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +3 -3
  89. package/src/components/ui/animated-number/AnimatedNumber.vue +49 -48
  90. package/src/components/ui/avatar/Avatar.vue +28 -28
  91. package/src/components/ui/avatar/AvatarFallback.vue +6 -6
  92. package/src/components/ui/avatar/AvatarGroup.vue +40 -40
  93. package/src/components/ui/avatar/AvatarImage.vue +3 -3
  94. package/src/components/ui/avatar/index.ts +17 -17
  95. package/src/components/ui/badge/Badge.vue +20 -20
  96. package/src/components/ui/breadcrumb/Breadcrumb.vue +4 -4
  97. package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +9 -9
  98. package/src/components/ui/breadcrumb/BreadcrumbItem.vue +4 -4
  99. package/src/components/ui/breadcrumb/BreadcrumbLink.vue +4 -4
  100. package/src/components/ui/breadcrumb/BreadcrumbList.vue +4 -4
  101. package/src/components/ui/breadcrumb/BreadcrumbPage.vue +4 -4
  102. package/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +4 -4
  103. package/src/components/ui/busy/Busy.vue +33 -33
  104. package/src/components/ui/button/Button.vue +23 -23
  105. package/src/components/ui/button/index.ts +56 -56
  106. package/src/components/ui/calendar/Calendar.vue +138 -138
  107. package/src/components/ui/calendar/CalendarCell.vue +7 -7
  108. package/src/components/ui/calendar/CalendarCellTrigger.vue +18 -18
  109. package/src/components/ui/calendar/CalendarGrid.vue +3 -3
  110. package/src/components/ui/calendar/CalendarGridBody.vue +3 -3
  111. package/src/components/ui/calendar/CalendarGridHead.vue +3 -3
  112. package/src/components/ui/calendar/CalendarGridRow.vue +3 -3
  113. package/src/components/ui/calendar/CalendarHeadCell.vue +7 -7
  114. package/src/components/ui/calendar/CalendarHeader.vue +7 -7
  115. package/src/components/ui/calendar/CalendarHeading.vue +6 -6
  116. package/src/components/ui/calendar/CalendarNextButton.vue +15 -15
  117. package/src/components/ui/calendar/CalendarPrevButton.vue +15 -15
  118. package/src/components/ui/calendar/index.ts +4 -4
  119. package/src/components/ui/card/Card.vue +20 -20
  120. package/src/components/ui/card/CardAction.vue +8 -8
  121. package/src/components/ui/card/CardContent.vue +4 -4
  122. package/src/components/ui/card/CardDescription.vue +12 -12
  123. package/src/components/ui/card/CardFooter.vue +4 -4
  124. package/src/components/ui/card/CardHeader.vue +8 -8
  125. package/src/components/ui/card/CardText.vue +8 -8
  126. package/src/components/ui/card/CardTitle.vue +8 -8
  127. package/src/components/ui/checkbox/Checkbox.vue +27 -27
  128. package/src/components/ui/collapsible/Collapsible.vue +3 -3
  129. package/src/components/ui/collapsible/CollapsibleContent.vue +3 -3
  130. package/src/components/ui/collapsible/CollapsibleTrigger.vue +3 -3
  131. package/src/components/ui/combobox/Combobox.vue +4 -4
  132. package/src/components/ui/combobox/ComboboxAnchor.vue +16 -16
  133. package/src/components/ui/combobox/ComboboxEmpty.vue +3 -3
  134. package/src/components/ui/combobox/ComboboxGroup.vue +9 -9
  135. package/src/components/ui/combobox/ComboboxInput.vue +6 -6
  136. package/src/components/ui/combobox/ComboboxItem.vue +17 -17
  137. package/src/components/ui/combobox/ComboboxList.vue +19 -19
  138. package/src/components/ui/combobox/ComboboxSelect.vue +77 -77
  139. package/src/components/ui/combobox/ComboboxSeparator.vue +1 -1
  140. package/src/components/ui/combobox/ComboboxTrigger.vue +10 -10
  141. package/src/components/ui/combobox/types.ts +5 -5
  142. package/src/components/ui/command/Command.vue +48 -48
  143. package/src/components/ui/command/CommandDialog.vue +14 -14
  144. package/src/components/ui/command/CommandEmpty.vue +4 -4
  145. package/src/components/ui/command/CommandGroup.vue +23 -23
  146. package/src/components/ui/command/CommandInput.vue +9 -9
  147. package/src/components/ui/command/CommandItem.vue +40 -40
  148. package/src/components/ui/command/CommandList.vue +9 -9
  149. package/src/components/ui/command/CommandSeparator.vue +3 -3
  150. package/src/components/ui/command/CommandShortcut.vue +8 -8
  151. package/src/components/ui/command/index.ts +11 -11
  152. package/src/components/ui/data-table/DataTable.vue +145 -145
  153. package/src/components/ui/data-table/index.ts +11 -11
  154. package/src/components/ui/date-picker/DatePicker.vue +31 -31
  155. package/src/components/ui/date-time-picker/DateTimePicker.vue +97 -97
  156. package/src/components/ui/dialog/Dialog.vue +3 -3
  157. package/src/components/ui/dialog/DialogClose.vue +3 -3
  158. package/src/components/ui/dialog/DialogContent.vue +21 -21
  159. package/src/components/ui/dialog/DialogDescription.vue +7 -7
  160. package/src/components/ui/dialog/DialogFooter.vue +8 -8
  161. package/src/components/ui/dialog/DialogHeader.vue +4 -4
  162. package/src/components/ui/dialog/DialogOverlay.vue +7 -7
  163. package/src/components/ui/dialog/DialogScrollContent.vue +32 -32
  164. package/src/components/ui/dialog/DialogTitle.vue +3 -3
  165. package/src/components/ui/dialog/DialogTrigger.vue +3 -3
  166. package/src/components/ui/dropdown-menu/DropdownMenu.vue +3 -3
  167. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +11 -11
  168. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +15 -15
  169. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +3 -3
  170. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +12 -12
  171. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +9 -9
  172. package/src/components/ui/dropdown-menu/DropdownMenuPortal.vue +3 -3
  173. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +3 -3
  174. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +11 -11
  175. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +1 -1
  176. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +4 -4
  177. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +3 -3
  178. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +15 -15
  179. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +15 -15
  180. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +3 -3
  181. package/src/components/ui/dropdown-menu/classes.ts +16 -16
  182. package/src/components/ui/field/Field.vue +5 -5
  183. package/src/components/ui/field/FieldContent.vue +8 -8
  184. package/src/components/ui/field/FieldDescription.vue +10 -10
  185. package/src/components/ui/field/FieldError.vue +39 -39
  186. package/src/components/ui/field/FieldGroup.vue +8 -8
  187. package/src/components/ui/field/FieldLabel.vue +10 -10
  188. package/src/components/ui/field/FieldLegend.vue +11 -11
  189. package/src/components/ui/field/FieldSeparator.vue +11 -11
  190. package/src/components/ui/field/FieldSet.vue +9 -9
  191. package/src/components/ui/field/FieldTitle.vue +8 -8
  192. package/src/components/ui/field/field-context.ts +36 -36
  193. package/src/components/ui/field/index.ts +22 -22
  194. package/src/components/ui/file-dropzone/FileDropzone.vue +144 -144
  195. package/src/components/ui/file-dropzone/index.ts +19 -19
  196. package/src/components/ui/hover-card/HoverCard.vue +5 -5
  197. package/src/components/ui/hover-card/HoverCardContent.vue +13 -13
  198. package/src/components/ui/hover-card/HoverCardTrigger.vue +3 -3
  199. package/src/components/ui/input/Input.vue +13 -13
  200. package/src/components/ui/kbd/Kbd.vue +10 -10
  201. package/src/components/ui/kbd/KbdGroup.vue +49 -49
  202. package/src/components/ui/label/Label.vue +7 -7
  203. package/src/components/ui/native-select/NativeSelect.vue +16 -16
  204. package/src/components/ui/native-select/NativeSelectOptGroup.vue +3 -3
  205. package/src/components/ui/native-select/NativeSelectOption.vue +3 -3
  206. package/src/components/ui/number-field/NumberField.vue +88 -88
  207. package/src/components/ui/pagination/Pagination.vue +4 -4
  208. package/src/components/ui/pagination/PaginationContent.vue +4 -4
  209. package/src/components/ui/pagination/PaginationEllipsis.vue +9 -9
  210. package/src/components/ui/pagination/PaginationFirst.vue +8 -8
  211. package/src/components/ui/pagination/PaginationItem.vue +14 -14
  212. package/src/components/ui/pagination/PaginationLast.vue +8 -8
  213. package/src/components/ui/pagination/PaginationNext.vue +8 -8
  214. package/src/components/ui/pagination/PaginationPrevious.vue +8 -8
  215. package/src/components/ui/pagination/SimplePagination.vue +25 -25
  216. package/src/components/ui/pin-input/PinInput.vue +20 -20
  217. package/src/components/ui/pin-input/PinInputInput.vue +17 -17
  218. package/src/components/ui/pin-input/context.ts +1 -1
  219. package/src/components/ui/popover/Popover.vue +3 -3
  220. package/src/components/ui/popover/PopoverAnchor.vue +3 -3
  221. package/src/components/ui/popover/PopoverContent.vue +12 -12
  222. package/src/components/ui/popover/PopoverTrigger.vue +3 -3
  223. package/src/components/ui/progress/Progress.vue +16 -16
  224. package/src/components/ui/radio-group/RadioGroup.vue +7 -7
  225. package/src/components/ui/radio-group/RadioGroupCard.vue +39 -39
  226. package/src/components/ui/radio-group/RadioGroupItem.vue +20 -20
  227. package/src/components/ui/scroll-area/ScrollArea.vue +14 -14
  228. package/src/components/ui/scroll-area/ScrollBar.vue +12 -12
  229. package/src/components/ui/select/Select.vue +3 -3
  230. package/src/components/ui/select/SelectContent.vue +25 -25
  231. package/src/components/ui/select/SelectGroup.vue +3 -3
  232. package/src/components/ui/select/SelectItem.vue +24 -24
  233. package/src/components/ui/select/SelectItemContent.vue +32 -32
  234. package/src/components/ui/select/SelectItemText.vue +3 -3
  235. package/src/components/ui/select/SelectLabel.vue +3 -3
  236. package/src/components/ui/select/SelectScrollDownButton.vue +9 -9
  237. package/src/components/ui/select/SelectScrollUpButton.vue +9 -9
  238. package/src/components/ui/select/SelectSeparator.vue +2 -2
  239. package/src/components/ui/select/SelectTrigger.vue +14 -14
  240. package/src/components/ui/select/SelectValue.vue +3 -3
  241. package/src/components/ui/select/SelectValueContent.vue +39 -39
  242. package/src/components/ui/separator/Separator.vue +7 -7
  243. package/src/components/ui/sheet/Sheet.vue +3 -3
  244. package/src/components/ui/sheet/SheetClose.vue +3 -3
  245. package/src/components/ui/sheet/SheetContent.vue +22 -22
  246. package/src/components/ui/sheet/SheetDescription.vue +3 -3
  247. package/src/components/ui/sheet/SheetFooter.vue +3 -3
  248. package/src/components/ui/sheet/SheetHeader.vue +3 -3
  249. package/src/components/ui/sheet/SheetOverlay.vue +7 -7
  250. package/src/components/ui/sheet/SheetTitle.vue +3 -3
  251. package/src/components/ui/sheet/SheetTrigger.vue +3 -3
  252. package/src/components/ui/sidebar/Sidebar.vue +57 -57
  253. package/src/components/ui/sidebar/SidebarContent.vue +8 -8
  254. package/src/components/ui/sidebar/SidebarFooter.vue +8 -8
  255. package/src/components/ui/sidebar/SidebarGroup.vue +8 -8
  256. package/src/components/ui/sidebar/SidebarGroupAction.vue +9 -9
  257. package/src/components/ui/sidebar/SidebarGroupContent.vue +4 -4
  258. package/src/components/ui/sidebar/SidebarGroupLabel.vue +8 -8
  259. package/src/components/ui/sidebar/SidebarHeader.vue +8 -8
  260. package/src/components/ui/sidebar/SidebarInput.vue +8 -8
  261. package/src/components/ui/sidebar/SidebarInset.vue +9 -9
  262. package/src/components/ui/sidebar/SidebarMenu.vue +4 -4
  263. package/src/components/ui/sidebar/SidebarMenuAction.vue +18 -18
  264. package/src/components/ui/sidebar/SidebarMenuBadge.vue +14 -14
  265. package/src/components/ui/sidebar/SidebarMenuButton.vue +21 -21
  266. package/src/components/ui/sidebar/SidebarMenuButtonChild.vue +10 -10
  267. package/src/components/ui/sidebar/SidebarMenuItem.vue +4 -4
  268. package/src/components/ui/sidebar/SidebarMenuSkeleton.vue +10 -10
  269. package/src/components/ui/sidebar/SidebarMenuSub.vue +9 -9
  270. package/src/components/ui/sidebar/SidebarMenuSubButton.vue +17 -17
  271. package/src/components/ui/sidebar/SidebarMenuSubItem.vue +4 -4
  272. package/src/components/ui/sidebar/SidebarProvider.vue +46 -46
  273. package/src/components/ui/sidebar/SidebarRail.vue +13 -13
  274. package/src/components/ui/sidebar/SidebarSeparator.vue +4 -4
  275. package/src/components/ui/sidebar/SidebarTrigger.vue +5 -5
  276. package/src/components/ui/sidebar/index.ts +29 -29
  277. package/src/components/ui/sidebar/utils.ts +7 -7
  278. package/src/components/ui/skeleton/Skeleton.vue +6 -6
  279. package/src/components/ui/slider/Slider.vue +14 -14
  280. package/src/components/ui/spinner/Spinner.vue +21 -21
  281. package/src/components/ui/stepper/SimpleStepper.vue +26 -26
  282. package/src/components/ui/stepper/Stepper.vue +6 -6
  283. package/src/components/ui/stepper/StepperDescription.vue +5 -5
  284. package/src/components/ui/stepper/StepperIndicator.vue +17 -17
  285. package/src/components/ui/stepper/StepperItem.vue +4 -4
  286. package/src/components/ui/stepper/StepperSeparator.vue +7 -7
  287. package/src/components/ui/stepper/StepperTitle.vue +5 -5
  288. package/src/components/ui/stepper/StepperTrigger.vue +4 -4
  289. package/src/components/ui/stepper/index.ts +3 -3
  290. package/src/components/ui/switch/Switch.vue +15 -15
  291. package/src/components/ui/table/Table.vue +6 -6
  292. package/src/components/ui/table/TableBody.vue +4 -4
  293. package/src/components/ui/table/TableCaption.vue +4 -4
  294. package/src/components/ui/table/TableCell.vue +8 -8
  295. package/src/components/ui/table/TableEmpty.vue +14 -14
  296. package/src/components/ui/table/TableFooter.vue +8 -8
  297. package/src/components/ui/table/TableHead.vue +8 -8
  298. package/src/components/ui/table/TableHeader.vue +4 -4
  299. package/src/components/ui/table/TableRow.vue +8 -8
  300. package/src/components/ui/tabs/Tabs.vue +4 -4
  301. package/src/components/ui/tabs/TabsContent.vue +4 -4
  302. package/src/components/ui/tabs/TabsList.vue +15 -15
  303. package/src/components/ui/tabs/TabsTrigger.vue +10 -10
  304. package/src/components/ui/tags-input/TagsInput.vue +17 -17
  305. package/src/components/ui/tags-input/TagsInputInput.vue +6 -6
  306. package/src/components/ui/tags-input/TagsInputItem.vue +15 -15
  307. package/src/components/ui/tags-input/TagsInputItemDelete.vue +12 -12
  308. package/src/components/ui/tags-input/TagsInputItemText.vue +4 -4
  309. package/src/components/ui/textarea/Textarea.vue +12 -12
  310. package/src/components/ui/time-picker/TimePicker.vue +25 -25
  311. package/src/components/ui/toggle-group/Toggle.vue +10 -10
  312. package/src/components/ui/toggle-group/ToggleGroup.vue +38 -38
  313. package/src/components/ui/toggle-group/ToggleGroupItem.vue +9 -9
  314. package/src/components/ui/toggle-group/index.ts +46 -46
  315. package/src/components/ui/tooltip/Tooltip.vue +3 -3
  316. package/src/components/ui/tooltip/TooltipContent.vue +13 -13
  317. package/src/components/ui/tooltip/TooltipProvider.vue +4 -4
  318. package/src/components/ui/tooltip/TooltipTrigger.vue +3 -3
  319. package/src/i18n/de.json +185 -185
  320. package/src/i18n/en.json +185 -185
  321. package/src/i18n/es.json +185 -185
  322. package/src/i18n/fr.json +185 -185
  323. package/src/i18n/it.json +185 -185
  324. package/src/i18n/ja.json +185 -185
  325. package/src/i18n/pt.json +185 -185
  326. package/src/i18n/ru.json +185 -185
  327. package/src/i18n/zh.json +185 -185
  328. package/src/lib/color-tokens.ts +24 -24
  329. package/src/lib/i18n.ts +65 -65
  330. package/src/lib/utils.ts +33 -33
  331. package/src/nuxt-components.d.ts +2 -2
  332. package/src/runtime/ui-vintage-i18n-plugin.ts +49 -49
  333. package/src/shims-vue.d.ts +3 -3
  334. package/src/styles.css +377 -377
@@ -10,32 +10,32 @@ import { cn } from '../../lib/utils';
10
10
 
11
11
  // Props
12
12
  const props = withDefaults(defineProps<{
13
- statusCode?: number | string;
14
- label?: string;
15
- title?: string;
16
- message?: string;
17
- actionLabel?: string;
18
- showBackground?: boolean;
19
- showDefaultAction?: boolean;
20
- class?: HTMLAttributes['class'];
21
- cardClass?: HTMLAttributes['class'];
22
- contentClass?: HTMLAttributes['class'];
23
- footerClass?: HTMLAttributes['class'];
13
+ statusCode?: number | string;
14
+ label?: string;
15
+ title?: string;
16
+ message?: string;
17
+ actionLabel?: string;
18
+ showBackground?: boolean;
19
+ showDefaultAction?: boolean;
20
+ class?: HTMLAttributes['class'];
21
+ cardClass?: HTMLAttributes['class'];
22
+ contentClass?: HTMLAttributes['class'];
23
+ footerClass?: HTMLAttributes['class'];
24
24
  }>(), {
25
- statusCode: 500,
26
- title: undefined,
27
- message: undefined,
28
- showBackground: true,
29
- showDefaultAction: true,
30
- class: undefined,
31
- cardClass: undefined,
32
- contentClass: undefined,
33
- footerClass: undefined
25
+ statusCode: 500,
26
+ title: undefined,
27
+ message: undefined,
28
+ showBackground: true,
29
+ showDefaultAction: true,
30
+ class: undefined,
31
+ cardClass: undefined,
32
+ contentClass: undefined,
33
+ footerClass: undefined
34
34
  });
35
35
 
36
36
  // Emits
37
37
  const emit = defineEmits<{
38
- action: [];
38
+ action: [];
39
39
  }>();
40
40
 
41
41
  const { t } = useI18n();
@@ -45,73 +45,73 @@ const resolvedActionLabel = computed(() => props.actionLabel || t('uiVintage.but
45
45
 
46
46
  // Resolve the heading copy
47
47
  const resolvedTitle = computed(() => {
48
- if (props.title) return props.title;
49
- if (resolvedStatusCode.value === '404') return t('uiVintage.errorPage.notFound.title');
50
- return t('uiVintage.errorPage.unexpected.title');
48
+ if (props.title) return props.title;
49
+ if (resolvedStatusCode.value === '404') return t('uiVintage.errorPage.notFound.title');
50
+ return t('uiVintage.errorPage.unexpected.title');
51
51
  });
52
52
 
53
53
  // Resolve the supporting message
54
54
  const resolvedMessage = computed(() => {
55
- if (props.message) return props.message;
56
- if (resolvedStatusCode.value === '404') return t('uiVintage.errorPage.notFound.message');
57
- return t('uiVintage.errorPage.unexpected.message');
55
+ if (props.message) return props.message;
56
+ if (resolvedStatusCode.value === '404') return t('uiVintage.errorPage.notFound.message');
57
+ return t('uiVintage.errorPage.unexpected.message');
58
58
  });
59
59
 
60
60
  // Emit the default action
61
61
  const handleAction = () => {
62
- emit('action');
62
+ emit('action');
63
63
  };
64
64
  </script>
65
65
 
66
66
  <template>
67
- <div :class="cn('relative min-h-screen bg-background text-foreground', props.class)">
68
- <!-- Decorative background -->
69
- <BackgroundGrid v-if="props.showBackground" />
67
+ <div :class="cn('relative min-h-screen bg-background text-foreground', props.class)">
68
+ <!-- Decorative background -->
69
+ <BackgroundGrid v-if="props.showBackground" />
70
70
 
71
- <!-- Main content -->
72
- <main class="relative z-10 mx-auto flex min-h-screen w-full max-w-6xl items-center justify-center px-4 py-10 sm:px-6 lg:px-8">
73
- <div class="w-full max-w-xl">
74
- <!-- Toolbar -->
75
- <div v-if="$slots.toolbar" class="mb-4 flex justify-end gap-3">
76
- <slot name="toolbar" />
77
- </div>
71
+ <!-- Main content -->
72
+ <main class="relative z-10 mx-auto flex min-h-screen w-full max-w-6xl items-center justify-center px-4 py-10 sm:px-6 lg:px-8">
73
+ <div class="w-full max-w-xl">
74
+ <!-- Toolbar -->
75
+ <div v-if="$slots.toolbar" class="mb-4 flex justify-end gap-3">
76
+ <slot name="toolbar" />
77
+ </div>
78
78
 
79
- <!-- Error card -->
80
- <Card :class="props.cardClass">
81
- <CardContent :class="cn('space-y-8', props.contentClass)">
82
- <!-- Brand -->
83
- <slot name="brand" />
79
+ <!-- Error card -->
80
+ <Card :class="props.cardClass">
81
+ <CardContent :class="cn('space-y-8', props.contentClass)">
82
+ <!-- Brand -->
83
+ <slot name="brand" />
84
84
 
85
- <!-- Error copy -->
86
- <div>
87
- <!-- Status code -->
88
- <div class="text-xs font-semibold uppercase tracking-[0.2em] text-primary">
89
- {{ resolvedLabel }} {{ resolvedStatusCode }}
90
- </div>
85
+ <!-- Error copy -->
86
+ <div>
87
+ <!-- Status code -->
88
+ <div class="text-xs font-semibold uppercase tracking-[0.2em] text-primary">
89
+ {{ resolvedLabel }} {{ resolvedStatusCode }}
90
+ </div>
91
91
 
92
- <!-- Title -->
93
- <h1 class="mt-3 text-2xl font-semibold tracking-tight">
94
- {{ resolvedTitle }}
95
- </h1>
92
+ <!-- Title -->
93
+ <h1 class="mt-3 text-2xl font-semibold tracking-tight">
94
+ {{ resolvedTitle }}
95
+ </h1>
96
96
 
97
- <!-- Message -->
98
- <p class="text-sm leading-7 text-muted-foreground sm:text-base mt-4">
99
- {{ resolvedMessage }}
100
- </p>
101
- </div>
102
- </CardContent>
97
+ <!-- Message -->
98
+ <p class="text-sm leading-7 text-muted-foreground sm:text-base mt-4">
99
+ {{ resolvedMessage }}
100
+ </p>
101
+ </div>
102
+ </CardContent>
103
103
 
104
- <!-- Actions -->
105
- <CardFooter :class="cn('items-start flex-col gap-3 sm:flex-row sm:items-center', props.footerClass)">
106
- <slot name="actions" :on-action="handleAction">
107
- <Button v-if="props.showDefaultAction" variant="primary" @click="handleAction">
108
- <HugeiconsIcon :icon="ArrowLeft01Icon" :stroke-width="1.8" class="size-4" />
109
- {{ resolvedActionLabel }}
110
- </Button>
111
- </slot>
112
- </CardFooter>
113
- </Card>
114
- </div>
115
- </main>
116
- </div>
104
+ <!-- Actions -->
105
+ <CardFooter :class="cn('items-start flex-col gap-3 sm:flex-row sm:items-center', props.footerClass)">
106
+ <slot name="actions" :on-action="handleAction">
107
+ <Button v-if="props.showDefaultAction" variant="primary" @click="handleAction">
108
+ <HugeiconsIcon :icon="ArrowLeft01Icon" :stroke-width="1.8" class="size-4" />
109
+ {{ resolvedActionLabel }}
110
+ </Button>
111
+ </slot>
112
+ </CardFooter>
113
+ </Card>
114
+ </div>
115
+ </main>
116
+ </div>
117
117
  </template>
@@ -6,43 +6,43 @@ import type { HugeiconsIconDefinition } from '../../lib/common-types';
6
6
 
7
7
  // Props
8
8
  const props = withDefaults(defineProps<{
9
- icon: HugeiconsIconDefinition;
10
- title?: string;
11
- description?: string | number;
12
- class?: HTMLAttributes['class'];
9
+ icon: HugeiconsIconDefinition;
10
+ title?: string;
11
+ description?: string | number;
12
+ class?: HTMLAttributes['class'];
13
13
  }>(), {
14
- title: '',
15
- description: ''
14
+ title: '',
15
+ description: ''
16
16
  });
17
17
  </script>
18
18
 
19
19
  <template>
20
- <Card :class="['flex flex-col items-center p-4! sm:flex-row', props.class]">
21
- <CardContent class="flex w-full flex-col items-center gap-0 p-0! sm:flex-row">
22
- <!-- Icon -->
23
- <span aria-hidden="true" class="mb-3 flex size-10 shrink-0 items-center justify-center rounded border border-primary/30 text-primary sm:mb-0 sm:mr-4">
24
- <HugeiconsIcon :icon="props.icon" class="size-4.5" />
25
- </span>
20
+ <Card :class="['flex flex-col items-center p-4! sm:flex-row', props.class]">
21
+ <CardContent class="flex w-full flex-col items-center gap-0 p-0! sm:flex-row">
22
+ <!-- Icon -->
23
+ <span aria-hidden="true" class="mb-3 flex size-10 shrink-0 items-center justify-center rounded border border-primary/30 text-primary sm:mb-0 sm:mr-4">
24
+ <HugeiconsIcon :icon="props.icon" class="size-4.5" />
25
+ </span>
26
26
 
27
- <!-- Content -->
28
- <div class="flex w-full flex-1 items-center justify-between text-center sm:w-auto sm:text-left">
29
- <div class="flex flex-col w-full gap-2 sm:gap-1">
30
- <!-- Title -->
31
- <span class="text-sm font-semibold text-foreground md:text-base">
32
- {{ props.title }}
33
- </span>
27
+ <!-- Content -->
28
+ <div class="flex w-full flex-1 items-center justify-between text-center sm:w-auto sm:text-left">
29
+ <div class="flex flex-col w-full gap-2 sm:gap-1">
30
+ <!-- Title -->
31
+ <span class="text-sm font-semibold text-foreground md:text-base">
32
+ {{ props.title }}
33
+ </span>
34
34
 
35
- <!-- Description -->
36
- <CardText v-if="props.description">
37
- {{ props.description }}
38
- </CardText>
39
- </div>
35
+ <!-- Description -->
36
+ <CardText v-if="props.description">
37
+ {{ props.description }}
38
+ </CardText>
39
+ </div>
40
40
 
41
- <!-- Right slot for custom elements -->
42
- <div v-if="$slots.right" class="ml-4">
43
- <slot name="right" />
44
- </div>
45
- </div>
46
- </CardContent>
47
- </Card>
41
+ <!-- Right slot for custom elements -->
42
+ <div v-if="$slots.right" class="ml-4">
43
+ <slot name="right" />
44
+ </div>
45
+ </div>
46
+ </CardContent>
47
+ </Card>
48
48
  </template>
@@ -4,12 +4,12 @@ import { cn } from '../../../lib/utils';
4
4
 
5
5
  // Props
6
6
  const props = defineProps<{
7
- class?: HTMLAttributes['class'];
7
+ class?: HTMLAttributes['class'];
8
8
  }>();
9
9
  </script>
10
10
 
11
11
  <template>
12
- <div :class="cn('mx-auto w-full max-w-6xl px-3 py-6 sm:px-6 lg:px-8 lg:py-14', props.class)">
13
- <slot />
14
- </div>
12
+ <div :class="cn('mx-auto w-full max-w-6xl px-3 py-6 sm:px-6 lg:px-8 lg:py-14', props.class)">
13
+ <slot />
14
+ </div>
15
15
  </template>
@@ -8,49 +8,49 @@ import { cn } from '../../../lib/utils';
8
8
  import type { HeadingLevel } from '../../../lib/common-types';
9
9
 
10
10
  export interface LandingFooterLink {
11
- id: string;
12
- label: string;
13
- href?: string;
14
- to?: unknown;
15
- newTab?: boolean;
11
+ id: string;
12
+ label: string;
13
+ href?: string;
14
+ to?: unknown;
15
+ newTab?: boolean;
16
16
  }
17
17
 
18
18
  export interface LandingFooterSection {
19
- id: string;
20
- title: string;
21
- links: LandingFooterLink[];
19
+ id: string;
20
+ title: string;
21
+ links: LandingFooterLink[];
22
22
  }
23
23
 
24
24
  // Props
25
25
  const props = withDefaults(defineProps<{
26
- appName: string;
27
- appLogo?: string;
28
- appLogoDark?: string;
29
- appLinkTo?: string;
30
- logoClass?: HTMLAttributes['class'];
31
- appDescription?: string;
32
- sections?: LandingFooterSection[];
33
- linkComponent?: Component | string;
34
- authorName?: string;
35
- authorLink?: string;
36
- year?: number;
37
- showBottomBar?: boolean;
38
- level?: HeadingLevel;
39
- class?: HTMLAttributes['class'];
40
- containerClass?: HTMLAttributes['class'];
41
- brandClass?: HTMLAttributes['class'];
42
- sectionsClass?: HTMLAttributes['class'];
43
- bottomBarClass?: HTMLAttributes['class'];
26
+ appName: string;
27
+ appLogo?: string;
28
+ appLogoDark?: string;
29
+ appLinkTo?: string;
30
+ logoClass?: HTMLAttributes['class'];
31
+ appDescription?: string;
32
+ sections?: LandingFooterSection[];
33
+ linkComponent?: Component | string;
34
+ authorName?: string;
35
+ authorLink?: string;
36
+ year?: number;
37
+ showBottomBar?: boolean;
38
+ level?: HeadingLevel;
39
+ class?: HTMLAttributes['class'];
40
+ containerClass?: HTMLAttributes['class'];
41
+ brandClass?: HTMLAttributes['class'];
42
+ sectionsClass?: HTMLAttributes['class'];
43
+ bottomBarClass?: HTMLAttributes['class'];
44
44
  }>(), {
45
- appLinkTo: '/',
46
- appDescription: '',
47
- sections: () => [],
48
- linkComponent: 'a',
49
- authorName: '',
50
- authorLink: '',
51
- year: () => new Date().getFullYear(),
52
- showBottomBar: true,
53
- level: 2
45
+ appLinkTo: '/',
46
+ appDescription: '',
47
+ sections: () => [],
48
+ linkComponent: 'a',
49
+ authorName: '',
50
+ authorLink: '',
51
+ year: () => new Date().getFullYear(),
52
+ showBottomBar: true,
53
+ level: 2
54
54
  });
55
55
 
56
56
  const { t } = useI18n();
@@ -59,21 +59,21 @@ const hasSingleSection = computed(() => props.sections.length === 1);
59
59
 
60
60
  // Get link props based on the type of link component and whether the link should open in a new tab
61
61
  const getLinkProps = (link: LandingFooterLink) => {
62
- const sharedProps = link.newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {};
63
-
64
- // If the link component is an anchor, use href. Otherwise, use to for router links.
65
- if (props.linkComponent === 'a') {
66
- return {
67
- href: link.href ?? '#',
68
- ...sharedProps
69
- };
70
- }
71
-
72
- // For non-anchor link components, assume they use a "to" prop (like Vue Router's <RouterLink>).
73
- return {
74
- to: link.to ?? link.href ?? '/',
75
- ...sharedProps
76
- };
62
+ const sharedProps = link.newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {};
63
+
64
+ // If the link component is an anchor, use href. Otherwise, use to for router links.
65
+ if (props.linkComponent === 'a') {
66
+ return {
67
+ href: link.href ?? '#',
68
+ ...sharedProps
69
+ };
70
+ }
71
+
72
+ // For non-anchor link components, assume they use a "to" prop (like Vue Router's <RouterLink>).
73
+ return {
74
+ to: link.to ?? link.href ?? '/',
75
+ ...sharedProps
76
+ };
77
77
  };
78
78
 
79
79
  // Logo sources for each theme (either one falls back to the other)
@@ -83,82 +83,82 @@ const hasDarkLogo = computed(() => darkLogo.value !== lightLogo.value);
83
83
  </script>
84
84
 
85
85
  <template>
86
- <footer :class="cn('relative z-10 border-t border-border bg-card', props.class)">
87
- <div :class="cn('mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8', props.containerClass)">
88
- <div :class="cn('flex flex-col gap-8 md:flex-row md:items-start md:justify-between')">
89
- <!-- Brand section -->
90
- <div :class="cn('max-w-md flex-1', props.brandClass)">
91
- <!-- App logo and name -->
92
- <a :href="props.appLinkTo" class="mb-4 inline-flex items-center gap-2 text-lg font-semibold tracking-tight text-foreground transition-opacity duration-150 hover:opacity-80">
93
- <template v-if="lightLogo">
94
- <NuxtImg :src="lightLogo" :alt="logoAlt" width="32" height="32" :sizes="{ 320: '32px', 1280: '32px' }" loading="lazy" decoding="async" :class="cn('size-8 shrink-0 object-contain', hasDarkLogo && 'dark:hidden', props.logoClass)" />
95
- <NuxtImg v-if="hasDarkLogo" :src="darkLogo" :alt="logoAlt" width="32" height="32" :sizes="{ 320: '32px', 1280: '32px' }" loading="lazy" decoding="async" :class="cn('hidden size-8 shrink-0 object-contain dark:block', props.logoClass)" />
96
- </template>
97
- <span>{{ props.appName }}</span>
98
- </a>
99
-
100
- <!-- App description -->
101
- <p v-if="props.appDescription" class="max-w-sm text-xs md:text-sm leading-relaxed text-muted-foreground">
102
- {{ props.appDescription }}
103
- </p>
104
- </div>
105
-
106
- <!-- Single link section -->
107
- <div v-if="hasSingleSection" :class="cn('min-w-0 md:flex md:justify-end', props.sectionsClass)">
108
- <div class="md:text-right">
109
- <!-- Section title -->
110
- <component :is="`h${props.level}`" class="mb-4 font-semibold text-foreground">
111
- {{ props.sections[0]?.title }}
112
- </component>
113
-
114
- <!-- Section links -->
115
- <ul class="space-y-3 text-xs sm:text-sm">
116
- <li v-for="link in props.sections[0]?.links" :key="link.id">
117
- <component :is="props.linkComponent" v-bind="getLinkProps(link)" class="bg-[linear-gradient(currentColor,currentColor)] bg-[length:0%_1px] bg-left-bottom bg-no-repeat text-muted-foreground transition-[color,background-size] duration-300 ease-out-expo hover:bg-[length:100%_1px] hover:text-primary">
118
- {{ link.label }}
119
- </component>
120
- </li>
121
- </ul>
122
- </div>
123
- </div>
124
-
125
- <!-- Link sections -->
126
- <div v-else class="flex flex-col gap-8 md:max-w-[60%] md:flex-row md:flex-wrap md:justify-end md:gap-16">
127
- <div v-for="section in props.sections" :key="section.id" :class="cn('min-w-28', props.sectionsClass)">
128
- <!-- Section title -->
129
- <component :is="`h${props.level}`" class="mb-4 font-semibold text-foreground">
130
- {{ section.title }}
131
- </component>
132
-
133
- <!-- Section links -->
134
- <ul class="space-y-3 text-xs sm:text-sm">
135
- <li v-for="link in section.links" :key="link.id">
136
- <component :is="props.linkComponent" v-bind="getLinkProps(link)" class="bg-[linear-gradient(currentColor,currentColor)] bg-[length:0%_1px] bg-left-bottom bg-no-repeat text-muted-foreground transition-[color,background-size] duration-300 ease-out-expo hover:bg-[length:100%_1px] hover:text-primary">
137
- {{ link.label }}
138
- </component>
139
- </li>
140
- </ul>
141
- </div>
142
- </div>
143
- </div>
144
-
145
- <!-- Bottom bar -->
146
- <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)">
147
- <!-- Copyright -->
148
- <div>
149
- &copy; {{ props.year }} {{ props.appName }}. {{ t('uiVintage.footer.allRightsReserved') }}
150
- </div>
151
-
152
- <!-- Author -->
153
- <div v-if="props.authorName && props.authorLink" class="flex flex-wrap items-center justify-center gap-1.5 md:justify-end">
154
- <span>{{ t('uiVintage.footer.madeWith') }}</span>
155
- <HugeiconsIcon :icon="FavouriteIcon" class="size-4 shrink-0 text-destructive" />
156
- <span>{{ t('uiVintage.footer.by') }}</span>
157
- <a :href="props.authorLink" target="_blank" rel="noopener noreferrer" class="font-semibold text-foreground hover:underline">
158
- {{ props.authorName }}
159
- </a>
160
- </div>
161
- </div>
162
- </div>
163
- </footer>
86
+ <footer :class="cn('relative z-10 border-t border-border bg-card', props.class)">
87
+ <div :class="cn('mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8', props.containerClass)">
88
+ <div :class="cn('flex flex-col gap-8 md:flex-row md:items-start md:justify-between')">
89
+ <!-- Brand section -->
90
+ <div :class="cn('max-w-md flex-1', props.brandClass)">
91
+ <!-- App logo and name -->
92
+ <a :href="props.appLinkTo" class="mb-4 inline-flex items-center gap-2 text-lg font-semibold tracking-tight text-foreground transition-opacity duration-150 hover:opacity-80">
93
+ <template v-if="lightLogo">
94
+ <NuxtImg :src="lightLogo" :alt="logoAlt" width="32" height="32" :sizes="{ 320: '32px', 1280: '32px' }" loading="lazy" decoding="async" :class="cn('size-8 shrink-0 object-contain', hasDarkLogo && 'dark:hidden', props.logoClass)" />
95
+ <NuxtImg v-if="hasDarkLogo" :src="darkLogo" :alt="logoAlt" width="32" height="32" :sizes="{ 320: '32px', 1280: '32px' }" loading="lazy" decoding="async" :class="cn('hidden size-8 shrink-0 object-contain dark:block', props.logoClass)" />
96
+ </template>
97
+ <span>{{ props.appName }}</span>
98
+ </a>
99
+
100
+ <!-- App description -->
101
+ <p v-if="props.appDescription" class="max-w-sm text-xs md:text-sm leading-relaxed text-muted-foreground">
102
+ {{ props.appDescription }}
103
+ </p>
104
+ </div>
105
+
106
+ <!-- Single link section -->
107
+ <div v-if="hasSingleSection" :class="cn('min-w-0 md:flex md:justify-end', props.sectionsClass)">
108
+ <div class="md:text-right">
109
+ <!-- Section title -->
110
+ <component :is="`h${props.level}`" class="mb-4 font-semibold text-foreground">
111
+ {{ props.sections[0]?.title }}
112
+ </component>
113
+
114
+ <!-- Section links -->
115
+ <ul class="space-y-3 text-xs sm:text-sm">
116
+ <li v-for="link in props.sections[0]?.links" :key="link.id">
117
+ <component :is="props.linkComponent" v-bind="getLinkProps(link)" class="bg-[linear-gradient(currentColor,currentColor)] bg-[length:0%_1px] bg-left-bottom bg-no-repeat text-muted-foreground transition-[color,background-size] duration-300 ease-out-expo hover:bg-[length:100%_1px] hover:text-primary">
118
+ {{ link.label }}
119
+ </component>
120
+ </li>
121
+ </ul>
122
+ </div>
123
+ </div>
124
+
125
+ <!-- Link sections -->
126
+ <div v-else class="flex flex-col gap-8 md:max-w-[60%] md:flex-row md:flex-wrap md:justify-end md:gap-16">
127
+ <div v-for="section in props.sections" :key="section.id" :class="cn('min-w-28', props.sectionsClass)">
128
+ <!-- Section title -->
129
+ <component :is="`h${props.level}`" class="mb-4 font-semibold text-foreground">
130
+ {{ section.title }}
131
+ </component>
132
+
133
+ <!-- Section links -->
134
+ <ul class="space-y-3 text-xs sm:text-sm">
135
+ <li v-for="link in section.links" :key="link.id">
136
+ <component :is="props.linkComponent" v-bind="getLinkProps(link)" class="bg-[linear-gradient(currentColor,currentColor)] bg-[length:0%_1px] bg-left-bottom bg-no-repeat text-muted-foreground transition-[color,background-size] duration-300 ease-out-expo hover:bg-[length:100%_1px] hover:text-primary">
137
+ {{ link.label }}
138
+ </component>
139
+ </li>
140
+ </ul>
141
+ </div>
142
+ </div>
143
+ </div>
144
+
145
+ <!-- Bottom bar -->
146
+ <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)">
147
+ <!-- Copyright -->
148
+ <div>
149
+ &copy; {{ props.year }} {{ props.appName }}. {{ t('uiVintage.footer.allRightsReserved') }}
150
+ </div>
151
+
152
+ <!-- Author -->
153
+ <div v-if="props.authorName && props.authorLink" class="flex flex-wrap items-center justify-center gap-1.5 md:justify-end">
154
+ <span>{{ t('uiVintage.footer.madeWith') }}</span>
155
+ <HugeiconsIcon :icon="FavouriteIcon" class="size-4 shrink-0 text-destructive" />
156
+ <span>{{ t('uiVintage.footer.by') }}</span>
157
+ <a :href="props.authorLink" target="_blank" rel="noopener noreferrer" class="font-semibold text-foreground hover:underline">
158
+ {{ props.authorName }}
159
+ </a>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ </footer>
164
164
  </template>