{"version":3,"file":"product-faqs-accordion-section.min.js","mappings":"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","sources":["webpack://lange/./sections/product-faqs-accordion/question-drawer.ts","webpack://lange/webpack/bootstrap","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/../node_modules/@integrabeauty/assert/src/index.ts","webpack://lange/./sections/product-faqs-accordion/yotpo-create-question.ts","webpack://lange/./sections/product-faqs-accordion/question-form.ts"],"sourcesContent":["type ModalOpenedEvent = GlobalEventHandlersEventMap['modal-opened'];\ntype ModalClosedEvent = GlobalEventHandlersEventMap['modal-closed'];\n\n/**\n * Opens the ask a question drawer.\n */\nfunction onAskQuestionClicked(event: MouseEvent) {\n  const button = event.currentTarget;\n  if (!(button instanceof HTMLButtonElement)) {\n    return;\n  }\n\n  button.setAttribute('aria-expanded', 'true');\n\n  // Claim focus return before opening. Without this the modal manager has nothing of ours on its\n  // focus stack, so closing the drawer reaches down to whichever opener an earlier modal left\n  // there, and focusing that one scrolls the page away to wherever it sits.\n  const focusEvent = new Event('focus-stack-push-requested', {\n    bubbles: true,\n    composed: true\n  });\n  button.dispatchEvent(focusEvent);\n\n  // The modal manager leaves the FAQ section active while the drawer is open, so the button would\n  // stay reachable by Tab behind it. We inert it here rather than when the drawer reports it has\n  // opened, so it is out of reach right away.\n  button.inert = true;\n\n  const container = button.closest('.product-faqs');\n  const modal = container.querySelector('modal-element');\n  modal.dataset.open = 'true';\n}\n\n/**\n * The modal manager inerts every section but the one holding the open modal, so while the ask a\n * question drawer is open, the FAQ heading and the accordion stay reachable by Tab behind it. We\n * inert them ourselves. The header is left alone since the drawer sits inside it.\n */\nfunction onModalOpened(event: ModalOpenedEvent) {\n  const target = event.currentTarget;\n  if (target instanceof HTMLElement) {\n    const selector = 'header > div, accordion-element';\n    const parts = target.querySelectorAll<HTMLElement>(selector);\n    for (const part of parts) {\n      part.inert = true;\n    }\n  }\n}\n\n/**\n * Takes the section's parts back out of inert, the ask a question button included. The modal\n * manager puts focus back on that button only after this runs, and a focus call into an inert\n * element does nothing.\n */\nfunction onModalClosed(event: ModalClosedEvent) {\n  const target = event.currentTarget;\n  if (target instanceof HTMLElement) {\n    const selector = 'header > div, .ask-question, accordion-element';\n    const parts = target.querySelectorAll<HTMLElement>(selector);\n    for (const part of parts) {\n      part.inert = false;\n    }\n\n    const askQuestion = target.querySelector('.ask-question');\n    askQuestion.setAttribute('aria-expanded', 'false');\n  }\n}\n\n// Each FAQ section on the page carries its own copy of this script, and every copy runs, so we skip\n// the sections an earlier copy already set up.\nconst selector = '.product-faqs:not([data-drawer-initialized])';\nconst sections = document.querySelectorAll<HTMLElement>(selector);\nfor (const section of sections) {\n  const askQuestion = section.querySelector<HTMLElement>('.ask-question');\n  askQuestion.addEventListener('click', onAskQuestionClicked);\n\n  section.addEventListener('modal-opened', onModalOpened);\n  section.addEventListener('modal-closed', onModalClosed);\n  section.dataset.drawerInitialized = 'true';\n}\n","// The module cache\nlet __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tlet cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tlet module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","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 * Throws an assertion error if the given condition is falsy.\n *\n * @param expression any expression, although one that evaluates to true or false is preferred by\n * convention\n * @param message optional error text\n */\nexport function assert(expression: unknown, message?: string) {\n  if (!expression) {\n    throw new AssertionError(message);\n  }\n}\n\nexport class AssertionError extends Error {\n  constructor(message = 'Assertion error') {\n    super(message);\n    this.name = this.constructor.name;\n  }\n}\n","import { assert } from '@integrabeauty/assert';\n\nexport interface Input {\n  appkey: string;\n\n  /**\n   * The customer's name\n   */\n  display_name: string;\n\n  /**\n   * The customer's email\n   */\n  email: string;\n\n  /**\n   * Prevents sending of two identical questions. It is recommended to set this to true.\n   */\n  prevent_duplicate_review?: boolean;\n\n  /**\n   * The description of the product\n   */\n  product_description?: string;\n\n  /**\n   * The URL of the image of the product\n   */\n  product_image_url?: string;\n\n  /**\n   * The tag you apply to a product in Custom Questions. This can only be a single string. Products\n   * can accept one tag per product and may not contain commas.\n   */\n  product_tags?: string;\n\n  /**\n   * The name of the product\n   */\n  product_title: string;\n\n  /**\n   * The URL of the product\n   */\n  product_url: string;\n\n  /**\n   * The question the customer asks\n   */\n  review_content: string;\n\n  /**\n   * The id of the product to which the new question should be attached. This may be a SKU.\n   */\n  sku: string;\n}\n\n/**\n * Create and send a Question which requires email confirmation.\n *\n * * The sku parameter only supports alphanumeric (a...z, A...Z, 0...9), \"_\" and \"-\" characters.\n * * Products can accept one tag per product and may not contain commas (,)\n * * Adding more than one product tag per product will result in a failed request (400 Error). As a\n *   result, no new question will be created.\n *\n * It is possible to allow questions without using a confirmation email. This function only supports\n * the \"with confirmation email\" requirement.\n *\n * @see https://apidocs.yotpo.com/reference/send-question-confirmation-mail\n */\nexport async function createQuestion(input: Partial<Input>) {\n  assert(input.appkey, 'Invalid app key');\n\n  const url = new URL('/questions/send_confirmation_mail', 'https://api.yotpo.com');\n\n  let response;\n  try {\n    response = await fetch(url, {\n      headers: {\n        'Content-Type': 'application/json'\n      },\n      body: JSON.stringify(input),\n      method: 'POST',\n      mode: 'cors'\n    });\n  } catch (cause) {\n    const error: any = new Error('Failed to send yotpo create question request', { cause });\n    error.url = url.href;\n    throw error;\n  }\n\n  if (!response.ok) {\n    const error: any = new Error('Received non-200 status code creating question');\n    error.code = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  // We are not using response.json() because it obscures errors.\n\n  let responseText;\n  try {\n    responseText = await response.text();\n  } catch (cause) {\n    const error: any = new Error('Failed to fetch yotpo create question response body', { cause });\n    error.code = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  // We are not hard-casting the object to its type here. Instead, we are leaving the type as\n  // unknown initially, and then later proving the type using a type assertion.\n\n  let body;\n  try {\n    body = JSON.parse(responseText);\n  } catch (cause) {\n    const error: any = new Error('Failed to parse yotpo create question response body', { cause });\n    error.body = responseText;\n    error.code = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  if (!isResponseBody(body)) {\n    const error: any = new Error('Malformed response body creating question');\n    error.body = body;\n    error.code = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  if (body.status.code > 399) {\n    const error: any = new Error('Nested response status code is not ok when creating question');\n    error.body = body;\n    error.code = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  return body;\n}\n\nexport interface ResponseBody {\n  status: {\n    code: number;\n    message: string;\n  };\n}\n\nexport function isResponseBody(value: any): value is ResponseBody {\n  return typeof value === 'object' && value !== null && typeof value.status === 'object' &&\n    value.status !== null;\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { createQuestion, type Input } from './yotpo-create-question.js';\n\n/**\n * Takes away the errors from an earlier attempt, so someone who closed the drawer partway and comes\n * back later doesn't reopen it to a form full of red. What they typed stays, and the errors come\n * back on the next post if it's still not right.\n */\nfunction onModalOpened(event: GlobalEventHandlersEventMap['modal-opened']) {\n  if (!(event.currentTarget instanceof HTMLElement)) {\n    return;\n  }\n\n  const form = event.currentTarget.querySelector('form');\n  form.classList.remove('error');\n\n  const errorElements = form.querySelectorAll('.error');\n  for (const element of errorElements) {\n    element.classList.remove('error');\n  }\n\n  const summaries = form.querySelectorAll<HTMLElement>('.error-summary, .post-error');\n  for (const summary of summaries) {\n    summary.hidden = true;\n  }\n}\n\n/**\n * Checks the ask a question form, and posts the question when every field is filled in right.\n */\nfunction onSubmitClicked(event: MouseEvent) {\n  event.preventDefault();\n\n  const submitButton = event.currentTarget;\n  if (!(submitButton instanceof HTMLButtonElement)) {\n    return;\n  }\n\n  const form = submitButton.form;\n  const errorSummary = form.querySelector<HTMLElement>('.error-summary');\n\n  if (!form.checkValidity()) {\n    for (const element of form.elements) {\n      if (!(element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {\n        continue;\n      }\n\n      if (element.checkValidity()) {\n        element.parentElement.classList.remove('error');\n      } else {\n        element.parentElement.classList.add('error');\n      }\n    }\n\n    const invalidField = form.querySelector<HTMLElement>(':invalid');\n    invalidField.focus({ focusVisible: true });\n\n    errorSummary.hidden = false;\n    return;\n  }\n\n  errorSummary.hidden = true;\n\n  postQuestion(form, submitButton).catch(console.error);\n}\n\n/**\n * Sends the question to Yotpo. Once it is accepted, we close the drawer and let the rest of the\n * page know a question was asked and who asked it.\n */\nasync function postQuestion(form: HTMLFormElement, submitButton: HTMLButtonElement) {\n  const formData = new FormData(form);\n  const displayName = formData.get('display_name');\n  const email = formData.get('email');\n  const reviewContent = formData.get('review_content');\n\n  const input: Partial<Input> = {\n    appkey: form.dataset.yotpoAppKey,\n    display_name: isString(displayName) ? displayName : '',\n    email: isString(email) ? email : '',\n    product_title: form.dataset.productTitle,\n    product_url: form.dataset.productUrl,\n    review_content: isString(reviewContent) ? reviewContent : '',\n    sku: form.dataset.productId\n  };\n\n  const loader = form.querySelector('loading-indicator');\n  submitButton.disabled = true;\n  loader.hidden = false;\n\n  try {\n    await createQuestion(input);\n  } catch (error) {\n    submitButton.disabled = false;\n    loader.hidden = true;\n    form.classList.add('error');\n\n    const postError = form.querySelector<HTMLElement>('.post-error');\n    postError.hidden = false;\n\n    console.error(error, input);\n    return;\n  }\n\n  submitButton.disabled = false;\n  loader.hidden = true;\n  form.reset();\n\n  const modal = form.closest('modal-element');\n  delete modal.dataset.open;\n\n  type Detail = WindowEventMap['yotpo-question-created']['detail'];\n  const createdEvent = new CustomEvent<Detail>('yotpo-question-created', {\n    bubbles: true,\n    composed: true,\n    detail: {\n      body: input.review_content,\n      customer_id: parseInt(form.dataset.customerId, 10),\n      email: input.email,\n      event_id: uuidv4(),\n      name: input.display_name,\n      product_title: form.dataset.productTitle,\n      product_url: form.dataset.productUrl\n    }\n  });\n  form.dispatchEvent(createdEvent);\n\n  const detail: WindowEventMap['identity-captured']['detail'] = {\n    email: input.email\n  };\n\n  // The display_name field may contain a full name. Attempt to parse it into first and last name by\n  // splitting on space. If there is only one part, treat it as the first name. If there are two\n  // parts, treat the first as the first name and the second as the last name. If there are more\n  // than two parts, treat the last part as the last name and the rest as the first name.\n  const parts = input.display_name.split(' ');\n  if (parts.length === 1) {\n    detail.first_name = parts[0];\n  } else if (parts.length === 2) {\n    detail.first_name = parts[0];\n    detail.last_name = parts[1];\n  } else {\n    detail.last_name = parts.pop();\n    detail.first_name = parts.join(' ');\n  }\n\n  const identityEvent = new CustomEvent<typeof detail>('identity-captured', {\n    bubbles: true,\n    composed: true,\n    detail\n  });\n  form.dispatchEvent(identityEvent);\n}\n\nfunction isString(value: any): value is string {\n  return typeof value === 'string';\n}\n\n// Each FAQ section on the page carries its own copy of this script, and every copy runs, so we skip\n// the sections an earlier copy already set up.\nconst sections = document.querySelectorAll<HTMLElement>(\n  '.product-faqs:not([data-form-initialized])');\nfor (const section of sections) {\n  const modal = section.querySelector('modal-element');\n  modal.addEventListener('modal-opened', onModalOpened);\n\n  const submitButton = section.querySelector<HTMLElement>('form button[type=\"submit\"]');\n  submitButton.addEventListener('click', onSubmitClicked);\n\n  section.dataset.formInitialized = 'true';\n}\n"],"names":["onAskQuestionClicked","event","button","currentTarget","HTMLButtonElement","setAttribute","focusEvent","Event","bubbles","composed","dispatchEvent","inert","closest","querySelector","dataset","open","onModalOpened","target","HTMLElement","selector","parts","querySelectorAll","part","onModalClosed","sections","document","section","addEventListener","drawerInitialized","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","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","AssertionError","constructor","message","super","this","name","async","createQuestion","input","expression","assert","appkey","url","URL","response","responseText","body","fetch","headers","JSON","stringify","method","mode","cause","error","href","ok","code","status","text","parse","value","form","classList","remove","errorElements","element","summaries","summary","hidden","onSubmitClicked","preventDefault","submitButton","errorSummary","checkValidity","elements","HTMLInputElement","HTMLTextAreaElement","parentElement","add","focus","focusVisible","formData","FormData","displayName","get","email","reviewContent","yotpoAppKey","display_name","isString","product_title","productTitle","product_url","productUrl","review_content","sku","productId","loader","disabled","console","reset","modal","createdEvent","CustomEvent","detail","customer_id","parseInt","customerId","event_id","split","first_name","last_name","pop","join","identityEvent","postQuestion","catch","formInitialized"],"sourceRoot":""}