@iqual/nuxt-icms 1.0.14 → 1.2.1

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 (427) hide show
  1. package/assets/css/ckeditor.css +4 -0
  2. package/assets/css/components/container.css +2 -2
  3. package/assets/css/tailwind.css +1 -1
  4. package/assets/css/typography.css +4 -0
  5. package/assets/symbols/download.svg +3 -0
  6. package/bundles.ts +4 -1
  7. package/components/Blokkli/TextMedia/index.vue +1 -2
  8. package/components/Blokkli/Timeline/Element/icms_timeline_element.svg +7 -0
  9. package/components/Blokkli/Timeline/Element/icon.svg +7 -0
  10. package/components/Blokkli/Timeline/Element/index.vue +14 -0
  11. package/components/Blokkli/Timeline/Layout/icms_layout_timeline.svg +16 -0
  12. package/components/Blokkli/Timeline/Layout/icon.svg +16 -0
  13. package/components/Blokkli/Timeline/Layout/index.vue +14 -0
  14. package/components/Blokkli/iFrame/icon-blokkli-option-large-spacing-bottom.svg +1 -0
  15. package/components/Blokkli/iFrame/icon-blokkli-option-large-spacing-top.svg +1 -0
  16. package/components/Blokkli/iFrame/icon-blokkli-option-no-spacing.svg +1 -0
  17. package/components/Blokkli/iFrame/icon-blokkli-option-small-spacing-bottom.svg +1 -0
  18. package/components/Blokkli/iFrame/icon-blokkli-option-small-spacing-top.svg +1 -0
  19. package/components/Blokkli/iFrame/{Layout/index.vue → index.vue} +2 -6
  20. package/components/DesignSystem/Atoms/Caption.vue +15 -0
  21. package/components/DesignSystem/Atoms/LinkListItem.vue +21 -0
  22. package/components/DesignSystem/Molecules/MediaSlider.vue +25 -8
  23. package/components/DesignSystem/Organisms/Map.vue +61 -0
  24. package/components/DesignSystem/Organisms/TimelineElement.vue +92 -0
  25. package/components/Media/Image/index.vue +4 -162
  26. package/components/Node/Icms/Page/SearchResult/fragment.graphql +8 -0
  27. package/components/Node/Icms/Page/SearchResult/index.vue +12 -0
  28. package/components/Node/Icms/Page/Teaser/fragment.graphql +17 -0
  29. package/components/Node/Icms/Page/Teaser/index.vue +20 -0
  30. package/components/Node/Icms/Page/fragment.graphql +18 -0
  31. package/components/Paragraph/CallToAction/index.vue +12 -8
  32. package/components/Paragraph/Card/Layout/index.vue +2 -2
  33. package/components/Paragraph/Downloads/index.vue +3 -14
  34. package/components/Paragraph/FAQ/Layout/index.vue +23 -1
  35. package/components/Paragraph/FlipTeasers/index.vue +2 -2
  36. package/components/Paragraph/Gallery/index.vue +32 -171
  37. package/components/Paragraph/HeroImage/index.vue +13 -4
  38. package/components/Paragraph/Media/index.vue +7 -2
  39. package/components/Paragraph/Table/index.vue +2 -2
  40. package/components/Paragraph/Team/Layout/index.vue +2 -2
  41. package/components/Paragraph/Teasers/fragment.graphql +2 -15
  42. package/components/Paragraph/Teasers/index.vue +11 -14
  43. package/components/Paragraph/TextMedia/index.vue +40 -33
  44. package/components/Paragraph/Timeline/Element/fragment.graphql +16 -0
  45. package/components/Paragraph/Timeline/Element/index.vue +31 -0
  46. package/components/Paragraph/Timeline/Layout/fragment.graphql +15 -0
  47. package/components/Paragraph/Timeline/Layout/index.vue +325 -0
  48. package/components/Paragraph/iFrame/{Layout/fragment.graphql → fragment.graphql} +2 -6
  49. package/components/Paragraph/iFrame/index.vue +56 -0
  50. package/components/Search/Facets/FacetDropdownUI.vue +222 -0
  51. package/components/Search/Facets/FacetedSearchUI.vue +397 -0
  52. package/components/Search/Facets/fragment.graphql +40 -0
  53. package/components/Section/Header/LanguageDropdown.vue +60 -73
  54. package/components/Section/Header/LanguageSwitcher.vue +37 -0
  55. package/components/Section/Header/MetaMenu.vue +10 -1
  56. package/components/Section/Header/index.vue +80 -67
  57. package/components/ui/accordion/Accordion.vue +2 -2
  58. package/components/ui/accordion/AccordionContent.vue +5 -5
  59. package/components/ui/accordion/AccordionItem.vue +9 -10
  60. package/components/ui/accordion/AccordionTrigger.vue +5 -5
  61. package/components/ui/alert/Alert.vue +17 -0
  62. package/components/ui/alert/AlertDescription.vue +14 -0
  63. package/components/ui/alert/AlertTitle.vue +14 -0
  64. package/components/ui/alert/index.ts +24 -0
  65. package/components/ui/alert-dialog/AlertDialog.vue +15 -0
  66. package/components/ui/alert-dialog/AlertDialogAction.vue +22 -0
  67. package/components/ui/alert-dialog/AlertDialogCancel.vue +29 -0
  68. package/components/ui/alert-dialog/AlertDialogContent.vue +43 -0
  69. package/components/ui/alert-dialog/AlertDialogDescription.vue +27 -0
  70. package/components/ui/alert-dialog/AlertDialogFooter.vue +21 -0
  71. package/components/ui/alert-dialog/AlertDialogHeader.vue +16 -0
  72. package/components/ui/alert-dialog/AlertDialogTitle.vue +24 -0
  73. package/components/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  74. package/components/ui/alert-dialog/index.ts +9 -0
  75. package/components/ui/aspect-ratio/AspectRatio.vue +12 -0
  76. package/components/ui/aspect-ratio/index.ts +1 -0
  77. package/components/ui/auto-form/AutoForm.vue +106 -0
  78. package/components/ui/auto-form/AutoFormField.vue +45 -0
  79. package/components/ui/auto-form/AutoFormFieldArray.vue +110 -0
  80. package/components/ui/auto-form/AutoFormFieldBoolean.vue +41 -0
  81. package/components/ui/auto-form/AutoFormFieldDate.vue +57 -0
  82. package/components/ui/auto-form/AutoFormFieldEnum.vue +49 -0
  83. package/components/ui/auto-form/AutoFormFieldFile.vue +74 -0
  84. package/components/ui/auto-form/AutoFormFieldInput.vue +36 -0
  85. package/components/ui/auto-form/AutoFormFieldNumber.vue +32 -0
  86. package/components/ui/auto-form/AutoFormFieldObject.vue +78 -0
  87. package/components/ui/auto-form/AutoFormLabel.vue +14 -0
  88. package/components/ui/auto-form/constant.ts +40 -0
  89. package/components/ui/auto-form/dependencies.ts +93 -0
  90. package/components/ui/auto-form/index.ts +15 -0
  91. package/components/ui/auto-form/interface.ts +95 -0
  92. package/components/ui/auto-form/utils.ts +188 -0
  93. package/components/ui/avatar/Avatar.vue +22 -0
  94. package/components/ui/avatar/AvatarFallback.vue +12 -0
  95. package/components/ui/avatar/AvatarImage.vue +10 -0
  96. package/components/ui/avatar/index.ts +25 -0
  97. package/components/ui/badge/Badge.vue +17 -0
  98. package/components/ui/badge/index.ts +26 -0
  99. package/components/ui/breadcrumb/Breadcrumb.vue +13 -0
  100. package/components/ui/breadcrumb/BreadcrumbEllipsis.vue +22 -0
  101. package/components/ui/breadcrumb/BreadcrumbItem.vue +16 -0
  102. package/components/ui/breadcrumb/BreadcrumbLink.vue +20 -0
  103. package/components/ui/breadcrumb/BreadcrumbList.vue +16 -0
  104. package/components/ui/breadcrumb/BreadcrumbPage.vue +19 -0
  105. package/components/ui/breadcrumb/BreadcrumbSeparator.vue +21 -0
  106. package/components/ui/breadcrumb/index.ts +7 -0
  107. package/components/ui/button/Button.vue +4 -2
  108. package/components/ui/button/index.ts +9 -9
  109. package/components/ui/calendar/Calendar.vue +62 -0
  110. package/components/ui/calendar/CalendarCell.vue +26 -0
  111. package/components/ui/calendar/CalendarCellTrigger.vue +40 -0
  112. package/components/ui/calendar/CalendarGrid.vue +26 -0
  113. package/components/ui/calendar/CalendarGridBody.vue +12 -0
  114. package/components/ui/calendar/CalendarGridHead.vue +12 -0
  115. package/components/ui/calendar/CalendarGridRow.vue +23 -0
  116. package/components/ui/calendar/CalendarHeadCell.vue +23 -0
  117. package/components/ui/calendar/CalendarHeader.vue +23 -0
  118. package/components/ui/calendar/CalendarHeading.vue +33 -0
  119. package/components/ui/calendar/CalendarNextButton.vue +34 -0
  120. package/components/ui/calendar/CalendarPrevButton.vue +34 -0
  121. package/components/ui/calendar/index.ts +12 -0
  122. package/components/ui/card/Card.vue +21 -0
  123. package/components/ui/card/CardContent.vue +14 -0
  124. package/components/ui/card/CardDescription.vue +14 -0
  125. package/components/ui/card/CardFooter.vue +14 -0
  126. package/components/ui/card/CardHeader.vue +14 -0
  127. package/components/ui/card/CardTitle.vue +18 -0
  128. package/components/ui/card/index.ts +6 -0
  129. package/components/ui/carousel/Carousel.vue +3 -23
  130. package/components/ui/carousel/CarouselContent.vue +1 -2
  131. package/components/ui/carousel/CarouselItem.vue +5 -7
  132. package/components/ui/carousel/CarouselNext.vue +7 -9
  133. package/components/ui/carousel/CarouselPrevious.vue +7 -9
  134. package/components/ui/carousel/index.ts +3 -1
  135. package/components/ui/carousel/interface.ts +3 -1
  136. package/components/ui/carousel/useCarousel.ts +13 -23
  137. package/components/ui/chart/ChartCrosshair.vue +45 -0
  138. package/components/ui/chart/ChartLegend.vue +50 -0
  139. package/components/ui/chart/ChartSingleTooltip.vue +64 -0
  140. package/components/ui/chart/ChartTooltip.vue +40 -0
  141. package/components/ui/chart/index.ts +18 -0
  142. package/components/ui/chart/interface.ts +64 -0
  143. package/components/ui/chart-area/AreaChart.vue +141 -0
  144. package/components/ui/chart-area/index.ts +66 -0
  145. package/components/ui/chart-bar/BarChart.vue +116 -0
  146. package/components/ui/chart-bar/index.ts +66 -0
  147. package/components/ui/chart-donut/DonutChart.vue +101 -0
  148. package/components/ui/chart-donut/index.ts +39 -0
  149. package/components/ui/chart-line/LineChart.vue +107 -0
  150. package/components/ui/chart-line/index.ts +66 -0
  151. package/components/ui/checkbox/Checkbox.vue +1 -1
  152. package/components/ui/collapsible/Collapsible.vue +15 -0
  153. package/components/ui/collapsible/CollapsibleContent.vue +12 -0
  154. package/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
  155. package/components/ui/collapsible/index.ts +3 -0
  156. package/components/ui/command/Command.vue +31 -0
  157. package/components/ui/command/CommandDialog.vue +21 -0
  158. package/components/ui/command/CommandEmpty.vue +21 -0
  159. package/components/ui/command/CommandGroup.vue +30 -0
  160. package/components/ui/command/CommandInput.vue +35 -0
  161. package/components/ui/command/CommandItem.vue +27 -0
  162. package/components/ui/command/CommandList.vue +28 -0
  163. package/components/ui/command/CommandSeparator.vue +24 -0
  164. package/components/ui/command/CommandShortcut.vue +14 -0
  165. package/components/ui/command/index.ts +9 -0
  166. package/components/ui/context-menu/ContextMenu.vue +15 -0
  167. package/components/ui/context-menu/ContextMenuCheckboxItem.vue +41 -0
  168. package/components/ui/context-menu/ContextMenuContent.vue +37 -0
  169. package/components/ui/context-menu/ContextMenuGroup.vue +12 -0
  170. package/components/ui/context-menu/ContextMenuItem.vue +35 -0
  171. package/components/ui/context-menu/ContextMenuLabel.vue +27 -0
  172. package/components/ui/context-menu/ContextMenuPortal.vue +12 -0
  173. package/components/ui/context-menu/ContextMenuRadioGroup.vue +19 -0
  174. package/components/ui/context-menu/ContextMenuRadioItem.vue +41 -0
  175. package/components/ui/context-menu/ContextMenuSeparator.vue +22 -0
  176. package/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
  177. package/components/ui/context-menu/ContextMenuSub.vue +19 -0
  178. package/components/ui/context-menu/ContextMenuSubContent.vue +36 -0
  179. package/components/ui/context-menu/ContextMenuSubTrigger.vue +36 -0
  180. package/components/ui/context-menu/ContextMenuTrigger.vue +14 -0
  181. package/components/ui/context-menu/index.ts +14 -0
  182. package/components/ui/dialog/Dialog.vue +2 -6
  183. package/components/ui/dialog/DialogClose.vue +2 -1
  184. package/components/ui/dialog/DialogContent.vue +10 -12
  185. package/components/ui/dialog/DialogDescription.vue +6 -10
  186. package/components/ui/dialog/DialogScrollContent.vue +15 -21
  187. package/components/ui/dialog/DialogTitle.vue +9 -6
  188. package/components/ui/dialog/DialogTrigger.vue +2 -1
  189. package/components/ui/drawer/Drawer.vue +19 -0
  190. package/components/ui/drawer/DrawerContent.vue +28 -0
  191. package/components/ui/drawer/DrawerDescription.vue +21 -0
  192. package/components/ui/drawer/DrawerFooter.vue +14 -0
  193. package/components/ui/drawer/DrawerHeader.vue +14 -0
  194. package/components/ui/drawer/DrawerOverlay.vue +19 -0
  195. package/components/ui/drawer/DrawerTitle.vue +21 -0
  196. package/components/ui/drawer/index.ts +8 -0
  197. package/components/ui/dropdown-menu/DropdownMenu.vue +15 -0
  198. package/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +41 -0
  199. package/components/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  200. package/components/ui/dropdown-menu/DropdownMenuGroup.vue +12 -0
  201. package/components/ui/dropdown-menu/DropdownMenuItem.vue +30 -0
  202. package/components/ui/dropdown-menu/DropdownMenuLabel.vue +26 -0
  203. package/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
  204. package/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +42 -0
  205. package/components/ui/dropdown-menu/DropdownMenuSeparator.vue +24 -0
  206. package/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  207. package/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  208. package/components/ui/dropdown-menu/DropdownMenuSubContent.vue +31 -0
  209. package/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +35 -0
  210. package/components/ui/dropdown-menu/DropdownMenuTrigger.vue +14 -0
  211. package/components/ui/dropdown-menu/index.ts +16 -0
  212. package/components/ui/form/FormControl.vue +16 -0
  213. package/components/ui/form/FormDescription.vue +20 -0
  214. package/components/ui/form/FormItem.vue +20 -0
  215. package/components/ui/form/FormLabel.vue +23 -0
  216. package/components/ui/form/FormMessage.vue +16 -0
  217. package/components/ui/form/index.ts +7 -0
  218. package/components/ui/form/injectionKeys.ts +4 -0
  219. package/components/ui/form/useFormField.ts +30 -0
  220. package/components/ui/hover-card/HoverCard.vue +15 -0
  221. package/components/ui/hover-card/HoverCardContent.vue +43 -0
  222. package/components/ui/hover-card/HoverCardTrigger.vue +12 -0
  223. package/components/ui/hover-card/index.ts +3 -0
  224. package/components/ui/input/Input.vue +1 -1
  225. package/components/ui/menubar/Menubar.vue +36 -0
  226. package/components/ui/menubar/MenubarCheckboxItem.vue +41 -0
  227. package/components/ui/menubar/MenubarContent.vue +45 -0
  228. package/components/ui/menubar/MenubarGroup.vue +12 -0
  229. package/components/ui/menubar/MenubarItem.vue +36 -0
  230. package/components/ui/menubar/MenubarLabel.vue +14 -0
  231. package/components/ui/menubar/MenubarMenu.vue +12 -0
  232. package/components/ui/menubar/MenubarRadioGroup.vue +20 -0
  233. package/components/ui/menubar/MenubarRadioItem.vue +41 -0
  234. package/components/ui/menubar/MenubarSeparator.vue +21 -0
  235. package/components/ui/menubar/MenubarShortcut.vue +14 -0
  236. package/components/ui/menubar/MenubarSub.vue +20 -0
  237. package/components/ui/menubar/MenubarSubContent.vue +40 -0
  238. package/components/ui/menubar/MenubarSubTrigger.vue +32 -0
  239. package/components/ui/menubar/MenubarTrigger.vue +31 -0
  240. package/components/ui/menubar/index.ts +15 -0
  241. package/components/ui/navigation-menu/NavigationMenu.vue +34 -0
  242. package/components/ui/navigation-menu/NavigationMenuContent.vue +35 -0
  243. package/components/ui/navigation-menu/NavigationMenuIndicator.vue +26 -0
  244. package/components/ui/navigation-menu/NavigationMenuItem.vue +12 -0
  245. package/components/ui/navigation-menu/NavigationMenuLink.vue +19 -0
  246. package/components/ui/navigation-menu/NavigationMenuList.vue +31 -0
  247. package/components/ui/navigation-menu/NavigationMenuTrigger.vue +36 -0
  248. package/components/ui/navigation-menu/NavigationMenuViewport.vue +35 -0
  249. package/components/ui/navigation-menu/index.ts +14 -0
  250. package/components/ui/number-field/NumberField.vue +24 -0
  251. package/components/ui/number-field/NumberFieldContent.vue +14 -0
  252. package/components/ui/number-field/NumberFieldDecrement.vue +26 -0
  253. package/components/ui/number-field/NumberFieldIncrement.vue +26 -0
  254. package/components/ui/number-field/NumberFieldInput.vue +16 -0
  255. package/components/ui/number-field/index.ts +5 -0
  256. package/components/ui/pagination/PaginationEllipsis.vue +24 -0
  257. package/components/ui/pagination/PaginationFirst.vue +31 -0
  258. package/components/ui/pagination/PaginationLast.vue +31 -0
  259. package/components/ui/pagination/PaginationNext.vue +31 -0
  260. package/components/ui/pagination/PaginationPrev.vue +31 -0
  261. package/components/ui/pagination/index.ts +10 -0
  262. package/components/ui/pin-input/PinInput.vue +25 -0
  263. package/components/ui/pin-input/PinInputGroup.vue +20 -0
  264. package/components/ui/pin-input/PinInputInput.vue +20 -0
  265. package/components/ui/pin-input/PinInputSeparator.vue +16 -0
  266. package/components/ui/pin-input/index.ts +4 -0
  267. package/components/ui/popover/Popover.vue +15 -0
  268. package/components/ui/popover/PopoverContent.vue +49 -0
  269. package/components/ui/popover/PopoverTrigger.vue +12 -0
  270. package/components/ui/popover/index.ts +3 -0
  271. package/components/ui/progress/Progress.vue +41 -0
  272. package/components/ui/progress/index.ts +1 -0
  273. package/components/ui/radio-group/RadioGroupItem.vue +1 -1
  274. package/components/ui/range-calendar/RangeCalendar.vue +62 -0
  275. package/components/ui/range-calendar/RangeCalendarCell.vue +26 -0
  276. package/components/ui/range-calendar/RangeCalendarCellTrigger.vue +42 -0
  277. package/components/ui/range-calendar/RangeCalendarGrid.vue +26 -0
  278. package/components/ui/range-calendar/RangeCalendarGridBody.vue +12 -0
  279. package/components/ui/range-calendar/RangeCalendarGridHead.vue +12 -0
  280. package/components/ui/range-calendar/RangeCalendarGridRow.vue +23 -0
  281. package/components/ui/range-calendar/RangeCalendarHeadCell.vue +23 -0
  282. package/components/ui/range-calendar/RangeCalendarHeader.vue +23 -0
  283. package/components/ui/range-calendar/RangeCalendarHeading.vue +33 -0
  284. package/components/ui/range-calendar/RangeCalendarNextButton.vue +34 -0
  285. package/components/ui/range-calendar/RangeCalendarPrevButton.vue +34 -0
  286. package/components/ui/range-calendar/index.ts +12 -0
  287. package/components/ui/resizable/ResizableHandle.vue +28 -0
  288. package/components/ui/resizable/ResizablePanelGroup.vue +23 -0
  289. package/components/ui/resizable/index.ts +3 -0
  290. package/components/ui/scroll-area/ScrollArea.vue +31 -0
  291. package/components/ui/scroll-area/ScrollBar.vue +32 -0
  292. package/components/ui/scroll-area/index.ts +2 -0
  293. package/components/ui/select/SelectContent.vue +1 -1
  294. package/components/ui/select/SelectItem.vue +1 -1
  295. package/components/ui/select/SelectSeparator.vue +1 -1
  296. package/components/ui/select/SelectTrigger.vue +1 -1
  297. package/components/ui/separator/Separator.vue +37 -0
  298. package/components/ui/separator/index.ts +1 -0
  299. package/components/ui/sheet/Sheet.vue +15 -0
  300. package/components/ui/sheet/SheetClose.vue +12 -0
  301. package/components/ui/sheet/SheetContent.vue +58 -0
  302. package/components/ui/sheet/SheetDescription.vue +24 -0
  303. package/components/ui/sheet/SheetFooter.vue +19 -0
  304. package/components/ui/sheet/SheetHeader.vue +16 -0
  305. package/components/ui/sheet/SheetTitle.vue +24 -0
  306. package/components/ui/sheet/SheetTrigger.vue +12 -0
  307. package/components/ui/sheet/index.ts +32 -0
  308. package/components/ui/sidebar/Sidebar.vue +85 -0
  309. package/components/ui/sidebar/SidebarContent.vue +17 -0
  310. package/components/ui/sidebar/SidebarFooter.vue +17 -0
  311. package/components/ui/sidebar/SidebarGroup.vue +17 -0
  312. package/components/ui/sidebar/SidebarGroupAction.vue +26 -0
  313. package/components/ui/sidebar/SidebarGroupContent.vue +17 -0
  314. package/components/ui/sidebar/SidebarGroupLabel.vue +24 -0
  315. package/components/ui/sidebar/SidebarHeader.vue +17 -0
  316. package/components/ui/sidebar/SidebarInput.vue +21 -0
  317. package/components/ui/sidebar/SidebarInset.vue +20 -0
  318. package/components/ui/sidebar/SidebarMenu.vue +17 -0
  319. package/components/ui/sidebar/SidebarMenuAction.vue +34 -0
  320. package/components/ui/sidebar/SidebarMenuBadge.vue +25 -0
  321. package/components/ui/sidebar/SidebarMenuButton.vue +51 -0
  322. package/components/ui/sidebar/SidebarMenuButtonChild.vue +35 -0
  323. package/components/ui/sidebar/SidebarMenuItem.vue +17 -0
  324. package/components/ui/sidebar/SidebarMenuSkeleton.vue +34 -0
  325. package/components/ui/sidebar/SidebarMenuSub.vue +21 -0
  326. package/components/ui/sidebar/SidebarMenuSubButton.vue +35 -0
  327. package/components/ui/sidebar/SidebarMenuSubItem.vue +8 -0
  328. package/components/ui/sidebar/SidebarProvider.vue +81 -0
  329. package/components/ui/sidebar/SidebarRail.vue +32 -0
  330. package/components/ui/sidebar/SidebarSeparator.vue +18 -0
  331. package/components/ui/sidebar/SidebarTrigger.vue +26 -0
  332. package/components/ui/sidebar/index.ts +60 -0
  333. package/components/ui/sidebar/utils.ts +19 -0
  334. package/components/ui/skeleton/Skeleton.vue +14 -0
  335. package/components/ui/skeleton/index.ts +1 -0
  336. package/components/ui/slider/Slider.vue +37 -0
  337. package/components/ui/slider/index.ts +1 -0
  338. package/components/ui/sonner/Sonner.vue +23 -0
  339. package/components/ui/sonner/index.ts +1 -0
  340. package/components/ui/stepper/Stepper.vue +32 -0
  341. package/components/ui/stepper/StepperDescription.vue +24 -0
  342. package/components/ui/stepper/StepperIndicator.vue +36 -0
  343. package/components/ui/stepper/StepperItem.vue +28 -0
  344. package/components/ui/stepper/StepperSeparator.vue +32 -0
  345. package/components/ui/stepper/StepperTitle.vue +24 -0
  346. package/components/ui/stepper/StepperTrigger.vue +27 -0
  347. package/components/ui/stepper/index.ts +7 -0
  348. package/components/ui/switch/Switch.vue +40 -0
  349. package/components/ui/switch/index.ts +1 -0
  350. package/components/ui/table/Table.vue +16 -0
  351. package/components/ui/table/TableBody.vue +14 -0
  352. package/components/ui/table/TableCaption.vue +14 -0
  353. package/components/ui/table/TableCell.vue +21 -0
  354. package/components/ui/table/TableEmpty.vue +38 -0
  355. package/components/ui/table/TableFooter.vue +14 -0
  356. package/components/ui/table/TableHead.vue +14 -0
  357. package/components/ui/table/TableHeader.vue +14 -0
  358. package/components/ui/table/TableRow.vue +14 -0
  359. package/components/ui/table/index.ts +9 -0
  360. package/components/ui/tabs/TabsContent.vue +6 -11
  361. package/components/ui/tabs/TabsList.vue +8 -8
  362. package/components/ui/tabs/TabsTrigger.vue +9 -11
  363. package/components/ui/tags-input/TagsInput.vue +24 -0
  364. package/components/ui/tags-input/TagsInputInput.vue +21 -0
  365. package/components/ui/tags-input/TagsInputItem.vue +24 -0
  366. package/components/ui/tags-input/TagsInputItemDelete.vue +26 -0
  367. package/components/ui/tags-input/TagsInputItemText.vue +21 -0
  368. package/components/ui/tags-input/index.ts +5 -0
  369. package/components/ui/textarea/Textarea.vue +1 -1
  370. package/components/ui/toast/Toast.vue +30 -0
  371. package/components/ui/toast/ToastAction.vue +21 -0
  372. package/components/ui/toast/ToastClose.vue +24 -0
  373. package/components/ui/toast/ToastDescription.vue +21 -0
  374. package/components/ui/toast/ToastProvider.vue +12 -0
  375. package/components/ui/toast/ToastTitle.vue +21 -0
  376. package/components/ui/toast/ToastViewport.vue +19 -0
  377. package/components/ui/toast/Toaster.vue +30 -0
  378. package/components/ui/toast/index.ts +39 -0
  379. package/components/ui/toast/use-toast.ts +165 -0
  380. package/components/ui/toggle/Toggle.vue +38 -0
  381. package/components/ui/toggle/index.ts +28 -0
  382. package/components/ui/toggle-group/ToggleGroup.vue +36 -0
  383. package/components/ui/toggle-group/ToggleGroupItem.vue +37 -0
  384. package/components/ui/toggle-group/index.ts +2 -0
  385. package/components/ui/tooltip/Tooltip.vue +15 -0
  386. package/components/ui/tooltip/TooltipContent.vue +33 -0
  387. package/components/ui/tooltip/TooltipProvider.vue +12 -0
  388. package/components/ui/tooltip/TooltipTrigger.vue +12 -0
  389. package/components/ui/tooltip/index.ts +4 -0
  390. package/components/ui/v-calendar/Calendar.vue +343 -0
  391. package/components/ui/v-calendar/index.ts +22 -0
  392. package/composables/useAccordionScroll.ts +1 -1
  393. package/composables/useContentSearch.ts +0 -0
  394. package/composables/useImageSources.ts +208 -0
  395. package/composables/useLightbox.ts +81 -0
  396. package/composables/useMainMenuLinks.ts +1 -1
  397. package/composables/useMessageBus.ts +74 -0
  398. package/composables/useMetaMenuLinks.ts +1 -1
  399. package/composables/useNavigationOffset.ts +1 -1
  400. package/layouts/default.vue +2 -2
  401. package/layouts/error.vue +8 -10
  402. package/modules/dynamicEntityComponentResolver.ts +182 -0
  403. package/modules/dynamicParagraphResolver.ts +1 -1
  404. package/nuxt.config.ts +28 -32
  405. package/package.json +3 -2
  406. package/pages/[...slug]/index.vue +2 -2
  407. package/pages/index.vue +2 -2
  408. package/pages/node/[nid]/index.vue +2 -2
  409. package/queries/query.contentSearch.graphql +17 -0
  410. package/tailwind.config.ts +1 -0
  411. package/types/fslightbox-vue.d.ts +1 -0
  412. package/components/Blokkli/iFrame/Element/icon.svg +0 -5
  413. package/components/Blokkli/iFrame/Element/index.vue +0 -14
  414. package/components/Paragraph/iFrame/Element/fragment.graphql +0 -9
  415. package/components/Paragraph/iFrame/Element/index.vue +0 -16
  416. package/components/Paragraph/iFrame/Layout/index.vue +0 -161
  417. package/composables/languageLinks.ts +0 -31
  418. package/modules/dynamicNodeResolver.ts +0 -95
  419. package/pages/search/index.vue +0 -69
  420. package/pages/static-page/example.vue +0 -40
  421. package/queries/fragment.routeQuery.graphql +0 -51
  422. /package/components/Blokkli/{iFrame → Timeline}/Layout/icon-blokkli-option-large-spacing-bottom.svg +0 -0
  423. /package/components/Blokkli/{iFrame → Timeline}/Layout/icon-blokkli-option-large-spacing-top.svg +0 -0
  424. /package/components/Blokkli/{iFrame → Timeline}/Layout/icon-blokkli-option-no-spacing.svg +0 -0
  425. /package/components/Blokkli/{iFrame → Timeline}/Layout/icon-blokkli-option-small-spacing-bottom.svg +0 -0
  426. /package/components/Blokkli/{iFrame → Timeline}/Layout/icon-blokkli-option-small-spacing-top.svg +0 -0
  427. /package/components/Blokkli/iFrame/{Layout/icon.svg → icon.svg} +0 -0
@@ -0,0 +1,222 @@
1
+ <script setup lang="ts">
2
+
3
+ import Popover from '@/components/ui/popover/Popover.vue'
4
+ import PopoverContent from '@/components/ui/popover/PopoverContent.vue'
5
+ import PopoverTrigger from '@/components/ui/popover/PopoverTrigger.vue'
6
+
7
+ // Incoming facet shape from GraphQL API.
8
+ export interface GraphQLFacetItem {
9
+ field: string
10
+ label: string
11
+ filter: {
12
+ id: string
13
+ label: string
14
+ }
15
+ count: number
16
+ }
17
+
18
+ // Internal normalized option shape (label == filter by default; could be mapped later)
19
+ interface NormalizedFacetOption { value: string; label: string; count: number }
20
+
21
+ type FacetSelections = Record<string, string[]>
22
+
23
+ const props = defineProps<{
24
+ facets?: GraphQLFacetItem[]
25
+ /** grouped selections keyed by facet field */
26
+ modelValue?: FacetSelections
27
+ placeholder?: string
28
+ label?: string
29
+ /** Total count of results for display */
30
+ totalCount?: number
31
+ /** Currently displayed count for display */
32
+ displayedCount?: number
33
+ /** Loading state */
34
+ loading?: boolean
35
+ }>()
36
+
37
+ const emit = defineEmits<{
38
+ 'update:modelValue': [FacetSelections]
39
+ /** Emitted whenever a selection changes so parent can notify siblings */
40
+ 'facets-change': [FacetSelections]
41
+ }>()
42
+
43
+ // Simple deep clone utility (data is plain: Record<string, string[]>)
44
+ function cloneSelections(val?: FacetSelections | null): FacetSelections {
45
+ try {
46
+ return val ? JSON.parse(JSON.stringify(val)) : {}
47
+ } catch {
48
+ // Fallback shallow copy in worst case.
49
+ return Object.assign({}, val || {}) as FacetSelections
50
+ }
51
+ }
52
+
53
+ // Reactive selections
54
+ const selections = ref<FacetSelections>(cloneSelections(props.modelValue))
55
+
56
+ // Track open state for each popover to handle chevron rotation
57
+ const openPopovers = ref<Record<string, boolean>>({})
58
+
59
+ // Group facets by field.
60
+ const grouped = computed(() => {
61
+ // Map key: { field, label } (label is fieldLabel if present, else field)
62
+ const map = new Map<{ field: string, label: string }, NormalizedFacetOption[]>()
63
+ const source = props.facets || []
64
+ for (const item of source) {
65
+ const field = item.field
66
+ const key = Array.from(map.keys()).find(k => k.field === field) || { field, label: item.label }
67
+ if (!map.has(key)) map.set(key, [])
68
+ map.get(key)!.push({
69
+ "value": item.filter.id,
70
+ "label": item.filter.label,
71
+ "count": item.count ,
72
+ })
73
+ }
74
+ // Sort each group alphabetically by label for stable UI.
75
+ for (const [, arr] of map) arr.sort((a, b) => a.label.localeCompare(b.label))
76
+ return map
77
+ })
78
+
79
+ // Flatten for utility lookups.
80
+ const optionMap = computed(() => {
81
+ // Map key: filter string -> NormalizedFacetOption
82
+ const map = new Map<string, NormalizedFacetOption>()
83
+ for (const [, arr] of grouped.value) {
84
+ for (const opt of arr) {
85
+ map.set(opt.value, opt)
86
+ }
87
+ }
88
+ return map
89
+ })
90
+
91
+ // Stable array of [field, options[]] to simplify template & avoid calling entries() on undefined.
92
+ // Array of [{ filter, label }, options[]] for template
93
+ const groupEntries = computed(() => Array.from(grouped.value?.entries?.() || []))
94
+
95
+ // Per-field trigger labels
96
+ function fieldTriggerLabel(fieldData: { field: string, label: string }) {
97
+ let field: string = fieldData.field
98
+ let label: string = fieldData.label
99
+ const arr = selections.value[field] || []
100
+ if (!arr.length) return props.placeholder || `Select ${label}`
101
+ if (arr.length === 1) return optionMap.value.get(arr[0])?.label || arr[0]
102
+ return `${arr.length} selected`
103
+ }
104
+
105
+ function toggle(field: string, value: string) {
106
+ if (!selections.value[field]) selections.value[field] = []
107
+ const arr = selections.value[field]
108
+ const idx = arr.indexOf(value)
109
+ if (idx === -1) arr.push(value)
110
+ else arr.splice(idx, 1)
111
+ // Remove empty arrays to keep payload small.
112
+ if (!arr.length) delete selections.value[field]
113
+ emitAll()
114
+ }
115
+
116
+ function clearField(field: string) {
117
+ if (selections.value[field]) {
118
+ delete selections.value[field]
119
+ emitAll()
120
+ }
121
+ }
122
+
123
+ function clearAll() {
124
+ if (Object.keys(selections.value || {}).length) {
125
+ selections.value = {}
126
+ emitAll()
127
+ }
128
+ }
129
+
130
+ function emitAll() {
131
+ // Clone to avoid mutation issues in parent watchers.
132
+ const base = selections.value && typeof selections.value === 'object' ? selections.value : {}
133
+ const payload: FacetSelections = JSON.parse(JSON.stringify(base))
134
+ emit('update:modelValue', payload)
135
+ emit('facets-change', payload)
136
+ }
137
+
138
+ // Keep internal selections in sync if modelValue changes externally.
139
+ watch(
140
+ () => props.modelValue,
141
+ (val) => {
142
+ if (val) selections.value = cloneSelections(val)
143
+ },
144
+ { deep: true }
145
+ )
146
+ </script>
147
+
148
+ <template>
149
+ <div class="facets-ui space-y-4" v-if="groupEntries.length">
150
+ <!-- Clear Filters Button -->
151
+ <div class="flex">
152
+ <Button
153
+ variant="ghost"
154
+ size="sm"
155
+ :disabled="!(selections && Object.keys(selections || {}).length)"
156
+ @click="clearAll"
157
+ class="flex items-center gap-2"
158
+ >
159
+ {{ $texts('listing.clear_filters', 'Clear all filters') }}
160
+ </Button>
161
+ </div>
162
+
163
+ <!-- Facet Groups -->
164
+ <div class="flex flex-wrap gap-4">
165
+ <template v-for="([key, opts]) in groupEntries" :key="key.field + '-' + key.label">
166
+ <div class="w-72">
167
+ <Label class="mb-1 block text-xs font-medium uppercase tracking-wide text-muted-foreground">{{ key.label }}</Label>
168
+ <Popover @update:open="(open: boolean) => openPopovers[key.field] = open">
169
+ <PopoverTrigger as-child>
170
+ <Button variant="outline" class="w-full justify-between" :aria-label="`Facet ${key.label}`">
171
+ <span>{{ fieldTriggerLabel(key) }}</span>
172
+ <SpriteSymbol
173
+ name="chevron-down"
174
+ aria-hidden="true"
175
+ :class="[
176
+ 'size-7 cursor-pointer text-black transition-all duration-300 group-hover/main:text-primary-500',
177
+ openPopovers[key.field] ? 'rotate-180' : 'rotate-0'
178
+ ]"
179
+ />
180
+ </Button>
181
+ </PopoverTrigger>
182
+ <PopoverContent class="p-0 w-72 bg-white" align="start">
183
+ <div class="max-h-72 overflow-y-auto py-1">
184
+ <template v-for="opt in opts" :key="opt.value">
185
+ <button
186
+ type="button"
187
+ class="flex w-full items-center gap-3 px-3 py-2 text-left text-sm hover:bg-muted/60 focus:bg-muted/70 focus:outline-none"
188
+ @click="toggle(key.field, opt.value)"
189
+ >
190
+ <Checkbox
191
+ :checked="selections[key.field]?.includes(opt.value)"
192
+ @update:checked="toggle(key.field, opt.value)"
193
+ class="pointer-events-none"
194
+ />
195
+ <span class="flex-1 truncate">{{ opt.label }}</span>
196
+ <span class="tabular-nums text-muted-foreground text-xs">{{ opt.count }}</span>
197
+ </button>
198
+ </template>
199
+ </div>
200
+ <div class="flex items-center justify-between border-t px-2 py-1.5 gap-2">
201
+ <Button size="sm" variant="ghost" :disabled="!(selections[key.field] && selections[key.field].length)" @click="clearField(key.field)">Clear</Button>
202
+ </div>
203
+ </PopoverContent>
204
+ </Popover>
205
+ </div>
206
+ </template>
207
+ </div>
208
+
209
+ <!-- Results Counter -->
210
+ <div v-if="totalCount !== undefined" class="mb-4">
211
+ <div class="text-lg font-medium text-gray-900">
212
+ <span v-if="loading">Loading...</span>
213
+ <span v-else>
214
+ {{ totalCount }} {{ totalCount === 1 ? $texts('listing.result', 'result') : $texts('listing.results', 'results') }}
215
+ <span v-if="displayedCount && displayedCount < totalCount" class="text-sm font-normal text-gray-600">
216
+ ({{ $texts('listing.showing', 'result') }} {{ displayedCount }})
217
+ </span>
218
+ </span>
219
+ </div>
220
+ </div>
221
+ </div>
222
+ </template>
@@ -0,0 +1,397 @@
1
+ <template>
2
+ <div>
3
+ <!-- Facets Section (only for 'all' listing type) -->
4
+ <div v-if="listingType === 'all' && facets.length > 0">
5
+ <SearchFacetsFacetDropdownUI
6
+ :facets="facetData"
7
+ v-model="facetSelections"
8
+ @facets-change="onFacetsChange"
9
+ :total-count="totalCount"
10
+ :displayed-count="displayedResults.length"
11
+ :loading="isLoading"
12
+ class="mb-6"
13
+ />
14
+
15
+ <template v-if="debug">
16
+ <!-- Debug info (only if enabled) -->
17
+ <pre class="mt-4 text-xs whitespace-pre bg-gray-50 p-3 rounded" v-if="Object.keys(facetSelections).length">{{ JSON.stringify(facetSelections, null, 2) }}</pre>
18
+ <pre class="mt-2 text-xs whitespace-pre bg-blue-50 p-3 rounded" v-if="facetData.length">Facets: {{ facetData.length }} items</pre>
19
+ </template>
20
+ </div>
21
+
22
+ <template v-if="debug && listingType !== 'all'">
23
+ <!-- Debug info for manual/contextual filters -->
24
+ <pre class="mb-4 text-xs whitespace-pre bg-yellow-50 p-3 rounded">Active Filters ({{ listingType }}): {{ JSON.stringify(activeFilters, null, 2) }}</pre>
25
+ </template>
26
+
27
+ <!-- Results Section -->
28
+ <div class="results-container">
29
+ <template v-if="displayedResults.length > 0">
30
+ <slot name="results" :results="displayedResults" :loading="loadingMore">
31
+ <!-- Default slot content if no slot is provided -->
32
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
33
+ <div v-for="result in displayedResults" :key="result?.id || Math.random()" class="result-item">
34
+ <pre class="text-xs bg-gray-100 p-2 rounded">{{ JSON.stringify(result, null, 2) }}</pre>
35
+ </div>
36
+ </div>
37
+ </slot>
38
+ </template>
39
+
40
+ <template v-else-if="!isLoading">
41
+ <slot name="no-results">
42
+ <div class="col-span-12 py-8 text-center text-gray-500">
43
+ {{ defaultNoResultsText }}
44
+ </div>
45
+ </slot>
46
+ </template>
47
+
48
+ <template v-if="isLoading">
49
+ <slot name="loading">
50
+ <div class="col-span-12 py-8 text-center text-gray-500">
51
+ {{ defaultLoadingText }}
52
+ </div>
53
+ </slot>
54
+ </template>
55
+ </div>
56
+
57
+ <!-- Load More Section -->
58
+ <div v-if="showLoadMore" class="mt-10 flex justify-center lg:mt-20">
59
+ <slot name="load-more" :loadMore="loadMore" :loading="loadingMore">
60
+ <button
61
+ @click="loadMore"
62
+ :disabled="loadingMore"
63
+ :class="props.loadMoreButtonClass || defaultButtonClass"
64
+ >
65
+ <span v-if="!loadingMore">{{ defaultLoadMoreText }}</span>
66
+ <span v-else>{{ defaultLoadingText }}</span>
67
+ </button>
68
+ </slot>
69
+ </div>
70
+ </div>
71
+ </template>
72
+
73
+ <script lang="ts" setup>
74
+ import type { SearchApiQueryFilterInput } from '#graphql-operations'
75
+
76
+ export interface FacetFilterItem {
77
+ id: string
78
+ label: string
79
+ }
80
+
81
+ export interface ManualFilters {
82
+ topics?: FacetFilterItem[]
83
+ }
84
+
85
+ export interface FacetedSearchUIProps {
86
+ /**
87
+ * Base filter conditions that are always applied (e.g., content type)
88
+ * Example: { conditions: [{ field: "type", value: ["icms_news"] }] }
89
+ */
90
+ baseFilter: SearchApiQueryFilterInput
91
+
92
+ /**
93
+ * Array of facet field names to request from the search API
94
+ * Example: ["topics", "project_phase", "locations"]
95
+ */
96
+ facets: string[]
97
+
98
+ /** Listing type: 'all' (faceted search), 'manual' (props filters), 'contextual' (injected filters) */
99
+ listingType?: 'all' | 'manual' | 'contextual'
100
+
101
+ /** Manual filters for 'manual' listing type */
102
+ manualFilters?: ManualFilters
103
+
104
+ /** Maximum number of results to display per page */
105
+ itemsPerPage?: number
106
+
107
+ /** Text labels for internationalization */
108
+ noResultsText?: string
109
+ loadingText?: string
110
+ loadMoreText?: string
111
+
112
+ /** Enable debug mode to show facet selection info */
113
+ debug?: boolean
114
+
115
+ /** Color scheme for default button styling */
116
+ colorScheme?: 'none' | 'dark' | 'light' | 'accent'
117
+
118
+ /** Custom CSS classes for the load more button */
119
+ loadMoreButtonClass?: string
120
+ }
121
+
122
+ const props = withDefaults(defineProps<FacetedSearchUIProps>(), {
123
+ itemsPerPage: 12,
124
+ debug: false,
125
+ colorScheme: 'none',
126
+ listingType: 'all'
127
+ })
128
+
129
+ // Get the $texts function for internationalization
130
+ const { $texts } = useNuxtApp()
131
+
132
+ // Default text values with fallbacks
133
+ const defaultNoResultsText = computed(() =>
134
+ props.noResultsText || $texts('listing.no_results', 'Currently there is no content available.')
135
+ )
136
+ const defaultLoadingText = computed(() =>
137
+ props.loadingText || $texts('listing.loading', 'Loading...')
138
+ )
139
+ const defaultLoadMoreText = computed(() =>
140
+ props.loadMoreText || $texts('listing.load_more', 'Load more')
141
+ )
142
+
143
+ // Reactive state
144
+ const facetSelections = ref<Record<string, string[]>>({})
145
+ const allFacets = ref<any[]>([])
146
+ const currentPage = ref(1)
147
+ const loadingMore = ref(false)
148
+ const isLoading = ref(false)
149
+
150
+ // Contextual filters (injected from parent)
151
+ const contextualFilters = {
152
+ topics: inject<FacetFilterItem[]>('topics', [])
153
+ }
154
+
155
+ // Get active filters based on listing type
156
+ const activeFilters = computed(() => {
157
+ if (props.listingType === 'manual' && props.manualFilters) {
158
+ return props.manualFilters
159
+ } else if (props.listingType === 'contextual') {
160
+ return contextualFilters
161
+ }
162
+ return {}
163
+ })
164
+
165
+ // Build GraphQL filter from base filter and facet selections or manual/contextual filters
166
+ const buildSearchFilter = (selections?: Record<string, string[]>): SearchApiQueryFilterInput => {
167
+ const baseConditions = props.baseFilter.conditions || []
168
+ const conditions = [...baseConditions]
169
+
170
+ if (props.listingType === 'all') {
171
+ // For 'all' listing type, use facet selections from dropdowns
172
+ const facetSelections = selections || {}
173
+ for (const [field, values] of Object.entries(facetSelections)) {
174
+ if (values.length > 0) {
175
+ conditions.push({
176
+ field,
177
+ value: values
178
+ })
179
+ }
180
+ }
181
+ } else {
182
+ // For 'manual' and 'contextual' listing types, use activeFilters
183
+ const filters = activeFilters.value
184
+ for (const [field, items] of Object.entries(filters)) {
185
+ if (items && Array.isArray(items) && items.length > 0) {
186
+ const values = items.map(item => item.id).filter(Boolean)
187
+ if (values.length > 0) {
188
+ // Convert camelCase field names to snake_case for GraphQL
189
+ const graphqlField = field.replace(/([A-Z])/g, '_$1').toLowerCase()
190
+ conditions.push({
191
+ field: graphqlField,
192
+ value: values
193
+ })
194
+ }
195
+ }
196
+ }
197
+ }
198
+
199
+ return { conditions }
200
+ }
201
+
202
+ // Initial query to get all available facets (only for 'all' listing type)
203
+ const { data: initialFacetsData } = await useAsyncData(
204
+ props.listingType === 'all' ? `facetedSearch-facets-${JSON.stringify(props.baseFilter)}` : 'skip-facets',
205
+ async () => {
206
+ if (props.listingType !== 'all') {
207
+ return null
208
+ }
209
+ return await useGraphqlQuery('layoutOverviewFacetsSearch', {
210
+ facets: props.facets,
211
+ filter: props.baseFilter
212
+ }).then((v) => {
213
+ return v.data?.searchApiQuery ?? null
214
+ })
215
+ }
216
+ )
217
+
218
+ // Initial query to get search results
219
+ const { data: initialResultsData, refresh: refreshResults } = await useAsyncData(
220
+ `facetedSearch-results-${props.listingType}-${JSON.stringify(props.baseFilter)}-${JSON.stringify(activeFilters.value)}`,
221
+ async () => {
222
+ const filter = buildSearchFilter()
223
+ const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
224
+ filter,
225
+ limit: props.itemsPerPage,
226
+ offset: 0
227
+ })
228
+
229
+ isLoading.value = false
230
+ return response.data?.searchApiQuery ?? null
231
+ }
232
+ )
233
+
234
+ // Initialize facets from initial query (only for 'all' listing type)
235
+ if (initialFacetsData.value) {
236
+ allFacets.value = initialFacetsData.value.facets || []
237
+ }
238
+
239
+ // Function to update search results when facets change (only for 'all' listing type)
240
+ async function updateSearchResults(selections: Record<string, string[]>) {
241
+ if (props.listingType !== 'all') {
242
+ return // No dynamic updates for manual/contextual
243
+ }
244
+
245
+ try {
246
+ isLoading.value = true
247
+ currentPage.value = 1 // Reset pagination when filters change
248
+ const filter = buildSearchFilter(selections)
249
+
250
+ const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
251
+ filter,
252
+ limit: props.itemsPerPage,
253
+ offset: 0
254
+ })
255
+
256
+ if (response.data?.searchApiQuery?.results) {
257
+ // Update the results data to reflect new search results
258
+ initialResultsData.value = {
259
+ ...initialResultsData.value,
260
+ results: response.data.searchApiQuery.results,
261
+ count: response.data.searchApiQuery.count
262
+ }
263
+ }
264
+ } catch (error) {
265
+ console.error('Error updating search results:', error)
266
+ } finally {
267
+ isLoading.value = false
268
+ }
269
+ }
270
+
271
+ // Computed properties
272
+ const displayedResults = computed(() => {
273
+ return initialResultsData.value?.results || []
274
+ })
275
+
276
+ const totalCount = computed(() => {
277
+ return initialResultsData.value?.count || 0
278
+ })
279
+
280
+ const showLoadMore = computed(() => {
281
+ const currentlyDisplayed = displayedResults.value.length
282
+ return currentlyDisplayed > 0 && currentlyDisplayed < totalCount.value && !isLoading.value
283
+ })
284
+
285
+ // Transform allFacets data into the format expected by FacetsUI component
286
+ const facetData = computed(() => {
287
+ if (!allFacets.value || !Array.isArray(allFacets.value)) {
288
+ return []
289
+ }
290
+
291
+ const transformedFacets: Array<{ field: string; label: string, filter: {id: string, label: string}; count: number; }> = []
292
+
293
+ allFacets.value.forEach((facet: any) => {
294
+ if (facet?.field && facet?.filter) {
295
+ transformedFacets.push({
296
+ field: facet.field,
297
+ label: facet.label,
298
+ filter: {
299
+ id: facet.filter.id,
300
+ label: facet.filter.label
301
+ },
302
+ count: facet.count || 0,
303
+ })
304
+ }
305
+ })
306
+
307
+ return transformedFacets
308
+ })
309
+
310
+ // Event handlers
311
+ function onFacetsChange(payload: Record<string, string[]>) {
312
+ facetSelections.value = payload
313
+ updateSearchResults(payload)
314
+ }
315
+
316
+ // Default button styling based on color scheme
317
+ const defaultButtonClass = computed(() => {
318
+ const baseClasses = 'shadow-none h-auto block text-h7 font-medium py-3 px-20 rounded-full duration-300 ease-in-out w-full md:w-fit border disabled:opacity-50 disabled:cursor-not-allowed'
319
+
320
+ const colorSchemeClasses = {
321
+ none: 'bg-white text-black hover:bg-black hover:text-white border-black',
322
+ dark: 'bg-white text-black hover:bg-black hover:text-white border-black',
323
+ light: 'bg-gray-50 text-black hover:bg-black hover:text-white border-black',
324
+ accent: 'bg-white text-black hover:bg-black hover:text-white border-black'
325
+ }
326
+
327
+ return `${baseClasses} ${colorSchemeClasses[props.colorScheme] || colorSchemeClasses.none}`
328
+ })
329
+
330
+ // Load more handler
331
+ async function loadMore() {
332
+ if (loadingMore.value || isLoading.value) return
333
+ loadingMore.value = true
334
+
335
+ try {
336
+ const filter = props.listingType === 'all'
337
+ ? buildSearchFilter(facetSelections.value)
338
+ : buildSearchFilter()
339
+ const offset = currentPage.value * props.itemsPerPage
340
+
341
+ const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
342
+ filter,
343
+ limit: props.itemsPerPage,
344
+ offset
345
+ })
346
+
347
+ if (response.data?.searchApiQuery?.results) {
348
+ // Append new results to existing ones
349
+ const currentResults = initialResultsData.value?.results || []
350
+ const newResults = response.data.searchApiQuery.results
351
+
352
+ initialResultsData.value = {
353
+ ...initialResultsData.value,
354
+ results: [...currentResults, ...newResults],
355
+ count: response.data.searchApiQuery.count
356
+ }
357
+
358
+ currentPage.value += 1
359
+ }
360
+ } catch (error) {
361
+ console.error('Error loading more results:', error)
362
+ } finally {
363
+ loadingMore.value = false
364
+ }
365
+ }
366
+
367
+ // Debug logging
368
+ watchEffect(() => {
369
+ if (props.debug) {
370
+ console.log('FacetedSearch - Listing type:', props.listingType)
371
+
372
+ if (props.listingType === 'all') {
373
+ if (facetData.value.length > 0) {
374
+ console.log('FacetedSearch - Transformed facet data:', facetData.value)
375
+ }
376
+ if (allFacets.value.length > 0) {
377
+ console.log('FacetedSearch - Raw facets from GraphQL:', allFacets.value)
378
+ }
379
+ } else {
380
+ console.log('FacetedSearch - Active filters:', activeFilters.value)
381
+ }
382
+
383
+ if (displayedResults.value.length > 0) {
384
+ console.log('FacetedSearch - Results loaded:', displayedResults.value.length, 'items')
385
+ }
386
+ }
387
+ })
388
+
389
+ // Expose functions for parent components if needed
390
+ defineExpose({
391
+ refreshResults,
392
+ loadMore,
393
+ facetSelections: readonly(facetSelections),
394
+ totalCount: readonly(totalCount),
395
+ displayedResults: readonly(displayedResults)
396
+ })
397
+ </script>
@@ -0,0 +1,40 @@
1
+ query layoutOverviewFacetsSearch(
2
+ $facets: [String!],
3
+ $filter: SearchApiQueryFilterInput,
4
+ ) {
5
+ searchApiQuery(
6
+ indexId: "content_search",
7
+ facets: $facets
8
+ filter: $filter
9
+ ) {
10
+ count
11
+ facets {
12
+ field
13
+ label
14
+ filter {
15
+ id
16
+ label
17
+ }
18
+ count
19
+ }
20
+ }
21
+ }
22
+
23
+ query layoutOverviewResultsSearch(
24
+ $filter: SearchApiQueryFilterInput,
25
+ $limit: Int,
26
+ $offset: Int
27
+ ) {
28
+ searchApiQuery(
29
+ indexId: "content_search",
30
+ filter: $filter
31
+ limit: $limit
32
+ offset: $offset
33
+ ) {
34
+ count
35
+ results {
36
+ bundle: __typename
37
+ ...entityTeaser
38
+ }
39
+ }
40
+ }