@iqual/nuxt-icms 1.1.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/css/ckeditor.css +4 -0
- package/assets/css/components/container.css +2 -2
- package/assets/css/tailwind.css +1 -1
- package/assets/css/typography.css +4 -0
- package/assets/symbols/download.svg +3 -0
- package/bundles.ts +4 -1
- package/components/Blokkli/TextMedia/index.vue +1 -2
- package/components/DesignSystem/Atoms/Caption.vue +15 -0
- package/components/DesignSystem/Atoms/LinkListItem.vue +21 -0
- package/components/DesignSystem/Molecules/MediaLightbox.vue +273 -0
- package/components/DesignSystem/Molecules/MediaSlider.vue +33 -22
- package/components/DesignSystem/Organisms/Map.vue +61 -0
- package/components/DesignSystem/README.md +489 -0
- package/components/Media/Image/index.vue +4 -162
- package/components/Media/RemoteVideo/index.vue +3 -3
- package/components/Node/Icms/Page/SearchResult/fragment.graphql +8 -0
- package/components/Node/Icms/Page/SearchResult/index.vue +12 -0
- package/components/Node/Icms/Page/Teaser/fragment.graphql +17 -0
- package/components/Node/Icms/Page/Teaser/index.vue +20 -0
- package/components/Node/Icms/Page/fragment.graphql +18 -0
- package/components/Node/Icms/Page/index.vue +5 -3
- package/components/Paragraph/CallToAction/index.vue +12 -8
- package/components/Paragraph/Card/Layout/index.vue +2 -2
- package/components/Paragraph/Contact/index.vue +1 -2
- package/components/Paragraph/Downloads/index.vue +4 -16
- package/components/Paragraph/FAQ/Layout/index.vue +24 -3
- package/components/Paragraph/FlipTeasers/index.vue +2 -2
- package/components/Paragraph/Gallery/index.vue +35 -172
- package/components/Paragraph/HeroImage/index.vue +13 -4
- package/components/Paragraph/IconText/Layout/index.vue +1 -2
- package/components/Paragraph/Media/index.vue +7 -2
- package/components/Paragraph/Table/index.vue +2 -2
- package/components/Paragraph/Team/Layout/index.vue +2 -2
- package/components/Paragraph/Teasers/fragment.graphql +2 -15
- package/components/Paragraph/Teasers/index.vue +12 -15
- package/components/Paragraph/TextMedia/index.vue +40 -33
- package/components/Paragraph/Timeline/Element/index.vue +1 -1
- package/components/Paragraph/Timeline/Layout/fragment.graphql +1 -0
- package/components/Paragraph/Timeline/Layout/index.vue +9 -6
- package/components/Paragraph/iFrame/index.vue +16 -2
- package/components/Search/Facets/FacetDropdownUI.vue +222 -0
- package/components/Search/Facets/FacetedSearchUI.vue +397 -0
- package/components/Search/Facets/fragment.graphql +40 -0
- package/components/Section/Footer/index.vue +15 -14
- package/components/Section/Header/GlobalMenu.vue +34 -34
- package/components/Section/Header/LanguageDropdown.vue +60 -73
- package/components/Section/Header/LanguageSwitcher.vue +37 -0
- package/components/Section/Header/MetaMenu.vue +27 -20
- package/components/Section/Header/index.vue +91 -79
- package/components/ui/accordion/Accordion.vue +2 -2
- package/components/ui/accordion/AccordionContent.vue +5 -5
- package/components/ui/accordion/AccordionItem.vue +9 -10
- package/components/ui/accordion/AccordionTrigger.vue +5 -5
- package/components/ui/alert/Alert.vue +17 -0
- package/components/ui/alert/AlertDescription.vue +14 -0
- package/components/ui/alert/AlertTitle.vue +14 -0
- package/components/ui/alert/index.ts +24 -0
- package/components/ui/alert-dialog/AlertDialog.vue +15 -0
- package/components/ui/alert-dialog/AlertDialogAction.vue +22 -0
- package/components/ui/alert-dialog/AlertDialogCancel.vue +29 -0
- package/components/ui/alert-dialog/AlertDialogContent.vue +43 -0
- package/components/ui/alert-dialog/AlertDialogDescription.vue +27 -0
- package/components/ui/alert-dialog/AlertDialogFooter.vue +21 -0
- package/components/ui/alert-dialog/AlertDialogHeader.vue +16 -0
- package/components/ui/alert-dialog/AlertDialogTitle.vue +24 -0
- package/components/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
- package/components/ui/alert-dialog/index.ts +9 -0
- package/components/ui/aspect-ratio/AspectRatio.vue +12 -0
- package/components/ui/aspect-ratio/index.ts +1 -0
- package/components/ui/auto-form/AutoForm.vue +106 -0
- package/components/ui/auto-form/AutoFormField.vue +45 -0
- package/components/ui/auto-form/AutoFormFieldArray.vue +110 -0
- package/components/ui/auto-form/AutoFormFieldBoolean.vue +41 -0
- package/components/ui/auto-form/AutoFormFieldDate.vue +57 -0
- package/components/ui/auto-form/AutoFormFieldEnum.vue +49 -0
- package/components/ui/auto-form/AutoFormFieldFile.vue +74 -0
- package/components/ui/auto-form/AutoFormFieldInput.vue +36 -0
- package/components/ui/auto-form/AutoFormFieldNumber.vue +32 -0
- package/components/ui/auto-form/AutoFormFieldObject.vue +78 -0
- package/components/ui/auto-form/AutoFormLabel.vue +14 -0
- package/components/ui/auto-form/constant.ts +40 -0
- package/components/ui/auto-form/dependencies.ts +93 -0
- package/components/ui/auto-form/index.ts +15 -0
- package/components/ui/auto-form/interface.ts +95 -0
- package/components/ui/auto-form/utils.ts +188 -0
- package/components/ui/avatar/Avatar.vue +22 -0
- package/components/ui/avatar/AvatarFallback.vue +12 -0
- package/components/ui/avatar/AvatarImage.vue +10 -0
- package/components/ui/avatar/index.ts +25 -0
- package/components/ui/badge/Badge.vue +17 -0
- package/components/ui/badge/index.ts +26 -0
- package/components/ui/breadcrumb/Breadcrumb.vue +13 -0
- package/components/ui/breadcrumb/BreadcrumbEllipsis.vue +22 -0
- package/components/ui/breadcrumb/BreadcrumbItem.vue +16 -0
- package/components/ui/breadcrumb/BreadcrumbLink.vue +20 -0
- package/components/ui/breadcrumb/BreadcrumbList.vue +16 -0
- package/components/ui/breadcrumb/BreadcrumbPage.vue +19 -0
- package/components/ui/breadcrumb/BreadcrumbSeparator.vue +21 -0
- package/components/ui/breadcrumb/index.ts +7 -0
- package/components/ui/button/Button.vue +4 -2
- package/components/ui/button/index.ts +9 -9
- package/components/ui/calendar/Calendar.vue +62 -0
- package/components/ui/calendar/CalendarCell.vue +26 -0
- package/components/ui/calendar/CalendarCellTrigger.vue +40 -0
- package/components/ui/calendar/CalendarGrid.vue +26 -0
- package/components/ui/calendar/CalendarGridBody.vue +12 -0
- package/components/ui/calendar/CalendarGridHead.vue +12 -0
- package/components/ui/calendar/CalendarGridRow.vue +23 -0
- package/components/ui/calendar/CalendarHeadCell.vue +23 -0
- package/components/ui/calendar/CalendarHeader.vue +23 -0
- package/components/ui/calendar/CalendarHeading.vue +33 -0
- package/components/ui/calendar/CalendarNextButton.vue +34 -0
- package/components/ui/calendar/CalendarPrevButton.vue +34 -0
- package/components/ui/calendar/index.ts +12 -0
- package/components/ui/card/Card.vue +21 -0
- package/components/ui/card/CardContent.vue +14 -0
- package/components/ui/card/CardDescription.vue +14 -0
- package/components/ui/card/CardFooter.vue +14 -0
- package/components/ui/card/CardHeader.vue +14 -0
- package/components/ui/card/CardTitle.vue +18 -0
- package/components/ui/card/index.ts +6 -0
- package/components/ui/carousel/Carousel.vue +3 -23
- package/components/ui/carousel/CarouselContent.vue +1 -2
- package/components/ui/carousel/CarouselItem.vue +5 -7
- package/components/ui/carousel/CarouselNext.vue +7 -9
- package/components/ui/carousel/CarouselPrevious.vue +7 -9
- package/components/ui/carousel/index.ts +3 -1
- package/components/ui/carousel/interface.ts +3 -1
- package/components/ui/carousel/useCarousel.ts +13 -23
- package/components/ui/chart/ChartCrosshair.vue +45 -0
- package/components/ui/chart/ChartLegend.vue +50 -0
- package/components/ui/chart/ChartSingleTooltip.vue +64 -0
- package/components/ui/chart/ChartTooltip.vue +40 -0
- package/components/ui/chart/index.ts +18 -0
- package/components/ui/chart/interface.ts +64 -0
- package/components/ui/chart-area/AreaChart.vue +141 -0
- package/components/ui/chart-area/index.ts +66 -0
- package/components/ui/chart-bar/BarChart.vue +116 -0
- package/components/ui/chart-bar/index.ts +66 -0
- package/components/ui/chart-donut/DonutChart.vue +101 -0
- package/components/ui/chart-donut/index.ts +39 -0
- package/components/ui/chart-line/LineChart.vue +107 -0
- package/components/ui/chart-line/index.ts +66 -0
- package/components/ui/checkbox/Checkbox.vue +1 -1
- package/components/ui/collapsible/Collapsible.vue +15 -0
- package/components/ui/collapsible/CollapsibleContent.vue +12 -0
- package/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
- package/components/ui/collapsible/index.ts +3 -0
- package/components/ui/command/Command.vue +31 -0
- package/components/ui/command/CommandDialog.vue +21 -0
- package/components/ui/command/CommandEmpty.vue +21 -0
- package/components/ui/command/CommandGroup.vue +30 -0
- package/components/ui/command/CommandInput.vue +35 -0
- package/components/ui/command/CommandItem.vue +27 -0
- package/components/ui/command/CommandList.vue +28 -0
- package/components/ui/command/CommandSeparator.vue +24 -0
- package/components/ui/command/CommandShortcut.vue +14 -0
- package/components/ui/command/index.ts +9 -0
- package/components/ui/context-menu/ContextMenu.vue +15 -0
- package/components/ui/context-menu/ContextMenuCheckboxItem.vue +41 -0
- package/components/ui/context-menu/ContextMenuContent.vue +37 -0
- package/components/ui/context-menu/ContextMenuGroup.vue +12 -0
- package/components/ui/context-menu/ContextMenuItem.vue +35 -0
- package/components/ui/context-menu/ContextMenuLabel.vue +27 -0
- package/components/ui/context-menu/ContextMenuPortal.vue +12 -0
- package/components/ui/context-menu/ContextMenuRadioGroup.vue +19 -0
- package/components/ui/context-menu/ContextMenuRadioItem.vue +41 -0
- package/components/ui/context-menu/ContextMenuSeparator.vue +22 -0
- package/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
- package/components/ui/context-menu/ContextMenuSub.vue +19 -0
- package/components/ui/context-menu/ContextMenuSubContent.vue +36 -0
- package/components/ui/context-menu/ContextMenuSubTrigger.vue +36 -0
- package/components/ui/context-menu/ContextMenuTrigger.vue +14 -0
- package/components/ui/context-menu/index.ts +14 -0
- package/components/ui/dialog/Dialog.vue +2 -6
- package/components/ui/dialog/DialogClose.vue +2 -1
- package/components/ui/dialog/DialogContent.vue +10 -12
- package/components/ui/dialog/DialogDescription.vue +6 -10
- package/components/ui/dialog/DialogScrollContent.vue +15 -21
- package/components/ui/dialog/DialogTitle.vue +9 -6
- package/components/ui/dialog/DialogTrigger.vue +2 -1
- package/components/ui/drawer/Drawer.vue +19 -0
- package/components/ui/drawer/DrawerContent.vue +28 -0
- package/components/ui/drawer/DrawerDescription.vue +21 -0
- package/components/ui/drawer/DrawerFooter.vue +14 -0
- package/components/ui/drawer/DrawerHeader.vue +14 -0
- package/components/ui/drawer/DrawerOverlay.vue +19 -0
- package/components/ui/drawer/DrawerTitle.vue +21 -0
- package/components/ui/drawer/index.ts +8 -0
- package/components/ui/dropdown-menu/DropdownMenu.vue +15 -0
- package/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +41 -0
- package/components/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
- package/components/ui/dropdown-menu/DropdownMenuGroup.vue +12 -0
- package/components/ui/dropdown-menu/DropdownMenuItem.vue +30 -0
- package/components/ui/dropdown-menu/DropdownMenuLabel.vue +26 -0
- package/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
- package/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +42 -0
- package/components/ui/dropdown-menu/DropdownMenuSeparator.vue +24 -0
- package/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
- package/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
- package/components/ui/dropdown-menu/DropdownMenuSubContent.vue +31 -0
- package/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +35 -0
- package/components/ui/dropdown-menu/DropdownMenuTrigger.vue +14 -0
- package/components/ui/dropdown-menu/index.ts +16 -0
- package/components/ui/form/FormControl.vue +16 -0
- package/components/ui/form/FormDescription.vue +20 -0
- package/components/ui/form/FormItem.vue +20 -0
- package/components/ui/form/FormLabel.vue +23 -0
- package/components/ui/form/FormMessage.vue +16 -0
- package/components/ui/form/index.ts +7 -0
- package/components/ui/form/injectionKeys.ts +4 -0
- package/components/ui/form/useFormField.ts +30 -0
- package/components/ui/hover-card/HoverCard.vue +15 -0
- package/components/ui/hover-card/HoverCardContent.vue +43 -0
- package/components/ui/hover-card/HoverCardTrigger.vue +12 -0
- package/components/ui/hover-card/index.ts +3 -0
- package/components/ui/input/Input.vue +1 -1
- package/components/ui/menubar/Menubar.vue +36 -0
- package/components/ui/menubar/MenubarCheckboxItem.vue +41 -0
- package/components/ui/menubar/MenubarContent.vue +45 -0
- package/components/ui/menubar/MenubarGroup.vue +12 -0
- package/components/ui/menubar/MenubarItem.vue +36 -0
- package/components/ui/menubar/MenubarLabel.vue +14 -0
- package/components/ui/menubar/MenubarMenu.vue +12 -0
- package/components/ui/menubar/MenubarRadioGroup.vue +20 -0
- package/components/ui/menubar/MenubarRadioItem.vue +41 -0
- package/components/ui/menubar/MenubarSeparator.vue +21 -0
- package/components/ui/menubar/MenubarShortcut.vue +14 -0
- package/components/ui/menubar/MenubarSub.vue +20 -0
- package/components/ui/menubar/MenubarSubContent.vue +40 -0
- package/components/ui/menubar/MenubarSubTrigger.vue +32 -0
- package/components/ui/menubar/MenubarTrigger.vue +31 -0
- package/components/ui/menubar/index.ts +15 -0
- package/components/ui/navigation-menu/NavigationMenu.vue +34 -0
- package/components/ui/navigation-menu/NavigationMenuContent.vue +35 -0
- package/components/ui/navigation-menu/NavigationMenuIndicator.vue +26 -0
- package/components/ui/navigation-menu/NavigationMenuItem.vue +12 -0
- package/components/ui/navigation-menu/NavigationMenuLink.vue +19 -0
- package/components/ui/navigation-menu/NavigationMenuList.vue +31 -0
- package/components/ui/navigation-menu/NavigationMenuTrigger.vue +36 -0
- package/components/ui/navigation-menu/NavigationMenuViewport.vue +35 -0
- package/components/ui/navigation-menu/index.ts +14 -0
- package/components/ui/number-field/NumberField.vue +24 -0
- package/components/ui/number-field/NumberFieldContent.vue +14 -0
- package/components/ui/number-field/NumberFieldDecrement.vue +26 -0
- package/components/ui/number-field/NumberFieldIncrement.vue +26 -0
- package/components/ui/number-field/NumberFieldInput.vue +16 -0
- package/components/ui/number-field/index.ts +5 -0
- package/components/ui/pagination/PaginationEllipsis.vue +24 -0
- package/components/ui/pagination/PaginationFirst.vue +31 -0
- package/components/ui/pagination/PaginationLast.vue +31 -0
- package/components/ui/pagination/PaginationNext.vue +31 -0
- package/components/ui/pagination/PaginationPrev.vue +31 -0
- package/components/ui/pagination/index.ts +10 -0
- package/components/ui/pin-input/PinInput.vue +25 -0
- package/components/ui/pin-input/PinInputGroup.vue +20 -0
- package/components/ui/pin-input/PinInputInput.vue +20 -0
- package/components/ui/pin-input/PinInputSeparator.vue +16 -0
- package/components/ui/pin-input/index.ts +4 -0
- package/components/ui/popover/Popover.vue +15 -0
- package/components/ui/popover/PopoverContent.vue +49 -0
- package/components/ui/popover/PopoverTrigger.vue +12 -0
- package/components/ui/popover/index.ts +3 -0
- package/components/ui/progress/Progress.vue +41 -0
- package/components/ui/progress/index.ts +1 -0
- package/components/ui/radio-group/RadioGroupItem.vue +1 -1
- package/components/ui/range-calendar/RangeCalendar.vue +62 -0
- package/components/ui/range-calendar/RangeCalendarCell.vue +26 -0
- package/components/ui/range-calendar/RangeCalendarCellTrigger.vue +42 -0
- package/components/ui/range-calendar/RangeCalendarGrid.vue +26 -0
- package/components/ui/range-calendar/RangeCalendarGridBody.vue +12 -0
- package/components/ui/range-calendar/RangeCalendarGridHead.vue +12 -0
- package/components/ui/range-calendar/RangeCalendarGridRow.vue +23 -0
- package/components/ui/range-calendar/RangeCalendarHeadCell.vue +23 -0
- package/components/ui/range-calendar/RangeCalendarHeader.vue +23 -0
- package/components/ui/range-calendar/RangeCalendarHeading.vue +33 -0
- package/components/ui/range-calendar/RangeCalendarNextButton.vue +34 -0
- package/components/ui/range-calendar/RangeCalendarPrevButton.vue +34 -0
- package/components/ui/range-calendar/index.ts +12 -0
- package/components/ui/resizable/ResizableHandle.vue +28 -0
- package/components/ui/resizable/ResizablePanelGroup.vue +23 -0
- package/components/ui/resizable/index.ts +3 -0
- package/components/ui/scroll-area/ScrollArea.vue +31 -0
- package/components/ui/scroll-area/ScrollBar.vue +32 -0
- package/components/ui/scroll-area/index.ts +2 -0
- package/components/ui/select/SelectContent.vue +1 -1
- package/components/ui/select/SelectItem.vue +1 -1
- package/components/ui/select/SelectSeparator.vue +1 -1
- package/components/ui/select/SelectTrigger.vue +1 -1
- package/components/ui/separator/Separator.vue +37 -0
- package/components/ui/separator/index.ts +1 -0
- package/components/ui/sheet/Sheet.vue +15 -0
- package/components/ui/sheet/SheetClose.vue +12 -0
- package/components/ui/sheet/SheetContent.vue +58 -0
- package/components/ui/sheet/SheetDescription.vue +24 -0
- package/components/ui/sheet/SheetFooter.vue +19 -0
- package/components/ui/sheet/SheetHeader.vue +16 -0
- package/components/ui/sheet/SheetTitle.vue +24 -0
- package/components/ui/sheet/SheetTrigger.vue +12 -0
- package/components/ui/sheet/index.ts +32 -0
- package/components/ui/sidebar/Sidebar.vue +85 -0
- package/components/ui/sidebar/SidebarContent.vue +17 -0
- package/components/ui/sidebar/SidebarFooter.vue +17 -0
- package/components/ui/sidebar/SidebarGroup.vue +17 -0
- package/components/ui/sidebar/SidebarGroupAction.vue +26 -0
- package/components/ui/sidebar/SidebarGroupContent.vue +17 -0
- package/components/ui/sidebar/SidebarGroupLabel.vue +24 -0
- package/components/ui/sidebar/SidebarHeader.vue +17 -0
- package/components/ui/sidebar/SidebarInput.vue +21 -0
- package/components/ui/sidebar/SidebarInset.vue +20 -0
- package/components/ui/sidebar/SidebarMenu.vue +17 -0
- package/components/ui/sidebar/SidebarMenuAction.vue +34 -0
- package/components/ui/sidebar/SidebarMenuBadge.vue +25 -0
- package/components/ui/sidebar/SidebarMenuButton.vue +51 -0
- package/components/ui/sidebar/SidebarMenuButtonChild.vue +35 -0
- package/components/ui/sidebar/SidebarMenuItem.vue +17 -0
- package/components/ui/sidebar/SidebarMenuSkeleton.vue +34 -0
- package/components/ui/sidebar/SidebarMenuSub.vue +21 -0
- package/components/ui/sidebar/SidebarMenuSubButton.vue +35 -0
- package/components/ui/sidebar/SidebarMenuSubItem.vue +8 -0
- package/components/ui/sidebar/SidebarProvider.vue +81 -0
- package/components/ui/sidebar/SidebarRail.vue +32 -0
- package/components/ui/sidebar/SidebarSeparator.vue +18 -0
- package/components/ui/sidebar/SidebarTrigger.vue +26 -0
- package/components/ui/sidebar/index.ts +60 -0
- package/components/ui/sidebar/utils.ts +19 -0
- package/components/ui/skeleton/Skeleton.vue +14 -0
- package/components/ui/skeleton/index.ts +1 -0
- package/components/ui/slider/Slider.vue +37 -0
- package/components/ui/slider/index.ts +1 -0
- package/components/ui/sonner/Sonner.vue +23 -0
- package/components/ui/sonner/index.ts +1 -0
- package/components/ui/stepper/Stepper.vue +32 -0
- package/components/ui/stepper/StepperDescription.vue +24 -0
- package/components/ui/stepper/StepperIndicator.vue +36 -0
- package/components/ui/stepper/StepperItem.vue +28 -0
- package/components/ui/stepper/StepperSeparator.vue +32 -0
- package/components/ui/stepper/StepperTitle.vue +24 -0
- package/components/ui/stepper/StepperTrigger.vue +27 -0
- package/components/ui/stepper/index.ts +7 -0
- package/components/ui/switch/Switch.vue +40 -0
- package/components/ui/switch/index.ts +1 -0
- package/components/ui/table/Table.vue +16 -0
- package/components/ui/table/TableBody.vue +14 -0
- package/components/ui/table/TableCaption.vue +14 -0
- package/components/ui/table/TableCell.vue +21 -0
- package/components/ui/table/TableEmpty.vue +38 -0
- package/components/ui/table/TableFooter.vue +14 -0
- package/components/ui/table/TableHead.vue +14 -0
- package/components/ui/table/TableHeader.vue +14 -0
- package/components/ui/table/TableRow.vue +14 -0
- package/components/ui/table/index.ts +9 -0
- package/components/ui/tabs/TabsContent.vue +6 -11
- package/components/ui/tabs/TabsList.vue +8 -8
- package/components/ui/tabs/TabsTrigger.vue +9 -11
- package/components/ui/tags-input/TagsInput.vue +24 -0
- package/components/ui/tags-input/TagsInputInput.vue +21 -0
- package/components/ui/tags-input/TagsInputItem.vue +24 -0
- package/components/ui/tags-input/TagsInputItemDelete.vue +26 -0
- package/components/ui/tags-input/TagsInputItemText.vue +21 -0
- package/components/ui/tags-input/index.ts +5 -0
- package/components/ui/textarea/Textarea.vue +1 -1
- package/components/ui/toast/Toast.vue +30 -0
- package/components/ui/toast/ToastAction.vue +21 -0
- package/components/ui/toast/ToastClose.vue +24 -0
- package/components/ui/toast/ToastDescription.vue +21 -0
- package/components/ui/toast/ToastProvider.vue +12 -0
- package/components/ui/toast/ToastTitle.vue +21 -0
- package/components/ui/toast/ToastViewport.vue +19 -0
- package/components/ui/toast/Toaster.vue +30 -0
- package/components/ui/toast/index.ts +39 -0
- package/components/ui/toast/use-toast.ts +165 -0
- package/components/ui/toggle/Toggle.vue +38 -0
- package/components/ui/toggle/index.ts +28 -0
- package/components/ui/toggle-group/ToggleGroup.vue +36 -0
- package/components/ui/toggle-group/ToggleGroupItem.vue +37 -0
- package/components/ui/toggle-group/index.ts +2 -0
- package/components/ui/tooltip/Tooltip.vue +15 -0
- package/components/ui/tooltip/TooltipContent.vue +33 -0
- package/components/ui/tooltip/TooltipProvider.vue +12 -0
- package/components/ui/tooltip/TooltipTrigger.vue +12 -0
- package/components/ui/tooltip/index.ts +4 -0
- package/components/ui/v-calendar/Calendar.vue +343 -0
- package/components/ui/v-calendar/index.ts +22 -0
- package/composables/useAccordionScroll.ts +1 -1
- package/composables/useContentSearch.ts +0 -0
- package/composables/useGlobalConfig.ts +57 -0
- package/composables/useGraphqlCacheability.ts +22 -0
- package/composables/useImageSources.ts +208 -0
- package/composables/useInitData.ts +20 -112
- package/composables/useMediaLightbox.ts +114 -0
- package/composables/useMenu.ts +66 -0
- package/composables/useMessageBus.ts +74 -0
- package/composables/useNavigationOffset.ts +1 -1
- package/layouts/default.vue +2 -2
- package/layouts/error.vue +8 -10
- package/modules/dynamicEntityComponentResolver.ts +162 -0
- package/modules/dynamicParagraphResolver.ts +1 -1
- package/nuxt.config.ts +11 -22
- package/package.json +2 -2
- package/pages/[...slug]/index.vue +2 -2
- package/pages/index.vue +2 -2
- package/pages/node/[nid]/index.vue +2 -2
- package/plugins/graphqlMiddleware.ts +27 -68
- package/plugins/initData.ts +105 -0
- package/queries/query.contentSearch.graphql +17 -0
- package/{composables → queries}/query.initData.graphql +2 -8
- package/queries/query.loadTranslations.graphql +5 -0
- package/tailwind.config.ts +1 -0
- package/types/initData.ts +1 -0
- package/components/Section/Header/SearchLink.vue +0 -26
- package/composables/languageLinks.ts +0 -31
- package/composables/useMainMenuLinks.ts +0 -69
- package/composables/useMetaMenuLinks.ts +0 -44
- package/modules/dynamicNodeResolver.ts +0 -95
- package/pages/search/index.vue +0 -69
- package/pages/static-page/example.vue +0 -40
- package/queries/fragment.routeQuery.graphql +0 -51
|
@@ -1,118 +1,26 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
footerMenuLinks: MenuLinkTreeElementFirstFragment[]
|
|
11
|
-
footerMetaMenuLinks: MenuLinkTreeElementFirstFragment[]
|
|
12
|
-
translations: Record<string, string | [string, string]>
|
|
13
|
-
globalConfig: {
|
|
14
|
-
companyLogo?: GlobalConfigFragment['companyLogo']
|
|
15
|
-
companyLogoAlt?: GlobalConfigFragment['companyLogoAlt']
|
|
16
|
-
companyName?: GlobalConfigFragment['companyName']
|
|
17
|
-
companyDescription?: GlobalConfigFragment['companyDescription']
|
|
18
|
-
address?: GlobalConfigFragment['address']
|
|
19
|
-
phoneNumber?: GlobalConfigFragment['phoneNumber']
|
|
20
|
-
emailAddress?: GlobalConfigFragment['emailAddress']
|
|
21
|
-
metaLinks?: GlobalConfigFragment['metaLinks']
|
|
22
|
-
contactButtons?: GlobalConfigFragment['contactButtons']
|
|
23
|
-
socialMediaLinks?: GlobalConfigFragment['socialMediaLinks']
|
|
1
|
+
import type { InitData, MappedMenuLink } from '../plugins/initData'
|
|
2
|
+
|
|
3
|
+
export type UseInitData = {
|
|
4
|
+
globalConfig: ComputedRef<InitData['globalConfig']>
|
|
5
|
+
menus: {
|
|
6
|
+
metaMenu: ComputedRef<MappedMenuLink[]>
|
|
7
|
+
mainMenu: ComputedRef<MappedMenuLink[]>
|
|
8
|
+
footerMenu: ComputedRef<MappedMenuLink[]>
|
|
9
|
+
footerMetaMenu: ComputedRef<MappedMenuLink[]>
|
|
24
10
|
}
|
|
25
11
|
}
|
|
26
12
|
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
): Record<string, string | [string, string]> {
|
|
30
|
-
if (!v) {
|
|
31
|
-
return {}
|
|
32
|
-
}
|
|
33
|
-
return Object.entries(
|
|
34
|
-
(v.translations || {}) as Record<
|
|
35
|
-
string,
|
|
36
|
-
string | { singular?: string; plural?: string }
|
|
37
|
-
>,
|
|
38
|
-
).reduce<Record<string, string | [string, string]>>(
|
|
39
|
-
(acc, [fullKey, value]) => {
|
|
40
|
-
const keyWithDots = fullKey.replace('__', '.')
|
|
41
|
-
if (typeof value === 'string') {
|
|
42
|
-
acc[keyWithDots] = value
|
|
43
|
-
} else if (typeof value === 'object' && value.plural && value.singular) {
|
|
44
|
-
acc[keyWithDots] = [value.singular, value.plural]
|
|
45
|
-
}
|
|
46
|
-
return acc
|
|
47
|
-
},
|
|
48
|
-
{},
|
|
49
|
-
)
|
|
50
|
-
}
|
|
13
|
+
export default function (): UseInitData {
|
|
14
|
+
const data = useState<InitData | null>('initData', () => null)
|
|
51
15
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
'initData_' + currentLanguage.value,
|
|
60
|
-
event,
|
|
61
|
-
)
|
|
62
|
-
if (value) {
|
|
63
|
-
data.value = value
|
|
64
|
-
return data
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// If the data is not in the cache, we fetch it from the payload / useState().
|
|
68
|
-
if (data.value) {
|
|
69
|
-
return data
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const config = useRuntimeConfig()
|
|
73
|
-
// Read the host from .env NUXT_HOST to support multisite setup.
|
|
74
|
-
// Read the host from .env NUXT_HOST to support multisite setup.
|
|
75
|
-
const url = useRequestURL()
|
|
76
|
-
let host = url.hostname
|
|
77
|
-
if (import.meta.server) {
|
|
78
|
-
host = config.requestHost
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Fetch the data from the server.
|
|
82
|
-
data.value = await useGraphqlQuery({
|
|
83
|
-
name: 'initData',
|
|
84
|
-
fetchOptions: {
|
|
85
|
-
query: {
|
|
86
|
-
language: currentLanguage.value,
|
|
87
|
-
__server: 'true',
|
|
88
|
-
},
|
|
89
|
-
headers: {
|
|
90
|
-
host,
|
|
91
|
-
'x-forwarded-host': host,
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
}).then((v) => {
|
|
95
|
-
const initData = {
|
|
96
|
-
metaMenuLinks: v.data.metaMenu?.links || [],
|
|
97
|
-
mainMenuLinks: v.data.mainMenu?.links || [],
|
|
98
|
-
footerMenuLinks: v.data.footerMenu?.links || [],
|
|
99
|
-
footerMetaMenuLinks: v.data.footerMetaMenu?.links || [],
|
|
100
|
-
globalConfig: v.data.globalConfig || {},
|
|
101
|
-
translations: getTranslations(v.data),
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// The cache tags are coming from the onServerResponse() function in the graphqlMiddleware.
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
import.meta.server &&
|
|
108
|
-
v.__cacheability?.isCacheable &&
|
|
109
|
-
v.__cacheability.tagsNuxt
|
|
110
|
-
) {
|
|
111
|
-
addToCache(initData, v.__cacheability.tagsNuxt)
|
|
16
|
+
return {
|
|
17
|
+
globalConfig: computed(() => data.value?.globalConfig || {}),
|
|
18
|
+
menus: {
|
|
19
|
+
metaMenu: computed(() => data.value?.metaMenuLinks || []),
|
|
20
|
+
mainMenu: computed(() => data.value?.mainMenuLinks || []),
|
|
21
|
+
footerMenu: computed(() => data.value?.footerMenuLinks || []),
|
|
22
|
+
footerMetaMenu: computed(() => data.value?.footerMetaMenuLinks || []),
|
|
112
23
|
}
|
|
113
|
-
|
|
114
|
-
return initData
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
return data
|
|
24
|
+
}
|
|
118
25
|
}
|
|
26
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { MediaFragment } from '#graphql-operations'
|
|
2
|
+
|
|
3
|
+
export function useMediaLightbox(media: (MediaFragment | null)[] | undefined) {
|
|
4
|
+
const isOpen = ref(false)
|
|
5
|
+
const currentIndex = ref(0)
|
|
6
|
+
|
|
7
|
+
const openLightbox = (index: number) => {
|
|
8
|
+
currentIndex.value = index
|
|
9
|
+
isOpen.value = true
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const closeLightbox = () => {
|
|
13
|
+
isOpen.value = false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const setCurrentIndex = (index: number) => {
|
|
17
|
+
currentIndex.value = index
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// For backward compatibility with the old fsLightbox API
|
|
21
|
+
const toggleLightbox = computed({
|
|
22
|
+
get: () => isOpen.value,
|
|
23
|
+
set: (value: boolean) => {
|
|
24
|
+
isOpen.value = value
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
// For backward compatibility - fsLightbox used 1-based indexing
|
|
29
|
+
const currentSlide = computed({
|
|
30
|
+
get: () => currentIndex.value + 1,
|
|
31
|
+
set: (value: number) => {
|
|
32
|
+
currentIndex.value = value - 1
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// Copy exact logic from the working composable
|
|
37
|
+
const computedMedia = computed(() =>
|
|
38
|
+
media?.map(item => {
|
|
39
|
+
if (!item) return ''
|
|
40
|
+
switch (item.type) {
|
|
41
|
+
case 'MediaImage':
|
|
42
|
+
return (item as any).sourceUrl?.path || ''
|
|
43
|
+
case 'MediaVideo':
|
|
44
|
+
return (item as any).url?.path || ''
|
|
45
|
+
case 'MediaRemoteVideo':
|
|
46
|
+
return (item as any).link || ''
|
|
47
|
+
default:
|
|
48
|
+
return ''
|
|
49
|
+
}
|
|
50
|
+
}).filter(Boolean) || []
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
// Expose filtered media objects for Media components
|
|
54
|
+
const mediaObjects = computed(() => media?.filter(Boolean) || [])
|
|
55
|
+
|
|
56
|
+
// Copy exact logic from the working composable
|
|
57
|
+
const computedCustomAttributes = computed(() =>
|
|
58
|
+
media?.map(item => {
|
|
59
|
+
if (!item) return {}
|
|
60
|
+
|
|
61
|
+
switch (item.type) {
|
|
62
|
+
case 'MediaImage':
|
|
63
|
+
return {
|
|
64
|
+
alt: (item as any).alt?.alt || '',
|
|
65
|
+
title: item.title || ''
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
case 'MediaVideo':
|
|
69
|
+
return {
|
|
70
|
+
alt: ((item as any).thumbnailOverride || (item as any).thumbnail)?.alt || '',
|
|
71
|
+
title: item.title || '',
|
|
72
|
+
poster: ((item as any).thumbnailOverride || (item as any).thumbnail)?.entity?.uri?.first?.url || '',
|
|
73
|
+
controls: true
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
case 'MediaRemoteVideo':
|
|
77
|
+
return {
|
|
78
|
+
alt: ((item as any).thumbnailOverride || (item as any).thumbnail)?.alt || '',
|
|
79
|
+
title: item.title || '',
|
|
80
|
+
poster: ((item as any).thumbnailOverride || (item as any).thumbnail)?.entity?.uri?.first?.url || ''
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
default:
|
|
84
|
+
return {}
|
|
85
|
+
}
|
|
86
|
+
}) || []
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// Copy exact logic from the working composable
|
|
90
|
+
const computedCaptions = computed(() =>
|
|
91
|
+
media?.map(item => (item as any)?.caption || '') || []
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
// New API for custom lightbox
|
|
96
|
+
isOpen: readonly(isOpen),
|
|
97
|
+
currentIndex: readonly(currentIndex),
|
|
98
|
+
openLightbox,
|
|
99
|
+
closeLightbox,
|
|
100
|
+
setCurrentIndex,
|
|
101
|
+
|
|
102
|
+
// Backward compatibility with fsLightbox API
|
|
103
|
+
toggleLightbox,
|
|
104
|
+
currentSlide,
|
|
105
|
+
|
|
106
|
+
// Data for lightbox component
|
|
107
|
+
sources: computedMedia,
|
|
108
|
+
customAttributes: computedCustomAttributes,
|
|
109
|
+
captions: computedCaptions,
|
|
110
|
+
|
|
111
|
+
// Media objects for Media components
|
|
112
|
+
mediaObjects
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { MappedMenuLink } from '../plugins/initData'
|
|
2
|
+
import type { MenuName } from '../types/initData'
|
|
3
|
+
|
|
4
|
+
function isLinkTreeActive(
|
|
5
|
+
tree: MappedMenuLink & { subtree?: Array<MappedMenuLink> },
|
|
6
|
+
currentRoutePath: string,
|
|
7
|
+
): boolean {
|
|
8
|
+
if (tree.href === currentRoutePath) {
|
|
9
|
+
return true
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (tree.subtree) {
|
|
13
|
+
return tree.subtree.some((subtreeEl) =>
|
|
14
|
+
isLinkTreeActive(subtreeEl, currentRoutePath),
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function useMenu(menuName: MenuName) {
|
|
22
|
+
const { menus } = useInitData()
|
|
23
|
+
|
|
24
|
+
const menuLinks = menus[menuName]
|
|
25
|
+
const currentRoute = useRoute()
|
|
26
|
+
|
|
27
|
+
const menuItems = computed(() => {
|
|
28
|
+
return menuLinks.value
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const menuItemActive = computed(() => {
|
|
32
|
+
return menuLinks.value.find((l) =>
|
|
33
|
+
isLinkTreeActive(l, currentRoute.path),
|
|
34
|
+
)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const menuItemActiveLevel1 = computed(() => {
|
|
38
|
+
return menuItemActive.value?.children?.find((l) =>
|
|
39
|
+
isLinkTreeActive(l, currentRoute.path),
|
|
40
|
+
)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const menuItemActiveLevel2 = computed(() => {
|
|
44
|
+
const activeSubtree = menuItemActiveLevel1.value?.children
|
|
45
|
+
if (activeSubtree) {
|
|
46
|
+
return activeSubtree.find((l) => isLinkTreeActive(l, currentRoute.path))
|
|
47
|
+
}
|
|
48
|
+
return null
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const menuTiemActiveLevel3 = computed(() => {
|
|
52
|
+
const activeSubtree = menuItemActiveLevel2.value?.children
|
|
53
|
+
if (activeSubtree) {
|
|
54
|
+
return activeSubtree.find((l) => isLinkTreeActive(l, currentRoute.path))
|
|
55
|
+
}
|
|
56
|
+
return null
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
menuItems,
|
|
61
|
+
menuItemActive,
|
|
62
|
+
menuItemActiveLevel1,
|
|
63
|
+
menuItemActiveLevel2,
|
|
64
|
+
menuTiemActiveLevel3,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Bus Composable
|
|
3
|
+
*
|
|
4
|
+
* This composable provides a simple in-memory message bus for communication between components.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* import { useMessageBus } from '#imports'
|
|
8
|
+
* const { bus, send, receive } = useMessageBus()
|
|
9
|
+
*
|
|
10
|
+
* // Send a message
|
|
11
|
+
* send('Hello World', 'receiverId', 'typeId')
|
|
12
|
+
*
|
|
13
|
+
* // Receive messages
|
|
14
|
+
* const messages = receive('receiverId', 'typeId')
|
|
15
|
+
*
|
|
16
|
+
* API:
|
|
17
|
+
* - bus: Ref<Array<BusMessage>>
|
|
18
|
+
* - send(message, receiver?, type?)
|
|
19
|
+
* - receive(receiver?, type?): BusMessage[]
|
|
20
|
+
*
|
|
21
|
+
* BusMessage:
|
|
22
|
+
* - receiver?: string
|
|
23
|
+
* - type?: string
|
|
24
|
+
* - message: any
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Represents a message sent through the message bus.
|
|
29
|
+
*/
|
|
30
|
+
export type BusMessage = {
|
|
31
|
+
receiver?: string
|
|
32
|
+
type?: string
|
|
33
|
+
message?: any
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const messageBus: Ref<Array<BusMessage>> = ref([]);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Sends a message to the message bus.
|
|
40
|
+
*
|
|
41
|
+
* @param message - The message payload to send.
|
|
42
|
+
* @param receiver - Optional receiver identifier.
|
|
43
|
+
* @param type - Optional message type identifier.
|
|
44
|
+
*/
|
|
45
|
+
function send(message: any, receiver?: string, type?: string) {
|
|
46
|
+
messageBus.value.push({ receiver, type, message });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Retrieves messages from the message bus matching the given receiver and type.
|
|
51
|
+
* Returns a deep clone of the matched messages.
|
|
52
|
+
*
|
|
53
|
+
* @param receiver - Optional receiver identifier to filter messages.
|
|
54
|
+
* @param type - Optional type identifier to filter messages.
|
|
55
|
+
* @returns Array of matching BusMessage objects (deep cloned).
|
|
56
|
+
*/
|
|
57
|
+
function receive(receiver?: string, type?: string): BusMessage[] {
|
|
58
|
+
return messageBus.value.filter(
|
|
59
|
+
msg => (receiver === undefined || msg.receiver === receiver) && (type === undefined || msg.type === type)
|
|
60
|
+
).map(msg => ({ ...msg, message: JSON.parse(JSON.stringify(msg.message)) }));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Provides access to the message bus, including send and receive functions.
|
|
65
|
+
*
|
|
66
|
+
* @returns An object containing the bus ref, send, and receive functions.
|
|
67
|
+
*/
|
|
68
|
+
export function useMessageBus() {
|
|
69
|
+
return {
|
|
70
|
+
bus: messageBus,
|
|
71
|
+
send,
|
|
72
|
+
receive,
|
|
73
|
+
};
|
|
74
|
+
}
|
package/layouts/default.vue
CHANGED
package/layouts/error.vue
CHANGED
|
@@ -6,16 +6,15 @@
|
|
|
6
6
|
@menu:close:finished="menuCloseFinish"
|
|
7
7
|
/>
|
|
8
8
|
|
|
9
|
-
<NuxtPageDependency>
|
|
9
|
+
<!-- <NuxtPageDependency>
|
|
10
10
|
<DrupalBreadcrumb v-if="showBreadcrumb" :links="breadcrumb" />
|
|
11
|
-
</NuxtPageDependency>
|
|
11
|
+
</NuxtPageDependency> -->
|
|
12
12
|
|
|
13
13
|
<div>
|
|
14
14
|
<ClientOnly>
|
|
15
15
|
<DrupalMessages v-if="!isEditing" />
|
|
16
16
|
</ClientOnly>
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
<div class="container mx-auto grid grid-cols-1 gap-6 py-12">
|
|
20
19
|
<div class="ck-editor text-center">
|
|
21
20
|
<h1>Whooops!</h1>
|
|
@@ -24,10 +23,10 @@
|
|
|
24
23
|
class="mt-8 inline-block underline"
|
|
25
24
|
:to="`/${currentLanguage}`"
|
|
26
25
|
prefetch
|
|
27
|
-
>Go back to home</NuxtLink
|
|
26
|
+
>Go back to home</NuxtLink
|
|
27
|
+
>
|
|
28
28
|
</div>
|
|
29
29
|
</div>
|
|
30
|
-
|
|
31
30
|
</div>
|
|
32
31
|
<SectionFooter />
|
|
33
32
|
</div>
|
|
@@ -57,7 +56,7 @@ const error = useError()
|
|
|
57
56
|
const errorCode = error.value?.statusCode || 'Unknown error'
|
|
58
57
|
|
|
59
58
|
const errorMessages = {
|
|
60
|
-
404:
|
|
59
|
+
404: "We can't find the page \nyou are looking for.",
|
|
61
60
|
500: 'An error occurred on the server. Please try again later.',
|
|
62
61
|
'Unknown error': 'An unknown error occurred.',
|
|
63
62
|
}
|
|
@@ -67,10 +66,10 @@ const errorMessage = computed(() => {
|
|
|
67
66
|
return errorMessages[errorCode]
|
|
68
67
|
}
|
|
69
68
|
return errorMessages['Unknown error']
|
|
70
|
-
})
|
|
69
|
+
})
|
|
71
70
|
|
|
72
71
|
useHead({
|
|
73
|
-
title: errorMessage
|
|
72
|
+
title: errorMessage,
|
|
74
73
|
})
|
|
75
74
|
|
|
76
75
|
const isMenuOpen = ref(false)
|
|
@@ -94,5 +93,4 @@ function menuCloseFinish() {
|
|
|
94
93
|
hasMenuFinishedClosing.value = true
|
|
95
94
|
}
|
|
96
95
|
}
|
|
97
|
-
|
|
98
|
-
</script>
|
|
96
|
+
</script>
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nuxt Layer Module: dynamicEntityComponentResolver
|
|
3
|
+
*
|
|
4
|
+
* Dynamically imports all Node components from every enabled Nuxt layer (including the main app),
|
|
5
|
+
* supports both single-file and index.vue conventions, and injects a dynamic resolver with
|
|
6
|
+
* proper override priority (main app overrides layers).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { defineNuxtModule, addPlugin, addTemplate, createResolver } from '@nuxt/kit'
|
|
10
|
+
import { join } from 'pathe'
|
|
11
|
+
|
|
12
|
+
export default defineNuxtModule({
|
|
13
|
+
meta: { name: 'dynamicEntityComponentResolver' },
|
|
14
|
+
setup(_options, nuxt) {
|
|
15
|
+
const { resolve } = createResolver(import.meta.url)
|
|
16
|
+
|
|
17
|
+
// Gather all layer root directories (main app is always first)
|
|
18
|
+
const appRoot = nuxt.options.rootDir
|
|
19
|
+
const layerDirs = nuxt.options._layers
|
|
20
|
+
.map(layer => layer.cwd.replace(appRoot, '').length ? layer.cwd.replace(appRoot, '') : '/')
|
|
21
|
+
|
|
22
|
+
// Helper to get icms config from a layer
|
|
23
|
+
function getLayerPageComponentTypes(layer) {
|
|
24
|
+
return (layer.config && layer.config.icms && Array.isArray(layer.config.icms.pageComponentTypes))
|
|
25
|
+
? layer.config.icms.pageComponentTypes
|
|
26
|
+
: [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Gather pageComponentTypes from all layers and main app
|
|
30
|
+
// @ts-ignore: allow access to icms
|
|
31
|
+
const allTypes = [Array.isArray(nuxt.options.icms?.pageComponentTypes) ? nuxt.options.icms.pageComponentTypes : []]
|
|
32
|
+
.concat(nuxt.options._layers.map(getLayerPageComponentTypes))
|
|
33
|
+
.flat()
|
|
34
|
+
.filter((v, i, arr) => arr.indexOf(v) === i); // dedupe
|
|
35
|
+
|
|
36
|
+
// Generate import.meta.glob for each layer's components for each type
|
|
37
|
+
const imports = layerDirs.map((dir, i) => {
|
|
38
|
+
return allTypes.map(type => {
|
|
39
|
+
const componentsPath = join(dir, `components/${type}/**/*.vue`)
|
|
40
|
+
return `const modules${i}_${type} = import.meta.glob(${JSON.stringify(componentsPath)});`;
|
|
41
|
+
}).join('\n');
|
|
42
|
+
}).join('\n');
|
|
43
|
+
|
|
44
|
+
// Merge logic (reverse order so main app overrides layers)
|
|
45
|
+
const mergeLogic = layerDirs
|
|
46
|
+
.map((_, i) => {
|
|
47
|
+
return allTypes.map(type => `
|
|
48
|
+
for (const path in modules${i}_${type}) {
|
|
49
|
+
const name = getComponentNameFromPath(path, "${type}");
|
|
50
|
+
if (name) componentMap[name] = defineAsyncComponent(modules${i}_${type}[path]);
|
|
51
|
+
}
|
|
52
|
+
`).join('\n');
|
|
53
|
+
})
|
|
54
|
+
.reverse()
|
|
55
|
+
.join('\n');
|
|
56
|
+
|
|
57
|
+
// Create the plugin template
|
|
58
|
+
addTemplate({
|
|
59
|
+
filename: 'dynamic-entity-component-resolver.plugin.mjs',
|
|
60
|
+
getContents: () => `
|
|
61
|
+
import { defineNuxtPlugin } from '#app'
|
|
62
|
+
import { defineAsyncComponent } from 'vue'
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Extracts a normalized component name from a file path for dynamic component mapping.
|
|
66
|
+
*
|
|
67
|
+
* Supports both single-file and directory-based Vue component structures:
|
|
68
|
+
* - /components/Type/Foo.vue -> TypeFoo
|
|
69
|
+
* - /components/Type/Foo/index.vue -> TypeFoo
|
|
70
|
+
* - /components/Type/Bar/Baz.vue -> TypeBarBaz
|
|
71
|
+
* - /components/Type/Bar/Baz/index.vue -> TypeBarBaz
|
|
72
|
+
*
|
|
73
|
+
* @param {string} path - The absolute or relative file path to the Vue component.
|
|
74
|
+
* @param {string} type - The entity type (e.g., 'Node', 'TaxonomyTerm').
|
|
75
|
+
* @returns {string|null} The normalized component name (e.g., 'NodeFoo' or 'TaxonomyTermBarBaz'), or null if the path does not match.
|
|
76
|
+
*/
|
|
77
|
+
function getComponentNameFromPath(path, type) {
|
|
78
|
+
// Escape type for RegExp
|
|
79
|
+
var escType = type.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
80
|
+
var re = new RegExp('/' + escType + '/(.+?)/?(index)?\\.vue$');
|
|
81
|
+
var match = path.match(re);
|
|
82
|
+
if (match) {
|
|
83
|
+
var parts = match[1].split('/').map(function(part) {
|
|
84
|
+
return part.charAt(0).toUpperCase() + part.slice(1);
|
|
85
|
+
});
|
|
86
|
+
return type + parts.join('');
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default defineNuxtPlugin(() => {
|
|
92
|
+
${imports}
|
|
93
|
+
var componentMap = {};
|
|
94
|
+
${mergeLogic}
|
|
95
|
+
return {
|
|
96
|
+
provide: {
|
|
97
|
+
resolveDynamicEntityComponent: function(name) { return componentMap[name] || null; }
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
`
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// Register the generated plugin
|
|
105
|
+
addPlugin({
|
|
106
|
+
src: resolve(nuxt.options.buildDir, 'dynamic-entity-component-resolver.plugin.mjs')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
// Private helper to extract unique fragment values from any routeQueries object
|
|
110
|
+
function extractFragments(routeQueries: any): string[] {
|
|
111
|
+
const fragments = new Set<string>();
|
|
112
|
+
|
|
113
|
+
function traverse(obj: any) {
|
|
114
|
+
if (Array.isArray(obj)) {
|
|
115
|
+
obj.forEach(item => traverse(item));
|
|
116
|
+
} else if (obj && typeof obj === 'object') {
|
|
117
|
+
for (const key in obj) {
|
|
118
|
+
if (key === 'fragments' && Array.isArray(obj[key])) {
|
|
119
|
+
obj[key].forEach(frag => {
|
|
120
|
+
if (typeof frag === 'string') fragments.add(frag);
|
|
121
|
+
});
|
|
122
|
+
} else {
|
|
123
|
+
traverse(obj[key]);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
traverse(routeQueries);
|
|
130
|
+
return Array.from(fragments);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const entityFragments = nuxt.options._layers
|
|
134
|
+
.map((layer, idx) => {
|
|
135
|
+
const queries = layer.config?.vuepal?.drupalRoute?.routeQueries;
|
|
136
|
+
const fragments = extractFragments(queries);
|
|
137
|
+
return fragments;
|
|
138
|
+
})
|
|
139
|
+
.filter(arr => Array.isArray(arr) && arr.length)
|
|
140
|
+
.flat()
|
|
141
|
+
.filter(Boolean);
|
|
142
|
+
|
|
143
|
+
const entityTeaserFagment = `
|
|
144
|
+
fragment entityTeaser on Entity {
|
|
145
|
+
__typename
|
|
146
|
+
${entityFragments.map((fragmentName) => fragmentName ? `...${fragmentName}Teaser` : '').join('\n ')}
|
|
147
|
+
}
|
|
148
|
+
`
|
|
149
|
+
const entitySearchResultFagment = `
|
|
150
|
+
fragment entitySearchResult on Entity {
|
|
151
|
+
__typename
|
|
152
|
+
${entityFragments.map((fragmentName) => fragmentName ? `...${fragmentName}SearchResult` : '').join('\n ')}
|
|
153
|
+
}
|
|
154
|
+
`
|
|
155
|
+
nuxt.hooks.hookOnce('nuxt-graphql-middleware:init', (context) => {
|
|
156
|
+
context.addDocument('fragment.entityTeaser.graphql', entityTeaserFagment)
|
|
157
|
+
context.addDocument('fragment.entitySearchResult.graphql', entitySearchResultFagment)
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
|
|
@@ -43,7 +43,7 @@ import { defineNuxtModule } from 'nuxt/kit'
|
|
|
43
43
|
*/
|
|
44
44
|
export default defineNuxtModule({
|
|
45
45
|
meta: {
|
|
46
|
-
name: '
|
|
46
|
+
name: 'dynamicParagraphResolver',
|
|
47
47
|
},
|
|
48
48
|
setup(_options, nuxt) {
|
|
49
49
|
// Collect all paragraph fragments from the Nuxt layers.
|