UNPKG

@taiga-ui/cdk

Version:

Base library for creating Angular components and applications using Taiga UI principles regarding of actual visual appearance

61 lines 8.07 kB
import { DOCUMENT } from '@angular/common'; import { Directive, inject } from '@angular/core'; import { tuiContainsOrAfter, tuiInjectElement, tuiIsHTMLElement, } from '@taiga-ui/cdk/utils/dom'; import { tuiGetClosestFocusable, tuiGetNativeFocused } from '@taiga-ui/cdk/utils/focus'; import * as i0 from "@angular/core"; class TuiFocusTrap { constructor() { this.doc = inject(DOCUMENT); this.el = tuiInjectElement(); this.activeElement = null; this.initialized = false; /** * This would cause currently focused element to lose focus, * but it might cause ExpressionChanged error due to potential HostBinding. * Microtask keeps it in the same frame but allows change detection to run */ Promise.resolve().then(() => { /** * The same event can synchronously close already opened focus trap and open another one. * All focus traps have microtask inside its `ngOnDestroy` – * they should be resolved before enabling of new focus trap. * Don't enable any new event listeners before `initialized` equals to `true`! */ this.initialized = true; this.activeElement = tuiGetNativeFocused(this.doc); this.el.focus(); }); } ngOnDestroy() { this.initialized = false; if (tuiIsHTMLElement(this.activeElement)) { this.activeElement.focus(); } } onFocusIn(node) { const { firstElementChild } = this.el; if (!tuiContainsOrAfter(this.el, node) && firstElementChild) { tuiGetClosestFocusable({ initial: firstElementChild, root: this.el, })?.focus(); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiFocusTrap, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiFocusTrap, isStandalone: true, selector: "[tuiFocusTrap]", host: { attributes: { "tabIndex": "0" }, listeners: { "window:focusin.zoneless": "initialized && onFocusIn($event.target)", "pointerdown": "$event.currentTarget?.removeAttribute(\"tabindex\")" } }, ngImport: i0 }); } } export { TuiFocusTrap }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiFocusTrap, decorators: [{ type: Directive, args: [{ standalone: true, selector: '[tuiFocusTrap]', host: { tabIndex: '0', '(window:focusin.zoneless)': 'initialized && onFocusIn($event.target)', // https://bugs.webkit.org/show_bug.cgi?id=303022 '(pointerdown)': '$event.currentTarget?.removeAttribute("tabindex")', }, }] }], ctorParameters: function () { return []; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9jdXMtdHJhcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jZGsvZGlyZWN0aXZlcy9mb2N1cy10cmFwL2ZvY3VzLXRyYXAuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUMsU0FBUyxFQUFFLE1BQU0sRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDaEUsT0FBTyxFQUNILGtCQUFrQixFQUNsQixnQkFBZ0IsRUFDaEIsZ0JBQWdCLEdBQ25CLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFDLHNCQUFzQixFQUFFLG1CQUFtQixFQUFDLE1BQU0sMkJBQTJCLENBQUM7O0FBRXRGLE1BVWEsWUFBWTtJQU1yQjtRQUxpQixRQUFHLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZCLE9BQUUsR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ2pDLGtCQUFhLEdBQW1CLElBQUksQ0FBQztRQUNuQyxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUcxQjs7OztXQUlHO1FBQ0gsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDeEI7Ozs7O2VBS0c7WUFDSCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztZQUN4QixJQUFJLENBQUMsYUFBYSxHQUFHLG1CQUFtQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNuRCxJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVNLFdBQVc7UUFDZCxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQztRQUV6QixJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRTtZQUN0QyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQzlCO0lBQ0wsQ0FBQztJQUVTLFNBQVMsQ0FBQyxJQUFVO1FBQzFCLE1BQU0sRUFBQyxpQkFBaUIsRUFBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7UUFFcEMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksaUJBQWlCLEVBQUU7WUFDekQsc0JBQXNCLENBQUM7Z0JBQ25CLE9BQU8sRUFBRSxpQkFBaUI7Z0JBQzFCLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRTthQUNoQixDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUM7U0FDZjtJQUNMLENBQUM7K0dBMUNRLFlBQVk7bUdBQVosWUFBWTs7U0FBWixZQUFZOzRGQUFaLFlBQVk7a0JBVnhCLFNBQVM7bUJBQUM7b0JBQ1AsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLFFBQVEsRUFBRSxnQkFBZ0I7b0JBQzFCLElBQUksRUFBRTt3QkFDRixRQUFRLEVBQUUsR0FBRzt3QkFDYiwyQkFBMkIsRUFBRSx5Q0FBeUM7d0JBQ3RFLGlEQUFpRDt3QkFDakQsZUFBZSxFQUFFLG1EQUFtRDtxQkFDdkU7aUJBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtEaXJlY3RpdmUsIGluamVjdCwgdHlwZSBPbkRlc3Ryb3l9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgICB0dWlDb250YWluc09yQWZ0ZXIsXG4gICAgdHVpSW5qZWN0RWxlbWVudCxcbiAgICB0dWlJc0hUTUxFbGVtZW50LFxufSBmcm9tICdAdGFpZ2EtdWkvY2RrL3V0aWxzL2RvbSc7XG5pbXBvcnQge3R1aUdldENsb3Nlc3RGb2N1c2FibGUsIHR1aUdldE5hdGl2ZUZvY3VzZWR9IGZyb20gJ0B0YWlnYS11aS9jZGsvdXRpbHMvZm9jdXMnO1xuXG5ARGlyZWN0aXZlKHtcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIHNlbGVjdG9yOiAnW3R1aUZvY3VzVHJhcF0nLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgdGFiSW5kZXg6ICcwJyxcbiAgICAgICAgJyh3aW5kb3c6Zm9jdXNpbi56b25lbGVzcyknOiAnaW5pdGlhbGl6ZWQgJiYgb25Gb2N1c0luKCRldmVudC50YXJnZXQpJyxcbiAgICAgICAgLy8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTMwMzAyMlxuICAgICAgICAnKHBvaW50ZXJkb3duKSc6ICckZXZlbnQuY3VycmVudFRhcmdldD8ucmVtb3ZlQXR0cmlidXRlKFwidGFiaW5kZXhcIiknLFxuICAgIH0sXG59KVxuZXhwb3J0IGNsYXNzIFR1aUZvY3VzVHJhcCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBkb2MgPSBpbmplY3QoRE9DVU1FTlQpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZWwgPSB0dWlJbmplY3RFbGVtZW50KCk7XG4gICAgcHJpdmF0ZSBhY3RpdmVFbGVtZW50OiBFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgcHJvdGVjdGVkIGluaXRpYWxpemVkID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgd291bGQgY2F1c2UgY3VycmVudGx5IGZvY3VzZWQgZWxlbWVudCB0byBsb3NlIGZvY3VzLFxuICAgICAgICAgKiBidXQgaXQgbWlnaHQgY2F1c2UgRXhwcmVzc2lvbkNoYW5nZWQgZXJyb3IgZHVlIHRvIHBvdGVudGlhbCBIb3N0QmluZGluZy5cbiAgICAgICAgICogTWljcm90YXNrIGtlZXBzIGl0IGluIHRoZSBzYW1lIGZyYW1lIGJ1dCBhbGxvd3MgY2hhbmdlIGRldGVjdGlvbiB0byBydW5cbiAgICAgICAgICovXG4gICAgICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBUaGUgc2FtZSBldmVudCBjYW4gc3luY2hyb25vdXNseSBjbG9zZSBhbHJlYWR5IG9wZW5lZCBmb2N1cyB0cmFwIGFuZCBvcGVuIGFub3RoZXIgb25lLlxuICAgICAgICAgICAgICogQWxsIGZvY3VzIHRyYXBzIGhhdmUgbWljcm90YXNrIGluc2lkZSBpdHMgYG5nT25EZXN0cm95YCDigJNcbiAgICAgICAgICAgICAqIHRoZXkgc2hvdWxkIGJlIHJlc29sdmVkIGJlZm9yZSBlbmFibGluZyBvZiBuZXcgZm9jdXMgdHJhcC5cbiAgICAgICAgICAgICAqIERvbid0IGVuYWJsZSBhbnkgbmV3IGV2ZW50IGxpc3RlbmVycyBiZWZvcmUgYGluaXRpYWxpemVkYCBlcXVhbHMgdG8gYHRydWVgIVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuYWN0aXZlRWxlbWVudCA9IHR1aUdldE5hdGl2ZUZvY3VzZWQodGhpcy5kb2MpO1xuICAgICAgICAgICAgdGhpcy5lbC5mb2N1cygpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTtcblxuICAgICAgICBpZiAodHVpSXNIVE1MRWxlbWVudCh0aGlzLmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICB0aGlzLmFjdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBvbkZvY3VzSW4obm9kZTogTm9kZSk6IHZvaWQge1xuICAgICAgICBjb25zdCB7Zmlyc3RFbGVtZW50Q2hpbGR9ID0gdGhpcy5lbDtcblxuICAgICAgICBpZiAoIXR1aUNvbnRhaW5zT3JBZnRlcih0aGlzLmVsLCBub2RlKSAmJiBmaXJzdEVsZW1lbnRDaGlsZCkge1xuICAgICAgICAgICAgdHVpR2V0Q2xvc2VzdEZvY3VzYWJsZSh7XG4gICAgICAgICAgICAgICAgaW5pdGlhbDogZmlyc3RFbGVtZW50Q2hpbGQsXG4gICAgICAgICAgICAgICAgcm9vdDogdGhpcy5lbCxcbiAgICAgICAgICAgIH0pPy5mb2N1cygpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19