{"version":3,"file":"FooterApp.js","sources":["../src/components/dhf-accordion/dhf-accordion.vue","../src/constants/form.constants.ts","../src/components/dhf-form/dhf-form.vue","../src/utils/isLinkList.ts","../src/components/dhf-footer/dhf-footer.vue","../src/FooterApp.vue"],"sourcesContent":["<template>\n <div class=\"dhf-accordion-group\">\n <h3 class=\"dhf-accordion-group__control\">\n <button\n :id=\"`dhf-accordion-group__control-button-${props.id}`\"\n :aria-controls=\"`dhf-accordion-group__section-${props.id}`\"\n :aria-expanded=\"isExpanded\"\n class=\"dhf-accordion-group__control-button\"\n type=\"button\"\n @click=\"toggleAccordion()\"\n >\n <slot name=\"title\" />\n <span class=\"dhf-accordion-group__icon\" :class=\"{ 'dhf-accordion-group__icon--active': isExpanded }\">\n <DhfIcon name=\"minus\" />\n <DhfIcon name=\"minus\" />\n </span>\n </button>\n </h3>\n\n <Transition name=\"expand\">\n <div\n v-show=\"isExpanded\"\n :id=\"`dhf-accordion-group__section-${props.id}`\"\n ref=\"bodyElement\"\n role=\"region\"\n :style=\"{ 'max-height': maxHeight + 'px' }\"\n :aria-labelledby=\"`dhf-accordion-group__control-button-${props.id}`\"\n class=\"dhf-accordion-group__section\"\n >\n <slot name=\"content\" />\n </div>\n </Transition>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { onBeforeUnmount, ref } from 'vue';\nimport DhfIcon from '@/components/dhf-icon/dhf-icon.vue';\n\nconst isExpanded = ref(false);\nconst bodyElement = ref<HTMLElement>();\nconst maxHeight = ref<number>(0);\nlet animationTimeout: any = null;\n\nconst props = defineProps<{\n id?: string;\n}>();\n\nfunction toggleAccordion() {\n const accordionElement = bodyElement.value;\n\n if (!accordionElement) {\n return;\n }\n\n isExpanded.value = !isExpanded.value;\n\n // wait until styling from transition component was done\n animationTimeout = setTimeout(() => {\n maxHeight.value = isExpanded.value ? accordionElement.scrollHeight : 0;\n }, 1);\n}\n\nonBeforeUnmount(() => {\n clearTimeout(animationTimeout);\n});\n</script>\n\n<style lang=\"scss\">\n@import './dhf-accordion.scss';\n</style>\n","export const LOCATOR_TRACKING_NAME = 'Find a Miele Partner';\nexport const LOCATOR_STORAGE_KEY = 'mieleFinderQueryString';\nexport const NEWSLETTER_TRACKING_NAME = 'Newsletter Subscription';\nexport const NEWSLETTER_STORAGE_KEY = 'newsletterEmail';\n","<template v-if=\"data?.isActive\">\n <div class=\"dhf-form\">\n <p v-if=\"data.formLabel\" class=\"dhf-form__section-title\" :aria-label=\"data.formLabel\">\n {{ data.formLabel }}\n </p>\n <form\n :action=\"data.href\"\n class=\"dhf-form__form\"\n :class=\"{ 'dhf-form__form--has-focus': isFocused }\"\n method=\"post\"\n @submit=\"handleSubmit\"\n >\n <label class=\"dhf-form__input-label\" :for=\"data.id\" :aria-label=\"data.label\">\n {{ data.label }}\n </label>\n <span class=\"dhf-form__input-field\">\n <input\n :id=\"data.id\"\n v-model=\"formInput\"\n :type=\"data.type\"\n :name=\"data.name\"\n :placeholder=\"data.placeholder\"\n class=\"dhf-form__input\"\n @focus=\"isFocused = true\"\n @blur=\"isFocused = false\"\n />\n <button\n type=\"submit\"\n class=\"dhf-form__button\"\n :data-testId=\"`dhf-footer-onSubmit-${data.label}`\"\n :aria-label=\"`Submit ${data.name}`\"\n >\n <DhfIcon name=\"arrow-angle\" />\n </button>\n </span>\n </form>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue';\nimport { useTracking } from '@/composables/useTracking';\nimport DhfIcon from '@/components/dhf-icon/dhf-icon.vue';\nimport type { Input } from '@/types/shared-types';\nimport {\n LOCATOR_TRACKING_NAME,\n LOCATOR_STORAGE_KEY,\n NEWSLETTER_TRACKING_NAME,\n NEWSLETTER_STORAGE_KEY,\n} from '@/constants/form.constants';\n\nconst props = withDefaults(\n defineProps<{\n data: Input;\n isNewsletter?: boolean;\n isLocator?: boolean;\n }>(),\n {\n isNewsletter: false,\n isLocator: false,\n }\n);\n\nconst { doFooterDataLayerPush } = useTracking();\nconst formInput = ref<string>('');\nconst isFocused = ref(false);\n\nconst handleSubmit = () => {\n saveToLocalStorage(formInput.value);\n doFooterDataLayerPush(\n props.isLocator ? LOCATOR_TRACKING_NAME : NEWSLETTER_TRACKING_NAME,\n `${props.data.label} | ${props.data.href}`,\n props.data.href,\n props.data.label\n );\n};\n\nfunction saveToLocalStorage(inputValue: string) {\n if (props.isLocator) {\n sessionStorage.setItem(LOCATOR_STORAGE_KEY, window.btoa(`loc=${inputValue}`));\n }\n if (props.isNewsletter) {\n localStorage.setItem(NEWSLETTER_STORAGE_KEY, inputValue);\n }\n}\n</script>\n\n<style lang=\"scss\">\n@import './dhf-form.scss';\n</style>\n","import type { Category, Link } from '@/types/shared-types';\n\nexport const isLinkList = function (items: Category[] | Link[] | undefined): items is Link[] {\n return (items as Category[])[0].items === undefined;\n};\n","<!-- eslint-disable vue/no-v-html -->\n<template>\n <footer class=\"dhf-footer\" :class=\"{ 'dhf-footer--minimal': minimal }\">\n <div class=\"dhf-footer__inner\">\n <div v-if=\"!minimal && data\" class=\"dhf-footer__top-section\">\n <div class=\"dhf-footer__top-section-sidebar\">\n <DhfForm\n :data=\"data.mielePartner\"\n class=\"dhf-footer__top-section-sidebar-mielePartner\"\n :is-locator=\"true\"\n />\n\n <div class=\"dhf-footer__top-section-sidebar-experienceCenter\">\n <p\n class=\"dhf-footer__top-section-sidebar-experienceCenter-label\"\n v-html=\"data.experienceCenter.label\"\n ></p>\n <ul v-if=\"isLinkList(data.experienceCenter.items)\">\n <li\n v-for=\"(item, index) in data.experienceCenter.items\"\n :key=\"index\"\n class=\"dhf-footer__top-section-sidebar-experienceCenter-item\"\n >\n <a\n v-if=\"item.isActive\"\n :href=\"item.href\"\n :target=\"item.target\"\n :data-testId=\"`dhf-footer-experienceCenter-link-${index}`\"\n @click=\"\n doFooterDataLayerPush(\n EventActionsFooter.experienceCenter,\n `${item.label} | ${item.href}`,\n item.href,\n item.label\n )\n \"\n v-html=\"item.label\"\n ></a>\n </li>\n </ul>\n </div>\n\n <DhfForm\n :data=\"data.newsletter\"\n class=\"dhf-footer__top-section-sidebar-newsletter\"\n :is-newsletter=\"true\"\n />\n\n <div class=\"dhf-footer__top-section-contact\">\n <p class=\"dhf-footer__top-section-contact-label\" v-html=\"data.contact.label\"></p>\n <ul class=\"dhf-footer__top-section-contact-numbersList\">\n <li v-for=\"(item, index) in data.contact.items\" :key=\"index\">\n <a\n :href=\"item.type === 'phone' ? `tel:${item.value}` : `mailto:${item.value}`\"\n @click=\"\n doFooterDataLayerPush(\n EventActionsFooter.contact,\n `${data?.contact.label} | ${item.value}`,\n item.value,\n data?.contact.label || ''\n )\n \"\n v-html=\"item.value\"\n >\n </a>\n </li>\n </ul>\n </div>\n\n <div v-if=\"resolvedLanguageResources\">\n <p class=\"dhf-footer__top-section-language-label\">\n {{ ct('nav.language-label') }}\n </p>\n <ul class=\"dhf-footer__top-section-language\" role=\"menu\">\n <li class=\"dhf-footer__top-section-language\" role=\"menuitem\">\n <div class=\"dhf-footer__top-section-language-wrapper\">\n <dhf-language-select\n v-if=\"resolvedLanguageResources\"\n :language-resources=\"resolvedLanguageResources\"\n :custom-class-list=\"'dhf-footer__top-section-language-dropdown'\"\n />\n </div>\n </li>\n </ul>\n </div>\n </div>\n <div class=\"dhf-footer__top-section-categories\">\n <div\n v-for=\"(category, index) in data.categories\"\n :key=\"index\"\n class=\"dhf-footer__top-section-categories-item\"\n >\n <DhfAccordion :id=\"index.toString()\" class=\"dhf-footer__top-section-categories-item-mobile\">\n <template #title>\n <span\n class=\"dhf-footer__top-section-categories-item-label\"\n v-html=\"category.label\"\n ></span>\n </template>\n <template #content>\n <ul class=\"dhf-footer__top-section-categories-item-accordion-list\">\n <li v-for=\"(item, i) in category.items\" :key=\"i\">\n <a\n :href=\"item.href\"\n @click=\"\n doFooterDataLayerPush(\n EventActionsFooter.footerLinks,\n `${item.label} | ${item.href}`,\n item.href || '',\n item.label\n )\n \"\n v-html=\"item.label\"\n ></a>\n </li>\n </ul>\n </template>\n </DhfAccordion>\n <div class=\"dhf-footer__top-section-categories-item-desktop\">\n <p class=\"dhf-footer__top-section-categories-item-label\" v-html=\"category.label\"></p>\n <ul>\n <li v-for=\"(item, i) in category.items\" :key=\"i\">\n <a\n :href=\"item.href\"\n @click=\"\n doFooterDataLayerPush(\n EventActionsFooter.footerLinks,\n `${item.label} | ${item.href}`,\n item.href || '',\n item.label\n )\n \"\n v-html=\"item.label\"\n ></a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n\n <hr v-if=\"!minimal\" class=\"dhf-footer__divider\" />\n\n <div v-if=\"data\" class=\"dhf-footer__bottom-section\">\n <div class=\"dhf-footer__bottom-section-legal\">\n <ul>\n <li\n v-for=\"(item, index) in data.legal\"\n :key=\"index\"\n class=\"dhf-footer__bottom-section-legal-item\"\n >\n <a\n v-if=\"item.isActive\"\n :href=\"item.href\"\n :target=\"item.target\"\n :data-testId=\"`dhf-footer-bootom-section-link-${index}`\"\n @click=\"\n doFooterDataLayerPush(\n EventActionsFooter.legal,\n `${item.label} | ${item.href}`,\n item.href,\n item.label\n )\n \"\n v-html=\"item.label\"\n ></a>\n </li>\n <li v-if=\"showCookieSettingsLink\" class=\"dhf-footer__bottom-section-legal-item\">\n <button id=\"ot-sdk-btn\" class=\"ot-sdk-show-settings\">Cookie Settings</button>\n </li>\n <li v-if=\"data.showDoNotSellMyInformationLink\" class=\"dhf-footer__bottom-section-legal-item\">\n <button class=\"not-sell-myinfo-button\" onclick=\"showCookieBanner();\" autocomplete=\"off\">\n {{ data.doNotSellMyInformationLabel }}\n </button>\n </li>\n </ul>\n </div>\n\n <div class=\"dhf-footer__bottom-section-social\">\n <a\n v-for=\"(item, index) in data.social\"\n :key=\"index\"\n :href=\"item.href\"\n :target=\"item.target\"\n :data-testId=\"`dhf-footer-social-${item.label}`\"\n @click=\"\n doFooterDataLayerPush(\n EventActionsFooter.social,\n `${item.label} | ${item.href}`,\n item.href,\n item.label,\n item.type\n )\n \"\n >\n <DhfIcon v-if=\"item.isActive\" :name=\"item.type\" :title=\"item.label\" />\n </a>\n </div>\n\n <div class=\"dhf-footer__bottom-section-payment\">\n <a\n v-for=\"(item, index) in data.payment\"\n :key=\"index\"\n :data-testId=\"`dhf-footer-payment-link-${item.label}`\"\n >\n <img :src=\"item.url\" :alt=\"item.label\" />\n </a>\n </div>\n </div>\n </div>\n </footer>\n\n <template v-if=\"data?.bnplFindomestic?.title || data?.bnplFindomestic?.message\">\n <div class=\"dhf-footer__financing-section\">\n <h4 class=\"dhf-footer__financing-section-title\" v-html=\"data.bnplFindomestic.title\"></h4>\n <p class=\"dhf-footer__financing-section-message\" v-html=\"data.bnplFindomestic.message\"></p>\n </div>\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, ref, onMounted, watch } from 'vue';\nimport type { FooterProps, ILanguageObject, ILanguageResources } from '@/types/shared-types';\nimport DhfAccordion from '@/components/dhf-accordion/dhf-accordion.vue';\nimport DhfForm from '@/components/dhf-form/dhf-form.vue';\nimport DhfIcon from '@/components/dhf-icon/dhf-icon.vue';\nimport { isLinkList } from '@/utils/isLinkList';\nimport { useTracking } from '@/composables/useTracking';\nimport useTranslations from '@/composables/useTranslations';\nimport DhfLanguageSelect from '@/components/dhf-language-select/dhf-language-select.vue';\nimport { useAlternateLanguage } from '@/composables/useAlternateLanguage';\n\nconst props = withDefaults(\n defineProps<{\n data: FooterProps | null;\n minimal: boolean;\n showCookieSettingsLink?: boolean;\n languageObject?: ILanguageObject | undefined;\n }>(),\n {\n showCookieSettingsLink: false,\n }\n);\n\nconst { EventActionsFooter, doFooterDataLayerPush } = useTracking();\n\nconst ct = useTranslations();\n\nconst resolvedLanguageResources = ref<ILanguageResources>();\n\nonMounted(async () => {\n const languageSelect = useAlternateLanguage() ?? undefined;\n\n if (languageSelect) {\n if (!props.languageObject) {\n const { data } = languageSelect.useLanguageQuery();\n\n if (data.value) {\n resolvedLanguageResources.value = await languageSelect.getLanguageResources(data.value);\n }\n\n watch(data, async () => {\n try {\n resolvedLanguageResources.value = await languageSelect.getLanguageResources(data.value);\n } catch (err) {\n console.error(err);\n throw err;\n }\n });\n } else if (props.languageObject && props.languageObject.languages?.length > 1) {\n resolvedLanguageResources.value = (await languageSelect.getLanguageResources(props.languageObject)) ?? null;\n\n watch([props], async () => {\n try {\n resolvedLanguageResources.value =\n (await languageSelect.getLanguageResources(props.languageObject)) ?? null;\n } catch (err) {\n console.error(err);\n throw err;\n }\n });\n }\n }\n});\n</script>\n\n<style lang=\"scss\">\n@import './dhf-footer.scss';\n</style>\n","<template>\n <DhfFooter\n :data=\"footerNavContents\"\n :minimal=\"useMinimalFooter\"\n :show-cookie-settings-link=\"showCookieSettingsLink\"\n :language-object=\"props?.languageObject\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue';\nimport DhfFooter from '@/components/dhf-footer/dhf-footer.vue';\nimport { useNavigationQuery } from '@/composables/useNavigation';\nimport { useTracking } from '@/composables/useTracking';\nimport type { IFooterAppProps, FooterProps } from '@/types/shared-types';\nimport useConfiguration from './composables/useConfiguration';\n\nconst props = withDefaults(defineProps<IFooterAppProps>(), {\n baseUrl: undefined,\n useDevNavigation: false,\n navigationData: undefined,\n minimal: false,\n isGtmEnabled: false,\n languageObject: undefined,\n});\n\nconst footerNavContents = ref<FooterProps | null>(null);\nconst showCookieSettingsLink = ref<boolean>(false);\n\n// For context check ECOMNOW-1654\nconst { setEnabled } = useTracking();\nwatch(\n () => props.isGtmEnabled,\n () => {\n setEnabled(props.isGtmEnabled);\n }\n);\n\nconst useMinimalFooter = computed(() => {\n if (typeof props.minimal === 'boolean') return props.minimal;\n\n return props.minimal.toLowerCase() === 'true';\n});\n\nonMounted(() => {\n const { globalsConfig, loadConfig } = useConfiguration(props?.globalsConfig);\n\n loadConfig().then(() => {\n if (!globalsConfig.value) return;\n const isCookieNoticeUrl = Boolean(globalsConfig.value['module.cookieNotice.url']);\n showCookieSettingsLink.value = !isCookieNoticeUrl;\n });\n});\n\n// Headless apps may pass in the navigation object, which\n// should be preferred over component fetching for SSR\nif (!props.navigationData) {\n const { data } = useNavigationQuery({\n useDev: props.useDevNavigation || false,\n baseUrl: props.baseUrl,\n });\n\n if (data.value?.footer) footerNavContents.value = data.value.footer;\n\n watch(data, () => {\n if (data.value?.footer) footerNavContents.value = data.value.footer;\n });\n} else {\n footerNavContents.value = props.navigationData || null;\n}\n</script>\n\n<style lang=\"scss\">\n@import './styles/app.scss';\n</style>\n"],"names":["isExpanded","ref","bodyElement","maxHeight","animationTimeout","props","__props","toggleAccordion","accordionElement","onBeforeUnmount","LOCATOR_TRACKING_NAME","LOCATOR_STORAGE_KEY","NEWSLETTER_TRACKING_NAME","NEWSLETTER_STORAGE_KEY","doFooterDataLayerPush","useTracking","formInput","isFocused","handleSubmit","saveToLocalStorage","inputValue","isLinkList","items","EventActionsFooter","ct","useTranslations","resolvedLanguageResources","onMounted","languageSelect","useAlternateLanguage","_a","watch","err","data","footerNavContents","showCookieSettingsLink","setEnabled","useMinimalFooter","computed","globalsConfig","loadConfig","useConfiguration","isCookieNoticeUrl","useNavigationQuery"],"mappings":"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"}