{"version":3,"sources":["webpack:///./src/js/helpers/index.js","webpack:///./src/js/constants.js","webpack:///./src/js/modules/modal.js"],"names":["isMobile","window","matchMedia","matches","isTabletLandscape","focusableElements","isDescendant","parent","child","node","parentNode","decodeEntity","str","ta","document","createElement","innerHTML","value","getSafeId","getRandomInt","min","max","Math","ceil","floor","random","sortFiltersBySitecore","unsortedFilters","sitecoreFilters","filtersInSitecore","filter","facet","indexOf","sortRemainingFilters","sort","a","b","toLowerCase","BREAKPOINTS","Object","freeze","mobile","tablet","tabletLandscape","desktop","moduleMax","wide","debounce","callback","wait","timerId","args","clearTimeout","setTimeout","KEYS","END","HOME","LEFT","UP","RIGHT","DOWN","ENTER","ESC","TAB","SPACE","KEYS_DIRECTION","37","38","39","40","Module","Component","this","dom","$modal","el","$trigger","_$","id","_$$","$closeButton","$backdrop","$content","$modalTitle","$modalSummary","$modalImage","$videoContainer","focusableModalElements","focusTrap","createFocusTrap","videoSrc","dataset","videoModalClass","_a","_b","_c","_on","handleBackdropClick","bind","closeModal","openModal","keyCode","e","target","currentTarget","handleKeydown","lastFocusedElement","activeElement","forEach","element","setAttribute","activate","length","focus","videoId","classList","add","remove","title","summary","src","image","alt","deactivate","getAttribute"],"mappings":"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","file":"40.9a429cc8ec32624cc00d.js?v=fe9d8e3725bdd7a10599","sourcesContent":["// /**\n// * Checks browser is running on a native mobile device\n// */\nexport const isMobileDevice = () => {\n const userAgent = navigator.userAgent || navigator.vendor || window.opera;\n\n return (\n /windows phone/i.test(userAgent) ||\n /android/i.test(userAgent) ||\n (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream)\n );\n};\n\n// /**\n// * Checks iOS user agent\n// */\nexport const iOS = () => {\n return (\n [\n 'iPad Simulator',\n 'iPhone Simulator',\n 'iPod Simulator',\n 'iPad',\n 'iPhone',\n 'iPod'\n ].includes(navigator.platform) ||\n (navigator.userAgent.includes('Mac') && 'ontouchend' in document)\n );\n};\n\n// /**\n// * Returns if media query matches mobile\n// */\nexport const isMobile = () => {\n return window.matchMedia('(max-width: 767px)').matches;\n};\n\n// /**\n// * Returns if media query matches tabletLandscape\n// */\nexport const isTabletLandscape = () => {\n return window.matchMedia('(max-width: 1023px)').matches;\n};\n\n// /**\n// * Returns the browser's scrollbar width\n// */\nexport const getScrollbarWidth = () => {\n return window.innerWidth - document.documentElement.clientWidth;\n};\n\n// /**\n// * Checks if an element is focusable\n// *\n// * @param {Object} el - HTML element you want to check if it's focusable\n// */\nexport const isFocusable = el => {\n if (\n el.tabIndex > 0 ||\n (el.tabIndex === 0 && el.getAttribute('tabIndex') !== null)\n ) {\n return true;\n }\n\n if (el.disabled) {\n return false;\n }\n\n /* eslint-disable indent */\n switch (el.nodeName) {\n case 'A':\n return !!el.href && el.rel !== 'ignore';\n case 'INPUT':\n return el.type !== 'hidden' && el.type !== 'file';\n case 'BUTTON':\n case 'SELECT':\n case 'TEXTAREA':\n return true;\n default:\n return false;\n }\n /* eslint-enable indent */\n};\n\n// /**\n// * FOCUSABLE ELEMENTS\n// */\nexport const focusableElements = [\n '[contenteditable]',\n '[tabindex]:not([tabindex^=\"-\"])',\n 'a[href]',\n 'area[href]',\n 'button:not([disabled]):not([aria-hidden])',\n 'embed',\n 'iframe',\n 'input:not([disabled]):not([type=\"hidden\"]):not([aria-hidden])',\n 'object',\n 'select:not([disabled]):not([aria-hidden])',\n 'textarea:not([disabled]):not([aria-hidden])'\n];\n\n// * Check if an element is outside the viewport\n// */\nexport const isOutOfViewport = elem => {\n // Get element's bounding\n const bounding = elem.getBoundingClientRect();\n\n // Check if it's out of the viewport on each side\n const out = {};\n out.top = bounding.top < 0;\n out.left = bounding.left < 0;\n out.bottom =\n bounding.bottom >\n (window.innerHeight || document.documentElement.clientHeight);\n out.right =\n bounding.right >\n (window.innerWidth || document.documentElement.clientWidth);\n out.any = out.top || out.left || out.bottom || out.right;\n out.all = out.top && out.left && out.bottom && out.right;\n\n return out;\n};\n\nexport const sameOrigin = (uri1, uri2 = false) => {\n if (uri1[0] === '/') return true;\n if (uri1[0] === '/' && uri2[0] === '/') return true;\n if (!uri2) uri2 = window.location.href;\n\n uri1 = new URL(uri1);\n uri2 = new URL(uri2);\n\n const host1 = uri1.hostname.split('www.')[1];\n const host2 = uri2.hostname.split('www.')[2];\n\n if (host1 !== host2) return false;\n if (uri1.port !== uri2.port) return false;\n\n return true;\n};\n\n// * Check if child is a descendant of parent\n// */\nexport const isDescendant = (parent, child) => {\n let node = child.parentNode;\n\n while(node) {\n if (node === parent) {\n return true;\n }\n\n node = node.parentNode;\n }\n\n return false;\n};\n\n// * Decode HTML entities\n// */\nexport const decodeEntity = str => {\n const ta = document.createElement('textarea');\n ta.innerHTML = str;\n return ta.value;\n};\n\n// * Returns a sanitized string to safely populate id parameters in HTML tags\n// */\nexport const getSafeId = str => {\n //return str.replace(/\\W/g, '_');\n return str;\n};\n\n// * Returns a random integer between min (inclusive) and max (inclusive).\n// */\nexport const getRandomInt = (min, max) => {\n min = Math.ceil(min);\n max = Math.floor(max);\n return Math.floor(Math.random() * (max - min + 1)) + min;\n};\n\nexport const sortFiltersBySitecore = (\n unsortedFilters,\n sitecoreFilters = []\n) => {\n const filtersInSitecore = unsortedFilters.filter(\n facet => sitecoreFilters.indexOf(facet.value) > -1\n );\n\n const remainingFilters = unsortedFilters.filter(\n facet => sitecoreFilters.indexOf(facet.value) === -1\n );\n\n const sortRemainingFilters = remainingFilters.sort((a, b) => {\n if (a.value.toLowerCase() > b.value.toLowerCase()) {\n return 1;\n }\n return -1;\n });\n\n const filtersInSitecoreOrdered = filtersInSitecore.sort(\n (a, b) =>\n sitecoreFilters.indexOf(a.value) - sitecoreFilters.indexOf(b.value)\n );\n\n return [...filtersInSitecoreOrdered, ...sortRemainingFilters];\n};\n\nexport const BREAKPOINTS = Object.freeze({\n mobile: 361,\n tablet: 769,\n tabletLandscape: 1025,\n desktop: 1281,\n moduleMax: 1251,\n wide: 1601\n});\n\nexport const debounce = (callback, wait) => {\n let timerId;\n return (...args) => {\n clearTimeout(timerId);\n timerId = setTimeout(() => {\n callback(...args);\n }, wait);\n };\n};\n","export const KEYS = {\n END: 35,\n HOME: 36,\n LEFT: 37,\n UP: 38,\n RIGHT: 39,\n DOWN: 40,\n ENTER: 13,\n ESC: 27,\n TAB: 9,\n SPACE: 32\n};\n\nexport const KEYS_DIRECTION = {\n 37: -1,\n 38: -1,\n 39: 1,\n 40: 1\n};\n","import { Component } from '@verndale/core';\nimport { createFocusTrap } from 'focus-trap';\nimport { focusableElements } from '../helpers';\nimport { KEYS } from '../constants';\n\nclass Module extends Component {\n setupDefaults() {\n this.dom = {\n $modal: this.el,\n $trigger:\n document._$(`[data-trigger-modal=\"${this.el.id}\"]`) ||\n document._$$('.gallery-row__content-button'),\n $closeButton: this.el._$('.modal__close-button'),\n $backdrop: this.el._$('.modal__backdrop'),\n $content: this.el._$('.modal__content'),\n $modalTitle: this.el._$('.modal__title'),\n $modalSummary: this.el._$('.modal__summary'),\n $modalImage: this.el._$('.modal__content-image'),\n $videoContainer: this.el._$('.modal .video__container')\n };\n\n this.focusableModalElements = this.el._$$(focusableElements);\n this.focusTrap = createFocusTrap(this.el);\n this.videoSrc = this.el.dataset.videoSrc;\n this.videoModalClass = 'modal--video';\n }\n\n addListeners() {\n this.dom.$backdrop?._on('click', this.handleBackdropClick.bind(this));\n this.dom.$closeButton?._on('click', this.closeModal.bind(this));\n this.dom.$trigger?._on('click', this.openModal.bind(this));\n }\n\n handleKeydown({ keyCode }) {\n if (keyCode === KEYS.ESC) {\n this.closeModal();\n }\n }\n\n handleBackdropClick(e) {\n if (e.target === this.dom.$backdrop) {\n this.closeModal();\n }\n }\n\n openModal(e) {\n const dataset = e.currentTarget.dataset;\n\n this.el._on('keydown', this.handleKeydown.bind(this));\n this.lastFocusedElement = document.activeElement;\n this.focusableModalElements?.forEach(element =>\n element.setAttribute('tabindex', '1')\n );\n this.el.setAttribute('aria-hidden', 'false');\n this.focusTrap.activate();\n\n if (this.focusableModalElements?.length) {\n if (this.focusableModalElements[0] !== this.dom.$closeButton)\n this.focusableModalElements[0].focus();\n }\n\n dataset.videoId\n ? this.dom.$modal.classList.add(this.videoModalClass)\n : this.dom.$modal.classList.remove(this.videoModalClass);\n\n this.dom.$modalTitle.innerHTML = dataset.title;\n this.dom.$modalSummary.innerHTML = dataset.summary;\n\n if (dataset.videoId) {\n this.dom.$videoContainer.setAttribute('data-video-id', dataset.videoId);\n } else {\n this.dom.$modalImage.src = ''; // clear previous image\n this.dom.$modalImage.src = dataset.image;\n this.dom.$modalImage.setAttribute('alt', dataset.alt);\n }\n }\n\n closeModal() {\n this.focusTrap.deactivate();\n this.el.setAttribute('aria-hidden', 'true');\n\n const iframe = this.el._$('iframe');\n\n if (iframe.getAttribute('title') !== 'reCAPTCHA') {\n this.el._$('iframe')?.remove();\n }\n\n if (this.lastFocusedElement) this.lastFocusedElement.focus();\n }\n}\n\nexport default Module;\n"],"sourceRoot":""}