UNPKG

primeng

Version:

PrimeNG is a premium UI library for Angular featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock,

114 lines (110 loc) 5.98 kB
import { isPlatformBrowser } from '@angular/common'; import * as i0 from '@angular/core'; import { input, booleanAttribute, effect, Directive, NgModule } from '@angular/core'; import { createElement, getFirstFocusableElement, focus, getLastFocusableElement } from '@primeuix/utils'; import { BaseComponent } from 'primeng/basecomponent'; /** * Focus Trap keeps focus within a certain DOM element while tabbing. * @group Components */ class FocusTrap extends BaseComponent { /** * When set as true, focus wouldn't be managed. * @group Props */ pFocusTrapDisabled = input(false, { ...(ngDevMode ? { debugName: "pFocusTrapDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); firstHiddenFocusableElement; lastHiddenFocusableElement; constructor() { super(); effect(() => { const disabled = this.pFocusTrapDisabled(); if (isPlatformBrowser(this.platformId)) { if (disabled) { this.removeHiddenFocusableElements(); } else if (!this.firstHiddenFocusableElement && !this.lastHiddenFocusableElement) { this.createHiddenFocusableElements(); } } }); } onInit() { if (isPlatformBrowser(this.platformId) && !this.pFocusTrapDisabled()) { !this.firstHiddenFocusableElement && !this.lastHiddenFocusableElement && this.createHiddenFocusableElements(); } } removeHiddenFocusableElements() { if (this.firstHiddenFocusableElement && this.firstHiddenFocusableElement.parentNode) { this.firstHiddenFocusableElement.parentNode.removeChild(this.firstHiddenFocusableElement); } if (this.lastHiddenFocusableElement && this.lastHiddenFocusableElement.parentNode) { this.lastHiddenFocusableElement.parentNode.removeChild(this.lastHiddenFocusableElement); } this.firstHiddenFocusableElement = null; this.lastHiddenFocusableElement = null; } getComputedSelector(selector) { return `:not(.p-hidden-focusable):not([data-p-hidden-focusable="true"])${selector ?? ''}`; } createHiddenFocusableElements() { const tabindex = '0'; const createFocusableElement = (onFocus) => { return createElement('span', { class: 'p-hidden-accessible p-hidden-focusable', tabindex, role: 'presentation', 'aria-hidden': true, 'data-p-hidden-accessible': true, 'data-p-hidden-focusable': true, onFocus: onFocus?.bind(this) }); }; this.firstHiddenFocusableElement = createFocusableElement(this.onFirstHiddenElementFocus); this.lastHiddenFocusableElement = createFocusableElement(this.onLastHiddenElementFocus); this.firstHiddenFocusableElement.setAttribute('data-pc-section', 'firstfocusableelement'); this.lastHiddenFocusableElement.setAttribute('data-pc-section', 'lastfocusableelement'); this.el.nativeElement.prepend(this.firstHiddenFocusableElement); this.el.nativeElement.append(this.lastHiddenFocusableElement); } onFirstHiddenElementFocus(event) { const { currentTarget, relatedTarget } = event; const focusableElement = relatedTarget === this.lastHiddenFocusableElement || !this.el.nativeElement?.contains(relatedTarget) ? getFirstFocusableElement(currentTarget.parentElement, ':not(.p-hidden-focusable)') : this.lastHiddenFocusableElement; focus(focusableElement); } onLastHiddenElementFocus(event) { const { currentTarget, relatedTarget } = event; const focusableElement = relatedTarget === this.firstHiddenFocusableElement || !this.el.nativeElement?.contains(relatedTarget) ? getLastFocusableElement(currentTarget.parentElement, ':not(.p-hidden-focusable)') : this.firstHiddenFocusableElement; focus(focusableElement); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FocusTrap, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.6", type: FocusTrap, isStandalone: true, selector: "[pFocusTrap]", inputs: { pFocusTrapDisabled: { classPropertyName: "pFocusTrapDisabled", publicName: "pFocusTrapDisabled", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FocusTrap, decorators: [{ type: Directive, args: [{ selector: '[pFocusTrap]', standalone: true }] }], ctorParameters: () => [], propDecorators: { pFocusTrapDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "pFocusTrapDisabled", required: false }] }] } }); class FocusTrapModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FocusTrapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.6", ngImport: i0, type: FocusTrapModule, imports: [FocusTrap], exports: [FocusTrap] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FocusTrapModule }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FocusTrapModule, decorators: [{ type: NgModule, args: [{ imports: [FocusTrap], exports: [FocusTrap] }] }] }); /** * Generated bundle index. Do not edit. */ export { FocusTrap, FocusTrapModule }; //# sourceMappingURL=primeng-focustrap.mjs.map