const findFocusable = (element: any, programmatic = false) => { if (!element) { return null } if (programmatic) { return element.querySelectorAll(`*[tabindex="-1"]`) } return element.querySelectorAll(`a[href]:not([tabindex="-1"]), area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex]:not([tabindex="-1"]), *[contenteditable]`) } let onKeyDown: any const bind = (el: any, { value = true }) => { if (value) { let focusable = findFocusable(el) let focusableProg = findFocusable(el, true) if (focusable && focusable.length > 0) { onKeyDown = (event: any) => { // Need to get focusable each time since it can change between key events // ex. changing month in a datepicker focusable = findFocusable(el) focusableProg = findFocusable(el, true) const firstFocusable = focusable[0] const lastFocusable = focusable[focusable.length - 1] if (event.target === firstFocusable && event.shiftKey && event.key === 'Tab') { event.preventDefault() lastFocusable.focus() } else if ((event.target === lastFocusable || Array.from(focusableProg).indexOf(event.target) >= 0) && !event.shiftKey && event.key === 'Tab') { event.preventDefault() firstFocusable.focus() } } el.addEventListener('keydown', onKeyDown) } } } const unbind = (el: any) => { el.removeEventListener('keydown', onKeyDown) } const directive = { beforeMount: bind, beforeUnmount: unbind, } export default directive