@taiga-ui/kit
Version:
Taiga UI Angular main components kit
145 lines (140 loc) • 7.09 kB
JavaScript
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