{"version":3,"file":"quiz-result-product-section.min.js","mappings":"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","sources":["webpack://lange/../node_modules/uuid/dist/rng.js","webpack://lange/../node_modules/uuid/dist/stringify.js","webpack://lange/../node_modules/uuid/dist/v4.js","webpack://lange/./lib/dom-ready.ts","webpack://lange/./sections/quiz-result-product/index.ts"],"sourcesContent":["const rnds8 = new Uint8Array(16);\nexport default function rng() {\n    return crypto.getRandomValues(rnds8);\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n    byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n    return (byteToHex[arr[offset + 0]] +\n        byteToHex[arr[offset + 1]] +\n        byteToHex[arr[offset + 2]] +\n        byteToHex[arr[offset + 3]] +\n        '-' +\n        byteToHex[arr[offset + 4]] +\n        byteToHex[arr[offset + 5]] +\n        '-' +\n        byteToHex[arr[offset + 6]] +\n        byteToHex[arr[offset + 7]] +\n        '-' +\n        byteToHex[arr[offset + 8]] +\n        byteToHex[arr[offset + 9]] +\n        '-' +\n        byteToHex[arr[offset + 10]] +\n        byteToHex[arr[offset + 11]] +\n        byteToHex[arr[offset + 12]] +\n        byteToHex[arr[offset + 13]] +\n        byteToHex[arr[offset + 14]] +\n        byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n    const uuid = unsafeStringify(arr, offset);\n    if (!validate(uuid)) {\n        throw TypeError('Stringified UUID is invalid');\n    }\n    return uuid;\n}\nexport default stringify;\n","import rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n    if (!buf && !options && crypto.randomUUID) {\n        return crypto.randomUUID();\n    }\n    return _v4(options, buf, offset);\n}\nfunction _v4(options, buf, offset) {\n    options = options || {};\n    const rnds = options.random ?? options.rng?.() ?? rng();\n    if (rnds.length < 16) {\n        throw new Error('Random bytes length must be >= 16');\n    }\n    rnds[6] = (rnds[6] & 0x0f) | 0x40;\n    rnds[8] = (rnds[8] & 0x3f) | 0x80;\n    if (buf) {\n        offset = offset || 0;\n        if (offset < 0 || offset + 16 > buf.length) {\n            throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n        }\n        for (let i = 0; i < 16; ++i) {\n            buf[offset + i] = rnds[i];\n        }\n        return buf;\n    }\n    return unsafeStringify(rnds);\n}\nexport default v4;\n","/**\n * Releases the handle returned from the ready() function.\n *\n * This is idempotent. Additional calls are pointless but harmless.\n */\nexport type ReleaseHandle = () => void;\n\n/**\n * A subset of events that pertain to document ready state.\n */\ntype LoadingEventMap = Pick<DocumentEventMap, 'DOMContentLoaded' | 'load'>;\n\n/**\n * Calls the provided callback when the document is ready. This works both when the document is\n * already ready and when it is not, so callers do not have to care. This exists because it ensures\n * that each caller consistently expresses its dependency on document readiness, and to save a bit\n * of boilerplate.\n *\n * A document is considered ready when it has been parsed. This corresponds to the ready state of\n * 'interactive'. When the document has been fully loaded, the ready state is 'complete'. The\n * callback runs either way, so callers do not have to check which one they are in.\n *\n * Ready means the html is parsed and the DOM is there to query. It does not mean the page's other\n * scripts have run. Deferred scripts and module scripts run after the ready state turns\n * 'interactive' and before DOMContentLoaded fires, so a callback here can run before them. When a\n * caller needs some other script to have run already, this is the wrong tool, and it should wait on\n * whatever that script produces instead.\n *\n * That remedy has a catch of its own when the calling bundle is loaded with async. An async bundle\n * can execute after DOMContentLoaded has already fired, so a plain listener for that event never\n * runs and the work silently never happens. Nothing here can detect that, because by the time this\n * file executes the event is long gone. Catching it needs something registered at parse time,\n * before any bundle loads.\n *\n * There is a second trap right next to that one, and it applies only when waiting for\n * DOMContentLoaded. The ready state stays 'interactive' after DOMContentLoaded has fired, all the\n * way until 'complete', so the ready state cannot tell you whether DOMContentLoaded is still coming\n * or has already gone. Waiting for load is not exposed to this, because the ready state turns\n * 'complete' and load fires in the same task, so seeing 'complete' means load has fired too.\n *\n * When the document is already ready, the callback is invoked via setTimeout. This way, if the\n * callback throws, the error surfaces to the global error handler in a way that is similar to what\n * happens when an event listener throws.\n *\n * We might one day want to move this to an NPM library.\n *\n * Beware of a quirk here. setTimeout yields, and the busier the frontend, the longer it takes to\n * fire. Page load is exactly when the frontend is busiest. The timeout is a floor and not a\n * guarantee, so there is no real bound on how long that yield lasts. What this means is that using\n * this library can introduce more delay than you might expect. Compare code that runs on async load\n * and checks ready state and invokes immediately to code that runs after setTimeout. The former\n * runs in the same tick, the latter runs in \"some later tick\". That later tick can be surprisingly\n * much later. That can cause initial paint issues.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event\n * @see https://html.spec.whatwg.org/multipage/parsing.html#the-end\n */\nexport function ready(callback: (event?: Event) => void,\n  type: keyof LoadingEventMap = 'DOMContentLoaded') {\n  if (document.readyState === 'complete' || (type === 'DOMContentLoaded' &&\n    document.readyState === 'interactive')) {\n    const timer = setTimeout(callback, 0);\n    const handle: ReleaseHandle = () => clearTimeout(timer);\n    return handle;\n  } else {\n    addEventListener(type, callback);\n    const handle: ReleaseHandle = () => removeEventListener(type, callback);\n    return handle;\n  }\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { ready } from '../../lib/dom-ready.js';\n\nfunction onReady() {\n  const urlParams = new URLSearchParams(window.location.search);\n  const respId = urlParams.get('resp_id');\n\n  // When a visitor completes a quiz, they are redirected to a specific result page based on their\n  // quiz results and dispatch a quiz completed event. However we only dispatch this event if the\n  // resp_id parameter is present in the URL, as this indicates that the quiz was completed\n  // successfully and the user did not directly navigate to the product page.\n  if (respId) {\n    const content: string[] = [];\n    const resultContent = document.querySelectorAll('[data-quiz-result-content]');\n    for (const resultEl of resultContent) {\n      const textContent = resultEl.textContent?.trim();\n      if (textContent) {\n        content.push(textContent);\n      }\n    }\n\n    const resultSteps = document.querySelectorAll('routine-step');\n    for (const step of resultSteps) {\n      const title = step.dataset.label?.trim();\n      if (title) {\n        content.push(title);\n      }\n\n      const description = step.dataset.description?.trim();\n      if (description) {\n        content.push(description);\n      }\n    }\n\n    type QuizCompletedEvent = WindowEventMap['quiz-completed'];\n    const event = new CustomEvent<QuizCompletedEvent['detail']>('quiz-completed', {\n      bubbles: true,\n      composed: true,\n      detail: {\n        event_id: uuidv4(),\n        content,\n        name: window.quiz.name,\n        persona_image: window.quiz.persona_image,\n        vendor: 'tangent',\n        url: location.pathname,\n        products: window.quiz.products,\n        resp_id: respId || ''\n      }\n    });\n\n    // The quiz itself is over by the time this page loads, so there is no quiz element here to\n    // dispatch from. The product detail section is our own markup and wraps the whole result, so\n    // that is the element responsible for the event. It bubbles, so the analytics bridge and the\n    // meta pixel listening at window scope still see it. If it ever goes missing we fall back to\n    // window, which is what this used to do unconditionally.\n    const eventTarget = document.querySelector('#product-detail-section') || window;\n    eventTarget.dispatchEvent(event);\n  }\n}\n\nready(onReady);\n"],"names":["rnds8","Uint8Array","byteToHex","i","push","toString","slice","unsafeStringify","arr","offset","toLowerCase","dist_v4","options","buf","crypto","randomUUID","_ref","_options$random","rnds","random","rng","getRandomValues","length","Error","RangeError","_v4","callback","type","document","readyState","timer","setTimeout","clearTimeout","addEventListener","ready","respId","URLSearchParams","window","location","search","get","content","resultContent","querySelectorAll","resultEl","_resultEl$textContent","textContent","trim","resultSteps","step","_step$dataset$label","_step$dataset$descrip","title","dataset","label","description","event","CustomEvent","bubbles","composed","detail","event_id","name","quiz","persona_image","vendor","url","pathname","products","resp_id","querySelector","dispatchEvent"],"sourceRoot":""}