UNPKG

@taiga-ui/cdk

Version:

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

67 lines 8.68 kB
import { DOCUMENT } from '@angular/common'; import { Directive, inject } from '@angular/core'; import { tuiContainsOrAfter, tuiInjectElement, tuiIsHTMLElement, } from '@taiga-ui/cdk/utils/dom'; import { tuiBlurNativeFocused, 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() { tuiBlurNativeFocused(this.doc); /** * HostListeners are triggered even after ngOnDestroy * {@link https://github.com/angular/angular/issues/38100} * so we need to delay it but stay in the same sync cycle, * therefore using Promise instead of setTimeout */ Promise.resolve().then(() => { 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)" } }, 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)', }, }] }], ctorParameters: function () { return []; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9jdXMtdHJhcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jZGsvZGlyZWN0aXZlcy9mb2N1cy10cmFwL2ZvY3VzLXRyYXAuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUV6QyxPQUFPLEVBQUMsU0FBUyxFQUFFLE1BQU0sRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNoRCxPQUFPLEVBQ0gsa0JBQWtCLEVBQ2xCLGdCQUFnQixFQUNoQixnQkFBZ0IsR0FDbkIsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQ0gsb0JBQW9CLEVBQ3BCLHNCQUFzQixFQUN0QixtQkFBbUIsR0FDdEIsTUFBTSwyQkFBMkIsQ0FBQzs7QUFFbkMsTUFRYSxZQUFZO0lBTXJCO1FBTGlCLFFBQUcsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdkIsT0FBRSxHQUFHLGdCQUFnQixFQUFFLENBQUM7UUFDakMsa0JBQWEsR0FBbUIsSUFBSSxDQUFDO1FBQ25DLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBRzFCOzs7O1dBSUc7UUFDSCxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUN4Qjs7Ozs7ZUFLRztZQUNILElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1lBQ3hCLElBQUksQ0FBQyxhQUFhLEdBQUcsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25ELElBQUksQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDcEIsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU0sV0FBVztRQUNkLG9CQUFvQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUUvQjs7Ozs7V0FLRztRQUNILE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ3hCLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUFFO2dCQUN0QyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQzlCO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRVMsU0FBUyxDQUFDLElBQVU7UUFDMUIsTUFBTSxFQUFDLGlCQUFpQixFQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUVwQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsSUFBSSxpQkFBaUIsRUFBRTtZQUN6RCxzQkFBc0IsQ0FBQztnQkFDbkIsT0FBTyxFQUFFLGlCQUFpQjtnQkFDMUIsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFO2FBQ2hCLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQztTQUNmO0lBQ0wsQ0FBQzsrR0FsRFEsWUFBWTttR0FBWixZQUFZOztTQUFaLFlBQVk7NEZBQVosWUFBWTtrQkFSeEIsU0FBUzttQkFBQztvQkFDUCxVQUFVLEVBQUUsSUFBSTtvQkFDaEIsUUFBUSxFQUFFLGdCQUFnQjtvQkFDMUIsSUFBSSxFQUFFO3dCQUNGLFFBQVEsRUFBRSxHQUFHO3dCQUNiLDJCQUEyQixFQUFFLHlDQUF5QztxQkFDekU7aUJBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHR5cGUge09uRGVzdHJveX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0RpcmVjdGl2ZSwgaW5qZWN0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gICAgdHVpQ29udGFpbnNPckFmdGVyLFxuICAgIHR1aUluamVjdEVsZW1lbnQsXG4gICAgdHVpSXNIVE1MRWxlbWVudCxcbn0gZnJvbSAnQHRhaWdhLXVpL2Nkay91dGlscy9kb20nO1xuaW1wb3J0IHtcbiAgICB0dWlCbHVyTmF0aXZlRm9jdXNlZCxcbiAgICB0dWlHZXRDbG9zZXN0Rm9jdXNhYmxlLFxuICAgIHR1aUdldE5hdGl2ZUZvY3VzZWQsXG59IGZyb20gJ0B0YWlnYS11aS9jZGsvdXRpbHMvZm9jdXMnO1xuXG5ARGlyZWN0aXZlKHtcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIHNlbGVjdG9yOiAnW3R1aUZvY3VzVHJhcF0nLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgdGFiSW5kZXg6ICcwJyxcbiAgICAgICAgJyh3aW5kb3c6Zm9jdXNpbi56b25lbGVzcyknOiAnaW5pdGlhbGl6ZWQgJiYgb25Gb2N1c0luKCRldmVudC50YXJnZXQpJyxcbiAgICB9LFxufSlcbmV4cG9ydCBjbGFzcyBUdWlGb2N1c1RyYXAgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZG9jID0gaW5qZWN0KERPQ1VNRU5UKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGVsID0gdHVpSW5qZWN0RWxlbWVudCgpO1xuICAgIHByaXZhdGUgYWN0aXZlRWxlbWVudDogRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIHByb3RlY3RlZCBpbml0aWFsaXplZCA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIHdvdWxkIGNhdXNlIGN1cnJlbnRseSBmb2N1c2VkIGVsZW1lbnQgdG8gbG9zZSBmb2N1cyxcbiAgICAgICAgICogYnV0IGl0IG1pZ2h0IGNhdXNlIEV4cHJlc3Npb25DaGFuZ2VkIGVycm9yIGR1ZSB0byBwb3RlbnRpYWwgSG9zdEJpbmRpbmcuXG4gICAgICAgICAqIE1pY3JvdGFzayBrZWVwcyBpdCBpbiB0aGUgc2FtZSBmcmFtZSBidXQgYWxsb3dzIGNoYW5nZSBkZXRlY3Rpb24gdG8gcnVuXG4gICAgICAgICAqL1xuICAgICAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGhlIHNhbWUgZXZlbnQgY2FuIHN5bmNocm9ub3VzbHkgY2xvc2UgYWxyZWFkeSBvcGVuZWQgZm9jdXMgdHJhcCBhbmQgb3BlbiBhbm90aGVyIG9uZS5cbiAgICAgICAgICAgICAqIEFsbCBmb2N1cyB0cmFwcyBoYXZlIG1pY3JvdGFzayBpbnNpZGUgaXRzIGBuZ09uRGVzdHJveWAg4oCTXG4gICAgICAgICAgICAgKiB0aGV5IHNob3VsZCBiZSByZXNvbHZlZCBiZWZvcmUgZW5hYmxpbmcgb2YgbmV3IGZvY3VzIHRyYXAuXG4gICAgICAgICAgICAgKiBEb24ndCBlbmFibGUgYW55IG5ldyBldmVudCBsaXN0ZW5lcnMgYmVmb3JlIGBpbml0aWFsaXplZGAgZXF1YWxzIHRvIGB0cnVlYCFcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmFjdGl2ZUVsZW1lbnQgPSB0dWlHZXROYXRpdmVGb2N1c2VkKHRoaXMuZG9jKTtcbiAgICAgICAgICAgIHRoaXMuZWwuZm9jdXMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0dWlCbHVyTmF0aXZlRm9jdXNlZCh0aGlzLmRvYyk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhvc3RMaXN0ZW5lcnMgYXJlIHRyaWdnZXJlZCBldmVuIGFmdGVyIG5nT25EZXN0cm95XG4gICAgICAgICAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2lzc3Vlcy8zODEwMH1cbiAgICAgICAgICogc28gd2UgbmVlZCB0byBkZWxheSBpdCBidXQgc3RheSBpbiB0aGUgc2FtZSBzeW5jIGN5Y2xlLFxuICAgICAgICAgKiB0aGVyZWZvcmUgdXNpbmcgUHJvbWlzZSBpbnN0ZWFkIG9mIHNldFRpbWVvdXRcbiAgICAgICAgICovXG4gICAgICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHR1aUlzSFRNTEVsZW1lbnQodGhpcy5hY3RpdmVFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgb25Gb2N1c0luKG5vZGU6IE5vZGUpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qge2ZpcnN0RWxlbWVudENoaWxkfSA9IHRoaXMuZWw7XG5cbiAgICAgICAgaWYgKCF0dWlDb250YWluc09yQWZ0ZXIodGhpcy5lbCwgbm9kZSkgJiYgZmlyc3RFbGVtZW50Q2hpbGQpIHtcbiAgICAgICAgICAgIHR1aUdldENsb3Nlc3RGb2N1c2FibGUoe1xuICAgICAgICAgICAgICAgIGluaXRpYWw6IGZpcnN0RWxlbWVudENoaWxkLFxuICAgICAgICAgICAgICAgIHJvb3Q6IHRoaXMuZWwsXG4gICAgICAgICAgICB9KT8uZm9jdXMoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==