{"version":3,"file":"js/366-7ac7c68e8f03ad24946c.chunk.js","mappings":"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","sources":["webpack://endrun/./app/javascript/app/stream/topshelf.js"],"sourcesContent":["// local\nimport { trackEvent } from '../analytics/helpers.js';\nimport { setStyle } from '../util/dom.js';\n\n/**\n *\n * @param {string} query\n * @param {() => void} callback\n */\nfunction onMatchMedia(query, callback) {\n // create our media query\n const mediaQueryList = window.matchMedia(query);\n\n // set up our change function\n function onChange() {\n if (mediaQueryList.matches) {\n callback();\n }\n }\n\n // listen for changes\n mediaQueryList.addEventListener('change', onChange);\n\n // call our callback immediately if the media query is already active\n onChange();\n}\n\n/**\n * @param {Element} el\n * @param {number} delta\n */\nexport function updateScrollPosition(el, delta) {\n el.scrollLeft = el.scrollLeft + delta;\n}\n\n/**\n * @param {Element} el\n */\nfunction getDimension(el) {\n const { left, right, width } = el.getBoundingClientRect();\n\n return {\n start: Math.round(left),\n end: Math.round(right),\n length: Math.round(width),\n };\n}\n\n/**\n * @param {Element} container\n * @param {Element} el\n * @param {boolean} [immediate]\n */\nfunction scrollContainerToElement(container, el, immediate = false) {\n const snapOffset = getDimension(el).start;\n const scrollOffset = getDimension(container).start;\n const delta = Math.round(snapOffset - scrollOffset);\n\n if (immediate) {\n setStyle(container, 'scroll-behavior', 'auto');\n } else {\n setStyle(container, 'scroll-behavior', 'smooth');\n }\n updateScrollPosition(container, delta);\n\n if (immediate) {\n setStyle(container, 'scroll-behavior', 'smooth');\n }\n}\n\n/**\n * @param {Element} container\n * @param {number} current\n * @param {number} max\n */\nfunction updateNavCircles(container, current, max) {\n const circlesContainer = container.querySelector('.nav-circles');\n const dots = circlesContainer.querySelectorAll('.nav-dot');\n const numberOfDots = dots.length;\n const diff = max - numberOfDots;\n const shouldAddDots = diff > 0;\n\n for (let i = 0; i < Math.abs(diff); i++) {\n if (shouldAddDots) {\n const dot = document.createElement('div');\n dot.classList.add('nav-dot');\n circlesContainer.appendChild(dot);\n } else {\n circlesContainer.removeChild(circlesContainer.lastChild);\n }\n }\n\n // query again to pick up any new dots\n circlesContainer.querySelectorAll('.nav-dot').forEach((dot, index) => {\n if (index === current) {\n dot.classList.add('active');\n } else {\n dot.classList.remove('active');\n }\n });\n}\n\n/**\n * @param {number} slideIndex\n * @param {number} numberOfDots\n * @param {Element} leftArrow\n * @param {Element} rightArrow\n */\nfunction updateArrows(slideIndex, numberOfDots, leftArrow, rightArrow) {\n if (slideIndex === 0) {\n leftArrow.classList.remove('active');\n } else {\n leftArrow.classList.add('active');\n }\n\n if (slideIndex === numberOfDots - 1) {\n rightArrow.classList.remove('active');\n } else {\n rightArrow.classList.add('active');\n }\n}\n\nfunction setup(/** @type {Element} */ container) {\n const placement = container.getAttribute('data-placement');\n const label = container.getAttribute('data-default-tab');\n\n container.addEventListener('tmp_hotzone_will_appear', () => {\n trackEvent('topshelf', 'view', label);\n });\n\n container.addEventListener('click', (event) => {\n if (event.target.matches('a')) {\n trackEvent('topshelf', 'item-click', label);\n }\n });\n\n const scrollContainer = container.querySelector('ul');\n const scrollItems = scrollContainer.querySelectorAll('li');\n const numberOfItems = scrollItems.length;\n let numberVisible = 4;\n let numberOfDots = Math.ceil(numberOfItems / numberVisible);\n let slideIndex = 0;\n\n const leftArrowButton = container.querySelector('.left-arrow');\n const rightArrowButton = container.querySelector('.right-arrow');\n\n function updateNumberOfVisibleSlides(/** @type {number} */ amount) {\n // set the number of visible slides for this shelf\n numberVisible = amount;\n // update the number of dots for this shelf\n numberOfDots = Math.ceil(numberOfItems / numberVisible);\n // modify the visible dots to match the new number of dots\n updateNavCircles(container, slideIndex, numberOfDots);\n // check if arrows need to be enabled/disabled as a result\n updateArrows(slideIndex, numberOfDots, leftArrowButton, rightArrowButton);\n // make sure the visible number of items is correct\n scrollItems.forEach((item) => {\n setStyle(item, 'flex', `0 0 ${100 / numberVisible}%`);\n });\n // immediately scroll to the right location based on the updates\n scrollContainerToElement(\n scrollContainer,\n scrollItems[slideIndex * numberVisible],\n true\n );\n }\n\n onMatchMedia('(max-width: 600px)', () => updateNumberOfVisibleSlides(1));\n onMatchMedia('(min-width: 601px) and (max-width: 800px)', () =>\n updateNumberOfVisibleSlides(2)\n );\n onMatchMedia('(min-width: 801px) and (max-width: 1140px)', () =>\n updateNumberOfVisibleSlides(3)\n );\n onMatchMedia('(min-width: 1141px)', () => updateNumberOfVisibleSlides(4));\n\n leftArrowButton.addEventListener('click', () => {\n slideIndex = Math.max(slideIndex - 1, 0);\n scrollContainerToElement(\n scrollContainer,\n scrollItems[slideIndex * numberVisible]\n );\n updateNavCircles(container, slideIndex, numberOfDots);\n updateArrows(slideIndex, numberOfDots, leftArrowButton, rightArrowButton);\n trackEvent(`topshelf:${placement}`, 'left_arrow');\n });\n\n rightArrowButton.addEventListener('click', () => {\n slideIndex = Math.min(slideIndex + 1, numberOfDots - 1);\n scrollContainerToElement(\n scrollContainer,\n scrollItems[slideIndex * numberVisible]\n );\n updateNavCircles(container, slideIndex, numberOfDots);\n updateArrows(slideIndex, numberOfDots, leftArrowButton, rightArrowButton);\n trackEvent(`topshelf:${placement}`, 'right_arrow');\n });\n\n window.addEventListener('resize', () => {\n scrollContainerToElement(\n scrollContainer,\n scrollItems[slideIndex * numberVisible],\n true\n );\n });\n}\n\nfunction initialize() {\n const shelfElements = document.querySelectorAll(\n '.topshelf, .topshelf-collection'\n );\n\n shelfElements.forEach((element) => {\n setup(element);\n });\n}\n\ninitialize();\n"],"names":["onMatchMedia","query","callback","mediaQueryList","window","matchMedia","onChange","matches","addEventListener","updateScrollPosition","el","delta","scrollLeft","getDimension","left","right","width","getBoundingClientRect","start","Math","round","end","length","scrollContainerToElement","container","immediate","snapOffset","scrollOffset","updateNavCircles","current","max","circlesContainer","querySelector","diff","querySelectorAll","shouldAddDots","i","abs","dot","document","createElement","classList","add","appendChild","removeChild","lastChild","forEach","index","remove","updateArrows","slideIndex","numberOfDots","leftArrow","rightArrow","element","placement","getAttribute","label","event","target","scrollContainer","scrollItems","numberOfItems","numberVisible","ceil","leftArrowButton","rightArrowButton","updateNumberOfVisibleSlides","amount","item","min","setup"],"sourceRoot":""}