{"version":3,"file":"yotpo-question-create-element-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/../node_modules/@integrabeauty/assert/src/index.ts","webpack://lange/./lib/decorate-error.ts","webpack://lange/./sections/yotpo-question-create/yotpo-question-create/yotpo-create-question.ts","webpack://lange/./sections/yotpo-question-create/yotpo-question-create/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 * 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","/**\n * Copies a single piece of supplementary context onto an error before it is thrown or reported.\n *\n * Use this when decorating a value the calling code did not construct, such as a caught value or an\n * error handed in by another module. An error the caller just built with new is always writable, so\n * plain assignment is fine there. A value from elsewhere may be a foreign object this code does not\n * own. Such a value can carry a non-writable property, such as a DOMException whose code is a read-\n * only accessor, or be frozen outright, and assigning to it then throws. Attaching context must\n * never itself fail, so a rejected assignment is swallowed and the remaining context is still\n * attempted. Guarding each property in isolation means a single read-only slot, the common case,\n * costs only that one property rather than all of them.\n *\n * In practice the value that triggers this is almost always a DOMException that reached the caller\n * from a fetch the browser cut short, such as an abort when an in-flight request is interrupted.\n * The platform defines a DOMException's code, name, and message as read-only attributes, so\n * assigning a code onto one throws under the strict mode that all bundled module code runs in. It\n * surfaces from Safari far more than elsewhere for two reasons. The reported wording, attempted to\n * assign to readonly property, is JavaScriptCore's phrasing for this failure, so the same bug in\n * another engine is worded differently and groups as a separate report, which makes this one look\n * Safari specific even though the read-only rule is not. And iOS Safari abandons in-flight fetches\n * aggressively when a tab is backgrounded or a connection drops, which is when such a DOMException\n * tends to be produced and handed to code that assumed an ordinary writable error.\n *\n * A swallowed failure is logged at a level low enough that it is recorded as a breadcrumb for\n * monitoring rather than escalated into its own captured event. That keeps the lost context visible\n * alongside the eventual report without adding fresh noise of its own. The breadcrumb names the\n * property that could not be attached, the kind of value that rejected it, and why, which is enough\n * to recognize a read-only or frozen caught value after the fact.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Read-only\n * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMException\n * @see https://webidl.spec.whatwg.org/#dfn-read-only\n */\nexport function decorateError(error: any, key: string, value: unknown) {\n  try {\n    error[key] = value;\n  } catch (assignmentError) {\n    let reason: string;\n    if (assignmentError instanceof Error) {\n      reason = assignmentError.message;\n    } else {\n      reason = `${assignmentError}`;\n    }\n\n    console.log('Failed to assign error property', {\n      key,\n      name: error?.name,\n      tag: Object.prototype.toString.call(error),\n      reason\n    });\n  }\n}\n","import { assert } from '@integrabeauty/assert';\nimport { decorateError } from '../../../lib/decorate-error.js';\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 * IMPORTANT: It's a copy of existing function in js/sections/yotpo-question-create/yotpo-question-\n * create/yotpo-create-question.ts It was copied for a A/B experiment redesigned component. After\n * the experiment is finished, only one component should remain.\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 (error) {\n    decorateError(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 (error) {\n    decorateError(error, 'code', response.status);\n    decorateError(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 (error) {\n    decorateError(error, 'body', responseText);\n    decorateError(error, 'code', response.status);\n    decorateError(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 type { CustomElement } from '@integrabeauty/custom-elements';\nimport { v4 as uuidv4 } from 'uuid';\nimport html from './index.html';\nimport styles from './index.scss';\nimport { createQuestion, type Input } from './yotpo-create-question.js';\n\n/**\n * Renders a Yotpo \"Ask question\" button and question form in a slide-in drawer. This is the v2\n * redesign of the question-create element, following the same drawer UI pattern as the review-\n * create-v2 element while keeping the question-specific form fields and Yotpo question API.\n */\nclass YotpoQuestionCreate extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Shopify customer id of currently logged in user\n     */\n    customerId: string;\n\n    /**\n     * Shopify product id to which the question will pertain\n     */\n    productId: string;\n\n    /**\n     * Shopify product title to which the question will pertain\n     */\n    productTitle: string;\n\n    /**\n     * Shopify product url to which the question will pertain\n     */\n    productUrl: string;\n\n    /**\n     * Yotpo API app key\n     */\n    yotpoAppKey: string;\n  };\n\n  private onAskQuestionButtonClickedBound = this.onAskQuestionButtonClicked.bind(this);\n  private onSubmitButtonClickedBound = this.onSubmitButtonClicked.bind(this);\n  private onCloseButtonClickedBound = this.onCloseButtonClicked.bind(this);\n  private onModalDismissRequestedBound = this.onModalDismissRequested.bind(this);\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n\n    const askQuestionButton = this.shadowRoot.querySelector<HTMLButtonElement>('.ask-question');\n    askQuestionButton?.addEventListener('click', this.onAskQuestionButtonClickedBound);\n\n    const submitButton = this.shadowRoot.querySelector<HTMLButtonElement>('button[type=\"submit\"]');\n    submitButton?.addEventListener('click', this.onSubmitButtonClickedBound);\n\n    const closeButton = this.shadowRoot.querySelector('close-button');\n    closeButton?.addEventListener('click', this.onCloseButtonClickedBound);\n  }\n\n  public disconnectedCallback() {\n    const askQuestionButton = this.shadowRoot.querySelector<HTMLButtonElement>('.ask-question');\n    askQuestionButton?.removeEventListener('click', this.onAskQuestionButtonClickedBound);\n\n    const submitButton = this.shadowRoot.querySelector<HTMLButtonElement>('button[type=\"submit\"]');\n    submitButton?.removeEventListener('click', this.onSubmitButtonClickedBound);\n\n    const closeButton = this.shadowRoot.querySelector('close-button');\n    closeButton?.removeEventListener('click', this.onCloseButtonClickedBound);\n  }\n\n  private initializeShadowRoot() {\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: 'open' });\n      this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n    }\n  }\n\n  private onSubmitButtonClicked(event: PointerEvent) {\n    event.preventDefault();\n\n    const submitButton = event.currentTarget;\n    if (!(submitButton instanceof HTMLButtonElement)) {\n      return;\n    }\n\n    const form = this.shadowRoot.querySelector('form');\n\n    const isValid = form.checkValidity();\n    if (!isValid) {\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.add('error');\n          const invalidField = form.querySelector<HTMLElement>(':invalid');\n          invalidField.focus({ focusVisible: true });\n        } else {\n          element.parentElement.classList.remove('error');\n        }\n      }\n\n      const errorSummary = this.shadowRoot.querySelector<HTMLElement>('.error-summary');\n      errorSummary.hidden = false;\n\n      return;\n    }\n\n    const errorSummary = this.shadowRoot.querySelector<HTMLElement>('.error-summary');\n    errorSummary.hidden = true;\n\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 createQuestionInput: Partial<Input> = {\n      appkey: this.dataset.yotpoAppKey,\n      display_name: isString(displayName) ? displayName : '',\n      email: isString(email) ? email : '',\n      product_title: this.dataset.productTitle,\n      product_url: this.dataset.productUrl,\n      review_content: isString(reviewContent) ? reviewContent : '',\n      sku: this.dataset.productId\n    };\n\n    const loader = this.shadowRoot.querySelector('loading-indicator');\n    submitButton.disabled = true;\n    loader.hidden = false;\n\n    createQuestion(createQuestionInput).then(() => {\n      submitButton.disabled = false;\n      loader.hidden = true;\n      form.reset();\n      this.closeDrawer();\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: isString(reviewContent) ? reviewContent : '',\n          customer_id: parseInt(this.dataset.customerId, 10),\n          email: createQuestionInput.email,\n          event_id: uuidv4(),\n          name: createQuestionInput.display_name,\n          product_title: this.dataset.productTitle,\n          product_url: this.dataset.productUrl\n        }\n      });\n      this.dispatchEvent(createdEvent);\n\n      const detail: WindowEventMap['identity-captured']['detail'] = {\n        email: createQuestionInput.email\n      };\n\n      // The display_name field may contain a full name. Attempt to parse it into first and last\n      // name by splitting on space. If there is only one part, treat it as the first name. If there\n      // are two parts, treat the first as the first name and the second as the last name. If there\n      // are more than two parts, treat the last part as the last name and the rest as the first\n      // name.\n      const parts = isString(displayName) && displayName.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      type IdentityCapturedEvent = WindowEventMap['identity-captured'];\n\n      const identityEvent = new CustomEvent<IdentityCapturedEvent['detail']>('identity-captured', {\n        bubbles: true,\n        composed: true,\n        detail\n      });\n      this.dispatchEvent(identityEvent);\n    }).catch(error => {\n      submitButton.disabled = false;\n      loader.hidden = true;\n      errorSummary.textContent = 'Sorry we are having temporary problems, please try again later.';\n      errorSummary.parentElement.classList.add('error');\n      errorSummary.hidden = false;\n\n      console.error(error, createQuestionInput);\n    });\n  }\n\n  /**\n   * Opens the ask a question form drawer when the button is clicked.\n   */\n  private onAskQuestionButtonClicked(event: PointerEvent) {\n    if (!(event.target instanceof HTMLButtonElement)) {\n      return;\n    }\n\n    const drawer = this.shadowRoot.querySelector<HTMLElement>('#drawer');\n    drawer.classList.add('active');\n    drawer.inert = false;\n\n    event.target.setAttribute('aria-expanded', 'true');\n\n    addEventListener('modal-dismiss-requested', this.onModalDismissRequestedBound);\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    event.target.dispatchEvent(focusEvent);\n\n    const modalShowEvent = new Event('modal-open-requested', { bubbles: true, composed: true });\n    drawer.dispatchEvent(modalShowEvent);\n\n    const closeButton = drawer.querySelector('close-button');\n    closeButton.focus({ focusVisible: true });\n  }\n\n  /**\n   * Handles the click event on the close button of the drawer.\n   */\n  private onCloseButtonClicked(_event: PointerEvent) {\n    this.closeDrawer();\n  }\n\n  /**\n   * Handles the event sent when clicking on the modal backdrop or pressing the Escape key. The\n   * event is sent by modal-manager.\n   */\n  private onModalDismissRequested(_event: Event) {\n    this.closeDrawer();\n  }\n\n  /**\n   * Close the form drawer.\n   */\n  private closeDrawer() {\n    const drawer = this.shadowRoot.querySelector<HTMLElement>('#drawer');\n    drawer.classList.remove('active');\n    drawer.inert = true;\n\n    const askQuestion = this.shadowRoot.querySelector('.ask-question');\n    askQuestion.setAttribute('aria-expanded', 'false');\n\n    removeEventListener('modal-dismiss-requested', this.onModalDismissRequestedBound);\n\n    const event = new Event('modal-close-requested', { bubbles: true, composed: true });\n    drawer.dispatchEvent(event);\n  }\n}\n\nfunction isString(value: any): value is string {\n  return typeof value === 'string';\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'yotpo-question-create': YotpoQuestionCreate;\n  }\n}\n\nif (!customElements.get('yotpo-question-create')) {\n  customElements.define('yotpo-question-create', YotpoQuestionCreate);\n}\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","AssertionError","constructor","message","super","this","name","decorateError","error","key","value","assignmentError","reason","console","log","tag","Object","prototype","call","async","createQuestion","input","expression","assert","appkey","url","URL","response","responseText","body","fetch","headers","JSON","stringify","method","mode","href","ok","code","status","text","parse","YotpoQuestionCreate","HTMLElement","onAskQuestionButtonClickedBound","onAskQuestionButtonClicked","bind","onSubmitButtonClickedBound","onSubmitButtonClicked","onCloseButtonClickedBound","onCloseButtonClicked","onModalDismissRequestedBound","onModalDismissRequested","connectedCallback","initializeShadowRoot","askQuestionButton","shadowRoot","querySelector","addEventListener","submitButton","closeButton","disconnectedCallback","removeEventListener","attachShadow","innerHTML","event","preventDefault","currentTarget","HTMLButtonElement","form","checkValidity","element","elements","HTMLInputElement","HTMLTextAreaElement","parentElement","classList","remove","add","focus","focusVisible","hidden","errorSummary","formData","FormData","displayName","get","email","reviewContent","createQuestionInput","dataset","yotpoAppKey","display_name","isString","product_title","productTitle","product_url","productUrl","review_content","sku","productId","loader","disabled","then","reset","closeDrawer","createdEvent","CustomEvent","bubbles","composed","detail","customer_id","parseInt","customerId","event_id","dispatchEvent","parts","split","first_name","last_name","pop","join","identityEvent","catch","textContent","target","drawer","inert","setAttribute","focusEvent","Event","modalShowEvent","_event","customElements","define"],"sourceRoot":""}