diff --git a/src/app/components/dropdown/dropdown.html b/src/app/components/dropdown/dropdown.html index 60d7cb6..5dc01e7 100644 --- a/src/app/components/dropdown/dropdown.html +++ b/src/app/components/dropdown/dropdown.html @@ -6,7 +6,7 @@ + (input)="onSearch($event)" (click)="handleInputClick($event)" (mousedown)="handleInputMouseDown()" (beforeinput)="preprocessInputContent($event)"> @if (!isOpen()) { {{ selectedLabel() }} diff --git a/src/app/components/dropdown/dropdown.ts b/src/app/components/dropdown/dropdown.ts index 1941097..d2ec326 100644 --- a/src/app/components/dropdown/dropdown.ts +++ b/src/app/components/dropdown/dropdown.ts @@ -13,7 +13,7 @@ import { viewChild, untracked, } from '@angular/core'; -import { CommonModule } from '@angular/common' +import { CommonModule } from '@angular/common'; import { TranslationService } from '../../services/translation.service'; export interface DropdownOption { @@ -106,7 +106,7 @@ export class Dropdown implements OnInit { }); filteredOptions = computed(() => { - const query = this.searchQuery().toLowerCase().trim().normalize("NFKD"); + const query = this.searchQuery().toLowerCase().trim().normalize('NFKD'); const opts = this.normalizedOptions(); if (!this.inputFocusMode()) return opts; @@ -170,6 +170,8 @@ export class Dropdown implements OnInit { const options = this.filteredOptions(); if (currentIndex >= 0 && currentIndex < options.length) { this.selectOption(options[currentIndex]); + } else if (options.length === 0) { + this.close(); } } else { this.toggle(); @@ -218,8 +220,9 @@ export class Dropdown implements OnInit { } onKeyDown(event: KeyboardEvent) { - if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey || event.key == 'Tab') - return; + const textArrowKeys = ['ArrowLeft', 'ArrowRight']; + + if (!textArrowKeys.includes(event.key)) return; if (!this.isOpen() || this.inputFocusMode()) return; this.inputFocusMode.set(true); @@ -257,6 +260,9 @@ export class Dropdown implements OnInit { } onSearch(event: Event) { + if (!this.isOpen()) return; + if (!this.inputFocusMode()) this.inputFocusMode.set(true); + const element = event.target as HTMLElement; const text = element.innerText; @@ -265,6 +271,21 @@ export class Dropdown implements OnInit { this.searchQuery.set(text); } + preprocessInputContent(event: InputEvent) { + if (event.inputType === 'insertLineBreak' || event.inputType === 'insertParagraph') { + event.preventDefault(); + } + + if (event.inputType === 'insertFromPaste') { + const originalText = event.dataTransfer!.getData('text/plain'); + const modifiedText = originalText.replace(/[\r\n]+/g, ''); + event.preventDefault(); + + // noinspection JSDeprecatedSymbols + document.execCommand('insertText', false, modifiedText); + } + } + selectedLabel = computed(() => { const selected = this.normalizedOptions().find((o) => o.value === this.value()); return selected ? selected.label : this.placeholder();