{"version":3,"file":"index.es.min.js","sources":["../../../packages/helpers/src/props.helpers.js","../../../packages/helpers/src/utils.ts","../../../packages/helpers/src/assets/js/eventDispatch.js","../../../packages/components/src/constants.mjs","../../../packages/page-builder-sections/src/content-composer/helpers/tracking.js","../../../packages/page-builder-sections/src/content-composer/helpers/renderButtons.js","../../../packages/helpers/src/viewport.helpers.ts","../../../packages/page-builder-sections/src/content-composer/helpers/getImage.js","../../../packages/page-builder-sections/src/content-composer/subcomponents/card.class.js","../../../packages/helpers/src/getCurrency.js","../../../packages/helpers/src/catalog.js","../../../packages/helpers/src/events.helpers.ts","../../../packages/helpers/src/gtmEvents.js","../../../packages/helpers/src/dataLayer.js","../../../packages/helpers/src/cremaDataHelper.js","../../../packages/components/src/sku-coffee/services/index.js","../../../packages/page-builder-sections/src/cross-sell-natural/dataTransform/product.coffee.dto.js","../../../services/plp/services.js","../../../packages/components/src/sku/services/index.js","../../../packages/page-builder-sections/src/content-composer/subcomponents/index.js","../../../packages/page-builder-sections/src/content-composer/subcomponents/video-card/video-card.composer.js","../../../packages/page-builder-sections/src/content-composer/subcomponents/image-card/image-card.composer.js","../../../packages/page-builder-sections/src/content-composer/subcomponents/product-card/product-card.composer.js","../../../packages/page-builder-sections/src/content-composer/subcomponents/product-sku/product-sku.composer.js","../../../packages/page-builder-sections/src/cross-sell-natural/dataTransform/product.dto.js","../../../packages/components/src/sku/constants.mjs","../../../packages/page-builder-sections/src/cross-sell-natural/dataTransform/product.machine.dto.js","../../../packages/page-builder-sections/src/cross-sell-natural/dataTransform/product.accessory.dto.js","../../../packages/page-builder-sections/src/cross-sell-natural/dataTransform/product.giftCard.dto.js","../../../packages/page-builder-sections/src/content-composer/subcomponents/text-card/text-card.composer.js","../../../packages/page-builder-sections/src/content-composer/helpers/columnsSizes.js","../../../packages/helpers/src/swipeEvents.ts","../../../packages/helpers/src/assets/js/scopedKeyboardNav.js","../../../packages/components/src/popin/components/overlay.js","../../../packages/components/src/popin/popin.js","../../../packages/page-builder-sections/src/content-composer/content-composer.js"],"sourcesContent":["const getData = attributes => attributes.find(attribute => attribute.nodeName === 'data')\n\nconst createProps = attributes => {\n const data = getData([...attributes])\n const props = [...attributes]\n .filter(attribute => attribute.nodeName !== 'data')\n .reduce((all, attr) => {\n return { ...all, [attr.nodeName]: attr.nodeValue }\n }, {})\n\n if (isNil(data)) {\n return props\n }\n\n try {\n return { ...props, ...JSON.parse(data.nodeValue) }\n } catch (error) {\n console.log('ERROR: No data', error, data?.nodeValue)\n }\n}\n\nconst isNil = obj => obj === undefined || obj === null\n\nexport const parseBool = value => (!value || value === 'false' ? false : true)\n\nexport default createProps\n","export { waitForSelector } from './waitForSelector'\n\nexport const constants = {\n LEFT: 37,\n UP: 38,\n RIGHT: 39,\n DOWN: 40,\n ESC: 27,\n SPACE: 32,\n ENTER: 13,\n TAB: 9\n}\n\nexport function capitalize(s = '') {\n return s[0].toUpperCase() + s.slice(1)\n}\n\nexport const convertToCamelCase = (str: string): string => {\n const arr = str.match(/[a-z]+|\\d+/gi)\n if (!arr) { return str }\n return arr.map((m, i) => {\n let low = m.toLowerCase()\n if (i !== 0) {\n low = low.split('').map((s, k) => (k === 0 ? s.toUpperCase() : s)).join(\"\")\n }\n return low\n }).join(\"\")\n}\n\nexport function slug(s = '') {\n return s\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, '-') // Replace spaces with -\n .replace(/[^\\w-]+/g, '') // Remove all non-word chars\n .replace(/--+/g, '-') // Replace multiple - with single -\n}\n\nexport function pxToEm(target: number, stripedInnerFontSize = 1) {\n return target / 14 / stripedInnerFontSize + 'em'\n}\n\nexport function percent(target: number) {\n return target + '%'\n}\n\nexport function parseHTML(str: string) {\n const tmp = document.implementation.createHTMLDocument('')\n tmp.body.innerHTML = str\n return tmp.body.childNodes\n}\n\nexport function stripHTML(str: string) {\n const tmp = document.implementation.createHTMLDocument('')\n tmp.body.innerHTML = str\n return (tmp.body.textContent ?? \"\").replace(RegExp('[\\\\s|\\'|\"]', 'g'), '')\n}\n\nexport function makeId(length: number) {\n var result = ''\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n var charactersLength = characters.length\n for (var i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength))\n }\n return result\n}\n\nexport function removeEmptyValues(obj: { [key: string]: any }): { [key: string]: any } {\n const findText = [\n 'Default campaign ID (tracking missing in Page Builder export)',\n 'Default campaign name (tracking missing in Page Builder export)',\n 'promoname', \n 'promoid', \n 'promocreative', \n 'undefined'\n ];\n \n for (let key in obj) {\n const value = obj[key];\n \n if (value === null || value === undefined || value === '') {\n delete obj[key];\n continue;\n }\n \n if (typeof value === 'string') {\n for (const text of findText) {\n if (value.includes(text)) {\n delete obj[key];\n break;\n }\n }\n }\n }\n \n return obj;\n}\n\nexport function makeHash(str: string) {\n var hash = 0,\n i,\n chr\n if (!str) {\n return hash\n }\n for (i = 0; i < str.length; i++) {\n chr = str.charCodeAt(i)\n hash = (hash << 5) - hash + chr\n hash |= 0 // Convert to 32bit integer\n }\n return 'id-' + hash\n}\n\nexport function getHashLink(link: string) {\n let linkHash = link\n let linkNoHash = link\n if (link.indexOf('#') !== -1) {\n linkNoHash = link.replace('#', '')\n } else {\n linkHash = '#' + link\n }\n\n return { linkNoHash, linkHash }\n}\n\nexport function lazyLoad(node: Element, attribute: string, value: any, url: string) {\n const CLASSNAME_OUT_OF_SCREEN = 'lazy-load'\n const CLASSNAME_IN_SCREEN = 'lazy-loaded'\n const CLASSNAME_ON_ERROR = 'lazy-loaded-error'\n\n const isOldIOS = () => {\n var agent = window.navigator.userAgent,\n start = agent.indexOf('OS ')\n if ((agent.indexOf('iPhone') > -1 || agent.indexOf('iPad') > -1) && start > -1) {\n return window.Number(agent.substr(start + 3, 3).replace('_', '.')) < 14\n }\n return false\n }\n\n const inViewPort = (attribute: string, value: any) => {\n node.setAttribute(attribute, value)\n\n const cb = () => node.classList.add(CLASSNAME_IN_SCREEN)\n\n if (url) {\n const img = new Image()\n img.src = url\n img.onload = cb\n img.onerror = () => {\n cb()\n node.classList.add(CLASSNAME_ON_ERROR)\n throw new Error(`Image ${url} cannot be loaded`)\n }\n\n return\n }\n\n cb()\n }\n\n if (/Trident\\/|MSIE/.test(window.navigator.userAgent) || isOldIOS()) {\n inViewPort(attribute, value)\n } else {\n if ('IntersectionObserver' in window) {\n node.classList.add(CLASSNAME_OUT_OF_SCREEN)\n let lazyBackgroundObserver = new IntersectionObserver(function (entries) {\n entries.forEach(function (entry) {\n if (entry.isIntersecting) {\n inViewPort(attribute, value)\n lazyBackgroundObserver.unobserve(entry.target)\n }\n })\n })\n lazyBackgroundObserver.observe(node)\n } else {\n inViewPort(attribute, value)\n }\n }\n}\n\nexport function lazyLoadCallback(node: Element, cb: () => void) {\n const isOldIOS = () => {\n var agent = window.navigator.userAgent,\n start = agent.indexOf('OS ')\n if ((agent.indexOf('iPhone') > -1 || agent.indexOf('iPad') > -1) && start > -1) {\n return window.Number(agent.substr(start + 3, 3).replace('_', '.')) < 14\n }\n return false\n }\n\n if (/Trident\\/|MSIE/.test(window.navigator.userAgent) || isOldIOS()) {\n cb()\n } else {\n if ('IntersectionObserver' in window) {\n let lazyBackgroundObserver = new IntersectionObserver(\n function (entries) {\n entries.forEach(function (entry) {\n if (entry.isIntersecting) {\n cb()\n lazyBackgroundObserver.unobserve(entry.target)\n }\n })\n },\n { rootMargin: '150% 0px' }\n )\n lazyBackgroundObserver.observe(node)\n }\n }\n}\n\n// Debounce\nexport function debounce<T>(func: (v: T) => void, time = 100) {\n let timer: number\n return function (event: T) {\n if (timer) {\n window.clearTimeout(timer)\n }\n timer = window.setTimeout(func, time, event)\n }\n}\n\n// isIE - to check for internet explorer\nexport function isIE() {\n let ua = window.navigator.userAgent,\n isIE = /MSIE|Trident/.test(ua)\n\n return isIE\n}\n\n// Load external script\nexport const loadExternalScript = ({\n src,\n callback = null,\n async = false,\n defer = false,\n module = false,\n id = ''\n}: {\n src: string;\n callback: null | GlobalEventHandlers[\"onload\"]\n module: boolean,\n defer: boolean,\n async: boolean,\n id: string\n}) => {\n const script = document.createElement('script')\n script.type = module ? 'module' : 'text/javascript'\n script.src = src\n id ? (script.id = id) : false // add id attribute only if passed\n if (typeof callback === 'function') {\n script.onload = callback\n }\n script.async = async\n script.defer = defer\n document.body.appendChild(script)\n}\n\n// Load external css\nexport const loadExternalCss = ({ src }: { src: string }) => {\n const script = document.createElement('link')\n script.rel = 'stylesheet'\n script.href = src\n document.body.appendChild(script)\n}\n// Lazy load vendor script\nexport const lazyLoadVendorScript = (handler, el) => {\n const observer = new IntersectionObserver(handler)\n observer.observe(el)\n}\n\n/**\n * Replaces variable inside a given string\n * Each variable have to be enclosed between stChr and enChr\n * The values have to be contained in the vars object, they key must match\n * example :\n * txt : 'See {resultsLength} Results'\n * vars : {resultsLength:'30'}\n * stChr : '{'\n * enChr : '}'\n *\n * will return : 'See 30 Results'\n *\n * @param {string} txt\n * @param {object} vars\n * @param {string} stChr\n * @param {string} enChr\n */\nexport function interpolate(txt: string, vars: Record<string, null | undefined | string>, stChr: string, enChr: string) {\n let curIdx = 0\n\n while (txt) {\n const stIdx = txt.indexOf(stChr, curIdx)\n if (stIdx === -1) {\n break\n }\n const enIdx = txt.indexOf(enChr, stIdx + 1)\n if (enIdx === -1) {\n break\n }\n const hashId = txt.substring(stIdx + stChr.length, enIdx)\n if (vars[hashId] != null) {\n txt = txt.substr(0, stIdx) + vars[hashId] + txt.substr(enIdx + enChr.length)\n curIdx = stIdx\n } else {\n curIdx = enIdx\n }\n }\n return txt\n}\n\n/**\n * Find in container element, add height to equal size of element\n * @param container css path where my element is contain e.g. `.c-container`\n * @param el css path of elements to equalized\n */\nexport const equalHeight = (containerSelector: string, el: string, elementScope: HTMLElement) => {\n const container = elementScope.querySelector<HTMLElement>(containerSelector)\n if (!container) {\n return\n }\n\n const items = container.querySelectorAll<HTMLElement>(el)\n let max = -1\n\n for (let i = 0; i < [...items].length; i++) {\n const item = [...items][i]\n let h = item.offsetHeight\n max = h > max ? h : max\n }\n\n if (max <= 0) {\n return\n }\n\n for (let i = 0; i < [...items].length; i++) {\n const item = [...items][i]\n item.style.height = `${max}px`\n }\n}\n\nexport const stringifyCurlyQuote = (data: {}) => JSON.stringify(data).replace(\"'\", '’')\n\nexport const stringifyForAttribute = (data = {}) => {\n return escapeHtml(JSON.stringify(data))\n}\n\n/**\n * This function is included instead of sanitizeString because for\n * inserting HTML into innerHTML we need to make sure all HTML\n * entities are escaped.\n */\nexport const escapeHtml = (text: string) => {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n } as { [s: string]: string }\n\n return text.replace(/[&<>\"']/g, (m) => map[m])\n}\n\n/**\n * Because setting attributes escapes more than the characters above and then preact also\n * escapes text we need a more complete way of unescaping all html entities (not just the ones\n * above)\n */\nconst domParser = new DOMParser()\nexport const unescapeHtml = (text: string) => {\n return domParser.parseFromString(text, \"text/html\").body.textContent\n}\n\nexport const sanitizeString = (data: {}) => {\n if (!data) {\n return ''\n }\n\n return data.toString().replace(/\"/g, '"').replace(/'/g, ''')\n}\n\nexport const stripTags = (s: string) => {\n return (s || '').replace(/(<([^>]+)>)/gi, '')\n}\n\nexport const setAttributes = (element: Element, attrs: Record<string, any>) => {\n for (let key in attrs) {\n element.setAttribute(key, attrs[key])\n }\n return element\n}\n\nexport const getMetaContent = (metaName: string) => {\n const metaTag = document.querySelector(`meta[name=${metaName}]`)\n if (!metaTag) {\n return ''\n }\n return metaTag.getAttribute('content')\n}\n\nexport const isObjectEmpty = (obj: {}) => {\n return Object.keys(obj).length === 0\n}\n","export const dispatchEvent = ({ eventName, args, element }) => {\n // Use the provided element or fallback to window if available\n if (!element) {\n if (typeof window !== 'undefined') {\n element = window\n } else {\n throw new Error(\n '`element` is not provided and `window` is unavailable. Provide a valid element to dispatch the event.'\n )\n }\n }\n\n let event\n if (args) {\n event = new CustomEvent(eventName, { detail: args, bubbles: true })\n } else {\n if (typeof Event === 'function') {\n event = new Event(eventName)\n } else {\n event = document.createEvent('Event')\n event.initEvent(eventName, true, true)\n }\n }\n element.dispatchEvent(event)\n}\n\nexport const readEvent = e => {\n if (!e.detail) {\n return\n }\n return e.detail\n}\n","export const MAX_WIDTH_CONTAINER = 1160\n\nexport const BREAKPOINT_XL = 1920\nexport const BREAKPOINT_TABLET = 1024\nexport const BREAKPOINT_L = 996\nexport const BREAKPOINT_M = 768\nexport const BREAKPOINT_S = 750\nexport const BREAKPOINT_XS = 375\n\nexport const CTA_PRIMARY = 'primary'\nexport const CTA_PRIMARY_TRANSPARENT = 'primary_transparent'\nexport const CTA_SUBTLE = 'subtle'\nexport const CTA_LINK = 'link'\nexport const CTA_LINK_UNDERLINE = 'link-underline'\nexport const CTA_LINK_GOLD = 'link-gold'\nexport const CTA_LINK_ADD_TO_CART_SMALL = 'AddToCart_small'\nexport const CTA_LINK_ADD_TO_CART_LARGE = 'AddToCart_large'\n\nexport const EVENT_TAB_CHANGE = 'EVENT_TAB_CHANGE'\n\nexport const EVENT_VIDEO = 'WEB_COMPONENT_VIDEO'\nexport const EVENT_POPIN_OPEN = 'WEB_COMPONENT_POPIN_OPEN'\nexport const EVENT_POPIN_OPENED = 'WEB_COMPONENT_POPIN_OPENED'\nexport const EVENT_POPIN_CLOSE = 'WEB_COMPONENT_POPIN_CLOSE'\nexport const EVENT_POPIN_CLOSED = 'WEB_COMPONENT_POPIN_CLOSED'\nexport const EVENT_POPIN_CLOSE_CLICK = 'WEB_COMPONENT_POPIN_CLOSE_CLICK'\nexport const EVENT_POPIN_KEY_DOWN = 'keydown'\nexport const EVENT_POPIN_FORM_TOGGLE_TITLE = 'WEB_COMPONENT_POPIN_FORM_TOGGLE_TITLE'\nexport const EVENT_CTA_CLICK = 'WEB_COMPONENT_CTA_CLICK'\nexport const EVENT_HERO_REORDER_OPEN = 'WEB_COMPONENT_HERO_REORDER_OPEN'\nexport const EVENT_HERO_REORDER_CLOSE = 'WEB_COMPONENT_HERO_REORDER_CLOSE'\nexport const EVENT_QUICKVIEW_OPEN = 'WEB_COMPONENT_QUICKVIEW_OPEN'\nexport const EVENT_QS_OPEN = 'WEB_COMPONENT_QS_OPEN'\nexport const EVENT_QS_OPENED = 'WEB_COMPONENT_QS_OPENED'\nexport const EVENT_QS_CLOSE = 'WEB_COMPONENT_QS_CLOSE'\nexport const EVENT_QS_CLOSED = 'WEB_COMPONENT_QS_CLOSED'\nexport const EVENT_QS_CLOSE_CLICK = 'WEB_COMPONENT_QS_CLOSE_CLICK'\nexport const EVENT_QS_KEY_DOWN = 'keydown'\nexport const EVENT_ADD_TO_CART = 'WEB_COMPONENT_ADD_TO_CART'\nexport const EVENT_CART_UPDATED = 'WEB_COMPONENT_CART_UPDATED'\nexport const EVENT_VIDEO_TOGGLE = 'WEB_COMPONENT_VIDEO_TOGGLE'\nexport const VIDEO_ON_HOVER = 'VIDEO_ON_HOVER'\nexport const VIDEO_ON_OUT = 'VIDEO_ON_OUT'\nexport const EVENT_DETAIL_OPEN = 'WEB_COMPONENT_DETAIL_OPEN'\nexport const EVENT_SLIDER_READY = 'WEB_COMPONENT_SLIDER_READY'\nexport const EVENT_SLIDE_CHANGE = 'WEB_COMPONENT_SLIDE_CHANGE'\nexport const EVENT_OVERLAY_OPEN = 'WEB_COMPONENT_OVERLAY_OPEN'\nexport const EVENT_OVERLAY_CLOSE = 'WEB_COMPONENT_OVERLAY_CLOSE'\nexport const EVENT_OVERLAY_CLICKED = 'WEB_COMPONENT_OVERLAY_CLICKED'\nexport const EVENT_OPEN_PRODUCT_AR_CLICKED = 'OPEN_PRODUCT_AR_CLICKED'\nexport const EVENT_SORT_BY_CHANGE = 'WEB_COMPONENT_SORT_BY_CHANGE'\n\nexport const EVENT_BUBBLE_SELECTED = 'EVENT_BUBBLE_SELECTED'\nexport const EVENT_RECO_TOOL_OPTION_CLICKED = 'EVENT_RECO_TOOL_OPTION_CLICKED'\nexport const WEB_COMPONENT_PROJECTS_LOADED = 'WEB_COMPONENT_PROJECTS_LOADED'\nexport const WEB_COMPONENT_ANCHOR_LOADED = 'WEB_COMPONENT_ANCHOR_LOADED'\n\nexport const EVENT_SWIPED_UP = 'swiped-up'\nexport const EVENT_SWIPED_DOWN = 'swiped-down'\nexport const EVENT_SWIPED_LEFT = 'swiped-left'\nexport const EVENT_SWIPED_RIGHT = 'swiped-right'\n\nexport const EVENT_HEADER_POSITION_CHANGED = 'EVENT_HEADER_POSITION_CHANGED'\n\nexport const keys = { ESC: 'Escape' }\n\nexport const ADD_TO_CART_MODIFIER_MINI = 'mini'\nexport const ADD_TO_CART_MODIFIER_DEFAULT = ADD_TO_CART_MODIFIER_MINI\n\nexport const COFFEE_ORIGINAL = 'original'\nexport const COFFEE_VERTUO = 'vertuo'\nexport const COFFEE_PRO = 'pro'\nexport const COFFEE_OL = 'OL'\nexport const COFFEE_VL = 'VL'\nexport const INTENSITY_MAX_OL = 14\nexport const INTENSITY_MAX_VL = 12\nexport const DEFAULT_BUBBLE_ICON = ''\n\nexport const NUMBER_PRODUCTS_SLIDER = 8\nexport const NUMBER_FEATURES_PDP = 8\n\nexport const ALIGNMENT = ['center', 'left', 'right']\nexport const POSITION = ['top', 'right', 'bottom', 'left']\nexport const TRANSLATION_ADD_TO_CART = 'Add to cart'\nexport const TRANSLATION_UPDATE_BASKET = 'Update basket'\n\nexport const TIME_INSTANT = 1\nexport const TIME_FAST = 300\nexport const TIME_MEDIUM = 600\nexport const TIME_SLOW = 1200\n\nexport const APP_APPLE_LINK = {\n default: 'https://apps.apple.com/us/app/nespresso/id342879434',\n us: 'https://apps.apple.com/us/app/nespresso-new/id1609639566',\n uk: 'https://apps.apple.com/gb/app/nespresso-new/id1609639566'\n}\nexport const APP_ANDROID_LINK =\n 'https://play.google.com/store/apps/details?id=com.nespresso.activities'\nexport const APP_HUAWEI_LINK = 'https://appgallery.huawei.com/app/C102571517'\n\nexport const SRC_PAGE_PLP = 'plp'\nexport const SRC_PAGE_PDP = 'pdp'\n\nexport const PLP_TYPE_COFFEE = 'coffee'\nexport const PLP_TYPE_MACHINE = 'machine'\nexport const PLP_TYPE_ACCESSORY = 'accessory'\nexport const CALLEO_API_DOMAIN = 'https://www.contact.nespresso.com/'\n\n// SCSS RELATED\n// Todo : should be shared by JS and SCSS\nexport const BROWSER_CONTEXT = 16 // 1rem = 16px\nexport const COLOR_WHITE_1000 = '#FFFFFF' // Do not change for #FFF shortcut, it will break slider-natural gradients !\n\nexport const CONTRAST_DARK = 'dark'\nexport const CONTRAST_LIGHT = 'light'\n\nexport const B2B_CONTACT_FORM_POPIN_ID = 'b2b-contact-form-popin-id'\nexport const B2B_CONTACT_FORM_POPIN_SRC_SEARCH = 'coveo-search'\n\nexport const B2B_CONTACT_FORM_POPIN_SRC_SKU_MAIN_INFO = 'sku-main-info'\n\nexport const B2B_CONTACT_FORM_POPIN_SRC_SKU_MAIN_INFO_AUTO = 'sku-main-info-auto'\n\nexport const ASPECT_RATIO_16_9 = '16/9'\nexport const ASPECT_RATIO_1_1 = '1/1'\n\nexport const NESPRESSO_PRODUCTION_DOMAIN = 'https://www.nespresso.com'\nexport const NESPRESSO_ROLLOUT_DOMAIN = 'https://nc2-env-rollout.nespresso.com'\n\nexport const EVENT_QUIZ_ON_GO_BACK = 'WEB_COMPONENT_EVENT_QUIZ_ON_GO_BACK'\nexport const EVENT_QUIZ_SUBMIT = 'WEB_COMPONENT_EVENT_QUIZ_SUBMIT'\n","export default {\n creative: 'before_content_composer'\n}\n","import { stringifyForAttribute } from '@kissui/helpers/src/utils'\nimport trackingData from './tracking'\nexport const renderCta = (props, cssClass) => {\n const {\n cta = {},\n campaign = { id: '', name: '', creative: '', position: trackingData.creative }\n } = props\n\n if (!cta.label) {\n return ''\n }\n\n cta.campaign_id = campaign.id || ''\n cta.campaign_name = campaign.name || ''\n cta.campaign_position = campaign.position || ''\n cta.campaign_creative = campaign.creative || ''\n\n const data = stringifyForAttribute(cta)\n\n return `<div class=\"${cssClass}\"><nb-cta\n data=\"${data}\">\n ${cta.label}\n </nb-cta></div>`\n}\n\nexport const renderLink = (props, cssClass, popin_id = '') => {\n const {\n link = {},\n campaign = { id: '', name: '', creative: '', position: trackingData.creative }\n } = props\n\n if (!link.label) {\n return ''\n }\n\n return `<div class=\"${cssClass}\"><nb-link\n campaign_id=\"${campaign.id}\"\n campaign_name=\"${name}\"\n campaign_creative=\"${campaign.creative}\"\n campaign_position=\"${campaign.position}\"\n link=\"${link.link}\"\n popin_id=\"${popin_id}\"\n color=\"${link.color}\"\n size=\"${link.size}\"\n seo_label=\"${link.seo_label}\"\n >${link.label}</nb-link></div>`\n}\n","import { BREAKPOINT_M, BREAKPOINT_TABLET } from '@kissui/components'\n\nconst viewport = () => {\n const lt = (ref: number) => {\n return window.innerWidth < ref\n }\n\n return {\n get is() {\n const { innerWidth: vw, devicePixelRatio } = window\n return {\n mobile: vw < BREAKPOINT_M,\n mobile_tablet: vw < BREAKPOINT_TABLET,\n tablet: vw >= BREAKPOINT_M && vw < BREAKPOINT_TABLET,\n desktop: vw >= BREAKPOINT_TABLET && devicePixelRatio <= 1,\n retina: vw >= BREAKPOINT_TABLET && devicePixelRatio > 1\n }\n },\n lt\n }\n}\n\nconst helper = viewport()\n\nexport default helper\n","import viewportHelper from '@kissui/helpers/src/viewport.helpers'\n\nexport const getImage = ({ background_retina, background_desktop, background_mobile }) => {\n if (viewportHelper.is.mobile && background_mobile) {\n return background_mobile\n } else if (viewportHelper.is.retina && background_retina) {\n return background_retina\n }\n\n return background_desktop\n}\n","export default class {\n constructor(_props, _campaign) {\n this.props = _props\n this.campaign = _campaign\n this.elementId = null\n }\n render() {\n throw new Error('You must implement the render method')\n }\n bindEvents() {\n return []\n }\n}\n","export const getCurrency = () => window[window.config.padl.namespace].dataLayer.app.app.currency\n","import { COFFEE_VERTUO } from '@kissui/components/src/constants.mjs'\nimport { getCurrency } from './getCurrency'\nexport { getCurrency } from './getCurrency'\n\nexport const ECAPI_TYPE_CAPSULE = 'capsule'\nexport const ECAPI_TYPE_MACHINE = 'machine'\nexport const ECAPI_TYPE_ACCESSORY = 'accessory'\nexport const ECAPI_TYPE_GIFT_CARD = 'giftcard'\n\nconst TECHNOLOGY_CATEGORY_IDENTIFIER = '/machineTechno/'\nconst SLEEVE_OF_10 = 10\nconst SLEEVE_OF_7 = 7\n\nconst trimSku = sku => sku.replace(/[^a-z0-9- +./]/gi, '')\n\nexport const getLegacySKU = productId => productId.split('prod/').pop()\n\nexport const getPriceFormatter = async () => await window.napi.priceFormat()\n\nexport const getProduct = sku => window.napi.catalog().getProduct(trimSku(sku))\n\nexport function getTechnologyName(productData) {\n const techno = productData.technologies[0]\n return techno.substring(\n techno.indexOf(TECHNOLOGY_CATEGORY_IDENTIFIER) + TECHNOLOGY_CATEGORY_IDENTIFIER.length\n )\n}\n\nfunction isMultipleOf(quantity, multiple) {\n return quantity % multiple === 0\n}\n\nexport function getSleeveNumber(product, getTechnologyNameFn = getTechnologyName) {\n if (product.sales_multiple !== 1 && isMultipleOf(product.sales_multiple, SLEEVE_OF_10)) {\n // Sleeve of original or vertuo\n return product.sales_multiple / SLEEVE_OF_10\n }\n\n if (\n product.sales_multiple !== 1 &&\n getTechnologyNameFn(product) === COFFEE_VERTUO &&\n isMultipleOf(product.sales_multiple, SLEEVE_OF_7)\n ) {\n // Sleeve of vertuo\n return product.sales_multiple / SLEEVE_OF_7\n }\n\n if (product.sales_multiple === 1 && isMultipleOf(product.unitQuantity, SLEEVE_OF_10)) {\n // Bundle of original or vertuo\n return product.unitQuantity / SLEEVE_OF_10\n }\n\n if (\n product.sales_multiple === 1 &&\n getTechnologyNameFn(product) === COFFEE_VERTUO &&\n isMultipleOf(product.unitQuantity, SLEEVE_OF_7)\n ) {\n // Bundle of vertuo\n return product.unitQuantity / SLEEVE_OF_7\n }\n\n return NaN\n}\n\n/**\n * Guess if the product is part of a bundle.\n * This is determined by checking the 'sales_multiple' and 'unitQuantity' properties.\n */\nexport function isBundled(productData) {\n // TODO: this function should not change the productData, but some components still need it\n productData.sales_multiple = productData.sales_multiple || productData.salesMultiple\n\n const isSalesMultipleGreaterThanOne = productData.sales_multiple > 1\n const isUnitQuantityEqualToOne = productData.unitQuantity === 1\n const isSalesMultipleEqualToOne = productData.sales_multiple === 1\n const isUnitQuantityGreaterThanOne = productData.unitQuantity > 1\n\n // The product is not bundled if sales_multiple > 1 and unitQuantity = 1\n if (isSalesMultipleGreaterThanOne && isUnitQuantityEqualToOne) {\n return false\n }\n\n // The product is bundled if sales_multiple = 1 and unitQuantity > 1\n return isSalesMultipleEqualToOne && isUnitQuantityGreaterThanOne\n}\n\n/**\n * Replace an array of SKU with product data\n * Remove the element inside the list if sku fail. It prevents to get an empty item.\n * @param {Array.<String>} skus\n * @param getProductFn\n * @returns {Promise<Awaited<unknown>[]>}\n */\nexport function getProductAndClean(skus, getProductFn = getProduct, napi = window.napi) {\n const promises = []\n\n if (!napi) {\n return Promise.reject()\n }\n\n if (!Array.isArray(skus)) {\n skus = [skus]\n }\n\n // Load manually the product to delete SKU fail\n for (const sku of skus) {\n promises.push(\n getProductFn(sku)\n .then(data => skus.splice(skus.indexOf(sku), 1, data))\n .catch(() => {\n skus.splice(skus.indexOf(sku), 1)\n console.error(`getProduct fail on sku ${sku}`)\n })\n )\n }\n\n return Promise.all(promises)\n}\n\nexport const getFormattedPrice = async price => {\n const priceFormatter = await getPriceFormatter()\n const currency = getCurrency()\n\n return priceFormatter.html\n ? priceFormatter.html(currency, price)\n : priceFormatter.short(currency, price) || ''\n}\n\nexport const getProductCategories = async sku => {\n const productDetails = await getProduct(sku)\n const productCategories = productDetails ? productDetails.supercategories : []\n const productCategoriesNew = await Promise.all(\n productCategories.map(async categoryEncoded => {\n const productCategoryData = await window.napi.catalog().getCategory(categoryEncoded)\n return productCategoryData\n })\n )\n return productCategoriesNew\n}\n","export type EventListener = {\n element: HTMLElement\n type: string\n listener: (e: Event) => void\n options?: boolean | AddEventListenerOptions\n}\n\nconst add = (eventListeners: EventListener[] = []) => {\n eventListeners.forEach(eventListener => {\n if (!eventListener || !eventListener.element) {\n return\n }\n return eventListener.element.addEventListener(\n eventListener.type,\n eventListener.listener,\n eventListener.options\n )\n })\n}\n\nconst remove = (eventListeners: EventListener[] = []) => {\n eventListeners.forEach(eventListener => {\n if (!eventListener || !eventListener.element) {\n return\n }\n eventListener.element.removeEventListener(eventListener.type, eventListener.listener)\n })\n}\n\nconst busNamespace = 'pageBuilder'\n\nexport const emitCustomEvent = (eventName: string, data: unknown) => {\n const customEvent = new CustomEvent(`${busNamespace}.${eventName}`, {\n detail: data,\n bubbles: true,\n cancelable: true,\n composed: false\n })\n\n window.dispatchEvent(customEvent)\n}\n\nexport default { add, emitCustomEvent, remove }\n","import { getProduct } from '@kissui/helpers/src/catalog'\nimport { emitCustomEvent } from './events.helpers'\nimport { removeEmptyValues } from '@kissui/helpers/src/utils'\n\nconst raisedByPB = 'page builder'\nconst raisedByWC = 'Web component'\n\n/**\n * helper method for 'itemDisplay' GTM event\n * @param {*} event : 'itemDisplay' - Mandatory as is\n * @param {*} eventRaisedBy : 'Web component' - Mandatory as is\n * @param {*} eventAction : 'Click' - Action that led to the item display. For example, click\n * @param {*} itemTypes : ['products'] - Mandatory as is\n * @param {*} rootElement : ['nb-slider'] - Root DOM element for item detection. Closest common ancestor element of the inserted/displayed promotions and products. It will help the detection to reduce its performance consumption. Set to 0 (zero) in order to request detection through the entire document.\n */\nexport const itemDisplay = args => {\n window.gtmDataObject = window.gtmDataObject || []\n const eventData = {\n event: 'itemDisplay',\n eventRaisedBy: raisedByWC,\n eventAction: 'Click',\n itemTypes: ['products'],\n ...args\n }\n window.gtmDataObject.push(eventData)\n emitCustomEvent('itemDisplay', eventData)\n}\n\n/**\n *\n * helper method for 'customEvent' GTM event\n * @param {*} args (event, eventRaisedBy, eventCategory, eventAction, eventLabel, nonInteraction)\n */\n\nexport const customEvent = args => {\n window.gtmDataObject = window.gtmDataObject || []\n var eventData\n if (args.event_GA4 === undefined || args.event_GA4 === false) {\n eventData = {\n event: 'customEvent',\n eventRaisedBy: raisedByWC,\n eventCategory: 'User Engagement',\n eventAction: 'Click',\n eventLabel: '',\n nonInteraction: 0,\n ...args\n }\n } else {\n eventData = {\n event_raised_by: raisedByPB,\n ...args\n }\n }\n window.gtmDataObject.push(eventData)\n emitCustomEvent('customEvent', eventData)\n}\n\n/**\n * Helper method for tracking component interactions, compatible with GA4.\n *\n * @param {String} creative : component raising the event, e.g. 'before_coffees_list', 'before_machines_list', 'before_accessories_list'\n * @param {String} actionType : description of the interaction, e.g 'pdp quick view'\n * @param {String} internationalId : long SKU, e.g. 'erp.pt.b2c/prod/7243.30'\n * @param {String} internationalName : international name of the product, e.g. 'Vertuo Carafe Pour-Over Style Mild'\n * @param {String} productType : type of product, i.e. 'capsule', 'machine', 'accessory'\n * @param {String} range : product range, e.g. 'ispirazione italiana'\n * @param {String} technology : technology, i.e. 'original', 'vertuo'\n * @param {Number} price : price, e.g. .51\n * @param {String} eventAction : description of the action, e.g. 'PDP Quick View'\n *\n * Initally created for PDP Quick View tracking:\n * https://dsu-confluence.nestle.biz/display/DIANA/BEFORE+-+PDP+Quick+View\n * Will probably be rolled out across all components, update this comment accordingly.\n */\nexport const trackComponentInteraction = ({\n creative = '',\n actionType = '',\n internationalId = '',\n internationalName = '',\n productType = '',\n technology = '',\n category = '',\n rawPrice = '',\n eventAction = ''\n}) => {\n window.gtmDataObject = window.gtmDataObject || []\n const eventData = {\n event: 'page_builder_component_interaction',\n event_raised_by: raisedByPB,\n component_name: creative,\n action_type: actionType,\n item_id_event: internationalId,\n item_name_event: internationalName,\n item_category_event: productType,\n item_technology_event: technology,\n item_range_event: category,\n item_price_event: rawPrice,\n eventCategory: 'User Engagement',\n eventAction: eventAction,\n eventLabel: `${productType} - ${technology} - ${internationalName}`\n }\n window.gtmDataObject.push(eventData)\n emitCustomEvent('page_builder_component_interaction', eventData)\n}\n\n/**\n *\n * Push 'view_promotion' event for GA 4\n * @param {*} args (event, event_raised_by, ecommerce: {promotion_id, promotion_name, creative_slot, creative_name})\n */\nexport const viewPromotion = args => {\n const event = 'view_promotion'\n const eventData = {\n event,\n event_raised_by: raisedByPB,\n ecommerce: {}\n }\n if (Object.keys(args).length) {\n const { id = '', creative = '', name = '', position = '' } = args\n let ecommerceData = {\n promotion_id: id,\n promotion_name: name,\n creative_slot: position,\n creative_name: creative\n }\n ecommerceData = removeEmptyValues(ecommerceData)\n eventData.ecommerce = ecommerceData\n }\n window.gtmDataObject ??= []\n window.gtmDataObject.push(eventData)\n emitCustomEvent(event, eventData)\n}\n\nexport const handlePromoClick = args => {\n const { campaign, cta_name } = args\n\n const cleanedData = removeEmptyValues(campaign)\n selectPromotion({ cta_name, ...cleanedData })\n}\n\n/**\n *\n * Push 'select_promotion' event for GA 4\n * @param {*} args (event, event_raised_by, cta_name, ecommerce: {promotion_id, promotion_name, creative_slot, creative_name})\n */\nexport const selectPromotion = args => {\n const event = 'select_promotion'\n const eventData = {\n event: 'select_promotion',\n cta_name: args?.cta_name ?? '(not set)',\n event_raised_by: raisedByPB,\n ecommerce: {}\n }\n if (Object.keys(args).length) {\n const { id = '', creative = '', name = '', position = '' } = args\n let ecommerceData = {\n promotion_id: id,\n promotion_name: name,\n creative_slot: position,\n creative_name: creative\n }\n ecommerceData = removeEmptyValues(ecommerceData)\n eventData.ecommerce = ecommerceData\n }\n\n window.gtmDataObject ??= []\n window.gtmDataObject.push(eventData)\n emitCustomEvent(event, eventData)\n}\n\nexport const interactionClick = (nameComponent, ctaName) => {\n window.gtmDataObject = window.gtmDataObject || []\n const eventData = {\n event: 'page_builder_component_interaction',\n event_raised_by: raisedByPB,\n eventCategory: 'User Engagement',\n eventAction: 'Click CTA',\n eventLabel: `Page Builder - ${nameComponent} - ${ctaName}`,\n component_name: nameComponent,\n action_type: 'web component click',\n cta_name: ctaName\n }\n window.gtmDataObject.push(eventData)\n emitCustomEvent('page_builder_component_interaction', eventData)\n}\n\nexport const getProductInfo = async (sku, data) => {\n let product = data\n if (!product) {\n product = await getProduct(sku)\n }\n return product\n}\n\nexport const getProductPayload = (data, actionField = {}) => {\n const {\n internationalName,\n internationalId,\n category,\n unitPrice,\n legacyId,\n name,\n technologies,\n bundled,\n inStock,\n type\n } = data\n\n const technology = technologies.map(item => item.split('/').pop()).join('|')\n const isDiscovery = category.toLowerCase().includes('discovery')\n\n return [\n // Array consists of one product details for PDP Product Detail View\n {\n ...actionField,\n name: internationalName, // '[[International Product Name]]' NIE, Contract\n id: internationalId, // '[[International Product ID]]'\n price: unitPrice, // '[[Product Price]'\n // dimension43: '[[true/false]]', // '[[true/false]]' // Signifies if this product is part of a standing order or not\n dimension44: isDiscovery.toString(), // '[[true/false]]', // Signifies if this product is part of a discovery offer\n dimension53: legacyId, // '[[Product Local market ID]]', // Local market id for product\n dimension54: name, // '[[Product Local market Name]]', // Local market name for product\n dimension55: category, // '[[Product Range]]', // Range of the product, eg: Barista Creations for Ice (Nessoft Category)\n dimension56: technology, // '[[Product Technology]]', //Product technology according to Nespresso categorization (original, vertuo, pro)\n dimension57: bundled ? 'bundle' : 'single', // '[[Product Type]]', //If the product is single or bundle\n dimension192: inStock ? 'in stock' : 'out of stock', // '[in stock]', // \"in stock\" or \"out of stock\"\n category: type, // '[[Product Category]]', //Product category according to Nespresso categorization (Nessoft type): capsule, accessory, machine\n brand: 'Nespresso' // Static value set to Nespresso\n }\n ]\n}\n\nexport const trackDetailView = async (sku, data) => {\n // https://dsu-confluence.nestle.biz/display/DIANA/HQ+PB+Tracking+-+Product+Detail+View\n if (window.pbTrackDetailViewPDP || !sku || !window.napi) {\n return\n }\n\n const productInfo = await getProductInfo(sku, data)\n const productPayload = getProductPayload(productInfo)\n const currency = productInfo.currency\n\n window.gtmDataObject = window.gtmDataObject || []\n const eventData = {\n event: 'detailView',\n currencyCode: currency,\n eventRaisedBy: raisedByPB,\n ecommerce: {\n detail: {\n actionField: {},\n products: productPayload\n }\n }\n }\n window.gtmDataObject.push(eventData)\n // Track only once per page\n window.pbTrackDetailViewPDP = true\n emitCustomEvent('detailView', eventData)\n}\n\nexport const trackAddToCartImpression = (product, isStickyBar) => {\n // https://dsu-confluence.nestle.biz/pages/viewpage.action?spaceKey=DIANA&title=PDP+-+Sticky+Add+To+Cart+Custom+Event\n\n window.gtmDataObject = window.gtmDataObject || []\n const eventData = {\n event: 'page_builder_component_interaction',\n event_raised_by: raisedByPB,\n component_name: 'before_sku_main_info',\n action_type: isStickyBar\n ? 'sticky add to cart impression'\n : 'standard add to cart impression',\n //product info\n item_id_event: product.internationalId,\n item_name_event: product.internationalName,\n item_category_event: product.type,\n item_price_event: product.price_per_capsule?.split(' ')[0],\n item_market_id_event: product.legacyId,\n item_market_name_event: product.name,\n item_range_event: product.category_name,\n item_technology_event: product.technology?.[0]?.split('/').slice(-1) ?? '',\n item_type_event: product.bundled ? 'bundle' : 'single'\n }\n window.gtmDataObject.push(eventData)\n emitCustomEvent('page_builder_component_interaction', eventData)\n}\n\nexport const productImpression = async (position, list, sku, data) => {\n // https://dsu-confluence.nestle.biz/pages/viewpage.action?pageId=225612781\n // don't track already tracked products\n window.gtmDataObject = window.gtmDataObject || []\n const hasDetailView = window.gtmDataObject.find(item => item.event === 'detailView')\n const alreadyTracked = !!hasDetailView?.ecommerce?.detail?.products.find(p =>\n sku.includes(p.id)\n )\n if (alreadyTracked) {\n return\n }\n\n const productInfo = await getProductInfo(sku, data)\n const productPayload = getProductPayload(productInfo, { list: list, position: position })\n const currency = productInfo.currency\n const eventData = {\n event: 'impression',\n eventAction: 'Product Impression',\n currencyCode: currency,\n eventRaisedBy: raisedByPB,\n ecommerce: {\n impressions: productPayload\n }\n }\n window.gtmDataObject.push(eventData)\n emitCustomEvent('impression', eventData)\n}\n\nexport const productClick = async (position, list, sku, data) => {\n // https://dsu-confluence.nestle.biz/pages/viewpage.action?pageId=225612781\n\n if (typeof list !== 'string') return\n\n const productInfo = await getProductInfo(sku, data)\n const productPayload = getProductPayload(productInfo, { position: position })\n const currency = productInfo.currency\n\n window.gtmDataObject = window.gtmDataObject || []\n const eventData = {\n event: 'productClick',\n eventAction: 'Product Click',\n currencyCode: currency,\n eventRaisedBy: raisedByPB,\n ecommerce: {\n click: {\n actionField: {\n list: list\n },\n products: productPayload\n }\n }\n }\n window.gtmDataObject.push(eventData)\n emitCustomEvent('productClick', eventData)\n}\n\nexport function filterTrackingFromPlpFilters(filtersSelected) {\n const grouped = groupSelectedFilters(filtersSelected)\n const groupKeys = Object.keys(grouped)\n const typesFiltersSelected = groupKeys.join('|').substring(0, 99)\n const valuesFiltersSelected = groupKeys\n .map(key => grouped[key].values.map(value => value.split('/').at(-1)).join(','))\n .join('|')\n .substring(0, 99)\n\n return [typesFiltersSelected, valuesFiltersSelected]\n}\n\nexport const filterActionEvent = (\n actionType,\n filterType,\n filterValues,\n clickLocation,\n dataType\n) => {\n // https://dsu-confluence.nestle.biz/display/DIANA/PLP+-+Filter+Revamp\n window.gtmDataObject = window.gtmDataObject || []\n const eventData = getExplicitFilterEventData(\n actionType,\n filterType,\n filterValues,\n clickLocation\n )\n\n window.gtmDataObject.push(eventData)\n if (window.NEXT_V1_PLP_EXPLICIT_FILTER_TRACKING && dataType) {\n window.gtmDataObject.push({\n ...window.NEXT_V1_PLP_EXPLICIT_FILTER_TRACKING,\n experiment_action: `${actionType} - ${dataType}`,\n cta_name: 'All filters'\n })\n }\n\n emitCustomEvent('plp_filter', eventData)\n}\n\nconst getExplicitFilterEventData = (actionType, filterType, filterValues, clickLocation) => {\n return {\n event: 'plp_filter',\n event_raised_by: raisedByPB,\n action_type: actionType,\n filter_type: filterType,\n ...(filterValues ? { filter_values: filterValues } : {}),\n ...(clickLocation ? { click_location: clickLocation } : {})\n }\n}\n\nfunction groupSelectedFilters(filtersSelected = []) {\n return filtersSelected.reduce((grouped, { key, value }) => {\n if (!grouped[key]) grouped[key] = { key, values: [] }\n grouped[key].values.push(value.replaceAll(',', '-'))\n return grouped\n }, {})\n}\n\nfunction arrTolastURLElementMapper(arr) {\n if (typeof arr === 'undefined' || arr.length === 0) return undefined\n\n return arr.map(item => item.split('/').pop()?.trim() || '')\n}\n\nfunction arrToJoinedString(arr, joiner = '|') {\n if (typeof arr === 'undefined' || arr.length === 0) return undefined\n\n return arr.map(item => item.trim()).join(joiner)\n}\n\nfunction findTechnogiesText(arr) {\n if (typeof arr === 'undefined' || arr.length === 0) return undefined\n\n if (arr.length === 1) return cleanText(arrTolastURLElementMapper(arr)?.[0])\n else return 'multiple'\n}\n\nfunction cleanText(str) {\n if (typeof str === 'undefined') return undefined\n\n return str.toString().trim()\n}\n\nconst generateEcommerceObject = async (productIds, options) => {\n const productRequests = productIds.map(SKU => getProduct(SKU))\n const productData = await Promise.all(productRequests)\n\n return {\n ecommerce: {\n currency: window[window.config.padl.namespace].dataLayer.app.app.currency,\n value: productData.reduce((ac, product) => {\n return ac + product.price\n }, 0),\n items: productData.map((product, index) => {\n if (product.type === 'bundle' || product.type === 'giftcard') {\n return {\n item_id: cleanText(product.internationalId),\n item_name: cleanText(product.internationalName),\n item_brand: 'nespresso',\n item_category: cleanText(product.type),\n index: index + 1\n }\n }\n\n let output = {\n item_id: cleanText(product.internationalId),\n item_name: cleanText(product.internationalName),\n item_brand: 'nespresso',\n item_category: cleanText(product.type),\n item_category2: arrToJoinedString(\n arrTolastURLElementMapper(product.technologies)\n ),\n item_category3: cleanText(product.category),\n price: product.price,\n quantity: product.salesMultiple,\n affiliation: 'nespresso online store',\n coupon: undefined,\n discount: undefined,\n location_id: undefined,\n item_list_name: cleanText(options?.listName),\n item_list_id: cleanText(options?.listId),\n index: index + 1,\n item_market_id: cleanText(product.legacyId),\n item_market_name: cleanText(product.name),\n item_technology: findTechnogiesText(product.technologies),\n item_range: cleanText(product.category),\n item_discovery_offer: product.category.includes('discovery').toString(),\n item_added_by_user: undefined,\n item_ecotax_applicable: product?.displayEcoTax\n ? cleanText(product?.displayEcoTax.toString())\n : undefined,\n item_selection_list: cleanText(arrToJoinedString(product.productSelections)),\n item_in_stock: product?.inStock\n ? cleanText(product?.inStock.toString())\n : undefined,\n item_subscription_name: undefined,\n item_subscription_category: undefined,\n item_subscription_price: undefined,\n item_subscription_duration: undefined,\n item_subscription_fee: undefined\n }\n\n switch (product.type) {\n case 'capsule': {\n const capsuleProduct = product\n\n output.item_category4 = capsuleProduct.bundled ? 'bundle' : 'single'\n\n output.item_type = capsuleProduct.bundled ? 'bundle' : 'single'\n\n output.item_coffee_aromatic_profile = cleanText(\n arrToJoinedString(capsuleProduct.capsuleProductAromatics)?.toLowerCase()\n )\n\n output.item_coffee_intensity =\n cleanText(capsuleProduct.capsuleProperties.intensity) ?? undefined\n\n output.item_coffee_cup_size = cleanText(\n arrToJoinedString(capsuleProduct.capsuleCupSizes)\n )?.toLowerCase()\n\n break\n }\n case 'machine': {\n const machineProduct = product\n\n output.item_machine_shade = cleanText(machineProduct.colorShade?.name)\n\n break\n }\n }\n\n if (product.type === 'machine' || product.type === 'accessory') {\n output.item_avg_rating = product.ratingCode\n output.item_number_of_reviews = product.ratingCode\n }\n\n return output\n })\n }\n }\n}\n\nexport const selectItems = async (productIds, options) => {\n const ecommerceObject = await generateEcommerceObject(productIds, options)\n\n const output = {\n event: 'select_item',\n event_raised_by: options?.eventRaisedBy ?? 'before_cross_sell_v3',\n click_location: options?.clickLocation ?? 'page builder cross sell quick view',\n item_list_id: options?.listId ?? 'before_cross_sell_v3',\n subscription_product_included: 'false',\n discovery_offer_included: 'false',\n ...ecommerceObject\n }\n\n window.gtmDataObject.push({ ecommerce: null })\n window.gtmDataObject.push(output)\n}\n\nexport const viewItemList = async (productIds, options) => {\n const ecommerceObject = await generateEcommerceObject(productIds, options)\n\n const output = {\n event: 'view_item_list',\n event_raised_by: options?.eventRaisedBy,\n subscription_product_included: 'false',\n discovery_offer_included: 'false',\n ...ecommerceObject\n }\n\n if (options?.eventRaisedBy === undefined) delete output.event_raised_by\n\n window.gtmDataObject.push({ ecommerce: null })\n window.gtmDataObject.push(output)\n}\n\nexport const isGtmTrackingExists = trackingData => {\n window.gtmDataObject = window.gtmDataObject || []\n\n return window.gtmDataObject.some(\n event =>\n event.event === trackingData.event &&\n event.ecommerce?.creative_slot === trackingData.campaign.position &&\n event.ecommerce?.promotion_id === trackingData.campaign.id &&\n event.ecommerce?.promotion_name === trackingData.campaign.name &&\n event.ecommerce?.creative_name === trackingData.campaign.creative\n )\n}\n","export const getDataLayer = () => {\n return window[window?.padlNamespace]?.dataLayer\n}\n\nexport const getMarketCode = () => {\n const dataLayer = getDataLayer()\n if (!dataLayer) {\n return 'ch'\n }\n\n return dataLayer.app.app.market.toLocaleLowerCase()\n}\n\nexport const getLangCode = () => {\n const dataLayer = getDataLayer()\n if (!dataLayer) {\n return 'en'\n }\n\n return getDataLayer().page.page.pageInfo.language.toLocaleLowerCase()\n}\n\nexport const getSegmentCode = () => {\n const dataLayer = getDataLayer()\n if (!dataLayer) {\n return 'B2C'\n }\n\n return getDataLayer().page.page.pageInfo.segmentBusiness\n}\n\nexport const isLoggedIn = () => {\n const dataLayer = getDataLayer()\n if (!dataLayer || !dataLayer.user) {\n return false\n }\n\n return dataLayer.user.isLoggedIn\n}\n\nexport const interpolateMarketLang = (string, market, lang) => {\n return string.replace('{market}', market).replace('{lang}', lang)\n}\n","import { getMarketCode } from './dataLayer'\n\nconst LABEL_CATEGORY_NAME = 'cat/capsule-range-label'\nconst LABEL_CATEGORY_NAME_MACHINE = 'cat/machine-range-label'\nexport const RANGE_CATEGORY_NAME = 'cat/capsule-range'\nconst FAIR_TRADE_CATEGORY_NAME = 'cat/capsule-range-fair-trade'\nconst VERTUO_NEXT_CATEGORY_NAME = 'cat/capsule-attribute-only-vertuo-next'\nconst ORGANIC_EU_CATEGORY_NAME = 'capsule-attribute-organic-eu'\nconst RAINFOREST_CATEGORY_NAME = 'capsule-attribute-rainforest'\nconst SUSTAINABILITY_CATEGORY_NAME = 'capsule-attribute-sustainability'\nconst ARABICA_CATEGORY_NAME = 'capsule-attribute-arabica'\nconst PRODUCT_HIGHLIGHT_CATEGORY_NAME = 'cat/capsule-attribute-highlight'\nconst TECHNOLOGY_CATEGORY_IDENTIFIER = '/machineTechno/'\n\nconst COMMON_URL = 'https://www.nespresso.com/shared_res/agility/commons/img/icons/'\n\nexport const FAIR_TRADE_IMG = COMMON_URL + 'fairTrade.svg'\nexport const ORGANIC_LOGO_IMG_EU = COMMON_URL + 'logo-organic-eu.svg'\nexport const ORGANIC_LOGO_IMG_US = COMMON_URL + 'logo-organic-us.svg'\nexport const ORGANIC_LOGO_IMG_CA = COMMON_URL + 'logo-organic-ca.svg'\nexport const ORGANIC_LOGO_IMG_BR = COMMON_URL + 'logo-organic-br.svg'\nexport const ORGANIC_LOGO_IMG_JP = COMMON_URL + 'logo-organic-jp.svg'\nexport const ORGANIC_LOGO_IMG_BE = COMMON_URL + 'logo-organic-be.png'\n\nexport const VERTUONEXT_LOGO_IMG = COMMON_URL + 'logo-only-vertuo-next.svg'\nexport const RAINFOREST_LOGO_IMG = COMMON_URL + 'logo-rainforest.svg'\nexport const SUSTAINABILITY_LOGO_IMG = COMMON_URL + 'logo-sustainability.svg'\nexport const Q_CERTIFICATION_ARABICA_LOGO_IMG = COMMON_URL + 'q_grade_certification_arabica.svg'\nexport const DESIGN_AWARD_2021_IMG = COMMON_URL + 'design_award_2021.svg'\n\nexport const LOGO_IMG_MAP = {\n fair_trade: FAIR_TRADE_IMG,\n is_organic: getOrganicLogo(),\n only_vertuo_next: VERTUONEXT_LOGO_IMG,\n is_q_certified_arabica: Q_CERTIFICATION_ARABICA_LOGO_IMG,\n is_rainforest: RAINFOREST_LOGO_IMG,\n is_sustainable: SUSTAINABILITY_LOGO_IMG,\n is_design_award_2021: DESIGN_AWARD_2021_IMG\n}\n\nexport function getOrganicLogo() {\n let organicLogoImg = ORGANIC_LOGO_IMG_EU\n\n switch (getMarketCode()) {\n case 'us':\n organicLogoImg = ORGANIC_LOGO_IMG_US\n break\n case 'ca':\n organicLogoImg = ORGANIC_LOGO_IMG_CA\n break\n case 'br':\n organicLogoImg = ORGANIC_LOGO_IMG_BR\n break\n case 'jp':\n organicLogoImg = ORGANIC_LOGO_IMG_JP\n break\n case 'be':\n organicLogoImg = ORGANIC_LOGO_IMG_BE\n break\n }\n\n return organicLogoImg\n}\n\n/**\n * retrieves the list of categories of type Vertuo Next\n * @param {category[]} categories\n */\nexport function getVertuoNext(categories) {\n return categories.find(category => isVertuoNext(category))\n}\n\n/**\n * returns true when the category is product vertuo next\n * @param {category} category\n */\nfunction isVertuoNext(category) {\n return getCategoryRegEx(VERTUO_NEXT_CATEGORY_NAME).test(category.id)\n}\n\n/**\n * retrieves the list of categories of type organic EU\n * @param {category[]} categories\n */\nexport function getOrganicEu(categories) {\n return categories.find(category => isOrganicEu(category))\n}\n\n/**\n * returns true when the category is product organic EU\n * @param {category} category\n */\nfunction isOrganicEu(category) {\n return getCategoryRegEx(ORGANIC_EU_CATEGORY_NAME).test(category.id)\n}\n\n/**\n * retrieves the list of categories of type rainforest\n * @param {category[]} categories\n */\nexport function getRainforest(categories) {\n return categories.find(category => isRainforest(category))\n}\n\n/**\n * returns true when the category is rainforest\n * @param {category} category\n */\nfunction isRainforest(category) {\n return getCategoryRegEx(RAINFOREST_CATEGORY_NAME).test(category.id)\n}\n\n/**\n * retrieves the list of categories of type sustainability\n * @param {category[]} categories\n */\nexport function getSustainability(categories) {\n return categories.find(category => isSustainability(category))\n}\n\n/**\n * retrieves the list of categories of type arabica\n * @param {category[]} categories\n */\nexport function getArabica(categories) {\n return categories.find(category => isArabica(category))\n}\n\n/**\n * returns true when the category is arabica\n * @param {category} category\n */\nfunction isArabica(category) {\n return getCategoryRegEx(ARABICA_CATEGORY_NAME).test(category.id)\n}\n\n/**\n * returns true when the category is sustainability\n * @param {category} category\n */\nfunction isSustainability(category) {\n return getCategoryRegEx(SUSTAINABILITY_CATEGORY_NAME).test(category.id)\n}\n\n/**\n * retrieves the list of categories of type label\n * @param {category[]} categories\n */\nexport function getLabels(categories) {\n return categories.filter(category => isLabel(category))\n}\n\n/**\n * retrieves the list of categories of type label\n * @param {category[]} categories\n */\nexport function getProductHighlight(categories) {\n return categories.find(category => isProductHighlight(category))\n}\n/**\n * retrieves the list of categories of type label\n * @param {category[]} categories\n */\nexport function getFairTrade(categories) {\n return categories.find(category => isFairTrade(category))\n}\n\n/**\n * returns a regex to match the tail (global) of a given local category ID\n * @param {string} categoryIdTail : should contain the end of the category ID\n */\nexport function getCategoryRegEx(categoryIdTail) {\n return new RegExp(categoryIdTail.replace(/\\//g, '\\\\/'))\n}\n\n/**\n * returns true when the category is child of the label category (is type label)\n * @param {category} category\n */\nfunction isLabel(category) {\n return (\n getCategoryRegEx(LABEL_CATEGORY_NAME).test(category.id) ||\n getCategoryRegEx(LABEL_CATEGORY_NAME_MACHINE).test(category.id)\n )\n}\n\n/**\n * returns true when the category is product highlight\n * @param {category} category\n */\nfunction isProductHighlight(category) {\n return getCategoryRegEx(PRODUCT_HIGHLIGHT_CATEGORY_NAME).test(category.id)\n}\n/**\n * returns true when the category is fair trade\n * @param {category} category\n */\nfunction isFairTrade(category) {\n return getCategoryRegEx(FAIR_TRADE_CATEGORY_NAME).test(category.id)\n}\n\n/**\n * returns true when the category is child of the range category (is type range)\n * @param {category} category\n */\nexport function isRange(category) {\n return category.superCategories.some(superCategory =>\n getCategoryRegEx(RANGE_CATEGORY_NAME).test(superCategory)\n )\n}\n\nexport function getTechnologyName(productData, categories) {\n if (!productData || !productData.technologies || !productData.technologies.length) {\n return null\n }\n\n const techno = productData.technologies[0]\n const categoryNameAsSubstring = techno.substring(\n techno.indexOf(TECHNOLOGY_CATEGORY_IDENTIFIER) + TECHNOLOGY_CATEGORY_IDENTIFIER.length\n )\n const category = categories?.find(cat => cat.id === techno)\n\n // Backward compatibility, return name as substring if the list of categories are not available\n return category?.name || categoryNameAsSubstring\n}\n\nexport function isCategoryHidden(categoryId) {\n let hideCategory = false\n // To enable AB testing: exclude categories which are to be hidden\n if (\n window.PLP_HIDE_CATEGORIES?.length &&\n window.PLP_HIDE_CATEGORIES.findIndex(c => categoryId.indexOf(c) >= 0) >= 0\n ) {\n hideCategory = true\n }\n\n // To enable AB testing: exclude categories except those which are to be shown\n if (window.PLP_ONLY_SHOW_CATEGORIES?.length) {\n // Default to hide\n hideCategory = true\n if (window.PLP_ONLY_SHOW_CATEGORIES.findIndex(c => categoryId.indexOf(c) >= 0) >= 0) {\n hideCategory = false\n }\n }\n return hideCategory\n}\n","import { INTENSITY_MAX_OL, INTENSITY_MAX_VL } from '@kissui/components'\n\nexport const getMaxIntensity = ({ technologies }) =>\n technologies.indexOf('original') !== -1 ? INTENSITY_MAX_OL : INTENSITY_MAX_VL\n","import { getFinalPrice } from '@kissui/plp/services'\nimport { isBundled } from '@kissui/helpers/src/catalog'\nimport { getMaxIntensity } from '@kissui/components/src/sku-coffee/services'\n\nexport const getMergedProductCoffeeData = (\n product,\n pageBuilderProductProps,\n pageBuilderProps,\n priceFormatter,\n currency\n) => {\n const { bundle_details } = pageBuilderProductProps\n const { options } = pageBuilderProps\n const { show_sleeve_price } = options\n\n const isBundledResult = isBundled(product)\n\n const { showCapsulePrice, price_per_capsule, final_price } = getFinalPrice(\n show_sleeve_price,\n product,\n isBundled\n )\n\n const option = {\n bundled: isBundledResult,\n intensity: product.capsuleProperties?.intensity || product.intensity || null,\n max_intensity: getMaxIntensity(product),\n price_per_capsule: price_per_capsule\n ? priceFormatter.short(currency, price_per_capsule)\n : null,\n show_capsule_price: showCapsulePrice\n }\n\n if (show_sleeve_price) {\n option.price = priceFormatter.short(currency, final_price)\n }\n\n if (bundle_details) {\n option.bundle_details = bundle_details\n }\n\n return option\n}\n","import {\n getVertuoNext,\n getOrganicEu,\n getRainforest,\n getLabels,\n getProductHighlight,\n getFairTrade,\n getSustainability,\n isRange,\n getCategoryRegEx,\n RANGE_CATEGORY_NAME,\n getArabica\n} from '@kissui/helpers/src/cremaDataHelper'\n\n/**\n * Modifies the structure to make it easier to use in components\n * Applies all the data customization mixing Page builder with HMC data\n * @param {object} plpData : original PLP data\n */\nexport async function getMergedPLPData(plpData) {\n const { data } = plpData\n if (!data) {\n return []\n }\n\n const eCommerceData = data.configuration.eCommerceData\n\n addLabels(eCommerceData)\n\n addProductAttribute(\n eCommerceData,\n getFairTrade,\n (prod, category) => (prod.fairTrade = category.name)\n )\n addProductAttribute(eCommerceData, getProductHighlight, prod => (prod.highlighted = true))\n addProductAttribute(eCommerceData, getVertuoNext, prod => (prod.onlyVertuoNext = true))\n addProductAttribute(eCommerceData, getOrganicEu, prod => (prod.organicEu = true))\n addProductAttribute(eCommerceData, getRainforest, prod => (prod.rainforest = true))\n addProductAttribute(eCommerceData, getSustainability, prod => (prod.sustainability = true))\n addProductAttribute(eCommerceData, getArabica, prod => (prod.arabica = true))\n\n addSubSegments(eCommerceData)\n\n return eCommerceData.categories\n}\n\nfunction addSubSegments(eCommerceData) {\n const { categories, productGroups, products } = eCommerceData\n // should be forEach if nothing returned/assigned\n categories.forEach(category => {\n const hasSegment = category.subCategories.length > 0 && isRange(category)\n if (hasSegment) {\n category.segments = category.subCategories.map(categoryId => {\n const segment = categories.find(subCategory => subCategory.id === categoryId)\n if (segment && isSubsegment(categories, segment)) {\n segment.products = getProductsData(productGroups, segment.id, products)\n segment.isSegment = true\n }\n return segment\n })\n }\n\n category.products = getProductsData(productGroups, category.id, products)\n })\n}\n\nexport function getProductsData(productGroups, categoryId, products) {\n let result = []\n try {\n const currentCategory = productGroups.find(category => category.categoryId === categoryId)\n\n if (!currentCategory) {\n return result\n }\n\n const { productIds } = currentCategory\n return productIds.map(productId => {\n const product = products.find(product => product.id === productId)\n return product\n })\n } catch (e) {\n //generally an anti pattern to only log the error, with no try catch the result would be the same\n console.log(e)\n }\n\n return result\n}\n\n/**\n * adds labels property to products containing each label's category data (JSON parsed description property) assigned to it\n * labels are categories that have the label base category as parent\n * to apply a label on a given product, the label has to contain the product\n * this function has to clean the productGroups as well by removing the label ones\n * @param {category[]} categories\n * @param {productGroup[]} productGroups\n * @param {product[]} products\n */\nfunction addLabels(eCommerceData) {\n const { categories, productGroups, products } = eCommerceData\n const labels = getLabels(categories)\n const labelGroups = getLabelGroups(productGroups, labels)\n labelGroups.forEach(group => {\n const label = labels.find(label => label.id === group.categoryId)\n group.productIds.forEach(productId => {\n const prod = products.find(product => product.id === productId)\n prod.labels = prod.labels || []\n prod.labels.push(label.description)\n })\n })\n //removing label categories from productGroups\n labelGroups.forEach(labelGroup => {\n const indexToRemove = productGroups.findIndex(\n productGroup => productGroup.categoryId === labelGroup.categoryId\n )\n productGroups.splice(indexToRemove, 1)\n })\n}\n\n/**\n * adds a property to products containing the given category assigned to it\n * The category is recognized by ID\n * to apply a the category on a given product, the category's productGroup has to contain the product\n * this function has to clean the productGroups as well by removing the given's one to not let it display as a range in the PLP\n * @param {category[]} categories\n * @param {productGroup[]} productGroups\n * @param {product[]} products\n */\nfunction addProductAttribute(eCommerceData, categoryFetcher, assignHandler) {\n const { categories, productGroups, products } = eCommerceData\n const category = categoryFetcher(categories)\n if (!category) {\n return\n }\n const categoryGroup = getCategoryGroup(productGroups, category)\n if (!categoryGroup) {\n return\n }\n categoryGroup.productIds.forEach(productId => {\n const prod = products.find(product => product.id === productId)\n if (categoryFetcher === getArabica) {\n console.log('addProductAttribute', prod)\n }\n assignHandler(prod, category)\n })\n const indexToRemove = productGroups.findIndex(\n productGroup => productGroup.categoryId === categoryGroup.categoryId\n )\n productGroups.splice(indexToRemove, 1)\n}\n\n/**\n * retrieve all the productGroup that are labels\n * @param {productGroup[]} productGroups\n * @param {category[]} labels\n */\nfunction getLabelGroups(productGroups, labels) {\n return productGroups.filter(group => labels.some(label => label.id === group.categoryId))\n}\n\n/**\n * retrieve the productGroup which correspond to a category\n * @param {productGroup[]} productGroups\n * @param {category} fairTrade\n */\nfunction getCategoryGroup(productGroups, category) {\n return productGroups.find(group => category.id === group.categoryId)\n}\n\n/**\n * returns true when the category is child of the range category (is type range)\n * @param {category} category\n */\nexport function isSubsegment(categories, category) {\n /*category.superCategories.some(superCategoryId => {\n const superCategoryData = categories.find(categoryToFind => categoryToFind.id === superCategoryId)\n })*/\n const result = category.superCategories.some(superCategory =>\n getCategoryRegEx(RANGE_CATEGORY_NAME).test(superCategory)\n )\n return result\n}\nexport function getFinalPrice(show_sleeve_price, product, isBundled) {\n let showCapsulePrice = show_sleeve_price\n let final_price\n let price_per_capsule\n\n const bundled = isBundled(product)\n\n if (product.type === 'capsule' && !bundled) {\n final_price = product.price * product.salesMultiple\n // this isn't necessary in prod but the mock price formatter needs it\n final_price = Math.round(final_price * 100) / 100\n price_per_capsule = product.price\n } else {\n showCapsulePrice = false\n final_price = product.price\n }\n\n return { showCapsulePrice, final_price, price_per_capsule }\n}\n","import {\n ECAPI_TYPE_ACCESSORY,\n ECAPI_TYPE_CAPSULE,\n ECAPI_TYPE_GIFT_CARD,\n ECAPI_TYPE_MACHINE\n} from '@kissui/helpers/src/catalog'\n\nexport const getSkuComponentByType = ({ type, is_machine_b2b }) => {\n let result = 'nb-sku'\n\n if (type === ECAPI_TYPE_CAPSULE) {\n result = 'nb-sku-coffee'\n } else if (type === ECAPI_TYPE_MACHINE && is_machine_b2b) {\n result = 'nb-sku-machine-b2b'\n } else if (type === ECAPI_TYPE_MACHINE) {\n result = 'nb-sku-machine'\n } else if (type === ECAPI_TYPE_ACCESSORY) {\n result = 'nb-sku-accessory'\n } else if (type === ECAPI_TYPE_GIFT_CARD) {\n result = 'nb-sku-gift-card'\n }\n\n return result\n}\n\nexport const apiOverride = (productData, pageBuilderData) => {\n if (!productData || !pageBuilderData) {\n return {}\n }\n\n const { images, name, headline, description } = productData\n const { api_override } = pageBuilderData\n\n if (!api_override) {\n return {}\n }\n\n return {\n image: api_override.image || images?.icon || images?.url || images?.push || images?.main,\n name: api_override.name || name,\n headline: api_override.headline || headline,\n description: api_override.description || description\n }\n}\n","import VideoCard from './video-card/video-card.composer'\nimport ImageCard from './image-card/image-card.composer'\nimport ProductCard from './product-card/product-card.composer'\nimport ProductSku from './product-sku/product-sku.composer'\nimport TextCard from './text-card/text-card.composer'\n\nexport default {\n video: VideoCard,\n image: ImageCard,\n product: ProductCard,\n productSku: ProductSku,\n text: TextCard\n}\n","/**\n *\n * Card Video Props\n *\n * - cardSize\n * - contrast\n * - animated\n * - title\n * - description\n * - cta {}\n * - link {}\n * - background_retina\n * - background_desktop\n * - background_mobile\n * - video {}\n *\n */\nimport { stripHTML, makeHash, stringifyForAttribute } from '@kissui/helpers/src/utils'\nimport { dispatchEvent } from '@kissui/helpers/src/assets/js/eventDispatch'\nimport { EVENT_POPIN_OPEN } from '@kissui/components'\nimport './video-card.composer.scss'\nimport { renderCta, renderLink } from '../../helpers/renderButtons'\nimport { getImage } from '../../helpers/getImage'\nimport Card from '../card.class'\nimport { handlePromoClick } from '@kissui/helpers/src/gtmEvents'\n\nconst POPIN_ID = 'nb-videos-popin'\n\nexport default class extends Card {\n render() {\n const {\n video: { auto_play = false }\n } = this.props\n\n return `${!auto_play ? this.renderDefaultCardVideo() : this.renderAutoPlayCardVideo()}`\n }\n\n renderAutoPlayCardVideo() {\n const { video } = this.props\n\n video.video_service = 'local'\n\n if (!video.video_id) {\n throw new Error('You must add the video ID and video service defined')\n }\n\n return `\n <div class=\"card-video card-video__is-autoplay\">\n <nb-video data=\"${stringifyForAttribute(video)}\"></nb-video>\n <button id=\"autoplay-toggle\" class=\"autoplay-button video_button icon-pause\" aria-pressed=\"false\" data-status=\"pause\">\n <span class=\"video_button__icon\">\n <nb-icon icon=\"24/symbol/play-solid\" class=\"playButton\"></nb-icon>\n <nb-icon icon=\"24/symbol/pause-solid\" class=\"pauseButton\"></nb-icon>\n </span>\n <span class=\"sr-only\">Pause</span>\n </button>\n </div>`\n }\n\n renderDefaultCardVideo() {\n const { video, contrast, cardSize, animated } = this.props\n\n if (!video.video_id || !video.video_service) {\n throw new Error('You must add the video ID and video service defined')\n }\n\n const image = getImage(this.props)\n const backgroundImage = image ? `background-image:url(${image})` : null\n this.elementId = 'play_' + this.createPopinID()\n\n return `\n <div class=\"card-video\"\n style=\"${backgroundImage}\"\n contrast=\"${contrast}\"\n card-size=\"${cardSize}\"\n animated=\"${animated}\"\n >\n\n ${this.renderPlayButton(this.elementId)}\n ${this.renderCardDisplay()}\n\n </div>${this.renderPlayer()}`\n }\n\n renderCardDisplay() {\n return `\n <div class=\"card-video__display\">\n <div class=\"gradient\"></div>\n ${this.renderTitle()}\n ${this.renderDescription()}\n ${renderCta(this.props, 'card-image__action')}\n ${renderLink(this.props, 'card-image__action')}\n </div>\n `\n }\n renderPlayButton(elementId) {\n return `\n <div class=\"card-video__play\" play_id=\"${elementId}\">\n <button class=\"card-video__videoIcon\">\n <nb-icon icon=\"24/symbol/play-solid\"></nb-icon>\n <span class=\"sr-only\">Play</span>\n </button>\n </div>\n `\n }\n\n renderPlayer() {\n const {\n video: {\n video_id,\n video_mobile = '',\n display_ui_controls,\n cc_policy_language,\n video_service\n } = {}\n } = this.props\n\n const POPIN_ID = this.createPopinID()\n return `<nb-popin id=\"${POPIN_ID}\" variation=\"before\" bgcolor=\"white\">\n <nb-video\n container_id=\"player-${POPIN_ID}\"\n video_id=\"${video_id}\"\n video_mobile=\"${video_mobile}\"\n video_service=\"${video_service}\"\n popin_id=\"${POPIN_ID}\"\n display_controls=\"${display_ui_controls}\"\n ccPolicy_language=\"${cc_policy_language}\"\n allow_popin_autoplay=\"true\"\n ></nb-video>\n </nb-popin>`\n }\n\n onOpenPlayer(e) {\n const { campaign } = this.props\n\n e.preventDefault()\n const POPIN_ID = this.createPopinID()\n dispatchEvent({ eventName: EVENT_POPIN_OPEN, args: { id: POPIN_ID } })\n handlePromoClick({\n campaign: campaign,\n cta_name: `VIDEO - ${this.props.video.video_id}`\n })\n }\n\n createPopinID() {\n const {\n title,\n video: { video_id }\n } = this.props\n const seed = title || video_id\n this.stripedHeading = stripHTML(seed).substr(0, 15)\n return `video-card-${makeHash(this.stripedHeading)}-${video_id}`\n }\n\n removePlayer() {\n const playerElement = document.querySelector(`#${POPIN_ID}`)\n if (playerElement) {\n playerElement.remove()\n }\n }\n\n boundOnButtonSelfVideoClick(e) {\n const targetElement = e.target || e.srcElement\n const video = document.querySelector('.card-video__is-autoplay video')\n const srOnly = document.querySelector('.sr-only')\n\n if (targetElement.dataset.status === 'pause') {\n video.pause()\n targetElement.dataset.status = 'play'\n targetElement.classList.remove('icon-pause')\n targetElement.classList.add('icon-play')\n srOnly.textContent = 'Play'\n } else {\n video.play()\n targetElement.dataset.status = 'pause'\n targetElement.classList.remove('icon-play')\n targetElement.classList.add('icon-pause')\n srOnly.textContent = 'Pause'\n }\n }\n\n bindEvents() {\n const elementId = 'play_' + this.createPopinID()\n\n this.renderSelfVideoButton = document.querySelector('#autoplay-toggle')\n if (this.renderSelfVideoButton) {\n this.renderSelfVideoButton.addEventListener('click', this.boundOnButtonSelfVideoClick)\n }\n\n return [\n {\n id: `[play_id=\"${elementId}\"]`,\n eventType: 'click',\n cb: this.onOpenPlayer.bind(this)\n }\n ]\n }\n\n renderTitle() {\n const { title } = this.props\n if (!title) {\n return ''\n }\n\n return `<h3 class=\"h-lg-500\">${title}</h3>`\n }\n\n renderDescription() {\n const { description } = this.props\n if (!description) {\n return ''\n }\n\n return `<p class=\"t-sm-400\">${description}</p>`\n }\n}\n","/**\n *\n * Card Image Props\n *\n * - cardSize\n * - contrast\n * - animated\n * - title\n * - description\n * - cta {}\n * - link {}\n * - background_retina\n * - background_desktop\n * - background_mobile\n *\n */\n\nimport './image-card.composer.scss'\nimport Card from '../card.class'\n\nimport { renderCta, renderLink } from '../../helpers/renderButtons'\nimport { getImage } from '../../helpers/getImage'\n\nexport default class extends Card {\n render() {\n const { animated, contrast, cardSize, title = '', description = '' } = this.props\n\n const image = getImage(this.props)\n const backgroundImage = `background-image:url(${image})`\n\n return `<div class=\"card-image\"\n style=\"${backgroundImage}\"\n animated=\"${animated}\"\n contrast=\"${contrast}\"\n card-size=\"${cardSize}\"\n >\n <div class=\"card-image__wrapper\">\n <div class=\"card-image__display\">\n ${title && `<h3 class=\"card-image__title h-lg-500\">${title}</h3>`}\n ${description && `<p class=\"t-sm-400\">${description}</p>`}\n ${renderCta(this.props, 'card-image__action')}\n ${renderLink(this.props, 'card-image__action')}\n </div>\n </div>\n ${this.renderPopin()}\n </div>`\n }\n\n renderPopin() {\n const { cta, popin = {} } = this.props\n const {\n id = '',\n image = '',\n heading = '',\n description = '',\n image_alt = '',\n close = ''\n } = popin\n\n if (!id || !cta.popin_id) {\n return ''\n }\n\n return `<nb-popin\n id=\"${cta.popin_id}\"\n heading=\"${heading}\"\n variation=\"right\"\n bgcolor=\"highlight\"\n image=\"${image}\"\n image_alt=\"${image_alt}\"\n label_close=\"${close}\"\n size=\"SS\">\n ${description}\n </nb-popin>`\n }\n}\n","/**\n *\n * Card Product Props\n *\n * - cardSize\n * - contrast\n * - heading\n * - title\n * - cta {}\n * - background_color\n * - background_retina\n * - background_desktop\n * - background_mobile\n *\n */\n\nimport './product-card.composer.scss'\nimport Card from '../card.class'\n\nimport { renderCta } from '../../helpers/renderButtons'\nimport { getImage } from '../../helpers/getImage'\n\nexport default class extends Card {\n render() {\n const {\n heading = '',\n title = '',\n productImage,\n productImageAlt = '',\n cardSize,\n contrast\n } = this.props\n\n const cardSizeAtrb = cardSize ? `card-size='${cardSize}'` : ``\n const image = getImage(this.props)\n const backgroundImage = image ? `background-image:url(${image});` : ``\n const backgroundColor = this.props['background_color']\n ? `background-color:${this.props['background_color']};`\n : ``\n\n return `<div\n class=\"card-product\"\n style=\"${backgroundImage + backgroundColor}\"\n ${cardSizeAtrb}\n contrast=\"${contrast}\">\n <div class=\"card-product\">\n <div class=\"card-product__display\">\n <div class=\"card-product__item card-product__image\">\n <img class=\"card-product__item\"\n src=\"${productImage}\"\n alt=\"${productImageAlt}\"\n height=\"150\"\n />\n </div>\n ${\n heading &&\n `<h3 class=\"t-xs-500-caps-sl card-product__item card-product__heading\">${heading}</h3>`\n }\n ${\n title &&\n `<h4 class=\"h-xl-700 card-product__item card-product__title\">${title}</h4>`\n }\n ${renderCta(this.props, 'card-product__item card-product__action')}\n </div>\n </div>\n </div>`\n }\n}\n","/**\n *\n * Card Product SKU Props\n *\n * - cardSize\n * - contrast\n * - heading\n * - title\n * - cta {}\n * - background_color\n * - background_retina\n * - background_desktop\n * - background_mobile\n *\n */\n\nimport './product-sku.composer.scss'\nimport Card from '../card.class'\n\nimport { makeId } from '@kissui/helpers/src/utils'\nimport { renderLink } from '../../helpers/renderButtons'\nimport { getImage } from '../../helpers/getImage'\nimport { getCurrency, getPriceFormatter, getProduct } from '@kissui/helpers/src/catalog'\nimport { getMergedProductData } from '@kissui/page-builder-sections/src/cross-sell-natural/dataTransform'\n\nexport default class extends Card {\n async getSkuQuickViewData(sku, popinId, props) {\n try {\n const payload = await getProduct(sku)\n\n if (!payload) {\n return\n }\n\n const CARD_ID = `cardId_${popinId}`\n const quickViewProps = await this.getSkuQuickViewProp(popinId, props, payload)\n\n let quickViewElement = document.createElement('nb-sku-quick-view')\n quickViewElement.setAttribute('data', JSON.stringify(quickViewProps))\n quickViewElement.setAttribute('id', popinId)\n\n const card = document.getElementById(CARD_ID)\n card.appendChild(quickViewElement)\n } catch (e) {\n console.error(`getProduct fail on sku ${sku}`)\n }\n }\n\n getCapsuleFeatures(capsuleProperties) {\n return {\n acidity: { value: capsuleProperties?.acidity },\n bitterness: { value: capsuleProperties?.bitterness },\n body: { value: capsuleProperties?.body },\n capsuleProperties: { intensity: capsuleProperties?.intensity },\n roast: { value: capsuleProperties?.roastLevel }\n }\n }\n\n async getSkuQuickViewProp(popinId, product, skuData) {\n const { sku_quick_view } = product\n\n this.priceFormatter = await getPriceFormatter()\n this.currency = getCurrency()\n\n const productInfo = await getProduct(product.sku)\n const mergedProductData = getMergedProductData(\n productInfo,\n product,\n this.props,\n this.priceFormatter,\n this.currency\n )\n\n const props = {\n popin: {\n popin_id: popinId,\n close: sku_quick_view.popin.close,\n footer: true\n },\n product: {\n ...product,\n ...skuData,\n ...this.getCapsuleFeatures(skuData.capsuleProperties)\n },\n intensity: {\n intensity_label: 'Intensity',\n a11y_intensity_max: 'max of {max_intensity}'\n },\n cup_sizes: {\n ...sku_quick_view.cup_sizes,\n items: product.cupSizesDetails\n },\n aromatic_profile: {\n ...sku_quick_view.aromatic_profile,\n items: mergedProductData.capsuleProductAromatics\n },\n link: {\n ...sku_quick_view.link,\n url: mergedProductData.pdpURLs.desktop\n },\n levels: {\n ...sku_quick_view.levels\n },\n pricing: {\n add_to_cart: {\n sku: mergedProductData.sku,\n longSku: mergedProductData.longSku,\n category_name: mergedProductData.categoryName,\n position: '',\n variation: 'small',\n price: mergedProductData.price,\n strikethrough_price: mergedProductData.strikethrough_price,\n hidePrice: mergedProductData.hidePrice,\n url: '',\n view_details_label: 'View details',\n rendererName: ''\n },\n showSleeve: {},\n showCapsulePrice: {}\n }\n }\n\n return props\n }\n\n render() {\n const {\n heading = '',\n title = '',\n productImage,\n productImageAlt = '',\n cardSize,\n contrast,\n sku\n } = this.props\n\n const popinId = `popin-product-sku-${makeId(5)}`\n\n this.getSkuQuickViewData(sku, popinId, this.props)\n\n const cardSizeAtrb = cardSize ? `card-size='${cardSize}'` : ``\n const image = getImage(this.props)\n const backgroundImage = image ? `background-image:url(${image});` : ``\n const backgroundColor = this.props['background_color']\n ? `background-color:${this.props['background_color']};`\n : ``\n\n return `<div\n class=\"card-product\"\n style=\"${backgroundImage + backgroundColor}\"\n ${cardSizeAtrb}\n contrast=\"${contrast}\"\n id=\"cardId_${popinId}\"\n >\n <div class=\"card-product\">\n <div class=\"card-product__display\">\n <div class=\"card-product__item card-product__image\">\n <img class=\"card-product__item\"\n src=\"${productImage}\"\n alt=\"${productImageAlt}\"\n height=\"150\"\n />\n </div>\n ${\n heading &&\n `<h3 class=\"t-xs-500-caps-sl card-product__item card-product__heading\">${heading}</h3>`\n }\n ${\n title &&\n `<h4 class=\"h-xl-700 card-product__item card-product__title\">${title}</h4>`\n }\n ${renderLink(\n this.props,\n 'card-product__item card-product__action link-button--tertiary',\n popinId\n )}\n </div>\n </div>\n </div>`\n }\n}\n","import { sanitizeString } from '@kissui/helpers/src/utils'\nimport { getMergedProductCoffeeData } from './product.coffee.dto'\nimport { getMergedProductMachineData } from './product.machine.dto'\nimport { VARIATION_PLP } from '@kissui/components/src/sku/constants'\nimport { getMergedProductGiftCardData } from './product.giftCard.dto'\nimport { getMergedProductAccessoryData } from './product.accessory.dto'\nimport { apiOverride } from '@kissui/components/src/sku/services'\nimport {\n ECAPI_TYPE_ACCESSORY,\n ECAPI_TYPE_CAPSULE,\n ECAPI_TYPE_GIFT_CARD,\n ECAPI_TYPE_MACHINE\n} from '@kissui/helpers/src/catalog'\n\nexport const getMergedProductData = (\n product,\n pageBuilderProductProps,\n pageBuilderProps,\n priceFormatter,\n currency\n) => {\n const { options } = pageBuilderProps\n const {\n variant = {},\n labels = [],\n strikethrough_price,\n additional_message,\n additional_message_icon,\n additional_message_link,\n contact_cta\n } = pageBuilderProductProps || {}\n\n // lists header props not coming from this.props\n let data = {\n sku: product.internationalId,\n technologies: product.technologies,\n longSku: product.id,\n name: product.name,\n headline: sanitizeString(product.headline),\n sales_multiple: product.salesMultiple,\n unit_quantity: product.unitQuantity,\n type: product.type,\n category_name: product.rangeData?.name || '',\n label_range: product.rangeData?.name || '',\n price: product.price ? priceFormatter.short(currency, product.price) : null,\n rawPrice: product.price,\n strikethrough_price: strikethrough_price || '',\n variation: VARIATION_PLP,\n image_alt_text: product.name,\n image: product.images?.icon || product.images?.push || product.images?.main,\n additional_message: additional_message || '',\n additional_message_icon: additional_message_icon || '',\n additional_message_link: additional_message_link || {},\n contact_cta: contact_cta || {},\n ...apiOverride(product, pageBuilderProductProps)\n }\n\n if (labels && labels.length) {\n data.labels = labels\n }\n\n if (product.highlighted) {\n data.highlighted = product.highlighted\n }\n\n let dataTransformObjectProductType = {}\n if (product.type === ECAPI_TYPE_CAPSULE) {\n dataTransformObjectProductType = getMergedProductCoffeeData(\n product,\n pageBuilderProductProps,\n pageBuilderProps,\n priceFormatter,\n currency\n )\n } else if (product.type === ECAPI_TYPE_MACHINE) {\n dataTransformObjectProductType = getMergedProductMachineData(\n product,\n pageBuilderProductProps,\n pageBuilderProps\n )\n } else if (product.type === ECAPI_TYPE_ACCESSORY) {\n dataTransformObjectProductType = getMergedProductAccessoryData(\n product,\n pageBuilderProductProps,\n pageBuilderProps\n )\n } else if (product.type === ECAPI_TYPE_GIFT_CARD) {\n dataTransformObjectProductType = getMergedProductGiftCardData(\n product,\n pageBuilderProductProps,\n pageBuilderProps\n )\n }\n\n return {\n ...product,\n ...options,\n ...variant,\n ...data,\n ...dataTransformObjectProductType\n }\n}\n","export const VARIATION_PLP = 'plp'\nexport const VARIATION_PDP = 'pdp'\nexport const VARIATION_CROSS_SELL = 'cross-sell'\nexport const VARIATION_SMALL = 'small'\n","export const getMergedProductMachineData = (product, pageBuilderProductProps, pageBuilderProps) => {\n const { strikethrough_price, variant = {} } = pageBuilderProductProps\n const { ratingsAndReviews } = product\n\n // lists header props not coming from this.props\n const options = {\n ratings: ratingsAndReviews\n }\n\n if (variant?.colors) {\n options.colors = variant.colors\n options.activeSku = product.internationalId\n options.max_colors = 99\n }\n\n options.strikethrough_price = strikethrough_price || ''\n options.show_ratings = (pageBuilderProps && pageBuilderProps.options.show_ratings) || false\n options.minimum_rating = (pageBuilderProps && pageBuilderProps.options.minimum_rating) || 0\n\n return options\n}\n","export const getMergedProductAccessoryData = () => ({})\n","export const getMergedProductGiftCardData = (_, pageBuilderProductProps) => {\n const { variant = {} } = pageBuilderProductProps\n\n return {\n image: variant && variant.default_image\n }\n}\n","/**\n *\n * Card Text Props\n *\n * - cardSize\n * - contrast\n * - icon {}\n * - heading\n * - title\n * - description\n * - link\n * - cta\n * - background_color\n * - background_retina\n * - background_desktop\n * - background_mobile\n *\n */\n\nimport './text-card.composer.scss'\nimport Card from '../card.class'\n\nimport { renderCta, renderLink } from '../../helpers/renderButtons'\nimport { getImage } from '../../helpers/getImage'\n\nexport default class extends Card {\n render() {\n const {\n heading = '',\n title = '',\n description = '',\n icon = '',\n background_color,\n cardSize,\n contrast\n } = this.props\n\n const backgroundColorStyle = background_color\n ? `background-color: ${background_color};`\n : ''\n const image = getImage(this.props)\n const backgroundImage = image ? `background-image:url(${image});` : ''\n\n return `<div class=\"card-text\" contrast=\"${contrast}\" style=\"${backgroundColorStyle}${backgroundImage}\" card-size=\"${cardSize}\">\n <div class=\"card-text\">\n <div class=\"card-text__display\">\n ${\n icon &&\n `<div class=\"card-text__item card-text__icon\">\n <nb-icon icon=\"${icon}\"></nb-icon>\n </div>`\n }\n ${\n heading &&\n `<h4 class=\"t-xs-700-caps-sl card-text__item card-text__heading\">${heading}</h4>`\n }\n ${\n title &&\n `<h3 class=\"h-xl-300 card-text__item card-text__title\">${title}</h3>`\n }\n ${\n description &&\n `<p class=\"t-sm-400 card-text__item card-text__body\">${description}</p>`\n }\n ${renderCta(this.props, 'card-text__item card-text__action')}\n ${renderLink(this.props, 'card-text__item card-text__action')}\n </div>\n </div>\n ${this.renderPopin()}\n </div>`\n }\n\n renderPopin() {\n const { cta, popin = {} } = this.props\n const {\n id = '',\n image = '',\n heading = '',\n description = '',\n image_alt = '',\n close = ''\n } = popin\n\n if (!id || !cta.popin_id) {\n return ''\n }\n\n return `<nb-popin\n id=\"${cta.popin_id}\"\n heading=\"${heading}\"\n variation=\"right\"\n bgcolor=\"highlight\"\n image=\"${image}\"\n image_alt=\"${image_alt}\"\n label_close=\"${close}\"\n size=\"SS\">\n ${description}\n </nb-popin>`\n }\n}\n","export default [\n 'one',\n 'three-equal',\n 'two-equal',\n 'two-x2-right-bigger',\n 'two-x2-left-bigger',\n 'right-big-square',\n 'left-big-square'\n]\n","/*!\n * swiped-events.js - v@version@\n * Pure JavaScript swipe events\n * https://github.com/john-doherty/swiped-events\n * @inspiration https://stackoverflow.com/questions/16348031/disable-scrolling-when-touch-moving-certain-element\n * @author John Doherty <www.johndoherty.info>\n * @license MIT\n */\n\n// scrollElement has been added as an optional parameter in order to avoid scrolling to fire a swipe\nconst swipeEvents = (window: Window & typeof globalThis, document: Document, stopEl?: HTMLElement) => {\n if (window.nwcSwipeEvents) {\n return\n }\n window.nwcSwipeEvents = true\n\n // patch CustomEvent to allow constructor creation (IE/Chrome)\n // if (typeof window.CustomEvent !== 'function') {\n // window.CustomEvent = function(event, params) {\n // params = params || {bubbles: false, cancelable: false, detail: undefined}\n //\n // let evt = document.createEvent('CustomEvent')\n // evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)\n // return evt\n // }\n //\n // window.CustomEvent.prototype = window.Event.prototype\n // }\n\n document.addEventListener('touchstart', handleTouchStart, false)\n document.addEventListener('touchmove', handleTouchMove, false)\n document.addEventListener('touchend', handleTouchEnd, false)\n\n let xDown: null | number = null\n let yDown: null | number = null\n let xDiff: null | number = null\n let yDiff: null | number = null\n let timeDown: null | number = null\n let startEl: HTMLElement | null = null\n\n // Variables added for checkScrollConditions\n let scrollTopArray: number[] = []\n let scrollLeftArray: number[] = []\n\n /**\n * Avoid swipe up or down events to fire by checking the scrollTop position of the optional param scrollEl (scrollable zone)\n * @param {string} direction - 'up' ,'down', 'left', 'right'\n * @returns {boolean}\n */\n function checkScrollCondition(direction: \"up\" |\"down\" | \"left\" | \"right\", e: TouchEvent) {\n if (stopEl === undefined) {\n return true\n }\n\n let el = e.target as HTMLElement\n let result = true\n let i = 0\n while (el !== stopEl && result) {\n if (isScrollable(el)) {\n switch (direction) {\n case 'up':\n result = scrollTopArray[i] === el.scrollHeight - el.clientHeight\n break\n case 'down':\n result = scrollTopArray[i] === 0\n break\n case 'left':\n result = scrollLeftArray[i] === el.scrollWidth - el.clientWidth\n break\n case 'right':\n result = scrollLeftArray[i] === 0\n break\n default:\n result = true\n }\n }\n el = el.parentNode as HTMLElement\n i++\n }\n return result\n }\n\n function memorizeStartElScrollPositions(el: HTMLElement) {\n if (stopEl === undefined || !stopEl.contains(el)) {\n return\n }\n scrollTopArray = []\n scrollLeftArray = []\n while (el !== stopEl) {\n scrollTopArray.push(el.scrollTop)\n scrollLeftArray.push(el.scrollLeft)\n el = el.parentNode as HTMLElement\n }\n }\n\n function isScrollable(el: HTMLElement) {\n return el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth\n }\n\n /**\n * Fires swiped event if swipe detected on touchend\n * @param {object} e - browser event object\n * @returns {void}\n */\n function handleTouchEnd(e: TouchEvent) {\n // if the user released on a different target, cancel!\n if (startEl !== e.target) {\n return\n }\n\n // Calculate the data-swipe-threshold to be a percentage of the viewport\n const defaultVertical = window.innerHeight * 0.25 // 25% of the viewport\n const defaultHorizontal = window.innerWidth * 0.5 // 50% of the viewport\n\n let swipeThresholdVertical =\n getNearestAttribute(startEl!, 'data-swipe-threshold', defaultVertical)\n\n let swipeThresholdHorizontal =\n getNearestAttribute(startEl!, 'data-swipe-threshold', defaultHorizontal)\n\n let swipeTimeout = getNearestAttribute(startEl!, 'data-swipe-timeout', 500) // default 500ms\n let timeDiff = Date.now() - timeDown!\n let eventType = ''\n let changedTouches = e.changedTouches || e.touches || []\n\n if (Math.abs(xDiff!) > Math.abs(yDiff!)) {\n // most significant\n if (Math.abs(xDiff!) > swipeThresholdHorizontal && timeDiff < swipeTimeout) {\n if (xDiff! > 0) {\n if (checkScrollCondition('left', e)) {\n eventType = 'swiped-left'\n }\n } else {\n if (checkScrollCondition('right', e)) {\n eventType = 'swiped-right'\n }\n }\n }\n } else if (Math.abs(yDiff!) > swipeThresholdVertical && timeDiff < swipeTimeout) {\n if (yDiff! > 0) {\n if (checkScrollCondition('up', e)) {\n eventType = 'swiped-up'\n }\n } else {\n if (checkScrollCondition('down', e)) {\n eventType = 'swiped-down'\n }\n }\n }\n\n if (eventType !== '') {\n let eventData = {\n dir: eventType.replace(/swiped-/, ''),\n touchType: (changedTouches[0] as Touch & { touchType: string })?.touchType ?? 'direct', // This is a non standard feature used only by safari\n xStart: xDown!,\n xEnd: (changedTouches[0] || {}).clientX || -1,\n yStart: yDown!,\n yEnd: (changedTouches[0] || {}).clientY || -1\n }\n\n // fire `swiped` event event on the element that started the swipe\n startEl!.dispatchEvent(\n new CustomEvent('swiped', { bubbles: true, cancelable: true, detail: eventData })\n )\n\n // fire `swiped-dir` event on the element that started the swipe\n startEl!.dispatchEvent(\n new CustomEvent(eventType, { bubbles: true, cancelable: true, detail: eventData })\n )\n }\n\n // reset values\n xDown = null\n yDown = null\n timeDown = null\n }\n\n /**\n * Records current location on touchstart event\n * @param {object} e - browser event object\n * @returns {void}\n */\n function handleTouchStart(e: TouchEvent) {\n const target = e.target as HTMLElement\n // if the element has data-swipe-ignore=\"true\" we stop listening for swipe events\n if (target.getAttribute('data-swipe-ignore') === 'true') {\n return\n }\n\n startEl = target\n memorizeStartElScrollPositions(startEl)\n\n timeDown = Date.now()\n xDown = e.touches[0].clientX\n yDown = e.touches[0].clientY\n xDiff = 0\n yDiff = 0\n }\n\n /**\n * Records location diff in px on touchmove event\n * @param {object} e - browser event object\n * @returns {void}\n */\n function handleTouchMove(e: TouchEvent) {\n if (!xDown || !yDown) {\n return\n }\n\n let xUp = e.touches[0].clientX\n let yUp = e.touches[0].clientY\n\n xDiff = xDown - xUp\n yDiff = yDown - yUp\n }\n\n /**\n * Gets attribute off HTML element or nearest parent\n * @param {object} el - HTML element to retrieve attribute from\n * @param {string} attributeName - name of the attribute\n * @param {any} defaultValue - default value to return if no match found\n * @returns {any} attribute value or defaultValue\n */\n function getNearestAttribute(el: HTMLElement, attributeName: string | number, defaultValue: number) {\n // walk up the dom tree looking for attributeName\n while (el && el !== document.documentElement) {\n let attributeValue = el.getAttribute(String(attributeName))\n\n if (attributeValue) {\n return parseInt(attributeValue, 10)\n }\n\n el = el.parentNode as HTMLElement\n }\n\n return defaultValue\n }\n}\n\nexport default swipeEvents\n","export function recursiveSwitchAriaHidden(elem, componentOpenState) {\n const parent = elem.parentNode\n const body = document.getElementsByTagName('body')[0]\n\n if (parent === body) {\n return\n }\n\n const brothers = parent.children\n for (const brother of brothers) {\n if (brother !== elem) {\n componentOpenState\n ? brother.setAttribute('aria-hidden', componentOpenState)\n : brother.removeAttribute('aria-hidden')\n }\n }\n recursiveSwitchAriaHidden(parent, componentOpenState)\n}\n\nexport function focusin(e, el, loop) {\n if (!el.contains(e.target)) {\n if (el.lastFocused === el.firstFocusable) {\n loop ? el.lastFocusable.focus() : el.firstFocusable.focus()\n } else {\n loop ? el.firstFocusable.focus() : el.lastFocusable.focus()\n }\n } else {\n el.lastFocused = e.target\n }\n}\n\nexport function setFirstAndLastFocusable(el) {\n const focusable = el.querySelectorAll('button, [href], input, select, textarea, [tabindex=\"0\"]')\n el.firstFocusable = focusable[0]\n el.lastFocusable = focusable[focusable.length - 1]\n el.lastFocused = el.firstFocusable\n}\n","import './overlay.scss'\nimport { dispatchEvent } from '@kissui/helpers/src/assets/js/eventDispatch'\nimport { EVENT_POPIN_CLOSE, TIME_INSTANT, TIME_SLOW } from '@kissui/components'\n\nconst open = popin_id => {\n const overlay = document.createElement('DIV')\n overlay.classList.add('nb-overlay')\n overlay.addEventListener('click', () => {\n dispatchEvent({ eventName: EVENT_POPIN_CLOSE, args: { id: popin_id } })\n })\n document.body.appendChild(overlay)\n setTimeout(() => {\n overlay.classList.add('fadein')\n }, TIME_INSTANT)\n}\n\nconst close = () => {\n if (!document.getElementsByClassName('nb-overlay').length) {\n return\n }\n const overlay = document.getElementsByClassName('nb-overlay')[0]\n overlay.classList.remove('fadein')\n setTimeout(() => {\n overlay.remove()\n }, TIME_SLOW)\n}\n\nexport default { open, close }\n","import swipeEvents from '@kissui/helpers/src/swipeEvents'\nimport createProps, { parseBool } from '@kissui/helpers/src/props.helpers'\nimport {\n recursiveSwitchAriaHidden,\n setFirstAndLastFocusable,\n focusin\n} from '@kissui/helpers/src/assets/js/scopedKeyboardNav'\nimport {\n TIME_FAST,\n EVENT_POPIN_OPENED,\n EVENT_POPIN_CLOSED,\n EVENT_VIDEO_TOGGLE,\n EVENT_POPIN_OPEN,\n EVENT_POPIN_CLOSE,\n EVENT_POPIN_KEY_DOWN,\n EVENT_SWIPED_DOWN\n} from '@kissui/components'\nimport Overlay from './components/overlay'\nimport viewportHelper from '@kissui/helpers/src/viewport.helpers'\nimport { dispatchEvent, readEvent } from '@kissui/helpers/src/assets/js/eventDispatch'\n\nconst STATE_OPEN = 'isOpen'\nconst SCROLL_LOCK = 'scroll-lock'\n\nclass Popin extends HTMLElement {\n constructor() {\n super()\n this.props = {}\n this.ariaModal = null\n this.isVideo = null\n\n this.boundOpen = this.open.bind(this)\n this.boundClose = this.close.bind(this)\n this.boundEscapeClose = this.escapeClose.bind(this)\n this.boundFocus = this.focus.bind(this)\n this.boundFocusin = this.focusin.bind(this)\n }\n\n connectedCallback() {\n this.style.display = 'none'\n this.props = createProps(this.attributes)\n\n if (!this.id) {\n this.id = this.props.id\n }\n\n if (!this.content && !this.slot) {\n this.slot = this.innerHTML\n }\n\n this.ariaModal = false\n this.isVideo = false\n this.render()\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n this.props = createProps(this.attributes)\n\n if (name === 'content') {\n this.props.content = newValue\n }\n }\n\n static get observedAttributes() {\n return ['content']\n }\n\n disconnectedCallback() {\n if (!this.hasEvent) {\n return\n }\n this.unbindEvent()\n }\n\n render() {\n if (this.hasEvent) {\n this.unbindEvent()\n }\n const {\n heading = '',\n subheading = '',\n bgcolor = 'highlight',\n size = 'M',\n label_close = 'Close',\n image = '',\n image_alt = '',\n variation = 'before',\n content = '',\n heading_class = viewportHelper.is.mobile ? 't-sm-700-sl' : 'h-lg-700'\n } = this.props\n const slot = content || this.slot\n\n if (slot === '') {\n this.bindEvent()\n this.classList.remove(STATE_OPEN)\n this.isOpen = false\n return false\n }\n this.checkIsVideo(slot)\n this.setAttribute('size', this.isVideo ? 'L' : size)\n\n // FYI : The role is dialog, not alertdialog (only used for alerts / warnings ...)\n this.setAttribute('role', 'dialog')\n this.setAttribute('aria-hidden', 'true')\n this.setAttribute('bgcolor', bgcolor)\n this.setAttribute('variation', variation)\n\n // Be careful to not remove the title div, even if empty, because it holds on purpose the top gradient for scroll effect\n this.innerHTML = `\n <nb-cta\n variation=\"navigation\"\n ${bgcolor === 'white' ? `contrast=\"highlight\"` : `contrast=\"light\"`}\n icon_right=\"24/symbol/close\"\n label=\"${label_close}\"></nb-cta>\n <div class=\"wrapper\">\n ${\n heading &&\n `<div class=\"title\" >\n ${heading && `<h2 class=\"${heading_class}\">${heading}</h2>`}\n </div>`\n }\n ${\n subheading &&\n `<div class=\"subtitle\">\n ${subheading && `<p class=\"t-sm-500\">${subheading}</p>`}\n </div>`\n }\n\n <div class=\"content t-sm-400\" tabindex=\"-1\">\n ${\n image &&\n `<div class=\"popin-header-img\"><img loading=\"lazy\" src=\"${image}\" alt=\"${image_alt}\" title=\"${image_alt}\" width=\"300\" height=\"225\" /></div>`\n }\n ${slot}\n </div>\n ${this.renderFooter()}\n </div>\n ${this.isVideo && viewportHelper.is.mobile ? '<div class=\"swipeOverlay\"></div>' : ''}\n `\n\n // Expected css to be downloaded\n setTimeout(() => {\n this.style.display = 'inherit'\n }, 100)\n\n // Set the first and last focusable elements\n setFirstAndLastFocusable(this)\n\n this.buttonElement = this.querySelector('button')\n this.bindEvent()\n }\n\n renderFooter() {\n const { footer } = this.props\n return parseBool(footer) ? '<footer></footer>' : ''\n }\n\n checkIsVideo(slot) {\n const tempEl = document.createElement('div')\n tempEl.innerHTML = slot\n if (tempEl.children.length === 1 && tempEl.children[0].tagName === 'NB-VIDEO') {\n this.isVideo = true\n this.setAttribute('video', 'true')\n }\n }\n\n addLock() {\n document.getElementsByTagName('html')[0].classList.add(SCROLL_LOCK)\n Overlay.open(this.id)\n }\n\n removeLock() {\n // In case we have popin inside a popin we shouldn't remove the scroll_lock\n const parentPopin = this.parentNode.closest('nb-popin')\n if (!parentPopin) {\n document.getElementsByTagName('html')[0].classList.remove(SCROLL_LOCK)\n }\n Overlay.close()\n }\n\n switchAriaModal() {\n this.ariaModal = !this.ariaModal\n // This is the future way to scope the SR focus to a modal, but it's not supported yet by all SR\n this.setAttribute('aria-modal', this.ariaModal)\n // So we need to set aria-hidden=false to all ancestors of parent until body\n recursiveSwitchAriaHidden(this, this.ariaModal)\n }\n\n async open(e) {\n const event = readEvent(e)\n if (event.id !== this.id) {\n return\n }\n // Transitionend listener is fired multiple times (fore each css property)\n // so we need to instantiate it only when we open or close and then we remove it on focusin\n this.addEventListener('transitionend', this.boundFocus)\n document.addEventListener('focusin', this.boundFocusin)\n this.openingSource = document.activeElement\n\n this.addLock()\n this.switchAriaModal()\n this.setAttribute('aria-hidden', 'false')\n this.isOpen = !this.isOpen\n\n // event variable already contains ID and other args sent along with dispatch event\n dispatchEvent({\n eventName: EVENT_POPIN_OPENED,\n args: event\n })\n\n await new Promise(resolve => {\n setTimeout(() => {\n this.classList.add(STATE_OPEN)\n resolve()\n }, TIME_FAST)\n })\n }\n\n close(event) {\n event.cancelBubble = true\n if (event.stopPropagation) {\n event.stopPropagation()\n }\n // Transitionend listener is fired multiple times (fore each css property)\n // so we need to instantiate it only when we open or close, and then we remove it on focusin\n this.addEventListener('transitionend', this.boundFocus)\n document.removeEventListener('focusin', this.boundFocusin)\n this.removeLock()\n if (this.isVideo) {\n const openVideoPopin = this.closest('.has-open-video')\n if (openVideoPopin) {\n openVideoPopin.classList.remove('has-open-video')\n }\n }\n this.switchAriaModal()\n this.setAttribute('aria-hidden', 'true')\n this.isOpen = !this.isOpen\n this.classList.remove(STATE_OPEN)\n\n dispatchEvent({\n eventName: EVENT_POPIN_CLOSED,\n args: { id: this.id }\n })\n }\n\n focus() {\n this.removeEventListener('transitionend', this.boundFocus)\n if (this.isOpen) {\n this.buttonElement.focus()\n } else {\n this.openingSource.focus()\n }\n }\n\n focusin(e) {\n focusin(e, this, true)\n }\n\n escapeClose(e) {\n if (e.key === 'Escape' && this.isOpen) {\n this.close(e)\n }\n }\n\n swipeDown(e) {\n if (this.isOpen) {\n this.close(e)\n }\n }\n\n swipeOverlayTogglePlayPause() {\n dispatchEvent({\n eventName: EVENT_VIDEO_TOGGLE,\n args: { id: this.id }\n })\n }\n\n bindEvent() {\n this.hasEvent = true\n this.buttonElement != null && this.buttonElement.addEventListener('click', this.boundClose)\n window.addEventListener(EVENT_POPIN_OPEN, this.boundOpen)\n window.addEventListener(EVENT_POPIN_CLOSE, this.boundClose)\n document.addEventListener(EVENT_POPIN_KEY_DOWN, this.boundEscapeClose)\n\n if (viewportHelper.is.mobile) {\n swipeEvents(window, document, this)\n this.boundSwipeDown = this.swipeDown.bind(this)\n document.addEventListener(EVENT_SWIPED_DOWN, this.boundSwipeDown)\n if (this.isVideo) {\n this.swipeOverlay = this.querySelector('.swipeOverlay')\n this.boundSwipeOverlayTogglePlayPause = this.swipeOverlayTogglePlayPause.bind(this)\n this.swipeOverlay.addEventListener('click', this.boundSwipeOverlayTogglePlayPause)\n }\n }\n }\n\n unbindEvent() {\n this.hasEvent = false\n this.buttonElement != null &&\n this.buttonElement.removeEventListener('click', this.boundClose)\n window.removeEventListener(EVENT_POPIN_OPEN, this.boundOpen)\n window.removeEventListener(EVENT_POPIN_CLOSE, this.boundClose)\n document.removeEventListener(EVENT_POPIN_KEY_DOWN, this.boundEscapeClose)\n if (this.boundSwipeDown) {\n document.removeEventListener(EVENT_SWIPED_DOWN, this.boundSwipeDown)\n this.boundSwipeDown = null\n }\n if (this.boundSwipeOverlayTogglePlayPause) {\n this.swipeOverlay.removeEventListener('click', this.boundSwipeOverlayTogglePlayPause)\n this.boundSwipeOverlayTogglePlayPause = null\n }\n }\n}\n\ncustomElements.get('nb-popin') || customElements.define('nb-popin', Popin)\n\nexport default Popin\n","/**\n *\n * Content Composer Props\n *\n * - copywriting\n * - - header {}\n * - - - is_visible\n * - - - heading\n * - - - title\n * - - - description\n * - - - background_color\n * - - components [type_of_cards]\n * - layout\n * - - contrast\n * - - padding_top\n * - - padding_bottom\n * - - card_background_color\n * - - row_size\n * - - layout_type []\n * - - gap []\n * - campaign\n * - - id\n * - - name\n * - - creative: before_content_composer\n * - - position: []\n */\nimport createProps from '@kissui/helpers/src/props.helpers'\nimport cardTypeToClass from './subcomponents/index'\nimport COLUMNS_TYPES from './helpers/columnsSizes'\nimport viewportHelper from '@kissui/helpers/src/viewport.helpers'\n\nimport '@kissui/components/src/popin'\n\nclass ContentComposer extends HTMLElement {\n connectedCallback() {\n this.props = createProps(this.attributes)\n this.controller = new AbortController()\n this.eventsArray = []\n this.render()\n }\n\n render() {\n const {\n copywriting: { header },\n layout: { padding_top, padding_bottom, card_background_color },\n campaign\n } = this.props\n\n const removeMarginTop = !header.is_visible ? '--padding-header: 0' : ''\n const padding_top_no_header = !header.is_visible ? padding_top : ''\n\n const styleCardBackgroundColor = card_background_color\n ? `--background-card: ${card_background_color};`\n : '--background-card: transparent;'\n\n this.innerHTML = `\n ${header.is_visible !== 'false' && this.renderHeader()}\n <nb-container\n background_color=\"white_1000\"\n style=\"${styleCardBackgroundColor} ${removeMarginTop}\"\n contrast=\"light\"\n class=\"content_composer__subcomponents\"\n classname='${padding_top_no_header} ${padding_bottom}'\n campaign_id='${campaign.id}'\n campaign_name='${campaign.name}'\n campaign_position='${campaign.position}'\n campaign_creative='${campaign.creative}'\n >\n ${this.renderSubcomponents()}\n </nb-container>\n `\n this.bindEvents()\n }\n\n renderHeader() {\n const {\n copywriting: {\n header: {\n is_visible,\n background_color = '',\n heading = null,\n title = null,\n description = null\n }\n },\n layout: { contrast = 'light', padding_top }\n } = this.props\n\n if (!is_visible) {\n return ''\n }\n\n const styleBackgroundColor = background_color\n ? `--background-header: ${background_color}`\n : ''\n\n return `<nb-container\n background_color=\"highlight_040_partial\"\n contrast=\"${contrast}\"\n classname=\"${padding_top} content-composer__heading\"\n style=\"${styleBackgroundColor};\"\n >\n <div class=\"content-composer__heading__inner\">\n ${heading && `<h3 class=\"t-md-700-sl\">${heading}</h3>`}\n ${title && `<h2 class=\"h-3xl-700\">${title}</h2>`}\n ${description && `<p class=\"t-sm-400\">${description}</p>`}\n </div>\n </nb-container>`\n }\n\n renderSubcomponents() {\n const {\n copywriting: { components },\n layout: { layout_type, gap }\n } = this.props\n\n const types = COLUMNS_TYPES\n const typeIndex = types.indexOf(layout_type)\n\n if (typeIndex === -1) {\n return ''\n }\n\n const gapSpace = gap || '4px'\n\n return `\n <div class=\"content-composer__showcase\" style=\"--main-gap-cards:${gapSpace}\" data-layout=\"${\n types[typeIndex]\n }\">\n ${components\n .map(component => this.renderSubComponent(component.variant))\n .join('')}\n </div>\n `\n }\n\n renderSubComponent(component) {\n const { row_size } = this.props.layout\n\n let cardType = ''\n for (const [key] of Object.entries(cardTypeToClass)) {\n if (component[`is_${key}`]) {\n cardType = key\n break\n }\n }\n\n const CardClass = cardTypeToClass[cardType]\n if (!CardClass) {\n throw new Error(`Invalid card type: ${cardType}`)\n }\n\n // if it isn't mobile get the size from the row\n if (!viewportHelper.is.mobile) {\n component.details.cardSize = row_size\n }\n // it it's \"touch\", disable the card display effect\n if (!viewportHelper.is.desktop && !viewportHelper.is.retina) {\n component.details.animated = false\n }\n\n const card = new CardClass(component.details)\n this.eventsArray = this.eventsArray.concat(card.bindEvents())\n return card.render()\n }\n\n bindEvents() {\n const signal = this.controller.signal\n this.eventsArray.forEach(e => {\n const element = document.querySelector(e.id)\n if (element) {\n element.addEventListener(e.eventType, e.cb, { signal })\n }\n })\n }\n\n disconnectedCallback() {\n this.controller.abort()\n }\n}\n\ncustomElements.get('nb-content-composer') ||\n customElements.define('nb-content-composer', ContentComposer)\n\nexport default ContentComposer\n"],"names":["createProps","attributes","data","find","attribute","nodeName","getData","props","filter","reduce","all","attr","nodeValue","isNil","JSON","parse","error","console","log","obj","removeEmptyValues","findText","key","value","text","includes","stringifyForAttribute","escapeHtml","stringify","map","replace","m","DOMParser","sanitizeString","toString","dispatchEvent","eventName","args","element","window","Error","event","CustomEvent","detail","bubbles","Event","document","createEvent","initEvent","BREAKPOINT_TABLET","EVENT_POPIN_OPEN","EVENT_POPIN_CLOSE","EVENT_POPIN_KEY_DOWN","EVENT_SWIPED_DOWN","trackingData","creative","renderCta","cssClass","cta","campaign","id","name","position","label","campaign_id","campaign_name","campaign_position","campaign_creative","renderLink","popin_id","link","color","size","seo_label","helper","is","innerWidth","vw","devicePixelRatio","mobile","mobile_tablet","tablet","desktop","retina","lt","ref","getImage","background_retina","background_desktop","background_mobile","viewportHelper","Card","constructor","_props","_campaign","this","elementId","render","bindEvents","getProduct","sku","napi","catalog","trimSku","isBundled","productData","sales_multiple","salesMultiple","isSalesMultipleGreaterThanOne","isUnitQuantityEqualToOne","unitQuantity","isSalesMultipleEqualToOne","isUnitQuantityGreaterThanOne","selectPromotion","eventData","cta_name","event_raised_by","ecommerce","Object","keys","length","ecommerceData","promotion_id","promotion_name","creative_slot","creative_name","gtmDataObject","push","emitCustomEvent","customEvent","cancelable","composed","getMarketCode","dataLayer","padlNamespace","app","market","toLocaleLowerCase","COMMON_URL","ORGANIC_LOGO_IMG_EU","ORGANIC_LOGO_IMG_US","ORGANIC_LOGO_IMG_CA","ORGANIC_LOGO_IMG_BR","ORGANIC_LOGO_IMG_JP","ORGANIC_LOGO_IMG_BE","organicLogoImg","getOrganicLogo","getMaxIntensity","technologies","INTENSITY_MAX_OL","indexOf","getMergedProductCoffeeData","product","pageBuilderProductProps","pageBuilderProps","priceFormatter","currency","bundle_details","options","show_sleeve_price","isBundledResult","showCapsulePrice","price_per_capsule","final_price","bundled","type","price","Math","round","getFinalPrice","option","intensity","capsuleProperties","max_intensity","short","show_capsule_price","apiOverride","pageBuilderData","images","headline","description","api_override","image","icon","url","main","cardTypeToClass","video","auto_play","renderAutoPlayCardVideo","renderDefaultCardVideo","video_service","video_id","contrast","cardSize","animated","backgroundImage","createPopinID","renderPlayButton","renderCardDisplay","renderPlayer","renderTitle","renderDescription","video_mobile","display_ui_controls","cc_policy_language","POPIN_ID","onOpenPlayer","e","preventDefault","cleanedData","handlePromoClick","title","seed","stripedHeading","str","tmp","implementation","createHTMLDocument","body","innerHTML","textContent","RegExp","stripHTML","substr","hash","i","charCodeAt","makeHash","removePlayer","playerElement","querySelector","remove","boundOnButtonSelfVideoClick","targetElement","target","srcElement","srOnly","dataset","status","pause","classList","add","play","renderSelfVideoButton","addEventListener","eventType","cb","bind","renderPopin","popin","heading","image_alt","close","productImage","productImageAlt","cardSizeAtrb","background_color","productSku","getSkuQuickViewData","popinId","payload","CARD_ID","quickViewProps","getSkuQuickViewProp","quickViewElement","createElement","setAttribute","getElementById","appendChild","getCapsuleFeatures","acidity","bitterness","roast","roastLevel","skuData","sku_quick_view","async","priceFormat","getPriceFormatter","config","padl","namespace","mergedProductData","getMergedProductData","variant","labels","strikethrough_price","additional_message","additional_message_icon","additional_message_link","contact_cta","internationalId","longSku","unit_quantity","category_name","rangeData","label_range","rawPrice","variation","image_alt_text","highlighted","dataTransformObjectProductType","getMergedProductMachineData","ratingsAndReviews","ratings","colors","activeSku","max_colors","show_ratings","minimum_rating","getMergedProductGiftCardData","_","default_image","footer","intensity_label","a11y_intensity_max","cup_sizes","items","cupSizesDetails","aromatic_profile","capsuleProductAromatics","pdpURLs","levels","pricing","add_to_cart","categoryName","hidePrice","view_details_label","rendererName","showSleeve","result","characters","charAt","floor","random","makeId","backgroundColorStyle","COLUMNS_TYPES","swipeEvents","stopEl","nwcSwipeEvents","getAttribute","el","undefined","contains","scrollTopArray","scrollLeftArray","scrollTop","scrollLeft","parentNode","memorizeStartElScrollPositions","startEl","timeDown","Date","now","touches","clientX","clientY","xDiff","yDiff","xDown","yDown","xUp","yUp","defaultVertical","innerHeight","defaultHorizontal","swipeThresholdVertical","getNearestAttribute","swipeThresholdHorizontal","swipeTimeout","timeDiff","changedTouches","abs","checkScrollCondition","dir","touchType","xStart","xEnd","yStart","yEnd","direction","isScrollable","scrollHeight","clientHeight","scrollWidth","clientWidth","attributeName","defaultValue","documentElement","attributeValue","String","parseInt","recursiveSwitchAriaHidden","elem","componentOpenState","parent","getElementsByTagName","brothers","children","brother","removeAttribute","Overlay","overlay","setTimeout","getElementsByClassName","STATE_OPEN","SCROLL_LOCK","Popin","HTMLElement","ariaModal","isVideo","boundOpen","open","boundClose","boundEscapeClose","escapeClose","boundFocus","focus","boundFocusin","focusin","connectedCallback","style","display","content","slot","attributeChangedCallback","oldValue","newValue","observedAttributes","disconnectedCallback","hasEvent","unbindEvent","subheading","bgcolor","label_close","heading_class","bindEvent","isOpen","checkIsVideo","renderFooter","focusable","querySelectorAll","firstFocusable","lastFocusable","lastFocused","setFirstAndLastFocusable","buttonElement","parseBool","tempEl","tagName","addLock","removeLock","closest","switchAriaModal","readEvent","openingSource","activeElement","Promise","resolve","cancelBubble","stopPropagation","removeEventListener","openVideoPopin","loop","swipeDown","swipeOverlayTogglePlayPause","boundSwipeDown","swipeOverlay","boundSwipeOverlayTogglePlayPause","customElements","get","define","ContentComposer","controller","AbortController","eventsArray","copywriting","header","layout","padding_top","padding_bottom","card_background_color","removeMarginTop","is_visible","padding_top_no_header","styleCardBackgroundColor","renderHeader","renderSubcomponents","components","layout_type","gap","types","typeIndex","component","renderSubComponent","join","row_size","cardType","entries","CardClass","details","card","concat","signal","forEach","abort"],"mappings":"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"}