red-ui/apps/red-ui/src/app/components/spotlight-search/spotlight-search.component.ts

65 lines
2.5 KiB
TypeScript

import { ChangeDetectionStrategy, Component, HostListener, Input, ViewChild } from '@angular/core';
import { debounceTime, distinctUntilChanged, map, tap } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';
import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action';
import { MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'redaction-spotlight-search [actions]',
templateUrl: './spotlight-search.component.html',
styleUrls: ['./spotlight-search.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SpotlightSearchComponent {
@Input() actions: readonly SpotlightSearchAction[];
@Input() placeholder?: string;
readonly valueChanges$ = new BehaviorSubject<string>('');
@ViewChild(MatMenuTrigger) private readonly _menuTrigger!: MatMenuTrigger;
readonly showActions$ = this.valueChanges$.pipe(
debounceTime(300),
map(value => value !== ''),
tap(show => (show ? this._menuTrigger.openMenu() : this._menuTrigger.closeMenu())),
);
private readonly _currentActionIdx$ = new BehaviorSubject(0);
readonly currentActionIdx$ = this._currentActionIdx$.asObservable().pipe(distinctUntilChanged());
get shownActions(): readonly SpotlightSearchAction[] {
return this.actions.filter(a => !a.hide?.());
}
private get _currentActionIdx(): number {
return this._currentActionIdx$.getValue();
}
openMenuIfValue(): void {
const value = this.valueChanges$.getValue();
if (value && value !== '') {
this._menuTrigger.openMenu();
}
}
executeCurrentAction(): void {
this.shownActions[this._currentActionIdx].action(this.valueChanges$.getValue());
}
@HostListener('keydown.arrowDown', ['$event'])
@HostListener('keydown.arrowUp', ['$event'])
handleKeyDown(event: KeyboardEvent): void {
event.preventDefault();
}
@HostListener('keyup.arrowDown', ['$event'])
handleKeyUpArrowDown(event: KeyboardEvent): void {
this.handleKeyDown(event);
const index = this._currentActionIdx + 1;
this._currentActionIdx$.next(index >= this.shownActions.length ? 0 : index);
}
@HostListener('keyup.arrowUp', ['$event'])
handleKeyUpArrowUp(event: KeyboardEvent): void {
this.handleKeyDown(event);
const index = this._currentActionIdx - 1;
this._currentActionIdx$.next(index < 0 ? this.shownActions.length - 1 : index);
}
}