{"version":3,"file":"Dropdown-3e56e6b3.js","sources":["../../../../src/js/utils/keycodes.js","../../../../src/js/utils/index.js","../../../../src/js/ui/dropdown.js","../../../../src/js/behaviours/Dropdown.js"],"sourcesContent":["export default {\n\tDELETE_KEY: 8,\n\tSHIFT_KEY: 16,\n\tCTRL_KEY: 17,\n\tALT_KEY: 18,\n\tRETURN_KEY: 13,\n\tESC_KEY: 27,\n\tSPACE_KEY: 32,\n\tLEFT_KEY: 37,\n\tUP_KEY: 38,\n\tRIGHT_KEY: 39,\n\tDOWN_KEY: 40,\n\tA_KEY: 65,\n\tS_KEY: 83,\n\tCMD_KEY: 91\n}\n","/**\n * @module utils/renderInTheLoop\n */\n\n/**\n * @function renderInTheLoop\n * @description fun with the event loop\n * @see https://www.youtube.com/watch?v=8aGhZQkoFbQ\n * @see https://www.youtube.com/watch?v=cCOL7MC4Pl0\n * @param {function} callback\n * @return {void}\n */\nexport function renderInTheLoop(callback) {\n\trequestAnimationFrame(() => {\n\t\trequestAnimationFrame(() => callback())\n\t})\n}\n\n/**\n * @module utils/getIdFromHref\n */\n\n/**\n * @function getIdFromHref\n * @param {HTMLElement} node\n * @return {string}\n */\nexport function getIdFromHref(node) {\n\t/**\n\t * get the href from the button\n\t *\n\t * @private\n\t * @type {String}\n\t */\n\tconst targetSelector = node.getAttribute('href')\n\n\t/**\n\t * remove the hash\n\t *\n\t * @private\n\t * @type {String}\n\t */\n\tconst id = targetSelector.split('#').pop()\n\n\treturn id\n}\n\nconst eventCache = {}\n\nexport function getEventName(event) {\n\tif (event !== 'transitionend' || event !== 'animationend') return event\n\n\tif (eventCache[event]) return eventCache[event]\n\n\tconst types =\n\t\tevent === 'transitionend'\n\t\t\t? {\n\t\t\t\tOTransition: 'oTransitionEnd',\n\t\t\t\tWebkitTransition: 'webkitTransitionEnd',\n\t\t\t\tMozTransition: 'transitionend',\n\t\t\t\ttransition: 'transitionend'\n\t\t\t}\n\t\t\t: {\n\t\t\t\tOAnimation: 'oAnimationEnd',\n\t\t\t\tWebkitAnimation: 'webkitAnimationEnd',\n\t\t\t\tMozAnimation: 'animationend',\n\t\t\t\tanimation: 'animationend'\n\t\t\t}\n\n\tconst elem = document.createElement('div')\n\n\tconst name = Object.keys(types).reduce(\n\t\t(prev, trans) => (undefined !== elem.style[trans] ? types[trans] : prev),\n\t\t''\n\t)\n\n\teventCache[event] = name\n\n\treturn name\n}\n\n","// @ts-check\n\nimport { eventBus } from '@spon/plugins'\nimport domEvents from '@spon/domevents'\nimport keycodes from '../utils/keycodes'\nimport { getIdFromHref } from '../utils'\n\n/**\n * @module ui/dropdown\n */\n\n/**\n * @function dropdown\n * @example\n * const dd = dropdown({ node: document.getElementById('btn'), name: 'user-menu' })\n * const html = document.documentElement\n *\n * dd.init()\n *\n * dd.on('user-menu:open', ({ target }) => {\n * \tif (html.classList.contains('user-is-tabbing')) {\n * \t\ttarget.querySelector('a').focus()\n * \t}\n * })\n *\n *
\n *\n * @param {Object} options\n * @property {HTMLElement} options.node - the root node, events are bound to this element\n * @property {String} options.name - a name to to use for events\n * @return {dropdownType}\n */\n\n/**\n * @typedef {Object} dropdownType\n * @property {function} dropdown.init - Bind the toggle events\n * @property {function} dropdown.destroy - Destroy the toggle events and reset any state\n * @property {function} dropdown.open - Open the toggle\n * @property {function} dropdown.close - Close the toggle\n * @property {function} dropdown.on - eventBus on event\n * @property {function} dropdown.off - eventBus off event\n * @property {function} dropdown.emit - eventBus emit event\n *\n */\n\nfunction dropdown({ node, name }) {\n\t/**\n\t * get the button\n\t *\n\t * @private\n\t * @type {HTMLElement}\n\t */\n\tconst button = node.querySelector('[data-dropdown-button]')\n\n\t/**\n\t * remove the hash\n\t *\n\t * @private\n\t * @type {String}\n\t */\n\tconst targetId = getIdFromHref(button)\n\n\t/**\n\t * get the target element\n\t *\n\t * @private\n\t * @type {HTMLElement}\n\t */\n\tconst target = document.getElementById(targetId)\n\n\t/**\n\t * get the items\n\t *\n\t * @private\n\t * @type {NodeListOf}\n\t */\n\tconst items = node.querySelectorAll('[data-dropdown-item]')\n\n\t/**\n\t * the current tabIndex\n\t *\n\t * @private\n\t * @type {number}\n\t */\n\tlet tabIndex = 0\n\n\t/**\n\t * a placeholder for the dom events container\n\t *\n\t * @private\n\t * @type {undefined|object}\n\t */\n\tlet events\n\n\ttarget.setAttribute('tabindex', '-1')\n\n\t/**\n\t * @function open\n\t * @memberOf dropdown\n\t * @inner\n\t * @return {void}\n\t */\n\tfunction open() {\n\t\ttarget.classList.add('is-open')\n\t\ttarget.focus()\n\t\tbutton.setAttribute('aria-expanded', 'true')\n\t\ttarget.setAttribute('aria-hidden', 'false')\n\t\teventBus.emit(`${name}:open`, { target, button })\n\t}\n\n\t/**\n\t * @function close\n\t * @memberOf dropdown\n\t * @inner\n\t * @return {void}\n\t */\n\tfunction close() {\n\t\ttabIndex = 0\n\t\ttarget.classList.remove('is-open')\n\t\tbutton.setAttribute('aria-expanded', 'false')\n\t\ttarget.setAttribute('aria-hidden', 'true')\n\t\teventBus.emit(`${name}:close`, { target, button })\n\t}\n\n\t/**\n\t * @function onBlur\n\t * @memberOf dropdown\n\t * @inner\n\t * @return {void}\n\t */\n\tfunction onBlur() {\n\t\tsetTimeout(() => {\n\t\t\tif (\n\t\t\t\t!target.contains(document.activeElement) &&\n\t\t\t\tdocument.activeElement !== button\n\t\t\t) {\n\t\t\t\tclose()\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * @function clickHandle\n\t * @memberOf dropdown\n\t * @inner\n\t * @param {Event} e -event object\n\t * @return {void}\n\t */\n\tfunction clickHandle(e) {\n\t\te.preventDefault()\n\n\t\tif (!target.classList.contains('is-open')) {\n\t\t\topen()\n\t\t} else {\n\t\t\tclose()\n\t\t}\n\t}\n\n\t/**\n\t * @function keyCodeAction\n\t * @memberOf dropdown\n\t * @inner\n\t * @param {Number} key the key code\n\t * @return {Function}\n\t */\n\tfunction keyCodeAction(key) {\n\t\treturn {\n\t\t\t[keycodes.ESC_KEY]: () => {\n\t\t\t\tclose()\n\t\t\t\tbutton.focus()\n\t\t\t},\n\n\t\t\t[keycodes.UP_KEY]: () => {\n\t\t\t\tif (tabIndex > 0) {\n\t\t\t\t\ttabIndex -= 1\n\t\t\t\t\titems[tabIndex].focus()\n\t\t\t\t} else {\n\t\t\t\t\ttabIndex = 0\n\t\t\t\t\tclose()\n\t\t\t\t\tbutton.focus()\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t[keycodes.DOWN_KEY]: () => {\n\t\t\t\tif (tabIndex < items.length - 1) {\n\t\t\t\t\ttabIndex += 1\n\t\t\t\t\titems[tabIndex].focus()\n\t\t\t\t}\n\t\t\t}\n\t\t}[key]\n\t}\n\n\t/**\n\t * @function init\n\t * @memberOf dropdown\n\t * @inner\n\t * @return {void}\n\t */\n\tfunction init() {\n\t\tevents = events || domEvents(node)\n\t\ttarget.setAttribute('tabindex', '-1')\n\t\ttarget.setAttribute('aria-hidden', 'true')\n\t\ttarget.setAttribute('role', 'dialog')\n\t\tbutton.setAttribute('aria-controls', targetId)\n\t\tbutton.setAttribute('aria-expanded', 'false')\n\n\t\tevents.addEvents({\n\t\t\t'click [data-dropdown-button]': clickHandle,\n\t\t\t'click [data-dropdown-item]': (e, elm) => {\n\t\t\t\teventBus.emit(`${name}:click`, { e, elm })\n\t\t\t},\n\t\t\t'blur [data-dropdown-menu]': [onBlur, true],\n\t\t\tkeydown: e => {\n\t\t\t\tconst action = keyCodeAction(e.keyCode)\n\t\t\t\tif (action) action()\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * @function destroy\n\t * @memberOf dropdown\n\t * @inner\n\t * @return {void}\n\t */\n\tfunction destroy() {\n\t\tevents.removeEvents()\n\t\teventBus.off(`${name}:click`)\n\t\ttarget.removeAttribute('tabindex')\n\t\ttarget.removeAttribute('aria-hidden')\n\t\ttarget.removeAttribute('role')\n\t\tbutton.removeAttribute('aria-controls')\n\t\tbutton.removeAttribute('aria-expanded')\n\t}\n\n\treturn {\n\t\tinit,\n\t\tdestroy,\n\t\topen,\n\t\tclose,\n\t\t...eventBus\n\t}\n}\n\nexport default dropdown\n","import uiDropdown from '../ui/dropdown'\n\nfunction Dropdown({ node }) {\n\tconst dd = uiDropdown({ node, name: 'film-dropdown' })\n\tconst html = document.documentElement\n\n\tdd.init()\n\n\tdd.on('user-menu:open', ({ target }) => {\n\t\tif (html.classList.contains('user-is-tabbing')) {\n\t\t\ttarget.querySelector('a').focus()\n\t\t}\n\t})\n\n\treturn () => {\n\t\tdd.destroy()\n\t}\n}\n\nexport default Dropdown\n"],"names":["keycodes","getIdFromHref","node","dropdown","name","button","targetId","target","items","tabIndex","events","open","eventBus","close","onBlur","clickHandle","e","keyCodeAction","key","init","domEvents","elm","action","destroy","Dropdown","dd","uiDropdown","html"],"mappings":"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"}