@iqual/nuxt-icms 1.2.1 → 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.
Files changed (38) hide show
  1. package/components/DesignSystem/Molecules/MediaLightbox.vue +273 -0
  2. package/components/DesignSystem/Molecules/MediaSlider.vue +19 -25
  3. package/components/DesignSystem/README.md +489 -0
  4. package/components/Media/RemoteVideo/index.vue +3 -3
  5. package/components/Node/Icms/Page/index.vue +5 -3
  6. package/components/Paragraph/Card/Layout/index.vue +2 -2
  7. package/components/Paragraph/Contact/index.vue +1 -2
  8. package/components/Paragraph/Downloads/index.vue +1 -2
  9. package/components/Paragraph/FAQ/Layout/index.vue +1 -2
  10. package/components/Paragraph/FlipTeasers/index.vue +2 -2
  11. package/components/Paragraph/Gallery/index.vue +16 -14
  12. package/components/Paragraph/IconText/Layout/index.vue +1 -2
  13. package/components/Paragraph/Table/index.vue +2 -2
  14. package/components/Paragraph/Team/Layout/index.vue +2 -2
  15. package/components/Paragraph/Teasers/index.vue +3 -3
  16. package/components/Paragraph/Timeline/Layout/index.vue +6 -3
  17. package/components/Paragraph/iFrame/index.vue +16 -2
  18. package/components/Section/Footer/index.vue +15 -14
  19. package/components/Section/Header/GlobalMenu.vue +34 -34
  20. package/components/Section/Header/MetaMenu.vue +17 -19
  21. package/components/Section/Header/index.vue +21 -22
  22. package/composables/useGlobalConfig.ts +57 -0
  23. package/composables/useGraphqlCacheability.ts +22 -0
  24. package/composables/useInitData.ts +20 -112
  25. package/composables/useMediaLightbox.ts +114 -0
  26. package/composables/useMenu.ts +66 -0
  27. package/modules/dynamicEntityComponentResolver.ts +0 -20
  28. package/package.json +1 -2
  29. package/plugins/graphqlMiddleware.ts +27 -68
  30. package/plugins/initData.ts +105 -0
  31. package/{composables → queries}/query.initData.graphql +2 -8
  32. package/queries/query.loadTranslations.graphql +5 -0
  33. package/types/initData.ts +1 -0
  34. package/components/Section/Header/SearchLink.vue +0 -26
  35. package/composables/useLightbox.ts +0 -81
  36. package/composables/useMainMenuLinks.ts +0 -69
  37. package/composables/useMetaMenuLinks.ts +0 -44
  38. package/types/fslightbox-vue.d.ts +0 -1
@@ -1,118 +1,26 @@
1
- import type {
2
- GlobalConfigFragment,
3
- InitDataQuery,
4
- MenuLinkTreeElementFirstFragment,
5
- } from '#graphql-operations'
6
-
7
- export interface InitData {
8
- metaMenuLinks: MenuLinkTreeElementFirstFragment[]
9
- mainMenuLinks: MenuLinkTreeElementFirstFragment[]
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 getTranslations(
28
- v?: InitDataQuery,
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
- export default async function (): Promise<Ref<InitData>> {
53
- const currentLanguage = useCurrentLanguage()
54
- const data = useState<InitData>('initData')
55
-
56
- // Let's try to fetch the data from the cache first.
57
- const event = useRequestEvent()
58
- const { value, addToCache } = await useDataCache<InitData>(
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
+ }
@@ -106,26 +106,6 @@ export default defineNuxtModule({
106
106
  src: resolve(nuxt.options.buildDir, 'dynamic-entity-component-resolver.plugin.mjs')
107
107
  })
108
108
 
109
- // Collect all page teaser fragments from the Nuxt layers.
110
- const paragraphFragments = nuxt.options._layers
111
- .map(layer => layer.config?.icms?.components?.fragments)
112
- .filter(Boolean)
113
- .flat()
114
- .map((fragmentName) => {
115
- return `...${fragmentName}`
116
- })
117
-
118
- const fragment = `
119
- fragment paragraph on Paragraph {
120
- id
121
- parentId
122
- ${paragraphFragments.join('\n ')}
123
- }
124
- `
125
- nuxt.hooks.hookOnce('nuxt-graphql-middleware:init', (context) => {
126
- context.addDocument('fragment.paragraph.graphql', fragment)
127
- })
128
-
129
109
  // Private helper to extract unique fragment values from any routeQueries object
130
110
  function extractFragments(routeQueries: any): string[] {
131
111
  const fragments = new Set<string>();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iqual/nuxt-icms",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "ICMS Base",
5
5
  "type": "module",
6
6
  "private": false,
@@ -26,7 +26,6 @@
26
26
  "class-variance-authority": "^0.7.1",
27
27
  "clsx": "^2.1.1",
28
28
  "embla-carousel-vue": "^8.6.0",
29
- "fslightbox-vue": "^2.2.1",
30
29
  "lucide-vue-next": "^0.469.0",
31
30
  "nuxt-easy-texts": "^2.0.0",
32
31
  "nuxt-graphql-middleware": "^5.1.0",
@@ -1,7 +1,7 @@
1
1
  import { defineNuxtPlugin } from 'nuxt/app'
2
- import type { DrupalMessage } from '~/composables/useDrupalMessages'
3
- import { useCDNHeaders } from '#nuxt-multi-cache/composables'
4
- import type { GraphqlResponseTyped } from '#graphql-middleware-server-options-build'
2
+ import type { DrupalMessage } from '../composables/useDrupalMessages'
3
+ import type { GraphqlResponseTyped } from '#nuxt-graphql-middleware/response'
4
+ import { buildProxyRequestHeaders } from '~/shared/request'
5
5
 
6
6
  type GraphqlMessengerMessage = {
7
7
  type: string
@@ -30,21 +30,24 @@ function extractMessages(data: GraphqlResponseTyped): DrupalMessage[] {
30
30
  * This is only called when performing a query or mutation from within the nuxt
31
31
  * app (e.g. not via custom server routes).
32
32
  */
33
- export default defineNuxtPlugin(() => {
34
- const state = useGraphqlState()
35
- const { messages } = useDrupalMessages()
36
- const language = useCurrentLanguage()
37
- const config = useRuntimeConfig()
33
+ export default defineNuxtPlugin({
34
+ name: 'starterkit:graphql-plugin',
35
+ dependsOn: ['nuxt-graphql-middleware-provide-state', 'nuxt:router'],
36
+ setup() {
37
+ const state = useGraphqlState()
38
+ const { messages } = useDrupalMessages()
38
39
 
39
- if (!state) {
40
- return
41
- }
40
+ const event = import.meta.server ? useRequestEvent() : undefined
41
+
42
+ if (!state) {
43
+ throw new Error('Missing nuxt-graphql-middleware state.')
44
+ }
42
45
 
43
- state.fetchOptions = {
44
- /**
45
- * Interceptor called whenever a GraphQL response arrives.
46
- */
47
- onResponse(result) {
46
+ if (import.meta.server && event) {
47
+ state.fetchOptions.headers = buildProxyRequestHeaders(event)
48
+ }
49
+
50
+ state.fetchOptions.onResponse = (result) => {
48
51
  const data = result.response?._data
49
52
  if (!data) {
50
53
  return
@@ -56,60 +59,16 @@ export default defineNuxtPlugin(() => {
56
59
  if (!exists) {
57
60
  messages.value.push(v)
58
61
 
59
- // When there are messages, we have to make the whole request uncacheable.
60
- useCDNHeaders((v) => v.private())
61
- }
62
- })
63
-
64
- if (import.meta.server) {
65
- const event = useRequestEvent()
66
-
67
- useCDNHeaders((helper) => {
68
- if (!data.__cacheability?.isCacheable) {
69
- helper.private()
70
- return
62
+ if (import.meta.server) {
63
+ // When there are messages, we have to make the whole request uncacheable.
64
+ useCDNHeaders((v) => v.private())
71
65
  }
72
-
73
- helper
74
- .public()
75
- .setNumeric('sharedMaxAge', data.__cacheability.sharedMaxAge)
76
- .addTags(data.__cacheability.tagsCdn)
77
- }, event)
78
- }
79
- },
80
-
81
- onRequest({ options, request }) {
82
- // if (import.meta.server && import.meta.dev) {
83
- // console.log('GraphQL Query: ' + request)
84
- // }
85
- try {
86
- if (!options.params) {
87
- options.params = {}
88
- }
89
-
90
- /*
91
- // Add the build hash to every GraphQL request.
92
- // We do this so that after a deployment, if the user is using the
93
- // "new" version of the app, the request URL issued is now different
94
- // than the previous one and thus will not be served from cache.
95
- options.params.__h = config.public.buildHash
96
-
97
- // Add the current language to the URL
98
- options.params.__l = language.value
99
-
100
- if (import.meta.server) {
101
- options.params.__server = 'true'
102
66
  }
103
- */
67
+ })
104
68
 
105
- const requestHeaders = useRequestHeaders()
106
- Object.keys(requestHeaders).forEach((key) => {
107
- options.headers?.append(key, requestHeaders[key])
108
- })
109
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
110
- } catch (e) {
111
- // Do nothing.
69
+ if (import.meta.server && event) {
70
+ useGraphqlCacheability(event, result.response?._data)
112
71
  }
113
- },
114
- }
72
+ }
73
+ },
115
74
  })
@@ -0,0 +1,105 @@
1
+
2
+ import type {
3
+ GlobalConfigFragment,
4
+ InitDataQuery,
5
+ MenuLinkTreeElementFirstFragment,
6
+ MenuLinkTreeFragment,
7
+ } from '#graphql-operations'
8
+ import type { GraphqlResponse } from '#nuxt-graphql-middleware/response'
9
+ type InitDataResponse = GraphqlResponse<InitDataQuery>
10
+ export type MappedMenuLink = {
11
+ id: string
12
+ label: string
13
+ href?: string
14
+ children?: MappedMenuLink[]
15
+ }
16
+ export interface InitData {
17
+ metaMenuLinks: MappedMenuLink[]
18
+ mainMenuLinks: MappedMenuLink[]
19
+ footerMenuLinks: MappedMenuLink[]
20
+ footerMetaMenuLinks: MappedMenuLink[]
21
+ globalConfig: GlobalConfigFragment
22
+ }
23
+ /**
24
+ * Maps a MenuLinkTreeElementFirstFragment array to a MappedMenuLink array.
25
+ */
26
+ export function mapMenuLinkTree(
27
+ menuLinks?: (MenuLinkTreeFragment | MenuLinkTreeElementFirstFragment)[],
28
+ context: { count: number } = { count: 0 },
29
+ ): MappedMenuLink[] {
30
+ if (!menuLinks) {
31
+ return []
32
+ }
33
+ return menuLinks.map((menuLink) => {
34
+ const id = `menu-item-${context.count++}`
35
+ // Extract the basic properties
36
+ const label = menuLink.link.label
37
+ const href = menuLink.link.url?.path
38
+ // Process children if they exist
39
+ const children =
40
+ 'subtree' in menuLink && menuLink.subtree && menuLink.subtree.length > 0
41
+ ? mapMenuLinkTree(menuLink.subtree, context)
42
+ : undefined
43
+ // Return the mapped menu link
44
+ return {
45
+ id,
46
+ label,
47
+ href,
48
+ children,
49
+ }
50
+ })
51
+ }
52
+ function mapInitData(response: InitDataResponse): InitData {
53
+ if (response.data) {
54
+ return {
55
+ metaMenuLinks: mapMenuLinkTree(response.data.metaMenu?.links),
56
+ mainMenuLinks: mapMenuLinkTree(response.data.mainMenu?.links),
57
+ footerMenuLinks: mapMenuLinkTree(response.data.footerMenu?.links),
58
+ footerMetaMenuLinks: mapMenuLinkTree(response.data.footerMetaMenu?.links),
59
+ globalConfig: response.data.globalConfig || {},
60
+ }
61
+ }
62
+ throw new Error('Failed to load init data.')
63
+ }
64
+ export default defineNuxtPlugin({
65
+ name: 'starterkit:init-data',
66
+ dependsOn: [
67
+ 'nuxt-graphql-middleware-provide-state',
68
+ 'starterkit:graphql-plugin',
69
+ 'nuxt:router',
70
+ ],
71
+ async setup() {
72
+ const data = useState<InitData | null>('initData', () => null)
73
+ if (import.meta.server) {
74
+ const event = useRequestEvent()
75
+ const language = useCurrentLanguage()
76
+ if (!event) {
77
+ throw new Error('Missing request event.')
78
+ }
79
+ const { value: cachedResponse, addToCache } =
80
+ await useDataCache<InitDataResponse>(
81
+ 'initData_' + language.value,
82
+ event,
83
+ )
84
+ const response = cachedResponse || (await useGraphqlQuery('initData'))
85
+ data.value = mapInitData(response)
86
+ if (!cachedResponse && response.extensions.cacheability?.isCacheable) {
87
+ await addToCache(response, response.extensions.cacheability?.tagsNuxt)
88
+ }
89
+ }
90
+ if (import.meta.client) {
91
+ async function loadInitData() {
92
+ data.value = await useGraphqlQuery('initData', null, {
93
+ graphqlCaching: {
94
+ client: true,
95
+ },
96
+ }).then(mapInitData)
97
+ }
98
+ if (!data.value) {
99
+ await loadInitData()
100
+ }
101
+ const language = useCurrentLanguage()
102
+ watch(language, loadInitData)
103
+ }
104
+ },
105
+ })
@@ -83,16 +83,10 @@ fragment globalConfig on TranslatableConfigPagesGlobal {
83
83
  phoneNumber: fieldIcmsPhoneNumber
84
84
  emailAddress: fieldIcmsEmailAddress
85
85
  contactButtons: fieldIcmsContactButtons {
86
- ...paragraphsFieldItem
87
- props {
88
- ...paragraphIcmsButtonElement
89
- }
86
+ ...paragraphIcmsButtonElement
90
87
  }
91
88
  metaLinks: fieldIcmsMetaLinks {
92
- ...paragraphsFieldItem
93
- props {
94
- ...paragraphIcmsButtonElement
95
- }
89
+ ...paragraphIcmsButtonElement
96
90
  }
97
91
  socialMediaLinks: fieldIcmsSocialMediaLinks {
98
92
  uri {
@@ -0,0 +1,5 @@
1
+ query loadTranslations {
2
+ translations: textsLoader {
3
+ ...easyTexts
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ export type MenuName = 'metaMenu' | 'mainMenu' | 'footerMenu' | 'footerMetaMenu'
@@ -1,26 +0,0 @@
1
- <template>
2
- <div
3
- class="pr-4 font-medium lg:pr-12"
4
- :class="{
5
- 'sticky top-0': isSticky,
6
- }"
7
- >
8
- <nuxt-link
9
- :to="{ name: 'search' }"
10
- class="flex h-10 items-center gap-1 px-3 text-primary-500 lg:h-[50px]"
11
- >
12
- <span class="sr-only lg:not-sr-only">
13
- {{ $texts('header.search', 'Suche') }}
14
- </span>
15
- <SpriteSymbol name="magnifyingglass" class="size-5" />
16
- </nuxt-link>
17
- </div>
18
- </template>
19
-
20
- <script lang="ts" setup>
21
- defineProps<{
22
- isSticky: boolean
23
- }>()
24
-
25
- const { $texts } = useNuxtApp()
26
- </script>