@taiga-ui/kit
Version:
Taiga UI Angular main components kit
82 lines (78 loc) • 4.75 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, DestroyRef, contentChildren, ElementRef, Directive } from '@angular/core';
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { tuiTypedFromEvent, tuiPreventDefault } from '@taiga-ui/cdk/observables';
import { tuiGetClosestFocusable } from '@taiga-ui/cdk/utils/focus';
import { TuiDropdownDirective } from '@taiga-ui/core/portals/dropdown';
import { map, shareReplay, switchMap, merge, filter, debounceTime, EMPTY, take, tap } from 'rxjs';
class TuiDataListDropdownManager {
constructor() {
this.destroyRef = inject(DestroyRef);
this.dropdowns = contentChildren(TuiDropdownDirective, {
descendants: true,
});
this.els = contentChildren(TuiDropdownDirective, {
read: ElementRef,
descendants: true,
});
this.elements$ = toObservable(this.els).pipe(map((array) => array.map(({ nativeElement }) => nativeElement)), shareReplay({ bufferSize: 1, refCount: true }));
this.right$ = this.elements$.pipe(switchMap((elements) => merge(...elements.map((element, index) => tuiTypedFromEvent(element, 'keydown').pipe(filter(({ key }) => key === 'ArrowRight'), tuiPreventDefault(), map(() => index))))));
this.immediate$ = this.elements$.pipe(switchMap((elements) => merge(...elements.map((element, index) => tuiTypedFromEvent(element, 'click').pipe(map(() => index))))));
this.debounce$ = this.elements$.pipe(switchMap((elements) => merge(...elements.map((element, index) => merge(tuiTypedFromEvent(element, 'focus'), tuiTypedFromEvent(element, 'blur')).pipe(filter(({ relatedTarget }) => this.notInDropdown(relatedTarget, index)), map(({ type }) => (type === 'focus' ? index : Number.NaN)))))), debounceTime(300));
}
ngAfterViewInit() {
this.right$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((index) => {
this.tryToFocus(index);
});
merge(this.immediate$, this.debounce$)
.pipe(switchMap((active) => {
this.dropdowns().forEach((dropdown, index) => {
dropdown.toggle(index === active);
});
const element = this.els()[active];
const dropdown = this.dropdowns()[active];
const ref = dropdown?.ref();
if (!element || !dropdown || !ref) {
return EMPTY;
}
const { nativeElement } = ref.location;
const mouseEnter$ = tuiTypedFromEvent(nativeElement, 'mouseenter').pipe(take(1));
const esc$ = merge(tuiTypedFromEvent(element.nativeElement, 'keydown'), tuiTypedFromEvent(nativeElement, 'keydown')).pipe(filter(({ key }) => key === 'Escape'));
return merge(mouseEnter$, esc$).pipe(tap((event) => {
if (dropdown.ref()) {
event.stopPropagation();
}
element.nativeElement.focus();
dropdown.toggle('offsetX' in event);
}));
}), takeUntilDestroyed(this.destroyRef))
.subscribe();
}
notInDropdown(element, index) {
return !this.dropdowns()[index]?.ref()?.location.nativeElement.contains(element);
}
tryToFocus(index) {
const content = this.dropdowns()[index]?.ref()?.location.nativeElement;
if (!content) {
return;
}
// First item is focus trap
const focusTrap = tuiGetClosestFocusable({ initial: content, root: content });
const item = tuiGetClosestFocusable({
initial: focusTrap || content,
root: content,
});
item?.focus();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiDataListDropdownManager, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "19.2.21", type: TuiDataListDropdownManager, isStandalone: true, selector: "tui-data-list[tuiDataListDropdownManager]", queries: [{ propertyName: "dropdowns", predicate: TuiDropdownDirective, descendants: true, isSignal: true }, { propertyName: "els", predicate: TuiDropdownDirective, descendants: true, read: ElementRef, isSignal: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiDataListDropdownManager, decorators: [{
type: Directive,
args: [{ selector: 'tui-data-list[tuiDataListDropdownManager]' }]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { TuiDataListDropdownManager };
//# sourceMappingURL=taiga-ui-kit-directives-data-list-dropdown-manager.mjs.map