{"version":3,"file":"frame.js","names":[],"sources":["../resources/javascript/features/auth/account-link.js","../resources/javascript/features/bundle/lazy.js","../resources/javascript/features/quick-add/lazy.js","../resources/javascript/frame.js"],"sourcesContent":["// @ts-check\n\n// The header is cacheable, so signed in state is reflected client side once the\n// server has reported it. Until then the link keeps its neutral server rendered\n// label, rather than asserting a state we do not know.\n\nimport { authStateChanged } from './constants.js';\nimport { isAuthenticatedSync, isAuthenticationKnown } from './session.js';\n\n/**\n * Reflect signed in state on the header account link.\n *\n * @returns {void}\n */\nconst render = () => {\n    const link = document.querySelector('[data-account-link]');\n    if (!(link instanceof HTMLElement) || !isAuthenticationKnown()) {\n        return;\n    }\n\n    const signedIn = isAuthenticatedSync();\n\n    // Labels come from the template, so they stay translated.\n    const label = signedIn\n        ? link.dataset.accountLabelSignedIn\n        : link.dataset.accountLabelSignedOut;\n\n    link.classList.toggle('header__account--signed-in', signedIn);\n\n    if (label) {\n        link.setAttribute('aria-label', label);\n    }\n};\n\n/**\n * @returns {void}\n */\nexport const initAccountLink = () => {\n    render();\n    document.addEventListener(authStateChanged, render);\n};\n","// @ts-check\n\nimport { once } from 'lodash-es';\nimport { whenIdle } from '../../util/idle';\nimport { onDOMContentLoaded } from '../../util/loaded';\n\nexport const loadBundle = once(async () => await import('./index'));\n\n/**\n * Initialise the \"Create your bundle\" buttons.\n *\n * Any element with `data-bundle-overlay-url` opens the bundle overlay for that\n * companion product. Add and Edit use the same attribute: the URL already\n * carries any existing selection, so the server decides which state to render.\n *\n * Loaded lazily when the browser is idle if a button is on the page, and\n * immediately on first click if not already loaded.\n */\nexport const initBundleButtons = async () => {\n    document.addEventListener('click', async e => {\n        if (!(e.target instanceof Element)) {\n            return;\n        }\n\n        const button = e.target.closest('[data-bundle-overlay-url]');\n        if (\n            !(button instanceof HTMLElement) ||\n            !button.dataset.bundleOverlayUrl\n        ) {\n            return;\n        }\n\n        e.preventDefault();\n\n        const { loadBundleOverlay } = await loadBundle();\n        await loadBundleOverlay(button.dataset.bundleOverlayUrl);\n    });\n\n    onDOMContentLoaded(() => {\n        whenIdle(() => {\n            if (document.querySelector('[data-bundle-overlay-url]')) {\n                whenIdle(async () => {\n                    await loadBundle();\n                }, 3000);\n            }\n        });\n    });\n};\n","// @ts-check\n\nimport { once } from 'lodash-es';\nimport { whenIdle } from '../../util/idle';\nimport { onDOMContentLoaded } from '../../util/loaded';\nimport { trackD3REvent } from '../../util/tracking';\n\nexport const loadQuickAdd = once(async () => await import('./index'));\n\n/**\n * Open the quick add overlay for a product.\n *\n * @param {object} data\n */\nexport const quickAdd = async data => {\n    const { quickAdd } = await loadQuickAdd();\n    return await quickAdd(data);\n};\n\n/**\n * Initialise quick add buttons.\n *\n * Any element with the `data-quick-add` attribute will be treated as a quick\n * add button. The value of the attribute should be a JSON encoded object. The\n * object must contain either a `productUrlname` or `key` property. It may\n * optionally contain an `options` property containing product options and the\n * quantity to add to the basket.\n *\n * See the PHP class method App\\Products\\Option\\OptionSet::getQuickAddButton for\n * example button HTML.\n *\n * Quick add functionality is lazy-loaded when the browser is idle, if a quick\n * add button is present on the page at the time initQuickAddButtons is called.\n * It is also lazy-loaded immediately after a quick add button is clicked, if\n * not already loaded.\n */\nexport const initQuickAddButtons = async () => {\n    document.addEventListener('click', async e => {\n        if (!(e.target instanceof Element)) {\n            return false;\n        }\n\n        const button = e.target.closest('[data-quick-add]');\n        if (!(button instanceof HTMLElement) || !button.dataset.quickAdd) {\n            return;\n        }\n\n        e.preventDefault();\n\n        // TODO should we support a loading indicator?\n\n        const data = JSON.parse(button.dataset.quickAdd);\n\n        // get the search params from the parent link, so colour/size selected\n        // on the listing card carry through to the quick-add overlay. Don't let\n        // link params override the button's own authoritative quick-add data.\n        const reservedKeys = ['key', 'productUrlname', 'suppressOverlay'];\n        const search = button.closest('a')?.search;\n        if (search) {\n            const params = new URLSearchParams(search);\n            for (const [paramName, paramValue] of params) {\n                if (!reservedKeys.includes(paramName)) {\n                    data[paramName] = paramValue;\n                }\n            }\n        }\n        // get the context of where the quick add button was clicked\n        let category = button.closest('.product-comparison-table__primary-cta')\n            ? 'quick-add/comparison'\n            : 'quick-add';\n\n        trackD3REvent({\n            category: category,\n            action: 'Added to basket',\n            label: 'User clicked quick add button',\n            value: { ...data, pathname: window.location.pathname },\n        });\n\n        if (data.suppressOverlay) {\n            button.disabled = true;\n            button.classList.add('button--added');\n            try {\n                await quickAdd(data);\n                setTimeout(() => {\n                    button.disabled = false;\n                    button.classList.remove('button--added');\n                }, 2000);\n            } catch {\n                button.disabled = false;\n                button.classList.remove('button--added');\n            }\n        } else {\n            await quickAdd(data);\n        }\n    });\n\n    // If any quick add buttons are currently on the page, lazy-load quick add\n    // functionality when the browser is idle.\n    onDOMContentLoaded(() => {\n        whenIdle(() => {\n            if (document.querySelector('[data-quick-add]')) {\n                whenIdle(async () => {\n                    await loadQuickAdd();\n                }, 3000);\n            }\n        });\n    });\n};\n","// @ts-check\n\nimport './features/dixa/globals';\nimport { initAccountLink } from './features/auth/account-link';\nimport { initBundleButtons } from './features/bundle/lazy';\nimport { initQuickAddButtons } from './features/quick-add/lazy';\nimport { initShortlistButtons } from './features/shortlist/lazy';\n\ninitAccountLink();\n\n// Guarded so shortlist setup cannot take quick add down with it.\ntry {\n    initShortlistButtons();\n} catch (e) {\n    console.error('Failed to initialise shortlist buttons', e);\n}\n\ninitQuickAddButtons();\ninitBundleButtons();\n"],"mappings":"mfAcA,MAAM,MAAe,CACjB,IAAM,EAAO,SAAS,cAAc,qBAAqB,EACzD,GAAI,EAAE,aAAgB,cAAgB,CAAC,EAAsB,EACzD,OAGJ,IAAM,EAAW,EAAoB,EAG/B,EAAQ,EACR,EAAK,QAAQ,qBACb,EAAK,QAAQ,sBAEnB,EAAK,UAAU,OAAO,6BAA8B,CAAQ,EAExD,GACA,EAAK,aAAa,aAAc,CAAK,CAE7C,EAKa,MAAwB,CACjC,EAAO,EACP,SAAS,iBAAiB,EAAkB,CAAM,CACtD,EClCa,EAAa,EAAK,SAAY,MAAM,OAAO,6BAAU,EAYrD,EAAoB,SAAY,CACzC,SAAS,iBAAiB,QAAS,KAAM,IAAK,CAC1C,GAAI,EAAE,EAAE,kBAAkB,SACtB,OAGJ,IAAM,EAAS,EAAE,OAAO,QAAQ,2BAA2B,EAC3D,GACI,EAAE,aAAkB,cACpB,CAAC,EAAO,QAAQ,iBAEhB,OAGJ,EAAE,eAAe,EAEjB,GAAM,CAAE,qBAAsB,MAAM,EAAW,EAC/C,MAAM,EAAkB,EAAO,QAAQ,gBAAgB,CAC3D,CAAC,EAED,MAAyB,CACrB,MAAe,CACP,SAAS,cAAc,2BAA2B,GAClD,EAAS,SAAY,CACjB,MAAM,EAAW,CACrB,EAAG,GAAI,CAEf,CAAC,CACL,CAAC,CACL,ECxCa,EAAe,EAAK,SAAY,MAAM,OAAO,gCAAU,EAOvD,EAAW,KAAM,IAAQ,CAClC,GAAM,CAAE,YAAa,MAAM,EAAa,EACxC,OAAO,MAAM,EAAS,CAAI,CAC9B,EAmBa,EAAsB,SAAY,CAC3C,SAAS,iBAAiB,QAAS,KAAM,IAAK,CAC1C,GAAI,EAAE,EAAE,kBAAkB,SACtB,MAAO,GAGX,IAAM,EAAS,EAAE,OAAO,QAAQ,kBAAkB,EAClD,GAAI,EAAE,aAAkB,cAAgB,CAAC,EAAO,QAAQ,SACpD,OAGJ,EAAE,eAAe,EAIjB,IAAM,EAAO,KAAK,MAAM,EAAO,QAAQ,QAAQ,EAKzC,EAAe,CAAC,MAAO,iBAAkB,iBAAA,EACzC,EAAS,EAAO,QAAQ,GAAG,CAAC,EAAE,OACpC,GAAI,EAAQ,CACR,IAAM,EAAS,IAAI,gBAAgB,CAAM,EACzC,IAAK,GAAM,CAAC,EAAW,KAAe,EAC7B,EAAa,SAAS,CAAS,IAChC,EAAK,GAAa,EAG9B,CAaA,GAPA,EAAc,CACV,SALW,EAAO,QAAQ,wCAAwC,EAChE,uBACA,YAIF,OAAQ,kBACR,MAAO,gCACP,MAAA,EAAA,CAAA,EAAY,EAAA,CAAM,SAAU,OAAO,SAAS,QAAA,CAAA,CAChD,CAAC,EAEG,EAAK,gBAAiB,CACtB,EAAO,SAAW,GAClB,EAAO,UAAU,IAAI,eAAe,EACpC,GAAI,CACA,MAAM,EAAS,CAAI,EACnB,eAAiB,CACb,EAAO,SAAW,GAClB,EAAO,UAAU,OAAO,eAAe,CAC3C,EAAG,GAAI,CACX,MAAQ,CACJ,EAAO,SAAW,GAClB,EAAO,UAAU,OAAO,eAAe,CAC3C,CACJ,MACI,MAAM,EAAS,CAAI,CAE3B,CAAC,EAID,MAAyB,CACrB,MAAe,CACP,SAAS,cAAc,kBAAkB,GACzC,EAAS,SAAY,CACjB,MAAM,EAAa,CACvB,EAAG,GAAI,CAEf,CAAC,CACL,CAAC,CACL,ECnGA,EAAgB,EAGhB,GAAI,CACA,EAAqB,CACzB,OAAS,EAAG,CACR,QAAQ,MAAM,yCAA0C,CAAC,CAC7D,CAEA,EAAoB,EACpB,EAAkB"}