{
  "version": 3,
  "sources": ["/cdn/shop/t/350/assets/ncd-rebuy-carousel.js?cb=1793994768392"],
  "sourcesContent": ["/* The arrows on Must Haves, the Rebuy strip in the cart drawer.\n\n   Kept apart from js--new-cart-drawer.js so that file stays the drawer, and\n   from new-cart-drawer-wiring.js so that one stays the argument with the\n   rest of the theme. This is one widget's carousel.\n\n   Why it exists\n   -------------\n   Rebuy has widget 139397 configured as a one-column carousel, and the\n   drawer's stylesheet lays its cards out three across at 168px. Splide is\n   told the first and draws the second, so its page model does not describe\n   what is on screen: it believes six slides of 528px, while the track holds\n   six of 180px. Clicking the right arrow asks it to travel a page, the\n   browser clamps that to the end of the real content, and from the start it\n   went\n\n     -360, -540, -540, -540, 0\n\n   -- two dead clicks at the end with the arrow still looking live, and then\n   a jump back to the first card, which is Splide's rewind firing because by\n   its own count it had run out of slides. Both of the things reported.\n\n   What this does\n   --------------\n   Takes the two arrows off Splide and moves the track itself, one card at a\n   time, clamped to the content. Splide never sees the click, so it never\n   rewinds; the travel is measured from the DOM, so it stops where the cards\n   actually stop; and the arrows carry `disabled` at each end, which the\n   stylesheet already dims.\n\n   Dragging is left to Splide. It keeps its own index and writes its own\n   transform, and the next arrow press reads the position off the element\n   rather than off a number kept here, so the two stay in step. */\n(function () {\n  if (window.NcdRebuyCarousel) return;\n\n  var WIDGET = '[data-ncd-rebuy]';\n  var ARROW = '.rebuy-carousel__arrow';\n\n  function parts(el) {\n    var widget = el.closest(WIDGET);\n    if (!widget || !widget.closest('.cart-drawer')) return null;\n\n    var list = widget.querySelector('.splide__list');\n    var track = widget.querySelector('.splide__track');\n    if (!list || !track) return null;\n\n    return {\n      widget: widget,\n      list: list,\n      track: track,\n      prev: widget.querySelector('.rebuy-carousel__arrow--prev'),\n      next: widget.querySelector('.rebuy-carousel__arrow--next'),\n    };\n  }\n\n  /* How far the track has travelled, as a positive number, read off the\n     element rather than remembered -- Splide writes this too, when the\n     shopper drags, and this has to see that. */\n  function travelled(list) {\n    var found = /translateX\\((-?[\\d.]+)px\\)/.exec(list.style.transform || '');\n    if (found) return -parseFloat(found[1]);\n\n    var matrix = getComputedStyle(list).transform;\n    var numbers = /matrix\\(([^)]+)\\)/.exec(matrix);\n    return numbers ? -parseFloat(numbers[1].split(',')[4]) : 0;\n  }\n\n  /* Where the cards actually start, as the browser laid them out.\n\n     This used to travel by a step -- one card's width plus its gap,\n     rounded -- and snap to multiples of it. On the pane that is exact; on\n     a phone it is not. The card is a fraction of the row rather than a\n     round number, so the real pitch is something like 176.34 and the step\n     was 176, and every press left a third of a pixel behind. Three\n     presses in, the card no longer lined up with the edge of the track or\n     with the arrows above it, which is what QA saw on the device and not\n     in any emulator.\n\n     offsetLeft is where the browser put the card, fractions and all, so\n     there is nothing to accumulate. Relative to the first card, because\n     the list may carry padding of its own.\n\n     Every stop is a card's edge, the last one included. The strip does\n     not divide into whole cards -- six 176s in a 355 track leaves 693 of\n     travel, which is 11 short of the fifth card -- and stopping at 693\n     would leave a sliver of the previous card against the left edge of\n     the track while the arrows above it sit flush. That sliver is the\n     thing QA is looking at. Going the extra 11 to the card instead costs\n     nothing: on a peek layout the right-hand card is meant to run off the\n     edge, and from there the rest of the strip is on screen anyway, so\n     the arrow still goes out in the right place.\n\n     The fallback at the end is for a card wider than the track, where no\n     card edge reaches the end of the content. */\n  function stops(p) {\n    var slides = p.widget.querySelectorAll('.splide__slide');\n    if (!slides.length) return [0];\n\n    var base = slides[0].offsetLeft;\n    var end = furthest(p);\n    var out = [];\n\n    for (var i = 0; i < slides.length; i++) {\n      var at = slides[i].offsetLeft - base;\n      out.push(at);\n      if (at >= end) break;\n    }\n    if (out[out.length - 1] < end) out.push(end);\n    return out;\n  }\n\n  /* How far there is left to go, measured from the last card's own right\n     edge rather than from the list's scroll width.\n\n     scrollWidth counts the gap the stylesheet puts after every card,\n     including the last one, so it reported more pixels of travel than\n     there were cards to show: the strip reached its final card with the\n     right arrow still live, and one more press crawled those last few\n     pixels before it gave up. Measuring the card ignores the trailing gap,\n     and ignores any padding either side, so the arrow goes out exactly\n     when the last card comes flush with the edge of the track. */\n  function furthest(p) {\n    var slides = p.widget.querySelectorAll('.splide__slide');\n    var last = slides[slides.length - 1];\n    if (!last) return Math.max(0, p.list.scrollWidth - p.track.clientWidth);\n\n    /* offsetLeft, not a client rect. A rect read while the track is easing\n       to its new position reports where the card is at that instant, so the\n       end came out a card too far and the arrow stayed live for one press\n       after the last card had already landed. offsetLeft is a layout value:\n       the transform does not touch it, and it is the same before, during\n       and after the slide. */\n    var contentEnd = last.offsetLeft + last.offsetWidth - slides[0].offsetLeft;\n    return Math.max(0, contentEnd - p.track.clientWidth);\n  }\n\n  /* Written only when it changes. Setting `disabled` to what it already is\n     still reflects to the attribute, and the observer below would see that\n     as a reason to run again. */\n  function state(arrow, off) {\n    if (arrow && arrow.disabled !== off) arrow.disabled = off;\n  }\n\n  function mark(p, at) {\n    var end = furthest(p);\n    state(p.prev, at <= 1);\n    /* Both ends at once when everything already fits: there is nowhere to go\n       in either direction, and an arrow that looks live is the complaint\n       this started from. */\n    state(p.next, end <= 1 || at >= end - 1);\n  }\n\n  /* One card along, in whichever direction. The position is read off the\n     element rather than remembered, so a drag Splide handled itself is\n     where this carries on from. */\n  function move(p, dir) {\n    var list = stops(p);\n    var now = travelled(p.list);\n\n    var i = 0;\n    var best = Infinity;\n    for (var k = 0; k < list.length; k++) {\n      var away = Math.abs(list[k] - now);\n      /* Ties go to the earlier stop, which is the one the shopper is\n         looking at when a drag has left the strip between two. */\n      if (away < best - 0.5) { best = away; i = k; }\n    }\n\n    var at = list[Math.min(list.length - 1, Math.max(0, i + dir))];\n    p.list.style.transform = 'translateX(' + -at + 'px)';\n    mark(p, at);\n  }\n\n  /* Capture, so Splide's own handler on the arrow never runs. That is what\n     stops the rewind: the wrap is Splide's answer to a click it no longer\n     has a slide for, and it is not asked. */\n  document.addEventListener(\n    'click',\n    function (event) {\n      var arrow = event.target.closest && event.target.closest(ARROW);\n      if (!arrow) return;\n\n      var p = parts(arrow);\n      if (!p) return; /* a Rebuy carousel somewhere else on the page */\n\n      event.preventDefault();\n      event.stopImmediatePropagation();\n\n      if (arrow.disabled) return;\n      move(p, arrow.classList.contains('rebuy-carousel__arrow--prev') ? -1 : 1);\n    },\n    true\n  );\n\n  /* The state the arrows should be in before anything is clicked: at the\n     start, so the left one is already dim. Rebuy renders asynchronously and\n     re-renders on its own, so this is driven by the markup arriving rather\n     than by a moment we would have to guess. */\n  function sync() {\n    document.querySelectorAll('.cart-drawer ' + WIDGET).forEach(function (widget) {\n      var p = parts(widget.querySelector(ARROW) || widget);\n      if (p && p.track.clientWidth) mark(p, travelled(p.list));\n    });\n  }\n\n  var pending = null;\n  function syncSoon() {\n    clearTimeout(pending);\n    pending = setTimeout(sync, 60);\n  }\n\n  /* Every .cart-drawer, not the first one. The theme still carries the old\n     drawer's empty #CartDrawer, and it comes first in the document -- so a\n     single querySelector watched a dead element and nothing here ever ran.\n     That is what left the left arrow live on a strip sitting at its first\n     card. */\n  function watch() {\n    var drawers = document.querySelectorAll('.cart-drawer');\n    if (!drawers.length) return false;\n\n    drawers.forEach(function (drawer) {\n      /* Rebuy rendering, and the drawer re-rendering around it. */\n      new MutationObserver(syncSoon).observe(drawer, { childList: true, subtree: true });\n\n      /* And the drawer opening, which is a class on the drawer itself and\n         not a change to anything inside it. It matters because a strip in a\n         closed drawer has no width to measure, so mark() leaves it alone\n         and something has to ask again once it has one. */\n      new MutationObserver(syncSoon).observe(drawer, {\n        attributes: true,\n        attributeFilter: ['class', 'hidden'],\n      });\n    });\n\n    window.addEventListener('resize', syncSoon);\n    syncSoon();\n    return true;\n  }\n\n  if (!watch()) {\n    /* The section can render after this file runs. */\n    var waiting = new MutationObserver(function () {\n      if (watch()) waiting.disconnect();\n    });\n    waiting.observe(document.documentElement, { childList: true, subtree: true });\n  }\n\n  window.NcdRebuyCarousel = { sync: sync };\n})();\n"],
  "mappings": "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",
  "names": []
}
