{"version":3,"file":"index.es.min.js","sources":["../../../packages/helpers/src/props.helpers.js","../../../packages/helpers/src/viewport.helpers.ts","../../../packages/helpers/src/utils.ts","../../../packages/page-builder-sections/src/pdp-detailed-description/subcomponents/list/list.js","../../../packages/page-builder-sections/src/pdp-detailed-description/subcomponents/detailed-description/detailed-description.js","../../../packages/helpers/src/dataLayer.js","../../../services/pdp-data/src/prod/index.js","../../../packages/helpers/src/cremaDataHelper.js","../../../packages/helpers/src/PDPservices.js","../../../packages/helpers/src/notesIcons.js","../../../packages/helpers/src/cupSizeIcons.js","../../../packages/page-builder-sections/src/pdp-detailed-description/pdp-detailed-description.js","../../../packages/helpers/src/catalog.js","../../../packages/helpers/src/render.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","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","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        '&': '&amp;',\n        '<': '&lt;',\n        '>': '&gt;',\n        '\"': '&quot;',\n        \"'\": '&#039;'\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, '&quot;').replace(/'/g, '&apos;')\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","import createProps from '@kissui/helpers/src/props.helpers'\n\nclass List extends HTMLElement {\n    constructor() {\n        super()\n    }\n\n    connectedCallback() {\n        this.props = createProps(this.attributes)\n\n        this.classes = this.createClasses()\n        this.render()\n    }\n\n    createClasses() {\n        const baseClass = 'nb-list'\n        return {\n            base: baseClass,\n            heading: `${baseClass}__heading t-sm-700-sl`,\n            items: `${baseClass}__items`,\n            item: {\n                base: `${baseClass}__item`,\n                single: `${baseClass}__item--single`,\n                icon: `${baseClass}__item-icon`,\n                label: `${baseClass}__item-label t-2xs-500-sl`\n            }\n        }\n    }\n\n    render() {\n        const { heading = '' } = this.props\n\n        this.innerHTML = `\n            <div class=\"${this.classes.base}\">\n                <div class=\"${this.classes.heading}\">${heading}</div>\n                ${this.renderItems()}\n            </div>\n        `\n    }\n\n    renderItems() {\n        const { items = [] } = this.props\n        const isSingle = items.length === 1\n\n        if (isSingle) {\n            const first = items.find(Boolean)\n            return this.renderItem(first, isSingle)\n        }\n\n        const renderedItems = items.reduce(\n            (output, item) => `${output}${this.renderItem(item)}`,\n            ''\n        )\n\n        return `<div class=\"${this.classes.items}\">${renderedItems}</div>`\n    }\n\n    renderItem({ icon, label, size }, single = false) {\n        const modifier = single ? this.classes.item.single : ''\n\n        return `\n            <div class=\"${this.classes.item.base} ${modifier}\">\n                <div class=\"${this.classes.item.icon}\">\n                    <nb-icon icon=\"${icon}\"></nb-icon>\n                </div>\n                <div class=\"${this.classes.item.label}\">\n                    ${label}\n                    ${size ? `<br>${size}` : ''}\n                </div>\n            </div>\n        `\n    }\n}\n\ncustomElements.get('nb-list') || customElements.define('nb-list', List)\n\nexport default List\n","import createProps from '@kissui/helpers/src/props.helpers.js'\nimport viewportHelper from '@kissui/helpers/src/viewport.helpers'\nimport { stringifyForAttribute } from '@kissui/helpers/src/utils'\nimport '../list'\nclass DetailedDescription extends HTMLElement {\n    connectedCallback() {\n        this.props = createProps(this.attributes)\n        this.render()\n    }\n\n    render() {\n        const { campaign, layout, copywriting } = this.props\n        const { levels = [] } = copywriting\n\n        const { padding_top, padding_bottom, background_color = 'white_1000' } = layout\n\n        const levelsAvailable = levels.length && levels.every(({ value }) => value !== 0)\n\n        this.innerHTML = `\n            <nb-container\n                background_color=\"${background_color}\"\n                campaign_id=\"${campaign.id}\"\n                campaign_name=\"${campaign.name}\"\n                campaign_creative=\"${campaign.creative}\"\n                campaign_position=\"${campaign.position}\"\n                classname=\"${padding_top} ${padding_bottom}\"\n                contrast=\"light\">\n\n                <div class=\"cb-header\">\n                    ${this.renderHeader()}\n                    ${levelsAvailable ? this.renderDescription() : ''}\n                </div>\n                ${\n                    levelsAvailable\n                        ? this.setPropertiesList()\n                        : `<div class=\"cb-desc cb-no-capsule-prop\">\n                            ${this.renderDescription()}\n                            ${this.setPropertiesList()}\n                        </div>`\n                }\n            </nb-container>\n      `\n    }\n\n    setPropertiesList() {\n        const { sizes, notes } = this.props.copywriting\n\n        return `<div class=\"cb-cols\">\n                <div class=\"cb-col caption\">\n                    ${this.renderRoastText()}\n                    ${this.renderList(sizes)}\n                    ${this.renderList(notes)}\n                </div>\n                <div class=\"cb-col\">\n                    ${this.renderLevels()}\n                    ${this.renderDetails()}\n                </div>\n            </div>`\n    }\n\n    transformRoastLevelToString() {\n        const { roast, levels_roast } = this.props.copywriting\n\n        if (roast.description < levels_roast.label_light_property) {\n            return levels_roast.label_light\n        } else if (roast.description < levels_roast.label_medium_property) {\n            return levels_roast.label_medium\n        } else if (roast.description < levels_roast.label_dark_property) {\n            return levels_roast.label_dark\n        } else {\n            return levels_roast.label_light\n        }\n    }\n\n    renderHeader() {\n        const { header_title } = this.props.copywriting\n        if (!header_title) {\n            return ''\n        }\n\n        return `<h2 class=\"h-2xl-700\">${header_title}</h2>`\n    }\n\n    renderDescription() {\n        const { description } = this.props.copywriting\n        if (!description) {\n            return ''\n        }\n\n        return `<div class=\"description wysiwyg ${\n            viewportHelper.is.mobile ? 't-sm-400' : 't-md-400'\n        }\">${description}</div>`\n    }\n\n    renderRoastText() {\n        const { roast = {} } = this.props.copywriting\n        const { heading, description } = roast\n        if (!heading || !description) {\n            return ''\n        }\n\n        return `\n            <div class=\"cb-table\">\n                <div class=\"cb-row\">\n                    <p class=\"t-xs-700-sl\">${heading}</p>\n                    <div class=\"cb-cell is-text\">\n                        <nb-icon icon=\"24/coffeenote/roasted\"></nb-icon> ${this.transformRoastLevelToString(\n                            description\n                        )}\n                    </div>\n                </div>\n            </div>\n        `\n    }\n\n    renderList(list) {\n        if (!list) {\n            return ''\n        }\n\n        return `<div class=\"cb-cell\">\n                    <nb-list data='${stringifyForAttribute(list)}'></nb-list>\n                </div>`\n    }\n\n    renderLevels() {\n        const { levels } = this.props.copywriting\n\n        if (!levels?.length) {\n            return ''\n        }\n        const renderedLevels = levels.reduce(\n            (output, level) => `${output}${this.renderLevel(level)}`,\n            ''\n        )\n        if (!renderedLevels) {\n            return ''\n        }\n        return `<div class=\"cb-table\">${renderedLevels}</div>`\n    }\n\n    renderLevel({ label, value, information }) {\n        const { a11y_level_of } = this.props.copywriting\n        if (!value) {\n            return ''\n        }\n        return `\n            <div class=\"cb-row\">\n                <p class=\"t-xs-700-sl\">${label}</p>\n                <div class=\"cb-cell\">\n                    <nb-level value=\"${value}\" a11y_of=\"${a11y_level_of}\"></nb-level>\n                </div>\n                <nb-tooltip\n                    content=\"${information}\"\n                    position=\"top\"\n                    alignment=\"${viewportHelper.is.mobile ? 'right' : 'center'}\">\n                </nb-tooltip>\n            </div>\n        `\n    }\n\n    renderDetails() {\n        const { details = {} } = this.props.copywriting\n        if (!details.heading || !details.text) {\n            return ''\n        }\n        const data = stringifyForAttribute({\n            ...details,\n            classes: { title: 't-sm-700-sl' }\n        })\n        return `<nb-collapse data='${data}'></nb-collapse>`\n    }\n}\n\ncustomElements.get('nb-detailed-description') ||\n    customElements.define('nb-detailed-description', DetailedDescription)\n\nexport default DetailedDescription\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 { getDataLayer } from '@kissui/helpers/src/dataLayer'\n\nexport async function setPDPDataProvider() {\n    window.getPDPData = window.getPDPData || getPDPData\n}\n\nexport async function getPDPData() {\n    return await window.pdpData\n}\n\nexport async function market() {\n    return napi.market().read() // eslint-disable-line\n}\n\nexport function getCurrency() {\n    return getDataLayer().currency\n}\n\nexport async function getPriceFormatter() {\n    return napi.priceFormat() // eslint-disable-line\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 {\n    getVertuoNext,\n    getOrganicEu,\n    getLabels,\n    getProductHighlight,\n    getFairTrade,\n    getRainforest,\n    getSustainability,\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 getMergedPDPData(pdpData) {\n    if (!pdpData) {\n        console.error('PDP data is not available')\n        return\n    }\n    const { configuration: { eCommerceData: { categories, product } = {} } = {} } = pdpData\n\n    if (product.ranges && product.ranges.length > 0) {\n        const rangeId = product.ranges[0]\n        const category = categories.find(category => category.id === rangeId)\n        if (category != null) {\n            product.rangeData = category\n        }\n    }\n\n    addLabels(categories, product)\n    addFairTrade(categories, product)\n    addProductHighlight(categories, product)\n    addVertuoNext(categories, product)\n    addOrganicEu(categories, product)\n    addRainforest(categories, product)\n    addSustainability(categories, product)\n    addArabica(categories, product)\n\n    return pdpData\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 {product} product\n */\nfunction addLabels(categories, product) {\n    const labels = getLabels(categories).map(label => label.description)\n    product.labels = labels\n}\n\nfunction addVertuoNext(categories, product) {\n    const onlyVertuoNext = getVertuoNext(categories)\n    if (!onlyVertuoNext) {\n        return\n    }\n    product.onlyVertuoNext = true\n}\n\nfunction addOrganicEu(categories, product) {\n    if (getOrganicEu(categories)) {\n        product.organicEu = true\n    }\n}\n\nfunction addRainforest(categories, product) {\n    if (getRainforest(categories)) {\n        product.rainforest = true\n    }\n}\n\nfunction addSustainability(categories, product) {\n    if (getSustainability(categories)) {\n        product.sustainability = true\n    }\n}\nfunction addArabica(categories, product) {\n    if (getArabica(categories)) {\n        product.arabica = true\n    }\n}\n\n/**\n * adds highlighted property to products containing the product highlight category assigned to it\n * product highlight is a category recognized by ID\n * to apply a the product highlight on a given product, the product highlight productGroup has to contain the product\n * this function has to clean the productGroups as well by removing the product highlight one\n * @param {category[]} categories\n * @param {product} product\n */\nfunction addProductHighlight(categories, product) {\n    const productHighlight = getProductHighlight(categories)\n    if (!productHighlight) {\n        return\n    }\n    product.highlighted = true\n}\n/**\n * adds fairTrade property to products containing the faire trade category assigned to it\n * Fair trade is a category recognized by ID\n * to apply a the fair trade on a given product, the faire trade productGroup has to contain the product\n * this function has to clean the productGroups as well by removing the fair trade one\n * @param {category[]} categories\n * @param {productGroup[]} productGroups\n * @param {product[]} products\n */\nfunction addFairTrade(categories, product) {\n    const fairTrade = getFairTrade(categories)\n    if (!fairTrade) {\n        return\n    }\n    product.fairTrade = fairTrade.name\n}\n","export const NOTES_ICON_DEFAULT = '24/coffee/coffee-aroma'\n\n/**\n * Normalize aromatic note\n * E.g. veryRoasted become roasted\n * For notes with hyphen, it's not necessary\n * E.g. nutty-and-balanced will be considered has nutty\n * @param {string} note\n * @returns {string}\n */\nconst harmonizeNoteName = _note => {\n    const sanityNote = _note.split('/')\n    let note = sanityNote.pop()\n    note = note.replace('capsule-aromatic-', '').replace('recipe-', '')\n\n    if (['peppery', 'spicy', 'peppery-note'].includes(note)) {\n        return '24/coffeenote/spicy'\n    } else if (['woody', 'wood', 'oak-wood', 'smoky-wood'].includes(note)) {\n        return '24/coffeenote/oak-wood'\n    } else if (\n        [\n            'sugar',\n            'brown-sugar-and-roasted-notes',\n            'candy-sweet',\n            'delicate-toasted-biscuit-notes'\n        ].includes(note)\n    ) {\n        return '24/coffeenote/sugar'\n    } else if (['sweet'].includes(note)) {\n        return '24/coffeenote/sweet'\n    } else if (['berry'].includes(note)) {\n        return '24/coffeenote/berry'\n    } else if (['baked-apple', 'apple', 'baked-apple-flavors'].includes(note)) {\n        return '24/coffeenote/baked-apple'\n    } else if (['bergamot'].includes(note)) {\n        return '24/coffeenote/bergamot'\n    } else if (['bitterness', 'bitter'].includes(note)) {\n        return '24/coffeenote/bitterness'\n    } else if (['blueberry'].includes(note)) {\n        return '24/coffeenote/blueberry'\n    } else if (['bread-aroma', 'bread'].includes(note)) {\n        return '24/coffeenote/bread-aroma'\n    } else if (['candied-fruit'].includes(note)) {\n        return '24/coffeenote/candied-fruit'\n    } else if (['caramel'].includes(note)) {\n        return '24/coffeenote/caramel'\n    } else if (['cereal', 'cerealFruity', 'mild-cereal', 'sweetCereal'].includes(note)) {\n        return '24/coffeenote/cereal'\n    } else if (\n        [\n            'maltedCereal',\n            'malted',\n            'toasted-cereal',\n            'malty-faintly-green-notes',\n            'maltyToasted'\n        ].includes(note)\n    ) {\n        return '24/coffeenote/malted'\n    } else if (\n        ['roastedCereal', 'veryRoasted', 'roasted', 'longRoasted', 'roastedCocoa'].includes(note)\n    ) {\n        return '24/coffeenote/roasted'\n    } else if (\n        [\n            'hintOfFruity',\n            'fruityWiney',\n            'fruity',\n            'fruity-exotic',\n            'juicy-fruity',\n            'ripe-fruits'\n        ].includes(note)\n    ) {\n        return '24/coffeenote/fruity'\n    } else if (['citric', 'lemon', 'citrus'].includes(note)) {\n        return '24/coffeenote/citrus'\n    } else if (['cocoa', 'hintsOfBitterCocoaPowderAndCereals'].includes(note)) {\n        return '24/coffeenote/cocoa'\n    } else if (['chocolate', 'dark-chocolate', 'white-chocolate'].includes(note)) {\n        return '24/coffeenote/chocolate'\n    } else if (['cardamom'].includes(note)) {\n        return '24/coffeenote/cardamom'\n    } else if (['ginger', 'cocoaGinger'].includes(note)) {\n        return '24/coffeenote/ginger'\n    } else if (['ginseng'].includes(note)) {\n        return '24/coffeenote/ginseng'\n    } else if (['nutty', 'nut', 'hazelnut', 'hazelnut-aromas'].includes(note)) {\n        return '24/coffeenote/hazelnut'\n    } else if (['refreshing-mint', 'peppermint'].includes(note)) {\n        return '24/coffeenote/peppermint'\n    } else if (['almond', 'almonds'].includes(note)) {\n        return '24/coffeenote/almonds'\n    } else if (['balance', 'balanced', 'smooth'].includes(note)) {\n        return '24/coffeenote/balance'\n    } else if (['tropical', 'exotic'].includes(note)) {\n        return '24/coffeenote/tropical'\n    } else if (['coconut'].includes(note)) {\n        return '24/coffeenote/coconut'\n    } else if (['cocktail'].includes(note)) {\n        return '24/coffeenote/cocktail'\n    } else if (['biscuity', 'biscuit', 'reminiscent-shortbread-cookies'].includes(note)) {\n        return '24/coffeenote/biscuit'\n    } else if (\n        ['whiskey', 'Whisky', 'whisky', 'alcohol', 'whiskey-flavor', 'whisky-flavour'].includes(\n            note\n        )\n    ) {\n        return '24/coffeenote/alcohol'\n    } else if (['watermelon'].includes(note)) {\n        return '24/coffeenote/watermelon'\n    } else if (['RedFruit', 'redfruit', 'red-fruit', 'strawberry'].includes(note)) {\n        return '24/coffeenote/red-fruit'\n    } else if (\n        [\n            'flowery',\n            'flower',\n            'Floral',\n            'floral',\n            'floralJasmine',\n            'floralandWild',\n            'orange-blossom'\n        ].includes(note)\n    ) {\n        return '24/coffeenote/flowery'\n    } else if (['herbal', 'dry-vegetal'].includes(note)) {\n        return '24/coffeenote/herbal'\n    } else if (['honey'].includes(note)) {\n        return '24/coffeenote/honey'\n    } else if (['smooth-b2b'].includes(note)) {\n        return '24/coffeenote/roasted'\n    } else if (\n        ['sweetnotes-b2b', 'toffeenotes-b2b', 'caramellynotes-b2b', 'caramelized'].includes(note)\n    ) {\n        return '24/coffeenote/caramel'\n    } else if (\n        [\n            'rich-b2b',\n            'veryRoasted',\n            'intense',\n            'intense-selection',\n            'rich',\n            'intense-roasted',\n            'bold-roasted-notes'\n        ].includes(note)\n    ) {\n        return '24/coffeenote/intense-roasted'\n    } else if (['leather'].includes(note)) {\n        return '24/coffeenote/leather'\n    } else if (['powerful-intense', 'powerful'].includes(note)) {\n        return '24/coffeenote/powerful-intense'\n    } else if (['milky', 'milk', 'milk-selection'].includes(note)) {\n        return '24/coffeenote/milky'\n    } else if (['pumpkin', 'sweet-pumpkin'].includes(note)) {\n        return '24/coffeenote/pumpkin'\n    } else if (['vanilla', 'vanillaAlmonds', 'vanillaCardamom'].includes(note)) {\n        return '24/coffeenote/vanilla'\n    } else if (['chicory', 'vegetal'].includes(note)) {\n        return '24/coffeenote/vegetal'\n    } else if (['winey', 'wine'].includes(note)) {\n        return '24/coffeenote/winey'\n    } else if (['pecan-nut', 'pecan', 'praline-notes'].includes(note)) {\n        return '24/coffeenote/nut'\n    } else if (['maple-syrup', 'syrup'].includes(note)) {\n        return '24/coffeenote/syrup'\n    } else if (['amaretti'].includes(note)) {\n        return '24/coffeenote/amaretti'\n    } else if (['dry-fruits'].includes(note)) {\n        return '24/coffeenote/dry-fruits'\n    } else if (['peanut'].includes(note)) {\n        return '24/coffeenote/peanut'\n    } else if (['popcorn'].includes(note)) {\n        return '24/coffeenote/popcorn'\n    } else if (['sesame'].includes(note)) {\n        return '24/coffeenote/toasted-sesame'\n    }\n    return NOTES_ICON_DEFAULT\n}\n\nexport const getNoteIcon = note => {\n    return harmonizeNoteName(note)\n}\n","export const CUPSIZE_ICON_DEFAULT = '24/cupsize/cupsize-espresso-ol'\n\nconst cupSizeLookup = {\n    ristretto: '24/cupsize/cupsize-ristretto-ol',\n    espresso: '24/cupsize/cupsize-espresso-ol',\n    lungo: '24/cupsize/cupsize-lungo-ol',\n    'lungo-plus': '24/cupsize/cupsize-lungo-plus-ol',\n    'ristretto-vertuo': '24/cupsize/cupsize-ristretto-vl',\n    'espresso-vertuo': '24/cupsize/cupsize-espresso-vl',\n    'double-espresso-vertuo': '24/cupsize/cupsize-lungo-vl',\n    'lungo-vertuo': '24/cupsize/cupsize-lungo-vl',\n    'gran-lungo': '24/cupsize/cupsize-gran-lungo-vl',\n    coffee: '24/cupsize/cupsize-mug-small-vl',\n    'mug-medium': '24/cupsize/cupsize-mug-medium-vl',\n    'mug-large': '24/cupsize/cupsize-mug-large-vl',\n    'paper-cup-extra-small-alt': '24/cupsize/paper-cup-extra-small-alt',\n    'paper-cup-extra-small': '24/cupsize/paper-cup-extra-small',\n    'paper-cup-large-alt': '24/cupsize/paper-cup-large-alt',\n    'paper-cup-large': '24/cupsize/paper-cup-large',\n    'paper-cup-medium-alt': '24/cupsize/paper-cup-medium-alt',\n    'paper-cup-medium': '24/cupsize/paper-cup-medium',\n    'paper-cup-small-alt': '24/cupsize/paper-cup-small-alt',\n    'paper-cup-small': '24/cupsize/paper-cup-small',\n    xl: '24/accessory/travel-mug-vl',\n    'cold-brew': '24/coffee/cold-brew',\n    'carafe-vertuo': '24/cupsize/cupsize-carafe-vl',\n    alto: '24/cupsize/cupsize-alto-vl',\n    americano: '24/cupsize/cupsize-americano-ol',\n    icedrecipe: '24/recipe/iced-coffee',\n    'icedrecipe-vertuo': '24/recipe/iced-vl',\n    milk: '24/coffeenote/milky',\n    'cappuccino-and-latte-macchiato': '24/recipe/cappuccino-ol',\n    'double-cappuccino': '24/recipe/double-cappuccino-vl',\n    reverso: '24/recipe/reverso-vl',\n    'cortado-cappuccino': '24/recipe/cortado-ol',\n    'ristretto-b2b': '',\n    'espresso-b2b': '',\n    'lungo-b2b': '',\n    'icedRecipe-b2b': ''\n}\n\n/**\n * @function\n * @description Returns the icon for a given cup size, or a default icon.\n * @param {string} cupSize\n * @param {boolean} returnDefaultIcon If true, an icon will always be returned, else `''`\n * @returns {string}\n */\nexport const getCupSizeIcon = (cupSize, returnDefaultIcon = true) => {\n    const cupSizeStr = cupSize ? cupSize.split('/')?.pop() : ''\n\n    const cupSizeKey = cupSizeStr\n        .toLowerCase()\n        .replace('capsule-cupsize-', '')\n        .replace('machine-cupsize.', '') // This seems incorrect, but is the information we currenrtly have about this cup size\n\n    return cupSizeLookup[cupSizeKey] || (returnDefaultIcon ? CUPSIZE_ICON_DEFAULT : '')\n}\n\n/**\n * @function\n * @description Returns the type of icon for a given cupsize, so to distinguish between\n * coffees for recipes or normal coffees\n * @param {string} cupSize\n * @returns {'recipe' | 'coffee'}\n */\nexport const getCupType = cupSize => {\n    const cupSizeIcon = getCupSizeIcon(cupSize)\n    if (cupSizeIcon.includes('recipe')) return 'recipe'\n    if (cupSizeIcon.includes('cupsize')) return 'coffee'\n}\n","import { setPDPDataProvider } from '@kissui/pdp-data'\n\nimport createProps from '@kissui/helpers/src/props.helpers'\nimport { renderComponent } from '@kissui/helpers/src/render'\nimport { interpolate } from '@kissui/helpers/src/utils'\n\nimport { getMergedPDPData } from '@kissui/helpers/src/PDPservices'\nimport { getNoteIcon } from '@kissui/helpers/src/notesIcons'\nimport { getCupSizeIcon } from '@kissui/helpers/src/cupSizeIcons'\nimport { getProduct } from '@kissui/helpers/src/catalog'\nimport './subcomponents/detailed-description'\n\nclass PdpDetailedDescription extends HTMLElement {\n    constructor() {\n        super()\n        this.props = {}\n        this.pdpData = {}\n        this.product = null\n        this.categories = null\n        this.napiProduct = null\n    }\n\n    async mergePdpData() {\n        this.pdpData = await getMergedPDPData(await window.getPDPData())\n        this.product = this.pdpData.configuration.eCommerceData.product\n        this.categories = this.pdpData.configuration.eCommerceData.categories\n    }\n\n    async connectedCallback() {\n        this.props = createProps(this.attributes)\n\n        setPDPDataProvider()\n\n        await this.mergePdpData()\n        this.render()\n\n        try {\n            this.napiProduct = await getProduct(this.product.id)\n        } catch (e) {\n            console.log('PDP, error fetching product data SKU:', this.product.id, e)\n        }\n\n        if (this.napiProduct.capsuleProperties) {\n            // We have new data, re-render the component\n            this.render()\n        }\n    }\n\n    render() {\n        const product = this.product\n\n        const { campaign, copywriting, layout } = this.props\n        const { levels } = copywriting\n\n        const {\n            levels_roast,\n            levels_acidity_label,\n            levels_bitterness_label,\n            levels_roastiness_label,\n            levels_body_label,\n            levels_acidity_info,\n            levels_bitterness_info,\n            levels_roastiness_info,\n            levels_body_info,\n            level_list\n        } = levels\n\n        const detailedDescData = { levels: level_list }\n\n        const notesItems = product?.flavors?.map(noteID => {\n            const noteKey = noteID.split('/')?.pop()\n            const { name = '' } = this.getCategory(noteID) || {}\n            return { icon: getNoteIcon(noteKey), label: name }\n        })\n        if (notesItems && notesItems.length > 0) {\n            detailedDescData.notes = { heading: copywriting.notes_title, items: notesItems }\n        }\n\n        const sizeItems = product?.cupSizes?.map(cupSizeID => {\n            const { name = '', capacityLabel = '' } = this.getCategory(cupSizeID) || {}\n            return { icon: getCupSizeIcon(cupSizeID), label: name, size: capacityLabel }\n        })\n        if (sizeItems && sizeItems.length > 0) {\n            detailedDescData.sizes = { heading: copywriting.sizes_title, items: sizeItems }\n        }\n\n        detailedDescData.details = {\n            heading: copywriting.details_heading,\n            text: this.renderDetailedDescIngredient(product.ingredients)\n        }\n\n        if (copywriting.description !== '') {\n            detailedDescData.description = interpolate(\n                copywriting.description,\n                {\n                    roasting: product.roastingDescription,\n                    origin: product.originDescription,\n                    aromatic: product.aromaticProfileDescription\n                },\n                '{',\n                '}'\n            )\n        } else {\n            detailedDescData.description = `<p>${product.originDescription}</p><p>${product.aromaticProfileDescription}</p>`\n        }\n\n        if (this.napiProduct?.capsuleProperties) {\n            // If data is already available from napi then use it instead\n            detailedDescData.levels = detailedDescData.levels || []\n\n            if (this.napiProduct.capsuleProperties.roastLevel != null && levels_roastiness_label) {\n                // we are Finding the index of the existing roastiness level item in the detailedDescData.levels array\n                const roastinessItemIndex = detailedDescData.levels.findIndex(\n                    item => item.label === levels_roastiness_label\n                )\n\n                // Checking if roastiness is separated and the item exists in the array\n                if (levels_roast && levels_roast.is_separated && roastinessItemIndex !== -1) {\n                    // If roastiness is separated and the item exists, update the roast data\n                    detailedDescData.roast = {\n                        heading: levels_roast.label,\n                        description: this.napiProduct.capsuleProperties.roastLevel\n                    }\n                } else if (roastinessItemIndex !== -1) {\n                    // If the roastinessItem exists but roastiness is not separated we update the existing item's value and information\n                    detailedDescData.levels[roastinessItemIndex].value =\n                        this.napiProduct.capsuleProperties.roastLevel\n                    detailedDescData.levels[roastinessItemIndex].information =\n                        levels_roastiness_info\n                } else {\n                    // If the item doesn't exist, add a new roastiness level object to the array\n                    detailedDescData.levels.unshift({\n                        label: levels_roastiness_label,\n                        value: this.napiProduct.capsuleProperties.roastLevel,\n                        information: levels_roastiness_info\n                    })\n                }\n            }\n\n            if (this.napiProduct.capsuleProperties.acidity != null && levels_acidity_label) {\n                const acidityItem = detailedDescData.levels.find(\n                    item => item.label === levels_acidity_label\n                )\n                if (acidityItem) {\n                    acidityItem.value = this.napiProduct.capsuleProperties.acidity\n                    acidityItem.information = levels_acidity_label\n                } else {\n                    detailedDescData.levels.unshift({\n                        label: levels_acidity_label,\n                        value: this.napiProduct.capsuleProperties.acidity,\n                        information: levels_acidity_info\n                    })\n                }\n            }\n\n            if (this.napiProduct.capsuleProperties.bitterness != null && levels_bitterness_label) {\n                const bitternessItem = detailedDescData.levels.find(\n                    item => item.label === levels_bitterness_label\n                )\n                if (bitternessItem) {\n                    bitternessItem.value = this.napiProduct.capsuleProperties.bitterness\n                    bitternessItem.information = levels_bitterness_label\n                } else {\n                    detailedDescData.levels.unshift({\n                        label: levels_bitterness_label,\n                        value: this.napiProduct.capsuleProperties.bitterness,\n                        information: levels_bitterness_info\n                    })\n                }\n            }\n\n            if (this.napiProduct.capsuleProperties.body > 0 && levels_body_label) {\n                // Body data was supplied by NAPI and needs to override Page Builder data\n                // so check if it already exists and remove it\n                const bodyItem = detailedDescData.levels.find(\n                    item => item.label === levels_body_label\n                )\n                if (bodyItem) {\n                    bodyItem.value = this.napiProduct.capsuleProperties.body\n                    bodyItem.information = levels_body_info\n                } else {\n                    detailedDescData.levels.unshift({\n                        label: levels_body_label,\n                        value: this.napiProduct.capsuleProperties.body,\n                        information: levels_body_info\n                    })\n                }\n            }\n        }\n\n        const dataToRender = {\n            campaign,\n            layout,\n            copywriting: {\n                ...copywriting,\n                ...detailedDescData,\n                levels_roast\n            }\n        }\n        renderComponent(this, dataToRender, 'nb-detailed-description', 0)\n    }\n\n    renderDetailedDescIngredient(ingredients) {\n        if (!ingredients || !ingredients.length) {\n            return ''\n        }\n\n        let hasParagraphOpened = false\n        return (\n            ingredients.reduce((acc, ingredient) => {\n                if (ingredient.type.code === 'TITLE') {\n                    hasParagraphOpened = true\n                    return acc + `<p><strong>${ingredient.text}</strong>`\n                } else if (ingredient.type.code === 'DESCRIPTION') {\n                    const content = `${!hasParagraphOpened ? '<p>' : '<br>'}${ingredient.text}</p>`\n                    hasParagraphOpened = false\n                    return acc + content\n                }\n            }, '') + (hasParagraphOpened ? '</p>' : '')\n        )\n    }\n\n    getCategory(id) {\n        return this.categories.find(cat => cat.id === id)\n    }\n}\n\ncustomElements.get('nb-pdp-detailed-description') ||\n    customElements.define('nb-pdp-detailed-description', PdpDetailedDescription)\n\nexport default PdpDetailedDescription\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 function renderComponent(container, data, tagName, order) {\n    const comp = document.createElement(tagName)\n    comp.setAttribute('data', JSON.stringify(data))\n    appendComponentInOrder(container, comp, tagName, order)\n}\n\nexport function appendComponentInOrder(\n    container,\n    component,\n    tagName,\n    order,\n    removeExisting = true\n) {\n    if (removeExisting) {\n        const existing = container.getElementsByTagName(tagName)\n        if (existing.length > 0 && existing[0].parentElement) {\n            // IE doesn't support element.remove() I don't know if it's transpiled or polyfill\n            existing[0].parentElement.removeChild(existing[0])\n        }\n    }\n    if (container.children.length >= order + 1) {\n        return container.insertBefore(component, container.children[order])\n    } else {\n        return container.appendChild(component)\n    }\n}\n"],"names":["createProps","attributes","data","find","attribute","nodeName","getData","props","filter","reduce","all","attr","nodeValue","isNil","JSON","parse","error","console","log","obj","helper","is","innerWidth","vw","devicePixelRatio","window","mobile","BREAKPOINT_M","mobile_tablet","BREAKPOINT_TABLET","tablet","desktop","retina","lt","ref","stringifyForAttribute","escapeHtml","stringify","text","map","replace","m","DOMParser","List","HTMLElement","constructor","connectedCallback","this","classes","createClasses","render","baseClass","base","heading","items","item","single","icon","label","innerHTML","renderItems","isSingle","length","first","Boolean","renderItem","renderedItems","output","size","modifier","customElements","get","define","DetailedDescription","campaign","layout","copywriting","levels","padding_top","padding_bottom","background_color","levelsAvailable","every","value","id","name","creative","position","renderHeader","renderDescription","setPropertiesList","sizes","notes","renderRoastText","renderList","renderLevels","renderDetails","transformRoastLevelToString","roast","levels_roast","description","label_light_property","label_light","label_medium_property","label_medium","label_dark_property","label_dark","header_title","viewportHelper","list","renderedLevels","level","renderLevel","information","a11y_level_of","details","title","getMarketCode","dataLayer","padlNamespace","app","market","toLocaleLowerCase","async","getPDPData","pdpData","LABEL_CATEGORY_NAME","LABEL_CATEGORY_NAME_MACHINE","FAIR_TRADE_CATEGORY_NAME","VERTUO_NEXT_CATEGORY_NAME","ORGANIC_EU_CATEGORY_NAME","RAINFOREST_CATEGORY_NAME","SUSTAINABILITY_CATEGORY_NAME","ARABICA_CATEGORY_NAME","PRODUCT_HIGHLIGHT_CATEGORY_NAME","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","getVertuoNext","categories","category","getCategoryRegEx","test","isVertuoNext","getOrganicEu","isOrganicEu","getRainforest","isRainforest","getSustainability","isSustainability","getArabica","isArabica","getLabels","isLabel","getProductHighlight","isProductHighlight","getFairTrade","isFairTrade","categoryIdTail","RegExp","getMergedPDPData","configuration","eCommerceData","product","ranges","rangeId","rangeData","addLabels","labels","fairTrade","addFairTrade","highlighted","addProductHighlight","onlyVertuoNext","addVertuoNext","organicEu","addOrganicEu","rainforest","addRainforest","sustainability","addSustainability","arabica","addArabica","organicLogoImg","getOrganicLogo","cupSizeLookup","ristretto","espresso","lungo","coffee","xl","alto","americano","icedrecipe","milk","reverso","getCupSizeIcon","cupSize","returnDefaultIcon","cupSizeKey","split","pop","toLowerCase","PdpDetailedDescription","super","napiProduct","mergePdpData","setPDPDataProvider","sku","napi","catalog","getProduct","trimSku","e","capsuleProperties","levels_acidity_label","levels_bitterness_label","levels_roastiness_label","levels_body_label","levels_acidity_info","levels_bitterness_info","levels_roastiness_info","levels_body_info","level_list","detailedDescData","notesItems","flavors","noteID","noteKey","getCategory","note","_note","includes","NOTES_ICON_DEFAULT","harmonizeNoteName","notes_title","sizeItems","cupSizes","cupSizeID","capacityLabel","sizes_title","details_heading","renderDetailedDescIngredient","ingredients","txt","vars","stChr","enChr","curIdx","stIdx","indexOf","enIdx","hashId","substring","substr","interpolate","roasting","roastingDescription","origin","originDescription","aromatic","aromaticProfileDescription","roastLevel","roastinessItemIndex","findIndex","is_separated","unshift","acidity","acidityItem","bitterness","bitternessItem","body","bodyItem","container","tagName","order","comp","document","createElement","setAttribute","component","removeExisting","existing","getElementsByTagName","parentElement","removeChild","children","insertBefore","appendChild","appendComponentInOrder","renderComponent","hasParagraphOpened","acc","ingredient","type","code","content","cat"],"mappings":"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"}