deep-focus-trap
Version:
A focus trap library that pierces that shadow dom. So you can use it with native web components. Deep Focus Trap is a lightweight library written in vanilla js with only one dependency (that is tree-shakable if not in use).
47 lines (42 loc) • 2.38 kB
JavaScript
import { querySelectorAll } from 'shadow-dom-utils'
import { focusTrap } from './focus-trap'
/**
* @description Used as a focus trap that can pierce the shadow dom. Meaning if you are using native
* web components and you have a component within a component. This focus trap will be able to peirce through the shadow dom and make a focus trap
* out of the child components as well.
*
*/
class deepFocusTrap extends focusTrap {
/**
* @param {object} config
* @param {string | HTMLElement} config.el - A selector or element used to trap focus within
* @param {boolean} [config.returnFocus=true] - An option when set to true returns focus upon deactivation to the last element that had focus before the trap was activated. Defaults to true.
* @param {HTMLElement} [config.focusElement] - An element to focus on as soon as the focus trap is activated.
* @param {boolean} [config.deep=true] - When set to false focusTrap will not peirce the shadowDOM.
* @param {callback} [config.escCallback] - A callback to be called when the user presses the escape key.
* @param {boolean} [config.includeActiveElement=false] - Includes element currently in focus when focusTrap is activated within the focusable elements.
* @param {boolean} [config.unordered=false] - Allows for elements to be in an order in the dom. Then follows the order of appearance in the focusableElements array instead.
*/
constructor(config) {
super(config)
this.deep = config.deep ?? true
}
/**
* Set the elements to cycle focus on within the focus trap. Uses the
* config.el selector to get its focusable children or takes a custom list of elements to cycle focus on.
*
* @param {HTMLElement[] | NodeList} [els] An array of elements or Nodelist of the elements to cycle through in the focus trap.
*/
setElements(els) {
if (this.deep === false) {
this.focusableElements = els ?? this.el.querySelectorAll(this.FOCUSABLE_ELEMENT_SELECTORS)
} else {
this.focusableElements = els ?? querySelectorAll(this.FOCUSABLE_ELEMENT_SELECTORS, this.el)
}
this.firstFocusableEl = this.focusableElements[0]
this.lastFocusableEl = this.focusableElements[this.focusableElements.length - 1]
this.elementToFocus = this.focusElement ? this.focusElement : this.firstFocusableEl
this.setReturnFocusEl()
}
}
export { deepFocusTrap }