{
  "version": 3,
  "sources": ["/cdn/shop/t/4/assets/sf-center-carousel.js?x=18441"],
  "sourcesContent": ["// Endless scroll-snap carousel. The card closest to the center is active.\n// Clicking a side card slides it to the center; after each scroll the cards are\n// rotated (first to last or last to first) so the active card always has neighbours.\nclass SfCenterCarousel extends HTMLElement {\n  connectedCallback() {\n    this.track = this.querySelector('[data-carousel-track]');\n    this.items = [...this.querySelectorAll('[data-carousel-item]')];\n    if (!this.track || !this.items.length) return;\n\n    this.track.addEventListener('scroll', () => {\n      if (!this.frame) {\n        this.frame = requestAnimationFrame(() => {\n          this.frame = null;\n          this.update();\n        });\n      }\n      // Fallback for browsers without the scrollend event. Where scrollend exists\n      // this timer must not run: a slow frame mid-scroll would rebalance early\n      // and make the slide jump.\n      if ('onscrollend' in window) return;\n      clearTimeout(this.settleTimer);\n      this.settleTimer = setTimeout(() => this.rebalance(), 150);\n    }, { passive: true });\n    this.track.addEventListener('scrollend', () => this.rebalance());\n\n    this.track.addEventListener('click', (event) => {\n      const item = event.target.closest('[data-carousel-item]');\n      if (!item || item === this.active) return;\n      event.preventDefault();\n      this.pauseHover();\n      // Rebalancing mid-slide would cancel the slide, so hold it until the card\n      // arrives (or a second has passed, if the slide was interrupted).\n      this.sliding = item;\n      clearTimeout(this.slideTimer);\n      this.slideTimer = setTimeout(() => {\n        this.sliding = null;\n        this.rebalance();\n      }, 1000);\n      this.makeRoom(item);\n      this.center(item, 'smooth');\n    });\n    window.addEventListener('resize', () => this.center(this.active, 'instant'));\n\n    this.center(this.items[this.middleIndex()], 'instant');\n  }\n\n  // The clicked card slides under the cursor; hold its hover state until the\n  // mouse actually moves (scrolling fires mousemove events with no movement).\n  pauseHover() {\n    this.setAttribute('data-hover-paused', '');\n    const resume = (event) => {\n      if (event.type === 'pointermove' && !event.movementX && !event.movementY) return;\n      this.removeAttribute('data-hover-paused');\n      this.removeEventListener('pointermove', resume);\n      this.removeEventListener('pointerleave', resume);\n    };\n    this.addEventListener('pointermove', resume);\n    this.addEventListener('pointerleave', resume);\n  }\n\n  // An end card can't scroll to the centre (nothing beyond it), e.g. the single\n  // left card when there's an even number of cards. Move a card from the other\n  // end next to it first, keeping the same picture on screen.\n  makeRoom(item) {\n    if (item === this.track.firstElementChild) this.track.prepend(this.track.lastElementChild);\n    else if (item === this.track.lastElementChild) this.track.append(this.track.firstElementChild);\n    else return;\n    this.track.scrollTo({ left: this.offsetFor(this.active), behavior: 'instant' });\n  }\n\n  middleIndex() {\n    return Math.floor((this.track.children.length - 1) / 2);\n  }\n\n  offsetFor(item) {\n    return item.offsetLeft - this.track.offsetLeft - (this.track.clientWidth - item.offsetWidth) / 2;\n  }\n\n  center(item, behavior) {\n    if (!item) return;\n    this.track.scrollTo({ left: this.offsetFor(item), behavior });\n    this.update();\n  }\n\n  // Move cards from one end to the other so the active card sits in the middle\n  // of the list, keeping the same picture on screen.\n  rebalance() {\n    clearTimeout(this.settleTimer);\n    if (this.sliding) {\n      if (Math.abs(this.track.scrollLeft - this.offsetFor(this.sliding)) > 2) return;\n      this.sliding = null;\n      clearTimeout(this.slideTimer);\n    }\n    const cards = this.track.children;\n    const mid = this.middleIndex();\n    let index = [...cards].indexOf(this.active);\n    if (index === mid || index < 0) return;\n\n    while (index > mid) {\n      this.track.append(cards[0]);\n      index--;\n    }\n    while (index < mid) {\n      this.track.prepend(cards[cards.length - 1]);\n      index++;\n    }\n    this.track.scrollTo({ left: this.offsetFor(this.active), behavior: 'instant' });\n  }\n\n  update() {\n    const mid = this.track.scrollLeft + this.track.clientWidth / 2;\n    const distance = (item) => Math.abs(item.offsetLeft - this.track.offsetLeft + item.offsetWidth / 2 - mid);\n    const best = this.items.reduce((a, b) => (distance(b) < distance(a) ? b : a));\n    if (best === this.active) return;\n    this.active?.classList.remove('is-active');\n    best.classList.add('is-active');\n    this.active = best;\n  }\n}\n\nif (!customElements.get('sf-center-carousel')) customElements.define('sf-center-carousel', SfCenterCarousel);\n"],
  "mappings": "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",
  "names": []
}
