UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

145 lines (140 loc) 7.09 kB
import { TuiLabel } from '@taiga-ui/core/components/label'; import { TuiTextfieldComponent, tuiInjectAuxiliary, tuiAsTextfieldAccessor, TuiTextfieldOptionsDirective } from '@taiga-ui/core/components/textfield'; import { TuiDropdownOpen, tuiDropdownEnabled, TuiDropdownDirective, TuiDropdownContent } from '@taiga-ui/core/portals/dropdown'; import * as i0 from '@angular/core'; import { inject, isSignal, computed, effect, untracked, input, Directive } from '@angular/core'; import { TuiControl, tuiAsControl } from '@taiga-ui/cdk/classes'; import { TUI_STRICT_MATCHER } from '@taiga-ui/cdk/constants'; import { tuiInjectElement } from '@taiga-ui/cdk/utils/dom'; import { tuiAsOptionContent } from '@taiga-ui/core/components/data-list'; import * as i1 from '@taiga-ui/core/components/input'; import { TuiInputDirective, TuiWithInput } from '@taiga-ui/core/components/input'; import { TUI_ITEMS_HANDLERS } from '@taiga-ui/core/directives/items-handlers'; import { TuiSelectOption } from '@taiga-ui/kit/components/select'; class TuiComboBoxDirective extends TuiControl { constructor() { super(...arguments); this.el = tuiInjectElement(); this.host = inject(TuiTextfieldComponent); this.input = inject(TuiInputDirective); this.open = inject(TuiDropdownOpen).open; this.dropdownEnabled = tuiDropdownEnabled(this.interactive); this.dropdown = inject(TuiDropdownDirective); this.handlers = inject(TUI_ITEMS_HANDLERS); this.datalist = tuiInjectAuxiliary((x) => 'options' in x && isSignal(x.options)); this.options = computed(() => this.datalist() ?.options() .filter((x) => !this.handlers.disabledItemHandler()(x)) ?? []); this.nonStrictControlEffect = effect(() => { if (!this.options().length && !this.strict() && this.stringify(this.value()) !== this.input.value()) { this.onChange(this.input.value() || null); } }); this.matchingEffect = effect(() => { const options = this.options(); const matcher = this.matcher(); if (!options.length || !matcher) { return; } const textfieldValue = this.input.value(); const selectedOption = options.find((x) => matcher(x, textfieldValue, this.handlers.stringify())); const value = untracked(this.value); const unchanged = this.stringify(value) === textfieldValue; const fallback = this.strict() || !textfieldValue ? null : textfieldValue; this.onChange(selectedOption ?? /** * Don't clear already not-null form control value on new `this.options()` array. * Otherwise, `ComboBox` becomes incompatible with virtual scroll * (which displays large lists of elements by only rendering the items that fit on-screen). * Users can still able to patch form value with `null` on new items if they wish the such behavior. */ (unchanged ? value : fallback)); }); this.newValueEffect = effect(() => { const stringified = this.stringify(this.value()); this.input.value.update((x) => stringified || x); }); this.blurEffect = effect(() => { const incomplete = untracked(() => this.strict() && this.input.value() && this.value() === null); if (!this.host.focused() && incomplete) { this.el.value = ''; this.el.dispatchEvent(new Event('input', { bubbles: true })); this.toggleDropdown(false); } }); this.strict = input(true); this.matcher = input(TUI_STRICT_MATCHER); } setValue(value) { this.input.setValue(value); this.onChange(value); if (!value) { this.toggleDropdown(true); } } writeValue(value) { const reset = this.control.pristine && this.control.untouched && !value; const changed = untracked(() => value !== this.value()); if (changed || reset) { super.writeValue(value); untracked(() => this.input.value.set(this.stringify(value))); } } toggleDropdown(open = !this.open()) { if (this.dropdownEnabled() && this.dropdown.content()) { this.open.set(open); } } keydownEnter(event) { if (!this.open()) { return; } event.preventDefault(); const options = this.options(); if (options.length === 1 && options[0]) { this.setValue(options[0]); this.toggleDropdown(false); } } stringify(value) { return value == null ? '' : this.handlers.stringify()(value); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiComboBoxDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: TuiComboBoxDirective, isStandalone: true, selector: "input[tuiComboBox]", inputs: { strict: { classPropertyName: "strict", publicName: "strict", isSignal: true, isRequired: false, transformFunction: null }, matcher: { classPropertyName: "matcher", publicName: "matcher", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "toggleDropdown()", "input": "toggleDropdown(true)", "keydown.enter": "keydownEnter($event)" }, properties: { "disabled": "disabled()" } }, providers: [ tuiAsOptionContent(TuiSelectOption), tuiAsTextfieldAccessor(TuiComboBoxDirective), tuiAsControl(TuiComboBoxDirective), ], usesInheritance: true, hostDirectives: [{ directive: i1.TuiWithInput }], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiComboBoxDirective, decorators: [{ type: Directive, args: [{ selector: 'input[tuiComboBox]', providers: [ tuiAsOptionContent(TuiSelectOption), tuiAsTextfieldAccessor(TuiComboBoxDirective), tuiAsControl(TuiComboBoxDirective), ], hostDirectives: [TuiWithInput], host: { '[disabled]': 'disabled()', '(click)': 'toggleDropdown()', '(input)': 'toggleDropdown(true)', '(keydown.enter)': 'keydownEnter($event)', }, }] }] }); const TuiComboBox = [ TuiComboBoxDirective, TuiLabel, TuiTextfieldComponent, TuiTextfieldOptionsDirective, TuiDropdownContent, ]; /** * Generated bundle index. Do not edit. */ export { TuiComboBox, TuiComboBoxDirective }; //# sourceMappingURL=taiga-ui-kit-components-combo-box.mjs.map