@m1z23r/ngx-ui 1.1.46 → 1.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -3969,6 +3969,11 @@ class ChipInputComponent {
|
|
|
3969
3969
|
allowDuplicates = input(false, ...(ngDevMode ? [{ debugName: "allowDuplicates" }] : []));
|
|
3970
3970
|
/** When false, only emits the `added` event without adding to the array (useful for custom object chips) */
|
|
3971
3971
|
autoAdd = input(true, ...(ngDevMode ? [{ debugName: "autoAdd" }] : []));
|
|
3972
|
+
suggestions = input([], ...(ngDevMode ? [{ debugName: "suggestions" }] : []));
|
|
3973
|
+
asyncSearch = input(null, ...(ngDevMode ? [{ debugName: "asyncSearch" }] : []));
|
|
3974
|
+
strict = input(false, ...(ngDevMode ? [{ debugName: "strict" }] : []));
|
|
3975
|
+
minSearchLength = input(0, ...(ngDevMode ? [{ debugName: "minSearchLength" }] : []));
|
|
3976
|
+
debounceTime = input(300, ...(ngDevMode ? [{ debugName: "debounceTime" }] : []));
|
|
3972
3977
|
/** The array of chip values */
|
|
3973
3978
|
value = model([], ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
3974
3979
|
/** Emitted when a chip is added */
|
|
@@ -3977,9 +3982,24 @@ class ChipInputComponent {
|
|
|
3977
3982
|
removed = output();
|
|
3978
3983
|
/** Custom chip template */
|
|
3979
3984
|
chipTemplate = contentChild(ChipTemplateDirective, { ...(ngDevMode ? { debugName: "chipTemplate" } : {}), read: TemplateRef });
|
|
3985
|
+
optionTemplate = contentChild(OptionTemplateDirective, ...(ngDevMode ? [{ debugName: "optionTemplate" }] : []));
|
|
3980
3986
|
inputRef;
|
|
3987
|
+
triggerRef;
|
|
3988
|
+
dropdownRef;
|
|
3981
3989
|
inputValue = signal('', ...(ngDevMode ? [{ debugName: "inputValue" }] : []));
|
|
3982
3990
|
isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : []));
|
|
3991
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
3992
|
+
focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : []));
|
|
3993
|
+
asyncOptions = signal([], ...(ngDevMode ? [{ debugName: "asyncOptions" }] : []));
|
|
3994
|
+
asyncLoading = signal(false, ...(ngDevMode ? [{ debugName: "asyncLoading" }] : []));
|
|
3995
|
+
asyncError = signal(null, ...(ngDevMode ? [{ debugName: "asyncError" }] : []));
|
|
3996
|
+
labelCache = new Map();
|
|
3997
|
+
elementRef = inject(ElementRef);
|
|
3998
|
+
document = inject(DOCUMENT);
|
|
3999
|
+
asyncSearchAbortController = null;
|
|
4000
|
+
debounceTimer = null;
|
|
4001
|
+
blurCloseTimer = null;
|
|
4002
|
+
positionCleanup = null;
|
|
3983
4003
|
containerClasses = computed(() => {
|
|
3984
4004
|
const classes = [
|
|
3985
4005
|
`ui-chip-input--${this.variant()}`,
|
|
@@ -3993,27 +4013,115 @@ class ChipInputComponent {
|
|
|
3993
4013
|
classes.push('ui-chip-input--error');
|
|
3994
4014
|
return classes.join(' ');
|
|
3995
4015
|
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
4016
|
+
isAsyncMode = computed(() => this.asyncSearch() !== null, ...(ngDevMode ? [{ debugName: "isAsyncMode" }] : []));
|
|
4017
|
+
normalizedSuggestions = computed(() => {
|
|
4018
|
+
return this.suggestions().map((s) => typeof s === 'string' ? { label: s, value: s } : s);
|
|
4019
|
+
}, ...(ngDevMode ? [{ debugName: "normalizedSuggestions" }] : []));
|
|
4020
|
+
visibleSuggestions = computed(() => {
|
|
4021
|
+
const source = this.isAsyncMode() ? this.asyncOptions() : this.normalizedSuggestions();
|
|
4022
|
+
const selected = this.value();
|
|
4023
|
+
const query = this.inputValue().toLowerCase().trim();
|
|
4024
|
+
const notPicked = source.filter((opt) => !selected.includes(opt.value));
|
|
4025
|
+
if (this.isAsyncMode())
|
|
4026
|
+
return notPicked;
|
|
4027
|
+
if (!query)
|
|
4028
|
+
return notPicked;
|
|
4029
|
+
return notPicked.filter((opt) => opt.label.toLowerCase().includes(query));
|
|
4030
|
+
}, ...(ngDevMode ? [{ debugName: "visibleSuggestions" }] : []));
|
|
4031
|
+
exactMatchExists = computed(() => {
|
|
4032
|
+
const query = this.inputValue().toLowerCase().trim();
|
|
4033
|
+
if (!query)
|
|
4034
|
+
return true;
|
|
4035
|
+
const source = this.isAsyncMode() ? this.asyncOptions() : this.normalizedSuggestions();
|
|
4036
|
+
return source.some((opt) => opt.label.toLowerCase() === query);
|
|
4037
|
+
}, ...(ngDevMode ? [{ debugName: "exactMatchExists" }] : []));
|
|
4038
|
+
showCreateRow = computed(() => {
|
|
4039
|
+
return (!this.strict() &&
|
|
4040
|
+
this.inputValue().trim().length > 0 &&
|
|
4041
|
+
!this.exactMatchExists());
|
|
4042
|
+
}, ...(ngDevMode ? [{ debugName: "showCreateRow" }] : []));
|
|
4043
|
+
ngOnDestroy() {
|
|
4044
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
4045
|
+
if (dropdown?.parentElement === this.document.body) {
|
|
4046
|
+
this.document.body.removeChild(dropdown);
|
|
4047
|
+
}
|
|
4048
|
+
this.removePositionListeners();
|
|
4049
|
+
this.cancelAsyncSearch();
|
|
4050
|
+
if (this.blurCloseTimer) {
|
|
4051
|
+
clearTimeout(this.blurCloseTimer);
|
|
4052
|
+
this.blurCloseTimer = null;
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
3996
4055
|
onContainerClick() {
|
|
3997
4056
|
if (!this.disabled()) {
|
|
3998
4057
|
this.inputRef?.nativeElement?.focus();
|
|
3999
4058
|
}
|
|
4000
4059
|
}
|
|
4001
4060
|
onInputKeydown(event) {
|
|
4002
|
-
const
|
|
4061
|
+
const trimmed = this.inputValue().trim();
|
|
4003
4062
|
switch (event.key) {
|
|
4004
|
-
case 'Enter':
|
|
4063
|
+
case 'Enter': {
|
|
4005
4064
|
event.preventDefault();
|
|
4006
|
-
|
|
4007
|
-
|
|
4065
|
+
const focused = this.focusedIndex();
|
|
4066
|
+
const visible = this.visibleSuggestions();
|
|
4067
|
+
if (focused >= 0 && focused < visible.length) {
|
|
4068
|
+
this.addSuggestion(visible[focused]);
|
|
4069
|
+
}
|
|
4070
|
+
else if (!this.strict() && trimmed) {
|
|
4071
|
+
this.addChip(trimmed);
|
|
4072
|
+
setTimeout(() => this.updateDropdownPosition());
|
|
4008
4073
|
}
|
|
4009
4074
|
break;
|
|
4075
|
+
}
|
|
4076
|
+
case 'ArrowDown': {
|
|
4077
|
+
if (!this.isOpen()) {
|
|
4078
|
+
this.open();
|
|
4079
|
+
return;
|
|
4080
|
+
}
|
|
4081
|
+
event.preventDefault();
|
|
4082
|
+
const visible = this.visibleSuggestions();
|
|
4083
|
+
let next = this.focusedIndex() + 1;
|
|
4084
|
+
while (next < visible.length && visible[next].disabled)
|
|
4085
|
+
next++;
|
|
4086
|
+
if (next < visible.length)
|
|
4087
|
+
this.focusedIndex.set(next);
|
|
4088
|
+
break;
|
|
4089
|
+
}
|
|
4090
|
+
case 'ArrowUp': {
|
|
4091
|
+
if (!this.isOpen())
|
|
4092
|
+
return;
|
|
4093
|
+
event.preventDefault();
|
|
4094
|
+
const visible = this.visibleSuggestions();
|
|
4095
|
+
let prev = this.focusedIndex() - 1;
|
|
4096
|
+
while (prev >= 0 && visible[prev].disabled)
|
|
4097
|
+
prev--;
|
|
4098
|
+
if (prev >= 0)
|
|
4099
|
+
this.focusedIndex.set(prev);
|
|
4100
|
+
break;
|
|
4101
|
+
}
|
|
4102
|
+
case 'Escape':
|
|
4103
|
+
event.preventDefault();
|
|
4104
|
+
this.close();
|
|
4105
|
+
break;
|
|
4010
4106
|
case 'Backspace':
|
|
4011
|
-
if (!
|
|
4107
|
+
if (!trimmed && this.value().length > 0) {
|
|
4012
4108
|
this.removeChip(this.value()[this.value().length - 1]);
|
|
4013
4109
|
}
|
|
4014
4110
|
break;
|
|
4015
4111
|
}
|
|
4016
4112
|
}
|
|
4113
|
+
onInputChange(value) {
|
|
4114
|
+
this.inputValue.set(value);
|
|
4115
|
+
this.focusedIndex.set(-1);
|
|
4116
|
+
if (!this.isOpen())
|
|
4117
|
+
this.open();
|
|
4118
|
+
if (this.isAsyncMode()) {
|
|
4119
|
+
this.triggerAsyncSearch(value);
|
|
4120
|
+
}
|
|
4121
|
+
else {
|
|
4122
|
+
setTimeout(() => this.updateDropdownPosition());
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4017
4125
|
addChip(chipValue) {
|
|
4018
4126
|
const current = this.value();
|
|
4019
4127
|
// For string chips, check duplicates
|
|
@@ -4026,8 +4134,29 @@ class ChipInputComponent {
|
|
|
4026
4134
|
this.inputValue.set('');
|
|
4027
4135
|
this.added.emit(chipValue);
|
|
4028
4136
|
}
|
|
4137
|
+
addSuggestion(option) {
|
|
4138
|
+
if (option.disabled)
|
|
4139
|
+
return;
|
|
4140
|
+
const current = this.value();
|
|
4141
|
+
if (!this.allowDuplicates() && current.includes(option.value))
|
|
4142
|
+
return;
|
|
4143
|
+
if (option.label !== String(option.value)) {
|
|
4144
|
+
this.labelCache.set(option.value, option.label);
|
|
4145
|
+
}
|
|
4146
|
+
if (this.autoAdd()) {
|
|
4147
|
+
this.value.set([...current, option.value]);
|
|
4148
|
+
}
|
|
4149
|
+
this.inputValue.set('');
|
|
4150
|
+
this.added.emit(option.label);
|
|
4151
|
+
this.focusedIndex.set(-1);
|
|
4152
|
+
setTimeout(() => {
|
|
4153
|
+
this.updateDropdownPosition();
|
|
4154
|
+
this.inputRef?.nativeElement?.focus();
|
|
4155
|
+
});
|
|
4156
|
+
}
|
|
4029
4157
|
removeChip(chipValue) {
|
|
4030
4158
|
this.value.set(this.value().filter((v) => v !== chipValue));
|
|
4159
|
+
this.labelCache.delete(chipValue);
|
|
4031
4160
|
this.removed.emit(chipValue);
|
|
4032
4161
|
// Refocus input after removal
|
|
4033
4162
|
setTimeout(() => this.inputRef?.nativeElement?.focus());
|
|
@@ -4041,23 +4170,202 @@ class ChipInputComponent {
|
|
|
4041
4170
|
}
|
|
4042
4171
|
/** Get display text for a chip (for default template) */
|
|
4043
4172
|
getChipDisplay(chip) {
|
|
4044
|
-
return String(chip);
|
|
4173
|
+
return this.labelCache.get(chip) ?? String(chip);
|
|
4045
4174
|
}
|
|
4046
4175
|
onFocus() {
|
|
4047
4176
|
this.isFocused.set(true);
|
|
4177
|
+
if (this.blurCloseTimer) {
|
|
4178
|
+
clearTimeout(this.blurCloseTimer);
|
|
4179
|
+
this.blurCloseTimer = null;
|
|
4180
|
+
}
|
|
4181
|
+
this.open();
|
|
4048
4182
|
}
|
|
4049
4183
|
onBlur() {
|
|
4050
4184
|
this.isFocused.set(false);
|
|
4185
|
+
this.blurCloseTimer = setTimeout(() => {
|
|
4186
|
+
this.close();
|
|
4187
|
+
this.blurCloseTimer = null;
|
|
4188
|
+
}, 150);
|
|
4189
|
+
}
|
|
4190
|
+
onDropdownMousedown(event) {
|
|
4191
|
+
event.preventDefault();
|
|
4192
|
+
if (this.blurCloseTimer) {
|
|
4193
|
+
clearTimeout(this.blurCloseTimer);
|
|
4194
|
+
this.blurCloseTimer = null;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
open() {
|
|
4198
|
+
if (this.disabled() || this.isOpen())
|
|
4199
|
+
return;
|
|
4200
|
+
this.isOpen.set(true);
|
|
4201
|
+
this.focusedIndex.set(-1);
|
|
4202
|
+
this.portalDropdown();
|
|
4203
|
+
if (this.isAsyncMode()) {
|
|
4204
|
+
this.triggerAsyncSearch(this.inputValue());
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
close() {
|
|
4208
|
+
if (!this.isOpen())
|
|
4209
|
+
return;
|
|
4210
|
+
this.unportalDropdown();
|
|
4211
|
+
this.isOpen.set(false);
|
|
4212
|
+
this.focusedIndex.set(-1);
|
|
4213
|
+
this.cancelAsyncSearch();
|
|
4214
|
+
this.asyncLoading.set(false);
|
|
4215
|
+
this.asyncError.set(null);
|
|
4216
|
+
}
|
|
4217
|
+
onDocumentClick(event) {
|
|
4218
|
+
const target = event.target;
|
|
4219
|
+
if (!this.elementRef.nativeElement.contains(target) &&
|
|
4220
|
+
!this.dropdownRef?.nativeElement?.contains(target)) {
|
|
4221
|
+
this.close();
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
portalDropdown() {
|
|
4225
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
4226
|
+
if (!dropdown)
|
|
4227
|
+
return;
|
|
4228
|
+
dropdown.style.display = 'block';
|
|
4229
|
+
this.document.body.appendChild(dropdown);
|
|
4230
|
+
this.updateDropdownPosition();
|
|
4231
|
+
this.addPositionListeners();
|
|
4232
|
+
}
|
|
4233
|
+
unportalDropdown() {
|
|
4234
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
4235
|
+
if (!dropdown)
|
|
4236
|
+
return;
|
|
4237
|
+
if (dropdown.parentElement === this.document.body) {
|
|
4238
|
+
const wrapper = this.elementRef.nativeElement.querySelector('.ui-chip-input-wrapper');
|
|
4239
|
+
if (wrapper)
|
|
4240
|
+
wrapper.appendChild(dropdown);
|
|
4241
|
+
}
|
|
4242
|
+
dropdown.style.display = '';
|
|
4243
|
+
dropdown.style.position = '';
|
|
4244
|
+
dropdown.style.top = '';
|
|
4245
|
+
dropdown.style.left = '';
|
|
4246
|
+
dropdown.style.bottom = '';
|
|
4247
|
+
dropdown.style.width = '';
|
|
4248
|
+
dropdown.style.zIndex = '';
|
|
4249
|
+
dropdown.style.margin = '';
|
|
4250
|
+
this.removePositionListeners();
|
|
4251
|
+
}
|
|
4252
|
+
updateDropdownPosition() {
|
|
4253
|
+
const trigger = this.triggerRef?.nativeElement;
|
|
4254
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
4255
|
+
if (!trigger || !dropdown)
|
|
4256
|
+
return;
|
|
4257
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
4258
|
+
const dropdownHeight = dropdown.scrollHeight;
|
|
4259
|
+
const gap = 4;
|
|
4260
|
+
const spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
4261
|
+
const spaceAbove = triggerRect.top;
|
|
4262
|
+
const openAbove = spaceBelow < dropdownHeight + gap && spaceAbove > spaceBelow;
|
|
4263
|
+
dropdown.style.position = 'fixed';
|
|
4264
|
+
dropdown.style.width = `${triggerRect.width}px`;
|
|
4265
|
+
dropdown.style.left = `${triggerRect.left}px`;
|
|
4266
|
+
dropdown.style.zIndex = '99999';
|
|
4267
|
+
dropdown.style.margin = '0';
|
|
4268
|
+
if (openAbove) {
|
|
4269
|
+
dropdown.style.top = 'auto';
|
|
4270
|
+
dropdown.style.bottom = `${window.innerHeight - triggerRect.top + gap}px`;
|
|
4271
|
+
}
|
|
4272
|
+
else {
|
|
4273
|
+
dropdown.style.top = `${triggerRect.bottom + gap}px`;
|
|
4274
|
+
dropdown.style.bottom = 'auto';
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
addPositionListeners() {
|
|
4278
|
+
const update = () => {
|
|
4279
|
+
if (this.isOpen())
|
|
4280
|
+
this.updateDropdownPosition();
|
|
4281
|
+
};
|
|
4282
|
+
window.addEventListener('scroll', update, true);
|
|
4283
|
+
window.addEventListener('resize', update);
|
|
4284
|
+
this.positionCleanup = () => {
|
|
4285
|
+
window.removeEventListener('scroll', update, true);
|
|
4286
|
+
window.removeEventListener('resize', update);
|
|
4287
|
+
};
|
|
4288
|
+
}
|
|
4289
|
+
removePositionListeners() {
|
|
4290
|
+
this.positionCleanup?.();
|
|
4291
|
+
this.positionCleanup = null;
|
|
4292
|
+
}
|
|
4293
|
+
triggerAsyncSearch(query) {
|
|
4294
|
+
if (this.debounceTimer) {
|
|
4295
|
+
clearTimeout(this.debounceTimer);
|
|
4296
|
+
this.debounceTimer = null;
|
|
4297
|
+
}
|
|
4298
|
+
if (this.asyncSearchAbortController) {
|
|
4299
|
+
this.asyncSearchAbortController.abort();
|
|
4300
|
+
this.asyncSearchAbortController = null;
|
|
4301
|
+
}
|
|
4302
|
+
const trimmed = query.trim();
|
|
4303
|
+
if (trimmed.length < this.minSearchLength()) {
|
|
4304
|
+
this.asyncOptions.set([]);
|
|
4305
|
+
this.asyncLoading.set(false);
|
|
4306
|
+
this.asyncError.set(null);
|
|
4307
|
+
this.focusedIndex.set(-1);
|
|
4308
|
+
return;
|
|
4309
|
+
}
|
|
4310
|
+
this.asyncLoading.set(true);
|
|
4311
|
+
this.asyncError.set(null);
|
|
4312
|
+
this.debounceTimer = setTimeout(() => {
|
|
4313
|
+
this.executeAsyncSearch(trimmed);
|
|
4314
|
+
}, this.debounceTime());
|
|
4315
|
+
}
|
|
4316
|
+
async executeAsyncSearch(query) {
|
|
4317
|
+
const searchFn = this.asyncSearch();
|
|
4318
|
+
if (!searchFn)
|
|
4319
|
+
return;
|
|
4320
|
+
this.asyncSearchAbortController = new AbortController();
|
|
4321
|
+
const signal = this.asyncSearchAbortController.signal;
|
|
4322
|
+
try {
|
|
4323
|
+
const results = await searchFn(query);
|
|
4324
|
+
if (signal.aborted)
|
|
4325
|
+
return;
|
|
4326
|
+
this.asyncOptions.set(results);
|
|
4327
|
+
this.asyncLoading.set(false);
|
|
4328
|
+
this.asyncError.set(null);
|
|
4329
|
+
this.focusedIndex.set(-1);
|
|
4330
|
+
setTimeout(() => this.updateDropdownPosition());
|
|
4331
|
+
}
|
|
4332
|
+
catch (error) {
|
|
4333
|
+
if (signal.aborted)
|
|
4334
|
+
return;
|
|
4335
|
+
this.asyncOptions.set([]);
|
|
4336
|
+
this.asyncLoading.set(false);
|
|
4337
|
+
this.asyncError.set(error instanceof Error ? error.message : 'Search failed');
|
|
4338
|
+
this.focusedIndex.set(-1);
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
cancelAsyncSearch() {
|
|
4342
|
+
if (this.debounceTimer) {
|
|
4343
|
+
clearTimeout(this.debounceTimer);
|
|
4344
|
+
this.debounceTimer = null;
|
|
4345
|
+
}
|
|
4346
|
+
if (this.asyncSearchAbortController) {
|
|
4347
|
+
this.asyncSearchAbortController.abort();
|
|
4348
|
+
this.asyncSearchAbortController = null;
|
|
4349
|
+
}
|
|
4051
4350
|
}
|
|
4052
4351
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ChipInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4053
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: ChipInputComponent, isStandalone: true, selector: "ui-chip-input", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null }, autoAdd: { classPropertyName: "autoAdd", publicName: "autoAdd", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", added: "added", removed: "removed" }, queries: [{ propertyName: "chipTemplate", first: true, predicate: ChipTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true }], ngImport: i0, template: "<div class=\"ui-chip-input-wrapper\">\n @if (label()) {\n <label class=\"ui-chip-input__label\">{{ label() }}</label>\n }\n\n <div\n class=\"ui-chip-input\"\n [class]=\"containerClasses()\"\n (click)=\"onContainerClick()\"\n >\n @for (chip of value(); track chip) {\n @if (chipTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"chipTemplate()!\"\n [ngTemplateOutletContext]=\"getChipContext(chip)\"\n />\n } @else {\n <span class=\"ui-chip-input__chip\">\n <span class=\"ui-chip-input__chip-text\">{{ getChipDisplay(chip) }}</span>\n @if (!disabled()) {\n <button\n type=\"button\"\n class=\"ui-chip-input__chip-remove\"\n (click)=\"removeChip(chip); $event.stopPropagation()\"\n aria-label=\"Remove\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n </span>\n }\n }\n <input\n #inputRef\n type=\"text\"\n class=\"ui-chip-input__input\"\n [placeholder]=\"value().length === 0 ? placeholder() : ''\"\n [disabled]=\"disabled()\"\n [(ngModel)]=\"inputValue\"\n (keydown)=\"onInputKeydown($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n />\n </div>\n\n @if (error()) {\n <span class=\"ui-chip-input__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-chip-input__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [".ui-chip-input-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-chip-input__label{font-size:.875rem;font-weight:500;color:var(--ui-text)}.ui-chip-input{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-spacing-xs);padding:var(--ui-spacing-xs) var(--ui-spacing-sm);min-height:42px;background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:text;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-chip-input--focused{border-color:var(--ui-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 15%,transparent)}.ui-chip-input--error{border-color:var(--ui-danger)}.ui-chip-input--error.ui-chip-input--focused{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 15%,transparent)}.ui-chip-input--disabled{background:var(--ui-bg-secondary);cursor:not-allowed;opacity:.6}.ui-chip-input--outlined{background:transparent}.ui-chip-input--filled{background:var(--ui-bg-secondary);border-color:transparent}.ui-chip-input--filled.ui-chip-input--focused{border-color:var(--ui-primary)}.ui-chip-input--sm{min-height:34px;padding:var(--ui-spacing-xs);font-size:.8125rem}.ui-chip-input--lg{min-height:50px;padding:var(--ui-spacing-sm);font-size:1rem}.ui-chip-input__chip{display:inline-flex;align-items:center;gap:var(--ui-spacing-xs);padding:.125rem .5rem;background:var(--ui-bg-secondary);border-radius:var(--ui-radius-sm);font-size:.875rem;color:var(--ui-text);white-space:nowrap}.ui-chip-input--sm .ui-chip-input__chip{padding:.0625rem .375rem;font-size:.75rem}.ui-chip-input--lg .ui-chip-input__chip{padding:.25rem .625rem;font-size:.9375rem}.ui-chip-input__chip-text{line-height:1.4}.ui-chip-input__chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;margin-left:.125rem;border:none;border-radius:var(--ui-radius-sm);background:transparent;color:var(--ui-text-muted);cursor:pointer;transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast)}.ui-chip-input__chip-remove:hover{background:var(--ui-danger);color:#fff}.ui-chip-input__input{flex:1;min-width:80px;padding:.25rem 0;border:none;background:transparent;font:inherit;color:var(--ui-text);outline:none}.ui-chip-input__input::placeholder{color:var(--ui-text-muted)}.ui-chip-input__input:disabled{cursor:not-allowed}.ui-chip-input__hint{font-size:.75rem;color:var(--ui-text-muted)}.ui-chip-input__error{font-size:.75rem;color:var(--ui-danger)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4352
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: ChipInputComponent, isStandalone: true, selector: "ui-chip-input", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null }, autoAdd: { classPropertyName: "autoAdd", publicName: "autoAdd", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, asyncSearch: { classPropertyName: "asyncSearch", publicName: "asyncSearch", isSignal: true, isRequired: false, transformFunction: null }, strict: { classPropertyName: "strict", publicName: "strict", isSignal: true, isRequired: false, transformFunction: null }, minSearchLength: { classPropertyName: "minSearchLength", publicName: "minSearchLength", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", added: "added", removed: "removed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "chipTemplate", first: true, predicate: ChipTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "optionTemplate", first: true, predicate: OptionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true }, { propertyName: "triggerRef", first: true, predicate: ["triggerRef"], descendants: true, static: true }, { propertyName: "dropdownRef", first: true, predicate: ["dropdownRef"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"ui-chip-input-wrapper\">\n @if (label()) {\n <label class=\"ui-chip-input__label\">{{ label() }}</label>\n }\n\n <div\n #triggerRef\n class=\"ui-chip-input\"\n [class]=\"containerClasses()\"\n (click)=\"onContainerClick()\"\n >\n @for (chip of value(); track chip) {\n @if (chipTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"chipTemplate()!\"\n [ngTemplateOutletContext]=\"getChipContext(chip)\"\n />\n } @else {\n <span class=\"ui-chip-input__chip\">\n <span class=\"ui-chip-input__chip-text\">{{ getChipDisplay(chip) }}</span>\n @if (!disabled()) {\n <button\n type=\"button\"\n class=\"ui-chip-input__chip-remove\"\n (click)=\"removeChip(chip); $event.stopPropagation()\"\n aria-label=\"Remove\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n </span>\n }\n }\n <input\n #inputRef\n type=\"text\"\n class=\"ui-chip-input__input\"\n [placeholder]=\"value().length === 0 ? placeholder() : ''\"\n [disabled]=\"disabled()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange($any($event.target).value)\"\n (keydown)=\"onInputKeydown($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n autocomplete=\"off\"\n />\n </div>\n\n <div\n #dropdownRef\n class=\"ui-chip-input__dropdown\"\n [class.ui-chip-input__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n (mousedown)=\"onDropdownMousedown($event)\"\n >\n <div class=\"ui-chip-input__options\">\n @if (isAsyncMode() && asyncLoading()) {\n <div class=\"ui-chip-input__loading\">\n <svg class=\"ui-chip-input__spinner\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke-opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n <span>Searching...</span>\n </div>\n } @else if (isAsyncMode() && asyncError()) {\n <div class=\"ui-chip-input__error-message\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"></line>\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"></line>\n </svg>\n <span>{{ asyncError() }}</span>\n </div>\n } @else {\n @for (option of visibleSuggestions(); track option.value; let i = $index) {\n <div\n class=\"ui-chip-input__suggestion\"\n [class.ui-chip-input__suggestion--focused]=\"focusedIndex() === i\"\n [class.ui-chip-input__suggestion--disabled]=\"option.disabled\"\n [attr.role]=\"'option'\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"addSuggestion(option)\"\n >\n @if (optionTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: option.value, option: option.value, selected: false, disabled: !!option.disabled }\"\n />\n } @else {\n <span class=\"ui-chip-input__suggestion-label\">{{ option.label }}</span>\n }\n </div>\n }\n @if (visibleSuggestions().length === 0 && !showCreateRow()) {\n @if (isAsyncMode() && inputValue().trim().length < minSearchLength() && minSearchLength() > 0) {\n <div class=\"ui-chip-input__empty\">Type at least {{ minSearchLength() }} characters to search</div>\n } @else {\n <div class=\"ui-chip-input__empty\">No suggestions</div>\n }\n }\n }\n </div>\n @if (showCreateRow()) {\n <div\n class=\"ui-chip-input__create\"\n (click)=\"addChip(inputValue().trim())\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n </svg>\n Create \"{{ inputValue().trim() }}\"\n </div>\n }\n </div>\n\n @if (error()) {\n <span class=\"ui-chip-input__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-chip-input__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [".ui-chip-input-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-chip-input__label{font-size:.875rem;font-weight:500;color:var(--ui-text)}.ui-chip-input{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-spacing-xs);padding:var(--ui-spacing-xs) var(--ui-spacing-sm);min-height:42px;background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:text;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-chip-input--focused{border-color:var(--ui-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 15%,transparent)}.ui-chip-input--error{border-color:var(--ui-danger)}.ui-chip-input--error.ui-chip-input--focused{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 15%,transparent)}.ui-chip-input--disabled{background:var(--ui-bg-secondary);cursor:not-allowed;opacity:.6}.ui-chip-input--outlined{background:transparent}.ui-chip-input--filled{background:var(--ui-bg-secondary);border-color:transparent}.ui-chip-input--filled.ui-chip-input--focused{border-color:var(--ui-primary)}.ui-chip-input--sm{min-height:34px;padding:var(--ui-spacing-xs);font-size:.8125rem}.ui-chip-input--lg{min-height:50px;padding:var(--ui-spacing-sm);font-size:1rem}.ui-chip-input__chip{display:inline-flex;align-items:center;gap:var(--ui-spacing-xs);padding:.125rem .5rem;background:var(--ui-bg-secondary);border-radius:var(--ui-radius-sm);font-size:.875rem;color:var(--ui-text);white-space:nowrap}.ui-chip-input--sm .ui-chip-input__chip{padding:.0625rem .375rem;font-size:.75rem}.ui-chip-input--lg .ui-chip-input__chip{padding:.25rem .625rem;font-size:.9375rem}.ui-chip-input__chip-text{line-height:1.4}.ui-chip-input__chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;margin-left:.125rem;border:none;border-radius:var(--ui-radius-sm);background:transparent;color:var(--ui-text-muted);cursor:pointer;transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast)}.ui-chip-input__chip-remove:hover{background:var(--ui-danger);color:#fff}.ui-chip-input__input{flex:1;min-width:80px;padding:.25rem 0;border:none;background:transparent;font:inherit;color:var(--ui-text);outline:none}.ui-chip-input__input::placeholder{color:var(--ui-text-muted)}.ui-chip-input__input:disabled{cursor:not-allowed}.ui-chip-input__hint{font-size:.75rem;color:var(--ui-text-muted)}.ui-chip-input__error{font-size:.75rem;color:var(--ui-danger)}.ui-chip-input__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast);box-sizing:border-box}.ui-chip-input__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-chip-input__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-chip-input__suggestion{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);cursor:pointer;transition:background-color var(--ui-transition-fast)}.ui-chip-input__suggestion:hover:not(.ui-chip-input__suggestion--disabled){background-color:var(--ui-bg-hover)}.ui-chip-input__suggestion--focused{background-color:var(--ui-bg-hover);outline:none}.ui-chip-input__suggestion--disabled{opacity:.5;cursor:not-allowed}.ui-chip-input__suggestion-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-chip-input__create{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:.875rem;color:var(--ui-primary);cursor:pointer;border-top:1px solid var(--ui-border);transition:background-color var(--ui-transition-fast)}.ui-chip-input__create:hover{background-color:var(--ui-bg-hover)}.ui-chip-input__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:.875rem}.ui-chip-input__loading{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-lg) var(--ui-spacing-md);color:var(--ui-text-muted);font-size:.875rem}.ui-chip-input__spinner{animation:ui-chip-input-spin 1s linear infinite}@keyframes ui-chip-input-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ui-chip-input__error-message{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-md);color:var(--ui-danger);font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4054
4353
|
}
|
|
4055
4354
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ChipInputComponent, decorators: [{
|
|
4056
4355
|
type: Component,
|
|
4057
|
-
args: [{ selector: 'ui-chip-input', standalone: true, imports: [FormsModule, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-chip-input-wrapper\">\n @if (label()) {\n <label class=\"ui-chip-input__label\">{{ label() }}</label>\n }\n\n <div\n class=\"ui-chip-input\"\n [class]=\"containerClasses()\"\n (click)=\"onContainerClick()\"\n >\n @for (chip of value(); track chip) {\n @if (chipTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"chipTemplate()!\"\n [ngTemplateOutletContext]=\"getChipContext(chip)\"\n />\n } @else {\n <span class=\"ui-chip-input__chip\">\n <span class=\"ui-chip-input__chip-text\">{{ getChipDisplay(chip) }}</span>\n @if (!disabled()) {\n <button\n type=\"button\"\n class=\"ui-chip-input__chip-remove\"\n (click)=\"removeChip(chip); $event.stopPropagation()\"\n aria-label=\"Remove\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n </span>\n }\n }\n <input\n #inputRef\n type=\"text\"\n class=\"ui-chip-input__input\"\n [placeholder]=\"value().length === 0 ? placeholder() : ''\"\n [disabled]=\"disabled()\"\n [
|
|
4058
|
-
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], autoAdd: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoAdd", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], added: [{ type: i0.Output, args: ["added"] }], removed: [{ type: i0.Output, args: ["removed"] }], chipTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ChipTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], inputRef: [{
|
|
4356
|
+
args: [{ selector: 'ui-chip-input', standalone: true, imports: [FormsModule, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-chip-input-wrapper\">\n @if (label()) {\n <label class=\"ui-chip-input__label\">{{ label() }}</label>\n }\n\n <div\n #triggerRef\n class=\"ui-chip-input\"\n [class]=\"containerClasses()\"\n (click)=\"onContainerClick()\"\n >\n @for (chip of value(); track chip) {\n @if (chipTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"chipTemplate()!\"\n [ngTemplateOutletContext]=\"getChipContext(chip)\"\n />\n } @else {\n <span class=\"ui-chip-input__chip\">\n <span class=\"ui-chip-input__chip-text\">{{ getChipDisplay(chip) }}</span>\n @if (!disabled()) {\n <button\n type=\"button\"\n class=\"ui-chip-input__chip-remove\"\n (click)=\"removeChip(chip); $event.stopPropagation()\"\n aria-label=\"Remove\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n </span>\n }\n }\n <input\n #inputRef\n type=\"text\"\n class=\"ui-chip-input__input\"\n [placeholder]=\"value().length === 0 ? placeholder() : ''\"\n [disabled]=\"disabled()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange($any($event.target).value)\"\n (keydown)=\"onInputKeydown($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n autocomplete=\"off\"\n />\n </div>\n\n <div\n #dropdownRef\n class=\"ui-chip-input__dropdown\"\n [class.ui-chip-input__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n (mousedown)=\"onDropdownMousedown($event)\"\n >\n <div class=\"ui-chip-input__options\">\n @if (isAsyncMode() && asyncLoading()) {\n <div class=\"ui-chip-input__loading\">\n <svg class=\"ui-chip-input__spinner\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke-opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n <span>Searching...</span>\n </div>\n } @else if (isAsyncMode() && asyncError()) {\n <div class=\"ui-chip-input__error-message\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"></line>\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"></line>\n </svg>\n <span>{{ asyncError() }}</span>\n </div>\n } @else {\n @for (option of visibleSuggestions(); track option.value; let i = $index) {\n <div\n class=\"ui-chip-input__suggestion\"\n [class.ui-chip-input__suggestion--focused]=\"focusedIndex() === i\"\n [class.ui-chip-input__suggestion--disabled]=\"option.disabled\"\n [attr.role]=\"'option'\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"addSuggestion(option)\"\n >\n @if (optionTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: option.value, option: option.value, selected: false, disabled: !!option.disabled }\"\n />\n } @else {\n <span class=\"ui-chip-input__suggestion-label\">{{ option.label }}</span>\n }\n </div>\n }\n @if (visibleSuggestions().length === 0 && !showCreateRow()) {\n @if (isAsyncMode() && inputValue().trim().length < minSearchLength() && minSearchLength() > 0) {\n <div class=\"ui-chip-input__empty\">Type at least {{ minSearchLength() }} characters to search</div>\n } @else {\n <div class=\"ui-chip-input__empty\">No suggestions</div>\n }\n }\n }\n </div>\n @if (showCreateRow()) {\n <div\n class=\"ui-chip-input__create\"\n (click)=\"addChip(inputValue().trim())\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n </svg>\n Create \"{{ inputValue().trim() }}\"\n </div>\n }\n </div>\n\n @if (error()) {\n <span class=\"ui-chip-input__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-chip-input__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [".ui-chip-input-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-chip-input__label{font-size:.875rem;font-weight:500;color:var(--ui-text)}.ui-chip-input{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-spacing-xs);padding:var(--ui-spacing-xs) var(--ui-spacing-sm);min-height:42px;background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:text;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-chip-input--focused{border-color:var(--ui-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 15%,transparent)}.ui-chip-input--error{border-color:var(--ui-danger)}.ui-chip-input--error.ui-chip-input--focused{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 15%,transparent)}.ui-chip-input--disabled{background:var(--ui-bg-secondary);cursor:not-allowed;opacity:.6}.ui-chip-input--outlined{background:transparent}.ui-chip-input--filled{background:var(--ui-bg-secondary);border-color:transparent}.ui-chip-input--filled.ui-chip-input--focused{border-color:var(--ui-primary)}.ui-chip-input--sm{min-height:34px;padding:var(--ui-spacing-xs);font-size:.8125rem}.ui-chip-input--lg{min-height:50px;padding:var(--ui-spacing-sm);font-size:1rem}.ui-chip-input__chip{display:inline-flex;align-items:center;gap:var(--ui-spacing-xs);padding:.125rem .5rem;background:var(--ui-bg-secondary);border-radius:var(--ui-radius-sm);font-size:.875rem;color:var(--ui-text);white-space:nowrap}.ui-chip-input--sm .ui-chip-input__chip{padding:.0625rem .375rem;font-size:.75rem}.ui-chip-input--lg .ui-chip-input__chip{padding:.25rem .625rem;font-size:.9375rem}.ui-chip-input__chip-text{line-height:1.4}.ui-chip-input__chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;margin-left:.125rem;border:none;border-radius:var(--ui-radius-sm);background:transparent;color:var(--ui-text-muted);cursor:pointer;transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast)}.ui-chip-input__chip-remove:hover{background:var(--ui-danger);color:#fff}.ui-chip-input__input{flex:1;min-width:80px;padding:.25rem 0;border:none;background:transparent;font:inherit;color:var(--ui-text);outline:none}.ui-chip-input__input::placeholder{color:var(--ui-text-muted)}.ui-chip-input__input:disabled{cursor:not-allowed}.ui-chip-input__hint{font-size:.75rem;color:var(--ui-text-muted)}.ui-chip-input__error{font-size:.75rem;color:var(--ui-danger)}.ui-chip-input__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast);box-sizing:border-box}.ui-chip-input__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-chip-input__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-chip-input__suggestion{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);cursor:pointer;transition:background-color var(--ui-transition-fast)}.ui-chip-input__suggestion:hover:not(.ui-chip-input__suggestion--disabled){background-color:var(--ui-bg-hover)}.ui-chip-input__suggestion--focused{background-color:var(--ui-bg-hover);outline:none}.ui-chip-input__suggestion--disabled{opacity:.5;cursor:not-allowed}.ui-chip-input__suggestion-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-chip-input__create{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:.875rem;color:var(--ui-primary);cursor:pointer;border-top:1px solid var(--ui-border);transition:background-color var(--ui-transition-fast)}.ui-chip-input__create:hover{background-color:var(--ui-bg-hover)}.ui-chip-input__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:.875rem}.ui-chip-input__loading{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-lg) var(--ui-spacing-md);color:var(--ui-text-muted);font-size:.875rem}.ui-chip-input__spinner{animation:ui-chip-input-spin 1s linear infinite}@keyframes ui-chip-input-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ui-chip-input__error-message{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-md);color:var(--ui-danger);font-size:.875rem}\n"] }]
|
|
4357
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], autoAdd: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoAdd", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], asyncSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "asyncSearch", required: false }] }], strict: [{ type: i0.Input, args: [{ isSignal: true, alias: "strict", required: false }] }], minSearchLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSearchLength", required: false }] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], added: [{ type: i0.Output, args: ["added"] }], removed: [{ type: i0.Output, args: ["removed"] }], chipTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ChipTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], optionTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => OptionTemplateDirective), { isSignal: true }] }], inputRef: [{
|
|
4059
4358
|
type: ViewChild,
|
|
4060
4359
|
args: ['inputRef']
|
|
4360
|
+
}], triggerRef: [{
|
|
4361
|
+
type: ViewChild,
|
|
4362
|
+
args: ['triggerRef', { static: true }]
|
|
4363
|
+
}], dropdownRef: [{
|
|
4364
|
+
type: ViewChild,
|
|
4365
|
+
args: ['dropdownRef', { static: true }]
|
|
4366
|
+
}], onDocumentClick: [{
|
|
4367
|
+
type: HostListener,
|
|
4368
|
+
args: ['document:click', ['$event']]
|
|
4061
4369
|
}] } });
|
|
4062
4370
|
|
|
4063
4371
|
class DatepickerComponent {
|