{"version":3,"file":"collection-page-section.min.js","mappings":"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","sources":["webpack://lange/./sections/collection-page/collection-viewed.ts","webpack://lange/webpack/bootstrap","webpack://lange/./sections/collection-page/collection-filters.ts","webpack://lange/./lib/dom-ready.ts"],"sourcesContent":["type CollectionViewedEvent = GlobalEventHandlersEventMap['collection-viewed'];\n\nconst event = new CustomEvent<CollectionViewedEvent['detail']>('collection-viewed', {\n  detail: {\n    all_products_count: collection_page_section.collection.all_products_count,\n    handle: collection_page_section.collection.handle,\n    id: collection_page_section.collection.id,\n    products_count: collection_page_section.collection.products_count,\n    title: collection_page_section.collection.title,\n    url: collection_page_section.collection.url\n  }\n});\n\ndispatchEvent(event);\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","import { ready } from '../../lib/dom-ready.js';\n\ninterface Detail {\n  /**\n   * Derived from the url of a collection page, it represents the collection page, similar to a\n   * handle.\n   */\n  category: string;\n\n  /**\n   * The filters currently applied. Largely derived from Mixitup.\n   */\n  filters: {\n    type: string;\n    value: string;\n  }[];\n\n  /**\n   * The list of products present after filtering the products on a collection page.\n   */\n  products: Product[];\n}\n\ninterface Product {\n  /**\n   * @example \"L'ange\"\n   */\n  brand: string;\n\n  /**\n   * @example \"cdn_base/s/files/1/2204/1955/product?crop=center&height=1024&width=1024\"\n   */\n  image_url: string;\n\n  /**\n   * @example \"Siena Wide Vented Brush Blush\"\n   */\n  name: string;\n\n  /**\n   * in dollars\n   *\n   * @example 25\n   */\n  price: number;\n\n  /**\n   * @example \"shopify_2506523279460_22516468940900\"\n   */\n  product_id: string;\n\n  /**\n   * Shopify's internal ID for a product\n   *\n   * @example 2506523279460\n   */\n  shopify_product_id: number;\n\n  /**\n   * Shopify's internal ID for a product variant\n   *\n   * @example 22516468940900\n   */\n  shopify_variant_id: number;\n\n  /**\n   * @example \"2513\"\n   */\n  sku: string;\n\n  /**\n   * The url of the product page.\n   *\n   * @example \"https://langehair.com/products/siena-wide-vented-brush-blush\"\n   */\n  url: string;\n}\n\n/**\n * Occurs when a user changes the filter settings on a collection page to view different products.\n */\ntype CollectionFilteredEvent = CustomEvent<Detail>;\n\ndeclare global {\n  interface GlobalEventHandlersEventMap {\n    'collection-filtered': CollectionFilteredEvent;\n  }\n}\n\nfunction onFilterModalOpenClick(_event: MouseEvent) {\n  const elements = document.querySelectorAll<HTMLElement>(\n    '.collection-page .backdrop, .collection-page .modal');\n  for (const element of elements) {\n    element.hidden = false;\n  }\n}\n\nfunction onFilterModalCloseClick(_event?: MouseEvent) {\n  const elements = document.querySelectorAll<HTMLElement>(\n    '.collection-page .backdrop, .collection-page .modal');\n  for (const element of elements) {\n    element.hidden = true;\n  }\n}\n\nfunction onClearFiltersClicked(_event: MouseEvent) {\n  // Deactivate all active filter toggles.\n  const buttons = document.querySelectorAll<HTMLElement>(\n    '.collection-page .modal .controls .tags > button.active[data-toggle]');\n  for (const button of buttons) {\n    button.classList.remove('active');\n  }\n\n  // Reveal every product now that no filters are active.\n  const products = document.querySelectorAll<HTMLElement>('product-card.collection-product');\n  for (const product of products) {\n    product.hidden = false;\n  }\n\n  updateNoProductsFound(products.length);\n\n  // Hide the desktop filter button controls.\n  const container = document.querySelector('.collection-page .button-controls');\n  container?.classList.add('hide-desktop');\n}\n\n/**\n * The message ships visible when the collection has nothing in it. Filtering can empty the grid\n * too, so we toggle the message whenever the number of visible products changes.\n */\nfunction updateNoProductsFound(visibleCount: number) {\n  const message = document.querySelector<HTMLElement>('#no-products-found');\n  if (!message) {\n    return;\n  }\n\n  message.hidden = visibleCount > 0;\n}\n\nfunction shouldShowProductForFilterGroup(filters: string[], tags: string[]) {\n  return filters.length === 0 || filters.some(filter => tags.includes(filter));\n}\n\nfunction applyGroups(activeFilterGroups: Record<string, string[]>) {\n  type ProductCard = HTMLElementTagNameMap['product-card'];\n\n  const cards = document.querySelectorAll<ProductCard>('product-card.collection-product');\n  const shownProducts = <CollectionFilteredEvent['detail']['products']>[];\n\n  for (const card of cards) {\n    const tags = card.dataset.tags?.split(' ') || [];\n\n    let showCard = true;\n    for (const activeGroup in activeFilterGroups) {\n      const shouldShow = shouldShowProductForFilterGroup(activeFilterGroups[activeGroup], tags);\n      if (!shouldShow) {\n        showCard = false;\n        break;\n      }\n    }\n\n    if (showCard) {\n      card.hidden = false;\n      const productSlot = card.querySelector<HTMLElementTagNameMap['product-element']>(\n        'product-element[slot=\"data\"]');\n      const selectedVariant = productSlot.querySelector<HTMLElementTagNameMap['variant-element']>(\n        `variant-element[data-id=\"${productSlot.dataset.selectedVariantId}\"]`);\n\n      shownProducts.push({\n        brand: 'L\\'ange',\n        image_url: productSlot.dataset.mainImage,\n        name: card.title,\n        price: Math.floor(parseInt(selectedVariant.dataset.price, 10) / 100),\n        product_id: card.id,\n        shopify_product_id: parseInt(card.dataset.id, 10),\n        shopify_variant_id: parseInt(selectedVariant.dataset.id, 10),\n        sku: selectedVariant.dataset.sku,\n        url: card.dataset.url\n      });\n    } else {\n      card.hidden = true;\n    }\n  }\n\n  updateNoProductsFound(shownProducts.length);\n\n  const resultsCount = document.querySelector('.collection-page .filter-cta span');\n  if (resultsCount) {\n    resultsCount.textContent = `${shownProducts.length} ${shownProducts.length > 1 ?\n      'Results' : 'Result'}`;\n  }\n\n  type Detail = CollectionFilteredEvent['detail'];\n\n  const filters: Detail['filters'] = [];\n  for (const filterGroup in activeFilterGroups) {\n    const activeFilters = activeFilterGroups[filterGroup];\n    for (const activeFilter of activeFilters) {\n      filters.push({\n        type: filterGroup,\n        value: activeFilter\n      });\n    }\n  }\n\n  const event = new CustomEvent<Detail>('collection-filtered', {\n    bubbles: true,\n    detail: {\n      category: location.pathname.split('/').pop(),\n      filters,\n      products: shownProducts\n    }\n  });\n\n  const host = document.querySelector('.collection-page .filters');\n  host.dispatchEvent(event);\n}\n\n/**\n * A filter tag is a plain button, not a custom element. We annotate its dataset so that its custom\n * attributes are type checked and documented. See snippets/collection-filter.liquid for the markup.\n */\ninterface FilterToggleButton extends HTMLButtonElement {\n  readonly dataset: {\n    /**\n     * A CSS attribute selector used to match the products belonging to this filter, of the form\n     * `[data-tags~='tag-handle']`. The tag handle (the portion between the single quotes) is the\n     * filter value.\n     */\n    toggle: string;\n  };\n}\n\nfunction buildActiveFilterGroups() {\n  const filterGroups = document.querySelectorAll<HTMLElement>('.collection-page .filter');\n  type FilterGroups = Record<string, string[]>;\n  const activeFilterGroups: FilterGroups = {};\n\n  for (const filterGroup of filterGroups) {\n    const title = filterGroup.querySelector('h3');\n    const groupName = title?.textContent;\n    if (!groupName) {\n      continue;\n    }\n\n    const selector = '.tags button.active[data-toggle]';\n    const filters = filterGroup.querySelectorAll<FilterToggleButton>(selector);\n    const activeFilters = [];\n    for (const filter of filters) {\n      const filterValue = filter.dataset.toggle.split('\\'')[1];\n      activeFilters.push(filterValue);\n    }\n\n    activeFilterGroups[groupName] = activeFilters;\n  }\n\n  return activeFilterGroups;\n}\n\nfunction onFilterToggleClick(event: MouseEvent) {\n  if (!(event.target instanceof HTMLButtonElement)) {\n    return;\n  }\n\n  event.target.classList.toggle('active');\n\n  const groups = buildActiveFilterGroups();\n\n  let filtersActive = 0;\n  for (const group in groups) {\n    filtersActive += groups[group].length;\n  }\n\n  if (filtersActive === 0) {\n    return;\n  }\n\n  const container = document.querySelector<HTMLElement>('.collection-page .button-controls');\n  if (container) {\n    container.classList.remove('hide-desktop');\n    container.addEventListener('click', onApplyFiltersButtonClick);\n  }\n}\n\nfunction onApplyFiltersButtonClick(event: MouseEvent) {\n  event.preventDefault();\n\n  const groups = buildActiveFilterGroups();\n  const filterCount = Object.keys(groups).reduce((acc, curr) => {\n    return acc + groups[curr].length;\n  }, 0);\n\n  // Only show the number in parentheses if at least one filter is applied\n  const filterCountDisplay = filterCount > 0 ? `(${filterCount})` : '';\n\n  const openButton = document.querySelector('.collection-page .filter-cta button');\n  if (openButton) {\n    openButton.textContent = `Filter ${filterCountDisplay}`;\n  }\n\n  const heading = document.querySelector('.collection-page .modal .heading');\n  if (heading) {\n    heading.textContent = `Filter ${filterCountDisplay}`;\n  }\n\n  applyGroups(groups);\n  onFilterModalCloseClick();\n}\n\nfunction onFilterTitleButtonClick(event: MouseEvent) {\n  if (!isDesktop()) {\n    return;\n  }\n\n  // A click on a child element of a disabled button still reaches this handler in Chrome and\n  // Safari, so we manually enforce the disabled state instead of relying on the browser.\n  if (!(event.currentTarget instanceof HTMLButtonElement)) {\n    return;\n  }\n\n  if (event.currentTarget.disabled) {\n    return;\n  }\n\n  const target = event.target;\n\n  if (!(target instanceof HTMLElement)) {\n    return;\n  }\n\n  const name = target.dataset.name;\n  const tags = document.querySelector(`.collection-page .tags[data-name=\"${name}\"]`);\n  if (!tags) {\n    return;\n  }\n\n  if (target.getAttribute('aria-expanded') === 'true') {\n    tags.classList.remove('show');\n    target.setAttribute('aria-expanded', 'false');\n    target.setAttribute('aria-label', 'Expand');\n  } else {\n    tags.classList.add('show');\n    target.setAttribute('aria-expanded', 'true');\n    target.setAttribute('aria-label', 'Collapse');\n  }\n}\n\n/**\n * Opens the expanded view for one filter group.\n *\n * On narrow screens each group only shows the first few of its options, because the options sit in\n * a strip that scrolls sideways and most of them are off the end of it. So we let the shopper open\n * one group on its own, where we hide the other groups and let that group's options wrap down the\n * page instead of running off the side. {@link collapseExpandedView} is how they get back out.\n *\n * The desktop sidebar is wide enough to show every group at once, so none of this applies there and\n * the stylesheet hides the button that gets us here.\n */\nfunction onViewAllClick(event: MouseEvent) {\n  if (!(event.target instanceof HTMLElement)) {\n    return;\n  }\n\n  const targetContainer = event.target.closest('.filter');\n\n  const containers = document.querySelectorAll<HTMLElement>('.collection-page .filter');\n  for (const container of containers) {\n    if (container === targetContainer) {\n      container.classList.add('expanded-view');\n    } else {\n      container.hidden = true;\n    }\n  }\n\n  event.target.hidden = true;\n\n  const backButton = targetContainer.querySelector<HTMLButtonElement>('.back-button');\n  if (backButton) {\n    backButton.hidden = false;\n    backButton.addEventListener('click', collapseExpandedView);\n  }\n}\n\n/**\n * Puts every filter group back on screen alongside the others, closing the expanded view that\n * {@link onViewAllClick} opened.\n *\n * We run this on the Back button, and again whenever the window grows wide enough for the sidebar,\n * since an expanded view left open there would show one group and hide the rest in a layout with\n * room for all of them.\n */\nfunction collapseExpandedView() {\n  const filterContainers = document.querySelectorAll<HTMLElement>('.collection-page .filter');\n  for (const container of filterContainers) {\n    container.classList.remove('expanded-view');\n    container.hidden = false;\n  }\n\n  const viewAllButtons = document.querySelectorAll<HTMLButtonElement>('.collection-page .view-all');\n  for (const button of viewAllButtons) {\n    button.hidden = false;\n  }\n\n  const backButtons = document.querySelectorAll<HTMLButtonElement>('.collection-page .back-button');\n  for (const button of backButtons) {\n    button.hidden = true;\n  }\n}\n\n/**\n * Turns the filter group headings into working expand and collapse buttons, or takes that away.\n *\n * The sidebar starts every group collapsed and the heading is how a shopper opens one. The narrow\n * layout has no use for that, because there we show all of a group's options already, so we leave\n * the headings disabled and the shopper reaches the rest of the options through the expanded view.\n */\nfunction setTitleButtonsDisabled(disabled: boolean) {\n  const buttons = document.querySelectorAll<HTMLButtonElement>('.collection-page .title-button');\n  for (const button of buttons) {\n    button.disabled = disabled;\n  }\n}\n\nfunction onReady() {\n  const openButton = document.querySelector<HTMLElement>('.collection-page .filter-cta button');\n  if (openButton) {\n    openButton.addEventListener('click', onFilterModalOpenClick);\n  }\n\n  const closeElements = document.querySelectorAll<HTMLElement>(\n    '.collection-page .backdrop, .collection-page .close');\n\n  for (const element of closeElements) {\n    element.addEventListener('click', onFilterModalCloseClick);\n  }\n\n  if (isDesktop()) {\n    const titleButtons = document.querySelectorAll<HTMLElement>('.collection-page .title-button');\n    for (const titleButton of titleButtons) {\n      titleButton.addEventListener('click', onFilterTitleButtonClick);\n    }\n  }\n\n  const viewAllButtons = document.querySelectorAll<HTMLElement>('.collection-page .view-all');\n  for (const button of viewAllButtons) {\n    button.addEventListener('click', onViewAllClick);\n  }\n\n  const filters = document.querySelectorAll<HTMLElement>(\n    '.collection-page .tags > button[data-toggle]');\n  for (const filter of filters) {\n    filter.addEventListener('click', onFilterToggleClick);\n  }\n\n  const clearFilters = document.querySelector<HTMLElement>(\n    '.collection-page .modal .controls button[type=\"reset\"]');\n  clearFilters?.addEventListener('click', onClearFiltersClicked);\n\n  setTitleButtonsDisabled(!isDesktop());\n\n  addEventListener('resize', onResize, { passive: true });\n}\n\nfunction onResize(_event: UIEvent) {\n  if (isDesktop()) {\n    collapseExpandedView();\n    setTitleButtonsDisabled(false);\n  } else {\n    setTitleButtonsDisabled(true);\n  }\n}\n\nfunction isDesktop() {\n  return innerWidth >= 1024;\n}\n\nready(onReady);\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"],"names":["event","CustomEvent","detail","all_products_count","collection_page_section","collection","handle","id","products_count","title","url","dispatchEvent","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","onFilterModalOpenClick","_event","elements","document","querySelectorAll","element","hidden","onFilterModalCloseClick","onClearFiltersClicked","buttons","button","classList","remove","products","product","updateNoProductsFound","length","container","querySelector","add","visibleCount","message","shouldShowProductForFilterGroup","filters","tags","some","filter","includes","buildActiveFilterGroups","filterGroups","activeFilterGroups","filterGroup","groupName","textContent","selector","activeFilters","filterValue","dataset","toggle","split","push","onFilterToggleClick","target","HTMLButtonElement","groups","filtersActive","group","addEventListener","onApplyFiltersButtonClick","preventDefault","filterCount","Object","keys","reduce","acc","curr","filterCountDisplay","openButton","heading","cards","shownProducts","card","_card$dataset$tags","showCard","activeGroup","productSlot","selectedVariant","selectedVariantId","brand","image_url","mainImage","name","price","Math","floor","parseInt","product_id","shopify_product_id","shopify_variant_id","sku","resultsCount","activeFilter","type","value","bubbles","category","location","pathname","pop","applyGroups","onFilterTitleButtonClick","isDesktop","currentTarget","disabled","HTMLElement","getAttribute","setAttribute","onViewAllClick","targetContainer","closest","containers","backButton","collapseExpandedView","filterContainers","viewAllButtons","backButtons","setTitleButtonsDisabled","onResize","innerWidth","callback","readyState","timer","setTimeout","clearTimeout","ready","closeElements","titleButtons","titleButton","clearFilters","passive"],"sourceRoot":""}