UNPKG

igniteui-webcomponents

Version:

Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.

144 lines 4.62 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { LitElement, css, html, nothing } from 'lit'; import { property, state } from 'lit/decorators.js'; import { registerComponent } from '../common/definitions/register.js'; import { isDefined } from '../common/util.js'; class IgcFocusTrapComponent extends LitElement { static register() { registerComponent(IgcFocusTrapComponent); } get focused() { return this._focused; } get focusableElements() { return Array.from(getFocusableElements(this)); } constructor() { super(); this._focused = false; this.disabled = false; this.addEventListener('focusin', this.onFocusIn); this.addEventListener('focusout', this.onFocusOut); } onFocusIn() { this._focused = true; } onFocusOut() { this._focused = false; } focusFirstElement() { this.focusableElements.at(0)?.focus(); } focusLastElement() { this.focusableElements.at(-1)?.focus(); } render() { const tabStop = !this.focused || this.disabled ? -1 : 0; return html ` <div id="start" tabindex=${tabStop} @focus=${this.disabled ? nothing : this.focusLastElement} ></div> <slot></slot> <div id="end" tabindex=${tabStop} @focus=${this.disabled ? nothing : this.focusFirstElement} ></div> `; } } IgcFocusTrapComponent.tagName = 'igc-focus-trap'; IgcFocusTrapComponent.styles = css ` :host { display: contents; } `; export default IgcFocusTrapComponent; __decorate([ state() ], IgcFocusTrapComponent.prototype, "_focused", void 0); __decorate([ property({ type: Boolean, reflect: true }) ], IgcFocusTrapComponent.prototype, "disabled", void 0); const defaultSelectors = [ '[tabindex]', 'a[href]', 'button', 'input', 'select', 'textarea', ]; function isHidden(node) { return (node.hasAttribute('hidden') || node.hasAttribute('inert') || (node.hasAttribute('aria-hidden') && node.getAttribute('aria-hidden') !== 'false')); } function isDisabled(node) { return node.hasAttribute('disabled') || node.hasAttribute('inert'); } function isContentEditable(node) { return (node.hasAttribute('contenteditable') && node.getAttribute('contenteditable') !== 'false'); } function isFocusable(node) { if (isHidden(node) || isDisabled(node)) { return false; } if (isContentEditable(node)) { return true; } if (node.tabIndex === -1) { return false; } return defaultSelectors.some((selector) => node.matches(selector)); } function shouldSkipElements(node, cache) { const element = node; return isHidden(element) || isDisabled(element) || cache?.has(element) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT; } function getSlottedElements(node) { const slot = node; const elements = slot.assignedElements(); return { elements, parent: elements.at(0)?.parentElement }; } function* getFocusableElements(root, cache) { if (!isDefined(globalThis.document)) { return; } let node; const _cache = cache ?? new WeakSet(); const visitor = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, (node) => shouldSkipElements(node, _cache)); while ((node = visitor.nextNode())) { if (_cache.has(node)) { continue; } if (node.shadowRoot) { yield* getFocusableElements(node.shadowRoot, _cache); continue; } if (node.tagName === 'SLOT') { const { elements, parent } = getSlottedElements(node); if (elements.length > 0) { for (const element of elements) { yield* getFocusableElements(parent, _cache); _cache.add(element); } } continue; } if (isFocusable(node)) { yield node; } } } //# sourceMappingURL=focus-trap.js.map